google-cloud-platformgoogle-cloud-spannergoogle-cloud-spanner-emulator

Cloud Spanner DB - Unable to read timestamp from ReadOnlyTransaction.getReadTimestamp()


I was trying to use ReadOnlyTransaction.getReadTimestamp() function but I keep running into exception: "Method can only be called after read has returned data or finished" I have returned one or two records from DB, but I can't read timestamp. Below is sample code how and what I am doing.

IO {
  val db    = spannerClientInstance
  val rotxn = db.singleUseReadOnlyTransaction()

  val sql = "SELECT " +
    "Name " +
    "FROM Person " +
    "WHERE Name= @Name"

  val resultSet = db.singleUse.executeQuery(
    Statement.newBuilder(sql).bind("Name").to(name).build()
  )

  (resultSet, rotxn)
}.bracket {
  case (resultSet, rotxn) =>
    IO {
      val result =
        scala.collection.mutable.Map.empty[String, Person]

      while (resultSet.next()) {
        result += (resultSet.getString(0) -> new Person(resultSet.getString(0)))
      }

      (result.toMap, rotxn.getReadTimestamp)
    }
} {
  case (resultSet, _) =>
    IO(resultSet.close())
}

I tried closing resultSet and/or rotxn with resultSet.close() and rotxn.close() and then calling rotxn.getReadTimestamp(), but didn't have much luck. I got the same error message.

I am using Spanner Java lib: com.google.cloud:google-cloud-spanner:2.0.1 Tried googling the issue but didn't find much. Any help is welcomed :)

Thanks. :)


Solution

  • It seems that you are not actually executing the query on the read-only transaction that you started. The code that is executing the query is:

      val resultSet = db.singleUse.executeQuery(
        Statement.newBuilder(sql).bind("Name").to(name).build()
      )
    

    That query is using a single-use read-only transaction, and not your previously read-only transaction. Try executing it like this instead:

      val resultSet = rotxn.executeQuery(
        Statement.newBuilder(sql).bind("Name").to(name).build()
      )