Урок 36. SQLite. Подробнее про метод query. Условие, сортировка, группировка

Обсуждение уроков
betirsolt
Сообщения: 38
Зарегистрирован: 03 июл 2014, 23:45

Re: Урок 36. SQLite. Подробнее про метод query. Условие, сор

Сообщение betirsolt » 10 авг 2014, 01:07

я не пойму зачем тут повторы в регионах?

Код: Выделить всё

String region[] = { "Азия", "Америка", "Америка", "Европа", "Азия",
			"Европа", "Африка", "Европа", "Европа", "Америка" };

Bolt
Сообщения: 5
Зарегистрирован: 03 ноя 2014, 18:22

Re: Урок 36. SQLite. Подробнее про метод query. Условие, сор

Сообщение Bolt » 19 ноя 2014, 20:14

У меня чёт кнопка не робит)) Функции)
В чем проблема?
Он не видит запрос sql count[*] as Count. Остальные кнопки работают.
Вложения
Безымянный213.JPG
Безымянный213.JPG (104.71 КБ) 13944 просмотра

Аватара пользователя
Millik
Сообщения: 7
Зарегистрирован: 18 ноя 2014, 16:54

Re: Урок 36. SQLite. Подробнее про метод query. Условие, сор

Сообщение Millik » 26 ноя 2014, 22:14

Bolt писал(а):У меня чёт кнопка не робит)) Функции)
В чем проблема?
Он не видит запрос sql count[*] as Count. Остальные кнопки работают.
потому что нужно просто "count(*) as Count" (круглые скобки а не квадратные)
betirsolt писал(а):я не пойму зачем тут повторы в регионах?

Код: Выделить всё

String region[] = { "Азия", "Америка", "Америка", "Европа", "Азия",
			"Европа", "Африка", "Европа", "Европа", "Америка" };
по одному значению на каждую запись в таблице
Последний раз редактировалось Millik 26 ноя 2014, 22:15, всего редактировалось 1 раз.

Аватара пользователя
Millik
Сообщения: 7
Зарегистрирован: 18 ноя 2014, 16:54

Re: Урок 36. SQLite. Подробнее про метод query. Условие, сор

Сообщение Millik » 27 ноя 2014, 12:02

Дмитрий Х. писал(а):public void onClick(View v) {
// подключаемся к базе
db = dbHelper.getWritableDatabase();
А зачем подключаться к БД каждый раз при нажатии на кнопку, а потом закрывать подключение? Разве того, что мы подключились в методе OnCreate не достаточно?
Потому, что в конце этого метода подключение и база закрываются. И при каждом нажатии кнопки нужно заново открывать базу и в конце работы закрывать. Можно конечно оставить соединение висеть, но есть шанс, что что-то пойдёт не так, и когда мы попытаемся след раз обратится к базе через это соединение, то словим ошибку.
Foenix писал(а):это не подключение.
Дмитрий Х. писал(а):
Foenix писал(а):это не подключение.
А что тогда, если не соединение с БД?
Foenix писал(а):http://developer.android.com/reference/ ... leDatabase()
метод возвращает в переменную сам объект(instance) бд для записи/чтения
Судя по документу - это нужно делать каждый раз перед записью/чтением из нее.
Это как раз и есть подключение к базе - "Create and/or open a database that will be used for reading and writing."

В апи написано "Once opened successfully, the database is cached, so you can call this method every time you need to write to the database", то есть вы можете каждый раз вызывать это метод.
То есть при первом вызове база открывается и кэшируется + устанавливается соединение. И дальше она открыта до того момента пока не вызван метод close()(Returns: a read/write database object valid until close() is called). Интернете пишут, что все повторные вызовы этого метода, фактически, всего лишь сбрасывают текущее соединение и создают новое.

Почитав что пишут на стэке я сделал выводы, что если все операции производятся в коротком промежутке времени и если шанс того, что что-то пойдёт не так минимален, то можно не вызывать повторно этот метод. Но в реальности, конечно же, все не так. Поэтому нужно перед каждой работой с базой устанавливать новое соединение.

vladsalat93
Сообщения: 5
Зарегистрирован: 09 фев 2015, 17:27

NullPointerException

Сообщение vladsalat93 » 09 мар 2015, 20:53

выкидует NPL на строку в онкриейт с таким содержанием.

Код: Выделить всё

Cursor c = db.query("mytable", null, null, null, null, null, null);
как так? =(

немного поменял код и теперь он меня тычит в пустую строку. Вот весь код.

Код: Выделить всё

package com.example.vladsalat.p0361_simplesqlitequery;

import android.app.Activity;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.*;

import static android.view.View.OnClickListener;


public class MainActivity extends Activity implements OnClickListener {

    final String LOG_TAG = "myLogs";

    String name[] = { "Китай", "США", "Бразилия", "Россия", "Япония",
            "Германия", "Египет", "Италия", "Франция", "Канада" };
    int people[] = { 1400, 311, 195, 142, 128, 82, 80, 60, 66, 35 };
    String region[] = { "Азия", "Америка", "Америка", "Европа", "Азия",
            "Европа", "Африка", "Европа", "Европа", "Америка" };

    Button btnAll, btnFunc, btnPeople, btnSort, btnGroup, btnHaving;
    EditText etFunc, etPeople, etRegionPeople;
    RadioGroup rgSort;

    DBHelper dbHelper;
    SQLiteDatabase db;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        btnAll = (Button) findViewById(R.id.btnAll);
        btnAll.setOnClickListener(this);

        btnFunc = (Button) findViewById(R.id.btnFunc);
        btnFunc.setOnClickListener(this);

        btnPeople = (Button) findViewById(R.id.btnPeople);
        btnPeople.setOnClickListener(this);

        btnSort = (Button) findViewById(R.id.btnSort);
        btnSort.setOnClickListener(this);

        btnGroup = (Button) findViewById(R.id.btnGroup);
        btnGroup.setOnClickListener(this);

        btnHaving = (Button) findViewById(R.id.btnHaving);
        btnHaving.setOnClickListener(this);

        etFunc = (EditText) findViewById(R.id.etFunc);
        etPeople = (EditText) findViewById(R.id.etPeople);
        etRegionPeople = (EditText) findViewById(R.id.etRegionPeople);

        rgSort = (RadioGroup) findViewById(R.id.rgSort);

        dbHelper = new DBHelper(this);
        //подключаемся к базе данных
        db = dbHelper.getWritableDatabase();

        Cursor c = db.query("mytable", null, null, null, null, null, null);
        if (c.getCount() == 0){
            ContentValues cv = new ContentValues();
            for (int i = 0; i<10;i++){
                cv.put("name", name[i]);
                cv.put("people", people[i]);
                cv.put("region", region[i]);
                Log.d(LOG_TAG, "id = " + db.insert("mytable", null, cv));
            }
        }
        c.close();
        dbHelper.close();
        // эмулируем нажатие кнопки btnAll
        onClick(btnAll);
    }


    @Override
    public void onClick(View v) {

        //подключаемся к базе
        db = dbHelper.getWritableDatabase();

        //данные с экрана
        String sFunc = etFunc.getText().toString();
        String sPeople  = etPeople.getText().toString();
        String sRegionPeople = etRegionPeople.getText().toString();

        //переменные для query
        String[] columns = null;
        String selection = null;
        String[] selectionArgs = null;
        String groupBy  = null;
        String having = null;
        String orderBy = null;

        //курсор
        Cursor c = null;

        // определяем нажатую кнопку
        switch (v.getId()){
        //все записи
            case R.id.btnAll:
                Log.d(LOG_TAG,"---Все записи---");
                c = db.query("mytable", null,null,null,null,null,null);
                break;
            //функция
            case R.id.btnFunc:
                Log.d(LOG_TAG, "---функция " + sFunc + "---");
                columns = new String[]{sFunc};
                c = db.query("mytable", columns, null,null,null,null,null);
                break;
            //  население больше, чем
            case R.id.btnPeople:
                Log.d(LOG_TAG, "---население больше" + sPeople + "---" );
                selection = "people > ?";
                selectionArgs = new String[]{sPeople};
                c = db.query("mytable", null, selection, selectionArgs, null,null,null);
                break;
            //население по региону
            case R.id.btnGroup:
                Log.d(LOG_TAG, "---население по региону---");
                columns = new String[]{"region" + "sum(people) as people"};
                groupBy = "region";
                c = db.query("mytable",columns, null, null, groupBy, null,null);
                break;
            //население о региону больше чем
            case R.id.btnHaving:
                Log.d(LOG_TAG, "---Регионы с населением больше чем " + sRegionPeople + "---");
                columns = new String[]{"region", "sum(people) as people"};
                groupBy = "region";
                having = "sum(people) > " + sRegionPeople;
                c = db.query("mytable", null,null, columns, groupBy, having, null);
                break;
            //сортировка
            case R.id.btnSort:
                //сортировка по
                switch (rgSort.getCheckedRadioButtonId()){
                 //наименование
                   case R.id.rName:
                       Log.d(LOG_TAG, "---сортировка по имени---");
                       orderBy = "name";
                       break;
                    case R.id.rPeople:
                        Log.d(LOG_TAG, "---сортировка по населению---");
                        orderBy = "people";
                        break;
                    case R.id.rRegion:
                        Log.d(LOG_TAG, "---сортировка по региону---");
                        orderBy = "region";
                        break;
                }
                c = db.query("mytable", null, null, null, null, null, orderBy);
                break;
        }

        if (c != null){
         if (c.moveToFirst()){
             String str;
             do {
                 str = "";
                 for (String cn : c.getColumnNames()){
                     str = str.concat(cn + " = " + c.getString(c.getColumnIndex(cn)) + "; ");
                 }
                 Log.d(LOG_TAG, str);
             }while (c.moveToNext());
         }
            c.close();
        }
        else Log.d(LOG_TAG, "Cursor is null");

        dbHelper.close();
    }


    class DBHelper extends SQLiteOpenHelper
    {

        public DBHelper(Context context) {
            super(context, "myDB", null, 1);
        }

        @Override
        public void onCreate(SQLiteDatabase db) {

            Log.d(LOG_TAG, "--- onCreate database ---");

            // создаем таблицу с полями

            db.execSQL("create table mytable ("
                    + "id integer primary key autoincrement," + "name text,"
                    + "people integer," + "region text" + ");");

        }

        @Override
        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

        }
    }
}
Последний раз редактировалось vladsalat93 09 мар 2015, 21:29, всего редактировалось 1 раз.

Аватара пользователя
doter.ua
Сообщения: 1106
Зарегистрирован: 23 ноя 2013, 16:08
Откуда: Ukraine

Re: NullPointerException

Сообщение doter.ua » 09 мар 2015, 21:20

vladsalat93 писал(а):выкидует NPL на строку в онкриейт с таким содержанием.

Код: Выделить всё

Cursor c = db.query("mytable", null, null, null, null, null, null);
как так? =(
Логи и код в студию.
Семь раз отмерь - поставь студию.
Эклипс не студия, ошибка вылетит - не исправишь.
Скажи мне кто твой друг, и оба поставили студию.
Студия - свет, а эклипс - тьма.

vladsalat93
Сообщения: 5
Зарегистрирован: 09 фев 2015, 17:27

Re: NullPointerException

Сообщение vladsalat93 » 09 мар 2015, 21:30

doter.ua писал(а):
vladsalat93 писал(а):выкидует NPL на строку в онкриейт с таким содержанием.

Код: Выделить всё

Cursor c = db.query("mytable", null, null, null, null, null, null);
как так? =(
Логи и код в студию.

Код: Выделить всё

03-09 13:42:16.335    1129-1129/com.example.vladsalat.p0361_simplesqlitequery D/AndroidRuntime﹕ Shutting down VM
03-09 13:42:16.335    1129-1129/com.example.vladsalat.p0361_simplesqlitequery W/dalvikvm﹕ threadid=1: thread exiting with uncaught exception (group=0xb3a55ba8)
03-09 13:42:16.385    1129-1129/com.example.vladsalat.p0361_simplesqlitequery E/AndroidRuntime﹕ FATAL EXCEPTION: main
    Process: com.example.vladsalat.p0361_simplesqlitequery, PID: 1129
    java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.vladsalat.p0361_simplesqlitequery/com.example.vladsalat.p0361_simplesqlitequery.MainActivity}: java.lang.NullPointerException
            at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2195)
            at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2245)
            at android.app.ActivityThread.access$800(ActivityThread.java:135)
            at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1196)
            at android.os.Handler.dispatchMessage(Handler.java:102)
            at android.os.Looper.loop(Looper.java:136)
            at android.app.ActivityThread.main(ActivityThread.java:5017)
            at java.lang.reflect.Method.invokeNative(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:515)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:779)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:595)
            at dalvik.system.NativeStart.main(Native Method)
     Caused by: java.lang.NullPointerException
            at com.example.vladsalat.p0361_simplesqlitequery.MainActivity.onCreate(MainActivity.java:67)
            at android.app.Activity.performCreate(Activity.java:5231)
            at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1087)
            at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2159)
            at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2245)
            at android.app.ActivityThread.access$800(ActivityThread.java:135)
            at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1196)
            at android.os.Handler.dispatchMessage(Handler.java:102)
            at android.os.Looper.loop(Looper.java:136)
            at android.app.ActivityThread.main(ActivityThread.java:5017)
            at java.lang.reflect.Method.invokeNative(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:515)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:779)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:595)
            at dalvik.system.NativeStart.main(Native Method)
03-09 13:42:23.815    1129-1129/com.example.vladsalat.p0361_simplesqlitequery I/Process﹕ Sending signal. PID: 1129 SIG: 9
03-09 13:48:59.695    1209-1209/com.example.vladsalat.p0361_simplesqlitequery D/AndroidRuntime﹕ Shutting down VM
03-09 13:48:59.695    1209-1209/com.example.vladsalat.p0361_simplesqlitequery W/dalvikvm﹕ threadid=1: thread exiting with uncaught exception (group=0xb3a55ba8)
03-09 13:48:59.725    1209-1209/com.example.vladsalat.p0361_simplesqlitequery E/AndroidRuntime﹕ FATAL EXCEPTION: main
    Process: com.example.vladsalat.p0361_simplesqlitequery, PID: 1209
    java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.vladsalat.p0361_simplesqlitequery/com.example.vladsalat.p0361_simplesqlitequery.MainActivity}: java.lang.NullPointerException
            at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2195)
            at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2245)
            at android.app.ActivityThread.access$800(ActivityThread.java:135)
            at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1196)
            at android.os.Handler.dispatchMessage(Handler.java:102)
            at android.os.Looper.loop(Looper.java:136)
            at android.app.ActivityThread.main(ActivityThread.java:5017)
            at java.lang.reflect.Method.invokeNative(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:515)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:779)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:595)
            at dalvik.system.NativeStart.main(Native Method)
     Caused by: java.lang.NullPointerException
            at com.example.vladsalat.p0361_simplesqlitequery.MainActivity.onCreate(MainActivity.java:67)
            at android.app.Activity.performCreate(Activity.java:5231)
            at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1087)
            at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2159)
            at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2245)
            at android.app.ActivityThread.access$800(ActivityThread.java:135)
            at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1196)
            at android.os.Handler.dispatchMessage(Handler.java:102)
            at android.os.Looper.loop(Looper.java:136)
            at android.app.ActivityThread.main(ActivityThread.java:5017)
            at java.lang.reflect.Method.invokeNative(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:515)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:779)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:595)
            at dalvik.system.NativeStart.main(Native Method)
03-09 13:49:19.335    1209-1209/com.example.vladsalat.p0361_simplesqlitequery I/Process﹕ Sending signal. PID: 1209 SIG: 9
код добавил в коммент выше

Аватара пользователя
doter.ua
Сообщения: 1106
Зарегистрирован: 23 ноя 2013, 16:08
Откуда: Ukraine

Re: Урок 36. SQLite. Подробнее про метод query. Условие, сор

Сообщение doter.ua » 09 мар 2015, 21:49

Вроде все норм, попробуй переустановить приложение (БД создается при установке приложения, при следующем запуске она уже существует) может дело в ней. Вручную удали приложение на девайсе\эмуляторе.
Семь раз отмерь - поставь студию.
Эклипс не студия, ошибка вылетит - не исправишь.
Скажи мне кто твой друг, и оба поставили студию.
Студия - свет, а эклипс - тьма.

vladsalat93
Сообщения: 5
Зарегистрирован: 09 фев 2015, 17:27

Re: Урок 36. SQLite. Подробнее про метод query. Условие, сор

Сообщение vladsalat93 » 09 мар 2015, 22:37

doter.ua писал(а):Вроде все норм, попробуй переустановить приложение (БД создается при установке приложения, при следующем запуске она уже существует) может дело в ней. Вручную удали приложение на девайсе\эмуляторе.

так и поступил, все заработало. Большое спасибо))

Аватара пользователя
Foenix
Сообщения: 4201
Зарегистрирован: 20 окт 2012, 12:01

Re: Урок 36. SQLite. Подробнее про метод query. Условие, сор

Сообщение Foenix » 09 мар 2015, 22:39

версию бд надо было менять
R.id.team

NullPointerException - что делать???
viewtopic.php?f=33&t=3899&p=28952#p28952
Где моя ошибка?
viewtopic.php?f=60&t=3198

Аватара пользователя
doter.ua
Сообщения: 1106
Зарегистрирован: 23 ноя 2013, 16:08
Откуда: Ukraine

Re: Урок 36. SQLite. Подробнее про метод query. Условие, сор

Сообщение doter.ua » 09 мар 2015, 23:08

Foenix писал(а):версию бд надо было менять
Ну это когда уже релиз был и выбора нет, а так лучше грохнуть приложение)
Семь раз отмерь - поставь студию.
Эклипс не студия, ошибка вылетит - не исправишь.
Скажи мне кто твой друг, и оба поставили студию.
Студия - свет, а эклипс - тьма.

Sanek517s
Сообщения: 33
Зарегистрирован: 03 ноя 2014, 19:39

Re: Урок 36. SQLite. Подробнее про метод query. Условие, сор

Сообщение Sanek517s » 21 мар 2015, 20:00

Как делать запрос из БД с условием? Я никак не могу понять, может кто-то объяснит, пожалуйста?

stskr
Сообщения: 6
Зарегистрирован: 18 апр 2015, 17:52

Re: Урок 36. SQLite. Подробнее про метод query

Сообщение stskr » 06 май 2015, 18:23

Есть ли какой-то инструментарий, который позволяет напрямую написать запрос к базе SQLite?
Когда пишешь запрос через методы класса не очень понятно, какой запрос на выходе получается.
(Соответственно, будет сложно найти ошибку в таком запросе.)

Аватара пользователя
doter.ua
Сообщения: 1106
Зарегистрирован: 23 ноя 2013, 16:08
Откуда: Ukraine

Re: Урок 36. SQLite. Подробнее про метод query

Сообщение doter.ua » 06 май 2015, 18:42

stskr писал(а):Есть ли какой-то инструментарий, который позволяет напрямую написать запрос к базе SQLite?
Когда пишешь запрос через методы класса не очень понятно, какой запрос на выходе получается.
(Соответственно, будет сложно найти ошибку в таком запросе.)

Код: Выделить всё

String query = "SELECT * FROM my_table";
Cursor c = db.rawQuery(query, null);
if (c != null && c.moveToFirst()) {
   // todo
}
Последний раз редактировалось doter.ua 06 май 2015, 18:42, всего редактировалось 1 раз.
Семь раз отмерь - поставь студию.
Эклипс не студия, ошибка вылетит - не исправишь.
Скажи мне кто твой друг, и оба поставили студию.
Студия - свет, а эклипс - тьма.

парень
Сообщения: 223
Зарегистрирован: 30 мар 2013, 22:52

Re: Урок 36. SQLite. Подробнее про метод query. Условие, сор

Сообщение парень » 06 май 2015, 18:42

[syntax=java5]String sql="SELECT * FROM tablename";
Cursor c=mDb.rawQuery(sql, null);
[/syntax]
Типа такого ? :)

Update: Опередили :)
Мой первенец: MyMoney. Менеджер расходов

Бьем рекорды русских топов :)

Могу ответить на любые вопросы по маркетингу и развитию.

stskr
Сообщения: 6
Зарегистрирован: 18 апр 2015, 17:52

Re: Урок 36. SQLite. Подробнее про метод query.

Сообщение stskr » 07 май 2015, 11:43

Нашел ответ сам на свой вопрос:
http://developer.android.com/tools/help/adb.html#sqlite
http://www.sqlite.org/cli.html

Выгружаю файл на комп, а потом открываю его через SQLite Manager.
http://softlakecity.ru/soft/chem-otkryi ... yih-sqlite
http://www.ginktage.com/2013/08/5-popul ... ent-tools/
http://www.youtube.com/watch?v=1eH8de2WIsc
Последний раз редактировалось stskr 07 май 2015, 13:15, всего редактировалось 2 раза.

Аватара пользователя
Foenix
Сообщения: 4201
Зарегистрирован: 20 окт 2012, 12:01

Re: Урок 36. SQLite. Подробнее про метод query. Условие, сор

Сообщение Foenix » 07 май 2015, 13:08

вопросы нужно правильно задавать
R.id.team

NullPointerException - что делать???
viewtopic.php?f=33&t=3899&p=28952#p28952
Где моя ошибка?
viewtopic.php?f=60&t=3198

Аватара пользователя
wtor
Сообщения: 33
Зарегистрирован: 05 янв 2015, 16:27

Re: Урок 36. SQLite. Подробнее про метод query. Условие, сор

Сообщение wtor » 15 май 2015, 19:03

А обязательно указывать логи или это чисто для показа?

Аватара пользователя
Foenix
Сообщения: 4201
Зарегистрирован: 20 окт 2012, 12:01

Re: Урок 36. SQLite. Подробнее про метод query. Условие, сор

Сообщение Foenix » 15 май 2015, 19:22

какие логи, где, для какого показа?
R.id.team

NullPointerException - что делать???
viewtopic.php?f=33&t=3899&p=28952#p28952
Где моя ошибка?
viewtopic.php?f=60&t=3198

Аватара пользователя
wtor
Сообщения: 33
Зарегистрирован: 05 янв 2015, 16:27

Re: Урок 36. SQLite. Подробнее про метод query. Условие, сор

Сообщение wtor » 15 май 2015, 19:36

Foenix писал(а):какие логи, где, для какого показа?
Вложения
2015-05-15_22-32-14.png
2015-05-15_22-32-14.png (25.36 КБ) 13633 просмотра

Ответить