@@ -56,84 +56,117 @@ public UserTable(AdvancedCorePlugin plugin, String name, Collection<Column> colu
5656 */
5757 public void forEachUser (BiConsumer <UUID , ArrayList <Column >> perUser , Consumer <Integer > onFinished ) {
5858 int processed = 0 ;
59- String query = "SELECT * FROM " + getName () + ";" ;
59+ final String query = "SELECT * FROM " + getName () + ";" ;
6060
61- PreparedStatement s = null ;
62- ResultSet rs = null ;
61+ try ( PreparedStatement ps = sqLite . getSQLConnection (). prepareStatement ( query , ResultSet . TYPE_FORWARD_ONLY ,
62+ ResultSet . CONCUR_READ_ONLY ); ResultSet rs = ps . executeQuery ()) {
6363
64- try {
65- s = sqLite .getSQLConnection ().prepareStatement (query );
66- rs = s .executeQuery ();
64+ // Helps on some JDBC drivers (SQLite varies, but harmless)
65+ try {
66+ ps .setFetchSize (500 );
67+ } catch (Exception ignored ) {
68+ }
69+
70+ // Compute metadata ONCE
71+ final ResultSetMetaData meta = rs .getMetaData ();
72+ final int colCount = meta .getColumnCount ();
73+
74+ // Precompute how each column should be read
75+ final String [] colNames = new String [colCount + 1 ];
76+ final byte [] kind = new byte [colCount + 1 ]; // 0=string, 1=int, 2=bool
77+ int uuidIndex = -1 ;
78+
79+ for (int i = 1 ; i <= colCount ; i ++) {
80+ String name = meta .getColumnLabel (i );
81+ colNames [i ] = name ;
82+
83+ if ("uuid" .equalsIgnoreCase (name )) {
84+ uuidIndex = i ;
85+ }
86+
87+ if (plugin .getUserManager ().getDataManager ().isInt (name )) {
88+ kind [i ] = 1 ;
89+ } else if (plugin .getUserManager ().getDataManager ().isBoolean (name )) {
90+ kind [i ] = 2 ;
91+ } else {
92+ kind [i ] = 0 ;
93+ }
94+ }
6795
6896 while (rs .next ()) {
69- final ResultSetMetaData meta = rs .getMetaData ();
70- ArrayList <Column > cols = new ArrayList <>();
7197 UUID uuid = null ;
7298
73- for (int i = 1 ; i <= meta .getColumnCount (); i ++) {
74- String columnName = meta .getColumnLabel (i );
99+ // Fast path: read uuid column directly (avoid scanning for it)
100+ if (uuidIndex > 0 ) {
101+ String uuidStr = rs .getString (uuidIndex );
102+ if (uuidStr != null && !uuidStr .isEmpty () && !"null" .equalsIgnoreCase (uuidStr )) {
103+ try {
104+ uuid = UUID .fromString (uuidStr );
105+ } catch (IllegalArgumentException ignored ) {
106+ // bad uuid; skip row below
107+ }
108+ }
109+ }
110+
111+ // Build cols only if we have a valid uuid (saves a ton if db has junk)
112+ if (uuid == null ) {
113+ continue ;
114+ }
115+
116+ ArrayList <Column > cols = new ArrayList <>(colCount );
117+
118+ for (int i = 1 ; i <= colCount ; i ++) {
119+ String columnName = colNames [i ];
75120 Column rCol ;
76121
77- if (plugin .getUserManager ().getDataManager ().isInt (columnName )) {
122+ switch (kind [i ]) {
123+ case 1 : { // int
78124 rCol = new Column (columnName , DataType .INTEGER );
125+ int v ;
79126 try {
80- rCol .setValue (new DataValueInt (rs .getInt (i )));
127+ v = rs .getInt (i );
128+ if (rs .wasNull ())
129+ v = 0 ;
81130 } catch (Exception e ) {
82131 String data = rs .getString (i );
83132 if (data != null ) {
84133 try {
85- rCol . setValue ( new DataValueInt ( Integer .parseInt (data )) );
134+ v = Integer .parseInt (data );
86135 } catch (NumberFormatException ex ) {
87- rCol . setValue ( new DataValueInt ( 0 )) ;
136+ v = 0 ;
88137 }
89138 } else {
90- rCol . setValue ( new DataValueInt ( 0 )) ;
139+ v = 0 ;
91140 }
92141 }
93- } else if (plugin .getUserManager ().getDataManager ().isBoolean (columnName )) {
142+ rCol .setValue (new DataValueInt (v ));
143+ break ;
144+ }
145+ case 2 : { // bool
94146 rCol = new Column (columnName , DataType .BOOLEAN );
147+ // Keep same semantics as your original: Boolean.valueOf(String)
95148 rCol .setValue (new DataValueBoolean (Boolean .valueOf (rs .getString (i ))));
96- } else {
149+ break ;
150+ }
151+ default : { // string
97152 rCol = new Column (columnName , DataType .STRING );
98- String val = rs .getString (i );
99- rCol .setValue (new DataValueString (val ));
100-
101- if ("uuid" .equalsIgnoreCase (columnName )) {
102- if (val != null && !val .isEmpty () && !"null" .equalsIgnoreCase (val )) {
103- try {
104- uuid = UUID .fromString (val );
105- } catch (IllegalArgumentException ignored ) {
106- // bad uuid in db; skip row below
107- }
108- }
109- }
153+ rCol .setValue (new DataValueString (rs .getString (i )));
154+ break ;
155+ }
110156 }
111157
112158 cols .add (rCol );
113159 }
114160
115- if (uuid != null ) {
116- processed ++;
117- perUser .accept (uuid , cols ); // <-- per row
118- }
119- // cols becomes eligible for GC after this loop iteration
161+ processed ++;
162+ perUser .accept (uuid , cols );
120163 }
164+
121165 } catch (SQLException e ) {
122166 e .printStackTrace ();
123167 } finally {
124- try {
125- if (rs != null )
126- rs .close ();
127- } catch (SQLException ignored ) {
128- }
129- try {
130- if (s != null )
131- s .close ();
132- } catch (SQLException ignored ) {
133- }
134-
135168 if (onFinished != null ) {
136- onFinished .accept (processed ); // <-- once
169+ onFinished .accept (processed );
137170 }
138171 }
139172 }
0 commit comments