Skip to content

Commit 8b638e3

Browse files
committed
20230623 Better Closes for #212 & #215
Code Cleanup. File(s): includes/base_db.inc.php Function(s): baseFKeyExists( $key ) Returns true if RI is enabled and the RI Foreign Key exists in the DB structure, false otherwise. Unit Test(s): Covers the following in the baseCon Class baseFKeyExists()
1 parent f89eec3 commit 8b638e3

File tree

5 files changed

+294
-103
lines changed

5 files changed

+294
-103
lines changed

includes/base_constants.inc.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949
// DB connection method
5050
SetConst("DB_CONNECT", 2);
5151
SetConst("DB_PCONNECT", 1);
52+
SetConst("DB_RICC", 8); // Referential Integrity Constraint Count.
5253

5354
// CleanVariable Mask
5455
SetConst("VAR_DIGIT", 1);

includes/base_db.inc.php

Lines changed: 209 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -475,8 +475,7 @@ function baseSetRI( $DS = true ){ // DB Referential Integrity Control.
475475
){ // MariaDB Check
476476
$MariaDB = true;
477477
}
478-
$tmp = $tmp['version'];
479-
$DBSV = VS2SV($tmp);
478+
$DBSV = VS2SV($tmp['version']);
480479
if( $DS ){ // Set RI if possible.
481480
$QF = false; // Query Flag.
482481
$RIE = false; // RI Enable Flag.
@@ -529,68 +528,151 @@ function baseSetRI( $DS = true ){ // DB Referential Integrity Control.
529528
}
530529
}
531530
if( $QF ){ // Query Info Schema for RI Information.
531+
$SE = true; // Assume Success
532532
$sqlPfx = 'SELECT ';
533-
$LPfx = '';
534-
$RPfx = 'referenced_';
533+
$sqlIS = 'information_schema';
534+
$SSfx = 'SCHEMA';
535535
if( $this->DB_type == 'postgres' ){
536-
$LPfx = 'kcu.';
537-
$RPfx = 'ccu.';
538-
$sqlPfx .= $LPfx . 'COLUMN_NAME, ' . $RPfx
539-
. 'COLUMN_NAME AS REFERENCED_COLUMN_NAME FROM '
540-
. 'information_schema.key_column_usage AS kcu JION'
541-
. ' information_schema.constraint_column_usage'
542-
. " AS ccu ON $RPfx" . 'constraint_name = '
543-
. $LPfx . 'constraint_name';
544-
}else{
545-
$sqlPfx .= $LPfx . 'COLUMN_NAME, ' . $RPfx
546-
. 'COLUMN_NAME FROM '
547-
. 'information_schema.key_column_usage';
536+
$SSfx = 'CATALOG';
548537
}
549-
$sqlPfx .= " WHERE $RPfx" . "table_name = 'event'"
550-
. " AND $LPfx" . "TABLE_SCHEMA = '" . $this->DB_name
551-
. "' AND $LPfx" . "TABLE_NAME = '";
552-
foreach( $RItbls as $val ){
553-
$EPfx = "$EMPfx$val ";
554-
$Cval = $RIcl[$val];
555-
$sql = "$sqlPfx$val' AND $LPfx"
556-
. "CONSTRAINT_NAME = '"
557-
. $Cval . "'";
558-
DumpSQL($sql, 3);
559-
$rs = $this->DB->Execute($sql);
560-
if(
561-
$rs != false && $this->baseErrorMessage() == ''
562-
){ // Error Check
563-
if( $rs->RecordCount() > 0 ){
564-
$tmp = '';
565-
if( $val == 'acid_ag_alert' ){
566-
$tmp = 'ag_';
538+
$sql = $sqlPfx . 'CONSTRAINT_NAME, UPDATE_RULE, '
539+
. 'DELETE_RULE FROM ' . $sqlIS
540+
. '.referential_constraints WHERE '
541+
. "CONSTRAINT_$SSfx = '" . $this->DB_name . "'";
542+
DumpSQL($sql, 3);
543+
$rs = $this->DB->Execute($sql);
544+
if(
545+
$rs != false && $this->baseErrorMessage() == ''
546+
){ // Error Check
547+
if( $rs->RecordCount() == DB_RICC ){
548+
$tmp = array_values($RIcl);
549+
while( !$rs->EOF ){
550+
$myrow = $rs->fields;
551+
if(
552+
!in_array($myrow[0], $tmp)
553+
|| $myrow[1] != $myrow[2]
554+
|| $myrow[1] != 'CASCADE'
555+
){
556+
$RSC = true; // Restructure
557+
break;
567558
}
568-
// RI setup in DB table, Verify Structure.
569-
while( !$rs->EOF ){
570-
$myrow = $rs->fields;
571-
$myrow[0] = preg_replace(
572-
'/^' . $tmp . '/', '', $myrow[0]
573-
);
574-
if( $myrow[0] != $myrow[1] ){
575-
// @codeCoverageIgnoreStart
576-
$rs->Close(); // Corrupt Structure.
577-
$RSC = true; // Restructure
578-
break 2;
579-
// @codeCoverageIgnoreEnd
559+
$rs->MoveNext();
560+
}
561+
$rs->Close();
562+
}else{
563+
$RSC = true; // Restructure
564+
}
565+
}else{ // Transient DB Error.
566+
// @codeCoverageIgnoreStart
567+
KML($EPfx . 'access error.', 3);
568+
$SE = false; // Failure
569+
// @codeCoverageIgnoreEnd
570+
}
571+
if ( $SE && !$RSC ){
572+
$tmp = '';
573+
if( $this->DB_class == 1 ){
574+
$tmp = ', referenced_COLUMN_NAME';
575+
}
576+
$sqlt = $sqlPfx . "COLUMN_NAME$tmp FROM $sqlIS"
577+
. ".key_column_usage WHERE TABLE_$SSfx = '"
578+
. $this->DB_name . "' AND TABLE_NAME = '";
579+
foreach( $RItbls as $val ){
580+
$EPfx = "$EMPfx$val ";
581+
$Cval = $RIcl[$val];
582+
$sql = "$sqlt$val' AND CONSTRAINT_NAME = '"
583+
. $Cval . "'";
584+
DumpSQL($sql, 3);
585+
$rs = $this->DB->Execute($sql);
586+
if(
587+
$rs != false
588+
&& $this->baseErrorMessage() == ''
589+
){ // Error Check
590+
if( $rs->RecordCount() > 0 ){
591+
$RCN = array();
592+
if( $this->DB_type == 'postgres' ){
593+
$sql2 = $sqlPfx . 'COLUMN_NAME'
594+
. " FROM $sqlIS"
595+
. '.constraint_column_usage WHERE '
596+
. "TABLE_$SSfx = '"
597+
. $this->DB_name . "' AND "
598+
. "CONSTRAINT_NAME = '" . $Cval
599+
. "'";
600+
DumpSQL($sql2, 3);
601+
$rs2 = $this->DB->Execute($sql2);
602+
if(
603+
$rs2 != false
604+
&& $this->baseErrorMessage()
605+
== ''
606+
){ // Error Check
607+
if( $rs2->RecordCount() > 0 ){
608+
while( !$rs2->EOF ){
609+
$myrow = $rs2->fields;
610+
array_push(
611+
$RCN, $myrow[0]
612+
);
613+
$rs2->MoveNext();
614+
}
615+
$rs2->Close();
616+
}else{
617+
$RSC = true; // Restructure
618+
}
619+
}else{ // Transient DB Error.
620+
// @codeCoverageIgnoreStart
621+
KML($EPfx . 'access error.', 3);
622+
$SE = false; // Failure
623+
break;
624+
// @codeCoverageIgnoreEnd
625+
}
626+
}
627+
$tmp = '';
628+
if( $val == 'acid_ag_alert' ){
629+
$tmp = 'ag_';
580630
}
581-
$rs->MoveNext();
631+
// RI setup in DB table, Verify
632+
// Structure.
633+
while( !$rs->EOF ){
634+
$myrow = $rs->fields;
635+
$myrow[0] = preg_replace(
636+
'/^' . $tmp . '/', '',
637+
$myrow[0]
638+
);
639+
$tmp2 = count($myrow);
640+
if( $this->DB_class == 1 ){
641+
if(
642+
$tmp2 < 2
643+
|| $myrow[0] != $myrow[1]
644+
){
645+
// @codeCoverageIgnoreStart
646+
$rs->Close(); // Corrupt Structure.
647+
$RSC = true; // Restructure
648+
break 2;
649+
// @codeCoverageIgnoreEnd
650+
}
651+
}else{
652+
if(
653+
!in_array($myrow[0], $RCN)
654+
){
655+
// @codeCoverageIgnoreStart
656+
$rs->Close(); // Corrupt Structure.
657+
$RSC = true; // Restructure
658+
break 2;
659+
// @codeCoverageIgnoreEnd
660+
}
661+
}
662+
$rs->MoveNext();
663+
}
664+
$rs->Close();
665+
}else{ // RI Not setup in DB table.
666+
$RSC = true; // Restructure
667+
break;
582668
}
583-
$rs->Close();
584-
}else{ // RI Not setup in DB table.
585-
$RSC = true; // Restructure
669+
}else{ // Transient DB Error.
670+
// @codeCoverageIgnoreStart
671+
KML($EPfx . 'access error.', 3);
672+
$SE = false; // Failure
586673
break;
674+
// @codeCoverageIgnoreEnd
587675
}
588-
}else{ // Transient DB Error.
589-
// @codeCoverageIgnoreStart
590-
KML($EPfx . 'access error.', 3);
591-
$SE = false; // Failure
592-
break;
593-
// @codeCoverageIgnoreEnd
594676
}
595677
}
596678
if( $RSC ){ // Clear DB RI Structure
@@ -655,19 +737,24 @@ function baseSetRI( $DS = true ){ // DB Referential Integrity Control.
655737
foreach( $RItbls as $val ){
656738
$EPfx = "$EMPfx$val ";
657739
$Cval = $RIcl[$val];
658-
$sql = "ALTER TABLE $val DROP $tmp $tmp2$Cval";
659-
DumpSQL($sql, 3);
660-
$rs = $this->DB->Execute($sql);
661740
if(
662-
$rs != false && $this->baseErrorMessage() == ''
663-
){ // Error Check
664-
$rs->Close();
665-
KML($EPfx . 'RI disabled.', 3);
666-
}else{ // Transient DB Error.
667-
// @codeCoverageIgnoreStart
668-
KML($EPfx . 'access error.', 3);
669-
break;
670-
// @codeCoverageIgnoreEnd
741+
LoadedString($tmp2)
742+
|| $this->baseFKeyExists($Cval)
743+
){
744+
$sql = "ALTER TABLE $val DROP $tmp $tmp2$Cval";
745+
DumpSQL($sql, 3);
746+
$rs = $this->DB->Execute($sql);
747+
if(
748+
$rs != false && $this->baseErrorMessage() == ''
749+
){ // Error Check
750+
$rs->Close();
751+
KML($EPfx . 'RI disabled.', 3);
752+
}else{ // Transient DB Error.
753+
// @codeCoverageIgnoreStart
754+
KML($EPfx . 'access error.', 3);
755+
break;
756+
// @codeCoverageIgnoreEnd
757+
}
671758
}
672759
}
673760
}
@@ -687,6 +774,60 @@ function baseGetRI ( ){
687774
return $Ret;
688775
}
689776

777+
function baseFKeyExists( $key = '' ){
778+
// Returns true if RI is enabled and the RI Foreign Key exists in the
779+
// DB structure, false otherwise.
780+
GLOBAL $use_referential_integrity, $BCR;
781+
$EMPfx = __FUNCTION__ . ': ';
782+
$Ret = false; // Return Value
783+
$RIF = false; // Referential Integrity Flag.
784+
// @codeCoverageIgnoreStart
785+
if( isset($BCR) && is_object($BCR) ){
786+
$RIF = $BCR->GetCap('BASE_SSRI');
787+
}else{
788+
if( intval($use_referential_integrity) == 1 ){
789+
$RIF = true;
790+
}
791+
}
792+
// @codeCoverageIgnoreEnd
793+
if( $RIF && $this->baseisDBUp(true) && LoadedString($key) ){
794+
$SE = false; // Step Execution Flag Assume Failure.
795+
$sqlPfx = 'SELECT ';
796+
$sqlIS = 'information_schema';
797+
$SSfx = 'SCHEMA';
798+
if( $this->DB_type == 'postgres' ){
799+
$SSfx = 'CATALOG';
800+
}
801+
$sql = $sqlPfx . 'CONSTRAINT_NAME, TABLE_NAME FROM '. $sqlIS
802+
. '.table_constraints WHERE '
803+
. "CONSTRAINT_$SSfx = '" . $this->DB_name
804+
. "' AND CONSTRAINT_TYPE = 'FOREIGN KEY'";
805+
DumpSQL($sql, 3);
806+
$rs = $this->DB->Execute($sql);
807+
if(
808+
$rs != false && $this->baseErrorMessage() == ''
809+
&& $rs->RecordCount() == DB_RICC
810+
){ // Error Check
811+
while( !$rs->EOF ){
812+
$myrow = $rs->fields;
813+
if( $myrow[0] == $key ){
814+
$SE = true; // Key Exists.
815+
break;
816+
}
817+
$rs->MoveNext();
818+
}
819+
$rs->Close();
820+
}else{ // Transient DB Error.
821+
// @codeCoverageIgnoreStart
822+
KML($EPfx . 'access error.', 3);
823+
$SE = false; // Failure
824+
// @codeCoverageIgnoreEnd
825+
}
826+
$Ret = $SE;
827+
}
828+
return $Ret;
829+
}
830+
690831
function baseTSE( $table = '' ){ // Get Table Storage Engine.
691832
$EMPfx = __FUNCTION__ . ': ';
692833
$Ret = '';

tests/php/iconstantsTest.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ public function testContents() {
3939
// DB connection method
4040
ValidateConst($this,"DB_CONNECT", 2);
4141
ValidateConst($this,"DB_PCONNECT", 1);
42+
ValidateConst($this,"DB_RICC", 8); // RI Constraint Count.
4243
// CleanVariable() Mask
4344
ValidateConst($this,"VAR_DIGIT", 1);
4445
ValidateConst($this,"VAR_LETTER", 2);

0 commit comments

Comments
 (0)