orasaurus 0.0.4 → 0.0.5

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.
@@ -0,0 +1,418 @@
1
+ /*<TOAD_FILE_CHUNK>*/
2
+ CREATE OR REPLACE PACKAGE pkg_notes
3
+ IS
4
+
5
+ logger t_logger := t_logger( 'DEBUG' );
6
+
7
+ TYPE note_rec
8
+ IS RECORD
9
+ ( notebook notebooks%ROWTYPE
10
+ , note notes%ROWTYPE
11
+ , tags pkg_array_utils.vc_arr
12
+ , comments pkg_note_comments.note_comments_tab );
13
+
14
+ TYPE notes_tab
15
+ IS TABLE OF note_rec
16
+ INDEX BY BINARY_INTEGER;
17
+
18
+ TYPE simple_notes_tab
19
+ IS TABLE OF notes%ROWTYPE
20
+ INDEX BY BINARY_INTEGER;
21
+
22
+ CURSOR cur_notes
23
+ ( the_notebook_id notes.notebook_id%TYPE )
24
+ RETURN notes%ROWTYPE;
25
+
26
+ CURSOR cur_notes_for_tags
27
+ ( the_notebook_id IN notebooks.id%TYPE
28
+ , the_tags vc_arr )
29
+ RETURN notes%ROWTYPE;
30
+
31
+ CURSOR cur_days_notes
32
+ ( the_notebook_id IN notebooks.id%TYPE
33
+ , the_date IN DATE )
34
+ RETURN notes%ROWTYPE;
35
+
36
+ CURSOR cur_find
37
+ ( the_notebook_id IN notebooks.id%TYPE
38
+ , the_search_text IN VARCHAR2 )
39
+ RETURN notes%ROWTYPE;
40
+
41
+ FUNCTION f_get_note
42
+ ( the_id IN notes.id%TYPE )
43
+ RETURN notes%ROWTYPE;
44
+
45
+ FUNCTION f_get_note_rec
46
+ ( the_id IN notes.id%TYPE )
47
+ RETURN note_rec;
48
+
49
+ FUNCTION f_get_notes_for_tags
50
+ ( the_notebook_id IN notebooks.id%TYPE
51
+ , the_tags IN vc_arr )
52
+ RETURN notes_tab;
53
+
54
+ FUNCTION f_get_notes
55
+ ( the_notebook_id notes.notebook_id%TYPE
56
+ , the_start_index INTEGER DEFAULT 1
57
+ , the_end_index INTEGER DEFAULT 25 )
58
+ RETURN notes_tab;
59
+
60
+ FUNCTION f_get_days_notes
61
+ ( the_notebook_id IN notebooks.id%TYPE
62
+ , the_date IN DATE )
63
+ RETURN notes_tab;
64
+
65
+ FUNCTION find
66
+ ( the_notebook_id IN notebooks.id%TYPE
67
+ , the_search_text IN VARCHAR2 )
68
+ RETURN notes_tab;
69
+
70
+ PROCEDURE p_save
71
+ ( the_note IN OUT notes%ROWTYPE );
72
+
73
+ PROCEDURE p_save
74
+ ( the_note_rec IN OUT note_rec );
75
+
76
+ PROCEDURE p_validate
77
+ ( the_note IN notes%ROWTYPE
78
+ , the_messages OUT pkg_array_utils.vc_arr );
79
+
80
+ PROCEDURE p_compose_note
81
+ ( notebook_id IN VARCHAR2
82
+ , note_title IN VARCHAR2
83
+ , note_note IN VARCHAR2
84
+ , note_tags IN VARCHAR2 DEFAULT NULL
85
+ , note_comments IN pkg_note_comments.note_comments_tab DEFAULT pkg_note_comments.empty_tab
86
+ , the_note OUT note_rec
87
+ , messages OUT pkg_array_utils.vc_arr );
88
+
89
+ PROCEDURE p_destroy
90
+ ( the_id IN notes.id%TYPE );
91
+
92
+ END;
93
+
94
+ /
95
+ /*<TOAD_FILE_CHUNK>*/
96
+
97
+ CREATE OR REPLACE PACKAGE BODY pkg_notes
98
+ IS
99
+
100
+ CURSOR cur_notes
101
+ ( the_notebook_id notes.notebook_id%TYPE )
102
+ RETURN notes%ROWTYPE
103
+ IS
104
+ SELECT *
105
+ FROM notes
106
+ WHERE notebook_id = the_notebook_id
107
+ ORDER BY updated_at DESC;
108
+
109
+ CURSOR cur_notes_for_tags
110
+ ( the_notebook_id IN notebooks.id%TYPE
111
+ , the_tags vc_arr )
112
+ RETURN notes%ROWTYPE
113
+ IS
114
+ SELECT DISTINCT n.*
115
+ FROM notes n
116
+ JOIN note_tags nt
117
+ ON n.id = nt.note_id
118
+ WHERE n.notebook_id = the_notebook_id
119
+ AND nt.tag IN ( SELECT * FROM TABLE( the_tags ) )
120
+ ORDER BY n.updated_at DESC;
121
+
122
+ CURSOR cur_days_notes
123
+ ( the_notebook_id IN notebooks.id%TYPE
124
+ , the_date IN DATE )
125
+ RETURN notes%ROWTYPE
126
+ IS
127
+ SELECT DISTINCT n.*
128
+ FROM notes n
129
+ LEFT OUTER JOIN note_comments c
130
+ ON n.id = c.note_id
131
+ WHERE notebook_id = the_notebook_id
132
+ AND ( ( TRUNC( n.created_at ) = TRUNC( the_date )
133
+ OR TRUNC( n.updated_at ) = TRUNC( the_date ) )
134
+ OR ( TRUNC( c.created_at ) = TRUNC( the_date )
135
+ OR TRUNC( c.updated_at ) = TRUNC( the_date ) ) )
136
+ ORDER BY n.updated_at DESC;
137
+
138
+ CURSOR cur_find
139
+ ( the_notebook_id IN notebooks.id%TYPE
140
+ , the_search_text IN VARCHAR2 )
141
+ RETURN notes%ROWTYPE
142
+ IS
143
+ SELECT DISTINCT n.*
144
+ FROM notes n
145
+ LEFT OUTER JOIN note_comments c
146
+ ON n.id = c.note_id
147
+ LEFT OUTER JOIN note_tags t
148
+ ON n.id = t.note_id
149
+ WHERE n.notebook_id = the_notebook_id
150
+ AND ( LOWER( n.title ) LIKE '%'||LOWER( the_search_text )||'%'
151
+ OR LOWER( n.note ) LIKE '%'||LOWER( the_search_text )||'%'
152
+ OR LOWER( c.text ) LIKE '%'||LOWER( the_search_text )||'%'
153
+ OR LOWER( t.tag ) LIKE '%'||LOWER( the_search_text )||'%' )
154
+ ORDER BY n.updated_at;
155
+
156
+ FUNCTION f_get_note
157
+ ( the_id IN notes.id%TYPE )
158
+ RETURN notes%ROWTYPE
159
+ IS
160
+ return_rec notes%ROWTYPE;
161
+ BEGIN
162
+
163
+ SELECT *
164
+ INTO return_rec
165
+ FROM notes
166
+ WHERE id = the_id;
167
+
168
+ RETURN return_rec;
169
+
170
+ END;
171
+
172
+ FUNCTION f_get_note_rec
173
+ ( the_id IN notes.id%TYPE )
174
+ RETURN note_rec
175
+ IS
176
+ return_rec note_rec;
177
+ BEGIN
178
+
179
+ SELECT *
180
+ INTO return_rec.note
181
+ FROM notes
182
+ WHERE id = the_id;
183
+
184
+ return_rec.notebook := pkg_notebooks.f_get( return_rec.note.notebook_id );
185
+
186
+ return_rec.tags := pkg_note_tags.f_get_tags( the_id );
187
+
188
+ return_rec.comments := pkg_note_comments.f_get_comments( the_id );
189
+
190
+ RETURN return_rec;
191
+
192
+ END;
193
+
194
+ FUNCTION f_get_notes_for_tags
195
+ ( the_notebook_id IN notebooks.id%TYPE
196
+ , the_tags IN vc_arr )
197
+ RETURN notes_tab
198
+ IS
199
+ return_tab notes_tab;
200
+ BEGIN
201
+
202
+ FOR i IN cur_notes_for_tags
203
+ ( the_notebook_id => the_notebook_id
204
+ , the_tags => the_tags )
205
+ LOOP
206
+ return_tab( return_tab.COUNT + 1 ) := f_get_note_rec( i.id );
207
+ END LOOP;
208
+
209
+ RETURN return_tab;
210
+
211
+ END;
212
+
213
+ FUNCTION f_get_notes
214
+ ( the_notebook_id notes.notebook_id%TYPE
215
+ , the_start_index INTEGER DEFAULT 1
216
+ , the_end_index INTEGER DEFAULT 25 )
217
+ RETURN notes_tab
218
+ IS
219
+ full_tab simple_notes_tab;
220
+ return_tab notes_tab;
221
+ final_end_index INTEGER := 0;
222
+ BEGIN
223
+
224
+ OPEN cur_notes( the_notebook_id => the_notebook_id );
225
+ FETCH cur_notes BULK COLLECT INTO full_tab;
226
+ CLOSE cur_notes;
227
+
228
+ IF full_tab.COUNT < the_end_index THEN
229
+ final_end_index := full_tab.COUNT;
230
+ ELSE
231
+ final_end_index := the_end_index;
232
+ END IF;
233
+
234
+ FOR i IN the_start_index..final_end_index LOOP
235
+ return_tab( return_tab.COUNT + 1 ) := f_get_note_rec( full_tab( i ).id );
236
+ END LOOP;
237
+
238
+ RETURN return_tab;
239
+
240
+ END;
241
+
242
+ FUNCTION f_get_days_notes
243
+ ( the_notebook_id IN notebooks.id%TYPE
244
+ , the_date IN DATE )
245
+ RETURN notes_tab
246
+ IS
247
+ temp_tab simple_notes_tab;
248
+ return_tab notes_tab;
249
+ BEGIN
250
+
251
+ OPEN cur_days_notes
252
+ ( the_notebook_id => the_notebook_id
253
+ , the_date => the_date );
254
+ FETCH cur_days_notes BULK COLLECT INTO temp_tab;
255
+ CLOSE cur_days_notes;
256
+
257
+ IF temp_tab.COUNT > 0 THEN
258
+ FOR i IN temp_tab.FIRST..temp_tab.LAST LOOP
259
+ return_tab( i ) := f_get_note_rec( temp_tab( i ).id );
260
+ END LOOP;
261
+ END IF;
262
+
263
+ RETURN return_tab;
264
+
265
+ END;
266
+
267
+ FUNCTION find
268
+ ( the_notebook_id IN notebooks.id%TYPE
269
+ , the_search_text IN VARCHAR2 )
270
+ RETURN notes_tab
271
+ IS
272
+ temp_tab simple_notes_tab;
273
+ return_tab notes_tab;
274
+ BEGIN
275
+
276
+ OPEN cur_find
277
+ ( the_notebook_id => the_notebook_id
278
+ , the_search_text => LOWER( the_search_text ) );
279
+ FETCH cur_find BULK COLLECT INTO temp_tab;
280
+ CLOSE cur_find;
281
+
282
+ IF temp_tab.COUNT > 0 THEN
283
+ FOR i IN temp_tab.FIRST..temp_tab.LAST LOOP
284
+ return_tab( i ) := f_get_note_rec( temp_tab( i ).id );
285
+ END LOOP;
286
+ END IF;
287
+
288
+ RETURN return_tab;
289
+
290
+ END;
291
+
292
+ PROCEDURE p_save
293
+ ( the_note IN OUT notes%ROWTYPE )
294
+ IS
295
+ BEGIN
296
+
297
+ IF the_note.id IS NULL THEN
298
+
299
+ SELECT notes_seq.NEXTVAL
300
+ INTO the_note.id
301
+ FROM DUAL;
302
+
303
+ the_note.created_at := SYSDATE;
304
+ the_note.created_by := USER;
305
+ the_note.updated_at := SYSDATE;
306
+ the_note.updated_by := USER;
307
+
308
+ INSERT INTO notes
309
+ ( id
310
+ , notebook_id
311
+ , title
312
+ , note
313
+ , created_at
314
+ , created_by
315
+ , updated_at
316
+ , updated_by )
317
+ VALUES
318
+ ( the_note.id
319
+ , the_note.notebook_id
320
+ , the_note.title
321
+ , the_note.note
322
+ , the_note.created_at
323
+ , the_note.created_by
324
+ , the_note.updated_at
325
+ , the_note.updated_by );
326
+
327
+ ELSE
328
+
329
+ the_note.updated_at := SYSDATE;
330
+ the_note.updated_by := USER;
331
+
332
+ UPDATE notes
333
+ SET title = the_note.title
334
+ , note = the_note.note
335
+ , notebook_id = the_note.notebook_id
336
+ , updated_at = the_note.updated_at
337
+ , updated_by = the_note.updated_by
338
+ WHERE id = the_note.id;
339
+
340
+ END IF;
341
+
342
+ END;
343
+
344
+ PROCEDURE p_save
345
+ ( the_note_rec IN OUT note_rec )
346
+ IS
347
+ test_note notes%ROWTYPE;
348
+ BEGIN
349
+
350
+ --SAVE THE NOTE
351
+ logger.p_debug( 'pkg_notes.p_save', 'save note' );
352
+ p_save( the_note => the_note_rec.note );
353
+ --SAVE THE TAGS
354
+ logger.p_debug( 'pkg_notes.p_save', 'save tags' );
355
+ pkg_note_tags.p_save_note_tags( the_note_rec.note.id, the_note_rec.tags );
356
+ --SAVE THE COMMENTS
357
+ logger.p_debug( 'pkg_notes.p_save', 'save comments' );
358
+ pkg_note_comments.p_save( the_note_rec.comments );
359
+
360
+ logger.p_debug( 'pkg_notes.p_save', 'done' );
361
+
362
+ END;
363
+
364
+ PROCEDURE p_validate
365
+ ( the_note IN notes%ROWTYPE
366
+ , the_messages OUT pkg_array_utils.vc_arr )
367
+ IS
368
+ BEGIN
369
+
370
+ IF the_note.note IS NULL THEN
371
+ the_messages( the_messages.COUNT + 1 ) := 'The note can not be left blank.';
372
+ END IF;
373
+
374
+ END;
375
+
376
+ PROCEDURE p_compose_note
377
+ ( notebook_id IN VARCHAR2
378
+ , note_title IN VARCHAR2
379
+ , note_note IN VARCHAR2
380
+ , note_tags IN VARCHAR2 DEFAULT NULL
381
+ , note_comments IN pkg_note_comments.note_comments_tab DEFAULT pkg_note_comments.empty_tab
382
+ , the_note OUT note_rec
383
+ , messages OUT pkg_array_utils.vc_arr )
384
+ IS
385
+ BEGIN
386
+
387
+ the_note.notebook := pkg_notebooks.f_get( the_id => notebook_id );
388
+
389
+ the_note.note.notebook_id := TRIM( notebook_id );
390
+ the_note.note.title := TRIM( note_title );
391
+ the_note.note.note := TRIM( note_note );
392
+
393
+ BEGIN
394
+ the_note.tags := pkg_array_utils.f_undelimit_me( note_tags, ',' );
395
+ the_note.tags := pkg_array_utils.f_trim_elements( the_note.tags );
396
+ EXCEPTION
397
+ WHEN OTHERS THEN
398
+ logger.p_error( 'note_create', 'Processing tags: '||SQLERRM );
399
+ messages( messages.COUNT + 1 ) := 'There has been a problem processing the tags. Try using a comma to separate the tags.';
400
+ END;
401
+
402
+ the_note.comments := note_comments;
403
+
404
+ p_validate( the_note => the_note.note, the_messages => messages );
405
+
406
+ END;
407
+
408
+ PROCEDURE p_destroy
409
+ ( the_id IN notes.id%TYPE )
410
+ IS
411
+ BEGIN
412
+
413
+ DELETE FROM notes WHERE id = the_id;
414
+
415
+ END;
416
+
417
+ END;
418
+ /
@@ -0,0 +1 @@
1
+ CREATE SEQUENCE note_comments_seq START WITH 1 INCREMENT BY 1;
@@ -0,0 +1 @@
1
+ CREATE SEQUENCE note_tags_seq START WITH 1 INCREMENT BY 1;
@@ -0,0 +1 @@
1
+ CREATE SEQUENCE notebooks_seq START WITH 1 INCREMENT BY 1;
@@ -0,0 +1 @@
1
+ CREATE SEQUENCE notes_seq START WITH 1 INCREMENT BY 1;
@@ -0,0 +1,27 @@
1
+ CREATE TABLE NOTE_COMMENTS
2
+ (
3
+ ID NUMBER,
4
+ NOTE_ID NUMBER NOT NULL,
5
+ TEXT VARCHAR2(4000 BYTE) NOT NULL,
6
+ CREATED_AT DATE NOT NULL,
7
+ CREATED_BY VARCHAR2(40 BYTE) NOT NULL,
8
+ UPDATED_AT DATE NOT NULL,
9
+ UPDATED_BY VARCHAR2( 40 BYTE) NOT NULL,
10
+ CONSTRAINT NOTE_COMMENTS_PK
11
+ PRIMARY KEY
12
+ (ID)
13
+ USING INDEX
14
+ TABLESPACE LARGE_TABLES,
15
+ CONSTRAINT NOTE_COMMENTS_NOTE_FK
16
+ FOREIGN KEY (NOTE_ID) REFERENCES NOTES(ID) ON DELETE CASCADE
17
+ )
18
+ TABLESPACE LARGE_TABLES
19
+ LOGGING
20
+ NOCOMPRESS
21
+ NOCACHE
22
+ NOPARALLEL
23
+ MONITORING;
24
+
25
+
26
+
27
+
@@ -0,0 +1,25 @@
1
+ CREATE TABLE NOTE_TAGS
2
+ (
3
+ ID NUMBER,
4
+ NOTE_ID NUMBER NOT NULL,
5
+ TAG VARCHAR2(255 BYTE) NOT NULL,
6
+ CONSTRAINT NOTES_TAGS_PK
7
+ PRIMARY KEY
8
+ (ID)
9
+ USING INDEX
10
+ TABLESPACE LARGE_TABLES,
11
+ CONSTRAINT FK_NOTE_TAGS_NOTE
12
+ FOREIGN KEY (NOTE_ID)
13
+ REFERENCES NOTES (ID)
14
+ ON DELETE CASCADE
15
+ )
16
+ TABLESPACE LARGE_TABLES
17
+ LOGGING
18
+ NOCOMPRESS
19
+ NOCACHE
20
+ NOPARALLEL
21
+ MONITORING;
22
+
23
+
24
+
25
+
@@ -0,0 +1,26 @@
1
+ CREATE TABLE NOTEBOOKS
2
+ (
3
+ ID NUMBER,
4
+ TITLE VARCHAR2(255 BYTE) NOT NULL,
5
+ CONSTRAINT NOTEBOOKS_PK
6
+ PRIMARY KEY
7
+ (ID)
8
+ USING INDEX
9
+ TABLESPACE LARGE_TABLES,
10
+ CONSTRAINT UNIQ_NOTEBOOK_TITLE
11
+ UNIQUE (TITLE)
12
+ USING INDEX
13
+ TABLESPACE LARGE_TABLES
14
+ )
15
+ TABLESPACE LARGE_TABLES
16
+ LOGGING
17
+ NOCOMPRESS
18
+ NOCACHE
19
+ NOPARALLEL
20
+ MONITORING;
21
+
22
+
23
+
24
+
25
+
26
+
@@ -0,0 +1,30 @@
1
+ CREATE TABLE NOTES
2
+ (
3
+ ID NUMBER,
4
+ NOTEBOOK_ID NUMBER,
5
+ TITLE VARCHAR2(250 BYTE) NOT NULL,
6
+ NOTE VARCHAR2(4000 BYTE) NOT NULL,
7
+ CREATED_AT DATE NOT NULL,
8
+ CREATED_BY VARCHAR2( 40 ) NOT NULL,
9
+ UPDATED_AT DATE NOT NULL,
10
+ UPDATED_BY VARCHAR2( 40 ) NOT NULL,
11
+ CONSTRAINT NOTES_PK
12
+ PRIMARY KEY
13
+ (ID)
14
+ USING INDEX
15
+ TABLESPACE LARGE_TABLES,
16
+ CONSTRAINT FK_NOTES_NOTEBOOK_ID
17
+ FOREIGN KEY
18
+ (NOTEBOOK_ID) REFERENCES NOTEBOOKS(ID)
19
+ ON DELETE CASCADE
20
+ )
21
+ TABLESPACE LARGE_TABLES
22
+ LOGGING
23
+ NOCOMPRESS
24
+ NOCACHE
25
+ NOPARALLEL
26
+ MONITORING;
27
+
28
+
29
+
30
+
@@ -0,0 +1,75 @@
1
+ require "oci8"
2
+ require "highline/import"
3
+ require "orasaurus"
4
+
5
+ $db_name = ""
6
+ $db_user = ""
7
+ $db_user_password = ""
8
+
9
+ def process_db_connect_params
10
+
11
+ if ENV['db_user'].nil? then
12
+ $db_user = ask("Database User: ") { |q| q.echo = true }
13
+ else
14
+ $db_user = ENV['db_user']
15
+ end
16
+
17
+ if ENV['db_user_password'].nil? then
18
+ $db_user_password = ask("Database User Password: ") { |q| q.echo = "*" }
19
+ else
20
+ $db_user_password = ENV['db_user_password']
21
+ end
22
+
23
+ if ENV['db_name'].nil? then
24
+ $db_name = ask("Database Instance: ") { |q| q.echo = true }
25
+ else
26
+ $db_name = ENV['db_name']
27
+ end
28
+
29
+ if not $db_user.nil? and not $db_user_password.nil? and not $db_name.nil? then
30
+ return true
31
+ else
32
+ puts "INVALID DATABASE CONNECTION PARAMETERS"
33
+ end
34
+
35
+ end
36
+
37
+ def sqlplus_connect_string
38
+ return $db_user + "/" + $db_user_password + "@" + $db_name
39
+ end
40
+
41
+ desc "Test database connection"
42
+ task :test_connection do
43
+ if not process_db_connect_params then
44
+ exit
45
+ puts "test failed"
46
+ else
47
+ puts "valid parameters"
48
+ end
49
+ puts "Starting database connection test"
50
+ begin
51
+ conn = OCI8.new( $db_user, $db_user_password, $db_name )
52
+ conn.logoff
53
+ puts "Connection successful"
54
+ rescue
55
+ puts $!
56
+ puts "Connection failed"
57
+ end
58
+ end
59
+
60
+ desc "Rebuild all build and teardown scripts"
61
+ task :rebuild_build_scripts do
62
+ if not process_db_connect_params then
63
+ exit
64
+ end
65
+
66
+ s = Orasaurus::ScriptBuilder.new( '.' )
67
+ puts "building simple build scripts"
68
+ s.build_all_scripts( 'build.sql', 'teardown.sql' )
69
+
70
+ #puts "re-doing table build scripts for proper order"
71
+ #t = Orasaurus::TableScriptBuilder.new( $db_user, $db_user_password, $db_name, './Tables/' )
72
+ #puts 'build_tables has finished'
73
+
74
+ puts 'done'
75
+ end
@@ -0,0 +1,3 @@
1
+ CREATE USER "ben" IDENTIFIED BY "FRANKLIN";
2
+ GRANT CONNECT TO "BEN";
3
+ GRANT DBA TO "BEN";
data/spec/spec_helper.rb CHANGED
@@ -1,8 +1,26 @@
1
1
  require 'rubygems'
2
2
  require 'bundler/setup'
3
3
 
4
- require 'orasaurus'
4
+ require File.dirname(__FILE__) + '/../lib/orasaurus.rb'
5
5
 
6
6
  RSpec.configure do |config|
7
- # some (optional) config here
7
+ # some (optional) config heredef capture(stream)
8
+ #lifted from thor's specs
9
+ def capture(stream)
10
+ begin
11
+ stream = stream.to_s
12
+ eval "$#{stream} = StringIO.new"
13
+ yield
14
+ result = eval("$#{stream}").string
15
+ ensure
16
+ eval("$#{stream} = #{stream.upcase}")
17
+ end
18
+
19
+ result
20
+ end
21
+ end
22
+
23
+ def cleanup
24
+ puts "deleting all test output files"
25
+ Dir['**/**'].grep(/build\.sql|teardown\.sql/).each { |t| File.delete(t) }
8
26
  end