View Javadoc

1   /*
2    * SymmetricDS is an open source database synchronization solution.
3    *   
4    * Copyright (C) Eric Long <erilong@users.sourceforge.net>
5    *
6    * This library is free software; you can redistribute it and/or
7    * modify it under the terms of the GNU Lesser General Public
8    * License as published by the Free Software Foundation; either
9    * version 3 of the License, or (at your option) any later version.
10   *
11   * This library is distributed in the hope that it will be useful,
12   * but WITHOUT ANY WARRANTY; without even the implied warranty of
13   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14   * Lesser General Public License for more details.
15   *
16   * You should have received a copy of the GNU Lesser General Public
17   * License along with this library; if not, see
18   * <http://www.gnu.org/licenses/>.
19   */
20  
21  package org.jumpmind.symmetric.db.postgresql;
22  
23  import org.apache.commons.logging.Log;
24  import org.apache.commons.logging.LogFactory;
25  import org.jumpmind.symmetric.db.AbstractDbDialect;
26  import org.jumpmind.symmetric.db.BinaryEncoding;
27  import org.jumpmind.symmetric.db.IDbDialect;
28  import org.jumpmind.symmetric.model.Trigger;
29  import org.jumpmind.symmetric.model.TriggerHistory;
30  
31  public class PostgreSqlDbDialect extends AbstractDbDialect implements IDbDialect {
32  
33      static final Log logger = LogFactory.getLog(PostgreSqlDbDialect.class);
34  
35      static final String TRANSACTION_ID_EXPRESSION = "txid_current()";
36  
37      static final String SYNC_TRIGGERS_DISABLED_VARIABLE = "symmetric.triggers_disabled";
38      
39      static final String SYNC_NODE_DISABLED_VARIABLE = "symmetric.node_disabled";
40  
41      private boolean supportsTransactionId = false;
42  
43      private String transactionIdExpression = "null";
44  
45      protected String defaultSchema;
46  
47      protected void initForSpecificDialect() {
48          if (getMajorVersion() >= 8 && getMinorVersion() >= 3) {
49              logger.info("Enabling transaction ID support");
50              supportsTransactionId = true;
51              transactionIdExpression = TRANSACTION_ID_EXPRESSION;
52          }
53          try {
54              enableSyncTriggers();
55          } catch (Exception e) {
56              logger.error("Please add \"custom_variable_classes = 'symmetric'\" to your postgresql.conf file");
57              throw new RuntimeException("Missing custom variable class 'symmetric'", e);
58          }
59          defaultSchema = (String) jdbcTemplate.queryForObject("select current_schema()", String.class);        
60      }
61  
62      @Override
63      protected boolean doesTriggerExistOnPlatform(String catalogName, String schema, String tableName, String triggerName) {
64          return jdbcTemplate.queryForInt(
65              "select count(*) from information_schema.triggers where trigger_name = ? " +
66              "and event_object_table = ? and trigger_schema = ?",
67              new Object[] { triggerName.toLowerCase(), tableName.toLowerCase(), schema == null ? defaultSchema : schema }) > 0;
68      }
69  
70      public void removeTrigger(String schemaName, String triggerName) {
71          throw new RuntimeException("Not implemented.  Use removeTrigger(schema, trigger, table) instead.");
72      }
73  
74      public void removeTrigger(String catalogName, String schemaName, String triggerName, String tableName, TriggerHistory oldHistory) {
75          schemaName = schemaName == null ? "" : (schemaName + ".");
76          try {
77              jdbcTemplate.update("drop trigger " + triggerName + " on " + schemaName + tableName);
78              jdbcTemplate.update("drop function " + schemaName + "f" + triggerName + "()");
79          } catch (Exception e) {
80              logger.warn("Trigger does not exist");
81          }
82      }
83  
84      public void disableSyncTriggers(String nodeId) {
85          jdbcTemplate.queryForList("select set_config('" + SYNC_TRIGGERS_DISABLED_VARIABLE + "', '1', false)");
86          if (nodeId == null) {
87              nodeId = "";
88          }
89          jdbcTemplate.queryForList("select set_config('" + SYNC_NODE_DISABLED_VARIABLE + "', '" + nodeId + "', false)");
90      }
91  
92      public void enableSyncTriggers() {
93          jdbcTemplate.queryForList("select set_config('" + SYNC_TRIGGERS_DISABLED_VARIABLE + "', '', false)");
94          jdbcTemplate.queryForList("select set_config('" + SYNC_NODE_DISABLED_VARIABLE + "', '', false)");
95      }
96  
97      public String getSyncTriggersExpression() {
98          return "fn_sym_triggers_disabled() = 0";
99      }
100 
101     public String getTransactionTriggerExpression(Trigger trigger) {
102         return transactionIdExpression;
103     }
104 
105     public String getSelectLastInsertIdSql(String sequenceName) {
106         return "select currval('" + sequenceName + "_seq')";
107     }
108 
109     public boolean requiresSavepointForFallback() {
110         return true;
111     }
112 
113     public boolean isCharSpacePadded() {
114         return true;
115     }
116 
117     public boolean isCharSpaceTrimmed() {
118         return false;
119     }
120 
121     public boolean isEmptyStringNulled() {
122         return false;
123     }
124 
125     public boolean storesLowerCaseNamesInCatalog() {
126         return true;
127     }
128 
129     protected boolean allowsNullForIdentityColumn() {
130         return false;
131     }
132 
133     public boolean supportsTransactionId() {
134         return supportsTransactionId;
135     }
136 
137     public void purge() {
138     }
139 
140     public String getDefaultCatalog() {
141         return null;
142     }
143 
144     public String getDefaultSchema() {
145         return defaultSchema;
146     }
147     
148     public BinaryEncoding getBinaryEncoding() {
149         return BinaryEncoding.BASE64;
150     }
151 
152 }