due to the difficulty to understand the order in which objects are highlighted.
@@ -1674,7 +3946,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 +3981,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 +4010,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..1a146cfe1a 100644
--- a/README.md
+++ b/README.md
@@ -1,51 +1,160 @@
-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
+The Premier Open-Source PostgreSQL Database Modeler
+Since 2006 • Professional-grade • Cross-platform excellence
-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.
+
+
+
-Licensing
----------
+## 🎯 Why Choose pgModeler?
-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.
+✅ **Visual Database Design** - Design PostgreSQL databases visually with drag-and-drop interface
+✅ **Reverse Engineering** - Import existing databases and visualize their complete structure
+✅ **Smart Diff & Sync** - Compare models with databases and generate precise migration scripts
+✅ **Code Generation** - Export clean, optimized SQL for any PostgreSQL version (9.x to 17+)
+✅ **Professional Features** - Advanced relationships, triggers, functions, procedures, and more
+✅ **Active Development** - 19 years of continuous development and community support
+
+## 🚀 Quick Start
+
+1. **📥 Download** - Get pre-compiled packages from [pgmodeler.io](https://pgmodeler.io/purchase)
+2. **🎨 Design** - Create tables, relationships, and constraints visually
+3. **🔄 Sync** - Generate SQL or sync directly with your PostgreSQL server
+4. **🚀 Deploy** - Export optimized DDL scripts for production
+
+> **💡 New User?** Check our [Video Tutorials](https://pgmodeler.io/support/tutorials) and [Documentation](https://pgmodeler.io/support/docs)
+
+## ⭐ Key Features
+
+- **🎨 Visual Modeling** - Intuitive drag-and-drop interface for database design
+- **🔄 Reverse Engineering** - Import and visualize existing PostgreSQL databases
+- **⚡ Smart Diff** - Compare models with databases and generate migration scripts
+- **🛠️ Code Generation** - Export clean SQL for any PostgreSQL version
+- **🔍 Database Administration** - Built-in SQL editor and database browser
+- **🔌 Plugin System** - Extend functionality with [official plugins](https://github.com/pgmodeler/plugins)
+- **🌍 Multi-Platform Support** - Linux, Windows, and macOS compatibility
+- **� Internationalization** - Multiple language support
+
+## 🏗️ Build Status
+
+[](https://github.com/pgmodeler/pgmodeler/actions?query=workflow%3A%22Linux+build%22)
+[](https://github.com/pgmodeler/pgmodeler/actions?query=workflow%3A%22Windows+build%22)
+[](https://github.com/pgmodeler/pgmodeler/actions?query=workflow%3A%22macOs+build%22)
+
+## 🌟 Community & Support
+
+- 🐘 **PostgreSQL Ecosystem** - Official PostgreSQL community member
+- 🌍 **Global Usage** - Used in enterprises, startups, and academia worldwide
+- 📚 **Rich Documentation** - Comprehensive guides and tutorials
+- 🔗 **Stay Connected** - Follow us on [X](https://x.com/pgmodeler), [Bluesky](https://bsky.app/profile/pgmodeler.io), [Mastodon](https://mastodon.social/@pgmodeler)
+
+**Need Help?** Visit our [Issues](https://github.com/pgmodeler/pgmodeler/issues) page or check the [official website](https://pgmodeler.io) for documentation and support.
+
+## 🔧 Building & Installation
+
+Being a multiplatform software, the building process differs slightly on each supported OS.
+
+### 📦 Pre-compiled Packages (Recommended)
+- Download from [pgmodeler.io](https://pgmodeler.io/purchase) for instant setup
+- Supports all major platforms with optimized builds
+
+### 🛠️ Build from Source
+- Complete build instructions: [Installation Guide](https://www.pgmodeler.io/support/installation)
+- Requirements: Qt 6.4+ (dropped 6.2/6.3 support), C++17 compiler, PostgreSQL client libraries
+- Check the [official plugin repository](https://github.com/pgmodeler/plugins) for extending features
+
+## 💖 Support pgModeler's Development
+
+pgModeler is **100% independent** with **19 years** of continuous development. Your support keeps this project alive!
+
+### 🎯 How You Can Help
+
+* 💰 **Financial Support** - pgModeler lives exclusively from [donations](https://pgmodeler.io/#donationForm) and [package purchases](https://www.pgmodeler.io/purchase). Your contribution directly supports development!
+
+* 👨💻 **Developers Welcome** - Know C++ and Qt? We need your help! The project has grown beyond what a solo developer can handle. Contact us to contribute to this **high-quality C++ codebase**!
+
+* 📢 **Spread the Word** - Share pgModeler in your networks, workplaces, and communities. The bigger our community, the stronger the project becomes!
+
+[](https://github.com/sponsors/pgmodeler)
+[](https://pgmodeler.io/#donationForm)
+
+## 🏆 Technical Excellence
+
+### 💎 **Crafted with Pride: Modern C++17 & Qt**
+- **96.5% C++** codebase with **professional-grade architecture**
+- **Advanced C++17 features**: Smart pointers, RAII, move semantics, and modern STL
+- **Custom Qt macros** for exception-safe signal/slot connections
+- **Template metaprogramming** for type-safe object management
+- **Memory-efficient** design with optimized data structures
+
+### 🚀 **Performance Achievements**
+- **~80% performance improvement** in model loading, validation, and object searching (v1.1.0)
+- **Optimized rendering engine** with Qt's raster graphics system
+- **Efficient SQL generation** with template-based code generation
+- **Smart caching** for database object metadata
+
+### 🛠️ **Engineering Highlights**
+- **Modular architecture**: 6 specialized libraries (`libcore`, `libgui`, `libconnector`, etc.)
+- **Plugin system** with extensible API for custom features
+- **Schema microlanguage**: Custom templating system for SQL generation
+- **Exception-safe design** with comprehensive error handling
+- **Cross-platform compatibility** (Linux, Windows, macOS)
+
+## 📋 License
+
+This program is free software: you can redistribute it and/or modify it under the terms of the **GNU General Public License v3**.
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 [LICENSE](https://github.com/pgmodeler/pgmodeler/blob/master/LICENSE) for details.
+See [LICENSE](https://github.com/pgmodeler/pgmodeler/blob/main/LICENSE) for complete details.
+
+## 📚 Resources & Legacy
-Donate to pgModeler
--------------------
+### 📖 **Documentation & Learning**
+- 📖 **Official Documentation** - [Complete Guides](https://pgmodeler.io/support/docs)
+- 🎥 **Video Tutorials** - [Learning Resources](https://pgmodeler.io/support/tutorials)
+- 📝 **Detailed Changelog** - [CHANGELOG.md](https://github.com/pgmodeler/pgmodeler/blob/main/CHANGELOG.md)
+- 🔌 **Plugin Development** - [Official Plugin Repository](https://github.com/pgmodeler/plugins)
-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).
+### 🏛️ **Project Legacy**
+- 🎂 **Born in 2006** - Originally named "pgsqlDBM"
+- 🔄 **2012 Reborn** - Complete rewrite as "pgModeler"
+- 🌟 **Trusted Worldwide** - Half a million downloads and growing
+- 🔗 **Historical Releases** - [Sourceforge Archive](http://sourceforge.net/projects/pgmodeler)
-Developers and Reviewers wanted!
---------------------------------
+## 🎨 About the Creator
-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!
+**Raphael Araújo e Silva** - The passionate C++ developer behind pgModeler since 2006. Living in Palmas, Brazil, Raphael combines **computer graphics**, **compilers**, and **database systems** knowledge into this masterpiece. His dedication to **clean C++ code** and **Qt framework expertise** shows in every line of the 96.5% C++ codebase.
-Compiling/Installation
-----------------------
+> *"This is pgModeler... this is my dream!"* - Raphael Araújo e Silva
-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).
+---
-Known Issues
------------
+## ⚠️ Known Issues & Limitations
-* 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.
+
+Click to view technical limitations
-Change Log
-----------
+* **Large models (500+ objects)**: Qt's raster engine may cause performance degradation with extensive models
+* **Diff process**: May present false-positive results requiring multiple runs or option tweaking
+* **Quoted identifiers**: Limited support for PostgreSQL's quoted identifier notation
+* **Microsoft Visual Studio**: Cannot be compiled due to GCC/Clang-specific extensions
+* **macOS file association**: Bundle particularities prevent proper .dbm file association in Finder
+* **Threading edge cases**: Rare crashes during export/import/validation on complex models due to race conditions
-The detailed log of changes 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)
+
+ 🐘 Made with ❤️ for the PostgreSQL Community
+ 19 years of continuous innovation • Professional C++17 codebase • Cross-platform excellence
+
\ No newline at end of file
diff --git a/RELEASENOTES.md b/RELEASENOTES.md
index 3840d69f48..e11cc76110 100644
--- a/RELEASENOTES.md
+++ b/RELEASENOTES.md
@@ -1,50 +1,88 @@
-v0.9.1-beta1
+v1.2.0
------
+Release date: May 9, 2025
+Changes since: v1.1.0
-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.
+Attention: pgModeler 1.2.0 introduces configuration changes that may affect compatibility with 1.1.x settings. On the first launch, pgModeler will automatically attempt to migrate your existing settings. Please note that this is an early development release where stability issues may occur. It's recommended that all models and databases be backed up before use. Please report any found bugs for prompt resolution. The mentioned migration process helps transition to improved configurations while minimizing disruption to your workflow.
+
+Summary: After one year and three months, 72 new features, 93 changes/improvements, and 74 bug fixes were delivered to this new major release. The result of this hard work is an even more optimized tool with features that will make a difference in any aspect of database modeling and administration! Below, we have a compilation of key new features, changes, and fixes implemented since pgModeler 1.1.0. Of course, some more technical changes were omitted, but you can see everything in the file CHANGELOG.md.
+
+**New features**
+
+* **Improved debug mode:** The debugging capabilities have been expanded with dedicated output tabs in the database import and diff forms. Now, every time the user checks the debug mode option in any of the mentioned forms, a new tab will be displayed, and any useful information that helps to track down errors/bugs will be logged there.
+
+* **Multiple objects source preview:** To make the code preview more flexible, the user can now visualize the source code of multiple selected objects in the canvas or the database objects tree. When using this feature, the code in the source code preview widget will be displayed in the order in which the objects are created. This feature is useful when you need the code of a small portion of the model and don't want to generate the whole code just to extract the desired parts of it.
+
+* **Relationships' FK columns indexes:** Now, the relationships that automatically create foreign key columns can also create indexes over those columns too. This can speed up the modeling process a bit more. The generated indexes, like relationships, are named after the specific pattern and the user has total control over the generated names in the relationship editing form or by defining a global name pattern under relationships settings.
+
+* **Improved layers setup:** The operation to move objects to certain layers was significantly improved in this version. Now, the quick action "Quick > Set layers" opens a dialog where the user can move the selected objects to one or more existing layers or even create a layer on the fly and assign it to the selection in the design view. In addition to that improvement, the layers configuration widget (the one that is toggled by the button "Layers" at the bottom of the design view) received an option that makes relationships follow the visibility of the linked tables. This means that if one table is moved to a layer, the relationships connected to it will move to that layer too.
+
+* **Transactional export process:** The export process is now capable of running the commands at once inside a transaction block. This is useful if you want an atomic execution of the generated DDLs, rolling back everything if one command fails in its execution. Note that the transactional option does not affect database and tablespace creation commands, since, by design, these commands need to be executed outside a transaction. The command-line interface tool also received support for the transactional export process, and it's enabled by default, like in the GUI. To deactivate it during the execution of any export operation, use the options -nt or --non-transactional.
+
+* **Improved code completion:** The code completion widget now supports the completion of names in ALTER/DROP commands. It even detects the type of objects being modified or dropped, suggesting the names filtered by the specified types. Another enhancement done is the capability of displaying column names in the ORDER BY clause.
+
+* **Tabbed data handling:** Before this version, data manipulation was performed via a standalone dialog, which could make data handling more difficult due to the number of standalone windows open. Now, all browsed tables are reunited in a single dialog but are displayed in their own tabs, facilitating data visualization.
+
+* **Improved schema microlanguage:** The pgModeler's code templating language (aka schema microlanguage) was improved in such a way as to support escaped character sequences that refer to metacharacter tokens. The supported escaped characters (and their related metacharacters) are \s ($sp), \t ($tb), \n ($br), [ ($ob), ] ($cb), { ($oc), } ($cc), $ ($ds), # ($hs), % ($ps), @ ($at), & ($am), \ ($bs) and * ($ds). The schema language now also supports the "include" statements that inject portions of code stored in other files into the currently parsed schema file. This is pretty handy for avoiding code duplication and facilitating the maintenance of schema files.
+
+* **Markdown data dictionaries:** pgModeler now supports the generation of data dictionaries in Markdown (.md) format in the model export form. This is useful to integrate data dictionaries generated by the tool with other documentation tools that use that file format to keep documentation pages. The pgmodeler-cli tool also received support for Markdown dictionaries through the option "--markdown".
+
+* **Improved older configs copy:** From now on, in the first run, pgModeler will try to copy the configuration files from a previous major version immediately before the current one. For example, running 1.2, the files to be copied will be from 1.1 and not from 0.9.x anymore. This will increase the chances of reusing settings from previous versions, diminishing the annoying situation of reconfiguring the tool every time it is updated.
+
+* **Improved code generation:** The DDL generation for objects that support "CREATE OR REPLACE" was updated to include the "OR REPLACE" portion; this is the case for functions, procedures, views, and others. The diff feature received the option "Replace modified objects", which causes objects to be replaced via "CREATE OR REPLACE" instead of being dropped and created again.
+
+* **Quick create constraints, indexes, and relationships:** This feature, introduced through an exclusive plugin in pgModeler Plus, allows the creation of constraints, indexes, and relationships based on the objects selected in the design view, without the need to open a single editing form or fill lots of fields. The objects created also support name patterns, and they can be configured in the plugin's settings menu in the main window.
+
+* **Query variables plugin:** pgModeler Plus received a new plugin that helps developers test their queries using variables that are replaced in the command at the moment of its execution. Basically, a query that contains some variables prefixed by $, like this "SELECT $cols FROM $schema.$table WHERE $condition", has the values for each variable replaced and the parsed query executed. The variables and their values can be specified in a special widget that is toggled by the button "Variables" in the SQL execution widget. The main goal of this new feature is to accelerate the query testing, mainly if you write parametrized queries based on some ORMs' syntaxes. This plugin supports four variable formats: $variable, :variable, @ variable, and {variable}.
+
+* **Improved plugin API:** The pgModeler's plugin development interface was improved and now allows more portions of the tool to receive user-created features to increase its set of functionalities. Unfortunately, for now, you still need a basic knowledge of C++ and Qt. But for future releases, I plan to simplify even more the plugin interface in such a way as to allow non-C++ developers to create their custom features for pgModeler.
+
+* **Removal of the support for Qt 6.2 and 6.3:** The support for Qt versions 6.2 and 6.3 was removed since it was causing a lot of conditional compilation instructions (the famous C/C++ macros) to be used. This approach tends to make the code hard to read and maintain. So, since Qt 6.2 and 6.3 official upstream support has ended, we decided to make the code compliant with newer framework versions. To be more precise, pgModeler now builds on Qt 6.4.x and above.
+
+**Miscellaneous**
+
+* Added support for PostgreSQL 17.
+* Improved the reverse engineering so columns can also be imported using the option "Import to the working model" in the database import form.
+* Graphical objects added to the canvas area will now blink, and the viewport will center on them to indicate to the user where they were put.
+* Adjusted pgmodeler-cli to raise errors when the ignore export error options are used in transactional export mode.
+* Minor adjustment in diff form by making transactional mode mutually exclusive with the ignore export errors option.
+* Minor fix in the file selector widget that was not applying correctly the palette colors in the line edit field.
+* Minor fix in extensions creation/loading processes by ignoring duplicated schemas and using the ones already available in the model.
+* Fixed a bug in the data dictionary generation for views.
+* Fixed a bug in the SQL generation of the database model SQL related to an unknown database attribute.
+* Fixed a bug when importing composite types having attributes using arrays of other user-defined types.
+* Fixed a bug when displaying the source, in Database Explorer, of a composite type that has one or more attributes referencing user-defined types.
+* Fixed a bug that was generating errors when running catalog queries of some objects in older versions of PostgreSQL.
+* The model objects widget now accepts an Alt + click over a graphical object, highlighting it in the design view.
+* Redundant search/replace instances all over the tool were removed due to the integrated search/replace widget in the source code editor.
+* The extension editing form now properly supports custom schema names in data types.
+* The database import process and the database model itself have been refactored for more reliable handling of extension-owned objects using the new extension object structure.
+* The comparison operations in the diff process have been optimized to filter system objects correctly.
+* The function behavior type was simplified by dropping the STRICT type since it has the same semantics as RETURNS NULL ON NULL INPUT.
+* The database import form, when in debug mode, will remain open so the user can inspect the commands and objects created during the process.
+* Fixed some crashes during diff operations on extension-created tables.
+* Fixed the importing of columns using arrays of user-defined types.
+* Fixed the time zone persistence on the timestamp data type.
+* Removed false-positive diffs for functions with comments or STRICT behavior.
+* Fixed reverse engineering of uppercase type names.
+* When the export, import, and diff processes finish, the taskbar blinks when the window is not visible.
+* Minor adjustment in the layers configuration widget to accept Enter/Return to apply settings.
+* Fixed some shortcut conflicts in the main window.
+* Minor fix in the "Open relationship" action in the design view.
+* Fixed the index catalog queries when using pgModeler in compatibility mode (PG 9.x).
+* Added support for displaying FK's update/delete actions in the data dictionary.
+* The file selection dialog now starts on the user's home by default and saves the last accessed directory, using it the next time it is opened.
+* Minor bug fix in code generation of tablespace, database, and user mapping objects.
+* Minor fix in the object search feature when searching by source/referenced constraint columns.
+* Minor fix in objects' grids to allow sorting the "ID" column as an integer value.
+* Fixed a bug in the function editing form that was not resetting the "SETOF" flag when changing the return mode to "Table".
+* Fixed a malformed markdown code when a table or view had a comment.
+* Fixed a bug in the diff process that was ignoring changes in columns.
+* Fixed a crash in the database import process when destroying detached inherited columns.
+* Fixed a bug in the database import that was crashing the application while trying to retrieve user mapping comments.
+* Fixed a bug in the index object that was preventing the removal of included columns.
+* The restriction of specifying OUT parameters in procedures was removed in compliance with newer PostgreSQL versions.
+* Added support for the options check_option, security_invoker, and security_barrier in views.
+* The syntax highlighting feature was completely refactored, being now more precise and the configuration files simpler.
+* Minor fix in pgmodeler-cli in such a way as to warn about invalid changelog entries, avoiding aborting the entire model fix process.
+* Fixed a bug in the reverse engineering feature that was not retrieving comments of sequences, causing false positives to be generated in the diff process.
diff --git a/apps/apps.pri b/apps/apps.pri
new file mode 100644
index 0000000000..6204f25182
--- /dev/null
+++ b/apps/apps.pri
@@ -0,0 +1,36 @@
+# 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 \
+ $$LIBCLI_LIB
+
+INCLUDEPATH += $$LIBGUI_INC \
+ $$LIBCANVAS_INC \
+ $$LIBCONNECTOR_INC \
+ $$LIBCORE_INC \
+ $$LIBPARSERS_INC \
+ $$LIBUTILS_INC \
+ $$LIBCLI_INC
+
+DEPENDPATH += $$LIBGUI_ROOT \
+ $$LIBCANVAS_ROOT \
+ $$LIBCONNECTOR_ROOT \
+ $$LIBCORE_ROOT \
+ $$LIBPARSERS_ROOT \
+ $$LIBUTILS_ROOT \
+ $$LIBCLI_ROOT
+
+
+unix:LIBS += $$QMAKE_LIBS_EXECINFO
+windows:RCC_DIR=src/
+windows:DESTDIR=$$PWD
+
+isEqual(PRIVATE_PLUGINS, false) {
+ windows:RC_FILE=res/windows_ico.qrc
+}
diff --git a/apps/pgmodeler-ch/pgmodeler-ch.pro b/apps/pgmodeler-ch/pgmodeler-ch.pro
new file mode 100644
index 0000000000..289170a024
--- /dev/null
+++ b/apps/pgmodeler-ch/pgmodeler-ch.pro
@@ -0,0 +1,17 @@
+include(../apps.pri)
+
+TEMPLATE = app
+TARGET = pgmodeler-ch
+
+isEqual(PRIVATE_PLUGINS, true) {
+ windows:RC_FILE=$$PRIV_RES_FOLDER/$$TARGET/windows_ico.qrc
+}
+
+SOURCES += src/main.cpp \
+ src/crashhandlerform.cpp
+
+HEADERS += src/crashhandlerform.h
+
+# Deployment settings
+target.path = $$PRIVATEBINDIR
+INSTALLS = target
diff --git a/apps/pgmodeler-ch/res/windows_ico.ico b/apps/pgmodeler-ch/res/windows_ico.ico
new file mode 100644
index 0000000000..9affe73043
Binary files /dev/null and b/apps/pgmodeler-ch/res/windows_ico.ico differ
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..312b6a5ea9
--- /dev/null
+++ b/apps/pgmodeler-ch/src/crashhandlerform.cpp
@@ -0,0 +1,216 @@
+/*
+# PostgreSQL Database Modeler (pgModeler)
+#
+# Copyright 2006-2025 - 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 "qtconnectmacros.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"));
+ setWindowIcon(QPixmap(":/images/images/crashhandler.png"));
+
+ 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(GuiUtilsNs::LtMargin,GuiUtilsNs::LtMargin,GuiUtilsNs::LtMargin,GuiUtilsNs::LtMargin);
+ wgt->setLayout(layout);
+
+ logo_lbl->setPixmap(QPixmap(":/images/images/crashhandler.png"));
+ report_twg->addTab(wgt, QIcon(GuiUtilsNs::getIconPath("alert")), 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->setFileMustExist(true);
+ 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(QIcon(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(hint_frm);
+
+ report_tab_grid->addWidget(input_wgt);
+ report_tab_grid->addWidget(details_gb);
+ report_tab_grid->addWidget(output_wgt);
+ report_tab_grid->addWidget(hint_frm);
+
+ setAnalysisMode(analysis_mode);
+
+ connect(input_sel, &FileSelectorWidget::s_fileSelected, this, __slot_n(this, CrashHandlerForm::loadReport));
+ connect(save_tb, &QToolButton::clicked, this, __slot(this, CrashHandlerForm::saveModel));
+
+ connect(input_sel, &FileSelectorWidget::s_selectorCleared, model_txt, &QPlainTextEdit::clear);
+ connect(input_sel, &FileSelectorWidget::s_selectorCleared, details_txt, &QPlainTextEdit::clear);
+ connect(input_sel, &FileSelectorWidget::s_selectorCleared, stack_txt, &QPlainTextEdit::clear);
+
+ connect(model_txt, &QPlainTextEdit::textChanged, this, [this](){
+ save_tb->setEnabled(!model_txt->toPlainText().isEmpty());
+ });
+}
+
+void CrashHandlerForm::loadReport(QString filename)
+{
+ QFile input;
+ QFileInfo fi;
+ char *buf = nullptr;
+
+ fi.setFile(filename);
+ input.setFileName(filename);
+ input.open(QFile::ReadOnly);
+
+ //Raises an error if the file could not be opened
+ if(!input.isOpen())
+ {
+ Messagebox::error(Exception::getErrorMessage(ErrorCode::FileDirectoryNotAccessed).arg(filename),
+ ErrorCode::FileDirectoryNotAccessed, __PRETTY_FUNCTION__, __FILE__, __LINE__);
+ }
+ 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()
+{
+ try
+ {
+ GuiUtilsNs::selectAndSaveFile(model_txt->toPlainText().toUtf8(),
+ tr("Save model"), QFileDialog::AnyFile,
+ { tr("Database model (*%1)").arg(GlobalAttributes::DbModelExt),
+ tr("All files (*.*)") }, {},
+ GlobalAttributes::DbModelExt);
+ }
+ catch(Exception &e)
+ {
+ Messagebox::error(e, __PRETTY_FUNCTION__, __FILE__, __LINE__);
+ }
+}
+
+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("Oh no! pgModeler just crashed!"));
+ msg_lbl->setText(tr("We apologize for what happened! It's clear that a nasty bug caused that. Please, fill out the form below describing your actions that somehow caused the unexpected closing. This will help us to investigate the causes and provide the proper fix for the problem."));
+ }
+}
+
+QByteArray CrashHandlerForm::generateReportBuffer()
+{
+ QByteArray buf=BugReportForm::generateReportBuffer();
+ buf.append(stack_txt->toPlainText().toUtf8());
+ buf.append(CharDelimiter);
+
+ return buf;
+}
diff --git a/apps/pgmodeler-ch/src/crashhandlerform.h b/apps/pgmodeler-ch/src/crashhandlerform.h
new file mode 100644
index 0000000000..4883b7b789
--- /dev/null
+++ b/apps/pgmodeler-ch/src/crashhandlerform.h
@@ -0,0 +1,66 @@
+/*
+# PostgreSQL Database Modeler (pgModeler)
+#
+# Copyright 2006-2025 - 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-ch
+\class CrashHandlerForm
+\brief Implements the pgModeler's crash handler enabling the generation an analysis of crash report files.
+*/
+
+#ifndef CRASH_HANDLER_H
+#define CRASH_HANDLER_H
+
+#include
+#include "tools/bugreportform.h"
+
+class CrashHandlerForm: public BugReportForm {
+ Q_OBJECT
+
+ private:
+ //! \brief Display the stacktrace
+ QPlainTextEdit *stack_txt;
+
+ //! \brief Container for widget that handles input report file
+ QWidget *input_wgt;
+
+ QLabel *input_lbl;
+
+ FileSelectorWidget *input_sel;
+
+ //! \brief Triggers the model saving to filesystem
+ QToolButton *save_tb;
+
+ void setAnalysisMode(bool value);
+
+ //! \brief Generates a report buffer containing the issue details, model and stacktrace
+ QByteArray generateReportBuffer();
+
+ public:
+ //! \brief Analysis mode argument
+ static const QString AnalysisMode;
+
+ CrashHandlerForm(bool analysis_mode=false, QWidget * parent = nullptr, Qt::WindowFlags f = Qt::Widget);
+
+ private slots:
+ //! \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..1af865f35c
--- /dev/null
+++ b/apps/pgmodeler-ch/src/main.cpp
@@ -0,0 +1,46 @@
+/*
+# PostgreSQL Database Modeler (pgModeler)
+#
+# Copyright 2006-2025 - 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
+ {
+ GlobalAttributes::init(argv[0], true);
+ Application app(argc,argv);
+ QStringList args = app.arguments();
+ app.loadTranslations(QLocale::system().name(), false);
+
+ 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_t(e.getErrorCode());
+ }
+}
diff --git a/apps/pgmodeler-cli/pgmodeler-cli.pro b/apps/pgmodeler-cli/pgmodeler-cli.pro
new file mode 100644
index 0000000000..7c6ef7af75
--- /dev/null
+++ b/apps/pgmodeler-cli/pgmodeler-cli.pro
@@ -0,0 +1,15 @@
+include(../apps.pri)
+
+CONFIG += console
+TEMPLATE = app
+TARGET = pgmodeler-cli
+
+isEqual(PRIVATE_PLUGINS, true) {
+ windows:RC_FILE=$$PRIV_RES_FOLDER/$$TARGET/windows_ico.qrc
+}
+
+SOURCES += src/main.cpp
+
+# 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..d1c0f0f2dd
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..b1c7953910
--- /dev/null
+++ b/apps/pgmodeler-cli/src/main.cpp
@@ -0,0 +1,61 @@
+/*
+# PostgreSQL Database Modeler (pgModeler)
+#
+# Copyright 2006-2025 - 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"
+
+int main(int argc, char **argv)
+{
+ QTextStream out(stdout);
+
+#ifdef DEMO_VERSION
+ out << Qt::endl;
+ out << "pgModeler " << GlobalAttributes::PgModelerVersion << QT_TR_NOOP(" command line interface.") << Qt::endl;
+ out << QT_TR_NOOP("PostgreSQL Database Modeler Project - pgmodeler.io") << Qt::endl;
+ out << QT_TR_NOOP("Copyright 2006-2024 Raphael Araújo e Silva ") << Qt::endl;
+ out << QT_TR_NOOP("\n** CLI disabled in demonstration version! **") << Qt::endl << Qt::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
+
+ GlobalAttributes::init(argv[0], false);
+ PgModelerCliApp pgmodeler_cli(argc, argv);
+ pgmodeler_cli.loadTranslations(QLocale::system().name(), true);
+
+ //Executes the cli
+ return pgmodeler_cli.exec();
+ }
+ catch(Exception &e)
+ {
+ out << Qt::endl;
+ out << e.getExceptionsText();
+ out << QT_TR_NOOP("** pgmodeler-cli aborted due to critical error(s). **") << Qt::endl << Qt::endl;
+ return (e.getErrorCode()==ErrorCode::Custom ? -1 : enum_t(e.getErrorCode()));
+ }
+#endif
+}
diff --git a/apps/pgmodeler-se/pgmodeler-se.pro b/apps/pgmodeler-se/pgmodeler-se.pro
new file mode 100644
index 0000000000..6da11c6deb
--- /dev/null
+++ b/apps/pgmodeler-se/pgmodeler-se.pro
@@ -0,0 +1,41 @@
+include(../apps.pri)
+
+TEMPLATE = app
+TARGET = pgmodeler-se
+
+isEqual(PRIVATE_PLUGINS, true) {
+ windows:RC_FILE=$$PRIV_RES_FOLDER/$$TARGET/windows_ico.qrc
+}
+
+SOURCES += src/main.cpp \
+ src/aboutsewidget.cpp \
+ src/schemaeditorform.cpp \
+ src/sourceeditorwidget.cpp
+
+FORMS += \
+ ui/aboutsewidget.ui \
+ ui/schemaeditorform.ui \
+ ui/sourceeditorwidget.ui
+
+HEADERS += \
+ src/aboutsewidget.h \
+ src/schemaeditorform.h \
+ src/sourceeditorwidget.h
+
+INCLUDEPATH += ../pgmodeler/src
+
+DEPENDPATH += ../pgmodeler \
+../pgmodeler/src
+
+# Forcing the linker to use the objects files generated
+# during the compilation of the main executable since
+# pgmodeler-se uses the same application class
+OBJECTS += ../pgmodeler/obj/pgmodelerapp.o \
+../pgmodeler/obj/moc_pgmodelerapp.o
+
+# 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..0c159bded8
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/aboutsewidget.cpp b/apps/pgmodeler-se/src/aboutsewidget.cpp
new file mode 100644
index 0000000000..9b16d4ca7f
--- /dev/null
+++ b/apps/pgmodeler-se/src/aboutsewidget.cpp
@@ -0,0 +1,32 @@
+/*
+# PostgreSQL Database Modeler (pgModeler)
+#
+# Copyright 2006-2025 - 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 "aboutsewidget.h"
+#include "guiutilsns.h"
+
+AboutSEWidget::AboutSEWidget(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/aboutsewidget.h b/apps/pgmodeler-se/src/aboutsewidget.h
new file mode 100644
index 0000000000..457b2a673a
--- /dev/null
+++ b/apps/pgmodeler-se/src/aboutsewidget.h
@@ -0,0 +1,37 @@
+/*
+# PostgreSQL Database Modeler (pgModeler)
+#
+# Copyright 2006-2025 - 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 AboutSEWidget
+\brief Form that contains information about software authoring and licensing.
+*/
+
+#ifndef ABOUT_SE_WIDGET_H
+#define ABOUT_SE_WIDGET_H
+
+#include "ui_aboutsewidget.h"
+
+class AboutSEWidget: public QWidget, public Ui::AboutSEWidget {
+ Q_OBJECT
+
+ public:
+ AboutSEWidget(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..e7dff1edc5
--- /dev/null
+++ b/apps/pgmodeler-se/src/main.cpp
@@ -0,0 +1,49 @@
+/*
+# PostgreSQL Database Modeler (pgModeler)
+#
+# Copyright 2006-2025 - 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 "schemaeditorform.h"
+#include "pgmodelerapp.h"
+#include "exception.h"
+#include "enumtype.h"
+
+int main(int argc, char **argv)
+{
+ try
+ {
+ GlobalAttributes::init(argv[0], true);
+ PgModelerApp app(argc,argv);
+ QStringList args = app.arguments();
+ SchemaEditorForm syntaxchk;
+
+ app.loadTranslations(QLocale::system().name(), false);
+
+ args.pop_front();
+ syntaxchk.loadFiles(args);
+ syntaxchk.showMaximized();
+ app.exec();
+
+ return 0;
+ }
+ catch(Exception &e)
+ {
+ QTextStream out(stdout);
+ out << e.getExceptionsText();
+ return enum_t(e.getErrorCode());
+ }
+}
diff --git a/apps/pgmodeler-se/src/schemaeditorform.cpp b/apps/pgmodeler-se/src/schemaeditorform.cpp
new file mode 100644
index 0000000000..9add901cff
--- /dev/null
+++ b/apps/pgmodeler-se/src/schemaeditorform.cpp
@@ -0,0 +1,562 @@
+/*
+# PostgreSQL Database Modeler (pgModeler)
+#
+# Copyright 2006-2025 - 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/appearanceconfigwidget.h"
+#include "settings/generalconfigwidget.h"
+#include "guiutilsns.h"
+#include "sourceeditorwidget.h"
+#include "aboutsewidget.h"
+#include "baseform.h"
+#include "utilsns.h"
+#include "qtconnectmacros.h"
+#include
+#include
+
+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.setWeight(QFont::Normal);
+ btn->setFont(fnt);
+ GuiUtilsNs::createDropShadow(btn, 1, 1, 5);
+
+ if(!btn->toolTip().isEmpty() && !btn->shortcut().toString().isEmpty())
+ btn->setToolTip(btn->toolTip() + QString(" (%1)").arg(btn->shortcut().toString()));
+ }
+
+ AppearanceConfigWidget appearance_conf_wgt;
+ appearance_conf_wgt.loadConfiguration();
+ GuiUtilsNs::updateDropShadows(qApp->allWidgets());
+
+ 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 (*%1)").arg(GlobalAttributes::ConfigurationExt) });
+
+ QAction *act = nullptr;
+ stx_action_grp = new QActionGroup(&syntax_cfg_menu);
+
+ act = syntax_cfg_menu.addAction("Schema file", this, &SchemaEditorForm::loadSyntaxConfig);
+ stx_action_grp->addAction(act);
+ act->setCheckable(true);
+ act->setChecked(true);
+ act->setData(GlobalAttributes::SchHighlightConf);
+
+ act = syntax_cfg_menu.addAction("XML script", this, &SchemaEditorForm::loadSyntaxConfig);
+ stx_action_grp->addAction(act);
+ act->setCheckable(true);
+ act->setChecked(false);
+ act->setData(GlobalAttributes::XMLHighlightConf);
+
+ act = syntax_cfg_menu.addAction("SQL script", this, &SchemaEditorForm::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, &QToolButton::clicked, this, __slot(this, SchemaEditorForm::applySyntaxConfig));
+ connect(save_conf_tb, &QToolButton::clicked, this, __slot(this, SchemaEditorForm::saveSyntaxConfig));
+ connect(reload_conf_tb, &QToolButton::clicked, this, __slot(this, SchemaEditorForm::loadSyntaxConfig));
+
+ connect(new_tb, &QToolButton::clicked, this, [this](){
+ __trycatch( addEditorTab(); )
+ });
+
+ connect(load_tb, &QToolButton::clicked, this, __slot(this, SchemaEditorForm::loadFile));
+ connect(exit_tb, &QToolButton::clicked, this, &SchemaEditorForm::close);
+
+ connect(save_tb, &QToolButton::clicked, this, __slot(this, SchemaEditorForm::saveFile));
+ connect(indent_all_tb, &QToolButton::clicked, this, &SchemaEditorForm::indentAll);
+
+ connect(save_all_tb, &QToolButton::clicked, this, __slot(this, SchemaEditorForm::saveAll));
+ connect(close_all_tb, &QToolButton::clicked, this, &SchemaEditorForm::closeAll);
+
+ connect(editors_tbw, &QTabWidget::tabCloseRequested, this, [this](int idx){
+ closeEditorTab(idx);
+ });
+
+ connect(editors_tbw, &QTabWidget::currentChanged, this, __slot(this, SchemaEditorForm::loadSyntaxFromCurrentTab));
+ connect(use_tmpl_file_chk, &QCheckBox::toggled, this, __slot(this, SchemaEditorForm::loadSyntaxConfig));
+
+ connect(syntax_txt, &NumberedTextEditor::textChanged, this, [this](){
+ alert_frm->setVisible(true);
+ });
+
+ connect(save_as_tb, &QToolButton::clicked, this, [this](){
+ __trycatch( saveFile(true); )
+ });
+
+ connect(about_tb, &QToolButton::clicked, this, [](){
+ AboutSEWidget *info_wgt = new AboutSEWidget;
+ 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())
+ {
+ int res = Messagebox::confirm(tr("There are modified files! Do you want to exit without saving them?"));
+
+ if(Messagebox::isRejected(res))
+ 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(QString("temp_XXXXXX%1").arg(GlobalAttributes::ConfigurationExt)));
+ 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;
+
+ qApp->setOverrideCursor(Qt::WaitCursor);
+
+ for(int tab = 0; tab < editors_tbw->count(); tab++)
+ {
+ editor = dynamic_cast(editors_tbw->widget(tab));
+ editor->indent_tb->click();
+ }
+
+ qApp->restoreOverrideCursor();
+}
+
+void SchemaEditorForm::saveAll()
+{
+ qApp->setOverrideCursor(Qt::WaitCursor);
+
+ for(int tab = 0; tab < editors_tbw->count(); tab++)
+ {
+ editors_tbw->setCurrentIndex(tab);
+
+ try
+ {
+ saveFile();
+ }
+ catch(Exception &e)
+ {
+ Messagebox::error(e, __PRETTY_FUNCTION__, __FILE__, __LINE__);
+ break;
+ }
+ }
+
+ qApp->restoreOverrideCursor();
+}
+
+void SchemaEditorForm::closeAll()
+{
+ if(hasModifiedEditors())
+ {
+ int res = Messagebox::confirm(tr("There are modified files! Do you want to close them without save?"));
+
+ if(Messagebox::isRejected(res))
+ return;
+ }
+
+ qApp->setOverrideCursor(Qt::WaitCursor);
+
+ while(editors_tbw->count() > 0)
+ closeEditorTab(0, false);
+
+ qApp->restoreOverrideCursor();
+}
+
+QStringList SchemaEditorForm::showFileDialog(bool save_mode)
+{
+ QFileDialog file_dlg;
+ QStringList files, filters= {
+ tr("Schema file (*%1)").arg(GlobalAttributes::SchemaExt),
+ tr("Database model file (*%1)").arg(GlobalAttributes::DbModelExt),
+ tr("pgModeler config file (*%1)").arg(GlobalAttributes::ConfigurationExt),
+ tr("Objects metadata file (*%1)").arg(GlobalAttributes::ObjMetadataExt),
+ 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 (*%1 *%2 *%3 *%4 *.sql *.xml *.dtd)")
+ .arg(GlobalAttributes::SchemaExt, GlobalAttributes::DbModelExt,
+ GlobalAttributes::ConfigurationExt, GlobalAttributes::ObjMetadataExt));
+
+ 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, this, [&file_dlg](QString filter){
+ filter.remove(QRegularExpression("(.)+(\\*)"));
+ filter.remove(")");
+ file_dlg.setDefaultSuffix(filter);
+ });
+ }
+
+ GuiUtilsNs::restoreFileDialogState(&file_dlg);
+
+ if(file_dlg.exec() == QFileDialog::Accepted)
+ files = file_dlg.selectedFiles();
+
+ GuiUtilsNs::saveFileDialogState(&file_dlg);
+
+ 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
+ {
+ qApp->setOverrideCursor(Qt::WaitCursor);
+
+ for(auto &file : filenames)
+ addEditorTab(file);
+
+ qApp->restoreOverrideCursor();
+ }
+ catch(Exception &e)
+ {
+ //qApp->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, &SourceEditorWidget::s_editorModified, this, &SchemaEditorForm::setTabModified);
+ }
+ 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));
+
+ if(editor_wgt->isModified() && confirm_close)
+ {
+ int res = Messagebox::confirm(tr("The source code was modified! Do you really want to close it without save?"));
+
+ if(Messagebox::isRejected(res))
+ 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..495029c1a5
--- /dev/null
+++ b/apps/pgmodeler-se/src/schemaeditorform.h
@@ -0,0 +1,78 @@
+/*
+# PostgreSQL Database Modeler (pgModeler)
+#
+# Copyright 2006-2025 - 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 "ui_schemaeditorform.h"
+#include "widgets/numberedtexteditor.h"
+#include "utils/syntaxhighlighter.h"
+#include "widgets/fileselectorwidget.h"
+
+class SchemaEditorForm: public QWidget, public Ui::SchemaEditorForm {
+ Q_OBJECT
+
+ private:
+ 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..8548a8a2ca
--- /dev/null
+++ b/apps/pgmodeler-se/src/sourceeditorwidget.cpp
@@ -0,0 +1,432 @@
+#include "sourceeditorwidget.h"
+#include "messagebox.h"
+#include "guiutilsns.h"
+#include "utilsns.h"
+#include
+
+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"},
+};
+
+QPalette SourceEditorWidget::def_editor_pal;
+
+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);
+ search_wgt = new SearchReplaceWidget(editor_txt, search_parent);
+ search_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);
+
+ for(auto &itr : snippets)
+ code_compl_wgt->insertCustomItem(itr.first, itr.second, QPixmap(GuiUtilsNs::getIconPath("codesnippet")));
+
+ vbox = new QVBoxLayout(search_parent);
+ vbox->setContentsMargins(0, 0, 0, GuiUtilsNs::LtMargin);
+ vbox->addWidget(search_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);
+
+ metachars_tb->setMenu(&metachar_conv_menu);
+ metachar_conv_menu.addAction(tr("Metachar to escaped"), this, [this](){
+ convertMetaChars(false);
+ });
+
+ metachar_conv_menu.addAction(tr("Escaped to metachar"), this, [this](){
+ convertMetaChars(true);
+ });
+
+ connect(code_compl_wgt, &CodeCompletionWidget::s_wordSelected, this, &SourceEditorWidget::handleSelectedSnippet);
+ connect(search_wgt, &SearchReplaceWidget::s_hideRequested, search_tb, &QToolButton::toggle);
+ connect(validate_tb, &QToolButton::clicked, this, &SourceEditorWidget::validateSyntax);
+ connect(indent_tb, &QToolButton::clicked, this, &SourceEditorWidget::applyIndentation);
+ connect(editor_txt, &NumberedTextEditor::modificationChanged, this, &SourceEditorWidget::restoreEditorPalette);
+ connect(editor_txt, &NumberedTextEditor::undoAvailable, this, &SourceEditorWidget::setModified);
+ connect(editor_txt, &NumberedTextEditor::cursorPositionChanged, this, &SourceEditorWidget::restoreEditorPalette);
+ connect(search_tb, &QToolButton::toggled, search_parent, &QWidget::setVisible);
+ connect(comment_tb, &QToolButton::clicked, this, &SourceEditorWidget::toggleComment);
+
+ connect(editor_txt, &NumberedTextEditor::selectionChanged, this, [this]() {
+ comment_tb->setEnabled(editor_txt->textCursor().hasSelection());
+ });
+}
+
+void SourceEditorWidget::saveFile(const QString &filename)
+{
+ UtilsNs::saveFile(filename, editor_txt->toPlainText().toUtf8());
+
+ 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();
+ metachars_tb->setEnabled(curr_sytax_cfg == GlobalAttributes::SchHighlightConf);
+ }
+ catch(Exception &e)
+ {
+ throw Exception(e.getErrorMessage(), e.getErrorCode(), __PRETTY_FUNCTION__, __FILE__, __LINE__, &e);
+ }
+}
+
+void SourceEditorWidget::toggleComment()
+{
+ QTextCursor tc = editor_txt->textCursor();
+
+ if(tc.hasSelection())
+ {
+ QMap comment_chrs = {
+ { GlobalAttributes::SchHighlightConf, { "# ", ""}},
+ { GlobalAttributes::SQLHighlightConf, { "-- ", ""}},
+ { GlobalAttributes::XMLHighlightConf, { ""}}
+ };
+ QString open_cmt, close_cmt,
+ sel_text = tc.selection().toPlainText();
+
+ open_cmt = comment_chrs[curr_sytax_cfg][0];
+ close_cmt = comment_chrs[curr_sytax_cfg][1];
+
+ if(curr_sytax_cfg == GlobalAttributes::XMLHighlightConf)
+ {
+ sel_text.prepend(open_cmt);
+ sel_text.append(close_cmt);
+ }
+ else
+ {
+ QStringList lines = sel_text.split(QChar::LineFeed);
+
+ for(auto &line : lines)
+ {
+ if(line.isEmpty())
+ continue;
+
+ if(line.startsWith(open_cmt))
+ line.remove(open_cmt);
+ else
+ line.prepend(open_cmt);
+
+ if(line.endsWith(close_cmt))
+ line.remove(close_cmt);
+ else
+ line.append(close_cmt);
+ }
+
+ sel_text = lines.join(QChar::LineFeed);
+ }
+
+ tc.insertText(sel_text);
+ }
+}
+
+void SourceEditorWidget::convertMetaChars(bool escaped_to_meta)
+{
+ attribs_map metas {
+ {"\\#", "$hs"}, {"\\s", "$sp"},
+ {"\\t", "$tb"}, {"\\n", "$br"},
+ {"\\[", "$ob"}, {"\\]", "$cb"},
+ {"\\{", "$oc"}, {"\\}", "$cc"},
+ {"\\\\", "$bs"}, {"\\@", "$at"},
+ {"\\%", "$ps"}, {"\\&", "$am"},
+ {"\\$", "$ms"}, {"\\*", "$ds"}
+ };
+
+ QString code = editor_txt->toPlainText();
+
+ for(const auto &[escaped, metachr] : metas)
+ {
+ if(escaped_to_meta)
+ code.replace(escaped, metachr);
+ else
+ code.replace(metachr, escaped);
+ }
+
+ editor_txt->blockSignals(true);
+ QTextCursor tc = editor_txt->textCursor();
+ tc.setPosition(0);
+ tc.movePosition(QTextCursor::End, QTextCursor::KeepAnchor);
+ tc.insertText(code);
+ editor_txt->moveCursor(QTextCursor::Start);
+ editor_txt->blockSignals(false);
+}
+
+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 == ".sql")
+ curr_sytax_cfg = GlobalAttributes::SQLHighlightConf;
+ else if(ext == GlobalAttributes::SchemaExt)
+ curr_sytax_cfg = GlobalAttributes::SchHighlightConf;
+ else
+ curr_sytax_cfg = GlobalAttributes::XMLHighlightConf;
+}
+
+void SourceEditorWidget::validateSyntax()
+{
+ SchemaParser schparser;
+
+ try
+ {
+ editor_txt->setPalette(def_editor_pal);
+ schparser.ignoreEmptyAttributes(true);
+ schparser.ignoreUnkownAttributes(true);
+ schparser.setSearchPath(QFileInfo(filename).absolutePath());
+ schparser.loadBuffer(editor_txt->toPlainText());
+ schparser.getSourceCode({});
+
+ Messagebox::info(tr("No lexical or sytactical errors found."));
+ }
+ 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);
+
+ Messagebox::error(e, __PRETTY_FUNCTION__, __FILE__, __LINE__);
+ }
+}
+
+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;
+ QRegularExpression 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(QRegularExpression(cond_pattern.arg(tk_if))) && !inline_ifend)
+ {
+ if_level++;
+ found_if = found_cond = true;
+ }
+ else if(line.contains(QRegularExpression(cond_pattern.arg(tk_else))) ||
+ line.contains(QRegularExpression(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, Qt::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;
+ }
+
+ QRegularExpression 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(QRegularExpression(cond_pattern.arg(tk_end))) &&
+ (next_next_line.contains(QRegularExpression(cond_pattern.arg(tk_else))) ||
+ next_next_line.contains(QRegularExpression(cond_pattern.arg(tk_end))))) ||
+
+ ((line.contains(QRegularExpression(cond_pattern.arg(tk_if))) ||
+ line.contains(QRegularExpression(cond_pattern.arg(tk_else)))) &&
+ (next_next_line.contains(QRegularExpression(cond_pattern.arg(tk_if))) ||
+ next_next_line.contains(QRegularExpression(cond_pattern.arg(tk_set))) ||
+ next_next_line.contains(QRegularExpression(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(QRegularExpression(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(QRegularExpression(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(QRegularExpression(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..ba4067af4f
--- /dev/null
+++ b/apps/pgmodeler-se/src/sourceeditorwidget.h
@@ -0,0 +1,106 @@
+/*
+# PostgreSQL Database Modeler (pgModeler)
+#
+# Copyright 2006-2025 - 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/searchreplacewidget.h"
+#include "widgets/codecompletionwidget.h"
+#include "widgets/fileselectorwidget.h"
+
+class SourceEditorWidget: public QWidget, public Ui::SourceEditorWidget {
+ Q_OBJECT
+
+ private:
+ static attribs_map snippets;
+
+ static QPalette def_editor_pal;
+
+ CodeCompletionWidget *code_compl_wgt;
+
+ FileSelectorWidget *source_file_sel;
+
+ NumberedTextEditor *editor_txt;
+
+ SyntaxHighlighter *editor_hl;
+
+ SearchReplaceWidget *search_wgt;
+
+ QString filename, curr_sytax_cfg;
+
+ QAction *act_break_inline_ifs;
+
+ QMenu indent_opts_menu, metachar_conv_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();
+
+ void convertMetaChars(bool escaped_to_meta);
+
+ 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);
+
+ void toggleComment();
+
+ 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/aboutsewidget.ui b/apps/pgmodeler-se/ui/aboutsewidget.ui
new file mode 100644
index 0000000000..f6329627e6
--- /dev/null
+++ b/apps/pgmodeler-se/ui/aboutsewidget.ui
@@ -0,0 +1,436 @@
+
+
+ AboutSEWidget
+
+
+ Qt::NonModal
+
+
+
+ 0
+ 0
+ 816
+ 704
+
+
+
+
+ 0
+ 0
+
+
+
+
+ 650
+ 500
+
+
+
+
+ 16777215
+ 16777215
+
+
+
+ About pgModeler Schema Editor
+
+
+
+ :/images/images/schemafile.png :/images/images/schemafile.png
+
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+ -
+
+
+ QFrame::NoFrame
+
+
+ QFrame::Raised
+
+
+
+ 5
+
+
+ 5
+
+
+ 5
+
+
+ 5
+
+
+ 5
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 100
+ 100
+
+
+
+
+ 100
+ 100
+
+
+
+
+
+
+
+
+
+ :/images/images/schemafile.png
+
+
+ true
+
+
+
+ -
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ true
+
+
+
+ pgModeler Schema Editor
+
+
+ Qt::AlignCenter
+
+
+ Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 0
+ 0
+
+
+
+
+ 16777215
+ 16777215
+
+
+
+
+ true
+ true
+
+
+
+
+
+
+ 0.0.0
+
+
+ Qt::AlignCenter
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+
+
+
+
+ 0
+ 129
+ 0
+
+
+
+
+
+
+
+
+ 0
+ 129
+ 0
+
+
+
+
+
+
+
+
+ 128
+ 128
+ 128
+
+
+
+
+
+
+
+
+ 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::AlignLeading|Qt::AlignLeft|Qt::AlignTop
+
+
+ true
+
+
+ 0
+
+
+ Qt::TextSelectableByMouse
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ License
+
+
+
+ 5
+
+
+ 5
+
+
+ 5
+
+
+ 5
+
+ -
+
+
+ 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" /><meta charset="utf-8" /><style type="text/css">
+p, li { white-space: pre-wrap; }
+</style></head><body style=" font-family:'Noto Sans'; font-size:12pt; 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 <</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;">></span></p></body></html>
+
+
+ false
+
+
+ Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse
+
+
+
+
+
+
+ -
+
+ -
+
+
+
+ 77
+ 48
+
+
+
+ pgModeler is proudly a brazilian software!
+
+
+
+
+
+
+
+
+ :/images/images/brazil_flag.png
+
+
+ true
+
+
+ Qt::AlignHCenter|Qt::AlignTop
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ <html><head/><body><p>Raphael Araújo e Silva <<a href="mailto:raphael@pgmodeler.com.br"><span style=" text-decoration: underline; color:#0057ae;">raphael@pgmodeler.io</span></a>></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..cdf65b0d69
--- /dev/null
+++ b/apps/pgmodeler-se/ui/schemaeditorform.ui
@@ -0,0 +1,992 @@
+
+
+ SchemaEditorForm
+
+
+
+ 0
+ 0
+ 1792
+ 1075
+
+
+
+
+ 800
+ 600
+
+
+
+ pgModeler Schema Editor
+
+
+
+ :/images/images/schemafile.png :/images/images/schemafile.png
+
+
+
+ 0
+
+
+ 0
+
+
+ 5
+
+
+ 5
+
+
+ 5
+
+ -
+
+
+ Qt::Horizontal
+
+
+ 5
+
+
+ true
+
+
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 0
+
+
+ 5
+
+ -
+
+
+
+ 16777215
+ 16777215
+
+
+
+ QTabWidget::North
+
+
+ true
+
+
+ true
+
+
+
+
+
+
+
+ false
+
+
+
+ 0
+
+
+ 5
+
+
+ 0
+
+
+ 0
+
+
+ 5
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ Syntax file:
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 0
+ 0
+
+
+
+ QFrame::StyledPanel
+
+
+ QFrame::Raised
+
+
+
+ 5
+
+
+ 5
+
+
+ 5
+
+
+ 5
+
+
+ 5
+
+ -
+
+
+ false
+
+
+ Save && apply
+
+
+
+ :/icons/icons/save.png :/icons/icons/save.png
+
+
+
+ 25
+ 25
+
+
+
+ Qt::ToolButtonTextBesideIcon
+
+
+
+ -
+
+
+
+ 25
+ 25
+
+
+
+
+ 25
+ 25
+
+
+
+
+
+
+ Qt::AutoText
+
+
+ :/icons/icons/alert.png
+
+
+ true
+
+
+
+ -
+
+
+ false
+
+
+ Apply only
+
+
+
+ :/icons/icons/confirm.png :/icons/icons/confirm.png
+
+
+
+ 25
+ 25
+
+
+
+ Qt::ToolButtonTextBesideIcon
+
+
+
+ -
+
+
+ false
+
+
+ Reload
+
+
+
+ :/icons/icons/refresh.png :/icons/icons/refresh.png
+
+
+
+ 25
+ 25
+
+
+
+ Qt::ToolButtonTextBesideIcon
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 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
+
+
+
+ 5
+
+
+ 5
+
+
+ 5
+
+
+ 5
+
+
+ 5
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 16777215
+ 16777215
+
+
+
+
+
+
+
+
+ DTD
+
+
+
+ 5
+
+
+ 5
+
+
+ 5
+
+
+ 5
+
+
+ 5
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 16777215
+ 16777215
+
+
+
+
+
+
+
+
+
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 0
+ 0
+
+
+
+
+ 5
+
+
+ 5
+
+
+ 5
+
+
+ 5
+
+
+ 5
+
+ -
+
+
+ Qt::Vertical
+
+
+
+ 20
+ 40
+
+
+
+
+ -
+
+
+ false
+
+
+
+ 0
+ 0
+
+
+
+
+ 0
+ 0
+
+
+
+ Choose the syntax highlighting mode
+
+
+ Syntax
+
+
+
+ :/icons/icons/xmlcode.png :/icons/icons/xmlcode.png
+
+
+
+ 32
+ 32
+
+
+
+ QToolButton::InstantPopup
+
+
+ Qt::ToolButtonTextUnderIcon
+
+
+ true
+
+
+ Qt::NoArrow
+
+
+
+ -
+
+
+ false
+
+
+
+ 0
+ 0
+
+
+
+
+ 0
+ 0
+
+
+
+
+
+
+ Close all
+
+
+
+ :/icons/icons/close.png :/icons/icons/close.png
+
+
+
+ 32
+ 32
+
+
+
+ Qt::ToolButtonTextUnderIcon
+
+
+ true
+
+
+
+ -
+
+
+ false
+
+
+
+ 0
+ 0
+
+
+
+
+ 0
+ 0
+
+
+
+ Save changes to another file
+
+
+ Save as
+
+
+
+ :/icons/icons/saveas.png :/icons/icons/saveas.png
+
+
+
+ 32
+ 32
+
+
+
+ Qt::ToolButtonTextUnderIcon
+
+
+ true
+
+
+
+ -
+
+
+ QFrame::Plain
+
+
+ Qt::Horizontal
+
+
+
+ -
+
+
+ false
+
+
+
+ 0
+ 0
+
+
+
+
+ 0
+ 0
+
+
+
+
+
+
+ Save all
+
+
+
+ :/icons/icons/saveall.png :/icons/icons/saveall.png
+
+
+
+ 32
+ 32
+
+
+
+ Qt::ToolButtonTextUnderIcon
+
+
+ true
+
+
+
+ -
+
+
+ QFrame::Plain
+
+
+ Qt::Horizontal
+
+
+
+ -
+
+
+ true
+
+
+
+ 0
+ 0
+
+
+
+
+ 0
+ 0
+
+
+
+ Open a new editor
+
+
+ New
+
+
+
+ :/icons/icons/new.png :/icons/icons/new.png
+
+
+
+ 32
+ 32
+
+
+
+ Ctrl+N
+
+
+ Qt::ToolButtonTextUnderIcon
+
+
+ true
+
+
+
+ -
+
+
+ true
+
+
+
+ 0
+ 0
+
+
+
+
+ 0
+ 0
+
+
+
+ Exit
+
+
+
+ :/icons/icons/exit.png :/icons/icons/exit.png
+
+
+
+ 32
+ 32
+
+
+
+ Qt::ToolButtonTextUnderIcon
+
+
+ true
+
+
+
+ -
+
+
+ false
+
+
+
+ 0
+ 0
+
+
+
+
+ 0
+ 0
+
+
+
+ Save changes
+
+
+ Save
+
+
+
+ :/icons/icons/save.png :/icons/icons/save.png
+
+
+
+ 32
+ 32
+
+
+
+ Ctrl+S
+
+
+ Qt::ToolButtonTextUnderIcon
+
+
+ true
+
+
+
+ -
+
+
+ true
+
+
+
+ 0
+ 0
+
+
+
+
+ 0
+ 0
+
+
+
+ Load files
+
+
+ Load
+
+
+
+ :/icons/icons/open.png :/icons/icons/open.png
+
+
+
+ 32
+ 32
+
+
+
+ Ctrl+L
+
+
+ Qt::ToolButtonTextUnderIcon
+
+
+ true
+
+
+
+ -
+
+
+ false
+
+
+
+ 0
+ 0
+
+
+
+
+ 0
+ 0
+
+
+
+ Apply identation to all open editors
+
+
+ Indent all
+
+
+
+ :/icons/icons/indent.png :/icons/icons/indent.png
+
+
+
+ 32
+ 32
+
+
+
+ Qt::ToolButtonTextUnderIcon
+
+
+ true
+
+
+
+ -
+
+
+ true
+
+
+
+ 0
+ 0
+
+
+
+
+ 0
+ 0
+
+
+
+ About
+
+
+
+ :/icons/icons/help.png :/icons/icons/help.png
+
+
+
+ 32
+ 32
+
+
+
+ F1
+
+
+ Qt::ToolButtonTextUnderIcon
+
+
+ true
+
+
+
+
+
+
+ -
+
+
+ 5
+
+
+ 5
+
+
+ 5
+
+
+ 5
+
+
+ 5
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 169
+ 35
+
+
+
+
+ 169
+ 35
+
+
+
+
+
+
+
+
+
+ Qt::PlainText
+
+
+ :/images/images/pgmodeler_name.png
+
+
+ true
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+
+
+
+
+
+ new_tb
+ load_tb
+ save_tb
+ save_as_tb
+ save_all_tb
+ close_all_tb
+ syntax_tb
+ indent_all_tb
+ about_tb
+ exit_tb
+ editors_tbw
+ tabWidget
+ use_tmpl_file_chk
+ save_conf_tb
+ apply_conf_tb
+ reload_conf_tb
+
+
+
+
+
+
+
diff --git a/apps/pgmodeler-se/ui/sourceeditorwidget.ui b/apps/pgmodeler-se/ui/sourceeditorwidget.ui
new file mode 100644
index 0000000000..5c390b2061
--- /dev/null
+++ b/apps/pgmodeler-se/ui/sourceeditorwidget.ui
@@ -0,0 +1,330 @@
+
+
+ SourceEditorWidget
+
+
+
+ 0
+ 0
+ 1212
+ 736
+
+
+
+ Form
+
+
+
+ 5
+
+
+ 5
+
+
+ 5
+
+
+ 5
+
+
+ 5
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ -
+
+
+ 5
+
+
+ 5
+
+ -
+
+
+ true
+
+
+
+ 0
+ 0
+
+
+
+
+ 0
+ 0
+
+
+
+ Validate the syntax of the schema file
+
+
+ Validate
+
+
+
+ :/icons/icons/validatesch.png :/icons/icons/validatesch.png
+
+
+
+ 28
+ 28
+
+
+
+ F5
+
+
+ QToolButton::InstantPopup
+
+
+ Qt::ToolButtonTextBesideIcon
+
+
+ false
+
+
+ Qt::NoArrow
+
+
+
+ -
+
+
+ true
+
+
+
+ 0
+ 0
+
+
+
+
+ 0
+ 0
+
+
+
+ Apply custom indentation to the code
+
+
+ Indent
+
+
+
+ :/icons/icons/indent.png :/icons/icons/indent.png
+
+
+
+ 28
+ 28
+
+
+
+ Ctrl+I
+
+
+ QToolButton::MenuButtonPopup
+
+
+ Qt::ToolButtonTextBesideIcon
+
+
+ false
+
+
+ Qt::NoArrow
+
+
+
+ -
+
+
+ false
+
+
+
+ 0
+ 0
+
+
+
+
+ 0
+ 0
+
+
+
+ Toggles the comments in the current selection
+
+
+ Comments
+
+
+
+ :/icons/icons/comment.png :/icons/icons/comment.png
+
+
+
+ 28
+ 28
+
+
+
+ Ctrl+/
+
+
+ Qt::ToolButtonTextBesideIcon
+
+
+ false
+
+
+
+ -
+
+
+ false
+
+
+
+ 0
+ 0
+
+
+
+
+ 0
+ 0
+
+
+
+ Convert metacharacters to escaped and vice-versa
+
+
+ Metachars
+
+
+
+ :/icons/icons/metatoescaped.png :/icons/icons/metatoescaped.png
+
+
+
+ 28
+ 28
+
+
+
+ QToolButton::InstantPopup
+
+
+ Qt::ToolButtonTextBesideIcon
+
+
+ false
+
+
+
+ -
+
+
+ true
+
+
+
+ 0
+ 0
+
+
+
+
+ 0
+ 0
+
+
+
+ Search
+
+
+
+ :/icons/icons/findtext.png :/icons/icons/findtext.png
+
+
+
+ 28
+ 28
+
+
+
+ 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..e4fe7b837a
--- /dev/null
+++ b/apps/pgmodeler/pgmodeler.pro
@@ -0,0 +1,38 @@
+include(../apps.pri)
+
+TEMPLATE = app
+TARGET = pgmodeler
+
+isEqual(PRIVATE_PLUGINS, true) {
+ windows:RC_FILE=$$PRIV_RES_FOLDER/$$TARGET/windows_ico.qrc
+}
+
+HEADERS += src/pgmodelerapp.h
+
+SOURCES += src/main.cpp \
+src/pgmodelerapp.cpp
+
+# Deployment settings
+target.path = $$BINDIR
+INSTALLS = target
+
+macx {
+ macdeps.files = $$PWD/res/Info.plist $$PWD/res/PkgInfo
+
+ isEqual(PRIVATE_PLUGINS, true) {
+ macdeps.files += $$PRIV_RES_FOLDER/$$TARGET/Resources
+ }
+
+ isEqual(PRIVATE_PLUGINS, false) {
+ macdeps.files += $$PWD/res/Resources
+ }
+
+ 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 94%
rename from main/res/Info.plist
rename to apps/pgmodeler/res/Info.plist
index 330902878e..6a51a1b180 100644
--- a/main/res/Info.plist
+++ b/apps/pgmodeler/res/Info.plist
@@ -25,7 +25,7 @@
CFBundleDisplayName
pgModeler
CFBundleIdentifier
- br.com.pgmodeler.pgModeler
+ io.pgmodeler.pgModeler
CFBundleInfoDictionaryVersion
1.0
CFBundlePackageType
@@ -33,7 +33,7 @@
CFBundleSignature
????
CFBundleVersion
- 0.8.0
+ 1.2.0
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/apps/pgmodeler/res/Resources/pgmodeler.icns b/apps/pgmodeler/res/Resources/pgmodeler.icns
new file mode 100644
index 0000000000..6d62e86368
Binary files /dev/null and b/apps/pgmodeler/res/Resources/pgmodeler.icns differ
diff --git a/apps/pgmodeler/res/Resources/pgmodeler_dbm.icns b/apps/pgmodeler/res/Resources/pgmodeler_dbm.icns
new file mode 100644
index 0000000000..fad7dcc34f
Binary files /dev/null and b/apps/pgmodeler/res/Resources/pgmodeler_dbm.icns differ
diff --git a/apps/pgmodeler/res/windows_ico.ico b/apps/pgmodeler/res/windows_ico.ico
new file mode 100644
index 0000000000..a3f57aafb0
Binary files /dev/null and b/apps/pgmodeler/res/windows_ico.ico differ
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/apps/pgmodeler/res/windows_ico1.ico b/apps/pgmodeler/res/windows_ico1.ico
new file mode 100644
index 0000000000..1beed722c4
Binary files /dev/null and b/apps/pgmodeler/res/windows_ico1.ico differ
diff --git a/apps/pgmodeler/src/main.cpp b/apps/pgmodeler/src/main.cpp
new file mode 100644
index 0000000000..8bed792dde
--- /dev/null
+++ b/apps/pgmodeler/src/main.cpp
@@ -0,0 +1,139 @@
+/*
+# PostgreSQL Database Modeler (pgModeler)
+#
+# Copyright 2006-2025 - 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"
+#include
+
+#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()) + " -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("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]) + "\n";
+ output.write(lin.toStdString().c_str(), lin.size());
+ }
+ free(symbols);
+#else
+ lin = "** 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
+ {
+ //Install a signal handler to start crashhandler when SIGSEGV or SIGABRT is emitted
+ signal(SIGSEGV, startCrashHandler);
+ signal(SIGABRT, startCrashHandler);
+
+ GlobalAttributes::init(argv[0], true);
+ PgModelerApp app(argc,argv);
+ int res=0;
+
+ //Loading the application splash screen
+ QSplashScreen splash;
+ QPixmap pix(":images/images/pgmodeler_splash.png");
+
+ if(qApp->primaryScreen()->devicePixelRatio() > 1)
+ pix.setDevicePixelRatio(qApp->primaryScreen()->devicePixelRatio());
+ else
+ pix = pix.scaledToWidth(320, Qt::SmoothTransformation);
+
+ splash.setPixmap(pix);
+ 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_t(e.getErrorCode());
+ }
+}
diff --git a/apps/pgmodeler/src/pgmodelerapp.cpp b/apps/pgmodeler/src/pgmodelerapp.cpp
new file mode 100644
index 0000000000..426df1399f
--- /dev/null
+++ b/apps/pgmodeler/src/pgmodelerapp.cpp
@@ -0,0 +1,85 @@
+/*
+# PostgreSQL Database Modeler (pgModeler)
+#
+# Copyright 2006-2025 - 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"
+#include
+
+PgModelerApp::PgModelerApp(int &argc, char **argv) : Application(argc,argv)
+{
+ QDir dir;
+
+ try
+ {
+ //Creating the initial user's configuration
+ createUserConfiguration();
+ }
+ catch(Exception &e)
+ {
+ Messagebox::error(e, __PRETTY_FUNCTION__, __FILE__, __LINE__);
+ }
+
+ //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::getPluginsPath()))
+ this->addLibraryPath(GlobalAttributes::getPluginsPath());
+
+ //Check if the temporary dir exists, if not, creates it.
+ if(!dir.exists(GlobalAttributes::getTemporaryPath()))
+ {
+ if(!dir.mkdir(GlobalAttributes::getTemporaryPath()))
+ {
+ Messagebox msg;
+ msg.show(Exception(Exception::getErrorMessage(ErrorCode::FileDirectoryNotWritten).arg(GlobalAttributes::getTemporaryPath()),
+ ErrorCode::FileDirectoryNotWritten, __PRETTY_FUNCTION__,__FILE__,__LINE__));
+ }
+ }
+
+ //Trying to identify if the user defined a custom UI language in the pgmodeler.conf file
+ QString lang_id = GlobalAttributes::getConfigParamFromFile(Attributes::UiLanguage, GlobalAttributes::GeneralConf);
+
+ if(lang_id.isEmpty())
+ lang_id = QLocale::system().name();
+
+ loadTranslations(lang_id, true);
+}
+
+bool PgModelerApp::notify(QObject *receiver, QEvent *event)
+{
+ try
+ {
+ return QApplication::notify(receiver,event);
+ }
+ catch(Exception &e)
+ {
+ Messagebox::error(e, __PRETTY_FUNCTION__, __FILE__, __LINE__);
+ return false;
+ }
+ catch(...)
+ {
+ Messagebox::error(tr("Unknown exception caught!"), ErrorCode::Custom,
+ __PRETTY_FUNCTION__, __FILE__, __LINE__);
+ return false;
+ }
+}
diff --git a/apps/pgmodeler/src/pgmodelerapp.h b/apps/pgmodeler/src/pgmodelerapp.h
new file mode 100644
index 0000000000..a0bc5ffa56
--- /dev/null
+++ b/apps/pgmodeler/src/pgmodelerapp.h
@@ -0,0 +1,42 @@
+/*
+# PostgreSQL Database Modeler (pgModeler)
+#
+# Copyright 2006-2025 - 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 {
+ Q_OBJECT
+
+ public:
+ PgModelerApp(int & argc, char ** argv);
+ bool notify(QObject * receiver, QEvent * event);
+};
+
+#endif
diff --git a/assets/conf/appearance.conf b/assets/conf/appearance.conf
new file mode 100644
index 0000000000..ccdf6441ad
--- /dev/null
+++ b/assets/conf/appearance.conf
@@ -0,0 +1,84 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
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/assets/conf/diff-presets.conf b/assets/conf/diff-presets.conf
new file mode 100644
index 0000000000..523bb17f14
--- /dev/null
+++ b/assets/conf/diff-presets.conf
@@ -0,0 +1,27 @@
+
+
+
+
+
diff --git a/assets/conf/dtd/appearance.dtd b/assets/conf/dtd/appearance.dtd
new file mode 100644
index 0000000000..8d99708d57
--- /dev/null
+++ b/assets/conf/dtd/appearance.dtd
@@ -0,0 +1,54 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/conf/dtd/connections.dtd b/assets/conf/dtd/connections.dtd
similarity index 96%
rename from conf/dtd/connections.dtd
rename to assets/conf/dtd/connections.dtd
index f3d167573c..5da900c26e 100644
--- a/conf/dtd/connections.dtd
+++ b/assets/conf/dtd/connections.dtd
@@ -3,7 +3,6 @@
Unexpected results may occur if the code is changed deliberately.
-->
-
@@ -20,6 +19,7 @@
+
diff --git a/assets/conf/dtd/diff-presets.dtd b/assets/conf/dtd/diff-presets.dtd
new file mode 100644
index 0000000000..d7c983791b
--- /dev/null
+++ b/assets/conf/dtd/diff-presets.dtd
@@ -0,0 +1,33 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/assets/conf/dtd/general.dtd b/assets/conf/dtd/general.dtd
new file mode 100644
index 0000000000..b79cf979c6
--- /dev/null
+++ b/assets/conf/dtd/general.dtd
@@ -0,0 +1,86 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/assets/conf/dtd/relationships.dtd b/assets/conf/dtd/relationships.dtd
new file mode 100644
index 0000000000..0cf5587ab8
--- /dev/null
+++ b/assets/conf/dtd/relationships.dtd
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/conf/dtd/snippets.dtd b/assets/conf/dtd/snippets.dtd
similarity index 86%
rename from conf/dtd/snippets.dtd
rename to assets/conf/dtd/snippets.dtd
index 56ec1c01a9..cd4831a649 100644
--- a/conf/dtd/snippets.dtd
+++ b/assets/conf/dtd/snippets.dtd
@@ -13,5 +13,5 @@
+ extension|eventtrigger|general|policy|foreigndatawrapper|foreignserver|usermapping) "general">
diff --git a/assets/conf/dtd/source-code-highlight.dtd b/assets/conf/dtd/source-code-highlight.dtd
new file mode 100644
index 0000000000..b74b69d5e8
--- /dev/null
+++ b/assets/conf/dtd/source-code-highlight.dtd
@@ -0,0 +1,84 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/conf/dtd/sql-history.dtd b/assets/conf/dtd/sql-history.dtd
similarity index 100%
rename from conf/dtd/sql-history.dtd
rename to assets/conf/dtd/sql-history.dtd
diff --git a/assets/conf/example.dbm b/assets/conf/example.dbm
new file mode 100644
index 0000000000..a3b6061a6e
--- /dev/null
+++ b/assets/conf/example.dbm
@@ -0,0 +1,230 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 0 ]]>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 0 ]]>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 0 ]]>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/assets/conf/general.conf b/assets/conf/general.conf
new file mode 100644
index 0000000000..b032293173
--- /dev/null
+++ b/assets/conf/general.conf
@@ -0,0 +1,48 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/assets/conf/icons-big.conf b/assets/conf/icons-big.conf
new file mode 100644
index 0000000000..6585a812c2
--- /dev/null
+++ b/assets/conf/icons-big.conf
@@ -0,0 +1,139 @@
+QLabel#db_icon_lbl {
+ min-width: 25px;
+ min-height: 25px;
+ max-width: 25px;
+ max-height: 25px;
+}
+
+QPushButton,
+QToolButton {
+ qproperty-iconSize: 28px;
+}
+
+QToolButton#hide_tb {
+ qproperty-iconSize: 20px;
+}
+
+QToolBar#tools_acts_tb {
+ qproperty-iconSize: 40px;
+}
+
+QToolBar#model_acts_tb {
+ qproperty-iconSize: 32px;
+}
+
+QWidget#bnts_parent_wgt > QToolButton {
+ qproperty-iconSize: 32px;
+}
+
+ModelNavigationWidget > QToolButton {
+ qproperty-iconSize: 32px;
+}
+
+WelcomeWidget > QToolButton {
+ qproperty-iconSize: 50px;
+ margin-left: 1px;
+ margin-right: 1px;
+}
+
+WelcomeWidget > QLabel#logo_lbl {
+ min-height: 300px;
+ min-width: 300px;
+ max-height: 300px;
+ max-width: 300px;
+}
+
+
+QTabWidget {
+ qproperty-iconSize: 22px;
+}
+
+QListWidget,
+QComboBox,
+QTreeWidget,
+QTableWidget,
+QTableView {
+ qproperty-iconSize: 25px;
+}
+
+ReferencesWidget QLabel#sel_obj_icon_lbl,
+ModelValidationWidget QLabel#warn_lbl,
+ModelValidationWidget QLabel#error_lbl,
+QFrame#protected_obj_frm QLabel#icon_lbl,
+QFrame#warning_frm QLabel#icon_lbl2,
+QFrame#hint_frm QLabel#icon_lbl,
+QFrame#hint_frm QLabel#icon_lbl2,
+QFrame#alert_frm QLabel#icon_lbl,
+QFrame#alert2_frm QLabel#icon_lbl2,
+QFrame#alert_frm2 QLabel#icon_lbl,
+QFrame#info_frm QLabel#icon_lbl {
+ min-width: 25px;
+ min-height: 25px;
+ max-width: 25px;
+ max-height: 25px;
+}
+
+Messagebox QLabel#icon_lbl {
+ min-width: 32px;
+ min-height: 32px;
+ max-width: 32px;
+ max-height: 32px;
+}
+
+NewObjectOverlayWidget > QFrame > QGroupBox > QWidget > QToolButton {
+ qproperty-iconSize: 32px;
+}
+
+ModelExportForm QRadioButton#export_to_dbms_rb,
+ModelExportForm QRadioButton#export_to_file_rb,
+ModelExportForm QRadioButton#export_to_img_rb,
+ModelExportForm QRadioButton#export_to_dict_rb {
+ qproperty-iconSize: 37px 90px;
+}
+
+SceneInfoWidget > QLabel#mouse_pos_ico_lbl,
+SceneInfoWidget > QLabel#zoom_ico_lbl,
+SceneInfoWidget > QLabel#obj_icon_lbl,
+SceneInfoWidget > QLabel#obj_pos_ico_lbl {
+ min-height: 25px;
+ max-height: 25px;
+ min-width: 25px;
+ max-width: 25px;
+}
+
+BaseObjectWidget QLabel#obj_icon_lbl,
+SourceCodeWidget QLabel#icon2_lbl {
+ min-height: 25px;
+ max-height: 25px;
+ min-width: 25px;
+ max-width: 25px;
+}
+
+QTabBar #ScrollLeftButton,
+QTabBar #ScrollRightButton {
+ min-height: 24px;
+ max-height: 24px;
+}
+
+QTabWidget#sql_exec_tbw QToolButton#sql_exec_corner_btn {
+ min-height: 24px;
+ max-height: 24px;
+ min-width: 24px;
+ max-width: 24px;
+ qproperty-iconSize: 22px 22px;
+}
+
+DataGridWidget > QGroupBox#tab_info_gb > QLabel#schema_ico_lbl,
+DataGridWidget > QGroupBox#tab_info_gb > QLabel#rows_cnt_ico_lbl,
+DataGridWidget > QGroupBox#tab_info_gb > QLabel#rows_added_ico_lbl,
+DataGridWidget > QGroupBox#tab_info_gb > QLabel#rows_changed_ico_lbl,
+DataGridWidget > QGroupBox#tab_info_gb > QLabel#rows_deleted_ico_lbl {
+ min-height: 25px;
+ max-height: 25px;
+ min-width: 25px;
+ max-width: 25px;
+}
+
+DataGridWidget > QGroupBox#tab_info_gb > QToolButton#vacuum_tb {
+ qproperty-iconSize: 25px 25px;
+}
diff --git a/assets/conf/icons-medium.conf b/assets/conf/icons-medium.conf
new file mode 100644
index 0000000000..828ef2c02f
--- /dev/null
+++ b/assets/conf/icons-medium.conf
@@ -0,0 +1,138 @@
+QLabel#db_icon_lbl {
+ min-width: 22px;
+ min-height: 22px;
+ max-width: 22px;
+ max-height: 22px;
+}
+
+QPushButton,
+QToolButton {
+ qproperty-iconSize: 20px;
+}
+
+QToolButton#hide_tb {
+ qproperty-iconSize: 18px;
+}
+
+QToolBar#tools_acts_tb {
+ qproperty-iconSize: 32px;
+}
+
+QToolBar#model_acts_tb {
+ qproperty-iconSize: 25px;
+}
+
+QWidget#bnts_parent_wgt > QToolButton {
+ qproperty-iconSize: 28px;
+}
+
+ModelNavigationWidget > QToolButton {
+ qproperty-iconSize: 25px;
+}
+
+WelcomeWidget > QToolButton {
+ qproperty-iconSize: 40px;
+ margin-left: 1px;
+ margin-right: 1px;
+}
+
+WelcomeWidget > QLabel#logo_lbl {
+ min-height: 250px;
+ min-width: 250px;
+ max-height: 250px;
+ max-width: 250px;
+}
+
+QTabWidget {
+ qproperty-iconSize: 20px;
+}
+
+QListWidget,
+QComboBox,
+QTreeWidget,
+QTableWidget,
+QTableView {
+ qproperty-iconSize: 20px;
+}
+
+ReferencesWidget QLabel#sel_obj_icon_lbl,
+ModelValidationWidget QLabel#warn_lbl,
+ModelValidationWidget QLabel#error_lbl,
+QFrame#protected_obj_frm QLabel#icon_lbl,
+QFrame#warning_frm QLabel#icon_lbl2,
+QFrame#hint_frm QLabel#icon_lbl,
+QFrame#hint_frm QLabel#icon_lbl2,
+QFrame#alert_frm QLabel#icon_lbl,
+QFrame#alert2_frm QLabel#icon_lbl2,
+QFrame#alert_frm2 QLabel#icon_lbl,
+QFrame#info_frm QLabel#icon_lbl {
+ min-width: 22px;
+ min-height: 22px;
+ max-width: 22px;
+ max-height: 22px;
+}
+
+Messagebox QLabel#icon_lbl {
+ min-width: 28px;
+ min-height: 28px;
+ max-width: 28px;
+ max-height: 28px;
+}
+
+NewObjectOverlayWidget > QFrame > QGroupBox > QWidget > QToolButton {
+ qproperty-iconSize: 28px;
+}
+
+ModelExportForm QRadioButton#export_to_dbms_rb,
+ModelExportForm QRadioButton#export_to_file_rb,
+ModelExportForm QRadioButton#export_to_img_rb,
+ModelExportForm QRadioButton#export_to_dict_rb {
+ qproperty-iconSize: 30px 75px;
+}
+
+SceneInfoWidget > QLabel#mouse_pos_ico_lbl,
+SceneInfoWidget > QLabel#zoom_ico_lbl,
+SceneInfoWidget > QLabel#obj_icon_lbl,
+SceneInfoWidget > QLabel#obj_pos_ico_lbl {
+ min-height: 22px;
+ max-height: 22px;
+ min-width: 22px;
+ max-width: 22px;
+}
+
+BaseObjectWidget QLabel#obj_icon_lbl,
+SourceCodeWidget QLabel#icon2_lbl {
+ min-height: 22px;
+ max-height: 22px;
+ min-width: 22px;
+ max-width: 22px;
+}
+
+QTabBar #ScrollLeftButton,
+QTabBar #ScrollRightButton {
+ min-height: 22px;
+ max-height: 22px;
+}
+
+QTabWidget#sql_exec_tbw QToolButton#sql_exec_corner_btn {
+ min-height: 22px;
+ max-height: 22px;
+ min-width: 22px;
+ max-width: 22px;
+ qproperty-iconSize: 20px 20px;
+}
+
+DataGridWidget > QGroupBox#tab_info_gb > QLabel#schema_ico_lbl,
+DataGridWidget > QGroupBox#tab_info_gb > QLabel#rows_cnt_ico_lbl,
+DataGridWidget > QGroupBox#tab_info_gb > QLabel#rows_added_ico_lbl,
+DataGridWidget > QGroupBox#tab_info_gb > QLabel#rows_changed_ico_lbl,
+DataGridWidget > QGroupBox#tab_info_gb > QLabel#rows_deleted_ico_lbl {
+ min-height: 22px;
+ max-height: 22px;
+ min-width: 22px;
+ max-width: 22px;
+}
+
+DataGridWidget > QGroupBox#tab_info_gb > QToolButton#vacuum_tb {
+ qproperty-iconSize: 22px 22px;
+}
\ No newline at end of file
diff --git a/assets/conf/icons-small.conf b/assets/conf/icons-small.conf
new file mode 100644
index 0000000000..bc35beacd3
--- /dev/null
+++ b/assets/conf/icons-small.conf
@@ -0,0 +1,138 @@
+QLabel#db_icon_lbl {
+ min-width: 16px;
+ min-height: 16px;
+ max-width: 16px;
+ max-height: 16px;
+}
+
+QPushButton,
+QToolButton {
+ qproperty-iconSize: 16px;
+}
+
+QToolButton#hide_tb {
+ qproperty-iconSize: 16px;
+}
+
+QToolBar#tools_acts_tb {
+ qproperty-iconSize: 28px;
+}
+
+QToolBar#model_acts_tb {
+ qproperty-iconSize: 20px;
+}
+
+QWidget#bnts_parent_wgt > QToolButton {
+ qproperty-iconSize: 25px;
+}
+
+ModelNavigationWidget > QToolButton {
+ qproperty-iconSize: 20px;
+}
+
+WelcomeWidget > QToolButton {
+ qproperty-iconSize: 32px;
+ margin-left: 1px;
+ margin-right: 1px;
+}
+
+WelcomeWidget > QLabel#logo_lbl {
+ min-height: 200px;
+ min-width: 200px;
+ max-height: 200px;
+ max-width: 200px;
+}
+
+QTabWidget {
+ qproperty-iconSize: 16px;
+}
+
+QListWidget,
+QComboBox,
+QTreeWidget,
+QTableWidget,
+QTableView {
+ qproperty-iconSize: 16px;
+}
+
+ReferencesWidget QLabel#sel_obj_icon_lbl,
+ModelValidationWidget QLabel#warn_lbl,
+ModelValidationWidget QLabel#error_lbl,
+QFrame#protected_obj_frm QLabel#icon_lbl,
+QFrame#warning_frm QLabel#icon_lbl2,
+QFrame#hint_frm QLabel#icon_lbl,
+QFrame#hint_frm QLabel#icon_lbl2,
+QFrame#alert_frm QLabel#icon_lbl,
+QFrame#alert2_frm QLabel#icon_lbl2,
+QFrame#alert_frm2 QLabel#icon_lbl,
+QFrame#info_frm QLabel#icon_lbl {
+ min-width: 20px;
+ min-height: 20px;
+ max-width: 20px;
+ max-height: 20px;
+}
+
+Messagebox QLabel#icon_lbl {
+ min-width: 25px;
+ min-height: 25px;
+ max-width: 25px;
+ max-height: 25px;
+}
+
+NewObjectOverlayWidget > QFrame > QGroupBox > QWidget > QToolButton {
+ qproperty-iconSize: 25px;
+}
+
+ModelExportForm QRadioButton#export_to_dbms_rb,
+ModelExportForm QRadioButton#export_to_file_rb,
+ModelExportForm QRadioButton#export_to_img_rb,
+ModelExportForm QRadioButton#export_to_dict_rb {
+ qproperty-iconSize: 26px 65px;
+}
+
+SceneInfoWidget > QLabel#mouse_pos_ico_lbl,
+SceneInfoWidget > QLabel#zoom_ico_lbl,
+SceneInfoWidget > QLabel#obj_icon_lbl,
+SceneInfoWidget > QLabel#obj_pos_ico_lbl {
+ min-height: 20px;
+ max-height: 20px;
+ min-width: 20px;
+ max-width: 20px;
+}
+
+BaseObjectWidget QLabel#obj_icon_lbl,
+SourceCodeWidget QLabel#icon2_lbl {
+ min-height: 20px;
+ max-height: 20px;
+ min-width: 20px;
+ max-width: 20px;
+}
+
+QTabBar #ScrollLeftButton,
+QTabBar #ScrollRightButton {
+ min-height: 20px;
+ max-height: 20px;
+}
+
+QTabWidget#sql_exec_tbw QToolButton#sql_exec_corner_btn {
+ min-height: 20px;
+ max-height: 20px;
+ min-width: 20px;
+ max-width: 20px;
+ qproperty-iconSize: 18px 18px;
+}
+
+DataGridWidget > QGroupBox#tab_info_gb > QLabel#schema_ico_lbl,
+DataGridWidget > QGroupBox#tab_info_gb > QLabel#rows_cnt_ico_lbl,
+DataGridWidget > QGroupBox#tab_info_gb > QLabel#rows_added_ico_lbl,
+DataGridWidget > QGroupBox#tab_info_gb > QLabel#rows_changed_ico_lbl,
+DataGridWidget > QGroupBox#tab_info_gb > QLabel#rows_deleted_ico_lbl {
+ min-height: 20px;
+ max-height: 20px;
+ min-width: 20px;
+ max-width: 20px;
+}
+
+DataGridWidget > QGroupBox#tab_info_gb > QToolButton#vacuum_tb {
+ qproperty-iconSize: 18px 18px;
+}
\ No newline at end of file
diff --git a/assets/conf/pgmodeler_dbm.png b/assets/conf/pgmodeler_dbm.png
new file mode 100644
index 0000000000..9f87db01a3
Binary files /dev/null and b/assets/conf/pgmodeler_dbm.png differ
diff --git a/assets/conf/pgmodeler_logo.png b/assets/conf/pgmodeler_logo.png
new file mode 100644
index 0000000000..a9ba493ff8
Binary files /dev/null and b/assets/conf/pgmodeler_logo.png differ
diff --git a/assets/conf/pgmodeler_sch.png b/assets/conf/pgmodeler_sch.png
new file mode 100644
index 0000000000..04d9be9284
Binary files /dev/null and b/assets/conf/pgmodeler_sch.png differ
diff --git a/assets/conf/relationships.conf b/assets/conf/relationships.conf
new file mode 100644
index 0000000000..23b8c53b82
--- /dev/null
+++ b/assets/conf/relationships.conf
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/assets/conf/schemas/appearance.sch b/assets/conf/schemas/appearance.sch
new file mode 100644
index 0000000000..8bc01516f0
--- /dev/null
+++ b/assets/conf/schemas/appearance.sch
@@ -0,0 +1,114 @@
+# XML definition for appearance settings.
+# CAUTION: Do not modify this file unless you know what you are doing.
+[] \n
+[] \n
+
+%set {spc} \t \t
+
+\n \n
+
+\n \t ] \n
+
+\n \t ] \n
+
+\n \t \n
+{spc} [ ] \n
+{spc} [ ] \n
+{spc} [ ] \n
+{spc} [ ] \n
+{spc} [ ] \n
+{spc} [ ] \n
+{spc} [ ] \n
+{spc} [ ] \n
+{spc} [ ] \n
+{spc} [ ] \n
+{spc} [ ] \n
+{spc} [ ] \n
+{spc} [ ] \n
+{spc} [ ] \n
+{spc} [ ] \n
+{spc} [ ] \n
+{spc} [ ] \n
+{spc} [ ] \n
+{spc} [ ] \n
+{spc} [ ] \n
+{spc} [ ] \n
+{spc} [ ] \n
+{spc} [ ] \n
+{spc} [ ] \n
+{spc} [ ] \n
+{spc} [ ] \n
+{spc} [ ] \n
+{spc} [ ] \n
+
+{spc} [ ] \n
+{spc} [ ] \n
+{spc} [ ] \n
+{spc} [ ] \n
+{spc} [ ] \n
+{spc} [ ] \n
+{spc} [ ] \n
+{spc} [ ] \n
+{spc} [ ] \n
+{spc} [ ] \n
+{spc} [ ] \n
+{spc} [ ] \n
+{spc} [ ] \n
+{spc} [ ] \n
+{spc} [ ] \n
+{spc} [ ] \n
+{spc} [ ] \n
+{spc} [ ] \n
+{spc} [ ] \n
+{spc} [ ] \n
+{spc} [ ] \n
+{spc} [ ] \n
+{spc} [ ] \n
+{spc} [ ] \n
+{spc} [ ] \n
+{spc} [ ] \n
+{spc} [ ] \n
+{spc} [ ] \n
+{spc} [ ] \n
+{spc} [ ] \n
+{spc} [ ] \n
+{spc} [ ] \n
+{spc} [ ] \n
+{spc} [ ] \n
+{spc} [ ] \n
+{spc} [ ] \n
+{spc} [ ] \n
+
+\t \n
+
diff --git a/assets/conf/schemas/application-dbm.sch b/assets/conf/schemas/application-dbm.sch
new file mode 100644
index 0000000000..1a0110f0a7
--- /dev/null
+++ b/assets/conf/schemas/application-dbm.sch
@@ -0,0 +1,11 @@
+[] \n
+[] \n
+\t []
+
+\t [pgModeler Database Model ] \n
+\t [ ] \n
+\t [ ] \n
+\t [ ] \n
+\t [ ] \n
+ \n
+
diff --git a/assets/conf/schemas/application-sch.sch b/assets/conf/schemas/application-sch.sch
new file mode 100644
index 0000000000..57ddc2150a
--- /dev/null
+++ b/assets/conf/schemas/application-sch.sch
@@ -0,0 +1,11 @@
+[] \n
+[] \n
+\t []
+
+\t [pgModeler Schema File ] \n
+\t [ ] \n
+\t [ ] \n
+\t [ ] \n
+\t [ ] \n
+ \n
+
diff --git a/assets/conf/schemas/commands.sch b/assets/conf/schemas/commands.sch
new file mode 100644
index 0000000000..58433d2278
--- /dev/null
+++ b/assets/conf/schemas/commands.sch
@@ -0,0 +1,6 @@
+# XML definition for sql commands included in sql history configuration file
+# CAUTION: Do not modify this file unless you know what you are doing.
+
+[ \n
+[ \n
+[ ] \n
diff --git a/assets/conf/schemas/connections.sch b/assets/conf/schemas/connections.sch
new file mode 100644
index 0000000000..3048d59e9b
--- /dev/null
+++ b/assets/conf/schemas/connections.sch
@@ -0,0 +1,60 @@
+# XML definition for connections configuration
+# CAUTION: Do not modify this file unless you know what you are doing.
+%if {connections} %then
+
+ [] \n
+ [] \n
+
+ \n
+
+ {connections}
+
+ \n
+
+%else
+
+ %set {spc} \n \t
+
+ \t [ \n
+%end
diff --git a/assets/conf/schemas/desktop-sch.sch b/assets/conf/schemas/desktop-sch.sch
new file mode 100644
index 0000000000..6b98f7b89e
--- /dev/null
+++ b/assets/conf/schemas/desktop-sch.sch
@@ -0,0 +1,14 @@
+\[ Desktop \s Entry \] \n
+[Comment=Edit and check the syntax of pgModeler schema files] \n
+[Exec=]&{application} \n
+[GenericName=pgModeler Schema Editor] \n
+[Icon=]&{icon} \n
+[MimeType=application/sch] \n
+[Name=pgModeler Schema Editor] \n
+[NoDisplay=false] \n
+[Path=]&{working-dir} \n
+[StartupNotify=false] \n
+[Terminal=false] \n
+[TerminalOptions=] \n
+[Type=Application] \n
+[Categories=Development;] \n
diff --git a/assets/conf/schemas/desktop.sch b/assets/conf/schemas/desktop.sch
new file mode 100644
index 0000000000..aeff953b53
--- /dev/null
+++ b/assets/conf/schemas/desktop.sch
@@ -0,0 +1,14 @@
+\[ Desktop \s Entry \] \n
+[Comment=Create and deploy PostgreSQL database models] \n
+[Exec=]&{application} \n
+[GenericName=PostgreSQL Database Modeler] \n
+[Icon=]&{icon} \n
+[MimeType=application/dbm] \n
+[Name=pgModeler] \n
+[NoDisplay=false] \n
+[Path=]&{working-dir} \n
+[StartupNotify=false] \n
+[Terminal=false] \n
+[TerminalOptions=] \n
+[Type=Application] \n
+[Categories=Development;] \n
diff --git a/assets/conf/schemas/diff-presets.sch b/assets/conf/schemas/diff-presets.sch
new file mode 100644
index 0000000000..551d1615c1
--- /dev/null
+++ b/assets/conf/schemas/diff-presets.sch
@@ -0,0 +1,11 @@
+# XML definition for relationships configuration file
+# CAUTION: Do not modify this file unless you know what you are doing.
+[] \n
+[] \n
+
+ \n
+{preset}
+ \n
diff --git a/assets/conf/schemas/file.sch b/assets/conf/schemas/file.sch
new file mode 100644
index 0000000000..b5894c3dd9
--- /dev/null
+++ b/assets/conf/schemas/file.sch
@@ -0,0 +1,3 @@
+# XML definition for files opened on a session
+# CAUTION: Do not modify this file unless you know what you are doing.
+\t\t [ \n
diff --git a/assets/conf/schemas/general.sch b/assets/conf/schemas/general.sch
new file mode 100644
index 0000000000..081a3f651e
--- /dev/null
+++ b/assets/conf/schemas/general.sch
@@ -0,0 +1,100 @@
+# XML definition for basic configurations file
+# CAUTION: Do not modify this file unless you know what you are doing.
+[] \n
+[] \n
+
+%set {spc} \t \t
+
+ \n
+\t [ \n
+
+%if {file} %then
+ \n \t \n
+ \t {file}
+ \t \n
+%end
+
+%if {recent-models} %then
+ \n \t \n
+ {recent-models}
+ \t \n
+%end
+
+%if {dock-widgets} %then
+ \n \t \n
+ {dock-widgets}
+ \t \n
+%end
+
+%if {widgets-geometry} %then
+ \n \t \n
+ {widgets-geometry}
+ \t \n
+%end
+
+ \n
diff --git a/assets/conf/schemas/patterns.sch b/assets/conf/schemas/patterns.sch
new file mode 100644
index 0000000000..41891b1992
--- /dev/null
+++ b/assets/conf/schemas/patterns.sch
@@ -0,0 +1,15 @@
+# XML definition for relationship name patterns (part of relationships.conf file)
+# CAUTION: Do not modify this file unless you know what you are doing.
+
+\t \t [ ] \n
diff --git a/assets/conf/schemas/preset.sch b/assets/conf/schemas/preset.sch
new file mode 100644
index 0000000000..42757da9bc
--- /dev/null
+++ b/assets/conf/schemas/preset.sch
@@ -0,0 +1,63 @@
+%set {spacer} \n \t \t
+
+\t [
+%else
+ >
+ {spacer} [ \n
+\t
+%end
+
+\n
\ No newline at end of file
diff --git a/assets/conf/schemas/relationships.sch b/assets/conf/schemas/relationships.sch
new file mode 100644
index 0000000000..98b0e5a27e
--- /dev/null
+++ b/assets/conf/schemas/relationships.sch
@@ -0,0 +1,25 @@
+# XML definition for relationships configuration file
+# CAUTION: Do not modify this file unless you know what you are doing.
+[] \n
+[] \n
+
+ \n
+
+\t [ ] \n
+
+\t \n
+{patterns}
+\t \n
+
+ \n
+
diff --git a/assets/conf/schemas/snippet.sch b/assets/conf/schemas/snippet.sch
new file mode 100644
index 0000000000..c98fc99712
--- /dev/null
+++ b/assets/conf/schemas/snippet.sch
@@ -0,0 +1,5 @@
+# XML definition for snippets configurations file
+# CAUTION: Do not modify this file unless you know what you are doing.
+\t [ \n
+[ \n
+\t \n \n
diff --git a/assets/conf/schemas/snippets.sch b/assets/conf/schemas/snippets.sch
new file mode 100644
index 0000000000..84e79fb34e
--- /dev/null
+++ b/assets/conf/schemas/snippets.sch
@@ -0,0 +1,15 @@
+# XML definition for snippets configurations file
+# CAUTION: Do not modify this file unless you know what you are doing.
+[] \n
+[] \n
+
+ \n
+
+%if {snippet} %then
+ {snippet}
+%end
+
+ \n
diff --git a/assets/conf/schemas/sql-history.sch b/assets/conf/schemas/sql-history.sch
new file mode 100644
index 0000000000..73591ca253
--- /dev/null
+++ b/assets/conf/schemas/sql-history.sch
@@ -0,0 +1,15 @@
+# XML definition for SQL history configurations file
+# CAUTION: Do not modify this file unless you know what you are doing.
+[] \n
+[] \n
+
+ \n
+
+%if {commands} %then
+ {commands}
+%end
+
+ \n
diff --git a/assets/conf/schemas/widget.sch b/assets/conf/schemas/widget.sch
new file mode 100644
index 0000000000..447f250cde
--- /dev/null
+++ b/assets/conf/schemas/widget.sch
@@ -0,0 +1,45 @@
+# XML definition for files opened on a session
+# CAUTION: Do not modify this file unless you know what you are doing.
+\t\t [ \n
diff --git a/assets/conf/snippets.conf b/assets/conf/snippets.conf
new file mode 100644
index 0000000000..fa4075ff22
--- /dev/null
+++ b/assets/conf/snippets.conf
@@ -0,0 +1,905 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/assets/conf/sql-history.conf b/assets/conf/sql-history.conf
new file mode 100644
index 0000000000..5f543c4a91
--- /dev/null
+++ b/assets/conf/sql-history.conf
@@ -0,0 +1,7 @@
+
+
+
+
diff --git a/assets/conf/themes/dark/appearance.conf b/assets/conf/themes/dark/appearance.conf
new file mode 100644
index 0000000000..ccdf6441ad
--- /dev/null
+++ b/assets/conf/themes/dark/appearance.conf
@@ -0,0 +1,84 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/assets/conf/themes/dark/extra-ui-style.conf b/assets/conf/themes/dark/extra-ui-style.conf
new file mode 100644
index 0000000000..4b4cec122c
--- /dev/null
+++ b/assets/conf/themes/dark/extra-ui-style.conf
@@ -0,0 +1,20 @@
+RelationshipConfigWidget QLabel#crows_foot_lbl {
+ qproperty-pixmap: url(":/images/images/rel_crows_foot_dark.png");
+}
+
+RelationshipConfigWidget QLabel#conn_tab_edges_lbl {
+ qproperty-pixmap: url(":/images/images/rel_tab_edges_dark.png");
+}
+
+RelationshipConfigWidget QLabel#conn_fk_pk_lbl {
+ qproperty-pixmap: url(":/images/images/rel_fk_to_pk_dark.png");
+}
+
+RelationshipConfigWidget QLabel#conn_cnt_pnts_lbl {
+ qproperty-pixmap: url(":/images/images/rel_center_pnts_dark.png");
+}
+
+ObjectRenameWidget QLabel#handle_lbl,
+LayersWidget QLabel#handle_lbl {
+ image: url(':/images/images/handle_dark.png');
+}
diff --git a/assets/conf/themes/dark/pattern-highlight.conf b/assets/conf/themes/dark/pattern-highlight.conf
new file mode 100644
index 0000000000..d829015d7c
--- /dev/null
+++ b/assets/conf/themes/dark/pattern-highlight.conf
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/assets/conf/themes/dark/sch-highlight.conf b/assets/conf/themes/dark/sch-highlight.conf
new file mode 100644
index 0000000000..4bd170fb65
--- /dev/null
+++ b/assets/conf/themes/dark/sch-highlight.conf
@@ -0,0 +1,94 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/assets/conf/themes/dark/sql-highlight.conf b/assets/conf/themes/dark/sql-highlight.conf
new file mode 100644
index 0000000000..d896ebd2d7
--- /dev/null
+++ b/assets/conf/themes/dark/sql-highlight.conf
@@ -0,0 +1,695 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/assets/conf/themes/dark/xml-highlight.conf b/assets/conf/themes/dark/xml-highlight.conf
new file mode 100644
index 0000000000..efda3eaac5
--- /dev/null
+++ b/assets/conf/themes/dark/xml-highlight.conf
@@ -0,0 +1,49 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/assets/conf/themes/inksaver/appearance.conf b/assets/conf/themes/inksaver/appearance.conf
new file mode 100644
index 0000000000..74b598ecb7
--- /dev/null
+++ b/assets/conf/themes/inksaver/appearance.conf
@@ -0,0 +1,82 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/assets/conf/themes/inksaver/extra-ui-style.conf b/assets/conf/themes/inksaver/extra-ui-style.conf
new file mode 100644
index 0000000000..a8be1233c8
--- /dev/null
+++ b/assets/conf/themes/inksaver/extra-ui-style.conf
@@ -0,0 +1,165 @@
+QWidget#bg_widget {
+ background-color: #d7d8d9;
+}
+
+QWidget#bg_widget > QStackedWidget {
+ border-top: 1px solid #9fa0a1;
+ border-left: 1px solid #9fa0a1;
+}
+
+QWidget#menu_title_wgt {
+ background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #ffffff , stop: 1 #E6E6E6);
+ border-color: #c0a0a0a0;
+}
+
+QWidget#bnts_parent_wgt {
+ background-color: #eff0f1;
+ border-color: #9fa0a1;
+}
+
+QWidget#bnts_parent_wgt > QFrame {
+ border-top: 1px solid #9fa0a1;
+}
+
+QMenuBar {
+ background-color: #eff0f1;
+}
+
+QMenuBar::item {
+ color: #303030;
+}
+
+QMenuBar::item:disabled {
+ color: #505050;
+}
+
+QMenu::item:disabled {
+ color: #505050;
+}
+
+QToolBar {
+ background-color: #eff0f1;
+}
+
+QToolBar::separator {
+ background-color: #9fa0a1;
+}
+
+QWidget#bnts_parent_wgt > QToolButton,
+QToolBar#tools_acts_tb > QToolButton {
+ color: #101010;
+}
+
+QWidget#bnts_parent_wgt > QToolButton:disabled,
+QToolBar#tools_acts_tb > QToolButton:disabled {
+ color: #505050;
+}
+
+QToolBar > QToolButton#qt_toolbar_ext_button,
+QToolBar#tools_acts_tb > QToolButton:hover,
+QToolBar#tools_acts_tb > QToolButton:checked,
+QToolBar#model_acts_tb > QToolButton:hover,
+QToolBar#model_acts_tb > QToolButton:checked,
+ModelNavigationWidget > QToolButton:hover,
+QWidget#bnts_parent_wgt > QToolButton:hover,
+QWidget#bnts_parent_wgt > QToolButton:checked,
+QMenuBar::item:selected {
+ color: #101010;
+ background-color: qlineargradient(x1: 0, y1: 0, x2: 1, y2: 1, stop: 0 #43c0ff, stop: 1 #39a4d9);
+}
+
+QToolBar > QToolButton#qt_toolbar_ext_button:pressed,
+QToolBar#model_acts_tb > QToolButton:pressed,
+QToolBar#tools_acts_tb > QToolButton:pressed,
+ModelNavigationWidget > QToolButton:pressed,
+QWidget#bnts_parent_wgt > QToolButton:pressed,
+QMenuBar::item:pressed {
+ color: #f0f0f0;
+ background-color: qlineargradient(x1: 0, y1: 0, x2: 1, y2: 1, stop: 0 #39a4d9, stop: 1 #2f88b1);
+}
+
+WelcomeWidget > QToolButton {
+ color: #101010;
+}
+
+WelcomeWidget > QToolButton:disabled {
+ color: #505050;
+}
+
+WelcomeWidget > QToolButton:hover {
+ background-color: qlineargradient(x1: 0, y1: 0, x2: 1, y2: 1, stop: 0 #43c0ff, stop: 1 #39a4d9);
+}
+
+WelcomeWidget > QToolButton:pressed {
+ color: #c0c0c0;
+ background-color: qlineargradient(x1: 0, y1: 0, x2: 1, y2: 1, stop: 0 #39a4d9, stop: 1 #2f88b1);
+}
+
+QCheckBox::indicator,
+QListWidget::indicator,
+QTableWidget::indicator {
+ width: 13px;
+ height: 13px;
+ border: 1px solid palette(mid);
+ background-color: palette(base);
+}
+
+QCheckBox::indicator:checked,
+QListWidget::indicator:checked,
+QTableWidget::indicator:checked {
+ image: url(":/images/images/checkmark_black.png");
+}
+
+QCheckBox::indicator:pressed,
+QListWidget::indicator:pressed,
+QTableWidget::indicator:pressed {
+ background-color: palette(button);
+}
+
+ChangelogWidget > QFrame > QGroupBox > QFrame#separator_ln {
+ border: 1px solid palette(mid);
+}
+
+RelationshipConfigWidget QLabel#crows_foot_lbl {
+ qproperty-pixmap: url(":/images/images/rel_crows_foot_light.png");
+}
+
+RelationshipConfigWidget QLabel#conn_tab_edges_lbl {
+ qproperty-pixmap: url(":/images/images/rel_tab_edges_light.png");
+}
+
+RelationshipConfigWidget QLabel#conn_fk_pk_lbl {
+ qproperty-pixmap: url(":/images/images/rel_fk_to_pk_light.png");
+}
+
+RelationshipConfigWidget QLabel#conn_cnt_pnts_lbl {
+ qproperty-pixmap: url(":/images/images/rel_center_pnts_light.png");
+}
+
+ObjectRenameWidget QLabel#handle_lbl,
+LayersWidget QLabel#handle_lbl {
+ image: url(':/images/images/handle_light.png');
+}
+
+QSplitter::handle:horizontal {
+ image: url(':/images/images/hsplitter_handle_light.png');
+ width: 4px;
+ margin: 1px;
+}
+
+QSplitter::handle:vertical {
+ image: url(':/images/images/vsplitter_handle_light.png');
+ height: 4px;
+ margin: 1px;
+}
+
+SceneInfoWidget > QFrame {
+ background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #c3c4c5 stop: 0.001 #e4e5e6, stop: 1 #e4e5e6);
+ border-radius: 4px;
+ border: 1px solid palette(mid);
+}
+
+SceneInfoWidget > QFrame > QFrame#separator_ln,
+SceneInfoWidget > QFrame > QFrame#separator_ln2 {
+ border: 1px solid palette(mid);
+}
diff --git a/assets/conf/themes/inksaver/pattern-highlight.conf b/assets/conf/themes/inksaver/pattern-highlight.conf
new file mode 100644
index 0000000000..f62069032d
--- /dev/null
+++ b/assets/conf/themes/inksaver/pattern-highlight.conf
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/assets/conf/themes/inksaver/sch-highlight.conf b/assets/conf/themes/inksaver/sch-highlight.conf
new file mode 100644
index 0000000000..242ec98ad5
--- /dev/null
+++ b/assets/conf/themes/inksaver/sch-highlight.conf
@@ -0,0 +1,94 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/assets/conf/themes/inksaver/sql-highlight.conf b/assets/conf/themes/inksaver/sql-highlight.conf
new file mode 100644
index 0000000000..8978c80e1c
--- /dev/null
+++ b/assets/conf/themes/inksaver/sql-highlight.conf
@@ -0,0 +1,695 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/assets/conf/themes/inksaver/xml-highlight.conf b/assets/conf/themes/inksaver/xml-highlight.conf
new file mode 100644
index 0000000000..0c936a5368
--- /dev/null
+++ b/assets/conf/themes/inksaver/xml-highlight.conf
@@ -0,0 +1,49 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/assets/conf/themes/light/appearance.conf b/assets/conf/themes/light/appearance.conf
new file mode 100644
index 0000000000..458a9162b7
--- /dev/null
+++ b/assets/conf/themes/light/appearance.conf
@@ -0,0 +1,82 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/assets/conf/themes/light/extra-ui-style.conf b/assets/conf/themes/light/extra-ui-style.conf
new file mode 100644
index 0000000000..a8be1233c8
--- /dev/null
+++ b/assets/conf/themes/light/extra-ui-style.conf
@@ -0,0 +1,165 @@
+QWidget#bg_widget {
+ background-color: #d7d8d9;
+}
+
+QWidget#bg_widget > QStackedWidget {
+ border-top: 1px solid #9fa0a1;
+ border-left: 1px solid #9fa0a1;
+}
+
+QWidget#menu_title_wgt {
+ background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #ffffff , stop: 1 #E6E6E6);
+ border-color: #c0a0a0a0;
+}
+
+QWidget#bnts_parent_wgt {
+ background-color: #eff0f1;
+ border-color: #9fa0a1;
+}
+
+QWidget#bnts_parent_wgt > QFrame {
+ border-top: 1px solid #9fa0a1;
+}
+
+QMenuBar {
+ background-color: #eff0f1;
+}
+
+QMenuBar::item {
+ color: #303030;
+}
+
+QMenuBar::item:disabled {
+ color: #505050;
+}
+
+QMenu::item:disabled {
+ color: #505050;
+}
+
+QToolBar {
+ background-color: #eff0f1;
+}
+
+QToolBar::separator {
+ background-color: #9fa0a1;
+}
+
+QWidget#bnts_parent_wgt > QToolButton,
+QToolBar#tools_acts_tb > QToolButton {
+ color: #101010;
+}
+
+QWidget#bnts_parent_wgt > QToolButton:disabled,
+QToolBar#tools_acts_tb > QToolButton:disabled {
+ color: #505050;
+}
+
+QToolBar > QToolButton#qt_toolbar_ext_button,
+QToolBar#tools_acts_tb > QToolButton:hover,
+QToolBar#tools_acts_tb > QToolButton:checked,
+QToolBar#model_acts_tb > QToolButton:hover,
+QToolBar#model_acts_tb > QToolButton:checked,
+ModelNavigationWidget > QToolButton:hover,
+QWidget#bnts_parent_wgt > QToolButton:hover,
+QWidget#bnts_parent_wgt > QToolButton:checked,
+QMenuBar::item:selected {
+ color: #101010;
+ background-color: qlineargradient(x1: 0, y1: 0, x2: 1, y2: 1, stop: 0 #43c0ff, stop: 1 #39a4d9);
+}
+
+QToolBar > QToolButton#qt_toolbar_ext_button:pressed,
+QToolBar#model_acts_tb > QToolButton:pressed,
+QToolBar#tools_acts_tb > QToolButton:pressed,
+ModelNavigationWidget > QToolButton:pressed,
+QWidget#bnts_parent_wgt > QToolButton:pressed,
+QMenuBar::item:pressed {
+ color: #f0f0f0;
+ background-color: qlineargradient(x1: 0, y1: 0, x2: 1, y2: 1, stop: 0 #39a4d9, stop: 1 #2f88b1);
+}
+
+WelcomeWidget > QToolButton {
+ color: #101010;
+}
+
+WelcomeWidget > QToolButton:disabled {
+ color: #505050;
+}
+
+WelcomeWidget > QToolButton:hover {
+ background-color: qlineargradient(x1: 0, y1: 0, x2: 1, y2: 1, stop: 0 #43c0ff, stop: 1 #39a4d9);
+}
+
+WelcomeWidget > QToolButton:pressed {
+ color: #c0c0c0;
+ background-color: qlineargradient(x1: 0, y1: 0, x2: 1, y2: 1, stop: 0 #39a4d9, stop: 1 #2f88b1);
+}
+
+QCheckBox::indicator,
+QListWidget::indicator,
+QTableWidget::indicator {
+ width: 13px;
+ height: 13px;
+ border: 1px solid palette(mid);
+ background-color: palette(base);
+}
+
+QCheckBox::indicator:checked,
+QListWidget::indicator:checked,
+QTableWidget::indicator:checked {
+ image: url(":/images/images/checkmark_black.png");
+}
+
+QCheckBox::indicator:pressed,
+QListWidget::indicator:pressed,
+QTableWidget::indicator:pressed {
+ background-color: palette(button);
+}
+
+ChangelogWidget > QFrame > QGroupBox > QFrame#separator_ln {
+ border: 1px solid palette(mid);
+}
+
+RelationshipConfigWidget QLabel#crows_foot_lbl {
+ qproperty-pixmap: url(":/images/images/rel_crows_foot_light.png");
+}
+
+RelationshipConfigWidget QLabel#conn_tab_edges_lbl {
+ qproperty-pixmap: url(":/images/images/rel_tab_edges_light.png");
+}
+
+RelationshipConfigWidget QLabel#conn_fk_pk_lbl {
+ qproperty-pixmap: url(":/images/images/rel_fk_to_pk_light.png");
+}
+
+RelationshipConfigWidget QLabel#conn_cnt_pnts_lbl {
+ qproperty-pixmap: url(":/images/images/rel_center_pnts_light.png");
+}
+
+ObjectRenameWidget QLabel#handle_lbl,
+LayersWidget QLabel#handle_lbl {
+ image: url(':/images/images/handle_light.png');
+}
+
+QSplitter::handle:horizontal {
+ image: url(':/images/images/hsplitter_handle_light.png');
+ width: 4px;
+ margin: 1px;
+}
+
+QSplitter::handle:vertical {
+ image: url(':/images/images/vsplitter_handle_light.png');
+ height: 4px;
+ margin: 1px;
+}
+
+SceneInfoWidget > QFrame {
+ background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #c3c4c5 stop: 0.001 #e4e5e6, stop: 1 #e4e5e6);
+ border-radius: 4px;
+ border: 1px solid palette(mid);
+}
+
+SceneInfoWidget > QFrame > QFrame#separator_ln,
+SceneInfoWidget > QFrame > QFrame#separator_ln2 {
+ border: 1px solid palette(mid);
+}
diff --git a/assets/conf/themes/light/pattern-highlight.conf b/assets/conf/themes/light/pattern-highlight.conf
new file mode 100644
index 0000000000..f62069032d
--- /dev/null
+++ b/assets/conf/themes/light/pattern-highlight.conf
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/assets/conf/themes/light/sch-highlight.conf b/assets/conf/themes/light/sch-highlight.conf
new file mode 100644
index 0000000000..34c6f73582
--- /dev/null
+++ b/assets/conf/themes/light/sch-highlight.conf
@@ -0,0 +1,94 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/assets/conf/themes/light/sql-highlight.conf b/assets/conf/themes/light/sql-highlight.conf
new file mode 100644
index 0000000000..7232c81a09
--- /dev/null
+++ b/assets/conf/themes/light/sql-highlight.conf
@@ -0,0 +1,695 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/assets/conf/themes/light/xml-highlight.conf b/assets/conf/themes/light/xml-highlight.conf
new file mode 100644
index 0000000000..0c936a5368
--- /dev/null
+++ b/assets/conf/themes/light/xml-highlight.conf
@@ -0,0 +1,49 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/assets/conf/ui-style.conf b/assets/conf/ui-style.conf
new file mode 100644
index 0000000000..a4eae5880b
--- /dev/null
+++ b/assets/conf/ui-style.conf
@@ -0,0 +1,375 @@
+/*
+ * QWidget
+ */
+QWidget#bg_widget {
+ background-color: #30353a;
+}
+
+QWidget#bg_widget > QStackedWidget {
+ border-top: 1px solid #303030;
+ border-left: 1px solid #303030;
+}
+
+QWidget#menu_title_wgt {
+ background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #ffffff , stop: 1 #E6E6E6);
+ border: 1px solid #c0a0a0a0;
+}
+
+/* DataManipulationForm styles */
+QWidget#bnts_parent_wgt {
+ background-color: #41454a;
+ border: 1px solid #2b2e32;
+ padding: 2px;
+}
+
+QWidget#bnts_parent_wgt > QToolButton {
+ border: none;
+ margin-bottom: 4px;
+ margin-left: 4px;
+ margin-right: 4px;
+ padding: 2px;
+}
+
+QWidget#bnts_parent_wgt > QToolButton::checked,
+QWidget#bnts_parent_wgt > QToolButton::hover {
+ padding: 3px;
+}
+
+QWidget#bnts_parent_wgt > QFrame {
+ border-top: 1px solid #303030;
+}
+
+/*
+ * QMenuBar
+ */
+QMenuBar {
+ background-color: #41454a;
+ padding: 4px;
+}
+
+QMenuBar::item {
+ border: transparent;
+ color: #fff;
+ padding-left: 3px;
+ padding-right: 3px;
+ padding-top: 2px;
+ padding-bottom: 2px;
+}
+
+QMenuBar::item:disabled {
+ color: #909090;
+}
+
+QMenu::item:disabled {
+ color: #909090;
+}
+
+/*
+ * QToolBar
+ */
+QToolBar {
+ background-color: #41454a;
+ border: transparent;
+}
+
+QToolBar::separator {
+ background-color: #23272a;
+}
+
+QWidget#bnts_parent_wgt > QToolButton,
+QToolBar#tools_acts_tb > QToolButton {
+ color: #f0f0f0;
+ margin-bottom: 3px;
+ margin-left: 3px;
+ margin-right: 3px;
+ border: none;
+ border-radius: 6px;
+ padding: 3px;
+}
+
+QWidget#bnts_parent_wgt > QToolButton:disabled,
+QToolBar#tools_acts_tb > QToolButton:disabled {
+ color: #808080;
+}
+
+QWidget#bnts_parent_wgt > QToolButton::menu-indicator,
+QToolBar#tools_acts_tb > QToolButton::menu-indicator {
+ image: url(":/icons/icons/h_menu_indicator.png");
+ subcontrol-position: right center;
+ max-width: 22px;
+ max-height: 22px;
+}
+
+QToolBar#model_acts_tb > QToolButton::menu-indicator {
+ border: transparent;
+}
+
+QToolBar#tools_acts_tb::separator {
+ height: 1px;
+ margin-top: 2px;
+ margin-bottom: 2px;
+}
+
+QToolBar#model_acts_tb::separator {
+ width: 1px;
+ margin-left: 2px;
+ margin-right: 2px;
+}
+
+QToolBar#model_acts_tb > QToolButton,
+ModelNavigationWidget > QToolButton {
+ padding: 3px;
+ margin-top: 2px;
+ margin-bottom: 2px;
+ border: none;
+ border-radius: 8px;
+}
+
+QToolBar#model_acts_tb > QToolButton {
+ margin-left: 3px;
+ margin-right: 3px;
+}
+
+/* Blue tool button */
+QToolBar > QToolButton#qt_toolbar_ext_button,
+QToolBar#tools_acts_tb > QToolButton:hover,
+QToolBar#tools_acts_tb > QToolButton:checked,
+QToolBar#model_acts_tb > QToolButton:hover,
+QToolBar#model_acts_tb > QToolButton:checked,
+ModelNavigationWidget > QToolButton:hover,
+QWidget#bnts_parent_wgt > QToolButton:hover,
+QWidget#bnts_parent_wgt > QToolButton:checked,
+QMenuBar::item:selected {
+ color: #fff;
+ background-color: qlineargradient(x1: 0, y1: 0, x2: 1, y2: 1, stop: 0 #2a79a1, stop: 1 #2f87b3);
+}
+
+/* Dark blue tool button */
+QToolBar > QToolButton#qt_toolbar_ext_button:pressed,
+QToolBar#model_acts_tb > QToolButton:pressed,
+QToolBar#tools_acts_tb > QToolButton:pressed,
+ModelNavigationWidget > QToolButton:pressed,
+QWidget#bnts_parent_wgt > QToolButton:pressed,
+QMenuBar::item:pressed {
+ color: #c0c0c0;
+ background-color: qlineargradient(x1: 0, y1: 0, x2: 1, y2: 1, stop: 0 #184e6f, stop: 1 #216996);
+}
+
+QToolBar > QToolButton#qt_toolbar_ext_button,
+QToolBar > QToolButton#qt_toolbar_ext_button:hover,
+QToolBar > QToolButton#qt_toolbar_ext_button:pressed {
+ border-radius: 0;
+}
+
+/*
+ * QToolButton
+ */
+QToolButton[toolButtonStyle="0"],
+QToolButton[toolButtonStyle="2"] {
+ padding: 3px;
+}
+
+/*
+ * QToolTip
+ */
+QToolTip {
+ color: #000;
+ background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #e6e6e6, stop: 1 #f0f0f0);
+ border: 1px solid #c0a0a0a0;
+ padding: 1px;
+}
+
+/*
+ * QTabWidget
+ */
+QTabWidget#models_tbw::pane {
+ border: transparent;
+ margin: 0;
+ padding: 0;
+}
+
+QTabWidget#sql_exec_tbw > QTabBar {
+ qproperty-iconSize: 16px 16px;
+}
+
+QTabBar::close-button,
+QTabBar::close-button {
+ margin-left: 5px;
+ margin-right: 0px;
+ subcontrol-position: right;
+ image: url(':/icons/icons/close1.png');
+}
+
+QTabBar::close-button:hover,
+QTabBar::close-button:hover {
+ image: url(':/icons/icons/close2.png');
+}
+
+QTabBar::close-button:pressed,
+SQTabBar::close-button:pressed {
+ image: url(':/icons/icons/close2.png');
+}
+
+/** pgModeler custom widgets **/
+
+/*
+ * ChangelogWidget
+ * */
+ChangelogWidget > QFrame > QGroupBox > QFrame#separator_ln {
+ border: 1px solid palette(mid);
+}
+
+/*
+ * CodeCompletionWidget
+ */
+CodeCompletionWidget > QWidget {
+ background-color: palette(button);
+ border: 1px solid palette(mid);
+}
+/*
+ * NewObjectOverlayWidget
+ */
+AboutWidget > QFrame,
+DonateWidget > QFrame,
+LayersConfigWidget > QFrame,
+ChangelogWidget > QFrame,
+UpdateNotifierWidget > QFrame,
+NewObjectOverlayWidget > QFrame,
+TaskProgressWidget > QFrame,
+ObjectRenameWidget > QFrame,
+LayersWidget > QFrame {
+ background-color: palette(button);
+ border: 1px solid palette(mid);
+ border-radius: 6px
+}
+
+NewObjectOverlayWidget > QFrame > QGroupBox {
+ font-weight: bold;
+ font-style: italic;
+}
+
+NewObjectOverlayWidget > QFrame > QGroupBox > QWidget > QToolButton {
+ font-style: italic;
+ border-radius: 6px;
+ min-width: 110px;
+ padding-top: 3px;
+ padding-bottom: 3px;
+}
+
+NewObjectOverlayWidget > QFrame > QGroupBox > QWidget > QToolButton:hover {
+ font-weight: bold;
+ background-color: palette(highlight);
+}
+
+NewObjectOverlayWidget > QFrame > QGroupBox > QWidget > QToolButton:pressed {
+ background-color: #800362d6;
+ border: 1px solid #02408d;
+ color: #fff;
+}
+
+
+WelcomeWidget > QToolButton {
+ background-color: transparent;
+ color: #fff;
+ padding: 3px;
+ border: none;
+ border-radius: 6px;
+}
+
+WelcomeWidget > QToolButton::menu-indicator {
+ border: transparent;
+}
+
+WelcomeWidget > QToolButton:disabled {
+ color: #606060;
+}
+
+WelcomeWidget > QToolButton:hover {
+ background-color: qlineargradient(x1: 0, y1: 0, x2: 1, y2: 1, stop: 0 #2a79a1, stop: 1 #2f87b3);
+}
+
+WelcomeWidget > QToolButton:pressed {
+ color: #c0c0c0;
+ background-color: qlineargradient(x1: 0, y1: 0, x2: 1, y2: 1, stop: 0 #184e6f, stop: 1 #216996);
+}
+
+QLineEdit > QToolButton {
+ qproperty-icon: url(":icons/icons/clearinput.png");
+}
+
+QLineEdit > QToolButton#password_show_btn {
+ qproperty-icon: url(":icons/icons/hidepwd.png");
+}
+
+RelationshipConfigWidget QLabel#crows_foot_lbl,
+RelationshipConfigWidget QLabel#conn_tab_edges_lbl,
+RelationshipConfigWidget QLabel#conn_fk_pk_lbl,
+RelationshipConfigWidget QLabel#conn_cnt_pnts_lbl {
+ min-height: 135px;
+ max-height: 135px;
+ min-width: 580px;
+ max-width: 580px;
+}
+
+QToolBar > QToolButton#qt_toolbar_ext_button {
+ qproperty-icon: none;
+}
+
+QCheckBox::indicator,
+QListWidget::indicator,
+QTableWidget::indicator {
+ width: 13px;
+ height: 13px;
+ border: 1px solid palette(mid);
+ background-color: palette(base);
+}
+
+QCheckBox::indicator:checked,
+QListWidget::indicator:checked,
+QTableWidget::indicator:checked {
+ image: url(":/images/images/checkmark_white.png");
+}
+
+QCheckBox::indicator:checked:disabled,
+QListWidget::indicator:checked:disabled,
+QTableWidget::indicator:checked:disabled {
+ image: url(":/images/images/checkmark_disabled.png");
+}
+
+QCheckBox::indicator:pressed,
+QListWidget::indicator:pressed,
+QTableWidget::indicator:pressed {
+ background-color: palette(button);
+}
+
+QSplitter::handle:horizontal {
+ image: url(':/images/images/hsplitter_handle_dark.png');
+ width: 4px;
+ margin: 1px;
+}
+
+QSplitter::handle:vertical {
+ image: url(':/images/images/vsplitter_handle_dark.png');
+ height: 4px;
+ margin: 1px;
+}
+
+SceneInfoWidget > QFrame {
+ background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 palette(base) stop: 0.01 palette(mid), stop: 1 palette(mid));
+ border-radius: 4px;
+ border: 1px solid palette(midlight);
+}
+
+SceneInfoWidget > QFrame > QFrame#separator_ln,
+SceneInfoWidget > QFrame > QFrame#separator_ln2 {
+ border: 1px solid palette(midlight);
+}
+
+DataGridWidget QGroupBox#tab_info_gb {
+ padding-bottom: 1px;
+ padding-top: 1px;
+}
+
+DataGridWidget > QGroupBox#tab_info_gb > QFrame#separator_ln {
+ border: 1px solid palette(dark);
+}
diff --git a/samples/3dcitydb.dbm b/assets/samples/3dcitydb.dbm
similarity index 84%
rename from samples/3dcitydb.dbm
rename to assets/samples/3dcitydb.dbm
index cd1053b81f..90932ff022 100644
--- a/samples/3dcitydb.dbm
+++ b/assets/samples/3dcitydb.dbm
@@ -1,21 +1,34 @@
-
-
+
+
+
+
+
+
+
+
+
+
@@ -23,6 +36,8 @@ CAUTION: Do not modify this file unless you know what you are doing.
+
+
@@ -30,6 +45,8 @@ CAUTION: Do not modify this file unless you know what you are doing.
+
+
@@ -37,6 +54,8 @@ CAUTION: Do not modify this file unless you know what you are doing.
+
+
@@ -44,6 +63,8 @@ CAUTION: Do not modify this file unless you know what you are doing.
+
+
@@ -51,6 +72,8 @@ CAUTION: Do not modify this file unless you know what you are doing.
+
+
@@ -58,6 +81,8 @@ CAUTION: Do not modify this file unless you know what you are doing.
+
+
@@ -65,6 +90,8 @@ CAUTION: Do not modify this file unless you know what you are doing.
+
+
@@ -72,6 +99,8 @@ CAUTION: Do not modify this file unless you know what you are doing.
+
+
@@ -79,6 +108,8 @@ CAUTION: Do not modify this file unless you know what you are doing.
+
+
@@ -86,6 +117,8 @@ CAUTION: Do not modify this file unless you know what you are doing.
+
+
@@ -93,6 +126,8 @@ CAUTION: Do not modify this file unless you know what you are doing.
+
+
@@ -100,6 +135,8 @@ CAUTION: Do not modify this file unless you know what you are doing.
+
+
@@ -107,33 +144,23 @@ CAUTION: Do not modify this file unless you know what you are doing.
+
+
-
-
-
-
-
-
-
+
-
+
-
+
-
+
@@ -148,14 +175,11 @@ CAUTION: Do not modify this file unless you know what you are doing.
-
+
-
+
@@ -170,17 +194,14 @@ CAUTION: Do not modify this file unless you know what you are doing.
-
+
-
+
-
+
@@ -216,10 +237,10 @@ CAUTION: Do not modify this file unless you know what you are doing.
-
+
-
+
@@ -234,10 +255,10 @@ CAUTION: Do not modify this file unless you know what you are doing.
-
+
-
+
@@ -249,10 +270,10 @@ CAUTION: Do not modify this file unless you know what you are doing.
-
+
-
+
@@ -267,14 +288,11 @@ CAUTION: Do not modify this file unless you know what you are doing.
-
+
-
+
@@ -376,17 +394,14 @@ CAUTION: Do not modify this file unless you know what you are doing.
-
+
-
+
-
+
@@ -503,14 +518,11 @@ CAUTION: Do not modify this file unless you know what you are doing.
-
+
-
+
@@ -525,10 +537,10 @@ CAUTION: Do not modify this file unless you know what you are doing.
-
+
-
+
@@ -648,7 +660,7 @@ CAUTION: Do not modify this file unless you know what you are doing.
-
+
@@ -696,10 +708,10 @@ CAUTION: Do not modify this file unless you know what you are doing.
-
+
-
+
@@ -780,10 +792,10 @@ CAUTION: Do not modify this file unless you know what you are doing.
-
+
-
+
@@ -822,10 +834,10 @@ CAUTION: Do not modify this file unless you know what you are doing.
-
+
-
+
@@ -837,7 +849,7 @@ CAUTION: Do not modify this file unless you know what you are doing.
-
+
@@ -876,10 +888,10 @@ CAUTION: Do not modify this file unless you know what you are doing.
-
+
-
+
@@ -909,21 +921,15 @@ CAUTION: Do not modify this file unless you know what you are doing.
-
+
-
+
-
+
@@ -947,7 +953,7 @@ CAUTION: Do not modify this file unless you know what you are doing.
-
+
@@ -962,7 +968,7 @@ CAUTION: Do not modify this file unless you know what you are doing.
-
+
@@ -980,7 +986,7 @@ CAUTION: Do not modify this file unless you know what you are doing.
-
+
@@ -995,10 +1001,10 @@ CAUTION: Do not modify this file unless you know what you are doing.
-
+
-
+
@@ -1015,14 +1021,14 @@ CAUTION: Do not modify this file unless you know what you are doing.
- = (0)::numeric) AND (lod < (5)::numeric))]]>
+ = (0)::numeric) AND (lod < (5)::numeric))]]>
-
+
-
+
@@ -1034,7 +1040,7 @@ CAUTION: Do not modify this file unless you know what you are doing.
-
+
@@ -1048,11 +1054,11 @@ CAUTION: Do not modify this file unless you know what you are doing.
- = (0)::numeric) AND (lod < (5)::numeric))]]>
+ = (0)::numeric) AND (lod < (5)::numeric))]]>
-
+
@@ -1082,10 +1088,10 @@ CAUTION: Do not modify this file unless you know what you are doing.
-
+
-
+
@@ -1130,7 +1136,7 @@ CAUTION: Do not modify this file unless you know what you are doing.
-
+
@@ -1181,10 +1187,10 @@ CAUTION: Do not modify this file unless you know what you are doing.
-
+
-
+
@@ -1226,10 +1232,10 @@ CAUTION: Do not modify this file unless you know what you are doing.
-
+
-
+
@@ -1286,10 +1292,10 @@ CAUTION: Do not modify this file unless you know what you are doing.
-
+
-
+
@@ -1400,7 +1406,7 @@ CAUTION: Do not modify this file unless you know what you are doing.
-
+
@@ -1454,10 +1460,10 @@ CAUTION: Do not modify this file unless you know what you are doing.
-
+
-
+
@@ -1469,10 +1475,10 @@ CAUTION: Do not modify this file unless you know what you are doing.
-
+
-
+
@@ -1499,7 +1505,7 @@ CAUTION: Do not modify this file unless you know what you are doing.
-
+
@@ -1517,7 +1523,7 @@ CAUTION: Do not modify this file unless you know what you are doing.
-
+
@@ -1604,10 +1610,10 @@ CAUTION: Do not modify this file unless you know what you are doing.
-
+
-
+
@@ -1619,10 +1625,10 @@ CAUTION: Do not modify this file unless you know what you are doing.
-
+
-
+
@@ -1658,10 +1664,10 @@ CAUTION: Do not modify this file unless you know what you are doing.
-
+
-
+
@@ -1691,14 +1697,11 @@ CAUTION: Do not modify this file unless you know what you are doing.
-
+
-
+
@@ -1737,10 +1740,10 @@ CAUTION: Do not modify this file unless you know what you are doing.
-
+
-
+
@@ -1821,10 +1824,10 @@ CAUTION: Do not modify this file unless you know what you are doing.
-
+
-
+
@@ -1869,10 +1872,10 @@ CAUTION: Do not modify this file unless you know what you are doing.
-
+
-
+
@@ -1959,10 +1962,10 @@ CAUTION: Do not modify this file unless you know what you are doing.
-
+
-
+
@@ -2007,10 +2010,10 @@ CAUTION: Do not modify this file unless you know what you are doing.
-
+
-
+
@@ -2091,10 +2094,10 @@ CAUTION: Do not modify this file unless you know what you are doing.
-
+
-
+
@@ -2133,10 +2136,10 @@ CAUTION: Do not modify this file unless you know what you are doing.
-
+
-
+
@@ -2148,10 +2151,10 @@ CAUTION: Do not modify this file unless you know what you are doing.
-
+
-
+
@@ -2187,10 +2190,10 @@ CAUTION: Do not modify this file unless you know what you are doing.
-
+
-
+
@@ -2223,7 +2226,7 @@ CAUTION: Do not modify this file unless you know what you are doing.
-
+
@@ -2328,7 +2331,7 @@ CAUTION: Do not modify this file unless you know what you are doing.
-
+
@@ -2343,17 +2346,14 @@ CAUTION: Do not modify this file unless you know what you are doing.
-
+
-
+
-
+
@@ -2410,7 +2410,7 @@ CAUTION: Do not modify this file unless you know what you are doing.
-
+
@@ -2446,7 +2446,7 @@ CAUTION: Do not modify this file unless you know what you are doing.
-
+
@@ -2473,10 +2473,10 @@ CAUTION: Do not modify this file unless you know what you are doing.
-
+
-
+
@@ -2524,7 +2524,7 @@ CAUTION: Do not modify this file unless you know what you are doing.
-
+
@@ -2569,7 +2569,7 @@ CAUTION: Do not modify this file unless you know what you are doing.
-
+
@@ -2644,7 +2644,7 @@ CAUTION: Do not modify this file unless you know what you are doing.
-
+
@@ -2692,10 +2692,10 @@ CAUTION: Do not modify this file unless you know what you are doing.
-
+
-
+
@@ -2749,7 +2749,7 @@ CAUTION: Do not modify this file unless you know what you are doing.
-
+
@@ -2773,7 +2773,7 @@ CAUTION: Do not modify this file unless you know what you are doing.
-
+
@@ -2797,7 +2797,7 @@ CAUTION: Do not modify this file unless you know what you are doing.
-
+
@@ -5615,7 +5615,7 @@ CAUTION: Do not modify this file unless you know what you are doing.
concurrent="false" unique="false" fast-update="false" buffering="false"
index-type="gist" factor="0">
-
+
@@ -5654,17 +5654,14 @@ CAUTION: Do not modify this file unless you know what you are doing.
-
-
-
+
+
+Created by: Felix Kunde]]>
-
-
-
-
-
-
-
-
-
-
-
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
-
-
-
-
-
-
-
+
+
+
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/assets/samples/cryptoconcept.dbm b/assets/samples/cryptoconcept.dbm
new file mode 100644
index 0000000000..8dd96edb08
--- /dev/null
+++ b/assets/samples/cryptoconcept.dbm
@@ -0,0 +1,1207 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/assets/samples/demo.dbm b/assets/samples/demo.dbm
new file mode 100644
index 0000000000..fdcb90f522
--- /dev/null
+++ b/assets/samples/demo.dbm
@@ -0,0 +1,393 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/assets/samples/northwind.dbm b/assets/samples/northwind.dbm
new file mode 100644
index 0000000000..4130912d91
--- /dev/null
+++ b/assets/samples/northwind.dbm
@@ -0,0 +1,595 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/assets/samples/pagila.dbm b/assets/samples/pagila.dbm
new file mode 100644
index 0000000000..4dfad6ce24
--- /dev/null
+++ b/assets/samples/pagila.dbm
@@ -0,0 +1,8635 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ = 1901) AND (VALUE <= 2155))]]>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ (film.rental_duration * '1 day'::interval),
+ ((rental.return_date - rental.rental_date) - (film.rental_duration * '1 day'::interval)),0)),0) INTO v_overfees
+ FROM rental, inventory, film
+ WHERE film.film_id = inventory.film_id
+ AND inventory.inventory_id = rental.inventory_id
+ AND rental.rental_date <= p_effective_date
+ AND rental.customer_id = p_customer_id;
+
+ SELECT COALESCE(SUM(payment.amount),0) INTO v_payments
+ FROM payment
+ WHERE payment.payment_date <= p_effective_date
+ AND payment.customer_id = p_customer_id;
+
+ RETURN v_rentfees + v_overfees - v_payments;
+END]]>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 0 THEN
+ RETURN FALSE;
+ ELSE
+ RETURN TRUE;
+ END IF;
+END ]]>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 0';
+ END IF;
+ IF min_dollar_amount_purchased = 0.00 THEN
+ RAISE EXCEPTION 'Minimum monthly dollar amount purchased parameter must be > $0.00';
+ END IF;
+
+ last_month_start := CURRENT_DATE - '3 month'::interval;
+ last_month_start := to_date((extract(YEAR FROM last_month_start) || '-' || extract(MONTH FROM last_month_start) || '-01'),'YYYY-MM-DD');
+ last_month_end := LAST_DAY(last_month_start);
+
+ /*
+ Create a temporary storage area for Customer IDs.
+ */
+ CREATE TEMPORARY TABLE tmpCustomer (customer_id INTEGER NOT NULL PRIMARY KEY);
+
+ /*
+ Find all customers meeting the monthly purchase requirements
+ */
+
+ tmpSQL := 'INSERT INTO tmpCustomer (customer_id)
+ SELECT p.customer_id
+ FROM payment AS p
+ WHERE DATE(p.payment_date) BETWEEN '||quote_literal(last_month_start) ||' AND '|| quote_literal(last_month_end) || '
+ GROUP BY customer_id
+ HAVING SUM(p.amount) > '|| min_dollar_amount_purchased || '
+ AND COUNT(customer_id) > ' ||min_monthly_purchases ;
+
+ EXECUTE tmpSQL;
+
+ /*
+ Output ALL customer information of matching rewardees.
+ Customize output as needed.
+ */
+ FOR rr IN EXECUTE 'SELECT c.* FROM tmpCustomer AS t INNER JOIN customer AS c ON t.customer_id = c.customer_id' LOOP
+ RETURN NEXT rr;
+ END LOOP;
+
+ /* Clean up */
+ tmpSQL := 'DROP TABLE tmpCustomer';
+ EXECUTE tmpSQL;
+
+RETURN;
+END]]>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ = operator]]>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ = and related operators on scalar datatypes]]>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ = and related operators on scalar datatypes]]>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ operator]]>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ and related operators on scalar datatypes]]>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ and related operators on scalar datatypes]]>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ = operator]]>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ operator]]>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ = operator]]>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ operator]]>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ = operator]]>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ operator]]>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ = operator]]>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ operator]]>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ = operator]]>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ operator]]>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ = operator]]>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ operator]]>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ = operator]]>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ operator]]>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ = operator]]>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ operator]]>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ = operator]]>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ operator]]>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ = operator]]>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ operator]]>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ = operator]]>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ operator]]>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ = operator]]>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ operator]]>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ = operator]]>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ operator]]>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ = operator]]>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ operator]]>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ = operator]]>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ operator]]>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ = operator]]>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ operator]]>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ = operator]]>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ operator]]>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ = operator]]>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ operator]]>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ = operator]]>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ operator]]>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ = operator]]>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ operator]]>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ = operator]]>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ operator]]>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/samples/usda.dbm b/assets/samples/usda.dbm
similarity index 80%
rename from samples/usda.dbm
rename to assets/samples/usda.dbm
index 24a34a2931..df31657e03 100644
--- a/samples/usda.dbm
+++ b/assets/samples/usda.dbm
@@ -1,21 +1,26 @@
-
-
+
+
-
+
-
+
-
+
@@ -48,10 +53,10 @@ CAUTION: Do not modify this file unless you know what you are doing.
-
+
-
+
@@ -66,10 +71,10 @@ CAUTION: Do not modify this file unless you know what you are doing.
-
+
-
+
@@ -81,10 +86,10 @@ CAUTION: Do not modify this file unless you know what you are doing.
-
+
-
+
@@ -96,10 +101,10 @@ CAUTION: Do not modify this file unless you know what you are doing.
-
+
-
+
@@ -147,10 +152,10 @@ CAUTION: Do not modify this file unless you know what you are doing.
-
+
-
+
@@ -168,10 +173,10 @@ CAUTION: Do not modify this file unless you know what you are doing.
-
+
-
+
@@ -228,10 +233,10 @@ CAUTION: Do not modify this file unless you know what you are doing.
-
+
-
+
@@ -255,10 +260,10 @@ CAUTION: Do not modify this file unless you know what you are doing.
-
+
-
+
@@ -270,10 +275,10 @@ CAUTION: Do not modify this file unless you know what you are doing.
-
+
-
+
@@ -351,21 +356,17 @@ CAUTION: Do not modify this file unless you know what you are doing.
-
-
-
+
+
+USDA food composition data is in the public domain and there is no copyright. They would appreciate it if you would list them as the source of the data and when possible they would like to see the product which uses the data or be notified of its use.]]>
-
-
-
-
-
-
-
-
-
-
diff --git a/assets/schemas/alter/column.sch b/assets/schemas/alter/column.sch
new file mode 100644
index 0000000000..68524151eb
--- /dev/null
+++ b/assets/schemas/alter/column.sch
@@ -0,0 +1,103 @@
+# SQL definition for columns's attributes change
+# CAUTION: Do not modify this file unless you know what you are doing.
+# Code generation can be broken if incorrect changes are made.
+
+%if {has-changes} %then
+ %set {alter-table} [ALTER TABLE ] {table} [ ALTER COLUMN ] {name}
+ %set {ddl-end} [;] $br [-- ddl-end --] $br
+
+ %if ({identity-type} == "unset") %then
+ {alter-table} [ DROP IDENTITY]
+ {ddl-end}
+ %end
+
+ %if {type} %then
+ {alter-table}
+ [ TYPE ] {type}
+
+ %if {collation} %then
+ [ COLLATE ] {collation}
+ %end
+
+ {ddl-end}
+ %end
+
+ %if {default-value} %then
+ {alter-table}
+
+ %if ({default-value}=="unset") %then
+ [ DROP DEFAULT]
+ %else
+ [ SET DEFAULT ] {default-value}
+ %end
+
+ {ddl-end}
+ %end
+
+ %if {not-null} %then
+ {alter-table}
+
+ %if ({not-null}=="unset") %then
+ [ DROP ]
+ %else
+ [ SET ]
+ %end
+
+ [NOT NULL]
+
+ {ddl-end}
+ %end
+
+ %if {cur-identity-type} %and {min-value} %then
+ {alter-table}
+ [ SET GENERATED ] {cur-identity-type} [ SET MINVALUE ] {min-value}
+ {ddl-end}
+ %end
+
+ %if {cur-identity-type} %and {max-value} %then
+ {alter-table}
+ [ SET GENERATED ] {cur-identity-type} [ SET MAXVALUE ] {max-value}
+ {ddl-end}
+ %end
+
+ %if {cur-identity-type} %and {start} %then
+ {alter-table}
+ [ SET GENERATED ] {cur-identity-type} [ SET START WITH ] {start}
+ {ddl-end}
+ %end
+
+ %if {cur-identity-type} %and {cache} %then
+ {alter-table}
+ [ SET GENERATED ] {cur-identity-type} [ SET CACHE ] {cache}
+ {ddl-end}
+ %end
+
+ %if {cur-identity-type} %and {increment} %then
+ {alter-table}
+ [ SET GENERATED ] {cur-identity-type} [ SET INCREMENT ] {increment}
+ {ddl-end}
+ %end
+
+ %if {cur-identity-type} %and {cycle} %then
+ {alter-table}
+ [ SET GENERATED ] {cur-identity-type} [ SET]
+
+ %if ({cycle}=="false") %then [ NO] %end
+
+ [ CYCLE]
+
+ {ddl-end}
+ %end
+
+ %if {new-identity-type} %or {identity-type} %and ({identity-type} != "unset") %then
+ {alter-table}
+
+ %if {new-identity-type} %then
+ [ SET GENERATED ] {new-identity-type}
+ %else
+ [ ADD GENERATED ] {identity-type} [ AS IDENTITY]
+ %end
+
+ {ddl-end}
+ %end
+%end
diff --git a/assets/schemas/alter/confparam.sch b/assets/schemas/alter/confparam.sch
new file mode 100644
index 0000000000..77051bb609
--- /dev/null
+++ b/assets/schemas/alter/confparam.sch
@@ -0,0 +1,10 @@
+# SQL definition for functions/procedures configuration parameters modification
+# CAUTION: Do not modify this file unless you know what you are doing.
+# Code generation can be broken if incorrect changes are made.
+
+%if ({value} == "unset") %then
+ $br $tb [RESET ] {name}
+%else
+ $br $tb [SET ] {name} [ = ] {value}
+%end
+
diff --git a/assets/schemas/alter/database.sch b/assets/schemas/alter/database.sch
new file mode 100644
index 0000000000..d05ae3d5a0
--- /dev/null
+++ b/assets/schemas/alter/database.sch
@@ -0,0 +1,31 @@
+# SQL definition for database's attributes change
+# CAUTION: Do not modify this file unless you know what you are doing.
+# Code generation can be broken if incorrect changes are made.
+
+%set {ddl-end} [;] $br [-- ddl-end --] $br
+
+%if {connlimit} %then
+ [ALTER ] {sql-object} $sp {signature} [ WITH ]
+
+ %if {connlimit} %then
+ $br $tb [ CONNECTION LIMIT ] {connlimit}
+ %end
+
+ {ddl-end}
+%end
+
+
+%if {allow-conns} %or {is-template} %then
+
+ [ALTER ] {sql-object} $sp {signature} [ WITH ]
+
+ %if {allow-conns} %then
+ $br $tb [ ALLOW_CONNECTIONS ] {allow-conns}
+ %end
+
+ %if {is-template} %then
+ $br $tb [ IS_TEMPLATE ] {is-template}
+ %end
+
+ {ddl-end}
+%end
diff --git a/assets/schemas/alter/diff.sch b/assets/schemas/alter/diff.sch
new file mode 100644
index 0000000000..e534d68fdc
--- /dev/null
+++ b/assets/schemas/alter/diff.sch
@@ -0,0 +1,75 @@
+# Basic structure for the diff script file generated by diff process
+# CAUTION: Do not modify this file unless you know what you are doing.
+# Code generation can be broken if incorrect changes are made.
+
+%if {has-changes} %then
+ %set {ddl-end} $br [-- ddl-end --] $br
+
+ [-- ** Diff code generated with pgModeler (PostgreSQL Database Modeler)] $br
+ [-- ** pgModeler version: ] {pgmodeler-ver} $br
+ [-- ** Diff date: ] {date} $br
+ [-- ** Source model: ] {dbmodel} $br
+ [-- ** Database: ] {database} $br
+ [-- ** PostgreSQL version: ] {pgsql-ver} $br
+
+ $br
+ [-- ** ] $ob [ Diff summary ] $cb $br
+ [-- ** Dropped objects: ] {drop} $br
+ [-- ** Created objects: ] {create} $br
+ [-- ** Changed objects: ] {change} $br
+
+ %if {function} %then
+ $br
+ [SET check_function_bodies = false;]
+
+ {ddl-end}
+ %end
+
+ %if {search-path} %then
+ $br
+ [SET search_path=] {search-path} ;
+ {ddl-end}
+ %end
+
+ %if {unset-perms} %then
+ $br $br
+ [-- ** ] $ob [ Undone permissions ] $cb $br $br
+ {unset-perms}
+ %end
+
+ %if {drop-cmds} %then
+ $br $br
+ [-- ** ] $ob [ Dropped objects ] $cb $br $br
+ {drop-cmds}
+ %end
+
+ %if {create-cmds} %then
+ $br $br
+ [-- ** ] $ob [ Created objects ] $cb $br $br
+ {create-cmds}
+ %end
+
+ %if {alter-cmds} %then
+ $br $br
+ [-- ** ] $ob [ Changed objects ] $cb $br $br
+ {alter-cmds}
+ %end
+
+ %if {constr-defs} %then
+ $br $br
+ [-- ** ] $ob [ Created constraints ] $cb $br $br
+ {constr-defs}
+ %end
+
+ %if {fk-defs} %then
+ $br $br
+ [-- ** ] $ob [ Created foreign keys ] $cb $br $br
+ {fk-defs}
+ %end
+
+ %if {set-perms} %then
+ $br $br
+ [-- ** ] $ob [ Created permissions ] $cb $br $br
+ {set-perms}
+ %end
+%end
diff --git a/assets/schemas/alter/domain.sch b/assets/schemas/alter/domain.sch
new file mode 100644
index 0000000000..0a03a9408c
--- /dev/null
+++ b/assets/schemas/alter/domain.sch
@@ -0,0 +1,40 @@
+# SQL definition for domain's attributes change
+# CAUTION: Do not modify this file unless you know what you are doing.
+# Code generation can be broken if incorrect changes are made.
+
+%set {ddl-end} $br [-- ddl-end --] $br
+
+#Changing default value
+%if {default-value} %then
+ [ALTER ] {sql-object} $sp {signature}
+
+ %if ({default-value} == "unset") %then
+ [ DROP DEFAULT]
+ %else
+ [ SET DEFAULT ] {default-value}
+ %end
+
+ ;
+
+ {ddl-end}
+%end
+
+#Changing NOT NULL constraint
+%if {not-null} %then
+ [ALTER ] {sql-object} $sp {signature}
+
+ %if ({not-null} == "unset") %then
+ [ DROP ]
+ %else
+ [ SET ]
+ %end
+
+ [NOT NULL;]
+
+ {ddl-end}
+%end
+
+#Changing CHECK expression
+%if {constraints} %then
+ {constraints}
+%end
diff --git a/assets/schemas/alter/domconstraint.sch b/assets/schemas/alter/domconstraint.sch
new file mode 100644
index 0000000000..f878f69468
--- /dev/null
+++ b/assets/schemas/alter/domconstraint.sch
@@ -0,0 +1,23 @@
+# SQL definition for domain's constraints change
+# CAUTION: Do not modify this file unless you know what you are doing.
+# Code generation can be broken if incorrect changes are made.
+
+[ALTER ] {sql-object} $sp {signature}
+
+%if ({expression} == "unset") %then
+ [ DROP CONSTRAINT ]
+%else
+ [ ADD CONSTRAINT ]
+%end
+
+%if {name} %then
+ {name}
+%end
+
+%if ({expression} != "unset") %then
+ $sp CHECK $sp ({expression})
+%end
+
+;
+
+$br [-- ddl-end --] $br
diff --git a/assets/schemas/alter/extension.sch b/assets/schemas/alter/extension.sch
new file mode 100644
index 0000000000..3ddd4b9d77
--- /dev/null
+++ b/assets/schemas/alter/extension.sch
@@ -0,0 +1,10 @@
+# SQL definition for extension's attributes change
+# CAUTION: Do not modify this file unless you know what you are doing.
+# Code generation can be broken if incorrect changes are made.
+
+{alter-cmds}
+
+%if {new-version} %then
+ [ALTER ] {sql-object} $sp {signature} [ UPDATE TO ] '{new-version}'
+ $br [-- ddl-end --] $br
+%end
diff --git a/assets/schemas/alter/foreigndatawrapper.sch b/assets/schemas/alter/foreigndatawrapper.sch
new file mode 100644
index 0000000000..532a1e7746
--- /dev/null
+++ b/assets/schemas/alter/foreigndatawrapper.sch
@@ -0,0 +1,40 @@
+# SQL definition for function's attributes change
+# CAUTION: Do not modify this file unless you know what you are doing.
+# Code generation can be broken if incorrect changes are made.
+
+{alter-cmds}
+
+%if {has-changes} %then
+ [ALTER ] {sql-object} $sp {signature}
+
+ %if {handler} %then
+ $br $tb
+
+ %if ({handler} == "unset") %then
+ [ NO HANDLER]
+ %else
+ [ HANDLER ] {handler}
+ %end
+ %end
+
+ %if {validator} %then
+ $br $tb
+
+ %if ({validator} == "unset") %then
+ [ NO VALIDATOR]
+ %else
+ [ VALIDATOR ] {validator}
+ %end
+ %end
+
+ %if {options} %then
+ $br $tb
+ [ OPTIONS (] {options} [)]
+ %end
+
+ ;
+
+ $br [-- ddl-end --] $br
+
+%end
+
diff --git a/assets/schemas/alter/foreignserver.sch b/assets/schemas/alter/foreignserver.sch
new file mode 100644
index 0000000000..75948e7cf7
--- /dev/null
+++ b/assets/schemas/alter/foreignserver.sch
@@ -0,0 +1,25 @@
+# SQL definition for foreign sever's attributes change
+# CAUTION: Do not modify this file unless you know what you are doing.
+# Code generation can be broken if incorrect changes are made.
+
+{alter-cmds}
+
+%if {has-changes} %then
+ [ALTER ] {sql-object} $sp {signature}
+
+ %if {version} %then
+ [ VERSION ] '{version}'
+
+ %end
+
+ %if {options} %then
+ $br $tb
+ [ OPTIONS (] {options} [)]
+ %end
+
+ ;
+
+ $br [-- ddl-end --] $br
+
+%end
+
diff --git a/assets/schemas/alter/foreigntable.sch b/assets/schemas/alter/foreigntable.sch
new file mode 100644
index 0000000000..7971ba81dd
--- /dev/null
+++ b/assets/schemas/alter/foreigntable.sch
@@ -0,0 +1,20 @@
+# SQL definition for foreign table's attributes change
+# CAUTION: Do not modify this file unless you know what you are doing.
+# Code generation can be broken if incorrect changes are made.
+
+{alter-cmds}
+
+%if {has-changes} %then
+ [ALTER ] {sql-object} $sp {signature}
+
+ %if {options} %then
+ $br $tb
+ [ OPTIONS (] {options} [)]
+ %end
+
+ ;
+
+ $br [-- ddl-end --] $br
+
+%end
+
diff --git a/assets/schemas/alter/function.sch b/assets/schemas/alter/function.sch
new file mode 100644
index 0000000000..8e9a3cfee7
--- /dev/null
+++ b/assets/schemas/alter/function.sch
@@ -0,0 +1,52 @@
+# SQL definition for function's attributes change
+# CAUTION: Do not modify this file unless you know what you are doing.
+# Code generation can be broken if incorrect changes are made.
+
+#%if {definition} %then
+# {definition}
+#%else
+
+ {alter-cmds}
+
+ %if {has-changes} %then
+ [ALTER ] {sql-object} $sp {signature}
+
+ %if {function-type} %then
+ $br $tb {function-type}
+ %end
+
+ %if {leakproof} %then
+ $br $tb
+ %if ({leakproof} == "unset") %then [ NOT ] %end
+ LEAKPROOF
+ %end
+
+ %if {behavior-type} %then
+ $br $tb {behavior-type}
+ %end
+
+ %if {security-type} %then
+ $br $tb {security-type}
+ %end
+
+ %if {parallel-type} %then
+ $br $tb {parallel-type}
+ %end
+
+ %if {execution-cost} %then
+ $br $tb [COST ] {execution-cost}
+ %end
+
+ %if {returns-setof} %and {row-amount} %then
+ $br $tb [ROWS ] {row-amount}
+ %end
+
+ %if {config-params} %then
+ {config-params}
+ %end
+
+ ;
+
+ $br [-- ddl-end --] $br
+ %end
+#%end
diff --git a/assets/schemas/alter/index.sch b/assets/schemas/alter/index.sch
new file mode 100644
index 0000000000..eeca1906c7
--- /dev/null
+++ b/assets/schemas/alter/index.sch
@@ -0,0 +1,31 @@
+# SQL definition for index's attributes change
+# CAUTION: Do not modify this file unless you know what you are doing.
+# Code generation can be broken if incorrect changes are made.
+
+{alter-cmds}
+
+%if {has-changes} %then
+ [ALTER ] {sql-object} $sp {signature}
+
+ $br [SET (]
+
+ %if {factor} %then
+ [FILLFACTOR = ] {factor}
+ %end
+
+ %if {fast-update} %then
+ %if {factor} %then [, ] %end
+ [FASTUPDATE = ] %if ({fast-update} == "unset") %then OFF %else ON %end
+ %end
+
+ %if {buffering} %then
+ %if {factor} %then [, ] %end
+ [BUFFERING = ] %if ({buffering} == "unset") %then OFF %else ON %end
+ %end
+
+ [)] ;
+
+ $br [-- ddl-end --] $br
+
+%end
+
diff --git a/assets/schemas/alter/owner.sch b/assets/schemas/alter/owner.sch
new file mode 100644
index 0000000000..04f25f10ce
--- /dev/null
+++ b/assets/schemas/alter/owner.sch
@@ -0,0 +1,14 @@
+# SQL definition for object's owner attribute change
+# CAUTION: Do not modify this file unless you know what you are doing.
+# Code generation can be broken if incorrect changes are made.
+
+[ALTER ]
+
+# Special condition for materialized views
+#%if {materialized} %then
+# [MATERIALIZED ]
+#%end
+
+{sql-object} $sp {signature} [ OWNER TO ] {owner};
+
+$br [-- ddl-end --] $br
diff --git a/assets/schemas/alter/permission.sch b/assets/schemas/alter/permission.sch
new file mode 100644
index 0000000000..0d92284211
--- /dev/null
+++ b/assets/schemas/alter/permission.sch
@@ -0,0 +1,18 @@
+# SQL definition for permissions change
+# CAUTION: Do not modify this file unless you know what you are doing.
+# Code generation can be broken if incorrect changes are made.
+
+%if {revoke} %then
+ {definition}
+%else
+ [REVOKE ALL PRIVILEGES ON] {object} [ FROM ] {roles}
+
+ %if {cascade} %then
+ [ CASCADE]
+ %end
+
+ ;
+
+ $br [-- ddl-end --] $br
+
+%end
diff --git a/assets/schemas/alter/policy.sch b/assets/schemas/alter/policy.sch
new file mode 100644
index 0000000000..de4e1ffb70
--- /dev/null
+++ b/assets/schemas/alter/policy.sch
@@ -0,0 +1,31 @@
+# SQL definition for policy's attributes change
+# CAUTION: Do not modify this file unless you know what you are doing.
+# Code generation can be broken if incorrect changes are made.
+
+{alter-cmds}
+
+%if {has-changes} %then
+ [ALTER POLICY ] {name} [ ON ] {table}
+
+ %if {roles} %then
+ $br $tb [TO ]
+
+ %if ({roles} == "unset") %then
+ PUBLIC
+ %else
+ {roles}
+ %end
+ %end
+
+ %if {using-exp} %then
+ $br $tb [USING (] {using-exp} [)]
+ %end
+
+ %if {check-exp} %then
+ $br $tb [WITH CHECK (] {check-exp} [)]
+ %end
+
+ ;
+
+ $br [-- ddl-end --] $br
+%end
diff --git a/assets/schemas/alter/procedure.sch b/assets/schemas/alter/procedure.sch
new file mode 100644
index 0000000000..5523a0ce50
--- /dev/null
+++ b/assets/schemas/alter/procedure.sch
@@ -0,0 +1,25 @@
+# SQL definition for procedure's attributes change
+# CAUTION: Do not modify this file unless you know what you are doing.
+# Code generation can be broken if incorrect changes are made.
+
+#%if {definition} %then
+# {definition}
+#%else
+ {alter-cmds}
+
+ %if {has-changes} %then
+ [ALTER ] {sql-object} $sp {signature}
+
+ %if {security-type} %then
+ $br $tb {security-type}
+ %end
+
+ %if {config-params} %then
+ {config-params}
+ %end
+
+ ;
+
+ $br [-- ddl-end --] $br
+ %end
+#%end
diff --git a/assets/schemas/alter/relationship.sch b/assets/schemas/alter/relationship.sch
new file mode 100644
index 0000000000..1a78bdcdd3
--- /dev/null
+++ b/assets/schemas/alter/relationship.sch
@@ -0,0 +1,35 @@
+# SQL definition for table inheritance configuration
+# CAUTION: Do not modify this file unless you know what you are doing.
+# Code generation can be broken if incorrect changes are made.
+
+%set {alter-table} [ALTER ] {sql-object} $sp
+
+%if {partitioned-table} %then
+ {alter-table} {partitioned-table}
+
+ %if ({partitioning}=="unset") %then [ DETACH] %else [ ATTACH] %end
+
+ [ PARTITION ] {table}
+
+ %if ({partitioning}!="unset") %then
+ %if {partition-bound-expr} %then
+ [ FOR VALUES ] {partition-bound-expr}
+ %else
+ [ DEFAULT]
+ %end
+ %end
+%else
+
+ {alter-table} {table}
+
+ %if ({inherit}=="unset") %then [ NO] %end
+
+ [ INHERIT ] {ancestor-table}
+%end
+
+;
+
+$br [-- ddl-end --] $br
+
+
+
diff --git a/assets/schemas/alter/rename.sch b/assets/schemas/alter/rename.sch
new file mode 100644
index 0000000000..d4f0accb1e
--- /dev/null
+++ b/assets/schemas/alter/rename.sch
@@ -0,0 +1,12 @@
+# SQL definition for object renaming
+# CAUTION: Do not modify this file unless you know what you are doing.
+# Code generation can be broken if incorrect changes are made.
+
+%if %not {constraint} %and %not {column} %then
+ [ALTER ] {sql-object} $sp {signature} [ RENAME TO ] {new-name};
+%else
+ [ALTER TABLE ] {table} [ RENAME ] {sql-object} $sp {name} [ TO ] {new-name};
+%end
+
+$br [-- ddl-end --] $br
+
diff --git a/assets/schemas/alter/role.sch b/assets/schemas/alter/role.sch
new file mode 100644
index 0000000000..ec6edf1e52
--- /dev/null
+++ b/assets/schemas/alter/role.sch
@@ -0,0 +1,73 @@
+# SQL definition for role's attributes change
+# CAUTION: Do not modify this file unless you know what you are doing.
+# Code generation can be broken if incorrect changes are made.
+
+{alter-cmds}
+
+%if {has-changes} %then
+ [ALTER ] {sql-object} $sp {signature}
+
+ %if {superuser} %then
+ $br $tb
+ %if ({superuser}=="unset") %then NO %end
+ SUPERUSER
+ %end
+
+ %if {createdb} %then
+ $br $tb
+ %if ({createdb}=="unset") %then NO %end
+ CREATEDB
+ %end
+
+ %if {createrole} %then
+ $br $tb
+ %if ({createrole}=="unset") %then NO %end
+ CREATEROLE
+ %end
+
+ %if {inherit} %then
+ $br $tb
+ %if ({inherit}=="unset") %then NO %end
+ INHERIT
+ %end
+
+ %if {login} %then
+ $br $tb
+ %if ({login}=="unset") %then NO %end
+ LOGIN
+ %end
+
+ %if {replication} %then
+ $br $tb
+ %if ({replication}=="unset") %then NO %end
+ REPLICATION
+ %end
+
+ %if {bypassrls} %then
+ $br $tb
+ %if ({bypassrls}=="unset") %then NO %end
+ BYPASSRLS
+ %end
+
+ %if {password} %or {empty-password} %then
+ $br $tb
+
+ %if {empty-password} %then
+ [PASSWORD ] ''
+ %else
+ [PASSWORD ] '{password}'
+ %end
+ %end
+
+ %if {connlimit} %then $br $tb [CONNECTION LIMIT ] {connlimit} %end
+ %if {validity} %then $br $tb [VALID UNTIL ] '{validity}' %end
+
+ ;
+
+ $br [-- ddl-end --] $br
+%end
+
+%if {member-roles} %then
+ {member-roles}
+%end
+
diff --git a/assets/schemas/alter/rolemembers.sch b/assets/schemas/alter/rolemembers.sch
new file mode 100644
index 0000000000..91904caba3
--- /dev/null
+++ b/assets/schemas/alter/rolemembers.sch
@@ -0,0 +1,33 @@
+# SQL definition for role members changes
+# CAUTION: Do not modify this file unless you know what you are doing.
+# Code generation can be broken if incorrect changes are made.
+
+%if {revoke} %then
+ [REVOKE ]
+
+ %if {admin-option} %then
+ [ADMIN OPTION FOR ]
+ %end
+%else
+ [GRANT ]
+%end
+
+{role}
+
+%if {revoke} %then
+ [ FROM ]
+%else
+ [ TO ]
+%end
+
+{roles}
+
+%if %not {revoke} %and {admin-option} %then
+ [ WITH ADMIN OPTION]
+%end
+
+%if {revoke} %then
+ [ CASCADE]
+%end
+
+; $br [-- ddl-end --] $br
diff --git a/assets/schemas/alter/schema.sch b/assets/schemas/alter/schema.sch
new file mode 100644
index 0000000000..2f438c491a
--- /dev/null
+++ b/assets/schemas/alter/schema.sch
@@ -0,0 +1,7 @@
+# SQL definition for object's schema attribute change
+# CAUTION: Do not modify this file unless you know what you are doing.
+# Code generation can be broken if incorrect changes are made.
+
+[ALTER ] {sql-object} $sp {signature} [ SET SCHEMA ] {schema};
+
+$br [-- ddl-end --] $br
diff --git a/assets/schemas/alter/sequence.sch b/assets/schemas/alter/sequence.sch
new file mode 100644
index 0000000000..93ed93526b
--- /dev/null
+++ b/assets/schemas/alter/sequence.sch
@@ -0,0 +1,55 @@
+# SQL definition for sequence's attributes change
+# CAUTION: Do not modify this file unless you know what you are doing.
+# Code generation can be broken if incorrect changes are made.
+
+{alter-cmds}
+
+%if {has-changes} %then
+ [ALTER ] {sql-object} $sp {signature} $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
+ %if ({cycle}=="unset") %then NO %end
+ CYCLE $br
+ %end
+
+ %if {owner-col} %then
+ $tb [OWNED BY ]
+
+ %if ({owner-col}=="unset") %then
+ NONE
+ %else
+ {owner-col}
+ %end
+ %end
+
+ ; $br
+
+ %if {owner-col} %and ({owner-col}!="unset") %then
+ $br
+ [ALTER TABLE ] {table} [ ALTER COLUMN ] {column} $br
+ [ SET DEFAULT nextval('] {name} ['::regclass);] $br
+ %end
+
+ [-- ddl-end --] $br
+%end
diff --git a/assets/schemas/alter/table.sch b/assets/schemas/alter/table.sch
new file mode 100644
index 0000000000..b532cc10fb
--- /dev/null
+++ b/assets/schemas/alter/table.sch
@@ -0,0 +1,61 @@
+# SQL definition for table's attributes change
+# CAUTION: Do not modify this file unless you know what you are doing.
+# Code generation can be broken if incorrect changes are made.
+
+{alter-cmds}
+
+%if {has-changes} %then
+ %set {alter} ALTER $sp {sql-object} $sp {signature}
+ %set {rls} [ROW LEVEL SECURITY]
+ %set {ddl-end} ; $br [-- ddl-end --] $br
+
+ %if ({pgsql-ver} <=f "11.0") %and {oids} %then
+ {alter} [ SET ]
+
+ %if ({oids}=="unset") %then
+ WITHOUT
+ %else
+ WITH
+ %end
+
+ [ OIDS]
+
+ {ddl-end}
+ %end
+
+ %if {unlogged} %then
+ {alter} [ SET ]
+
+ %if ({unlogged}=="unset") %then
+ [LOGGED]
+ %else
+ [UNLOGGED]
+ %end
+
+ {ddl-end}
+ %end
+
+ %if {rls-enabled} %then
+ {alter}
+
+ %if ({rls-enabled}=="unset") %then
+ [ DISABLE ]
+ %else
+ [ ENABLE ]
+ %end
+
+ {rls}
+ {ddl-end}
+ %end
+
+ %if {rls-forced} %then
+ {alter}
+
+ %if ({rls-forced}=="unset") %then
+ [ NO]
+ %end
+
+ [ FORCE ] {rls}
+ {ddl-end}
+ %end
+%end
diff --git a/assets/schemas/alter/tablespace.sch b/assets/schemas/alter/tablespace.sch
new file mode 100644
index 0000000000..443b58dc60
--- /dev/null
+++ b/assets/schemas/alter/tablespace.sch
@@ -0,0 +1,7 @@
+# SQL definition for object's tablespace attribute change
+# CAUTION: Do not modify this file unless you know what you are doing.
+# Code generation can be broken if incorrect changes are made.
+
+[ALTER ] {sql-object} $sp {name} [ SET TABLESPACE ] {tablespace};
+
+$br [-- ddl-end --] $br
diff --git a/assets/schemas/alter/truncate.sch b/assets/schemas/alter/truncate.sch
new file mode 100644
index 0000000000..ea5edd0f1f
--- /dev/null
+++ b/assets/schemas/alter/truncate.sch
@@ -0,0 +1,17 @@
+# SQL definition for trucate tables
+# CAUTION: Do not modify this file unless you know what you are doing.
+# Code generation can be broken if incorrect changes are made.
+
+[TRUNCATE ] {sql-object} $sp {signature}
+
+%if {restart-seq} %then
+ [ RESTART IDENTITY ]
+%end
+
+%if {cascade} %then
+ [ CASCADE]
+%end
+
+;
+
+$br [-- ddl-end --] $br
diff --git a/assets/schemas/alter/usermapping.sch b/assets/schemas/alter/usermapping.sch
new file mode 100644
index 0000000000..46e538bd9b
--- /dev/null
+++ b/assets/schemas/alter/usermapping.sch
@@ -0,0 +1,21 @@
+# SQL definition for user mapping's attributes change
+# CAUTION: Do not modify this file unless you know what you are doing.
+# Code generation can be broken if incorrect changes are made.
+
+{alter-cmds}
+
+%if {has-changes} %then
+ [ALTER ] {sql-object} $sp {signature}
+
+
+ %if {options} %then
+ $br $tb
+ [ OPTIONS (] {options} [)]
+ %end
+
+ ;
+
+ $br [-- ddl-end --] $br
+
+%end
+
diff --git a/assets/schemas/alter/usertype.sch b/assets/schemas/alter/usertype.sch
new file mode 100644
index 0000000000..b45b4227e6
--- /dev/null
+++ b/assets/schemas/alter/usertype.sch
@@ -0,0 +1,45 @@
+# SQL definition for user defined types' attributes change
+# CAUTION: Do not modify this file unless you know what you are doing.
+# Code generation can be broken if incorrect changes are made.
+
+%if {has-changes} %then
+ %set {alter-type} [ALTER ] {sql-object} $sp {name}
+ %set {ddl-end} ; $br [-- ddl-end --] $br
+
+ %if {value} %then
+ {alter-type}
+ [ ADD VALUE ] '{value}'
+
+ %if {before} %then
+ [ BEFORE ]
+ %else
+ [ AFTER ]
+ %end
+
+ '{existing-value}'
+
+ {ddl-end}
+ %end
+
+ %if {attribute} %then
+ {alter-type}
+
+ %if {drop} %then
+ [ DROP ATTRIBUTE ] {attribute}
+ %else
+ %if {change} %then
+ [ ALTER ATTRIBUTE ] {attribute} [ TYPE ] {type}
+ %else
+ [ ADD ATTRIBUTE ] {attribute} $sp {type}
+
+ %if {collation} %then
+ [ COLLATE ] {collation}
+ %end
+ %end
+ %end
+
+ [ CASCADE]
+
+ {ddl-end}
+ %end
+%end
diff --git a/assets/schemas/catalog/aggregate.sch b/assets/schemas/catalog/aggregate.sch
new file mode 100644
index 0000000000..8852ae6bcf
--- /dev/null
+++ b/assets/schemas/catalog/aggregate.sch
@@ -0,0 +1,81 @@
+# Catalog queries for aggregates
+# 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 "10.0") %then
+ %set {is-agg} [pr.proisagg IS TRUE]
+%else
+ %set {is-agg} [pr.prokind = 'a']
+%end
+
+%if {list} %then
+ %if {use-signature} %then
+ %set {signature} [ ns.nspname || '.' || ]
+ %end
+
+ [SELECT pr.oid, proname || '(' ||
+
+ CASE
+ WHEN array_length(proargtypes,1) = 0 THEN '*'
+ ELSE array_to_string(proargtypes::regtype] $ob $cb [,',')
+ END || ')' AS name,
+
+ ns.nspname AS parent, 'schema' AS parent_type, NULL AS extra_info
+
+ FROM pg_proc AS pr
+ LEFT JOIN pg_namespace AS ns ON pr.pronamespace = ns.oid ]
+
+ %if {schema} %then
+ [ WHERE ] {is-agg} [ AND ns.nspname = ] '{schema}'
+ %else
+ [ WHERE ] {is-agg}
+ %end
+
+ %if {last-sys-oid} %then
+ [ AND pr.oid ] {oid-filter-op} $sp {last-sys-oid}
+ %end
+
+ %if {not-ext-object} %then
+ [ AND ] ( {not-ext-object} )
+ %end
+
+ %if {name-filter} %then
+ [ AND ] ( {signature} [ proname ~* ] E'{name-filter}' )
+ %end
+%else
+ %if {attribs} %then
+ [SELECT pr.oid AS oid, ag.aggfnoid AS name, ag.aggtransfn::oid AS transition,
+ ag.aggfinalfn::oid AS final, ag.aggsortop::oid AS sort_op, aggtranstype AS state_type,
+ pr.proargtypes::oid] $ob $cb [ AS types, ag.agginitval AS initial_cond, pr.proowner AS owner,
+ pr.pronamespace AS schema, pr.proacl AS permission, ]
+
+ ({comment}) [ AS comment ]
+
+ [ FROM pg_aggregate AS ag
+ LEFT JOIN pg_proc AS pr ON pr.oid=ag.aggfnoid::oid ]
+
+ %if {schema} %then
+ [ LEFT JOIN pg_namespace AS ns ON pr.pronamespace = ns.oid ]
+ %end
+
+ [ WHERE ] {is-agg}
+
+ %if {last-sys-oid} %then
+ [ AND pr.oid ] {oid-filter-op} $sp {last-sys-oid}
+ %end
+
+ %if {not-ext-object} %then
+ [ AND ] ( {not-ext-object} )
+ %end
+
+ %if {filter-oids} %or {schema} %then
+ %if {filter-oids} %then
+ [ AND pr.oid IN (] {filter-oids} )
+ %end
+
+ %if {schema} %then
+ [ AND ns.nspname = ] '{schema}'
+ %end
+ %end
+ %end
+%end
diff --git a/assets/schemas/catalog/cast.sch b/assets/schemas/catalog/cast.sch
new file mode 100644
index 0000000000..3d2c3df233
--- /dev/null
+++ b/assets/schemas/catalog/cast.sch
@@ -0,0 +1,79 @@
+# Catalog queries for casts
+# CAUTION: Do not modify this file unless you know what you are doing.
+# Code generation can be broken if incorrect changes are made.
+
+%if {list} %then
+ %set {cast-name} ['cast('|| castsource::regtype::text || ',' || casttarget::regtype::text || ')']
+
+ [SELECT cs.oid, ] {cast-name} [ AS name, current_database() AS parent,
+ 'database' AS parent_type, NULL AS extra_info
+ FROM pg_cast AS cs ]
+
+ %if {last-sys-oid} %or {not-ext-object} %or {name-filter} %then
+ [ WHERE ]
+
+ %if {last-sys-oid} %then
+ [ oid ] {oid-filter-op} $sp {last-sys-oid}
+ %end
+
+ %if {not-ext-object} %then
+ %if {last-sys-oid} %then
+ [ AND ]
+ %end
+
+ ( {not-ext-object} )
+ %end
+
+ %if {name-filter} %then
+ %if {last-sys-oid} %or {not-ext-object} %then
+ [ AND ]
+ %end
+
+ ( {cast-name} [ ~* ] E'{name-filter}' )
+ %end
+ %end
+%else
+ %if {attribs} %then
+ [SELECT oid, 'cast('|| castsource::regtype::text || ',' || casttarget::regtype::text || ')' AS name,
+ castsource AS source_type, casttarget AS destiny_type, castfunc AS function,
+
+ CASE castcontext
+ WHEN 'a' THEN 'assignment'
+ WHEN 'i' THEN 'implicit'
+ ELSE 'explicit'
+ END AS cast_type,
+
+ CASE castmethod
+ WHEN 'b' THEN TRUE
+ ELSE FALSE
+ END AS io_cast_bool, ]
+
+ ({comment}) [ AS comment ]
+
+ [ FROM pg_cast AS cs]
+
+ %if {last-sys-oid} %then
+ [ WHERE oid ] {oid-filter-op} $sp {last-sys-oid}
+ %end
+
+ %if {filter-oids} %then
+ %if {last-sys-oid} %then
+ [ AND]
+ %else
+ [ WHERE ]
+ %end
+
+ [ oid IN (] {filter-oids} )
+ %end
+
+ %if {not-ext-object} %then
+ %if {last-sys-oid} %or {filter-oids} %then
+ [ AND ]
+ %else
+ [ WHERE ]
+ %end
+
+ ( {not-ext-object} )
+ %end
+ %end
+%end
diff --git a/assets/schemas/catalog/collation.sch b/assets/schemas/catalog/collation.sch
new file mode 100644
index 0000000000..824c8f68f3
--- /dev/null
+++ b/assets/schemas/catalog/collation.sch
@@ -0,0 +1,128 @@
+# Catalog queries for collation
+# CAUTION: Do not modify this file unless you know what you are doing.
+# Code generation can be broken if incorrect changes are made.
+
+%if {list} %then
+ %if {use-signature} %then
+ %set {signature} [ ns.nspname || '.' || ]
+ %end
+
+ [SELECT cl.oid, collname AS name,
+ ns.nspname AS parent, 'schema' AS parent_type, NULL AS extra_info
+ FROM pg_collation AS cl
+ LEFT JOIN pg_namespace AS ns ON cl.collnamespace = ns.oid ]
+
+ %if {schema} %then
+ [ WHERE ns.nspname = ] '{schema}'
+ %end
+
+ %if {last-sys-oid} %then
+ %if {schema} %then
+ [ AND ]
+ %else
+ [ WHERE ]
+ %end
+
+ [ cl.oid ] {oid-filter-op} $sp {last-sys-oid}
+ %end
+
+ %if {not-ext-object} %then
+ %if {last-sys-oid} %or {schema} %then
+ [ AND ]
+ %else
+ [ WHERE ]
+ %end
+
+ ( {not-ext-object} )
+ %end
+
+ %if {name-filter} %then
+ %if {last-sys-oid} %or {schema} %or {not-ext-object} %then
+ [ AND ]
+ %else
+ [ WHERE ]
+ %end
+
+ ( {signature} [ cl.collname ~* ] E'{name-filter}' )
+ %end
+%else
+ %if {attribs} %then
+ [ SELECT cl.oid, cl.collname AS name, cl.collnamespace AS schema,
+ cl.collowner AS owner, pg_encoding_to_char(cl.collencoding) AS encoding,
+ cl.collcollate AS lc_collate, cl.collctype AS lc_ctype,
+ split_part(collctype, '@', 2) AS lc_ctype_mod,
+ split_part(collcollate, '@', 2) AS lc_collate_mod, ]
+
+ %if ({pgsql-ver} >=f "10.0") %then
+ [ CASE
+ WHEN collprovider = 'i' THEN 'icu'
+ WHEN collprovider = 'c' THEN 'libc'
+ ELSE 'default'
+ END AS provider, ]
+ %else
+ [ '' AS provider, ]
+ %end
+
+ %if ({pgsql-ver} >=f "12.0") %then
+ [ collisdeterministic AS deterministic_bool, ]
+ %else
+ [ false AS deterministic_bool, ]
+ %end
+
+ %if ({pgsql-ver} >=f "15.0") %then
+
+ %if ({pgsql-ver} <=f "16.0") %then
+ [ colliculocale ]
+ %else
+ [ colllocale ]
+ %end
+
+ [ AS locale, ]
+
+ %else
+ [ null AS locale, ]
+ %end
+
+ ({comment}) [ AS comment ]
+
+ [ FROM pg_collation AS cl ]
+
+ %if {schema} %then
+ [ LEFT JOIN pg_namespace AS ns ON cl.collnamespace = ns.oid ]
+ %end
+
+ %if {last-sys-oid} %then
+ [ WHERE cl.oid ] {oid-filter-op} $sp {last-sys-oid}
+ %end
+
+ %if {not-ext-object} %then
+ %if {last-sys-oid} %then
+ [ AND ]
+ %else
+ [ WHERE ]
+ %end
+
+ ( {not-ext-object} )
+ %end
+
+ %if {filter-oids} %or {schema} %then
+ %if {last-sys-oid} %or {not-ext-object} %then
+ [ AND ]
+ %else
+ [ WHERE ]
+ %end
+
+ %if {filter-oids} %then
+ [ cl.oid IN (] {filter-oids} )
+
+ %if {schema} %then
+ [ AND ]
+ %end
+ %end
+
+ %if {schema} %then
+ [ ns.nspname = ] '{schema}'
+ %end
+ %end
+ %end
+%end
diff --git a/assets/schemas/catalog/column.sch b/assets/schemas/catalog/column.sch
new file mode 100644
index 0000000000..ee05bc6ef5
--- /dev/null
+++ b/assets/schemas/catalog/column.sch
@@ -0,0 +1,82 @@
+# Catalog queries 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.
+
+#NOTE: For columns and other table object is needed to pass the table name as
+# well the schema name of the parent table in the both data retrieving methods (list/attribs)
+
+%if {list} %then
+ [ SELECT cl.attnum AS oid, cl.attname AS name,
+ cl.attrelid::regclass::text AS parent,
+ 'table' AS parent_type, NULL AS extra_info
+ FROM pg_attribute AS cl
+ LEFT JOIN pg_class AS tb ON tb.oid = cl.attrelid
+ LEFT JOIN pg_namespace AS ns ON ns.oid = tb.relnamespace
+ WHERE cl.attisdropped IS FALSE AND relname=]'{table}' [ AND nspname= ] '{schema}'
+
+ %if {name-filter} %then
+ [ AND ] ( cl.attname ~* E'{name-filter}' )
+ %end
+
+ [ AND attnum >= 0 ORDER BY attnum ASC ]
+%else
+ %if {attribs} %then
+ [SELECT cl.attnum AS oid, cl.attname AS name, cl.attnotnull AS not_null_bool,
+ cl.attacl AS permission, pg_get_expr(df.adbin, df.adrelid) AS default_value,
+ ds.description AS comment, tb.oid AS table, ]
+
+ %if ({pgsql-ver} >=f "10.0") %then
+ [ CASE
+ WHEN cl.attidentity = 'a' THEN 'ALWAYS'
+ WHEN cl.attidentity = 'd' THEN 'BY DEFAULT'
+ ELSE NULL
+ END AS identity_type, ]
+ %else
+ [ NULL AS identity_type, ]
+ %end
+
+ %if ({pgsql-ver} >=f "12.0") %then
+ [ CASE
+ WHEN cl.attgenerated = 's' THEN TRUE
+ ELSE FALSE
+ END AS generated_bool, ]
+ %else
+ [ FALSE AS generated_bool, ]
+ %end
+
+ #Creating an attribute to indicate if the column is inherited or not
+ [ CASE
+ WHEN cl.attinhcount > 0 THEN TRUE
+ ELSE FALSE
+ END AS inherited_bool, ]
+
+ # This subquery retrieve the schema name for the type when it is undeer public schema.
+ # This is necessary because pgModeler identifies user-defined types by the complete
+ # type signature [schema].[typename]
+ [(SELECT
+ CASE
+ WHEN ns.nspname='public' THEN ns.nspname || '.'
+ ELSE ''
+ END
+ FROM pg_namespace AS ns
+ LEFT JOIN pg_type AS tp ON tp.typnamespace=ns.oid
+ WHERE tp.oid=cl.atttypid) || format_type(atttypid,atttypmod) AS type,
+
+ atttypid AS type_oid, cl.attcollation AS collation
+
+ FROM pg_attribute AS cl
+ LEFT JOIN pg_attrdef AS df ON df.adrelid=cl.attrelid AND df.adnum=cl.attnum
+ LEFT JOIN pg_description AS ds ON ds.objoid=cl.attrelid AND ds.objsubid=cl.attnum
+ LEFT JOIN pg_class AS tb ON tb.oid = cl.attrelid
+ LEFT JOIN pg_namespace AS ns ON ns.oid = tb.relnamespace
+ WHERE cl.attisdropped IS FALSE AND relname= ] '{table}'
+ [ AND nspname= ] '{schema}'
+ [ AND attnum >= 0 ]
+
+ %if {filter-oids} %then
+ [ AND cl.attnum IN (] {filter-oids} )
+ %end
+
+ [ ORDER BY attnum ASC ]
+ %end
+%end
diff --git a/assets/schemas/catalog/comment.sch b/assets/schemas/catalog/comment.sch
new file mode 100644
index 0000000000..1e2246929e
--- /dev/null
+++ b/assets/schemas/catalog/comment.sch
@@ -0,0 +1,21 @@
+# Catalog queries to retrive object comments
+# CAUTION: Do not modify this file unless you know what you are doing.
+# Code generation can be broken if incorrect changes are made.
+
+[SELECT description FROM ]
+
+%if {shared-obj} %then
+ pg_shdescription
+%else
+ pg_description
+%end
+
+[ WHERE objoid = ] {oid}
+
+%if {obj-rel-name} %then
+ [ AND classoid = '] {obj-rel-name} ['::regclass::oid ]
+%end
+
+%if %not {shared-obj} %then
+ [ AND objsubid = 0 ]
+%end
diff --git a/assets/schemas/catalog/constraint.sch b/assets/schemas/catalog/constraint.sch
new file mode 100644
index 0000000000..77b117cad3
--- /dev/null
+++ b/assets/schemas/catalog/constraint.sch
@@ -0,0 +1,188 @@
+# Catalog queries 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 {list} %then
+ %set {parent-name} [ ns.nspname || '.' || tb.relname ]
+
+ %if {use-signature} %then
+ %set {signature} {parent-name} [ || '.' || ]
+ %end
+
+ [ SELECT cs.oid, cs.conname AS name, ] {parent-name} [ AS parent,
+ 'table' AS parent_type,
+
+ CASE cs.contype
+ WHEN 'p' THEN 'pk-constr'
+ WHEN 'u' THEN 'uq-constr'
+ WHEN 'c' THEN 'ck-constr'
+ WHEN 'f' THEN 'fk-constr'
+ ELSE 'ex-constr'
+ END AS extra_info
+
+ FROM pg_constraint AS cs
+ LEFT JOIN pg_class AS tb ON cs.conrelid = tb.oid
+ LEFT JOIN pg_namespace AS ns ON ns.oid = cs.connamespace ]
+
+ %if {schema} %then
+ [ WHERE nspname= ] '{schema}'
+
+ %if {table} %then
+ [ AND relkind IN ('r','p','f') AND relname=] '{table}'
+ %end
+ %end
+
+ %if {last-sys-oid} %then
+ %if {schema} %then
+ [ AND ]
+ %else
+ [ WHERE ]
+ %end
+
+ [ cs.oid ] {oid-filter-op} $sp {last-sys-oid}
+ %end
+
+ %if {last-sys-oid} %or {schema} %then
+ [ AND ]
+ %else
+ [ WHERE ]
+ %end
+
+ #Avoiding the listing of constraint generated by constraint triggers and those inherited
+ [ cs.oid NOT IN (SELECT DISTINCT tgconstraint FROM pg_trigger WHERE tgconstrindid=0)
+ AND cs.conislocal IS TRUE ]
+
+ %if {not-ext-object} %then
+ [ AND ]( {not-ext-object} )
+ %end
+
+ %if {name-filter} %then
+ [ AND ] ( {signature} cs.conname ~* E'{name-filter}' )
+ %end
+
+ %if {extra-condition} %then
+ [ AND ] ( {extra-condition} )
+ %end
+%else
+ %if {attribs} %then
+ [SELECT cs.oid, cs.conname AS name, cs.conrelid AS table,
+ cs.conkey AS src_columns, cs.confkey AS dst_columns,
+ cs.condeferrable AS deferrable_bool, cs.confrelid AS ref_table,
+ cl.reltablespace AS tablespace, cs.conexclop AS operators,
+ am.amname AS index_type, cl.reloptions AS factor, ]
+
+ [ id.indkey::oid] $ob $cb [ AS columns,
+ id.indclass::oid] $ob $cb [ AS opclasses,
+ id.indoption::int2] $ob $cb [ AS options,
+ pg_get_expr(id.indpred, id.indrelid) AS condition,
+ pg_get_constraintdef(cs.oid) AS expressions,
+
+ cs.connoinherit AS no_inherit_bool,
+
+ CASE cs.coninhcount
+ WHEN 0 THEN FALSE
+ ELSE TRUE
+ END AS inherited_bool,
+
+ CASE cs.contype
+ WHEN 'p' THEN 'pk-constr'
+ WHEN 'u' THEN 'uq-constr'
+ WHEN 'c' THEN 'ck-constr'
+ WHEN 'f' THEN 'fk-constr'
+ ELSE 'ex-constr'
+ END AS type,
+
+ CASE cs.condeferred
+ WHEN TRUE THEN 'INITIALLY DEFERRED'
+ ELSE 'INITIALLY IMMEDIATE'
+ END AS defer_type,
+
+ CASE cs.confupdtype
+ WHEN 'a' THEN 'NO ACTION'
+ WHEN 'r' THEN 'RESTRICT'
+ WHEN 'c' THEN 'CASCADE'
+ WHEN 'n' THEN 'SET NULL'
+ WHEN 'd' THEN 'SET DEFAULT'
+ ELSE NULL
+ END AS upd_action,
+
+ CASE cs.confdeltype
+ WHEN 'a' THEN 'NO ACTION'
+ WHEN 'r' THEN 'RESTRICT'
+ WHEN 'c' THEN 'CASCADE'
+ WHEN 'n' THEN 'SET NULL'
+ WHEN 'd' THEN 'SET DEFAULT'
+ ELSE NULL
+ END AS del_action,
+
+ CASE cs.confmatchtype
+ WHEN 'f' THEN 'MATCH FULL'
+ WHEN 'p' THEN 'MATCH PARTIAL'
+ WHEN 's' THEN 'MATCH SIMPLE'
+ ELSE NULL
+ END AS comparison_type,
+
+ CASE
+ WHEN tb.relkind = 'r' THEN 'table'
+ WHEN tb.relkind = 'p' THEN 'table'
+ WHEN tb.relkind = 'f' THEN 'foreigntable'
+ END AS table_type, ]
+
+ ({comment}) [ AS comment, ]
+
+ %if ({pgsql-ver} >=f "15.0") %then
+ [ id.indnullsnotdistinct AS nulls_not_distinct_bool ]
+ %else
+ [ FALSE AS nulls_not_distinct_bool ]
+ %end
+
+ [ FROM pg_constraint AS cs
+ LEFT JOIN pg_class AS cl ON cl.oid = cs.conindid
+ LEFT JOIN pg_am AS am ON cl.relam = am.oid
+ LEFT JOIN pg_index AS id ON id.indexrelid= cs.conindid
+ LEFT JOIN pg_class AS tb ON cs.conrelid = tb.oid ]
+
+ %if {schema} %then
+ [ LEFT JOIN pg_namespace AS ns ON ns.oid = cs.connamespace
+ WHERE ns.nspname= ] '{schema}'
+
+ %if {table} %then
+ [ AND tb.relkind IN ('r','p','f') AND tb.relname= ] '{table}'
+ %end
+ %end
+
+ %if {last-sys-oid} %then
+ %if {schema} %then
+ [ AND ]
+ %else
+ [ WHERE ]
+ %end
+
+ [ cs.oid ] {oid-filter-op} $sp {last-sys-oid}
+ %end
+
+ %if {filter-oids} %then
+ %if {schema} %or {last-sys-oid} %then
+ [ AND ]
+ %else
+ [ WHERE ]
+ %end
+
+ [ cs.oid IN (] {filter-oids} )
+ %end
+
+ %if {filter-oids} %or {last-sys-oid} %or {schema} %then
+ [ AND ]
+ %else
+ [ WHERE ]
+ %end
+
+ #Avoiding the listing of constraint generated by constraint triggers and those inherited
+ [ cs.oid NOT IN (SELECT DISTINCT tgconstraint FROM pg_trigger WHERE tgconstrindid=0)
+ AND cs.conislocal IS TRUE ]
+
+ %if {not-ext-object} %then
+ [ AND ]( {not-ext-object} )
+ %end
+ %end
+%end
diff --git a/assets/schemas/catalog/conversion.sch b/assets/schemas/catalog/conversion.sch
new file mode 100644
index 0000000000..1a166fb2d4
--- /dev/null
+++ b/assets/schemas/catalog/conversion.sch
@@ -0,0 +1,99 @@
+# Catalog queries for conversions
+# CAUTION: Do not modify this file unless you know what you are doing.
+# Code generation can be broken if incorrect changes are made.
+
+%if {list} %then
+ %if {use-signature} %then
+ %set {signature} [ ns.nspname || '.' || ]
+ %end
+
+ [ SELECT cn.oid, cn.conname AS name,
+ ns.nspname AS parent, 'schema' AS parent_type, NULL AS extra_info
+ FROM pg_conversion AS cn
+ LEFT JOIN pg_namespace AS ns ON cn.connamespace = ns.oid ]
+
+ %if {schema} %then
+ [ WHERE ns.nspname = ] '{schema}'
+ %end
+
+ %if {last-sys-oid} %then
+ %if {schema} %then
+ [ AND ]
+ %else
+ [ WHERE ]
+ %end
+
+ [ cn.oid ] {oid-filter-op} $sp {last-sys-oid}
+ %end
+
+ %if {not-ext-object} %then
+ %if {last-sys-oid} %or {schema} %then
+ [ AND ]
+ %else
+ [ WHERE ]
+ %end
+
+ ( {not-ext-object} )
+ %end
+
+ %if {name-filter} %then
+ %if {last-sys-oid} %or {schema} %or {not-ext-object} %then
+ [ AND ]
+ %else
+ [ WHERE ]
+ %end
+
+ ( {signature} [ cn.conname ~* ] E'{name-filter}' )
+ %end
+%else
+ %if {attribs} %then
+ [SELECT cn.oid, cn.conname AS name, cn.connamespace AS schema, cn.conowner AS owner,
+ pg_encoding_to_char(conforencoding) AS src_encoding,
+ pg_encoding_to_char(contoencoding) AS dst_encoding,
+ cn.conproc::oid AS function, cn.condefault AS default_bool, ]
+
+ ({comment}) [ AS comment ]
+
+ [ FROM pg_conversion AS cn ]
+
+ %if {schema} %then
+ [ LEFT JOIN pg_namespace AS ns ON cn.connamespace = ns.oid ]
+ %end
+
+ %if {filter-oids} %or {schema} %then
+ [ WHERE ]
+
+ %if {filter-oids} %then
+ [ cn.oid IN (] {filter-oids} )
+
+ %if {schema} %then
+ [ AND ]
+ %end
+ %end
+
+ %if {schema} %then
+ [ ns.nspname = ] '{schema}'
+ %end
+ %end
+
+ %if {last-sys-oid} %then
+ %if {filter-oids} %or {schema} %then
+ [ AND ]
+ %else
+ [ WHERE ]
+ %end
+
+ [ cn.oid ] {oid-filter-op} $sp {last-sys-oid}
+ %end
+
+ %if {not-ext-object} %then
+ %if {filter-oids} %or {last-sys-oid} %or {schema} %then
+ [ AND ]
+ %else
+ [ WHERE ]
+ %end
+
+ ( {not-ext-object} )
+ %end
+ %end
+%end
diff --git a/assets/schemas/catalog/database.sch b/assets/schemas/catalog/database.sch
new file mode 100644
index 0000000000..0c5a65cfee
--- /dev/null
+++ b/assets/schemas/catalog/database.sch
@@ -0,0 +1,45 @@
+# Catalog queries for database
+# CAUTION: Do not modify this file unless you know what you are doing.
+# Code generation can be broken if incorrect changes are made.
+
+%if {list} %then
+ [SELECT oid, datname AS name, ]
+
+ # According to PostgreSQL sources the maximum OID value for a built-in object (A.K.A system object) is 16383.
+ # This way we query the pg_depend and get the latest object id closest to that limit (16383) and assume it
+ # as the last built-in system object OID.
+ # Reference: https://github.com/postgres/postgres/blob/master/src/include/access/transam.h#L156)
+
+ [ (select objid as last_system_oid from pg_depend
+ where objid > 0 and objid <= 16383
+ order by objid desc limit 1) AS last_sys_oid ]
+
+ [ FROM pg_database
+ WHERE datistemplate = FALSE ]
+
+ %if {name} %then
+ [ AND datname = ] '{name}'
+ %end
+%else
+ %if {attribs} %then
+ [SELECT oid, datname AS name, pg_encoding_to_char(encoding) AS encoding, datdba AS owner,
+ datcollate AS lc_collate, datctype AS lc_ctype, datconnlimit AS connlimit,
+ datacl AS permission, dattablespace AS tablespace, datdba AS owner,
+ NULL AS template, ]
+
+ ({comment}) [ AS comment, datallowconn AS allow_conns_bool, datistemplate AS is_template_bool
+ FROM pg_database WHERE datistemplate = FALSE ]
+
+ #%if {last-sys-oid} %then
+ # [ AND oid ] {oid-filter-op} $sp {last-sys-oid}
+ #%end
+
+ %if {filter-oids} %then
+ [ AND oid IN (] {filter-oids} )
+ %end
+
+ %if {name} %then
+ [ AND datname = ] '{name}'
+ %end
+ %end
+%end
diff --git a/assets/schemas/catalog/domain.sch b/assets/schemas/catalog/domain.sch
new file mode 100644
index 0000000000..02bbff26fd
--- /dev/null
+++ b/assets/schemas/catalog/domain.sch
@@ -0,0 +1,84 @@
+# Catalog queries 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.
+
+%if {list} %then
+ %if {use-signature} %then
+ %set {signature} [ _dm1.domain_schema || '.' || ]
+ %end
+
+ [SELECT dm.oid, dm.typname AS name,
+ _dm1.domain_schema AS parent, 'schema' AS parent_type, NULL AS extra_info
+ FROM pg_type AS dm
+ INNER JOIN information_schema.domains AS _dm1 ON dm.typname=_dm1.domain_name
+ WHERE dm.typrelid=0 ]
+
+ %if {schema} %then
+ [ AND domain_schema=] '{schema}'
+ %end
+
+ %if {last-sys-oid} %then
+ [ AND dm.oid ] {oid-filter-op} $sp {last-sys-oid}
+ %end
+
+ %if {not-ext-object} %then
+ [ AND ]( {not-ext-object} )
+ %end
+
+ %if {name-filter} %then
+ [ AND ] ( {signature} [ dm.typname ~* ] E'{name-filter}' )
+ %end
+%else
+ %if {attribs} %then
+ [SELECT dm.oid, dm.typname AS name, dm.typowner AS owner, dm.typnamespace AS schema, dm.typndims AS dimension,
+ dm.typbasetype AS type, dm.typacl AS permission, dm.typcollation AS collation,
+
+ CASE
+ WHEN _dm1.numeric_precision_radix IS NOT NULL THEN _dm1.numeric_precision_radix
+ ELSE _dm1.character_maximum_length
+ END AS length,
+
+ CASE
+ WHEN _dm1.numeric_precision_radix IS NOT NULL THEN _dm1.numeric_scale
+ WHEN _dm1.datetime_precision IS NOT NULL THEN _dm1.datetime_precision
+ WHEN _dm1.interval_precision IS NOT NULL THEN _dm1.interval_precision
+ ELSE NULL
+ END AS precision,
+
+ dm.typnotnull AS not_null_bool,
+ _dm1.interval_type, _dm1.domain_default AS default_value,
+ (select array_to_string(array_agg(conname || ' ' || pg_get_constraintdef(oid)), '] $ds [')
+ from pg_constraint where contype <> 'n' and contypid = dm.oid) as constraints,
+ ]
+
+ ({comment}) [ AS comment ]
+
+ [ FROM pg_type AS dm
+ LEFT JOIN information_schema.domains AS _dm1 ON dm.typname=_dm1.domain_name
+ WHERE dm.typrelid=0 ]
+
+ %if {filter-oids} %or {schema} %then
+ [ AND ]
+
+ %if {filter-oids} %then
+ [ dm.oid IN (] {filter-oids} )
+
+ %if {schema} %then
+ [ AND ]
+ %end
+ %end
+
+ %if {schema} %then
+ [ _dm1.domain_schema= ] '{schema}'
+ %end
+ %end
+
+ %if {last-sys-oid} %then
+ [ AND dm.oid ] {oid-filter-op} $sp {last-sys-oid}
+ %end
+
+ %if {not-ext-object} %then
+ [ AND ]( {not-ext-object} )
+ %end
+ %end
+%end
diff --git a/assets/schemas/catalog/eventtrigger.sch b/assets/schemas/catalog/eventtrigger.sch
new file mode 100644
index 0000000000..4cf09d52d7
--- /dev/null
+++ b/assets/schemas/catalog/eventtrigger.sch
@@ -0,0 +1,55 @@
+# Catalog queries 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 {list} %then
+ [SELECT oid, evtname AS name,
+ current_database() AS parent, 'database' AS parent_type, NULL AS extra_info
+ FROM pg_event_trigger AS et ]
+
+ %if {last-sys-oid} %then
+ [ WHERE oid ] {oid-filter-op} $sp {last-sys-oid}
+ %end
+
+ %if {not-ext-object} %then
+ %if {last-sys-oid} %then
+ [ AND ]
+ %else
+ [ WHERE ]
+ %end
+
+ ( {not-ext-object} )
+ %end
+
+ %if {name-filter} %then
+ %if {last-sys-oid} %or {not-ext-object} %then
+ [ AND ]
+ %else
+ [ WHERE ]
+ %end
+
+ ( [et.evtname ~* ] E'{name-filter}' )
+ %end
+%else
+ %if {attribs} %then
+ [SELECT oid, evtname AS name, evtevent AS event, evtowner AS owner, evtfoid AS function, evttags AS values, ]
+
+ ({comment}) [ AS comment ]
+
+ [ FROM pg_event_trigger AS et ]
+
+ %if {last-sys-oid} %then
+ [ WHERE oid ] {oid-filter-op} $sp {last-sys-oid}
+ %end
+
+ %if {not-ext-object} %then
+ %if {last-sys-oid} %then
+ [ AND ]
+ %else
+ [ WHERE ]
+ %end
+
+ ( {not-ext-object} )
+ %end
+ %end
+%end
diff --git a/assets/schemas/catalog/extension.sch b/assets/schemas/catalog/extension.sch
new file mode 100644
index 0000000000..0bd2405bcd
--- /dev/null
+++ b/assets/schemas/catalog/extension.sch
@@ -0,0 +1,81 @@
+# Catalog queries 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 {list} %then
+ [SELECT ex.oid, extname AS name, ns.nspname AS parent,
+ 'schema' AS parent_type, NULL AS extra_info
+ FROM pg_extension AS ex
+ LEFT JOIN pg_namespace AS ns ON ex.extnamespace = ns.oid ]
+
+ %if {schema} %then
+ [ WHERE ns.nspname = ] '{schema}'
+ %end
+
+ %if {last-sys-oid} %then
+ %if {schema} %then
+ [ AND ]
+ %else
+ [ WHERE ]
+ %end
+
+ [ ex.oid ] {oid-filter-op} $sp {last-sys-oid}
+ %end
+
+ %if {name-filter} %then
+ %if {last-sys-oid} %or {schema} %then
+ [ AND ]
+ %else
+ [ WHERE ]
+ %end
+
+ ( [ex.extname ~* ] E'{name-filter}' )
+ %end
+%else
+ %if {attribs} %then
+ [SELECT ex.oid, ex.extname AS name, ex.extversion AS cur_version, NULL AS old_version,
+ ex.extowner AS owner, ex.extnamespace AS schema, ]
+
+ [ (SELECT array_agg(objid::regtype::text)
+ FROM pg_depend AS _dp LEFT JOIN pg_extension AS _ex ON _ex.oid =_dp.objid
+ WHERE _dp.refobjid = ex.oid AND classid::regclass::text = 'pg_type') AS types,
+
+ (SELECT array_agg(objid::regnamespace::text)
+ FROM pg_depend AS _dp LEFT JOIN pg_extension AS _ex ON _ex.oid =_dp.objid
+ WHERE _dp.refobjid = ex.oid AND classid::regclass::text = 'pg_namespace') AS schemas, ]
+
+ ({comment}) [ AS comment ]
+
+ [ FROM pg_extension AS ex ]
+
+ %if {schema} %then
+ [ LEFT JOIN pg_namespace AS ns ON ex.extnamespace = ns.oid ]
+ %end
+
+ %if {filter-oids} %or {schema} %then
+ [ WHERE ]
+
+ %if {filter-oids} %then
+ [ ex.oid IN (] {filter-oids} )
+
+ %if {schema} %then
+ [ AND ]
+ %end
+ %end
+
+ %if {schema} %then
+ [ nspname = ] '{schema}'
+ %end
+ %end
+
+ %if {last-sys-oid} %then
+ %if {filter-oids} %or {schema} %then
+ [ AND ]
+ %else
+ [ WHERE ]
+ %end
+
+ [ ex.oid ] {oid-filter-op} $sp {last-sys-oid}
+ %end
+ %end
+%end
diff --git a/assets/schemas/catalog/foreigndatawrapper.sch b/assets/schemas/catalog/foreigndatawrapper.sch
new file mode 100644
index 0000000000..0ca736a44b
--- /dev/null
+++ b/assets/schemas/catalog/foreigndatawrapper.sch
@@ -0,0 +1,66 @@
+# Catalog queries 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.
+
+%if {list} %then
+ [ SELECT fw.oid, fdwname AS name, current_database() AS parent,
+ 'database' AS parent_type, NULL AS extra_info
+ FROM pg_foreign_data_wrapper AS fw ]
+
+ %if {last-sys-oid} %or {not-ext-object} %or {name-filter} %then
+ [ WHERE ]
+
+ %if {last-sys-oid} %then
+ [ fw.oid ] {oid-filter-op} $sp {last-sys-oid}
+ %end
+
+ %if {not-ext-object} %then
+ %if {last-sys-oid} %then
+ [ AND ]
+ %end
+
+ ( {not-ext-object} )
+ %end
+
+ %if {name-filter} %then
+ %if {last-sys-oid} %or {not-ext-object} %then
+ [ AND ]
+ %end
+
+ ( [fw.fdwname ~* ] E'{name-filter}' )
+ %end
+ %end
+%else
+ %if {attribs} %then
+ [SELECT oid, fdwname AS name, fdwhandler AS handler, fdwvalidator AS validator,
+ fdwacl AS permission, fdwowner AS owner, fdwoptions AS options, ]
+
+ ({comment}) [ AS comment ]
+
+ [ FROM pg_foreign_data_wrapper AS fw ]
+
+ %if {last-sys-oid} %then
+ [ WHERE oid ] {oid-filter-op} $sp {last-sys-oid}
+ %end
+
+ %if {not-ext-object} %then
+ %if {last-sys-oid} %then
+ [ AND ]
+ %else
+ [ WHERE ]
+ %end
+
+ ( {not-ext-object} )
+ %end
+
+ %if {filter-oids} %then
+ %if {last-sys-oid} %or {not-ext-object} %then
+ [ AND ]
+ %else
+ [ WHERE ]
+ %end
+
+ [ oid IN (] {filter-oids} )
+ %end
+ %end
+%end
diff --git a/assets/schemas/catalog/foreignserver.sch b/assets/schemas/catalog/foreignserver.sch
new file mode 100644
index 0000000000..a76430a7c5
--- /dev/null
+++ b/assets/schemas/catalog/foreignserver.sch
@@ -0,0 +1,67 @@
+# Catalog queries 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.
+
+%if {list} %then
+ [ SELECT sv.oid, srvname AS name, current_database() AS parent,
+ 'database' AS parent_type, NULL AS extra_info
+ FROM pg_foreign_server AS sv ]
+
+ %if {last-sys-oid} %or {not-ext-object} %or {name-filter} %then
+ [ WHERE ]
+
+ %if {last-sys-oid} %then
+ [ sv.oid ] {oid-filter-op} $sp {last-sys-oid}
+ %end
+
+ %if {not-ext-object} %then
+ %if {last-sys-oid} %then
+ [ AND ]
+ %end
+
+ ( {not-ext-object} )
+ %end
+
+ %if {name-filter} %then
+ %if {last-sys-oid} %or {not-ext-object} %then
+ [ AND ]
+ %end
+
+ ( [sv.srvname ~* ] E'{name-filter}' )
+ %end
+ %end
+%else
+ %if {attribs} %then
+ [SELECT oid, srvname AS name, srvversion AS version, srvtype AS type,
+ srvfdw AS fdw, srvacl AS permission, srvowner AS owner,
+ srvoptions AS options, ]
+
+ ({comment}) [ AS comment ]
+
+ [ FROM pg_foreign_server AS sv ]
+
+ %if {last-sys-oid} %then
+ [ WHERE oid ] {oid-filter-op} $sp {last-sys-oid}
+ %end
+
+ %if {not-ext-object} %then
+ %if {last-sys-oid} %then
+ [ AND ]
+ %else
+ [ WHERE ]
+ %end
+
+ ( {not-ext-object} )
+ %end
+
+ %if {filter-oids} %then
+ %if {last-sys-oid} %or {not-ext-object} %then
+ [ AND ]
+ %else
+ [ WHERE ]
+ %end
+
+ [ oid IN (] {filter-oids} )
+ %end
+ %end
+%end
diff --git a/assets/schemas/catalog/foreigntable.sch b/assets/schemas/catalog/foreigntable.sch
new file mode 100644
index 0000000000..74a222f981
--- /dev/null
+++ b/assets/schemas/catalog/foreigntable.sch
@@ -0,0 +1,84 @@
+# Catalog queries 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.
+
+%if {list} %then
+ %if {use-signature} %then
+ %set {signature} [ ns.nspname || '.' || ]
+ %end
+
+ [ SELECT ft.oid, ft.relname AS name, ns.nspname AS parent,
+ 'schema' AS parent_type, NULL AS extra_info
+ FROM pg_class AS ft
+ LEFT JOIN pg_namespace AS ns ON ns.oid=ft.relnamespace ]
+
+ %if {schema} %then
+ [ WHERE ft.relkind = 'f' AND ns.nspname= ] '{schema}'
+ %else
+ [ WHERE ft.relkind = 'f' ]
+ %end
+
+ %if {last-sys-oid} %then
+ [ AND ft.oid ] {oid-filter-op} $sp {last-sys-oid}
+ %end
+
+ %if {not-ext-object} %then
+ [ AND ] ( {not-ext-object} )
+ %end
+
+ %if {name-filter} %then
+ [ AND ] ( {signature} [ ft.relname ~* ] E'{name-filter}' )
+ %end
+%else
+ %if {attribs} %then
+ [SELECT ft.oid, ft.relname AS name, ft.relnamespace AS schema, ft.relowner AS owner, ft.relacl AS permission,
+ ftserver AS server, ftoptions AS options, ]
+
+ %if ({pgsql-ver} >=f "10.0") %then
+ [ (SELECT array_agg(inhparent) AS parents FROM pg_inherits WHERE inhrelid = ft.oid
+ AND inhparent NOT IN (SELECT partrelid FROM pg_partitioned_table)),
+
+ CASE relispartition
+ WHEN TRUE THEN
+ (SELECT inhparent FROM pg_inherits WHERE inhrelid = ft.oid)
+ ELSE
+ NULL
+ END AS partitioned_table,
+
+ pg_get_expr(relpartbound, ft.oid) AS partition_bound_expr, ]
+ %else
+ [ NULL AS partitioned_table, NULL AS partition_bound_expr, ]
+ %end
+
+ ({comment}) [ AS comment ]
+
+ [ FROM pg_class AS ft
+ LEFT JOIN pg_foreign_table AS _ft1 ON _ft1.ftrelid=ft.oid ]
+
+ %if ({pgsql-ver} >=f "10.0") %then
+ [ LEFT JOIN pg_partitioned_table AS pt ON pt.partrelid = ft.oid ]
+ %end
+
+ [ WHERE ft.relkind = 'f' ]
+
+ %if {last-sys-oid} %then
+ [ AND ft.oid ] {oid-filter-op} $sp {last-sys-oid}
+ %end
+
+ %if {not-ext-object} %then
+ [ AND ] ( {not-ext-object} )
+ %end
+
+ %if {filter-oids} %or {schema} %then
+ [ AND ]
+
+ %if {filter-oids} %then
+ [ ft.oid IN (] {filter-oids} )
+
+ %if {schema} %then
+ [ AND ]
+ %end
+ %end
+ %end
+ %end
+%end
diff --git a/assets/schemas/catalog/function.sch b/assets/schemas/catalog/function.sch
new file mode 100644
index 0000000000..2f493663ad
--- /dev/null
+++ b/assets/schemas/catalog/function.sch
@@ -0,0 +1,137 @@
+# Catalog queries 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 ({pgsql-ver} <=f "10.0") %then
+ %set {is-not-agg-proc} [pr.proisagg IS FALSE]
+ %set {window-func} [pr.proiswindow AS window_func_bool]
+%else
+ %set {is-not-agg-proc} [pr.prokind NOT IN ('a', 'p') ]
+ %set {window-func} [CASE pr.prokind WHEN 'w' THEN TRUE ELSE FALSE END AS window_func_bool]
+%end
+
+%if {list} %then
+ %if {use-signature} %then
+ %set {signature} [ ns.nspname || '.' || ]
+ %end
+
+ [SELECT pr.oid, pr.proname || '(' ||
+ CASE
+ WHEN array_length(pr.proargtypes, 1) = 0 THEN ''
+ ELSE
+ array_to_string(
+ (SELECT array_agg(
+ CASE ns.nspname
+ WHEN 'pg_catalog' then ''
+ ELSE ns.nspname || '.'
+ END || tp.typname )
+ FROM (SELECT unnest(proargtypes) AS oid FROM pg_proc WHERE oid = pr.oid) AS atp
+ LEFT JOIN pg_type AS tp ON tp.oid = atp.oid
+ LEFT JOIN pg_namespace AS ns ON ns.oid = tp.typnamespace),',')
+ END || ')' AS name,
+ ns.nspname AS parent, 'schema' AS parent_type, NULL AS extra_info
+ FROM pg_proc AS pr
+ LEFT JOIN pg_namespace AS ns ON pr.pronamespace = ns.oid ]
+
+ %if {schema} %then
+ [ WHERE ] {is-not-agg-proc} [ AND ns.nspname = ] '{schema}'
+ %else
+ [ WHERE ] {is-not-agg-proc}
+ %end
+
+ %if {last-sys-oid} %then
+ [ AND pr.oid ] {oid-filter-op} $sp {last-sys-oid}
+ %end
+
+ %if {not-ext-object} %then
+ [ AND ] ( {not-ext-object} )
+ %end
+
+ %if {name-filter} %then
+ [ AND ] ( {signature} [ pr.proname ~* ] E'{name-filter}' )
+ %end
+%else
+ %if {attribs} %then
+ [SELECT pr.oid,
+ pronamespace AS schema,
+ pr.proowner AS owner,
+ pr.proacl AS permission,
+ pr.proname AS name,
+ pr.prolang AS language,
+ pr.procost AS execution_cost,
+ pr.prorows AS row_amount,
+ array_to_string(pr.proconfig, '] $ds [', '') AS config_params, ]
+
+ {window-func},
+
+ [ pr.proretset AS returns_setof_bool,
+ pr.pronargs AS arg_count,
+ pr.pronargdefaults AS arg_def_count,
+ pr.prorettype AS return_type, ]
+
+ [ CASE
+ WHEN proallargtypes IS NOT NULL THEN proallargtypes
+ ELSE proargtypes::oid ] $ob $cb
+ [ END AS arg_types,
+
+ pr.proargmodes AS arg_modes,
+ pr.proargnames AS arg_names,
+ pg_get_expr(proargdefaults, 'pg_class'::regclass) AS arg_defaults,
+ pr.prosrc AS definition,
+ pr.probin AS library,
+
+ CASE
+ WHEN pr.prosecdef THEN 'SECURITY DEFINER'
+ ELSE 'SECURITY INVOKER'
+ END AS security_type,
+
+ CASE
+ WHEN pr.provolatile='v' THEN 'VOLATILE'
+ WHEN pr.provolatile='i' THEN 'IMMUTABLE'
+ ELSE 'STABLE'
+ END AS function_type,
+
+ CASE
+ WHEN pr.proisstrict THEN 'RETURNS NULL ON NULL INPUT'
+ ELSE 'CALLED ON NULL INPUT'
+ END AS behavior_type,
+
+ pr.proleakproof AS leakproof_bool,
+
+ CASE
+ WHEN pr.proparallel='u' THEN 'PARALLEL UNSAFE'
+ WHEN pr.proparallel='r' THEN 'PARALLEL RESTRICTED'
+ ELSE 'PARALLEL SAFE'
+ END AS parallel_type,
+
+ pr.protrftypes AS transform_types, ]
+
+ ({comment}) [ AS comment ]
+
+ [ FROM pg_proc AS pr ]
+
+ %if {schema} %then
+ [ LEFT JOIN pg_namespace AS ns ON pr.pronamespace = ns.oid ]
+ %end
+
+ [ WHERE ] {is-not-agg-proc}
+
+ %if {last-sys-oid} %then
+ [ AND pr.oid ] {oid-filter-op} $sp {last-sys-oid}
+ %end
+
+ %if {not-ext-object} %then
+ [ AND ] ( {not-ext-object} )
+ %end
+
+ %if {filter-oids} %or {schema} %then
+ %if {filter-oids} %then
+ [ AND pr.oid IN (] {filter-oids} )
+ %end
+
+ %if {schema} %then
+ [ AND ns.nspname = ] '{schema}'
+ %end
+ %end
+ %end
+%end
diff --git a/assets/schemas/catalog/index.sch b/assets/schemas/catalog/index.sch
new file mode 100644
index 0000000000..bc67aae3c3
--- /dev/null
+++ b/assets/schemas/catalog/index.sch
@@ -0,0 +1,147 @@
+# Catalog queries 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 {list} %then
+ %set {parent-name} [ ns.nspname || '.' || tb.relname ]
+
+ %if {use-signature} %then
+ %set {signature} {parent-name} [ || '.' || ]
+ %end
+
+ [SELECT id.indexrelid AS oid, cl.relname AS name, ] {parent-name} [ AS parent,
+ 'table' AS parent_type, NULL AS extra_info
+ FROM pg_index AS id
+ LEFT JOIN pg_class AS cl ON cl.oid = id.indexrelid
+ LEFT JOIN pg_class AS tb ON id.indrelid = tb.oid
+ LEFT JOIN pg_namespace AS ns ON ns.oid = tb.relnamespace ]
+
+ %if {schema} %then
+ [ WHERE nspname= ] '{schema}'
+
+ %if {table} %then
+ [ AND ((tb.relkind = 'r' OR tb.relkind = 'm' OR tb.relkind = 'p') AND tb.relname = ] '{table}' [)]
+ %end
+ %end
+
+ %if {last-sys-oid} %then
+ %if {schema} %then
+ [ AND ]
+ %else
+ [ WHERE ]
+ %end
+
+ [ id.indexrelid ] {oid-filter-op} $sp {last-sys-oid}
+ %end
+
+ %if %not {schema} %and %not {last-sys-oid} %then
+ [ WHERE ]
+ %else
+ [ AND ]
+ %end
+
+ %if ({pgsql-ver} >=f "10.0") %then
+ # cl.relispartition IS FALSE avoids retriving indexes created automatically in partition tables
+ [ cl.relispartition IS FALSE
+ AND (id.indisprimary IS FALSE AND id.indisexclusion IS FALSE)
+ AND ((SELECT count(oid) FROM pg_constraint WHERE conindid=id.indexrelid)=0) ]
+ %else
+ # This is just a place holder for the above clause
+ # because in version below 10 there is no relispartition field
+ [ TRUE ]
+ %end
+
+ %if {not-ext-object} %then
+ [ AND ]( {not-ext-object} )
+ %end
+
+ %if {name-filter} %then
+ [ AND ] ( {signature} [ cl.relname ~* ] E'{name-filter}' )
+ %end
+
+ %if {extra-condition} %then
+ [ AND ] ( {extra-condition} )
+ %end
+%else
+ %if {attribs} %then
+ [SELECT id.indexrelid AS oid, cl.relname AS name,
+ am.amname AS index_type, id.indrelid AS table,
+ id.indoption::int2] $ob $cb [ AS options, id.indisunique AS unique_bool,
+ indcollation::oid] $ob $cb [ AS collations,
+ id.indkey::oid] $ob $cb [ AS columns,
+ id.indclass::oid] $ob $cb [ AS opclasses,
+ pg_get_expr(indexprs, indrelid) AS expressions,
+ pg_get_expr(indpred, indrelid, true) predicate, ]
+
+ %if ({pgsql-ver} >=f "11.0") %then
+ [ id.indnkeyatts AS elements_count, ]
+ %else
+ [ id.indnatts AS elements_count, ]
+ %end
+
+ %if ({pgsql-ver} >=f "15.0") %then
+ [ id.indnullsnotdistinct AS nulls_not_distinct_bool, ]
+ %else
+ [ FALSE AS nulls_not_distinct_bool, ]
+ %end
+
+ ({comment}) [ AS comment ]
+
+ [
+ FROM pg_index AS id
+ LEFT JOIN pg_class AS cl ON cl.oid = id.indexrelid
+ LEFT JOIN pg_am AS am ON cl.relam = am.oid
+ ]
+
+ %if {schema} %then
+ [ LEFT JOIN pg_class AS tb ON id.indrelid = tb.oid
+ LEFT JOIN pg_namespace AS ns ON ns.oid = tb.relnamespace
+ WHERE ns.nspname= ] '{schema}'
+
+ %if {table} %then
+ [ AND ((tb.relkind = 'r' OR tb.relkind = 'm' OR tb.relkind = 'p') AND tb.relname = ] '{table}' [)]
+ %end
+ %end
+
+ %if {last-sys-oid} %then
+ %if {schema} %then
+ [ AND ]
+ %else
+ [ WHERE ]
+ %end
+
+ [ id.indexrelid ] {oid-filter-op} $sp {last-sys-oid}
+ %end
+
+ %if {filter-oids} %then
+ %if {schema} %or {last-sys-oid} %then
+ [ AND ]
+ %else
+ [ WHERE ]
+ %end
+
+ [ id.indexrelid IN (] {filter-oids} )
+ %end
+
+ %if %not {schema} %and %not {last-sys-oid} %and %not {filter-oids} %then
+ [ WHERE ]
+ %else
+ [ AND ]
+ %end
+
+ %if ({pgsql-ver} >=f "10.0") %then
+ # cl.relispartition IS FALSE avoids retriving indexes created automatically in partition tables
+ [ cl.relispartition IS FALSE
+ AND (id.indisprimary IS FALSE AND id.indisexclusion IS FALSE )
+ AND ((SELECT count(oid) FROM pg_constraint WHERE conindid=id.indexrelid)=0) ]
+ %else
+ # This is just a place holder for the above clause
+ # because in version below 10 there is no relispartition field
+ [ TRUE ]
+ %end
+
+ %if {not-ext-object} %then
+ [ AND ]( {not-ext-object} )
+ %end
+ %end
+%end
diff --git a/assets/schemas/catalog/language.sch b/assets/schemas/catalog/language.sch
new file mode 100644
index 0000000000..a4fffd801a
--- /dev/null
+++ b/assets/schemas/catalog/language.sch
@@ -0,0 +1,67 @@
+# Catalog queries for languages
+# CAUTION: Do not modify this file unless you know what you are doing.
+# Code generation can be broken if incorrect changes are made.
+
+%if {list} %then
+ [SELECT oid, lanname AS name, current_database() AS parent,
+ 'database' AS parent_type, NULL AS extra_info
+ FROM pg_language ]
+
+ %if {last-sys-oid} %then
+ [ WHERE oid ] {oid-filter-op} $sp {last-sys-oid}
+ %end
+
+ %if {not-ext-object} %then
+ %if {last-sys-oid} %then
+ [ AND ]
+ %else
+ [ WHERE ]
+ %end
+
+ ( {not-ext-object} )
+ %end
+
+ %if {name-filter} %then
+ %if {last-sys-oid} %or {not-ext-object} %then
+ [ AND ]
+ %else
+ [ WHERE ]
+ %end
+
+ ( [lanname ~* ] E'{name-filter}' )
+ %end
+%else
+ %if {attribs} %then
+ [SELECT oid, lanname AS name, lanpltrusted AS trusted_bool,
+ lanplcallfoid AS handler, laninline AS inline,
+ lanvalidator AS validator, lanacl AS permission, lanowner AS owner, ]
+
+ ({comment}) [ AS comment ]
+
+ [ FROM pg_language ]
+
+ %if {last-sys-oid} %then
+ [ WHERE oid ] {oid-filter-op} $sp {last-sys-oid}
+ %end
+
+ %if {not-ext-object} %then
+ %if {last-sys-oid} %then
+ [ AND ]
+ %else
+ [ WHERE ]
+ %end
+
+ ( {not-ext-object} )
+ %end
+
+ %if {filter-oids} %then
+ %if {last-sys-oid} %or {not-ext-object} %then
+ [ AND ]
+ %else
+ [ WHERE ]
+ %end
+
+ [ oid IN (] {filter-oids} )
+ %end
+ %end
+%end
diff --git a/assets/schemas/catalog/notextobject.sch b/assets/schemas/catalog/notextobject.sch
new file mode 100644
index 0000000000..dc3a9a16ea
--- /dev/null
+++ b/assets/schemas/catalog/notextobject.sch
@@ -0,0 +1,8 @@
+# Catalog query to check if the object was created by an exentsion
+# CAUTION: Do not modify this file unless you know what you are doing.
+# Code generation can be broken if incorrect changes are made.
+
+%if {ext-obj-oids} %then
+ {oid} [ NOT IN ( ] {ext-obj-oids} [) ]
+%end
+
diff --git a/assets/schemas/catalog/objcount.sch b/assets/schemas/catalog/objcount.sch
new file mode 100644
index 0000000000..ed82061ebe
--- /dev/null
+++ b/assets/schemas/catalog/objcount.sch
@@ -0,0 +1,10 @@
+# Catalog query to check the amount of objects in pg_class
+# CAUTION: Do not modify this file unless you know what you are doing.
+# Code generation can be broken if incorrect changes are made.
+
+[ SELECT count(oid) AS objcount FROM pg_class
+WHERE relkind IN ('r','i','S','v','m','c','f','p','I') ]
+
+%if {last-sys-oid} %then
+ [ AND oid > ] {last-sys-oid}
+%end
diff --git a/assets/schemas/catalog/opclass.sch b/assets/schemas/catalog/opclass.sch
new file mode 100644
index 0000000000..c7d0687175
--- /dev/null
+++ b/assets/schemas/catalog/opclass.sch
@@ -0,0 +1,107 @@
+# Catalog queries for operator class
+# CAUTION: Do not modify this file unless you know what you are doing.
+# Code generation can be broken if incorrect changes are made.
+
+%if {list} %then
+ %if {use-signature} %then
+ %set {signature} [ ns.nspname || '.' || ]
+ %end
+
+ [SELECT op.oid, opcname || ' ] $ob [' || am.amname || '] $cb [' AS name,
+ ns.nspname AS parent, 'schema' AS parent_type, NULL AS extra_info
+ FROM pg_opclass AS op
+ LEFT JOIN pg_namespace AS ns ON op.opcnamespace = ns.oid
+ LEFT JOIN pg_am AS am ON op.opcmethod = am.oid ]
+
+ %if {schema} %then
+ [ WHERE ns.nspname = ] '{schema}'
+ %end
+
+ %if {last-sys-oid} %then
+ %if {schema} %then
+ [ AND ]
+ %else
+ [ WHERE ]
+ %end
+
+ [ op.oid ] {oid-filter-op} $sp {last-sys-oid}
+ %end
+
+ %if {not-ext-object} %then
+ %if {last-sys-oid} %or {schema} %then
+ [ AND ]
+ %else
+ [ WHERE ]
+ %end
+
+ ( {not-ext-object} )
+ %end
+
+ %if {name-filter} %then
+ %if {last-sys-oid} %or {schema} %or {not-ext-object} %then
+ [ AND ]
+ %else
+ [ WHERE ]
+ %end
+
+ ( {signature} [ op.opcname ~* ] E'{name-filter}' )
+ %end
+%else
+ %if {attribs} %then
+ [SELECT op.oid, op.opcname AS name, op.opcnamespace AS schema, op.opcowner AS owner,
+ op.opcfamily AS family, op.opcintype AS type, op.opcdefault AS default_bool,
+ op.opckeytype AS storage, am.amname AS index_type, ]
+
+ [(SELECT array_agg(amopstrategy::text || ':' || amopopr::text || ':' || amopsortfamily::text)
+ FROM pg_amop AS ap WHERE ap.amopfamily=op.opcfamily AND ap.amopmethod=am.oid) AS operator, ]
+
+ [(SELECT array_agg(amprocnum::text || ':' || amproc::oid::text)
+ FROM pg_amproc AS _ap1 WHERE _ap1.amprocfamily=op.opcfamily) AS function, ]
+
+ ({comment}) [ AS comment ]
+
+
+ [ FROM pg_opclass AS op
+ LEFT JOIN pg_am AS am ON op.opcmethod = am.oid ]
+
+ %if {schema} %then
+ [ LEFT JOIN pg_namespace AS ns ON op.opcnamespace = ns.oid ]
+ %end
+
+ %if {filter-oids} %or {schema} %then
+ [ WHERE ]
+
+ %if {filter-oids} %then
+ [ op.oid IN (] {filter-oids} )
+
+ %if {schema} %then
+ [ AND ]
+ %end
+ %end
+
+ %if {schema} %then
+ [ ns.nspname = ] '{schema}'
+ %end
+ %end
+
+ %if {last-sys-oid} %then
+ %if {schema} %or {filter-oids} %then
+ [ AND ]
+ %else
+ [ WHERE ]
+ %end
+
+ [ op.oid ] {oid-filter-op} $sp {last-sys-oid}
+ %end
+
+ %if {not-ext-object} %then
+ %if {last-sys-oid} %or {schema} %or {filter-oids} %then
+ [ AND ]
+ %else
+ [ WHERE ]
+ %end
+
+ ( {not-ext-object} )
+ %end
+ %end
+%end
diff --git a/assets/schemas/catalog/operator.sch b/assets/schemas/catalog/operator.sch
new file mode 100644
index 0000000000..8a885a513e
--- /dev/null
+++ b/assets/schemas/catalog/operator.sch
@@ -0,0 +1,110 @@
+# Catalog queries 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.
+
+%if {list} %then
+ %if {use-signature} %then
+ %set {signature} [ ns.nspname || '.' || ]
+ %end
+
+ [SELECT op.oid, oprname || '(' ||
+
+ CASE
+ WHEN oprleft::char = '0' THEN 'NONE'
+ ELSE
+ (SELECT
+ CASE _ns.nspname
+ WHEN 'pg_catalog' THEN ''
+ ELSE _ns.nspname || '.'
+ END || tp.typname
+ FROM pg_type AS tp
+ LEFT JOIN pg_namespace AS _ns ON _ns.oid = tp.typnamespace
+ WHERE tp.oid = op.oprleft)
+ END
+
+ || ',' ||
+
+ CASE
+ WHEN oprright::char = '0' THEN 'NONE'
+ ELSE
+ (SELECT
+ CASE _ns.nspname
+ WHEN 'pg_catalog' THEN ''
+ ELSE _ns.nspname || '.'
+ END || tp.typname
+ FROM pg_type AS tp
+ LEFT JOIN pg_namespace AS _ns ON _ns.oid = tp.typnamespace
+ WHERE tp.oid = op.oprright)
+ END
+
+ || ')' AS name,
+
+ ns.nspname AS parent, 'schema' AS parent_type, NULL AS extra_info
+
+ FROM pg_operator AS op
+ LEFT JOIN pg_namespace AS ns ON op.oprnamespace = ns.oid ]
+
+ %if {schema} %then
+ [ WHERE oprcode > 0 AND ns.nspname = ] '{schema}'
+ %else
+ [ WHERE oprcode > 0 ]
+ %end
+
+ %if {last-sys-oid} %then
+ [ AND op.oid ] {oid-filter-op} $sp {last-sys-oid}
+ %end
+
+ %if {not-ext-object} %then
+ [ AND ] ( {not-ext-object} )
+ %end
+
+ %if {name-filter} %then
+ [ AND ] ( {signature} [ op.oprname ~* ] E'{name-filter}' )
+ %end
+%else
+ %if {attribs} %then
+ [SELECT op.oid, op.oprname AS name, op.oprnamespace AS schema, op.oprowner AS owner,
+ op.oprcanmerge AS merges_bool, op.oprcanhash AS hashes_bool, op.oprleft AS left_type,
+ op.oprright AS right_type, op.oprcom AS commutator_op,
+ op.oprrest::oid AS restriction, op.oprjoin::oid AS "join",
+ op.oprcode::oid AS operfunc, op.oprnegate AS negator_op, ]
+
+ # This case statement selects the correct negator operator for the current operator
+ # [ CASE
+ # WHEN op.oprnegate > 0 THEN
+ # (SELECT _op2.oid FROM pg_operator AS _op1
+ # LEFT JOIN pg_operator AS _op2 ON _op1.oprname=_op2.oprname AND _op1.oprnamespace=_op2.oprnamespace
+ # WHERE _op1.oid=op.oprnegate AND _op2.oprcode > 0
+ # AND _op2.oprnegate=0 AND _op2.oprcom=0 AND _op2.oprrest=0 AND _op2.oprjoin=0
+ # AND ((_op2.oprleft > 0 AND _op2.oprright=0) OR (_op2.oprleft=0 AND _op2.oprright > 0)))
+ # ELSE 0
+ # END
+ # AS negator_op, ]
+
+ ({comment}) [ AS comment ]
+
+ [ FROM pg_operator AS op ]
+
+ %if {schema} %then
+ [ LEFT JOIN pg_namespace AS ns ON op.oprnamespace = ns.oid ]
+ %end
+
+ [ WHERE oprcode > 0 ]
+
+ %if {filter-oids} %then
+ [ AND op.oid IN (] {filter-oids} )
+ %end
+
+ %if {schema} %then
+ [ AND ns.nspname = ] '{schema}'
+ %end
+
+ %if {last-sys-oid} %then
+ [ AND op.oid ] {oid-filter-op} $sp {last-sys-oid}
+ %end
+
+ %if {not-ext-object} %then
+ [ AND (] {not-ext-object} )
+ %end
+ %end
+%end
diff --git a/assets/schemas/catalog/opfamily.sch b/assets/schemas/catalog/opfamily.sch
new file mode 100644
index 0000000000..038475772e
--- /dev/null
+++ b/assets/schemas/catalog/opfamily.sch
@@ -0,0 +1,100 @@
+# Catalog queries 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.
+
+%if {list} %then
+ %if {use-signature} %then
+ %set {signature} [ ns.nspname || '.' || ]
+ %end
+
+ [SELECT op.oid, op.opfname || ' ] $ob [' || am.amname || '] $cb [' AS name,
+ ns.nspname AS parent, 'schema' AS parent_type, NULL AS extra_info
+ FROM pg_opfamily AS op
+ LEFT JOIN pg_namespace AS ns ON op.opfnamespace = ns.oid
+ LEFT JOIN pg_am AS am ON op.opfmethod = am.oid ]
+
+ %if {schema} %then
+ [ WHERE ns.nspname = ] '{schema}'
+ %end
+
+ %if {last-sys-oid} %then
+ %if {schema} %then
+ [ AND ]
+ %else
+ [ WHERE ]
+ %end
+
+ [ op.oid ] {oid-filter-op} $sp {last-sys-oid}
+ %end
+
+ %if {not-ext-object} %then
+ %if {last-sys-oid} %or {schema} %then
+ [ AND ]
+ %else
+ [ WHERE ]
+ %end
+
+ ( {not-ext-object} )
+ %end
+
+ %if {name-filter} %then
+ %if {last-sys-oid} %or {schema} %or {not-ext-object} %then
+ [ AND ]
+ %else
+ [ WHERE ]
+ %end
+
+ ( {signature} [ op.opfname ~* ] E'{name-filter}' )
+ %end
+%else
+ %if {attribs} %then
+ [ SELECT op.oid, op.opfname AS name, am.amname AS index_type,
+ op.opfowner AS owner, op.opfnamespace AS schema, ]
+
+ ({comment}) [ AS comment ]
+
+ [ FROM pg_opfamily AS op
+ LEFT JOIN pg_am AS am ON op.opfmethod = am.oid ]
+
+ %if {schema} %then
+ [ LEFT JOIN pg_namespace AS ns ON op.opfnamespace = ns.oid ]
+ %end
+
+ %if {filter-oids} %or {schema} %then
+ [ WHERE ]
+
+ %if {filter-oids} %then
+ [ op.oid IN (] {filter-oids} )
+
+ %if {schema} %then
+ [ AND ]
+ %end
+ %end
+
+ %if {schema} %then
+ [ ns.nspname = ] '{schema}'
+ %end
+ %end
+
+
+ %if {last-sys-oid} %then
+ %if {schema} %or {filter-oids} %then
+ [ AND ]
+ %else
+ [ WHERE ]
+ %end
+
+ [ op.oid ] {oid-filter-op} $sp {last-sys-oid}
+ %end
+
+ %if {not-ext-object} %then
+ %if {last-sys-oid} %or {schema} %or {filter-oids} %then
+ [ AND ]
+ %else
+ [ WHERE ]
+ %end
+
+ ( {not-ext-object} )
+ %end
+ %end
+%end
diff --git a/assets/schemas/catalog/policy.sch b/assets/schemas/catalog/policy.sch
new file mode 100644
index 0000000000..58736f95e5
--- /dev/null
+++ b/assets/schemas/catalog/policy.sch
@@ -0,0 +1,103 @@
+# Catalog queries 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.
+
+%if {list} %then
+ %set {parent-name} [ ns.nspname || '.' || tb.relname ]
+
+ %if {use-signature} %then
+ %set {signature} {parent-name} [ || '.' || ]
+ %end
+
+ [ SELECT pl.oid, polname AS name, ] {parent-name} [ AS parent, 'table' AS parent_type, NULL AS extra_info
+ FROM pg_policy AS pl
+ LEFT JOIN pg_class AS tb ON pl.polrelid = tb.oid
+ LEFT JOIN pg_namespace AS ns ON ns.oid = tb.relnamespace ]
+
+ %if {schema} %then
+ [ WHERE nspname= ] '{schema}'
+
+ %if {table} %then
+ [ AND tb.relkind='r' AND tb.relname=] '{table}'
+ %end
+
+ %if {last-sys-oid} %or {not-ext-object} %then
+ [ AND ]
+ %end
+ %else
+ %if {last-sys-oid} %or {not-ext-object} %or {name-filter} %or {extra-condition} %then
+ [ WHERE ]
+ %end
+ %end
+
+ %if {last-sys-oid} %then
+ [ pl.oid ] {oid-filter-op} $sp {last-sys-oid}
+ %end
+
+ %if {not-ext-object} %then
+ %if {last-sys-oid} %then
+ [ AND ]
+ %end
+
+ ( {not-ext-object} )
+ %end
+
+ %if {name-filter} %then
+ %if {last-sys-oid} %or {not-ext-object} %then
+ [ AND ]
+ %end
+
+ ( {signature} [ pl.polname ~* ] E'{name-filter}' )
+ %end
+
+ %if {extra-condition} %then
+ %if {last-sys-oid} %or {not-ext-object} %or {name-filter} %then
+ [ AND ]
+ %end
+
+ ( {extra-condition} )
+ %end
+%else
+ [SELECT pl.oid, pl.polname AS name, pl.polrelid AS table,
+ pl.polpermissive AS permissive_bool, pg_get_expr(pl.polqual, pl.polrelid, true) AS using_exp,
+ pg_get_expr(pl.polwithcheck, pl.polrelid, true) AS check_exp,
+
+ CASE pl.polcmd
+ WHEN '*' THEN 'ALL'
+ WHEN 'r' THEN 'SELECT'
+ WHEN 'a' THEN 'INSERT'
+ WHEN 'w' THEN 'UPDATE'
+ ELSE 'DELETE'
+ END AS command,
+
+ pl.polroles AS roles, ]
+
+ ({comment}) [ AS comment ]
+
+ [ FROM pg_policy AS pl ]
+
+ %if {last-sys-oid} %then
+ [ WHERE pl.oid ] {oid-filter-op} $sp {last-sys-oid}
+ %end
+
+ %if {filter-oids} %then
+ %if {last-sys-oid} %then
+ [ AND]
+ %else
+ [ WHERE ]
+ %end
+
+ [ pl.oid IN (] {filter-oids} )
+ %end
+
+ %if {not-ext-object} %then
+ %if {last-sys-oid} %or {filter-oids} %then
+ [ AND ]
+ %else
+ [ WHERE ]
+ %end
+
+ ( {not-ext-object} )
+ %end
+%end
+
diff --git a/assets/schemas/catalog/procedure.sch b/assets/schemas/catalog/procedure.sch
new file mode 100644
index 0000000000..b6ba77b917
--- /dev/null
+++ b/assets/schemas/catalog/procedure.sch
@@ -0,0 +1,102 @@
+# Catalog queries 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
+ %set {is-procedure} [pr.prokind = 'p']
+
+ %if {list} %then
+ %if {use-signature} %then
+ %set {signature} [ ns.nspname || '.' || ]
+ %end
+
+ [SELECT pr.oid, pr.proname || '(' ||
+ CASE
+ WHEN array_length(pr.proargtypes, 1) = 0 THEN ''
+ ELSE
+ array_to_string(
+ (SELECT array_agg(
+ CASE ns.nspname
+ WHEN 'pg_catalog' then ''
+ ELSE ns.nspname || '.'
+ END || tp.typname )
+ FROM (SELECT unnest(proargtypes) AS oid FROM pg_proc WHERE oid = pr.oid) AS atp
+ LEFT JOIN pg_type AS tp ON tp.oid = atp.oid
+ LEFT JOIN pg_namespace AS ns ON ns.oid = tp.typnamespace),',')
+ END || ')' AS name,
+ ns.nspname AS parent, 'schema' AS parent_type, NULL AS extra_info
+ FROM pg_proc AS pr
+ LEFT JOIN pg_namespace AS ns ON pr.pronamespace = ns.oid ]
+
+ %if {schema} %then
+ [ WHERE ] {is-procedure} [ AND ns.nspname = ] '{schema}'
+ %else
+ [ WHERE ] {is-procedure}
+ %end
+
+ %if {last-sys-oid} %then
+ [ AND pr.oid ] {oid-filter-op} $sp {last-sys-oid}
+ %end
+
+ %if {not-ext-object} %then
+ [ AND ] ( {not-ext-object} )
+ %end
+
+ %if {name-filter} %then
+ [ AND ] ( {signature} [ pr.proname ~* ] E'{name-filter}' )
+ %end
+ %else
+ %if {attribs} %then
+
+ [ SELECT pr.oid, pronamespace AS schema, pr.proowner AS owner,
+ pr.proacl AS permission, pr.proname AS name, pr.prolang AS language,
+ pr.pronargs AS arg_count, pr.pronargdefaults AS arg_def_count,
+ array_to_string(pr.proconfig, '] $ds [', '') AS config_params, ]
+
+ [ CASE
+ WHEN proallargtypes IS NOT NULL THEN proallargtypes
+ ELSE proargtypes::oid ] $ob $cb
+ [ END AS arg_types,
+
+ pr.proargmodes AS arg_modes,
+ pr.proargnames AS arg_names,
+ pg_get_expr(proargdefaults, 'pg_class'::regclass) AS arg_defaults,
+ pr.prosrc AS definition,
+ pr.probin AS library,
+ pr.protrftypes AS transform_types,
+
+ CASE
+ WHEN pr.prosecdef THEN 'SECURITY DEFINER'
+ ELSE 'SECURITY INVOKER'
+ END AS security_type, ]
+
+ ({comment}) [ AS comment ]
+
+ [ FROM pg_proc AS pr ]
+
+ %if {schema} %then
+ [ LEFT JOIN pg_namespace AS ns ON pr.pronamespace = ns.oid ]
+ %end
+
+ [ WHERE ] {is-procedure}
+
+ %if {last-sys-oid} %then
+ [ AND pr.oid ] {oid-filter-op} $sp {last-sys-oid}
+ %end
+
+ %if {not-ext-object} %then
+ [ AND ] ( {not-ext-object} )
+ %end
+
+ %if {filter-oids} %or {schema} %then
+ %if {filter-oids} %then
+ [ AND pr.oid IN (] {filter-oids} )
+ %end
+
+ %if {schema} %then
+ [ AND ns.nspname = ] '{schema}'
+ %end
+ %end
+ %end
+ %end
+%end
diff --git a/assets/schemas/catalog/role.sch b/assets/schemas/catalog/role.sch
new file mode 100644
index 0000000000..f4461e0318
--- /dev/null
+++ b/assets/schemas/catalog/role.sch
@@ -0,0 +1,62 @@
+# Catalog queries 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 {list} %then
+ [SELECT oid, rolname AS name, current_database() AS parent,
+ 'database' AS parent_type, NULL AS extra_info FROM pg_roles ]
+
+ %if {last-sys-oid} %then
+ [ WHERE oid ] {oid-filter-op} $sp {last-sys-oid}
+ %end
+
+ %if {name-filter} %then
+ %if {last-sys-oid} %then
+ [ AND ]
+ %else
+ [ WHERE ]
+ %end
+
+ ( [rolname ~* ] E'{name-filter}' )
+ %end
+%else
+ %if {attribs} %then
+ [ SELECT rl1.oid, rolname AS name, rolsuper AS superuser_bool, rolinherit AS inherit_bool,
+ rolcreaterole AS createrole_bool, rolcreatedb AS createdb_bool, rolcanlogin AS login_bool,
+ rolconnlimit AS connlimit, TRUE AS encrypted_bool, rolpassword AS password,
+
+ CASE
+ WHEN rolvaliduntil = 'infinity' THEN NULL
+ ELSE rolvaliduntil
+ END AS validity,
+
+ rolreplication AS replication_bool,
+ rolbypassrls AS bypassrls_bool,
+
+ (SELECT array_agg(rl.oid) AS member_roles FROM pg_auth_members AS am
+ LEFT JOIN pg_roles AS rl ON rl.oid=am.member
+ WHERE am.roleid=rl1.oid AND am.admin_option IS FALSE),
+
+ (SELECT array_agg(rl.oid) AS admin_roles FROM pg_auth_members AS am
+ LEFT JOIN pg_roles AS rl ON rl.oid=am.member
+ WHERE am.roleid=rl1.oid AND am.admin_option IS TRUE), ]
+
+ ({comment}) [ AS comment
+
+ FROM pg_roles AS rl1 ]
+
+ %if {last-sys-oid} %then
+ [ WHERE oid ] {oid-filter-op} $sp {last-sys-oid}
+ %end
+
+ %if {filter-oids} %then
+ %if {last-sys-oid} %then
+ [ AND ]
+ %else
+ [ WHERE ]
+ %end
+
+ [ oid IN (] {filter-oids} )
+ %end
+ %end
+%end
diff --git a/assets/schemas/catalog/rule.sch b/assets/schemas/catalog/rule.sch
new file mode 100644
index 0000000000..3ed2197a27
--- /dev/null
+++ b/assets/schemas/catalog/rule.sch
@@ -0,0 +1,148 @@
+# Catalog queries 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.
+
+%if {list} %then
+ %set {parent-name} [ ns.nspname || '.' || cl.relname ]
+
+ %if {use-signature} %then
+ %set {signature} {parent-name} [ || '.' || ]
+ %end
+
+ [SELECT rl.oid, rl.rulename AS name, ] {parent-name} [ AS parent,
+ 'table' AS parent_type, NULL AS extra_info
+ FROM ( SELECT rw.* ]
+
+ %if ({pgsql-ver} <=f "11.0") %then
+ [ , rw.oid ]
+ %end
+
+ [ FROM pg_rewrite AS rw
+ WHERE rw.ev_type <> '1'::"char"
+ ) AS rl
+ LEFT JOIN pg_class cl ON cl.oid = rl.ev_class AND cl.relkind IN ('r','v','m')
+ LEFT JOIN pg_namespace AS ns ON ns.oid = cl.relnamespace ]
+
+ %if {schema} %then
+ [ WHERE ns.nspname= ] '{schema}'
+
+ %if {table} %then
+ [ AND cl.relname=]'{table}'
+ %end
+ %end
+
+ %if {last-sys-oid} %then
+ %if {schema} %then
+ [ AND ]
+ %else
+ [ WHERE ]
+ %end
+
+ [ rl.oid ] {oid-filter-op} $sp {last-sys-oid}
+ %end
+
+ %if {not-ext-object} %then
+ %if %not {last-sys-oid} %and %not {schema} %then
+ [ WHERE ]
+ %else
+ [ AND ]
+ %end
+
+ ( {not-ext-object} )
+ %end
+
+ %if {name-filter} %then
+ %if %not {last-sys-oid} %and %not {schema} %and %not {not-ext-object} %then
+ [ WHERE ]
+ %else
+ [ AND ]
+ %end
+
+ ( {signature} [ rl.rulename ~* ] E'{name-filter}' )
+ %end
+
+ %if {extra-condition} %then
+ %if %not {last-sys-oid} %and %not {schema} %and %not {not-ext-object} %and %not {name-filter} %then
+ [ WHERE ]
+ %else
+ [ AND ]
+ %end
+
+ ( {extra-condition} )
+ %end
+%else
+ %if {attribs} %then
+ [SELECT rl.oid, rl.rulename AS name, cl.oid as table,
+ pg_get_ruledef(rl.oid) AS commands,
+ ds.description AS comment,
+ CASE
+ WHEN rl.is_instead IS TRUE THEN 'INSTEAD'
+ ELSE 'ALSO'
+ END exec_type,
+
+ CASE rl.ev_type
+ WHEN '1'::"char" THEN 'ON SELECT'::text
+ WHEN '2'::"char" THEN 'ON UPDATE'::text
+ WHEN '3'::"char" THEN 'ON INSERT'::text
+ WHEN '4'::"char" THEN 'ON DELETE'::text
+ ELSE NULL::text
+ END AS event_type,
+
+ CASE
+ WHEN cl.relkind = 'r' THEN 'table'
+ WHEN cl.relkind = 'v' THEN 'view'
+ WHEN cl.relkind = 'm' THEN 'view'
+ END AS table_type
+
+ FROM (SELECT rw.* ]
+
+ %if ({pgsql-ver} <=f "11.0") %then
+ [ , rw.oid ]
+ %end
+
+ [ FROM pg_rewrite AS rw
+ ) AS rl
+
+ LEFT JOIN pg_class AS cl ON cl.oid = rl.ev_class AND cl.relkind IN ('r','v','m')
+ LEFT JOIN pg_description ds ON ds.objoid = rl.oid ]
+
+ %if {schema} %then
+ [ LEFT JOIN pg_namespace AS ns ON ns.oid = cl.relnamespace
+ WHERE ns.nspname= ] '{schema}'
+
+ %if {table} %then
+ [ AND cl.relname=]'{table}'
+ %end
+ %end
+
+ %if {last-sys-oid} %then
+ %if {schema} %then
+ [ AND ]
+ %else
+ [ WHERE ]
+ %end
+
+ [ rl.oid ] {oid-filter-op} $sp {last-sys-oid}
+ %end
+
+ %if {filter-oids} %then
+ %if %not {last-sys-oid} %then
+ [ WHERE ]
+ %else
+ [ AND ]
+ %end
+
+ [ rl.oid IN (] {filter-oids} )
+ %end
+
+ %if {not-ext-object} %then
+ %if %not {last-sys-oid} %and %not {filter-oids} %and %not {schema} %then
+ [ WHERE ]
+ %else
+ [ AND ]
+ %end
+
+ ( {not-ext-object} )
+ %end
+ %end
+%end
diff --git a/assets/schemas/catalog/schema.sch b/assets/schemas/catalog/schema.sch
new file mode 100644
index 0000000000..e764e4ac21
--- /dev/null
+++ b/assets/schemas/catalog/schema.sch
@@ -0,0 +1,42 @@
+# Catalog queries 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 {list} %then
+ [SELECT oid, nspname AS name, current_database() AS parent, 'database' AS parent_type, NULL AS extra_info
+ FROM pg_namespace
+ WHERE (nspname NOT LIKE 'pg_temp%' AND nspname NOT LIKE 'pg_toast%') ]
+
+ %if {last-sys-oid} %then
+ [ AND ( oid ] {oid-filter-op} $sp {last-sys-oid} [ OR nspname = 'public' ) ]
+ %end
+
+ %if {not-ext-object} %then
+ [ AND ] ( {not-ext-object} )
+ %end
+
+ %if {name-filter} %then
+ [ AND ] ( [nspname ~* ] E'{name-filter}' )
+ %end
+%else
+ %if {attribs} %then
+ [SELECT oid, nspname AS name, nspacl AS permission, nspowner AS owner, ]
+
+ ({comment}) [ AS comment ]
+
+ [ FROM pg_namespace
+ WHERE (nspname NOT LIKE 'pg_temp%' AND nspname NOT LIKE 'pg_toast%') ]
+
+ %if {last-sys-oid} %then
+ [ AND (oid ] {oid-filter-op} $sp {last-sys-oid} [ OR nspname = 'public' ) ]
+ %end
+
+ %if {filter-oids} %then
+ [ AND oid IN (] {filter-oids} )
+ %end
+
+ %if {not-ext-object} %then
+ [ AND ] ( {not-ext-object} )
+ %end
+ %end
+%end
diff --git a/assets/schemas/catalog/sequence.sch b/assets/schemas/catalog/sequence.sch
new file mode 100644
index 0000000000..0b0b0c9326
--- /dev/null
+++ b/assets/schemas/catalog/sequence.sch
@@ -0,0 +1,96 @@
+# Catalog queries 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.
+
+%if {list} %then
+ %if {use-signature} %then
+ %set {signature} [ ns.nspname || '.' || ]
+ %end
+
+ [SELECT sq.oid, relname AS name, ns.nspname AS parent, 'schema' AS parent_type, NULL AS extra_info
+ FROM pg_class AS sq
+ LEFT JOIN pg_namespace AS ns ON sq.relnamespace = ns.oid ]
+
+ %if {schema} %then
+ [
+ WHERE relkind='S' AND ns.nspname = ] '{schema}'
+ %else
+ [ WHERE relkind='S']
+ %end
+
+ %if {last-sys-oid} %then
+ [ AND sq.oid ] {oid-filter-op} $sp {last-sys-oid}
+ %end
+
+ %if {not-ext-object} %then
+ [ AND ] ( {not-ext-object} )
+ %end
+
+ %if {name-filter} %then
+ [ AND ] ( {signature} [ sq.relname ~* ] E'{name-filter}' )
+ %end
+%else
+ %if {attribs} %then
+ #Creates a temporary function to retrieve the sequence attributes
+ [CREATE OR REPLACE FUNCTION pg_temp.__pgmodeler_tmp_get_seq_attribs(text,text)
+ RETURNS text
+ AS
+ $$
+ DECLARE
+ res record;
+ BEGIN ]
+
+ %if ({pgsql-ver} >=f "10.0") %then
+ [ EXECUTE 'SELECT s.seqstart AS start_value, s.seqmin AS min_value, s.seqmax AS max_value, ' ||
+ ' s.seqincrement AS increment_by, seqcache as cache_value, ' ||
+ ' CASE WHEN seqcycle IS FALSE THEN NULL ELSE seqcycle END AS is_cycled ' ||
+ ' FROM pg_sequence AS s ' ||
+ ' LEFT JOIN pg_class AS c ON s.seqrelid = c.oid ' ||
+ ' LEFT JOIN pg_namespace AS n ON n.oid = c.relnamespace ' ||
+ ' WHERE n.nspname = ''' || $1 ||''' AND c.relname = ''' || $2 ||''' LIMIT 1;' INTO res; ]
+ %else
+ [ EXECUTE 'SELECT start_value, min_value, max_value, increment_by, cache_value, ' ||
+ ' CASE WHEN is_cycled IS FALSE THEN NULL ' ||
+ ' ELSE is_cycled END FROM ' || '"' || $1 || '"' || '.' || '"' || $2 || '"' || ' LIMIT 1;' INTO res; ]
+ %end
+
+ [ RETURN replace(replace(res::text,'(','{'),')','}');
+ END
+ $$
+ LANGUAGE plpgsql; ]
+
+ [ SELECT sq.oid, sq.relname AS name, sq.relnamespace AS schema, sq.relowner AS owner,
+ (SELECT DISTINCT refobjid || ':' || refobjsubid FROM pg_depend WHERE classid = 'pg_class'::regclass::oid AND objid=sq.oid AND deptype in ('a', 'i')) AS owner_col,
+ (pg_temp.__pgmodeler_tmp_get_seq_attribs(ns.nspname, sq.relname)) AS attribute, ]
+
+ ({comment}) [ AS comment ]
+
+ [ FROM pg_class AS sq
+ LEFT JOIN pg_namespace AS ns ON ns.oid=sq.relnamespace
+ WHERE relkind='S' ]
+
+ %if {last-sys-oid} %then
+ [ AND sq.oid ] {oid-filter-op} $sp {last-sys-oid}
+ %end
+
+ %if {not-ext-object} %then
+ [ AND ] ( {not-ext-object} )
+ %end
+
+ %if {filter-oids} %or {schema} %then
+ [ AND ]
+
+ %if {filter-oids} %then
+ [ sq.oid IN (] {filter-oids} )
+
+ %if {schema} %then
+ [ AND ]
+ %end
+ %end
+
+ %if {schema} %then
+ [ ns.nspname= ] '{schema}'
+ %end
+ %end
+ %end
+%end
diff --git a/assets/schemas/catalog/server.sch b/assets/schemas/catalog/server.sch
new file mode 100644
index 0000000000..b7b24b3c99
--- /dev/null
+++ b/assets/schemas/catalog/server.sch
@@ -0,0 +1,26 @@
+# Catalog queries for server attributes
+# CAUTION: Do not modify this file unless you know what you are doing.
+# Code generation can be broken if incorrect changes are made.
+
+[SELECT name AS attribute, setting AS value FROM pg_settings WHERE name
+IN (
+'client_encoding',
+'config_file',
+'data_directory',
+'dynamic_library_path',
+'dynamic_shared_memory_type',
+'hba_file',
+'lc_collate',
+'lc_ctype',
+'listen_addresses',
+'max_connections',
+'port',
+'server_encoding',
+'ssl',
+'ssl_ca_file',
+'ssl_cert_file',
+'ssl_crl_file',
+'ssl_key_file',
+'password_encryption',
+'ident_file'
+);]
diff --git a/assets/schemas/catalog/table.sch b/assets/schemas/catalog/table.sch
new file mode 100644
index 0000000000..6411c90620
--- /dev/null
+++ b/assets/schemas/catalog/table.sch
@@ -0,0 +1,126 @@
+# Catalog queries 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.
+
+%if {list} %then
+ %if {use-signature} %then
+ %set {signature} [ ns.nspname || '.' || ]
+ %end
+
+ [ SELECT tb.oid, tb.relname AS name, ns.nspname AS parent, 'schema' AS parent_type, NULL AS extra_info
+ FROM pg_class AS tb
+ LEFT JOIN pg_namespace AS ns ON ns.oid=tb.relnamespace ]
+
+ %if {schema} %then
+ [ WHERE tb.relkind IN ('r','p') AND ns.nspname= ] '{schema}'
+ %else
+ [ WHERE tb.relkind IN ('r','p')]
+ %end
+
+ %if {last-sys-oid} %then
+ [ AND tb.oid ] {oid-filter-op} $sp {last-sys-oid}
+ %end
+
+ %if {not-ext-object} %then
+ [ AND ] ( {not-ext-object} )
+ %end
+
+ %if {name-filter} %then
+ [ AND ] ( {signature} [ tb.relname ~* ] E'{name-filter}' )
+ %end
+%else
+ %if {attribs} %then
+ [SELECT tb.oid, tb.relname AS name, tb.relnamespace AS schema, tb.relowner AS owner,
+ tb.reltablespace AS tablespace, tb.relacl AS permission, ]
+
+ %if ({pgsql-ver} =f "10.0") %then
+ [ (SELECT array_agg(inhparent) AS parents FROM pg_inherits WHERE inhrelid = tb.oid
+ AND inhparent NOT IN (SELECT partrelid FROM pg_partitioned_table)),
+
+ CASE relkind
+ WHEN 'p' THEN TRUE
+ ELSE FALSE
+ END AS is_partitioned_bool,
+
+ CASE relispartition
+ WHEN TRUE THEN
+ (SELECT inhparent FROM pg_inherits WHERE inhrelid = tb.oid)
+ ELSE
+ NULL
+ END AS partitioned_table,
+ pg_get_expr(relpartbound, tb.oid) AS partition_bound_expr, ]
+ %else
+ [NULL AS partitioned_table, NULL AS partition_bound_expr, ]
+ %end
+
+ ({comment}) [ AS comment ]
+
+ [ , st.n_tup_ins AS tuples_ins, st.n_tup_upd AS tuples_upd, st.n_tup_del AS tuples_del, st.n_live_tup AS row_amount,
+ st.n_dead_tup AS dead_rows_amount, st.last_vacuum, st.last_autovacuum, st.last_analyze, ]
+
+ %if ({pgsql-ver} >=f "10.0") %then
+ [ CASE partstrat
+ WHEN 'l' then 'LIST'
+ WHEN 'r' then 'RANGE'
+ WHEN 'h' then 'HASH'
+ ELSE NULL
+ END AS partitioning,
+ pg_get_expr(partexprs, partrelid) AS part_key_exprs,
+ partattrs::oid] $ob $cb [ AS part_key_cols,
+ partclass::oid] $ob $cb [ AS part_key_opcls,
+ partcollation::oid] $ob $cb [ AS part_key_colls ]
+ %else
+ [ NULL AS partitioning, NULL AS part_key_exprs,
+ NULL AS part_key_cols, NULL AS part_key_opcls,
+ NULL AS part_key_colls ]
+ %end
+
+ [ FROM pg_class AS tb
+ LEFT JOIN pg_tables AS _tb1 ON _tb1.tablename=tb.relname
+ LEFT JOIN pg_stat_all_tables AS st ON st.relid=tb.oid ]
+
+ %if ({pgsql-ver} >=f "10.0") %then
+ [ LEFT JOIN pg_partitioned_table AS pt ON pt.partrelid = tb.oid ]
+ %end
+
+ [ WHERE tb.relkind IN ('r','p') ]
+
+ %if {last-sys-oid} %then
+ [ AND tb.oid ] {oid-filter-op} $sp {last-sys-oid}
+ %end
+
+ %if {not-ext-object} %then
+ [ AND ] ( {not-ext-object} )
+ %end
+
+ %if {filter-oids} %or {schema} %then
+ [ AND ]
+
+ %if {filter-oids} %then
+ [ tb.oid IN (] {filter-oids} )
+
+ %if {schema} %then
+ [ AND ]
+ %end
+ %end
+
+ %if {schema} %then
+ [ _tb1.schemaname= ] '{schema}'
+ %end
+ %end
+ %end
+%end
diff --git a/assets/schemas/catalog/tablespace.sch b/assets/schemas/catalog/tablespace.sch
new file mode 100644
index 0000000000..4ba70566a4
--- /dev/null
+++ b/assets/schemas/catalog/tablespace.sch
@@ -0,0 +1,45 @@
+# Catalog queries 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.
+
+%if {list} %then
+ [SELECT oid, spcname AS name, current_database() AS parent, 'database' AS parent_type, NULL AS extra_info
+ FROM pg_tablespace ]
+
+ %if {last-sys-oid} %then
+ [ WHERE oid ] {oid-filter-op} $sp {last-sys-oid}
+ %end
+
+ %if {name-filter} %then
+ %if {last-sys-oid} %then
+ [ AND ]
+ %else
+ [ WHERE ]
+ %end
+
+ ( [spcname ~* ] E'{name-filter}' )
+ %end
+%else
+ %if {attribs} %then
+ [SELECT oid, spcname AS name, spcacl AS permission, spcowner AS owner,
+ pg_tablespace_location(oid) AS directory, ]
+
+ ({comment}) [ AS comment ]
+
+ [ FROM pg_tablespace ]
+
+ %if {last-sys-oid} %then
+ [ WHERE oid ] {oid-filter-op} $sp {last-sys-oid}
+ %end
+
+ %if {filter-oids} %then
+ %if {last-sys-oid} %then
+ [ AND ]
+ %else
+ [ WHERE ]
+ %end
+
+ [ oid IN (] {filter-oids} )
+ %end
+ %end
+%end
diff --git a/assets/schemas/catalog/template.sch b/assets/schemas/catalog/template.sch
new file mode 100644
index 0000000000..faac27c6fe
--- /dev/null
+++ b/assets/schemas/catalog/template.sch
@@ -0,0 +1,12 @@
+# Catalog queries for
+# CAUTION: Do not modify this file unless you know what you are doing.
+# Code generation can be broken if incorrect changes are made.
+
+%if {list} %then
+
+%else
+ %if {attribs} %then
+
+
+ %end
+%end
diff --git a/assets/schemas/catalog/transform.sch b/assets/schemas/catalog/transform.sch
new file mode 100644
index 0000000000..42022b4b4a
--- /dev/null
+++ b/assets/schemas/catalog/transform.sch
@@ -0,0 +1,70 @@
+# Catalog queries 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 "10.0") %then
+ %set {transf-name} [trftype::regtype::text || '_' || lg.lanname ]
+
+ %if {list} %then
+
+ [ SELECT tr.oid, ] {transf-name} [ AS name, current_database() AS parent, 'database' AS parent_type, NULL AS extra_info
+ FROM pg_transform AS tr
+ LEFT JOIN pg_language AS lg ON lg.oid = tr.trflang ]
+
+ %if {last-sys-oid} %or {not-ext-object} %or {name-filter} %then
+ [ WHERE ]
+
+ %if {last-sys-oid} %then
+ [ tr.oid ] {oid-filter-op} $sp {last-sys-oid}
+ %end
+
+ %if {not-ext-object} %then
+ %if {last-sys-oid} %then
+ [ AND ]
+ %end
+
+ ( {not-ext-object} )
+ %end
+
+ %if {name-filter} %then
+ %if {last-sys-oid} %or {not-ext-object} %then
+ [ AND ]
+ %end
+
+ ( {transf-name} [ ~* ] E'{name-filter}' )
+ %end
+ %end
+ %else
+ %if {attribs} %then
+
+ [ SELECT tr.oid, ] {transf-name} [ AS name, tr.trftype AS type, lg.oid AS language,
+ tr.trffromsql::regproc::oid AS fromsql, tr.trftosql::regproc::oid AS tosql
+ FROM pg_transform AS tr
+ LEFT JOIN pg_language AS lg ON lg.oid = tr.trflang ]
+
+ %if {last-sys-oid} %then
+ [ WHERE tr.oid ] {oid-filter-op} $sp {last-sys-oid}
+ %end
+
+ %if {filter-oids} %then
+ %if {last-sys-oid} %then
+ [ AND]
+ %else
+ [ WHERE ]
+ %end
+
+ [ tr.oid IN (] {filter-oids} )
+ %end
+
+ %if {not-ext-object} %then
+ %if {last-sys-oid} %or {filter-oids} %then
+ [ AND ]
+ %else
+ [ WHERE ]
+ %end
+
+ ( {not-ext-object} )
+ %end
+ %end
+ %end
+%end
diff --git a/assets/schemas/catalog/trigger.sch b/assets/schemas/catalog/trigger.sch
new file mode 100644
index 0000000000..d976a0578e
--- /dev/null
+++ b/assets/schemas/catalog/trigger.sch
@@ -0,0 +1,142 @@
+# Catalog queries for trigger
+# CAUTION: Do not modify this file unless you know what you are doing.
+# Code generation can be broken if incorrect changes are made.
+
+%if {list} %then
+ %set {parent-name} [ ns.nspname || '.' || tb.relname ]
+
+ %if {use-signature} %then
+ %set {signature} {parent-name} [ || '.' || ]
+ %end
+
+ [SELECT tg.oid, tgname AS name, ] {parent-name} [ AS parent, 'table' AS parent_type, NULL AS extra_info
+ FROM pg_trigger AS tg
+ LEFT JOIN pg_class AS tb ON tg.tgrelid = tb.oid AND relkind IN ('r','v','m','f','p')
+ LEFT JOIN pg_namespace AS ns ON ns.oid = tb.relnamespace ]
+
+ %if {schema} %then
+ [ WHERE ns.nspname= ] '{schema}'
+
+ %if {table} %then
+ [ AND tb.relname=]'{table}'
+ %end
+
+ [ AND ]
+ %else
+ [ WHERE ]
+ %end
+
+ [ tgisinternal IS FALSE ]
+
+
+ %if ({pgsql-ver} >=f "13.0") %then
+ [ AND tgparentid = 0 ]
+ %end
+
+ %if {last-sys-oid} %then
+ [ AND tg.oid ] {oid-filter-op} $sp {last-sys-oid}
+ %end
+
+ %if {not-ext-object} %then
+ [ AND ]( {not-ext-object} )
+ %end
+
+ %if {name-filter} %then
+ [ AND ] ( {signature} [ tgname ~* ] E'{name-filter}' )
+ %end
+
+ %if {extra-condition} %then
+ [ AND ] ( {extra-condition} )
+ %end
+%else
+ %if {attribs} %then
+ # pg_trigger.tgtype datails:
+ # bit 0 -> FOR EACH ROW [1] | STATEMENT [0]
+ # bit 1 -> AFTER [0] | BEFORE [1]
+ # bit 2 -> INSERT
+ # bit 3 -> DELETE
+ # bit 4 -> UPDATE
+ # bit 5 -> TRUNCATE
+ # bit 6 -> INTEAD OF [1] (only for views)
+ [ SELECT DISTINCT(tg.oid), tg.tgname AS name, tg.tgfoid AS trigger_func, tb.oid AS table,
+
+ CASE
+ WHEN tb.relkind = 'r' THEN 'table'
+ WHEN tb.relkind = 'f' THEN 'foreigntable'
+ WHEN tb.relkind = 'v' THEN 'view'
+ WHEN tb.relkind = 'm' THEN 'view'
+ WHEN tb.relkind = 'p' THEN 'table'
+ END AS table_type, ]
+
+ #Convert the arguments from bytea to a string array. The last element is always empty and can be discarded
+ [ encode(tg.tgargs,'escape') AS arguments,
+
+ it.action_condition AS condition,
+ (B'0000001'::integer & tgtype = 1) AS per_line_bool,
+ (B'0000100'::integer & tgtype = 4) AS ins_event_bool,
+ (B'0001000'::integer & tgtype = 8) AS del_event_bool,
+ (B'0010000'::integer & tgtype = 16) AS upd_event_bool,
+ (B'0100000'::integer & tgtype = 32) AS trunc_event_bool,
+ tg.tgdeferrable AS deferrable_bool,
+ (tg.tgconstraint > 0) AS constraint_bool,
+
+ CASE
+ WHEN B'0000010'::integer & tgtype = 2 THEN 'BEFORE'
+ WHEN B'1000000'::integer & tgtype = 64 THEN 'INSTEAD OF'
+ ELSE 'AFTER'
+ END AS firing_type,
+
+ CASE tg.tginitdeferred
+ WHEN TRUE THEN 'INITIALLY DEFERRED'
+ ELSE 'INITIALLY IMMEDIATE'
+ END AS defer_type,
+
+ CASE
+ WHEN (tg.tgconstraint > 0) THEN
+ regexp_replace(regexp_replace(pg_get_triggerdef(tg.oid), '(.)+((INSERT|DELETE|UPDATE)|( OF))', ''), '( ON)(.)*','')
+ ELSE NULL
+ END AS columns, ]
+
+ %if ({pgsql-ver} >=f "10.0") %then
+ [ tgoldtable AS old_table_name, tgnewtable AS new_table_name, ]
+ %else
+ [ NULL AS old_table_name, NULL AS new_table_name, ]
+ %end
+
+ ({comment}) [ AS comment ]
+
+ [ FROM pg_trigger AS tg
+ LEFT JOIN pg_constraint AS cs ON tg.tgconstraint = cs.oid
+ LEFT JOIN pg_class AS tb ON tg.tgrelid = tb.oid
+ LEFT JOIN pg_namespace AS ns ON ns.oid = tb.relnamespace
+ LEFT JOIN information_schema.triggers AS it ON
+ it.trigger_schema=ns.nspname AND
+ it.trigger_name=tg.tgname AND
+ it.event_object_table=tb.relname
+ WHERE tg.tgisinternal IS FALSE ]
+
+ %if ({pgsql-ver} >=f "13.0") %then
+ [ AND tgparentid = 0 ]
+ %end
+
+ %if {schema} %then
+ [ AND ns.nspname= ] '{schema}'
+
+ %if {table} %then
+ [ AND tb.relname=]'{table}'
+ %end
+ %end
+
+ %if {last-sys-oid} %then
+ [ AND tg.oid ] {oid-filter-op} $sp {last-sys-oid}
+ %end
+
+ %if {filter-oids} %then
+ [ AND tg.oid IN (] {filter-oids} )
+ %end
+
+ %if {not-ext-object} %then
+ [ AND ]( {not-ext-object} )
+ %end
+ %end
+%end
diff --git a/assets/schemas/catalog/usermapping.sch b/assets/schemas/catalog/usermapping.sch
new file mode 100644
index 0000000000..0ac760401e
--- /dev/null
+++ b/assets/schemas/catalog/usermapping.sch
@@ -0,0 +1,65 @@
+# Catalog queries 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.
+
+%if {list} %then
+ %set {usermap-name} [um.usename || '@' || um.srvname]
+
+ [ SELECT um.umid AS oid, ] {usermap-name} [ AS name,
+ current_database() AS parent, 'database' AS parent_type, NULL AS extra_info
+ FROM pg_user_mappings AS um ]
+
+ %if {last-sys-oid} %or {not-ext-object} %or {name-filter} %then
+ [ WHERE ]
+
+ %if {last-sys-oid} %then
+ [ um.umid ] {oid-filter-op} $sp {last-sys-oid}
+ %end
+
+ %if {not-ext-object} %then
+ %if {last-sys-oid} %then
+ [ AND ]
+ %end
+
+ ( {not-ext-object} )
+ %end
+
+ %if {name-filter} %then
+ %if {last-sys-oid} %or {not-ext-object} %then
+ [ AND ]
+ %end
+
+ ( {usermap-name} [ ~* ] E'{name-filter}' )
+ %end
+ %end
+%else
+ %if {attribs} %then
+ [SELECT umid AS oid, usename || '@' || srvname AS name, um.srvid AS server,
+ umuser AS owner, umoptions AS options
+ FROM pg_user_mappings AS um ]
+
+ %if {last-sys-oid} %then
+ [ WHERE umid ] {oid-filter-op} $sp {last-sys-oid}
+ %end
+
+ %if {not-ext-object} %then
+ %if {last-sys-oid} %then
+ [ AND ]
+ %else
+ [ WHERE ]
+ %end
+
+ ( {not-ext-object} )
+ %end
+
+ %if {filter-oids} %then
+ %if {last-sys-oid} %or {not-ext-object} %then
+ [ AND ]
+ %else
+ [ WHERE ]
+ %end
+
+ [ umid IN (] {filter-oids} )
+ %end
+ %end
+%end
diff --git a/assets/schemas/catalog/usertype.sch b/assets/schemas/catalog/usertype.sch
new file mode 100644
index 0000000000..456381093a
--- /dev/null
+++ b/assets/schemas/catalog/usertype.sch
@@ -0,0 +1,177 @@
+# Catalog queries 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.
+
+%if {list} %then
+ %if {use-signature} %then
+ %set {signature} [ ns.nspname || '.' || ]
+ %end
+
+ [SELECT tp.oid, replace(replace(tp.oid::regtype::text,'"', ''), ns.nspname || '.', '') AS name,
+ ns.nspname AS parent, 'schema' AS parent_type, NULL AS extra_info
+ FROM pg_type AS tp
+ LEFT JOIN pg_namespace AS ns ON tp.typnamespace = ns.oid ]
+
+ %if {schema} %then
+ [ WHERE ns.nspname = ] '{schema}' [ AND ]
+ %else
+ [ WHERE ]
+ %end
+
+ [ (typtype IN ('p','b','c','e','r') AND (typname = 'pg_lsn' OR typname NOT LIKE 'pg_%')) ]
+
+ #Excluding types related to tables/views/sequeces/materialized views/foreign tables
+ %if {filter-tab-types} %then
+ [ AND (SELECT count(oid) FROM pg_class WHERE relname=typname AND relkind IN ('r','S','v','m','p','f'))=0 ]
+ %end
+
+ %if {exc-builtin-arrays} %then
+ #The tp.typtype='p' indicates to include pseudo-type even if they are an array construction
+ [ AND (tp.typtype='p' OR tp.typarray > 0) ]
+ %end
+
+ %if {last-sys-oid} %then
+ [ AND tp.oid ] {oid-filter-op} $sp {last-sys-oid}
+ %end
+
+ %if {not-ext-object} %then
+ [ AND ] ( {not-ext-object} )
+ %end
+
+ %if {name-filter} %then
+ [ AND ] ( {signature} [ tp.typname ~* ] E'{name-filter}' )
+ %end
+%else
+ %if {attribs} %then
+ [SELECT tp.oid, replace(replace(tp.oid::regtype::text,'"', ''), ns.nspname || '.', '') AS name, tp.typnamespace AS schema, tp.typowner AS owner, ]
+
+ # Create a bool column that indicates if the type is a extension child object
+ [(SELECT CASE WHEN count(objid) > 0 THEN true ELSE false END
+ FROM pg_depend
+ WHERE deptype = 'e' AND
+ classid::regclass::text = 'pg_type' AND
+ objid = tp.oid) AS is_ext_type_bool],
+
+ #Retrieve the OID for table/view/sequence that generates the composite type
+ [
+ CASE
+ WHEN cl.relkind = 'r' THEN 'table'
+ WHEN cl.relkind = 'S' THEN 'sequence'
+ WHEN cl.relkind = 'v' THEN 'view'
+ WHEN cl.relkind = 'm' THEN 'view'
+ WHEN cl.relkind = 'p' THEN 'table'
+ WHEN cl.relkind = 'f' THEN 'foreigntable'
+ END AS type_class, tp.typrelid AS object_id,
+
+ tp.typacl AS permission, tp.typcollation AS collation,
+
+ CASE
+ WHEN typtype = 'e' THEN 'enumeration'
+ WHEN typtype = 'b' THEN 'base'
+ WHEN typtype = 'c' THEN 'composite'
+ WHEN typtype = 'r' THEN 'range'
+ WHEN typtype = 'd' THEN 'domain'
+ WHEN typtype = 'p' THEN 'pseudo'
+ END AS configuration, ]
+
+ # Retrieve the enumaration labels (is null when the type is not an enumeration)
+ [ CASE WHEN typtype = 'e' THEN
+ (SELECT array_to_string(array_agg(enumlabel),'] $ds [', '')
+ FROM pg_enum WHERE enumtypid=tp.oid)
+ END AS labels,
+
+ ta.typeattrib, ]
+
+ # Retrieve the range type attributes (is null when the type is not a range) (pgsql >= 9.2)
+
+ [ CASE WHEN typtype = 'r' THEN (SELECT string_to_array(rngsubtype||':'||rngcollation||':'||rngsubopc::oid||':'||
+ rngcanonical::oid||':'||rngsubdiff::oid, ':')
+ FROM pg_range WHERE rngtypid=tp.oid)
+ END AS range_attribs,
+
+ tp.typinput::oid AS input, tp.typoutput::oid AS output, tp.typreceive::oid AS receive, tp.typsend::oid AS send,
+ tp.typmodin::oid AS tpmodin, tp.typmodout::oid AS tpmodout, tp.typanalyze::oid AS analyze,
+ tp.typlen AS internal_length, tp.typbyval AS by_value_bool,
+
+ CASE tp.typalign
+ WHEN 'i' THEN 'integer'
+ WHEN 'c' THEN 'char'
+ WHEN 's' THEN 'smallint'
+ ELSE 'double precision'
+ END AS alignment,
+
+ CASE tp.typstorage
+ WHEN 'p' THEN 'plain'
+ WHEN 'm' THEN 'main'
+ WHEN 'x' THEN 'extended'
+ ELSE 'external'
+ END AS storage,
+
+ tp.typdefault AS default_value, tp.typelem AS element,
+ tp.typdelim AS delimiter, tp.typispreferred AS preferred_bool,
+ tp.typcategory AS category,
+
+ CASE
+ WHEN tp.typcollation <> 0 THEN TRUE
+ ELSE FALSE
+ END AS collatable_bool, ]
+
+ ({comment}) [ AS comment ]
+
+ [ FROM pg_type AS tp
+ LEFT JOIN pg_class AS cl ON cl.oid = tp.typrelid
+ LEFT JOIN pg_namespace AS ns ON tp.typnamespace = ns.oid ]
+
+ # Retrieving composite type attributes using lateral join on 9.3+ (way more performatic)
+ [ LEFT JOIN LATERAl (
+ SELECT array_agg(
+ attname
+ || ':'
+ || _tp.oid
+ || ':'
+ || attcollation
+ ) AS typeattrib
+ FROM pg_attribute AS at
+ JOIN pg_type AS _tp on _tp.oid = at.atttypid
+ JOIN pg_namespace AS ns ON ns.oid = _tp.typnamespace
+ WHERE at.attrelid = cl.oid
+ ) ta ON (TRUE) ]
+
+ #Excluding types related to tables/views/sequeces
+ [ WHERE typtype IN ('p','b','c','e','r', 'd') AND (typname = 'pg_lsn' OR typname NOT LIKE 'pg_%') ]
+
+ #Excluding types related to tables/views/sequeces/materialized views
+ %if {filter-tab-types} %then
+ [ AND (SELECT count(oid) FROM pg_class WHERE relname=typname AND relkind IN ('r','S','v','m','p','f'))=0 ]
+ %end
+
+ %if {exc-builtin-arrays} %then
+ #The tp.typtype='p' indicates to include pseudo-type even if they are an array construction
+ [ AND (tp.typtype='p' OR tp.typarray > 0) ]
+ %end
+
+ %if {last-sys-oid} %then
+ [ AND tp.oid ] {oid-filter-op} $sp {last-sys-oid}
+ %end
+
+ %if {not-ext-object} %then
+ [ AND ] ( {not-ext-object} )
+ %end
+
+ %if {filter-oids} %or {schema} %then
+ [ AND ]
+
+ %if {filter-oids} %then
+ [ tp.oid IN (] {filter-oids} )
+
+ %if {schema} %then
+ [ AND ]
+ %end
+ %end
+
+ %if {schema} %then
+ [ ns.nspname = ] '{schema}'
+ %end
+ %end
+ %end
+%end
diff --git a/assets/schemas/catalog/view.sch b/assets/schemas/catalog/view.sch
new file mode 100644
index 0000000000..89fb63d931
--- /dev/null
+++ b/assets/schemas/catalog/view.sch
@@ -0,0 +1,88 @@
+# Catalog queries 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.
+
+%if {list} %then
+ %if {use-signature} %then
+ %set {signature} [ ns.nspname || '.' || ]
+ %end
+
+ [SELECT vw.oid, vw.relname AS name, ns.nspname AS parent, 'schema' AS parent_type, NULL AS extra_info
+ FROM pg_class AS vw
+ LEFT JOIN pg_namespace AS ns ON ns.oid=vw.relnamespace
+ WHERE vw.relkind IN ('v','m') ]
+
+ %if {schema} %then
+ [ AND ns.nspname= ] '{schema}'
+ %end
+
+ %if {last-sys-oid} %then
+ [ AND vw.oid ] {oid-filter-op} $sp {last-sys-oid}
+ %end
+
+ %if {not-ext-object} %then
+ [ AND ] ( {not-ext-object} )
+ %end
+
+ %if {name-filter} %then
+ [ AND ] ( {signature} [ vw.relname ~* ] E'{name-filter}' )
+ %end
+%else
+ %if {attribs} %then
+ [SELECT vw.oid, vw.relname AS name, vw.relnamespace AS schema, vw.relowner AS owner,
+ vw.reltablespace AS tablespace,
+ vw.relacl AS permission, pg_get_viewdef(vw.oid) AS definition, reloptions AS options, ]
+
+ # Subquery that retrieves the tables that the view refereces
+ # Extracted from the definition of the relation information_schema.view_table_usage
+ [(SELECT array_agg(DISTINCT dt.refobjid)
+ FROM pg_namespace AS nv,
+ pg_class AS v,
+ pg_depend AS dv,
+ pg_depend AS dt,
+ pg_class AS t,
+ pg_namespace AS nt
+ WHERE nv.oid = v.relnamespace AND v.relkind IN ('v','m')
+ AND v.oid = dv.refobjid AND dv.refclassid = 'pg_class'::regclass::oid
+ AND dv.classid = 'pg_rewrite'::regclass::oid AND dv.deptype = 'i'
+ AND dv.objid = dt.objid AND dv.refobjid <> dt.refobjid AND dt.classid = 'pg_rewrite'::regclass::oid
+ AND dt.refclassid = 'pg_class'::regclass::oid AND dt.refobjid = t.oid
+ AND t.relnamespace = nt.oid AND t.relkind IN ('r', 'p', 'f', 'v','m')
+ AND v.oid = ] vw.oid [) AS ref_tables, ]
+
+ [ CASE
+ WHEN vw.relkind='m' THEN TRUE
+ ELSE FALSE
+ END AS materialized_bool, ]
+
+ ({comment}) [ AS comment ]
+
+ [ FROM pg_class AS vw
+ LEFT JOIN pg_namespace AS ns ON ns.oid = vw.relnamespace
+ WHERE vw.relkind IN ('v','m') ]
+
+ %if {last-sys-oid} %then
+ [ AND vw.oid ] {oid-filter-op} $sp {last-sys-oid}
+ %end
+
+ %if {not-ext-object} %then
+ [ AND ] ( {not-ext-object} )
+ %end
+
+ %if {filter-oids} %or {schema} %then
+ [ AND ]
+
+ %if {filter-oids} %then
+ [ vw.oid IN (] {filter-oids} )
+
+ %if {schema} %then
+ [ AND ]
+ %end
+ %end
+
+ %if {schema} %then
+ [ ns.nspname= ] '{schema}'
+ %end
+ %end
+ %end
+%end
diff --git a/assets/schemas/datadict/html/column.sch b/assets/schemas/datadict/html/column.sch
new file mode 100644
index 0000000000..699836cffc
--- /dev/null
+++ b/assets/schemas/datadict/html/column.sch
@@ -0,0 +1,23 @@
+# 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.
+
+%set {spc} \n \s
+
+{spc}
+{spc} {name}
+{spc} {type}
+
+%if ({parent} != "view") %then
+ %if ({parent} == "table") %then
+ {spc} {pk-constr}
+ {spc} {fk-constr}
+ {spc} {uq-constr}
+ %end
+
+ {spc} {not-null}
+ {spc} {default-value}
+ {spc} {comment}
+%end
+
+{spc}
diff --git a/assets/schemas/datadict/html/constraint.sch b/assets/schemas/datadict/html/constraint.sch
new file mode 100644
index 0000000000..84983e812a
--- /dev/null
+++ b/assets/schemas/datadict/html/constraint.sch
@@ -0,0 +1,40 @@
+# 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.
+
+%set {spc} \n \s
+
+{spc}
+{spc} {name}
+{spc} {type}
+{spc} {columns}
+{spc}
+
+%if {ref-table} %then
+ %if {split} %then
+ {ref-table}
+ %else
+ {ref-table}
+ %end
+%end
+
+
+
+%if ({type} != "FOREIGN KEY") %then
+ {spc} \
+ {spc} \
+%else
+ {spc} {upd-action}
+ {spc} {del-action}
+%end
+
+{spc}
+
+%if ({type} == "CHECK") %then
+ {expression}
+%end
+
+
+
+{spc} {comment}
+{spc}
diff --git a/assets/schemas/datadict/html/datadict.sch b/assets/schemas/datadict/html/datadict.sch
new file mode 100644
index 0000000000..499e7be318
--- /dev/null
+++ b/assets/schemas/datadict/html/datadict.sch
@@ -0,0 +1,13 @@
+# 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.
+
+@include "header"
+
+%if %not {split} %and {datadictidx} %then
+ {datadictidx}
+%end
+
+{objects}
+
+@include "footer"
diff --git a/assets/schemas/datadict/html/datadictidx.sch b/assets/schemas/datadict/html/datadictidx.sch
new file mode 100644
index 0000000000..da51fe5e87
--- /dev/null
+++ b/assets/schemas/datadict/html/datadictidx.sch
@@ -0,0 +1,43 @@
+# 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.
+
+@include "header"
+
+%set {spc} \n \s
+
+\n [ Data dictionary index ]
+
+{spc}
+{spc} [Database: ] {name}
+
+%if {table} %then
+ {spc} Tables
+ {spc}
+ {spc}
+%end
+
+%if {foreigntable} %then
+ {spc} [Foreign tables]
+ {spc}
+ {spc}
+%end
+
+%if {view} %then
+ {spc} Views
+ {spc}
+ {spc}
+%end
+
+{spc}
+\n
+
+%if {split} %then
+ @include "footer"
+%end
diff --git a/assets/schemas/datadict/html/footer.sch b/assets/schemas/datadict/html/footer.sch
new file mode 100644
index 0000000000..6f7928b577
--- /dev/null
+++ b/assets/schemas/datadict/html/footer.sch
@@ -0,0 +1,13 @@
+# 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.
+
+\n
+\n