1. Project Clover database Wed Nov 12 2025 05:07:35 UTC
  2. Package guru.mikelue.foxglove.jdbc

File GeneratedValueLoader.java

 

Coverage histogram

../../../../img/srcFileCovDistChart10.png
0% of files have more coverage

Code metrics

12
27
3
1
109
77
9
0.33
9
3
3

Classes

Class Line # Actions
GeneratedValueLoader 25 27 0% 9 1
0.9761904597.6%
 

Contributing tests

This file is covered by 48 tests. .

Source view

1    package guru.mikelue.foxglove.jdbc;
2   
3    import java.sql.PreparedStatement;
4    import java.sql.ResultSet;
5    import java.sql.SQLException;
6    import java.util.ArrayList;
7    import java.util.LinkedHashMap;
8    import java.util.List;
9    import java.util.Map;
10    import java.util.stream.Stream;
11   
12    import org.slf4j.Logger;
13    import org.slf4j.LoggerFactory;
14   
15    import guru.mikelue.foxglove.ColumnMeta;
16    import guru.mikelue.foxglove.TupleAccessor;
17   
18    import static java.util.Collections.unmodifiableList;
19   
20    /**
21    * Stateful loader for generated values after insert operation.
22    *
23    * This class will keep the metadata generated by {@link PreparedStatement#getGeneratedKeys()}.
24    */
 
25    class GeneratedValueLoader {
26    private final Logger logger = LoggerFactory.getLogger(GeneratedValueLoader.class);
27   
28    private final String[] askedGeneratedColumns;
29    private ColumnMeta[] metaOfColumns = null;
30    private TupleAccessorImpl.TupleSchema tupleSchema = null;
31   
 
32  109 toggle GeneratedValueLoader(String[] askedGeneratedColumns)
33    {
34  109 this.askedGeneratedColumns = askedGeneratedColumns;
35    }
36   
 
37  131 toggle List<TupleAccessor> toTuples(ResultSet rs) throws SQLException
38    {
39  131 initMetadata(rs);
40   
41  131 var tempRows = new ArrayList<TupleAccessor>(rs.getFetchSize());
42   
43  131 var rowIndexOfGeneratedKeys = 0;
44  1492 while (rs.next()) {
45  1361 Map<ColumnMeta, Object> rowValues = new LinkedHashMap<ColumnMeta, Object>(metaOfColumns.length);
46   
47  3478 for (var i = 0; i < metaOfColumns.length; i++) {
48  2117 rowValues.put(metaOfColumns[i], rs.getObject(i + 1));
49    }
50   
51  1361 var newTuple = tupleSchema.createTupleAccessor(rowValues, 0);
52  1361 logger.trace("Have fetched generated row: {}", newTuple);
53   
54  1361 tempRows.add(newTuple);
55  1361 rowIndexOfGeneratedKeys++;
56    }
57   
58  131 logger.debug("Have fetched [{}] generated keys.", rowIndexOfGeneratedKeys);
59   
60  131 return unmodifiableList(tempRows);
61    }
62   
 
63  131 toggle private void initMetadata(ResultSet rs) throws SQLException
64    {
65  131 if (metaOfColumns != null) {
66  22 return;
67    }
68   
69  109 if (askedGeneratedColumns.length == 0) {
70  47 metaOfColumns = MetaUtils.getColumnMetaList(rs.getMetaData()).toArray(new ColumnMeta[0]);
71  47 tupleSchema = new TupleAccessorImpl.TupleSchema(
72    List.of(metaOfColumns)
73    );
74  47 return;
75    }
76   
77    /*
78    * Since database like derby, sqlite would gives no column name by getGeneratedKeys(),
79    * we refine the column meta info here according to the asked generated columns.
80    */
81  62 metaOfColumns = MetaUtils.getColumnMetaList(rs.getMetaData()).toArray(new ColumnMeta[0]);
82   
83  125 for (var i = 0; i < askedGeneratedColumns.length; i++) {
84  63 var currentMeta = metaOfColumns[i];
85   
86  63 metaOfColumns[i] = new ColumnMeta(
87    askedGeneratedColumns[i],
88    currentMeta.properties(),
89    currentMeta.typeName(), currentMeta.jdbcType(),
90    currentMeta.size(), currentMeta.decimalDigits()
91    );
92    }
93   
94  62 tupleSchema = new TupleAccessorImpl.TupleSchema(
95    List.of(metaOfColumns)
96    );
97    // :~)
98   
99  62 if (logger.isDebugEnabled()) {
100  62 logger.debug("Loaded metadata for getGeneratedKeys(): {}",
101    Stream.of(metaOfColumns)
102    .map(col ->
103    String.format("%s(%s)", col.name(), col.jdbcType())
104    )
105    .toList()
106    );
107    }
108    }
109    }