Search code examples
algorithmmatrixmultidimensional-arrayplpgsqlmatrix-multiplication

Getting the error "ERROR: array subscript out of range" when multiplying matrices PL/pgSQL?


I'm traiying to code, as exercise, a PL/pgSQL function that multiplies two matrices then print the solution when called. I'm new in this language and can't find what's wrong with the code. Help!

CREATE OR REPLACE FUNCTION multiplicarMatrizes(matriz1 float[][], matriz2 float[][], OUT produto float[][]) AS
$$
DECLARE
    i integer;
    j integer;
    k integer;
BEGIN
    
    IF array_length(matriz1, 1) <> array_length(matriz2, 2) THEN
        RAISE EXCEPTION 'O número de linhas da matriz 1 deve ser igual ao número de colunas da matriz 2';
    END IF;

    FOR i IN 1..array_length(matriz1, 1) LOOP
        FOR j IN 1..array_length(matriz2, 2) LOOP
            FOR k IN 1..array_length(matriz1, 1) LOOP
                produto[i][j] = produto[i][j] + matriz1[i][k] * matriz2[k][j];
            END LOOP;
        END LOOP;
    END LOOP;

END;
$$ language plpgsql;


SELECT multiplicarMatrizes('{{1.0,2.0}, {2.0,1.0}}', '{{1.0,0.0},{0.0,1.0}}'); // CALLING THE FUNCTION

As result, I'm getting the error:

[44:1] Failed in 0 s.
[Exception, Error code 0, SQLState 2202E] ERROR: array subscript out of range
  Onde: função PL/pgSQL multiplicarmatrizes(double precision[],double precision[]) linha 15 em atribuição
  Line 44, column 1

Can anyone help, please?!


Solution

  • PostgreSQL doesn't supports resize of multidimensional array when you modify one valule. Initially produto is empty array, so any change of this output variable should to fail. You need to initialize space of array by function array_fill

    More - default value of any variable is NULL, and NULL + anything is NULL again.

    CREATE OR REPLACE FUNCTION multiplicarMatrizes(matriz1 float[][],
                                                   matriz2 float[][],
                                                   OUT produto float[][]) AS
    $$
    DECLARE
        i integer;
        j integer;
        k integer;
    BEGIN
        
        IF array_length(matriz1, 1) <> array_length(matriz2, 2) THEN
            RAISE EXCEPTION 'O número de linhas da matriz 1 deve ser igual ao número de colunas da matriz 2';
        END IF;
    
        produto := array_fill(0, ARRAY[array_length(matriz1, 1), array_length(matriz2, 2)]);
    
        FOR i IN 1..array_length(matriz1, 1)
        LOOP
            FOR j IN 1..array_length(matriz2, 2)
            LOOP
                FOR k IN 1..array_length(matriz1, 1)
                LOOP
                    produto[i][j] := produto[i][j] + matriz1[i][k] * matriz2[k][j];
                END LOOP;
            END LOOP;
        END LOOP;
    END;
    $$ language plpgsql;