Skip to content

Commit

Permalink
Reporting %TYPE syntax for type names in the Function and Procedure o…
Browse files Browse the repository at this point in the history
…bjects (#2004)

Reporting the %TYPE syntax issues in FUNCTION and PROCEDURE objects in Variable declaration, function parameters, and return type of function.
Added tests in the analyze and assessment test.
  • Loading branch information
priyanshi-yb authored Dec 4, 2024
1 parent d46d4fa commit 995f770
Show file tree
Hide file tree
Showing 14 changed files with 1,393 additions and 42 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -87,4 +87,90 @@ BEGIN
SELECT * FROM employees e WHERE e.xmax = (SELECT MAX(xmax) FROM employees WHERE department = e.department);

END;
$$;
$$;

CREATE FUNCTION public.get_employeee_salary(emp_id integer) RETURNS numeric
LANGUAGE plpgsql
AS $$
DECLARE
emp_salary employees.salary%TYPE; -- Declare a variable with the same type as employees.salary
BEGIN
SELECT salary INTO emp_salary
FROM employees
WHERE employee_id = emp_id;
RETURN emp_salary;
END;
$$;

CREATE OR REPLACE FUNCTION calculate_tax(salary_amount NUMERIC) RETURNS NUMERIC AS $$
DECLARE
tax_rate employees.tax_rate%TYPE; -- Inherits type from employees.tax_rate column
tax_amount NUMERIC;
BEGIN
-- Assign a value to the variable
SELECT tax_rate INTO tax_rate FROM employees WHERE id = 1;

-- Use the variable in a calculation
tax_amount := salary_amount * tax_rate;
RETURN tax_amount;
END;
$$ LANGUAGE plpgsql;

CREATE OR REPLACE FUNCTION log_salary_change() RETURNS TRIGGER AS $$
DECLARE
old_salary employees.salary%TYPE; -- Matches the type of the salary column
new_salary employees.salary%TYPE;
BEGIN
old_salary := OLD.salary;
new_salary := NEW.salary;

IF new_salary <> old_salary THEN
INSERT INTO salary_log(employee_id, old_salary, new_salary, changed_at)
VALUES (NEW.id, old_salary, new_salary, now());
END IF;

RETURN NEW;
END;
$$ LANGUAGE plpgsql;

CREATE TRIGGER salary_update_trigger
AFTER UPDATE OF salary ON employees
FOR EACH ROW EXECUTE FUNCTION log_salary_change();

CREATE OR REPLACE FUNCTION get_employee_details(emp_id employees.id%Type)
RETURNS public.employees.name%Type AS $$
DECLARE
employee_name employees.name%TYPE;
BEGIN
SELECT name INTO employee_name FROM employees WHERE id = emp_id;
RETURN employee_name;
END;
$$ LANGUAGE plpgsql;


CREATE OR REPLACE FUNCTION list_high_earners(threshold NUMERIC) RETURNS VOID AS $$
DECLARE
emp_name employees.name%TYPE;
emp_salary employees.salary%TYPE;
BEGIN
FOR emp_name, emp_salary IN
SELECT name, salary FROM employees WHERE salary > threshold
LOOP
RAISE NOTICE 'Employee: %, Salary: %', emp_name, emp_salary;
END LOOP;
END;
$$ LANGUAGE plpgsql;


CREATE OR REPLACE FUNCTION copy_high_earners(threshold NUMERIC) RETURNS VOID AS $$
DECLARE
temp_salary employees.salary%TYPE;
BEGIN
CREATE TEMP TABLE temp_high_earners AS
SELECT * FROM employees WHERE salary > threshold;

FOR temp_salary IN SELECT salary FROM temp_high_earners LOOP
RAISE NOTICE 'High earner salary: %', temp_salary;
END LOOP;
END;
$$ LANGUAGE plpgsql;
Original file line number Diff line number Diff line change
Expand Up @@ -149,3 +149,27 @@ BEGIN
RAISE NOTICE 'Employee % of age % added successfully.', emp_name, emp_age;
END;
$$;

CREATE OR REPLACE PROCEDURE update_salary(emp_id INT, increment NUMERIC) AS $$
DECLARE
current_salary employees.salary%TYPE; -- Matches the type of the salary column
BEGIN
SELECT salary INTO current_salary FROM employees WHERE id = emp_id;

IF current_salary IS NULL THEN
RAISE NOTICE 'Employee ID % does not exist.', emp_id;
ELSE
UPDATE employees SET salary = current_salary + increment WHERE id = emp_id;
END IF;
END;
$$ LANGUAGE plpgsql;


CREATE OR REPLACE PROCEDURE get_employee_details_proc(emp_id employees.id%Type, salary employees.salary%TYPE, tax_rate numeric) AS $$
DECLARE
employee_name employees.name%TYPE;
BEGIN
SELECT name INTO employee_name FROM employees e WHERE e.id = emp_id and e.salary = salary and e.tax_rate = tax_rate;

END;
$$ LANGUAGE plpgsql;
140 changes: 140 additions & 0 deletions migtests/tests/analyze-schema/expected_issues.json
Original file line number Diff line number Diff line change
Expand Up @@ -1584,5 +1584,145 @@
"Suggestion": "",
"GH": "",
"DocsLink": "https://docs.yugabyte.com/preview/yugabyte-voyager/known-issues/postgresql/#system-columns-is-not-yet-supported"
},
{
"IssueType": "unsupported_plpgsql_objects",
"ObjectType": "FUNCTION",
"ObjectName": "public.get_employeee_salary",
"Reason": "Referenced type declaration of variables",
"SqlStatement": "employees.salary%TYPE",
"Suggestion": "Fix the syntax to include the actual type name instead of referencing the type of a column",
"GH": "https://github.com/yugabyte/yugabyte-db/issues/23619",
"DocsLink": "https://docs.yugabyte.com/preview/yugabyte-voyager/known-issues/postgresql/#type-syntax-is-not-supported"
},
{
"IssueType": "unsupported_plpgsql_objects",
"ObjectType": "FUNCTION",
"ObjectName": "calculate_tax",
"Reason": "Referenced type declaration of variables",
"SqlStatement": "employees.tax_rate%TYPE",
"Suggestion": "Fix the syntax to include the actual type name instead of referencing the type of a column",
"GH": "https://github.com/yugabyte/yugabyte-db/issues/23619",
"DocsLink": "https://docs.yugabyte.com/preview/yugabyte-voyager/known-issues/postgresql/#type-syntax-is-not-supported"
},
{
"IssueType": "unsupported_plpgsql_objects",
"ObjectType": "FUNCTION",
"ObjectName": "log_salary_change",
"Reason": "Referenced type declaration of variables",
"SqlStatement": "employees.salary%TYPE",
"Suggestion": "Fix the syntax to include the actual type name instead of referencing the type of a column",
"GH": "https://github.com/yugabyte/yugabyte-db/issues/23619",
"DocsLink": "https://docs.yugabyte.com/preview/yugabyte-voyager/known-issues/postgresql/#type-syntax-is-not-supported"
},
{
"IssueType": "unsupported_plpgsql_objects",
"ObjectType": "FUNCTION",
"ObjectName": "log_salary_change",
"Reason": "Referenced type declaration of variables",
"SqlStatement": "employees.salary%TYPE",
"Suggestion": "Fix the syntax to include the actual type name instead of referencing the type of a column",
"GH": "https://github.com/yugabyte/yugabyte-db/issues/23619",
"DocsLink": "https://docs.yugabyte.com/preview/yugabyte-voyager/known-issues/postgresql/#type-syntax-is-not-supported"
},
{
"IssueType": "unsupported_plpgsql_objects",
"ObjectType": "FUNCTION",
"ObjectName": "get_employee_details",
"Reason": "Referenced type declaration of variables",
"SqlStatement": "employees.name%TYPE",
"Suggestion": "Fix the syntax to include the actual type name instead of referencing the type of a column",
"GH": "https://github.com/yugabyte/yugabyte-db/issues/23619",
"DocsLink": "https://docs.yugabyte.com/preview/yugabyte-voyager/known-issues/postgresql/#type-syntax-is-not-supported"
},
{
"IssueType": "unsupported_plpgsql_objects",
"ObjectType": "FUNCTION",
"ObjectName": "get_employee_details",
"Reason": "Referenced type declaration of variables",
"SqlStatement": "employees.id%TYPE",
"Suggestion": "Fix the syntax to include the actual type name instead of referencing the type of a column",
"GH": "https://github.com/yugabyte/yugabyte-db/issues/23619",
"DocsLink": "https://docs.yugabyte.com/preview/yugabyte-voyager/known-issues/postgresql/#type-syntax-is-not-supported"
},
{
"IssueType": "unsupported_plpgsql_objects",
"ObjectType": "FUNCTION",
"ObjectName": "list_high_earners",
"Reason": "Referenced type declaration of variables",
"SqlStatement": "employees.name%TYPE",
"Suggestion": "Fix the syntax to include the actual type name instead of referencing the type of a column",
"GH": "https://github.com/yugabyte/yugabyte-db/issues/23619",
"DocsLink": "https://docs.yugabyte.com/preview/yugabyte-voyager/known-issues/postgresql/#type-syntax-is-not-supported"
},
{
"IssueType": "unsupported_plpgsql_objects",
"ObjectType": "FUNCTION",
"ObjectName": "list_high_earners",
"Reason": "Referenced type declaration of variables",
"SqlStatement": "employees.salary%TYPE",
"Suggestion": "Fix the syntax to include the actual type name instead of referencing the type of a column",
"GH": "https://github.com/yugabyte/yugabyte-db/issues/23619",
"DocsLink": "https://docs.yugabyte.com/preview/yugabyte-voyager/known-issues/postgresql/#type-syntax-is-not-supported"
},
{
"IssueType": "unsupported_plpgsql_objects",
"ObjectType": "FUNCTION",
"ObjectName": "copy_high_earners",
"Reason": "Referenced type declaration of variables",
"SqlStatement": "employees.salary%TYPE",
"Suggestion": "Fix the syntax to include the actual type name instead of referencing the type of a column",
"GH": "https://github.com/yugabyte/yugabyte-db/issues/23619",
"DocsLink": "https://docs.yugabyte.com/preview/yugabyte-voyager/known-issues/postgresql/#type-syntax-is-not-supported"
},
{
"IssueType": "unsupported_plpgsql_objects",
"ObjectType": "PROCEDURE",
"ObjectName": "update_salary",
"Reason": "Referenced type declaration of variables",
"SqlStatement": "employees.salary%TYPE",
"Suggestion": "Fix the syntax to include the actual type name instead of referencing the type of a column",
"GH": "https://github.com/yugabyte/yugabyte-db/issues/23619",
"DocsLink": "https://docs.yugabyte.com/preview/yugabyte-voyager/known-issues/postgresql/#type-syntax-is-not-supported"
},
{
"IssueType": "unsupported_plpgsql_objects",
"ObjectType": "PROCEDURE",
"ObjectName": "get_employee_details_proc",
"Reason": "Referenced type declaration of variables",
"SqlStatement": "employees.name%TYPE",
"Suggestion": "Fix the syntax to include the actual type name instead of referencing the type of a column",
"GH": "https://github.com/yugabyte/yugabyte-db/issues/23619",
"DocsLink": "https://docs.yugabyte.com/preview/yugabyte-voyager/known-issues/postgresql/#type-syntax-is-not-supported"
},
{
"IssueType": "unsupported_plpgsql_objects",
"ObjectType": "PROCEDURE",
"ObjectName": "get_employee_details_proc",
"Reason": "Referenced type declaration of variables",
"SqlStatement": "employees.id%TYPE",
"Suggestion": "Fix the syntax to include the actual type name instead of referencing the type of a column",
"GH": "https://github.com/yugabyte/yugabyte-db/issues/23619",
"DocsLink": "https://docs.yugabyte.com/preview/yugabyte-voyager/known-issues/postgresql/#type-syntax-is-not-supported"
},
{
"IssueType": "unsupported_plpgsql_objects",
"ObjectType": "PROCEDURE",
"ObjectName": "get_employee_details_proc",
"Reason": "Referenced type declaration of variables",
"SqlStatement": "employees.salary%TYPE",
"Suggestion": "Fix the syntax to include the actual type name instead of referencing the type of a column",
"GH": "https://github.com/yugabyte/yugabyte-db/issues/23619",
"DocsLink": "https://docs.yugabyte.com/preview/yugabyte-voyager/known-issues/postgresql/#type-syntax-is-not-supported"
},
{
"IssueType": "unsupported_plpgsql_objects",
"ObjectType": "FUNCTION",
"ObjectName": "get_employee_details",
"Reason": "Referenced type declaration of variables",
"SqlStatement": "public.employees.name%TYPE",
"Suggestion": "Fix the syntax to include the actual type name instead of referencing the type of a column",
"GH": "https://github.com/yugabyte/yugabyte-db/issues/23619",
"DocsLink": "https://docs.yugabyte.com/preview/yugabyte-voyager/known-issues/postgresql/#type-syntax-is-not-supported"
}
]
12 changes: 6 additions & 6 deletions migtests/tests/analyze-schema/summary.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,15 +36,15 @@
},
{
"ObjectType": "FUNCTION",
"TotalCount": 1,
"InvalidCount": 1,
"ObjectNames": "create_and_populate_tables"
"TotalCount": 7,
"InvalidCount": 7,
"ObjectNames": "create_and_populate_tables, public.get_employeee_salary, get_employee_details, calculate_tax, log_salary_change, list_high_earners, copy_high_earners"
},
{
"ObjectType": "PROCEDURE",
"TotalCount": 6,
"InvalidCount": 4,
"ObjectNames": "foo, foo1, sp_createnachabatch, test, test1, add_employee"
"TotalCount": 8,
"InvalidCount": 6,
"ObjectNames": "foo, foo1, sp_createnachabatch, test, get_employee_details_proc, test1, add_employee, update_salary"
},
{
"ObjectType": "VIEW",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,10 +55,9 @@
},
{
"ObjectType": "FUNCTION",
"TotalCount": 9,
"InvalidCount": 2,
"ObjectNames": "public.process_order, schema2.process_order, public.auditlogfunc, public.check_sales_region, public.prevent_update_shipped_without_date, public.total, schema2.auditlogfunc, schema2.prevent_update_shipped_without_date, schema2.total"
},
"TotalCount": 10,
"InvalidCount": 3,
"ObjectNames": "public.auditlogfunc, public.check_sales_region, public.prevent_update_shipped_without_date, public.process_combined_tbl, public.process_order, public.total, schema2.auditlogfunc, schema2.prevent_update_shipped_without_date, schema2.process_order, schema2.total" },
{
"ObjectType": "AGGREGATE",
"TotalCount": 2,
Expand All @@ -67,9 +66,9 @@
},
{
"ObjectType": "PROCEDURE",
"TotalCount": 2,
"InvalidCount": 0,
"ObjectNames": "public.tt_insert_data, schema2.tt_insert_data"
"TotalCount": 3,
"InvalidCount": 1,
"ObjectNames": "public.tt_insert_data, public.update_combined_tbl_data, schema2.tt_insert_data"
},
{
"ObjectType": "VIEW",
Expand Down Expand Up @@ -2131,6 +2130,22 @@
}
],
"UnsupportedPlPgSqlObjects": [
{
"FeatureName": "Referenced type declaration of variables",
"Objects": [
{
"ObjectType": "FUNCTION",
"ObjectName": "public.process_combined_tbl",
"SqlStatement": "public.combined_tbl.maddr%TYPE"
},
{
"ObjectType": "PROCEDURE",
"ObjectName": "public.update_combined_tbl_data",
"SqlStatement": "public.combined_tbl.maddr%TYPE"
}
],
"DocsLink": "https://docs.yugabyte.com/preview/yugabyte-voyager/known-issues/postgresql/#type-syntax-is-not-supported"
},
{
"FeatureName": "Advisory Locks",
"Objects": [
Expand Down
53 changes: 53 additions & 0 deletions migtests/tests/pg/assessment-report-test/pg_assessment_report.sql
Original file line number Diff line number Diff line change
Expand Up @@ -294,3 +294,56 @@ END;
$$ LANGUAGE plpgsql;

select process_order(1);

-- In PG migration from pg_dump the function parameters and return will never have the %TYPE syntax, instead they have the actual type in the DDLs
-- e.g. for the below function this will be the export one `CREATE FUNCTION public.process_combined_tbl(p_id integer, p_c cidr, p_bitt bit, p_inds3 interval) RETURNS macaddr`
CREATE OR REPLACE FUNCTION public.process_combined_tbl(
p_id public.combined_tbl.id%TYPE,
p_c public.combined_tbl.c%TYPE,
p_bitt public.combined_tbl.bitt%TYPE,
p_inds3 public.combined_tbl.inds3%TYPE
)
RETURNS public.combined_tbl.maddr%TYPE AS
$$
DECLARE
v_maddr public.combined_tbl.maddr%TYPE;
BEGIN
-- Example logic: Assigning local variable using passed-in parameter
v_maddr := p_c::text; -- Example conversion (cidr to macaddr), just for illustration

-- Processing the passed parameters
RAISE NOTICE 'Processing: ID = %, CIDR = %, BIT = %, Interval = %, MAC = %',
p_id, p_c, p_bitt, p_inds3, v_maddr;

-- Returning a value of the macaddr type (this could be more meaningful logic)
RETURN v_maddr; -- Returning a macaddr value
END;
$$ LANGUAGE plpgsql;

CREATE OR REPLACE PROCEDURE public.update_combined_tbl_data(
p_id public.combined_tbl.id%TYPE,
p_c public.combined_tbl.c%TYPE,
p_bitt public.combined_tbl.bitt%TYPE,
p_d public.combined_tbl.d%TYPE
)
AS
$$
DECLARE
v_new_mac public.combined_tbl.maddr%TYPE;
BEGIN
-- Example: Using a local variable to store a macaddr value (for illustration)
v_new_mac := '00:14:22:01:23:45'::macaddr;

-- Updating the table with provided parameters
UPDATE public.combined_tbl
SET
c = p_c, -- Updating cidr type column
bitt = p_bitt, -- Updating bit column
d = p_d, -- Updating daterange column
maddr = v_new_mac -- Using the local macaddr variable in update
WHERE id = p_id;

RAISE NOTICE 'Updated record with ID: %, CIDR: %, BIT: %, Date range: %',
p_id, p_c, p_bitt, p_d;
END;
$$ LANGUAGE plpgsql;
Loading

0 comments on commit 995f770

Please sign in to comment.