Skip to content

Compatibility Issues with Oracle SQL for Voter Benchmark #338

Closed
@AshishVirdi

Description

@AshishVirdi

Issue 1 : Description:

While creating Database for Voter Benchmark in Oracle Database 19c/23c, since bigint datatype is not natively supported by Oracle sql, the following error occurs :

[INFO ] 2023-07-13 01:27:58,225 [main]  com.oltpbenchmark.DBWorkload main (181) - ======================================================================
[INFO ] 2023-07-13 01:27:58,293 [main]  com.oltpbenchmark.DBWorkload main (406) - Creating new VOTER database...
[ERROR] 2023-07-13 01:28:06,440 [main]  com.oltpbenchmark.DBWorkload main (411) - Unexpected error when creating benchmark database tables.
java.sql.SQLSyntaxErrorException: ORA-00902: invalid datatype

	at oracle.jdbc.driver.T4CTTIoer11.processError(T4CTTIoer11.java:629)
	at oracle.jdbc.driver.T4CTTIoer11.processError(T4CTTIoer11.java:563)
	at oracle.jdbc.driver.T4C8Oall.processError(T4C8Oall.java:1230)
	at oracle.jdbc.driver.T4CTTIfun.receive(T4CTTIfun.java:771)
	at oracle.jdbc.driver.T4CTTIfun.doRPC(T4CTTIfun.java:298)
	at oracle.jdbc.driver.T4C8Oall.doOALL(T4C8Oall.java:511)
	at oracle.jdbc.driver.T4CStatement.doOall8(T4CStatement.java:122)
	at oracle.jdbc.driver.T4CStatement.executeForRows(T4CStatement.java:1199)
	at oracle.jdbc.driver.OracleStatement.executeSQLStatement(OracleStatement.java:1819)
	at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:1471)
	at oracle.jdbc.driver.OracleStatement.executeInternal(OracleStatement.java:2504)
	at oracle.jdbc.driver.OracleStatement.execute(OracleStatement.java:2459)
	at oracle.jdbc.driver.OracleStatementWrapper.execute(OracleStatementWrapper.java:327)
	at com.oltpbenchmark.util.ScriptRunner.runScript(ScriptRunner.java:125)
	at com.oltpbenchmark.util.ScriptRunner.runScript(ScriptRunner.java:82)
	at com.oltpbenchmark.util.ScriptRunner.runScript(ScriptRunner.java:71)
	at com.oltpbenchmark.api.BenchmarkModule.createDatabase(BenchmarkModule.java:234)
	at com.oltpbenchmark.api.BenchmarkModule.createDatabase(BenchmarkModule.java:213)
	at com.oltpbenchmark.DBWorkload.runCreator(DBWorkload.java:628)
	at com.oltpbenchmark.DBWorkload.main(DBWorkload.java:407)
Caused by: Error : 902, Position : 42, Sql = CREATE TABLE VOTES (   vote_id            bigint     NOT NULL,   phone_number       bigint     NOT NULL,   state              varchar(2) NOT NULL,   contestant_number  integer    NOT NULL REFERENCES CONTESTANTS (contestant_number),   created            timestamp  NOT NULL ), OriginalSql = CREATE TABLE VOTES (   vote_id            bigint     NOT NULL,   phone_number       bigint     NOT NULL,   state              varchar(2) NOT NULL,   contestant_number  integer    NOT NULL REFERENCES CONTESTANTS (contestant_number),   created            timestamp  NOT NULL ), Error Msg = ORA-00902: invalid datatype

Description:

We add a new oracle specific sql file i.e. benchmarks/voter/ddl-oracle.sql as it's not already present. Here phone_number will not exceed 10 digits so we are using NUMBER(11, 0) and for vote_id we use NUMBER(19, 0), since its range is considered to be equivalent to that of bigint. (For Oracle Sql)

-- Before changes
-- votes table holds every valid vote.
--   voters are not allowed to submit more than <x> votes, x is passed to client application
CREATE TABLE VOTES
(
  vote_id            bigint     NOT NULL,
  phone_number       bigint     NOT NULL,
  state              varchar(2) NOT NULL,
  contestant_number  integer    NOT NULL REFERENCES CONTESTANTS (contestant_number),
  created            timestamp  NOT NULL
);
CREATE INDEX idx_votes_phone_number ON VOTES (phone_number);

-- After changes (new file - ddl-oracle.sql)
-- votes table holds every valid vote.
--   voters are not allowed to submit more than <x> votes, x is passed to client application
CREATE TABLE VOTES
(
  vote_id            NUMBER(19, 0)     NOT NULL,
  phone_number       NUMBER(11, 0)     NOT NULL,
  state              varchar(2) NOT NULL,
  contestant_number  integer    NOT NULL REFERENCES CONTESTANTS (contestant_number),
  created            timestamp  NOT NULL
);
CREATE INDEX idx_votes_phone_number ON VOTES (phone_number);

Issue 2 : Description:

Create step works fine following the above resolution. But at the execute step, the following error is displayed repeatedly. This is because NOW() function is not available in Oracle sql and therefore we use SYSTIMESTAMP which is an equivalent for NOW() and this ensures that all errors are resolved and proper timestamps are stored in the votes table.

[INFO ] 2023-07-13 01:31:35,716 [main]  com.oltpbenchmark.DBWorkload main (181) - ======================================================================
[INFO ] 2023-07-13 01:31:46,743 [main]  com.oltpbenchmark.DBWorkload runWorkload (640) - Creating 10 virtual terminals...
[INFO ] 2023-07-13 01:32:19,465 [main]  com.oltpbenchmark.DBWorkload runWorkload (644) - Launching the VOTER Benchmark with 1 Phase...
[INFO ] 2023-07-13 01:32:19,476 [main]  com.oltpbenchmark.ThreadBench runRateLimitedMultiPhase (128) - PHASE START :: [Workload=VOTER] [Serial=false] [Time=300] [WarmupTime=0] [Rate=10000] [Arrival=REGULAR] [Ratios=[100.0]] [ActiveWorkers=10]
[INFO ] 2023-07-13 01:32:19,483 [main]  com.oltpbenchmark.ThreadBench runRateLimitedMultiPhase (280) - MEASURE :: Warmup complete, starting measurements.
[WARN ] 2023-07-13 01:32:21,624 [VoterWorker<000>]  com.oltpbenchmark.api.Worker doWork (449) - SQLException occurred during [com.oltpbenchmark.benchmarks.voter.procedures.Vote/01] and will not be retried... sql state [42000], error code [904].
java.sql.SQLSyntaxErrorException: ORA-00904: "NOW": invalid identifier

	at oracle.jdbc.driver.T4CTTIoer11.processError(T4CTTIoer11.java:629)
	at oracle.jdbc.driver.T4CTTIoer11.processError(T4CTTIoer11.java:563)
	at oracle.jdbc.driver.T4C8Oall.processError(T4C8Oall.java:1230)
	at oracle.jdbc.driver.T4CTTIfun.receive(T4CTTIfun.java:771)
	at oracle.jdbc.driver.T4CTTIfun.doRPC(T4CTTIfun.java:298)
	at oracle.jdbc.driver.T4C8Oall.doOALL(T4C8Oall.java:511)
	at oracle.jdbc.driver.T4CPreparedStatement.doOall8(T4CPreparedStatement.java:162)
	at oracle.jdbc.driver.T4CPreparedStatement.executeForRows(T4CPreparedStatement.java:1240)
	at oracle.jdbc.driver.OracleStatement.executeSQLStatement(OracleStatement.java:1819)
	at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:1471)
	at oracle.jdbc.driver.OraclePreparedStatement.executeInternal(OraclePreparedStatement.java:3760)
	at oracle.jdbc.driver.OraclePreparedStatement.execute(OraclePreparedStatement.java:4135)
	at oracle.jdbc.driver.OraclePreparedStatementWrapper.execute(OraclePreparedStatementWrapper.java:1013)
	at com.oltpbenchmark.benchmarks.voter.procedures.Vote.run(Vote.java:129)
	at com.oltpbenchmark.benchmarks.voter.VoterWorker.executeWork(VoterWorker.java:46)
	at com.oltpbenchmark.api.Worker.doWork(Worker.java:416)
	at com.oltpbenchmark.api.Worker.run(Worker.java:282)
	at java.base/java.lang.Thread.run(Thread.java:833)
Caused by: Error : 904, Position : 105, Sql = INSERT INTO votes (vote_id, phone_number, state, contestant_number, created) VALUES (:1 , :2 , :3 , :4 , NOW()), OriginalSql = INSERT INTO votes (vote_id, phone_number, state, contestant_number, created) VALUES (?, ?, ?, ?, NOW()), Error Msg = ORA-00904: "NOW": invalid identifier

Description:

We create a dialect file i.e. benchmarks/voter/dialect-oracle.xml which is used to execute the corrected insertVoteStmt statement with SYSTIMESTAMP.

<?xml version="1.0"?>
<dialects>
    <dialect type="ORACLE">
        <procedure name="Vote">
            <statement name="insertVoteStmt">
                INSERT INTO votes (vote_id, phone_number, state, contestant_number, created) VALUES (?, ?, ?, ?, SYSTIMESTAMP)
            </statement>
        </procedure>
    </dialect>
</dialects>

Also remove semi-colons from all the statements inside SQLStmt() in Vote.java.
Otherwise we get this : Error Msg = ORA-00933: unexpected token at or near

-- After changes
public final SQLStmt checkContestantStmt = new SQLStmt(
          "SELECT contestant_number FROM " + TABLENAME_CONTESTANTS + " WHERE contestant_number = ?"
  );
  // Checks if the voter has exceeded their allowed number of votes
  public final SQLStmt checkVoterStmt = new SQLStmt(
          "SELECT COUNT(*) FROM " + TABLENAME_VOTES + " WHERE phone_number = ?"
  );
  // Checks an area code to retrieve the corresponding state
  public final SQLStmt checkStateStmt = new SQLStmt(
          "SELECT state FROM " + TABLENAME_LOCATIONS + " WHERE area_code = ?"
  );
  // Records a vote
  public final SQLStmt insertVoteStmt = new SQLStmt(
          "INSERT INTO " + TABLENAME_VOTES + " (vote_id, phone_number, state, contestant_number, created) " +
                  "VALUES (?, ?, ?, ?, NOW())"
  );

Metadata

Metadata

Assignees

Labels

bugSomething isn't workingdbms-fixenhancementNew feature or request

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions