Windows.h with SQLite visual c++ error - winapi

I have just started windows application programming 2 days ago.. I am using VC++ and it is having some issues which I am unable to figure out.
When i send proper arguments to the function below, it displays everything properly but it doesn't save the insert query to the DB.
Here is the statement:
INSERT INTO BOOKS(ID,USERNAME,ISSUER,RETURNED) VALUES(1,'xyz','xyz',0);
Here is the table creation statement of sqlite:
sql = "CREATE TABLE IF NOT EXISTS BOOKS(" \
"ID INT PRIMARY KEY NOT NULL," \
"BOOKNAME TEXT NOT NULL," \
"ISSUER TEXT NOT NULL," \
"RETURNED INT);";
Here is the function:
using namespace std;
int WriteToDB(sqlite3 *,const char [],wchar_t *,HWND *);
int WriteToDB(sqlite3 *_db,const char _query[],wchar_t *ermsg,HWND *hw)
{
sqlite3_stmt *insertStmt;
MessageBox(*hw,L"Creating insert statement",L"INFO",MB_OK);
if(sqlite3_prepare(_db, _query, 400,&insertStmt, NULL))
MessageBox(*hw,L"Prepared!",L"Info",MB_OK);
MessageBox(*hw,L"Stepping into insert statement",L"INFO",MB_OK);
MessageBox(*hw,(LPWSTR)_query,L"Input",MB_OK);
if (sqlite3_step(insertStmt) != SQLITE_DONE)
{
wcscpy(ermsg,CharToWChar("Didn't Insert Item! Please check statement or DataBase!!"));
return 0;
}
sqlite3_finalize(insertStmt);
return 1;
}
EDIT: Here is the new error i got:
In SQLite,
near "I": Syntax Error
This Statement:
INSERT INTO BOOKS(ID,BOOKNAME,ISSUER,RETURNED) VALUES(1,'xyz','xyz',0);

Mistake here:
if(sqlite3_prepare(_db, _query, 400,&insertStmt, NULL)) //...
Should be:
if(sqlite3_prepare(_db, _query, 400,&insertStmt, NULL)==SQLITE_OK) //...
Because #define SQLITE_OK 0 /* Successful result */, your previous condition was opposite to pretended one.
Advice: instead of merging data in SQL statement, consider using parameters and sqlite3_bind_* interfaces.
EDIT:
Using sqlite3_prepare_v2 is recommended over sqlite3_prepare. Using such, you can easily have information on error cause with sqlite3_errmsg:
if(sqlite3_prepare(_db, _query, 400,&insertStmt, NULL) == SQLITE_OK) {
MessageBox(*hw,L"Prepared!",L"Info",MB_OK);
} else {
MessageBox(*hw, sqlite3_errmsg16(_db), L"Error", MB_OK);
}

Related

Ensure data is physically deleted from a data file

Consider the following:
You create a table space/data file for a table. You insert data into the table and this table has an index.
When you delete the data, it is possible that the data is not actually deleted from the data file. I wrote the program
#include <stdio.h>
int main()
{
FILE *file = fopen("/some/file/name", "r");
int ch;
while ((ch = fgetc(file)) != EOF) {
if (isprint(ch)) printf("%c", ch);
}
}
This will display any printable characters. I have found that sometimes the data still exists in the data file (on the OS level)
Is there a way of getting Oracle to zero this data?

Using snmpgetnext on a table

I am writing my own MIB Module containing a table with 2 columns. Using snmptable works just fine and retrieves all values of the table with all the rows.
But with snmpgetnext I can only retrieve the first row of the table.
snmpgetnext -v2c -c public localhost sensorTable
MY-PERSONAL-MIB::sensorVoltage."1" = STRING: "2.3V"
To retrieve the next value I must run:
snmpgetnext -v2c -c public localhost sensorVoltage."2"
MY-PERSONAL-MIB::sensorTemperature."1" = "3.2C"
Running snmpgetnext -v2c -c public localhost sensorVoltage."1" would result in sensorVoltage."1" again, the same for sensorTemperature."1".
snmpgetnext -v2c -c public localhost sensorTemperature."2"
SNMPv2-MIB::snmpSetSerialNo.0 = INTEGER: 1664041205
Also, I ran snmptable -CB so the manager only uses GETNEXT to retrieve the table values. This works fine as well.
So why can't I retrieve the single values with a simple snmpgetnext request?
As last, snmpget doesn't work at all. I get the following error:
snmpget -v2c -c publicl localhost sensorTemperature."1"
MY-PERSONAL-MIB::sensorTemperature.1 = No such Instance currently exists at this OID
At last, my code I use for my MIB-Module. I use the handler to read data from a file and create a table struct through it. I tried using snmpgetnext with a table created through the initialization routine resulting in the same problem, so the handler routine shouldn't be the issue here but I still appended it just for completion and well, who knows!
#include <net-snmp/net-snmp-config.h>
#include <net-snmp/net-snmp-includes.h>
#include <net-snmp/agent/net-snmp-agent-includes.h>
#include "sensorTable.h"
#define firstEntryRow 2
netsnmp_table_data_set *table_set;
void
initialize_table_sensorTable(void)
{
netsnmp_ds_set_string(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_X_SOCKET, "tcp:localhost:705");
const oid sensorTable_oid[] = { 1 ,3 ,6 ,1 ,4 ,1 ,8072 ,1259 ,1 ,1 };
table_set = netsnmp_create_table_data_set("sensorTable");
netsnmp_table_row *row;
table_set->allow_creation = 1;
DEBUGMSGTL(("initialize_table_sensorTable",
"adding indexes to table sensorTable\n"));
netsnmp_table_dataset_add_index(table_set,
ASN_OCTET_STR);
DEBUGMSGTL(("initialize_table_sensorTable",
"adding column types to table sensorTable\n"));
netsnmp_table_set_multi_add_default_row(table_set,
COLUMN_SENSORVOLTAGE, ASN_OCTET_STR, 1,
NULL, 0,
COLUMN_SENSORTEMPERATURE, ASN_OCTET_STR, 1,
NULL, 0,
0);
netsnmp_register_table_data_set(netsnmp_create_handler_registration("sensorTable", sensorTable_handler,
sensorTable_oid,
OID_LENGTH(sensorTable_oid),
HANDLER_CAN_RWRITE),
table_set, NULL);
row = netsnmp_create_table_data_row();
netsnmp_table_row_add_index(row, ASN_OCTET_STR, "1",
strlen("1"));
netsnmp_set_row_column(row, 2, ASN_OCTET_STR,
"5.9V", strlen("5.9V"));
netsnmp_set_row_column(row, 3, ASN_OCTET_STR,
"21.5C", strlen("21.5C"));
netsnmp_table_dataset_add_row(table_set, row);
}
void
init_sensorTable(void)
{
initialize_table_sensorTable();
}
int
sensorTable_handler(
netsnmp_mib_handler *handler,
netsnmp_handler_registration *reginfo,
netsnmp_agent_request_info *reqinfo,
netsnmp_request_info *requests) {
netsnmp_table_row *row, *tempRow;
if( table_set != NULL )
{
for ( tempRow = table_set->table->first_row;
tempRow; tempRow = tempRow->next )
{
row = netsnmp_table_data_set_get_first_row(table_set);
netsnmp_table_dataset_remove_row(table_set, row);
}
}
/* Start reading "input.txt */
char sensorValues[32];
char *singleValue;
FILE *f = fopen("/home/supra/Desktop/input.txt", "r");
/* check if the file was found */
if( f == NULL ) {
printf("Error opening file!\n");
exit(EXIT_FAILURE);
}
/* check if the file is empty */
if ( fgets( sensorValues, sizeof(sensorValues), f) == NULL )
{
printf("Warning: File is empty!\n");
exit(EXIT_FAILURE);
}
/* if the file is not empty, create a row and start
* breaking the string into words. Fill the row with the words
* and add it to the table. */
do
{
int rowEntries = firstEntryRow;
singleValue = strtok( sensorValues, " ");
row = netsnmp_create_table_data_row();
netsnmp_table_row_add_index(row, ASN_OCTET_STR, singleValue, strlen(singleValue) );
singleValue = strtok( NULL, " ");
/* Fill the row with values */
while(singleValue != NULL)
{
netsnmp_set_row_column(row, rowEntries, ASN_OCTET_STR, singleValue, strlen(singleValue) );
rowEntries++;
singleValue = strtok(NULL, " ");
}
netsnmp_table_dataset_add_row(table_set, row);
} while( fgets( sensorValues, sizeof(sensorValues), f) != NULL);
fclose(f);
return SNMP_ERR_NOERROR;
}
Regarding :
So why can't I retrieve the single values with a simple snmpgetnext request?
Quoting man snmpgetnext
DESCRIPTION
snmpget is an SNMP application that uses the SNMP GETNEXT request to query for information on a network entity. One or more
object identifiers (OIDs) may
be given as arguments on the command line. Each variable name is given in the format specified in variables(5). For each one, the
variable that is lexicographically "next" in the remote entity's MIB will be returned. For example:
snmpgetnext -c public zeus interfaces.ifTable.ifEntry.ifType.1
will retrieve the variable
interfaces.ifTable.ifEntry.ifType.2
In other words its job is to get one thing back.
If you want to use it to get a full table, you need to invoke it multiple times. Quoting man page for snmptable :
snmptable is an SNMP application that repeatedly uses the SNMP GETNEXT or GETBULK requests to query for information on a network entity.

mariadb jdbc driver blob update not supported

After I replaced mysql jdbc driver 5.1 with mariadb jdbc driver 1.1.5 and tested the existing code base that connected with MySQL Server 5.0 and MariaDB Server 5.2, everything works fine except a JDBC call to update a blob field in a table.
The blob field contains XML configuration file. It can be read out, and convert to xml and insert some values.
Then convert it to ByteArrayInputStream object, and call the method
statement.updateBinaryStream(columnLabel, the ByteArrayInputStream object, its length)
but an exception is thrown:
Perhaps you have some incorrect SQL syntax?
java.sql.SQLFeatureNotSupportedException: Updates are not supported
at
org.mariadb.jdbc.internal.SQLExceptionMapper.getFeatureNotSupportedException(SQLExceptionMapper.java:165)
at
org.mariadb.jdbc.MySQLResultSet.updateBinaryStream(MySQLResultSet.java:1642)
at
org.apache.commons.dbcp.DelegatingResultSet.updateBinaryStream(DelegatingResultSet.java:511)
I tried updateBlob method, the same exception was thrown.
The code works well with mysql jdbc driver 5.1.
Any suggestions on how to work around with this situation?
See the ticket updating blob with updateBinaryStream, which in commnet states that it isn't supported.
A workaround would be to use two SQL statements. One which is used to select the data and other to update the data. Something like this:
final Statement select = connection.createStatement();
try {
final PreparedStatement update = connection.prepareStatement( "UPDATE table SET blobColumn=? WHERE idColumn=?" );
try {
final ResultSet selectSet = select.executeQuery( "SELECT idColumn,blobColumn FROM table" );
try {
final int id = selectSet.getInt( "idColumn" );
final InputStream stream = workWithSTreamAndRetrunANew( selectSet.getBinaryStream( "blobColumn" ) ) );
update.setBinaryStream( 1,stream );
update.setInt( 2,id );
update.execute();
}
finally {
if( selectSet != null )
selectSet.close();
}
}
finally {
if( update != null )
update.close();
}
}
finally {
if( select != null )
select.close();
}
But be aware that you need some information how to uniquely identify a table entry, in this example the column idColumn was used for that purpose. Furthermore is you stored empty stream in the
database you might get an SQLException.
A simpler work around is using binary literals (like X'2a4b54') and concatenation (UPDATE table SET blobcol = blobcol || X'2a4b54') like this:
int iBUFSIZ = 4096;
byte[] buf = new byte[iBUFSIZ];
int iLength = 0;
int iUpdated = 1;
for (int iRead = stream.read(buf, 0, iBUFSIZ);
(iUpdated == 1) && (iRead != -1) && (iLength < iTotalLength);
iRead = stream.read(buf, 0, iBUFSIZ))
{
String sValue = "X'" + toHex(buf,0,iRead) + "'";
if (iLength > 0)
sValue = sBlobColumn + " || " + sValue;
String sSql = "UPDATE "+sTable+" SET "+sBlobColumn+"= "+sValue;
Statement stmt = connection.createStatement();
iUpdated = stmt.executeUpdate(sSql);
stmt.close();
}

CREATE PROCEDURE - how to check if successfully compiled?

I'm using OCILIB.
Statements of the form CREATE OR REPLACE PROCEDURE AA1 AS BEGIN XXX; END; are always successful (ie, no error or warning is reported). How can I check whether the statement was compiled correctly?
There should be a function to get that information (I hope).
Here is a quick & dirty example that shows the issue:
#include <stdio.h>
#include <ocilib.h>
void print_error() {
printf("Error:");
OCI_Error *err = OCI_GetLastError();
if (err) printf(" %d: %s\n", OCI_ErrorGetOCICode(err), OCI_ErrorGetString(err));
else printf(" no error.");
printf("\n");
}
int main (int argc, char **argv) {
OCI_Connection *cn;
OCI_Statement *st;
OCI_EnableWarnings(TRUE);
if (!OCI_Initialize(NULL, NULL, OCI_ENV_DEFAULT | OCI_ENV_CONTEXT)) {
puts("Failed to initialize OCI");
return 2;
}
cn = OCI_ConnectionCreate("XE", "<your user>", "<your pwd>", OCI_SESSION_DEFAULT);
print_error();
OCI_SetAutoCommit(cn, TRUE); print_error();
st = OCI_StatementCreate(cn); print_error();
OCI_ExecuteStmt(st, "create or replace procedure aaa as begin garbage end;");
print_error();
OCI_Cleanup();
return 0;
}
Output:
$ ./ocitest
Error: no error.
Error: no error.
Error: no error.
Error: no error.
There was an issue in OCILIB that was not reporting SQL Warnings properly. This is fixed and OCILIB repository is up to date with the fix :)
You can check the status in the user_objects view:
select status
from user_objects
where object_type = 'PROCEDURE'
and object_name = 'AA1';
If that is not VALID, you can get the actual errors by querying the user_errors view:
select * -- or just line, position and text
from user_errors
where type = 'PROCEDURE'
and name = 'AA1'
order by sequence;
I'm surprised you don't get an exception, but this isn't a stack I use...

Alternative to fgets()?

Description:
Obtain output from an executable
Note:
Will not compile, due to fgets() declaration
Question:
What is the best alternative to fgets, as fgets requires char *?
Is there a better alternative?
Illustration:
void Q_analysis (const char *data)
{
string buffer;
size_t found;
found = buffer.find_first_of (*data);
FILE *condorData = _popen ("condor_q", "r");
while (fgets (buffer.c_str(), buffer.max_size(), condorData) != NULL)
{
if (found == string::npos)
{
Sleep(2000);
} else {
break;
}
}
return;
}
You should be using the string.getline function for strings
cppreference
however in your case, you should be using a char[] to read into.
eg
string s;
char buffer[ 4096 ];
fgets(buffer, sizeof( buffer ), condorData);
s.assign( buffer, strlen( buffer ));
or your code:
void Q_analysis( const char *data )
{
char buffer[ 4096 ];
FILE *condorData = _popen ("condor_q", "r");
while( fgets( buffer, sizeof( buffer ), condorData ) != NULL )
{
if( strstr( buffer, data ) == NULL )
{
Sleep(2000);
}
else
{
break;
}
}
}
Instead of declaring you buffer as a string declare it as something like:
char buffer[MY_MAX_SIZE]
call fgets with that, and then build the string from the buffer if you need in that form instead of going the other way.
The reason what you're doing doesn't work is that you're getting a copy of the buffer contents as a c-style string, not a pointer into the gut of the buffer. It is, by design, read only.
-- MarkusQ
You're right that you can't read directly into a std::string because its c_str and data methods both return const pointers. You could read into a std::vector<char> instead.
You could also use the getline function. But it requires an iostream object, not a C FILE pointer. You can get from one to the other, though, in a vendor-specific way. See "A Handy Guide To Handling Handles" for a diagram and some suggestions on how to get from one file type to another. Call fileno on your FILE* to get a numeric file descriptor, and then use fstream::attach to associate it with an fstream object. Then you can use getline.
Try the boost library - I believe it has a function to create an fstream from a FILE*
or you could use fileno() to get a standard C file handle from the FILE, then use fstream::attach to attach a stream to that file. From there you can use getline(), etc. Something like this:
FILE *condorData = _popen ("condor_q", "r");
std::ifstream &stream = new std::ifstream();
stream.attach(_fileno(condorData));
I haven't tested it all too well, but the below appears to do the job:
//! read a line of text from a FILE* to a std::string, returns false on 'no data'
bool stringfgets(FILE* fp, std::string& line)
{
char buffer[1024];
line.clear();
do {
if(!fgets(buffer, sizeof(buffer), fp))
return !line.empty();
line.append(buffer);
} while(!strchr(buffer, '\n'));
return true;
}
Be aware however that this will happily read a 100G line of text, so care must be taken that this is not a DoS-vector from untrusted source files or sockets.

Resources