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