Skip to content

Commit

Permalink
- Added DisconnectOnExit to upsizing engine so can keep connection op…
Browse files Browse the repository at this point in the history
…en after upsizing done

- Handles field names with reserved words and removes CHR(0) from fields in bulk XML load
  • Loading branch information
DougHennig committed Feb 4, 2019
1 parent cdeff97 commit 2017b6a
Show file tree
Hide file tree
Showing 13 changed files with 46 additions and 19 deletions.
2 changes: 1 addition & 1 deletion INCLUDE/alldefs.h
Original file line number Diff line number Diff line change
Expand Up @@ -377,7 +377,7 @@ upsize will be reset." + CHR(10) + CHR(13) + CHR(10) + CHR(13)+ "Continue?"
#DEFINE THIS_VIEW_LOC "View '|1'"

#DEFINE DEXPORT_FAILED_LOC "Data export halted because of export errors."
#DEFINE SOME_ERRS_LOC "|1 records not exported successfully."
#DEFINE SOME_ERRS_LOC "|1 records not exported successfully for |2."
#DEFINE DATA_EXPORT_LOC "Data export"
#DEFINE CLUSTER_LOC "Cluster"
#DEFINE TABLE_LOC "Table"
Expand Down
4 changes: 4 additions & 0 deletions LIB/upswiz.vc2
Original file line number Diff line number Diff line change
Expand Up @@ -4386,7 +4386,9 @@ DEFINE CLASS upsizingwizardform AS basewizardform OF "basewizard.vcx"
Combo1.Name = "Combo1", ;
lblReportDir.Name = "lblReportDir", ;
lblReportOptions.Name = "lblReportOptions", ;
lblServerTempFolder.Name = "lblServerTempFolder", ;
txtReportDir.Name = "txtReportDir", ;
txtServerTempFolder.Name = "txtServerTempFolder", ;
Wizlabel1.Name = "Wizlabel1", ;
Wizlabel2.Name = "Wizlabel2", ;
Wizlabel3.Name = "Wizlabel3", ;
Expand Down Expand Up @@ -4538,6 +4540,7 @@ DEFINE CLASS upsizingwizardform AS basewizardform OF "basewizard.vcx"
llApp = upper(justext(lcProgram)) = 'APP'
lcMain = addbs(justpath(iif(llApp, lcProgram, ;
fullpath(justpath(lcProgram) + '\..\'))))
* The only function the Upsizing Wizard uses in UPSWIZ.FLL is GetSQLServers
lcFFLLocation = lcMain + 'UPSWIZ.FLL'
if file(lcFFLLocation)
try
Expand All @@ -4554,6 +4557,7 @@ DEFINE CLASS upsizingwizardform AS basewizardform OF "basewizard.vcx"

if not llApp
This.cPath = set('PATH')
set step on
lcPath = lcMain + 'program,' + lcMain + 'data,' + lcMain + 'lib'
set path to '&lcPath' additive
endif not llApp
Expand Down
Binary file modified LIB/upswiz.vct
Binary file not shown.
Binary file modified LIB/upswiz.vcx
Binary file not shown.
Binary file modified LIB/vfpctrls.vct
Binary file not shown.
Binary file modified LIB/vfpctrls.vcx
Binary file not shown.
31 changes: 20 additions & 11 deletions PROGRAM/bulkxmlload.prg
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* Function: BulkXMLLoad
* Purpose: Performs a SQL Server bulk XML load
* Author: Doug Hennig
* Last revision: 01/24/2019
* Last revision: 02/01/2019
* Parameters: tcAlias - the alias of the cursor to export
* tcTable - the name of the table to import into
* ttBlank - the value to use for blank DateTime values
Expand Down Expand Up @@ -88,13 +88,14 @@ local lnSelect, ;
loBulkLoad
#include ..\Include\AllDefs.H

* These characters are illegal according to the XML 1.0 specification. CHR(0)
* is also illegal, but we're leaving that alone because they may be situations
* where someone intentionally stores that.
* These characters are illegal according to the XML 1.0 specification.

#define XML_ILLEGAL_CHARS CHR(1)+CHR(2)+CHR(3)+CHR(4)+CHR(5)+CHR(6)+CHR(7)+CHR(8)+CHR(11)+CHR(12)+ ;
CHR(14)+CHR(15)+CHR(16)+CHR(17)+CHR(18)+CHR(19)+CHR(20)+CHR(21)+CHR(22)+ ;
CHR(23)+CHR(24)+CHR(25)+CHR(26)+CHR(27)+CHR(28)+CHR(29)+CHR(30)+CHR(31)
#define XML_ILLEGAL_CHARS 'chr(0)+chr(1)+chr(2)+chr(3)+chr(4)+chr(5)+' + ;
'chr(6)+chr(7)+chr(8)+chr(11)+chr(12)+chr(14)+' + ;
'chr(15)+chr(16)+chr(17)+chr(18)+chr(19)+' + ;
'chr(20)+chr(21)+chr(22)+chr(23)+chr(24)+' + ;
'chr(25)+chr(26)+chr(27)+chr(28)+chr(29)+' + ;
'chr(30)+chr(31)'

* If there are any date fields in the selected cursor and we're not supposed to
* upsize blank dates as NULL, create a cursor from it with the appropriate
Expand Down Expand Up @@ -142,17 +143,23 @@ if ascan(laFields, 'C', -1, -1, 2, 7) > 0 or ;
* Loop through the non-NOCPTRANS string fields and strip out any illegal
* characters. This assumes that those characters were not entered
* intentionally and that we do not need to substitute something else for the
* characters being removed.
* characters being removed. Note: the reason "(lcField)" is used is to prevent
* an error if the field name is a reserved word like "FROM".

for lnI = 1 to lnFields
lcField = laFields[lnI, 1]
lcType = laFields[lnI, 2]
if inlist(lcType, 'C', 'M', 'V') and not laFields[lnI, 6]
lcReplaceCommand = 'REPLACE ' + lcField + ' WITH CHRTRAN(' + ;
lcField + ", '" + XML_ILLEGAL_CHARS + ;
"', '') FOR NOT EMPTY(" + ;
lcReplaceCommand = 'REPLACE (lcField) WITH CHRTRAN(' + ;
lcField + ', ' + XML_ILLEGAL_CHARS + ;
", '') FOR NOT EMPTY(" + ;
iif(lcType = 'M', 'RTRIM(' + lcField + ')', lcField) + ')'
try
&lcReplaceCommand
catch to loException
messagebox(tcAlias + chr(13) + lcReplaceCommand)
set step on
endtry
endif inlist(lcType, 'C', 'M', 'V') ...
next lnI
endif ascan(laFields ...
Expand Down Expand Up @@ -235,6 +242,8 @@ do while lnRecsProcessed < reccount()
loBulkLoad.Execute(lcSchema, lcData)
catch to loException
lcReturn = loException.Message
messagebox(lcReturn)
set step on
endtry
endif empty(lcReturn)
lnRecsProcessed = lnRecsProcessed + lnRecords
Expand Down
21 changes: 16 additions & 5 deletions PROGRAM/wizusz.prg
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ DEFINE CLASS UpsizeEngine AS WizEngineAll of WZEngine.prg

*ODBC-related properties
MasterConnHand=0
*** DH 2019-01-29: added new property
DisconnectOnExit = .T.
CONNECTSTRING=""
DataSourceName=""
ServerType="SQL Server"
Expand Down Expand Up @@ -243,8 +245,10 @@ DEFINE CLASS UpsizeEngine AS WizEngineAll of WZEngine.prg
cDir = Sys(16)
cDir = FullPath(Addbs(justpath(substr(m.cDir, atc(' ', m.cDir, 2) + 1))) + '..\')
&& upsizing wizard root folder
*** 2019-02-01: include program folder in path
if Empty(_VFP.StartMode) and not lower(m.cDir) + 'data' $ lower(set('PATH'))
set path to (m.cDir + 'data;' + m.cDir + 'program;') additive
*** set path to (m.cDir + 'data;' + m.cDir + 'program;') additive
set path to (m.cDir + ';' + m.cDir + 'data;' + m.cDir + 'program;') additive
endif
*** 2015-11-30 DH: end of new code
endfunc
Expand Down Expand Up @@ -530,7 +534,9 @@ DEFINE CLASS UpsizeEngine AS WizEngineAll of WZEngine.prg
* ENDIF

*Connection cleanup
IF THIS.MasterConnHand>0 THEN
*** DH 2019-01-29: only disconnect if DisconnectOnExit is .T.
*** IF THIS.MasterConnHand>0 THEN
if This.MasterConnHand > 0 and This.DisconnectOnExit
SQLDISCONN(THIS.MasterConnHand)
ENDIF

Expand Down Expand Up @@ -1909,8 +1915,8 @@ DEFINE CLASS UpsizeEngine AS WizEngineAll of WZEngine.prg
* jvf 1/9/01 SQL >= 7 can handle 1024 SP Parameters. Handled in Case below.
ll255=(MAX_PARAMS=THIS.CountFields(lcCursorName))

* If we're upsizing to SQL Server 2005 or later, try to do a bulk XML import
* since it's way faster.
* If we're upsizing to SQL Server 2005 or later, try to do a bulk SQL copy or
* XML import since they're way faster.

if This.SQLServer and This.ServerVer >= 9
llDone = This.BulkXMLLoad(lcTableName, lcCursorName, ;
Expand All @@ -1925,6 +1931,7 @@ DEFINE CLASS UpsizeEngine AS WizEngineAll of WZEngine.prg
case llDone
CASE lcExportType = "BULKINSERT" AND THIS.Perm_Database
* jvf Use SQL 7's BULK INSERT technique
messagebox('Bulk insert for ' + lcTableName)
lnExportErrors=THIS.BulkInsert(lcTableName, lcCursorName, ;
lcRmtTableName, @llMaxErrExceeded)
IF (lnExportErrors == -1) THEN
Expand All @@ -1934,10 +1941,12 @@ DEFINE CLASS UpsizeEngine AS WizEngineAll of WZEngine.prg
CASE lcExportType = "FASTEXPORT" AND THIS.Perm_Sproc AND ;
(!ll255 OR (THIS.ServerType="Oracle" OR THIS.ServerVer<7)) AND !TStampAdd
*go fast if possible and user can create sprocs
messagebox('Fast insert for ' + lcTableName)
lnExportErrors=THIS.FastExport(lcTableName, lcCursorName, lcRmtTableName, @llMaxErrExceeded)
OTHERWISE
*** 11/20/2012: pass .T. to JimExport so it updates the thermometer
*** lnExportErrors=THIS.JimExport(lcTableName, lcCursorName, lcRmtTableName, @llMaxErrExceeded)
messagebox('Jim insert for ' + lcTableName)
lnExportErrors=THIS.JimExport(lcTableName, lcCursorName, lcRmtTableName, @llMaxErrExceeded, '', .T.)
ENDCASE

Expand All @@ -1954,6 +1963,8 @@ DEFINE CLASS UpsizeEngine AS WizEngineAll of WZEngine.prg
ELSE
IF lnExportErrors<>0 THEN
lcErrMsg=STRTRAN(SOME_ERRS_LOC,"|1",LTRIM(STR(lnExportErrors)))
*** DH 2019-01-30: include table name in message
lcErrMsg = strtran(lcErrMsg, '|2', lcTableName)
THIS.StoreError(.NULL.,"","",lcErrMsg,lcTableName,DATA_EXPORT_LOC)
ENDIF
ENDIF
Expand Down Expand Up @@ -9586,4 +9597,4 @@ DEFINE CLASS UpsizeEngine AS WizEngineAll of WZEngine.prg

RETURN lcRes
ENDPROC
ENDDEFINE
ENDDEFINE
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ This Sedna update release includes:

The Upsizing Wizard is part of [Sedna](https://github.com/VFPX/Sedna), a collection of libraries, samples and add-ons to Visual FoxPro 9.0 SP2.

**2019.02.04 Release**
This update adds a DisconnectOnExit property to the upsizing engine (the default is .T.) which allows you to keep the connection to SQL Server open after upsizing is completed (such as if you have other tasks to execute). It also handles field names with reserved words and removes CHR(0), which is an illegal XML character, from fields when doing bulk XML load.

**2019.01.24 Release**
This update handles large tables in BulkXMLLoad better by processing records in batches. It also renames the built-in tables Keywords.dbf, ExprMap.dbf, and TypeMap.dbf to have an underscore prefix to avoid conflict with tables using those names in the database to be upsized.

Expand Down
Binary file modified UpsizingWizard.PJT
Binary file not shown.
Binary file modified upsizingwizard.app
Binary file not shown.
4 changes: 2 additions & 2 deletions upsizingwizard.pj2
Original file line number Diff line number Diff line change
Expand Up @@ -86,12 +86,12 @@ WITH loProject.FILES
.ADD('lib\sfprogressbar.vcx') && *< FileMetadata: Type="V" Cpid="1252" Timestamp="0" ID="0" ObjRev="544" User="" DevInfo="XzU5MDBPNVo2TQ==" />
.ADD('lib\upswiz.vcx') && *< FileMetadata: Type="V" Cpid="1252" Timestamp="0" ID="0" ObjRev="544" User="" DevInfo="XzU5MDBPNVo0Rw==" />
.ADD('lib\vfpctrls.vcx') && *< FileMetadata: Type="V" Cpid="1252" Timestamp="0" ID="0" ObjRev="544" User="" DevInfo="XzU5MDBPNVo2Sw==" />
.ADD('program\bulkxmlload.prg') && *< FileMetadata: Type="P" Cpid="1252" Timestamp="0" ID="0" ObjRev="544" User="" DevInfo="AQARAGluY2x1ZGVcYWxsZGVmcy5orqTzZvhC" />
.ADD('program\bulkxmlload.prg') && *< FileMetadata: Type="P" Cpid="1252" Timestamp="0" ID="0" ObjRev="544" User="" DevInfo="AQARAGluY2x1ZGVcYWxsZGVmcy5ozhkNhj5O" />
.ADD('program\foxresource.prg') && *< FileMetadata: Type="P" Cpid="1252" Timestamp="0" ID="0" ObjRev="544" User="" DevInfo="" />
.ADD('program\main.prg') && *< FileMetadata: Type="P" Cpid="1252" Timestamp="0" ID="0" ObjRev="544" User="" DevInfo="" />
.ADD('program\upswzfunc.prg') && *< FileMetadata: Type="P" Cpid="1252" Timestamp="0" ID="0" ObjRev="544" User="" DevInfo="" />
.ADD('program\wizjoin.prg') && *< FileMetadata: Type="P" Cpid="1252" Timestamp="0" ID="0" ObjRev="544" User="" DevInfo="" />
.ADD('program\wizusz.prg') && *< FileMetadata: Type="P" Cpid="1252" Timestamp="0" ID="0" ObjRev="544" User="" DevInfo="AQARAGluY2x1ZGVcYWxsZGVmcy5olvXzZvhC" />
.ADD('program\wizusz.prg') && *< FileMetadata: Type="P" Cpid="1252" Timestamp="0" ID="0" ObjRev="544" User="" DevInfo="AQARAGluY2x1ZGVcYWxsZGVmcy5oxhYNhj5O" />
.ADD('program\wzengine.prg') && *< FileMetadata: Type="P" Cpid="1252" Timestamp="0" ID="0" ObjRev="544" User="" DevInfo="AQAQAGluY2x1ZGVcd2l6YXJkLmiupGdn5DQ=" />
.ADD('upswiz.fll') && *< FileMetadata: Type="L" Cpid="0" Timestamp="0" ID="0" ObjRev="0" User="" DevInfo="XzU5MDBPNVoxWg==" />
*</BuildProj>
Expand Down
Binary file modified upsizingwizard.pjx
Binary file not shown.

0 comments on commit 2017b6a

Please sign in to comment.