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