1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 package org.efaps.db.print;
22
23 import java.sql.ResultSet;
24 import java.sql.SQLException;
25 import java.sql.Statement;
26 import java.util.ArrayList;
27 import java.util.List;
28
29 import org.apache.commons.dbutils.handlers.ArrayListHandler;
30 import org.apache.commons.lang3.builder.ToStringBuilder;
31 import org.efaps.admin.datamodel.Attribute;
32 import org.efaps.admin.datamodel.Type;
33 import org.efaps.db.AbstractPrintQuery;
34 import org.efaps.db.Context;
35 import org.efaps.db.Instance;
36 import org.efaps.db.InstanceQuery;
37 import org.efaps.db.QueryCache;
38 import org.efaps.db.QueryKey;
39 import org.efaps.db.transaction.ConnectionResource;
40 import org.efaps.db.wrapper.SQLPart;
41 import org.efaps.db.wrapper.SQLSelect;
42 import org.efaps.util.EFapsException;
43 import org.efaps.util.cache.CacheReloadException;
44 import org.infinispan.Cache;
45 import org.slf4j.Logger;
46 import org.slf4j.LoggerFactory;
47
48
49
50
51
52
53
54 public class LinkFromSelect
55 extends AbstractPrintQuery
56 {
57
58
59
60 private static final Logger LOG = LoggerFactory.getLogger(OneSelect.class);
61
62
63
64
65 private final String attrName;
66
67
68
69
70 private final Type type;
71
72
73
74
75 private boolean hasResult;
76
77
78
79
80 private final String key;
81
82
83
84
85
86
87 public LinkFromSelect(final String _linkFrom,
88 final String _key)
89 throws CacheReloadException
90 {
91 this.key = _key;
92 final String[] linkfrom = _linkFrom.split("#");
93 this.type = Type.get(linkfrom[0]);
94 this.attrName = linkfrom[1];
95 if (this.type == null) {
96 LinkFromSelect.LOG.error("Could not get type for linkfrom: '{}'", _linkFrom);
97 }
98 LinkFromSelect.LOG.debug("adding linkfrom: '{}'", _linkFrom);
99 final OneSelect onsel = new OneSelect(this, _linkFrom);
100 addOneSelect(onsel);
101 onsel.setFromSelect(this);
102 onsel.getSelectParts().add(new ISelectPart() {
103
104 @Override
105 public Type getType()
106 {
107 return LinkFromSelect.this.type;
108 }
109
110 @Override
111 public int join(final OneSelect _oneselect,
112 final SQLSelect _select,
113 final int _relIndex)
114 {
115
116 return 0;
117 }
118
119 @Override
120 public void addObject(final Object[] _rs)
121 throws SQLException
122 {
123
124 }
125
126 @Override
127 public Object getObject()
128 {
129 return null;
130 }
131
132 @Override
133 public void add2Where(final OneSelect _oneselect,
134 final SQLSelect _select)
135 {
136
137 }
138
139 @Override
140 public void next()
141 throws EFapsException
142 {
143
144 }
145 });
146 }
147
148
149
150
151
152
153 public boolean hasResult()
154 {
155 return this.hasResult;
156 }
157
158
159
160
161
162
163
164 public boolean execute(final OneSelect _onesel)
165 throws EFapsException
166 {
167 this.hasResult = executeOneCompleteStmt(createSQLStatement(_onesel), getAllSelects());
168 return this.hasResult;
169 }
170
171
172
173
174
175
176
177
178 private String createSQLStatement(final OneSelect _parentOnesel)
179 throws EFapsException
180 {
181 final Attribute attr = this.type.getAttribute(this.attrName);
182
183 if (attr == null) {
184 LOG.error("Could not find Attribute '{}' in Type '{}'", this.attrName, this.type.getName());
185 }
186
187 final SQLSelect select = new SQLSelect()
188 .column(0, "ID")
189 .column(0, attr.getSqlColNames().get(0))
190 .from(this.type.getMainTable().getSqlTable(), 0);
191
192
193 getAllSelects().get(0).append2SQLFrom(select);
194
195 int colIndex = select.getColumns().size() + 1;
196
197 for (final OneSelect oneSel : getAllSelects()) {
198 colIndex += oneSel.append2SQLSelect(select, colIndex);
199 }
200 select.addPart(SQLPart.WHERE)
201 .addColumnPart(0, attr.getSqlColNames().get(0))
202 .addPart(SQLPart.IN).addPart(SQLPart.PARENTHESIS_OPEN);
203
204 if (_parentOnesel.isMultiple()) {
205 boolean first = true;
206 final List<?> ids = (List<?>) _parentOnesel.getObject();
207 for (final Object id : ids) {
208 if (first) {
209 first = false;
210 } else {
211 select.addPart(SQLPart.COMMA);
212 }
213 select.addValuePart(id);
214 }
215 } else {
216 select.addValuePart(_parentOnesel.getObject());
217 }
218 select.addPart(SQLPart.PARENTHESIS_CLOSE);
219
220 _parentOnesel.setValueSelect(null);
221
222
223 if (this.type.getMainTable().getSqlColType() != null) {
224 select.addPart(SQLPart.AND)
225 .addColumnPart(0, this.type.getMainTable().getSqlColType())
226 .addPart(SQLPart.IN).addPart(SQLPart.PARENTHESIS_OPEN);
227 boolean first = true;
228 if (this.type.isAbstract()) {
229 for (final Type atype : getAllChildTypes(this.type)) {
230 if (first) {
231 first = false;
232 } else {
233 select.addPart(SQLPart.COMMA);
234 }
235 select.addValuePart(atype.getId());
236 }
237 if (first) {
238 LinkFromSelect.LOG.error("The type is declared abstract but does not have children: {}", this.type);
239 }
240 } else {
241 select.addValuePart(this.type.getId());
242 }
243
244 select.addPart(SQLPart.PARENTHESIS_CLOSE);
245 }
246
247 return select.getSQL();
248 }
249
250
251
252
253
254
255
256
257 private List<Type> getAllChildTypes(final Type _parent)
258 throws CacheReloadException
259 {
260 final List<Type> ret = new ArrayList<Type>();
261 for (final Type child : _parent.getChildTypes()) {
262 ret.addAll(getAllChildTypes(child));
263 ret.add(child);
264 }
265 return ret;
266 }
267
268
269
270
271 @SuppressWarnings("unchecked")
272 @Override
273 protected boolean executeOneCompleteStmt(final String _complStmt,
274 final List<OneSelect> _oneSelects)
275 throws EFapsException
276 {
277 boolean ret = false;
278 ConnectionResource con = null;
279 try {
280 LOG.debug("Executing SQLL: {}", _complStmt);
281 List<Object[]> rows = null;
282 boolean cached = false;
283 if (isCacheEnabled()) {
284 final QueryKey querykey = QueryKey.get(getKey(), _complStmt);
285 final Cache<QueryKey, Object> cache = QueryCache.getSqlCache();
286 if (cache.containsKey(querykey)) {
287 final Object object = cache.get(querykey);
288 if (object instanceof List) {
289 rows = (List<Object[]>) object;
290 }
291 cached = true;
292 }
293 }
294 if (!cached) {
295 con = Context.getThreadContext().getConnectionResource();
296 final Statement stmt = con.getConnection().createStatement();
297
298 final ResultSet rs = stmt.executeQuery(_complStmt.toString());
299 final ArrayListHandler handler = new ArrayListHandler(Context.getDbType().getRowProcessor());
300 rows = handler.handle(rs);
301 rs.close();
302 stmt.close();
303 con.commit();
304 if (isCacheEnabled()) {
305 final QueryKey querykey = QueryKey.get(getKey(), _complStmt);
306 final Cache<QueryKey, Object> cache = QueryCache.getSqlCache();
307 cache.put(querykey, rows);
308 }
309 }
310 for (final Object[] row : rows) {
311 for (final OneSelect onesel : _oneSelects) {
312 onesel.addObject(row);
313 }
314 ret = true;
315 }
316
317 } catch (final SQLException e) {
318 throw new EFapsException(InstanceQuery.class, "executeOneCompleteStmt", e);
319 } finally {
320 if (con != null && con.isOpened()) {
321 con.abort();
322 }
323 }
324 return ret;
325 }
326
327
328
329
330
331
332 public OneSelect getMainOneSelect()
333 {
334 return getAllSelects().get(0);
335 }
336
337
338
339
340
341
342
343
344 public Type getType()
345 {
346 return this.type;
347 }
348
349
350
351
352 @Override
353 public Instance getCurrentInstance()
354 {
355 return null;
356 }
357
358
359
360
361 @Override
362 public List<Instance> getInstanceList()
363 {
364 return null;
365 }
366
367
368
369
370 @Override
371 public Type getMainType()
372 {
373 return null;
374 }
375
376 @Override
377 public String toString()
378 {
379 return ToStringBuilder.reflectionToString(this);
380 }
381
382
383
384
385 @Override
386 public boolean isCacheEnabled()
387 {
388 return this.key != null;
389 }
390 }