-
Notifications
You must be signed in to change notification settings - Fork 16
feat/CUS-9809-Added class to execute multiple queries at a time in oracle db #296
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat/CUS-9809-Added class to execute multiple queries at a time in oracle db #296
Conversation
📝 WalkthroughWalkthroughThe pull request bumps the project version from 1.0.9 to 1.0.10 and introduces four new OracleMultipleQueriesSelect action classes across Android, iOS, Mobile Web, and Web platforms. Each action executes multiple Oracle SELECT queries sequentially over a JDBC connection, formats results, and stores aggregated output into runtime variables. Changes
Sequence DiagramsequenceDiagram
participant Action as OracleMultipleQueriesSelect
participant DB as DatabaseUtil
participant JDBC as JDBC Driver
participant Oracle as Oracle Database
participant Runtime as Runtime Variable
Action->>Action: Parse queries from testData1
Action->>DB: getConnection(testData2 - URL)
DB->>JDBC: DriverManager.getConnection(url)
JDBC->>Oracle: Establish connection
Oracle-->>JDBC: Connection OK
JDBC-->>DB: Return Connection
DB-->>Action: Return Connection
Action->>Action: Split queries by semicolon
loop For each query
Action->>JDBC: Create Statement
Action->>JDBC: Execute query (SELECT)
JDBC->>Oracle: Run query
Oracle-->>JDBC: ResultSet
JDBC-->>Action: ResultSet + Metadata
Action->>Action: Extract column names from metadata
Action->>Action: Iterate rows, build output
Action->>Action: Format UI-friendly output
Action->>Action: Format log-friendly output
Action->>Action: Accumulate row values (comma-separated)
end
alt Runtime variable provided
Action->>Runtime: Store aggregated runtimeValue with variable name
Runtime-->>Action: Variable stored
end
Action->>JDBC: Close Statement
Action->>JDBC: Close Connection
JDBC->>Oracle: Disconnect
Oracle-->>JDBC: OK
JDBC-->>Action: Resources cleaned
Action-->>Action: Return Result.SUCCESS with message
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Suggested reviewers
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✨ Finishing touches
Warning Review ran into problems🔥 ProblemsGit: Failed to clone repository. Please run the Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 8
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (3)
oracledb_queries/src/main/java/com/testsigma/addons/web/OracleMultipleQueriesSelect.java (1)
1-140: Same critical and major issues as Android action.This Web action contains the same issues identified in the Android action review:
Critical issues:
- No null validation for
testData1andtestData2(lines 51, 54)- SQL injection risk - no validation that queries are SELECT-only (lines 54-65)
- ResultSet resource leak (line 64 onwards)
Major issues:
- No connection/query timeout (lines 51-53)
- Sensitive data exposure in logs (lines 62, 73)
Code duplication:
- This action duplicates the Android implementation with only
WebActionbase class andApplicationType.WEBdifferingRefer to the Android action review comments for detailed fixes. The essential refactor to extract common logic would address the duplication across all platform actions.
oracledb_queries/src/main/java/com/testsigma/addons/mobileweb/OracleMultipleQueriesSelect.java (1)
1-140: Same critical and major issues as Android and Web actions.This MobileWeb action contains identical issues:
Critical:
- Missing null validation for required inputs (lines 51, 54)
- SQL injection vulnerability (lines 54-65)
- ResultSet never closed (line 64 onwards)
Major:
- No timeout configuration (lines 51-53)
- PII/sensitive data logging (lines 62, 73)
Essential refactor:
- Code duplicated from Android/Web actions
See the Android action review for detailed remediation steps.
oracledb_queries/src/main/java/com/testsigma/addons/ios/OracleMultipleQueriesSelect.java (1)
1-142: Same critical and major issues as other platform actions.This iOS action contains the same issues identified in the Android action:
Critical issues:
- No null validation for
testData1andtestData2(lines 53, 56)- SQL injection risk - queries not validated as SELECT-only (lines 56-66)
- ResultSet resource leak (line 66 onwards)
Major issues:
- No connection/query timeout (lines 53-54)
- Sensitive data exposure in logs (lines 64, 74)
Code duplication:
- Core logic duplicated from Android/Web/MobileWeb actions
Refer to the Android action review for detailed remediation approaches and the essential refactor to eliminate duplication.
🤖 Fix all issues with AI Agents
In
@oracledb_queries/src/main/java/com/testsigma/addons/android/OracleMultipleQueriesSelect.java:
- Around line 1-140: The Android action OracleMultipleQueriesSelect duplicates
the same execute logic across platform-specific classes; extract the shared
DB-query/run-time-variable logic into a new utility (e.g.,
OracleMultipleQueriesExecutor) with a static method (e.g., execute(TestData
queries, TestData connectionUrl, TestData variableName, Logger logger,
Consumer<String> setSuccessMessage, Consumer<String> setErrorMessage)) that
contains the core code currently inside OracleMultipleQueriesSelect.execute(),
and update OracleMultipleQueriesSelect.execute() (and the iOS/MobileWeb/Web
action classes) to simply delegate to that utility, passing
testData1/testData2/testData3, logger, this::setSuccessMessage and
this::setErrorMessage so platform classes only differ by their base class and
ApplicationType.
- Around line 62-74: The code currently logs and displays the full SQL text
(variable query) via logger.info(...) and successMessage.append(...), which may
expose PII; update OracleMultipleQueriesSelect to stop emitting raw query
strings: replace the direct uses of query in logger.info and successMessage with
a sanitized representation (e.g., a helper method sanitizeQuery(String query)
that strips or masks literal values and parameters and/or returns only the query
type and table names), or log only the queryCounter and query type; ensure
successMessage shows the sanitizedQuery or a generic message like "Query N:
SELECT ... (parameters redacted)"; update references to logger.info("Executing
Query [" + queryCounter + "]: " + query) and successMessage.append(...
.append(query) ...) to use the sanitized value and add a short comment in docs
or method javadoc warning users not to include sensitive data in queries.
- Line 7: Remove the unused import of WebAction in
OracleMultipleQueriesSelect.java: delete the line importing
com.testsigma.sdk.WebAction since the class extends AndroidAction and never
references WebAction (class OracleMultipleQueriesSelect); after removal, rebuild
to ensure no references remain.
- Around line 51-53: The code in OracleMultipleQueriesSelect.java calls
DatabaseUtil.getConnection(testData2.getValue().toString()) and then creates a
Statement (stmt) without any timeouts; update the code to set a statement/query
timeout (use stmt.setQueryTimeout(seconds) after creating the Statement) and set
a network/connection timeout on the Connection (e.g.,
connection.setNetworkTimeout(...) or ensure DatabaseUtil.getConnection(...)
configures a socket/connection timeout), and if applicable set the driver login
timeout (DriverManager.setLoginTimeout or equivalent) so the action cannot hang
indefinitely while waiting for the DB.
- Around line 54-65: The loop executing user-supplied SQL in
OracleMultipleQueriesSelect.java (variables: testData1, queries, rawQuery,
query, and the stmt.executeQuery call producing ResultSet rs) must validate each
statement is a read-only SELECT before executing: trim and strip leading
comments, reject any query containing a semicolon or any DDL/DML keywords (e.g.,
INSERT, UPDATE, DELETE, DROP, ALTER, CREATE, TRUNCATE) and require the first
non-whitespace token to match a case-insensitive "SELECT" (e.g., regex like
^\s*(?i)select\b). For invalid queries, log an error or throw an exception and
skip executing it instead of calling stmt.executeQuery; keep the validation
logic adjacent to where rawQuery/query are prepared so no non-SELECT statement
can reach stmt.executeQuery.
- Around line 49-56: The code in OracleMultipleQueriesSelect accesses testData1
and testData2 (and their getValue() results) without null checks and can NPE;
before using them in the method where connection and stmt are created, validate
that testData1, testData2 and their getValue() results are non-null (e.g., in
the start of the execute/run method in OracleMultipleQueriesSelect), and handle
failures by logging a clear error via logger (including which input is missing)
and returning/throwing a controlled exception instead of proceeding to
connection/statement creation; ensure the split(" ;") on
testData1.getValue().toString() only runs after validation.
- Around line 64-119: The ResultSet created by stmt.executeQuery(query) in
OracleMultipleQueriesSelect is never closed, leaking DB resources and risking
issues when reusing the same Statement; fix by ensuring each ResultSet (variable
rs) is closed after processing—preferably wrap the executeQuery/iteration in a
try-with-resources or explicitly call rs.close() in a finally block right after
logging and before incrementing queryCounter, so every loop iteration closes its
ResultSet before the next executeQuery on stmt.
In
@oracledb_queries/src/main/java/com/testsigma/addons/ios/OracleMultipleQueriesSelect.java:
- Line 7: Remove the unused imports in OracleMultipleQueriesSelect.java: delete
the import of com.testsigma.sdk.WebAction and the import of
org.openqa.selenium.devtools.v135.io.IO since the class extends IOSAction and
neither symbol is referenced; ensure only required imports remain and run a
quick compile or IDE optimize imports to confirm no other unused imports exist.
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (5)
oracledb_queries/pom.xmloracledb_queries/src/main/java/com/testsigma/addons/android/OracleMultipleQueriesSelect.javaoracledb_queries/src/main/java/com/testsigma/addons/ios/OracleMultipleQueriesSelect.javaoracledb_queries/src/main/java/com/testsigma/addons/mobileweb/OracleMultipleQueriesSelect.javaoracledb_queries/src/main/java/com/testsigma/addons/web/OracleMultipleQueriesSelect.java
🔇 Additional comments (1)
oracledb_queries/pom.xml (1)
9-9: LGTM: Version bump aligns with new feature addition.The version increment from 1.0.9 to 1.0.10 is appropriate for introducing the new OracleMultipleQueriesSelect action classes across platforms.
| package com.testsigma.addons.android; | ||
|
|
||
| import com.testsigma.addons.oracledb.util.DatabaseUtil; | ||
| import com.testsigma.sdk.AndroidAction; | ||
| import com.testsigma.sdk.ApplicationType; | ||
| import com.testsigma.sdk.Result; | ||
| import com.testsigma.sdk.WebAction; | ||
| import com.testsigma.sdk.annotation.Action; | ||
| import com.testsigma.sdk.annotation.RunTimeData; | ||
| import com.testsigma.sdk.annotation.TestData; | ||
| import lombok.Data; | ||
| import org.apache.commons.lang3.exception.ExceptionUtils; | ||
| import org.openqa.selenium.NoSuchElementException; | ||
|
|
||
| import java.sql.*; | ||
|
|
||
| @Data | ||
| @Action( | ||
| actionText = "Execute OracleDB Multiple Select-Queries on the connection DB_Connection_URL and store output into a variable-name", | ||
| description = "Executes multiple Oracle SELECT queries, logs formatted result sets, and stores output in a runtime variable.", | ||
| applicationType = ApplicationType.ANDROID | ||
| ) | ||
| public class OracleMultipleQueriesSelect extends AndroidAction { | ||
|
|
||
| @TestData(reference = "Select-Queries") | ||
| private com.testsigma.sdk.TestData testData1; | ||
|
|
||
| @TestData(reference = "DB_Connection_URL") | ||
| private com.testsigma.sdk.TestData testData2; | ||
|
|
||
| @TestData(reference = "variable-name", isRuntimeVariable = true) | ||
| private com.testsigma.sdk.TestData testData3; | ||
|
|
||
| @RunTimeData | ||
| private com.testsigma.sdk.RunTimeData runTimeData; | ||
|
|
||
| @Override | ||
| public Result execute() throws NoSuchElementException { | ||
|
|
||
| Result result = Result.SUCCESS; | ||
| DatabaseUtil databaseUtil = new DatabaseUtil(); | ||
|
|
||
| Connection connection = null; | ||
| Statement stmt = null; | ||
|
|
||
| StringBuilder successMessage = new StringBuilder(); | ||
| StringBuilder runtimeValue = new StringBuilder(); | ||
|
|
||
| try { | ||
| logger.info("====== Oracle DB Multiple Query Execution Started ======"); | ||
|
|
||
| connection = databaseUtil.getConnection(testData2.getValue().toString()); | ||
| stmt = connection.createStatement(); | ||
|
|
||
| String[] queries = testData1.getValue().toString().split(";"); | ||
| int queryCounter = 1; | ||
|
|
||
| for (String rawQuery : queries) { | ||
|
|
||
| String query = rawQuery.trim(); | ||
| if (query.isEmpty()) continue; | ||
|
|
||
| logger.info("Executing Query [" + queryCounter + "]: " + query); | ||
|
|
||
| ResultSet rs = stmt.executeQuery(query); | ||
| ResultSetMetaData rsmd = rs.getMetaData(); | ||
| int columnCount = rsmd.getColumnCount(); | ||
|
|
||
| /* ---------- UI OUTPUT ---------- */ | ||
| successMessage.append("<br><b>Query ") | ||
| .append(queryCounter) | ||
| .append(" Result: ") | ||
| .append(query) | ||
| .append("</b><br>"); | ||
|
|
||
| /* ---------- LOG OUTPUT ---------- */ | ||
| StringBuilder log = new StringBuilder(); | ||
| log.append("\nQuery ").append(queryCounter) | ||
| .append(" Result: ").append(query).append("\n"); | ||
|
|
||
| log.append("--------------------------------------------------------\n"); | ||
|
|
||
| // Headers | ||
| StringBuilder headerRow = new StringBuilder(); | ||
| for (int i = 1; i <= columnCount; i++) { | ||
| headerRow.append(rsmd.getColumnName(i)); | ||
| if (i < columnCount) headerRow.append(" | "); | ||
| } | ||
| log.append(headerRow).append("\n"); | ||
| log.append("--------------------------------------------------------\n"); | ||
|
|
||
| // UI headers | ||
| for (int i = 1; i <= columnCount; i++) { | ||
| successMessage.append(rsmd.getColumnName(i)).append(" | "); | ||
| } | ||
| successMessage.append("<br>"); | ||
|
|
||
| // Rows | ||
| while (rs.next()) { | ||
| StringBuilder row = new StringBuilder(); | ||
| for (int j = 1; j <= columnCount; j++) { | ||
| String value = rs.getString(j); | ||
| String safe = value == null ? "" : value; | ||
|
|
||
| row.append(safe); | ||
| if (j < columnCount) row.append(" | "); | ||
|
|
||
| successMessage.append(safe).append(" | "); | ||
| runtimeValue.append(safe).append(","); | ||
| } | ||
| log.append(row).append("\n"); | ||
| successMessage.append("<br>"); | ||
| } | ||
|
|
||
| logger.info(log.toString()); | ||
| logger.info("Query [" + queryCounter + "] executed successfully"); | ||
|
|
||
| queryCounter++; | ||
| } | ||
|
|
||
| if (testData3 != null) { | ||
| runTimeData = new com.testsigma.sdk.RunTimeData(); | ||
| runTimeData.setKey(testData3.getValue().toString()); | ||
| runTimeData.setValue(runtimeValue.toString().replaceAll(",$", "")); | ||
| } | ||
|
|
||
| setSuccessMessage("Successfully executed all queries.<br>" + successMessage); | ||
| logger.info("====== Oracle DB Multiple Query Execution Completed ======"); | ||
|
|
||
| } catch (Exception e) { | ||
| setErrorMessage(ExceptionUtils.getStackTrace(e)); | ||
| return Result.FAILED; | ||
| } finally { | ||
| try { if (stmt != null) stmt.close(); } catch (Exception ignored) {} | ||
| try { if (connection != null) connection.close(); } catch (Exception ignored) {} | ||
| } | ||
|
|
||
| return result; | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion | 🟠 Major
Significant code duplication across platform actions.
This Android action is nearly identical to the iOS, MobileWeb, and Web variants (files under review). Only the package, base class, and ApplicationType differ. The core logic (lines 38-139) is duplicated 4 times, violating DRY principles and making maintenance error-prone.
💡 Refactor suggestion: Extract common logic
Consider creating a shared utility class or base action:
// New shared utility
public class OracleMultipleQueriesExecutor {
public static Result execute(
TestData queries,
TestData connectionUrl,
TestData variableName,
Logger logger,
Consumer<String> successMessageSetter,
Consumer<String> errorMessageSetter
) {
// Move the entire execute logic here
}
}Then each platform action becomes:
@Override
public Result execute() {
return OracleMultipleQueriesExecutor.execute(
testData1, testData2, testData3,
logger, this::setSuccessMessage, this::setErrorMessage
);
}This reduces duplication from ~140 lines × 4 files to a single shared implementation.
🤖 Prompt for AI Agents
In
@oracledb_queries/src/main/java/com/testsigma/addons/android/OracleMultipleQueriesSelect.java
around lines 1 - 140, The Android action OracleMultipleQueriesSelect duplicates
the same execute logic across platform-specific classes; extract the shared
DB-query/run-time-variable logic into a new utility (e.g.,
OracleMultipleQueriesExecutor) with a static method (e.g., execute(TestData
queries, TestData connectionUrl, TestData variableName, Logger logger,
Consumer<String> setSuccessMessage, Consumer<String> setErrorMessage)) that
contains the core code currently inside OracleMultipleQueriesSelect.execute(),
and update OracleMultipleQueriesSelect.execute() (and the iOS/MobileWeb/Web
action classes) to simply delegate to that utility, passing
testData1/testData2/testData3, logger, this::setSuccessMessage and
this::setErrorMessage so platform classes only differ by their base class and
ApplicationType.
| import com.testsigma.sdk.AndroidAction; | ||
| import com.testsigma.sdk.ApplicationType; | ||
| import com.testsigma.sdk.Result; | ||
| import com.testsigma.sdk.WebAction; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove unused import.
WebAction is imported but never used. This class extends AndroidAction.
🔎 Proposed fix
-import com.testsigma.sdk.WebAction;📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| import com.testsigma.sdk.WebAction; |
🤖 Prompt for AI Agents
In
@oracledb_queries/src/main/java/com/testsigma/addons/android/OracleMultipleQueriesSelect.java
at line 7, Remove the unused import of WebAction in
OracleMultipleQueriesSelect.java: delete the line importing
com.testsigma.sdk.WebAction since the class extends AndroidAction and never
references WebAction (class OracleMultipleQueriesSelect); after removal, rebuild
to ensure no references remain.
| try { | ||
| logger.info("====== Oracle DB Multiple Query Execution Started ======"); | ||
|
|
||
| connection = databaseUtil.getConnection(testData2.getValue().toString()); | ||
| stmt = connection.createStatement(); | ||
|
|
||
| String[] queries = testData1.getValue().toString().split(";"); | ||
| int queryCounter = 1; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add null validation for required inputs.
testData1 and testData2 are accessed without null checks. If either field or their values are null, a NullPointerException will be thrown.
🔎 Recommended fix: Add validation
try {
logger.info("====== Oracle DB Multiple Query Execution Started ======");
+
+ if (testData1 == null || testData1.getValue() == null) {
+ setErrorMessage("Select-Queries parameter is required");
+ return Result.FAILED;
+ }
+ if (testData2 == null || testData2.getValue() == null) {
+ setErrorMessage("DB_Connection_URL parameter is required");
+ return Result.FAILED;
+ }
connection = databaseUtil.getConnection(testData2.getValue().toString());🤖 Prompt for AI Agents
In
@oracledb_queries/src/main/java/com/testsigma/addons/android/OracleMultipleQueriesSelect.java
around lines 49 - 56, The code in OracleMultipleQueriesSelect accesses testData1
and testData2 (and their getValue() results) without null checks and can NPE;
before using them in the method where connection and stmt are created, validate
that testData1, testData2 and their getValue() results are non-null (e.g., in
the start of the execute/run method in OracleMultipleQueriesSelect), and handle
failures by logging a clear error via logger (including which input is missing)
and returning/throwing a controlled exception instead of proceeding to
connection/statement creation; ensure the split(" ;") on
testData1.getValue().toString() only runs after validation.
|
|
||
| connection = databaseUtil.getConnection(testData2.getValue().toString()); | ||
| stmt = connection.createStatement(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add connection and query timeout to prevent hanging.
No timeouts are configured for the database connection or statement execution. If the database is slow or unresponsive, the action could hang indefinitely.
🔎 Recommended fix: Set timeouts
connection = databaseUtil.getConnection(testData2.getValue().toString());
stmt = connection.createStatement();
+stmt.setQueryTimeout(30); // 30 seconds timeout per queryAdditionally, consider configuring connection timeout in DatabaseUtil.getConnection() if not already done.
🤖 Prompt for AI Agents
In
@oracledb_queries/src/main/java/com/testsigma/addons/android/OracleMultipleQueriesSelect.java
around lines 51 - 53, The code in OracleMultipleQueriesSelect.java calls
DatabaseUtil.getConnection(testData2.getValue().toString()) and then creates a
Statement (stmt) without any timeouts; update the code to set a statement/query
timeout (use stmt.setQueryTimeout(seconds) after creating the Statement) and set
a network/connection timeout on the Connection (e.g.,
connection.setNetworkTimeout(...) or ensure DatabaseUtil.getConnection(...)
configures a socket/connection timeout), and if applicable set the driver login
timeout (DriverManager.setLoginTimeout or equivalent) so the action cannot hang
indefinitely while waiting for the DB.
|
|
||
| String[] queries = testData1.getValue().toString().split(";"); | ||
| int queryCounter = 1; | ||
|
|
||
| for (String rawQuery : queries) { | ||
|
|
||
| String query = rawQuery.trim(); | ||
| if (query.isEmpty()) continue; | ||
|
|
||
| logger.info("Executing Query [" + queryCounter + "]: " + query); | ||
|
|
||
| ResultSet rs = stmt.executeQuery(query); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
SQL injection risk: Validate queries are SELECT-only.
User-provided queries are executed without validation. While the action description specifies "SELECT queries," there's no enforcement preventing malicious users from injecting DML/DDL statements (INSERT, UPDATE, DELETE, DROP, etc.).
🔎 Recommended fix: Add query type validation
String[] queries = testData1.getValue().toString().split(";");
int queryCounter = 1;
for (String rawQuery : queries) {
String query = rawQuery.trim();
if (query.isEmpty()) continue;
+
+ // Validate query is SELECT only
+ if (!query.toUpperCase().startsWith("SELECT")) {
+ setErrorMessage("Only SELECT queries are allowed. Query [" + queryCounter + "]: " + query);
+ return Result.FAILED;
+ }
logger.info("Executing Query [" + queryCounter + "]: " + query);🤖 Prompt for AI Agents
In
@oracledb_queries/src/main/java/com/testsigma/addons/android/OracleMultipleQueriesSelect.java
around lines 54 - 65, The loop executing user-supplied SQL in
OracleMultipleQueriesSelect.java (variables: testData1, queries, rawQuery,
query, and the stmt.executeQuery call producing ResultSet rs) must validate each
statement is a read-only SELECT before executing: trim and strip leading
comments, reject any query containing a semicolon or any DDL/DML keywords (e.g.,
INSERT, UPDATE, DELETE, DROP, ALTER, CREATE, TRUNCATE) and require the first
non-whitespace token to match a case-insensitive "SELECT" (e.g., regex like
^\s*(?i)select\b). For invalid queries, log an error or throw an exception and
skip executing it instead of calling stmt.executeQuery; keep the validation
logic adjacent to where rawQuery/query are prepared so no non-SELECT statement
can reach stmt.executeQuery.
|
|
||
| logger.info("Executing Query [" + queryCounter + "]: " + query); | ||
|
|
||
| ResultSet rs = stmt.executeQuery(query); | ||
| ResultSetMetaData rsmd = rs.getMetaData(); | ||
| int columnCount = rsmd.getColumnCount(); | ||
|
|
||
| /* ---------- UI OUTPUT ---------- */ | ||
| successMessage.append("<br><b>Query ") | ||
| .append(queryCounter) | ||
| .append(" Result: ") | ||
| .append(query) | ||
| .append("</b><br>"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Potential PII/sensitive data exposure in logs.
The full query text is logged at line 64 and included in the success message at line 73. If queries contain sensitive data (e.g., WHERE email='[email protected]'), this could violate privacy policies (GDPR, CCPA) and leak PII into logs.
Consider:
- Redacting query parameters in logs
- Logging only query structure/type instead of full text
- Documenting that users should not include sensitive data in queries
🤖 Prompt for AI Agents
In
@oracledb_queries/src/main/java/com/testsigma/addons/android/OracleMultipleQueriesSelect.java
around lines 62 - 74, The code currently logs and displays the full SQL text
(variable query) via logger.info(...) and successMessage.append(...), which may
expose PII; update OracleMultipleQueriesSelect to stop emitting raw query
strings: replace the direct uses of query in logger.info and successMessage with
a sanitized representation (e.g., a helper method sanitizeQuery(String query)
that strips or masks literal values and parameters and/or returns only the query
type and table names), or log only the queryCounter and query type; ensure
successMessage shows the sanitizedQuery or a generic message like "Query N:
SELECT ... (parameters redacted)"; update references to logger.info("Executing
Query [" + queryCounter + "]: " + query) and successMessage.append(...
.append(query) ...) to use the sanitized value and add a short comment in docs
or method javadoc warning users not to include sensitive data in queries.
|
|
||
| ResultSet rs = stmt.executeQuery(query); | ||
| ResultSetMetaData rsmd = rs.getMetaData(); | ||
| int columnCount = rsmd.getColumnCount(); | ||
|
|
||
| /* ---------- UI OUTPUT ---------- */ | ||
| successMessage.append("<br><b>Query ") | ||
| .append(queryCounter) | ||
| .append(" Result: ") | ||
| .append(query) | ||
| .append("</b><br>"); | ||
|
|
||
| /* ---------- LOG OUTPUT ---------- */ | ||
| StringBuilder log = new StringBuilder(); | ||
| log.append("\nQuery ").append(queryCounter) | ||
| .append(" Result: ").append(query).append("\n"); | ||
|
|
||
| log.append("--------------------------------------------------------\n"); | ||
|
|
||
| // Headers | ||
| StringBuilder headerRow = new StringBuilder(); | ||
| for (int i = 1; i <= columnCount; i++) { | ||
| headerRow.append(rsmd.getColumnName(i)); | ||
| if (i < columnCount) headerRow.append(" | "); | ||
| } | ||
| log.append(headerRow).append("\n"); | ||
| log.append("--------------------------------------------------------\n"); | ||
|
|
||
| // UI headers | ||
| for (int i = 1; i <= columnCount; i++) { | ||
| successMessage.append(rsmd.getColumnName(i)).append(" | "); | ||
| } | ||
| successMessage.append("<br>"); | ||
|
|
||
| // Rows | ||
| while (rs.next()) { | ||
| StringBuilder row = new StringBuilder(); | ||
| for (int j = 1; j <= columnCount; j++) { | ||
| String value = rs.getString(j); | ||
| String safe = value == null ? "" : value; | ||
|
|
||
| row.append(safe); | ||
| if (j < columnCount) row.append(" | "); | ||
|
|
||
| successMessage.append(safe).append(" | "); | ||
| runtimeValue.append(safe).append(","); | ||
| } | ||
| log.append(row).append("\n"); | ||
| successMessage.append("<br>"); | ||
| } | ||
|
|
||
| logger.info(log.toString()); | ||
| logger.info("Query [" + queryCounter + "] executed successfully"); | ||
|
|
||
| queryCounter++; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Critical resource leak: ResultSet never closed.
ResultSet objects created at line 65 are never closed, causing resource leaks. Additionally, reusing the same Statement for multiple queries without closing the previous ResultSet can lead to issues.
🔎 Recommended fix: Close ResultSet after each query
for (String rawQuery : queries) {
String query = rawQuery.trim();
if (query.isEmpty()) continue;
logger.info("Executing Query [" + queryCounter + "]: " + query);
- ResultSet rs = stmt.executeQuery(query);
- ResultSetMetaData rsmd = rs.getMetaData();
- int columnCount = rsmd.getColumnCount();
+ ResultSet rs = null;
+ try {
+ rs = stmt.executeQuery(query);
+ ResultSetMetaData rsmd = rs.getMetaData();
+ int columnCount = rsmd.getColumnCount();
- /* ---------- UI OUTPUT ---------- */
- successMessage.append("<br><b>Query ")
- .append(queryCounter)
- .append(" Result: ")
- .append(query)
- .append("</b><br>");
+ /* ---------- UI OUTPUT ---------- */
+ successMessage.append("<br><b>Query ")
+ .append(queryCounter)
+ .append(" Result: ")
+ .append(query)
+ .append("</b><br>");
- /* ---------- LOG OUTPUT ---------- */
- StringBuilder log = new StringBuilder();
- log.append("\nQuery ").append(queryCounter)
- .append(" Result: ").append(query).append("\n");
+ /* ---------- LOG OUTPUT ---------- */
+ StringBuilder log = new StringBuilder();
+ log.append("\nQuery ").append(queryCounter)
+ .append(" Result: ").append(query).append("\n");
- log.append("--------------------------------------------------------\n");
+ log.append("--------------------------------------------------------\n");
- // Headers
- StringBuilder headerRow = new StringBuilder();
- for (int i = 1; i <= columnCount; i++) {
- headerRow.append(rsmd.getColumnName(i));
- if (i < columnCount) headerRow.append(" | ");
- }
- log.append(headerRow).append("\n");
- log.append("--------------------------------------------------------\n");
+ // Headers
+ StringBuilder headerRow = new StringBuilder();
+ for (int i = 1; i <= columnCount; i++) {
+ headerRow.append(rsmd.getColumnName(i));
+ if (i < columnCount) headerRow.append(" | ");
+ }
+ log.append(headerRow).append("\n");
+ log.append("--------------------------------------------------------\n");
- // UI headers
- for (int i = 1; i <= columnCount; i++) {
- successMessage.append(rsmd.getColumnName(i)).append(" | ");
- }
- successMessage.append("<br>");
+ // UI headers
+ for (int i = 1; i <= columnCount; i++) {
+ successMessage.append(rsmd.getColumnName(i)).append(" | ");
+ }
+ successMessage.append("<br>");
- // Rows
- while (rs.next()) {
- StringBuilder row = new StringBuilder();
- for (int j = 1; j <= columnCount; j++) {
- String value = rs.getString(j);
- String safe = value == null ? "" : value;
-
- row.append(safe);
- if (j < columnCount) row.append(" | ");
-
- successMessage.append(safe).append(" | ");
- runtimeValue.append(safe).append(",");
+ // Rows
+ while (rs.next()) {
+ StringBuilder row = new StringBuilder();
+ for (int j = 1; j <= columnCount; j++) {
+ String value = rs.getString(j);
+ String safe = value == null ? "" : value;
+
+ row.append(safe);
+ if (j < columnCount) row.append(" | ");
+
+ successMessage.append(safe).append(" | ");
+ runtimeValue.append(safe).append(",");
+ }
+ log.append(row).append("\n");
+ successMessage.append("<br>");
}
- log.append(row).append("\n");
- successMessage.append("<br>");
- }
- logger.info(log.toString());
- logger.info("Query [" + queryCounter + "] executed successfully");
+ logger.info(log.toString());
+ logger.info("Query [" + queryCounter + "] executed successfully");
+ } finally {
+ try { if (rs != null) rs.close(); } catch (Exception ignored) {}
+ }
queryCounter++;
}🤖 Prompt for AI Agents
In
@oracledb_queries/src/main/java/com/testsigma/addons/android/OracleMultipleQueriesSelect.java
around lines 64 - 119, The ResultSet created by stmt.executeQuery(query) in
OracleMultipleQueriesSelect is never closed, leaking DB resources and risking
issues when reusing the same Statement; fix by ensuring each ResultSet (variable
rs) is closed after processing—preferably wrap the executeQuery/iteration in a
try-with-resources or explicitly call rs.close() in a finally block right after
logging and before incrementing queryCounter, so every loop iteration closes its
ResultSet before the next executeQuery on stmt.
| import com.testsigma.sdk.ApplicationType; | ||
| import com.testsigma.sdk.IOSAction; | ||
| import com.testsigma.sdk.Result; | ||
| import com.testsigma.sdk.WebAction; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove unused imports.
Two imports are unused:
- Line 7:
WebAction(class extendsIOSAction) - Line 14:
org.openqa.selenium.devtools.v135.io.IO(never referenced)
🔎 Proposed fix
-import com.testsigma.sdk.WebAction;
import com.testsigma.sdk.annotation.Action;
import com.testsigma.sdk.annotation.RunTimeData;
import com.testsigma.sdk.annotation.TestData;
import lombok.Data;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.openqa.selenium.NoSuchElementException;
-import org.openqa.selenium.devtools.v135.io.IO;
import java.sql.*;Also applies to: 14-14
🤖 Prompt for AI Agents
In
@oracledb_queries/src/main/java/com/testsigma/addons/ios/OracleMultipleQueriesSelect.java
at line 7, Remove the unused imports in OracleMultipleQueriesSelect.java: delete
the import of com.testsigma.sdk.WebAction and the import of
org.openqa.selenium.devtools.v135.io.IO since the class extends IOSAction and
neither symbol is referenced; ensure only required imports remain and run a
quick compile or IDE optimize imports to confirm no other unused imports exist.
Publish this addon as public
Addon Name: OracleDB_Queries
Jarvis Link: https://jarvis.testsigma.com/ui/tenants/2817/addons
Jira : https://testsigma.atlassian.net/browse/CUS-9809
Added class to execute multiple queries at a time in oracle db
Summary by CodeRabbit
✏️ Tip: You can customize this high-level summary in your review settings.