Skip to content

Commit

Permalink
Make NEWID() and NEWSEQUENTIALID() functions VOLATILE
Browse files Browse the repository at this point in the history
Altering a table to add a column with DEFAULT NEWID() makes
the values all the same value which is not the correct bheaviour.
This is because NEWID and NEWSEQUENTIALID are both STABLE when
then should be VOLATILE.

Task: BABEL-4923
Signed-off-by: Kristian Lejao <[email protected]>
  • Loading branch information
lejaokri committed May 2, 2024
1 parent b80c264 commit e48a8ec
Show file tree
Hide file tree
Showing 25 changed files with 1,480 additions and 45 deletions.
2 changes: 1 addition & 1 deletion contrib/babelfishpg_common/Version.config
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
BBFPGCMN_MAJOR_VERSION=2
BBFPGCMN_MINOR_VERSION=6
BBFPGCMN_MINOR_VERSION=7
BBFPGCMN_MICRO_VERSION=0

4 changes: 2 additions & 2 deletions contrib/babelfishpg_common/sql/uniqueidentifier.sql
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ CREATE TYPE sys.UNIQUEIDENTIFIER (
CREATE OR REPLACE FUNCTION sys.newid()
RETURNS sys.UNIQUEIDENTIFIER
AS 'uuid-ossp', 'uuid_generate_v4' -- uuid-ossp was added as dependency
LANGUAGE C STABLE STRICT PARALLEL SAFE;
LANGUAGE C VOLATILE STRICT PARALLEL SAFE;

/*
* in tsql, NEWSEQUENTIALID() produces a new unique value
Expand All @@ -47,7 +47,7 @@ LANGUAGE C STABLE STRICT PARALLEL SAFE;
CREATE OR REPLACE FUNCTION sys.NEWSEQUENTIALID()
RETURNS sys.UNIQUEIDENTIFIER
AS 'uuid-ossp', 'uuid_generate_v4'
LANGUAGE C STABLE STRICT PARALLEL SAFE;
LANGUAGE C VOLATILE STRICT PARALLEL SAFE;

CREATE FUNCTION sys.uniqueidentifiereq(sys.UNIQUEIDENTIFIER, sys.UNIQUEIDENTIFIER)
RETURNS bool
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
-- complain if script is sourced in psql, rather than via ALTER EXTENSION
\echo Use "ALTER EXTENSION ""babelfishpg_common"" UPDATE TO '2.7.0'" to load this file. \quit

SELECT set_config('search_path', 'sys, '||current_setting('search_path'), false);

ALTER FUNCTION sys.newid() VOLATILE;
ALTER FUNCTION sys.NEWSEQUENTIALID() VOLATILE;

-- Reset search_path to not affect any subsequent scripts
SELECT set_config('search_path', trim(leading 'sys, ' from current_setting('search_path')), false);
158 changes: 156 additions & 2 deletions test/JDBC/expected/BABEL-1858.out
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
-- tsql

USE master;
GO

Expand Down Expand Up @@ -31,18 +33,50 @@ int
~~END~~


TRUNCATE TABLE newid_volatile
GO


DECLARE @i INT = 1
DECLARE @num_iter INT = 5
WHILE @i <= @num_iter
BEGIN
INSERT INTO newid_volatile VALUES (NEWSEQUENTIALID())
SET @i = @i + 1
END
-- should be equal to @num_iter
select count(distinct u) from newid_volatile
go
~~ROW COUNT: 1~~

~~ROW COUNT: 1~~

~~ROW COUNT: 1~~

~~ROW COUNT: 1~~

~~ROW COUNT: 1~~

~~START~~
int
5
~~END~~


-- test volatility of function in procedure
-- should see different id values with each iteration
CREATE PROC p_newid AS
DECLARE @num_iter INT = 5
DECLARE @i INT = 1
CREATE TABLE newid_volatile_proc (u uniqueidentifier)
CREATE TABLE newid_volatile_proc (u uniqueidentifier, v uniqueidentifier)
WHILE @i <= @num_iter
BEGIN
INSERT INTO newid_volatile_proc VALUES (NEWID())
INSERT INTO newid_volatile_proc VALUES (NEWID(), NEWSEQUENTIALID())
SET @i = @i + 1
END
go


EXEC p_newid
-- should be equal to @num_iter
select count(distinct u) from newid_volatile_proc
Expand All @@ -63,8 +97,128 @@ int
~~END~~


select count(distinct v) from newid_volatile_proc
GO
~~START~~
int
5
~~END~~


DROP TABLE newid_volatile
DROP TABLE newid_volatile_proc
DROP PROCEDURE p_newid
GO

-- Add alter table coverage
CREATE TABLE TestNewId(
id INT,
name VARCHAR(32)
)
GO

insert into TestNewId values(1, 'aaa')
insert into TestNewId values(2, 'bbb')
insert into TestNewId values(3, 'ccc')
GO
~~ROW COUNT: 1~~

~~ROW COUNT: 1~~

~~ROW COUNT: 1~~


-- should be successful
ALTER TABLE TestNewId ADD uuid UNIQUEIDENTIFIER NOT NULL DEFAULT NEWID() PRIMARY KEY;
GO

INSERT INTO TestNewId SELECT generate_series(1, 1000, 1), 'hello', NEWID()
GO
~~ROW COUNT: 1000~~


-- should be 1000+3
SELECT COUNT(DISTINCT uuid) FROM TestNewId
GO
~~START~~
int
1003
~~END~~


-- psql
ANALYZE master_dbo.TestNewId
GO

-- tsql

select set_config('babelfishpg_tsql.explain_costs', 'off', false);
GO
~~START~~
text
off
~~END~~


-- cannot use indexscan with volatile anymore
SET BABELFISH_SHOWPLAN_ALL ON
SELECT * FROM TestNewId WHERE uuid=NEWID()
GO
~~START~~
text
Query Text: SELECT * FROM TestNewId WHERE uuid=NEWID()
Seq Scan on testnewid
Filter: (uuid = newid())
~~END~~


SET BABELFISH_SHOWPLAN_ALL OFF
GO

-- Repeat with NEWSEQUENTIALID instead of NEWID
ALTER TABLE TestNewId DROP COLUMN uuid
GO

ALTER TABLE TestNewId ADD uuid UNIQUEIDENTIFIER NOT NULL DEFAULT NEWSEQUENTIALID() PRIMARY KEY;
GO

-- psql
ANALYZE master_dbo.TestNewId
GO


-- tsql
select set_config('babelfishpg_tsql.explain_costs', 'off', false);
GO
~~START~~
text
off
~~END~~


-- cannot use indexscan with volatile anymore
SET BABELFISH_SHOWPLAN_ALL ON
SELECT * FROM TestNewId WHERE uuid=NEWID()
GO
~~START~~
text
Query Text: SELECT * FROM TestNewId WHERE uuid=NEWID()
Seq Scan on testnewid
Filter: (uuid = newid())
~~END~~


SET BABELFISH_SHOWPLAN_ALL OFF
GO

-- should still be 1003
SELECT COUNT(DISTINCT uuid) FROM TestNewId
GO
~~START~~
int
1003
~~END~~


DROP TABLE TestNewId
GO
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@

DROP PROC babel_4923_newid_proc
DROP PROC babel_4923_newid_proc_2
GO

DROP TABLE babel_4923_newid_tab2
DROP TABLE babel_4923_newid_tab3
DROP TABLE babel_4923_newid_tab4
GO
Loading

0 comments on commit e48a8ec

Please sign in to comment.