<?xml version="1.0" encoding="UTF-8" ?>
<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" version="2.0"><channel><title>Yorvi Arias | CrunchyData Blog</title>
<atom:link href="https://www.crunchydata.com/blog/author/yorvi-arias/rss.xml" rel="self" type="application/rss+xml" />
<link>https://www.crunchydata.com/blog/author/yorvi-arias</link>
<image><url>https://www.crunchydata.com/build/_assets/default.png-W4XGD4DB.webp</url>
<title>Yorvi Arias | CrunchyData Blog</title>
<link>https://www.crunchydata.com/blog/author/yorvi-arias</link>
<width>256</width>
<height>256</height></image>
<description>PostgreSQL experts from Crunchy Data share advice, performance tips, and guides on successfully running PostgreSQL and Kubernetes solutions</description>
<language>en-us</language>
<pubDate>Fri, 13 Nov 2020 04:00:00 EST</pubDate>
<dc:date>2020-11-13T09:00:00.000Z</dc:date>
<dc:language>en-us</dc:language>
<sy:updatePeriod>hourly</sy:updatePeriod>
<sy:updateFrequency>1</sy:updateFrequency>
<item><title><![CDATA[ Postgres Streaming Replication on Windows: A Quick Guide ]]></title>
<link>https://www.crunchydata.com/blog/postgres-streaming-replication-on-windows-a-quick-guide</link>
<description><![CDATA[ In this blog post, we'll discuss how to set up streaming replication in Windows. Credit goes to my colleague Douglas Hunley whose blog post on setting up streaming replication on Linux served as inspiration. ]]></description>
<content:encoded><![CDATA[ <p>The Postgres documentation covers <a href=https://www.postgresql.org/docs/current/warm-standby.html#STREAMING-REPLICATION>streaming replication</a> pretty comprehensively, but you may also need something more digestible for reference. In this blog post, we'll discuss how to set up streaming replication in Windows. Credit goes to my colleague Douglas Hunley whose blog post on <a href=https://hunleyd.github.io/posts/postgresql-streaming-replication-in-10-minutes/>setting up streaming replication on Linux</a> served as inspiration.<p>To recap, Postgres replication is the process of copying data from one database server (primary) to another (standby). While this blog post will focus on streaming replication, there is another option with <a href=https://www.postgresql.org/docs/current/logical-replication.html>logical replication</a> as well.<p>The general steps are the same in Windows as in Linux but for the sake of convenience the commands and code samples in this post are tailored specifically to a Windows environment. We are assuming that you already have two servers with Postgres installed on them. Our testing environment was Postgres 11.9 on Windows Server 2012.<p>Keep in mind that when we say "primary," we mean the Postgres node that you already have running and have configured for read/writes (standbys are not available for writing).<p>Now, let’s get started.<h2 id=update-postgresconf-and-pg_hbaconf><a href=#update-postgresconf-and-pg_hbaconf>Update Postgres.conf and pg_hba.conf</a></h2><p>On your primary, you would need to edit your Postgres.conf to append the following settings:<pre><code class=language-ini>wal_level = hot_standby
full_page_writes = on
wal_log_hints = on
max_wal_senders = 6
max_replication_slots = 6
hot_standby = on
hot_standby_feedback = on
</code></pre><p>You will also need to edit your pg_hba.conf on your primary and add the external IP addresses of both the servers. Yes, you will need to put both IP addresses. Below is an example:<pre><code class=language-txt>host replication repl_user IP_of_primary/32 scram-sha-256
host replication repl_user IP_of_standby/32 scram-sha-256
</code></pre><p>This file will be replicated to the standby. When that node is promoted to a primary, it will already be configured to allow the old primary to connect.<h2 id=create-a-replication-user-called-repl_user><a href=#create-a-replication-user-called-repl_user>Create a replication user called repl_user</a></h2><p>You may be wondering: who is the repl_user? This is the user we are going to create that has the replication privilege that is needed. We should probably explain why we do this. On your primary, in the command prompt, run the following:<pre><code class=language-shell>psql  -d postgres   -U postgres   -c "CREATE ROLE repl_user LOGIN REPLICATION ENCRYPTED PASSWORD 'secretpasswordhere';"
</code></pre><p>As you might have noticed in our configuration changes above (<em>max_replication_slots = 6</em> ), we are using <a href=https://www.postgresql.org/docs/current/warm-standby.html#STREAMING-REPLICATION-SLOTS>replication slots</a> for this setup as well. Replication slots avoid issues with not being able to find <dfn>write-ahead log</dfn> (<abbr>WAL</abbr>) segments when a standby goes down and is brought back up at a later time.<p>There is one thing to keep in mind about replication slots: when the standby is down, the primary will continue to accumulate WAL since the replication slot isn't being updated. This will cause the WAL directory to fill until the standby is back up and receiving the WAL or until the replication slot is removed. Postgres 13 did bring in a parameter to help with replication slots and disk usage. Postgres 13 now has the <a href=https://www.postgresql.org/docs/13/runtime-config-replication.html#GUC-MAX-SLOT-WAL-KEEP-SIZE>max_slot_wal_keep_size parameter</a> which will allow you to specify the amount of WAL replication slots retained. While this will prevent Postgres from filling your disk with WAL waiting for the missing standby, it also means WAL will be discarded and your standby will need to be rebuilt due to the necessary WAL being absent.<p>On the primary, create the replication slot for the standby by running the following:<pre><code class=language-shell>psql -d postgres -U postgres  -c "SELECT * FROM pg_create_physical_replication_slot('standby1', true);"
</code></pre><h2 id=perform-a-base-backup-of-primary-to-standby><a href=#perform-a-base-backup-of-primary-to-standby>Perform a base backup of primary to standby</a></h2><p>After you have completed the above, you will need to wipe your existing standby. To do this you will first need to stop the cluster.<pre><code class=language-shell>pg_ctl -D "your\data\directory" stop -mi
</code></pre><p>After stopping the cluster you will need to delete the data directory. You can do this by either using the command prompt and running:<pre><code class=language-shell>rmdir /s \your\data\directory
</code></pre><p>Or you can delete it from File Explorer.<p>Once you’ve deleted the data directory on your standby, you will now run <a href=https://www.postgresql.org/docs/11/app-pgbasebackup.html>pg_basebackup</a> on the standby to copy your primary’s data directory to it.<pre><code class=language-shell>pg_basebackup -D \your\data\directory -Fp -R -Xs -c fast -l 'initial clone' -P -v -h IP_of_master -U repl_user
</code></pre><p>Keep in mind that you will need to enter the repl_user’s password when asked.<h2 id=update-standby-server-settings><a href=#update-standby-server-settings>Update standby server settings</a></h2><p>Lastly, once the base backup has completed for Postgres 11 and below, you will need to edit your standby’s recovery.conf and add the replication slot name. For Postgres 12 and up, the recovery.conf file no longer exists and the settings for recovery.conf are now moved to Postgres.conf. (Take a look at the <a href=https://www.postgresql.org/docs/12/release-12.html#id-1.11.6.9.4>release notes</a> for more details.) Using your favorite text editing tool append the below to either your recovery.conf or Postgres.conf depending on your version.<pre><code class=language-ini>primary_slot_name = 'standby1'
</code></pre><p>Once you’ve edited the above you can start the standby by either using <code><a href=https://www.postgresql.org/docs/current/app-pg-ctl.html>pg_ctl</a> -D [data dir] start</code> as the Postgres user, or using the <code>net start</code> command if you created a service entry on your Windows server.<p>There are many ways to check that replication is working properly. First, in the logs you should see:<pre><code class=language-txt>Started streaming from primary at [wal] on timeline [number]
</code></pre><p>You can also run the following commands:<ul><li><p>On the primary<pre><code class=language-pgsql>SELECT * FROM pg_stat_replication;
</code></pre><li><p>On the replica<pre><code class=language-pgsql>SELECT * FROM pg_stat_wal_receiver;
</code></pre></ul><p>You have now successfully set up streaming replication - congratulations!<p>Once again a huge shout out to Douglas Hunley and his blog post on streaming replication for Linux environments. As always, it is recommended that you review the Postgres documentation. With that said, you might be interested in checking out more blog posts about replication by my Crunchy colleagues. Hope you enjoy:<ol><li><a href=/blog/synchronous-replication-in-postgresql>Synchronous Replication in Postgres</a><li><a href=/blog/synchronous-replication-in-the-postgresql-operator-for-kubernetes-guarding-against-transactions-loss>Guard Against Transaction Loss with Postgres Synchronous Replication</a></ol> ]]></content:encoded>
<category><![CDATA[ Production Postgres ]]></category>
<author><![CDATA[ Yorvi.Arias@crunchydata.com (Yorvi Arias) ]]></author>
<dc:creator><![CDATA[ Yorvi Arias ]]></dc:creator>
<guid isPermalink="false">https://blog.crunchydata.com/blog/postgres-streaming-replication-on-windows-a-quick-guide</guid>
<pubDate>Fri, 13 Nov 2020 04:00:00 EST</pubDate>
<dc:date>2020-11-13T09:00:00.000Z</dc:date>
<atom:updated>2020-11-13T09:00:00.000Z</atom:updated></item>
<item><title><![CDATA[ Setup ora2pg for Oracle to Postgres Migration ]]></title>
<link>https://www.crunchydata.com/blog/setup-ora2pg-for-oracle-to-postgres-migration</link>
<description><![CDATA[ An important part of performing a migration from Oracle to PostgreSQL is selecting the right tool for helping with the conversion between systems. ]]></description>
<content:encoded><![CDATA[ <p>An important part of performing a migration from Oracle to PostgreSQL is selecting the right tool for helping with the conversion between systems. When people ask me how they can get the migration process started, I like to recommend a powerful open source utility called "<a href=https://ora2pg.darold.net/>ora2pg</a>".<p>As the name suggests, ora2pg is a tool that migrates Oracle (or MySQL) databases to PostgreSQL by generating compatible SQL files As the documentation states, ora2pg “connects your Oracle database, scans it automatically and extracts its structure or data, it then generates SQL scripts that you can load into your PostgreSQL database.”<p>ora2pg also has a bunch of neat features that you can see below. To see all of the features and to learn more about ora2pg please visit <a href=https://ora2pg.darold.net/start.html>https://ora2pg.darold.net/start.html</a>.<ul><li>Export full database schema (tables, views, sequences, indexes), with unique, primary, foreign key and check constraints.<li>Export grants/privileges for users and groups.<li>Export range/list partitions and subpartitions.<li>Migration cost assessment of an Oracle database.<li>Migration difficulty level assessment of an Oracle database.<li>Migration cost assessment of PL/SQL code from a file.</ul><h2 id=summary><a href=#summary>Summary</a></h2><p>The process for installing ora2pg is fairly straightforward, but the number of steps involved tend to seem a bit daunting. Below is a summary of the steps we will go through:<ol><li>Install necessary prerequisites<li>Build and install DBD::Oracle<li>Build and install ora2pg<li>Configure ora2pg<li>Test and use ora2pg</ol><h2 id=demo-setup><a href=#demo-setup>Demo Setup</a></h2><p>For this demo on how to install ora2pg, we are using a Centos 7.7 Environment with Oracle 12.1 installed. We will also be using ora2pg 20.0. ora2pg can either be run on the PostgreSQL server or you can run it on the Oracle server. ora2pg was run on my Oracle server. In this demo I used a virtual box to create my environment, I will assume that you have your Oracle environment already setup.<p>If you don't want to install ora2pg on the Oracle server and instead on the PostgreSQL server there are a couple of extra steps that need to be done. First you will need to have PostgreSQL installed. If you need help installing PostgreSQL please look at the <a href=/blog/postgresql-installing-and-creating-cluster-with-rpm-packages>previously published blog post</a>.<p>In your PostgreSQL server you will need to install the following prerequisites and will need to install the Oracle Instant Client SDK.<p>Prerequisites: After installing PostgreSQL and making sure everything is running properly you will need to run<pre><code class=language-shell>sudo yum install -y gcc postgresql11-devel \ perl-ExtUtils-MakeMaker perl-DBI perl-DBD-Pg perl-tests
</code></pre><p>Oracle Instant Client SDK: These are the following steps that need to be taken to install the Instant Client in your PostgreSQL server.<ul><li>You will need to download the Oracle 12.2 Basic &#38 SDK Instant Client RPMs, sqlplus suggested from the following site. <a href=https://www.oracle.com/technetwork/topics/linuxx86-64soft-092277.html>https://www.oracle.com/technetwork/topics/linuxx86-64soft-092277.html</a></ul><p>To install the packages simply run<pre><code class=language-shell>sudo yum localinstall -y /path/to/oracle-instantclient12*.rpm
</code></pre><p>You will need to include the below in your <code>~/.bash_profile</code>:<pre><code class=language-shell># InstantClient
export ORACLE_HOME=/usr/lib/oracle/12.2/client64
export LD_LIBRARY_PATH=$ORACLE_HOME/lib:$LD_LIBRARY_PAT
export PATH=$ORACLE_HOME/bin:$PATH
</code></pre><p>Then source the new env vars by running<pre><code class=language-shell>source ~/.bash_profile
</code></pre><p>You will then test the connection to your Oracle server (if you've installed the sqlplus instantclient package simply run the below):<pre><code class=language-shell>sqlplus hr/hr1234@//192.168.99.21:1521/ORCLPDB1
</code></pre><p>Keep in mind that you only have to do the above if you are going to install ora2pg in your PostgreSQL server. After you do the above you can continue with the <a href=#buildinstall-dbdoracle>Build/Install DBD:oracle section</a>.<h2 id=prerequisites-for-building><a href=#prerequisites-for-building>Prerequisites for Building</a></h2><p>Before getting started there were some prerequisites my environment needed in order to build DBD::Oracle and ora2pg. I needed to install a couple of perl modules in order to get everything up and running. I did so by running:<pre><code class=language-shell>sudo yum install perl-devel
</code></pre><pre><code class=language-shell>sudo yum install perl-DBI.x86_64
</code></pre><h2 id=buildinstall-dbdoracle><a href=#buildinstall-dbdoracle>Build/Install DBD::Oracle</a></h2><p>Before we build/install ora2pg you need to build/install the Perl module DBD::Oracle. DBD::Oracle is a Perl module that works with the DBI module to provide access to Oracle databases. If you would like to learn more about it please click the following link <a href=https://metacpan.org/pod/DBD::Oracle>https://metacpan.org/pod/DBD::Oracle</a>.<p>As you can see below there are two ways you can build/install DBD::Oracle. In my environment, I did it the first way. You can see in the first step to run the wget command to get the tar file from the site. If you don’t have wget and are using a Centos or RHEL OS, you can install it by running<pre><code class=language-shell>sudo yum install wget
wget https://cpan.metacpan.org/authors/id/Z/ZA/ZARQUON/DBD-Oracle-1.76.tar.gz
tar -xvzf DBD-Oracle-1.76.tar.gz
cd DBD-Oracle-1.76
perl Makefile.PL
make &#38&#38 make test
sudo make install
</code></pre><p>As mentioned previously, if you don’t want to do the above steps, you can simply do the below two steps to build/install DBD::Oracle.<pre><code class=language-shell>sudo yum install perl-CPAN
perl -MCPAN -e 'install DBD::Oracle' # configure for sudo
</code></pre><h2 id=buildinstall-ora2pg><a href=#buildinstall-ora2pg>Build/Install ora2pg</a></h2><p>After you have installed DBD::Oracle, you will then need to build/install ora2pg. The steps below are similar to the steps in the documentation of ora2pg which you can find in this link <a href=https://ora2pg.darold.net/>https://ora2pg.darold.net/</a>. The only difference is the first step, where you need to wget the tar file from ora2pg Github archive.<pre><code class=language-shell>wget https://github.com/darold/ora2pg/archive/v20.0.tar.gz
tar -xvzf v20.0.tar.gz
cd ora2pg-20.0
perl Makefile.PL
make
sudo make install
</code></pre><h2 id=configure-ora2pg><a href=#configure-ora2pg>Configure ora2pg</a></h2><p>After you have ora2pg built and installed you can now configure the <code>ora2pg.conf</code> to work with your Oracle server. The settings that you see below are the settings in my environment. The <code>ora2pg.conf</code> file has many configuration settings that you can change. Below are the configuration changes that you will need to apply to your <code>ora2pg.conf</code> in order to be able to use ora2pg. Please keep in mind that you will need to change the settings to match your environment. If you would like to learn more about the other configurations please look at the documentation: <a href=https://ora2pg.darold.net/documentation.html#CONFIGURATION>https://ora2pg.darold.net/documentation.html#CONFIGURATION</a>.<pre><code class=language-txt>In ora2pg-20.0/ora2pg.conf:
PG_VERSION      11
ORACLE_DSN      dbi:Oracle:host=192.168.99.21;port=1521;service_name=ORCLPDB1
ORACLE_USER     hr
ORACLE_PWD      hr1234
USER_GRANTS	    1

EXPORT_SCHEMA   1
SCHEMA          hr
TRANSACTION     READONLY

# This is needed for Oracle XE 11 with ora2pg &#60= v20, but safe
# to add for any version
SYSUSERS        APEX_040000
</code></pre><h2 id=testing-ora2pg><a href=#testing-ora2pg>Testing ora2pg</a></h2><p>Now that ora2pg has been configured you can finally test connectivity. By testing the connectivity you will see that you have configured ora2pg correctly, if you didn’t you will receive errors. You can test by running the below command:<pre><code class=language-shell>ora2pg -t SHOW_VERSION -c ora2pg.conf
</code></pre><h2 id=estimation-report><a href=#estimation-report>Estimation report</a></h2><p>Ora2pg has an amazing feature in that it can give you an estimate of the migration cost from Oracle to PostgreSQL. It is important that you use this feature before actually migrating. Per the documentation, “To obtain a good assessment of this migration cost, Ora2Pg will inspect all database objects, all functions and stored procedures to detect if there's still some objects and PL/SQL code that can not be automatically converted by Ora2Pg.”<p>As it says above generating an estimation report shows if there are any database objects, PL/SQL code, etc that won’t be automatically converted by ora2pg. This means that you will need to do some manual work. This may be something you didn’t want to hear, but only in a perfect world can a tool do all the work for you. To learn more about the estimation report please look at <a href=https://ora2pg.darold.net/documentation.html#Migration-cost-assessment>the documentation</a>.<p>There are many ways to generate an estimation report as you can see in the link above. Below is the command that will give you the report as well as an estimate of the migration cost.<pre><code class=language-shell>ora2pg -t SHOW_REPORT --estimate_cost -c ora2pg.conf
</code></pre><p>The following link shows a great example of the report feature that ora2pg has: <a href=https://ora2pg.darold.net/report.html>https://ora2pg.darold.net/report.html</a>.<p>As you can see in the link this feature gives a pretty detailed report and even provides workarounds when an object isn’t available in PostgreSQL. For example, if you look for the following objects <code>SEQUENCE</code> and <code>SYNONYM</code> in the report the comments say the below.<p><code>SEQUENCE</code>: Sequences are fully supported, but all call to <code>sequence_name.NEXTVAL</code> or <code>sequence_name.CURRVAL</code> will be transformed into <code>NEXTVAL('sequence_name')</code> or <code>CURRVAL('sequence_name')</code>.<p><code>SYNONYM</code>: <code>SYNONYM</code>s will be exported as views. <code>SYNONYM</code>s do not exist with PostgreSQL but a common workaround is to use views or set the PostgreSQL <code>search_path</code> in your session to access objects outside the current schema.<p>The report feature is valuable for planning your migration to ora2pg.<h2 id=work-that-you-will-have-to-do><a href=#work-that-you-will-have-to-do>Work that you will have to do</a></h2><p>Below I would like to provide bullet points for you to take into consideration when migrating from Oracle to PostgreSQL.<ul><li>Keep in mind that before you do the migration, your team will need PostgreSQL training. More PostgreSQL knowledge before starting to migrate will lead to a more efficient migration and you will learn more about both Oracle and PostgreSQL during the migration.<li>You should do an in depth analysis of your Oracle database architecture. As mentioned previously, ora2pg doesn’t migrate every single object or function. It is best to analyze your Oracle database and determine if you can change anything in there to make your migration easier.<li>Think about your applications that connect to the database. You need to make sure that you don't have a third party application that does work with PostgreSQL.<li>Finally make sure that you do your research. It can be tedious but it's better to do the research than to have everything break. By reading this article, you’re already researching.<li>Transactions in PostgreSQL are implemented differently than in Oracle. Oracle supports nested transactions, PostgreSQL does not. Often you can use PostgreSQL <code>SAVEPOINT</code>s to achieve similar behavior, but if your Oracle deployment uses PL/SQL extensively and uses nested transactions, you will likely have some manual porting to do.<li>Schemas are different in PostgreSQL vs Oracle. In PostgreSQL, schema objects are used to add namespaces or scope to DB’s. In PostgreSQL, a schema is independent of a user, group or role object.<li>In PostgreSQL, roles, users and groups are global objects - a role/user/group is not part of a database, they are independent of all databases in a PostgreSQL instance. A role/user/group can be granted privileges to any DB in an instance. A user instance can be directly connected to one database in a cluster at a time.<li>Oracle provides hundreds of packages. If you use Oracle packages extensively, you will likely have some manual porting ahead.<li>Both Oracle and PostgreSQL provide stored procedures and user-defined functions. PostgreSQL supports multiple embedded languages in the server. The most commonly used procedural server-side languages - PL/SQL in Oracle and PL/pgSQL in PostgreSQL - are similar enough that ora2pg will translate some functions or UDF’s directly. It will identify those that it can’t translate directly and identify problems.<li>There are common alternatives in PostgreSQL to Oracle’s Native Dynamic SQL, <code>EXECUTE IMMEDIATE</code> - see using the dblink PostgreSQL extension.<li>PostgreSQL provides a way to extend the core - PostgreSQL extensions. There is a large and growing number of extensions. It’s worth reviewing extensions to see if there are some that can help you migrate.</ul> ]]></content:encoded>
<category><![CDATA[ Production Postgres ]]></category>
<author><![CDATA[ Yorvi.Arias@crunchydata.com (Yorvi Arias) ]]></author>
<dc:creator><![CDATA[ Yorvi Arias ]]></dc:creator>
<guid isPermalink="false">https://blog.crunchydata.com/blog/setup-ora2pg-for-oracle-to-postgres-migration</guid>
<pubDate>Wed, 24 Jun 2020 05:00:00 EDT</pubDate>
<dc:date>2020-06-24T09:00:00.000Z</dc:date>
<atom:updated>2020-06-24T09:00:00.000Z</atom:updated></item>
<item><title><![CDATA[ Migrating from Oracle to PostgreSQL: Tips and Tricks ]]></title>
<link>https://www.crunchydata.com/blog/migrating-from-oracle-to-postgresql-questions-and-considerations</link>
<description><![CDATA[ Migrating from one database to another is inherently new technology and can raise a multitude of questions. ]]></description>
<content:encoded><![CDATA[ <p>Migrating to PostgreSQL from Oracle is a topic that often comes up in discussions around PostgreSQL. At Crunchy Data, we are of course not surprised that there is broad interest in moving to the world's most advanced database.<p>There are a lot of great reasons to migrate to PostgreSQL, and if you haven't looked at PostgreSQL lately, it would be a good time to do so again given the various improvements in PostgreSQL 12.<p>That said, migrating from one database to another is inherently new technology and can raise a multitude of questions. To help ease the transition, we are providing a few frequently asked questions and answers from users transitioning from Oracle to PostgreSQL, based on real life scenarios, to serve as a helpful resource.<h2 id=common-questions-differences-and-solutions><a href=#common-questions-differences-and-solutions>Common Questions, Differences and Solutions</a></h2><h3 id=how-to-install-orafce><a href=#how-to-install-orafce>How To Install Orafce</a></h3><p>Orafce is a useful extension that allows you to implement some functions from Oracle in PostgreSQL. For example, if you are used to DATE functions in Oracle, this extension allows you to use those functions. For additional information about Orafce: <a href=https://github.com/orafce/orafce>https://github.com/orafce/orafce.</a><p>Simply follow these steps to get Orafce up and running in a PostgreSQL 12 and RHEL 7 environment.<p>Typically, the process to build Orafce from source code is relatively user-friendly, but requires a number of dependencies. First, it is necessary to have the <code>postgresql12-devel</code> package installed, as it contains the binary for pg_config. Assuming <code>postgresql12-devel</code> is installed, you may proceed to the following steps to build Orafce and create the extension.<ol><li><p>Install the dependencies:<pre><code class=language-shell>sudo yum -y install flex bison readline-devel zlib-devel openssl-devel wget libicu-devel install llvm5.0-devel llvm-toolset-7-clang gcc-c++
</code></pre><li><p>Download the full Orafce source code, available on GitHub. If you are able to connect to GitHub directly, you may use the following command:<pre><code class=language-shell>git clone git@github.com:orafce/orafce.git
</code></pre><li><p>Make sure you have pg_config in your path. You may use <code>echo $PATH</code> to check if <code>/usr/pgsql-12/bin</code> is present. If not, do the following: <code>export PATH=$PATH:/usr/pgsql-12/bin/</code><li><p>Build the source code. From within the orafce directory, run the following command:<pre><code class=language-shell>make all
</code></pre><li><p>Install the source code. From within the orafce directory, run the following command:<pre><code class=language-shell>make install
</code></pre><li><p>Create the orafce extension inside the database. Connect to the database as a user with extension creating privileges and use the following command:<pre><code class=language-pgsql>CREATE EXTENSION orafce;
</code></pre></ol><p>You will also need to have <code>rhel-7-server-devtools-rpms</code> enabled in order to access the <code>llvm-toolset-7-clang package</code>. This repo can be enabled by running the following command as superuser: <code>subscription-manager repos --enable=rhel-7-server-devtools-rpms</code>.<p>Having performed all of these steps, you will have successfully created the orafce extension for your PostgreSQL database.<h3 id=how-to-disable-and-enable-constraints><a href=#how-to-disable-and-enable-constraints>How To Disable and Enable Constraints</a></h3><p>As you may know, Oracle allows you to disable and enable a constraint as many times as needed. This is something that is not commonly done in PostgreSQL and generally isn’t recommended in any database instance. Even though Oracle allows users to disable and enable constraints, this can cause you to run into data corruption if not handled with great care.<p>In PostgreSQL, instead of disabling constraints, one typically creates the constraints as deferrable and then uses the <code>SET CONSTRAINTS</code> command to defer them. If the constraint isn't currently deferrable then it will need to be dropped and recreated as deferrable. When creating a constraint, the deferrable clause specifies the default time to check the constraint.<p>It may also possible to alter the constraint and make it deferrable, avoiding the need to drop and recreate. Note that all DDL in PostgreSQL is transactional, so if you wish to drop and recreate things without letting users enter potentially bad data, you can put all of the DDL in a transaction denoted by the <code>BEGIN/COMMIT</code> block. The tables will be locked for the transaction.<h3 id=how-to-disable-not-null-constraint><a href=#how-to-disable-not-null-constraint>How To Disable ‘NOT NULL’ Constraint</a></h3><p>Similar to the question above, we were asked how to disable <code>NOT NULL</code> constraint in PostgreSQL. In Oracle, when you run the command DISABLE CONSTRAINT it disabled all of the constraints including <code>NOT NULL</code>. As mentioned before it is not recommended to disable and enable constraints because the constraints can allow bad data into the database table without warning or notice. If this happens there would be no way to tell how long queries will have been returning necessarily insufficient and/or incorrect results based on bad data.<p>Fortunately, it is currently not possible to disable/enable <code>NOT NULL</code> in PostgreSQL. If you are required to do this, a better way is to drop and re-add the constraint. The command <code>ALTER TABLE tablename ALTER COLUMN columnname DROP NOT NULL;</code> is how you drop the NOT NULL constraint.<p>To re-add the <code>NOT NULL</code> constraint you will use the command <code>ALTER TABLE tablename ALTER COLUMN columnname SET NOT NULL;</code>. Re-adding the NOT NULL constraint will cause the constraint to be validated again, so this is not an instant operation. However, dropping and re-adding the <code>NOT NULL</code> constraints might be faster than having the constraint evaluated on every write during your process.<h3 id=the-grant-command><a href=#the-grant-command>The GRANT Command</a></h3><p>The GRANT command in PostgreSQL operates very similarly to Oracle. There are two basic variants to the command. It can grant privileges on a database object and grant membership to a role. A common question is how to grant create procedure or trigger to a role in PostgreSQL.<p>In PostgreSQL, you can grant the <code>TRIGGER</code> privilege to a table which gives the ability to create triggers on that table, not to use them. So, if trigger creation is all you are trying to grant, that is the only privilege you need to grant. You do not have to grant any special privileges to roles other than normal write privileges <code>(INSERT,UPDATE,DELETE)</code> in order to be able to then use the triggers on that table. As long as a role has normal write privileges to that table the triggers will automatically fire as needed.<p>All triggers in PostgreSQL use <code>FUNCTIONS</code> as the underlying object that performs the trigger action, not <code>PROCEDURES</code>. <code>PROCEDURES</code> code> did not exist in PostgreSQL prior to version 11 and as of version 11 they are two distinct object types.<p>The command syntax for <code>CREATE TRIGGER</code> requires some consideration. Prior to version 11, the clause to the <code>CREATE TRIGGER</code> command used the phrase <code>EXECUTE PROCEDURE</code> to name the object that the trigger will fire. As of version 11, it allows you to use the clause <code>EXECUTE PROCEDURE</code> or <code>FUNCTION</code>, however a function is still the only object allowed to be given here as the argument. As the current documentation for the command states:<p>"In the syntax of <code>CREATE TRIGGER</code>, the keywords <code>FUNCTION</code> and <code>PROCEDURE</code> are equivalent, but the referenced function must in any case be a function, not a procedure. The use of the keyword <code>PROCEDURE</code> here is historical and depreciated."<p>Additional information regarding <code>CREATE TRIGGER</code> can be found <a href=https://www.postgresql.org/docs/current/sql-createtrigger.html>here.</a><p>You can also do mass grants of specific privileges on existing objects, to grant all privileges to all procedures in the given schema. So to grant trigger creation privileges on all tables in a given schema you can do:<br><code>GRANT TRIGGER ON ALL TABLES IN SCHEMA &#60schema_name> TO ;</code><p>Note that it does not give the privilege to then drop triggers. Only the owner of a table can drop them. This command only does that for existing objects and not any future objects that may be created.<h3 id=is-it-possible-to-drop-database-objects-in-postgresql><a href=#is-it-possible-to-drop-database-objects-in-postgresql>Is it possible to drop database objects in PostgreSQL?</a></h3><p>In PostgreSQL, only the owner of the database or a super user is allowed to drop objects.<p>As per the following <a href=https://www.postgresql.org/docs/11/sql-grant.html>documentation</a>, “The right to drop or alter an object, is not treated as a grantable privilege. The owner inherits this privilege. (However, a similar effect can be obtained by granting or revoking membership in the role that owns the object) The owner implicitly has all grant options for the object, too.”<p>Please note: If your application or service depends on the Oracle ability to drop objects, it is possible that you might need to rewrite or reconfigure how this action is performed.<h3 id=how-to-check-for-not-null><a href=#how-to-check-for-not-null>How To Check for NOT NULL</a></h3><p>In Oracle, if you want to know which columns in a table are <code>NOT NULL</code> you can use the command <code>CHECK (&#60col_name> IS NOT NULL)</code>. PostgreSQL does this a little differently. Here’s how to check for this.<p>There is a <code>NOT NULL</code> constraint column in the <code>pg_attribute</code> systems catalog. The pg_attribute catalog stores information about table columns. As stated in the documentation (<a href=https://www.postgresql.org/docs/current/catalog-pg-attribute.html>https://www.postgresql.org/docs/current/catalog-pg-attribute.html</a>), “there will be exactly one pg_attribute row for every column in every table in the database.” <code>attnotnull</code> is the column name in pg_attribute that represents NOT NULL constraints.<p>If you are wondering where other constraints are stored in the system catalog, you can look at the following documentation (<a href=https://www.postgresql.org/docs/11/catalog-pg-constraint.html>https://www.postgresql.org/docs/11/catalog-pg-constraint.html</a>).<p>For an example query of how to link catalogs together to find not null constraint information, the query below that shows all user tables in the database that have not-null columns along with which columns they are.<br>If you also want to see these columns in the system catalogs, you can remove the WHERE condition that excludes the system schemas. Many links in system catalogs are managed via "oid" values and which tables they relate to are explicitly mentioned in the documentation for that system catalog (Ex: pg_attribute.attrelid relates to pg_class.oid).<pre><code class=language-pgsql>SELECT n.nspname as schemaname, c.relname as tablename, a.attname as columnname
FROM pg_class c
JOIN pg_namespace n ON c.relnamespace = n.oid
JOIN pg_attribute a ON c.oid = a.attrelid
WHERE a.attnotnull IS NOT NULL
AND n.nspname NOT IN ('information_schema', 'pg_catalog', 'pg_toast')
AND a.attnum > 0
ORDER BY 1,2,3;
</code></pre><h3 id=rowid-ctid-and-identity-columns><a href=#rowid-ctid-and-identity-columns>ROWID, CTID and Identity columns</a></h3><p>Oracle has a pseudocolumn called ROWID, which returns the address of the row in a table. PostgreSQL has something similar to this called CTID. The only problem is that the CTID gets changed after every VACUUM function. Fortunately, there is a good alternative for this: identity columns.<p>Since there is no ROWID in PostgreSQL we suggest using self-generated unique identifiers. This can be achieved in the form of identity columns. Identity columns will help you because they are generated when the row is created and will never change during the life of that row. It is important to know that the way IDENTITY is implemented means that you cannot pre-allocate values. IDENTITY also has additional logic controlling their generation/application, even though it is backed by a sequence. Use the following syntax to create an identity column:<pre><code class=language-txt>column_name type GENERATED { ALWAYS | BY DEFAULT } AS IDENTITY[ ( sequence_option ) ]
</code></pre><p>In the syntax you can see the additional logic as how you would generate the identity column. GENERATED ALWAYS instructs PostgreSQL to always generate a value for the identity column. If you try to insert/update a value in this GENERATED ALWAYS column, PostgreSQL will give you a warning. This is because the values are system generated and GENERATED ALWAYS means it can only have the system generated values.<p>GENERATED BY DEFAULT also instructs PostgreSQL to generate a value for the identity column. However, with GENERATED BY DEFAULT you can insert or update a value into the column, and PostgreSQL will use that value for the identity column instead of using the system-generated value.<p>We hope that this overview of a few common issues in transitioning from Oracle to PostgreSQL eases the process and gives long time Oracle users greater comfort as they evaluate PostgreSQL as an alternative.<p>For those just getting started with the migration consideration, no blog post on Oracle to PostgreSQL migration would be complete without a mention of ora2pg - a great open source Oracle migration tool that can help evaluate the of difficulty in your migration. Of course Crunchy Data is always here and happy to assist as well! ]]></content:encoded>
<category><![CDATA[ Production Postgres ]]></category>
<author><![CDATA[ Yorvi.Arias@crunchydata.com (Yorvi Arias) ]]></author>
<dc:creator><![CDATA[ Yorvi Arias ]]></dc:creator>
<guid isPermalink="false">https://blog.crunchydata.com/blog/migrating-from-oracle-to-postgresql-questions-and-considerations</guid>
<pubDate>Thu, 23 Jan 2020 04:00:00 EST</pubDate>
<dc:date>2020-01-23T09:00:00.000Z</dc:date>
<atom:updated>2020-01-23T09:00:00.000Z</atom:updated></item></channel></rss>