1 /*
2 / Objects.cpp
3 / miscellaneous ancillary classes implementation
4 /
5 / version 1.7, 2013 May 8
6 /
7 / Author: Sandro Furieri a-furieri@lqt.it
8 /
9 / Copyright (C) 2008-2013  Alessandro Furieri
10 /
11 /    This program is free software: you can redistribute it and/or modify
12 /    it under the terms of the GNU General Public License as published by
13 /    the Free Software Foundation, either version 3 of the License, or
14 /    (at your option) any later version.
15 /
16 /    This program is distributed in the hope that it will be useful,
17 /    but WITHOUT ANY WARRANTY; without even the implied warranty of
18 /    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19 /    GNU General Public License for more details.
20 /
21 /    You should have received a copy of the GNU General Public License
22 /    along with this program.  If not, see <http://www.gnu.org/licenses/>.
23 /
24 */
25 
26 #include "Classdef.h"
27 
MyObject(int type,wxString & name)28 MyObject::MyObject(int type, wxString & name)
29 {
30 //
31 // constructor - TreeItemData
32 //
33   Type = type;
34   Name = name;
35   Column = wxT("");
36   DbAlias = wxT("");
37   Temporary = false;
38 }
39 
MyObject(int type,wxString & name,bool tmp)40 MyObject::MyObject(int type, wxString & name, bool tmp)
41 {
42 //
43 // constructor - TreeItemData
44 //
45   Type = type;
46   Name = name;
47   Column = wxT("");
48   DbAlias = wxT("");
49   Temporary = tmp;
50 }
51 
MyObject(int type,wxString & name,wxString & column)52 MyObject::MyObject(int type, wxString & name, wxString & column)
53 {
54 //
55 // constructor - TreeItemData
56 //
57   Type = type;
58   Name = name;
59   Column = column;
60   DbAlias = wxT("");
61   Temporary = false;
62 }
63 
MyObject(int type,bool WXUNUSED (attached),wxString & dbAlias,wxString & name)64 MyObject::MyObject(int type, bool WXUNUSED(attached), wxString & dbAlias,
65                    wxString & name)
66 {
67 //
68 // constructor - TreeItemData
69 //
70   Type = type;
71   Name = name;
72   Column = wxT("");
73   DbAlias = dbAlias;
74   Temporary = false;
75 }
76 
Copy(MyVariant * other)77 void MyVariant::Copy(MyVariant * other)
78 {
79 //
80 // transfers a BLOB value
81 //
82   if (other->Type != MY_BLOB_VARIANT)
83     return;
84   if (!(other->Blob))
85     return;
86   if (Blob)
87     delete[]Blob;
88   Type = MY_BLOB_VARIANT;
89   BlobSize = other->BlobSize;
90   Blob = other->Blob;
91   other->Type = MY_NULL_VARIANT;
92   other->Blob = NULL;
93   other->BlobSize = 0;
94 }
95 
Set(const unsigned char * text)96 void MyVariant::Set(const unsigned char *text)
97 {
98 //
99 // sets a String value for this Variant value
100 //
101   Type = MY_TXT_VARIANT;
102   TxtValue = wxString::FromUTF8((const char *) text);
103 }
104 
Set(const void * blob,int size)105 void MyVariant::Set(const void *blob, int size)
106 {
107 //
108 // sets a BLOB value for this Variant value
109 //
110   if (size <= 0)
111     return;
112   Type = MY_BLOB_VARIANT;
113   BlobSize = size;
114   Blob = new unsigned char[size];
115   memcpy(Blob, blob, size);
116 }
117 
Create(int cols)118 void MyRowVariant::Create(int cols)
119 {
120 //
121 // creating the row variant
122 //
123   if (ColumnArray)
124     delete[]ColumnArray;
125   NumCols = cols;
126   ColumnArray = new MyVariant[NumCols];
127 }
128 
Set(int col,sqlite3_int64 value)129 void MyRowVariant::Set(int col, sqlite3_int64 value)
130 {
131 //
132 // setting an Integer value for the Nth column
133 //
134   MyVariant *var;
135   if (col < 0 || col >= NumCols)
136     return;
137   var = ColumnArray + col;
138   var->Set(value);
139 }
140 
Set(int col,double value)141 void MyRowVariant::Set(int col, double value)
142 {
143 //
144 // setting a Double value for the Nth column
145 //
146   MyVariant *var;
147   if (col < 0 || col >= NumCols)
148     return;
149   var = ColumnArray + col;
150   var->Set(value);
151 }
152 
Set(int col,const unsigned char * value)153 void MyRowVariant::Set(int col, const unsigned char *value)
154 {
155 //
156 // setting a String value for the Nth column
157 //
158   MyVariant *var;
159   if (col < 0 || col >= NumCols)
160     return;
161   var = ColumnArray + col;
162   var->Set(value);
163 }
164 
Set(int col,const void * blob,int size)165 void MyRowVariant::Set(int col, const void *blob, int size)
166 {
167 //
168 // setting a BLOB value for the Nth column
169 //
170   MyVariant *var;
171   if (col < 0 || col >= NumCols)
172     return;
173   var = ColumnArray + col;
174   var->Set(blob, size);
175 }
176 
GetColumn(int col)177 MyVariant *MyRowVariant::GetColumn(int col)
178 {
179 //
180 // returns a Column Variant Value
181 //
182   MyVariant *var;
183   if (col < 0 || col >= NumCols)
184     return NULL;
185   var = ColumnArray + col;
186   return var;
187 }
188 
MyVariantList()189 MyVariantList::MyVariantList()
190 {
191 //
192 // constructor - result set container
193 //
194   NumCols = 0;
195   ColumnName = NULL;
196   First = NULL;
197   Last = NULL;
198 }
199 
~MyVariantList()200 MyVariantList::~MyVariantList()
201 {
202 //
203 // destructor - result set container
204 //
205   Reset();
206 }
207 
Reset(void)208 void MyVariantList::Reset(void)
209 {
210 // resetting the list to the initial (empty) state
211   MyRowVariant *el;
212   MyRowVariant *elN;
213   if (ColumnName)
214     delete[]ColumnName;
215   el = First;
216   while (el)
217     {
218       elN = el->GetNext();
219       delete el;
220       el = elN;
221     }
222   NumCols = 0;
223   ColumnName = NULL;
224   First = NULL;
225   Last = NULL;
226 }
227 
GetRows()228 int MyVariantList::GetRows()
229 {
230 //
231 // counting how many rows are there
232 //
233   int cnt = 0;
234   MyRowVariant *el = First;
235   while (el)
236     {
237       cnt++;
238       el = el->GetNext();
239     }
240   return cnt;
241 }
242 
Add(int columns)243 MyRowVariant *MyVariantList::Add(int columns)
244 {
245 //
246 // adds a row into the result set
247 //
248   if (!NumCols)
249     {
250       NumCols = columns;
251       ColumnName = new wxString[NumCols];
252     }
253   MyRowVariant *el = new MyRowVariant(columns);
254   if (!First)
255     First = el;
256   if (Last)
257     Last->SetNext(el);
258   Last = el;
259   return el;
260 }
261 
SetColumnName(int col,const char * name)262 void MyVariantList::SetColumnName(int col, const char *name)
263 {
264 //
265 // storing a column name
266 //
267   if (col < 0 || col >= NumCols)
268     return;
269   ColumnName[col] = wxString::FromUTF8(name);
270 }
271 
GetColumnName(int col)272 wxString & MyVariantList::GetColumnName(int col)
273 {
274 //
275 // retrieving a column name
276 //
277   return ColumnName[col];
278 }
279 
MyBlobs(int rows,int cols)280 MyBlobs::MyBlobs(int rows, int cols)
281 {
282 //
283 // constructor - a BLOB matrix
284 //
285   int r;
286   MyRowVariant *rowVar;
287   NumRows = 0;
288   NumCols = 0;
289   Rows = NULL;
290   if (rows < 1 || cols < 1)
291     return;
292   NumRows = rows;
293   NumCols = cols;
294   Rows = new MyRowVariant[rows];
295   for (r = 0; r < rows; r++)
296     {
297       rowVar = Rows + r;
298       rowVar->Create(cols);
299     }
300 }
301 
~MyBlobs()302 MyBlobs::~MyBlobs()
303 {
304 //
305 // destructor - a BLOB matrix
306 //
307   if (Rows)
308     delete[]Rows;
309 }
310 
SetBlob(int row,int col,MyVariant * org)311 void MyBlobs::SetBlob(int row, int col, MyVariant * org)
312 {
313 //
314 // setting a BLOB value
315 //
316   MyRowVariant *rowVar;
317   MyVariant *dest;
318   if (row < 0 || row >= NumRows)
319     return;
320   if (col < 0 || col >= NumCols)
321     return;
322   rowVar = Rows + row;
323   if (!rowVar)
324     return;
325   dest = rowVar->GetColumn(col);
326   if (!dest)
327     return;
328   dest->Copy(org);
329 }
330 
GetBlob(int row,int col)331 MyVariant *MyBlobs::GetBlob(int row, int col)
332 {
333 //
334 // return a BLOB value
335 //
336   MyRowVariant *rowVar;
337   MyVariant *dest;
338   if (row < 0 || row >= NumRows)
339     return NULL;
340   if (col < 0 || col >= NumCols)
341     return NULL;
342   rowVar = Rows + row;
343   if (!rowVar)
344     return NULL;
345   dest = rowVar->GetColumn(col);
346   if (!dest)
347     return NULL;
348   if (dest->GetType() != MY_BLOB_VARIANT)
349     return NULL;
350   return dest;
351 }
352 
MyValues(int rows,int cols)353 MyValues::MyValues(int rows, int cols)
354 {
355 //
356 // constructor - a generic values matrix
357 //
358   int r;
359   MyRowVariant *rowVar;
360   NumRows = 0;
361   NumCols = 0;
362   Rows = NULL;
363   if (rows < 1 || cols < 1)
364     return;
365   NumRows = rows;
366   NumCols = cols;
367   Rows = new MyRowVariant[rows];
368   for (r = 0; r < rows; r++)
369     {
370       rowVar = Rows + r;
371       rowVar->Create(cols);
372     }
373 }
374 
~MyValues()375 MyValues::~MyValues()
376 {
377 //
378 // destructor - a generic values matrix
379 //
380   if (Rows)
381     delete[]Rows;
382 }
383 
SetValue(int row,int col,sqlite3_int64 value)384 void MyValues::SetValue(int row, int col, sqlite3_int64 value)
385 {
386 //
387 // setting an integer value
388 //
389   MyRowVariant *rowVar;
390   MyVariant *dest;
391   if (row < 0 || row >= NumRows)
392     return;
393   if (col < 0 || col >= NumCols)
394     return;
395   rowVar = Rows + row;
396   if (!rowVar)
397     return;
398   dest = rowVar->GetColumn(col);
399   if (!dest)
400     return;
401   dest->Set(value);
402 }
403 
SetValue(int row,int col,double value)404 void MyValues::SetValue(int row, int col, double value)
405 {
406 //
407 // setting a double value
408 //
409   MyRowVariant *rowVar;
410   MyVariant *dest;
411   if (row < 0 || row >= NumRows)
412     return;
413   if (col < 0 || col >= NumCols)
414     return;
415   rowVar = Rows + row;
416   if (!rowVar)
417     return;
418   dest = rowVar->GetColumn(col);
419   if (!dest)
420     return;
421   dest->Set(value);
422 }
423 
SetValue(int row,int col,wxString & value)424 void MyValues::SetValue(int row, int col, wxString & value)
425 {
426 //
427 // setting a string value
428 //
429   MyRowVariant *rowVar;
430   MyVariant *dest;
431   if (row < 0 || row >= NumRows)
432     return;
433   if (col < 0 || col >= NumCols)
434     return;
435   rowVar = Rows + row;
436   if (!rowVar)
437     return;
438   dest = rowVar->GetColumn(col);
439   if (!dest)
440     return;
441   dest->Set(value);
442 }
443 
GetValue(int row,int col)444 MyVariant *MyValues::GetValue(int row, int col)
445 {
446 //
447 // return a generic value
448 //
449   MyRowVariant *rowVar;
450   MyVariant *dest;
451   if (row < 0 || row >= NumRows)
452     return NULL;
453   if (col < 0 || col >= NumCols)
454     return NULL;
455   rowVar = Rows + row;
456   if (!rowVar)
457     return NULL;
458   dest = rowVar->GetColumn(col);
459   if (!dest)
460     return NULL;
461   return dest;
462 }
463 
GetRow(int row)464 MyRowVariant *MyValues::GetRow(int row)
465 {
466 //
467 // return a row of generic values
468 //
469   MyRowVariant *rowVar;
470   if (row < 0 || row >= NumRows)
471     return NULL;
472   rowVar = Rows + row;
473   return rowVar;
474 }
475 
MyColumnInfo(wxString & name,bool pkey)476 MyColumnInfo::MyColumnInfo(wxString & name, bool pkey)
477 {
478 //
479 // constructor - a table column object
480 //
481   Name = name;
482   PrimaryKey = pkey;
483   Geometry = false;
484   GeometryIndex = false;
485   MbrCache = false;
486   Next = NULL;
487 }
488 
MyIndexInfo(wxString & name)489 MyIndexInfo::MyIndexInfo(wxString & name)
490 {
491 //
492 // constructor - a table index object
493 //
494   Name = name;
495   Next = NULL;
496 }
497 
MyTriggerInfo(wxString & name)498 MyTriggerInfo::MyTriggerInfo(wxString & name)
499 {
500 //
501 // constructor - a table trigger object
502 //
503   Name = name;
504   Next = NULL;
505 }
506 
~MyTableInfo()507 MyTableInfo::~MyTableInfo()
508 {
509 //
510 // destructor - a table columns collection
511 //
512   MyColumnInfo *elc;
513   MyColumnInfo *elcN;
514   MyIndexInfo *eli;
515   MyIndexInfo *eliN;
516   MyTriggerInfo *elt;
517   MyTriggerInfo *eltN;
518   elc = FirstColumn;
519   while (elc)
520     {
521       elcN = elc->GetNext();
522       delete elc;
523       elc = elcN;
524     }
525   eli = FirstIndex;
526   while (eli)
527     {
528       eliN = eli->GetNext();
529       delete eli;
530       eli = eliN;
531     }
532   elt = FirstTrigger;
533   while (elt)
534     {
535       eltN = elt->GetNext();
536       delete elt;
537       elt = eltN;
538     }
539 }
540 
AddColumn(wxString & name,bool pkey)541 void MyTableInfo::AddColumn(wxString & name, bool pkey)
542 {
543 //
544 // inserting a column def into a table
545 //
546   MyColumnInfo *el = new MyColumnInfo(name, pkey);
547   if (!FirstColumn)
548     FirstColumn = el;
549   if (LastColumn)
550     LastColumn->SetNext(el);
551   LastColumn = el;
552 }
553 
SetGeometry(wxString & name,bool index,bool cached)554 void MyTableInfo::SetGeometry(wxString & name, bool index, bool cached)
555 {
556 //
557 //setting a geometry column
558 //
559   MyColumnInfo *elc;
560   elc = FirstColumn;
561   while (elc)
562     {
563       if (name.CmpNoCase(elc->GetName()) == 0)
564         {
565           elc->SetGeometry();
566           if (index == true)
567             elc->SetGeometryIndex();
568           if (cached == true)
569             elc->SetMbrCache();
570         }
571       elc = elc->GetNext();
572     }
573 }
574 
AddIndex(wxString & name)575 void MyTableInfo::AddIndex(wxString & name)
576 {
577 //
578 // inserting an index def into a table
579 //
580   MyIndexInfo *el = new MyIndexInfo(name);
581   if (!FirstIndex)
582     FirstIndex = el;
583   if (LastIndex)
584     LastIndex->SetNext(el);
585   LastIndex = el;
586 }
587 
AddTrigger(wxString & name)588 void MyTableInfo::AddTrigger(wxString & name)
589 {
590 //
591 // inserting a trigger def into a table
592 //
593   MyTriggerInfo *el = new MyTriggerInfo(name);
594   if (!FirstTrigger)
595     FirstTrigger = el;
596   if (LastTrigger)
597     LastTrigger->SetNext(el);
598   LastTrigger = el;
599 }
600 
~MyViewInfo()601 MyViewInfo::~MyViewInfo()
602 {
603 //
604 // destructor - a view columns collection
605 //
606   MyColumnInfo *elc;
607   MyColumnInfo *elcN;
608   MyTriggerInfo *elt;
609   MyTriggerInfo *eltN;
610   elc = First;
611   while (elc)
612     {
613       elcN = elc->GetNext();
614       delete elc;
615       elc = elcN;
616     }
617   elt = FirstTrigger;
618   while (elt)
619     {
620       eltN = elt->GetNext();
621       delete elt;
622       elt = eltN;
623     }
624 }
625 
AddColumn(wxString & name)626 void MyViewInfo::AddColumn(wxString & name)
627 {
628 //
629 // inserting a column def into a view
630 //
631   MyColumnInfo *el = new MyColumnInfo(name, false);
632   if (!First)
633     First = el;
634   if (Last)
635     Last->SetNext(el);
636   Last = el;
637 }
638 
AddTrigger(wxString & name)639 void MyViewInfo::AddTrigger(wxString & name)
640 {
641 //
642 // inserting a trigger def into a view
643 //
644   MyTriggerInfo *el = new MyTriggerInfo(name);
645   if (!FirstTrigger)
646     FirstTrigger = el;
647   if (LastTrigger)
648     LastTrigger->SetNext(el);
649   LastTrigger = el;
650 }
651 
SetGeometry(wxString & name,bool index,bool cached)652 void MyViewInfo::SetGeometry(wxString & name, bool index, bool cached)
653 {
654 //
655 //setting a geometry column
656 //
657   MyColumnInfo *elc;
658   elc = First;
659   while (elc)
660     {
661       if (name.CmpNoCase(elc->GetName()) == 0)
662         {
663           elc->SetGeometry();
664           if (index == true)
665             elc->SetGeometryIndex();
666           if (cached == true)
667             elc->SetMbrCache();
668         }
669       elc = elc->GetNext();
670     }
671 }
672 
~MySqlHistory()673 MySqlHistory::~MySqlHistory()
674 {
675 //
676 // destructor - the SQL queries history
677 //
678   MySqlQuery *elq;
679   MySqlQuery *elqN;
680   elq = First;
681   while (elq)
682     {
683       elqN = elq->GetNext();
684       delete elq;
685       elq = elqN;
686     }
687 }
688 
Prepend(wxString & sql)689 void MySqlHistory::Prepend(wxString & sql)
690 {
691 //
692 // inserting an SQL query into the history [reverse order]
693 //
694   if (First)
695     {
696       // avoiding stupid duplicates
697       if (First->GetSql() == sql)
698         return;
699     }
700   MySqlQuery *el = new MySqlQuery(sql);
701   el->SetNext(First);
702   if (First)
703     First->SetPrev(el);
704   if (Last == NULL)
705     Last = el;
706   First = el;
707   Current = Last;
708 }
709 
Add(wxString & sql)710 void MySqlHistory::Add(wxString & sql)
711 {
712 //
713 // inserting an SQL query into the history
714 //
715   if (Last)
716     {
717       // avoiding stupid duplicates
718       if (Last->GetSql() == sql)
719         return;
720     }
721   MySqlQuery *el = new MySqlQuery(sql);
722   if (!First)
723     First = el;
724   el->SetPrev(Last);
725   if (Last)
726     Last->SetNext(el);
727   Last = el;
728   Current = el;
729 }
730 
GetNext()731 MySqlQuery *MySqlHistory::GetNext()
732 {
733 //
734 // return the next SQL query
735 //
736   if (Current)
737     {
738       if (Current->GetNext())
739         {
740           Current = Current->GetNext();
741           return Current;
742       } else
743         return NULL;
744     }
745   return NULL;
746 }
747 
GetPrev()748 MySqlQuery *MySqlHistory::GetPrev()
749 {
750 //
751 // return the previous SQL query
752 //
753   if (Current)
754     {
755       if (Current->GetPrev())
756         {
757           Current = Current->GetPrev();
758           return Current;
759       } else
760         return NULL;
761     }
762   return NULL;
763 }
764 
TestNext()765 bool MySqlHistory::TestNext()
766 {
767 //
768 // tests if the next SQL query exists
769 //
770   if (Current)
771     {
772       if (Current->GetNext())
773         return true;
774       else
775         return false;
776     }
777   return false;
778 }
779 
TestPrev()780 bool MySqlHistory::TestPrev()
781 {
782 //
783 // tests if the previous SQL query exists
784 //
785   if (Current)
786     {
787       if (Current->GetPrev())
788         return true;
789       else
790         return false;
791     }
792   return false;
793 }
794 
~AutoFDOTables()795 AutoFDOTables::~AutoFDOTables()
796 {
797 //
798 // destructor - auto FDO-OGR wrapper linked list
799 //
800   AutoFDOTable *el;
801   AutoFDOTable *elN;
802   el = First;
803   while (el)
804     {
805       elN = el->GetNext();
806       delete el;
807       el = elN;
808     }
809 }
810 
Add(const char * name,const int len)811 void AutoFDOTables::Add(const char *name, const int len)
812 {
813 //
814 // adding a table name to the auto FDO-OGR wrapper linked list
815 //
816   AutoFDOTable *el = new AutoFDOTable(name, len);
817   if (!First)
818     First = el;
819   if (Last)
820     Last->SetNext(el);
821   Last = el;
822 }
823 
GeomColumn(wxString & name,wxString & type,wxString & dims,int srid,int idx)824 GeomColumn::GeomColumn(wxString & name, wxString & type, wxString & dims,
825                        int srid, int idx)
826 {
827 // Geometry Column - constructor
828   GeometryName = name;
829   GeometryType = type;
830   CoordDims = dims;
831   Srid = srid;
832   RTree = false;
833   MbrCache = false;
834   if (idx == 1)
835     RTree = true;
836   if (idx == 2)
837     MbrCache = true;
838   NotNull = false;
839   Next = NULL;
840 }
841 
GeomColsList()842 GeomColsList::GeomColsList()
843 {
844 // Geometry Columns List - constructor
845   First = NULL;
846   Last = NULL;
847 }
848 
~GeomColsList()849 GeomColsList::~GeomColsList()
850 {
851 // Geometry Columns List - destructor
852   GeomColumn *pG;
853   GeomColumn *pGn;
854   pG = First;
855   while (pG)
856     {
857       pGn = pG->GetNext();
858       delete pG;
859       pG = pGn;
860     }
861 }
862 
Add(wxString & name,wxString & type,wxString & dims,int srid,int idx)863 void GeomColsList::Add(wxString & name, wxString & type, wxString & dims,
864                        int srid, int idx)
865 {
866 // adding a Geometry Column to the list
867   GeomColumn *p = new GeomColumn(name, type, dims, srid, idx);
868   if (!First)
869     First = p;
870   if (Last)
871     Last->SetNext(p);
872   Last = p;
873 }
874 
SetNotNull(wxString & name)875 void GeomColsList::SetNotNull(wxString & name)
876 {
877 // setting a NOT NULL geometry
878   GeomColumn *pG = First;
879   while (pG)
880     {
881       if (pG->GetGeometryName() == name)
882         {
883           pG->SetNotNull();
884           return;
885         }
886       pG = pG->GetNext();
887     }
888 }
889 
IndexColumn(wxString & name)890 IndexColumn::IndexColumn(wxString & name)
891 {
892 // Index Column - constructor
893   ColumnName = name;
894   Valid = true;
895   Next = NULL;
896 }
897 
TblIndex(wxString & name,bool unique)898 TblIndex::TblIndex(wxString & name, bool unique)
899 {
900 // Table Index - constructor
901   IndexName = name;
902   Unique = unique;
903   Valid = true;
904   First = NULL;
905   Last = NULL;
906   Next = NULL;
907 }
908 
~TblIndex()909 TblIndex::~TblIndex()
910 {
911 // Table Index - destructor
912   IndexColumn *pC;
913   IndexColumn *pCn;
914   pC = First;
915   while (pC)
916     {
917       pCn = pC->GetNext();
918       delete pC;
919       pC = pCn;
920     }
921 }
922 
Add(wxString & name)923 void TblIndex::Add(wxString & name)
924 {
925 // adding a Column to the Index
926   IndexColumn *p = new IndexColumn(name);
927   if (!First)
928     First = p;
929   if (Last)
930     Last->SetNext(p);
931   Last = p;
932 }
933 
Invalidate(wxString & name)934 void TblIndex::Invalidate(wxString & name)
935 {
936 // invalidating a column/index
937   IndexColumn *pC = First;
938   while (pC)
939     {
940       if (pC->GetColumnName() == name)
941         {
942           pC->Invalidate();
943           Valid = false;
944           return;
945         }
946       pC = pC->GetNext();
947     }
948 }
949 
TblIndexList()950 TblIndexList::TblIndexList()
951 {
952 // Table Index List - constructor
953   First = NULL;
954   Last = NULL;
955 }
956 
~TblIndexList()957 TblIndexList::~TblIndexList()
958 {
959 // Table Index List - destructor
960   TblIndex *pI;
961   TblIndex *pIn;
962   pI = First;
963   while (pI)
964     {
965       pIn = pI->GetNext();
966       delete pI;
967       pI = pIn;
968     }
969 }
970 
Add(wxString & name,bool unique)971 void TblIndexList::Add(wxString & name, bool unique)
972 {
973 // adding an Index to the List
974   TblIndex *p = new TblIndex(name, unique);
975   if (!First)
976     First = p;
977   if (Last)
978     Last->SetNext(p);
979   Last = p;
980 }
981 
Invalidate(wxString & name)982 void TblIndexList::Invalidate(wxString & name)
983 {
984 // invalidating a column/index
985   TblIndex *pI = First;
986   while (pI)
987     {
988       pI->Invalidate(name);
989       pI = pI->GetNext();
990     }
991 }
992 
MyChartData()993 MyChartData::MyChartData()
994 {
995 // constructor (unique values)
996   Initialized = false;
997   Array = NULL;
998   First = NULL;
999   Last = NULL;
1000   MaxFreq = INT_MIN;
1001   TotFreq = 0;
1002   MaxClasses = 0;
1003   NumClasses = 0;
1004   OtherUniquesFreq = 0;
1005   OtherUniquesCount = 0;
1006   Valid = false;
1007   ByIntervals = false;
1008 }
1009 
~MyChartData()1010 MyChartData::~MyChartData()
1011 {
1012 // destructor
1013   MyChartUniqueClass *p;
1014   MyChartUniqueClass *pN;
1015   if (Array)
1016     delete[]Array;
1017   p = First;
1018   while (p)
1019     {
1020       pN = p->GetNext();
1021       delete p;
1022       p = pN;
1023     }
1024 }
1025 
Check(bool by_interval,int classes)1026 bool MyChartData::Check(bool by_interval, int classes)
1027 {
1028 // checking if current Data are still valid
1029   if (Initialized == false)
1030     return false;
1031   if (by_interval == true && Array == NULL)
1032     return false;
1033   if (by_interval == false && First == NULL)
1034     return false;
1035   if (by_interval == true && classes != NumClasses)
1036     return false;
1037   if (by_interval == false && classes != MaxClasses)
1038     return false;
1039   return true;
1040 }
1041 
CleanData()1042 void MyChartData::CleanData()
1043 {
1044 // resetting to the initial (not initialized) state
1045 
1046   MyChartUniqueClass *p;
1047   MyChartUniqueClass *pN;
1048   if (Array)
1049     delete[]Array;
1050   p = First;
1051   while (p)
1052     {
1053       pN = p->GetNext();
1054       delete p;
1055       p = pN;
1056     }
1057   Initialized = false;
1058   Array = NULL;
1059   First = NULL;
1060   Last = NULL;
1061   MaxFreq = INT_MIN;
1062   TotFreq = 0;
1063   MaxClasses = 0;
1064   NumClasses = 0;
1065   OtherUniquesFreq = 0;
1066   OtherUniquesCount = 0;
1067   Valid = false;
1068   ByIntervals = false;
1069 }
1070 
Create(int max_classes)1071 bool MyChartData::Create(int max_classes)
1072 {
1073 // constructor (unique values)
1074   if (Initialized == true)
1075     return false;
1076   MaxClasses = max_classes;
1077   Valid = false;
1078   ByIntervals = false;
1079   return true;
1080 }
1081 
Create(double min,double max,int classes)1082 bool MyChartData::Create(double min, double max, int classes)
1083 {
1084 // constructor (interval values)
1085   int ind;
1086   double base = min;
1087   double step;
1088   if (Initialized == true)
1089     return false;
1090   Array = new MyChartIntervalClass[classes];
1091   Min = min;
1092   Max = max;
1093   NumClasses = classes;
1094   Valid = false;
1095   ByIntervals = true;
1096   step = (max - min) / (double) classes;
1097   for (ind = 0; ind < classes; ind++)
1098     {
1099       MyChartIntervalClass *p = GetClass(ind);
1100       p->Create(base, base + step);
1101       base += step;
1102     }
1103   return true;
1104 }
1105 
GetClass(int idx)1106 MyChartIntervalClass *MyChartData::GetClass(int idx)
1107 {
1108 // retriving an interval class by index
1109   if (idx >= 0 && idx < NumClasses)
1110     return Array + idx;
1111   return NULL;
1112 }
1113 
Add(double value)1114 void MyChartData::Add(double value)
1115 {
1116 // incrementing the frequence count for an interval class
1117   double step = (Max - Min) / (double) NumClasses;
1118   int idx = (int) floor((value - Min) / step);
1119   if (idx >= 0 && idx < NumClasses)
1120     {
1121       MyChartIntervalClass *p = GetClass(idx);
1122       p->Add();
1123       TotFreq++;
1124       if (p->GetCount() > MaxFreq)
1125         MaxFreq = p->GetCount();
1126     }
1127 }
1128 
Add(wxString & value,int count)1129 void MyChartData::Add(wxString & value, int count)
1130 {
1131 // appending a new Unique Value (if limit not already reached)
1132   if (NumClasses < MaxClasses)
1133     {
1134       MyChartUniqueClass *p = new MyChartUniqueClass(value, count);
1135       if (First == NULL)
1136         First = p;
1137       if (Last != NULL)
1138         Last->SetNext(p);
1139       Last = p;
1140       NumClasses++;
1141       if (count > MaxFreq)
1142         MaxFreq = count;
1143   } else
1144     {
1145       OtherUniquesFreq += count;
1146       OtherUniquesCount++;
1147       if (OtherUniquesFreq > MaxFreq)
1148         MaxFreq = OtherUniquesFreq;
1149     }
1150   TotFreq += count;
1151 }
1152 
~MyChartScaleLabels()1153 MyChartScaleLabels::~MyChartScaleLabels()
1154 {
1155 // destructor
1156   MyChartScaleLabel *p;
1157   MyChartScaleLabel *pN;
1158   p = First;
1159   while (p)
1160     {
1161       pN = p->GetNext();
1162       delete p;
1163       p = pN;
1164     }
1165 }
1166 
Initialize(double span,int max_freq)1167 void MyChartScaleLabels::Initialize(double span, int max_freq)
1168 {
1169 // setting the Chart Scale labels
1170   int tic;
1171   int tic2;
1172   char text[128];
1173   double pos;
1174 
1175   if (max_freq < 20)
1176     {
1177       tic = 1;
1178       while (tic < max_freq)
1179         {
1180           sprintf(text, "%d", tic);
1181           pos = span * ((double) tic / max_freq);
1182           Add(text, pos);
1183           tic++;
1184         }
1185   } else if (max_freq < 200)
1186     {
1187       tic = 10;
1188       while (tic < max_freq)
1189         {
1190           sprintf(text, "%d", tic);
1191           pos = span * ((double) tic / max_freq);
1192           Add(text, pos);
1193           tic += 10;
1194         }
1195   } else if (max_freq < 2000)
1196     {
1197       tic = 100;
1198       while (tic < max_freq)
1199         {
1200           sprintf(text, "%d", tic);
1201           pos = span * ((double) tic / max_freq);
1202           Add(text, pos);
1203           tic += 100;
1204         }
1205   } else if (max_freq < 20000)
1206     {
1207       tic = 1000;
1208       tic2 = 1;
1209       while (tic < max_freq)
1210         {
1211           sprintf(text, "%dK", tic2);
1212           pos = span * ((double) tic / max_freq);
1213           Add(text, pos);
1214           tic += 1000;
1215           tic2++;
1216         }
1217   } else if (max_freq < 200000)
1218     {
1219       tic = 10000;
1220       tic2 = 1;
1221       while (tic < max_freq)
1222         {
1223           sprintf(text, "%d0K", tic2);
1224           pos = span * ((double) tic / max_freq);
1225           Add(text, pos);
1226           tic += 10000;
1227           tic2++;
1228         }
1229   } else if (max_freq < 2000000)
1230     {
1231       tic = 100000;
1232       tic2 = 1;
1233       while (tic < max_freq)
1234         {
1235           sprintf(text, "%d00K", tic2);
1236           pos = span * ((double) tic / max_freq);
1237           Add(text, pos);
1238           tic += 100000;
1239           tic2++;
1240         }
1241   } else if (max_freq < 20000000)
1242     {
1243       tic = 1000000;
1244       tic2 = 1;
1245       while (tic < max_freq)
1246         {
1247           sprintf(text, "%dM", tic2);
1248           pos = span * ((double) tic / max_freq);
1249           Add(text, pos);
1250           tic += 1000000;
1251           tic2++;
1252         }
1253   } else if (max_freq < 200000000)
1254     {
1255       tic = 10000000;
1256       tic2 = 1;
1257       while (tic < max_freq)
1258         {
1259           sprintf(text, "%d0M", tic2);
1260           pos = span * ((double) tic / max_freq);
1261           Add(text, pos);
1262           tic += 10000000;
1263           tic2++;
1264         }
1265   } else if (max_freq < 200000000)
1266     {
1267       tic = 100000000;
1268       tic2 = 1;
1269       while (tic < max_freq)
1270         {
1271           sprintf(text, "%d00M", tic2);
1272           pos = span * ((double) tic / max_freq);
1273           Add(text, pos);
1274           tic += 100000000;
1275           tic2++;
1276         }
1277   } else
1278     {
1279       tic = 1000000000;
1280       tic2 = 1;
1281       while (tic < max_freq)
1282         {
1283           sprintf(text, "%dG", tic2);
1284           pos = span * ((double) tic / max_freq);
1285           Add(text, pos);
1286           tic += 1000000000;
1287           tic2++;
1288         }
1289     }
1290 }
1291 
Add(const char * label,double pos)1292 void MyChartScaleLabels::Add(const char *label, double pos)
1293 {
1294 // adding a Scale Label
1295   wxString text = wxString::FromUTF8(label);
1296   MyChartScaleLabel *p = new MyChartScaleLabel(text, pos);
1297   if (First == NULL)
1298     First = p;
1299   if (Last != NULL)
1300     Last->SetNext(p);
1301   Last = p;
1302 }
1303 
MyPieChartLabels()1304 MyPieChartLabels::MyPieChartLabels()
1305 {
1306 // constructor
1307   First = NULL;
1308   Last = NULL;
1309   NumLeftLabels = 0;
1310   LeftLabels = NULL;
1311   NumRightLabels = 0;
1312   RightLabels = NULL;
1313 }
1314 
~MyPieChartLabels()1315 MyPieChartLabels::~MyPieChartLabels()
1316 {
1317 // destructor
1318   MyPieChartLabel *p;
1319   MyPieChartLabel *pN;
1320   p = First;
1321   while (p)
1322     {
1323       pN = p->GetNext();
1324       delete p;
1325       p = pN;
1326     }
1327   if (LeftLabels)
1328     delete[]LeftLabels;
1329   if (RightLabels)
1330     delete[]RightLabels;
1331 }
1332 
Add(const char * label,double x,double y)1333 void MyPieChartLabels::Add(const char *label, double x, double y)
1334 {
1335 // adding a PieChart Label
1336   wxString text = wxString::FromUTF8(label);
1337   MyPieChartLabel *p = new MyPieChartLabel(text, x, y);
1338   if (First == NULL)
1339     First = p;
1340   if (Last != NULL)
1341     Last->SetNext(p);
1342   Last = p;
1343 }
1344 
Sort(double cx)1345 void MyPieChartLabels::Sort(double cx)
1346 {
1347 // sorting the Left/Right arrays
1348   MyPieChartLabel *p;
1349   MyPieChartLabel *p2;
1350   int idx;
1351   bool ok;
1352 
1353   if (LeftLabels)
1354     delete[]LeftLabels;
1355   if (RightLabels)
1356     delete[]RightLabels;
1357   NumLeftLabels = 0;
1358   LeftLabels = NULL;
1359   NumRightLabels = 0;
1360   RightLabels = NULL;
1361 
1362   p = First;
1363   while (p)
1364     {
1365       // counting how many 'left' labels are there
1366       if (p->GetX() < cx)
1367         NumLeftLabels++;
1368       p = p->GetNext();
1369     }
1370   p = First;
1371   while (p)
1372     {
1373       // counting how many 'right' labels are there
1374       if (p->GetX() >= cx)
1375         NumRightLabels++;
1376       p = p->GetNext();
1377     }
1378   if (NumLeftLabels > 0)
1379     {
1380       // allocating the Left array
1381       LeftLabels = new MyPieChartLabel *[NumLeftLabels];
1382       idx = 0;
1383       p = First;
1384       while (p)
1385         {
1386           // initializing the Left array
1387           if (p->GetX() < cx)
1388             {
1389               *(LeftLabels + idx) = p;
1390               idx++;
1391             }
1392           p = p->GetNext();
1393         }
1394       ok = true;
1395       while (ok)
1396         {
1397           // bubble-sorting the Left array
1398           ok = false;
1399           for (idx = 1; idx < NumLeftLabels; idx++)
1400             {
1401               p = *(LeftLabels + idx - 1);
1402               p2 = *(LeftLabels + idx);
1403               if (p->GetY() > p2->GetY())
1404                 {
1405                   *(LeftLabels + idx - 1) = p2;
1406                   *(LeftLabels + idx) = p;
1407                   ok = true;
1408                 }
1409             }
1410         }
1411     }
1412   if (NumRightLabels > 0)
1413     {
1414       // allocating the Right array
1415       RightLabels = new MyPieChartLabel *[NumRightLabels];
1416       idx = 0;
1417       p = First;
1418       while (p)
1419         {
1420           // initializing the Right array
1421           if (p->GetX() >= cx)
1422             {
1423               *(RightLabels + idx) = p;
1424               idx++;
1425             }
1426           p = p->GetNext();
1427         }
1428       ok = true;
1429       while (ok)
1430         {
1431           // bubble-sorting the Right array
1432           ok = false;
1433           for (idx = 1; idx < NumRightLabels; idx++)
1434             {
1435               p = *(RightLabels + idx - 1);
1436               p2 = *(RightLabels + idx);
1437               if (p->GetY() > p2->GetY())
1438                 {
1439                   *(RightLabels + idx - 1) = p2;
1440                   *(RightLabels + idx) = p;
1441                   ok = true;
1442                 }
1443             }
1444         }
1445     }
1446 }
1447 
GetLeftLabel(int idx)1448 MyPieChartLabel *MyPieChartLabels::GetLeftLabel(int idx)
1449 {
1450 // return a Left Label pointer by index
1451   if (idx >= 0 && idx < NumLeftLabels)
1452     return *(LeftLabels + idx);
1453   return NULL;
1454 }
1455 
GetRightLabel(int idx)1456 MyPieChartLabel *MyPieChartLabels::GetRightLabel(int idx)
1457 {
1458 // return a Right Label pointer by index
1459   if (idx >= 0 && idx < NumRightLabels)
1460     return *(RightLabels + idx);
1461   return NULL;
1462 }
1463 
Topology(MyTableTree * tree,wxTreeItemId & root,TopologySet * topology)1464 Topology::Topology(MyTableTree * tree, wxTreeItemId & root,
1465                    TopologySet * topology)
1466 {
1467 // constructor: Topology Tree Node
1468   wxString prefix = topology->GetPrefix();
1469   wxString name;
1470   char bufSrid[64];
1471   TopologyItem *pT;
1472   name = prefix;
1473   sprintf(bufSrid, " [SRID=%d]", topology->GetSrid());
1474   name += wxString::FromUTF8(bufSrid);
1475   if (topology->GetCoordDims() == wxT("XYZ"))
1476     name += wxT(" 3D");
1477   else
1478     name += wxT(" 2D");
1479   TopologyNode = tree->AppendItem(root, name);
1480   tree->SetItemImage(TopologyNode, 20);
1481   TopologyItems.SetPrefix(topology->GetPrefix());
1482   TopologyItems.SetSrid(topology->GetSrid());
1483   TopologyItems.SetCoordDims(topology->GetCoordDims());
1484   pT = topology->GetFirst();
1485   while (pT)
1486     {
1487       // copying Topology Items
1488       if (pT->IsTable() == true)
1489         TopologyItems.AddTable(pT->GetName());
1490       else if (pT->IsView() == true)
1491         TopologyItems.AddView(pT->GetName());
1492       pT = pT->GetNext();
1493     }
1494   Next = NULL;
1495 }
1496 
Check(wxString & table)1497 wxTreeItemId *Topology::Check(wxString & table)
1498 {
1499 // checking if some table belongs to this Topology
1500   TopologyItem *pT = TopologyItems.GetFirst();
1501   while (pT)
1502     {
1503       // copying Topology Items
1504       if (pT->GetName() == table)
1505         return &TopologyNode;
1506       pT = pT->GetNext();
1507     }
1508   return NULL;
1509 }
1510 
Flush()1511 void TopologyList::Flush()
1512 {
1513 // resetting TopologyList to initial empty state
1514   Topology *pT;
1515   Topology *pTn;
1516   pT = First;
1517   while (pT)
1518     {
1519       pTn = pT->GetNext();
1520       delete pT;
1521       pT = pTn;
1522     }
1523   First = NULL;
1524   Last = NULL;
1525   Count = 0;
1526 }
1527 
Add(class MyTableTree * tree,wxTreeItemId & root,TopologySet * topology)1528 void TopologyList::Add(class MyTableTree * tree, wxTreeItemId & root,
1529                        TopologySet * topology)
1530 {
1531 // inserting a Topology into the list
1532   Topology *pT = new Topology(tree, root, topology);
1533   Count++;
1534   if (First == NULL)
1535     First = pT;
1536   if (Last != NULL)
1537     Last->SetNext(pT);
1538   Last = pT;
1539 }
1540 
FindNode(wxString & table)1541 wxTreeItemId *TopologyList::FindNode(wxString & table)
1542 {
1543 // serching corresponding Topology Node (if any)
1544   Topology *pT = First;
1545   while (pT)
1546     {
1547       wxTreeItemId *node = pT->Check(table);
1548       if (node != NULL)
1549         return node;
1550       pT = pT->GetNext();
1551     }
1552   return NULL;
1553 }
1554 
PostGISColumn()1555 PostGISColumn::PostGISColumn()
1556 {
1557 // constructor
1558   Nullable = true;
1559   PrimaryKey = false;
1560   Autoincrement = false;
1561   Null = 0;
1562   Boolean = 0;
1563   Int8 = 0;
1564   UInt8 = 0;
1565   Int16 = 0;
1566   UInt16 = 0;
1567   Int32 = 0;
1568   UInt32 = 0;
1569   Int64 = 0;
1570   Double = 0;
1571   Text = 0;
1572   MaxTextLen = 0;
1573   Date = 0;
1574   DateTime = 0;
1575   Blob = 0;
1576   Point = 0;
1577   MultiPoint = 0;
1578   LineString = 0;
1579   MultiLineString = 0;
1580   Polygon = 0;
1581   MultiPolygon = 0;
1582   GeometryCollection = 0;
1583   Srid1 = INT_MIN;
1584   Srid2 = INT_MIN;;
1585   CoordDims1 = GAIA_UNKNOWN;
1586   CoordDims2 = GAIA_UNKNOWN;
1587   DataType = PostGISHelper::DATA_TYPE_UNDEFINED;
1588 }
1589 
IncrPoint(int srid,int dims)1590 void PostGISColumn::IncrPoint(int srid, int dims)
1591 {
1592 // increasing POINT statistics
1593   Point++;
1594   if (srid == Srid1 || srid == Srid2)
1595     ;
1596   else
1597     {
1598       if (Srid1 == INT_MIN)
1599         Srid1 = srid;
1600       else if (Srid2 == INT_MIN)
1601         Srid2 = srid;
1602     }
1603   if (dims == CoordDims1 || dims == CoordDims2)
1604     ;
1605   else
1606     {
1607       if (CoordDims1 == GAIA_UNKNOWN)
1608         CoordDims1 = dims;
1609       else if (CoordDims2 == GAIA_UNKNOWN)
1610         CoordDims2 = dims;
1611     }
1612 }
1613 
IncrMultiPoint(int srid,int dims)1614 void PostGISColumn::IncrMultiPoint(int srid, int dims)
1615 {
1616 // increasing MULTIPOINT statistics
1617   MultiPoint++;
1618   if (srid == Srid1 || srid == Srid2)
1619     ;
1620   else
1621     {
1622       if (Srid1 == INT_MIN)
1623         Srid1 = srid;
1624       else if (Srid2 == INT_MIN)
1625         Srid2 = srid;
1626     }
1627   if (dims == CoordDims1 || dims == CoordDims2)
1628     ;
1629   else
1630     {
1631       if (CoordDims1 == GAIA_UNKNOWN)
1632         CoordDims1 = dims;
1633       else if (CoordDims2 == GAIA_UNKNOWN)
1634         CoordDims2 = dims;
1635     }
1636 }
1637 
IncrLineString(int srid,int dims)1638 void PostGISColumn::IncrLineString(int srid, int dims)
1639 {
1640 // increasing LINESTRING statistics
1641   LineString++;
1642   if (srid == Srid1 || srid == Srid2)
1643     ;
1644   else
1645     {
1646       if (Srid1 == INT_MIN)
1647         Srid1 = srid;
1648       else if (Srid2 == INT_MIN)
1649         Srid2 = srid;
1650     }
1651   if (dims == CoordDims1 || dims == CoordDims2)
1652     ;
1653   else
1654     {
1655       if (CoordDims1 == GAIA_UNKNOWN)
1656         CoordDims1 = dims;
1657       else if (CoordDims2 == GAIA_UNKNOWN)
1658         CoordDims2 = dims;
1659     }
1660 }
1661 
IncrMultiLineString(int srid,int dims)1662 void PostGISColumn::IncrMultiLineString(int srid, int dims)
1663 {
1664 // increasing MULTILINESTRING statistics
1665   MultiLineString++;
1666   if (srid == Srid1 || srid == Srid2)
1667     ;
1668   else
1669     {
1670       if (Srid1 == INT_MIN)
1671         Srid1 = srid;
1672       else if (Srid2 == INT_MIN)
1673         Srid2 = srid;
1674     }
1675   if (dims == CoordDims1 || dims == CoordDims2)
1676     ;
1677   else
1678     {
1679       if (CoordDims1 == GAIA_UNKNOWN)
1680         CoordDims1 = dims;
1681       else if (CoordDims2 == GAIA_UNKNOWN)
1682         CoordDims2 = dims;
1683     }
1684 }
1685 
IncrPolygon(int srid,int dims)1686 void PostGISColumn::IncrPolygon(int srid, int dims)
1687 {
1688 // increasing POLYGON statistics
1689   Polygon++;
1690   if (srid == Srid1 || srid == Srid2)
1691     ;
1692   else
1693     {
1694       if (Srid1 == INT_MIN)
1695         Srid1 = srid;
1696       else if (Srid2 == INT_MIN)
1697         Srid2 = srid;
1698     }
1699   if (dims == CoordDims1 || dims == CoordDims2)
1700     ;
1701   else
1702     {
1703       if (CoordDims1 == GAIA_UNKNOWN)
1704         CoordDims1 = dims;
1705       else if (CoordDims2 == GAIA_UNKNOWN)
1706         CoordDims2 = dims;
1707     }
1708 }
1709 
IncrMultiPolygon(int srid,int dims)1710 void PostGISColumn::IncrMultiPolygon(int srid, int dims)
1711 {
1712 // increasing MULTIPOLYGON statistics
1713   MultiPolygon++;
1714   if (srid == Srid1 || srid == Srid2)
1715     ;
1716   else
1717     {
1718       if (Srid1 == INT_MIN)
1719         Srid1 = srid;
1720       else if (Srid2 == INT_MIN)
1721         Srid2 = srid;
1722     }
1723   if (dims == CoordDims1 || dims == CoordDims2)
1724     ;
1725   else
1726     {
1727       if (CoordDims1 == GAIA_UNKNOWN)
1728         CoordDims1 = dims;
1729       else if (CoordDims2 == GAIA_UNKNOWN)
1730         CoordDims2 = dims;
1731     }
1732 }
1733 
IncrGeometryCollection(int srid,int dims)1734 void PostGISColumn::IncrGeometryCollection(int srid, int dims)
1735 {
1736 // increasing GEOMETRYCOLLECTION statistics
1737   GeometryCollection++;
1738   if (srid == Srid1 || srid == Srid2)
1739     ;
1740   else
1741     {
1742       if (Srid1 == INT_MIN)
1743         Srid1 = srid;
1744       else if (Srid2 == INT_MIN)
1745         Srid2 = srid;
1746     }
1747   if (dims == CoordDims1 || dims == CoordDims2)
1748     ;
1749   else
1750     {
1751       if (CoordDims1 == GAIA_UNKNOWN)
1752         CoordDims1 = dims;
1753       else if (CoordDims2 == GAIA_UNKNOWN)
1754         CoordDims2 = dims;
1755     }
1756 }
1757 
IsDate(const char * txt)1758 bool PostGISColumn::IsDate(const char *txt)
1759 {
1760 // checking if a text string looks like a DATE
1761   if (txt == NULL)
1762     return false;
1763   if (strlen(txt) != 10)
1764     return false;
1765   if (*(txt + 0) >= '0' && *(txt + 0) <= '9')
1766     ;
1767   else
1768     return false;
1769   if (*(txt + 1) >= '0' && *(txt + 1) <= '9')
1770     ;
1771   else
1772     return false;
1773   if (*(txt + 2) >= '0' && *(txt + 2) <= '9')
1774     ;
1775   else
1776     return false;
1777   if (*(txt + 3) >= '0' && *(txt + 3) <= '9')
1778     ;
1779   else
1780     return false;
1781   if (*(txt + 4) != '-')
1782     return false;
1783   if (*(txt + 5) >= '0' && *(txt + 5) <= '9')
1784     ;
1785   else
1786     return false;
1787   if (*(txt + 6) >= '0' && *(txt + 6) <= '9')
1788     ;
1789   else
1790     return false;
1791   if (*(txt + 7) != '-')
1792     return false;
1793   if (*(txt + 8) >= '0' && *(txt + 8) <= '9')
1794     ;
1795   else
1796     return false;
1797   if (*(txt + 9) >= '0' && *(txt + 9) <= '9')
1798     ;
1799   else
1800     return false;
1801   return true;
1802 }
1803 
IsDateTime(const char * txt)1804 bool PostGISColumn::IsDateTime(const char *txt)
1805 {
1806 // checking if a text string looks like a DATETIME
1807   if (txt == NULL)
1808     return false;
1809   if (strlen(txt) != 19)
1810     return false;
1811   if (*(txt + 0) >= '0' && *(txt + 0) <= '9')
1812     ;
1813   else
1814     return false;
1815   if (*(txt + 1) >= '0' && *(txt + 1) <= '9')
1816     ;
1817   else
1818     return false;
1819   if (*(txt + 2) >= '0' && *(txt + 2) <= '9')
1820     ;
1821   else
1822     return false;
1823   if (*(txt + 3) >= '0' && *(txt + 3) <= '9')
1824     ;
1825   else
1826     return false;
1827   if (*(txt + 4) != '-')
1828     return false;
1829   if (*(txt + 5) >= '0' && *(txt + 5) <= '9')
1830     ;
1831   else
1832     return false;
1833   if (*(txt + 6) >= '0' && *(txt + 6) <= '9')
1834     ;
1835   else
1836     return false;
1837   if (*(txt + 7) != '-')
1838     return false;
1839   if (*(txt + 8) >= '0' && *(txt + 8) <= '9')
1840     ;
1841   else
1842     return false;
1843   if (*(txt + 9) >= '0' && *(txt + 9) <= '9')
1844     ;
1845   else
1846     return false;
1847   if (*(txt + 10) != ' ')
1848     return false;
1849   if (*(txt + 11) >= '0' && *(txt + 11) <= '9')
1850     ;
1851   else
1852     return false;
1853   if (*(txt + 12) >= '0' && *(txt + 12) <= '9')
1854     ;
1855   else
1856     return false;
1857   if (*(txt + 13) != ':')
1858     return false;
1859   if (*(txt + 14) >= '0' && *(txt + 14) <= '9')
1860     ;
1861   else
1862     return false;
1863   if (*(txt + 15) >= '0' && *(txt + 15) <= '9')
1864     ;
1865   else
1866     return false;
1867   if (*(txt + 16) != ':')
1868     return false;
1869   if (*(txt + 17) >= '0' && *(txt + 17) <= '9')
1870     ;
1871   else
1872     return false;
1873   if (*(txt + 18) >= '0' && *(txt + 18) <= '9')
1874     ;
1875   else
1876     return false;
1877   return true;
1878 }
1879 
Prepare()1880 void PostGISColumn::Prepare()
1881 {
1882 // determining the exact Column Data Type
1883   if (!Boolean && !Int8 && !UInt8 && !Int16 && !UInt16 && !Int32 && !UInt32
1884       && !Int64 && !Double && !Text && !Date && !DateTime && !Blob)
1885     {
1886       // testing for Geometry
1887       int type = PostGISHelper::DATA_TYPE_UNDEFINED;
1888       if ((Point + MultiPoint + LineString + MultiLineString + Polygon +
1889            MultiPolygon + GeometryCollection) > 0)
1890         type = PostGISHelper::DATA_TYPE_GEOMETRY;
1891       else
1892         {
1893           // surely not a Geometry: defaulting to TEXT
1894           DataType = PostGISHelper::DATA_TYPE_TEXT;
1895           return;
1896         }
1897       if (Point > 0 && !MultiPoint && !LineString && !MultiLineString
1898           && !Polygon && !MultiPolygon && !GeometryCollection)
1899         type = PostGISHelper::DATA_TYPE_POINT;
1900       if (MultiPoint > 0 && !LineString && !MultiLineString && !Polygon
1901           && !MultiPolygon && !GeometryCollection)
1902         type = PostGISHelper::DATA_TYPE_MULTIPOINT;
1903       if (!Point && !MultiPoint && LineString > 0 && !MultiLineString
1904           && !Polygon && !MultiPolygon && !GeometryCollection)
1905         type = PostGISHelper::DATA_TYPE_LINESTRING;
1906       if (!Point && !MultiPoint && MultiLineString > 0 && !Polygon
1907           && !MultiPolygon && !GeometryCollection)
1908         type = PostGISHelper::DATA_TYPE_MULTILINESTRING;
1909       if (!Point && !MultiPoint && !LineString && !MultiLineString
1910           && Polygon > 0 && !MultiPolygon && !GeometryCollection)
1911         type = PostGISHelper::DATA_TYPE_POLYGON;
1912       if (!Point && !MultiPoint && !LineString && !MultiLineString
1913           && MultiPolygon > 0 && !GeometryCollection)
1914         type = PostGISHelper::DATA_TYPE_MULTIPOLYGON;
1915       if (!Point && !MultiPoint && !LineString && !MultiLineString && !Polygon
1916           && !MultiPolygon && GeometryCollection > 0)
1917         type = PostGISHelper::DATA_TYPE_GEOMETRYCOLLECTION;
1918       if (type != PostGISHelper::DATA_TYPE_UNDEFINED)
1919         {
1920           if (Srid2 == INT_MIN && CoordDims2 == GAIA_UNKNOWN)
1921             {
1922               // ok, valid Geometry
1923               DataType = type;
1924               return;
1925           } else
1926             {
1927               // no, invalid Geometry
1928               DataType = PostGISHelper::DATA_TYPE_BLOB;
1929               return;
1930             }
1931         }
1932       DataType = PostGISHelper::DATA_TYPE_BLOB;
1933       return;
1934     }
1935 
1936   if (Boolean > 0 && !Int8 && !UInt8 && !Int16 && !UInt16 && !Int32 && !UInt32
1937       && !Int64 && !Double && !Text && !Date && !DateTime && !Blob)
1938     {
1939       DataType = PostGISHelper::DATA_TYPE_BOOLEAN;
1940       return;
1941     }
1942   if ((Int8 > 0 && !UInt8) && !Int16 && !UInt16 && !Int32 && !UInt32 && !Int64
1943       && !Double && !Text && !Date && !DateTime && !Blob)
1944     {
1945       DataType = PostGISHelper::DATA_TYPE_INT8;
1946       return;
1947     }
1948   if (UInt8 > 0 && !Int16 && !UInt16 && !Int32 && !UInt32 && !Int64 && !Double
1949       && !Text && !Date && !DateTime && !Blob)
1950     {
1951       DataType = PostGISHelper::DATA_TYPE_UINT8;
1952       return;
1953     }
1954   if ((Int16 > 0 && !UInt16) && !Int32 && !UInt32 && !Int64 && !Double && !Text
1955       && !Date && !DateTime && !Blob)
1956     {
1957       DataType = PostGISHelper::DATA_TYPE_INT16;
1958       return;
1959     }
1960   if (UInt16 > 0 && !Int32 && !UInt32 && !Int64 && !Double && !Text && !Date
1961       && !DateTime && !Blob)
1962     {
1963       DataType = PostGISHelper::DATA_TYPE_UINT16;
1964       return;
1965     }
1966   if ((Int32 > 0 && !UInt32) && !Int64 && !Double && !Text && !Date && !DateTime
1967       && !Blob)
1968     {
1969       DataType = PostGISHelper::DATA_TYPE_INT32;
1970       return;
1971     }
1972   if (UInt32 > 0 && !Int64 && !Double && !Text && !Date && !DateTime && !Blob)
1973     {
1974       DataType = PostGISHelper::DATA_TYPE_UINT32;
1975       return;
1976     }
1977   if (Int64 > 0 && !Double && !Text && !Date && !DateTime && !Blob)
1978     {
1979       DataType = PostGISHelper::DATA_TYPE_INT64;
1980       return;
1981     }
1982   if (Double > 0 && !Text && !Date && !DateTime && !Blob)
1983     {
1984       DataType = PostGISHelper::DATA_TYPE_DOUBLE;
1985       return;
1986     }
1987   if (!Boolean && !Int8 && !UInt8 && !Int16 && !UInt16 && !Int32 && !UInt32
1988       && !Int64 && !Double && Text > 0 && !Date && !DateTime && !Blob)
1989     {
1990       DataType = PostGISHelper::DATA_TYPE_TEXT;
1991       return;
1992     }
1993   if (!Boolean && !Int8 && !UInt8 && !Int16 && !UInt16 && !Int32 && !UInt32
1994       && !Int64 && !Double && !Text && Date > 0 && !DateTime && !Blob)
1995     {
1996       DataType = PostGISHelper::DATA_TYPE_DATE;
1997       return;
1998     }
1999   if (!Boolean && !Int8 && !UInt8 && !Int16 && !UInt16 && !Int32 && !UInt32
2000       && !Int64 && !Double && !Text && DateTime > 0 && !Blob)
2001     {
2002       DataType = PostGISHelper::DATA_TYPE_DATETIME;
2003       return;
2004     }
2005   if (!Boolean && !Int8 && !UInt8 && !Int16 && !UInt16 && !Int32 && !UInt32
2006       && !Int64 && !Double && !Text && !Date && !DateTime && Blob > 0)
2007     {
2008       DataType = PostGISHelper::DATA_TYPE_BLOB;
2009       return;
2010     }
2011   if ((Boolean + Int8 + UInt8 + Int16 + UInt16 + Int32 + UInt32 + Int64 +
2012        Double + Text + Date + DateTime) > 0 && !Blob)
2013     {
2014       DataType = PostGISHelper::DATA_TYPE_TEXT;
2015       return;
2016     }
2017   if (Null > 0)
2018     Nullable = true;
2019 // unable to establish a valid Data Type
2020   DataType = PostGISHelper::DATA_TYPE_UNDEFINED;
2021 }
2022 
IsGeometry()2023 bool PostGISColumn::IsGeometry()
2024 {
2025 // does this column corresponds to some Geometry ?
2026   switch (DataType)
2027     {
2028       case PostGISHelper::DATA_TYPE_POINT:
2029       case PostGISHelper::DATA_TYPE_LINESTRING:
2030       case PostGISHelper::DATA_TYPE_POLYGON:
2031       case PostGISHelper::DATA_TYPE_MULTIPOINT:
2032       case PostGISHelper::DATA_TYPE_MULTILINESTRING:
2033       case PostGISHelper::DATA_TYPE_MULTIPOLYGON:
2034       case PostGISHelper::DATA_TYPE_GEOMETRYCOLLECTION:
2035       case PostGISHelper::DATA_TYPE_GEOMETRY:
2036         return true;
2037     }
2038   return false;
2039 }
2040 
~PostGISIndex()2041 PostGISIndex::~PostGISIndex()
2042 {
2043 // destructor
2044   PostGISIndexField *pI;
2045   PostGISIndexField *pIn;
2046   pI = First;
2047   while (pI)
2048     {
2049       pIn = pI->GetNext();
2050       delete pI;
2051       pI = pIn;
2052     }
2053 }
2054 
AddField(int seq,PostGISColumn * col)2055 void PostGISIndex::AddField(int seq, PostGISColumn * col)
2056 {
2057 // adding a Field into this Index
2058   PostGISIndexField *field = new PostGISIndexField(seq, col);
2059   if (First == NULL)
2060     First = field;
2061   if (Last != NULL)
2062     Last->SetNext(field);
2063   Last = field;
2064 }
2065 
PostGISHelper()2066 PostGISHelper::PostGISHelper()
2067 {
2068 // constructor
2069   DumbName = wxT("DumbColumn");
2070   Count = 0;
2071   Columns = NULL;
2072   FirstIdx = NULL;
2073   LastIdx = NULL;
2074   Autoincrement = false;
2075 }
2076 
~PostGISHelper()2077 PostGISHelper::~PostGISHelper()
2078 {
2079 // destructor
2080   PostGISIndex *pI;
2081   PostGISIndex *pIn;
2082   if (Columns != NULL)
2083     delete[]Columns;
2084   pI = FirstIdx;
2085   while (pI)
2086     {
2087       pIn = pI->GetNext();
2088       delete pI;
2089       pI = pIn;
2090     }
2091 }
2092 
Alloc(int count)2093 void PostGISHelper::Alloc(int count)
2094 {
2095 //
2096 // allocating the Columns array
2097 //
2098   Count = count;
2099   if (Columns != NULL)
2100     delete[]Columns;
2101   Columns = new PostGISColumn[Count];
2102 }
2103 
SetName(int pos,const char * name)2104 void PostGISHelper::SetName(int pos, const char *name)
2105 {
2106 //
2107 // setting a Column Name
2108 //
2109   if (pos >= 0 && pos < Count)
2110     {
2111       wxString Name = wxString::FromUTF8(name);
2112       Columns[pos].SetName(Name);
2113     }
2114 }
2115 
Eval(int pos,sqlite3_int64 val)2116 void PostGISHelper::Eval(int pos, sqlite3_int64 val)
2117 {
2118 //
2119 // evaluating an INT value
2120 //
2121   if (pos >= 0 && pos < Count)
2122     {
2123       bool skip = false;
2124       if (val == 1 || val == 0)
2125         {
2126           Columns[pos].IncrBoolean();
2127           skip = true;
2128         }
2129       if (!skip)
2130         {
2131           if (val >= SCHAR_MIN && val <= SCHAR_MAX)
2132             {
2133               Columns[pos].IncrInt8();
2134               skip = true;
2135             }
2136           if (val > SCHAR_MAX && val <= UCHAR_MAX)
2137             {
2138               Columns[pos].IncrUInt8();
2139               skip = true;
2140             }
2141         }
2142       if (!skip)
2143         {
2144           if (val >= SHRT_MIN && val <= SHRT_MAX)
2145             {
2146               Columns->IncrInt16();
2147               skip = true;
2148             }
2149           if (val > SHRT_MAX && val <= USHRT_MAX)
2150             {
2151               Columns[pos].IncrUInt16();
2152               skip = true;
2153             }
2154         }
2155       if (!skip)
2156         {
2157           if (val >= INT_MIN && val <= INT_MAX)
2158             {
2159               Columns[pos].IncrInt32();
2160               skip = true;
2161             }
2162           if (val > INT_MAX && val <= UINT_MAX)
2163             {
2164               Columns[pos].IncrUInt32();
2165               skip = true;
2166             }
2167         }
2168       if (!skip)
2169         Columns[pos].IncrInt64();
2170     }
2171 }
2172 
Eval(int pos,double val)2173 void PostGISHelper::Eval(int pos, double val)
2174 {
2175 //
2176 // evaluating a DOUBLE value
2177 //
2178   if (val > 0)
2179     val = 0.0;                  // suppressing stupid warnings
2180   if (pos >= 0 && pos < Count)
2181     Columns[pos].IncrDouble();
2182 }
2183 
Eval(int pos,const char * val)2184 void PostGISHelper::Eval(int pos, const char *val)
2185 {
2186 //
2187 // evaluating a TEXT value
2188 //
2189   if (pos >= 0 && pos < Count)
2190     {
2191       int len = strlen(val);
2192       if (Columns[pos].IsDate(val) == true)
2193         Columns[pos].IncrDate();
2194       else if (Columns[pos].IsDateTime(val) == true)
2195         Columns[pos].IncrDateTime();
2196       else
2197         Columns[pos].IncrText(len);
2198     }
2199 }
2200 
Eval(int pos,gaiaGeomCollPtr geom)2201 void PostGISHelper::Eval(int pos, gaiaGeomCollPtr geom)
2202 {
2203 //
2204 // evaluating a Geometry value
2205 //
2206   if (pos >= 0 && pos < Count)
2207     {
2208       switch (geom->DeclaredType)
2209         {
2210           case GAIA_POINT:
2211             Columns[pos].IncrPoint(geom->Srid, geom->DimensionModel);
2212             break;
2213           case GAIA_LINESTRING:
2214             Columns[pos].IncrLineString(geom->Srid, geom->DimensionModel);
2215             break;
2216           case GAIA_POLYGON:
2217             Columns[pos].IncrPolygon(geom->Srid, geom->DimensionModel);
2218             break;
2219           case GAIA_MULTIPOINT:
2220             Columns[pos].IncrMultiPoint(geom->Srid, geom->DimensionModel);
2221             break;
2222           case GAIA_MULTILINESTRING:
2223             Columns[pos].IncrMultiLineString(geom->Srid, geom->DimensionModel);
2224             break;
2225           case GAIA_MULTIPOLYGON:
2226             Columns[pos].IncrMultiPolygon(geom->Srid, geom->DimensionModel);
2227             break;
2228           case GAIA_GEOMETRYCOLLECTION:
2229             Columns[pos].IncrGeometryCollection(geom->Srid,
2230                                                 geom->DimensionModel);
2231             break;
2232         };
2233     }
2234 }
2235 
EvalBlob(int pos)2236 void PostGISHelper::EvalBlob(int pos)
2237 {
2238 //
2239 // evaluating a BLOB value
2240 //
2241   if (pos >= 0 && pos < Count)
2242     Columns[pos].IncrBlob();
2243 }
2244 
Eval(int pos)2245 void PostGISHelper::Eval(int pos)
2246 {
2247 //
2248 // evaluating a NULL value
2249 //
2250   if (pos >= 0 && pos < Count)
2251     Columns[pos].IncrNull();
2252 }
2253 
GetName(int pos,bool to_lower)2254 wxString & PostGISHelper::GetName(int pos, bool to_lower)
2255 {
2256 //
2257 // return a Column name [by relative position]
2258 //
2259   wxString name;
2260   if (pos >= 0 && pos < Count)
2261     name = Columns[pos].GetName();
2262   else
2263     name = wxT("DumbColumn");
2264   if (to_lower)
2265     DumbName = name.MakeLower();
2266   else
2267     DumbName = name;
2268   return DumbName;
2269 }
2270 
Prepare()2271 void PostGISHelper::Prepare()
2272 {
2273 //
2274 // setting PostGIS data types for each Column
2275 //
2276   int i;
2277   for (i = 0; i < Count; i++)
2278     Columns[i].Prepare();
2279 }
2280 
IsSingleFieldPrimaryKey()2281 bool PostGISHelper::IsSingleFieldPrimaryKey()
2282 {
2283 // testing if there is a single column PK
2284   int count = 0;
2285   int i;
2286   for (i = 0; i < Count; i++)
2287     {
2288       if (Columns[i].IsPrimaryKey() == true)
2289         count++;
2290     }
2291   if (count == 1)
2292     return true;
2293   return false;
2294 }
2295 
IsGeometry(int pos)2296 bool PostGISHelper::IsGeometry(int pos)
2297 {
2298 //
2299 // checking if a column is of any Geometry type
2300 //
2301   if (pos >= 0 && pos < Count)
2302     return Columns[pos].IsGeometry();
2303   return false;
2304 }
2305 
GetDataType(int pos)2306 int PostGISHelper::GetDataType(int pos)
2307 {
2308 //
2309 // return the data type for some column
2310 //
2311   if (pos >= 0 && pos < Count)
2312     return Columns[pos].GetDataType();
2313   return DATA_TYPE_UNDEFINED;
2314 }
2315 
GetSrid(int pos)2316 int PostGISHelper::GetSrid(int pos)
2317 {
2318 //
2319 // return the SRID for some Geometry column
2320 //
2321   if (pos >= 0 && pos < Count)
2322     return Columns[pos].GetSrid();
2323   return -1;
2324 }
2325 
GetCoordDims(int pos)2326 int PostGISHelper::GetCoordDims(int pos)
2327 {
2328 //
2329 // return the Coord Dimensions for some Geometry column
2330 //
2331   if (pos >= 0 && pos < Count)
2332     return Columns[pos].GetCoordDims();
2333   return GAIA_XY;
2334 }
2335 
SetColumn(wxString & name,bool isNull,bool isPKey)2336 void PostGISHelper::SetColumn(wxString & name, bool isNull, bool isPKey)
2337 {
2338 //
2339 // setting up Column params
2340 //
2341   int i;
2342   for (i = 0; i < Count; i++)
2343     {
2344       if (Columns[i].GetName() == name)
2345         {
2346           if (isNull)
2347             Columns[i].SetNotNull();
2348           if (isPKey)
2349             {
2350               Columns[i].SetPrimaryKey();
2351             }
2352           break;
2353         }
2354     }
2355 }
2356 
GetDataType(int pos,char * definition)2357 void PostGISHelper::GetDataType(int pos, char *definition)
2358 {
2359 //
2360 // return the data definition for some column
2361 //
2362   if (pos >= 0 && pos < Count)
2363     {
2364       int len;
2365       int data_type = Columns[pos].GetDataType();
2366       switch (data_type)
2367         {
2368           case DATA_TYPE_BOOLEAN:
2369           case DATA_TYPE_INT8:
2370           case DATA_TYPE_UINT8:
2371           case DATA_TYPE_INT16:
2372             strcpy(definition, "smallint");
2373             break;
2374           case DATA_TYPE_UINT16:
2375           case DATA_TYPE_INT32:
2376             strcpy(definition, "integer");
2377             break;
2378           case DATA_TYPE_UINT32:
2379           case DATA_TYPE_INT64:
2380             strcpy(definition, "bigint");
2381             break;
2382           case DATA_TYPE_DOUBLE:
2383             strcpy(definition, "double precision");
2384             break;
2385           case DATA_TYPE_DATE:
2386             strcpy(definition, "date");
2387             break;
2388           case DATA_TYPE_DATETIME:
2389             strcpy(definition, "timestamp");
2390             break;
2391           case DATA_TYPE_TEXT:
2392             len = Columns[pos].GetMaxTextLen();
2393             if (len <= 255)
2394               {
2395                 sprintf(definition, "character varying(%d)",
2396                         (len == 0) ? 255 : len);
2397             } else
2398               strcpy(definition, "text");
2399             break;
2400           case DATA_TYPE_BLOB:
2401             strcpy(definition, "bytea");
2402             break;
2403           default:
2404             strcpy(definition, "unknownType");
2405         };
2406       if (Columns[pos].IsNotNull() == true)
2407         strcat(definition, " NOT NULL");
2408       if (Columns[pos].IsPrimaryKey() == true
2409           && IsSingleFieldPrimaryKey() == true)
2410         {
2411           if (IsAutoincrement() == true)
2412             strcpy(definition, "SERIAL");
2413           else
2414             {
2415               // attempting to promote any PK as int-4
2416               switch (data_type)
2417                 {
2418                   case DATA_TYPE_BOOLEAN:
2419                   case DATA_TYPE_INT8:
2420                   case DATA_TYPE_UINT8:
2421                   case DATA_TYPE_INT16:
2422                   case DATA_TYPE_UINT16:
2423                   case DATA_TYPE_INT32:
2424                     strcpy(definition, "integer");
2425                     break;
2426                 }
2427             }
2428           strcat(definition, " PRIMARY KEY");
2429         }
2430       return;
2431     }
2432   *definition = '\0';
2433 }
2434 
OutputBooleanValue(FILE * out,sqlite3_int64 value)2435 void PostGISHelper::OutputBooleanValue(FILE * out, sqlite3_int64 value)
2436 {
2437 // outputting a BOOLEAN value
2438   if (value == 0)
2439     fprintf(out, "0");
2440   else
2441     fprintf(out, "1");
2442 }
2443 
OutputValue(FILE * out,sqlite3_int64 value)2444 void PostGISHelper::OutputValue(FILE * out, sqlite3_int64 value)
2445 {
2446 // outputting an INTEGER value
2447 #if defined(_WIN32) || defined(__MINGW32__)
2448 // CAVEAT - M$ runtime doesn't supports %lld for 64 bits
2449   fprintf(out, "%I64d", value);
2450 #else
2451   fprintf(out, "%lld", value);
2452 #endif
2453 }
2454 
OutputValue(FILE * out,double value)2455 void PostGISHelper::OutputValue(FILE * out, double value)
2456 {
2457 // outputting a DOUBLE value
2458   fprintf(out, "%1.15f", value);
2459 }
2460 
OutputValue(FILE * out,const char * value)2461 void PostGISHelper::OutputValue(FILE * out, const char *value)
2462 {
2463 // outputting a TEXT value
2464   const char *p = value;
2465   fputc('\'', out);
2466   while (*p != '\0')
2467     {
2468       if (*p == '\'')
2469         fputc('\'', out);
2470       fputc(*p++, out);
2471     }
2472   fputc('\'', out);
2473 }
2474 
OutputValue(FILE * out,gaiaGeomCollPtr geom)2475 void PostGISHelper::OutputValue(FILE * out, gaiaGeomCollPtr geom)
2476 {
2477 // outputting a GEOMETRY EWKB value
2478   gaiaOutBuffer out_buf;
2479   gaiaOutBufferInitialize(&out_buf);
2480   gaiaToEWKB(&out_buf, geom);
2481   if (out_buf.Error || out_buf.Buffer == NULL)
2482     fprintf(out, "NULL");
2483   else
2484     {
2485       int len = out_buf.WriteOffset;
2486       int i;
2487       fputc('\'', out);
2488       for (i = 0; i < len; i++)
2489         fputc(out_buf.Buffer[i], out);
2490       fputc('\'', out);
2491     }
2492   gaiaOutBufferReset(&out_buf);
2493 }
2494 
OutputValue(FILE * out,const unsigned char * value,int len)2495 void PostGISHelper::OutputValue(FILE * out, const unsigned char *value, int len)
2496 {
2497 // outputting a BLOB value as BYTEA
2498   int i;
2499   const char *in = (const char *) value;
2500 
2501 // encoding a BLOB as BYTEA [escaped octects]
2502   putc('E', out);
2503   putc('\'', out);
2504   for (i = 0; i < len; i++)
2505     {
2506       if (in[i] <= 31 || in[i] >= 127 || in[i] == '\'' || in[i] == '\\')
2507         fprintf(out, "\\\\%03o", in[i]);
2508       else
2509         putc(in[i], out);
2510     }
2511   putc('\'', out);
2512 }
2513 
AddIndex(wxString & Name)2514 PostGISIndex *PostGISHelper::AddIndex(wxString & Name)
2515 {
2516 // adding a Primary Key to this Table
2517   wxString name = wxT("pk_") + Name;
2518   PostGISIndex *idx = new PostGISIndex(name);
2519   if (FirstIdx == NULL)
2520     FirstIdx = idx;
2521   if (LastIdx != NULL)
2522     LastIdx->SetNext(idx);
2523   LastIdx = idx;
2524   return idx;
2525 }
2526 
AddIndex(wxString & name,bool unique)2527 PostGISIndex *PostGISHelper::AddIndex(wxString & name, bool unique)
2528 {
2529 // adding an Index to this Table
2530   PostGISIndex *idx = FirstIdx;
2531   while (idx)
2532     {
2533       if (idx->GetName() == name)
2534         {
2535           // already inserted
2536           return idx;
2537         }
2538       idx = idx->GetNext();
2539     }
2540 
2541   idx = new PostGISIndex(name, unique);
2542   if (FirstIdx == NULL)
2543     FirstIdx = idx;
2544   if (LastIdx != NULL)
2545     LastIdx->SetNext(idx);
2546   LastIdx = idx;
2547   return idx;
2548 }
2549 
Find(wxString & name)2550 PostGISColumn *PostGISHelper::Find(wxString & name)
2551 {
2552 // retrieving a Column by name
2553   int i;
2554   for (i = 0; i < Count; i++)
2555     {
2556       PostGISColumn *pC = Columns + i;
2557       if (pC->GetName() == name)
2558         return pC;
2559     }
2560   return NULL;
2561 }
2562 
ExpandIndexFields(MyFrame * MainFrame,PostGISIndex * index,wxString & idxName)2563 void PostGISHelper::ExpandIndexFields(MyFrame * MainFrame, PostGISIndex * index,
2564                                       wxString & idxName)
2565 {
2566 //
2567 // expanding the Index Fields
2568 //
2569   int i;
2570   char **results;
2571   int rows;
2572   int columns;
2573   char *errMsg = NULL;
2574   char *name;
2575   int seq;
2576   wxString Name;
2577   wxString sql;
2578   char xname[1024];
2579   int ret;
2580 
2581   sql = wxT("PRAGMA index_info(");
2582   strcpy(xname, idxName.ToUTF8());
2583   MainFrame->DoubleQuotedSql(xname);
2584   sql += wxString::FromUTF8(xname);
2585   sql += wxT(")");
2586   ret = sqlite3_get_table(MainFrame->GetSqlite(), sql.ToUTF8(), &results,
2587                           &rows, &columns, &errMsg);
2588   if (ret != SQLITE_OK)
2589     {
2590       wxMessageBox(wxT("PostGIS SQL dump error: ") + wxString::FromUTF8(errMsg),
2591                    wxT("spatialite_gui"), wxOK | wxICON_ERROR, MainFrame);
2592       sqlite3_free(errMsg);
2593       return;
2594     }
2595   if (rows < 1)
2596     ;
2597   else
2598     {
2599       for (i = 1; i <= rows; i++)
2600         {
2601           seq = atoi(results[(i * columns) + 0]);
2602           name = results[(i * columns) + 2];
2603           Name = wxString::FromUTF8(name);
2604           PostGISColumn *col = Find(Name);
2605           index->AddField(seq, col);
2606         }
2607     }
2608   sqlite3_free_table(results);
2609 }
2610 
GetKeys(MyFrame * MainFrame,wxString & tableName)2611 void PostGISHelper::GetKeys(MyFrame * MainFrame, wxString & tableName)
2612 {
2613 //
2614 // identifying the Primary Key (and any Index)
2615 //
2616   int i;
2617   char **results;
2618   int rows;
2619   int columns;
2620   char *errMsg = NULL;
2621   char *name;
2622   wxString Name;
2623   bool pKey;
2624   bool notNull;
2625   bool unique;
2626   wxString sql;
2627   int ret;
2628   char xname[1024];
2629 
2630 // retrieving the Table Columns
2631   sql = wxT("PRAGMA table_info(");
2632   strcpy(xname, tableName.ToUTF8());
2633   MainFrame->DoubleQuotedSql(xname);
2634   sql += wxString::FromUTF8(xname);
2635   sql += wxT(")");
2636   ret = sqlite3_get_table(MainFrame->GetSqlite(), sql.ToUTF8(), &results,
2637                           &rows, &columns, &errMsg);
2638   if (ret != SQLITE_OK)
2639     {
2640       wxMessageBox(wxT("PostGIS SQL dump error: ") + wxString::FromUTF8(errMsg),
2641                    wxT("spatialite_gui"), wxOK | wxICON_ERROR, MainFrame);
2642       sqlite3_free(errMsg);
2643       return;
2644     }
2645   if (rows < 1)
2646     ;
2647   else
2648     {
2649       for (i = 1; i <= rows; i++)
2650         {
2651           name = results[(i * columns) + 1];
2652           if (atoi(results[(i * columns) + 3]) == 0)
2653             notNull = false;
2654           else
2655             notNull = true;
2656           if (atoi(results[(i * columns) + 5]) == 0)
2657             pKey = false;
2658           else
2659             pKey = true;
2660           Name = wxString::FromUTF8(name);
2661           SetColumn(Name, notNull, pKey);
2662         }
2663     }
2664   sqlite3_free_table(results);
2665 
2666 // retrieving any Index bounded to this Table
2667   sql = wxT("PRAGMA index_list(");
2668   strcpy(xname, tableName.ToUTF8());
2669   MainFrame->DoubleQuotedSql(xname);
2670   sql += wxString::FromUTF8(xname);
2671   sql += wxT(")");
2672   ret = sqlite3_get_table(MainFrame->GetSqlite(), sql.ToUTF8(), &results,
2673                           &rows, &columns, &errMsg);
2674   if (ret != SQLITE_OK)
2675     {
2676       wxMessageBox(wxT("PostGIS SQL dump error: ") + wxString::FromUTF8(errMsg),
2677                    wxT("spatialite_gui"), wxOK | wxICON_ERROR, MainFrame);
2678       sqlite3_free(errMsg);
2679       return;
2680     }
2681   if (rows < 1)
2682     ;
2683   else
2684     {
2685       for (i = 1; i <= rows; i++)
2686         {
2687           name = results[(i * columns) + 1];
2688           if (atoi(results[(i * columns) + 2]) == 0)
2689             unique = false;
2690           else
2691             unique = true;
2692           Name = wxString::FromUTF8(name);
2693           PostGISIndex *index;
2694           if (Name.StartsWith(wxT("sqlite_autoindex_")) == true)
2695             index = AddIndex(tableName);
2696           else
2697             index = AddIndex(Name, unique);
2698           ExpandIndexFields(MainFrame, index, Name);
2699         }
2700     }
2701   sqlite3_free_table(results);
2702 
2703   if (IsSingleFieldPrimaryKey() == true)
2704     {
2705       // checking for AUTOINCREMENT
2706       sql =
2707         wxT("SELECT Count(*) FROM sqlite_sequence WHERE Lower(name) = Lower('");
2708       strcpy(xname, tableName.ToUTF8());
2709       MainFrame->CleanSqlString(xname);
2710       sql += wxString::FromUTF8(xname);
2711       sql += wxT("')");
2712       ret = sqlite3_get_table(MainFrame->GetSqlite(), sql.ToUTF8(), &results,
2713                               &rows, &columns, &errMsg);
2714       if (ret != SQLITE_OK)
2715         return;
2716       if (rows < 1)
2717         ;
2718       else
2719         {
2720           int cnt = 0;
2721           for (i = 1; i <= rows; i++)
2722             {
2723               cnt = atoi(results[(i * columns) + 0]);
2724             }
2725           if (cnt)
2726             Autoincrement = true;
2727         }
2728       sqlite3_free_table(results);
2729     }
2730 }
2731 
TopologyItem(wxString & name)2732 TopologyItem::TopologyItem(wxString & name)
2733 {
2734 // constructor
2735   Name = name;
2736   Table = false;
2737   View = false;
2738   Next = NULL;
2739 }
2740 
TopologySet()2741 TopologySet::TopologySet()
2742 {
2743 // constructor
2744   Srid = 0;
2745   First = NULL;
2746   Last = NULL;
2747 }
2748 
~TopologySet()2749 TopologySet::~TopologySet()
2750 {
2751 // destructor
2752   TopologyItem *pT;
2753   TopologyItem *pTn;
2754   pT = First;
2755   while (pT)
2756     {
2757       pTn = pT->GetNext();
2758       delete pT;
2759       pT = pTn;
2760     }
2761 }
2762 
SetCoordDims(const char * coords)2763 void TopologySet::SetCoordDims(const char *coords)
2764 {
2765 // setting CoordDims
2766   CoordDims = wxString::FromUTF8(coords);
2767 }
2768 
Add(const char * name,bool table,bool view)2769 void TopologySet::Add(const char *name, bool table, bool view)
2770 {
2771 // adding a Table/View
2772   wxString xName = wxString::FromUTF8(name);
2773   TopologyItem *pT = new TopologyItem(xName);
2774   if (table == true)
2775     pT->SetTable();
2776   if (view == true)
2777     pT->SetView();
2778   if (First == NULL)
2779     First = pT;
2780   if (Last != NULL)
2781     Last->SetNext(pT);
2782   Last = pT;
2783 }
2784 
AddTable(wxString & name)2785 void TopologySet::AddTable(wxString & name)
2786 {
2787 // adding a Table
2788   TopologyItem *pT = new TopologyItem(name);
2789   pT->SetTable();
2790   if (First == NULL)
2791     First = pT;
2792   if (Last != NULL)
2793     Last->SetNext(pT);
2794   Last = pT;
2795 }
2796 
AddView(wxString & name)2797 void TopologySet::AddView(wxString & name)
2798 {
2799 // adding a View
2800   TopologyItem *pT = new TopologyItem(name);
2801   pT->SetView();
2802   if (First == NULL)
2803     First = pT;
2804   if (Last != NULL)
2805     Last->SetNext(pT);
2806   Last = pT;
2807 }
2808 
CheckPrefix()2809 bool TopologySet::CheckPrefix()
2810 {
2811 // attempting to check (and validate) Prefix
2812   int count = 0;
2813   int errors = 0;
2814   wxString prefix;
2815   TopologyItem *pT = First;
2816   while (pT != NULL)
2817     {
2818       if (pT->GetName().EndsWith(wxT("nodes"), &prefix) == true)
2819         break;
2820       pT = pT->GetNext();
2821     }
2822   if (prefix.Len() == 0)
2823     return false;
2824   pT = First;
2825   while (pT != NULL)
2826     {
2827       if (pT->GetName().StartsWith(prefix) == true)
2828         count++;
2829       else
2830         errors++;
2831       pT = pT->GetNext();
2832     }
2833   if (count > 1 && errors == 0)
2834     {
2835       Prefix = prefix;
2836       return true;
2837     }
2838   return false;
2839 }
2840