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

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. :)

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()
)

Related

c++ MySql Connector Query always returns true even if errored

I am using MySql C++ Connector latest build in a c++ app
But every query i make to any table it returns true
E.x. code :
string MyQueryTest(){
string returnValue;
try{
stmt->execute("UPDATE testtbl SET Name = 'Test' WHERE id = '2'");
}
catch(SQLException e){
returnValue = "false";
}
returnValue = "true";
return returnValue;
}
string MyValue = MyQueryTest();
The above code return true though in my testtbl there is no id = 2 data, i have only one data entered which is id = 1 Name = MyTests
Does anyone knows any solutions around this ?
I have tried to place the returnValue = "true" inside the try statement,
also i used exit(1) function inside catch error function
None got me the desired returnValue to false which is the correct return of the above code
It's not an exceptional case when there is no data to be updated. SQLException will be thrown if you have problems with connection to Database or SQL query syntax is incorrect.
Statement class has executeUpdate() method that returns number of affected rows, you can use it to achieve your aim.

MySQL call procedure with output parameter from C++ mysqlpp

I need help with the C++ mysqlpp driver calling a stored procedure and retrieving its output parameter. The queries seem to pass successfully but trying to get the stored value causes segmentation fault. My current pseudo code is:
mysqlpp::Connection* connection; // the connection type I am bound to use, no createStatement, prepareStatement methods
Query query = connection->query();
Query transactionQuery = connection->query();
query << "CALL sp_get_transactions_count(" << inputId << ", #transactionsCount);";
transactionQuery << "SELECT #transactionsCount as combinations;";
ClearQuerySentry cleanUpQuery(transactionQuery);
query.exec();
mysqlpp::StoreQueryResult transactionsResult = transactionQuery.store();
if (!transactionsResult || transactionsResult.num_rows() == 0)
{
logWarning(....);
}
else
{
const mysqlpp::Row& transactionRecord = result[0];
environment.pairTransactionsCount = verboseLexicalCast<int>(transactionRecord, "combinations"); // segfault on trying to cast static_cast<const char*>(row[fieldName.c_str()]))
}
I am not very experienced with mysqlpp and MySQL as a whole so it is possible my perception of the solution to be wrong. Thanks in advance.

Execute PL/SQL script in C++ using OCCI oracle

I want to run SQL script from a C++ program. my code goes like this:
int main()
{
//.....
sql_stmt = "Insert into t1 values ('qwerty');\nInsert into t1 values ('dothar');"
"//and many more INSERT statements";
sql_stmt = "DECLARE\nrollback_check_counter number;\n"
"BEGIN\n"
"rollback_check_counter :=1;\n"
"SAVEPOINT sp_1;\nIF rollback_check_counter = 1 THEN\n"
"BEGIN\n"+sql_stmt+"EXCEPTION\n"
"WHEN PROGRAM_ERROR THEN\n"
"rollback_check_counter :=0;\n"
"ROLLBACK TO sp_1;\n"
"WHEN OTHERS THEN\n"
"rollback_check_counter :=0;\n"
"ROLLBACK TO sp_1;\n"
"END;\n"
"END IF;\n"
"commit;\n"
"END;";
try
{
Connection *conn = env->createConnection(user,passwd); //error prone
Statement *stmt = conn->createStatement();
stmt->setSQL(sql_stmt);
row_count = stmt->execute(); //stmt->execute(sql_stmt);
Connection::conn->terminateStatement(Statement *stmt);
//con->terminateStatement(stmt);
env->terminateConnection(conn);
Environment::terminateEnvironment(env);
}
catch(SQLException& ex)
{}
//.....
return 0;
}
Although when i run these insert statement only they fairly run well but when i forms a SQL Script structure they seems to fail. I want to do so because i want to implement rollback. What am i missing? Could anyone suggest any alternative to implement it.
There are ; missing after both ROLLBACK TO sp_1

WMI performance query

I am having an issue with a WMI query.
I use a WMI query to search and resume an instance in BizTalk.
When there are not that many instances (so when the data isn't that much) the query performs pretty good.
But when the data is large (about 3000 instances) the query takes about 6 - 10 seconds to execute, and this isn't tolerable.
Code is as following:
string query = "SELECT * FROM MSBTS_ServiceInstance WHERE InstanceID = \"" + OrchestrationId + "\"";
ManagementObjectSearcher searcher = new ManagementObjectSearcher(new ManagementScope(#"root\MicrosoftBizTalkServer"), new WqlObjectQuery(query), null);
int count = searcher.Get().Count;
if (count > 0)
{
string[] strArray = new string[count];
string[] strArray2 = new string[count];
string[] strArray3 = new string[count];
string str2 = string.Empty;
string str3 = string.Empty;
int index = 0;
foreach (ManagementObject obj2 in searcher.Get())
{
if (str2 == string.Empty)
{
str2 = obj2["HostName"].ToString();
}
strArray2[index] = obj2["ServiceClassId"].ToString();
strArray3[index] = obj2["ServiceTypeId"].ToString();
strArray[index] = obj2["InstanceID"].ToString();
str3 = str3 + string.Format(" {0}\n", obj2["InstanceID"].ToString());
index++;
}
new ManagementObject(string.Format("root\\MicrosoftBizTalkServer:MSBTS_HostQueue.HostName=\"{0}\"", str2)).InvokeMethod("ResumeServiceInstancesByID", new object[] { strArray2, strArray3, strArray, 1 });
It's the first query (Select * from MSBS_ServiceInstance..) that takes to long when te data is getting bigger.
Any ideas how I can improve this?
The platform is Windows Server 2008 Enterprise..
Thx!
It looks like you are getting all service instances for your orchestration, not just the suspended ones.
Try adding the following to your query's where clause, so that only suspended and suspended-not-resumable service instances are returned:
and (ServiceStatus = 4 or ServiceStatus = 16)
Thank you for the replies.
The reason I got that many suspended instances sometimes is by design.
Whenever a message isn't in sequence, the orchestration gets suspended until the previous message went through.
I found another way to resume the instances using the BizTalkOperations class that is installed with BizTalk:
BizTalkOperations operations = new BizTalkOperations(dataSource, initialCatalog);
foreach (Guid id in instanceIds)
{
operations.ResumeInstance(id);
}
This code is much more performant then the WMI code (and less code ^^) :)
Thanks

How to use transactions in Informix CSDK and OIC++

I'd need some advice how to handle transactions with Informix CSDK and OIC++.
conn is a open connection object. Select works find. The database here is setup with logging — as I found out while update stmt on its own does nothing.
Here's what I tried:
conn.SetTransaction( ITConnection::BEGIN );
qtext = "UPDATE transit_kunde_s SET erledigt='Y' WHERE transitkunde='"+ts+"'";
cout << qtext << endl;
code = query_up.ExecForStatus(qtext.c_str());
cout << "code " << code << endl;
conn.SetTransaction( ITConnection::COMMIT );
okay once again I answer myself...
from Informix C++ DocNotes
Operations can now be performed on large objects within a fetched row even though the connection is still checked out (locked). A connection is checked out after the ITQuery::ExecForIteration() method returns multiple rows in the result set. It remains checked out until either the last row in the result set has been fetched with ITQuery::NextRow() or the query processing has been terminated by calling ITQuery::Finish(). While a connection is checked out, no other query can be executed on that connection.
So as I am in the while loop of one query result iteration I need for another update query a new connection
// already have 2 connection objects: conn, conn2
ITQuery query(conn);
ITQuery query_up(conn2);
string qtext;
qtext = "SELECT * FROM transit_kunde_s WHERE erledigt='N' ORDER BY transitkunde";
okay = query.ExecForIteration(qtext.c_str());
while (row = query.NextRow()) {
// do stuff
// NOW WANT TO DO ANOTHER QUERY? --> NEED ANOTHER CONNECTION!!
ok_ta = conn2.SetTransaction( ITConnection::BEGIN);
qtext = "UPDATE transit_kunde_s SET erledigt='Y' WHERE transitkunde='"+ts+"'";
code = query_up.ExecForStatus(qtext.c_str());
ok_ta = conn2.SetTransaction( ITConnection::COMMIT );
}
// we see later the 1st query to be finished here
query.Finish();