int_servlib.c
上传用户:dgyhgb
上传日期:2007-01-07
资源大小:676k
文件大小:10k
源码类别:

SQL Server

开发平台:

Unix_Linux

  1. /*
  2.  *  int_servlib.c  - top level functions of GNU SQL interpretator server
  3.  *
  4.  *  This file is a part of GNU SQL Server
  5.  *
  6.  *  Copyright (c) 1996, 1997, Free Software Foundation, Inc
  7.  *  Developed at the Institute of System Programming
  8.  *  This file is written by Konstantin Dyshlevoi
  9.  *
  10.  *  This program is free software; you can redistribute it and/or modify
  11.  *  it under the terms of the GNU General Public License as published by
  12.  *  the Free Software Foundation; either version 2 of the License, or
  13.  *  (at your option) any later version.
  14.  *
  15.  *  This program is distributed in the hope that it will be useful,
  16.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  17.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18.  *  GNU General Public License for more details.
  19.  *
  20.  *  You should have received a copy of the GNU General Public License
  21.  *  along with this program; if not, write to the Free Software
  22.  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  23.  *
  24.  *  Contact: gss@ispras.ru
  25.  *
  26.  */
  27. /* $Id: int_servlib.c,v 1.246 1997/04/25 10:50:38 kml Exp $ */
  28. #include "global.h"
  29. #include "gsqltrn.h"
  30. #ifdef HAVE_UNISTD_H
  31. #include <unistd.h>
  32. #endif
  33. #include "sql.h"
  34. #include "inprtyp.h"
  35. #include "inpop.h"
  36. #include "svr_lib.h"
  37. #include "type_lib.h"
  38. extern DataUnit *data_st; /*[MAX_STACK]*/
  39. extern StackUnit *stack; /*[MAX_STACK]*/
  40. extern i4_t dt_ind, dt_max;
  41. extern i4_t st_ind, st_max;
  42. extern pid_t parent;            /* administrator process id */
  43. extern i4_t msqidt;              
  44. extern i4_t minidnt;
  45. extern i4_t       res_hole_cnt;
  46. extern parm_t    *res_hole;
  47. #define CH_ERR_IN(cd)  if (chck_err(cd)) return 
  48. #define RET            return 
  49. i4_t cnt_res;
  50. /*
  51.  * Receiving of argumens to interpretator process and result sending.     
  52.  * Returns SQLCODE in result (=0 if O'K, < 0 if error, =100 if EndOfScan) 
  53.  */
  54. static void
  55. do_insn(insn_t *in)
  56. {
  57.   parm_t *args = (in->parms.parm_row_t_len) ? in->parms.parm_row_t_val : NULL;
  58.   
  59.   i4_t i, error;
  60.   char *cur; /* current pointer */
  61.   enum CmdCode code;
  62.   VADR *SectTable, *arr;
  63.   Scanid *cur_scan;
  64.   UnId *cur_tid;
  65.   i4_t sectnum;
  66.   i4_t command;
  67.   struct S_CursorHeader *CHE  = NULL;
  68.   struct S_Drop_Reg     *DR   = NULL;
  69.   struct S_SavePar      *SPAR = NULL;
  70.   
  71.   cnt_res = 0;
  72.   SQLCODE = 0;
  73.   InitDat;
  74.   InitStack;
  75.   
  76.   start_processing();
  77.   
  78.   sectnum = in->sectnum;
  79.   
  80.   if (sectnum < 0) /* commit or rollback */
  81.     {
  82.       if (sectnum == -1)
  83. rollback (0);
  84.       else if (sectnum==-2)
  85. {
  86.   change_statistic ();
  87.   commit ();
  88. }
  89.       else
  90.         yyfatal("unrecognized section number");
  91.         
  92.       RET;
  93.     }
  94.   command = in->command;
  95.   switch_to_segment ((VADR)(in->vadr_segm));
  96.   
  97.   SectTable = V_PTR (*V_PTR ((VADR) 4, VADR), VADR);
  98.   /* first element of SectTable - sections number */
  99.   if (((i4_t *) (SectTable))[0] <= sectnum)
  100.     CH_ERR_IN (-ER_5);
  101.   cur = V_PTR (SectTable[sectnum + 1], char);
  102.   
  103. #define READ_CMD(adr, cmnd) code = *((enum CmdCode *) cur);                   
  104.                             if (code == cmnd)                                 
  105.                               { int sz;                                       
  106.                                 sz = sizeof (enum CmdCode); ALIGN(sz,SZ_LNG); 
  107.                                 cur += sz;                                    
  108.                                 adr = (struct S_##cmnd *) cur;                
  109.                                 sz = SIZES (S_##cmnd); ALIGN(sz,SZ_LNG);      
  110.                                 cur += sz;                                    
  111.       }
  112.   
  113.   READ_CMD(CHE, CursorHeader);
  114.   READ_CMD(DR, Drop_Reg);
  115.   READ_CMD(SPAR, SavePar);
  116.   
  117. #undef READ_CMD
  118.   
  119.   if (CHE)
  120.     {
  121.       /* value of OpFl is :                          *
  122.        * 0 - cursor wasn't opened;                   *
  123.        * 1 - cursor was opened but wasn't used ;     *
  124.        * 2 - cursor was opened and was used ;        *
  125.        * 3 - cursor was opened but there was already *
  126.        *     SQLCODE =100 (scanning is finished)     */
  127.       if (!DR)
  128. CH_ERR_IN (-ER_8);
  129.       switch (command)
  130. {
  131. case 0: /* OPEN CURSOR */
  132.   if (CHE->OpFl)
  133.     CH_ERR_IN (-ER_OpCur);
  134.   (CHE->OpFl)++;
  135.   break;
  136. case 1: /* FETCH */
  137.   if (!(CHE->OpFl))
  138.     CH_ERR_IN (-ER_Fetch);
  139.   if (CHE->OpFl == 3) /* end of scan was already found */
  140.     CH_ERR_IN (-EOSCAN);
  141.   CHE->OpFl = 2;
  142.   cur = CHE->Cur;
  143.   SPAR = NULL;
  144.   break;
  145. case 2: /* CLOSE CURSOR */
  146.   if (!(CHE->OpFl))
  147.     CH_ERR_IN (-ER_Close);
  148.   if (CHE->OpFl > 1) /* there was work with cursor  *
  149.               * ( not only "open cursor" )  */ 
  150.     {
  151.       if (DR->ScanNum)
  152. {
  153.   arr = V_ADR(DR,Scan,VADR);
  154.   for (i = 0; i < DR->ScanNum; i++)
  155.     {
  156.       cur_scan = V_PTR(arr[i], Scanid);
  157.       if ( *cur_scan >= 0)
  158. {
  159.   error = closescan (*cur_scan);
  160.   CH_ERR_IN (error);
  161.   *cur_scan = -1;
  162. }
  163.     }
  164. }
  165.       if (DR->TabdNum)
  166. {
  167.   arr = V_ADR(DR,Tabd,VADR);
  168.   for (i = 0; i < DR->TabdNum; i++)
  169.     {
  170.       cur_tid = V_PTR(arr[i], UnId);
  171.       if ((cur_tid->t).untabid)
  172. {
  173.   error = dropttab (&(cur_tid->t));
  174.   CH_ERR_IN (error);
  175.   (cur_tid->t).untabid = 0;
  176. }
  177.     }
  178. }
  179.     }
  180.   (CHE->OpFl) = 0;
  181.   RET;
  182. case 3: /* DELETE : POSITIONED */
  183.   if ((CHE->OpFl) != 2)
  184.     CH_ERR_IN (-ER_Delete);
  185.   if (!DR || (DR->ScanNum != 1))
  186.     CH_ERR_IN (-ER_8);
  187.   error = check_and_put (0, NULL, NULL, NULL,
  188.  V_ADR (CHE, DelCurConstr, S_ConstrHeader));
  189.   CH_ERR_IN (error);
  190.   
  191.   error = delrow (*V_PTR (*V_ADR (DR,Scan,VADR), Scanid), NULL);
  192.   CH_ERR_IN (error);
  193.   RET;
  194. default:
  195.   CH_ERR_IN (-ER_6); /* ERROR */
  196. } /* switch, if */
  197.     } /* if */
  198.   /* cur = pointer to first command */
  199.   if (SPAR || args)
  200.     {
  201.       if (!(SPAR && args))
  202. CH_ERR_IN (-ER_CLNT);
  203.       /* fprintf (STDOUT, " INTERPR: CODE=%dn", code); */
  204.       
  205.       if (SPAR->flag != 'y')
  206. {
  207.   off_adr (&(SPAR->PlaceOff), SPAR->ParamNum);
  208.   SPAR->flag = 'y';
  209. }
  210.       
  211.       for (i = 0; i < SPAR->ParamNum; i++)
  212. {
  213.   error = rpc_to_DU (args + i, PTR (SPAR, PlaceOff, i, DataUnit));
  214.   /* what I need to do when error > 0 ( string was shortened ) ? */
  215.   if (error < 0)
  216.     CH_ERR_IN (error);
  217. }
  218.     }
  219.   
  220.   if (CHE && !command) /* OPEN CURSOR */
  221.     {
  222.       CHE->Cur = cur;
  223.       RET;
  224.     }
  225.   
  226.   error = proc_work (cur, (CHE) ? &(CHE->Cur) : NULL, 0);
  227.   
  228.   if (SQLCODE == 100 && CHE) /* if eoscan found in cursor */ 
  229.     CHE->OpFl = 3; /* saving information about End Of Scan for CURSOR */
  230.   
  231.   RET;
  232. } /* do_insn */
  233. #undef RET
  234. /* Initialization of interpretator's work with module.    *
  235.  * Returns virtual address of loaded module or error (<0) */
  236. result_t*
  237. module_init(string_t *in, struct svc_req *rqstp)
  238. {
  239.   FILE *fmodule;
  240.   char *beg;
  241.   i4_t leng;
  242.   gsqltrn_rc.sqlcode = -MDLINIT;
  243.   fmodule = fopen (*in, "r");
  244.   if (fmodule)
  245.     {
  246.       fseek (fmodule, 0, SEEK_END);
  247.       leng = ftell (fmodule);
  248.       fseek (fmodule, 0, SEEK_SET);
  249.       beg = xmalloc (leng);
  250.       fread (beg, leng, 1, fmodule);
  251.       fclose (fmodule);
  252.       gsqltrn_rc.sqlcode = 0;
  253.       gsqltrn_rc.info.rett = RET_SEG;
  254.       gsqltrn_rc.info.return_data_u.segid = link_segment (beg, leng);
  255.     }
  256.   /* what about correlation between current BD and module ? */
  257.   return &gsqltrn_rc;
  258. } /* module_init */
  259. static void
  260. put_in_row(parm_row_t *r)
  261. {
  262.   void   *ptr;
  263.   i4_t     i;
  264.   
  265.   assert(cnt_res);
  266.   
  267.   ptr = xmalloc ( sizeof(parm_t)*cnt_res);
  268.   bcopy(res_hole,ptr,sizeof(parm_t)*cnt_res);
  269.   
  270.   r->parm_row_t_len = cnt_res;
  271.   r->parm_row_t_val = ptr;
  272.   for (i=0; i < cnt_res; i++)
  273.     {
  274.       parm_t *e = &(r->parm_row_t_val[i]);
  275.       if( (e->indicator == 0) && (e->value.type == SQLType_Char))
  276.         {  /* if data is a valuable string -- save copy of the string */
  277.           void *p = xmalloc(e->value.data_u.Str.Str_len);
  278.           bcopy(e->value.data_u.Str.Str_val,p,e->value.data_u.Str.Str_len);
  279.           e->value.data_u.Str.Str_val = p;
  280.         }
  281.     }
  282. }
  283. result_t *
  284. execute_stmt (insn_t *insn, struct svc_req *rqstp)
  285. {
  286.   insn_t     *cinsn;
  287.   i4_t count, total;
  288.   
  289.   SQLCODE = 0;
  290.   for(cinsn = insn,total = 0; cinsn ; cinsn = cinsn -> next )
  291.     total += 1 + cinsn->options;
  292.   if ( total > 1) /* request for table */
  293.     {
  294.       i4_t tbl_width=0;
  295.       gsqltrn_rc.info.rett = RET_TBL;
  296.       gsqltrn_rc.info.return_data_u.tbl.tbl_len = total;
  297.       gsqltrn_rc.info.return_data_u.tbl.tbl_val = xmalloc ( sizeof(parm_row_t)*total);
  298.       count = 0;
  299.       for (cinsn = insn;
  300.            cinsn && (SQLCODE==0) && (count<total);
  301.            cinsn = cinsn -> next)
  302.         while ((cinsn->options-- >=0) && (count<total))
  303.           {
  304.             do_insn(cinsn);
  305.             if (SQLCODE<0)
  306.               goto table_exit;
  307.             if (cnt_res)
  308.               {
  309.                 if (!tbl_width) tbl_width = cnt_res;
  310.                 assert(tbl_width == cnt_res);
  311.                 put_in_row(&(gsqltrn_rc.info.return_data_u.tbl.tbl_val[count++]));
  312.               }
  313.           }
  314.     table_exit:
  315.       if (!count)
  316.         gsqltrn_rc.info.rett = RET_VOID;
  317.       else if (count>1)
  318.         gsqltrn_rc.info.return_data_u.tbl.tbl_len = count;
  319.       else /* if count == 1 */
  320.         {
  321.           parm_row_t *row = gsqltrn_rc.info.return_data_u.tbl.tbl_val;
  322.           bcopy(row,&(gsqltrn_rc.info.return_data_u.row),sizeof(parm_row_t));
  323.           xfree(row);
  324.           gsqltrn_rc.info.rett = RET_ROW;
  325.         }
  326.     }
  327.   else if (total==1)
  328.     {
  329.       do_insn(insn);
  330.       if (cnt_res)
  331.         {
  332.           if (SQLCODE>=0)
  333.             {
  334.               gsqltrn_rc.info.rett = RET_ROW;
  335.               put_in_row(&gsqltrn_rc.info.return_data_u.row);
  336.             }
  337.           else
  338.             gsqltrn_rc.info.rett = RET_VOID;
  339.         }
  340.       else
  341.         assert(gsqltrn_rc.info.rett == RET_VOID);
  342.     }
  343.   gsqltrn_rc.sqlcode = SQLCODE;
  344.   return &gsqltrn_rc;
  345. }