i have a question. i have a complex query and it contains group_concat.
MYSQL_RES* res = GetDBManager()->Query("select ls.time, count(ws.id) , group_concat(wc.id) , group_concat(ws.SIGNAL_STRENGTH) , ul.LATITUDE , ul.LONGITUDE , ul.ALTITUDE from user_location_scan ls, wifi_scan ws, wifi_cell wc, user_location ul where ls.id = ws.user_scan and ws.wifi_cell = wc.id and ls.time = ul.time group by ls.id order by ls.id");
how can i assign the data in group_concat to a struct such as
struct {
int APid;
double rssi;
}* sigstr;
i already tried a loop for() but it didn't work.
while (row = mysql_fetch_row(res)) {
int j = 0;
inf.time.FromSQL(row[j++]);
inf.numAP = atoi(row[j++]);
for (int i = 0; i < inf.numAP; i++) {
inf.sigstr[i].APid = atoi(row[j++]);
inf.sigstr[i].rssi = atof(row[j++]);
}
...
please help me.
UPDATE:
after some searching, i found that the data returned by group_concat actually cannot be assigned to an array. are there any ways to convert it?
Related
I'm working on a wrapper for MariaDB Connector C. There is a typical situation when a developer doesn't know a length of a data stored in a field. As I figured out, one of the ways to obtain a real length of the field is to pass a buffer of lengths to mysql_stmt_bind_result and then to fetch each column by calling mysql_stmt_fetch_column. But I can't understand how the function mysql_stmt_fetch_column works because I'm getting a memory corruption and app abortion.
Here is how I'm trying to reach my goal
// preparations here
...
if (!mysql_stmt_execute(stmt))
{
int columnNum = mysql_stmt_field_count(stmt);
if (columnNum > 0)
{
MYSQL_RES* metadata = mysql_stmt_result_metadata(stmt);
MYSQL_FIELD* fields = mysql_fetch_fields(metadata);
MYSQL_BIND* result = new MYSQL_BIND[columnNum];
std::memset(result, 0, sizeof (MYSQL_BIND) * columnNum);
std::vector<unsigned long> lengths;
lengths.resize(columnNum);
for (int i = 0; i < columnNum; ++i)
result[i].length = &lengths[i];
if (!mysql_stmt_bind_result(stmt, result))
{
while (true)
{
int status = mysql_stmt_fetch(stmt);
if (status == 1)
{
m_lastError = mysql_stmt_error(stmt);
isOK = false;
break;
}
else if (status == MYSQL_NO_DATA)
{
isOK = true;
break;
}
for (int i = 0; i < columnNum; ++i)
{
my_bool isNull = true;
if (lengths.at(i) > 0)
{
result[i].buffer_type = fields[i].type;
result[i].is_null = &isNull;
result[i].buffer = malloc(lengths.at(i));
result[i].buffer_length = lengths.at(i);
mysql_stmt_fetch_column(stmt, result, i, 0);
if (!isNull)
{
// here I'm trying to read a result and I'm getting a valid result only from the first column
}
}
}
}
}
}
If I put an array to the mysql_stmt_fetch_column then I'm fetching the only first field valid, all other fields are garbage. If I put a single MYSQL_BIND structure to this function, then I'm getting an abortion of the app on approximately 74th field (funny thing that it's always this field). If I use another array of MYSQL_BIND then the situation is the same as the first case.
Please help me to understand how to use it correctly! Thanks
Minimal reproducible example
Basically I am using an API to retrieve stock data to me in the form of a ytd so it will return data of the closing price of the stock everyday from january until now. At first I was simply using a for loop and reading until i < json.size() but after figuring out the .size() does not properly return what i need for it to work i am again stuck on this. My code is below
//Retrieves json format of data
Json::Value chartData = IEX::stocks::chartYtd(symbol_std);
//Stores x and y values
QVector<double> time(365), closePrice(365);
//Intialize first vector to first values
closePrice[0] = chartData[0]["close"].asDouble();
time[0] = startYearTime;
//Finds max and min for range
float maxAvg = closePrice[0];
float minAvg = closePrice[0];
//Reads in data from json(historical data 1 day delayed)
for(int i = 1; ; i++)
{
time[i] = startYearTime + 86400*i;
closePrice[i] = (chartData[i]["close"].asDouble());
if((closePrice[i] == 0) && (time[i] != chartData.size() - 1))
{
closePrice[i] = closePrice[i-1];
}
if(closePrice[i] > maxAvg)
{
maxAvg = closePrice[i];
}
else if(closePrice[i] < minAvg)
{
minAvg = closePrice[i];
}
}
The json file looks like this
what can i do to have my code store the "close" value in the json file until there is no more "close" value to read in and then in which it stops, thank you in advance as im a new developer!
I am ver new to VTK.
This is part of my code:
vtkDataSetReader *rdr = vtkDataSetReader::New();
rdr->SetFileName("proj7b.vtk");
rdr->SetScalarsName("hardyglobal");
rdr->Update();
int dims[3];
vtkRectilinearGrid *rgrid = (vtkRectilinearGrid *) rdr->GetOutput();
rgrid->GetDimensions(dims);
vtkDataArray *dataArray;
dataArray = vtkDoubleArray::New();
dataArray = rgrid->GetPointData()->GetScalars()->GetVoidPointer(0);
for(i=0;i<10;i++)
{
cout<<"here----------"<<endl;
cout<<" "<<dataArray[i]<<" ";
}
I want to read the data into my vtkDataArray. But this code cannot be compile:
proj7b.cxx:525:15: error:
assigning to 'vtkDataArray *' from incompatible type 'void *'
dataArray = rgrid->GetPointData()->GetScalars()->GetVoidPointer(0);
^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1 error generated.
Is there anyone knows how to read data into vtkDataArray?
Vtk provides the method for it, you don't need to use the "low level" method:
rgrid->GetPointData()->GetArray(0)
or
rgrid->GetPointData()->GetArray("arrayname")
It works the same way for FieldData and CellData ( http://www.vtk.org/doc/release/6.2/html/classvtkFieldData.html)
What you get is a vtkArray, not a simple c++ array, so you will have to read it like:
cout<<" "<<dataArray->GetValue(i) <<" ";
There are a lot of examples in the wiki http://www.vtk.org/Wiki/VTK/Examples/Cxx
please see this page: https://cloud.tencent.com/developer/ask/sof/148655
void doSomething(vtkSmartPointer<vtkDataArray> dataArray)
{
vtkIdType numTuples = dataArray->GetNumberOfTuples();
for (vtkIdType tupleIdx = 0; tupleIdx < numTuples; ++tupleIdx)
{
double* tuple = dataArray->GetTuple(tupleIdx);
for (int j = 0; j < /*¿¿¿???*/; ++j)
{
double var = tuple[j];
// Do something with var
// Carefull don't go out of bounds
}
}
}
I have the following code:
using (CPASEntities ctx = new CPASEntities())
{
IWorksheet ws = wb.Worksheets[0];
ws.Name = "Summary";
var tsm = (from x in ctx.tblTimesheetMasters
where x.TSID == TSID
select new
{
TimesheetID = x.TSID,
Comments = x.TSComments,
Vendor = x.tblVendor.Vendor_Name,
StartDate = x.TSStartDate,
Author = x.TSAuthor,
Approver = x.TSApprover,
Override_Approver = x.TSOverrideApprover,
Status = x.tblTimesheetStatu.TSStatusDesc
}
).ToList();
SpreadsheetGear.IRange range = ws.Cells["A1"];
// I want to copy the entire tsm list to this range, including headings.
}
As the comment states, I want to put that entire list into the ws worksheet starting at A1. I include the code in case it's easier to use a different construct. FWIW, there will be only one entry...TSID is the primary key. I can, of course, use the .FirstorDefault() construct if that is important. I thought it not important.
Your range is only one cell. You need a range big enough to contain all the cells the list would populate.
To populate your worksheet with the list, you could do something like this.
int iRow = 0;
int iCol = 0;
if (tsm.Count() > 0)
{
foreach (var prop in tsm[0].GetType().GetProperties())
{
ws.Cells[iRow, iCol].Value = prop.Name;
iCol++;
}
iRow++;
foreach (var t in tsm)
{
iCol = 0;
foreach (var prop in t.GetType().GetProperties())
{
ws.Cells[iRow, iCol].Value = prop.GetValue(t, null);
iCol++;
}
iRow++;
}
}
If you want a range, you could add this line.
SpreadsheetGear.IRange range = ws.Cells[0, 0, iRow - 1, iCol - 1];
Help me, I want to make a generic function that get the results of any query string and puts all rows into another variable. When iterating over a row, how can I know the numbers of columns available?
Environment *env = Environment::createEnvironment();
Connection *conn = env->createConnection("user","pass");
quantLinhas = 0;
if( conn != NULL ) {
Statement *stmt = conn->createStatement(query);
ResultSet *rs = stmt->executeQuery();
resultadoSQL->linhas.clear();
while (rs->next()) {
aux.campos.clear();
numbers_colums = rs->whatever_method() //WHAT DO I DO HERE??
for(i = 0; i < numbers_colums ; i++) {
aux.campos.push_back( rs->getString(i) );
quantLinhas++;
}
resultadoSQL->linhas.push_back( aux );
}
stmt->closeResultSet(rs);
conn->terminateStatement(stmt);
env->terminateConnection(conn);
}
According the documentation you can use getColumnListMetaData function. The number of elements in the returned vector might be what you want. You may check if each element is of PTYPE_COL to ensure it.
try this
vector<MetaData> columnList = rs->getColumnListMetaData();
numbers_colums = columnList.size();
columnList.clear();
it worked for me.
source link