]> git.8kb.co.uk Git - dataflex/df32func/commitdiff
Maintain types on matrix columns
authorglyn <glyn@8kb.co.uk>
Tue, 6 Oct 2015 12:06:10 +0000 (13:06 +0100)
committerglyn <glyn@8kb.co.uk>
Tue, 6 Oct 2015 12:06:10 +0000 (13:06 +0100)
src/df32/data.inc [changed mode: 0644->0755]

old mode 100644 (file)
new mode 100755 (executable)
index 5f80d00..738d249
@@ -796,6 +796,8 @@ end_class
 //    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
@@ -870,13 +872,17 @@ class matrix is an array
         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
@@ -899,10 +905,19 @@ class matrix is an array
             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
@@ -981,15 +996,31 @@ class matrix is an array
     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
@@ -1058,12 +1089,14 @@ class matrix is an array
     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
@@ -1077,14 +1110,51 @@ class matrix is an array
                 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
@@ -1152,8 +1222,7 @@ class matrix is an array
             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
@@ -1327,7 +1396,7 @@ class matrix is an array
 \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
@@ -1353,7 +1422,7 @@ class matrix is an array
         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
@@ -1590,11 +1659,11 @@ class matrix is an array
         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
@@ -1603,12 +1672,21 @@ class matrix is an array
         \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