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
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 }
141
142 }
143
144
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
188
189 buffer.append(";");
190 return buffer.toString();
191 }
192
193
194 }