Skip to content

Commit c50b6f3

Browse files
committed
Address review feedback for system tables
1 parent 1e1dee1 commit c50b6f3

File tree

5 files changed

+59
-32
lines changed

5 files changed

+59
-32
lines changed

pinot-broker/pom.xml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@
3636
<dependency>
3737
<groupId>org.apache.pinot</groupId>
3838
<artifactId>pinot-java-client</artifactId>
39-
<version>${project.version}</version>
4039
</dependency>
4140
<dependency>
4241
<groupId>org.apache.pinot</groupId>

pinot-broker/src/main/java/org/apache/pinot/broker/requesthandler/BaseSingleStageBrokerRequestHandler.java

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1155,19 +1155,17 @@ private BrokerResponseNative buildSystemTableBrokerResponse(String tableName, Sc
11551155
DataSchema dataSchema = buildSystemTableDataSchema(schema, projectionColumns);
11561156
List<GenericRow> rows = response != null ? response.getRows() : Collections.emptyList();
11571157
List<Object[]> resultRows = new ArrayList<>();
1158-
if (rows != null) {
1159-
for (GenericRow row : rows) {
1160-
Object[] values = new Object[projectionColumns.size()];
1161-
for (int i = 0; i < projectionColumns.size(); i++) {
1162-
values[i] = row.getValue(projectionColumns.get(i));
1163-
}
1164-
resultRows.add(values);
1158+
for (GenericRow row : rows) {
1159+
Object[] values = new Object[projectionColumns.size()];
1160+
for (int i = 0; i < projectionColumns.size(); i++) {
1161+
values[i] = row.getValue(projectionColumns.get(i));
11651162
}
1163+
resultRows.add(values);
11661164
}
11671165
BrokerResponseNative brokerResponse = new BrokerResponseNative();
11681166
brokerResponse.setResultTable(new ResultTable(dataSchema, resultRows));
11691167
brokerResponse.setNumDocsScanned(resultRows.size());
1170-
brokerResponse.setNumEntriesScannedPostFilter(resultRows.size());
1168+
brokerResponse.setNumEntriesScannedPostFilter(response != null ? response.getTotalRows() : 0);
11711169
if (response != null) {
11721170
brokerResponse.setTotalDocs(response.getTotalRows());
11731171
}

pinot-broker/src/test/java/org/apache/pinot/broker/requesthandler/SystemTableBrokerRequestHandlerTest.java

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,21 @@ public SystemTableResponse getRows(SystemTableRequest request)
152152
row2.putValue("status", "OFFLINE");
153153
rows.add(row2);
154154

155-
return new SystemTableResponse(rows, System.currentTimeMillis(), rows.size());
155+
int totalRows = rows.size();
156+
int offset = Math.max(0, request.getOffset());
157+
int limit = request.getLimit();
158+
if (offset > 0) {
159+
if (offset >= rows.size()) {
160+
return new SystemTableResponse(List.of(), System.currentTimeMillis(), totalRows);
161+
}
162+
rows = new ArrayList<>(rows.subList(offset, rows.size()));
163+
}
164+
if (limit == 0) {
165+
rows = List.of();
166+
} else if (limit > 0 && rows.size() > limit) {
167+
rows = new ArrayList<>(rows.subList(0, limit));
168+
}
169+
return new SystemTableResponse(rows, System.currentTimeMillis(), totalRows);
156170
}
157171
}
158172
}

pinot-common/src/main/java/org/apache/pinot/common/systemtable/provider/TablesSystemTableProvider.java

Lines changed: 32 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,18 @@ public final class TablesSystemTableProvider implements SystemTableProvider {
7272
.addSingleValueDimension("tableConfig", FieldSpec.DataType.STRING)
7373
.build();
7474

75+
private static final boolean IS_ADMIN_CLIENT_AVAILABLE;
76+
static {
77+
boolean available;
78+
try {
79+
Class.forName("org.apache.pinot.client.admin.PinotAdminClient");
80+
available = true;
81+
} catch (ClassNotFoundException e) {
82+
available = false;
83+
}
84+
IS_ADMIN_CLIENT_AVAILABLE = available;
85+
}
86+
7587
private final TableCache _tableCache;
7688
private final @Nullable HelixAdmin _helixAdmin;
7789
private final @Nullable String _clusterName;
@@ -130,12 +142,12 @@ public SystemTableResponse getRows(SystemTableRequest request) {
130142
List<String> sortedTableNames = new ArrayList<>(tableNamesWithType);
131143
sortedTableNames.sort(Comparator.naturalOrder());
132144

133-
List<GenericRow> rows = new ArrayList<>(sortedTableNames.size());
134-
int offset = request.getOffset();
145+
int offset = Math.max(0, request.getOffset());
135146
int limit = request.getLimit();
136-
if (limit == 0) {
137-
return new SystemTableResponse(List.of(), System.currentTimeMillis(), 0);
138-
}
147+
boolean hasLimit = limit > 0;
148+
int totalRows = 0;
149+
int initialCapacity = hasLimit ? Math.min(sortedTableNames.size(), limit) : 0;
150+
List<GenericRow> rows = new ArrayList<>(initialCapacity);
139151
for (String tableNameWithType : sortedTableNames) {
140152
TableType tableType = TableNameBuilder.getTableTypeFromTableName(tableNameWithType);
141153
if (tableType == null) {
@@ -146,6 +158,17 @@ public SystemTableResponse getRows(SystemTableRequest request) {
146158
if (!matchesFilter(request.getFilter(), stats, rawTableName)) {
147159
continue;
148160
}
161+
totalRows++;
162+
if (offset > 0) {
163+
offset--;
164+
continue;
165+
}
166+
if (limit == 0) {
167+
continue;
168+
}
169+
if (hasLimit && rows.size() >= limit) {
170+
continue;
171+
}
149172
GenericRow row = new GenericRow();
150173
row.putValue("tableName", rawTableName);
151174
row.putValue("type", stats._type);
@@ -159,16 +182,9 @@ public SystemTableResponse getRows(SystemTableRequest request) {
159182
row.putValue("serverTenant", stats._serverTenant);
160183
row.putValue("replicas", stats._replicas);
161184
row.putValue("tableConfig", stats._tableConfig);
162-
if (offset > 0) {
163-
offset--;
164-
continue;
165-
}
166185
rows.add(row);
167-
if (limit > 0 && rows.size() >= limit) {
168-
break;
169-
}
170186
}
171-
return new SystemTableResponse(rows, System.currentTimeMillis(), rows.size());
187+
return new SystemTableResponse(rows, System.currentTimeMillis(), totalRows);
172188
}
173189

174190
private TableStats buildStats(String tableNameWithType, TableType tableType) {
@@ -364,7 +380,7 @@ private boolean matchesNumber(List<String> candidates, long actual, SystemTableF
364380
baseUrl, response.statusCode(), response.body());
365381
}
366382
} catch (Exception e) {
367-
LOGGER.warn("system.tables: error fetching table size for {} via {}: {}", tableName, baseUrl, e.toString(), e);
383+
LOGGER.warn("system.tables: error fetching table size for {} via {}", tableName, baseUrl, e);
368384
}
369385
}
370386
return null;
@@ -453,13 +469,10 @@ private List<String> discoverControllersFromHelix() {
453469
}
454470

455471
private boolean isAdminClientAvailable() {
456-
try {
457-
Class.forName("org.apache.pinot.client.admin.PinotAdminClient");
458-
return true;
459-
} catch (ClassNotFoundException e) {
472+
if (!IS_ADMIN_CLIENT_AVAILABLE) {
460473
LOGGER.debug("PinotAdminClient not on classpath; falling back to HTTP for table size fetch");
461-
return false;
462474
}
475+
return IS_ADMIN_CLIENT_AVAILABLE;
463476
}
464477

465478
private @Nullable TableSize fetchWithAdminClient(List<String> controllers, String tableNameWithType) {

pinot-common/src/main/java/org/apache/pinot/common/utils/DatabaseUtils.java

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -67,9 +67,12 @@ public static String translateTableName(String tableName, @Nullable String datab
6767
case 2:
6868
Preconditions.checkArgument(!tableSplit[1].isEmpty(), "Invalid table name '%s'", tableName);
6969
String databasePrefix = tableSplit[0];
70-
// Allow system tables to bypass database prefix validation so they can be queried regardless of header.
71-
// System tables are globally accessible and not subject to database-level access controls, so skip validation.
72-
// Ensure system tables do not expose sensitive information because this bypass is intentional.
70+
/*
71+
* Allow system tables to bypass database prefix validation so they can be queried regardless of the database
72+
* header. System tables are intended to be globally accessible and are not subject to database-level access
73+
* controls. Ensure system tables do not expose sensitive information because they can be queried without a
74+
* matching database context.
75+
*/
7376
if ("system".equalsIgnoreCase(databasePrefix)) {
7477
return tableName;
7578
}

0 commit comments

Comments
 (0)