-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathMessages.pgc
More file actions
180 lines (147 loc) · 4.32 KB
/
Messages.pgc
File metadata and controls
180 lines (147 loc) · 4.32 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
#include <stdio.h>
#include <stdbool.h>
#include <malloc.h>
#include <time.h>
#include <stdlib.h>
#include <pgtypes.h>
#include <pgtypes_timestamp.h>
#include <ecpglib.h>
#include <ecpgerrno.h>
#include <sqlca.h>
#include "IO.h"
#include "Messages.h"
#include "Locks.h"
#include "Dialogs.h"
EXEC SQL WHENEVER SQLWARNING SQLPRINT;
EXEC SQL WHENEVER SQLERROR SQLPRINT;
EXEC SQL WHENEVER NOT FOUND CONTINUE;
void CreateMessagesTable()
{
EXEC SQL CREATE TABLE Messages
(
MessageId serial PRIMARY KEY,
Text text NOT NULL,
SendDateTime timestamp NOT NULL DEFAULT current_timestamp,
DialogId int NOT NULL,
AuthorId int NOT NULL,
FOREIGN KEY (DialogId) REFERENCES Dialogs (DialogId) ON DELETE CASCADE,
FOREIGN KEY (AuthorId) REFERENCES Accounts (AccountId) ON DELETE CASCADE
);
EXEC SQL COMMIT;
}
void DropMessagesTable()
{
EXEC SQL DROP TABLE IF EXISTS Messages CASCADE;
EXEC SQL COMMIT;
}
void AddMessage(int authorId, int dialogId, char* message)
{
EXEC SQL BEGIN DECLARE SECTION;
int authorId_ = authorId;
int dialogId_ = dialogId;
char* message_ = message;
EXEC SQL END DECLARE SECTION;
EXEC SQL INSERT INTO Messages (Text, AuthorId, DialogId) VALUES (:message_, :authorId_, :dialogId_);
EXEC SQL COMMIT;
}
void SendMessage(int authorId, int dialogId, char* message)
{
AddMessage(authorId, dialogId, message);
UnlockDialog(dialogId);
}
void StartSendingMessages(char* nickname, int dialogId)
{
EXEC SQL BEGIN DECLARE SECTION;
char* nickname_ = nickname;
int authorId;
EXEC SQL END DECLARE SECTION;
EXEC SQL SELECT AccountId INTO :authorId FROM Accounts WHERE Nickname = :nickname_;
while (true)
{
printf(" > ");
char msg[MESSAGE_SIZE];
while (InputLine(msg, MESSAGE_SIZE) <= 0)
{
}
SendMessage(authorId, dialogId, msg);
}
}
void GetPrintMessages(int dialogId, int lastMessages)
{
EXEC SQL BEGIN DECLARE SECTION;
int dialogId_ = dialogId;
int offset;
int count;
timestamp ts;
char msg[MESSAGE_SIZE];
int authorId;
char name1[STRING_SIZE];
char name2[STRING_SIZE];
int maxAuthorId;
EXEC SQL END DECLARE SECTION;
GetDialogTwoMembers(dialogId, name1, name2);
EXEC SQL SELECT max(AccountId) INTO :maxAuthorId FROM AccountsDialogs WHERE DialogId = :dialogId_;
if (lastMessages == -1)
{
offset = 0;
}
else
{
EXEC SQL SELECT count(*) INTO :count FROM Messages WHERE DialogId = :dialogId_;
offset = count - lastMessages;
offset = offset < 0 ? 0 : offset;
}
EXEC SQL DECLARE cursor5 CURSOR FOR
SELECT Text, SendDateTime, AuthorId FROM Messages
WHERE DialogId = :dialogId_
ORDER BY SendDateTime
OFFSET :offset;
EXEC SQL OPEN cursor5;
EXEC SQL WHENEVER NOT FOUND DO BREAK;
while (true)
{
EXEC SQL FETCH cursor5 INTO :msg, :ts, :authorId;
OutputMessage(authorId < maxAuthorId ? name1 : name2, msg, ts);
}
EXEC SQL WHENEVER NOT FOUND CONTINUE;
EXEC SQL CLOSE cursor5;
}
void ReceiveMessage(int dialogId)
{
EXEC SQL BEGIN DECLARE SECTION;
int dialogId_ = dialogId;
char msg[MESSAGE_SIZE];
timestamp sendDateTime;
int authorId;
char authorName[STRING_SIZE];
EXEC SQL END DECLARE SECTION;
timestamp current;
PGTYPEStimestamp_current(¤t);
char* currentstr = PGTYPEStimestamp_to_asc(current);
char lockname[STRING_SIZE];
sprintf(lockname, "%s-%d", currentstr, rand());
PGTYPESchar_free(currentstr);
Lock(lockname, dialogId);
Wait(lockname);
EXEC SQL SELECT Text, SendDateTime, AuthorId
INTO :msg, :sendDateTime, :authorId
FROM Messages
WHERE DialogId = :dialogId_
ORDER BY SendDateTime DESC
LIMIT 1;
EXEC SQL SELECT Nickname INTO :authorName FROM Accounts WHERE AccountId = :authorId;
OutputMessage(authorName, msg, sendDateTime);
EXEC SQL COMMIT;
}
void StartReceivingMessages(int dialogId, int lastMessages)
{
EXEC SQL BEGIN DECLARE SECTION;
int dialogId_ = dialogId;
EXEC SQL END DECLARE SECTION;
printf("Диалог №%d:\n", dialogId_);
GetPrintMessages(dialogId, lastMessages);
while (true)
{
ReceiveMessage(dialogId_);
}
}