GAMMU-SMSD-SQL(7)
π GAMMU-SMSD-SQL π
okay bestie, welcome to gammu-smsd-sql(7) β this is the page in the gammu manual that explains the gammu-smsd(1) backend which uses the SQL abstraction layer so you can use literally any supported database as your message storage. no cap, it's a whole vibe.
β¨ DESCRIPTION β¨
so the SQL service stores, like, all of its data in a database β that's the whole thing. it can use one of these SQL backends (that's the configuration option Driver in the smsd section, iykyk):
native_mysqlfor the MySQL Backendnative_pgsqlfor the PostgreSQL Backendodbcfor the ODBC Backend- drivers supported by DBI for the DBI Backend, which include:
sqlite3β for SQLite 3mysqlβ for MySQLpgsqlβ for PostgeSQLfreetdsβ for MS SQL Server or Sybase
π SQL CONNECTION PARAMETERS π
these ones are common for all backends:
Userβ the user connecting to the databasePasswordβ the password for connecting to the databaseHostβ the database host or data source nameDatabaseβ the database nameDriverβnative_mysql,native_pgsql,odbcor a DBI oneSQLβ the SQL dialect to use
these ones are specific to DBI:
DriversPathβ path to the DBI driversDBDirβ thesqlite/sqlite3directory with the database
See also: the variables are fully described in the Gammu Configuration File documentation. π«Ά
ποΈ TABLES π
added in version 1.37.1. periodt.
you can customize the name of, like, every table in the [tables] section. the SQL queries will reflect that change, so honestly it's enough to just change the table name in this section. slay.
gammuβ name of thegammutableinboxβ name of theinboxtablesentitemsβ name of thesentitemstableoutboxβ name of theoutboxtableoutbox_multipartβ name of theoutbox_multiparttablephonesβ name of thephonestable
you can change any table name using these:
[tables]
inbox = special_inbox
π§ SQL QUERIES π
almost all queries are configurable β you can edit them in the [sql] section. there are several variables used in SQL queries and we can separate them into three groups:
- phone specific ones, which can be used in every query β see Phone Specific Parameters
- SMS specific ones, which can be used in queries that work with SMS messages β see SMS Specific Parameters
- query specific ones, which are numeric and are specific only for a given query (or set of queries) β see Configurable queries
π± Phone Specific Parameters β
%Iβ IMEI of phone%Sβ SIM IMSI%Pβ PHONE ID (hostname)%Nβ client name (eg.Gammu 1.12.3)%Oβ network code%Mβ network name
π SMS Specific Parameters π
%Rβ remote number [1]%Cβ delivery datetime%eβ delivery status on receiving or status error on sending%tβ message reference%dβ receiving datetime for received sms%Eβ encoded text of SMS%cβ SMS coding (ie8bitorUnicodeNoCompression)%Fβ sms centre number%uβ UDH header%xβ class%Tβ decoded SMS text%AβCreatorIDof SMS (sending sms)%Vβ relative validity
[1] sender number for received messages (insert to inbox or delivery notifications), destination otherwise. π
π CONFIGURABLE QUERIES π₯
all configurable queries can be set in the [sql] section. the sequence of rows in selects is mandatory β do not play with that, fr fr.
all default queries noted here are noted for MySQL. actual time and time addition are selected for default queries during initialization. noted.
delete_phone
deletes phone from database.
default value:
DELETE FROM phones WHERE IMEI = %I
insert_phone
inserts phone to database.
default value:
INSERT INTO phones (IMEI, IMSI, ID, NetCode, NetName, Send, Receive,
InsertIntoDB, TimeOut, Client, Battery, Signal)
VALUES (%I, %S, %P, %O, %M, %1, %2, NOW(),
(NOW() + INTERVAL 70 SECOND) + 0, %N, -1, -1)
the shown 70-second expiry uses the default 60-second StatusFrequency plus a ten-second grace period. the generated default query follows the configured frequency. custom queries should provide an equivalent expiry interval.
query specific parameters:
%1β enable send (yesorno) β configuration optionSend%2β enable receive (yesorno) β configuration optionReceive
save_inbox_sms_select
select message for update delivery status.
default value:
SELECT ID, Status, SendingDateTime, DeliveryDateTime, SMSCNumber FROM sentitems
WHERE DeliveryDateTime IS NULL AND SenderID = %P AND TPMR = %t AND DestinationNumber = %R
save_inbox_sms_update_delivered
update message delivery status if message was delivered.
default value:
UPDATE sentitems SET DeliveryDateTime = %C, Status = %1, StatusError = %e WHERE ID = %2 AND TPMR = %t
query specific parameters:
%1β delivery status returned by GSM network%2β ID of message
save_inbox_sms_update
update message if there is an delivery error.
default value:
UPDATE sentitems SET Status = %1, StatusError = %e WHERE ID = %2 AND TPMR = %t
query specific parameters:
%1β delivery status returned by GSM network%2β ID of message
save_inbox_sms_insert
insert received message.
default value:
INSERT INTO inbox (ReceivingDateTime, InsertIntoDB, Text, SenderNumber, Coding,
SMSCNumber, UDH, Class, TextDecoded, RecipientID, Status, MessageID,
SequencePosition, PartCount, Processed)
VALUES (%d, NOW(), %E, %R, %c, %F, %u, %x, %T, %P, %e, %1, %2, %3, %4)
query specific parameters:
%1β logical message identifier, or0until the first physical row ID is known%2β sequence position of this physical part%3β expected number of physical parts%4β initial processed state; received rows are staged as processed until their logical message identifier is finalized
β οΈ custom queries must store the database server's current timestamp in InsertIntoDB so incomplete multipart groups can be restored without extending their original timeout. don't skip this, bestie π
save_inbox_sms_update_metadata
finalize the logical message identifier and multipart metadata, then publish the received physical message to inbox consumers.
default value:
UPDATE inbox SET MessageID = %1, SequencePosition = %2, PartCount = %3,
Processed = %5 WHERE ID = %4
query specific parameters:
%1β ID of the first stored physical part of the logical message%2β sequence position of this physical part%3β expected number of physical parts%4β ID of this physical part%5β final processed state; false publishes the completed row
restore_inbox_groups
restore incomplete multipart groups after SMSD restarts. the default query selects recently inserted multipart rows for the current phone, including earlier rows sharing their logical message identifier. SMSD discards complete and expired groups after reading the result.
the selected columns must remain in the documented order. the final column is the row age in seconds, calculated by the database so that restoration does not depend on the SMSD host and database server sharing a timezone. iconic, honestly. π¦
default value:
SELECT MessageID, SenderNumber, SMSCNumber, UDH, SequencePosition,
PartCount, TIMESTAMPDIFF(SECOND, InsertIntoDB, NOW()) FROM inbox WHERE
PartCount > 1 AND RecipientID = %P AND MessageID IN (SELECT MessageID
FROM inbox WHERE PartCount > 1 AND RecipientID = %P AND
InsertIntoDB >= NOW() - INTERVAL 600 SECOND)
ORDER BY InsertIntoDB ASC, ID ASC
update_received
update statistics after receiving message.
default value:
UPDATE phones SET Received = Received + 1 WHERE IMEI = %I
refresh_send_status
update messages in outbox.
default value:
UPDATE outbox SET SendingTimeOut = (NOW() + INTERVAL 60 SECOND) + 0
WHERE ID = %1 AND (SendingTimeOut < NOW() OR SendingTimeOut IS NULL)
the default query calculates sending timeout based on the LoopSleep value. β¨
query specific parameters:
%1β ID of message
find_outbox_sms_id
find sms messages for sending.
default value:
SELECT ID, InsertIntoDB, SendingDateTime, SenderID FROM outbox
WHERE SendingDateTime < NOW() AND SendingTimeOut < NOW() AND
SendBefore >= CURTIME() AND SendAfter <= CURTIME() AND
(SendDays & %2) <> 0 AND
( SenderID is NULL OR SenderID = '' OR SenderID = %P )
ORDER BY Priority DESC, InsertIntoDB ASC LIMIT %1
query specific parameters:
%1β limit of sms messages sended in one walk in loop%2β bit mask for the current weekday in the SMSD process local timezone, using Monday as1through Sunday as64
β οΈ custom queries need to use%2to enforce theoutboxSendDaysrestriction. the default bitwise expression is adapted to the configured SQL dialect. yep, keep it.
find_outbox_body
select body of message.
default value:
SELECT Text, Coding, UDH, Class, TextDecoded, ID, DestinationNumber, MultiPart,
RelativeValidity, DeliveryReport, CreatorID FROM outbox WHERE ID=%1
query specific parameters:
%1β ID of message
find_outbox_multipart
select remaining parts of sms message.
default value:
SELECT Text, Coding, UDH, Class, TextDecoded, ID, SequencePosition
FROM outbox_multipart WHERE ID=%1 AND SequencePosition=%2
query specific parameters:
%1β ID of message%2β number of multipart message
find_sent_item
find an existing sent message before transmission. SMSD uses this to reconcile messages which were written to sentitems but not removed from outbox, for example when the daemon stopped between these two operations. π
The selected columns and their order are mandatory β like, don't shuffle them, don't skip one, nope π . SMSD compares the stored message identity and payload against the outbox message. If it's a matching message that already sent successfully, it gets skipped (slay, we're done here). But if it's a different message chilling under the same ID, it stays in the outbox and gets reported as a conflict π.
Default value:
SELECT Text, Coding, UDH, Class, TextDecoded, DestinationNumber,
InsertIntoDB, RelativeValidity, CreatorID, Status
FROM sentitems WHERE ID=%1 AND SequencePosition=%2
Query specific parameters:
%1β ID of message%2β Number of multipart message
delete_outbox
Removes messages from outbox once they've sent successfully. Bye bestie π
Default value:
DELETE FROM outbox WHERE ID=%1
Query specific parameters:
%1β ID of message
delete_outbox_multipart
Same energy, but it clears messages out of outbox_multipart after their successful send π§Ήβ¨
Default value:
DELETE FROM outbox_multipart WHERE ID=%1
Query specific parameters:
%1β ID of message
create_outbox
Creates a message β aka inserts it into outbox. Main character entry moment π
Default value:
INSERT INTO outbox (CreatorID, SenderID, DeliveryReport, MultiPart,
InsertIntoDB, Text, DestinationNumber, RelativeValidity, Coding, UDH, Class,
TextDecoded) VALUES (%1, %P, %2, %3, NOW(), %E, %R, %V, %c, %u, %x, %T)
Query specific parameters:
%1β creator of message%2β delivery status report - yes/default%3β multipart - FALSE/TRUE%4β Part (part number)%5β ID of message
create_outbox_multipart
Creates the remaining parts of a message β the rest of the multipart squad showing up π«Ά
Default value:
INSERT INTO outbox_multipart (SequencePosition, Text, Coding, UDH, Class,
TextDecoded, ID) VALUES (%4, %E, %c, %u, %x, %T, %5)
Query specific parameters:
%1β creator of message%2β delivery status report - yes/default%3β multipart - FALSE/TRUE%4β Part (part number)%5β ID of message
add_sent_info
Inserts into sentitems β the receipt of record, no cap π
Default value:
INSERT INTO sentitems (CreatorID,ID,SequencePosition,Status,SendingDateTime,
SMSCNumber, TPMR, SenderID,Text,DestinationNumber,Coding,UDH,Class,TextDecoded,
InsertIntoDB,RelativeValidity)
VALUES (%A, %1, %2, %3, NOW(), %F, %4, %P, %E, %R, %c, %u, %x, %T, %5, %V)
Query specific parameters:
%1β ID of sms message%2β part number (for multipart sms)%3β message state (SendingError,Error,SendingOK,SendingOKNoReport)%4β message reference (TPMR)%5β time when inserted in db
update_sent
Updates the sent statistics after sending a message. Gotta keep the receipts up to date, periodt π
Default value:
UPDATE phones SET Sent= Sent + 1 WHERE IMEI = %I
refresh_phone_status
Updates phone status (battery, signal, and network). Little wellness check for your modem πΈπ
Default value:
UPDATE phones SET TimeOut = (NOW() + INTERVAL 70 SECOND) + 0,
Battery = %1, Signal = %2, NetCode = %O, NetName = %M
WHERE IMEI = %I
The expiry interval is generated from theStatusFrequencyoption plus a ten-second grace period, as described forinsert_phone. Custom queries should keepTimeOutvalid through the next refresh β like, don't break the timing bestie π.
Query specific parameters:
%1β battery percent%2β signal percent
update_retries
Updates the number of retries for an outbox message. The interval can be configured by the RetryTimeout option π
UPDATE outbox SET SendngTimeOut = (NOW() + INTERVAL 600 SECOND) + 0,
Retries = %2 WHERE ID = %1
Query specific parameters:
%1β message ID%2β number of retries
π AUTHOR
Michal ΔihaΕ <michal@cihar.com>
π¦ COPYRIGHT
2009-2015, Michal ΔihaΕ <michal@cihar.com>
And that's the whole page, bestie, you ate it up πβ¨ This edition is 1.45.0, dated Sep 16, 2026, and it lives at GAMMU-SMSD-SQL(7) β go forth and query responsibly π
π¦ where this page comes from
- arch rolling: gammu 1.45.0-1 Β· GPL-2.0-or-later
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms