DbUtils.lua
上传用户:cccombo
上传日期:2021-01-31
资源大小:16445k
文件大小:22k
源码类别:

MySQL数据库

开发平台:

SQL

  1. -- ----------------------------------------------------------------------------------------
  2. -- Copyright (C) 2004 MySQL AB
  3. --
  4. -- This program is free software; you can redistribute it and/or modify
  5. -- it under the terms of the GNU General Public License as published by
  6. -- the Free Software Foundation; either version 2 of the License, or
  7. -- (at your option) any later version.
  8. --
  9. -- This program is distributed in the hope that it will be useful,
  10. -- but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12. -- GNU General Public License for more details.
  13. --
  14. -- You should have received a copy of the GNU General Public License
  15. -- along with this program; if not, write to the Free Software
  16. -- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  17. -- ----------------------------------------------------------------------------------------
  18. -- ----------------------------------------------------------------------------------------
  19. -- @file Workbench.lua
  20. -- @brief Module that contains program logic for MySQL Workbench
  21. -- ----------------------------------------------------------------------------------------
  22. -- ----------------------------------------------------------------------------------------
  23. -- @brief Returns the information about this module
  24. --
  25. --   Every Grt module has to implement this function to return information about the 
  26. -- module. Note that new functions that should be exposed to the Grt have to be listed 
  27. -- here. Function that are not exposed should start with a underscore.
  28. --
  29. -- @return A dict that contains the name and the function names of the module
  30. -- ----------------------------------------------------------------------------------------
  31. function getModuleInfo()
  32.   local moduleInfo= 
  33.     {
  34.       name= "DbUtils", 
  35.       functions= {
  36.         "mergeCatalogs::",
  37.         "removeIgnoredObjectsFromCatalog::",
  38.         "removeEmptySchemataFromCatalog::",
  39.         "setColumnDatatypeByString::",
  40.         "getColumnDatatypeAsString::",
  41.         "getRoutineName::",
  42.         "getRoutineType::",
  43.         "getTriggerStatement::",
  44.         "getTriggerEvent::",
  45.         "getTriggerTiming::",
  46.         "copyColumnType::",
  47.         "getCatalogsChanges::",
  48.         "generateTableTestData::"
  49.       }, 
  50.       extends= ''
  51.     }
  52.   return moduleInfo
  53. end
  54. -- ----------------------------------------------------------------------------------------
  55. -- @brief Builds a tree of db.DatabaseSyncObject 
  56. -- 
  57. --   Builds a tree of db.DatabaseSyncObject which described the differences between
  58. -- the original catalog and modified
  59. --
  60. -- @param originalCatalog
  61. -- @param modifiedCatalog
  62. --
  63. -- @return the tree object on success or nil on error
  64. -- ----------------------------------------------------------------------------------------
  65. -- function getCatalogsChanges(args)
  66.   
  67. --  local t= grtV.newObj("db.DatabaseSyncObject", "syncObj", grt.newGuid(), "")
  68. --  local originalCatalog= args[1]
  69. --  local modifiedCatalog= args[2]  
  70. --  t.dbObject= originalCatalog
  71. --  t.modelObject= modifiedCatalog
  72.   
  73. --  return grt.success(t)
  74. -- end
  75. -- ----------------------------------------------------------------------------------------
  76. -- @brief Merges two catalogs
  77. --
  78. --   Adds all schemata from the source catalog to the target catalog. If there are
  79. -- duplicate schema names the user is asked to enter a unique name.
  80. -- The owner field of added schemas is updated to the new catalog.
  81. --
  82. -- @param sourceCatalog
  83. -- @param targetCatalog
  84. --
  85. -- @return 1 on success or an error
  86. -- ----------------------------------------------------------------------------------------
  87. function mergeCatalogs(args)
  88.   if (args == nil) or (grtV.getn(args) ~= 2) then
  89.     return grt.error(_("This function needs two catalogs as arguments."))
  90.   end
  91.   
  92.   local sourceCatalog= args[1]
  93.   local targetCatalog= args[2]
  94.   local i
  95.   
  96.   -- loop over all schemata in the source catalog
  97.   for i= 1, grtV.getn(sourceCatalog.schemata) do
  98.     local sourceSchema= sourceCatalog.schemata[i]
  99.     local nameIsUnique= false
  100.     local j
  101.     local schemaName= grtV.toLua(sourceSchema.name)
  102.     
  103.     -- loop until the schema name is unique
  104.     while not(nameIsUnique) and (schemaName ~= "") do
  105.       nameIsUnique= true
  106.       
  107.       -- check the source schema name against all schemata in the target catalog
  108.       for j= 1, grtV.getn(targetCatalog.schemata) do
  109.         if grtV.toLua(targetCatalog.schemata[j].name) == schemaName then
  110.           nameIsUnique= false
  111.           break
  112.         end
  113.       end
  114.     
  115.       -- if the name is already taken, ask the user for another name
  116.       if not(nameIsUnique) then
  117.         schemaName= input(string.format(_("The schema name "%s" is not unique. " ..
  118.           "Please enter a new name or leave the name empty to skip this schema."), schemaName))
  119.       end
  120.     end
  121.     
  122.     -- if the user enters "", skip this schema
  123.     if schemaName ~= "" then
  124.       sourceSchema.name= schemaName
  125.       sourceSchema.owner= targetCatalog
  126.       -- add source schema to target catalog
  127.       grtV.insert(targetCatalog.schemata, sourceSchema)
  128.     end
  129.   end
  130.   
  131.   -- Free cached GRT values on Lua side
  132.   collectgarbage()
  133.   
  134.   return grt.success()
  135. end
  136. -- ----------------------------------------------------------------------------------------
  137. -- @brief Removes all objects from a catalog that are on the given ignore list
  138. --
  139. --   Loops over all schemata and schema objects and removes the objects that are on
  140. -- the ignore list
  141. --
  142. -- @param catalog
  143. -- @param ignoreList
  144. --
  145. -- @return 1 on success or an error
  146. -- ----------------------------------------------------------------------------------------
  147. function removeIgnoredObjectsFromCatalog(args)
  148.   if (args == nil) or (grtV.getn(args) ~= 2) then
  149.     return grt.error(_("This function needs a catalog and an ignore list as arguments."))
  150.   end
  151.   
  152.   local i
  153.   local catalog= args[1]
  154.   local ignoreList= args[2]
  155.   
  156.   -- loop over all schemata
  157.   for i= 1, grtV.getn(catalog.schemata) do
  158.     local schema= catalog.schemata[i]
  159.     local schemaStructName= grtS.get(schema)
  160.     local member= grtS.getMembers(schemaStructName)
  161.     local j
  162.     
  163.     -- check all members of the schema struct
  164.     for j= 1, table.getn(member) do
  165.       local memberContentStruct= grtS.getMemberContentStruct(schemaStructName, member[j])
  166.       
  167.       -- if the member holds a list of objects that derive from "db.DatabaseObject" check it
  168.       if (memberContentStruct ~= nil) and grtS.inheritsFrom(memberContentStruct, "db.DatabaseObject") then
  169.         local objList= schema[member[j]]
  170.         
  171.         if objList ~= nil then
  172.           local k
  173.           
  174.           -- loop over all objects in the list
  175.           for k= grtV.getn(objList), 1, -1 do
  176.             local objStructName= grtS.get(objList[k])
  177.             
  178.             -- check if this object is on the ignore list
  179.             for l= 1, grtV.getn(ignoreList) do
  180.               local ignoreString= objStructName .. ":" .. grtV.toLua(schema.name) .. "." .. 
  181.                 grtV.toLua(objList[k].name)
  182.                 
  183.               -- if it is, remove it from the list
  184.               if (ignoreString == grtV.toLua(ignoreList[l])) then
  185.                 grtV.remove(objList, k)
  186.                 break -- bug #18778
  187.               end
  188.             end
  189.           end
  190.         end
  191.       end
  192.     end
  193.   end
  194.   
  195.   -- Free cached GRT values on Lua side
  196.   collectgarbage()
  197.   
  198.   return grt.success()
  199. end
  200. -- ----------------------------------------------------------------------------------------
  201. -- @brief Removes all schemata from the given catalog if they are empty
  202. --
  203. --   Removes all schemata from the given catalog if they contain no sub-objects
  204. --
  205. -- @param catalog a catalog object
  206. --
  207. -- @return 1 on success or an error
  208. -- ----------------------------------------------------------------------------------------
  209. function removeEmptySchemataFromCatalog(args)
  210.   local catalog= args[1]
  211.   local i
  212.   local isEmpty= true
  213.   
  214.   -- loop over all schemata
  215.   for i= grtV.getn(catalog.schemata), 1, -1 do
  216.     local schema= catalog.schemata[i]
  217.     local schemaStructName= grtS.get(schema)
  218.     local j
  219.     
  220.     -- check all schemata member variables
  221.     local members= grtS.getMembers(schemaStructName)
  222.     for j= 1, grtV.getn(members) do
  223.     
  224.       -- if the member variable is a list
  225.       if (grtS.getMemberType(schemaStructName, members[j]) == "list") then
  226.         local memberContentType= grtS.getMemberContentStruct(schemaStructName, members[j])
  227.         
  228.         -- check content type of the list and the list count
  229.         if ((memberContentType ~= nil) and grtS.inheritsFrom(memberContentType, "db.DatabaseObject")) and 
  230.           (grtV.getn(schema[members[j]]) > 0) then
  231.           isEmpty= false
  232.           break
  233.         end
  234.       end
  235.     end
  236.     
  237.     if isEmpty then
  238.       print(string.format(_("Removing schema %s"), grtV.toLua(catalog.schemata[i].name)))
  239.       grtV.remove(catalog.schemata, i)
  240.     end
  241.   end
  242.   
  243.   return grt.success()
  244. end
  245. -- ----------------------------------------------------------------------------------------
  246. -- @brief Sets the datatype defined by a string to the given column
  247. --
  248. --   Assigns a datatype defined by a string like NUMERIC(7, 2) to the
  249. -- given column
  250. --
  251. -- @param simpleDatatypeSource can be a RDBMS, a list or a ref list of SimpleDatatypes
  252. -- @param column
  253. -- @param datatypeString
  254. --
  255. -- @return 1 on success or an error
  256. -- ----------------------------------------------------------------------------------------
  257. function setColumnDatatypeByString(args)
  258.   local simpleDatatypeSource= args[1]
  259.   local column= args[2]
  260.   local datatypeString= grtV.toLua(args[3])
  261.   
  262.   -- regex to split INT (10, 5)
  263.   -- (w*)s*(((d+)s*(,s*(d+))?))?
  264.   -- 1.. INT
  265.   -- 3.. 10 (optional)
  266.   -- 5.. 5 (optional)
  267.   local regExDatatype= "(\w*)\s*(\((\d+)\s*(\,\s*(\d+))?\))?"
  268.   
  269.   -- regex to split ENUM ("red", "blue")
  270.   -- (w*)s*((.*)?)?
  271.   -- 1.. ENUM
  272.   -- 2.. ("red", "blue")
  273.   local regExExplicitParams= "(\w*)\s*(\(.*)?\)?"
  274.   
  275.   -- get datatype name
  276.   local datatypeName= grtU.regExVal(datatypeString, regExDatatype, 1)
  277.   
  278.   column.precision= 0
  279.   column.scale= 0
  280.   column.length= 0
  281.   column.datatypeExplicitParams= ""
  282.   if datatypeName ~= nil then
  283.     local simpleDatatype
  284.     column.datatypeName= datatypeName
  285.     
  286.     -- find the simple datatype with this datatypeName
  287.     if grtV.typeOf(simpleDatatypeSource) == "dict" then
  288.       simpleDatatype= grtV.getListItemByObjName(simpleDatatypeSource.simpleDatatypes, datatypeName)
  289.     elseif (grtV.getContentType(simpleDatatypeSource) == "string") then
  290.       simpleDatatype= grtV.getListRefValueByObjName(simpleDatatypeSource, datatypeName)
  291.     else
  292.       simpleDatatype= grtV.getListItemByObjName(simpleDatatypeSource, datatypeName)
  293.     end
  294.     
  295.     if simpleDatatype ~= nil then
  296.       column.simpleType= simpleDatatype
  297.       
  298.       -- get precision
  299.       if grtV.toLua(simpleDatatype.numericPrecision) > 0 then
  300.         local precision= grtU.regExVal(datatypeString, regExDatatype, 3)
  301.         
  302.         if precision ~= "" then
  303.           column.precision= tonumber(precision)
  304.         end
  305.         
  306.         -- get scale
  307.         if grtV.toLua(simpleDatatype.numericScale) > 0 then
  308.           local scale= grtU.regExVal(datatypeString, regExDatatype, 5)
  309.           
  310.           if scale ~= "" then
  311.             column.scale= tonumber(scale)
  312.           end
  313.         end
  314.       -- get length
  315.       elseif grtV.toLua(simpleDatatype.characterMaximumLength) > 0 then
  316.         local length= grtU.regExVal(datatypeString, regExDatatype, 3)
  317.         
  318.         if length ~= "" then
  319.           column.length= tonumber(length)
  320.         end        
  321.       -- other stuff like ENUM()
  322.       else
  323.         column.datatypeExplicitParams= grtU.regExVal(datatypeString, regExExplicitParams, 2)
  324.       end
  325.     else
  326.       column.datatypeExplicitParams= grtU.regExVal(datatypeString, regExExplicitParams, 2)
  327.     end
  328.   end
  329.   
  330.   return grt.success()
  331. end
  332. -- ----------------------------------------------------------------------------------------
  333. -- @brief Returns the datatype of the given column as string
  334. --
  335. --   Returns the datatype of the given column as string like "NUMERIC(7, 2)"
  336. --
  337. -- @param rdbms
  338. -- @param column
  339. --
  340. -- @return the datatype string on success or an error
  341. -- ----------------------------------------------------------------------------------------
  342. function getColumnDatatypeAsString(args)
  343.   local column= args[1]
  344.   local simpleDatatype= column.simpleType
  345.   local typeString
  346.   
  347.   if (simpleDatatype ~= nil) and (grtV.typeOf(simpleDatatype) == "dict") then
  348.     typeString= grtV.toLua(simpleDatatype.name)
  349.     
  350.     -- check precision
  351.     if grtV.toLua(simpleDatatype.numericPrecision) > 0 then
  352.       local precision= grtV.toLua(column.precision)
  353.       
  354.       if precision > 0 then
  355.         typeString= typeString .. "(" .. precision
  356.         
  357.         -- check scale
  358.         if grtV.toLua(simpleDatatype.numericScale) > 0 then
  359.           local scale= grtV.toLua(column.scale)
  360.           
  361.           if (scale > 0) then
  362.             typeString= typeString .. ", " .. scale
  363.           end
  364.         end
  365.         
  366.         typeString= typeString .. ")"
  367.       end
  368.       
  369.     elseif grtV.toLua(simpleDatatype.characterMaximumLength) > 0 then
  370.       typeString= typeString .. "(" .. grtV.toLua(column.length) .. ")"
  371.     else
  372.       local explParams= grtV.toLua(column.datatypeExplicitParams)
  373.       
  374.       typeString= typeString .. explParams
  375.     end
  376.   else
  377.     local precision= grtV.toLua(column.precision)
  378.     local length= grtV.toLua(column.length)
  379.     local explParams= grtV.toLua(column.datatypeExplicitParams)
  380.     
  381.     typeString= grtV.toLua(column.datatypeName)
  382.     
  383.     if precision > 0 then
  384.       local scale= grtV.toLua(column.scale)
  385.       
  386.       typeString= typeString .. "(" .. precision
  387.       
  388.       if scale > 0 then
  389.         typeString= typeString .. ", " .. scale
  390.       end
  391.       
  392.       typeString= typeString .. ")"
  393.     elseif length > 0 then
  394.       typeString= typeString .. "(" .. length .. ")"
  395.     elseif explParams ~= "" then
  396.       typeString= typeString .. explParams
  397.     end
  398.   end
  399.   return grt.success(typeString)
  400. end
  401. -- ----------------------------------------------------------------------------------------
  402. -- @brief Returns the name from the given routine SQL
  403. --
  404. --   Returns the name from the given routine SQL
  405. --
  406. -- @param sql
  407. --
  408. -- @return the name string on success or an error
  409. -- ----------------------------------------------------------------------------------------
  410. function getRoutineName(args)
  411.   local sql= grtV.toLua(args[1])
  412.   local name
  413.   
  414.   -- .creates+(procedure|function)s+(w+)s*(
  415.   name= grtU.regExVal(sql, ".*create\s+(procedure|function|trigger)\s+(\w+)\s*", 2)
  416.   
  417.   return grt.success(name)
  418. end
  419. -- ----------------------------------------------------------------------------------------
  420. -- @brief Returns the trigger statement from the given trigger SQL
  421. --
  422. --   Returns the trigger statement from the given trigger SQL
  423. --
  424. -- @param sql
  425. --
  426. -- @return the trigger statement string on success or an error
  427. -- ----------------------------------------------------------------------------------------
  428. function getTriggerStatement(args)
  429.   local sql= grtV.toLua(args[1])
  430.   local name
  431.   
  432.     name= grtU.regExVal(sql, ".*create\s+trigger\s+\w+\s*(before|after)\s*(insert|update|delete)\s*on\s*\w+\s*for\s*each\s*row\r?\n?((.|\r|\n|\s)*)", 3)
  433.   
  434.   return grt.success(name)
  435. end
  436. -- ----------------------------------------------------------------------------------------
  437. -- @brief Returns the trigger event from the given trigger SQL
  438. --
  439. --   Returns the trigger event from the given trigger SQL
  440. --
  441. -- @param sql
  442. --
  443. -- @return the trigger event string on success or an error
  444. -- ----------------------------------------------------------------------------------------
  445. function getTriggerEvent(args)
  446.   local sql= grtV.toLua(args[1])
  447.   local name
  448.   
  449.     name= grtU.regExVal(sql, ".*create\s+trigger\s+\w+\s*(before|after)\s*(insert|update|delete)((.|\r|\n|\s)*)", 2)
  450.   
  451.   return grt.success(name)
  452. end
  453. -- ----------------------------------------------------------------------------------------
  454. -- @brief Returns the trigger timing from the given trigger SQL
  455. --
  456. --   Returns the trigger timing from the given trigger SQL
  457. --
  458. -- @param sql
  459. --
  460. -- @return the trigger timing string on success or an error
  461. -- ----------------------------------------------------------------------------------------
  462. function getTriggerTiming(args)
  463.   local sql= grtV.toLua(args[1])
  464.   local name
  465.   
  466.     name= grtU.regExVal(sql, ".*create\s+trigger\s+\w+\s*(before|after)((.|\r|\n|\s)*)", 1)
  467.   
  468.   return grt.success(name)
  469. end
  470. -- ----------------------------------------------------------------------------------------
  471. -- @brief Returns the name from the given routine SQL
  472. --
  473. --   Returns the name from the given routine SQL
  474. --
  475. -- @param sql
  476. --
  477. -- @return the name string on success or an error
  478. -- ----------------------------------------------------------------------------------------
  479. function getRoutineType(args)
  480.   local sql= grtV.toLua(args[1])
  481.   local routineType
  482.   -- .creates+(procedure|function)s+(w+)s*(
  483.   routineType= grtU.regExVal(sql, ".*create\s+(procedure|function|trigger)\s+(\w+)\s*", 1)
  484.   
  485.   return grt.success(routineType)
  486. end
  487. -- ----------------------------------------------------------------------------------------
  488. -- @brief Copies the column datatype from the source column to the dest column
  489. --
  490. -- @param sourceColumn
  491. -- @param destColumn
  492. -- 
  493. -- ----------------------------------------------------------------------------------------
  494. function copyColumnType(args)
  495.   local source= args[1]
  496.   local dest= args[1]
  497.   dest["datatypeName"]= grtV.toLua(source["datatypeName"])
  498.   if source["precision"] ~= nil then
  499.     dest["precision"]= grtV.toLua(source["precision"])
  500.   end 
  501.   if source["scale"] ~= nil then
  502.     dest["scale"]= grtV.toLua(source["scale"])
  503.   end
  504.   if source["length"] ~= nil then
  505.     dest["length"]= grtV.toLua(source["length"])
  506.   end
  507.   if source["characterSetName"] ~= nil then
  508.     dest["characterSetName"]= grtV.toLua(source["characterSetName"])
  509.   end 
  510.   if source["collationName"] ~= nil then
  511.     dest["collationName"]= grtV.toLua(source["collationName"])
  512.   end
  513.   if source["flags"] ~= nil then
  514.     dest["flags"]= grtV.newList("string")
  515.     for i=1,grtV.getn(source["flags"]) do
  516.       grtV.insert(dest["flags"], grtV.toLua(source["flags"][i]))
  517.     end
  518.   end
  519.   if source["simpleType"] ~= nil then
  520.     dest["simpleType"]= grtV.toLua(source["simpleType"])
  521.   end
  522.   if source["structuredDatatype"] ~= nil then
  523.     dest["structuredDatatype"]= grtV.toLua(source["structuredDatatype"])
  524.   end
  525.   if source["datatypeExplicitParams"] ~= nil then
  526.     dest["datatypeExplicitParams"]= grtV.toLua(source["datatypeExplicitParams"])
  527.   end
  528.   return grt.success()
  529. end
  530. -- ----------------------------------------------------------------------------------------
  531. -- @brief Generates test data that can be used for tests, yet not all datatypes are handled
  532. --
  533. -- @param tbl  the db.Table to generate testdata for
  534. -- @param numOfRows  number of rows to generate
  535. -- @param fileName  the filename the INSERT statements get written to
  536. -- 
  537. -- ----------------------------------------------------------------------------------------
  538. function generateTableTestData(tbl, numOfRows, fileName)
  539.   local i, j
  540.   local sql= ""
  541.   local sqlHeader= "INSERT INTO " .. grtV.toLua(tbl.name) .. "("
  542.   local colUnsigned= {}
  543.   local sqlFile= io.open(fileName, "w")
  544.   
  545.   -- built INSERT header listing all columns
  546.   for i= 1, grtV.getn(tbl.columns) do    
  547.     local col= tbl.columns[i]
  548.     if (i > 1) then
  549.       sqlHeader= sqlHeader .. ", "
  550.     end
  551.     
  552.     sqlHeader= sqlHeader .. grtV.toLua(col.name)
  553.     
  554.     -- cache unsigned flag
  555.     colUnsigned[i]= 0
  556.     for j= 1, grtV.getn(col.flags) do
  557.       if grtV.toLua(col.flags[j]) == "unsigned" then
  558.         colUnsigned[i]= 1
  559.         break
  560.       end
  561.     end
  562.   end
  563.   sqlHeader= sqlHeader .. ") VALUESn  ("
  564.   
  565.   sql= sqlHeader
  566.   
  567.   -- generate as much rows as needed
  568.   for i= 1, numOfRows do
  569.     for j= 1, grtV.getn(tbl.columns) do
  570.       local col= tbl.columns[j]
  571.       
  572.       if (j > 1) then
  573.         sql= sql .. ", "
  574.       end
  575.       
  576.       if (grtV.toLua(col.autoIncrement) == 1) then
  577.         -- deal with AutoIncrement values
  578.         sql= sql .. i
  579.       elseif (grtV.toLua(col.datatypeName) == "TINYINT") or 
  580.         (grtV.toLua(col.datatypeName) == "SMALLINT") or
  581.         (grtV.toLua(col.datatypeName) == "MEDIUMINT") or
  582.         (grtV.toLua(col.datatypeName) == "INT") or
  583.         (grtV.toLua(col.datatypeName) == "BIGINT") then
  584.         -- deal with INTEGER values
  585.         local val
  586.         local intRange= 255
  587.         
  588.         if grtV.toLua(col.datatypeName) == "SMALLINT" then
  589.           intRange= 65535
  590.         elseif grtV.toLua(col.datatypeName) == "MEDIUMINT" then
  591.           intRange= 16777215
  592.         elseif grtV.toLua(col.datatypeName) == "MEDIUMINT" then
  593.           intRange= 4294967295
  594.         end
  595.         
  596.         if colUnsigned[i] == 0 then
  597.           val= (math.random(intRange) - math.floor(intRange / 2))
  598.         else
  599.           val= math.random(intRange)        
  600.         end
  601.         
  602.         sql= sql .. val
  603.       elseif (grtV.toLua(col.datatypeName) == "VARCHAR") or
  604.         (grtV.toLua(col.datatypeName) == "CHAR") then
  605.         -- deal with string values
  606.         local k
  607.         local val= ""
  608.         local len= grtV.toLua(col.length)        
  609.         len= len - math.random(len - 1)
  610.         
  611.         for k= 1, len do
  612.           val= val .. string.char(math.random(65, 90))
  613.         end
  614.         
  615.         sql= sql .. "'" .. val .. "'"
  616.       end
  617.     end
  618.     
  619.     -- make sure to not excede maximum command length
  620.     if string.len(sql) < 16000 and i < numOfRows then
  621.       sql= sql .. "),n  ("
  622.     else
  623.       sql= sql .. ");nn"
  624.       sqlFile:write(sql)
  625.       
  626.       sql= sqlHeader
  627.     end
  628.     
  629.     -- print status
  630.     if i - math.floor(i/100)*100 == 0 then
  631.       print("Rows processed: " .. i)
  632.     end
  633.   end
  634.   
  635.   if string.len(sql) ~= string.len(sqlHeader) then
  636.     sql= sql .. ");nn"
  637.     sqlFile:write(sql)
  638.   end
  639.   
  640.   sqlFile:close()
  641. end