Browse Source

* removing boost dependencies

Erik Winn 6 years ago
parent
commit
17f2dcb875

+ 1
- 2
CMakeLists.txt View File

@@ -15,12 +15,11 @@ set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
15 15
 find_package(MySQL)
16 16
 find_package(Sqlite3)
17 17
 find_package(Ctemplate REQUIRED)
18
-find_package(Boost REQUIRED)
19 18
 
20 19
 #ADD_DEFINITIONS(-Wall -O2)
21 20
 ADD_DEFINITIONS(-Wall -g)
22 21
 
23
-include_directories( ${Boost_INCLUDE_DIRS} ${WORM_INCLUDE_DIRS} ${SQLITE3_INCLUDE_DIR})
22
+include_directories( ${WORM_INCLUDE_DIRS} ${SQLITE3_INCLUDE_DIR} )
24 23
 
25 24
 add_subdirectory(src)
26 25
 install(FILES src/orm/templates/class_declaration.tpl DESTINATION share/worm)

+ 56
- 59
src/sql/drivers/wsqlitedriver.cpp View File

@@ -21,9 +21,8 @@
21 21
 #include "wsqlforeignkey.h"
22 22
 
23 23
 #include <iostream>
24
-#include <boost/algorithm/string.hpp>
25 24
 
26
-#define ROWENDTAG "-*-"
25
+#define LOCALDEBUG 0
27 26
 
28 27
 namespace WSql
29 28
 {
@@ -65,22 +64,20 @@ namespace WSql
65 64
 /*! \internal - dont use this.*/
66 65
 bool isForeignKeyDefinition ( std::string sql )
67 66
 {
68
-	boost::to_upper ( sql );
69
-	return ( sql.find ( "FOREIGN KEY" ) != std::string::npos );
67
+	return ( WSqlDataType::iFind (sql, "FOREIGN KEY" ) != std::string::npos );
70 68
 }
71 69
 /*! \internal - dont use this.*/
72 70
 bool isIndexDefinition ( std::string sql )
73 71
 {
74
-	boost::to_upper ( sql );
75
-	return ( boost::istarts_with ( sql, "UNIQUE" )
76
-			 || boost::istarts_with ( sql, "PRIMARY KEY" )
77
-			 || boost::istarts_with ( sql, "INDEX" )
78
-			 || boost::istarts_with ( sql, "CREATE INDEX" )
79
-			 || boost::istarts_with ( sql, "CREATE PRIMARY KEY" )
80
-			 || boost::istarts_with ( sql, "CREATE UNIQUE" )
81
-			 || boost::istarts_with ( sql, "CONSTRAINT INDEX" )
82
-			 || boost::istarts_with ( sql, "CONSTRAINT UNIQUE" )
83
-			 || boost::istarts_with ( sql, "CONSTRAINT PRIMARY KEY" )
72
+	return ( WSqlDataType::iFind(sql, "UNIQUE" ) == 0
73
+			 || WSqlDataType::iFind(sql, "PRIMARY KEY" ) == 0
74
+			 || WSqlDataType::iFind(sql, "INDEX" ) == 0
75
+			 || WSqlDataType::iFind(sql, "CREATE INDEX" ) == 0
76
+			 || WSqlDataType::iFind(sql, "CREATE PRIMARY KEY" ) == 0
77
+			 || WSqlDataType::iFind(sql, "CREATE UNIQUE" ) == 0
78
+			 || WSqlDataType::iFind(sql, "CONSTRAINT INDEX" ) == 0
79
+			 || WSqlDataType::iFind(sql, "CONSTRAINT UNIQUE" ) == 0
80
+			 || WSqlDataType::iFind(sql, "CONSTRAINT PRIMARY KEY" ) == 0
84 81
 		   );
85 82
 }
86 83
 
@@ -94,9 +91,9 @@ WSqlForeignKey createForeignKey ( std::string sqldef )
94 91
 	while ( pos < sz ) //sqlite is case insensitive ..
95 92
 		sqldef[pos] = tolower ( sqldef[pos++] );
96 93
 
97
-//    std::cerr << "FK def: *" << sqldef << "*" << std::endl;
94
+    if(LOCALDEBUG) std::cout << "FK def: *" << sqldef << "*" << std::endl;
98 95
 	//constraint "fk_comment_post" foreign key ("post_id") references "post" ("id")
99
-	boost::trim_if ( sqldef, boost::is_any_of ( "\n\t " ) );
96
+	WSqlDataType::trim ( sqldef );
100 97
 
101 98
 	size_t start = sqldef.find_first_of ( "(" );
102 99
 	size_t end = sqldef.find_first_of ( ")", start );
@@ -104,8 +101,8 @@ WSqlForeignKey createForeignKey ( std::string sqldef )
104 101
 	if ( std::string::npos != start && std::string::npos != end )
105 102
 	{
106 103
 		std::string tmp = sqldef.substr ( start + 1, ( end - start ) - 1 );
107
-		boost::trim_if ( tmp, boost::is_any_of ( " '\"[]" ) );
108
-//        std::cerr << " column: trimmed *" << tmp << "*" <<  std::endl;
104
+		WSqlDataType::trim( tmp, std::string(" '\"[]") );
105
+		if(LOCALDEBUG) std::cerr << " column: trimmed *" << tmp << "*" <<  std::endl;
109 106
 		start = sqldef.find_first_of ( "(", end );
110 107
 		end = sqldef.find_first_of ( ")", start );
111 108
 		fkToReturn.setColumnName ( tmp );
@@ -113,8 +110,8 @@ WSqlForeignKey createForeignKey ( std::string sqldef )
113 110
 		if ( std::string::npos != start && std::string::npos != end )
114 111
 		{
115 112
 			std::string tmp2 = sqldef.substr ( start + 1, ( end - start ) - 1 );
116
-			boost::trim_if ( tmp2, boost::is_any_of ( " '\"[]" ) );
117
-//            std::cerr << "target column: trimmed *" << tmp2 << "*" <<  std::endl;
113
+			WSqlDataType::trim( tmp2, std::string(" '\"[]") );
114
+			if(LOCALDEBUG) std::cerr << "target column: trimmed *" << tmp2 << "*" <<  std::endl;
118 115
 			fkToReturn.setReferencedColumnName ( tmp2 );
119 116
 		}
120 117
 	}
@@ -128,8 +125,8 @@ WSqlForeignKey createForeignKey ( std::string sqldef )
128 125
 		start += 10;
129 126
 		end = sqldef.find ( "(", start );
130 127
 		std::string tmp3 = sqldef.substr ( start, ( end - start ) - 1 );
131
-		boost::trim_if ( tmp3, boost::is_any_of ( " '\"[]" ) );
132
-//        std::cerr << "== references table: trimmed *" << tmp3 << "*" <<  std::endl;
128
+		WSqlDataType::trim(tmp3, std::string(" '\"[]"));
129
+		if(LOCALDEBUG) std::cerr << "== references table: trimmed *" << tmp3 << "*" <<  std::endl;
133 130
 		fkToReturn.setReferencedTableName ( tmp3 );
134 131
 	}
135 132
 	else
@@ -142,8 +139,8 @@ WSqlForeignKey createForeignKey ( std::string sqldef )
142 139
 		start = sqldef.find_first_of ( "'\"" );
143 140
 		end = sqldef.find_first_of ( "'\"", start + 1 );
144 141
 		std::string tmp4 = sqldef.substr ( start, ( end - start ) - 1 );
145
-		boost::trim_if ( tmp4, boost::is_any_of ( " '\"[]" ) );
146
-//        std::cerr << "constraint name: trimmed *" << tmp4 << "*" <<  std::endl;
142
+		WSqlDataType::trim(tmp4, std::string(" '\"[]"));
143
+		if(LOCALDEBUG) std::cerr << "constraint name: trimmed *" << tmp4 << "*" <<  std::endl;
147 144
 		fkToReturn.setKeyName ( tmp4 );
148 145
 	}
149 146
 
@@ -166,10 +163,10 @@ void splitIntoDefinitions ( std::vector<std::string> &vecToFill, std::string sql
166 163
 		if ( sql[pos] == ',' )
167 164
 		{
168 165
 			std::string part = sql.substr ( 0, pos );
169
-			boost::trim ( part );
166
+			WSqlDataType::trim(part);
170 167
 			vecToFill.push_back ( part );
171 168
 			sql.erase ( 0, pos + 1 );
172
-			boost::trim ( sql );
169
+			WSqlDataType::trim(sql);
173 170
 			max = sql.size();
174 171
 			pos = 0;
175 172
 		}
@@ -185,8 +182,7 @@ void splitIntoDefinitions ( std::vector<std::string> &vecToFill, std::string sql
185 182
  */
186 183
 WSqlDataType::Type WSqliteDriver::sqlite3TypeToWSqlType ( std::string tname ) const
187 184
 {
188
-	boost::to_lower ( tname );
189
-
185
+	WSqlDataType::toLower(tname);
190 186
 	//note - this includes "bigint"; that would be stored as an "integer" in sqlite
191 187
 	if ( tname.find ( "int" ) != std::string::npos )
192 188
 		return WSqlDataType::INT;
@@ -464,8 +460,7 @@ WSqlTable WSqliteDriver::tableMetaData ( const std::string &tableName )
464 460
 		return tblToReturn;
465 461
 
466 462
 	//parse and store info from the create statement ..
467
-	std::string sqlToParse = fetchTableCreateStatement ( tableName );
468
-	parseSchema ( sqlToParse );
463
+	parseSchema ( fetchTableCreateStatement ( tableName ) );
469 464
 
470 465
 	sqlite3_stmt *statement;
471 466
 	std::string col_descript;
@@ -545,21 +540,20 @@ bool WSqliteDriver::columnIsAutoIncrement ( const std::string &columnname ) cons
545 540
 		return false;
546 541
 
547 542
 	std::string col_definition = it->second;
548
-	boost::to_lower ( col_definition );
543
+	WSqlDataType::toLower ( col_definition );
549 544
 
550 545
 	if ( col_definition.find ( "autoincrement" ) != std::string::npos
551
-			|| col_definition.find ( "auto_increment" ) != std::string::npos
552
-	   )
546
+			|| col_definition.find ( "auto_increment" ) != std::string::npos )
553 547
 		return true;
554 548
 
555 549
 	return false;
556 550
 }
557 551
 
558 552
 /*! \internal - dont use this.*/
559
-std::string WSqliteDriver::fetchTableCreateStatement ( const std::string &tablename ) const
553
+std::vector< std::string > WSqliteDriver::fetchTableCreateStatement ( const std::string &tablename ) const
560 554
 {
561 555
 	sqlite3_stmt *statement;
562
-	std::string sqlToReturn;
556
+	std::vector< std::string > vecToReturn;
563 557
 	std::string sql ( "SELECT sql from sqlite_master WHERE tbl_name = '" );
564 558
 	sql.append ( tablename );
565 559
 	sql.append ( "';" );
@@ -571,24 +565,17 @@ std::string WSqliteDriver::fetchTableCreateStatement ( const std::string &tablen
571 565
 			const unsigned char *safety = sqlite3_column_text ( statement, 0 );
572 566
 
573 567
 			if ( safety && SQLITE_ERROR != *safety )
574
-			{
575
-				sqlToReturn.append ( ( char * ) safety );
576
-				sqlToReturn.append ( ROWENDTAG );
577
-			}
568
+				vecToReturn.push_back(std::string( (char*) safety ) );
578 569
 			else
579
-			{
580 570
 				//this is quite weird - empty rows ..
581 571
 				std::cerr << "fetchTableCreateStatement - sqlite weirdness: " << tablename << std::endl;
582 572
 				//std::cerr <<  sqlite3_errmsg( _objSqlite ) << std::endl;
583
-			}
584
-
585
-			//??usleep();
586 573
 		}
587 574
 
588 575
 		sqlite3_finalize ( statement );
589 576
 	}
590 577
 
591
-	return sqlToReturn;
578
+	return vecToReturn;
592 579
 }
593 580
 
594 581
 /*! \internal - dont use this.*/
@@ -604,35 +591,41 @@ std::string WSqliteDriver::extractStatement ( const std::string &sqlToParse, con
604 591
 		return sqlToReturn;
605 592
 
606 593
 	sqlToReturn = sqlToParse.substr ( pos_start + 1, pos_end - ( pos_start + 1 ) );
607
-//    std::cerr << "extract Statement sqlToReturn: " << sqlToReturn << std::endl;
594
+	if(LOCALDEBUG) std::cout << "extract Statement sqlToReturn: " << sqlToReturn << std::endl;
608 595
 	return sqlToReturn;
609 596
 }
610 597
 
611 598
 //eh, not graceful but mostly works
612 599
 /*! \internal - dont use this. This parses the create statement for a table ..*/
613
-void WSqliteDriver::parseSchema ( std::string &sql )
614
-{
600
+void WSqliteDriver::parseSchema ( std::vector<std::string>  statements )
601
+{					
615 602
 	typedef std::vector<std::string>::iterator Iter;
616
-	std::vector<std::string> statements;  //complete statements in parens
617 603
 	std::vector<std::string> definitions;  //comma separated column defs
618 604
 
619 605
 	std::vector<std::string> columns;      //stored split off columns, constraints, indices
620 606
 	std::vector<std::string> indices;
621 607
 
622
-	boost::trim_if ( sql, boost::is_any_of ( "-*" ) );
623
-	boost::split ( statements, sql,  boost::is_any_of ( "-*" ), boost::token_compress_on );
624 608
 	Iter stmt_it = statements.begin();
625 609
 
626 610
 	for ( ; stmt_it != statements.end(); ++stmt_it )
627 611
 	{
628 612
 		std::string cur_statement =  *stmt_it;
629
-		boost::trim ( cur_statement );
630
-
613
+		if(LOCALDEBUG) std::cout << "************** STATEMENT (FULL) ***************" << std::endl 
614
+						<< "cur_statement: *" << cur_statement << "*" << std::endl;
615
+		
616
+		WSqlDataType::trim(cur_statement);
617
+
618
+		if(LOCALDEBUG) std::cout << "************** STATEMENT (TRIMMED) ***************" << std::endl 
619
+						<< "cur_statement: " << cur_statement << std::endl;
620
+		
631 621
 		//get statement between parens - but only for the first "CREATE";
632 622
 		//thus avoid extracting primary key definitions like (x_id,y_id)
633
-		if ( boost::istarts_with ( cur_statement, "CREATE TABLE" ) )
623
+		if ( WSqlDataType::iFind ( cur_statement, "CREATE TABLE" ) == 0 )
634 624
 			cur_statement = extractStatement ( cur_statement );
635 625
 
626
+		if (LOCALDEBUG) std::cout << "************** STATEMENT (extracted) ***************" << std::endl 
627
+						<< "cur_statement: " << cur_statement << std::endl;
628
+
636 629
 		//cut up by line -comma separated column definitions
637 630
 		splitIntoDefinitions ( definitions, cur_statement );
638 631
 		Iter defs_it = definitions.begin();
@@ -640,20 +633,23 @@ void WSqliteDriver::parseSchema ( std::string &sql )
640 633
 		for ( ; defs_it != definitions.end(); ++defs_it )
641 634
 		{
642 635
 			std::string cur_definition = *defs_it;
643
-			boost::trim ( cur_definition );
636
+			WSqlDataType::trim(cur_definition);
637
+
638
+			if (LOCALDEBUG) std::cout << "************** CURRENT DEFINITION ***************"  << std::endl
639
+							<< "cur_definition: " << cur_definition << std::endl;
644 640
 
645 641
 			if ( isForeignKeyDefinition ( cur_definition ) )
646 642
 			{
647
-				/*                std::cout << "cur_definition: " << cur_definition << std::endl
648
-				                    << "************** FOREIGN KEY ***************" << std::endl;*/
643
+				if (LOCALDEBUG) std::cout << "************** FOREIGN KEY ***************"  << std::endl
644
+								<< "cur_definition: " << cur_definition << std::endl;
649 645
 				WSqlForeignKey fk = createForeignKey ( cur_definition );
650 646
 				_foreign_keys.push_back ( fk );
651 647
 			}
652 648
 			else
653 649
 				if ( isIndexDefinition ( cur_definition ) )
654 650
 				{
655
-					/*                std::cout << "cur_definition: " << cur_definition << std::endl
656
-					                << "************** INDEX ***************" << std::endl;*/
651
+					if (LOCALDEBUG) std::cout << "************** INDEX ***************" << std::endl
652
+									<< "cur_definition: " << cur_definition << std::endl;
657 653
 					indices.push_back ( cur_definition );
658 654
 				}
659 655
 				else
@@ -680,9 +676,10 @@ void WSqliteDriver::mapColumns ( std::vector<std::string> &vecColumnDefinitions
680 676
 		if ( pos != std::string::npos )
681 677
 		{
682 678
 			std::string cur_colname = cur_definition.substr ( 0, pos );
683
-			boost::trim_if ( cur_colname, boost::is_any_of ( "\n\t []`'\"" ) );
679
+			WSqlDataType::trim( cur_colname, std::string( "\n\t []`'\"" ) );
684 680
 			_columns_map[cur_colname] = cur_definition.erase ( 0, pos + 1 );
685 681
 		}
686 682
 	}
687 683
 }
684
+
688 685
 }//namespace WSql

+ 4
- 2
src/sql/drivers/wsqlitedriver.h View File

@@ -52,11 +52,13 @@ class WSqliteDriver : public WSqlDriver
52 52
 
53 53
         WSqlDataType::Type sqlite3TypeToWSqlType( std::string tname) const;
54 54
         WSqlDataType::Type sqlite3TypeToWSqlType(int dtype)const;
55
-        std::string fetchTableCreateStatement(const std::string& tablename)const;
55
+//        std::string fetchTableCreateStatement(const std::string& tablename)const;
56
+        std::vector<std::string> fetchTableCreateStatement(const std::string& tablename)const;
56 57
         std::string extractStatement(const std::string& sql, const char start='(', const char end=')') const;        
57
-        void parseSchema( std::string& sql);
58
+        void parseSchema( std::vector< std::string > sql );
58 59
         bool columnIsAutoIncrement(const std::string& columnname)const;
59 60
         void mapColumns(std::vector<std::string> &column_definitions);
61
+		void sql ( const char *arg1 );
60 62
         //temporary buffers; cleared after each metatable init ..
61 63
         std::map<std::string, std::string> _columns_map;
62 64
         std::vector<WSqlForeignKey> _foreign_keys;

+ 361
- 225
src/sql/wsqldatatype.h View File

@@ -21,235 +21,371 @@
21 21
 #define WSQLDATATYPE_H
22 22
 
23 23
 #include <string>
24
-#include <boost/algorithm/string.hpp>
25 24
 #include <iostream>
25
+#include <algorithm>
26 26
 
27
-namespace WSql {
28
-
29
-    /*! \namespace WSql::WSqlDataType 
30
-     * \brief WSqlDataType namespace - Utilities and definitions of supported data types
31
-     * 
32
-     * This is a container for type flags and convenience functions for the supported
33
-     * SQL datatypes. In this namespace are definitions for datatypes, facilities for 
34
-     * translating these to and from other naming conventions as well as facilities for
35
-     * generating transformations of datatypes into various strings used in the ORM
36
-     * generating classes.
37
-     * 
38
-     * This provides a central utility namespace for transformations and definitions
39
-     * related to data types as defined in DBMSs and C++, including ORM mapping
40
-     * of table names to class names, column names and types to variable names and
41
-     * types, etc.
42
-     * 
43
-     * Below is a list the ANSI SQl standard types supported by WSQL - these will be 
44
-     * mapped to native C++ data types in ORM class generation.  For example  a 
45
-     * TINYINT column will declared as a member of type "short", a VARCHAR or 
46
-     * TEXT as type std::string, a DECIMAL to a double, etc. Implementers of drivers 
47
-     * can use this as a guide for translating types for a particular DBMS.
48
-     *
49
-     * Writers of drivers must translate any proprietary or other data types specific to the
50
-     * DBMS of the driver to these types. Most DBMS metadata is returned in a string identifier
51
-     * of one of these types and can usually be mapped conveniently by using the functions 
52
-     * toString(type) or toType(string).
53
-     *  
54
-     * See the following for more information on the specific data types:
55
-     * \include datatypes.txt
56
-     * 
57
-     * \ingroup WSql
58
-     * 
59
-     */
60
-    
61
-    namespace WSqlDataType {
62
-    
63
-    
64
-    /*!\enum Type - flags representing data types
65
-     * The types currently supported - adjust this if/when new strings
66
-     * are added.
67
-     */
68
-    enum Type {
69
-        NOTYPE = 0,
70
-        TINYINT,
71
-        SMALLINT,
72
-        MEDIUMINT,
73
-        INT,
74
-        BIGINT,
75
-        FLOAT,
76
-        DOUBLE,
77
-        DECIMAL,
78
-        DATE,
79
-        DATETIME,
80
-        YEAR,
81
-        TIME,
82
-        TIMESTAMP,
83
-        TIMESTAMPTZ,
84
-        CHAR,
85
-        VARCHAR,
86
-        NCHAR,
87
-        NVARCHAR,
88
-        TEXT,
89
-        TINYTEXT,
90
-        MEDIUMTEXT,
91
-        LONGTEXT,
92
-        ENUM,
93
-        SET,
94
-        BLOB
95
-    };
96
-    /*! \a TypeNames - array of strings representing data types
97
-     * The types currently supported in handy string format - adjust this if/when new strings
98
-     * are added.
99
-     */
100
-    static const char * const TypeNames[] ={
101
-        "NOTYPE",
102
-        "TINYINT",
103
-        "SMALLINT",
104
-        "MEDIUMINT",
105
-        "INT",
106
-        "BIGINT",
107
-        "FLOAT",
108
-        "DOUBLE",
109
-        "DECIMAL",
110
-        "DATE",
111
-        "DATETIME",
112
-        "TIME",
113
-        "YEAR",
114
-        "TIMESTAMP",
115
-        "TIMESTAMPTZ",
116
-        "CHAR",
117
-        "VARCHAR",
118
-        "NCHAR",
119
-        "NVARCHAR",
120
-        "TEXT",
121
-        "TINYTEXT",
122
-        "MEDIUMTEXT",
123
-        "LONGTEXT",
124
-        "ENUM",
125
-        "SET",
126
-        "BLOB"
127
-    };
128
-    
129
-    //! Number of types supported. \note Change this if you add types!!
130
-    static const unsigned short number_of_datatypes = 26;
131
-    
132
-    //! Covenience function - returns a string for the type
133
-    static std::string toString(Type type)
134
-    {
135
-        std::string strToReturn;
136
-        if (type < 0 || type > (number_of_datatypes - 1))
137
-            strToReturn = "INVALID";
138
-        else
139
-            strToReturn = TypeNames[type]; //careful .. dont mess this up, add types and name in order.
140
-        return strToReturn;
141
-    }
142
-    
143
-    //! Convenience function - translates a string to a type flag
144
-    static Type toType(std::string name)
145
-    {
146
-        boost::to_upper(name);
147
-        boost::trim(name);
148
-        //!\todo intelligence - support more type names, translate to ours ..
149
-        int i = 0;
150
-        for ( ; i < number_of_datatypes; ++i)
151
-            if ( name.compare(TypeNames[i]) == 0 )
152
-                return static_cast<Type>(i);
153
-        return static_cast<Type>(0);//NOTYPE
154
-    }
155
-    
156
-    //! Attempt to return a singularized form of \a name
157
-    static std::string toSingular(const std::string& name)
158
-    {
159
-        std::string strToReturn = name;
160
-        size_t size = strToReturn.size();
161
-        if(!size)
162
-            return strToReturn;
163
-        if('s' == strToReturn[size-1] && 's' != strToReturn[size-2])//dont fix dress, address ..
164
-        {
165
-            strToReturn.erase(size-1);
166
-            if('e' == strToReturn[size-2])
167
-            {//eg. Cities to City ..
168
-                if( 'i' == strToReturn[size-3])
169
-                {
170
-                    strToReturn.erase(size-3);
171
-                    strToReturn.append("y");
172
-                }else if( 'h' == strToReturn[size-3])//eg. bushes .. might need fixing ..
173
-                    strToReturn.erase(size-2);                
174
-            }
175
-            return strToReturn;
176
-        }
177
-        /*!\todo add intelligence:        std::string cmp = boost::to_lower_copy(strToReturn);
178
-         *        if(cmp.compare("people") .. or some such ..*/
179
-        return strToReturn;
180
-    }
181
-    
182
-    //! Attempt to return a pluralized form of \a name
183
-    static std::string toPlural(const std::string& name)
184
-    {
185
-        std::string strToReturn = name;
186
-        size_t sz = name.size();
187
-        if(sz && 's' == strToReturn[sz - 1])
188
-            strToReturn.append("es");
189
-        else if(sz > 2 && 'y' == strToReturn[sz - 1]
190
-            && 'o' != strToReturn[sz - 2]
191
-            && 'a' != strToReturn[sz - 2])
192
-        {
193
-                strToReturn.erase(sz - 1);
194
-                strToReturn.append("ies");
195
-        }
196
-        else
197
-            strToReturn.append("s");
198
-        //!\todo make me a little smarter .. people, fish, sheep etc.
199
-        return strToReturn;
200
-    }
201
-    
202
-    /*! \brief Returns a suitable variable name transformed from \a columnname
203
-     *     
204
-     *     This translates a column name as defined in a database to a variable name.
205
-     *     A column name should have the format "name" or "some_name", eg. "user" or 
206
-     *     "order_id" - these will be rendered as "user" and "orderId". Note that in contrast 
207
-     *     to tableNameToClass() the first letter is not capitalized and plural are left plural.
208
-     *     
209
-     *     \param std::string - columnname - the name to transform
210
-     *     \retval std::string - a string suitable for a variable name
211
-     */
212
-    static std::string columnNameToVariable(const std::string& columnname)
213
-    {
214
-        std::string strToReturn = columnname;
215
-        size_t pos = 0;
216
-        pos = strToReturn.find('_');
217
-        while(pos != std::string::npos)
218
-        {
219
-            strToReturn.erase(pos,1);
220
-            if((pos + 1) < strToReturn.size())
221
-                strToReturn[pos]= toupper(strToReturn[pos]);
222
-            pos = strToReturn.find('_');
223
-        }
224
-        return strToReturn;
225
-    }
226
-    
227
-    /*! \brief Returns a transformed table name as a class name
228
-     *     
229
-     *     This translates a table name as defined in a database to a class name.
230
-     *     A table name should have the format "names" or "some_names", eg. "users" or 
231
-     *     "phone_numbers" - these will be rendered as "User" and "PhoneNumber".
232
-     *     Note that in keeping with accepted convention the table names are plural;
233
-     *     these will also be singularized; this results in the table "orders" being 
234
-     *     rendered as "Order" and "order_items" as "OrderItem"
235
-     * 
236
-     *     \note This assumes that tables are named according to convention as
237
-     *      found also in Rails - tablenames without this convention are left as
238
-     *      is - they will be rendered  but may cause problems with class instance 
239
-     *     declarations in generated output.    
240
-     * 
241
-     *     \param std::string tablename - the name to transform
242
-     *     \retval std::string - a string suitable for a class name
243
-     */
244
-    static std::string tableNameToClass(const std::string& tablename)
245
-    {
246
-        std::string strToReturn = toSingular(tablename);
247
-        strToReturn[0] = toupper(strToReturn[0]);
248
-        return columnNameToVariable(strToReturn);
249
-    }
27
+namespace WSql
28
+{
29
+
30
+/*! \namespace WSql::WSqlDataType
31
+ * \brief WSqlDataType namespace - Utilities and definitions of supported data types
32
+ *
33
+ * This is a container for type flags and convenience functions for the supported
34
+ * SQL datatypes. In this namespace are definitions for datatypes, facilities for
35
+ * translating these to and from other naming conventions as well as facilities for
36
+ * generating transformations of datatypes into various strings used in the ORM
37
+ * generating classes.
38
+ *
39
+ * This provides a central utility namespace for transformations and definitions
40
+ * related to data types as defined in DBMSs and C++, including ORM mapping
41
+ * of table names to class names, column names and types to variable names and
42
+ * types, etc.
43
+ *
44
+ * Below is a list the ANSI SQl standard types supported by WSQL - these will be
45
+ * mapped to native C++ data types in ORM class generation.  For example  a
46
+ * TINYINT column will declared as a member of type "short", a VARCHAR or
47
+ * TEXT as type std::string, a DECIMAL to a double, etc. Implementers of drivers
48
+ * can use this as a guide for translating types for a particular DBMS.
49
+ *
50
+ * Writers of drivers must translate any proprietary or other data types specific to the
51
+ * DBMS of the driver to these types. Most DBMS metadata is returned in a string identifier
52
+ * of one of these types and can usually be mapped conveniently by using the functions
53
+ * toString(type) or toType(string).
54
+ *
55
+ * See the following for more information on the specific data types:
56
+ * \include datatypes.txt
57
+ *
58
+ * \ingroup WSql
59
+ *
60
+ */
61
+
62
+namespace WSqlDataType
63
+{
64
+
65
+/*!\enum Type - flags representing data types
66
+ * The types currently supported - adjust this if/when new strings
67
+ * are added.
68
+ */
69
+enum Type
70
+{
71
+	NOTYPE = 0,
72
+	TINYINT,
73
+	SMALLINT,
74
+	MEDIUMINT,
75
+	INT,
76
+	BIGINT,
77
+	FLOAT,
78
+	DOUBLE,
79
+	DECIMAL,
80
+	DATE,
81
+	DATETIME,
82
+	YEAR,
83
+	TIME,
84
+	TIMESTAMP,
85
+	TIMESTAMPTZ,
86
+	CHAR,
87
+	VARCHAR,
88
+	NCHAR,
89
+	NVARCHAR,
90
+	TEXT,
91
+	TINYTEXT,
92
+	MEDIUMTEXT,
93
+	LONGTEXT,
94
+	ENUM,
95
+	SET,
96
+	BLOB
97
+};
98
+/*! \a TypeNames - array of strings representing data types
99
+ * The types currently supported in handy string format - adjust this if/when new strings
100
+ * are added.
101
+ */
102
+static const char *const TypeNames[] =
103
+{
104
+	"NOTYPE",
105
+	"TINYINT",
106
+	"SMALLINT",
107
+	"MEDIUMINT",
108
+	"INT",
109
+	"BIGINT",
110
+	"FLOAT",
111
+	"DOUBLE",
112
+	"DECIMAL",
113
+	"DATE",
114
+	"DATETIME",
115
+	"TIME",
116
+	"YEAR",
117
+	"TIMESTAMP",
118
+	"TIMESTAMPTZ",
119
+	"CHAR",
120
+	"VARCHAR",
121
+	"NCHAR",
122
+	"NVARCHAR",
123
+	"TEXT",
124
+	"TINYTEXT",
125
+	"MEDIUMTEXT",
126
+	"LONGTEXT",
127
+	"ENUM",
128
+	"SET",
129
+	"BLOB"
130
+};
131
+
132
+//! Number of types supported. \note Change this if you add types!!
133
+static const unsigned short number_of_datatypes = 26;
134
+/*! Transform a string to all upper case
135
+ */
136
+static void toUpper ( std::string &s )
137
+{
138
+	std::transform ( s.begin(), s.end(), s.begin(), ::toupper );
139
+}
140
+
141
+/*! Transform a string to all lower case
142
+ */
143
+static void toLower ( std::string &s )
144
+{
145
+	std::transform ( s.begin(), s.end(), s.begin(), ::tolower );
146
+}
147
+
148
+/*! Case insensitive find string in string
149
+ */
150
+static size_t iFind ( std::string haystack, std::string needle, size_t pos = 0 )
151
+{
152
+	toUpper(haystack);
153
+	toUpper(needle);
154
+	return haystack.find ( needle, pos );
155
+}
156
+
157
+/*! Trim whitespace from beginning of string ..
158
+ */
159
+static void lTrim ( std::string &s )
160
+{
161
+	size_t pos = 0;
162
+	size_t len = s.length();
163
+	
164
+	while(pos < len && isspace( s[pos] ) ) 
165
+		pos++;
166
+	if(pos && pos < len)
167
+		s.erase(0, pos);
168
+}
169
+
170
+/*! Trim whitespace from end of string ..
171
+ */
172
+static void rTrim ( std::string &s )
173
+{
174
+	size_t pos = s.length() - 1;
175
+	if(!pos)//ingnore empty strings
176
+		return;
177
+	while( isspace( s[pos] ) ) 
178
+		pos--;
179
+	if(pos != s.length() -1)
180
+		s.erase(pos + 1);
181
+}
182
+
183
+/*! Trim whitespace from string ..
184
+ */
185
+static void trim ( std::string &s )
186
+{
187
+	lTrim(s);
188
+	rTrim(s);
189
+}
190
+
191
+/*! Trim chars in findme from beginning of string s..
192
+ */
193
+static void lTrim ( std::string &s, std::string removeme )
194
+{
195
+	if(removeme.empty())
196
+		return lTrim(s);
197
+	size_t pos = 0;
198
+	size_t len = s.length();
199
+	size_t removeme_len = removeme.length();
200
+
201
+	for(int i = 0; i < removeme_len; i++)
202
+		for(pos = 0; pos < len; pos++)
203
+		{
204
+			if( s[pos] != removeme[i] )
205
+			{
206
+				if(pos)
207
+				{
208
+					s.erase(0, pos);
209
+					len = s.length();
210
+				}
211
+				break;
212
+			}
213
+		}
214
+}
215
+
216
+/*! Trim chars in findme from end of string s..
217
+ */
218
+static void rTrim ( std::string &s, std::string removeme )
219
+{
220
+	if(removeme.empty())
221
+		return rTrim(s);
222
+	size_t pos = 0;
223
+	size_t len = s.length();
224
+	size_t removeme_len = removeme.length();
225
+
226
+	for(int i = 0; i < removeme_len; i++)
227
+		for(pos = len; pos; )
228
+		{
229
+			if( s[--pos] != removeme[i] )
230
+			{
231
+				if(pos != len - 1 )
232
+				{
233
+					s.erase(pos + 1);
234
+					len = s.length();
235
+				}
236
+				break;
237
+			}
238
+		}
239
+}
240
+
241
+/*! Trim chars in removeme from string ..
242
+ */
243
+static void trim ( std::string &s, std::string removeme )
244
+{
245
+	lTrim(s, removeme);
246
+	rTrim(s, removeme);
247
+}
248
+
249
+//! Covenience function - returns a string for the type
250
+static std::string toString ( Type type )
251
+{
252
+	std::string strToReturn;
253
+
254
+	if ( type < 0 || type > ( number_of_datatypes - 1 ) )
255
+		strToReturn = "INVALID";
256
+	else
257
+		strToReturn = TypeNames[type]; //careful .. dont mess this up, add types and name in order.
258
+
259
+	return strToReturn;
260
+}
261
+
262
+//! Convenience function - translates a string to a type flag
263
+static Type toType ( std::string name )
264
+{
265
+	WSqlDataType::toUpper ( name );
266
+	WSqlDataType::trim ( name );
267
+	//!\todo intelligence - support more type names, translate to ours ..
268
+	int i = 0;
269
+
270
+	for ( ; i < number_of_datatypes; ++i )
271
+		if ( name.compare ( TypeNames[i] ) == 0 )
272
+			return static_cast<Type> ( i );
273
+
274
+	return static_cast<Type> ( 0 ); //NOTYPE
275
+}
276
+
277
+//! Attempt to return a singularized form of \a name
278
+static std::string toSingular ( const std::string &name )
279
+{
280
+	std::string strToReturn = name;
281
+	size_t size = strToReturn.size();
282
+
283
+	if ( !size )
284
+		return strToReturn;
285
+
286
+	if ( 's' == strToReturn[size - 1] && 's' != strToReturn[size - 2] ) //dont fix dress, address ..
287
+	{
288
+		strToReturn.erase ( size - 1 );
289
+
290
+		if ( 'e' == strToReturn[size - 2] )
291
+		{
292
+			//eg. Cities to City ..
293
+			if ( 'i' == strToReturn[size - 3] )
294
+			{
295
+				strToReturn.erase ( size - 3 );
296
+				strToReturn.append ( "y" );
297
+			}
298
+			else
299
+				if ( 'h' == strToReturn[size - 3] ) //eg. bushes .. might need fixing ..
300
+					strToReturn.erase ( size - 2 );
301
+		}
302
+
303
+		return strToReturn;
304
+	}
305
+
306
+	/*!\todo add intelligence:        std::string cmp = to_lower(strToReturn);
307
+	 *        if(cmp.compare("people") .. or some such ..*/
308
+	return strToReturn;
309
+}
310
+
311
+//! Attempt to return a pluralized form of \a name
312
+static std::string toPlural ( const std::string &name )
313
+{
314
+	std::string strToReturn = name;
315
+	size_t sz = name.size();
316
+
317
+	if ( sz && 's' == strToReturn[sz - 1] )
318
+		strToReturn.append ( "es" );
319
+	else
320
+		if ( sz > 2 && 'y' == strToReturn[sz - 1]
321
+				&& 'o' != strToReturn[sz - 2]
322
+				&& 'a' != strToReturn[sz - 2] )
323
+		{
324
+			strToReturn.erase ( sz - 1 );
325
+			strToReturn.append ( "ies" );
326
+		}
327
+		else
328
+			strToReturn.append ( "s" );
329
+
330
+	//!\todo make me a little smarter .. people, fish, sheep etc.
331
+	return strToReturn;
332
+}
333
+
334
+/*! \brief Returns a suitable variable name transformed from \a columnname
335
+ *
336
+ *     This translates a column name as defined in a database to a variable name.
337
+ *     A column name should have the format "name" or "some_name", eg. "user" or
338
+ *     "order_id" - these will be rendered as "user" and "orderId". Note that in contrast
339
+ *     to tableNameToClass() the first letter is not capitalized and plural are left plural.
340
+ *
341
+ *     \param std::string - columnname - the name to transform
342
+ *     \retval std::string - a string suitable for a variable name
343
+ */
344
+static std::string columnNameToVariable ( const std::string &columnname )
345
+{
346
+	std::string strToReturn = columnname;
347
+	size_t pos = 0;
348
+	pos = strToReturn.find ( '_' );
349
+
350
+	while ( pos != std::string::npos )
351
+	{
352
+		strToReturn.erase ( pos, 1 );
353
+
354
+		if ( ( pos + 1 ) < strToReturn.size() )
355
+			strToReturn[pos] = toupper ( strToReturn[pos] );
356
+
357
+		pos = strToReturn.find ( '_' );
358
+	}
359
+
360
+	return strToReturn;
361
+}
362
+
363
+/*! \brief Returns a transformed table name as a class name
364
+ *
365
+ *     This translates a table name as defined in a database to a class name.
366
+ *     A table name should have the format "names" or "some_names", eg. "users" or
367
+ *     "phone_numbers" - these will be rendered as "User" and "PhoneNumber".
368
+ *     Note that in keeping with accepted convention the table names are plural;
369
+ *     these will also be singularized; this results in the table "orders" being
370
+ *     rendered as "Order" and "order_items" as "OrderItem"
371
+ *
372
+ *     \note This assumes that tables are named according to convention as
373
+ *      found also in Rails - tablenames without this convention are left as
374
+ *      is - they will be rendered  but may cause problems with class instance
375
+ *     declarations in generated output.
376
+ *
377
+ *     \param std::string tablename - the name to transform
378
+ *     \retval std::string - a string suitable for a class name
379
+ */
380
+static std::string tableNameToClass ( const std::string &tablename )
381
+{
382
+	std::string strToReturn = toSingular ( tablename );
383
+	strToReturn[0] = toupper ( strToReturn[0] );
384
+	return columnNameToVariable ( strToReturn );
385
+}
250 386
 
251 387
 } //namespace WSqlDataType
252
-    
388
+
253 389
 }// namespace WSql
254 390
 
255 391
 #endif // WSQLDATATYPE_H

+ 3
- 4
src/sql/wsqldatum.cpp View File

@@ -28,10 +28,9 @@ namespace WSql
28 28
  *    be instatiated to hold the types supported by WSqlDataType. It includes methods for conversion
29 29
  *   to various types on demand.
30 30
  *
31
- * \todo - resolve: whether to use boost::any instead of string for internal storage .. or, revert to the
32
- * previous void pointer version?  why? unsure of data integrity, eg. blob to string, longlong, etc .. contrary
33
- * to initial assumptions, some dbms may return types in the api (sqlite?) rather than string reps thereof.
34
- * regardless, blob is another issue, may be huge .. or streamable .. think on this.
31
+ * \todo - resolve:  revert to the previous void pointer version?  why? unsure of data integrity, eg. blob to string, longlong, 
32
+ * etc .. contrary to initial assumptions, some dbms may return types in the api (sqlite?) rather than string reps thereof.
33
+ * regardless, blob is another issue
35 34
  *
36 35
  *    \ingroup WSql
37 36
  *    \sa WSqlDataType WSqlField WSqlColumn

+ 39
- 45
src/sql/wsqldatum.h View File

@@ -20,7 +20,7 @@
20 20
 #define WSQLDATUM_H
21 21
 
22 22
 #include <string>
23
-#include <boost/lexical_cast.hpp>
23
+#include <sstream>
24 24
 
25 25
 namespace WSql
26 26
 {
@@ -28,53 +28,47 @@ namespace WSql
28 28
 class WSqlDatum
29 29
 {
30 30
 
31
-    public:
32
-        WSqlDatum();
33
-        WSqlDatum( const WSqlDatum& other );
34
-        virtual ~WSqlDatum();
35
-        virtual WSqlDatum& operator=( const WSqlDatum& other );
36
-        virtual bool operator==( const WSqlDatum& other ) const;
37
-        inline bool operator!=( const WSqlDatum &other ) const {
38
-            return !operator==( other );
39
-        }
40
-        template <typename T> void setData( const T t ) {
41
-            try {
42
-                _data = boost::lexical_cast<std::string>( t );
43
-            }
44
-            catch ( boost::bad_lexical_cast &e ) {
45
-                //!\todo handle exception
46
-            }
47
-        };
48
-
49
-        template <typename T> T data()const {
50
-            try {
51
-                return boost::lexical_cast<T>( _data );
52
-            }
53
-            catch ( boost::bad_lexical_cast &e ) {
54
-                //!\todo handle exception
55
-                //well, gotta do _something ..
56
-                return T();
57
-            }
58
-        };
59
-
60
-        short toShort()const {return data<short>(); }
61
-        int toInt()const {return data<int>(); }
62
-        long toLong()const {return data<long>(); }
63
-        float toFloat()const {return data<float>(); }
64
-        double toDouble()const {return data<double>(); }
65
-
66
-        unsigned short toUShort()const {return data<unsigned short>(); }
67
-        unsigned int toUInt()const {return data<unsigned int>(); }
68
-        unsigned long toULong()const {return data<unsigned long>(); }
69
-
70
-        std::string toString()const {return data<std::string>(); }
71
-
72
-        void clear();
73
-    private:
74
-        std::string _data;
31
+	public:
32
+		WSqlDatum();
33
+		WSqlDatum( const WSqlDatum& other );
34
+		virtual ~WSqlDatum();
35
+		virtual WSqlDatum& operator=( const WSqlDatum& other );
36
+		virtual bool operator==( const WSqlDatum& other ) const;
37
+		inline bool operator!=( const WSqlDatum &other ) const {
38
+			return !operator==( other );
39
+		}
40
+		template <typename T> void setData( const T t ) {
41
+			_converter << t;
42
+			_data = _converter.str();
43
+		};
44
+
45
+		template <typename T> T data(){
46
+			T result;
47
+			_converter << _data;
48
+			_converter >> result;
49
+			return result;
50
+		};
51
+
52
+		short toShort() {return data<short>(); }
53
+		int toInt() {return data<int>(); }
54
+		long toLong() {return data<long>(); }
55
+		float toFloat() {return data<float>(); }
56
+		double toDouble() {return data<double>(); }
57
+
58
+		unsigned short toUShort() {return data<unsigned short>(); }
59
+		unsigned int toUInt() {return data<unsigned int>(); }
60
+		unsigned long toULong() {return data<unsigned long>(); }
61
+
62
+		std::string toString() {return data<std::string>(); }
63
+
64
+		void clear();
65
+	private:
66
+		std::string _data;
67
+		std::stringstream _converter;
75 68
 
76 69
 };
77 70
 
78 71
 }//namespace WSql
79 72
 #endif // WSQLDATUM_H
80 73
 
74
+

+ 1
- 3
src/sql/wsqlfield.cpp View File

@@ -66,9 +66,7 @@ namespace WSql
66 66
  *    all setting the data with the supported types. Note that the types are coverted to string
67 67
  *    and stored in the WSqlDatum.
68 68
  *
69
- *  \todo maybe should implement deep copy of _data ..? also, missing copy ctor .. this only
70
- * applies if WSqlDatum changes the internal storage from string to boost::any ..
71
- *
69
+ *  \todo maybe should implement deep copy of _data ..? 
72 70
  *
73 71
  *   \ingroup WSql
74 72
  *   \sa data() name() columnName() setData()

Loading…
Cancel
Save