Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / Баг update fdw? / 19 сообщений из 19, страница 1 из 1
09.11.2016, 19:55
    #39344454
Dany305
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Баг update fdw?
PostgreSQL 9.5.4

При выполнении 3 условий:
1. update на fdw
2. сторонняя таблица нарезана на партиции
3. where есть условия на локальные таблицы

update на fdw работает неправильно

запрос
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
WITH
  ids AS (
    SELECT id FROM qaz
  )
UPDATE foo
  SET bar = 1	
FROM ids
WHERE foo.id = rec.id)


превращается в
Код: plsql
1.
CONTEXT:  Remote SQL command: UPDATE foo SET bar = $2 WHERE ctid = $1 


получается что FDW думает что ctid якобы уникальный, и им можно оперировать для указания конкретной записи.
а по факту он уникальным не является (является не всегда) -- для набора партиций.


в результате обновляются совершенно случайные записи , с совпадающим ctid!
...
Рейтинг: 0 / 0
09.11.2016, 20:53
    #39344469
qwwq
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Баг update fdw?
Dany305,

откуда мораль -- не присоединяйте предков и прочие суррогаты. присоединяйте сами "партиции" и наследуйте от таблицы--пустышки на стороне присоединения. (и повторяйте логику партицирования на этой пустышке)


забавно, забавно. судя по всему fdw писали люди не знакомые с наследованием в пж. ара калоеды небось (ара--кальный фдв в прошлом был лучше постгресовского)

а што буит при множественном наследоавании ? или вложенном?

...
Рейтинг: 0 / 0
09.11.2016, 21:12
    #39344478
Dany305
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Баг update fdw?
qwwqDany305,
откуда мораль -- не присоединяйте предков и прочие суррогаты. присоединяйте сами "партиции" и наследуйте от таблицы--пустышки на стороне присоединения. (и повторяйте логику партицирования на этой пустышке)


а как тогда ловить появление новых партиций и цеплять к ним fdw?
...
Рейтинг: 0 / 0
09.11.2016, 22:12
    #39344503
qwwq
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Баг update fdw?
Dany305qwwqDany305,
откуда мораль -- не присоединяйте предков и прочие суррогаты. присоединяйте сами "партиции" и наследуйте от таблицы--пустышки на стороне присоединения. (и повторяйте логику партицирования на этой пустышке)


а как тогда ловить появление новых партиций и цеплять к ним fdw?
партицирование зло
а динамическое -- подавно
и кто вам виноват, что вы до него пали
//боюсь не у вас одного это вылезло боком.

теперь надо придумывать динамическое присоединение новых партиций -- потому как апдейт по цид в фдв -- данность (которую вы наблюли экспериментально), написанная людьми немного далёкими от пж. -- следовательно соединять предков попросту нельзя. можно только сами таблицы данных.


попробуйте на стороне апдейта добавить ещё условие , по партицирующему признаку. хотя, боюсь, вам точно так же не удастся просунуть его "на ту сторону". в общем -- надо потыкаться экспериментально.
...
Рейтинг: 0 / 0
10.11.2016, 00:01
    #39344525
qwwq
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Баг update fdw?
qwwq -- потому как апдейт по цид в фдв -- данность (которую вы наблюли экспериментально), написанная людьми немного далёкими от пж.

надеюсь, в следующий раз они таки догадаются добавить " AND tableoid=$2" , <...>

т.ч. пишите скорее письма в спортлото и вырезайте пока fdw--линковку иерархий из продакшыноф. (и планы её запилить)
...
Рейтинг: 0 / 0
10.11.2016, 00:32
    #39344531
ocp_dba_rhce
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Баг update fdw?
qwwqDany305пропущено...


а как тогда ловить появление новых партиций и цеплять к ним fdw?
партицирование зло
а динамическое -- подавно
и кто вам виноват, что вы до него пали


смешно :)
...
Рейтинг: 0 / 0
10.11.2016, 08:55
    #39344577
qwwq
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Баг update fdw?
ocp_dba_rhceqwwqпропущено...

партицирование зло
а динамическое -- подавно
и кто вам виноват, что вы до него пали


смешно :)
ага, уписаться можно.

остается надеяться что это только если в планах запроса на вызывающей стороне -- фулскан.
и что у нас в "2.0" этого нигде не возникает (т.к. фулскан -- "уже "ошибка"")
хотел с утра отписаться. но теперь незачем.
...
Рейтинг: 0 / 0
10.11.2016, 08:56
    #39344578
qwwq
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Баг update fdw?
Dany305,

покажите, каков план запроса на вызывающей стороне
...
Рейтинг: 0 / 0
10.11.2016, 09:33
    #39344585
ocp_dba_rhce
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Баг update fdw?
qwwq,

Там и возникло....
...
Рейтинг: 0 / 0
10.11.2016, 11:31
    #39344664
qwwq
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Баг update fdw?
ocp_dba_rhceqwwq,

Там и возникло....
печаль

есть слабая надежда, что оно так не всегда, а только когда не может пропихнуть условие "как есть" на ту сторону.

т.е. скатывается в плане к фуллскану на стороне линковки и отсылает апдейт по конкретной отобранной фулсканом строке(кам) на ту сторону. (забывая про тейблоиды)

тогда надо развалить конструкцию with .... на plpgsql--ное получение значения в переменную.
и отдельный стейтмент -- апдейт по индексу по значению из переменной, который фдв сможет передать "как есть". (если нельзя клиентом разложить на части). даже бз динамики.

но надежда не очень сильная, да
...
Рейтинг: 0 / 0
10.11.2016, 13:43
    #39344814
antonov.impulsm
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Баг update fdw?
включу сюда в беседу (на всякий случай) -- пару строк кода из /contrib/postgres_fdw/postgres_fdw.c

( https://github.com/postgrespro/postgrespro/blob/PGPRO9_5/contrib/postgres_fdw/postgres_fdw.c )

Datum postgres_fdw_handler(PG_FUNCTION_ARGS)

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
/*
 * Foreign-data wrapper handler function: return a struct with pointers
 * to my callback routines.
 */
Datum
postgres_fdw_handler(PG_FUNCTION_ARGS)
{
	FdwRoutine *routine = makeNode(FdwRoutine);

	/* Functions for scanning foreign tables */
	routine->GetForeignRelSize = postgresGetForeignRelSize;
	routine->GetForeignPaths = postgresGetForeignPaths;
	routine->GetForeignPlan = postgresGetForeignPlan;
	routine->BeginForeignScan = postgresBeginForeignScan;
	routine->IterateForeignScan = postgresIterateForeignScan;
	routine->ReScanForeignScan = postgresReScanForeignScan;
	routine->EndForeignScan = postgresEndForeignScan;

	/* Functions for updating foreign tables */
	routine->AddForeignUpdateTargets = postgresAddForeignUpdateTargets;
	routine->PlanForeignModify = postgresPlanForeignModify;
	routine->BeginForeignModify = postgresBeginForeignModify;
	routine->ExecForeignInsert = postgresExecForeignInsert;
	routine->ExecForeignUpdate = postgresExecForeignUpdate;
	routine->ExecForeignDelete = postgresExecForeignDelete;
	routine->EndForeignModify = postgresEndForeignModify;
	routine->IsForeignRelUpdatable = postgresIsForeignRelUpdatable;

	/* Support functions for EXPLAIN */
	routine->ExplainForeignScan = postgresExplainForeignScan;
	routine->ExplainForeignModify = postgresExplainForeignModify;

	/* Support functions for ANALYZE */
	routine->AnalyzeForeignTable = postgresAnalyzeForeignTable;

	/* Support functions for IMPORT FOREIGN SCHEMA */
	routine->ImportForeignSchema = postgresImportForeignSchema;

	PG_RETURN_POINTER(routine);
}




postgresAddForeignUpdateTargets(..)
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
/*
 * postgresAddForeignUpdateTargets
 *		Add resjunk column(s) needed for update/delete on a foreign table
 */
static void
postgresAddForeignUpdateTargets(Query *parsetree,
								RangeTblEntry *target_rte,
								Relation target_relation)
{
	Var		   *var;
	const char *attrname;
	TargetEntry *tle;

	/*
	 * In postgres_fdw, what we need is the ctid, same as for a regular table.
	 */

	/* Make a Var representing the desired value */
	var = makeVar(parsetree->resultRelation,
				  SelfItemPointerAttributeNumber,
				  TIDOID,
				  -1,
				  InvalidOid,
				  0);

	/* Wrap it in a resjunk TLE with the right name ... */
	attrname = "ctid";

	tle = makeTargetEntry((Expr *) var,
						  list_length(parsetree->targetList) + 1,
						  pstrdup(attrname),
						  true);

	/* ... and add it to the query's targetlist */
	parsetree->targetList = lappend(parsetree->targetList, tle);
}



postgresBeginForeignModify(..)
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
/*
 * postgresBeginForeignModify
 *		Begin an insert/update/delete operation on a foreign table
 */
static void
postgresBeginForeignModify(ModifyTableState *mtstate,
						   ResultRelInfo *resultRelInfo,
						   List *fdw_private,
						   int subplan_index,
						   int eflags)
{
	PgFdwModifyState *fmstate;
	EState	   *estate = mtstate->ps.state;
	CmdType		operation = mtstate->operation;
	Relation	rel = resultRelInfo->ri_RelationDesc;
	RangeTblEntry *rte;
	Oid			userid;
	ForeignTable *table;
	ForeignServer *server;
	UserMapping *user;
	AttrNumber	n_params;
	Oid			typefnoid;
	bool		isvarlena;
	ListCell   *lc;

	/*
	 * Do nothing in EXPLAIN (no ANALYZE) case.  resultRelInfo->ri_FdwState
	 * stays NULL.
	 */
	if (eflags & EXEC_FLAG_EXPLAIN_ONLY)
		return;

	/* Begin constructing PgFdwModifyState. */
	fmstate = (PgFdwModifyState *) palloc0(sizeof(PgFdwModifyState));
	fmstate->rel = rel;

	/*
	 * Identify which user to do the remote access as.  This should match what
	 * ExecCheckRTEPerms() does.
	 */
	rte = rt_fetch(resultRelInfo->ri_RangeTableIndex, estate->es_range_table);
	userid = rte->checkAsUser ? rte->checkAsUser : GetUserId();

	/* Get info about foreign table. */
	table = GetForeignTable(RelationGetRelid(rel));
	server = GetForeignServer(table->serverid);
	user = GetUserMapping(userid, server->serverid);

	/* Open connection; report that we'll create a prepared statement. */
	fmstate->conn = GetConnection(server, user, true);
	fmstate->p_name = NULL;		/* prepared statement not made yet */

	/* Deconstruct fdw_private data. */
	fmstate->query = strVal(list_nth(fdw_private,
									 FdwModifyPrivateUpdateSql));
	fmstate->target_attrs = (List *) list_nth(fdw_private,
											  FdwModifyPrivateTargetAttnums);
	fmstate->has_returning = intVal(list_nth(fdw_private,
											 FdwModifyPrivateHasReturning));
	fmstate->retrieved_attrs = (List *) list_nth(fdw_private,
											 FdwModifyPrivateRetrievedAttrs);

	/* Create context for per-tuple temp workspace. */
	fmstate->temp_cxt = AllocSetContextCreate(estate->es_query_cxt,
											  "postgres_fdw temporary data",
											  ALLOCSET_SMALL_MINSIZE,
											  ALLOCSET_SMALL_INITSIZE,
											  ALLOCSET_SMALL_MAXSIZE);

	/* Prepare for input conversion of RETURNING results. */
	if (fmstate->has_returning)
		fmstate->attinmeta = TupleDescGetAttInMetadata(RelationGetDescr(rel));

	/* Prepare for output conversion of parameters used in prepared stmt. */
	n_params = list_length(fmstate->target_attrs) + 1;
	fmstate->p_flinfo = (FmgrInfo *) palloc0(sizeof(FmgrInfo) * n_params);
	fmstate->p_nums = 0;

	if (operation == CMD_UPDATE || operation == CMD_DELETE)
	{
		/* Find the ctid resjunk column in the subplan's result */
		Plan	   *subplan = mtstate->mt_plans[subplan_index]->plan;

		fmstate->ctidAttno = ExecFindJunkAttributeInTlist(subplan->targetlist,
														  "ctid");
		if (!AttributeNumberIsValid(fmstate->ctidAttno))
			elog(ERROR, "could not find junk ctid column");

		/* First transmittable parameter will be ctid */
		getTypeOutputInfo(TIDOID, &typefnoid, &isvarlena);
		fmgr_info(typefnoid, &fmstate->p_flinfo[fmstate->p_nums]);
		fmstate->p_nums++;
	}

	if (operation == CMD_INSERT || operation == CMD_UPDATE)
	{
		/* Set up for remaining transmittable parameters */
		foreach(lc, fmstate->target_attrs)
		{
			int			attnum = lfirst_int(lc);
			Form_pg_attribute attr = RelationGetDescr(rel)->attrs[attnum - 1];

			Assert(!attr->attisdropped);

			getTypeOutputInfo(attr->atttypid, &typefnoid, &isvarlena);
			fmgr_info(typefnoid, &fmstate->p_flinfo[fmstate->p_nums]);
			fmstate->p_nums++;
		}
	}

	Assert(fmstate->p_nums <= n_params);

	resultRelInfo->ri_FdwState = fmstate;
}

...
Рейтинг: 0 / 0
10.11.2016, 15:02
    #39344927
qwwq
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Баг update fdw?
antonov.impulsm,

подсуньте вместо предка иерархии -- вью на него же. (т.е. подцепите снаружи как ф-таблу вьюху на корень)

1. она (вьюха) в 9.5. д.б. уже апдейтебл без рукописей.
2. и в ней (вьюхе) наверняка не видно ctid -- следовательно fdw может и обломаться со своим недохаком.

хотя "C" я абсолютно не читаю. так, по их же комментам судя, ---- что--то должно "пойти не так".

из минусов -- наиболее вероятен вечный фулскан (или же ашипка)
т.е. чисто экспериментальная ценность.


в спортлото уже отписались ?
...
Рейтинг: 0 / 0
10.11.2016, 15:32
    #39344979
Dany305
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Баг update fdw?
вся сила в deparseUpdateSql() :)
...
Рейтинг: 0 / 0
10.11.2016, 15:40
    #39344992
antonov.impulsm
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Баг update fdw?
Dany305вся сила в deparseUpdateSql() :)

Dany305, да.. это вызывается из ``routine->PlanForeignModify(..)`` ( то есть из ``postgresPlanForeignModify(..)`` )

тут кстати есть не далеко описание этих фнкций:

https://github.com/postgrespro/postgrespro/blob/PGPRO9_5/doc/src/sgml/fdwhandler.sgml

про PlanForeignModify написано:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
<programlisting>
List *
PlanForeignModify (PlannerInfo *root,
                   ModifyTable *plan,
                   Index resultRelation,
                   int subplan_index);
</programlisting>

     Perform any additional planning actions needed for an insert, update, or
     delete on a foreign table.  This function generates the FDW-private
     information that will be attached to the <structname>ModifyTable</> plan
     node that performs the update action.  This private information must
     have the form of a <literal>List</>, and will be delivered to
     <function>BeginForeignModify</> during the execution stage.
    </para>

    <para>
     <literal>root</> is the planner's global information about the query.
     <literal>plan</> is the <structname>ModifyTable</> plan node, which is
     complete except for the <structfield>fdwPrivLists</> field.
     <literal>resultRelation</> identifies the target foreign table by its
     range table index.  <literal>subplan_index</> identifies which target of
     the <structname>ModifyTable</> plan node this is, counting from zero;
     use this if you want to index into <literal>plan->plans</> or other
     substructure of the <literal>plan</> node.
    </para>

    <para>
     See <xref linkend="fdw-planning"> for additional information.
    </para>

    <para>
     If the <function>PlanForeignModify</> pointer is set to
     <literal>NULL</>, no additional plan-time actions are taken, and the
     <literal>fdw_private</> list delivered to
     <function>BeginForeignModify</> will be NIL.
    </para>

<para>
...
Рейтинг: 0 / 0
10.11.2016, 16:00
    #39345020
qwwq
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Баг update fdw?
Dany305,

если тут
https://www.postgresql.org/docs/current/static/ddl-system-columns.html ctid

The physical location of the row version within its table. Note that although the ctid can be used to locate the row version very quickly, a row's ctid will change if it is updated or moved by VACUUM FULL. Therefore ctid is useless as a long-term row identifier. The OID, or even better a user-defined serial number, should be used to identify logical rows.


физ--смысл цтид не ясен. (т.е. степень уникальности/на базу)

есть такая гипотеза :

http://grokbase.com/t/postgresql/pgsql-general/02635say4v/ctid-updates it looks like
(and I'm guessing) that ctid is a page/row offset. So there should be only
one thing at each ctid address.
-------------------------
-------------------------
2#
Also, is ctid unique for each row?
Yes, per table.


откуда марал -- эти экс--пертцы не заложились на наследство (hierarhy) и продинамили часть ключа -- tableoid -- и их надо поскорее пнуть. нас (вас) это не спасает, но упрощает будущее. которое рано или поздно придётся писать.
...
Рейтинг: 0 / 0
14.12.2016, 13:13
    #39366678
RENO4
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Баг update fdw?
Всем доброе время суток!

Так об этом глюке кто-нибудь написал в pgsql-bugs@postgresql.org или еще нет?
Т.е. стоит вообще ожидать какой-то реакции в виде попыток выпуска исправлений в будущих релизах?
...
Рейтинг: 0 / 0
14.12.2016, 13:28
    #39366695
vyegorov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Баг update fdw?
Нужно сделать самостоятельный тест кейс для 9.6.1 версии (как самой свежей), тогда можно будет закинуть.
...
Рейтинг: 0 / 0
14.12.2016, 13:37
    #39366713
RENO4
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Баг update fdw?
qwwq...
т.ч. пишите скорее письма в спортлото и вырезайте пока fdw--линковку иерархий из продакшыноф. (и планы её запилить)


qwwq...
в спортлото уже отписались ?


qwwq...
хотел с утра отписаться. но теперь незачем.


vyegorovНужно сделать самостоятельный тест кейс для 9.6.1 версии (как самой свежей), тогда можно будет закинуть.


Могу, конечно, сделать и сам, но хотелось бы знать, что никого не задублирую. Да и проблема не мною обнаружена.
...
Рейтинг: 0 / 0
14.12.2016, 17:45
    #39367070
qwwq
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Баг update fdw?
RENO4,

там всё очевидно из c--кода даже не читая.
но вот вам тест:

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
DROP TABLE IF EXISTS t_t cascade;
CREATE TABLE t_t 
(part integer NOT NULL 
,t_id serial primary key
,fld text 
,CHECK (part is null ) no inherit
);

CREATE TABLE t_1
(
 CHECK (part =1 ) no inherit 
)
inherits (t_t)
;
CREATE TABLE t_2
(
 CHECK (part = 2 ) no inherit
)
inherits (t_t)
;

CREATE OR REPLACE FUNCTION part_insert_trigger()
RETURNS TRIGGER AS $body$
BEGIN
	IF (NEW.part= 1) THEN
		INSERT INTO t_1 VALUES (NEW.*);
	ELSIF (NEW.part = 2) THEN
		INSERT INTO t_2 VALUES (NEW.*);
	ELSE
		RAISE EXCEPTION 'partition key is out of range.  Fix the trigger function';
		--INSERT INTO t_t VALUES (NEW.*);
	END IF;
	RETURN NULL;
END;
$body$
LANGUAGE plpgsql;

CREATE TRIGGER ins
BEFORE INSERT ON t_t
FOR EACH ROW EXECUTE PROCEDURE part_insert_trigger();
--tests
	INSERT INTO t_t (part /*,t_id*/ ,fld) --values (1,default,'1-chk');
	SELECT 1 +(g%2)  , g::text fROM generate_series (1,1000) g;
	SELECT tableoid::regclass,* FROM t_t;
---------------------------------
CREATE SERVER self
   FOREIGN DATA WRAPPER postgres_fdw
  OPTIONS (port '5433' , dbname 'db1' );

CREATE USER MAPPING FOR postgres
        SERVER self
        OPTIONS (user 'postgres' , password 'postgres' );
---------------------------------
CREATE FOREIGN TABLE public.t_f (
	part integer NOT NULL,
	t_id integer NOT NULL,
	fld text
  ) SERVER self
  OPTIONS (schema_name 'public', table_name 't_t');

----------------------------------
UPDATE t_f SET fld= '000' ||fld WHERE t_id = 500;
Query returned successfully: one row affected, 41 msec execution time.

SELECT * FROM t_f ORDER BY fld ;
------RESULTS-------------------------------------------
2,499,'000500' -- <== что это, берримор ?
1,500,'000500'
2,1,'1'
......
......

...
Рейтинг: 0 / 0
Форумы / PostgreSQL [игнор отключен] [закрыт для гостей] / Баг update fdw? / 19 сообщений из 19, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]