root/vtcross/trunk/src/include/vtcross/cbr.h @ 471

Revision 471, 11.9 KB (checked in by bhilburn, 15 years ago)

Larger-block reformats. About to start converting from c-strings to
std::string.

Line 
1/*
2 Copyright 2009 Virginia Polytechnic Institute and State University 
3
4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at
7 
8 http://www.apache.org/licenses/LICENSE-2.0
9
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
15*/
16
17/* This file contains the full implementation of the CBR class - the default
18 * VTCROSS case-based reasoner.
19 */
20
21
22
23#ifndef CBR_H
24#define CBR_H
25
26#include <cstdlib>
27#include <cstring>
28#include <cstdio>
29#include <stdint.h>
30#include <string>
31
32#include <sqlite3.h>
33
34#include "vtcross/common.h"
35#include "vtcross/debug.h"
36#include "vtcross/error.h"
37
38using namespace std;
39
40
41#define DATABASENAME "vtcross_cbr"
42
43
44/* This is an internal debugging function used by some sqlite3 function calls.
45 * It is not used otherwise in the VTCROSS codebase. */
46int32_t
47callback(void *notUsed, int argc, char **argv, char **azColName)
48{
49    for(size_t i = 0; i < argc; i++) {
50        LOG("%s = %s\n", azColName[i], argv[i] ? argv[i] : "NULL");
51    }
52    LOG("\n");
53
54    return 0;
55}
56
57
58/* The CBR class is designed to used as either as-is, or as a parent class.  All
59 * functions are declared virtual, and internal members are 'protected' rather
60 * than private. If you require functionality in a CBR not specifically provided
61 * by this class, include this header in your source file, create a new class
62 * that derives from CBR, and implement your desired functionality over the
63 * original virtual functions as necessary.
64 */
65class CBR
66{
67    public:
68        /* Constructors for the CBR class. Note that the default constructor
69         * must be defined inline here so that super-calls from child classes
70         * don't fail (i.e. we cannot rely on the compiler-provided constructor. */
71        CBR(){};
72        CBR(char *_filename, char *_tablename, char *_cols[], uint32_t _len);
73        CBR(char *_filename, char *_tablename, char *_cols[], \
74                char *_primcols[], uint32_t _len, uint32_t _primlen);
75
76        /* Destructor for the CBR class. Note that this destructor will be
77         * called automatically by any derived classes, and so child classes
78         * should not repeat the freeing actions performed in this function. */
79        virtual ~CBR();
80
81        /* This function opens the VTCROSS database, or if it has not been
82         * created yet, creates it. */
83        virtual int32_t OpenDatabase();
84
85        /* Execute a sqlite3 command and return the sqlite3 return code. */
86        virtual int32_t ExecuteCommand();
87
88        /* Execute a sqlite3 search command and store the results in the passed
89         * retvals argument. */
90        virtual int32_t ExecuteSearchCommand(float *_retvals);
91
92        /* Print the VTCROSS sqlite3 database. */
93        virtual void Print();
94
95        /* Search the VTCROSS database for specific fields and store the results
96         * in the passed retvals argument. */
97        virtual int32_t Search(char *_names[], int32_t *_ops, float *_vals, \
98                uint32_t _n, float *_retvals);
99        virtual int32_t SearchSum(char *_name, float *_retvals);
100        virtual int32_t SearchRand(char *_names[], int *_ops, float *_vals, uint32_t _n, \
101            float *_retvals);
102
103        /* Update a row in the VTCROSS sqlite3 database. */
104        virtual int32_t Update(char *_where[], char *_set[], float *_wherevals, \
105                float *_setvals, uint32_t _wherelen, uint32_t _setlen);
106
107        /* Add a row to the VTCROSS sqlite3 database. */
108        virtual int32_t AddRow(char *_cols[], float *_vals, uint32_t _len);
109
110    protected:
111        char filename[64];
112        char tablename[64];
113        char command[2048];
114        sqlite3 *db;
115        uint32_t numColumns;
116};
117
118
119CBR::CBR(char *_filename, char *_tablename, char *_cols[], uint32_t _len)
120{
121    // copy filename
122    unsigned int i=0;
123    strcpy(filename, _filename);
124
125    // execute create database command
126    // database handle
127    //db = NULL;
128    OpenDatabase();
129
130    // create table
131
132    // copy tablename
133    strcpy(tablename, _tablename);
134
135    // number of columns in the table
136    numColumns = _len;
137
138    // generate command
139    strcpy(command, "CREATE TABLE ");
140    strcat(command, tablename);
141    strcat(command, "(");
142    for (i=0; i<numColumns; i++) {
143        strcat(command, _cols[i]);
144        strcat(command, " FLOAT");
145        if (i != numColumns-1) // not last entry
146            strcat(command, ", ");
147    }
148    strcat(command, ");");
149
150    // execute create table command
151    ExecuteCommand();
152}
153
154CBR::CBR(char * _filename, char * _tablename,
155        char * _cols[], char * _primcols[], unsigned int _len,
156        unsigned int _primlen)
157{
158    // create database
159
160    // copy filename
161    unsigned int i=0;
162    strcpy(filename, _filename);
163
164    // execute create database command
165    // database handle
166    //db = NULL;
167    OpenDatabase();
168
169    // create table
170
171    // copy tablename
172    strcpy(tablename, _tablename);
173
174    // number of columns in the table
175    numColumns = _len;
176
177    // generate command
178    strcpy(command, "CREATE TABLE ");
179    strcat(command, tablename);
180    strcat(command, "(");
181    for (i=0; i<numColumns; i++) {
182        strcat(command, _cols[i]);
183        strcat(command, " FLOAT");
184        strcat(command, ", ");
185    }
186   strcat(command, "PRIMARY KEY (");
187    for (i=0; i<_primlen; i++) {
188        strcat(command, _primcols[i]);
189        if (i != _primlen-1) // not last entry
190            strcat(command, ", ");
191    }
192    strcat(command, "));");
193
194    // execute create table command
195    ExecuteCommand();
196}
197
198
199
200CBR::~CBR()
201
202    // generate command, remove a table with its content
203    strcpy(command, "drop table ");
204    strcat(command, tablename);
205
206    // execute delete command
207    ExecuteCommand();
208
209    // clean the database
210    strcpy(command, "vacuum");
211    ExecuteCommand();
212}
213
214
215
216
217int32_t
218CBR::OpenDatabase()
219{
220    int32_t rc;
221
222    rc = sqlite3_open(filename, &db);
223    if(rc) {
224        WARNING("Can't open database: %s\n", sqlite3_errmsg(db));
225        sqlite3_close(db);
226        exit(1);
227    }
228
229    return rc;
230}
231
232
233int32_t
234CBR::ExecuteCommand()
235{
236    int rc;
237    char *zErrMsg = 0;
238
239    rc = sqlite3_exec(db, command, callback, 0, &zErrMsg);
240    if( rc!=SQLITE_OK){
241        fprintf(stderr, "SQL error: %s: %s\n", zErrMsg, command);
242        sqlite3_free(zErrMsg);
243    }
244
245    return rc;
246}
247
248
249int32_t
250CBR::ExecuteSearchCommand(float *_retvals)
251{
252    int rc;
253    unsigned int i;
254
255    sqlite3_stmt * pStatement;
256    rc = sqlite3_prepare_v2(db, command, -1, &pStatement, NULL);
257    if (rc == SQLITE_OK){
258        if (sqlite3_step(pStatement) == SQLITE_ROW){
259            for (i=0; i<numColumns; ++i)
260                _retvals[i] = sqlite3_column_double(pStatement, i);
261        } else {
262                    printf("CBR:: No matched results returning default.\n");
263                        rc=31337;
264                }
265    } else {
266                printf("CBR:: Error executing SQL statement. rc = %i\n%s\n",rc,command);
267    }
268
269    sqlite3_finalize(pStatement);
270   
271    return rc;
272}
273void
274CBR::Print()
275{
276    // generate commandi
277    strcpy(command, "select ");
278    strcat(command, tablename);
279    strcat(command, ".* from ");
280    strcat(command, tablename);
281    strcat(command, ";");
282
283    // execute print (select all)  command
284    ExecuteCommand();
285    printf("database %s, table %s:\n", filename, tablename);
286}
287
288int32_t
289CBR::Search(
290    char *_names[],
291    int * _ops,
292    float *_vals,
293    unsigned int _n,
294    float *_retvals)
295{   
296    int rc;
297        const char *ops_str[] = {"==", "!=", ">", ">=", "<", "<="};
298    // generate command
299    strcpy(command, "select ");
300    strcat(command, tablename);
301    strcat(command, ".* from ");
302    strcat(command, tablename);
303    strcat(command, " where ");
304
305    unsigned int i;
306    char str_buffer[64];
307    printf("number of ops %d:\n", _n);
308    for (i=0; i<_n; i++) {
309        // ensure valid ops value
310        if (_ops[i] < 0 || _ops[i] > 5) {
311            printf("error: cbr_search(), invalid ops id : %d\n", _ops[i]);
312            exit(1);
313        }
314
315        strcat(command, _names[i]);
316        strcat(command, ops_str[_ops[i]]);
317    printf("search command: %s\n", command);
318        sprintf(str_buffer, "%E", _vals[i]);
319        strcat(command, str_buffer);
320
321
322        if (i<_n-1)
323            strcat(command, " AND ");
324        else
325            strcat(command, " order by utility desc;");
326    }
327
328
329    rc = ExecuteSearchCommand(_retvals);
330   
331    return rc;
332}
333
334int32_t
335CBR::SearchSum(
336    char *_name,
337    float *_retvals)
338{   
339    int rc;
340    // generate command
341    strcpy(command, "select SUM( ");
342    strcat(command, tablename);
343    strcat(command, ".");
344    strcat(command, _name);
345    strcat(command, ") from ");
346    strcat(command, tablename);
347    strcat(command, ";");
348
349    //printf("search command: %s\n", command);
350
351    rc = ExecuteSearchCommand(_retvals);
352    /*printf("search result: ");
353    for (int i=0; i<numColumns; i++)
354        printf("%f, ",_retvals[i]);
355    printf("\n");
356    */
357    return rc;
358}
359
360
361int32_t
362CBR::SearchRand(
363    char *_names[],
364    int * _ops,
365    float *_vals,
366    unsigned int _n,
367    float *_retvals)
368{   
369        const char *ops_str[] = {"==", "!=", ">", ">=", "<", "<="};
370    int rc;
371    // generate command
372    strcpy(command, "select ");
373    strcat(command, tablename);
374    strcat(command, ".* from ");
375    strcat(command, tablename);
376    strcat(command, " where ");
377
378    unsigned int i;
379    char str_buffer[64];
380    for (i=0; i<_n; i++) {
381        // ensure valid ops value
382        if (_ops[i] < 0 || _ops[i] > 5) {
383            printf("error: cbr_search(), invalid ops id : %d\n", _ops[i]);
384            exit(1);
385        }
386
387        strcat(command, _names[i]);
388        strcat(command, ops_str[_ops[i]]);
389        sprintf(str_buffer, "%E", _vals[i]);
390        strcat(command, str_buffer);
391
392        if (i<_n-1)
393            strcat(command, " AND ");
394        else
395            strcat(command, " order by RAND();");
396    }
397
398    //printf("search command: %s\n", command);
399
400    rc = ExecuteSearchCommand(_retvals);
401   
402    /*printf("search result: ");
403    for (i=0; i<numColumns; i++)
404        printf("%f, ",_retvals[i]);
405    printf("\n");
406*/
407    return rc;
408}
409
410
411
412
413int32_t
414CBR::Update(char *_where[], char*_set[], float *_wherevals, float *_setvals,
415                unsigned int _wherelen, unsigned int _setlen)
416{
417    unsigned int i;
418   
419    // generate command
420    strcpy(command, "UPDATE ");
421    strcat(command, tablename);
422   
423    strcat(command, " SET ");
424    for (i=0; i<_setlen; i++) {
425        strcat(command, _set[i]);
426        strcat(command, " = ");
427        sprintf(command, "%s%f", command, _setvals[i]);
428        strcat(command, "  ");
429        if (i != _setlen-1) // not last entry
430            strcat(command, ", ");
431    }
432    strcat(command, " WHERE ");
433
434    for (i=0; i<_wherelen; i++) {
435        strcat(command, _where[i]);
436        strcat(command, " = ");
437        sprintf(command, "%s%f", command, _wherevals[i]);
438        strcat(command, "  ");
439        if (i != _wherelen-1) // not last entry
440            strcat(command, "AND ");
441    }
442    strcat(command, ";");
443   
444    // execute add command
445    ExecuteCommand();
446
447    return 0;
448}
449
450int32_t
451CBR::AddRow(char *_cols[], float *_vals, unsigned int _len)
452{
453    unsigned int i;
454   
455    // generate command
456    strcpy(command, "insert into ");
457    strcat(command, tablename);
458   
459    strcat(command, " (");
460    for (i=0; i<_len; i++) {
461        strcat(command, _cols[i]);
462        if (i != numColumns-1) // not last entry
463            strcat(command, ", ");
464    }
465    strcat(command, ") ");
466
467    strcat(command, " values(");
468    for (i=0; i<_len; i++) {
469        // ???? how to fill the values if numColumns != _len
470        // assume = in the following
471        sprintf(command, "%s%f", command, _vals[i]);
472        if (i != numColumns-1) // not last entry
473            strcat(command, ", ");
474    }
475    strcat(command, ");");
476   
477    // execute add command
478    ExecuteCommand();
479
480    return 0;
481}
482
483#endif
Note: See TracBrowser for help on using the browser.