// sort_items_num - Y pos to sort on, ASC OR DESC (numeric)\r
// matrix_delete - X and Y pos to delete \r
// delete_item - X position to delete (this reshuffles the matrix; avoid using)\r
+// type_store - Store column type against column (speeds up sort_items at expense of numeric inserts) DEFAULT\r
+// remove_type_store - Do not store column type against column (speeds up numeric inserts at expense of sort_items (but not sort_items_ascii or num))\r
// hash_on_column_algorithm - Hash algorithm to use\r
// hash_on_column - Y pos of column to hash\r
// remove_hash_on_column - Remove the hash from the column\r
property integer c_iLastIndexTableHash\r
property integer c_iLastIndexTablePos\r
property integer c_iEnforceUnique\r
+ property integer c_iMaintainTypes\r
property string c_sHashAlgorithm\r
+ property string c_sTypes\r
\r
+ set c_sTypes to ""\r
set c_sHashAlgorithm to ""\r
set c_iHashOn to -1\r
set c_iLastIndexTableHash to -1\r
set c_iLastIndexTablePos to -1\r
set c_iEnforceUnique to 0\r
+ set c_iMaintainTypes to 1\r
end_procedure \r
\r
// Pull the value of a column from the string representation\r
set c_sHashAlgorithm to hashalg\r
end \r
end_procedure\r
+\r
+ procedure type_store\r
+ set c_iMaintainTypes to 1\r
+ end_procedure\r
+ \r
+ procedure remove_type_store\r
+ set c_iMaintainTypes to 0\r
+ set c_sTypes to ""\r
+ end_procedure \r
\r
procedure hash_is_unique\r
set c_iEnforceUnique to 1\r
- end_procedure \r
+ end_procedure\r
\r
procedure remove_hash_is_unique\r
set c_iEnforceUnique to 0\r
end_procedure\r
\r
procedure set matrix_value integer itemx integer itemy string val\r
- local string l_sBuf l_sTmp l_sOldVal \r
- local integer l_i l_iWidth l_iHashOn l_iHash l_iEnforceUnique l_iHashError\r
+ local string l_sBuf l_sTmp l_sOldVal l_sTypes\r
+ local integer l_i l_iWidth l_iHashOn l_iHash l_iEnforceUnique l_iHashError l_iMaintainTypes\r
\r
move 0 to l_iHashError\r
get c_iWidth to l_iWidth\r
- get c_iHashOn to l_iHashOn\r
+ get c_iHashOn to l_iHashOn \r
\r
forward get array_value item itemx to l_sBuf\r
- \r
+ \r
+ //Maintain (guess of) types of columns\r
+ get c_iMaintainTypes to l_iMaintainTypes\r
+ if (l_iMaintainTypes = 1) begin\r
+ get c_sTypes to l_sTypes\r
+ //All columns start off as numeric\r
+ while (length(l_sTypes) < 1+itemy)\r
+ append l_sTypes "1"\r
+ loop\r
+ //If we encounter a non-numeric value when we have defined numeric switch the type\r
+ if ((mid(l_sTypes,1,1+itemy) = "1") and not (is_number(val))) begin\r
+ move (overstrike("0",l_sTypes,1+itemy)) to l_sTypes\r
+ set c_sTypes to l_sTypes\r
+ end \r
+ end\r
+ \r
+ // Maintain width of matrix \r
if (itemy > l_iWidth) begin\r
set c_iWidth to itemy\r
move itemy to l_iWidth\r
end_procedure\r
\r
procedure matrix_append_csv string row \r
- local integer l_iMax l_iValues l_i l_iHashOn l_iWidth l_iCount\r
- local string l_sBuf\r
+ local integer l_iMax l_iValues l_i l_iHashOn l_iWidth l_iOffset l_iCount l_iMaintainTypes\r
+ local string l_sChar l_sBuf l_sTypes\r
\r
get c_iHashOn to l_iHashOn\r
forward get item_count to l_iMax\r
\r
+ // If the csv data contains quoted data we currenlty have to\r
+ // pass each column on to matrix_value\r
if ((l_iHashOn <> -1) or (row contains '"')) begin \r
send delete_data to (mTokens2(current_object))\r
send set_string_csv to (mTokens2(current_object)) row\r
if (err) break\r
loop\r
end\r
+ // Otherwise we take a shortcut and set the array row in one\r
else begin\r
- get c_iWidth to l_iWidth \r
+ // Maintain width of matrix\r
+ get c_iWidth to l_iWidth\r
+ \r
+ //Maintain (guess of) types of columns\r
+ get c_iMaintainTypes to l_iMaintainTypes \r
+ if (l_iMaintainTypes = 1) begin\r
+ get c_sTypes to l_sTypes\r
+ move 0 to l_iOffset\r
+ end \r
+ else;\r
+ move (pos(',', row)) to l_iOffset\r
+ \r
move 0 to l_iCount\r
+ move "" to l_sBuf\r
forward set array_value item l_iMax to (replaces(',', row, character(1)))\r
- for l_i from (pos(',', row)) to (length(row))\r
- if (mid(row,1,l_i) = ',') increment l_iCount\r
+ for l_i from l_iOffset to (length(row))\r
+ move (mid(row,1,l_i)) to l_sChar\r
+ if (l_sChar = ',') begin\r
+ increment l_iCount\r
+ \r
+ if (l_iMaintainTypes = 1) begin\r
+ //All columns start off as numeric\r
+ while (length(l_sTypes) < l_iCount)\r
+ append l_sTypes "1"\r
+ loop\r
+ //If we encounter a non-numeric value when we have defined numeric switch the type\r
+ if ((mid(l_sTypes,1,l_iCount) = "1") and not (is_number(l_sBuf))) begin\r
+ move (overstrike("0",l_sTypes,l_iCount)) to l_sTypes\r
+ end \r
+ move "" to l_sBuf\r
+ end\r
+ end\r
+ else if (l_iMaintainTypes = 1);\r
+ append l_sBuf l_sChar\r
loop \r
- if (l_iCount > l_iWidth) set c_iWidth to l_iCount\r
+ if (l_iCount > l_iWidth);\r
+ set c_iWidth to l_iCount\r
+ if (l_iMaintainTypes = 1) begin\r
+ if ((mid(l_sTypes,1,l_iCount) = "1") and not (is_number(l_sBuf))) begin\r
+ move (overstrike("0",l_sTypes,l_iCount)) to l_sTypes\r
+ end \r
+ set c_sTypes to l_sTypes\r
+ end \r
end\r
\r
end_procedure\r
loop\r
close_output channel DEFAULT_FILE_CHANNEL\r
end_procedure \r
- \r
- \r
+ \r
function matrix_value integer itemx integer itemy returns string\r
local string l_sBuf l_sTmp\r
\r
\r
forward set array_value item itemx to l_sBuf\r
\r
- // Delete in the value to the hash\r
+ // Delete the value in the hash\r
if (l_iHashOn = itemy) begin \r
get find_hash of (mHash_table(current_object)) item l_sOldVal to l_iHash\r
if (l_iHash <> 0) begin \r
local integer l_iHashOn l_iHash l_i l_j l_iItems l_iIndexValues l_iIndex\r
\r
get c_iHashOn to l_iHashOn\r
- // Delete in the value to the hash\r
+ // Delete the value in the hash\r
if (l_iHashOn <> -1) begin\r
forward get array_value item itemx to l_sBuf\r
send delete_data to (mTokens(current_object))\r
end \r
end_procedure \r
\r
- // Perform a quick sort on a perticular column (y) in the martix\r
+ // Perform a quick sort on a particular column (y) in the martix\r
// This is done in native dataflex, so no match for compiled C\r
procedure quick_sort integer itemy string order integer mode\r
- local integer l_i l_j l_iHashOn l_iMax l_iInvert\r
- local string l_sBuf\r
+ local integer l_i l_j l_iHashOn l_iMax l_iInvert l_iMaintainTypes\r
+ local string l_sBuf l_sTypes\r
\r
if (uppercase(left(trim(order),4)) = "DESC") move 1 to l_iInvert\r
else move 0 to l_iInvert \r
\r
// If we've not been told string/numeric, try and work out here.\r
if (mode = -1) begin\r
- for l_i from 0 to (l_iMax-1)\r
- forward get array_value item l_i to l_sBuf\r
- get column_value item itemy item l_sBuf to l_sBuf\r
- move (is_number(l_sBuf)) to mode\r
- if (mode = 0) break\r
- loop\r
+ // If we've been maintaining type information use it\r
+ get c_iMaintainTypes to l_iMaintainTypes\r
+ if (l_iMaintainTypes = 1) begin\r
+ get c_sTypes to l_sTypes\r
+ move (integer(mid(l_sTypes,1,1+itemy))) to mode \r
+ end\r
+ // Else loop until we can make a decision\r
+ else begin\r
+ for l_i from 0 to (l_iMax-1)\r
+ forward get array_value item l_i to l_sBuf\r
+ get column_value item itemy item l_sBuf to l_sBuf\r
+ move (is_number(l_sBuf)) to mode\r
+ if (mode = 0) break\r
+ loop\r
+ end\r
end\r
\r
// Remove the current hash index if there is one \r