I am trying to use ADO to do some queries in C++. Here is my code
string commandline = "SELECT * FROM My_Table";
ADODB::_RecordsetPtr pRS("ADODB.Recordset");
ADODB::_ConnectionPtr pConn("ADODB.Connection");
pRS->Open(commandline.c_str(), _variant_t((IDispatch *) pConn, true), ADODB::adOpenUnspecified, ADODB::adLockUnspecified, ADODB::adCmdText);
cout<<pRS->GetRecordCount();
I have 1000 records in My_Table, thus I expect to see output 1000. However, the output is -1.
May I know what am I wrong?
Many thanks in advance.
The RecourdCount property works only if the underlying provider or cursor type actually support it, otherwise -1 is returned.
Try using a static cursor (passing ADODB::adOpenStatic instead of ADODB::adOpenUnspecified)
Please also note that even when the provider supports it, getting the record count may use a lot of resources because the provider has to fetch all records prior to knowing the number of records affected by the query.
Refer to this MSDN page for detailed documentation.
Related
I have below query criteria to fetch State based on linearId. I am trying below code
//query criteria
QueryCriteria queryCriteria = new LinearStateQueryCriteria(
null,
ImmutableList.of(UUID.fromString(linearId))
);
However, I am getting a compile time error asking to change QueryCriteria to QueryCriteria.LinearStateQueryCriteria. If I do that, then vaultService.queryBy() does not accept the queryCriteria and throws a compile time error.
As per documentation, API: Vault Query - Custom queries in Java it should have worked. Can someone help ?
glad to see you figured it out, even though I'm not sure why IJ would flag the wrong error. In any event, here's my go-to code sample of making a query on a linear state.
link attached:
https://github.com/corda/samples-java/blob/master/Advanced/obligation-cordapp/workflows/src/main/java/net/corda/samples/obligation/flows/IOUSettleFlow.java#L57-L62
I am currently attempting to use transactions in my C++ app, but I have a problem with the ODBC's auto commit mode.
I am using the POCO libaries to create a connection to a PostgreSQL database on the same machine. Currently, I can send data to this database as single statements, but I cannot get my head around how to use Poco's transaction libraries to be able to send this data more quickly.
As I have several thousand records to insert, and so continuing to use single insert statements is extrememly slow and inpractical - So I am trying to use Poco's transaction to speed this up a bit (a fair bit).
The error I am encountering is a theoretically a simple one - Poco is throwing the following error:
'Invalid access: Session is in auto commit mode.'
I understand, as a result of this, I should somehow set "auto commit" to false - as it only allows me to commit data to the database line by line, rather than as a single transaction.
The problem is how I set this.
Currently, I have a session created from Session.h, that looks alot like this:
session = new Poco::Data::Session(
"ODBC",
connection_data.str()
);
Where connection data is a simple stringstream with the login information, password, database, server and "Driver={PostgreSQL ANSI};" to tell ODBC to utilize PostgreSQL's driver.
I have tried just setting a property "autocommit" to false through the session's setFeature or setProperty settings, this, of course, was to no avail. (it was more of a ditch attempt at this point).
session->setFeature("AUTOCOMMIT", false);
Looking around, I saw a possible alternative method by creating a ODBC sessionImpl directly from ODBC/session/SessionImpl.h instead of using this generic method above, and then creating a new session object from this.
The benefits of this are that ODBC's sessionImpl has references to autocommit mode in the header, which would suggest it would be able to handle this:
void autoCommit(const std::string&, bool val);
/// Sets autocommit property for the session.
However, having not used sessionImpl before, I cannot garuntee if this will work or if can can get this to work with the limited documentation available.
I am using C++ 03 (Not 11), with Visual Studio 2015
Poco 1.7.5
Boost (Where needed)
Would any one know the correct way of setting this feature (above) or a alternative method to achieving this?
edit: Looking at the source of poco, at:
https://github.com/pocoproject/poco/blob/develop/Data/ODBC/src/SessionImpl.cpp#L153
The property seems be named autoCommit, and looking at
https://github.com/pocoproject/poco/blob/develop/Data/include/Poco/Data/AbstractSessionImpl.h#L120
the case of the property names seem to matter. So, does it help if you use session->setFeature("autoCommit", false);?
Cant you just call session->begin(); and session->end(); on the corresponding Session object?
What is returned by session->canTransact()?
According to the doc begin() will start a new transaction, the doc does not mention any property that needs to be set before or after.
See: https://pocoproject.org/docs/Poco.Data.Session.html
Also faced a similar issue.
First of all before begin() need:
m_ses.setFeature("autoCommit", false);
m_ses.begin();
And the second issue is that this feature stays "autoCommit" in false for all other sessions. So don't forget for the next session call
session.setFeature("autoCommit", true);
I need to intercept my loopback queries before they query my Mongodb to add additional filters, for example, to limit the object to what the user has access to.
I can successfully update the query on access operation hook to add filters to the GET /Applications , where Applications is my object. However This fails to work for GET /Applications/count
The command runs with a 200, however it returns zero results, even though I'm adding the exact same filters. There most be something different about count that I'm missing. The ctx object looks have a ton of functions/objects in it. I'm only touching the query property, but there must be something else I need to do.
Any ideas? Thank you, Dan
Could you please share your access hook observer's implementation. I tried it on a sample app, and following access hook works as expected for /api/Books/count:
module.exports = function(Book) {
Book.observe('access', function logQuery(ctx, next) {
ctx.query.where.id = 2; // changing filter value for where
console.log('Accessing %s matching %j', ctx.Model.modelName, ctx.query.where);
next();
});
};
Verify that you're modifying query property of Context (see access hook).
Hope that helps.
I have BitLocker enabled on my machine and I want to use the wbemtest.exe utility to view properties about the Bitlocker data.
According to the properties section at MSDN, some of the data that I want to retrieve are DeviceID, DriveLetter, PersistentVolumeID, and ProtectionStatus.
However, when I execute the query
SELECT * from Win32_EncryptableVolume
using wbemtest.exe, only one object gets returned, and that is BitLocker DeviceID. I also want this query to return the DriveLetter and the other properties. What do I do to retrieve these? The data should be there, because my C# app using System.Management is able to get data on the other properties without any trouble (by assigning the return value of a ManagementClass GetInstances() method to a a ManagementObjectCollection.)
It turns out that I am able to view the data I need quite simply by using the WMI Code Creator utility.
I found this information on windows-noob
It seems that c++ drivers doesn't accept mongodb connection uri format.
There's no documentation on how i should create connection string, any guess?
I need to connect to a replica set with 3 servers, and set readPreference options.
Create a connection to a replica set in MongoDB C++ client
Until the problems explained in #acm's answer are resolved, I have found a workaround to the bad Connection Strings of the C++ driver. You can create a DBClientReplicaSet using a vector of hosts and ports this way:
//First create a vector of hosts
//( you can ignore port numbers if yours are default)
vector<HostAndPort> hosts;
hosts.push_back(mongo::HostAndPort("YourHost1.com:portNumber1"));
hosts.push_back(mongo::HostAndPort("YourHost2.com:portNumber2"));
hosts.push_back(mongo::HostAndPort("YourHost3.com:portNumber3"));
//Then create a Replica Set DB Client:
mongo::DBClientReplicaSet connection("YourReplicaSetName",hosts,0);
//Connect to it now:
connection.connect();
//Authenticate to the database(s) if needed
std::string errmsg;
connection.auth("DB1Name","UserForDB1","pass1",errmsg);
connection.auth("DB2Name","UserForDB2","pass2",errmsg);
Now, you can use insert, update, etc. just as you did with DBClientConnection. For a quick fix, you can replace your references to DBClientConnection with DBClientBase (which is a parent to both DBClientConnection and DBClientReplicaSet)
Last pitfall: if you are using getLastError(), you must use it with the aimed database name like this:
connection.getLastError(std::string("DBName"));
cause otherwise it will always return "command failed: must log in" as described in this JIRA ticket.
Set the read preferences for every request
You have two ways to do that:
SlaveOK option
It lets your read queries be directed to secondary servers.
It takes place in the query options, which are at the end of the parameters of DBClientReplicaSet.query(). The options are listed in Mongo's official documentation
The one you would look for is mongo::QueryOption_SlaveOk, which will allow you to have reads made on secondary instances.
This is how you should call query();
connection.query("Database.Collection",
QUERY("_id" << id),
n,
m,
BSON("SomeField" << 1),
QueryOption_SlaveOk);
where n is the number of documents to return (0 if you don't want any limit), m the number to skip (defaults to 0), the next field is your projection and the last your query option.
To use several query option, you can use bitwise or | like this :
connection.query("Database.Collection",
QUERY("_id" << id),
n,
m,
BSON("SomeField" << 1),
QueryOption_SlaveOk | QueryOption_NoCursorTimeout | QueryOption_Exhaust);
Query::readPref option
The Query object has a readPref method which sets read preferences for a special query. It should be called for each query.
You can pass different arguments for more control. They are listed here.
So here's what you should do (I did not test that one cause I can't right now but it should work just fine)
/* you should pass an array for the tags. Not sure if this is required.
Anyway, let's create an empty array using the builder. */
BSONArrayBuilder bab;
/* if any, add your tags here */
connection.query("Database.Collection",
QUERY("_id" << id).readPref(ReadPreference_SecondaryPreferred, bab.arr()),
n,
m,
BSON("SomeField" << 1),
QueryOption_NoCursorTimeout | QueryOption_Exhaust);
Note: if any readPref option is used, it should override the slaveOk option.
Hope this helped.
Please see the connection string documentation for details on the connection string format.
(code links below are to 2.2.3 files)
To use a connection string with the C++ driver, you should use the ConnectionString class. You first call the ConnectionString::parse static method with a connection string to obtain a ConnectionString object. You then call ConnectionString::connect to obtain a DBClientBase object which you can then use to send queries.
As for read preference, at the moment I do not see a way to set the read preference in the connection string for the C++ driver, which would preclude a per-connection setting.
However, the implementation of DBClientBase returned by calling ConnectionString::parse with a string that identifies a replica set will return you an instance of DBClientReplicaSet. That class honors $readPreference in queries, so you can set your read preference on a per-query basis.
Since the current C++ drivers still do not accept the standard mongodb connection URIs, I've opened a ticket:
https://jira.mongodb.org/browse/CXX-2
Please vote for it to help get this fixed.
it seems like you can set read Preference before send a read request by call "readPref" method of your Query object. I'v not found a way to set read Preference on mongo collection object yet.