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
60ce9e92
Commit
60ce9e92
authored
Sep 02, 2001
by
Peter Eisentraut
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
New blood and fresh air for tutorial
parent
5608f130
Changes
9
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
1333 additions
and
1122 deletions
+1333
-1122
doc/src/sgml/advanced.sgml
doc/src/sgml/advanced.sgml
+246
-227
doc/src/sgml/arch.sgml
doc/src/sgml/arch.sgml
+0
-88
doc/src/sgml/filelist.sgml
doc/src/sgml/filelist.sgml
+5
-4
doc/src/sgml/info.sgml
doc/src/sgml/info.sgml
+2
-2
doc/src/sgml/query.sgml
doc/src/sgml/query.sgml
+604
-295
doc/src/sgml/start.sgml
doc/src/sgml/start.sgml
+341
-350
doc/src/sgml/tutorial.sgml
doc/src/sgml/tutorial.sgml
+33
-3
src/tutorial/advanced.source
src/tutorial/advanced.source
+4
-71
src/tutorial/basics.source
src/tutorial/basics.source
+98
-82
No files found.
doc/src/sgml/advanced.sgml
View file @
60ce9e92
This diff is collapsed.
Click to expand it.
doc/src/sgml/arch.sgml
deleted
100644 → 0
View file @
5608f130
<Chapter Id="arch">
<TITLE>Architecture</TITLE>
<Sect1 id="arch-concepts">
<Title><ProductName>Postgres</ProductName> Architectural Concepts</Title>
<Para>
Before we begin, you should understand the basic
<ProductName>Postgres</ProductName> system architecture. Understanding how the
parts of <ProductName>Postgres</ProductName> interact will make the next chapter
somewhat clearer.
In database jargon, <ProductName>Postgres</ProductName> uses a simple "process
per-user" client/server model. A <ProductName>Postgres</ProductName> session
consists of the following cooperating Unix processes (programs):
</Para>
<ItemizedList>
<ListItem>
<Para>
A supervisory daemon process (<Application>postmaster</Application>),
</Para>
</ListItem>
<ListItem>
<Para>
the user's frontend application (e.g., the <Application>psql</Application> program), and
</Para>
</ListItem>
<ListItem>
<Para>
the one or more backend database servers (the <Application>postgres</Application> process itself).
</Para>
</ListItem>
</ItemizedList>
<Para>
A single <Application>postmaster</Application> manages a given collection of
databases on a single host. Such a collection of
databases is called a cluster (of databases). Frontend
applications that wish to access a given database
within a cluster make calls to the library.
The library sends user requests over the network to the
<Application>postmaster</Application> (<XRef LinkEnd="ARCH-CLIENTSERVER">),
which in turn starts a new backend server process
<Figure Id="ARCH-CLIENTSERVER">
<Title>How a connection is established</Title>
<Graphic Align="center" FileRef="clientserver.gif" Format="GIF"></Graphic>
</Figure>
and connects the
frontend process to the new server. From
that point on, the frontend process and the backend
server communicate without intervention by the
<Application>postmaster</Application>. Hence, the <Application>postmaster</Application> is always running, waiting
for requests, whereas frontend and backend processes
come and go.
</Para>
<Para>
The <FileName>libpq</FileName> library allows a single
frontend to make multiple connections to backend processes.
However, the frontend application is still a
single-threaded process. Multithreaded frontend/backend
connections are not currently supported in <FileName>libpq</FileName>.
One implication of this architecture is that the
<Application>postmaster</Application> and the backend always run on the same
machine (the database server), while the frontend
application may run anywhere. You should keep this
in mind,
because the files that can be accessed on a client
machine may not be accessible (or may only be accessed
using a different filename) on the database server
machine.
</Para>
<Para>
You should also be aware that the <Application>postmaster</Application> and
postgres servers run with the user-id of the <ProductName>Postgres</ProductName>
"superuser." Note that the <ProductName>Postgres</ProductName> superuser does not
have to be a special user (e.g., a user named
"postgres"). Furthermore, the <ProductName>Postgres</ProductName> superuser
should
definitely not be the Unix superuser ("root")! In any
case, all files relating to a database should belong to
this <ProductName>Postgres</ProductName> superuser.
</Para>
</sect1>
</Chapter>
doc/src/sgml/filelist.sgml
View file @
60ce9e92
<!-- $Header: /cvsroot/pgsql/doc/src/sgml/filelist.sgml,v 1.1
4 2001/08/26 21:17:12 tgl
Exp $ -->
<!-- $Header: /cvsroot/pgsql/doc/src/sgml/filelist.sgml,v 1.1
5 2001/09/02 23:27:49 petere
Exp $ -->
<!entity history SYSTEM "history.sgml">
<!entity history SYSTEM "history.sgml">
<!entity info SYSTEM "info.sgml">
<!entity info SYSTEM "info.sgml">
<!entity intro SYSTEM "intro.sgml">
<!entity legal SYSTEM "legal.sgml">
<!entity legal SYSTEM "legal.sgml">
<!entity notation SYSTEM "notation.sgml">
<!entity notation SYSTEM "notation.sgml">
<!entity problems SYSTEM "problems.sgml">
<!entity problems SYSTEM "problems.sgml">
...
@@ -12,12 +13,12 @@
...
@@ -12,12 +13,12 @@
<!-- tutorial -->
<!-- tutorial -->
<!entity advanced SYSTEM "advanced.sgml">
<!entity advanced SYSTEM "advanced.sgml">
<!entity arch SYSTEM "arch.sgml">
<!entity intro SYSTEM "intro.sgml">
<!entity query SYSTEM "query.sgml">
<!entity query SYSTEM "query.sgml">
<!entity sql SYSTEM "sql.sgml">
<!entity start SYSTEM "start.sgml">
<!entity start SYSTEM "start.sgml">
<!-- currently unused, but contains some interesting information -->
<!entity sql SYSTEM "sql.sgml">
<!-- user's guide -->
<!-- user's guide -->
<!entity array SYSTEM "array.sgml">
<!entity array SYSTEM "array.sgml">
<!entity datatype SYSTEM "datatype.sgml">
<!entity datatype SYSTEM "datatype.sgml">
...
...
doc/src/sgml/info.sgml
View file @
60ce9e92
<!--
<!--
$Header: /cvsroot/pgsql/doc/src/sgml/info.sgml,v 1.1
1 2001/02/03 19:03:26
petere Exp $
$Header: /cvsroot/pgsql/doc/src/sgml/info.sgml,v 1.1
2 2001/09/02 23:27:49
petere Exp $
-->
-->
<sect1 id="resources">
<sect1 id="resources">
...
@@ -13,7 +13,7 @@ $Header: /cvsroot/pgsql/doc/src/sgml/info.sgml,v 1.11 2001/02/03 19:03:26 petere
...
@@ -13,7 +13,7 @@ $Header: /cvsroot/pgsql/doc/src/sgml/info.sgml,v 1.11 2001/02/03 19:03:26 petere
<term>Tutorial</term>
<term>Tutorial</term>
<listitem>
<listitem>
<para>
<para>
An in
troduction for new users. Does not cover advanced features.
An in
formal introduction for new users
</para>
</para>
</listitem>
</listitem>
</varlistentry>
</varlistentry>
...
...
doc/src/sgml/query.sgml
View file @
60ce9e92
This diff is collapsed.
Click to expand it.
doc/src/sgml/start.sgml
View file @
60ce9e92
This diff is collapsed.
Click to expand it.
doc/src/sgml/tutorial.sgml
View file @
60ce9e92
<!--
<!--
$Header: /cvsroot/pgsql/doc/src/sgml/Attic/tutorial.sgml,v 1.1
4 2001/02/03 19:03:27
petere Exp $
$Header: /cvsroot/pgsql/doc/src/sgml/Attic/tutorial.sgml,v 1.1
5 2001/09/02 23:27:49
petere Exp $
-->
-->
<book id="tutorial">
<book id="tutorial">
...
@@ -10,16 +10,46 @@ $Header: /cvsroot/pgsql/doc/src/sgml/Attic/tutorial.sgml,v 1.14 2001/02/03 19:03
...
@@ -10,16 +10,46 @@ $Header: /cvsroot/pgsql/doc/src/sgml/Attic/tutorial.sgml,v 1.14 2001/02/03 19:03
&legal;
&legal;
</bookinfo>
</bookinfo>
<preface id="tutorial-welcome">
<title>Welcome</title>
<para>
Welcome to <productname>PostgreSQL</productname> and the
<citetitle>PostgreSQL Tutorial</citetitle>. The following few
chapters are intended to give a simple introduction to
<productname>PostgreSQL</productname>, relational database
concepts, and the SQL language to those who are new to any one of
these aspects. We only assume some general knowledge about how to
use computers. No particular Unix or programming experience is
required.
</para>
<para>
After you have worked through this tutorial you might want to move on
to reading the <![%single-book;[<citetitle>User's
Guide</citetitle>]]><![%set-of-books;[<xref linkend="user">]]> to
gain a more formal knowledge of the SQL language, or the
<![%single-book;[<citetitle>Programmer's
Guide</citetitle>]]><![%set-of-books;[<xref linkend="programmer">]]>
for information about developing applications for
<productname>PostgreSQL</productname>.
</para>
<para>
We hope you have a pleasant experience with
<productname>PostgreSQL</productname>.
</para>
</preface>
<![%single-book;[
<![%single-book;[
&intro;
&intro;
]]>
]]>
&sql;
&arch;
&start;
&start;
&query;
&query;
&advanced;
&advanced;
<![%single-book;[
<![%single-book;[
&biblio;
&biblio;
&bookindex;
]]>
]]>
</book>
</book>
...
...
src/tutorial/advanced.source
View file @
60ce9e92
---------------------------------------------------------------------------
---------------------------------------------------------------------------
--
--
-- advanced.sql-
-- advanced.sql-
-- more POSTGRES SQL features. (These are not part of the SQL-92
-- Tutorial on advanced more PostgreSQL features
-- standard.)
--
--
--
--
-- Copyright (c) 1994, Regents of the University of California
-- Copyright (c) 1994, Regents of the University of California
--
--
-- $Id: advanced.source,v 1.
3 1999/07/08 15:28:51 momjian
Exp $
-- $Id: advanced.source,v 1.
4 2001/09/02 23:27:50 petere
Exp $
--
--
---------------------------------------------------------------------------
---------------------------------------------------------------------------
-----------------------------
-----------------------------
-- Inheritance:
-- Inheritance:
--
a table can inherit from zero or more tables.
A query can reference
--
S table can inherit from zero or more tables.
A query can reference
-- either all rows of a table or all rows of a table plus all of its
-- either all rows of a table or all rows of a table plus all of its
-- descendants.
-- descendants.
-----------------------------
-----------------------------
...
@@ -31,7 +30,7 @@ CREATE TABLE capitals (
...
@@ -31,7 +30,7 @@ CREATE TABLE capitals (
state char(2)
state char(2)
) INHERITS (cities);
) INHERITS (cities);
--
now, let's populate the tables
--
Now, let's populate the tables.
INSERT INTO cities VALUES ('San Francisco', 7.24E+5, 63);
INSERT INTO cities VALUES ('San Francisco', 7.24E+5, 63);
INSERT INTO cities VALUES ('Las Vegas', 2.583E+5, 2174);
INSERT INTO cities VALUES ('Las Vegas', 2.583E+5, 2174);
INSERT INTO cities VALUES ('Mariposa', 1200, 1953);
INSERT INTO cities VALUES ('Mariposa', 1200, 1953);
...
@@ -56,72 +55,6 @@ FROM cities* c
...
@@ -56,72 +55,6 @@ FROM cities* c
WHERE c.altitude > 500;
WHERE c.altitude > 500;
-----------------------------
-- Time Travel:
-- this feature allows you to run historical queries.
-- removed for v6.3, but possible using triggers.
-- see contrib/spi/README for more information.
-----------------------------
-- first, let's make some changes to the cities table (suppose Mariposa's
-- population grows 10% this year)
-- UPDATE cities
-- SET population = population * 1.1
-- WHERE name = 'Mariposa';
-- the default time is the current time ('now'):
-- SELECT * FROM cities WHERE name = 'Mariposa';
-- we can also retrieve the population of Mariposa ever has. ('epoch' is the
-- earliest time representable by the system)
-- SELECT name, population
-- FROM cities['epoch', 'now'] -- can be abbreviated to cities[,]
-- WHERE name = 'Mariposa';
----------------------
-- Arrays:
-- attributes can be arrays of base types or user-defined types
----------------------
CREATE TABLE sal_emp (
name text,
pay_by_quarter int4[],
schedule text[][]
);
-- insert instances with array attributes. Note the use of braces
INSERT INTO sal_emp VALUES (
'Bill',
'{10000,10000,10000,10000}',
'{{"meeting", "lunch"}, {}}');
INSERT INTO sal_emp VALUES (
'Carol',
'{20000,25000,25000,25000}',
'{{"talk", "consult"}, {"meeting"}}');
----------------------
-- queries on array attributes
----------------------
SELECT name FROM sal_emp WHERE
sal_emp.pay_by_quarter[1] <> sal_emp.pay_by_quarter[2];
-- retrieve third quarter pay of all employees
SELECT sal_emp.pay_by_quarter[3] FROM sal_emp;
-- select subarrays
SELECT sal_emp.schedule[1:2][1:1] FROM sal_emp WHERE
sal_emp.name = 'Bill';
-- clean up (you must remove the children first)
-- clean up (you must remove the children first)
DROP TABLE sal_emp;
DROP TABLE capitals;
DROP TABLE capitals;
DROP TABLE cities;
DROP TABLE cities;
src/tutorial/basics.source
View file @
60ce9e92
...
@@ -6,22 +6,22 @@
...
@@ -6,22 +6,22 @@
--
--
-- Copyright (c) 1994, Andrew Yu, University of California
-- Copyright (c) 1994, Andrew Yu, University of California
--
--
-- $Id: basics.source,v 1.
3 1999/07/08 15:27:01 momjian
Exp $
-- $Id: basics.source,v 1.
4 2001/09/02 23:27:50 petere
Exp $
--
--
---------------------------------------------------------------------------
---------------------------------------------------------------------------
-----------------------------
-----------------------------
-- Creating a
t
able:
-- Creating a
New T
able:
--
a CREATE TABLE is used to create base tables. POSTGRES
SQL has
--
A CREATE TABLE is used to create base tables. Postgre
SQL has
-- its own set of built-in types.
(Note that keywords are
case-
-- its own set of built-in types.
(Note that SQL is
case-
-- insensitive
but identifiers are case-sensitive
.)
-- insensitive.)
-----------------------------
-----------------------------
CREATE TABLE weather (
CREATE TABLE weather (
city varchar(80),
city varchar(80),
temp_lo int, -- low temperature
temp_lo int, -- low temperature
temp_hi int, -- high temperature
temp_hi int, -- high temperature
prcp
float8
, -- precipitation
prcp
real
, -- precipitation
date date
date date
);
);
...
@@ -30,98 +30,105 @@ CREATE TABLE cities (
...
@@ -30,98 +30,105 @@ CREATE TABLE cities (
location point
location point
);
);
-----------------------------
-----------------------------
--
Inserting data
:
--
Populating a Table With Rows
:
--
an INSERT statement is used to insert a new row into a table.
There
--
An INSERT statement is used to insert a new row into a table.
There
-- are several ways you can specify what columns the data should go to.
-- are several ways you can specify what columns the data should go to.
-----------------------------
-----------------------------
-- 1.
t
he simplest case is when the list of value correspond to the order of
-- 1.
T
he simplest case is when the list of value correspond to the order of
-- the columns specified in CREATE TABLE.
-- the columns specified in CREATE TABLE.
INSERT INTO weather
INSERT INTO weather
VALUES ('San Francisco', 46, 50, 0.25, '11/27/1994
');
VALUES ('San Francisco', 46, 50, 0.25, '1994-11-27
');
INSERT INTO cities
INSERT INTO cities
VALUES ('San Francisco', '(-194.0, 53.0)');
VALUES ('San Francisco', '(-194.0, 53.0)');
-- 2.
you can also specify what column the values correspond to.
(The columns
-- 2.
You can also specify what column the values correspond to.
(The columns
-- can be specified in any order.
You may also omit any number of columns.
-- can be specified in any order.
You may also omit any number of columns,
-- e
g. unknown precipitation below)
-- e
.g., unknown precipitation below.
INSERT INTO weather (city, temp_lo, temp_hi, prcp, date)
INSERT INTO weather (city, temp_lo, temp_hi, prcp, date)
VALUES ('San Francisco', 43, 57, 0.0, '11/29/1994
');
VALUES ('San Francisco', 43, 57, 0.0, '1994-11-29
');
INSERT INTO weather (date, city, temp_hi, temp_lo)
INSERT INTO weather (date, city, temp_hi, temp_lo)
VALUES ('11/29/1994
', 'Hayward', 54, 37);
VALUES ('1994-11-29
', 'Hayward', 54, 37);
-----------------------------
-----------------------------
--
Retrieving data
:
--
Querying a Table
:
--
a SELECT statement is used for retrieving data.
The basic syntax is
--
A SELECT statement is used for retrieving data.
The basic syntax is
--
SELECT columns FROM tables WHERE predicates
--
SELECT columns FROM tables WHERE predicates.
-----------------------------
-----------------------------
-- A simple one would be:
SELECT * FROM weather;
SELECT * FROM weather;
--
You may also specify expressions in the target list. (T
he 'AS column'
-- you may also specify expressions in the target list (the 'AS column'
-- specifies the column name of the result.
It is optional.)
SELECT city, (temp_hi+temp_lo)/2 AS temp_avg, date FROM weather;
SELECT city, (temp_hi+temp_lo)/2 AS temp_avg, date FROM weather;
--
If you want to retrieve rows that satisfy certain condition (i.e.,
a
-- if you want to retrieve rows that satisfy certain condition (ie. a
-- restriction), specify the condition in WHERE.
The following retrieves
-- the weather of San Francisco on rainy days.
-- the weather of San Francisco on rainy days.
SELECT *
SELECT *
SELECT *
FROM weather
FROM weather
WHERE city = 'San Francisco'
WHE
RE
city = 'San Francisco'
AND
prcp > 0.0;
--
Here is a more complicated one.
Duplicates are removed when DISTINCT is
-- here is a more complicated one. Duplicates are removed when DISTINCT is
-- specified. ORDER BY specifies the column to sort on.
(Just to make sure the
-- following won't confuse you, DISTINCT and ORDER BY can be used separately.)
-- following won't confuse you, DISTINCT and ORDER BY can be used separately.)
SELECT DISTINCT city
SELECT DISTINCT city
SELECT DISTINCT city
FROM weather
FROM weather
ORDER BY city;
-----------------------------
-----------------------------
-----------------------------
-- Joins Between Tables:
-- Retrieving data into other classes:
-- queries can access multiple tables at once or access the same table
-- a SELECT ... INTO statement can be used to retrieve data into
-- in such a way that multiple instances of the table are being processed
-- at the same time.
-----------------------------
-----------------------------
-- The following joins the weather table and the cities table.
SELECT * INTO TABLE mytemp
FROM weather
WHERE city = 'San Francisco'
SELECT *
FROM weather, cities
WHERE city = name;
-- This prevents a duplicate city name column:
-----------------------------
-- Aggregates
SELECT city, temp_lo, temp_hi, prcp, date, location
SELECT max(temp_lo)
FROM weather, cities
WHERE city = name;
-- since the column names are all different, we don't have to specify the
-- Aggregate with GROUP BY
-- table name. If you want to be clear, you can do the following. They give
SELECT city, max(temp_lo)
-- identical results, of course.
FROM weather
SELECT weather.city, weather.temp_lo, weather.temp_hi, weather.prcp, weather.date, cities.location
-----------------------------
FROM weather, cities
-- Joining tables:
WHERE cities.name = weather.city;
-- queries can access multiple tables at once or access the same table
-- in such a way that multiple instances of the table are being processed
-- at the same time.
-- JOIN syntax
-- suppose we want to find all the records that are in the temperature range
SELECT *
FROM weather JOIN cities ON (weather.city = cities.name);
-- Outer join
SELECT *
FROM weather LEFT OUTER JOIN cities ON (weather.city = cities.name);
-- Suppose we want to find all the records that are in the temperature range
-- of other records. W1 and W2 are aliases for weather.
SELECT W1.city, W1.temp_lo, W1.temp_hi,
SELECT W1.city, W1.temp_lo, W1.temp_hi,
W2.city, W2.temp_lo, W2.temp_hi
W2.city, W2.temp_lo, W2.temp_hi
...
@@ -129,60 +136,69 @@ FROM weather W1, weather W2
...
@@ -129,60 +136,69 @@ FROM weather W1, weather W2
WHERE W1.temp_lo < W2.temp_lo
WHERE W1.temp_lo < W2.temp_lo
and W1.temp_hi > W2.temp_hi;
and W1.temp_hi > W2.temp_hi;
-- let's join two tables. The following joins the weather table
-- and the cities table.
SELECT city, location, prcp, date
-----------------------------
FROM weather, citie
s
-- Aggregate Function
s
WHERE name = city;
-----------------------------
-- since the column names are all different, we don't have to specify the
SELECT max(temp_lo)
-- table name. If you want to be clear, you can do the following. They give
FROM weather;
-- identical results, of course.
SELECT city FROM weather
WHERE temp_lo = (SELECT max(temp_lo) FROM weather);
-- Aggregate with GROUP BY
SELECT city, max(temp_lo)
FROM weather
GROUP BY city;
-- ... and HAVING
SELECT city, max(temp_lo)
FROM weather
GROUP BY city
HAVING max(temp_lo) < 40;
SELECT w.city, c.location, w.prcp, w.date
FROM weather w, cities c
WHERE c.name = w.city;
-----------------------------
-----------------------------
-- Updat
ing data
:
-- Updat
es
:
--
an UPDATE statement is used for updating data.
--
An UPDATE statement is used for updating data.
-----------------------------
-----------------------------
--
s
uppose you discover the temperature readings are all off by 2 degrees as
--
S
uppose you discover the temperature readings are all off by 2 degrees as
-- of Nov 28, you may update the data as follow:
-- of Nov 28, you may update the data as follow:
UPDATE weather
UPDATE weather
SET temp_hi = temp_hi - 2, temp_lo = temp_lo - 2
SET temp_hi = temp_hi - 2, temp_lo = temp_lo - 2
WHERE date > '11/28/1994
';
WHERE date > '1994-11-28
';
SELECT *
from
weather;
SELECT *
FROM
weather;
-----------------------------
-----------------------------
-- Deleti
ng data
:
-- Deleti
ons
:
--
a
DELETE statement is used for deleting rows from a table.
--
A
DELETE statement is used for deleting rows from a table.
-----------------------------
-----------------------------
--
suppose you are no longer interested in the weather of Hayward,
you can
--
Suppose you are no longer interested in the weather of Hayward, then
you can
-- do the following to delete those rows from the table
-- do the following to delete those rows from the table
.
DELETE FROM weather WHERE city = 'Hayward';
DELETE FROM weather WHERE city = 'Hayward';
SELECT *
from
weather;
SELECT *
FROM
weather;
--
you can also delete all the rows in a table by doing the following.
(This
--
You can also delete all the rows in a table by doing the following.
(This
-- is different from DROP TABLE which removes the table in addition to the
-- is different from DROP TABLE which removes the table in addition to the
-- removing the rows.)
-- removing the rows.)
DELETE FROM weather;
DELETE FROM weather;
SELECT * from weather;
SELECT * FROM weather;
-----------------------------
-----------------------------
-- Removing the tables:
-- Removing the tables:
-- DROP TABLE is used to remove tables. After you have done this, you
-- DROP TABLE is used to remove tables.
After you have done this, you
-- can no longer use those tables.
-- can no longer use those tables.
-----------------------------
-----------------------------
DROP TABLE weather, cities
, mytemp
;
DROP TABLE weather, cities;
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