home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / dbutil.zip / BUFOP.ZIP / GENSQL.CPP < prev    next >
Text File  |  1993-09-13  |  16KB  |  454 lines

  1. #include "compsql.hpp"                                  
  2. #include <istring.hpp>                                  
  3. #include "files.hpp"
  4. #include <fstream.h>                                    
  5. #include <iset.h>                                       
  6. #include "hostvars.hpp"         // host variables       
  7. #include <sqlaprep.h>                                   
  8. #include <sql.h>                                        
  9. #include <stdlib.h>                                     
  10.  
  11. extern sqlca mysqlca;
  12. extern sqla_program_id progID; 
  13.  
  14. Boolean optimize;
  15.  
  16.  
  17. //
  18. //  On an SQL error, warning or not found - the goto labels
  19. //
  20. static IString NotFoundLabel="";
  21. static IString WarningLabel ="";
  22. static IString ErrorLabel = "";
  23.  
  24.  
  25. /*********************************************************************
  26. *   Generate the source code for access to the database
  27. *  The generate instructions are in the task array 
  28. *  (created by the precompiler services)
  29. *  Variables and usage is in the token array (usage filled in by
  30. *  precompiler services)
  31. **********************************************************************/
  32.  
  33. /*********************************************************************
  34. * Proto Types of internal functions to gen code
  35. *********************************************************************/
  36.  
  37. void inputFile(IString const & Stmt, unsigned long );
  38.  
  39. static unsigned short nxtSQLDA=1,inputSQLDA=0, outputSQLDA=0;
  40.  
  41. void genConnect(char type,      // exclusive or shared
  42.                 IString const & stmt, // SQL statment with DB name in
  43.                 unsigned long x,  // offset to DBName & DBLen
  44.                 ofstream & fout); // output file
  45.  
  46. void GenSetVArray(int nbrTokens,                
  47.                   unsigned short StmtID,        
  48.                   Boolean input,                
  49.                   ofstream & fout,              
  50.                   sqla_tokens * tokenArray);
  51.  
  52. void GenOnError(ofstream & fout);
  53.  
  54. void GenOnWarning(ofstream & fout);
  55.  
  56. void GenOnNotFound(ofstream & fout);
  57.  
  58. IString MakeLabel(IString & theLabel);
  59.  
  60. void GenIncludeSQLDA(ofstream & fout);
  61.  
  62. void GenIncludeSQLCA(ofstream & fout);
  63.  
  64. void GenSQLASets(int theID, ofstream & fout);
  65.  
  66.  
  67.  
  68. /*************************************************************  */
  69. /*  G E N E R A T E   C O D E    TO   I N T E R F A C E         */
  70. /*  D B 2 / 2                                                   */
  71. /************************************************************** */
  72.  
  73.  
  74. genSQL(ofstream & fout, sqla_tasks * taskArray, sqla_tokens * tokenArray,
  75.        unsigned short sectionNbr, IString const & Stmt, int stmttype)
  76. {
  77.    int task;
  78. //
  79. //  reset the sqlda ids for this call
  80. //
  81.    inputSQLDA = 0;
  82.    outputSQLDA = 0;
  83.    for (int j=0;j<taskArray->header.used ;j++ ) {
  84.       switch (taskArray->task[j].func) {
  85.         case SQLA_START:  fout <<  "     sqlastrt(&sqla_program_id,NULL,&sqlca); \n";
  86.            break;
  87.         case SQLA_DECLARE:
  88.               if (taskArray->task[j].val == SQLA_BEGIN) {
  89.                  setDeclare(true);
  90.               } else {
  91.                  setDeclare(false);
  92.               } /* endif */
  93.            break;
  94.         case SQLA_INCLUDE:   
  95.              if (taskArray->task[j].val == SQLA_SQLCA) {
  96.                 GenIncludeSQLCA(fout);
  97.              } else {
  98.                 GenIncludeSQLDA(fout);
  99.              } /* endif */
  100.  
  101.            break;
  102.         case SQLA_ALLOC_INPUT: GenSetVArray(taskArray->task[j].val,sectionNbr,
  103.                                        true,fout,tokenArray);
  104.  
  105.            break;
  106.       case SQLA_ALLOC_OUTPUT: GenSetVArray(taskArray->task[j].val,sectionNbr,
  107.                                       false,fout,tokenArray);
  108.            break;
  109.         case SQLA_SETS: GenSQLASets(taskArray->task[j].val, fout);
  110.            break;
  111.         case SQLA_USDA_INPUT: // TBD GenSQLDA(taskArray->task[j].value); 
  112.            break;
  113.         case SQLA_USDA_OUTPUT: // TBDGenInputSQLDA(taskArray->task[j].value);
  114.            break;
  115.         case SQLA_CALL: 
  116.                  fout << "     sqlacall("  
  117.                       << taskArray->task[j].val << ", "
  118.                       << sectionNbr << ", " 
  119.                       << inputSQLDA << ", " 
  120.                       << outputSQLDA
  121.                       << ",NULL); \n";
  122.            break;
  123.         case SQLA_DEALLOC:   /* not used */
  124.            break;
  125.         case SQLA_STOP:    fout << "     sqlastop(NULL); \n";
  126.            break;
  127.         case SQLA_SQLERROR: GenOnError(fout);
  128.            break;
  129.         case SQLA_SQLWARNING: GenOnWarning(fout);
  130.            break;
  131.         case SQLA_NOT_FOUND: GenOnNotFound(fout);
  132.            break;
  133.         case SQLA_CONNECT_EXCL:  genConnect('X',Stmt,taskArray->task[j].val,fout);
  134.            break;
  135.         case SQLA_CONNECT_SHARE:  genConnect('S',Stmt,taskArray->task[j].val,fout);
  136.            break;
  137.         case SQLA_CONNECT_RESET:  fout << "    _RC = sqlestpd(&sqlca);  \n";// not used
  138.            break;
  139.         case SQLA_INC_TEXTFILE:
  140.             {inputFile(Stmt,taskArray->task[j].val);}
  141.  
  142.            break;
  143.       } /* endswitch */
  144.   } /* endfor  each task in task array*/
  145.  
  146. //-----------------------------------------------------------------------
  147. //  C H E C K   F O R  A   W H E N E V E R  S T M T
  148. //  a "whenever statement does not associate any tasks
  149. //  must pick up the info based on statement type
  150. //    N O T I C E 
  151. //      do not support ":label" no colon in the label
  152. //----------------------------------------------------------------------
  153.   if (stmttype == SQLA_TYPE_WHEN_NOT_FOUND ) {
  154.      NotFoundLabel = Stmt.word(Stmt.numWords());  // skip "whenever not found"
  155.   } else {
  156.     if (stmttype == SQLA_TYPE_WHEN_SQLERROR ) {
  157.        ErrorLabel = Stmt.word(Stmt.numWords());   // skip " whenever sqlwarning"
  158.     } else {
  159.        if (stmttype == SQLA_TYPE_WHEN_SQLWARNING ) {
  160.           WarningLabel = Stmt.word(Stmt.numWords());  // skip " whenever sqlerror "
  161.        } /* endif */
  162.     } /* endif */
  163.   } /* endif */
  164.  
  165.  
  166. } /* end of gen code */
  167.  
  168. /***************************************************************************
  169. * support functions for code generation
  170. ***************************************************************************/
  171. void GenSetVArray(int nbrTokens, 
  172.                   unsigned short StmtID,
  173.                   Boolean input, 
  174.                   ofstream & fout, 
  175.                   sqla_tokens * tokenArray)
  176. {
  177.          short useSQLDA;     // id of sqlda to use
  178.  
  179.   Variable Var;                 // a variable objects
  180.  
  181. // -----------------------------------------------------------
  182.     if (input) {
  183.        inputSQLDA =nxtSQLDA++;
  184.        useSQLDA = inputSQLDA;
  185.     } else {
  186.        outputSQLDA = nxtSQLDA++;
  187.        useSQLDA = outputSQLDA;
  188.     } /* endif */
  189.     fout << "     _RC = sqlaaloc(" << useSQLDA << ", " << nbrTokens << ","
  190.           << StmtID << ",NULL);// allocate an sqlda \n";
  191.  
  192. //
  193. //              for each host variable used - gen setV code
  194. //
  195. //      if the indicator is with Indicator, the next in the array
  196. //      will be the null indicator - get that and send the name
  197. //
  198.   if (optimize) {
  199.     fout << "if (sqlca.code == 0) { \n";    // gen the optimization stuff
  200.   } /* endif*/
  201.  
  202.   int index = 0;
  203.   int theID, theNullInd;
  204.   Variable theToken;
  205. /***********************************************************************
  206. *  The token array has all tokens used  For input only process the ones
  207. *  markeds for input, for output, only process the ones marked for output
  208. ************************************************************************/
  209.  
  210.   if (input) {
  211.  
  212.       for (int j = 0;j < tokenArray->header.used ;j++ ) {
  213.              theID = tokenArray->token[j].id;
  214.          switch (tokenArray->token[j].use) {
  215.          case SQLA_INPUT_HVAR : theToken = getVarByID(theID); // get the token
  216.                                  theToken.setV(useSQLDA,index,fout);
  217.                                  index++;
  218.             break;
  219.          case SQLA_INPUT_WITH_IND : theToken = getVarByID(theID);
  220.                                     theNullInd = tokenArray->token[j+1].id;
  221.                                     theToken.setVNull(useSQLDA,index,fout,theNullInd);
  222.                                     index++;
  223.             break;
  224.          case SQLA_INDICATOR:       // do nothing - already done by withNull
  225.             break;
  226.          } /* endswitch */
  227.       }  /* end for */
  228.   } else {
  229.        for (int j = 0;j < tokenArray->header.used ;j++ ) {
  230.              theID = tokenArray->token[j].id;
  231.          switch (tokenArray->token[j].use) {
  232.          case SQLA_OUTPUT_HVAR : theToken = getVarByID(theID); // get the token
  233.                                  theToken.setV(useSQLDA,index,fout);
  234.                                  index++;
  235.             break;
  236.          case SQLA_OUTPUT_WITH_IND: theToken = getVarByID(theID);
  237.                                     theNullInd = tokenArray->token[j+1].id;
  238.                                     theToken.setVNull(useSQLDA,index,fout,theNullInd);
  239.                                     index++;
  240.             break;
  241.          case SQLA_INDICATOR:       // do nothing - already done by withNull
  242.             break;
  243.          } /* endswitch */
  244.  
  245.   } /* end for */
  246.   } /* end if*/
  247.   if (optimize) {
  248.      fout << "}  // end of optimize \n ";
  249.   } /* endif */
  250. }
  251.  
  252.  
  253. /**********************************************************************
  254. * and EXEC SQL IMPORT
  255. * was found in the input stream.  Isolate the file name and
  256. * make a recursive call to process file with the file name
  257. **********************************************************************/
  258.  
  259. void inputFile(IString const & Stmt, unsigned long x)
  260.   sqla_return_token *  p = (sqla_return_token *) &x;
  261.  
  262.   IString FileName=Stmt.subString(p->offset,p->length);
  263.   FileName.translate("'","");
  264.   FileName.strip(' ');
  265.   processFile(FileName);
  266. }
  267.  
  268.  
  269. /************************************************************ 
  270. *
  271. *  Generate call to connent the database
  272. *  in form of
  273. *  _rc =sqlestrd("dbname",use,&sqlca);
  274. **************************************************************/
  275. void genConnect(char type,      // exclusive or shared
  276.                 IString const & stmt, // SQL statment with DB name in
  277.                 unsigned long x,  // offset to DBName & DBLen
  278.                 ofstream & fout) // output file
  279.  
  280. {
  281.    sqla_return_token * p = (sqla_return_token *) &x;  
  282.    IString dbName = stmt.subString((p->offset)+1,p->length);
  283.    fout << "\n  unsigned char dbname[]= \"" << dbName << "\";\n";
  284.    fout <<"     _RC = sqlestrd(dbname, '" << type << "',&sqlca);\n";
  285. }
  286.  
  287.  
  288.  
  289. //========================================================================
  290. //  an sqlca includes both the CA and the DA  and....
  291. //  in this implementation generates the program ID sqla_program_id
  292. //  defines the ca to use in all DB calls
  293. //  defines the Booean _found
  294. //  one of these should be put into every program module that
  295. //  makes DB calls
  296. //========================================================================
  297. void GenIncludeSQLCA(ofstream & fout)
  298. {
  299.  //unsigned short letter;
  300.  unsigned char * pProgID =  (unsigned char *) &progID;  // pointer to program ID
  301.  
  302.     fout << "#include <sqlda.h>   // sqlda structure \n"
  303.          << "#include <sqlca.h>   // sqlca structre \n"
  304.          << "#include <sqlaprep.h> // api(s) for most calls \n"
  305.          << "#include <sqlenv.h>   // api(s) for start & stop db \n"
  306.          << "sqlca sqlca; \n"          // an instance of sqlca
  307.          << "typedef int  Boolean; \n"
  308.          << "#define false 0\n"
  309.          << "#define true 1 \n"
  310.          << "Boolean _sqlfound = false;\n"
  311.          << "Boolean _sqlerror = false;\n"
  312.          << "Boolean _sqlwarn = false; \n"
  313.          << "int _RC;\n"
  314.          << "const unsigned char sqla_program_id[40] = {";
  315.    fout << hex;
  316.    fout.setf(ios::showbase);
  317.          for (int j=0;j<4 ;j++ ) { // print 4 lines of 10
  318.             fout << "\n       ";
  319.             for (int k=j*10;k<(j+1)*10 ;k++ ) {  // do 10 char
  320.                fout  << short (pProgID[k]);
  321.                if (k < 39) {
  322.                   fout <<",";
  323.                } /* endif */
  324.             } /* endfor */
  325.          } /* endfor */
  326.     fout << "};\n\n";
  327.     fout << dec;                // change it back to decimal
  328. }
  329.  
  330.  
  331.  
  332. //=================================================================
  333. //  an sqlda include only includes the file
  334. //  wow big deal.  changed the including of the
  335. //  structure into the program  to generating an include <sqlda.h>
  336. //  does the same thing but no so messy
  337. //  I don't know of any real use for this command.
  338. //===================================================================
  339. void GenIncludeSQLDA(ofstream & fout)
  340. { fout <<  "#include <sqlda.h>\n";
  341. }
  342.  
  343.  
  344. //------------------------------------------------------
  345. //  support for dynamic sql SQLASets
  346. //  the hostvar in the ID
  347. //  get the hostvar by the ID and generate SQLASETS
  348. //-----------------------------------------------------------
  349. void GenSQLASets(int theID, ofstream & fout)
  350. { IString VName,lenstr;
  351.    Variable V;
  352.    V = getVarByID(theID);
  353.    VName = V.getFullName();
  354.    if (VName.includes('&')) {
  355.       lenstr = VName.strip('&');
  356.     }else{
  357.       lenstr = VName;
  358.    } /* endif */
  359.    fout << "     _RC  = sqlasets(strlen( " << lenstr << "),"
  360.         << VName << ",NULL);\n";
  361. }
  362.  
  363.  
  364. /***************************************************************
  365. *  A word about GOTOs (on error, warning, not found )
  366. *  I HATE Gotos  but SQL uses them.  So I cheat!
  367. *  If the goto label is of the patterm xxxx(x)
  368. *  I will call it as a function rather than a goto
  369. *  If the no found is _found  I will gen code to
  370. *  set the boolean _found
  371. *  otherwise I'll just gen the go-old goto
  372. *************************************************************/
  373.  
  374.  
  375. void GenOnError(ofstream & fout){
  376.  const char SB[]=
  377.   "      if (sqlca.sqlcode < 0) { \n"
  378.   "         _sqlerror = true;\n"
  379.   "       } else { \n"
  380.   "          _sqlerror = false;\n"
  381.   "       } /* endif */ \n";
  382.  
  383.  const char GT[] =
  384.   "      if (sqlca.sqlcode < 0) { \n";
  385.  
  386.     if (ErrorLabel.includes("_sqlerror")) {  // generate code to set boolean
  387.       fout << SB;
  388.     } else {   fout << "        " << MakeLabel(NotFoundLabel) << ";\n"
  389.                     << "    }\n";
  390.     } /* endif */
  391.  
  392.  
  393.  }
  394.                                                    
  395. void GenOnWarning(ofstream & fout){
  396.  
  397.  const char SB[]=
  398.   "   if (((sqlca.sqlcode > 0) && (sqlca.sqlcode !=100))) ||\n"
  399.   "      ((sqlca.sqlcode ==0) && (sqlca.sqlwarn[0] == 'W'))){\n"
  400.   "         _sqlwarn = true;\n"
  401.   "       } else { \n"
  402.   "          _sqlwarn = true;\n"
  403.   "       } /* endif */ \n";
  404.  
  405.  const char GT[] =
  406.   "      if (sqlca.sqlcode == 100) { \n";
  407.  
  408.     if (WarningLabel.includes("_sqlwarn")) {  // generate code to set boolean
  409.       fout << SB;
  410.     } else {   fout << "        " << MakeLabel(NotFoundLabel) << ";\n"
  411.                     << "    }\n";
  412.     } /* endif */
  413.  
  414.  
  415.  }
  416. void GenOnNotFound(ofstream & fout){
  417.  const char SB[]=
  418.   "      if (sqlca.sqlcode == 100) { \n"
  419.   "         _sqlfound = false;\n"
  420.   "       } else { \n"
  421.   "          _sqlfound = true;\n"
  422.   "       } /* endif */ \n";
  423.  
  424.  const char GT[] =
  425.   "      if (sqlca.sqlcode == 100) { \n";
  426.  
  427.     if (NotFoundLabel.includes("_sqlfound")) {  // generate code to set boolean
  428.       fout << SB;
  429.     } else {   fout << "        " << MakeLabel(NotFoundLabel) << ";\n"
  430.                     << "    }\n";
  431.     } /* endif */
  432.                                                    
  433. }
  434.  
  435. IString MakeLabel(IString & theLabel) {
  436.    if (theLabel.isLike("*(*)")) {    // make it a function call
  437.       return theLabel+ ";\n";  
  438.    } else {
  439.       return "goto " + theLabel;
  440.    } /* endif */           
  441. }
  442.                                                    
  443.  
  444.  
  445.  
  446.  
  447.  
  448.  
  449.  
  450.  
  451.  
  452.  
  453.