<commit_before>package protocol

import (
	"context"
	"database/sql"
	"encoding/json"
	"fmt"
	"strings"

	"github.com/status-im/status-go/protocol/protobuf"

	"github.com/pkg/errors"
)

var (
	errRecordNotFound = errors.New("record not found")
)

func (db sqlitePersistence) tableUserMessagesAllFields() string {
	return `id,
    		whisper_timestamp,
    		source,
    		text,
    		content_type,
    		username,
    		timestamp,
    		chat_id,
		local_chat_id,
    		message_type,
    		clock_value,
    		seen,
    		outgoing_status,
		parsed_text,
		sticker_pack,
		sticker_hash,
		image_payload,
		image_type,
		image_base64,
		audio_payload,
		audio_type,
		audio_duration_ms,
		audio_base64,
		command_id,
		command_value,
		command_from,
		command_address,
		command_contract,
		command_transaction_hash,
		command_state,
		command_signature,
		replace_message,
		rtl,
		line_count,
		response_to`
}

func (db sqlitePersistence) tableUserMessagesAllFieldsJoin() string {
	return `m1.id,
    		m1.whisper_timestamp,
    		m1.source,
    		m1.text,
    		m1.content_type,
    		m1.username,
    		m1.timestamp,
    		m1.chat_id,
		m1.local_chat_id,
    		m1.message_type,
    		m1.clock_value,
    		m1.seen,
    		m1.outgoing_status,
		m1.parsed_text,
		m1.sticker_pack,
		m1.sticker_hash,
		m1.image_base64,
		COALESCE(m1.audio_duration_ms,0),
		m1.audio_base64,
		m1.command_id,
		m1.command_value,
		m1.command_from,
		m1.command_address,
		m1.command_contract,
		m1.command_transaction_hash,
		m1.command_state,
		m1.command_signature,
		m1.replace_message,
		m1.rtl,
		m1.line_count,
		m1.response_to,
		m2.source,
		m2.text,
		m2.image_base64,
		m2.audio_duration_ms,
		m2.audio_base64,
		c.alias,
		c.identicon`
}

func (db sqlitePersistence) tableUserMessagesAllFieldsCount() int {
	return strings.Count(db.tableUserMessagesAllFields(), ",") + 1
}

type scanner interface {
	Scan(dest ...interface{}) error
}

func (db sqlitePersistence) tableUserMessagesScanAllFields(row scanner, message *Message, others ...interface{}) error {
	var quotedText sql.NullString
	var quotedFrom sql.NullString
	var quotedImage sql.NullString
	var quotedAudio sql.NullString
	var quotedAudioDuration sql.NullInt64
	var alias sql.NullString
	var identicon sql.NullString

	sticker := &protobuf.StickerMessage{}
	command := &CommandParameters{}
	audio := &protobuf.AudioMessage{}

	args := []interface{}{
		&message.ID,
		&message.WhisperTimestamp,
		&message.From, // source in table
		&message.Text,
		&message.ContentType,
		&message.Alias,
		&message.Timestamp,
		&message.ChatId,
		&message.LocalChatID,
		&message.MessageType,
		&message.Clock,
		&message.Seen,
		&message.OutgoingStatus,
		&message.ParsedText,
		&sticker.Pack,
		&sticker.Hash,
		&message.Base64Image,
		&audio.DurationMs,
		&message.Base64Audio,
		&command.ID,
		&command.Value,
		&command.From,
		&command.Address,
		&command.Contract,
		&command.TransactionHash,
		&command.CommandState,
		&command.Signature,
		&message.Replace,
		&message.RTL,
		&message.LineCount,
		&message.ResponseTo,
		&quotedFrom,
		&quotedText,
		&quotedImage,
		&quotedAudioDuration,
		&quotedAudio,
		&alias,
		&identicon,
	}
	err := row.Scan(append(args, others...)...)
	if err != nil {
		return err
	}

	if quotedText.Valid {
		message.QuotedMessage = &QuotedMessage{
			From:            quotedFrom.String,
			Text:            quotedText.String,
			Base64Image:     quotedImage.String,
			AudioDurationMs: uint64(quotedAudioDuration.Int64),
			Base64Audio:     quotedAudio.String,
		}
	}
	message.Alias = alias.String
	message.Identicon = identicon.String

	// TODO switch

	if message.ContentType == protobuf.ChatMessage_STICKER {
		message.Payload = &protobuf.ChatMessage_Sticker{Sticker: sticker}
	}

	if message.ContentType == protobuf.ChatMessage_AUDIO {
		message.Payload = &protobuf.ChatMessage_Audio{Audio: audio}
	}

	if message.ContentType == protobuf.ChatMessage_TRANSACTION_COMMAND {
		message.CommandParameters = command
	}

	return nil
}

func (db sqlitePersistence) tableUserMessagesAllValues(message *Message) ([]interface{}, error) {
	sticker := message.GetSticker()
	if sticker == nil {
		sticker = &protobuf.StickerMessage{}
	}

	image := message.GetImage()
	if image == nil {<commit_msg>Added switch to persistence<commit_after>package protocol

import (
	"context"
	"database/sql"
	"encoding/json"
	"fmt"
	"strings"

	"github.com/status-im/status-go/protocol/protobuf"

	"github.com/pkg/errors"
)

var (
	errRecordNotFound = errors.New("record not found")
)

func (db sqlitePersistence) tableUserMessagesAllFields() string {
	return `id,
    		whisper_timestamp,
    		source,
    		text,
    		content_type,
    		username,
    		timestamp,
    		chat_id,
		local_chat_id,
    		message_type,
    		clock_value,
    		seen,
    		outgoing_status,
		parsed_text,
		sticker_pack,
		sticker_hash,
		image_payload,
		image_type,
		image_base64,
		audio_payload,
		audio_type,
		audio_duration_ms,
		audio_base64,
		command_id,
		command_value,
		command_from,
		command_address,
		command_contract,
		command_transaction_hash,
		command_state,
		command_signature,
		replace_message,
		rtl,
		line_count,
		response_to`
}

func (db sqlitePersistence) tableUserMessagesAllFieldsJoin() string {
	return `m1.id,
    		m1.whisper_timestamp,
    		m1.source,
    		m1.text,
    		m1.content_type,
    		m1.username,
    		m1.timestamp,
    		m1.chat_id,
		m1.local_chat_id,
    		m1.message_type,
    		m1.clock_value,
    		m1.seen,
    		m1.outgoing_status,
		m1.parsed_text,
		m1.sticker_pack,
		m1.sticker_hash,
		m1.image_base64,
		COALESCE(m1.audio_duration_ms,0),
		m1.audio_base64,
		m1.command_id,
		m1.command_value,
		m1.command_from,
		m1.command_address,
		m1.command_contract,
		m1.command_transaction_hash,
		m1.command_state,
		m1.command_signature,
		m1.replace_message,
		m1.rtl,
		m1.line_count,
		m1.response_to,
		m2.source,
		m2.text,
		m2.image_base64,
		m2.audio_duration_ms,
		m2.audio_base64,
		c.alias,
		c.identicon`
}

func (db sqlitePersistence) tableUserMessagesAllFieldsCount() int {
	return strings.Count(db.tableUserMessagesAllFields(), ",") + 1
}

type scanner interface {
	Scan(dest ...interface{}) error
}

func (db sqlitePersistence) tableUserMessagesScanAllFields(row scanner, message *Message, others ...interface{}) error {
	var quotedText sql.NullString
	var quotedFrom sql.NullString
	var quotedImage sql.NullString
	var quotedAudio sql.NullString
	var quotedAudioDuration sql.NullInt64
	var alias sql.NullString
	var identicon sql.NullString

	sticker := &protobuf.StickerMessage{}
	command := &CommandParameters{}
	audio := &protobuf.AudioMessage{}

	args := []interface{}{
		&message.ID,
		&message.WhisperTimestamp,
		&message.From, // source in table
		&message.Text,
		&message.ContentType,
		&message.Alias,
		&message.Timestamp,
		&message.ChatId,
		&message.LocalChatID,
		&message.MessageType,
		&message.Clock,
		&message.Seen,
		&message.OutgoingStatus,
		&message.ParsedText,
		&sticker.Pack,
		&sticker.Hash,
		&message.Base64Image,
		&audio.DurationMs,
		&message.Base64Audio,
		&command.ID,
		&command.Value,
		&command.From,
		&command.Address,
		&command.Contract,
		&command.TransactionHash,
		&command.CommandState,
		&command.Signature,
		&message.Replace,
		&message.RTL,
		&message.LineCount,
		&message.ResponseTo,
		&quotedFrom,
		&quotedText,
		&quotedImage,
		&quotedAudioDuration,
		&quotedAudio,
		&alias,
		&identicon,
	}
	err := row.Scan(append(args, others...)...)
	if err != nil {
		return err
	}

	if quotedText.Valid {
		message.QuotedMessage = &QuotedMessage{
			From:            quotedFrom.String,
			Text:            quotedText.String,
			Base64Image:     quotedImage.String,
			AudioDurationMs: uint64(quotedAudioDuration.Int64),
			Base64Audio:     quotedAudio.String,
		}
	}
	message.Alias = alias.String
	message.Identicon = identicon.String

	switch message.ContentType {
	case protobuf.ChatMessage_STICKER:
		message.Payload = &protobuf.ChatMessage_Sticker{Sticker: sticker}

		if message.ContentType == protobuf.ChatMessage_AUDIO {
			message.Payload = &protobuf.ChatMessage_Audio{Audio: audio}
		}

	case protobuf.ChatMessage_TRANSACTION_COMMAND:
		message.CommandParameters = command
	}

	return nil
}

func (db sqlitePersistence) tableUserMessagesAllValues(message *Message) ([]interface{}, error) {
	sticker := message.GetSticker()
	if sticker == nil {
		sticker = &protobuf.StickerMessage{}
	}

	image := message.GetImage()
	if image == nil {
{'fraction_non_alphanumeric': 0.10930697729144605, 'fraction_numerical': 0.01506059536416049, 'mean_word_length': 3.859919954259577, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5263265', 'n_tokens_mistral': 3375, 'n_tokens_neox': 3111, 'n_words': 521}