peasys-ruby 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/lib/pea_client.rb +478 -0
- data/lib/pea_exception.rb +31 -0
- data/lib/pea_response.rb +300 -0
- metadata +45 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: a2bfe718a25db8bdd2f49fa52d98d431b72bcc7615a8228b39e57d8e92b3d587
|
4
|
+
data.tar.gz: 896d7f841636adec7f73a3b3f32beb5ede86267c27622b825d9c4acf9464d3e0
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 0fb9b7343f3fdf459aff902176db299311b6d88a23457ac0fc1c88821cf3a716364d3eaf0fb82da1066b53972679450d053ecc32f3969d0bc3ec77a2dafcd9c1
|
7
|
+
data.tar.gz: 2a8c6efd843b885428da0fa402f4d0b8bded3234a19700b26ea132429cef0169ac21f1f7fb0e830300bd8c8c8614b4c7e4f0ad0beebfd812c33bb3680fc9fab4
|
data/lib/pea_client.rb
ADDED
@@ -0,0 +1,478 @@
|
|
1
|
+
require 'socket'
|
2
|
+
require 'json'
|
3
|
+
require 'uri'
|
4
|
+
require 'net/http'
|
5
|
+
|
6
|
+
class PeaClient
|
7
|
+
@@end_pack = "dipsjbiemg"
|
8
|
+
|
9
|
+
##
|
10
|
+
# Initialize a new instance of the PeaClient class. Initiates a connexion with the AS/400 server.
|
11
|
+
#
|
12
|
+
# Params:
|
13
|
+
# +partition_name+:: DNS name (name of the partition) of the remote AS/400 server.
|
14
|
+
# +port+:: Port used for the data exchange between the client and the server.
|
15
|
+
# +username+:: Username of the AS/400 profile used for connexion.
|
16
|
+
# +password+:: Password of the AS/400 profile used for connexion.
|
17
|
+
# +id_client+:: ID of the client account on the DIPS website.
|
18
|
+
# +online_version+:: Set to true if you want to use the online version of Peasys (<see cref="https://dips400.com/docs/connexion"/>).
|
19
|
+
# +retrieve_statistics+:: Set to true if you want the statistics of the license key use to be collect.
|
20
|
+
#
|
21
|
+
# raises a PeaInvalidCredentialsError if credentials are empty.
|
22
|
+
# raises a PeaConnexionError if an error occured during the connexion process.
|
23
|
+
# raises a PeaInvalidCredentialsError if IBMi credentials are invalid.
|
24
|
+
|
25
|
+
def initialize(ip_adress, partition_name, port, username, password, id_client, online_version, retrieve_statistics)
|
26
|
+
|
27
|
+
if ip_adress.empty? || username.empty? || password.empty?
|
28
|
+
raise PeaInvalidCredentialsError.new("Parameters of the PeaClient should not be either null or empty")
|
29
|
+
end
|
30
|
+
|
31
|
+
@ip_adress = ip_adress
|
32
|
+
@id_client = id_client
|
33
|
+
@partition_name = partition_name
|
34
|
+
@username = username
|
35
|
+
@password = password
|
36
|
+
@port = port
|
37
|
+
@online_version = online_version
|
38
|
+
@retrieve_statistics = retrieve_statistics
|
39
|
+
@connexion_status = "ds"
|
40
|
+
@connexion_message = "ds"
|
41
|
+
|
42
|
+
token = "xqdsg27010wmca6052009050000000IDSP1tiupozxreybjhlk"
|
43
|
+
if online_version
|
44
|
+
begin
|
45
|
+
uri = URI("https://dips400.com/api/license-key/retrieve-token/#{partition_name}/#{id_client}")
|
46
|
+
res = Net::HTTP.get_response(uri)
|
47
|
+
|
48
|
+
data = JSON.parse(res.body)
|
49
|
+
token = data["token"]
|
50
|
+
is_valid = data["isValid"]
|
51
|
+
|
52
|
+
if not(is_valid)
|
53
|
+
raise PeaInvalidLicenseKeyError.new("Your subscription is not valid, visit https://dips400.com/account/subscriptions for more information.")
|
54
|
+
end
|
55
|
+
|
56
|
+
rescue PeaInvalidLicenseKeyError => e
|
57
|
+
raise e
|
58
|
+
rescue StandardError => error
|
59
|
+
# If dips400.com doesn't respond, let's try an affline verification with the offline token
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
begin
|
64
|
+
@tcp_client = TCPSocket.new ip_adress, port
|
65
|
+
rescue => error
|
66
|
+
raise PeaConnexionError.new(error.full_message)
|
67
|
+
else
|
68
|
+
login = username.ljust(10, " ") + token.ljust(50, " ") + password
|
69
|
+
@tcp_client.send(login, 0)
|
70
|
+
@connexion_status = @tcp_client.read(1)
|
71
|
+
|
72
|
+
case @connexion_status
|
73
|
+
when "1"
|
74
|
+
@connexion_message = "Connected"
|
75
|
+
@connexion_status = 1
|
76
|
+
when "2"
|
77
|
+
@connexion_message = "Unable to set profile, check profile validity."
|
78
|
+
@connexion_status = 2
|
79
|
+
raise PeaConnexionError.new("Unable to set profile, check profile validity.")
|
80
|
+
when "3"
|
81
|
+
@connexion_message = "Invalid credential"
|
82
|
+
@connexion_status = 1
|
83
|
+
raise PeaInvalidCredentialsError.new("Invalid userName or password, check again")
|
84
|
+
when "B"
|
85
|
+
@connexion_message = "Peasys Online : your token connexion is no longer valid, retry to connect."
|
86
|
+
@connexion_status = 5
|
87
|
+
raise PeaConnexionError.new("Peasys Online : your token connexion is no longer valid, retry to connect.")
|
88
|
+
when "D"
|
89
|
+
@connexion_message = "Peasys Online : the partition name you provided doesn't match the actual name of the machine."
|
90
|
+
@connexion_status = 6
|
91
|
+
raise PeaConnexionError.new("Peasys Online : the partition name you provided doesn't match the actual name of the machine.")
|
92
|
+
when "E"
|
93
|
+
@connexion_message = "You reached the max number of simultaneously connected peasys users for that partition and license key. Contact us for upgrading your license."
|
94
|
+
@connexion_status = 7
|
95
|
+
raise PeaConnexionError.new("You reached the max number of simultaneously connected peasys users for that partition and license key. Contact us for upgrading your license.")
|
96
|
+
when "F"
|
97
|
+
@connexion_message = "Your license is no longer valid. Subscribe to another license in order to continue using Peasys."
|
98
|
+
@connexion_status = 8
|
99
|
+
raise PeaConnexionError.new("Your license is no longer valid. Subscribe to another license in order to continue using Peasys.")
|
100
|
+
when "0" , "A" , "C" , "G"
|
101
|
+
@connexion_message = "Error linked to DIPS source code. Please, contact us immediatly to fix the issue."
|
102
|
+
@connexion_status = -1
|
103
|
+
raise PeaConnexionError.new("Error linked to DIPS source code. Please, contact us immediatly to fix the issue.")
|
104
|
+
else
|
105
|
+
raise PeaConnexionError.new("Exception during connexion process, contact us for more informations")
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
##
|
111
|
+
# Sends the SELECT SQL query to the server that execute it and retrieve the desired data.
|
112
|
+
#
|
113
|
+
# Params:
|
114
|
+
# +query+:: SQL query that should start with the SELECT keyword.
|
115
|
+
#
|
116
|
+
# raises a PeaInvalidSyntaxQueryError if query is empty or doesn't start with SELECT.
|
117
|
+
|
118
|
+
def execute_select(query)
|
119
|
+
if query.empty?
|
120
|
+
raise PeaInvalidSyntaxQueryError.new("Query should not be either null or empty")
|
121
|
+
end
|
122
|
+
if !query.upcase.start_with?("SELECT")
|
123
|
+
raise PeaInvalidSyntaxQueryError.new("Query should start with the SELECT SQL keyword")
|
124
|
+
end
|
125
|
+
|
126
|
+
result, list_name, nb_row, sql_state, sql_message = build_data(query)
|
127
|
+
|
128
|
+
return PeaSelectResponse.new(sql_message.eql?("00000"), sql_message, sql_state, result, nb_row, list_name)
|
129
|
+
end
|
130
|
+
|
131
|
+
##
|
132
|
+
# Sends the UPDATE SQL query to the server that execute it and retrieve the desired data.
|
133
|
+
#
|
134
|
+
# Params:
|
135
|
+
# +query+:: SQL query that should start with the UPDATE keyword.
|
136
|
+
#
|
137
|
+
# raises a PeaInvalidSyntaxQueryError if query is empty or doesn't start with UPDATE.
|
138
|
+
|
139
|
+
def execute_update(query)
|
140
|
+
if query.empty?
|
141
|
+
raise PeaInvalidSyntaxQueryError.new("Query should not be either null or empty")
|
142
|
+
end
|
143
|
+
if !query.upcase.start_with?("UPDATE")
|
144
|
+
raise PeaInvalidSyntaxQueryError.new("Query should start with the UPDATE SQL keyword")
|
145
|
+
end
|
146
|
+
|
147
|
+
nb_row, sql_state, sql_message = modify_table(query)
|
148
|
+
has_succeeded = sql_state.eql?("00000") || sql_state.eql?("01504")
|
149
|
+
|
150
|
+
return PeaUpdateResponse.new(has_succeeded, sql_message, sql_state, nb_row)
|
151
|
+
end
|
152
|
+
|
153
|
+
##
|
154
|
+
# Sends the CREATE SQL query to the server that execute it and retrieve the desired data.
|
155
|
+
#
|
156
|
+
# Params:
|
157
|
+
# +query+:: SQL query that should start with the CREATE keyword.
|
158
|
+
#
|
159
|
+
# raises a PeaInvalidSyntaxQueryError if query is empty or doesn't start with CREATE.
|
160
|
+
|
161
|
+
def execute_create(query)
|
162
|
+
if query.empty?
|
163
|
+
raise PeaInvalidSyntaxQueryError.new("Query should not be either null or empty")
|
164
|
+
end
|
165
|
+
if !query.upcase.start_with?("CREATE")
|
166
|
+
raise PeaInvalidSyntaxQueryError.new("Query should start with the CREATE SQL keyword")
|
167
|
+
end
|
168
|
+
|
169
|
+
nb_row, sql_state, sql_message = modify_table(query)
|
170
|
+
|
171
|
+
query_words = query.split(' ')
|
172
|
+
tb_schema = Hash.new()
|
173
|
+
if query_words[1].upcase.eql?("TABLE")
|
174
|
+
names = query_words[2].split('/')
|
175
|
+
tb_query = """SELECT COLUMN_NAME, ORDINAL_POSITION, DATA_TYPE, LENGTH, NUMERIC_SCALE, IS_NULLABLE, IS_UPDATABLE, NUMERIC_PRECISION FROM
|
176
|
+
QSYS2.SYSCOLUMNS WHERE SYSTEM_TABLE_NAME = '""" + names[1].upcase + "' AND SYSTEM_TABLE_SCHEMA = '" + names[0].upcase + "'"
|
177
|
+
|
178
|
+
result, list_name, nb_row, sql_state, sql_message = build_data(tb_query)
|
179
|
+
|
180
|
+
for i in 0..(nb_row - 1) do
|
181
|
+
tb_schema["column_name"] = ColumnInfo.new(result["COLUMN_NAME"][i], result["ORDINAL_POSITION"][i], result["DATA_TYPE"][i], result["LENGTH"][i],
|
182
|
+
result["NUMERIC_SCALE"][i], result["IS_NULLABLE"][i], result["IS_UPDATABLE"][i], result["NUMERIC_PRECISION"][i])
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
case query_words[1].upcase
|
187
|
+
when "TABLE"
|
188
|
+
return PeaCreateResponse.new(sql_message.eql?("00000"), sql_message, sql_state, "", "", tb_schema)
|
189
|
+
when "INDEX"
|
190
|
+
return PeaCreateResponse.new(sql_message.eql?("00000"), sql_message, sql_state, "", query_words[2], "")
|
191
|
+
when "DATABASE"
|
192
|
+
return PeaCreateResponse.new(sql_message.eql?("00000"), sql_message, sql_state, query_words[2], "", "")
|
193
|
+
else
|
194
|
+
raise PeaConnexionError.new("Exception during connexion process, contact us for more informations")
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
##
|
199
|
+
# Sends the DELETE SQL query to the server that execute it and retrieve the desired data.
|
200
|
+
#
|
201
|
+
# Params:
|
202
|
+
# +query+:: SQL query that should start with the DELETE keyword.
|
203
|
+
#
|
204
|
+
# raises a PeaInvalidSyntaxQueryError if query is empty or doesn't start with DELETE.
|
205
|
+
|
206
|
+
def execute_delete(query)
|
207
|
+
if query.empty?
|
208
|
+
raise PeaInvalidSyntaxQueryError.new("Query should not be either null or empty")
|
209
|
+
end
|
210
|
+
if !query.upcase.start_with?("DELETE")
|
211
|
+
raise PeaInvalidSyntaxQueryError.new("Query should start with the DELETE SQL keyword")
|
212
|
+
end
|
213
|
+
|
214
|
+
nb_row, sql_state, sql_message = modify_table(query)
|
215
|
+
|
216
|
+
return PeaDeleteResponse.new(sql_message.eql?("00000"), sql_message, sql_state, nb_row)
|
217
|
+
end
|
218
|
+
|
219
|
+
##
|
220
|
+
# Sends the ALTER SQL query to the server that execute it and retrieve the desired data.
|
221
|
+
#
|
222
|
+
# Params:
|
223
|
+
# +query+:: SQL query that should start with the ALTER keyword.
|
224
|
+
#
|
225
|
+
# raises a PeaInvalidSyntaxQueryError if query is empty or doesn't start with ALTER.
|
226
|
+
|
227
|
+
def execute_alter(query, retrieve_table_schema)
|
228
|
+
if query.empty?
|
229
|
+
raise PeaInvalidSyntaxQueryError.new("Query should not be either null or empty")
|
230
|
+
end
|
231
|
+
if !query.upcase.start_with?("ALTER")
|
232
|
+
raise PeaInvalidSyntaxQueryError.new("Query should start with the ALTER SQL keyword")
|
233
|
+
end
|
234
|
+
|
235
|
+
nb_row, sql_state, sql_message = modify_table(query)
|
236
|
+
|
237
|
+
tb_schema = Hash.new()
|
238
|
+
if retrieve_table_schema
|
239
|
+
query_words = query.split(' ')
|
240
|
+
names = query_words[2].split('/')
|
241
|
+
tb_query = """SELECT COLUMN_NAME, ORDINAL_POSITION, DATA_TYPE, LENGTH, NUMERIC_SCALE, IS_NULLABLE, IS_UPDATABLE, NUMERIC_PRECISION FROM
|
242
|
+
QSYS2.SYSCOLUMNS WHERE SYSTEM_TABLE_NAME = '""" + names[1].upcase + "' AND SYSTEM_TABLE_SCHEMA = '" + names[0].upcase + "'"
|
243
|
+
|
244
|
+
result, list_name, nb_row, sql_state, sql_message = build_data(tb_query)
|
245
|
+
|
246
|
+
for i in 0..(nb_row - 1) do
|
247
|
+
tb_schema["column_name"] = ColumnInfo.new(result["COLUMN_NAME"][i], result["ORDINAL_POSITION"][i], result["DATA_TYPE"][i], result["LENGTH"][i],
|
248
|
+
result["NUMERIC_SCALE"][i], result["IS_NULLABLE"][i], result["IS_UPDATABLE"][i], result["NUMERIC_PRECISION"][i])
|
249
|
+
end
|
250
|
+
end
|
251
|
+
|
252
|
+
return PeaAlterResponse.new(sql_message.eql?("00000"), sql_message, sql_state, tb_schema)
|
253
|
+
end
|
254
|
+
|
255
|
+
##
|
256
|
+
# Sends the DROP SQL query to the server that execute it and retrieve the desired data.
|
257
|
+
#
|
258
|
+
# Params:
|
259
|
+
# +query+:: SQL query that should start with the DROP keyword.
|
260
|
+
#
|
261
|
+
# raises a PeaInvalidSyntaxQueryError if query is empty or doesn't start with DROP.
|
262
|
+
|
263
|
+
def execute_drop(query)
|
264
|
+
if query.empty?
|
265
|
+
raise PeaInvalidSyntaxQueryError.new("Query should not be either null or empty")
|
266
|
+
end
|
267
|
+
if !query.upcase.start_with?("DROP")
|
268
|
+
raise PeaInvalidSyntaxQueryError.new("Query should start with the DROP SQL keyword")
|
269
|
+
end
|
270
|
+
|
271
|
+
nb_row, sql_state, sql_message = modify_table(query)
|
272
|
+
|
273
|
+
return PeaDropResponse.new(sql_message.eql?("00000"), sql_message, sql_state)
|
274
|
+
end
|
275
|
+
|
276
|
+
##
|
277
|
+
# Sends the INSERT SQL query to the server that execute it and retrieve the desired data.
|
278
|
+
#
|
279
|
+
# Params:
|
280
|
+
# +query+:: SQL query that should start with the INSERT keyword.
|
281
|
+
#
|
282
|
+
# raises a PeaInvalidSyntaxQueryError if query is empty or doesn't start with INSERT.
|
283
|
+
|
284
|
+
def execute_insert(query)
|
285
|
+
if query.empty?
|
286
|
+
raise PeaInvalidSyntaxQueryError.new("Query should not be either null or empty")
|
287
|
+
end
|
288
|
+
if !query.upcase.start_with?("INSERT")
|
289
|
+
raise PeaInvalidSyntaxQueryError.new("Query should start with the INSERT SQL keyword")
|
290
|
+
end
|
291
|
+
|
292
|
+
nb_row, sql_state, sql_message = modify_table(query)
|
293
|
+
|
294
|
+
return PeaInsertResponse.new(sql_message.eql?("00000"), sql_message, sql_state, nb_row)
|
295
|
+
end
|
296
|
+
|
297
|
+
##
|
298
|
+
# Sends the SQL query to the server that execute it and retrieve the desired data.
|
299
|
+
#
|
300
|
+
# Params:
|
301
|
+
# +query+:: SQL query.
|
302
|
+
#
|
303
|
+
# raises a PeaInvalidSyntaxQueryError if query is empty.
|
304
|
+
|
305
|
+
def execute_sql(query)
|
306
|
+
if query.empty?
|
307
|
+
raise PeaInvalidSyntaxQueryError.new("Query should not be either null or empty")
|
308
|
+
end
|
309
|
+
|
310
|
+
nb_row, sql_state, sql_message = modify_table(query)
|
311
|
+
|
312
|
+
return PeaResponse.new(sql_message.eql?("00000"), sql_message, sql_state)
|
313
|
+
end
|
314
|
+
|
315
|
+
##
|
316
|
+
# Sends a OS/400 command to the server and retreives the potential warning messages.
|
317
|
+
#
|
318
|
+
# Params:
|
319
|
+
# +command+:: The command that will be sent to the server.
|
320
|
+
|
321
|
+
def execute_command(command)
|
322
|
+
data = retrieve_data("exas" + command + @@end_pack)
|
323
|
+
description_offset = 112
|
324
|
+
result = Array.new()
|
325
|
+
|
326
|
+
/C[A-Z]{2}[0-9]{4}/.match(data) do |m|
|
327
|
+
|
328
|
+
if !m[0].start_with?("CPI") && m.offset(0)[0] + description_offset < data.length
|
329
|
+
description = data[m.offset(0)[0] + description_offset..(data.length - (m.offset(0)[0] + description_offset))]
|
330
|
+
description = description[0..description.index(".")]
|
331
|
+
description = description.gsub(/[^a-zA-Z0-9 ._'*:-]/, '')
|
332
|
+
end
|
333
|
+
|
334
|
+
result.append(m[0] + " " + description)
|
335
|
+
|
336
|
+
end
|
337
|
+
return PeaCommandResponse.new(result)
|
338
|
+
end
|
339
|
+
|
340
|
+
##
|
341
|
+
# Closes the TCP connexion with the server.
|
342
|
+
|
343
|
+
def disconnect()
|
344
|
+
@tcp_client.send("stopdipsjbiemg", 0)
|
345
|
+
@tcp_client.close()
|
346
|
+
end
|
347
|
+
|
348
|
+
def id_client
|
349
|
+
@id_client
|
350
|
+
end
|
351
|
+
|
352
|
+
def partition_name
|
353
|
+
@partition_name
|
354
|
+
end
|
355
|
+
|
356
|
+
def username
|
357
|
+
@username
|
358
|
+
end
|
359
|
+
|
360
|
+
def port
|
361
|
+
@port
|
362
|
+
end
|
363
|
+
|
364
|
+
def online_version
|
365
|
+
@online_version
|
366
|
+
end
|
367
|
+
|
368
|
+
def retrieve_statistics
|
369
|
+
@retrieve_statistics
|
370
|
+
end
|
371
|
+
|
372
|
+
def connexion_status
|
373
|
+
@connexion_status
|
374
|
+
end
|
375
|
+
|
376
|
+
def connexion_message
|
377
|
+
@connexion_message
|
378
|
+
end
|
379
|
+
|
380
|
+
private
|
381
|
+
|
382
|
+
def build_data(query)
|
383
|
+
header = retrieve_data("geth" + query + @@end_pack)
|
384
|
+
sql_state = "00000"
|
385
|
+
sql_message = "SELECT correctly executed"
|
386
|
+
|
387
|
+
begin
|
388
|
+
header_data = JSON.parse(header)
|
389
|
+
rescue
|
390
|
+
sql_state = header[1..5];
|
391
|
+
sql_message = header[6..];
|
392
|
+
else
|
393
|
+
list_name = Array.new()
|
394
|
+
list_type = Array.new()
|
395
|
+
list_prec = Array.new()
|
396
|
+
list_scal = Array.new();
|
397
|
+
|
398
|
+
header_data.each do |item|
|
399
|
+
list_name = list_name.append(item["name"].strip)
|
400
|
+
list_type = list_type.append(item["type"].to_i)
|
401
|
+
list_prec = list_prec.append(item["prec"].to_i)
|
402
|
+
list_scal = list_scal.append(item["scal"].to_i)
|
403
|
+
end
|
404
|
+
end
|
405
|
+
|
406
|
+
nb_col = list_name.length
|
407
|
+
sum_precision = 0
|
408
|
+
result = Hash.new()
|
409
|
+
list_prec.each_index do |i|
|
410
|
+
sum_precision += list_prec[i]
|
411
|
+
result[list_name[i]] = Array.new()
|
412
|
+
end
|
413
|
+
|
414
|
+
data = retrieve_data("getd" + query + @@end_pack)
|
415
|
+
|
416
|
+
# sends statistics
|
417
|
+
|
418
|
+
nb_row = data.length / sum_precision;
|
419
|
+
pointer = 0;
|
420
|
+
while pointer != data.length
|
421
|
+
for m in 0..(nb_col - 1) do
|
422
|
+
scale = list_scal[m]
|
423
|
+
precision = list_prec[m]
|
424
|
+
type = list_type[m]
|
425
|
+
name = list_name[m]
|
426
|
+
|
427
|
+
if ((type == 484 && scale != 0) || (type == 485 && scale != 0) || (type == 488 && scale != 0) || (type == 489 && scale != 0)) # numeric packed
|
428
|
+
temp_float_data = data[pointer..(pointer + precision - 1)].to_f / 10 ** scale
|
429
|
+
pointer += precision;
|
430
|
+
result[name].append(temp_float_data.to_s);
|
431
|
+
elsif (type == 492 || type == 493) # long
|
432
|
+
result[name].append(data[pointer..(pointer + 20 - 1)].strip);
|
433
|
+
pointer += 20;
|
434
|
+
elsif (type == 496 || type == 497) # int
|
435
|
+
result[name].append(data[pointer..(pointer + 10 - 1)].strip);
|
436
|
+
pointer += 10;
|
437
|
+
elsif (type == 500 || type == 501) # short
|
438
|
+
result[name].append(data[pointer..(pointer + 5 - 1)].strip);
|
439
|
+
pointer += 5;
|
440
|
+
else # string, date, time, timestamp
|
441
|
+
result[name].append(data[pointer..(pointer + precision - 1)].strip);
|
442
|
+
pointer += precision;
|
443
|
+
end
|
444
|
+
end
|
445
|
+
end
|
446
|
+
return result, list_name, nb_row, sql_state, sql_message
|
447
|
+
end
|
448
|
+
|
449
|
+
def modify_table(query)
|
450
|
+
header = retrieve_data("updt" + query + @@end_pack)
|
451
|
+
sql_state = header[1..5]
|
452
|
+
sql_message = header[6..]
|
453
|
+
|
454
|
+
# retrieve stats
|
455
|
+
|
456
|
+
row_count = 0
|
457
|
+
if query.upcase.start_with?("INSERT") || query.upcase.start_with?("UPDATE") || query.upcase.start_with?("DELETE")
|
458
|
+
row_count = sql_state.eql?("00000") ? sql_message[..1].to_i : 0
|
459
|
+
end
|
460
|
+
|
461
|
+
return row_count, sql_state, sql_message
|
462
|
+
end
|
463
|
+
|
464
|
+
def retrieve_data(command)
|
465
|
+
|
466
|
+
@tcp_client.send(command, 0)
|
467
|
+
|
468
|
+
data = ""
|
469
|
+
if command.start_with?("geth") || command.start_with?("updt")
|
470
|
+
data += "["
|
471
|
+
end
|
472
|
+
|
473
|
+
while data.length < @@end_pack.length || data[(data.length - @@end_pack.length)..(data.length-1)] != @@end_pack
|
474
|
+
data += @tcp_client.read(1)
|
475
|
+
end
|
476
|
+
return data[0..(data.length - (@@end_pack.length + 1))]
|
477
|
+
end
|
478
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
|
2
|
+
class PeaError < StandardError
|
3
|
+
|
4
|
+
##
|
5
|
+
# Abstract the concept of exception encountered during the manipulation of the Peasys library
|
6
|
+
#
|
7
|
+
# Params:
|
8
|
+
# +msg+:: The message describing the error.
|
9
|
+
|
10
|
+
def initialize(msg="Error coming from the Peasys library")
|
11
|
+
super(msg)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
class PeaConnexionError < PeaError
|
16
|
+
end
|
17
|
+
|
18
|
+
class PeaInvalidCredentialsError < PeaConnexionError
|
19
|
+
end
|
20
|
+
|
21
|
+
class PeaInvalidLicenseKeyError < PeaConnexionError
|
22
|
+
end
|
23
|
+
|
24
|
+
class PeaQueryerror < PeaError
|
25
|
+
end
|
26
|
+
|
27
|
+
class PeaInvalidSyntaxQueryError < PeaQueryerror
|
28
|
+
end
|
29
|
+
|
30
|
+
class PeaUnsupportedOperationError < PeaQueryerror
|
31
|
+
end
|
data/lib/pea_response.rb
ADDED
@@ -0,0 +1,300 @@
|
|
1
|
+
# Abstracts the concept of response in the case of a query executed on the database of an AS/400 server by a PeaClient object.
|
2
|
+
|
3
|
+
class PeaResponse
|
4
|
+
|
5
|
+
##
|
6
|
+
# Initialize a new instance of the PeaResponse class.
|
7
|
+
#
|
8
|
+
# Params:
|
9
|
+
# +has_succeeded+:: Boolean set to true if the query has correctly been executed. Set to true if the SQL state is 00000.
|
10
|
+
# +sql_message+:: SQL message return from the execution of the query.
|
11
|
+
# +sql_state+:: SQL state return from the execution of the query.
|
12
|
+
|
13
|
+
def initialize(has_succeeded, sql_message, sql_state)
|
14
|
+
@has_succeeded = has_succeeded
|
15
|
+
@sql_message = sql_message
|
16
|
+
@sql_state = sql_state
|
17
|
+
end
|
18
|
+
|
19
|
+
def has_succeeded
|
20
|
+
@has_succeeded
|
21
|
+
end
|
22
|
+
|
23
|
+
def sql_message
|
24
|
+
@sql_message
|
25
|
+
end
|
26
|
+
|
27
|
+
def sql_state
|
28
|
+
@sql_state
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
# Represents the concept of response in the case of a CREATE query executed on the database of an AS/400 server by a PeaClient object.
|
33
|
+
|
34
|
+
class PeaCreateResponse < PeaResponse
|
35
|
+
|
36
|
+
##
|
37
|
+
# Initialize a new instance of the PeaCreateResponse class.
|
38
|
+
#
|
39
|
+
# Params:
|
40
|
+
# +has_succeeded+:: Boolean set to true if the query has correctly been executed. Set to true if the SQL state is 00000.
|
41
|
+
# +sql_message+:: SQL message return from the execution of the query.
|
42
|
+
# +sql_state+:: SQL state return from the execution of the query.
|
43
|
+
# +database_name+:: Name of the database if the SQL create query creates a new database.
|
44
|
+
# +index_name+:: Name of the index if the SQL create query creates a new index.
|
45
|
+
# +table_schema+:: Schema of the table if the SQL create query creates a new table. The Schema is a Dictionary with columns' name as key and a ColumnInfo object as value.
|
46
|
+
|
47
|
+
def initialize(has_succeeded, sql_message, sql_state, database_name, index_name, table_schema)
|
48
|
+
super has_succeeded, sql_message, sql_state
|
49
|
+
|
50
|
+
@database_name = database_name
|
51
|
+
@index_name = index_name
|
52
|
+
@table_schema = table_schema
|
53
|
+
end
|
54
|
+
|
55
|
+
def database_name
|
56
|
+
@database_name
|
57
|
+
end
|
58
|
+
|
59
|
+
def index_name
|
60
|
+
@index_name
|
61
|
+
end
|
62
|
+
|
63
|
+
def table_schema
|
64
|
+
@table_schema
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
# Represents the concept of response in the case of an ALTER query executed on the database of an AS/400 server by a PeaClient object.
|
69
|
+
|
70
|
+
class PeaAlterResponse < PeaResponse
|
71
|
+
|
72
|
+
##
|
73
|
+
# Initialize a new instance of the PeaAlterResponse class.
|
74
|
+
#
|
75
|
+
# Params:
|
76
|
+
# +has_succeeded+:: Boolean set to true if the query has correctly been executed. Set to true if the SQL state is 00000.
|
77
|
+
# +sql_message+:: SQL message return from the execution of the query.
|
78
|
+
# +sql_state+:: SQL state return from the execution of the query.
|
79
|
+
# +table_schema+:: Schema of the table if the SQL create query creates a new table. The Schema is a Dictionary with columns' name as key and a ColumnInfo object as value.
|
80
|
+
|
81
|
+
def initialize(has_succeeded, sql_message, sql_state, table_schema)
|
82
|
+
super has_succeeded, sql_message, sql_state
|
83
|
+
|
84
|
+
@table_schema = table_schema
|
85
|
+
end
|
86
|
+
|
87
|
+
def table_schema
|
88
|
+
@table_schema
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
# Represents the concept of response in the case of a DROP query executed on the database of an AS/400 server by a PeaClient object.
|
93
|
+
|
94
|
+
class PeaDropResponse < PeaResponse
|
95
|
+
|
96
|
+
##
|
97
|
+
# Initialize a new instance of the PeaDropResponse class.
|
98
|
+
#
|
99
|
+
# Params:
|
100
|
+
# +has_succeeded+:: Boolean set to true if the query has correctly been executed. Set to true if the SQL state is 00000.
|
101
|
+
# +sql_message+:: SQL message return from the execution of the query.
|
102
|
+
# +sql_state+:: SQL state return from the execution of the query.
|
103
|
+
|
104
|
+
def initialize(has_succeeded, sql_message, sql_state)
|
105
|
+
super has_succeeded, sql_message, sql_state
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
# Represents the concept of response in the case of a SELECT query executed on the database of an AS/400 server by a PeaClient object.
|
110
|
+
|
111
|
+
class PeaSelectResponse < PeaResponse
|
112
|
+
|
113
|
+
##
|
114
|
+
# Initialize a new instance of the PeaSelectResponse class.
|
115
|
+
#
|
116
|
+
# Params:
|
117
|
+
# +has_succeeded+:: Boolean set to true if the query has correctly been executed. Set to true if the SQL state is 00000.
|
118
|
+
# +sql_message+:: SQL message return from the execution of the query.
|
119
|
+
# +sql_state+:: SQL state return from the execution of the query.
|
120
|
+
# +result+:: Results of the query in the form of an Dictionary where the columns' name are the key and the values are the elements of this column in the SQL table.
|
121
|
+
# +row_count+:: Represents the number of rows that have been retreived by the query.
|
122
|
+
# +columns_name+:: Array representing the name of the columns in the order of the SELECT query.
|
123
|
+
|
124
|
+
def initialize(has_succeeded, sql_message, sql_state, result, row_count, columns_name)
|
125
|
+
super has_succeeded, sql_message, sql_state
|
126
|
+
|
127
|
+
@result = result
|
128
|
+
@row_count = row_count
|
129
|
+
@columns_name = columns_name
|
130
|
+
end
|
131
|
+
|
132
|
+
def result
|
133
|
+
@result
|
134
|
+
end
|
135
|
+
|
136
|
+
def row_count
|
137
|
+
@row_count
|
138
|
+
end
|
139
|
+
|
140
|
+
def columns_name
|
141
|
+
@columns_name
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
# Represents the concept of response in the case of an UPDATE query executed on the database of an AS/400 server by a PeaClient object.
|
146
|
+
|
147
|
+
class PeaUpdateResponse < PeaResponse
|
148
|
+
|
149
|
+
##
|
150
|
+
# Initialize a new instance of the PeaResponse class.
|
151
|
+
#
|
152
|
+
# Params:
|
153
|
+
# +has_succeeded+:: Boolean set to true if the query has correctly been executed. Set to true if the SQL state is 00000.
|
154
|
+
# +sql_message+:: SQL message return from the execution of the query.
|
155
|
+
# +sql_state+:: SQL state return from the execution of the query.
|
156
|
+
# +row_count+:: Represents the number of rows that have been updated by the query.
|
157
|
+
|
158
|
+
def initialize(has_succeeded, sql_message, sql_state, row_count)
|
159
|
+
super has_succeeded, sql_message, sql_state
|
160
|
+
|
161
|
+
@row_count = row_count
|
162
|
+
end
|
163
|
+
|
164
|
+
def row_count
|
165
|
+
@row_count
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
# Represents the concept of response in the case of a DELETE query executed on the database of an AS/400 server by a PeaClient object.
|
170
|
+
|
171
|
+
class PeaDeleteResponse < PeaResponse
|
172
|
+
|
173
|
+
##
|
174
|
+
# Initialize a new instance of the PeaResponse class.
|
175
|
+
#
|
176
|
+
# Params:
|
177
|
+
# +has_succeeded+:: Boolean set to true if the query has correctly been executed. Set to true if the SQL state is 00000.
|
178
|
+
# +sql_message+:: SQL message return from the execution of the query.
|
179
|
+
# +sql_state+:: SQL state return from the execution of the query.
|
180
|
+
# +row_count+:: Represents the number of rows that have been updated by the query.
|
181
|
+
|
182
|
+
def initialize(has_succeeded, sql_message, sql_state, row_count)
|
183
|
+
super has_succeeded, sql_message, sql_state
|
184
|
+
|
185
|
+
@row_count = row_count
|
186
|
+
end
|
187
|
+
|
188
|
+
def row_count
|
189
|
+
@row_count
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
# Represents the concept of response in the case of an INSERT query executed on the database of an AS/400 server by a PeaClient object.
|
194
|
+
|
195
|
+
class PeaInsertResponse < PeaResponse
|
196
|
+
|
197
|
+
##
|
198
|
+
# Initialize a new instance of the PeaResponse class.
|
199
|
+
#
|
200
|
+
# Params:
|
201
|
+
# +has_succeeded+:: Boolean set to true if the query has correctly been executed. Set to true if the SQL state is 00000.
|
202
|
+
# +sql_message+:: SQL message return from the execution of the query.
|
203
|
+
# +sql_state+:: SQL state return from the execution of the query.
|
204
|
+
# +row_count+:: Represents the number of rows that have been updated by the query.
|
205
|
+
|
206
|
+
def initialize(has_succeeded, sql_message, sql_state, row_count)
|
207
|
+
super has_succeeded, sql_message, sql_state
|
208
|
+
|
209
|
+
@row_count = row_count
|
210
|
+
end
|
211
|
+
|
212
|
+
def row_count
|
213
|
+
@row_count
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
217
|
+
# Represents the concept of response in the case of an OS/400 command executed on the database of an AS/400 server by a PeaClient object.
|
218
|
+
|
219
|
+
class PeaCommandResponse
|
220
|
+
|
221
|
+
##
|
222
|
+
# Initialize a new instance of the PeaCommandResponse class.
|
223
|
+
#
|
224
|
+
# Params:
|
225
|
+
# +has_succeeded+:: Boolean set to true if the command has correctly been executed meaning that no CPFxxxx was return. Still, description messages can be return along with CP*xxxx.
|
226
|
+
# +warnings+:: List of warnings that results form the command execution. Errors are of the form : CP*xxxx Description of the warning.
|
227
|
+
|
228
|
+
def initialize(warnings)
|
229
|
+
@warnings = warnings
|
230
|
+
end
|
231
|
+
|
232
|
+
def warnings
|
233
|
+
@warnings
|
234
|
+
end
|
235
|
+
end
|
236
|
+
|
237
|
+
# Represents the concept of metadata for a column of an SQL table on the AS/400 server.
|
238
|
+
class ColumnInfo
|
239
|
+
|
240
|
+
##
|
241
|
+
# Initialize a new instance of the ColumnInfo class.
|
242
|
+
#
|
243
|
+
# Params:
|
244
|
+
# +column_name+:: Name of the column.
|
245
|
+
# +ordinal_position+:: Ordinal position of the column.
|
246
|
+
# +data_type+:: DB2 Type of the data contain in the column.
|
247
|
+
# +length+:: Length of the data contain in the column.
|
248
|
+
# +numeric_scale+:: Scale of the data contain in the column if numeric type.
|
249
|
+
# +is_nullable+:: Y/N depending on the nullability of the field.
|
250
|
+
# +is_updatable+:: Y/N depending on the updaptability of the field.
|
251
|
+
# +numeric_precision+:: Precision of the data contain in the column if numeric type.
|
252
|
+
|
253
|
+
def initialize(column_name, ordinal_position, data_type, length, numeric_scale, is_nullable, is_updatable, numeric_precision)
|
254
|
+
@column_name = column_name
|
255
|
+
@ordinal_position = ordinal_position
|
256
|
+
@data_type = data_type
|
257
|
+
@length = length
|
258
|
+
@numeric_scale = numeric_scale
|
259
|
+
@numeric_precision = numeric_precision
|
260
|
+
@is_nullable = is_nullable
|
261
|
+
@is_updatable = is_updatable
|
262
|
+
@numeric_precision = numeric_precision
|
263
|
+
end
|
264
|
+
|
265
|
+
def column_name
|
266
|
+
@column_name
|
267
|
+
end
|
268
|
+
|
269
|
+
def ordinal_position
|
270
|
+
@ordinal_position
|
271
|
+
end
|
272
|
+
|
273
|
+
def data_type
|
274
|
+
@data_type
|
275
|
+
end
|
276
|
+
|
277
|
+
def length
|
278
|
+
@length
|
279
|
+
end
|
280
|
+
|
281
|
+
def numeric_scale
|
282
|
+
@numeric_scale
|
283
|
+
end
|
284
|
+
|
285
|
+
def numeric_precision
|
286
|
+
@numeric_precision
|
287
|
+
end
|
288
|
+
|
289
|
+
def is_nullable
|
290
|
+
@is_nullable
|
291
|
+
end
|
292
|
+
|
293
|
+
def is_updatable
|
294
|
+
@is_updatable
|
295
|
+
end
|
296
|
+
|
297
|
+
def numeric_precision
|
298
|
+
@numeric_precision
|
299
|
+
end
|
300
|
+
end
|
metadata
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: peasys-ruby
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.2
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- DIPS
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2024-07-15 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: Ruby client for IBM Db2 and peasys service
|
14
|
+
email: dips@dips400.com
|
15
|
+
executables: []
|
16
|
+
extensions: []
|
17
|
+
extra_rdoc_files: []
|
18
|
+
files:
|
19
|
+
- lib/pea_client.rb
|
20
|
+
- lib/pea_exception.rb
|
21
|
+
- lib/pea_response.rb
|
22
|
+
homepage: https://github.com/dips400.com/peasys-ruby
|
23
|
+
licenses:
|
24
|
+
- MIT
|
25
|
+
metadata: {}
|
26
|
+
post_install_message:
|
27
|
+
rdoc_options: []
|
28
|
+
require_paths:
|
29
|
+
- lib
|
30
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
31
|
+
requirements:
|
32
|
+
- - ">="
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: '0'
|
35
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - ">="
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: '0'
|
40
|
+
requirements: []
|
41
|
+
rubygems_version: 3.4.19
|
42
|
+
signing_key:
|
43
|
+
specification_version: 4
|
44
|
+
summary: Ruby client for IBM Db2 and peasys service
|
45
|
+
test_files: []
|