View Javadoc

1   package com.sri.emo.commandline.defaults;
2   
3   import com.jcorporate.expresso.core.dataobjects.DataException;
4   import com.jcorporate.expresso.core.dataobjects.DataObject;
5   import com.jcorporate.expresso.core.dataobjects.DuplicateKeyException;
6   import com.jcorporate.expresso.core.dataobjects.jdbc.JDBCObjectMetaData;
7   import com.jcorporate.expresso.core.dataobjects.jdbc.JDBCUtil;
8   import com.jcorporate.expresso.core.db.DBException;
9   import com.jcorporate.expresso.core.dbobj.DBField;
10  import com.jcorporate.expresso.core.dbobj.DBObject;
11  import com.sri.common.dbobj.RepositoryException;
12  import com.sri.emo.commandline.SqlRowGenerator;
13  import org.apache.log4j.Logger;
14  
15  import java.util.Iterator;
16  
17  /***
18   * Generates an insertion.
19   *
20   * @author Michael Rimov
21   * @version 1.0
22   */
23  public class DefaultSQLGenerator implements SqlRowGenerator {
24  
25      private static Logger log = Logger.getLogger(DefaultSQLGenerator.class);
26  
27      public static final boolean USE_IGNORE_SYNTAX = true;
28  
29      public static final boolean SKIP_IGNORE_SYNTAX = false;
30  
31      private final boolean useIgnoreSyntax;
32  
33      public DefaultSQLGenerator() {
34          this(SKIP_IGNORE_SYNTAX);
35      }
36  
37      public DefaultSQLGenerator(boolean useIgnoreSyntax) {
38          super();
39          this.useIgnoreSyntax = useIgnoreSyntax;
40      }
41  
42  
43      public String generateInsert(DBObject individualRow) {
44          try {
45              return generateAdd(individualRow);
46          } catch (DataException ex) {
47              throw new RepositoryException("Error generating insert for " + individualRow + ".", ex);
48          }
49      }
50  
51  
52      public String generateAdd(DataObject valueObject) throws DataException, DuplicateKeyException {
53          try {
54              if (valueObject == null) {
55                  throw new IllegalArgumentException(DefaultSQLGenerator.class.getName() + "add(DataObject):  valueObject was null");
56              }
57  
58              DBObject theObject = (DBObject) valueObject;
59              JDBCObjectMetaData metadata = (JDBCObjectMetaData) valueObject.getMetaData();
60  
61              boolean needComma = false;
62  
63  
64              theObject.checkAllRefsPublic();
65  
66              DBField oneField = null;
67  
68              /***
69               * sqlCommand will eventually = sqlCommand + valuesCommand.  The two
70               * are assembled in parallel in the loop below.
71               */
72              StringBuffer sqlCommand = new StringBuffer();
73              StringBuffer valuesCommand = new StringBuffer();
74              String theSqlCommand = null;
75              try {
76  
77                  sqlCommand.append("INSERT ");
78                  if (useIgnoreSyntax) {
79                      sqlCommand.append(" IGNORE ");
80                  }
81  
82                  sqlCommand.append(" INTO ");
83                  sqlCommand.append(metadata.getTargetSQLTable(theObject.getDataContext()));
84                  sqlCommand.append(" (");
85  
86                  valuesCommand.append(") VALUES (");
87  
88                  boolean needCommaValues = false;
89                  for (Iterator i = metadata.getAllFieldsMap().values().iterator(); i.hasNext();) {
90                      oneField = (DBField) i.next();
91  
92                      if (!oneField.isVirtual()) {
93                          theObject.checkField(oneField.getName(), theObject.getField(oneField.getName()));
94  
95                          if (oneField.isBinaryObjectType()) {
96                              if (log.isDebugEnabled()) {
97                                  log.debug("Skipping BINARY Object: " + oneField.getName());
98                              }
99                              continue;
100                         }
101 
102                         if (needComma) {
103                             sqlCommand.append(", ");
104                         }
105 
106                         sqlCommand.append(oneField.getName());
107                         needComma = true;
108 
109                         if (needCommaValues) {
110                             valuesCommand.append(", ");
111                         }
112                         if (oneField.isDateType()) {
113                             Object tmpData = valueObject.get(oneField.getName());
114                             String data;
115                             //
116                             //FIXME allow for appropriate support of other data types.
117                             //
118                             if (tmpData == null) {
119                                 data = null;
120                             } else if (tmpData instanceof String) {
121                                 data = (String) tmpData;
122                             } else {
123                                 data = tmpData.toString();
124                             }
125 
126                             if (data == null || (data.length() == 0)) {
127                                 valuesCommand.append("null");
128                             } else {
129                                 valuesCommand.append(JDBCUtil.getInstance()
130                                         .formatDateTime(valueObject, oneField.getName()));
131                             }
132                         } else if (oneField.isLongBinaryType()) {
133                             throw new UnsupportedOperationException("Cannot export long binaries");
134                         } else {
135                             valuesCommand.append(theObject.quoteIfNeeded(oneField.getName(),
136                                     null));
137                         }
138 
139                         needCommaValues = true;
140                     } /* if field is not virtual */
141 
142                 } /* for each field */
143 
144                 //Now we merge the values of the parallel loops
145                 sqlCommand.append(valuesCommand);
146                 sqlCommand.append(")");
147                 theSqlCommand = sqlCommand.toString();
148             } catch (NullPointerException npe) {
149                 log.error("NPE", npe);
150                 throw new DataException("Null Pointer Exception", npe);
151             } catch (DBException dbe) {
152                 log.error("DBException", dbe);
153                 throw dbe;
154             }
155 
156             theSqlCommand = postProcessCommand(theSqlCommand);
157             return theSqlCommand;
158         } catch (DBException ex) {
159             throw new RuntimeException("Error generating SQL for "
160                     + ((valueObject != null) ? valueObject.toString() : "null"), ex);
161         }
162 
163 
164     }
165 
166     /***
167      * Escapes newline sequences.  Otherwise, they'll be faithfully dumped ot the system. :(
168      *
169      * @param theSqlCommand the sql command to execute.
170      * @return
171      * @todo do we need tabs as well?
172      */
173     private String postProcessCommand(String theSqlCommand) {
174         StringBuffer buffer = new StringBuffer(theSqlCommand.length() + 1);
175 
176         for (int i = 0; i < theSqlCommand.length(); i++) {
177             char eachChar = theSqlCommand.charAt(i);
178             if (eachChar == '\n') {
179                 buffer.append("//n");
180             } else if (eachChar == '\r') {
181                 continue;
182             } else {
183                 buffer.append(eachChar);
184             }
185         }
186 
187         //Add the semicolon so MySQL query script users can
188         //operate.
189         buffer.append(";");
190         return buffer.toString();
191     }
192 
193 
194 }