1 /* @source ensbaseadaptor *****************************************************
2 **
3 ** Ensembl Base Adaptor functions
4 **
5 ** @author Copyright (C) 1999 Ensembl Developers
6 ** @author Copyright (C) 2006 Michael K. Schuster
7 ** @version $Revision: 1.40 $
8 ** @modified 2009 by Alan Bleasby for incorporation into EMBOSS core
9 ** @modified $Date: 2013/02/17 13:03:35 $ by $Author: mks $
10 ** @@
11 **
12 ** This library is free software; you can redistribute it and/or
13 ** modify it under the terms of the GNU Lesser General Public
14 ** License as published by the Free Software Foundation; either
15 ** version 2.1 of the License, or (at your option) any later version.
16 **
17 ** This library is distributed in the hope that it will be useful,
18 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
19 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 ** Lesser General Public License for more details.
21 **
22 ** You should have received a copy of the GNU Lesser General Public
23 ** License along with this library; if not, write to the Free Software
24 ** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
25 ** MA 02110-1301, USA.
26 **
27 ******************************************************************************/
28
29 /* ========================================================================= */
30 /* ============================= include files ============================= */
31 /* ========================================================================= */
32
33 #include "ensanalysis.h"
34 #include "ensbaseadaptor.h"
35 #include "ensfeature.h"
36 #include "enstable.h"
37
38
39
40
41 /* ========================================================================= */
42 /* =============================== constants =============================== */
43 /* ========================================================================= */
44
45 /* @const ensKBaseadaptorMaximumIdentifiers ***********************************
46 **
47 ** Limit the number of identifier instances in SQL queries to chunks of
48 ** maximum size.
49 **
50 ** Ensure that the MySQL max_allowed_packet is not exceeded, which defaults
51 ** to 1 MB, by splitting large queries into smaller queries of at most 256 KiB
52 ** (32768 8-bit characters). Assuming a (generous) average identifier string
53 ** length of 16, this means a maximum of 2048 identifier instances in each
54 ** statement.
55 **
56 ******************************************************************************/
57
58 const ajuint ensKBaseadaptorMaximumIdentifiers = 2048U;
59
60
61
62
63 /* ========================================================================= */
64 /* =========================== global variables ============================ */
65 /* ========================================================================= */
66
67
68
69
70 /* ========================================================================= */
71 /* ============================= private data ============================== */
72 /* ========================================================================= */
73
74
75
76
77 /* ========================================================================= */
78 /* =========================== private constants =========================== */
79 /* ========================================================================= */
80
81
82
83
84 /* ========================================================================= */
85 /* =========================== private variables =========================== */
86 /* ========================================================================= */
87
88
89
90
91 /* ========================================================================= */
92 /* =========================== private functions =========================== */
93 /* ========================================================================= */
94
95 static AjBool baseadaptorFetchAllStatement(
96 EnsPBaseadaptor ba,
97 const char* const* Pcolumnnames,
98 const AjPStr constraint,
99 AjPStr *Pstatement);
100
101 static AjBool baseadaptorRetrieveAllStatement(
102 EnsPBaseadaptor ba,
103 const AjPStr tablename,
104 const AjPStr columnname,
105 AjPStr *Pstatement);
106
107
108
109
110 /* ========================================================================= */
111 /* ======================= All functions by section ======================== */
112 /* ========================================================================= */
113
114
115
116
117 /* @filesection ensbaseadaptor ************************************************
118 **
119 ** @nam1rule ens Function belongs to the Ensembl library
120 **
121 ******************************************************************************/
122
123
124
125
126 /* @datasection [EnsPBaseadaptor] Ensembl Base Adaptor ************************
127 **
128 ** @nam2rule Baseadaptor Functions for manipulating
129 ** Ensembl Base Adaptor objects
130 **
131 ** @cc Bio::EnsEMBL::DBSQL::BaseAdaptor
132 ** @cc CVS Revision: 1.68
133 ** @cc CVS Tag: branch-ensembl-68
134 **
135 ******************************************************************************/
136
137
138
139
140 /* @section constructors ******************************************************
141 **
142 ** All constructors return a new Ensembl Base Adaptor by pointer.
143 ** It is the responsibility of the user to first destroy any previous
144 ** Base Adaptor. The target pointer does not need to be initialised to
145 ** NULL, but it is good programming practice to do so anyway.
146 **
147 ** @fdata [EnsPBaseadaptor]
148 **
149 ** @nam3rule New Constructor with initial values
150 **
151 ** @argrule New dba [EnsPDatabaseadaptor]
152 ** Ensembl Database Adaptor
153 ** @argrule New Ptablenames [const char* const*]
154 ** SQL table name array
155 ** @argrule New Pcolumnnames [const char* const*]
156 ** SQL column name array
157 ** @argrule New leftjoins [const EnsPBaseadaptorLeftjoin]
158 ** SQL LEFT JOIN condition array
159 ** @argrule New defaultcondition [const char*]
160 ** SQL SELECT default condition
161 ** @argrule New finalcondition [const char*]
162 ** SQL SELECT final condition
163 ** @argrule New Fstatement [AjBool function]
164 ** Statement function address
165 **
166 ** @valrule * [EnsPBaseadaptor] Ensembl Base Adaptor or NULL
167 **
168 ** @fcategory new
169 ******************************************************************************/
170
171
172
173
174 /* @func ensBaseadaptorNew ****************************************************
175 **
176 ** Default constructor for an Ensembl Base Adaptor.
177 **
178 ** @cc Bio::EnsEMBL::DBSQL::BaseAdaptor::new
179 ** @param [u] dba [EnsPDatabaseadaptor]
180 ** Ensembl Database Adaptor
181 ** @param [r] Ptablenames [const char* const*]
182 ** SQL table name array
183 ** @param [r] Pcolumnnames [const char* const*]
184 ** SQL column name array
185 ** @param [rN] leftjoins [const EnsPBaseadaptorLeftjoin]
186 ** SQL LEFT JOIN condition array
187 ** @param [rN] defaultcondition [const char*]
188 ** SQL SELECT default condition
189 ** @param [rN] finalcondition [const char*]
190 ** SQL SELECT final condition
191 ** @param [f] Fstatement [AjBool function]
192 ** Statement function address
193 **
194 ** @return [EnsPBaseadaptor] Ensembl Base Adaptor or NULL
195 **
196 ** @release 6.2.0
197 ** @@
198 ******************************************************************************/
199
ensBaseadaptorNew(EnsPDatabaseadaptor dba,const char * const * Ptablenames,const char * const * Pcolumnnames,const EnsPBaseadaptorLeftjoin leftjoins,const char * defaultcondition,const char * finalcondition,AjBool (* Fstatement)(EnsPBaseadaptor ba,const AjPStr statement,EnsPAssemblymapper am,EnsPSlice slice,AjPList objects))200 EnsPBaseadaptor ensBaseadaptorNew(
201 EnsPDatabaseadaptor dba,
202 const char *const *Ptablenames,
203 const char *const *Pcolumnnames,
204 const EnsPBaseadaptorLeftjoin leftjoins,
205 const char *defaultcondition,
206 const char *finalcondition,
207 AjBool (*Fstatement) (EnsPBaseadaptor ba,
208 const AjPStr statement,
209 EnsPAssemblymapper am,
210 EnsPSlice slice,
211 AjPList objects))
212 {
213 EnsPBaseadaptor ba = NULL;
214
215 if (!dba)
216 return NULL;
217
218 if (!Ptablenames)
219 return NULL;
220
221 if (!Pcolumnnames)
222 return NULL;
223
224 if (!Fstatement)
225 return NULL;
226
227 AJNEW0(ba);
228
229 ba->Adaptor = dba;
230 ba->Tablenames = Ptablenames;
231 ba->Columnnames = Pcolumnnames;
232 ba->Leftjoins = leftjoins;
233 ba->Defaultcondition = defaultcondition;
234 ba->Finalcondition = finalcondition;
235 ba->Fstatement = Fstatement;
236
237 return ba;
238 }
239
240
241
242
243 /* @section destructors *******************************************************
244 **
245 ** Destruction destroys all internal data structures and frees the memory
246 ** allocated for an Ensembl Base Adaptor object.
247 **
248 ** @fdata [EnsPBaseadaptor]
249 **
250 ** @nam3rule Del Destroy (free) an Ensembl Base Adaptor
251 **
252 ** @argrule * Pba [EnsPBaseadaptor*] Ensembl Base Adaptor address
253 **
254 ** @valrule * [void]
255 **
256 ** @fcategory delete
257 ******************************************************************************/
258
259
260
261
262 /* @func ensBaseadaptorDel ****************************************************
263 **
264 ** Default destructor for an Ensembl Base Adaptor.
265 **
266 ** @param [d] Pba [EnsPBaseadaptor*] Ensembl Base Adaptor address
267 **
268 ** @return [void]
269 **
270 ** @release 6.2.0
271 ** @@
272 ******************************************************************************/
273
ensBaseadaptorDel(EnsPBaseadaptor * Pba)274 void ensBaseadaptorDel(EnsPBaseadaptor *Pba)
275 {
276 EnsPBaseadaptor pthis = NULL;
277
278 if (!Pba)
279 return;
280
281 #if defined(AJ_DEBUG) && AJ_DEBUG >= 1
282 if (ajDebugTest("ensBaseadaptorDel"))
283 ajDebug("ensBaseadaptorDel\n"
284 " *Pba %p\n",
285 *Pba);
286 #endif /* defined(AJ_DEBUG) && AJ_DEBUG >= 1 */
287
288 if (!(pthis = *Pba))
289 return;
290
291 ajMemFree((void **) Pba);
292
293 return;
294 }
295
296
297
298
299 /* @section member retrieval **************************************************
300 **
301 ** Functions for returning members of an Ensembl Base Adaptor object.
302 **
303 ** @fdata [EnsPBaseadaptor]
304 **
305 ** @nam3rule Get Return Base Adaptor attribute(s)
306 ** @nam4rule Columnnames Return the SQl column name array
307 ** @nam4rule Databaseadaptor Return the Ensembl Database Adaptor
308 ** @nam4rule Tablenames Return the SQL table name array
309 **
310 ** @argrule * ba [const EnsPBaseadaptor] Ensembl Base Adaptor
311 **
312 ** @valrule Columnnames [const char* const*] SQL column name array or NULL
313 ** @valrule Databaseadaptor [EnsPDatabaseadaptor] Ensembl Database Adaptor
314 ** or NULL
315 ** @valrule Tablenames [const char* const*] SQL table name array or NULL
316 **
317 ** @fcategory use
318 ******************************************************************************/
319
320
321
322
323 /* @func ensBaseadaptorGetColumnnames *****************************************
324 **
325 ** Get the SQL column name array member of an Ensembl Base Adaptor.
326 **
327 ** @cc Bio::EnsEMBL::DBSQL::BaseAdaptor::_columns
328 ** @param [r] ba [const EnsPBaseadaptor] Ensembl Base Adaptor
329 **
330 ** @return [const char* const*] SQL column name array or NULL
331 **
332 ** @release 6.2.0
333 ** @@
334 ******************************************************************************/
335
ensBaseadaptorGetColumnnames(const EnsPBaseadaptor ba)336 const char* const* ensBaseadaptorGetColumnnames(const EnsPBaseadaptor ba)
337 {
338 return (ba) ? ba->Columnnames : NULL;
339 }
340
341
342
343
344 /* @func ensBaseadaptorGetDatabaseadaptor *************************************
345 **
346 ** Get the Ensembl Database Adaptor member of an Ensembl Base Adaptor.
347 **
348 ** @cc Bio::EnsEMBL::DBSQL::BaseAdaptor::db
349 ** @param [r] ba [const EnsPBaseadaptor] Ensembl Base Adaptor
350 **
351 ** @return [EnsPDatabaseadaptor] Ensembl Database Adaptor or NULL
352 **
353 ** @release 6.2.0
354 ** @@
355 ******************************************************************************/
356
ensBaseadaptorGetDatabaseadaptor(const EnsPBaseadaptor ba)357 EnsPDatabaseadaptor ensBaseadaptorGetDatabaseadaptor(const EnsPBaseadaptor ba)
358 {
359 return (ba) ? ba->Adaptor : NULL;
360 }
361
362
363
364
365 /* @func ensBaseadaptorGetTablenames ******************************************
366 **
367 ** Get the SQL table name array member of an Ensembl Base Adaptor.
368 **
369 ** @cc Bio::EnsEMBL::DBSQL::BaseAdaptor::_tables
370 ** @param [r] ba [const EnsPBaseadaptor] Ensembl Base Adaptor
371 **
372 ** @return [const char* const*] SQL table name array or NULL
373 **
374 ** @release 6.2.0
375 ** @@
376 ******************************************************************************/
377
ensBaseadaptorGetTablenames(const EnsPBaseadaptor ba)378 const char* const* ensBaseadaptorGetTablenames(const EnsPBaseadaptor ba)
379 {
380 return (ba) ? ba->Tablenames : NULL;
381 }
382
383
384
385
386 /* @section member assignment *************************************************
387 **
388 ** Functions for assigning members of an Ensembl Base Adaptor object.
389 **
390 ** @fdata [EnsPBaseadaptor]
391 **
392 ** @nam3rule Set Set one member of a Base Adaptor
393 ** @nam4rule Columnnames Set the SQL column name array
394 ** @nam4rule Defaultcondition Set the SQL SELECT default condition
395 ** @nam4rule Finalcondition Set the SQL SELECT final condition
396 ** @nam4rule Tablenames Set the SQL table name array
397 **
398 ** @argrule * ba [EnsPBaseadaptor] Base Adaptor
399 ** @argrule Columnnames Pcolumnnames [const char* const*]
400 ** SQL column name array
401 ** @argrule Defaultcondition defaultcondition [const char*]
402 ** SQL SELECT default condition
403 ** @argrule Finalcondition finalcondition [const char*]
404 ** SQL SELECT final condition
405 ** @argrule Tablenames Ptablenames [const char* const*]
406 ** SQL table name array
407 **
408 ** @valrule * [AjBool] ajTrue upon success, ajFalse otherwise
409 **
410 ** @fcategory modify
411 ******************************************************************************/
412
413
414
415
416 /* @func ensBaseadaptorSetColumnnames *****************************************
417 **
418 ** Set the SQL column name array member of an Ensembl Base Adaptor.
419 **
420 ** @cc Bio::EnsEMBL::DBSQL::BaseAdaptor::_columns
421 ** @param [u] ba [EnsPBaseadaptor] Ensembl Base Adaptor
422 ** @param [r] Pcolumnnames [const char* const*] SQL column name array
423 **
424 ** @return [AjBool] ajTrue upon success, ajFalse otherwise
425 **
426 ** @release 6.2.0
427 ** @@
428 ******************************************************************************/
429
ensBaseadaptorSetColumnnames(EnsPBaseadaptor ba,const char * const * Pcolumnnames)430 AjBool ensBaseadaptorSetColumnnames(EnsPBaseadaptor ba,
431 const char* const* Pcolumnnames)
432 {
433 if (!ba)
434 return ajFalse;
435
436 if (!Pcolumnnames)
437 return ajFalse;
438
439 ba->Columnnames = Pcolumnnames;
440
441 return ajTrue;
442 }
443
444
445
446
447 /* @func ensBaseadaptorSetDefaultcondition ************************************
448 **
449 ** Set the SQL SELECT default condition member of an Ensembl Base Adaptor.
450 **
451 ** @cc Bio::EnsEMBL::DBSQL::BaseAdaptor::_default_where_clause
452 ** @param [u] ba [EnsPBaseadaptor] Ensembl Base Adaptor
453 ** @param [r] defaultcondition [const char*] SQL SELECT default condition
454 **
455 ** @return [AjBool] ajTrue upon success, ajFalse otherwise
456 **
457 ** @release 6.4.0
458 ** @@
459 ******************************************************************************/
460
ensBaseadaptorSetDefaultcondition(EnsPBaseadaptor ba,const char * defaultcondition)461 AjBool ensBaseadaptorSetDefaultcondition(EnsPBaseadaptor ba,
462 const char *defaultcondition)
463 {
464 if (!ba)
465 return ajFalse;
466
467 ba->Defaultcondition = defaultcondition;
468
469 return ajTrue;
470 }
471
472
473
474
475 /* @func ensBaseadaptorSetFinalcondition **************************************
476 **
477 ** Set the SQL SELECT final condition member of an Ensembl Base Adaptor.
478 **
479 ** @cc Bio::EnsEMBL::DBSQL::BaseAdaptor::_final_clause
480 ** @param [u] ba [EnsPBaseadaptor] Ensembl Base Adaptor
481 ** @param [r] finalcondition [const char*] SQL SELECT final condition
482 **
483 ** @return [AjBool] ajTrue upon success, ajFalse otherwise
484 **
485 ** @release 6.4.0
486 ** @@
487 ******************************************************************************/
488
ensBaseadaptorSetFinalcondition(EnsPBaseadaptor ba,const char * finalcondition)489 AjBool ensBaseadaptorSetFinalcondition(EnsPBaseadaptor ba,
490 const char *finalcondition)
491 {
492 if (!ba)
493 return ajFalse;
494
495 ba->Finalcondition = finalcondition;
496
497 return ajTrue;
498 }
499
500
501
502
503 /* @func ensBaseadaptorSetTablenames ******************************************
504 **
505 ** Set the SQL table name array member of an Ensembl Base Adaptor.
506 **
507 ** @cc Bio::EnsEMBL::DBSQL::BaseAdaptor::_tables
508 ** @param [u] ba [EnsPBaseadaptor] Ensembl Base Adaptor
509 ** @param [r] Ptablenames [const char* const*] SQL table name array
510 **
511 ** @return [AjBool] ajTrue upon success, ajFalse otherwise
512 **
513 ** @release 6.2.0
514 ** @@
515 ******************************************************************************/
516
ensBaseadaptorSetTablenames(EnsPBaseadaptor ba,const char * const * Ptablenames)517 AjBool ensBaseadaptorSetTablenames(EnsPBaseadaptor ba,
518 const char* const* Ptablenames)
519 {
520 if (!ba)
521 return ajFalse;
522
523 if (!Ptablenames)
524 return ajFalse;
525
526 ba->Tablenames = Ptablenames;
527
528 return ajTrue;
529 }
530
531
532
533
534 /* @section convenience functions *********************************************
535 **
536 ** Ensembl Base Adaptor convenience functions
537 **
538 ** @fdata [EnsPBaseadaptor]
539 **
540 ** @nam3rule Escape Escape a string
541 ** @nam4rule C Escape to an AJAX String
542 ** @nam4rule S Escape to a C-type character string
543 ** @nam3rule Get Get members(s)
544 ** @nam4rule All Get all members
545 ** @nam4rule Multispecies Get the Ensembl Database Adaptor
546 ** multiple-species flag
547 ** @nam4rule Primarytable Get the primary SQL table name
548 ** @nam4rule Speciesidentifier Get the Ensembl Database Adaptor
549 ** species identifier
550 **
551 ** @argrule Escape ba [EnsPBaseadaptor] Ensembl Base Adaptor
552 ** @argrule EscapeC Ptxt [char**] Address of the (new) SQL-escaped C string
553 ** @argrule EscapeC str [const AjPStr] AJAX String to be escaped
554 ** @argrule EscapeS Pstr [AjPStr*] Address of the (new) SQL-escaped AJAX String
555 ** @argrule EscapeS str [const AjPStr] AJAX String to be escaped
556 ** @argrule Get ba [const EnsPBaseadaptor] Ensembl Base Adaptor
557 **
558 ** @valrule EscapeC [AjBool] ajTrue upon success, ajFalse otherwise
559 ** @valrule EscapeS [AjBool] ajTrue upon success, ajFalse otherwise
560 ** @valrule Multispecies [AjBool] ajTrue for multiple species
561 ** @valrule Primarytable [const char*] Primary table name address or NULL
562 ** @valrule Speciesidentifier [ajuint] Ensembl Database Adaptor
563 ** species identifier or 0
564 **
565 ** @fcategory use
566 ******************************************************************************/
567
568
569
570
571 /* @func ensBaseadaptorEscapeC ************************************************
572 **
573 ** Escape special characters in an AJAX String for use in an SQL statement,
574 ** taking into account the current character set of the AJAX SQL Connection
575 ** and return a C-type character string.
576 **
577 ** The caller is responsible for deleting the escaped C-type character string.
578 **
579 ** @param [u] ba [EnsPBaseadaptor] Ensembl Base Adaptor
580 ** @param [wP] Ptxt [char**] Address of the (new) SQL-escaped C string
581 ** @param [r] str [const AjPStr] AJAX String to be escaped
582 **
583 ** @return [AjBool] ajTrue upon success, ajFalse otherwise
584 **
585 ** @release 6.2.0
586 ** @@
587 ******************************************************************************/
588
ensBaseadaptorEscapeC(EnsPBaseadaptor ba,char ** Ptxt,const AjPStr str)589 AjBool ensBaseadaptorEscapeC(EnsPBaseadaptor ba,
590 char **Ptxt,
591 const AjPStr str)
592 {
593 #if defined(AJ_DEBUG) && AJ_DEBUG >= 1
594 if (ajDebugTest("ensBaseadaptorEscapeC"))
595 ajDebug("ensBaseadaptorEscapeC\n"
596 " ba %p\n"
597 " Ptxt %p\n"
598 " str '%S'\n",
599 ba,
600 Ptxt,
601 str);
602 #endif /* defined(AJ_DEBUG) && AJ_DEBUG >= 1 */
603
604 return ensDatabaseadaptorEscapeC(
605 ensBaseadaptorGetDatabaseadaptor(ba),
606 Ptxt,
607 str);
608 }
609
610
611
612
613 /* @func ensBaseadaptorEscapeS ************************************************
614 **
615 ** Escape special characters in an AJAX String for use in an SQL statement,
616 ** taking into account the current character set of the AJAX SQL Connection
617 ** and return an AJAX String.
618 **
619 ** The caller is responsible for deleting the escaped AJAX String.
620 **
621 ** @param [u] ba [EnsPBaseadaptor] Ensembl Base Adaptor
622 ** @param [wP] Pstr [AjPStr*] Address of the (new) SQL-escaped AJAX String
623 ** @param [r] str [const AjPStr] AJAX String to be escaped
624 **
625 ** @return [AjBool] ajTrue upon success, ajFalse otherwise
626 **
627 ** @release 6.2.0
628 ** @@
629 ******************************************************************************/
630
ensBaseadaptorEscapeS(EnsPBaseadaptor ba,AjPStr * Pstr,const AjPStr str)631 AjBool ensBaseadaptorEscapeS(EnsPBaseadaptor ba,
632 AjPStr *Pstr,
633 const AjPStr str)
634 {
635 #if defined(AJ_DEBUG) && AJ_DEBUG >= 1
636 if (ajDebugTest("ensBaseadaptorEscapeS"))
637 ajDebug("ensBaseadaptorEscapeS\n"
638 " ba %p\n"
639 " Pstr %p\n"
640 " str '%S'\n",
641 ba,
642 Pstr,
643 str);
644 #endif /* defined(AJ_DEBUG) && AJ_DEBUG >= 1 */
645
646 return ensDatabaseadaptorEscapeS(
647 ensBaseadaptorGetDatabaseadaptor(ba),
648 Pstr,
649 str);
650 }
651
652
653
654
655 /* @func ensBaseadaptorGetMultispecies ****************************************
656 **
657 ** Get the multiple-species member of the Ensembl Database Adaptor member
658 ** of an Ensembl Base Adaptor.
659 **
660 ** @cc Bio::EnsEMBL::DBSQL::BaseAdaptor::is_multispecies
661 ** @param [r] ba [const EnsPBaseadaptor] Ensembl Base Adaptor
662 **
663 ** @return [AjBool] ajTrue if the database contains multiple species,
664 ** ajFalse otherwise
665 **
666 ** @release 6.4.0
667 ** @@
668 ******************************************************************************/
669
ensBaseadaptorGetMultispecies(const EnsPBaseadaptor ba)670 AjBool ensBaseadaptorGetMultispecies(const EnsPBaseadaptor ba)
671 {
672 return ensDatabaseadaptorGetMultispecies(
673 ensBaseadaptorGetDatabaseadaptor(ba));
674 }
675
676
677
678
679 /* @func ensBaseadaptorGetPrimarytable ****************************************
680 **
681 ** Get the primary SQL table name address of an Ensembl Base Adaptor.
682 ** The primary SQL table name is the first one in the SQL table name array.
683 **
684 ** @param [r] ba [const EnsPBaseadaptor] Ensembl Base Adaptor
685 **
686 ** @return [const char*] Primary SQL table name address or NULL
687 **
688 ** @release 6.4.0
689 ** @@
690 ******************************************************************************/
691
ensBaseadaptorGetPrimarytable(const EnsPBaseadaptor ba)692 const char* ensBaseadaptorGetPrimarytable(const EnsPBaseadaptor ba)
693 {
694 return (ba) ? ba->Tablenames[0] : NULL;
695 }
696
697
698
699
700 /* @func ensBaseadaptorGetSpeciesidentifier ***********************************
701 **
702 ** Get the species identifier member of the Ensembl Database Adaptor member
703 ** of an Ensembl Base Adaptor.
704 **
705 ** @cc Bio::EnsEMBL::DBSQL::BaseAdaptor::species_id
706 ** @param [r] ba [const EnsPBaseadaptor] Ensembl Base Adaptor
707 **
708 ** @return [ajuint] Ensembl species identifier or 0U, defaults to 1U
709 **
710 ** @release 6.4.0
711 ** @@
712 ******************************************************************************/
713
ensBaseadaptorGetSpeciesidentifier(const EnsPBaseadaptor ba)714 ajuint ensBaseadaptorGetSpeciesidentifier(const EnsPBaseadaptor ba)
715 {
716 return ensDatabaseadaptorGetIdentifier(
717 ensBaseadaptorGetDatabaseadaptor(ba));
718 }
719
720
721
722
723 /* @funcstatic baseadaptorFetchAllStatement ***********************************
724 **
725 ** Generic function to fetch Ensembl Objects via an Ensembl Base Adaptor.
726 **
727 ** The caller is responsible for deleting the Ensembl Objects before
728 ** deleting the AJAX List.
729 **
730 ** @cc Bio::EnsEMBL::DBSQL::BaseAdaptor::_generate_sql
731 ** @param [u] ba [EnsPBaseadaptor] Ensembl Base Adaptor
732 ** @param [rN] Pcolumnnames [const char* const*] SQL column name array
733 ** @param [rN] constraint [const AjPStr] SQL SELECT constraint
734 ** @param [u] Pstatement [AjPStr*] AJAX String (SQL statement) address
735 **
736 ** @return [AjBool] ajTrue upon success, ajFalse otherwise
737 **
738 ** @release 6.5.0
739 ** @@
740 ******************************************************************************/
741
baseadaptorFetchAllStatement(EnsPBaseadaptor ba,const char * const * Pcolumnnames,const AjPStr constraint,AjPStr * Pstatement)742 static AjBool baseadaptorFetchAllStatement(
743 EnsPBaseadaptor ba,
744 const char* const* Pcolumnnames,
745 const AjPStr constraint,
746 AjPStr *Pstatement)
747 {
748 const char *const *columnnamesrray = NULL;
749
750 register ajuint i = 0U;
751 register ajuint j = 0U;
752
753 AjBool debug = AJFALSE;
754 AjBool match = AJFALSE;
755
756 AjPStr columnnames = NULL;
757 AjPStr tablenames = NULL;
758 AjPStr joins = NULL;
759 AjPStr parentheses = NULL;
760
761 debug = ajDebugTest("baseadaptorFetchAllStatement");
762
763 if (debug)
764 ajDebug("baseadaptorFetchAllStatement\n"
765 " ba %p\n"
766 " Pcolumnnames %p\n"
767 " constraint '%S'\n"
768 " Pstatement %p\n",
769 ba,
770 Pcolumnnames,
771 constraint,
772 Pstatement);
773
774 if (!ba)
775 return ajFalse;
776
777 if (!Pstatement)
778 return ajFalse;
779
780 if (*Pstatement)
781 ajStrAssignClear(Pstatement);
782 else
783 *Pstatement = ajStrNew();
784
785 columnnames = ajStrNew();
786 tablenames = ajStrNew();
787 joins = ajStrNew();
788 parentheses = ajStrNew();
789
790 /* Build the column expression. */
791
792 columnnamesrray = (Pcolumnnames) ? Pcolumnnames : ba->Columnnames;
793
794 for (i = 0U; columnnamesrray[i]; i++)
795 ajFmtPrintAppS(&columnnames, "%s, ", columnnamesrray[i]);
796
797 /* Remove last comma and space from the column expression. */
798
799 ajStrCutEnd(&columnnames, 2);
800
801 /*
802 ** Build the SQL table expression.
803 ** Construct a LEFT JOIN statement if one was defined and subsequently,
804 ** remove the left-joined SQL table from the SQL table expression.
805 */
806
807 for (i = 0U; ba->Tablenames[i]; i++)
808 {
809 if (debug)
810 ajDebug("ensBaseadaptorFetchAllbyConstraint "
811 "array index %u "
812 "SQL table name '%s'\n",
813 i, ba->Tablenames[i]);
814
815 match = ajFalse;
816
817 if (ba->Leftjoins)
818 {
819 for (j = 0U; ba->Leftjoins[j].Tablename; j++)
820 {
821 if (ajCharMatchC(ba->Tablenames[i], ba->Leftjoins[j].Tablename))
822 {
823 ajStrAppendK(&parentheses, '(');
824
825 ajFmtPrintAppS(&joins,
826 "LEFT JOIN %s ON %s) ",
827 ba->Leftjoins[j].Tablename,
828 ba->Leftjoins[j].Condition);
829
830 match = ajTrue;
831
832 break;
833 }
834 }
835 }
836
837 if (!match)
838 ajFmtPrintAppS(&tablenames, "%s, ", ba->Tablenames[i]);
839 }
840
841 /* Remove last comma and space from the SQL table expression. */
842
843 ajStrCutEnd(&tablenames, 2);
844
845 /* Build the SQL statement. */
846
847 ajStrAssignC(Pstatement, "SELECT");
848
849 if (ba->Mysqlstraightjoin)
850 ajStrAppendC(Pstatement, " STRAIGHT_JOIN");
851
852 ajFmtPrintAppS(Pstatement, " %S FROM %S(%S)",
853 columnnames, parentheses, tablenames);
854
855 if (joins && ajStrGetLen(joins))
856 ajFmtPrintAppS(Pstatement, " %S", joins);
857
858 if (constraint && ajStrGetLen(constraint))
859 {
860 ajFmtPrintAppS(Pstatement, " WHERE %S", constraint);
861
862 if (ba->Defaultcondition)
863 ajFmtPrintAppS(Pstatement, " AND %s", ba->Defaultcondition);
864 }
865 else if (ba->Defaultcondition)
866 ajFmtPrintAppS(Pstatement, " WHERE %s", ba->Defaultcondition);
867
868 if (ba->Finalcondition)
869 ajFmtPrintAppS(Pstatement, " %s", ba->Finalcondition);
870
871 ajStrDel(&columnnames);
872 ajStrDel(&tablenames);
873 ajStrDel(&joins);
874 ajStrDel(&parentheses);
875
876 return ajTrue;
877 }
878
879
880
881
882 /* @section object count ******************************************************
883 **
884 ** Functions for counting Ensembl Objects in an Ensembl database.
885 **
886 ** @fdata [EnsPBaseadaptor]
887 **
888 ** @nam3rule Count Count Ensembl Object(s)
889 ** @nam4rule All Count all Ensembl Objects
890 ** @nam4rule Allby Count all Ensembl Objects matching a criterion
891 ** @nam5rule Constraint Count all Ensembl Objects by an SQL SELECT constraint
892 **
893 ** @argrule * ba [EnsPBaseadaptor] Ensembl Base Adaptor
894 ** @argrule AllbyConstraint constraint [const AjPStr] SQL SELECT constraint
895 ** @argrule * Pcount [ajuint*]
896 ** AJAX integer (Ensembl Object count) address
897 **
898 ** @valrule * [AjBool] ajTrue upon success, ajFalse otherwise
899 **
900 ** @fcategory use
901 ******************************************************************************/
902
903
904
905
906 /* @func ensBaseadaptorCountAll ***********************************************
907 **
908 ** Generic function to count all Ensembl Objects via an Ensembl Base Adaptor.
909 ** Please note that it is probably not a good idea to use this function on
910 ** very large SQL tables quite common in the Ensembl genome annotation system.
911 **
912 ** @cc Bio::EnsEMBL::DBSQL::BaseAdaptor::fetch_all
913 ** @param [u] ba [EnsPBaseadaptor] Ensembl Base Adaptor
914 ** @param [u] Pcount [ajuint*] AJAX integer (Ensembl Object count) address
915 **
916 ** @return [AjBool] ajTrue upon success, ajFalse otherwise
917 **
918 ** @release 6.5.0
919 ** @@
920 ******************************************************************************/
921
ensBaseadaptorCountAll(EnsPBaseadaptor ba,ajuint * Pcount)922 AjBool ensBaseadaptorCountAll(
923 EnsPBaseadaptor ba,
924 ajuint *Pcount)
925 {
926 return ensBaseadaptorCountAllbyConstraint(ba, (AjPStr) NULL, Pcount);
927 }
928
929
930
931
932 /* @func ensBaseadaptorCountAllbyConstraint ***********************************
933 **
934 ** Generic function to count all Ensembl Objects via an Ensembl Base Adaptor.
935 **
936 ** @cc Bio::EnsEMBL::DBSQL::BaseAdaptor::generic_count
937 ** @param [u] ba [EnsPBaseadaptor] Ensembl Base Adaptor
938 ** @param [rN] constraint [const AjPStr] Constraint (optional)
939 ** @param [u] Pcount [ajuint*] AJAX integer (Ensembl Object count) address
940 **
941 ** @return [AjBool] ajTrue upon success, ajFalse otherwise
942 **
943 ** @release 6.5.0
944 ** @@
945 ******************************************************************************/
946
ensBaseadaptorCountAllbyConstraint(EnsPBaseadaptor ba,const AjPStr constraint,ajuint * Pcount)947 AjBool ensBaseadaptorCountAllbyConstraint(
948 EnsPBaseadaptor ba,
949 const AjPStr constraint,
950 ajuint *Pcount)
951 {
952 const char *const Pcolumnnames[] =
953 {
954 "COUNT(*)",
955 (const char*) NULL
956 };
957
958 AjBool result = AJFALSE;
959
960 AjPSqlstatement sqls = NULL;
961 AjISqlrow sqli = NULL;
962 AjPSqlrow sqlr = NULL;
963
964 AjPStr statement = NULL;
965
966 EnsPDatabaseadaptor dba = NULL;
967
968 if (!ba)
969 return ajFalse;
970
971 if (!Pcount)
972 return ajFalse;
973
974 *Pcount = 0U;
975
976 statement = ajStrNew();
977
978 result = baseadaptorFetchAllStatement(
979 ba,
980 Pcolumnnames,
981 constraint,
982 &statement);
983
984 if (!result)
985 {
986 ajStrDel(&statement);
987 return ajFalse;
988 }
989
990 dba = ensBaseadaptorGetDatabaseadaptor(ba);
991
992 sqls = ensDatabaseadaptorSqlstatementNew(dba, statement);
993
994 sqli = ajSqlrowiterNew(sqls);
995
996 while (!ajSqlrowiterDone(sqli))
997 {
998 *Pcount = 0U;
999
1000 sqlr = ajSqlrowiterGet(sqli);
1001
1002 ajSqlcolumnToUint(sqlr, Pcount);
1003 }
1004
1005 ajSqlrowiterDel(&sqli);
1006
1007 ensDatabaseadaptorSqlstatementDel(dba, &sqls);
1008
1009 ajStrDel(&statement);
1010
1011 return result;
1012 }
1013
1014
1015
1016
1017 /* @section object retrieval **************************************************
1018 **
1019 ** Functions for fetching Ensembl Objects from an Ensembl database.
1020 **
1021 ** @fdata [EnsPBaseadaptor]
1022 **
1023 ** @nam3rule Fetch Fetch Ensembl Object(s)
1024 ** @nam4rule All Fetch all Ensembl Objects
1025 ** @nam4rule Allby Fetch all Ensembl Objects matching a criterion
1026 ** @nam5rule Constraint Fetch all Ensembl Objects by an SQL SELECT constraint
1027 ** @nam5rule Identifiers Fetch all by SQL database-internal identifier objects
1028 ** @nam4rule By Fetch one Ensembl Object matching a criterion
1029 ** @nam5rule Identifier Fetch by SQL database-internal identifier
1030 **
1031 ** @argrule * ba [EnsPBaseadaptor] Ensembl Base Adaptor
1032 ** @argrule All objects [AjPList] AJAX List of Ensembl Objects
1033 ** @argrule AllbyConstraint constraint [const AjPStr] SQL SELECT constraint
1034 ** @argrule AllbyConstraint am [EnsPAssemblymapper] Ensembl Assembly Mapper
1035 ** @argrule AllbyConstraint slice [EnsPSlice] Ensembl Slice
1036 ** @argrule AllbyConstraint objects [AjPList] AJAX List of Ensembl Objects
1037 ** @argrule AllbyIdentifiers slice [EnsPSlice] Ensembl Slice
1038 ** @argrule AllbyIdentifiers FobjectGetIdentifier [ajuint function]
1039 ** Get Ensembl Object Identifier function address
1040 ** @argrule AllbyIdentifiers objects [AjPTable]
1041 ** AJAX Table of AJAX unsigned integer key data (SQL database-internal
1042 ** identifier used in an SQL SELECT IN comparison function) and Ensembl Object
1043 ** value data
1044 ** @argrule Identifier identifier [ajuint] SQL database-internal identifier
1045 ** @argrule By Pobject [void**] Ensembl Object address
1046 **
1047 ** @valrule * [AjBool] ajTrue upon success, ajFalse otherwise
1048 **
1049 ** @fcategory use
1050 ******************************************************************************/
1051
1052
1053
1054
1055 /* @func ensBaseadaptorFetchAll ***********************************************
1056 **
1057 ** Generic function to fetch all Ensembl Objects via an Ensembl Base Adaptor.
1058 ** Please note that it is probably not a good idea to use this function on
1059 ** very large SQL tables quite common in the Ensembl genome annotation system.
1060 **
1061 ** @cc Bio::EnsEMBL::DBSQL::BaseAdaptor::fetch_all
1062 ** @param [u] ba [EnsPBaseadaptor] Ensembl Base Adaptor
1063 ** @param [u] objects [AjPList] AJAX List of Ensembl Objects
1064 **
1065 ** @return [AjBool] ajTrue upon success, ajFalse otherwise
1066 **
1067 ** @release 6.2.0
1068 ** @@
1069 ******************************************************************************/
1070
ensBaseadaptorFetchAll(EnsPBaseadaptor ba,AjPList objects)1071 AjBool ensBaseadaptorFetchAll(
1072 EnsPBaseadaptor ba,
1073 AjPList objects)
1074 {
1075 return ensBaseadaptorFetchAllbyConstraint(
1076 ba,
1077 (AjPStr) NULL,
1078 (EnsPAssemblymapper) NULL,
1079 (EnsPSlice) NULL,
1080 objects);
1081 }
1082
1083
1084
1085
1086 /* @func ensBaseadaptorFetchAllbyConstraint ***********************************
1087 **
1088 ** Generic function to fetch Ensembl Objects via an Ensembl Base Adaptor.
1089 **
1090 ** The caller is responsible for deleting the Ensembl Objects before
1091 ** deleting the AJAX List.
1092 **
1093 ** @cc Bio::EnsEMBL::DBSQL::BaseAdaptor::generic_fetch
1094 ** @param [u] ba [EnsPBaseadaptor] Ensembl Base Adaptor
1095 ** @param [rN] constraint [const AjPStr] SQL SELECT constraint
1096 ** @param [uN] am [EnsPAssemblymapper] Ensembl Assembly Mapper
1097 ** @param [uN] slice [EnsPSlice] Ensembl Slice
1098 ** @param [u] objects [AjPList] AJAX List to Ensembl Objects
1099 **
1100 ** @return [AjBool] ajTrue upon success, ajFalse otherwise
1101 **
1102 ** @release 6.4.0
1103 ** @@
1104 ******************************************************************************/
1105
ensBaseadaptorFetchAllbyConstraint(EnsPBaseadaptor ba,const AjPStr constraint,EnsPAssemblymapper am,EnsPSlice slice,AjPList objects)1106 AjBool ensBaseadaptorFetchAllbyConstraint(
1107 EnsPBaseadaptor ba,
1108 const AjPStr constraint,
1109 EnsPAssemblymapper am,
1110 EnsPSlice slice,
1111 AjPList objects)
1112 {
1113 AjBool debug = AJFALSE;
1114 AjBool result = AJFALSE;
1115
1116 AjPStr statement = NULL;
1117
1118 debug = ajDebugTest("ensBaseadaptorFetchAllbyConstraint");
1119
1120 if (debug)
1121 ajDebug("ensBaseadaptorFetchAllbyConstraint\n"
1122 " ba %p\n"
1123 " constraint '%S'\n"
1124 " am %p\n"
1125 " slice %p\n"
1126 " objects %p\n",
1127 ba,
1128 constraint,
1129 am,
1130 slice,
1131 objects);
1132
1133 if (!ba)
1134 return ajFalse;
1135
1136 if (!objects)
1137 return ajFalse;
1138
1139 statement = ajStrNew();
1140
1141 result = baseadaptorFetchAllStatement(
1142 ba,
1143 (const char *const *) NULL,
1144 constraint,
1145 &statement);
1146
1147 if (!result)
1148 {
1149 ajStrDel(&statement);
1150 return ajFalse;
1151 }
1152
1153 result = (*ba->Fstatement) (ba, statement, am, slice, objects);
1154
1155 ajStrDel(&statement);
1156
1157 return result;
1158 }
1159
1160
1161
1162
1163 /* @func ensBaseadaptorFetchAllbyIdentifiers **********************************
1164 **
1165 ** Generic function to fetch Ensembl Objects by an AJAX Table of
1166 ** AJAX unsigned integer (SQL database-internal identifier) key data objects
1167 ** via an Ensembl Base Adaptor.
1168 **
1169 ** @cc Bio::EnsEMBL::DBSQL::BaseAdaptor::fetch_all_by_dbID_list
1170 ** @param [u] ba [EnsPBaseadaptor] Ensembl Base Adaptor.
1171 **
1172 ** @param [uN] slice [EnsPSlice] Ensembl Slice
1173 ** @param [f] FobjectGetIdentifier [ajuint function]
1174 ** Get Ensembl Object Identifier function address
1175 ** @param [u] objects [AjPTable]
1176 ** AJAX Table of AJAX unsigned integer key data (SQL database-internal
1177 ** identifier used in an SQL SELECT IN comparison function) and Ensembl Object
1178 ** value data
1179 **
1180 ** @return [AjBool] ajTrue upon success, ajFalse otherwise
1181 **
1182 ** @release 6.4.0
1183 ** @@
1184 ******************************************************************************/
1185
ensBaseadaptorFetchAllbyIdentifiers(EnsPBaseadaptor ba,EnsPSlice slice,ajuint (* FobjectGetIdentifier)(const void * object),AjPTable objects)1186 AjBool ensBaseadaptorFetchAllbyIdentifiers(
1187 EnsPBaseadaptor ba,
1188 EnsPSlice slice,
1189 ajuint (*FobjectGetIdentifier) (const void *object),
1190 AjPTable objects)
1191 {
1192 void **keyarray = NULL;
1193
1194 register ajuint i = 0U;
1195
1196 AjBool debug = AJFALSE;
1197
1198 AjPList list = NULL;
1199
1200 AjPStr constraint = NULL;
1201 AjPStr csv = NULL;
1202
1203 debug = ajDebugTest("ensBaseadaptorFetchAllbyIdentifiers");
1204
1205 if (debug)
1206 {
1207 ajDebug("ensBaseadaptorFetchAllbyIdentifiers"
1208 " ba %p\n"
1209 " slice %p\n"
1210 " FobjectGetIdentifier %p\n"
1211 " objects %p\n",
1212 ba,
1213 slice,
1214 FobjectGetIdentifier,
1215 objects);
1216
1217 ajTableTrace(objects);
1218 }
1219
1220 if (!ba)
1221 return ajFalse;
1222
1223 if (!FobjectGetIdentifier)
1224 return ajFalse;
1225
1226 if (!objects)
1227 return ajFalse;
1228
1229 list = ajListNew();
1230
1231 csv = ajStrNew();
1232
1233 /*
1234 ** Large queries are split into smaller ones on the basis of the maximum
1235 ** number of identifier instances configured in the Ensembl Base Adaptor
1236 ** module.
1237 ** This ensures that MySQL is faster and the maximum query size is not
1238 ** exceeded.
1239 */
1240
1241 ajTableToarrayKeys(objects, &keyarray);
1242
1243 for (i = 0U; keyarray[i]; i++)
1244 {
1245 if (debug)
1246 ajDebug("ensBaseadaptorFetchAllbyIdentifiers identifier %u\n",
1247 *((ajuint *) keyarray[i]));
1248
1249 ajFmtPrintAppS(&csv, "%u, ", *((ajuint *) keyarray[i]));
1250
1251 /*
1252 ** Run the statement if the maximum chunk size is exceed or
1253 ** if there are no more array elements to process.
1254 */
1255
1256 if ((((i + 1U) % ensKBaseadaptorMaximumIdentifiers) == 0) ||
1257 (keyarray[i + 1U] == NULL))
1258 {
1259 /* Remove the last comma and space. */
1260
1261 ajStrCutEnd(&csv, 2);
1262
1263 if (ajStrGetLen(csv))
1264 {
1265 constraint = ajFmtStr("%s.%s_id IN (%S)",
1266 ba->Tablenames[0U],
1267 ba->Tablenames[0U],
1268 csv);
1269
1270 ensBaseadaptorFetchAllbyConstraint(
1271 ba,
1272 constraint,
1273 (EnsPAssemblymapper) NULL,
1274 slice,
1275 list);
1276
1277 ajStrDel(&constraint);
1278 }
1279
1280 ajStrAssignClear(&csv);
1281 }
1282 }
1283
1284 AJFREE(keyarray);
1285
1286 ajStrDel(&csv);
1287
1288 /* Move Ensembl Objects from the AJAX List to the AJAX Table. */
1289
1290 ensTableuintFromList(objects, FobjectGetIdentifier, list);
1291
1292 ajListFree(&list);
1293
1294 return ajTrue;
1295 }
1296
1297
1298
1299
1300 /* @func ensBaseadaptorFetchByIdentifier **************************************
1301 **
1302 ** Generic function to fetch an Ensembl Object by its SQL database-internal
1303 ** identifier via an Ensembl Base Adaptor.
1304 **
1305 ** @cc Bio::EnsEMBL::DBSQL::BaseAdaptor::fetch_by_dbID
1306 ** @param [u] ba [EnsPBaseadaptor] Ensembl Base Adaptor
1307 ** @param [r] identifier [ajuint] SQL database-internal identifier
1308 ** @param [wP] Pobject [void**] Ensembl Object address
1309 **
1310 ** @return [AjBool] ajTrue upon success, ajFalse otherwise
1311 **
1312 ** @release 6.2.0
1313 ** @@
1314 ******************************************************************************/
1315
ensBaseadaptorFetchByIdentifier(EnsPBaseadaptor ba,ajuint identifier,void ** Pobject)1316 AjBool ensBaseadaptorFetchByIdentifier(
1317 EnsPBaseadaptor ba,
1318 ajuint identifier,
1319 void **Pobject)
1320 {
1321 AjBool result = AJFALSE;
1322
1323 AjPList objects = NULL;
1324
1325 AjPStr constraint = NULL;
1326
1327 if (!ba)
1328 return ajFalse;
1329
1330 if (!identifier)
1331 return ajFalse;
1332
1333 if (!Pobject)
1334 return ajFalse;
1335
1336 if (!ba->Tablenames[0])
1337 return ajFalse;
1338
1339 *Pobject = NULL;
1340
1341 constraint = ajFmtStr(
1342 "%s.%s_id = %u",
1343 ba->Tablenames[0],
1344 ba->Tablenames[0],
1345 identifier);
1346
1347 objects = ajListNew();
1348
1349 result = ensBaseadaptorFetchAllbyConstraint(
1350 ba,
1351 constraint,
1352 (EnsPAssemblymapper) NULL,
1353 (EnsPSlice) NULL,
1354 objects);
1355
1356 if (ajListGetLength(objects) > 1)
1357 ajFatal("ensBaseadaptorFetchByIdentifier got more than one object "
1358 "for constraint '%S'.\n", constraint);
1359
1360 /*
1361 ** NOTE: Since an object-specific deletion function is not available,
1362 ** any additional objects lead to a memory leak.
1363 */
1364
1365 ajListPop(objects, Pobject);
1366
1367 ajListFree(&objects);
1368
1369 ajStrDel(&constraint);
1370
1371 return result;
1372 }
1373
1374
1375
1376
1377 /* @section accessory object retrieval ****************************************
1378 **
1379 ** Functions for retrieving objects releated to Ensembl Transcript objects
1380 ** from an Ensembl SQL database.
1381 **
1382 ** @fdata [EnsPBaseadaptor]
1383 **
1384 ** @nam3rule Retrieve Retrieve Ensembl Object-releated object(s)
1385 ** @nam4rule All Retrieve all Ensembl Object-releated objects
1386 ** @nam5rule Identifiers Retrieve all SQL database-internal identifier objects
1387 ** @nam5rule Strings Retrieve all AJAX String objects
1388 ** @nam4rule Feature Retrieve an Ensembl Feature
1389 **
1390 ** @argrule * ba [EnsPBaseadaptor] Ensembl Base Adaptor
1391 ** @argrule All tablename [const AjPStr] SQL table name
1392 ** @argrule All columnname [const AjPStr] SQL column name
1393 ** @argrule Identifiers identifiers [AjPList]
1394 ** AJAX List of AJAX unsigned integer objects
1395 ** @argrule Strings strings [AjPList]
1396 ** AJAX List of AJAX String objects
1397 ** @argrule Feature analysisid [ajuint] Ensembl Analysis identifier
1398 ** @argrule Feature srid [ajuint] Ensembl Sequence Region identifier
1399 ** @argrule Feature srstart [ajuint] Ensembl Sequence Region start
1400 ** @argrule Feature srend [ajuint] Ensembl Sequence Region end
1401 ** @argrule Feature srstrand [ajint] Ensembl Sequence Region strand
1402 ** @argrule Feature am [EnsPAssemblymapper] Ensembl Assembly Mapper
1403 ** @argrule Feature slice [EnsPSlice] Ensembl Slice
1404 ** @argrule Feature Pfeature [EnsPFeature*] Ensembl Feature
1405 **
1406 ** @valrule * [AjBool] ajTrue upon success, ajFalse otherwise
1407 **
1408 ** @fcategory use
1409 ******************************************************************************/
1410
1411
1412
1413
1414 /* @funcstatic baseadaptorRetrieveAllStatement ********************************
1415 **
1416 ** Helper function building a complete SQL statement for the generic retrieval
1417 ** of AJAX unsigned integer or AJAX String Ensembl Object identifiers via an
1418 ** Ensembl Base Adaptor.
1419 **
1420 ** If a SQL column name has not been provided, the primary key will be used,
1421 ** which by definition in Ensembl, is always the SQL table name suffixed
1422 ** with "_id".
1423 **
1424 ** The caller is responsible for deleting the AJAX String.
1425 **
1426 ** @cc Bio::EnsEMBL::DBSQL::BaseAdaptor::_list_dbIDs
1427 ** @param [u] ba [EnsPBaseadaptor] Ensembl Base Adaptor
1428 ** @param [r] tablename [const AjPStr] SQL table name
1429 ** @param [rN] columnname [const AjPStr] SQL column name
1430 ** @param [u] Pstatement [AjPStr*] AJAX String address
1431 **
1432 ** @return [AjBool] ajTrue upon success, ajFalse otherwise
1433 **
1434 ** @release 6.5.0
1435 ** @@
1436 ******************************************************************************/
1437
baseadaptorRetrieveAllStatement(EnsPBaseadaptor ba,const AjPStr tablename,const AjPStr columnname,AjPStr * Pstatement)1438 static AjBool baseadaptorRetrieveAllStatement(
1439 EnsPBaseadaptor ba,
1440 const AjPStr tablename,
1441 const AjPStr columnname,
1442 AjPStr *Pstatement)
1443 {
1444 if (!ba)
1445 return ajFalse;
1446
1447 if (!tablename)
1448 return ajFalse;
1449
1450 if (!Pstatement)
1451 return ajFalse;
1452
1453 if (*Pstatement)
1454 ajStrAssignClear(Pstatement);
1455 else
1456 *Pstatement = ajStrNew();
1457
1458 if (columnname && ajStrGetLen(columnname))
1459 ajFmtPrintAppS(Pstatement,
1460 "SELECT %S.%S FROM %S",
1461 tablename,
1462 columnname,
1463 tablename);
1464 else
1465 ajFmtPrintAppS(Pstatement,
1466 "SELECT %S.%S_id FROM %S",
1467 tablename,
1468 tablename,
1469 tablename);
1470
1471 return ajTrue;
1472 }
1473
1474
1475
1476
1477 /* @func ensBaseadaptorRetrieveAllIdentifiers *********************************
1478 **
1479 ** Generic function to retrieve SQL database-internal identifier objects of
1480 ** Ensembl Objects via an Ensembl Base Adaptor.
1481 **
1482 ** If a SQL column name has not been provided, the primary key will be used,
1483 ** which by definition in Ensembl, is always the SQL table name suffixed
1484 ** with "_id".
1485 **
1486 ** The caller is responsible for deleting the AJAX unsigned integer objects
1487 ** before deleting the AJAX List.
1488 **
1489 ** @cc Bio::EnsEMBL::DBSQL::BaseAdaptor::_list_dbIDs
1490 ** @param [u] ba [EnsPBaseadaptor] Ensembl Base Adaptor
1491 ** @param [r] tablename [const AjPStr] SQL table name
1492 ** @param [rN] columnname [const AjPStr] SQL column name
1493 ** @param [u] identifiers [AjPList] AJAX List of AJAX unsigned integer
1494 ** (SQL database-internal identifier) objects
1495 **
1496 ** @return [AjBool] ajTrue upon success, ajFalse otherwise
1497 **
1498 ** @release 6.4.0
1499 ** @@
1500 ** NOTE: The Perl API has an ordered parameter to this function, which
1501 ** appends an 'order by seq_region_id, seq_region_start' clause.
1502 ** A seq_region column, however, may not be part of the table definition,
1503 ** especially if this object does not inherit from Bio::EnsEMBL::Feature.
1504 ** This should probably move into the Bio::EnEMBL::DBSQL::BaseFeatureAdaptor,
1505 ** which always has a seq_region_id associated.
1506 ******************************************************************************/
1507
ensBaseadaptorRetrieveAllIdentifiers(EnsPBaseadaptor ba,const AjPStr tablename,const AjPStr columnname,AjPList identifiers)1508 AjBool ensBaseadaptorRetrieveAllIdentifiers(
1509 EnsPBaseadaptor ba,
1510 const AjPStr tablename,
1511 const AjPStr columnname,
1512 AjPList identifiers)
1513 {
1514 ajuint *Pidentifier = NULL;
1515
1516 AjPSqlstatement sqls = NULL;
1517 AjISqlrow sqli = NULL;
1518 AjPSqlrow sqlr = NULL;
1519
1520 AjPStr statement = NULL;
1521
1522 EnsPDatabaseadaptor dba = NULL;
1523
1524 if (!ba)
1525 return ajFalse;
1526
1527 if (!tablename)
1528 return ajFalse;
1529
1530 if (!identifiers)
1531 return ajFalse;
1532
1533 statement = ajStrNew();
1534
1535 baseadaptorRetrieveAllStatement(ba, tablename, columnname, &statement);
1536
1537 dba = ensBaseadaptorGetDatabaseadaptor(ba);
1538
1539 sqls = ensDatabaseadaptorSqlstatementNew(dba, statement);
1540
1541 sqli = ajSqlrowiterNew(sqls);
1542
1543 while (!ajSqlrowiterDone(sqli))
1544 {
1545 AJNEW0(Pidentifier);
1546
1547 sqlr = ajSqlrowiterGet(sqli);
1548
1549 ajSqlcolumnToUint(sqlr, Pidentifier);
1550
1551 ajListPushAppend(identifiers, (void *) Pidentifier);
1552 }
1553
1554 ajSqlrowiterDel(&sqli);
1555
1556 ensDatabaseadaptorSqlstatementDel(dba, &sqls);
1557
1558 ajStrDel(&statement);
1559
1560 return ajTrue;
1561 }
1562
1563
1564
1565
1566 /* @func ensBaseadaptorRetrieveAllStrings *************************************
1567 **
1568 ** Generic function to retrieve SQL database-internal AJAX String objects of
1569 ** Ensembl Objects via an Ensembl Base Adaptor.
1570 **
1571 ** If a SQL column name has not been provided, the primary key will be used,
1572 ** which by definition in Ensembl, is always the SQL table name suffixed
1573 ** with "_id".
1574 **
1575 ** The caller is responsible for deleting the AJAX String objects before
1576 ** deleting the AJAX List.
1577 **
1578 ** @cc Bio::EnsEMBL::DBSQL::BaseAdaptor::_list_dbIDs
1579 ** @param [u] ba [EnsPBaseadaptor] Ensembl Base Adaptor
1580 ** @param [r] tablename [const AjPStr] SQL table name
1581 ** @param [rN] columnname [const AjPStr] SQL column name
1582 ** @param [u] strings [AjPList]
1583 ** AJAX List of AJAX String (SQL database-internal string) objects
1584 **
1585 ** @return [AjBool] ajTrue upon success, ajFalse otherwise
1586 **
1587 ** @release 6.4.0
1588 ** @@
1589 ** NOTE: The Perl API has an ordered parameter to this function, which
1590 ** appends an 'order by seq_region_id, seq_region_start' clause.
1591 ** A seq_region column, however, may not be part of the table definition,
1592 ** especially if this object does not inherit from Bio::EnsEMBL::Feature.
1593 ** This should probably move into the Bio::EnEMBL::DBSQL::BaseFeatureAdaptor,
1594 ** which always has a seq_region_id associated.
1595 ******************************************************************************/
1596
ensBaseadaptorRetrieveAllStrings(EnsPBaseadaptor ba,const AjPStr tablename,const AjPStr columnname,AjPList strings)1597 AjBool ensBaseadaptorRetrieveAllStrings(
1598 EnsPBaseadaptor ba,
1599 const AjPStr tablename,
1600 const AjPStr columnname,
1601 AjPList strings)
1602 {
1603 AjPSqlstatement sqls = NULL;
1604 AjISqlrow sqli = NULL;
1605 AjPSqlrow sqlr = NULL;
1606
1607 AjPStr statement = NULL;
1608 AjPStr string = NULL;
1609
1610 EnsPDatabaseadaptor dba = NULL;
1611
1612 if (!ba)
1613 return ajFalse;
1614
1615 if (!tablename)
1616 return ajFalse;
1617
1618 if (!strings)
1619 return ajFalse;
1620
1621 statement = ajStrNew();
1622
1623 baseadaptorRetrieveAllStatement(ba, tablename, columnname, &statement);
1624
1625 dba = ensBaseadaptorGetDatabaseadaptor(ba);
1626
1627 sqls = ensDatabaseadaptorSqlstatementNew(dba, statement);
1628
1629 sqli = ajSqlrowiterNew(sqls);
1630
1631 while (!ajSqlrowiterDone(sqli))
1632 {
1633 string = ajStrNew();
1634
1635 sqlr = ajSqlrowiterGet(sqli);
1636
1637 ajSqlcolumnToStr(sqlr, &string);
1638
1639 ajListPushAppend(strings, (void *) string);
1640 }
1641
1642 ajSqlrowiterDel(&sqli);
1643
1644 ensDatabaseadaptorSqlstatementDel(dba, &sqls);
1645
1646 ajStrDel(&statement);
1647
1648 return ajTrue;
1649 }
1650
1651
1652
1653
1654 /* @func ensBaseadaptorRetrieveFeature ****************************************
1655 **
1656 ** Maps Ensembl Sequence Region coordinates for Ensembl Feature objects into
1657 ** Ensembl Slice coordinates and returns an Ensembl Feature object.
1658 **
1659 ** The caller is responsible for deleting the Ensembl Feature.
1660 ** This function aims to simplify all private
1661 ** objectadaptorFetchAllByStatement functions.
1662 **
1663 ** @param [u] ba [EnsPBaseadaptor] Ensembl Base Adaptor
1664 ** @param [r] analysisid [ajuint] Ensembl Analysis identifier
1665 ** @param [r] srid [ajuint] Ensembl Sequence Region identifier
1666 ** @param [r] srstart [ajuint] Ensembl Sequence Region start
1667 ** @param [r] srend [ajuint] Ensembl Sequence Region end
1668 ** @param [r] srstrand [ajint] Ensembl Sequence Region strand
1669 ** @param [uN] am [EnsPAssemblymapper] Ensembl Assembly Mapper
1670 ** @param [uN] slice [EnsPSlice] Ensembl Slice
1671 ** @param [u] Pfeature [EnsPFeature*] Ensembl Feature
1672 **
1673 ** @return [AjBool] ajTrue upon success, ajFalse otherwise
1674 ** @@
1675 ******************************************************************************/
1676
ensBaseadaptorRetrieveFeature(EnsPBaseadaptor ba,ajuint analysisid,ajuint srid,ajuint srstart,ajuint srend,ajint srstrand,EnsPAssemblymapper am,EnsPSlice slice,EnsPFeature * Pfeature)1677 AjBool ensBaseadaptorRetrieveFeature(
1678 EnsPBaseadaptor ba,
1679 ajuint analysisid,
1680 ajuint srid,
1681 ajuint srstart,
1682 ajuint srend,
1683 ajint srstrand,
1684 EnsPAssemblymapper am,
1685 EnsPSlice slice,
1686 EnsPFeature *Pfeature)
1687 {
1688 ajint slstart = 0;
1689 ajint slend = 0;
1690 ajint slstrand = 0;
1691 ajint sllength = 0;
1692 ajint tmpstart = 0;
1693
1694 AjBool circular = AJFALSE;
1695
1696 AjPList mrs = NULL;
1697
1698 EnsPAnalysis analysis = NULL;
1699 EnsPAnalysisadaptor ana = NULL;
1700
1701 EnsPAssemblymapperadaptor ama = NULL;
1702
1703 EnsPCoordsystemadaptor csa = NULL;
1704
1705 EnsPDatabaseadaptor dba = NULL;
1706
1707 EnsPMapperresult mr = NULL;
1708
1709 EnsPSlice srslice = NULL;
1710 EnsPSliceadaptor sla = NULL;
1711
1712 /* Presult has to be the first! */
1713
1714 if (Pfeature)
1715 *Pfeature = NULL;
1716 else
1717 return ajFalse;
1718
1719 if (!ba)
1720 return ajFalse;
1721
1722 dba = ensBaseadaptorGetDatabaseadaptor(ba);
1723
1724 ana = ensRegistryGetAnalysisadaptor(dba);
1725 ama = ensRegistryGetAssemblymapperadaptor(dba);
1726 csa = ensRegistryGetCoordsystemadaptor(dba);
1727 sla = (slice) ? ensSliceGetAdaptor(slice) : ensRegistryGetSliceadaptor(dba);
1728
1729 /* Need to get the internal Ensembl Sequence Region identifier. */
1730
1731 srid = ensCoordsystemadaptorGetSeqregionidentifierInternal(csa, srid);
1732
1733 /*
1734 ** Since the Ensembl SQL schema defines Sequence Region start and end
1735 ** coordinates as unsigned integers for all Ensembl Feature objects,
1736 ** the range needs checking.
1737 */
1738
1739 if (srstart <= INT_MAX)
1740 slstart = (ajint) srstart;
1741 else
1742 ajFatal("ensBaseadaptorRetrieveFeature got an Ensembl "
1743 "Sequence Region start coordinate (%u) outside the "
1744 "maximum integer limit (%d).",
1745 srstart, INT_MAX);
1746
1747 if (srend <= INT_MAX)
1748 slend = (ajint) srend;
1749 else
1750 ajFatal("ensBaseadaptorRetrieveFeature got an Ensembl "
1751 "Sequence Region end coordinate (%u) outside the "
1752 "maximum integer limit (%d).",
1753 srend, INT_MAX);
1754
1755 slstrand = srstrand;
1756
1757 /* Fetch a Slice spanning the entire Sequence Region. */
1758
1759 ensSliceadaptorFetchBySeqregionIdentifier(sla, srid, 0, 0, 0, &srslice);
1760
1761 /*
1762 ** Increase the reference counter of the Ensembl Assembly Mapper if
1763 ** one has been specified, otherwise fetch it from the database if a
1764 ** destination Slice has been specified.
1765 */
1766
1767 if (am)
1768 am = ensAssemblymapperNewRef(am);
1769 else if (slice && (!ensCoordsystemMatch(
1770 ensSliceGetCoordsystemObject(slice),
1771 ensSliceGetCoordsystemObject(srslice))))
1772 ensAssemblymapperadaptorFetchBySlices(ama, slice, srslice, &am);
1773
1774 /*
1775 ** Remap the Ensembl Feature coordinates to another
1776 ** Ensembl Coordinate System, if an Ensembl Assembly Mapper is defined
1777 ** at this point.
1778 */
1779
1780 if (am)
1781 {
1782 mrs = ajListNew();
1783
1784 ensAssemblymapperMapToSeqregion(am,
1785 ensSliceGetSeqregion(srslice),
1786 slstart,
1787 slend,
1788 slstrand,
1789 ensSliceGetSeqregion(slice),
1790 ajTrue, /* fastmap mode */
1791 mrs);
1792
1793 /*
1794 ** The ensAssemblymapperMapToSeqregion function in fastmap mode
1795 ** returns at best one Ensembl Mapper Result.
1796 */
1797
1798 ajListPeekFirst(mrs, (void **) &mr);
1799
1800 /*
1801 ** Skip Features that map to gaps or
1802 ** Coordinate System boundaries.
1803 */
1804
1805 if (ensMapperresultGetType(mr) != ensEMapperresultTypeCoordinate)
1806 {
1807 /* This Ensembl Feature could not be mapped successfully. */
1808
1809 while (ajListPop(mrs, (void **) &mr))
1810 ensMapperresultDel(&mr);
1811
1812 ajListFree(&mrs);
1813
1814 ensAssemblymapperDel(&am);
1815
1816 ensSliceDel(&srslice);
1817
1818 return ajTrue;
1819 }
1820
1821 srid = ensMapperresultGetObjectidentifier(mr);
1822 slstart = ensMapperresultGetCoordinateStart(mr);
1823 slend = ensMapperresultGetCoordinateEnd(mr);
1824 slstrand = ensMapperresultGetCoordinateStrand(mr);
1825
1826 /*
1827 ** Replace the original Sequence Region Slice by a Slice in the
1828 ** Coordinate System just mapped to.
1829 */
1830
1831 ensSliceDel(&srslice);
1832
1833 ensSliceadaptorFetchBySeqregionIdentifier(sla,
1834 srid,
1835 0,
1836 0,
1837 0,
1838 &srslice);
1839
1840 while (ajListPop(mrs, (void **) &mr))
1841 ensMapperresultDel(&mr);
1842
1843 ajListFree(&mrs);
1844 }
1845
1846 ensAssemblymapperDel(&am);
1847
1848 /*
1849 ** Convert Sequence Region Slice coordinates to destination Slice
1850 ** coordinates, if a destination Slice has been provided.
1851 */
1852
1853 if (slice)
1854 {
1855 /* Check that the length of the Slice is within range. */
1856
1857 if (ensSliceCalculateLength(slice) <= INT_MAX)
1858 sllength = (ajint) ensSliceCalculateLength(slice);
1859 else
1860 ajFatal("ensBaseadaptorRetrieveFeature got an Ensembl Slice, "
1861 "which length (%u) exceeds the "
1862 "maximum integer limit (%d).",
1863 ensSliceCalculateLength(slice), INT_MAX);
1864
1865 if (!ensSliceIsCircular(slice, &circular))
1866 return ajFalse;
1867
1868 if (ensSliceGetStrand(slice) >= 0)
1869 {
1870 /* On the positive strand ... */
1871
1872 slstart = slstart - ensSliceGetStart(slice) + 1;
1873 slend = slend - ensSliceGetStart(slice) + 1;
1874
1875 if (
1876 (
1877 (slend > ensSliceGetStart(slice))
1878 ||
1879 (slend < 0)
1880 ||
1881 (
1882 (ensSliceGetStart(slice) > ensSliceGetEnd(slice))
1883 &&
1884 (slend < 0)
1885 )
1886 )
1887 &&
1888 (circular == ajTrue)
1889 )
1890 {
1891 if (slstart > slend)
1892 {
1893 /* A Feature overlapping the chromsome origin. */
1894
1895 /* Region in the beginning of the chromosome. */
1896 if (slend > ensSliceGetStart(slice))
1897 slstart -= sllength;
1898
1899 if (slend < 0)
1900 slend += sllength;
1901 }
1902 else
1903 {
1904 if ((ensSliceGetStart(slice) > ensSliceGetEnd(slice))
1905 && (slend < 0))
1906 {
1907 /*
1908 ** A region overlapping the chromosome origin
1909 ** and a Feature, which is at the beginning of
1910 ** the chromosome.
1911 */
1912
1913 slstart += sllength;
1914 slend += sllength;
1915 }
1916 }
1917 }
1918 }
1919 else
1920 {
1921 /* On the negative strand ... */
1922
1923 if ((slstart > slend) && (circular == ajTrue))
1924 {
1925 /* Handle circular chromosomes. */
1926
1927 if (ensSliceGetStart(slice) > ensSliceGetEnd(slice))
1928 {
1929 tmpstart = slstart;
1930 slstart = ensSliceGetEnd(slice) - slend + 1;
1931 slend = ensSliceGetEnd(slice) + sllength - tmpstart + 1;
1932 }
1933 else
1934 {
1935 if (slend > ensSliceGetStart(slice))
1936 {
1937 /*
1938 ** Looking at the region in the beginning of the
1939 ** chromosome.
1940 */
1941
1942 slstart = ensSliceGetEnd(slice) - slend + 1;
1943 slend = slend - sllength - slstart + 1;
1944 }
1945 else
1946 {
1947 tmpstart = slstart;
1948 slstart = ensSliceGetEnd(slice) - slend - sllength + 1;
1949 slend = slend - tmpstart + 1;
1950 }
1951 }
1952 }
1953 else
1954 {
1955 /* Non-circular Ensembl Slice objects... */
1956
1957 slend = ensSliceGetEnd(slice) - slstart + 1;
1958 slstart = ensSliceGetEnd(slice) - slend + 1;
1959 }
1960
1961 slstrand *= -1;
1962 }
1963
1964 /*
1965 ** Throw away Features off the end of the requested Slice or on
1966 ** any other than the requested Slice.
1967 */
1968
1969 if ((slend < 1) ||
1970 (slstart > sllength) ||
1971 (srid != ensSliceGetSeqregionIdentifier(slice)))
1972 {
1973 /* This Ensembl Feature could not be mapped successfully. */
1974
1975 ensSliceDel(&srslice);
1976
1977 return ajTrue;
1978 }
1979
1980 /* Delete the Sequence Region Slice and set the requested Slice. */
1981
1982 ensSliceDel(&srslice);
1983
1984 srslice = ensSliceNewRef(slice);
1985 }
1986
1987 if (analysisid)
1988 ensAnalysisadaptorFetchByIdentifier(ana, analysisid, &analysis);
1989
1990 *Pfeature = ensFeatureNewIniS(analysis, srslice, slstart, slend, slstrand);
1991
1992 ensAnalysisDel(&analysis);
1993
1994 ensSliceDel(&srslice);
1995
1996 return ajTrue;
1997 }
1998