a42872c3b598c5a7c2d2acf11751350a2ba418ec
[bse.git] / site / cgi-bin / modules / BSE / DB / Mysql.pm
1 package BSE::DB::Mysql;
2 use strict;
3 use DBI;
4 use vars qw/@ISA/;
5 use Carp 'confess';
6 @ISA = qw(BSE::DB);
7
8 our $VERSION = "1.013";
9
10 use vars qw($VERSION $MAX_CONNECTION_AGE);
11
12 use Constants 0.1 qw/$DSN $UN $PW $DBOPTS/;
13
14 use Carp;
15
16 my $self;
17
18 $MAX_CONNECTION_AGE = 1200;
19
20 my %statements =
21   (
22    # don't ever load the entire articles table
23    #Articles => 'select * from article',
24    replaceArticle =>
25      'replace article values (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)',
26    addArticle =>  
27      'insert article values (null, ?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)',
28    deleteArticle => 'delete from article where id = ?',
29    getArticleByPkey => 'select * from article where id = ?',
30    
31    getArticleByLevel => 'select * from article where level = ?',
32    getArticleByParentid => 'select * from article where parentid = ?',
33    getArticleByLinkAlias => 'select * from article where linkAlias = ?',
34    'Articles.stepParents' => <<EOS,
35 select ar.* from article ar, other_parents op
36   where ar.id = op.parentId and op.childId = ?
37 order by op.childDisplayOrder desc
38 EOS
39    'Articles.visibleStepParents' => <<EOS,
40 select ar.* from article ar, other_parents op
41   where ar.id = op.parentId and op.childId = ?
42      and date_format(?, '%Y%m%d') between date_format(op.release, '%Y%m%d') and date_format(op.expire, '%Y%m%d')
43      and listed <> 0
44 order by op.childDisplayOrder desc
45 EOS
46    'Articles.stepKids' => <<EOS,
47 select ar.* from article ar, other_parents op
48    where op.childId = ar.id and op.parentId = ?
49 EOS
50 # originally "... and ? between op.release and op.expire"
51 # but since the first argument was a string, mysql treated the comparisons
52 # as string comparisons
53    'Articles.visibleStepKids' => <<EOS,
54 select ar.* from article ar, other_parents op
55    where op.childId = ar.id 
56      and op.parentId = ? 
57      and date_format(?, '%Y%m%d') between date_format(op.release, '%Y%m%d') and date_format(op.expire, '%Y%m%d') and listed <> 0
58 EOS
59    'Articles.ids'=>'select id from article',
60    articlePossibleStepparents => <<EOS,
61 select a.id, a.title from article a
62 where a.id not in (select parentId from other_parents where childId = ?) 
63       and a.id <> ?;
64 EOS
65    articlePossibleStepchildren => <<EOS,
66 select a.id, a.title from article a 
67 where a.id not in (select childId from other_parents where parentId = ?) 
68       and a.id <> ?;
69 EOS
70    bse_MaxArticleDisplayOrder => <<EOS,
71 select max(displayOrder) as "displayOrder" from article
72 EOS
73
74    Images => 'select * from image',
75    replaceImage =>
76      'replace image values (?,?,?,?,?,?,?,?,?,?,?,?)',
77    addImage => 'insert image values(null, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)',
78    deleteImage => 'delete from image where id = ?',
79    getImageByArticleId => 'select * from image where articleId = ? order by displayOrder',
80    getImageByPkey => 'select * from image where id = ?',
81    getImageByArticleIdAndName => <<SQL,
82 select * from image where articleId = ? and name = ?
83 SQL
84    
85    dropIndex => 'delete from searchindex',
86    insertIndex => 'insert searchindex values(?, ?, ?, ?)',
87    searchIndex => 'select * from searchindex where id = ?',
88    searchIndexWC => 'select * from searchindex where id like ?',
89    
90    Products=> 'select article.*, product.* from article, product where id = articleId',
91    addProduct => 'insert product values(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)',
92    getProductByPkey => 'select article.*, product.* from article, product where id=? and articleId = id',
93    getProductByProduct_code => 'select article.*, product.* from article, product where product_code=? and articleId = id',
94    getProductByLinkAlias => 'select article.*, product.* from article, product where linkAlias=? and articleId = id',
95    replaceProduct => 'replace product values(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)',
96    'Products.stepProducts' => <<EOS,
97 select ar.*, pr.* from article ar, product pr, other_parents op
98    where ar.id = pr.articleId and op.childId = ar.id and op.parentId = ?
99 EOS
100    'Products.visibleStep' => <<EOS,
101 select ar.*, pr.* from article ar, product pr, other_parents op
102    where ar.id = pr.articleId and op.childId = ar.id 
103      and op.parentId = ? and ? between op.release and op.expire
104      and listed <> 0
105 EOS
106    'Products.subscriptionDependent' => <<SQL,
107 select ar.*, pr.* from article ar, product pr
108    where ar.id = pr.articleId
109      and (pr.subscription_id = ? or subscription_required = ?)
110 SQL
111    'Products.orderProducts' => <<SQL,
112 select ar.*, pr.* from article ar, product pr, order_item oi
113   where oi.orderId = ? and oi.productId = ar.id and ar.id = pr.articleId
114 SQL
115    deleteProduct => 'delete from product where articleId = ?',
116    'Products.userWishlist' => <<SQL,
117 select ar.*, pr.* from article ar, product pr, bse_wishlist wi
118   where wi.user_id = ? and wi.product_id = ar.id and ar.id = pr.articleId
119 order by wi.display_order desc
120 SQL
121    'Products.visible_children_of' => <<SQL,
122 select ar.*, pr.* from article ar, product pr
123    where ar.id = pr.articleId 
124      and listed <> 0
125      and ar.parentid = ?
126      and ? between ar.release and ar.expire
127 SQL
128    bse_userWishlistOrder => <<SQL,
129 select product_id, display_order
130 from bse_wishlist
131 where user_id = ?
132 order by display_order desc
133 SQL
134    bse_userWishlistReorder => <<SQL,
135 update bse_wishlist
136   set display_order = ?
137 where user_id = ? and product_id = ?
138 SQL
139    bse_addToWishlist => <<SQL,
140 insert into bse_wishlist(user_id, product_id, display_order)
141   values(?, ?, ?)
142 SQL
143    bse_removeFromWishlist => <<SQL,
144 delete from bse_wishlist where user_id = ? and product_id = ?
145 SQL
146
147    Orders => 'select * from orders',
148    #getOrderByPkey => 'select * from orders where id = ?',
149    getOrderItemByOrderId => 'select * from order_item where orderId = ?',
150    #addOrder => 'insert orders values(null,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)',
151    #replaceOrder => 'replace orders values(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)',
152    addOrderItem => 'insert order_item values(null,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)',
153    replaceOrderItem => 'replace order_item values(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)',
154    #getOrderByUserId => 'select * from orders where userId = ?',
155    deleteOrdersItems => 'delete from order_item where orderId = ?',
156
157    getOrderItemByProductId => 'select * from order_item where productId = ?',
158
159    OtherParents => 'select * from other_parents',
160    getOtherParentByChildId => <<EOS,
161 select * from other_parents where childId = ? order by childDisplayOrder desc
162 EOS
163    getOtherParentByParentId => <<EOS,
164 select * from other_parents where parentId = ? order by parentDisplayOrder desc
165 EOS
166    getOtherParentByParentIdAndChildId =>
167    'select * from other_parents where parentId = ? and childId = ?',
168    addOtherParent=>'insert other_parents values(null,?,?,?,?,?,?)',
169    deleteOtherParent => 'delete from other_parents where id = ?',
170    replaceOtherParent=>'replace other_parents values(?,?,?,?,?,?,?)',
171    'OtherParents.anylinks' => 
172    'select * from other_parents where childId = ? or parentId = ?',
173
174    ArticleFiles => 'select * from article_files',
175    addArticleFile =>
176    'insert into article_files values (null,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)',
177    replaceArticleFile =>
178    'replace article_files values (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)',
179    deleteArticleFile => 'delete from article_files where id = ?',
180    getArticleFileByArticleId =>
181    'select * from article_files where articleId = ? order by displayOrder desc',
182    getArticleFileByPkey => 'select * from article_files where id = ?',
183
184    "ArticleFiles.orderFiles" =><<SQL,
185 select distinct af.*
186 from article_files af, order_item oi
187 where af.articleId = oi.productId and oi.orderId = ?
188 order by oi.id, af.displayOrder desc
189 SQL
190    
191    # getSiteUserByUserId =>
192    # 'select * from site_users where userId = ?',
193    # getSiteUserByPkey =>
194    # 'select * from site_users where id = ?',
195    # getSiteUserByAffiliate_name =>
196    # 'select * from site_users where affiliate_name = ?',
197    # addSiteUser => 'insert site_users values(null,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)',
198    # replaceSiteUser => 'replace site_users values(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)',
199    'SiteUsers.removeSubscriptions'=>
200    'delete from subscribed_users where userId = ?',
201    'SiteUsers.removeSub'=>
202    'delete from subscribed_users where userId = ? and subId = ?',
203    'SiteUsers.subRecipients' => <<EOS,
204 select si.* from bse_siteusers si, subscribed_users su
205   where confirmed <> 0 and disabled = 0 and si.id = su.userId and su.subId = ?
206 EOS
207    SiteUsers => 'select * from bse_siteusers',
208    'SiteUsers.allSubscribers' => <<SQL,
209 select distinct su.* 
210   from bse_siteusers su, orders od, order_item oi
211   where su.id = od.siteuser_id and od.id = oi.orderId 
212         and oi.subscription_id <> -1
213 SQL
214    siteuserAllIds => 'select id from bse_siteusers',
215    getBSESiteuserImage => <<SQL,
216 select * from bse_siteuser_images
217   where siteuser_id = ? and image_id = ?
218 SQL
219    getBSESiteuserImages => <<SQL,
220 select * from bse_siteuser_images where siteuser_id = ?
221 SQL
222    addBSESiteuserImage => <<SQL,
223 insert bse_siteuser_images values(?,?,?,?,?,?,?,?)
224 SQL
225    replaceBSESiteuserImage => <<SQL,
226 replace bse_siteuser_images values(?,?,?,?,?,?,?,?)
227 SQL
228    deleteBSESiteuserImage=> <<SQL,
229 delete from bse_siteuser_images where siteuser_id = ? and image_id = ?
230 SQL
231
232    SubscriptionTypes =>
233    'select * from subscription_types',
234    addSubscriptionType=>
235    'insert subscription_types values(null,?,?,?,?,?,?,?,?,?,?,?,?)',
236    replaceSubscriptionType=>
237    'replace subscription_types values(?,?,?,?,?,?,?,?,?,?,?,?,?)',
238    getSubscriptionTypeByPkey =>
239    'select * from subscription_types where id = ? order by name',
240    deleteSubscriptionType =>
241    'delete from subscription_types where id = ?',
242    subRecipientCount => <<EOS,
243 select count(*) as "count" from bse_siteusers si, subscribed_users su
244   where confirmed <> 0 and disabled = 0 and si.id = su.userId and su.subId = ?
245 EOS
246    'SubscriptionTypes.userSubscribedTo' => <<'EOS',
247 select su.* from subscription_types su, subscribed_users us
248   where us.userId = ? and us.subId = su.id
249 EOS
250
251    addSubscribedUser=>
252    'insert subscribed_users values(null,?,?)',
253    getSubscribedUserByUserId =>
254    'select * from subscribed_users where userId = ?',
255
256    # the following don't work with the row/table classes
257    articlesList =>
258    'select id, title from article order by level, displayOrder desc',
259
260    getEmailBlackEntryByEmail =>
261    'select * from email_blacklist where email = ?',
262    addEmailBlackEntry =>
263    'insert email_blacklist values(null,?,?)',
264
265    addEmailRequest =>
266    'insert email_requests values(null,?,?,?,?)',
267    replaceEmailRequest =>
268    'replace email_requests values(?,?,?,?,?)',
269    deleteEmailRequest =>
270    'delete from email_requests where id = ?',
271    getEmailRequestByGenEmail =>
272    'select * from email_requests where genEmail = ?',
273
274    addAdminBase => 'insert into admin_base values(null, ?)',
275    replaceAdminBase => 'replace into admin_base values(?, ?)',
276    deleteAdminBase => 'delete from admin_base where id = ?',
277    getAdminBaseByPkey => 'select * from admin_base where id=?',
278    
279    AdminUsers => <<SQL,
280 select bs.*, us.* from admin_base bs, admin_users us
281   where bs.id = us.base_id
282    order by logon
283 SQL
284    getAdminUserByLogon => <<SQL,
285 select bs.*, us.* from admin_base bs, admin_users us
286   where bs.id = us.base_id and us.logon = ?
287 SQL
288    getAdminUserByPkey => <<SQL,
289 select bs.*, us.* from admin_base bs, admin_users us
290   where bs.id = us.base_id and bs.id = ?
291 SQL
292    addAdminUser => 'insert into admin_users values(?,?,?,?,?,?,?)',
293    replaceAdminUser => 'replace into admin_users values(?,?,?,?,?,?,?)',
294    deleteAdminUser => 'delete from admin_users where base_id = ?',
295    "AdminUsers.group_members" => <<SQL,
296 select bs.*, us.*
297   from admin_base bs, admin_users us, admin_membership am
298   where bs.id = us.base_id && am.group_id = ? and am.user_id = bs.id
299   order by logon
300 SQL
301    adminUsersGroups => <<SQL,
302 select bs.*, gr.*
303   from admin_base bs, admin_groups gr, admin_membership am
304   where bs.id = gr.base_id && am.user_id = ? and am.group_id = bs.id
305   order by gr.name
306 SQL
307    userGroups => 'select * from admin_membership where user_id = ?',
308    deleteUserGroups => 'delete from admin_membership where user_id = ?',
309
310    AdminGroups => <<SQL,
311 select bs.*, gr.* 
312   from admin_base bs, admin_groups gr
313   where bs.id = gr.base_id
314   order by name
315 SQL
316    getAdminGroupByName => <<SQL,
317 select bs.*, gr.* from admin_base bs, admin_groups gr
318   where bs.id = gr.base_id and gr.name = ?
319 SQL
320    getAdminGroupByPkey => <<SQL,
321 select bs.*, gr.* from admin_base bs, admin_groups gr
322   where bs.id = gr.base_id and bs.id = ?
323 SQL
324    addAdminGroup => 'insert into admin_groups values(?,?,?,?,?)',
325    replaceAdminGroup => 'replace into admin_groups values(?,?,?,?,?)',
326    deleteAdminGroup => 'delete from admin_groups where base_id = ?',
327    groupUsers => 'select * from admin_membership where group_id = ?',
328    bseAdminGroupMember => <<SQL,
329 select 1
330 from admin_membership
331 where group_id = ?
332   and user_id = ?
333 SQL
334    'AdminGroups.userPermissionGroups' => <<SQL,
335 select bs.*, ag.* from admin_base bs, admin_groups ag, admin_membership am
336 where bs.id = ag.base_id
337   and ( (ag.base_id = am.group_id and am.user_id = ?) 
338         or ag.name = 'everyone' )
339 SQL
340
341    addUserToGroup => 'insert into admin_membership values(?,?)',
342    delUserFromGroup => <<SQL,
343 delete from admin_membership where user_id = ? and group_id = ?
344 SQL
345    deleteGroupUsers => 'delete from admin_membership where group_id = ?',
346
347    articleObjectPerm => <<SQL,
348 select * from admin_perms where object_id = ? and admin_id = ?
349 SQL
350    addArticleObjectPerm => 'insert into admin_perms values(?,?,?)',
351    replaceArticleObjectPerm => 'replace into admin_perms values(?,?,?)',
352    userPerms => <<SQL,
353 select distinct ap.* 
354 from admin_perms ap
355 where ap.admin_id = ?
356 SQL
357    groupPerms => <<SQL,
358 select distinct ap.* 
359 from admin_perms ap, admin_membership am
360 where ap.admin_id = am.group_id and am.user_id = ?
361 SQL
362    commonPerms => <<SQL,
363 select distinct ap.* 
364 from admin_perms ap, admin_groups ag
365 where ap.admin_id = ag.base_id and ag.name = 'everyone'
366 SQL
367    Subscriptions => 'select * from bse_subscriptions',
368    addSubscription => 'insert bse_subscriptions values(null,?,?,?,?)',
369    replaceSubscription => 'replace bse_subscriptions values(?,?,?,?,?)',
370    deleteSubscription => <<SQL,
371 delete from bse_subscriptions where subscription_id = ?
372 SQL
373    getSubscriptionByPkey => <<SQL,
374 select * from bse_subscriptions where subscription_id = ?
375 SQL
376    getSubscriptionByText_id => <<SQL,
377 select * from bse_subscriptions where text_id = ?
378 SQL
379    subscriptionOrderItemCount => <<SQL,
380 select count(*) as "count" from order_item where subscription_id = ?
381 SQL
382    subscriptionOrderSummary => <<SQL,
383 select od.id, od.userId, od.orderDate, od.siteuser_id, od.billFirstName, od.billLastName, od.filled, 
384     sum(oi.subscription_period * oi.units) as "subscription_period"
385   from orders od, order_item oi
386   where oi.subscription_id = ? and od.id = oi.orderId and od.complete <> 0
387   group by od.id, od.userId, od.orderDate, od.siteuser_id
388   order by od.orderDate desc
389 SQL
390    subscriptionUserSummary => <<SQL,
391 select su.*, us.*
392   from bse_siteusers su, bse_user_subscribed us
393 where su.id = us.siteuser_id and us.subscription_id = ?
394 SQL
395    subscriptionProductCount => <<SQL,
396 select count(*) as "count" from product 
397   where subscription_id = ? or subscription_required = ?
398 SQL
399    removeUserSubscribed => <<SQL,
400 delete from bse_user_subscribed where subscription_id = ? and siteuser_id = ?
401 SQL
402    addUserSubscribed => <<SQL,
403 insert bse_user_subscribed values (?,?,?,?,?)
404 SQL
405    subscriptionUserBought => <<SQL,
406 select od.orderDate,
407   oi.subscription_period * oi.units as "subscription_period",
408   oi.max_lapsed, 
409   od.id as "order_id", oi.id as "item_id", oi.productId as "product_id"
410   from orders od, order_item oi
411   where oi.subscription_id = ? and od.id = oi.orderId and od.siteuser_id = ?
412         and od.complete <> 0
413 SQL
414    userSubscribedEntry => <<SQL,
415 select * from bse_user_subscribed 
416   where siteuser_id = ? and subscription_id = ?
417 SQL
418    siteuserSubscriptions => <<SQL,
419 select su.*, us.started_at, us.ends_at, us.max_lapsed
420   from bse_subscriptions su, bse_user_subscribed us
421 where us.siteuser_id = ? and us.subscription_id = su.subscription_id
422    and us.ends_at >= curdate()
423 SQL
424
425    addLocation => <<SQL,
426 insert bse_locations values(null,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)
427 SQL
428    replaceLocation => <<SQL,
429 replace bse_locations values(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)
430 SQL
431    getLocationByPkey => 'select * from bse_locations where id = ?',
432    deleteLocation => 'delete from bse_locations where id = ?',
433    Locations => 'select * from bse_locations order by description',
434
435    Seminars => <<SQL,
436 select ar.*, pr.*, se.*
437   from article ar, product pr, bse_seminars se
438   where ar.id = pr.articleId and ar.id = se.seminar_id
439 SQL
440    addSeminar => 'insert bse_seminars values(?,?)',
441    replaceSeminar => 'replace bse_seminars values(?,?)',
442    deleteSeminar => 'delete from bse_seminars where seminar_id = ?',
443    getSeminarByPkey => <<SQL,
444 select ar.*, pr.*, se.*
445   from article ar, product pr, bse_seminars se
446   where id = ? and ar.id = pr.articleId and ar.id = se.seminar_id
447 SQL
448    getSeminarByProduct_code => <<SQL,
449 select ar.*, pr.*, se.*
450   from article ar, product pr, bse_seminars se
451   where product_code = ? and ar.id = pr.articleId and ar.id = se.seminar_id
452 SQL
453    'Locations.seminarFuture' => <<SQL,
454 select distinct lo.*
455   from bse_locations lo, bse_seminar_sessions ss
456 where ss.seminar_id = ? and ss.when_at > ?
457   and ss.location_id = lo.id
458 order by lo.description
459 SQL
460    'Locations.session_id' => <<SQL,
461 select lo.*
462   from bse_locations lo, bse_seminar_sessions ss
463 where lo.id = ss.location_id and ss.id = ?
464 SQL
465
466    seminarSessionInfo => <<SQL,
467 select se.*, lo.description
468   from bse_seminar_sessions se, bse_locations lo
469   where se.seminar_id = ? and se.location_id = lo.id
470 order by when_at desc
471 SQL
472    seminarFutureSessionInfo => <<SQL,
473 select se.*, lo.description, lo.room, lo.street1, lo.street2, lo.suburb, 
474     lo.state, lo.country, lo.postcode, lo.public_notes
475   from bse_seminar_sessions se, bse_locations lo
476   where se.seminar_id = ? and se.when_at > ? and se.location_id = lo.id
477 order by when_at desc
478 SQL
479    addSeminarSession => 'insert bse_seminar_sessions values(null,?,?,?,?)',
480    replaceSeminarSession => 'replace bse_seminar_sessions values(?,?,?,?,?)',
481    deleteSeminarSession => 'delete from bse_seminar_sessions where id = ?',
482    getSeminarSessionByPkey => 'select * from bse_seminar_sessions where id = ?',
483    getSeminarSessionByLocation_idAndWhen_at => <<SQL,
484 select * from bse_seminar_sessions
485   where location_id = ? and when_at = ?
486 SQL
487    getSeminarSessionBySeminar_id => <<SQL,
488 select * from bse_seminar_sessions
489   where seminar_id = ?
490 SQL
491    'SeminarSessions.futureSessions' => <<SQL,
492 select * from bse_seminar_sessions
493   where seminar_id = ? and when_at >= ?
494 SQL
495    'SeminarSessions.futureSeminarLocation' => <<SQL,
496 select *
497   from bse_seminar_sessions
498   where seminar_id = ? and location_id = ? and when_at > ?
499 SQL
500    'SiteUsers.sessionBookings' => <<SQL,
501 select su.* from bse_siteusers su, bse_seminar_bookings sb
502   where sb.session_id = ? and su.id = sb.siteuser_id
503 SQL
504    cancelSeminarSessionBookings => <<SQL,
505 delete from bse_seminar_bookings where session_id = ?
506 SQL
507    conflictSeminarSessions => <<SQL,
508 select bo1.siteuser_id
509   from bse_seminar_bookings bo1, bse_seminar_bookings bo2
510 where bo1.session_id = ? and bo2.session_id = ? 
511   and bo1.siteuser_id = bo2.siteuser_id
512 SQL
513    seminarSessionBookedIds => <<SQL,
514 select * from bse_seminar_bookings where session_id = ?
515 SQL
516    addSeminarBooking => <<SQL,
517 insert bse_seminar_bookings values(null,?,?,?,?,?,?)
518 SQL
519    seminarSessionRollCallEntries => <<SQL,
520 select bo.roll_present, su.id, su.userId, su.name1, su.name2, su.email,
521     bo.id as booking_id
522   from bse_seminar_bookings bo, bse_siteusers su
523 where bo.session_id = ? and bo.siteuser_id = su.id
524 SQL
525   updateSessionRollPresent => <<SQL,
526 update bse_seminar_bookings
527   set roll_present = ?
528   where session_id = ? and siteuser_id = ?
529 SQL
530    userSeminarSessionBookings => <<SQL,
531 select session_id 
532   from bse_seminar_bookings sb, bse_seminar_sessions ss
533 where ss.seminar_id = ? and ss.id = sb.session_id and siteuser_id = ?
534 SQL
535    SiteUserGroups => 'select * from bse_siteuser_groups',
536    addSiteUserGroup => 'insert bse_siteuser_groups values(null,?)',
537    replaceSiteUserGroup => 'replace bse_siteuser_groups values(?,?)',
538    deleteSiteUserGroup => 'delete from bse_siteuser_groups where id = ?',
539    getSiteUserGroupByPkey => 'select * from bse_siteuser_groups where id = ?',
540    getSiteUserGroupByName => 'select * from bse_siteuser_groups where name = ?',
541    siteuserGroupMemberIds => <<SQL,
542 select siteuser_id as "id" 
543 from bse_siteuser_membership 
544 where group_id = ?
545 SQL
546    siteuserGroupAddMember => <<SQL,
547 insert bse_siteuser_membership values(?,?)
548 SQL
549    siteuserGroupDeleteMember => <<SQL,
550 delete from bse_siteuser_membership where group_id = ? and siteuser_id = ?
551 SQL
552     siteuserGroupDeleteAllMembers => <<SQL,
553 delete from bse_siteuser_membership where group_id = ?
554 SQL
555     siteuserMemberOfGroup => <<SQL,
556 select * from bse_siteuser_membership 
557 where siteuser_id = ? and group_id = ?
558 SQL
559     siteuserGroupsForUser => <<SQL,
560 select group_id as "id" from bse_siteuser_membership where siteuser_id = ?
561 SQL
562
563     articleAccessibleToGroup => <<SQL,
564 select * from bse_article_groups
565 where article_id = ? and group_id = ?
566 SQL
567     siteuserGroupsForArticle => <<SQL,
568 select group_id as "id" from bse_article_groups
569 where article_id = ?
570 SQL
571     articleAddSiteUserGroup => <<SQL,
572 insert bse_article_groups values(?,?)
573 SQL
574     articleDeleteSiteUserGroup => <<SQL,
575 delete from bse_article_groups 
576 where article_id = ? and group_id = ?
577 SQL
578     siteuserGroupDeleteAllPermissions => <<SQL,
579 delete from bse_article_groups where group_id = ?
580 SQL
581   );
582
583 # called when we start working on a new request, mysql seems to have
584 # problems with old connections sometimes, or so it seems, so
585 # disconnect occasionally (only matters for fastcgi, mod_perl)
586 sub _startup {
587   my $class = shift;
588
589   if ($self) {
590     unless ($self->{dbh}->ping) {
591       print STDERR "Database connection lost - reconnecting\n";
592       $self->{dbh} = $class->connect;
593       $self->{birth} = time();
594     }
595   }
596 }
597
598 sub connect {
599   my ($class, $dbname) = @_;
600
601   my $dsn = $class->dsn($dbname);
602   my $un = $self->dbuser($dbname);
603   my $pass = $self->dbpassword($dbname);
604   my $dbopts = $self->dbopts($dbname);
605   my $dbh = DBI->connect( $dsn, $un, $pass, $dbopts)
606       or die "Cannot connect to database: $DBI::errstr";
607
608   # this might fail, but I don't care
609   $dbh->do("set session sql_mode='ansi_quotes'");
610
611   return $dbh;
612 }
613
614 sub _single
615 {
616   my ($class, $cfg) = @_;
617
618   warn "Incorrect number of parameters passed to BSE::DB::Mysql::single\n" unless @_ == 2;
619   
620   unless ( defined $self ) {
621     $self = bless 
622       { 
623        dbh => undef,
624        birth => time(),
625        cfg => $cfg,
626       }, $class;
627
628     $self->{dbh} = $self->connect;
629   }
630   $self;
631 }
632
633 sub _forked {
634   my $self = shift;
635
636   $self->{dbh}{InactiveDestroy} = 1;
637   delete $self->{dbh};
638   $self->{dbh} = $self->connect;
639 }
640
641
642 my $get_sql_by_name = 'select sql_statement from sql_statements where name=?';
643
644 my %sql_cache;
645
646 sub stmt_sql {
647   my ($self, $name) = @_;
648
649   $name =~ s/BSE.*:://;
650
651   my $sql = $statements{$name};
652   unless ($sql) {
653     if (exists $sql_cache{$name}) {
654       return $sql_cache{$name};
655     }
656   }
657   unless ($sql) {
658     my @row = $self->{dbh}->selectrow_array($get_sql_by_name, {}, $name);
659     if (@row) {
660       $sql = $row[0];
661       #print STDERR "Found SQL '$sql'\n";
662     }
663     else {
664       #print STDERR "SQL statment $name not found in sql_statements table\n";
665     }
666
667     $sql_cache{$name} = $sql;
668   }
669
670   return $sql;
671 }
672
673 sub stmt {
674   my ($self, $name) = @_;
675
676   my $sql = $self->stmt_sql($name)
677     or confess "Statement named '$name' not found";
678   my $sth = $self->{dbh}->prepare($sql)
679     or croak "Cannot prepare $name statment: ",$self->{dbh}->errstr;
680
681   $sth;
682 }
683
684 sub stmt_noerror {
685   my ($self, $name) = @_;
686
687   my $sql = $self->stmt_sql($name)
688     or return;
689   my $sth = $self->{dbh}->prepare($sql)
690     or croak "Cannot prepare $name statment: ",$self->{dbh}->errstr;
691
692   $sth;
693 }
694
695 sub insert_id {
696   my ($self, $sth) = @_;
697
698   my $id = $sth->{"mysql_insertid"};
699
700   return $id;
701 }
702
703 sub dbopts {
704   my ($class) = @_;
705
706   my $opts = $class->SUPER::dbopts();
707
708   if (BSE::Cfg->utf8
709       && lc(BSE::Cfg->charset) eq "utf-8") {
710     $opts->{mysql_enable_utf8} = 1;
711   }
712
713   return $opts;
714 }
715
716 # gotta love this
717 sub DESTROY
718 {
719   my ($self) = @_;
720   # this is wierd - we only need to reset this on 5.6.x (for x == 0 so
721   # far)
722   # Works fine without the reset for 5.005_03
723   if ($self->{dbh}) {
724     $self->{dbh}->disconnect;
725     delete $self->{dbh};
726   }
727 }
728
729 1;
730