Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
P
Postgres FD Implementation
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Abuhujair Javed
Postgres FD Implementation
Commits
b65cd562
Commit
b65cd562
authored
Jan 10, 2003
by
Peter Eisentraut
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Read-only transactions, as defined in SQL.
parent
b7ca9bdf
Changes
16
Hide whitespace changes
Inline
Side-by-side
Showing
16 changed files
with
427 additions
and
146 deletions
+427
-146
doc/src/sgml/features.sgml
doc/src/sgml/features.sgml
+14
-14
doc/src/sgml/ref/set_transaction.sgml
doc/src/sgml/ref/set_transaction.sgml
+47
-23
doc/src/sgml/ref/start_transaction.sgml
doc/src/sgml/ref/start_transaction.sgml
+12
-41
doc/src/sgml/release.sgml
doc/src/sgml/release.sgml
+2
-1
src/backend/access/transam/xact.c
src/backend/access/transam/xact.c
+5
-1
src/backend/catalog/namespace.c
src/backend/catalog/namespace.c
+25
-1
src/backend/commands/copy.c
src/backend/commands/copy.c
+5
-1
src/backend/executor/execMain.c
src/backend/executor/execMain.c
+49
-1
src/backend/parser/gram.y
src/backend/parser/gram.y
+54
-33
src/backend/tcop/utility.c
src/backend/tcop/utility.c
+115
-10
src/backend/utils/misc/guc.c
src/backend/utils/misc/guc.c
+14
-4
src/bin/psql/tab-complete.c
src/bin/psql/tab-complete.c
+30
-14
src/include/access/xact.h
src/include/access/xact.h
+4
-1
src/include/catalog/namespace.h
src/include/catalog/namespace.h
+2
-1
src/test/regress/expected/transactions.out
src/test/regress/expected/transactions.out
+28
-0
src/test/regress/sql/transactions.sql
src/test/regress/sql/transactions.sql
+21
-0
No files found.
doc/src/sgml/features.sgml
View file @
b65cd562
<!--
$Header: /cvsroot/pgsql/doc/src/sgml/features.sgml,v 2.1
3 2003/01/10 11:02:41
petere Exp $
$Header: /cvsroot/pgsql/doc/src/sgml/features.sgml,v 2.1
4 2003/01/10 22:03:26
petere Exp $
-->
<appendix id="features">
...
...
@@ -642,6 +642,12 @@ $Header: /cvsroot/pgsql/doc/src/sgml/features.sgml,v 2.13 2003/01/10 11:02:41 pe
<entry>ROLLBACK statement</entry>
<entry></entry>
</row>
<row>
<entry>E152</entry>
<entry>Core</entry>
<entry>Basic SET TRANSACTION statement</entry>
<entry></entry>
</row>
<row>
<entry>E152-01</entry>
<entry>Core</entry>
...
...
@@ -649,6 +655,13 @@ $Header: /cvsroot/pgsql/doc/src/sgml/features.sgml,v 2.13 2003/01/10 11:02:41 pe
clause</entry>
<entry></entry>
</row>
<row>
<entry>E152-02</entry>
<entry>Core</entry>
<entry>SET TRANSACTION statement: READ ONLY and READ WRITE
clauses</entry>
<entry></entry>
</row>
<row>
<entry>E161</entry>
<entry>Core</entry>
...
...
@@ -1598,19 +1611,6 @@ $Header: /cvsroot/pgsql/doc/src/sgml/features.sgml,v 2.13 2003/01/10 11:02:41 pe
<entry>WITH HOLD cursors</entry>
<entry>Cursor to stay open across transactions</entry>
</row>
<row>
<entry>E152</entry>
<entry>Core</entry>
<entry>Basic SET TRANSACTION statement</entry>
<entry></entry>
</row>
<row>
<entry>E152-02</entry>
<entry>Core</entry>
<entry>SET TRANSACTION statement: READ ONLY and READ WRITE
clauses</entry>
<entry>Syntax accepted; READ ONLY not supported</entry>
</row>
<row>
<entry>E153</entry>
<entry>Core</entry>
...
...
doc/src/sgml/ref/set_transaction.sgml
View file @
b65cd562
<!-- $Header: /cvsroot/pgsql/doc/src/sgml/ref/set_transaction.sgml,v 1.
9 2002/08/04 04:31:44 momjian
Exp $ -->
<!-- $Header: /cvsroot/pgsql/doc/src/sgml/ref/set_transaction.sgml,v 1.
10 2003/01/10 22:03:27 petere
Exp $ -->
<refentry id="SQL-SET-TRANSACTION">
<docinfo>
<date>2000-11-24</date>
...
...
@@ -16,9 +16,10 @@
<refsynopsisdiv>
<synopsis>
SET TRANSACTION ISOLATION LEVEL { READ COMMITTED | SERIALIZABLE }
SET SESSION CHARACTERISTICS AS TRANSACTION ISOLATION LEVEL
{ READ COMMITTED | SERIALIZABLE }
SET TRANSACTION
[ ISOLATION LEVEL { READ COMMITTED | SERIALIZABLE } ] [ READ WRITE | READ ONLY ]
SET SESSION CHARACTERISTICS AS TRANSACTION
[ ISOLATION LEVEL { READ COMMITTED | SERIALIZABLE } ] [ READ WRITE | READ ONLY ]
</synopsis>
</refsynopsisdiv>
...
...
@@ -26,17 +27,19 @@ SET SESSION CHARACTERISTICS AS TRANSACTION ISOLATION LEVEL
<title>Description</title>
<para>
This command sets the transaction isolation level. The
<command>SET TRANSACTION</command> command sets the characteristics
for the current SQL-transaction. It has no effect on any subsequent
transactions. This command cannot be used after the first query or data-modification
statement (<command>SELECT</command>, <command>INSERT</command>,
<command>DELETE</command>, <command>UPDATE</command>,
<command>FETCH</command>, <command>COPY</command>) of a transaction
has been executed. <command>SET SESSION CHARACTERISTICS</command>
sets the default transaction isolation level for each transaction
for a session. <command>SET TRANSACTION</command> can override it
for an individual transaction.
The <command>SET TRANSACTION</command> command sets the transaction
characteristics of the current SQL-transaction. It has no effect on
any subsequent transactions. <command>SET SESSION
CHARACTERISTICS</command> sets the default transaction
characteristics for each transaction of a session. <command>SET
TRANSACTION</command> can override it for an individual
transaction.
</para>
<para>
The available transaction characteristics are the transaction
isolation level and the transaction access mode (read/write or
read-only).
</para>
<para>
...
...
@@ -45,7 +48,7 @@ SET SESSION CHARACTERISTICS AS TRANSACTION ISOLATION LEVEL
<variablelist>
<varlistentry>
<term>
READ COMMITTED
</term>
<term>
<literal>READ COMMITTED<literal>
</term>
<listitem>
<para>
A statement can only see rows committed before it began. This
...
...
@@ -55,7 +58,7 @@ SET SESSION CHARACTERISTICS AS TRANSACTION ISOLATION LEVEL
</varlistentry>
<varlistentry>
<term>
SERIALIZABLE
</term>
<term>
<literal>SERIALIZABLE</literal>
</term>
<listitem>
<para>
The current transaction can only see rows committed before
...
...
@@ -72,6 +75,28 @@ SET SESSION CHARACTERISTICS AS TRANSACTION ISOLATION LEVEL
</listitem>
</varlistentry>
</variablelist>
The transaction isolation level cannot be set after the first query
or data-modification statement (<command>SELECT</command>,
<command>INSERT</command>, <command>DELETE</command>,
<command>UPDATE</command>, <command>FETCH</command>,
<command>COPY</command>) of a transaction has been executed.
</para>
<para>
The transaction access mode determines whether the transaction is
read/write or read-only. Read/write is the default. When a
transaction is read-only, the following SQL commands are
disallowed: <literal>INSERT</literal>, <literal>UPDATE</literal>,
<literal>DELETE</literal>, and <literal>COPY TO</literal> if the
table they would write to is not a temporary table; all
<literal>CREATE</literal>, <literal>ALTER</literal>, and
<literal>DROP</literal> commands; <literal>COMMENT</literal>,
<literal>GRANT</literal>, <literal>REVOKE</literal>,
<literal>TRUNCATE</literal>; and <literal>EXPLAIN ANALYZE</literal>
and <literal>EXECUTE</literal> if the command they would execute is
among those listed. This is a high-level notion of read-only that
does not prevent writes to disk.
</para>
</refsect1>
...
...
@@ -97,7 +122,7 @@ SET default_transaction_isolation = '<replaceable>value</replaceable>'
<title>SQL92, SQL99</title>
<para>
<option>SERIALIZABLE</option> is the default level in
<option>SERIALIZABLE</option> is the default
transaction isolation
level in
<acronym>SQL</acronym>. <productname>PostgreSQL</productname> does
not provide the isolation levels <option>READ UNCOMMITTED</option>
and <option>REPEATABLE READ</option>. Because of multiversion
...
...
@@ -107,11 +132,10 @@ SET default_transaction_isolation = '<replaceable>value</replaceable>'
</para>
<para>
In <acronym>SQL</acronym> there are two other transaction
characteristics that can be set with these commands: whether the
transaction is read-only and the size of the diagnostics area.
Neither of these concepts are supported in
<productname>PostgreSQL</productname>.
In <acronym>SQL</acronym> there is one other transaction
characteristic that can be set with these commands: the size of
the diagnostics area. This concept is not supported in
<productname>PostgreSQL</productname>.
</para>
</refsect2>
</refsect1>
...
...
doc/src/sgml/ref/start_transaction.sgml
View file @
b65cd562
<!--
$Header: /cvsroot/pgsql/doc/src/sgml/ref/start_transaction.sgml,v 1.
3 2002/08/30 22:45:25 tgl
Exp $
$Header: /cvsroot/pgsql/doc/src/sgml/ref/start_transaction.sgml,v 1.
4 2003/01/10 22:03:27 petere
Exp $
PostgreSQL documentation
-->
...
...
@@ -20,7 +20,7 @@ PostgreSQL documentation
<refsynopsisdiv>
<synopsis>
START TRANSACTION [ ISOLATION LEVEL { READ COMMITTED | SERIALIZABLE } ]
START TRANSACTION [ ISOLATION LEVEL { READ COMMITTED | SERIALIZABLE } ]
[ READ WRITE | READ ONLY ]
</synopsis>
<refsect2 id="R2-SQL-START-TRANSACTION-1">
...
...
@@ -77,52 +77,23 @@ WARNING: BEGIN: already a transaction in progress
<title>Description</title>
<para>
This command begins a new transaction. If the isolation level is
specified, the new transaction has that isolation level. In all other
respects, the behavior of this command is identical to the
<xref linkend="sql-begin" endterm="sql-begin-title"> command.
This command begins a new transaction. If the isolation level or
read/write mode is specified, the new transaction has those
characteristics, as if <xref linkend="sql-set-transaction"
endterm="sql-set-transaction-title"> was executed. In all other
respects, the behavior of this command is identical to the <xref
linkend="sql-begin" endterm="sql-begin-title"> command.
</para>
</refsect1>
<refsect1>
<title>Notes</title>
<para>
The isolation level of a transaction can also be set with the <xref
linkend="sql-set-transaction" endterm="sql-set-transaction-title">
command. If no isolation level is specified, the default isolation
level is used.
</para>
</refsect1>
<refsect1 id="R1-SQL-START-TRANSACTION-3">
<title>Compatibility</title>
<refsect2 id="R2-SQL-START-TRANSACTION-4">
<title>SQL99</title>
<para>
<option>SERIALIZABLE</option> is the default isolation level in
<acronym>SQL99</acronym>, but it is not the usual default in
<productname>PostgreSQL</productname>: the factory default setting
is READ COMMITTED.
<productname>PostgreSQL</productname>
does not provide the isolation levels <option>READ UNCOMMITTED</option>
and <option>REPEATABLE READ</option>. Because of lack of predicate
locking, the <option>SERIALIZABLE</option> level is
not truly serializable. See the <citetitle>User's Guide</citetitle>
for details.
</para>
<para>
In <acronym>SQL99</acronym> this statement can specify two other
properties of the new transaction: whether the transaction is
read-only and the size of the diagnostics area. Neither of these
concepts are currently supported in
<productname>PostgreSQL</productname>.
</para>
</refsect2>
<para>
SQL99; but see also the compatibility section of <xref
linkend="sql-set-transaction" endterm="sql-set-transaction-title">.
</para>
</refsect1>
</refentry>
...
...
doc/src/sgml/release.sgml
View file @
b65cd562
<!--
$Header: /cvsroot/pgsql/doc/src/sgml/release.sgml,v 1.17
6 2003/01/08 00:22:26 tgl
Exp $
$Header: /cvsroot/pgsql/doc/src/sgml/release.sgml,v 1.17
7 2003/01/10 22:03:26 petere
Exp $
-->
<appendix id="release">
...
...
@@ -36,6 +36,7 @@ System can use either hash- or sort-based strategy for grouped aggregation
ON COMMIT options for temp tables
extra_float_digits option allows pg_dump to dump float data accurately
Long options for psql and pg_dump are now available on all platforms
Read-only transactions
]]></literallayout>
</sect1>
...
...
src/backend/access/transam/xact.c
View file @
b65cd562
...
...
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/transam/xact.c,v 1.14
0 2002/11/23 03:59:06 momjian
Exp $
* $Header: /cvsroot/pgsql/src/backend/access/transam/xact.c,v 1.14
1 2003/01/10 22:03:27 petere
Exp $
*
* NOTES
* Transaction aborts can now occur two ways:
...
...
@@ -208,6 +208,9 @@ TransactionState CurrentTransactionState = &CurrentTransactionStateData;
int
DefaultXactIsoLevel
=
XACT_READ_COMMITTED
;
int
XactIsoLevel
;
bool
DefaultXactReadOnly
=
false
;
bool
XactReadOnly
;
bool
autocommit
=
true
;
int
CommitDelay
=
0
;
/* precommit delay in microseconds */
...
...
@@ -848,6 +851,7 @@ StartTransaction(void)
FreeXactSnapshot
();
XactIsoLevel
=
DefaultXactIsoLevel
;
XactReadOnly
=
DefaultXactReadOnly
;
/*
* Check the current transaction state. If the transaction system is
...
...
src/backend/catalog/namespace.c
View file @
b65cd562
...
...
@@ -13,7 +13,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/catalog/namespace.c,v 1.4
3 2003/01/07 20:56:06 tgl
Exp $
* $Header: /cvsroot/pgsql/src/backend/catalog/namespace.c,v 1.4
4 2003/01/10 22:03:27 petere
Exp $
*
*-------------------------------------------------------------------------
*/
...
...
@@ -278,6 +278,30 @@ RelnameGetRelid(const char *relname)
return
InvalidOid
;
}
/*
* RelidGetNamespaceId
* Given a relation OID, return the namespace OID.
*/
Oid
RelidGetNamespaceId
(
Oid
relid
)
{
HeapTuple
tuple
;
Form_pg_class
pg_class_form
;
Oid
result
;
tuple
=
SearchSysCache
(
RELOID
,
ObjectIdGetDatum
(
relid
),
0
,
0
,
0
);
if
(
!
HeapTupleIsValid
(
tuple
))
elog
(
ERROR
,
"cache lookup failed for relation %u"
,
relid
);
pg_class_form
=
(
Form_pg_class
)
GETSTRUCT
(
tuple
);
result
=
pg_class_form
->
relnamespace
;
ReleaseSysCache
(
tuple
);
return
result
;
}
/*
* RelationIsVisible
* Determine whether a relation (identified by OID) is visible in the
...
...
src/backend/commands/copy.c
View file @
b65cd562
...
...
@@ -9,7 +9,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.18
7 2002/12/15 16:17:38 tgl
Exp $
* $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.18
8 2003/01/10 22:03:27 petere
Exp $
*
*-------------------------------------------------------------------------
*/
...
...
@@ -348,6 +348,10 @@ DoCopy(const CopyStmt *stmt)
*/
rel
=
heap_openrv
(
relation
,
(
is_from
?
RowExclusiveLock
:
AccessShareLock
));
/* check read-only transaction */
if
(
XactReadOnly
&&
!
is_from
&&
!
isTempNamespace
(
RelationGetNamespace
(
rel
)))
elog
(
ERROR
,
"transaction is read-only"
);
/* Check permissions. */
aclresult
=
pg_class_aclcheck
(
RelationGetRelid
(
rel
),
GetUserId
(),
required_access
);
...
...
src/backend/executor/execMain.c
View file @
b65cd562
...
...
@@ -26,7 +26,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.19
6 2003/01/08 23:32:29 tgl
Exp $
* $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.19
7 2003/01/10 22:03:27 petere
Exp $
*
*-------------------------------------------------------------------------
*/
...
...
@@ -85,6 +85,7 @@ static void ExecUpdate(TupleTableSlot *slot, ItemPointer tupleid,
static
TupleTableSlot
*
EvalPlanQualNext
(
EState
*
estate
);
static
void
EndEvalPlanQual
(
EState
*
estate
);
static
void
ExecCheckRTEPerms
(
RangeTblEntry
*
rte
,
CmdType
operation
);
static
void
ExecCheckXactReadOnly
(
Query
*
parsetree
,
CmdType
operation
);
static
void
EvalPlanQualStart
(
evalPlanQual
*
epq
,
EState
*
estate
,
evalPlanQual
*
priorepq
);
static
void
EvalPlanQualStop
(
evalPlanQual
*
epq
);
...
...
@@ -201,6 +202,14 @@ ExecutorRun(QueryDesc *queryDesc,
operation
=
queryDesc
->
operation
;
dest
=
queryDesc
->
dest
;
/*
* If the transaction is read-only, we need to check if any writes
* are planned to non-temporary tables. This is done here at this
* rather late stage so that we can handle EXPLAIN vs. EXPLAIN
* ANALYZE easily.
*/
ExecCheckXactReadOnly
(
queryDesc
->
parsetree
,
operation
);
/*
* startup tuple receiver
*/
...
...
@@ -385,6 +394,45 @@ ExecCheckRTEPerms(RangeTblEntry *rte, CmdType operation)
*/
static
void
ExecCheckXactReadOnly
(
Query
*
parsetree
,
CmdType
operation
)
{
if
(
!
XactReadOnly
)
return
;
/* CREATE TABLE AS or SELECT INTO */
if
(
operation
==
CMD_SELECT
&&
parsetree
->
into
!=
NULL
)
goto
fail
;
if
(
operation
==
CMD_DELETE
||
operation
==
CMD_INSERT
||
operation
==
CMD_UPDATE
)
{
List
*
lp
;
foreach
(
lp
,
parsetree
->
rtable
)
{
RangeTblEntry
*
rte
=
lfirst
(
lp
);
if
(
rte
->
rtekind
!=
RTE_RELATION
)
continue
;
if
(
!
rte
->
checkForWrite
)
continue
;
if
(
isTempNamespace
(
RelidGetNamespaceId
(
rte
->
relid
)))
continue
;
goto
fail
;
}
}
return
;
fail:
elog
(
ERROR
,
"transaction is read-only"
);
}
/* ----------------------------------------------------------------
* InitPlan
*
...
...
src/backend/parser/gram.y
View file @
b65cd562
...
...
@@ -11,7 +11,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.39
4 2003/01/10 21:08:13 tgl
Exp $
* $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.39
5 2003/01/10 22:03:27 petere
Exp $
*
* HISTORY
* AUTHOR DATE MAJOR EVENT
...
...
@@ -162,7 +162,7 @@ static void doNegateFloat(Value *v);
%type <defelt> createdb_opt_item copy_opt_item
%type <ival> opt_lock lock_type cast_context
%type <boolean> opt_force opt_or_replace
%type <boolean> opt_force opt_or_replace
transaction_access_mode
%type <list> user_list
...
...
@@ -215,7 +215,8 @@ static void doNegateFloat(Value *v);
target_list update_target_list insert_column_list
insert_target_list def_list opt_indirection
group_clause TriggerFuncArgs select_limit
opt_select_limit opclass_item_list trans_options
opt_select_limit opclass_item_list transaction_mode_list
transaction_mode_list_or_empty
TableFuncElementList
prep_type_clause prep_type_list
execute_param_clause
...
...
@@ -863,18 +864,18 @@ set_rest: ColId TO var_list_or_default
n->args = makeList1($3);
$$ = n;
}
| TRANSACTION
ISOLATION LEVEL iso_level opt_mode
| TRANSACTION
transaction_mode_list
{
VariableSetStmt *n = makeNode(VariableSetStmt);
n->name = "TRANSACTION
ISOLATION LEVEL
";
n->args =
makeList1(makeStringConst($4, NULL))
;
n->name = "TRANSACTION";
n->args =
$2
;
$$ = n;
}
| SESSION CHARACTERISTICS AS TRANSACTION
ISOLATION LEVEL iso_level
| SESSION CHARACTERISTICS AS TRANSACTION
transaction_mode_list
{
VariableSetStmt *n = makeNode(VariableSetStmt);
n->name = "
default_transaction_isolation
";
n->args =
makeList1(makeStringConst($7, NULL))
;
n->name = "
SESSION CHARACTERISTICS
";
n->args =
$5
;
$$ = n;
}
| NAMES opt_encoding
...
...
@@ -922,16 +923,6 @@ iso_level: READ COMMITTED { $$ = "read committed"; }
| SERIALIZABLE { $$ = "serializable"; }
;
opt_mode: READ WRITE
{}
| READ ONLY
{
elog(ERROR, "SET TRANSACTION/READ ONLY not yet supported");
}
| /*EMPTY*/
{}
;
opt_boolean:
TRUE_P { $$ = "true"; }
| FALSE_P { $$ = "false"; }
...
...
@@ -1020,7 +1011,7 @@ VariableShowStmt:
| SHOW TRANSACTION ISOLATION LEVEL
{
VariableShowStmt *n = makeNode(VariableShowStmt);
n->name = "
TRANSACTION ISOLATION LEVEL
";
n->name = "
transaction_isolation
";
$$ = (Node *) n;
}
| SHOW SESSION AUTHORIZATION
...
...
@@ -1053,7 +1044,7 @@ VariableResetStmt:
| RESET TRANSACTION ISOLATION LEVEL
{
VariableResetStmt *n = makeNode(VariableResetStmt);
n->name = "
TRANSACTION ISOLATION LEVEL
";
n->name = "
transaction_isolation
";
$$ = (Node *) n;
}
| RESET SESSION AUTHORIZATION
...
...
@@ -3500,42 +3491,42 @@ UnlistenStmt:
*****************************************************************************/
TransactionStmt:
ABORT_TRANS opt_trans
ABORT_TRANS opt_trans
action
{
TransactionStmt *n = makeNode(TransactionStmt);
n->command = ROLLBACK;
n->options = NIL;
$$ = (Node *)n;
}
| BEGIN_TRANS opt_trans
| BEGIN_TRANS opt_trans
action
{
TransactionStmt *n = makeNode(TransactionStmt);
n->command = BEGIN_TRANS;
n->options = NIL;
$$ = (Node *)n;
}
| START TRANSACTION trans
_options
| START TRANSACTION trans
action_mode_list_or_empty
{
TransactionStmt *n = makeNode(TransactionStmt);
n->command = START;
n->options = $3;
$$ = (Node *)n;
}
| COMMIT opt_trans
| COMMIT opt_trans
action
{
TransactionStmt *n = makeNode(TransactionStmt);
n->command = COMMIT;
n->options = NIL;
$$ = (Node *)n;
}
| END_TRANS opt_trans
| END_TRANS opt_trans
action
{
TransactionStmt *n = makeNode(TransactionStmt);
n->command = COMMIT;
n->options = NIL;
$$ = (Node *)n;
}
| ROLLBACK opt_trans
| ROLLBACK opt_trans
action
{
TransactionStmt *n = makeNode(TransactionStmt);
n->command = ROLLBACK;
...
...
@@ -3544,16 +3535,46 @@ TransactionStmt:
}
;
trans_options: ISOLATION LEVEL iso_level
{ $$ = makeList1(makeStringConst($3, NULL)); }
| /* EMPTY */ { $$ = NIL; }
;
opt_trans: WORK {}
opt_transaction: WORK {}
| TRANSACTION {}
| /*EMPTY*/ {}
;
transaction_mode_list:
ISOLATION LEVEL iso_level
{ $$ = makeList1(makeDefElem("transaction_isolation",
makeStringConst($3, NULL))); }
| transaction_access_mode
{ $$ = makeList1(makeDefElem("transaction_read_only",
makeIntConst($1))); }
| ISOLATION LEVEL iso_level transaction_access_mode
{
$$ = makeList2(makeDefElem("transaction_isolation",
makeStringConst($3, NULL)),
makeDefElem("transaction_read_only",
makeIntConst($4)));
}
| transaction_access_mode ISOLATION LEVEL iso_level
{
$$ = makeList2(makeDefElem("transaction_read_only",
makeIntConst($1)),
makeDefElem("transaction_isolation",
makeStringConst($4, NULL)));
}
;
transaction_mode_list_or_empty:
transaction_mode_list
| /* EMPTY */
{ $$ = NIL; }
;
transaction_access_mode:
READ ONLY { $$ = TRUE; }
| READ WRITE { $$ = FALSE; }
;
/*****************************************************************************
*
* QUERY:
...
...
src/backend/tcop/utility.c
View file @
b65cd562
...
...
@@ -10,7 +10,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.18
8 2003/01/06 00:31:44 tgl
Exp $
* $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.18
9 2003/01/10 22:03:28 petere
Exp $
*
*-------------------------------------------------------------------------
*/
...
...
@@ -168,6 +168,66 @@ CheckOwnership(RangeVar *rel, bool noCatalogs)
}
static
void
check_xact_readonly
(
Node
*
parsetree
)
{
if
(
!
XactReadOnly
)
return
;
/*
* Note: Commands that need to do more complicated checking are
* handled elsewhere.
*/
switch
(
nodeTag
(
parsetree
))
{
case
T_AlterDatabaseSetStmt
:
case
T_AlterDomainStmt
:
case
T_AlterGroupStmt
:
case
T_AlterTableStmt
:
case
T_RenameStmt
:
case
T_AlterUserStmt
:
case
T_AlterUserSetStmt
:
case
T_CommentStmt
:
case
T_DefineStmt
:
case
T_CreateCastStmt
:
case
T_CreateConversionStmt
:
case
T_CreatedbStmt
:
case
T_CreateDomainStmt
:
case
T_CreateFunctionStmt
:
case
T_CreateGroupStmt
:
case
T_IndexStmt
:
case
T_CreatePLangStmt
:
case
T_CreateOpClassStmt
:
case
T_RuleStmt
:
case
T_CreateSchemaStmt
:
case
T_CreateSeqStmt
:
case
T_CreateStmt
:
case
T_CreateTrigStmt
:
case
T_CompositeTypeStmt
:
case
T_CreateUserStmt
:
case
T_ViewStmt
:
case
T_RemoveAggrStmt
:
case
T_DropCastStmt
:
case
T_DropStmt
:
case
T_DropdbStmt
:
case
T_RemoveFuncStmt
:
case
T_DropGroupStmt
:
case
T_DropPLangStmt
:
case
T_RemoveOperStmt
:
case
T_RemoveOpClassStmt
:
case
T_DropPropertyStmt
:
case
T_DropUserStmt
:
case
T_GrantStmt
:
case
T_TruncateStmt
:
elog
(
ERROR
,
"transaction is read-only"
);
break
;
default:
/*nothing*/
;
}
}
/*
* ProcessUtility
* general utility function invoker
...
...
@@ -187,6 +247,8 @@ ProcessUtility(Node *parsetree,
CommandDest
dest
,
char
*
completionTag
)
{
check_xact_readonly
(
parsetree
);
if
(
completionTag
)
completionTag
[
0
]
=
'\0'
;
...
...
@@ -214,16 +276,21 @@ ProcessUtility(Node *parsetree,
{
BeginTransactionBlock
();
/*
* Currently, the only option that can be set
* by START TRANSACTION is the isolation
* level.
*/
if
(
stmt
->
options
)
{
SetPGVariable
(
"TRANSACTION ISOLATION LEVEL"
,
stmt
->
options
,
false
);
List
*
head
;
foreach
(
head
,
stmt
->
options
)
{
DefElem
*
item
=
(
DefElem
*
)
lfirst
(
head
);
if
(
strcmp
(
item
->
defname
,
"transaction_isolation"
)
==
0
)
SetPGVariable
(
"transaction_isolation"
,
makeList1
(
item
->
arg
),
false
);
else
if
(
strcmp
(
item
->
defname
,
"transaction_read_only"
)
==
0
)
SetPGVariable
(
"transaction_read_only"
,
makeList1
(
item
->
arg
),
false
);
}
}
}
break
;
...
...
@@ -765,7 +832,45 @@ ProcessUtility(Node *parsetree,
{
VariableSetStmt
*
n
=
(
VariableSetStmt
*
)
parsetree
;
SetPGVariable
(
n
->
name
,
n
->
args
,
n
->
is_local
);
/*
* Special cases for special SQL syntax that
* effectively sets more than one variable per
* statement.
*/
if
(
strcmp
(
n
->
name
,
"TRANSACTION"
)
==
0
)
{
List
*
head
;
foreach
(
head
,
n
->
args
)
{
DefElem
*
item
=
(
DefElem
*
)
lfirst
(
head
);
if
(
strcmp
(
item
->
defname
,
"transaction_isolation"
)
==
0
)
SetPGVariable
(
"transaction_isolation"
,
makeList1
(
item
->
arg
),
n
->
is_local
);
else
if
(
strcmp
(
item
->
defname
,
"transaction_read_only"
)
==
0
)
SetPGVariable
(
"transaction_read_only"
,
makeList1
(
item
->
arg
),
n
->
is_local
);
}
}
else
if
(
strcmp
(
n
->
name
,
"SESSION CHARACTERISTICS"
)
==
0
)
{
List
*
head
;
foreach
(
head
,
n
->
args
)
{
DefElem
*
item
=
(
DefElem
*
)
lfirst
(
head
);
if
(
strcmp
(
item
->
defname
,
"transaction_isolation"
)
==
0
)
SetPGVariable
(
"default_transaction_isolation"
,
makeList1
(
item
->
arg
),
n
->
is_local
);
else
if
(
strcmp
(
item
->
defname
,
"transaction_read_only"
)
==
0
)
SetPGVariable
(
"default_transaction_read_only"
,
makeList1
(
item
->
arg
),
n
->
is_local
);
}
}
else
SetPGVariable
(
n
->
name
,
n
->
args
,
n
->
is_local
);
}
break
;
...
...
src/backend/utils/misc/guc.c
View file @
b65cd562
...
...
@@ -5,7 +5,7 @@
* command, configuration file, and command line options.
* See src/backend/utils/misc/README for more information.
*
* $Header: /cvsroot/pgsql/src/backend/utils/misc/guc.c,v 1.1
09 2002/12/27 14:06:34 momjian
Exp $
* $Header: /cvsroot/pgsql/src/backend/utils/misc/guc.c,v 1.1
10 2003/01/10 22:03:29 petere
Exp $
*
* Copyright 2000 by PostgreSQL Global Development Group
* Written by Peter Eisentraut <peter_e@gmx.net>.
...
...
@@ -516,6 +516,14 @@ static struct config_bool
{
"autocommit"
,
PGC_USERSET
},
&
autocommit
,
true
,
NULL
,
NULL
},
{
{
"default_transaction_read_only"
,
PGC_USERSET
},
&
DefaultXactReadOnly
,
false
,
NULL
,
NULL
},
{
{
"transaction_read_only"
,
PGC_USERSET
,
GUC_NO_RESET_ALL
},
&
XactReadOnly
,
false
,
NULL
,
NULL
},
{
{
NULL
,
0
},
NULL
,
false
,
NULL
,
NULL
...
...
@@ -841,7 +849,7 @@ static struct config_string
},
{
{
"
TRANSACTION ISOLATION LEVEL
"
,
PGC_USERSET
,
GUC_NO_RESET_ALL
},
{
"
transaction_isolation
"
,
PGC_USERSET
,
GUC_NO_RESET_ALL
},
&
XactIsoLevel_string
,
NULL
,
assign_XactIsoLevel
,
show_XactIsoLevel
},
...
...
@@ -1157,10 +1165,12 @@ InitializeGUCOptions(void)
guc_string_workspace
=
NULL
;
/*
* Prevent any attempt to override
TRANSACTION ISOLATION LEVEL
from
* Prevent any attempt to override
the transaction modes
from
* non-interactive sources.
*/
SetConfigOption
(
"TRANSACTION ISOLATION LEVEL"
,
"default"
,
SetConfigOption
(
"transaction_isolation"
,
"default"
,
PGC_POSTMASTER
,
PGC_S_OVERRIDE
);
SetConfigOption
(
"transaction_read_only"
,
"no"
,
PGC_POSTMASTER
,
PGC_S_OVERRIDE
);
/*
...
...
src/bin/psql/tab-complete.c
View file @
b65cd562
...
...
@@ -3,7 +3,7 @@
*
* Copyright 2000-2002 by PostgreSQL Global Development Group
*
* $Header: /cvsroot/pgsql/src/bin/psql/tab-complete.c,v 1.7
0 2002/12/13 05:36:24 momjian
Exp $
* $Header: /cvsroot/pgsql/src/bin/psql/tab-complete.c,v 1.7
1 2003/01/10 22:03:30 petere
Exp $
*/
/*----------------------------------------------------------------------
...
...
@@ -212,13 +212,7 @@ psql_completion(char *text, int start, int end)
"CONSTRAINTS"
,
"NAMES"
,
"SESSION"
,
"TRANSACTION ISOLATION LEVEL"
,
/* these are treated in backend/commands/variable.c */
"DateStyle"
,
"TimeZone"
,
"client_encoding"
,
"server_encoding"
,
"seed"
,
"TRANSACTION"
,
/*
* the rest should match USERSET entries in
...
...
@@ -229,12 +223,14 @@ psql_completion(char *text, int start, int end)
"autocommit"
,
"checkpoint_segments"
,
"checkpoint_timeout"
,
"client_encoding"
,
"client_min_messages"
,
"commit_delay"
,
"commit_siblings"
,
"cpu_index_tuple_cost"
,
"cpu_operator_cost"
,
"cpu_tuple_cost"
,
"DateStyle"
,
"db_user_namespace"
,
"deadlock_timeout"
,
"debug_pretty_print"
,
...
...
@@ -269,7 +265,7 @@ psql_completion(char *text, int start, int end)
"lc_messages"
,
"lc_monetary"
,
"lc_numeric"
,
"lc_time
C
"
,
"lc_time"
,
"log_connections"
,
"log_duration"
,
"log_min_error_statement"
,
...
...
@@ -294,6 +290,8 @@ psql_completion(char *text, int start, int end)
"log_planner_stats"
,
"log_source_port"
,
"log_statement_stats"
,
"seed"
,
"server_encoding"
,
"silent_mode"
,
"sort_mem"
,
"sql_inheritance"
,
...
...
@@ -309,6 +307,7 @@ psql_completion(char *text, int start, int end)
"syslog_facility"
,
"syslog_ident"
,
"tcpip_socket"
,
"TimeZone"
,
"trace_notify"
,
"transform_null_equals"
,
"unix_socket_directory"
,
...
...
@@ -817,10 +816,18 @@ psql_completion(char *text, int start, int end)
strcasecmp
(
prev_wd
,
"RESET"
)
==
0
||
strcasecmp
(
prev_wd
,
"SHOW"
)
==
0
)
COMPLETE_WITH_LIST
(
pgsql_variables
);
/* Complete "SET TRANSACTION ISOLOLATION LEVEL" */
else
if
(
strcasecmp
(
prev2_wd
,
"SET"
)
==
0
&&
strcasecmp
(
prev_wd
,
"TRANSACTION"
)
==
0
)
COMPLETE_WITH_CONST
(
"ISOLATION"
);
/* Complete "SET TRANSACTION" */
else
if
((
strcasecmp
(
prev2_wd
,
"SET"
)
==
0
&&
strcasecmp
(
prev_wd
,
"TRANSACTION"
)
==
0
)
||
(
strcasecmp
(
prev4_wd
,
"SESSION"
)
==
0
&&
strcasecmp
(
prev3_wd
,
"CHARACTERISTICS"
)
==
0
&&
strcasecmp
(
prev2_wd
,
"AS"
)
==
0
&&
strcasecmp
(
prev_wd
,
"TRANSACTION"
)
==
0
))
{
char
*
my_list
[]
=
{
"ISOLATION"
,
"READ"
,
NULL
};
COMPLETE_WITH_LIST
(
my_list
);
}
else
if
(
strcasecmp
(
prev3_wd
,
"SET"
)
==
0
&&
strcasecmp
(
prev2_wd
,
"TRANSACTION"
)
==
0
&&
strcasecmp
(
prev_wd
,
"ISOLATION"
)
==
0
)
...
...
@@ -840,6 +847,15 @@ psql_completion(char *text, int start, int end)
strcasecmp
(
prev2_wd
,
"LEVEL"
)
==
0
&&
strcasecmp
(
prev_wd
,
"READ"
)
==
0
)
COMPLETE_WITH_CONST
(
"COMMITTED"
);
else
if
((
strcasecmp
(
prev3_wd
,
"SET"
)
==
0
||
strcasecmp
(
prev3_wd
,
"AS"
)
==
0
)
&&
strcasecmp
(
prev2_wd
,
"TRANSACTION"
)
==
0
&&
strcasecmp
(
prev_wd
,
"READ"
)
==
0
)
{
char
*
my_list
[]
=
{
"ONLY"
,
"WRITE"
,
NULL
};
COMPLETE_WITH_LIST
(
my_list
);
}
/* Complete SET CONSTRAINTS <foo> with DEFERRED|IMMEDIATE */
else
if
(
strcasecmp
(
prev3_wd
,
"SET"
)
==
0
&&
strcasecmp
(
prev2_wd
,
"CONSTRAINTS"
)
==
0
)
...
...
@@ -853,7 +869,7 @@ psql_completion(char *text, int start, int end)
strcasecmp
(
prev_wd
,
"SESSION"
)
==
0
)
{
char
*
my_list
[]
=
{
"AUTHORIZATION"
,
"CHARACTERISTICS AS TRANSACTION
ISOLATION LEVEL
"
,
"CHARACTERISTICS AS TRANSACTION"
,
NULL
};
COMPLETE_WITH_LIST
(
my_list
);
...
...
src/include/access/xact.h
View file @
b65cd562
...
...
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $Id: xact.h,v 1.4
8 2002/11/18 01:17:39 tgl
Exp $
* $Id: xact.h,v 1.4
9 2003/01/10 22:03:30 petere
Exp $
*
*-------------------------------------------------------------------------
*/
...
...
@@ -29,6 +29,9 @@
extern
int
DefaultXactIsoLevel
;
extern
int
XactIsoLevel
;
extern
bool
DefaultXactReadOnly
;
extern
bool
XactReadOnly
;
/* ----------------
* transaction state structure
...
...
src/include/catalog/namespace.h
View file @
b65cd562
...
...
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $Id: namespace.h,v 1.2
4 2003/01/07 20:56:07 tgl
Exp $
* $Id: namespace.h,v 1.2
5 2003/01/10 22:03:30 petere
Exp $
*
*-------------------------------------------------------------------------
*/
...
...
@@ -51,6 +51,7 @@ typedef struct _OpclassCandidateList
extern
Oid
RangeVarGetRelid
(
const
RangeVar
*
relation
,
bool
failOK
);
extern
Oid
RangeVarGetCreationNamespace
(
const
RangeVar
*
newRelation
);
extern
Oid
RelnameGetRelid
(
const
char
*
relname
);
extern
Oid
RelidGetNamespaceId
(
Oid
relid
);
extern
bool
RelationIsVisible
(
Oid
relid
);
extern
Oid
TypenameGetTypid
(
const
char
*
typname
);
...
...
src/test/regress/expected/transactions.out
View file @
b65cd562
...
...
@@ -40,3 +40,31 @@ SELECT * FROM aggtest;
42 | 324.78
(4 rows)
-- Read-only tests
CREATE TABLE writetest (a int);
CREATE TEMPORARY TABLE temptest (a int);
SET SESSION CHARACTERISTICS AS TRANSACTION READ ONLY;
DROP TABLE writetest; -- fail
ERROR: transaction is read-only
INSERT INTO writetest VALUES (1); -- fail
ERROR: transaction is read-only
SELECT * FROM writetest; -- ok
a
---
(0 rows)
DELETE FROM temptest; -- ok
UPDATE temptest SET a = 0 WHERE a = 1 AND writetest.a = temptest.a; -- ok
PREPARE test AS UPDATE writetest SET a = 0; -- ok
EXECUTE test; -- fail
ERROR: transaction is read-only
SELECT * FROM writetest, temptest; -- ok
a | a
---+---
(0 rows)
CREATE TABLE test AS SELECT * FROM writetest; -- fail
ERROR: transaction is read-only
START TRANSACTION READ WRITE;
DROP TABLE writetest; -- ok
COMMIT;
src/test/regress/sql/transactions.sql
View file @
b65cd562
...
...
@@ -33,3 +33,24 @@ SELECT oid FROM pg_class WHERE relname = 'disappear';
-- should have members again
SELECT
*
FROM
aggtest
;
-- Read-only tests
CREATE
TABLE
writetest
(
a
int
);
CREATE
TEMPORARY
TABLE
temptest
(
a
int
);
SET
SESSION
CHARACTERISTICS
AS
TRANSACTION
READ
ONLY
;
DROP
TABLE
writetest
;
-- fail
INSERT
INTO
writetest
VALUES
(
1
);
-- fail
SELECT
*
FROM
writetest
;
-- ok
DELETE
FROM
temptest
;
-- ok
UPDATE
temptest
SET
a
=
0
WHERE
a
=
1
AND
writetest
.
a
=
temptest
.
a
;
-- ok
PREPARE
test
AS
UPDATE
writetest
SET
a
=
0
;
-- ok
EXECUTE
test
;
-- fail
SELECT
*
FROM
writetest
,
temptest
;
-- ok
CREATE
TABLE
test
AS
SELECT
*
FROM
writetest
;
-- fail
START
TRANSACTION
READ
WRITE
;
DROP
TABLE
writetest
;
-- ok
COMMIT
;
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment