I have a table with multiple VARCHAR2(n) columns ('n' differs for each column). I access the table from a C++ application via OCCI library. Is there a way to get this limit value (n) for a column using the OCCI library?
That can be done using MetaData. Here is the sample:
MetaData metaData = connection->getMetaData((utext*)L"\"TableName\"", MetaData::PTYPE_TABLE);
vector<MetaData> metaDataVector = metaData.getVector(MetaData::ATTR_LIST_COLUMNS);
for (UINT i = 0; i < (UINT)metaDataVector.size(); i++)
{
if(metaDataVector[i].getInt(MetaData::ATTR_DATA_TYPE) == OCCI_SQLT_CHR)
columnInfo.size = metaDataVector[i].getInt(MetaData::ATTR_DATA_SIZE);
}
Related
I am executing a database (PostgreSQL) query.
Сomment column has "text" data type.
SELECT Comment FROM table WHERE id = 1;
RecordSet result = query->execute("");
bool more = result .moveFirst();
while (more)
{
std::string comment = result["Comment"].convert<std::string>());
or
std::string comment = result["Comment"].extract<std::string>());
more = result.moveNext();
}
I get an exception
Poco::SQL::UnknownTypeException
How can I read a field without changing the database data type?
I figured out
Poco::SQL::MetaColumn::ColumnDataType type = result.columnType("Comment");
type is Poco::SQL::MetaColumn::ColumnDataType::FDT_CLOB
Poco::SQL::CLOB comment = response["Comment"].extract<Poco::SQL::CLOB>();
Look the same https://github.com/pocoproject/poco/issues/2566 if POCO version < 1.9.1
I have a method (from a third party lib)
bool READ_DB(Connection* con, long value);
void TAMLTradeProcessor::CreateThreads() {
long nThreads = 15; // we can configure this
// set up and run the threads
HANDLE* pWaitHandles = new HANDLE[nThreads];
CThreadInfoData* pTid = new CThreadInfoData[nThreads];
UINT nRunningThreads = 0;
long lSharedIndex = -1;
// Initialise data blocks
int i;
for (i = 0; i < nThreads; i++)
{
pTid[i].m_bRunning = true;
pTid[i].m_pnCurrentIndexPosition = &lSharedIndex; // common index
pTid[i].m_pDbConn = new CDatabaseConnection();
pTid[i].m_hThread = (HANDLE )_beginthreadex(NULL,0,ThreadCB,&pTid[i],0,&pTid[i].m_nThreadId);
...
}
It reads data off the database using the connection I pass in and matching the query for that specific value.
I have a huge list of values so I created multiple threads that retrieves values off the list and call the method, in other word I am retrieving the data in parallel using mutiple DB connection.
ThreadCB will call READ_DB.
At the moment I have created the threads myself and I have created 15 of them...just a casual number.
Is there a better way of doing this using Windows ThreadPool API?
In other words if I need to run the same DB query over and over gain for different values (but I can only use one value at time) what is the best approach?
I'm able to generate the facet and bind the result in Linkbutton within repeater control. Now I'm facing problem in generating the facet query with OR operator when the user selects more than 1 value of same facet type in Sitecore 7.
What can be done to solve it?
Thanks
Here's a blog post about solving this using PredicateBuilder with a specific code example:
http://www.nttdatasitecore.com/en/Blog/2013/November/Building-Facet-Queries-with-PredicateBuilder.aspx
To implement the Facet search in Sitecore use PredicateBuilder class to build the filter query and then add the filter query to the base query. Code is mentioned below:
List<PeopleFields> objPeoplefields = new List<PeopleFields>();
IQueryable<PeopleFields> Query = null;
var predicatePractice = Sitecore.ContentSearch.Utilities.PredicateBuilder.False<PeopleFields>();
var predicateOffice = Sitecore.ContentSearch.Utilities.PredicateBuilder.False<PeopleFields>();
using (var context = ContentSearchManager.GetIndex(SITECORE_WEB_INDEX).CreateSearchContext())
{
//Base query
Query = context.GetQueryable<PeopleFields>().Where(i => i.FirstName.StartsWith(txtFirstName.Text)).Where(i => i.LastName.StartsWith(txtLastName.Text));
foreach (string strselecteFacet in lstPracticefacetSelected)
{
//filter query
predicatePractice = predicatePractice.Or(x => x.Practice.Like(strselecteFacet));
}
foreach (string strselecteFacet in lstOfficefacetSelected)
{
//Filter query
predicateOffice = predicateOffice.Or(x => x.Office.Like(strselecteFacet));
}
//Joining the filter query alongwith base query
if (lstPracticefacetSelected.Count > 0 && lstOfficefacetSelected.Count > 0)
Query = Query.Filter(predicatePractice).Filter(predicateOffice);
else if (lstPracticefacetSelected.Count > 0 && lstOfficefacetSelected.Count == 0)
Query = Query.Filter(predicatePractice);
else if (lstPracticefacetSelected.Count == 0 && lstOfficefacetSelected.Count > 0)
Query = Query.Filter(predicateOffice);
objPeoplefields = Query.ToList();
}
As a quick way, if you're ok with having SitecoreUISearchResultItem as the query result type, you may be able to utilize the same method Sitecore 7 uses to parse queries entered in the content editor search:
Sitecore.Buckets.Util.UIFilterHelpers.ParseDatasourceString(string query)
If that's not up to what you're after, reading how it's implemented with a decompiler (ILSpy, DotPeek, Reflector, Resharper, etc) may help you in composing an expression manually based on dynamic criteria.
My question is: How can I order a DBGrid by a calculated field. I am using the C++Builder Starter Editon and do not have a ClientDataSet available in this version to create an Index on the field and order by the index of a column.So this is not an option. (Read this in many threads) I am using an TIBDataSet (ibds below) and I am filtering the data. Works fine....for the DB-columns, not for the calculated ones... Any ideas of how I might get around this problem?
void __fastcall TForm1::DBGrid3TitleClick(TColumn *Column)
{
static cIdx = 0;
static String oby = "ASC";
TBookmark CurrentPosition;
TIBDataSet *ibds = IBDS_accountsDist;
CurrentPosition = ibds->GetBookmark();
if (cIdx != Column->Index) {
oby = "ASC"; // ANOTHER column choosen
} else if (oby == "ASC") {
oby = "DESC";
} else oby = "ASC";
cIdx = Column->Index;
ibds->Filtered = false;
switch (Column->Index){
case 0: ibds->Filter = "ORDER BY SumAj "+oby; break; // SumAj is a calculated field => Does not work
case 1: ibds->Filter = "ORDER BY CSAL_ACCOUNTNAME "+ oby; break; // DB-field WORKS FINE
}
ibds->Filtered = true;
ibds->GotoBookmark(CurrentPosition);
}
You cannot do it. TIBDataSet is a representation of the underlying database. Basically it fetches the records in the order defined in the SQL.
The easiest way is to use TDBClientDataset but it is not included in Starter version of c++ Builder. You can explore other ways, for example pre-loading all records in a std::list and then use the order function to order the records. Finally you can show them using a simple TGrid o TStringGrid.
In any case, I recommend to upgrade C++Builder since TClientDataSet is one of the main pieces in most of data projects, specially when you need to create medium-large projects.
Mixing database specific components like TIBDataSet with the user interface penalizes the scalability and maintenance of the project.
I have added a record to my table which auto-increments the primary key. I am having no luck retrieving this new value. The MySQL documents say to use the SELECT LAST_INSERT_ID(); in a query. I have done this, but can't retrieve the results.
According the the metadata of the result set, the data type is BIGINT and the column name is LAST_INSERT_ID(). The C++ connector has a getUInt64() for the result set, which I assume is the correct method to use.
The ResultSet class declaration contains the following:
virtual uint64_t getUInt64(uint32_t columnIndex) const = 0;
virtual uint64_t getUInt64(const std::string& columnLabel) const = 0;
The documentation does not state whether the columnIndex is zero based or one based. I tried both and get sql::InvalidArgumentException for both cases.
Using the result set metadata, I retrieved the column name and passed it directly to the getUInt64 method and still receive the sql::InvalidArgumentException. This not a good indication (when the returned column name doesn't work when fetching the data).
Here is my code fragment:
std::string query_text;
query_text = "SELECT LAST_INSERT_ID();";
boost::shared_ptr<sql::Statement> query(m_db_connection->createStatement());
boost::shared_ptr<sql::ResultSet> query_results(query->executeQuery(query_text));
long id_value = 0;
if (query_results)
{
ResultSetMetaData p_metadata = NULL;
p_metadata = query_results->getMetaData();
unsigned int columns = 0;
columns = p_metadata->getColumnCount();
std::string column_label;
std::string column_name;
std::string column_type;
for (i = 0; i < columns; ++i)
{
column_label = p_metadata->getColumnLabel(i);
column_name = p_metadata->getColumnName(i);
column_type = p_metadata->getColumnTypeName(i);
wxLogDebug("Column label: \"%s\"\nColumn name: \"%s\"\nColumn type: \"%s\"\n",
column_label.c_str(),
column_name.c_str(),
column_type.c_str());
}
unsigned int column_index = 0;
column_index = query_results->findColumn(column_name);
// The value of column_index is 1 (one).
// All of the following will generate sql::InvalidArgumentException
id_value = query_results->getUInt64(column_index);
id_value = query_results->getUInt64(column_name);
id_value = query_results->getUInt64(0);
id_value = query_results->getUInt64(1);
id_record.set_record_id(id_value);
}
Here is the debug output (from wxLogDebug):
10:50:58: Column label: "LAST_INSERT_ID()"
Column name: "LAST_INSERT_ID()"
Column type: "BIGINT"
My Question: How do I retrieve the LAST_INSERT_ID() using the MySQL C++ Connector?
Do I need to use a prepared statement instead?
I am using MySQL Connector C++ 1.0.5 on Windows Vista and Windows XP with Visual Studio 9 (2008).
Resolved.
I inserted a query_results->next() before retrieving the data and that worked.