DB.pm 64 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376
  1. # -*- Mode: perl; indent-tabs-mode: nil -*-
  2. #
  3. # The contents of this file are subject to the Mozilla Public
  4. # License Version 1.1 (the "License"); you may not use this file
  5. # except in compliance with the License. You may obtain a copy of
  6. # the License at http://www.mozilla.org/MPL/
  7. #
  8. # Software distributed under the License is distributed on an "AS
  9. # IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
  10. # implied. See the License for the specific language governing
  11. # rights and limitations under the License.
  12. #
  13. # The Original Code is the Bugzilla Bug Tracking System.
  14. #
  15. # The Initial Developer of the Original Code is Netscape Communications
  16. # Corporation. Portions created by Netscape are
  17. # Copyright (C) 1998 Netscape Communications Corporation. All
  18. # Rights Reserved.
  19. #
  20. # Contributor(s): Terry Weissman <terry@mozilla.org>
  21. # Dan Mosedale <dmose@mozilla.org>
  22. # Jacob Steenhagen <jake@bugzilla.org>
  23. # Bradley Baetz <bbaetz@student.usyd.edu.au>
  24. # Christopher Aillon <christopher@aillon.com>
  25. # Tomas Kopal <Tomas.Kopal@altap.cz>
  26. # Max Kanat-Alexander <mkanat@bugzilla.org>
  27. # Lance Larsh <lance.larsh@oracle.com>
  28. package Bugzilla::DB;
  29. use strict;
  30. use DBI;
  31. # Inherit the DB class from DBI::db.
  32. use base qw(DBI::db);
  33. use Bugzilla::Constants;
  34. use Bugzilla::Install::Requirements;
  35. use Bugzilla::Install::Util qw(vers_cmp);
  36. use Bugzilla::Install::Localconfig;
  37. use Bugzilla::Util;
  38. use Bugzilla::Error;
  39. use Bugzilla::DB::Schema;
  40. use List::Util qw(max);
  41. use Storable qw(dclone);
  42. #####################################################################
  43. # Constants
  44. #####################################################################
  45. use constant BLOB_TYPE => DBI::SQL_BLOB;
  46. use constant ISOLATION_LEVEL => 'REPEATABLE READ';
  47. use constant GROUPBY_REGEXP => '(?:.*\s+AS\s+)?(\w+(\.\w+)?)(?:\s+(ASC|DESC))?$';
  48. # Set default values for what used to be the enum types. These values
  49. # are no longer stored in localconfig. If we are upgrading from a
  50. # Bugzilla with enums to a Bugzilla without enums, we use the
  51. # enum values.
  52. #
  53. # The values that you see here are ONLY DEFAULTS. They are only used
  54. # the FIRST time you run checksetup.pl, IF you are NOT upgrading from a
  55. # Bugzilla with enums. After that, they are either controlled through
  56. # the Bugzilla UI or through the DB.
  57. use constant ENUM_DEFAULTS => {
  58. bug_severity => ['blocker', 'critical', 'major', 'normal',
  59. 'minor', 'trivial', 'enhancement'],
  60. priority => ["P1","P2","P3","P4","P5"],
  61. op_sys => ["All","Windows","Mac OS","Linux","Other"],
  62. rep_platform => ["All","PC","Macintosh","Other"],
  63. bug_status => ["UNCONFIRMED","NEW","ASSIGNED","REOPENED","RESOLVED",
  64. "VERIFIED","CLOSED"],
  65. resolution => ["","FIXED","INVALID","WONTFIX", "DUPLICATE","WORKSFORME",
  66. "MOVED"],
  67. };
  68. #####################################################################
  69. # Connection Methods
  70. #####################################################################
  71. sub connect_shadow {
  72. my $params = Bugzilla->params;
  73. die "Tried to connect to non-existent shadowdb"
  74. unless $params->{'shadowdb'};
  75. my $lc = Bugzilla->localconfig;
  76. return _connect($lc->{db_driver}, $params->{"shadowdbhost"},
  77. $params->{'shadowdb'}, $params->{"shadowdbport"},
  78. $params->{"shadowdbsock"}, $lc->{db_user}, $lc->{db_pass});
  79. }
  80. sub connect_main {
  81. my $lc = Bugzilla->localconfig;
  82. return _connect($lc->{db_driver}, $lc->{db_host}, $lc->{db_name}, $lc->{db_port},
  83. $lc->{db_sock}, $lc->{db_user}, $lc->{db_pass});
  84. }
  85. sub _connect {
  86. my ($driver, $host, $dbname, $port, $sock, $user, $pass) = @_;
  87. my $pkg_module = DB_MODULE->{lc($driver)}->{db};
  88. # do the actual import
  89. eval ("require $pkg_module")
  90. || die ("'$driver' is not a valid choice for \$db_driver in "
  91. . " localconfig: " . $@);
  92. # instantiate the correct DB specific module
  93. my $dbh = $pkg_module->new($user, $pass, $host, $dbname, $port, $sock);
  94. return $dbh;
  95. }
  96. sub _handle_error {
  97. require Carp;
  98. # Cut down the error string to a reasonable size
  99. $_[0] = substr($_[0], 0, 2000) . ' ... ' . substr($_[0], -2000)
  100. if length($_[0]) > 4000;
  101. $_[0] = Carp::longmess($_[0]);
  102. return 0; # Now let DBI handle raising the error
  103. }
  104. sub bz_check_requirements {
  105. my ($output) = @_;
  106. my $lc = Bugzilla->localconfig;
  107. my $db = DB_MODULE->{lc($lc->{db_driver})};
  108. # Only certain values are allowed for $db_driver.
  109. if (!defined $db) {
  110. die "$lc->{db_driver} is not a valid choice for \$db_driver in"
  111. . bz_locations()->{'localconfig'};
  112. }
  113. die("It is not safe to run Bugzilla inside the 'mysql' database.\n"
  114. . "Please pick a different value for \$db_name in localconfig.")
  115. if $lc->{db_name} eq 'mysql';
  116. # Check the existence and version of the DBD that we need.
  117. my $dbd = $db->{dbd};
  118. my $sql_server = $db->{name};
  119. my $sql_want = $db->{db_version};
  120. unless (have_vers($dbd, $output)) {
  121. my $command = install_command($dbd);
  122. my $root = ROOT_USER;
  123. my $dbd_mod = $dbd->{module};
  124. my $dbd_ver = $dbd->{version};
  125. my $version = $dbd_ver ? " $dbd_ver or higher" : '';
  126. print <<EOT;
  127. For $sql_server, Bugzilla requires that perl's $dbd_mod $dbd_ver or later be
  128. installed. To install this module, run the following command (as $root):
  129. $command
  130. EOT
  131. exit;
  132. }
  133. # We don't try to connect to the actual database if $db_check is
  134. # disabled.
  135. unless ($lc->{db_check}) {
  136. print "\n" if $output;
  137. return;
  138. }
  139. # And now check the version of the database server itself.
  140. my $dbh = _get_no_db_connection();
  141. printf("Checking for %15s %-9s ", $sql_server, "(v$sql_want)")
  142. if $output;
  143. my $sql_vers = $dbh->bz_server_version;
  144. $dbh->disconnect;
  145. # Check what version of the database server is installed and let
  146. # the user know if the version is too old to be used with Bugzilla.
  147. if ( vers_cmp($sql_vers,$sql_want) > -1 ) {
  148. print "ok: found v$sql_vers\n" if $output;
  149. } else {
  150. print <<EOT;
  151. Your $sql_server v$sql_vers is too old. Bugzilla requires version
  152. $sql_want or later of $sql_server. Please download and install a
  153. newer version.
  154. EOT
  155. exit;
  156. }
  157. print "\n" if $output;
  158. }
  159. # Note that this function requires that localconfig exist and
  160. # be valid.
  161. sub bz_create_database {
  162. my $dbh;
  163. # See if we can connect to the actual Bugzilla database.
  164. my $conn_success = eval { $dbh = connect_main(); };
  165. my $db_name = Bugzilla->localconfig->{db_name};
  166. if (!$conn_success) {
  167. $dbh = _get_no_db_connection();
  168. print "Creating database $db_name...\n";
  169. # Try to create the DB, and if we fail print a friendly error.
  170. my $success = eval {
  171. my @sql = $dbh->_bz_schema->get_create_database_sql($db_name);
  172. # This ends with 1 because this particular do doesn't always
  173. # return something.
  174. $dbh->do($_) foreach @sql; 1;
  175. };
  176. if (!$success) {
  177. my $error = $dbh->errstr || $@;
  178. chomp($error);
  179. print STDERR "The '$db_name' database could not be created.",
  180. " The error returned was:\n\n $error\n\n",
  181. _bz_connect_error_reasons();
  182. exit;
  183. }
  184. }
  185. $dbh->disconnect;
  186. }
  187. # A helper for bz_create_database and bz_check_requirements.
  188. sub _get_no_db_connection {
  189. my ($sql_server) = @_;
  190. my $dbh;
  191. my $lc = Bugzilla->localconfig;
  192. my $conn_success = eval {
  193. $dbh = _connect($lc->{db_driver}, $lc->{db_host}, '', $lc->{db_port},
  194. $lc->{db_sock}, $lc->{db_user}, $lc->{db_pass});
  195. };
  196. if (!$conn_success) {
  197. my $sql_server = DB_MODULE->{lc($lc->{db_driver})}->{name};
  198. # Can't use $dbh->errstr because $dbh is undef.
  199. my $error = $DBI::errstr || $@;
  200. chomp($error);
  201. print STDERR "There was an error connecting to $sql_server:\n\n",
  202. " $error\n\n", _bz_connect_error_reasons();
  203. exit;
  204. }
  205. return $dbh;
  206. }
  207. # Just a helper because we have to re-use this text.
  208. # We don't use this in db_new because it gives away the database
  209. # username, and db_new errors can show up on CGIs.
  210. sub _bz_connect_error_reasons {
  211. my $lc_file = bz_locations()->{'localconfig'};
  212. my $lc = Bugzilla->localconfig;
  213. my $db = DB_MODULE->{lc($lc->{db_driver})};
  214. my $server = $db->{name};
  215. return <<EOT;
  216. This might have several reasons:
  217. * $server is not running.
  218. * $server is running, but there is a problem either in the
  219. server configuration or the database access rights. Read the Bugzilla
  220. Guide in the doc directory. The section about database configuration
  221. should help.
  222. * Your password for the '$lc->{db_user}' user, specified in \$db_pass, is
  223. incorrect, in '$lc_file'.
  224. * There is a subtle problem with Perl, DBI, or $server. Make
  225. sure all settings in '$lc_file' are correct. If all else fails, set
  226. '\$db_check' to 0.
  227. EOT
  228. }
  229. # List of abstract methods we are checking the derived class implements
  230. our @_abstract_methods = qw(REQUIRED_VERSION PROGRAM_NAME DBD_VERSION
  231. new sql_regexp sql_not_regexp sql_limit sql_to_days
  232. sql_date_format sql_interval);
  233. # This overridden import method will check implementation of inherited classes
  234. # for missing implementation of abstract methods
  235. # See http://perlmonks.thepen.com/44265.html
  236. sub import {
  237. my $pkg = shift;
  238. # do not check this module
  239. if ($pkg ne __PACKAGE__) {
  240. # make sure all abstract methods are implemented
  241. foreach my $meth (@_abstract_methods) {
  242. $pkg->can($meth)
  243. or croak("Class $pkg does not define method $meth");
  244. }
  245. }
  246. # Now we want to call our superclass implementation.
  247. # If our superclass is Exporter, which is using caller() to find
  248. # a namespace to populate, we need to adjust for this extra call.
  249. # All this can go when we stop using deprecated functions.
  250. my $is_exporter = $pkg->isa('Exporter');
  251. $Exporter::ExportLevel++ if $is_exporter;
  252. $pkg->SUPER::import(@_);
  253. $Exporter::ExportLevel-- if $is_exporter;
  254. }
  255. sub sql_istrcmp {
  256. my ($self, $left, $right, $op) = @_;
  257. $op ||= "=";
  258. return $self->sql_istring($left) . " $op " . $self->sql_istring($right);
  259. }
  260. sub sql_istring {
  261. my ($self, $string) = @_;
  262. return "LOWER($string)";
  263. }
  264. sub sql_iposition {
  265. my ($self, $fragment, $text) = @_;
  266. $fragment = $self->sql_istring($fragment);
  267. $text = $self->sql_istring($text);
  268. return $self->sql_position($fragment, $text);
  269. }
  270. sub sql_position {
  271. my ($self, $fragment, $text) = @_;
  272. return "POSITION($fragment IN $text)";
  273. }
  274. sub sql_group_by {
  275. my ($self, $needed_columns, $optional_columns) = @_;
  276. my $expression = "GROUP BY $needed_columns";
  277. $expression .= ", " . $optional_columns if $optional_columns;
  278. return $expression;
  279. }
  280. sub sql_string_concat {
  281. my ($self, @params) = @_;
  282. return '(' . join(' || ', @params) . ')';
  283. }
  284. sub sql_in {
  285. my ($self, $column_name, $in_list_ref) = @_;
  286. return " $column_name IN (" . join(',', @$in_list_ref) . ") ";
  287. }
  288. sub sql_fulltext_search {
  289. my ($self, $column, $text) = @_;
  290. # This is as close as we can get to doing full text search using
  291. # standard ANSI SQL, without real full text search support. DB specific
  292. # modules should override this, as this will be always much slower.
  293. # make the string lowercase to do case insensitive search
  294. my $lower_text = lc($text);
  295. # split the text we search for into separate words
  296. my @words = split(/\s+/, $lower_text);
  297. # surround the words with wildcards and SQL quotes so we can use them
  298. # in LIKE search clauses
  299. @words = map($self->quote("%$_%"), @words);
  300. # untaint words, since they are safe to use now that we've quoted them
  301. map(trick_taint($_), @words);
  302. # turn the words into a set of LIKE search clauses
  303. @words = map("LOWER($column) LIKE $_", @words);
  304. # search for occurrences of all specified words in the column
  305. return "CASE WHEN (" . join(" AND ", @words) . ") THEN 1 ELSE 0 END";
  306. }
  307. #####################################################################
  308. # General Info Methods
  309. #####################################################################
  310. # XXX - Needs to be documented.
  311. sub bz_server_version {
  312. my ($self) = @_;
  313. return $self->get_info(18); # SQL_DBMS_VER
  314. }
  315. sub bz_last_key {
  316. my ($self, $table, $column) = @_;
  317. return $self->last_insert_id(Bugzilla->localconfig->{db_name}, undef,
  318. $table, $column);
  319. }
  320. #####################################################################
  321. # Database Setup
  322. #####################################################################
  323. sub bz_setup_database {
  324. my ($self) = @_;
  325. # If we haven't ever stored a serialized schema,
  326. # set up the bz_schema table and store it.
  327. $self->_bz_init_schema_storage();
  328. my @desired_tables = $self->_bz_schema->get_table_list();
  329. foreach my $table_name (@desired_tables) {
  330. $self->bz_add_table($table_name);
  331. }
  332. }
  333. # This really just exists to get overridden in Bugzilla::DB::Mysql.
  334. sub bz_enum_initial_values {
  335. return ENUM_DEFAULTS;
  336. }
  337. sub bz_populate_enum_tables {
  338. my ($self) = @_;
  339. my $enum_values = $self->bz_enum_initial_values();
  340. while (my ($table, $values) = each %$enum_values) {
  341. $self->_bz_populate_enum_table($table, $values);
  342. }
  343. }
  344. sub bz_setup_foreign_keys {
  345. my ($self) = @_;
  346. # We use _bz_schema because bz_add_table has removed all REFERENCES
  347. # items from _bz_real_schema.
  348. my @tables = $self->_bz_schema->get_table_list();
  349. foreach my $table (@tables) {
  350. my @columns = $self->_bz_schema->get_table_columns($table);
  351. foreach my $column (@columns) {
  352. my $def = $self->_bz_schema->get_column_abstract($table, $column);
  353. if ($def->{REFERENCES}) {
  354. $self->bz_add_fk($table, $column, $def->{REFERENCES});
  355. }
  356. }
  357. }
  358. }
  359. # This is used by contrib/bzdbcopy.pl, mostly.
  360. sub bz_drop_foreign_keys {
  361. my ($self) = @_;
  362. my @tables = $self->_bz_real_schema->get_table_list();
  363. foreach my $table (@tables) {
  364. my @columns = $self->_bz_real_schema->get_table_columns($table);
  365. foreach my $column (@columns) {
  366. $self->bz_drop_fk($table, $column);
  367. }
  368. }
  369. }
  370. #####################################################################
  371. # Schema Modification Methods
  372. #####################################################################
  373. sub bz_add_column {
  374. my ($self, $table, $name, $new_def, $init_value) = @_;
  375. # You can't add a NOT NULL column to a table with
  376. # no DEFAULT statement, unless you have an init_value.
  377. # SERIAL types are an exception, though, because they can
  378. # auto-populate.
  379. if ( $new_def->{NOTNULL} && !exists $new_def->{DEFAULT}
  380. && !defined $init_value && $new_def->{TYPE} !~ /SERIAL/)
  381. {
  382. ThrowCodeError('column_not_null_without_default',
  383. { name => "$table.$name" });
  384. }
  385. my $current_def = $self->bz_column_info($table, $name);
  386. if (!$current_def) {
  387. my @statements = $self->_bz_real_schema->get_add_column_ddl(
  388. $table, $name, $new_def,
  389. defined $init_value ? $self->quote($init_value) : undef);
  390. print get_text('install_column_add',
  391. { column => $name, table => $table }) . "\n"
  392. if Bugzilla->usage_mode == USAGE_MODE_CMDLINE;
  393. foreach my $sql (@statements) {
  394. $self->do($sql);
  395. }
  396. $self->_bz_real_schema->set_column($table, $name, $new_def);
  397. $self->_bz_store_real_schema;
  398. }
  399. }
  400. sub bz_add_fk {
  401. my ($self, $table, $column, $def) = @_;
  402. my $col_def = $self->bz_column_info($table, $column);
  403. if (!$col_def->{REFERENCES}) {
  404. $self->_check_references($table, $column, $def->{TABLE},
  405. $def->{COLUMN});
  406. print get_text('install_fk_add',
  407. { table => $table, column => $column, fk => $def })
  408. . "\n" if Bugzilla->usage_mode == USAGE_MODE_CMDLINE;
  409. my @sql = $self->_bz_real_schema->get_add_fk_sql($table, $column, $def);
  410. $self->do($_) foreach @sql;
  411. $col_def->{REFERENCES} = $def;
  412. $self->_bz_real_schema->set_column($table, $column, $col_def);
  413. $self->_bz_store_real_schema;
  414. }
  415. }
  416. sub bz_alter_column {
  417. my ($self, $table, $name, $new_def, $set_nulls_to) = @_;
  418. my $current_def = $self->bz_column_info($table, $name);
  419. if (!$self->_bz_schema->columns_equal($current_def, $new_def)) {
  420. # You can't change a column to be NOT NULL if you have no DEFAULT
  421. # and no value for $set_nulls_to, if there are any NULL values
  422. # in that column.
  423. if ($new_def->{NOTNULL} &&
  424. !exists $new_def->{DEFAULT} && !defined $set_nulls_to)
  425. {
  426. # Check for NULLs
  427. my $any_nulls = $self->selectrow_array(
  428. "SELECT 1 FROM $table WHERE $name IS NULL");
  429. ThrowCodeError('column_not_null_no_default_alter',
  430. { name => "$table.$name" }) if ($any_nulls);
  431. }
  432. $self->bz_alter_column_raw($table, $name, $new_def, $current_def,
  433. $set_nulls_to);
  434. $self->_bz_real_schema->set_column($table, $name, $new_def);
  435. $self->_bz_store_real_schema;
  436. }
  437. }
  438. # bz_alter_column_raw($table, $name, $new_def, $current_def)
  439. #
  440. # Description: A helper function for bz_alter_column.
  441. # Alters a column in the database
  442. # without updating any Schema object. Generally
  443. # should only be called by bz_alter_column.
  444. # Used when either: (1) You don't yet have a Schema
  445. # object but you need to alter a column, for some reason.
  446. # (2) You need to alter a column for some database-specific
  447. # reason.
  448. # Params: $table - The name of the table the column is on.
  449. # $name - The name of the column you're changing.
  450. # $new_def - The abstract definition that you are changing
  451. # this column to.
  452. # $current_def - (optional) The current definition of the
  453. # column. Will be used in the output message,
  454. # if given.
  455. # $set_nulls_to - The same as the param of the same name
  456. # from bz_alter_column.
  457. # Returns: nothing
  458. #
  459. sub bz_alter_column_raw {
  460. my ($self, $table, $name, $new_def, $current_def, $set_nulls_to) = @_;
  461. my @statements = $self->_bz_real_schema->get_alter_column_ddl(
  462. $table, $name, $new_def,
  463. defined $set_nulls_to ? $self->quote($set_nulls_to) : undef);
  464. my $new_ddl = $self->_bz_schema->get_type_ddl($new_def);
  465. print "Updating column $name in table $table ...\n";
  466. if (defined $current_def) {
  467. my $old_ddl = $self->_bz_schema->get_type_ddl($current_def);
  468. print "Old: $old_ddl\n";
  469. }
  470. print "New: $new_ddl\n";
  471. $self->do($_) foreach (@statements);
  472. }
  473. sub bz_add_index {
  474. my ($self, $table, $name, $definition) = @_;
  475. my $index_exists = $self->bz_index_info($table, $name);
  476. if (!$index_exists) {
  477. $self->bz_add_index_raw($table, $name, $definition);
  478. $self->_bz_real_schema->set_index($table, $name, $definition);
  479. $self->_bz_store_real_schema;
  480. }
  481. }
  482. # bz_add_index_raw($table, $name, $silent)
  483. #
  484. # Description: A helper function for bz_add_index.
  485. # Adds an index to the database
  486. # without updating any Schema object. Generally
  487. # should only be called by bz_add_index.
  488. # Used when you don't yet have a Schema
  489. # object but you need to add an index, for some reason.
  490. # Params: $table - The name of the table the index is on.
  491. # $name - The name of the index you're adding.
  492. # $definition - The abstract index definition, in hashref
  493. # or arrayref format.
  494. # $silent - (optional) If specified and true, don't output
  495. # any message about this change.
  496. # Returns: nothing
  497. #
  498. sub bz_add_index_raw {
  499. my ($self, $table, $name, $definition, $silent) = @_;
  500. my @statements = $self->_bz_schema->get_add_index_ddl(
  501. $table, $name, $definition);
  502. print "Adding new index '$name' to the $table table ...\n" unless $silent;
  503. $self->do($_) foreach (@statements);
  504. }
  505. sub bz_add_table {
  506. my ($self, $name) = @_;
  507. my $table_exists = $self->bz_table_info($name);
  508. if (!$table_exists) {
  509. $self->_bz_add_table_raw($name);
  510. my $table_def = dclone($self->_bz_schema->get_table_abstract($name));
  511. my %fields = @{$table_def->{FIELDS}};
  512. foreach my $col (keys %fields) {
  513. # Foreign Key references have to be added by Install::DB after
  514. # initial table creation, because column names have changed
  515. # over history and it's impossible to keep track of that info
  516. # in ABSTRACT_SCHEMA.
  517. delete $fields{$col}->{REFERENCES};
  518. }
  519. $self->_bz_real_schema->add_table($name, $table_def);
  520. $self->_bz_store_real_schema;
  521. }
  522. }
  523. # _bz_add_table_raw($name) - Private
  524. #
  525. # Description: A helper function for bz_add_table.
  526. # Creates a table in the database without
  527. # updating any Schema object. Generally
  528. # should only be called by bz_add_table and by
  529. # _bz_init_schema_storage. Used when you don't
  530. # yet have a Schema object but you need to
  531. # add a table, for some reason.
  532. # Params: $name - The name of the table you're creating.
  533. # The definition for the table is pulled from
  534. # _bz_schema.
  535. # Returns: nothing
  536. #
  537. sub _bz_add_table_raw {
  538. my ($self, $name) = @_;
  539. my @statements = $self->_bz_schema->get_table_ddl($name);
  540. print "Adding new table $name ...\n" unless i_am_cgi();
  541. $self->do($_) foreach (@statements);
  542. }
  543. sub _bz_add_field_table {
  544. my ($self, $name, $schema_ref) = @_;
  545. # We do nothing if the table already exists.
  546. return if $self->bz_table_info($name);
  547. # Copy this so that we're not modifying the passed reference.
  548. # (This avoids modifying a constant in Bugzilla::DB::Schema.)
  549. my %table_schema = %$schema_ref;
  550. my %indexes = @{ $table_schema{INDEXES} };
  551. my %fixed_indexes;
  552. foreach my $key (keys %indexes) {
  553. $fixed_indexes{$name . "_" . $key} = $indexes{$key};
  554. }
  555. # INDEXES is supposed to be an arrayref, so we have to convert back.
  556. my @indexes_array = %fixed_indexes;
  557. $table_schema{INDEXES} = \@indexes_array;
  558. # We add this to the abstract schema so that bz_add_table can find it.
  559. $self->_bz_schema->add_table($name, \%table_schema);
  560. $self->bz_add_table($name);
  561. }
  562. sub bz_add_field_tables {
  563. my ($self, $field) = @_;
  564. $self->_bz_add_field_table($field->name,
  565. $self->_bz_schema->FIELD_TABLE_SCHEMA);
  566. if ( $field->type == FIELD_TYPE_MULTI_SELECT ) {
  567. $self->_bz_add_field_table('bug_' . $field->name,
  568. $self->_bz_schema->MULTI_SELECT_VALUE_TABLE);
  569. }
  570. }
  571. sub bz_drop_field_tables {
  572. my ($self, $field) = @_;
  573. if ($field->type == FIELD_TYPE_MULTI_SELECT) {
  574. $self->bz_drop_table('bug_' . $field->name);
  575. }
  576. $self->bz_drop_table($field->name);
  577. }
  578. sub bz_drop_column {
  579. my ($self, $table, $column) = @_;
  580. my $current_def = $self->bz_column_info($table, $column);
  581. if ($current_def) {
  582. my @statements = $self->_bz_real_schema->get_drop_column_ddl(
  583. $table, $column);
  584. print get_text('install_column_drop',
  585. { table => $table, column => $column }) . "\n"
  586. if Bugzilla->usage_mode == USAGE_MODE_CMDLINE;
  587. foreach my $sql (@statements) {
  588. # Because this is a deletion, we don't want to die hard if
  589. # we fail because of some local customization. If something
  590. # is already gone, that's fine with us!
  591. eval { $self->do($sql); } or warn "Failed SQL: [$sql] Error: $@";
  592. }
  593. $self->_bz_real_schema->delete_column($table, $column);
  594. $self->_bz_store_real_schema;
  595. }
  596. }
  597. sub bz_drop_fk {
  598. my ($self, $table, $column) = @_;
  599. my $col_def = $self->bz_column_info($table, $column);
  600. if ($col_def && exists $col_def->{REFERENCES}) {
  601. my $def = $col_def->{REFERENCES};
  602. print get_text('install_fk_drop',
  603. { table => $table, column => $column, fk => $def })
  604. . "\n" if Bugzilla->usage_mode == USAGE_MODE_CMDLINE;
  605. my @sql = $self->_bz_real_schema->get_drop_fk_sql($table,$column,$def);
  606. $self->do($_) foreach @sql;
  607. delete $col_def->{REFERENCES};
  608. $self->_bz_real_schema->set_column($table, $column, $col_def);
  609. $self->_bz_store_real_schema;
  610. }
  611. }
  612. sub bz_drop_index {
  613. my ($self, $table, $name) = @_;
  614. my $index_exists = $self->bz_index_info($table, $name);
  615. if ($index_exists) {
  616. $self->bz_drop_index_raw($table, $name);
  617. $self->_bz_real_schema->delete_index($table, $name);
  618. $self->_bz_store_real_schema;
  619. }
  620. }
  621. # bz_drop_index_raw($table, $name, $silent)
  622. #
  623. # Description: A helper function for bz_drop_index.
  624. # Drops an index from the database
  625. # without updating any Schema object. Generally
  626. # should only be called by bz_drop_index.
  627. # Used when either: (1) You don't yet have a Schema
  628. # object but you need to drop an index, for some reason.
  629. # (2) You need to drop an index that somehow got into the
  630. # database but doesn't exist in Schema.
  631. # Params: $table - The name of the table the index is on.
  632. # $name - The name of the index you're dropping.
  633. # $silent - (optional) If specified and true, don't output
  634. # any message about this change.
  635. # Returns: nothing
  636. #
  637. sub bz_drop_index_raw {
  638. my ($self, $table, $name, $silent) = @_;
  639. my @statements = $self->_bz_schema->get_drop_index_ddl(
  640. $table, $name);
  641. print "Removing index '$name' from the $table table...\n" unless $silent;
  642. foreach my $sql (@statements) {
  643. # Because this is a deletion, we don't want to die hard if
  644. # we fail because of some local customization. If something
  645. # is already gone, that's fine with us!
  646. eval { $self->do($sql) } or warn "Failed SQL: [$sql] Error: $@";
  647. }
  648. }
  649. sub bz_drop_table {
  650. my ($self, $name) = @_;
  651. my $table_exists = $self->bz_table_info($name);
  652. if ($table_exists) {
  653. my @statements = $self->_bz_schema->get_drop_table_ddl($name);
  654. print get_text('install_table_drop', { name => $name }) . "\n"
  655. if Bugzilla->usage_mode == USAGE_MODE_CMDLINE;
  656. foreach my $sql (@statements) {
  657. # Because this is a deletion, we don't want to die hard if
  658. # we fail because of some local customization. If something
  659. # is already gone, that's fine with us!
  660. eval { $self->do($sql); } or warn "Failed SQL: [$sql] Error: $@";
  661. }
  662. $self->_bz_real_schema->delete_table($name);
  663. $self->_bz_store_real_schema;
  664. }
  665. }
  666. sub bz_rename_column {
  667. my ($self, $table, $old_name, $new_name) = @_;
  668. my $old_col_exists = $self->bz_column_info($table, $old_name);
  669. if ($old_col_exists) {
  670. my $already_renamed = $self->bz_column_info($table, $new_name);
  671. ThrowCodeError('db_rename_conflict',
  672. { old => "$table.$old_name",
  673. new => "$table.$new_name" }) if $already_renamed;
  674. my @statements = $self->_bz_real_schema->get_rename_column_ddl(
  675. $table, $old_name, $new_name);
  676. print get_text('install_column_rename',
  677. { old => "$table.$old_name", new => "$table.$new_name" })
  678. . "\n" if Bugzilla->usage_mode == USAGE_MODE_CMDLINE;
  679. foreach my $sql (@statements) {
  680. $self->do($sql);
  681. }
  682. $self->_bz_real_schema->rename_column($table, $old_name, $new_name);
  683. $self->_bz_store_real_schema;
  684. }
  685. }
  686. sub bz_rename_table {
  687. my ($self, $old_name, $new_name) = @_;
  688. my $old_table = $self->bz_table_info($old_name);
  689. return if !$old_table;
  690. my $new = $self->bz_table_info($new_name);
  691. ThrowCodeError('db_rename_conflict', { old => $old_name,
  692. new => $new_name }) if $new;
  693. my @sql = $self->_bz_real_schema->get_rename_table_sql($old_name, $new_name);
  694. print get_text('install_table_rename',
  695. { old => $old_name, new => $new_name }) . "\n"
  696. if Bugzilla->usage_mode == USAGE_MODE_CMDLINE;
  697. $self->do($_) foreach @sql;
  698. $self->_bz_real_schema->rename_table($old_name, $new_name);
  699. $self->_bz_store_real_schema;
  700. }
  701. #####################################################################
  702. # Schema Information Methods
  703. #####################################################################
  704. sub _bz_schema {
  705. my ($self) = @_;
  706. return $self->{private_bz_schema} if exists $self->{private_bz_schema};
  707. my @module_parts = split('::', ref $self);
  708. my $module_name = pop @module_parts;
  709. $self->{private_bz_schema} = Bugzilla::DB::Schema->new($module_name);
  710. return $self->{private_bz_schema};
  711. }
  712. # _bz_get_initial_schema()
  713. #
  714. # Description: A protected method, intended for use only by Bugzilla::DB
  715. # and subclasses. Used to get the initial Schema that will
  716. # be written to disk for _bz_init_schema_storage. You probably
  717. # want to use _bz_schema or _bz_real_schema instead of this
  718. # method.
  719. # Params: none
  720. # Returns: A Schema object that can be serialized and written to disk
  721. # for _bz_init_schema_storage.
  722. sub _bz_get_initial_schema {
  723. my ($self) = @_;
  724. return $self->_bz_schema->get_empty_schema();
  725. }
  726. sub bz_column_info {
  727. my ($self, $table, $column) = @_;
  728. my $def = $self->_bz_real_schema->get_column_abstract($table, $column);
  729. # We dclone it so callers can't modify the Schema.
  730. $def = dclone($def) if defined $def;
  731. return $def;
  732. }
  733. sub bz_index_info {
  734. my ($self, $table, $index) = @_;
  735. my $index_def =
  736. $self->_bz_real_schema->get_index_abstract($table, $index);
  737. if (ref($index_def) eq 'ARRAY') {
  738. $index_def = {FIELDS => $index_def, TYPE => ''};
  739. }
  740. return $index_def;
  741. }
  742. sub bz_table_info {
  743. my ($self, $table) = @_;
  744. return $self->_bz_real_schema->get_table_abstract($table);
  745. }
  746. sub bz_table_columns {
  747. my ($self, $table) = @_;
  748. return $self->_bz_real_schema->get_table_columns($table);
  749. }
  750. sub bz_table_indexes {
  751. my ($self, $table) = @_;
  752. my $indexes = $self->_bz_real_schema->get_table_indexes_abstract($table);
  753. my %return_indexes;
  754. # We do this so that they're always hashes.
  755. foreach my $name (keys %$indexes) {
  756. $return_indexes{$name} = $self->bz_index_info($table, $name);
  757. }
  758. return \%return_indexes;
  759. }
  760. #####################################################################
  761. # Protected "Real Database" Schema Information Methods
  762. #####################################################################
  763. # Only Bugzilla::DB and subclasses should use these methods.
  764. # If you need a method that does the same thing as one of these
  765. # methods, use the version without _real on the end.
  766. # bz_table_columns_real($table)
  767. #
  768. # Description: Returns a list of columns on a given table
  769. # as the table actually is, on the disk.
  770. # Params: $table - Name of the table.
  771. # Returns: An array of column names.
  772. #
  773. sub bz_table_columns_real {
  774. my ($self, $table) = @_;
  775. my $sth = $self->column_info(undef, undef, $table, '%');
  776. return @{ $self->selectcol_arrayref($sth, {Columns => [4]}) };
  777. }
  778. # bz_table_list_real()
  779. #
  780. # Description: Gets a list of tables in the current
  781. # database, directly from the disk.
  782. # Params: none
  783. # Returns: An array containing table names.
  784. sub bz_table_list_real {
  785. my ($self) = @_;
  786. my $table_sth = $self->table_info(undef, undef, undef, "TABLE");
  787. return @{$self->selectcol_arrayref($table_sth, { Columns => [3] })};
  788. }
  789. #####################################################################
  790. # Transaction Methods
  791. #####################################################################
  792. sub bz_in_transaction {
  793. return $_[0]->{private_bz_transaction_count} ? 1 : 0;
  794. }
  795. sub bz_start_transaction {
  796. my ($self) = @_;
  797. if ($self->bz_in_transaction) {
  798. $self->{private_bz_transaction_count}++;
  799. } else {
  800. # Turn AutoCommit off and start a new transaction
  801. $self->begin_work();
  802. # REPEATABLE READ means "We work on a snapshot of the DB that
  803. # is created when we execute our first SQL statement." It's
  804. # what we need in Bugzilla to be safe, for what we do.
  805. # Different DBs have different defaults for their isolation
  806. # level, so we just set it here manually.
  807. $self->do('SET TRANSACTION ISOLATION LEVEL ' . $self->ISOLATION_LEVEL);
  808. $self->{private_bz_transaction_count} = 1;
  809. }
  810. }
  811. sub bz_commit_transaction {
  812. my ($self) = @_;
  813. if ($self->{private_bz_transaction_count} > 1) {
  814. $self->{private_bz_transaction_count}--;
  815. } elsif ($self->bz_in_transaction) {
  816. $self->commit();
  817. $self->{private_bz_transaction_count} = 0;
  818. } else {
  819. ThrowCodeError('not_in_transaction');
  820. }
  821. }
  822. sub bz_rollback_transaction {
  823. my ($self) = @_;
  824. # Unlike start and commit, if we rollback at any point it happens
  825. # instantly, even if we're in a nested transaction.
  826. if (!$self->bz_in_transaction) {
  827. ThrowCodeError("not_in_transaction");
  828. } else {
  829. $self->rollback();
  830. $self->{private_bz_transaction_count} = 0;
  831. }
  832. }
  833. #####################################################################
  834. # Subclass Helpers
  835. #####################################################################
  836. sub db_new {
  837. my ($class, $dsn, $user, $pass, $override_attrs) = @_;
  838. # set up default attributes used to connect to the database
  839. # (may be overridden by DB driver implementations)
  840. my $attributes = { RaiseError => 0,
  841. AutoCommit => 1,
  842. PrintError => 0,
  843. ShowErrorStatement => 1,
  844. HandleError => \&_handle_error,
  845. TaintIn => 1,
  846. FetchHashKeyName => 'NAME',
  847. # Note: NAME_lc causes crash on ActiveState Perl
  848. # 5.8.4 (see Bug 253696)
  849. # XXX - This will likely cause problems in DB
  850. # back ends that twiddle column case (Oracle?)
  851. };
  852. if ($override_attrs) {
  853. foreach my $key (keys %$override_attrs) {
  854. $attributes->{$key} = $override_attrs->{$key};
  855. }
  856. }
  857. # connect using our known info to the specified db
  858. my $self = DBI->connect($dsn, $user, $pass, $attributes)
  859. or die "\nCan't connect to the database.\nError: $DBI::errstr\n"
  860. . " Is your database installed and up and running?\n Do you have"
  861. . " the correct username and password selected in localconfig?\n\n";
  862. # RaiseError was only set to 0 so that we could catch the
  863. # above "die" condition.
  864. $self->{RaiseError} = 1;
  865. bless ($self, $class);
  866. return $self;
  867. }
  868. #####################################################################
  869. # Private Methods
  870. #####################################################################
  871. =begin private
  872. =head1 PRIVATE METHODS
  873. These methods really are private. Do not override them in subclasses.
  874. =over 4
  875. =item C<_init_bz_schema_storage>
  876. Description: Initializes the bz_schema table if it contains nothing.
  877. Params: none
  878. Returns: nothing
  879. =cut
  880. sub _bz_init_schema_storage {
  881. my ($self) = @_;
  882. my $table_size;
  883. eval {
  884. $table_size =
  885. $self->selectrow_array("SELECT COUNT(*) FROM bz_schema");
  886. };
  887. if (!$table_size) {
  888. my $init_schema = $self->_bz_get_initial_schema;
  889. my $store_me = $init_schema->serialize_abstract();
  890. my $schema_version = $init_schema->SCHEMA_VERSION;
  891. # If table_size is not defined, then we hit an error reading the
  892. # bz_schema table, which means it probably doesn't exist yet. So,
  893. # we have to create it. If we failed above for some other reason,
  894. # we'll see the failure here.
  895. # However, we must create the table after we do get_initial_schema,
  896. # because some versions of get_initial_schema read that the table
  897. # exists and then add it to the Schema, where other versions don't.
  898. if (!defined $table_size) {
  899. $self->_bz_add_table_raw('bz_schema');
  900. }
  901. print "Initializing the new Schema storage...\n";
  902. my $sth = $self->prepare("INSERT INTO bz_schema "
  903. ." (schema_data, version) VALUES (?,?)");
  904. $sth->bind_param(1, $store_me, $self->BLOB_TYPE);
  905. $sth->bind_param(2, $schema_version);
  906. $sth->execute();
  907. # And now we have to update the on-disk schema to hold the bz_schema
  908. # table, if the bz_schema table didn't exist when we were called.
  909. if (!defined $table_size) {
  910. $self->_bz_real_schema->add_table('bz_schema',
  911. $self->_bz_schema->get_table_abstract('bz_schema'));
  912. $self->_bz_store_real_schema;
  913. }
  914. }
  915. # Sanity check
  916. elsif ($table_size > 1) {
  917. # We tell them to delete the newer one. Better to have checksetup
  918. # run migration code too many times than to have it not run the
  919. # correct migration code at all.
  920. die "Attempted to initialize the schema but there are already "
  921. . " $table_size copies of it stored.\nThis should never happen.\n"
  922. . " Compare the rows of the bz_schema table and delete the "
  923. . "newer one(s).";
  924. }
  925. }
  926. =item C<_bz_real_schema()>
  927. Description: Returns a Schema object representing the database
  928. that is being used in the current installation.
  929. Params: none
  930. Returns: A C<Bugzilla::DB::Schema> object representing the database
  931. as it exists on the disk.
  932. =cut
  933. sub _bz_real_schema {
  934. my ($self) = @_;
  935. return $self->{private_real_schema} if exists $self->{private_real_schema};
  936. my ($data, $version) = $self->selectrow_array(
  937. "SELECT schema_data, version FROM bz_schema");
  938. (die "_bz_real_schema tried to read the bz_schema table but it's empty!")
  939. if !$data;
  940. $self->{private_real_schema} =
  941. $self->_bz_schema->deserialize_abstract($data, $version);
  942. return $self->{private_real_schema};
  943. }
  944. =item C<_bz_store_real_schema()>
  945. Description: Stores the _bz_real_schema structures in the database
  946. for later recovery. Call this function whenever you make
  947. a change to the _bz_real_schema.
  948. Params: none
  949. Returns: nothing
  950. Precondition: $self->{_bz_real_schema} must exist.
  951. =back
  952. =end private
  953. =cut
  954. sub _bz_store_real_schema {
  955. my ($self) = @_;
  956. # Make sure that there's a schema to update
  957. my $table_size = $self->selectrow_array("SELECT COUNT(*) FROM bz_schema");
  958. die "Attempted to update the bz_schema table but there's nothing "
  959. . "there to update. Run checksetup." unless $table_size;
  960. # We want to store the current object, not one
  961. # that we read from the database. So we use the actual hash
  962. # member instead of the subroutine call. If the hash
  963. # member is not defined, we will (and should) fail.
  964. my $update_schema = $self->{private_real_schema};
  965. my $store_me = $update_schema->serialize_abstract();
  966. my $schema_version = $update_schema->SCHEMA_VERSION;
  967. my $sth = $self->prepare("UPDATE bz_schema
  968. SET schema_data = ?, version = ?");
  969. $sth->bind_param(1, $store_me, $self->BLOB_TYPE);
  970. $sth->bind_param(2, $schema_version);
  971. $sth->execute();
  972. }
  973. # For bz_populate_enum_tables
  974. sub _bz_populate_enum_table {
  975. my ($self, $table, $valuelist) = @_;
  976. my $sql_table = $self->quote_identifier($table);
  977. # Check if there are any table entries
  978. my $table_size = $self->selectrow_array("SELECT COUNT(*) FROM $sql_table");
  979. # If the table is empty...
  980. if (!$table_size) {
  981. my $insert = $self->prepare(
  982. "INSERT INTO $sql_table (value,sortkey) VALUES (?,?)");
  983. print "Inserting values into the '$table' table:\n";
  984. my $sortorder = 0;
  985. my $maxlen = max(map(length($_), @$valuelist)) + 2;
  986. foreach my $value (@$valuelist) {
  987. $sortorder += 100;
  988. printf "%-${maxlen}s sortkey: $sortorder\n", "'$value'";
  989. $insert->execute($value, $sortorder);
  990. }
  991. }
  992. }
  993. # This is used before adding a foreign key to a column, to make sure
  994. # that the database won't fail adding the key.
  995. sub _check_references {
  996. my ($self, $table, $column, $foreign_table, $foreign_column) = @_;
  997. my $bad_values = $self->selectcol_arrayref(
  998. "SELECT DISTINCT $table.$column
  999. FROM $table LEFT JOIN $foreign_table
  1000. ON $table.$column = $foreign_table.$foreign_column
  1001. WHERE $foreign_table.$foreign_column IS NULL
  1002. AND $table.$column IS NOT NULL");
  1003. if (@$bad_values) {
  1004. my $values = join(', ', @$bad_values);
  1005. print <<EOT;
  1006. ERROR: There are invalid values for the $column column in the $table
  1007. table. (These values do not exist in the $foreign_table table, in the
  1008. $foreign_column column.)
  1009. Before continuing with checksetup, you will need to fix these values,
  1010. either by deleting these rows from the database, or changing the values
  1011. of $column in $table to point to valid values in $foreign_table.$foreign_column.
  1012. The bad values from the $table.$column column are:
  1013. $values
  1014. EOT
  1015. # I just picked a number above 2, to be considered "abnormal exit."
  1016. exit 3;
  1017. }
  1018. }
  1019. 1;
  1020. __END__
  1021. =head1 NAME
  1022. Bugzilla::DB - Database access routines, using L<DBI>
  1023. =head1 SYNOPSIS
  1024. # Obtain db handle
  1025. use Bugzilla::DB;
  1026. my $dbh = Bugzilla->dbh;
  1027. # prepare a query using DB methods
  1028. my $sth = $dbh->prepare("SELECT " .
  1029. $dbh->sql_date_format("creation_ts", "%Y%m%d") .
  1030. " FROM bugs WHERE bug_status != 'RESOLVED' " .
  1031. $dbh->sql_limit(1));
  1032. # Execute the query
  1033. $sth->execute;
  1034. # Get the results
  1035. my @result = $sth->fetchrow_array;
  1036. # Schema Modification
  1037. $dbh->bz_add_column($table, $name, \%definition, $init_value);
  1038. $dbh->bz_add_index($table, $name, $definition);
  1039. $dbh->bz_add_table($name);
  1040. $dbh->bz_drop_index($table, $name);
  1041. $dbh->bz_drop_table($name);
  1042. $dbh->bz_alter_column($table, $name, \%new_def, $set_nulls_to);
  1043. $dbh->bz_drop_column($table, $column);
  1044. $dbh->bz_rename_column($table, $old_name, $new_name);
  1045. # Schema Information
  1046. my $column = $dbh->bz_column_info($table, $column);
  1047. my $index = $dbh->bz_index_info($table, $index);
  1048. =head1 DESCRIPTION
  1049. Functions in this module allows creation of a database handle to connect
  1050. to the Bugzilla database. This should never be done directly; all users
  1051. should use the L<Bugzilla> module to access the current C<dbh> instead.
  1052. This module also contains methods extending the returned handle with
  1053. functionality which is different between databases allowing for easy
  1054. customization for particular database via inheritance. These methods
  1055. should be always preffered over hard-coding SQL commands.
  1056. =head1 CONSTANTS
  1057. Subclasses of Bugzilla::DB are required to define certain constants. These
  1058. constants are required to be subroutines or "use constant" variables.
  1059. =over
  1060. =item C<BLOB_TYPE>
  1061. The C<\%attr> argument that must be passed to bind_param in order to
  1062. correctly escape a C<LONGBLOB> type.
  1063. =item C<ISOLATION_LEVEL>
  1064. The argument that this database should send to
  1065. C<SET TRANSACTION ISOLATION LEVEL> when starting a transaction. If you
  1066. override this in a subclass, the isolation level you choose should
  1067. be as strict as or more strict than the default isolation level defined in
  1068. L<Bugzilla::DB>.
  1069. =back
  1070. =head1 CONNECTION
  1071. A new database handle to the required database can be created using this
  1072. module. This is normally done by the L<Bugzilla> module, and so these routines
  1073. should not be called from anywhere else.
  1074. =head2 Functions
  1075. =over
  1076. =item C<connect_main>
  1077. =over
  1078. =item B<Description>
  1079. Function to connect to the main database, returning a new database handle.
  1080. =item B<Params>
  1081. =over
  1082. =item C<$no_db_name> (optional) - If true, connect to the database
  1083. server, but don't connect to a specific database. This is only used
  1084. when creating a database. After you create the database, you should
  1085. re-create a new Bugzilla::DB object without using this parameter.
  1086. =back
  1087. =item B<Returns>
  1088. New instance of the DB class
  1089. =back
  1090. =item C<connect_shadow>
  1091. =over
  1092. =item B<Description>
  1093. Function to connect to the shadow database, returning a new database handle.
  1094. This routine C<die>s if no shadow database is configured.
  1095. =item B<Params> (none)
  1096. =item B<Returns>
  1097. A new instance of the DB class
  1098. =back
  1099. =item C<bz_check_requirements>
  1100. =over
  1101. =item B<Description>
  1102. Checks to make sure that you have the correct DBD and database version
  1103. installed for the database that Bugzilla will be using. Prints a message
  1104. and exits if you don't pass the requirements.
  1105. If C<$db_check> is false (from F<localconfig>), we won't check the
  1106. database version.
  1107. =item B<Params>
  1108. =over
  1109. =item C<$output> - C<true> if the function should display informational
  1110. output about what it's doing, such as versions found.
  1111. =back
  1112. =item B<Returns> (nothing)
  1113. =back
  1114. =item C<bz_create_database>
  1115. =over
  1116. =item B<Description>
  1117. Creates an empty database with the name C<$db_name>, if that database
  1118. doesn't already exist. Prints an error message and exits if we can't
  1119. create the database.
  1120. =item B<Params> (none)
  1121. =item B<Returns> (nothing)
  1122. =back
  1123. =item C<_connect>
  1124. =over
  1125. =item B<Description>
  1126. Internal function, creates and returns a new, connected instance of the
  1127. correct DB class. This routine C<die>s if no driver is specified.
  1128. =item B<Params>
  1129. =over
  1130. =item C<$driver> - name of the database driver to use
  1131. =item C<$host> - host running the database we are connecting to
  1132. =item C<$dbname> - name of the database to connect to
  1133. =item C<$port> - port the database is listening on
  1134. =item C<$sock> - socket the database is listening on
  1135. =item C<$user> - username used to log in to the database
  1136. =item C<$pass> - password used to log in to the database
  1137. =back
  1138. =item B<Returns>
  1139. A new instance of the DB class
  1140. =back
  1141. =item C<_handle_error>
  1142. Function passed to the DBI::connect call for error handling. It shortens the
  1143. error for printing.
  1144. =item C<import>
  1145. Overrides the standard import method to check that derived class
  1146. implements all required abstract methods. Also calls original implementation
  1147. in its super class.
  1148. =back
  1149. =head1 ABSTRACT METHODS
  1150. Note: Methods which can be implemented generically for all DBs are implemented in
  1151. this module. If needed, they can be overridden with DB specific code.
  1152. Methods which do not have standard implementation are abstract and must
  1153. be implemented for all supported databases separately.
  1154. To avoid confusion with standard DBI methods, all methods returning string with
  1155. formatted SQL command have prefix C<sql_>. All other methods have prefix C<bz_>.
  1156. =head2 Constructor
  1157. =over
  1158. =item C<new>
  1159. =over
  1160. =item B<Description>
  1161. Constructor. Abstract method, should be overridden by database specific
  1162. code.
  1163. =item B<Params>
  1164. =over
  1165. =item C<$user> - username used to log in to the database
  1166. =item C<$pass> - password used to log in to the database
  1167. =item C<$host> - host running the database we are connecting to
  1168. =item C<$dbname> - name of the database to connect to
  1169. =item C<$port> - port the database is listening on
  1170. =item C<$sock> - socket the database is listening on
  1171. =back
  1172. =item B<Returns>
  1173. A new instance of the DB class
  1174. =item B<Note>
  1175. The constructor should create a DSN from the parameters provided and
  1176. then call C<db_new()> method of its super class to create a new
  1177. class instance. See L<db_new> description in this module. As per
  1178. DBI documentation, all class variables must be prefixed with
  1179. "private_". See L<DBI>.
  1180. =back
  1181. =back
  1182. =head2 SQL Generation
  1183. =over
  1184. =item C<sql_regexp>
  1185. =over
  1186. =item B<Description>
  1187. Outputs SQL regular expression operator for POSIX regex
  1188. searches (case insensitive) in format suitable for a given
  1189. database.
  1190. Abstract method, should be overridden by database specific code.
  1191. =item B<Params>
  1192. =over
  1193. =item C<$expr> - SQL expression for the text to be searched (scalar)
  1194. =item C<$pattern> - the regular expression to search for (scalar)
  1195. =back
  1196. =item B<Returns>
  1197. Formatted SQL for regular expression search (e.g. REGEXP) (scalar)
  1198. =back
  1199. =item C<sql_not_regexp>
  1200. =over
  1201. =item B<Description>
  1202. Outputs SQL regular expression operator for negative POSIX
  1203. regex searches (case insensitive) in format suitable for a given
  1204. database.
  1205. Abstract method, should be overridden by database specific code.
  1206. =item B<Params>
  1207. =over
  1208. =item C<$expr> - SQL expression for the text to be searched (scalar)
  1209. =item C<$pattern> - the regular expression to search for (scalar)
  1210. =back
  1211. =item B<Returns>
  1212. Formatted SQL for negative regular expression search (e.g. NOT REGEXP)
  1213. (scalar)
  1214. =back
  1215. =item C<sql_limit>
  1216. =over
  1217. =item B<Description>
  1218. Returns SQL syntax for limiting results to some number of rows
  1219. with optional offset if not starting from the begining.
  1220. Abstract method, should be overridden by database specific code.
  1221. =item B<Params>
  1222. =over
  1223. =item C<$limit> - number of rows to return from query (scalar)
  1224. =item C<$offset> - number of rows to skip before counting (scalar)
  1225. =back
  1226. =item B<Returns>
  1227. Formatted SQL for limiting number of rows returned from query
  1228. with optional offset (e.g. LIMIT 1, 1) (scalar)
  1229. =back
  1230. =item C<sql_from_days>
  1231. =over
  1232. =item B<Description>
  1233. Outputs SQL syntax for converting Julian days to date.
  1234. Abstract method, should be overridden by database specific code.
  1235. =item B<Params>
  1236. =over
  1237. =item C<$days> - days to convert to date
  1238. =back
  1239. =item B<Returns>
  1240. Formatted SQL for returning Julian days in dates. (scalar)
  1241. =back
  1242. =item C<sql_to_days>
  1243. =over
  1244. =item B<Description>
  1245. Outputs SQL syntax for converting date to Julian days.
  1246. Abstract method, should be overridden by database specific code.
  1247. =item B<Params>
  1248. =over
  1249. =item C<$date> - date to convert to days
  1250. =back
  1251. =item B<Returns>
  1252. Formatted SQL for returning date fields in Julian days. (scalar)
  1253. =back
  1254. =item C<sql_date_format>
  1255. =over
  1256. =item B<Description>
  1257. Outputs SQL syntax for formatting dates.
  1258. Abstract method, should be overridden by database specific code.
  1259. =item B<Params>
  1260. =over
  1261. =item C<$date> - date or name of date type column (scalar)
  1262. =item C<$format> - format string for date output (scalar)
  1263. (C<%Y> = year, four digits, C<%y> = year, two digits, C<%m> = month,
  1264. C<%d> = day, C<%a> = weekday name, 3 letters, C<%H> = hour 00-23,
  1265. C<%i> = minute, C<%s> = second)
  1266. =back
  1267. =item B<Returns>
  1268. Formatted SQL for date formatting (scalar)
  1269. =back
  1270. =item C<sql_interval>
  1271. =over
  1272. =item B<Description>
  1273. Outputs proper SQL syntax for a time interval function.
  1274. Abstract method, should be overridden by database specific code.
  1275. =item B<Params>
  1276. =over
  1277. =item C<$interval> - the time interval requested (e.g. '30') (integer)
  1278. =item C<$units> - the units the interval is in (e.g. 'MINUTE') (string)
  1279. =back
  1280. =item B<Returns>
  1281. Formatted SQL for interval function (scalar)
  1282. =back
  1283. =item C<sql_position>
  1284. =over
  1285. =item B<Description>
  1286. Outputs proper SQL syntax determining position of a substring
  1287. (fragment) withing a string (text). Note: if the substring or
  1288. text are string constants, they must be properly quoted (e.g. "'pattern'").
  1289. It searches for the string in a case-sensitive manner. If you want to do
  1290. a case-insensitive search, use L</sql_iposition>.
  1291. =item B<Params>
  1292. =over
  1293. =item C<$fragment> - the string fragment we are searching for (scalar)
  1294. =item C<$text> - the text to search (scalar)
  1295. =back
  1296. =item B<Returns>
  1297. Formatted SQL for substring search (scalar)
  1298. =back
  1299. =item C<sql_iposition>
  1300. Just like L</sql_position>, but case-insensitive.
  1301. =item C<sql_group_by>
  1302. =over
  1303. =item B<Description>
  1304. Outputs proper SQL syntax for grouping the result of a query.
  1305. For ANSI SQL databases, we need to group by all columns we are
  1306. querying for (except for columns used in aggregate functions).
  1307. Some databases require (or even allow) to specify only one
  1308. or few columns if the result is uniquely defined. For those
  1309. databases, the default implementation needs to be overloaded.
  1310. =item B<Params>
  1311. =over
  1312. =item C<$needed_columns> - string with comma separated list of columns
  1313. we need to group by to get expected result (scalar)
  1314. =item C<$optional_columns> - string with comma separated list of all
  1315. other columns we are querying for, but which are not in the required list.
  1316. =back
  1317. =item B<Returns>
  1318. Formatted SQL for row grouping (scalar)
  1319. =back
  1320. =item C<sql_string_concat>
  1321. =over
  1322. =item B<Description>
  1323. Returns SQL syntax for concatenating multiple strings (constants
  1324. or values from table columns) together.
  1325. =item B<Params>
  1326. =over
  1327. =item C<@params> - array of column names or strings to concatenate
  1328. =back
  1329. =item B<Returns>
  1330. Formatted SQL for concatenating specified strings
  1331. =back
  1332. =item C<sql_fulltext_search>
  1333. =over
  1334. =item B<Description>
  1335. Returns SQL syntax for performing a full text search for specified text
  1336. on a given column.
  1337. There is a ANSI SQL version of this method implemented using LIKE operator,
  1338. but it's not a real full text search. DB specific modules should override
  1339. this, as this generic implementation will be always much slower. This
  1340. generic implementation returns 'relevance' as 0 for no match, or 1 for a
  1341. match.
  1342. =item B<Params>
  1343. =over
  1344. =item C<$column> - name of column to search (scalar)
  1345. =item C<$text> - text to search for (scalar)
  1346. =back
  1347. =item B<Returns>
  1348. Formatted SQL for full text search
  1349. =back
  1350. =item C<sql_istrcmp>
  1351. =over
  1352. =item B<Description>
  1353. Returns SQL for a case-insensitive string comparison.
  1354. =item B<Params>
  1355. =over
  1356. =item C<$left> - What should be on the left-hand-side of the operation.
  1357. =item C<$right> - What should be on the right-hand-side of the operation.
  1358. =item C<$op> (optional) - What the operation is. Should be a valid ANSI
  1359. SQL comparison operator, such as C<=>, C<E<lt>>, C<LIKE>, etc. Defaults
  1360. to C<=> if not specified.
  1361. =back
  1362. =item B<Returns>
  1363. A SQL statement that will run the comparison in a case-insensitive fashion.
  1364. =item B<Note>
  1365. Uses L</sql_istring>, so it has the same performance concerns.
  1366. Try to avoid using this function unless absolutely necessary.
  1367. Subclass Implementors: Override sql_istring instead of this
  1368. function, most of the time (this function uses sql_istring).
  1369. =back
  1370. =item C<sql_istring>
  1371. =over
  1372. =item B<Description>
  1373. Returns SQL syntax "preparing" a string or text column for case-insensitive
  1374. comparison.
  1375. =item B<Params>
  1376. =over
  1377. =item C<$string> - string to convert (scalar)
  1378. =back
  1379. =item B<Returns>
  1380. Formatted SQL making the string case insensitive.
  1381. =item B<Note>
  1382. The default implementation simply calls LOWER on the parameter.
  1383. If this is used to search on a text column with index, the index
  1384. will not be usually used unless it was created as LOWER(column).
  1385. =back
  1386. =item C<sql_in>
  1387. =over
  1388. =item B<Description>
  1389. Returns SQL syntax for the C<IN ()> operator.
  1390. Only necessary where an C<IN> clause can have more than 1000 items.
  1391. =item B<Params>
  1392. =over
  1393. =item C<$column_name> - Column name (e.g. C<bug_id>)
  1394. =item C<$in_list_ref> - an arrayref containing values for C<IN ()>
  1395. =back
  1396. =item B<Returns>
  1397. Formatted SQL for the C<IN> operator.
  1398. =back
  1399. =back
  1400. =head1 IMPLEMENTED METHODS
  1401. These methods are implemented in Bugzilla::DB, and only need
  1402. to be implemented in subclasses if you need to override them for
  1403. database-compatibility reasons.
  1404. =head2 General Information Methods
  1405. These methods return information about data in the database.
  1406. =over
  1407. =item C<bz_last_key>
  1408. =over
  1409. =item B<Description>
  1410. Returns the last serial number, usually from a previous INSERT.
  1411. Must be executed directly following the relevant INSERT.
  1412. This base implementation uses L<DBI/last_insert_id>. If the
  1413. DBD supports it, it is the preffered way to obtain the last
  1414. serial index. If it is not supported, the DB-specific code
  1415. needs to override this function.
  1416. =item B<Params>
  1417. =over
  1418. =item C<$table> - name of table containing serial column (scalar)
  1419. =item C<$column> - name of column containing serial data type (scalar)
  1420. =back
  1421. =item B<Returns>
  1422. Last inserted ID (scalar)
  1423. =back
  1424. =back
  1425. =head2 Database Setup Methods
  1426. These methods are used by the Bugzilla installation programs to set up
  1427. the database.
  1428. =over
  1429. =item C<bz_populate_enum_tables>
  1430. =over
  1431. =item B<Description>
  1432. For an upgrade or an initial installation, populates the tables that hold
  1433. the legal values for the old "enum" fields: C<bug_severity>,
  1434. C<resolution>, etc. Prints out information if it inserts anything into the
  1435. DB.
  1436. =item B<Params> (none)
  1437. =item B<Returns> (nothing)
  1438. =back
  1439. =back
  1440. =head2 Schema Modification Methods
  1441. These methods modify the current Bugzilla Schema.
  1442. Where a parameter says "Abstract index/column definition", it returns/takes
  1443. information in the formats defined for indexes and columns in
  1444. C<Bugzilla::DB::Schema::ABSTRACT_SCHEMA>.
  1445. =over
  1446. =item C<bz_add_column>
  1447. =over
  1448. =item B<Description>
  1449. Adds a new column to a table in the database. Prints out a brief statement
  1450. that it did so, to stdout. Note that you cannot add a NOT NULL column that
  1451. has no default -- the database won't know what to set all the NULL
  1452. values to.
  1453. =item B<Params>
  1454. =over
  1455. =item C<$table> - the table where the column is being added
  1456. =item C<$name> - the name of the new column
  1457. =item C<\%definition> - Abstract column definition for the new column
  1458. =item C<$init_value> (optional) - An initial value to set the column
  1459. to. Required if your column is NOT NULL and has no DEFAULT set.
  1460. =back
  1461. =item B<Returns> (nothing)
  1462. =back
  1463. =item C<bz_add_index>
  1464. =over
  1465. =item B<Description>
  1466. Adds a new index to a table in the database. Prints out a brief statement
  1467. that it did so, to stdout. If the index already exists, we will do nothing.
  1468. =item B<Params>
  1469. =over
  1470. =item C<$table> - The table the new index is on.
  1471. =item C<$name> - A name for the new index.
  1472. =item C<$definition> - An abstract index definition. Either a hashref
  1473. or an arrayref.
  1474. =back
  1475. =item B<Returns> (nothing)
  1476. =back
  1477. =item C<bz_add_table>
  1478. =over
  1479. =item B<Description>
  1480. Creates a new table in the database, based on the definition for that
  1481. table in the abstract schema.
  1482. Note that unlike the other 'add' functions, this does not take a
  1483. definition, but always creates the table as it exists in
  1484. L<Bugzilla::DB::Schema/ABSTRACT_SCHEMA>.
  1485. If a table with that name already exists, then this function returns
  1486. silently.
  1487. =item B<Params>
  1488. =over
  1489. =item C<$name> - The name of the table you want to create.
  1490. =back
  1491. =item B<Returns> (nothing)
  1492. =back
  1493. =item C<bz_drop_index>
  1494. =over
  1495. =item B<Description>
  1496. Removes an index from the database. Prints out a brief statement that it
  1497. did so, to stdout. If the index doesn't exist, we do nothing.
  1498. =item B<Params>
  1499. =over
  1500. =item C<$table> - The table that the index is on.
  1501. =item C<$name> - The name of the index that you want to drop.
  1502. =back
  1503. =item B<Returns> (nothing)
  1504. =back
  1505. =item C<bz_drop_table>
  1506. =over
  1507. =item B<Description>
  1508. Drops a table from the database. If the table doesn't exist, we just
  1509. return silently.
  1510. =item B<Params>
  1511. =over
  1512. =item C<$name> - The name of the table to drop.
  1513. =back
  1514. =item B<Returns> (nothing)
  1515. =back
  1516. =item C<bz_alter_column>
  1517. =over
  1518. =item B<Description>
  1519. Changes the data type of a column in a table. Prints out the changes
  1520. being made to stdout. If the new type is the same as the old type,
  1521. the function returns without changing anything.
  1522. =item B<Params>
  1523. =over
  1524. =item C<$table> - the table where the column is
  1525. =item C<$name> - the name of the column you want to change
  1526. =item C<\%new_def> - An abstract column definition for the new
  1527. data type of the columm
  1528. =item C<$set_nulls_to> (Optional) - If you are changing the column
  1529. to be NOT NULL, you probably also want to set any existing NULL columns
  1530. to a particular value. Specify that value here. B<NOTE>: The value should
  1531. not already be SQL-quoted.
  1532. =back
  1533. =item B<Returns> (nothing)
  1534. =back
  1535. =item C<bz_drop_column>
  1536. =over
  1537. =item B<Description>
  1538. Removes a column from a database table. If the column doesn't exist, we
  1539. return without doing anything. If we do anything, we print a short
  1540. message to C<stdout> about the change.
  1541. =item B<Params>
  1542. =over
  1543. =item C<$table> - The table where the column is
  1544. =item C<$column> - The name of the column you want to drop
  1545. =back
  1546. =item B<Returns> (nothing)
  1547. =back
  1548. =item C<bz_rename_column>
  1549. =over
  1550. =item B<Description>
  1551. Renames a column in a database table. If the C<$old_name> column
  1552. doesn't exist, we return without doing anything. If C<$old_name>
  1553. and C<$new_name> both already exist in the table specified, we fail.
  1554. =item B<Params>
  1555. =over
  1556. =item C<$table> - The name of the table containing the column
  1557. that you want to rename
  1558. =item C<$old_name> - The current name of the column that you want to rename
  1559. =item C<$new_name> - The new name of the column
  1560. =back
  1561. =item B<Returns> (nothing)
  1562. =back
  1563. =item C<bz_rename_table>
  1564. =over
  1565. =item B<Description>
  1566. Renames a table in the database. Does nothing if the table doesn't exist.
  1567. Throws an error if the old table exists and there is already a table
  1568. with the new name.
  1569. =item B<Params>
  1570. =over
  1571. =item C<$old_name> - The current name of the table.
  1572. =item C<$new_name> - What you're renaming the table to.
  1573. =back
  1574. =item B<Returns> (nothing)
  1575. =back
  1576. =back
  1577. =head2 Schema Information Methods
  1578. These methods return information about the current Bugzilla database
  1579. schema, as it currently exists on the disk.
  1580. Where a parameter says "Abstract index/column definition", it returns/takes
  1581. information in the formats defined for indexes and columns for
  1582. L<Bugzilla::DB::Schema/ABSTRACT_SCHEMA>.
  1583. =over
  1584. =item C<bz_column_info>
  1585. =over
  1586. =item B<Description>
  1587. Get abstract column definition.
  1588. =item B<Params>
  1589. =over
  1590. =item C<$table> - The name of the table the column is in.
  1591. =item C<$column> - The name of the column.
  1592. =back
  1593. =item B<Returns>
  1594. An abstract column definition for that column. If the table or column
  1595. does not exist, we return C<undef>.
  1596. =back
  1597. =item C<bz_index_info>
  1598. =over
  1599. =item B<Description>
  1600. Get abstract index definition.
  1601. =item B<Params>
  1602. =over
  1603. =item C<$table> - The table the index is on.
  1604. =item C<$index> - The name of the index.
  1605. =back
  1606. =item B<Returns>
  1607. An abstract index definition for that index, always in hashref format.
  1608. The hashref will always contain the C<TYPE> element, but it will
  1609. be an empty string if it's just a normal index.
  1610. If the index does not exist, we return C<undef>.
  1611. =back
  1612. =back
  1613. =head2 Transaction Methods
  1614. These methods deal with the starting and stopping of transactions
  1615. in the database.
  1616. =over
  1617. =item C<bz_in_transaction>
  1618. Returns C<1> if we are currently in the middle of an uncommitted transaction,
  1619. C<0> otherwise.
  1620. =item C<bz_start_transaction>
  1621. Starts a transaction.
  1622. It is OK to call C<bz_start_transaction> when you are already inside of
  1623. a transaction. However, you must call L</bz_commit_transaction> as many
  1624. times as you called C<bz_start_transaction>, in order for your transaction
  1625. to actually commit.
  1626. Bugzilla uses C<REPEATABLE READ> transactions.
  1627. Returns nothing and takes no parameters.
  1628. =item C<bz_commit_transaction>
  1629. Ends a transaction, commiting all changes. Returns nothing and takes
  1630. no parameters.
  1631. =item C<bz_rollback_transaction>
  1632. Ends a transaction, rolling back all changes. Returns nothing and takes
  1633. no parameters.
  1634. =back
  1635. =head1 SUBCLASS HELPERS
  1636. Methods in this class are intended to be used by subclasses to help them
  1637. with their functions.
  1638. =over
  1639. =item C<db_new>
  1640. =over
  1641. =item B<Description>
  1642. Constructor
  1643. =item B<Params>
  1644. =over
  1645. =item C<$dsn> - database connection string
  1646. =item C<$user> - username used to log in to the database
  1647. =item C<$pass> - password used to log in to the database
  1648. =item C<\%override_attrs> - set of attributes for DB connection (optional).
  1649. You only have to set attributes that you want to be different from
  1650. the default attributes set inside of C<db_new>.
  1651. =back
  1652. =item B<Returns>
  1653. A new instance of the DB class
  1654. =item B<Note>
  1655. The name of this constructor is not C<new>, as that would make
  1656. our check for implementation of C<new> by derived class useless.
  1657. =back
  1658. =back
  1659. =head1 SEE ALSO
  1660. L<DBI>
  1661. L<Bugzilla::Constants/DB_MODULE>