Search code examples
phpmysqlmysqlisignals

mysqli signal to php error


I have Mysql stored procedure, that in some cases give a signal error like this:

    CREATE DEFINER=`root`@`localhost` PROCEDURE `InsertAction`(IN `EmployerID` INT, IN `StoreFromID` INT, IN `StoreToID` INT, IN `StoreID` INT, IN `ProductID` INT, IN `Quantity` DECIMAL(10,2), IN `DualOperation` TINYINT, IN `inOrOut` TINYINT)
    LANGUAGE SQL
    NOT DETERMINISTIC
    CONTAINS SQL
    SQL SECURITY DEFINER
    COMMENT ''
BEGIN
    START TRANSACTION;
        SELECT @lastActionID;
        SELECT @lastTransferID;
        SELECT @retval;
        SELECT SUM(ad.Quantity) INTO @retVal FROM productin pri JOIN actiondetails ad ON ad.ID=pri.ID;
        IF DualOperation = 1
            THEN
                IF @retVal>Quantity
                    THEN
                        INSERT INTO Actions (EmployerID, StorehouseID, `Date`)
                            VALUES (EmployerID, StoreFromID, CURDATE());
                        SET @lastActionID = (SELECT ID FROM Actions ORDER BY ID DESC LIMIT 1);
                        INSERT INTO ProductTransfer (ID, TransferType)
                            VALUES (@lastActionID, 0);

                        INSERT INTO ActionDetails (ID,ProductID, Quantity)
                            VALUES (@lastActionID, ProductID, Quantity);

                        SET @lastTransferID = (SELECT ID FROM ProductTransfer ORDER BY ID DESC LIMIT 1);
                        INSERT INTO Actions (EmployerID, StorehouseID, `Date`) VALUES (EmployerID, StoreToID, CURDATE());
                        SET @lastActionID = (SELECT ID FROM Actions ORDER BY ID DESC LIMIT 1);
                        INSERT INTO ProductTransfer (ID, TransferType, ParentID) VALUES (@lastActionID, 1, @lastTransferID);

                        INSERT INTO ActionDetails (ID,ProductID, Quantity)
                            VALUES (@lastActionID, ProductID, Quantity);
                    ELSE
                        SIGNAL SQLSTATE '45000'
                    SET MESSAGE_TEXT = 'Not enough materials';
            END IF;
        ELSE
                INSERT INTO Actions (EmployerID, StorehouseID, `Date`)
                    VALUES (EmployerID, StoreID, CURDATE());
                SET @lastActionID = (SELECT ID FROM Actions ORDER BY ID DESC LIMIT 1);
                INSERT INTO ActionDetails (ID, ProductID, Quantity)
                    VALUES (@lastActionID, ProductID, Quantity);
                IF InOrOut = 0
                    THEN
                        INSERT INTO ProductIn (ID, OrganizationID) values (@lastActionID, NULL);
                    ELSE
                        IF @retVal>Quantity
                            THEN
                                INSERT INTO ProductOut (ID, OrganizationID) values (@lastActionID, NULL);
                            ELSE
                                SIGNAL SQLSTATE '45000'
                            SET MESSAGE_TEXT = 'Not enough materials';
                    END IF;
                END IF;
        END IF;
    COMMIT;
END

When i run this code through Mysql query everything seems to be working just fine. it gives a signal of "not enough materials" IF @retVal<=Quantity and no records are inserted(works as it should be)... But when i call this procedure from PHP it simply doesn't give any error. none of rows are inserted but i cant get notification that the oppreration failed... here is php code:

$mysqli->query("CALL `InsertAction`('6', '1', '2', '0', '13', '431243241', '1', '0')");

the $mysqli->sqlstate gives 0000. how should i understand the procedure was done or got signal?

so what i really want is, if @retVal<=Quantity then give php exception. and this code prints "string" out:

try {
$mysqli->query("CALL `InsertAction`(6, 1, 2, 0, 13, 431243241, 1, 0)");
}
catch (Exception $e){
    echo "string";
}

Solution

  • The real problem in the code above is that variables are not Declared. so i changed this Select statements to Declare statements.

    BEGIN
    DECLARE lastActionID INT unsigned;
    DECLARE lastTransferID INT unsigned;
    DECLARE retval INT unsigned;
        START TRANSACTION;
            SELECT SUM(ad.Quantity) INTO retVal FROM productin pri JOIN actiondetails ad ON ad.ID=pri.ID;
            IF DualOperation = 1
                THEN
                    IF retVal>Quantity
                        THEN
                            INSERT INTO Actions (EmployerID, StorehouseID, `Date`)
                                VALUES (EmployerID, StoreFromID, CURDATE());
                            SET lastActionID = (SELECT ID FROM Actions ORDER BY ID DESC LIMIT 1);
                            INSERT INTO ProductTransfer (ID, TransferType)
                                VALUES (lastActionID, 0);
    
                            INSERT INTO ActionDetails (ID, ProductID, Quantity)
                                VALUES (lastActionID, ProductID, Quantity);
    
                            SET lastTransferID = (SELECT ID FROM ProductTransfer ORDER BY ID DESC LIMIT 1);
                            INSERT INTO Actions (EmployerID, StorehouseID, `Date`) VALUES (EmployerID, StoreToID, CURDATE());
                            SET lastActionID = (SELECT ID FROM Actions ORDER BY ID DESC LIMIT 1);
                            INSERT INTO ProductTransfer (ID, TransferType, ParentID) VALUES (lastActionID, 1, lastTransferID);
    
                            INSERT INTO ActionDetails (ID,ProductID, Quantity)
                                VALUES (lastActionID, ProductID, Quantity);
                        ELSE
                            SIGNAL SQLSTATE '45000'
                        SET MESSAGE_TEXT = 'Not enough materials';
                END IF;
            ELSE
                    INSERT INTO Actions (EmployerID, StorehouseID, `Date`)
                        VALUES (EmployerID, StoreID, CURDATE());
                    SET @lastActionID = (SELECT ID FROM Actions ORDER BY ID DESC LIMIT 1);
                    INSERT INTO ActionDetails (ID, ProductID, Quantity)
                        VALUES (lastActionID, ProductID, Quantity);
                    IF InOrOut = 0
                        THEN
                            INSERT INTO ProductIn (ID, OrganizationID) values (lastActionID, NULL);
                        ELSE
                            IF retVal>Quantity
                                THEN
                                    INSERT INTO ProductOut (ID, OrganizationID) values (lastActionID, NULL);
                                ELSE
                                    SIGNAL SQLSTATE '45000'
                                SET MESSAGE_TEXT = 'Not enough materials';
                        END IF;
                    END IF;
            END IF;
        COMMIT;
        select true;
    END
    

    now i am able to get $mysqli->sqlstate 45000 and check whether there was an error in procedure