Does QT have reflections for C++? - c++

I want to create a SQL table in QT C++. So I have made this code.
And it is going to create a database for me, where the first argument tableName is the name of the table I want to create. Then the next argument is quite tricky.
Here, columns, specify the column name and it's data type. I think this is a bad way to do. Example
QVector<QPair<QString, QString>> myColumns = new QVector<QPair<QString, QString>>{{"ID", "BIGINT"}, {"logging_id", "INT"}};
Because If i have for example like 50 columns. The myColumns is going to be very long.
My question if QT C++ have some kind of reflections, so I can:
Get the name if every field
Get the data type of every field
If the field is an array, then I'm going to know how many elements there are inside that array
I was planning to have an entity class where I create a class, and use that class to get the information to create each columns in the database.
void Database::createTable(QString tableName, const QVector<QPair<QString, QString>> columns){
QSqlQuery query;
for (int i = 0; i < columns.length(); i++){
/* Get the Qpair values */
QString columnName = columns.at(i).first;
QString dataType = columns.at(i).second;
/* If key is ID, then try to create a new table */
if(columnName == "ID"){
query.exec("CREATE TABLE " + tableName + "(" + columnName + " " + dataType + " NOT NULL AUTO_INCREMENT PRIMARY KEY)");
continue;
}
/* If not, then try append new columns */
query.exec("ALTER TABLE " + tableName + " ADD " + columnName + " " + dataType);
}
}

Related

Can't check if a table exist in QT MYSQL

I'm trying to check if a table exist in a schema for QMYSQL inside QT framework.
I have connected the MySQL server and it can create a table, but NOT check if a table exist.
This is the code for checking if a table exist
query.exec("CREATE TABLE " + table_name + "(ID BIGINT PRIMARY KEY)");
QStringList tables = this->qSqlDatabase.tables();
qDebug() << "Table name: " + table_name;
for(int i = 0; i < tables.length(); i++)
qDebug() << tables[i];
qDebug() << tables.length();
if(tables.contains(table_name))
The if-statement does not run and the output is:
"Table name: table0"
0
In this case table_name = "table0". But why does this happening?
try this line:
query.exec("CREATE TABLE " + table_name + " (ID BIGINT, PRIMARY KEY (ID));");

Create a JPA Named Query with conditional where clause based on user value selections

I am rewriting an existing application and am required to use the existing application queries using JPA 2. How do I write a Named Query that replaces a dynamic query that will add sections to the where clause based on a value selection. In other words, if a value is selected from a drop down box, I will add a AND/OR section to the where clause. If not, that where clause section is omitted. For example:
int paramIdx = 0;
String query = "SELECT * FROM ANIMAL_TABLE WHERE...something";
String whereClause = "";
if(canine!= null and canine.trim().length() > 0) {
whereClause += " AND canine_type = :" + (paramIdx + 1) + viewObject.setWhereClauseParam(paramIdx, canine);
paramIdx++;
}
if(cat != null and cat.trim().length() > 0) {
whereClause += " AND cat_type = :" + (paramIdx + 1) + viewObject.setWhereClauseParam(paramIdx, cat);
}
I'm wondering if there is a way to accomplish this using JPA. Any ideas or suggestions would be helpful.

SqlDataAdapter not loading datatable - C++

I have been trying to load an SQL database into a datatable in C++, however; it doesn't seem to want to work. The connection is working though, as DataReader works. Here is my code
void importDatabase() {
SqlConnection con;
SqlDataAdapter^ da;
SqlCommand cmd;
DataTable^ dt;
int count = 1;
try {
con.ConnectionString = "Data Source=MYNAME\\SQLEXPRESS;Initial Catalog=VinylRecords;Integrated Security=True";
cmd.CommandText = "SELECT * FROM Records";
cmd.Connection = %con;
con.Open();
da = gcnew SqlDataAdapter(%cmd);
dt = gcnew DataTable("Records");
Console::Write(da->ToString());
da->Fill(dt);
for (int i = 0; i < dt->Rows->Count - 1; i++) {
String^ value_string;
value_string = dt->Rows[i]->ToString();
Console::WriteLine(dt->Rows[i]->ToString());
count++;
}
cout << "There are " << count << " many records";
}
catch (Exception^ ex) {
Console::WriteLine(ex->ToString());
}
}
Please note, that I slightly altered the source name to post here, but only the first part.
What is wrong with my code?
So, the problem is here:
dt->Rows[i]->ToString()
Rows[i] is a Row object. And the Row class's ToString() method always prints out the fully qualified typename, which is what you are seeing. So this is technically working just fine. What you will need to do to get something useful is: you will need to access a specific column in that row and get it's value, then output that.
Something along the lines of:
foreach (DataRow dr in dt.Rows)
{
Console.Write(dr.Field<int>("ColumnOne"));
Console.Write(" | ");
Console.WriteLine(dr.Field<string>("ColumnTwo"));
}
I am not entirely sure on the syntax for accessing a specific cell inside of a DataTable when using C++\CLI. So I have provided the C# equivalent to explain why it is you were getting output of managed type names (e.g. "System.Data.DataRow") instead of the info inside of the Row's columns.
Also, I noticed you tagged this question with "mysql", but you are using the ADO.NET System.Data.SqlClient namespace. The SqlDataReader and SqlDataAdapter classes only work with TSQL (Microsoft's SQL Server databases) If you are actually connecting to a mysql database you will want to use the System.Data.OdbcDataAdapter class. You can read a little more here: https://msdn.microsoft.com/en-us/library/ms254931.aspx

PQexecParams in C++, query error

I'm using pqlib with postgresql version 9.1.11
I have the following code
const char *spid = std::to_string(pid).c_str();
PGresult *res;
const char *paramValues[2] = {u->getID().c_str(), spid};
std::string table;
table = table.append("public.\"").append(Constants::USER_PATTERNS_TABLE).append("\"");
std::string param_name_pid = Constants::RELATION_TABLE_PATTERN_ID;
std::string param_name_uid = Constants::RELATION_TABLE_USER_ID;
std::string command = Constants::INSERT_COMMAND + table + " (" + param_name_uid + ", " + param_name_pid + ") VALUES ($1, $2::int)";
std::cout << "command: " << command << std::endl;
res = PQexecParams(conn, command.c_str(), 2, NULL, paramValues, NULL, NULL,0);
Where
INSERT_COMMAND = "INSERT INTO " (string)
USER_PATTERN_TABLE = "User_Patterns" (string)
RELATION_TABLE_PATTERN_ID = "pattern_id" (string)
RELATION_TABLE_USER_ID = "user_id" (string)
pid = an int
u->getID() = a string
conn = the connection to the db
The table "User_Patterns" is defined as
CREATE TABLE "User_Patterns"(
user_id TEXT references public."User" (id) ON UPDATE CASCADE ON DELETE CASCADE
,pattern_id BIGSERIAL references public."Pattern" (id) ON UPDATE CASCADE
,CONSTRAINT user_patterns_pkey PRIMARY KEY (user_id,pattern_id) -- explicit pk
)WITH (
OIDS=FALSE
);
I already have a user and a pattern loaded into their respective tables.
The command generated is :
INSERT INTO public."User_Patterns" (user_id, pattern_id) VALUES ($1, $2::int)
I also tried with $2, $2::bigint, $2::int4
The problem is:
I receive the error :
ERROR: invalid input syntax for integer: "public.""
I already use PQexecParams to store users and patterns, the only difference is that they all have text/xml fields (the only int field on patterns is a serial one and I don't store that value myself) but because the user_patterns is a relation table I need to store and int for the pattern_id.
I already read the docs for pqlib and saw the examples, both are useless.
The problem is in the lines:
const char *spid = std::to_string(pid).c_str();
const char *paramValues[2] = {u->getID().c_str(), spid};
std::to_string(pid) creates temporary string and .c_str() returns a pointer to an internal representation of this string, which is destroyed at the end of the line, resulting in a dead pointer. You may also see answer to the question
stringstream::str copy lifetime

Invalid Argument to getUInt64 when retrieving LAST_INSERT_ID()

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.