1
0
mirror of https://github.com/MariaDB/server.git synced 2025-05-19 01:41:20 +03:00

7050 Commits

Author SHA1 Message Date
Sergey Petrunya
5eecea8caf MDEV-324: SHOW EXPLAIN: Plan produced by SHOW EXPLAIN for a query with TEMPTABLE view loses 'DERIVED' line
- Make SHOW EXPLAIN code take into account that st_select_lex object without joins can be
  a full-featured SELECTs which were already executed and cleaned up.
2012-06-07 19:55:22 +04:00
unknown
c2677de7ac Merge the fix for lp:944706, mdev-193 2012-06-06 22:26:40 +03:00
Michael Widenius
56ea8e9c05 Fixed build failures found by buildbot
- Added suppression of warnings
- Fixed some test cases


BUILD/FINISH.sh:
  Added AM_EXTRA_MAKEFLAGS
BUILD/SETUP.sh:
  Added option --extra-makeflags
client/mysqldump.c:
  Added suppression
mysql-test/r/mysql.result:
  Updated results
mysql-test/r/mysql_upgrade.result:
  Updated results
mysql-test/r/partition_innodb_plugin.result:
  Updated results
mysql-test/r/partition_open_files_limit.result:
  Updated results
mysql-test/r/symlink.result:
  Updated results
mysql-test/suite/innodb/r/innodb-create-options.result:
  Updated results
mysql-test/suite/innodb/t/innodb-create-options.test:
  Don't print error message (as it's varies on different system)
mysql-test/t/mysql.test:
  Don't print error message (as it's varies on different system)
mysql-test/t/mysql_upgrade.test:
  Fixed checking of error number
mysql-test/t/partition_innodb_plugin.test:
  Don't print error message (as it's varies on different system)
plugin/semisync/semisync_master.cc:
  Added suppression
sql/ha_partition.cc:
  Added suppression
sql/item_subselect.cc:
  Added suppression
sql/multi_range_read.cc:
  Added suppression
sql/sql_parse.cc:
  Added suppression
sql/sql_select.cc:
  Added suppression
storage/innobase/handler/ha_innodb.cc:
  Removed not used variable
storage/maria/ma_delete.c:
  Added suppression
storage/maria/ma_key_recover.c:
  Added suppression
storage/maria/ma_write.c:
  Added suppression
strings/ctype-ucs2.c:
  Added suppression
support-files/compiler_warnings.supp:
  Added suppressions
unittest/mysys/my_vsnprintf-t.c:
  Fixed test case with %M to also work on Solaris
2012-06-05 14:09:18 +03:00
Sergey Petrunya
9a7b3bf4b7 MDEV-299: SHOW EXPLAIN: Plan produced by SHOW EXPLAIN changes back and forth during query execution
- Make SHOW EXPLAIN ignore range accesses when printing "Range checked for each record" plans.
2012-06-04 23:37:45 +04:00
Sergey Petrunya
13e985787e Added comments about create_ref_for_key() 2012-06-04 20:07:02 +04:00
Sergey Petrunya
a8b2e831f0 MDEV-305: SHOW EXPLAIN: ref returned by SHOW EXPLAIN is different from the normal EXPLAIN ('const' vs empty string)
- The problem was that create_ref_for_key() would act differently, depending on 
  whether we're running EXPLAIN or the actual query.
- As the first step, fixed the EXPLAIN printout not to depend on actions in create_ref_for_key().
2012-06-04 19:48:53 +04:00
Sergei Golubchik
3e3606d21d merge with 5.3.
Take only test cases from MDEV-136 Non-blocking "set read_only"
2012-06-04 17:26:11 +02:00
Igor Babaev
27ab01243c Merge 2012-06-01 13:42:39 -07:00
unknown
7ddd5418d0 Fixed bug MDEV-288
CHEAP SQ: Valgrind warnings "Memory lost" with IN and EXISTS nested subquery, materialization+semijoin

Analysis:
The memory leak was a result of the interaction of semi-join optimization
with early optimization of constant subqueries. The function:
setup_jtbm_semi_joins() created a dummy temporary table "dummy_table"
in order to make some JOIN_TAB objects complete. Normally, such temporary
tables are freed inside JOIN_TAB::cleanup.

However, the inner-most subquery is pre-optimized, which allows the
optimization fo the MAX subquery to determine that its WHERE is TRUE,
and thus to compute the result of the MAX during optimization. This
ultimately allows the optimize phase of the outer query to find that
it WHERE clause is FALSE. Once JOIN::optimize finds that the result
set is empty, it sets zero_result_cause, and returns *before* it ever
reached make_join_statistics(). As a result the query plan has no
JOIN_TABs at all. Since the temporary table is supposed to be cleanup
via JOIN_TAB::cleanup, this never happens because there is no JOIN_TAB
for this table. Hence we get a memory leak.

Solution:
Whenever there are no JOIN_TABs, iterate over all table reference in
JOIN::join_list, and free the ones that contain semi-join temporary
tables.
2012-06-01 14:10:15 +03:00
Annamalai Gurusami
a28a2ca798 Bug #13933132: [ERROR] GOT ERROR -1 WHEN READING TABLE APPEARED
WHEN KILLING

Suppose there is a query waiting for a lock.  If the user kills
this query, then "Got error -1 when reading table" error message
must not be logged in the server log file.  Since this is a user
requested interruption, no spurious error message must be logged
in the server log.  This patch will remove the error message from
the log.

approved by joh and tatjana
2012-06-01 14:12:57 +05:30
Annamalai Gurusami
08f360703f Bug #13933132: [ERROR] GOT ERROR -1 WHEN READING TABLE APPEARED
WHEN KILLING

Suppose there is a query waiting for a lock.  If the user kills
this query, then "Got error -1 when reading table" error message
must not be logged in the server log file.  Since this is a user
requested interruption, no spurious error message must be logged
in the server log.  This patch will remove the error message from
the log.

approved by joh and tatjana
2012-06-01 14:12:57 +05:30
Annamalai Gurusami
4acca3431f Merge from mysql-5.1 to mysql-5.5. 2012-06-01 11:49:07 +05:30
Annamalai Gurusami
633fcac144 Merge from mysql-5.1 to mysql-5.5. 2012-06-01 11:49:07 +05:30
Annamalai Gurusami
a2bc9b3669 Bug #13933132: [ERROR] GOT ERROR -1 WHEN READING TABLE APPEARED
WHEN KILLING

Suppose there is a query waiting for a lock.  If the user kills
this query, then "Got error -1 when reading table" error message
must not be logged in the server log file.  Since this is a user
requested interruption, no spurious error message must be logged
in the server log.  This patch will remove the error message from
the log.

approved by joh and tatjana
2012-05-30 10:05:04 +05:30
Annamalai Gurusami
9b92ce0dbd Bug #13933132: [ERROR] GOT ERROR -1 WHEN READING TABLE APPEARED
WHEN KILLING

Suppose there is a query waiting for a lock.  If the user kills
this query, then "Got error -1 when reading table" error message
must not be logged in the server log file.  Since this is a user
requested interruption, no spurious error message must be logged
in the server log.  This patch will remove the error message from
the log.

approved by joh and tatjana
2012-05-30 10:05:04 +05:30
Sergey Petrunya
5b73a17b3a BUG#1002630: Valgrind warnings 'Invalid read' in subselect_engine::calc_const_tables with SELECT
- In JOIN::exec(), make the having->update_used_tables() call before we've
  made the JOIN::cleanup(full=true) call. The latter frees SJ-Materialization
  structures, which correlated subquery predicate items attempt to walk afterwards.
2012-05-25 01:20:40 +04:00
Sergey Petrunya
6f199f7c4f MDEV-275: SHOW EXPLAIN: server crashes in JOIN::print_explain with IN subquery and aggregate function
- Don't try to produce plans after JOIN::cleanup() has been called, because:
   = JOIN::cleanup leaves data structures in partially-cleaned state
   = Walking them is hazardous (see this bug), and has funny effects
     (See previous commits, "Using join cache" may or may not be shown)
   = Changing data structures to be persisted may cause unwanted side effects
- The consequence is that SHOW EXPLAIN will show "Query plan already deleted" when e.g. 
  reading data after filesort.
2012-05-24 22:22:39 +04:00
unknown
d56f5dae1e Fix bug lp:1001506
This is a backport of the (unchaged) fix for MySQL bug #11764372, 57197.

Analysis:

When the outer query finishes its main execution and computes GROUP BY,
it needs to construct a new temporary table (and a corresponding JOIN) to
execute the last DISTINCT operation. At this point JOIN::exec calls
JOIN::join_free, which calls JOIN::cleanup -> TMP_TABLE_PARAM::cleanup
for both the outer and the inner JOINs. The call to the inner
TMP_TABLE_PARAM::cleanup sets copy_field = NULL, but not copy_field_end.

The final execution phase that computes the DISTINCT invokes:
evaluate_join_record -> end_write -> copy_funcs
The last function copies the results of all functions into the temp table.
copy_funcs walks over all functions in join->tmp_table_param.items_to_copy.
In this case items_to_copy contains both assignments to user variables.
The process of copying user variables invokes Item_func_set_user_var::check
which in turn re-evaluates the arguments of the user variable assignment.
This in turn triggers re-evaluation of the subquery, and ultimately
copy_field.

However, the previous call to TMP_TABLE_PARAM::cleanup for the subquery
already set copy_field to NULL but not its copy_field_end. This results
in a null pointer access, and a crash.

Fix:
Set copy_field_end and save_copy_field_end to null when deleting
copy fields in TMP_TABLE_PARAM::cleanup().
2012-05-23 18:18:08 +03:00
Sergey Petrunya
1d3ba8a791 BUG#1000051: Query with simple join and ORDER BY takes thousands times longer when run with ICP
- Disable IndexConditionPushdown for reverse scans.
2012-05-23 11:46:40 +04:00
Sergei Golubchik
7f6f53a8df 5.2 merge 2012-05-20 14:57:29 +02:00
Igor Babaev
d48b4a83a2 Merge. 2012-05-18 09:50:30 -07:00
Sergey Petrunya
02c4c5f735 BUG#1000269: Wrong result (extra rows) with semijoin+materialization, IN subqueries, join_cache_level>0
- make make_cond_after_sjm() correctly handle OR clauses where one branch refers to the semi-join table
  while the other branch refers to the non-semijoin table.
2012-05-18 16:24:12 +04:00
Sergei Golubchik
280fcf0808 5.1 merge 2012-05-18 14:23:05 +02:00
unknown
e5bca74bfb Fixed bug mdev-277 as part of the fix for lp:944706
The cause for this bug is that the method JOIN::get_examined_rows iterates over all
JOIN_TABs of the join assuming they are just a sequence. In the query above, the
innermost subquery is merged into its parent query. When we call
JOIN::get_examined_rows for the second-level subquery, the iteration that
assumes sequential order of join tabs goes outside the join_tab array and calls
the method JOIN_TAB::get_examined_rows on uninitialized memory. 

The fix is to iterate over JOIN_TABs in a way that takes into account the nested
semi-join structure of JOIN_TABs. In particular iterate as select_describe.
2012-05-18 14:52:01 +03:00
Igor Babaev
9b79feba56 Fixed the bug that caused displaying incorrect values in
the column cardinality of the table information_schema.statistics.
2012-05-17 16:54:26 -07:00
unknown
da5214831d Fix for bug lp:944706, task MDEV-193
The patch enables back constant subquery execution during
query optimization after it was disabled during the development
of MWL#89 (cost-based choice of IN-TO-EXISTS vs MATERIALIZATION).

The main idea is that constant subqueries are allowed to be executed
during optimization if their execution is not expensive.

The approach is as follows:
- Constant subqueries are recursively optimized in the beginning of
  JOIN::optimize of the outer query. This is done by the new method
  JOIN::optimize_constant_subqueries(). This is done so that the cost
  of executing these queries can be estimated.
- Optimization of the outer query proceeds normally. During this phase
  the optimizer may request execution of non-expensive constant subqueries.
  Each place where the optimizer may potentially execute an expensive
  expression is guarded with the predicate Item::is_expensive().
- The implementation of Item_subselect::is_expensive has been extended
  to use the number of examined rows (estimated by the optimizer) as a
  way to determine whether the subquery is expensive or not.
- The new system variable "expensive_subquery_limit" controls how many
  examined rows are considered to be not expensive. The default is 100.

In addition, multiple changes were needed to make this solution work
in the light of the changes made by MWL#89. These changes were needed
to fix various crashes and wrong results, and legacy bugs discovered
during development.
2012-05-17 13:46:05 +03:00
Sergei Golubchik
0a8c9b98f6 merge with mysql-5.1.63 2012-05-17 12:12:33 +02:00
Igor Babaev
4dc963a9f3 Fixed LP bug #999251: Q13 from DBT3 uses table scan instead of covering index scan.
The optimizer chose a less efficient execution plan due to the following
defects of the code:
1. the generic handler function handler::keyread_time did not take into account
   that in clustered primary keys record data is included into each index entry
2. the function make_join_readinfo erroneously decided that index only scan
   could not be used if join cache was empoyed.

Added no additional test case.
Adjusted some of the test results.
2012-05-16 20:39:03 -07:00
Sergey Petrunya
34e9a4c1e2 Merge of recent changes in MWL#182 in 5.3 with {Merge of MWL#182 with 5.5} 2012-05-17 00:59:03 +04:00
Sergey Petrunya
dfbd777fd8 MWL#182: SHOW EXPLAIN: Merge 5.3->5.5 2012-05-16 19:20:00 +04:00
Sergey Petrunya
382e81ca84 MDEV-270: SHOW EXPLAIN: server crashes in JOIN::print_explain on a query with
select tables optimized away
- Take into account, that for some degenerate joins instead of "join->table_count=0"
  the code sets "join->tables_list=0".
2012-05-15 15:56:50 +04:00
Olav Sandstaa
c5dc1ea526 Fix for Bug#12667154 SAME QUERY EXEC AS WHERE SUBQ GIVES DIFFERENT
RESULTS ON IN() & NOT IN() COMP #3

This bug causes a wrong result in mysql-trunk when ICP is used
and bad performance in mysql-5.5 and mysql-trunk.

Using the query from bug report to explain what happens and causes
the wrong result from the query when ICP is enabled:

1. The t3 table contains four records. The outer query will read
   these and for each of these it will execute the subquery.

2. Before the first execution of the subquery it will be optimized. In
   this case the important is what happens to the first table t1:
   -make_join_select() will call the range optimizer which decides
    that t1 should be accessed using a range scan on the k1 index
    It creates a QUICK_RANGE_SELECT object for this.
   -As the last part of optimization the ICP code pushes the
    condition down to the storage engine for table t1 on the k1 index.

   This produces the following information in the explain for this table:

     2 DEPENDENT SUBQUERY t1 range k1 k1 5 NULL 3 Using index condition; Using filesort

   Note the use of filesort.

3. The first execution of the subquery does (among other things) due
   to the need for sorting:
   a. Call create_sort_index() which again will call find_all_keys():
   b. find_all_keys() will read the required keys for all qualifying
      rows from the storage engine. To do this it checks if it has a
      quick-select for the table. It will use the quick-select for
      reading records. In this case it will read four records from the
      storage engine (based on the range criteria). The storage engine
      will evaluate the pushed index condition for each record.
   c. At the end of create_sort_index() there is code that cleans up a
      lot of stuff on the join tab. One of the things that is cleaned
      is the select object. The result of this is that the
      quick-select object created in make_join_select is deleted.

4. The second execution of the subquery does the same as the first but
   the result is different:
   a. Call create_sort_index() which again will call find_all_keys()
      (same as for the first execution)
   b. find_all_keys() will read the keys from the storage engine. To
      do this it checks if it has a quick-select for the table. Now
      there is NO quick-select object(!) (since it was deleted in
      step 3c). So find_all_keys defaults to read the table using a
      table scan instead. So instead of reading the four relevant records
      in the range it reads the entire table (6 records). It then
      evaluates the table's condition (and here it goes wrong). Since
      the entire condition has been pushed down to the storage engine
      using ICP all 6 records qualify. (Note that the storage engine
      will not evaluate the pushed index condition in this case since
      it was pushed for the k1 index and now we do a table scan
      without any index being used).
      The result is that here we return six qualifying key values
      instead of four due to not evaluating the table's condition.
   c. As above.

5. The two last execution of the subquery will also produce wrong results
   for the same reason.

Summary: The problem occurs due to all but the first executions of the
subquery is done as a table scan without evaluating the table's
condition (which is pushed to the storage engine on a different
index). This is caused by the create_sort_index() function deleting
the quick-select object that should have been used for executing the
subquery as a range scan.

Note that this bug in addition to causing wrong results also can
result in bad performance due to executing the subquery using a table
scan instead of a range scan. This is an issue in MySQL 5.5.

The fix for this problem is to avoid that the Quick-select-object that
the optimizer created is deleted when create_sort_index() is doing
clean-up of the join-tab. This will ensure that the quick-select
object and the corresponding pushed index condition will be available
and used by all following executions of the subquery.


sql/sql_select.cc:
  Fix for Bug#12667154: Change how create_sort_index() cleans up the 
  join_tab's select and quick-select objects in order to avoid that a 
  quick-select object created outside of create_sort_index() is deleted.
2012-05-16 09:49:23 +02:00
Olav Sandstaa
1e6966228d Fix for Bug#12667154 SAME QUERY EXEC AS WHERE SUBQ GIVES DIFFERENT
RESULTS ON IN() & NOT IN() COMP #3

This bug causes a wrong result in mysql-trunk when ICP is used
and bad performance in mysql-5.5 and mysql-trunk.

Using the query from bug report to explain what happens and causes
the wrong result from the query when ICP is enabled:

1. The t3 table contains four records. The outer query will read
   these and for each of these it will execute the subquery.

2. Before the first execution of the subquery it will be optimized. In
   this case the important is what happens to the first table t1:
   -make_join_select() will call the range optimizer which decides
    that t1 should be accessed using a range scan on the k1 index
    It creates a QUICK_RANGE_SELECT object for this.
   -As the last part of optimization the ICP code pushes the
    condition down to the storage engine for table t1 on the k1 index.

   This produces the following information in the explain for this table:

     2 DEPENDENT SUBQUERY t1 range k1 k1 5 NULL 3 Using index condition; Using filesort

   Note the use of filesort.

3. The first execution of the subquery does (among other things) due
   to the need for sorting:
   a. Call create_sort_index() which again will call find_all_keys():
   b. find_all_keys() will read the required keys for all qualifying
      rows from the storage engine. To do this it checks if it has a
      quick-select for the table. It will use the quick-select for
      reading records. In this case it will read four records from the
      storage engine (based on the range criteria). The storage engine
      will evaluate the pushed index condition for each record.
   c. At the end of create_sort_index() there is code that cleans up a
      lot of stuff on the join tab. One of the things that is cleaned
      is the select object. The result of this is that the
      quick-select object created in make_join_select is deleted.

4. The second execution of the subquery does the same as the first but
   the result is different:
   a. Call create_sort_index() which again will call find_all_keys()
      (same as for the first execution)
   b. find_all_keys() will read the keys from the storage engine. To
      do this it checks if it has a quick-select for the table. Now
      there is NO quick-select object(!) (since it was deleted in
      step 3c). So find_all_keys defaults to read the table using a
      table scan instead. So instead of reading the four relevant records
      in the range it reads the entire table (6 records). It then
      evaluates the table's condition (and here it goes wrong). Since
      the entire condition has been pushed down to the storage engine
      using ICP all 6 records qualify. (Note that the storage engine
      will not evaluate the pushed index condition in this case since
      it was pushed for the k1 index and now we do a table scan
      without any index being used).
      The result is that here we return six qualifying key values
      instead of four due to not evaluating the table's condition.
   c. As above.

5. The two last execution of the subquery will also produce wrong results
   for the same reason.

Summary: The problem occurs due to all but the first executions of the
subquery is done as a table scan without evaluating the table's
condition (which is pushed to the storage engine on a different
index). This is caused by the create_sort_index() function deleting
the quick-select object that should have been used for executing the
subquery as a range scan.

Note that this bug in addition to causing wrong results also can
result in bad performance due to executing the subquery using a table
scan instead of a range scan. This is an issue in MySQL 5.5.

The fix for this problem is to avoid that the Quick-select-object that
the optimizer created is deleted when create_sort_index() is doing
clean-up of the join-tab. This will ensure that the quick-select
object and the corresponding pushed index condition will be available
and used by all following executions of the subquery.
2012-05-16 09:49:23 +02:00
Sergey Petrunya
e1b6e1b899 Merge 5.2->5.3 2012-05-12 12:12:35 +04:00
Sergey Petrunya
97ae1682f1 BUG#997747: Assertion `join->best_read < ((double)1.79..5e+308L)' failed
in greedy_search with LEFT JOINs and unique keys
- Backport the fix for BUG#806524 from MariaDB 5.3
2012-05-12 11:53:14 +04:00
Sergey Petrunya
6bce336624 MDEV-240: SHOW EXPLAIN: Assertion `this->optimized == 2' failed
- Fix the bug: SHOW EXPLAIN may hit a case where a join is partially 
  optimized.
- Change JOIN::optimized to use enum instead of numeric constants
2012-05-11 18:13:06 +04:00
unknown
e10fecc02f Merge 5.2->5.3 2012-05-11 11:40:23 +03:00
Sergei Golubchik
1185420da0 5.3 merge 2012-05-21 20:54:41 +02:00
Sergei Golubchik
431e042b5d c 2012-05-21 15:30:25 +02:00
Sergey Petrunya
6fae4447f0 # MDEV-239: Assertion `field_types == 0 ... ' failed in Protocol_text::store...
- Make all functions that produce parts of EXPLAIN output take 
  explain_flags as parameter, instead of looking into thd->lex->describe
2012-05-10 15:13:57 +04:00
Sergey Petrunya
58b9164f04 MDEV-238: SHOW EXPLAIN: Server crashes in JOIN::print_explain with FROM subquery and GROUP BY
- Support SHOW EXPLAIN for selects that have "Using temporary; Using filesort".
2012-05-10 13:43:48 +04:00
unknown
4e2926d927 Addition to the fix to LP bug#994275.
It is problem of constant propagated to ref* access method (the problem was hiden by using debug binaries for testing).
2012-05-08 19:13:26 +03:00
Sunanda Menon
074ce71e90 Merge from mysql-5.1.63-release 2012-05-08 07:19:14 +02:00
Sunanda Menon
d37a28c9b0 Merge from mysql-5.1.63-release 2012-05-08 07:19:14 +02:00
Joerg Bruehe
5be07ceadd Merge 5.5.24 back into main 5.5.
This is a weave merge, but without any conflicts.
In 14 source files, the copyright year needed to be updated to 2012.
2012-05-07 22:20:42 +02:00
Joerg Bruehe
ad1e123f47 Merge 5.5.24 back into main 5.5.
This is a weave merge, but without any conflicts.
In 14 source files, the copyright year needed to be updated to 2012.
2012-05-07 22:20:42 +02:00
unknown
ea8314fdd5 LP bug#994275 fix.
In 5.3 we substitute constants in ref access values it can't be null so we do not need add NOT NULL for early NULL filtering.
2012-05-07 21:14:37 +03:00
unknown
213476ef3e Fix for bug lp:992405
The patch backports two patches from mysql 5.6:
- BUG#12640437: USING SQL_BUFFER_RESULT RESULTS IN A DIFFERENT QUERY OUTPUT
- Bug#12578908: SELECT SQL_BUFFER_RESULT OUTPUTS TOO MANY ROWS WHEN GROUP IS OPTIMIZED AWAY

Original comment:
-----------------
3714 Jorgen Loland	2012-03-01
      BUG#12640437 - USING SQL_BUFFER_RESULT RESULTS IN A DIFFERENT 
                     QUERY OUTPUT
      
      For all but simple grouped queries, temporary tables are used to
      resolve grouping. In these cases, the list of grouping fields is
      stored in the temporary table and grouping is resolved
      there (e.g. by adding a unique constraint on the involved
      fields). Because of this, grouping is already done when the rows
      are read from the temporary table.
      
      In the case where a group clause may be optimized away, grouping
      does not have to be resolved using a temporary table. However, if
      a temporary table is explicitly requested (e.g. because the
      SQL_BUFFER_RESULT hint is used, or the statement is
      INSERT...SELECT), a temporary table is used anyway. In this case,
      the temporary table is created with an empty group list (because
      the group clause was optimized away) and it will therefore not
      create groups. Since the temporary table does not take care of
      grouping, JOIN::group shall not be set to false in 
      make_simple_join(). This was fixed in bug 12578908. 
      
      However, there is an exception where make_simple_join() should
      set JOIN::group to false even if the query uses a temporary table
      that was explicitly requested but is not strictly needed. That
      exception is if the loose index scan access method (explain
      says "Using index for group-by") is used to read into the 
      temporary table. With loose index scan, grouping is resolved 
      by the access method. This is exactly what happens in this bug.
2012-05-07 11:02:58 +03:00
Sergei Golubchik
44cf9ee5f7 5.3 merge 2012-05-04 07:16:38 +02:00
Sergei Golubchik
99e2ba4848 5.2 merge 2012-05-02 22:02:06 +02:00