]> git.sur5r.net Git - openldap/blob - servers/slapd/back-sql/modify.c
Summary of changes:
[openldap] / servers / slapd / back-sql / modify.c
1 /*
2  *       Copyright 1999, Dmitry Kovalev <mit@openldap.org>, All rights reserved.
3  *
4  *       Redistribution and use in source and binary forms are permitted only
5  *       as authorized by the OpenLDAP Public License.  A copy of this
6  *       license is available at http://www.OpenLDAP.org/license.html or
7  *       in file LICENSE in the top-level directory of the distribution.
8  */
9
10 #include "portable.h"
11
12 #ifdef SLAPD_SQL
13
14 #include <stdio.h>
15 #include <sys/types.h>
16 #include <string.h>
17 #include "slap.h"
18 #include "back-sql.h"
19 #include "sql-wrap.h"
20 #include "schema-map.h"
21 #include "entry-id.h"
22 #include "util.h"
23
24 int backsql_modify(BackendDB *be,Connection *conn,Operation *op,
25         const char *dn,const char *ndn,LDAPModList *modlist)
26 {
27  backsql_info *bi=(backsql_info*)be->be_private;
28  SQLHDBC dbh;
29  SQLHSTMT sth;
30  RETCODE rc;
31  backsql_oc_map_rec *oc=NULL;
32  backsql_entryID e_id,*res;
33  LDAPModList *c_mod;
34  backsql_at_map_rec *at=NULL;
35  struct berval *at_val;
36  int i;
37  int pno,po;//first parameter no, parameter order
38  int prc; //procedure return code
39
40  Debug(LDAP_DEBUG_TRACE,"==>backsql_modify(): changing entry '%s'\n",ndn,0,0);
41  dbh=backsql_get_db_conn(be,conn);
42  if (!dbh)
43  {
44   Debug(LDAP_DEBUG_TRACE,"backsql_modify(): could not get connection handle - exiting\n",0,0,0);
45   send_ldap_result(conn,op,LDAP_OTHER,"","SQL-backend error",NULL,NULL);
46   return 1;
47  }
48  res=backsql_dn2id(bi,&e_id,dbh,(char*)ndn);
49  if (res==NULL)
50  {
51   Debug(LDAP_DEBUG_TRACE,"backsql_modify(): could not lookup entry id\n",0,0,0);
52   send_ldap_result(conn,op,LDAP_NO_SUCH_OBJECT,"",NULL,NULL,NULL);
53   return 1;
54  }
55
56  oc=backsql_oc_with_id(bi,e_id.oc_id);
57  if (oc==NULL)
58  {
59   Debug(LDAP_DEBUG_TRACE,"backsql_modify(): cannot determine objectclass of entry -- aborting\n",0,0,0);
60   send_ldap_result(conn,op,LDAP_OTHER,"","SQL-backend error",NULL,NULL);
61   return 1;
62  }
63
64  SQLAllocStmt(dbh, &sth);
65
66  Debug(LDAP_DEBUG_TRACE,"backsql_modify(): traversing modifications list\n",0,0,0);
67  for(c_mod=modlist;c_mod!=NULL;c_mod=c_mod->ml_next)
68  {
69   Debug(LDAP_DEBUG_TRACE,"backsql_modify(): attribute '%s'\n",c_mod->ml_type,0,0);
70   at=backsql_at_with_name(oc,c_mod->ml_type);
71   if (at==NULL)
72   {
73    Debug(LDAP_DEBUG_TRACE,"backsql_modify(): attribute provided is not registered in this objectclass ('%s')\n",c_mod->ml_type,0,0);
74    continue;
75   }
76   
77   switch(c_mod->ml_op)
78   {
79    case LDAP_MOD_REPLACE:
80                         {
81                          SQLHSTMT asth;
82                          BACKSQL_ROW_NTS row;
83                          
84                          Debug(LDAP_DEBUG_TRACE,"backsql_modify(): replacing values for attribute '%s'\n",at->name,0,0);
85              if (at->add_proc==NULL)
86                          {
87                           Debug(LDAP_DEBUG_TRACE,"backsql_modify(): add procedure is not defined for this attribute ('%s') - unable to perform replacements\n",at->name,0,0);
88                           break;
89                          }
90 del_all:
91                          
92                          if ((rc=backsql_Prepare(dbh,&asth,at->query,0)) != SQL_SUCCESS)
93                          {
94                           Debug(LDAP_DEBUG_TRACE,"backsql_modify(): error preparing query\n",0,0,0);
95                           backsql_PrintErrors(bi->db_env,dbh,asth,rc);
96                           break;
97                          }
98
99                          if (backsql_BindParamID(asth,1,&e_id.keyval) != SQL_SUCCESS)
100                          {
101                           Debug(LDAP_DEBUG_TRACE,"backsql_modify(): error binding key value parameter\n",0,0,0);
102                           backsql_PrintErrors(bi->db_env,dbh,asth,rc);
103                           SQLFreeStmt(asth,SQL_DROP);
104                           break;
105                          }
106
107                          if ((rc=SQLExecute(asth)) != SQL_SUCCESS && rc!= SQL_SUCCESS_WITH_INFO)
108                          {
109                           Debug(LDAP_DEBUG_TRACE,"backsql_modify(): error executing attribute query\n",0,0,0);
110                           backsql_PrintErrors(bi->db_env,dbh,asth,rc);
111                           SQLFreeStmt(asth,SQL_DROP);
112                           break;
113                          }
114
115                          backsql_BindRowAsStrings(asth,&row);
116                          while ((rc=SQLFetch(asth)) == SQL_SUCCESS || rc==SQL_SUCCESS_WITH_INFO)
117                          {
118                           for (i=0;i<row.ncols;i++)
119                           {
120                            if (at->expect_return & BACKSQL_DEL)
121                            {
122                             pno=1;
123                             SQLBindParameter(sth,1,SQL_PARAM_OUTPUT,SQL_C_ULONG,SQL_INTEGER,0,0,&prc,0,0);
124                            }
125                            else
126                             pno=0;
127                            po=(at->param_order & BACKSQL_DEL)>0;
128                            SQLBindParameter(sth,(SQLUSMALLINT)(pno+1+po),SQL_PARAM_INPUT,SQL_C_ULONG,SQL_INTEGER,0,0,&e_id.keyval,0,0);
129                            //check for syntax needed here - maybe need binary bind?
130                            SQLBindParameter(sth,(SQLUSMALLINT)(pno+2-po),SQL_PARAM_INPUT,SQL_C_CHAR,SQL_CHAR,0,0,row.cols[i],strlen(row.cols[i]),0);
131                          
132                            Debug(LDAP_DEBUG_TRACE,"backsql_modify(): executing '%s'\n",at->delete_proc,0,0);
133                            rc=SQLExecDirect(sth,at->delete_proc,SQL_NTS);
134                            if (rc!=SQL_SUCCESS)
135                                 {
136                              Debug(LDAP_DEBUG_TRACE,"backsql_modify(): delete_proc execution failed\n",0,0,0);
137                              backsql_PrintErrors(bi->db_env,dbh,sth,rc);
138                                 }
139                           }
140                          }
141                          backsql_FreeRow(&row);
142              SQLFreeStmt(asth,SQL_DROP);
143                         }
144                         //PASSTHROUGH - to add new attributes -- do NOT add break
145   case LDAP_MOD_ADD:
146                         if (at->add_proc==NULL)
147                         {
148                          Debug(LDAP_DEBUG_TRACE,"backsql_modify(): add procedure is not defined for this attribute ('%s')\n",at->name,0,0);
149                          break;
150                         }
151                         if (c_mod->ml_bvalues==NULL)
152                         {
153                          Debug(LDAP_DEBUG_TRACE,"backsql_modify(): no values given to add for attribute '%s'\n",at->name,0,0);
154                          break;
155                         }
156                         Debug(LDAP_DEBUG_TRACE,"backsql_modify(): adding new values for attribute '%s'\n",at->name,0,0);
157                         for(i=0,at_val=c_mod->ml_bvalues[0];at_val!=NULL;i++,at_val=c_mod->ml_bvalues[i])
158                         {
159                          if (at->expect_return & BACKSQL_ADD)
160                          {
161                           pno=1;
162                           SQLBindParameter(sth,1,SQL_PARAM_OUTPUT,SQL_C_ULONG,SQL_INTEGER,0,0,&prc,0,0);
163                          }
164                          else
165                           pno=0;
166                          po=(at->param_order & BACKSQL_ADD)>0;
167                          SQLBindParameter(sth,(SQLUSMALLINT)(pno+1+po),SQL_PARAM_INPUT,SQL_C_ULONG,SQL_INTEGER,0,0,&e_id.keyval,0,0);
168                          //check for syntax needed here - maybe need binary bind?
169                          SQLBindParameter(sth,(SQLUSMALLINT)(pno+2-po),SQL_PARAM_INPUT,SQL_C_CHAR,SQL_CHAR,0,0,at_val->bv_val,at_val->bv_len,0);
170                          
171                          Debug(LDAP_DEBUG_TRACE,"backsql_modify(): executing '%s'\n",at->add_proc,0,0);
172                          rc=SQLExecDirect(sth,at->add_proc,SQL_NTS);
173                          if (rc!=SQL_SUCCESS)
174                          {
175                           Debug(LDAP_DEBUG_TRACE,"backsql_modify(): add_proc execution failed\n",0,0,0);
176                           backsql_PrintErrors(bi->db_env,dbh,sth,rc);
177                          }
178                         }
179                         break;
180   case LDAP_MOD_DELETE:
181                         if (at->delete_proc==NULL)
182                         {
183                          Debug(LDAP_DEBUG_TRACE,"backsql_modify(): delete procedure is not defined for this attribute ('%s')\n",at->name,0,0);
184                          break;
185                         }
186                         if (c_mod->ml_bvalues==NULL)
187                         {
188                          Debug(LDAP_DEBUG_TRACE,"backsql_modify(): no values given to delete for attribute '%s' -- deleting all values\n",at->name,0,0);
189                          goto del_all;
190                         }
191             Debug(LDAP_DEBUG_TRACE,"backsql_modify(): deleting values for attribute '%s'\n",at->name,0,0);
192                         for(i=0,at_val=c_mod->ml_bvalues[0];at_val!=NULL;i++,at_val=c_mod->ml_bvalues[i])
193                         {
194                          if (at->expect_return & BACKSQL_DEL)
195                           {
196                            pno=1;
197                            SQLBindParameter(sth,1,SQL_PARAM_OUTPUT,SQL_C_ULONG,SQL_INTEGER,0,0,&prc,0,0);
198                           }
199                          else
200                           pno=0;
201                          po=(at->param_order & BACKSQL_DEL)>0;
202                          SQLBindParameter(sth,(SQLUSMALLINT)(pno+1+po),SQL_PARAM_INPUT,SQL_C_ULONG,SQL_INTEGER,0,0,&e_id.keyval,0,0);
203                          //check for syntax needed here - maybe need binary bind?
204                          SQLBindParameter(sth,(SQLUSMALLINT)(pno+2-po),SQL_PARAM_INPUT,SQL_C_CHAR,SQL_CHAR,0,0,at_val->bv_val,at_val->bv_len,0);
205                            
206                          Debug(LDAP_DEBUG_TRACE,"backsql_modify(): executing '%s'\n",at->delete_proc,0,0);
207                          rc=SQLExecDirect(sth,at->delete_proc,SQL_NTS);
208                          if (rc!=SQL_SUCCESS)
209                          {
210                           Debug(LDAP_DEBUG_TRACE,"backsql_modify(): delete_proc execution failed\n",0,0,0);
211                           backsql_PrintErrors(bi->db_env,dbh,sth,rc);
212                          }
213                         }
214                         break;
215   }
216   SQLFreeStmt(sth,SQL_RESET_PARAMS);
217  }
218
219  SQLFreeStmt(sth,SQL_DROP);
220  send_ldap_result(conn,op,LDAP_SUCCESS,"",NULL,NULL,NULL);
221  Debug(LDAP_DEBUG_TRACE,"<==backsql_modify()\n",0,0,0);
222  return 0;
223 }
224
225 int backsql_modrdn(BackendDB *be,Connection *conn,Operation *op,
226         const char *dn,const char *ndn,const char *newrdn,int deleteoldrdn,const char *newSuperior)
227 {
228  Debug(LDAP_DEBUG_TRACE,"==>backsql_modrdn()\n",0,0,0);
229  return 0;
230 }
231
232 int backsql_add(BackendDB *be,Connection *conn,Operation *op,Entry *e)
233 {
234  backsql_info *bi=(backsql_info*)be->be_private;
235  SQLHDBC dbh;
236  SQLHSTMT sth;
237  unsigned long new_keyval;
238  long i;
239  RETCODE rc;
240  backsql_oc_map_rec *oc=NULL;
241  backsql_at_map_rec *at_rec=NULL;
242  backsql_entryID parent_id,*res;
243  Attribute *at;
244  struct berval *at_val;
245  char *pdn;
246  int pno,po;//first parameter no, parameter order
247  int prc; //procedure return code
248
249  Debug(LDAP_DEBUG_TRACE,"==>backsql_add(): adding entry '%s'\n",e->e_dn,0,0);
250  if (dn_validate(e->e_dn)==NULL)
251  {
252   Debug(LDAP_DEBUG_TRACE,"==>backsql_add(): invalid dn '%s' -- aborting\n",e->e_dn,0,0);
253  }
254  for(at=e->e_attrs;at!=NULL;at=at->a_next)
255  {
256   //Debug(LDAP_DEBUG_TRACE,"backsql_add(): scanning entry -- %s\n",at->a_type,0,0);
257   if (!strcasecmp(at->a_type,"objectclass"))
258   {
259    oc=backsql_oc_with_name(bi,at->a_vals[0]->bv_val);
260    break;
261   }
262  }
263
264  if (oc==NULL)
265  {
266   Debug(LDAP_DEBUG_TRACE,"backsql_add(): cannot determine objectclass of entry -- aborting\n",0,0,0);
267   send_ldap_result(conn,op,LDAP_OTHER,"","SQL-backend error",NULL,NULL);
268   return 1;
269  }
270  if (oc->create_proc == NULL)
271  {
272   Debug(LDAP_DEBUG_TRACE,"backsql_add(): create procedure is not defined for this objectclass - aborting\n",0,0,0);
273   send_ldap_result(conn,op,LDAP_OTHER,"","SQL-backend error",NULL,NULL);
274   return 1;
275  }
276
277  dbh=backsql_get_db_conn(be,conn);
278  if (!dbh)
279  {
280   Debug(LDAP_DEBUG_TRACE,"backsql_add(): could not get connection handle - exiting\n",0,0,0);
281   send_ldap_result(conn,op,LDAP_OTHER,"","SQL-backend error",NULL,NULL);
282   return 1;
283  }
284
285  SQLAllocStmt(dbh, &sth);
286  SQLBindParameter(sth,1,SQL_PARAM_OUTPUT,SQL_C_ULONG,SQL_INTEGER,0,0,&new_keyval,0,0);
287
288  Debug(LDAP_DEBUG_TRACE,"backsql_add(): executing '%s'\n",oc->create_proc,0,0);
289  rc=SQLExecDirect(sth,oc->create_proc,SQL_NTS);
290  if (rc != SQL_SUCCESS)
291  {
292   Debug(LDAP_DEBUG_TRACE,"backsql_add(): create_proc execution failed\n",0,0,0);
293   backsql_PrintErrors(bi->db_env,dbh,sth,rc);
294   SQLFreeStmt(sth,SQL_DROP);
295   send_ldap_result(conn,op,LDAP_OTHER,"","SQL-backend error",NULL,NULL);
296   return 1;
297  }
298  SQLFreeStmt(sth,SQL_RESET_PARAMS);
299  Debug(LDAP_DEBUG_TRACE,"backsql_add(): create_proc returned keyval=%d\n",new_keyval,0,0);
300
301  for(at=e->e_attrs;at!=NULL;at=at->a_next)
302  {
303   at_rec=backsql_at_with_name(oc,at->a_type);
304   if (at_rec==NULL)
305   {
306    Debug(LDAP_DEBUG_TRACE,"backsql_add(): attribute provided is not registered in this objectclass ('%s')\n",at->a_type,0,0);
307    continue;
308   }
309   if (at_rec->add_proc==NULL)
310   {
311    Debug(LDAP_DEBUG_TRACE,"backsql_add(): add procedure is not defined for this attribute ('%s')\n",at->a_type,0,0);
312    continue;
313   }
314   
315   for(i=0,at_val=at->a_vals[0];at_val!=NULL;i++,at_val=at->a_vals[i])
316   {
317         if (at_rec->expect_return & BACKSQL_ADD)
318         {
319          pno=1;
320          SQLBindParameter(sth,1,SQL_PARAM_OUTPUT,SQL_C_ULONG,SQL_INTEGER,0,0,&prc,0,0);
321         }
322         else
323          pno=0;
324         po=(at_rec->param_order & BACKSQL_ADD)>0;
325         SQLBindParameter(sth,(SQLUSMALLINT)(pno+1+po),SQL_PARAM_INPUT,SQL_C_ULONG,SQL_INTEGER,0,0,&new_keyval,0,0);
326         //check for syntax needed here - maybe need binary bind?
327         SQLBindParameter(sth,(SQLUSMALLINT)(pno+2-po),SQL_PARAM_INPUT,SQL_C_CHAR,SQL_CHAR,0,0,at_val->bv_val,at_val->bv_len,0);
328    Debug(LDAP_DEBUG_TRACE,"backsql_add(): executing '%s'\n",at_rec->add_proc,0,0);
329    rc=SQLExecDirect(sth,at_rec->add_proc,SQL_NTS);
330    if (rc!=SQL_SUCCESS)
331    {
332         Debug(LDAP_DEBUG_TRACE,"backsql_add(): add_proc execution failed\n",0,0,0);
333         backsql_PrintErrors(bi->db_env,dbh,sth,rc);
334    }
335   }
336  }
337  SQLFreeStmt(sth,SQL_RESET_PARAMS); 
338  pdn=dn_parent(be,e->e_dn);
339  res=backsql_dn2id(bi,&parent_id,dbh,pdn);
340  if (res==NULL)
341  {
342   Debug(LDAP_DEBUG_TRACE,"backsql_add(): could not lookup parent entry for new record ('%s')\n",
343                                                                                                 pdn,0,0);
344   send_ldap_result(conn,op,LDAP_OTHER,"","SQL-backend error",NULL,NULL);
345   return 1;
346  }
347  free(pdn);
348  backsql_BindParamStr(sth,1,e->e_dn,BACKSQL_MAX_DN_LEN);
349  SQLBindParameter(sth,2,SQL_PARAM_INPUT,SQL_C_LONG,SQL_INTEGER,0,0,&oc->id,0,0);
350  SQLBindParameter(sth,3,SQL_PARAM_INPUT,SQL_C_LONG,SQL_INTEGER,0,0,&parent_id.id,0,0);
351  SQLBindParameter(sth,4,SQL_PARAM_INPUT,SQL_C_LONG,SQL_INTEGER,0,0,&new_keyval,0,0);
352  rc=SQLExecDirect(sth,bi->insentry_query,SQL_NTS);
353  if (rc != SQL_SUCCESS)
354  {
355   Debug(LDAP_DEBUG_TRACE,"backsql_add(): could not insert ldap_entries record\n",0,0,0);
356   backsql_PrintErrors(bi->db_env,dbh,sth,rc);
357   //execute delete_proc to delete data added !!!
358   SQLFreeStmt(sth,SQL_DROP);
359   send_ldap_result(conn,op,LDAP_OTHER,"","SQL-backend error",NULL,NULL);
360   return 1;
361  }
362  SQLFreeStmt(sth,SQL_DROP);
363  send_ldap_result(conn,op,LDAP_SUCCESS,"",NULL,NULL,NULL);
364  return 0;
365 }
366
367 int backsql_delete(BackendDB *be,Connection *conn,Operation *op,
368         const char *dn,const char *ndn)
369 {
370  backsql_info *bi=(backsql_info*)be->be_private;
371  SQLHDBC dbh;
372  SQLHSTMT sth;
373  RETCODE rc;
374  backsql_oc_map_rec *oc=NULL;
375  backsql_entryID e_id,*res;
376  int pno;//first parameter no, parameter order
377
378  Debug(LDAP_DEBUG_TRACE,"==>backsql_delete(): deleting entry '%s'\n",ndn,0,0);
379  dbh=backsql_get_db_conn(be,conn);
380  if (!dbh)
381  {
382   Debug(LDAP_DEBUG_TRACE,"backsql_delete(): could not get connection handle - exiting\n",0,0,0);
383   send_ldap_result(conn,op,LDAP_OTHER,"","SQL-backend error",NULL,NULL);
384   return 1;
385  }
386  res=backsql_dn2id(bi,&e_id,dbh,(char*)ndn);
387  if (res==NULL)
388  {
389   Debug(LDAP_DEBUG_TRACE,"backsql_delete(): could not lookup entry id\n",0,0,0);
390   send_ldap_result(conn,op,LDAP_NO_SUCH_OBJECT,"",NULL,NULL,NULL);
391   return 1;
392  }
393
394  oc=backsql_oc_with_id(bi,e_id.oc_id);
395  if (oc==NULL)
396  {
397   Debug(LDAP_DEBUG_TRACE,"backsql_delete(): cannot determine objectclass of entry -- aborting\n",0,0,0);
398   send_ldap_result(conn,op,LDAP_OTHER,"","SQL-backend error",NULL,NULL);
399   return 1;
400  }
401  if (oc->delete_proc == NULL)
402  {
403   Debug(LDAP_DEBUG_TRACE,"backsql_delete(): delete procedure is not defined for this objectclass - aborting\n",0,0,0);
404   send_ldap_result(conn,op,LDAP_OTHER,"","SQL-backend error",NULL,NULL);
405   return 1;
406  }
407
408  SQLAllocStmt(dbh, &sth);
409  if (oc->expect_return)
410  {
411   pno=1;
412   SQLBindParameter(sth,1,SQL_PARAM_OUTPUT,SQL_C_ULONG,SQL_INTEGER,0,0,&rc,0,0);
413  }
414  else
415   pno=0;
416  SQLBindParameter(sth,(SQLUSMALLINT)(pno+1),SQL_PARAM_INPUT,SQL_C_ULONG,SQL_INTEGER,0,0,&e_id.keyval,0,0);
417  //SQLBindParameter(sth,2,SQL_PARAM_OUTPUT,SQL_C_SLONG,SQL_INTEGER,0,0,&retcode,0,0);
418
419  Debug(LDAP_DEBUG_TRACE,"backsql_delete(): executing '%s'\n",oc->delete_proc,0,0);
420  rc=SQLExecDirect(sth,oc->delete_proc,SQL_NTS);
421  if (rc != SQL_SUCCESS)
422  {
423   Debug(LDAP_DEBUG_TRACE,"backsql_delete(): delete_proc execution failed\n",0,0,0);
424   backsql_PrintErrors(bi->db_env,dbh,sth,rc);
425   SQLFreeStmt(sth,SQL_DROP);
426   send_ldap_result(conn,op,LDAP_OTHER,"","SQL-backend error",NULL,NULL);
427   return 1;
428  }
429  SQLFreeStmt(sth,SQL_RESET_PARAMS);
430
431  SQLBindParameter(sth,1,SQL_PARAM_INPUT,SQL_C_ULONG,SQL_INTEGER,0,0,&e_id.id,0,0);
432  rc=SQLExecDirect(sth,bi->delentry_query,SQL_NTS);
433  if (rc != SQL_SUCCESS)
434  {
435   Debug(LDAP_DEBUG_TRACE,"backsql_delete(): failed to delete record from ldap_entries\n",0,0,0);
436   backsql_PrintErrors(bi->db_env,dbh,sth,rc);
437   SQLFreeStmt(sth,SQL_DROP);
438   send_ldap_result(conn,op,LDAP_OTHER,"","SQL-backend error",NULL,NULL);
439   return 1;
440  }
441  SQLFreeStmt(sth,SQL_DROP);
442
443  send_ldap_result(conn,op,LDAP_SUCCESS,"",NULL,NULL,NULL);
444  Debug(LDAP_DEBUG_TRACE,"<==backsql_delete()\n",0,0,0);
445  return 0;
446 }
447
448 #endif /* SLAPD_SQL */