All pages
1 of 81

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Salesforce OAuth Login Types

CapStorm applications connect to Salesforce using several supported OAuth login types. This section covers the available options:

  • JWT

  • Client Credentials

  • Username-Password

Each flow offers a different approach to authentication depending on how your Salesforce org is configured.

Why Are CaseMilestone Fields / Salesforce Formulas Not Updating?

CaseMilestone is an example of a Salesforce table that contains formula columns whose values may change even when other fields of a CaseMilestone record do not change. In fact, the CaseMilestone table contains both types of Salesforce formula columns difficult to include in an incremental backup:

  1. A formula field whose value changes when the value in another record (in the same table or a different table) changes.

  2. A formula field whose value is computed using the current date or time.

To identify Salesforce formulas in a Salesforce standard table look for non-reference field columns where the API does not have update access. Knowing whether a formula field value will change even when the corresponding fields in the record do not change is a bit more difficult.

Fixing The Problem

The solution to this problem is to periodically run the CopyStorm/Medic Refresh Columns tool to bring the problem formula columns back in sync with Salesforce.

The following table lists Salesforce defined formula fields that are known to have the issue described above:

Table
Problem Formula Fields

OAuth Client Credentials Login

To connect to Salesforce using the OAUTH CLIENT CREDENTIALS flow, CopyStorm can be configured with:

  1. The OAuth Client ID

  2. The OAuth Client Secret

OAuth Client Credentials can be enabled in Salesforce by following this tutorial.

OAuth Client Credential logins can be enabled in CopyStorm by navigating to the Advanced Parameters dialog on the Main tab:

After selecting the OAuth 2.0 Client Credentials login type, provide the credentials needed to authenticate with Salesforce:

Parameter Name
Description

OAuth Username-Password Login

To connect to Salesforce using the OAUTH CLIENT CREDENTIALS flow, CopyStorm can be configured with:

  1. OAuth Client ID

  2. OAuth Client Secret

  3. Username

  4. Password

OAuth Client Credentials can be enabled in Salesforce by following .

OAuth Client Credential logins can be enabled in CopyStorm by navigating to the Advanced Parameters dialog on the Main tab:

After selecting the OAuth 2.0 Username-Password login type, provide the credentials needed to authenticate with Salesforce:

Parameter Name
Description

Connect to S3 With Permanent AWS Credentials

When connecting to S3, by default, CapStorm applications will:

  1. Read Permanent Credentials provided using the AWS Provider Chain

  2. Use these credentials to request temporary session credentials via the AWS STS (Security Token Service).

  3. Periodically refresh the temporary credentials for continued access.

This approach minimizes the use of permanent credentials by keeping them off the wire during ongoing operations.

Out of Memory Java Heap Space Error

Note: For CopyStorm versions 10.56.6 and higher, Java memory parameters can be provided without modifying the CopyStorm start script. For more details, please see .

CopyStorm uses the default settings for Java heap space. Most of the times this works well, but if you are seeing an Out of Memory error referencing Java Heap Space you may need to increase the memory allowance for CopyStorm. Settings can be adjusted as described in the “CopyStorm.bat” file, but the exact settings will depend on the size needed for the data in your Salesforce instance.

The most common reason to adjust the default memory settings is that a large content item (usually an Attachment, Document, or ContentVersion) is too large to fit in available CopyStorm memory. CopyStorm requires 3 to 4 times the size of the largest content item. Here are the steps to find the largest content items in your Salesforce:

In the management menu found by clicking on your name in the upper right-hand corner, go to:

Setup -> Data Management -> Storage Usage -> Overall Top Files by Storage Utilization

How Do I Refresh Out of Sync Columns

Though CopyStorm keeps a data in sync with Salesforce, there are a few cases where the data can become out of sync:

  • A new column is created and populated in Salesforce, but the Salesforce credentials used by CopyStorm cannot see the column.

    • When permissions are changed and CopyStorm can see the column, any data populated prior to CopyStorm having visibility will be null and the data will need to be propagated.

  • A column contains a formula whose value changes without the timestamp on the row changing.

How to Use the SOAP API With Attachments

By default, CopyStorm will use the Salesforce REST API for Attachments and other tables which contain BASE64 columns. REST is used by default because it minimizes the amount of memory needed by CopyStorm (See the technical details section at the end of this document is you are interested in the details).

If using the REST API is a problem then a simple CopyStorm configuration file change can force the SOAP API to be used instead. The primary need we have seen for this is when a local virus checker or network filter is blocking attachment downloads from Salesforce.

Make CopyStorm use the SOAP API for Attachments

Open the file [CopyStorm]/config/TableRuleRegistry.xml and change:

<TableRule name="Attachment" predicate="bodyLength&lt;800000000" />

to

<TableRule name="Attachment" predicate="bodyLength&lt;800000000" useRestAPI="false"/>

Alternatively, if you are using a custom directory of CopyStorm configuration files, simply add the following rule to your private TableRuleRegistry.xml file.

<TableRule name="Attachment" useRestAPI="false"/>

Since Salesforce SOAP API returns an entire attachment in a single response, the amount of memory required to parse the response and send the attachment to a target database can be huge (for huge attachments). The Salesforce REST API can be used to avoid loading an entire attachment into memory. Here is why:

  • The REST API returns an attachment BODY as a hyperlink.

  • CopyStorm downloads the hyperlink to a temporary file (taking very little memory).

  • The temporary file is loaded directly into the target database without ever being loaded into CopyStorm memory. No all database support this feature but those that do minimize CopyStorm memory usage.

How to Fix Cannot Alter Column Used by A View Errors

There are a handful of tables where CopyStorm uses database views rather than tables. A good example is ActivityHistory (a view combining the Task and Event tables). If Salesforce makes a change which alters the type of length of a column in a table and the column is used in an existing view, PostgreSQL will throw an error like the following when CopyStorm tries to make the change in the database.

  • org.postgresql.util.PSQLException: ERROR: cannot alter type of a column used by a view or rule Detail: rule _RETURN on view openactivity depends on column “status”

The process to fix the issue is to:

  • Drop the views that depend on the table that needs modification

Can I Use Apache's log4j2?

Yes you can — CopyStorm supports log4j2. This article contains the instructions you will need.

CopyStorm comes packaged with log4j2 — configuring configuring CopyStorm to use it is a two-step process:

  • Select the “Use Apache Logging” option on the configuration section of CopyStorm’s Configuration tab.

    • When checked, CopyStorm will use the Apache Commons Logging system rather than the default.

How Does CopyStorm Base64 Chunking Work?

All programming languages, databases, and most applications have limits on the maximum size of values they can store or manipulate. For example, Salesforce has a 2 GB limit the size of an uploaded file, and PostgreSQL has a 1 GB limit on the size of a column value.

When CopyStorm downloads large files from Salesforce, CopyStorm streams the Base64-encoded file body to the file system (which has no size limits other than available disk space). Without using CopyStorm’s Base64 Chunking feature the Base64-encoded file body will be written directly to the database, subject to the size limitations (e.g. 1 GB in PostgreSQL).

The CopyStorm Base64 Chunking feature allows large files to be broken apart into chunks, storing these chunks in a separate table named CopyForceTableFieldChunk. By default, files will be broken into 100 MB chunks – but this is configurable. For example, if the Body field of a ContentVersion record is 500 MB, and the Base64 Chunking feature is enabled, then the 500 MB file will be broken into 5 parts that are stored as 5 separate entries in the CopyForceTableFieldChunk table.

With Base64 Chunking enabled, there are no practical database storage limits to the size of field values in SalesForce objects that can be brought into the CopyStorm database, and CopyStorm is not subject to the maximum size limitations of the database.

The Base64 Chunking feature is disabled by default when CopyStorm is initially configured – to enable this feature, check the

CaseMilestone

  • IsViolated

  • ElapsedTimeIn.*

Problem Salesforce Formula Fields

Technical Details

Edit the log4j2.properties file in the “lib” subdirectory of the CopyStorm installation to match your logging preferences.

Using log4j2

Logging

Client ID

The unique identifier issued by Salesforce when you register a connected app. Required for all OAuth flows to identify the requesting application.

Client Secret

A confidential key generated by Salesforce for your connected app. Used alongside the Client ID to authenticate the application during OAuth flows.

OAuth Client Credentials Connection Parameters

Password

The Salesforce password for the specified user. Note: If your org requires it, append the user’s security token directly to the end of the password, with no spaces.

Client ID

The unique identifier issued by Salesforce when you register a connected app. Required for all OAuth flows to identify the requesting application.

Client Secret

A confidential key generated by Salesforce for your connected app. Used alongside the Client ID to authenticate the application during OAuth flows.

Username

this tutorial

The Salesforce username (email address) of the user the application will authenticate as. This must match a valid, active user in the connected Salesforce org.

Use a 64-bit Java JRE if possible.
  • Increase the amount of heap space available by setting the JVM_ARGS parameter as showing in the CopyStorm.bat file. This file can be edited.

    1. The following example sets the min and max memory allocations to 300 and 1000 megabytes, respectively: set JVM_ARGS=-Xms300m -Xmx1000m

    1. Use a 64-bit Java JRE if possible.

    2. Increase the amount of heap space by modifying the last line of the CopyStorm.sh script, adding memory allocation rules immediately after the “$JAVA”.

      1. The following example sets the min and max memory allocations to 300 and 1000 megabytes, respectively: “$JAVA” -Xms300m -Xmx1000m -cp (… see the file for the rest of the command)

    Increasing CopyStorm’s Memory Limit on Windows

    this page

    Increasing CopyStorm’s Memory Limit on Linux

    Chunk Base64 Values
    checkbox on the
    configuration editor.

    When this checkbox is:

    • Unchecked, then Base64 field values are always stored in-line in the primary CopyStorm data tables.

    • Checked, then Base64 field values that are larger than the chunk size will be stored in the CopyForceTableFieldChunk table.

      • In this case, a pointer value will be stored in the primary CopyStorm data table.

    The pointer is the string representation of a JSON object containing field metadata. For example:

    All chunked values will be prefixed with the value “#AAA:”. Inlined Base64 values will never begin with this value because the “#” character is not valid in Base64 strings.

    All of the Base64 chunking information within this page also applies to CopyStorm Snapshots, with two differences:

    1. CopyStorm Snapshots store Base64 values in a secondary chunked data table named CopyForceArchiveFieldChunk.

    2. CopyStorm Snapshots will always chunk Base64 values, regardless of whether Base64 chunking is enabled in the primary CopyStorm database.

    To override the system default chunk size, create a Base64ChunkParameters.xml file and place it in the [CopyStorm]/config/ directory. This file is used to provide the chunk size to CopyStorm. In the example below, the default chunk size has been changed to 5 MB (5000000):

    All chunks created after updating this file will be created using the newly provided chunk size.

    CopyStorm will automatically delete records from the CopyForceTableFieldChunk table as parent records are deleted from the primary CopyStorm data tables. If the CopyStorm tables are truncated, or if records are deleted from the CopyStorm tables without CopyStorm performing the deletions, then the CopyStorm/Medic Delete Orphaned Base64 Chunks tool can be used to scan for and delete any CopyForceTableFieldChunk records that point to records that are no longer present in the primary CopyStorm data tables.

    Snapshot chunked records contained in the CopyForceArchiveFieldChunk table will be automatically cascade-deleted when their parent records are deleted.

    Base64 Chunk Usage

    Base64 Snapshot Chunking

    Overriding System Default Chunk Sizes

    Deleting Base64 Chunk Records

    Database Schema
    In some environments — such as self hosted S3-compatible storage or situations where STS is unavailable — you may need to bypass temporary credential retrieval.

    This article describes how to configure CapStorm applications to connect to S3 using permanent credentials directly.

    To configure CopyStorm to use permanent AWS credentials when communicating with S3:

    1. Create an XML file called CapStormAWSCredentialsProvider.xml

    2. Place the XML file in the config directory of the CopyStorm base installation.

      1. Note: If External Configuration is being used, this file can instead be placed in the designated External Configuration location.

    An example CapStormAWSCredentialsProvider.xmldisabling temporary credentials is shown below:

    When to Use Permanent Credentials Directly

    Configuring CopyStorm to Use Permanent Credentials

    #AAA:{
       "numChunks": "5",
       "chunkSize": "100000000",
       "contentSize": "500000000",
       "salesforceId": "0686300000190d9AAA",
       "hash": "bcfc403cba99fda2224395a843d9397b"
     }
    <Base64ChunkParameters>
                <DataSourceType name="SQLServer" chunkSize="5000000" />
                <DataSourceType name="Oracle"  chunkSize="5000000" />
                <DataSourceType name="MySQL" chunkSize="5000000" />
                <DataSourceType name="H2" chunkSize="5000000" />
                <DataSourceType name="PostgreSQL" chunkSize="5000000" />
                <DataSourceType name="RedShift" chunkSize="5000000" />
                <DataSourceType name="Snowflake" chunkSize="5000000" />
                <DataSourceType name="Unknown" chunkSize="5000000" />
    </Base64ChunkParameters>
    <CapStormAWSCredentialProvider>
    	<EnableSessionToken value="false"/>
    </CapStormAWSCredentialProvider>

    If you know the specific columns that need to be updated, the fastest approach is to use the CopyStorm/Medic RefreshColumns tool. However, if you are not sure which columns are out of sync or if you want to check all columns, the fastest approach is to use CopyStorm.

    The fundamental operation that needs to be performed is to force CopyStorm to scan a specific range of records and update columns in the target database, even if the timestamps in CopyStorm and Salesforce are the same. This can be done by modifying your existing CopyStorm job for a one-time run using the following parameters:

    • Verify that the “Optimize Update SQL” option is checked (it is by default).

      • When this option is checked columns whose values differ between CopyStorm and Salesforce will be updated in the database.

    • Enable the “Force Updates” option.

      • When this option is checked, CopyStorm will do a field-by-field comparison between CopyStorm and Salesforce records even when the two timestamps match.

    • Enter a date into the Modified Since parameter that is earlier in time than when the data sync problem is believe to have occurred.

      • For example, if a new column was introduced on 16-Mar-2017 and permissions were fixed on 21-Mar-2017 then only records modified after 15-Mar-2017 need to be scanned.

    Now run CopyStorm — any fields that do not match will be updated and matching fields will be left untouched.

    Do not save changes to your CopyStorm configuration file.

    This example will scan all records in nearly all tables and fix any data mismatches:

    Refreshing Tables in CopyStorm

    Run CopyStorm — it will make the table modification and automatically recreate the views.

    In Summer’20 Salesforce increased then length of the column Task.Status. Since the Task.Status column is used in CopyStorm views the update to Task.Status failed with:

    • org.postgresql.util.PSQLException: ERROR: cannot alter type of a column used by a view or rule Detail: rule _RETURN on view openactivity depends on column “status”

    Here are the steps to fix this problem.

    The next time CopyStorm runs it will:

    • Successfully ALTER the Task.Status column because the dependent views no longer exist.

    • Recreate the views after detecting they have been deleted.

    How to Fix “Cannot Alter Column Used by a View” Errors

    Example From Summer’20

    Step 1: Drop the Views Which Depend on Task.Status

    Step 2: Run CopyStorm

    How to Fix Index and Column Creation Timeouts

    When CopyStorm adds a new column to an existing database table or indexes a new column the operation may have timeout issues if the table has a large number rows. This article describes how to solve this problem by increasing the amount of time CopyStorm will wait for a DDL operation to complete.

    The parameter that controls how long CopyStorm will wait for an ALTER TABLE ADD/ALTER COLUMN, CREATE INDEX, or any other DDL type operation is kept in the section of the Configuration tab.

    The default DDL Timeout Parameter is 3600 seconds so set the value to a much larger value.

    Database Networking

    How To Capture CopyStorm Runtime Logs

    This article provides information on how to capture CopyStorm job execution log data that is output via Standard Error/Out in a text file. This approach is useful for doing advanced troubleshooting in order to capture error symptoms that may not appear within the application GUI or within the logged exceptions of the job history entry found on the “History” tab.

    The general approach is as follows:

    1. Open a headless CopyStorm script for editing.

      1. This is the script that is scheduled using CRON or Windows Task Scheduler, and is created using the “Batch File” tab of CopyStorm.

    2. Create a directory that will be used to save the application logs.

    3. Edit the batch script to create a log file with the appropriate name in the established directory and write all job execution output to the file.

    Here is an unedited example of a Windows batch script generated by CopyStorm. This script will be modified to output CopyStorm job logs to a file:

    The following code is added after the line that begins with “SET CopyStormConfigFile”

      • This code sets a local script variable that establishes the path to the directory where the log files will be stored.

      • The “C:\Capstorm\CopyStormLogs” path should point to your desired CopyStorm log directory path.

    Next, the second to last line (starting with “CALL %CopyStormCmd%”) will need to be modified to write to the logfile. The final line will look like this:

    This code creates a logfile and redirects stderr and stdout to the file, capturing all job execution logs.

    The “CopyStorm_Log_” prefix is used to identify the type of logfile – if you have multiple scheduled jobs, it is best practice to use a different prefix for each scheduled job. For example, “CopyStorm_Hourly_Data_” and “CopyStorm_Daily_Metadata_” if there is an hourly job for data and a separate daily job for metadata.

    The example above will create log files with names like:

    • CopyStorm_Log_2023-02-21T19-45-32.txt

    Here is an edited version of the batch script shown above:

    Here is an unedited example of a Linux sh script generated by CopyStorm. This script will be modified to output CopyStorm job logs to a file:

    The following code is added after the line that begins with “CopyStormConfigFile=”

      • This code sets a local script variable that establishes the path to the directory where the log files will be stored.

      • The “/opt/Capstorm/CopyStormLogs” path should point to your desired CopyStorm log directory path.

    Next, the second to last line (starting with “sh $CopyStormRootDir”) will need to be modified to write to the logfile. The final line will look like this:

    This code creates a logfile and redirects stderr and stdout to the file, capturing all job execution logs.

    The “CopyStorm_Log_” prefix is used to identify the type of logfile – if you have multiple scheduled jobs, it is best practice to use a different prefix for each scheduled job. For example, “CopyStorm_Hourly_Data_” and “CopyStorm_Daily_Metadata_” if there is an hourly job for data and a separate daily job for metadata.

    The example above will create log files with names like:

    • CopyStorm_Log_2023-02-21T19:45:32.txt

    Here is an edited version of the batch script shown above:

    How to Compare Metadata From Two Backups

    Since CopyStorm keeps a copy of Salesforce metadata in local database tables it is a fairly trivial task to compare metadata from multiple CopyStorm backups.

    Problem 1: Compare Table and Field definitions from Two Backups

    The key CopyStorm tables required to perform table and field comparisons are CopyForceTable and CopyForceTableField. These are the tables CopyStorm uses to keep the CopyStorm database structure in sync with Salesforce. Rather than bore you with details, download the following SQL script for an example of how to exhaustively search for table and field differences.

    • Search for Table and Field Differences Script.

    Problem: Compare Salesforce Metadata Objects from Two Backups

    This solution compares elements like Apex Classes, Page Layouts, Settings, etc. from two difference CopyStorm backups. The key table in CopyStorm is SFMetaFileProperties since this table contains the most recently backed version of each metadata type. Note that the companion table, SFMetaFilePropertiesHistory, contains historical values for each metadata type. Download the following script for an example of how to exhaustively compare metadata.

    SOQL’s Seven Deadly Sins

    There are a number of Salesforce quirks that make creating incremental backup software more difficult than a person might expect. The content of this article will help you understand some of the quirks and give you information that makes you happy that Capstorm backs up Salesforce for you. Note, the text may look familiar to an article published originally on — that’s OK since the blogspot author is one of the founders of Capstorm.

    This article is not about how to be a better SOQL programmer. It is about pitfalls in SOQL that are obscure and often difficult to diagnose and understand when encountered.

    1. The SOQL WHERE clause cannot be trusted.

    2. The SOQL LIMIT parameter is not always optional.

    How to Fix SQL/Server Page SIze Too Small Errors

    SQL/Server 2016 and later will sometimes complain about adding or altering table columns with a error like:

    • SQLServerException: Cannot create a row of size 8063 which is greater than the allowable maximum row size of 8060

    If you do not understand what this means then google the message. To fix this issue keep reading.

    The simplest fix is to drop the table and let CopyStorm rebuild it automatically during the next backup. SQL/Server will examine the columns in the CREATE TABLE statement and avoid the problem.

    The technique for fixing a table without rebuilding it involves converting the longest NVARCHAR(n) columns to NVARCHAR(MAX). This will cause a SQL/Serve table to have a bit more row space for each column that is converted and thus allow the addition of new columns.

    If you want to perform the fix by hand, here are the specific steps:

    How to Convert to Database Views

    If your CopyStorm database was created before Database Views were introduced then are likely many database tables in your backup that could be represented as database views instead. For safety, CopyStorm will not convert an existing table to a view UNLESS you follow the instructions in this article.

    The technique to force CopyStorm to switch to a database view for a table is simple:

    • Manually drop the table in the CopyStorm database that should be a view. The next time CopyStorm runs it will create the view.

    For example:

    • DROP TABLE AccountFeed

    ALTER a few of the longer NVARCHAR2 columns to be NVARCHAR2(MAX)

  • DBCC CLEANTABLE (databaseName, ‘TableName’, 0 )

  • ALTER TABLE tableName REBUILD

  • If you would prefer a computer to do the analysis for you and generate a script that will fix the problem then:

    • Paste the following script into SQL Server Management Studio

    • Change the values for @catalog, @schema, @column, and @cutoff to match the table your want to fix.

    • Run the script

    • Take the output of the script and paste into a new SQL Server Management Studio window and run it.

    — — Find all NVARCHAR columns longer than a specified cutoff and generate a script that changes them to NVARCHAR(MAX) — — This can be helpful if an alter to a table is causing the table to exceed the maximum page size. — — Note: those code generates a script that would make the column changes — it does not make the changes — BEGIN DECLARE @catalog VARCHAR(128) DECLARE @schema VARCHAR(128) DECLARE @table VARCHAR(128) DECLARE @column VARCHAR(128) DECLARE @cutoff INTEGER DECLARE @sql VARCHAR(MAX)

    SELECT @catalog = ‘gsmithfarmer’ — look in this database SELECT @schema = ‘dbo’ — look in this schema SELECT @table = ‘account’ — change columns in this table. SELECT @cutoff = 200 — ALTER NVARCHAR columns that are longer than this to NVARCHAR(MAX)

    DECLARE @candidates TABLE (table_catalog VARCHAR(128), table_schema VARCHAR(128), table_name VARCHAR(128), column_name VARCHAR(128), character_maximum_length INTEGER );

    INSERT INTO @candidates(table_catalog, table_schema, table_name, column_name, character_maximum_length ) SELECT table_catalog, table_schema, table_name, column_name, character_maximum_length FROM INFORMATION_SCHEMA.columns WHERE TABLE_CATALOG=@catalog AND TABLE_SCHEMA=@schema AND TABLE_NAME=@table AND DATA_TYPE=’nvarchar’ AND CHARACTER_MAXIMUM_LENGTH>@cutoff

    ;

    DECLARE candCursor CURSOR FOR SELECT table_catalog, table_schema, table_name, column_name FROM @candidates ORDER BY character_maximum_length DESC ;

    OPEN candCursor FETCH NEXT FROM candCursor INTO @catalog, @schema, @table, @column WHILE @@FETCH_STATUS=0 BEGIN SET @sql = ‘ALTER TABLE ‘ + @catalog + ‘.’ + @schema + ‘.’ + @table + ‘ ALTER COLUMN ‘ + @column + ‘ NVARCHAR(MAX) NULL;’

    PRINT @sql FETCH NEXT FROM candCursor INTO @catalog, @schema, @table, @column END CLOSE candCursor DEALLOCATE candCursor PRINT ‘DBCC CLEANTABLE (‘ + @catalog + ‘,’ + @table + ‘,0)’ PRINT ‘ALTER TABLE ‘ + @catalog + ‘.’ + @schema + ‘.’ + @table + ‘ REBUILD;’

    END

    Simple Solution – Rebuild the Problem Table

    A Harder Solution – Fix the Problem Table

    For Additional Help

    Exhaustively Compare Metadata Objects Script.
    Where Does CopyStorm Store Salesforce Metadata?
    Does CopyStorm Backup Metadata?
    Where Does CopyStorm Keep Past Revisions of Metadata?

    DROP TABLE ActivityHistory

    will cause CopyStorm to recreate AccountFeed and ActivityHistory to views the next time CopyStorm runs.

    The CopyStorm/Medic Table Editor tool provides a simple GUI for dropping tables from a CopyStorm database.

    • Go to the documentation for the CopyStorm/Medic Table Editor

    • All tables ending with Feed. Examples:

      • AccountFeed

      • MyCustomObject__Feed

    • ActivityHistory

    • AccountUserTerritory2View

    The DBA Approach

    The Non-DBA Approach

    What Tables Can Be Converted To Database Views?

    This code sets a local script variable to the current timestamp at which the script is executed. Timestamps will be generated using YYYY-MM-DDTHH-mm-SS.SS formatting – e.g. “2023-02-21T19-45-32.12”.
  • You do not need to change any of this code, just copy and paste it directly.

  • This code sets a local script variable to the current timestamp at which the script is executed. Timestamps will be generated using YYYY-MM-DDTHH:mm:SS formatting – e.g. “2023-02-21T19:45:32”.
  • You do not need to change any of this code, just copy and paste it directly.

  • Windows

    Linux

    @ECHO OFF
    REM 
    REM This script runs CopyStorm and relies on the notification system built into CopyStorm
    REM to report the success/failure of a job. Log file information is written to stdout 
    REM in addition to the logging tables in the CopyStorm database.
    REM 
    REM    CopyStormRootDir - the directory in which CopyStorm is installed.
    REM    CopyStormConfigFile -- the name of the CopyStorm configuration file to run.
    
    SET CopyStormRootDir=C:\Capstorm\CopyStorm
    SET CopyStormConfigFile=C:\Capstorm\CapstormConfig\config.copyStorm
    
    SET CopyStormCmd="%CopyStormRootDir%\CopyStorm.bat" -run "%CopyStormConfigFile%" 
    CALL %CopyStormCmd% 2>&1
    
    EXIT /B %ERRORLEVEL%
    SET LOGDIR=C:\Capstorm\CopyStormLogs
    SET TIMESTAMP=%date:~10,4%-%date:~7,2%-%date:~4,2%T%TIME::=-%
    SET TIMESTAMP=%TIMESTAMP: =0%
    CALL %CopyStormCmd% >> %LOGDIR%\CopyStorm_Log_%TIMESTAMP%.txt 2>&1
    
    @ECHO OFF
    REM
    REM This script runs CopyStorm and relies on the notification system built into CopyStorm
    REM to report the success/failure of a job. Log file information is written to stdout
    REM in addition to the logging tables in the CopyStorm database.
    REM
    REM CopyStormRootDir - the directory in which CopyStorm is installed.
    REM CopyStormConfigFile -- the name of the CopyStorm configuration file to run.
    
    SET CopyStormRootDir=C:\Capstorm\CopyStorm
    SET CopyStormConfigFile=C:\Capstorm\CapstormConfig\config.copyStorm
    
    SET LOGDIR=C:\Capstorm\CopyStormLogs
    SET TIMESTAMP=%date:~10,4%-%date:~7,2%-%date:~4,2%T%TIME::=-%
    SET TIMESTAMP=%TIMESTAMP: =0%
    
    SET CopyStormCmd="%CopyStormRootDir%\CopyStorm.bat" -run "%CopyStormConfigFile%"
    CALL %CopyStormCmd% >> %LOGDIR%\CopyStorm_Log_%TIMESTAMP%.txt 2>&1
    
    EXIT /B %ERRORLEVEL%
    
    
    #!/bin/sh
    #############################################################################
    
    # This script runs CopyStorm and relies on the notification system built into CopyStorm
    
    # to report the success/failure of a job. Log file information is written to stdout
    
    # in addition to the logging tables in the CopyStorm database.
    
    #
    
    # CopyStormRootDir - the directory in which CopyStorm is installed.
    
    # CopyStormConfigFile -- the name of the CopyStorm configuration file to run.
    
    #
    #############################################################################
    
    CopyStormRootDir="/opt/Capstorm/CopyStorm"
    CopyStormConfigFile="/opt/Capstorm/CopyStormConfig/configFile.copyStorm"
    
    sh $CopyStormRootDir/CopyStorm.sh -run $CopyStormConfigFile 2>&1
    
    exit $?
    
    LOGDIR="/opt/Capstorm/CopyStormLogs"
    TIMESTAMP=$(date +"%Y-%m-%dT%H:%M:%S")
    
    sh $CopyStormRootDir/CopyStorm.sh -run $CopyStormConfigFile >> "$LOGDIR/CopyStorm_Log_$TIMESTAMP.txt" 2>&1
    #!/bin/sh
    #############################################################################
    # This script runs CopyStorm and relies on the notification system built into CopyStorm
    # to report the success/failure of a job. Log file information is written to stdout 
    # in addition to the logging tables in the CopyStorm database.
    #
    #   CopyStormRootDir - the directory in which CopyStorm is installed.
    #   CopyStormConfigFile -- the name of the CopyStorm configuration file to run.
    #
    #############################################################################
    
    CopyStormRootDir="/opt/Capstorm/CopyStorm"
    CopyStormConfigFile="/opt/Capstorm/CopyStormConfig/configFile.copyStorm"
    
    LOGDIR="/opt/Capstorm/CopyStormLogs/"
    TIMESTAMP=$(date +"%Y-%m-%dT%H:%M:%S")
    
    sh $CopyStormRootDir/CopyStorm.sh -run $CopyStormConfigFile >> "$LOGDIR/CopyStorm_Log_$TIMESTAMP.txt" 2>&1
    
    exit $?

    Timestamps returned by SOQL believe in time travel.

  • SOQL can return field data that is invalid based on the field definition.

  • SOQL has a love/hate relationship with tables containing lots of custom fields.

  • SOQL does not treat all table equally – not knowing the exceptions can take down your org.

  • SOQL chokes on tables with lots of functional columns.

  • Here is a trick question. Will the following SOQL statement return any records that were modified today?

    SELECT id, name FROM Account WHERE systemModStamp < LAST_YEAR

    The answer is……usually not. However it will return a record modified today when:

    • The record fit the WHERE criteria when the record set to return was determined.

    • The record is modified before it was fetched from Salesforce.

    This “sin” is easy to reproduce with a Python script and a web browser.

    1. In the web browser open the Salesforce GUI on the record that will be the most recent one to match the LAST_YEAR criteria.

    2. Start a Python script that fetches records using:

    SELECT id,name,systemModStamp FROM Account WHERE systemModStamp < LAST_YEAR ORDER BY systemModStamp ASC

    1. Modify the record in the Salesforce GUI after the Python script starts fetching records.

    2. One of the last records you read from Salesforce will have a modification date of today

    Though the SOQL documentation says that the LIMIT parameter is optional there are a handful of Salesforce tables where it is nearly impossible to run a large query without the dreaded Query Timeout error. If you are not a believer then try running these queries on a mature Salesforce instance.

    1. SELECT id, accountId, description FROM Task ORDER BY SystemModStamp ASC

    2. SELECT application,browser,loginTime FROM LoginHistory ORDER BY loginTime ASC

    Short of begging Salesforce for a max timeout value longer than the default, a solution has to “know” good limit values for problem tables. Here are good values for a handful of the more troublesome table.

    Table Name (or name pattern)

    Good LIMIT Value

    .*History

    5000

    .*History__c

    5000

    .*Feed

    Here’s another SOQL quiz. In the following code snippet, is it possible for the Exception to be thrown? For the quiz assume that all Account records have unique timestamp values and no records are deleted.

    Account accts1[] = [SELECT id, systemmodstamp FROM Account ORDER BY systemmodstamp ASC;

    Account maxAcct = accts1[acct1.size() – 1]

    Account accts2[] = [SELECT id, systemmodstamp FROM Account WHERE systemmodstamp <=:maxAcct.systemmodstamp ORDER BY systemmodstamp ASC;

    if( accts2.size() > accts2.size()) {

    throw new Exception(‘Timewarp – new account created in the past!’);

    }

    The answer….usually no. However, Salesforce does not guarantee that records are committed in timestamp order.

    It is possible for a record with a SystemModStamp of 2014-12-31T00:12:12.000Z to be committed to Salesforce after a record in the same table with a SystemModStamp of 2014-12-31T00:13:12.000Z.

    This is a hard “sin” to reproduce because it depends on the current load of the Salesforce servers. We discovered the problem by monitoring a high volume production instance for three weeks – the problem occurred just a couple of times during this period. It was sort of like searching for a Higgs particle.

    The moral: Do not assume that the MAX(SystemModStamp) or MAX(LastModifiedDate) value is a good constraint to find all values that are older.

    The solution: Do not rely on timestamps that are fresh. Give Salesforce a little while to commit all recent transactions. In practice this odd state seems to settle out on Salesforce servers after 10-120 seconds.

    This quiz should be easy for experienced SOQL users.

    1. Is it possible for an invalid email address to be stored and returned in a Salesforce Email field?

    2. Is is possible to store a 132 character string in a 128 character Salesforce field?

    The answer to #1 is, of course, possible. Check out contact Ms. Barbara Levy in any developer force instance. Her email is: b.levy@expressl&t.net Try saving the record and Salesforce will tell you that the email format is invalid (using the API will throw the same error).

    The answer to #2 is also “possible.” In fact Salesforce creates an email template with an invalid length subject when Sites is enabled.

    There is other “invalid” data (related to currency values) lurking in the developer force instance – you will have to find this one yourself.

    Thing to remember:

    1. Just because Salesforce meta data says a field is 80 characters long does not mean it may have a longer value.

    2. Just because Salesforce meta data says a number is DECIMAL(5,2) do not trust it. An API program may have inserted data that does not match the spec.

    3. Do not be surprised if you read data from one Salesforce instance and it fails to upsert into another instance – the source data may be bad.

    Though Salesforce allows many custom fields to be created on a table, using too many columns in a SOQL statement will cause a QUERY_TOO_COMPLICATED error. At least this “sin” is one Salesforce documents but after 10 years one would assume they would have a work-around in the back-end.

    If you really need to do the equivalent of “SELECT * FROM Account” and SOQL will not allow the read in a single statement what needs to be done? There are two problem to solve.

    1. Figure out the minimum number of SOQL queries to run. If none of the columns are formulas then this can usually be done by using 500 columns for each query. If formula columns are involved the problem is much harder – in this case see Sin #7.[

    2. Join the results of multiple queries together.

    Realistically, grab the data from a Salesforce dump file or use a tool like Capstorm’s CopyStorm to extract the table into a relational database. Doing it yourself is hard.

    The transaction cost of querying a table with SOQL varies a lot. The first time you query a high cost table and cause your production org to run out of transactions will probably be the last time.

    Here a SOQL quiz. How many Salesforce transactions does it take to run the following SOQL statement?

    SELECT id, name FROM TableName LIMIT 2000

    The answer, of course, depends on TableName and is either 2000, 200, 40, 20, 10, 4, 2, or 1.

    The “1 transaction per record” rule for Attachment records is documented. The same rule applies to QuoteDocument and ContentVersion but we have learned this from experience rather than documentation. In general 2000 and 1000 are the common number of records per transaction but the only way to know for certain is the write a bit of code and see how many come back in a bunch.

    When Salesforce runs a SOQL query it turns it into SQL first. Once in SQL there is a 64K character query limit. If the 64K SQL query limit is passed then SOQL will return a QUERY_TOO_COMPLICATED exception.

    Here a SOQL quiz: Given a SOQL statement how can you accurately (or inaccurately even) guess that it will generated a SQL statement less than 64 characters?

    The answer is……if table has a lot of formula columns you probably cannot guess accurately.

    In practice, the addition of formula columns in a SOQL statement can cause the size of the resultant SQL to explode – sometimes. It all depends on the complexity and number of tables referenced by the formula.

    • The complexity of the formula seems to matter. My guess is that Saleforce is in-lining the formula calculation into the generated SQL.

    • A formula that references other tables likely causes the table expression and predicate portion of the generated SQL to grow rapidly.

    The solution to this problem is nearly the same as Sin #5 but the first step, determining the minimum number of SOQL query to run can difficult. The only solution we have found that works reliably is iterative.

    1. Sort column in ascending order by the length of their name or length of their corresponding formula.

    2. Set maxColumn = total # of columns

    3. Run a query run using columns 1 thru maxColumn with a LIMIT 1.

    • If the query succeeds then save the query, remove the query’s columns from the list of available columns.

    • If the query fails then set maxColumn = maxColumn – 1 and start step 3 again.

    1. Set maxColumn = # remaining columns

    2. If maxColumn > 0 goto Step #3, otherwise all queries have been determined.

    The “SOQL Sins” described in this article were accumulated over a number years while developing:

    • CopyStorm – keep a hot backup of your Salesforce instance in SQL/Server, Oracle, MySQL, PostgreSQL, and H2

    • CopyStorm/Restore – restore a backup to any production, development, or sandbox instance. This is a restore tool even your manager could use.

    • SQLForce – a standard Python module for Salesforce. Works with Python 2.8. 3.3, and 3.4. Use SQLForce when Apex is just too hard.

    For more information see www.capstorm.com

    SOQL’s Seven Deadly Sins

    blogspot in 2014

    Sin 1: The SOQL WHERE clause cannot be trusted.

    Sin 2: The SOQL LIMIT parameter is not always optional.

    Sin 3: Timestamps returned by SOQL believe in time travel.

    Sin 4: SOQL can return invalid field data.

    Sin 5: SOQL has a love/hate relationship with custom fields.

    Sin 6: SOQL does not treat all tables equally.

    Sin 7: SOQL chokes on tables with many functional columns.

    Credits

    OAuth JWT Login

    How to Login to Salesforce as an External Client App

    This page provides instructions for connecting to Salesforce using certificate-based / JWT authentication.

    To connect to Salesforce using JWT authentication it is necessary configure an External Client App with a certificate, and to provide the certificate and OAUTH Client Id to CapStorm.

    Step 1: Create a Certificate

    Create a certificate using CapStorm by selecting the JWT credential type and exporting the certificate file.

    To select the JWT credential type:

    1. Click on the Edit button for Advanced Parameters.

    2. Select Oauth 2.0 JWT in the dropdown.

    To Save the certificate:

    This will create two files:

    1. The certificate and private key are stored in a file CapStorm_JWT.jks in the CapstormConfig folder.

      1. The CapstormConfig folder is a folder next to the application folder.

      2. For example, if CopyStorm is installed in C:\CapStorm\CopyStorm

      3. Then the CapstormConfig folder will be C:\CapStorm\CapstormConfig

    Create an External Client App using the PEM file exported in Step 1.

    Login to Salesforce and go to Setup. Search for External Client App Manager in the Quick Find box, and click on New External Client App.

    Enter app details:

    1. External Client App Name

    2. API Name

    3. Contact Email

    4. Callback URL

    Then, click on “Create”.

    After creating the External Client App, configure app policies to allow access.

    Click on “Edit” for App Policies, and update the policy to enable appropriate users. In this example, a Permission Set is used to grant access to the app:

    1. Under OAuth Policies, change Permitted Users to:

      1. Admin approved users are pre-authorized.

    2. Under Select Profiles and Select Permission Sets:

      1. Select the Permission Set(s) or Profile(s) that should be granted access to the External Client App.

    To configure CapStorm, the Oauth Client Id (Consumer key) from the External Client App will be needed.

    1. Go to the Settings tab of the External Client App.

    2. Under OAuth Settings, click on Consumer Key and Secret.

    3. In the Consumer Details page, copy the Consumer Key.

    Copy the Consumer Key:

    Now, to finish configuring CapStorm:

    1. Copy the Consumer Key value into the OAuth Client Id text box.

    2. Enter the Salesforce User’s username into the Username text box.

      1. The user must be a member of the Permission Set or Profile configured in the OAuth policy.

    3. Enter the Salesforce instance’s host name into the Salesforce Host text box.

    To verify the connection, click on the “Test Salesforce Connection” button. If successful, the below window will appear:

    The custom certificate checkbox allows users to create and use their own custom java keystore file, separate from the built-in Java JRE keystore. By enabling this checkbox, several new fields will appear in the login form:

    The process of configuring OAuth JWT login with a custom certificate is largely similar to the above steps, the main differences being:

    • OAuth Public and Private keys will need to be generated manually

    • The Certificate will need to be generated manually from the public and private keys

    • The certificate will need to be added to a java keystore file or a PKCS12 file

    • Keystore info (file path, keystore password, key password, and name) must be entered manually into CopyStorm

    After manually generating the above keys and files, the rest of the setup is largely similar to the non-custom certificate flow. Create an external client app, upload the certificate to the external client app, configure the external client app, and finally configure CopyStorm.

    For more information on generating keys and certificates for use in Salesforce OAuth JWT, see this .

    Parameter Name
    Default Setting
    Required
    Description

    How Do CopyStorm Views Work?

    The Salesforce API presents all SObjects (Account,Contact, etc.) as tables to the outside world even though quite a number of SObjects are really subsets/views of other SObjects. The most common example is Salesforce feed tables — there are dozens of feed tables (AccountFeed, ContactFeed, etc.) that are simply views of the table that contains all feeds: FeedItem.

    • The AccountFeed table is really a view on the base table FeedItem.

      • SELECT * FROM FeedItem WHERE parentId IS an Account Record.

    There are also cases where the Salesforce API does not support a direct query on an SObject but the SObject can be constructed from other SObjects.

    • The ActivityHistory table is a union of the Event and Task SObjects but cannot be queried directly using SOQL.

    There are other issues of this kind, but lets get to the important part. When Database Views are enabled in CopyStorm, then CopyStorm will use views in the target database rather than copying a table. This can lead to much faster backups for each table that can be represented as a view.

    Database Views are enabled by default in CopyStorm and when enabled:

    • If a Salesforce table does not exist in the target database and can be represented as a view, then CopyStorm will create it as a view.

    • If a Salesforce table already exists in the target database, then CopyStorm will not re-create it as a view but will continue to treat it as a table.

    If Database Views are disabled in CopyStorm:

    • Database Views will not be created for new tables.

    • If a Database View already exists in the target database, then CopyStorm will not change it.

    The toggle that enables/disables Database Views is found in the configuration section of the CopyStorm Configuration tab.

    This section is for anyone wanting to know exactly how the logic for determining whether a Database View should be used works.

    5000

    .*Share

    5000

    FeedComment

    5000

    Task

    5000

    EmailMessage

    5000

    CaseComment

    50

    FieldPermissions

    2000

    LoginHistory

    2000

    How to Enable Database Views

    Implementation Details

    Case 1: Use Database View = TRUE

    Case 2: Use Database Views = FALSE

    Database Schema

    The exported PEM file.

    NOTE: This field is required, but the value for Callback URL is not used for JWT Apps.

  • Enter https://localhost/ as the Callback URL.

  • OAuth Scopes

    1. At a minimum, the following scopes must be selected:

      1. Access the identity URL service (id, profile, email, address, phone).

      2. Manage user data via APIs (api).

      3. Perform requests at any time (refresh_token, offline_access).

  • Enable OAuth

    1. This checkbox must be checked.

  • Enable JWT Bearer Flow

    1. This checkbox allows JWT access.

  • Certificate Upload

    1. Upload the PEM file that was saved in Step 1.

  • Click on “Create” to create the External Client App.

  • CapStorm recommends configuring a Permission Set to limit App access.

  • Click on “Save” to save the App policies.

  • Sandboxes will have host names like:

    1. mycompany–mysandboxname.sandbox.my.salesforce.com

  • Production orgs will have host names like:

    1. mycompany.my.salesforce.com

  • Click on Test Connection to verify.

  • Yes

    Password used to access the Keystore (blank if the Keystore does not have a password).

    Key Name

    Yes

    The name of the private key used to sign JWT requests.

    Key Password

    Yes

    The password used to access the private key.

    OAUTH Client Id

    Yes

    The Salesforce-generated Client Id for the Connected Application.

    Username

    Yes

    The login Id of the CopyStorm Salesforce user.

    Custom Certificate

    Unchecked

    No

    Check this box to use a custom-made Java keystore file (.jks). Leaving the box unchecked will cause the application to use the default Java key store.

    Token Validity (minutes)

    240

    Yes

    The lifetime of JWT access tokens. If the token expires during the CopyStorm run, CopyStorm will re-authenticate and get a new token.

    Keystore

    Yes

    Path to a JKS or PKCS12 Keystore containing the private key used to sign JWT requests.

    Step 2: Create an External Client App

    Step 3: Configure CapStorm

    Custom Certificate

    OAuth Custom Certificate Connection Parameters

    Salesforce Documentation

    Keystore Password

    Installation

    How to Convert UTC Timestamp to Local Time

    CopyStorm always stores timestamp value using UTC — exactly like Salesforce. This article demonstrates how to convert a UTC datetime column to a timestamp in your local timezone.

    How Does CopyStorm Work

    MySQL

    Oracle

    PostgreSQL

    SQL/Server

    select 
    	AA.systemmodstamp
        , CONVERT_TZ( AA.systemmodstamp, '+00:00', '-06:00')
    from Account AA;
    SELECT
        AA.systemmodstamp
        , (FROM_TZ(AA.systemmodstamp,'+00:00') AT TIME ZONE 'US/Eastern') localtime
    
    FROM Account AA
    select 
    	AA.systemmodstamp
    	, AA.systemmodstamp at time zone 'utc' at time zone 'pst' as localtime
    from Account AA;
    SELECT AA.systemmodstamp, CONVERT(datetime, 
                   SWITCHOFFSET(CONVERT(datetimeoffset, 
                                        AA.systemmodstamp), 
                                DATENAME(TzOffset, SYSDATETIMEOFFSET()))) 
           AS ColumnInLocalTime
    FROM Account AA

    How Does CopyStorm Provide Salesforce Backup Security?

    With any backup solution an organization will want to know how their data is secured. Common questions include:

    • Where is my data stored?

    • How securely is my data transferred over the internet?

    • When and where is my data at rest?

    For CopyStorm the Salesforce backup security answers are simple and complete:

    • Your Salesforce data is stored in a relational database that is created by you and is totally under your control.

      • CopyStorm neither knows nor cares where the data is stored — the database can be in your data center or in a cloud provider like Amazon.

      • The choice and level of security is entirely up to you.

    • CopyStorm runs on your computers and transfers all data from Salesforce using HTTPS.

    Another common question is:

    • What Salesforce and database privileges are required by CopyStorm?

    For Salesforce, the only absolutely required privileges are API Access and View Setup and Configuration. The Salesforce API ensures that CopyStorm always respects the privileges of the Salesforce credentials used by CopyStorm to connect. This means that CopyStorm will backup exactly what the privileged credentials would see if they were used with a web browser.

    Full details are described in the .

    For the target relational database CopyStorm needs to own a schema and does not need visibility outside of its assigned schema. No general DBA privileges are necessary.

    Why is My Batch File Not Sending Email?

    While the CopyStorm Batch File can be configured to send email, the best practice is generally to use CopyStorm’s built-in notification settings.


    The CopyStorm Batch File tab will generate a script that is useful for running CopyStorm in batch mode. Although the script generator asks for email addresses to notify on CopyStorm success and failure, some installation configurations may cause the generated script to not successfully send a Salesforce backup notification email.

    The Batch File tab will generate scripts in a variety of languages. Some of these languages have a built-in way to send email in an operating system independent way, but some do not. When a scripting language (like BAT) does not have a built-in way to send an email then it is the responsibility of the script to implement the behavior.

    See the following sections for help with each batch script type.

    Hints On Using a Generated BAT File

    There is no standard way to send an email from a Windows BAT file, and CopyStorm does not try to guess the technique used by your organization. Generated BAT scripts isolate the “email sending” code to a small subroutine that must be implemented according to your company standard. At the end of a BAT script generated by CopyStorm you will see code that looks like:

    :SendEmail REM REM Code your site specific email rule procedure here. REM REM %1 is the email subject REM %2 is the email address that should receive the mail REM %3 is a file containing the body of the email REM

    ECHO TODO: Send email to %2 with subject %1 EXIT /B

    This code is a subroutine that the script will call each time it attempts to send a Salesforce backup notification email. To finish the script, you need to implement your organization’s email sending logic. BAT file emailing is accomplished using a number of techniques, varying by organization:

    • Copying the log file to a directory using a name that indicates when the job completed.

    • Using the open source tool to email the status.

    The following screenshot indicates where the script changes must be made:

    Windows VBS has a built-in way to send an email if the name of an email server is specified. The default email server is GOING TO BE WRONG all of the time, and CopyStorm has no way to guess the correct server. The aspmx.l.google.com server name must be replaced by the name of your company’s email server.

    • aspmx.l.google.com is a well-known server that will process email addressed to gmail accounts.

    The following screenshot indicates the values that must be changed to match your environment:

    The rules for using a BASH script are the same as those for a VBS script — two values must be changed before generating the script:

    • EMail Server

    • EMail From

    See the screenshot under the VBS section above for an example.

    The rules for using a Python script are the same as those for a VBS script — two values must be changed before generating the script:

    • EMail Server

    • EMail From

    See the screenshot under the VBS section above for an example.

    How Do I Tunnel Into A Remote Database Using SSH?

    A common question is “How do I connect to a database running on Amazon (or Azure) from my local laptop?” The answer often is:

    • Create an SSH tunnel that will allow you to treat the remote database as if it was local.

    Example

    We have an instance of MySQL running on an Amazon EC2 instance and want to access it from our local network. Technically what we want to do is:

    • Pretend that there is a MySQL instance listening on port 3307 on our local network.

    • Have magic forward all communication on localhost port 3307 to a MySQL instance living on Amazon EC2.

    The secret sauce requires setting up a forwarding port using ssh. Example:

    ssh -L 3307:127.0.0.1:3306 myuser@myhost

    This statement will open a terminal prompt on capstormlabs.com and a tunnel listening on 127.0.0.1 that forwards traffic on local port 3307 to port 3306 (e.g. MySQL) on capstormlabs.com. With any CopyStorm product the remote MySQL instance can be reference with a connection string like:

    //localhost:3307/myDatabaseName

    If you are hungry for more information then see for all the details.

    How Do CopyStorm Snapshots Work

    A CopyStorm Snapshot is a database store containing tamper resistant snapshots of records from any Salesforce table where the snapshots are captured based on rules provided by a user. This section explores the architecture and implementation of the CopyStorm Snapshot subsystem and contains recipes for common snapshot tasks.

    Good places to start include:

    • CopyStorm Snapshot System Overview

    • How to Setup the Capstorm Recycle Bin

    What are the Minimum CopyStorm Salesforce Permissions?

    The minimum Salesforce backup permissions needed for CopyStorm to copy data from Salesforce to a database are:

    • API Enabled

    • View Setup and Configuration

    Almost all of the time, the following permissions should be granted:

    • View All Data — this permission bypasses sharing rules and often increases performance.

    Help! CopyStorm Cannot Get a License!

    When CopyStorm runs it tries to find a license on the local machine. If a valid license is not found then it requests one from license.capstorm.com.

    If CopyStorm cannot get a license and fails with an error like “Connection Refused” then your firewall is blocking access to license.capstorm.com.

    There are two common solutions to this problem:

    If your browser is using a proxy to connect to the internet then CopyStorm may have to use the same proxy. See for help setting proxy parameters.

    If your company firewall is blocking access to license.capstorm.com, the problem can be fixed by asking your network staff to open port 443 to license.capstorm.com (75.2.67.235).

    If the CapstormCustomerKey.txt file is not installed correctly, move the file to a .

    In all cases the connection to the Capstorm license server can be validated by following the instructions on .

    If your organization will not allow communication with license.capstorm.com, the solution is to send an email to with the following information and we will email you a license file:

    How Do I Fix Random Oracle Login Connection Timeouts?

    On Linux systems the Oracle JDBC driver has a login dependency on the random number generator “/dev/random”. Under certain circumstances, the “/dev/random” generator can take an inordinate amount of time to generate a random number — this can cause unpredictable timeouts when logging into Oracle.

    • See for the technical details.

    CopyStorm releases after 8.40.1 patch 28-Nov-2017 have fixed this problem internally. If you are on an earlier release, this article describes how to fix the issue.

    Open the CopyStorm.sh script in a text editor and add the flag “-Djava.security.egd=file:/dev/./urandom” to the command that launches CopyStorm.

    For example, in our tests we added this flag using the following changes to the CopyStorm.sh script:

    RAND= if [ -e “/dev/urandom” ]; then RAND=”-Djava.security.egd=file:/dev/./urandom” fi

    “$JAVA” -cp “$MYROOT/lib/*” $RAND -Dcopystorm.root=”$MYROOT” -Dhttps.protocols=”$MYPROTOCOLS” $MYAPPLICATION -license $MYLICENSE $*

    Can CopyStorm Create Detailed Salesforce Backup Debug Information?

    There are a number of situations where you may want to review Salesforce backup debug logs from CopyStorm — usually this is because something is “wrong” with the Salesforce infrastructure and the problem needs to be narrowed down enough to encourage Salesforce support to rapidly take ownership. Here are a few examples Capstorm has encountered:

    • A customer had a table where a query would always time out — even when a single row was selected. The problem was a formula column causing problems with the Salesforce infrastructure. Using CopyStorm’s debug information a sample query exhibiting the behavior (even in the Salesforce Workbench) was quickly found:

      • SELECT id, customFormulaColumnName FROM Contact LIMIT 1

    How to Setup a Custom Snapshot Policy

    CopyStorm Snapshots are designed so a user can set up new snapshots for a variety of purposes. This tutorial describes a realistic scenario and then walks thru the steps to setup the associated CopyStorm Snapshot Policy.

    The legal team for the ACME Beach Club has informed the Salesforce administrator that all Account, Contact, Case, and EMail records related to the account Evil Empire need to be retained and any future changes also need to be retained. To prepare for this situation the Salesforce administrator has already added a formula column in Salesforce, LegalArchivalSet__c, that will evaluate to the string “EvilEmpire” for all of the records the legal team wants to be retained.

    The next few sections walk to the steps to setup a CopyStorm snapshot for “Evil Empire” records.

    The first step is to create a new snapshot that will only include tables that the legal department indicated.

    • Set up the top level parameters for the snapshot including a snapshot policy name and description

    How to Login to Salesforce using SSO

    CopyStorm supports a number of authentication mechanisms, including:

    • Salesforce Username & Password (default)

    • The OAuth JWT flow

    • SFDX

    If Salesforce is using SSO to authenticate users, the Username & Password may not work. If this is happening, there are two options to fix authentication:

    How Does CopyStorm Handle Daylight Savings?

    CopyStorm includes logic specific to Daylight Savings or Summer Time changeovers.

    This logic accommodates both time changes and Salesforce record commit latency issues.

    When a CopyStorm job finishes within a few hours of a time change, the next job will re-query for records modified before the time change.

    The next job will re-scan an extra 90 minutes of record changes prior to the time change. This ensures that Salesforce commit latency issues and time change issues do not cause missing records in the database.

    Jobs that run near a time change will take longer to complete.

    This is because the job intentionally reads extra data to ensure that all records are copied. As a result, you will likely see a higher number of “Skipped” records – the job is re-checking data that is already up to date in the CopyStorm database.

    Use JWT or SFDX to authenticate.

  • Manually set the User’s password in Salesforce.

    1. This causes Salesforce to bypass SSO and use its default Username & Password authentication when logging in via the API.

  • What Does CopyStorm Do?

    What’s the Impact?

  • All data is encrypted and the strength of the encryption is controlled by Salesforce.

  • The only time data is at rest is when it is written to your database.

  • Salesforce Minimum Privileges article
    this article
    How to Setup a Custom Snapshot
    How to Export Data from a Snapshot
    • Product Name

    • Product Version

    • IP Address of your computer

    • Salesforce Org Id

    Solution 1: Set Proxy Parameters

    Solution 2: Open Firewall Access to license.capstorm.com

    Solution 3: Verify Installation of CapstormCustomerKey.txt

    In All Cases…

    this page
    supported installation location
    this page
    support@capstorm.com

    If you are not familiar with Linux scripting, the changes say:

    • Set the local RAND variable to blank.

    • If the system has the faster “/dev/urandom” character device:

      • Set the RAND variable to the Java setting which will make Java’s random number generator use “/dev/urandom”.

    • Add the RAND variable to the Java command that launches CopyStorm.

    Workaround for CopyStorm Versions On or Before 8.40.1 Patch Level 28-Nov-2017

    this article

    Hints On Using a Generated VBS Script

    Hints On Using a Generated BASH Script

    Hints On Using a Generated Python Script

    BLAT

    How Many Salesforce Instances Can a Single Computer Backup?

    Suppose a company has five Salesforce production instances and needs to backup all of them with CopyStorm. How many computers or virtual machines are needed?

    This question is a lot like asking “How long is a piece of string?”. Though running many CopyStorm jobs on the same computer will work, the maximum number depends on a lot of factors. Here are a few key questions to ask:

    • What is the largest record each job will need to back up?

      • The primary determining factor in the amount of memory required by CopyStorm is the size of the largest record that must be retrieved from Salesforce.

        • For example, if your Salesforce contains a 500MB Attachment then CopyStorm will need around 1300MB of memory at runtime (500MB for the record from Salesforce, 500MB for the prepared database record, and a bit more for overhead).

        • Except for Attachments and ContentVersions, CopyStorm can usually run in 100-120MB (you will see larger usage in most cases because the system allows it and the application uses more memory to avoid frequent garbage collection).

      • You can discover the size of your largest record in the Salesforce GUI and use this information to estimate CopyStorm memory usage.

    • How often will each backup run?

      • To backup multiple Salesforce instances, where CopyStorm jobs are scheduled to run at the same or overlapping times the total amount of memory required on your computer may need to be increased.

      • Though running two jobs may not double memory usage, the difference will be material.

    • What is the throughput to/from the internet on the computer?

      • The #1 performance bottleneck for CopyStorm is typically the rate at which Salesforce responds to queries.

      • For a single CopyStorm job it is unlikely that throughput to/from the internet will be a problem, but running many CopyStorm jobs simultaneously may swamp a computer’s Ethernet capabilities.

    • What is the throughput to/from the database where CopyStorm backups will be stored?

      • The #2 performance bottleneck for CopyStorm is the rate at which data can be written to the target database.

    The short answer is that you can keep adding scheduled CopyStorm jobs until you are unhappy with the performance. Running several jobs at the same time will rarely be an issue, but running dozens at the same time may require revisiting your computer’s memory and Ethernet performance.

    How Can I Create a Schema-Only Salesforce Backup?

    To create a schema-only CopyStorm backup, you can:

    1. Start with an empty database.

    2. Go to the “Configuration” tab.

    3. Select the “Guardrails” configuration section.

    4. Check the “Schema Only Backup” option.

    5. Press “Start Copy”.

    This will cause CopyStorm to start a new backup, create tables in the database, and copy no table data!

    After the CopyStorm backup has completed, the backup database will contain an empty Salesforce schema that is compatible with CopyStorm/Restore.

    If new tables or fields are added to the Salesforce instance, running CopyStorm again with the same configuration will update the database with the new or modified tables and fields.

    Problems & Solutions

  • Read Encrypted Data — this permissions returns the plain text value for encrypted fields.

  • Query All Files — this permission allows files in private folders to be read.

  • Knowledge User — this license allows draft knowledge articles to be read.

  • There are also several tables that have a restricted syntax, and will not be backed up unless the Salesforce user is an administrator. These tables include:

    • NewsFeed

    • EntitySubscription

    If the source Salesforce instance uses Chatter, or has the Chatter setting “Enable Unlisted Groups” feature enabled, the following permissions should be granted:

    • Manage Unlisted Groups — this permission bypasses Unlisted Groups access checks for Feed records.

    In the scenario where “Forecasting” objects such as “ForecastingQuota” are desired to be backed up and optionally restored, the following user permission is required:

    • Allow Forecasting — this permission grants a user the ability to access and utilize the forecasting features within Salesforce.

    Many people assume that a Salesforce Administrator automatically has permission to access all data. Wrong! Even some core Salesforce tables and fields are hidden from administrators by default. Fortunately, the CopyStorm/Medic Permission Checker tool will find all tables and fields inaccessible for any Salesforce user with the permissions API Enabled and View Setup and Configuration.

    A Wrong Assumption

    A customer had a handful of records in a table where the SOAP API provided invalid XML. CopyStorm’s debug tools gave a trace of the request and response envelopes sent to/from Salesforce. In this case the problem was caused by security middleware that was rewriting part of the response from Salesforce.

  • A customer had a table where every query would return a Salesforce UNKNOWN_EXCEPTION exception. CopyStorm’s debug tools identified the problem query and a short time in Workbench crafted a two column query that reproduced the problem every time.

  • A customer had a table where a query on several records would return a Salesforce UNKNOWN_EXCEPTION exception, though most records could be queried. CopyStorm’s debug tools isolated the records and queries and allowed something short to be given to Salesforce support:

    • SELECT id, customColumn WHERE id IN (‘……’)

  • To view the SOQL generated by CopyStorm, run CopyStorm in command line mode with the “-debug” flag.

    • CopyStorm.bat -debug -run myFile.copyStorm

    • sh CopyStorm.sh -debug -run myFile.copyStorm

    That’s it — you will see the SOQL statements in the command line window.

    To capture the SOAP generated by CopyStorm, run CopyStorm in command line mode with the “-apiTraceFile” parameter.

    Note: The “-apiTraceFile” flag ALWAYS takes a file name as an argument (this is good because the SOAP envelopes tend to be large).

    • CopyStorm.bat -apiTraceFile mytrace.txt -run myFile.copyStorm

    • sh CopyStorm.sh -apiTraceFile mytrace.txt -run myFile.copyStorm

    How to View the SOQL Generated by CopyStorm

    How to View the SOAP Request/Response Packets Generated by CopyStorm

    Change the filter type to use a column expression and only grab records where the LegalArchiveType__c value is “EvilEmpire”

    Check the “active” box, save changes and the snapshot rule will automatically include “Evil Empire” records that are modified in the future. The next step will force a snapshot of all historical “Evil Empire” records.

    At this point the “Evil Empire” snapshot policy is active and will automatically include future activity in Salesforce. For addition information see:

    • How to Export Data from a Snapshot

    • The Snapshot Policy Editor

    • How Do CopyStorm Snapshots Work

    The Scenario

    Create a Snapshot

    Add Existing Records to the New Policy

    Next Steps

    Where Does CopyStorm Store Passwords?

    By default, CopyStorm does not store Salesforce or database passwords. To enable this option, select the “Store Passwords” option when saving a configuration file. When checked, CopyStorm will maintain Salesforce password security by encrypting Salesforce and database passwords in the save file.

    What if I Want to Store Passwords in a Password Manager?

    CopyStorm includes an extensible system which allows the usage of third-party password managers to store Salesforce passwords. The default password storage locations include:

    • Directly within the CopyStorm save file (this is the default).

    • Within a KeePass file named “passwords.kdbx” located in any of:

      • The user’s home directory.

      • The CopyStorm installation directory.

      • A subdirectory of the CopyStorm installation directory named “config”.

      • Any directory adjacent to the CopyStorm installation directory.

    To use your own password manager, please see our tutorial titled .

    To enforce Salesforce password security using the KeePass password manager to authenticate with Salesforce, you will need:

    • A kdbx (KeePass v2.x) formatted password file containing the username and password of the Salesforce user.

      • For more information on the KeePass password manager, see

      • The user’s Security Token may be either:

        • Appended to the user’s password.

    After installing Perl with the kpcli dependencies:

    • Put the passwords.kdbx file in one of the locations referenced above.

    • Put the kpcli.pl script in one of the locations referenced above (make sure the file is named “kpcli.pl”).

    • Make sure the script is installed correctly by running the command:

    How to Fix Display Issues on Windows

    When running on Windows using Java 1.9 or higher, you may see popups within CopyStorm and CopyStorm/Restore displaying incorrectly. This can occur when using multiple monitors that are configured to use different display scaling settings – a common configuration when running on a laptop computer that is connected to an external display.

    The underlying issue that causes this behavior has to do with how Windows displays applications at different scaling settings. To fix the issue, you can:

    Step 1: Open the File Properties for Java

    CopyStorm may be launched by either javaw.exe or java.exe – if using the Windows version, they will be located at:

    • [CopyStorm]/jre/bin/javaw.exe

    • [CopyStorm]/jre/bin/java.exe

    If there is no jre folder in the CopyStorm installation, then you will need to find the system-installed Java executables.

    Right-click on the executables and select ‘Properties’.

    1. Select “Compatibility”

    2. Select “Change high DPI settings”

    1. Check “Override high DPI scaling behavior.”

    2. Set “Scaling performed by:” to “System”

    After saving / applying the settings (and restarting CopyStorm), the application should display everything correctly!

    How Do I Convert a BASE64 String Into Its Native Format?

    Salesforce stores the Attachment and ContentVersion bodies as BASE64 strings — a common question is “How can I turn a database Attachment into a file my application can read?”. Since the data is stored as a BASE64 string, this is equivalent to “How do I convert a BASE64 string into its binary equivalent?”.

    The answer to this question is database dependent.

    Oracle

    To perform BASE64 to binary conversion in Oracle:

    • Download the base64decode() function from the link on oracle-base.com.

    • Use SQL to convert the body of Attachments to their binary format:

      • SELECT id, BASE64DECODE(body) AS rawbody FROM Attachment

    You may want to use the BASE64DECODE() function to create a permanent view to the Attachment or ContentVersion table.

    To convert a BASE64 column to a text column in SQL/Server:

    To convert a BASE64 column to a binary column in SQL/Server:

    How Does CopyStorm Handle Deleted Records?

    CopyStorm copies both active and deleted records from Salesforce to the target database by inspecting the Salesforce recycle bin. When a deleted record is discovered its “isDeleted” column is set to true in the target database.

    The retention policy for deleted records in the target database is set using the Advanced tab parameter “Delete Older Than”. Available values can range from:

    • Remove deleted records immediately.

    • Remove deleted records after they have been deleted in Salesforce for 7 days.

    • Never remove deleted records.

    Delete Older Than
    Description

    There are also situations where a record is deleted in Salesforce but is not discovered by CopyStorm. This situation may occur when:

    • A user deletes records in Salesforce and empties the recycle bin BEFORE CopyStorm has run.

    • A system administrator empties the global recycle bin.

    • A Salesforce API program does a hard delete on Salesforce records.

      • A hard delete bypasses the Salesforce recycle bin mechanism.

    When a Salesforce record is hard-deleted it is usually wise to use the CopyStorm/Medic Fix IsDeleted tool to mark the appropriate records as deleted in the target database. For information on when and how the CopyStorm/Medic tool should be used see .

    How to Export Data From A Snapshot

    While the brave at heart will export data from the CopyStorm Snapshot subsystem using raw database SQL queries, most people will want some help from a GUI. If you happen to be a “brave at heart database person” then jump to the article on CopyStorm Snapshot Data Storage.

    For the Rest of Us…

    The CopyStorm Snapshot Explorer tool is designed to find and export data from a CopyStorm Snapshot. The tool is launched using a hyperlink next to the snapshot of interest in the CopyStorm GUI.

    For this tutorial we will:

    • Launch the Snapshot Explorer

    • Search for Contacts in a snapshot that match specific criteria.

    • Export the found contacts to a CSV file.

    See the following articles for additional help.

    How to Login to Salesforce Using SFDX

    For developers, a useful way to provide CopyStorm with Salesforce credentials is via a SFDX username or alias. When an SFDX username is provided, CopyStorm calls out to SFDX to create the a Salesforce session token, relying on SFDX to do all of the OAuth dirty work!

    Step 1: Change the CopyStorm credential type to SFDX Username or Alias.

    Step 2: Enter an SFDX username or alias.

    As a final step, optionally test the connection using the Test Salesforce Connection button.

    As a best practice, we recommend using an SFDX alias rather than a username in order to support easier reuse when new scratch orgs are created.

    How Do I Upgrade CopyStorm?

    Upgrading CopyStorm can be a simple task if you follow one rule:

    • Do not store site specific customizations or configuration files in the CopyStorm distribution directory.

    If you have set up your Capstorm software by following our Best Practice Guide, you should be ready to continue with the upgrade. If you have included site specific files in the CopyStorm distribution directory then move them into their own directory before starting the upgrade.

    To upgrade a CopyStorm installation:

    • Download the latest CopyStorm release from https://www.capstorm.com/download

    • Rename the existing CopyStorm root directory to a new name.

    • Unzip the CopyStorm distribution archive.

    • Move the unzipped CopyStorm directory to the same location as your previous CopyStorm installation.

    • Copy any site-specific configuration files from the previous installation directory to the newly moved installation directory.

      • Be sure to include the file, if it is installed in the CopyStorm product directory.

    You’re finished! CopyStorm distributions have always been backwards compatible with configuration files from previous versions so there is nothing else to change.

    WARNING: DO NOT unzip a CopyStorm distribution over an existing installation of CopyStorm.

    Where Does CopyStorm Keep Salesforce Metadata?

    Metadata tables in a CopyStorm database are primarily copies of the equivalent Salesforce metadata calls plus mappings from Salesforce to CopyStorm names for tables and fields. These tables are the “CopyForce” tables found in the CopyStorm database.

    CopyForceTable

    CopyForceTable maps the Salesforce API table name to the CopyStorm created database table name. It contains the same fields as a Salesforce DescribeSObjectResult. Where possible CopyStorm uses the same name, but there are several reasons why CopyStorm may use a different table name:

    • Names that are the same as reserved words in the target database will be modified.

      • For example, User is renamed to User2 in SQL/Server.

    • Table and column name size limitations in Oracle dictate shortening longer names.

    For more information, see

    CopyForceTableField maps table field names to CopyStorm created field names. It contains the same fields as a Salesforce field.

    For more information, see:

    CopyForceTableChildRelationship maps parent table names to child table names. It contains the same fields as a Salesforce ChildRelationship.

    For more information, see:

    How to Fix ALTER COLUMN Errors

    CopyStorm does its best to keep column definitions in the target database exactly the same as the corresponding definitions in Salesforce. Normally this happens automatically as CopyStorm performs required ALTER TABLE/COLUMN statements on the target database. This article describes what to do when an ALTER fails. An ALTER may fail for several reasons:

    • A column data type in Salesforce changes. Few databases support this conversion automatically.

      • For example, changing a String to a Number.

    CopyStorm Snapshot System Overview

    CopyStorm’s Snapshot System creates tamper resistant snapshots of Salesforce records under conditions that are specified by a customer. Examples:

    • Snapshot all deleted records.

    • Snapshot modifications to closed Opportunity records.

    • Snapshot modifications to Case records where the custom file archiveStatus__c is set to Active or Continuous.

    How Does CopyStorm Handle Internal Schema Upgrades?

    When a new version of CopyStorm is released, adjustments to the internal CopyStorm data model may be required. By default, CopyStorm automatically handles database version upgrades. To disable automatic schema upgrades, refer to the .

    CopyStorm’s default behavior is to display a Schema Upgrade Notice dialog to the user:

    From this dialog, you can:

    • View all pending schema upgrades.

    • View specific details about a schema upgrade, including the underling SQL to be executed.

    How is DateTime Data Stored?

    In Salesforce all Date/Time data is stored in UTC — . UTC is not a time zone but rather a time standard used commonly around the world.

    For practical purposes, we can assume that UTC is the same as the older GMT (Greenwich Mean Time) standard and is the current time in London, UK.

    CopyStorm also stores all Date/Time values in UTC and it is up to an application to convert UTC values to the timezone of each application using the data. This makes a lot of sense for systems with users accessing the same data from wildly different timezones. Each user expects to see Date/Time values displayed in their local time zone!

    This section lists a few techniques for converting from UTC to the local timezone of the computer hosting the CopyStorm database.

    Example query:

    SELECT systemmodstamp ,DATEADD(hh,((DATEDIFF(ss,systemmodstamp,GETDATE())-DATEDIFF(ss,systemmodstamp,GETUTCDATE()))/3600), systemmodstamp) AS LocalTimestamp FROM Account

    There are two things to note with this solution:

    How Many API Calls Does CopyStorm Use?

    In general, CopyStorm uses the minimal number of API calls possible to do a backup.

    Detailed information can be found in this table:

    Phase
    Number of Transactions
    Description

    Salesforce SOAP API login() Retirement

    Salesforce has recently announced their plans to deprecate the SOAP API login method. The purpose of this article is to outline the impact to the CapStorm applications that will result from this change to the Salesforce platform. More information about this change to the Salesforce platform can be found .

    When using CopyStorm, the only Salesforce credential type that uses the Soap API login is the "Username and password" option. Note: This does not include OAuth Username and Password.

    This change to the Salesforce platform will have a few noteworthy impacts on the CapStorm family of applications. These changes will only affect version 10.65.1 (V5.4 of the CapStorm Container) and newer:

    • CapStorm applications using the Username and Password Salesforce login type will fallback to Salesforce API version 64.

    Where Are the Foreign Key Relationships?

    The first time a programmer brings a CopyStorm database into ERwin (or another data modeling tool) one of the first questions asked is:

    • Where are the relationships between tables?

    The “database equivalent” question is:

    • Why doesn’t CopyStorm generate FOREIGN KEY constraints?

    The short answer to this question is:

    The addition of Foreign Key constraints would dramatically increase the complexity and cost of extracting data from Salesforce without improving the performance of database queries.

    How to Login as a Connected Application

    To connect to Salesforce using the , CopyStorm can be configured with:

    1. The OAUTH Consumer Key and Certificate.

    2. The username and endpoint for the Salesforce instance.

    JWT Authentication can be enabled in Salesforce by following . The overall process is to:

    1. Create a Connected Application.

    How to Generate SQL for a Snapshot

    The CopyStorm Snapshot subsystem stores record data in database XML column types and many database professionals may not be familiar with how to write SQL queries to read snapshot data. Though we do not expect many people to write their own SQL queries against CopyStorm snapshots, we have include a query generator to help a programmer to get started.

    The basic procedure is:

    • Open the Snapshot Explore for the snapshot you want to query.

    • Select a table and the columns you want in the query.

    How to Fix SQL/SQL Server the 1024 Column Limit

    For normal tables, SQL/Server has a hard limit of 1024 columns. This article explains what to do if your Salesforce table has more than 1024 columns.

    SQL/Server will support up to 30,000 columns per table but to achieve this columns above the 1024 limit must be created as SPARSE columns. A sparse column is a column whose value is stored in a special column that contains an XML document. Naturally, sparse columns are more expensive to search and update than regular columns but they do provide a way to get past the 1024 limit.

    The produced to fix a problem table is:

    1. Turn a table into a wide table by adding a new column to hold sparse column values.

    2. Identify which columns to change to sparse columns.

    Can Two CopyStorm Jobs Run on the Same Database at the Same Time?

    Having multiple CopyStorm jobs run on the same database at the same time is perfectly OK if the two jobs are processing different Salesforce tables. However, what if two CopyStorm jobs are running at the same time on the same set of tables? How can this happen?

    • CopyStorm is scheduled to run every 30 minutes.

    • A CopyStorm job starts at 12:00.

    • At 12:30 the first CopyStorm job is still running because there were a LOT of updates in Salesforce.

    How Do I Validate a CopyStorm Backup?

    Since, in nearly all cases, Salesforce is a live system that is always changing, it can be difficult to prove that a CopyStorm backup is complete. There are, however, techniques that can be used to gain confidence that a backup is “complete.”

    One common approach sites take is to compare record counts reported by Salesforce with record counts in the CopyStorm backup. This approach works pretty well as long as the following facts are understood.

    • Salesforce does not include archived or deleted records in reported record counts. CopyStorm backs up both of these record types and may report more records than indicated by Salesforce.

    • By default, CopyStorm will not back up a record until it is unchanged for approximately 2 minutes. There is a good reason for this default behavior and it is because of the “” feature. This means that Salesforce may report slightly more records than CopyStorm

    How to Login to Salesforce With an Authenticator

    To connect to Salesforce using a Time-Base One-Time-Pad (TOTP) Authenticator code, CopyStorm can be configured with:

    1. A TOTP Authenticator App Code.

    2. The username and password for the Salesforce instance.

    TOTP authentication can be enabled in CopyStorm by selecting the “One-Time Password Authenticator” credential type:

    CapstormCustomerKey.txt

    CopyForceTableField

    CopyForceTableChildRelationship

    https://developer.salesforce.com/docs/atlas.en-us.api.meta/api/sforce_api_calls_describesobjects_describesobjectresult.htm
    http://www.salesforce.com/us/developer/docs/api/Content/sforce_api_calls_describesobjects_describesobjectresult.htm#i1427375
    http://www.salesforce.com/us/developer/docs/api/Content/sforce_api_calls_describesobjects_describesobjectresult.htm#i1427334

    Step 2: Go to High DPI Settings

    Step 3: Override High DPI scaling

    Launch the Snapshot Explorer

    Select a Snapshot

    Select a Table and Fields

    Build a Query and Preview Results

    Export Records to a CSV File

    For Additional Help

    Snapshot Explorer Reference

    Usage

    Salesforce performs a hard delete.

    • There are a few tables that Salesforce hard deletes by default.

    0

    Any deleted records copied from Salesforce are immediately deleted from the target database.

    7

    Deleted records are removed from the target database after they have been deleted in Salesforce for 7 days.

    this best practice article

    A blank value means that deleted records are never removed from the target database.

    Snapshot all changes to Account and Contact records.

  • Snapshot all changes made to Contact records by User myuser@demo.capstorm.com

  • As you may suspect, the conditions that can be specified to trigger the snapshot of a record can be quite rich.

    There are several broad situations where a CopyStorm Snapshot is a great choice.

    By default, CopyStorm creates one snapshot — the Default Recycle Bin. The CopyStorm recycle bin is similar to the Salesforce recycle bin but with many features unavailable within Salesforce.

    • Any type of record can be snapshot — even those not supported by the Salesforce recycle bin.

    • The recycle bin can keep deleted records forever (or any other specified duration)

    • Data retention policies can be applied on per table basis. For example, it is easy to tell the system that Accounts, Contacts, Cases, and Opportunities should be snapshot forever while other snapshot records should be deleted after 90 days.

    In addition to a record’s data, the snapshot system will remember the field definitions in place at the time that the record version is added to the snapshot.

    Sometimes it makes sense to delete old records from Salesforce but the records still need to be kept around “just in case”. This is easily achievable with a CopyStorm snapshot.

    • Define a new CopyStorm snapshot with a filter describing the records that should be snapshot.

    • Run the snapshot by hand. This will scan existing Salesforce records and snapshot those that meet the filter.

    • Delete the snapshot records in Salesforce.

    The snapshot data can be retrieved using the CopyStorm Snapshot Explorer or by running your own SQL queries.

    Once records have been stored in a CopyStorm Snapshot, a common use case is to display the snapshot records in the Salesforce GUI. If you have technical staff with the required skills, this is a fairly simple task.

    • Create REST Web Services for querying a CopyStorm Snapshot. You can host the web services in the container of your choice.

    • Craft a handful of Salesforce lightning components that use the web services.

    • Add the lightning components to Salesforce pages.

    If this sounds too complex, our reference implementation based on Apache/Tomcat can get you started (contact support@capstorm.com for the status of our reference implementation).

    The original motivation for CopyStorm Snapshot came from a customer:

    We have hundreds of active lawsuits at any given point in time and we need to snapshot all changes to related Salesforce records.

    A CopyStorm snapshot can be used to solve this problem by creating a new snapshot that contains a filter to define the criteria under which records should be snapshot. If this snapshot is activated, CopyStorm will automatically apply the filter to records as they are backed up and snapshot them if they meet the filter criteria. Examples:

    • Snapshot all changes to Contracts associated with Account “Acme Industries” that occur after 2019-01-01.

    • Snapshot all email communications with Contacts working for “Acme Industries” and any emails to the domain “acme.com”.

    To assist compliance, snapshot records will be tamper resistant. Any tampering will be detectable because it will cause the computed fingerprint associated with a record to change. Records can be made tamper proof if an snapshot’s database protections are set to write-only.

    CopyStorm Snapshot is implemented as a set of documentation tables that are automatically created and maintained by CopyStorm. There is nothing a user has to do to create or maintain the tables — they are created on first use of the snapshot system and maintained by CopyStorm.

    Like other other CopyStorm tables, the schema is documented and the tables are directly queryable by customers. However, unlike other CopyStorm tables, you may need a little help constructing queries since most of the data for snapshot records is stored as XML. The good news: CopyStorm’s Snapshot Explorer can be used to easily generated base SQL queries which a customer can modify for their specific needs (We have a hard time remembering how to construct XML based queries for databases too!).

    Use Cases

    Deleted Record Retention — Recycle Bin

    Permanent Record Deletion in Salesforce

    Show Snapshot Records in Salesforce

    Meet Compliance Requirements

    Implementation Details

    SQL/Server 2016 has a direct solution to this problem (see this article).

  • This example does not take daylight savings time into consideration.

    • See this script for a solution that takes daylight savings time into consideration.

  • Example query:

    SELECT systemmodstamp, systemmodstamp + (systimestamp – SYS_EXTRACT_UTC(systimestamp)) LocalTime FROM Account

    Example query:

    SELECT systemmodstamp, systemmodstamp + INTERVAL (TIMESTAMPDIFF(SECOND, UTC_TIMESTAMP() , NOW())) SECOND FROM Account

    Example query:

    SELECT systemmodstamp, systemmodstamp AT TIME ZONE ‘UTC’ FROM Account

    How Do I Convert From UTC to My Local Time Zone?

    Microsoft SQL/Server

    Coordinated Universal Time

    Oracle

    MySQL

    PostgreSQL

    This means that Username and Password login type will still be functional for the near future.

  • It should be noted that Salesforce objects and fields made available in Salesforce API v65 and newer will not be available for backup/restore when using Username and Password login.

  • CapStorm applications using the Username and Password Salesforce login type will display a warning when using the "Test Salesforce Connection" button, informing the user that using this login method is causing the application to fall back to API version 64.

  • CapStorm applications using the Username and Password Salesforce login type will report an exception to notify the user that SOAP API login is being deprecated. This exception is purely informative, and does not indicate any errors in the application.

  • CapStorm applications making use of any of the supported OAuth login options will be unaffected by these changes.

  • We recommend that users migrate to using any of the available OAuth login methods in order to stay up to date with Salesforce's best practices and make use of the latest CopyStorm supported Salesforce API version. Please see the following pages for more info on configuring CopyStorm to make use of OAuth login:

    • OAuth JWT

    • OAuth Username and Password

    • OAuth Client Credentials

    How to determine if SOAP API login is being used?

    How will this change impact CapStorm applications?

    here

    What user action is required?

    In a database, the purpose of a Foreign Key constraint is to enforce referential integrity. A Foreign Key constraint does nothing to improve query performance — that is a job for indexes (CopyStorm does create the indexes!). If Foreign Key constraints were enabled on a CopyStorm database then several hugely complex problems start appearing:
    • Records MUST be inserted/updated in an order that maintains referential integrity — 100% of the time.

    • Bi-directional relationships must be backed up in two passes. This type of relationship occurs frequently in Salesforce.

    Let’s look at one simple referential integrity example. Salesforce’s Account table contains a “Parent Account” field. If there are three accounts in Salesforce (A, B, and C), and A is the parent of B and B is the parent of C then the records have to be written to the database in the order:

    • A then B then C

    Any other order will cause a referential integrity error in the database. Add a few dozen tables and their cross relationships and the complexity of this problem explodes (along with the runtime)!

    Let’s look at a simple bi-directional relationship where it is impossible to copy the records in the proper order.

    • Each User record in Salesforce references a Profile record.

    • Each Profile record in Salesforce references the User table via the Profile.ownerId field.

    This is a problem because it makes it impossible to copy the “correct record first” due to the mutual dependency. Any restore approach (if Foreign Key constraints are enabled) would require an approach like:

    • Copy the User record, leaving the ProfileId field null.

    • Copy the Profile record.

    • Update the User record’s ProfileId field with the id of the Profile record restored in the previous step.

    Does this sound like a lot of data retrieval and graph theory to make a backup work? In practice the problem is much harder than these examples when the reality of hundreds of tables and their interrelationships are added.

    Though CopyStorm does not declare Foreign Key constraints, it does create indexes on all columns that are involved in foreign key relationships. This means that JOINs will run fast (even though ERwin will not display a nice picture of the relationships).

    When you need to know the key relationships there are several good sources:

    • Salesforce publishes ERDs of their data models.

    • CopyStorm maintains tables of all relationships in several tables included in every CopyStorm backup.

    How Does CopyStorm Help?

    ALTER the definition of the identified columns to be sparse.

    The following example code creates a regular table and then turns it into a wide table and changes most of its columns to be sparse.

    CREATE TABLE SparseExample (

    id BIGINT IDENTITY

    ,name VARCHAR(50)

    ,address VARCHAR(255)

    ,other VARCHAR(MAX)

    );

    ALTER TABLE SparseExample ADD sparseColumns XML COLUMN_SET FOR ALL_SPARSE_COLUMNS;

    ALTER TABLE SparseExample ALTER COLUMN name VARCHAR(50) SPARSE;

    ALTER TABLE SparseExample ALTER COLUMN address VARCHAR(255) SPARSE;

    ALTER TABLE SparseExample ALTER COLUMN other VARCHAR(MAX) SPARSE;

    INSERT INTO SparseExample(name,address,other) VALUES(‘Capstorm’, ‘Florida’, ‘Now is the time for all good men…’);

    SELECT name, address,other, sparseColumns FROM SparseExample

    Google SQL Server Wide Table and you will find many helpful articles.

    Overall Solution

    Example

    For Additional Help

    In the end, you will want to be comfortable that CopyStorm is backing up all of your data and Capstorm provides several tools in CopyStorm’s companion product, CopyStorm/Medic to help you.
    • The CopyStorm/Medic Scan Timestamps tool will do an exhaustive comparison between records in Saleforce and the CopyStorm database and report both on records that do not match, records that will be made to match in a future backup, and records that will be inserted in a future backup.

    • The CopyStorm/Medic Count Records tool will count records both in Salesforce and CopyStorm and compare the results. This technique works until a Salesforce table becomes too large to count records (e.g. a SELECT COUNT() always times out).

    When the backup is missing a column the problem is nearly always because the Salesforce credentials given to CopyStorm do not have permission to see the column. It is common for a person so assume that a Salesforce Admin user can see everything — unfortunately this assumption is commonly wrong.

    When the backup is missing a table then it either has been explicitly excluded in CopyStorm or the Salesforce credentials given to CopyStorm do not have permission to see the table. Include the table and/or change permissions then then table will appear in the backup.

    This root cause to this problem is almost always one of two issues:

    The XYZ column is a formula. Formula columns are not updated on a record unless a non-formula column changes because CopyStorm relies on record timestamps to efficiently perform incremental backups and timestamps do not change when a formula value changes. If you want specific formula columns to always match Salesforce then use the CopyStorm/Medic Refresh Columns tool periodically to update formula columns.

    The permissions on column XYZ were changed to make it visible. When CopyStorm first sees a column it assumes that it is a brand new column and creates a corresponding column in the backup database. As a new column, any values for the column are then picked up an incremental backup. If column XYZ is not really a new column but rather a column newly made visible then older records containing XYZ will have a null value until the timestamp on the containing record changes. The solution is to force an update on the problem column using the CopyStorm/Medic Refresh Columns tool.

    Salesforce believes in time travel

    Common Issues

    The ABC Table is Missing Column XYZ from Salesforce

    The ABC Table is Missing in the Backup

    Data in Column XYZ Is Not Being Updated

    SQL Server

    The scheduler starts a second CopyStorm job at 12:30.

    In practice this is unlikely to cause an issue because the second job will not catch up with the first job (e.g. the two jobs will never be operating on the same table at the same time by happenstance). However, this is a condition that is easily AND SHOULD BE avoided.

    To prevent the same job running twice (or more times) is the flock command. The following script ensures that the CopyStorm job never runs twice at the same time:

    If the script is run twice, the second script will wait (at the flock) command until the first script completes. Once the first invocation of the script completes, the flock command will return and the second invocation will continue.

    The easiest way to prevent a job from running twice on Windows is to use the Windows scheduler. By default, the Windows Scheduler will not start a scheduled task again if a previous invocation is still running.

    How to Avoid a Job Running Twice on Linux and Mac

    How to Avoid a Job Running Twice on Windows

    SELECT
        CONVERT(
            VARCHAR(MAX),
            CAST(” AS XML).value(‘xs:base64Binary(sql:column(“Body”))’, ‘VARBINARY(MAX)’)
        ) AS RESULT
    FROM
        Attachment
    SELECT
        CAST(” AS XML).value(‘xs:base64Binary(sql:column(“Body”))’, ‘VARBINARY(MAX)’)
    FROM
        Attachment
    (
    flock -x 9
    sh /home/greg/bin/CopyStorm/CopyStorm.sh -run /home/greg/copyStormConfig/MyJob.copyStorm
    ) 9>/tmp/MyJob.lock
  • Stored in a text attribute named “Security Token”

  • A copy of the kpcli.pl Perl script (version 3.2) available here:

    • http://kpcli.sourceforge.net/

    • The Perl script is used for both Windows and Linux installations — the Windows-formatted exe will not work.

  • A Perl installation with all dependencies for kpcli installed.

    • Dependencies can be found at the kpcli homepage (http://kpcli.sourceforge.net/)

  • If kpcli.pl is installed correctly and the password entry path is correct, it will print the Salesforce credentials.

  • Restart the CopyStorm UI. Under the “Advanced Parameters” section of the Main tab, a “Credential Type” option of “Keepass” will appear:

  • Enter the KeePass file password and the path to the Salesforce user’s password entry:

  • Test the connection by pressing the “Test Salesforce Connection” button.

    • If the KeePass file password is incorrect, or if the kpcli.pl script is set up incorrectly, an error will appear which looks like:

    • If the Entry does not appear in the Keepass file, an error will appear which looks like:

  • perl /path/to/kpcli.pl -kdb /path/to/passwords.kdbx --command "show -f /password/entry"
    

    How to Use the KeePass Password Manager

    How to Add a New Password Manager
    https://keepass.info/
    Changes to the length of a column in Salesforce force a fundamental data type change in the database. Some databases support this, some do not.
    • For example, changing a VARCHAR to a CLOB.

  • A new Salesforce column or a length change to an existing column makes the database table “too wide” for the database.

    • This issue typically only arises in MySQL.

  • Solutions for this class of problems are discussed in the following sections.

    A solution that almost always works for any database type is to DROP the problem table and let CopyStorm rebuild it from scratch. When a table is dropped in the database, CopyStorm will detect the change and automatically rebuild it.

    There are two common ways to DROP a table. The simplest approach is to do one of:

    • Use your favorite SQL tool to run a “DROP TABLE tableName” command.

    • On the Database Reset section of the CopyStorm Configuration tab temporarily check the “Force Rebuild” option and run CopyStorm with only the problem table selected. CopyStorm will drop and rebuild the table when it runs.

    The following approach is more complex but avoids re-downloading data from Salesforce:

    • Rename the table causing the ALTER issue.

    • Open CopyStorm and use it to recreate the problem table WITHOUT downloading any data. The procedure is:

      • Go to the Configuration tab.

      • Select just the problem table in the Core Configuration section.

      • Enter a date far into the future for the “Modified Since” value (e.g. 1/1/2150). This parameter can be found in the section.

      • Start the copy. CopyStorm will create the table but not transfer data.

      • Close CopyStorm without saving changes.

    • Copy the contents of the renamed table into the table just created by CopyStorm:

      • INSERT INTO tableName (fieldName1, fieldName2, …) SELECT fieldName1, fieldName2, … FROM RenamedTable

    • Drop the renamed table.

    Oracle does not support directly changing a column type from VARCHAR2 to CLOB. Unfortunately, this operation is needed when a column in Salesforce increases length to an amount not supported by an Oracle VARCHAR2 column.

    To fix this problem, you can rebuild the problem column by hand.

    For example, suppose that the column Account.myField__c has increased in length from 2000 to 8000. To hold values in Oracle the corresponding column in Oracle needs to change from VARCHAR2 to CLOB. The following SQL statements will make this happen:

    • ALTER TABLE Account ADD scratch CLOB NULL

    • UPDATE Account SET scratch=myField__c

    • ALTER TABLE Account DROP COLUMN myField__c

    • ALTER TABLE Account RENAME COLUMN scratch TO myField__c

    MySQL has a unique design property among databases that can cause issues when backing up Salesforce: A table cannot be declared wider than the database page size.

    When a new column is added in Salesforce or a column’s length is increased, MySQL sometimes reports a “Row Size Too Large” error when increasing a column size or adding a column would push a table beyond the maximum database page size.

    Any solution that backs up all record data involves changing the data type of some VARCHAR columns to TEXT. This works because TEXT columns take less space in a table row than VARCHAR types because TEXT column data is not stored within a table row.

    The easiest solution is to drop the table and let CopyStorm rebuild it.

    • Starting with CopyStorm version 7.37.10, CopyStorm will automatically store “enough” VARCHAR columns as TEXT to make the table row size small enough.

    • In earlier CopyStorm versions, the parameter “Max Varchar” on the Configuration tab can be adjusted until table creation works.

      • “Max Varchar” determines the largest string that will be stored as a VARCHAR, larger strings will be stored as TEXT.

      • This parameter can be found in the configuration section.

    An alternate solution is to change some of the longer columns in your table from VARCHAR to TEXT:

    • ALTER TABLE myTable__c MODIFY myColumn__c LONGTEXT CHARACTER SET utf8

    Cross-Database Solutions

    Oracle Specific Solutions

    MySQL Specific Solutions

    Approve or Disapprove of the changes.

    • Approving the changes will cause CopyStorm to execute all upgrade SQL.

    • Disapproving the changes will cause CopyStorm to terminate.

    • Note: By default, CopyStorm automatically applies the upgrades.

  • View the progress of the approved changes.

  • CopyStorm offers users the ability to view details about an individual internal schema upgrade.

    Users have the ability to see:

    • Schema Upgrade Description

      • High level information about the purpose of the upgrade.

    • SQLassociated with the Schema Upgrade

      • This provides users with the ability to copy & run the SQL manually.

      • Note: For some upgrades, SQL can also be generated dynamically by CopyStorm. In these cases, it is not appropriate to run upgrade SQL manually. Please contact support@capstorm.com before proceeding to run any upgrade SQL manually.

    *Note:*The Schema Upgrade shown in the above screenshots are for an update to introduce support for off-database partitions. To learn more about how off-database partitions work, refer to the documentation.

    When Schema Upgrades are not approved, the following dialog will be shown:

    From this point, users have the options to:

    • Exit

      • Terminate the CopyStorm application

    • Cancel

      • Return to the Schema Upgrade Notice Dialog

    Schema Upgrade Notice Dialog

    documentation

    Viewing Individual Upgrade Details

    What Happens When Changes Are Not Approved?

    Setup

    3

    In this step CopyStorm reads Salesforce table definitions for all tables being backed up. By default it takes a single API call per 100 tables.

    Backup

    1 * Number of Tables

    CopyStorm uses at least 1 API call for each Salesforce table in the backup set. If there are no records to be backed up or if there are fewer than 2000 records to be backed up then this is the only API call used.

    The number of records that can be read per API call varies by table in Salesforce. For most tables, between 1000 and 2000 can be returned for each API call. However, there are a few tables that return a single record per API call. This includes:

    • Attachment

    • ContentVersion

    • EventLogFile

    For example:

    A frequent incremental CopyStorm backup of 100 tables that includes Attachments would usually take a number of API calls equal to:

    • 3 + 3 + 99 + The Number of Changed Attachments

    Bootstrap

    3

    There are several operations that take place each time CopyStorm connects to Salesforce:

    • Find the name of all visible tables in Salesforce (1 API Call)

    • Cache the definition of the User and Profile tables (1 API Call)

    • Read the User record for the current User (1 API Call)

  • Configure Mutual Authentication, including a Digital Signature and appropriate OAuth Scopes.

  • Update the Connected Application Policies to allow appropriate users to login to Salesforce.

  • OAUTH logins can be enabled in CopyStorm by going to the Advanced Parameters dialog on the Main tab:

    After selecting the Oauth 2.0 JWT login type, provide the credentials needed to authenticate with Salesforce:

    Parameter Name
    Default Setting
    Required
    Description

    Keystore

    Yes

    Path to a JKS or PKCS12 Keystore containing the private key used to sign JWT requests.

    OAUTH JWT flow
    this tutorial

    OAuth Connection Parameters

    Go to the Preview stage and click on the “Generate Query” button. The system will open a dialog which shows the SQL that matches your query. Copy and Paste the generated SQL and you will have a good starting point for your own query.

    The generated SQL queries provided by CopyStorm should help you avoid a deep dive into a study of how to build an XML column query for your specific database type.

    To practice this procedure see:

    • Snapshot Explorer

    • How to Export Data from a Snapshot

    • The How to Setup a Custom Snapshot tutorial

    • The reference page Column Expression Filter Rule.

    Launch the Snapshot Explorer from the Snapshot Tab

    Choose A Snapshot

    Select a Table and Columns for the SQL

    Open the Preview and Set a Filter

    View the Generated SQL

    To configure a TOTP Security Key in Salesforce:

    1. Open the User Details page.

    2. Click on the link to Connect a One-Time Password Authenticator.

    3. Select “I Can’t Scan the QR Code”.

    4. Copy the Key into CopyStorm.

    5. Generate a Code in CopyStorm and paste it into Salesforce.

    6. Click on the “Connect” button in Salesforce to complete the connection.

    7. Save the CopyStorm Configuration File.

    Enabling TOTP Authentication in CopyStorm

    https://help.salesforce.com/s/articleView?id=sf.add_time-based_token.htm&type=5

    Enabling TOTP Authentication in Salesforce

    How to Fix PBES2 SecretKeyFactory Errors in Snowflake

    When connecting to Snowflake using the “private_key_file” and “private_key_file_pwd” parameters, Copystorm may report an error with the text:

    • PBES2 SecretKeyFactory not available

    This error indicates that the certificate file is encrypted, and that the Java installation used by CopyStorm does not support the encryption used to secure the certificate file.

    This is a known issue in the Snowflake driver (details can be found here) – with multiple possible solutions.

    The simplest solutions are to:

    • Update the CopyStorm Java version to version 21 or later – Java 21 includes the required libraries.

    • Modifying the Private Key File to be unencrypted. While this is not advised due to security concerns, it will resolve the issue by bypassing the problem encryption logic.

    A more complex solution is to:

    • Update CopyStorm with an encryption library that adds support for the encryption type.

    The remainder of this article details the “complex solution” – integrating a third-party library with CopyStorm to enable the missing encryption algorithm. Instructions in this document are for the BouncyCastle security provider.

    BouncyCastle is an open-source standard cryptographic library. It can be added to CopyStorm to enable support for additional encryption functions, including the PBES2 function that is missing in Java versions 20 and earlier. For more information about Bouncy Castle, please see .

    To add the BouncyCastle PKIX library to CopyStorm, there are three steps:

    1. Add the library JAR files to the CopyStorm lib/ directory.

    2. Add a JVM argument in the CopyStorm.bat or CopyStorm.sh launch script.

    3. Update the Java installation’s java.security file to enable BouncyCastle.

    BouncyCastle jars can be downloaded here:

    You will need to download two JAR files:

    • bcprov-jdk18on-[version].jar

    • bcpkix-jdk18on-[version].jar

    To add the JARs to CopyStorm, copy them into the [CopyStorm]/lib/ directory.

    The following JVM argument is added to the CopyStorm.bat or CopyStorm.sh script:

    • -Dnet.snowflake.jdbc.enableBouncycastle=TRUE

    To add the parameter in Linux:

    • Modify this line of CopyStorm.sh:

      • “$JAVA” -Dcsapp.class=CopyStorm -jar “$MYROOT/lib/CapstormAppLoader.jar” “$@”

    • Adding the parameter:

      • “$JAVA” -Dnet.snowflake.jdbc.enableBouncycastle=TRUE -Dcsapp.class=CopyStorm -jar “$MYROOT/lib/CapstormAppLoader.jar” “$@”

    To add the parameter in Windows:

    • Modify this line of CopyStorm.bat:

      • SET JVM_ARGS=

    • Adding the parameter:

      • SET JVM_ARGS=-Dnet.snowflake.jdbc.enableBouncycastle=TRUE

    This step requires modifying the java.security file to add BouncyCastle support to Java.

    The java.security file is located in the Java installation directory. For example, in the Windows release of CopyStorm, it can be found at:

    • [CopyStorm]/jre/conf/security/java.security

    To add BouncyCastle:

    • Open the java.security file.

    • Find the lines that begin with “security.provider.”.

    • Add a new line to the end of the list.

    • The new line will look like:

    Changes will take effect the next time CopyStorm is launched.

    • Close any running instances of CopyStorm.

    • Start a new CopyStorm instance by running the CopyStorm.bat or CopyStorm.sh script.

    Help! I Am Getting a Certificate Error (PKIX Path)

    If your site is using a self-signed certificate to establish SSL (HTTPS) connections you may see an error like the following when attempting to connect to Salesforce:

    Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
                    at sun.security.validator.PKIXValidator.doBuild(Unknown Source)
                    at sun.security.validator.PKIXValidator.engineValidate(Unknown Source)
                    at sun.security.validator.Validator.validate(Unknown Source)
                    at sun.security.ssl.X509TrustManagerImpl.validate(Unknown Source)
                    at sun.security.ssl.X509TrustManagerImpl.checkTrusted(Unknown Source)
                    at sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(Unknown Source)
                    ... 26 more
    Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
                    at sun.security.provider.certpath.SunCertPathBuilder.build(Unknown Source)
                    at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(Unknown Source)
                    at java.security.cert.CertPathBuilder.build(Unknown Source)
                    ... 32 more

    This type of error typically means that your network is using a self-signed certificate. To make CopyStorm (or any other Java based application) work with your certificate, you must add the certificate to Java’s trusted store file “cacerts”.

    To automatically add the certificate

    • Open the “Help” menu in the top left of the application GUI and select the “Load Network Certificates” option:

    • This will open the “Certificate Viewer” popup where you can view, approve, or export the necessary certificates:

    • Approve the certificates by clicking the “Approve” button. This will create a keystore file called “CapStormKeyStore.jks” in the OR the current user’s home directory that will contain the approved certificates. CapStorm applications will use this keystore file for SSL traffic.

    • Get a copy of your certificate.

      • This will be a CER or CRT file (example: mycompany.crt).

    • Copy the certificate to the certificate directory in your CopyStorm installation:

      • [CopyStormRoot]/jre/lib/security

    If your environment requires that multiple certificates be installed, you will need to import each certificate using a unique alias:

    • ....\bin\keytool -import -keystore cacerts -file firstcertificate.crt -alias firstcertificate

    • ....\bin\keytool -import -keystore cacerts -file secondcertificate.crt -alias secondcertificate

    If you have encountered this problem, it is better in the long run to use a “cacerts” file for a Java runtime that is installed globally on your computer. The procedure is the same, but the “cacerts” file is in a different location. If you take this approach then remove the “jre” directory from CopyStorm and the application will use the system default Java.

    Here is a with more details — please reference it if you need more help.

    Where Does CopyStorm Keep Past Revisions of Salesforce Metadata?

    When metadata backup is enabled for CopyStorm a table named SFMetaFileProperties will be created in the target database to hold metadata backups. In addition a table named SFMetaFilePropertiesHistory will be created to hold past revisions of metadata.

    The columns in SFMetaFileProperties mimic the FileProperties data structure returned from the Salesforce Metadata API:

    Column
    Description

    id

    The companion table “SFMetaFilePropertiesHistory” has the same structure as SFMetaFileProperties but with two additional columns:

    Column
    Description

    It is doubtful that you will want to access these tables directly. However, CopyStorm’s companion product, CopyStorm/Restore, uses these tables to provide a metadata report experience that can be performed with surgical accuracy.

    How Does Capstorm License Management Work?

    This article explains how Capstorm license management works and provides tips on diagnosing license management problems.

    When a Capstorm product connects to Salesforce it also checks for a valid product license in the file “license.txt”. The “license.txt” file will be located in the same directory as the script used to launch the Capstorm product. If a license.txt file is not found or a valid non-expired license is not found in the file, the Capstorm product will issue a request to the Capstorm license service to retrieve (or generate) a license.

    When issuing the license request to the Capstorm license server, the CapstormCustomerKey.txt file will be used to identify the installation. If the CapstormCustomerKey.txt file is not valid, a message indicating the issue will be shown.

    If a Capstorm product fails to retrieve/generate a license it is usually because the connection is blocked by a firewall rule. Diagnosing and confirming this condition can be done using a web browser. Here’s how.

    To retrieve or generate a license, a Capstorm product makes a https request in the following form:

    Where:

    • salesforceOrgId is the full 18 character unique identifier of your Salesforce organization.

    • productName is the name of the product for which a license is desired.

    • productVersion is the version number of the product.

    For example:

    If the request is successful the license server will return a JSON string in the following form:

    Information from the JSON string will be added to the product’s license.txt file.

    If a firewall is blocking access to the Capstorm license server then pasting a license request into a browser will almost always provide a meaningful message. If you receive a “Connection Refused” response then a firewall is likely blocking access to license.capstorm.com. You need to tell your network administrator to open ports 80 and 443 to license.capstorm.com (75.2.67.235).

    Here are a few URLs you can click on to test the connection to the license manager:

    Product
    Test URL

    How Does CopyStorm Work?

    This article explains how CopyStorm optimally decides which records are copied from Salesforce.

    The Most Important Point

    CopyStorm’s default behavior is to perform an incremental copy from Salesforce every time it runs. There are no special parameters to set — just use the defaults and CopyStorm will incrementally update your Salesforce backup.

    How CopyStorm Selects Records to Copy

    CopyStorm minimizes the number of records processed during each run by using record timestamps stored in the CopyStorm database from previous runs.

    For example, if the most recent timestamp for an Account in the CopyStorm database is 14-Jul-2013 at 12:00:00.000 then there is no need to read records from Salesforce that were modified before this timestamp.

    The following diagram illustrates how CopyStorm reads records for each selected table:

    The details are a bit more complex than the above diagram — for example, records are not read one at a time in the code. However, this is the exact logical process followed by CopyStorm.

    Advanced Timestamp Details

    This section provides a bit more detail on exactly how timestamp values are used by CopyStorm. You do not need to grasp this section to understand how CopyStorm works.

    Salesforce has an interesting quirk — records are not committed to a Salesforce database in timestamp order. The implications of this are:

    • At 13:01 a SOQL query indicates that there are 1000 records created earlier than 13:00.

    • At 13:02 the same SOQL query may indicate that there are 1001 records created earlier than 13:00.

    It seems that records written to Salesforce “take a little while” to be committed to the database AND are committed in no particular order.

    CopyStorm overcomes this Salesforce quirk using two parameters on the Advanced tab:

    • The SFDC Commit Latency parameter indicates how long to wait for Salesforce to commit records. The default is 300 seconds.

      • This means that, by default, CopyStorm will not read a record from Salesforce until it has a timestamp at least 300 seconds old.

    • The Timestamp Latency parameter indicates how many seconds to subtract from the most recent timestamp found in CopyStorm.

    To sum up the details, the SOQL used by CopyStorm really looks like:

    • SELECT * FROM TT WHERE TT.systemmodstamp>=(MostRecent – “TimestampLatency”) AND TT.systemdstamp <=(CURRENT_TIME – “SFDC Commit Latency”)

    In Salesforce a query of the form “SELECT * FROM TT” will often fail with a timeout error on large tables. To avoid this problem CopyStorm runs every SOQL query with a LIMIT. For most tables the LIMIT value is set to 20,000 — but is configured to be smaller for a handful of tables known to have problems with this high of a limit.

    The default LIMIT value can be overridden on the Advanced tab using the “Row LIMIT per Query” option — however, changing this parameter generally results in non-optimal behavior.

    In the case where all records in a batch have exactly the same timestamp, CopyStorm dynamically increases the LIMIT value until the end of records is reached or not all records have the same timestamp. When this type of adjustment is required it is rarely noticed unless a Salesforce table has 100,000’s of records with exactly the same timestamp.

    If you would like to know about further Salesforce quirks CopyStorm has to manage (and be convinced that you don’t want to write your own CopyStorm) take a look at this blog post: .

    How to Add a New Database Password Manager

    CopyStorm supports reading Database credentials from a user-supplied Database password manager.

    This feature was introduced to eliminate the need to:

    • Change the saved password in many CopyStorm configuration files.

    • Provide the password to CopyStorm on the command line due to security rules.

    In addition to security benefits, this feature allows you to use your own company-wide password manager.

    The process to add a new Database password manager to CopyStorm is to:

    How to Run CopyStorm in Batch Mode

    CopyStorm can be configured to provide a headless Salesforce backup by running in batch/background mode and leveraging the built-in scheduler on your computer. This article will show you how.

    The base script used to launch the CopyStorm UI can also be used to start CopyStorm as a headless Salesforce backup application (required for a batch job). To configure the CopyStorm command line:

    1. Save your CopyStorm configuration file using the “Encrypted” and “Save Passwords” options on the CopyStorm “Save As” dialog.

      • This will create a file named “MySettings.copyStorm” (using the name you choose for the file).

    How to Fix Task, Event, and Other Table Timeouts

    During the initial backup of Salesforce instances which include large numbers of old Tasks or Events, CopyStorm may experience repeated Salesforce timeout issues when running SOQL queries on these tables. This article explains approaches for solving these problems.

    Once the initial backup of the Task and/or Event tables is complete, the Salesforce timeout issue goes away and the recommendations on this page are no longer needed.

    Note that these recommendations apply to any Salesforce table, but this issue is rarely seen elsewhere.

    Within the Salesforce infrastructure there are multiple levels of data storage — within this section we will refer to them as Tier-1, Tier-2, and Tier-3. Frequently used data (and most tables) tend to be kept in fast Tier-1 storage. Data in some tables (like Task) are migrated to slower storage as they age and are not queried by a user. Eventually most old Task records will be migrated into the slowest storage tier, Tier-3, and become fairly time consuming to query. When data has been migrated to Tier-3 storage, the only way to cause it to move back go faster storage is to attempt to read the Tier-3 data. When old data has been referenced enough times it will be “promoted” into faster storage — even old Task records can migrate from slow Tier-3 storage back to Tier-1 storage if they are referenced frequently.

    When CopyStorm first attempts to backup the Task table it runs a query like:

    SELECT * FROM Task ORDER BY SystemModStamp ASC LIMIT 20000

    How Do I Fix a Salesforce SOAP Entity Not Recognized Error?

    If you have a security gateway that manipulates XML returned from Salesforce before passing it along to CopyStorm, you may see a Salesforce SOAP Entity Not Recognized error like:

    • ConnectionException: Found invalid XML. could not resolve entity named ‘deg’ (position: START_TAG seen …1133;敌湈त 2;喚솕驘&# 20077;°… @122:9536)

    This error means that your gateway has converted a standard XML character representation (e.g. “°”) into its equivalent HTML entity (in this case “°”). XML parsers are not required to understand the hundreds of entity tags used by HTML (and many, including the one used by the core WSC Salesforce libraries, do not).

    Due to this issue, starting with version 8.37.1, CopyStorm has augmented the standard WSC parser to understand nearly all HTML entity tags. If you encounter an entity tag missed by CopyStorm, this article explains how to fix the issue.

    To add a new entity to the core Salesforce XML parser:

    The general Salesforce rule is to expect 1 record per API call if a record contains a BASE64 column (e.g. a CLOB / File Data).

    The ID of this metadata record — unlike other IDs in Salesforce it is not guaranteed to be non-null OR unique. In short, internal Salesforce objects violate the normal non-null uniqueness rule.

    metatype

    The type of metadata in this record (e.g. CustomObject, ApexTrigger, etc…). Note that if a meta type is contained within another meta type (e.g. CustomField lives within CustomObject) then it will not have an entry in this table. The data will be contained in the parent record for the object.

    fileName

    The name of the file the metadata API requires for the record.

    fullName

    The full API name of the record.

    manageableState

    This field will contain “unmanaged” for types of metadata that can be redeployed.

    namespacePrefix

    For installed packages this contains the name of the package’s namespace.

    metaxml

    For records that require a companion “-meta.xml” this field contains the content.

    content

    The raw base64 encoded data for this meta record.

    body

    For records in UTF-8, contains the decoded value of the content column.

    createdById

    ID of the user in Salesforce who created this metadata record. NOTE: this value may be null.

    createdByName

    Name of the user in Salesforce who created this metadata record. NOTE: this value may be null.

    createdDate

    Timestamp of when the record was created.

    lastModifiedById

    ID of the user in Salesforce who last modified this metadata record. NOTE: this value may be null.

    lastModifiedByName

    Name of the user in Salesforce who last modified this metadata record. NOTE: this value may be null.

    lastModifiedDate

    Timestamp of when the record was last modified.

    historyDate

    Timestamp of when this history record was written. Older versions have older historyDate values.

    version

    The history date represented as the number of milliseconds since 1-Jan-1970.

    Create a text file named “HTMLEntityResolver.xml”.

  • Put the following text into the file:

    • ``

  • Add as many Entity tags as necessary. Each will either override or supplement the entity tags built into CopyStorm.

  • Put the file in the “config” subdirectory of the CopyStorm installation directory.

  • Finally, send an email to support@capstorm.com to tell us you had to add a new entity. We will add it to our built-in list.

    Our standard list includes all of the entities defined on this Wiki page.

    Add an Entity to the Core Salesforce XML Parser

    Maintenance
    Database Schema

    security.provider.N=org.bouncycastle.jce.provider.BouncyCastleProvider

  • Where N is the next sequential number.

  • Adding BouncyCastle to CopyStorm

    Step 1: Add BouncyCastle JAR files to CopyStorm

    Step 2: Add JVM Argument to CopyStorm

    Step 3: Add BouncyCastle to Java

    Step 4: Restart CopyStorm

    here
    https://www.bouncycastle.org/download/bouncy-castle-java/#latest

    Keystore Password

    Yes

    Password used to access the Keystore (blank if the Keystore does not have a password).

    Key Alias

    Yes

    The name of the private key used to sign JWT requests.

    Key Password

    Yes

    The password used to access the private key.

    OAUTH Client Id

    Yes

    The Salesforce-generated Client Id for the Connected Application.

    Username

    Yes

    The login Id of the CopyStorm Salesforce user.

    Token Validity (minutes)

    240

    Yes

    The lifetime of JWT access tokens. If the token expires during the CopyStorm run, CopyStorm will re-authenticate and get a new token.

    LIMIT Related Details

    Other Quirky Details

    SOQL’s Seven Deadly Sins

    Navigate to the certificate directory in a shell (Linux) or command prompt (Windows) and run the command:

    • ....\bin\keytool -import -keystore cacerts -file mycompany.crt

    • The tool will ask you for a password. It is “changeit”.

  • You’re done! CopyStorm will now connect to Salesforce without a PKIX error.

  • To manually add the certificate

    best practice setup CapstormConfig directory
    great article

    CopyStorm/PostgreSQL

    CopyStorm/H2

    CopyStorm/Restore

    {“license”:{“id”:1,”ipAddress”:”38.114.70.254″,”licenseKey”:”2520b633-13fd-4488-800e-449526035835″,”product”:”CopyStorm/MySQL”,”version”:”Test”,”sfdcOrganization”:”CAPSTORMTEST000000″,”grantDate”:”2013-08-10″,”createdDate”:”2013-08-10″,”modifiedDate”:”2014-04-02″,”lock”:”q/nI2XtrIaof6u0CdEVSe28EDxjiUUW21uB8h9mpQfE\u003d”,”note”:””,”ipOrganization”:”Capstorm”,”ipDomain”:”wisperisp.com”,”ipCity”:”Edwardsville”,”ipCountry”:”United States”,”ipRegion”:”Illinois”},”successful”:true}

    CopyStorm/MySQL

    https://license.capstorm.com/LicenseStore/GetLicense?sfdcOrg=CAPSTORMTEST000000&product=CopyStorm/MySQL&version=Test&instanceType=sandbox

    CopyStorm/SQL Server

    https://license.capstorm.com/LicenseStore/GetLicense?sfdcOrg=CAPSTORMTEST000000&product=CopyStorm/SQL%20Server&version=Test&instanceType=sandbox

    CopyStorm/Oracle

    https://license.capstorm.com/LicenseStore/GetLicense?sfdcOrg=salesforceOrgId&product=productName&version=productVersion&instanceType=sandbox
    https://license.capstorm.com/LicenseStore/GetLicense?sfdcOrg=CAPSTORMTEST000000&product=CopyStorm/MySQL&version=Test&instanceType=sandbox

    Write a Java class that extends the class com.aslan.sfdc.connect.credentials.AbstractJDBCUserPasswordCredentials

  • Package the new Java class in a jar and place it in the “lib” subdirectory of the CopyStorm installation.

  • Add a new CredentialsRegistry.xml file to CopyStorm’s config directory to register thenew credential manager with CopyStorm.

  • The Java class needs to extend com.aslan.sfdc.connect.credentials.AbstractJDBCUserPasswordCredentials, and will need to override/implement the following methods:

    Method Signature
    Required
    Description

    String getUsername()

    Yes

    Returns the username used when authenticating with the Database.

    String getPassword()

    Yes

    In addition to the required methods above, there are several convenience methods which may be used by credential managers:

    Method Signature
    Description

    void fireCredentialsComplete(boolean complete)

    Enables or disables the “Test Database Connection” button.

    void addRowToUI(String label, String toltip, JComponent editor, JPanel panel, int row

    Adds a new editor to the UI. This method can be used in the injectIntoUI() method to maintain consistent styling with the rest of the CopyStorm UI.

    String encrypt(String text)

    Click Here to view the Java source of Capstorm’s built-in Keepass Database password manager.

    Feature Overview

    Writing the Java Class

    Example Credential Manager: Keepass

    0f4e25aa-KeepassJDBCUserPasswordCredentials.java
    10KB
    Open

    On Windows run the command:

    • CopyStorm.bat -run MySettings.copyStorm

  • On Linux or Mac run the command:

    • sh CopyStorm.sh -run MySettings.copyStorm

  • If the notification feature built into CopyStorm is used then this is likely the only command you will need.

    There are a number of optional command line switches (documentation available here), but you do not need this information to go through the process in this article.

    If you do not want to use CopyStorm’s built-in email notification or you want to be notified even when the CopyStorm program fails to start then you may want to use the CopyStorm Batch tab to build a starting script.

    In practice, a script that does a bit more than run CopyStorm is often used for a batch job. In a typical batch job an organization wants to be notified if a CopyStorm job fails and many organizations also want to be notified any time CopyStorm runs. Though an organization is always free to write their own script for launching CopyStorm, the CopyStorm GUI has a built-in tool for creating a launch script. The generated launch script is often very close to what is desired:

    • The CopyStorm tool can create a launch script in a variety of scripting languages.

    • The generated launch script is readily customizable.

    • The script is easy to run as as a scheduled job under CRON or Windows Scheduler.

    The Batch File tab on the CopyStorm GUI is used to create a script for launching a headless Salesforce backup, running CopyStorm as a batch job. Once the required parameters have been specified, press the “Generate Script” button to create a launch script and then press the “Save Script” button to save the script to disk.

    Parameter
    Required
    Description

    Script Format

    Yes

    Indicates the scripting language to be used for the generated script. Options include:

    • bat — Windows BAT language.

    • vbs — Windows Visual Basic.

    • bash — Linux/Mac shell script.

    • python — The Python scripting language.

    Most Linux or Mac computers manage scheduled jobs using the built-in cron tool. If the script that runs CopyStorm is called RunProductionCopyStorm.sh:

    • Run the command “crontab -e”

    • Add the following line to the crontab to run CopyStorm once a day at 17:00

      • 0 17 * * * sh ~/RunProductionCopyStorm.sh

    For additional information on the format of a crontab entry see the Wikipedia article on cron.

    Here is an example crontab from one of Capstorm’s servers:

    Scheduled jobs on Windows are usually managed using the Windows Scheduler. The following procedure will add a CopyStorm job using a script named RunProductionCopyStorm.vbs to the Windows Scheduler:

    Find and Open the Windows Scheduler

    Open the Create Basic Task Wizard

    Follow the Create Basic Task Wizard Steps

    Step 1: Create a Script That Runs CopyStorm

    Advanced Scripts

    Step 2: Schedule the CopyStorm Job

    Schedule on Linux/Mac

    Schedule on Windows

    If a large number of Tasks are in Tier-3 storage then this query will often timeout — sometimes it will timeout multiple times as CopyStorm tries to re-run the query (by default up to 5 times).

    The good news is that this problem tends to go away after the initial backup, because the Tasks that need to be backed up going forward are generally still in fast storage.

    Note that each of the possible solutions on this page are one-time tasks that rarely have to be repeated.

    If you ask Salesforce, they can increase the amount of time a query can run before timing out. Once Salesforce makes the change, update the “Max Timeout (seconds)” option in the “Advanced” popup on CopyStorm’s Main tab before restarting your backup job.

    This solution increases the number of times CopyStorm will attempt to re-run a query if it times out. This usually works because repeatedly running the same query tends to force more data to migrate to faster storage tiers. This parameter is called “Reconnect Delay” and is located in the Salesforce Network configuration section of the CopyStorm Configuration tab.

    • Set the CopyStorm “Reconnect Delay” to a large value (20 or greater).

    • Select just the Task table.

    • Run CopyStorm.

    This solution requires knowing the date of the earliest Task in your Salesforce instance. Once this date is known then use the “Modified Since” and “Modified Thru” CopyStorm options to backup a selected slice of Tasks.

    For example, if the earliest Task has a SystemModStamp of 1-Feb-2000:

    • Go to the Configuration tab.

    • Select the Maintenance configuration section.

    • Set Modified Since to 2000-02-01T00:00:00.000Z

    • Set Modified Thru to 2001-02-01T00:00:00.000Z

    • Select just the Task table.

    • Run CopyStorm. It will only backup Tasks from the year 2000.

      • If the query still times out, then decrease the timebox.

    • Repeat the first four steps for the next timebox.

    This solution performs a backup of Tasks based on the sort order of Task.Id rather than Task.SystemModStamp.

    Here is the process when applied to the Task table (but the same process will work for any table):

    • Truncate the Task table.

    • Select only the Task table on the Configuration tab “Select Tables to Copy” section.

      • You can also type just “Task” into the input box rather than select it from the popup.

    • In the Maintenance configuration section of the Configuration tab, check the “Ignore Timestamps” option.

      • If you do not see this option then make sure that the “Advanced” Configuration Level is selected.

    • Run CopyStorm. This will backup records based on their unique Salesforce Id.

      • If Salesforce or the database fails during this procedure restart CopyStorm — it will continue backing up by Salesforce Id starting from where it last stopped.

    • Perform the following steps to get the CopyStorm database into a state where incremental timestamp-based updates will work going forward:

      • Uncheck the “Ignore Timestamps” option. This will cause CopyStorm to perform subsequent backups based on record timestamps.

      • Set the “Modified Since” parameter to LAST_WEEK (or any timestamp earlier than when you started this solution).

      • Run CopyStorm. This will back up all Task modifications that occurred while performing the Id-based backup.

    After these steps are completed, CopyStorm will be able to perform subsequent backups using Salesforce timestamp data (e.g. CopyStorm backups will be incremental).

    Background

    Solution 1: Increase Your Salesforce Query Timeout

    Solution 2: Increase CopyStorm’s Reconnect Attempts

    Solution 3: Timebox the Backup

    Solution 4: Do an Id Based Backup

    Help! CopyStorm Did Not Copy/Update a Record or Field

    This articles explores situations where CopyStorm appears to miss an update or insert of a record from Salesforce and the solutions to correct the CopyStorm database. The root causes tend to be one of the following:

    • Salesforce permission changes altered what columns are visible to the credentials used when running CopyStorm.

    • Salesforce permission changes altered what records are visible to the credentials used when running CopyStorm.

    • There is a problem altering the CopyStorm schema to match Salesforce.

    • The “Salesforce believes in Time Travel” problem.

    When CopyStorm discovers a new column from the Salesforce metadata it automatically creates the new column in the database and assumes that it must be a new column in Salesforce. Here is the scenario where changing Salesforce permissions make it look like CopyStorm missed updating column.

    • The Salesforce credentials used by CopyStorm do not have permission to see the column Contact.MyCustom__c.

    • On Monday the Contact table is backed up with CopyStorm.

    • On Tuesday morning an administrator changes permissions to allow the CopyStorm Salesforce account to see Contact.MyCustom__c

    • On Tuesday afternoon an incremental backup of the Contact table happens.

    How do you fix this issue? There are two easy approaches:

    • Use CopyStorm/Medic’s tool.

    • Run CopyStorm with the following options:

      • Enter the name of the problem table in the Tables to Copy box.

      • Enable the Force Updates option.

    Since CopyStorm can only backup Salesforce records it can see, if a Salesforce permission change makes new records available they normally will not be picked up until their timestamp changes. Here is how to make CopyStorm rescan all records in a table and pick up missing records.

    • Enter the name of the problem table in the Tables to Copy box.

    • Enter 1/1/1990 in the Modified Since option.

    • Run a Copy

    • CopyStorm will rescan all records and insert any missing records into the database.

    If a field is altered or added in Salesforce and CopyStorm finds it impossible to make the same change to the database then CopyStorm will record an error and refuse to backup data to the table until the error is resolved.

    The quickest way to fix this problem is:

    • Enter the name of the problem table in the Tables to Copy box.

    • Click on the Force Rebuild option.

    • Run a backup and CopyStorm will drop the problem table, recreate it, and then repopulate it with data from Salesforce.

    If the quick fix is too drastic for your case, the see the article.

    First, this problem does not occur unless CopyStorm internal parameters are modified but it is included in this article for completeness (and because it is rare condition that few people know about). The end of this section describes how to make it possible for the “Time Travel” issue to occur but you may have to wait months for it to happen!

    CopyStorm achieves fast incremental backup of Salesforce by using the timestamp on Salesforce records. Logically CopyStorm does the following each time it runs:

    • Read the most recent timestamp from the CopyStorm database and call it “T”

    • Run SOQL that looks like: SELECT * FROM TableName WHERE timestamp >= T

    The “Time Travel” problem is that Salesforce DOES NOT always commit records in timestamp order. This means that a record whose timestamp is 12:02 may show up in Salesforce BEFORE a record with a timestamp of 12:01. This does happen often but when it does it is likely that any program doing incremental copies based on a timestamp may:

    • Save all records modified at timestamp 12:02 or earlier in the first run MISSING the one record modified at 12:01.

    • Start searching for new records using timestamp 12:02 in the second run and NEVER SEE the 12:01 record.

    Fortunately it is possible to pretend that Salesforce always writes records in timestamp order by not processing records that have been modified in the past 2 minutes. How did we pick 2 minutes? We worked with a lot of high volume sites and also simulated massive Salesforce loads that reproduced the problem.

    Occasionally a person evaluating CopyStorm will decide that it is skipping a record when performing an experiment like:

    • Backup all Contacts

    • In Salesforce, modify a Contact.

    • Immediately run CopyStorm. It will copy no records because the change is less than 2 minutes old.

    When the evaluator emails support@capstorm.com we point them to the original time travel post and suggest that they run CopyStorm again. Of course, it picks up the changed record the second time.

    If you are doing CopyStorm work on a sandbox and are willing to live with the “time travel” problem you can tell CopyStorm to pretend that a safe amount of time to wait is 1 second. Here is how:

    • Select the section of the CopyStorm Configuration Tab.

    • Click on the Edit... button next to Internal Parameters.

    • Set SFDC Commit Latency and Timestamp Latency to 1.

    How to Determine Performance Bottlenecks

    The CopyStorm “Copying…” tab has real-time metrics which help identify a components that are limiting the speed of a database backup. The metrics, located in the lower right hand corner of a “Copying…” tab are described in this article.

    There are two primary factors which limit the speed of a CopyStorm job:

    • The rate at which Salesforce delivers data to CopyStorm.

    • The rate at which the target database accepts data from CopyStorm.

    Metrics highlighted in the following image provide data indicating which component is the bottleneck at your site:

    Metrics are divided into three sections:

    Section
    Sample Data
    Description

    In a balanced system:

    • The “S” threads will be blinking blue almost all of the time.

      • This means that a steady stream of data is being delivered from Salesforce.

    • The “D” threads will be grey most of the time but blinking blue rapidly.

    • The data throughput values will be less than 50ms and the database write speed will be less than 20ms.

    In a system where the database is the bottleneck:

    • The “S” threads will often turn grey.

    • The “D” threads will be blue most of the time.

    • The database write speed will be large.

      • This value is elapsed time for a single request to the database to write a block of records.

    In a system where Salesforce is the bottleneck:

    • The “S” threads will be solid blue most of the time.

      • This means that they are waiting for a response from Salesforce.

    • The “D” threads will be grey most of the time.

    • The first data throughput number will be large.

    The most common issue we see is that CopyStorm and the database are not in the same data center. The underlying issue is that the protocols used to talk to relational databases require close proximity between the application and the database for great performance. Until we discover a way to increase the speed of light, CopyStorm running in India and talking to a database in Canada will give slow performance. You can solve this problem by running CopyStorm and its corresponding database in the same data center.

    CopyStorm will write data to a database as quickly as Salesforce delivers it. If the “S” threads are grey, the “D” threads are blue, the data throughput numbers are large, and you are sure that CopyStorm and the database are in the same data center; then the database is likely overloaded. Using system monitoring tools on the database computer will quickly pinpoint the issue — often the database computer will be page-faulting like crazy.

    If the CopyStorm “S” threads are solid blue, the “D” threads are almost always grey, and the first data throughput number is large; then Salesforce is not delivering data rapidly. Even with a modest internet bandwidth of 20M/s, CopyStorm can easily transfer 20,000 – 30,000 accounts per minute. If you are sure that your available bandwidth is high then see your system administrators. There may be network software inspecting and slowing packets from Salesforce.

    Though CopyStorm’s runtime requirements are modest, it cannot control demands made by other applications. Use a local system monitor to see which applications are using a high amount of CPU time. On a balanced system CopyStorm will always be consuming CPU — reading from Salesforce and writing to the target database.

    Configure Connected Salesforce App For CapStorm User

    To ensure seamless integration between CapStorm and Salesforce, you’ll need to configure a Salesforce Connected App.

    This setup enables CapStorm to access Salesforce APIs and retrieve necessary data.

    This guide walks you through the steps to configure a Connected App

    and use it to see exact API responses from Salesforce, particularly for support purposes.

    1. Log in to Salesforce with an administrator account.

    2. Navigate to the Setup Menu:

    Clear the “Modified Since” parameter.

    Returns the password used when authenticating with the Database.

    boolean setRequired(boolean required)

    Yes

    Update the credentials editor to indicate that the connection type does not require credential information (e.g. when using SQL/Server’s integrated security).

    int injectIntoUI(JPanel panel, int startRow)

    No

    Adds any UI elements needed by the password manager to the CopyStorm UI.

    boolean isAvailable()

    No

    Returns true if the password manager should appear as an option in the UI.

    void saveState(Element e, boolean savePasswords)

    Yes

    Adds XML attributes to the provided Element to save any information needed to restore system state. This information is saved to CopyStorm’s configuration file.

    void restoreState(Element e)

    Yes

    Restore XML state saved via saveState()

    String getFingerprint()

    Yes

    Returns a value used to determine whether or not credentials have changed. This is used to determine whether or not a cached session may be used when connecting with the Database.

    boolean isComplete()

    Yes

    Returns true when information provided by the user is enough to attempt a connection to the Database.

    void clear()

    Yes

    Clears out any internal state kept by the password manager.

    Encrypts text. This method can be used in the saveState() function to avoid implementing a custom encryption scheme to support encrypting saved passwords.

    String decrypt(String encryptedText)

    Decrypts text encrypted with encrypt(). This method can be used in the restoreState() function to avoid implementing a custom encryption scheme.

    void saveXMLAttribute(Element e, String key, String value)

    Adds a new attribute to an XML element. This method can be used in the saveState() function to avoid interacting with the Element directly.

    String loadXMLAttribute(Element e, String key)

    Retrieves an attribute to an XML element This method can be used in the restoreState() function to avoid interacting with the Element directly.

    CopyStorm create the column Contact.MyCustom__c in the database.

  • The value for all modified records are backed up — including their value for Contact.MyCustom__c

  • On late Tuesday afternoon someone notices that not all records in CopyStorm have the correct value in the MyCustom__c record. All records with timestamps earlier than Tuesday afternoon seem to have the problem.

  • Enter 1/1/1990 in the Modified Since option.

  • Run a backup.

  • Salesforce Permission Changes Altered What Columns Are Visible

    Salesforce Permission Changes Altered What Records Are Visible

    Problem Altering CopyStorm Schema to Match Salesforce

    The “Salesforce Believes in Time Travel” Problem

    Refresh Columns
    How to Fix ALTER COLUMN Errors
    Salesforce Optimization
    https://license.capstorm.com/LicenseStore/GetLicense?sfdcOrg=CAPSTORMTEST000000&product=CopyStorm/Oracle&version=Test&instanceType=sandbox
    https://license.capstorm.com/LicenseStore/GetLicense?sfdcOrg=CAPSTORMTEST000000&product=CopyStorm/PostgreSQL&version=Test&instanceType=sandbox
    https://license.capstorm.com/LicenseStore/GetLicense?sfdcOrg=CAPSTORMTEST000000&product=CopyStorm/H2&version=Test&instanceType=sandbox
    https://license.capstorm.com/LicenseStore/GetLicense?sfdcOrg=CAPSTORMTEST000000&product=CopyStorm/Restore&version=Test&instanceType=sandbox

    Memory Usage

    84m/201m

    These two numbers indicate:

    • The amount of virtual memory currently in use. In this example, 14 megabytes are in use.

    • The maximum amount of virtual memory used during this session. In this example, 201 megabytes is the maximum memory usage so far.

    For example, if the “Destination Batch Size” is 100 and the database write speed is 4500ms then this means that the database is taking 4.5 seconds to write 100 records (e.g. terrible performance).

    This number indicates how frequently a buffer is ready to be written to the database.

  • The second data throughput number will be small.

  • Read/Write Threads

    S D

    The “S” and “D” values indicate thread execution status:

    • “S”, “R”, and “B” threads read data from Salesforce.

    • “D” threads write data to the target database.

    When a “S” thread is BLUE then it is either reading data from Salesforce or waiting for Salesforce to respond to a read request.

    When a “D” thread is BLUE then it is writing data to the target database.

    When either type of thread is GREY then it has nothing to do or is waiting for the other thread type to catch up.

    Data Throughput

    44ms/16ms

    Common Problems

    Problem #1: Proximity of CopyStorm and the Database

    Problem #2: Overloaded Database

    Problem #3: Slow Internet

    Problem #4: Overloaded Client Computer

    These two numbers indicate:

    • How frequently a write request is being sent to a “D” thread. In this example, 44ms means that a write request was sent to a “D” thread 44 milliseconds ago.

    • How quickly the database processed the most recent write operation. In this example, 16ms means that the last write to the database took 16 milliseconds.

  • Click on the gear icon (⚙️) in the upper right corner.

  • Select Setup.

  • Search for “App Manager” in the Quick Find box.

  • Create a New Connected App:

    • Click New Connected App.

  • Fill in the Connected App Details:

    • Connected App Name: Enter a descriptive name (e.g., “CapStorm Integration”).

    • API Name: This will auto-fill based on the name you enter.

    • Contact Email: Enter a valid email address for contact.

  • Configure OAuth Settings:

    • Check the Enable OAuth Settings box.

    • Callback URL: Enter https://localhost/callback (adjust based on your environment if needed).

    • OAuth Scopes: Select the appropriate scopes. For CapStorm, you’ll likely need:

      • Full Access (full)

      • Perform requests on your behalf at any time (refresh_token, offline_access)

  • Save the Connected App:

    • Click Save.

    • After saving, you’ll be redirected to the Connected App’s detail page where you can find the Consumer Key and Consumer Secret.

      • Make a note of these credentials.

  • Configure Additional Settings:

    • In the API (Enable OAuth Settings) section, adjust any additional settings as needed.

    1. Open Postman and create a new collection named “CapStorm Connected App”.

    2. Configure the Collection for OAuth 2.0:

      • Click on the collection name.

      • Go to the Authorization tab.

      • Set the Type to OAuth 2.0.

      • Scroll Down to Configure New Token.

    3. Enter Token Request Details:

      • Token Name: Enter a descriptive name (e.g., “CapStorm Token”).

      • Grant Type: Set to Password Credentials.

    4. Save and Obtain the Access Token:

      • Click Request Token to obtain an access token.

      • Once successful, click Use Token to apply it to your collection.

    5. Test API Endpoints:

      • Use the access token to make API requests in Postman.

      • Verify that the requests are successful and review the responses.

      • Example ContentVersion Endpoint

    6. Troubleshoot Common Issues:

      • Invalid Grant: Verify that the username, password, and security token are correctly concatenated.

      • Invalid Client ID: Ensure that the client_id and client_secret match those from the Connected App.

    1. Enable OAuth Scopes: Ensure that all necessary OAuth scopes are enabled to provide CapStorm with the required permissions.

    2. Callback URL: Adjust the callback URL based on your specific environment or testing setup.

    3. Security Settings: If you encounter authentication issues, check the security settings and ensure that IP restrictions are configured correctly.

    Configure a Connected App for CapStorm Salesforce Integration

    Step 2: Configure CapStorm User to Integrate with Postman

    Additional Configuration Options

    How Large Does My Database Need to Be?

    When Salesforce says your instance uses 4.2GB of table space and 100.8GB of file space, how much space should you allocate for your CopyStorm Salesforce backup database?

    This is a harder question than it appears because Salesforce computes used space differently than databases. This article describes Capstorm’s guidelines for computing space requirements for CopyStorm databases.

    Space Hogs Salesforce Does Not Count

    Salesforce does not appear to count the cost of indexes when it reports used space. The space used by indexes can add up quickly in a relational database. For example, on SQL/Server we have learned:

    • The core indexes CopyStorm needs to work incrementally plus the primary key index take around 15.25MB per 100,000 table rows.

    • Each index on a reference field takes around 4.3MB per 100,000 table rows.

    In practice, nearly all Salesforce tables contain at least two reference fields (CreatedById and LastModifiedById), and many also contain OwnerId. It is not uncommon for a table to contain 10 or more reference fields.

    In summary, for every 100,000 rows you can expect to need at least this much space for indexes where is always at least 3 and usually much larger:

    • 15.25M + *4.3MB

    Once CopyStorm has built a schema and before any data has been copied, you can guess the amount of space required for indexes with a bit of SQL. Note: In each example, you must substitute “NumberOfRows” with the actual number of rows in Salesforce.

    • SQL/Server: SELECT ((SELECT (15.24 + (4.12*COUNT(*))) FROM CopyForceTableField WHERE tableName=’Account’ and fieldType=’reference’)*(NumberOfRows)/100000.0)

    • Oracle: SELECT ((SELECT (15.24 + (4.12*COUNT(*))) FROM CopyForceTableField WHERE tableName=’Account’ and fieldType=’reference’)*(NumberOfRows)/100000.0) FROM DUAL

    • PostgreSQL: SELECT ((SELECT (15.24 + (4.12*COUNT(*))) FROM CopyForceTableField WHERE tableName=’Account’ and fieldType=’reference’)*(NumberOfRows)/100000.0)

    • MySQL: SELECT ((SELECT (15.24 + (4.12*COUNT(*))) FROM CopyForceTableField WHERE tableName=’Account’ and fieldType=’reference’)*(NumberOfRows)/100000.0

    Any table with a BASE64 column (for example, Attachment and ContentVersion) seem to report much less space usage in Salesforce than in a target database. Often 3-4x more space is needed in a relational database than what is reported in Salesforce.

    We have never seen a case where 5x the size reported by Salesforce is too small but this may be overkill for your case. In most cases sizing the Salesforce backup database to be 4x the size of your file storage and 2x the size of your data storage will be sufficient.

    Tables With Mysterious Sizes

    Just Tell Me How Big to Size My Database

    Access Token URL
    :
    • For Salesforce sandbox: https://test.salesforce.com/services/oauth2/token

    • For Salesforce production: https://login.salesforce.com/services/oauth2/token

  • Client ID: Enter the Consumer Key from your Connected App.

  • Client Secret: Enter the Consumer Secret from your Connected App.

  • Username: Enter your Salesforce username.

  • Password: Enter your Salesforce password followed by your security token.

  • Client Authentication: Select Send client credentials in body.

  • https://example.sandbox.my.salesforce.com/services/data/v57.0/sobjects/ContentVersion/0681F000000LYN4QAO/
    https://example.sandbox.my.salesforce.com/services/data/v57.0/sobjects/ContentVersion/0681F000000LYN4QAO/VersionData

    How to Add a New Salesforce Password Manager

    CopyStorm supports reading Salesforce credentials from a user-supplied Salesforce password manager.

    This feature was introduced when a customer had strict rules on password changes for service accounts in Salesforce and did not want to:

    • Change the saved password in many CopyStorm configuration files.

    • Provide the password to CopyStorm on the command line due to security rules.

    Since this customer used their own company-wide password manager, an extension was added to CopyStorm to allow them to retrieve password information directly from their password manager instead of from CopyStorm configuration files or the command line.

    This article describes how to add a new custom password manager to CopyStorm.

    The process to add a new Salesforce password manager to CopyStorm is to:

    1. Write a Java class that extends the class com.aslan.sfdc.connect.credentials.AbstractSalesforceUserPasswordCredentials.

    2. Package the new Java class in a jar and place it in the “lib” subdirectory of the CopyStorm installation.

    3. Add a new CredentialsRegistry.xml file to CopyStorm’s config directory to register the new credential manager with CopyStorm.

    The Java class needs to extend com.aslan.sfdc.connect.credentials.AbstractSalesforceUserPasswordCredentials, and will need to override/implement the following methods:

    Method Signature
    Required
    Description

    In addition to the required methods above, there are several convenience methods which may be used by credential managers:

    Method Signature
    Description

    CopyStorm discovers all available Salesforce Password Managers by looking for a file named “CredentialsRegistry.xml” in the CopyStorm config directory.

    The following CredentialsRegistry.xml file will load a new password manager named “Keyring”:

    Click Here to view the Java source of Capstorm’s built-in Keepass Salesforce password manager.

    How to Setup the Capstorm Recycle Bin

    By default, CopyStorm has a single snapshot policy named the Default Recycle Bin. The Default Recycle Bin is a regular snapshot policy, implemented using the same features available for custom snapshots, with a few limitations.

    • The name of the Default Recycle Bin cannot be changed.

    • The filter used by the Default Recycle Bin cannot be changed.

    By default, the Default Recycle Bin is not enabled and you should make a few decisions before enabling it.

    • Do you want to restrict the tables where the recycle bin is used?

    • How many days do you want to keep records in the recycle bin?

    • Do you want to keep records from some tables longer than others?

    Once you have made these decisions and applied them to the Default Recycle Bin, simply enable the snapshot and CopyStorm will automatically manage the Default Recycle Bin as part of a backup.

    Prior to setting up our recycle bin, we have made the following choices. (Your criteria will likely be different!)

    • All tables except history and change event tables will be managed by the Default Recycle Bin.

    • The default retention period for a record will be 90 days (after 90 days a record will be deleted from the snapshot).

    • EmailMessages should be retained for a two full years.

    • Accounts, Contacts, and Cases should be retained for a full year.

    Launch the Policy Editor for the Default Recycle Bin

    Set a 90 Day Default Record Retention Policy

    Add Custom Record Retention Rules

    Select Tables to put in the Recycle Bin

    There are two basic ways to select the tables to include in the Recycle bin.

    • A White List can be used to indicate the tables to include.

    • A Black List can be used to indicate the tables to exclude. All tables not on the black list will be included.

    For additional help see the .

    Activate the Default Recycle Bin

    Congratulations! You have successfully setup the Default Recycle Bin.

    String getUsername()

    Yes

    Returns the username used when authenticating with Salesforce.

    String getPassword()

    Yes

    void fireCredentialsComplete(boolean complete)

    Enables or disables the “Test Salesforce Connection” button.

    void addRowToUI(String label, String toltip, JComponent editor, JPanel panel, int row

    Adds a new editor to the UI. This method can be used in the injectIntoUI() method to maintain consistent styling with the rest of the CopyStorm UI.

    String encrypt(String text)

    <Credentials>
       <CredentialType family="Salesforce" name="Keyring" 
          class="com.mycompany.copystorm.credentials.KeyringSalesforceCredentials"
          />
    </Credentials>

    Feature Overview

    Writing the Java Class

    Adding the New Password Manager to CopyStorm

    Example Credential Manager: Keepass

    ca4158cd-KeepassSalesforceUserPasswordCredentials.java
    10KB
    Open

    Example of a Default Recycle Bin Setup

    White/Black List documentation

    Returns the password used when authenticating with Salesforce.

    String getSecurityToken()

    Yes

    Returns the security token used when authenticating with Salesforce.

    int injectIntoUI(JPanel panel, int startRow)

    No

    Adds any UI elements needed by the password manager to the CopyStorm UI.

    boolean isAvailable()

    No

    Returns true if the password manager should appear as an option in the UI.

    void saveState(Element e, boolean savePasswords)

    Yes

    Adds XML attributes to the provided Element to save any information needed to restore system state. This information is saved to CopyStorm’s configuration file.

    void restoreState(Element e)

    Yes

    Restore XML state saved via saveState()

    String getFingerprint()

    Yes

    Returns a value used to determine whether or not credentials have changed. This is used to determine whether or not a cached session may be used when connecting with Salesforce.

    boolean isComplete()

    Yes

    Returns true when information provided by the user is enough to attempt a connection to Salesforce.

    void clear()

    Yes

    Clears out any internal state kept by the password manager.

    Encrypts text. This method can be used in the saveState() function to avoid implementing a custom encryption scheme to support encrypting saved passwords.

    String decrypt(String encryptedText)

    Decrypts text encrypted with encrypt(). This method can be used in the restoreState() function to avoid implementing a custom encryption scheme.

    void saveXMLAttribute(Element e, String key, String value)

    Adds a new attribute to an XML element. This method can be used in the saveState() function to avoid interacting with the Element directly.

    String loadXMLAttribute(Element e, String key)

    Retrieves an attribute to an XML element This method can be used in the restoreState() function to avoid interacting with the Element directly.

    How Do I Create Salesforce Table Views?

    Salesforce has a handful of tables that are almost certainly implemented as database Views internally within Salesforce. Some of the views are quite odd:

    • The ActivityHistory table combines data from the Task and Event table BUT cannot be queried directly using Salesforce APIs.

    Though most Salesforce table views can be read directly, representing them as a view in the Salesforce backup database rather than including them as tables in the Salesforce data backup speeds up CopyStorm backup jobs and reduces the size of database files.

    The following table contains links to SQL that can be used to create database views in your CopyStorm Salesforce backup that will mimic the corresponding Salesforce table views:

    Salesforce Table Name
    View Name
    Link to CREATE VIEW SQL

    After creating the corresponding database view you will no longer need to include the table in your Salesforce backup, speeding up backup time and reducing storage costs.

    ActivityHistory

    ActivityHistoryView

    AccountUserTerritory2View

    AccountUserTerritory2View

    ActivityHistory.sql
    AccountUserTerritory2View.sql

    Does the CopyStorm Database Have Logging Tables?

    Each time CopyStorm runs it records a variety of data into tables in the CopyStorm database:

    • A summary of records written to the database and any exceptions.

      • The content and structure of the tables will be familiar because they mimic what is displayed as progress within the CopyStorm GUI.

    • Changes to field values (see CopyForceFieldHistory in this article).

    • DDL statements (e.g. ALTER TABLE) that were issued against the CopyStorm database.

    CopyStorm database logging tables were introduced starting with the 7.*.* version of CopyStorm.

    The following tables are used for logging:

    Table Name
    Description

    These logging tables are created automatically by CopyStorm. The only changes that should ever be performed by a customer is the deletion of log records — this should be done using .

    The simplest way to view and manage CopyStorm log data is often the tool in CopyStorm/Medic.

    The remainder of this article describes the column structure for each table.

    The CopyForceJob table contains one record for each time CopyStorm successfully connects to Salesforce, connects to the target database, and starts a copy.

    The table contains these columns:

    Column Name
    Data Type
    Description

    The CopyForceJobTable table contains one record for each table that was modified during a CopyStorm run.

    The table contains these columns:

    Column Name
    Data Type
    Description

    The CopyForceJobException table contains one record for each exception that occurred during a CopyStorm run.

    The table contains these columns:

    Column Name
    Data Type
    Description

    The CopyForceDDLLog table contains a record of each DDL statement ran against the CopyStorm database.

    The table contains these columns:

    Column Name
    Data Type
    Description

    The CopyForceFieldHistory table records changes to field value. This table will be empty unless field history tracking is explicitly enabled.

    History records will be maintained even if the referenced table / field is modified or deleted in Salesforce.

    The table contains these columns:

    Column Name
    Data Type
    Description

    The CopyForceMedicJob table contains one record for each time a CopyStorm/Medic job runs.

    The table contains these columns:

    Column Name
    Data Type
    Description

    The CopyForceMedicJobException table contains one record for each exception that occurred during a CopyStorm/Medic run.

    The table contains these columns:

    Column Name
    Data Type
    Description

    CopyForceJob

    Contains a single record for each time CopyStorm runs.

    CopyForceJobTable

    Contains a single record for each table modified in a CopyStorm run.

    CopyForceJobException

    jobId

    integer

    Unique ID for this job. This value is the job’s primary key.

    startTime

    jobId

    integer

    The unique ID of the job that modified the table.

    tableName

    jobId

    integer

    The unique ID of the job where the exception occurred.

    exceptionId

    string

    tableName

    string

    The name of the table addressed by the DDL statement.

    command

    string

    id

    string

    The unique Salesforce record ID of the record that was the source of the data.

    tableName

    string

    jobId

    integer

    The unique ID of the job.

    startTime

    jobId

    integer

    The unique ID of the job where the exception occurred.

    exceptionId

    integer

    CopyForceJob

    CopyForceJobTable

    CopyForceJobException

    CopyForceDDLLog

    CopyForceFieldHistory

    CopyForceMedicJob Table

    CopyForceMedicJobException

    CopyStorm/Medic
    Log Manager

    Contains a record of each exception (problem) encountered during a CopyStorm run.

    CopyForceDDLLog

    Contains a record of all DDL type statements issued against the database.

    CopyForceFieldHistory

    If field history tracking is enabled, this table will record the old and new value each time a field changes (except on record insert).

    CopyForceMedicJob

    Contains a single record for every time a CopyStorm/Medic job runs.

    CopyForceMedicJobException

    Contains a record of each exception (problem) encountered during a CopyStorm/Medic run.

    timestamp

    The time when the job started. Note that this time will be slightly after the start of the CopyStorm executable because it takes a few seconds for CopyStorm to initialize and connect to its data sources.

    endTime

    timestamp

    The time when the job completed. This time is updated as each table finishes and after the entire job completes.

    nCopied

    integer

    The total number of records copied to the target database.

    nImagesCopied

    integer

    The total number of image records copied to the target database.

    nImagesRead

    integer

    The total number of image records read from the target Salesforce Org.

    nDeleted

    integer

    The total number of records deleted from the target database in accordance of the configured retention policies.

    nFieldHistory

    integer

    The total number of field history records inserted into the target database.

    nArchived

    integer

    The total number of record snapshots inserted into the target database via the Snapshot feature.

    nTransactions

    integer

    The number of Salesforce transactions used during the run.

    nExceptions

    integer

    The number of exceptions encountered during the run. If this value is non-zero then details for each exception will be recorded in the CopyStormJobException table.

    configFileName

    string

    The base name of the CopyStorm configuration file used for the run. This value will be NULL if there was no active configuration file.

    configFileDir

    string

    The directory containing the CopyStorm configuration file used for the run.

    copyStormVersion

    string

    The version of CopyStorm that created the log record (e.g. 7.34.1).

    copyStormDir

    string

    The directory in which CopyStorm was installed when the job ran.

    elapsedTime

    float

    The total number of seconds taken by the job to run.

    processId

    integer

    The system process id for the CopyStorm process.

    string

    The Salesforce name of the modified table.

    startTime

    timestamp

    The time when CopyStorm started processing the table.

    endTime

    timestamp

    The time when CopyStorm finished processing the table.

    startTimestamp

    timestamp

    The timestamp of the first record copied from Salesforce when CopyStorm started processing the table.

    endTimestamp

    timestamp

    The timestamp of the last record read from Salesforce when CopyStorm finished processing the table.

    nRead

    integer

    The total number of records read from Salesforce.

    nCopied

    integer

    The number of records inserted or updated in the CopyStorm database.

    nSkipped

    integer

    The number of records read from Salesforce and skipped because they were already up to date in the CopyStorm database.

    nDeleted

    integer

    The number of records deleted from the CopyStorm database.

    nImagesCopied

    integer

    The total number of image records copied to the target database table.

    nImagesRead

    integer

    The total number of image records read from the target Salesforce Org.

    nFieldHistory

    integer

    The total number of field history records inserted into the target database for this table.

    nArchived

    integer

    The total number of record snapshots inserted into the target database for this table via the Snapshot feature.

    nPerMinute

    integer

    The average number of records processed per minute.

    elapsedTime

    float

    The total number of seconds used to process the table.

    startSize

    integer

    The size of the table in bytes when CopyStorm started processing the table.

    endSize

    integer

    The size of the table in bytes when CopyStorm finished processing the table.

    Order in which the exception occurred (starting at 0).

    tableName

    string

    The name of the table being processed when the exception occurred.

    message

    string

    A short message describing the exception.

    traceback

    string

    The full traceback from the exception.

    exceptionTime

    timestamp

    The time when the exception occurred.

    The full DDL command.

    traceback

    string

    If the DDL command failed, this field contains the full traceback from CopyStorm.

    applyDate

    timestamp

    The date on which the DDL was executed.

    The Salesforce API table name.

    fieldName

    string

    The Salesforce API field name.

    oldValue

    string

    The value of the field before it was updated.

    newValue

    string

    The updated value of the field.

    lastModifiedById

    string

    The unique Salesforce ID of the User that last modified the record.

    lastModifiedDate

    timestamp

    The date on which the record was last modified.

    createdDate

    timestamp

    The date on which the history record was created.

    timestamp

    The time when the CopyStorm/Medic job started.

    endTime

    timestamp

    The time when the CopyStorm/Medic job finished.

    elapsedTime

    float

    The total number of seconds that the job ran.

    nTransactions

    integer

    The number of Salesforce transactions used by the job.

    nExceptions

    integer

    The number of Exceptions (problems) reported by the job.

    configFileName

    string

    The name of the configuration file used to start the job.

    configFileDir

    string

    The path to the configuration file used to start the job.

    medicVersion

    string

    The CopyStorm/Medic application version.

    processId

    integer

    The system process id for the CopyStorm/Medic process.

    toolName

    string

    The medic tool ran by the job. This corresponds to the value provided on the -tool command line switch.

    status

    string

    The job status – one of Pending, Running, Cancelled, Finished, or Error.

    output

    CLOB

    The job’s output. The format of this field will depend on the type of job that was ran.

    Order in which the exception occurred (starting at 0).

    message

    string

    A short message describing the exception.

    traceback

    string

    The full traceback from the exception.

    exceptionTime

    timestamp

    The time when the exception occurred.

    Snapshot Data Storage Structure

    CopyStorm stores all snapshot data in the following database tables.

    Table Name
    Description

    CopyForceArchiveToken

    Mapping from string names to integer tokens. The table is used to minimize the size of other tables.

    CopyForceArchiveFilter

    The following diagram illustrates the relationships between the various tables.

    Note: All physical database tables are prefixed with “CopyForce”.

    Column
    Data Type
    Description

    A CopyForceArchiveFilter describes the implementation of Java class which can determine if records should be snapshot. These classes are built into the CopyStorm Snapshot subsystem and include:

    • Deleted Records — determine if a record has been deleted in Salesforce.

    • Column Expression — evaluation of a user supplied expression to determine if a record matches.

    • All Changes — indicate if a record matches if it has any changes.

    • SQL Predicate — use a bit of user supplied SQL to determine if a record matches.

    Column
    Data Type
    Description

    A CopyForceArchivePolicy record holds the definition for a CopyStorm Snapshot — if a record matches the rules for a CopyStormArchivePolicy then it will be written to the policy’s associated database storage.

    Column
    Data Type
    Description

    The CopyForceArchivePolicyStat contains table level statistics about a CopyStorm Snapshot. Statistics about the tables contained in a CopyStorm Snapshot are maintained automatically while the record count statistics require a scheduled job.

    Column
    Data Type
    Description

    The CopyForceArchiveRetentionRule table contains rules that override the default data retention rules for an archive for specific tables. For example:

    • The default retention rule for an archive is set to 30 days.

    • For the Account,Contact, and Case table use a override retention rule to keep them in the archive for 180 days.

    The algorithm which determines the policy for a specific table always selects the matching rule with the longest number of days.

    Column
    Data Type
    Description

    The CopyForceArchiveFieldSet table contains a unique configuration of the fields for a Saleforce table. When a record is snapshot:

    • If the current table field definitions have never been snapshot then create a record in the CopyForceArchiveFieldSet table*.*

    • Associate a CopyForceArchiveFieldSet with each snapshot record. This supports recovering both the schema and data for a snapshot record.

    Column
    Data Type
    Description

    The fields in this type of record are represented as XML in the form below. Naturally, a complete record will contains many more fields and this is only a subset.

    The CopyForceArchiveRecord table contains all snapshot records. Since it can grow quite large sites may consideration partitioning the table based on the policyId column.

    Column
    Data Type
    Description

    CopyForceArchiveRecord field data can be read directly using the XML extensions for your database though most people will use SQL generated from the CopyStorm Snapshot Explorer tool rather than handcraft XML. However, if you are a master of XML and database then this section illustrates the format of a snapshot record. Note:

    • In the example code formula column values were excluded.

    • In the example fields with empty values were excluded.

    The purpose of the CopyForceArchiveRecordRelat table is to support rapid traversal of relationships between snapshot records by avoiding scanning the XML to find relationships.

    Column
    Data Type
    Description

    List of filter types that are used to determine if a record belongs in a snapshot.

    CopyForceArchivePolicy

    This the root table for each individual snapshot.

    CopyForceArchivePolicyStat

    Statistics about the data stored in each snapshot.

    CopyForceArchiveRetentionRule

    Rules which describe data retention rules for groups of tables within a snapshot. This table allows a single snapshot to support different retention policies for various tables.

    CopyForceArchiveFieldSet

    Description of the fields defined in Salesforce at the point a record was snapshot.

    CopyForceArchiveRecord

    Snapshot records. This is the primary storage table for each snapshot.

    CopyForceArchiveRecordRelat

    Relationships between record based on Salesforce references fields. The purpose of this table is to facilitate fast record relationship traversal without scanning the complete text of a snapshot record in the CopyForceArchiveRecord table.

    Id

    Integer

    Unique Id assigned to the Name.

    Name

    String

    Id

    Integer

    Unique internal id for the filter.

    Name

    String

    Id

    Integer

    Unique internal id for the filter.

    Name

    PolicyId

    Integer

    Snapshot policy that owns the statistic

    TableNameToken

    Integer

    Id

    Integer

    Unique id for the rule.

    PolicyId

    Integer

    Id

    Integer

    Unique id for the field set.

    TableName

    String

    <ArchiveFields table="Account" version="24MAY18">
       <Field name="AccountNumber" label="Account Number" type="string" length="40" ndigits="0" scale="0" nameField="false" calculated="false" encrypted="false" custom="false"/>
       <Field name="AccountSource" label="Account Source" type="picklist" length="40" ndigits="0" scale="0" nameField="false" calculated="false" encrypted="false" custom="false"/>
       <Field name="Active__c" label="Active" type="boolean" length="0" ndigits="0" scale="0" nameField="false" calculated="false" encrypted="false" custom="true"/>
    
       <Field name="CLS_Account_Reconcile__c" label="Account Reconcile" type="string" length="1300" ndigits="0" scale="0" nameField="false" calculated="true" formula="IF( RecordType.DeveloperName = 'Procurement_Supplier', 'ESP', &#xA;IF( RecordType.DeveloperName = 'CLS_Customer_Account', 'CLS', &#xA;IF( RecordType.DeveloperName = 'Global_Account', 'GLOBAL', &#xA;IF( RecordType.DeveloperName = 'Supplier', 'SRM', &#xA;'' &#xA;))))" encrypted="false" custom="true"/>
    </ArchiveFields>

    Id

    Integer

    Unique id for the snapshot record.

    SalesforceId

    String

    <FieldData>
       <Active__c>false</Active__c>
       <BillingCity>Orlando</BillingCity>
       <BillingCountry>Florida</BillingCountry>
       <BillingPostalCode>L4B 1Y3</BillingPostalCode>
       <BillingState>Orlando</BillingState>
       <BillingStreet>Walt Disney Street</BillingStreet>
       <CreatedById>0051a000000EVk1AAG</CreatedById>
       <CreatedDate>2015-04-23T15:06:27.000Z</CreatedDate>
       <Description>Walt Disney World is a leading entertainment destination.</Description>
       <Id>0011a000003B7M2AAK</Id>
       <Industry>Media</Industry>
       <IsCustomerPortal>false</IsCustomerPortal>
       <IsDeleted>false</IsDeleted>
       <LastActivityDate>2015-04-22</LastActivityDate>
       <LastModifiedById>0051a000000EVk1AAG</LastModifiedById>
       <LastModifiedDate>2015-04-23T15:06:27.000Z</LastModifiedDate>
       <Name>Walt Disney</Name>
       <NumberOfEmployees>14668</NumberOfEmployees>
       <OwnerId>0051a000000EVk1AAG</OwnerId>
       <Phone>(905) 232-8888</Phone>
       <SystemModstamp>2016-07-29T10:57:56.000Z</SystemModstamp>
       <Type>Prospect</Type>
    </FieldData>

    ArchiveRecordId

    Integer

    Id of the CopyForceArchiveRecord entry that contains the relationship.

    ParentTableToken

    String

    CopyForceArchiveToken

    CopyForceArchiveFilter

    CopyForceArchivePolicy

    CopyForceArchivePolicyStat

    CopyForceArchiveRetentionRule

    CopyForceArchiveFieldSet

    CopyForceArchiveRecord

    CopyForceArchiveRecordRelat

    Name of a table, field, etc. in Salesforce.

    Name of the filter as presented to a user.

    Description

    String

    Description of the filter.

    ClassName

    String

    Name of a Java class that implements the filter. These classes are typically developed by Capstorm rather than customers.

    CreatedDate

    Timestamp

    Timestamp of when the record was created.

    ModifiedDate

    Timestamp

    Timestamp of the most recent modification to the record.

    String

    Name of the filter as presented to a user.

    Description

    String

    Description of the policy.

    FilterId

    Integer

    Id of the CopyForceArchiveFilter that will be used to determine if a record matches the policy.

    Active

    Boolean

    True if the policy should be automatically evaluated during a CopyStorm backup.

    IncludeFormulaFields

    Boolean

    True if formula field values should be stored in an archived record.

    IncludeNullFields

    Boolean

    True if field with an empty (null) value should be explicitly stored in an archive record.

    IncludedTables

    Boolean

    Comma separated list of table names and/or regular expressions for which this policy is applicable.

    ExcludedTables

    String

    Comma separated list of tables and/or regular expressions that should be ignored by the policy. If the IncludedTables value is not blank then the ExcludedTables value is ignored.

    ExcludedReferenceFields

    String

    Comma separated list of Salesforce reference field names that should be excluded from the CopyForceArchiveRecordRelat table. The primary reason to exclude a reference field is to save space.

    Argument

    String

    Argument that will be passed to the corresponding ArchiveFilterId logic. For example, the Column Expression filter has a argument the represents the expression.

    ArchiveAfterInsert

    Boolean

    If True and the policy is active then evaluate a record for potential snapshot by the policy immediately after it is inserted into CopyStorm.

    ArchiveBeforeUpdate

    Boolean

    If True and the policy is active then evaluate a record for potential snapshot by the policy just before it is updated in CopyStorm.

    ArchiveAfterUpdate

    Boolean

    If True and the policy is active then evaluate a record for potential snapshot by the policy just after it is updated in CopyStorm.

    RetentionDays

    Integer

    Default number of days a record will be retained in the snapshot before it is deleted. If blank then records will be kept forever.

    RetentionVersions

    Integer

    Maximum number of versions to keep for a record even when the default retention days has not been met.

    CreatedDate

    Timestamp

    Timestamp of when the record was created.

    ModifiedDate

    Timestamp

    Timestamp of the most recent modification to the record.

    Table for which the statistic applies.

    NumRecords

    Integer

    Number of table records in the snapshot (updated on demand).

    FirstArchiveDate

    Timestamp

    Timestamp of the earliest record in the snapshot (updated on demand).

    LastArchiveDate

    Timestamp

    Timestamp of the oldest record in the snapshot (updated on demand).

    LastRetentionRunDate

    Timestamp

    Most recent date on which the policy’s record retention date rules were run.

    NumRetentionDeleted

    Integer

    Number of records deleted from the snapshot during the most recent record retention policy run.

    The archive policy that owns the rule.

    RetentionDays

    Integer

    Number to retain records before they are deleted from the archive.

    IncludedTables

    String

    Comma separated list of table names and/or regular expressions for which the retention rule applies.

    API Name of the Salesforce table used to define the field set.

    TableLabel

    String

    Label of the Salesforce table used to define the field set.

    Fingerprint

    String

    Unique fingerprint for the field set. Used for rapid searching and duplicate detection.

    Fields

    XML

    Simple XML document describing the fields in a table.

    CreatedDate

    Timestamp

    Date on which the field set was created.

    ModifiedDate

    Timestamp

    Date on which the field set was last updated.

    Salesforce Id of the snapshot record.

    Name

    String

    Value of the Salesforce Name field for the record. If a record does not contain a Name field then the table name is used.

    TableNameToken

    Integer

    Internal Id used to lookup the name of the Salesforce table.

    PolicyId

    Integer

    Internal Id of the snapshot policy which created the record.

    FieldSetId

    Integer

    Internal Id of the field set definitions in place when the record was snapshot.

    Fingerprint

    String

    Unique string used to rapidly avoid redundant snapshot records.

    FieldData

    XML

    Simple XML document describing data in the record.

    SystemModStamp

    Timestamp

    The Salesforce SystemModStamp when the record was snapshot. In the rare case where a record does not have a SystemModStamp column a different column with the same semantics is selected.

    CreatedDate

    Timestamp

    The Salesforce CreatedDate when the record was snapshot. In the rare case where a record does not have a CreatedDate column a different column with the same semantics is selected.

    ModifiedDate

    Timestamp

    The Salesforce ModifiedDate when the record was snapshot. In the rare case where a record does not have a ModifiedDate column a different column with the same semantics is selected.

    ArchivedDate

    Timestamp

    The timestamp when the record was written to the snapshot (UTC).

    Salesforce tokenized name of the table that owns the relationship. Example: Contact

    ParentFieldToken

    String

    Salesforce tokenized name of the table column that owns the relationship. Example: AccountId (for relationship Contact.ParentId)

    ParentId

    String

    Salesforce Id of the record that owns the relationships.

    ReferenceTableToken

    Integer

    Salesforce tokenized name of the table pointed to by the relationship. Example: Account.

    ReferenceId

    Integer

    Salesforce Id of the record the relationship is pointing to.

    ArchivedDate

    Timestamp

    The timestamp when the record was written to the snapshot (UTC).

    Frequently Asked Questions

    How Do I Backup Massive Salesforce Attachments?

    If a Salesforce instance contains extremely large Attachments (600MB – 2000MB), backing them up with CopyStorm may take a special approach. The reasons are rooted in the fact that none of the APIs provided by Salesforce provide a sufficient solution “out of the box”.

    • Fact 1: The Salesforce SOAP API returns attachment bodies as part of the SOAP XML envelope. This can cause two problems:

      • The SOAP envelope will cause large memory requirements for the XML parser. Increasing the maximum amount of memory allowed for CopyStorm will usually solve this problem.

      • If the SOAP envelope is too large to fit in a single string variable, the XML parser will suffer a fatal error. The largest string the XML parser can handle is 2GB and the string in a SOAP envelope can exceed this length.

    • Fact 2: The Salesforce REST API returns attachment bodies as hyperlinks to the body content. This approach minimizes the memory requirements for CopyStorm but has some downsides:

      • Salesforce throttles the retrieval of attachment bodies to 1MB per second AND limits the time of retrieval to 10 minutes. This means that attachments larger than roughly 600MB cannot be retrieved using the REST API under default Salesforce parameters.

    There is a way to get around this issue but it requires a call to Salesforce support:

    • Call Salesforce and ask them to increase your Organization’s maximum timeout to a value that will allow your largest attachment to be read (at a rate of ~1MB per second).

    • In CopyStorm, backup massive Salesforce Attachments using the REST API.

      • The default is SOAP — it is generally faster.

    Does CopyStorm Backup Meta Data?

    The short answer is “Yes, CopyStorm backs up all Salesforce metadata.”

    In Salesforce, metadata is stored in two different ways:

    • In Tables (SObject) — much of the key Salesforce metadata is stored in tables.

      • Examples include Apex Classes, Apex Pages, Apex Triggers, and Workflows/Processes

    • Not In Tables — this type of data is only accessible as zip archives via the Salesforce Metadata API.

    CopyStorm backs up all metadata stored in Tables and, just as importantly, maintains revision history as the records change.

    For example:

    • If an ApexClass changes, the old version of the class is saved in a field history tracking table.

    • If an ApexPage is deleted, the definition of the ApexPage just before it was deleted is saved in a field history tracking table.

    Since metadata tables used by CopyStorm are defined by Salesforce’s ERD, the data in them is readily accessible within the CopyStorm database. For example, the definition of the ApexClass “MyFavoriteClass” can be found with the following SQL:

    • SELECT body FROM ApexClass WHERE name=”MyFavoriteClass”

    Starting with CopyStorm 7.37.2, metadata accessible only via the Salesforce metadata API is backed up to the CopyStorm table SFMetaFileProperties and can be restored using CopyStorm/Restore.

    How Do Salesforce Types Map to Database Column Types?

    The following table describes how Salesforce column data types are mapped to database data types:

    Salesforce Type
    H2
    MySQL
    Oracle(see notes)
    PostgreSQL
    SQL/Server
    • The compound type ADDRESS is ignored but its data is picked up in component fields.

    • The compound type LOCATION is ignored but its data is picked up in its component Latitude and Longitude fields.

    • If the length of any string type column exceeds the “Maximum Varchar” parameter then its data type will be the same as used for BASE64 types.

    For Oracle Only:

    • CopyStorm can be forced to use a VARCHAR2 rather than NVARCHAR2 by unchecking the “Use NVARCHAR2” option in the Advanced Database Options on the Advanced tab. When CopyStorm creates or modifies a column it chooses a VARCHAR2 or NVARCHAR2 Oracle data type based on the current setting of the “Use NVARCHAR2” option. Note: CopyStorm will not change the data type of an existing column unless the column’s length increases in Salesforce.

    ANYTYPE

    CLOB

    TEXT

    NCLOB

    TEXT

    NVARCHAR(MAX)

    BASE64

    CLOB

    TEXT, MEDIUMTEXT, or LONGTEXT

    CLOB

    TEXT

    VARCHAR(MAX)

    BOOLEAN

    BOOLEAN

    BOOLEAN

    DECIMAL(1)

    BOOLEAN

    BIT

    COMBOBOX

    NVARCHAR

    VARCHAR

    NVARCHAR2

    VARCHAR

    NVARCHAR

    CURRENCY

    DECIMAL

    DECIMAL

    NUMBER

    NUMERIC

    DECIMAL

    DATACATEGORYGROUPREFERENCE

    CHAR

    CHAR

    CHAR

    CHAR

    CHAR

    DATE

    TIMESTAMP

    DATE

    DATE

    DATE

    DATE

    DATETIME

    TIMESTAMP

    DATETIME

    TIMESTAMP(3)

    TIMESTAMP

    DATETIME

    DOUBLE

    DECIMAL

    DECIMAL

    NUMBER

    NUMERIC

    DECIMAL

    EMAIL

    NVARCHAR

    VARCHAR

    NVARCHAR2

    VARCHAR

    NVARCHAR

    ENCRYPTEDSTRING

    NVARCHAR

    VARCHAR

    NVARCHAR2

    VARCHAR

    NVARCHAR

    ID

    CHAR

    CHAR

    CHAR

    CHAR

    CHAR

    INT

    INTEGER

    INTEGER, DECIMAL, or BIGINT

    NUMBER

    INTEGER

    INT or BIGINT

    MULTIPICKLIST

    NVARCHAR

    VARCHAR

    NVARCHAR2

    VARCHAR

    NVARCHAR

    PERCENT

    DECIMAL

    DECIMAL

    NUMBER

    NUMERIC

    DECIMAL

    PHONE

    NVARCHAR

    VARCHAR

    NVARCHAR2

    VARCHAR

    NVARCHAR

    PICKLIST

    NVARCHAR

    VARCHAR

    NVARCHAR2

    VARCHAR

    NVARCHAR

    REFERENCE

    CHAR

    CHAR

    CHAR

    CHAR

    CHAR

    STRING

    NVARCHAR

    VARCHAR

    NVARCHAR2

    VARCHAR

    NVARCHAR

    TEXTAREA

    NVARCHAR

    VARCHAR

    NVARCHAR2

    VARCHAR

    NVARCHAR

    TIME

    TIME

    DATETIME

    TIMESTAMP(3)

    TIME

    DATETIME

    URL

    NVARCHAR

    VARCHAR

    NVARCHAR2

    VARCHAR

    NVARCHAR

    Notes

    Can Multiple CopyStorm Jobs Run on the Same Database?

    CopyStorm supports the use of multiple running CopyStorm jobs to backup the same Salesforce instance to a Salesforce backup database, and there are some situations in which this can be preferable to a single job. For example:

    • A company has 20 CopyStorm Oracle tables that they want to be no more than 10 minutes behind the data in Salesforce. An incremental backup of all tables would take too long to allow a job to run every 10 minutes.

    • A company has a limited number of Salesforce API calls and does not want to accidentally use them all during the week. On the weekend they decide to backup the API-expensive tables (Attachment and ContentVersion).

    While there is no practical limit to the number of CopyStorm jobs that can run at the same time while writing to the Salesforce backup database, there are a few restrictions:

    • Two CopyStorm jobs SHOULD NEVER be configured to backup the same table if they can run at the same time.

      • While this is unlikely to cause database issues, a lot of exceptions will likely be reported.

    • Salesforce will randomly kill a session if too many queries are active for an organization. This is a Salesforce governor limit and is typically around 20.

      • CopyStorm often generates longer running queries, so this has a material effect on how many CopyStorm jobs can be run at the same time on the same Salesforce organization.

    One common good practice is to divide Salesforce tables into two groups:

    • Group A: Tables where it is important to keep the data in your database in near real-time sync with Salesforce.

    • Group B: All tables not in Group A.

    The configuration file for Group A lists the tables to be backed up in the “Included Tables” section.

    The configuration file for Group B leaves the “Include Tables” section blank and puts the tables from “Group A” in the “Excluded Tables” section.

    The CopyStorm job for Group A is scheduled to run every 30 to 60 minutes. The CopyStorm job for Group B is scheduled to run every night or every weekend.

    Since the tables in Group A and Group B do not overlap, it is safe to run both jobs at the same time.

    One Common Good Practice