Updated database structure, updated sqlite (don't use this source code, it may be changed)

This commit is contained in:
DrKLO 2014-10-09 00:22:22 +04:00
parent 43674c486f
commit c6b1a3430b
20 changed files with 5921 additions and 3321 deletions

File diff suppressed because it is too large Load Diff

View File

@ -107,9 +107,9 @@ extern "C" {
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
** [sqlite_version()] and [sqlite_source_id()].
*/
#define SQLITE_VERSION "3.8.4.1"
#define SQLITE_VERSION_NUMBER 3008004
#define SQLITE_SOURCE_ID "2014-03-11 15:27:36 018d317b1257ce68a92908b05c9c7cf1494050d0"
#define SQLITE_VERSION "3.8.6"
#define SQLITE_VERSION_NUMBER 3008006
#define SQLITE_SOURCE_ID "2014-08-15 11:46:33 9491ba7d738528f168657adb43a198238abde19e"
/*
** CAPI3REF: Run-Time Library Version Numbers
@ -269,7 +269,7 @@ typedef sqlite_uint64 sqlite3_uint64;
**
** ^The sqlite3_close() and sqlite3_close_v2() routines are destructors
** for the [sqlite3] object.
** ^Calls to sqlite3_close() and sqlite3_close_v2() return SQLITE_OK if
** ^Calls to sqlite3_close() and sqlite3_close_v2() return [SQLITE_OK] if
** the [sqlite3] object is successfully destroyed and all associated
** resources are deallocated.
**
@ -277,7 +277,7 @@ typedef sqlite_uint64 sqlite3_uint64;
** statements or unfinished sqlite3_backup objects then sqlite3_close()
** will leave the database connection open and return [SQLITE_BUSY].
** ^If sqlite3_close_v2() is called with unfinalized prepared statements
** and unfinished sqlite3_backups, then the database connection becomes
** and/or unfinished sqlite3_backups, then the database connection becomes
** an unusable "zombie" which will automatically be deallocated when the
** last prepared statement is finalized or the last sqlite3_backup is
** finished. The sqlite3_close_v2() interface is intended for use with
@ -290,7 +290,7 @@ typedef sqlite_uint64 sqlite3_uint64;
** with the [sqlite3] object prior to attempting to close the object. ^If
** sqlite3_close_v2() is called on a [database connection] that still has
** outstanding [prepared statements], [BLOB handles], and/or
** [sqlite3_backup] objects then it returns SQLITE_OK but the deallocation
** [sqlite3_backup] objects then it returns [SQLITE_OK] and the deallocation
** of resources is deferred until all [prepared statements], [BLOB handles],
** and [sqlite3_backup] objects are also destroyed.
**
@ -386,16 +386,14 @@ SQLITE_API int sqlite3_exec(
/*
** CAPI3REF: Result Codes
** KEYWORDS: SQLITE_OK {error code} {error codes}
** KEYWORDS: {result code} {result codes}
** KEYWORDS: {result code definitions}
**
** Many SQLite functions return an integer result code from the set shown
** here in order to indicate success or failure.
**
** New error codes may be added in future versions of SQLite.
**
** See also: [SQLITE_IOERR_READ | extended result codes],
** [sqlite3_vtab_on_conflict()] [SQLITE_ROLLBACK | result codes].
** See also: [extended result code definitions]
*/
#define SQLITE_OK 0 /* Successful result */
/* beginning-of-error-codes */
@ -433,26 +431,19 @@ SQLITE_API int sqlite3_exec(
/*
** CAPI3REF: Extended Result Codes
** KEYWORDS: {extended error code} {extended error codes}
** KEYWORDS: {extended result code} {extended result codes}
** KEYWORDS: {extended result code definitions}
**
** In its default configuration, SQLite API routines return one of 26 integer
** [SQLITE_OK | result codes]. However, experience has shown that many of
** In its default configuration, SQLite API routines return one of 30 integer
** [result codes]. However, experience has shown that many of
** these result codes are too coarse-grained. They do not provide as
** much information about problems as programmers might like. In an effort to
** address this, newer versions of SQLite (version 3.3.8 and later) include
** support for additional result codes that provide more detailed information
** about errors. The extended result codes are enabled or disabled
** about errors. These [extended result codes] are enabled or disabled
** on a per database connection basis using the
** [sqlite3_extended_result_codes()] API.
**
** Some of the available extended result codes are listed here.
** One may expect the number of extended result codes will increase
** over time. Software that uses extended result codes should expect
** to see new result codes in future releases of SQLite.
**
** The SQLITE_OK result code will never be extended. It will always
** be exactly zero.
** [sqlite3_extended_result_codes()] API. Or, the extended code for
** the most recent error can be obtained using
** [sqlite3_extended_errcode()].
*/
#define SQLITE_IOERR_READ (SQLITE_IOERR | (1<<8))
#define SQLITE_IOERR_SHORT_READ (SQLITE_IOERR | (2<<8))
@ -560,7 +551,10 @@ SQLITE_API int sqlite3_exec(
** file that were written at the application level might have changed
** and that adjacent bytes, even bytes within the same sector are
** guaranteed to be unchanged. The SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN
** flag indicate that a file cannot be deleted when open.
** flag indicate that a file cannot be deleted when open. The
** SQLITE_IOCAP_IMMUTABLE flag indicates that the file is on
** read-only media and cannot be changed even by processes with
** elevated privileges.
*/
#define SQLITE_IOCAP_ATOMIC 0x00000001
#define SQLITE_IOCAP_ATOMIC512 0x00000002
@ -575,6 +569,7 @@ SQLITE_API int sqlite3_exec(
#define SQLITE_IOCAP_SEQUENTIAL 0x00000400
#define SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN 0x00000800
#define SQLITE_IOCAP_POWERSAFE_OVERWRITE 0x00001000
#define SQLITE_IOCAP_IMMUTABLE 0x00002000
/*
** CAPI3REF: File Locking Levels
@ -681,7 +676,7 @@ struct sqlite3_file {
** locking strategy (for example to use dot-file locks), to inquire
** about the status of a lock, or to break stale locks. The SQLite
** core reserves all opcodes less than 100 for its own use.
** A [SQLITE_FCNTL_LOCKSTATE | list of opcodes] less than 100 is available.
** A [file control opcodes | list of opcodes] less than 100 is available.
** Applications that define a custom xFileControl method should use opcodes
** greater than 100 to avoid conflicts. VFS implementations should
** return [SQLITE_NOTFOUND] for file control opcodes that they do not
@ -754,6 +749,7 @@ struct sqlite3_io_methods {
/*
** CAPI3REF: Standard File Control Opcodes
** KEYWORDS: {file control opcodes} {file control opcode}
**
** These integer constants are opcodes for the xFileControl method
** of the [sqlite3_io_methods] object and for the [sqlite3_file_control()]
@ -943,6 +939,12 @@ struct sqlite3_io_methods {
** on whether or not the file has been renamed, moved, or deleted since it
** was first opened.
**
** <li>[[SQLITE_FCNTL_WIN32_SET_HANDLE]]
** The [SQLITE_FCNTL_WIN32_SET_HANDLE] opcode is used for debugging. This
** opcode causes the xFileControl method to swap the file handle with the one
** pointed to by the pArg argument. This capability is used during testing
** and only needs to be supported when SQLITE_TEST is defined.
**
** </ul>
*/
#define SQLITE_FCNTL_LOCKSTATE 1
@ -966,6 +968,7 @@ struct sqlite3_io_methods {
#define SQLITE_FCNTL_HAS_MOVED 20
#define SQLITE_FCNTL_SYNC 21
#define SQLITE_FCNTL_COMMIT_PHASETWO 22
#define SQLITE_FCNTL_WIN32_SET_HANDLE 23
/*
** CAPI3REF: Mutex Handle
@ -2026,27 +2029,33 @@ SQLITE_API int sqlite3_complete16(const void *sql);
/*
** CAPI3REF: Register A Callback To Handle SQLITE_BUSY Errors
**
** ^This routine sets a callback function that might be invoked whenever
** an attempt is made to open a database table that another thread
** or process has locked.
** ^The sqlite3_busy_handler(D,X,P) routine sets a callback function X
** that might be invoked with argument P whenever
** an attempt is made to access a database table associated with
** [database connection] D when another thread
** or process has the table locked.
** The sqlite3_busy_handler() interface is used to implement
** [sqlite3_busy_timeout()] and [PRAGMA busy_timeout].
**
** ^If the busy callback is NULL, then [SQLITE_BUSY] or [SQLITE_IOERR_BLOCKED]
** ^If the busy callback is NULL, then [SQLITE_BUSY]
** is returned immediately upon encountering the lock. ^If the busy callback
** is not NULL, then the callback might be invoked with two arguments.
**
** ^The first argument to the busy handler is a copy of the void* pointer which
** is the third argument to sqlite3_busy_handler(). ^The second argument to
** the busy handler callback is the number of times that the busy handler has
** been invoked for this locking event. ^If the
** been invoked for the same locking event. ^If the
** busy callback returns 0, then no additional attempts are made to
** access the database and [SQLITE_BUSY] or [SQLITE_IOERR_BLOCKED] is returned.
** access the database and [SQLITE_BUSY] is returned
** to the application.
** ^If the callback returns non-zero, then another attempt
** is made to open the database for reading and the cycle repeats.
** is made to access the database and the cycle repeats.
**
** The presence of a busy handler does not guarantee that it will be invoked
** when there is lock contention. ^If SQLite determines that invoking the busy
** handler could result in a deadlock, it will go ahead and return [SQLITE_BUSY]
** or [SQLITE_IOERR_BLOCKED] instead of invoking the busy handler.
** to the application instead of invoking the
** busy handler.
** Consider a scenario where one process is holding a read lock that
** it is trying to promote to a reserved lock and
** a second process is holding a reserved lock that it is trying
@ -2060,28 +2069,15 @@ SQLITE_API int sqlite3_complete16(const void *sql);
**
** ^The default busy callback is NULL.
**
** ^The [SQLITE_BUSY] error is converted to [SQLITE_IOERR_BLOCKED]
** when SQLite is in the middle of a large transaction where all the
** changes will not fit into the in-memory cache. SQLite will
** already hold a RESERVED lock on the database file, but it needs
** to promote this lock to EXCLUSIVE so that it can spill cache
** pages into the database file without harm to concurrent
** readers. ^If it is unable to promote the lock, then the in-memory
** cache will be left in an inconsistent state and so the error
** code is promoted from the relatively benign [SQLITE_BUSY] to
** the more severe [SQLITE_IOERR_BLOCKED]. ^This error code promotion
** forces an automatic rollback of the changes. See the
** <a href="/cvstrac/wiki?p=CorruptionFollowingBusyError">
** CorruptionFollowingBusyError</a> wiki page for a discussion of why
** this is important.
**
** ^(There can only be a single busy handler defined for each
** [database connection]. Setting a new busy handler clears any
** previously set handler.)^ ^Note that calling [sqlite3_busy_timeout()]
** will also set or clear the busy handler.
** or evaluating [PRAGMA busy_timeout=N] will change the
** busy handler and thus clear any previously set busy handler.
**
** The busy callback should not take any actions which modify the
** database connection that invoked the busy handler. Any such actions
** database connection that invoked the busy handler. In other words,
** the busy handler is not reentrant. Any such actions
** result in undefined behavior.
**
** A busy handler must not close the database connection
@ -2097,7 +2093,7 @@ SQLITE_API int sqlite3_busy_handler(sqlite3*, int(*)(void*,int), void*);
** will sleep multiple times until at least "ms" milliseconds of sleeping
** have accumulated. ^After at least "ms" milliseconds of sleeping,
** the handler returns 0 which causes [sqlite3_step()] to return
** [SQLITE_BUSY] or [SQLITE_IOERR_BLOCKED].
** [SQLITE_BUSY].
**
** ^Calling this routine with an argument less than or equal to zero
** turns off all busy handlers.
@ -2106,6 +2102,8 @@ SQLITE_API int sqlite3_busy_handler(sqlite3*, int(*)(void*,int), void*);
** [database connection] any any given moment. If another busy handler
** was defined (using [sqlite3_busy_handler()]) prior to calling
** this routine, that other busy handler is cleared.)^
**
** See also: [PRAGMA busy_timeout]
*/
SQLITE_API int sqlite3_busy_timeout(sqlite3*, int ms);
@ -2507,8 +2505,8 @@ SQLITE_API int sqlite3_set_authorizer(
** [sqlite3_set_authorizer | authorizer documentation] for additional
** information.
**
** Note that SQLITE_IGNORE is also used as a [SQLITE_ROLLBACK | return code]
** from the [sqlite3_vtab_on_conflict()] interface.
** Note that SQLITE_IGNORE is also used as a [conflict resolution mode]
** returned from the [sqlite3_vtab_on_conflict()] interface.
*/
#define SQLITE_DENY 1 /* Abort the SQL statement with an error */
#define SQLITE_IGNORE 2 /* Don't allow access, but don't generate an error */
@ -2779,6 +2777,30 @@ SQLITE_API void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
** ^If sqlite3_open_v2() is used and the "cache" parameter is present in
** a URI filename, its value overrides any behavior requested by setting
** SQLITE_OPEN_PRIVATECACHE or SQLITE_OPEN_SHAREDCACHE flag.
**
** <li> <b>psow</b>: ^The psow parameter may be "true" (or "on" or "yes" or
** "1") or "false" (or "off" or "no" or "0") to indicate that the
** [powersafe overwrite] property does or does not apply to the
** storage media on which the database file resides. ^The psow query
** parameter only works for the built-in unix and Windows VFSes.
**
** <li> <b>nolock</b>: ^The nolock parameter is a boolean query parameter
** which if set disables file locking in rollback journal modes. This
** is useful for accessing a database on a filesystem that does not
** support locking. Caution: Database corruption might result if two
** or more processes write to the same database and any one of those
** processes uses nolock=1.
**
** <li> <b>immutable</b>: ^The immutable parameter is a boolean query
** parameter that indicates that the database file is stored on
** read-only media. ^When immutable is set, SQLite assumes that the
** database file cannot be changed, even by a process with higher
** privilege, and so the database is opened read-only and all locking
** and change detection is disabled. Caution: Setting the immutable
** property on a database file that does in fact change can result
** in incorrect query results and/or [SQLITE_CORRUPT] errors.
** See also: [SQLITE_IOCAP_IMMUTABLE].
**
** </ul>
**
** ^Specifying an unknown parameter in the query component of a URI is not an
@ -2808,8 +2830,9 @@ SQLITE_API void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
** Open file "data.db" in the current directory for read-only access.
** Regardless of whether or not shared-cache mode is enabled by
** default, use a private cache.
** <tr><td> file:/home/fred/data.db?vfs=unix-nolock <td>
** Open file "/home/fred/data.db". Use the special VFS "unix-nolock".
** <tr><td> file:/home/fred/data.db?vfs=unix-dotfile <td>
** Open file "/home/fred/data.db". Use the special VFS "unix-dotfile"
** that uses dot-files in place of posix advisory locking.
** <tr><td> file:data.db?mode=readonly <td>
** An error. "readonly" is not a valid option for the "mode" parameter.
** </table>
@ -4670,6 +4693,13 @@ SQLITE_API int sqlite3_sleep(int);
** is a NULL pointer, then SQLite performs a search for an appropriate
** temporary file directory.
**
** Applications are strongly discouraged from using this global variable.
** It is required to set a temporary folder on Windows Runtime (WinRT).
** But for all other platforms, it is highly recommended that applications
** neither read nor write this variable. This global variable is a relic
** that exists for backwards compatibility of legacy applications and should
** be avoided in new projects.
**
** It is not safe to read or modify this variable in more than one
** thread at a time. It is not safe to read or modify this variable
** if a [database connection] is being used at the same time in a separate
@ -4688,6 +4718,11 @@ SQLITE_API int sqlite3_sleep(int);
** Hence, if this variable is modified directly, either it should be
** made NULL or made to point to memory obtained from [sqlite3_malloc]
** or else the use of the [temp_store_directory pragma] should be avoided.
** Except when requested by the [temp_store_directory pragma], SQLite
** does not free the memory that sqlite3_temp_directory points to. If
** the application wants that memory to be freed, it must do
** so itself, taking care to only do so after all [database connection]
** objects have been destroyed.
**
** <b>Note to Windows Runtime users:</b> The temporary directory must be set
** prior to calling [sqlite3_open] or [sqlite3_open_v2]. Otherwise, various
@ -5822,10 +5857,12 @@ SQLITE_API int sqlite3_vfs_unregister(sqlite3_vfs*);
** <li> SQLITE_MUTEX_RECURSIVE
** <li> SQLITE_MUTEX_STATIC_MASTER
** <li> SQLITE_MUTEX_STATIC_MEM
** <li> SQLITE_MUTEX_STATIC_MEM2
** <li> SQLITE_MUTEX_STATIC_OPEN
** <li> SQLITE_MUTEX_STATIC_PRNG
** <li> SQLITE_MUTEX_STATIC_LRU
** <li> SQLITE_MUTEX_STATIC_LRU2
** <li> SQLITE_MUTEX_STATIC_PMEM
** <li> SQLITE_MUTEX_STATIC_APP1
** <li> SQLITE_MUTEX_STATIC_APP2
** </ul>)^
**
** ^The first two constants (SQLITE_MUTEX_FAST and SQLITE_MUTEX_RECURSIVE)
@ -6029,6 +6066,9 @@ SQLITE_API int sqlite3_mutex_notheld(sqlite3_mutex*);
#define SQLITE_MUTEX_STATIC_LRU 6 /* lru page list */
#define SQLITE_MUTEX_STATIC_LRU2 7 /* NOT USED */
#define SQLITE_MUTEX_STATIC_PMEM 7 /* sqlite3PageMalloc() */
#define SQLITE_MUTEX_STATIC_APP1 8 /* For use by application */
#define SQLITE_MUTEX_STATIC_APP2 9 /* For use by application */
#define SQLITE_MUTEX_STATIC_APP3 10 /* For use by application */
/*
** CAPI3REF: Retrieve the mutex for a database connection
@ -6123,7 +6163,9 @@ SQLITE_API int sqlite3_test_control(int op, ...);
#define SQLITE_TESTCTRL_EXPLAIN_STMT 19
#define SQLITE_TESTCTRL_NEVER_CORRUPT 20
#define SQLITE_TESTCTRL_VDBE_COVERAGE 21
#define SQLITE_TESTCTRL_LAST 21
#define SQLITE_TESTCTRL_BYTEORDER 22
#define SQLITE_TESTCTRL_ISINIT 23
#define SQLITE_TESTCTRL_LAST 23
/*
** CAPI3REF: SQLite Runtime Status
@ -7107,6 +7149,9 @@ SQLITE_API void *sqlite3_wal_hook(
** ^The [wal_autocheckpoint pragma] can be used to invoke this interface
** from SQL.
**
** ^Checkpoints initiated by this mechanism are
** [sqlite3_wal_checkpoint_v2|PASSIVE].
**
** ^Every new [database connection] defaults to having the auto-checkpoint
** enabled with a threshold of 1000 or [SQLITE_DEFAULT_WAL_AUTOCHECKPOINT]
** pages. The use of this interface
@ -7123,6 +7168,10 @@ SQLITE_API int sqlite3_wal_autocheckpoint(sqlite3 *db, int N);
** empty string, then a checkpoint is run on all databases of
** connection D. ^If the database connection D is not in
** [WAL | write-ahead log mode] then this interface is a harmless no-op.
** ^The [sqlite3_wal_checkpoint(D,X)] interface initiates a
** [sqlite3_wal_checkpoint_v2|PASSIVE] checkpoint.
** Use the [sqlite3_wal_checkpoint_v2()] interface to get a FULL
** or RESET checkpoint.
**
** ^The [wal_checkpoint pragma] can be used to invoke this interface
** from SQL. ^The [sqlite3_wal_autocheckpoint()] interface and the
@ -7145,10 +7194,12 @@ SQLITE_API int sqlite3_wal_checkpoint(sqlite3 *db, const char *zDb);
** Checkpoint as many frames as possible without waiting for any database
** readers or writers to finish. Sync the db file if all frames in the log
** are checkpointed. This mode is the same as calling
** sqlite3_wal_checkpoint(). The busy-handler callback is never invoked.
** sqlite3_wal_checkpoint(). The [sqlite3_busy_handler|busy-handler callback]
** is never invoked.
**
** <dt>SQLITE_CHECKPOINT_FULL<dd>
** This mode blocks (calls the busy-handler callback) until there is no
** This mode blocks (it invokes the
** [sqlite3_busy_handler|busy-handler callback]) until there is no
** database writer and all readers are reading from the most recent database
** snapshot. It then checkpoints all frames in the log file and syncs the
** database file. This call blocks database writers while it is running,
@ -7156,7 +7207,8 @@ SQLITE_API int sqlite3_wal_checkpoint(sqlite3 *db, const char *zDb);
**
** <dt>SQLITE_CHECKPOINT_RESTART<dd>
** This mode works the same way as SQLITE_CHECKPOINT_FULL, except after
** checkpointing the log file it blocks (calls the busy-handler callback)
** checkpointing the log file it blocks (calls the
** [sqlite3_busy_handler|busy-handler callback])
** until all readers are reading from the database file only. This ensures
** that the next client to write to the database file restarts the log file
** from the beginning. This call blocks database writers while it is running,
@ -7294,6 +7346,7 @@ SQLITE_API int sqlite3_vtab_on_conflict(sqlite3 *);
/*
** CAPI3REF: Conflict resolution modes
** KEYWORDS: {conflict resolution mode}
**
** These constants are returned by [sqlite3_vtab_on_conflict()] to
** inform a [virtual table] implementation what the [ON CONFLICT] mode
@ -7346,6 +7399,16 @@ extern "C" {
#endif
typedef struct sqlite3_rtree_geometry sqlite3_rtree_geometry;
typedef struct sqlite3_rtree_query_info sqlite3_rtree_query_info;
/* The double-precision datatype used by RTree depends on the
** SQLITE_RTREE_INT_ONLY compile-time option.
*/
#ifdef SQLITE_RTREE_INT_ONLY
typedef sqlite3_int64 sqlite3_rtree_dbl;
#else
typedef double sqlite3_rtree_dbl;
#endif
/*
** Register a geometry callback named zGeom that can be used as part of an
@ -7356,11 +7419,7 @@ typedef struct sqlite3_rtree_geometry sqlite3_rtree_geometry;
SQLITE_API int sqlite3_rtree_geometry_callback(
sqlite3 *db,
const char *zGeom,
#ifdef SQLITE_RTREE_INT_ONLY
int (*xGeom)(sqlite3_rtree_geometry*, int n, sqlite3_int64 *a, int *pRes),
#else
int (*xGeom)(sqlite3_rtree_geometry*, int n, double *a, int *pRes),
#endif
int (*xGeom)(sqlite3_rtree_geometry*, int, sqlite3_rtree_dbl*,int*),
void *pContext
);
@ -7372,11 +7431,60 @@ SQLITE_API int sqlite3_rtree_geometry_callback(
struct sqlite3_rtree_geometry {
void *pContext; /* Copy of pContext passed to s_r_g_c() */
int nParam; /* Size of array aParam[] */
double *aParam; /* Parameters passed to SQL geom function */
sqlite3_rtree_dbl *aParam; /* Parameters passed to SQL geom function */
void *pUser; /* Callback implementation user data */
void (*xDelUser)(void *); /* Called by SQLite to clean up pUser */
};
/*
** Register a 2nd-generation geometry callback named zScore that can be
** used as part of an R-Tree geometry query as follows:
**
** SELECT ... FROM <rtree> WHERE <rtree col> MATCH $zQueryFunc(... params ...)
*/
SQLITE_API int sqlite3_rtree_query_callback(
sqlite3 *db,
const char *zQueryFunc,
int (*xQueryFunc)(sqlite3_rtree_query_info*),
void *pContext,
void (*xDestructor)(void*)
);
/*
** A pointer to a structure of the following type is passed as the
** argument to scored geometry callback registered using
** sqlite3_rtree_query_callback().
**
** Note that the first 5 fields of this structure are identical to
** sqlite3_rtree_geometry. This structure is a subclass of
** sqlite3_rtree_geometry.
*/
struct sqlite3_rtree_query_info {
void *pContext; /* pContext from when function registered */
int nParam; /* Number of function parameters */
sqlite3_rtree_dbl *aParam; /* value of function parameters */
void *pUser; /* callback can use this, if desired */
void (*xDelUser)(void*); /* function to free pUser */
sqlite3_rtree_dbl *aCoord; /* Coordinates of node or entry to check */
unsigned int *anQueue; /* Number of pending entries in the queue */
int nCoord; /* Number of coordinates */
int iLevel; /* Level of current node or entry */
int mxLevel; /* The largest iLevel value in the tree */
sqlite3_int64 iRowid; /* Rowid for current entry */
sqlite3_rtree_dbl rParentScore; /* Score of parent node */
int eParentWithin; /* Visibility of parent node */
int eWithin; /* OUT: Visiblity */
sqlite3_rtree_dbl rScore; /* OUT: Write the score here */
};
/*
** Allowed values for sqlite3_rtree_query.eWithin and .eParentWithin.
*/
#define NOT_WITHIN 0 /* Object completely outside of query region */
#define PARTLY_WITHIN 1 /* Object partially overlaps query region */
#define FULLY_WITHIN 2 /* Object fully contained within query region */
#ifdef __cplusplus
} /* end of the 'extern "C"' block */

View File

@ -236,7 +236,7 @@ public class ContactsController {
ContentResolver cr = ApplicationLoader.applicationContext.getContentResolver();
HashMap<String, Contact> shortContacts = new HashMap<String, Contact>();
String ids = "";
StringBuilder ids = new StringBuilder();
Cursor pCur = cr.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, projectionPhones, null, null, null);
if (pCur != null) {
if (pCur.getCount() > 0) {
@ -262,9 +262,9 @@ public class ContactsController {
Integer id = pCur.getInt(0);
if (ids.length() != 0) {
ids += ",";
ids.append(",");
}
ids += id;
ids.append(id);
int type = pCur.getInt(2);
Contact contact = contactsMap.get(id);
@ -299,7 +299,7 @@ public class ContactsController {
pCur.close();
}
pCur = cr.query(ContactsContract.Data.CONTENT_URI, projectionNames, ContactsContract.CommonDataKinds.StructuredName.CONTACT_ID + " IN (" + ids + ") AND " + ContactsContract.Data.MIMETYPE + " = '" + ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE + "'", null, null);
pCur = cr.query(ContactsContract.Data.CONTENT_URI, projectionNames, ContactsContract.CommonDataKinds.StructuredName.CONTACT_ID + " IN (" + ids.toString() + ") AND " + ContactsContract.Data.MIMETYPE + " = '" + ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE + "'", null, null);
if (pCur != null && pCur.getCount() > 0) {
while (pCur.moveToNext()) {
int id = pCur.getInt(0);
@ -844,14 +844,14 @@ public class ContactsController {
return 0;
}
});
String ids = "";
StringBuilder ids = new StringBuilder();
for (TLRPC.TL_contact aContactsArr : contactsArr) {
if (ids.length() != 0) {
ids += ",";
ids.append(",");
}
ids += aContactsArr.user_id;
ids.append(aContactsArr.user_id);
}
UserConfig.contactsHash = Utilities.MD5(ids);
UserConfig.contactsHash = Utilities.MD5(ids.toString());
UserConfig.saveConfig(false);
}
@ -1084,7 +1084,7 @@ public class ContactsController {
});
}
String ids = "";
StringBuilder ids = new StringBuilder();
final HashMap<String, ArrayList<TLRPC.TL_contact>> sectionsDict = new HashMap<String, ArrayList<TLRPC.TL_contact>>();
final ArrayList<String> sortedSectionsArray = new ArrayList<String>();
@ -1114,11 +1114,11 @@ public class ContactsController {
}
arr.add(value);
if (ids.length() != 0) {
ids += ",";
ids.append(",");
}
ids += value.user_id;
ids.append(value.user_id);
}
UserConfig.contactsHash = Utilities.MD5(ids);
UserConfig.contactsHash = Utilities.MD5(ids.toString());
UserConfig.saveConfig(false);
Collections.sort(sortedSectionsArray, new Comparator<String>() {
@ -1189,8 +1189,8 @@ public class ContactsController {
}
FileLog.e("tmessages", "process update - contacts add = " + newC.size() + " delete = " + contactsTD.size());
String toAdd = "";
String toDelete = "";
StringBuilder toAdd = new StringBuilder();
StringBuilder toDelete = new StringBuilder();
boolean reloadContacts = false;
for (TLRPC.TL_contact newContact : newC) {
@ -1216,9 +1216,9 @@ public class ContactsController {
}
}
if (toAdd.length() != 0) {
toAdd += ",";
toAdd.append(",");
}
toAdd += user.phone;
toAdd.append(user.phone);
}
for (final Integer uid : contactsTD) {
@ -1252,14 +1252,14 @@ public class ContactsController {
}
}
if (toDelete.length() != 0) {
toDelete += ",";
toDelete.append(",");
}
toDelete += user.phone;
toDelete.append(user.phone);
}
}
if (toAdd.length() != 0 || toDelete.length() != 0) {
MessagesStorage.getInstance().applyPhoneBookUpdates(toAdd, toDelete);
MessagesStorage.getInstance().applyPhoneBookUpdates(toAdd.toString(), toDelete.toString());
}
if (reloadContacts) {

View File

@ -69,7 +69,6 @@ public class MessagesController implements NotificationCenter.NotificationCenter
private boolean gettingNewDeleteTask = false;
private int currentDeletingTaskTime = 0;
private Long currentDeletingTask = null;
private ArrayList<Integer> currentDeletingTaskMids = null;
public int totalDialogsCount = 0;
@ -322,7 +321,6 @@ public class MessagesController implements NotificationCenter.NotificationCenter
currentDeletingTaskTime = 0;
currentDeletingTaskMids = null;
gettingNewDeleteTask = false;
currentDeletingTask = null;
loadingDialogs = false;
dialogsEndReached = false;
gettingDifference = false;
@ -508,14 +506,14 @@ public class MessagesController implements NotificationCenter.NotificationCenter
Utilities.stageQueue.postRunnable(new Runnable() {
@Override
public void run() {
if (currentDeletingTask == null && !gettingNewDeleteTask || currentDeletingTaskTime != 0 && minDate < currentDeletingTaskTime) {
if (currentDeletingTaskMids == null && !gettingNewDeleteTask || currentDeletingTaskTime != 0 && minDate < currentDeletingTaskTime) {
getNewDeleteTask(null);
}
}
});
}
public void getNewDeleteTask(final Long oldTask) {
public void getNewDeleteTask(final ArrayList<Integer> oldTask) {
Utilities.stageQueue.postRunnable(new Runnable() {
@Override
public void run() {
@ -528,7 +526,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter
private void checkDeletingTask() {
int currentServerTime = ConnectionsManager.getInstance().getCurrentTime();
if (currentDeletingTask != null && currentDeletingTaskTime != 0 && currentDeletingTaskTime <= currentServerTime) {
if (currentDeletingTaskMids != null && currentDeletingTaskTime != 0 && currentDeletingTaskTime <= currentServerTime) {
currentDeletingTaskTime = 0;
AndroidUtilities.RunOnUIThread(new Runnable() {
@Override
@ -538,9 +536,9 @@ public class MessagesController implements NotificationCenter.NotificationCenter
Utilities.stageQueue.postRunnable(new Runnable() {
@Override
public void run() {
getNewDeleteTask(currentDeletingTask);
getNewDeleteTask(currentDeletingTaskMids);
currentDeletingTaskTime = 0;
currentDeletingTask = null;
currentDeletingTaskMids = null;
}
});
}
@ -548,20 +546,18 @@ public class MessagesController implements NotificationCenter.NotificationCenter
}
}
public void processLoadedDeleteTask(final Long taskId, final int taskTime, final ArrayList<Integer> messages) {
public void processLoadedDeleteTask(final int taskTime, final ArrayList<Integer> messages) {
Utilities.stageQueue.postRunnable(new Runnable() {
@Override
public void run() {
gettingNewDeleteTask = false;
if (taskId != null) {
if (messages != null) {
currentDeletingTaskTime = taskTime;
currentDeletingTask = taskId;
currentDeletingTaskMids = messages;
checkDeletingTask();
} else {
currentDeletingTaskTime = 0;
currentDeletingTask = null;
currentDeletingTaskMids = null;
}
}
@ -1275,10 +1271,10 @@ public class MessagesController implements NotificationCenter.NotificationCenter
}
}
public void loadMessages(final long dialog_id, final int count, final int max_id, boolean fromCache, int midDate, final int classGuid, boolean from_unread, boolean forward) {
public void loadMessages(final long dialog_id, final int count, final int max_id, boolean fromCache, int midDate, final int classGuid, boolean from_unread, boolean forward, final Semaphore semaphore) {
int lower_part = (int)dialog_id;
if (fromCache || lower_part == 0) {
MessagesStorage.getInstance().getMessages(dialog_id, count, max_id, midDate, classGuid, from_unread, forward);
MessagesStorage.getInstance().getMessages(dialog_id, count, max_id, midDate, classGuid, from_unread, forward, semaphore);
} else {
TLRPC.TL_messages_getHistory req = new TLRPC.TL_messages_getHistory();
if (lower_part < 0) {
@ -1303,7 +1299,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter
public void run(TLObject response, TLRPC.TL_error error) {
if (error == null) {
final TLRPC.messages_Messages res = (TLRPC.messages_Messages) response;
processLoadedMessages(res, dialog_id, count, max_id, false, classGuid, 0, 0, 0, 0, false);
processLoadedMessages(res, dialog_id, count, max_id, false, classGuid, 0, 0, 0, 0, false, semaphore);
}
}
});
@ -1311,7 +1307,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter
}
}
public void processLoadedMessages(final TLRPC.messages_Messages messagesRes, final long dialog_id, final int count, final int max_id, final boolean isCache, final int classGuid, final int first_unread, final int last_unread, final int unread_count, final int last_date, final boolean isForward) {
public void processLoadedMessages(final TLRPC.messages_Messages messagesRes, final long dialog_id, final int count, final int max_id, final boolean isCache, final int classGuid, final int first_unread, final int last_unread, final int unread_count, final int last_date, final boolean isForward, final Semaphore semaphore) {
Utilities.stageQueue.postRunnable(new Runnable() {
@Override
public void run() {
@ -1320,10 +1316,13 @@ public class MessagesController implements NotificationCenter.NotificationCenter
MessagesStorage.getInstance().putMessages(messagesRes, dialog_id);
}
if (lower_id != 0 && isCache && messagesRes.messages.size() == 0 && !isForward) {
if (semaphore != null) {
semaphore.release();
}
AndroidUtilities.RunOnUIThread(new Runnable() {
@Override
public void run() {
loadMessages(dialog_id, count, max_id, false, 0, classGuid, false, false);
loadMessages(dialog_id, count, max_id, false, 0, classGuid, false, false, null);
}
});
return;
@ -1337,6 +1336,12 @@ public class MessagesController implements NotificationCenter.NotificationCenter
message.dialog_id = dialog_id;
objects.add(new MessageObject(message, usersLocal, 2));
}
if (semaphore != null) {
putUsers(messagesRes.users, isCache);
putChats(messagesRes.chats, isCache);
NotificationCenter.getInstance().postNotificationName(NotificationCenter.messagesDidLoaded, dialog_id, count, objects, isCache, first_unread, last_unread, unread_count, last_date, isForward);
semaphore.release();
} else {
AndroidUtilities.RunOnUIThread(new Runnable() {
@Override
public void run() {
@ -1346,6 +1351,7 @@ public class MessagesController implements NotificationCenter.NotificationCenter
}
});
}
}
});
}

View File

@ -11,6 +11,7 @@ package org.telegram.android;
import android.content.Context;
import android.content.SharedPreferences;
import android.text.Html;
import android.text.TextUtils;
import android.util.SparseArray;
import org.telegram.PhoneFormat.PhoneFormat;
@ -90,7 +91,7 @@ public class MessagesStorage {
database.executeFast("PRAGMA temp_store = 1").stepThis().dispose();
if (createTable) {
database.executeFast("CREATE TABLE users(uid INTEGER PRIMARY KEY, name TEXT, status INTEGER, data BLOB)").stepThis().dispose();
database.executeFast("CREATE TABLE messages(mid INTEGER PRIMARY KEY, uid INTEGER, read_state INTEGER, send_state INTEGER, date INTEGER, data BLOB, out INTEGER, ttl INTEGER)").stepThis().dispose();
database.executeFast("CREATE TABLE messages(mid INTEGER PRIMARY KEY, uid INTEGER, read_state INTEGER, send_state INTEGER, date INTEGER, data BLOB, out INTEGER, ttl INTEGER, media INTEGER)").stepThis().dispose();
database.executeFast("CREATE TABLE chats(uid INTEGER PRIMARY KEY, name TEXT, data BLOB)").stepThis().dispose();
database.executeFast("CREATE TABLE enc_chats(uid INTEGER PRIMARY KEY, user INTEGER, name TEXT, data BLOB, g BLOB, authkey BLOB, ttl INTEGER)").stepThis().dispose();
database.executeFast("CREATE TABLE dialogs(did INTEGER PRIMARY KEY, date INTEGER, unread_count INTEGER, last_mid INTEGER)").stepThis().dispose();
@ -101,7 +102,7 @@ public class MessagesStorage {
database.executeFast("CREATE TABLE media_counts(uid INTEGER PRIMARY KEY, count INTEGER)").stepThis().dispose();
database.executeFast("CREATE TABLE wallpapers(uid INTEGER PRIMARY KEY, data BLOB)").stepThis().dispose();
database.executeFast("CREATE TABLE randoms(random_id INTEGER PRIMARY KEY, mid INTEGER)").stepThis().dispose();
database.executeFast("CREATE TABLE enc_tasks(date INTEGER, data BLOB)").stepThis().dispose();
database.executeFast("CREATE TABLE enc_tasks_v2(mid INTEGER PRIMARY KEY, date INTEGER)").stepThis().dispose();
database.executeFast("CREATE TABLE params(id INTEGER PRIMARY KEY, seq INTEGER, pts INTEGER, date INTEGER, qts INTEGER, lsv INTEGER, sg INTEGER, pbytes BLOB)").stepThis().dispose();
database.executeFast("INSERT INTO params VALUES(1, 0, 0, 0, 0, 0, 0, NULL)").stepThis().dispose();
database.executeFast("CREATE TABLE user_photos(uid INTEGER, id INTEGER, data BLOB, PRIMARY KEY (uid, id))").stepThis().dispose();
@ -122,7 +123,7 @@ public class MessagesStorage {
database.executeFast("CREATE INDEX IF NOT EXISTS sphone_deleted_idx_user_phones ON user_phones_v6(sphone, deleted);").stepThis().dispose();
database.executeFast("CREATE INDEX IF NOT EXISTS date_idx_dialogs ON dialogs(date);").stepThis().dispose();
database.executeFast("CREATE INDEX IF NOT EXISTS date_idx_enc_tasks ON enc_tasks(date);").stepThis().dispose();
database.executeFast("CREATE INDEX IF NOT EXISTS date_idx_enc_tasks_v2 ON enc_tasks_v2(date);").stepThis().dispose();
database.executeFast("CREATE INDEX IF NOT EXISTS last_mid_idx_dialogs ON dialogs(last_mid);").stepThis().dispose();
database.executeFast("CREATE INDEX IF NOT EXISTS unread_count_idx_dialogs ON dialogs(unread_count);").stepThis().dispose();
@ -135,7 +136,7 @@ public class MessagesStorage {
database.executeFast("CREATE INDEX IF NOT EXISTS mid_out_idx_messages ON messages(mid, out);").stepThis().dispose();
database.executeFast("CREATE INDEX IF NOT EXISTS task_idx_messages ON messages(uid, out, read_state, ttl, date, send_state);").stepThis().dispose();
database.executeFast("CREATE INDEX IF NOT EXISTS send_state_idx_messages ON messages(mid, send_state, date) WHERE mid < 0 AND send_state = 1;").stepThis().dispose();
database.executeFast("PRAGMA user_version = 4").stepThis().dispose();
database.executeFast("PRAGMA user_version = 6").stepThis().dispose();
} else {
try {
SQLiteCursor cursor = database.queryFinalized("SELECT seq, pts, date, qts, lsv, sg, pbytes FROM params WHERE id = 1");
@ -167,8 +168,8 @@ public class MessagesStorage {
}
int version = database.executeInt("PRAGMA user_version");
if (version < 4) {
updateDbToVersion4();
if (version < 6) {
updateDbToLastVersion(version);
}
}
} catch (Exception e) {
@ -177,11 +178,12 @@ public class MessagesStorage {
loadUnreadMessages();
}
public void updateDbToVersion4() {
public void updateDbToLastVersion(final int currentVersion) {
storageQueue.postRunnable(new Runnable() {
@Override
public void run() {
try {
if (currentVersion < 4) {
database.executeFast("CREATE TABLE IF NOT EXISTS user_photos(uid INTEGER, id INTEGER, data BLOB, PRIMARY KEY (uid, id))").stepThis().dispose();
database.executeFast("CREATE INDEX IF NOT EXISTS mid_idx_media ON media(mid);").stepThis().dispose();
@ -216,7 +218,6 @@ public class MessagesStorage {
database.executeFast("UPDATE messages SET send_state = 2 WHERE mid < 0 AND send_state = 1").stepThis().dispose();
database.executeFast("PRAGMA user_version = 4").stepThis().dispose();
storageQueue.postRunnable(new Runnable() {
@Override
public void run() {
@ -253,6 +254,37 @@ public class MessagesStorage {
}
}
});
}
if (currentVersion < 6) {
database.executeFast("CREATE TABLE IF NOT EXISTS enc_tasks_v2(mid INTEGER PRIMARY KEY, date INTEGER)").stepThis().dispose();
database.executeFast("CREATE INDEX IF NOT EXISTS date_idx_enc_tasks_v2 ON enc_tasks_v2(date);").stepThis().dispose();
database.beginTransaction();
SQLiteCursor cursor = database.queryFinalized("SELECT date, data FROM enc_tasks WHERE 1");
SQLitePreparedStatement state = database.executeFast("REPLACE INTO enc_tasks_v2 VALUES(?, ?)");
if (cursor.next()) {
int date = cursor.intValue(0);
int length = 0;
ByteBufferDesc data = buffersStorage.getFreeBuffer(cursor.byteArrayLength(1));
if ((length = cursor.byteBufferValue(1, data.buffer)) != 0) {
for (int a = 0; a < length / 4; a++) {
state.requery();
state.bindInteger(1, data.readInt32());
state.bindInteger(2, date);
state.step();
}
}
buffersStorage.reuseFreeBuffer(data);
}
state.dispose();
cursor.dispose();
database.commitTransaction();
database.executeFast("DROP INDEX IF EXISTS date_idx_enc_tasks;").stepThis().dispose();
database.executeFast("DROP TABLE IF EXISTS enc_tasks;").stepThis().dispose();
database.executeFast("ALTER TABLE messages ADD COLUMN media INTEGER").stepThis().dispose();
database.executeFast("PRAGMA user_version = 6").stepThis().dispose();
}
} catch (Exception e) {
FileLog.e("tmessages", e);
}
@ -368,16 +400,16 @@ public class MessagesStorage {
try {
final HashMap<Long, Integer> pushDialogs = new HashMap<Long, Integer>();
SQLiteCursor cursor = database.queryFinalized("SELECT d.did, d.unread_count, s.flags FROM dialogs as d LEFT JOIN dialog_settings as s ON d.did = s.did WHERE d.unread_count != 0");
String ids = "";
StringBuilder ids = new StringBuilder();
while (cursor.next()) {
if (cursor.isNull(2) || cursor.intValue(2) != 1) {
long did = cursor.longValue(0);
int count = cursor.intValue(1);
pushDialogs.put(did, count);
if (ids.length() != 0) {
ids += ",";
ids.append(",");
}
ids += did;
ids.append(did);
}
}
cursor.dispose();
@ -391,7 +423,7 @@ public class MessagesStorage {
ArrayList<Integer> chatIds = new ArrayList<Integer>();
ArrayList<Integer> encryptedChatIds = new ArrayList<Integer>();
cursor = database.queryFinalized("SELECT read_state, data, send_state, mid, date, uid FROM messages WHERE uid IN (" + ids + ") AND out = 0 AND read_state = 0 ORDER BY date DESC LIMIT 50");
cursor = database.queryFinalized("SELECT read_state, data, send_state, mid, date, uid FROM messages WHERE uid IN (" + ids.toString() + ") AND out = 0 AND read_state = 0 ORDER BY date DESC LIMIT 50");
while (cursor.next()) {
ByteBufferDesc data = buffersStorage.getFreeBuffer(cursor.byteArrayLength(1));
if (data != null && cursor.byteBufferValue(1, data.buffer) != 0) {
@ -449,14 +481,8 @@ public class MessagesStorage {
}
cursor.dispose();
String stringToLoad = "";
if (!encryptedChatIds.isEmpty()) {
for (int uid : encryptedChatIds) {
if (stringToLoad.length() != 0) {
stringToLoad += ",";
}
stringToLoad += uid;
}
String stringToLoad = TextUtils.join(",", encryptedChatIds);
cursor = database.queryFinalized(String.format(Locale.US, "SELECT data, user, g, authkey, ttl FROM enc_chats WHERE uid IN(%s)", stringToLoad));
while (cursor.next()) {
ByteBufferDesc data = buffersStorage.getFreeBuffer(cursor.byteArrayLength(0));
@ -477,13 +503,7 @@ public class MessagesStorage {
}
if (!userIds.isEmpty()) {
stringToLoad = "";
for (Integer uid : userIds) {
if (stringToLoad.length() != 0) {
stringToLoad += ",";
}
stringToLoad += uid;
}
String stringToLoad = TextUtils.join(",", userIds);
cursor = database.queryFinalized(String.format(Locale.US, "SELECT data, status FROM users WHERE uid IN(%s)", stringToLoad));
while (cursor.next()) {
ByteBufferDesc data = buffersStorage.getFreeBuffer(cursor.byteArrayLength(0));
@ -500,13 +520,7 @@ public class MessagesStorage {
}
if (!chatIds.isEmpty()) {
stringToLoad = "";
for (Integer cid : chatIds) {
if (stringToLoad.length() != 0) {
stringToLoad += ",";
}
stringToLoad += cid;
}
String stringToLoad = TextUtils.join(",", chatIds);
cursor = database.queryFinalized(String.format(Locale.US, "SELECT data FROM chats WHERE uid IN(%s)", stringToLoad));
while (cursor.next()) {
ByteBufferDesc data = buffersStorage.getFreeBuffer(cursor.byteArrayLength(0));
@ -593,19 +607,19 @@ public class MessagesStorage {
ArrayList<Integer> ids = new ArrayList<Integer>();
ArrayList<TLRPC.User> users = new ArrayList<TLRPC.User>();
SQLiteCursor cursor = database.queryFinalized(String.format(Locale.US, "SELECT * FROM blocked_users WHERE 1"));
String usersToLoad = "";
StringBuilder usersToLoad = new StringBuilder();
while (cursor.next()) {
int user_id = cursor.intValue(0);
ids.add(user_id);
if (usersToLoad.length() != 0) {
usersToLoad += ",";
usersToLoad.append(",");
}
usersToLoad += user_id;
usersToLoad.append(user_id);
}
cursor.dispose();
if (usersToLoad.length() != 0) {
cursor = database.queryFinalized(String.format(Locale.US, "SELECT data, status FROM users WHERE uid IN(%s)", usersToLoad));
cursor = database.queryFinalized(String.format(Locale.US, "SELECT data, status FROM users WHERE uid IN(%s)", usersToLoad.toString()));
while (cursor.next()) {
ByteBufferDesc data = buffersStorage.getFreeBuffer(cursor.byteArrayLength(0));
if (data != null && cursor.byteBufferValue(0, data.buffer) != 0) {
@ -793,34 +807,28 @@ public class MessagesStorage {
});
}
public void getNewTask(final Long oldTask) {
public void getNewTask(final ArrayList<Integer> oldTask) {
storageQueue.postRunnable(new Runnable() {
@Override
public void run() {
try {
if (oldTask != null) {
database.executeFast("DELETE FROM enc_tasks WHERE rowid = " + oldTask).stepThis().dispose();
String ids = TextUtils.join(",", oldTask);
database.executeFast(String.format(Locale.US, "DELETE FROM enc_tasks_v2 WHERE mid IN(%s)", ids)).stepThis().dispose();
}
Long taskId = null;
int date = 0;
ArrayList<Integer> arr = null;
SQLiteCursor cursor = database.queryFinalized("SELECT rowid, date, data FROM enc_tasks ORDER BY date ASC LIMIT 1");
if (cursor.next()) {
taskId = cursor.longValue(0);
SQLiteCursor cursor = database.queryFinalized("SELECT mid, date FROM enc_tasks_v2 WHERE date = (SELECT min(date) FROM enc_tasks_v2)");
while (cursor.next()) {
Integer mid = cursor.intValue(0);
date = cursor.intValue(1);
int length = 0;
ByteBufferDesc data = buffersStorage.getFreeBuffer(cursor.byteArrayLength(2));
if ((length = cursor.byteBufferValue(2, data.buffer)) != 0) {
if (arr == null) {
arr = new ArrayList<Integer>();
for (int a = 0; a < length / 4; a++) {
arr.add(data.readInt32());
}
}
buffersStorage.reuseFreeBuffer(data);
arr.add(mid);
}
cursor.dispose();
MessagesController.getInstance().processLoadedDeleteTask(taskId, date, arr);
MessagesController.getInstance().processLoadedDeleteTask(date, arr);
} catch (Exception e) {
FileLog.e("tmessages", e);
}
@ -835,13 +843,11 @@ public class MessagesStorage {
try {
int minDate = Integer.MAX_VALUE;
SparseArray<ArrayList<Integer>> messages = new SparseArray<ArrayList<Integer>>();
String mids = "";
SQLiteCursor cursor = database.queryFinalized(String.format(Locale.US, "SELECT mid, ttl, read_state FROM messages WHERE uid = %d AND out = %d AND ttl > 0 AND date <= %d AND send_state = 0", ((long)chat_id) << 32, isOut, time));
StringBuilder mids = new StringBuilder();
SQLiteCursor cursor = database.queryFinalized(String.format(Locale.US, "SELECT mid, ttl FROM messages WHERE uid = %d AND out = %d AND read_state = 1 AND ttl > 0 AND date <= %d AND send_state = 0 AND media != 1", ((long)chat_id) << 32, isOut, time));
while (cursor.next()) {
int mid = cursor.intValue(0);
int ttl = cursor.intValue(1);
int read_state = cursor.intValue(2);
int date = readTime + ttl;
int date = readTime + cursor.intValue(1);
minDate = Math.min(minDate, date);
ArrayList<Integer> arr = messages.get(date);
if (arr == null) {
@ -849,38 +855,28 @@ public class MessagesStorage {
messages.put(date, arr);
}
if (mids.length() != 0) {
mids += ",";
mids.append(",");
}
mids += "" + mid;
mids.append(mid);
arr.add(mid);
}
cursor.dispose();
if (messages.size() != 0) {
database.beginTransaction();
SQLitePreparedStatement state = database.executeFast("INSERT INTO enc_tasks VALUES(?, ?)");
SQLitePreparedStatement state = database.executeFast("REPLACE INTO enc_tasks_v2 VALUES(?, ?)");
for (int a = 0; a < messages.size(); a++) {
int key = messages.keyAt(a);
ArrayList<Integer> arr = messages.get(key);
ByteBufferDesc data = buffersStorage.getFreeBuffer(404);
int count = 0;
for (int b = 0; b < arr.size(); b++) {
int mid = arr.get(b);
data.writeInt32(mid);
count++;
if (b == arr.size() - 1 || b != 0 && b % 100 == 0) {
for (Integer mid : arr) {
state.requery();
data.limit(count * 4);
state.bindInteger(1, key);
state.bindByteBuffer(2, data.buffer);
state.bindInteger(1, mid);
state.bindInteger(2, key);
state.step();
count = 0;
}
}
buffersStorage.reuseFreeBuffer(data);
}
state.dispose();
database.commitTransaction();
database.executeFast(String.format(Locale.US, "UPDATE messages SET ttl = 0 WHERE mid IN(%s)", mids)).stepThis().dispose();
database.executeFast(String.format(Locale.US, "UPDATE messages SET ttl = 0 WHERE mid IN(%s)", mids.toString())).stepThis().dispose();
MessagesController.getInstance().didAddedNewTask(minDate);
}
} catch (Exception e) {
@ -896,15 +892,9 @@ public class MessagesStorage {
}
try {
HashMap<Long, Integer> dialogsToUpdate = new HashMap<Long, Integer>();
String dialogsToReload = "";
if (messages != null && !messages.isEmpty()) {
String ids = "";
for (int uid : messages) {
if (ids.length() != 0) {
ids += ",";
}
ids += uid;
}
StringBuilder dialogsToReload = new StringBuilder();
String ids = TextUtils.join(",", messages);
int totalCount = 0;
SQLiteCursor cursor = database.queryFinalized(String.format(Locale.US, "SELECT uid, read_state, out FROM messages WHERE mid IN(%s)", ids));
while (cursor.next()) {
@ -922,20 +912,16 @@ public class MessagesStorage {
if (currentCount == null) {
dialogsToUpdate.put(uid, 1);
if (dialogsToReload.length() != 0) {
dialogsToReload += ",";
dialogsToReload.append(",");
}
dialogsToReload += uid;
dialogsToReload.append(uid);
} else {
dialogsToUpdate.put(uid, currentCount + 1);
}
}
cursor.dispose();
if (totalCount != messages.size()) {
FileLog.e("tmessages", "messages read mismatch!");
}
cursor = database.queryFinalized(String.format(Locale.US, "SELECT did, unread_count FROM dialogs WHERE did IN(%s)", dialogsToReload));
cursor = database.queryFinalized(String.format(Locale.US, "SELECT did, unread_count FROM dialogs WHERE did IN(%s)", dialogsToReload.toString()));
while (cursor.next()) {
long did = cursor.longValue(0);
int count = cursor.intValue(1);
@ -1098,7 +1084,7 @@ public class MessagesStorage {
if (info != null) {
boolean modified = false;
ArrayList<Integer> usersArr = new ArrayList<Integer>();
String usersToLoad = "";
StringBuilder usersToLoad = new StringBuilder();
for (int a = 0; a < info.participants.size(); a++) {
TLRPC.TL_chatParticipant c = info.participants.get(a);
if (usersArr.contains(c.user_id)) {
@ -1107,14 +1093,14 @@ public class MessagesStorage {
a--;
} else {
if (usersToLoad.length() != 0) {
usersToLoad += ",";
usersToLoad.append(",");
}
usersArr.add(c.user_id);
usersToLoad += c.user_id;
usersToLoad.append(c.user_id);
}
}
if (usersToLoad.length() != 0) {
cursor = database.queryFinalized(String.format(Locale.US, "SELECT data, status FROM users WHERE uid IN(%s)", usersToLoad));
cursor = database.queryFinalized(String.format(Locale.US, "SELECT data, status FROM users WHERE uid IN(%s)", usersToLoad.toString()));
while (cursor.next()) {
ByteBufferDesc data = buffersStorage.getFreeBuffer(cursor.byteArrayLength(0));
if (data != null && cursor.byteBufferValue(0, data.buffer) != 0) {
@ -1322,13 +1308,7 @@ public class MessagesStorage {
@Override
public void run() {
try {
String ids = "";
for (Integer uid : uids) {
if (ids.length() != 0) {
ids += ",";
}
ids += "" + uid;
}
String ids = TextUtils.join(",", uids);
database.executeFast("DELETE FROM contacts WHERE uid IN(" + ids + ")").stepThis().dispose();
} catch (Exception e) {
FileLog.e("tmessages", e);
@ -1446,7 +1426,7 @@ public class MessagesStorage {
ArrayList<TLRPC.User> users = new ArrayList<TLRPC.User>();
try {
SQLiteCursor cursor = database.queryFinalized("SELECT * FROM contacts WHERE 1");
String uids = "";
StringBuilder uids = new StringBuilder();
while (cursor.next()) {
int user_id = cursor.intValue(0);
if (user_id == UserConfig.getClientUserId()) {
@ -1456,15 +1436,15 @@ public class MessagesStorage {
contact.user_id = user_id;
contact.mutual = cursor.intValue(1) == 1;
if (uids.length() != 0) {
uids += ",";
uids.append(",");
}
contacts.add(contact);
uids += contact.user_id;
uids.append(contact.user_id);
}
cursor.dispose();
if (uids.length() != 0) {
cursor = database.queryFinalized(String.format(Locale.US, "SELECT data, status FROM users WHERE uid IN(%s)", uids));
cursor = database.queryFinalized(String.format(Locale.US, "SELECT data, status FROM users WHERE uid IN(%s)", uids.toString()));
while (cursor.next()) {
ByteBufferDesc data = buffersStorage.getFreeBuffer(cursor.byteArrayLength(0));
if (data != null && cursor.byteBufferValue(0, data.buffer) != 0) {
@ -1574,18 +1554,18 @@ public class MessagesStorage {
}
cursor.dispose();
String usersToLoad = "";
StringBuilder usersToLoad = new StringBuilder();
for (int uid : fromUser) {
if (!loadedUsers.contains(uid)) {
if (usersToLoad.length() != 0) {
usersToLoad += ",";
usersToLoad.append(",");
}
usersToLoad += uid;
usersToLoad.append(uid);
loadedUsers.add(uid);
}
}
if (usersToLoad.length() != 0) {
cursor = database.queryFinalized(String.format(Locale.US, "SELECT data, status FROM users WHERE uid IN(%s)", usersToLoad));
cursor = database.queryFinalized(String.format(Locale.US, "SELECT data, status FROM users WHERE uid IN(%s)", usersToLoad.toString()));
while (cursor.next()) {
ByteBufferDesc data = buffersStorage.getFreeBuffer(cursor.byteArrayLength(0));
if (data != null && cursor.byteBufferValue(0, data.buffer) != 0) {
@ -1722,14 +1702,9 @@ public class MessagesStorage {
}
cursor.dispose();
String stringToLoad = "";
if (!encryptedChatIds.isEmpty()) {
for (int uid : encryptedChatIds) {
if (stringToLoad.length() != 0) {
stringToLoad += ",";
}
stringToLoad += uid;
}
String stringToLoad = TextUtils.join(",", encryptedChatIds);
cursor = database.queryFinalized(String.format(Locale.US, "SELECT data, user, g, authkey, ttl FROM enc_chats WHERE uid IN(%s)", stringToLoad));
while (cursor.next()) {
ByteBufferDesc data = buffersStorage.getFreeBuffer(cursor.byteArrayLength(0));
@ -1751,13 +1726,7 @@ public class MessagesStorage {
if (!userIds.isEmpty()) {
stringToLoad = "";
for (Integer uid : userIds) {
if (stringToLoad.length() != 0) {
stringToLoad += ",";
}
stringToLoad += uid;
}
String stringToLoad = TextUtils.join(",", userIds);
cursor = database.queryFinalized(String.format(Locale.US, "SELECT data, status FROM users WHERE uid IN(%s)", stringToLoad));
while (cursor.next()) {
ByteBufferDesc data = buffersStorage.getFreeBuffer(cursor.byteArrayLength(0));
@ -1774,20 +1743,20 @@ public class MessagesStorage {
}
if (!chatIds.isEmpty() || !broadcastIds.isEmpty()) {
stringToLoad = "";
StringBuilder stringToLoad = new StringBuilder();
for (Integer cid : chatIds) {
if (stringToLoad.length() != 0) {
stringToLoad += ",";
stringToLoad.append(",");
}
stringToLoad += cid;
stringToLoad.append(cid);
}
for (Integer cid : broadcastIds) {
if (stringToLoad.length() != 0) {
stringToLoad += ",";
stringToLoad.append(",");
}
stringToLoad += (-cid);
stringToLoad.append(-cid);
}
cursor = database.queryFinalized(String.format(Locale.US, "SELECT data FROM chats WHERE uid IN(%s)", stringToLoad));
cursor = database.queryFinalized(String.format(Locale.US, "SELECT data FROM chats WHERE uid IN(%s)", stringToLoad.toString()));
while (cursor.next()) {
ByteBufferDesc data = buffersStorage.getFreeBuffer(cursor.byteArrayLength(0));
if (data != null && cursor.byteBufferValue(0, data.buffer) != 0) {
@ -1807,7 +1776,7 @@ public class MessagesStorage {
});
}
public void getMessages(final long dialog_id, final int count, final int max_id, final int minDate, final int classGuid, final boolean from_unread, final boolean forward) {
public void getMessages(final long dialog_id, final int count, final int max_id, final int minDate, final int classGuid, final boolean from_unread, final boolean forward, final Semaphore semaphore) {
storageQueue.postRunnable(new Runnable() {
@Override
public void run() {
@ -1991,18 +1960,18 @@ public class MessagesStorage {
}
cursor.dispose();
String usersToLoad = "";
StringBuilder usersToLoad = new StringBuilder();
for (int uid : fromUser) {
if (!loadedUsers.contains(uid)) {
if (usersToLoad.length() != 0) {
usersToLoad += ",";
usersToLoad.append(",");
}
usersToLoad += uid;
usersToLoad.append(uid);
loadedUsers.add(uid);
}
}
if (usersToLoad.length() != 0) {
cursor = database.queryFinalized(String.format(Locale.US, "SELECT data, status FROM users WHERE uid IN(%s)", usersToLoad));
cursor = database.queryFinalized(String.format(Locale.US, "SELECT data, status FROM users WHERE uid IN(%s)", usersToLoad.toString()));
while (cursor.next()) {
ByteBufferDesc data = buffersStorage.getFreeBuffer(cursor.byteArrayLength(0));
if (data != null && cursor.byteBufferValue(0, data.buffer) != 0) {
@ -2023,7 +1992,7 @@ public class MessagesStorage {
res.users.clear();
FileLog.e("tmessages", e);
} finally {
MessagesController.getInstance().processLoadedMessages(res, dialog_id, count_query, max_id, true, classGuid, min_unread_id, max_unread_id, count_unread, max_unread_date, forward);
MessagesController.getInstance().processLoadedMessages(res, dialog_id, count_query, max_id, true, classGuid, min_unread_id, max_unread_id, count_unread, max_unread_date, forward, semaphore);
}
}
});
@ -2448,6 +2417,18 @@ public class MessagesStorage {
});
}
private int getMessageMediaType(TLRPC.Message message) {
if (message.media == null) {
return 0;
} else if (message.media instanceof TLRPC.TL_messageMediaPhoto) {
return 1;
} else if (message.media instanceof TLRPC.TL_messageMediaVideo) {
return 2;
} else {
return 0;
}
}
private void putMessagesInternal(final ArrayList<TLRPC.Message> messages, final boolean withTransaction, final boolean isBroadcast, final int downloadMask) {
try {
if (withTransaction) {
@ -2458,9 +2439,9 @@ public class MessagesStorage {
HashMap<Long, Integer> mediaCounts = new HashMap<Long, Integer>();
HashMap<Integer, Long> messagesIdsMap = new HashMap<Integer, Long>();
HashMap<Integer, Long> messagesMediaIdsMap = new HashMap<Integer, Long>();
String messageIds = "";
String messageMediaIds = "";
SQLitePreparedStatement state = database.executeFast("REPLACE INTO messages VALUES(?, ?, ?, ?, ?, ?, ?, ?)");
StringBuilder messageIds = new StringBuilder();
StringBuilder messageMediaIds = new StringBuilder();
SQLitePreparedStatement state = database.executeFast("REPLACE INTO messages VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?)");
SQLitePreparedStatement state2 = database.executeFast("REPLACE INTO media VALUES(?, ?, ?, ?)");
SQLitePreparedStatement state3 = database.executeFast("REPLACE INTO randoms VALUES(?, ?)");
SQLitePreparedStatement state4 = database.executeFast("REPLACE INTO download_queue VALUES(?, ?, ?, ?)");
@ -2477,23 +2458,23 @@ public class MessagesStorage {
if (message.unread && !message.out) {
if (messageIds.length() > 0) {
messageIds += ",";
messageIds.append(",");
}
messageIds += message.id;
messageIds.append(message.id);
messagesIdsMap.put(message.id, dialog_id);
}
if (message.media instanceof TLRPC.TL_messageMediaVideo || message.media instanceof TLRPC.TL_messageMediaPhoto) {
if (message.ttl == 0 && (message.media instanceof TLRPC.TL_messageMediaVideo || message.media instanceof TLRPC.TL_messageMediaPhoto)) {
if (messageMediaIds.length() > 0) {
messageMediaIds += ",";
messageMediaIds.append(",");
}
messageMediaIds += message.id;
messageMediaIds.append(message.id);
messagesMediaIdsMap.put(message.id, dialog_id);
}
}
if (messageIds.length() > 0) {
SQLiteCursor cursor = database.queryFinalized("SELECT mid FROM messages WHERE mid IN(" + messageIds + ")");
SQLiteCursor cursor = database.queryFinalized("SELECT mid FROM messages WHERE mid IN(" + messageIds.toString() + ")");
while (cursor.next()) {
int mid = cursor.intValue(0);
messagesIdsMap.remove(mid);
@ -2510,7 +2491,7 @@ public class MessagesStorage {
}
if (messageMediaIds.length() > 0) {
SQLiteCursor cursor = database.queryFinalized("SELECT mid FROM media WHERE mid IN(" + messageMediaIds + ")");
SQLiteCursor cursor = database.queryFinalized("SELECT mid FROM media WHERE mid IN(" + messageMediaIds.toString() + ")");
while (cursor.next()) {
int mid = cursor.intValue(0);
messagesMediaIdsMap.remove(mid);
@ -2557,6 +2538,7 @@ public class MessagesStorage {
state.bindByteBuffer(6, data.buffer);
state.bindInteger(7, (message.out ? 1 : 0));
state.bindInteger(8, message.ttl);
state.bindInteger(9, getMessageMediaType(message));
state.step();
if (message.random_id != 0) {
@ -2566,7 +2548,7 @@ public class MessagesStorage {
state3.step();
}
if (message.media instanceof TLRPC.TL_messageMediaVideo || message.media instanceof TLRPC.TL_messageMediaPhoto) {
if (message.ttl == 0 && (message.media instanceof TLRPC.TL_messageMediaVideo || message.media instanceof TLRPC.TL_messageMediaPhoto)) {
state2.requery();
state2.bindInteger(1, messageId);
state2.bindLong(2, dialog_id);
@ -2862,17 +2844,17 @@ public class MessagesStorage {
database.commitTransaction();
}
} else {
String ids = "";
StringBuilder ids = new StringBuilder();
HashMap<Integer, TLRPC.User> usersDict = new HashMap<Integer, TLRPC.User>();
for (TLRPC.User user : users) {
if (ids.length() != 0) {
ids += ",";
ids.append(",");
}
ids += user.id;
ids.append(user.id);
usersDict.put(user.id, user);
}
ArrayList<TLRPC.User> loadedUsers = new ArrayList<TLRPC.User>();
SQLiteCursor cursor = database.queryFinalized(String.format(Locale.US, "SELECT data, status FROM users WHERE uid IN(%s)", ids));
SQLiteCursor cursor = database.queryFinalized(String.format(Locale.US, "SELECT data, status FROM users WHERE uid IN(%s)", ids.toString()));
while (cursor.next()) {
ByteBufferDesc data = buffersStorage.getFreeBuffer(cursor.byteArrayLength(0));
if (data != null && cursor.byteBufferValue(0, data.buffer) != 0) {
@ -2950,13 +2932,7 @@ public class MessagesStorage {
}
try {
if (messages != null && !messages.isEmpty()) {
String ids = "";
for (int uid : messages) {
if (ids.length() != 0) {
ids += ",";
}
ids += uid;
}
String ids = TextUtils.join(",", messages);
database.executeFast(String.format(Locale.US, "UPDATE messages SET read_state = 1 WHERE mid IN(%s)", ids)).stepThis().dispose();
}
if (encryptedMessages != null && !encryptedMessages.isEmpty()) {
@ -2997,13 +2973,7 @@ public class MessagesStorage {
@Override
public void run() {
try {
String ids = "";
for (long uid : messages) {
if (ids.length() != 0) {
ids += ",";
}
ids += uid;
}
String ids = TextUtils.join(",", messages);
SQLiteCursor cursor = database.queryFinalized(String.format(Locale.US, "SELECT mid FROM randoms WHERE random_id IN(%s)", ids));
final ArrayList<Integer> mids = new ArrayList<Integer>();
while (cursor.next()) {
@ -3038,13 +3008,7 @@ public class MessagesStorage {
throw new RuntimeException("wrong db thread");
}
try {
String ids = "";
for (int uid : messages) {
if (ids.length() != 0) {
ids += ",";
}
ids += uid;
}
String ids = TextUtils.join(",", messages);
database.executeFast(String.format(Locale.US, "DELETE FROM messages WHERE mid IN(%s)", ids)).stepThis().dispose();
database.executeFast(String.format(Locale.US, "DELETE FROM media WHERE mid IN(%s)", ids)).stepThis().dispose();
database.executeFast("DELETE FROM media_counts WHERE 1").stepThis().dispose();
@ -3059,13 +3023,7 @@ public class MessagesStorage {
throw new RuntimeException("wrong db thread");
}
try {
String ids = "";
for (int uid : messages) {
if (ids.length() != 0) {
ids += ",";
}
ids += uid;
}
String ids = TextUtils.join(",", messages);
SQLiteCursor cursor = database.queryFinalized(String.format(Locale.US, "SELECT did FROM dialogs WHERE last_mid IN(%s)", ids));
ArrayList<Long> dialogsToUpdate = new ArrayList<Long>();
while (cursor.next()) {
@ -3084,13 +3042,7 @@ public class MessagesStorage {
state.dispose();
database.commitTransaction();
ids = "";
for (long uid : dialogsToUpdate) {
if (ids.length() != 0) {
ids += ",";
}
ids += uid;
}
ids = TextUtils.join(",", dialogsToUpdate);
TLRPC.messages_Dialogs dialogs = new TLRPC.messages_Dialogs();
ArrayList<TLRPC.EncryptedChat> encryptedChats = new ArrayList<TLRPC.EncryptedChat>();
@ -3157,13 +3109,7 @@ public class MessagesStorage {
cursor.dispose();
if (!encryptedToLoad.isEmpty()) {
String toLoad = "";
for (int uid : encryptedToLoad) {
if (toLoad.length() != 0) {
toLoad += ",";
}
toLoad += uid;
}
String toLoad = TextUtils.join(",", encryptedToLoad);
cursor = database.queryFinalized(String.format(Locale.US, "SELECT data, user, g, authkey, ttl FROM enc_chats WHERE uid IN(%s)", toLoad));
while (cursor.next()) {
ByteBufferDesc data = buffersStorage.getFreeBuffer(cursor.byteArrayLength(0));
@ -3184,13 +3130,7 @@ public class MessagesStorage {
}
if (!chatsToLoad.isEmpty()) {
String toLoad = "";
for (int uid : chatsToLoad) {
if (toLoad.length() != 0) {
toLoad += ",";
}
toLoad += uid;
}
String toLoad = TextUtils.join(",", chatsToLoad);
cursor = database.queryFinalized(String.format(Locale.US, "SELECT data FROM chats WHERE uid IN(%s)", toLoad));
while (cursor.next()) {
ByteBufferDesc data = buffersStorage.getFreeBuffer(cursor.byteArrayLength(0));
@ -3204,13 +3144,7 @@ public class MessagesStorage {
}
if (!usersToLoad.isEmpty()) {
String toLoad = "";
for (int uid : usersToLoad) {
if (toLoad.length() != 0) {
toLoad += ",";
}
toLoad += uid;
}
String toLoad = TextUtils.join(",", usersToLoad);
cursor = database.queryFinalized(String.format(Locale.US, "SELECT data, status FROM users WHERE uid IN(%s)", toLoad));
while (cursor.next()) {
ByteBufferDesc data = buffersStorage.getFreeBuffer(cursor.byteArrayLength(0));
@ -3276,7 +3210,7 @@ public class MessagesStorage {
try {
database.beginTransaction();
if (!messages.messages.isEmpty()) {
SQLitePreparedStatement state = database.executeFast("REPLACE INTO messages VALUES(?, ?, ?, ?, ?, ?, ?, ?)");
SQLitePreparedStatement state = database.executeFast("REPLACE INTO messages VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?)");
SQLitePreparedStatement state2 = database.executeFast("REPLACE INTO media VALUES(?, ?, ?, ?)");
for (TLRPC.Message message : messages.messages) {
state.requery();
@ -3290,6 +3224,7 @@ public class MessagesStorage {
state.bindByteBuffer(6, data.buffer);
state.bindInteger(7, (message.out ? 1 : 0));
state.bindInteger(8, 0);
state.bindInteger(9, getMessageMediaType(message));
state.step();
if (message.media instanceof TLRPC.TL_messageMediaVideo || message.media instanceof TLRPC.TL_messageMediaPhoto) {
@ -3430,13 +3365,7 @@ public class MessagesStorage {
cursor.dispose();
if (!encryptedToLoad.isEmpty()) {
String toLoad = "";
for (int uid : encryptedToLoad) {
if (toLoad.length() != 0) {
toLoad += ",";
}
toLoad += uid;
}
String toLoad = TextUtils.join(",", encryptedToLoad);
cursor = database.queryFinalized(String.format(Locale.US, "SELECT data, user, g, authkey, ttl FROM enc_chats WHERE uid IN(%s)", toLoad));
while (cursor.next()) {
try {
@ -3463,13 +3392,7 @@ public class MessagesStorage {
}
if (!chatsToLoad.isEmpty()) {
String toLoad = "";
for (int uid : chatsToLoad) {
if (toLoad.length() != 0) {
toLoad += ",";
}
toLoad += uid;
}
String toLoad = TextUtils.join(",", chatsToLoad);
cursor = database.queryFinalized(String.format(Locale.US, "SELECT data FROM chats WHERE uid IN(%s)", toLoad));
while (cursor.next()) {
try {
@ -3489,13 +3412,7 @@ public class MessagesStorage {
}
if (!usersToLoad.isEmpty()) {
String toLoad = "";
for (int uid : usersToLoad) {
if (toLoad.length() != 0) {
toLoad += ",";
}
toLoad += uid;
}
String toLoad = TextUtils.join(",", usersToLoad);
cursor = database.queryFinalized(String.format(Locale.US, "SELECT data, status FROM users WHERE uid IN(%s)", toLoad));
while (cursor.next()) {
try {
@ -3549,7 +3466,7 @@ public class MessagesStorage {
}
if (!dialogs.dialogs.isEmpty()) {
SQLitePreparedStatement state = database.executeFast("REPLACE INTO messages VALUES(?, ?, ?, ?, ?, ?, ?, ?)");
SQLitePreparedStatement state = database.executeFast("REPLACE INTO messages VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?)");
SQLitePreparedStatement state2 = database.executeFast("REPLACE INTO dialogs(did, date, unread_count, last_mid) VALUES(?, ?, ?, ?)");
SQLitePreparedStatement state3 = database.executeFast("REPLACE INTO media VALUES(?, ?, ?, ?)");
SQLitePreparedStatement state4 = database.executeFast("REPLACE INTO dialog_settings VALUES(?, ?)");
@ -3574,6 +3491,7 @@ public class MessagesStorage {
state.bindByteBuffer(6, data.buffer);
state.bindInteger(7, (message.out ? 1 : 0));
state.bindInteger(8, 0);
state.bindInteger(9, getMessageMediaType(message));
state.step();
state2.bindLong(1, uid);
@ -3683,14 +3601,7 @@ public class MessagesStorage {
public ArrayList<TLRPC.User> getUsers(final ArrayList<Integer> uids, final boolean[] error) {
ArrayList<TLRPC.User> users = new ArrayList<TLRPC.User>();
try {
String uidsStr = "";
for (Integer uid : uids) {
if (uidsStr.length() != 0) {
uidsStr += ",";
}
uidsStr += uid;
}
String uidsStr = TextUtils.join(",", uids);
SQLiteCursor cursor = database.queryFinalized(String.format(Locale.US, "SELECT data, status FROM users WHERE uid IN (%s)", uidsStr));
while (cursor.next()) {

View File

@ -24,9 +24,9 @@ import java.util.zip.ZipFile;
public class NativeLoader {
private static final long sizes[] = new long[] {
946908, //armeabi
1028848, //armeabi-v7a
1603780, //x86
951052, //armeabi
1032992, //armeabi-v7a
1612020, //x86
0, //mips
};

View File

@ -9000,6 +9000,41 @@ public class TLRPC {
}
}
public static class TL_message_secret extends TL_message {
public static int constructor = 0x555555F8;
public void readParams(AbsSerializedData stream) {
id = stream.readInt32();
from_id = stream.readInt32();
to_id = (Peer)TLClassStore.Instance().TLdeserialize(stream, stream.readInt32());
out = stream.readBool();
unread = stream.readBool();
date = stream.readInt32();
message = stream.readString();
media = (MessageMedia)TLClassStore.Instance().TLdeserialize(stream, stream.readInt32());
if (id < 0 || (media != null && !(media instanceof TL_messageMediaEmpty) && message != null && message.length() != 0 && message.startsWith("-1"))) {
attachPath = stream.readString();
}
if (id < 0 && message.length() > 6 && media instanceof TL_messageMediaVideo) {
videoEditedInfo = new VideoEditedInfo();
videoEditedInfo.parseString(message);
}
}
public void serializeToStream(AbsSerializedData stream) {
stream.writeInt32(constructor);
stream.writeInt32(id);
stream.writeInt32(from_id);
to_id.serializeToStream(stream);
stream.writeBool(out);
stream.writeBool(unread);
stream.writeInt32(date);
stream.writeString(message);
media.serializeToStream(stream);
stream.writeString(attachPath);
}
}
public static class TL_messages_deleteMessages extends TLObject {
public static int constructor = 0x14f2dd0a;

View File

@ -117,6 +117,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
private TypingDotsDrawable typingDotsDrawable;
private View emptyViewContainer;
private ArrayList<View> actionModeViews = new ArrayList<View>();
private Semaphore testSemaphore = new Semaphore(0);
private TextView bottomOverlayText;
@ -352,7 +353,14 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
super.onFragmentCreate();
loading = true;
MessagesController.getInstance().loadMessages(dialog_id, 30, 0, true, 0, classGuid, true, false);
MessagesController.getInstance().loadMessages(dialog_id, AndroidUtilities.isTablet() ? 30 : 20, 0, true, 0, classGuid, true, false, testSemaphore);
try {
testSemaphore.acquire();
} catch (Exception e) {
FileLog.e("tmessages", e);
}
if (currentUser != null) {
userBlocked = MessagesController.getInstance().blockedUsers.contains(currentUser.id);
}
@ -766,16 +774,16 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
if (firstVisibleItem <= 4) {
if (!endReached && !loading) {
if (messagesByDays.size() != 0) {
MessagesController.getInstance().loadMessages(dialog_id, 20, maxMessageId, !cacheEndReaced, minDate, classGuid, false, false);
MessagesController.getInstance().loadMessages(dialog_id, 20, maxMessageId, !cacheEndReaced, minDate, classGuid, false, false, null);
} else {
MessagesController.getInstance().loadMessages(dialog_id, 20, 0, !cacheEndReaced, minDate, classGuid, false, false);
MessagesController.getInstance().loadMessages(dialog_id, 20, 0, !cacheEndReaced, minDate, classGuid, false, false, null);
}
loading = true;
}
}
if (firstVisibleItem + visibleItemCount >= totalItemCount - 6) {
if (!unread_end_reached && !loadingForward) {
MessagesController.getInstance().loadMessages(dialog_id, 20, minMessageId, true, maxDate, classGuid, false, true);
MessagesController.getInstance().loadMessages(dialog_id, 20, minMessageId, true, maxDate, classGuid, false, true, null);
loadingForward = true;
}
}
@ -896,7 +904,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
unread_end_reached = true;
loading = true;
chatAdapter.notifyDataSetChanged();
MessagesController.getInstance().loadMessages(dialog_id, 30, 0, true, 0, classGuid, true, false);
MessagesController.getInstance().loadMessages(dialog_id, 30, 0, true, 0, classGuid, true, false, null);
}
}
@ -2249,7 +2257,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
}
maxDate = Integer.MIN_VALUE;
minDate = 0;
MessagesController.getInstance().loadMessages(dialog_id, 30, 0, !cacheEndReaced, minDate, classGuid, false, false);
MessagesController.getInstance().loadMessages(dialog_id, 30, 0, !cacheEndReaced, minDate, classGuid, false, false, null);
loading = true;
}
}

View File

@ -2138,7 +2138,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat
float ai = -1;
if (System.currentTimeMillis() - animationStartTime < animationDuration) {
ai = interpolator.getInterpolation((float)(System.currentTimeMillis() - animationStartTime) / animationDuration);
if (ai >= 0.95) {
if (ai >= 0.999f) {
ai = -1;
}
}

View File

@ -0,0 +1,3 @@
<?xml version="1.0" encoding="utf-8"?>
<decelerateInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
android:factor="1.5" />

View File

@ -1,15 +1,31 @@
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<scale android:fromXScale="0.9"
android:fromYScale="0.9"
android:toXScale="1.0"
android:toYScale="1.0"
android:pivotX="50%"
android:pivotY="50%"
android:duration="150"/>
<!--<scale-->
<!--android:fromXScale="0.9"-->
<!--android:fromYScale="0.9"-->
<!--android:toXScale="1.0"-->
<!--android:toYScale="1.0"-->
<!--android:pivotX="50%"-->
<!--android:pivotY="50%"-->
<!--android:interpolator="@android:anim/decelerate_interpolator"-->
<!--android:duration="220"/>-->
<!--<alpha android:fromAlpha="0.0"-->
<!--android:toAlpha="1.0"-->
<!--android:interpolator="@android:anim/decelerate_interpolator"-->
<!--android:duration="@android:integer/config_mediumAnimTime" />-->
<alpha android:fromAlpha="0.0"
<alpha
android:fromAlpha="0.0"
android:toAlpha="1.0"
android:duration="150" />
android:interpolator="@anim/decelerate_cubic"
android:duration="220"/>
<scale
android:fromXScale=".8" android:toXScale="1.0"
android:fromYScale=".8" android:toYScale="1.0"
android:pivotX="50%p" android:pivotY="50%p"
android:interpolator="@anim/decelerate_cubic"
android:duration="220"/>
</set>

View File

@ -1,16 +1,34 @@
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<scale android:fromXScale="1.0"
android:fromYScale="1.0"
android:toXScale="0.9"
android:toYScale="0.9"
android:pivotX="50%"
android:pivotY="50%"
android:interpolator="@android:anim/accelerate_decelerate_interpolator"
android:duration="150"/>
<!--<scale-->
<!--android:fromXScale="1.0"-->
<!--android:fromYScale="1.0"-->
<!--android:toXScale="0.9"-->
<!--android:toYScale="0.9"-->
<!--android:pivotX="50%"-->
<!--android:pivotY="50%"-->
<!--android:interpolator="@android:anim/decelerate_interpolator"-->
<!--android:duration="220"/>-->
<alpha android:fromAlpha="1.0"
<!--<alpha-->
<!--android:fromAlpha="1.0"-->
<!--android:toAlpha="0.0"-->
<!--android:interpolator="@android:anim/decelerate_interpolator"-->
<!--android:duration="220" />-->
<alpha
android:fromAlpha="1.0"
android:toAlpha="0.0"
android:interpolator="@android:anim/accelerate_decelerate_interpolator"
android:duration="150" />
android:interpolator="@anim/decelerate_cubic"
android:duration="220"/>
<scale
android:fromXScale="1.0"
android:toXScale=".8"
android:fromYScale="1.0"
android:toYScale=".8"
android:pivotX="50%p"
android:pivotY="50%p"
android:interpolator="@anim/decelerate_cubic"
android:duration="220"/>
</set>

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB