Line 1... |
Line 1... |
1 |
/*
|
1 |
/*
|
2 |
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
|
2 |
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
|
3 |
*
|
3 |
*
|
4 |
* Copyright 2011 OpenConcerto, by ILM Informatique. All rights reserved.
|
4 |
* Copyright 2011-2019 OpenConcerto, by ILM Informatique. All rights reserved.
|
5 |
*
|
5 |
*
|
6 |
* The contents of this file are subject to the terms of the GNU General Public License Version 3
|
6 |
* The contents of this file are subject to the terms of the GNU General Public License Version 3
|
7 |
* only ("GPL"). You may not use this file except in compliance with the License. You can obtain a
|
7 |
* only ("GPL"). You may not use this file except in compliance with the License. You can obtain a
|
8 |
* copy of the License at http://www.gnu.org/licenses/gpl-3.0.html See the License for the specific
|
8 |
* copy of the License at http://www.gnu.org/licenses/gpl-3.0.html See the License for the specific
|
9 |
* language governing permissions and limitations under the License.
|
9 |
* language governing permissions and limitations under the License.
|
Line 21... |
Line 21... |
21 |
import org.openconcerto.sql.model.SQLSelect.LockStrength;
|
21 |
import org.openconcerto.sql.model.SQLSelect.LockStrength;
|
22 |
import org.openconcerto.sql.model.SQLTable.VirtualFields;
|
22 |
import org.openconcerto.sql.model.SQLTable.VirtualFields;
|
23 |
import org.openconcerto.sql.model.graph.Link;
|
23 |
import org.openconcerto.sql.model.graph.Link;
|
24 |
import org.openconcerto.sql.model.graph.Link.Direction;
|
24 |
import org.openconcerto.sql.model.graph.Link.Direction;
|
25 |
import org.openconcerto.sql.model.graph.Path;
|
25 |
import org.openconcerto.sql.model.graph.Path;
|
- |
|
26 |
import org.openconcerto.utils.CollectionUtils;
|
26 |
import org.openconcerto.utils.ListMap;
|
27 |
import org.openconcerto.utils.ListMap;
|
27 |
import org.openconcerto.utils.SetMap;
|
28 |
import org.openconcerto.utils.SetMap;
|
28 |
import org.openconcerto.utils.Tuple2.List2;
|
29 |
import org.openconcerto.utils.Tuple2.List2;
|
29 |
|
30 |
|
30 |
import java.sql.ResultSet;
|
31 |
import java.sql.ResultSet;
|
Line 40... |
Line 41... |
40 |
import java.util.LinkedHashSet;
|
41 |
import java.util.LinkedHashSet;
|
41 |
import java.util.List;
|
42 |
import java.util.List;
|
42 |
import java.util.Map;
|
43 |
import java.util.Map;
|
43 |
import java.util.Map.Entry;
|
44 |
import java.util.Map.Entry;
|
44 |
import java.util.Set;
|
45 |
import java.util.Set;
|
- |
|
46 |
import java.util.function.BiFunction;
|
45 |
import java.util.logging.Level;
|
47 |
import java.util.logging.Level;
|
46 |
|
48 |
|
47 |
import org.apache.commons.dbutils.ResultSetHandler;
|
49 |
import org.apache.commons.dbutils.ResultSetHandler;
|
48 |
|
50 |
|
49 |
/**
|
51 |
/**
|
Line 100... |
Line 102... |
100 |
* @return la ligne correspondante.
|
102 |
* @return la ligne correspondante.
|
101 |
* @throws SQLException si problème lors de l'accès au ResultSet.
|
103 |
* @throws SQLException si problème lors de l'accès au ResultSet.
|
102 |
* @see SQLRow#SQLRow(SQLTable, Map)
|
104 |
* @see SQLRow#SQLRow(SQLTable, Map)
|
103 |
* @deprecated use {@link SQLRowListRSH} or {@link SQLRowValuesListFetcher} instead or if you
|
105 |
* @deprecated use {@link SQLRowListRSH} or {@link SQLRowValuesListFetcher} instead or if you
|
104 |
* must use a {@link ResultSet} call
|
106 |
* must use a {@link ResultSet} call
|
105 |
* {@link #createFromRS(SQLTable, ResultSet, ResultSetMetaData, boolean)} thus
|
107 |
* {@link #createListFromRS(SQLTable, ResultSet, boolean)} thus avoiding the
|
106 |
* avoiding the potentially costly {@link ResultSet#getMetaData()}
|
108 |
* potentially costly {@link ResultSet#getMetaData()}
|
107 |
*/
|
109 |
*/
|
108 |
public static final SQLRow createFromRS(SQLTable table, ResultSet rs, final boolean onlyTable) throws SQLException {
|
110 |
public static final SQLRow createFromRS(SQLTable table, ResultSet rs, final boolean onlyTable) throws SQLException {
|
109 |
return createFromRS(table, rs, rs.getMetaData(), onlyTable);
|
111 |
return createFromRS(table, rs, rs.getMetaData(), onlyTable);
|
110 |
}
|
112 |
}
|
111 |
|
113 |
|
- |
|
114 |
// see createListFromRS()
|
- |
|
115 |
@Deprecated
|
112 |
public static final SQLRow createFromRS(SQLTable table, ResultSet rs, final ResultSetMetaData rsmd, final boolean onlyTable) throws SQLException {
|
116 |
public static final SQLRow createFromRS(SQLTable table, ResultSet rs, final ResultSetMetaData rsmd, final boolean onlyTable) throws SQLException {
|
113 |
return createFromRS(table, rs, getFieldNames(table, rsmd, onlyTable));
|
117 |
return createFromRS(table, rs, new SQLFieldRowProcessor(table, getFieldNames(table, rsmd, onlyTable)), true);
|
114 |
}
|
118 |
}
|
115 |
|
119 |
|
116 |
private static final List<String> getFieldNames(SQLTable table, final ResultSetMetaData rsmd, final boolean tableOnly) throws SQLException {
|
120 |
private static final List<String> getFieldNames(SQLTable table, final ResultSetMetaData rsmd, final boolean tableOnly) throws SQLException {
|
117 |
final int colCount = rsmd.getColumnCount();
|
121 |
final int colCount = rsmd.getColumnCount();
|
118 |
final List<String> names = new ArrayList<String>(colCount);
|
122 |
final List<String> names = new ArrayList<String>(colCount);
|
Line 128... |
Line 132... |
128 |
}
|
132 |
}
|
129 |
|
133 |
|
130 |
return names;
|
134 |
return names;
|
131 |
}
|
135 |
}
|
132 |
|
136 |
|
133 |
// MAYBE create an opaque class holding names so that we can make this method, getFieldNames()
|
- |
|
134 |
// and createListFromRS() public
|
137 |
// ATTN doesn't check that names are fields of table
|
135 |
static final SQLRow createFromRS(SQLTable table, ResultSet rs, final List<String> names) throws SQLException {
|
138 |
public static final SQLRow createFromRS(SQLTable table, ResultSet rs, final SQLFieldRowProcessor rowProc, final boolean immutable) throws SQLException {
|
136 |
final int indexCount = names.size();
|
- |
|
137 |
|
- |
|
138 |
final Map<String, Object> m = new HashMap<String, Object>(indexCount);
|
139 |
final Map<String, Object> m = rowProc.toMap(rs);
|
139 |
for (int i = 0; i < indexCount; i++) {
|
- |
|
140 |
final String colName = names.get(i);
|
- |
|
141 |
if (colName != null)
|
- |
|
142 |
m.put(colName, rs.getObject(i + 1));
|
- |
|
143 |
}
|
- |
|
144 |
|
140 |
|
145 |
final Number id = getID(m, table, true);
|
141 |
final Number id = getID(m, table, true);
|
146 |
// e.g. LEFT JOIN : missing values are null
|
142 |
// e.g. LEFT JOIN : missing values are null
|
147 |
if (id == null)
|
143 |
if (id == null)
|
148 |
return null;
|
144 |
return null;
|
149 |
|
145 |
|
150 |
// pass already found ID
|
146 |
// pass already found ID
|
- |
|
147 |
final SQLRow res = new SQLRow(table, id, Collections.unmodifiableMap(m));
|
- |
|
148 |
if (immutable)
|
- |
|
149 |
res.freeze();
|
151 |
return new SQLRow(table, id, m);
|
150 |
return res;
|
152 |
}
|
151 |
}
|
153 |
|
152 |
|
154 |
/**
|
153 |
/**
|
155 |
* Create a list of rows using the metadata to find the columns' names.
|
154 |
* Create a list of rows using the metadata to find the columns' names.
|
156 |
*
|
155 |
*
|
Line 160... |
Line 159... |
160 |
* <code>table</code>.
|
159 |
* <code>table</code>.
|
161 |
* @return the data of the result set as SQLRows.
|
160 |
* @return the data of the result set as SQLRows.
|
162 |
* @throws SQLException if an error occurs while reading <code>rs</code>.
|
161 |
* @throws SQLException if an error occurs while reading <code>rs</code>.
|
163 |
*/
|
162 |
*/
|
164 |
public static final List<SQLRow> createListFromRS(SQLTable table, ResultSet rs, final boolean tableOnly) throws SQLException {
|
163 |
public static final List<SQLRow> createListFromRS(SQLTable table, ResultSet rs, final boolean tableOnly) throws SQLException {
|
165 |
return createListFromRS(table, rs, getFieldNames(table, rs.getMetaData(), tableOnly));
|
164 |
return createListFromRS(table, rs, getFieldNames(table, rs.getMetaData(), tableOnly), true);
|
166 |
}
|
165 |
}
|
167 |
|
166 |
|
168 |
/**
|
167 |
/**
|
169 |
* Create a list of rows without using the metadata.
|
168 |
* Create a list of rows without using the metadata.
|
170 |
*
|
169 |
*
|
171 |
* @param table the table of the rows.
|
170 |
* @param table the table of the rows.
|
172 |
* @param rs the result set.
|
171 |
* @param rs the result set.
|
173 |
* @param names the name of the field for each column, nulls are ignored, e.g. ["DESIGNATION",
|
172 |
* @param names the name of the field for each column, nulls are ignored, e.g. ["DESIGNATION",
|
174 |
* null, "ID"].
|
173 |
* null, "ID"].
|
- |
|
174 |
* @param immutable <code>true</code> if the result should be immutable.
|
175 |
* @return the data of the result set as SQLRows.
|
175 |
* @return the data of the result set as SQLRows.
|
176 |
* @throws SQLException if an error occurs while reading <code>rs</code>.
|
176 |
* @throws SQLException if an error occurs while reading <code>rs</code>.
|
177 |
*/
|
177 |
*/
|
178 |
static final List<SQLRow> createListFromRS(SQLTable table, ResultSet rs, final List<String> names) throws SQLException {
|
178 |
static final List<SQLRow> createListFromRS(SQLTable table, ResultSet rs, final List<String> names, final boolean immutable) throws SQLException {
|
179 |
final List<SQLRow> res = new ArrayList<SQLRow>();
|
179 |
final List<SQLRow> res = new ArrayList<SQLRow>();
|
- |
|
180 |
final SQLFieldRowProcessor rowProc = new SQLFieldRowProcessor(table, names);
|
180 |
while (rs.next()) {
|
181 |
while (rs.next()) {
|
181 |
final SQLRow row = createFromRS(table, rs, names);
|
182 |
final SQLRow row = createFromRS(table, rs, rowProc, immutable);
|
182 |
if (row != null)
|
183 |
if (row != null)
|
183 |
res.add(row);
|
184 |
res.add(row);
|
184 |
}
|
185 |
}
|
185 |
return res;
|
186 |
return immutable ? Collections.unmodifiableList(res) : res;
|
186 |
}
|
187 |
}
|
187 |
|
188 |
|
188 |
static final SQLRow createFromSelect(final SQLTable t, final VirtualFields vfs, final int id, final LockStrength l) {
|
189 |
static final SQLRow createFromSelect(final SQLTable t, final VirtualFields vfs, final int id, final LockStrength l) {
|
189 |
final SQLSelect sel = new SQLSelect(true).addAllSelect(t.getFields(vfs));
|
190 |
final SQLSelect sel = new SQLSelect(true).addAllSelect(t.getFields(vfs));
|
190 |
sel.setLockStrength(l);
|
191 |
sel.setLockStrength(l);
|
191 |
sel.setWhere(new Where(t.getKey(), "=", id));
|
192 |
sel.setWhere(new Where(t.getKey(), "=", id));
|
192 |
@SuppressWarnings("unchecked")
|
193 |
@SuppressWarnings("unchecked")
|
193 |
final Map<String, ?> map = (Map<String, ?>) t.getDBSystemRoot().getDataSource().execute(sel.asString(), new IResultSetHandler(SQLDataSource.MAP_HANDLER, l.equals(LockStrength.NONE)));
|
194 |
final Map<String, Object> map = (Map<String, Object>) t.getDBSystemRoot().getDataSource().execute(sel.asString(),
|
- |
|
195 |
new IResultSetHandler(SQLDataSource.MAP_HANDLER, l.equals(LockStrength.NONE)));
|
194 |
return new SQLRow(t, id, map);
|
196 |
return new SQLRow(t, id, map == null ? null : Collections.unmodifiableMap(map));
|
195 |
}
|
197 |
}
|
196 |
|
198 |
|
197 |
/**
|
199 |
/**
|
198 |
* Create an empty existing row (without checking the DB).
|
200 |
* Create an empty existing row (without checking the DB).
|
199 |
*
|
201 |
*
|
200 |
* @param t the table.
|
202 |
* @param t the table.
|
201 |
* @param id the ID.
|
203 |
* @param id the ID.
|
202 |
* @return a new {@link #exists() existing} {@link #isFilled() filled} {@link #getFields()
|
204 |
* @return a new {@link #exists() existing} {@link #isFilled() filled} {@link #isFrozen()
|
203 |
* empty} row.
|
205 |
* frozen} {@link #getFields() empty} row.
|
204 |
*/
|
206 |
*/
|
205 |
static final SQLRow createEmpty(final SQLTable t, final int id) {
|
207 |
public static final SQLRow createEmpty(final SQLTable t, final int id) {
|
206 |
return new SQLRow(t, id, Collections.<String, Object> emptyMap());
|
208 |
final SQLRow res = new SQLRow(t, id, Collections.<String, Object> emptyMap());
|
- |
|
209 |
res.freeze();
|
- |
|
210 |
return res;
|
- |
|
211 |
}
|
- |
|
212 |
|
- |
|
213 |
public static final <R extends SQLRowAccessor, A> SQLRow trim(final R r, final BiFunction<? super R, ? super A, ? extends Map<String, Object>> getVals, final A arg) {
|
- |
|
214 |
final SQLRow res = new SQLRow(r.getTable(), null, CollectionUtils.toImmutableMap(getVals.apply(r, arg)));
|
- |
|
215 |
res.freeze();
|
- |
|
216 |
return res;
|
207 |
}
|
217 |
}
|
208 |
|
218 |
|
209 |
private final int ID;
|
219 |
private final int ID;
|
210 |
private final Number idNumber;
|
220 |
private final Number idNumber;
|
211 |
private Map<String, Object> values;
|
221 |
private Map<String, Object> values;
|
212 |
private boolean fetched;
|
222 |
private boolean fetched;
|
- |
|
223 |
private boolean frozen = false;
|
213 |
|
224 |
|
214 |
private SQLRow(SQLTable table, Number id) {
|
225 |
private SQLRow(SQLTable table, Number id) {
|
215 |
super(table);
|
226 |
super(table);
|
216 |
this.fetched = false;
|
227 |
this.fetched = false;
|
217 |
this.ID = id.intValue();
|
228 |
this.ID = id.intValue();
|
Line 237... |
Line 248... |
237 |
* @param table la table.
|
248 |
* @param table la table.
|
238 |
* @param values les valeurs de la lignes.
|
249 |
* @param values les valeurs de la lignes.
|
239 |
* @throws IllegalArgumentException si values ne contient pas la clef de la table.
|
250 |
* @throws IllegalArgumentException si values ne contient pas la clef de la table.
|
240 |
*/
|
251 |
*/
|
241 |
public SQLRow(SQLTable table, Map<String, ?> values) {
|
252 |
public SQLRow(SQLTable table, Map<String, ?> values) {
|
242 |
this(table, null, values);
|
253 |
this(table, null, values == null ? null : CollectionUtils.toImmutableMap(values));
|
243 |
}
|
254 |
}
|
244 |
|
255 |
|
245 |
// allow to call getID() only once
|
256 |
// allow to call getID() only once
|
- |
|
257 |
// Private since it doesn't make sure the map is immutable.
|
246 |
private SQLRow(SQLTable table, final Number id, Map<String, ?> values) {
|
258 |
private SQLRow(SQLTable table, final Number id, Map<String, Object> values) {
|
247 |
this(table, id == null ? getID(values, table, false) : id);
|
259 |
this(table, id == null ? getID(values, table, false) : id);
|
248 |
// faire une copie, sinon backdoor pour changer les valeurs sans qu'on s'en aperçoive
|
- |
|
249 |
this.setValues(values == null ? null : new HashMap<String, Object>(values));
|
260 |
this.setValues(values);
|
250 |
}
|
261 |
}
|
251 |
|
262 |
|
252 |
// return ID, must always be present but may be null if <code>nullAllowed</code>
|
263 |
// return ID, must always be present but may be null if <code>nullAllowed</code>
|
253 |
private static Number getID(Map<String, ?> values, final SQLTable table, final boolean nullAllowed) {
|
264 |
private static Number getID(Map<String, ?> values, final SQLTable table, final boolean nullAllowed) {
|
254 |
final String keyName = table.getKey().getName();
|
265 |
final String keyName = table.getKey().getName();
|
Line 263... |
Line 274... |
263 |
final String valS = keyValue == null ? "' is null" : "' isn't a Number : " + keyValue.getClass() + " " + keyValue;
|
274 |
final String valS = keyValue == null ? "' is null" : "' isn't a Number : " + keyValue.getClass() + " " + keyValue;
|
264 |
throw new IllegalArgumentException("The value of '" + keyName + valS);
|
275 |
throw new IllegalArgumentException("The value of '" + keyName + valS);
|
265 |
}
|
276 |
}
|
266 |
}
|
277 |
}
|
267 |
|
278 |
|
- |
|
279 |
public final SQLRow copy(final boolean freeze) {
|
- |
|
280 |
final SQLRow res = new SQLRow(this.getTable(), this.getIDNumber());
|
- |
|
281 |
if (this.isFilled())
|
- |
|
282 |
// safe to share map, since it is immutable
|
- |
|
283 |
res.setValues(this.getValues());
|
- |
|
284 |
assert res.isFilled() == this.isFilled();
|
- |
|
285 |
if (freeze)
|
- |
|
286 |
res.freeze();
|
- |
|
287 |
assert res.isFrozen() == freeze;
|
- |
|
288 |
return res;
|
- |
|
289 |
}
|
- |
|
290 |
|
- |
|
291 |
@Override
|
- |
|
292 |
public final boolean isFrozen() {
|
- |
|
293 |
return this.frozen;
|
- |
|
294 |
}
|
- |
|
295 |
|
- |
|
296 |
private void checkFrozen() {
|
- |
|
297 |
if (this.isFrozen())
|
- |
|
298 |
throw new IllegalStateException("SQLRow is not modifiable");
|
- |
|
299 |
}
|
- |
|
300 |
|
- |
|
301 |
/**
|
- |
|
302 |
* Freeze this instance so that no modification can be made. Once this method returns, this
|
- |
|
303 |
* instance can be safely published (e.g. stored into a field that is properly guarded by a
|
- |
|
304 |
* lock) to other threads without further synchronizations.
|
- |
|
305 |
*
|
- |
|
306 |
* @return <code>true</code> if this call changed the frozen status.
|
- |
|
307 |
*/
|
- |
|
308 |
public final boolean freeze() {
|
- |
|
309 |
if (this.frozen)
|
- |
|
310 |
return false;
|
- |
|
311 |
this.frozen = true;
|
- |
|
312 |
return true;
|
- |
|
313 |
}
|
- |
|
314 |
|
- |
|
315 |
@Override
|
- |
|
316 |
public final SQLRow toImmutable() {
|
- |
|
317 |
if (this.isFrozen())
|
- |
|
318 |
return this;
|
- |
|
319 |
return this.copy(true);
|
- |
|
320 |
}
|
- |
|
321 |
|
268 |
/**
|
322 |
/**
|
269 |
* Whether this contains values or just the {@link #getIDNumber() id}. NOTE that
|
323 |
* Whether this contains values or just the {@link #getIDNumber() id}. NOTE that
|
270 |
* {@link #getObject(String)} (and thus any other methods that call it) will access the DB if
|
324 |
* {@link #getObject(String)} (and thus any other methods that call it) will access the DB if
|
271 |
* the requested field is {@link #getFields() missing} even if this returns <code>true</code>.
|
325 |
* the requested field is {@link #getFields() missing} even if this returns <code>true</code>.
|
272 |
*
|
326 |
*
|
Line 311... |
Line 365... |
311 |
*
|
365 |
*
|
312 |
* @param useCache <code>true</code> to use the {@link SQLDataSource#isCacheEnabled() cache}.
|
366 |
* @param useCache <code>true</code> to use the {@link SQLDataSource#isCacheEnabled() cache}.
|
313 |
* @return a new instance.
|
367 |
* @return a new instance.
|
314 |
*/
|
368 |
*/
|
315 |
public final SQLRow fetchNew(final boolean useCache) {
|
369 |
public final SQLRow fetchNew(final boolean useCache) {
|
316 |
return new SQLRow(this.getTable(), this.getIDNumber()).fetchValues(useCache);
|
370 |
return this.fetchNewRow(useCache);
|
317 |
}
|
371 |
}
|
318 |
|
372 |
|
319 |
@SuppressWarnings("unchecked")
|
373 |
@SuppressWarnings("unchecked")
|
320 |
SQLRow fetchValues(final boolean readCache, final boolean writeCache) {
|
374 |
SQLRow fetchValues(final boolean readCache, final boolean writeCache) {
|
- |
|
375 |
// not necessary here, but allows to fail early and avoid a request
|
- |
|
376 |
// implique trop de regression dans la branche : checkFrozen();
|
321 |
final IResultSetHandler handler = new IResultSetHandler(SQLDataSource.MAP_HANDLER, readCache, writeCache) {
|
377 |
final IResultSetHandler handler = new IResultSetHandler(SQLDataSource.MAP_HANDLER, readCache, writeCache) {
|
322 |
@Override
|
378 |
@Override
|
323 |
public Set<SQLRow> getCacheModifiers() {
|
379 |
public Set<SQLRow> getCacheModifiers() {
|
324 |
return Collections.singleton(SQLRow.this);
|
380 |
return Collections.singleton(SQLRow.this);
|
325 |
}
|
381 |
}
|
326 |
};
|
382 |
};
|
327 |
this.setValues((Map<String, Object>) this.getTable().getBase().getDataSource().execute(this.getQuery(), handler, false));
|
383 |
final Map<String, Object> values = (Map<String, Object>) this.getTable().getBase().getDataSource().execute(this.getQuery(), handler, false);
|
- |
|
384 |
this.setValues(values == null ? null : Collections.unmodifiableMap(values));
|
328 |
return this;
|
385 |
return this;
|
329 |
}
|
386 |
}
|
330 |
|
387 |
|
331 |
// attention ne vérifie pas que tous les champs soient présents
|
388 |
// Attention ne vérifie pas que tous les champs soient présents.
|
- |
|
389 |
// Private since it doesn't make sure the map is immutable.
|
332 |
private final void setValues(Map<String, Object> values) {
|
390 |
private final void setValues(Map<String, Object> values) {
|
- |
|
391 |
// implique trop de regression dans la branche : checkFrozen();
|
333 |
this.values = values;
|
392 |
this.values = values;
|
334 |
if (!this.fetched)
|
393 |
if (!this.fetched)
|
335 |
this.fetched = true;
|
394 |
this.fetched = true;
|
336 |
}
|
395 |
}
|
337 |
|
396 |
|
Line 340... |
Line 399... |
340 |
*
|
399 |
*
|
341 |
* @return les noms des champs qui ont été chargé depuis la base.
|
400 |
* @return les noms des champs qui ont été chargé depuis la base.
|
342 |
*/
|
401 |
*/
|
343 |
@Override
|
402 |
@Override
|
344 |
public Set<String> getFields() {
|
403 |
public Set<String> getFields() {
|
345 |
return this.fetched ? Collections.unmodifiableSet(this.getValues().keySet()) : Collections.<String> emptySet();
|
404 |
return this.isFilled() ? this.getValues().keySet() : Collections.<String> emptySet();
|
346 |
}
|
405 |
}
|
347 |
|
406 |
|
348 |
// avoid Collections.unmodifiableSet() allocation
|
407 |
// avoid Collections.unmodifiableSet() allocation
|
349 |
@Override
|
408 |
@Override
|
350 |
public boolean contains(String fieldName) {
|
409 |
public boolean contains(String fieldName) {
|
351 |
return this.fetched ? this.getValues().containsKey(fieldName) : false;
|
410 |
return this.isFilled() ? this.getValues().containsKey(fieldName) : false;
|
352 |
}
|
411 |
}
|
353 |
|
412 |
|
354 |
private String getQuery() {
|
413 |
private String getQuery() {
|
355 |
return "SELECT * FROM " + this.getTable().getSQLName().quote() + " WHERE " + this.getWhere().getClause();
|
414 |
return "SELECT * FROM " + this.getTable().getSQLName().quote() + " WHERE " + this.getWhere().getClause();
|
356 |
}
|
415 |
}
|
Line 409... |
Line 468... |
409 |
}
|
468 |
}
|
410 |
assert this.getValues().containsKey(field);
|
469 |
assert this.getValues().containsKey(field);
|
411 |
return this.getValues().get(field);
|
470 |
return this.getValues().get(field);
|
412 |
}
|
471 |
}
|
413 |
|
472 |
|
- |
|
473 |
@Override
|
- |
|
474 |
public final Object getObjectNoCheck(String field) {
|
- |
|
475 |
return this.values.get(field);
|
- |
|
476 |
}
|
- |
|
477 |
|
414 |
/**
|
478 |
/**
|
415 |
* Fetch from the DB this row and the next/previous one. ATTN the rows are locked
|
479 |
* Fetch from the DB this row and the next/previous one. ATTN the rows are locked
|
416 |
* {@link LockStrength#UPDATE for update}, but if this method is not called from within a
|
480 |
* {@link LockStrength#UPDATE for update}, but if this method is not called from within a
|
417 |
* transaction, they will immediately be obsolete.
|
481 |
* transaction, they will immediately be obsolete.
|
418 |
*
|
482 |
*
|
Line 1038... |
Line 1102... |
1038 |
* @see #getAllValues()
|
1102 |
* @see #getAllValues()
|
1039 |
* @see #getObject(String)
|
1103 |
* @see #getObject(String)
|
1040 |
*/
|
1104 |
*/
|
1041 |
@Override
|
1105 |
@Override
|
1042 |
public Map<String, Object> getAbsolutelyAll() {
|
1106 |
public Map<String, Object> getAbsolutelyAll() {
|
1043 |
return Collections.unmodifiableMap(this.getValues());
|
1107 |
return this.getValues();
|
1044 |
}
|
1108 |
}
|
1045 |
|
1109 |
|
1046 |
private static final VirtualFields ALL_VALUES_FIELDS = VirtualFields.ALL.difference(VirtualFields.KEYS, VirtualFields.ARCHIVE, VirtualFields.ORDER);
|
1110 |
private static final VirtualFields ALL_VALUES_FIELDS = VirtualFields.ALL.difference(VirtualFields.KEYS, VirtualFields.ARCHIVE, VirtualFields.ORDER);
|
1047 |
|
1111 |
|
1048 |
/**
|
1112 |
/**
|
Line 1091... |
Line 1155... |
1091 |
public Number getIDNumber() {
|
1155 |
public Number getIDNumber() {
|
1092 |
return this.idNumber;
|
1156 |
return this.idNumber;
|
1093 |
}
|
1157 |
}
|
1094 |
|
1158 |
|
1095 |
@Override
|
1159 |
@Override
|
1096 |
public SQLRow asRow() {
|
1160 |
public SQLRow asRow(final Boolean immutable) {
|
- |
|
1161 |
if (immutable == null || this.isFrozen() == immutable)
|
1097 |
return this;
|
1162 |
return this;
|
- |
|
1163 |
else
|
- |
|
1164 |
return this.copy(immutable);
|
1098 |
}
|
1165 |
}
|
1099 |
|
1166 |
|
1100 |
@Override
|
1167 |
@Override
|
1101 |
public final SQLRowValues asRowValues() {
|
1168 |
public final SQLRowValues asRowValues(final Boolean immutable) {
|
1102 |
return this.createUpdateRow();
|
1169 |
final SQLRowValues res = this.createUpdateRow();
|
- |
|
1170 |
if (Boolean.TRUE.equals(immutable))
|
- |
|
1171 |
res.getGraph().freeze();
|
- |
|
1172 |
return res;
|
1103 |
}
|
1173 |
}
|
1104 |
|
1174 |
|
1105 |
/**
|
1175 |
/**
|
1106 |
* Note : ne compare pas les valeurs des champs de cette ligne.
|
1176 |
* Note : ne compare pas les valeurs des champs de cette ligne.
|
1107 |
*
|
1177 |
*
|