├── LICENSE ├── README.md ├── app.js ├── config ├── .gitignore └── config_sample.json └── source ├── .gitignore └── apex-diff.sql /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 OraOpenSource 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # APEX Diff (Alpha) 2 | The purpose of this project is to create a export of an APEX application in JSON format. Having the application export in JSON format will allow for easy diffs on different versions of an application 3 | 4 | _This project is still undergoing active development. As such, configuration and command line options may change._ 5 | 6 | # Pre-requisites 7 | 8 | ## SQLcl 9 | This projects requires that [SQLcl](http://www.oracle.com/technetwork/developer-tools/sql-developer/downloads/index.html) (_Oct 13, 2015 or above_) is installed. It is used for its ability to quickly output queries in JSON format and cursor support. 10 | 11 | Mac users can find additional information on how to install and configre SQLcl [here](http://www.talkapex.com/2015/04/installing-sqlcl.html). 12 | 13 | To find the current version of SQLcl, simply run SQLcl and it will be displayed. Minimum required version is `SQLcl: Release 4.2.0.15.286.1242 RC`. 14 | 15 | ## Node.js 16 | [Node.js](https://nodejs.org) version 0.12.x or greater is required. To find your current version run: 17 | 18 | ```bash 19 | node --version 20 | ``` 21 | 22 | # Running 23 | 24 | ## Download 25 | Either download this project from GitHub or clone it using git: 26 | `git clone https://github.com/OraOpenSource/apex-diff.git` 27 | 28 | _Note: This project may eventually be listed on npm for easy install._ 29 | 30 | ## Config 31 | Create a new (or copy `config_sample.json`) config file in the `config` folder called `config.json`. 32 | 33 | - `debug`: optional, boolean, default `false`. 34 | - If `true` will output each step of the process. 35 | - `rebuildTempFile` : optional, boolean, default `true`. 36 | - If `true`, the temp sql file will be re-generated. Unless upgrading APEX, it is not recommended to set this to `true` as it takes additional time to generate the temp sql file. 37 | - `sqlcl` : optional, string, default `sql`. 38 | - Command name (or full path to) SQLcl file. 39 | - `filters` : optional, array of regular expressions to remove objects from JSON file 40 | - The filter will be applied on both the `apex_view_name` and the `apex_view_name.column_name`. 41 | - Filters will be applied for all connections. 42 | - It is case insensitive. 43 | - Any `\` needs to be escaped with `\\` as the regular expression must also be a valid JSON string. 44 | - `filterGroups` : optional, JSON object, defining set of filterGroups. 45 | - Define a set of filters that can then be easily applied to specific connections 46 | - Each entry is a name/value pair. 47 | - Value is an array of filters that correspond to the filterGroup 48 | - `connections` : required, JSON object. 49 | - Name/value pair for each database connection or connection object 50 | - Connection Object: Use this for specific connection information for a connection 51 | - `connectionDetails`: required, database connection 52 | - `filters`: optional, array of filters (see `filters` above) 53 | - `filterGroups`: optional, array of list of `filterGroups` to apply 54 | 55 | 56 | Example: 57 | ```json 58 | { 59 | "sqlcl" : "sqlcl", 60 | "connections" : { 61 | "dev" : { 62 | "connectionDetails" : "giffy/giffy@localhost:11521/xe", 63 | "filters" : ["apex_application_pages"], 64 | "filterGroups" : ["updateInfo"] 65 | }, 66 | "prod" : "oos/oos@prod.oraopensource.com:1521/xe" 67 | }, 68 | "filters" : ["apex_application_lists"], 69 | "filterGroups" : { 70 | "updateInfo" : [".+\\..+_updated_.*"] 71 | } 72 | } 73 | ``` 74 | 75 | Example Explanation: 76 | 77 | - `filters`: For all connections data for `apex_application_lists` will be removed. 78 | - `connections`: They're two connections, `dev` and `prod`, 79 | - `dev`: 80 | - `filters`: Just for this connection, all entries for `apex_application_pages` will be removed. 81 | - `filterGroups`: Any filters defined in the `filterGroup` `updateInfo` will be applied. In this example, all column names that contain `_updated_` will be removed. 82 | - `filterGroups`: A filterGroup called `updateInfo` has been created and can be applied to individual connections. 83 | 84 | ### Filter Examples 85 | The following list is an example of filters that you can either add to a `filters` option or a `filterGroup`. _Note: the filters are already escaped for JSON use. If testing in a regexp tester ensure to unescape._ 86 | 87 | _All entries tagged with a `*` are recommended default filters._ 88 | 89 | | Filter | Description 90 | ------------- | ------------- | ------------- 91 | * | `^(.(?!page_id$))*_id$` | Exclude all id columns except for `page_id` 92 | * | `.+\\..+_updated_.*` | All columns that contain the name `_updated_` 93 | * | `.+\\.(items|buttons|display_sequence)` | Exclude all columns with .. 94 | | `apex_application_templates.reference_count` | Self Explanatory 95 | | `apex_application_auth` | All entries for the `apex_application_auth` view 96 | 97 | 98 | ## Run 99 | The Node.js application requires two parameters: 100 | 101 | - `connection name`: This is the name that is found in the `connections` object in `config.json`. 102 | - `app_id`: Application ID to generate the JSON for. 103 | 104 | Using the example configuration file above, the following example shows how to call the application: 105 | 106 | ```bash 107 | # Can call from any directory that you want f113.json in. 108 | node ~/Documents/GitHub/apex-diff/app.js dev 113 109 | ``` 110 | 111 | This will generate a prettified JSON file: `f113.json`. 112 | 113 | # Developers 114 | To help with future development, the following configuration can be added to `config.json`: 115 | 116 | - `dev` 117 | - `runSql`: `boolean` - If false, will skip over the SQL command. This is useful for testing JSON parsing. 118 | - `saveJson`: `boolean` - If false, will not save any changes to the JSON file. 119 | 120 | Example: 121 | ```json 122 | ... 123 | "dev" : { 124 | "runSql" : false, 125 | "saveJson" : true 126 | } 127 | ... 128 | ``` 129 | 130 | # Known Issues 131 | 132 | ## ORA-00600 Error 133 | If you get an `ORA-00600` error, it is a known bug that was fixed in Oracle 12.1.0.1 but re-appeared in 12.1.0.2: 134 | 135 | ```sql 136 | ORA-00600: internal error code, arguments: [qkeIsExprReferenced1], [], [], [], [], [], [], [], [], [], [], [] 137 | 00600. 00000 - "internal error code, arguments: [%s], [%s], [%s], [%s], [%s], [%s], [%s], [%s], [%s], [%s], [%s], [%s]" 138 | *Cause: This is the generic internal error number for Oracle program 139 | exceptions. It indicates that a process has encountered a low-level, 140 | unexpected condition. The first argument is the internal message 141 | number. This argument and the database version number are critical in 142 | identifying the root cause and the potential impact to your system. 143 | ``` 144 | 145 | If you get it, you my need to add the following to `apex-diff.sql`: 146 | 147 | ```sql 148 | alter system set "_projection_pushdown" = false scope=memory; 149 | ``` 150 | 151 | # Support 152 | If you're having issues the following are common problems that people have: 153 | 154 | - Make sure that your version of Node.js is up to date 155 | -------------------------------------------------------------------------------- /app.js: -------------------------------------------------------------------------------- 1 | /** 2 | * apex-diff 3 | * oraopensource.com 4 | * Project & license info: https://github.com/OraOpenSource/apex-diff 5 | */ 6 | var fs = require('fs'); 7 | var execSync = require('child_process').execSync; 8 | var extend = require('util')._extend; 9 | var path = require('path'); 10 | 11 | /** 12 | * Wrapper for console statement 13 | * 14 | */ 15 | function debug(){ 16 | if (options.debug) { 17 | log.apply(console.log, arguments ); 18 | } 19 | }//debug 20 | 21 | /** 22 | * Determines if a specific object should be deleted based on filter 23 | * 24 | * Returns true or false 25 | */ 26 | function filterObject(name){ 27 | var lReturn = false; 28 | 29 | for(var i in options.filtersRegExp){ 30 | if(options.filtersRegExp[i].test(name)){ 31 | lReturn = true; 32 | break; 33 | } 34 | }//for 35 | 36 | return lReturn; 37 | }//filterObject 38 | 39 | 40 | /** 41 | * Logs time from start of app.js 42 | */ 43 | function logTime(){ 44 | debug('Time:', (new Date() - timer.start)/1000 + 's'); 45 | } 46 | 47 | // TODO mdsouza: 48 | //http://stackoverflow.com/questions/1584370/how-to-merge-two-arrays-in-javascript-and-de-duplicate-items 49 | // Array.prototype.unique = function() { 50 | // var a = this.concat(); 51 | // for(var i=0; i