diff --git a/.gitignore b/.gitignore index 26ad46e..de11101 100644 --- a/.gitignore +++ b/.gitignore @@ -9,3 +9,6 @@ *.log target .metadata +/node_modules/ +/package-lock.json +/sf-jdbc-driver/src/test/java/com/ascendix/jdbc/salesforce/ForceDriverConnectivityTest.java diff --git a/README.md b/README.md index e7b17b6..38f276e 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,90 @@ -# sforce-jdbc [![Build Status](https://api.travis-ci.org/ascendix/salesforce-jdbc.svg?branch=master)](https://travis-ci.org/ascendix/salesforce-jdbc) [![Build Status](https://sonarcloud.io/api/project_badges/measure?project=com.ascendix.salesforce%3Asalesforce-jdbc&metric=alert_status)](https://sonarcloud.io/dashboard?id=com.ascendix.salesforce%3Asalesforce-jdbc) -Salesforce JDBC driver allows Java programs to connect to Salesforce data services using standard, database independent Java code. It is an open source JDBC driver written in Pure Java, and communicates over SOAP/HTTP(S) protocol. - +# sforce-jdbc +Salesforce JDBC driver allows Java programs to connect to a Salesforce data services using standard, database independent Java code. Is an open source JDBC driver written in Pure Java, +and communicates over SOAP/HTTP(S) protocol. The main purpose of the driver is to retrieve (only) data from Salesforce services for data analysis. Primary target platform for the driver usage is Eclipse BIRT engine. +The original Git repository for this driver is [here](https://github.com/ascendix/salesforce-jdbc) +However that version is not compatible with IntelliJ because of a lot of unsupported features: +* table names and columns names filtration is not implemented +* table name and column names are case sensitive +* no metadata provided for queries so IntelliJ just ignores the results returned by the driver + +These issues were fixed in the current version in this fork. + +[Watch the demo video](https://spuliaiev-sfdc.github.io/salesforce-jdbc/docs/SOQL-JDBC-IntelliJ-demo-264.mp4) + +[![Watch the demo video](https://spuliaiev-sfdc.github.io/salesforce-jdbc/docs/intelliJ.png)](https://spuliaiev-sfdc.github.io/salesforce-jdbc/docs/SOQL-JDBC-IntelliJ-demo-264.mp4) + ## Supported Salesforce and Java versions The current version of the driver should be compatible with **Salesforce Partner API version 39.0 and higher** and **Java 8**. ## Get the driver -Download the driver [here](https://github.com/ascendix/mvnrepo/raw/master/com/ascendix/salesforce/salesforce-jdbc/1.1-SNAPSHOT/salesforce-jdbc-1.1-20180403.104727-1-single.jar) +Download the driver JAR file: +1. Read-Only version 1.3.1 : from [here](https://spuliaiev-sfdc.github.io/salesforce-jdbc/deliverables/sf-jdbc-driver-1.3.1-SNAPSHOT-jar-with-dependencies.jar) +2. Write support version 1.4.0 : from [here](https://spuliaiev-sfdc.github.io/salesforce-jdbc/deliverables/sf-jdbc-driver-1.4.0-SNAPSHOT-jar-with-dependencies.jar) + +## Supported features +1. Queries support native SOQL; + ```SQL + select Id, Account.Name, Owner.id, Owner.Name from Account +``` +2. Nested queries are supported; +3. Write is supported as INSERT/UPDATE statements for version >= 1.4.0 + + The following functions are supported as part of calculation of new values: + * NOW() + * GETDATE() + + For Example: + ```SQL + INSERT INTO Account(Name, Phone) VALUES + ('Account01', '555-123-1111'), + ('Account02', '555-123-2222'); + + INSERT INTO Contact(FirstName, LastName, AccountId) + SELECT Name, Phone, Id + FROM Account + WHERE Name like 'Account0%'; + + UPDATE Contact SET LastName = 'Updated_Now_'+NOW() + WHERE AccountId IN ( + SELECT ID from Account where Phone = '555-123-1111' + ); +``` +4. Request caching support on local drive. Caching supports 2 modes: global and session. Global mode means that the cached result will be accessible for all system users for certain JVM session. Session cache mode works for each Salesforce connection session separately. Both modes cache stores request result while JVM still running but no longer than for 1 hour. The cache mode can be enabled with a prefix of SOQL query. + +How to use: + * Global cache mode: + ```SQL + CACHE GLOBAL SELECT Id, Name FROM Account + ``` + * Session cache mode + ```SQL + CACHE SESSION SELECT Id, Name FROM Account + ``` +5. Reconnect to other organization at the same host +```SQL +-- Postgres Notation +CONNECT USER admin@OtherOrg.com IDENTIFIED by "123456" + +-- Oracle Notation +CONNECT admin@OtherOrg.com/123456 + +-- Postgres Notation to a different host using secure connection (by default) +CONNECT + TO ap1.stmpa.stm.salesforce.com + USER admin@OtherOrg.com IDENTIFIED by "123456" + +-- Postgres Notation to a different host - local host using insecure connection +CONNECT + TO http://localhost:6109 + USER admin@OtherOrg.com IDENTIFIED by "123456" +``` +P.S. You need to use the machine host name in the connection url - not MyDomain org host name. + +## Limitations +1. ***Version < 1.4.0*** The driver is only for read-only purposes now. Insert/update/delete functionality is not implemented yet. +2. ***Version >= 1.4.0*** Limited support of INSERT/UPDATE operations ## With Maven @@ -30,8 +107,8 @@ Download the driver [here](https://github.com/ascendix/mvnrepo/raw/master/com/as ### Add dependency com.ascendix.salesforce - salesforce-jdbc - 1.1-20180403.104727-1 + sf-jdbc-driver + 1.4.0-SNAPSHOT @@ -68,24 +145,7 @@ jdbc:ascendix:salesforce://;sessionId=uniqueIdAssociatedWithTheSession | _https_ | Switch to use HTTP protocol instead of HTTPS
Default value is _true_| | _api_ | Api version to use.
Default value is _50.0_.
Set _test.salesforce.com_ value to use sandbox. | | _client_ | Client Id to use.
Default value is empty. | - - -## Supported features -1. Queries support native SOQL; -2. Nested queries are supported; -3. Request caching support on local drive. Caching supports 2 modes: global and session. Global mode means that the cached result will be accessible for all system users for certain JVM session. Session cache mode works for each Salesforce connection session separately. Both modes cache stores request result while JVM still running but no longer than for 1 hour. The cache mode can be enabled with a prefix of SOQL query. How to use: -======= - * Global cache mode: - ```SQL - CACHE GLOBAL SELECT Id, Name FROM Account - ``` - * Session cache mode - ```SQL - CACHE SESSION SELECT Id, Name FROM Account - ``` - -## Limitations -1. The driver is only for read-only purposes now. Insert/udate/delete functionality is not implemented yet. +| _insecurehttps_ | Allow invalid certificates for SSL. | ## Configure BIRT Studio to use Salesforce JDBC driver @@ -99,6 +159,67 @@ jdbc:ascendix:salesforce://;sessionId=uniqueIdAssociatedWithTheSession See how it's done in [Salesforce JDBC report sample](docs/birt/Salesforce JDBC sample.rptdesign) +## Configure IntelliJ to use Salesforce JDBC driver + +1. [How to add a JDBC driver](https://www.jetbrains.com/help/idea/data-sources-and-drivers-dialog.html) +2. How to set configuration properties for Salesforce JDBC driver. + + IntelliJ provides various ways to set parameters for JDBC driver. For example, it can be done with the property binding feature in the data source editor and a report parameter. + Example JDBC Url: + + ```jdbc:ascendix:salesforce://dev@Local.org:123456@localorg.localhost.internal.salesforce.com:6109?https=false&api=48.0``` + + Please check what kind of access do you have to your org - HTTP or HTTPS and the API version to use. + Here is screenshot about results output and autocomplete support for SOQL queries in IntelliJ: + + ![image](/docs/Autocomplete-SOQL.png) + + +## In case of issues with the WSDL + +Steps to update the partners.wsdl + +1. Get and build https://github.com/forcedotcom/wsc +2. Run command: + + `java -jar target/force-wsc-50.0.0-uber.jar blt/app/main/core/shared/submodules/wsdl/src/main/wsdl/partner.wsdl sforce-partner.jar` +3. Copy the com.sforce.soap to the driver + +## SOQL Parser + +This project uses a bit modified version of MuleSoft SOQL Parser which also supports quotes around field names. +It could be obtained from here: https://github.com/spuliaiev-sfdc/salesforce-soql-parser + + +## Version History + +### 1.3.1.3 +CONNECT command parsing fixes + +### 1.3.1.0 +Re-connection to a different host using CONNECT command + +### 1.3.0.1 + Insecure HTTPS - disabling the SSL Certificate verification + +### 1.2.6.03 + Update force-partner-api to 51.0.0 + +### 1.2.6.02 + Fields for SubSelects aliases + + Returning flat resultset for field + +### 1.2.6.01 + Update force-partner-api to 50.0.0 + + Implement parameters: +* loginDomain +* client +* https +* api + + Implement missing JDBC methods which are required for JetBrains IntelliJ IDE ### Sponsors [Ascendix Technologies Inc.](https://ascendix.com/) diff --git a/build.sh b/build.sh new file mode 100755 index 0000000..ec1eeec --- /dev/null +++ b/build.sh @@ -0,0 +1,2 @@ +source ~/java8 +mvn clean install -P single-jar && cp -f ./sf-jdbc-driver/target/sf-jdbc-driver-*-SNAPSHOT-jar-with-dependencies.jar ./deliverables/ diff --git a/deliverables/sf-jdbc-driver-1.2-SNAPSHOT-jar-with-dependencies.jar b/deliverables/sf-jdbc-driver-1.2-SNAPSHOT-jar-with-dependencies.jar new file mode 100644 index 0000000..80ed52b Binary files /dev/null and b/deliverables/sf-jdbc-driver-1.2-SNAPSHOT-jar-with-dependencies.jar differ diff --git a/deliverables/sf-jdbc-driver-1.3.0-SNAPSHOT-jar-with-dependencies.jar b/deliverables/sf-jdbc-driver-1.3.0-SNAPSHOT-jar-with-dependencies.jar new file mode 100644 index 0000000..de8358c Binary files /dev/null and b/deliverables/sf-jdbc-driver-1.3.0-SNAPSHOT-jar-with-dependencies.jar differ diff --git a/deliverables/sf-jdbc-driver-1.3.1-SNAPSHOT-jar-with-dependencies.jar b/deliverables/sf-jdbc-driver-1.3.1-SNAPSHOT-jar-with-dependencies.jar new file mode 100644 index 0000000..7700db5 Binary files /dev/null and b/deliverables/sf-jdbc-driver-1.3.1-SNAPSHOT-jar-with-dependencies.jar differ diff --git a/deliverables/sf-jdbc-driver-1.4.0-SNAPSHOT-jar-with-dependencies.jar b/deliverables/sf-jdbc-driver-1.4.0-SNAPSHOT-jar-with-dependencies.jar new file mode 100644 index 0000000..d2d4f96 Binary files /dev/null and b/deliverables/sf-jdbc-driver-1.4.0-SNAPSHOT-jar-with-dependencies.jar differ diff --git a/docs/Autocomplete-SOQL.png b/docs/Autocomplete-SOQL.png new file mode 100644 index 0000000..b72bb1d Binary files /dev/null and b/docs/Autocomplete-SOQL.png differ diff --git a/docs/SOQL-JDBC-IntelliJ-demo-264.mp4 b/docs/SOQL-JDBC-IntelliJ-demo-264.mp4 new file mode 100644 index 0000000..c691764 Binary files /dev/null and b/docs/SOQL-JDBC-IntelliJ-demo-264.mp4 differ diff --git a/docs/cases/intellij/run_flow_00.txt b/docs/cases/intellij/run_flow_00.txt new file mode 100644 index 0000000..620c5c4 --- /dev/null +++ b/docs/cases/intellij/run_flow_00.txt @@ -0,0 +1,81 @@ +2020-08-13 13:10:26,965 [4842581] INFO - g.FileBasedIndexProjectHandler - Has changed files: false; project=Project (name=untitled, containerState=ACTIVE, componentStore=/Users/spuliaiev/IdeaProjects/untitled) +2020-08-13 13:10:28,764 [4844380] WARN - ution.rmi.RemoteProcessSupport - Aug 13, 2020 8:10:28 PM com.ascendix.jdbc.salesforce.connection.ForceConnection isValid +2020-08-13 13:10:28,764 [4844380] WARN - ution.rmi.RemoteProcessSupport - INFO: isValid NOT_IMPLEMENTED +2020-08-13 13:10:28,766 [4844382] WARN - ution.rmi.RemoteProcessSupport - Aug 13, 2020 8:10:28 PM com.ascendix.jdbc.salesforce.connection.ForceConnection isValid +2020-08-13 13:10:28,766 [4844382] WARN - ution.rmi.RemoteProcessSupport - INFO: isValid NOT_IMPLEMENTED +2020-08-13 13:10:28,767 [4844383] WARN - ution.rmi.RemoteProcessSupport - Aug 13, 2020 8:10:28 PM com.ascendix.jdbc.salesforce.connection.ForceConnection isValid +2020-08-13 13:10:28,767 [4844383] WARN - ution.rmi.RemoteProcessSupport - INFO: isValid NOT_IMPLEMENTED +2020-08-13 13:10:28,780 [4844396] WARN - ution.rmi.RemoteProcessSupport - Aug 13, 2020 8:10:28 PM com.ascendix.jdbc.salesforce.connection.ForceConnection getCatalog +2020-08-13 13:10:28,781 [4844397] WARN - ution.rmi.RemoteProcessSupport - INFO: getCatalog NOT_IMPLEMENTED +2020-08-13 13:10:28,782 [4844398] WARN - ution.rmi.RemoteProcessSupport - Aug 13, 2020 8:10:28 PM com.ascendix.jdbc.salesforce.connection.ForceConnection createStatement +2020-08-13 13:10:28,782 [4844398] WARN - ution.rmi.RemoteProcessSupport - INFO: createStatement +2020-08-13 13:10:28,782 [4844398] ERROR - ij.database.console.JdbcEngine - connection.remoteConnection.createStatement() must not be null +java.lang.IllegalStateException: connection.remoteConnection.createStatement() must not be null + at com.intellij.database.dataSource.connection.statements.JdbcBasedSmartStatement$Simple.createStatement(JdbcBasedSmartStatement.kt:238) + at com.intellij.database.dataSource.connection.statements.JdbcBasedSmartStatement$Simple.createStatement(JdbcBasedSmartStatement.kt:219) + at com.intellij.database.dataSource.connection.statements.JdbcBasedSmartStatement$statementInstance$1.invoke(JdbcBasedSmartStatement.kt:100) + at com.intellij.database.dataSource.connection.statements.JdbcBasedSmartStatement$statementInstance$1.invoke(JdbcBasedSmartStatement.kt:18) + at com.intellij.database.dataSource.connection.statements.SmartStatementsUtil.runReporting(SmartStatementsUtil.kt:80) + at com.intellij.database.dataSource.connection.statements.JdbcBasedSmartStatement.statementInstance(JdbcBasedSmartStatement.kt:99) + at com.intellij.database.dataSource.connection.statements.JdbcBasedSmartStatement.access$statementInstance(JdbcBasedSmartStatement.kt:18) + at com.intellij.database.dataSource.connection.statements.JdbcBasedSmartStatement$getCurrentStatement$1.invoke(JdbcBasedSmartStatement.kt:118) + at com.intellij.database.dataSource.connection.statements.JdbcBasedSmartStatement$getCurrentStatement$1.invoke(JdbcBasedSmartStatement.kt:18) + at com.intellij.database.dataSource.connection.statements.StatementHolder$OneShot.invoke(StatementHolder.kt:36) + at com.intellij.database.dataSource.connection.statements.StatementHolder$OneShot.invoke(StatementHolder.kt:31) + at com.intellij.database.dataSource.connection.statements.JdbcBasedSmartStatement.getCurrentStatement(JdbcBasedSmartStatement.kt:118) + at com.intellij.database.dataSource.connection.statements.JdbcBasedSmartStatement.executeInCommonWay(JdbcBasedSmartStatement.kt:64) + at com.intellij.database.dataSource.connection.statements.JdbcBasedSmartStatement.execute(JdbcBasedSmartStatement.kt:42) + at com.intellij.database.dataSource.connection.statements.NoisyStatement.execute(NoisyStatement.kt:23) + at com.intellij.database.console.JdbcEngine$RegularExecutor.execute(JdbcEngine.java:1502) + at com.intellij.database.console.JdbcEngine$QueryExecutionOperation.lambda$execute$1(JdbcEngine.java:2086) + at com.intellij.database.dialects.base.BaseExecutionEnvironmentHelper.runInSpecificEnvironment(BaseExecutionEnvironmentHelper.java:52) + at com.intellij.database.console.JdbcEngine$QueryExecutionOperation.execute(JdbcEngine.java:2085) + at com.intellij.database.console.JdbcEngine$QueryExecutionOperation.perform(JdbcEngine.java:2030) + at com.intellij.database.console.JdbcEngine$OperationBase.perform(JdbcEngine.java:1699) + at com.intellij.database.console.JdbcEngine.lambda$visitQuery$5(JdbcEngine.java:384) + at com.intellij.database.console.AbstractEngine.lambda$submitRequest$4(AbstractEngine.java:182) + at com.intellij.database.console.AbstractEngine.lambda$null$2(AbstractEngine.java:156) + at com.intellij.openapi.progress.impl.CoreProgressManager.executeProcessUnderProgress(CoreProgressManager.java:577) + at com.intellij.openapi.progress.impl.ProgressManagerImpl.executeProcessUnderProgress(ProgressManagerImpl.java:61) + at com.intellij.database.dataSource.AsyncUtil.underProgress(AsyncUtil.java:180) + at com.intellij.database.console.AbstractEngine.lambda$submitRunnable$3(AbstractEngine.java:154) + at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) + at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) + at java.base/java.lang.Thread.run(Thread.java:834) +2020-08-13 13:10:28,783 [4844399] ERROR - ij.database.console.JdbcEngine - IntelliJ IDEA 2020.1 Build #IU-201.6668.121 +2020-08-13 13:10:28,783 [4844399] ERROR - ij.database.console.JdbcEngine - JDK: 11.0.6; VM: OpenJDK 64-Bit Server VM; Vendor: JetBrains s.r.o +2020-08-13 13:10:28,783 [4844399] ERROR - ij.database.console.JdbcEngine - OS: Mac OS X +2020-08-13 13:10:28,783 [4844399] ERROR - ij.database.console.JdbcEngine - Last Action: Console.Jdbc.Execute +2020-08-13 13:10:28,783 [4844399] WARN - ic.GenericDatabaseErrorHandler - connection.remoteConnection.createStatement() must not be null +java.lang.IllegalStateException: connection.remoteConnection.createStatement() must not be null + at com.intellij.database.dataSource.connection.statements.JdbcBasedSmartStatement$Simple.createStatement(JdbcBasedSmartStatement.kt:238) + at com.intellij.database.dataSource.connection.statements.JdbcBasedSmartStatement$Simple.createStatement(JdbcBasedSmartStatement.kt:219) + at com.intellij.database.dataSource.connection.statements.JdbcBasedSmartStatement$statementInstance$1.invoke(JdbcBasedSmartStatement.kt:100) + at com.intellij.database.dataSource.connection.statements.JdbcBasedSmartStatement$statementInstance$1.invoke(JdbcBasedSmartStatement.kt:18) + at com.intellij.database.dataSource.connection.statements.SmartStatementsUtil.runReporting(SmartStatementsUtil.kt:80) + at com.intellij.database.dataSource.connection.statements.JdbcBasedSmartStatement.statementInstance(JdbcBasedSmartStatement.kt:99) + at com.intellij.database.dataSource.connection.statements.JdbcBasedSmartStatement.access$statementInstance(JdbcBasedSmartStatement.kt:18) + at com.intellij.database.dataSource.connection.statements.JdbcBasedSmartStatement$getCurrentStatement$1.invoke(JdbcBasedSmartStatement.kt:118) + at com.intellij.database.dataSource.connection.statements.JdbcBasedSmartStatement$getCurrentStatement$1.invoke(JdbcBasedSmartStatement.kt:18) + at com.intellij.database.dataSource.connection.statements.StatementHolder$OneShot.invoke(StatementHolder.kt:36) + at com.intellij.database.dataSource.connection.statements.StatementHolder$OneShot.invoke(StatementHolder.kt:31) + at com.intellij.database.dataSource.connection.statements.JdbcBasedSmartStatement.getCurrentStatement(JdbcBasedSmartStatement.kt:118) + at com.intellij.database.dataSource.connection.statements.JdbcBasedSmartStatement.executeInCommonWay(JdbcBasedSmartStatement.kt:64) + at com.intellij.database.dataSource.connection.statements.JdbcBasedSmartStatement.execute(JdbcBasedSmartStatement.kt:42) + at com.intellij.database.dataSource.connection.statements.NoisyStatement.execute(NoisyStatement.kt:23) + at com.intellij.database.console.JdbcEngine$RegularExecutor.execute(JdbcEngine.java:1502) + at com.intellij.database.console.JdbcEngine$QueryExecutionOperation.lambda$execute$1(JdbcEngine.java:2086) + at com.intellij.database.dialects.base.BaseExecutionEnvironmentHelper.runInSpecificEnvironment(BaseExecutionEnvironmentHelper.java:52) + at com.intellij.database.console.JdbcEngine$QueryExecutionOperation.execute(JdbcEngine.java:2085) + at com.intellij.database.console.JdbcEngine$QueryExecutionOperation.perform(JdbcEngine.java:2030) + at com.intellij.database.console.JdbcEngine$OperationBase.perform(JdbcEngine.java:1699) + at com.intellij.database.console.JdbcEngine.lambda$visitQuery$5(JdbcEngine.java:384) + at com.intellij.database.console.AbstractEngine.lambda$submitRequest$4(AbstractEngine.java:182) + at com.intellij.database.console.AbstractEngine.lambda$null$2(AbstractEngine.java:156) + at com.intellij.openapi.progress.impl.CoreProgressManager.executeProcessUnderProgress(CoreProgressManager.java:577) + at com.intellij.openapi.progress.impl.ProgressManagerImpl.executeProcessUnderProgress(ProgressManagerImpl.java:61) + at com.intellij.database.dataSource.AsyncUtil.underProgress(AsyncUtil.java:180) + at com.intellij.database.console.AbstractEngine.lambda$submitRunnable$3(AbstractEngine.java:154) + at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) + at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) + at java.base/java.lang.Thread.run(Thread.java:834) diff --git a/docs/cases/intellij/run_flow_01.txt b/docs/cases/intellij/run_flow_01.txt new file mode 100644 index 0000000..bce8c7a --- /dev/null +++ b/docs/cases/intellij/run_flow_01.txt @@ -0,0 +1,52 @@ +2020-08-13 19:06:40,407 [ 32699] WARN - ution.rmi.RemoteProcessSupport - Aug 14, 2020 2:06:40 AM com.ascendix.jdbc.salesforce.statement.ForcePreparedStatement executeQuery +2020-08-13 19:06:40,407 [ 32699] WARN - ution.rmi.RemoteProcessSupport - INFO: executeQuery IMPLEMENTED select Id from Account +2020-08-13 19:06:40,409 [ 32701] WARN - ution.rmi.RemoteProcessSupport - Aug 14, 2020 2:06:40 AM com.ascendix.jdbc.salesforce.statement.ForcePreparedStatement executeQuery +2020-08-13 19:06:40,409 [ 32701] WARN - ution.rmi.RemoteProcessSupport - INFO: executeQuery IMPLEMENTED select Id from Account +2020-08-13 19:06:40,410 [ 32702] WARN - ution.rmi.RemoteProcessSupport - Aug 14, 2020 2:06:40 AM com.ascendix.jdbc.salesforce.statement.ForcePreparedStatement query +2020-08-13 19:06:40,410 [ 32702] WARN - ution.rmi.RemoteProcessSupport - INFO: query IMPLEMENTED select Id from Account +2020-08-13 19:06:40,410 [ 32702] WARN - ution.rmi.RemoteProcessSupport - Aug 14, 2020 2:06:40 AM com.ascendix.jdbc.salesforce.statement.ForcePreparedStatement prepareQuery +2020-08-13 19:06:40,410 [ 32702] WARN - ution.rmi.RemoteProcessSupport - INFO: prepareQuery IMPLEMENTED select Id from Account +2020-08-13 19:06:40,411 [ 32703] WARN - ution.rmi.RemoteProcessSupport - Aug 14, 2020 2:06:40 AM com.ascendix.jdbc.salesforce.statement.ForcePreparedStatement setParams +2020-08-13 19:06:40,411 [ 32703] WARN - ution.rmi.RemoteProcessSupport - INFO: setParams IMPLEMENTED select Id from Account +2020-08-13 19:06:40,411 [ 32703] WARN - ution.rmi.RemoteProcessSupport - Aug 14, 2020 2:06:40 AM com.ascendix.jdbc.salesforce.statement.ForcePreparedStatement getParameters +2020-08-13 19:06:40,412 [ 32704] WARN - ution.rmi.RemoteProcessSupport - INFO: getParameters IMPLEMENTED select Id from Account +2020-08-13 19:06:40,415 [ 32707] WARN - ution.rmi.RemoteProcessSupport - Aug 14, 2020 2:06:40 AM com.ascendix.jdbc.salesforce.statement.ForcePreparedStatement getPartnerService +2020-08-13 19:06:40,415 [ 32707] WARN - ution.rmi.RemoteProcessSupport - INFO: getPartnerService IMPLEMENTED select Id from Account +2020-08-13 19:06:40,416 [ 32708] WARN - ution.rmi.RemoteProcessSupport - Aug 14, 2020 2:06:40 AM com.ascendix.jdbc.salesforce.statement.ForcePreparedStatement getFieldDefinitions +2020-08-13 19:06:40,416 [ 32708] WARN - ution.rmi.RemoteProcessSupport - INFO: getFieldDefinitions IMPLEMENTED select Id from Account +2020-08-13 19:06:40,417 [ 32709] WARN - ution.rmi.RemoteProcessSupport - Aug 14, 2020 2:06:40 AM com.ascendix.jdbc.salesforce.statement.ForcePreparedStatement getQueryAnalyzer +2020-08-13 19:06:40,417 [ 32709] WARN - ution.rmi.RemoteProcessSupport - INFO: getQueryAnalyzer IMPLEMENTED select Id from Account +2020-08-13 19:06:40,418 [ 32710] WARN - ution.rmi.RemoteProcessSupport - Aug 14, 2020 2:06:40 AM com.ascendix.jdbc.salesforce.statement.ForcePreparedStatement prepareQuery +2020-08-13 19:06:40,418 [ 32710] WARN - ution.rmi.RemoteProcessSupport - INFO: prepareQuery IMPLEMENTED select Id from Account +2020-08-13 19:06:40,419 [ 32711] WARN - ution.rmi.RemoteProcessSupport - Aug 14, 2020 2:06:40 AM com.ascendix.jdbc.salesforce.statement.ForcePreparedStatement setParams +2020-08-13 19:06:40,419 [ 32711] WARN - ution.rmi.RemoteProcessSupport - INFO: setParams IMPLEMENTED select Id from Account +2020-08-13 19:06:40,419 [ 32711] WARN - ution.rmi.RemoteProcessSupport - Aug 14, 2020 2:06:40 AM com.ascendix.jdbc.salesforce.statement.ForcePreparedStatement getParameters +2020-08-13 19:06:40,419 [ 32711] WARN - ution.rmi.RemoteProcessSupport - INFO: getParameters IMPLEMENTED select Id from Account +2020-08-13 19:06:40,557 [ 32849] WARN - ution.rmi.RemoteProcessSupport - Aug 14, 2020 2:06:40 AM com.ascendix.jdbc.salesforce.statement.ForcePreparedStatement getPartnerService +2020-08-13 19:06:40,558 [ 32850] WARN - ution.rmi.RemoteProcessSupport - INFO: getPartnerService IMPLEMENTED select Id from Account +2020-08-13 19:06:41,377 [ 33669] WARN - ution.rmi.RemoteProcessSupport - Aug 14, 2020 2:06:41 AM com.ascendix.jdbc.salesforce.statement.ForcePreparedStatement getMetaData +2020-08-13 19:06:41,377 [ 33669] WARN - ution.rmi.RemoteProcessSupport - INFO: getMetaData IMPLEMENTED select Id from Account +2020-08-13 19:06:41,377 [ 33669] WARN - ution.rmi.RemoteProcessSupport - Aug 14, 2020 2:06:41 AM com.ascendix.jdbc.salesforce.statement.ForcePreparedStatement loadMetaData +2020-08-13 19:06:41,377 [ 33669] WARN - ution.rmi.RemoteProcessSupport - INFO: loadMetaData IMPLEMENTED select Id from Account +2020-08-13 19:06:41,379 [ 33671] WARN - ution.rmi.RemoteProcessSupport - Aug 14, 2020 2:06:41 AM com.ascendix.jdbc.salesforce.statement.ForcePreparedStatement getQueryAnalyzer +2020-08-13 19:06:41,379 [ 33671] WARN - ution.rmi.RemoteProcessSupport - INFO: getQueryAnalyzer IMPLEMENTED select Id from Account +2020-08-13 19:06:41,379 [ 33671] WARN - ution.rmi.RemoteProcessSupport - Aug 14, 2020 2:06:41 AM com.ascendix.jdbc.salesforce.statement.ForcePreparedStatement getFieldDefinitions +2020-08-13 19:06:41,380 [ 33672] WARN - ution.rmi.RemoteProcessSupport - INFO: getFieldDefinitions IMPLEMENTED select Id from Account +2020-08-13 19:06:41,380 [ 33672] WARN - ution.rmi.RemoteProcessSupport - Aug 14, 2020 2:06:41 AM com.ascendix.jdbc.salesforce.statement.ForcePreparedStatement flatten +2020-08-13 19:06:41,380 [ 33672] WARN - ution.rmi.RemoteProcessSupport - INFO: flatten IMPLEMENTED select Id from Account +2020-08-13 19:06:41,513 [ 33805] WARN - ution.rmi.RemoteProcessSupport - Aug 14, 2020 2:06:41 AM com.ascendix.jdbc.salesforce.statement.ForcePreparedStatement getMoreResults +2020-08-13 19:06:41,513 [ 33805] WARN - ution.rmi.RemoteProcessSupport - INFO: getMoreResults NOT_IMPLEMENTED select Id from Account +2020-08-13 19:06:41,514 [ 33806] WARN - ution.rmi.RemoteProcessSupport - Aug 14, 2020 2:06:41 AM com.ascendix.jdbc.salesforce.statement.ForcePreparedStatement getUpdateCount +2020-08-13 19:06:41,514 [ 33806] WARN - ution.rmi.RemoteProcessSupport - INFO: getUpdateCount NOT_IMPLEMENTED select Id from Account +2020-08-13 19:06:41,516 [ 33808] WARN - ution.rmi.RemoteProcessSupport - Aug 14, 2020 2:06:41 AM com.ascendix.jdbc.salesforce.statement.ForcePreparedStatement getMoreResults +2020-08-13 19:06:41,516 [ 33808] WARN - ution.rmi.RemoteProcessSupport - INFO: getMoreResults NOT_IMPLEMENTED select Id from Account +2020-08-13 19:06:41,516 [ 33808] WARN - ution.rmi.RemoteProcessSupport - Aug 14, 2020 2:06:41 AM com.ascendix.jdbc.salesforce.statement.ForcePreparedStatement getUpdateCount +2020-08-13 19:06:41,516 [ 33808] WARN - ution.rmi.RemoteProcessSupport - INFO: getUpdateCount NOT_IMPLEMENTED select Id from Account +2020-08-13 19:06:41,517 [ 33809] WARN - ution.rmi.RemoteProcessSupport - Aug 14, 2020 2:06:41 AM com.ascendix.jdbc.salesforce.statement.ForcePreparedStatement getMoreResults +2020-08-13 19:06:41,517 [ 33809] WARN - ution.rmi.RemoteProcessSupport - INFO: getMoreResults NOT_IMPLEMENTED select Id from Account +2020-08-13 19:06:41,518 [ 33810] WARN - ution.rmi.RemoteProcessSupport - Aug 14, 2020 2:06:41 AM com.ascendix.jdbc.salesforce.statement.ForcePreparedStatement getUpdateCount +2020-08-13 19:06:41,518 [ 33810] WARN - ution.rmi.RemoteProcessSupport - INFO: getUpdateCount NOT_IMPLEMENTED select Id from Account +2020-08-13 19:06:41,519 [ 33811] WARN - ution.rmi.RemoteProcessSupport - Aug 14, 2020 2:06:41 AM com.ascendix.jdbc.salesforce.statement.ForcePreparedStatement getMoreResults +2020-08-13 19:06:41,519 [ 33811] WARN - ution.rmi.RemoteProcessSupport - INFO: getMoreResults NOT_IMPLEMENTED select Id from Account +2020-08-13 19:06:41,519 [ 33811] WARN - ution.rmi.RemoteProcessSupport - Aug 14, 2020 2:06:41 AM com.ascendix.jdbc.salesforce.statement.ForcePreparedStatement getUpdateCount +2020-08-13 19:06:41,519 [ 33811] WARN - ution.rmi.RemoteProcessSupport - INFO: getUpdateCount NOT_IMPLEMENTED select Id from Account diff --git a/docs/conv.sh b/docs/conv.sh new file mode 100755 index 0000000..5def6e5 --- /dev/null +++ b/docs/conv.sh @@ -0,0 +1,5 @@ +time ffmpeg -i SOQL-JDBC-IntelliJ-demo.mp4 -vcodec libx264 \ +-vf "pad=width=1720:height=1300:x=0:y=1:color=black" -acodec copy result.mp4 +#time ffmpeg -i SOQL-JDBC-IntelliJ-demo.mp4 -c:v libx264 -c:a aac -tag:v hvc1 SOQL-JDBC-IntelliJ-demo-264.mp4 +#time ffmpeg -i SOQL-JDBC-IntelliJ-demo.mp4 -c:v libx265 -c:a aac -tag:v -s 1920x1300 hvc1 SOQL-JDBC-IntelliJ-demo-hevc3.mp4 +#time ffmpeg -i SOQL-JDBC-IntelliJ-demo.mp4 -c:v libx265 -crf 28 -c:a aac -b:a 128k -tag:v hvc1 SOQL-JDBC-IntelliJ-demo-hevc3.mp4 \ No newline at end of file diff --git a/docs/intelliJ.png b/docs/intelliJ.png new file mode 100644 index 0000000..49a7803 Binary files /dev/null and b/docs/intelliJ.png differ diff --git a/docs/script-demo-2021-02-01.txt b/docs/script-demo-2021-02-01.txt new file mode 100644 index 0000000..2310324 --- /dev/null +++ b/docs/script-demo-2021-02-01.txt @@ -0,0 +1,63 @@ + + +Let me show you the simplest way to run SOQL queries to any environment from single IDE. +I am ging to show this on the IntelliJ IDE, but the driver I am working on is a regular JDBC driver - +so it can be used from any IDE you prefer - Eclipse, Oracle SQL Developer or any other. + +So in order to get access there I need to download the JDBC driver from the page: +https://github.com/spuliaiev-sfdc/salesforce-jdbc + +And we need to register this driver in the IDE. + +Let's start with registration of the database datasoure +admin@RecColl03.org +test12345 +jdbc:ascendix:salesforce://ap1.stmpa.stm.salesforce.com + +Let's test the connectivity. +Here we see the driver version reported and that connection is good. + +By default API version used is 50.0 +We can also change the API version used by supplying the parameter +?api=51.0 + +Now we can run the queries for that org: +select Id, Name from Organization + +And we can pull the list of Accounts: +select Id, Name, Owner.Id, Owner.Name from Account + +When the pull of existing Entities available for this Org is finished we will see the autocomplete +for the Entity Names and Entity Fields. + See in the Database Tab the list of available entities. + + +For now Driver supports only SOQL and some admin commands. And I want to show you how to use CONNECT command. +The syntax of the command is following: + + Let's say I have a diffent org on the same server - I can swithc to that org and get it's data: + CONNECT USER admin@RecColl04.org IDENTIFIED BY test12345; + + And verifying that org has been switched: + select Id, Name from Organization + +And we can switch not only to another org on this server - we can switch to any server: + + + Let's test Locally running server: + Please use the real host name - not the domain name generated for the particular org by MyDomain feature. + + CONNECT TO jdbc:ascendix:salesforce://dev@Local.org:123456@spuliaiev-wsm1.internal.salesforce.com:6109?https=false&api=51.0 + + Select id, name from Organization; + + There is another syntax a bit simplier to do the same: + CONNECT TO http://spuliaiev-wsm1.internal.salesforce.com:6109 + USER demo@jdbc.org IDENTIFIED BY "123456" + Select id, name from Organization; + + It uses the schema http or https to identify should it use SSL or not. Sometimes for self signed SSL certificates you will have to use option insecurehttps=true + + That's it for now. + I am also working on adding UPDATE and INSERT parsers so you could run these commands + to set up entities in a much simpler manner than using workbench now. diff --git a/pom.xml b/pom.xml index 4a17429..accd221 100644 --- a/pom.xml +++ b/pom.xml @@ -3,15 +3,22 @@ 4.0.0 com.ascendix.salesforce salesforce-jdbc - 1.2-SNAPSHOT + ${revision} pom + + https://github.com/spuliaiev-sfdc/salesforce-jdbc.git + https://github.com/spuliaiev-sfdc/salesforce-jdbc.git + https://github.com/spuliaiev-sfdc/salesforce-jdbc + + sf-auth-client sf-jdbc-driver + 1.4.0-SNAPSHOT 1.8 1.8 UTF-8 @@ -21,6 +28,7 @@ 1.25.0 3.8 4.1 + 1.3.2 4.13.1 1.3 @@ -32,12 +40,12 @@ 3.1.0 3.1.0 2.8.2 - 2.0 - 50.0.0 + 2.0-sfdc + 51.0.0 3.0.5 3.5.2 4.2 - 1.4.8 + 1.4.16 2.4 @@ -109,6 +117,11 @@ antlr ${antlr.version} + + org.apache.commons + commons-io + ${commons-io.version} + org.apache.commons commons-collections4 @@ -136,7 +149,8 @@ com.thoughtworks.xstream xstream - ${xstream.version} + 1.4.16 + test diff --git a/sf-auth-client/pom.xml b/sf-auth-client/pom.xml index c434e27..2840ef7 100644 --- a/sf-auth-client/pom.xml +++ b/sf-auth-client/pom.xml @@ -6,7 +6,8 @@ salesforce-jdbc com.ascendix.salesforce - 1.2-SNAPSHOT + ${revision} + ../pom.xml sf-auth-client @@ -22,4 +23,4 @@ - \ No newline at end of file + diff --git a/sf-jdbc-driver/pom.xml b/sf-jdbc-driver/pom.xml index 0649ff5..8a16d34 100644 --- a/sf-jdbc-driver/pom.xml +++ b/sf-jdbc-driver/pom.xml @@ -6,7 +6,8 @@ salesforce-jdbc com.ascendix.salesforce - 1.2-SNAPSHOT + ${revision} + ../pom.xml sf-jdbc-driver @@ -32,6 +33,10 @@ org.apache.commons commons-lang3 + + org.apache.commons + commons-io + org.antlr antlr @@ -40,6 +45,11 @@ org.apache.commons commons-collections4 + + com.github.jsqlparser + jsqlparser + 4.0 + @@ -81,10 +91,15 @@ jar-with-dependencies + + + com.ascendix.jdbc.salesforce.metadata.ForceDatabaseMetaData + + - \ No newline at end of file + diff --git a/sf-jdbc-driver/src/main/java/com/ascendix/jdbc/salesforce/ForceDriver.java b/sf-jdbc-driver/src/main/java/com/ascendix/jdbc/salesforce/ForceDriver.java index 50b5120..bf9b49a 100644 --- a/sf-jdbc-driver/src/main/java/com/ascendix/jdbc/salesforce/ForceDriver.java +++ b/sf-jdbc-driver/src/main/java/com/ascendix/jdbc/salesforce/ForceDriver.java @@ -4,13 +4,19 @@ import com.ascendix.jdbc.salesforce.connection.ForceConnectionInfo; import com.ascendix.jdbc.salesforce.connection.ForceService; import com.sforce.soap.partner.PartnerConnection; +import com.sforce.soap.partner.fault.ApiFault; import com.sforce.ws.ConnectionException; import lombok.extern.slf4j.Slf4j; +import javax.net.ssl.*; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.nio.charset.StandardCharsets; +import java.security.KeyManagementException; +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; +import java.security.cert.X509Certificate; import java.sql.Connection; import java.sql.Driver; import java.sql.DriverManager; @@ -18,6 +24,7 @@ import java.sql.SQLException; import java.sql.SQLFeatureNotSupportedException; import java.util.Properties; +import java.util.logging.Level; import java.util.logging.Logger; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -26,14 +33,22 @@ @Slf4j public class ForceDriver implements Driver { + private static final String SF_JDBC_DRIVER_NAME = "SF JDBC driver"; + private static final Logger logger = Logger.getLogger(SF_JDBC_DRIVER_NAME); + private static final String ACCEPTABLE_URL = "jdbc:ascendix:salesforce"; private static final Pattern URL_PATTERN = Pattern.compile("\\A" + ACCEPTABLE_URL + "://(.*)"); private static final Pattern URL_HAS_AUTHORIZATION_SEGMENT = Pattern.compile("\\A" + ACCEPTABLE_URL + "://([^:]+):([^@]+)@([^?]*)([?](.*))?"); private static final Pattern PARAM_STANDARD_PATTERN = Pattern.compile("(([^=]+)=([^&]*)&?)"); + private static final Pattern VALID_IP_ADDRESS_REGEX = Pattern.compile("^(?https?://)?(?(?(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))(:(?[0-9]+))?)$"); + private static final Pattern VALID_HOST_NAME_REGEX = Pattern.compile("^(?https?://)?(?(?(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\\-]*[a-zA-Z0-9])\\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\\-]*[A-Za-z0-9]))(:(?[0-9]+))?)$"); + static { try { + logger.info("[ForceDriver] registration"); DriverManager.registerDriver(new ForceDriver()); + } catch (Exception e) { throw new RuntimeException("Failed register ForceDriver: " + e.getMessage(), e); } @@ -58,14 +73,60 @@ public Connection connect(String url, Properties properties) throws SQLException info.setUserName(properties.getProperty("user")); info.setClientName(properties.getProperty("client")); info.setPassword(properties.getProperty("password")); + info.setClientName(properties.getProperty("client")); info.setSessionId(properties.getProperty("sessionId")); info.setSandbox(resolveSandboxProperty(properties)); info.setHttps(resolveBooleanProperty(properties, "https", true)); + if (resolveBooleanProperty(properties, "insecurehttps", false)) { + HttpsTrustManager.allowAllSSL(); + } info.setApiVersion(resolveStringProperty(properties, "api", ForceService.DEFAULT_API_VERSION)); info.setLoginDomain(resolveStringProperty(properties, "loginDomain", ForceService.DEFAULT_LOGIN_DOMAIN)); PartnerConnection partnerConnection = ForceService.createPartnerConnection(info); - return new ForceConnection(partnerConnection); + return new ForceConnection(partnerConnection, (newUrl, userName, userPassword) -> { + logger.info("[ForceDriver] relogin helper "); + Properties newConnStringProps; + Properties newProperties = new Properties(); + newProperties.putAll(properties); + ForceConnectionInfo newInfo = new ForceConnectionInfo(); + if (newUrl != null) { + try { + newConnStringProps = getConnStringProperties(newUrl); + newProperties.putAll(newConnStringProps); + } catch (Exception e) { + logger.log(Level.WARNING, "[ForceDriver] relogin helper failed - url parsing error", e); + } + } + if (userName != null && userPassword != null) { + newProperties.setProperty("user", userName); + newProperties.setProperty("password", userPassword); + } + newInfo.setUserName(newProperties.getProperty("user")); + newInfo.setPassword(newProperties.getProperty("password")); + newInfo.setClientName(newProperties.getProperty("client")); + newInfo.setSessionId(newProperties.getProperty("sessionId")); + newInfo.setSandbox(resolveSandboxProperty(newProperties)); + newInfo.setHttps(resolveBooleanProperty(newProperties, "https", true)); + if (resolveBooleanProperty(newProperties, "insecurehttps", false)) { + HttpsTrustManager.allowAllSSL(); + } + newInfo.setApiVersion(resolveStringProperty(newProperties, "api", ForceService.DEFAULT_API_VERSION)); + newInfo.setLoginDomain(resolveStringProperty(newProperties, "loginDomain", ForceService.DEFAULT_LOGIN_DOMAIN)); + + PartnerConnection newPartnerConnection; + try { + newPartnerConnection = ForceService.createPartnerConnection(newInfo); + logger.log(Level.WARNING, "[ForceDriver] relogin helper success="+(newPartnerConnection != null)); + return newPartnerConnection; + } catch (ApiFault e) { + logger.log(Level.WARNING, "[ForceDriver] relogin helper failed "+ e.getMessage(), e); + throw new ConnectionException("Relogin failed ("+e.getExceptionCode()+") "+ e.getExceptionMessage(), e); + } catch (ConnectionException e) { + logger.log(Level.WARNING, "[ForceDriver] relogin helper failed "+ e.getMessage(), e); + throw new ConnectionException("Relogin failed", e); + } + }); } catch (ConnectionException | IOException e) { throw new SQLException(e); } @@ -83,7 +144,7 @@ private static Boolean resolveSandboxProperty(Properties properties) { return null; } - private static Boolean resolveBooleanProperty(Properties properties, String propertyName, boolean defaultValue) { + protected static Boolean resolveBooleanProperty(Properties properties, String propertyName, boolean defaultValue) { String boolValue = properties.getProperty(propertyName); if (boolValue != null) { return Boolean.valueOf(boolValue); @@ -100,7 +161,7 @@ private static String resolveStringProperty(Properties properties, String proper } - protected Properties getConnStringProperties(String urlString) throws IOException { + public static Properties getConnStringProperties(String urlString) throws IOException { Properties result = new Properties(); String urlProperties = null; @@ -108,8 +169,12 @@ protected Properties getConnStringProperties(String urlString) throws IOExceptio Matcher authMatcher = URL_HAS_AUTHORIZATION_SEGMENT.matcher(urlString); if (authMatcher.matches()) { - result.put("user", authMatcher.group(1)); - result.put("password", authMatcher.group(2)); + if (authMatcher.group(1) != null) { + result.put("user", authMatcher.group(1)); + } + if (authMatcher.group(2) != null) { + result.put("password", authMatcher.group(2)); + } result.put("loginDomain", authMatcher.group(3)); if (authMatcher.groupCount() > 4 && authMatcher.group(5) != null) { // has some other parameters - parse them from standard URL format like @@ -121,11 +186,36 @@ protected Properties getConnStringProperties(String urlString) throws IOExceptio String value = 3 >= matcher.groupCount() ? matcher.group(3) : null; result.put(param, value); } - } } else if (stdMatcher.matches()) { - urlProperties = stdMatcher.group(1); + String dataString = stdMatcher.group(1); + int endOfHost = dataString.contains(";") ? dataString.indexOf(";")-1 : dataString.length()-1; + String possibleHost = dataString.substring(0, endOfHost+1); + if (possibleHost.trim().length() > 0 && !possibleHost.contains("=")) { + result.put("loginDomain", possibleHost); + urlProperties = dataString.substring(endOfHost+1); + } else { + urlProperties = dataString; + } urlProperties = urlProperties.replaceAll(";", "\n"); + } else { + Matcher ipMatcher = VALID_IP_ADDRESS_REGEX.matcher(urlString); + if (ipMatcher.matches()) { + result.put("loginDomain", ipMatcher.group("loginDomain")); + result.put("https", "true"); + if (ipMatcher.group("protocol") != null && ipMatcher.group("protocol").toLowerCase().equals("http://")) { + result.put("https", "false"); + } + } else { + Matcher hostMatcher = VALID_HOST_NAME_REGEX.matcher(urlString); + if (hostMatcher.matches()) { + result.put("loginDomain", hostMatcher.group("loginDomain")); + result.put("https", "true"); + if (hostMatcher.group("protocol") != null && hostMatcher.group("protocol").toLowerCase().equals("http://")) { + result.put("https", "false"); + } + } + } } if (urlProperties != null) { @@ -167,4 +257,53 @@ public Logger getParentLogger() throws SQLFeatureNotSupportedException { throw new SQLFeatureNotSupportedException(); } + public static class HttpsTrustManager implements X509TrustManager { + private static TrustManager[] trustManagers; + private static final X509Certificate[] _AcceptedIssuers = new X509Certificate[]{}; + + @Override + public void checkClientTrusted( + X509Certificate[] x509Certificates, String s) + throws java.security.cert.CertificateException { + + } + + @Override + public void checkServerTrusted( + X509Certificate[] x509Certificates, String s) + throws java.security.cert.CertificateException { + + } + + public boolean isClientTrusted(X509Certificate[] chain) { + return true; + } + + public boolean isServerTrusted(X509Certificate[] chain) { + return true; + } + + @Override + public X509Certificate[] getAcceptedIssuers() { + return _AcceptedIssuers; + } + + public static void allowAllSSL() { + HttpsURLConnection.setDefaultHostnameVerifier((arg0, arg1) -> true); + + if (trustManagers == null) { + trustManagers = new TrustManager[]{new HttpsTrustManager()}; + } + + try { + SSLContext context = SSLContext.getInstance("TLS"); + context.init(null, trustManagers, new SecureRandom()); + HttpsURLConnection.setDefaultSSLSocketFactory(context.getSocketFactory()); + } catch (NoSuchAlgorithmException | KeyManagementException e) { + e.printStackTrace(); + } + + } + } + } diff --git a/sf-jdbc-driver/src/main/java/com/ascendix/jdbc/salesforce/connection/ForceConnection.java b/sf-jdbc-driver/src/main/java/com/ascendix/jdbc/salesforce/connection/ForceConnection.java index 0fe589f..edb4e6c 100644 --- a/sf-jdbc-driver/src/main/java/com/ascendix/jdbc/salesforce/connection/ForceConnection.java +++ b/sf-jdbc-driver/src/main/java/com/ascendix/jdbc/salesforce/connection/ForceConnection.java @@ -3,6 +3,7 @@ import com.ascendix.jdbc.salesforce.statement.ForcePreparedStatement; import com.ascendix.jdbc.salesforce.metadata.ForceDatabaseMetaData; import com.sforce.soap.partner.PartnerConnection; +import com.sforce.ws.ConnectionException; import java.sql.Array; import java.sql.Blob; @@ -23,11 +24,32 @@ import java.util.Map; import java.util.Properties; import java.util.concurrent.Executor; +import java.util.function.BiFunction; +import java.util.logging.Level; import java.util.logging.Logger; public class ForceConnection implements Connection { + @FunctionalInterface + public interface UpdateLoginFunction { + + /** + * Applies this function to the given arguments. + * + * @param url the first function argument + * @param user the second function argument + * @param pass the second function argument + * @return the function result + */ + PartnerConnection apply(String url, String user, String pass) throws ConnectionException; + } + private final PartnerConnection partnerConnection; + /** the updated partner connection in case if we want to support relogin command */ + private PartnerConnection partnerConnectionUpdated; + /** the function to provide partner connection in case if we want to support relogin command */ + UpdateLoginFunction loginHandler; + private final DatabaseMetaData metadata; private static final String SF_JDBC_DRIVER_NAME = "SF JDBC driver"; private static final Logger logger = Logger.getLogger(SF_JDBC_DRIVER_NAME); @@ -35,21 +57,52 @@ public class ForceConnection implements Connection { private Map connectionCache = new HashMap<>(); Properties clientInfo = new Properties(); - public ForceConnection(PartnerConnection partnerConnection) { + public ForceConnection(PartnerConnection partnerConnection, UpdateLoginFunction loginHandler) { this.partnerConnection = partnerConnection; this.metadata = new ForceDatabaseMetaData(this); + this.loginHandler = loginHandler; } public PartnerConnection getPartnerConnection() { + if (partnerConnectionUpdated != null) { + return partnerConnectionUpdated; + } return partnerConnection; } + public boolean updatePartnerConnection(String url, String userName, String userPass) throws ConnectionException { + boolean result = false; + String currentUserName = null; + try { + currentUserName = partnerConnection.getUserInfo().getUserName(); + } catch (ConnectionException e) { + } + logger.info("[Conn] updatePartnerConnection IMPLEMENTED newUserName="+userName + " oldUserName="+currentUserName + " newUrl="+url); + if (loginHandler != null) { + try { + PartnerConnection newPartnerConnection = loginHandler.apply(url, userName, userPass); + if (newPartnerConnection != null) { + partnerConnectionUpdated = newPartnerConnection; + logger.info("[Conn] updatePartnerConnection UPDATED to newUserName="+userName); + result = true; + } else { + logger.log(Level.SEVERE, "[Conn] updatePartnerConnection UPDATE FAILED to newUserName="+userName+" currentUserName="+currentUserName); + } + } catch (Exception e) { + logger.log(Level.SEVERE, "[Conn] updatePartnerConnection UPDATE FAILED to newUserName="+userName+" currentUserName="+currentUserName, e); + throw e; + } + } + return result; + } + public DatabaseMetaData getMetaData() { return metadata; } @Override public PreparedStatement prepareStatement(String soql) { + logger.info("[Conn] prepareStatement IMPLEMENTED "+soql); return new ForcePreparedStatement(this, soql); } @@ -77,7 +130,7 @@ public boolean isWrapperFor(Class iface) { @Override public Statement createStatement() { logger.info("[Conn] createStatement 1 IMPLEMENTED "); - return null; + return new ForcePreparedStatement(this); } @Override @@ -100,26 +153,22 @@ public void setAutoCommit(boolean autoCommit) { @Override public boolean getAutoCommit() throws SQLException { - // TODO Auto-generated method stub - return false; + return true; } @Override public void commit() throws SQLException { - // TODO Auto-generated method stub - + logger.info("[Conn] commit NOT_IMPLEMENTED "); } @Override public void rollback() throws SQLException { - // TODO Auto-generated method stub - + logger.info("[Conn] rollback NOT_IMPLEMENTED "); } @Override public void close() throws SQLException { - // TODO Auto-generated method stub - + logger.info("[Conn] close NOT_IMPLEMENTED "); } @Override @@ -143,13 +192,13 @@ public boolean isReadOnly() throws SQLException { @Override public void setCatalog(String catalog) throws SQLException { // TODO Auto-generated method stub - + logger.info("[Conn] setCatalog NOT_IMPLEMENTED set to '"+catalog+"'"); } @Override public String getCatalog() throws SQLException { - // TODO Auto-generated method stub - return null; + logger.info("[Conn] getCatalog IMPLEMENTED returning "+ForceDatabaseMetaData.DEFAULT_CATALOG); + return ForceDatabaseMetaData.DEFAULT_CATALOG; } @Override @@ -178,26 +227,26 @@ public void clearWarnings() throws SQLException { @Override public Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException { - Logger.getLogger(SF_JDBC_DRIVER_NAME).info(Object.class.getEnclosingMethod().getName()); - return null; + logger.info("[Conn] createStatement 2 IMPLEMENTED"); + return new ForcePreparedStatement(this); } @Override public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency) throws SQLException { - Logger.getLogger(SF_JDBC_DRIVER_NAME).info(Object.class.getEnclosingMethod().getName()); - return null; + logger.info("[Conn] prepareStatement 1 IMPLEMENTED "+sql); + return new ForcePreparedStatement(this, sql); } @Override public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) throws SQLException { - Logger.getLogger(SF_JDBC_DRIVER_NAME).info(Object.class.getEnclosingMethod().getName()); + logger.info("[Conn] prepareCall NOT_IMPLEMENTED "+sql); return null; } @Override public Map> getTypeMap() throws SQLException { - Logger.getLogger(SF_JDBC_DRIVER_NAME).info(Object.class.getEnclosingMethod().getName()); + logger.info("[Conn] getTypeMap NOT_IMPLEMENTED "); return null; } @@ -233,52 +282,52 @@ public Savepoint setSavepoint(String name) throws SQLException { @Override public void rollback(Savepoint savepoint) throws SQLException { - // TODO Auto-generated method stub + logger.info("[Conn] rollback Savepoint NOT_IMPLEMENTED"); } @Override public void releaseSavepoint(Savepoint savepoint) throws SQLException { - // TODO Auto-generated method stub + logger.info("[Conn] releaseSavepoint NOT_IMPLEMENTED"); } @Override public Statement createStatement(int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException { - Logger.getLogger(SF_JDBC_DRIVER_NAME).info(Object.class.getEnclosingMethod().getName()); - return null; + logger.info("[Conn] createStatement 3 NOT_IMPLEMENTED"); + return new ForcePreparedStatement(this); } @Override public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException { - Logger.getLogger(SF_JDBC_DRIVER_NAME).info(Object.class.getEnclosingMethod().getName()); + logger.info("[Conn] prepareStatement 2 NOT_IMPLEMENTED "+sql ); return null; } @Override public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException { - Logger.getLogger(SF_JDBC_DRIVER_NAME).info(Object.class.getEnclosingMethod().getName()); + logger.info("[Conn] prepareCall 2 NOT_IMPLEMENTED "+sql ); return null; } @Override public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) throws SQLException { - Logger.getLogger(SF_JDBC_DRIVER_NAME).info(Object.class.getEnclosingMethod().getName()); + logger.info("[Conn] prepareStatement 3 NOT_IMPLEMENTED "+sql ); return null; } @Override public PreparedStatement prepareStatement(String sql, int[] columnIndexes) throws SQLException { - Logger.getLogger(SF_JDBC_DRIVER_NAME).info(Object.class.getEnclosingMethod().getName()); + logger.info("[Conn] prepareStatement 4 NOT_IMPLEMENTED "+sql ); return null; } @Override public PreparedStatement prepareStatement(String sql, String[] columnNames) throws SQLException { - Logger.getLogger(SF_JDBC_DRIVER_NAME).info(Object.class.getEnclosingMethod().getName()); + logger.info("[Conn] prepareStatement 5 NOT_IMPLEMENTED "+sql ); return null; } @@ -309,7 +358,8 @@ public SQLXML createSQLXML() throws SQLException { @Override public boolean isValid(int timeout) throws SQLException { // TODO Auto-generated method stub - return false; + logger.info("[Conn] isValid NOT_IMPLEMENTED "); + return true; } @Override @@ -352,7 +402,7 @@ public Struct createStruct(String typeName, Object[] attributes) throws SQLExcep @Override public void setSchema(String schema) throws SQLException { // TODO Auto-generated method stub - + logger.info("[Conn] setSchema NOT_IMPLEMENTED "); } @Override @@ -372,4 +422,5 @@ public int getNetworkTimeout() throws SQLException { // TODO Auto-generated method stub return 0; } + } diff --git a/sf-jdbc-driver/src/main/java/com/ascendix/jdbc/salesforce/connection/ForceService.java b/sf-jdbc-driver/src/main/java/com/ascendix/jdbc/salesforce/connection/ForceService.java index cc07f38..c824b77 100644 --- a/sf-jdbc-driver/src/main/java/com/ascendix/jdbc/salesforce/connection/ForceService.java +++ b/sf-jdbc-driver/src/main/java/com/ascendix/jdbc/salesforce/connection/ForceService.java @@ -74,6 +74,7 @@ private static PartnerConnection createConnectionBySessionId(ForceConnectionInfo private static PartnerConnection createConnectionByUserCredential(ForceConnectionInfo info) throws ConnectionException { + ConnectorConfig partnerConfig = new ConnectorConfig(); partnerConfig.setUsername(info.getUserName()); partnerConfig.setPassword(info.getPassword()); @@ -87,7 +88,7 @@ private static PartnerConnection createConnectionByUserCredential(ForceConnectio try { info.setSandbox(false); partnerConfig.setAuthEndpoint(buildAuthEndpoint(info)); - connection = Connector.newConnection(partnerConfig); + connection = Connector.newConnection(partnerConfig); } catch (ConnectionException ce) { info.setSandbox(true); partnerConfig.setAuthEndpoint(buildAuthEndpoint(info)); diff --git a/sf-jdbc-driver/src/main/java/com/ascendix/jdbc/salesforce/delegates/PartnerService.java b/sf-jdbc-driver/src/main/java/com/ascendix/jdbc/salesforce/delegates/PartnerService.java index a13477d..1267ad7 100644 --- a/sf-jdbc-driver/src/main/java/com/ascendix/jdbc/salesforce/delegates/PartnerService.java +++ b/sf-jdbc-driver/src/main/java/com/ascendix/jdbc/salesforce/delegates/PartnerService.java @@ -3,26 +3,22 @@ import com.ascendix.jdbc.salesforce.metadata.Column; import com.ascendix.jdbc.salesforce.metadata.Table; import com.ascendix.jdbc.salesforce.statement.FieldDef; -import com.sforce.soap.partner.DescribeGlobalResult; -import com.sforce.soap.partner.DescribeGlobalSObjectResult; -import com.sforce.soap.partner.DescribeSObjectResult; -import com.sforce.soap.partner.Field; -import com.sforce.soap.partner.PartnerConnection; -import com.sforce.soap.partner.QueryResult; +import com.sforce.soap.partner.*; +import com.sforce.soap.partner.sobject.SObject; import com.sforce.ws.ConnectionException; import com.sforce.ws.bind.XmlObject; import org.apache.commons.collections4.IteratorUtils; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.List; +import java.util.*; +import java.util.logging.Logger; import java.util.stream.Collectors; +import java.util.stream.Stream; public class PartnerService { + private static final String SF_JDBC_DRIVER_NAME = "SF JDBC driver"; + private static final Logger logger = Logger.getLogger(SF_JDBC_DRIVER_NAME); + private PartnerConnection partnerConnection; private List sObjectTypesCache; @@ -31,17 +27,22 @@ public PartnerService(PartnerConnection partnerConnection) { } public List getTables() { + logger.info("[PartnerService] getTables IMPLEMENTED "); List sObjects = getSObjectsDescription(); - return sObjects.stream() + List
tables = sObjects.stream() .map(this::convertToTable) .collect(Collectors.toList()); + logger.info("[PartnerService] getTables tables count="+tables.size()); + return tables; } public DescribeSObjectResult describeSObject(String sObjectType) throws ConnectionException { + logger.info("[PartnerService] describeSObject "+sObjectType); return partnerConnection.describeSObject(sObjectType); } private Table convertToTable(DescribeSObjectResult so) { + logger.info("[PartnerService] convertToTable "+so.getName()); List fields = Arrays.asList(so.getFields()); List columns = fields.stream() .map(this::convertToColumn) @@ -83,6 +84,7 @@ private List getSObjectTypes() throws ConnectionException { sObjectTypesCache = Arrays.stream(sobs) .map(DescribeGlobalSObjectResult::getName) .collect(Collectors.toList()); + logger.info("[PartnerService] getSObjectTypes count="+sObjectTypesCache.size()); } return sObjectTypesCache; @@ -127,40 +129,58 @@ private List> toBatches(List objects, int batchSize) { } public List query(String soql, List expectedSchema) throws ConnectionException { + logger.info("[PartnerService] query "+soql); List resultRows = Collections.synchronizedList(new LinkedList<>()); QueryResult queryResult = null; do { queryResult = queryResult == null ? partnerConnection.query(soql) : partnerConnection.queryMore(queryResult.getQueryLocator()); - resultRows.addAll(removeServiceInfo(Arrays.asList(queryResult.getRecords()))); + + List rows = Arrays.asList(queryResult.getRecords()); + // extract the root entity name + Object rootEntityName = rows.stream().filter(xmlo -> "type".equals(xmlo.getName().getLocalPart())).findFirst().map(XmlObject::getValue).orElse(null); + String parentName = null; + resultRows.addAll(removeServiceInfo(rows, parentName, rootEntityName==null ? null : (String)rootEntityName)); } while (!queryResult.isDone()); return PartnerResultToCrtesianTable.expand(resultRows, expectedSchema); } - private List removeServiceInfo(Iterator rows) { - return removeServiceInfo(IteratorUtils.toList(rows)); - } - - private List removeServiceInfo(List rows) { + private List removeServiceInfo(List rows, String parentName, String rootEntityName) { return rows.stream() .filter(this::isDataObjectType) - .map(this::removeServiceInfo) + .map(row -> removeServiceInfo(row, parentName, rootEntityName)) .collect(Collectors.toList()); } - private List removeServiceInfo(XmlObject row) { + private List removeServiceInfo(XmlObject row, String parentName, String rootEntityName) { return IteratorUtils.toList(row.getChildren()).stream() .filter(this::isDataObjectType) .skip(1) // Removes duplicate Id from SF Partner API response // (https://developer.salesforce.com/forums/?id=906F00000008kciIAA) - .map(field -> isNestedResultset(field) - ? removeServiceInfo(field.getChildren()) - : toForceResultField(field)) + .flatMap(field -> translateField(field, parentName, rootEntityName)) .collect(Collectors.toList()); } - private ForceResultField toForceResultField(XmlObject field) { + private Stream translateField(XmlObject field, String parentName, String rootEntityName) { + Stream.Builder outStream = Stream.builder(); + + String fieldType = field.getXmlType() != null ? field.getXmlType().getLocalPart() : null; + if ("sObject".equalsIgnoreCase(fieldType)) { + List childFields = removeServiceInfo(field, field.getName().getLocalPart(), rootEntityName); + childFields.forEach(outStream::add); + } else { + if (isNestedResultset(field)) { + outStream.add(removeServiceInfo(IteratorUtils.toList(field.getChildren()), field.getName().getLocalPart(), rootEntityName)); + } else { + outStream.add(toForceResultField(field, parentName, rootEntityName)); + } + } + return outStream.build(); + } + + + private ForceResultField toForceResultField(XmlObject field, String parentName, String rootEntityName) { String fieldType = field.getXmlType() != null ? field.getXmlType().getLocalPart() : null; if ("sObject".equalsIgnoreCase(fieldType)) { List children = new ArrayList<>(); @@ -168,6 +188,9 @@ private ForceResultField toForceResultField(XmlObject field) { field = children.get(2); } String name = field.getName().getLocalPart(); + if (parentName != null && (rootEntityName == null || !rootEntityName.equals(parentName))) { + name = parentName+"."+name; + } Object value = field.getValue(); return new ForceResultField(null, fieldType, name, value); } @@ -179,7 +202,47 @@ private boolean isNestedResultset(XmlObject object) { private final static List SOAP_RESPONSE_SERVICE_OBJECT_TYPES = Arrays.asList("type", "done", "queryLocator", "size"); - private boolean isDataObjectType(XmlObject object) { - return !SOAP_RESPONSE_SERVICE_OBJECT_TYPES.contains(object.getName().getLocalPart()); + private boolean isDataObjectType(XmlObject obj) { + return !SOAP_RESPONSE_SERVICE_OBJECT_TYPES.contains(obj.getName().getLocalPart()); + } + + public SaveResult[] createRecords(String entityName, List> recordsDefinitions) throws ConnectionException { + // Create a new sObject of type Contact + // and fill out its fields. + + SObject[] records = new SObject[recordsDefinitions.size()]; + + + for (int i = 0; i < recordsDefinitions.size(); i++) { + Map recordDef = recordsDefinitions.get(i); + SObject record = records[i] = new SObject(); + record.setType(entityName); + for (Map.Entry field: recordDef.entrySet()) { + record.setField(field.getKey(), field.getValue()); + } + } + // Make a create call and pass it the array of sObjects + SaveResult[] results = partnerConnection.create(records); + return results; + } + + public SaveResult[] saveRecords(String entityName, List> recordsDefinitions) throws ConnectionException { + // Create a new sObject of type Contact + // and fill out its fields. + + SObject[] records = new SObject[recordsDefinitions.size()]; + + + for (int i = 0; i < recordsDefinitions.size(); i++) { + Map recordDef = recordsDefinitions.get(i); + SObject record = records[i] = new SObject(); + record.setType(entityName); + for (Map.Entry field: recordDef.entrySet()) { + record.setField(field.getKey(), field.getValue()); + } + } + // Make a create call and pass it the array of sObjects + SaveResult[] results = partnerConnection.update(records); + return results; } } diff --git a/sf-jdbc-driver/src/main/java/com/ascendix/jdbc/salesforce/exceptions/UnsupportedArgumentTypeException.java b/sf-jdbc-driver/src/main/java/com/ascendix/jdbc/salesforce/exceptions/UnsupportedArgumentTypeException.java new file mode 100644 index 0000000..be789f1 --- /dev/null +++ b/sf-jdbc-driver/src/main/java/com/ascendix/jdbc/salesforce/exceptions/UnsupportedArgumentTypeException.java @@ -0,0 +1,13 @@ +package com.ascendix.jdbc.salesforce.exceptions; + +public class UnsupportedArgumentTypeException extends RuntimeException { + + public UnsupportedArgumentTypeException(String message) { + super(message); + } + + public UnsupportedArgumentTypeException(String message, Throwable cause) { + super(message, cause); + } + +} diff --git a/sf-jdbc-driver/src/main/java/com/ascendix/jdbc/salesforce/metadata/ColumnMap.java b/sf-jdbc-driver/src/main/java/com/ascendix/jdbc/salesforce/metadata/ColumnMap.java index 9a6a896..8dd213f 100644 --- a/sf-jdbc-driver/src/main/java/com/ascendix/jdbc/salesforce/metadata/ColumnMap.java +++ b/sf-jdbc-driver/src/main/java/com/ascendix/jdbc/salesforce/metadata/ColumnMap.java @@ -18,6 +18,11 @@ public V put(K key, V value) { return value; } + public ColumnMap add(K key, V value) { + put(key, value); + return this; + } + public V get(K key) { int index = columnNames.indexOf(key); return index != -1 ? values.get(index) : null; @@ -30,4 +35,16 @@ public V get(K key) { public V getByIndex(int index) { return values.get(index - 1); } + + public int size() { + return columnNames.size(); + } + + public ArrayList getColumnNames() { + return columnNames; + } + + public ArrayList getValues() { + return values; + } } diff --git a/sf-jdbc-driver/src/main/java/com/ascendix/jdbc/salesforce/metadata/ForceDatabaseMetaData.java b/sf-jdbc-driver/src/main/java/com/ascendix/jdbc/salesforce/metadata/ForceDatabaseMetaData.java index 62518ce..60dba57 100644 --- a/sf-jdbc-driver/src/main/java/com/ascendix/jdbc/salesforce/metadata/ForceDatabaseMetaData.java +++ b/sf-jdbc-driver/src/main/java/com/ascendix/jdbc/salesforce/metadata/ForceDatabaseMetaData.java @@ -1,10 +1,10 @@ package com.ascendix.jdbc.salesforce.metadata; +import com.ascendix.jdbc.salesforce.ForceDriver; import com.ascendix.jdbc.salesforce.connection.ForceConnection; import com.ascendix.jdbc.salesforce.delegates.PartnerService; import com.ascendix.jdbc.salesforce.resultset.CachedResultSet; -import org.apache.commons.lang3.tuple.ImmutablePair; -import org.apache.commons.lang3.tuple.Pair; +import com.ascendix.jdbc.salesforce.statement.ForcePreparedStatement; import java.io.Serializable; import java.sql.Connection; @@ -15,11 +15,18 @@ import java.sql.Types; import java.util.*; import java.util.concurrent.atomic.AtomicInteger; +import java.util.logging.Logger; import java.util.stream.Collectors; public class ForceDatabaseMetaData implements DatabaseMetaData, Serializable { - private static final String DEFAULT_SCHEMA = "Salesforce"; + private static final String SF_JDBC_DRIVER_NAME = "SF JDBC driver"; + private static final Logger logger = Logger.getLogger(SF_JDBC_DRIVER_NAME); + + public static final String DEFAULT_SCHEMA = "Salesforce"; + public static final String DEFAULT_CATALOG = "database"; + public static final String DEFAULT_TABLE_TYPE = "TABLE"; + private transient PartnerService partnerService; private transient ForceConnection connection; private List
tablesCache; @@ -30,36 +37,53 @@ public ForceDatabaseMetaData(ForceConnection connection) { this.partnerService = new PartnerService(connection.getPartnerConnection()); } + private ForceDatabaseMetaData() { + this.connection = connection; + this.partnerService = null; + } + @Override public ResultSet getTables(String catalog, String schemaPattern, String tableNamePattern, String[] types) { - List> maps = new ArrayList<>(); + logger.info("[Meta] getTables catalog="+catalog+" schema="+schemaPattern+" table="+tableNamePattern); + List> rows = new ArrayList<>(); + ColumnMap firstRow = null; for (Table table : getTables()) { - ColumnMap map = new ColumnMap<>(); - map.put("TABLE_CAT", null); - map.put("TABLE_SCHEM", null); - map.put("TABLE_NAME", table.getName()); - map.put("TABLE_TYPE", "TABLE"); - map.put("REMARKS", table.getComments()); - map.put("TYPE_CAT", null); - map.put("TYPE_SCHEM", null); - map.put("TYPE_NAME", null); - map.put("SELF_REFERENCING_COL_NAME", null); - map.put("REF_GENERATION", null); - maps.add(map); + if(tableNamePattern == null || "%".equals(tableNamePattern.trim()) || table.getName().equalsIgnoreCase(tableNamePattern)) { + ColumnMap map = new ColumnMap<>(); + map.put("TABLE_CAT", DEFAULT_CATALOG); + map.put("TABLE_SCHEM", DEFAULT_SCHEMA); + map.put("TABLE_NAME", table.getName()); + map.put("TABLE_TYPE", DEFAULT_TABLE_TYPE); + map.put("REMARKS", table.getComments()); + map.put("TYPE_CAT", null); + map.put("TYPE_SCHEM", null); + map.put("TYPE_NAME", null); + map.put("SELF_REFERENCING_COL_NAME", null); + map.put("REF_GENERATION", null); + rows.add(map); + if (firstRow == null) { + firstRow = map; + } + } } - return new CachedResultSet(maps); + logger.info("[Meta] getTables RESULT catalog="+catalog+" schema="+schemaPattern+" table="+tableNamePattern+ + "\n firstRowFound="+(firstRow!=null?"yes":"no")+ " TablesFound="+rows.size()); + return new CachedResultSet(rows, ForcePreparedStatement.dummyMetaData(firstRow)); } private List
getTables() { if (tablesCache == null) { + logger.info("[Meta] getTables requested - fetching"); tablesCache = partnerService.getTables(); + } else { + logger.info("[Meta] getTables requested - from cache"); } return tablesCache; } public Table findTableInfo(String tableName) { return getTables().stream() - .filter(table -> tableName.equals(table.getName())) + .filter(table -> table.getName().equalsIgnoreCase(tableName)) .findFirst() .orElse(null); } @@ -67,14 +91,15 @@ public Table findTableInfo(String tableName) { @Override public ResultSet getColumns(String catalog, String schemaPattern, String tableNamePattern, String columnNamePattern) { AtomicInteger ordinal = new AtomicInteger(1); - return new CachedResultSet(getTables().stream() - .filter(table -> tableNamePattern == null || table.getName().equals(tableNamePattern)) + logger.info("[Meta] getColumns catalog="+catalog+" schema="+schemaPattern+" table="+tableNamePattern+" column="+columnNamePattern ); + List> rows = getTables().stream() + .filter(table -> tableNamePattern == null || "%".equals(tableNamePattern.trim()) || table.getName().equalsIgnoreCase(tableNamePattern)) .flatMap(table -> table.getColumns().stream()) - .filter(column -> columnNamePattern == null || column.getName().equals(columnNamePattern)) + .filter(column -> columnNamePattern == null || "%".equals(columnNamePattern.trim())|| column.getName().equalsIgnoreCase(columnNamePattern)) .map(column -> new ColumnMap() {{ TypeInfo typeInfo = lookupTypeInfo(column.getType()); - put("TABLE_CAT", null); - put("TABLE_SCHEM", null); + put("TABLE_CAT", DEFAULT_CATALOG); + put("TABLE_SCHEM", DEFAULT_SCHEMA); put("TABLE_NAME", column.getTable().getName()); put("COLUMN_NAME", column.getName()); put("DATA_TYPE", typeInfo != null ? typeInfo.sqlDataType : Types.OTHER); @@ -100,8 +125,11 @@ public ResultSet getColumns(String catalog, String schemaPattern, String tableNa column.isNillable() ? DatabaseMetaData.columnNullable : DatabaseMetaData.columnNoNulls); }}) - .collect(Collectors.toList()) - ); + .collect(Collectors.toList()); + ColumnMap firstRow = rows.size() > 0 ? rows.get(0) : null; + logger.info("[Meta] getColumns RESULT catalog="+catalog+" schema="+schemaPattern+" table="+tableNamePattern+" column="+columnNamePattern + + "\n firstRowFound="+(firstRow!=null?"yes":"no")+ " ColumnsFound="+rows.size()); + return new CachedResultSet(rows, ForcePreparedStatement.dummyMetaData(firstRow)); } public static TypeInfo lookupTypeInfo(String forceTypeName) { @@ -112,42 +140,67 @@ public static TypeInfo lookupTypeInfo(String forceTypeName) { .orElse(OTHER_TYPE_INFO); } + public static TypeInfo lookupTypeInfoFromJavaType(String javaTypeName) { + if (javaTypeName == null) { + javaTypeName = "string"; + } + if (javaTypeName.equals("java.lang.Boolean")) { + javaTypeName = "boolean"; + } + if (javaTypeName.equals("java.lang.String")) { + javaTypeName = "string"; + } + String typeName = javaTypeName; + return Arrays.stream(TYPE_INFO_DATA) + .filter(entry -> typeName.equals(entry.typeName)) + .findAny() + .orElse(OTHER_TYPE_INFO); + } + @Override public ResultSet getSchemas() throws SQLException { ColumnMap row = new ColumnMap<>(); row.put("TABLE_SCHEM", DEFAULT_SCHEMA); - row.put("TABLE_CATALOG", null); + row.put("TABLE_CATALOG", DEFAULT_CATALOG); row.put("IS_DEFAULT", true); - return new CachedResultSet(row); + return new CachedResultSet(row, ForcePreparedStatement.dummyMetaData(row)); } @Override public ResultSet getPrimaryKeys(String catalog, String schema, String tableName) throws SQLException { + logger.info("[Meta] getPrimaryKeys RESULT catalog="+catalog+" schema="+schema+" table="+tableName); List> maps = new ArrayList<>(); + ColumnMap firstRow = null; for (Table table : getTables()) { - if (table.getName().equals(tableName)) { + if (tableName == null || "%".equals(tableName.trim()) || table.getName().equalsIgnoreCase(tableName)) { for (Column column : table.getColumns()) { if (column.getName().equalsIgnoreCase("Id")) { ColumnMap map = new ColumnMap<>(); - map.put("TABLE_CAT", null); - map.put("TABLE_SCHEM", null); + map.put("TABLE_CAT", DEFAULT_CATALOG); + map.put("TABLE_SCHEM", DEFAULT_SCHEMA); map.put("TABLE_NAME", table.getName()); map.put("COLUMN_NAME", "" + column.getName()); map.put("KEY_SEQ", 0); map.put("PK_NAME", "FakePK" + counter); maps.add(map); + if (firstRow == null) { + firstRow = map; + } } } } } - return new CachedResultSet(maps); + logger.info("[Meta] getPrimaryKeys RESULT catalog="+catalog+" schema="+schema+" table="+tableName+ + "\n firstRowFound="+(firstRow!=null?"yes":"no")+ " KeysFound="+maps.size()); + return new CachedResultSet(maps, ForcePreparedStatement.dummyMetaData(firstRow)); } @Override public ResultSet getImportedKeys(String catalog, String schema, String tableName) throws SQLException { List> maps = new ArrayList<>(); + ColumnMap firstRow = null; for (Table table : getTables()) { - if (table.getName().equals(tableName)) { + if (tableName == null || "%".equals(tableName.trim()) || table.getName().equalsIgnoreCase(tableName)) { for (Column column : table.getColumns()) { if (column.getReferencedTable() != null && column.getReferencedColumn() != null) { ColumnMap map = new ColumnMap<>(); @@ -167,23 +220,27 @@ public ResultSet getImportedKeys(String catalog, String schema, String tableName map.put("DEFERRABILITY", 0); counter++; maps.add(map); + if (firstRow == null) { + firstRow = map; + } } } } } - return new CachedResultSet(maps); + return new CachedResultSet(maps, ForcePreparedStatement.dummyMetaData(firstRow)); } @Override public ResultSet getIndexInfo(String catalog, String schema, String tableName, boolean unique, boolean approximate) { List> maps = new ArrayList<>(); + ColumnMap firstRow = null; for (Table table : getTables()) { - if (table.getName().equals(tableName)) { + if (tableName == null || "%".equals(tableName.trim()) || table.getName().equalsIgnoreCase(tableName)) { for (Column column : table.getColumns()) { if (column.getName().equalsIgnoreCase("Id")) { ColumnMap map = new ColumnMap<>(); - map.put("TABLE_CAT", null); - map.put("TABLE_SCHEM", null); + map.put("TABLE_CAT", DEFAULT_CATALOG); + map.put("TABLE_SCHEM", DEFAULT_SCHEMA); map.put("TABLE_NAME", table.getName()); map.put("NON_UNIQUE", true); map.put("INDEX_QUALIFIER", null); @@ -197,17 +254,23 @@ public ResultSet getIndexInfo(String catalog, String schema, String tableName, b map.put("FILTER_CONDITION", null); maps.add(map); + + if (firstRow == null) { + firstRow = map; + } } } } } - return new CachedResultSet(maps); + return new CachedResultSet(maps, ForcePreparedStatement.dummyMetaData(firstRow)); } @SuppressWarnings("unchecked") @Override public ResultSet getCatalogs() throws SQLException { - return new CachedResultSet(Collections.EMPTY_LIST); + ColumnMap row = new ColumnMap<>(); + row.put("TABLE_CAT", DEFAULT_CATALOG); + return new CachedResultSet(row, ForcePreparedStatement.dummyMetaData(row)); } public static class TypeInfo { @@ -263,6 +326,7 @@ public TypeInfo(String typeName, int sqlDataType, int precision, int minScale, i @Override public ResultSet getTypeInfo() throws SQLException { + ColumnMap firstRow = null; List> rows = new ArrayList<>(); for (TypeInfo typeInfo : TYPE_INFO_DATA) { ColumnMap row = new ColumnMap<>(); @@ -287,13 +351,16 @@ public ResultSet getTypeInfo() throws SQLException { row.put("TYPE_SUB", 1); rows.add(row); + if (firstRow == null) { + firstRow = row; + } } - return new CachedResultSet(rows); + return new CachedResultSet(rows, ForcePreparedStatement.dummyMetaData(firstRow)); } @Override public T unwrap(Class iface) throws SQLException { - // TODO Auto-generated method stub + logger.info("[Meta] unwrap requested NOT_IMPLEMENTED ifaceType="+iface.getName()); return null; } @@ -318,7 +385,7 @@ public boolean allTablesAreSelectable() throws SQLException { @Override public String getURL() throws SQLException { // TODO Auto-generated method stub - return ""; + return null; } @Override @@ -359,12 +426,12 @@ public boolean nullsAreSortedAtEnd() throws SQLException { @Override public String getDatabaseProductName() throws SQLException { - return "Ascendix JDBC driver for Salesforce"; + return "Salesforce"; } @Override public String getDatabaseProductVersion() throws SQLException { - return "39"; + return String.valueOf(getDatabaseMajorVersion()); } @Override @@ -374,7 +441,7 @@ public String getDriverName() throws SQLException { @Override public String getDriverVersion() throws SQLException { - return "1.1"; + return getDriverMajorVersion()+"."+getDriverMinorVersion()+".0.0"; } @Override @@ -384,7 +451,7 @@ public int getDriverMajorVersion() { @Override public int getDriverMinorVersion() { - return 0; + return 4; } @Override @@ -660,7 +727,7 @@ public boolean supportsLimitedOuterJoins() throws SQLException { @Override public String getSchemaTerm() throws SQLException { // TODO Auto-generated method stub - return ""; + return DEFAULT_SCHEMA; } @Override @@ -672,7 +739,7 @@ public String getProcedureTerm() throws SQLException { @Override public String getCatalogTerm() throws SQLException { // TODO Auto-generated method stub - return ""; + return DEFAULT_CATALOG; } @Override @@ -684,7 +751,7 @@ public boolean isCatalogAtStart() throws SQLException { @Override public String getCatalogSeparator() throws SQLException { // TODO Auto-generated method stub - return ""; + return "."; } @Override @@ -1009,60 +1076,71 @@ public boolean dataDefinitionIgnoredInTransactions() throws SQLException { public ResultSet getProcedures(String catalog, String schemaPattern, String procedureNamePattern) throws SQLException { // TODO Auto-generated method stub - return null; + logger.info("[Meta] getProcedures requested NOT_IMPLEMENTED catalog="+catalog+" schema="+schemaPattern+" proc="+procedureNamePattern); + return new CachedResultSet(Collections.EMPTY_LIST, null); } @Override public ResultSet getProcedureColumns(String catalog, String schemaPattern, String procedureNamePattern, String columnNamePattern) throws SQLException { // TODO Auto-generated method stub - return null; + logger.info("[Meta] getProcedureColumns requested NOT_IMPLEMENTED catalog="+catalog+" schema="+schemaPattern+" procs="+procedureNamePattern+" col="+columnNamePattern); + return new CachedResultSet(Collections.EMPTY_LIST, null); } @Override public ResultSet getTableTypes() throws SQLException { - // TODO Auto-generated method stub - return null; + logger.info("[Meta] getTableTypes requested IMPLEMENTED"); + ColumnMap row = new ColumnMap<>(); + row.put("TABLE_TYPE", DEFAULT_TABLE_TYPE); + return new CachedResultSet(row, ForcePreparedStatement.dummyMetaData(row)); } @Override public ResultSet getColumnPrivileges(String catalog, String schema, String table, String columnNamePattern) throws SQLException { + logger.info("[Meta] getColumnPrivileges requested NOT_IMPLEMENTED catalog="+catalog+" schema="+schema+" table="+table+" column="+columnNamePattern); // TODO Auto-generated method stub - return null; + return new CachedResultSet(Collections.EMPTY_LIST, null); } @Override public ResultSet getTablePrivileges(String catalog, String schemaPattern, String tableNamePattern) throws SQLException { + logger.info("[Meta] getTablePrivileges requested NOT_IMPLEMENTED catalog="+catalog+" schema="+schemaPattern+" table="+tableNamePattern); // TODO Auto-generated method stub - return null; + return new CachedResultSet(Collections.EMPTY_LIST, null); } @Override public ResultSet getBestRowIdentifier(String catalog, String schema, String table, int scope, boolean nullable) throws SQLException { + logger.info("[Meta] getBestRowIdentifier requested NOT_IMPLEMENTED catalog="+catalog+" schema="+schema+" table="+table); // TODO Auto-generated method stub - return null; + return new CachedResultSet(Collections.EMPTY_LIST, null); } @Override public ResultSet getVersionColumns(String catalog, String schema, String table) throws SQLException { + logger.info("[Meta] getVersionColumns requested NOT_IMPLEMENTED catalog="+catalog+" schema="+schema+" table="+table); // TODO Auto-generated method stub - return null; + return new CachedResultSet(Collections.EMPTY_LIST, null); } @Override public ResultSet getExportedKeys(String catalog, String schema, String table) throws SQLException { + logger.info("[Meta] getExportedKeys requested NOT_IMPLEMENTED catalog="+catalog+" schema="+schema+" table="+table); // TODO Auto-generated method stub - return null; + return new CachedResultSet(Collections.EMPTY_LIST, null); } @Override public ResultSet getCrossReference(String parentCatalog, String parentSchema, String parentTable, String foreignCatalog, String foreignSchema, String foreignTable) throws SQLException { + logger.info("[Meta] getCrossReference requested NOT_IMPLEMENTED parentCat="+parentCatalog+" parentSc="+parentSchema+" parentTable="+parentTable+" catalog="+foreignCatalog+" schema="+foreignSchema+" table="+foreignTable); + // TODO Auto-generated method stub - return null; + return new CachedResultSet(Collections.EMPTY_LIST, null); } @Override @@ -1141,7 +1219,8 @@ public boolean supportsBatchUpdates() throws SQLException { public ResultSet getUDTs(String catalog, String schemaPattern, String typeNamePattern, int[] types) throws SQLException { // TODO Auto-generated method stub - return null; + logger.info("[Meta] getUDTs requested NOT_IMPLEMENTED"); + return new CachedResultSet(Collections.EMPTY_LIST, null); } @Override @@ -1177,20 +1256,23 @@ public boolean supportsGetGeneratedKeys() throws SQLException { @Override public ResultSet getSuperTypes(String catalog, String schemaPattern, String typeNamePattern) throws SQLException { // TODO Auto-generated method stub - return null; + logger.info("[Meta] getSuperTypes requested NOT_IMPLEMENTED catalog="+catalog+" schema="+schemaPattern+" type="+typeNamePattern); + return new CachedResultSet(Collections.EMPTY_LIST, null); } @Override public ResultSet getSuperTables(String catalog, String schemaPattern, String tableNamePattern) throws SQLException { // TODO Auto-generated method stub - return null; + logger.info("[Meta] getSuperTables requested NOT_IMPLEMENTED catalog="+catalog+" schema="+schemaPattern+" table="+tableNamePattern); + return new CachedResultSet(Collections.EMPTY_LIST, null); } @Override public ResultSet getAttributes(String catalog, String schemaPattern, String typeNamePattern, String attributeNamePattern) throws SQLException { // TODO Auto-generated method stub - return null; + logger.info("[Meta] getAttributes requested NOT_IMPLEMENTED catalog="+catalog+" schema="+schemaPattern+" type="+typeNamePattern+" attr="+attributeNamePattern); + return new CachedResultSet(Collections.EMPTY_LIST, null); } @Override @@ -1207,7 +1289,7 @@ public int getResultSetHoldability() throws SQLException { @Override public int getDatabaseMajorVersion() throws SQLException { - return 39; + return 51; } @Override @@ -1246,6 +1328,7 @@ public boolean supportsStatementPooling() throws SQLException { @Override public RowIdLifetime getRowIdLifetime() throws SQLException { // TODO Auto-generated method stub + logger.info("[Meta] getRowIdLifetime requested NOT_IMPLEMENTED"); return null; } @@ -1269,28 +1352,32 @@ public boolean autoCommitFailureClosesAllResultSets() throws SQLException { @Override public ResultSet getClientInfoProperties() throws SQLException { // TODO Auto-generated method stub - return null; + logger.info("[Meta] getClientInfoProperties requested NOT_IMPLEMENTED"); + return new CachedResultSet(Collections.EMPTY_LIST, null); } @Override public ResultSet getFunctions(String catalog, String schemaPattern, String functionNamePattern) throws SQLException { // TODO Auto-generated method stub - return null; + logger.info("[Meta] getSuperTables requested NOT_IMPLEMENTED catalog="+catalog+" schema="+schemaPattern+" func="+functionNamePattern); + return new CachedResultSet(Collections.EMPTY_LIST, null); } @Override public ResultSet getFunctionColumns(String catalog, String schemaPattern, String functionNamePattern, String columnNamePattern) throws SQLException { // TODO Auto-generated method stub - return null; + logger.info("[Meta] getSuperTables requested NOT_IMPLEMENTED catalog="+catalog+" schema="+schemaPattern+" func="+functionNamePattern+" column="+columnNamePattern); + return new CachedResultSet(Collections.EMPTY_LIST, null); } @Override public ResultSet getPseudoColumns(String catalog, String schemaPattern, String tableNamePattern, String columnNamePattern) throws SQLException { // TODO Auto-generated method stub - return null; + logger.info("[Meta] getPseudoColumns requested NOT_IMPLEMENTED catalog="+catalog+" schema="+schemaPattern+" table="+tableNamePattern+" column="+columnNamePattern); + return new CachedResultSet(Collections.EMPTY_LIST, null); } @Override @@ -1299,4 +1386,28 @@ public boolean generatedKeyAlwaysReturned() throws SQLException { return false; } + public static void main(String[] args) throws SQLException { + ForceDatabaseMetaData metadata = new ForceDatabaseMetaData(); + System.out.println(metadata.getDriverName() + " version "+metadata.getDriverVersion()+ " for API "+metadata.getDatabaseProductVersion()); + + if (args.length > 0) { + System.out.println("Test the tables from the url "); + ForceDriver driver = new ForceDriver(); + ForceConnection connection = (ForceConnection)driver.connect(args[0], new Properties()); + + ForceDatabaseMetaData metaData = new ForceDatabaseMetaData(connection); + ResultSet schemas = metaData.getSchemas(); + ResultSet catalogs = metaData.getCatalogs(); + String[] types = null; + ResultSet tables = metaData.getTables("catalog", "", "%", types); + int count = 0; + while(tables.next()) { + System.out.println(" "+tables.getString("TABLE_NAME")); + count++; + } + System.out.println(count+" Tables total"); + } + } + + } diff --git a/sf-jdbc-driver/src/main/java/com/ascendix/jdbc/salesforce/resultset/CachedResultSet.java b/sf-jdbc-driver/src/main/java/com/ascendix/jdbc/salesforce/resultset/CachedResultSet.java index 78fc9a5..532df05 100644 --- a/sf-jdbc-driver/src/main/java/com/ascendix/jdbc/salesforce/resultset/CachedResultSet.java +++ b/sf-jdbc-driver/src/main/java/com/ascendix/jdbc/salesforce/resultset/CachedResultSet.java @@ -25,34 +25,42 @@ import java.sql.Timestamp; import java.text.ParseException; import java.text.SimpleDateFormat; -import java.util.Arrays; -import java.util.Base64; -import java.util.Calendar; -import java.util.GregorianCalendar; -import java.util.List; -import java.util.Map; -import java.util.Optional; +import java.util.*; import java.util.function.Function; +import java.util.logging.Logger; public class CachedResultSet implements ResultSet, Serializable { + private static final String SF_JDBC_DRIVER_NAME = "SF JDBC driver RS"; + private static final Logger logger = Logger.getLogger(SF_JDBC_DRIVER_NAME); + private static final long serialVersionUID = 1L; private transient Integer index; - private List> rows; + private List> rows = new ArrayList<>(); private ResultSetMetaData metadata; + private SQLWarning warningsChain; public CachedResultSet(List> rows) { - this.rows = rows; + this.rows = new ArrayList(rows); } public CachedResultSet(List> rows, ResultSetMetaData metadata) { - this(rows); + this(new ArrayList(rows)); + this.metadata = metadata; + } + + public CachedResultSet(ResultSetMetaData metadata) { + this(new ArrayList()); this.metadata = metadata; } public CachedResultSet(ColumnMap singleRow) { - this(Arrays.asList(singleRow)); + this(new ArrayList(Arrays.asList(singleRow))); + } + + public CachedResultSet(ColumnMap singleRow, ResultSetMetaData metadata) { + this(new ArrayList(Arrays.asList(singleRow)), metadata); } public Object getObject(String columnName) throws SQLException { @@ -63,6 +71,10 @@ public Object getObject(int columnIndex) throws SQLException { return rows.get(getIndex()).getByIndex(columnIndex); } + protected void addRow(ColumnMap row) { + rows.add(row); + } + private int getIndex() { if (index == null) { index = -1; @@ -421,7 +433,8 @@ public void cancelRowUpdates() throws SQLException { } public void clearWarnings() throws SQLException { - + logger.info("clearWarnings"); + this.warningsChain = null; } public void close() throws SQLException { @@ -565,8 +578,29 @@ public InputStream getUnicodeStream(String columnName) throws SQLException { } public SQLWarning getWarnings() throws SQLException { + return warningsChain; + } - return null; + public void addWarning(SQLWarning warn) { + logger.info("Adding Warning: "+warn.getMessage()); + if (warningsChain != null) { + SQLWarning last = warningsChain; + while (last != null && last.getNextWarning() != null) last = last.getNextWarning(); + last.setNextWarning(warn); + } else { + warningsChain = warn; + } + } + + public void addWarning(String reason) { + logger.info("Adding Warning: "+reason); + if (warningsChain != null) { + SQLWarning last = warningsChain; + while (last != null && last.getNextWarning() != null) last = last.getNextWarning(); + last.setNextWarning(new SQLWarning(reason)); + } else { + warningsChain = new SQLWarning(reason); + } } public void insertRow() throws SQLException { diff --git a/sf-jdbc-driver/src/main/java/com/ascendix/jdbc/salesforce/resultset/CommandLogCachedResultSet.java b/sf-jdbc-driver/src/main/java/com/ascendix/jdbc/salesforce/resultset/CommandLogCachedResultSet.java new file mode 100644 index 0000000..6631a5c --- /dev/null +++ b/sf-jdbc-driver/src/main/java/com/ascendix/jdbc/salesforce/resultset/CommandLogCachedResultSet.java @@ -0,0 +1,27 @@ +package com.ascendix.jdbc.salesforce.resultset; + +import com.ascendix.jdbc.salesforce.metadata.ColumnMap; +import com.ascendix.jdbc.salesforce.statement.ForcePreparedStatement; + +import java.util.*; +import java.util.stream.Collectors; + +public class CommandLogCachedResultSet extends CachedResultSet { + + public static String LOG_COLUMN = "Log"; + + private static ColumnMap DEFAULT_COLUMN_MAP = new ColumnMap().add(LOG_COLUMN,"Value"); + + public CommandLogCachedResultSet() { + super(ForcePreparedStatement.dummyMetaData(DEFAULT_COLUMN_MAP)); + } + + public CommandLogCachedResultSet(List commandLog) { + super(commandLog.stream().map( logLine -> new ColumnMap().add(LOG_COLUMN, logLine)).collect(Collectors.toList()), ForcePreparedStatement.dummyMetaData(DEFAULT_COLUMN_MAP)); + } + + public void log(String logLine) { + addRow(new ColumnMap().add(LOG_COLUMN, logLine)); + } + +} diff --git a/sf-jdbc-driver/src/main/java/com/ascendix/jdbc/salesforce/statement/FieldDef.java b/sf-jdbc-driver/src/main/java/com/ascendix/jdbc/salesforce/statement/FieldDef.java index 7c2f88a..cbe3ddf 100644 --- a/sf-jdbc-driver/src/main/java/com/ascendix/jdbc/salesforce/statement/FieldDef.java +++ b/sf-jdbc-driver/src/main/java/com/ascendix/jdbc/salesforce/statement/FieldDef.java @@ -2,11 +2,17 @@ public class FieldDef { + /** Name of the field (or Name of the field used in aggregation) */ private String name; + /** Full bname of the field with sub entity or name of the aggregation function like: + * 1) Owner.Name for select Owner.Name from Account + * 2) maxLastName for MAX(LastName)*/ + private String alias; private String type; - public FieldDef(String name, String type) { + public FieldDef(String name, String alias, String type) { this.name = name; + this.alias = alias; this.type = type; } @@ -14,6 +20,10 @@ public String getName() { return name; } + public String getAlias() { + return alias; + } + public String getType() { return type; } diff --git a/sf-jdbc-driver/src/main/java/com/ascendix/jdbc/salesforce/statement/ForcePreparedStatement.java b/sf-jdbc-driver/src/main/java/com/ascendix/jdbc/salesforce/statement/ForcePreparedStatement.java index 5757982..b725177 100644 --- a/sf-jdbc-driver/src/main/java/com/ascendix/jdbc/salesforce/statement/ForcePreparedStatement.java +++ b/sf-jdbc-driver/src/main/java/com/ascendix/jdbc/salesforce/statement/ForcePreparedStatement.java @@ -6,6 +6,7 @@ import com.ascendix.jdbc.salesforce.delegates.ForceResultField; import com.ascendix.jdbc.salesforce.metadata.ColumnMap; import com.ascendix.jdbc.salesforce.metadata.ForceDatabaseMetaData; +import com.ascendix.jdbc.salesforce.statement.processor.*; import com.sforce.ws.ConnectionException; import org.apache.commons.lang3.StringUtils; import org.mapdb.DB; @@ -38,15 +39,11 @@ import java.sql.Timestamp; import java.text.DateFormat; import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.Calendar; -import java.util.Collections; -import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; +import java.util.*; import java.util.concurrent.TimeUnit; import java.util.function.Function; +import java.util.logging.Level; +import java.util.logging.Logger; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.stream.Collectors; @@ -54,6 +51,9 @@ public class ForcePreparedStatement implements PreparedStatement { + private static final String SF_JDBC_DRIVER_NAME = "SF JDBC driver"; + private static final Logger logger = Logger.getLogger(SF_JDBC_DRIVER_NAME); + private final static String CACHE_HINT = "(?is)\\A\\s*(CACHE\\s*(GLOBAL|SESSION)).*"; private final static int GB = 1073741824; @@ -68,8 +68,13 @@ protected enum CacheMode { private int fetchSize; private int maxRows; private List parameters = new ArrayList<>(); - private final CacheMode cacheMode; + private CacheMode cacheMode; private static DB cacheDb = DBMaker.tempFileDB().closeOnJvmShutdown().make(); + private int updateCount = -1; + private boolean updateCountReturned = false; + private ResultSet resultSet; + private boolean resultSetReturned = false; + private SQLWarning warnings = new SQLWarning(); // TODO: Join caches and move it to ForceConnection class. Divide to session // and static global cache. @@ -84,7 +89,13 @@ protected enum CacheMode { .expireStoreSize(1 * GB) .create(); + public ForcePreparedStatement(ForceConnection connection) { + logger.info("[PrepStat] constructor conn IMPLEMENTED "); + this.connection = connection; + } + public ForcePreparedStatement(ForceConnection connection, String soql) { + logger.info("[PrepStat] constructor soql IMPLEMENTED "+soql); this.connection = connection; this.cacheMode = getCacheMode(soql); this.soqlQuery = removeCacheHints(soql); @@ -96,6 +107,12 @@ public static RuntimeException rethrowAsNonChecked(Throwab @Override public ResultSet executeQuery() throws SQLException { + logger.info("[PrepStat] executeQuery IMPLEMENTED "+soqlQuery); + this.updateCount = -1; + this.updateCountReturned = false; + this.resultSetReturned = false; + this.resultSet = null; + return cacheMode == CacheMode.NO_CACHE ? query() : dataCache.computeIfAbsent(getCacheKey(), s -> { @@ -109,6 +126,34 @@ public ResultSet executeQuery() throws SQLException { } private ResultSet query() throws SQLException { + logger.info("[PrepStat] query IMPLEMENTED "+soqlQuery); + if ("SELECT 'keep alive'".equals(soqlQuery)) { + logger.info("[PrepStat] query KEEP ALIVE "); + return new CachedResultSet(Collections.emptyList(), getMetaData()); + } + if (AdminQueryProcessor.isAdminQuery(soqlQuery)) { + try { + return AdminQueryProcessor.processQuery(this, soqlQuery, getPartnerService()); + } catch (ConnectionException | SOQLParsingException e) { + throw new SQLException(e); + } + } + InsertQueryAnalyzer insertQueryAnalyzer = getInsertQueryAnalyzer(); + if (InsertQueryProcessor.isInsertQuery(soqlQuery, insertQueryAnalyzer)) { + try { + return InsertQueryProcessor.processQuery(this, soqlQuery, getPartnerService(), insertQueryAnalyzer); + } catch (ConnectionException | SOQLParsingException e) { + throw new SQLException(e); + } + } + UpdateQueryAnalyzer updateQueryAnalyzer = getUpdateQueryAnalyzer(); + if (UpdateQueryProcessor.isUpdateQuery(soqlQuery, updateQueryAnalyzer)) { + try { + return UpdateQueryProcessor.processQuery(this, soqlQuery, getPartnerService(), updateQueryAnalyzer); + } catch (ConnectionException | SOQLParsingException e) { + throw new SQLException(e); + } + } try { String preparedSoql = prepareQuery(); List forceQueryResult = getPartnerService().query(preparedSoql, getFieldDefinitions()); @@ -125,6 +170,7 @@ private ResultSet query() throws SQLException { } private String prepareQuery() { + logger.info("[PrepStat] prepareQuery IMPLEMENTED "+soqlQuery); return setParams(soqlQuery); } @@ -166,7 +212,10 @@ private String getCacheKey() { } public List getParameters() { + logger.info("[PrepStat] getParameters IMPLEMENTED "+soqlQuery); int paramsCountInQuery = StringUtils.countMatches(soqlQuery, '?'); + logger.info("[PrepStat] getParameters detected "+paramsCountInQuery+" parameters"); + logger.info("[PrepStat] getParameters parameters provided "+parameters.size()); if (parameters.size() < paramsCountInQuery) { parameters.addAll(Collections.nCopies(paramsCountInQuery - parameters.size(), null)); } @@ -174,6 +223,7 @@ public List getParameters() { } protected String setParams(String soql) { + logger.info("[PrepStat] setParams IMPLEMENTED "+soql); String result = soql; for (Object param : getParameters()) { String paramRepresentation = convertToSoqlParam(param); @@ -217,11 +267,45 @@ protected static Class getParamClass(Object paramValue) { return paramClass; } + public static ResultSetMetaData dummyMetaData(ColumnMap row) { + if (row == null) { + return null; + } + try { + logger.info("[PrepStat] dummyMetaData IMPLEMENTED "); + RowSetMetaDataImpl result = new RowSetMetaDataImpl(); + int columnsCount = row.size(); + result.setColumnCount(columnsCount); + for (int i = 1; i <= columnsCount; i++) { + String fieldName = row.getColumnNames().get(i-1); + result.setAutoIncrement(i, false); + result.setColumnName(i, fieldName); + result.setColumnLabel(i, fieldName); + Object value = row.getValues().get(i-1); + String javaTypeName = value == null ? "string" : value.getClass().getName(); + ForceDatabaseMetaData.TypeInfo typeInfo = ForceDatabaseMetaData.lookupTypeInfoFromJavaType(javaTypeName); + logger.info("[PrepStat] dummyMetaData ("+i+") "+fieldName+" : "+javaTypeName+" => "+typeInfo.sqlDataType); + result.setColumnType(i, typeInfo.sqlDataType); + result.setColumnTypeName(i, typeInfo.typeName); + result.setPrecision(i, typeInfo.precision); + result.setSchemaName(i, ForceDatabaseMetaData.DEFAULT_SCHEMA); + result.setCatalogName(i, ForceDatabaseMetaData.DEFAULT_CATALOG); + result.setTableName(i, null); + } + return result; + } catch (Exception e) { + // Ignore for metadata - just return empty + logger.log(Level.WARNING, "Failed to compile dummy metadata information", e); + return null; + } + } + private ResultSetMetaData loadMetaData() throws SQLException { try { + logger.info("[PrepStat] loadMetaData IMPLEMENTED "+soqlQuery); if (metadata == null) { RowSetMetaDataImpl result = new RowSetMetaDataImpl(); - SoqlQueryAnalyzer queryAnalyzer = getQueryAnalyzer(); + SoqlQueryAnalyzer queryAnalyzer = getSoqlQueryAnalyzer(); List resultFieldDefinitions = flatten(getFieldDefinitions()); int columnsCount = resultFieldDefinitions.size(); result.setColumnCount(columnsCount); @@ -229,13 +313,14 @@ private ResultSetMetaData loadMetaData() throws SQLException { FieldDef field = resultFieldDefinitions.get(i - 1); result.setAutoIncrement(i, false); result.setColumnName(i, field.getName()); - result.setColumnLabel(i, field.getName()); + result.setColumnLabel(i, field.getAlias()); String forceTypeName = field.getType(); ForceDatabaseMetaData.TypeInfo typeInfo = ForceDatabaseMetaData.lookupTypeInfo(forceTypeName); result.setColumnType(i, typeInfo.sqlDataType); result.setColumnTypeName(i, typeInfo.typeName); result.setPrecision(i, typeInfo.precision); - result.setSchemaName(i, "Salesforce"); + result.setSchemaName(i, ForceDatabaseMetaData.DEFAULT_SCHEMA); + result.setCatalogName(i, ForceDatabaseMetaData.DEFAULT_CATALOG); result.setTableName(i, queryAnalyzer.getFromObjectName()); } metadata = result; @@ -247,6 +332,7 @@ private ResultSetMetaData loadMetaData() throws SQLException { } private List flatten(List fieldDefinitions) { + logger.info("[PrepStat] flatten IMPLEMENTED "+soqlQuery); return (List) fieldDefinitions.stream() .flatMap(def -> def instanceof List ? ((List) def).stream() @@ -257,17 +343,23 @@ private List flatten(List fieldDefinitions) { private List fieldDefinitions; private List getFieldDefinitions() { + logger.info("[PrepStat] getFieldDefinitions IMPLEMENTED "+soqlQuery); if (fieldDefinitions == null) { - fieldDefinitions = getQueryAnalyzer().getFieldDefinitions(); + fieldDefinitions = getSoqlQueryAnalyzer().getFieldDefinitions(); + logger.info("[PrepStat] getFieldDefinitions:\n "+ + fieldDefinitions.stream().map( fd -> fd.getName()+":"+fd.getType()).collect(Collectors.joining("\n "))); } return fieldDefinitions; } - private SoqlQueryAnalyzer queryAnalyzer; + private SoqlQueryAnalyzer soqlQueryAnalyzer; + private InsertQueryAnalyzer insertQueryAnalyzer; + private UpdateQueryAnalyzer updateQueryAnalyzer; - private SoqlQueryAnalyzer getQueryAnalyzer() { - if (queryAnalyzer == null) { - queryAnalyzer = new SoqlQueryAnalyzer(prepareQuery(), (objName) -> { + private SoqlQueryAnalyzer getSoqlQueryAnalyzer() { + logger.info("[PrepStat] getSoqlQueryAnalyzer IMPLEMENTED "+soqlQuery); + if (soqlQueryAnalyzer == null) { + soqlQueryAnalyzer = new SoqlQueryAnalyzer(prepareQuery(), (objName) -> { try { return getPartnerService().describeSObject(objName); } catch (ConnectionException e) { @@ -275,7 +367,62 @@ private SoqlQueryAnalyzer getQueryAnalyzer() { } }, connection.getCache()); } - return queryAnalyzer; + return soqlQueryAnalyzer; + } + + private InsertQueryAnalyzer getInsertQueryAnalyzer() { + logger.info("[PrepStat] getInsertQueryAnalyzer IMPLEMENTED "+soqlQuery); + if (insertQueryAnalyzer == null) { + insertQueryAnalyzer = new InsertQueryAnalyzer(prepareQuery(), (objName) -> { + try { + return getPartnerService().describeSObject(objName); + } catch (ConnectionException e) { + throw new RuntimeException(e); + } + }, connection.getCache(), + soql -> runResolveSubselect(soql)); + } + return insertQueryAnalyzer; + } + + private UpdateQueryAnalyzer getUpdateQueryAnalyzer() { + logger.info("[PrepStat] getUpdateQueryAnalyzer IMPLEMENTED "+soqlQuery); + if (updateQueryAnalyzer == null) { + updateQueryAnalyzer = new UpdateQueryAnalyzer(prepareQuery(), (objName) -> { + try { + return getPartnerService().describeSObject(objName); + } catch (ConnectionException e) { + throw new RuntimeException(e); + } + }, connection.getCache(), + soql -> runResolveSubselect(soql)); + } + return updateQueryAnalyzer; + } + + private List> runResolveSubselect(String soql) { + List> results = new ArrayList<>(); + logger.info("Resolving subselect \n"+soql); + try { + ForcePreparedStatement forcePreparedStatement = new ForcePreparedStatement(connection, soql); + ResultSet resultSet = forcePreparedStatement.query(); + + while(resultSet.next()) { + // LinkedHashMap is needed to save the order of the fields + Map record = new LinkedHashMap<>(); + results.add(record); + for(int i = 0; i < resultSet.getMetaData().getColumnCount(); i++) { + record.put(resultSet.getMetaData().getColumnName(i+1), resultSet.getString(i+1)); + } + } + logger.info(" "+results.size()+" records resolved with "+resultSet.getMetaData().getColumnCount()+" columns"); + } catch (Exception e) { + logger.log(Level.WARNING, "Failed to resolve sub-select \n"+soql, e); + this.warnings.addSuppressed(new SQLWarning("Failed to resolve sub-select \n"+soql, e)); + throw new java.lang.IllegalArgumentException("Failed to resolve sub-select: "+e.getMessage()); + } + + return results; } @Override @@ -284,6 +431,7 @@ public ParameterMetaData getParameterMetaData() throws SQLException { } public ResultSetMetaData getMetaData() throws SQLException { + logger.info("[PrepStat] getMetaData IMPLEMENTED "+soqlQuery); return cacheMode == CacheMode.NO_CACHE ? loadMetaData() : metadataCache.computeIfAbsent(getCacheKey(), s -> { @@ -297,12 +445,21 @@ public ResultSetMetaData getMetaData() throws SQLException { } private PartnerService getPartnerService() throws ConnectionException { + logger.info("[PrepStat] getPartnerService IMPLEMENTED "+soqlQuery); if (partnerService == null) { + logger.info("[PrepStat] getPartnerService creating service "); partnerService = new PartnerService(connection.getPartnerConnection()); } return partnerService; } + public boolean reconnect(String url, String userName, String userPass) throws ConnectionException { + logger.info("[PrepStat] RECONNECT IMPLEMENTED newUserName="+userName + " url="+url); + boolean updated = connection.updatePartnerConnection(url, userName, userPass); + partnerService = null; + return updated; + } + public void setFetchSize(int rows) throws SQLException { this.fetchSize = rows; } @@ -320,18 +477,14 @@ public int getMaxRows() throws SQLException { } public void setArray(int i, Array x) throws SQLException { - String methodName = this.getClass().getSimpleName() + "." + new Object() { - }.getClass().getEnclosingMethod().getName(); - throw new UnsupportedOperationException("The " + methodName + " is not implemented yet."); - + logger.info("[PrepStat] setArray NOT_IMPLEMENTED "+soqlQuery); + throw new UnsupportedOperationException("The setArray is not implemented yet."); } public void setAsciiStream(int parameterIndex, InputStream x, int length) throws SQLException { - String methodName = this.getClass().getSimpleName() + "." + new Object() { - }.getClass().getEnclosingMethod().getName(); - throw new UnsupportedOperationException("The " + methodName + " is not implemented yet."); - + logger.info("[PrepStat] setAsciiStream NOT_IMPLEMENTED "+soqlQuery); + throw new UnsupportedOperationException("The setAsciiStream is not implemented yet."); } public void setBigDecimal(int parameterIndex, BigDecimal x) @@ -340,6 +493,7 @@ public void setBigDecimal(int parameterIndex, BigDecimal x) } protected void addParameter(int parameterIndex, Object x) { + logger.info("[PrepStat] addParameter "+parameterIndex+" IMPLEMENTED "+soqlQuery); parameterIndex--; if (parameters.size() < parameterIndex) { parameters.addAll(Collections.nCopies(parameterIndex - parameters.size(), null)); @@ -349,17 +503,13 @@ protected void addParameter(int parameterIndex, Object x) { public void setBinaryStream(int parameterIndex, InputStream x, int length) throws SQLException { - String methodName = this.getClass().getSimpleName() + "." + new Object() { - }.getClass().getEnclosingMethod().getName(); - throw new UnsupportedOperationException("The " + methodName + " is not implemented yet."); - + logger.info("[PrepStat] setBinaryStream NOT_IMPLEMENTED "+soqlQuery); + throw new UnsupportedOperationException("The setBinaryStream is not implemented yet."); } public void setBlob(int i, Blob x) throws SQLException { - String methodName = this.getClass().getSimpleName() + "." + new Object() { - }.getClass().getEnclosingMethod().getName(); - throw new UnsupportedOperationException("The " + methodName + " is not implemented yet."); - + logger.info("[PrepStat] setBlob NOT_IMPLEMENTED "+soqlQuery); + throw new UnsupportedOperationException("The setBlob is not implemented yet."); } public void setBoolean(int parameterIndex, boolean x) throws SQLException { @@ -367,29 +517,24 @@ public void setBoolean(int parameterIndex, boolean x) throws SQLException { } public void setByte(int parameterIndex, byte x) throws SQLException { - String methodName = this.getClass().getSimpleName() + "." + new Object() { - }.getClass().getEnclosingMethod().getName(); - throw new UnsupportedOperationException("The " + methodName + " is not implemented yet."); + logger.info("[PrepStat] setByte NOT_IMPLEMENTED "+soqlQuery); + throw new UnsupportedOperationException("The setByte is not implemented yet."); } public void setBytes(int parameterIndex, byte[] x) throws SQLException { - String methodName = this.getClass().getSimpleName() + "." + new Object() { - }.getClass().getEnclosingMethod().getName(); - throw new UnsupportedOperationException("The " + methodName + " is not implemented yet."); - + logger.info("[PrepStat] setBytes NOT_IMPLEMENTED "+soqlQuery); + throw new UnsupportedOperationException("The setBytes is not implemented yet."); } public void setCharacterStream(int parameterIndex, Reader reader, int length) throws SQLException { - String methodName = this.getClass().getSimpleName() + "." + new Object() { - }.getClass().getEnclosingMethod().getName(); - throw new UnsupportedOperationException("The " + methodName + " is not implemented yet."); + logger.info("[PrepStat] setCharacterStream NOT_IMPLEMENTED "+soqlQuery); + throw new UnsupportedOperationException("The setCharacterStream is not implemented yet."); } public void setClob(int i, Clob x) throws SQLException { - String methodName = this.getClass().getSimpleName() + "." + new Object() { - }.getClass().getEnclosingMethod().getName(); - throw new UnsupportedOperationException("The " + methodName + " is not implemented yet."); + logger.info("[PrepStat] setClob NOT_IMPLEMENTED "+soqlQuery); + throw new UnsupportedOperationException("The setClob is not implemented yet."); } public void setDate(int parameterIndex, Date x) throws SQLException { @@ -398,9 +543,8 @@ public void setDate(int parameterIndex, Date x) throws SQLException { public void setDate(int parameterIndex, Date x, Calendar cal) throws SQLException { - String methodName = this.getClass().getSimpleName() + "." + new Object() { - }.getClass().getEnclosingMethod().getName(); - throw new UnsupportedOperationException("The " + methodName + " is not implemented yet."); + logger.info("[PrepStat] setDate NOT_IMPLEMENTED "+soqlQuery); + throw new UnsupportedOperationException("The setDate is not implemented yet."); } public void setDouble(int parameterIndex, double x) throws SQLException { @@ -429,23 +573,20 @@ public void setNull(int paramIndex, int sqlType, String typeName) } public void setObject(int parameterIndex, Object x) throws SQLException { - String methodName = this.getClass().getSimpleName() + "." + new Object() { - }.getClass().getEnclosingMethod().getName(); - throw new UnsupportedOperationException("The " + methodName + " is not implemented yet."); + logger.info("[PrepStat] setObject 1 NOT_IMPLEMENTED "+soqlQuery); + throw new UnsupportedOperationException("The setObject 1 is not implemented yet."); } public void setObject(int parameterIndex, Object x, int targetSqlType) throws SQLException { - String methodName = this.getClass().getSimpleName() + "." + new Object() { - }.getClass().getEnclosingMethod().getName(); - throw new UnsupportedOperationException("The " + methodName + " is not implemented yet."); + logger.info("[PrepStat] setObject 2 NOT_IMPLEMENTED "+soqlQuery); + throw new UnsupportedOperationException("The setObject 2 is not implemented yet."); } public void setObject(int parameterIndex, Object x, int targetSqlType, int scale) throws SQLException { - String methodName = this.getClass().getSimpleName() + "." + new Object() { - }.getClass().getEnclosingMethod().getName(); - throw new UnsupportedOperationException("The " + methodName + " is not implemented yet."); + logger.info("[PrepStat] setObject 3 NOT_IMPLEMENTED "+soqlQuery); + throw new UnsupportedOperationException("The setObject 3 is not implemented yet."); } public void setRef(int i, Ref x) throws SQLException { @@ -506,13 +647,24 @@ public void setUnicodeStream(int parameterIndex, InputStream x, int length) @Override public ResultSet executeQuery(String sql) throws SQLException { - throw new RuntimeException("Not yet implemented."); + logger.info("[PrepStat] executeQuery IMPLEMENTED "+sql); + this.cacheMode = getCacheMode(sql); + this.soqlQuery = removeCacheHints(sql); + this.resultSet = executeQuery(); + return this.resultSet; } @Override public int executeUpdate(String sql) throws SQLException { - // TODO Auto-generated method stub - return 0; + logger.info("[PrepStat] executeUpdate IMPLEMENTED "+sql); + this.cacheMode = getCacheMode(sql); + this.soqlQuery = removeCacheHints(sql); + + this.updateCount = -1; + this.updateCountReturned = false; + this.resultSet = executeQuery(); + this.resultSetReturned = false; + return this.updateCount; } @Override @@ -559,14 +711,17 @@ public void cancel() throws SQLException { @Override public SQLWarning getWarnings() throws SQLException { - // TODO Auto-generated method stub - return null; + logger.info("[PrepStat] getWarnings IMPLEMENTED "); + return resultSet != null ? resultSet.getWarnings() : warnings; } @Override public void clearWarnings() throws SQLException { - // TODO Auto-generated method stub - + logger.info("[PrepStat] clearWarnings IMPLEMENTED "); + if(resultSet != null) { + resultSet.clearWarnings(); + } + warnings = new SQLWarning(); } @Override @@ -577,26 +732,55 @@ public void setCursorName(String name) throws SQLException { @Override public boolean execute(String sql) throws SQLException { - // TODO Auto-generated method stub - return false; + logger.info("[PrepStat] execute IMPLEMENTED "+sql); + this.cacheMode = getCacheMode(sql); + this.soqlQuery = removeCacheHints(sql); + + this.updateCount = -1; + this.updateCountReturned = false; + this.resultSet = executeQuery(); + this.resultSetReturned = false; + boolean result = this.updateCount < 0; + logger.info("[PrepStat] execute IMPLEMENTED ("+result+")"+sql); + return result; } @Override public ResultSet getResultSet() throws SQLException { - // TODO Auto-generated method stub - return null; + ResultSet toReturn = updateCount < 0 ? resultSet : null; + if (this.resultSetReturned) { + logger.info("[PrepStat] getResultSet IMPLEMENTED Already Returned " + soqlQuery + "\n " + + (resultSet == null ? " resultSet is NULL" : "resultSet is present") + + (toReturn == null ? " -> Not to be returned" : " -> Returning")); + return null; + } + this.resultSetReturned = true; + logger.info("[PrepStat] getResultSet IMPLEMENTED " + soqlQuery + "\n " + + (resultSet == null ? " resultSet is NULL" : "resultSet is present") + + (toReturn == null ? " -> Not to be returned" : " -> Returning")); + return toReturn; } @Override public int getUpdateCount() throws SQLException { - // TODO Auto-generated method stub - return 0; + if (this.updateCountReturned) { + logger.info("[PrepStat] getUpdateCount Already Returned "+updateCount+" IMPLEMENTED "+soqlQuery); + return -1; + } + logger.info("[PrepStat] getUpdateCount "+updateCount+" IMPLEMENTED "+soqlQuery); + this.updateCountReturned = true; + return updateCount; } @Override public boolean getMoreResults() throws SQLException { - // TODO Auto-generated method stub - return false; + if (updateCount >=0 ) { + logger.info("[PrepStat] getMoreResults IMPLEMENTED (false) updateCount="+updateCount+" sql="+soqlQuery); + return false; + } + boolean more = resultSet != null && resultSet.next(); + logger.info("[PrepStat] getMoreResults IMPLEMENTED ("+more+") updateCount="+updateCount+" sql="+soqlQuery); + return more; } @Override @@ -619,37 +803,36 @@ public int getResultSetConcurrency() throws SQLException { @Override public int getResultSetType() throws SQLException { - // TODO Auto-generated method stub + logger.info("[PrepStat] getResultSetType NOT_IMPLEMENTED "+soqlQuery); return 0; } @Override public void addBatch(String sql) throws SQLException { - // TODO Auto-generated method stub + logger.info("[PrepStat] addBatch NOT_IMPLEMENTED "+sql); } @Override public void clearBatch() throws SQLException { - // TODO Auto-generated method stub - + logger.info("[PrepStat] clearBatch NOT_IMPLEMENTED "+soqlQuery); } @Override public int[] executeBatch() throws SQLException { - // TODO Auto-generated method stub + logger.info("[PrepStat] executeBatch NOT_IMPLEMENTED "+soqlQuery); return null; } @Override public Connection getConnection() throws SQLException { - // TODO Auto-generated method stub + logger.info("[PrepStat] getConnection NOT_IMPLEMENTED "+soqlQuery); return null; } @Override public boolean getMoreResults(int current) throws SQLException { - // TODO Auto-generated method stub + logger.info("[PrepStat] getMoreResults NOT_IMPLEMENTED "+soqlQuery); return false; } @@ -661,38 +844,38 @@ public ResultSet getGeneratedKeys() throws SQLException { @Override public int executeUpdate(String sql, int autoGeneratedKeys) throws SQLException { - // TODO Auto-generated method stub - return 0; + logger.info("[PrepStat] executeUpdate 1 NOT_IMPLEMENTED "+sql); + return executeUpdate(sql); } @Override public int executeUpdate(String sql, int[] columnIndexes) throws SQLException { - // TODO Auto-generated method stub - return 0; + logger.info("[PrepStat] executeUpdate 2 NOT_IMPLEMENTED "+sql); + return executeUpdate(sql); } @Override public int executeUpdate(String sql, String[] columnNames) throws SQLException { - // TODO Auto-generated method stub - return 0; + logger.info("[PrepStat] executeUpdate 3 NOT_IMPLEMENTED "+sql); + return executeUpdate(sql); } @Override public boolean execute(String sql, int autoGeneratedKeys) throws SQLException { - // TODO Auto-generated method stub - return false; + logger.info("[PrepStat] execute 1 NOT_IMPLEMENTED "+sql); + return executeUpdate(sql) > 0; } @Override public boolean execute(String sql, int[] columnIndexes) throws SQLException { - // TODO Auto-generated method stub - return false; + logger.info("[PrepStat] execute 2 NOT_IMPLEMENTED "+sql); + return executeUpdate(sql) > 0; } @Override public boolean execute(String sql, String[] columnNames) throws SQLException { - // TODO Auto-generated method stub - return false; + logger.info("[PrepStat] execute 3 NOT_IMPLEMENTED "+sql); + return executeUpdate(sql) > 0; } @Override @@ -745,24 +928,26 @@ public boolean isWrapperFor(Class iface) throws SQLException { @Override public int executeUpdate() throws SQLException { - // TODO Auto-generated method stub - return 0; + logger.info("[PrepStat] executeUpdate 2 NOT_IMPLEMENTED "+soqlQuery); + return executeUpdate(soqlQuery); } @Override public void clearParameters() throws SQLException { + logger.info("[PrepStat] clearParameters 2 NOT_IMPLEMENTED "+soqlQuery); // TODO Auto-generated method stub } @Override public boolean execute() throws SQLException { - // TODO Auto-generated method stub - return false; + logger.info("[PrepStat] execute NOT_IMPLEMENTED "+soqlQuery); + return executeUpdate(soqlQuery) > 0; } @Override public void addBatch() throws SQLException { + logger.info("[PrepStat] addBatch NOT_IMPLEMENTED "+soqlQuery); // TODO Auto-generated method stub } @@ -770,95 +955,111 @@ public void addBatch() throws SQLException { @Override public void setRowId(int parameterIndex, RowId x) throws SQLException { // TODO Auto-generated method stub + logger.info("[PrepStat] setRowId NOT_IMPLEMENTED "+soqlQuery); } @Override public void setNString(int parameterIndex, String value) throws SQLException { + logger.info("[PrepStat] setNString NOT_IMPLEMENTED "+soqlQuery); // TODO Auto-generated method stub } @Override public void setNCharacterStream(int parameterIndex, Reader value, long length) throws SQLException { + logger.info("[PrepStat] setNCharacterStream NOT_IMPLEMENTED "+soqlQuery); // TODO Auto-generated method stub } @Override public void setNClob(int parameterIndex, NClob value) throws SQLException { + logger.info("[PrepStat] setNClob NOT_IMPLEMENTED "+soqlQuery); // TODO Auto-generated method stub } @Override public void setClob(int parameterIndex, Reader reader, long length) throws SQLException { + logger.info("[PrepStat] setClob NOT_IMPLEMENTED "+soqlQuery); // TODO Auto-generated method stub } @Override public void setBlob(int parameterIndex, InputStream inputStream, long length) throws SQLException { + logger.info("[PrepStat] setBlob NOT_IMPLEMENTED "+soqlQuery); // TODO Auto-generated method stub } @Override public void setNClob(int parameterIndex, Reader reader, long length) throws SQLException { + logger.info("[PrepStat] setNClob NOT_IMPLEMENTED "+soqlQuery); // TODO Auto-generated method stub } @Override public void setSQLXML(int parameterIndex, SQLXML xmlObject) throws SQLException { + logger.info("[PrepStat] setSQLXML NOT_IMPLEMENTED "+soqlQuery); // TODO Auto-generated method stub } @Override public void setAsciiStream(int parameterIndex, InputStream x, long length) throws SQLException { + logger.info("[PrepStat] setAsciiStream NOT_IMPLEMENTED "+soqlQuery); // TODO Auto-generated method stub } @Override public void setBinaryStream(int parameterIndex, InputStream x, long length) throws SQLException { + logger.info("[PrepStat] setBinaryStream NOT_IMPLEMENTED "+soqlQuery); // TODO Auto-generated method stub } @Override public void setCharacterStream(int parameterIndex, Reader reader, long length) throws SQLException { + logger.info("[PrepStat] setCharacterStream NOT_IMPLEMENTED "+soqlQuery); // TODO Auto-generated method stub } @Override public void setAsciiStream(int parameterIndex, InputStream x) throws SQLException { + logger.info("[PrepStat] setAsciiStream NOT_IMPLEMENTED "+soqlQuery); // TODO Auto-generated method stub } @Override public void setBinaryStream(int parameterIndex, InputStream x) throws SQLException { + logger.info("[PrepStat] setBinaryStream NOT_IMPLEMENTED "+soqlQuery); // TODO Auto-generated method stub } @Override public void setCharacterStream(int parameterIndex, Reader reader) throws SQLException { + logger.info("[PrepStat] setCharacterStream NOT_IMPLEMENTED "+soqlQuery); // TODO Auto-generated method stub } @Override public void setNCharacterStream(int parameterIndex, Reader value) throws SQLException { + logger.info("[PrepStat] setNCharacterStream NOT_IMPLEMENTED "+soqlQuery); // TODO Auto-generated method stub } @Override public void setClob(int parameterIndex, Reader reader) throws SQLException { + logger.info("[PrepStat] setClob NOT_IMPLEMENTED "+soqlQuery); // TODO Auto-generated method stub } @@ -866,13 +1067,22 @@ public void setClob(int parameterIndex, Reader reader) throws SQLException { @Override public void setBlob(int parameterIndex, InputStream inputStream) throws SQLException { // TODO Auto-generated method stub + logger.info("[PrepStat] setBlob NOT_IMPLEMENTED "+soqlQuery); } @Override public void setNClob(int parameterIndex, Reader reader) throws SQLException { // TODO Auto-generated method stub + logger.info("[PrepStat] setNClob NOT_IMPLEMENTED "+soqlQuery); + + } + public void setUpdateCount(int updateCount) { + this.updateCount = updateCount; } + public void setResultSet(ResultSet resultSet) { + this.resultSet = resultSet; + } } diff --git a/sf-jdbc-driver/src/main/java/com/ascendix/jdbc/salesforce/statement/SoqlQueryAnalyzer.java b/sf-jdbc-driver/src/main/java/com/ascendix/jdbc/salesforce/statement/SoqlQueryAnalyzer.java index 1b0393a..251a3d0 100644 --- a/sf-jdbc-driver/src/main/java/com/ascendix/jdbc/salesforce/statement/SoqlQueryAnalyzer.java +++ b/sf-jdbc-driver/src/main/java/com/ascendix/jdbc/salesforce/statement/SoqlQueryAnalyzer.java @@ -40,10 +40,22 @@ public SoqlQueryAnalyzer(String soql, Function ob private class SelectSpecVisitor extends SOQLDataBaseVisitor { + private final String rootEntityName; + + public SelectSpecVisitor(String rootEntityName) { + this.rootEntityName = rootEntityName; + } + @Override public Void visitFieldSpec(FieldSpec fieldSpec) { String name = fieldSpec.getFieldName(); + String alias = fieldSpec.getAlias() != null ? fieldSpec.getAlias() : name; + // If Object Name specified - verify it is not the same as SOQL root entity + String objectPrefix = fieldSpec.getObjectPrefixNames().size() > 0 ? fieldSpec.getObjectPrefixNames().get(0) : null; + if (fieldSpec.getAlias() == null && objectPrefix != null && !objectPrefix.equals(rootEntityName)) { + alias = objectPrefix + "." + name; + } List prefixNames = new ArrayList<>(fieldSpec.getObjectPrefixNames()); FieldDef result = createFieldDef(name, alias, prefixNames); fieldDefinitions.add(result); @@ -63,7 +75,7 @@ private FieldDef createFieldDef(String name, String alias, List prefixNa fieldPrefixes.remove(0); } String type = findField(name, describeObject(fromObject), fld -> fld.getName()).getType().name(); - FieldDef result = new FieldDef(alias, type); + FieldDef result = new FieldDef(name, alias, type); return result; } @@ -75,7 +87,7 @@ private FieldDef createFieldDef(String name, String alias, List prefixNa public Void visitFunctionCallSpec(FunctionCallSpec functionCallSpec) { String alias = functionCallSpec.getAlias() != null ? functionCallSpec.getAlias() : functionCallSpec.getFunctionName(); if (FUNCTIONS_HAS_INT_RESULT.contains(functionCallSpec.getFunctionName().toUpperCase())) { - fieldDefinitions.add(new FieldDef(alias, "int")); + fieldDefinitions.add(new FieldDef(alias, alias, "int")); } else { org.mule.tools.soql.query.data.Field param = (org.mule.tools.soql.query.data.Field) functionCallSpec.getFunctionParameters().get(0); FieldDef result = createFieldDef(param.getFieldName(), alias, param.getObjectPrefixNames()); @@ -106,7 +118,8 @@ public Void visitSOQLSubQuery(SOQLSubQuery soqlSubQuery) { public List getFieldDefinitions() { if (fieldDefinitions == null) { fieldDefinitions = new ArrayList<>(); - SelectSpecVisitor visitor = new SelectSpecVisitor(); + String rootEntityName = getQueryData().getFromClause().getMainObjectSpec().getObjectName(); + SelectSpecVisitor visitor = new SelectSpecVisitor(rootEntityName); getQueryData().getSelectSpecs() .forEach(spec -> spec.accept(visitor)); } @@ -115,7 +128,7 @@ public List getFieldDefinitions() { private Field findField(String name, DescribeSObjectResult objectDesc, Function nameFetcher) { return Arrays.stream(objectDesc.getFields()) - .filter(field -> name.equals(nameFetcher.apply(field))) + .filter(field -> name.equalsIgnoreCase(nameFetcher.apply(field))) .findFirst() .orElseThrow(() -> new IllegalArgumentException("Unknown field name \"" + name + "\" in object \"" + objectDesc.getName() + "\"")); } diff --git a/sf-jdbc-driver/src/main/java/com/ascendix/jdbc/salesforce/statement/processor/AdminQueryProcessor.java b/sf-jdbc-driver/src/main/java/com/ascendix/jdbc/salesforce/statement/processor/AdminQueryProcessor.java new file mode 100644 index 0000000..9dacdff --- /dev/null +++ b/sf-jdbc-driver/src/main/java/com/ascendix/jdbc/salesforce/statement/processor/AdminQueryProcessor.java @@ -0,0 +1,142 @@ +package com.ascendix.jdbc.salesforce.statement.processor; + +import com.ascendix.jdbc.salesforce.ForceDriver; +import com.ascendix.jdbc.salesforce.delegates.PartnerService; +import com.ascendix.jdbc.salesforce.resultset.CommandLogCachedResultSet; +import com.ascendix.jdbc.salesforce.statement.ForcePreparedStatement; + + +import java.io.IOException; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.Properties; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class AdminQueryProcessor { + + /* ADMIN Queries + Postgres LOGIN command format + https://www.postgresql.org/docs/9.1/ecpg-sql-connect.html + https://docs.oracle.com/cd/E18283_01/server.112/e16604/ch_twelve015.htm + + Example: CONNECT TO tcp:postgresql://localhost/connectdb USER connectuser IDENTIFIED BY connectpw; + Local Syntax: CONNECT [ TO ] USER IDENTIFIED BY ; + */ + private static final Pattern LOGIN_COMMAND_PG = Pattern.compile("CONNECT(\\s+TO\\s+(?\\S+))?(\\s+USER\\s+(?\\S+)\\s+IDENTIFIED BY\\s+(?\\S+))?\\s*;?", Pattern.CASE_INSENSITIVE); + + private static final Pattern LOGIN_COMMAND_ORA = Pattern.compile("CONN(?:ECT)?(?)\\s+(?\\S+)/(?\\S+)\\s*;?", Pattern.CASE_INSENSITIVE); + private static final String EXISTING_HOST = "existing host"; + + + public static boolean isAdminQuery(String soqlQuery) { + if (soqlQuery == null || soqlQuery.trim().length() == 0) { + return false; + } + soqlQuery = soqlQuery.trim(); + + Matcher matcherLogin = LOGIN_COMMAND_PG.matcher(soqlQuery); + if (matcherLogin.matches()) { + return true; + } + matcherLogin = LOGIN_COMMAND_ORA.matcher(soqlQuery); + return matcherLogin.matches(); + } + + public static ResultSet processQuery(ForcePreparedStatement statement, String soqlQuery, PartnerService partnerService) throws SQLException { + CommandLogCachedResultSet resultSet = new CommandLogCachedResultSet(); + if (soqlQuery == null || soqlQuery.trim().length() == 0) { + resultSet.log("No SOQL or ADMIN query found"); + return resultSet; + } + soqlQuery = soqlQuery.trim(); + + processLoginCommand(soqlQuery, resultSet, (url, userName, userPass, host) -> { + try { + boolean reconnected = statement.reconnect(url, userName, userPass); + if (reconnected) { + resultSet.log("Admin query: CONNECTION SUCCESSFUL as " + userName + " to " + host); + } else { + resultSet.log("Admin query: CONNECTION FAILED as " + userName + " to " + host); + return false; + } + } catch (Exception e) { + resultSet.log("Admin query: CONNECTION ERROR as " + userName + " to " + host + " : " +e.getMessage()); + throw new SQLException("CONNECTION ERROR as " + userName + " to " + host + " : " +e.getMessage(), "08000", e); + } + return true; + }); + return resultSet; + } + + @FunctionalInterface + public interface LoginCommandProcessor { + boolean processCommand(String url, String userName, String userPass, String host) throws SQLException; + } + + static boolean processLoginCommand(String soqlQuery, CommandLogCachedResultSet resultSet, LoginCommandProcessor processor) throws SQLException { + Matcher matcher = LOGIN_COMMAND_PG.matcher(soqlQuery); + if (!matcher.matches()) { + // if no PG command - also check for ORA + matcher = LOGIN_COMMAND_ORA.matcher(soqlQuery); + } + if (matcher.matches()) { + if (resultSet != null) { + resultSet.log("Admin query: CONNECT ATTEMPT"); + } + + String userName = matcher.group("username"); + String userPass = matcher.group("userpass"); + String url = matcher.group("url"); + if ("".equals(url)) { + url = null; + } + + if (userName != null) { + userName = userName.trim().replaceAll("^['\"]", "").replaceAll("['\"]$", ""); + } + if (userPass != null) { + if (userPass.endsWith(";")) { + userPass = userPass.substring(0, userPass.length() - 1); + } + userPass = userPass.trim().replaceAll("^['\"]", "").replaceAll("['\"]$", ""); + } + if (url != null) { + url = url.trim().replaceAll("^['\"]", "").replaceAll("['\"]$", ""); + if (url.endsWith(";")) { + url = url.substring(0, url.length() - 1); + } + } + // evaluate credentials and url properties - just for logging + String host = null; + + if (url != null) { + try { + Properties props = ForceDriver.getConnStringProperties(url); + if (userName == null && props.getProperty("user") != null) { + userName = props.getProperty("user"); + } + if (props.getProperty("loginDomain") != null) { + host = props.getProperty("loginDomain"); + } + } catch (IOException e) { + // No log as it's only for logging - will be triggered inside the reconnect operation + } + } + try { + return processor.processCommand(url, userName, userPass, host); + } catch (Exception e) { + if (host == null) { + host = EXISTING_HOST; + } + if (resultSet != null) { + resultSet.log("Admin query: CONNECTION ERROR as " + userName + " to " + host + " : " + e.getMessage()); + } + throw new SQLException("CONNECTION ERROR as " + userName + " to " + host + " : " +e.getMessage(), "08000", e); + } + + } else { + return false; + } + } +} diff --git a/sf-jdbc-driver/src/main/java/com/ascendix/jdbc/salesforce/statement/processor/InsertQueryAnalyzer.java b/sf-jdbc-driver/src/main/java/com/ascendix/jdbc/salesforce/statement/processor/InsertQueryAnalyzer.java new file mode 100644 index 0000000..b5e957c --- /dev/null +++ b/sf-jdbc-driver/src/main/java/com/ascendix/jdbc/salesforce/statement/processor/InsertQueryAnalyzer.java @@ -0,0 +1,170 @@ +package com.ascendix.jdbc.salesforce.statement.processor; + +import com.ascendix.jdbc.salesforce.statement.processor.utils.ValueToStringVisitor; +import com.sforce.soap.partner.DescribeSObjectResult; +import com.sforce.soap.partner.Field; +import net.sf.jsqlparser.JSQLParserException; +import net.sf.jsqlparser.expression.operators.relational.ExpressionList; +import net.sf.jsqlparser.expression.operators.relational.ItemsListVisitor; +import net.sf.jsqlparser.expression.operators.relational.MultiExpressionList; +import net.sf.jsqlparser.expression.operators.relational.NamedExpressionList; +import net.sf.jsqlparser.parser.CCJSqlParserUtil; +import net.sf.jsqlparser.schema.Column; +import net.sf.jsqlparser.statement.Statement; +import net.sf.jsqlparser.statement.insert.Insert; +import net.sf.jsqlparser.statement.select.SubSelect; + +import java.util.*; +import java.util.function.Function; +import java.util.logging.Level; +import java.util.logging.Logger; + +import static com.ascendix.jdbc.salesforce.statement.processor.InsertQueryProcessor.SF_JDBC_DRIVER_NAME; + +public class InsertQueryAnalyzer { + + private static final Logger logger = Logger.getLogger(SF_JDBC_DRIVER_NAME); + + private String soql; + private Function objectDescriptor; + private Map describedObjectsCache; + private Function>> subSelectResolver; + private Insert queryData; + private List> records; + + public InsertQueryAnalyzer(String soql, Function objectDescriptor) { + this(soql, objectDescriptor, new HashMap<>(), null); + } + + public InsertQueryAnalyzer(String soql, + Function objectDescriptor, + Map describedObjectsCache, + Function>> subSelectResolver) { + this.soql = soql; + this.objectDescriptor = objectDescriptor; + this.describedObjectsCache = describedObjectsCache; + this.subSelectResolver = subSelectResolver; + } + + public boolean analyse(String soql) { + if (soql == null || soql.trim().length() == 0) { + return false; + } + this.soql = soql; + return getQueryData() != null; + } + + public class InsertItemsListVisitor implements ItemsListVisitor { + List columns; + List> records; + + public InsertItemsListVisitor(List columns, List> records) { + this.columns = columns; + this.records = records; + } + + @Override + public void visit(SubSelect subSelect) { + System.out.println("SubSelect Visitor"); + } + + @Override + public void visit(ExpressionList expressionList) { + System.out.println("Expression Visitor"); + HashMap fieldValues = new HashMap<>(); + records.add(fieldValues); + + for(int i = 0; i < columns.size(); i++) { + expressionList.getExpressions().get(i).accept( + new ValueToStringVisitor( + fieldValues, + columns.get(i).getColumnName(), + subSelectResolver) + ); + } + } + + @Override + public void visit(NamedExpressionList namedExpressionList) { + System.out.println("NamedExpression Visitor"); + } + + @Override + public void visit(MultiExpressionList multiExprList) { + System.out.println("MultiExpression Visitor"); + multiExprList.getExpressionLists().forEach(expressions -> { + expressions.accept(new InsertItemsListVisitor(columns, records)); + }); + } + } + + private Field findField(String name, DescribeSObjectResult objectDesc, Function nameFetcher) { + return Arrays.stream(objectDesc.getFields()) + .filter(field -> name.equalsIgnoreCase(nameFetcher.apply(field))) + .findFirst() + .orElseThrow(() -> new IllegalArgumentException("Unknown field name \"" + name + "\" in object \"" + objectDesc.getName() + "\"")); + } + + private DescribeSObjectResult describeObject(String fromObjectName) { + if (!describedObjectsCache.containsKey(fromObjectName)) { + DescribeSObjectResult description = objectDescriptor.apply(fromObjectName); + describedObjectsCache.put(fromObjectName, description); + return description; + } else { + return describedObjectsCache.get(fromObjectName); + } + } + + protected String getFromObjectName() { + return queryData.getTable().getName(); + } + + private Insert getQueryData() { + if (queryData == null) { + try { + Statement statement = CCJSqlParserUtil.parse(soql); + if (statement instanceof Insert) { + queryData = (Insert) statement; + } + } catch (JSQLParserException e) { + logger.log(Level.SEVERE,"Failed request to create entities with error: "+e.getMessage(), e); + } + } + return queryData; + } + + public List> getRecords() { + if (queryData != null && records == null) { + records = new ArrayList<>(); + if (getQueryData().isUseValues()) { + getQueryData().getItemsList().accept(new InsertItemsListVisitor(getQueryData().getColumns(), records)); + } else { + if (getQueryData().getSelect() != null) { + if (subSelectResolver != null) { + logger.info("Insert/Update has a sub-select: "+getQueryData().getSelect().toString()); + List> subRecords = subSelectResolver.apply(getQueryData().getSelect().toString()); + logger.info("Insert/Update fetched " +subRecords.size()+ " records from a sub-select: "+getQueryData().getSelect().toString()); + for (Map subRecord: subRecords) { + // this subRecord is LinkedHashMap - so the order of fields is determined by soql + Map record = new HashMap<>(); + records.add(record); + int fieldIndex = 0; + Iterator> fieldsIterator = subRecord.entrySet().iterator(); + while(fieldsIterator.hasNext()) { + Map.Entry fieldEntry = fieldsIterator.next(); + String insertFieldName = queryData.getColumns().get(fieldIndex).getColumnName(); + String subSelectFieldName = fieldEntry.getKey(); + Object subSelectFieldValue = fieldEntry.getValue(); + record.put(insertFieldName, subSelectFieldValue); + + fieldIndex ++; + } + } + + } + } + } + } + return records; + } +} diff --git a/sf-jdbc-driver/src/main/java/com/ascendix/jdbc/salesforce/statement/processor/InsertQueryProcessor.java b/sf-jdbc-driver/src/main/java/com/ascendix/jdbc/salesforce/statement/processor/InsertQueryProcessor.java new file mode 100644 index 0000000..083d8ad --- /dev/null +++ b/sf-jdbc-driver/src/main/java/com/ascendix/jdbc/salesforce/statement/processor/InsertQueryProcessor.java @@ -0,0 +1,57 @@ +package com.ascendix.jdbc.salesforce.statement.processor; + +import com.ascendix.jdbc.salesforce.delegates.PartnerService; +import com.ascendix.jdbc.salesforce.resultset.CommandLogCachedResultSet; +import com.ascendix.jdbc.salesforce.statement.ForcePreparedStatement; +import com.sforce.soap.partner.*; +import com.sforce.ws.ConnectionException; + +import java.sql.ResultSet; +import java.util.Arrays; +import java.util.logging.Level; +import java.util.logging.Logger; +import java.util.stream.Collectors; + +public class InsertQueryProcessor { + + public static final String SF_JDBC_DRIVER_NAME = "SF JDBC driver"; + private static final Logger logger = Logger.getLogger(SF_JDBC_DRIVER_NAME); + + public static boolean isInsertQuery(String soqlQuery, InsertQueryAnalyzer queryAnalyzer) { + if (soqlQuery == null || soqlQuery.trim().length() == 0) { + return false; + } + soqlQuery = soqlQuery.trim(); + + return queryAnalyzer.analyse(soqlQuery); + } + + public static ResultSet processQuery(ForcePreparedStatement statement, String soqlQuery, PartnerService partnerService, InsertQueryAnalyzer insertQueryAnalyzer) { + CommandLogCachedResultSet resultSet = new CommandLogCachedResultSet(); + if (soqlQuery == null || soqlQuery.trim().length() == 0) { + resultSet.log("No INSERT query found"); + return resultSet; + } + + try { + int updateCount = 0; + ISaveResult[] records = partnerService.createRecords(insertQueryAnalyzer.getFromObjectName(), insertQueryAnalyzer.getRecords()); + + for(ISaveResult result: records) { + if (result.isSuccess()) { + resultSet.log(insertQueryAnalyzer.getFromObjectName()+" created with Id="+result.getId()); + updateCount++; + } else { + resultSet.addWarning(insertQueryAnalyzer.getFromObjectName()+" failed to create with error="+ Arrays.stream(result.getErrors()).map(IError::getMessage).collect(Collectors.joining(","))); + } + } + statement.setUpdateCount(updateCount); + statement.setResultSet(resultSet); + } catch (ConnectionException e) { + resultSet.addWarning("Failed request to create entities with error: "+e.getMessage()); + logger.log(Level.SEVERE,"Failed request to create entities with error: "+e.getMessage(), e); + } + return resultSet; + } + +} diff --git a/sf-jdbc-driver/src/main/java/com/ascendix/jdbc/salesforce/statement/processor/UpdateQueryAnalyzer.java b/sf-jdbc-driver/src/main/java/com/ascendix/jdbc/salesforce/statement/processor/UpdateQueryAnalyzer.java new file mode 100644 index 0000000..2bf7deb --- /dev/null +++ b/sf-jdbc-driver/src/main/java/com/ascendix/jdbc/salesforce/statement/processor/UpdateQueryAnalyzer.java @@ -0,0 +1,245 @@ +package com.ascendix.jdbc.salesforce.statement.processor; + +import com.ascendix.jdbc.salesforce.statement.processor.utils.ColumnsFinderVisitor; +import com.ascendix.jdbc.salesforce.statement.processor.utils.UpdateRecordVisitor; +import com.ascendix.jdbc.salesforce.statement.processor.utils.ValueToStringVisitor; +import com.sforce.soap.partner.DescribeSObjectResult; +import com.sforce.soap.partner.Field; +import net.sf.jsqlparser.JSQLParserException; +import net.sf.jsqlparser.expression.Expression; +import net.sf.jsqlparser.expression.ExpressionVisitor; +import net.sf.jsqlparser.expression.StringValue; +import net.sf.jsqlparser.expression.operators.relational.*; +import net.sf.jsqlparser.parser.CCJSqlParserUtil; +import net.sf.jsqlparser.schema.Column; +import net.sf.jsqlparser.statement.Statement; +import net.sf.jsqlparser.statement.select.PlainSelect; +import net.sf.jsqlparser.statement.select.Select; +import net.sf.jsqlparser.statement.select.SubSelect; +import net.sf.jsqlparser.statement.update.Update; +import net.sf.jsqlparser.util.SelectUtils; + +import java.util.*; +import java.util.function.Function; +import java.util.logging.Level; +import java.util.logging.Logger; + +import static com.ascendix.jdbc.salesforce.statement.processor.InsertQueryProcessor.SF_JDBC_DRIVER_NAME; + +public class UpdateQueryAnalyzer { + + private static final Logger logger = Logger.getLogger(SF_JDBC_DRIVER_NAME); + + private String soql; + private Function objectDescriptor; + private Map describedObjectsCache; + private Function>> subSelectResolver; + private Update queryData; + private List> records; + + public UpdateQueryAnalyzer(String soql, Function objectDescriptor) { + this(soql, objectDescriptor, new HashMap<>(), null); + } + + public UpdateQueryAnalyzer(String soql, + Function objectDescriptor, + Map describedObjectsCache, + Function>> subSelectResolver) { + this.soql = soql; + this.objectDescriptor = objectDescriptor; + this.describedObjectsCache = describedObjectsCache; + this.subSelectResolver = subSelectResolver; + } + + public boolean analyse(String soql) { + if (soql == null || soql.trim().length() == 0) { + return false; + } + this.soql = soql; + return getQueryData() != null; + } + + public class UpdateItemsListVisitor implements ItemsListVisitor { + List columns; + List> records; + + public UpdateItemsListVisitor(List columns, List> records) { + this.columns = columns; + this.records = records; + } + + @Override + public void visit(SubSelect subSelect) { + System.out.println("SubSelect Visitor"); + } + + @Override + public void visit(ExpressionList expressionList) { + System.out.println("Expression Visitor"); + HashMap fieldValues = new HashMap<>(); + records.add(fieldValues); + + for(int i = 0; i < columns.size(); i++) { + expressionList.getExpressions().get(i).accept( + new ValueToStringVisitor( + fieldValues, + columns.get(i).getColumnName(), + subSelectResolver) + ); + } + } + + @Override + public void visit(NamedExpressionList namedExpressionList) { + System.out.println("NamedExpression Visitor"); + } + + @Override + public void visit(MultiExpressionList multiExprList) { + System.out.println("MultiExpression Visitor"); + multiExprList.getExpressionLists().forEach(expressions -> { + expressions.accept(new UpdateItemsListVisitor(columns, records)); + }); + } + } + + private Field findField(String name, DescribeSObjectResult objectDesc, Function nameFetcher) { + return Arrays.stream(objectDesc.getFields()) + .filter(field -> name.equalsIgnoreCase(nameFetcher.apply(field))) + .findFirst() + .orElseThrow(() -> new IllegalArgumentException("Unknown field name \"" + name + "\" in object \"" + objectDesc.getName() + "\"")); + } + + private DescribeSObjectResult describeObject(String fromObjectName) { + if (!describedObjectsCache.containsKey(fromObjectName)) { + DescribeSObjectResult description = objectDescriptor.apply(fromObjectName); + describedObjectsCache.put(fromObjectName, description); + return description; + } else { + return describedObjectsCache.get(fromObjectName); + } + } + + protected String getFromObjectName() { + return queryData.getTable().getName(); + } + + private Update getQueryData() { + if (queryData == null) { + try { + Statement statement = CCJSqlParserUtil.parse(soql); + if (statement instanceof Update) { + queryData = (Update) statement; + } + } catch (JSQLParserException e) { + logger.log(Level.SEVERE,"Failed request to create entities with error: "+e.getMessage(), e); + } + } + return queryData; + } + + public List> getRecords() { + if (queryData != null && records == null) { + records = new ArrayList<>(); + + String id = checkIsDirectIdWhere(); + if (id != null) { + Set columnsToFetch = new HashSet<>(); + boolean isFunctionFound = findSubFields(columnsToFetch, getQueryData().getExpressions()); + if (columnsToFetch.size() == 0 && !isFunctionFound) { + // means there is no calculations in the new field values + Map record = new HashMap<>(); + records.add(record); + record.put("Id", id); + + List columns = getQueryData().getColumns(); + for(int i = 0; i < columns.size(); i++) { + getQueryData().getExpressions().get(i).accept( + new ValueToStringVisitor( + record, + columns.get(i).getColumnName(), + subSelectResolver) + ); + } + return records; + } + } + // otherwise we need to fetch all the Entity Ids applicable to this WHERE condition and then build a records using these Ids with fields to update + if (subSelectResolver != null) { + try { + Set columnsToFetch = new HashSet<>(); + findSubFields(columnsToFetch, getQueryData().getExpressions()); + columnsToFetch.add("Id"); + Select select = SelectUtils.buildSelectFromTableAndExpressions(getQueryData().getTable(), columnsToFetch.toArray(new String[]{})); + ((PlainSelect)select.getSelectBody()).setWhere(getQueryData().getWhere()); + + List> subRecords = subSelectResolver.apply(select.toString()); + + for (Map subRecord: subRecords) { + // this subRecord is LinkedHashMap - so the order of fields is determined by soql + Map record = new HashMap<>(); + records.add(record); + record.put("Id", subRecord.get("Id")); + + List columns = getQueryData().getColumns(); + // Iterating over the received entities and adding fields to update + for(int i = 0; i < columns.size(); i++) { + Expression expr = getQueryData().getExpressions().get(i); + expr.accept( + new UpdateRecordVisitor( + getQueryData(), + record, + subRecord, + columns.get(i).getColumnName(), + subSelectResolver) + ); + } + } + } catch (JSQLParserException e) { + logger.log(Level.SEVERE,"Failed request to fetch the applicable entities: error in columns to fetch", e); + } + + } else { + logger.log(Level.SEVERE,"Failed request to fetch the applicable entities: subSelectResolver not defined"); + } + + } + return records; + } + + private Set findFields(List expressions) { + Set columns = new HashSet<>(); + findSubFields(columns, expressions); + return columns; + } + + private boolean findSubFields(Set columns, List expressions) { + ColumnsFinderVisitor visitor = new ColumnsFinderVisitor(columns); + expressions.forEach(expr -> expr.accept(visitor)); + return visitor.isFunctionFound(); + } + + /** Checks if this update is using WHERE Id='001xx010201' notation and no other criteria */ + private String checkIsDirectIdWhere() { + if (queryData.getWhere() != null && queryData.getWhere() instanceof EqualsTo) { + EqualsTo whereRoot = (EqualsTo) queryData.getWhere(); + // direct ID comparison like Id='001xx192918212' + if (whereRoot.getLeftExpression() instanceof Column && whereRoot.getRightExpression() instanceof StringValue) { + Column col = (Column)whereRoot.getLeftExpression(); + if ("id".equalsIgnoreCase(col.getColumnName())) { + StringValue idValue = (StringValue) whereRoot.getRightExpression(); + return idValue.getValue(); + }; + } + // direct ID comparison like '001xx192918212'=Id + if (whereRoot.getLeftExpression() instanceof StringValue && whereRoot.getRightExpression() instanceof Column) { + Column col = (Column)whereRoot.getRightExpression(); + if ("id".equalsIgnoreCase(col.getColumnName())) { + StringValue idValue = (StringValue) whereRoot.getLeftExpression(); + return idValue.getValue(); + }; + } + } + return null; + } +} diff --git a/sf-jdbc-driver/src/main/java/com/ascendix/jdbc/salesforce/statement/processor/UpdateQueryProcessor.java b/sf-jdbc-driver/src/main/java/com/ascendix/jdbc/salesforce/statement/processor/UpdateQueryProcessor.java new file mode 100644 index 0000000..7f63703 --- /dev/null +++ b/sf-jdbc-driver/src/main/java/com/ascendix/jdbc/salesforce/statement/processor/UpdateQueryProcessor.java @@ -0,0 +1,56 @@ +package com.ascendix.jdbc.salesforce.statement.processor; + +import com.ascendix.jdbc.salesforce.delegates.PartnerService; +import com.ascendix.jdbc.salesforce.resultset.CommandLogCachedResultSet; +import com.ascendix.jdbc.salesforce.statement.ForcePreparedStatement; +import com.sforce.soap.partner.IError; +import com.sforce.soap.partner.ISaveResult; +import com.sforce.ws.ConnectionException; + +import java.sql.ResultSet; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.logging.Level; +import java.util.logging.Logger; +import java.util.stream.Collectors; + +public class UpdateQueryProcessor { + + public static final String SF_JDBC_DRIVER_NAME = "SF JDBC driver"; + private static final Logger logger = Logger.getLogger(SF_JDBC_DRIVER_NAME); + + public static boolean isUpdateQuery(String soqlQuery, UpdateQueryAnalyzer queryAnalyzer) { + if (soqlQuery == null || soqlQuery.trim().length() == 0) { + return false; + } + soqlQuery = soqlQuery.trim(); + + return queryAnalyzer.analyse(soqlQuery); + } + + public static ResultSet processQuery(ForcePreparedStatement statement, String soqlQuery, PartnerService partnerService, UpdateQueryAnalyzer updateQueryAnalyzer) { + CommandLogCachedResultSet resultSet = new CommandLogCachedResultSet(); + if (soqlQuery == null || soqlQuery.trim().length() == 0) { + resultSet.log("No UPDATE query found"); + return resultSet; + } + + try { + List> recordsToUpdate = updateQueryAnalyzer.getRecords(); + ISaveResult[] records = partnerService.saveRecords(updateQueryAnalyzer.getFromObjectName(), recordsToUpdate); + for(ISaveResult result: records) { + if (result.isSuccess()) { + resultSet.log(updateQueryAnalyzer.getFromObjectName()+" updated with Id="+result.getId()); + } else { + resultSet.addWarning(updateQueryAnalyzer.getFromObjectName()+" failed to update with error="+ Arrays.stream(result.getErrors()).map(IError::getMessage).collect(Collectors.joining(","))); + } + } + } catch (ConnectionException e) { + resultSet.addWarning("Failed request to update entities with error: "+e.getMessage()); + logger.log(Level.SEVERE,"Failed request to update entities with error: "+e.getMessage(), e); + } + return resultSet; + } + +} diff --git a/sf-jdbc-driver/src/main/java/com/ascendix/jdbc/salesforce/statement/processor/utils/ColumnsFinderVisitor.java b/sf-jdbc-driver/src/main/java/com/ascendix/jdbc/salesforce/statement/processor/utils/ColumnsFinderVisitor.java new file mode 100644 index 0000000..e7d0abc --- /dev/null +++ b/sf-jdbc-driver/src/main/java/com/ascendix/jdbc/salesforce/statement/processor/utils/ColumnsFinderVisitor.java @@ -0,0 +1,478 @@ +package com.ascendix.jdbc.salesforce.statement.processor.utils; + +import net.sf.jsqlparser.expression.*; +import net.sf.jsqlparser.expression.operators.arithmetic.*; +import net.sf.jsqlparser.expression.operators.conditional.AndExpression; +import net.sf.jsqlparser.expression.operators.conditional.OrExpression; +import net.sf.jsqlparser.expression.operators.relational.*; +import net.sf.jsqlparser.schema.Column; +import net.sf.jsqlparser.statement.select.SubSelect; + +import java.util.Set; +import java.util.logging.Logger; + +import static com.ascendix.jdbc.salesforce.statement.processor.InsertQueryProcessor.SF_JDBC_DRIVER_NAME; + +public class ColumnsFinderVisitor implements ExpressionVisitor { + private static final Logger logger = Logger.getLogger(SF_JDBC_DRIVER_NAME); + + private final Set columns; + private boolean functionFound = false; + + public ColumnsFinderVisitor(Set columns) { + this.columns = columns; + } + + public boolean isFunctionFound() { + return functionFound; + } + + private void addColumn(Column column) { + if (columns.add(column.getColumnName())) { + logger.info("New column found: "+column.getColumnName()); + } else { + logger.info("Already detected column: "+column.getColumnName()); + } + } + + private void processExpression(Expression expr) { + expr.accept(this); + } + + private void processBinaryExpression(BinaryExpression expr) { + expr.getLeftExpression().accept(this); + expr.getRightExpression().accept(this); + } + + @Override + public void visit(BitwiseRightShift aThis) { + System.out.println("[ColumnsFinder] BitwiseRightShift"); + processBinaryExpression(aThis); + } + + @Override + public void visit(BitwiseLeftShift aThis) { + System.out.println("[ColumnsFinder] BitwiseLeftShift"); + processBinaryExpression(aThis); + } + + @Override + public void visit(NullValue nullValue) { + System.out.println("[ColumnsFinder] NullValue "); + } + + @Override + public void visit(Function function) { + System.out.println("[ColumnsFinder] Function"); + functionFound = true; + } + + @Override + public void visit(SignedExpression signedExpression) { + System.out.println("[ColumnsFinder] SignedExpression"); + signedExpression.getExpression().accept(this); + } + + @Override + public void visit(JdbcParameter jdbcParameter) { + System.out.println("[ColumnsFinder] JdbcParameter"); + } + + @Override + public void visit(JdbcNamedParameter jdbcNamedParameter) { + System.out.println("[ColumnsFinder] JdbcNamedParameter"); + } + + @Override + public void visit(DoubleValue doubleValue) { + System.out.println("[ColumnsFinder] DoubleValue"); + } + + @Override + public void visit(LongValue longValue) { + System.out.println("[ColumnsFinder] LongValue"); + } + + @Override + public void visit(HexValue hexValue) { + System.out.println("[ColumnsFinder] HexValue"); + } + + @Override + public void visit(DateValue dateValue) { + System.out.println("[ColumnsFinder] DateValue"); + } + + @Override + public void visit(TimeValue timeValue) { + System.out.println("[ColumnsFinder] BitwiseRightShift"); + } + + @Override + public void visit(TimestampValue timestampValue) { + System.out.println("[ColumnsFinder] TimestampValue"); + } + + @Override + public void visit(Parenthesis parenthesis) { + System.out.println("[ColumnsFinder] Parenthesis"); + parenthesis.getExpression().accept(this); + } + + @Override + public void visit(StringValue stringValue) { + System.out.println("[ColumnsFinder] StringValue"); + } + + @Override + public void visit(Addition addition) { + System.out.println("[ColumnsFinder] Addition"); + processBinaryExpression(addition); + } + + @Override + public void visit(Division division) { + System.out.println("[ColumnsFinder] Division"); + processBinaryExpression(division); + } + + @Override + public void visit(IntegerDivision division) { + System.out.println("[ColumnsFinder] IntegerDivision"); + processBinaryExpression(division); + } + + @Override + public void visit(Multiplication multiplication) { + System.out.println("[ColumnsFinder] Multiplication"); + processBinaryExpression(multiplication); + } + + @Override + public void visit(Subtraction subtraction) { + System.out.println("[ColumnsFinder] Subtraction"); + processBinaryExpression(subtraction); + } + + @Override + public void visit(AndExpression andExpression) { + System.out.println("[ColumnsFinder] AndExpression"); + processBinaryExpression(andExpression); + } + + @Override + public void visit(OrExpression orExpression) { + System.out.println("[ColumnsFinder] OrExpression"); + processBinaryExpression(orExpression); + } + + @Override + public void visit(Between between) { + System.out.println("[ColumnsFinder] Between"); + between.getLeftExpression().accept(this); + between.getBetweenExpressionStart().accept(this); + between.getBetweenExpressionEnd().accept(this); + } + + @Override + public void visit(EqualsTo equalsTo) { + System.out.println("[ColumnsFinder] EqualsTo"); + processBinaryExpression(equalsTo); + } + + @Override + public void visit(GreaterThan greaterThan) { + System.out.println("[ColumnsFinder] GreaterThan"); + processBinaryExpression(greaterThan); + } + + @Override + public void visit(GreaterThanEquals greaterThanEquals) { + System.out.println("[ColumnsFinder] GreaterThanEquals"); + processBinaryExpression(greaterThanEquals); + } + + @Override + public void visit(InExpression inExpression) { + System.out.println("[ColumnsFinder] InExpression"); + inExpression.getLeftExpression().accept(this); + } + + @Override + public void visit(FullTextSearch fullTextSearch) { + System.out.println("[ColumnsFinder] FullTextSearch"); + fullTextSearch.getMatchColumns().forEach( this::addColumn ); + } + + @Override + public void visit(IsNullExpression isNullExpression) { + System.out.println("[ColumnsFinder] IsNullExpression"); + isNullExpression.getLeftExpression().accept(this); + } + + @Override + public void visit(IsBooleanExpression isBooleanExpression) { + System.out.println("[ColumnsFinder] IsBooleanExpression"); + isBooleanExpression.getLeftExpression().accept(this); + } + + @Override + public void visit(LikeExpression likeExpression) { + System.out.println("[ColumnsFinder] LikeExpression"); + processExpression(likeExpression); + } + + @Override + public void visit(MinorThan minorThan) { + System.out.println("[ColumnsFinder] MinorThan"); + processBinaryExpression(minorThan); + } + + @Override + public void visit(MinorThanEquals minorThanEquals) { + System.out.println("[ColumnsFinder] MinorThanEquals"); + processBinaryExpression(minorThanEquals); + } + + @Override + public void visit(NotEqualsTo notEqualsTo) { + System.out.println("[ColumnsFinder] NotEqualsTo"); + processBinaryExpression(notEqualsTo); + } + + @Override + public void visit(Column tableColumn) { + System.out.println("[ColumnsFinder] Column"); + addColumn(tableColumn); + } + + @Override + public void visit(SubSelect subSelect) { + System.out.println("[VtoxSVisitor] SubSelect="+subSelect.toString()); +// Object value = null; +// if (subSelectResolver != null) { +// subSelect.setUseBrackets(false); +// List> records = subSelectResolver.apply(subSelect.toString()); +// if (records.size() == 1 && records.get(0).size() == 1) { +// return the value as plain value +// value = records.get(0).entrySet().iterator().next().getValue(); +// System.out.println("[ColumnsFinder] resolved to "+value); +// } +// } else { +// System.out.println("[ColumnsFinder] subSelectResolver is undefined"); +// } +// recordFieldsToUpdate.put(columnName, value); + } + + @Override + public void visit(CaseExpression caseExpression) { + System.out.println("[ColumnsFinder] CaseExpression NOT_SUPPORTED"); + } + + @Override + public void visit(WhenClause whenClause) { + System.out.println("[ColumnsFinder] WhenClause"); + + } + + @Override + public void visit(ExistsExpression existsExpression) { + System.out.println("[ColumnsFinder] ExistsExpression"); + existsExpression.getRightExpression().accept(this); + } + + @Override + public void visit(AllComparisonExpression allComparisonExpression) { + System.out.println("[ColumnsFinder] AllComparisonExpression NOT_SUPPORTED!!!"); + + } + + @Override + public void visit(AnyComparisonExpression anyComparisonExpression) { + System.out.println("[ColumnsFinder] AnyComparisonExpression"); + + } + + @Override + public void visit(Concat concat) { + System.out.println("[ColumnsFinder] Concat"); + processBinaryExpression(concat); + } + + @Override + public void visit(Matches matches) { + System.out.println("[ColumnsFinder] Matches"); + processBinaryExpression(matches); + } + + @Override + public void visit(BitwiseAnd bitwiseAnd) { + System.out.println("[ColumnsFinder] BitwiseAnd"); + processBinaryExpression(bitwiseAnd); + } + + @Override + public void visit(BitwiseOr bitwiseOr) { + System.out.println("[ColumnsFinder] BitwiseOr"); + processBinaryExpression(bitwiseOr); + } + + @Override + public void visit(BitwiseXor bitwiseXor) { + System.out.println("[ColumnsFinder] BitwiseXor"); + processBinaryExpression(bitwiseXor); + } + + @Override + public void visit(CastExpression cast) { + System.out.println("[ColumnsFinder] CastExpression"); + cast.getLeftExpression().accept(this); + } + + @Override + public void visit(Modulo modulo) { + System.out.println("[ColumnsFinder] Modulo"); + processBinaryExpression(modulo); + } + + @Override + public void visit(AnalyticExpression aexpr) { + System.out.println("[ColumnsFinder] AnalyticExpression"); + aexpr.getExpression().accept(this); + } + + @Override + public void visit(ExtractExpression eexpr) { + System.out.println("[ColumnsFinder] BitwiseRightShift"); + eexpr.getExpression().accept(this); + } + + @Override + public void visit(IntervalExpression iexpr) { + System.out.println("[ColumnsFinder] IntervalExpression"); + iexpr.getExpression().accept(this); + } + + @Override + public void visit(OracleHierarchicalExpression oexpr) { + System.out.println("[ColumnsFinder] OracleHierarchicalExpression"); + oexpr.getStartExpression().accept(this); + oexpr.getConnectExpression().accept(this); + } + + @Override + public void visit(RegExpMatchOperator rexpr) { + System.out.println("[ColumnsFinder] RegExpMatchOperator"); + processBinaryExpression(rexpr); + } + + @Override + public void visit(JsonExpression jsonExpr) { + System.out.println("[ColumnsFinder] JsonExpression"); + addColumn(jsonExpr.getColumn()); + } + + @Override + public void visit(JsonOperator jsonExpr) { + System.out.println("[ColumnsFinder] JsonOperator"); + processBinaryExpression(jsonExpr); + } + + @Override + public void visit(RegExpMySQLOperator regExpMySQLOperator) { + System.out.println("[ColumnsFinder] RegExpMySQLOperator"); + processBinaryExpression(regExpMySQLOperator); + } + + @Override + public void visit(UserVariable var) { + System.out.println("[ColumnsFinder] UserVariable"); + + } + + @Override + public void visit(NumericBind bind) { + System.out.println("[ColumnsFinder] NumericBind"); + } + + @Override + public void visit(KeepExpression aexpr) { + System.out.println("[ColumnsFinder] KeepExpression"); + + } + + @Override + public void visit(MySQLGroupConcat groupConcat) { + System.out.println("[ColumnsFinder] MySQLGroupConcat"); + groupConcat.getExpressionList().getExpressions().forEach( expression -> expression.accept(this)); + } + + @Override + public void visit(ValueListExpression valueList) { + System.out.println("[ColumnsFinder] ValueListExpression"); + valueList.getExpressionList().getExpressions().forEach( expression -> expression.accept(this)); + } + + @Override + public void visit(RowConstructor rowConstructor) { + System.out.println("[ColumnsFinder] RowConstructor"); + rowConstructor.getExprList().getExpressions().forEach( expression -> expression.accept(this)); + } + + @Override + public void visit(OracleHint hint) { + System.out.println("[ColumnsFinder] OracleHint"); + } + + @Override + public void visit(TimeKeyExpression timeKeyExpression) { + System.out.println("[ColumnsFinder] TimeKeyExpression"); + } + + @Override + public void visit(DateTimeLiteralExpression literal) { + System.out.println("[ColumnsFinder] DateTimeLiteralExpression"); + } + + @Override + public void visit(NotExpression aThis) { + System.out.println("[ColumnsFinder] NotExpression"); + aThis.getExpression().accept(this); + } + + @Override + public void visit(NextValExpression aThis) { + System.out.println("[ColumnsFinder] NextValExpression"); + } + + @Override + public void visit(CollateExpression aThis) { + System.out.println("[ColumnsFinder] CollateExpression"); + aThis.getLeftExpression().accept(this); + } + + @Override + public void visit(SimilarToExpression aThis) { + System.out.println("[ColumnsFinder] SimilarToExpression"); + processBinaryExpression(aThis); + } + + @Override + public void visit(ArrayExpression aThis) { + System.out.println("[ColumnsFinder] ArrayExpression"); + aThis.getIndexExpression().accept(this); + aThis.getObjExpression().accept(this); + } + + @Override + public void visit(VariableAssignment aThis) { + System.out.println("[ColumnsFinder] VariableAssignment"); + aThis.getExpression().accept(this); + } + + @Override + public void visit(XMLSerializeExpr aThis) { + System.out.println("[ColumnsFinder] XMLSerializeExpr"); + aThis.getExpression().accept(this); + } +} diff --git a/sf-jdbc-driver/src/main/java/com/ascendix/jdbc/salesforce/statement/processor/utils/EvaluateExpressionVisitor.java b/sf-jdbc-driver/src/main/java/com/ascendix/jdbc/salesforce/statement/processor/utils/EvaluateExpressionVisitor.java new file mode 100644 index 0000000..ae50fa2 --- /dev/null +++ b/sf-jdbc-driver/src/main/java/com/ascendix/jdbc/salesforce/statement/processor/utils/EvaluateExpressionVisitor.java @@ -0,0 +1,754 @@ +package com.ascendix.jdbc.salesforce.statement.processor.utils; + +import com.ascendix.jdbc.salesforce.exceptions.UnsupportedArgumentTypeException; +import net.sf.jsqlparser.expression.*; +import net.sf.jsqlparser.expression.operators.arithmetic.*; +import net.sf.jsqlparser.expression.operators.conditional.AndExpression; +import net.sf.jsqlparser.expression.operators.conditional.OrExpression; +import net.sf.jsqlparser.expression.operators.relational.*; +import net.sf.jsqlparser.schema.Column; +import net.sf.jsqlparser.statement.select.SubSelect; + +import java.math.BigDecimal; +import java.math.MathContext; +import java.sql.Time; + +import java.time.*; +import java.util.Date; +import java.util.Map; +import java.util.logging.Level; +import java.util.logging.Logger; + +import static com.ascendix.jdbc.salesforce.statement.processor.InsertQueryProcessor.SF_JDBC_DRIVER_NAME; + +public class EvaluateExpressionVisitor implements ExpressionVisitor { + + protected static final Logger logger = Logger.getLogger(SF_JDBC_DRIVER_NAME); + protected Map recordFieldsFromDB; + protected Object result; + + public EvaluateExpressionVisitor(Map recordFieldsFromDB) { + this.recordFieldsFromDB = recordFieldsFromDB; + } + + public EvaluateExpressionVisitor subVisitor() { + return new EvaluateExpressionVisitor(recordFieldsFromDB); + } + + public Object getResult() { + return result; + } + + public String getResultString() { + return (String) result; + } + + public String getResultString(String ifNull) { + if (result == null) { + return ifNull; + } + if (result instanceof String) return ((String) result); + return result.toString(); + } + + public long getResultFixedNumber() { + if (result == null) { + return 0; + } + if (result instanceof Double) return ((Double) result).longValue(); + if (result instanceof Float) return ((Float) result).longValue(); + if (result instanceof Long) return ((Long) result); + if (result instanceof Integer) return ((Integer) result).longValue(); + if (result instanceof String) return Long.parseLong((String)result); + String message = String.format("Cannot convert to Fixed type %s value %s", result.getClass().getName(), result); + logger.log(Level.SEVERE, message); + throw new UnsupportedArgumentTypeException(message); + } + + public double getResultFloatNumber() { + if (result == null) { + return 0d; + } + if (result instanceof Double) return (Double) result; + if (result instanceof Float) return ((Float) result).doubleValue(); + if (result instanceof Long) return ((Long) result).doubleValue(); + if (result instanceof Integer) return ((Integer) result).doubleValue(); + if (result instanceof String) return Double.parseDouble((String)result); + String message = String.format("Cannot convert to Float type %s value %s", result.getClass().getName(), result); + logger.log(Level.SEVERE, message); + throw new UnsupportedArgumentTypeException(message); + } + + public boolean isResultString() { + return result != null && result instanceof String; + } + + public boolean isResultFixedNumber() { + return result != null && ( + result instanceof Long || + result instanceof Integer); + } + + public boolean isResultFloatNumber() { + return result != null && ( + result instanceof Double || + result instanceof Float); + } + + public boolean isResultDateTime() { + return result != null && ( + result instanceof Instant || + result instanceof java.sql.Timestamp); + } + + public boolean isResultTime() { + return result != null && ( + result instanceof java.sql.Time); + } + + public boolean isResultDate() { + return result != null && ( + result instanceof java.sql.Date); + } + + public boolean isResultNull() { + return result == null; + } + + @Override + public void visit(BitwiseRightShift aThis) { + System.out.println("[UpdateVisitor] BitwiseRightShift"); + } + + @Override + public void visit(BitwiseLeftShift aThis) { + System.out.println("[UpdateVisitor] BitwiseLeftShift"); + } + + @Override + public void visit(NullValue nullValue) { + System.out.println("[UpdateVisitor] NullValue"); + result = null; + } + + @Override + public void visit(Function function) { + System.out.println("[UpdateVisitor] Function function="+function.getName()); + if ("now".equalsIgnoreCase(function.getName())) { + result = new Date(); + return; + } + if ("getdate".equalsIgnoreCase(function.getName())) { + result = LocalDate.now(); + return; + } + throw new RuntimeException("Function '"+function.getName()+"' is not implemented."); + } + + @Override + public void visit(SignedExpression signedExpression) { + System.out.println("[UpdateVisitor] SignedExpression"); + } + + @Override + public void visit(JdbcParameter jdbcParameter) { + System.out.println("[UpdateVisitor] BitwiseRightShift"); + } + + @Override + public void visit(JdbcNamedParameter jdbcNamedParameter) { + System.out.println("[UpdateVisitor] JdbcNamedParameter"); + } + + @Override + public void visit(DoubleValue doubleValue) { + System.out.println("[UpdateVisitor] DoubleValue="+doubleValue.getValue()); + result = doubleValue.getValue(); + } + + @Override + public void visit(LongValue longValue) { + System.out.println("[UpdateVisitor] LongValue="+longValue.getValue()); + result = longValue.getValue(); + } + + @Override + public void visit(HexValue hexValue) { + System.out.println("[UpdateVisitor] HexValue="+hexValue.getValue()); + result = hexValue.getValue(); + } + + @Override + public void visit(DateValue dateValue) { + System.out.println("[UpdateVisitor] DateValue "); + result = dateValue.getValue(); + } + + @Override + public void visit(TimeValue timeValue) { + System.out.println("[UpdateVisitor] BitwiseRightShift"); + result = timeValue.getValue(); + } + + @Override + public void visit(TimestampValue timestampValue) { + System.out.println("[UpdateVisitor] TimestampValue"); + result = timestampValue.getValue(); + } + + @Override + public void visit(Parenthesis parenthesis) { + System.out.println("[UpdateVisitor] Parenthesis"); + EvaluateExpressionVisitor subEvaluatorLeft = subVisitor(); + parenthesis.getExpression().accept(subEvaluatorLeft); + result = subEvaluatorLeft.getResult(); + } + + @Override + public void visit(StringValue stringValue) { + System.out.println("[UpdateVisitor] StringValue="+stringValue.getValue()); + result = stringValue.getValue(); + } + + Object processDateNumberOperation(EvaluateExpressionVisitor left, EvaluateExpressionVisitor right, boolean isAdding) { + BigDecimal changeValue = BigDecimal.valueOf(right.getResultFloatNumber()); + // https://oracle-base.com/articles/misc/oracle-dates-timestamps-and-intervals + // Also rounding - because otherwise 1 second will be 0.999993600 + long secondsValue = changeValue.subtract(BigDecimal.valueOf(changeValue.intValue())).multiply(BigDecimal.valueOf(86400), new MathContext(4)).longValue(); + + Period changeDays = Period.ofDays(isAdding ? changeValue.intValue() : -changeValue.intValue()); + Duration changeSec = Duration.ofSeconds(isAdding ? secondsValue : -secondsValue); + if (left.result instanceof java.sql.Date) { + LocalDate instant = ((java.sql.Date)left.result).toLocalDate(); + instant = instant.plus(changeDays); + result = java.sql.Date.valueOf(instant); + } + if (left.result instanceof Instant) { + Instant instant = ((Instant)left.result); + instant = instant.plus(changeDays); + instant = instant.plus(changeSec); + result = instant; + } + if (left.result instanceof java.sql.Timestamp) { + Instant instant = ((java.sql.Timestamp)left.result).toInstant(); + instant = instant.plus(changeDays); + instant = instant.plus(changeSec); + result = new java.sql.Timestamp(instant.toEpochMilli()); + } + if (left.result instanceof Time) { + LocalTime instant = ((java.sql.Time)left.result).toLocalTime(); + instant = instant.plus(changeSec); + result = java.sql.Time.valueOf(instant); + } + + return result; + } + + @Override + public void visit(Addition addition) { + System.out.println("[UpdateVisitor] Addition"); + EvaluateExpressionVisitor subEvaluatorLeft = subVisitor(); + addition.getLeftExpression().accept(subEvaluatorLeft); + EvaluateExpressionVisitor subEvaluatorRight = subVisitor(); + addition.getRightExpression().accept(subEvaluatorRight); + + if (!subEvaluatorLeft.isResultNull() && !subEvaluatorRight.isResultNull()){ + if ((subEvaluatorLeft.isResultDateTime() || subEvaluatorLeft.isResultDate() || subEvaluatorLeft.isResultTime()) && + (subEvaluatorRight.isResultFloatNumber() || subEvaluatorRight.isResultFixedNumber()) ) { + result = processDateNumberOperation(subEvaluatorLeft, subEvaluatorRight, true); + return; + } + } + + boolean isString = subEvaluatorLeft.isResultString() || subEvaluatorRight.isResultString(); + try { + if (subEvaluatorLeft.isResultFloatNumber() || subEvaluatorRight.isResultFloatNumber()) { + result = subEvaluatorLeft.getResultFloatNumber() + subEvaluatorRight.getResultFloatNumber(); + return; + } + if (subEvaluatorLeft.isResultFixedNumber() || subEvaluatorRight.isResultFixedNumber()) { + result = subEvaluatorLeft.getResultFixedNumber() + subEvaluatorRight.getResultFixedNumber(); + return; + } + } catch (NumberFormatException e) { + isString = true; + } + + if (isString) { + // if string - convert to string "null" + result = subEvaluatorLeft.getResultString("null") + subEvaluatorRight.getResultString("null"); + return; + } + + if (subEvaluatorLeft.isResultNull() || subEvaluatorRight.isResultNull()) { + // if any of the parameters is null - return null + result = null; + return; + } + result = null; + String message = String.format("Addition not implemented for types %s and %s", subEvaluatorLeft.result.getClass().getName(), subEvaluatorRight.result.getClass().getName()); + logger.log(Level.SEVERE, message); + throw new UnsupportedArgumentTypeException(message); + } + + @Override + public void visit(Division division) { + System.out.println("[UpdateVisitor] Division"); + EvaluateExpressionVisitor subEvaluatorLeft = subVisitor(); + division.getLeftExpression().accept(subEvaluatorLeft); + EvaluateExpressionVisitor subEvaluatorRight = subVisitor(); + division.getRightExpression().accept(subEvaluatorRight); + + if (subEvaluatorLeft.isResultNull() || subEvaluatorRight.isResultNull()) { + // if any of the parameters is null - return null + result = null; + return; + } + + boolean isString = subEvaluatorLeft.isResultString()|| subEvaluatorRight.isResultString(); + if (isString) { + String message = String.format("Division not implemented for types %s and %s", subEvaluatorLeft.result.getClass().getName(), subEvaluatorRight.result.getClass().getName()); + logger.log(Level.SEVERE, message); + throw new UnsupportedArgumentTypeException(message); + } + + if (subEvaluatorLeft.isResultFloatNumber() || subEvaluatorRight.isResultFloatNumber()) { + result = subEvaluatorLeft.getResultFloatNumber() / subEvaluatorRight.getResultFloatNumber(); + return; + } + if (subEvaluatorLeft.isResultFixedNumber() || subEvaluatorRight.isResultFixedNumber()) { + result = subEvaluatorLeft.getResultFixedNumber() / subEvaluatorRight.getResultFixedNumber(); + return; + } + result = null; + String message = String.format("Division not implemented for types %s and %s", subEvaluatorLeft.result.getClass().getName(), subEvaluatorRight.result.getClass().getName()); + logger.log(Level.SEVERE, message); + throw new UnsupportedArgumentTypeException(message); + } + + @Override + public void visit(IntegerDivision division) { + System.out.println("[UpdateVisitor] IntegerDivision"); + EvaluateExpressionVisitor subEvaluatorLeft = subVisitor(); + division.getLeftExpression().accept(subEvaluatorLeft); + EvaluateExpressionVisitor subEvaluatorRight = subVisitor(); + division.getRightExpression().accept(subEvaluatorRight); + + if (subEvaluatorLeft.isResultNull() || subEvaluatorRight.isResultNull()) { + // if any of the parameters is null - return null + result = null; + return; + } + + boolean isString = subEvaluatorLeft.isResultString() || subEvaluatorRight.isResultString(); + if (isString) { + String message = String.format("Division not implemented for types %s and %s", subEvaluatorLeft.result.getClass().getName(), subEvaluatorRight.result.getClass().getName()); + logger.log(Level.SEVERE, message); + throw new UnsupportedArgumentTypeException(message); + } + + if (subEvaluatorLeft.isResultFloatNumber() || subEvaluatorRight.isResultFloatNumber()) { + result = Double.doubleToLongBits(subEvaluatorLeft.getResultFloatNumber() / subEvaluatorRight.getResultFloatNumber()); + return; + } + if (subEvaluatorLeft.isResultFixedNumber() || subEvaluatorRight.isResultFixedNumber()) { + result = subEvaluatorLeft.getResultFixedNumber() / subEvaluatorRight.getResultFixedNumber(); + return; + } + String message = String.format("Division not implemented for types %s and %s", subEvaluatorLeft.result.getClass().getName(), subEvaluatorRight.result.getClass().getName()); + logger.log(Level.SEVERE, message); + throw new UnsupportedArgumentTypeException(message); + } + + @Override + public void visit(Multiplication multiplication) { + System.out.println("[UpdateVisitor] Multiplication"); + EvaluateExpressionVisitor subEvaluatorLeft = subVisitor(); + multiplication.getLeftExpression().accept(subEvaluatorLeft); + EvaluateExpressionVisitor subEvaluatorRight = subVisitor(); + multiplication.getRightExpression().accept(subEvaluatorRight); + + if (subEvaluatorLeft.isResultNull() || subEvaluatorRight.isResultNull()) { + // if any of the parameters is null - return null + result = null; + return; + } + + boolean isString = subEvaluatorLeft.isResultString() || subEvaluatorRight.isResultString(); + if (isString) { + String message = String.format("Multiplication not implemented for types %s and %s", subEvaluatorLeft.result.getClass().getName(), subEvaluatorRight.result.getClass().getName()); + logger.log(Level.SEVERE, message); + throw new UnsupportedArgumentTypeException(message); + } + + if (subEvaluatorLeft.isResultFloatNumber() || subEvaluatorRight.isResultFloatNumber()) { + result = subEvaluatorLeft.getResultFloatNumber() * subEvaluatorRight.getResultFloatNumber(); + return; + } + if (subEvaluatorLeft.isResultFixedNumber() || subEvaluatorRight.isResultFixedNumber()) { + result = subEvaluatorLeft.getResultFixedNumber() * subEvaluatorRight.getResultFixedNumber(); + return; + } + result = null; + String message = String.format("Multiplication not implemented for types %s and %s", subEvaluatorLeft.result.getClass().getName(), subEvaluatorRight.result.getClass().getName()); + logger.log(Level.SEVERE, message); + throw new UnsupportedArgumentTypeException(message); + } + + @Override + public void visit(Subtraction subtraction) { + System.out.println("[UpdateVisitor] Subtraction"); + EvaluateExpressionVisitor subEvaluatorLeft = subVisitor(); + subtraction.getLeftExpression().accept(subEvaluatorLeft); + EvaluateExpressionVisitor subEvaluatorRight = subVisitor(); + subtraction.getRightExpression().accept(subEvaluatorRight); + + if (!subEvaluatorLeft.isResultNull() && !subEvaluatorRight.isResultNull()){ + if ((subEvaluatorLeft.isResultDateTime() || subEvaluatorLeft.isResultDate() || subEvaluatorLeft.isResultTime()) && + (subEvaluatorRight.isResultFloatNumber() || subEvaluatorRight.isResultFixedNumber()) ) { + result = processDateNumberOperation(subEvaluatorLeft, subEvaluatorRight, false); + return; + } + } + + if (subEvaluatorLeft.isResultNull() || subEvaluatorRight.isResultNull()) { + // if any of the parameters is null - return null + result = null; + return; + } + + boolean isString = subEvaluatorLeft.isResultString() || subEvaluatorRight.isResultString(); + if (isString) { + String message = String.format("Subtraction not implemented for types %s and %s", subEvaluatorLeft.result.getClass().getName(), subEvaluatorRight.result.getClass().getName()); + logger.log(Level.SEVERE, message); + throw new UnsupportedArgumentTypeException(message); + } + + if (subEvaluatorLeft.isResultFloatNumber() || subEvaluatorRight.isResultFloatNumber()) { + result = subEvaluatorLeft.getResultFloatNumber() - subEvaluatorRight.getResultFloatNumber(); + return; + } + if (subEvaluatorLeft.isResultFixedNumber() || subEvaluatorRight.isResultFixedNumber()) { + result = subEvaluatorLeft.getResultFixedNumber() - subEvaluatorRight.getResultFixedNumber(); + return; + } + String message = String.format("Subtraction not implemented for types %s and %s", subEvaluatorLeft.result.getClass().getName(), subEvaluatorRight.result.getClass().getName()); + logger.log(Level.SEVERE, message); + result = null; + throw new UnsupportedArgumentTypeException(message); + } + + @Override + public void visit(AndExpression andExpression) { + System.out.println("[UpdateVisitor] AndExpression"); + + } + + @Override + public void visit(OrExpression orExpression) { + System.out.println("[UpdateVisitor] OrExpression"); + + } + + @Override + public void visit(Between between) { + System.out.println("[UpdateVisitor] Between"); + + } + + @Override + public void visit(EqualsTo equalsTo) { + System.out.println("[UpdateVisitor] EqualsTo"); + } + + @Override + public void visit(GreaterThan greaterThan) { + System.out.println("[UpdateVisitor] GreaterThan"); + + } + + @Override + public void visit(GreaterThanEquals greaterThanEquals) { + System.out.println("[UpdateVisitor] GreaterThanEquals"); + + } + + @Override + public void visit(InExpression inExpression) { + System.out.println("[UpdateVisitor] InExpression"); + + } + + @Override + public void visit(FullTextSearch fullTextSearch) { + System.out.println("[UpdateVisitor] FullTextSearch"); + + } + + @Override + public void visit(IsNullExpression isNullExpression) { + System.out.println("[UpdateVisitor] IsNullExpression"); + + } + + @Override + public void visit(IsBooleanExpression isBooleanExpression) { + System.out.println("[UpdateVisitor] IsBooleanExpression"); + + } + + @Override + public void visit(LikeExpression likeExpression) { + System.out.println("[UpdateVisitor] LikeExpression"); + + } + + @Override + public void visit(MinorThan minorThan) { + System.out.println("[UpdateVisitor] MinorThan"); + + } + + @Override + public void visit(MinorThanEquals minorThanEquals) { + System.out.println("[UpdateVisitor] MinorThanEquals"); + + } + + @Override + public void visit(NotEqualsTo notEqualsTo) { + System.out.println("[UpdateVisitor] NotEqualsTo"); + + } + + @Override + public void visit(Column tableColumn) { + System.out.println("[UpdateVisitor] Column column="+tableColumn.getColumnName()); + result = recordFieldsFromDB.get(tableColumn.getColumnName()); + } + + @Override + public void visit(SubSelect subSelect) { + System.out.println("[VtoxSVisitor] SubSelect="+subSelect.toString()); + } + + @Override + public void visit(CaseExpression caseExpression) { + System.out.println("[UpdateVisitor] CaseExpression"); + EvaluateExpressionVisitor caseEvaluatorLeft = subVisitor(); + caseExpression.getSwitchExpression().accept(caseEvaluatorLeft); + } + + @Override + public void visit(WhenClause whenClause) { + System.out.println("[UpdateVisitor] WhenClause"); + } + + @Override + public void visit(ExistsExpression existsExpression) { + System.out.println("[UpdateVisitor] ExistsExpression"); + } + + @Override + public void visit(AllComparisonExpression allComparisonExpression) { + System.out.println("[UpdateVisitor] AllComparisonExpression"); + + } + + @Override + public void visit(AnyComparisonExpression anyComparisonExpression) { + System.out.println("[UpdateVisitor] AnyComparisonExpression"); + + } + + @Override + public void visit(Concat concat) { + System.out.println("[UpdateVisitor] Concat"); + EvaluateExpressionVisitor subEvaluatorLeft = subVisitor(); + concat.getLeftExpression().accept(subEvaluatorLeft); + EvaluateExpressionVisitor subEvaluatorRight = subVisitor(); + concat.getRightExpression().accept(subEvaluatorRight); + + result = subEvaluatorLeft.getResultString("null") + subEvaluatorRight.getResultString("null"); + } + + @Override + public void visit(Matches matches) { + System.out.println("[UpdateVisitor] Matches"); + + } + + @Override + public void visit(BitwiseAnd bitwiseAnd) { + System.out.println("[UpdateVisitor] BitwiseAnd"); + + } + + @Override + public void visit(BitwiseOr bitwiseOr) { + System.out.println("[UpdateVisitor] BitwiseOr"); + + } + + @Override + public void visit(BitwiseXor bitwiseXor) { + System.out.println("[UpdateVisitor] BitwiseXor"); + + } + + @Override + public void visit(CastExpression cast) { + System.out.println("[UpdateVisitor] CastExpression"); + + } + + @Override + public void visit(Modulo modulo) { + System.out.println("[UpdateVisitor] Modulo"); + + } + + @Override + public void visit(AnalyticExpression aexpr) { + System.out.println("[UpdateVisitor] AnalyticExpression"); + + } + + @Override + public void visit(ExtractExpression eexpr) { + System.out.println("[UpdateVisitor] BitwiseRightShift"); + + } + + @Override + public void visit(IntervalExpression iexpr) { + System.out.println("[UpdateVisitor] IntervalExpression"); + + } + + @Override + public void visit(OracleHierarchicalExpression oexpr) { + System.out.println("[UpdateVisitor] OracleHierarchicalExpression"); + + } + + @Override + public void visit(RegExpMatchOperator rexpr) { + System.out.println("[UpdateVisitor] RegExpMatchOperator"); + + } + + @Override + public void visit(JsonExpression jsonExpr) { + System.out.println("[UpdateVisitor] JsonExpression"); + + } + + @Override + public void visit(JsonOperator jsonExpr) { + System.out.println("[UpdateVisitor] JsonOperator"); + + } + + @Override + public void visit(RegExpMySQLOperator regExpMySQLOperator) { + System.out.println("[UpdateVisitor] RegExpMySQLOperator"); + + } + + @Override + public void visit(UserVariable var) { + System.out.println("[UpdateVisitor] UserVariable"); + + } + + @Override + public void visit(NumericBind bind) { + System.out.println("[UpdateVisitor] NumericBind"); + + } + + @Override + public void visit(KeepExpression aexpr) { + System.out.println("[UpdateVisitor] KeepExpression"); + + } + + @Override + public void visit(MySQLGroupConcat groupConcat) { + System.out.println("[UpdateVisitor] MySQLGroupConcat"); + + } + + @Override + public void visit(ValueListExpression valueList) { + System.out.println("[UpdateVisitor] ValueListExpression"); + + } + + @Override + public void visit(RowConstructor rowConstructor) { + System.out.println("[UpdateVisitor] RowConstructor"); + + } + + @Override + public void visit(OracleHint hint) { + System.out.println("[UpdateVisitor] OracleHint"); + + } + + @Override + public void visit(TimeKeyExpression timeKeyExpression) { + System.out.println("[UpdateVisitor] TimeKeyExpression"); + + } + + @Override + public void visit(DateTimeLiteralExpression literal) { + System.out.println("[UpdateVisitor] DateTimeLiteralExpression"); + + } + + @Override + public void visit(NotExpression aThis) { + System.out.println("[UpdateVisitor] NotExpression"); + + } + + @Override + public void visit(NextValExpression aThis) { + System.out.println("[UpdateVisitor] NextValExpression"); + + } + + @Override + public void visit(CollateExpression aThis) { + System.out.println("[UpdateVisitor] CollateExpression"); + + } + + @Override + public void visit(SimilarToExpression aThis) { + System.out.println("[UpdateVisitor] SimilarToExpression"); + + } + + @Override + public void visit(ArrayExpression aThis) { + System.out.println("[UpdateVisitor] ArrayExpression"); + + } + + @Override + public void visit(VariableAssignment aThis) { + System.out.println("[UpdateVisitor] VariableAssignment"); + + } + + @Override + public void visit(XMLSerializeExpr aThis) { + System.out.println("[UpdateVisitor] XMLSerializeExpr"); + + } +} diff --git a/sf-jdbc-driver/src/main/java/com/ascendix/jdbc/salesforce/statement/processor/utils/UpdateRecordVisitor.java b/sf-jdbc-driver/src/main/java/com/ascendix/jdbc/salesforce/statement/processor/utils/UpdateRecordVisitor.java new file mode 100644 index 0000000..a96037f --- /dev/null +++ b/sf-jdbc-driver/src/main/java/com/ascendix/jdbc/salesforce/statement/processor/utils/UpdateRecordVisitor.java @@ -0,0 +1,478 @@ +package com.ascendix.jdbc.salesforce.statement.processor.utils; + +import net.sf.jsqlparser.expression.*; +import net.sf.jsqlparser.expression.operators.arithmetic.*; +import net.sf.jsqlparser.expression.operators.conditional.AndExpression; +import net.sf.jsqlparser.expression.operators.conditional.OrExpression; +import net.sf.jsqlparser.expression.operators.relational.*; +import net.sf.jsqlparser.schema.Column; +import net.sf.jsqlparser.statement.select.SubSelect; +import net.sf.jsqlparser.statement.update.Update; + +import java.util.List; +import java.util.Map; + +public class UpdateRecordVisitor implements ExpressionVisitor { + + private Update updateStatement; + private Map recordFieldsToUpdate; + private Map recordFieldsFromDB; + private String columnName; + private java.util.function.Function>> subSelectResolver; + + public UpdateRecordVisitor(Update updateStatement, Map recordFieldsToUpdate, Map recordFieldsFromDB, String columnName, java.util.function.Function>> subSelectResolver) { + this.updateStatement = updateStatement; + this.recordFieldsToUpdate = recordFieldsToUpdate; + this.recordFieldsFromDB = recordFieldsFromDB; + this.columnName = columnName; + this.subSelectResolver = subSelectResolver; + } + + @Override + public void visit(BitwiseRightShift aThis) { + System.out.println("[UpdateVisitor] BitwiseRightShift"); + } + + @Override + public void visit(BitwiseLeftShift aThis) { + System.out.println("[UpdateVisitor] BitwiseLeftShift"); + } + + @Override + public void visit(NullValue nullValue) { + System.out.println("[UpdateVisitor] NullValue column="+columnName); + recordFieldsToUpdate.put(columnName, null); + } + + @Override + public void visit(Function function) { + System.out.println("[UpdateVisitor] Function function="+function.getName()); + } + + @Override + public void visit(SignedExpression signedExpression) { + System.out.println("[UpdateVisitor] SignedExpression"); + } + + @Override + public void visit(JdbcParameter jdbcParameter) { + System.out.println("[UpdateVisitor] BitwiseRightShift"); + } + + @Override + public void visit(JdbcNamedParameter jdbcNamedParameter) { + System.out.println("[UpdateVisitor] JdbcNamedParameter"); + } + + @Override + public void visit(DoubleValue doubleValue) { + System.out.println("[UpdateVisitor] DoubleValue="+doubleValue.getValue()+" column="+columnName); + recordFieldsToUpdate.put(columnName, doubleValue.getValue()); + } + + @Override + public void visit(LongValue longValue) { + System.out.println("[UpdateVisitor] LongValue="+longValue.getValue()+" column="+columnName); + recordFieldsToUpdate.put(columnName, longValue.getValue()); + } + + @Override + public void visit(HexValue hexValue) { + System.out.println("[UpdateVisitor] HexValue="+hexValue.getValue()+" column="+columnName); + recordFieldsToUpdate.put(columnName, hexValue.getValue()); + } + + @Override + public void visit(DateValue dateValue) { + System.out.println("[UpdateVisitor] DateValue column="+columnName); + } + + @Override + public void visit(TimeValue timeValue) { + System.out.println("[UpdateVisitor] BitwiseRightShift"); + recordFieldsToUpdate.put(columnName, timeValue.getValue()); + } + + @Override + public void visit(TimestampValue timestampValue) { + System.out.println("[UpdateVisitor] TimestampValue"); + recordFieldsToUpdate.put(columnName, timestampValue.getValue()); + } + + EvaluateExpressionVisitor evaluator() { + return new EvaluateExpressionVisitor(recordFieldsFromDB); + } + + private void evaluate(Expression expr) { + EvaluateExpressionVisitor subEvaluatorLeft = evaluator(); + expr.accept(subEvaluatorLeft); + recordFieldsToUpdate.put(columnName, subEvaluatorLeft.getResult()); + } + + + @Override + public void visit(Parenthesis parenthesis) { + System.out.println("[UpdateVisitor] Parenthesis"); + evaluate(parenthesis); + } + + @Override + public void visit(StringValue stringValue) { + System.out.println("[UpdateVisitor] StringValue="+stringValue.getValue()+" column="+columnName); + recordFieldsToUpdate.put(columnName, stringValue.getValue()); + } + + @Override + public void visit(Addition addition) { + System.out.println("[UpdateVisitor] Addition"); + evaluate(addition); + } + + @Override + public void visit(Division division) { + System.out.println("[UpdateVisitor] Division"); + evaluate(division); + } + + @Override + public void visit(IntegerDivision division) { + System.out.println("[UpdateVisitor] IntegerDivision"); + evaluate(division); + } + + @Override + public void visit(Multiplication multiplication) { + System.out.println("[UpdateVisitor] Multiplication"); + evaluate(multiplication); + } + + @Override + public void visit(Subtraction subtraction) { + System.out.println("[UpdateVisitor] Subtraction"); + evaluate(subtraction); + } + + @Override + public void visit(AndExpression andExpression) { + System.out.println("[UpdateVisitor] AndExpression"); + evaluate(andExpression); + } + + @Override + public void visit(OrExpression orExpression) { + System.out.println("[UpdateVisitor] OrExpression"); + evaluate(orExpression); + } + + @Override + public void visit(Between between) { + System.out.println("[UpdateVisitor] Between"); + evaluate(between); + } + + @Override + public void visit(EqualsTo equalsTo) { + System.out.println("[UpdateVisitor] EqualsTo"); + evaluate(equalsTo); + } + + @Override + public void visit(GreaterThan greaterThan) { + System.out.println("[UpdateVisitor] GreaterThan"); + evaluate(greaterThan); + } + + @Override + public void visit(GreaterThanEquals greaterThanEquals) { + System.out.println("[UpdateVisitor] GreaterThanEquals"); + evaluate(greaterThanEquals); + } + + @Override + public void visit(InExpression inExpression) { + System.out.println("[UpdateVisitor] InExpression"); + evaluate(inExpression); + } + + @Override + public void visit(FullTextSearch fullTextSearch) { + System.out.println("[UpdateVisitor] FullTextSearch"); + evaluate(fullTextSearch); + } + + @Override + public void visit(IsNullExpression isNullExpression) { + System.out.println("[UpdateVisitor] IsNullExpression"); + evaluate(isNullExpression); + } + + @Override + public void visit(IsBooleanExpression isBooleanExpression) { + System.out.println("[UpdateVisitor] IsBooleanExpression"); + evaluate(isBooleanExpression); + } + + @Override + public void visit(LikeExpression likeExpression) { + System.out.println("[UpdateVisitor] LikeExpression"); + evaluate(likeExpression); + } + + @Override + public void visit(MinorThan minorThan) { + System.out.println("[UpdateVisitor] MinorThan"); + evaluate(minorThan); + } + + @Override + public void visit(MinorThanEquals minorThanEquals) { + System.out.println("[UpdateVisitor] MinorThanEquals"); + evaluate(minorThanEquals); + } + + @Override + public void visit(NotEqualsTo notEqualsTo) { + System.out.println("[UpdateVisitor] NotEqualsTo"); + evaluate(notEqualsTo); + } + + @Override + public void visit(Column tableColumn) { + System.out.println("[UpdateVisitor] Column column="+tableColumn.getColumnName()); + evaluate(tableColumn); + } + + @Override + public void visit(SubSelect subSelect) { + System.out.println("[VtoxSVisitor] SubSelect="+subSelect.toString()+" column="+columnName); +// Object value = null; +// if (subSelectResolver != null) { +// subSelect.setUseBrackets(false); +// List> records = subSelectResolver.apply(subSelect.toString()); +// if (records.size() == 1 && records.get(0).size() == 1) { +// return the value as plain value +// value = records.get(0).entrySet().iterator().next().getValue(); +// System.out.println("[UpdateVisitor] resolved to "+value); +// } +// } else { +// System.out.println("[UpdateVisitor] subSelectResolver is undefined"); +// } +// recordFieldsToUpdate.put(columnName, value); + } + + @Override + public void visit(CaseExpression caseExpression) { + System.out.println("[UpdateVisitor] CaseExpression"); + evaluate(caseExpression); + } + + @Override + public void visit(WhenClause whenClause) { + System.out.println("[UpdateVisitor] WhenClause"); + evaluate(whenClause); + } + + @Override + public void visit(ExistsExpression existsExpression) { + System.out.println("[UpdateVisitor] ExistsExpression"); + evaluate(existsExpression); + } + + @Override + public void visit(AllComparisonExpression allComparisonExpression) { + System.out.println("[UpdateVisitor] AllComparisonExpression"); + evaluate(allComparisonExpression); + } + + @Override + public void visit(AnyComparisonExpression anyComparisonExpression) { + System.out.println("[UpdateVisitor] AnyComparisonExpression"); + evaluate(anyComparisonExpression); + } + + @Override + public void visit(Concat concat) { + System.out.println("[UpdateVisitor] Concat"); + evaluate(concat); + } + + @Override + public void visit(Matches matches) { + System.out.println("[UpdateVisitor] Matches"); + evaluate(matches); + } + + @Override + public void visit(BitwiseAnd bitwiseAnd) { + System.out.println("[UpdateVisitor] BitwiseAnd"); + evaluate(bitwiseAnd); + } + + @Override + public void visit(BitwiseOr aThis) { + System.out.println("[UpdateVisitor] BitwiseOr"); + evaluate(aThis); + } + + @Override + public void visit(BitwiseXor aThis) { + System.out.println("[UpdateVisitor] BitwiseXor"); + evaluate(aThis); + } + + @Override + public void visit(CastExpression aThis) { + System.out.println("[UpdateVisitor] CastExpression"); + evaluate(aThis); + } + + @Override + public void visit(Modulo aThis) { + System.out.println("[UpdateVisitor] Modulo"); + evaluate(aThis); + } + + @Override + public void visit(AnalyticExpression aThis) { + System.out.println("[UpdateVisitor] AnalyticExpression"); + evaluate(aThis); + } + + @Override + public void visit(ExtractExpression aThis) { + System.out.println("[UpdateVisitor] BitwiseRightShift"); + evaluate(aThis); + } + + @Override + public void visit(IntervalExpression aThis) { + System.out.println("[UpdateVisitor] IntervalExpression"); + evaluate(aThis); + } + + @Override + public void visit(OracleHierarchicalExpression aThis) { + System.out.println("[UpdateVisitor] OracleHierarchicalExpression"); + evaluate(aThis); + } + + @Override + public void visit(RegExpMatchOperator aThis) { + System.out.println("[UpdateVisitor] RegExpMatchOperator"); + evaluate(aThis); + } + + @Override + public void visit(JsonExpression aThis) { + System.out.println("[UpdateVisitor] JsonExpression"); + evaluate(aThis); + } + + @Override + public void visit(JsonOperator aThis) { + System.out.println("[UpdateVisitor] JsonOperator"); + evaluate(aThis); + } + + @Override + public void visit(RegExpMySQLOperator aThis) { + System.out.println("[UpdateVisitor] RegExpMySQLOperator"); + evaluate(aThis); + } + + @Override + public void visit(UserVariable aThis) { + System.out.println("[UpdateVisitor] UserVariable"); + evaluate(aThis); + } + + @Override + public void visit(NumericBind aThis) { + System.out.println("[UpdateVisitor] NumericBind"); + evaluate(aThis); + } + + @Override + public void visit(KeepExpression aThis) { + System.out.println("[UpdateVisitor] KeepExpression"); + evaluate(aThis); + } + + @Override + public void visit(MySQLGroupConcat aThis) { + System.out.println("[UpdateVisitor] MySQLGroupConcat"); + evaluate(aThis); + } + + @Override + public void visit(ValueListExpression aThis) { + System.out.println("[UpdateVisitor] ValueListExpression"); + evaluate(aThis); + } + + @Override + public void visit(RowConstructor aThis) { + System.out.println("[UpdateVisitor] RowConstructor"); + evaluate(aThis); + } + + @Override + public void visit(OracleHint aThis) { + System.out.println("[UpdateVisitor] OracleHint"); + evaluate(aThis); + } + + @Override + public void visit(TimeKeyExpression aThis) { + System.out.println("[UpdateVisitor] TimeKeyExpression"); + evaluate(aThis); + } + + @Override + public void visit(DateTimeLiteralExpression aThis) { + System.out.println("[UpdateVisitor] DateTimeLiteralExpression"); + evaluate(aThis); + } + + @Override + public void visit(NotExpression aThis) { + System.out.println("[UpdateVisitor] NotExpression"); + evaluate(aThis); + } + + @Override + public void visit(NextValExpression aThis) { + System.out.println("[UpdateVisitor] NextValExpression"); + evaluate(aThis); + } + + @Override + public void visit(CollateExpression aThis) { + System.out.println("[UpdateVisitor] CollateExpression"); + evaluate(aThis); + } + + @Override + public void visit(SimilarToExpression aThis) { + System.out.println("[UpdateVisitor] SimilarToExpression"); + evaluate(aThis); + } + + @Override + public void visit(ArrayExpression aThis) { + System.out.println("[UpdateVisitor] ArrayExpression"); + evaluate(aThis); + } + + @Override + public void visit(VariableAssignment aThis) { + System.out.println("[UpdateVisitor] VariableAssignment"); + evaluate(aThis); + } + + @Override + public void visit(XMLSerializeExpr aThis) { + System.out.println("[UpdateVisitor] XMLSerializeExpr"); + evaluate(aThis); + } +} diff --git a/sf-jdbc-driver/src/main/java/com/ascendix/jdbc/salesforce/statement/processor/utils/ValueToStringVisitor.java b/sf-jdbc-driver/src/main/java/com/ascendix/jdbc/salesforce/statement/processor/utils/ValueToStringVisitor.java new file mode 100644 index 0000000..61af8a5 --- /dev/null +++ b/sf-jdbc-driver/src/main/java/com/ascendix/jdbc/salesforce/statement/processor/utils/ValueToStringVisitor.java @@ -0,0 +1,458 @@ +package com.ascendix.jdbc.salesforce.statement.processor.utils; + +import net.sf.jsqlparser.expression.*; +import net.sf.jsqlparser.expression.operators.arithmetic.*; +import net.sf.jsqlparser.expression.operators.conditional.AndExpression; +import net.sf.jsqlparser.expression.operators.conditional.OrExpression; +import net.sf.jsqlparser.expression.operators.relational.*; +import net.sf.jsqlparser.schema.Column; +import net.sf.jsqlparser.statement.select.SubSelect; + +import java.util.List; +import java.util.Map; + +public class ValueToStringVisitor implements ExpressionVisitor { + + private Map fieldValues; + private String columnName; + private java.util.function.Function>> subSelectResolver; + + public ValueToStringVisitor(Map fieldValues, String columnName, java.util.function.Function>> subSelectResolver) { + this.fieldValues = fieldValues; + this.columnName = columnName; + this.subSelectResolver = subSelectResolver; + } + + @Override + public void visit(BitwiseRightShift aThis) { + System.out.println("[VtoSVisitor] BitwiseRightShift"); + } + + @Override + public void visit(BitwiseLeftShift aThis) { + System.out.println("[VtoSVisitor] BitwiseLeftShift"); + } + + @Override + public void visit(NullValue nullValue) { + System.out.println("[VtoSVisitor] NullValue"); + fieldValues.put(columnName, null); + } + + @Override + public void visit(Function function) { + System.out.println("[VtoSVisitor] Function"); + } + + @Override + public void visit(SignedExpression signedExpression) { + System.out.println("[VtoSVisitor] SignedExpression"); + } + + @Override + public void visit(JdbcParameter jdbcParameter) { + System.out.println("[VtoSVisitor] BitwiseRightShift"); + } + + @Override + public void visit(JdbcNamedParameter jdbcNamedParameter) { + System.out.println("[VtoSVisitor] JdbcNamedParameter"); + } + + @Override + public void visit(DoubleValue doubleValue) { + System.out.println("[VtoSVisitor] DoubleValue="+doubleValue.getValue()); + fieldValues.put(columnName, doubleValue.getValue()); + } + + @Override + public void visit(LongValue longValue) { + System.out.println("[VtoSVisitor] LongValue="+longValue.getValue()); + fieldValues.put(columnName, longValue.getValue()); + } + + @Override + public void visit(HexValue hexValue) { + System.out.println("[VtoSVisitor] HexValue="+hexValue.getValue()); + fieldValues.put(columnName, hexValue.getValue()); + } + + @Override + public void visit(DateValue dateValue) { + System.out.println("[VtoSVisitor] DateValue"); + } + + @Override + public void visit(TimeValue timeValue) { + System.out.println("[VtoSVisitor] BitwiseRightShift"); + } + + @Override + public void visit(TimestampValue timestampValue) { + System.out.println("[VtoSVisitor] TimestampValue"); + } + + @Override + public void visit(Parenthesis parenthesis) { + System.out.println("[VtoSVisitor] Parenthesis"); + } + + @Override + public void visit(StringValue stringValue) { + System.out.println("[VtoSVisitor] StringValue="+stringValue.getValue()); + fieldValues.put(columnName, stringValue.getValue()); + } + + @Override + public void visit(Addition addition) { + System.out.println("[VtoSVisitor] Addition"); + } + + @Override + public void visit(Division division) { + System.out.println("[VtoSVisitor] Division"); + + } + + @Override + public void visit(IntegerDivision division) { + System.out.println("[VtoSVisitor] IntegerDivision"); + + } + + @Override + public void visit(Multiplication multiplication) { + System.out.println("[VtoSVisitor] Multiplication"); + + } + + @Override + public void visit(Subtraction subtraction) { + System.out.println("[VtoSVisitor] Subtraction"); + + } + + @Override + public void visit(AndExpression andExpression) { + System.out.println("[VtoSVisitor] AndExpression"); + + } + + @Override + public void visit(OrExpression orExpression) { + System.out.println("[VtoSVisitor] OrExpression"); + + } + + @Override + public void visit(Between between) { + System.out.println("[VtoSVisitor] Between"); + + } + + @Override + public void visit(EqualsTo equalsTo) { + System.out.println("[VtoSVisitor] EqualsTo"); + + } + + @Override + public void visit(GreaterThan greaterThan) { + System.out.println("[VtoSVisitor] GreaterThan"); + + } + + @Override + public void visit(GreaterThanEquals greaterThanEquals) { + System.out.println("[VtoSVisitor] GreaterThanEquals"); + + } + + @Override + public void visit(InExpression inExpression) { + System.out.println("[VtoSVisitor] InExpression"); + + } + + @Override + public void visit(FullTextSearch fullTextSearch) { + System.out.println("[VtoSVisitor] FullTextSearch"); + + } + + @Override + public void visit(IsNullExpression isNullExpression) { + System.out.println("[VtoSVisitor] IsNullExpression"); + + } + + @Override + public void visit(IsBooleanExpression isBooleanExpression) { + System.out.println("[VtoSVisitor] IsBooleanExpression"); + + } + + @Override + public void visit(LikeExpression likeExpression) { + System.out.println("[VtoSVisitor] LikeExpression"); + + } + + @Override + public void visit(MinorThan minorThan) { + System.out.println("[VtoSVisitor] MinorThan"); + + } + + @Override + public void visit(MinorThanEquals minorThanEquals) { + System.out.println("[VtoSVisitor] MinorThanEquals"); + + } + + @Override + public void visit(NotEqualsTo notEqualsTo) { + System.out.println("[VtoSVisitor] NotEqualsTo"); + + } + + @Override + public void visit(Column tableColumn) { + System.out.println("[VtoSVisitor] Column"); + + } + + @Override + public void visit(SubSelect subSelect) { + System.out.println("[VtoxSVisitor] SubSelect="+subSelect.toString()); + Object value = null; + if (subSelectResolver != null) { + subSelect.setUseBrackets(false); + List> records = subSelectResolver.apply(subSelect.toString()); + if (records.size() == 1 && records.get(0).size() == 1) { + // return the value as plain value + value = records.get(0).entrySet().iterator().next().getValue(); + System.out.println("[VtoSVisitor] resolved to "+value); + } + } else { + System.out.println("[VtoSVisitor] subSelectResolver is undefined"); + } + fieldValues.put(columnName, value); + } + + @Override + public void visit(CaseExpression caseExpression) { + System.out.println("[VtoSVisitor] CaseExpression"); + + } + + @Override + public void visit(WhenClause whenClause) { + System.out.println("[VtoSVisitor] WhenClause"); + + } + + @Override + public void visit(ExistsExpression existsExpression) { + System.out.println("[VtoSVisitor] ExistsExpression"); + + } + + @Override + public void visit(AllComparisonExpression allComparisonExpression) { + System.out.println("[VtoSVisitor] AllComparisonExpression"); + + } + + @Override + public void visit(AnyComparisonExpression anyComparisonExpression) { + System.out.println("[VtoSVisitor] AnyComparisonExpression"); + + } + + @Override + public void visit(Concat concat) { + System.out.println("[VtoSVisitor] Concat"); + + } + + @Override + public void visit(Matches matches) { + System.out.println("[VtoSVisitor] Matches"); + + } + + @Override + public void visit(BitwiseAnd bitwiseAnd) { + System.out.println("[VtoSVisitor] BitwiseAnd"); + + } + + @Override + public void visit(BitwiseOr bitwiseOr) { + System.out.println("[VtoSVisitor] BitwiseOr"); + + } + + @Override + public void visit(BitwiseXor bitwiseXor) { + System.out.println("[VtoSVisitor] BitwiseXor"); + + } + + @Override + public void visit(CastExpression cast) { + System.out.println("[VtoSVisitor] CastExpression"); + + } + + @Override + public void visit(Modulo modulo) { + System.out.println("[VtoSVisitor] Modulo"); + + } + + @Override + public void visit(AnalyticExpression aexpr) { + System.out.println("[VtoSVisitor] AnalyticExpression"); + + } + + @Override + public void visit(ExtractExpression eexpr) { + System.out.println("[VtoSVisitor] BitwiseRightShift"); + + } + + @Override + public void visit(IntervalExpression iexpr) { + System.out.println("[VtoSVisitor] IntervalExpression"); + + } + + @Override + public void visit(OracleHierarchicalExpression oexpr) { + System.out.println("[VtoSVisitor] OracleHierarchicalExpression"); + + } + + @Override + public void visit(RegExpMatchOperator rexpr) { + System.out.println("[VtoSVisitor] RegExpMatchOperator"); + + } + + @Override + public void visit(JsonExpression jsonExpr) { + System.out.println("[VtoSVisitor] JsonExpression"); + + } + + @Override + public void visit(JsonOperator jsonExpr) { + System.out.println("[VtoSVisitor] JsonOperator"); + + } + + @Override + public void visit(RegExpMySQLOperator regExpMySQLOperator) { + System.out.println("[VtoSVisitor] RegExpMySQLOperator"); + + } + + @Override + public void visit(UserVariable var) { + System.out.println("[VtoSVisitor] UserVariable"); + + } + + @Override + public void visit(NumericBind bind) { + System.out.println("[VtoSVisitor] NumericBind"); + + } + + @Override + public void visit(KeepExpression aexpr) { + System.out.println("[VtoSVisitor] KeepExpression"); + + } + + @Override + public void visit(MySQLGroupConcat groupConcat) { + System.out.println("[VtoSVisitor] MySQLGroupConcat"); + + } + + @Override + public void visit(ValueListExpression valueList) { + System.out.println("[VtoSVisitor] ValueListExpression"); + + } + + @Override + public void visit(RowConstructor rowConstructor) { + System.out.println("[VtoSVisitor] RowConstructor"); + + } + + @Override + public void visit(OracleHint hint) { + System.out.println("[VtoSVisitor] OracleHint"); + + } + + @Override + public void visit(TimeKeyExpression timeKeyExpression) { + System.out.println("[VtoSVisitor] TimeKeyExpression"); + + } + + @Override + public void visit(DateTimeLiteralExpression literal) { + System.out.println("[VtoSVisitor] DateTimeLiteralExpression"); + + } + + @Override + public void visit(NotExpression aThis) { + System.out.println("[VtoSVisitor] NotExpression"); + + } + + @Override + public void visit(NextValExpression aThis) { + System.out.println("[VtoSVisitor] NextValExpression"); + + } + + @Override + public void visit(CollateExpression aThis) { + System.out.println("[VtoSVisitor] CollateExpression"); + + } + + @Override + public void visit(SimilarToExpression aThis) { + System.out.println("[VtoSVisitor] SimilarToExpression"); + + } + + @Override + public void visit(ArrayExpression aThis) { + System.out.println("[VtoSVisitor] ArrayExpression"); + + } + + @Override + public void visit(VariableAssignment aThis) { + System.out.println("[VtoSVisitor] VariableAssignment"); + + } + + @Override + public void visit(XMLSerializeExpr aThis) { + System.out.println("[VtoSVisitor] XMLSerializeExpr"); + + } +} diff --git a/sf-jdbc-driver/src/test/java/com/ascendix/jdbc/salesforce/ForceDriverTest.java b/sf-jdbc-driver/src/test/java/com/ascendix/jdbc/salesforce/ForceDriverTest.java index 93b57d7..d9234cc 100644 --- a/sf-jdbc-driver/src/test/java/com/ascendix/jdbc/salesforce/ForceDriverTest.java +++ b/sf-jdbc-driver/src/test/java/com/ascendix/jdbc/salesforce/ForceDriverTest.java @@ -1,11 +1,16 @@ package com.ascendix.jdbc.salesforce; +import com.ascendix.jdbc.salesforce.connection.ForceConnection; +import com.ascendix.jdbc.salesforce.metadata.ForceDatabaseMetaData; +import com.ascendix.jdbc.salesforce.metadata.Table; +import com.sforce.soap.partner.PartnerConnection; import org.junit.Before; +import org.junit.Ignore; import org.junit.Test; import java.io.IOException; -import java.sql.Connection; -import java.sql.SQLException; +import java.sql.*; +import java.util.List; import java.util.Properties; import static org.junit.Assert.*; @@ -20,7 +25,7 @@ public void setUp() { } @Test - public void testGetConnStringProperties() throws IOException { + public void testGetConnStringProperties_ListNoHost() throws IOException { Properties actuals = driver.getConnStringProperties("jdbc:ascendix:salesforce://prop1=val1;prop2=val2"); assertEquals(2, actuals.size()); @@ -28,6 +33,16 @@ public void testGetConnStringProperties() throws IOException { assertEquals("val2", actuals.getProperty("prop2")); } + @Test + public void testGetConnStringProperties_ListWithHost() throws IOException { + Properties actuals = driver.getConnStringProperties("jdbc:ascendix:salesforce://login.salesforce.ru:7642;prop1=val1;prop2=val2"); + + assertEquals(3, actuals.size()); + assertEquals("login.salesforce.ru:7642", actuals.getProperty("loginDomain")); + assertEquals("val1", actuals.getProperty("prop1")); + assertEquals("val2", actuals.getProperty("prop2")); + } + @Test public void testGetConnStringProperties_WhenNoValue() throws IOException { Properties actuals = driver.getConnStringProperties("jdbc:ascendix:salesforce://prop1=val1; prop2; prop3 = val3"); @@ -37,22 +52,82 @@ public void testGetConnStringProperties_WhenNoValue() throws IOException { assertEquals("", actuals.getProperty("prop2")); } - @Test - public void testConnect_WhenWrongURL() throws SQLException { - Connection connection = driver.connect("jdbc:mysql://localhost/test", new Properties()); - - assertNull(connection); + private String renderResultSet(ResultSet results) throws SQLException { + StringBuilder out = new StringBuilder(); + + int count = 0; + int columnsCount = results.getMetaData().getColumnCount(); + + // print header + for(int i = 0; i < columnsCount; i++) { + out.append(results.getMetaData().getColumnName(i+1)).append("\t"); + } + out.append("\n"); + + while(results.next()) { + for(int i = 0; i < columnsCount; i++) { + out.append(" " + results.getString(i+1)).append("\t"); + } + out.append("\n"); + count++; + } + out.append("-----------------\n"); + out.append(count).append(" records\n"); + if (results.getWarnings() != null) { + out.append("----------------- WARNINGS:\n"); + SQLWarning warning = results.getWarnings(); + while(warning != null) { + out.append(warning.getMessage()).append("\n"); + warning = warning.getNextWarning(); + } + } + return out.toString(); } @Test public void testGetConnStringProperties_StandartUrlFormat() throws IOException { - Properties actuals = driver.getConnStringProperties("jdbc:ascendix:salesforce://test@test.ru:aaaa!aaa@login.salesforce.ru"); + Properties actuals = driver.getConnStringProperties("jdbc:ascendix:salesforce://test@test.ru:aaaa!aaa@login.salesforce.ru:7642"); assertEquals(3, actuals.size()); assertTrue(actuals.containsKey("user")); assertEquals("test@test.ru", actuals.getProperty("user")); assertEquals("aaaa!aaa", actuals.getProperty("password")); - assertEquals("login.salesforce.ru", actuals.getProperty("loginDomain")); + assertEquals("login.salesforce.ru:7642", actuals.getProperty("loginDomain")); + } + + @Test + public void testGetConnStringProperties_JdbcUrlFormatNoUser() throws IOException { + Properties actuals = driver.getConnStringProperties("jdbc:ascendix:salesforce://login.salesforce.ru:7642"); + + assertEquals(1, actuals.size()); + assertEquals("login.salesforce.ru:7642", actuals.getProperty("loginDomain")); + } + + @Test + public void testGetConnStringProperties_HostName() throws IOException { + Properties actuals = driver.getConnStringProperties("login.salesforce.ru:7642"); + + assertEquals(2, actuals.size()); + assertEquals("login.salesforce.ru:7642", actuals.getProperty("loginDomain")); + assertEquals(true, driver.resolveBooleanProperty(actuals, "https", true)); + } + + @Test + public void testGetConnStringProperties_HostNameHttp() throws IOException { + Properties actuals = driver.getConnStringProperties("http://login.salesforce.ru:7642"); + + assertEquals(2, actuals.size()); + assertEquals("login.salesforce.ru:7642", actuals.getProperty("loginDomain")); + assertEquals(false, driver.resolveBooleanProperty(actuals, "https", true)); + } + + @Test + public void testGetConnStringProperties_IP() throws IOException { + Properties actuals = driver.getConnStringProperties("192.168.0.2:7642"); + + assertEquals(2, actuals.size()); + assertEquals("192.168.0.2:7642", actuals.getProperty("loginDomain")); + assertEquals(true, driver.resolveBooleanProperty(actuals, "https", true)); } @Test diff --git a/sf-jdbc-driver/src/test/java/com/ascendix/jdbc/salesforce/metadata/ForceDatabaseMetaDataTest.java b/sf-jdbc-driver/src/test/java/com/ascendix/jdbc/salesforce/metadata/ForceDatabaseMetaDataTest.java index 37bfa8f..1bcfb51 100644 --- a/sf-jdbc-driver/src/test/java/com/ascendix/jdbc/salesforce/metadata/ForceDatabaseMetaDataTest.java +++ b/sf-jdbc-driver/src/test/java/com/ascendix/jdbc/salesforce/metadata/ForceDatabaseMetaDataTest.java @@ -1,6 +1,5 @@ package com.ascendix.jdbc.salesforce.metadata; -import com.ascendix.jdbc.salesforce.metadata.ForceDatabaseMetaData; import org.junit.Test; import java.sql.Types; diff --git a/sf-jdbc-driver/src/test/java/com/ascendix/jdbc/salesforce/statement/SoqlQueryAnalyzerTest.java b/sf-jdbc-driver/src/test/java/com/ascendix/jdbc/salesforce/statement/SoqlQueryAnalyzerTest.java index 1ae5e31..76a4fef 100644 --- a/sf-jdbc-driver/src/test/java/com/ascendix/jdbc/salesforce/statement/SoqlQueryAnalyzerTest.java +++ b/sf-jdbc-driver/src/test/java/com/ascendix/jdbc/salesforce/statement/SoqlQueryAnalyzerTest.java @@ -2,12 +2,16 @@ import com.sforce.soap.partner.DescribeSObjectResult; import com.thoughtworks.xstream.XStream; +import com.thoughtworks.xstream.security.NoTypePermission; +import com.thoughtworks.xstream.security.NullPermission; +import com.thoughtworks.xstream.security.PrimitiveTypePermission; import org.junit.Test; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Paths; import java.util.Arrays; +import java.util.Collection; import java.util.List; import java.util.stream.Collectors; @@ -30,6 +34,12 @@ private List listFlatFieldNames(SoqlQueryAnalyzer analyzer) { .collect(Collectors.toList()); } + private List listFlatFieldAliases(SoqlQueryAnalyzer analyzer) { + return listFlatFieldDefinitions(analyzer.getFieldDefinitions()).stream() + .map(FieldDef::getAlias) + .collect(Collectors.toList()); + } + @Test public void testGetFieldNames_SelectWithReferences() { SoqlQueryAnalyzer analyzer = new SoqlQueryAnalyzer(" select Id , Account.Name \r\nfrom Contact\r\n where something = 'nothing' ", n -> this.describeSObject(n)); @@ -42,12 +52,33 @@ public void testGetFieldNames_SelectWithReferences() { @Test public void testGetFieldNames_SelectWithAggregateAliased() { SoqlQueryAnalyzer analyzer = new SoqlQueryAnalyzer(" select Id , Account.Name, count(id) aggrAlias1\r\nfrom Contact\r\n where something = 'nothing' ", n -> this.describeSObject(n)); + // Just Name is confusing - see the case List expecteds = Arrays.asList("Id", "Name", "aggrAlias1"); List actuals = listFlatFieldNames(analyzer); assertEquals(expecteds, actuals); } + @Test + public void testGetFieldNames_SubSelectWithSameFields() { + SoqlQueryAnalyzer analyzer = new SoqlQueryAnalyzer(" select Id, Account.Name, Owner.Id, Owner.Name from Account ", n -> this.describeSObject(n)); + // Just Name is confusing - see the case + List expecteds = Arrays.asList("Id", "Name", "Id", "Name"); + List actuals = listFlatFieldNames(analyzer); + + assertEquals(expecteds, actuals); + } + + @Test + public void testGetFieldNames_SubSelectWithSameFieldAliases() { + SoqlQueryAnalyzer analyzer = new SoqlQueryAnalyzer(" select Id, Account.Name, Owner.Id, Owner.Name from Account ", n -> this.describeSObject(n)); + // Just Name is confusing - see the case + List expecteds = Arrays.asList("Id", "Name", "Owner.Id", "Owner.Name"); + List actuals = listFlatFieldAliases(analyzer); + + assertEquals(expecteds, actuals); + } + @Test public void testGetFieldNames_SelectWithAggregate() { SoqlQueryAnalyzer analyzer = new SoqlQueryAnalyzer(" select Id , Account.Name, count(id)\r\nfrom Contact\r\n where something = 'nothing' ", n -> this.describeSObject(n)); @@ -103,7 +134,7 @@ public void testGetAggregateFieldDefinition() { List actuals = listFlatFieldDefinitions(analyzer.getFieldDefinitions()); assertEquals(1, actuals.size()); - assertEquals("MIN", actuals.get(0).getName()); + assertEquals("MIN", actuals.get(0).getAlias()); assertEquals("string", actuals.get(0).getType()); } @@ -142,9 +173,23 @@ private DescribeSObjectResult describeSObject(String sObjectType) { try { String xml = new String(Files.readAllBytes(Paths.get("src/test/resources/" + sObjectType + "_desription.xml"))); XStream xstream = new XStream(); + XStream.setupDefaultSecurity(xstream); + + // clear out existing permissions and set own ones + xstream.addPermission(NoTypePermission.NONE); + // allow some basics + xstream.addPermission(NullPermission.NULL); + xstream.addPermission(PrimitiveTypePermission.PRIMITIVES); + xstream.allowTypeHierarchy(Collection.class); + + xstream.addImmutableType(com.sforce.soap.partner.SoapType.class, true); + xstream.addImmutableType(com.sforce.soap.partner.FieldType.class, true); + xstream.allowTypesByRegExp(new String[] { ".*" }); return (DescribeSObjectResult) xstream.fromXML(xml); } catch (IOException e) { throw new RuntimeException(e); + } catch (Exception e) { + throw new RuntimeException(e); } } @@ -165,7 +210,7 @@ public void testFetchFieldDefinitions_WithIncludedSeslect() { assertEquals("id", fieldDef.getType()); fieldDef = (FieldDef) suqueryDef.get(1); - assertEquals("maxLastName", fieldDef.getName()); + assertEquals("maxLastName", fieldDef.getAlias()); assertEquals("string", fieldDef.getType()); fieldDef = (FieldDef) actuals.get(2); diff --git a/sf-jdbc-driver/src/test/java/com/ascendix/jdbc/salesforce/statement/processor/AdminQueryProcessorTest.java b/sf-jdbc-driver/src/test/java/com/ascendix/jdbc/salesforce/statement/processor/AdminQueryProcessorTest.java new file mode 100644 index 0000000..0e4bf5b --- /dev/null +++ b/sf-jdbc-driver/src/test/java/com/ascendix/jdbc/salesforce/statement/processor/AdminQueryProcessorTest.java @@ -0,0 +1,118 @@ +package com.ascendix.jdbc.salesforce.statement.processor; + +import com.ascendix.jdbc.salesforce.statement.ForcePreparedStatement; +import org.junit.Test; + +import java.math.BigDecimal; +import java.sql.SQLException; +import java.text.SimpleDateFormat; +import java.util.GregorianCalendar; +import java.util.List; + +import static org.junit.Assert.*; + +public class AdminQueryProcessorTest { + + @Test + public void testConnectORA_isAdminQuery() { + assertFalse(AdminQueryProcessor.isAdminQuery("")); + assertTrue(AdminQueryProcessor.isAdminQuery("CONN dev@Local.org/123456")); + assertTrue(AdminQueryProcessor.isAdminQuery("CONNECT dev@Local.org/123456")); + assertTrue(AdminQueryProcessor.isAdminQuery("CONN dev@Local.org/123456;")); + assertTrue(AdminQueryProcessor.isAdminQuery("CONNECT dev@Local.org/123456;")); + assertTrue(AdminQueryProcessor.isAdminQuery("CONN 'dev@Local.org'/'123456'")); + assertTrue(AdminQueryProcessor.isAdminQuery("CONNECT \"dev@Local.org\"/\"123456\"")); + assertTrue(AdminQueryProcessor.isAdminQuery("CONN dev@Local.org/123456;")); + assertTrue(AdminQueryProcessor.isAdminQuery("CONNECT dev@Local.org/123456;")); + assertTrue(AdminQueryProcessor.isAdminQuery("CONN 'dev@Local.org'/'123456';")); + assertTrue(AdminQueryProcessor.isAdminQuery("CONNECT \"dev@Local.org\"/\"123456\";")); + assertTrue(AdminQueryProcessor.isAdminQuery("CONN 'dev@Local.org/123456';")); + assertTrue(AdminQueryProcessor.isAdminQuery("CONNECT \"dev@Local.org/123456\";")); + } + + @Test + public void testConnectPG_isAdminQuery_NoTO() { + assertFalse(AdminQueryProcessor.isAdminQuery("")); + assertTrue(AdminQueryProcessor.isAdminQuery("CONNECT USER dev@Local.org IDENTIFIED BY 123456")); + assertTrue(AdminQueryProcessor.isAdminQuery("CONNECT USER dev@Local.org IDENTIFIED BY 123456;")); + assertTrue(AdminQueryProcessor.isAdminQuery("CONNECT USER 'dev@Local.org' IDENTIFIED BY '123456'")); + assertTrue(AdminQueryProcessor.isAdminQuery("CONNECT USER 'dev@Local.org' IDENTIFIED BY '123456';")); + assertTrue(AdminQueryProcessor.isAdminQuery("CONNECT USER \"dev@Local.org\" IDENTIFIED BY \"123456\"")); + assertTrue(AdminQueryProcessor.isAdminQuery("CONNECT USER \"dev@Local.org\" IDENTIFIED BY \"123456\";")); + } + + @Test + public void testConnectPG_isAdminQuery_WithTo() { + assertFalse(AdminQueryProcessor.isAdminQuery("")); + assertTrue(AdminQueryProcessor.isAdminQuery("CONNECT TO http://localhost:6109")); + assertTrue(AdminQueryProcessor.isAdminQuery("CONNECT TO http://localhost:6109 USER dev@Local.org IDENTIFIED BY 123456")); + assertTrue(AdminQueryProcessor.isAdminQuery("CONNECT TO http://localhost:6109;")); + assertTrue(AdminQueryProcessor.isAdminQuery("CONNECT TO http://localhost:6109 USER dev@Local.org IDENTIFIED BY 123456;")); + } + + @Test + public void testConnectORA_processLoginCommand() throws SQLException { + assertTrue(AdminQueryProcessor.processLoginCommand("CONN dev@Local.org/123456", null, + testProcessor(null, "dev@Local.org", "123456", null, true))); + assertTrue(AdminQueryProcessor.processLoginCommand("CONNECT dev@Local.org/123456", null, + testProcessor(null, "dev@Local.org", "123456", null, true))); + assertTrue(AdminQueryProcessor.processLoginCommand("CONN dev@Local.org/123456;", null, + testProcessor(null, "dev@Local.org", "123456", null, true))); + assertTrue(AdminQueryProcessor.processLoginCommand("CONNECT dev@Local.org/123456;", null, + testProcessor(null, "dev@Local.org", "123456", null, true))); + assertTrue(AdminQueryProcessor.processLoginCommand("CONN 'dev@Local.org'/'123456'", null, + testProcessor(null, "dev@Local.org", "123456", null, true))); + assertTrue(AdminQueryProcessor.processLoginCommand("CONNECT \"dev@Local.org\"/\"123456\"", null, + testProcessor(null, "dev@Local.org", "123456", null, true))); + assertTrue(AdminQueryProcessor.processLoginCommand("CONN dev@Local.org/123456;", null, + testProcessor(null, "dev@Local.org", "123456", null, true))); + assertTrue(AdminQueryProcessor.processLoginCommand("CONNECT dev@Local.org/123456;", null, + testProcessor(null, "dev@Local.org", "123456", null, true))); + assertTrue(AdminQueryProcessor.processLoginCommand("CONN 'dev@Local.org'/'123456';", null, + testProcessor(null, "dev@Local.org", "123456", null, true))); + assertTrue(AdminQueryProcessor.processLoginCommand("CONNECT \"dev@Local.org\"/\"123456\";", null, + testProcessor(null, "dev@Local.org", "123456", null, true))); + assertTrue(AdminQueryProcessor.processLoginCommand("CONN 'dev@Local.org/123456';", null, + testProcessor(null, "dev@Local.org", "123456", null, true))); + assertTrue(AdminQueryProcessor.processLoginCommand("CONNECT \"dev@Local.org/123456\";", null, + testProcessor(null, "dev@Local.org", "123456", null, true))); + } + @Test + public void testConnectPG_processLoginCommand_NoTO() throws SQLException { + assertTrue(AdminQueryProcessor.processLoginCommand("CONNECT USER dev@Local.org IDENTIFIED BY 123456", null, + testProcessor(null, "dev@Local.org", "123456", null, true))); + assertTrue(AdminQueryProcessor.processLoginCommand("CONNECT USER dev@Local.org IDENTIFIED BY 123456;", null, + testProcessor(null, "dev@Local.org", "123456", null, true))); + assertTrue(AdminQueryProcessor.processLoginCommand("CONNECT USER 'dev@Local.org' IDENTIFIED BY '123456'", null, + testProcessor(null, "dev@Local.org", "123456", null, true))); + assertTrue(AdminQueryProcessor.processLoginCommand("CONNECT USER 'dev@Local.org' IDENTIFIED BY '123456';", null, + testProcessor(null, "dev@Local.org", "123456", null, true))); + assertTrue(AdminQueryProcessor.processLoginCommand("CONNECT USER \"dev@Local.org\" IDENTIFIED BY \"123456\"", null, + testProcessor(null, "dev@Local.org", "123456", null, true))); + assertTrue(AdminQueryProcessor.processLoginCommand("CONNECT USER \"dev@Local.org\" IDENTIFIED BY \"123456\";", null, + testProcessor(null, "dev@Local.org", "123456", null, true))); + } + + @Test + public void testConnectPG_processLoginCommand_WithTo() throws SQLException { + assertFalse(AdminQueryProcessor.processLoginCommand("", null, null)); + assertTrue(AdminQueryProcessor.processLoginCommand("CONNECT TO http://localhost:6109", null, + testProcessor("http://localhost:6109", null, null, "localhost:6109", true))); + assertTrue(AdminQueryProcessor.processLoginCommand("CONNECT TO http://localhost:6109 USER dev@Local.org IDENTIFIED BY 123456", null, + testProcessor("http://localhost:6109", "dev@Local.org", "123456", "localhost:6109", true))); + assertTrue(AdminQueryProcessor.processLoginCommand("CONNECT TO http://localhost:6109;", null, + testProcessor("http://localhost:6109", null, null, "localhost:6109", true))); + assertTrue(AdminQueryProcessor.processLoginCommand("CONNECT TO http://localhost:6109 USER dev@Local.org IDENTIFIED BY 123456;", null, + testProcessor("http://localhost:6109", "dev@Local.org", "123456", "localhost:6109", true))); + } + + private AdminQueryProcessor.LoginCommandProcessor testProcessor(String expectedUrl, String expectedUserName, String expectedUserPass, String expectedHost, boolean result) throws SQLException { + return (url, userName, userPass, host) -> { + assertEquals(expectedUrl, url); + assertEquals(expectedUserName, userName); + assertEquals(expectedUserPass, userPass); + assertEquals(expectedHost, host); + return result; + }; + } +} diff --git a/sf-jdbc-driver/src/test/java/com/ascendix/jdbc/salesforce/statement/processor/InsertQueryAnalyzerTest.java b/sf-jdbc-driver/src/test/java/com/ascendix/jdbc/salesforce/statement/processor/InsertQueryAnalyzerTest.java new file mode 100644 index 0000000..841b649 --- /dev/null +++ b/sf-jdbc-driver/src/test/java/com/ascendix/jdbc/salesforce/statement/processor/InsertQueryAnalyzerTest.java @@ -0,0 +1,111 @@ +package com.ascendix.jdbc.salesforce.statement.processor; + +import com.google.common.collect.Sets; +import com.sforce.soap.partner.DescribeSObjectResult; +import org.junit.Test; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; + +import static org.junit.Assert.*; + +public class InsertQueryAnalyzerTest { + + @Test + public void testIsInsertQuery() { + String soql = "insert into Account(Name, OwnerId) values ('FirstAccount', '005xx1231231233123')"; + Map cache = new HashMap<>(); + InsertQueryAnalyzer analyzer = new InsertQueryAnalyzer(soql, this::describeSObject, cache, null); + + assertTrue(analyzer.analyse(soql)); + } + + private DescribeSObjectResult describeSObject(String objName) { + DescribeSObjectResult result = new DescribeSObjectResult(); + result.setName(objName); + return result; + } + + @Test + public void testProcessInsert_ValuesOne() { + String soql = "insert into Account(Name, OwnerId, Title) values ('FirstAccount', '005xx1231231233123', Null)"; + Map cache = new HashMap<>(); + InsertQueryAnalyzer analyzer = new InsertQueryAnalyzer(soql, this::describeSObject, cache, null); + + assertTrue(analyzer.analyse(soql)); + assertEquals("Account", analyzer.getFromObjectName()); + + // Verify we have exactly one record to save + assertEquals(1, analyzer.getRecords().size()); + Map record = analyzer.getRecords().get(0); + // Verify the fields count for the first record + assertEquals(3, record.size()); + // Verify the fields' names for the first record + assertEquals(Sets.newHashSet("Name", "OwnerId", "Title"), record.keySet()); + assertEquals("FirstAccount", record.get("Name")); + assertEquals("005xx1231231233123", record.get("OwnerId")); + assertTrue(record.containsKey("Title")); + assertNull(record.get("Title")); + } + + @Test + public void testProcessInsert_ValuesOneSubSelect() { + String soql = "insert into Account(Name, OwnerId) values ('FirstAccount', " + + " (SELECT Id from User where Name='CollectionOwner-f CollectionOwner-l' LIMIT 1) " + + ")"; + Map cache = new HashMap<>(); + InsertQueryAnalyzer analyzer = new InsertQueryAnalyzer(soql, this::describeSObject, cache, subSoql -> { + if ("SELECT Id FROM User WHERE Name = 'CollectionOwner-f CollectionOwner-l' LIMIT 1".equals(subSoql)) { + Map record = new HashMap<>(); + record.put("id", "005xx1231231233123"); + return Arrays.asList(record); + } + return Arrays.asList(); + }); + + assertTrue(analyzer.analyse(soql)); + assertEquals("Account", analyzer.getFromObjectName()); + + // Verify we have exactly one record to save + assertEquals(1, analyzer.getRecords().size()); + Map record = analyzer.getRecords().get(0); + // Verify the fields count for the first record + assertEquals(2, record.size()); + // Verify the fields' names for the first record + assertEquals(Sets.newHashSet("Name", "OwnerId"), record.keySet()); + assertEquals("FirstAccount", record.get("Name")); + assertEquals("005xx1231231233123", record.get("OwnerId")); + } + + @Test + public void testProcessInsert_ValuesTwo() { + String soql = "insert into Account(Name, OwnerId) values ('FirstAccount', '005xx1111111111111'), ('SecondAccount', '005xx2222222222222')"; + Map cache = new HashMap<>(); + InsertQueryAnalyzer analyzer = new InsertQueryAnalyzer(soql, this::describeSObject, cache, null); + + assertTrue(analyzer.analyse(soql)); + assertEquals("Account", analyzer.getFromObjectName()); + + // Verify we have exactly one record to save + assertEquals(2, analyzer.getRecords().size()); + + // Verify the first record + Map record = analyzer.getRecords().get(0); + // Verify the fields count for the first record + assertEquals(2, record.size()); + // Verify the fields' names for the first record + assertEquals(Sets.newHashSet("Name", "OwnerId"), record.keySet()); + assertEquals("FirstAccount", record.get("Name")); + assertEquals("005xx1111111111111", record.get("OwnerId")); + + // Verify the second record + record = analyzer.getRecords().get(1); + // Verify the fields count for the second record + assertEquals(2, record.size()); + // Verify the fields' names for the first record + assertEquals(Sets.newHashSet("Name", "OwnerId"), record.keySet()); + assertEquals("SecondAccount", record.get("Name")); + assertEquals("005xx2222222222222", record.get("OwnerId")); + } +} diff --git a/sf-jdbc-driver/src/test/java/com/ascendix/jdbc/salesforce/statement/processor/InsertQueryProcessorTest.java b/sf-jdbc-driver/src/test/java/com/ascendix/jdbc/salesforce/statement/processor/InsertQueryProcessorTest.java new file mode 100644 index 0000000..9a26899 --- /dev/null +++ b/sf-jdbc-driver/src/test/java/com/ascendix/jdbc/salesforce/statement/processor/InsertQueryProcessorTest.java @@ -0,0 +1,12 @@ +package com.ascendix.jdbc.salesforce.statement.processor; + +import org.junit.Test; + +public class InsertQueryProcessorTest { + + @Test + public void testAnalyse() { +// InsertQueryProcessor + + } +} diff --git a/sf-jdbc-driver/src/test/java/com/ascendix/jdbc/salesforce/statement/processor/UpdateQueryAnalyzerTest.java b/sf-jdbc-driver/src/test/java/com/ascendix/jdbc/salesforce/statement/processor/UpdateQueryAnalyzerTest.java new file mode 100644 index 0000000..64c5c3d --- /dev/null +++ b/sf-jdbc-driver/src/test/java/com/ascendix/jdbc/salesforce/statement/processor/UpdateQueryAnalyzerTest.java @@ -0,0 +1,143 @@ +package com.ascendix.jdbc.salesforce.statement.processor; + +import com.ascendix.jdbc.salesforce.statement.processor.utils.RecordFieldsBuilder; +import com.google.common.collect.Sets; +import com.sforce.soap.partner.DescribeSObjectResult; +import org.junit.Test; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; + +import static org.junit.Assert.*; + +public class UpdateQueryAnalyzerTest { + + @Test + public void testIsUpdateQuery_ById() { + String soql = "Update Account set Name ='FirstAccount_new' where Id='001xx000003GeY0AAK'"; + Map cache = new HashMap<>(); + UpdateQueryAnalyzer analyzer = new UpdateQueryAnalyzer(soql, this::describeSObject, cache, null); + + assertTrue(analyzer.analyse(soql)); + } + + private DescribeSObjectResult describeSObject(String objName) { + DescribeSObjectResult result = new DescribeSObjectResult(); + result.setName(objName); + return result; + } + + @Test + public void testProcessUpdate_One_ById() { + String soql = "Update Account set Name ='FirstAccount_new' where Id='001xx000003GeY0AAK'"; + Map cache = new HashMap<>(); + UpdateQueryAnalyzer analyzer = new UpdateQueryAnalyzer(soql, this::describeSObject, cache, null); + + assertTrue(analyzer.analyse(soql)); + assertEquals("Account", analyzer.getFromObjectName()); + + // Verify we have exactly one record to save + assertEquals(1, analyzer.getRecords().size()); + Map record = analyzer.getRecords().get(0); + // Verify the fields count for the first record + assertEquals(2, record.size()); + // Verify the fields' names for the first record + assertEquals(Sets.newHashSet("Name", "Id"), record.keySet()); + assertEquals("FirstAccount_new", record.get("Name")); + assertEquals("001xx000003GeY0AAK", record.get("Id")); + } + + @Test + public void testProcessUpdate_One_ByName() { + String soql = "Update Account set Name ='NEW_AccountName' where Name='FirstAccount_new'"; + Map cache = new HashMap<>(); + UpdateQueryAnalyzer analyzer = new UpdateQueryAnalyzer(soql, this::describeSObject, cache, subSoql -> { + if ("SELECT Id FROM Account WHERE Name = 'FirstAccount_new'".equals(subSoql)) { + return Arrays.asList( + RecordFieldsBuilder.id("005xx1111111111111"), + RecordFieldsBuilder.id("005xx2222222222222"), + RecordFieldsBuilder.id("005xx3333333333333") + ); + } + return Arrays.asList(); + }); + + assertTrue(analyzer.analyse(soql)); + assertEquals("Account", analyzer.getFromObjectName()); + + // Verify we have exactly three record to save + assertEquals(3, analyzer.getRecords().size()); + + Map record = analyzer.getRecords().get(0); + // Verify the fields count for the first record + assertEquals(2, record.size()); + // Verify the fields' names for the first record + assertEquals(Sets.newHashSet("Name", "Id"), record.keySet()); + assertEquals("NEW_AccountName", record.get("Name")); + assertEquals("005xx1111111111111", record.get("Id")); + + record = analyzer.getRecords().get(1); + // Verify the fields count for the first record + assertEquals(2, record.size()); + // Verify the fields' names for the first record + assertEquals(Sets.newHashSet("Name", "Id"), record.keySet()); + assertEquals("NEW_AccountName", record.get("Name")); + assertEquals("005xx2222222222222", record.get("Id")); + + record = analyzer.getRecords().get(2); + // Verify the fields count for the first record + assertEquals(2, record.size()); + // Verify the fields' names for the first record + assertEquals(Sets.newHashSet("Name", "Id"), record.keySet()); + assertEquals("NEW_AccountName", record.get("Name")); + assertEquals("005xx3333333333333", record.get("Id")); + } + + @Test + public void testProcessUpdate_One_ByName_CALC() { + String soql = "Update Account set Name=Name+'-' where Name='FirstAccount_new'"; + Map cache = new HashMap<>(); + UpdateQueryAnalyzer analyzer = new UpdateQueryAnalyzer(soql, this::describeSObject, cache, subSoql -> { + if ("SELECT Id, Name FROM Account WHERE Name = 'FirstAccount_new'".equals(subSoql)) { + return Arrays.asList( + RecordFieldsBuilder.setId("005xx1111111111111").set("Name", "Acc_01").build(), + RecordFieldsBuilder.setId("005xx2222222222222").set("Name", "Acc_02").build(), + RecordFieldsBuilder.setId("005xx3333333333333").set("Name", "Acc_03").build() + ); + } + return Arrays.asList(); + }); + + assertTrue(analyzer.analyse(soql)); + assertEquals("Account", analyzer.getFromObjectName()); + + // Verify we have exactly three record to save + assertEquals(3, analyzer.getRecords().size()); + + Map record = analyzer.getRecords().get(0); + // Verify the fields count for the first record + assertEquals(2, record.size()); + // Verify the fields' names for the first record + assertEquals(Sets.newHashSet("Name", "Id"), record.keySet()); + assertEquals("Acc_01-", record.get("Name")); + assertEquals("005xx1111111111111", record.get("Id")); + + record = analyzer.getRecords().get(1); + // Verify the fields count for the first record + assertEquals(2, record.size()); + // Verify the fields' names for the first record + assertEquals(Sets.newHashSet("Name", "Id"), record.keySet()); + assertEquals("Acc_02-", record.get("Name")); + assertEquals("005xx2222222222222", record.get("Id")); + + record = analyzer.getRecords().get(2); + // Verify the fields count for the first record + assertEquals(2, record.size()); + // Verify the fields' names for the first record + assertEquals(Sets.newHashSet("Name", "Id"), record.keySet()); + assertEquals("Acc_03-", record.get("Name")); + assertEquals("005xx3333333333333", record.get("Id")); + } + +} diff --git a/sf-jdbc-driver/src/test/java/com/ascendix/jdbc/salesforce/statement/processor/utils/EvaluateExpressionVisitorTest.java b/sf-jdbc-driver/src/test/java/com/ascendix/jdbc/salesforce/statement/processor/utils/EvaluateExpressionVisitorTest.java new file mode 100644 index 0000000..93249fd --- /dev/null +++ b/sf-jdbc-driver/src/test/java/com/ascendix/jdbc/salesforce/statement/processor/utils/EvaluateExpressionVisitorTest.java @@ -0,0 +1,323 @@ +package com.ascendix.jdbc.salesforce.statement.processor.utils; + +import com.ascendix.jdbc.salesforce.exceptions.UnsupportedArgumentTypeException; +import net.sf.jsqlparser.expression.*; +import net.sf.jsqlparser.expression.operators.arithmetic.Addition; +import net.sf.jsqlparser.expression.operators.arithmetic.Subtraction; +import org.junit.Test; + +import java.util.Map; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + +public class EvaluateExpressionVisitorTest { + + public class EvaluateExpressionVisitorTesting extends EvaluateExpressionVisitor { + public EvaluateExpressionVisitorTesting(Map recordFieldsFromDB) { + super(recordFieldsFromDB); + } + + public void visit(Function function) { + if ("now".equalsIgnoreCase(function.getName())) { + result = "2021-Test-Day 12:12:12"; + } else { + super.visit(function); + } + } + } + + @Test + public void testResolveSimpleTypes() { + Map recordFieldsFromDB = RecordFieldsBuilder.setId("001xx1111111111111").build(); + + EvaluateExpressionVisitor visitorS1 = new EvaluateExpressionVisitor(recordFieldsFromDB); + new StringValue("TestValue-String").accept(visitorS1); + assertEquals("TestValue-String", visitorS1.getResult()); + + EvaluateExpressionVisitor visitorD1 = new EvaluateExpressionVisitor(recordFieldsFromDB); + new DoubleValue("1.7976931348623157e+308").accept(visitorD1); + assertEquals(Double.MAX_VALUE, visitorD1.getResult()); + + EvaluateExpressionVisitor visitorL1 = new EvaluateExpressionVisitor(recordFieldsFromDB); + new LongValue("9223372036854775807").accept(visitorL1); + assertEquals(9223372036854775807L, visitorL1.getResult()); + + EvaluateExpressionVisitor visitorTS1 = new EvaluateExpressionVisitor(recordFieldsFromDB); + new TimestampValue("'2021-10-25 07:19:33'").accept(visitorTS1); + assertEquals(java.sql.Timestamp.valueOf("2021-10-25 07:19:33"), visitorTS1.getResult()); + + EvaluateExpressionVisitor visitorDate1 = new EvaluateExpressionVisitor(recordFieldsFromDB); + new DateValue("'1964-10-27'").accept(visitorDate1); + assertEquals(java.sql.Date.valueOf("1964-10-27"), visitorDate1.getResult()); + + EvaluateExpressionVisitor visitorT1 = new EvaluateExpressionVisitor(recordFieldsFromDB); + new TimeValue("'03:26:57'").accept(visitorT1); + assertEquals(java.sql.Time.valueOf("03:26:57"), visitorT1.getResult()); + + } + + @Test + public void testResolveAdditions_Dates() { + Map recordFieldsFromDB = RecordFieldsBuilder.setId("001xx1111111111111").build(); + + EvaluateExpressionVisitor visitorTS1 = new EvaluateExpressionVisitor(recordFieldsFromDB); + new Addition() + .withLeftExpression( new TimestampValue("'2021-10-25 07:19:33'")) + .withRightExpression(new LongValue("1")) + .accept(visitorTS1); + assertEquals(java.sql.Timestamp.valueOf("2021-10-26 07:19:33"), visitorTS1.getResult()); + + EvaluateExpressionVisitor visitorDate1 = new EvaluateExpressionVisitor(recordFieldsFromDB); + new Addition() + .withLeftExpression( new DateValue("'1964-10-27'")) + .withRightExpression(new LongValue("1")) + .accept(visitorDate1); + assertEquals(java.sql.Date.valueOf("1964-10-28"), visitorDate1.getResult()); + + EvaluateExpressionVisitor visitorT1 = new EvaluateExpressionVisitor(recordFieldsFromDB); + new Addition() + .withLeftExpression( new TimeValue("'03:26:57'")) + .withRightExpression(new DoubleValue("0.000011574")) // 1 second = 1/86400 of day = 1/(24*60*60) of day + .accept(visitorT1); + assertEquals(java.sql.Time.valueOf("03:26:58"), visitorT1.getResult()); + } + + @Test + public void testResolveAdditions_SimpleTypes() { + Map recordFieldsFromDB = RecordFieldsBuilder.setId("001xx1111111111111").build(); + + EvaluateExpressionVisitor visitorSS = new EvaluateExpressionVisitor(recordFieldsFromDB); + new Addition() + .withLeftExpression( new StringValue("TestPartLeft-")) + .withRightExpression(new StringValue("TestPartRight~")) + .accept(visitorSS); + assertEquals("TestPartLeft-TestPartRight~", visitorSS.getResult()); + + EvaluateExpressionVisitor visitorDD = new EvaluateExpressionVisitor(recordFieldsFromDB); + new Addition() + .withLeftExpression( new DoubleValue("12345678.1231")) + .withRightExpression(new DoubleValue("88456634.4333")) + .accept(visitorDD); + assertEquals(100802312.5564, visitorDD.getResult()); + + EvaluateExpressionVisitor visitorLL = new EvaluateExpressionVisitor(recordFieldsFromDB); + new Addition() + .withLeftExpression( new LongValue("89983422234")) + .withRightExpression(new LongValue("76463763473")) + .accept(visitorLL); + assertEquals(166447185707L, visitorLL.getResult()); + + EvaluateExpressionVisitor visitorSNL = new EvaluateExpressionVisitor(recordFieldsFromDB); + new Addition() + .withLeftExpression( new StringValue("89983422234")) + .withRightExpression(new LongValue("76463763473")) + .accept(visitorSNL); + assertEquals(166447185707L, visitorSNL.getResult()); + + EvaluateExpressionVisitor visitorSL = new EvaluateExpressionVisitor(recordFieldsFromDB); + new Addition() + .withLeftExpression( new StringValue("StrNotNum")) + .withRightExpression(new LongValue("76463763473")) + .accept(visitorSL); + assertEquals("StrNotNum76463763473", visitorSL.getResult()); + + EvaluateExpressionVisitor visitorLS = new EvaluateExpressionVisitor(recordFieldsFromDB); + new Addition() + .withLeftExpression( new LongValue("89983422234")) + .withRightExpression(new StringValue("76463763473")) + .accept(visitorLS); + assertEquals(166447185707L, visitorLS.getResult()); + + EvaluateExpressionVisitor visitorLSN = new EvaluateExpressionVisitor(recordFieldsFromDB); + new Addition() + .withLeftExpression( new LongValue("89983422234")) + .withRightExpression(new StringValue("StrNotNum")) + .accept(visitorLSN); + assertEquals("89983422234StrNotNum", visitorLSN.getResult()); + + EvaluateExpressionVisitor visitorDS = new EvaluateExpressionVisitor(recordFieldsFromDB); + new Addition() + .withLeftExpression( new DoubleValue("12345678.1231")) + .withRightExpression(new StringValue("88456634.4333")) + .accept(visitorDS); + assertEquals(100802312.5564, visitorDS.getResult()); + + EvaluateExpressionVisitor visitorDSN = new EvaluateExpressionVisitor(recordFieldsFromDB); + new Addition() + .withLeftExpression( new DoubleValue("12345678.1231")) + .withRightExpression(new StringValue("StrNotNum")) + .accept(visitorDSN); + assertEquals("1.23456781231E7StrNotNum", visitorDSN.getResult()); + + EvaluateExpressionVisitor visitorSD = new EvaluateExpressionVisitor(recordFieldsFromDB); + new Addition() + .withLeftExpression( new StringValue("12345678.1231")) + .withRightExpression(new DoubleValue("88456634.4333")) + .accept(visitorSD); + assertEquals(100802312.5564, visitorSD.getResult()); + + EvaluateExpressionVisitor visitorSND = new EvaluateExpressionVisitor(recordFieldsFromDB); + new Addition() + .withLeftExpression( new StringValue("StrNotNum")) + .withRightExpression(new DoubleValue("88456634.4333")) + .accept(visitorSND); + assertEquals("StrNotNum8.84566344333E7", visitorSND.getResult()); + + } + + @Test + public void testResolveSubstractions_Dates() { + Map recordFieldsFromDB = RecordFieldsBuilder.setId("001xx1111111111111").build(); + + EvaluateExpressionVisitor visitorTS1 = new EvaluateExpressionVisitor(recordFieldsFromDB); + new Subtraction() + .withLeftExpression( new TimestampValue("'2021-10-25 07:19:33'")) + .withRightExpression(new LongValue("1")) + .accept(visitorTS1); + assertEquals(java.sql.Timestamp.valueOf("2021-10-24 07:19:33"), visitorTS1.getResult()); + + EvaluateExpressionVisitor visitorDate1 = new EvaluateExpressionVisitor(recordFieldsFromDB); + new Subtraction() + .withLeftExpression( new DateValue("'1964-10-27'")) + .withRightExpression(new LongValue("1")) + .accept(visitorDate1); + assertEquals(java.sql.Date.valueOf("1964-10-26"), visitorDate1.getResult()); + + EvaluateExpressionVisitor visitorT1 = new EvaluateExpressionVisitor(recordFieldsFromDB); + new Subtraction() + .withLeftExpression( new TimeValue("'03:26:57'")) + .withRightExpression(new DoubleValue("0.000011574")) // 1 second = 1/86400 of day = 1/(24*60*60) of day + .accept(visitorT1); + assertEquals(java.sql.Time.valueOf("03:26:56"), visitorT1.getResult()); + } + + @Test + public void testResolveSubstractions_SimpleTypes() { + Map recordFieldsFromDB = RecordFieldsBuilder.setId("001xx1111111111111").build(); + + EvaluateExpressionVisitor visitorSS = new EvaluateExpressionVisitor(recordFieldsFromDB); + try { + new Subtraction() + .withLeftExpression(new StringValue("TestPartLeft-")) + .withRightExpression(new StringValue("TestPartRight~")) + .accept(visitorSS); + assertNull(visitorSS.getResult()); // Not supported! + } catch (UnsupportedArgumentTypeException e) { + // It's right! + } + + EvaluateExpressionVisitor visitorDD = new EvaluateExpressionVisitor(recordFieldsFromDB); + new Subtraction() + .withLeftExpression( new DoubleValue("12345678.1231")) + .withRightExpression(new DoubleValue("88456634.4333")) + .accept(visitorDD); + assertEquals(-7.61109563102E7, visitorDD.getResult()); + + EvaluateExpressionVisitor visitorLL = new EvaluateExpressionVisitor(recordFieldsFromDB); + new Subtraction() + .withLeftExpression( new LongValue("89983422234")) + .withRightExpression(new LongValue("76463763473")) + .accept(visitorLL); + assertEquals(13519658761L, visitorLL.getResult()); + + EvaluateExpressionVisitor visitorSNL = new EvaluateExpressionVisitor(recordFieldsFromDB); + try { + new Subtraction() + .withLeftExpression( new StringValue("89983422234")) + .withRightExpression(new LongValue("76463763473")) + .accept(visitorSNL); + assertNull(visitorSS.getResult()); // Not supported! + } catch (UnsupportedArgumentTypeException e) { + // It's right! + } + + EvaluateExpressionVisitor visitorSL = new EvaluateExpressionVisitor(recordFieldsFromDB); + try { + new Subtraction() + .withLeftExpression( new StringValue("StrNotNum")) + .withRightExpression(new LongValue("76463763473")) + .accept(visitorSL); + assertNull(visitorSS.getResult()); // Not supported! + } catch (UnsupportedArgumentTypeException e) { + // It's right! + } + + EvaluateExpressionVisitor visitorLS = new EvaluateExpressionVisitor(recordFieldsFromDB); + try { + new Subtraction() + .withLeftExpression( new LongValue("89983422234")) + .withRightExpression(new StringValue("76463763473")) + .accept(visitorLS); + assertNull(visitorSS.getResult()); // Not supported! + } catch (UnsupportedArgumentTypeException e) { + // It's right! + } + + EvaluateExpressionVisitor visitorLSN = new EvaluateExpressionVisitor(recordFieldsFromDB); + try { + new Subtraction() + .withLeftExpression( new LongValue("89983422234")) + .withRightExpression(new StringValue("StrNotNum")) + .accept(visitorLSN); + assertNull(visitorSS.getResult()); // Not supported! + } catch (UnsupportedArgumentTypeException e) { + // It's right! + } + + EvaluateExpressionVisitor visitorDS = new EvaluateExpressionVisitor(recordFieldsFromDB); + try { + new Subtraction() + .withLeftExpression( new DoubleValue("12345678.1231")) + .withRightExpression(new StringValue("88456634.4333")) + .accept(visitorDS); + assertNull(visitorSS.getResult()); // Not supported! + } catch (UnsupportedArgumentTypeException e) { + // It's right! + } + + EvaluateExpressionVisitor visitorDSN = new EvaluateExpressionVisitor(recordFieldsFromDB); + try { + new Subtraction() + .withLeftExpression( new DoubleValue("12345678.1231")) + .withRightExpression(new StringValue("StrNotNum")) + .accept(visitorDSN); + assertNull(visitorSS.getResult()); // Not supported! + } catch (UnsupportedArgumentTypeException e) { + // It's right! + } + + EvaluateExpressionVisitor visitorSD = new EvaluateExpressionVisitor(recordFieldsFromDB); + try { + new Subtraction() + .withLeftExpression( new StringValue("12345678.1231")) + .withRightExpression(new DoubleValue("88456634.4333")) + .accept(visitorSD); + assertNull(visitorSS.getResult()); // Not supported! + } catch (UnsupportedArgumentTypeException e) { + // It's right! + } + + EvaluateExpressionVisitor visitorSND = new EvaluateExpressionVisitor(recordFieldsFromDB); + try { + new Subtraction() + .withLeftExpression( new StringValue("StrNotNum")) + .withRightExpression(new DoubleValue("88456634.4333")) + .accept(visitorSND); + assertNull(visitorSS.getResult()); // Not supported! + } catch (UnsupportedArgumentTypeException e) { + // It's right! + } + } + + @Test + public void testResolveFunctions() { + Map recordFieldsFromDB = RecordFieldsBuilder.setId("001xx1111111111111").build(); + + EvaluateExpressionVisitor visitorS1 = new EvaluateExpressionVisitorTesting(recordFieldsFromDB); + Function func = new Function(); + func.setName("now"); + func.accept(visitorS1); + assertEquals("2021-Test-Day 12:12:12", visitorS1.getResult()); + } +} diff --git a/sf-jdbc-driver/src/test/java/com/ascendix/jdbc/salesforce/statement/processor/utils/RecordFieldsBuilder.java b/sf-jdbc-driver/src/test/java/com/ascendix/jdbc/salesforce/statement/processor/utils/RecordFieldsBuilder.java new file mode 100644 index 0000000..f2e2535 --- /dev/null +++ b/sf-jdbc-driver/src/test/java/com/ascendix/jdbc/salesforce/statement/processor/utils/RecordFieldsBuilder.java @@ -0,0 +1,29 @@ +package com.ascendix.jdbc.salesforce.statement.processor.utils; + +import com.ascendix.jdbc.salesforce.statement.processor.UpdateQueryAnalyzerTest; + +import java.util.HashMap; +import java.util.Map; + +public class RecordFieldsBuilder { + + Map record = new HashMap<>(); + + public static RecordFieldsBuilder setId(String id) { + return new RecordFieldsBuilder().set("Id", id); + } + + public static Map id(String id) { + return new RecordFieldsBuilder().set("Id", id).build(); + } + + public RecordFieldsBuilder set(String field, Object value) { + record.put(field, value); + return this; + } + + public Map build() { + return record; + } + +} diff --git a/sf-jdbc-driver/src/test/resources/User_desription.xml b/sf-jdbc-driver/src/test/resources/User_desription.xml new file mode 100644 index 0000000..7515599 --- /dev/null +++ b/sf-jdbc-driver/src/test/resources/User_desription.xml @@ -0,0 +1,43003 @@ + + false + + true + false + true + true + true + + + true + false + true + AIApplication + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + AIApplication + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + AIApplicationConfig + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + AIApplicationConfig + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + AIInsightAction + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + AIInsightAction + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + AIInsightFeedback + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + AIInsightFeedback + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + AIInsightReason + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + AIInsightReason + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + AIInsightValue + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + AIInsightValue + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + AIPredictionEvent + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + AIRecordInsight + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + AIRecordInsight + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + AcceptedEventRelation + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + AcceptedEventRelation + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + AcceptedEventRelation + true + false + true + RelationId + false + + false + + true + AcceptedEventRelations + false + false + + + true + false + true + Account + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + Account + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + Account + true + false + true + OwnerId + false + + false + + false + false + false + + + true + false + true + Account + true + false + true + PersonActionCadenceAssigneeId + false + + false + + false + false + false + + + true + false + true + AccountChangeEvent + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + AccountChangeEvent + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + AccountChangeEvent + true + false + true + OwnerId + false + + false + + false + false + false + + + true + false + true + AccountContactRole + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + AccountContactRole + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + AccountContactRoleChangeEvent + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + AccountContactRoleChangeEvent + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + AccountFeed + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + AccountFeed + true + false + true + InsertedById + false + + false + + false + false + false + + + true + false + true + AccountHistory + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + AccountPartner + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + AccountPartner + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + AccountShare + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + true + true + AccountShare + true + false + true + UserOrGroupId + false + + false + + false + false + false + + + true + false + true + ActionCadence + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + ActionCadence + true + false + true + FolderId + false + + false + + false + true + true + + + true + false + true + ActionCadence + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + ActionCadence + true + false + true + OwnerId + false + + false + + false + false + false + + + true + false + true + ActionCadenceChangeEvent + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + ActionCadenceChangeEvent + true + false + true + FolderId + false + + false + + false + false + false + + + true + false + true + ActionCadenceChangeEvent + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + ActionCadenceChangeEvent + true + false + true + OwnerId + false + + false + + false + false + false + + + true + false + true + ActionCadenceRule + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + ActionCadenceRule + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + ActionCadenceRuleCondition + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + ActionCadenceRuleCondition + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + ActionCadenceShare + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + true + true + ActionCadenceShare + true + false + true + UserOrGroupId + false + + false + + false + false + false + + + true + false + true + ActionCadenceStep + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + ActionCadenceStep + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + ActionCadenceStepChangeEvent + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + ActionCadenceStepChangeEvent + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + ActionCadenceStepTracker + true + false + true + CompletedById + false + + false + + true + ActionCadenceStepTrackers + false + false + + + true + false + true + ActionCadenceStepTracker + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + ActionCadenceStepTracker + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + ActionCadenceStepTrackerChangeEvent + true + false + true + CompletedById + false + + false + + false + false + false + + + true + false + true + ActionCadenceStepTrackerChangeEvent + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + ActionCadenceStepTrackerChangeEvent + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + ActionCadenceTracker + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + ActionCadenceTracker + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + ActionCadenceTracker + true + false + true + OwnerId + false + + false + + false + false + false + + + true + false + true + ActionCadenceTrackerChangeEvent + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + ActionCadenceTrackerChangeEvent + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + ActionCadenceTrackerChangeEvent + true + false + true + OwnerId + false + + false + + false + false + false + + + true + false + true + ActionCadenceTrackerShare + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + true + true + ActionCadenceTrackerShare + true + false + true + UserOrGroupId + false + + false + + false + false + false + + + true + false + true + ActionLinkGroupTemplate + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + ActionLinkGroupTemplate + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + ActionLinkTemplate + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + ActionLinkTemplate + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + ActivityHistory + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + ActivityHistory + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + ActivityHistory + true + false + true + OwnerId + false + + false + + false + false + false + + + true + false + true + AdditionalNumber + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + AdditionalNumber + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + Announcement + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + Announcement + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + ApexClass + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + ApexClass + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + ApexComponent + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + ApexComponent + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + ApexEmailNotification + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + ApexEmailNotification + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + true + true + ApexEmailNotification + true + false + true + UserId + false + + false + + false + false + false + + + true + true + true + ApexLog + true + false + true + LogUserId + false + + false + + false + false + false + + + true + false + true + ApexPage + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + ApexPage + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + ApexTestQueueItem + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + ApexTestResultLimits + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + ApexTestResultLimits + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + ApexTestRunResult + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + ApexTestRunResult + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + ApexTestRunResult + true + false + true + UserId + false + + false + + false + false + false + + + true + false + true + ApexTestSuite + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + ApexTestSuite + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + ApexTrigger + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + ApexTrigger + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + AppAnalyticsQueryRequest + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + AppAnalyticsQueryRequest + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + AppMenuItem + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + AppMenuItem + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + Asset + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + Asset + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + Asset + true + false + true + OwnerId + false + + false + + false + false + false + + + true + false + true + AssetChangeEvent + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + AssetChangeEvent + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + AssetChangeEvent + true + false + true + OwnerId + false + + false + + false + false + false + + + true + false + true + AssetFeed + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + AssetFeed + true + false + true + InsertedById + false + + false + + false + false + false + + + true + false + true + AssetHistory + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + AssetRelationship + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + AssetRelationship + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + AssetRelationshipFeed + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + AssetRelationshipFeed + true + false + true + InsertedById + false + + false + + false + false + false + + + true + false + true + AssetRelationshipHistory + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + AssetShare + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + true + true + AssetShare + true + false + true + UserOrGroupId + false + + false + + false + false + false + + + true + false + true + AssetTokenEvent + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + AssetTokenEvent + true + false + true + UserId + false + + false + + false + false + false + + + true + false + true + AssignmentRule + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + AssignmentRule + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + AssociatedLocation + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + AssociatedLocation + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + AssociatedLocationHistory + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + AsyncApexJob + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + AsyncOperationEvent + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + AsyncOperationStatus + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + AttachedContentDocument + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + AttachedContentDocument + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + true + true + AttachedContentDocument + true + false + true + LinkedEntityId + false + + false + + true + AttachedContentDocuments + false + false + + + true + false + true + Attachment + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + Attachment + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + Attachment + true + false + true + OwnerId + false + + false + + false + false + false + + + true + false + true + AuraDefinition + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + AuraDefinition + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + AuraDefinitionBundle + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + AuraDefinitionBundle + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + AuthConfig + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + AuthConfig + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + AuthConfigProviders + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + AuthConfigProviders + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + AuthProvider + true + false + true + ExecutionUserId + false + + false + + false + false + false + + + true + false + true + AuthSession + true + false + true + UsersId + false + + false + + false + false + false + + + true + false + true + AuthorizationForm + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + AuthorizationForm + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + AuthorizationForm + true + false + true + OwnerId + false + + false + + false + false + false + + + true + false + true + AuthorizationFormConsent + true + false + true + ConsentGiverId + false + + false + + true + AuthorizationFormConsents + true + true + + + true + false + true + AuthorizationFormConsent + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + AuthorizationFormConsent + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + AuthorizationFormConsent + true + false + true + OwnerId + false + + false + + false + false + false + + + true + false + true + AuthorizationFormConsentChangeEvent + true + false + true + ConsentGiverId + false + + false + + false + false + false + + + true + false + true + AuthorizationFormConsentChangeEvent + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + AuthorizationFormConsentChangeEvent + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + AuthorizationFormConsentChangeEvent + true + false + true + OwnerId + false + + false + + false + false + false + + + true + false + true + AuthorizationFormConsentHistory + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + AuthorizationFormConsentShare + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + true + true + AuthorizationFormConsentShare + true + false + true + UserOrGroupId + false + + false + + false + false + false + + + true + false + true + AuthorizationFormDataUse + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + AuthorizationFormDataUse + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + AuthorizationFormDataUse + true + false + true + OwnerId + false + + false + + false + false + false + + + true + false + true + AuthorizationFormDataUseHistory + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + AuthorizationFormDataUseShare + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + true + true + AuthorizationFormDataUseShare + true + false + true + UserOrGroupId + false + + false + + false + false + false + + + true + false + true + AuthorizationFormHistory + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + AuthorizationFormShare + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + true + true + AuthorizationFormShare + true + false + true + UserOrGroupId + false + + false + + false + false + false + + + true + false + true + AuthorizationFormText + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + AuthorizationFormText + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + AuthorizationFormTextHistory + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + BackgroundOperation + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + BackgroundOperation + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + BatchApexErrorEvent + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + BrandTemplate + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + BrandTemplate + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + BrandingSet + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + BrandingSet + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + BrandingSetProperty + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + BrandingSetProperty + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + BusinessHours + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + BusinessHours + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + BusinessProcess + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + BusinessProcess + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + Calendar + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + Calendar + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + true + true + Calendar + true + false + true + UserId + false + + false + + false + false + false + + + true + false + true + CalendarView + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + CalendarView + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + CalendarView + true + false + true + OwnerId + false + + false + + false + false + false + + + true + false + true + CalendarView + true + false + true + PublisherId + false + + false + + false + false + false + + + true + false + true + CalendarViewShare + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + true + true + CalendarViewShare + true + false + true + UserOrGroupId + false + + false + + false + false + false + + + true + false + true + CallCenter + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + CallCenter + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + CallCoachConfigModifyEvent + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + CallCoachingMediaProvider + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + CallCoachingMediaProvider + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + CallDisposition + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + CallDisposition + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + CallDispositionCategory + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + CallDispositionCategory + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + CampaignInfluenceModel + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + CampaignInfluenceModel + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + Case + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + Case + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + Case + true + false + true + OwnerId + false + + false + + false + false + false + + + true + false + true + CaseChangeEvent + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + CaseChangeEvent + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + CaseChangeEvent + true + false + true + OwnerId + false + + false + + false + false + false + + + true + false + true + CaseComment + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + CaseComment + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + CaseContactRole + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + CaseContactRole + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + CaseFeed + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + CaseFeed + true + false + true + InsertedById + false + + false + + false + false + false + + + true + false + true + CaseHistory + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + CaseShare + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + true + true + CaseShare + true + false + true + UserOrGroupId + false + + false + + false + false + false + + + true + false + true + CaseSolution + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + CaseStatus + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + CaseStatus + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + CaseSubjectParticle + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + CaseSubjectParticle + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + CaseTeamMember + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + CaseTeamMember + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + true + true + CaseTeamMember + true + false + true + MemberId + false + + false + + false + false + false + + + true + false + true + CaseTeamRole + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + CaseTeamRole + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + CaseTeamTemplate + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + CaseTeamTemplate + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + CaseTeamTemplateMember + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + CaseTeamTemplateMember + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + true + true + CaseTeamTemplateMember + true + false + true + MemberId + false + + false + + false + false + false + + + true + false + true + CaseTeamTemplateRecord + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + CategoryData + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + CategoryData + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + CategoryNode + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + CategoryNode + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + ChatterActivity + true + false + true + ParentId + false + + false + + false + false + false + + + true + false + true + ChatterExtension + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + ChatterExtension + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + ChatterExtensionConfig + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + ChatterExtensionConfig + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + true + true + ClientBrowser + true + false + true + UsersId + false + + false + + false + false + false + + + true + false + true + CollaborationGroup + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + CollaborationGroup + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + CollaborationGroup + true + false + true + OwnerId + false + + false + + false + false + false + + + true + false + true + CollaborationGroupFeed + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + CollaborationGroupFeed + true + false + true + InsertedById + false + + false + + false + false + false + + + true + false + true + CollaborationGroupMember + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + CollaborationGroupMember + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + true + true + CollaborationGroupMember + true + false + true + MemberId + false + + false + + true + GroupMemberships + false + false + + + true + false + true + CollaborationGroupMemberRequest + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + CollaborationGroupMemberRequest + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + true + true + CollaborationGroupMemberRequest + true + false + true + RequesterId + false + + false + + true + GroupMembershipRequests + false + false + + + true + false + true + CollaborationGroupRecord + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + CollaborationGroupRecord + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + true + true + CollaborationInvitation + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + CollaborationInvitation + true + false + true + InviterId + false + + false + + false + false + false + + + true + false + true + CollaborationInvitation + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + true + true + CollaborationInvitation + true + false + true + SharedEntityId + false + + false + + false + false + false + + + true + false + true + CombinedAttachment + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + CombinedAttachment + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + true + true + CombinedAttachment + true + false + true + ParentId + false + + false + + true + CombinedAttachments + false + false + + + true + false + true + CommSubscription + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + CommSubscription + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + CommSubscription + true + false + true + OwnerId + false + + false + + false + false + false + + + true + false + true + CommSubscriptionChannelType + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + CommSubscriptionChannelType + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + CommSubscriptionChannelType + true + false + true + OwnerId + false + + false + + false + false + false + + + true + false + true + CommSubscriptionChannelTypeFeed + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + CommSubscriptionChannelTypeFeed + true + false + true + InsertedById + false + + false + + false + false + false + + + true + false + true + CommSubscriptionChannelTypeHistory + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + CommSubscriptionChannelTypeShare + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + true + true + CommSubscriptionChannelTypeShare + true + false + true + UserOrGroupId + false + + false + + false + false + false + + + true + false + true + CommSubscriptionConsent + true + false + true + ConsentGiverId + false + + false + + true + CommSubscriptionConsents + true + true + + + true + false + true + CommSubscriptionConsent + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + CommSubscriptionConsent + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + CommSubscriptionConsent + true + false + true + OwnerId + false + + false + + false + false + false + + + true + false + true + CommSubscriptionConsentChangeEvent + true + false + true + ConsentGiverId + false + + false + + false + false + false + + + true + false + true + CommSubscriptionConsentChangeEvent + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + CommSubscriptionConsentChangeEvent + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + CommSubscriptionConsentChangeEvent + true + false + true + OwnerId + false + + false + + false + false + false + + + true + false + true + CommSubscriptionConsentFeed + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + CommSubscriptionConsentFeed + true + false + true + InsertedById + false + + false + + false + false + false + + + true + false + true + CommSubscriptionConsentHistory + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + CommSubscriptionConsentShare + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + true + true + CommSubscriptionConsentShare + true + false + true + UserOrGroupId + false + + false + + false + false + false + + + true + false + true + CommSubscriptionFeed + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + CommSubscriptionFeed + true + false + true + InsertedById + false + + false + + false + false + false + + + true + false + true + CommSubscriptionHistory + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + CommSubscriptionShare + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + true + true + CommSubscriptionShare + true + false + true + UserOrGroupId + false + + false + + false + false + false + + + true + false + true + CommSubscriptionTiming + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + CommSubscriptionTiming + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + CommSubscriptionTimingFeed + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + CommSubscriptionTimingFeed + true + false + true + InsertedById + false + + false + + false + false + false + + + true + false + true + CommSubscriptionTimingHistory + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + Community + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + Community + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + ConferenceNumber + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + ConferenceNumber + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + ConnectedApplication + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + ConnectedApplication + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + Contact + true + false + true + ActionCadenceAssigneeId + false + + false + + false + false + false + + + true + false + true + Contact + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + Contact + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + Contact + true + false + true + OwnerId + false + + false + + false + false + false + + + true + false + true + ContactChangeEvent + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + ContactChangeEvent + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + ContactChangeEvent + true + false + true + OwnerId + false + + false + + false + false + false + + + true + false + true + ContactFeed + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + ContactFeed + true + false + true + InsertedById + false + + false + + false + false + false + + + true + false + true + ContactHistory + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + ContactPointAddress + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + ContactPointAddress + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + ContactPointAddress + true + false + true + OwnerId + false + + false + + false + false + false + + + true + false + true + ContactPointAddressChangeEvent + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + ContactPointAddressChangeEvent + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + ContactPointAddressChangeEvent + true + false + true + OwnerId + false + + false + + false + false + false + + + true + false + true + ContactPointAddressHistory + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + ContactPointAddressShare + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + true + true + ContactPointAddressShare + true + false + true + UserOrGroupId + false + + false + + false + false + false + + + true + false + true + ContactPointConsent + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + ContactPointConsent + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + ContactPointConsent + true + false + true + OwnerId + false + + false + + false + false + false + + + true + false + true + ContactPointConsentChangeEvent + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + ContactPointConsentChangeEvent + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + ContactPointConsentChangeEvent + true + false + true + OwnerId + false + + false + + false + false + false + + + true + false + true + ContactPointConsentHistory + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + ContactPointConsentShare + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + true + true + ContactPointConsentShare + true + false + true + UserOrGroupId + false + + false + + false + false + false + + + true + false + true + ContactPointEmail + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + ContactPointEmail + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + ContactPointEmail + true + false + true + OwnerId + false + + false + + false + false + false + + + true + false + true + ContactPointEmailChangeEvent + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + ContactPointEmailChangeEvent + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + ContactPointEmailChangeEvent + true + false + true + OwnerId + false + + false + + false + false + false + + + true + false + true + ContactPointEmailHistory + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + ContactPointEmailShare + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + true + true + ContactPointEmailShare + true + false + true + UserOrGroupId + false + + false + + false + false + false + + + true + false + true + ContactPointPhone + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + ContactPointPhone + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + ContactPointPhone + true + false + true + OwnerId + false + + false + + false + false + false + + + true + false + true + ContactPointPhoneChangeEvent + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + ContactPointPhoneChangeEvent + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + ContactPointPhoneChangeEvent + true + false + true + OwnerId + false + + false + + false + false + false + + + true + false + true + ContactPointPhoneHistory + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + ContactPointPhoneShare + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + true + true + ContactPointPhoneShare + true + false + true + UserOrGroupId + false + + false + + false + false + false + + + true + false + true + ContactPointTypeConsent + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + ContactPointTypeConsent + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + ContactPointTypeConsent + true + false + true + OwnerId + false + + false + + false + false + false + + + true + false + true + ContactPointTypeConsentChangeEvent + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + ContactPointTypeConsentChangeEvent + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + ContactPointTypeConsentChangeEvent + true + false + true + OwnerId + false + + false + + false + false + false + + + true + false + true + ContactPointTypeConsentHistory + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + ContactPointTypeConsentShare + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + true + true + ContactPointTypeConsentShare + true + false + true + UserOrGroupId + false + + false + + false + false + false + + + true + false + true + ContactRequest + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + ContactRequest + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + ContactRequest + true + false + true + OwnerId + false + + false + + false + false + false + + + true + false + true + ContactRequest + true + false + true + WhoId + false + + false + + true + ContactRequests + false + false + + + true + false + true + ContactRequestShare + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + true + true + ContactRequestShare + true + false + true + UserOrGroupId + false + + false + + false + false + false + + + true + false + true + ContactShare + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + true + true + ContactShare + true + false + true + UserOrGroupId + false + + false + + false + false + false + + + true + false + true + ContentAsset + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + ContentAsset + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + ContentDistribution + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + ContentDistribution + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + true + true + ContentDistribution + true + false + true + OwnerId + false + + false + + false + false + false + + + true + false + true + ContentDistributionView + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + ContentDocument + true + false + true + ArchivedById + false + + false + + false + false + false + + + true + false + true + ContentDocument + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + ContentDocument + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + ContentDocument + true + false + true + OwnerId + false + + false + + false + false + false + + + true + false + true + ContentDocumentFeed + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + ContentDocumentFeed + true + false + true + InsertedById + false + + false + + false + false + false + + + true + false + true + ContentDocumentHistory + true + false + true + CreatedById + false + + false + + false + false + false + + + true + true + true + ContentDocumentLink + true + false + true + LinkedEntityId + false + + false + + true + ContentDocumentLinks + false + false + + + true + true + true + ContentDocumentSubscription + true + false + true + UserId + false + + false + + false + false + false + + + true + false + true + ContentFolder + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + ContentFolder + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + ContentFolderItem + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + ContentFolderItem + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + ContentFolderMember + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + ContentFolderMember + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + ContentNotification + true + false + true + EntityIdentifierId + false + + false + + false + false + false + + + true + true + true + ContentNotification + true + false + true + UsersId + false + + false + + false + false + false + + + true + true + true + ContentTagSubscription + true + false + true + UserId + false + + false + + false + false + false + + + true + true + true + ContentUserSubscription + true + false + true + SubscribedToUserId + false + + false + + false + false + false + + + true + true + true + ContentUserSubscription + true + false + true + SubscriberUserId + false + + false + + false + false + false + + + true + false + true + ContentVersion + true + false + true + ContentModifiedById + false + + false + + false + false + false + + + true + false + true + ContentVersion + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + ContentVersion + true + false + true + FirstPublishLocationId + false + + false + + false + false + false + + + true + false + true + ContentVersion + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + ContentVersion + true + false + true + OwnerId + false + + false + + false + false + false + + + true + false + true + ContentVersionHistory + true + false + true + CreatedById + false + + false + + false + false + false + + + true + true + true + ContentVersionRating + true + false + true + UserId + false + + false + + false + false + false + + + true + false + true + ContentWorkspace + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + ContentWorkspace + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + ContentWorkspaceMember + true + false + true + CreatedById + false + + false + + false + false + false + + + true + true + true + ContentWorkspaceMember + true + false + true + MemberId + false + + false + + false + false + false + + + true + false + true + ContentWorkspacePermission + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + ContentWorkspacePermission + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + true + true + ContentWorkspaceSubscription + true + false + true + UserId + false + + false + + false + false + false + + + true + false + true + Contract + true + false + true + ActivatedById + false + + false + + false + false + false + + + true + false + true + Contract + true + false + true + CompanySignedId + false + + false + + true + ContractsSigned + false + false + + + true + false + true + Contract + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + Contract + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + Contract + true + false + true + OwnerId + false + + false + + false + false + false + + + true + false + true + ContractChangeEvent + true + false + true + ActivatedById + false + + false + + false + false + false + + + true + false + true + ContractChangeEvent + true + false + true + CompanySignedId + false + + false + + false + false + false + + + true + false + true + ContractChangeEvent + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + ContractChangeEvent + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + ContractChangeEvent + true + false + true + OwnerId + false + + false + + false + false + false + + + true + false + true + ContractContactRole + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + ContractContactRole + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + ContractFeed + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + ContractFeed + true + false + true + InsertedById + false + + false + + false + false + false + + + true + false + true + ContractHistory + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + ContractStatus + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + ContractStatus + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + ConversationChannelResponse + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + ConversationChannelResponse + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + CorsWhitelistEntry + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + CorsWhitelistEntry + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + CronTrigger + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + CronTrigger + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + CronTrigger + true + false + true + OwnerId + false + + false + + false + false + false + + + true + false + true + CspTrustedSite + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + CspTrustedSite + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + CustomBrand + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + CustomBrand + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + CustomBrandAsset + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + CustomBrandAsset + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + CustomHelpMenuItem + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + CustomHelpMenuItem + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + CustomHelpMenuSection + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + CustomHelpMenuSection + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + CustomHttpHeader + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + CustomHttpHeader + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + CustomNotificationType + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + CustomNotificationType + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + CustomPermission + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + CustomPermission + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + CustomPermissionDependency + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + CustomPermissionDependency + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + Dashboard + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + Dashboard + true + false + true + FolderId + false + + false + + false + false + false + + + true + false + true + Dashboard + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + Dashboard + true + false + true + RunningUserId + false + + false + + false + false + false + + + true + false + true + DashboardComponentFeed + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + DashboardComponentFeed + true + false + true + InsertedById + false + + false + + false + false + false + + + true + false + true + DashboardFeed + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + DashboardFeed + true + false + true + InsertedById + false + + false + + false + false + false + + + true + false + true + DataAssessmentFieldMetric + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + DataAssessmentFieldMetric + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + DataAssessmentMetric + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + DataAssessmentMetric + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + DataAssessmentValueMetric + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + DataAssessmentValueMetric + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + DataClassification + true + false + true + BusinessOwnerId + false + + false + + false + false + false + + + true + false + true + DataClassification + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + DataClassification + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + DataIntegrationRecordPurchasePermission + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + DataIntegrationRecordPurchasePermission + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + true + true + DataIntegrationRecordPurchasePermission + true + false + true + UserId + false + + false + + false + false + false + + + true + false + true + DataStatistics + true + false + true + UserId + false + + false + + false + false + false + + + true + false + true + DataUseLegalBasis + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + DataUseLegalBasis + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + DataUseLegalBasis + true + false + true + OwnerId + false + + false + + false + false + false + + + true + false + true + DataUseLegalBasisHistory + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + DataUseLegalBasisShare + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + true + true + DataUseLegalBasisShare + true + false + true + UserOrGroupId + false + + false + + false + false + false + + + true + false + true + DataUsePurpose + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + DataUsePurpose + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + DataUsePurpose + true + false + true + OwnerId + false + + false + + false + false + false + + + true + false + true + DataUsePurposeHistory + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + DataUsePurposeShare + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + true + true + DataUsePurposeShare + true + false + true + UserOrGroupId + false + + false + + false + false + false + + + true + false + true + DeclinedEventRelation + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + DeclinedEventRelation + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + DeclinedEventRelation + true + false + true + RelationId + false + + false + + true + DeclinedEventRelations + false + false + + + true + false + true + DeleteEvent + true + false + true + DeletedById + false + + false + + false + false + false + + + true + false + true + DialerCallUsage + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + DialerCallUsage + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + DialerCallUsage + true + false + true + OwnerId + false + + false + + false + false + false + + + true + false + true + DialerCallUsageShare + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + true + true + DialerCallUsageShare + true + false + true + UserOrGroupId + false + + false + + false + false + false + + + true + false + true + Document + true + false + true + AuthorId + false + + false + + false + false + false + + + true + false + true + Document + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + Document + true + false + true + FolderId + false + + false + + false + false + false + + + true + false + true + Document + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + DocumentAttachmentMap + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + Domain + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + Domain + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + DomainSite + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + DomainSite + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + DuplicateRecordItem + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + DuplicateRecordItem + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + DuplicateRecordSet + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + DuplicateRecordSet + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + DuplicateRule + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + DuplicateRule + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + EmailCapture + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + EmailCapture + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + EmailDomainFilter + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + EmailDomainFilter + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + EmailDomainKey + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + EmailDomainKey + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + EmailMessage + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + EmailMessage + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + EmailMessageChangeEvent + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + EmailMessageChangeEvent + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + EmailMessageRelation + true + false + true + CreatedById + false + + false + + false + false + false + + + true + true + true + EmailMessageRelation + true + false + true + RelationId + false + + false + + true + EmailMessageRelations + false + false + + + true + false + true + EmailRelay + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + EmailRelay + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + EmailServicesAddress + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + EmailServicesAddress + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + EmailServicesAddress + true + false + true + RunAsUserId + false + + false + + false + false + false + + + true + false + true + EmailServicesFunction + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + EmailServicesFunction + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + EmailStatus + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + EmailStatus + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + EmailTemplate + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + EmailTemplate + true + false + true + FolderId + false + + false + + false + false + false + + + true + false + true + EmailTemplate + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + EmailTemplate + true + false + true + OwnerId + false + + false + + false + false + false + + + true + false + true + EmailTemplateChangeEvent + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + EmailTemplateChangeEvent + true + false + true + FolderId + false + + false + + false + false + false + + + true + false + true + EmailTemplateChangeEvent + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + EmailTemplateChangeEvent + true + false + true + OwnerId + false + + false + + false + false + false + + + true + false + true + EngagementChannelType + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + EngagementChannelType + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + EngagementChannelType + true + false + true + OwnerId + false + + false + + false + false + false + + + true + false + true + EngagementChannelTypeFeed + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + EngagementChannelTypeFeed + true + false + true + InsertedById + false + + false + + false + false + false + + + true + false + true + EngagementChannelTypeHistory + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + EngagementChannelTypeShare + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + true + true + EngagementChannelTypeShare + true + false + true + UserOrGroupId + false + + false + + false + false + false + + + true + false + true + EnhancedLetterhead + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + EnhancedLetterhead + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + EnhancedLetterheadFeed + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + EnhancedLetterheadFeed + true + false + true + InsertedById + false + + false + + false + false + false + + + true + false + true + EntityDefinition + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + true + true + EntitySubscription + true + false + true + CreatedById + false + + false + + false + false + false + + + true + true + true + EntitySubscription + true + false + true + ParentId + false + + false + + true + FeedSubscriptionsForEntity + false + false + + + true + true + true + EntitySubscription + true + false + true + SubscriberId + false + + false + + true + FeedSubscriptions + false + false + + + true + false + true + Event + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + Event + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + Event + true + false + true + OwnerId + false + + false + + false + false + false + + + true + false + true + EventChangeEvent + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + EventChangeEvent + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + EventChangeEvent + true + false + true + OwnerId + false + + false + + false + false + false + + + true + false + true + EventFeed + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + EventFeed + true + false + true + InsertedById + false + + false + + false + false + false + + + true + false + true + EventLogFile + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + EventLogFile + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + EventRelation + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + EventRelation + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + true + true + EventRelation + true + false + true + RelationId + false + + false + + true + EventRelations + false + false + + + true + false + true + EventRelationChangeEvent + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + EventRelationChangeEvent + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + EventRelationChangeEvent + true + false + true + RelationId + false + + false + + false + false + false + + + true + false + true + ExternalDataSource + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + ExternalDataSource + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + ExternalDataUserAuth + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + ExternalDataUserAuth + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + ExternalDataUserAuth + true + false + true + UserId + false + + false + + true + ExternalDataUserAuths + false + false + + + true + false + true + ExternalEvent + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + ExternalEvent + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + ExternalEventMapping + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + ExternalEventMapping + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + ExternalEventMapping + true + false + true + OwnerId + false + + false + + false + false + false + + + true + false + true + ExternalEventMappingShare + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + true + true + ExternalEventMappingShare + true + false + true + UserOrGroupId + false + + false + + false + false + false + + + true + false + true + ExternalSocialAccount + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + ExternalSocialAccount + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + true + true + FeedComment + true + false + true + CreatedById + false + + false + + false + false + false + + + true + true + true + FeedComment + true + false + true + InsertedById + false + + false + + false + false + false + + + true + false + true + FeedComment + true + false + true + LastEditById + false + + false + + false + false + false + + + true + false + true + FeedComment + true + false + true + ParentId + false + + false + + false + false + false + + + true + true + true + FeedItem + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + FeedItem + true + false + true + InsertedById + false + + false + + false + false + false + + + true + false + true + FeedItem + true + false + true + LastEditById + false + + false + + false + false + false + + + true + true + true + FeedItem + true + false + true + ParentId + false + + false + + false + false + false + + + true + true + true + FeedLike + true + false + true + CreatedById + false + + false + + false + false + false + + + true + true + true + FeedLike + true + false + true + InsertedById + false + + false + + false + false + false + + + true + false + true + FeedPollChoice + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + FeedPollVote + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + FeedRevision + true + false + true + CreatedById + false + + false + + false + false + false + + + true + true + true + FeedSignal + true + false + true + CreatedById + false + + false + + false + false + false + + + true + true + true + FeedSignal + true + false + true + InsertedById + false + + false + + false + false + false + + + true + false + true + FieldDefinition + true + false + true + BusinessOwnerId + false + + false + + false + false + false + + + true + false + true + FieldDefinition + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + FieldSecurityClassification + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + FieldSecurityClassification + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + FileSearchActivity + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + FileSearchActivity + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + FlowExecutionErrorEvent + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + FlowExecutionErrorEvent + true + false + true + InterviewStartedById + false + + false + + false + false + false + + + true + false + true + FlowExecutionErrorEvent + true + false + true + UserId + false + + false + + false + false + false + + + true + false + true + FlowInterview + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + FlowInterview + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + FlowInterview + true + false + true + OwnerId + false + + false + + false + false + false + + + true + false + true + FlowInterviewLog + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + FlowInterviewLog + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + FlowInterviewLog + true + false + true + OwnerId + false + + false + + false + false + false + + + true + false + true + FlowInterviewLogEntry + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + FlowInterviewLogEntry + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + FlowInterviewLogShare + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + true + true + FlowInterviewLogShare + true + false + true + UserOrGroupId + false + + false + + false + false + false + + + true + false + true + FlowInterviewShare + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + true + true + FlowInterviewShare + true + false + true + UserOrGroupId + false + + false + + false + false + false + + + true + false + true + FlowRecordRelation + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + FlowRecordRelation + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + FlowStageRelation + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + FlowStageRelation + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + Folder + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + Folder + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + FolderedContentDocument + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + FolderedContentDocument + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + GrantedByLicense + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + GrantedByLicense + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + Group + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + Group + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + Group + true + false + true + OwnerId + false + + false + + false + false + false + + + true + false + true + Group + true + false + true + RelatedId + false + + false + + false + false + false + + + true + true + true + GroupMember + true + false + true + UserOrGroupId + false + + false + + false + false + false + + + true + false + true + Holiday + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + Holiday + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + Idea + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + Idea + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + IdeaComment + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + IdpEventLog + true + false + true + UserId + false + + false + + false + false + false + + + true + false + true + IframeWhiteListUrl + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + IframeWhiteListUrl + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + Image + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + Image + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + Image + true + false + true + OwnerId + false + + false + + false + false + false + + + true + false + true + ImageFeed + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + ImageFeed + true + false + true + InsertedById + false + + false + + false + false + false + + + true + false + true + ImageHistory + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + ImageShare + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + true + true + ImageShare + true + false + true + UserOrGroupId + false + + false + + false + false + false + + + true + false + true + Individual + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + Individual + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + true + true + Individual + true + false + true + OwnerId + false + + false + + false + false + false + + + true + false + true + IndividualChangeEvent + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + IndividualChangeEvent + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + IndividualChangeEvent + true + false + true + OwnerId + false + + false + + false + false + false + + + true + false + true + IndividualHistory + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + IndividualShare + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + true + true + IndividualShare + true + false + true + UserOrGroupId + false + + false + + false + false + false + + + true + false + true + InstalledMobileApp + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + InstalledMobileApp + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + true + true + InstalledMobileApp + true + false + true + UserId + false + + false + + true + InstalledMobileApps + false + false + + + true + false + true + KnowledgeableUser + true + false + true + UserId + false + + false + + false + false + false + + + true + false + true + Lead + true + false + true + ActionCadenceAssigneeId + false + + false + + false + false + false + + + true + false + true + Lead + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + Lead + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + Lead + true + false + true + OwnerId + false + + false + + false + false + false + + + true + false + true + LeadChangeEvent + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + LeadChangeEvent + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + LeadChangeEvent + true + false + true + OwnerId + false + + false + + false + false + false + + + true + false + true + LeadFeed + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + LeadFeed + true + false + true + InsertedById + false + + false + + false + false + false + + + true + false + true + LeadHistory + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + LeadShare + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + true + true + LeadShare + true + false + true + UserOrGroupId + false + + false + + false + false + false + + + true + false + true + LeadStatus + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + LeadStatus + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + true + true + LightningExitByPageMetrics + true + false + true + UserId + false + + false + + false + false + false + + + true + false + true + LightningExperienceTheme + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + LightningExperienceTheme + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + LightningOnboardingConfig + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + LightningOnboardingConfig + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + true + true + LightningToggleMetrics + true + false + true + UserId + false + + false + + false + false + false + + + true + true + true + LightningUsageByAppTypeMetrics + true + false + true + UserId + false + + false + + false + false + false + + + true + true + true + LightningUsageByPageMetrics + true + false + true + UserId + false + + false + + false + false + false + + + true + false + true + ListEmail + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + ListEmail + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + ListEmail + true + false + true + OwnerId + false + + false + + false + false + false + + + true + false + true + ListEmailChangeEvent + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + ListEmailChangeEvent + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + ListEmailChangeEvent + true + false + true + OwnerId + false + + false + + false + false + false + + + true + false + true + ListEmailIndividualRecipient + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + ListEmailIndividualRecipient + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + ListEmailRecipientSource + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + ListEmailRecipientSource + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + ListEmailShare + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + true + true + ListEmailShare + true + false + true + UserOrGroupId + false + + false + + false + false + false + + + true + false + true + ListView + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + ListView + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + ListViewChart + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + ListViewChart + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + true + true + ListViewChart + true + false + true + OwnerId + false + + false + + false + false + false + + + true + false + true + Location + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + Location + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + Location + true + false + true + OwnerId + false + + false + + false + false + false + + + true + false + true + LocationChangeEvent + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + LocationChangeEvent + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + LocationChangeEvent + true + false + true + OwnerId + false + + false + + false + false + false + + + true + false + true + LocationFeed + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + LocationFeed + true + false + true + InsertedById + false + + false + + false + false + false + + + true + false + true + LocationHistory + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + LocationShare + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + true + true + LocationShare + true + false + true + UserOrGroupId + false + + false + + false + false + false + + + true + false + true + LocationTrustMeasure + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + LocationTrustMeasure + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + LocationTrustMeasure + true + false + true + OwnerId + false + + false + + false + false + false + + + true + false + true + LocationTrustMeasureShare + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + true + true + LocationTrustMeasureShare + true + false + true + UserOrGroupId + false + + false + + false + false + false + + + true + false + true + LoginGeo + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + LoginGeo + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + true + true + LoginHistory + true + false + true + UserId + false + + false + + false + false + false + + + true + true + true + LoginIp + true + false + true + UsersId + false + + false + + false + false + false + + + true + false + true + LogoutEventStream + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + LogoutEventStream + true + false + true + UserId + false + + false + + false + false + false + + + true + false + true + MLDataDefinition + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + MLDataDefinition + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + MLField + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + MLField + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + MLFilter + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + MLFilter + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + MLPredictionDefinition + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + MLPredictionDefinition + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + MailmergeTemplate + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + MailmergeTemplate + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + MatchingInformation + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + MatchingInformation + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + true + true + MatchingInformation + true + false + true + UserId + false + + false + + false + false + false + + + true + false + true + MatchingRule + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + MatchingRule + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + MatchingRuleItem + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + MatchingRuleItem + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + MedicationRequest + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + MedicationRequest + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + MedicationRequestFeed + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + MedicationRequestFeed + true + false + true + InsertedById + false + + false + + false + false + false + + + true + false + true + MedicationRequestHistory + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + MessagingChannel + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + MessagingChannel + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + MobileApplicationDetail + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + MobileApplicationDetail + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + MsgChannelLanguageKeyword + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + MsgChannelLanguageKeyword + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + MutingPermissionSet + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + MutingPermissionSet + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + MyDomainDiscoverableLogin + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + MyDomainDiscoverableLogin + true + false + true + ExecuteApexHandlerAsId + false + + false + + false + true + true + + + true + false + true + MyDomainDiscoverableLogin + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + NamedCredential + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + NamedCredential + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + Note + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + Note + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + Note + true + false + true + OwnerId + false + + false + + false + false + false + + + true + false + true + NoteAndAttachment + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + NoteAndAttachment + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + NoteAndAttachment + true + false + true + OwnerId + false + + false + + false + false + false + + + true + false + true + OauthCustomScope + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + OauthCustomScope + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + OauthCustomScopeApp + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + OauthCustomScopeApp + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + OauthToken + true + false + true + UserId + false + + false + + false + false + false + + + true + false + true + ObjectPermissions + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + ObjectPermissions + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + OnboardingMetrics + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + OnboardingMetrics + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + true + true + OnboardingMetrics + true + false + true + UserId + false + + false + + false + false + false + + + true + false + true + OpenActivity + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + OpenActivity + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + OpenActivity + true + false + true + OwnerId + false + + false + + false + false + false + + + true + false + true + Opportunity + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + Opportunity + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + Opportunity + true + false + true + OwnerId + false + + false + + false + false + false + + + true + false + true + OpportunityChangeEvent + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + OpportunityChangeEvent + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + OpportunityChangeEvent + true + false + true + OwnerId + false + + false + + false + false + false + + + true + false + true + OpportunityCompetitor + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + OpportunityCompetitor + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + OpportunityContactRole + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + OpportunityContactRole + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + OpportunityContactRoleChangeEvent + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + OpportunityContactRoleChangeEvent + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + OpportunityFeed + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + OpportunityFeed + true + false + true + InsertedById + false + + false + + false + false + false + + + true + false + true + OpportunityFieldHistory + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + OpportunityHistory + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + OpportunityLineItem + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + OpportunityLineItem + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + OpportunityPartner + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + OpportunityPartner + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + OpportunityShare + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + true + true + OpportunityShare + true + false + true + UserOrGroupId + false + + false + + false + false + false + + + true + false + true + OpportunityStage + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + OpportunityStage + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + Order + true + false + true + ActivatedById + false + + false + + false + false + false + + + true + false + true + Order + true + false + true + CompanyAuthorizedById + false + + false + + false + false + false + + + true + false + true + Order + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + Order + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + Order + true + false + true + OwnerId + false + + false + + false + false + false + + + true + false + true + OrderChangeEvent + true + false + true + ActivatedById + false + + false + + false + false + false + + + true + false + true + OrderChangeEvent + true + false + true + CompanyAuthorizedById + false + + false + + false + false + false + + + true + false + true + OrderChangeEvent + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + OrderChangeEvent + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + OrderChangeEvent + true + false + true + OwnerId + false + + false + + false + false + false + + + true + false + true + OrderFeed + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + OrderFeed + true + false + true + InsertedById + false + + false + + false + false + false + + + true + false + true + OrderHistory + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + OrderItem + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + OrderItem + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + OrderItemChangeEvent + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + OrderItemChangeEvent + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + OrderItemFeed + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + OrderItemFeed + true + false + true + InsertedById + false + + false + + false + false + false + + + true + false + true + OrderItemHistory + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + OrderShare + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + true + true + OrderShare + true + false + true + UserOrGroupId + false + + false + + false + false + false + + + true + false + true + OrderStatus + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + OrderStatus + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + OrgLifecycleNotification + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + OrgMetric + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + OrgMetric + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + OrgMetricScanResult + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + OrgMetricScanResult + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + OrgMetricScanSummary + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + OrgMetricScanSummary + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + OrgWideEmailAddress + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + OrgWideEmailAddress + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + Organization + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + Organization + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + OutgoingEmailRelation + true + false + true + RelationId + false + + false + + true + OutgoingEmailRelations + false + false + + + true + false + true + OwnedContentDocument + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + OwnedContentDocument + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + true + true + OwnedContentDocument + true + false + true + OwnerId + false + + false + + true + OwnedContentDocuments + false + false + + + true + false + true + Partner + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + Partner + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + PartnerRole + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + PartnerRole + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + PartyConsent + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + PartyConsent + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + PartyConsent + true + false + true + OwnerId + false + + false + + false + false + false + + + true + false + true + PartyConsentChangeEvent + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + PartyConsentChangeEvent + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + PartyConsentChangeEvent + true + false + true + OwnerId + false + + false + + false + false + false + + + true + false + true + PartyConsentFeed + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + PartyConsentFeed + true + false + true + InsertedById + false + + false + + false + false + false + + + true + false + true + PartyConsentHistory + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + PartyConsentShare + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + true + true + PartyConsentShare + true + false + true + UserOrGroupId + false + + false + + false + false + false + + + true + false + true + PermissionSet + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + PermissionSet + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + true + true + PermissionSetAssignment + true + false + true + AssigneeId + false + + false + + true + PermissionSetAssignments + false + false + + + true + false + true + PermissionSetGroup + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + PermissionSetGroup + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + PermissionSetGroupComponent + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + PermissionSetGroupComponent + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + PermissionSetLicense + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + PermissionSetLicense + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + true + true + PermissionSetLicenseAssign + true + false + true + AssigneeId + false + + false + + true + PermissionSetLicenseAssignments + false + false + + + true + false + true + PermissionSetLicenseAssign + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + PermissionSetLicenseAssign + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + PlatformAction + true + false + true + InvokedByUserId + false + + false + + false + false + false + + + true + false + true + PlatformCachePartition + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + PlatformCachePartition + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + PlatformCachePartitionType + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + PlatformCachePartitionType + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + PlatformEventSubscriberConfig + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + PlatformEventSubscriberConfig + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + PlatformEventSubscriberConfig + true + false + true + UserId + false + + false + + false + false + false + + + true + false + true + PlatformStatusAlertEvent + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + PlatformStatusAlertEvent + true + false + true + UserId + false + + false + + false + false + false + + + true + false + true + Pricebook2 + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + Pricebook2 + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + Pricebook2ChangeEvent + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + Pricebook2ChangeEvent + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + Pricebook2History + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + PricebookEntry + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + PricebookEntry + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + PricebookEntryHistory + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + ProcessDefinition + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + ProcessDefinition + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + ProcessInstance + true + false + true + CreatedById + false + + false + + false + false + false + + + true + true + true + ProcessInstance + true + false + true + LastActorId + false + + false + + false + false + false + + + true + false + true + ProcessInstance + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + true + true + ProcessInstance + true + false + true + SubmittedById + false + + false + + false + false + false + + + true + false + true + ProcessInstanceHistory + true + false + true + ActorId + false + + false + + false + false + false + + + true + false + true + ProcessInstanceHistory + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + ProcessInstanceHistory + true + false + true + OriginalActorId + false + + false + + false + false + false + + + true + false + true + ProcessInstanceNode + true + false + true + CreatedById + false + + false + + false + false + false + + + true + true + true + ProcessInstanceNode + true + false + true + LastActorId + false + + false + + false + false + false + + + true + false + true + ProcessInstanceNode + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + true + true + ProcessInstanceStep + true + false + true + ActorId + false + + false + + false + false + false + + + true + false + true + ProcessInstanceStep + true + false + true + CreatedById + false + + false + + false + false + false + + + true + true + true + ProcessInstanceStep + true + false + true + OriginalActorId + false + + false + + false + false + false + + + true + false + true + ProcessInstanceWorkitem + true + false + true + ActorId + false + + false + + false + false + false + + + true + false + true + ProcessInstanceWorkitem + true + false + true + CreatedById + false + + false + + false + false + false + + + true + true + true + ProcessInstanceWorkitem + true + false + true + OriginalActorId + false + + false + + false + false + false + + + true + false + true + Product2 + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + Product2 + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + Product2ChangeEvent + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + Product2ChangeEvent + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + Product2Feed + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + Product2Feed + true + false + true + InsertedById + false + + false + + false + false + false + + + true + false + true + Product2History + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + Profile + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + Profile + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + ProfileSkill + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + ProfileSkill + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + ProfileSkill + true + false + true + OwnerId + false + + false + + false + false + false + + + true + false + true + ProfileSkillEndorsement + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + ProfileSkillEndorsement + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + true + true + ProfileSkillEndorsement + true + false + true + UserId + false + + false + + true + UserProfileSkillUserEndorsements + false + false + + + true + false + true + ProfileSkillEndorsementFeed + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + ProfileSkillEndorsementFeed + true + false + true + InsertedById + false + + false + + false + false + false + + + true + false + true + ProfileSkillEndorsementHistory + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + ProfileSkillFeed + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + ProfileSkillFeed + true + false + true + InsertedById + false + + false + + false + false + false + + + true + false + true + ProfileSkillHistory + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + ProfileSkillShare + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + true + true + ProfileSkillShare + true + false + true + UserOrGroupId + false + + false + + false + false + false + + + true + false + true + ProfileSkillUser + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + ProfileSkillUser + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + true + true + ProfileSkillUser + true + false + true + UserId + false + + false + + true + UserProfileSkillChildren + false + false + + + true + false + true + ProfileSkillUserFeed + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + ProfileSkillUserFeed + true + false + true + InsertedById + false + + false + + false + false + false + + + true + false + true + ProfileSkillUserHistory + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + Prompt + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + Prompt + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + PromptAction + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + PromptAction + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + PromptAction + true + false + true + OwnerId + false + + false + + false + false + false + + + true + true + true + PromptAction + true + false + true + UserId + false + + false + + false + false + false + + + true + false + true + PromptActionShare + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + true + true + PromptActionShare + true + false + true + UserOrGroupId + false + + false + + false + false + false + + + true + false + true + PromptVersion + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + PromptVersion + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + PromptVersion + true + false + true + PublishedByUserId + false + + false + + false + false + false + + + true + false + true + PublishStatusDetail + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + PublishStatusEvent + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + PushTopic + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + PushTopic + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + QueueSobject + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + QuickText + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + QuickText + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + QuickText + true + false + true + OwnerId + false + + false + + false + false + false + + + true + false + true + QuickTextChangeEvent + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + QuickTextChangeEvent + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + QuickTextChangeEvent + true + false + true + OwnerId + false + + false + + false + false + false + + + true + false + true + QuickTextHistory + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + QuickTextShare + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + true + true + QuickTextShare + true + false + true + UserOrGroupId + false + + false + + false + false + false + + + true + false + true + QuickTextUsage + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + QuickTextUsage + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + QuickTextUsage + true + false + true + OwnerId + false + + false + + false + false + false + + + true + false + true + QuickTextUsage + true + false + true + UserId + false + + false + + false + false + false + + + true + false + true + QuickTextUsageShare + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + true + true + QuickTextUsageShare + true + false + true + UserOrGroupId + false + + false + + false + false + false + + + true + false + true + RecentChangeSignal + true + false + true + ValueChangedById + false + + false + + false + false + false + + + true + false + true + Recommendation + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + Recommendation + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + RecommendationChangeEvent + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + RecommendationChangeEvent + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + RecordAction + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + RecordAction + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + true + true + RecordAction + true + false + true + RecordId + false + + false + + true + RecordActions + false + false + + + true + false + true + RecordActionHistory + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + RecordActionHistory + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + RecordActionHistory + true + false + true + ParentRecordId + false + + false + + true + RecordActionHistories + false + false + + + true + false + true + RecordActionHistory + true + false + true + UserId + false + + false + + false + false + false + + + true + false + true + RecordType + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + RecordType + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + RedirectWhitelistUrl + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + RedirectWhitelistUrl + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + Report + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + Report + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + Report + true + false + true + OwnerId + false + + false + + false + false + false + + + true + false + true + ReportFeed + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + ReportFeed + true + false + true + InsertedById + false + + false + + false + false + false + + + true + false + true + SalesWorkQueueSettings + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + SalesWorkQueueSettings + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + SamlSsoConfig + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + SamlSsoConfig + true + false + true + ExecutionUserId + false + + false + + false + false + false + + + true + false + true + SamlSsoConfig + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + Scontrol + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + Scontrol + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + SearchLayout + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + SecureAgentsCluster + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + SecureAgentsCluster + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + SecurityCustomBaseline + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + SecurityCustomBaseline + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + SessionPermSetActivation + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + SessionPermSetActivation + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + true + true + SessionPermSetActivation + true + false + true + UserId + false + + false + + true + SessionPermSetActivations + false + false + + + true + false + true + SetupAssistantStep + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + SetupAssistantStep + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + SetupAuditTrail + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + SharingRecordCollection + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + SharingRecordCollection + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + SharingRecordCollection + true + false + true + OwnerId + false + + false + + false + false + false + + + true + false + true + SharingRecordCollectionItem + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + SharingRecordCollectionItem + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + SharingRecordCollectionMember + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + SharingRecordCollectionMember + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + true + true + SharingRecordCollectionMember + true + false + true + UserOrGroupId + false + + false + + false + false + false + + + true + false + true + SharingRecordCollectionShare + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + true + true + SharingRecordCollectionShare + true + false + true + UserOrGroupId + false + + false + + false + false + false + + + true + false + true + Site + true + false + true + AdminId + false + + false + + true + UserSites + false + false + + + true + false + true + Site + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + Site + true + false + true + GuestRecordDefaultOwnerId + false + + false + + false + false + false + + + true + false + true + Site + true + false + true + GuestUserId + false + + false + + false + false + false + + + true + false + true + Site + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + SiteFeed + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + SiteFeed + true + false + true + InsertedById + false + + false + + false + false + false + + + true + false + true + SiteHistory + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + SiteIframeWhiteListUrl + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + SiteIframeWhiteListUrl + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + SocialPersona + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + SocialPersona + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + SocialPersonaHistory + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + SocialPost + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + SocialPost + true + false + true + DeletedById + false + + false + + false + false + false + + + true + false + true + SocialPost + true + false + true + HiddenById + false + + false + + false + false + false + + + true + false + true + SocialPost + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + SocialPost + true + false + true + OwnerId + false + + false + + false + false + false + + + true + false + true + SocialPostChangeEvent + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + SocialPostChangeEvent + true + false + true + DeletedById + false + + false + + false + false + false + + + true + false + true + SocialPostChangeEvent + true + false + true + HiddenById + false + + false + + false + false + false + + + true + false + true + SocialPostChangeEvent + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + SocialPostChangeEvent + true + false + true + OwnerId + false + + false + + false + false + false + + + true + false + true + SocialPostFeed + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + SocialPostFeed + true + false + true + InsertedById + false + + false + + false + false + false + + + true + false + true + SocialPostHistory + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + SocialPostShare + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + true + true + SocialPostShare + true + false + true + UserOrGroupId + false + + false + + false + false + false + + + true + false + true + Solution + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + Solution + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + Solution + true + false + true + OwnerId + false + + false + + false + false + false + + + true + false + true + SolutionFeed + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + SolutionFeed + true + false + true + InsertedById + false + + false + + false + false + false + + + true + false + true + SolutionHistory + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + SolutionStatus + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + SolutionStatus + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + Stamp + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + Stamp + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + StampAssignment + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + StampAssignment + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + true + true + StampAssignment + true + false + true + SubjectId + false + + false + + false + false + false + + + true + false + true + StaticResource + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + StaticResource + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + StreamingChannel + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + StreamingChannel + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + StreamingChannel + true + false + true + OwnerId + false + + false + + false + false + false + + + true + false + true + StreamingChannelShare + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + true + true + StreamingChannelShare + true + false + true + UserOrGroupId + false + + false + + false + false + false + + + true + false + true + Task + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + Task + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + Task + true + false + true + OwnerId + false + + false + + false + false + false + + + true + false + true + TaskChangeEvent + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + TaskChangeEvent + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + TaskChangeEvent + true + false + true + OwnerId + false + + false + + false + false + false + + + true + false + true + TaskFeed + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + TaskFeed + true + false + true + InsertedById + false + + false + + false + false + false + + + true + false + true + TaskPriority + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + TaskPriority + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + TaskStatus + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + TaskStatus + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + TenantUsageEntitlement + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + TenantUsageEntitlement + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + TestSuiteMembership + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + TestSuiteMembership + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + ThirdPartyAccountLink + true + false + true + UserId + false + + false + + false + false + false + + + true + false + true + TodayGoal + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + TodayGoal + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + TodayGoal + true + false + true + OwnerId + false + + false + + false + false + false + + + true + true + true + TodayGoal + true + false + true + UserId + false + + false + + false + false + false + + + true + false + true + TodayGoalShare + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + true + true + TodayGoalShare + true + false + true + UserOrGroupId + false + + false + + false + false + false + + + true + false + true + Topic + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + TopicAssignment + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + TopicFeed + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + TopicFeed + true + false + true + InsertedById + false + + false + + false + false + false + + + true + false + true + TopicUserEvent + true + false + true + UserId + false + + false + + false + false + false + + + true + false + true + Translation + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + Translation + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + UiFormulaCriterion + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + UiFormulaCriterion + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + UiFormulaRule + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + UiFormulaRule + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + UndecidedEventRelation + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + UndecidedEventRelation + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + UndecidedEventRelation + true + false + true + RelationId + false + + false + + true + UndecidedEventRelations + false + false + + + true + false + true + User + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + User + true + false + true + DelegatedApproverId + false + + false + + true + DelegatedUsers + false + false + + + true + false + true + User + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + User + true + false + true + ManagerId + false + + false + + true + ManagedUsers + false + false + + + true + false + true + UserAppInfo + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + UserAppInfo + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + true + true + UserAppInfo + true + false + true + UserId + false + + false + + false + false + false + + + true + false + true + UserAppMenuCustomization + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + UserAppMenuCustomization + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + UserAppMenuCustomization + true + false + true + OwnerId + false + + false + + false + false + false + + + true + false + true + UserAppMenuCustomizationShare + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + true + true + UserAppMenuCustomizationShare + true + false + true + UserOrGroupId + false + + false + + false + false + false + + + true + false + true + UserChangeEvent + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + UserChangeEvent + true + false + true + DelegatedApproverId + false + + false + + false + false + false + + + true + false + true + UserChangeEvent + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + UserChangeEvent + true + false + true + ManagerId + false + + false + + false + false + false + + + true + false + true + UserEmailPreferredPerson + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + UserEmailPreferredPerson + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + UserEmailPreferredPerson + true + false + true + OwnerId + false + + false + + false + false + false + + + true + true + true + UserEmailPreferredPerson + true + false + true + PersonRecordId + false + + false + + true + PersonRecord + false + false + + + true + false + true + UserEmailPreferredPersonShare + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + true + true + UserEmailPreferredPersonShare + true + false + true + UserOrGroupId + false + + false + + false + false + false + + + true + false + true + UserEntityAccess + true + false + true + UserId + false + + false + + true + UserEntityAccessRights + false + false + + + true + false + true + UserFeed + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + UserFeed + true + false + true + InsertedById + false + + false + + false + false + false + + + true + true + true + UserFeed + true + false + true + ParentId + false + + false + + true + Feeds + false + false + + + true + false + true + UserFieldAccess + true + false + true + UserId + false + + false + + true + UserFieldAccessRights + false + false + + + true + false + true + UserListView + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + UserListView + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + true + true + UserListView + true + false + true + UserId + false + + false + + false + false + false + + + true + false + true + UserListViewCriterion + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + UserListViewCriterion + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + UserLogin + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + UserLogin + true + false + true + UserId + false + + false + + false + false + false + + + true + false + true + UserPackageLicense + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + UserPackageLicense + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + true + true + UserPackageLicense + true + false + true + UserId + false + + false + + false + false + false + + + true + true + true + UserPreference + true + false + true + UserId + false + + false + + true + UserPreferences + false + false + + + true + false + true + UserProvAccount + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + UserProvAccount + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + UserProvAccount + true + false + true + SalesforceUserId + false + + false + + false + false + false + + + true + false + true + UserProvAccountStaging + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + UserProvAccountStaging + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + UserProvAccountStaging + true + false + true + SalesforceUserId + false + + false + + false + false + false + + + true + false + true + UserProvMockTarget + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + UserProvMockTarget + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + UserProvisioningConfig + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + UserProvisioningConfig + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + UserProvisioningLog + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + UserProvisioningLog + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + UserProvisioningLog + true + false + true + UserId + false + + false + + false + false + false + + + true + false + true + UserProvisioningRequest + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + UserProvisioningRequest + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + UserProvisioningRequest + true + false + true + ManagerId + false + + false + + false + false + false + + + true + false + true + UserProvisioningRequest + true + false + true + OwnerId + false + + false + + false + false + false + + + true + false + true + UserProvisioningRequest + true + false + true + SalesforceUserId + false + + false + + false + false + false + + + true + false + true + UserProvisioningRequestShare + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + true + true + UserProvisioningRequestShare + true + false + true + UserOrGroupId + false + + false + + false + false + false + + + true + false + true + UserRecordAccess + true + false + true + UserId + false + + false + + false + false + false + + + true + false + true + UserRole + true + false + true + ForecastUserId + false + + false + + false + false + false + + + true + false + true + UserRole + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + UserRole + true + false + true + PortalAccountOwnerId + false + + false + + false + false + false + + + true + false + true + UserShare + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + true + true + UserShare + true + false + true + UserId + false + + false + + true + Shares + false + false + + + true + true + true + UserShare + true + false + true + UserOrGroupId + false + + false + + false + false + false + + + true + false + true + UserWorkList + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + UserWorkList + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + UserWorkList + true + false + true + OwnerId + false + + false + + false + false + false + + + true + false + true + UserWorkListItem + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + UserWorkListItem + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + UserWorkListShare + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + true + true + UserWorkListShare + true + false + true + UserOrGroupId + false + + false + + false + false + false + + + true + false + true + VerificationHistory + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + VerificationHistory + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + VerificationHistory + true + false + true + UserId + false + + false + + false + false + false + + + true + false + true + VoiceCall + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + VoiceCall + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + VoiceCall + true + false + true + OwnerId + false + + false + + false + false + false + + + true + false + true + VoiceCall + true + false + true + UserId + false + + false + + true + VoiceCalls + false + false + + + true + false + true + VoiceCallChangeEvent + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + VoiceCallChangeEvent + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + VoiceCallChangeEvent + true + false + true + OwnerId + false + + false + + false + false + false + + + true + false + true + VoiceCallChangeEvent + true + false + true + UserId + false + + false + + false + false + false + + + true + false + true + VoiceCallFeed + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + VoiceCallFeed + true + false + true + InsertedById + false + + false + + false + false + false + + + true + false + true + VoiceCallQualityFeedback + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + VoiceCallQualityFeedback + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + VoiceCallQualityFeedback + true + false + true + OwnerId + false + + false + + false + false + false + + + true + false + true + VoiceCallQualityFeedbackShare + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + true + true + VoiceCallQualityFeedbackShare + true + false + true + UserOrGroupId + false + + false + + false + false + false + + + true + false + true + VoiceCallRecording + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + VoiceCallRecording + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + VoiceCallRecording + true + false + true + OwnerId + false + + false + + false + false + false + + + true + false + true + VoiceCallRecordingChangeEvent + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + VoiceCallRecordingChangeEvent + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + VoiceCallRecordingChangeEvent + true + false + true + OwnerId + false + + false + + false + false + false + + + true + false + true + VoiceCallShare + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + true + true + VoiceCallShare + true + false + true + UserOrGroupId + false + + false + + false + false + false + + + true + false + true + VoiceOrgSetting + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + VoiceOrgSetting + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + VoiceVendorInfo + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + VoiceVendorInfo + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + VoiceVendorLine + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + VoiceVendorLine + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + VoiceVendorLine + true + false + true + OwnerId + false + + false + + false + false + false + + + true + false + true + VoiceVendorLine + true + false + true + UserId + false + + false + + true + VoiceVendorLines + false + false + + + true + false + true + VoiceVendorLineShare + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + true + true + VoiceVendorLineShare + true + false + true + UserOrGroupId + false + + false + + false + false + false + + + true + true + true + Vote + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + Vote + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + WaveAutoInstallRequest + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + WaveAutoInstallRequest + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + WaveCompatibilityCheckItem + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + WaveCompatibilityCheckItem + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + WebLink + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + WebLink + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + WorkAccess + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + WorkAccess + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + WorkAccess + true + false + true + OwnerId + false + + false + + false + false + false + + + true + false + true + WorkAccessShare + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + true + true + WorkAccessShare + true + false + true + UserOrGroupId + false + + false + + false + false + false + + + true + false + true + WorkBadge + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + WorkBadge + true + false + true + GiverId + false + + false + + false + false + false + + + true + false + true + WorkBadge + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + WorkBadge + true + false + true + RecipientId + false + + false + + true + Badges + true + true + + + true + false + true + WorkBadgeDefinition + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + WorkBadgeDefinition + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + WorkBadgeDefinition + true + false + true + OwnerId + false + + false + + false + false + false + + + true + false + true + WorkBadgeDefinitionFeed + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + WorkBadgeDefinitionFeed + true + false + true + InsertedById + false + + false + + false + false + false + + + true + false + true + WorkBadgeDefinitionHistory + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + WorkBadgeDefinitionShare + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + true + true + WorkBadgeDefinitionShare + true + false + true + UserOrGroupId + false + + false + + false + false + false + + + true + false + true + WorkOrder + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + WorkOrder + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + WorkOrder + true + false + true + OwnerId + false + + false + + false + false + false + + + true + false + true + WorkOrderChangeEvent + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + WorkOrderChangeEvent + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + WorkOrderChangeEvent + true + false + true + OwnerId + false + + false + + false + false + false + + + true + false + true + WorkOrderFeed + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + WorkOrderFeed + true + false + true + InsertedById + false + + false + + false + false + false + + + true + false + true + WorkOrderHistory + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + WorkOrderLineItem + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + WorkOrderLineItem + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + WorkOrderLineItemChangeEvent + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + WorkOrderLineItemChangeEvent + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + WorkOrderLineItemFeed + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + WorkOrderLineItemFeed + true + false + true + InsertedById + false + + false + + false + false + false + + + true + false + true + WorkOrderLineItemHistory + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + WorkOrderLineItemStatus + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + WorkOrderLineItemStatus + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + WorkOrderShare + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + true + true + WorkOrderShare + true + false + true + UserOrGroupId + false + + false + + false + false + false + + + true + false + true + WorkOrderStatus + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + WorkOrderStatus + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + WorkThanks + true + false + true + CreatedById + false + + false + + false + false + false + + + true + false + true + WorkThanks + true + false + true + GiverId + false + + false + + true + GivenThanks + true + true + + + true + false + true + WorkThanks + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + false + true + WorkThanks + true + false + true + OwnerId + false + + false + + false + false + false + + + true + false + true + WorkThanksShare + true + false + true + LastModifiedById + false + + false + + false + false + false + + + true + true + true + WorkThanksShare + true + false + true + UserOrGroupId + false + + false + + false + false + false + + + true + true + true + true + true + false + true + false + false + false + true + false + true + true + false + true + false + true + true + true + + + true + true + true + false + true + false + true + 18 + true + false + false + false + false + true + false + false + false + true + false + true + false + false + false + false + false + true + true + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + true + false + false + false + false + true + true + false + true + + true + 18 + false + false + true + Id + true + false + true + false + true + false + true + false + false + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + ID + true + true + true + id + true + false + true + false + false + false + + + true + true + true + false + true + false + true + 240 + true + false + false + false + false + true + false + false + false + true + true + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + true + false + false + false + false + true + true + false + true + + true + 80 + false + false + true + Username + true + false + true + false + true + false + true + false + false + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + string + true + true + true + string + true + false + true + true + false + false + + + true + true + true + false + true + false + true + 240 + true + false + false + false + false + true + false + true + Name + false + true + true + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + true + personname + true + true + false + false + false + true + true + false + false + false + false + true + false + false + true + + true + 80 + false + false + true + LastName + true + false + true + false + true + false + true + false + false + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + string + true + true + true + string + true + false + true + true + false + false + + + true + true + true + false + true + false + true + 120 + true + false + false + false + false + true + false + true + Name + false + true + true + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + true + personname + true + true + false + false + false + true + true + false + false + false + false + true + false + false + true + + true + 40 + false + false + true + FirstName + true + false + true + false + true + true + true + false + false + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + string + true + true + true + string + true + false + true + true + false + false + + + true + true + true + false + true + false + true + 363 + true + false + false + false + false + true + false + false + false + true + false + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + true + personname + true + true + false + false + false + true + true + false + false + false + false + true + false + false + true + + true + 121 + false + false + true + Name + true + true + true + false + true + false + true + false + false + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + string + true + true + true + string + true + false + true + false + false + false + + + true + true + true + false + true + false + true + 240 + true + false + false + false + false + true + false + false + false + true + true + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + true + false + false + false + false + true + false + false + true + + true + 80 + false + false + true + CompanyName + true + false + true + false + true + true + true + false + false + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + string + true + true + true + string + true + false + true + true + false + false + + + true + true + true + false + true + false + true + 240 + true + false + false + false + false + true + false + false + false + true + true + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + true + false + false + false + false + true + false + false + true + + true + 80 + false + false + true + Division + true + false + true + false + true + true + true + false + false + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + string + true + true + true + string + true + false + true + true + false + false + + + true + true + true + false + true + false + true + 240 + true + false + false + false + false + true + false + false + false + true + true + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + true + false + false + false + false + true + false + false + true + + true + 80 + false + false + true + Department + true + false + true + false + true + true + true + false + false + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + string + true + true + true + string + true + false + true + true + false + false + + + true + true + true + false + true + false + true + 240 + true + false + false + false + false + true + false + false + false + true + true + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + true + false + false + false + false + true + false + false + true + + true + 80 + false + false + true + Title + true + false + true + false + true + true + true + false + false + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + string + true + true + true + string + true + false + true + true + false + false + + + true + true + true + false + true + false + true + 765 + true + false + false + false + false + true + false + true + Address + false + true + true + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + true + plaintextarea + true + true + false + false + false + true + true + false + false + false + false + true + false + false + true + + true + 255 + false + false + true + Street + true + false + true + false + true + true + true + false + false + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + string + true + true + true + textarea + true + false + true + true + false + false + + + true + true + true + false + true + false + true + 120 + true + false + false + false + false + true + false + true + Address + false + true + true + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + true + false + false + false + false + true + false + false + true + + true + 40 + false + false + true + City + true + false + true + false + true + true + true + false + false + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + string + true + true + true + string + true + false + true + true + false + false + + + true + true + true + false + true + false + true + 240 + true + false + false + false + false + true + false + true + Address + false + true + true + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + true + false + false + false + false + true + false + false + true + + true + 80 + false + false + true + State + true + false + true + false + true + true + true + false + false + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + string + true + true + true + string + true + false + true + true + false + false + + + true + true + true + false + true + false + true + 60 + true + false + false + false + false + true + false + true + Address + false + true + true + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + true + false + false + false + false + true + false + false + true + + true + 20 + false + false + true + PostalCode + true + false + true + false + true + true + true + false + false + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + string + true + true + true + string + true + false + true + true + false + false + + + true + true + true + false + true + false + true + 240 + true + false + false + false + false + true + false + true + Address + false + true + true + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + true + false + false + false + false + true + false + false + true + + true + 80 + false + false + true + Country + true + false + true + false + true + true + true + false + false + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + string + true + true + true + string + true + false + true + true + false + false + + + true + true + true + false + true + false + true + 0 + true + false + false + false + false + true + false + true + Address + false + true + true + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + false + false + false + false + false + true + false + false + true + + true + 0 + false + false + true + Latitude + true + false + true + false + true + true + true + false + false + + true + false + true + 18 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 15 + true + false + true + _double + true + true + true + _double + true + false + true + true + false + false + + + true + true + true + false + true + false + true + 0 + true + false + false + false + false + true + false + true + Address + false + true + true + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + false + false + false + false + false + true + false + false + true + + true + 0 + false + false + true + Longitude + true + false + true + false + true + true + true + false + false + + true + false + true + 18 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 15 + true + false + true + _double + true + true + true + _double + true + false + true + true + false + false + + + true + true + true + false + true + false + true + 120 + true + false + false + false + false + true + false + true + Address + false + true + true + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + true + false + false + false + false + true + false + false + true + + true + 40 + false + false + true + GeocodeAccuracy + true + false + true + false + true + true + true + false + true + + + true + true + true + false + true + + false + true + Address + + + true + true + true + false + true + + false + true + NearAddress + + + true + true + true + false + true + + false + true + Block + + + true + true + true + false + true + + false + true + Street + + + true + true + true + false + true + + false + true + ExtendedZip + + + true + true + true + false + true + + false + true + Zip + + + true + true + true + false + true + + false + true + Neighborhood + + + true + true + true + false + true + + false + true + City + + + true + true + true + false + true + + false + true + County + + + true + true + true + false + true + + false + true + State + + + true + true + true + false + true + + false + true + Unknown + + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + true + true + 0 + true + false + true + string + true + true + true + picklist + true + false + true + true + false + false + + + true + false + true + false + true + false + true + 0 + true + false + false + false + false + true + false + false + false + true + false + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + false + false + false + false + false + true + false + false + true + + true + 0 + false + false + true + Address + true + false + true + false + true + true + true + false + false + + true + false + true + 0 + true + true + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + address + true + false + true + address + true + false + true + false + false + false + + + true + true + true + false + true + false + true + 384 + true + false + false + false + false + true + false + false + false + true + true + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + true + false + false + false + false + true + true + false + true + + true + 128 + false + false + true + Email + true + false + true + false + true + false + true + false + false + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + string + true + true + true + email + true + false + true + true + false + false + + + true + false + true + false + true + false + true + 0 + true + false + false + false + false + true + false + false + false + true + true + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + false + false + false + false + false + true + false + false + true + + true + 0 + false + false + true + EmailPreferencesAutoBcc + true + false + true + false + true + false + true + false + false + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + _boolean + true + false + true + _boolean + true + false + true + true + false + false + + + true + false + true + false + true + false + true + 0 + true + false + false + false + false + true + false + false + false + true + true + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + false + false + false + false + false + true + false + false + true + + true + 0 + false + false + true + EmailPreferencesAutoBccStayInTouch + true + false + true + false + true + false + true + false + false + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + _boolean + true + false + true + _boolean + true + false + true + true + false + false + + + true + false + true + false + true + false + true + 0 + true + false + false + false + false + true + false + false + false + true + true + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + false + false + false + false + false + true + false + false + true + + true + 0 + false + false + true + EmailPreferencesStayInTouchReminder + true + false + true + false + true + false + true + false + false + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + _boolean + true + false + true + _boolean + true + false + true + true + false + false + + + true + true + true + false + true + false + true + 240 + true + false + false + false + false + true + false + false + false + true + true + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + true + false + false + false + false + true + false + false + true + + true + 80 + false + false + true + SenderEmail + true + false + true + false + true + true + true + false + false + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + string + true + true + true + email + true + false + true + true + false + false + + + true + true + true + false + true + false + true + 240 + true + false + false + false + false + true + false + false + false + true + true + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + true + false + false + false + false + true + false + false + true + + true + 80 + false + false + true + SenderName + true + false + true + false + true + true + true + false + false + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + string + true + true + true + string + true + false + true + true + false + false + + + true + true + true + false + true + false + true + 3999 + true + false + false + false + false + true + false + false + false + true + true + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + true + plaintextarea + true + true + false + false + false + true + false + false + false + false + false + true + false + false + true + + true + 1333 + false + false + true + Signature + true + false + true + false + true + true + true + false + false + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + string + true + true + true + textarea + true + false + true + true + false + false + + + true + true + true + false + true + false + true + 240 + true + false + false + false + false + true + false + false + false + true + true + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + true + false + false + false + false + true + false + false + true + + true + 80 + false + false + true + StayInTouchSubject + true + false + true + false + true + true + true + false + false + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + string + true + true + true + string + true + false + true + true + false + false + + + true + true + true + false + true + false + true + 1536 + true + false + false + false + false + true + false + false + false + true + true + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + true + plaintextarea + true + true + false + false + false + true + false + false + false + false + false + true + false + false + true + + true + 512 + false + false + true + StayInTouchSignature + true + false + true + false + true + true + true + false + false + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + string + true + true + true + textarea + true + false + true + true + false + false + + + true + true + true + false + true + false + true + 1536 + true + false + false + false + false + true + false + false + false + true + true + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + false + false + false + false + false + true + false + false + true + + true + 512 + false + false + true + StayInTouchNote + true + false + true + false + true + true + true + false + false + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + string + true + true + true + string + true + false + true + true + false + false + + + true + true + true + false + true + false + true + 120 + true + false + false + false + false + true + false + false + false + true + true + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + true + false + false + false + false + true + false + false + true + + true + 40 + false + false + true + Phone + true + false + true + false + true + true + true + false + false + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + string + true + true + true + phone + true + false + true + true + false + false + + + true + true + true + false + true + false + true + 120 + true + false + false + false + false + true + false + false + false + true + true + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + true + false + false + false + false + true + false + false + true + + true + 40 + false + false + true + Fax + true + false + true + false + true + true + true + false + false + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + string + true + true + true + phone + true + false + true + true + false + false + + + true + true + true + false + true + false + true + 120 + true + false + false + false + false + true + false + false + false + true + true + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + true + false + false + false + false + true + false + false + true + + true + 40 + false + false + true + MobilePhone + true + false + true + false + true + true + true + false + false + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + string + true + true + true + phone + true + false + true + true + false + false + + + true + true + true + false + true + false + true + 24 + true + false + false + false + false + true + false + false + false + true + true + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + true + false + false + false + false + true + false + false + true + + true + 8 + false + false + true + Alias + true + false + true + false + true + false + true + false + false + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + string + true + true + true + string + true + false + true + true + false + false + + + true + true + true + false + true + false + true + 120 + true + false + false + false + false + true + false + false + false + true + true + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + true + false + false + false + false + true + false + false + true + + true + 40 + false + false + true + CommunityNickname + true + false + true + false + true + false + true + false + false + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + string + true + true + true + string + true + false + true + true + false + false + + + true + true + true + false + true + false + true + 240 + true + false + false + false + false + true + false + false + false + true + false + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + true + false + false + false + false + true + false + false + true + + true + 80 + false + false + true + BadgeText + true + false + true + false + true + true + true + false + false + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + string + true + true + true + string + true + false + true + false + false + false + + + true + false + true + false + true + false + true + 0 + true + false + false + false + false + true + false + false + false + true + true + true + false + false + false + true + false + false + true + true + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + true + false + false + false + false + true + false + false + true + + true + 0 + false + false + true + IsActive + true + false + true + false + true + false + true + false + false + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + _boolean + true + true + true + _boolean + true + false + true + true + false + false + + + true + true + true + false + true + false + true + 120 + true + false + false + false + false + true + false + false + false + true + true + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + true + false + false + false + false + true + false + false + true + + true + 40 + false + false + true + TimeZoneSidKey + true + false + true + false + true + false + true + false + true + + + true + true + true + false + true + + false + true + Pacific/Kiritimati + + + true + true + true + false + true + + false + true + Pacific/Chatham + + + true + true + true + false + true + + false + true + Pacific/Auckland + + + true + true + true + false + true + + false + true + Pacific/Enderbury + + + true + true + true + false + true + + false + true + Pacific/Tongatapu + + + true + true + true + false + true + + false + true + Asia/Kamchatka + + + true + true + true + false + true + + false + true + Pacific/Fiji + + + true + true + true + false + true + + false + true + Pacific/Norfolk + + + true + true + true + false + true + + false + true + Australia/Lord_Howe + + + true + true + true + false + true + + false + true + Australia/Sydney + + + true + true + true + false + true + + false + true + Pacific/Guadalcanal + + + true + true + true + false + true + + false + true + Australia/Adelaide + + + true + true + true + false + true + + false + true + Australia/Brisbane + + + true + true + true + false + true + + false + true + Australia/Darwin + + + true + true + true + false + true + + false + true + Asia/Seoul + + + true + true + true + false + true + + false + true + Asia/Tokyo + + + true + true + true + false + true + + false + true + Asia/Hong_Kong + + + true + true + true + false + true + + false + true + Asia/Kuala_Lumpur + + + true + true + true + false + true + + false + true + Asia/Manila + + + true + true + true + false + true + + false + true + Asia/Shanghai + + + true + true + true + false + true + + false + true + Asia/Singapore + + + true + true + true + false + true + + false + true + Asia/Taipei + + + true + true + true + false + true + + false + true + Australia/Perth + + + true + true + true + false + true + + false + true + Asia/Bangkok + + + true + true + true + false + true + + false + true + Asia/Ho_Chi_Minh + + + true + true + true + false + true + + false + true + Asia/Jakarta + + + true + true + true + false + true + + false + true + Asia/Rangoon + + + true + true + true + false + true + + false + true + Asia/Dhaka + + + true + true + true + false + true + + false + true + Asia/Kathmandu + + + true + true + true + false + true + + false + true + Asia/Colombo + + + true + true + true + false + true + + false + true + Asia/Kolkata + + + true + true + true + false + true + + false + true + Asia/Karachi + + + true + true + true + false + true + + false + true + Asia/Tashkent + + + true + true + true + false + true + + false + true + Asia/Yekaterinburg + + + true + true + true + false + true + + false + true + Asia/Kabul + + + true + true + true + false + true + + false + true + Asia/Baku + + + true + true + true + false + true + + false + true + Asia/Dubai + + + true + true + true + false + true + + false + true + Asia/Tbilisi + + + true + true + true + false + true + + false + true + Asia/Yerevan + + + true + true + true + false + true + + false + true + Asia/Tehran + + + true + true + true + false + true + + false + true + Africa/Nairobi + + + true + true + true + false + true + + false + true + Asia/Baghdad + + + true + true + true + false + true + + false + true + Asia/Kuwait + + + true + true + true + false + true + + false + true + Asia/Riyadh + + + true + true + true + false + true + + false + true + Europe/Istanbul + + + true + true + true + false + true + + false + true + Europe/Minsk + + + true + true + true + false + true + + false + true + Europe/Moscow + + + true + true + true + false + true + + false + true + Africa/Cairo + + + true + true + true + false + true + + false + true + Africa/Johannesburg + + + true + true + true + false + true + + false + true + Asia/Beirut + + + true + true + true + false + true + + false + true + Asia/Jerusalem + + + true + true + true + false + true + + false + true + Europe/Athens + + + true + true + true + false + true + + false + true + Europe/Bucharest + + + true + true + true + false + true + + false + true + Europe/Helsinki + + + true + true + true + false + true + + false + true + Africa/Algiers + + + true + true + true + false + true + + false + true + Africa/Casablanca + + + true + true + true + false + true + + false + true + Europe/Amsterdam + + + true + true + true + false + true + + false + true + Europe/Berlin + + + true + true + true + false + true + + false + true + Europe/Brussels + + + true + true + true + false + true + + false + true + Europe/Paris + + + true + true + true + false + true + + false + true + Europe/Prague + + + true + true + true + false + true + + false + true + Europe/Rome + + + true + true + true + false + true + + false + true + Europe/Dublin + + + true + true + true + false + true + + false + true + Europe/Lisbon + + + true + true + true + false + true + + false + true + Europe/London + + + true + true + true + false + true + + false + true + GMT + + + true + true + true + false + true + + false + true + America/Scoresbysund + + + true + true + true + false + true + + false + true + Atlantic/Azores + + + true + true + true + false + true + + false + true + Atlantic/Cape_Verde + + + true + true + true + false + true + + false + true + Atlantic/South_Georgia + + + true + true + true + false + true + + false + true + America/St_Johns + + + true + true + true + false + true + + false + true + America/Argentina/Buenos_Aires + + + true + true + true + false + true + + false + true + America/Halifax + + + true + true + true + false + true + + false + true + America/Santiago + + + true + true + true + false + true + + false + true + America/Sao_Paulo + + + true + true + true + false + true + + false + true + Atlantic/Bermuda + + + true + true + true + false + true + + false + true + America/Caracas + + + true + true + true + false + true + + false + true + America/Indiana/Indianapolis + + + true + true + true + false + true + + false + true + America/New_York + + + true + true + true + false + true + + false + true + America/Puerto_Rico + + + true + true + true + false + true + + false + true + America/Bogota + + + true + true + true + false + true + + false + true + America/Chicago + + + true + true + true + false + true + + false + true + America/Lima + + + true + true + true + false + true + + false + true + America/Panama + + + true + true + true + false + true + + false + true + America/Denver + + + true + true + true + false + true + + false + true + America/El_Salvador + + + true + true + true + false + true + + false + true + America/Mexico_City + + + true + true + true + false + true + + false + true + America/Los_Angeles + + + true + true + true + false + true + + false + true + America/Mazatlan + + + true + true + true + false + true + + false + true + America/Phoenix + + + true + true + true + false + true + + false + true + America/Tijuana + + + true + true + true + false + true + + false + true + America/Anchorage + + + true + true + true + false + true + + false + true + Pacific/Pitcairn + + + true + true + true + false + true + + false + true + America/Adak + + + true + true + true + false + true + + false + true + Pacific/Gambier + + + true + true + true + false + true + + false + true + Pacific/Marquesas + + + true + true + true + false + true + + false + true + Pacific/Honolulu + + + true + true + true + false + true + + false + true + Pacific/Niue + + + true + true + true + false + true + + false + true + Pacific/Pago_Pago + + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + true + true + 0 + true + false + true + string + true + true + true + picklist + true + false + true + true + false + false + + + true + true + true + false + true + false + true + 18 + true + false + false + false + false + true + false + false + false + true + true + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + true + false + false + false + false + true + false + false + true + + true + 18 + false + false + true + UserRoleId + true + false + true + false + true + true + true + false + false + + true + false + true + 0 + true + false + false + true + + UserRole + + true + UserRole + false + 0 + false + false + true + false + true + 0 + true + false + true + ID + true + true + true + reference + true + false + true + true + false + false + + + true + true + true + false + true + false + true + 120 + true + false + false + false + false + true + false + false + false + true + true + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + true + false + false + false + false + true + false + false + true + + true + 40 + false + false + true + LocaleSidKey + true + false + true + false + true + false + true + false + true + + + true + true + true + false + true + + false + true + af_ZA + + + true + true + true + false + true + + false + true + sq_AL + + + true + true + true + false + true + + false + true + am_ET + + + true + true + true + false + true + + false + true + ar_DZ + + + true + true + true + false + true + + false + true + ar_BH + + + true + true + true + false + true + + false + true + ar_EG + + + true + true + true + false + true + + false + true + ar_IQ + + + true + true + true + false + true + + false + true + ar_JO + + + true + true + true + false + true + + false + true + ar_KW + + + true + true + true + false + true + + false + true + ar_LB + + + true + true + true + false + true + + false + true + ar_LY + + + true + true + true + false + true + + false + true + ar_MA + + + true + true + true + false + true + + false + true + ar_OM + + + true + true + true + false + true + + false + true + ar_QA + + + true + true + true + false + true + + false + true + ar_SA + + + true + true + true + false + true + + false + true + ar_SD + + + true + true + true + false + true + + false + true + ar_SY + + + true + true + true + false + true + + false + true + ar_TN + + + true + true + true + false + true + + false + true + ar_AE + + + true + true + true + false + true + + false + true + ar_YE + + + true + true + true + false + true + + false + true + hy_AM + + + true + true + true + false + true + + false + true + az_AZ + + + true + true + true + false + true + + false + true + bn_BD + + + true + true + true + false + true + + false + true + bn_IN + + + true + true + true + false + true + + false + true + eu_ES + + + true + true + true + false + true + + false + true + be_BY + + + true + true + true + false + true + + false + true + bs_BA + + + true + true + true + false + true + + false + true + bg_BG + + + true + true + true + false + true + + false + true + my_MM + + + true + true + true + false + true + + false + true + ca_ES + + + true + true + true + false + true + + false + true + zh_CN_PINYIN + + + true + true + true + false + true + + false + true + zh_CN_STROKE + + + true + true + true + false + true + + false + true + zh_CN + + + true + true + true + false + true + + false + true + zh_HK_STROKE + + + true + true + true + false + true + + false + true + zh_HK + + + true + true + true + false + true + + false + true + zh_MO + + + true + true + true + false + true + + false + true + zh_SG + + + true + true + true + false + true + + false + true + zh_TW_STROKE + + + true + true + true + false + true + + false + true + zh_TW + + + true + true + true + false + true + + false + true + hr_HR + + + true + true + true + false + true + + false + true + cs_CZ + + + true + true + true + false + true + + false + true + da_DK + + + true + true + true + false + true + + false + true + nl_AW + + + true + true + true + false + true + + false + true + nl_BE + + + true + true + true + false + true + + false + true + nl_NL + + + true + true + true + false + true + + false + true + nl_SR + + + true + true + true + false + true + + false + true + dz_BT + + + true + true + true + false + true + + false + true + en_AG + + + true + true + true + false + true + + false + true + en_AU + + + true + true + true + false + true + + false + true + en_BS + + + true + true + true + false + true + + false + true + en_BB + + + true + true + true + false + true + + false + true + en_BZ + + + true + true + true + false + true + + false + true + en_BM + + + true + true + true + false + true + + false + true + en_BW + + + true + true + true + false + true + + false + true + en_CM + + + true + true + true + false + true + + false + true + en_CA + + + true + true + true + false + true + + false + true + en_KY + + + true + true + true + false + true + + false + true + en_ER + + + true + true + true + false + true + + false + true + en_SZ + + + true + true + true + false + true + + false + true + en_FK + + + true + true + true + false + true + + false + true + en_FJ + + + true + true + true + false + true + + false + true + en_GM + + + true + true + true + false + true + + false + true + en_GH + + + true + true + true + false + true + + false + true + en_GI + + + true + true + true + false + true + + false + true + en_GY + + + true + true + true + false + true + + false + true + en_HK + + + true + true + true + false + true + + false + true + en_IN + + + true + true + true + false + true + + false + true + en_ID + + + true + true + true + false + true + + false + true + en_IE + + + true + true + true + false + true + + false + true + en_JM + + + true + true + true + false + true + + false + true + en_KE + + + true + true + true + false + true + + false + true + en_LR + + + true + true + true + false + true + + false + true + en_MG + + + true + true + true + false + true + + false + true + en_MW + + + true + true + true + false + true + + false + true + en_MY + + + true + true + true + false + true + + false + true + en_MU + + + true + true + true + false + true + + false + true + en_NA + + + true + true + true + false + true + + false + true + en_NZ + + + true + true + true + false + true + + false + true + en_NG + + + true + true + true + false + true + + false + true + en_PK + + + true + true + true + false + true + + false + true + en_PG + + + true + true + true + false + true + + false + true + en_PH + + + true + true + true + false + true + + false + true + en_RW + + + true + true + true + false + true + + false + true + en_WS + + + true + true + true + false + true + + false + true + en_SC + + + true + true + true + false + true + + false + true + en_SL + + + true + true + true + false + true + + false + true + en_SG + + + true + true + true + false + true + + false + true + en_SX + + + true + true + true + false + true + + false + true + en_SB + + + true + true + true + false + true + + false + true + en_ZA + + + true + true + true + false + true + + false + true + en_SH + + + true + true + true + false + true + + false + true + en_TZ + + + true + true + true + false + true + + false + true + en_TO + + + true + true + true + false + true + + false + true + en_TT + + + true + true + true + false + true + + false + true + en_UG + + + true + true + true + false + true + + false + true + en_GB + + + true + true + true + false + true + + false + true + en_US + + + true + true + true + false + true + + false + true + en_VU + + + true + true + true + false + true + + false + true + et_EE + + + true + true + true + false + true + + false + true + fi_FI + + + true + true + true + false + true + + false + true + fr_BE + + + true + true + true + false + true + + false + true + fr_CA + + + true + true + true + false + true + + false + true + fr_KM + + + true + true + true + false + true + + false + true + fr_FR + + + true + true + true + false + true + + false + true + fr_GN + + + true + true + true + false + true + + false + true + fr_HT + + + true + true + true + false + true + + false + true + fr_LU + + + true + true + true + false + true + + false + true + fr_MR + + + true + true + true + false + true + + false + true + fr_MC + + + true + true + true + false + true + + false + true + fr_CH + + + true + true + true + false + true + + false + true + fr_WF + + + true + true + true + false + true + + false + true + ka_GE + + + true + true + true + false + true + + false + true + de_AT + + + true + true + true + false + true + + false + true + de_BE + + + true + true + true + false + true + + false + true + de_DE + + + true + true + true + false + true + + false + true + de_LU + + + true + true + true + false + true + + false + true + de_CH + + + true + true + true + false + true + + false + true + el_GR + + + true + true + true + false + true + + false + true + gu_IN + + + true + true + true + false + true + + false + true + iw_IL + + + true + true + true + false + true + + false + true + hi_IN + + + true + true + true + false + true + + false + true + hu_HU + + + true + true + true + false + true + + false + true + is_IS + + + true + true + true + false + true + + false + true + in_ID + + + true + true + true + false + true + + false + true + ga_IE + + + true + true + true + false + true + + false + true + it_IT + + + true + true + true + false + true + + false + true + it_CH + + + true + true + true + false + true + + false + true + ja_JP + + + true + true + true + false + true + + false + true + kn_IN + + + true + true + true + false + true + + false + true + kk_KZ + + + true + true + true + false + true + + false + true + km_KH + + + true + true + true + false + true + + false + true + ko_KP + + + true + true + true + false + true + + false + true + ko_KR + + + true + true + true + false + true + + false + true + ky_KG + + + true + true + true + false + true + + false + true + lo_LA + + + true + true + true + false + true + + false + true + lv_LV + + + true + true + true + false + true + + false + true + lt_LT + + + true + true + true + false + true + + false + true + lu_CD + + + true + true + true + false + true + + false + true + lb_LU + + + true + true + true + false + true + + false + true + mk_MK + + + true + true + true + false + true + + false + true + ms_BN + + + true + true + true + false + true + + false + true + ms_MY + + + true + true + true + false + true + + false + true + ml_IN + + + true + true + true + false + true + + false + true + mt_MT + + + true + true + true + false + true + + false + true + mr_IN + + + true + true + true + false + true + + false + true + sh_ME_USD + + + true + true + true + false + true + + false + true + sh_ME + + + true + true + true + false + true + + false + true + ne_NP + + + true + true + true + false + true + + false + true + no_NO + + + true + true + true + false + true + + false + true + ps_AF + + + true + true + true + false + true + + false + true + fa_IR + + + true + true + true + false + true + + false + true + pl_PL + + + true + true + true + false + true + + false + true + pt_AO + + + true + true + true + false + true + + false + true + pt_BR + + + true + true + true + false + true + + false + true + pt_CV + + + true + true + true + false + true + + false + true + pt_MZ + + + true + true + true + false + true + + false + true + pt_PT + + + true + true + true + false + true + + false + true + pt_ST + + + true + true + true + false + true + + false + true + ro_MD + + + true + true + true + false + true + + false + true + ro_RO + + + true + true + true + false + true + + false + true + rm_CH + + + true + true + true + false + true + + false + true + rn_BI + + + true + true + true + false + true + + false + true + ru_KZ + + + true + true + true + false + true + + false + true + ru_RU + + + true + true + true + false + true + + false + true + sr_BA + + + true + true + true + false + true + + false + true + sr_CS + + + true + true + true + false + true + + false + true + sh_BA + + + true + true + true + false + true + + false + true + sh_CS + + + true + true + true + false + true + + false + true + sr_RS + + + true + true + true + false + true + + false + true + sk_SK + + + true + true + true + false + true + + false + true + sl_SI + + + true + true + true + false + true + + false + true + so_DJ + + + true + true + true + false + true + + false + true + so_SO + + + true + true + true + false + true + + false + true + es_AR + + + true + true + true + false + true + + false + true + es_BO + + + true + true + true + false + true + + false + true + es_CL + + + true + true + true + false + true + + false + true + es_CO + + + true + true + true + false + true + + false + true + es_CR + + + true + true + true + false + true + + false + true + es_CU + + + true + true + true + false + true + + false + true + es_DO + + + true + true + true + false + true + + false + true + es_EC + + + true + true + true + false + true + + false + true + es_SV + + + true + true + true + false + true + + false + true + es_GT + + + true + true + true + false + true + + false + true + es_HN + + + true + true + true + false + true + + false + true + es_MX + + + true + true + true + false + true + + false + true + es_NI + + + true + true + true + false + true + + false + true + es_PA + + + true + true + true + false + true + + false + true + es_PY + + + true + true + true + false + true + + false + true + es_PE + + + true + true + true + false + true + + false + true + es_PR + + + true + true + true + false + true + + false + true + es_ES + + + true + true + true + false + true + + false + true + es_US + + + true + true + true + false + true + + false + true + es_UY + + + true + true + true + false + true + + false + true + es_VE + + + true + true + true + false + true + + false + true + sw_KE + + + true + true + true + false + true + + false + true + sv_SE + + + true + true + true + false + true + + false + true + tl_PH + + + true + true + true + false + true + + false + true + tg_TJ + + + true + true + true + false + true + + false + true + ta_IN + + + true + true + true + false + true + + false + true + ta_LK + + + true + true + true + false + true + + false + true + te_IN + + + true + true + true + false + true + + false + true + mi_NZ + + + true + true + true + false + true + + false + true + th_TH + + + true + true + true + false + true + + false + true + ti_ET + + + true + true + true + false + true + + false + true + tr_TR + + + true + true + true + false + true + + false + true + uk_UA + + + true + true + true + false + true + + false + true + ur_PK + + + true + true + true + false + true + + false + true + uz_LATN_UZ + + + true + true + true + false + true + + false + true + vi_VN + + + true + true + true + false + true + + false + true + cy_GB + + + true + true + true + false + true + + false + true + xh_ZA + + + true + true + true + false + true + + false + true + yo_BJ + + + true + true + true + false + true + + false + true + zu_ZA + + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + true + true + 0 + true + false + true + string + true + true + true + picklist + true + false + true + true + false + false + + + true + false + true + false + true + false + true + 0 + true + false + false + false + false + true + false + false + false + true + true + true + false + false + false + true + false + false + true + true + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + true + false + false + false + false + true + false + false + true + + true + 0 + false + false + true + ReceivesInfoEmails + true + false + true + false + true + false + true + false + false + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + _boolean + true + true + true + _boolean + true + false + true + true + false + false + + + true + false + true + false + true + false + true + 0 + true + false + false + false + false + true + false + false + false + true + true + true + false + false + false + true + false + false + true + true + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + true + false + false + false + false + true + false + false + true + + true + 0 + false + false + true + ReceivesAdminInfoEmails + true + false + true + false + true + false + true + false + false + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + _boolean + true + true + true + _boolean + true + false + true + true + false + false + + + true + true + true + false + true + false + true + 120 + true + false + false + false + false + true + false + false + false + true + true + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + true + false + false + false + false + true + false + false + true + + true + 40 + false + false + true + EmailEncodingKey + true + false + true + false + true + false + true + false + true + + + true + true + true + false + true + + false + true + UTF-8 + + + true + true + true + false + true + + false + true + ISO-8859-1 + + + true + true + true + false + true + + false + true + Shift_JIS + + + true + true + true + false + true + + false + true + ISO-2022-JP + + + true + true + true + false + true + + false + true + EUC-JP + + + true + true + true + false + true + + false + true + ks_c_5601-1987 + + + true + true + true + false + true + + false + true + Big5 + + + true + true + true + false + true + + false + true + GB2312 + + + true + true + true + false + true + + false + true + Big5-HKSCS + + + true + true + true + false + true + + false + true + x-SJIS_0213 + + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + true + true + 0 + true + false + true + string + true + true + true + picklist + true + false + true + true + false + false + + + true + true + true + false + true + false + true + 18 + true + false + false + false + false + true + false + false + false + true + true + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + true + false + false + false + false + true + false + false + true + + true + 18 + false + false + true + ProfileId + true + false + true + false + true + false + true + false + false + + true + false + true + 0 + true + false + false + true + + Profile + + true + Profile + false + 0 + false + false + true + false + true + 0 + true + false + true + ID + true + true + true + reference + true + false + true + true + false + false + + + true + true + true + false + true + false + true + 120 + true + false + false + false + false + true + false + false + false + true + false + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + true + false + false + false + false + true + false + false + true + + true + 40 + false + false + true + UserType + true + false + true + false + true + true + true + false + true + + + true + true + true + false + true + + false + true + Standard + + + true + true + true + false + true + + false + true + PowerPartner + + + true + true + true + false + true + + false + true + PowerCustomerSuccess + + + true + true + true + false + true + + false + true + CustomerSuccess + + + true + true + true + false + true + + false + true + Guest + + + true + true + true + false + true + + false + true + CspLitePortal + + + true + true + true + false + true + + false + true + CsnOnly + + + true + true + true + false + true + + false + true + SelfService + + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + true + true + 0 + true + false + true + string + true + true + true + picklist + true + false + true + false + false + false + + + true + true + true + false + true + false + true + 120 + true + false + false + false + false + true + false + false + false + true + true + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + true + false + false + false + false + true + false + false + true + + true + 40 + false + false + true + LanguageLocaleKey + true + false + true + false + true + false + true + false + true + + + true + true + true + false + true + + false + true + en_US + + + true + true + true + false + true + + false + true + de + + + true + true + true + false + true + + false + true + es + + + true + true + true + false + true + + false + true + fr + + + true + true + true + false + true + + false + true + it + + + true + true + true + false + true + + false + true + ja + + + true + true + true + false + true + + false + true + sv + + + true + true + true + false + true + + false + true + ko + + + true + true + true + false + true + + false + true + zh_TW + + + true + true + true + false + true + + false + true + zh_CN + + + true + true + true + false + true + + false + true + pt_BR + + + true + true + true + false + true + + false + true + nl_NL + + + true + true + true + false + true + + false + true + da + + + true + true + true + false + true + + false + true + th + + + true + true + true + false + true + + false + true + fi + + + true + true + true + false + true + + false + true + ru + + + true + true + true + false + true + + false + true + es_MX + + + true + true + true + false + true + + false + true + no + + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + true + true + 0 + true + false + true + string + true + true + true + picklist + true + false + true + true + false + false + + + true + true + true + false + true + false + true + 60 + true + false + false + false + false + true + false + false + false + true + true + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + true + false + false + false + false + true + false + false + true + + true + 20 + false + false + true + EmployeeNumber + true + false + true + false + true + true + true + false + false + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + string + true + true + true + string + true + false + true + true + false + false + + + true + true + true + false + true + false + true + 18 + true + false + false + false + false + true + false + false + false + true + true + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + true + false + false + false + false + true + false + false + true + + true + 18 + false + false + true + DelegatedApproverId + true + false + true + false + true + true + true + false + false + + true + true + true + 0 + true + false + false + true + + Group + User + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + ID + true + true + true + reference + true + false + true + true + false + false + + + true + true + true + false + true + false + true + 18 + true + false + false + false + false + true + false + false + false + true + true + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + true + false + false + false + false + true + false + false + true + + true + 18 + false + false + true + ManagerId + true + false + true + false + true + true + true + false + false + + true + false + true + 0 + true + false + false + true + + User + + true + Manager + false + 0 + false + false + true + false + true + 0 + true + false + true + ID + true + true + true + reference + true + false + true + true + false + false + + + true + true + true + false + true + false + true + 0 + true + false + false + false + false + true + false + false + false + true + false + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + false + false + false + false + false + true + false + false + true + + true + 0 + false + false + true + LastLoginDate + true + false + true + false + true + true + true + false + false + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + dateTime + true + true + true + datetime + true + false + true + false + false + false + + + true + true + true + false + true + false + true + 0 + true + false + false + false + false + true + false + false + false + true + false + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + false + false + false + false + false + true + false + false + true + + true + 0 + false + false + true + LastPasswordChangeDate + true + false + true + false + true + true + true + false + false + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + dateTime + true + true + true + datetime + true + false + true + false + false + false + + + true + true + true + false + true + false + true + 0 + true + false + false + false + false + true + false + false + false + true + false + true + false + false + false + false + false + true + true + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + false + false + false + false + false + true + false + false + true + + true + 0 + false + false + true + CreatedDate + true + false + true + false + true + false + true + false + false + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + dateTime + true + true + true + datetime + true + false + true + false + false + false + + + true + true + true + false + true + false + true + 18 + true + false + false + false + false + true + false + false + false + true + false + true + false + false + false + false + false + true + true + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + true + false + false + false + false + true + false + false + true + + true + 18 + false + false + true + CreatedById + true + false + true + false + true + false + true + false + false + + true + false + true + 0 + true + false + false + true + + User + + true + CreatedBy + false + 0 + false + false + true + false + true + 0 + true + false + true + ID + true + true + true + reference + true + false + true + false + false + false + + + true + true + true + false + true + false + true + 0 + true + false + false + false + false + true + false + false + false + true + false + true + false + false + false + false + false + true + true + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + false + false + false + false + false + true + false + false + true + + true + 0 + false + false + true + LastModifiedDate + true + false + true + false + true + false + true + false + false + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + dateTime + true + true + true + datetime + true + false + true + false + false + false + + + true + true + true + false + true + false + true + 18 + true + false + false + false + false + true + false + false + false + true + false + true + false + false + false + false + false + true + true + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + true + false + false + false + false + true + false + false + true + + true + 18 + false + false + true + LastModifiedById + true + false + true + false + true + false + true + false + false + + true + false + true + 0 + true + false + false + true + + User + + true + LastModifiedBy + false + 0 + false + false + true + false + true + 0 + true + false + true + ID + true + true + true + reference + true + false + true + false + false + false + + + true + true + true + false + true + false + true + 0 + true + false + false + false + false + true + false + false + false + true + false + true + false + false + false + false + false + true + true + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + false + false + false + false + false + true + false + false + true + + true + 0 + false + false + true + SystemModstamp + true + false + true + false + true + false + true + false + false + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + dateTime + true + true + true + datetime + true + false + true + false + false + false + + + true + true + true + false + true + false + true + 0 + true + false + false + false + false + true + false + false + false + true + false + true + false + false + false + false + false + true + false + false + false + true + false + true + 9 + false + false + false + false + false + false + false + true + true + false + false + false + true + true + false + false + false + false + true + false + false + true + + true + 0 + false + false + true + NumberOfFailedLogins + true + false + true + false + true + true + true + false + false + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + _int + true + true + true + _int + true + false + true + false + false + false + + + true + true + true + false + true + false + true + 0 + true + false + false + false + false + true + false + false + false + true + false + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + false + false + false + false + false + true + false + false + true + + true + 0 + false + false + true + OfflineTrialExpirationDate + true + false + true + false + true + true + true + false + false + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + dateTime + true + true + true + datetime + true + false + true + false + false + false + + + true + true + true + false + true + false + true + 0 + true + false + false + false + false + true + false + false + false + true + false + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + false + false + false + false + false + true + false + false + true + + true + 0 + false + false + true + OfflinePdaTrialExpirationDate + true + false + true + false + true + true + true + false + false + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + dateTime + true + true + true + datetime + true + false + true + false + false + false + + + true + false + true + false + true + false + true + 0 + true + false + false + false + false + true + false + false + false + true + true + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + false + false + false + false + false + true + false + false + true + + true + 0 + false + false + true + UserPermissionsMarketingUser + true + false + true + false + true + false + true + false + false + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + _boolean + true + false + true + _boolean + true + false + true + true + false + false + + + true + false + true + false + true + false + true + 0 + true + false + false + false + false + true + false + false + false + true + true + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + false + false + false + false + false + true + false + false + true + + true + 0 + false + false + true + UserPermissionsOfflineUser + true + false + true + false + true + false + true + false + false + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + _boolean + true + false + true + _boolean + true + false + true + true + false + false + + + true + false + true + false + true + false + true + 0 + true + false + false + false + false + true + false + false + false + true + true + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + false + false + false + false + false + true + false + false + true + + true + 0 + false + false + true + UserPermissionsAvantgoUser + true + false + true + false + true + false + true + false + false + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + _boolean + true + false + true + _boolean + true + false + true + true + false + false + + + true + false + true + false + true + false + true + 0 + true + false + false + false + false + true + false + false + false + true + true + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + false + false + false + false + false + true + false + false + true + + true + 0 + false + false + true + UserPermissionsCallCenterAutoLogin + true + false + true + false + true + false + true + false + false + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + _boolean + true + false + true + _boolean + true + false + true + true + false + false + + + true + false + true + false + true + false + true + 0 + true + false + false + false + false + true + false + false + false + true + true + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + false + false + false + false + false + true + false + false + true + + true + 0 + false + false + true + UserPermissionsSFContentUser + true + false + true + false + true + false + true + false + false + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + _boolean + true + false + true + _boolean + true + false + true + true + false + false + + + true + false + true + false + true + false + true + 0 + true + false + false + false + false + true + false + false + false + true + true + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + false + false + false + false + false + true + false + false + true + + true + 0 + false + false + true + UserPermissionsInteractionUser + true + false + true + false + true + false + true + false + false + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + _boolean + true + false + true + _boolean + true + false + true + true + false + false + + + true + false + true + false + true + false + true + 0 + true + false + false + false + false + true + false + false + false + true + true + true + false + false + false + true + false + false + true + true + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + true + false + false + false + false + true + false + false + true + + true + 0 + false + false + true + ForecastEnabled + true + false + true + false + true + false + true + false + false + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + _boolean + true + true + true + _boolean + true + false + true + true + false + false + + + true + false + true + false + true + false + true + 0 + true + false + false + false + false + true + false + false + false + true + true + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + false + false + false + false + false + true + false + false + true + + true + 0 + false + false + true + UserPreferencesActivityRemindersPopup + true + false + true + false + true + false + true + false + false + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + _boolean + true + false + true + _boolean + true + false + true + true + false + false + + + true + false + true + false + true + false + true + 0 + true + false + false + false + false + true + false + false + false + true + true + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + false + false + false + false + false + true + false + false + true + + true + 0 + false + false + true + UserPreferencesEventRemindersCheckboxDefault + true + false + true + false + true + false + true + false + false + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + _boolean + true + false + true + _boolean + true + false + true + true + false + false + + + true + false + true + false + true + false + true + 0 + true + false + false + false + false + true + false + false + false + true + true + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + false + false + false + false + false + true + false + false + true + + true + 0 + false + false + true + UserPreferencesTaskRemindersCheckboxDefault + true + false + true + false + true + false + true + false + false + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + _boolean + true + false + true + _boolean + true + false + true + true + false + false + + + true + false + true + false + true + false + true + 0 + true + false + false + false + false + true + false + false + false + true + true + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + false + false + false + false + false + true + false + false + true + + true + 0 + false + false + true + UserPreferencesReminderSoundOff + true + false + true + false + true + false + true + false + false + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + _boolean + true + false + true + _boolean + true + false + true + true + false + false + + + true + false + true + false + true + false + true + 0 + true + false + false + false + false + true + false + false + false + true + true + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + false + false + false + false + false + true + false + false + true + + true + 0 + false + false + true + UserPreferencesDisableAllFeedsEmail + true + false + true + false + true + false + true + false + false + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + _boolean + true + false + true + _boolean + true + false + true + true + false + false + + + true + false + true + false + true + false + true + 0 + true + false + false + false + false + true + false + false + false + true + true + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + false + false + false + false + false + true + false + false + true + + true + 0 + false + false + true + UserPreferencesDisableFollowersEmail + true + false + true + false + true + false + true + false + false + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + _boolean + true + false + true + _boolean + true + false + true + true + false + false + + + true + false + true + false + true + false + true + 0 + true + false + false + false + false + true + false + false + false + true + true + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + false + false + false + false + false + true + false + false + true + + true + 0 + false + false + true + UserPreferencesDisableProfilePostEmail + true + false + true + false + true + false + true + false + false + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + _boolean + true + false + true + _boolean + true + false + true + true + false + false + + + true + false + true + false + true + false + true + 0 + true + false + false + false + false + true + false + false + false + true + true + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + false + false + false + false + false + true + false + false + true + + true + 0 + false + false + true + UserPreferencesDisableChangeCommentEmail + true + false + true + false + true + false + true + false + false + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + _boolean + true + false + true + _boolean + true + false + true + true + false + false + + + true + false + true + false + true + false + true + 0 + true + false + false + false + false + true + false + false + false + true + true + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + false + false + false + false + false + true + false + false + true + + true + 0 + false + false + true + UserPreferencesDisableLaterCommentEmail + true + false + true + false + true + false + true + false + false + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + _boolean + true + false + true + _boolean + true + false + true + true + false + false + + + true + false + true + false + true + false + true + 0 + true + false + false + false + false + true + false + false + false + true + true + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + false + false + false + false + false + true + false + false + true + + true + 0 + false + false + true + UserPreferencesDisProfPostCommentEmail + true + false + true + false + true + false + true + false + false + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + _boolean + true + false + true + _boolean + true + false + true + true + false + false + + + true + false + true + false + true + false + true + 0 + true + false + false + false + false + true + false + false + false + true + true + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + false + false + false + false + false + true + false + false + true + + true + 0 + false + false + true + UserPreferencesContentNoEmail + true + false + true + false + true + false + true + false + false + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + _boolean + true + false + true + _boolean + true + false + true + true + false + false + + + true + false + true + false + true + false + true + 0 + true + false + false + false + false + true + false + false + false + true + true + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + false + false + false + false + false + true + false + false + true + + true + 0 + false + false + true + UserPreferencesContentEmailAsAndWhen + true + false + true + false + true + false + true + false + false + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + _boolean + true + false + true + _boolean + true + false + true + true + false + false + + + true + false + true + false + true + false + true + 0 + true + false + false + false + false + true + false + false + false + true + true + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + false + false + false + false + false + true + false + false + true + + true + 0 + false + false + true + UserPreferencesApexPagesDeveloperMode + true + false + true + false + true + false + true + false + false + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + _boolean + true + false + true + _boolean + true + false + true + true + false + false + + + true + false + true + false + true + false + true + 0 + true + false + false + false + false + true + false + false + false + true + true + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + false + false + false + false + false + true + false + false + true + + true + 0 + false + false + true + UserPreferencesReceiveNoNotificationsAsApprover + true + false + true + false + true + false + true + false + false + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + _boolean + true + false + true + _boolean + true + false + true + true + false + false + + + true + false + true + false + true + false + true + 0 + true + false + false + false + false + true + false + false + false + true + true + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + false + false + false + false + false + true + false + false + true + + true + 0 + false + false + true + UserPreferencesReceiveNotificationsAsDelegatedApprover + true + false + true + false + true + false + true + false + false + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + _boolean + true + false + true + _boolean + true + false + true + true + false + false + + + true + false + true + false + true + false + true + 0 + true + false + false + false + false + true + false + false + false + true + true + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + false + false + false + false + false + true + false + false + true + + true + 0 + false + false + true + UserPreferencesHideCSNGetChatterMobileTask + true + false + true + false + true + false + true + false + false + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + _boolean + true + false + true + _boolean + true + false + true + true + false + false + + + true + false + true + false + true + false + true + 0 + true + false + false + false + false + true + false + false + false + true + true + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + false + false + false + false + false + true + false + false + true + + true + 0 + false + false + true + UserPreferencesDisableMentionsPostEmail + true + false + true + false + true + false + true + false + false + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + _boolean + true + false + true + _boolean + true + false + true + true + false + false + + + true + false + true + false + true + false + true + 0 + true + false + false + false + false + true + false + false + false + true + true + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + false + false + false + false + false + true + false + false + true + + true + 0 + false + false + true + UserPreferencesDisMentionsCommentEmail + true + false + true + false + true + false + true + false + false + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + _boolean + true + false + true + _boolean + true + false + true + true + false + false + + + true + false + true + false + true + false + true + 0 + true + false + false + false + false + true + false + false + false + true + true + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + false + false + false + false + false + true + false + false + true + + true + 0 + false + false + true + UserPreferencesHideCSNDesktopTask + true + false + true + false + true + false + true + false + false + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + _boolean + true + false + true + _boolean + true + false + true + true + false + false + + + true + false + true + false + true + false + true + 0 + true + false + false + false + false + true + false + false + false + true + true + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + false + false + false + false + false + true + false + false + true + + true + 0 + false + false + true + UserPreferencesHideChatterOnboardingSplash + true + false + true + false + true + false + true + false + false + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + _boolean + true + false + true + _boolean + true + false + true + true + false + false + + + true + false + true + false + true + false + true + 0 + true + false + false + false + false + true + false + false + false + true + true + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + false + false + false + false + false + true + false + false + true + + true + 0 + false + false + true + UserPreferencesHideSecondChatterOnboardingSplash + true + false + true + false + true + false + true + false + false + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + _boolean + true + false + true + _boolean + true + false + true + true + false + false + + + true + false + true + false + true + false + true + 0 + true + false + false + false + false + true + false + false + false + true + true + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + false + false + false + false + false + true + false + false + true + + true + 0 + false + false + true + UserPreferencesDisCommentAfterLikeEmail + true + false + true + false + true + false + true + false + false + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + _boolean + true + false + true + _boolean + true + false + true + true + false + false + + + true + false + true + false + true + false + true + 0 + true + false + false + false + false + true + false + false + false + true + true + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + false + false + false + false + false + true + false + false + true + + true + 0 + false + false + true + UserPreferencesDisableLikeEmail + true + false + true + false + true + false + true + false + false + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + _boolean + true + false + true + _boolean + true + false + true + true + false + false + + + true + false + true + false + true + false + true + 0 + true + false + false + false + false + true + false + false + false + true + true + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + false + false + false + false + false + true + false + false + true + + true + 0 + false + false + true + UserPreferencesSortFeedByComment + true + false + true + false + true + false + true + false + false + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + _boolean + true + false + true + _boolean + true + false + true + true + false + false + + + true + false + true + false + true + false + true + 0 + true + false + false + false + false + true + false + false + false + true + true + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + false + false + false + false + false + true + false + false + true + + true + 0 + false + false + true + UserPreferencesDisableMessageEmail + true + false + true + false + true + false + true + false + false + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + _boolean + true + false + true + _boolean + true + false + true + true + false + false + + + true + false + true + false + true + false + true + 0 + true + false + false + false + false + true + false + false + false + true + true + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + false + false + false + false + false + true + false + false + true + + true + 0 + false + false + true + UserPreferencesDisableBookmarkEmail + true + false + true + false + true + false + true + false + false + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + _boolean + true + false + true + _boolean + true + false + true + true + false + false + + + true + false + true + false + true + false + true + 0 + true + false + false + false + false + true + false + false + false + true + true + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + false + false + false + false + false + true + false + false + true + + true + 0 + false + false + true + UserPreferencesDisableSharePostEmail + true + false + true + false + true + false + true + false + false + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + _boolean + true + false + true + _boolean + true + false + true + true + false + false + + + true + false + true + false + true + false + true + 0 + true + false + false + false + false + true + false + false + false + true + true + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + false + false + false + false + false + true + false + false + true + + true + 0 + false + false + true + UserPreferencesEnableAutoSubForFeeds + true + false + true + false + true + false + true + false + false + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + _boolean + true + false + true + _boolean + true + false + true + true + false + false + + + true + false + true + false + true + false + true + 0 + true + false + false + false + false + true + false + false + false + true + true + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + false + false + false + false + false + true + false + false + true + + true + 0 + false + false + true + UserPreferencesDisableFileShareNotificationsForApi + true + false + true + false + true + false + true + false + false + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + _boolean + true + false + true + _boolean + true + false + true + true + false + false + + + true + false + true + false + true + false + true + 0 + true + false + false + false + false + true + false + false + false + true + true + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + false + false + false + false + false + true + false + false + true + + true + 0 + false + false + true + UserPreferencesShowTitleToExternalUsers + true + false + true + false + true + false + true + false + false + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + _boolean + true + false + true + _boolean + true + false + true + true + false + false + + + true + false + true + false + true + false + true + 0 + true + false + false + false + false + true + false + false + false + true + true + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + false + false + false + false + false + true + false + false + true + + true + 0 + false + false + true + UserPreferencesShowManagerToExternalUsers + true + false + true + false + true + false + true + false + false + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + _boolean + true + false + true + _boolean + true + false + true + true + false + false + + + true + false + true + false + true + false + true + 0 + true + false + false + false + false + true + false + false + false + true + true + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + false + false + false + false + false + true + false + false + true + + true + 0 + false + false + true + UserPreferencesShowEmailToExternalUsers + true + false + true + false + true + false + true + false + false + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + _boolean + true + false + true + _boolean + true + false + true + true + false + false + + + true + false + true + false + true + false + true + 0 + true + false + false + false + false + true + false + false + false + true + true + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + false + false + false + false + false + true + false + false + true + + true + 0 + false + false + true + UserPreferencesShowWorkPhoneToExternalUsers + true + false + true + false + true + false + true + false + false + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + _boolean + true + false + true + _boolean + true + false + true + true + false + false + + + true + false + true + false + true + false + true + 0 + true + false + false + false + false + true + false + false + false + true + true + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + false + false + false + false + false + true + false + false + true + + true + 0 + false + false + true + UserPreferencesShowMobilePhoneToExternalUsers + true + false + true + false + true + false + true + false + false + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + _boolean + true + false + true + _boolean + true + false + true + true + false + false + + + true + false + true + false + true + false + true + 0 + true + false + false + false + false + true + false + false + false + true + true + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + false + false + false + false + false + true + false + false + true + + true + 0 + false + false + true + UserPreferencesShowFaxToExternalUsers + true + false + true + false + true + false + true + false + false + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + _boolean + true + false + true + _boolean + true + false + true + true + false + false + + + true + false + true + false + true + false + true + 0 + true + false + false + false + false + true + false + false + false + true + true + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + false + false + false + false + false + true + false + false + true + + true + 0 + false + false + true + UserPreferencesShowStreetAddressToExternalUsers + true + false + true + false + true + false + true + false + false + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + _boolean + true + false + true + _boolean + true + false + true + true + false + false + + + true + false + true + false + true + false + true + 0 + true + false + false + false + false + true + false + false + false + true + true + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + false + false + false + false + false + true + false + false + true + + true + 0 + false + false + true + UserPreferencesShowCityToExternalUsers + true + false + true + false + true + false + true + false + false + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + _boolean + true + false + true + _boolean + true + false + true + true + false + false + + + true + false + true + false + true + false + true + 0 + true + false + false + false + false + true + false + false + false + true + true + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + false + false + false + false + false + true + false + false + true + + true + 0 + false + false + true + UserPreferencesShowStateToExternalUsers + true + false + true + false + true + false + true + false + false + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + _boolean + true + false + true + _boolean + true + false + true + true + false + false + + + true + false + true + false + true + false + true + 0 + true + false + false + false + false + true + false + false + false + true + true + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + false + false + false + false + false + true + false + false + true + + true + 0 + false + false + true + UserPreferencesShowPostalCodeToExternalUsers + true + false + true + false + true + false + true + false + false + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + _boolean + true + false + true + _boolean + true + false + true + true + false + false + + + true + false + true + false + true + false + true + 0 + true + false + false + false + false + true + false + false + false + true + true + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + false + false + false + false + false + true + false + false + true + + true + 0 + false + false + true + UserPreferencesShowCountryToExternalUsers + true + false + true + false + true + false + true + false + false + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + _boolean + true + false + true + _boolean + true + false + true + true + false + false + + + true + false + true + false + true + false + true + 0 + true + false + false + false + false + true + false + false + false + true + true + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + false + false + false + false + false + true + false + false + true + + true + 0 + false + false + true + UserPreferencesShowProfilePicToGuestUsers + true + false + true + false + true + false + true + false + false + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + _boolean + true + false + true + _boolean + true + false + true + true + false + false + + + true + false + true + false + true + false + true + 0 + true + false + false + false + false + true + false + false + false + true + true + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + false + false + false + false + false + true + false + false + true + + true + 0 + false + false + true + UserPreferencesShowTitleToGuestUsers + true + false + true + false + true + false + true + false + false + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + _boolean + true + false + true + _boolean + true + false + true + true + false + false + + + true + false + true + false + true + false + true + 0 + true + false + false + false + false + true + false + false + false + true + true + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + false + false + false + false + false + true + false + false + true + + true + 0 + false + false + true + UserPreferencesShowCityToGuestUsers + true + false + true + false + true + false + true + false + false + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + _boolean + true + false + true + _boolean + true + false + true + true + false + false + + + true + false + true + false + true + false + true + 0 + true + false + false + false + false + true + false + false + false + true + true + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + false + false + false + false + false + true + false + false + true + + true + 0 + false + false + true + UserPreferencesShowStateToGuestUsers + true + false + true + false + true + false + true + false + false + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + _boolean + true + false + true + _boolean + true + false + true + true + false + false + + + true + false + true + false + true + false + true + 0 + true + false + false + false + false + true + false + false + false + true + true + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + false + false + false + false + false + true + false + false + true + + true + 0 + false + false + true + UserPreferencesShowPostalCodeToGuestUsers + true + false + true + false + true + false + true + false + false + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + _boolean + true + false + true + _boolean + true + false + true + true + false + false + + + true + false + true + false + true + false + true + 0 + true + false + false + false + false + true + false + false + false + true + true + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + false + false + false + false + false + true + false + false + true + + true + 0 + false + false + true + UserPreferencesShowCountryToGuestUsers + true + false + true + false + true + false + true + false + false + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + _boolean + true + false + true + _boolean + true + false + true + true + false + false + + + true + false + true + false + true + false + true + 0 + true + false + false + false + false + true + false + false + false + true + true + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + false + false + false + false + false + true + false + false + true + + true + 0 + false + false + true + UserPreferencesHideS1BrowserUI + true + false + true + false + true + false + true + false + false + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + _boolean + true + false + true + _boolean + true + false + true + true + false + false + + + true + false + true + false + true + false + true + 0 + true + false + false + false + false + true + false + false + false + true + true + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + false + false + false + false + false + true + false + false + true + + true + 0 + false + false + true + UserPreferencesDisableEndorsementEmail + true + false + true + false + true + false + true + false + false + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + _boolean + true + false + true + _boolean + true + false + true + true + false + false + + + true + false + true + false + true + false + true + 0 + true + false + false + false + false + true + false + false + false + true + true + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + false + false + false + false + false + true + false + false + true + + true + 0 + false + false + true + UserPreferencesPathAssistantCollapsed + true + false + true + false + true + false + true + false + false + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + _boolean + true + false + true + _boolean + true + false + true + true + false + false + + + true + false + true + false + true + false + true + 0 + true + false + false + false + false + true + false + false + false + true + true + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + false + false + false + false + false + true + false + false + true + + true + 0 + false + false + true + UserPreferencesCacheDiagnostics + true + false + true + false + true + false + true + false + false + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + _boolean + true + false + true + _boolean + true + false + true + true + false + false + + + true + false + true + false + true + false + true + 0 + true + false + false + false + false + true + false + false + false + true + true + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + false + false + false + false + false + true + false + false + true + + true + 0 + false + false + true + UserPreferencesShowEmailToGuestUsers + true + false + true + false + true + false + true + false + false + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + _boolean + true + false + true + _boolean + true + false + true + true + false + false + + + true + false + true + false + true + false + true + 0 + true + false + false + false + false + true + false + false + false + true + true + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + false + false + false + false + false + true + false + false + true + + true + 0 + false + false + true + UserPreferencesShowManagerToGuestUsers + true + false + true + false + true + false + true + false + false + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + _boolean + true + false + true + _boolean + true + false + true + true + false + false + + + true + false + true + false + true + false + true + 0 + true + false + false + false + false + true + false + false + false + true + true + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + false + false + false + false + false + true + false + false + true + + true + 0 + false + false + true + UserPreferencesShowWorkPhoneToGuestUsers + true + false + true + false + true + false + true + false + false + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + _boolean + true + false + true + _boolean + true + false + true + true + false + false + + + true + false + true + false + true + false + true + 0 + true + false + false + false + false + true + false + false + false + true + true + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + false + false + false + false + false + true + false + false + true + + true + 0 + false + false + true + UserPreferencesShowMobilePhoneToGuestUsers + true + false + true + false + true + false + true + false + false + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + _boolean + true + false + true + _boolean + true + false + true + true + false + false + + + true + false + true + false + true + false + true + 0 + true + false + false + false + false + true + false + false + false + true + true + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + false + false + false + false + false + true + false + false + true + + true + 0 + false + false + true + UserPreferencesShowFaxToGuestUsers + true + false + true + false + true + false + true + false + false + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + _boolean + true + false + true + _boolean + true + false + true + true + false + false + + + true + false + true + false + true + false + true + 0 + true + false + false + false + false + true + false + false + false + true + true + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + false + false + false + false + false + true + false + false + true + + true + 0 + false + false + true + UserPreferencesShowStreetAddressToGuestUsers + true + false + true + false + true + false + true + false + false + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + _boolean + true + false + true + _boolean + true + false + true + true + false + false + + + true + false + true + false + true + false + true + 0 + true + false + false + false + false + true + false + false + false + true + true + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + false + false + false + false + false + true + false + false + true + + true + 0 + false + false + true + UserPreferencesLightningExperiencePreferred + true + false + true + false + true + false + true + false + false + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + _boolean + true + false + true + _boolean + true + false + true + true + false + false + + + true + false + true + false + true + false + true + 0 + true + false + false + false + false + true + false + false + false + true + true + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + false + false + false + false + false + true + false + false + true + + true + 0 + false + false + true + UserPreferencesPreviewLightning + true + false + true + false + true + false + true + false + false + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + _boolean + true + false + true + _boolean + true + false + true + true + false + false + + + true + false + true + false + true + false + true + 0 + true + false + false + false + false + true + false + false + false + true + true + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + false + false + false + false + false + true + false + false + true + + true + 0 + false + false + true + UserPreferencesHideEndUserOnboardingAssistantModal + true + false + true + false + true + false + true + false + false + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + _boolean + true + false + true + _boolean + true + false + true + true + false + false + + + true + false + true + false + true + false + true + 0 + true + false + false + false + false + true + false + false + false + true + true + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + false + false + false + false + false + true + false + false + true + + true + 0 + false + false + true + UserPreferencesHideLightningMigrationModal + true + false + true + false + true + false + true + false + false + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + _boolean + true + false + true + _boolean + true + false + true + true + false + false + + + true + false + true + false + true + false + true + 0 + true + false + false + false + false + true + false + false + false + true + true + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + false + false + false + false + false + true + false + false + true + + true + 0 + false + false + true + UserPreferencesHideSfxWelcomeMat + true + false + true + false + true + false + true + false + false + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + _boolean + true + false + true + _boolean + true + false + true + true + false + false + + + true + false + true + false + true + false + true + 0 + true + false + false + false + false + true + false + false + false + true + true + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + false + false + false + false + false + true + false + false + true + + true + 0 + false + false + true + UserPreferencesHideBiggerPhotoCallout + true + false + true + false + true + false + true + false + false + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + _boolean + true + false + true + _boolean + true + false + true + true + false + false + + + true + false + true + false + true + false + true + 0 + true + false + false + false + false + true + false + false + false + true + true + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + false + false + false + false + false + true + false + false + true + + true + 0 + false + false + true + UserPreferencesAutoLogCallAsTask + true + false + true + false + true + false + true + false + false + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + _boolean + true + false + true + _boolean + true + false + true + true + false + false + + + true + false + true + false + true + false + true + 0 + true + false + false + false + false + true + false + false + false + true + true + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + false + false + false + false + false + true + false + false + true + + true + 0 + false + false + true + UserPreferencesGlobalNavBarWTShown + true + false + true + false + true + false + true + false + false + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + _boolean + true + false + true + _boolean + true + false + true + true + false + false + + + true + false + true + false + true + false + true + 0 + true + false + false + false + false + true + false + false + false + true + true + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + false + false + false + false + false + true + false + false + true + + true + 0 + false + false + true + UserPreferencesGlobalNavGridMenuWTShown + true + false + true + false + true + false + true + false + false + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + _boolean + true + false + true + _boolean + true + false + true + true + false + false + + + true + false + true + false + true + false + true + 0 + true + false + false + false + false + true + false + false + false + true + true + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + false + false + false + false + false + true + false + false + true + + true + 0 + false + false + true + UserPreferencesCreateLEXAppsWTShown + true + false + true + false + true + false + true + false + false + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + _boolean + true + false + true + _boolean + true + false + true + true + false + false + + + true + false + true + false + true + false + true + 0 + true + false + false + false + false + true + false + false + false + true + true + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + false + false + false + false + false + true + false + false + true + + true + 0 + false + false + true + UserPreferencesFavoritesWTShown + true + false + true + false + true + false + true + false + false + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + _boolean + true + false + true + _boolean + true + false + true + true + false + false + + + true + false + true + false + true + false + true + 0 + true + false + false + false + false + true + false + false + false + true + true + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + false + false + false + false + false + true + false + false + true + + true + 0 + false + false + true + UserPreferencesRecordHomeSectionCollapseWTShown + true + false + true + false + true + false + true + false + false + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + _boolean + true + false + true + _boolean + true + false + true + true + false + false + + + true + false + true + false + true + false + true + 0 + true + false + false + false + false + true + false + false + false + true + true + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + false + false + false + false + false + true + false + false + true + + true + 0 + false + false + true + UserPreferencesRecordHomeReservedWTShown + true + false + true + false + true + false + true + false + false + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + _boolean + true + false + true + _boolean + true + false + true + true + false + false + + + true + false + true + false + true + false + true + 0 + true + false + false + false + false + true + false + false + false + true + true + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + false + false + false + false + false + true + false + false + true + + true + 0 + false + false + true + UserPreferencesFavoritesShowTopFavorites + true + false + true + false + true + false + true + false + false + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + _boolean + true + false + true + _boolean + true + false + true + true + false + false + + + true + false + true + false + true + false + true + 0 + true + false + false + false + false + true + false + false + false + true + true + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + false + false + false + false + false + true + false + false + true + + true + 0 + false + false + true + UserPreferencesExcludeMailAppAttachments + true + false + true + false + true + false + true + false + false + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + _boolean + true + false + true + _boolean + true + false + true + true + false + false + + + true + false + true + false + true + false + true + 0 + true + false + false + false + false + true + false + false + false + true + true + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + false + false + false + false + false + true + false + false + true + + true + 0 + false + false + true + UserPreferencesSuppressTaskSFXReminders + true + false + true + false + true + false + true + false + false + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + _boolean + true + false + true + _boolean + true + false + true + true + false + false + + + true + false + true + false + true + false + true + 0 + true + false + false + false + false + true + false + false + false + true + true + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + false + false + false + false + false + true + false + false + true + + true + 0 + false + false + true + UserPreferencesSuppressEventSFXReminders + true + false + true + false + true + false + true + false + false + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + _boolean + true + false + true + _boolean + true + false + true + true + false + false + + + true + false + true + false + true + false + true + 0 + true + false + false + false + false + true + false + false + false + true + true + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + false + false + false + false + false + true + false + false + true + + true + 0 + false + false + true + UserPreferencesPreviewCustomTheme + true + false + true + false + true + false + true + false + false + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + _boolean + true + false + true + _boolean + true + false + true + true + false + false + + + true + false + true + false + true + false + true + 0 + true + false + false + false + false + true + false + false + false + true + true + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + false + false + false + false + false + true + false + false + true + + true + 0 + false + false + true + UserPreferencesHasCelebrationBadge + true + false + true + false + true + false + true + false + false + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + _boolean + true + false + true + _boolean + true + false + true + true + false + false + + + true + false + true + false + true + false + true + 0 + true + false + false + false + false + true + false + false + false + true + true + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + false + false + false + false + false + true + false + false + true + + true + 0 + false + false + true + UserPreferencesUserDebugModePref + true + false + true + false + true + false + true + false + false + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + _boolean + true + false + true + _boolean + true + false + true + true + false + false + + + true + false + true + false + true + false + true + 0 + true + false + false + false + false + true + false + false + false + true + true + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + false + false + false + false + false + true + false + false + true + + true + 0 + false + false + true + UserPreferencesSRHOverrideActivities + true + false + true + false + true + false + true + false + false + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + _boolean + true + false + true + _boolean + true + false + true + true + false + false + + + true + false + true + false + true + false + true + 0 + true + false + false + false + false + true + false + false + false + true + true + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + false + false + false + false + false + true + false + false + true + + true + 0 + false + false + true + UserPreferencesNewLightningReportRunPageEnabled + true + false + true + false + true + false + true + false + false + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + _boolean + true + false + true + _boolean + true + false + true + true + false + false + + + true + false + true + false + true + false + true + 0 + true + false + false + false + false + true + false + false + false + true + true + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + false + false + false + false + false + true + false + false + true + + true + 0 + false + false + true + UserPreferencesNativeEmailClient + true + false + true + false + true + false + true + false + false + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + _boolean + true + false + true + _boolean + true + false + true + true + false + false + + + true + false + true + false + true + false + true + 0 + true + false + false + false + false + true + false + false + false + true + true + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + false + false + false + false + false + true + false + false + true + + true + 0 + false + false + true + UserPreferencesUseSalesforceMailerForLexEmail + true + false + true + false + true + false + true + false + false + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + _boolean + true + false + true + _boolean + true + false + true + true + false + false + + + true + true + true + false + true + false + true + 18 + true + false + false + false + false + true + false + false + false + true + true + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + true + false + false + false + false + true + false + false + true + + true + 18 + false + false + true + ContactId + true + false + true + false + true + true + true + false + false + + true + false + true + 0 + true + false + false + true + + Contact + + true + Contact + false + 0 + false + false + true + false + true + 0 + true + false + true + ID + true + true + true + reference + true + false + true + true + false + false + + + true + true + true + false + true + false + true + 18 + true + false + false + false + false + true + false + false + false + true + false + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + true + false + false + false + false + true + false + false + true + + true + 18 + false + false + true + AccountId + true + false + true + false + true + true + true + false + false + + true + false + true + 0 + true + false + false + true + + Account + + true + Account + false + 0 + false + false + true + false + true + 0 + true + false + true + ID + true + true + true + reference + true + false + true + false + false + false + + + true + true + true + false + true + false + true + 18 + true + false + false + false + false + true + false + false + false + true + true + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + true + false + false + false + false + true + false + false + true + + true + 18 + false + false + true + CallCenterId + true + false + true + false + true + true + true + false + false + + true + false + true + 0 + true + false + false + true + + CallCenter + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + ID + true + true + true + reference + true + false + true + true + false + false + + + true + true + true + false + true + false + true + 120 + true + false + false + false + false + true + false + false + false + true + true + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + true + false + false + false + false + true + false + false + true + + true + 40 + false + false + true + Extension + true + false + true + false + true + true + true + false + false + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + string + true + true + true + phone + true + false + true + true + false + false + + + true + true + true + false + true + false + true + 1536 + true + false + false + false + false + true + false + false + false + true + true + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + false + false + false + false + false + true + true + false + true + + true + 512 + false + false + true + FederationIdentifier + true + false + true + false + true + true + true + false + false + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + string + true + true + true + string + true + false + true + true + false + false + + + true + true + true + false + true + false + true + 3000 + true + false + false + false + false + true + false + false + false + true + true + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + true + plaintextarea + true + true + false + false + false + true + false + false + false + false + false + true + false + false + true + + true + 1000 + false + false + true + AboutMe + true + false + true + false + true + true + true + false + false + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + string + true + true + true + textarea + true + false + true + true + false + false + + + true + true + true + false + true + false + true + 3072 + true + false + false + false + false + true + false + false + false + true + false + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + false + false + false + false + false + true + false + false + true + + true + 1024 + false + false + true + FullPhotoUrl + true + false + true + false + true + true + true + false + false + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + string + true + true + true + url + true + false + true + false + false + false + + + true + true + true + false + true + false + true + 3072 + true + false + false + false + false + true + false + false + false + true + false + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + true + imageurl + true + true + false + false + false + true + false + false + false + false + false + true + false + false + true + + true + 1024 + false + false + true + SmallPhotoUrl + true + false + true + false + true + true + true + false + false + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + string + true + true + true + url + true + false + true + false + false + false + + + true + false + true + false + true + false + true + 0 + true + false + false + false + false + true + false + false + false + true + false + true + false + false + false + true + false + false + true + true + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + true + false + false + false + false + true + false + false + true + + true + 0 + false + false + true + IsExtIndicatorVisible + true + false + true + false + true + false + true + false + false + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + _boolean + true + true + true + _boolean + true + false + true + false + false + false + + + true + false + true + false + true + false + true + 120 + true + false + false + false + false + true + false + false + false + true + false + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + true + false + false + false + false + true + false + false + true + + true + 40 + false + false + true + OutOfOfficeMessage + true + false + true + false + true + true + true + false + false + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + string + true + true + true + string + true + false + true + false + false + false + + + true + true + true + false + true + false + true + 3072 + true + false + false + false + false + true + false + false + false + true + false + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + true + imageurl + true + true + false + false + false + true + false + false + false + false + false + true + false + false + true + + true + 1024 + false + false + true + MediumPhotoUrl + true + false + true + false + true + true + true + false + false + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + string + true + true + true + url + true + false + true + false + false + false + + + true + true + true + false + true + false + true + 120 + true + false + false + false + false + true + false + false + false + true + true + true + false + false + false + true + N + false + true + true + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + true + false + false + false + false + true + false + false + true + + true + 40 + false + false + true + DigestFrequency + true + false + true + false + true + false + true + false + true + + + true + true + true + false + true + + false + true + D + + + true + true + true + false + true + + false + true + W + + + true + true + true + true + true + + false + true + N + + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + true + true + 0 + true + false + true + string + true + true + true + picklist + true + false + true + true + false + false + + + true + true + true + false + true + false + true + 120 + true + false + false + false + false + true + false + false + false + true + true + true + false + false + false + true + N + false + true + true + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + true + false + false + false + false + true + false + false + true + + true + 40 + false + false + true + DefaultGroupNotificationFrequency + true + false + true + false + true + false + true + false + true + + + true + true + true + false + true + + false + true + P + + + true + true + true + false + true + + false + true + D + + + true + true + true + false + true + + false + true + W + + + true + true + true + true + true + + false + true + N + + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + true + true + 0 + true + false + true + string + true + true + true + picklist + true + false + true + true + false + false + + + true + true + true + false + true + false + true + 0 + true + false + false + false + false + true + false + false + false + true + false + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + false + false + false + false + false + true + false + false + true + + true + 0 + false + false + true + LastViewedDate + true + false + true + false + true + true + true + false + false + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + dateTime + true + true + true + datetime + true + false + true + false + false + false + + + true + true + true + false + true + false + true + 0 + true + false + false + false + false + true + false + false + false + true + false + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + false + false + false + false + false + true + false + false + true + + true + 0 + false + false + true + LastReferencedDate + true + false + true + false + true + true + true + false + false + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + dateTime + true + true + true + datetime + true + false + true + false + false + false + + + true + true + true + false + true + false + true + 3072 + true + false + false + false + false + true + false + false + false + true + false + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + false + false + false + false + false + true + false + false + true + + true + 1024 + false + false + true + BannerPhotoUrl + true + false + true + false + true + true + true + false + false + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + string + true + true + true + url + true + false + true + false + false + false + + + true + true + true + false + true + false + true + 3072 + true + false + false + false + false + true + false + false + false + true + false + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + false + false + false + false + false + true + false + false + true + + true + 1024 + false + false + true + SmallBannerPhotoUrl + true + false + true + false + true + true + true + false + false + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + string + true + true + true + url + true + false + true + false + false + false + + + true + true + true + false + true + false + true + 3072 + true + false + false + false + false + true + false + false + false + true + false + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + false + false + false + false + false + true + false + false + true + + true + 1024 + false + false + true + MediumBannerPhotoUrl + true + false + true + false + true + true + true + false + false + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + string + true + true + true + url + true + false + true + false + false + false + + + true + false + true + false + true + false + true + 0 + true + false + false + false + false + true + false + false + false + true + false + true + false + false + false + true + false + false + true + true + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + true + false + false + false + false + true + false + false + true + + true + 0 + false + false + true + IsProfilePhotoActive + true + false + true + false + true + false + true + false + false + + true + false + true + 0 + true + false + false + false + + false + false + 0 + false + false + true + false + true + 0 + true + false + true + _boolean + true + true + true + _boolean + true + false + true + false + false + false + + + true + true + true + false + true + false + true + 18 + true + false + false + false + false + true + false + false + false + true + true + true + false + false + false + false + false + true + false + false + false + true + false + true + 0 + false + false + false + false + false + false + false + true + true + false + false + false + true + true + false + false + false + false + true + false + false + true + + true + 18 + false + false + true + IndividualId + true + false + true + false + true + true + true + false + false + + true + false + true + 0 + true + false + false + true + + Individual + + true + Individual + false + 0 + false + false + true + false + true + 0 + true + false + true + ID + true + true + true + reference + true + false + true + true + false + false + + + true + false + true + true + true + true + true + false + true + false + true + 005 + true + + true + Users + true + true + false + false + false + false + true + false + true + true + true + User + true + + + true + UserAlt + + + true + true + true + false + + true + true + true + true + true + true + true + true + true + + + true + + true + everything + + + true + true + true + false + true + true + true + http://localorg.localhost.internal.salesforce.com:6109/{ID} + true + http://localorg.localhost.internal.salesforce.com:6109/{ID}/e + true + http://localorg.localhost.internal.salesforce.com:6109/005/e +