Showing 88 changed files with 12754 additions and 0 deletions
+1
Makefile.PL
... ...
@@ -19,4 +19,5 @@ WriteMakefile(
19 19
     },
20 20
     dist                => { COMPRESS => 'gzip -9f', SUFFIX => 'gz', },
21 21
     clean               => { FILES => 'DBIx-Custom-*' },
22
+    test => {TESTS => 't/*.t t/next/*.t'}
22 23
 );
+876
Makefile.old
... ...
@@ -0,0 +1,876 @@
1
+# This Makefile is for the DBIx::Custom extension to perl.
2
+#
3
+# It was generated automatically by MakeMaker version
4
+# 6.56 (Revision: 65600) from the contents of
5
+# Makefile.PL. Don't edit this file, edit Makefile.PL instead.
6
+#
7
+#       ANY CHANGES MADE HERE WILL BE LOST!
8
+#
9
+#   MakeMaker ARGV: ()
10
+#
11
+
12
+#   MakeMaker Parameters:
13
+
14
+#     ABSTRACT_FROM => q[lib/DBIx/Custom/Next.pm]
15
+#     AUTHOR => q[Yuki Kimoto <kimoto.yuki@gmail.com>]
16
+#     BUILD_REQUIRES => {  }
17
+#     LICENSE => q[perl]
18
+#     NAME => q[DBIx::Custom]
19
+#     PL_FILES => {  }
20
+#     PREREQ_PM => { Test::More=>q[0], Object::Simple=>q[3.0621], DBD::SQLite=>q[1.25], DBI=>q[1.605] }
21
+#     VERSION_FROM => q[lib/DBIx/Custom/Next.pm]
22
+#     clean => { FILES=>q[DBIx-Custom-*] }
23
+#     dist => { COMPRESS=>q[gzip -9f], SUFFIX=>q[gz] }
24
+#     test => { TESTS=>q[t/*.t t/next/*.t] }
25
+
26
+# --- MakeMaker post_initialize section:
27
+
28
+
29
+# --- MakeMaker const_config section:
30
+
31
+# These definitions are from config.sh (via /usr/lib/perl5/5.8.8/i386-linux-thread-multi/Config.pm).
32
+# They may have been overridden via Makefile.PL or on the command line.
33
+AR = ar
34
+CC = gcc
35
+CCCDLFLAGS = -fPIC
36
+CCDLFLAGS = -Wl,-E -Wl,-rpath,/usr/lib/perl5/5.8.8/i386-linux-thread-multi/CORE
37
+DLEXT = so
38
+DLSRC = dl_dlopen.xs
39
+EXE_EXT = 
40
+FULL_AR = /usr/bin/ar
41
+LD = gcc
42
+LDDLFLAGS = -shared -O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4 -m32 -march=i386 -mtune=generic -fasynchronous-unwind-tables -L/usr/local/lib
43
+LDFLAGS =  -L/usr/local/lib
44
+LIBC = /lib/libc-2.5.so
45
+LIB_EXT = .a
46
+OBJ_EXT = .o
47
+OSNAME = linux
48
+OSVERS = 2.6.18-53.el5
49
+RANLIB = :
50
+SITELIBEXP = /usr/lib/perl5/site_perl/5.8.8
51
+SITEARCHEXP = /usr/lib/perl5/site_perl/5.8.8/i386-linux-thread-multi
52
+SO = so
53
+VENDORARCHEXP = /usr/lib/perl5/vendor_perl/5.8.8/i386-linux-thread-multi
54
+VENDORLIBEXP = /usr/lib/perl5/vendor_perl/5.8.8
55
+
56
+
57
+# --- MakeMaker constants section:
58
+AR_STATIC_ARGS = cr
59
+DIRFILESEP = /
60
+DFSEP = $(DIRFILESEP)
61
+NAME = DBIx::Custom
62
+NAME_SYM = DBIx_Custom
63
+VERSION = 0.20_01
64
+VERSION_MACRO = VERSION
65
+VERSION_SYM = 0_20_01
66
+DEFINE_VERSION = -D$(VERSION_MACRO)=\"$(VERSION)\"
67
+XS_VERSION = 0.20_01
68
+XS_VERSION_MACRO = XS_VERSION
69
+XS_DEFINE_VERSION = -D$(XS_VERSION_MACRO)=\"$(XS_VERSION)\"
70
+INST_ARCHLIB = blib/arch
71
+INST_SCRIPT = blib/script
72
+INST_BIN = blib/bin
73
+INST_LIB = blib/lib
74
+INST_MAN1DIR = blib/man1
75
+INST_MAN3DIR = blib/man3
76
+MAN1EXT = 1
77
+MAN3EXT = 3pm
78
+INSTALLDIRS = site
79
+DESTDIR = 
80
+PREFIX = $(SITEPREFIX)
81
+PERLPREFIX = /usr
82
+SITEPREFIX = /usr
83
+VENDORPREFIX = /usr
84
+INSTALLPRIVLIB = /usr/lib/perl5/5.8.8
85
+DESTINSTALLPRIVLIB = $(DESTDIR)$(INSTALLPRIVLIB)
86
+INSTALLSITELIB = /usr/lib/perl5/site_perl/5.8.8
87
+DESTINSTALLSITELIB = $(DESTDIR)$(INSTALLSITELIB)
88
+INSTALLVENDORLIB = /usr/lib/perl5/vendor_perl/5.8.8
89
+DESTINSTALLVENDORLIB = $(DESTDIR)$(INSTALLVENDORLIB)
90
+INSTALLARCHLIB = /usr/lib/perl5/5.8.8/i386-linux-thread-multi
91
+DESTINSTALLARCHLIB = $(DESTDIR)$(INSTALLARCHLIB)
92
+INSTALLSITEARCH = /usr/lib/perl5/site_perl/5.8.8/i386-linux-thread-multi
93
+DESTINSTALLSITEARCH = $(DESTDIR)$(INSTALLSITEARCH)
94
+INSTALLVENDORARCH = /usr/lib/perl5/vendor_perl/5.8.8/i386-linux-thread-multi
95
+DESTINSTALLVENDORARCH = $(DESTDIR)$(INSTALLVENDORARCH)
96
+INSTALLBIN = /usr/bin
97
+DESTINSTALLBIN = $(DESTDIR)$(INSTALLBIN)
98
+INSTALLSITEBIN = /usr/bin
99
+DESTINSTALLSITEBIN = $(DESTDIR)$(INSTALLSITEBIN)
100
+INSTALLVENDORBIN = /usr/bin
101
+DESTINSTALLVENDORBIN = $(DESTDIR)$(INSTALLVENDORBIN)
102
+INSTALLSCRIPT = /usr/bin
103
+DESTINSTALLSCRIPT = $(DESTDIR)$(INSTALLSCRIPT)
104
+INSTALLSITESCRIPT = /usr/bin
105
+DESTINSTALLSITESCRIPT = $(DESTDIR)$(INSTALLSITESCRIPT)
106
+INSTALLVENDORSCRIPT = /usr/bin
107
+DESTINSTALLVENDORSCRIPT = $(DESTDIR)$(INSTALLVENDORSCRIPT)
108
+INSTALLMAN1DIR = /usr/share/man/man1
109
+DESTINSTALLMAN1DIR = $(DESTDIR)$(INSTALLMAN1DIR)
110
+INSTALLSITEMAN1DIR = /usr/share/man/man1
111
+DESTINSTALLSITEMAN1DIR = $(DESTDIR)$(INSTALLSITEMAN1DIR)
112
+INSTALLVENDORMAN1DIR = /usr/share/man/man1
113
+DESTINSTALLVENDORMAN1DIR = $(DESTDIR)$(INSTALLVENDORMAN1DIR)
114
+INSTALLMAN3DIR = /usr/share/man/man3
115
+DESTINSTALLMAN3DIR = $(DESTDIR)$(INSTALLMAN3DIR)
116
+INSTALLSITEMAN3DIR = /usr/share/man/man3
117
+DESTINSTALLSITEMAN3DIR = $(DESTDIR)$(INSTALLSITEMAN3DIR)
118
+INSTALLVENDORMAN3DIR = /usr/share/man/man3
119
+DESTINSTALLVENDORMAN3DIR = $(DESTDIR)$(INSTALLVENDORMAN3DIR)
120
+PERL_LIB = /usr/lib/perl5/5.8.8
121
+PERL_ARCHLIB = /usr/lib/perl5/5.8.8/i386-linux-thread-multi
122
+LIBPERL_A = libperl.a
123
+FIRST_MAKEFILE = Makefile
124
+MAKEFILE_OLD = Makefile.old
125
+MAKE_APERL_FILE = Makefile.aperl
126
+PERLMAINCC = $(CC)
127
+PERL_INC = /usr/lib/perl5/5.8.8/i386-linux-thread-multi/CORE
128
+PERL = /usr/bin/perl
129
+FULLPERL = /usr/bin/perl
130
+ABSPERL = $(PERL)
131
+PERLRUN = $(PERL)
132
+FULLPERLRUN = $(FULLPERL)
133
+ABSPERLRUN = $(ABSPERL)
134
+PERLRUNINST = $(PERLRUN) "-I$(INST_ARCHLIB)" "-I$(INST_LIB)"
135
+FULLPERLRUNINST = $(FULLPERLRUN) "-I$(INST_ARCHLIB)" "-I$(INST_LIB)"
136
+ABSPERLRUNINST = $(ABSPERLRUN) "-I$(INST_ARCHLIB)" "-I$(INST_LIB)"
137
+PERL_CORE = 0
138
+PERM_DIR = 755
139
+PERM_RW = 644
140
+PERM_RWX = 755
141
+
142
+MAKEMAKER   = /home/kimoto/perl5/lib/perl5/ExtUtils/MakeMaker.pm
143
+MM_VERSION  = 6.56
144
+MM_REVISION = 65600
145
+
146
+# FULLEXT = Pathname for extension directory (eg Foo/Bar/Oracle).
147
+# BASEEXT = Basename part of FULLEXT. May be just equal FULLEXT. (eg Oracle)
148
+# PARENT_NAME = NAME without BASEEXT and no trailing :: (eg Foo::Bar)
149
+# DLBASE  = Basename part of dynamic library. May be just equal BASEEXT.
150
+MAKE = make
151
+FULLEXT = DBIx/Custom
152
+BASEEXT = Custom
153
+PARENT_NAME = DBIx
154
+DLBASE = $(BASEEXT)
155
+VERSION_FROM = lib/DBIx/Custom/Next.pm
156
+OBJECT = 
157
+LDFROM = $(OBJECT)
158
+LINKTYPE = dynamic
159
+BOOTDEP = 
160
+
161
+# Handy lists of source code files:
162
+XS_FILES = 
163
+C_FILES  = 
164
+O_FILES  = 
165
+H_FILES  = 
166
+MAN1PODS = 
167
+MAN3PODS = lib/DBIx/Custom/Next.pm \
168
+	lib/DBIx/Custom/Next/Mapper.pm \
169
+	lib/DBIx/Custom/Next/Model.pm \
170
+	lib/DBIx/Custom/Next/NotExists.pm \
171
+	lib/DBIx/Custom/Next/Order.pm \
172
+	lib/DBIx/Custom/Next/Result.pm \
173
+	lib/DBIx/Custom/Next/Util.pm \
174
+	lib/DBIx/Custom/Next/Where.pm
175
+
176
+# Where is the Config information that we are using/depend on
177
+CONFIGDEP = $(PERL_ARCHLIB)$(DFSEP)Config.pm $(PERL_INC)$(DFSEP)config.h
178
+
179
+# Where to build things
180
+INST_LIBDIR      = $(INST_LIB)/DBIx
181
+INST_ARCHLIBDIR  = $(INST_ARCHLIB)/DBIx
182
+
183
+INST_AUTODIR     = $(INST_LIB)/auto/$(FULLEXT)
184
+INST_ARCHAUTODIR = $(INST_ARCHLIB)/auto/$(FULLEXT)
185
+
186
+INST_STATIC      = 
187
+INST_DYNAMIC     = 
188
+INST_BOOT        = 
189
+
190
+# Extra linker info
191
+EXPORT_LIST        = 
192
+PERL_ARCHIVE       = 
193
+PERL_ARCHIVE_AFTER = 
194
+
195
+
196
+TO_INST_PM = lib/DBIx/Custom/Next.pm \
197
+	lib/DBIx/Custom/Next/Mapper.pm \
198
+	lib/DBIx/Custom/Next/Model.pm \
199
+	lib/DBIx/Custom/Next/NotExists.pm \
200
+	lib/DBIx/Custom/Next/Order.pm \
201
+	lib/DBIx/Custom/Next/Result.pm \
202
+	lib/DBIx/Custom/Next/Util.pm \
203
+	lib/DBIx/Custom/Next/Where.pm \
204
+	next.pl
205
+
206
+PM_TO_BLIB = lib/DBIx/Custom/Next/Util.pm \
207
+	blib/lib/DBIx/Custom/Next/Util.pm \
208
+	lib/DBIx/Custom/Next/Model.pm \
209
+	blib/lib/DBIx/Custom/Next/Model.pm \
210
+	lib/DBIx/Custom/Next/Order.pm \
211
+	blib/lib/DBIx/Custom/Next/Order.pm \
212
+	lib/DBIx/Custom/Next/NotExists.pm \
213
+	blib/lib/DBIx/Custom/Next/NotExists.pm \
214
+	lib/DBIx/Custom/Next/Mapper.pm \
215
+	blib/lib/DBIx/Custom/Next/Mapper.pm \
216
+	lib/DBIx/Custom/Next/Where.pm \
217
+	blib/lib/DBIx/Custom/Next/Where.pm \
218
+	lib/DBIx/Custom/Next.pm \
219
+	blib/lib/DBIx/Custom/Next.pm \
220
+	next.pl \
221
+	$(INST_LIB)/DBIx/next.pl \
222
+	lib/DBIx/Custom/Next/Result.pm \
223
+	blib/lib/DBIx/Custom/Next/Result.pm
224
+
225
+
226
+# --- MakeMaker platform_constants section:
227
+MM_Unix_VERSION = 6.56
228
+PERL_MALLOC_DEF = -DPERL_EXTMALLOC_DEF -Dmalloc=Perl_malloc -Dfree=Perl_mfree -Drealloc=Perl_realloc -Dcalloc=Perl_calloc
229
+
230
+
231
+# --- MakeMaker tool_autosplit section:
232
+# Usage: $(AUTOSPLITFILE) FileToSplit AutoDirToSplitInto
233
+AUTOSPLITFILE = $(ABSPERLRUN)  -e 'use AutoSplit;  autosplit($$ARGV[0], $$ARGV[1], 0, 1, 1)' --
234
+
235
+
236
+
237
+# --- MakeMaker tool_xsubpp section:
238
+
239
+
240
+# --- MakeMaker tools_other section:
241
+SHELL = /bin/sh
242
+CHMOD = chmod
243
+CP = cp
244
+MV = mv
245
+NOOP = $(TRUE)
246
+NOECHO = @
247
+RM_F = rm -f
248
+RM_RF = rm -rf
249
+TEST_F = test -f
250
+TOUCH = touch
251
+UMASK_NULL = umask 0
252
+DEV_NULL = > /dev/null 2>&1
253
+MKPATH = $(ABSPERLRUN) -MExtUtils::Command -e 'mkpath' --
254
+EQUALIZE_TIMESTAMP = $(ABSPERLRUN) -MExtUtils::Command -e 'eqtime' --
255
+FALSE = false
256
+TRUE = true
257
+ECHO = echo
258
+ECHO_N = echo -n
259
+UNINST = 0
260
+VERBINST = 0
261
+MOD_INSTALL = $(ABSPERLRUN) -MExtUtils::Install -e 'install([ from_to => {@ARGV}, verbose => '\''$(VERBINST)'\'', uninstall_shadows => '\''$(UNINST)'\'', dir_mode => '\''$(PERM_DIR)'\'' ]);' --
262
+DOC_INSTALL = $(ABSPERLRUN) -MExtUtils::Command::MM -e 'perllocal_install' --
263
+UNINSTALL = $(ABSPERLRUN) -MExtUtils::Command::MM -e 'uninstall' --
264
+WARN_IF_OLD_PACKLIST = $(ABSPERLRUN) -MExtUtils::Command::MM -e 'warn_if_old_packlist' --
265
+MACROSTART = 
266
+MACROEND = 
267
+USEMAKEFILE = -f
268
+FIXIN = $(ABSPERLRUN) -MExtUtils::MY -e 'MY->fixin(shift)' --
269
+
270
+
271
+# --- MakeMaker makemakerdflt section:
272
+makemakerdflt : all
273
+	$(NOECHO) $(NOOP)
274
+
275
+
276
+# --- MakeMaker dist section:
277
+TAR = tar
278
+TARFLAGS = cvf
279
+ZIP = zip
280
+ZIPFLAGS = -r
281
+COMPRESS = gzip -9f
282
+SUFFIX = gz
283
+SHAR = shar
284
+PREOP = $(NOECHO) $(NOOP)
285
+POSTOP = $(NOECHO) $(NOOP)
286
+TO_UNIX = $(NOECHO) $(NOOP)
287
+CI = ci -u
288
+RCS_LABEL = rcs -Nv$(VERSION_SYM): -q
289
+DIST_CP = best
290
+DIST_DEFAULT = tardist
291
+DISTNAME = DBIx-Custom
292
+DISTVNAME = DBIx-Custom-0.20_01
293
+
294
+
295
+# --- MakeMaker macro section:
296
+
297
+
298
+# --- MakeMaker depend section:
299
+
300
+
301
+# --- MakeMaker cflags section:
302
+
303
+
304
+# --- MakeMaker const_loadlibs section:
305
+
306
+
307
+# --- MakeMaker const_cccmd section:
308
+
309
+
310
+# --- MakeMaker post_constants section:
311
+
312
+
313
+# --- MakeMaker pasthru section:
314
+
315
+PASTHRU = LIBPERL_A="$(LIBPERL_A)"\
316
+	LINKTYPE="$(LINKTYPE)"\
317
+	PREFIX="$(PREFIX)"
318
+
319
+
320
+# --- MakeMaker special_targets section:
321
+.SUFFIXES : .xs .c .C .cpp .i .s .cxx .cc $(OBJ_EXT)
322
+
323
+.PHONY: all config static dynamic test linkext manifest blibdirs clean realclean disttest distdir
324
+
325
+
326
+
327
+# --- MakeMaker c_o section:
328
+
329
+
330
+# --- MakeMaker xs_c section:
331
+
332
+
333
+# --- MakeMaker xs_o section:
334
+
335
+
336
+# --- MakeMaker top_targets section:
337
+all :: pure_all manifypods
338
+	$(NOECHO) $(NOOP)
339
+
340
+
341
+pure_all :: config pm_to_blib subdirs linkext
342
+	$(NOECHO) $(NOOP)
343
+
344
+subdirs :: $(MYEXTLIB)
345
+	$(NOECHO) $(NOOP)
346
+
347
+config :: $(FIRST_MAKEFILE) blibdirs
348
+	$(NOECHO) $(NOOP)
349
+
350
+help :
351
+	perldoc ExtUtils::MakeMaker
352
+
353
+
354
+# --- MakeMaker blibdirs section:
355
+blibdirs : $(INST_LIBDIR)$(DFSEP).exists $(INST_ARCHLIB)$(DFSEP).exists $(INST_AUTODIR)$(DFSEP).exists $(INST_ARCHAUTODIR)$(DFSEP).exists $(INST_BIN)$(DFSEP).exists $(INST_SCRIPT)$(DFSEP).exists $(INST_MAN1DIR)$(DFSEP).exists $(INST_MAN3DIR)$(DFSEP).exists
356
+	$(NOECHO) $(NOOP)
357
+
358
+# Backwards compat with 6.18 through 6.25
359
+blibdirs.ts : blibdirs
360
+	$(NOECHO) $(NOOP)
361
+
362
+$(INST_LIBDIR)$(DFSEP).exists :: Makefile.PL
363
+	$(NOECHO) $(MKPATH) $(INST_LIBDIR)
364
+	$(NOECHO) $(CHMOD) $(PERM_DIR) $(INST_LIBDIR)
365
+	$(NOECHO) $(TOUCH) $(INST_LIBDIR)$(DFSEP).exists
366
+
367
+$(INST_ARCHLIB)$(DFSEP).exists :: Makefile.PL
368
+	$(NOECHO) $(MKPATH) $(INST_ARCHLIB)
369
+	$(NOECHO) $(CHMOD) $(PERM_DIR) $(INST_ARCHLIB)
370
+	$(NOECHO) $(TOUCH) $(INST_ARCHLIB)$(DFSEP).exists
371
+
372
+$(INST_AUTODIR)$(DFSEP).exists :: Makefile.PL
373
+	$(NOECHO) $(MKPATH) $(INST_AUTODIR)
374
+	$(NOECHO) $(CHMOD) $(PERM_DIR) $(INST_AUTODIR)
375
+	$(NOECHO) $(TOUCH) $(INST_AUTODIR)$(DFSEP).exists
376
+
377
+$(INST_ARCHAUTODIR)$(DFSEP).exists :: Makefile.PL
378
+	$(NOECHO) $(MKPATH) $(INST_ARCHAUTODIR)
379
+	$(NOECHO) $(CHMOD) $(PERM_DIR) $(INST_ARCHAUTODIR)
380
+	$(NOECHO) $(TOUCH) $(INST_ARCHAUTODIR)$(DFSEP).exists
381
+
382
+$(INST_BIN)$(DFSEP).exists :: Makefile.PL
383
+	$(NOECHO) $(MKPATH) $(INST_BIN)
384
+	$(NOECHO) $(CHMOD) $(PERM_DIR) $(INST_BIN)
385
+	$(NOECHO) $(TOUCH) $(INST_BIN)$(DFSEP).exists
386
+
387
+$(INST_SCRIPT)$(DFSEP).exists :: Makefile.PL
388
+	$(NOECHO) $(MKPATH) $(INST_SCRIPT)
389
+	$(NOECHO) $(CHMOD) $(PERM_DIR) $(INST_SCRIPT)
390
+	$(NOECHO) $(TOUCH) $(INST_SCRIPT)$(DFSEP).exists
391
+
392
+$(INST_MAN1DIR)$(DFSEP).exists :: Makefile.PL
393
+	$(NOECHO) $(MKPATH) $(INST_MAN1DIR)
394
+	$(NOECHO) $(CHMOD) $(PERM_DIR) $(INST_MAN1DIR)
395
+	$(NOECHO) $(TOUCH) $(INST_MAN1DIR)$(DFSEP).exists
396
+
397
+$(INST_MAN3DIR)$(DFSEP).exists :: Makefile.PL
398
+	$(NOECHO) $(MKPATH) $(INST_MAN3DIR)
399
+	$(NOECHO) $(CHMOD) $(PERM_DIR) $(INST_MAN3DIR)
400
+	$(NOECHO) $(TOUCH) $(INST_MAN3DIR)$(DFSEP).exists
401
+
402
+
403
+
404
+# --- MakeMaker linkext section:
405
+
406
+linkext :: $(LINKTYPE)
407
+	$(NOECHO) $(NOOP)
408
+
409
+
410
+# --- MakeMaker dlsyms section:
411
+
412
+
413
+# --- MakeMaker dynamic section:
414
+
415
+dynamic :: $(FIRST_MAKEFILE) $(INST_DYNAMIC) $(INST_BOOT)
416
+	$(NOECHO) $(NOOP)
417
+
418
+
419
+# --- MakeMaker dynamic_bs section:
420
+
421
+BOOTSTRAP =
422
+
423
+
424
+# --- MakeMaker dynamic_lib section:
425
+
426
+
427
+# --- MakeMaker static section:
428
+
429
+## $(INST_PM) has been moved to the all: target.
430
+## It remains here for awhile to allow for old usage: "make static"
431
+static :: $(FIRST_MAKEFILE) $(INST_STATIC)
432
+	$(NOECHO) $(NOOP)
433
+
434
+
435
+# --- MakeMaker static_lib section:
436
+
437
+
438
+# --- MakeMaker manifypods section:
439
+
440
+POD2MAN_EXE = $(PERLRUN) "-MExtUtils::Command::MM" -e pod2man "--"
441
+POD2MAN = $(POD2MAN_EXE)
442
+
443
+
444
+manifypods : pure_all  \
445
+	lib/DBIx/Custom/Next/Util.pm \
446
+	lib/DBIx/Custom/Next/Model.pm \
447
+	lib/DBIx/Custom/Next/Order.pm \
448
+	lib/DBIx/Custom/Next/NotExists.pm \
449
+	lib/DBIx/Custom/Next/Mapper.pm \
450
+	lib/DBIx/Custom/Next/Where.pm \
451
+	lib/DBIx/Custom/Next.pm \
452
+	lib/DBIx/Custom/Next/Result.pm
453
+	$(NOECHO) $(POD2MAN) --section=3 --perm_rw=$(PERM_RW) \
454
+	  lib/DBIx/Custom/Next/Util.pm $(INST_MAN3DIR)/DBIx::Custom::Next::Util.$(MAN3EXT) \
455
+	  lib/DBIx/Custom/Next/Model.pm $(INST_MAN3DIR)/DBIx::Custom::Next::Model.$(MAN3EXT) \
456
+	  lib/DBIx/Custom/Next/Order.pm $(INST_MAN3DIR)/DBIx::Custom::Next::Order.$(MAN3EXT) \
457
+	  lib/DBIx/Custom/Next/NotExists.pm $(INST_MAN3DIR)/DBIx::Custom::Next::NotExists.$(MAN3EXT) \
458
+	  lib/DBIx/Custom/Next/Mapper.pm $(INST_MAN3DIR)/DBIx::Custom::Next::Mapper.$(MAN3EXT) \
459
+	  lib/DBIx/Custom/Next/Where.pm $(INST_MAN3DIR)/DBIx::Custom::Next::Where.$(MAN3EXT) \
460
+	  lib/DBIx/Custom/Next.pm $(INST_MAN3DIR)/DBIx::Custom::Next.$(MAN3EXT) \
461
+	  lib/DBIx/Custom/Next/Result.pm $(INST_MAN3DIR)/DBIx::Custom::Next::Result.$(MAN3EXT) 
462
+
463
+
464
+
465
+
466
+# --- MakeMaker processPL section:
467
+
468
+
469
+# --- MakeMaker installbin section:
470
+
471
+
472
+# --- MakeMaker subdirs section:
473
+
474
+# none
475
+
476
+# --- MakeMaker clean_subdirs section:
477
+clean_subdirs :
478
+	$(NOECHO) $(NOOP)
479
+
480
+
481
+# --- MakeMaker clean section:
482
+
483
+# Delete temporary files but do not touch installed files. We don't delete
484
+# the Makefile here so a later make realclean still has a makefile to use.
485
+
486
+clean :: clean_subdirs
487
+	- $(RM_F) \
488
+	  *$(LIB_EXT) core \
489
+	  core.[0-9] $(INST_ARCHAUTODIR)/extralibs.all \
490
+	  core.[0-9][0-9] $(BASEEXT).bso \
491
+	  pm_to_blib.ts core.[0-9][0-9][0-9][0-9] \
492
+	  $(BASEEXT).x $(BOOTSTRAP) \
493
+	  perl$(EXE_EXT) tmon.out \
494
+	  *$(OBJ_EXT) pm_to_blib \
495
+	  $(INST_ARCHAUTODIR)/extralibs.ld blibdirs.ts \
496
+	  core.[0-9][0-9][0-9][0-9][0-9] *perl.core \
497
+	  core.*perl.*.? $(MAKE_APERL_FILE) \
498
+	  perl $(BASEEXT).def \
499
+	  core.[0-9][0-9][0-9] mon.out \
500
+	  lib$(BASEEXT).def perlmain.c \
501
+	  perl.exe so_locations \
502
+	  $(BASEEXT).exp 
503
+	- $(RM_RF) \
504
+	  DBIx-Custom-* blib 
505
+	- $(MV) $(FIRST_MAKEFILE) $(MAKEFILE_OLD) $(DEV_NULL)
506
+
507
+
508
+# --- MakeMaker realclean_subdirs section:
509
+realclean_subdirs :
510
+	$(NOECHO) $(NOOP)
511
+
512
+
513
+# --- MakeMaker realclean section:
514
+# Delete temporary files (via clean) and also delete dist files
515
+realclean purge ::  clean realclean_subdirs
516
+	- $(RM_F) \
517
+	  $(MAKEFILE_OLD) $(FIRST_MAKEFILE) 
518
+	- $(RM_RF) \
519
+	  $(DISTVNAME) 
520
+
521
+
522
+# --- MakeMaker metafile section:
523
+metafile : create_distdir
524
+	$(NOECHO) $(ECHO) Generating META.yml
525
+	$(NOECHO) $(ECHO) '--- #YAML:1.0' > META_new.yml
526
+	$(NOECHO) $(ECHO) 'name:               DBIx-Custom' >> META_new.yml
527
+	$(NOECHO) $(ECHO) 'version:            0.20_01' >> META_new.yml
528
+	$(NOECHO) $(ECHO) 'abstract:           ~' >> META_new.yml
529
+	$(NOECHO) $(ECHO) 'author:' >> META_new.yml
530
+	$(NOECHO) $(ECHO) '    - Yuki Kimoto <kimoto.yuki@gmail.com>' >> META_new.yml
531
+	$(NOECHO) $(ECHO) 'license:            perl' >> META_new.yml
532
+	$(NOECHO) $(ECHO) 'distribution_type:  module' >> META_new.yml
533
+	$(NOECHO) $(ECHO) 'configure_requires:' >> META_new.yml
534
+	$(NOECHO) $(ECHO) '    ExtUtils::MakeMaker:  0' >> META_new.yml
535
+	$(NOECHO) $(ECHO) 'build_requires:' >> META_new.yml
536
+	$(NOECHO) $(ECHO) '    ExtUtils::MakeMaker:  0' >> META_new.yml
537
+	$(NOECHO) $(ECHO) 'requires:' >> META_new.yml
538
+	$(NOECHO) $(ECHO) '    DBD::SQLite:     1.25' >> META_new.yml
539
+	$(NOECHO) $(ECHO) '    DBI:             1.605' >> META_new.yml
540
+	$(NOECHO) $(ECHO) '    Object::Simple:  3.0621' >> META_new.yml
541
+	$(NOECHO) $(ECHO) '    Test::More:      0' >> META_new.yml
542
+	$(NOECHO) $(ECHO) 'no_index:' >> META_new.yml
543
+	$(NOECHO) $(ECHO) '    directory:' >> META_new.yml
544
+	$(NOECHO) $(ECHO) '        - t' >> META_new.yml
545
+	$(NOECHO) $(ECHO) '        - inc' >> META_new.yml
546
+	$(NOECHO) $(ECHO) 'generated_by:       ExtUtils::MakeMaker version 6.56' >> META_new.yml
547
+	$(NOECHO) $(ECHO) 'meta-spec:' >> META_new.yml
548
+	$(NOECHO) $(ECHO) '    url:      http://module-build.sourceforge.net/META-spec-v1.4.html' >> META_new.yml
549
+	$(NOECHO) $(ECHO) '    version:  1.4' >> META_new.yml
550
+	-$(NOECHO) $(MV) META_new.yml $(DISTVNAME)/META.yml
551
+
552
+
553
+# --- MakeMaker signature section:
554
+signature :
555
+	cpansign -s
556
+
557
+
558
+# --- MakeMaker dist_basics section:
559
+distclean :: realclean distcheck
560
+	$(NOECHO) $(NOOP)
561
+
562
+distcheck :
563
+	$(PERLRUN) "-MExtUtils::Manifest=fullcheck" -e fullcheck
564
+
565
+skipcheck :
566
+	$(PERLRUN) "-MExtUtils::Manifest=skipcheck" -e skipcheck
567
+
568
+manifest :
569
+	$(PERLRUN) "-MExtUtils::Manifest=mkmanifest" -e mkmanifest
570
+
571
+veryclean : realclean
572
+	$(RM_F) *~ */*~ *.orig */*.orig *.bak */*.bak *.old */*.old 
573
+
574
+
575
+
576
+# --- MakeMaker dist_core section:
577
+
578
+dist : $(DIST_DEFAULT) $(FIRST_MAKEFILE)
579
+	$(NOECHO) $(ABSPERLRUN) -l -e 'print '\''Warning: Makefile possibly out of date with $(VERSION_FROM)'\''' \
580
+	  -e '    if -e '\''$(VERSION_FROM)'\'' and -M '\''$(VERSION_FROM)'\'' < -M '\''$(FIRST_MAKEFILE)'\'';' --
581
+
582
+tardist : $(DISTVNAME).tar$(SUFFIX)
583
+	$(NOECHO) $(NOOP)
584
+
585
+uutardist : $(DISTVNAME).tar$(SUFFIX)
586
+	uuencode $(DISTVNAME).tar$(SUFFIX) $(DISTVNAME).tar$(SUFFIX) > $(DISTVNAME).tar$(SUFFIX)_uu
587
+
588
+$(DISTVNAME).tar$(SUFFIX) : distdir
589
+	$(PREOP)
590
+	$(TO_UNIX)
591
+	$(TAR) $(TARFLAGS) $(DISTVNAME).tar $(DISTVNAME)
592
+	$(RM_RF) $(DISTVNAME)
593
+	$(COMPRESS) $(DISTVNAME).tar
594
+	$(POSTOP)
595
+
596
+zipdist : $(DISTVNAME).zip
597
+	$(NOECHO) $(NOOP)
598
+
599
+$(DISTVNAME).zip : distdir
600
+	$(PREOP)
601
+	$(ZIP) $(ZIPFLAGS) $(DISTVNAME).zip $(DISTVNAME)
602
+	$(RM_RF) $(DISTVNAME)
603
+	$(POSTOP)
604
+
605
+shdist : distdir
606
+	$(PREOP)
607
+	$(SHAR) $(DISTVNAME) > $(DISTVNAME).shar
608
+	$(RM_RF) $(DISTVNAME)
609
+	$(POSTOP)
610
+
611
+
612
+# --- MakeMaker distdir section:
613
+create_distdir :
614
+	$(RM_RF) $(DISTVNAME)
615
+	$(PERLRUN) "-MExtUtils::Manifest=manicopy,maniread" \
616
+		-e "manicopy(maniread(),'$(DISTVNAME)', '$(DIST_CP)');"
617
+
618
+distdir : create_distdir distmeta 
619
+	$(NOECHO) $(NOOP)
620
+
621
+
622
+
623
+# --- MakeMaker dist_test section:
624
+disttest : distdir
625
+	cd $(DISTVNAME) && $(ABSPERLRUN) Makefile.PL 
626
+	cd $(DISTVNAME) && $(MAKE) $(PASTHRU)
627
+	cd $(DISTVNAME) && $(MAKE) test $(PASTHRU)
628
+
629
+
630
+
631
+# --- MakeMaker dist_ci section:
632
+
633
+ci :
634
+	$(PERLRUN) "-MExtUtils::Manifest=maniread" \
635
+	  -e "@all = keys %{ maniread() };" \
636
+	  -e "print(qq{Executing $(CI) @all\n}); system(qq{$(CI) @all});" \
637
+	  -e "print(qq{Executing $(RCS_LABEL) ...\n}); system(qq{$(RCS_LABEL) @all});"
638
+
639
+
640
+# --- MakeMaker distmeta section:
641
+distmeta : create_distdir metafile
642
+	$(NOECHO) cd $(DISTVNAME) && $(ABSPERLRUN) -MExtUtils::Manifest=maniadd -e 'eval { maniadd({q{META.yml} => q{Module meta-data (added by MakeMaker)}}) } ' \
643
+	  -e '    or print "Could not add META.yml to MANIFEST: $${'\''@'\''}\n"' --
644
+
645
+
646
+
647
+# --- MakeMaker distsignature section:
648
+distsignature : create_distdir
649
+	$(NOECHO) cd $(DISTVNAME) && $(ABSPERLRUN) -MExtUtils::Manifest=maniadd -e 'eval { maniadd({q{SIGNATURE} => q{Public-key signature (added by MakeMaker)}}) } ' \
650
+	  -e '    or print "Could not add SIGNATURE to MANIFEST: $${'\''@'\''}\n"' --
651
+	$(NOECHO) cd $(DISTVNAME) && $(TOUCH) SIGNATURE
652
+	cd $(DISTVNAME) && cpansign -s
653
+
654
+
655
+
656
+# --- MakeMaker install section:
657
+
658
+install :: pure_install doc_install
659
+	$(NOECHO) $(NOOP)
660
+
661
+install_perl :: pure_perl_install doc_perl_install
662
+	$(NOECHO) $(NOOP)
663
+
664
+install_site :: pure_site_install doc_site_install
665
+	$(NOECHO) $(NOOP)
666
+
667
+install_vendor :: pure_vendor_install doc_vendor_install
668
+	$(NOECHO) $(NOOP)
669
+
670
+pure_install :: pure_$(INSTALLDIRS)_install
671
+	$(NOECHO) $(NOOP)
672
+
673
+doc_install :: doc_$(INSTALLDIRS)_install
674
+	$(NOECHO) $(NOOP)
675
+
676
+pure__install : pure_site_install
677
+	$(NOECHO) $(ECHO) INSTALLDIRS not defined, defaulting to INSTALLDIRS=site
678
+
679
+doc__install : doc_site_install
680
+	$(NOECHO) $(ECHO) INSTALLDIRS not defined, defaulting to INSTALLDIRS=site
681
+
682
+pure_perl_install :: all
683
+	$(NOECHO) $(MOD_INSTALL) \
684
+		read $(PERL_ARCHLIB)/auto/$(FULLEXT)/.packlist \
685
+		write $(DESTINSTALLARCHLIB)/auto/$(FULLEXT)/.packlist \
686
+		$(INST_LIB) $(DESTINSTALLPRIVLIB) \
687
+		$(INST_ARCHLIB) $(DESTINSTALLARCHLIB) \
688
+		$(INST_BIN) $(DESTINSTALLBIN) \
689
+		$(INST_SCRIPT) $(DESTINSTALLSCRIPT) \
690
+		$(INST_MAN1DIR) $(DESTINSTALLMAN1DIR) \
691
+		$(INST_MAN3DIR) $(DESTINSTALLMAN3DIR)
692
+	$(NOECHO) $(WARN_IF_OLD_PACKLIST) \
693
+		$(SITEARCHEXP)/auto/$(FULLEXT)
694
+
695
+
696
+pure_site_install :: all
697
+	$(NOECHO) $(MOD_INSTALL) \
698
+		read $(SITEARCHEXP)/auto/$(FULLEXT)/.packlist \
699
+		write $(DESTINSTALLSITEARCH)/auto/$(FULLEXT)/.packlist \
700
+		$(INST_LIB) $(DESTINSTALLSITELIB) \
701
+		$(INST_ARCHLIB) $(DESTINSTALLSITEARCH) \
702
+		$(INST_BIN) $(DESTINSTALLSITEBIN) \
703
+		$(INST_SCRIPT) $(DESTINSTALLSITESCRIPT) \
704
+		$(INST_MAN1DIR) $(DESTINSTALLSITEMAN1DIR) \
705
+		$(INST_MAN3DIR) $(DESTINSTALLSITEMAN3DIR)
706
+	$(NOECHO) $(WARN_IF_OLD_PACKLIST) \
707
+		$(PERL_ARCHLIB)/auto/$(FULLEXT)
708
+
709
+pure_vendor_install :: all
710
+	$(NOECHO) $(MOD_INSTALL) \
711
+		read $(VENDORARCHEXP)/auto/$(FULLEXT)/.packlist \
712
+		write $(DESTINSTALLVENDORARCH)/auto/$(FULLEXT)/.packlist \
713
+		$(INST_LIB) $(DESTINSTALLVENDORLIB) \
714
+		$(INST_ARCHLIB) $(DESTINSTALLVENDORARCH) \
715
+		$(INST_BIN) $(DESTINSTALLVENDORBIN) \
716
+		$(INST_SCRIPT) $(DESTINSTALLVENDORSCRIPT) \
717
+		$(INST_MAN1DIR) $(DESTINSTALLVENDORMAN1DIR) \
718
+		$(INST_MAN3DIR) $(DESTINSTALLVENDORMAN3DIR)
719
+
720
+doc_perl_install :: all
721
+	$(NOECHO) $(ECHO) Appending installation info to $(DESTINSTALLARCHLIB)/perllocal.pod
722
+	-$(NOECHO) $(MKPATH) $(DESTINSTALLARCHLIB)
723
+	-$(NOECHO) $(DOC_INSTALL) \
724
+		"Module" "$(NAME)" \
725
+		"installed into" "$(INSTALLPRIVLIB)" \
726
+		LINKTYPE "$(LINKTYPE)" \
727
+		VERSION "$(VERSION)" \
728
+		EXE_FILES "$(EXE_FILES)" \
729
+		>> $(DESTINSTALLARCHLIB)/perllocal.pod
730
+
731
+doc_site_install :: all
732
+	$(NOECHO) $(ECHO) Appending installation info to $(DESTINSTALLARCHLIB)/perllocal.pod
733
+	-$(NOECHO) $(MKPATH) $(DESTINSTALLARCHLIB)
734
+	-$(NOECHO) $(DOC_INSTALL) \
735
+		"Module" "$(NAME)" \
736
+		"installed into" "$(INSTALLSITELIB)" \
737
+		LINKTYPE "$(LINKTYPE)" \
738
+		VERSION "$(VERSION)" \
739
+		EXE_FILES "$(EXE_FILES)" \
740
+		>> $(DESTINSTALLARCHLIB)/perllocal.pod
741
+
742
+doc_vendor_install :: all
743
+	$(NOECHO) $(ECHO) Appending installation info to $(DESTINSTALLARCHLIB)/perllocal.pod
744
+	-$(NOECHO) $(MKPATH) $(DESTINSTALLARCHLIB)
745
+	-$(NOECHO) $(DOC_INSTALL) \
746
+		"Module" "$(NAME)" \
747
+		"installed into" "$(INSTALLVENDORLIB)" \
748
+		LINKTYPE "$(LINKTYPE)" \
749
+		VERSION "$(VERSION)" \
750
+		EXE_FILES "$(EXE_FILES)" \
751
+		>> $(DESTINSTALLARCHLIB)/perllocal.pod
752
+
753
+
754
+uninstall :: uninstall_from_$(INSTALLDIRS)dirs
755
+	$(NOECHO) $(NOOP)
756
+
757
+uninstall_from_perldirs ::
758
+	$(NOECHO) $(UNINSTALL) $(PERL_ARCHLIB)/auto/$(FULLEXT)/.packlist
759
+
760
+uninstall_from_sitedirs ::
761
+	$(NOECHO) $(UNINSTALL) $(SITEARCHEXP)/auto/$(FULLEXT)/.packlist
762
+
763
+uninstall_from_vendordirs ::
764
+	$(NOECHO) $(UNINSTALL) $(VENDORARCHEXP)/auto/$(FULLEXT)/.packlist
765
+
766
+
767
+# --- MakeMaker force section:
768
+# Phony target to force checking subdirectories.
769
+FORCE :
770
+	$(NOECHO) $(NOOP)
771
+
772
+
773
+# --- MakeMaker perldepend section:
774
+
775
+
776
+# --- MakeMaker makefile section:
777
+# We take a very conservative approach here, but it's worth it.
778
+# We move Makefile to Makefile.old here to avoid gnu make looping.
779
+$(FIRST_MAKEFILE) : Makefile.PL $(CONFIGDEP)
780
+	$(NOECHO) $(ECHO) "Makefile out-of-date with respect to $?"
781
+	$(NOECHO) $(ECHO) "Cleaning current config before rebuilding Makefile..."
782
+	-$(NOECHO) $(RM_F) $(MAKEFILE_OLD)
783
+	-$(NOECHO) $(MV)   $(FIRST_MAKEFILE) $(MAKEFILE_OLD)
784
+	- $(MAKE) $(USEMAKEFILE) $(MAKEFILE_OLD) clean $(DEV_NULL)
785
+	$(PERLRUN) Makefile.PL 
786
+	$(NOECHO) $(ECHO) "==> Your Makefile has been rebuilt. <=="
787
+	$(NOECHO) $(ECHO) "==> Please rerun the $(MAKE) command.  <=="
788
+	$(FALSE)
789
+
790
+
791
+
792
+# --- MakeMaker staticmake section:
793
+
794
+# --- MakeMaker makeaperl section ---
795
+MAP_TARGET    = perl
796
+FULLPERL      = /usr/bin/perl
797
+
798
+$(MAP_TARGET) :: static $(MAKE_APERL_FILE)
799
+	$(MAKE) $(USEMAKEFILE) $(MAKE_APERL_FILE) $@
800
+
801
+$(MAKE_APERL_FILE) : $(FIRST_MAKEFILE) pm_to_blib
802
+	$(NOECHO) $(ECHO) Writing \"$(MAKE_APERL_FILE)\" for this $(MAP_TARGET)
803
+	$(NOECHO) $(PERLRUNINST) \
804
+		Makefile.PL DIR= \
805
+		MAKEFILE=$(MAKE_APERL_FILE) LINKTYPE=static \
806
+		MAKEAPERL=1 NORECURS=1 CCCDLFLAGS=
807
+
808
+
809
+# --- MakeMaker test section:
810
+
811
+TEST_VERBOSE=0
812
+TEST_TYPE=test_$(LINKTYPE)
813
+TEST_FILE = test.pl
814
+TEST_FILES = t/*.t t/next/*.t
815
+TESTDB_SW = -d
816
+
817
+testdb :: testdb_$(LINKTYPE)
818
+
819
+test :: $(TEST_TYPE) subdirs-test
820
+
821
+subdirs-test ::
822
+	$(NOECHO) $(NOOP)
823
+
824
+
825
+test_dynamic :: pure_all
826
+	PERL_DL_NONLAZY=1 $(FULLPERLRUN) "-MExtUtils::Command::MM" "-e" "test_harness($(TEST_VERBOSE), '$(INST_LIB)', '$(INST_ARCHLIB)')" $(TEST_FILES)
827
+
828
+testdb_dynamic :: pure_all
829
+	PERL_DL_NONLAZY=1 $(FULLPERLRUN) $(TESTDB_SW) "-I$(INST_LIB)" "-I$(INST_ARCHLIB)" $(TEST_FILE)
830
+
831
+test_ : test_dynamic
832
+
833
+test_static :: test_dynamic
834
+testdb_static :: testdb_dynamic
835
+
836
+
837
+# --- MakeMaker ppd section:
838
+# Creates a PPD (Perl Package Description) for a binary distribution.
839
+ppd :
840
+	$(NOECHO) $(ECHO) '<SOFTPKG NAME="$(DISTNAME)" VERSION="0.20_01">' > $(DISTNAME).ppd
841
+	$(NOECHO) $(ECHO) '    <ABSTRACT></ABSTRACT>' >> $(DISTNAME).ppd
842
+	$(NOECHO) $(ECHO) '    <AUTHOR>Yuki Kimoto &lt;kimoto.yuki@gmail.com&gt;</AUTHOR>' >> $(DISTNAME).ppd
843
+	$(NOECHO) $(ECHO) '    <IMPLEMENTATION>' >> $(DISTNAME).ppd
844
+	$(NOECHO) $(ECHO) '        <REQUIRE NAME="DBD::SQLite" VERSION="1.25" />' >> $(DISTNAME).ppd
845
+	$(NOECHO) $(ECHO) '        <REQUIRE NAME="DBI::" VERSION="1.605" />' >> $(DISTNAME).ppd
846
+	$(NOECHO) $(ECHO) '        <REQUIRE NAME="Object::Simple" VERSION="3.0621" />' >> $(DISTNAME).ppd
847
+	$(NOECHO) $(ECHO) '        <REQUIRE NAME="Test::More" />' >> $(DISTNAME).ppd
848
+	$(NOECHO) $(ECHO) '        <ARCHITECTURE NAME="i386-linux-thread-multi-5.8" />' >> $(DISTNAME).ppd
849
+	$(NOECHO) $(ECHO) '        <CODEBASE HREF="" />' >> $(DISTNAME).ppd
850
+	$(NOECHO) $(ECHO) '    </IMPLEMENTATION>' >> $(DISTNAME).ppd
851
+	$(NOECHO) $(ECHO) '</SOFTPKG>' >> $(DISTNAME).ppd
852
+
853
+
854
+# --- MakeMaker pm_to_blib section:
855
+
856
+pm_to_blib : $(FIRST_MAKEFILE) $(TO_INST_PM)
857
+	$(NOECHO) $(ABSPERLRUN) -MExtUtils::Install -e 'pm_to_blib({@ARGV}, '\''$(INST_LIB)/auto'\'', q[$(PM_FILTER)], '\''$(PERM_DIR)'\'')' -- \
858
+	  lib/DBIx/Custom/Next/Util.pm blib/lib/DBIx/Custom/Next/Util.pm \
859
+	  lib/DBIx/Custom/Next/Model.pm blib/lib/DBIx/Custom/Next/Model.pm \
860
+	  lib/DBIx/Custom/Next/Order.pm blib/lib/DBIx/Custom/Next/Order.pm \
861
+	  lib/DBIx/Custom/Next/NotExists.pm blib/lib/DBIx/Custom/Next/NotExists.pm \
862
+	  lib/DBIx/Custom/Next/Mapper.pm blib/lib/DBIx/Custom/Next/Mapper.pm \
863
+	  lib/DBIx/Custom/Next/Where.pm blib/lib/DBIx/Custom/Next/Where.pm \
864
+	  lib/DBIx/Custom/Next.pm blib/lib/DBIx/Custom/Next.pm \
865
+	  next.pl $(INST_LIB)/DBIx/next.pl \
866
+	  lib/DBIx/Custom/Next/Result.pm blib/lib/DBIx/Custom/Next/Result.pm 
867
+	$(NOECHO) $(TOUCH) pm_to_blib
868
+
869
+
870
+# --- MakeMaker selfdocument section:
871
+
872
+
873
+# --- MakeMaker postamble section:
874
+
875
+
876
+# End.
+2809
lib/DBIx/Custom/Next.pm
... ...
@@ -0,0 +1,2809 @@
1
+package DBIx::Custom::Next;
2
+use Object::Simple -base;
3
+
4
+our $VERSION = '0.20_01';
5
+$VERSION = eval $VERSION;
6
+use 5.008001;
7
+
8
+use Carp 'croak';
9
+use DBI;
10
+use DBIx::Custom::Next::Result;
11
+use DBIx::Custom::Next::Where;
12
+use DBIx::Custom::Next::Model;
13
+use DBIx::Custom::Next::Order;
14
+use DBIx::Custom::Next::Util qw/_array_to_hash _subname/;
15
+use DBIx::Custom::Next::Mapper;
16
+use DBIx::Custom::Next::NotExists;
17
+use Encode qw/encode encode_utf8 decode_utf8/;
18
+use Scalar::Util qw/weaken/;
19
+
20
+has [qw/connector dsn password quote user exclude_table user_table_info
21
+        user_column_info/],
22
+    option => sub { {} },
23
+    default_option => sub {
24
+        {
25
+            RaiseError => 1,
26
+            PrintError => 0,
27
+            AutoCommit => 1
28
+        }
29
+    },
30
+    filters => sub {
31
+        {
32
+            encode_utf8 => sub { encode_utf8($_[0]) },
33
+            decode_utf8 => sub { decode_utf8($_[0]) }
34
+        }
35
+    },
36
+    last_sql => '',
37
+    models => sub { {} },
38
+    now => sub {
39
+        sub {
40
+            my ($sec, $min, $hour, $mday, $mon, $year) = localtime;
41
+            $mon++;
42
+            $year += 1900;
43
+            my $now = sprintf("%04d-%02d-%02d %02d:%02d:%02d",
44
+              $year, $mon, $mday, $hour, $min, $sec);
45
+            return $now;
46
+        }
47
+    },
48
+    result_class  => 'DBIx::Custom::Next::Result',
49
+    safety_character => '\w',
50
+    separator => '.',
51
+    stash => sub { {} };
52
+
53
+sub available_datatype {
54
+    my $self = shift;
55
+    
56
+    my $data_types = '';
57
+    for my $i (-1000 .. 1000) {
58
+         my $type_info = $self->dbh->type_info($i);
59
+         my $data_type = $type_info->{DATA_TYPE};
60
+         my $type_name = $type_info->{TYPE_NAME};
61
+         $data_types .= "$data_type ($type_name)\n"
62
+           if defined $data_type;
63
+    }
64
+    return "Data Type maybe equal to Type Name" unless $data_types;
65
+    $data_types = "Data Type (Type name)\n" . $data_types;
66
+    return $data_types;
67
+}
68
+
69
+sub available_typename {
70
+    my $self = shift;
71
+    
72
+    # Type Names
73
+    my $type_names = {};
74
+    $self->each_column(sub {
75
+        my ($self, $table, $column, $column_info) = @_;
76
+        $type_names->{$column_info->{TYPE_NAME}} = 1
77
+          if $column_info->{TYPE_NAME};
78
+    });
79
+    my @output = sort keys %$type_names;
80
+    unshift @output, "Type Name";
81
+    return join "\n", @output;
82
+}
83
+
84
+our $AUTOLOAD;
85
+sub AUTOLOAD {
86
+    my $self = shift;
87
+
88
+    # Method name
89
+    my ($package, $mname) = $AUTOLOAD =~ /^([\w\:]+)\:\:(\w+)$/;
90
+
91
+    # Call method
92
+    $self->{_methods} ||= {};
93
+    if (my $method = $self->{_methods}->{$mname}) {
94
+        return $self->$method(@_)
95
+    }
96
+    elsif ($self->{dbh} && (my $dbh_method = $self->dbh->can($mname))) {
97
+        $self->dbh->$dbh_method(@_);
98
+    }
99
+    else {
100
+        croak qq{Can't locate object method "$mname" via "$package" }
101
+            . _subname;
102
+    }
103
+}
104
+
105
+sub assign_clause {
106
+    my ($self, $param, $opts) = @_;
107
+    
108
+    my $wrap = $opts->{wrap} || {};
109
+    my ($q, $p) = split //, $self->q('');
110
+    
111
+    # Assign clause (performance is important)
112
+    join(
113
+      ', ',
114
+      map {
115
+          ref $param->{$_} eq 'SCALAR' ? "$q$_$p = " . ${$param->{$_}}
116
+          : $wrap->{$_} ? "$q$_$p = " . $wrap->{$_}->(":$_")
117
+          : "$q$_$p = :$_";
118
+      } sort keys %$param
119
+    );
120
+}
121
+
122
+sub column {
123
+    my $self = shift;
124
+    my $option = pop if ref $_[-1] eq 'HASH';
125
+    my $real_table = shift;
126
+    my $columns = shift;
127
+    my $table = $option->{alias} || $real_table;
128
+    
129
+    # Columns
130
+    unless (defined $columns) {
131
+        $columns ||= $self->model($real_table)->columns;
132
+    }
133
+    
134
+    # Separator
135
+    my $separator = $self->separator;
136
+    
137
+    # Column clause
138
+    my @column;
139
+    $columns ||= [];
140
+    push @column, $self->q($table) . "." . $self->q($_) .
141
+      " as " . $self->q("${table}${separator}$_")
142
+      for @$columns;
143
+    
144
+    return join (', ', @column);
145
+}
146
+
147
+sub connect {
148
+    my $self = ref $_[0] ? shift : shift->new(@_);
149
+    
150
+    my $connector = $self->connector;
151
+    
152
+    if (!ref $connector && $connector) {
153
+        require DBIx::Connector;
154
+        
155
+        my $dsn = $self->dsn;
156
+        my $user = $self->user;
157
+        my $password = $self->password;
158
+        my $option = $self->option;
159
+        my $connector = DBIx::Connector->new($dsn, $user, $password,
160
+          {%{$self->default_option} , %$option});
161
+        $self->connector($connector);
162
+    }
163
+    
164
+    # Connect
165
+    $self->dbh;
166
+    
167
+    return $self;
168
+}
169
+
170
+sub count { shift->select(column => 'count(*)', @_)->fetch_first->[0] }
171
+
172
+sub dbh {
173
+    my $self = shift;
174
+    
175
+    # Set
176
+    if (@_) {
177
+        $self->{dbh} = $_[0];
178
+        
179
+        return $self;
180
+    }
181
+    
182
+    # Get
183
+    else {
184
+        # From Connction manager
185
+        if (my $connector = $self->connector) {
186
+            croak "connector must have dbh() method " . _subname
187
+              unless ref $connector && $connector->can('dbh');
188
+              
189
+            $self->{dbh} = $connector->dbh;
190
+        }
191
+        
192
+        # Connect
193
+        $self->{dbh} ||= $self->_connect;
194
+        
195
+        # Quote
196
+        unless (defined $self->quote) {
197
+            my $driver = $self->_driver;
198
+            my $quote =  $driver eq 'odbc' ? '[]'
199
+                       : $driver eq 'ado' ? '[]'
200
+                       : $driver eq 'mysql' ? '`'
201
+                       : '"';
202
+            $self->quote($quote);
203
+        }
204
+        
205
+        return $self->{dbh};
206
+    }
207
+}
208
+
209
+sub delete {
210
+    my ($self, %opt) = @_;
211
+    
212
+    # Don't allow delete all rows
213
+    croak qq{delete method where or id option must be specified } . _subname
214
+      if !$opt{where} && !defined $opt{id} && !$opt{allow_delete_all};
215
+    
216
+    # Where
217
+    my $w = $self->_where_clause_and_param($opt{where}, {},
218
+      delete $opt{id}, $opt{primary_key}, $opt{table});
219
+
220
+    # Delete statement
221
+    my $sql = "delete ";
222
+    $sql .= "$opt{prefix} " if defined $opt{prefix};
223
+    $sql .= "from " . $self->q($opt{table}) . " $w->{clause} ";
224
+    
225
+    # Execute query
226
+    $self->execute($sql, $w->{param}, %opt);
227
+}
228
+
229
+sub delete_all { shift->delete(@_, allow_delete_all => 1) }
230
+
231
+sub DESTROY {}
232
+
233
+sub create_model {
234
+    my $self = shift;
235
+    
236
+    # Options
237
+    my $opt = ref $_[0] eq 'HASH' ? $_[0] : {@_};
238
+    $opt->{dbi} = $self;
239
+    my $model_class = delete $opt->{model_class} || 'DBIx::Custom::Next::Model';
240
+    my $model_table = delete $opt->{table};
241
+    
242
+    # Create model
243
+    my $model = $model_class->new($opt);
244
+    weaken $model->{dbi};
245
+    $model->table($model_table) unless $model->table;
246
+    
247
+    # Set model
248
+    $self->model($model->table, $model);
249
+    
250
+    return $self->model($model->table);
251
+}
252
+
253
+sub each_column {
254
+    my ($self, $cb, %options) = @_;
255
+
256
+    my $user_column_info = $self->user_column_info;
257
+    
258
+    if ($user_column_info) {
259
+        $self->$cb($_->{table}, $_->{column}, $_->{info}) for @$user_column_info;
260
+    }
261
+    else {
262
+    
263
+        my $re = $self->exclude_table || $options{exclude_table};
264
+        # Tables
265
+        my %tables;
266
+        $self->each_table(sub { $tables{$_[1]}++ });
267
+
268
+        # Iterate all tables
269
+        my @tables = sort keys %tables;
270
+        for (my $i = 0; $i < @tables; $i++) {
271
+            my $table = $tables[$i];
272
+            
273
+            # Iterate all columns
274
+            my $sth_columns;
275
+            eval {$sth_columns = $self->dbh->column_info(undef, undef, $table, '%')};
276
+            next if $@;
277
+            while (my $column_info = $sth_columns->fetchrow_hashref) {
278
+                my $column = $column_info->{COLUMN_NAME};
279
+                $self->$cb($table, $column, $column_info);
280
+            }
281
+        }
282
+    }
283
+}
284
+
285
+sub each_table {
286
+    my ($self, $cb, %option) = @_;
287
+    
288
+    my $user_table_infos = $self->user_table_info;
289
+    
290
+    # Iterate tables
291
+    if ($user_table_infos) {
292
+        $self->$cb($_->{table}, $_->{info}) for @$user_table_infos;
293
+    }
294
+    else {
295
+        my $re = $self->exclude_table || $option{exclude};
296
+        my $sth_tables = $self->dbh->table_info;
297
+        while (my $table_info = $sth_tables->fetchrow_hashref) {
298
+            
299
+            # Table
300
+            my $table = $table_info->{TABLE_NAME};
301
+            next if defined $re && $table =~ /$re/;
302
+            $self->$cb($table, $table_info);
303
+        }
304
+    }
305
+}
306
+
307
+sub execute {
308
+    my ($self, $sql, $param, %opt) = @_;
309
+    $param ||= {};
310
+
311
+    my $tables = $opt{table} || [];
312
+    $tables = [$tables] unless ref $tables eq 'ARRAY';
313
+    
314
+    # Merge second parameter
315
+    my @cleanup;
316
+    my $saved_param;
317
+    if (ref $param eq 'ARRAY') {
318
+        my $param2 = $param->[1];
319
+        $param = $param->[0];
320
+        for my $column (keys %$param2) {
321
+            if (!exists $param->{$column}) {
322
+                $param->{$column} = $param2->{$column};
323
+                push @cleanup, $column;
324
+            }
325
+            else {
326
+                delete $param->{$_} for @cleanup;
327
+                @cleanup = ();
328
+                $saved_param  = $param;
329
+                $param = $self->merge_param($param, $param2);
330
+                delete $saved_param->{$_} for (@{$opt{cleanup} || []});
331
+                last;
332
+            }
333
+        }
334
+    }
335
+    
336
+    # Append
337
+    $sql .= " $opt{append}" if defined $opt{append};
338
+    
339
+    # Query
340
+    my $query;
341
+    $query = $opt{reuse}->{$sql} if $opt{reuse};
342
+    
343
+    if ($query) {
344
+        # Save query
345
+        $self->{last_sql} = $query->{sql};
346
+    }
347
+    else {
348
+        
349
+        my $safety = $self->{safety_character} || $self->safety_character;
350
+        # Check unsafety keys
351
+        unless ((join('', keys %$param) || '') =~ /^[$safety\.]+$/) {
352
+            for my $column (keys %$param) {
353
+                croak qq{"$column" is not safety column name } . _subname
354
+                  unless $column =~ /^[$safety\.]+$/;
355
+            }
356
+        }
357
+
358
+        # Query
359
+        $query = $self->_build_query($sql);
360
+
361
+        # After build sql
362
+        $query->{sql} = $opt{after_build_sql}->($query->{sql})
363
+          if $opt{after_build_sql};
364
+            
365
+        # Save sql
366
+        $self->{last_sql} = $query->{sql};
367
+        
368
+        # Prepare statement handle
369
+        my $sth;
370
+        eval { $sth = $self->dbh->prepare($query->{sql}) };
371
+        
372
+        if ($@) {
373
+            $self->_croak($@, qq{. Following SQL is executed.\n}
374
+              . qq{$query->{sql}\n} . _subname);
375
+        }
376
+        
377
+        # Set statement handle
378
+        $query->{sth} = $sth;
379
+        
380
+        # Save query
381
+        $opt{reuse}->{$sql} = $query if $opt{reuse};
382
+    }
383
+
384
+    # Return query
385
+    if ($opt{query}) {
386
+      delete $param->{$_} for (@cleanup, @{$opt{cleanup} || []});
387
+      return $query;
388
+    }
389
+    
390
+    # Tables
391
+    my $main_table = @{$tables}[-1];
392
+    
393
+    # Type rule
394
+    my $type_filters = {};
395
+    my $type_rule_off = !$self->{_type_rule_is_called} || $opt{type_rule_off};
396
+    unless ($type_rule_off) {
397
+        my $type_rule_off_parts = {
398
+            1 => $opt{type_rule1_off},
399
+            2 => $opt{type_rule2_off}
400
+        };
401
+        for my $i (1, 2) {
402
+            unless ($type_rule_off_parts->{$i}) {
403
+                $type_filters->{$i} = {};
404
+                my $table_alias = $opt{table_alias} || {};
405
+                for my $alias (keys %$table_alias) {
406
+                    my $table = $table_alias->{$alias};
407
+                    
408
+                    for my $column (keys %{$self->{"_into$i"}{key}{$table} || {}}) {
409
+                        $type_filters->{$i}->{"$alias.$column"} = $self->{"_into$i"}{key}{$table}{$column};
410
+                    }
411
+                }
412
+                $type_filters->{$i} = {%{$type_filters->{$i}}, %{$self->{"_into$i"}{key}{$main_table} || {}}}
413
+                  if $main_table;
414
+            }
415
+        }
416
+    }
417
+
418
+    my $sth = $query->{sth};
419
+    my $affected;
420
+    
421
+    # Execute
422
+    my $bind;
423
+    my $bind_types;
424
+    if (!$query->{duplicate} && $type_rule_off &&
425
+      !$opt{filter} && !$opt{bind_type} && !$ENV{DBIX_CUSTOM_DEBUG}) 
426
+    {
427
+        eval { $affected = $sth->execute(map { $param->{$_} } @{$query->{columns}}) };
428
+    }
429
+    else {
430
+        ($bind, $bind_types) = $self->_create_bind_values($param,
431
+           $query->{columns}, $opt{filter}, $type_filters, $opt{bind_type});
432
+        eval {
433
+            if ($opt{bind_type}) {
434
+                $sth->bind_param($_ + 1, $bind->[$_],
435
+                    $bind_types->[$_] ? $bind_types->[$_] : ())
436
+                  for (0 .. @$bind - 1);
437
+                $affected = $sth->execute;
438
+            }
439
+            else { $affected = $sth->execute(@$bind) }
440
+        };
441
+    }
442
+    $self->_croak($@, qq{. Following SQL is executed.\n}
443
+      . qq{$query->{sql}\n} . _subname) if $@;
444
+
445
+    # Remove id from parameter
446
+    delete $param->{$_} for (@cleanup, @{$opt{cleanup} || []});
447
+    
448
+    # DEBUG message
449
+    if ($ENV{DBIX_CUSTOM_DEBUG}) {
450
+        warn "SQL:\n" . $query->{sql} . "\n";
451
+        my @output;
452
+        for my $value (@$bind) {
453
+            $value = 'undef' unless defined $value;
454
+            $value = encode($ENV{DBIX_CUSTOM_DEBUG_ENCODING} || 'UTF-8', $value)
455
+              if utf8::is_utf8($value);
456
+            push @output, $value;
457
+        }
458
+        warn "Bind values: " . join(', ', @output) . "\n\n";
459
+    }
460
+    
461
+    # Not select statement
462
+    return $affected unless $sth->{NUM_OF_FIELDS};
463
+    
464
+    # Result
465
+    return $self->result_class->new(
466
+        sth => $sth,
467
+        dbi => $self,
468
+        type_rule => {
469
+            from1 => $self->type_rule->{from1},
470
+            from2 => $self->type_rule->{from2}
471
+        },
472
+    );
473
+}
474
+
475
+sub get_table_info {
476
+    my ($self, %opt) = @_;
477
+    
478
+    my $exclude = delete $opt{exclude};
479
+    croak qq/"$_" is wrong option/ for keys %opt;
480
+    
481
+    my $table_info = [];
482
+    $self->each_table(
483
+        sub { push @$table_info, {table => $_[1], info => $_[2] } },
484
+        exclude => $exclude
485
+    );
486
+    
487
+    return [sort {$a->{table} cmp $b->{table} } @$table_info];
488
+}
489
+
490
+sub get_column_info {
491
+    my ($self, %opt) = @_;
492
+    
493
+    my $exclude_table = delete $opt{exclude_table};
494
+    croak qq/"$_" is wrong option/ for keys %opt;
495
+    
496
+    my $column_info = [];
497
+    $self->each_column(
498
+        sub { push @$column_info, {table => $_[1], column => $_[2], info => $_[3] } },
499
+        exclude_table => $exclude_table
500
+    );
501
+    
502
+    return [
503
+      sort {$a->{table} cmp $b->{table} || $a->{column} cmp $b->{column} }
504
+        @$column_info];
505
+}
506
+
507
+sub helper {
508
+    my $self = shift;
509
+    
510
+    # Register method
511
+    my $methods = ref $_[0] eq 'HASH' ? $_[0] : {@_};
512
+    $self->{_methods} = {%{$self->{_methods} || {}}, %$methods};
513
+    
514
+    return $self;
515
+}
516
+
517
+sub insert {
518
+    my ($self, $param, %opt) = @_;
519
+    $param ||= {};
520
+
521
+    # Created time and updated time
522
+    my @cleanup;
523
+    if (defined $opt{created_at} || defined $opt{updated_at}) {
524
+        my $now = $self->now;
525
+        $now = $now->() if ref $now eq 'CODE';
526
+        if (defined $opt{created_at}) {
527
+            $param->{$opt{created_at}} = $now;
528
+            push @cleanup, $opt{created_at};
529
+        }
530
+        if (defined $opt{updated_at}) {
531
+            $param->{$opt{updated_at}} = $now;
532
+            push @cleanup, $opt{updated_at};
533
+        }
534
+    }
535
+    
536
+    # Merge id to parameter
537
+    my $id_param = {};
538
+    if (defined $opt{id}) {
539
+        croak "insert id option must be specified with primary_key option"
540
+          unless $opt{primary_key};
541
+        $opt{primary_key} = [$opt{primary_key}] unless ref $opt{primary_key};
542
+        $opt{id} = [$opt{id}] unless ref $opt{id};
543
+        for (my $i = 0; $i < @{$opt{id}}; $i++) {
544
+           my $key = $opt{primary_key}->[$i];
545
+           next if exists $param->{$key};
546
+           $param->{$key} = $opt{id}->[$i];
547
+           push @cleanup, $key;
548
+        }
549
+        delete $opt{id};
550
+    }
551
+    
552
+    # Insert statement
553
+    my $sql = "insert ";
554
+    $sql .= "$opt{prefix} " if defined $opt{prefix};
555
+    $sql .= "into " . $self->q($opt{table}) . " "
556
+      . $self->values_clause($param, {wrap => $opt{wrap}}) . " ";
557
+    
558
+    # Execute query
559
+    $opt{cleanup} = \@cleanup;
560
+    $self->execute($sql, $param, %opt);
561
+}
562
+
563
+sub include_model {
564
+    my ($self, $name_space, $model_infos) = @_;
565
+    
566
+    # Name space
567
+    $name_space ||= '';
568
+    
569
+    # Get Model infomations
570
+    unless ($model_infos) {
571
+
572
+        # Load name space module
573
+        croak qq{"$name_space" is invalid class name } . _subname
574
+          if $name_space =~ /[^\w:]/;
575
+        eval "use $name_space";
576
+        croak qq{Name space module "$name_space.pm" is needed. $@ }
577
+            . _subname
578
+          if $@;
579
+        
580
+        # Search model modules
581
+        my $path = $INC{"$name_space.pm"};
582
+        $path =~ s/\.pm$//;
583
+        opendir my $dh, $path
584
+          or croak qq{Can't open directory "$path": $! } . _subname
585
+        $model_infos = [];
586
+        while (my $module = readdir $dh) {
587
+            push @$model_infos, $module
588
+              if $module =~ s/\.pm$//;
589
+        }
590
+        close $dh;
591
+    }
592
+    
593
+    # Include models
594
+    for my $model_info (@$model_infos) {
595
+        
596
+        # Load model
597
+        my $model_class;
598
+        my $model_table;
599
+        if (ref $model_info eq 'HASH') {
600
+            $model_class = $model_info->{class};
601
+            $model_table = $model_info->{table};
602
+            $model_table ||= $model_class;
603
+        }
604
+        else { $model_class = $model_table = $model_info }
605
+        my $mclass = "${name_space}::$model_class";
606
+        croak qq{"$mclass" is invalid class name } . _subname
607
+          if $mclass =~ /[^\w:]/;
608
+        unless ($mclass->can('isa')) {
609
+            eval "use $mclass";
610
+            croak "$@ " . _subname if $@;
611
+        }
612
+        
613
+        # Create model
614
+        my $opt = {};
615
+        $opt->{model_class} = $mclass if $mclass;
616
+        $opt->{table}       = $model_table if $model_table;
617
+        $self->create_model($opt);
618
+    }
619
+    
620
+    return $self;
621
+}
622
+
623
+sub like_value { sub { "%$_[0]%" } }
624
+
625
+sub mapper {
626
+    my $self = shift;
627
+    return DBIx::Custom::Next::Mapper->new(@_);
628
+}
629
+
630
+sub merge_param {
631
+    my ($self, @params) = @_;
632
+    
633
+    # Merge parameters
634
+    my $merge = {};
635
+    for my $param (@params) {
636
+        for my $column (keys %$param) {
637
+            my $param_is_array = ref $param->{$column} eq 'ARRAY' ? 1 : 0;
638
+            
639
+            if (exists $merge->{$column}) {
640
+                $merge->{$column} = [$merge->{$column}]
641
+                  unless ref $merge->{$column} eq 'ARRAY';
642
+                push @{$merge->{$column}},
643
+                  ref $param->{$column} ? @{$param->{$column}} : $param->{$column};
644
+            }
645
+            else {
646
+                $merge->{$column} = $param->{$column};
647
+            }
648
+        }
649
+    }
650
+    
651
+    return $merge;
652
+}
653
+
654
+sub model {
655
+    my ($self, $name, $model) = @_;
656
+    
657
+    # Set model
658
+    if ($model) {
659
+        $self->models->{$name} = $model;
660
+        return $self;
661
+    }
662
+    
663
+    # Check model existance
664
+    croak qq{Model "$name" is not included } . _subname
665
+      unless $self->models->{$name};
666
+    
667
+    # Get model
668
+    return $self->models->{$name};
669
+}
670
+
671
+sub mycolumn {
672
+    my ($self, $table, $columns) = @_;
673
+    
674
+    # Create column clause
675
+    my @column;
676
+    $columns ||= [];
677
+    push @column, $self->q($table) . "." . $self->q($_) .
678
+      " as " . $self->q($_)
679
+      for @$columns;
680
+    
681
+    return join (', ', @column);
682
+}
683
+
684
+sub new {
685
+    my $self = shift->SUPER::new(@_);
686
+    
687
+    # Check attributes
688
+    my @attrs = keys %$self;
689
+    for my $attr (@attrs) {
690
+        croak qq{Invalid attribute: "$attr" } . _subname
691
+          unless $self->can($attr);
692
+    }
693
+
694
+    return $self;
695
+}
696
+
697
+sub not_exists { DBIx::Custom::Next::NotExists->singleton }
698
+
699
+sub order {
700
+    my $self = shift;
701
+    return DBIx::Custom::Next::Order->new(dbi => $self, @_);
702
+}
703
+
704
+sub q {
705
+    my ($self, $value, $quotemeta) = @_;
706
+    
707
+    my $quote = $self->{quote} || $self->quote || '';
708
+    return "$quote$value$quote"
709
+      if !$quotemeta && ($quote eq '`' || $quote eq '"');
710
+    
711
+    my $q = substr($quote, 0, 1) || '';
712
+    my $p;
713
+    if (defined $quote && length $quote > 1) {
714
+        $p = substr($quote, 1, 1);
715
+    }
716
+    else { $p = $q }
717
+    
718
+    if ($quotemeta) {
719
+        $q = quotemeta($q);
720
+        $p = quotemeta($p);
721
+    }
722
+    
723
+    return "$q$value$p";
724
+}
725
+
726
+sub register_filter {
727
+    my $self = shift;
728
+    
729
+    # Register filter
730
+    my $filters = ref $_[0] eq 'HASH' ? $_[0] : {@_};
731
+    $self->filters({%{$self->filters}, %$filters});
732
+    
733
+    return $self;
734
+}
735
+
736
+sub select {
737
+    my ($self, %opt) = @_;
738
+
739
+    # Options
740
+    my $tables = [$opt{table}];
741
+    my $param = delete $opt{param} || {};
742
+    
743
+    # Select statement
744
+    my $sql = 'select ';
745
+    
746
+    # Prefix
747
+    $sql .= "$opt{prefix} " if defined $opt{prefix};
748
+    
749
+    # Column
750
+    if (defined $opt{column}) {
751
+        my $columns
752
+          = ref $opt{column} eq 'ARRAY' ? $opt{column} : [$opt{column}];
753
+        for my $column (@$columns) {
754
+            $column = $self->column(%$column) if ref $column eq 'HASH';
755
+            unshift @$tables, @{$self->_search_tables($column)};
756
+            $sql .= "$column, ";
757
+        }
758
+        $sql =~ s/, $/ /;
759
+    }
760
+    else { $sql .= '* ' }
761
+    
762
+    # Table
763
+    croak "select method table option must be specified " . _subname
764
+      unless defined $tables->[-1];
765
+    $sql .= 'from ' . $self->q($tables->[-1] || '') . ' ';
766
+    $sql =~ s/, $/ /;
767
+
768
+    # Add tables in parameter
769
+    unshift @$tables,
770
+            @{$self->_search_tables(join(' ', keys %$param) || '')};
771
+    
772
+    # Where
773
+    my $w = $self->_where_clause_and_param($opt{where}, $param,
774
+      delete $opt{id}, $opt{primary_key}, $tables->[-1]);
775
+    
776
+    # Add table names in where clause
777
+    unshift @$tables, @{$self->_search_tables($w->{clause})};
778
+    
779
+    # Join statement
780
+    $self->_push_join(\$sql, $opt{join}, $tables) if defined $opt{join};
781
+    
782
+    # Add where clause
783
+    $sql .= "$w->{clause} ";
784
+    
785
+    # Execute query
786
+    my $result = $self->execute($sql, $w->{param}, %opt);
787
+    
788
+    $result;
789
+}
790
+
791
+sub setup_model {
792
+    my $self = shift;
793
+    
794
+    # Setup model
795
+    $self->each_column(
796
+        sub {
797
+            my ($self, $table, $column, $column_info) = @_;
798
+            if (my $model = $self->models->{$table}) {
799
+                push @{$model->columns}, $column;
800
+            }
801
+        }
802
+    );
803
+    return $self;
804
+}
805
+
806
+sub show_datatype {
807
+    my ($self, $table) = @_;
808
+    croak "Table name must be specified" unless defined $table;
809
+    print "$table\n";
810
+    
811
+    my $result = $self->select(table => $table, where => "'0' <> '0'");
812
+    my $sth = $result->sth;
813
+
814
+    my $columns = $sth->{NAME};
815
+    my $data_types = $sth->{TYPE};
816
+    
817
+    for (my $i = 0; $i < @$columns; $i++) {
818
+        my $column = $columns->[$i];
819
+        my $data_type = lc $data_types->[$i];
820
+        print "$column: $data_type\n";
821
+    }
822
+}
823
+
824
+sub show_typename {
825
+    my ($self, $t) = @_;
826
+    croak "Table name must be specified" unless defined $t;
827
+    print "$t\n";
828
+    
829
+    $self->each_column(sub {
830
+        my ($self, $table, $column, $infos) = @_;
831
+        return unless $table eq $t;
832
+        my $typename = lc $infos->{TYPE_NAME};
833
+        print "$column: $typename\n";
834
+    });
835
+    
836
+    return $self;
837
+}
838
+
839
+sub show_tables {
840
+    my $self = shift;
841
+    
842
+    my %tables;
843
+    $self->each_table(sub { $tables{$_[1]}++ });
844
+    print join("\n", sort keys %tables) . "\n";
845
+    return $self;
846
+}
847
+
848
+sub type_rule {
849
+    my $self = shift;
850
+
851
+    $self->{_type_rule_is_called} = 1;
852
+    
853
+    if (@_) {
854
+        my $type_rule = ref $_[0] eq 'HASH' ? $_[0] : {@_};
855
+        
856
+        # Into
857
+        for my $i (1 .. 2) {
858
+            my $into = "into$i";
859
+            my $exists_into = exists $type_rule->{$into};
860
+            $type_rule->{$into} = _array_to_hash($type_rule->{$into});
861
+            $self->{type_rule} = $type_rule;
862
+            $self->{"_$into"} = {};
863
+            for my $type_name (keys %{$type_rule->{$into} || {}}) {
864
+                croak qq{type name of $into section must be lower case}
865
+                  if $type_name =~ /[A-Z]/;
866
+            }
867
+            
868
+            $self->each_column(sub {
869
+                my ($dbi, $table, $column, $column_info) = @_;
870
+                
871
+                my $type_name = lc $column_info->{TYPE_NAME};
872
+                if ($type_rule->{$into} &&
873
+                    (my $filter = $type_rule->{$into}->{$type_name}))
874
+                {
875
+                    return unless exists $type_rule->{$into}->{$type_name};
876
+                    if  (defined $filter && ref $filter ne 'CODE') 
877
+                    {
878
+                        my $fname = $filter;
879
+                        croak qq{Filter "$fname" is not registered" } . _subname
880
+                          unless exists $self->filters->{$fname};
881
+                        
882
+                        $filter = $self->filters->{$fname};
883
+                    }
884
+
885
+                    $self->{"_$into"}{key}{$table}{$column} = $filter;
886
+                    $self->{"_$into"}{dot}{"$table.$column"} = $filter;
887
+                }
888
+            });
889
+        }
890
+
891
+        # From
892
+        for my $i (1 .. 2) {
893
+            $type_rule->{"from$i"} = _array_to_hash($type_rule->{"from$i"});
894
+            for my $data_type (keys %{$type_rule->{"from$i"} || {}}) {
895
+                croak qq{data type of from$i section must be lower case or number}
896
+                  if $data_type =~ /[A-Z]/;
897
+                my $fname = $type_rule->{"from$i"}{$data_type};
898
+                if (defined $fname && ref $fname ne 'CODE') {
899
+                    croak qq{Filter "$fname" is not registered" } . _subname
900
+                      unless exists $self->filters->{$fname};
901
+                    
902
+                    $type_rule->{"from$i"}{$data_type} = $self->filters->{$fname};
903
+                }
904
+            }
905
+        }
906
+        
907
+        return $self;
908
+    }
909
+    
910
+    return $self->{type_rule} || {};
911
+}
912
+
913
+sub update {
914
+    my ($self, $param, %opt) = @_;
915
+    $param ||= {};
916
+    
917
+    # Don't allow update all rows
918
+    croak qq{update method where option must be specified } . _subname
919
+      if !$opt{where} && !defined $opt{id} && !$opt{allow_update_all};
920
+    
921
+    # Created time and updated time
922
+    my @cleanup;
923
+    if (defined $opt{updated_at}) {
924
+        my $now = $self->now;
925
+        $now = $now->() if ref $now eq 'CODE';
926
+        $param->{$opt{updated_at}} = $self->now->();
927
+        push @cleanup, $opt{updated_at};
928
+    }
929
+
930
+    # Assign clause
931
+    my $assign_clause = $self->assign_clause($param, {wrap => $opt{wrap}});
932
+    
933
+    # Where
934
+    my $w = $self->_where_clause_and_param($opt{where}, {},
935
+      delete $opt{id}, $opt{primary_key}, $opt{table});
936
+    
937
+    # Update statement
938
+    my $sql = "update ";
939
+    $sql .= "$opt{prefix} " if defined $opt{prefix};
940
+    $sql .= $self->q($opt{table}) . " set $assign_clause $w->{clause} ";
941
+    
942
+    # Execute query
943
+    $opt{cleanup} = \@cleanup;
944
+    $self->execute($sql, [$param, $w->{param}], %opt);
945
+}
946
+
947
+sub update_all { shift->update(@_, allow_update_all => 1) };
948
+
949
+sub update_or_insert {
950
+    my ($self, $param, %opt) = @_;
951
+    croak "update_or_insert method need primary_key and id option "
952
+      unless defined $opt{id} && defined $opt{primary_key};
953
+    my $statement_opt = $opt{option} || {};
954
+
955
+    my $rows = $self->select(%opt, %{$statement_opt->{select} || {}})->all;
956
+    if (@$rows == 0) {
957
+        return $self->insert($param, %opt, %{$statement_opt->{insert} || {}});
958
+    }
959
+    elsif (@$rows == 1) {
960
+        return $self->update($param, %opt, %{$statement_opt->{update} || {}});
961
+    }
962
+    else {
963
+        croak "selected row must be one " . _subname;
964
+    }
965
+}
966
+
967
+sub values_clause {
968
+    my ($self, $param, $opts) = @_;
969
+    
970
+    my $wrap = $opts->{wrap} || {};
971
+    
972
+    # Create insert parameter
973
+    my ($q, $p) = split //, $self->q('');
974
+    
975
+    # values clause(performance is important)
976
+    '(' .
977
+    join(
978
+      ', ',
979
+      map { "$q$_$p" } sort keys %$param
980
+    ) .
981
+    ') values (' .
982
+    join(
983
+      ', ',
984
+      map {
985
+          ref $param->{$_} eq 'SCALAR' ? ${$param->{$_}} :
986
+          $wrap->{$_} ? $wrap->{$_}->(":$_") :
987
+          ":$_";
988
+      } sort keys %$param
989
+    ) .
990
+    ')'
991
+}
992
+
993
+sub where { DBIx::Custom::Next::Where->new(dbi => shift, @_) }
994
+
995
+sub _build_query {
996
+    my ($self, $sql) = @_;
997
+    
998
+    $sql ||= '';
999
+    my $columns = [];
1000
+    my %duplicate;
1001
+    my $duplicate;
1002
+    my $c = $self->{safety_character} || $self->safety_character;
1003
+    # Parameter regex
1004
+    $sql =~ s/([0-9]):/$1\\:/g;
1005
+    while ($sql =~ /(^|.*?[^\\]):([$c\.]+)(?:\{(.*?)\})?(.*)/sg) {
1006
+        push @$columns, $2;
1007
+        $duplicate = 1 if ++$duplicate{$columns->[-1]} > 1;
1008
+        $sql = defined $3 ? "$1$2 $3 ?$4" : "$1?$4";
1009
+    }
1010
+    $sql =~ s/\\:/:/g if index($sql, "\\:") != -1;
1011
+
1012
+    # Create query
1013
+    {sql => $sql, columns => $columns, duplicate => $duplicate};
1014
+}
1015
+
1016
+sub _create_query {
1017
+    
1018
+    my ($self, $source, $after_build_sql) = @_;
1019
+    
1020
+    # Query
1021
+    my $query = $self->_build_query($source);
1022
+
1023
+    # After build sql
1024
+    $query->{sql} = $after_build_sql->($query->{sql}) if $after_build_sql;
1025
+        
1026
+    # Save sql
1027
+    $self->{last_sql} = $query->{sql};
1028
+    
1029
+    # Prepare statement handle
1030
+    my $sth;
1031
+    eval { $sth = $self->dbh->prepare($query->{sql}) };
1032
+    
1033
+    if ($@) {
1034
+        $self->_croak($@, qq{. Following SQL is executed.\n}
1035
+          . qq{$query->{sql}\n} . _subname);
1036
+    }
1037
+    
1038
+    # Set statement handle
1039
+    $query->{sth} = $sth;
1040
+    
1041
+    return $query;
1042
+}
1043
+
1044
+sub _create_bind_values {
1045
+    my ($self, $params, $columns, $filter, $type_filters, $bind_type) = @_;
1046
+    
1047
+    # Bind type
1048
+    $bind_type ||= {};
1049
+    $bind_type = _array_to_hash($bind_type) if ref $bind_type eq 'ARRAY';
1050
+
1051
+    # Replace filter name to code
1052
+    $filter ||= {};
1053
+    $filter = ref $filter eq 'ARRAY' ? _array_to_hash($filter) : $filter;
1054
+    for my $column (keys %$filter) {
1055
+        my $name = $filter->{$column};
1056
+        if (!defined $name) {
1057
+            $filter->{$column} = undef;
1058
+        }
1059
+        elsif (ref $name ne 'CODE') {
1060
+          croak qq{Filter "$name" is not registered" } . _subname
1061
+            unless exists $self->filters->{$name};
1062
+          $filter->{$column} = $self->filters->{$name};
1063
+        }
1064
+    }
1065
+    
1066
+    # Create bind values
1067
+    my @bind;
1068
+    my @types;
1069
+    my %count;
1070
+    my %not_exists;
1071
+    for my $column (@$columns) {
1072
+        
1073
+        # Bind value
1074
+        if(ref $params->{$column} eq 'ARRAY') {
1075
+            my $i = $count{$column} || 0;
1076
+            $i += $not_exists{$column} || 0;
1077
+            my $found;
1078
+            for (my $k = $i; $i < @{$params->{$column}}; $k++) {
1079
+                if (ref $params->{$column}->[$k] eq 'DBIx::Custom::Next::NotExists') {
1080
+                    $not_exists{$column}++;
1081
+                }
1082
+                else  {
1083
+                    push @bind, $params->{$column}->[$k];
1084
+                    $found = 1;
1085
+                    last
1086
+                }
1087
+            }
1088
+            next unless $found;
1089
+        }
1090
+        else { push @bind, $params->{$column} }
1091
+        
1092
+        # Filter
1093
+        $bind[-1] = $filter->{$column}->($bind[-1]) if $filter->{$column};
1094
+        
1095
+        # Type rule
1096
+        if ($self->{_type_rule_is_called}) {
1097
+            my $tf1 = $self->{"_into1"}->{dot}->{$column}
1098
+              || $type_filters->{1}->{$column};
1099
+            $bind[-1] = $tf1->($bind[-1]) if $tf1;
1100
+            my $tf2 = $self->{"_into2"}->{dot}->{$column}
1101
+              || $type_filters->{2}->{$column};
1102
+            $bind[-1] = $tf2->($bind[-1]) if $tf2;
1103
+        }
1104
+       
1105
+        # Bind types
1106
+        push @types, $bind_type->{$column};
1107
+        
1108
+        # Count up 
1109
+        $count{$column}++;
1110
+    }
1111
+    
1112
+    return (\@bind, \@types);
1113
+}
1114
+
1115
+sub _id_to_param {
1116
+    my ($self, $id, $primary_keys, $table) = @_;
1117
+    
1118
+    # Check primary key
1119
+    croak "primary_key option " .
1120
+          "must be specified when id option is used" . _subname
1121
+      unless defined $primary_keys;
1122
+    $primary_keys = [$primary_keys] unless ref $primary_keys eq 'ARRAY';
1123
+    
1124
+    # Create parameter
1125
+    my $param = {};
1126
+    if (defined $id) {
1127
+        $id = [$id] unless ref $id;
1128
+        for(my $i = 0; $i < @$id; $i++) {
1129
+           my $key = $primary_keys->[$i];
1130
+           $key = "$table." . $key if $table;
1131
+           $param->{$key} = $id->[$i];
1132
+        }
1133
+    }
1134
+    
1135
+    return $param;
1136
+}
1137
+
1138
+sub _connect {
1139
+    my $self = shift;
1140
+    
1141
+    # Attributes
1142
+    my $dsn = $self->dsn;
1143
+    croak qq{"dsn" must be specified } . _subname
1144
+      unless $dsn;
1145
+    my $user        = $self->user;
1146
+    my $password    = $self->password;
1147
+    my $option = $self->option;
1148
+    $option = {%{$self->default_option}, %$option};
1149
+    
1150
+    # Connect
1151
+    my $dbh;
1152
+    eval {
1153
+        $dbh = DBI->connect(
1154
+            $dsn,
1155
+            $user,
1156
+            $password,
1157
+            $option
1158
+        );
1159
+    };
1160
+    
1161
+    # Connect error
1162
+    croak "$@ " . _subname if $@;
1163
+    
1164
+    return $dbh;
1165
+}
1166
+
1167
+sub _croak {
1168
+    my ($self, $error, $append) = @_;
1169
+    
1170
+    # Append
1171
+    $append ||= "";
1172
+    
1173
+    # Verbose
1174
+    if ($Carp::Verbose) { croak $error }
1175
+    
1176
+    # Not verbose
1177
+    else {
1178
+        
1179
+        # Remove line and module infromation
1180
+        my $at_pos = rindex($error, ' at ');
1181
+        $error = substr($error, 0, $at_pos);
1182
+        $error =~ s/\s+$//;
1183
+        croak "$error$append";
1184
+    }
1185
+}
1186
+
1187
+sub _driver { lc shift->{dbh}->{Driver}->{Name} }
1188
+
1189
+sub _need_tables {
1190
+    my ($self, $tree, $need_tables, $tables) = @_;
1191
+    
1192
+    # Get needed tables
1193
+    for my $table (@$tables) {
1194
+        if ($tree->{$table}) {
1195
+            $need_tables->{$table} = 1;
1196
+            $self->_need_tables($tree, $need_tables, [$tree->{$table}{parent}])
1197
+        }
1198
+    }
1199
+}
1200
+
1201
+sub _push_join {
1202
+    my ($self, $sql, $join, $join_tables) = @_;
1203
+    
1204
+    $join = [$join] unless ref $join eq 'ARRAY';
1205
+    
1206
+    # No join
1207
+    return unless @$join;
1208
+    
1209
+    # Push join clause
1210
+    my $tree = {};
1211
+    for (my $i = 0; $i < @$join; $i++) {
1212
+        
1213
+        # Arrange
1214
+        my $join_clause;;
1215
+        my $option;
1216
+        if (ref $join->[$i] eq 'HASH') {
1217
+            $join_clause = $join->[$i]->{clause};
1218
+            $option = {table => $join->[$i]->{table}};
1219
+        }
1220
+        else {
1221
+            $join_clause = $join->[$i];
1222
+            $option = {};
1223
+        };
1224
+
1225
+        # Find tables in join clause
1226
+        my $table1;
1227
+        my $table2;
1228
+        if (my $table = $option->{table}) {
1229
+            $table1 = $table->[0];
1230
+            $table2 = $table->[1];
1231
+        }
1232
+        else {
1233
+            my $q = $self->quote || '';
1234
+            my $j_clause = (split /\s+on\s+/, $join_clause)[-1];
1235
+            $j_clause =~ s/'.+?'//g;
1236
+            my $q_re = quotemeta($q);
1237
+            $j_clause =~ s/[$q_re]//g;
1238
+            
1239
+            my @j_clauses = reverse split /\s(and|on)\s/, $j_clause;
1240
+            my $c = $self->safety_character;
1241
+            my $join_re = qr/($c+)\.$c+[^$c].*?($c+)\.$c+/sm;
1242
+            for my $clause (@j_clauses) {
1243
+                if ($clause =~ $join_re) {
1244
+                    $table1 = $1;
1245
+                    $table2 = $2;
1246
+                    last;
1247
+                }                
1248
+            }
1249
+        }
1250
+        croak qq{join clause must have two table name after "on" keyword. } .
1251
+              qq{"$join_clause" is passed }  . _subname
1252
+          unless defined $table1 && defined $table2;
1253
+        croak qq{right side table of "$join_clause" must be unique }
1254
+            . _subname
1255
+          if exists $tree->{$table2};
1256
+        croak qq{Same table "$table1" is specified} . _subname
1257
+          if $table1 eq $table2;
1258
+        $tree->{$table2}
1259
+          = {position => $i, parent => $table1, join => $join_clause};
1260
+    }
1261
+    
1262
+    # Search need tables
1263
+    my $need_tables = {};
1264
+    $self->_need_tables($tree, $need_tables, $join_tables);
1265
+    my @need_tables = sort { $tree->{$a}{position} <=> $tree->{$b}{position} }
1266
+      keys %$need_tables;
1267
+    
1268
+    # Add join clause
1269
+    $$sql .= $tree->{$_}{join} . ' ' for @need_tables;
1270
+}
1271
+
1272
+sub _remove_duplicate_table {
1273
+    my ($self, $tables, $main_table) = @_;
1274
+    
1275
+    # Remove duplicate table
1276
+    my %tables = map {defined $_ ? ($_ => 1) : ()} @$tables;
1277
+    delete $tables{$main_table} if $main_table;
1278
+    
1279
+    my $new_tables = [keys %tables, $main_table ? $main_table : ()];
1280
+    if (my $q = $self->quote || '') {
1281
+        $q = quotemeta($q);
1282
+        $_ =~ s/[$q]//g for @$new_tables;
1283
+    }
1284
+
1285
+    return $new_tables;
1286
+}
1287
+
1288
+sub _search_tables {
1289
+    my ($self, $source) = @_;
1290
+    
1291
+    # Search tables
1292
+    my $tables = [];
1293
+    my $safety_character = $self->safety_character;
1294
+    my $q = $self->quote;
1295
+    my $quoted_safety_character_re = $self->q("?([$safety_character]+)", 1);
1296
+    my $table_re = $q ? qr/(?:^|[^$safety_character])${quoted_safety_character_re}?\./
1297
+                      : qr/(?:^|[^$safety_character])([$safety_character]+)\./;
1298
+    while ($source =~ /$table_re/g) {
1299
+        push @$tables, $1;
1300
+    }
1301
+    
1302
+    return $tables;
1303
+}
1304
+
1305
+sub _where_clause_and_param {
1306
+    my ($self, $where, $param, $id, $primary_key, $table) = @_;
1307
+
1308
+    $where ||= {};
1309
+    $where = $self->_id_to_param($id, $primary_key, $table) if defined $id;
1310
+    $param ||= {};
1311
+    my $w = {};
1312
+    my $where_clause = '';
1313
+
1314
+    my $obj;
1315
+    
1316
+    if (ref $where) {
1317
+        if (ref $where eq 'HASH') {
1318
+            my $clause = ['and'];
1319
+            my $column_join = '';
1320
+            for my $column (keys %$where) {
1321
+                $column_join .= $column;
1322
+                my $table;
1323
+                my $c;
1324
+                if ($column =~ /(?:(.*?)\.)?(.*)/) {
1325
+                    $table = $1;
1326
+                    $c = $2;
1327
+                }
1328
+                
1329
+                my $table_quote;
1330
+                $table_quote = $self->q($table) if defined $table;
1331
+                my $column_quote = $self->q($c);
1332
+                $column_quote = $table_quote . '.' . $column_quote
1333
+                  if defined $table_quote;
1334
+                push @$clause, "$column_quote = :$column";
1335
+            }
1336
+
1337
+            # Check unsafety column
1338
+            my $safety = $self->safety_character;
1339
+            unless ($column_join =~ /^[$safety\.]+$/) {
1340
+                for my $column (keys %$where) {
1341
+                    croak qq{"$column" is not safety column name } . _subname
1342
+                      unless $column =~ /^[$safety\.]+$/;
1343
+                }
1344
+            }
1345
+            
1346
+            $obj = $self->where(clause => $clause, param => $where);
1347
+        }
1348
+        elsif (ref $where eq 'DBIx::Custom::Next::Where') { $obj = $where }
1349
+        elsif (ref $where eq 'ARRAY') {
1350
+            $obj = $self->where(clause => $where->[0], param => $where->[1]);
1351
+        }
1352
+        
1353
+        # Check where argument
1354
+        croak qq{"where" must be hash reference or DBIx::Custom::Next::Where object}
1355
+            . qq{or array reference, which contains where clause and parameter}
1356
+            . _subname
1357
+          unless ref $obj eq 'DBIx::Custom::Next::Where';
1358
+
1359
+        $w->{param} = keys %$param
1360
+                    ? $self->merge_param($param, $obj->param)
1361
+                    : $obj->param;
1362
+        $w->{clause} = $obj->to_string;
1363
+    }
1364
+    elsif ($where) {
1365
+        $w->{clause} = "where $where";
1366
+        $w->{param} = $param;
1367
+    }
1368
+    
1369
+    return $w;
1370
+}
1371
+
1372
+1;
1373
+
1374
+=head1 NAME
1375
+
1376
+DBIx::Custom::Next - DBI extension to execute insert, update, delete, and select easily
1377
+
1378
+=head1 SYNOPSIS
1379
+
1380
+    use DBIx::Custom::Next;
1381
+    
1382
+    # Connect
1383
+    my $dbi = DBIx::Custom::Next->connect(
1384
+        dsn => "dbi:mysql:database=dbname",
1385
+        user => 'ken',
1386
+        password => '!LFKD%$&',
1387
+        option => {mysql_enable_utf8 => 1}
1388
+    );
1389
+
1390
+    # Insert 
1391
+    $dbi->insert({title => 'Perl', author => 'Ken'}, table  => 'book');
1392
+    
1393
+    # Update 
1394
+    $dbi->update({title => 'Perl', author => 'Ken'}, table  => 'book',
1395
+      where  => {id => 5});
1396
+    
1397
+    # Delete
1398
+    $dbi->delete(table  => 'book', where => {author => 'Ken'});
1399
+
1400
+    # Select
1401
+    my $result = $dbi->select(table  => 'book',
1402
+      column => ['title', 'author'], where  => {author => 'Ken'});
1403
+
1404
+    # Select, more complex
1405
+    my $result = $dbi->select(
1406
+        table  => 'book',
1407
+        column => [
1408
+            {book => [qw/title author/]},
1409
+            {company => ['name']}
1410
+        ],
1411
+        where  => {'book.author' => 'Ken'},
1412
+        join => ['left outer join company on book.company_id = company.id'],
1413
+        append => 'order by id limit 5'
1414
+    );
1415
+    
1416
+    # Fetch
1417
+    while (my $row = $result->fetch) {
1418
+        
1419
+    }
1420
+    
1421
+    # Fetch as hash
1422
+    while (my $row = $result->fetch_hash) {
1423
+        
1424
+    }
1425
+    
1426
+    # Execute SQL with parameter.
1427
+    $dbi->execute(
1428
+        "select id from book where author = :author and title like :title",
1429
+        {author => 'ken', title => '%Perl%'}
1430
+    );
1431
+    
1432
+=head1 DESCRIPTION
1433
+
1434
+L<DBIx::Custom::Next> is L<DBI> wrapper module to execute SQL easily.
1435
+This module have the following features.
1436
+
1437
+=over 4
1438
+
1439
+=item *
1440
+
1441
+Execute C<insert>, C<update>, C<delete>, or C<select> statement easily
1442
+
1443
+=item *
1444
+
1445
+Create C<where> clause flexibly
1446
+
1447
+=item *
1448
+
1449
+Named place holder support
1450
+
1451
+=item *
1452
+
1453
+Model support
1454
+
1455
+=item *
1456
+
1457
+Connection manager support
1458
+
1459
+=item *
1460
+
1461
+Choice your favorite relational database management system,
1462
+C<MySQL>, C<SQLite>, C<PostgreSQL>, C<Oracle>,
1463
+C<Microsoft SQL Server>, C<Microsoft Access>, C<DB2> or anything, 
1464
+
1465
+=item *
1466
+
1467
+Filtering by data type or column name
1468
+
1469
+=item *
1470
+
1471
+Create C<order by> clause flexibly
1472
+
1473
+=back
1474
+
1475
+=head1 DOCUMENTATION
1476
+
1477
+L<DBIx::Custom::Next::Guide> - How to use L<DBIx::Custom::Next>
1478
+
1479
+L<DBIx::Custom::Next Wiki|https://github.com/yuki-kimoto/DBIx-Custom/wiki>
1480
+- Theare are various examples.
1481
+
1482
+Module documentations - 
1483
+L<DBIx::Custom::Next::Result>,
1484
+L<DBIx::Custom::Next::Query>,
1485
+L<DBIx::Custom::Next::Where>,
1486
+L<DBIx::Custom::Next::Model>,
1487
+L<DBIx::Custom::Next::Order>
1488
+
1489
+=head1 ATTRIBUTES
1490
+
1491
+=head2 C<connector>
1492
+
1493
+    my $connector = $dbi->connector;
1494
+    $dbi = $dbi->connector($connector);
1495
+
1496
+Connection manager object. if C<connector> is set, you can get C<dbh>
1497
+through connection manager. Conection manager object must have C<dbh> mehtod.
1498
+
1499
+This is L<DBIx::Connector> example. Please pass
1500
+C<default_option> to L<DBIx::Connector> C<new> method.
1501
+
1502
+    my $connector = DBIx::Connector->new(
1503
+        "dbi:mysql:database=$database",
1504
+        $user,
1505
+        $password,
1506
+        DBIx::Custom::Next->new->default_option
1507
+    );
1508
+    
1509
+    my $dbi = DBIx::Custom::Next->connect(connector => $connector);
1510
+
1511
+If C<connector> is set to 1 when connect method is called,
1512
+L<DBIx::Connector> is automatically set to C<connector>
1513
+
1514
+    my $dbi = DBIx::Custom::Next->connect(
1515
+      dsn => $dsn, user => $user, password => $password, connector => 1);
1516
+    
1517
+    my $connector = $dbi->connector; # DBIx::Connector
1518
+
1519
+Note that L<DBIx::Connector> must be installed.
1520
+
1521
+=head2 C<dsn>
1522
+
1523
+    my $dsn = $dbi->dsn;
1524
+    $dbi = $dbi->dsn("DBI:mysql:database=dbname");
1525
+
1526
+Data source name, used when C<connect> method is executed.
1527
+
1528
+=head2 C<default_option>
1529
+
1530
+    my $default_option = $dbi->default_option;
1531
+    $dbi = $dbi->default_option($default_option);
1532
+
1533
+L<DBI> default option, used when C<connect> method is executed,
1534
+default to the following values.
1535
+
1536
+    {
1537
+        RaiseError => 1,
1538
+        PrintError => 0,
1539
+        AutoCommit => 1,
1540
+    }
1541
+
1542
+=head2 C<exclude_table>
1543
+
1544
+    my $exclude_table = $dbi->exclude_table;
1545
+    $dbi = $dbi->exclude_table(qr/pg_/);
1546
+
1547
+Excluded table regex.
1548
+C<each_column>, C<each_table>, C<type_rule>,
1549
+and C<setup_model> methods ignore matching tables.
1550
+
1551
+=head2 C<filters>
1552
+
1553
+    my $filters = $dbi->filters;
1554
+    $dbi = $dbi->filters(\%filters);
1555
+
1556
+Filters, registered by C<register_filter> method.
1557
+
1558
+=head2 C<last_sql>
1559
+
1560
+    my $last_sql = $dbi->last_sql;
1561
+    $dbi = $dbi->last_sql($last_sql);
1562
+
1563
+Get last successed SQL executed by C<execute> method.
1564
+
1565
+=head2 C<now>
1566
+
1567
+    my $now = $dbi->now;
1568
+    $dbi = $dbi->now($now);
1569
+
1570
+Code reference which return current time, default to the following code reference.
1571
+
1572
+    sub {
1573
+        my ($sec, $min, $hour, $mday, $mon, $year) = localtime;
1574
+        $mon++;
1575
+        $year += 1900;
1576
+        return sprintf("%04d-%02d-%02d %02d:%02d:%02d");
1577
+    }
1578
+
1579
+This return the time like C<2011-10-14 05:05:27>.
1580
+
1581
+This is used by C<insert> method's C<created_at> option and C<updated_at> option,
1582
+and C<update> method's C<updated_at> option.
1583
+
1584
+=head2 C<models>
1585
+
1586
+    my $models = $dbi->models;
1587
+    $dbi = $dbi->models(\%models);
1588
+
1589
+Models, included by C<include_model> method.
1590
+
1591
+=head2 C<option>
1592
+
1593
+    my $option = $dbi->option;
1594
+    $dbi = $dbi->option($option);
1595
+
1596
+L<DBI> option, used when C<connect> method is executed.
1597
+Each value in option override the value of C<default_option>.
1598
+
1599
+=head2 C<password>
1600
+
1601
+    my $password = $dbi->password;
1602
+    $dbi = $dbi->password('lkj&le`@s');
1603
+
1604
+Password, used when C<connect> method is executed.
1605
+
1606
+=head2 C<quote>
1607
+
1608
+     my quote = $dbi->quote;
1609
+     $dbi = $dbi->quote('"');
1610
+
1611
+Reserved word quote.
1612
+Default to double quote '"' except for mysql.
1613
+In mysql, default to back quote '`'
1614
+
1615
+You can set quote pair.
1616
+
1617
+    $dbi->quote('[]');
1618
+
1619
+=head2 C<result_class>
1620
+
1621
+    my $result_class = $dbi->result_class;
1622
+    $dbi = $dbi->result_class('DBIx::Custom::Next::Result');
1623
+
1624
+Result class, default to L<DBIx::Custom::Next::Result>.
1625
+
1626
+=head2 C<safety_character>
1627
+
1628
+    my $safety_character = $dbi->safety_character;
1629
+    $dbi = $dbi->safety_character($character);
1630
+
1631
+Regex of safety character for table and column name, default to '\w'.
1632
+Note that you don't have to specify like '[\w]'.
1633
+
1634
+=head2 C<separator>
1635
+
1636
+    my $separator = $dbi->separator;
1637
+    $dbi = $dbi->separator('-');
1638
+
1639
+Separator which join table name and column name.
1640
+This have effect to C<column> and C<mycolumn> method,
1641
+and C<select> method's column option.
1642
+
1643
+Default to C<.>.
1644
+
1645
+=head2 C<user>
1646
+
1647
+    my $user = $dbi->user;
1648
+    $dbi = $dbi->user('Ken');
1649
+
1650
+User name, used when C<connect> method is executed.
1651
+
1652
+=head2 C<user_column_info>
1653
+
1654
+    my $user_column_info = $dbi->user_column_info;
1655
+    $dbi = $dbi->user_column_info($user_column_info);
1656
+
1657
+You can set the date like the following one.
1658
+
1659
+    [
1660
+        {table => 'book', column => 'title', info => {...}},
1661
+        {table => 'author', column => 'name', info => {...}}
1662
+    ]
1663
+
1664
+Usually, you set return value of C<get_column_info>.
1665
+
1666
+    my $user_column_info
1667
+      = $dbi->get_column_info(exclude_table => qr/^system/);
1668
+    $dbi->user_column_info($user_column_info);
1669
+
1670
+If C<user_column_info> is set, C<each_column> use C<user_column_info>
1671
+to find column info. this is very fast.
1672
+
1673
+=head2 C<user_table_info>
1674
+
1675
+    my $user_table_info = $dbi->user_table_info;
1676
+    $dbi = $dbi->user_table_info($user_table_info);
1677
+
1678
+You can set the following data.
1679
+
1680
+    [
1681
+        {table => 'book', info => {...}},
1682
+        {table => 'author', info => {...}}
1683
+    ]
1684
+
1685
+Usually, you can set return value of C<get_table_info>.
1686
+
1687
+    my $user_table_info = $dbi->get_table_info(exclude => qr/^system/);
1688
+    $dbi->user_table_info($user_table_info);
1689
+
1690
+If C<user_table_info> is set, C<each_table> use C<user_table_info>
1691
+to find table info.
1692
+
1693
+=head1 METHODS
1694
+
1695
+L<DBIx::Custom::Next> inherits all methods from L<Object::Simple>
1696
+and use all methods of L<DBI>
1697
+and implements the following new ones.
1698
+
1699
+=head2 C<available_datatype>
1700
+
1701
+    print $dbi->available_datatype;
1702
+
1703
+Get available data types. You can use these data types
1704
+in C<type rule>'s C<from1> and C<from2> section.
1705
+
1706
+=head2 C<available_typename>
1707
+
1708
+    print $dbi->available_typename;
1709
+
1710
+Get available type names. You can use these type names in
1711
+C<type_rule>'s C<into1> and C<into2> section.
1712
+
1713
+=head2 C<assign_clause>
1714
+
1715
+    my $assign_clause = $dbi->assign_clause({title => 'a', age => 2});
1716
+
1717
+Create assign clause
1718
+
1719
+    title = :title, author = :author
1720
+
1721
+This is used to create update clause.
1722
+
1723
+    "update book set " . $dbi->assign_clause({title => 'a', age => 2});
1724
+
1725
+=head2 C<column>
1726
+
1727
+    my $column = $dbi->column(book => ['author', 'title']);
1728
+
1729
+Create column clause. The follwoing column clause is created.
1730
+
1731
+    book.author as "book.author",
1732
+    book.title as "book.title"
1733
+
1734
+You can change separator by C<separator> attribute.
1735
+
1736
+    # Separator is hyphen
1737
+    $dbi->separator('-');
1738
+    
1739
+    book.author as "book-author",
1740
+    book.title as "book-title"
1741
+    
1742
+=head2 C<connect>
1743
+
1744
+    my $dbi = DBIx::Custom::Next->connect(
1745
+        dsn => "dbi:mysql:database=dbname",
1746
+        user => 'ken',
1747
+        password => '!LFKD%$&',
1748
+        option => {mysql_enable_utf8 => 1}
1749
+    );
1750
+
1751
+Connect to the database and create a new L<DBIx::Custom::Next> object.
1752
+
1753
+L<DBIx::Custom::Next> is a wrapper of L<DBI>.
1754
+C<AutoCommit> and C<RaiseError> options are true, 
1755
+and C<PrintError> option is false by default.
1756
+
1757
+=head2 C<count>
1758
+
1759
+    my $count = $dbi->count(table => 'book');
1760
+
1761
+Get rows count.
1762
+
1763
+Options is same as C<select> method's ones.
1764
+
1765
+=head2 C<create_model>
1766
+
1767
+    my $model = $dbi->create_model(
1768
+        table => 'book',
1769
+        primary_key => 'id',
1770
+        join => [
1771
+            'inner join company on book.comparny_id = company.id'
1772
+        ],
1773
+    );
1774
+
1775
+Create L<DBIx::Custom::Next::Model> object and initialize model.
1776
+the module is also used from C<model> method.
1777
+
1778
+   $dbi->model('book')->select(...);
1779
+
1780
+=head2 C<dbh>
1781
+
1782
+    my $dbh = $dbi->dbh;
1783
+
1784
+Get L<DBI> database handle. if C<connector> is set, you can get
1785
+database handle through C<connector> object.
1786
+
1787
+=head2 C<delete>
1788
+
1789
+    $dbi->delete(table => 'book', where => {title => 'Perl'});
1790
+
1791
+Execute delete statement.
1792
+
1793
+The following opitons are available.
1794
+
1795
+B<OPTIONS>
1796
+
1797
+C<delete> method use all of C<execute> method's options,
1798
+and use the following new ones.
1799
+
1800
+=over 4
1801
+
1802
+=item C<id>
1803
+
1804
+    id => 4
1805
+    id => [4, 5]
1806
+
1807
+ID corresponding to C<primary_key>.
1808
+You can delete rows by C<id> and C<primary_key>.
1809
+
1810
+    $dbi->delete(
1811
+        primary_key => ['id1', 'id2'],
1812
+        id => [4, 5],
1813
+        table => 'book',
1814
+    );
1815
+
1816
+The above is same as the followin one.
1817
+
1818
+    $dbi->delete(where => {id1 => 4, id2 => 5}, table => 'book');
1819
+
1820
+=item C<prefix>
1821
+
1822
+    prefix => 'some'
1823
+
1824
+prefix before table name section.
1825
+
1826
+    delete some from book
1827
+
1828
+=item C<table>
1829
+
1830
+    table => 'book'
1831
+
1832
+Table name.
1833
+
1834
+=item C<where>
1835
+
1836
+Same as C<select> method's C<where> option.
1837
+
1838
+=back
1839
+
1840
+=head2 C<delete_all>
1841
+
1842
+    $dbi->delete_all(table => $table);
1843
+
1844
+Execute delete statement for all rows.
1845
+Options is same as C<delete>.
1846
+
1847
+=head2 C<each_column>
1848
+
1849
+    $dbi->each_column(
1850
+        sub {
1851
+            my ($dbi, $table, $column, $column_info) = @_;
1852
+            
1853
+            my $type = $column_info->{TYPE_NAME};
1854
+            
1855
+            if ($type eq 'DATE') {
1856
+                # ...
1857
+            }
1858
+        }
1859
+    );
1860
+
1861
+Iterate all column informations in database.
1862
+Argument is callback which is executed when one column is found.
1863
+Callback receive four arguments. C<DBIx::Custom::Next object>, C<table name>,
1864
+C<column name>, and C<column information>.
1865
+
1866
+If C<user_column_info> is set, C<each_column> method use C<user_column_info>
1867
+infromation, you can improve the performance of C<each_column> in
1868
+the following way.
1869
+
1870
+    my $column_infos = $dbi->get_column_info(exclude_table => qr/^system_/);
1871
+    $dbi->user_column_info($column_info);
1872
+    $dbi->each_column(sub { ... });
1873
+
1874
+=head2 C<each_table>
1875
+
1876
+    $dbi->each_table(
1877
+        sub {
1878
+            my ($dbi, $table, $table_info) = @_;
1879
+            
1880
+            my $table_name = $table_info->{TABLE_NAME};
1881
+        }
1882
+    );
1883
+
1884
+Iterate all table informationsfrom in database.
1885
+Argument is callback which is executed when one table is found.
1886
+Callback receive three arguments, C<DBIx::Custom::Next object>, C<table name>,
1887
+C<table information>.
1888
+
1889
+If C<user_table_info> is set, C<each_table> method use C<user_table_info>
1890
+infromation, you can improve the performance of C<each_table> in
1891
+the following way.
1892
+
1893
+    my $table_infos = $dbi->get_table_info(exclude => qr/^system_/);
1894
+    $dbi->user_table_info($table_info);
1895
+    $dbi->each_table(sub { ... });
1896
+
1897
+=head2 C<execute>
1898
+
1899
+    my $result = $dbi->execute(
1900
+      "select * from book where title = :title and author like :author",
1901
+      {title => 'Perl', author => '%Ken%'}
1902
+    );
1903
+
1904
+    my $result = $dbi->execute(
1905
+      "select * from book where title = :book.title and author like :book.author",
1906
+      {'book.title' => 'Perl', 'book.author' => '%Ken%'}
1907
+    );
1908
+
1909
+Execute SQL. SQL can contain column parameter such as :author and :title.
1910
+You can append table name to column name such as :book.title and :book.author.
1911
+Second argunet is data, embedded into column parameter.
1912
+Return value is L<DBIx::Custom::Next::Result> object when select statement is executed,
1913
+or the count of affected rows when insert, update, delete statement is executed.
1914
+
1915
+Named placeholder such as C<:title> is replaced by placeholder C<?>.
1916
+    
1917
+    # Original
1918
+    select * from book where title = :title and author like :author
1919
+    
1920
+    # Replaced
1921
+    select * from where title = ? and author like ?;
1922
+
1923
+You can specify operator with named placeholder
1924
+by C<name{operator}> syntax.
1925
+
1926
+    # Original
1927
+    select * from book where :title{=} and :author{like}
1928
+    
1929
+    # Replaced
1930
+    select * from where title = ? and author like ?;
1931
+
1932
+Note that colons in time format such as 12:13:15 is exeption,
1933
+it is not parsed as named placeholder.
1934
+If you want to use colon generally, you must escape it by C<\\>
1935
+
1936
+    select * from where title = "aa\\:bb";
1937
+
1938
+B<OPTIONS>
1939
+
1940
+The following opitons are available.
1941
+
1942
+=over 4
1943
+
1944
+=item C<after_build_sql> 
1945
+
1946
+You can filter sql after the sql is build.
1947
+
1948
+    after_build_sql => $code_ref
1949
+
1950
+The following one is one example.
1951
+
1952
+    $dbi->select(
1953
+        table => 'book',
1954
+        column => 'distinct(name)',
1955
+        after_build_sql => sub {
1956
+            "select count(*) from ($_[0]) as t1"
1957
+        }
1958
+    );
1959
+
1960
+The following SQL is executed.
1961
+
1962
+    select count(*) from (select distinct(name) from book) as t1;
1963
+
1964
+=item C<append>
1965
+
1966
+    append => 'order by name'
1967
+
1968
+Append some statement after SQL.
1969
+
1970
+=item C<bind_type>
1971
+
1972
+Specify database bind data type.
1973
+
1974
+    bind_type => [image => DBI::SQL_BLOB]
1975
+    bind_type => [[qw/image audio/] => DBI::SQL_BLOB]
1976
+
1977
+This is used to bind parameter by C<bind_param> of statment handle.
1978
+
1979
+    $sth->bind_param($pos, $value, DBI::SQL_BLOB);
1980
+
1981
+=item C<filter>
1982
+    
1983
+    filter => {
1984
+        title  => sub { uc $_[0] }
1985
+        author => sub { uc $_[0] }
1986
+    }
1987
+
1988
+    # Filter name
1989
+    filter => {
1990
+        title  => 'upper_case',
1991
+        author => 'upper_case'
1992
+    }
1993
+        
1994
+    # At once
1995
+    filter => [
1996
+        [qw/title author/]  => sub { uc $_[0] }
1997
+    ]
1998
+
1999
+Filter. You can set subroutine or filter name
2000
+registered by by C<register_filter>.
2001
+This filter is executed before data is saved into database.
2002
+and before type rule filter is executed.
2003
+
2004
+=item C<query>
2005
+
2006
+    query => 1
2007
+
2008
+C<execute> method return L<DBIx::Custom::Next::Query> object, not executing SQL.
2009
+You can check SQL, column, or get statment handle.
2010
+
2011
+    my $sql = $query->{sql};
2012
+    my $sth = $query->{sth};
2013
+    my $columns = $query->{columns};
2014
+    
2015
+=item C<reuse>
2016
+    
2017
+    reuse => $hash_ref
2018
+
2019
+Reuse query object if the hash reference variable is set.
2020
+    
2021
+    my $queries = {};
2022
+    $dbi->execute($sql, $param, reuse => $queries);
2023
+
2024
+This will improved performance when you want to execute same query repeatedly
2025
+because generally creating query object is slow.
2026
+
2027
+=item C<primary_key>
2028
+
2029
+    primary_key => 'id'
2030
+    primary_key => ['id1', 'id2']
2031
+
2032
+Priamry key. This is used for C<id> option.
2033
+
2034
+=item C<table>
2035
+    
2036
+    table => 'author'
2037
+
2038
+If you want to omit table name in column name
2039
+and enable C<into1> and C<into2> type filter,
2040
+You must set C<table> option.
2041
+
2042
+    $dbi->execute("select * from book where title = :title and author = :author",
2043
+        {title => 'Perl', author => 'Ken', table => 'book');
2044
+
2045
+    # Same
2046
+    $dbi->execute(
2047
+      "select * from book where title = :book.title and author = :book.author",
2048
+      {title => 'Perl', author => 'Ken');
2049
+
2050
+=item C<table_alias>
2051
+
2052
+    table_alias => {user => 'worker'}
2053
+
2054
+Table alias. Key is real table name, value is alias table name.
2055
+If you set C<table_alias>, you can enable C<into1> and C<into2> type rule
2056
+on alias table name.
2057
+
2058
+=item C<type_rule_off>
2059
+
2060
+    type_rule_off => 1
2061
+
2062
+Turn C<into1> and C<into2> type rule off.
2063
+
2064
+=item C<type_rule1_off>
2065
+
2066
+    type_rule1_off => 1
2067
+
2068
+Turn C<into1> type rule off.
2069
+
2070
+=item C<type_rule2_off>
2071
+
2072
+    type_rule2_off => 1
2073
+
2074
+Turn C<into2> type rule off.
2075
+
2076
+=back
2077
+
2078
+=head2 C<get_column_info>
2079
+
2080
+    my $column_infos = $dbi->get_column_info(exclude_table => qr/^system_/);
2081
+
2082
+get column infomation except for one which match C<exclude_table> pattern.
2083
+
2084
+    [
2085
+        {table => 'book', column => 'title', info => {...}},
2086
+        {table => 'author', column => 'name' info => {...}}
2087
+    ]
2088
+
2089
+=head2 C<get_table_info>
2090
+
2091
+    my $table_infos = $dbi->get_table_info(exclude => qr/^system_/);
2092
+
2093
+get table infomation except for one which match C<exclude> pattern.
2094
+
2095
+    [
2096
+        {table => 'book', info => {...}},
2097
+        {table => 'author', info => {...}}
2098
+    ]
2099
+
2100
+You can set this value to C<user_table_info>.
2101
+
2102
+=head2 C<helper>
2103
+
2104
+    $dbi->helper(
2105
+        find_or_create   => sub {
2106
+            my $self = shift;
2107
+            
2108
+            # Process
2109
+        },
2110
+        ...
2111
+    );
2112
+
2113
+Register helper. These helper is called directly from L<DBIx::Custom::Next> object.
2114
+
2115
+    $dbi->find_or_create;
2116
+
2117
+=head2 C<insert>
2118
+
2119
+    $dbi->insert({title => 'Perl', author => 'Ken'}, table  => 'book');
2120
+
2121
+Execute insert statement. First argument is row data. Return value is
2122
+affected row count.
2123
+
2124
+If you want to set constant value to row data, use scalar reference
2125
+as parameter value.
2126
+
2127
+    {date => \"NOW()"}
2128
+
2129
+B<options>
2130
+
2131
+C<insert> method use all of C<execute> method's options,
2132
+and use the following new ones.
2133
+
2134
+=over 4
2135
+
2136
+=item C<created_at>
2137
+
2138
+    created_at => 'created_datetime'
2139
+
2140
+Created timestamp column name. time when row is created is set to the column.
2141
+default time format is "YYYY-mm-dd HH:MM:SS", which can be changed by
2142
+C<now> attribute.
2143
+
2144
+=item C<id>
2145
+
2146
+    id => 4
2147
+    id => [4, 5]
2148
+
2149
+ID corresponding to C<primary_key>.
2150
+You can insert a row by C<id> and C<primary_key>.
2151
+
2152
+    $dbi->insert(
2153
+        {title => 'Perl', author => 'Ken'}
2154
+        primary_key => ['id1', 'id2'],
2155
+        id => [4, 5],
2156
+        table => 'book'
2157
+    );
2158
+
2159
+The above is same as the followin one.
2160
+
2161
+    $dbi->insert(
2162
+        {id1 => 4, id2 => 5, title => 'Perl', author => 'Ken'},
2163
+        table => 'book'
2164
+    );
2165
+
2166
+=item C<prefix>
2167
+
2168
+    prefix => 'or replace'
2169
+
2170
+prefix before table name section
2171
+
2172
+    insert or replace into book
2173
+
2174
+=item C<table>
2175
+
2176
+    table => 'book'
2177
+
2178
+Table name.
2179
+
2180
+=item C<updated_at>
2181
+
2182
+This option is same as C<update> method C<updated_at> option.
2183
+
2184
+=item C<wrap>
2185
+
2186
+    wrap => {price => sub { "max($_[0])" }}
2187
+
2188
+placeholder wrapped string.
2189
+
2190
+If the following statement
2191
+
2192
+    $dbi->insert({price => 100}, table => 'book',
2193
+      {price => sub { "$_[0] + 5" }});
2194
+
2195
+is executed, the following SQL is executed.
2196
+
2197
+    insert into book price values ( ? + 5 );
2198
+
2199
+=back
2200
+
2201
+=over 4
2202
+
2203
+=head2 C<include_model>
2204
+
2205
+    $dbi->include_model('MyModel');
2206
+
2207
+Include models from specified namespace,
2208
+the following layout is needed to include models.
2209
+
2210
+    lib / MyModel.pm
2211
+        / MyModel / book.pm
2212
+                  / company.pm
2213
+
2214
+Name space module, extending L<DBIx::Custom::Next::Model>.
2215
+
2216
+B<MyModel.pm>
2217
+
2218
+    package MyModel;
2219
+    use DBIx::Custom::Next::Model -base;
2220
+    
2221
+    1;
2222
+
2223
+Model modules, extending name space module.
2224
+
2225
+B<MyModel/book.pm>
2226
+
2227
+    package MyModel::book;
2228
+    use MyModel -base;
2229
+    
2230
+    1;
2231
+
2232
+B<MyModel/company.pm>
2233
+
2234
+    package MyModel::company;
2235
+    use MyModel -base;
2236
+    
2237
+    1;
2238
+    
2239
+MyModel::book and MyModel::company is included by C<include_model>.
2240
+
2241
+You can get model object by C<model>.
2242
+
2243
+    my $book_model = $dbi->model('book');
2244
+    my $company_model = $dbi->model('company');
2245
+
2246
+See L<DBIx::Custom::Next::Model> to know model features.
2247
+
2248
+=head2 C<like_value>
2249
+
2250
+    my $like_value = $dbi->like_value
2251
+
2252
+Code reference which return a value for the like value.
2253
+
2254
+    sub { "%$_[0]%" }
2255
+
2256
+=head2 C<mapper>
2257
+
2258
+    my $mapper = $dbi->mapper(param => $param);
2259
+
2260
+Create a new L<DBIx::Custom::Next::Mapper> object.
2261
+
2262
+=head2 C<merge_param>
2263
+
2264
+    my $param = $dbi->merge_param({key1 => 1}, {key1 => 1, key2 => 2});
2265
+
2266
+Merge parameters. The following new parameter is created.
2267
+
2268
+    {key1 => [1, 1], key2 => 2}
2269
+
2270
+If same keys contains, the value is converted to array reference.
2271
+
2272
+=head2 C<model>
2273
+
2274
+    my $model = $dbi->model('book');
2275
+
2276
+Get a L<DBIx::Custom::Next::Model> object
2277
+create by C<create_model> or C<include_model>
2278
+
2279
+=head2 C<mycolumn>
2280
+
2281
+    my $column = $dbi->mycolumn(book => ['author', 'title']);
2282
+
2283
+Create column clause for myself. The follwoing column clause is created.
2284
+
2285
+    book.author as author,
2286
+    book.title as title
2287
+
2288
+=head2 C<new>
2289
+
2290
+    my $dbi = DBIx::Custom::Next->new(
2291
+        dsn => "dbi:mysql:database=dbname",
2292
+        user => 'ken',
2293
+        password => '!LFKD%$&',
2294
+        option => {mysql_enable_utf8 => 1}
2295
+    );
2296
+
2297
+Create a new L<DBIx::Custom::Next> object.
2298
+
2299
+=head2 C<not_exists>
2300
+
2301
+    my $not_exists = $dbi->not_exists;
2302
+
2303
+DBIx::Custom::Next::NotExists object, indicating the column is not exists.
2304
+This is used in C<param> of L<DBIx::Custom::Next::Where> .
2305
+
2306
+=head2 C<order>
2307
+
2308
+    my $order = $dbi->order;
2309
+
2310
+Create a new L<DBIx::Custom::Next::Order> object.
2311
+
2312
+=head2 C<q>
2313
+
2314
+    my $quooted = $dbi->q("title");
2315
+
2316
+Quote string by value of C<quote>.
2317
+
2318
+=head2 C<register_filter>
2319
+
2320
+    $dbi->register_filter(
2321
+        # Time::Piece object to database DATE format
2322
+        tp_to_date => sub {
2323
+            my $tp = shift;
2324
+            return $tp->strftime('%Y-%m-%d');
2325
+        },
2326
+        # database DATE format to Time::Piece object
2327
+        date_to_tp => sub {
2328
+           my $date = shift;
2329
+           return Time::Piece->strptime($date, '%Y-%m-%d');
2330
+        }
2331
+    );
2332
+    
2333
+Register filters, used by C<filter> option of many methods.
2334
+
2335
+=head2 C<select>
2336
+
2337
+    my $result = $dbi->select(
2338
+        table  => 'book',
2339
+        column => ['author', 'title'],
2340
+        where  => {author => 'Ken'},
2341
+    );
2342
+    
2343
+Execute select statement.
2344
+
2345
+B<OPTIONS>
2346
+
2347
+C<select> method use all of C<execute> method's options,
2348
+and use the following new ones.
2349
+
2350
+=over 4
2351
+
2352
+=item C<column>
2353
+    
2354
+    column => 'author'
2355
+    column => ['author', 'title']
2356
+
2357
+Column clause.
2358
+    
2359
+if C<column> is not specified, '*' is set.
2360
+
2361
+    column => '*'
2362
+
2363
+You can specify hash of array reference.
2364
+
2365
+    column => [
2366
+        {book => [qw/author title/]},
2367
+        {person => [qw/name age/]}
2368
+    ]
2369
+
2370
+This is expanded to the following one by using C<colomn> method.
2371
+
2372
+    book.author as "book.author",
2373
+    book.title as "book.title",
2374
+    person.name as "person.name",
2375
+    person.age as "person.age"
2376
+
2377
+You can specify array of array reference, first argument is
2378
+column name, second argument is alias.
2379
+
2380
+    column => [
2381
+        ['date(book.register_datetime)' => 'book.register_date']
2382
+    ];
2383
+
2384
+Alias is quoted properly and joined.
2385
+
2386
+    date(book.register_datetime) as "book.register_date"
2387
+
2388
+=item C<id>
2389
+
2390
+    id => 4
2391
+    id => [4, 5]
2392
+
2393
+ID corresponding to C<primary_key>.
2394
+You can select rows by C<id> and C<primary_key>.
2395
+
2396
+    $dbi->select(
2397
+        primary_key => ['id1', 'id2'],
2398
+        id => [4, 5],
2399
+        table => 'book'
2400
+    );
2401
+
2402
+The above is same as the followin one.
2403
+
2404
+    $dbi->select(
2405
+        where => {id1 => 4, id2 => 5},
2406
+        table => 'book'
2407
+    );
2408
+    
2409
+=item C<param>
2410
+
2411
+    param => {'table2.key3' => 5}
2412
+
2413
+Parameter shown before where clause.
2414
+    
2415
+For example, if you want to contain tag in join clause, 
2416
+you can pass parameter by C<param> option.
2417
+
2418
+    join  => ['inner join (select * from table2 where table2.key3 = :table2.key3)' . 
2419
+              ' as table2 on table1.key1 = table2.key1']
2420
+
2421
+=itme C<prefix>
2422
+
2423
+    prefix => 'SQL_CALC_FOUND_ROWS'
2424
+
2425
+Prefix of column cluase
2426
+
2427
+    select SQL_CALC_FOUND_ROWS title, author from book;
2428
+
2429
+=item C<join>
2430
+
2431
+    join => [
2432
+        'left outer join company on book.company_id = company_id',
2433
+        'left outer join location on company.location_id = location.id'
2434
+    ]
2435
+        
2436
+Join clause. If column cluase or where clause contain table name like "company.name",
2437
+join clausees needed when SQL is created is used automatically.
2438
+
2439
+    $dbi->select(
2440
+        table => 'book',
2441
+        column => ['company.location_id as location_id'],
2442
+        where => {'company.name' => 'Orange'},
2443
+        join => [
2444
+            'left outer join company on book.company_id = company.id',
2445
+            'left outer join location on company.location_id = location.id'
2446
+        ]
2447
+    );
2448
+
2449
+In above select, column and where clause contain "company" table,
2450
+the following SQL is created
2451
+
2452
+    select company.location_id as location_id
2453
+    from book
2454
+      left outer join company on book.company_id = company.id
2455
+    where company.name = ?;
2456
+
2457
+You can specify two table by yourself. This is useful when join parser can't parse
2458
+the join clause correctly.
2459
+
2460
+    $dbi->select(
2461
+        table => 'book',
2462
+        column => ['company.location_id as location_id'],
2463
+        where => {'company.name' => 'Orange'},
2464
+        join => [
2465
+            {
2466
+                clause => 'left outer join location on company.location_id = location.id',
2467
+                table => ['company', 'location']
2468
+            }
2469
+        ]
2470
+    );
2471
+
2472
+=item C<table>
2473
+
2474
+    table => 'book'
2475
+
2476
+Table name.
2477
+
2478
+=item C<where>
2479
+    
2480
+    # Hash refrence
2481
+    where => {author => 'Ken', 'title' => 'Perl'}
2482
+    
2483
+    # DBIx::Custom::Next::Where object
2484
+    where => $dbi->where(
2485
+        clause => ['and', ':author{=}', ':title{like}'],
2486
+        param  => {author => 'Ken', title => '%Perl%'}
2487
+    );
2488
+    
2489
+    # Array reference, this is same as above
2490
+    where => [
2491
+        ['and', ':author{=}', ':title{like}'],
2492
+        {author => 'Ken', title => '%Perl%'}
2493
+    ];
2494
+    
2495
+    # String
2496
+    where => 'title is null'
2497
+
2498
+Where clause. See L<DBIx::Custom::Next::Where>.
2499
+    
2500
+=back
2501
+
2502
+=head2 C<setup_model>
2503
+
2504
+    $dbi->setup_model;
2505
+
2506
+Setup all model objects.
2507
+C<columns> of model object is automatically set, parsing database information.
2508
+
2509
+=head2 C<type_rule>
2510
+
2511
+    $dbi->type_rule(
2512
+        into1 => {
2513
+            date => sub { ... },
2514
+            datetime => sub { ... }
2515
+        },
2516
+        into2 => {
2517
+            date => sub { ... },
2518
+            datetime => sub { ... }
2519
+        },
2520
+        from1 => {
2521
+            # DATE
2522
+            9 => sub { ... },
2523
+            # DATETIME or TIMESTAMP
2524
+            11 => sub { ... },
2525
+        }
2526
+        from2 => {
2527
+            # DATE
2528
+            9 => sub { ... },
2529
+            # DATETIME or TIMESTAMP
2530
+            11 => sub { ... },
2531
+        }
2532
+    );
2533
+
2534
+Filtering rule when data is send into and get from database.
2535
+This has a little complex problem.
2536
+
2537
+In C<into1> and C<into2> you can specify
2538
+type name as same as type name defined
2539
+by create table, such as C<DATETIME> or C<DATE>.
2540
+
2541
+Note that type name and data type don't contain upper case.
2542
+If these contain upper case charactor, you convert it to lower case.
2543
+
2544
+C<into2> is executed after C<into1>.
2545
+
2546
+Type rule of C<into1> and C<into2> is enabled on the following
2547
+column name.
2548
+
2549
+=over 4
2550
+
2551
+=item 1. column name
2552
+
2553
+    issue_date
2554
+    issue_datetime
2555
+
2556
+This need C<table> option in each method.
2557
+
2558
+=item 2. table name and column name, separator is dot
2559
+
2560
+    book.issue_date
2561
+    book.issue_datetime
2562
+
2563
+=back
2564
+
2565
+You get all type name used in database by C<available_typename>.
2566
+
2567
+    print $dbi->available_typename;
2568
+
2569
+In C<from1> and C<from2> you specify data type, not type name.
2570
+C<from2> is executed after C<from1>.
2571
+You get all data type by C<available_datatype>.
2572
+
2573
+    print $dbi->available_datatype;
2574
+
2575
+You can also specify multiple types at once.
2576
+
2577
+    $dbi->type_rule(
2578
+        into1 => [
2579
+            [qw/DATE DATETIME/] => sub { ... },
2580
+        ],
2581
+    );
2582
+
2583
+=head2 C<update>
2584
+
2585
+    $dbi->update({title => 'Perl'}, table  => 'book', where  => {id => 4});
2586
+
2587
+Execute update statement. First argument is update row data.
2588
+
2589
+If you want to set constant value to row data, use scalar reference
2590
+as parameter value.
2591
+
2592
+    {date => \"NOW()"}
2593
+
2594
+B<OPTIONS>
2595
+
2596
+C<update> method use all of C<execute> method's options,
2597
+and use the following new ones.
2598
+
2599
+=over 4
2600
+
2601
+=item C<id>
2602
+
2603
+    id => 4
2604
+    id => [4, 5]
2605
+
2606
+ID corresponding to C<primary_key>.
2607
+You can update rows by C<id> and C<primary_key>.
2608
+
2609
+    $dbi->update(
2610
+        {title => 'Perl', author => 'Ken'}
2611
+        primary_key => ['id1', 'id2'],
2612
+        id => [4, 5],
2613
+        table => 'book'
2614
+    );
2615
+
2616
+The above is same as the followin one.
2617
+
2618
+    $dbi->update(
2619
+        {title => 'Perl', author => 'Ken'}
2620
+        where => {id1 => 4, id2 => 5},
2621
+        table => 'book'
2622
+    );
2623
+
2624
+=item C<prefix>
2625
+
2626
+    prefix => 'or replace'
2627
+
2628
+prefix before table name section
2629
+
2630
+    update or replace book
2631
+
2632
+=item C<table>
2633
+
2634
+    table => 'book'
2635
+
2636
+Table name.
2637
+
2638
+=item C<where>
2639
+
2640
+Same as C<select> method's C<where> option.
2641
+
2642
+=item C<wrap>
2643
+
2644
+    wrap => {price => sub { "max($_[0])" }}
2645
+
2646
+placeholder wrapped string.
2647
+
2648
+If the following statement
2649
+
2650
+    $dbi->update({price => 100}, table => 'book',
2651
+      {price => sub { "$_[0] + 5" }});
2652
+
2653
+is executed, the following SQL is executed.
2654
+
2655
+    update book set price =  ? + 5;
2656
+
2657
+=item C<updated_at>
2658
+
2659
+    updated_at => 'updated_datetime'
2660
+
2661
+Updated timestamp column name. time when row is updated is set to the column.
2662
+default time format is C<YYYY-mm-dd HH:MM:SS>, which can be changed by
2663
+C<now> attribute.
2664
+
2665
+=back
2666
+
2667
+=head2 C<update_all>
2668
+
2669
+    $dbi->update_all({title => 'Perl'}, table => 'book', );
2670
+
2671
+Execute update statement for all rows.
2672
+Options is same as C<update> method.
2673
+
2674
+=head2 C<update_or_insert>
2675
+    
2676
+    # ID
2677
+    $dbi->update_or_insert(
2678
+        {title => 'Perl'},
2679
+        table => 'book',
2680
+        id => 1,
2681
+        primary_key => 'id',
2682
+        option => {
2683
+            select => {
2684
+                 append => 'for update'
2685
+            }
2686
+        }
2687
+    );
2688
+
2689
+Update or insert.
2690
+
2691
+C<update_or_insert> method execute C<select> method first to find row.
2692
+If the row is exists, C<update> is executed.
2693
+If not, C<insert> is executed.
2694
+
2695
+C<OPTIONS>
2696
+
2697
+C<update_or_insert> method use all common option
2698
+in C<select>, C<update>, C<delete>, and has the following new ones.
2699
+
2700
+=over 4
2701
+
2702
+=item C<option>
2703
+
2704
+    option => {
2705
+        select => {
2706
+            append => '...'
2707
+        },
2708
+        insert => {
2709
+            prefix => '...'
2710
+        },
2711
+        update => {
2712
+            filter => {}
2713
+        }
2714
+    }
2715
+
2716
+If you want to pass option to each method,
2717
+you can use C<option> option.
2718
+
2719
+=over 4
2720
+
2721
+=item C<select_option>
2722
+
2723
+    select_option => {append => 'for update'}
2724
+
2725
+select method option,
2726
+select method is used to check the row is already exists.
2727
+
2728
+=head2 C<show_datatype>
2729
+
2730
+    $dbi->show_datatype($table);
2731
+
2732
+Show data type of the columns of specified table.
2733
+
2734
+    book
2735
+    title: 5
2736
+    issue_date: 91
2737
+
2738
+This data type is used in C<type_rule>'s C<from1> and C<from2>.
2739
+
2740
+=head2 C<show_tables>
2741
+
2742
+    $dbi->show_tables;
2743
+
2744
+Show tables.
2745
+
2746
+=head2 C<show_typename>
2747
+
2748
+    $dbi->show_typename($table);
2749
+
2750
+Show type name of the columns of specified table.
2751
+
2752
+    book
2753
+    title: varchar
2754
+    issue_date: date
2755
+
2756
+This type name is used in C<type_rule>'s C<into1> and C<into2>.
2757
+
2758
+=head2 C<values_clause>
2759
+
2760
+    my $values_clause = $dbi->values_clause({title => 'a', age => 2});
2761
+
2762
+Create values clause.
2763
+
2764
+    (title, author) values (title = :title, age = :age);
2765
+
2766
+You can use this in insert statement.
2767
+
2768
+    my $insert_sql = "insert into book $values_clause";
2769
+
2770
+=head2 C<where>
2771
+
2772
+    my $where = $dbi->where(
2773
+        clause => ['and', 'title = :title', 'author = :author'],
2774
+        param => {title => 'Perl', author => 'Ken'}
2775
+    );
2776
+
2777
+Create a new L<DBIx::Custom::Next::Where> object.
2778
+
2779
+=head1 ENVIRONMENTAL VARIABLES
2780
+
2781
+=head2 C<DBIX_CUSTOM_DEBUG>
2782
+
2783
+If environment variable C<DBIX_CUSTOM_DEBUG> is set to true,
2784
+executed SQL and bind values are printed to STDERR.
2785
+
2786
+=head2 C<DBIX_CUSTOM_DEBUG_ENCODING>
2787
+
2788
+DEBUG output encoding. Default to UTF-8.
2789
+
2790
+=head1 BUGS
2791
+
2792
+Please tell me bugs if found.
2793
+
2794
+C<< <kimoto.yuki at gmail.com> >>
2795
+
2796
+L<http://github.com/yuki-kimoto/DBIx-Custom>
2797
+
2798
+=head1 AUTHOR
2799
+
2800
+Yuki Kimoto, C<< <kimoto.yuki at gmail.com> >>
2801
+
2802
+=head1 COPYRIGHT & LICENSE
2803
+
2804
+Copyright 2009-2011 Yuki Kimoto, all rights reserved.
2805
+
2806
+This program is free software; you can redistribute it and/or modify it
2807
+under the same terms as Perl itself.
2808
+
2809
+=cut
+249
lib/DBIx/Custom/Next/Mapper.pm
... ...
@@ -0,0 +1,249 @@
1
+package DBIx::Custom::Next::Mapper;
2
+use Object::Simple -base;
3
+
4
+use DBIx::Custom::Next::NotExists;
5
+
6
+use Carp 'croak';
7
+use DBIx::Custom::Next::Util '_subname';
8
+
9
+# Carp trust relationship
10
+push @DBIx::Custom::Next::CARP_NOT, __PACKAGE__;
11
+
12
+has [qw/param/],
13
+    condition => sub {
14
+        sub { defined $_[0] && length $_[0] }
15
+    },
16
+    pass => sub { [] };
17
+
18
+sub map {
19
+    my ($self, %rule) = @_;
20
+    my $param = $self->param;
21
+    $rule{$_} = {key => $_} for @{$self->pass};
22
+    
23
+    # Mapping
24
+    my $new_param = {};
25
+    for my $key (keys %rule) {
26
+        
27
+        my $mapping = $rule{$key};
28
+        
29
+        # Get mapping information
30
+        my $new_key;
31
+        my $value;
32
+        my $condition;
33
+        
34
+        if (ref $mapping eq 'ARRAY') {
35
+            $new_key = $mapping->[0];
36
+            $value = $mapping->[1];
37
+            $condition = ref $mapping->[2] eq 'HASH' ? $mapping->[2]->{condition} : $mapping->[2];
38
+        }
39
+        elsif (ref $mapping eq 'HASH') {
40
+            $new_key = $mapping->{key};
41
+            $value = $mapping->{value};
42
+            $condition = $mapping->{condition};
43
+        }
44
+        
45
+        $new_key = $key unless defined $new_key;
46
+        $condition ||= $self->condition;
47
+        $condition = $self->_condition_to_sub($condition);
48
+
49
+        # Map parameter
50
+        if (ref $condition eq 'CODE') {
51
+            if (ref $param->{$key} eq 'ARRAY') {
52
+                $new_param->{$new_key} = [];
53
+                for (my $i = 0; $i < @{$param->{$key}}; $i++) {
54
+                    $new_param->{$new_key}->[$i]
55
+                      = $condition->($param->{$key}->[$i]) ? $param->{$key}->[$i]
56
+                      : DBIx::Custom::Next::NotExists->singleton;
57
+                }
58
+            }
59
+            else {
60
+              if ($condition->($param->{$key})) {
61
+                  $new_param->{$new_key} = defined $value
62
+                                         ? $value->($param->{$key})
63
+                                         : $param->{$key};
64
+              }
65
+            }
66
+        }
67
+        elsif ($condition eq 'exists') {
68
+            if (ref $param->{$key} eq 'ARRAY') {
69
+                $new_param->{$new_key} = [];
70
+                for (my $i = 0; $i < @{$param->{$key}}; $i++) {
71
+                    $new_param->{$new_key}->[$i]
72
+                      = exists $param->{$key}->[$i] ? $param->{$key}->[$i]
73
+                      : DBIx::Custom::Next::NotExists->singleton;
74
+                }
75
+            }
76
+            else {
77
+                if (exists $param->{$key}) {
78
+                    $new_param->{$new_key} = defined $value
79
+                                           ? $value->($param->{$key})
80
+                                           : $param->{$key};
81
+                }
82
+            }
83
+        }
84
+        else { croak qq/Condition must be code reference or "exists" / . _subname }
85
+    }
86
+    
87
+    return $new_param;
88
+}
89
+
90
+sub new {
91
+    my $self = shift->SUPER::new(@_);
92
+    
93
+    # Check attribute names
94
+    my @attrs = keys %$self;
95
+    for my $attr (@attrs) {
96
+        croak qq{"$attr" is invalid attribute name (} . _subname . ")"
97
+          unless $self->can($attr);
98
+    }
99
+    
100
+    return $self;
101
+}
102
+
103
+
104
+sub _condition_to_sub {
105
+    my ($self, $if) = @_;
106
+    $if = $if eq 'exists' ? $if
107
+            : $if eq 'defined' ? sub { defined $_[0] }
108
+            : $if eq 'length'  ? sub { defined $_[0] && length $_[0] }
109
+            : ref $if eq 'CODE' ? $if
110
+            : undef;
111
+
112
+    croak "You can must specify right value to C<condition> " . _subname
113
+      unless $if;
114
+    
115
+    return $if;
116
+}
117
+
118
+1;
119
+
120
+=head1 NAME
121
+
122
+DBIx::Custom::Next::Mapper - Mapper of parameter
123
+
124
+=head1 SYNOPSYS
125
+
126
+    my $mapper = $dbi->mapper(param => $param);
127
+    my $new_param = $mapper->map(
128
+        title => 'book.title', # Key
129
+        author => sub { '%' . $_[0] . '%'} # Value
130
+        price => ['book.price' => sub { '%' . $_[0] . '%' }], # Key and value
131
+    );
132
+
133
+=head1 ATTRIBUTES
134
+
135
+=head2 C<param>
136
+
137
+    my $param = $mapper->param;
138
+    $mapper = $mapper->param({title => 'Perl', author => 'Ken'});
139
+
140
+Parameter.
141
+
142
+=head2 C<pass>
143
+
144
+    my $pass = $mapper->pass;
145
+    $mapper = $mapper->pass([qw/title author/]);
146
+
147
+the key and value is copied without change when C<map> method is executed.
148
+
149
+=head2 C<condition>
150
+
151
+    my $condition = $mapper->condition;
152
+    $mapper = $mapper->condition('exists');
153
+
154
+Mapping condtion, default to C<length>.
155
+
156
+You can set the following values to C<condition>.
157
+
158
+=over 4
159
+
160
+=item * C<exists>
161
+   
162
+    condition => 'exists'
163
+
164
+If key exists, key and value is mapped.
165
+
166
+=item * C<defined>
167
+
168
+    condition => 'defined';
169
+
170
+If value is defined, key and value is mapped.
171
+
172
+=item * C<length>
173
+
174
+    condition => 'length';
175
+
176
+If value is defined and has length, key and value is mapped.
177
+
178
+=item * C<code reference>
179
+
180
+    condition => sub { defined $_[0] }
181
+
182
+You can set code reference to C<condtion>.
183
+The subroutine return true, key and value is mapped.
184
+
185
+=head1 METHODS
186
+
187
+L<DBIx::Custom::Next::Mapper> inherits all methods from L<Object::Simple>
188
+and implements the following new ones.
189
+
190
+=head2 C<map>
191
+
192
+    my $new_param = $mapper->map(
193
+        price => {key => 'book.price'}
194
+        title => {value => sub { '%' . $_[0] . '%'}}
195
+        author => ['book.author' => sub { '%' . $_[0] . '%'}] # Key and value
196
+    );
197
+
198
+Map C<param> into new parameter.
199
+
200
+For example, if C<param> is set to
201
+
202
+    {
203
+        price => 1900,
204
+        title => 'Perl',
205
+        author => 'Ken',
206
+        issue_date => '2010-11-11'
207
+    }
208
+
209
+The following hash reference is returned.
210
+
211
+    {
212
+        'book.price' => 1900,
213
+        title => '%Perl%',
214
+        'book.author' => '%Ken%',
215
+    }
216
+
217
+By default, If the value has length, key and value is mapped.
218
+
219
+    title => 'Perl'  # Mapped
220
+    {title => '' }   # Not mapped
221
+    {title => undef} # Not mapped
222
+    {}               # Not mapped
223
+
224
+You can set change mapping condition by C<condition> attribute.
225
+
226
+    $mapper->condition('defined');
227
+
228
+Or you can set C<condtion> option for each key.
229
+
230
+    my $new_param = $mapper->map(
231
+        price => {key => 'book.price', condition => 'defined'}]
232
+        title => {value => sub { '%' . $_[0] . '%'}, condition => 'defined'}
233
+        author => ['book.author', sub { '%' . $_[0] . '%'}, 'exists']
234
+    );
235
+
236
+If C<pass> attrivute is set, the keys and value is copied without change.
237
+
238
+    $mapper->pass([qw/title author/]);
239
+    my $new_param = $mapper->map(price => {key => 'book.price'});
240
+
241
+The following hash reference
242
+    
243
+    {title => 'Perl', author => 'Ken', price => 1900}
244
+
245
+is mapped to
246
+
247
+    {title => 'Perl', author => 'Ken', 'book.price' => 1900}
248
+
249
+=cut
+302
lib/DBIx/Custom/Next/Model.pm
... ...
@@ -0,0 +1,302 @@
1
+package DBIx::Custom::Next::Model;
2
+use Object::Simple -base;
3
+
4
+use Carp 'croak';
5
+use DBIx::Custom::Next::Util '_subname';
6
+
7
+# Carp trust relationship
8
+push @DBIx::Custom::Next::CARP_NOT, __PACKAGE__;
9
+
10
+has [qw/dbi table created_at updated_at bind_type join primary_key/],
11
+    columns => sub { [] };
12
+
13
+our $AUTOLOAD;
14
+
15
+sub AUTOLOAD {
16
+    my $self = shift;
17
+
18
+    # Method name
19
+    my ($package, $mname) = $AUTOLOAD =~ /^([\w\:]+)\:\:(\w+)$/;
20
+
21
+    # Method
22
+    $self->{_methods} ||= {};
23
+    if (my $method = $self->{_methods}->{$mname}) {
24
+        return $self->$method(@_)
25
+    }
26
+    elsif (my $dbi_method = $self->dbi->can($mname)) {
27
+        $self->dbi->$dbi_method(@_);
28
+    }
29
+    elsif ($self->{dbh} && (my $dbh_method = $self->dbh->can($mname))) {
30
+        $self->dbi->dbh->$dbh_method(@_);
31
+    }
32
+    else {
33
+        croak qq{Can't locate object method "$mname" via "$package" }
34
+            . _subname;
35
+    }
36
+}
37
+
38
+my @methods = qw/insert update update_all delete delete_all select count/;
39
+for my $method (@methods) {
40
+    
41
+    my $code =
42
+         qq/sub {/ .
43
+         qq/my \$self = shift;/ .
44
+         qq/\$self->dbi->$method(/;
45
+    
46
+    $code .= qq/shift,/
47
+      if $method eq  'insert' || $method eq 'update' || $method eq 'update_all';
48
+    
49
+    my @attrs = qw/table primary_key bind_type/;
50
+    my @insert_attrs = qw/created_at updated_at/;
51
+    my @update_attrs = qw/updated_at/;
52
+    my @select_attrs = qw/join/;
53
+    if ($method eq 'insert') { push @attrs, @insert_attrs }
54
+    elsif ($method eq 'update') { push @attrs, @update_attrs }
55
+    elsif (index($method, 'select') != -1) { push @attrs, @select_attrs }
56
+    
57
+    for my $attr (@attrs) {
58
+        $code .= "exists \$self->{$attr} ? ($attr => \$self->{$attr}) : (),";
59
+    }
60
+    
61
+    $code .= qq/\@_);/ .
62
+         qq/}/;
63
+    
64
+    no strict 'refs';
65
+    *{__PACKAGE__ . "::$method"} = eval $code;
66
+    croak $code if $@;
67
+}
68
+
69
+sub update_or_insert {
70
+    my ($self, $param, %opt) = @_;
71
+    
72
+    croak "update_or_insert method need primary_key and id option "
73
+      unless (defined $opt{id} || defined $self->{id})
74
+          && (defined $opt{primary_key} || defined $self->{primary_key});
75
+    
76
+    my $statement_opt = $opt{option} || {};
77
+    my $rows = $self->select(%opt, %{$statement_opt->{select} || {}})->all;
78
+    if (@$rows == 0) {
79
+        return $self->insert($param, %opt, %{$statement_opt->{insert} || {}});
80
+    }
81
+    elsif (@$rows == 1) {
82
+        return $self->update($param, %opt, %{$statement_opt->{update} || {}});
83
+    }
84
+    else {
85
+        croak "selected row must be one " . _subname;
86
+    }
87
+}
88
+
89
+sub DESTROY { }
90
+
91
+sub helper {
92
+    my $self = shift;
93
+    
94
+    # Merge
95
+    my $methods = ref $_[0] eq 'HASH' ? $_[0] : {@_};
96
+    $self->{_methods} = {%{$self->{_methods} || {}}, %$methods};
97
+    
98
+    return $self;
99
+}
100
+
101
+sub mycolumn {
102
+    my $self = shift;
103
+    my $table = shift unless ref $_[0];
104
+    my $columns = shift;
105
+    
106
+    $table ||= $self->table || '';
107
+    $columns ||= $self->columns;
108
+    
109
+    return $self->dbi->mycolumn($table, $columns);
110
+}
111
+
112
+sub new {
113
+    my $self = shift->SUPER::new(@_);
114
+    
115
+    # Check attribute names
116
+    my @attrs = keys %$self;
117
+    for my $attr (@attrs) {
118
+        croak qq{"$attr" is invalid attribute name } . _subname
119
+          unless $self->can($attr);
120
+    }
121
+    
122
+    # Cache
123
+    for my $attr (qw/dbi table created_at updated_at bind_type join primary_key/) {
124
+        $self->$attr;
125
+        $self->{$attr} = undef unless exists $self->{$attr};
126
+    }
127
+    $self->columns;
128
+    
129
+    return $self;
130
+}
131
+
132
+1;
133
+
134
+=head1 NAME
135
+
136
+DBIx::Custom::Next::Model - Model
137
+
138
+=head1 SYNOPSIS
139
+
140
+use DBIx::Custom::Next::Model;
141
+
142
+my $model = DBIx::Custom::Next::Model->new(table => 'books');
143
+
144
+=head1 ATTRIBUTES
145
+
146
+=head2 C<dbi>
147
+
148
+    my $dbi = $model->dbi;
149
+    $model = $model->dbi($dbi);
150
+
151
+L<DBIx::Custom::Next> object.
152
+
153
+=head2 C<created_at EXPERIMENTAL>
154
+
155
+    my $created_at = $model->created_at;
156
+    $model = $model->created_at('created_datatime');
157
+
158
+Create timestamp column, this is passed to C<insert> or C<update> method.
159
+
160
+=head2 C<join>
161
+
162
+    my $join = $model->join;
163
+    $model = $model->join(
164
+        ['left outer join company on book.company_id = company.id']
165
+    );
166
+    
167
+Join clause, this value is passed to C<select> method.
168
+
169
+=head2 C<primary_key>
170
+
171
+    my $primary_key = $model->primary_key;
172
+    $model = $model->primary_key(['id', 'number']);
173
+
174
+Primary key,this is passed to C<insert>, C<update>,
175
+C<delete>, and C<select> method.
176
+
177
+=head2 C<table>
178
+
179
+    my $model = $model->table;
180
+    $model = $model->table('book');
181
+
182
+Table name, this is passed to C<select> method.
183
+
184
+=head2 C<bind_type>
185
+
186
+    my $type = $model->bind_type;
187
+    $model = $model->bind_type(['image' => DBI::SQL_BLOB]);
188
+    
189
+Database data type, this is used as type optioon of C<insert>, 
190
+C<update>, C<update_all>, C<delete>, C<delete_all>,
191
+and C<select> method
192
+
193
+=head2 C<updated_at EXPERIMENTAL>
194
+
195
+    my $updated_at = $model->updated_at;
196
+    $model = $model->updated_at('updated_datatime');
197
+
198
+Updated timestamp column, this is passed to C<update> method.
199
+
200
+=head1 METHODS
201
+
202
+L<DBIx::Custom::Next::Model> inherits all methods from L<Object::Simple>,
203
+and you can use all methods of L<DBIx::Custom::Next> and L<DBI>
204
+and implements the following new ones.
205
+
206
+=head2 C<count>
207
+
208
+    my $count = $model->count;
209
+
210
+Get rows count.
211
+
212
+Options is same as C<select> method's ones.
213
+
214
+=head2 C<delete>
215
+
216
+    $model->delete(...);
217
+    
218
+Same as C<delete> of L<DBIx::Custom::Next> except that
219
+you don't have to specify options if you set attribute in model.
220
+
221
+=head2 C<delete_all>
222
+
223
+    $model->delete_all(...);
224
+    
225
+Same as C<delete_all> of L<DBIx::Custom::Next> except that
226
+you don't have to specify options if you set attribute in model.
227
+
228
+=head2 C<insert>
229
+
230
+    $model->insert(...);
231
+    
232
+Same as C<insert> of L<DBIx::Custom::Next> except that
233
+you don't have to specify options if you set attribute in model.
234
+
235
+=head2 C<helper>
236
+
237
+    $model->helper(
238
+        update_or_insert => sub {
239
+            my $self = shift;
240
+            
241
+            # ...
242
+        },
243
+        find_or_create   => sub {
244
+            my $self = shift;
245
+            
246
+            # ...
247
+    );
248
+
249
+Register helper. These helper is called directly from L<DBIx::Custom::Next::Model> object.
250
+
251
+    $model->update_or_insert;
252
+    $model->find_or_create;
253
+
254
+=head2 C<mycolumn>
255
+
256
+    my $column = $self->mycolumn;
257
+    my $column = $self->mycolumn(book => ['author', 'title']);
258
+    my $column = $self->mycolumn(['author', 'title']);
259
+
260
+Create column clause for myself. The follwoing column clause is created.
261
+
262
+    book.author as author,
263
+    book.title as title
264
+
265
+If table name is ommited, C<table> attribute of the model is used.
266
+If column names is omitted, C<columns> attribute of the model is used.
267
+
268
+=head2 C<new>
269
+
270
+    my $model = DBIx::Custom::Next::Model->new;
271
+
272
+Create a L<DBIx::Custom::Next::Model> object.
273
+
274
+=head2 C<select>
275
+
276
+    $model->select(...);
277
+    
278
+Same as C<select> of L<DBIx::Custom::Next> except that
279
+you don't have to specify options if you set attribute in model.
280
+
281
+=head2 C<update>
282
+
283
+    $model->update(...);
284
+    
285
+Same as C<update> of L<DBIx::Custom::Next> except that
286
+you don't have to specify options if you set attribute in model.
287
+
288
+=head2 C<update_all>
289
+
290
+    $model->update_all(param => \%param);
291
+    
292
+Same as C<update_all> of L<DBIx::Custom::Next> except that
293
+you don't have to specify options if you set attribute in model.
294
+
295
+=head2 C<update_or_insert>
296
+
297
+    $model->update_or_insert(...);
298
+    
299
+Same as C<update> of L<DBIx::Custom::Next> except that
300
+you don't have to specify options if you set attribute in model.
301
+
302
+=cut
+26
lib/DBIx/Custom/Next/NotExists.pm
... ...
@@ -0,0 +1,26 @@
1
+package DBIx::Custom::Next::NotExists;
2
+
3
+use strict;
4
+use warnings;
5
+
6
+my $not_exists = bless {}, 'DBIx::Custom::Next::NotExists';
7
+
8
+sub singleton { $not_exists }
9
+
10
+=head1 NAME
11
+
12
+DBIx::Custom::Next::NotExists
13
+
14
+=head1 SYNOPSYS
15
+
16
+    $not_exists = DBIx::Custom::Next::NotExists->singleton;
17
+
18
+=head1 METHODS
19
+
20
+=head2 C<singleton>
21
+
22
+    $not_exists = DBIx::Custom::Next::NotExists->singleton;
23
+
24
+L<DBIx::Custom::Next::NotExists> singleton object.
25
+
26
+=cut
+89
lib/DBIx/Custom/Next/Order.pm
... ...
@@ -0,0 +1,89 @@
1
+package DBIx::Custom::Next::Order;
2
+use Object::Simple -base;
3
+use overload
4
+  'bool'   => sub {1},
5
+  '""'     => sub { shift->to_string },
6
+  fallback => 1;
7
+
8
+has 'dbi',
9
+    orders => sub { [] };
10
+
11
+sub prepend {
12
+    my $self = shift;
13
+    
14
+    for my $order (reverse @_) {
15
+        unshift @{$self->orders}, $order;
16
+    }
17
+    
18
+    return $self;
19
+}
20
+
21
+sub to_string {
22
+    my $self = shift;
23
+    
24
+    my $exists = {};
25
+    my @orders;
26
+    for my $order (@{$self->orders}) {
27
+        next unless defined $order;
28
+        $order =~ s/^\s+//;
29
+        $order =~ s/\s+$//;
30
+        my ($column, $direction) = split /\s+/, $order;
31
+        push @orders, $order unless $exists->{$column};
32
+        $exists->{$column} = 1;
33
+    }
34
+    
35
+    return '' unless @orders;
36
+    return 'order by ' . join(', ', @orders);
37
+}
38
+
39
+1;
40
+
41
+=head1 NAME
42
+
43
+DBIx::Custom::Next::Order - Order by
44
+
45
+=head1 SYNOPSIS
46
+
47
+    # Result
48
+    my $order = DBIx::Custom::Next::Order->new;
49
+    $order->prepend('title', 'author desc');
50
+    my $order_by = "$order";
51
+    
52
+=head1 ATTRIBUTES
53
+
54
+=head2 C<dbi>
55
+
56
+    my $dbi = $order->dbi;
57
+    $order = $order->dbi($dbi);
58
+
59
+L<DBIx::Custom::Next> object.
60
+
61
+=head2 C<orders>
62
+
63
+    my $orders = $result->orders;
64
+    $result = $result->orders(\%orders);
65
+
66
+Parts of order by clause
67
+
68
+=head1 METHODS
69
+
70
+L<DBIx::Custom::Next::Result> inherits all methods from L<Object::Simple>
71
+and implements the following new ones.
72
+
73
+=head2 C<prepend>
74
+
75
+    $order->prepend('title', 'author desc');
76
+
77
+Prepend order parts to C<orders>.
78
+
79
+=head2 C<to_string>
80
+
81
+    my $order_by = $order->to_string;
82
+
83
+Create order by clause. If column name is duplicated, First one is used.
84
+C<to_string> override stringification. so you can write the follwoing way.
85
+
86
+    my $order_by = "$order";
87
+
88
+=cut
89
+
+505
lib/DBIx/Custom/Next/Result.pm
... ...
@@ -0,0 +1,505 @@
1
+package DBIx::Custom::Next::Result;
2
+use Object::Simple -base;
3
+
4
+use Carp 'croak';
5
+use DBIx::Custom::Next::Util qw/_array_to_hash _subname/;
6
+
7
+has [qw/dbi sth/],
8
+    stash => sub { {} };
9
+
10
+*all = \&fetch_hash_all;
11
+
12
+sub filter {
13
+    my $self = shift;
14
+    
15
+    # Set
16
+    if (@_) {
17
+        
18
+        # Convert filter name to subroutine
19
+        my $filter = @_ == 1 ? $_[0] : [@_];
20
+        $filter = _array_to_hash($filter);
21
+        for my $column (keys %$filter) {
22
+            my $fname = $filter->{$column};
23
+            if  (exists $filter->{$column}
24
+              && defined $fname
25
+              && ref $fname ne 'CODE') 
26
+            {
27
+              croak qq{Filter "$fname" is not registered" } . _subname
28
+                unless exists $self->dbi->filters->{$fname};
29
+              $filter->{$column} = $self->dbi->filters->{$fname};
30
+            }
31
+        }
32
+        
33
+        # Merge
34
+        $self->{filter} = {%{$self->filter}, %$filter};
35
+        
36
+        return $self;
37
+    }
38
+    
39
+    return $self->{filter} ||= {};
40
+}
41
+
42
+sub fetch {
43
+    my $self = shift;
44
+    
45
+    # Info
46
+    $self->_cache unless $self->{_cache};
47
+    
48
+    # Fetch
49
+    my @row = $self->{sth}->fetchrow_array;
50
+    return unless @row;
51
+    
52
+    # Type rule
53
+    if ($self->{type_rule}->{from1} && !$self->{type_rule_off} && !$self->{type_rule1_off}) {
54
+        my $from = $self->{type_rule}->{from1};
55
+        for my $type (keys %$from) {
56
+            for my $column (@{$self->{_type_map}->{$type}}) {
57
+                $row[$_] = $from->{$type}->($row[$_])
58
+                  for @{$self->{_pos}{$column} || []};
59
+            }
60
+        }
61
+    }
62
+    if ($self->{type_rule}->{from2} && !$self->{type_rule_off} && !$self->{type_rule2_off}) {
63
+        my $from = $self->{type_rule}->{from2};
64
+        for my $type (keys %$from) {
65
+            for my $column (@{$self->{_type_map}->{$type}}) {
66
+                $row[$_] = $from->{$type}->($row[$_])
67
+                  for @{$self->{_pos}{$column} || []};
68
+            }
69
+        }
70
+    }
71
+    
72
+    # Filter
73
+    if ($self->{filter}) {
74
+         for my $column (keys %{$self->{filter}}) {
75
+             my $filter = $self->{filter}->{$column};
76
+             next unless $filter;
77
+             $row[$_] = $filter->($row[$_])
78
+               for @{$self->{_pos}{$column} || []};
79
+         }
80
+    }
81
+    return \@row;
82
+}
83
+
84
+sub fetch_hash {
85
+    my $self = shift;
86
+    
87
+    # Info
88
+    $self->_cache unless $self->{_cache};
89
+    
90
+    # Fetch
91
+    return unless my $row = $self->{sth}->fetchrow_hashref;
92
+    
93
+    # Type rule
94
+    if ($self->{type_rule}->{from1} &&
95
+      !$self->{type_rule_off} && !$self->{type_rule1_off})
96
+    {
97
+        my $from = $self->{type_rule}->{from1};
98
+        for my $type (keys %$from) {
99
+            $from->{$type} and $row->{$_} = $from->{$type}->($row->{$_})
100
+              for @{$self->{_type_map}->{$type}};
101
+        }
102
+    }
103
+    if ($self->{type_rule}->{from2} &&
104
+      !$self->{type_rule_off} && !$self->{type_rule2_off})
105
+    {
106
+        my $from = $self->{type_rule}->{from2};
107
+        for my $type (keys %{$self->{type_rule}->{from2}}) {
108
+            $from->{$type} and $row->{$_} = $from->{$type}->($row->{$_})
109
+              for @{$self->{_type_map}->{$type}};
110
+        }
111
+    }        
112
+    # Filter
113
+    if ($self->{filter}) {
114
+       exists $row->{$_} && $self->{filter}->{$_}
115
+           and $row->{$_} = $self->{filter}->{$_}->($row->{$_})
116
+         for keys %{$self->{filter}};
117
+    }
118
+    $row;
119
+}
120
+
121
+sub fetch_all {
122
+    my $self = shift;
123
+    
124
+    # Fetch all rows
125
+    my $rows = [];
126
+    while(my $row = $self->fetch) { push @$rows, $row}
127
+    
128
+    return $rows;
129
+}
130
+
131
+sub fetch_first {
132
+    my $self = shift;
133
+    
134
+    # Fetch
135
+    my $row = $self->fetch;
136
+    return unless $row;
137
+    
138
+    # Finish statement handle
139
+    $self->sth->finish;
140
+    
141
+    return $row;
142
+}
143
+
144
+sub fetch_hash_all {
145
+    my $self = shift;
146
+    
147
+    # Fetch all rows as hash
148
+    my $rows = [];
149
+    while(my $row = $self->fetch_hash) { push @$rows, $row }
150
+    
151
+    return $rows;
152
+}
153
+
154
+sub fetch_hash_first {
155
+    my $self = shift;
156
+    
157
+    # Fetch hash
158
+    my $row = $self->fetch_hash;
159
+    return unless $row;
160
+    
161
+    # Finish statement handle
162
+    $self->sth->finish;
163
+    
164
+    return $row;
165
+}
166
+
167
+sub fetch_hash_multi {
168
+    my ($self, $count) = @_;
169
+    
170
+    # Fetch multiple rows
171
+    croak 'Row count must be specified ' . _subname
172
+      unless $count;
173
+    
174
+    return if $self->{_finished};
175
+
176
+    my $rows = [];
177
+    for (my $i = 0; $i < $count; $i++) {
178
+        my $row = $self->fetch_hash;
179
+        unless ($row) {
180
+            $self->{_finished} = 1;
181
+            last;
182
+        }
183
+        push @$rows, $row;
184
+    }
185
+    
186
+    return unless @$rows;
187
+    return $rows;
188
+}
189
+
190
+sub fetch_multi {
191
+    my ($self, $count) = @_;
192
+    
193
+    # Row count not specifed
194
+    croak 'Row count must be specified ' . _subname
195
+      unless $count;
196
+    
197
+    return if $self->{_finished};
198
+    
199
+    # Fetch multi rows
200
+    my $rows = [];
201
+    for (my $i = 0; $i < $count; $i++) {
202
+        my $row = $self->fetch;
203
+        unless ($row) {
204
+            $self->{_finished} = 1;
205
+            last;
206
+        }
207
+        push @$rows, $row;
208
+    }
209
+    
210
+    return unless @$rows;
211
+    return $rows;
212
+}
213
+
214
+sub header { shift->sth->{NAME} }
215
+
216
+*one = \&fetch_hash_first;
217
+
218
+sub type_rule {
219
+    my $self = shift;
220
+    
221
+    if (@_) {
222
+        my $type_rule = ref $_[0] eq 'HASH' ? $_[0] : {@_};
223
+
224
+        # From
225
+        for my $i (1 .. 2) {
226
+            $type_rule->{"from$i"} = _array_to_hash($type_rule->{"from$i"});
227
+            for my $data_type (keys %{$type_rule->{"from$i"} || {}}) {
228
+                croak qq{data type of from$i section must be lower case or number}
229
+                  if $data_type =~ /[A-Z]/;
230
+                my $fname = $type_rule->{"from$i"}{$data_type};
231
+                if (defined $fname && ref $fname ne 'CODE') {
232
+                    croak qq{Filter "$fname" is not registered" } . _subname
233
+                      unless exists $self->dbi->filters->{$fname};
234
+                    
235
+                    $type_rule->{"from$i"}{$data_type} = $self->dbi->filters->{$fname};
236
+                }
237
+            }
238
+        }
239
+        $self->{type_rule} = $type_rule;
240
+        
241
+        return $self;
242
+    }
243
+    
244
+    return $self->{type_rule} || {};
245
+}
246
+
247
+sub type_rule_off {
248
+    my $self = shift;
249
+    $self->{type_rule_off} = 1;
250
+    return $self;
251
+}
252
+
253
+sub type_rule_on {
254
+    my $self = shift;
255
+    $self->{type_rule_off} = 0;
256
+    return $self;
257
+}
258
+
259
+sub type_rule1_off {
260
+    my $self = shift;
261
+    $self->{type_rule1_off} = 1;
262
+    return $self;
263
+}
264
+
265
+sub type_rule1_on {
266
+    my $self = shift;
267
+    $self->{type_rule1_off} = 0;
268
+    return $self;
269
+}
270
+
271
+sub type_rule2_off {
272
+    my $self = shift;
273
+    $self->{type_rule2_off} = 1;
274
+    return $self;
275
+}
276
+
277
+sub type_rule2_on {
278
+    my $self = shift;
279
+    $self->{type_rule2_off} = 0;
280
+    return $self;
281
+}
282
+
283
+sub _cache {
284
+    my $self = shift;
285
+    $self->{_type_map} = {};
286
+    $self->{_pos} = {};
287
+    $self->{_columns} = {};
288
+    for (my $i = 0; $i < @{$self->{sth}->{NAME}}; $i++) {
289
+        my $type = lc $self->{sth}{TYPE}[$i];
290
+        my $name = $self->{sth}{NAME}[$i];
291
+        $self->{_type_map}{$type} ||= [];
292
+        push @{$self->{_type_map}{$type}}, $name;
293
+        $self->{_pos}{$name} ||= [];
294
+        push @{$self->{_pos}{$name}}, $i;
295
+        $self->{_columns}{$name} = 1;
296
+    }
297
+    $self->{_cache} = 1;
298
+}
299
+
300
+1;
301
+
302
+=head1 NAME
303
+
304
+DBIx::Custom::Next::Result - Result of select statement
305
+
306
+=head1 SYNOPSIS
307
+
308
+    # Result
309
+    my $result = $dbi->select(table => 'book');
310
+
311
+    # Fetch a row and put it into array reference
312
+    while (my $row = $result->fetch) {
313
+        my $author = $row->[0];
314
+        my $title  = $row->[1];
315
+    }
316
+    
317
+    # Fetch only a first row and put it into array reference
318
+    my $row = $result->fetch_first;
319
+    
320
+    # Fetch all rows and put them into array of array reference
321
+    my $rows = $result->fetch_all;
322
+
323
+    # Fetch a row and put it into hash reference
324
+    while (my $row = $result->fetch_hash) {
325
+        my $title  = $row->{title};
326
+        my $author = $row->{author};
327
+    }
328
+    
329
+    # Fetch only a first row and put it into hash reference
330
+    my $row = $result->fetch_hash_first;
331
+    my $row = $result->one; # Same as fetch_hash_first
332
+    
333
+    # Fetch all rows and put them into array of hash reference
334
+    my $rows = $result->fetch_hash_all;
335
+    my $rows = $result->all; # Same as fetch_hash_all
336
+
337
+=head1 ATTRIBUTES
338
+
339
+=head2 C<dbi>
340
+
341
+    my $dbi = $result->dbi;
342
+    $result = $result->dbi($dbi);
343
+
344
+L<DBIx::Custom::Next> object.
345
+
346
+=head2 C<sth>
347
+
348
+    my $sth = $reuslt->sth
349
+    $result = $result->sth($sth);
350
+
351
+Statement handle of L<DBI>.
352
+
353
+=head1 METHODS
354
+
355
+L<DBIx::Custom::Next::Result> inherits all methods from L<Object::Simple>
356
+and implements the following new ones.
357
+
358
+=head2 C<all>
359
+
360
+    my $rows = $result->all;
361
+
362
+Same as C<fetch_hash_all>.
363
+
364
+=head2 C<fetch>
365
+
366
+    my $row = $result->fetch;
367
+
368
+Fetch a row and put it into array reference.
369
+
370
+=head2 C<fetch_all>
371
+
372
+    my $rows = $result->fetch_all;
373
+
374
+Fetch all rows and put them into array of array reference.
375
+
376
+=head2 C<fetch_first>
377
+
378
+    my $row = $result->fetch_first;
379
+
380
+Fetch only a first row and put it into array reference,
381
+and finish statment handle.
382
+
383
+=head2 C<fetch_hash>
384
+
385
+    my $row = $result->fetch_hash;
386
+
387
+Fetch a row and put it into hash reference.
388
+
389
+=head2 C<fetch_hash_all>
390
+
391
+    my $rows = $result->fetch_hash_all;
392
+
393
+Fetch all rows and put them into array of hash reference.
394
+
395
+=head2 C<fetch_hash_first>
396
+    
397
+    my $row = $result->fetch_hash_first;
398
+
399
+Fetch only a first row and put it into hash reference,
400
+and finish statment handle.
401
+
402
+=head2 C<fetch_hash_multi>
403
+
404
+    my $rows = $result->fetch_hash_multi(5);
405
+    
406
+Fetch multiple rows and put them into array of hash reference.
407
+
408
+=head2 C<fetch_multi>
409
+
410
+    my $rows = $result->fetch_multi(5);
411
+    
412
+Fetch multiple rows and put them into array of array reference.
413
+
414
+=head2 C<filter>
415
+
416
+    $result->filter(title  => sub { uc $_[0] }, author => 'to_upper');
417
+    $result->filter([qw/title author/] => 'to_upper');
418
+
419
+Set filter for column.
420
+You can use subroutine or filter name as filter.
421
+This filter is executed after C<type_rule> filter.
422
+
423
+=head2 C<header>
424
+
425
+    my $header = $result->header;
426
+
427
+Get header column names.
428
+
429
+=head2 C<one>
430
+
431
+    my $row = $result->one;
432
+
433
+Same as C<fetch_hash_first>.
434
+
435
+=head2 C<stash>
436
+
437
+    my $stash = $result->stash;
438
+    my $foo = $result->stash->{foo};
439
+    $result->stash->{foo} = $foo;
440
+
441
+Stash is hash reference for data.
442
+
443
+=head2 C<type_rule>
444
+    
445
+    # Merge type rule
446
+    $result->type_rule(
447
+        # DATE
448
+        9 => sub { ... },
449
+        # DATETIME or TIMESTAMP
450
+        11 => sub { ... }
451
+    );
452
+
453
+    # Replace type rule(by reference)
454
+    $result->type_rule([
455
+        # DATE
456
+        9 => sub { ... },
457
+        # DATETIME or TIMESTAMP
458
+        11 => sub { ... }
459
+    ]);
460
+
461
+This is same as L<DBIx::Custom::Next>'s C<type_rule>'s <from>.
462
+
463
+=head2 C<type_rule_off>
464
+
465
+    $result = $result->type_rule_off;
466
+
467
+Turn C<from1> and C<from2> type rule off.
468
+By default, type rule is on.
469
+
470
+=head2 C<type_rule_on>
471
+
472
+    $result = $result->type_rule_on;
473
+
474
+Turn C<from1> and C<from2> type rule on.
475
+By default, type rule is on.
476
+
477
+=head2 C<type_rule1_off>
478
+
479
+    $result = $result->type_rule1_off;
480
+
481
+Turn C<from1> type rule off.
482
+By default, type rule is on.
483
+
484
+=head2 C<type_rule1_on>
485
+
486
+    $result = $result->type_rule1_on;
487
+
488
+Turn C<from1> type rule on.
489
+By default, type rule is on.
490
+
491
+=head2 C<type_rule2_off>
492
+
493
+    $result = $result->type_rule2_off;
494
+
495
+Turn C<from2> type rule off.
496
+By default, type rule is on.
497
+
498
+=head2 C<type_rule2_on>
499
+
500
+    $result = $result->type_rule2_on;
501
+
502
+Turn C<from2> type rule on.
503
+By default, type rule is on.
504
+
505
+=cut
+41
lib/DBIx/Custom/Next/Util.pm
... ...
@@ -0,0 +1,41 @@
1
+package DBIx::Custom::Next::Util;
2
+
3
+use strict;
4
+use warnings;
5
+
6
+use base 'Exporter';
7
+
8
+our @EXPORT_OK = qw/_array_to_hash _subname/;
9
+
10
+sub _array_to_hash {
11
+    my $array = shift;
12
+    
13
+    return $array if ref $array eq 'HASH';
14
+    return unless $array;
15
+    
16
+    my $hash = {};
17
+    
18
+    for (my $i = 0; $i < @$array; $i += 2) {
19
+        my $key = $array->[$i];
20
+        my $f = $array->[$i + 1];
21
+        
22
+        if (ref $key eq 'ARRAY') {
23
+            for my $k (@$key) {
24
+                $hash->{$k} = $f;
25
+            }
26
+        }
27
+        else {
28
+            $hash->{$key} = $f;
29
+        }
30
+    }
31
+    return $hash;
32
+}
33
+
34
+sub _subname { '(' . (caller 1)[3] . ')' }
35
+
36
+1;
37
+
38
+=head1 NAME
39
+
40
+DBIx::Custom::Next::Util - Utility class
41
+
+255
lib/DBIx/Custom/Next/Where.pm
... ...
@@ -0,0 +1,255 @@
1
+package DBIx::Custom::Next::Where;
2
+use Object::Simple -base;
3
+
4
+use Carp 'croak';
5
+use DBIx::Custom::Next::Util '_subname';
6
+use overload 'bool' => sub {1}, fallback => 1;
7
+use overload '""' => sub { shift->to_string }, fallback => 1;
8
+
9
+# Carp trust relationship
10
+push @DBIx::Custom::Next::CARP_NOT, __PACKAGE__;
11
+
12
+has [qw/dbi param/],
13
+    clause => sub { [] };
14
+
15
+sub new {
16
+    my $self = shift->SUPER::new(@_);
17
+    
18
+    # Check attribute names
19
+    my @attrs = keys %$self;
20
+    for my $attr (@attrs) {
21
+        croak qq{"$attr" is invalid attribute name (} . _subname . ")"
22
+          unless $self->can($attr);
23
+    }
24
+    
25
+    return $self;
26
+}
27
+
28
+sub to_string {
29
+    my $self = shift;
30
+    
31
+    # Clause
32
+    my $clause = $self->clause;
33
+    $clause = ['and', $clause] unless ref $clause eq 'ARRAY';
34
+    $clause->[0] = 'and' unless @$clause;
35
+    
36
+    # Parse
37
+    my $where = [];
38
+    my $count = {};
39
+    $self->{_safety_character} = $self->dbi->safety_character;
40
+    $self->{_quote} = $self->dbi->quote;
41
+    $self->_parse($clause, $where, $count, 'and');
42
+
43
+    # Stringify
44
+    unshift @$where, 'where' if @$where;
45
+    return join(' ', @$where);
46
+}
47
+    
48
+our %VALID_OPERATIONS = map { $_ => 1 } qw/and or/;
49
+sub _parse {
50
+    my ($self, $clause, $where, $count, $op, $info) = @_;
51
+    
52
+    # Array
53
+    if (ref $clause eq 'ARRAY') {
54
+        
55
+        # Start
56
+        push @$where, '(';
57
+        
58
+        # Operation
59
+        my $op = $clause->[0] || '';
60
+        croak qq{First argument must be "and" or "or" in where clause } .
61
+              qq{"$op" is passed} . _subname . ")"
62
+          unless $VALID_OPERATIONS{$op};
63
+        
64
+        my $pushed_array;
65
+        # Parse internal clause
66
+        for (my $i = 1; $i < @$clause; $i++) {
67
+            my $pushed = $self->_parse($clause->[$i], $where, $count, $op);
68
+            push @$where, $op if $pushed;
69
+            $pushed_array = 1 if $pushed;
70
+        }
71
+        pop @$where if $where->[-1] eq $op;
72
+        
73
+        # Undo
74
+        if ($where->[-1] eq '(') {
75
+            pop @$where;
76
+            pop @$where if ($where->[-1] || '') eq $op;
77
+        }
78
+        # End
79
+        else { push @$where, ')' }
80
+        
81
+        return $pushed_array;
82
+    }
83
+    
84
+    # String
85
+    else {
86
+        # Pushed
87
+        my $pushed;
88
+        
89
+        # Column
90
+        my $c = $self->{_safety_character};
91
+        
92
+        my $column;
93
+        my $sql = $clause;
94
+        $sql =~ s/([0-9]):/$1\\:/g;
95
+        if ($sql =~ /[^\\]:([$c\.]+)/s || $sql =~ /^:([$c\.]+)/s) {
96
+            $column = $1;
97
+        }
98
+        unless (defined $column) {
99
+            push @$where, $clause;
100
+            $pushed = 1;
101
+            return $pushed;
102
+        }
103
+        
104
+        # Column count up
105
+        my $count = ++$count->{$column};
106
+        
107
+        # Push
108
+        my $param = $self->{param};
109
+        if (ref $param eq 'HASH') {
110
+            if (exists $param->{$column}) {
111
+                my $if = $self->{_if};
112
+                
113
+                if (ref $param->{$column} eq 'ARRAY') {
114
+                    $pushed = 1 if exists $param->{$column}->[$count - 1]
115
+                      && ref $param->{$column}->[$count - 1] ne 'DBIx::Custom::Next::NotExists'
116
+                }
117
+                elsif ($count == 1) { $pushed = 1 }
118
+            }
119
+            push @$where, $clause if $pushed;
120
+        }
121
+        elsif (!defined $param) {
122
+            push @$where, $clause;
123
+            $pushed = 1;
124
+        }
125
+        else {
126
+            croak "Parameter must be hash reference or undfined value ("
127
+                . _subname . ")"
128
+        }
129
+        return $pushed;
130
+    }
131
+    return;
132
+}
133
+1;
134
+
135
+=head1 NAME
136
+
137
+DBIx::Custom::Next::Where - Where clause
138
+
139
+=head1 SYNOPSYS
140
+    
141
+    # Create DBIx::Custom::Next::Where object
142
+    my $where = $dbi->where;
143
+    
144
+    # Set clause and parameter
145
+    $where->clause(['and', ':title{like}', ':price{=}']);
146
+    
147
+    # Create where clause by to_string method
148
+    my $where_clause = $where->to_string;
149
+    
150
+    # Create where clause by stringify
151
+    my $where_clause = "$where";
152
+    
153
+    # Created where clause in the above way
154
+    where :title{=} and :price{like}
155
+    
156
+    # Only price condition
157
+    $where->clause(['and', ':title{like}', ':price{=}']);
158
+    $where->param({price => 1900});
159
+    my $where_clause = "$where";
160
+    
161
+    # Created where clause in the above way
162
+    where :price{=}
163
+    
164
+    # Only title condition
165
+    $where->clause(['and', ':title{like}', ':price{=}']);
166
+    $where->param({title => 'Perl'});
167
+    my $where_clause = "$where";
168
+    
169
+    # Created where clause in the above way
170
+    where :title{like}
171
+    
172
+    # Nothing
173
+    $where->clause(['and', ':title{like}', ':price{=}']);
174
+    $where->param({});
175
+    my $where_clause = "$where";
176
+    
177
+    # or condition
178
+    $where->clause(['or', ':title{like}', ':price{=}']);
179
+    
180
+    # More than one parameter
181
+    $where->clause(['and', ':price{>}', ':price{<}']);
182
+    $where->param({price => [1000, 2000]});
183
+    
184
+    # Only first condition
185
+    $where->clause(['and', ':price{>}', ':price{<}']);
186
+    $where->param({price => [1000, $dbi->not_exists]});
187
+    
188
+    # Only second condition
189
+    $where->clause(['and', ':price{>}', ':price{<}']);
190
+    $where->param({price => [$dbi->not_exists, 2000]});
191
+    
192
+    # More complex condition
193
+    $where->clause(
194
+        [
195
+            'and',
196
+            ':price{=}',
197
+            ['or', ':title{=}', ':title{=}', ':title{=}']
198
+        ]
199
+    );
200
+    my $where_clause = "$where";
201
+    
202
+    # Created where clause in the above way
203
+    where :price{=} and (:title{=} or :title{=} or :title{=})
204
+    
205
+    # Using Full-qualified column name
206
+    $where->clause(['and', ':book.title{like}', ':book.price{=}']);
207
+
208
+=head1 ATTRIBUTES
209
+
210
+=head2 C<clause>
211
+
212
+    my $clause = $where->clause;
213
+    $where = $where->clause(
214
+        ['and',
215
+            ':title{=}', 
216
+            ['or', ':date{<}', ':date{>}']
217
+        ]
218
+    );
219
+
220
+Where clause. Above one is expanded to the following SQL by to_string
221
+If all parameter names is exists.
222
+
223
+    where title = :title and ( date < :date or date > :date )
224
+
225
+=head2 C<param>
226
+
227
+    my $param = $where->param;
228
+    $where = $where->param({
229
+        title => 'Perl',
230
+        date => ['2010-11-11', '2011-03-05'],
231
+    });
232
+
233
+=head2 C<dbi>
234
+
235
+    my $dbi = $where->dbi;
236
+    $where = $where->dbi($dbi);
237
+
238
+L<DBIx::Custom::Next> object.
239
+
240
+=head1 METHODS
241
+
242
+L<DBIx::Custom::Next::Where> inherits all methods from L<Object::Simple>
243
+and implements the following new ones.
244
+
245
+=head2 C<to_string>
246
+
247
+    $where->to_string;
248
+
249
+Convert where clause to string.
250
+
251
+double quote is override to execute C<to_string> method.
252
+
253
+    my $string_where = "$where";
254
+
255
+=cut
t/run/access.run → t/_run/access.run
File renamed without changes.
t/run/access2007-accdb.run → t/_run/access2007-accdb.run
File renamed without changes.
t/run/access2010-accdb.run → t/_run/access2010-accdb.run
File renamed without changes.
t/run/common-db2.run → t/_run/common-db2.run
File renamed without changes.
t/run/common-mysql.run → t/_run/common-mysql.run
File renamed without changes.
t/run/common-oracle.run → t/_run/common-oracle.run
File renamed without changes.
t/run/common-postgresql.run → t/_run/common-postgresql.run
File renamed without changes.
t/run/common-sqlserver.run → t/_run/common-sqlserver.run
File renamed without changes.
t/run/mysql.run → t/_run/mysql.run
File renamed without changes.
t/run/mysql2.run → t/_run/mysql2.run
File renamed without changes.
t/next/_run/access.run
No changes.
t/next/_run/access2007-accdb.run
No changes.
t/next/_run/access2010-accdb.run
No changes.
+5
t/next/_run/common-db2.run
... ...
@@ -0,0 +1,5 @@
1
+### DB2 Install
2
+
3
+cd /usr/local/src
4
+
5
+curl -L https://www6.software.ibm.com/sdfdl/v2/regs2/db2pmopn/db2_v97/expc/Xa.2/Xb.aA_60_-iVlRRTUNBO90Dq4FHTisv_wdecoCQFeRQbw/Xc.db2exc_974_LNX_x86.tar.gz/Xd./Xf.LPr.D1vk/Xg.6107654/Xi.swg-db2expressc/XY.regsrvs/XZ.2ygJIAbTC5bn3tv2hlm2PnXUcz8/db2exc_974_LNX_x86.tar.gz > db2exc_974_LNX_x86.tar.gz
+5
t/next/_run/common-mysql.run
... ...
@@ -0,0 +1,5 @@
1
+# Create database
2
+create database dbix_custom;
3
+
4
+# Create User
5
+GRANT ALL PRIVILEGES ON dbix_custom.* TO dbix_custom@"localhost" IDENTIFIED BY 'dbix_custom';
+55
t/next/_run/common-oracle.run
... ...
@@ -0,0 +1,55 @@
1
+# Download
2
+http://download.oracle.com/otn/linux/oracle10g/xe/10201/oracle-xe-univ-10.2.0.1-1.0.i386.rpm
3
+
4
+# Install
5
+rpm -ivh oracle-xe-univ-10.2.0.1-1.0.i386.rpm
6
+/etc/init.d/oracle-xe configure
7
+
8
+# Note
9
+Port number is set to 8090
10
+
11
+# HTTP access
12
+http://127.0.0.1:8090/apex
13
+
14
+# Create user
15
+id: dbix_custom
16
+password: dbix_custom
17
+
18
+Add all privirage
19
+
20
+# DBD::Oracle
21
+You must be install install client
22
+oracle-instantclient11.2-basic-11.2.0.2.0.i386.rpm
23
+oracle-instantclient11.2-devel-11.2.0.2.0.i386.rpm
24
+oracle-instantclient11.2-sqlplus-11.2.0.2.0.i386.rpm
25
+
26
+rpm -hiv oracle-instantclient11.2-basic-11.2.0.2.0.i386.rpm
27
+rpm -hiv oracle-instantclient11.2-devel-11.2.0.2.0.i386.rpm
28
+rpm -hiv oracle-instantclient11.2-sqlplus-11.2.0.2.0.i386.rpm
29
+
30
+vi /etc/profile.d/oracle.sh
31
+export ORACLE_HOME='/usr/lib/oracle/11.2/client'
32
+export C_INCLUDE_PATH='/usr/include/oracle/11.2/client'
33
+export LD_LIBRARY_PATH='/usr/lib/oracle/11.2/client/lib'
34
+
35
+vi /etc/ld.so.conf.d/oracle.conf
36
+/usr/lib/oracle/11.2/client/lib
37
+
38
+cpan DBD::Oracle
39
+
40
+sqlplus dbix_custom/dbix_custom@localhost:1521/XE
41
+
42
+mkdir -p $ORACLE_HOME/network/admin/
43
+vi $ORACLE_HOME/network/admin/tnsnames.ora
44
+
45
+XE =
46
+  (DESCRIPTION =
47
+    (ADDRESS_LIST =
48
+      (ADDRESS = (PROTOCOL = TCP)(HOST = localhost)(PORT = 1521))
49
+    )
50
+    (CONNECT_DATA =
51
+      (SID = orcl)
52
+    )
53
+  )
54
+
55
+
+35
t/next/_run/common-postgresql.run
... ...
@@ -0,0 +1,35 @@
1
+### CentOS5
2
+
3
+# Install
4
+yum -y install postgresql-server
5
+yum -y install postgresql
6
+yum -y install postgresql-devel
7
+chkconfig --level 2345 postgresql on
8
+
9
+# Start server
10
+service postgresql start
11
+
12
+# Change config file
13
+vi /var/lib/pgsql/data/pg_hba.conf
14
+  # "local" is for Unix domain socket connections only
15
+  local   all         all                               trust
16
+
17
+# Create user and database
18
+su - postgres
19
+createuser -a -d -U postgres -P dbix_custom
20
+  # Shall the new role be a superuser? (y/n) -> y
21
+  # Shall the new role be allowed to create databases? (y/n) -> y
22
+  # Shall the new role be allowed to create more new roles? (y/n) -> y
23
+
24
+createdb dbix_custom -U dbix_custom
25
+
26
+# Connect to database
27
+psql -U dbix_custom dbix_custom
28
+
29
+# Install DBD::pg
30
+cpanm DBD::Pg
31
+
32
+### Memo
33
+
34
+# Drop user
35
+dropuser dbix_custom
+13
t/next/_run/common-sqlserver.run
... ...
@@ -0,0 +1,13 @@
1
+# Site
2
+http://awoni.net/fc/sql-server-2008-express/
3
+
4
+
5
+# Install
6
+http://www.microsoft.com/downloads/ja-jp/details.aspx?displaylang=ja&FamilyID=967225eb-207b-4950-91df-eeb5f35a80ee
7
+
8
+
9
+# Note
10
+You enable SQL Server authentication.
11
+You create user "dbix_custom", password "dbix_custom"
12
+You give create_table, insert, update, delete, select authority to user "dbix_custom".
13
+
t/next/_run/mysql.run
No changes.
t/next/_run/mysql2.run
No changes.
BIN
t/next/access.mdb
Binary file not shown.
+35
t/next/access.t
... ...
@@ -0,0 +1,35 @@
1
+use Test::More;
2
+use strict;
3
+use warnings;
4
+use utf8;
5
+
6
+use FindBin;
7
+use DBIx::Custom::Next;
8
+
9
+my $dbi;
10
+my $dsn;
11
+my $args;
12
+my $database = "$FindBin::Bin/access.mdb";
13
+
14
+$dsn = "dbi:ODBC:driver=Microsoft Access Driver (*.mdb);dbq=$database";
15
+
16
+plan skip_all => 'Microsoft access(ODBC, *.mdb) private test' unless -f "$FindBin::Bin/run/access.run"
17
+  && eval { $dbi = DBIx::Custom::Next->connect(dsn => $dsn); 1 };
18
+plan 'no_plan';
19
+
20
+my $model;
21
+my $result;
22
+my $rows;
23
+
24
+eval { $dbi->execute("drop table table1") };
25
+$dbi->execute("create table table1 (key1 varchar(255), key2 varchar(255))");
26
+$model = $dbi->create_model(table => 'table1');
27
+$model->insert({key1 => 1, key2 => 2});
28
+$model->insert({key1 => 4, key2 => 5});
29
+$model->insert({key1 => 6, key2 => 7});
30
+$model->update({key2 => 3}, where => {key1 => 1});
31
+$model->delete(where => {key1 => 6});
32
+$rows = $model->select->all;
33
+is_deeply($rows, [{key1 => 1, key2 => 3}, {key1 => 4, key2 => 5}]);
34
+is($model->count, 2);
35
+
+46
t/next/access2007-accdb.t
... ...
@@ -0,0 +1,46 @@
1
+use Test::More;
2
+use strict;
3
+use warnings;
4
+use utf8;
5
+
6
+use FindBin;
7
+use DBIx::Custom::Next;
8
+
9
+my $dbi;
10
+my $dsn;
11
+my $database = "$FindBin::Bin/access2007.accdb";
12
+
13
+$dsn = "dbi:ODBC:Driver={Microsoft Access Driver (*.mdb, *.accdb)};DBQ=$database";
14
+
15
+plan skip_all => 'Microsoft access(ODBC, *.accdb(2007)) private test'
16
+  unless -f "$FindBin::Bin/run/access2007-accdb.run"
17
+      && eval { $dbi = DBIx::Custom::Next->connect(dsn => $dsn); 1 };
18
+plan 'no_plan';
19
+
20
+my $model;
21
+my $result;
22
+my $row;
23
+my $rows;
24
+
25
+eval { $dbi->execute("drop table table1") };
26
+eval { $dbi->execute("drop table table2") };
27
+$dbi->execute("create table table1 (key1 varchar(255), key2 varchar(255))");
28
+$dbi->execute("create table table2 (key1 varchar(255), key3 varchar(255))");
29
+$model = $dbi->create_model(table => 'table1');
30
+$model->insert({key1 => 1, key2 => 2});
31
+$model->insert({key1 => 4, key2 => 5});
32
+$model->insert({key1 => 6, key2 => 7});
33
+$model->update({key2 => 3}, where => {key1 => 1});
34
+$model->delete(where => {key1 => 6});
35
+$rows = $model->select->all;
36
+is_deeply($rows, [{key1 => 1, key2 => 3}, {key1 => 4, key2 => 5}]);
37
+is($model->count, 2);
38
+$dbi->insert({key1 => 1, key3 => 2}, table => 'table2');
39
+$dbi->separator('-');
40
+$row = $model->select(
41
+    table => 'table1',
42
+    column => {table2 => [qw/key3/]},
43
+    join => ['left outer join table2 on table1.key1 = table2.key1']
44
+)->one;
45
+is_deeply($row, {"table2-key3" => 2});
46
+
BIN
t/next/access2007.accdb
Binary file not shown.
+46
t/next/access2010-accdb.t
... ...
@@ -0,0 +1,46 @@
1
+use Test::More;
2
+use strict;
3
+use warnings;
4
+use utf8;
5
+
6
+use FindBin;
7
+use DBIx::Custom::Next;
8
+
9
+my $dbi;
10
+my $dsn;
11
+my $database = "$FindBin::Bin/access2010.accdb";
12
+
13
+$dsn = "dbi:ODBC:Driver={Microsoft Access Driver (*.mdb, *.accdb)};DBQ=$database";
14
+
15
+plan skip_all => 'Microsoft access(ODBC, *.accdb(2010)) private test'
16
+  unless -f "$FindBin::Bin/run/access2010-accdb.run"
17
+      && eval { $dbi = DBIx::Custom::Next->connect(dsn => $dsn); 1 };
18
+plan 'no_plan';
19
+
20
+my $model;
21
+my $result;
22
+my $row;
23
+my $rows;
24
+
25
+eval { $dbi->execute("drop table table1") };
26
+eval { $dbi->execute("drop table table2") };
27
+$dbi->execute("create table table1 (key1 varchar(255), key2 varchar(255))");
28
+$dbi->execute("create table table2 (key1 varchar(255), key3 varchar(255))");
29
+$model = $dbi->create_model(table => 'table1');
30
+$model->insert({key1 => 1, key2 => 2});
31
+$model->insert({key1 => 4, key2 => 5});
32
+$model->insert({key1 => 6, key2 => 7});
33
+$model->update({key2 => 3}, where => {key1 => 1});
34
+$model->delete(where => {key1 => 6});
35
+$rows = $model->select->all;
36
+is_deeply($rows, [{key1 => 1, key2 => 3}, {key1 => 4, key2 => 5}]);
37
+is($model->count, 2);
38
+$dbi->insert({key1 => 1, key3 => 2}, table => 'table2');
39
+$dbi->separator('-');
40
+$row = $model->select(
41
+    table => 'table1',
42
+    column => {table2 => [qw/key3/]},
43
+    join => ['left outer join table2 on table1.key1 = table2.key1']
44
+)->one;
45
+is_deeply($row, {"table2-key3" => 2});
46
+
BIN
t/next/access2010.accdb
Binary file not shown.
+77
t/next/common-mysql.t
... ...
@@ -0,0 +1,77 @@
1
+use strict;
2
+use warnings;
3
+
4
+use FindBin;
5
+use lib "$FindBin::Bin/common";
6
+$ENV{DBIX_CUSTOM_TEST_RUN} = 1
7
+  if -f "$FindBin::Bin/run/common-mysql.run";
8
+$ENV{DBIX_CUSTOM_SKIP_MESSAGE} = 'mysql private test';
9
+
10
+
11
+
12
+use DBIx::Custom::Next;
13
+{
14
+    package DBIx::Custom::Next;
15
+    no warnings 'redefine';
16
+
17
+    my $table1 = 'table1';
18
+    my $table2 = 'table2';
19
+    my $table2_alias = 'table2_alias';
20
+    my $table3 = 'table3';
21
+    my $key1 = 'key1';
22
+    my $key2 = 'key2';
23
+    my $key3 = 'key3';
24
+    my $key4 = 'key4';
25
+    my $key5 = 'key5';
26
+    my $key6 = 'key6';
27
+    my $key7 = 'key7';
28
+    my $key8 = 'key8';
29
+    my $key9 = 'key9';
30
+    my $key10 = 'key10';
31
+
32
+    has table1 => $table1;
33
+    has table2 => $table2;
34
+    has table2_alias => $table2_alias;
35
+    has table3 => $table3;
36
+    has key1 => $key1;
37
+    has key2 => $key2;
38
+    has key3 => $key3;
39
+    has key4 => $key4;
40
+    has key5 => $key5;
41
+    has key6 => $key6;
42
+    has key7 => $key7;
43
+    has key8 => $key8;
44
+    has key9 => $key9;
45
+    has key10 => $key10;
46
+
47
+    my $date_typename = 'Date';
48
+    my $datetime_typename = 'Datetime';
49
+    
50
+    sub date_typename { lc $date_typename }
51
+    sub datetime_typename { lc $datetime_typename }
52
+
53
+    my $date_datatype = 9;
54
+    my $datetime_datatype = 11;
55
+    
56
+    sub date_datatype { lc $date_datatype }
57
+    sub datetime_datatype { lc $datetime_datatype }
58
+
59
+    no warnings 'redefine';
60
+    has dsn => "dbi:mysql:database=dbix_custom";
61
+    has user => 'dbix_custom';
62
+    has password => 'dbix_custom';
63
+    
64
+    sub create_table1 { "create table $table1 ($key1 varchar(255), $key2 varchar(255)) engine=InnoDB" }
65
+    sub create_table1_2 { "create table $table1 ($key1 varchar(255), $key2 varchar(255), "
66
+     . "$key3 varchar(255), key4 varchar(255), key5 varchar(255)) engine=InnoDB" }
67
+    sub create_table1_type { "create table $table1 ($key1 $date_typename, $key2 $datetime_typename) engine=InnoDB" }
68
+    sub create_table1_highperformance { "create table $table1 ($key1 varchar(255), $key2 varchar(255), "
69
+      . "$key3 varchar(255), $key4 varchar(255), $key5 varchar(255), $key6 varchar(255), $key7 varchar(255)) engine=InnoDB" }
70
+    sub create_table2 { "create table $table2 ($key1 varchar(255), $key3 varchar(255)) engine=InnoDB" }
71
+    sub create_table2_2 { "create table $table2 ($key1 varchar(255), $key2 varchar(255), $key3 varchar(255)) engine=InnoDB" }
72
+    sub create_table3 { "create table $table3 ($key1 varchar(255), $key2 varchar(255), $key3 varchar(255)) engine=InnoDB" }
73
+    sub create_table_reserved {
74
+      'create table `table` (`select` varchar(255), `update` varchar(255)) engine=InnoDB' }
75
+}
76
+
77
+require "$FindBin::Bin/common.t";
+1663
t/next/common-oracle.t
... ...
@@ -0,0 +1,1663 @@
1
+use strict;
2
+use warnings;
3
+
4
+use FindBin;
5
+use lib "$FindBin::Bin/common_uc";
6
+$ENV{DBIX_CUSTOM_TEST_RUN} = 1
7
+  if -f "$FindBin::Bin/run/common-oracle.run";
8
+$ENV{DBIX_CUSTOM_SKIP_MESSAGE} = 'oracle private test';
9
+
10
+use DBIx::Custom::Next;
11
+{
12
+    package DBIx::Custom::Next;
13
+    no warnings 'redefine';
14
+    
15
+    has option => sub {
16
+        {
17
+            Callbacks => {
18
+              connected => sub {
19
+                  shift->do(
20
+                      "ALTER SESSION SET NLS_DATE_FORMAT = 'YYYY-MM-DD HH24:MI:SS'"
21
+                  );
22
+                  return;
23
+              },
24
+            }
25
+        }
26
+    };
27
+
28
+    my $table1 = 'TABLE1';
29
+    my $table2 = 'TABLE2';
30
+    my $table2_alias = 'TABLE2_ALIAS';
31
+    my $table3 = 'TABLE3';
32
+    my $key1 = 'KEY1';
33
+    my $key2 = 'KEY2';
34
+    my $key3 = 'KEY3';
35
+    my $key4 = 'KEY4';
36
+    my $key5 = 'KEY5';
37
+    my $key6 = 'KEY6';
38
+    my $key7 = 'KEY7';
39
+    my $key8 = 'KEY8';
40
+    my $key9 = 'KEY9';
41
+    my $key10 = 'KEY10';
42
+    
43
+    has table1 => $table1;
44
+    has table2 => $table2;
45
+    has table2_alias => $table2_alias;
46
+    has table3 => $table3;
47
+    has key1 => $key1;
48
+    has key2 => $key2;
49
+    has key3 => $key3;
50
+    has key4 => $key4;
51
+    has key5 => $key5;
52
+    has key6 => $key6;
53
+    has key7 => $key7;
54
+    has key8 => $key8;
55
+    has key9 => $key9;
56
+    has key10 => $key10;
57
+
58
+    my $date_typename = 'CHAR(10)';
59
+    my $datetime_typename = 'DATE';
60
+
61
+    sub date_typename { lc 'CHAR' }
62
+    sub datetime_typename { lc $datetime_typename }
63
+
64
+    my $date_datatype = 1;
65
+    my $datetime_datatype = 93;
66
+
67
+    sub date_datatype { lc $date_datatype }
68
+    sub datetime_datatype { lc $datetime_datatype }
69
+
70
+    my @system_tables = qw#
71
+        WWV_FLOW_SESSION_SEQ
72
+        WWV_SEQ
73
+        SAMPLE_SEQ
74
+        SDO_IDX_TAB_SEQUENCE
75
+        TMP_COORD_OPS
76
+        XDB$NAMESUFF_SEQ
77
+        ABSPATH
78
+        ALERT_TYPE
79
+        ALL_
80
+        ANYDATA
81
+        ANYDATASET
82
+        ANYTYPE
83
+        APEX
84
+        APPLICATION_AUTHENTICATION
85
+        AQ$INTERNET_USERS
86
+        AREA
87
+        ASBINARY
88
+        ASTEXT
89
+        AUDIT_ACTIONS
90
+        AWRDRPT_TEXT_TYPE
91
+        AWRRPT_CLB_ARY
92
+        AWRRPT_HTML_TYPE
93
+        AWRRPT_NUM_ARY
94
+        AWRRPT_ROW_TYPE
95
+        AWRRPT_TEXT_TYPE
96
+        AWRRPT_VCH_ARY
97
+        AWRSQRPT_TEXT_TYPE
98
+        BOUNDARY
99
+        BUFFER
100
+        CAT
101
+        CATSEARCH
102
+        CENTROID
103
+        CHANGE_PROPAGATIONS
104
+        CHANGE_PROPAGATION_SETS
105
+        CHANGE_SETS
106
+        CHANGE_SOURCES
107
+        CIRCULARSTRING
108
+        CLU
109
+        COL
110
+        COLLECT
111
+        COLS
112
+        COLUMN_PRIVILEGES
113
+        COMPOUNDCURVE
114
+        CONTAINS
115
+        CONTENTSCHEMAIS
116
+        CONTEXT
117
+        CONVEXHULL
118
+        CROSS
119
+        CS_SRS
120
+        CTXCAT
121
+        CTXRULE
122
+        CTXXPATH
123
+        CTX_CLASSES
124
+        CTX_CLS
125
+        CTX_DDL
126
+        CTX_DOC
127
+        CTX_INDEX_SETS
128
+        CTX_INDEX_SET_INDEXES
129
+        CTX_OBJECTS
130
+        CTX_OBJECT_ATTRIBUTES
131
+        CTX_OBJECT_ATTRIBUTE_LOV
132
+        CTX_OUTPUT
133
+        CTX_PARAMETERS
134
+        CTX_PREFERENCES
135
+        CTX_PREFERENCE_VALUES
136
+        CTX_QUERY
137
+        CTX_REPORT
138
+        CTX_SECTIONS
139
+        CTX_SECTION_GROUPS
140
+        CTX_SQES
141
+        CTX_STOPLISTS
142
+        CTX_STOPWORDS
143
+        CTX_SUB_LEXERS
144
+        CTX_THES
145
+        CTX_THESAURI
146
+        CTX_THES_PHRASES
147
+        CTX_TRACE_VALUES
148
+        CTX_ULEXER
149
+        CTX_USER_INDEXES
150
+        CTX_USER_INDEX_ERRORS
151
+        CTX_USER_INDEX_OBJECTS
152
+        CTX_USER_INDEX_PARTITIONS
153
+        CTX_USER_INDEX_SETS
154
+        CTX_USER_INDEX_SET_INDEXES
155
+        CTX_USER_INDEX_SUB_LEXERS
156
+        CTX_USER_INDEX_SUB_LEXER_VALS
157
+        CTX_USER_INDEX_VALUES
158
+        CTX_USER_PENDING
159
+        CTX_USER_PREFERENCES
160
+        CTX_USER_PREFERENCE_VALUES
161
+        CTX_USER_SECTIONS
162
+        CTX_USER_SECTION_GROUPS
163
+        CTX_USER_SQES
164
+        CTX_USER_STOPLISTS
165
+        CTX_USER_STOPWORDS
166
+        CTX_USER_SUB_LEXERS
167
+        CTX_USER_THESAURI
168
+        CTX_USER_THES_PHRASES
169
+        CURVE
170
+        CURVEPOLYGON
171
+        DATABASE_COMPATIBLE_LEVEL
172
+        DATABASE_EXPORT_OBJECTS
173
+        DATABASE_PROPERTIES
174
+        DATAPUMP_OBJECT_CONNECT
175
+        DATAPUMP_PATHMAP
176
+        DATAPUMP_PATHS
177
+        DATAPUMP_REMAP_OBJECTS
178
+        DBA_2PC_NEIGHBORS
179
+        DBA_
180
+        DBMSHSXP
181
+        DBMSHSXP_SQL_PROFILE_ATTR
182
+        DBMSOBJGWRAPPER
183
+        DBMSOUTPUT_LINESARRAY
184
+        DBMSZEXP_SYSPKGGRNT
185
+        DBMS_
186
+        DBURITYPE
187
+        DEFCALL
188
+        DEFCALLDEST
189
+        DEFDEFAULTDEST
190
+        DEFERRCOUNT
191
+        DEFERROR
192
+        DEFLOB
193
+        DEFPROPAGATOR
194
+        DEFSCHEDULE
195
+        DEFTRAN
196
+        DEFTRANDEST
197
+        DEPTH
198
+        DEVELOPMENT_SERVICE_HOME
199
+        DEVELOPMENT_SERVICE_HOME_LOGIN
200
+        DEVELOPMENT_SERVICE_SIGNUP
201
+        DICT
202
+        DICTIONARY
203
+        DICT_COLUMNS
204
+        DIFFERENCE
205
+        DIMENSION
206
+        DISJOINT
207
+        DISTANCE
208
+        DM_CENTROIDS
209
+        DM_CL_BUILD
210
+        DM_SVM_APPLY
211
+        DM_SVM_BUILD
212
+        DRVODM
213
+        DS_SQL_WORKSHOP
214
+        DUAL
215
+        ENDPOINT
216
+        ENVELOPE
217
+        EQUALS
218
+        EQUALS_PATH
219
+        EXPLAINMVARRAYTYPE
220
+        EXPLAINMVMESSAGE
221
+        EXTERIORRING
222
+        F
223
+        FLASHBACK_TRANSACTION_QUERY
224
+        FTPURITYPE
225
+        GEOMETRY
226
+        GEOMETRYCOLLECTION
227
+        GEOMETRYN
228
+        GEOMETRYTYPE
229
+        GLOBAL_CONTEXT
230
+        GLOBAL_NAME
231
+        GV$ACCESS
232
+        GV$ACTIVE_INSTANCES
233
+        GV$ACTIVE_SERVICES
234
+        GV$ACTIVE_SESSION_HISTORY
235
+        GV$ACTIVE_SESS_POOL_MTH
236
+        GV$ADVISOR_PROGRESS
237
+        GV$ALERT_TYPES
238
+        GV$AQ
239
+        GV$AQ1
240
+        GV$ARCHIVE
241
+        GV$ARCHIVED_LOG
242
+        GV$ARCHIVE_DEST
243
+        GV$ARCHIVE_DEST_STATUS
244
+        GV$ARCHIVE_GAP
245
+        GV$ARCHIVE_PROCESSES
246
+        GV$ASM_ALIAS
247
+        GV$ASM_CLIENT
248
+        GV$ASM_DISK
249
+        GV$ASM_DISKGROUP
250
+        GV$ASM_DISKGROUP_STAT
251
+        GV$ASM_DISK_STAT
252
+        GV$ASM_FILE
253
+        GV$ASM_OPERATION
254
+        GV$ASM_TEMPLATE
255
+        GV$AW_AGGREGATE_OP
256
+        GV$AW_ALLOCATE_OP
257
+        GV$AW_CALC
258
+        GV$AW_LONGOPS
259
+        GV$AW_OLAP
260
+        GV$AW_SESSION_INFO
261
+        GV$BACKUP
262
+        GV$BACKUP_ASYNC_IO
263
+        GV$BACKUP_CORRUPTION
264
+        GV$BACKUP_DATAFILE
265
+        GV$BACKUP_DEVICE
266
+        GV$BACKUP_PIECE
267
+        GV$BACKUP_REDOLOG
268
+        GV$BACKUP_SET
269
+        GV$BACKUP_SPFILE
270
+        GV$BACKUP_SYNC_IO
271
+        GV$BGPROCESS
272
+        GV$BH
273
+        GV$BLOCKING_QUIESCE
274
+        GV$BSP
275
+        GV$BUFFERED_PUBLISHERS
276
+        GV$BUFFERED_QUEUES
277
+        GV$BUFFERED_SUBSCRIBERS
278
+        GV$BUFFER_POOL
279
+        GV$BUFFER_POOL_STATISTICS
280
+        GV$CIRCUIT
281
+        GV$CLASS_CACHE_TRANSFER
282
+        GV$CLASS_PING
283
+        GV$CLIENT_STATS
284
+        GV$CLUSTER_INTERCONNECTS
285
+        GV$CONFIGURED_INTERCONNECTS
286
+        GV$CONTEXT
287
+        GV$CONTROLFILE
288
+        GV$CONTROLFILE_RECORD_SECTION
289
+        GV$COPY_CORRUPTION
290
+        GV$CR_BLOCK_SERVER
291
+        GV$CURRENT_BLOCK_SERVER
292
+        GV$DATABASE
293
+        GV$DATABASE_BLOCK_CORRUPTION
294
+        GV$DATABASE_INCARNATION
295
+        GV$DATAFILE
296
+        GV$DATAFILE_COPY
297
+        GV$DATAFILE_HEADER
298
+        GV$DATAGUARD_CONFIG
299
+        GV$DATAGUARD_STATUS
300
+        GV$DATAPUMP_JOB
301
+        GV$DATAPUMP_SESSION
302
+        GV$DBFILE
303
+        GV$DBLINK
304
+        GV$DB_CACHE_ADVICE
305
+        GV$DB_OBJECT_CACHE
306
+        GV$DB_PIPES
307
+        GV$DELETED_OBJECT
308
+        GV$DISPATCHER
309
+        GV$DISPATCHER_CONFIG
310
+        GV$DISPATCHER_RATE
311
+        GV$DLM_ALL_LOCKS
312
+        GV$DLM_CONVERT_LOCAL
313
+        GV$DLM_CONVERT_REMOTE
314
+        GV$DLM_LATCH
315
+        GV$DLM_LOCKS
316
+        GV$DLM_MISC
317
+        GV$DLM_RESS
318
+        GV$DLM_TRAFFIC_CONTROLLER
319
+        GV$ENABLEDPRIVS
320
+        GV$ENQUEUE_LOCK
321
+        GV$ENQUEUE_STAT
322
+        GV$ENQUEUE_STATISTICS
323
+        GV$EVENTMETRIC
324
+        GV$EVENT_HISTOGRAM
325
+        GV$EVENT_NAME
326
+        GV$EXECUTION
327
+        GV$FAST_START_SERVERS
328
+        GV$FAST_START_TRANSACTIONS
329
+        GV$FILEMETRIC
330
+        GV$FILEMETRIC_HISTORY
331
+        GV$FILESPACE_USAGE
332
+        GV$FILESTAT
333
+        GV$FILE_CACHE_TRANSFER
334
+        GV$FILE_HISTOGRAM
335
+        GV$FILE_PING
336
+        GV$FIXED_VIEW_DEFINITION
337
+        GV$FLASHBACK_DATABASE_LOG
338
+        GV$FLASHBACK_DATABASE_LOGFILE
339
+        GV$FLASHBACK_DATABASE_STAT
340
+        GV$GCSHVMASTER_INFO
341
+        GV$GCSPFMASTER_INFO
342
+        GV$GC_ELEMENT
343
+        GV$GC_ELEMENTS_WITH_COLLISIONS
344
+        GV$GES_BLOCKING_ENQUEUE
345
+        GV$GES_ENQUEUE
346
+        GV$GLOBALCONTEXT
347
+        GV$GLOBAL_BLOCKED_LOCKS
348
+        GV$GLOBAL_TRANSACTION
349
+        GV$HS_AGENT
350
+        GV$HS_PARAMETER
351
+        GV$HS_SESSION
352
+        GV$HVMASTER_INFO
353
+        GV$INDEXED_FIXED_COLUMN
354
+        GV$INSTANCE
355
+        GV$INSTANCE_CACHE_TRANSFER
356
+        GV$INSTANCE_LOG_GROUP
357
+        GV$INSTANCE_RECOVERY
358
+        GV$JAVAPOOL
359
+        GV$JAVA_LIBRARY_CACHE_MEMORY
360
+        GV$JAVA_POOL_ADVICE
361
+        GV$LATCH
362
+        GV$LATCHHOLDER
363
+        GV$LATCHNAME
364
+        GV$LATCH_CHILDREN
365
+        GV$LATCH_MISSES
366
+        GV$LATCH_PARENT
367
+        GV$LIBRARYCACHE
368
+        GV$LIBRARY_CACHE_MEMORY
369
+        GV$LICENSE
370
+        GV$LOADISTAT
371
+        GV$LOADPSTAT
372
+        GV$LOCK
373
+        GV$LOCKED_OBJECT
374
+        GV$LOCKS_WITH_COLLISIONS
375
+        GV$LOCK_ACTIVITY
376
+        GV$LOCK_ELEMENT
377
+        GV$LOCK_TYPE
378
+        GV$LOG
379
+        GV$LOGFILE
380
+        GV$LOGHIST
381
+        GV$LOGMNR_CALLBACK
382
+        GV$LOGMNR_CONTENTS
383
+        GV$LOGMNR_DICTIONARY
384
+        GV$LOGMNR_DICTIONARY_LOAD
385
+        GV$LOGMNR_LATCH
386
+        GV$LOGMNR_LOGFILE
387
+        GV$LOGMNR_LOGS
388
+        GV$LOGMNR_PARAMETERS
389
+        GV$LOGMNR_PROCESS
390
+        GV$LOGMNR_REGION
391
+        GV$LOGMNR_SESSION
392
+        GV$LOGMNR_STATS
393
+        GV$LOGMNR_TRANSACTION
394
+        GV$LOGSTDBY
395
+        GV$LOGSTDBY_PROCESS
396
+        GV$LOGSTDBY_PROGRESS
397
+        GV$LOGSTDBY_STATE
398
+        GV$LOGSTDBY_STATS
399
+        GV$LOGSTDBY_TRANSACTION
400
+        GV$LOG_HISTORY
401
+        GV$MANAGED_STANDBY
402
+        GV$MAP_COMP_LIST
403
+        GV$MAP_ELEMENT
404
+        GV$MAP_EXT_ELEMENT
405
+        GV$MAP_FILE
406
+        GV$MAP_FILE_EXTENT
407
+        GV$MAP_FILE_IO_STACK
408
+        GV$MAP_LIBRARY
409
+        GV$MAP_SUBELEMENT
410
+        GV$MAX_ACTIVE_SESS_TARGET_MTH
411
+        GV$METRIC
412
+        GV$METRICGROUP
413
+        GV$METRICNAME
414
+        GV$METRIC_HISTORY
415
+        GV$MTTR_TARGET_ADVICE
416
+        GV$MUTEX_SLEEP
417
+        GV$MUTEX_SLEEP_HISTORY
418
+        GV$MVREFRESH
419
+        GV$MYSTAT
420
+        GV$NLS_PARAMETERS
421
+        GV$NLS_VALID_VALUES
422
+        GV$OBJECT_DEPENDENCY
423
+        GV$OBSOLETE_PARAMETER
424
+        GV$OFFLINE_RANGE
425
+        GV$OPEN_CURSOR
426
+        GV$OPTION
427
+        GV$OSSTAT
428
+        GV$PARALLEL_DEGREE_LIMIT_MTH
429
+        GV$PARAMETER
430
+        GV$PARAMETER2
431
+        GV$PARAMETER_VALID_VALUES
432
+        GV$PGASTAT
433
+        GV$PGA_TARGET_ADVICE
434
+        GV$PGA_TARGET_ADVICE_HISTOGRAM
435
+        GV$PQ_SESSTAT
436
+        GV$PQ_SLAVE
437
+        GV$PQ_SYSSTAT
438
+        GV$PQ_TQSTAT
439
+        GV$PROCESS
440
+        GV$PROCESS_MEMORY
441
+        GV$PROCESS_MEMORY_DETAIL
442
+        GV$PROCESS_MEMORY_DETAIL_PROG
443
+        GV$PROPAGATION_RECEIVER
444
+        GV$PROPAGATION_SENDER
445
+        GV$PROXY_ARCHIVEDLOG
446
+        GV$PROXY_DATAFILE
447
+        GV$PWFILE_USERS
448
+        GV$PX_BUFFER_ADVICE
449
+        GV$PX_PROCESS
450
+        GV$PX_PROCESS_SYSSTAT
451
+        GV$PX_SESSION
452
+        GV$PX_SESSTAT
453
+        GV$QUEUE
454
+        GV$QUEUEING_MTH
455
+        GV$RECOVERY_FILE_STATUS
456
+        GV$RECOVERY_LOG
457
+        GV$RECOVERY_PROGRESS
458
+        GV$RECOVERY_STATUS
459
+        GV$RECOVER_FILE
460
+        GV$REPLPROP
461
+        GV$REPLQUEUE
462
+        GV$REQDIST
463
+        GV$RESERVED_WORDS
464
+        GV$RESOURCE
465
+        GV$RESOURCE_LIMIT
466
+        GV$RESTORE_POINT
467
+        GV$RESUMABLE
468
+        GV$RFS_THREAD
469
+        GV$RMAN_CONFIGURATION
470
+        GV$RMAN_OUTPUT
471
+        GV$ROLLSTAT
472
+        GV$ROWCACHE
473
+        GV$ROWCACHE_PARENT
474
+        GV$ROWCACHE_SUBORDINATE
475
+        GV$RSRC_CONSUMER_GROUP
476
+        GV$RSRC_CONSUMER_GROUP_CPU_MTH
477
+        GV$RSRC_CONS_GROUP_HISTORY
478
+        GV$RSRC_PLAN
479
+        GV$RSRC_PLAN_CPU_MTH
480
+        GV$RSRC_PLAN_HISTORY
481
+        GV$RSRC_SESSION_INFO
482
+        GV$RULE
483
+        GV$RULE_SET
484
+        GV$RULE_SET_AGGREGATE_STATS
485
+        GV$SCHEDULER_RUNNING_JOBS
486
+        GV$SEGMENT_STATISTICS
487
+        GV$SEGSTAT
488
+        GV$SEGSTAT_NAME
489
+        GV$SERVICEMETRIC
490
+        GV$SERVICEMETRIC_HISTORY
491
+        GV$SERVICES
492
+        GV$SERVICE_EVENT
493
+        GV$SERVICE_STATS
494
+        GV$SERVICE_WAIT_CLASS
495
+        GV$SERV_MOD_ACT_STATS
496
+        GV$SESSION
497
+        GV$SESSION_CONNECT_INFO
498
+        GV$SESSION_CURSOR_CACHE
499
+        GV$SESSION_EVENT
500
+        GV$SESSION_LONGOPS
501
+        GV$SESSION_OBJECT_CACHE
502
+        GV$SESSION_WAIT
503
+        GV$SESSION_WAIT_CLASS
504
+        GV$SESSION_WAIT_HISTORY
505
+        GV$SESSMETRIC
506
+        GV$SESSTAT
507
+        GV$SESS_IO
508
+        GV$SESS_TIME_MODEL
509
+        GV$SES_OPTIMIZER_ENV
510
+        GV$SGA
511
+        GV$SGAINFO
512
+        GV$SGASTAT
513
+        GV$SGA_CURRENT_RESIZE_OPS
514
+        GV$SGA_DYNAMIC_COMPONENTS
515
+        GV$SGA_DYNAMIC_FREE_MEMORY
516
+        GV$SGA_RESIZE_OPS
517
+        GV$SGA_TARGET_ADVICE
518
+        GV$SHARED_POOL_ADVICE
519
+        GV$SHARED_POOL_RESERVED
520
+        GV$SHARED_SERVER
521
+        GV$SHARED_SERVER_MONITOR
522
+        GV$SORT_SEGMENT
523
+        GV$SORT_USAGE
524
+        GV$SPPARAMETER
525
+        GV$SQL
526
+        GV$SQLAREA
527
+        GV$SQLAREA_PLAN_HASH
528
+        GV$SQLSTATS
529
+        GV$SQLTEXT
530
+        GV$SQLTEXT_WITH_NEWLINES
531
+        GV$SQL_BIND_CAPTURE
532
+        GV$SQL_BIND_DATA
533
+        GV$SQL_BIND_METADATA
534
+        GV$SQL_CURSOR
535
+        GV$SQL_JOIN_FILTER
536
+        GV$SQL_OPTIMIZER_ENV
537
+        GV$SQL_PLAN
538
+        GV$SQL_PLAN_STATISTICS
539
+        GV$SQL_PLAN_STATISTICS_ALL
540
+        GV$SQL_REDIRECTION
541
+        GV$SQL_SHARED_CURSOR
542
+        GV$SQL_SHARED_MEMORY
543
+        GV$SQL_WORKAREA
544
+        GV$SQL_WORKAREA_ACTIVE
545
+        GV$SQL_WORKAREA_HISTOGRAM
546
+        GV$STANDBY_APPLY_SNAPSHOT
547
+        GV$STANDBY_LOG
548
+        GV$STATISTICS_LEVEL
549
+        GV$STATNAME
550
+        GV$STREAMS_APPLY_COORDINATOR
551
+        GV$STREAMS_APPLY_READER
552
+        GV$STREAMS_APPLY_SERVER
553
+        GV$STREAMS_CAPTURE
554
+        GV$STREAMS_POOL_ADVICE
555
+        GV$STREAMS_TRANSACTION
556
+        GV$SUBCACHE
557
+        GV$SYSAUX_OCCUPANTS
558
+        GV$SYSMETRIC
559
+        GV$SYSMETRIC_HISTORY
560
+        GV$SYSMETRIC_SUMMARY
561
+        GV$SYSSTAT
562
+        GV$SYSTEM_CURSOR_CACHE
563
+        GV$SYSTEM_EVENT
564
+        GV$SYSTEM_PARAMETER
565
+        GV$SYSTEM_PARAMETER2
566
+        GV$SYSTEM_WAIT_CLASS
567
+        GV$SYS_OPTIMIZER_ENV
568
+        GV$SYS_TIME_MODEL
569
+        GV$TEMPFILE
570
+        GV$TEMPORARY_LOBS
571
+        GV$TEMPSEG_USAGE
572
+        GV$TEMPSTAT
573
+        GV$TEMP_CACHE_TRANSFER
574
+        GV$TEMP_EXTENT_MAP
575
+        GV$TEMP_EXTENT_POOL
576
+        GV$TEMP_HISTOGRAM
577
+        GV$TEMP_PING
578
+        GV$TEMP_SPACE_HEADER
579
+        GV$THREAD
580
+        GV$THRESHOLD_TYPES
581
+        GV$TIMER
582
+        GV$TIMEZONE_FILE
583
+        GV$TIMEZONE_NAMES
584
+        GV$TRANSACTION
585
+        GV$TRANSACTION_ENQUEUE
586
+        GV$TSM_SESSIONS
587
+        GV$TYPE_SIZE
588
+        GV$UNDOSTAT
589
+        GV$VERSION
590
+        GV$VPD_POLICY
591
+        GV$WAITCLASSMETRIC
592
+        GV$WAITCLASSMETRIC_HISTORY
593
+        GV$WAITSTAT
594
+        GV$WALLET
595
+        GV$XML_AUDIT_TRAIL
596
+        GV$_LOCK
597
+        HHAND
598
+        HHBYTELEN
599
+        HHCBIT
600
+        HHCELLBNDRY
601
+        HHCELLSIZE
602
+        HHCLDATE
603
+        HHCOLLAPSE
604
+        HHCOMMONCODE
605
+        HHCOMPARE
606
+        HHCOMPOSE
607
+        HHDECODE
608
+        HHDISTANCE
609
+        HHENCODE
610
+        HHENCODE_BYLEVEL
611
+        HHGBIT
612
+        HHGETCID
613
+        HHGROUP
614
+        HHGTBIT
615
+        HHGTYPE
616
+        HHIDLPART
617
+        HHIDPART
618
+        HHINCRLEV
619
+        HHJLDATE
620
+        HHLENGTH
621
+        HHLEVELS
622
+        HHMATCH
623
+        HHMAXCODE
624
+        HHNCOMPARE
625
+        HHNDIM
626
+        HHOR
627
+        HHORDER
628
+        HHPRECISION
629
+        HHSBIT
630
+        HHSETCID
631
+        HHSTBIT
632
+        HHSTYPE
633
+        HHSUBDIVIDE
634
+        HHSUBSTR
635
+        HHXOR
636
+        HS_ALL_CAPS
637
+        HS_ALL_DD
638
+        HS_ALL_INITS
639
+        HS_BASE_CAPS
640
+        HS_BASE_DD
641
+        HS_CLASS_CAPS
642
+        HS_CLASS_DD
643
+        HS_CLASS_INIT
644
+        HS_FDS_CLASS
645
+        HS_FDS_CLASS_DATE
646
+        HS_FDS_INST
647
+        HS_INST_CAPS
648
+        HS_INST_DD
649
+        HS_INST_INIT
650
+        HTF
651
+        HTMLDB
652
+        HTMLDB_ACTIVITY_LOG
653
+        HTMLDB_APPLICATION
654
+        HTMLDB_APPLICATION_FILES
655
+        HTMLDB_APPLICATION_GLOBAL
656
+        HTMLDB_COLLECTION
657
+        HTMLDB_COLLECTIONS
658
+        HTMLDB_CUSTOM_AUTH
659
+        HTMLDB_ITEM
660
+        HTMLDB_LANG
661
+        HTMLDB_LDAP
662
+        HTMLDB_LOGIN
663
+        HTMLDB_MAIL
664
+        HTMLDB_MAIL_LOG
665
+        HTMLDB_MAIL_QUEUE
666
+        HTMLDB_PLSQL_JOB
667
+        HTMLDB_PLSQL_JOBS
668
+        HTMLDB_SYSTEM
669
+        HTMLDB_UTIL
670
+        HTP
671
+        HTTPURITYPE
672
+        IND
673
+        INDEX_HISTOGRAM
674
+        INDEX_STATS
675
+        INTERIORRINGN
676
+        INTERSECTION
677
+        INTERSECTS
678
+        ISCLOSED
679
+        ISEMPTY
680
+        ISRING
681
+        ISSIMPLE
682
+        KU$_AUDDEF_T
683
+        KU$_AUDIT_DEFAULT_LIST_T
684
+        KU$_AUDIT_LIST_T
685
+        KU$_AUDOBJ_T
686
+        KU$_CHUNK_LIST_T
687
+        KU$_CHUNK_T
688
+        KU$_DDL
689
+        KU$_DDLS
690
+        KU$_DUMPFILE
691
+        KU$_DUMPFILE1010
692
+        KU$_DUMPFILE1020
693
+        KU$_DUMPFILESET
694
+        KU$_DUMPFILESET1010
695
+        KU$_DUMPFILESET1020
696
+        KU$_DUMPFILE_INFO
697
+        KU$_DUMPFILE_ITEM
698
+        KU$_ERRORLINE
699
+        KU$_ERRORLINES
700
+        KU$_JAVA_T
701
+        KU$_JOBDESC
702
+        KU$_JOBDESC1010
703
+        KU$_JOBDESC1020
704
+        KU$_JOBSTATUS
705
+        KU$_JOBSTATUS1010
706
+        KU$_JOBSTATUS1020
707
+        KU$_LOGENTRY
708
+        KU$_LOGENTRY1010
709
+        KU$_LOGENTRY1020
710
+        KU$_LOGLINE
711
+        KU$_LOGLINE1010
712
+        KU$_LOGLINE1020
713
+        KU$_MULTI_DDL
714
+        KU$_MULTI_DDLS
715
+        KU$_OBJNUMPAIR
716
+        KU$_OBJNUMPAIRLIST
717
+        KU$_OBJNUMSET
718
+        KU$_PARAMVALUE
719
+        KU$_PARAMVALUE1010
720
+        KU$_PARAMVALUE1020
721
+        KU$_PARAMVALUES
722
+        KU$_PARAMVALUES1010
723
+        KU$_PARAMVALUES1020
724
+        KU$_PARSED_ITEM
725
+        KU$_PARSED_ITEMS
726
+        KU$_PROCOBJ_LINE
727
+        KU$_PROCOBJ_LINES
728
+        KU$_PROCOBJ_LOC
729
+        KU$_PROCOBJ_LOCS
730
+        KU$_SOURCE_LIST_T
731
+        KU$_SOURCE_T
732
+        KU$_STATUS
733
+        KU$_STATUS1010
734
+        KU$_STATUS1020
735
+        KU$_SUBMITRESULT
736
+        KU$_SUBMITRESULTS
737
+        KU$_TACTION_LIST_T
738
+        KU$_TACTION_T
739
+        KU$_VCNT
740
+        KU$_WORKERSTATUS
741
+        KU$_WORKERSTATUS1010
742
+        KU$_WORKERSTATUS1020
743
+        KU$_WORKERSTATUSLIST
744
+        KU$_WORKERSTATUSLIST1010
745
+        KU$_WORKERSTATUSLIST1020
746
+        KUPCC
747
+        LINESTRING
748
+        LINESTRINGFROMTEXT
749
+        LINESTRINGFROMWKB
750
+        LOADER_COL_FLAGS
751
+        LOADER_COL_INFO
752
+        LOADER_COL_TYPE
753
+        LOADER_CONSTRAINT_INFO
754
+        LOADER_DIR_OBJS
755
+        LOADER_FILE_TS
756
+        LOADER_FULL_ATTR_NAME
757
+        LOADER_INTCOL_INFO
758
+        LOADER_LOB_FLAGS
759
+        LOADER_NESTED_VARRAYS
760
+        LOADER_OID_INFO
761
+        LOADER_PARAM_INFO
762
+        LOADER_PART_INFO
763
+        LOADER_REF_INFO
764
+        LOADER_SKIP_UNUSABLE_INDEXES
765
+        LOADER_TAB_INFO
766
+        LOADER_TRIGGER_INFO
767
+        LOCATOR_WITHIN_DISTANCE
768
+        MAP_OBJECT
769
+        MATCHES
770
+        MATCH_SCORE
771
+        MD
772
+        MD_LRS
773
+        MULTICURVE
774
+        MULTILINESTRING
775
+        MULTILINESTRINGFROMTEXT
776
+        MULTILINESTRINGFROMWKB
777
+        MULTIPOINT
778
+        MULTIPOLYGON
779
+        MULTIPOLYGONFROMTEXT
780
+        MULTIPOLYGONFROMWKB
781
+        MULTISURFACE
782
+        MY_SDO_INDEX_METADATA
783
+        NLS_DATABASE_PARAMETERS
784
+        NLS_INSTANCE_PARAMETERS
785
+        NLS_SESSION_PARAMETERS
786
+        NUMGEOMETRIES
787
+        NUMINTERIORRINGS
788
+        NUMPOINTS
789
+        NV
790
+        OBJ
791
+        ODCICONST
792
+        ODM_UTIL
793
+        OGC_CONTAINS
794
+        OGC_LENGTH
795
+        OGC_UNION
796
+        OGIS_GEOMETRY_COLUMNS
797
+        OGIS_SPATIAL_REFERENCE_SYSTEMS
798
+        OL$
799
+        OL$HINTS
800
+        OL$NODES
801
+        OLAP_BOOL_SRF
802
+        OLAP_CONDITION
803
+        OLAP_DATE_SRF
804
+        OLAP_EXPRESSION
805
+        OLAP_EXPRESSION_BOOL
806
+        OLAP_EXPRESSION_DATE
807
+        OLAP_EXPRESSION_TEXT
808
+        OLAP_NUMBER_SRF
809
+        OLAP_SRF_T
810
+        OLAP_TEXT_SRF
811
+        ORA_CLIENT_IP_ADDRESS
812
+        ORA_DATABASE_NAME
813
+        ORA_DES_ENCRYPTED_PASSWORD
814
+        ORA_DICT_OBJ_NAME
815
+        ORA_DICT_OBJ_NAME_LIST
816
+        ORA_DICT_OBJ_OWNER
817
+        ORA_DICT_OBJ_OWNER_LIST
818
+        ORA_DICT_OBJ_TYPE
819
+        ORA_DM_TREE_NODES
820
+        ORA_FI_DECISION_TREE_HORIZ
821
+        ORA_GRANTEE
822
+        ORA_INSTANCE_NUM
823
+        ORA_IS_ALTER_COLUMN
824
+        ORA_IS_DROP_COLUMN
825
+        ORA_IS_SERVERERROR
826
+        ORA_KGLR7_DB_LINKS
827
+        ORA_KGLR7_DEPENDENCIES
828
+        ORA_KGLR7_IDL_CHAR
829
+        ORA_KGLR7_IDL_SB4
830
+        ORA_KGLR7_IDL_UB1
831
+        ORA_KGLR7_IDL_UB2
832
+        ORA_LOGIN_USER
833
+        ORA_PARTITION_POS
834
+        ORA_PRIVILEGE_LIST
835
+        ORA_REVOKEE
836
+        ORA_SERVER_ERROR
837
+        ORA_SERVER_ERROR_DEPTH
838
+        ORA_SERVER_ERROR_MSG
839
+        ORA_SERVER_ERROR_NUM_PARAMS
840
+        ORA_SERVER_ERROR_PARAM
841
+        ORA_SPACE_ERROR_INFO
842
+        ORA_SQL_TXT
843
+        ORA_SYSEVENT
844
+        ORA_WITH_GRANT_OPTION
845
+        OUTLINE
846
+        OUTLN_PKG
847
+        OVERLAP
848
+        OWA
849
+        OWA_CACHE
850
+        OWA_COOKIE
851
+        OWA_CUSTOM
852
+        OWA_GLOBAL
853
+        OWA_IMAGE
854
+        OWA_INIT
855
+        OWA_MATCH
856
+        OWA_OPT_LOCK
857
+        OWA_PATTERN
858
+        OWA_SEC
859
+        OWA_TEXT
860
+        OWA_UTIL
861
+        P
862
+        PATH
863
+        PATH_VIEW
864
+        PBSDE
865
+        PLITBLM
866
+        POINT
867
+        POINTFROMTEXT
868
+        POINTFROMWKB
869
+        POINTN
870
+        POINTONSURFACE
871
+        POLYGON
872
+        POLYGONFROMTEXT
873
+        POLYGONFROMWKB
874
+        PRODUCT_COMPONENT_VERSION
875
+        PRODUCT_PROFILE
876
+        PRODUCT_USER_PROFILE
877
+        PROXY_ROLES
878
+        PROXY_USERS
879
+        PROXY_USERS_AND_ROLES
880
+        PUBLIC_DEPENDENCY
881
+        QUEUE_PRIVILEGES
882
+        RECYCLEBIN
883
+        RELATE
884
+        REPCAT_REPCOLUMN_BASE
885
+        RESOURCE_COST
886
+        RESOURCE_VIEW
887
+        REWRITEARRAYTYPE
888
+        REWRITEMESSAGE
889
+        ROLE_ROLE_PRIVS
890
+        ROLE_SYS_PRIVS
891
+        ROLE_TAB_PRIVS
892
+        RTREEJOINFUNC
893
+        SCHEMA_EXPORT_OBJECTS
894
+        SCN_TO_TIMESTAMP
895
+        SCORE
896
+        SDO
897
+        SDOAGGRTYPE
898
+        SDO_3GL
899
+        SDO_ADDR_ARRAY
900
+        SDO_ADMIN
901
+        SDO_AGGR_CENTROID
902
+        SDO_AGGR_CONCAT_LINES
903
+        SDO_AGGR_CONVEXHULL
904
+        SDO_AGGR_LRS_CONCAT
905
+        SDO_AGGR_LRS_CONCAT_3D
906
+        SDO_AGGR_MBR
907
+        SDO_AGGR_UNION
908
+        SDO_ANGLE_UNITS
909
+        SDO_ANYINTERACT
910
+        SDO_AREA_UNITS
911
+        SDO_AVAILABLE_ELEM_OPS
912
+        SDO_AVAILABLE_NON_ELEM_OPS
913
+        SDO_AVAILABLE_OPS
914
+        SDO_CATALOG
915
+        SDO_CONTAINS
916
+        SDO_COORD_AXES
917
+        SDO_COORD_AXIS_NAMES
918
+        SDO_COORD_OPS
919
+        SDO_COORD_OP_METHODS
920
+        SDO_COORD_OP_PARAMS
921
+        SDO_COORD_OP_PARAM_USE
922
+        SDO_COORD_OP_PARAM_VALS
923
+        SDO_COORD_OP_PATHS
924
+        SDO_COORD_REF_SYS
925
+        SDO_COORD_REF_SYSTEM
926
+        SDO_COORD_SYS
927
+        SDO_COVEREDBY
928
+        SDO_COVERS
929
+        SDO_CRS_COMPOUND
930
+        SDO_CRS_ENGINEERING
931
+        SDO_CRS_GEOCENTRIC
932
+        SDO_CRS_GEOGRAPHIC2D
933
+        SDO_CRS_GEOGRAPHIC3D
934
+        SDO_CRS_PROJECTED
935
+        SDO_CRS_VERTICAL
936
+        SDO_CS
937
+        SDO_DATUMS
938
+        SDO_DATUMS_OLD_FORMAT
939
+        SDO_DATUMS_OLD_SNAPSHOT
940
+        SDO_DATUM_ENGINEERING
941
+        SDO_DATUM_GEODETIC
942
+        SDO_DATUM_VERTICAL
943
+        SDO_DIM_ARRAY
944
+        SDO_DIM_ELEMENT
945
+        SDO_DIST_UNITS
946
+        SDO_EDGE_ARRAY
947
+        SDO_ELEM_INFO_ARRAY
948
+        SDO_ELLIPSOIDS
949
+        SDO_ELLIPSOIDS_OLD_FORMAT
950
+        SDO_ELLIPSOIDS_OLD_SNAPSHOT
951
+        SDO_EQUAL
952
+        SDO_FILTER
953
+        SDO_GEOM
954
+        SDO_GEOMETRY
955
+        SDO_GEO_ADDR
956
+        SDO_INDEX_METADATA
957
+        SDO_INSIDE
958
+        SDO_JOIN
959
+        SDO_KEYWORDARRAY
960
+        SDO_LIST_TYPE
961
+        SDO_LRS
962
+        SDO_MBR
963
+        SDO_MIGRATE
964
+        SDO_NN
965
+        SDO_NN_DISTANCE
966
+        SDO_NUMBER_ARRAY
967
+        SDO_ON
968
+        SDO_ORDINATE_ARRAY
969
+        SDO_OVERLAPBDYDISJOINT
970
+        SDO_OVERLAPBDYINTERSECT
971
+        SDO_OVERLAPS
972
+        SDO_POINT_TYPE
973
+        SDO_PREFERRED_OPS_SYSTEM
974
+        SDO_PREFERRED_OPS_USER
975
+        SDO_PRIDX
976
+        SDO_PRIME_MERIDIANS
977
+        SDO_PROJECTIONS_OLD_FORMAT
978
+        SDO_PROJECTIONS_OLD_SNAPSHOT
979
+        SDO_REGAGGR
980
+        SDO_REGAGGRSET
981
+        SDO_REGION
982
+        SDO_REGIONSET
983
+        SDO_RELATE
984
+        SDO_RELATE_MASK
985
+        SDO_ROWIDPAIR
986
+        SDO_ROWIDSET
987
+        SDO_RTREE_ADMIN
988
+        SDO_RTREE_FILTER
989
+        SDO_RTREE_RELATE
990
+        SDO_SRID_CHAIN
991
+        SDO_SRID_LIST
992
+        SDO_STRING_ARRAY
993
+        SDO_TFM_CHAIN
994
+        SDO_TGL_OBJECT
995
+        SDO_TGL_OBJECT_ARRAY
996
+        SDO_TOPO_DATA$
997
+        SDO_TOPO_GEOMETRY
998
+        SDO_TOPO_GEOMETRY_LAYER
999
+        SDO_TOPO_GEOMETRY_LAYER_ARRAY
1000
+        SDO_TOPO_NSTD_TBL
1001
+        SDO_TOPO_OBJECT
1002
+        SDO_TOPO_OBJECT_ARRAY
1003
+        SDO_TOPO_TRANSACT_DATA$
1004
+        SDO_TOUCH
1005
+        SDO_TRANSIENT_RULE
1006
+        SDO_TRANSIENT_RULE_SET
1007
+        SDO_TUNE
1008
+        SDO_TXN_IDX_DELETES
1009
+        SDO_TXN_IDX_EXP_UPD_RGN
1010
+        SDO_TXN_IDX_INSERTS
1011
+        SDO_UNITS_OF_MEASURE
1012
+        SDO_UTIL
1013
+        SDO_VERSION
1014
+        SDO_VPOINT_TYPE
1015
+        SDO_WITHIN_DISTANCE
1016
+        SEQ
1017
+        SESSION_CONTEXT
1018
+        SESSION_PRIVS
1019
+        SESSION_ROLES
1020
+        SM$VERSION
1021
+        SPATIAL_INDEX
1022
+        SQLPROF_ATTR
1023
+        SQLSET
1024
+        SQLSET_ROW
1025
+        SQL_BIND
1026
+        SQL_BINDS
1027
+        SQL_BIND_SET
1028
+        SQL_OBJECTS
1029
+        SQL_PLAN_ROW_TYPE
1030
+        SQL_PLAN_STAT_ROW_TYPE
1031
+        SRID
1032
+        STARTPOINT
1033
+        STMT_AUDIT_OPTION_MAP
1034
+        SURFACE
1035
+        SYMMETRICDIFFERENCE
1036
+        SYN
1037
+        SYSTEM_PRIVILEGE_MAP
1038
+        SYS_IXQAGG
1039
+        SYS_NT_COLLECT
1040
+        SYS_XMLAGG
1041
+        TEMP$LOB
1042
+        TFM_PLAN
1043
+        TIMESTAMP_TO_SCN
1044
+        TMP_COORD_OPS
1045
+        TOUCH
1046
+        TRUSTED_SERVERS
1047
+        UNDER_PATH
1048
+        URIFACTORY
1049
+        URITYPE
1050
+        USER_
1051
+        UTL_
1052
+        V
1053
+        V$
1054
+        WITHIN
1055
+        WPG_DOCLOAD
1056
+        WWV_
1057
+        X
1058
+        XDB$STRING_LIST_T
1059
+        XDBURITYPE
1060
+        XDB_PVTRIG_PKG
1061
+        XDB_RVTRIG_PKG
1062
+        XMLAGG
1063
+        XMLDOM
1064
+        XMLFORMAT
1065
+        XMLPARSER
1066
+        XMLSEQUENCE
1067
+        XMLSEQUENCETYPE
1068
+        XMLTYPE
1069
+        XQSEQUENCE
1070
+        XSLPROCESSOR
1071
+        Y
1072
+        Z
1073
+        _ALL_INSTANTIATION_DDL
1074
+        _ALL_REPEXTENSIONS
1075
+        _ALL_REPSITES_NEW
1076
+        _ALL_SQLSET_STATEMENTS_ONLY
1077
+        _ALL_SQLSET_STATEMENTS_PHV
1078
+        _ALL_SQLSET_STATISTICS_ONLY
1079
+        SCHEDULER$_JOBSUFFIX_S
1080
+        AUDIT_ACTIONS
1081
+        DUAL
1082
+        IMPDP_STATS
1083
+        KU$NOEXP_TAB
1084
+        ODCI_SECOBJ$
1085
+        ODCI_WARNINGS$
1086
+        PSTUBTBL
1087
+        STMT_AUDIT_OPTION_MAP
1088
+        SYSTEM_PRIVILEGE_MAP
1089
+        WRI$_ADV_ASA_RECO_DATA
1090
+        DEF$_TEMP$LOB
1091
+        HELP
1092
+        OL$
1093
+        OL$HINTS
1094
+        OL$NODES
1095
+        ALL_
1096
+        CATALOG
1097
+        COL
1098
+        COLUMN_PRIVILEGES
1099
+        DATABASE_COMPATIBLE_LEVEL
1100
+        DATABASE_EXPORT_OBJECTS
1101
+        DATABASE_PROPERTIES
1102
+        DATAPUMP_DDL_TRANSFORM_PARAMS
1103
+        DATAPUMP_OBJECT_CONNECT
1104
+        DATAPUMP_PATHMAP
1105
+        DATAPUMP_PATHS
1106
+        DATAPUMP_REMAP_OBJECTS
1107
+        DBA_AUTO_SEGADV_CTL
1108
+        DBA_AUTO_SEGADV_SUMMARY
1109
+        DEFERRCOUNT
1110
+        DICTIONARY
1111
+        DICT_COLUMNS
1112
+        EXPCOMPRESSEDPART
1113
+        EXPCOMPRESSEDSUB
1114
+        EXPCOMPRESSEDTAB
1115
+        EXPEXEMPT
1116
+        EXPGETENCCOLNAM
1117
+        EXPTABSUBPART
1118
+        EXPTABSUBPARTDATA_VIEW
1119
+        EXPTABSUBPARTLOBFRAG
1120
+        EXPTABSUBPARTLOB_VIEW
1121
+        EXU102XTYPU
1122
+        EXU10ADEFPSWITCHES
1123
+        EXU10AOBJSWITCH
1124
+        EXU10ASCU
1125
+        EXU10CCLO
1126
+        EXU10CCLU
1127
+        EXU10COEU
1128
+        EXU10DEFPSWITCHES
1129
+        EXU10DOSO
1130
+        EXU10IND_BASE
1131
+        EXU10LNKU
1132
+        EXU10MVL
1133
+        EXU10MVLU
1134
+        EXU10OBJSWITCH
1135
+        EXU10R2DEFPSWITCHES
1136
+        EXU10R2OBJSWITCH
1137
+        EXU10SNAPLU
1138
+        EXU10SNAPU
1139
+        EXU10TABSU
1140
+        EXU10TABU
1141
+        EXU816MAXSQV
1142
+        EXU816TGRU
1143
+        EXU81ACTIONOBJ
1144
+        EXU81ACTIONPKG
1145
+        EXU81ASSOC
1146
+        EXU81CSC
1147
+        EXU81DOIU
1148
+        EXU81IND
1149
+        EXU81IND_BASE
1150
+        EXU81ITYU
1151
+        EXU81IXCPU
1152
+        EXU81IXSPU
1153
+        EXU81JAV
1154
+        EXU81JAVT
1155
+        EXU81LBCPU
1156
+        EXU81LBPU
1157
+        EXU81LBSPU
1158
+        EXU81NOS
1159
+        EXU81OBJECTPKG
1160
+        EXU81OPRU
1161
+        EXU81PLBU
1162
+        EXU81PROCOBJ
1163
+        EXU81PROCOBJINSTANCE
1164
+        EXU81RGCU
1165
+        EXU81RGSU
1166
+        EXU81RLS
1167
+        EXU81SCMU
1168
+        EXU81SLFCU
1169
+        EXU81SNAPLU
1170
+        EXU81SNAPU
1171
+        EXU81SPOKIU
1172
+        EXU81SPOKU
1173
+        EXU81SRTU
1174
+        EXU81TABSU
1175
+        EXU81TABU
1176
+        EXU81TBCPU
1177
+        EXU81TBSPU
1178
+        EXU81TGRU
1179
+        EXU81TYPU
1180
+        EXU81USCIU
1181
+        EXU8ANAL
1182
+        EXU8ASCU
1183
+        EXU8BSZ
1184
+        EXU8CCLO
1185
+        EXU8CCLU
1186
+        EXU8CCOU
1187
+        EXU8CGRU
1188
+        EXU8CLUU
1189
+        EXU8CMTU
1190
+        EXU8COEU
1191
+        EXU8COLU
1192
+        EXU8CONU
1193
+        EXU8COOU
1194
+        EXU8CPO
1195
+        EXU8CSET
1196
+        EXU8CSNU
1197
+        EXU8DIM
1198
+        EXU8DIMU
1199
+        EXU8FPTU
1200
+        EXU8FUL
1201
+        EXU8GLOB
1202
+        EXU8GRNU
1203
+        EXU8HSTU
1204
+        EXU8ICO
1205
+        EXU8ICOU
1206
+        EXU8ICPLSQL
1207
+        EXU8INDU
1208
+        EXU8INKU
1209
+        EXU8IOVU
1210
+        EXU8IXPU
1211
+        EXU8JBQU
1212
+        EXU8LIBU
1213
+        EXU8LNKU
1214
+        EXU8LOBU
1215
+        EXU8NTBU
1216
+        EXU8NXPU
1217
+        EXU8OIDU
1218
+        EXU8OPT
1219
+        EXU8ORD
1220
+        EXU8ORDU
1221
+        EXU8ORFS
1222
+        EXU8PDSU
1223
+        EXU8PNTU
1224
+        EXU8POKIU
1225
+        EXU8POKU
1226
+        EXU8PSTU
1227
+        EXU8REFU
1228
+        EXU8RFSU
1229
+        EXU8RGCU
1230
+        EXU8RGSU
1231
+        EXU8SCMU
1232
+        EXU8SEQU
1233
+        EXU8SLFCU
1234
+        EXU8SLOGU
1235
+        EXU8SNAPLU
1236
+        EXU8SNAPU
1237
+        EXU8SPSU
1238
+        EXU8SPU
1239
+        EXU8SRTU
1240
+        EXU8STOU
1241
+        EXU8SYNU
1242
+        EXU8TABU
1243
+        EXU8TBPU
1244
+        EXU8TGRU
1245
+        EXU8TNE
1246
+        EXU8TNEB
1247
+        EXU8TYPBU
1248
+        EXU8TYPTU
1249
+        EXU8TYPU
1250
+        EXU8USCU
1251
+        EXU8USRU
1252
+        EXU8VDPTU
1253
+        EXU8VER
1254
+        EXU8VEWU
1255
+        EXU8VINFU
1256
+        EXU8VNCU
1257
+        EXU92FPTPU
1258
+        EXU92FPTU
1259
+        EXU92TGRU
1260
+        EXU92TSP
1261
+        EXU92TSPL
1262
+        EXU9ACTIONOBJ
1263
+        EXU9BJF
1264
+        EXU9BJW
1265
+        EXU9CCLO
1266
+        EXU9CCLU
1267
+        EXU9COEU
1268
+        EXU9COOU
1269
+        EXU9DEFPSWITCHES
1270
+        EXU9DOIU
1271
+        EXU9DOSO
1272
+        EXU9EIP
1273
+        EXU9FGA
1274
+        EXU9GSAS
1275
+        EXU9IND
1276
+        EXU9IND_BASE
1277
+        EXU9INHCOLCONS
1278
+        EXU9IXCPU
1279
+        EXU9LBCPU
1280
+        EXU9LBPU
1281
+        EXU9LNKU
1282
+        EXU9LOBU
1283
+        EXU9MVL
1284
+        EXU9MVLCDCCC
1285
+        EXU9MVLCDCS
1286
+        EXU9MVLCDCSC
1287
+        EXU9MVLCDCST
1288
+        EXU9MVLU
1289
+        EXU9NLS
1290
+        EXU9NOS
1291
+        EXU9OBJSWITCH
1292
+        EXU9OTNNULL
1293
+        EXU9PCT
1294
+        EXU9PDSU
1295
+        EXU9PGP
1296
+        EXU9PLBU
1297
+        EXU9PTS
1298
+        EXU9RLS
1299
+        EXU9SNAPLU
1300
+        EXU9SNAPU
1301
+        EXU9STOU
1302
+        EXU9SYNU
1303
+        EXU9TABSU
1304
+        EXU9TABU
1305
+        EXU9TAB_UNUSED_COLS
1306
+        EXU9TBCPU
1307
+        EXU9TNE
1308
+        EXU9TNEB
1309
+        EXU9TYPTU
1310
+        EXU9TYPTU2
1311
+        EXU9TYPU
1312
+        EXU9UTSU
1313
+        EXU9XDBUID
1314
+        EXU9XMLST
1315
+        EXU9XTB
1316
+        FLASHBACK_TRANSACTION_QUERY
1317
+        GLOBAL_CONTEXT
1318
+        GLOBAL_NAME
1319
+        GV_$ACTIVE_INSTANCES
1320
+        GV_$ACTIVE_SESS_POOL_MTH
1321
+        GV_$AW_AGGREGATE_OP
1322
+        GV_$AW_ALLOCATE_OP
1323
+        GV_$AW_CALC
1324
+        GV_$AW_LONGOPS
1325
+        GV_$AW_OLAP
1326
+        GV_$AW_SESSION_INFO
1327
+        GV_$BH
1328
+        GV_$BLOCKING_QUIESCE
1329
+        GV_$LOADISTAT
1330
+        GV_$LOADPSTAT
1331
+        GV_$LOCK_ACTIVITY
1332
+        GV_$MAX_ACTIVE_SESS_TARGET_MTH
1333
+        GV_$NLS_PARAMETERS
1334
+        GV_$NLS_VALID_VALUES
1335
+        GV_$OPTION
1336
+        GV_$PARALLEL_DEGREE_LIMIT_MTH
1337
+        GV_$PQ_SESSTAT
1338
+        GV_$PQ_TQSTAT
1339
+        GV_$QUEUEING_MTH
1340
+        GV_$RESTORE_POINT
1341
+        GV_$RSRC_CONSUMER_GROUP
1342
+        GV_$RSRC_CONSUME_GROUP_CPU_MTH
1343
+        GV_$RSRC_CONS_GROUP_HISTORY
1344
+        GV_$RSRC_PLAN
1345
+        GV_$RSRC_PLAN_CPU_MTH
1346
+        GV_$RSRC_PLAN_HISTORY
1347
+        GV_$RSRC_SESSION_INFO
1348
+        GV_$SESSION_LONGOPS
1349
+        GV_$TEMPORARY_LOBS
1350
+        GV_$TIMEZONE_FILE
1351
+        GV_$TIMEZONE_NAMES
1352
+        GV_$VERSION
1353
+        IMP8CDTU
1354
+        IMP8REPCAT
1355
+        IMP8TTDU
1356
+        IMP8UEC
1357
+        IMP9COMPAT
1358
+        IMP9SYN4
1359
+        IMP9TVOID
1360
+        IMP9USR
1361
+        IMP_LOB_INFO
1362
+        IMP_LOB_NOTNULL
1363
+        IMP_TAB_TRIG
1364
+        INDEX_HISTOGRAM
1365
+        INDEX_STATS
1366
+        KU$
1367
+        KU_NOEXP_VIEW
1368
+        LOADER_
1369
+        NLS_DATABASE_PARAMETERS
1370
+        NLS_INSTANCE_PARAMETERS
1371
+        NLS_SESSION_PARAMETERS
1372
+        ORA_KGLR7_DB_LINKS
1373
+        ORA_KGLR7_DEPENDENCIES
1374
+        ORA_KGLR7_IDL_CHAR
1375
+        ORA_KGLR7_IDL_SB4
1376
+        ORA_KGLR7_IDL_UB1
1377
+        ORA_KGLR7_IDL_UB2
1378
+        PRODUCT_COMPONENT_VERSION
1379
+        PUBLICSYN
1380
+        PUBLIC_DEPENDENCY
1381
+        QUEUE_PRIVILEGES
1382
+        RESOURCE_COST
1383
+        ROLE_ROLE_PRIVS
1384
+        ROLE_SYS_PRIVS
1385
+        ROLE_TAB_PRIVS
1386
+        SCHEMA_EXPORT_OBJECTS
1387
+        SESSION_CONTEXT
1388
+        SESSION_PRIVS
1389
+        SESSION_ROLES
1390
+        SM_$VERSION
1391
+        SYNONYMS
1392
+        SYSCATALOG
1393
+        SYSFILES
1394
+        SYSSEGOBJ
1395
+        USER_
1396
+        UTL_ALL_IND_COMPS
1397
+        V$OBJECT_USAGE
1398
+        V_$ACTIVE_INSTANCES
1399
+        V_$ACTIVE_SESS_POOL_MTH
1400
+        V_$ADVISOR_PROGRESS
1401
+        V_$AW_AGGREGATE_OP
1402
+        V_$AW_ALLOCATE_OP
1403
+        V_$AW_CALC
1404
+        V_$AW_LONGOPS
1405
+        V_$AW_OLAP
1406
+        V_$AW_SESSION_INFO
1407
+        V_$BH
1408
+        V_$BLOCKING_QUIESCE
1409
+        V_$LOADISTAT
1410
+        V_$LOADPSTAT
1411
+        V_$LOCK_ACTIVITY
1412
+        V_$MAX_ACTIVE_SESS_TARGET_MTH
1413
+        V_$NLS_PARAMETERS
1414
+        V_$NLS_VALID_VALUES
1415
+        V_$OPTION
1416
+        V_$PARALLEL_DEGREE_LIMIT_MTH
1417
+        V_$PQ_SESSTAT
1418
+        V_$PQ_TQSTAT
1419
+        V_$QUEUEING_MTH
1420
+        V_$RESTORE_POINT
1421
+        V_$RSRC_CONSUMER_GROUP
1422
+        V_$RSRC_CONSUMER_GROUP_CPU_MTH
1423
+        V_$RSRC_CONS_GROUP_HISTORY
1424
+        V_$RSRC_PLAN
1425
+        V_$RSRC_PLAN_CPU_MTH
1426
+        V_$RSRC_PLAN_HISTORY
1427
+        V_$RSRC_SESSION_INFO
1428
+        V_$SESSION_CONNECT_INFO
1429
+        V_$SESSION_LONGOPS
1430
+        V_$TEMPORARY_LOBS
1431
+        V_$TIMEZONE_FILE
1432
+        V_$TIMEZONE_NAMES
1433
+        V_$VERSION
1434
+        _ALL_FILE_GROUPS
1435
+        _ALL_FILE_GROUP_EXPORT_INFO
1436
+        _ALL_FILE_GROUP_FILES
1437
+        _ALL_FILE_GROUP_TABLES
1438
+        _ALL_FILE_GROUP_TABLESPACES
1439
+        _ALL_FILE_GROUP_VERSIONS
1440
+        _ALL_INSTANTIATION_DDL
1441
+        _ALL_REPCOLUMN
1442
+        _ALL_REPCOLUMN_GROUP
1443
+        _ALL_REPCONFLICT
1444
+        _ALL_REPEXTENSIONS
1445
+        _ALL_REPFLAVOR_OBJECTS
1446
+        _ALL_REPGROUPED_COLUMN
1447
+        _ALL_REPPARAMETER_COLUMN
1448
+        _ALL_REPRESOLUTION
1449
+        _ALL_REPSITES_NEW
1450
+        _ALL_SQLSET_STATEMENTS_ONLY
1451
+        _ALL_SQLSET_STATEMENTS_PHV
1452
+        _ALL_SQLSET_STATISTICS_ONLY
1453
+        PRODUCT_PRIVS
1454
+        DR$NUMBER_SEQUENCE
1455
+        DR$OBJECT_ATTRIBUTE
1456
+        DR$POLICY_TAB
1457
+        BIN$qoPod3b/5/jgQAB/AQB1gw==$0
1458
+        BIN$qoa+IroQdCDgQAB/AQAShg==$0
1459
+        BIN$qoa+gX3av6bgQAB/AQASoA==$0
1460
+        BIN$qoa97kXfAGHgQAB/AQASdw==$0
1461
+        BIN$qoaJ7wJwYOLgQAB/AQAITA==$0
1462
+        BIN$qoamIR+TOebgQAB/AQANmw==$0
1463
+        BIN$qoamP2m44xXgQAB/AQANoA==$0
1464
+        BIN$qoamm6N5i3bgQAB/AQANtg==$0
1465
+        BIN$qob17xzsmp3gQAB/AQAgOA==$0
1466
+        BIN$qod/Sxxh583gQAB/AQAGVg==$0
1467
+        BIN$qod/pFQZipXgQAB/AQAGaw==$0
1468
+        WWV_FLOW_DUAL100
1469
+        WWV_FLOW_FIELD_TEMPLATES
1470
+        WWV_FLOW_LISTS_OF_VALUES$
1471
+        WWV_FLOW_LIST_OF_VALUES_DATA
1472
+        WWV_FLOW_LOV_TEMP
1473
+        WWV_FLOW_PATCHES
1474
+        WWV_FLOW_TEMP_TABLE
1475
+        OGIS_GEOMETRY_COLUMNS
1476
+        OGIS_SPATIAL_REFERENCE_SYSTEMS
1477
+        SDO_COORD_AXES
1478
+        SDO_COORD_AXIS_NAMES
1479
+        SDO_COORD_OPS
1480
+        SDO_COORD_OP_METHODS
1481
+        SDO_COORD_OP_PARAMS
1482
+        SDO_COORD_OP_PARAM_USE
1483
+        SDO_COORD_OP_PARAM_VALS
1484
+        SDO_COORD_OP_PATHS
1485
+        SDO_COORD_REF_SYS
1486
+        SDO_COORD_SYS
1487
+        SDO_CS_SRS
1488
+        SDO_DATUMS
1489
+        SDO_DATUMS_OLD_SNAPSHOT
1490
+        SDO_ELLIPSOIDS
1491
+        SDO_ELLIPSOIDS_OLD_SNAPSHOT
1492
+        SDO_PREFERRED_OPS_SYSTEM
1493
+        SDO_PREFERRED_OPS_USER
1494
+        SDO_PRIME_MERIDIANS
1495
+        SDO_PROJECTIONS_OLD_SNAPSHOT
1496
+        SDO_TOPO_DATA$
1497
+        SDO_TOPO_RELATION_DATA
1498
+        SDO_TOPO_TRANSACT_DATA
1499
+        SDO_TXN_IDX_DELETES
1500
+        SDO_TXN_IDX_EXP_UPD_RGN
1501
+        SDO_TXN_IDX_INSERTS
1502
+        SDO_UNITS_OF_MEASURE
1503
+        XDB$ACL
1504
+        XDB$ALL_MODEL
1505
+        XDB$ANY
1506
+        XDB$ANYATTR
1507
+        XDB$ATTRGROUP_DEF
1508
+        XDB$ATTRGROUP_REF
1509
+        XDB$ATTRIBUTE
1510
+        XDB$CHOICE_MODEL
1511
+        XDB$COMPLEX_TYPE
1512
+        XDB$ELEMENT
1513
+        XDB$GROUP_DEF
1514
+        XDB$GROUP_REF
1515
+        XDB$SCHEMA
1516
+        XDB$SEQUENCE_MODEL
1517
+        XDB$SIMPLE_TYPE
1518
+        CTX_CLASSES
1519
+        CTX_INDEX_SETS
1520
+        CTX_INDEX_SET_INDEXES
1521
+        CTX_OBJECTS
1522
+        CTX_OBJECT_ATTRIBUTES
1523
+        CTX_OBJECT_ATTRIBUTE_LOV
1524
+        CTX_PARAMETERS
1525
+        CTX_PREFERENCES
1526
+        CTX_PREFERENCE_VALUES
1527
+        CTX_SECTIONS
1528
+        CTX_SECTION_GROUPS
1529
+        CTX_SQES
1530
+        CTX_STOPLISTS
1531
+        CTX_STOPWORDS
1532
+        CTX_SUB_LEXERS
1533
+        CTX_THESAURI
1534
+        CTX_THES_PHRASES
1535
+        CTX_TRACE_VALUES
1536
+        CTX_USER_INDEXES
1537
+        CTX_USER_INDEX_ERRORS
1538
+        CTX_USER_INDEX_OBJECTS
1539
+        CTX_USER_INDEX_PARTITIONS
1540
+        CTX_USER_INDEX_SETS
1541
+        CTX_USER_INDEX_SET_INDEXES
1542
+        CTX_USER_INDEX_SUB_LEXERS
1543
+        CTX_USER_INDEX_SUB_LEXER_VALS
1544
+        CTX_USER_INDEX_VALUES
1545
+        CTX_USER_PENDING
1546
+        CTX_USER_PREFERENCES
1547
+        CTX_USER_PREFERENCE_VALUES
1548
+        CTX_USER_SECTIONS
1549
+        CTX_USER_SECTION_GROUPS
1550
+        CTX_USER_SQES
1551
+        CTX_USER_STOPLISTS
1552
+        CTX_USER_STOPWORDS
1553
+        CTX_USER_SUB_LEXERS
1554
+        CTX_USER_THESAURI
1555
+        CTX_USER_THES_PHRASES
1556
+        DRV$DELETE
1557
+        DRV$DELETE2
1558
+        DRV$ONLINE_PENDING
1559
+        DRV$PENDING
1560
+        DRV$UNINDEXED
1561
+        DRV$UNINDEXED2
1562
+        DRV$WAITING
1563
+        WWV_FLOW_CLICKTHRU_LOG
1564
+        WWV_FLOW_COLLECTIONS
1565
+        WWV_FLOW_FILES
1566
+        WWV_FLOW_GROUP_USERS
1567
+        WWV_FLOW_HOURS_12
1568
+        WWV_FLOW_HOURS_24
1569
+        WWV_FLOW_MINUTES
1570
+        WWV_FLOW_MINUTES_5
1571
+        WWV_FLOW_MONTHS_MON
1572
+        WWV_FLOW_MONTHS_MONTH
1573
+        WWV_FLOW_PLSQL_JOBS
1574
+        WWV_FLOW_USERS
1575
+        WWV_FLOW_USER_ACTIVITY_LOG
1576
+        WWV_FLOW_USER_MAIL_LOG
1577
+        WWV_FLOW_USER_MAIL_QUEUE
1578
+        WWV_FLOW_YEARS
1579
+        ALL_GEOMETRY_COLUMNS
1580
+        ALL_SDO_GEOM_METADATA
1581
+        ALL_SDO_INDEX_INFO
1582
+        ALL_SDO_INDEX_METADATA
1583
+        ALL_SDO_LRS_METADATA
1584
+        ALL_SDO_MAPS
1585
+        ALL_SDO_STYLES
1586
+        ALL_SDO_THEMES
1587
+        ALL_SDO_TOPO_INFO
1588
+        ALL_SDO_TOPO_METADATA
1589
+        CS_SRS
1590
+        DBA_SDO_MAPS
1591
+        DBA_SDO_STYLES
1592
+        DBA_SDO_THEMES
1593
+        GEODETIC_SRIDS
1594
+        MY_SDO_INDEX_METADATA
1595
+        SDO_ANGLE_UNITS
1596
+        SDO_AREA_UNITS
1597
+        SDO_AVAILABLE_ELEM_OPS
1598
+        SDO_AVAILABLE_NON_ELEM_OPS
1599
+        SDO_AVAILABLE_OPS
1600
+        SDO_COORD_REF_SYSTEM
1601
+        SDO_CRS_COMPOUND
1602
+        SDO_CRS_ENGINEERING
1603
+        SDO_CRS_GEOCENTRIC
1604
+        SDO_CRS_GEOGRAPHIC2D
1605
+        SDO_CRS_GEOGRAPHIC3D
1606
+        SDO_CRS_PROJECTED
1607
+        SDO_CRS_VERTICAL
1608
+        SDO_DATUMS_OLD_FORMAT
1609
+        SDO_DATUM_ENGINEERING
1610
+        SDO_DATUM_GEODETIC
1611
+        SDO_DATUM_VERTICAL
1612
+        SDO_DIST_UNITS
1613
+        SDO_ELLIPSOIDS_OLD_FORMAT
1614
+        SDO_PROJECTIONS_OLD_FORMAT
1615
+        SDO_RELATEMASK_TABLE
1616
+        SDO_TOPO_TRANSACT_DATA$
1617
+        USER_
1618
+        PATH_VIEW
1619
+        RESOURCE_VIEW
1620
+        CHANGE_TABLES
1621
+        DATAPUMP_TABLE_DATA
1622
+        GV$DB_TRANSPORTABLE_PLATFORM
1623
+        GV$FIXED_TABLE
1624
+        GV$TABLESPACE
1625
+        GV$TRANSPORTABLE_PLATFORM
1626
+        OLAPRC_TABLE
1627
+        OLAP_TABLE
1628
+        ORA_IS_CREATING_NESTED_TABLE
1629
+        SQL_PLAN_TABLE_TYPE
1630
+        TABLESPACE_EXPORT_OBJECTS
1631
+        TABLE_EXPORT_OBJECTS
1632
+        TABLE_PRIVILEGES
1633
+        TABLE_PRIVILEGE_MAP
1634
+        TABQUOTAS
1635
+        TABS
1636
+        TRANSPORTABLE_EXPORT_OBJECTS
1637
+    #;
1638
+
1639
+    @system_tables = map {quotemeta $_} @system_tables;
1640
+    push @system_tables, 'BIN';
1641
+    my $system_table_re = '^(' . join('|', @system_tables) . ')';
1642
+    
1643
+    has exclude_table => sub {
1644
+        return $system_table_re;
1645
+    };
1646
+
1647
+    has dsn => 'dbi:Oracle:host=localhost;port=1521;sid=XE';
1648
+    has user  => 'dbix_custom';
1649
+    has password => 'dbix_custom';
1650
+
1651
+    sub create_table1 { "create table $table1 ($key1 varchar2(255), $key2 varchar2(255))" }
1652
+    sub create_table1_2 { "create table $table1 ($key1 varchar2(255), $key2 varchar2(255), "
1653
+     . "$key3 varchar2(255), $key4 varchar2(255), $key5 varchar2(255))" }
1654
+    sub create_table1_type { "create table $table1 ($key1 $date_typename, $key2 $datetime_typename)" }
1655
+    sub create_table1_highperformance { "create table $table1 ($key1 varchar2(255), $key2 varchar2(255), "
1656
+      . "$key3 varchar2(255), $key4 varchar2(255), $key5 varchar2(255), $key6 varchar2(255), $key7 varchar2(255))" }
1657
+    sub create_table2 { "create table $table2 ($key1 varchar2(255), $key3 varchar2(255))" }
1658
+    sub create_table2_2 { "create table $table2 ($key1 varchar2(255), $key2 varchar2(255), $key3 varchar2(255))" }
1659
+    sub create_table3 { "create table $table3 ($key1 varchar2(255), $key2 varchar2(255), $key3 varchar2(255))" }
1660
+    sub create_table_reserved { 'create table "table" ("select" varchar2(255), "update" varchar2(255))' }
1661
+}
1662
+
1663
+require "$FindBin::Bin/common.t";
+105
t/next/common-postgresql.t
... ...
@@ -0,0 +1,105 @@
1
+use strict;
2
+use warnings;
3
+
4
+use FindBin;
5
+use lib "$FindBin::Bin/common";
6
+$ENV{DBIX_CUSTOM_TEST_RUN} = 1
7
+  if -f "$FindBin::Bin/run/common-postgresql.run";
8
+$ENV{DBIX_CUSTOM_SKIP_MESSAGE} = 'postgresql private test';
9
+
10
+use DBIx::Custom::Next;
11
+{
12
+    package DBIx::Custom::Next;
13
+    no warnings 'redefine';
14
+
15
+    my $table1 = 'table1';
16
+    my $table2 = 'table2';
17
+    my $table2_alias = 'table2_alias';
18
+    my $table3 = 'table3';
19
+    my $key1 = 'key1';
20
+    my $key2 = 'key2';
21
+    my $key3 = 'key3';
22
+    my $key4 = 'key4';
23
+    my $key5 = 'key5';
24
+    my $key6 = 'key6';
25
+    my $key7 = 'key7';
26
+    my $key8 = 'key8';
27
+    my $key9 = 'key9';
28
+    my $key10 = 'key10';
29
+    
30
+    has table1 => $table1;
31
+    has table2 => $table2;
32
+    has table2_alias => $table2_alias;
33
+    has table3 => $table3;
34
+    has key1 => $key1;
35
+    has key2 => $key2;
36
+    has key3 => $key3;
37
+    has key4 => $key4;
38
+    has key5 => $key5;
39
+    has key6 => $key6;
40
+    has key7 => $key7;
41
+    has key8 => $key8;
42
+    has key9 => $key9;
43
+    has key10 => $key10;
44
+
45
+    my $date_typename = 'Date';
46
+    my $datetime_typename = 'Timestamp';
47
+
48
+    sub date_typename { lc $date_typename }
49
+    sub datetime_typename { 'timestamp without time zone' }
50
+
51
+    my $date_datatype = 91;
52
+    my $datetime_datatype = 11;
53
+
54
+    sub date_datatype { lc $date_datatype }
55
+    sub datetime_datatype { lc $datetime_datatype }
56
+
57
+    has dsn => "dbi:Pg:dbname=dbix_custom";
58
+    has user  => 'dbix_custom';
59
+    has password => 'dbix_custom';
60
+    has exclude_table => sub {
61
+
62
+        return qr/^(
63
+            pg_|column_|role_|view_|sql_
64
+            |applicable_roles
65
+            |check_constraints
66
+            |columns
67
+            |constraint_column_usage
68
+            |constraint_table_usage
69
+            |data_type_privileges
70
+            |domain_constraints
71
+            |domain_udt_usage
72
+            |domains
73
+            |element_types
74
+            |enabled_roles
75
+            |information_schema
76
+            |information_schema_catalog_name
77
+            |key_column_usage
78
+            |parameters
79
+            |referential_constraints
80
+            |routine_privileges
81
+            |routines
82
+            |schemata
83
+            |table_constraints
84
+            |table_privileges
85
+            |tables
86
+            |triggered_update_columns
87
+            |triggers
88
+            |usage_privileges
89
+            |views
90
+        )/x
91
+    };
92
+    
93
+    sub create_table1 { "create table $table1 ($key1 varchar(255), $key2 varchar(255))" }
94
+    sub create_table1_2 {"create table $table1 ($key1 varchar(255), $key2 varchar(255), "
95
+     . "$key3 varchar(255), $key4 varchar(255), $key5 varchar(255))" }
96
+    sub create_table1_type { "create table $table1 ($key1 $date_typename, $key2 $datetime_typename)" }
97
+    sub create_table1_highperformance { "create table $table1 ($key1 varchar(255), $key2 varchar(255), "
98
+      . "$key3 varchar(255), $key4 varchar(255), $key5 varchar(255), $key6 varchar(255), $key7 varchar(255))" }
99
+    sub create_table2 { "create table $table2 ($key1 varchar(255), $key3 varchar(255))" }
100
+    sub create_table2_2 { "create table $table2 ($key1 varchar(255), $key2 varchar(255), $key3 varchar(255))" }
101
+    sub create_table3 { "create table $table3 ($key1 varchar(255), $key2 varchar(255), $key3 varchar(255))" }
102
+    sub create_table_reserved { 'create table "table" ("select" varchar(255), "update" varchar(255))' }
103
+}
104
+
105
+require "$FindBin::Bin/common.t";
+70
t/next/common-sqlite-quote.t
... ...
@@ -0,0 +1,70 @@
1
+use strict;
2
+use warnings;
3
+
4
+use FindBin;
5
+use lib "$FindBin::Bin/common";
6
+$ENV{DBIX_CUSTOM_TEST_RUN} = 1;
7
+
8
+use DBIx::Custom::Next;
9
+{
10
+    package DBIx::Custom::Next;
11
+    no warnings 'redefine';
12
+    
13
+    my $table1 = 'table1';
14
+    my $table2 = 'table2';
15
+    my $table2_alias = 'table2_alias';
16
+    my $table3 = 'table3';
17
+    my $key1 = 'key1';
18
+    my $key2 = 'key2';
19
+    my $key3 = 'key3';
20
+    my $key4 = 'key4';
21
+    my $key5 = 'key5';
22
+    my $key6 = 'key6';
23
+    my $key7 = 'key7';
24
+    my $key8 = 'key8';
25
+    my $key9 = 'key9';
26
+    my $key10 = 'key10';
27
+    
28
+    has table1 => $table1;
29
+    has table2 => $table2;
30
+    has table2_alias => $table2_alias;
31
+    has table3 => $table3;
32
+    has key1 => $key1;
33
+    has key2 => $key2;
34
+    has key3 => $key3;
35
+    has key4 => $key4;
36
+    has key5 => $key5;
37
+    has key6 => $key6;
38
+    has key7 => $key7;
39
+    has key8 => $key8;
40
+    has key9 => $key9;
41
+    has key10 => $key10;
42
+    
43
+    my $date_typename = 'Date';
44
+    my $datetime_typename = 'Datetime';
45
+    
46
+    sub date_typename { lc $date_typename }
47
+    sub datetime_typename { lc $datetime_typename }
48
+
49
+    my $date_datatype = 'Date';
50
+    my $datetime_datatype = 'Datetime';
51
+    
52
+    sub date_datatype { lc $date_datatype }
53
+    sub datetime_datatype { lc $datetime_datatype }
54
+
55
+    has dsn => 'dbi:SQLite:dbname=:memory:';
56
+    sub create_table1 { "create table $table1 ($key1 varchar, $key2 varchar)" }
57
+    sub create_table1_2 {"create table $table1 ($key1 varchar, $key2 varchar, $key3 varchar, key4 varchar, key5 varchar)" }
58
+    sub create_table1_type { "create table $table1 ($key1 $date_typename, $key2 $datetime_typename)" }
59
+    
60
+    sub create_table1_highperformance { "create table $table1 (key1 varchar, key2 varchar, key3 varchar, key4 varchar, key5 varchar, key6 varchar, key7 varchar)" }
61
+    
62
+    sub create_table2 { "create table $table2 ($key1 varchar, $key3 varchar)" }
63
+    sub create_table2_2 { "create table $table2 ($key1 varchar, $key2 varchar, $key3 varchar)" }
64
+    sub create_table3 { "create table $table3 ($key1 varchar, $key2 varchar, $key3 varchar)" }
65
+    sub create_table_reserved { 'create table "table" ("select" varchar, "update" varchar)' }
66
+
67
+    sub quote { '""' }
68
+}
69
+
70
+require "$FindBin::Bin/common.t";
+69
t/next/common-sqlite.t
... ...
@@ -0,0 +1,69 @@
1
+use strict;
2
+use warnings;
3
+
4
+use FindBin;
5
+use lib "$FindBin::Bin/common";
6
+$ENV{DBIX_CUSTOM_TEST_RUN} = 1;
7
+
8
+use DBIx::Custom::Next;
9
+{
10
+    package DBIx::Custom::Next;
11
+    no warnings 'redefine';
12
+    
13
+    my $table1 = 'table1';
14
+    my $table2 = 'table2';
15
+    my $table2_alias = 'table2_alias';
16
+    my $table3 = 'table3';
17
+    my $key1 = 'key1';
18
+    my $key2 = 'key2';
19
+    my $key3 = 'key3';
20
+    my $key4 = 'key4';
21
+    my $key5 = 'key5';
22
+    my $key6 = 'key6';
23
+    my $key7 = 'key7';
24
+    my $key8 = 'key8';
25
+    my $key9 = 'key9';
26
+    my $key10 = 'key10';
27
+    
28
+    has table1 => $table1;
29
+    has table2 => $table2;
30
+    has table2_alias => $table2_alias;
31
+    has table3 => $table3;
32
+    has key1 => $key1;
33
+    has key2 => $key2;
34
+    has key3 => $key3;
35
+    has key4 => $key4;
36
+    has key5 => $key5;
37
+    has key6 => $key6;
38
+    has key7 => $key7;
39
+    has key8 => $key8;
40
+    has key9 => $key9;
41
+    has key10 => $key10;
42
+    
43
+    my $date_typename = 'Date';
44
+    my $datetime_typename = 'Datetime';
45
+    
46
+    sub date_typename { lc $date_typename }
47
+    sub datetime_typename { lc $datetime_typename }
48
+
49
+    my $date_datatype = 'Date';
50
+    my $datetime_datatype = 'Datetime';
51
+    
52
+    sub date_datatype { lc $date_datatype }
53
+    sub datetime_datatype { lc $datetime_datatype }
54
+
55
+    has dsn => 'dbi:SQLite:dbname=:memory:';
56
+    sub create_table1 { "create table $table1 ($key1 varchar, $key2 varchar)" }
57
+    sub create_table1_2 {"create table $table1 ($key1 varchar, $key2 varchar, $key3 varchar, key4 varchar, key5 varchar)" }
58
+    sub create_table1_type { "create table $table1 ($key1 $date_typename, $key2 $datetime_typename)" }
59
+    
60
+    sub create_table1_highperformance { "create table $table1 (key1 varchar, key2 varchar, key3 varchar, key4 varchar, key5 varchar, key6 varchar, key7 varchar)" }
61
+    
62
+    sub create_table2 { "create table $table2 ($key1 varchar, $key3 varchar)" }
63
+    sub create_table2_2 { "create table $table2 ($key1 varchar, $key2 varchar, $key3 varchar)" }
64
+    sub create_table3 { "create table $table3 ($key1 varchar, $key2 varchar, $key3 varchar)" }
65
+    sub create_table_reserved { 'create table "table" ("select" varchar, "update" varchar)' }
66
+    
67
+}
68
+
69
+require "$FindBin::Bin/common.t";
+428
t/next/common-sqlserver.t
... ...
@@ -0,0 +1,428 @@
1
+use strict;
2
+use warnings;
3
+
4
+use FindBin;
5
+use lib "$FindBin::Bin/common";
6
+$ENV{DBIX_CUSTOM_TEST_RUN} = 1
7
+  if -f "$FindBin::Bin/run/common-sqlserver.run";
8
+$ENV{DBIX_CUSTOM_SKIP_MESSAGE} = 'sqlserver private test';
9
+
10
+use DBIx::Custom::Next;
11
+{
12
+    package DBIx::Custom::Next;
13
+    no warnings 'redefine';
14
+
15
+    my $table1 = 'table1';
16
+    my $table2 = 'table2';
17
+    my $table2_alias = 'table2_alias';
18
+    my $table3 = 'table3';
19
+    my $key1 = 'key1';
20
+    my $key2 = 'key2';
21
+    my $key3 = 'key3';
22
+    my $key4 = 'key4';
23
+    my $key5 = 'key5';
24
+    my $key6 = 'key6';
25
+    my $key7 = 'key7';
26
+    my $key8 = 'key8';
27
+    my $key9 = 'key9';
28
+    my $key10 = 'key10';
29
+    
30
+    has table1 => $table1;
31
+    has table2 => $table2;
32
+    has table2_alias => $table2_alias;
33
+    has table3 => $table3;
34
+    has key1 => $key1;
35
+    has key2 => $key2;
36
+    has key3 => $key3;
37
+    has key4 => $key4;
38
+    has key5 => $key5;
39
+    has key6 => $key6;
40
+    has key7 => $key7;
41
+    has key8 => $key8;
42
+    has key9 => $key9;
43
+    has key10 => $key10;
44
+
45
+    my $date_typename = 'date';
46
+    my $datetime_typename = 'datetime';
47
+
48
+    sub date_typename { lc $date_typename }
49
+    sub datetime_typename { lc $datetime_typename }
50
+
51
+    my $date_datatype = -9;
52
+    my $datetime_datatype = 93;
53
+
54
+    sub date_datatype { lc $date_datatype }
55
+    sub datetime_datatype { lc $datetime_datatype }
56
+
57
+    has exclude_table => sub {
58
+        return qr/^(
59
+          CHECK_CONSTRAINTS
60
+          |COLUMN_DOMAIN_USAGE
61
+          |COLUMN_PRIVILEGES
62
+          |COLUMNS
63
+          |CONSTRAINT_COLUMN_USAGE
64
+          |CONSTRAINT_TABLE_USAGE
65
+          |DOMAIN_CONSTRAINTS
66
+          |DOMAINS
67
+          |KEY_COLUMN_USAGE
68
+          |PARAMETERS
69
+          |REFERENTIAL_CONSTRAINTS
70
+          |ROUTINE_COLUMNS
71
+          |ROUTINES
72
+          |SCHEMATA
73
+          |TABLE_CONSTRAINTS
74
+          |TABLE_PRIVILEGES
75
+          |TABLES
76
+          |VIEW_COLUMN_USAGE
77
+          |VIEW_TABLE_USAGE
78
+          |VIEWS
79
+          |all_columns
80
+          |all_objects
81
+          |all_parameters
82
+          |all_sql_modules
83
+          |all_views
84
+          |allocation_units
85
+          |assemblies
86
+          |assembly_files
87
+          |assembly_modules
88
+          |assembly_references
89
+          |assembly_types
90
+          |asymmetric_keys
91
+          |backup_devices
92
+          |certificates
93
+          |change_tracking_databases
94
+          |change_tracking_tables
95
+          |check_constraints
96
+          |column_type_usages
97
+          |column_xml_schema_collection_usages
98
+          |columns
99
+          |computed_columns
100
+          |configurations
101
+          |conversation_endpoints
102
+          |conversation_groups
103
+          |conversation_priorities
104
+          |credentials
105
+          |crypt_properties
106
+          |cryptographic_providers
107
+          |data_spaces
108
+          |database_audit_specification_details
109
+          |database_audit_specifications
110
+          |database_files
111
+          |database_mirroring
112
+          |database_mirroring_endpoints
113
+          |database_permissions
114
+          |database_principal_aliases
115
+          |database_principals
116
+          |database_recovery_status
117
+          |database_role_members
118
+          |databases
119
+          |default_constraints
120
+          |destination_data_spaces
121
+          |dm_audit_actions
122
+          |dm_audit_class_type_map
123
+          |dm_broker_activated_tasks
124
+          |dm_broker_connections
125
+          |dm_broker_forwarded_messages
126
+          |dm_broker_queue_monitors
127
+          |dm_cdc_errors
128
+          |dm_cdc_log_scan_sessions
129
+          |dm_clr_appdomains
130
+          |dm_clr_loaded_assemblies
131
+          |dm_clr_properties
132
+          |dm_clr_tasks
133
+          |dm_cryptographic_provider_properties
134
+          |dm_database_encryption_keys
135
+          |dm_db_file_space_usage
136
+          |dm_db_index_usage_stats
137
+          |dm_db_mirroring_auto_page_repair
138
+          |dm_db_mirroring_connections
139
+          |dm_db_mirroring_past_actions
140
+          |dm_db_missing_index_details
141
+          |dm_db_missing_index_group_stats
142
+          |dm_db_missing_index_groups
143
+          |dm_db_partition_stats
144
+          |dm_db_persisted_sku_features
145
+          |dm_db_script_level
146
+          |dm_db_session_space_usage
147
+          |dm_db_task_space_usage
148
+          |dm_exec_background_job_queue
149
+          |dm_exec_background_job_queue_stats
150
+          |dm_exec_cached_plans
151
+          |dm_exec_connections
152
+          |dm_exec_procedure_stats
153
+          |dm_exec_query_memory_grants
154
+          |dm_exec_query_optimizer_info
155
+          |dm_exec_query_resource_semaphores
156
+          |dm_exec_query_stats
157
+          |dm_exec_query_transformation_stats
158
+          |dm_exec_requests
159
+          |dm_exec_sessions
160
+          |dm_exec_trigger_stats
161
+          |dm_filestream_file_io_handles
162
+          |dm_filestream_file_io_requests
163
+          |dm_fts_active_catalogs
164
+          |dm_fts_fdhosts
165
+          |dm_fts_index_population
166
+          |dm_fts_memory_buffers
167
+          |dm_fts_memory_pools
168
+          |dm_fts_outstanding_batches
169
+          |dm_fts_population_ranges
170
+          |dm_io_backup_tapes
171
+          |dm_io_cluster_shared_drives
172
+          |dm_io_pending_io_requests
173
+          |dm_os_buffer_descriptors
174
+          |dm_os_child_instances
175
+          |dm_os_cluster_nodes
176
+          |dm_os_dispatcher_pools
177
+          |dm_os_dispatchers
178
+          |dm_os_hosts
179
+          |dm_os_latch_stats
180
+          |dm_os_loaded_modules
181
+          |dm_os_memory_allocations
182
+          |dm_os_memory_brokers
183
+          |dm_os_memory_cache_clock_hands
184
+          |dm_os_memory_cache_counters
185
+          |dm_os_memory_cache_entries
186
+          |dm_os_memory_cache_hash_tables
187
+          |dm_os_memory_clerks
188
+          |dm_os_memory_node_access_stats
189
+          |dm_os_memory_nodes
190
+          |dm_os_memory_objects
191
+          |dm_os_memory_pools
192
+          |dm_os_nodes
193
+          |dm_os_performance_counters
194
+          |dm_os_process_memory
195
+          |dm_os_ring_buffers
196
+          |dm_os_schedulers
197
+          |dm_os_spinlock_stats
198
+          |dm_os_stacks
199
+          |dm_os_sublatches
200
+          |dm_os_sys_info
201
+          |dm_os_sys_memory
202
+          |dm_os_tasks
203
+          |dm_os_threads
204
+          |dm_os_virtual_address_dump
205
+          |dm_os_wait_stats
206
+          |dm_os_waiting_tasks
207
+          |dm_os_worker_local_storage
208
+          |dm_os_workers
209
+          |dm_qn_subscriptions
210
+          |dm_repl_articles
211
+          |dm_repl_schemas
212
+          |dm_repl_tranhash
213
+          |dm_repl_traninfo
214
+          |dm_resource_governor_configuration
215
+          |dm_resource_governor_resource_pools
216
+          |dm_resource_governor_workload_groups
217
+          |dm_server_audit_status
218
+          |dm_tran_active_snapshot_database_transactions
219
+          |dm_tran_active_transactions
220
+          |dm_tran_commit_table
221
+          |dm_tran_current_snapshot
222
+          |dm_tran_current_transaction
223
+          |dm_tran_database_transactions
224
+          |dm_tran_locks
225
+          |dm_tran_session_transactions
226
+          |dm_tran_top_version_generators
227
+          |dm_tran_transactions_snapshot
228
+          |dm_tran_version_store
229
+          |dm_xe_map_values
230
+          |dm_xe_object_columns
231
+          |dm_xe_objects
232
+          |dm_xe_packages
233
+          |dm_xe_session_event_actions
234
+          |dm_xe_session_events
235
+          |dm_xe_session_object_columns
236
+          |dm_xe_session_targets
237
+          |dm_xe_sessions
238
+          |endpoint_webmethods
239
+          |endpoints
240
+          |event_notification_event_types
241
+          |event_notifications
242
+          |events
243
+          |extended_procedures
244
+          |extended_properties
245
+          |filegroups
246
+          |foreign_key_columns
247
+          |foreign_keys
248
+          |fulltext_catalogs
249
+          |fulltext_document_types
250
+          |fulltext_index_catalog_usages
251
+          |fulltext_index_columns
252
+          |fulltext_index_fragments
253
+          |fulltext_indexes
254
+          |fulltext_languages
255
+          |fulltext_stoplists
256
+          |fulltext_stopwords
257
+          |fulltext_system_stopwords
258
+          |function_order_columns
259
+          |http_endpoints
260
+          |identity_columns
261
+          |index_columns
262
+          |indexes
263
+          |internal_tables
264
+          |key_constraints
265
+          |key_encryptions
266
+          |linked_logins
267
+          |login_token
268
+          |master_files
269
+          |master_key_passwords
270
+          |message_type_xml_schema_collection_usages
271
+          |messages
272
+          |module_assembly_usages
273
+          |numbered_procedure_parameters
274
+          |numbered_procedures
275
+          |objects
276
+          |openkeys
277
+          |parameter_type_usages
278
+          |parameter_xml_schema_collection_usages
279
+          |parameters
280
+          |partition_functions
281
+          |partition_parameters
282
+          |partition_range_values
283
+          |partition_schemes
284
+          |partitions
285
+          |plan_guides
286
+          |procedures
287
+          |remote_logins
288
+          |remote_service_bindings
289
+          |resource_governor_configuration
290
+          |resource_governor_resource_pools
291
+          |resource_governor_workload_groups
292
+          |routes
293
+          |schemas
294
+          |securable_classes
295
+          |server_assembly_modules
296
+          |server_audit_specification_details
297
+          |server_audit_specifications
298
+          |server_audits
299
+          |server_event_notifications
300
+          |server_event_session_actions
301
+          |server_event_session_events
302
+          |server_event_session_fields
303
+          |server_event_session_targets
304
+          |server_event_sessions
305
+          |server_events
306
+          |server_file_audits
307
+          |server_permissions
308
+          |server_principal_credentials
309
+          |server_principals
310
+          |server_role_members
311
+          |server_sql_modules
312
+          |server_trigger_events
313
+          |server_triggers
314
+          |servers
315
+          |service_broker_endpoints
316
+          |service_contract_message_usages
317
+          |service_contract_usages
318
+          |service_contracts
319
+          |service_message_types
320
+          |service_queue_usages
321
+          |service_queues
322
+          |services
323
+          |soap_endpoints
324
+          |spatial_index_tessellations
325
+          |spatial_indexes
326
+          |spatial_reference_systems
327
+          |sql_dependencies
328
+          |sql_logins
329
+          |sql_modules
330
+          |stats
331
+          |stats_columns
332
+          |symmetric_keys
333
+          |synonyms
334
+          |syscacheobjects
335
+          |syscharsets
336
+          |syscolumns
337
+          |syscomments
338
+          |sysconfigures
339
+          |sysconstraints
340
+          |syscurconfigs
341
+          |syscursorcolumns
342
+          |syscursorrefs
343
+          |syscursors
344
+          |syscursortables
345
+          |sysdatabases
346
+          |sysdepends
347
+          |sysdevices
348
+          |sysfilegroups
349
+          |sysfiles
350
+          |sysforeignkeys
351
+          |sysfulltextcatalogs
352
+          |sysindexes
353
+          |sysindexkeys
354
+          |syslanguages
355
+          |syslockinfo
356
+          |syslogins
357
+          |sysmembers
358
+          |sysmessages
359
+          |sysobjects
360
+          |sysoledbusers
361
+          |sysopentapes
362
+          |sysperfinfo
363
+          |syspermissions
364
+          |sysprocesses
365
+          |sysprotects
366
+          |sysreferences
367
+          |sysremotelogins
368
+          |sysservers
369
+          |system_columns
370
+          |system_components_surface_area_configuration
371
+          |system_objects
372
+          |system_parameters
373
+          |system_sql_modules
374
+          |system_views
375
+          |systypes
376
+          |sysusers
377
+          |table_types
378
+          |tables
379
+          |tcp_endpoints
380
+          |trace_categories
381
+          |trace_columns
382
+          |trace_event_bindings
383
+          |trace_events
384
+          |trace_subclass_values
385
+          |traces
386
+          |transmission_queue
387
+          |trigger_event_types
388
+          |trigger_events
389
+          |triggers
390
+          |type_assembly_usages
391
+          |types
392
+          |user_token
393
+          |via_endpoints
394
+          |views
395
+          |xml_indexes
396
+          |xml_schema_attributes
397
+          |xml_schema_collections
398
+          |xml_schema_component_placements
399
+          |xml_schema_components
400
+          |xml_schema_elements
401
+          |xml_schema_facets
402
+          |xml_schema_model_groups
403
+          |xml_schema_namespaces
404
+          |xml_schema_types
405
+          |xml_schema_wildcard_namespaces
406
+          |xml_schema_wildcards
407
+        )/x
408
+    };
409
+
410
+    my $dsn = "dbi:ODBC:driver={SQL Server};Server={localhost\\SQLEXPRESS};"
411
+      . "Trusted_Connection=No;AutoTranslate=No;Database=dbix_custom;";
412
+    has dsn => $dsn;
413
+    has user  => 'dbix_custom';
414
+    has password => 'dbix_custom';
415
+    
416
+    sub create_table1 { "create table $table1 ($key1 varchar(255), $key2 varchar(255))" }
417
+    sub create_table1_2 {"create table $table1 ($key1 varchar(255), $key2 varchar(255), "
418
+     . "$key3 varchar(255), $key4 varchar(255), $key5 varchar(255))" }
419
+    sub create_table1_type { "create table $table1 ($key1 $date_typename, $key2 $datetime_typename)" }
420
+    sub create_table1_highperformance { "create table $table1 ($key1 varchar(255), $key2 varchar(255), "
421
+      . "$key3 varchar(255), $key4 varchar(255), $key5 varchar(255), $key6 varchar(255), $key7 varchar(255))" }
422
+    sub create_table2 { "create table $table2 ($key1 varchar(255), $key3 varchar(255))" }
423
+    sub create_table2_2 { "create table $table2 ($key1 varchar(255), $key2 varchar(255), $key3 varchar(255))" }
424
+    sub create_table3 { "create table $table3 ($key1 varchar(255), $key2 varchar(255), $key3 varchar(255))" }
425
+    sub create_table_reserved { 'create table "table" ("select" varchar(255), "update" varchar(255))' }
426
+}
427
+
428
+require "$FindBin::Bin/common.t";
+3898
t/next/common.t
... ...
@@ -0,0 +1,3898 @@
1
+use Test::More;
2
+use strict;
3
+use warnings;
4
+use Encode qw/encode_utf8/;
5
+use FindBin;
6
+use Scalar::Util 'isweak';
7
+
8
+my $dbi;
9
+
10
+plan skip_all => $ENV{DBIX_CUSTOM_SKIP_MESSAGE} || 'common.t is always skipped'
11
+  unless $ENV{DBIX_CUSTOM_TEST_RUN}
12
+    && eval { $dbi = DBIx::Custom::Next->connect; 1 };
13
+
14
+plan 'no_plan';
15
+
16
+$SIG{__WARN__} = sub { warn $_[0] unless $_[0] =~ /DEPRECATED/};
17
+sub test { print "# $_[0]\n" }
18
+
19
+# Constant
20
+my $table1 = $dbi->table1;
21
+my $table2 = $dbi->table2;
22
+my $table2_alias = $dbi->table2_alias;
23
+my $table3 = $dbi->table3;
24
+my $key1 = $dbi->key1;
25
+my $key2 = $dbi->key2;
26
+my $key3 = $dbi->key3;
27
+my $key4 = $dbi->key4;
28
+my $key5 = $dbi->key5;
29
+my $key6 = $dbi->key6;
30
+my $key7 = $dbi->key7;
31
+my $key8 = $dbi->key8;
32
+my $key9 = $dbi->key9;
33
+my $key10 = $dbi->key10;
34
+my $create_table1 = $dbi->create_table1;
35
+my $create_table1_2 = $dbi->create_table1_2;
36
+my $create_table1_type = $dbi->create_table1_type;
37
+my $create_table2 = $dbi->create_table2;
38
+my $create_table2_2 = $dbi->create_table2_2;
39
+my $create_table3 = $dbi->create_table3;
40
+my $create_table_reserved = $dbi->create_table_reserved;
41
+my $q = substr($dbi->quote, 0, 1);
42
+my $p = substr($dbi->quote, 1, 1) || $q;
43
+my $date_typename = $dbi->date_typename;
44
+my $datetime_typename = $dbi->datetime_typename;
45
+my $date_datatype = $dbi->date_datatype;
46
+my $datetime_datatype = $dbi->datetime_datatype;
47
+
48
+# Variables
49
+my $builder;
50
+my $datas;
51
+my $sth;
52
+my $source;
53
+my @sources;
54
+my $select_source;
55
+my $insert_source;
56
+my $update_source;
57
+my $param;
58
+my $params;
59
+my $sql;
60
+my $result;
61
+my $row;
62
+my @rows;
63
+my $rows;
64
+my $query;
65
+my @queries;
66
+my $select_query;
67
+my $insert_query;
68
+my $update_query;
69
+my $ret_val;
70
+my $infos;
71
+my $model;
72
+my $model2;
73
+my $where;
74
+my $update_param;
75
+my $insert_param;
76
+my $join;
77
+my $binary;
78
+my $user_table_info;
79
+my $user_column_info;
80
+my $values_clause;
81
+my $assign_clause;
82
+my $reuse;
83
+
84
+require MyDBI1;
85
+{
86
+    package MyDBI4;
87
+
88
+    use strict;
89
+    use warnings;
90
+
91
+    use base 'DBIx::Custom::Next';
92
+
93
+    sub connect {
94
+        my $self = shift->SUPER::connect(@_);
95
+        
96
+        $self->include_model(
97
+            MyModel2 => [
98
+                $table1,
99
+                {class => $table2, name => $table2}
100
+            ]
101
+        );
102
+    }
103
+
104
+    package MyModel2::Base1;
105
+
106
+    use strict;
107
+    use warnings;
108
+
109
+    use base 'DBIx::Custom::Next::Model';
110
+
111
+    package MyModel2::table1;
112
+
113
+    use strict;
114
+    use warnings;
115
+
116
+    use base 'MyModel2::Base1';
117
+
118
+    sub insert {
119
+        my ($self, $param) = @_;
120
+        
121
+        return $self->SUPER::insert($param);
122
+    }
123
+
124
+    sub list { shift->select; }
125
+
126
+    package MyModel2::table2;
127
+
128
+    use strict;
129
+    use warnings;
130
+
131
+    use base 'MyModel2::Base1';
132
+
133
+    sub insert {
134
+        my ($self, $param) = @_;
135
+        
136
+        return $self->SUPER::insert($param);
137
+    }
138
+
139
+    sub list { shift->select; }
140
+
141
+    package MyModel2::TABLE1;
142
+
143
+    use strict;
144
+    use warnings;
145
+
146
+    use base 'MyModel2::Base1';
147
+
148
+    sub insert {
149
+        my ($self, $param) = @_;
150
+        
151
+        return $self->SUPER::insert($param);
152
+    }
153
+
154
+    sub list { shift->select; }
155
+
156
+    package MyModel2::TABLE2;
157
+
158
+    use strict;
159
+    use warnings;
160
+
161
+    use base 'MyModel2::Base1';
162
+
163
+    sub insert {
164
+        my ($self, $param) = @_;
165
+        
166
+        return $self->SUPER::insert($param);
167
+    }
168
+
169
+    sub list { shift->select; }
170
+}
171
+{
172
+     package MyDBI5;
173
+
174
+    use strict;
175
+    use warnings;
176
+
177
+    use base 'DBIx::Custom::Next';
178
+
179
+    sub connect {
180
+        my $self = shift->SUPER::connect(@_);
181
+        
182
+        $self->include_model('MyModel4');
183
+    }
184
+}
185
+{
186
+    package MyDBI6;
187
+    
188
+    use base 'DBIx::Custom::Next';
189
+    
190
+    sub connect {
191
+        my $self = shift->SUPER::connect(@_);
192
+        
193
+        $self->include_model('MyModel5');
194
+        
195
+        return $self;
196
+    }
197
+}
198
+{
199
+    package MyDBI7;
200
+    
201
+    use base 'DBIx::Custom::Next';
202
+    
203
+    sub connect {
204
+        my $self = shift->SUPER::connect(@_);
205
+        
206
+        $self->include_model('MyModel6');
207
+        
208
+        
209
+        return $self;
210
+    }
211
+}
212
+{
213
+    package MyDBI8;
214
+    
215
+    use base 'DBIx::Custom::Next';
216
+    
217
+    sub connect {
218
+        my $self = shift->SUPER::connect(@_);
219
+        
220
+        $self->include_model('MyModel7');
221
+        
222
+        return $self;
223
+    }
224
+}
225
+
226
+{
227
+    package MyDBI9;
228
+    
229
+    use base 'DBIx::Custom::Next';
230
+    
231
+    sub connect {
232
+        my $self = shift->SUPER::connect(@_);
233
+        
234
+        $self->include_model('MyModel8');
235
+        
236
+        return $self;
237
+    }
238
+}
239
+
240
+test 'execute reuse option';
241
+eval { $dbi->execute("drop table $table1") };
242
+$dbi->execute($create_table1);
243
+$reuse = {};
244
+for my $i (1 .. 2) {
245
+  $dbi->insert({$key1 => 1, $key2 => 2}, table => $table1, reuse => $reuse);
246
+}
247
+$rows = $dbi->select(table => $table1)->all;
248
+is_deeply($rows, [{$key1 => 1, $key2 => 2}, {$key1 => 1, $key2 => 2}]);
249
+
250
+# Get user table info
251
+$dbi = DBIx::Custom::Next->connect;
252
+eval { $dbi->execute("drop table $table1") };
253
+eval { $dbi->execute("drop table $table2") };
254
+eval { $dbi->execute("drop table $table3") };
255
+$dbi->execute($create_table1);
256
+$dbi->execute($create_table2);
257
+$dbi->execute($create_table3);
258
+$user_table_info = $dbi->get_table_info(exclude => $dbi->exclude_table);
259
+
260
+# Create table
261
+$dbi = DBIx::Custom::Next->connect;
262
+eval { $dbi->execute("drop table $table1") };
263
+$dbi->execute($create_table1);
264
+$model = $dbi->create_model(table => $table1);
265
+$model->insert({$key1 => 1, $key2 => 2});
266
+is_deeply($model->select->all, [{$key1 => 1, $key2 => 2}]);
267
+
268
+test 'DBIx::Custom::Next::Result test';
269
+$dbi->delete_all(table => $table1);
270
+$dbi->insert({$key1 => 1, $key2 => 2}, table => $table1);
271
+$dbi->insert({$key1 => 3, $key2 => 4}, table => $table1);
272
+$source = "select $key1, $key2 from $table1";
273
+$result = $dbi->execute($source);
274
+
275
+@rows = ();
276
+while (my $row = $result->fetch) {
277
+    push @rows, [@$row];
278
+}
279
+is_deeply(\@rows, [[1, 2], [3, 4]], "fetch");
280
+
281
+$result = $dbi->execute($source);
282
+@rows = ();
283
+while (my $row = $result->fetch_hash) {
284
+    push @rows, {%$row};
285
+}
286
+is_deeply(\@rows, [{$key1 => 1, $key2 => 2}, {$key1 => 3, $key2 => 4}], "fetch_hash");
287
+
288
+$result = $dbi->execute($source);
289
+$rows = $result->fetch_all;
290
+is_deeply($rows, [[1, 2], [3, 4]], "fetch_all");
291
+
292
+$result = $dbi->execute($source);
293
+$rows = $result->fetch_hash_all;
294
+is_deeply($rows, [{$key1 => 1, $key2 => 2}, {$key1 => 3, $key2 => 4}], "all");
295
+
296
+test 'Insert query return value';
297
+$source = "insert into $table1 " . $dbi->values_clause({$key1 => 1, $key2 => 2});
298
+$query = $dbi->execute($source, {}, query => 1);
299
+$ret_val = $dbi->execute($source, {$key1 => 1, $key2 => 2});
300
+ok($ret_val);
301
+
302
+test 'Direct query';
303
+$dbi->delete_all(table => $table1);
304
+$insert_source = "insert into $table1 " . $dbi->values_clause({$key1 => 1, $key2 => 2});
305
+$dbi->execute($insert_source, {$key1 => 1, $key2 => 2});
306
+$result = $dbi->execute("select * from $table1");
307
+$rows = $result->all;
308
+is_deeply($rows, [{$key1 => 1, $key2 => 2}]);
309
+
310
+test 'Filter basic';
311
+$dbi->delete_all(table => $table1);
312
+$dbi->register_filter(twice       => sub { $_[0] * 2}, 
313
+                    three_times => sub { $_[0] * 3});
314
+
315
+$insert_source  = "insert into $table1 " . $dbi->values_clause({$key1 => 1, $key2 => 2});
316
+$dbi->execute($insert_source, {$key1 => 1, $key2 => 2}, filter => {$key1 => 'twice'});
317
+$result = $dbi->execute("select * from $table1");
318
+$rows = $result->filter({$key2 => 'three_times'})->all;
319
+is_deeply($rows, [{$key1 => 2, $key2 => 6}], "filter fetch_filter");
320
+
321
+test 'Named placeholder';
322
+eval { $dbi->execute("drop table $table1") };
323
+$dbi->execute($create_table1_2);
324
+$dbi->insert({$key1 => 1, $key2 => 2, $key3 => 3, $key4 => 4, $key5 => 5}, table => $table1);
325
+$dbi->insert({$key1 => 6, $key2 => 7, $key3 => 8, $key4 => 9, $key5 => 10}, table => $table1);
326
+
327
+$source = "select * from $table1 where $key1 = :$key1 and $key2 = :$key2";
328
+$result = $dbi->execute($source, {$key1 => 1, $key2 => 2});
329
+$rows = $result->all;
330
+is_deeply($rows, [{$key1 => 1, $key2 => 2, $key3 => 3, $key4 => 4, $key5 => 5}]);
331
+
332
+$source = "select * from $table1 where $key1 = \n:$key1\n and $key2 = :$key2";
333
+$result = $dbi->execute($source, {$key1 => 1, $key2 => 2});
334
+$rows = $result->all;
335
+is_deeply($rows, [{$key1 => 1, $key2 => 2, $key3 => 3, $key4 => 4, $key5 => 5}]);
336
+
337
+$source = "select * from $table1 where $key1 = :$key1 or $key1 = :$key1";
338
+$result = $dbi->execute($source, {$key1 => [1, 2]});
339
+$rows = $result->all;
340
+is_deeply($rows, [{$key1 => 1, $key2 => 2, $key3 => 3, $key4 => 4, $key5 => 5}]);
341
+
342
+$source = "select * from $table1 where $key1 = :$table1.$key1 and $key2 = :$table1.$key2";
343
+$result = $dbi->execute(
344
+    $source,
345
+    {"$table1.$key1" => 1, "$table1.$key2" => 1},
346
+    filter => {"$table1.$key2" => sub { $_[0] * 2 }}
347
+);
348
+$rows = $result->all;
349
+is_deeply($rows, [{$key1 => 1, $key2 => 2, $key3 => 3, $key4 => 4, $key5 => 5}]);
350
+
351
+eval { $dbi->execute("drop table $table1") };
352
+$dbi->execute($create_table1);
353
+$dbi->insert({$key1 => '2011-10-14 12:19:18', $key2 => 2}, table => $table1);
354
+$source = "select * from $table1 where $key1 = '2011-10-14 12:19:18' and $key2 = :$key2";
355
+$result = $dbi->execute(
356
+    $source,
357
+    {$key2 => 2},
358
+);
359
+
360
+$rows = $result->all;
361
+like($rows->[0]->{$key1}, qr/2011-10-14 12:19:18/);
362
+is($rows->[0]->{$key2}, 2);
363
+
364
+$dbi->delete_all(table => $table1);
365
+$dbi->insert({$key1 => 'a:b c:d', $key2 => 2}, table => $table1);
366
+$source = "select * from $table1 where $key1 = 'a\\:b c\\:d' and $key2 = :$key2";
367
+$result = $dbi->execute(
368
+    $source,
369
+    {$key2 => 2},
370
+);
371
+$rows = $result->all;
372
+is_deeply($rows, [{$key1 => 'a:b c:d', $key2 => 2}]);
373
+
374
+test 'Error case';
375
+eval {DBIx::Custom::Next->connect(dsn => 'dbi:SQLit')};
376
+ok($@, "connect error");
377
+
378
+test 'insert';
379
+eval { $dbi->execute("drop table $table1") };
380
+$dbi->execute($create_table1);
381
+$dbi->insert({$key1 => 1, $key2 => 2}, table => $table1);
382
+$dbi->insert({$key1 => 3, $key2 => 4}, table => $table1);
383
+$result = $dbi->execute("select * from $table1");
384
+$rows   = $result->all;
385
+is_deeply($rows, [{$key1 => 1, $key2 => 2}, {$key1 => 3, $key2 => 4}], "basic");
386
+
387
+eval { $dbi->execute("drop table $table1") };
388
+$dbi->execute($create_table1);
389
+$dbi->insert({$key1 => 1, $key2 => 2}, table => $table1);
390
+$dbi->insert({$key1 => 3, $key2 => 4}, table => $table1);
391
+$result = $dbi->execute("select * from $table1");
392
+$rows   = $result->all;
393
+is_deeply($rows, [{$key1 => 1, $key2 => 2}, {$key1 => 3, $key2 => 4}], "basic");
394
+
395
+$dbi->execute("delete from $table1");
396
+$dbi->register_filter(
397
+    twice       => sub { $_[0] * 2 },
398
+    three_times => sub { $_[0] * 3 }
399
+);
400
+$dbi->insert({$key1 => 1, $key2 => 2}, table => $table1, filter => {$key1 => 'three_times'});
401
+$result = $dbi->execute("select * from $table1");
402
+$rows   = $result->all;
403
+is_deeply($rows, [{$key1 => 3, $key2 => 2}], "filter");
404
+
405
+eval { $dbi->execute("drop table $table1") };
406
+$dbi->execute($create_table1);
407
+$dbi->insert({$key1 => 1, $key2 => 2}, table => $table1, append => '   ');
408
+$rows = $dbi->select(table => $table1)->all;
409
+is_deeply($rows, [{$key1 => 1, $key2 => 2}], 'insert append');
410
+
411
+eval{$dbi->insert({';' => 1}, table => 'table')};
412
+like($@, qr/safety/);
413
+
414
+eval { $dbi->execute("drop table $table1") };
415
+$dbi->execute($create_table1);
416
+$dbi->insert({$key1 => 1, $key2 => 2}, table => $table1);
417
+$dbi->insert({$key1 => 3, $key2 => 4}, table => $table1);
418
+$result = $dbi->execute("select * from $table1");
419
+$rows   = $result->all;
420
+is_deeply($rows, [{$key1 => 1, $key2 => 2}, {$key1 => 3, $key2 => 4}], "basic");
421
+
422
+eval { $dbi->execute("drop table $table1") };
423
+$dbi->execute($create_table1);
424
+$dbi->insert({$key1 => \"'1'", $key2 => 2}, table => $table1);
425
+$dbi->insert({$key1 => 3, $key2 => 4}, table => $table1);
426
+$result = $dbi->execute("select * from $table1");
427
+$rows   = $result->all;
428
+is_deeply($rows, [{$key1 => 1, $key2 => 2}, {$key1 => 3, $key2 => 4}], "basic");
429
+
430
+eval { $dbi->execute("drop table $table1") };
431
+$dbi->execute($create_table1);
432
+$dbi->insert({$key1 => 1, $key2 => 2}, table => $table1,
433
+  wrap => {$key1 => sub { "$_[0] - 1" }});
434
+$dbi->insert({$key1 => 3, $key2 => 4}, table => $table1);
435
+$result = $dbi->execute("select * from $table1");
436
+$rows   = $result->all;
437
+is_deeply($rows, [{$key1 => 0, $key2 => 2}, {$key1 => 3, $key2 => 4}], "basic");
438
+
439
+eval { $dbi->execute("drop table $table1") };
440
+$dbi->execute($create_table1_2);
441
+$param = {$key1 => 1};
442
+$dbi->insert($param, table => $table1, created_at => $key2);
443
+$result = $dbi->select(table => $table1);
444
+is_deeply($param, {$key1 => 1});
445
+$row   = $result->one;
446
+is($row->{$key1}, 1);
447
+like($row->{$key2}, qr/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$/);
448
+
449
+eval { $dbi->execute("drop table $table1") };
450
+$dbi->execute($create_table1_2);
451
+$param = {$key1 => 1};
452
+$dbi->insert($param, table => $table1, updated_at => $key3);
453
+$result = $dbi->select(table => $table1);
454
+is_deeply($param, {$key1 => 1});
455
+$row   = $result->one;
456
+is($row->{$key1}, 1);
457
+like($row->{$key3}, qr/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$/);
458
+
459
+eval { $dbi->execute("drop table $table1") };
460
+$dbi->execute($create_table1_2);
461
+$param = {$key1 => 1};
462
+$dbi->insert($param, table => $table1, created_at => $key2, updated_at => $key3);
463
+$result = $dbi->select(table => $table1);
464
+is_deeply($param, {$key1 => 1});
465
+$row   = $result->one;
466
+is($row->{$key1}, 1);
467
+like($row->{$key2}, qr/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$/);
468
+like($row->{$key3}, qr/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$/);
469
+is($row->{$key2}, $row->{$key3});
470
+
471
+eval { $dbi->execute("drop table $table1") };
472
+$dbi->execute($create_table1_2);
473
+$model = $dbi->create_model(table => $table1, created_at => $key2);
474
+$param = {$key1 => 1};
475
+$model->insert($param);
476
+$result = $dbi->select(table => $table1);
477
+is_deeply($param, {$key1 => 1});
478
+$row   = $result->one;
479
+is($row->{$key1}, 1);
480
+like($row->{$key2}, qr/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$/);
481
+
482
+eval { $dbi->execute("drop table $table1") };
483
+$dbi->execute($create_table1_2);
484
+$param = {$key1 => 1};
485
+$model = $dbi->create_model(table => $table1, updated_at => $key3);
486
+$model->insert($param);
487
+$result = $dbi->select(table => $table1);
488
+is_deeply($param, {$key1 => 1});
489
+$row   = $result->one;
490
+is($row->{$key1}, 1);
491
+like($row->{$key3}, qr/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$/);
492
+
493
+eval { $dbi->execute("drop table $table1") };
494
+$dbi->execute($create_table1_2);
495
+$param = {$key1 => 1};
496
+$model = $dbi->create_model(table => $table1, created_at => $key2, updated_at => $key3);
497
+$model->insert($param);
498
+$result = $dbi->select(table => $table1);
499
+is_deeply($param, {$key1 => 1});
500
+$row   = $result->one;
501
+is($row->{$key1}, 1);
502
+like($row->{$key2}, qr/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$/);
503
+like($row->{$key3}, qr/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$/);
504
+is($row->{$key2}, $row->{$key3});
505
+
506
+test 'update_or_insert';
507
+eval { $dbi->execute("drop table $table1") };
508
+$dbi->execute($create_table1);
509
+$dbi->update_or_insert(
510
+    {$key2 => 2},
511
+    table => $table1,
512
+    primary_key => $key1,
513
+    id => 1
514
+);
515
+$row = $dbi->select(id => 1, table => $table1, primary_key => $key1)->one;
516
+is_deeply($row, {$key1 => 1, $key2 => 2}, "basic");
517
+
518
+$dbi->update_or_insert(
519
+    {$key2 => 3},
520
+    table => $table1,
521
+    primary_key => $key1,
522
+    id => 1
523
+);
524
+$rows = $dbi->select(id => 1, table => $table1, primary_key => $key1)->all;
525
+is_deeply($rows, [{$key1 => 1, $key2 => 3}], "basic");
526
+
527
+eval {
528
+    $dbi->update_or_insert(
529
+        {$key2 => 3},
530
+        table => $table1,
531
+    );
532
+};
533
+
534
+like($@, qr/primary_key/);
535
+
536
+eval {
537
+    $dbi->insert({$key1 => 1}, table => $table1);
538
+    $dbi->update_or_insert(
539
+        {$key2 => 3},
540
+        table => $table1,
541
+        primary_key => $key1,
542
+        id => 1
543
+    );
544
+};
545
+like($@, qr/one/);
546
+
547
+test 'model update_or_insert';
548
+eval { $dbi->execute("drop table $table1") };
549
+$dbi->execute($create_table1);
550
+$model = $dbi->create_model(
551
+    table => $table1,
552
+    primary_key => $key1
553
+);
554
+$model->update_or_insert({$key2 => 2}, id => 1);
555
+$row = $model->select(id => 1)->one;
556
+is_deeply($row, {$key1 => 1, $key2 => 2}, "basic");
557
+
558
+eval {
559
+    $model->insert({$key1 => 1});
560
+    $model->update_or_insert(
561
+        {$key2 => 3},
562
+        id => 1
563
+    );
564
+};
565
+like($@, qr/one/);
566
+
567
+test 'filter';
568
+$dbi->execute("delete from $table1");
569
+$dbi->register_filter(
570
+    twice       => sub { $_[0] * 2 },
571
+    three_times => sub { $_[0] * 3 }
572
+);
573
+$dbi->insert({$key1 => 1, $key2 => 2}, table => $table1, filter => {$key1 => 'three_times'});
574
+$result = $dbi->execute("select * from $table1");
575
+$rows   = $result->all;
576
+is_deeply($rows, [{$key1 => 3, $key2 => 2}], "filter");
577
+
578
+test 'update';
579
+eval { $dbi->execute("drop table $table1") };
580
+$dbi->execute($create_table1_2);
581
+$dbi->insert({$key1 => 1, $key2 => 2, $key3 => 3, $key4 => 4, $key5 => 5}, table => $table1);
582
+$dbi->insert({$key1 => 6, $key2 => 7, $key3 => 8, $key4 => 9, $key5 => 10}, table => $table1);
583
+$dbi->update({$key2 => 11}, table => $table1, where => {$key1 => 1});
584
+$result = $dbi->execute("select * from $table1 order by $key1");
585
+$rows   = $result->all;
586
+is_deeply($rows, [{$key1 => 1, $key2 => 11, $key3 => 3, $key4 => 4, $key5 => 5},
587
+                  {$key1 => 6, $key2 => 7,  $key3 => 8, $key4 => 9, $key5 => 10}],
588
+                  "basic");
589
+
590
+eval { $dbi->execute("drop table $table1") };
591
+$dbi->execute($create_table1_2);
592
+$dbi->insert({$key1 => 1, $key2 => 2, $key3 => 3, $key4 => 4, $key5 => 5}, table => $table1);
593
+$dbi->insert({$key1 => 6, $key2 => 7, $key3 => 8, $key4 => 9, $key5 => 10}, table => $table1);
594
+$dbi->update({$key2 => 11}, table => $table1, where => {$key1 => 1});
595
+$result = $dbi->execute("select * from $table1 order by $key1");
596
+$rows   = $result->all;
597
+is_deeply($rows, [{$key1 => 1, $key2 => 11, $key3 => 3, $key4 => 4, $key5 => 5},
598
+                  {$key1 => 6, $key2 => 7,  $key3 => 8, $key4 => 9, $key5 => 10}],
599
+                  "basic");
600
+                  
601
+$dbi->execute("delete from $table1");
602
+$dbi->insert({$key1 => 1, $key2 => 2, $key3 => 3, $key4 => 4, $key5 => 5}, table => $table1);
603
+$dbi->insert({$key1 => 6, $key2 => 7, $key3 => 8, $key4 => 9, $key5 => 10}, table => $table1);
604
+$dbi->update({$key2 => 12}, table => $table1, where => {$key2 => 2, $key3 => 3});
605
+$result = $dbi->execute("select * from $table1 order by $key1");
606
+$rows   = $result->all;
607
+is_deeply($rows, [{$key1 => 1, $key2 => 12, $key3 => 3, $key4 => 4, $key5 => 5},
608
+                  {$key1 => 6, $key2 => 7,  $key3 => 8, $key4 => 9, $key5 => 10}],
609
+                  "update key same as search key");
610
+
611
+$dbi->update({$key2 => [12]}, table => $table1, where => {$key2 => 2, $key3 => 3});
612
+$result = $dbi->execute("select * from $table1 order by $key1");
613
+$rows   = $result->all;
614
+is_deeply($rows, [{$key1 => 1, $key2 => 12, $key3 => 3, $key4 => 4, $key5 => 5},
615
+                  {$key1 => 6, $key2 => 7,  $key3 => 8, $key4 => 9, $key5 => 10}],
616
+                  "update key same as search key : param is array ref");
617
+
618
+$dbi->execute("delete from $table1");
619
+$dbi->insert({$key1 => 1, $key2 => 2, $key3 => 3, $key4 => 4, $key5 => 5}, table => $table1);
620
+$dbi->insert({$key1 => 6, $key2 => 7, $key3 => 8, $key4 => 9, $key5 => 10}, table => $table1);
621
+$dbi->register_filter(twice => sub { $_[0] * 2 });
622
+$dbi->update({$key2 => 11}, table => $table1, where => {$key1 => 1},
623
+              filter => {$key2 => sub { $_[0] * 2 }});
624
+$result = $dbi->execute("select * from $table1 order by $key1");
625
+$rows   = $result->all;
626
+is_deeply($rows, [{$key1 => 1, $key2 => 22, $key3 => 3, $key4 => 4, $key5 => 5},
627
+                  {$key1 => 6, $key2 => 7,  $key3 => 8, $key4 => 9, $key5 => 10}],
628
+                  "filter");
629
+
630
+$result = $dbi->update({$key2 => 11}, table => $table1, where => {$key1 => 1}, append => '   ');
631
+
632
+eval{$dbi->update({}, table => $table1)};
633
+like($@, qr/where/, "not contain where");
634
+
635
+eval { $dbi->execute("drop table $table1") };
636
+$dbi->execute($create_table1);
637
+$dbi->insert({$key1 => 1, $key2 => 2}, table => $table1);
638
+$where = $dbi->where;
639
+$where->clause(['and', "$key1 = :$key1", "$key2 = :$key2"]);
640
+$where->param({$key1 => 1, $key2 => 2});
641
+$dbi->update({$key1 => 3}, table => $table1, where => $where);
642
+$result = $dbi->select(table => $table1);
643
+is_deeply($result->all, [{$key1 => 3, $key2 => 2}], 'update() where');
644
+
645
+eval { $dbi->execute("drop table $table1") };
646
+$dbi->execute($create_table1);
647
+$dbi->insert({$key1 => 1, $key2 => 2}, table => $table1);
648
+$dbi->update(
649
+    {$key1 => 3},
650
+    table => $table1,
651
+    where => [
652
+        ['and', "$key1 = :$key1", "$key2 = :$key2"],
653
+        {$key1 => 1, $key2 => 2}
654
+    ]
655
+);
656
+$result = $dbi->select(table => $table1);
657
+is_deeply($result->all, [{$key1 => 3, $key2 => 2}], 'update() where');
658
+
659
+eval { $dbi->execute("drop table $table1") };
660
+$dbi->execute($create_table1);
661
+$dbi->insert({$key1 => 1, $key2 => 2}, table => $table1);
662
+$where = $dbi->where;
663
+$where->clause(['and', "$key2 = :$key2"]);
664
+$where->param({$key2 => 2});
665
+$dbi->update({$key1 => 3}, table => $table1, where => $where);
666
+$result = $dbi->select(table => $table1);
667
+is_deeply($result->all, [{$key1 => 3, $key2 => 2}], 'update() where');
668
+
669
+eval{$dbi->update({';' => 1}, table => $table1, where => {$key1 => 1})};
670
+like($@, qr/safety/);
671
+
672
+eval{$dbi->update({$key1 => 1}, table => $table1, where => {';' => 1})};
673
+like($@, qr/safety/);
674
+
675
+eval { $dbi->execute("drop table $table1") };
676
+eval { $dbi->execute("drop table ${q}table$p") };
677
+$dbi->execute($create_table_reserved);
678
+$dbi->insert({select => 1}, table => 'table');
679
+$dbi->update({update => 2}, table => 'table', where => {select => 1});
680
+$result = $dbi->execute("select * from ${q}table$p");
681
+$rows   = $result->all;
682
+is_deeply($rows, [{select => 1, update => 2}], "reserved word");
683
+
684
+eval {$dbi->update_all({';' => 2}, table => 'table') };
685
+like($@, qr/safety/);
686
+
687
+eval { $dbi->execute("drop table ${q}table$p") };
688
+$dbi->execute($create_table_reserved);
689
+$dbi->insert({select => 1}, table => 'table');
690
+$dbi->update({update => 2}, table => 'table', where => {'table.select' => 1});
691
+$result = $dbi->execute("select * from ${q}table$p");
692
+$rows   = $result->all;
693
+is_deeply($rows, [{select => 1, update => 2}], "reserved word");
694
+
695
+eval { $dbi->execute("drop table $table1") };
696
+$dbi->execute($create_table1_2);
697
+$dbi->insert({$key1 => 1, $key2 => 2, $key3 => 3, $key4 => 4, $key5 => 5}, table => $table1);
698
+$dbi->insert({$key1 => 6, $key2 => 7, $key3 => 8, $key4 => 9, $key5 => 10}, table => $table1);
699
+$dbi->update({$key2 => 11}, table => $table1, where => {$key1 => 1});
700
+$result = $dbi->execute("select * from $table1 order by $key1");
701
+$rows   = $result->all;
702
+is_deeply($rows, [{$key1 => 1, $key2 => 11, $key3 => 3, $key4 => 4, $key5 => 5},
703
+                  {$key1 => 6, $key2 => 7,  $key3 => 8, $key4 => 9, $key5 => 10}],
704
+                  "basic");
705
+
706
+eval { $dbi->execute("drop table $table1") };
707
+$dbi->execute($create_table1_2);
708
+$dbi->insert({$key1 => 1, $key2 => 2, $key3 => 3, $key4 => 4, $key5 => 5}, table => $table1);
709
+$dbi->insert({$key1 => 6, $key2 => 7, $key3 => 8, $key4 => 9, $key5 => 10}, table => $table1);
710
+$dbi->update({$key2 => 11}, table => $table1, where => {$key1 => 1},
711
+wrap => {$key2 => sub { "$_[0] - 1" }});
712
+$result = $dbi->execute("select * from $table1 order by $key1");
713
+$rows   = $result->all;
714
+is_deeply($rows, [{$key1 => 1, $key2 => 10, $key3 => 3, $key4 => 4, $key5 => 5},
715
+                  {$key1 => 6, $key2 => 7,  $key3 => 8, $key4 => 9, $key5 => 10}],
716
+                  "basic");
717
+
718
+eval { $dbi->execute("drop table $table1") };
719
+$dbi->execute($create_table1_2);
720
+$dbi->insert({$key1 => 1, $key2 => 2, $key3 => 3, $key4 => 4, $key5 => 5}, table => $table1);
721
+$dbi->insert({$key1 => 6, $key2 => 7, $key3 => 8, $key4 => 9, $key5 => 10}, table => $table1);
722
+$dbi->update({$key2 => \"'11'"}, table => $table1, where => {$key1 => 1});
723
+$result = $dbi->execute("select * from $table1 order by $key1");
724
+$rows   = $result->all;
725
+is_deeply($rows, [{$key1 => 1, $key2 => 11, $key3 => 3, $key4 => 4, $key5 => 5},
726
+                  {$key1 => 6, $key2 => 7,  $key3 => 8, $key4 => 9, $key5 => 10}],
727
+                  "basic");
728
+
729
+eval { $dbi->execute("drop table $table1") };
730
+$dbi->execute($create_table1_2);
731
+$dbi->insert({$key1 => 1, $key2 => 2, $key3 => 3, $key4 => 4, $key5 => 5}, table => $table1);
732
+$dbi->insert({$key1 => 6, $key2 => 7, $key3 => 8, $key4 => 9, $key5 => 10}, table => $table1);
733
+$param = {$key2 => 11};
734
+$dbi->update($param, table => $table1, where => {$key1 => 1});
735
+is_deeply($param, {$key2 => 11});
736
+$result = $dbi->execute("select * from $table1 order by $key1");
737
+$rows   = $result->all;
738
+is_deeply($rows, [{$key1 => 1, $key2 => 11, $key3 => 3, $key4 => 4, $key5 => 5},
739
+                  {$key1 => 6, $key2 => 7,  $key3 => 8, $key4 => 9, $key5 => 10}],
740
+                  "basic");
741
+
742
+eval { $dbi->execute("drop table $table1") };
743
+$dbi->execute($create_table1_2);
744
+$dbi->insert({$key1 => 1, $key2 => 2, $key3 => 3, $key4 => 4, $key5 => 5}, table => $table1);
745
+$dbi->insert({$key1 => 6, $key2 => 7, $key3 => 8, $key4 => 9, $key5 => 10}, table => $table1);
746
+$param = {$key2 => 11};
747
+$dbi->update($param, table => $table1, where => {$key2 => 2});
748
+is_deeply($param, {$key2 => 11});
749
+$result = $dbi->execute("select * from $table1 order by $key1");
750
+$rows   = $result->all;
751
+is_deeply($rows, [{$key1 => 1, $key2 => 11, $key3 => 3, $key4 => 4, $key5 => 5},
752
+                  {$key1 => 6, $key2 => 7,  $key3 => 8, $key4 => 9, $key5 => 10}],
753
+                  "basic");
754
+
755
+eval { $dbi->execute("drop table $table1") };
756
+$dbi->execute($create_table1_2);
757
+$param = {$key3 => 4};
758
+$dbi->insert({$key1 => 1, $key2 => 2, $key3 => 3}, table => $table1);
759
+$dbi->update($param, table => $table1, updated_at => $key2, where => {$key1 => 1});
760
+$result = $dbi->select(table => $table1);
761
+is_deeply($param, {$key3 => 4});
762
+$row   = $result->one;
763
+is($row->{$key3}, 4);
764
+like($row->{$key2}, qr/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$/);
765
+
766
+eval { $dbi->execute("drop table $table1") };
767
+$dbi->execute($create_table1_2);
768
+$param = {$key3 => 4};
769
+$dbi->insert({$key1 => 1, $key2 => 2, $key3 => 3}, table => $table1);
770
+$dbi->update($param, table => $table1, updated_at => $key2, where => {$key3 => 3});
771
+$result = $dbi->select(table => $table1);
772
+is_deeply($param, {$key3 => 4});
773
+$row   = $result->one;
774
+is($row->{$key3}, 4);
775
+like($row->{$key2}, qr/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$/);
776
+
777
+eval { $dbi->execute("drop table $table1") };
778
+$dbi->execute($create_table1_2);
779
+$model = $dbi->create_model(table => $table1, updated_at => $key2);
780
+$param = {$key3 => 4};
781
+$dbi->insert({$key1 => 1, $key2 => 2, $key3 => 3}, table => $table1);
782
+$model->update($param, where => {$key1 => 1});
783
+$result = $dbi->select(table => $table1);
784
+is_deeply($param, {$key3 => 4});
785
+$row   = $result->one;
786
+is($row->{$key3}, 4);
787
+like($row->{$key2}, qr/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$/);
788
+
789
+test 'update_all';
790
+eval { $dbi->execute("drop table $table1") };
791
+$dbi->execute($create_table1_2);
792
+$dbi->insert({$key1 => 1, $key2 => 2, $key3 => 3, $key4 => 4, $key5 => 5}, table => $table1);
793
+$dbi->insert({$key1 => 6, $key2 => 7, $key3 => 8, $key4 => 9, $key5 => 10}, table => $table1);
794
+$dbi->register_filter(twice => sub { $_[0] * 2 });
795
+$dbi->update_all({$key2 => 10}, table => $table1, filter => {$key2 => 'twice'});
796
+$result = $dbi->execute("select * from $table1");
797
+$rows   = $result->all;
798
+is_deeply($rows, [{$key1 => 1, $key2 => 20, $key3 => 3, $key4 => 4, $key5 => 5},
799
+                  {$key1 => 6, $key2 => 20, $key3 => 8, $key4 => 9, $key5 => 10}],
800
+                  "filter");
801
+
802
+
803
+test 'delete';
804
+eval { $dbi->execute("drop table $table1") };
805
+$dbi->execute($create_table1);
806
+$dbi->insert({$key1 => 1, $key2 => 2}, table => $table1);
807
+$dbi->insert({$key1 => 3, $key2 => 4}, table => $table1);
808
+$dbi->delete(table => $table1, where => {$key1 => 1});
809
+$result = $dbi->execute("select * from $table1");
810
+$rows   = $result->all;
811
+is_deeply($rows, [{$key1 => 3, $key2 => 4}], "basic");
812
+
813
+$dbi->execute("delete from $table1");
814
+$dbi->insert({$key1 => 1, $key2 => 2}, table => $table1);
815
+$dbi->insert({$key1 => 3, $key2 => 4}, table => $table1);
816
+$dbi->register_filter(twice => sub { $_[0] * 2 });
817
+$dbi->delete(table => $table1, where => {$key2 => 1}, filter => {$key2 => 'twice'});
818
+$result = $dbi->execute("select * from $table1");
819
+$rows   = $result->all;
820
+is_deeply($rows, [{$key1 => 3, $key2 => 4}], "filter");
821
+
822
+$dbi->delete(table => $table1, where => {$key1 => 1}, append => '   ');
823
+
824
+$dbi->delete_all(table => $table1);
825
+$dbi->insert({$key1 => 1, $key2 => 2}, table => $table1);
826
+$dbi->insert({$key1 => 3, $key2 => 4}, table => $table1);
827
+$dbi->delete(table => $table1, where => {$key1 => 1, $key2 => 2});
828
+$rows = $dbi->select(table => $table1)->all;
829
+is_deeply($rows, [{$key1 => 3, $key2 => 4}], "delete multi key");
830
+
831
+eval { $dbi->execute("drop table $table1") };
832
+$dbi->execute($create_table1);
833
+$dbi->insert({$key1 => 1, $key2 => 2}, table => $table1);
834
+$dbi->insert({$key1 => 3, $key2 => 4}, table => $table1);
835
+$where = $dbi->where;
836
+$where->clause(['and', "$key1 = :$key1", "$key2 = :$key2"]);
837
+$where->param({ke1 => 1, $key2 => 2});
838
+$dbi->delete(table => $table1, where => $where);
839
+$result = $dbi->select(table => $table1);
840
+is_deeply($result->all, [{$key1 => 3, $key2 => 4}], 'delete() where');
841
+
842
+eval { $dbi->execute("drop table $table1") };
843
+$dbi->execute($create_table1);
844
+$dbi->insert({$key1 => 1, $key2 => 2}, table => $table1);
845
+$dbi->insert({$key1 => 3, $key2 => 4}, table => $table1);
846
+$dbi->delete(
847
+    table => $table1,
848
+    where => [
849
+        ['and', "$key1 = :$key1", "$key2 = :$key2"],
850
+        {ke1 => 1, $key2 => 2}
851
+    ]
852
+);
853
+$result = $dbi->select(table => $table1);
854
+is_deeply($result->all, [{$key1 => 3, $key2 => 4}], 'delete() where');
855
+
856
+eval { $dbi->execute("drop table $table1") };
857
+$dbi->execute($create_table1);
858
+$dbi->insert({$key1 => 1, $key2 => 2}, table => $table1);
859
+$dbi->delete(table => $table1, where => {$key1 => 1}, prefix => '    ');
860
+$result = $dbi->execute("select * from $table1");
861
+$rows   = $result->all;
862
+is_deeply($rows, [], "basic");
863
+
864
+test 'delete error';
865
+eval { $dbi->execute("drop table $table1") };
866
+$dbi->execute($create_table1);
867
+eval{$dbi->delete(table => $table1)};
868
+like($@, qr/where/, "where key-value pairs not specified");
869
+
870
+eval{$dbi->delete(table => $table1, where => {';' => 1})};
871
+like($@, qr/safety/);
872
+
873
+$dbi = undef;
874
+$dbi = DBIx::Custom::Next->connect;
875
+eval { $dbi->execute("drop table ${q}table$p") };
876
+$dbi->execute($create_table_reserved);
877
+$dbi->insert({select => 1}, table => 'table');
878
+$dbi->delete(table => 'table', where => {select => 1});
879
+$result = $dbi->execute("select * from ${q}table$p");
880
+$rows   = $result->all;
881
+is_deeply($rows, [], "reserved word");
882
+
883
+test 'delete_all';
884
+eval { $dbi->execute("drop table $table1") };
885
+$dbi->execute($create_table1);
886
+$dbi->insert({$key1 => 1, $key2 => 2}, table => $table1);
887
+$dbi->insert({$key1 => 3, $key2 => 4}, table => $table1);
888
+$dbi->delete_all(table => $table1);
889
+$result = $dbi->execute("select * from $table1");
890
+$rows   = $result->all;
891
+is_deeply($rows, [], "basic");
892
+
893
+
894
+test 'select';
895
+eval { $dbi->execute("drop table $table1") };
896
+$dbi->execute($create_table1);
897
+$dbi->insert({$key1 => 1, $key2 => 2}, table => $table1);
898
+$dbi->insert({$key1 => 3, $key2 => 4}, table => $table1);
899
+$rows = $dbi->select(table => $table1)->all;
900
+is_deeply($rows, [{$key1 => 1, $key2 => 2},
901
+                  {$key1 => 3, $key2 => 4}], "table");
902
+
903
+$rows = $dbi->select(table => $table1, column => [$key1])->all;
904
+is_deeply($rows, [{$key1 => 1}, {$key1 => 3}], "table and columns and where key");
905
+
906
+$rows = $dbi->select(table => $table1, where => {$key1 => 1})->all;
907
+is_deeply($rows, [{$key1 => 1, $key2 => 2}], "table and columns and where key");
908
+
909
+$rows = $dbi->select(table => $table1, column => [$key1], where => {$key1 => 3})->all;
910
+is_deeply($rows, [{$key1 => 3}], "table and columns and where key");
911
+
912
+$dbi->register_filter(decrement => sub { $_[0] - 1 });
913
+$rows = $dbi->select(table => $table1, where => {$key1 => 2}, filter => {$key1 => 'decrement'})
914
+            ->all;
915
+is_deeply($rows, [{$key1 => 1, $key2 => 2}], "filter");
916
+
917
+eval { $dbi->execute("drop table $table2") };
918
+$dbi->execute($create_table2);
919
+$dbi->insert({$key1 => 1, $key3 => 5}, table => $table2);
920
+$rows = $dbi->select(
921
+    table => $table1,
922
+    column => "$table1.$key1 as ${table1}_$key1, $table2.$key1 as ${table2}_$key1, $key2, $key3",
923
+    where   => {"$table1.$key2" => 2},
924
+    join  => "inner join $table2 on $table1.$key1 = $table2.$key1"
925
+)->all;
926
+is_deeply($rows, [{"${table1}_$key1" => 1, "${table2}_$key1" => 1, $key2 => 2, $key3 => 5}], "exists where");
927
+
928
+$rows = $dbi->select(
929
+    table => $table1,
930
+    column => ["$table1.$key1 as ${table1}_$key1", "${table2}.$key1 as ${table2}_$key1", $key2, $key3],
931
+    join  => "inner join $table2 on $table1.$key1 = $table2.$key1"
932
+)->all;
933
+is_deeply($rows, [{"${table1}_$key1" => 1, "${table2}_$key1" => 1, $key2 => 2, $key3 => 5}], "no exists where");
934
+
935
+$dbi = DBIx::Custom::Next->connect;
936
+eval { $dbi->execute("drop table ${q}table$p") };
937
+$dbi->execute($create_table_reserved);
938
+$dbi->insert({select => 1, update => 2}, table => 'table');
939
+$result = $dbi->select(table => 'table', where => {select => 1});
940
+$rows   = $result->all;
941
+is_deeply($rows, [{select => 1, update => 2}], "reserved word");
942
+
943
+test 'fetch filter';
944
+eval { $dbi->execute("drop table $table1") };
945
+$dbi->register_filter(
946
+    twice       => sub { $_[0] * 2 },
947
+    three_times => sub { $_[0] * 3 }
948
+);
949
+$dbi->execute($create_table1);
950
+$dbi->insert({$key1 => 1, $key2 => 2}, table => $table1);
951
+$result = $dbi->select(table => $table1);
952
+$result->filter({$key1 => 'three_times'});
953
+$row = $result->one;
954
+is_deeply($row, {$key1 => 3, $key2 => 2}, "default_fetch_filter and filter");
955
+
956
+eval { $dbi->execute("drop table $table1") };
957
+$dbi->execute($create_table1);
958
+$dbi->insert({$key1 => 1, $key2 => 2}, table => $table1);
959
+$result = $dbi->select(column => [$key1, $key1, $key2], table => $table1);
960
+$result->filter({$key1 => 'three_times'});
961
+$row = $result->fetch_first;
962
+is_deeply($row, [3, 3, 2], "default_fetch_filter and filter");
963
+
964
+test 'filters';
965
+$dbi = DBIx::Custom::Next->new;
966
+
967
+is($dbi->filters->{decode_utf8}->(encode_utf8('あ')),
968
+   'あ', "decode_utf8");
969
+
970
+is($dbi->filters->{encode_utf8}->('あ'),
971
+   encode_utf8('あ'), "encode_utf8");
972
+
973
+test 'transaction1';
974
+$dbi = DBIx::Custom::Next->connect;
975
+eval { $dbi->execute("drop table $table1") };
976
+$dbi->execute($create_table1);
977
+$dbi->begin_work;
978
+$dbi->dbh->{AutoCommit} = 0;
979
+$dbi->insert({$key1 => 1, $key2 => 2}, table => $table1);
980
+$dbi->rollback;
981
+$dbi->dbh->{AutoCommit} = 1;
982
+
983
+$result = $dbi->select(table => $table1);
984
+ok(! $result->fetch_first, "rollback");
985
+
986
+
987
+$dbi = DBIx::Custom::Next->connect;
988
+eval { $dbi->execute("drop table $table1") };
989
+$dbi->execute($create_table1);
990
+$dbi->begin_work;
991
+$dbi->dbh->{AutoCommit} = 0;
992
+$dbi->insert({$key1 => 1, $key2 => 2}, table => $table1);
993
+$dbi->insert({$key1 => 2, $key2 => 3}, table => $table1);
994
+$dbi->commit;
995
+$dbi->dbh->{AutoCommit} = 1;
996
+$result = $dbi->select(table => $table1);
997
+is_deeply(scalar $result->all, [{$key1 => 1, $key2 => 2}, {$key1 => 2, $key2 => 3}],
998
+          "commit");
999
+
1000
+test 'execute';
1001
+eval { $dbi->execute("drop table $table1") };
1002
+$dbi->execute($create_table1);
1003
+{
1004
+    local $Carp::Verbose = 0;
1005
+    eval{$dbi->execute("select * frm $table1")};
1006
+    like($@, qr/\Qselect * frm $table1/, "fail prepare");
1007
+    like($@, qr/\.t /, "fail : not verbose");
1008
+}
1009
+{
1010
+    local $Carp::Verbose = 1;
1011
+    eval{$dbi->execute("select * frm $table1")};
1012
+    like($@, qr/Custom.*\.t /s, "fail : verbose");
1013
+}
1014
+
1015
+$query = $dbi->execute("select * from $table1 where $key1 = :$key1", {}, query => 1);
1016
+$dbi->dbh->disconnect;
1017
+eval{$dbi->execute($query, {$key1 => {a => 1}})};
1018
+ok($@, "execute fail");
1019
+
1020
+test 'transaction2';
1021
+$dbi = DBIx::Custom::Next->connect;
1022
+eval { $dbi->execute("drop table $table1") };
1023
+$dbi->execute($create_table1);
1024
+
1025
+$dbi->begin_work;
1026
+
1027
+eval {
1028
+    $dbi->insert({$key1 => 1, $key2 => 2}, table => $table1);
1029
+    die "Error";
1030
+    $dbi->insert({$key1 => 3, $key2 => 4}, table => $table1);
1031
+};
1032
+
1033
+$dbi->rollback if $@;
1034
+
1035
+$result = $dbi->select(table => $table1);
1036
+$rows = $result->all;
1037
+is_deeply($rows, [], "rollback");
1038
+
1039
+$dbi->begin_work;
1040
+
1041
+eval {
1042
+    $dbi->insert({$key1 => 1, $key2 => 2}, table => $table1);
1043
+    $dbi->insert({$key1 => 3, $key2 => 4}, table => $table1);
1044
+};
1045
+
1046
+$dbi->commit unless $@;
1047
+
1048
+$result = $dbi->select(table => $table1);
1049
+$rows = $result->all;
1050
+is_deeply($rows, [{$key1 => 1, $key2 => 2}, {$key1 => 3, $key2 => 4}], "commit");
1051
+
1052
+$dbi->dbh->{AutoCommit} = 0;
1053
+eval{ $dbi->begin_work };
1054
+ok($@, "exception");
1055
+$dbi->dbh->{AutoCommit} = 1;
1056
+
1057
+test 'execute';
1058
+eval { $dbi->execute("drop table $table1") };
1059
+$dbi->execute($create_table1);
1060
+{
1061
+    local $Carp::Verbose = 0;
1062
+    eval{$dbi->execute("select * frm $table1")};
1063
+    like($@, qr/\Qselect * frm $table1/, "fail prepare");
1064
+    like($@, qr/\.t /, "fail : not verbose");
1065
+}
1066
+{
1067
+    local $Carp::Verbose = 1;
1068
+    eval{$dbi->execute("select * frm $table1")};
1069
+    like($@, qr/Custom.*\.t /s, "fail : verbose");
1070
+}
1071
+
1072
+$query = $dbi->execute("select * from $table1 where $key1 = :$key1", {}, query => 1);
1073
+$dbi->dbh->disconnect;
1074
+eval{$dbi->execute($query, {$key1 => {a => 1}})};
1075
+ok($@, "execute fail");
1076
+
1077
+test 'helper';
1078
+$dbi->helper(
1079
+    one => sub { 1 }
1080
+);
1081
+$dbi->helper(
1082
+    two => sub { 2 }
1083
+);
1084
+$dbi->helper({
1085
+    twice => sub {
1086
+        my $self = shift;
1087
+        return $_[0] * 2;
1088
+    }
1089
+});
1090
+
1091
+is($dbi->one, 1, "first");
1092
+is($dbi->two, 2, "second");
1093
+is($dbi->twice(5), 10 , "second");
1094
+
1095
+eval {$dbi->XXXXXX};
1096
+ok($@, "not exists");
1097
+
1098
+test 'out filter';
1099
+$dbi = DBIx::Custom::Next->connect;
1100
+eval { $dbi->execute("drop table $table1") };
1101
+$dbi->execute($create_table1);
1102
+$dbi->register_filter(twice => sub { $_[0] * 2 });
1103
+$dbi->register_filter(three_times => sub { $_[0] * 3});
1104
+$dbi->insert({$key1 => 1, $key2 => 2}, table => $table1);
1105
+$result = $dbi->execute("select * from $table1");
1106
+$row   = $result->fetch_hash_first;
1107
+is_deeply($row, {$key1 => 1, $key2 => 2}, "insert");
1108
+$result = $dbi->select(table => $table1);
1109
+$row   = $result->one;
1110
+is_deeply($row, {$key1 => 1, $key2 => 2}, "insert");
1111
+
1112
+$dbi = DBIx::Custom::Next->connect;
1113
+eval { $dbi->execute("drop table $table1") };
1114
+$dbi->execute($create_table1);
1115
+$dbi->register_filter(twice => sub { $_[0] * 2 });
1116
+$dbi->register_filter(three_times => sub { $_[0] * 3});
1117
+$dbi->insert({$key1 => 1, $key2 => 2}, table => $table1);
1118
+$result = $dbi->execute("select * from $table1");
1119
+$row   = $result->one;
1120
+is_deeply($row, {$key1 => 1, $key2 => 2}, "insert");
1121
+
1122
+$dbi = DBIx::Custom::Next->connect;
1123
+eval { $dbi->execute("drop table $table1") };
1124
+$dbi->execute($create_table1);
1125
+$dbi->register_filter(twice => sub { $_[0] * 2 });
1126
+$dbi->insert({$key1 => 1, $key2 => 2},table => $table1, filter => {$key1 => undef});
1127
+$dbi->update({$key1 => 2}, table => $table1, where => {$key2 => 2});
1128
+$result = $dbi->execute("select * from $table1");
1129
+$row   = $result->one;
1130
+is_deeply($row, {$key1 => 2, $key2 => 2}, "update");
1131
+
1132
+$dbi = DBIx::Custom::Next->connect;
1133
+eval { $dbi->execute("drop table $table1") };
1134
+$dbi->execute($create_table1);
1135
+$dbi->register_filter(twice => sub { $_[0] * 2 });
1136
+$dbi->insert({$key1 => 2, $key2 => 2}, table => $table1, filter => {$key1=> undef});
1137
+$dbi->delete(table => $table1, where => {$key1 => 2});
1138
+$result = $dbi->execute("select * from $table1");
1139
+$rows   = $result->all;
1140
+is_deeply($rows, [], "delete");
1141
+
1142
+$dbi = DBIx::Custom::Next->connect;
1143
+eval { $dbi->execute("drop table $table1") };
1144
+$dbi->execute($create_table1);
1145
+$dbi->register_filter(twice => sub { $_[0] * 2 });
1146
+$dbi->insert({$key1 => 2, $key2 => 2}, table => $table1, filter => {$key1 => undef});
1147
+$result = $dbi->select(table => $table1, where => {$key1 => 2});
1148
+$result->filter({$key2 => 'twice'});
1149
+$rows   = $result->all;
1150
+is_deeply($rows, [{$key1 => 2, $key2 => 4}], "select");
1151
+
1152
+$dbi = DBIx::Custom::Next->connect;
1153
+eval { $dbi->execute("drop table $table1") };
1154
+$dbi->execute($create_table1);
1155
+$dbi->register_filter(twice => sub { $_[0] * 2 });
1156
+$dbi->insert({$key1 => 2, $key2 => 2}, table => $table1, filter => {$key1 => undef});
1157
+$result = $dbi->execute("select * from $table1 where $key1 = :$key1 and $key2 = :$key2",
1158
+                        {$key1 => 2, $key2 => 2},
1159
+                        table => [$table1]);
1160
+$rows   = $result->all;
1161
+is_deeply($rows, [{$key1 => 2, $key2 => 2}], "execute");
1162
+
1163
+$dbi = DBIx::Custom::Next->connect;
1164
+eval { $dbi->execute("drop table $table1") };
1165
+$dbi->execute($create_table1);
1166
+$dbi->register_filter(twice => sub { $_[0] * 2 });
1167
+$dbi->insert({$key1 => 2, $key2 => 2}, table => $table1, filter => {$key1 => undef});
1168
+$result = $dbi->execute("select * from $table1 where $key1 = :$key1 and $key2 = :$key2",
1169
+                        {$key1 => 2, $key2 => 2}, table => $table1);
1170
+$rows   = $result->all;
1171
+is_deeply($rows, [{$key1 => 2, $key2 => 2}], "execute table tag");
1172
+
1173
+$dbi = DBIx::Custom::Next->connect;
1174
+eval { $dbi->execute("drop table $table1") };
1175
+eval { $dbi->execute("drop table $table2") };
1176
+$dbi->execute($create_table1);
1177
+$dbi->execute($create_table2);
1178
+$dbi->register_filter(twice => sub { $_[0] * 2 });
1179
+$dbi->register_filter(three_times => sub { $_[0] * 3 });
1180
+$dbi->insert({$key1 => 5, $key2 => 2}, table => $table1, filter => {$key2 => undef});
1181
+$dbi->insert({$key1 => 5, $key3 => 6}, table => $table2, filter => {$key3 => undef});
1182
+$result = $dbi->select(
1183
+     table => $table1,
1184
+     column => [$key2, $key3],
1185
+     where => {"$table1.$key2" => 2, "$table2.$key3" => 6},
1186
+     join => "inner join $table2 on $table1.$key1 = $table2.$key1"
1187
+);
1188
+$result->filter({$key2 => 'twice'});
1189
+$rows   = $result->all;
1190
+is_deeply($rows, [{$key2 => 4, $key3 => 6}], "select : join");
1191
+
1192
+$result = $dbi->select(
1193
+     table => $table1,
1194
+     column => [$key2, $key3, "$table2.$key3 as ${table2}_$key3"],
1195
+     where => {$key2 => 2, $key3 => 6},
1196
+     join => "inner join $table2 on $table1.$key1 = $table2.$key1"
1197
+);
1198
+
1199
+$result->filter({$key2 => 'twice'});
1200
+$rows   = $result->all;
1201
+is_deeply($rows, [{$key2 => 4, $key3 => 6, "${table2}_$key3" => 6}], "select : join : omit");
1202
+
1203
+test 'connect super';
1204
+$dbi = DBIx::Custom::Next->connect;
1205
+eval { $dbi->execute("drop table $table1") };
1206
+$dbi->execute($create_table1);
1207
+$dbi->insert({$key1 => 1, $key2 => 2}, table => $table1);
1208
+is($dbi->select(table => $table1)->one->{$key1}, 1);
1209
+
1210
+$dbi = DBIx::Custom::Next->new;
1211
+$dbi->connect;
1212
+eval { $dbi->execute("drop table $table1") };
1213
+$dbi->execute($create_table1);
1214
+$dbi->insert({$key1 => 1, $key2 => 2}, table => $table1);
1215
+is($dbi->select(table => $table1)->one->{$key1}, 1);
1216
+
1217
+$dbi = DBIx::Custom::Next->connect;
1218
+eval { $dbi->execute("drop table $table1") };
1219
+$dbi->execute($create_table1);
1220
+$dbi->insert({$key1 => 1, $key2 => 2}, table => $table1);
1221
+is($dbi->select(table => $table1)->one->{$key1}, 1);
1222
+
1223
+test 'filter';
1224
+$dbi = DBIx::Custom::Next->connect;
1225
+eval { $dbi->execute("drop table $table1") };
1226
+$dbi->execute($create_table1);
1227
+$dbi->insert({$key1 => 1, $key2 => 2}, table => $table1);
1228
+$result = $dbi->select(table => $table1);
1229
+$result->filter($key1 => sub { $_[0] * 2 }, $key2 => sub { $_[0] * 4 });
1230
+$row = $result->fetch_first;
1231
+is_deeply($row, [2, 8]);
1232
+
1233
+$dbi = DBIx::Custom::Next->connect;
1234
+eval { $dbi->execute("drop table $table1") };
1235
+$dbi->execute($create_table1);
1236
+$dbi->insert({$key1 => 1, $key2 => 2}, table => $table1);
1237
+$result = $dbi->select(column => [$key1, $key1, $key2], table => $table1);
1238
+$result->filter($key1 => sub { $_[0] * 2 }, $key2 => sub { $_[0] * 4 });
1239
+$row = $result->fetch_first;
1240
+is_deeply($row, [2, 2, 8]);
1241
+
1242
+$dbi = DBIx::Custom::Next->connect;
1243
+eval { $dbi->execute("drop table $table1") };
1244
+$dbi->execute($create_table1);
1245
+$dbi->insert({$key1 => 1, $key2 => 2}, table => $table1);
1246
+$result = $dbi->select(table => $table1);
1247
+$result->filter([$key1, $key2] => sub { $_[0] * 2 });
1248
+$row = $result->fetch_first;
1249
+is_deeply($row, [2, 4]);
1250
+
1251
+$dbi = DBIx::Custom::Next->connect;
1252
+eval { $dbi->execute("drop table $table1") };
1253
+$dbi->execute($create_table1);
1254
+$dbi->insert({$key1 => 1, $key2 => 2}, table => $table1);
1255
+$result = $dbi->select(table => $table1);
1256
+$result->filter([[$key1, $key2] => sub { $_[0] * 2 }]);
1257
+$row = $result->fetch_first;
1258
+is_deeply($row, [2, 4]);
1259
+
1260
+$dbi->register_filter(five_times => sub { $_[0] * 5 });
1261
+$result = $dbi->select(table => $table1);
1262
+$result->filter($key1 => sub { $_[0] * 2 }, $key2 => sub { $_[0] * 4 });
1263
+$row = $result->one;
1264
+is_deeply($row, {$key1 => 2, $key2 => 8});
1265
+
1266
+$dbi->register_filter(five_times => sub { $_[0] * 5 });
1267
+$result = $dbi->select(table => $table1);
1268
+$result->filter($key1 => sub { $_[0] * 2 }, $key2 => sub { $_[0] * 4 });
1269
+$row = $result->one;
1270
+is_deeply($row, {$key1 => 2, $key2 => 8}, 'apply_filter');
1271
+
1272
+test 'empty where select';
1273
+$dbi = DBIx::Custom::Next->connect;
1274
+eval { $dbi->execute("drop table $table1") };
1275
+$dbi->execute($create_table1);
1276
+$dbi->insert({$key1 => 1, $key2 => 2}, table => $table1);
1277
+$result = $dbi->select(table => $table1, where => {});
1278
+$row = $result->one;
1279
+is_deeply($row, {$key1 => 1, $key2 => 2});
1280
+
1281
+test 'select query option';
1282
+$dbi = DBIx::Custom::Next->connect;
1283
+eval { $dbi->execute("drop table $table1") };
1284
+$dbi->execute($create_table1);
1285
+$query = $dbi->insert({$key1 => 1, $key2 => 2}, table => $table1, query => 1);
1286
+is(ref $query, 'HASH');
1287
+$query = $dbi->update({$key2 => 2}, table => $table1, where => {$key1 => 1}, query => 1);
1288
+is(ref $query, 'HASH');
1289
+$query = $dbi->delete(table => $table1, where => {$key1 => 1}, query => 1);
1290
+is(ref $query, 'HASH');
1291
+$query = $dbi->select(table => $table1, where => {$key1 => 1, $key2 => 2}, query => 1);
1292
+is(ref $query, 'HASH');
1293
+
1294
+test 'where';
1295
+$dbi = DBIx::Custom::Next->connect;
1296
+eval { $dbi->execute("drop table $table1") };
1297
+$dbi->execute($create_table1);
1298
+$dbi->insert({$key1 => 1, $key2 => 2}, table => $table1);
1299
+$dbi->insert({$key1 => 3, $key2 => 4}, table => $table1);
1300
+$where = $dbi->where->clause(['and', "$key1 = :$key1", "$key2 = :$key2"]);
1301
+is("$where", "where ( $key1 = :$key1 and $key2 = :$key2 )", 'no param');
1302
+
1303
+$where = $dbi->where
1304
+             ->clause(['and', "$key1 = :$key1", "$key2 = :$key2"])
1305
+             ->param({$key1 => 1});
1306
+
1307
+$result = $dbi->select(
1308
+    table => $table1,
1309
+    where => $where
1310
+);
1311
+$row = $result->all;
1312
+is_deeply($row, [{$key1 => 1, $key2 => 2}]);
1313
+
1314
+$result = $dbi->select(
1315
+    table => $table1,
1316
+    where => [
1317
+        ['and', "$key1 = :$key1", "$key2 = :$key2"],
1318
+        {$key1 => 1}
1319
+    ]
1320
+);
1321
+$row = $result->all;
1322
+is_deeply($row, [{$key1 => 1, $key2 => 2}]);
1323
+
1324
+$where = $dbi->where
1325
+             ->clause(['and', "$key1 = :$key1", "$key2 = :$key2"])
1326
+             ->param({$key1 => 1, $key2 => 2});
1327
+$result = $dbi->select(
1328
+    table => $table1,
1329
+    where => $where
1330
+);
1331
+$row = $result->all;
1332
+is_deeply($row, [{$key1 => 1, $key2 => 2}]);
1333
+
1334
+$where = $dbi->where
1335
+             ->clause(['and', "$key1 = :$key1", "$key2 = :$key2"])
1336
+             ->param({});
1337
+$result = $dbi->select(
1338
+    table => $table1,
1339
+    where => $where,
1340
+);
1341
+$row = $result->all;
1342
+is_deeply($row, [{$key1 => 1, $key2 => 2}, {$key1 => 3, $key2 => 4}]);
1343
+
1344
+$where = $dbi->where
1345
+             ->clause(['and', ['or', "$key1 > :$key1", "$key1 < :$key1"], "$key2 = :$key2"])
1346
+             ->param({$key1 => [0, 3], $key2 => 2});
1347
+$result = $dbi->select(
1348
+    table => $table1,
1349
+    where => $where,
1350
+); 
1351
+$row = $result->all;
1352
+is_deeply($row, [{$key1 => 1, $key2 => 2}]);
1353
+
1354
+$where = $dbi->where;
1355
+$result = $dbi->select(
1356
+    table => $table1,
1357
+    where => $where
1358
+);
1359
+$row = $result->all;
1360
+is_deeply($row, [{$key1 => 1, $key2 => 2}, {$key1 => 3, $key2 => 4}]);
1361
+
1362
+eval {
1363
+$where = $dbi->where
1364
+             ->clause(['uuu']);
1365
+$result = $dbi->select(
1366
+    table => $table1,
1367
+    where => $where
1368
+);
1369
+};
1370
+ok($@);
1371
+
1372
+$where = $dbi->where;
1373
+is("$where", '');
1374
+
1375
+$where = $dbi->where
1376
+             ->clause(['or', ("$key1 = :$key1") x 2])
1377
+             ->param({$key1 => [1, 3]});
1378
+$result = $dbi->select(
1379
+    table => $table1,
1380
+    where => $where,
1381
+);
1382
+$row = $result->all;
1383
+is_deeply($row, [{$key1 => 1, $key2 => 2}, {$key1 => 3, $key2 => 4}]);
1384
+
1385
+$where = $dbi->where
1386
+             ->clause(['or', ("$key1 = :$key1") x 2])
1387
+             ->param({$key1 => [1]});
1388
+$result = $dbi->select(
1389
+    table => $table1,
1390
+    where => $where,
1391
+);
1392
+$row = $result->all;
1393
+is_deeply($row, [{$key1 => 1, $key2 => 2}]);
1394
+
1395
+$where = $dbi->where
1396
+             ->clause(['or', ("$key1 = :$key1") x 2])
1397
+             ->param({$key1 => 1});
1398
+$result = $dbi->select(
1399
+    table => $table1,
1400
+    where => $where,
1401
+);
1402
+$row = $result->all;
1403
+is_deeply($row, [{$key1 => 1, $key2 => 2}]);
1404
+
1405
+$where = $dbi->where
1406
+             ->clause("$key1 = :$key1")
1407
+             ->param({$key1 => 1});
1408
+$result = $dbi->select(
1409
+    table => $table1,
1410
+    where => $where,
1411
+);
1412
+$row = $result->all;
1413
+is_deeply($row, [{$key1 => 1, $key2 => 2}]);
1414
+
1415
+$where = $dbi->where
1416
+             ->clause(['or', ("$key1 = :$key1") x 3])
1417
+             ->param({$key1 => [$dbi->not_exists, 1, 3]});
1418
+$result = $dbi->select(
1419
+    table => $table1,
1420
+    where => $where,
1421
+);
1422
+$row = $result->all;
1423
+is_deeply($row, [{$key1 => 1, $key2 => 2}, {$key1 => 3, $key2 => 4}], 'not_exists');
1424
+
1425
+$where = $dbi->where
1426
+             ->clause(['or', ("$key1 = :$key1") x 3])
1427
+             ->param({$key1 => [1, $dbi->not_exists, 3]});
1428
+$result = $dbi->select(
1429
+    table => $table1,
1430
+    where => $where,
1431
+);
1432
+$row = $result->all;
1433
+is_deeply($row, [{$key1 => 1, $key2 => 2}, {$key1 => 3, $key2 => 4}], 'not_exists');
1434
+
1435
+$where = $dbi->where
1436
+             ->clause(['or', ("$key1 = :$key1") x 3])
1437
+             ->param({$key1 => [1, 3, $dbi->not_exists]});
1438
+$result = $dbi->select(
1439
+    table => $table1,
1440
+    where => $where,
1441
+);
1442
+$row = $result->all;
1443
+is_deeply($row, [{$key1 => 1, $key2 => 2}, {$key1 => 3, $key2 => 4}], 'not_exists');
1444
+
1445
+$where = $dbi->where
1446
+             ->clause(['or', ("$key1 = :$key1") x 3])
1447
+             ->param({$key1 => [1, $dbi->not_exists, $dbi->not_exists]});
1448
+$result = $dbi->select(
1449
+    table => $table1,
1450
+    where => $where,
1451
+);
1452
+$row = $result->all;
1453
+is_deeply($row, [{$key1 => 1, $key2 => 2}], 'not_exists');
1454
+
1455
+$where = $dbi->where
1456
+             ->clause(['or', ("$key1 = :$key1") x 3])
1457
+             ->param({$key1 => [$dbi->not_exists, 1, $dbi->not_exists]});
1458
+$result = $dbi->select(
1459
+    table => $table1,
1460
+    where => $where,
1461
+);
1462
+$row = $result->all;
1463
+is_deeply($row, [{$key1 => 1, $key2 => 2}], 'not_exists');
1464
+
1465
+$where = $dbi->where
1466
+             ->clause(['or', ("$key1 = :$key1") x 3])
1467
+             ->param({$key1 => [$dbi->not_exists, $dbi->not_exists, 1]});
1468
+$result = $dbi->select(
1469
+    table => $table1,
1470
+    where => $where,
1471
+);
1472
+$row = $result->all;
1473
+is_deeply($row, [{$key1 => 1, $key2 => 2}], 'not_exists');
1474
+
1475
+$where = $dbi->where
1476
+             ->clause(['or', ("$key1 = :$key1") x 3])
1477
+             ->param({$key1 => [$dbi->not_exists, $dbi->not_exists, $dbi->not_exists]});
1478
+$result = $dbi->select(
1479
+    table => $table1,
1480
+    where => $where,
1481
+);
1482
+$row = $result->all;
1483
+is_deeply($row, [{$key1 => 1, $key2 => 2}, {$key1 => 3, $key2 => 4}], 'not_exists');
1484
+
1485
+$where = $dbi->where
1486
+             ->clause(['or', ("$key1 = :$key1") x 3])
1487
+             ->param({$key1 => []});
1488
+$result = $dbi->select(
1489
+    table => $table1,
1490
+    where => $where,
1491
+);
1492
+$row = $result->all;
1493
+is_deeply($row, [{$key1 => 1, $key2 => 2}, {$key1 => 3, $key2 => 4}], 'not_exists');
1494
+
1495
+$where = $dbi->where
1496
+             ->clause(['and', ":${key1}{>}", ":${key1}{<}" ])
1497
+             ->param({$key1 => [2, $dbi->not_exists]});
1498
+$result = $dbi->select(
1499
+    table => $table1,
1500
+    where => $where,
1501
+);
1502
+$row = $result->all;
1503
+is_deeply($row, [{$key1 => 3, $key2 => 4}], 'not_exists');
1504
+
1505
+$where = $dbi->where
1506
+             ->clause(['and', ":${key1}{>}", ":${key1}{<}" ])
1507
+             ->param({$key1 => [$dbi->not_exists, 2]});
1508
+$result = $dbi->select(
1509
+    table => $table1,
1510
+    where => $where,
1511
+);
1512
+$row = $result->all;
1513
+is_deeply($row, [{$key1 => 1, $key2 => 2}], 'not_exists');
1514
+
1515
+$where = $dbi->where
1516
+             ->clause(['and', ":${key1}{>}", ":${key1}{<}" ])
1517
+             ->param({$key1 => [$dbi->not_exists, $dbi->not_exists]});
1518
+$result = $dbi->select(
1519
+    table => $table1,
1520
+    where => $where,
1521
+);
1522
+$row = $result->all;
1523
+is_deeply($row, [{$key1 => 1, $key2 => 2},{$key1 => 3, $key2 => 4}], 'not_exists');
1524
+
1525
+$where = $dbi->where
1526
+             ->clause(['and', ":${key1}{>}", ":${key1}{<}" ])
1527
+             ->param({$key1 => [0, 2]});
1528
+$result = $dbi->select(
1529
+    table => $table1,
1530
+    where => $where,
1531
+);
1532
+$row = $result->all;
1533
+is_deeply($row, [{$key1 => 1, $key2 => 2}], 'not_exists');
1534
+
1535
+$where = $dbi->where
1536
+             ->clause(['and',"$key1 is not null", "$key2 is not null" ]);
1537
+$result = $dbi->select(
1538
+    table => $table1,
1539
+    where => $where,
1540
+);
1541
+$row = $result->all;
1542
+is_deeply($row, [{$key1 => 1, $key2 => 2}, {$key1 => 3, $key2 => 4}], 'not_exists');
1543
+
1544
+eval {$dbi->where(ppp => 1) };
1545
+like($@, qr/invalid/);
1546
+
1547
+$where = $dbi->where(
1548
+    clause => ['and', ['or'], ['and', "$key1 = :$key1", "$key2 = :$key2"]],
1549
+    param => {$key1 => 1, $key2 => 2}
1550
+);
1551
+$result = $dbi->select(
1552
+    table => $table1,
1553
+    where => $where,
1554
+);
1555
+$row = $result->all;
1556
+is_deeply($row, [{$key1 => 1, $key2 => 2}]);
1557
+
1558
+
1559
+$where = $dbi->where(
1560
+    clause => ['and', ['or'], ['or', ":$key1", ":$key2"]],
1561
+    param => {}
1562
+);
1563
+$result = $dbi->select(
1564
+    table => $table1,
1565
+    where => $where,
1566
+);
1567
+$row = $result->all;
1568
+is_deeply($row, [{$key1 => 1, $key2 => 2}, {$key1 => 3, $key2 => 4}]);
1569
+
1570
+$where = $dbi->where;
1571
+$where->clause(['and', ":${key1}{=}"]);
1572
+$where->param({$key1 => undef});
1573
+$result = $dbi->execute("select * from $table1 $where", {$key1 => 1});
1574
+$row = $result->all;
1575
+is_deeply($row, [{$key1 => 1, $key2 => 2}]);
1576
+
1577
+$where = $dbi->where;
1578
+$where->clause(['or', ":${key1}{=}", ":${key1}{=}"]);
1579
+$where->param({$key1 => [undef, undef]});
1580
+$result = $dbi->execute("select * from $table1 $where", {$key1 => [1, 0]});
1581
+$row = $result->all;
1582
+is_deeply($row, [{$key1 => 1, $key2 => 2}]);
1583
+$result = $dbi->execute("select * from $table1 $where", {$key1 => [0, 1]});
1584
+$row = $result->all;
1585
+is_deeply($row, [{$key1 => 1, $key2 => 2}]);
1586
+
1587
+
1588
+$dbi = DBIx::Custom::Next->connect;
1589
+eval { $dbi->execute("drop table $table1") };
1590
+$dbi->execute($create_table1);
1591
+$dbi->insert({$key1 => 1, $key2 => '00:00:00'}, table => $table1);
1592
+$dbi->insert({$key1 => 1, $key2 => '3'}, table => $table1);
1593
+$where = $dbi->where
1594
+             ->clause(['and', "$key1 = :$key1", "$key2 = '00:00:00'"])
1595
+             ->param({$key1 => 1});
1596
+
1597
+$result = $dbi->select(
1598
+    table => $table1,
1599
+    where => $where
1600
+);
1601
+$row = $result->all;
1602
+is_deeply($row, [{$key1 => 1, $key2 => '00:00:00'}]);
1603
+
1604
+test 'table not specify exception';
1605
+$dbi = DBIx::Custom::Next->connect;
1606
+eval {$dbi->select};
1607
+like($@, qr/table/);
1608
+
1609
+$dbi = DBIx::Custom::Next->connect;
1610
+eval { $dbi->execute("drop table $table1") };
1611
+$dbi->execute($create_table1);
1612
+$dbi->insert({$key1 => 1, $key2 => 2}, table => $table1);
1613
+$dbi->insert({$key1 => 3, $key2 => 4}, table => $table1);
1614
+$rows = $dbi->select(table => $table1, where => {$key2 => 2})->all;
1615
+is_deeply($rows, [{$key1 => 1, $key2 => 2}]);
1616
+
1617
+$dbi = DBIx::Custom::Next->connect;
1618
+eval { $dbi->execute("drop table $table1") };
1619
+$dbi->execute($create_table1);
1620
+$dbi->insert({$key1 => 1, $key2 => 2}, table => $table1);
1621
+$dbi->insert({$key1 => 3, $key2 => 4}, table => $table1);
1622
+$rows = $dbi->select(table => $table1, where => {$key2 => 2})->all;
1623
+is_deeply($rows, [{$key1 => 1, $key2 => 2}]);
1624
+
1625
+$dbi->helper({one => sub { 1 }});
1626
+is($dbi->one, 1);
1627
+
1628
+eval{DBIx::Custom::Next->connect(dsn => undef)};
1629
+like($@, qr/_connect/);
1630
+
1631
+$dbi = DBIx::Custom::Next->connect;
1632
+eval { $dbi->execute("drop table $table1") };
1633
+$dbi->execute($create_table1);
1634
+$dbi->register_filter(twice => sub { $_[0] * 2 });
1635
+$dbi->insert({$key1 => 1, $key2 => 2}, table => $table1,
1636
+             filter => {$key1 => 'twice'});
1637
+$row = $dbi->select(table => $table1)->one;
1638
+is_deeply($row, {$key1 => 2, $key2 => 2});
1639
+eval {$dbi->insert({$key1 => 1, $key2 => 2}, table => $table1,
1640
+             filter => {$key1 => 'no'}) };
1641
+like($@, qr//);
1642
+
1643
+$dbi = DBIx::Custom::Next->connect;
1644
+eval { $dbi->execute("drop table $table1") };
1645
+$dbi->execute($create_table1);
1646
+$dbi->register_filter(one => sub { 1 });
1647
+$result = $dbi->select(table => $table1);
1648
+eval {$result->filter($key1 => 'no')};
1649
+like($@, qr/not registered/);
1650
+
1651
+test 'option';
1652
+$dbi = DBIx::Custom::Next->connect(option => {PrintError => 1});
1653
+ok($dbi->dbh->{PrintError});
1654
+$dbi = DBIx::Custom::Next->connect(option => {PrintError => 1});
1655
+ok($dbi->dbh->{PrintError});
1656
+$dbi = DBIx::Custom::Next->connect(option => {PrintError => 1});
1657
+ok($dbi->dbh->{PrintError});
1658
+
1659
+test 'DBIx::Custom::Next::Result stash()';
1660
+$result = DBIx::Custom::Next::Result->new;
1661
+is_deeply($result->stash, {}, 'default');
1662
+$result->stash->{foo} = 1;
1663
+is($result->stash->{foo}, 1, 'get and set');
1664
+
1665
+test 'delete';
1666
+$dbi = DBIx::Custom::Next->connect;
1667
+eval { $dbi->execute("drop table $table1") };
1668
+$dbi->execute($create_table1_2);
1669
+$dbi->insert({$key1 => 1, $key2 => 2, $key3 => 3}, table => $table1);
1670
+$dbi->delete(
1671
+    table => $table1,
1672
+    primary_key => [$key1, $key2],
1673
+    id => [1, 2],
1674
+);
1675
+is_deeply($dbi->select(table => $table1)->all, []);
1676
+
1677
+$dbi->insert({$key1 => 1, $key2 => 2, $key3 => 3}, table => $table1);
1678
+$dbi->delete(
1679
+    table => $table1,
1680
+    primary_key => $key1,
1681
+    id => 1,
1682
+);
1683
+is_deeply($dbi->select(table => $table1)->all, []);
1684
+
1685
+test 'insert';
1686
+$dbi = DBIx::Custom::Next->connect;
1687
+eval { $dbi->execute("drop table $table1") };
1688
+$dbi->execute($create_table1_2);
1689
+$dbi->insert(
1690
+    {$key3 => 3},
1691
+    primary_key => [$key1, $key2], 
1692
+    table => $table1,
1693
+    id => [1, 2],
1694
+);
1695
+is($dbi->select(table => $table1)->one->{$key1}, 1);
1696
+is($dbi->select(table => $table1)->one->{$key2}, 2);
1697
+is($dbi->select(table => $table1)->one->{$key3}, 3);
1698
+
1699
+$dbi->delete_all(table => $table1);
1700
+$dbi->insert({$key1 => 1, $key2 => 2, $key3 => 3}, table => $table1);
1701
+$dbi->insert(
1702
+    {$key2 => 2, $key3 => 3},
1703
+    primary_key => $key1, 
1704
+    table => $table1,
1705
+    id => 1,
1706
+);
1707
+
1708
+is($dbi->select(table => $table1)->one->{$key1}, 1);
1709
+is($dbi->select(table => $table1)->one->{$key2}, 2);
1710
+is($dbi->select(table => $table1)->one->{$key3}, 3);
1711
+
1712
+$dbi = DBIx::Custom::Next->connect;
1713
+eval { $dbi->execute("drop table $table1") };
1714
+$dbi->execute($create_table1_2);
1715
+$dbi->insert(
1716
+    {$key3 => 3},
1717
+    primary_key => [$key1, $key2], 
1718
+    table => $table1,
1719
+    id => [1, 2],
1720
+);
1721
+is($dbi->select(table => $table1)->one->{$key1}, 1);
1722
+is($dbi->select(table => $table1)->one->{$key2}, 2);
1723
+is($dbi->select(table => $table1)->one->{$key3}, 3);
1724
+
1725
+test 'update';
1726
+$dbi = DBIx::Custom::Next->connect;
1727
+eval { $dbi->execute("drop table $table1") };
1728
+$dbi->execute($create_table1_2);
1729
+$dbi->insert({$key1 => 1, $key2 => 2, $key3 => 3}, table => $table1);
1730
+$dbi->update(
1731
+    {$key3 => 4},
1732
+    table => $table1,
1733
+    primary_key => [$key1, $key2],
1734
+    id => [1, 2],
1735
+);
1736
+is($dbi->select(table => $table1)->one->{$key1}, 1);
1737
+is($dbi->select(table => $table1)->one->{$key2}, 2);
1738
+is($dbi->select(table => $table1)->one->{$key3}, 4);
1739
+
1740
+$dbi->delete_all(table => $table1);
1741
+$dbi->insert({$key1 => 1, $key2 => 2, $key3 => 3}, table => $table1);
1742
+$dbi->update(
1743
+    {$key3 => 4},
1744
+    table => $table1,
1745
+    primary_key => $key1,
1746
+    id => 1,
1747
+);
1748
+is($dbi->select(table => $table1)->one->{$key1}, 1);
1749
+is($dbi->select(table => $table1)->one->{$key2}, 2);
1750
+is($dbi->select(table => $table1)->one->{$key3}, 4);
1751
+
1752
+$dbi = DBIx::Custom::Next->connect;
1753
+eval { $dbi->execute("drop table $table1") };
1754
+$dbi->execute($create_table1_2);
1755
+$dbi->insert({$key1 => 1, $key2 => 2, $key3 => 3}, table => $table1);
1756
+$dbi->update(
1757
+    {$key3 => 4},
1758
+    table => $table1,
1759
+    primary_key => [$key1, $key2],
1760
+    id=> [1, 2]
1761
+);
1762
+is($dbi->select(table => $table1)->one->{$key1}, 1);
1763
+is($dbi->select(table => $table1)->one->{$key2}, 2);
1764
+is($dbi->select(table => $table1)->one->{$key3}, 4);
1765
+
1766
+test 'select';
1767
+$dbi = DBIx::Custom::Next->connect;
1768
+eval { $dbi->execute("drop table $table1") };
1769
+$dbi->execute($create_table1_2);
1770
+$dbi->insert({$key1 => 1, $key2 => 2, $key3 => 3}, table => $table1);
1771
+$result = $dbi->select(
1772
+    table => $table1,
1773
+    primary_key => [$key1, $key2],
1774
+    id => [1, 2]
1775
+);
1776
+$row = $result->one;
1777
+is($row->{$key1}, 1);
1778
+is($row->{$key2}, 2);
1779
+is($row->{$key3}, 3);
1780
+
1781
+$dbi->delete_all(table => $table1);
1782
+$dbi->insert({$key1 => 1, $key2 => 2, $key3 => 3}, table => $table1);
1783
+$result = $dbi->select(
1784
+    table => $table1,
1785
+    primary_key => $key1,
1786
+    id => 1,
1787
+);
1788
+$row = $result->one;
1789
+is($row->{$key1}, 1);
1790
+is($row->{$key2}, 2);
1791
+is($row->{$key3}, 3);
1792
+
1793
+$dbi->delete_all(table => $table1);
1794
+$dbi->insert({$key1 => 1, $key2 => 2, $key3 => 3}, table => $table1);
1795
+$result = $dbi->select(
1796
+    table => $table1,
1797
+    primary_key => [$key1, $key2],
1798
+    id => [1, 2]
1799
+);
1800
+$row = $result->one;
1801
+is($row->{$key1}, 1);
1802
+is($row->{$key2}, 2);
1803
+is($row->{$key3}, 3);
1804
+
1805
+test 'model delete';
1806
+$dbi = MyDBI6->connect;
1807
+eval { $dbi->execute("drop table $table1") };
1808
+eval { $dbi->execute("drop table $table2") };
1809
+eval { $dbi->execute("drop table $table3") };
1810
+$dbi->execute($create_table1_2);
1811
+$dbi->execute($create_table2_2);
1812
+$dbi->execute($create_table3);
1813
+$dbi->insert({$key1 => 1, $key2 => 2, $key3 => 3}, table => $table1);
1814
+$dbi->model($table1)->delete(id => [1, 2]);
1815
+is_deeply($dbi->select(table => $table1)->all, []);
1816
+$dbi->insert({$key1 => 1, $key2 => 2, $key3 => 3}, table => $table2);
1817
+$dbi->model($table1)->delete(id => [1, 2]);
1818
+is_deeply($dbi->select(table => $table1)->all, []);
1819
+$dbi->insert({$key1 => 1, $key2 => 2, $key3 => 3}, table => $table3);
1820
+$dbi->model($table3)->delete(id => [1, 2]);
1821
+is_deeply($dbi->select(table => $table3)->all, []);
1822
+
1823
+test 'model insert';
1824
+$dbi = MyDBI6->connect;
1825
+eval { $dbi->execute("drop table $table1") };
1826
+$dbi->execute($create_table1_2);
1827
+$dbi->model($table1)->insert(
1828
+    {$key3 => 3},
1829
+    id => [1, 2],
1830
+);
1831
+$result = $dbi->model($table1)->select;
1832
+$row = $result->one;
1833
+is($row->{$key1}, 1);
1834
+is($row->{$key2}, 2);
1835
+is($row->{$key3}, 3);
1836
+
1837
+test 'model update';
1838
+$dbi = MyDBI6->connect;
1839
+eval { $dbi->execute("drop table $table1") };
1840
+$dbi->execute($create_table1_2);
1841
+$dbi->insert({$key1 => 1, $key2 => 2, $key3 => 3}, table => $table1);
1842
+$dbi->model($table1)->update(
1843
+    {$key3 => 4},
1844
+    id => [1, 2],
1845
+);
1846
+$result = $dbi->model($table1)->select;
1847
+$row = $result->one;
1848
+is($row->{$key1}, 1);
1849
+is($row->{$key2}, 2);
1850
+is($row->{$key3}, 4);
1851
+
1852
+test 'model select';
1853
+$dbi = MyDBI6->connect;
1854
+eval { $dbi->execute("drop table $table1") };
1855
+$dbi->execute($create_table1_2);
1856
+$dbi->insert({$key1 => 1, $key2 => 2, $key3 => 3}, table => $table1);
1857
+$result = $dbi->model($table1)->select(id => [1, 2]);
1858
+$row = $result->one;
1859
+is($row->{$key1}, 1);
1860
+is($row->{$key2}, 2);
1861
+is($row->{$key3}, 3);
1862
+
1863
+
1864
+test 'mycolumn and column';
1865
+$dbi = MyDBI7->connect;
1866
+$dbi->user_table_info($user_table_info);
1867
+eval { $dbi->execute("drop table $table1") };
1868
+eval { $dbi->execute("drop table $table2") };
1869
+$dbi->execute($create_table1);
1870
+$dbi->execute($create_table2);
1871
+$dbi->separator('__');
1872
+$dbi->setup_model;
1873
+$dbi->insert({$key1 => 1, $key2 => 2}, table => $table1);
1874
+$dbi->insert({$key1 => 1, $key3 => 3}, table => $table2);
1875
+$model = $dbi->model($table1);
1876
+$result = $model->select(
1877
+    column => [$model->mycolumn, $model->column($table2)],
1878
+    where => {"$table1.$key1" => 1}
1879
+);
1880
+is_deeply($result->one,
1881
+          {$key1 => 1, $key2 => 2, "${table2}__$key1" => 1, "${table2}__$key3" => 3});
1882
+
1883
+test 'values_clause';
1884
+$dbi = DBIx::Custom::Next->connect;
1885
+eval { $dbi->execute("drop table $table1") };
1886
+$dbi->execute($create_table1_2);
1887
+$param = {$key1 => 1, $key2 => 2};
1888
+$values_clause = $dbi->values_clause($param);
1889
+$sql = <<"EOS";
1890
+insert into $table1 $values_clause
1891
+EOS
1892
+$dbi->execute($sql, $param, table => $table1);
1893
+is($dbi->select(table => $table1)->one->{$key1}, 1);
1894
+is($dbi->select(table => $table1)->one->{$key2}, 2);
1895
+
1896
+$dbi = DBIx::Custom::Next->connect;
1897
+eval { $dbi->execute("drop table $table1") };
1898
+$dbi->execute($create_table1_2);
1899
+$param = {$key1 => 1, $key2 => 2};
1900
+$values_clause = $dbi->values_clause($param);
1901
+$sql = <<"EOS";
1902
+insert into $table1 $values_clause
1903
+EOS
1904
+$dbi->execute($sql, $param, table => $table1);
1905
+is($dbi->select(table => $table1)->one->{$key1}, 1);
1906
+is($dbi->select(table => $table1)->one->{$key2}, 2);
1907
+
1908
+test 'mycolumn';
1909
+$dbi = MyDBI8->connect;
1910
+$dbi->user_table_info($user_table_info);
1911
+eval { $dbi->execute("drop table $table1") };
1912
+eval { $dbi->execute("drop table $table2") };
1913
+$dbi->execute($create_table1);
1914
+$dbi->execute($create_table2);
1915
+$dbi->setup_model;
1916
+$dbi->insert({$key1 => 1, $key2 => 2}, table => $table1);
1917
+$dbi->insert({$key1 => 1, $key3 => 3}, table => $table2);
1918
+$model = $dbi->model($table1);
1919
+$result = $model->select(
1920
+    column => [
1921
+        $model->mycolumn,
1922
+        $model->column($table2)
1923
+    ]
1924
+);
1925
+is_deeply($result->one,
1926
+          {$key1 => 1, $key2 => 2, "$table2.$key1" => 1, "$table2.$key3" => 3});
1927
+
1928
+$result = $model->select(
1929
+    column => [
1930
+        $model->mycolumn([$key1]),
1931
+        $model->column($table2 => [$key1])
1932
+    ]
1933
+);
1934
+is_deeply($result->one,
1935
+          {$key1 => 1, "$table2.$key1" => 1});
1936
+$result = $model->select(
1937
+    column => [
1938
+        $model->mycolumn([$key1]),
1939
+        {$table2 => [$key1]}
1940
+    ]
1941
+);
1942
+is_deeply($result->one,
1943
+          {$key1 => 1, "$table2.$key1" => 1});
1944
+
1945
+$result = $model->select(
1946
+    column => [
1947
+        $model->mycolumn([$key1]),
1948
+        "$table2.$key1 as " . $dbi->q("$table2.$key1")
1949
+    ]
1950
+);
1951
+is_deeply($result->one,
1952
+          {$key1 => 1, "$table2.$key1" => 1});
1953
+
1954
+$result = $model->select(
1955
+    column => [
1956
+        $model->mycolumn([$key1]),
1957
+        "$table2.$key1 as " . $dbi->q("$table2.$key1")
1958
+    ]
1959
+);
1960
+is_deeply($result->one,
1961
+          {$key1 => 1, "$table2.$key1" => 1});
1962
+
1963
+test 'merge_param';
1964
+$dbi = DBIx::Custom::Next->new;
1965
+$params = [
1966
+    {$key1 => 1, $key2 => 2, $key3 => 3},
1967
+    {$key1 => 1, $key2 => 2},
1968
+    {$key1 => 1}
1969
+];
1970
+$param = $dbi->merge_param($params->[0], $params->[1], $params->[2]);
1971
+is_deeply($param, {$key1 => [1, 1, 1], $key2 => [2, 2], $key3 => 3});
1972
+
1973
+$params = [
1974
+    {$key1 => [1, 2], $key2 => 1, $key3 => [1, 2]},
1975
+    {$key1 => [3, 4], $key2 => [2, 3], $key3 => 3}
1976
+];
1977
+$param = $dbi->merge_param($params->[0], $params->[1]);
1978
+is_deeply($param, {$key1 => [1, 2, 3, 4], $key2 => [1, 2, 3], $key3 => [1, 2, 3]});
1979
+
1980
+test 'select() param option';
1981
+$dbi = DBIx::Custom::Next->connect;
1982
+eval { $dbi->execute("drop table $table1") };
1983
+$dbi->execute($create_table1);
1984
+$dbi->insert({$key1 => 1, $key2 => 2}, table => $table1);
1985
+$dbi->insert({$key1 => 2, $key2 => 3}, table => $table1);
1986
+eval { $dbi->execute("drop table $table2") };
1987
+$dbi->execute($create_table2);
1988
+$dbi->insert({$key1 => 1, $key3 => 4}, table => $table2);
1989
+$dbi->insert({$key1 => 2, $key3 => 5}, table => $table2);
1990
+$rows = $dbi->select(
1991
+    table => $table1,
1992
+    column => "$table1.$key1 as ${table1}_$key1, $key2, $key3",
1993
+    where   => {"$table1.$key2" => 3},
1994
+    join  => ["inner join (select * from $table2 where :$table2.${key3}{=})" . 
1995
+              " $table2 on $table1.$key1 = $table2.$key1"],
1996
+    param => {"$table2.$key3" => 5}
1997
+)->all;
1998
+is_deeply($rows, [{"${table1}_$key1" => 2, $key2 => 3, $key3 => 5}]);
1999
+
2000
+$rows = $dbi->select(
2001
+    table => $table1,
2002
+    column => "$table1.$key1 as ${table1}_$key1, $key2, $key3",
2003
+    where   => {"$table1.$key2" => 3},
2004
+    join  => "inner join (select * from $table2 where :$table2.${key3}{=})" . 
2005
+             " $table2 on $table1.$key1 = $table2.$key1",
2006
+    param => {"$table2.$key3" => 5}
2007
+)->all;
2008
+is_deeply($rows, [{"${table1}_$key1" => 2, $key2 => 3, $key3 => 5}]);
2009
+
2010
+test 'select() string where';
2011
+$dbi = DBIx::Custom::Next->connect;
2012
+eval { $dbi->execute("drop table $table1") };
2013
+$dbi->execute($create_table1);
2014
+$dbi->insert({$key1 => 1, $key2 => 2}, table => $table1);
2015
+$dbi->insert({$key1 => 2, $key2 => 3}, table => $table1);
2016
+$rows = $dbi->select(
2017
+    table => $table1,
2018
+    where => [
2019
+        "$key1 = :$key1 and $key2 = :$key2",
2020
+        {$key1 => 1, $key2 => 2}
2021
+    ]
2022
+)->all;
2023
+is_deeply($rows, [{$key1 => 1, $key2 => 2}]);
2024
+
2025
+$dbi = DBIx::Custom::Next->connect;
2026
+eval { $dbi->execute("drop table $table1") };
2027
+$dbi->execute($create_table1);
2028
+$dbi->insert({$key1 => 1, $key2 => 2}, table => $table1);
2029
+$dbi->insert({$key1 => 2, $key2 => 3}, table => $table1);
2030
+$rows = $dbi->select(
2031
+    table => $table1,
2032
+    where => [
2033
+        "$key1 = :$key1 and $key2 = :$key2",
2034
+        {$key1 => 1, $key2 => 2}
2035
+    ]
2036
+)->all;
2037
+is_deeply($rows, [{$key1 => 1, $key2 => 2}]);
2038
+
2039
+$dbi = DBIx::Custom::Next->connect;
2040
+eval { $dbi->execute("drop table $table1") };
2041
+$dbi->execute($create_table1);
2042
+$dbi->insert({$key1 => 1, $key2 => 2}, table => $table1);
2043
+$dbi->insert({$key1 => 2, $key2 => 3}, table => $table1);
2044
+$rows = $dbi->select(
2045
+    table => $table1,
2046
+    where => [
2047
+        "$key1 = :$key1 and $key2 = :$key2",
2048
+        {$key1 => 1, $key2 => 2}
2049
+    ]
2050
+)->all;
2051
+is_deeply($rows, [{$key1 => 1, $key2 => 2}]);
2052
+
2053
+test 'delete() string where';
2054
+$dbi = DBIx::Custom::Next->connect;
2055
+eval { $dbi->execute("drop table $table1") };
2056
+$dbi->execute($create_table1);
2057
+$dbi->insert({$key1 => 1, $key2 => 2}, table => $table1);
2058
+$dbi->insert({$key1 => 2, $key2 => 3}, table => $table1);
2059
+$dbi->delete(
2060
+    table => $table1,
2061
+    where => [
2062
+        "$key1 = :$key1 and $key2 = :$key2",
2063
+        {$key1 => 1, $key2 => 2}
2064
+    ]
2065
+);
2066
+$rows = $dbi->select(table => $table1)->all;
2067
+is_deeply($rows, [{$key1 => 2, $key2 => 3}]);
2068
+
2069
+$dbi = DBIx::Custom::Next->connect;
2070
+eval { $dbi->execute("drop table $table1") };
2071
+$dbi->execute($create_table1);
2072
+$dbi->insert({$key1 => 1, $key2 => 2}, table => $table1);
2073
+$dbi->insert({$key1 => 2, $key2 => 3}, table => $table1);
2074
+$dbi->delete(
2075
+    table => $table1,
2076
+    where => [
2077
+        "$key1 = :$key1 and $key2 = :$key2",
2078
+         {$key1 => 1, $key2 => 2}
2079
+    ]
2080
+);
2081
+$rows = $dbi->select(table => $table1)->all;
2082
+is_deeply($rows, [{$key1 => 2, $key2 => 3}]);
2083
+
2084
+
2085
+test 'update() string where';
2086
+$dbi = DBIx::Custom::Next->connect;
2087
+eval { $dbi->execute("drop table $table1") };
2088
+$dbi->execute($create_table1);
2089
+$dbi->insert({$key1 => 1, $key2 => 2}, table => $table1);
2090
+$dbi->update(
2091
+    {$key1 => 5},
2092
+    table => $table1,
2093
+    where => [
2094
+        "$key1 = :$key1 and $key2 = :$key2",
2095
+        {$key1 => 1, $key2 => 2}
2096
+    ]
2097
+);
2098
+$rows = $dbi->select(table => $table1)->all;
2099
+is_deeply($rows, [{$key1 => 5, $key2 => 2}]);
2100
+
2101
+$dbi = DBIx::Custom::Next->connect;
2102
+eval { $dbi->execute("drop table $table1") };
2103
+$dbi->execute($create_table1);
2104
+$dbi->insert({$key1 => 1, $key2 => 2}, table => $table1);
2105
+$dbi->update(
2106
+    {$key1 => 5},
2107
+    table => $table1,
2108
+    where => [
2109
+        "$key1 = :$key1 and $key2 = :$key2",
2110
+        {$key1 => 1, $key2 => 2}
2111
+    ]
2112
+);
2113
+$rows = $dbi->select(table => $table1)->all;
2114
+is_deeply($rows, [{$key1 => 5, $key2 => 2}]);
2115
+
2116
+test 'insert id and primary_key option';
2117
+$dbi = DBIx::Custom::Next->connect;
2118
+eval { $dbi->execute("drop table $table1") };
2119
+$dbi->execute($create_table1_2);
2120
+$dbi->insert(
2121
+    {$key3 => 3},
2122
+    primary_key => [$key1, $key2], 
2123
+    table => $table1,
2124
+    id => [1, 2],
2125
+);
2126
+is($dbi->select(table => $table1)->one->{$key1}, 1);
2127
+is($dbi->select(table => $table1)->one->{$key2}, 2);
2128
+is($dbi->select(table => $table1)->one->{$key3}, 3);
2129
+
2130
+$dbi->delete_all(table => $table1);
2131
+$dbi->insert(
2132
+    {$key2 => 2, $key3 => 3},
2133
+    primary_key => $key1, 
2134
+    table => $table1,
2135
+    id => 0,
2136
+);
2137
+
2138
+is($dbi->select(table => $table1)->one->{$key1}, 0);
2139
+is($dbi->select(table => $table1)->one->{$key2}, 2);
2140
+is($dbi->select(table => $table1)->one->{$key3}, 3);
2141
+
2142
+$dbi = DBIx::Custom::Next->connect;
2143
+eval { $dbi->execute("drop table $table1") };
2144
+$dbi->execute($create_table1_2);
2145
+$dbi->insert(
2146
+    {$key3 => 3},
2147
+    primary_key => [$key1, $key2], 
2148
+    table => $table1,
2149
+    id => 1,
2150
+);
2151
+is($dbi->select(table => $table1)->one->{$key1}, 1);
2152
+ok(!$dbi->select(table => $table1)->one->{$key2});
2153
+is($dbi->select(table => $table1)->one->{$key3}, 3);
2154
+
2155
+$dbi = DBIx::Custom::Next->connect;
2156
+eval { $dbi->execute("drop table $table1") };
2157
+$dbi->execute($create_table1_2);
2158
+$dbi->insert(
2159
+    {$key3 => 3},
2160
+    primary_key => [$key1, $key2], 
2161
+    table => $table1,
2162
+    id => [1, 2],
2163
+);
2164
+is($dbi->select(table => $table1)->one->{$key1}, 1);
2165
+is($dbi->select(table => $table1)->one->{$key2}, 2);
2166
+is($dbi->select(table => $table1)->one->{$key3}, 3);
2167
+
2168
+$dbi = DBIx::Custom::Next->connect;
2169
+eval { $dbi->execute("drop table $table1") };
2170
+$dbi->execute($create_table1_2);
2171
+$param = {$key3 => 3, $key2 => 4};
2172
+$dbi->insert(
2173
+    $param,
2174
+    primary_key => [$key1, $key2], 
2175
+    table => $table1,
2176
+    id => [1, 2],
2177
+);
2178
+is($dbi->select(table => $table1)->one->{$key1}, 1);
2179
+is($dbi->select(table => $table1)->one->{$key2}, 4);
2180
+is($dbi->select(table => $table1)->one->{$key3}, 3);
2181
+is_deeply($param, {$key3 => 3, $key2 => 4});
2182
+
2183
+$dbi = DBIx::Custom::Next->connect;
2184
+eval { $dbi->execute("drop table $table1") };
2185
+$dbi->execute($create_table1_2);
2186
+$param = {$key3 => 3, $key2 => 4};
2187
+$dbi->insert(
2188
+    $param,
2189
+    primary_key => [$key1, $key2], 
2190
+    table => $table1,
2191
+    id => [1, 2],
2192
+    query => 1
2193
+);
2194
+is(ref $query, 'HASH');
2195
+is_deeply($param, {$key3 => 3, $key2 => 4});
2196
+
2197
+test 'model insert id and primary_key option';
2198
+$dbi = MyDBI6->connect;
2199
+eval { $dbi->execute("drop table $table1") };
2200
+$dbi->execute($create_table1_2);
2201
+$dbi->model($table1)->insert(
2202
+    {$key3 => 3},
2203
+    id => [1, 2],
2204
+);
2205
+$result = $dbi->model($table1)->select;
2206
+$row = $result->one;
2207
+is($row->{$key1}, 1);
2208
+is($row->{$key2}, 2);
2209
+is($row->{$key3}, 3);
2210
+
2211
+$dbi = MyDBI6->connect;
2212
+eval { $dbi->execute("drop table $table1") };
2213
+$dbi->execute($create_table1_2);
2214
+$dbi->model($table1)->insert(
2215
+    {$key3 => 3},
2216
+    id => [1, 2]
2217
+);
2218
+$result = $dbi->model($table1)->select;
2219
+$row = $result->one;
2220
+is($row->{$key1}, 1);
2221
+is($row->{$key2}, 2);
2222
+is($row->{$key3}, 3);
2223
+
2224
+test 'update and id option';
2225
+$dbi = DBIx::Custom::Next->connect;
2226
+eval { $dbi->execute("drop table $table1") };
2227
+$dbi->execute($create_table1_2);
2228
+$dbi->insert({$key1 => 1, $key2 => 2, $key3 => 3}, table => $table1);
2229
+$dbi->update(
2230
+    {$key3 => 4},
2231
+    table => $table1,
2232
+    primary_key => [$key1, $key2],
2233
+    id => [1, 2],
2234
+);
2235
+is($dbi->select(table => $table1)->one->{$key1}, 1);
2236
+is($dbi->select(table => $table1)->one->{$key2}, 2);
2237
+is($dbi->select(table => $table1)->one->{$key3}, 4);
2238
+
2239
+$dbi->delete_all(table => $table1);
2240
+$dbi->insert({$key1 => 0, $key2 => 2, $key3 => 3}, table => $table1);
2241
+$dbi->update(
2242
+    {$key3 => 4},
2243
+    table => $table1,
2244
+    primary_key => $key1,
2245
+    id => 0,
2246
+);
2247
+is($dbi->select(table => $table1)->one->{$key1}, 0);
2248
+is($dbi->select(table => $table1)->one->{$key2}, 2);
2249
+is($dbi->select(table => $table1)->one->{$key3}, 4);
2250
+
2251
+$dbi = DBIx::Custom::Next->connect;
2252
+eval { $dbi->execute("drop table $table1") };
2253
+$dbi->execute($create_table1_2);
2254
+$dbi->insert({$key1 => 1, $key2 => 2, $key3 => 3}, table => $table1);
2255
+$dbi->update(
2256
+    {$key3 => 4},
2257
+    table => $table1,
2258
+    primary_key => [$key1, $key2],
2259
+    id => [1, 2]
2260
+);
2261
+is($dbi->select(table => $table1)->one->{$key1}, 1);
2262
+is($dbi->select(table => $table1)->one->{$key2}, 2);
2263
+is($dbi->select(table => $table1)->one->{$key3}, 4);
2264
+
2265
+
2266
+test 'model update and id option';
2267
+$dbi = MyDBI6->connect;
2268
+eval { $dbi->execute("drop table $table1") };
2269
+$dbi->execute($create_table1_2);
2270
+$dbi->insert({$key1 => 1, $key2 => 2, $key3 => 3}, table => $table1);
2271
+$dbi->model($table1)->update(
2272
+    {$key3 => 4},
2273
+    id => [1, 2],
2274
+);
2275
+$result = $dbi->model($table1)->select;
2276
+$row = $result->one;
2277
+is($row->{$key1}, 1);
2278
+is($row->{$key2}, 2);
2279
+is($row->{$key3}, 4);
2280
+
2281
+
2282
+test 'delete and id option';
2283
+$dbi = DBIx::Custom::Next->connect;
2284
+eval { $dbi->execute("drop table $table1") };
2285
+$dbi->execute($create_table1_2);
2286
+$dbi->insert({$key1 => 1, $key2 => 2, $key3 => 3}, table => $table1);
2287
+$dbi->delete(
2288
+    table => $table1,
2289
+    primary_key => [$key1, $key2],
2290
+    id => [1, 2],
2291
+);
2292
+is_deeply($dbi->select(table => $table1)->all, []);
2293
+
2294
+$dbi->insert({$key1 => 0, $key2 => 2, $key3 => 3}, table => $table1);
2295
+$dbi->delete(
2296
+    table => $table1,
2297
+    primary_key => $key1,
2298
+    id => 0,
2299
+);
2300
+is_deeply($dbi->select(table => $table1)->all, []);
2301
+
2302
+
2303
+test 'model delete and id option';
2304
+$dbi = MyDBI6->connect;
2305
+eval { $dbi->execute("drop table $table1") };
2306
+eval { $dbi->execute("drop table $table2") };
2307
+eval { $dbi->execute("drop table $table3") };
2308
+$dbi->execute($create_table1_2);
2309
+$dbi->execute($create_table2_2);
2310
+$dbi->execute($create_table3);
2311
+$dbi->insert({$key1 => 1, $key2 => 2, $key3 => 3}, table => $table1);
2312
+$dbi->model($table1)->delete(id => [1, 2]);
2313
+is_deeply($dbi->select(table => $table1)->all, []);
2314
+$dbi->insert({$key1 => 1, $key2 => 2, $key3 => 3}, table => $table2);
2315
+$dbi->model($table1)->delete(id => [1, 2]);
2316
+is_deeply($dbi->select(table => $table1)->all, []);
2317
+$dbi->insert({$key1 => 1, $key2 => 2, $key3 => 3}, table => $table3);
2318
+$dbi->model($table3)->delete(id => [1, 2]);
2319
+is_deeply($dbi->select(table => $table3)->all, []);
2320
+
2321
+
2322
+test 'select and id option';
2323
+$dbi = DBIx::Custom::Next->connect;
2324
+eval { $dbi->execute("drop table $table1") };
2325
+$dbi->execute($create_table1_2);
2326
+$dbi->insert({$key1 => 1, $key2 => 2, $key3 => 3}, table => $table1);
2327
+$result = $dbi->select(
2328
+    table => $table1,
2329
+    primary_key => [$key1, $key2],
2330
+    id => [1, 2]
2331
+);
2332
+$row = $result->one;
2333
+is($row->{$key1}, 1);
2334
+is($row->{$key2}, 2);
2335
+is($row->{$key3}, 3);
2336
+
2337
+$dbi->delete_all(table => $table1);
2338
+$dbi->insert({$key1 => 0, $key2 => 2, $key3 => 3}, table => $table1);
2339
+$result = $dbi->select(
2340
+    table => $table1,
2341
+    primary_key => $key1,
2342
+    id => 0,
2343
+);
2344
+$row = $result->one;
2345
+is($row->{$key1}, 0);
2346
+is($row->{$key2}, 2);
2347
+is($row->{$key3}, 3);
2348
+
2349
+$dbi->delete_all(table => $table1);
2350
+$dbi->insert({$key1 => 1, $key2 => 2, $key3 => 3}, table => $table1);
2351
+$result = $dbi->select(
2352
+    table => $table1,
2353
+    primary_key => [$key1, $key2],
2354
+    id => [1, 2]
2355
+);
2356
+$row = $result->one;
2357
+is($row->{$key1}, 1);
2358
+is($row->{$key2}, 2);
2359
+is($row->{$key3}, 3);
2360
+
2361
+
2362
+test 'model select';
2363
+$dbi = MyDBI6->connect;
2364
+eval { $dbi->execute("drop table $table1") };
2365
+$dbi->execute($create_table1_2);
2366
+$dbi->insert({$key1 => 1, $key2 => 2, $key3 => 3}, table => $table1);
2367
+$result = $dbi->model($table1)->select(id => [1, 2]);
2368
+$row = $result->one;
2369
+is($row->{$key1}, 1);
2370
+is($row->{$key2}, 2);
2371
+is($row->{$key3}, 3);
2372
+
2373
+test 'column separator is default .';
2374
+$dbi = MyDBI7->connect;
2375
+$dbi->user_table_info($user_table_info);
2376
+eval { $dbi->execute("drop table $table1") };
2377
+eval { $dbi->execute("drop table $table2") };
2378
+$dbi->execute($create_table1);
2379
+$dbi->execute($create_table2);
2380
+$dbi->setup_model;
2381
+$dbi->insert({$key1 => 1, $key2 => 2}, table => $table1);
2382
+$dbi->insert({$key1 => 1, $key3 => 3}, table => $table2);
2383
+$model = $dbi->model($table1);
2384
+$result = $model->select(
2385
+    column => [$model->column($table2)],
2386
+    where => {"$table1.$key1" => 1}
2387
+);
2388
+is_deeply($result->one,
2389
+          {"$table2.$key1" => 1, "$table2.$key3" => 3});
2390
+
2391
+$result = $model->select(
2392
+    column => [$model->column($table2 => [$key1, $key3])],
2393
+    where => {"$table1.$key1" => 1}
2394
+);
2395
+is_deeply($result->one,
2396
+          {"$table2.$key1" => 1, "$table2.$key3" => 3});
2397
+
2398
+test 'separator';
2399
+$dbi = DBIx::Custom::Next->connect;
2400
+$dbi->user_table_info($user_table_info);
2401
+eval { $dbi->execute("drop table $table1") };
2402
+eval { $dbi->execute("drop table $table2") };
2403
+$dbi->execute($create_table1);
2404
+$dbi->execute($create_table2);
2405
+
2406
+$dbi->create_model(
2407
+    table => $table1,
2408
+    join => [
2409
+       "left outer join $table2 on $table1.$key1 = $table2.$key1"
2410
+    ],
2411
+    primary_key => [$key1],
2412
+);
2413
+$model2 = $dbi->create_model(
2414
+    table => $table2,
2415
+);
2416
+$dbi->setup_model;
2417
+$dbi->insert({$key1 => 1, $key2 => 2}, table => $table1);
2418
+$dbi->insert({$key1 => 1, $key3 => 3}, table => $table2);
2419
+$model = $dbi->model($table1);
2420
+$result = $model->select(
2421
+    column => [
2422
+        $model->mycolumn,
2423
+        {$table2 => [$key1, $key3]}
2424
+    ],
2425
+    where => {"$table1.$key1" => 1}
2426
+);
2427
+is_deeply($result->one,
2428
+          {$key1 => 1, $key2 => 2, "$table2.$key1" => 1, "$table2.$key3" => 3});
2429
+is_deeply($model2->select->one, {$key1 => 1, $key3 => 3});
2430
+
2431
+$dbi->separator('__');
2432
+$model = $dbi->model($table1);
2433
+$result = $model->select(
2434
+    column => [
2435
+        $model->mycolumn,
2436
+        {$table2 => [$key1, $key3]}
2437
+    ],
2438
+    where => {"$table1.$key1" => 1}
2439
+);
2440
+is_deeply($result->one,
2441
+          {$key1 => 1, $key2 => 2, "${table2}__$key1" => 1, "${table2}__$key3" => 3});
2442
+is_deeply($model2->select->one, {$key1 => 1, $key3 => 3});
2443
+
2444
+$dbi->separator('-');
2445
+$model = $dbi->model($table1);
2446
+$result = $model->select(
2447
+    column => [
2448
+        $model->mycolumn,
2449
+        {$table2 => [$key1, $key3]}
2450
+    ],
2451
+    where => {"$table1.$key1" => 1}
2452
+);
2453
+is_deeply($result->one,
2454
+          {$key1 => 1, $key2 => 2, "$table2-$key1" => 1, "$table2-$key3" => 3});
2455
+is_deeply($model2->select->one, {$key1 => 1, $key3 => 3});
2456
+
2457
+
2458
+$dbi = DBIx::Custom::Next->connect;
2459
+$dbi->user_table_info($user_table_info);
2460
+eval { $dbi->execute("drop table $table1") };
2461
+eval { $dbi->execute("drop table $table2") };
2462
+$dbi->execute($create_table1);
2463
+$dbi->execute($create_table2);
2464
+
2465
+$dbi->create_model(
2466
+    table => $table1,
2467
+    join => [
2468
+       "left outer join $table2 on $table1.$key1 = $table2.$key1"
2469
+    ],
2470
+    primary_key => [$key1],
2471
+);
2472
+$dbi->setup_model;
2473
+$dbi->insert({$key1 => 1, $key2 => 2}, table => $table1);
2474
+$model = $dbi->model($table1);
2475
+$result = $model->select(column => $key1);
2476
+$result->filter($key1 => sub { $_[0] * 2 });
2477
+is_deeply($result->one, {$key1 => 2});
2478
+
2479
+test 'available_datetype';
2480
+$dbi = DBIx::Custom::Next->connect;
2481
+ok($dbi->can('available_datatype'));
2482
+
2483
+
2484
+test 'select prefix option';
2485
+$dbi = DBIx::Custom::Next->connect;
2486
+eval { $dbi->execute("drop table $table1") };
2487
+$dbi->execute($create_table1);
2488
+$dbi->insert({$key1 => 1, $key2 => 2}, table => $table1);
2489
+$rows = $dbi->select(prefix => "$key1,", column => $key2, table => $table1)->all;
2490
+is_deeply($rows, [{$key1 => 1, $key2 => 2}], "table");
2491
+
2492
+
2493
+test 'mapper';
2494
+$dbi = DBIx::Custom::Next->connect;
2495
+$param = $dbi->mapper(param => {id => 1, author => 'Ken', price => 1900})->map(
2496
+    id => {key => "$table1.id"},
2497
+    author => ["$table1.author" => sub { '%' . $_[0] . '%' }],
2498
+    price => {key => "$table1.price", condition => sub { $_[0] eq 1900 }}
2499
+);
2500
+is_deeply($param, {"$table1.id" => 1, "$table1.author" => '%Ken%',
2501
+  "$table1.price" => 1900});
2502
+
2503
+$dbi = DBIx::Custom::Next->connect;
2504
+$param = $dbi->mapper(param => {id => 1, author => 'Ken', price => 1900})->map(
2505
+    id => {key => "$table1.id"},
2506
+    author => ["$table1.author" => $dbi->like_value],
2507
+    price => {key => "$table1.price", condition => sub { $_[0] eq 1900 }}
2508
+);
2509
+is_deeply($param, {"$table1.id" => 1, "$table1.author" => '%Ken%',
2510
+  "$table1.price" => 1900});
2511
+
2512
+$param = $dbi->mapper(param => {id => 0, author => 0, price => 0})->map(
2513
+    id => {key => "$table1.id"},
2514
+    author => ["$table1.author" => sub { '%' . $_[0] . '%' }],
2515
+    price => ["$table1.price", sub { '%' . $_[0] . '%' }, sub { $_[0] eq 0 }]
2516
+);
2517
+is_deeply($param, {"$table1.id" => 0, "$table1.author" => '%0%', "$table1.price" => '%0%'});
2518
+
2519
+$param = $dbi->mapper(param => {id => '', author => '', price => ''})->map(
2520
+    id => {key => "$table1.id"},
2521
+    author => ["$table1.author" => sub { '%' . $_[0] . '%' }],
2522
+    price => ["$table1.price", sub { '%' . $_[0] . '%' }, sub { $_[0] eq 1 }]
2523
+);
2524
+is_deeply($param, {});
2525
+
2526
+$param = $dbi->mapper(param => {id => undef, author => undef, price => undef})->map(
2527
+    id => {key => "$table1.id"},
2528
+    price => {key => "$table1.price", condition => 'exists'}
2529
+);
2530
+is_deeply($param, {"$table1.price" => undef});
2531
+
2532
+$param = $dbi->mapper(param => {price => 'a'})->map(
2533
+    id => {key => "$table1.id", condition => 'exists'},
2534
+    price => ["$table1.price", sub { '%' . $_[0] }, 'exists']
2535
+);
2536
+is_deeply($param, {"$table1.price" => '%a'});
2537
+
2538
+$param = $dbi->mapper(param => {price => 'a'}, condition => 'exists')->map(
2539
+    id => {key => "$table1.id"},
2540
+    price => ["$table1.price", sub { '%' . $_[0] }]
2541
+);
2542
+is_deeply($param, {"$table1.price" => '%a'});
2543
+
2544
+eval { $dbi->execute("drop table $table1") };
2545
+$dbi->execute($create_table1);
2546
+$dbi->insert({$key1 => 1, $key2 => 2}, table => $table1);
2547
+$dbi->insert({$key1 => 3, $key2 => 4}, table => $table1);
2548
+
2549
+$where = $dbi->where;
2550
+$where->clause(['and', ":${key1}{=}"]);
2551
+$param = $dbi->mapper(param => {$key1 => undef}, condition => 'defined')->map;
2552
+$where->param($param);
2553
+$result = $dbi->execute("select * from $table1 $where", {$key1 => 1});
2554
+$row = $result->all;
2555
+is_deeply($row, [{$key1 => 1, $key2 => 2}, {$key1 => 3, $key2 => 4}]);
2556
+
2557
+$where = $dbi->where;
2558
+$where->clause(['or', ":${key1}{=}", ":${key1}{=}"]);
2559
+$param = $dbi->mapper(param => {$key1 => [undef, undef]}, condition => 'exists')->map;
2560
+$result = $dbi->execute("select * from $table1 $where", {$key1 => [1, 0]});
2561
+$row = $result->all;
2562
+is_deeply($row, [{$key1 => 1, $key2 => 2}]);
2563
+$result = $dbi->execute("select * from $table1 $where", {$key1 => [0, 1]});
2564
+$row = $result->all;
2565
+is_deeply($row, [{$key1 => 1, $key2 => 2}]);
2566
+
2567
+$where = $dbi->where;
2568
+$where->clause(['and', ":${key1}{=}"]);
2569
+$param = $dbi->mapper(param => {$key1 => [undef, undef]}, condition => 'defined')->map;
2570
+$where->param($param);
2571
+$result = $dbi->execute("select * from $table1 $where", {$key1 => [1, 0]});
2572
+$row = $result->all;
2573
+is_deeply($row, [{$key1 => 1, $key2 => 2}, {$key1 => 3, $key2 => 4}]);
2574
+$result = $dbi->execute("select * from $table1 $where", {$key1 => [0, 1]});
2575
+$row = $result->all;
2576
+is_deeply($row, [{$key1 => 1, $key2 => 2}, {$key1 => 3, $key2 => 4}]);
2577
+
2578
+
2579
+$where = $dbi->where;
2580
+$where->clause(['and', ":${key1}{=}"]);
2581
+$param = $dbi->mapper(param => {$key1 => 0}, condition => 'length')
2582
+  ->pass([$key1, $key2])->map;
2583
+$where->param($param);
2584
+$result = $dbi->execute("select * from $table1 $where", {$key1 => 1});
2585
+$row = $result->all;
2586
+is_deeply($row, [{$key1 => 1, $key2 => 2}]);
2587
+
2588
+$where = $dbi->where;
2589
+$where->clause(['and', ":${key1}{=}"]);
2590
+$param = $dbi->mapper(param => {$key1 => ''}, condition => 'length')->map;
2591
+$where->param($param);
2592
+$result = $dbi->execute("select * from $table1 $where", {$key1 => 1});
2593
+$row = $result->all;
2594
+is_deeply($row, [{$key1 => 1, $key2 => 2}, {$key1 => 3, $key2 => 4}]);
2595
+
2596
+$where = $dbi->where;
2597
+$where->clause(['and', ":${key1}{=}"]);
2598
+$param = $dbi->mapper(param => {$key1 => 5}, condition => sub { ($_[0] || '') eq 5 })
2599
+  ->pass([$key1, $key2])->map;
2600
+$where->param($param);
2601
+$result = $dbi->execute("select * from $table1 $where", {$key1 => 1});
2602
+$row = $result->all;
2603
+is_deeply($row, [{$key1 => 1, $key2 => 2}]);
2604
+
2605
+
2606
+$where = $dbi->where;
2607
+$where->clause(['and', ":${key1}{=}"]);
2608
+$param = $dbi->mapper(param => {$key1 => 7}, condition => sub { ($_[0] || '') eq 5 })->map;
2609
+$where->param($param);
2610
+$result = $dbi->execute("select * from $table1 $where", {$key1 => 1});
2611
+$row = $result->all;
2612
+is_deeply($row, [{$key1 => 1, $key2 => 2}, {$key1 => 3, $key2 => 4}]);
2613
+
2614
+$where = $dbi->where;
2615
+$param = $dbi->mapper(param => {id => 1, author => 'Ken', price => 1900})->map(
2616
+    id => {key => "$table1.id"},
2617
+    author => ["$table1.author", sub { '%' . $_[0] . '%' }],
2618
+    price => {key => "$table1.price", condition => sub { $_[0] eq 1900 }}
2619
+);
2620
+$where->param($param);
2621
+is_deeply($where->param, {"$table1.id" => 1, "$table1.author" => '%Ken%',
2622
+  "$table1.price" => 1900});
2623
+
2624
+$where = $dbi->where;
2625
+$param = $dbi->mapper(param => {id => 0, author => 0, price => 0})->map(
2626
+    id => {key => "$table1.id"},
2627
+    author => ["$table1.author", sub { '%' . $_[0] . '%' }],
2628
+    price => ["$table1.price", sub { '%' . $_[0] . '%' }, sub { $_[0] eq 0 }]
2629
+);
2630
+$where->param($param);
2631
+is_deeply($where->param, {"$table1.id" => 0, "$table1.author" => '%0%', "$table1.price" => '%0%'});
2632
+
2633
+$where = $dbi->where;
2634
+$param = $dbi->mapper(param => {id => '', author => '', price => ''})->map(
2635
+    id => {key => "$table1.id"},
2636
+    author => ["$table1.author", sub { '%' . $_[0] . '%' }],
2637
+    price => ["$table1.price", sub { '%' . $_[0] . '%' }, sub { $_[0] eq 1 }]
2638
+);
2639
+$where->param($param);
2640
+is_deeply($where->param, {});
2641
+
2642
+$where = $dbi->where;
2643
+$param = $dbi->mapper(param => {id => undef, author => undef, price => undef}, condition => 'exists')->map(
2644
+    id => {key => "$table1.id"},
2645
+    price => {key => "$table1.price", condition => 'exists'}
2646
+);
2647
+is_deeply($param, {"$table1.id"  => undef,"$table1.price" => undef});
2648
+
2649
+$where = $dbi->where;
2650
+$param = $dbi->mapper(param => {price => 'a'})->map(
2651
+    id => {key => "$table1.id", condition => 'exists'},
2652
+    price => ["$table1.price", sub { '%' . $_[0] }, 'exists']
2653
+);
2654
+is_deeply($param, {"$table1.price" => '%a'});
2655
+
2656
+$where = $dbi->where;
2657
+$param = $dbi->mapper(param => {id => [1, 2], author => 'Ken', price => 1900})->map(
2658
+    id => {key => "$table1.id"},
2659
+    author => ["$table1.author", sub { '%' . $_[0] . '%' }],
2660
+    price => {key => "$table1.price", condition => sub { $_[0] eq 1900 }}
2661
+);
2662
+is_deeply($param, {"$table1.id" => [1, 2], "$table1.author" => '%Ken%',
2663
+  "$table1.price" => 1900});
2664
+
2665
+$where = $dbi->where;
2666
+$param = $dbi->mapper(param => {id => ['', ''], author => 'Ken', price => 1900}, condition => 'length')->map(
2667
+    id => {key => "$table1.id"},
2668
+    author => ["$table1.author", sub { '%' . $_[0] . '%' }],
2669
+    price => {key => "$table1.price", condition => sub { $_[0] eq 1900 }}
2670
+);
2671
+is_deeply($param, {"$table1.id" => [$dbi->not_exists, $dbi->not_exists], "$table1.author" => '%Ken%',
2672
+  "$table1.price" => 1900});
2673
+
2674
+$where = $dbi->where;
2675
+$param = $dbi->mapper(param => {id => ['', ''], author => 'Ken', price => 1900})->map(
2676
+    id => {key => "$table1.id", condition => 'length'},
2677
+    author => ["$table1.author", sub { '%' . $_[0] . '%' }, 'defined'],
2678
+    price => {key => "$table1.price", condition => sub { $_[0] eq 1900 }}
2679
+);
2680
+is_deeply($param, {"$table1.id" => [$dbi->not_exists, $dbi->not_exists], "$table1.author" => '%Ken%',
2681
+  "$table1.price" => 1900});
2682
+
2683
+$where = $dbi->where;
2684
+$param = $dbi->mapper(param => {id => 'a', author => 'b', price => 'c'}, pass => [qw/id author/])
2685
+  ->map(price => {key => 'book.price'});
2686
+is_deeply($param, {id => 'a', author => 'b', 'book.price' => 'c'});
2687
+
2688
+test 'order';
2689
+$dbi = DBIx::Custom::Next->connect;
2690
+eval { $dbi->execute("drop table $table1") };
2691
+$dbi->execute($create_table1);
2692
+$dbi->insert({$key1 => 1, $key2 => 1}, table => $table1);
2693
+$dbi->insert({$key1 => 1, $key2 => 3}, table => $table1);
2694
+$dbi->insert({$key1 => 2, $key2 => 2}, table => $table1);
2695
+$dbi->insert({$key1 => 2, $key2 => 4}, table => $table1);
2696
+my $order = $dbi->order;
2697
+$order->prepend($key1, "$key2 desc");
2698
+$result = $dbi->select(table => $table1, append => $order);
2699
+is_deeply($result->all, [{$key1 => 1, $key2 => 3}, {$key1 => 1, $key2 => 1},
2700
+  {$key1 => 2, $key2 => 4}, {$key1 => 2, $key2 => 2}]);
2701
+$order->prepend("$key1 desc");
2702
+$result = $dbi->select(table => $table1, append => $order);
2703
+is_deeply($result->all, [{$key1 => 2, $key2 => 4}, {$key1 => 2, $key2 => 2},
2704
+  {$key1 => 1, $key2 => 3}, {$key1 => 1, $key2 => 1}]);
2705
+
2706
+$order = $dbi->order;
2707
+$order->prepend($dbi->q("$table1-$key1"), $dbi->q("$table1-$key2") . ' desc');
2708
+$result = $dbi->select(table => $table1,
2709
+  column => ["$key1 as " . $dbi->q("$table1-$key1"), "$key2 as " . $dbi->q("$table1-$key2")],
2710
+  append => $order);
2711
+is_deeply($result->all, [{"$table1-$key1" => 1, "$table1-$key2" => 3},
2712
+  {"$table1-$key1" => 1, "$table1-$key2" => 1},
2713
+  {"$table1-$key1" => 2, "$table1-$key2" => 4},
2714
+  {"$table1-$key1" => 2, "$table1-$key2" => 2}]);
2715
+
2716
+test 'last_sql';
2717
+$dbi = DBIx::Custom::Next->connect;
2718
+eval { $dbi->execute("drop table $table1") };
2719
+$dbi->execute($create_table1);
2720
+$dbi->execute("select * from $table1");
2721
+is($dbi->last_sql, "select * from $table1");
2722
+
2723
+eval{$dbi->execute("aaa")};
2724
+is($dbi->last_sql, 'aaa');
2725
+
2726
+test 'DBIx::Custom::Next header';
2727
+$dbi = DBIx::Custom::Next->connect;
2728
+eval { $dbi->execute("drop table $table1") };
2729
+$dbi->execute($create_table1);
2730
+$result = $dbi->execute("select $key1 as h1, $key2 as h2 from $table1");
2731
+is_deeply([map { lc } @{$result->header}], [qw/h1 h2/]);
2732
+
2733
+test 'Named placeholder :name(operater) syntax';
2734
+eval { $dbi->execute("drop table $table1") };
2735
+$dbi->execute($create_table1_2);
2736
+$dbi->insert({$key1 => 1, $key2 => 2, $key3 => 3, $key4 => 4, $key5 => 5}, table => $table1);
2737
+$dbi->insert({$key1 => 6, $key2 => 7, $key3 => 8, $key4 => 9, $key5 => 10}, table => $table1);
2738
+
2739
+$source = "select * from $table1 where :${key1}{=} and :${key2}{=}";
2740
+$result = $dbi->execute($source, {$key1 => 1, $key2 => 2});
2741
+$rows = $result->all;
2742
+is_deeply($rows, [{$key1 => 1, $key2 => 2, $key3 => 3, $key4 => 4, $key5 => 5}]);
2743
+
2744
+$source = "select * from $table1 where :${key1}{ = } and :${key2}{=}";
2745
+$result = $dbi->execute($source, {$key1 => 1, $key2 => 2});
2746
+$rows = $result->all;
2747
+is_deeply($rows, [{$key1 => 1, $key2 => 2, $key3 => 3, $key4 => 4, $key5 => 5}]);
2748
+
2749
+$source = "select * from $table1 where :${key1}{<} and :${key2}{=}";
2750
+$result = $dbi->execute($source, {$key1 => 5, $key2 => 2});
2751
+$rows = $result->all;
2752
+is_deeply($rows, [{$key1 => 1, $key2 => 2, $key3 => 3, $key4 => 4, $key5 => 5}]);
2753
+
2754
+$source = "select * from $table1 where :$table1.${key1}{=} and :$table1.${key2}{=}";
2755
+$result = $dbi->execute(
2756
+    $source,
2757
+    {"$table1.$key1" => 1, "$table1.$key2" => 1},
2758
+    filter => {"$table1.$key2" => sub { $_[0] * 2 }}
2759
+);
2760
+$rows = $result->all;
2761
+is_deeply($rows, [{$key1 => 1, $key2 => 2, $key3 => 3, $key4 => 4, $key5 => 5}]);
2762
+
2763
+eval { $dbi->execute("drop table $table1") };
2764
+eval { $dbi->execute("drop table $table2") };
2765
+$dbi->execute($create_table1);
2766
+$dbi->execute($create_table2);
2767
+$model = $dbi->create_model(table => $table1, primary_key => $key1);
2768
+$model->insert({$key1 => 1, $key2 => 2});
2769
+$model = $dbi->create_model(table => $table2, primary_key => $key1,
2770
+    join => ["left outer join $table1 on $table2.$key1 = $table1.$key1"]);
2771
+$model->insert({$key1 => 1, $key3 => 3});
2772
+$result = $model->select(
2773
+    column => {$table1 => ["$key2"]},
2774
+    id => 1
2775
+);
2776
+is_deeply($result->all, [{"$table1.$key2" => 2}]);
2777
+
2778
+test 'result';
2779
+$dbi = DBIx::Custom::Next->connect;
2780
+eval { $dbi->execute("drop table $table1") };
2781
+$dbi->execute($create_table1);
2782
+$dbi->insert({$key1 => 1, $key2 => 2}, table => $table1);
2783
+$dbi->insert({$key1 => 3, $key2 => 4}, table => $table1);
2784
+
2785
+$result = $dbi->select(table => $table1);
2786
+@rows = ();
2787
+while (my $row = $result->fetch) {
2788
+    push @rows, [@$row];
2789
+}
2790
+is_deeply(\@rows, [[1, 2], [3, 4]]);
2791
+
2792
+$result = $dbi->select(table => $table1);
2793
+@rows = ();
2794
+while (my $row = $result->fetch_hash) {
2795
+    push @rows, {%$row};
2796
+}
2797
+is_deeply(\@rows, [{$key1 => 1, $key2 => 2}, {$key1 => 3, $key2 => 4}]);
2798
+
2799
+$dbi = DBIx::Custom::Next->connect;
2800
+eval { $dbi->execute("drop table $table1") };
2801
+$dbi->execute($create_table1);
2802
+$dbi->insert({$key1 => 1, $key2 => 2}, table => $table1);
2803
+$dbi->insert({$key1 => 3, $key2 => 4}, table => $table1);
2804
+
2805
+test 'fetch_all';
2806
+$result = $dbi->select(table => $table1);
2807
+$rows = $result->fetch_all;
2808
+is_deeply($rows, [[1, 2], [3, 4]]);
2809
+
2810
+$result = $dbi->select(table => $table1);
2811
+$rows = $result->fetch_hash_all;
2812
+is_deeply($rows, [{$key1 => 1, $key2 => 2}, {$key1 => 3, $key2 => 4}]);
2813
+
2814
+$result = $dbi->select(table => $table1);
2815
+$result->dbi->filters({three_times => sub { $_[0] * 3}});
2816
+$result->filter({$key1 => 'three_times'});
2817
+$rows = $result->fetch_all;
2818
+is_deeply($rows, [[3, 2], [9, 4]], "array");
2819
+
2820
+$result = $dbi->select(column => [$key1, $key1, $key2], table => $table1);
2821
+$result->dbi->filters({three_times => sub { $_[0] * 3}});
2822
+$result->filter({$key1 => 'three_times'});
2823
+$rows = $result->fetch_all;
2824
+is_deeply($rows, [[3, 3, 2], [9, 9, 4]], "array");
2825
+
2826
+$result = $dbi->select(table => $table1);
2827
+$result->dbi->filters({three_times => sub { $_[0] * 3}});
2828
+$result->filter({$key1 => 'three_times'});
2829
+$rows = $result->fetch_hash_all;
2830
+is_deeply($rows, [{$key1 => 3, $key2 => 2}, {$key1 => 9, $key2 => 4}], "hash");
2831
+
2832
+test 'DBIx::Custom::Next::Result fetch_multi';
2833
+eval { $dbi->execute("drop table $table1") };
2834
+$dbi->execute($create_table1);
2835
+$dbi->insert({$key1 => 1, $key2 => 2}, table => $table1);
2836
+$dbi->insert({$key1 => 3, $key2 => 4}, table => $table1);
2837
+$dbi->insert({$key1 => 5, $key2 => 6}, table => $table1);
2838
+$result = $dbi->select(table => $table1);
2839
+$rows = $result->fetch_multi(2);
2840
+is_deeply($rows, [[1, 2], [3, 4]]);
2841
+$rows = $result->fetch_multi(2);
2842
+is_deeply($rows, [[5, 6]]);
2843
+$rows = $result->fetch_multi(2);
2844
+ok(!$rows);
2845
+
2846
+test 'DBIx::Custom::Next::Result fetch_hash_multi';
2847
+eval { $dbi->execute("drop table $table1") };
2848
+$dbi->execute($create_table1);
2849
+$dbi->insert({$key1 => 1, $key2 => 2}, table => $table1);
2850
+$dbi->insert({$key1 => 3, $key2 => 4}, table => $table1);
2851
+$dbi->insert({$key1 => 5, $key2 => 6}, table => $table1);
2852
+$result = $dbi->select(table => $table1);
2853
+$rows = $result->fetch_hash_multi(2);
2854
+is_deeply($rows, [{$key1 => 1, $key2 => 2}, {$key1 => 3, $key2 => 4}]);
2855
+$rows = $result->fetch_hash_multi(2);
2856
+is_deeply($rows, [{$key1 => 5, $key2 => 6}]);
2857
+$rows = $result->fetch_hash_multi(2);
2858
+ok(!$rows);
2859
+
2860
+test 'select() after_build_sql option';
2861
+$dbi = DBIx::Custom::Next->connect;
2862
+$dbi->user_table_info($user_table_info);
2863
+eval { $dbi->execute("drop table $table1") };
2864
+$dbi->execute($create_table1);
2865
+$dbi->insert({$key1 => 1, $key2 => 2}, table => $table1);
2866
+$dbi->insert({$key1 => 2, $key2 => 3}, table => $table1);
2867
+$rows = $dbi->select(
2868
+    table => $table1,
2869
+    column => $key1,
2870
+    after_build_sql => sub {
2871
+        my $sql = shift;
2872
+        $sql = "select * from ( $sql ) t where $key1 = 1";
2873
+        return $sql;
2874
+    }
2875
+)->all;
2876
+is_deeply($rows, [{$key1 => 1}]);
2877
+
2878
+test 'select() after_build_sql option';
2879
+$dbi = DBIx::Custom::Next->connect;
2880
+$dbi->user_table_info($user_table_info);
2881
+eval { $dbi->execute("drop table $table1") };
2882
+$dbi->execute($create_table1);
2883
+$dbi->insert({$key1 => 1, $key2 => 2}, table => $table1);
2884
+$dbi->insert({$key1 => 2, $key2 => 3}, table => $table1);
2885
+$rows = $dbi->select(
2886
+    table => $table1,
2887
+    column => $key1,
2888
+    after_build_sql => sub {
2889
+        my $sql = shift;
2890
+        $sql = "select * from ( $sql ) t where $key1 = 1";
2891
+        return $sql;
2892
+    }
2893
+)->all;
2894
+is_deeply($rows, [{$key1 => 1}]);
2895
+
2896
+test 'dbi helper from model';
2897
+$dbi = MyDBI9->connect;
2898
+eval { $dbi->execute("drop table $table1") };
2899
+$dbi->execute($create_table1);
2900
+$dbi->setup_model;
2901
+$model = $dbi->model($table1);
2902
+eval{$model->execute("select * from $table1")};
2903
+ok(!$@);
2904
+
2905
+test 'column table option';
2906
+$dbi = MyDBI9->connect;
2907
+$dbi->user_table_info($user_table_info);
2908
+eval { $dbi->execute("drop table $table1") };
2909
+$dbi->execute($create_table1);
2910
+eval { $dbi->execute("drop table $table2") };
2911
+$dbi->execute($create_table2);
2912
+$dbi->setup_model;
2913
+$dbi->execute("insert into $table1 ($key1, $key2) values (1, 2)");
2914
+$dbi->execute("insert into $table2 ($key1, $key3) values (1, 4)");
2915
+$model = $dbi->model($table1);
2916
+$result = $model->select(
2917
+    column => [
2918
+        $model->column($table2, {alias => $table2_alias})
2919
+    ],
2920
+    where => {"$table2_alias.$key3" => 4}
2921
+);
2922
+is_deeply($result->one, 
2923
+          {"$table2_alias.$key1" => 1, "$table2_alias.$key3" => 4});
2924
+
2925
+$dbi->separator('__');
2926
+$result = $model->select(
2927
+    column => [
2928
+        $model->column($table2, {alias => $table2_alias})
2929
+    ],
2930
+    where => {"$table2_alias.$key3" => 4}
2931
+);
2932
+is_deeply($result->one, 
2933
+          {"${table2_alias}__$key1" => 1, "${table2_alias}__$key3" => 4});
2934
+
2935
+$dbi->separator('-');
2936
+$result = $model->select(
2937
+    column => [
2938
+        $model->column($table2, {alias => $table2_alias})
2939
+    ],
2940
+    where => {"$table2_alias.$key3" => 4}
2941
+);
2942
+is_deeply($result->one, 
2943
+          {"$table2_alias-$key1" => 1, "$table2_alias-$key3" => 4});
2944
+
2945
+test 'create_model';
2946
+$dbi = DBIx::Custom::Next->connect;
2947
+$dbi->user_table_info($user_table_info);
2948
+eval { $dbi->execute("drop table $table1") };
2949
+eval { $dbi->execute("drop table $table2") };
2950
+$dbi->execute($create_table1);
2951
+$dbi->execute($create_table2);
2952
+
2953
+$dbi->create_model(
2954
+    table => $table1,
2955
+    join => [
2956
+       "left outer join $table2 on $table1.$key1 = $table2.$key1"
2957
+    ],
2958
+    primary_key => [$key1]
2959
+);
2960
+$model2 = $dbi->create_model(
2961
+    table => $table2
2962
+);
2963
+$dbi->create_model(
2964
+    table => $table3,
2965
+);
2966
+$dbi->setup_model;
2967
+$dbi->insert({$key1 => 1, $key2 => 2}, table => $table1);
2968
+$dbi->insert({$key1 => 1, $key3 => 3}, table => $table2);
2969
+$model = $dbi->model($table1);
2970
+$result = $model->select(
2971
+    column => [$model->mycolumn, $model->column($table2)],
2972
+    where => {"$table1.$key1" => 1}
2973
+);
2974
+is_deeply($result->one,
2975
+          {$key1 => 1, $key2 => 2, "$table2.$key1" => 1, "$table2.$key3" => 3});
2976
+is_deeply($model2->select->one, {$key1 => 1, $key3 => 3});
2977
+
2978
+test 'model helper';
2979
+$dbi = DBIx::Custom::Next->connect;
2980
+eval { $dbi->execute("drop table $table2") };
2981
+$dbi->execute($create_table2);
2982
+$dbi->insert({$key1 => 1, $key3 => 3}, table => $table2);
2983
+$model = $dbi->create_model(
2984
+    table => $table2
2985
+);
2986
+$model->helper(foo => sub { shift->select(@_) });
2987
+is_deeply($model->foo->one, {$key1 => 1, $key3 => 3});
2988
+
2989
+test 'model helper';
2990
+$dbi = DBIx::Custom::Next->connect;
2991
+eval { $dbi->execute("drop table $table2") };
2992
+$dbi->execute($create_table2);
2993
+$dbi->insert({$key1 => 1, $key3 => 3}, table => $table2);
2994
+$model = $dbi->create_model(
2995
+    table => $table2
2996
+);
2997
+$model->helper(foo => sub { shift->select(@_) });
2998
+is_deeply($model->foo->one, {$key1 => 1, $key3 => 3});
2999
+
3000
+test 'assign_clause';
3001
+$dbi = DBIx::Custom::Next->connect;
3002
+eval { $dbi->execute("drop table $table1") };
3003
+$dbi->execute($create_table1_2);
3004
+$dbi->insert({$key1 => 1, $key2 => 2, $key3 => 3, $key4 => 4, $key5 => 5}, table => $table1);
3005
+$dbi->insert({$key1 => 6, $key2 => 7, $key3 => 8, $key4 => 9, $key5 => 10}, table => $table1);
3006
+
3007
+$param = {$key2 => 11};
3008
+$assign_clause = $dbi->assign_clause($param);
3009
+$sql = <<"EOS";
3010
+update $table1 set $assign_clause
3011
+where $key1 = 1
3012
+EOS
3013
+$dbi->execute($sql, $param);
3014
+$result = $dbi->execute("select * from $table1 order by $key1", {}, table => $table1);
3015
+$rows   = $result->all;
3016
+is_deeply($rows, [{$key1 => 1, $key2 => 11, $key3 => 3, $key4 => 4, $key5 => 5},
3017
+                  {$key1 => 6, $key2 => 7,  $key3 => 8, $key4 => 9, $key5 => 10}],
3018
+                  "basic");
3019
+
3020
+
3021
+$dbi = DBIx::Custom::Next->connect;
3022
+eval { $dbi->execute("drop table $table1") };
3023
+$dbi->execute($create_table1_2);
3024
+$dbi->insert({$key1 => 1, $key2 => 2, $key3 => 3, $key4 => 4, $key5 => 5}, table => $table1);
3025
+$dbi->insert({$key1 => 6, $key2 => 7, $key3 => 8, $key4 => 9, $key5 => 10}, table => $table1);
3026
+
3027
+$param = {$key2 => 11, $key3 => 33};
3028
+$assign_clause = $dbi->assign_clause($param);
3029
+$sql = <<"EOS";
3030
+update $table1 set $assign_clause
3031
+where $key1 = 1
3032
+EOS
3033
+$dbi->execute($sql, $param);
3034
+$result = $dbi->execute("select * from $table1 order by $key1", {}, table => $table1);
3035
+$rows   = $result->all;
3036
+is_deeply($rows, [{$key1 => 1, $key2 => 11, $key3 => 33, $key4 => 4, $key5 => 5},
3037
+                  {$key1 => 6, $key2 => 7,  $key3 => 8, $key4 => 9, $key5 => 10}],
3038
+                  "basic");
3039
+
3040
+$dbi = DBIx::Custom::Next->connect;
3041
+eval { $dbi->execute("drop table $table1") };
3042
+$dbi->execute($create_table1_2);
3043
+$dbi->insert({$key1 => 1, $key2 => 2, $key3 => 3, $key4 => 4, $key5 => 5}, table => $table1);
3044
+$dbi->insert({$key1 => 6, $key2 => 7, $key3 => 8, $key4 => 9, $key5 => 10}, table => $table1);
3045
+
3046
+$param = {$key2 => 11, $key3 => 33};
3047
+$assign_clause = $dbi->assign_clause($param);
3048
+$sql = <<"EOS";
3049
+update $table1 set $assign_clause
3050
+where $key1 = 1
3051
+EOS
3052
+$dbi->execute($sql, $param);
3053
+$result = $dbi->execute("select * from $table1 order by $key1", {}, table => $table1);
3054
+$rows   = $result->all;
3055
+is_deeply($rows, [{$key1 => 1, $key2 => 11, $key3 => 33, $key4 => 4, $key5 => 5},
3056
+                  {$key1 => 6, $key2 => 7,  $key3 => 8, $key4 => 9, $key5 => 10}],
3057
+                  "update param no_set");
3058
+
3059
+            
3060
+$dbi = DBIx::Custom::Next->connect;
3061
+eval { $dbi->execute("drop table $table1") };
3062
+$dbi->execute($create_table1_2);
3063
+$dbi->insert({$key1 => 1, $key2 => 2, $key3 => 3, $key4 => 4, $key5 => 5}, table => $table1);
3064
+$dbi->insert({$key1 => 6, $key2 => 7, $key3 => 8, $key4 => 9, $key5 => 10}, table => $table1);
3065
+
3066
+$param = {$key2 => 11};
3067
+$assign_clause = $dbi->assign_clause($param);
3068
+$sql = <<"EOS";
3069
+update $table1 set $assign_clause
3070
+where $key1 = 1
3071
+EOS
3072
+$dbi->execute($sql, $param, table => $table1);
3073
+$result = $dbi->execute("select * from $table1 order by $key1");
3074
+$rows   = $result->all;
3075
+is_deeply($rows, [{$key1 => 1, $key2 => 11, $key3 => 3, $key4 => 4, $key5 => 5},
3076
+                  {$key1 => 6, $key2 => 7,  $key3 => 8, $key4 => 9, $key5 => 10}],
3077
+                  "basic");
3078
+
3079
+$param = {$key2 => 11};
3080
+$assign_clause = $dbi->assign_clause($param);
3081
+$sql = <<"EOS";
3082
+update $table1 set $assign_clause
3083
+where $key1 = 1
3084
+EOS
3085
+$dbi->execute($sql, $param, table => $table1);
3086
+$result = $dbi->execute("select * from $table1 order by $key1");
3087
+$rows   = $result->all;
3088
+is_deeply($rows, [{$key1 => 1, $key2 => 11, $key3 => 3, $key4 => 4, $key5 => 5},
3089
+                  {$key1 => 6, $key2 => 7,  $key3 => 8, $key4 => 9, $key5 => 10}],
3090
+                  "basic");
3091
+
3092
+test 'Model class';
3093
+$dbi = MyDBI1->connect;
3094
+eval { $dbi->execute("drop table $table1") };
3095
+$dbi->execute($create_table1);
3096
+$model = $dbi->model($table1);
3097
+$model->insert({$key1 => 'a', $key2 => 'b'});
3098
+is_deeply($model->list->all, [{$key1 => 'a', $key2 => 'b'}], 'basic');
3099
+eval { $dbi->execute("drop table $table2") };
3100
+$dbi->execute($create_table2);
3101
+$model = $dbi->model($table2);
3102
+$model->insert({$key1 => 'a'});
3103
+is_deeply($model->list->all, [{$key1 => 'a', $key3 => undef}], 'basic');
3104
+is($dbi->models->{$table1}, $dbi->model($table1));
3105
+is($dbi->models->{$table2}, $dbi->model($table2));
3106
+
3107
+$dbi = MyDBI4->connect;
3108
+eval { $dbi->execute("drop table $table1") };
3109
+$dbi->execute($create_table1);
3110
+$model = $dbi->model($table1);
3111
+$model->insert({$key1 => 'a', $key2 => 'b'});
3112
+is_deeply($model->list->all, [{$key1 => 'a', $key2 => 'b'}], 'basic');
3113
+eval { $dbi->execute("drop table $table2") };
3114
+$dbi->execute($create_table2);
3115
+$model = $dbi->model($table2);
3116
+$model->insert({$key1 => 'a'});
3117
+is_deeply($model->list->all, [{$key1 => 'a', $key3 => undef}], 'basic');
3118
+
3119
+$dbi = MyDBI5->connect;
3120
+eval { $dbi->execute("drop table $table1") };
3121
+eval { $dbi->execute("drop table $table2") };
3122
+$dbi->execute($create_table1);
3123
+$dbi->execute($create_table2);
3124
+$model = $dbi->model($table2);
3125
+$model->insert({$key1 => 'a'});
3126
+is_deeply($model->list->all, [{$key1 => 'a', $key3 => undef}], 'include all model');
3127
+$dbi->insert({$key1 => 1}, table => $table1);
3128
+$model = $dbi->model($table1);
3129
+is_deeply($model->list->all, [{$key1 => 1, $key2 => undef}], 'include all model');
3130
+
3131
+test 'primary_key';
3132
+$dbi = MyDBI1->connect;
3133
+$model = $dbi->model($table1);
3134
+$model->primary_key([$key1, $key2]);
3135
+is_deeply($model->primary_key, [$key1, $key2]);
3136
+
3137
+test 'columns';
3138
+$dbi = MyDBI1->connect;
3139
+$model = $dbi->model($table1);
3140
+$model->columns([$key1, $key2]);
3141
+is_deeply($model->columns, [$key1, $key2]);
3142
+
3143
+test 'setup_model';
3144
+$dbi = MyDBI1->connect;
3145
+$dbi->user_table_info($user_table_info);
3146
+eval { $dbi->execute("drop table $table1") };
3147
+eval { $dbi->execute("drop table $table2") };
3148
+
3149
+$dbi->execute($create_table1);
3150
+$dbi->execute($create_table2);
3151
+$dbi->setup_model;
3152
+is_deeply([sort @{$dbi->model($table1)->columns}], [$key1, $key2]);
3153
+is_deeply([sort @{$dbi->model($table2)->columns}], [$key1, $key3]);
3154
+
3155
+test 'each_column';
3156
+$dbi = DBIx::Custom::Next->connect;
3157
+eval { $dbi->execute("drop table ${q}table$p") };
3158
+eval { $dbi->execute("drop table $table1") };
3159
+eval { $dbi->execute("drop table $table2") };
3160
+eval { $dbi->execute("drop table $table3") };
3161
+$dbi->execute($create_table1_type);
3162
+$dbi->execute($create_table2);
3163
+
3164
+$infos = [];
3165
+$dbi->each_column(sub {
3166
+    my ($self, $table, $column, $cinfo) = @_;
3167
+    
3168
+    if ($table =~ /^table\d/i) {
3169
+         my $info = [$table, $column, $cinfo->{COLUMN_NAME}];
3170
+         push @$infos, $info;
3171
+    }
3172
+});
3173
+$infos = [sort { $a->[0] cmp $b->[0] || $a->[1] cmp $b->[1] } @$infos];
3174
+is_deeply($infos, 
3175
+    [
3176
+        [$table1, $key1, $key1],
3177
+        [$table1, $key2, $key2],
3178
+        [$table2, $key1, $key1],
3179
+        [$table2, $key3, $key3]
3180
+    ]
3181
+    
3182
+);
3183
+
3184
+test 'each_table';
3185
+$dbi = DBIx::Custom::Next->connect;
3186
+eval { $dbi->execute("drop table $table1") };
3187
+eval { $dbi->execute("drop table $table2") };
3188
+$dbi->execute($create_table2);
3189
+$dbi->execute($create_table1_type);
3190
+
3191
+$infos = [];
3192
+$dbi->each_table(sub {
3193
+    my ($self, $table, $table_info) = @_;
3194
+    
3195
+    if ($table =~ /^table\d/i) {
3196
+         my $info = [$table, $table_info->{TABLE_NAME}];
3197
+         push @$infos, $info;
3198
+    }
3199
+});
3200
+$infos = [sort { $a->[0] cmp $b->[0] || $a->[1] cmp $b->[1] } @$infos];
3201
+is_deeply($infos, 
3202
+    [
3203
+        [$table1, $table1],
3204
+        [$table2, $table2],
3205
+    ]
3206
+);
3207
+
3208
+$dbi = DBIx::Custom::Next->connect;
3209
+eval { $dbi->execute("drop table $table1") };
3210
+eval { $dbi->execute("drop table $table2") };
3211
+$dbi->execute($create_table2);
3212
+$dbi->execute($create_table1_type);
3213
+
3214
+$infos = [];
3215
+$dbi->user_table_info($user_table_info);
3216
+$dbi->each_table(sub {
3217
+    my ($self, $table, $table_info) = @_;
3218
+    
3219
+    if ($table =~ /^table\d/i) {
3220
+         my $info = [$table, $table_info->{TABLE_NAME}];
3221
+         push @$infos, $info;
3222
+    }
3223
+});
3224
+$infos = [sort { $a->[0] cmp $b->[0] || $a->[1] cmp $b->[1] } @$infos];
3225
+is_deeply($infos, 
3226
+    [
3227
+        [$table1, $table1],
3228
+        [$table2, $table2],
3229
+        [$table3, $table3],
3230
+    ]
3231
+);
3232
+
3233
+test 'type_rule into';
3234
+eval { $dbi->execute("drop table $table1") };
3235
+$dbi->execute($create_table1_type);
3236
+$user_column_info = $dbi->get_column_info(exclude_table => $dbi->exclude_table);
3237
+
3238
+
3239
+$dbi = DBIx::Custom::Next->connect;
3240
+eval { $dbi->execute("drop table $table1") };
3241
+$dbi->execute($create_table1_type);
3242
+
3243
+$dbi->user_column_info($user_column_info);
3244
+$dbi->type_rule(
3245
+    into1 => {
3246
+        $date_typename => sub { '2010-' . $_[0] }
3247
+    }
3248
+);
3249
+$dbi->insert({$key1 => '01-01'}, table => $table1);
3250
+$result = $dbi->select(table => $table1);
3251
+like($result->one->{$key1}, qr/^2010-01-01/);
3252
+
3253
+$dbi = DBIx::Custom::Next->connect;
3254
+eval { $dbi->execute("drop table $table1") };
3255
+$dbi->execute($create_table1_type);
3256
+$dbi->user_column_info($user_column_info);
3257
+$dbi->type_rule(
3258
+    into1 => [
3259
+         [$date_typename, $datetime_typename] => sub {
3260
+            my $value = shift;
3261
+            $value =~ s/02/03/g;
3262
+            return $value;
3263
+         }
3264
+    ]
3265
+);
3266
+$dbi->insert({$key1 => '2010-01-02', $key2 => '2010-01-01 01:01:02'}, table => $table1);
3267
+$result = $dbi->select(table => $table1);
3268
+$row = $result->one;
3269
+like($row->{$key1}, qr/^2010-01-03/);
3270
+like($row->{$key2}, qr/^2010-01-01 01:01:03/);
3271
+
3272
+$dbi = DBIx::Custom::Next->connect;
3273
+eval { $dbi->execute("drop table $table1") };
3274
+$dbi->execute($create_table1_type);
3275
+$dbi->insert({$key1 => '2010-01-03', $key2 => '2010-01-01 01:01:03'}, table => $table1);
3276
+$dbi->user_column_info($user_column_info);
3277
+$dbi->type_rule(
3278
+    into1 => [
3279
+        [$date_typename, $datetime_typename] => sub {
3280
+            my $value = shift;
3281
+            $value =~ s/02/03/g;
3282
+            return $value;
3283
+        }
3284
+    ]
3285
+);
3286
+$result = $dbi->execute(
3287
+    "select * from $table1 where $key1 = :$key1 and $key2 = :$table1.$key2",
3288
+    {$key1 => '2010-01-03', "$table1.$key2" => '2010-01-01 01:01:02'}
3289
+);
3290
+$row = $result->one;
3291
+like($row->{$key1}, qr/^2010-01-03/);
3292
+like($row->{$key2}, qr/^2010-01-01 01:01:03/);
3293
+
3294
+$dbi = DBIx::Custom::Next->connect;
3295
+eval { $dbi->execute("drop table $table1") };
3296
+$dbi->execute($create_table1_type);
3297
+$dbi->insert({$key1 => '2010-01-03', $key2 => '2010-01-01 01:01:03'}, table => $table1);
3298
+$dbi->user_column_info($user_column_info);
3299
+$dbi->type_rule(
3300
+    into1 => [
3301
+        [$date_typename, $datetime_typename] => sub {
3302
+            my $value = shift;
3303
+            $value =~ s/02/03/g;
3304
+            return $value;
3305
+        }
3306
+    ]
3307
+);
3308
+$result = $dbi->execute(
3309
+    "select * from $table1 where $key1 = :$key1 and $key2 = :$table1.$key2",
3310
+    {$key1 => '2010-01-02', "$table1.$key2" => '2010-01-01 01:01:02'},
3311
+    table => $table1
3312
+);
3313
+$row = $result->one;
3314
+like($row->{$key1}, qr/^2010-01-03/);
3315
+like($row->{$key2}, qr/2010-01-01 01:01:03/);
3316
+
3317
+$dbi = DBIx::Custom::Next->connect;
3318
+eval { $dbi->execute("drop table $table1") };
3319
+$dbi->execute($create_table1_type);
3320
+$dbi->register_filter(convert => sub {
3321
+    my $value = shift || '';
3322
+    $value =~ s/02/03/;
3323
+    return $value;
3324
+});
3325
+$dbi->user_column_info($user_column_info);
3326
+$dbi->type_rule(
3327
+    from1 => {
3328
+        $date_datatype => 'convert',
3329
+    },
3330
+    into1 => {
3331
+        $date_typename => 'convert',
3332
+    }
3333
+);
3334
+$dbi->insert({$key1 => '2010-02-02'}, table => $table1);
3335
+$result = $dbi->select(table => $table1);
3336
+like($result->fetch->[0], qr/^2010-03-03/);
3337
+$result = $dbi->select(column => [$key1, $key1], table => $table1);
3338
+$row = $result->fetch;
3339
+like($row->[0], qr/^2010-03-03/);
3340
+like($row->[1], qr/^2010-03-03/);
3341
+
3342
+test 'type_rule and filter order';
3343
+$dbi = DBIx::Custom::Next->connect;
3344
+eval { $dbi->execute("drop table $table1") };
3345
+$dbi->execute($create_table1_type);
3346
+$dbi->user_column_info($user_column_info);
3347
+$dbi->type_rule(
3348
+    into1 => {
3349
+        $date_typename => sub { my $v = shift || ''; $v =~ s/4/5/; return $v }
3350
+    },
3351
+    into2 => {
3352
+        $date_typename => sub { my $v = shift || ''; $v =~ s/5/6/; return $v }
3353
+    },
3354
+    from1 => {
3355
+        $date_datatype => sub { my $v = shift || ''; $v =~ s/6/7/; return $v }
3356
+    },
3357
+    from2 => {
3358
+        $date_datatype => sub { my $v = shift || ''; $v =~ s/7/8/; return $v }
3359
+    }
3360
+);
3361
+$dbi->insert({$key1 => '2010-01-03'}, 
3362
+  table => $table1, filter => {$key1 => sub { my $v = shift || ''; $v =~ s/3/4/; return $v }});
3363
+$result = $dbi->select(table => $table1);
3364
+$result->filter($key1 => sub { my $v = shift || ''; $v =~ s/8/9/; return $v });
3365
+like($result->fetch_first->[0], qr/^2010-01-09/);
3366
+
3367
+
3368
+$dbi = DBIx::Custom::Next->connect;
3369
+eval { $dbi->execute("drop table $table1") };
3370
+$dbi->execute($create_table1_type);
3371
+$dbi->user_column_info($user_column_info);
3372
+$dbi->type_rule(
3373
+    from1 => {
3374
+        $date_datatype => sub { my $v = shift || ''; $v =~ s/3/4/; return $v }
3375
+    },
3376
+    from2 => {
3377
+        $date_datatype => sub { my $v = shift || ''; $v =~ s/4/5/; return $v }
3378
+    },
3379
+);
3380
+$dbi->insert({$key1 => '2010-01-03'}, table => $table1);
3381
+$result = $dbi->select(table => $table1);
3382
+$dbi->user_column_info($user_column_info);
3383
+$result->type_rule(
3384
+    from1 => {
3385
+        $date_datatype => sub { my $v = shift || ''; $v =~ s/3/6/; return $v }
3386
+    },
3387
+    from2 => {
3388
+        $date_datatype => sub { my $v = shift || ''; $v =~ s/6/8/; return $v }
3389
+    }
3390
+);
3391
+$result->filter($key1 => sub { my $v = shift || ''; $v =~ s/8/9/; return $v });
3392
+like($result->fetch_first->[0], qr/^2010-01-09/);
3393
+
3394
+test 'type_rule_off';
3395
+$dbi = DBIx::Custom::Next->connect;
3396
+eval { $dbi->execute("drop table $table1") };
3397
+$dbi->execute($create_table1_type);
3398
+$dbi->user_column_info($user_column_info);
3399
+$dbi->type_rule(
3400
+    from1 => {
3401
+        $date_datatype => sub { my $v = shift || ''; $v =~ s/3/5/; return $v }
3402
+    },
3403
+    into1 => {
3404
+        $date_typename => sub { my $v = shift || ''; $v =~ s/3/4/; return $v }
3405
+    }
3406
+);
3407
+$dbi->insert({$key1 => '2010-01-03'}, table => $table1, type_rule_off => 1);
3408
+$result = $dbi->select(table => $table1, type_rule_off => 1);
3409
+like($result->type_rule_off->fetch->[0], qr/^2010-01-03/);
3410
+
3411
+$dbi = DBIx::Custom::Next->connect;
3412
+eval { $dbi->execute("drop table $table1") };
3413
+$dbi->execute($create_table1_type);
3414
+$dbi->user_column_info($user_column_info);
3415
+$dbi->type_rule(
3416
+    from1 => {
3417
+        $date_datatype => sub { my $v = shift || ''; $v =~ s/3/4/; return $v }
3418
+    },
3419
+    into1 => {
3420
+        $date_typename => sub { my $v = shift || ''; $v =~ s/3/5/; return $v }
3421
+    }
3422
+);
3423
+$dbi->insert({$key1 => '2010-01-03'}, table => $table1, type_rule_off => 1);
3424
+$result = $dbi->select(table => $table1, type_rule_off => 1);
3425
+like($result->one->{$key1}, qr/^2010-01-04/);
3426
+
3427
+$dbi = DBIx::Custom::Next->connect;
3428
+eval { $dbi->execute("drop table $table1") };
3429
+$dbi->execute($create_table1_type);
3430
+$dbi->user_column_info($user_column_info);
3431
+$dbi->type_rule(
3432
+    from1 => {
3433
+        $date_datatype => sub { my $v = shift || ''; $v =~ s/4/5/; return $v }
3434
+    },
3435
+    into1 => {
3436
+        $date_typename => sub { my $v = shift || ''; $v =~ s/3/4/; return $v }
3437
+    }
3438
+);
3439
+$dbi->insert({$key1 => '2010-01-03'}, table => $table1);
3440
+$result = $dbi->select(table => $table1);
3441
+like($result->one->{$key1}, qr/^2010-01-05/);
3442
+
3443
+$dbi = DBIx::Custom::Next->connect;
3444
+eval { $dbi->execute("drop table $table1") };
3445
+$dbi->execute($create_table1_type);
3446
+$dbi->user_column_info($user_column_info);
3447
+$dbi->type_rule(
3448
+    from1 => {
3449
+        $date_datatype => sub { my $v = shift || ''; $v =~ s/4/5/; return $v }
3450
+    },
3451
+    into1 => {
3452
+        $date_typename => sub { my $v = shift || ''; $v =~ s/3/4/; return $v }
3453
+    }
3454
+);
3455
+$dbi->insert({$key1 => '2010-01-03'}, table => $table1);
3456
+$result = $dbi->select(table => $table1);
3457
+like($result->fetch->[0], qr/2010-01-05/);
3458
+
3459
+$dbi = DBIx::Custom::Next->connect;
3460
+eval { $dbi->execute("drop table $table1") };
3461
+$dbi->execute($create_table1_type);
3462
+$dbi->register_filter(ppp => sub { my $v = shift || ''; $v =~ s/3/4/; return $v });
3463
+$dbi->user_column_info($user_column_info);
3464
+$dbi->type_rule(
3465
+    into1 => {
3466
+        $date_typename => 'ppp'
3467
+    }
3468
+);
3469
+$dbi->insert({$key1 => '2010-01-03'}, table => $table1);
3470
+$result = $dbi->select(table => $table1);
3471
+like($result->one->{$key1}, qr/^2010-01-04/);
3472
+
3473
+eval{$dbi->type_rule(
3474
+    into1 => {
3475
+        $date_typename => 'pp'
3476
+    }
3477
+)};
3478
+like($@, qr/not registered/);
3479
+
3480
+$dbi = DBIx::Custom::Next->connect;
3481
+eval { $dbi->execute("drop table $table1") };
3482
+$dbi->execute($create_table1_type);
3483
+eval {
3484
+    $dbi->type_rule(
3485
+        from1 => {
3486
+            Date => sub { $_[0] * 2 },
3487
+        }
3488
+    );
3489
+};
3490
+like($@, qr/lower/);
3491
+
3492
+eval {
3493
+    $dbi->type_rule(
3494
+        into1 => {
3495
+            Date => sub { $_[0] * 2 },
3496
+        }
3497
+    );
3498
+};
3499
+like($@, qr/lower/);
3500
+
3501
+$dbi = DBIx::Custom::Next->connect;
3502
+eval { $dbi->execute("drop table $table1") };
3503
+$dbi->execute($create_table1_type);
3504
+$dbi->user_column_info($user_column_info);
3505
+$dbi->type_rule(
3506
+    from1 => {
3507
+        $date_datatype => sub { my $v = shift || ''; $v =~ s/4/5/; return $v }
3508
+    },
3509
+    into1 => {
3510
+        $date_typename => sub { my $v = shift || ''; $v =~ s/3/4/; return $v }
3511
+    }
3512
+);
3513
+$dbi->insert({$key1 => '2010-01-03'}, table => $table1);
3514
+$result = $dbi->select(table => $table1);
3515
+$result->type_rule_off;
3516
+like($result->one->{$key1}, qr/^2010-01-04/);
3517
+
3518
+$dbi = DBIx::Custom::Next->connect;
3519
+eval { $dbi->execute("drop table $table1") };
3520
+$dbi->execute($create_table1_type);
3521
+$dbi->user_column_info($user_column_info);
3522
+$dbi->type_rule(
3523
+    from1 => {
3524
+        $date_datatype => sub { my $v = shift || ''; $v =~ s/3/4/; return $v },
3525
+        $datetime_datatype => sub { my $v = shift || ''; $v =~ s/3/4/; return $v }
3526
+    },
3527
+);
3528
+$dbi->insert({$key1 => '2010-01-03', $key2 => '2010-01-01 01:01:03'}, table => $table1);
3529
+$result = $dbi->select(table => $table1);
3530
+$result->type_rule(
3531
+    from1 => {
3532
+        $date_datatype => sub { my $v = shift || ''; $v =~ s/3/5/; return $v }
3533
+    }
3534
+);
3535
+$row = $result->one;
3536
+like($row->{$key1}, qr/^2010-01-05/);
3537
+like($row->{$key2}, qr/^2010-01-01 01:01:03/);
3538
+
3539
+$result = $dbi->select(table => $table1);
3540
+$result->type_rule(
3541
+    from1 => {
3542
+        $date_datatype => sub { my $v = shift || ''; $v =~ s/3/5/; return $v }
3543
+    }
3544
+);
3545
+$row = $result->one;
3546
+like($row->{$key1}, qr/2010-01-05/);
3547
+like($row->{$key2}, qr/2010-01-01 01:01:03/);
3548
+
3549
+$result = $dbi->select(table => $table1);
3550
+$result->type_rule(
3551
+    from1 => {
3552
+        $date_datatype => sub { my $v = shift || ''; $v =~ s/3/5/; return $v }
3553
+    }
3554
+);
3555
+$row = $result->one;
3556
+like($row->{$key1}, qr/2010-01-05/);
3557
+like($row->{$key2}, qr/2010-01-01 01:01:03/);
3558
+
3559
+$result = $dbi->select(table => $table1);
3560
+$result->type_rule(
3561
+    from1 => [$date_datatype => sub { my $v = shift || ''; $v =~ s/3/5/; return $v }]
3562
+);
3563
+$row = $result->one;
3564
+like($row->{$key1}, qr/2010-01-05/);
3565
+like($row->{$key2}, qr/2010-01-01 01:01:03/);
3566
+
3567
+$dbi->register_filter(five => sub { my $v = shift || ''; $v =~ s/3/5/; return $v });
3568
+$result = $dbi->select(table => $table1);
3569
+$result->type_rule(
3570
+    from1 => [$date_datatype => 'five']
3571
+);
3572
+$row = $result->one;
3573
+like($row->{$key1}, qr/^2010-01-05/);
3574
+like($row->{$key2}, qr/^2010-01-01 01:01:03/);
3575
+
3576
+$result = $dbi->select(table => $table1);
3577
+$result->type_rule(
3578
+    from1 => [$date_datatype => undef]
3579
+);
3580
+$row = $result->one;
3581
+like($row->{$key1}, qr/^2010-01-03/);
3582
+like($row->{$key2}, qr/^2010-01-01 01:01:03/);
3583
+
3584
+$dbi = DBIx::Custom::Next->connect;
3585
+eval { $dbi->execute("drop table $table1") };
3586
+$dbi->execute($create_table1_type);
3587
+$dbi->user_column_info($user_column_info);
3588
+$dbi->type_rule(
3589
+    from1 => {
3590
+        $date_datatype => sub { my $v = shift || ''; $v =~ s/3/4/; return $v },
3591
+    },
3592
+);
3593
+$dbi->insert({$key1 => '2010-01-03'}, table => $table1);
3594
+$result = $dbi->select(table => $table1);
3595
+$result->filter($key1 => sub { my $v = shift || ''; $v =~ s/4/5/; return $v });
3596
+like($result->one->{$key1}, qr/^2010-01-05/);
3597
+
3598
+$dbi = DBIx::Custom::Next->connect;
3599
+eval { $dbi->execute("drop table $table1") };
3600
+$dbi->execute($create_table1_type);
3601
+$dbi->user_column_info($user_column_info);
3602
+$dbi->type_rule(
3603
+    from1 => {
3604
+        $date_datatype => sub { my $v = shift || ''; $v =~ s/3/4/; return $v }
3605
+    },
3606
+);
3607
+$dbi->insert({$key1 => '2010-01-03'}, table => $table1);
3608
+$result = $dbi->select(table => $table1);
3609
+$result->filter($key1 => sub { my $v = shift || ''; $v =~ s/4/5/; return $v });
3610
+like($result->fetch->[0], qr/^2010-01-05/);
3611
+
3612
+$dbi = DBIx::Custom::Next->connect;
3613
+eval { $dbi->execute("drop table $table1") };
3614
+$dbi->execute($create_table1_type);
3615
+$dbi->user_column_info($user_column_info);
3616
+$dbi->type_rule(
3617
+    into1 => {
3618
+        $date_typename => sub { my $v = shift || ''; $v =~ s/3/4/; return $v }
3619
+    },
3620
+    into2 => {
3621
+        $date_typename => sub { my $v = shift || ''; $v =~ s/3/5/; return $v }
3622
+    },
3623
+    from1 => {
3624
+        $date_datatype => sub { my $v = shift || ''; $v =~ s/3/6/; return $v }
3625
+    },
3626
+    from2 => {
3627
+        $date_datatype => sub { my $v = shift || ''; $v =~ s/(3|6)/7/; return $v }
3628
+    }
3629
+);
3630
+$dbi->insert({$key1 => '2010-01-03'}, table => $table1, type_rule_off => 1);
3631
+$result = $dbi->select(table => $table1);
3632
+like($result->type_rule_off->fetch_first->[0], qr/^2010-01-03/);
3633
+$result = $dbi->select(table => $table1);
3634
+like($result->type_rule_on->fetch_first->[0], qr/^2010-01-07/);
3635
+
3636
+$dbi = DBIx::Custom::Next->connect;
3637
+eval { $dbi->execute("drop table $table1") };
3638
+$dbi->execute($create_table1_type);
3639
+$dbi->user_column_info($user_column_info);
3640
+$dbi->type_rule(
3641
+    into1 => {
3642
+        $date_typename => sub { my $v = shift || ''; $v =~ s/3/4/; return $v }
3643
+    },
3644
+    into2 => {
3645
+        $date_typename => sub { my $v = shift || ''; $v =~ s/3/5/; return $v }
3646
+    },
3647
+    from1 => {
3648
+        $date_datatype => sub { my $v = shift || ''; $v =~ s/(3|5)/6/; return $v }
3649
+    },
3650
+    from2 => {
3651
+        $date_datatype => sub { my $v = shift || ''; $v =~ s/6/7/; return $v }
3652
+    }
3653
+);
3654
+$dbi->insert({$key1 => '2010-01-03'}, table => $table1, type_rule1_off => 1);
3655
+$result = $dbi->select(table => $table1);
3656
+like($result->type_rule1_off->fetch_first->[0], qr/^2010-01-05/);
3657
+$result = $dbi->select(table => $table1);
3658
+like($result->type_rule1_on->fetch_first->[0], qr/^2010-01-07/);
3659
+
3660
+$dbi = DBIx::Custom::Next->connect;
3661
+eval { $dbi->execute("drop table $table1") };
3662
+$dbi->execute($create_table1_type);
3663
+$dbi->user_column_info($user_column_info);
3664
+$dbi->type_rule(
3665
+    into1 => {
3666
+        $date_typename => sub { my $v = shift || ''; $v =~ s/3/5/; return $v }
3667
+    },
3668
+    into2 => {
3669
+        $date_typename => sub { my $v = shift || ''; $v =~ s/3/4/; return $v }
3670
+    },
3671
+    from1 => {
3672
+        $date_datatype => sub { my $v = shift || ''; $v =~ s/5/6/; return $v }
3673
+    },
3674
+    from2 => {
3675
+        $date_datatype => sub { my $v = shift || ''; $v =~ s/(3|6)/7/; return $v }
3676
+    }
3677
+);
3678
+$dbi->insert({$key1 => '2010-01-03'}, table => $table1, type_rule2_off => 1);
3679
+$result = $dbi->select(table => $table1);
3680
+like($result->type_rule2_off->fetch_first->[0], qr/^2010-01-06/);
3681
+$result = $dbi->select(table => $table1);
3682
+like($result->type_rule2_on->fetch_first->[0], qr/^2010-01-07/);
3683
+
3684
+test 'join';
3685
+$dbi = DBIx::Custom::Next->connect;
3686
+eval { $dbi->execute("drop table $table1") };
3687
+$dbi->execute($create_table1);
3688
+$dbi->insert({$key1 => 1, $key2 => 2}, table => $table1);
3689
+$dbi->insert({$key1 => 3, $key2 => 4}, table => $table1);
3690
+eval { $dbi->execute("drop table $table2") };
3691
+$dbi->execute($create_table2);
3692
+$dbi->insert({$key1 => 1, $key3 => 5}, table => $table2);
3693
+eval { $dbi->execute("drop table $table3") };
3694
+$dbi->execute("create table $table3 ($key3 int, $key4 int)");
3695
+$dbi->insert({$key3 => 5, $key4 => 4}, table => $table3);
3696
+$rows = $dbi->select(
3697
+    table => $table1,
3698
+    column => "$table1.$key1 as ${table1}_$key1, $table2.$key1 as ${table2}_$key1, $key2, $key3",
3699
+    where   => {"$table1.$key2" => 2},
3700
+    join  => ["left outer join $table2 on $table1.$key1 = $table2.$key1"]
3701
+)->all;
3702
+is_deeply($rows, [{"${table1}_$key1" => 1, "${table2}_$key1" => 1, $key2 => 2, $key3 => 5}]);
3703
+
3704
+$dbi = DBIx::Custom::Next->connect;
3705
+eval { $dbi->execute("drop table $table1") };
3706
+$dbi->execute($create_table1);
3707
+$dbi->insert({$key1 => 1, $key2 => 2}, table => $table1);
3708
+$dbi->insert({$key1 => 3, $key2 => 4}, table => $table1);
3709
+eval { $dbi->execute("drop table $table2") };
3710
+$dbi->execute($create_table2);
3711
+$dbi->insert({$key1 => 1, $key3 => 5}, table => $table2);
3712
+eval { $dbi->execute("drop table $table3") };
3713
+$dbi->execute("create table $table3 ($key3 int, $key4 int)");
3714
+$dbi->insert({$key3 => 5, $key4 => 4}, table => $table3);
3715
+$rows = $dbi->select(
3716
+    table => $table1,
3717
+    column => "$table1.$key1 as ${table1}_$key1, $table2.$key1 as ${table2}_$key1, $key2, $key3",
3718
+    where   => {"$table1.$key2" => 2},
3719
+    join  => {
3720
+        clause => "left outer join $table2 on $table1.$key1 = $table2.$key1",
3721
+        table => [$table1, $table2]
3722
+    }
3723
+)->all;
3724
+is_deeply($rows, [{"${table1}_$key1" => 1, "${table2}_$key1" => 1, $key2 => 2, $key3 => 5}]);
3725
+
3726
+$rows = $dbi->select(
3727
+    table => $table1,
3728
+    where   => {$key1 => 1},
3729
+    join  => ["left outer join $table2 on $table1.$key1 = $table2.$key1"]
3730
+)->all;
3731
+is_deeply($rows, [{$key1 => 1, $key2 => 2}]);
3732
+
3733
+$rows = $dbi->select(
3734
+    table => $table1,
3735
+    where   => {$key1 => 1},
3736
+    join  => ["left outer join $table2 on $table1.$key1 = $table2.$key1",
3737
+              "left outer join $table3 on $table2.$key3 = $table3.$key3"]
3738
+)->all;
3739
+is_deeply($rows, [{$key1 => 1, $key2 => 2}]);
3740
+
3741
+$rows = $dbi->select(
3742
+    column => "$table3.$key4 as ${table3}__$key4",
3743
+    table => $table1,
3744
+    where   => {"$table1.$key1" => 1},
3745
+    join  => ["left outer join $table2 on $table1.$key1 = $table2.$key1",
3746
+              "left outer join $table3 on $table2.$key3 = $table3.$key3"]
3747
+)->all;
3748
+is_deeply($rows, [{"${table3}__$key4" => 4}]);
3749
+
3750
+$rows = $dbi->select(
3751
+    column => "$table1.$key1 as ${table1}__$key1",
3752
+    table => $table1,
3753
+    where   => {"$table3.$key4" => 4},
3754
+    join  => ["left outer join $table2 on $table1.$key1 = $table2.$key1",
3755
+              "left outer join $table3 on $table2.$key3 = $table3.$key3"]
3756
+)->all;
3757
+is_deeply($rows, [{"${table1}__$key1" => 1}]);
3758
+
3759
+$dbi = DBIx::Custom::Next->connect;
3760
+eval { $dbi->execute("drop table $table1") };
3761
+$dbi->execute($create_table1);
3762
+$dbi->insert({$key1 => 1, $key2 => 2}, table => $table1);
3763
+eval { $dbi->execute("drop table $table2") };
3764
+$dbi->execute($create_table2);
3765
+$dbi->insert({$key1 => 1, $key3 => 5}, table => $table2);
3766
+$rows = $dbi->select(
3767
+    table => $table1,
3768
+    column => "${q}$table1$p.${q}$key1$p as ${q}${table1}_$key1$p, ${q}$table2$p.${q}$key1$p as ${q}${table2}_$key1$p, ${q}$key2$p, ${q}$key3$p",
3769
+    where   => {"$table1.$key2" => 2},
3770
+    join  => ["left outer join ${q}$table2$p on ${q}$table1$p.${q}$key1$p = ${q}$table2$p.${q}$key1$p"],
3771
+)->all;
3772
+is_deeply($rows, [{"${table1}_$key1" => 1, "${table2}_$key1" => 1, $key2 => 2, $key3 => 5}],
3773
+          'quote');
3774
+
3775
+
3776
+$dbi = DBIx::Custom::Next->connect;
3777
+eval { $dbi->execute("drop table $table1") };
3778
+$dbi->execute($create_table1);
3779
+$dbi->insert({$key1 => 1, $key2 => 2}, table => $table1);
3780
+$sql = <<"EOS";
3781
+left outer join (
3782
+  select * from $table1 t1
3783
+  where t1.$key2 = (
3784
+    select max(t2.$key2) from $table1 t2
3785
+    where t1.$key1 = t2.$key1
3786
+  )
3787
+) $table3 on $table1.$key1 = $table3.$key1
3788
+EOS
3789
+$join = [$sql];
3790
+$rows = $dbi->select(
3791
+    table => $table1,
3792
+    column => "$table3.$key1 as ${table3}__$key1",
3793
+    join  => $join
3794
+)->all;
3795
+is_deeply($rows, [{"${table3}__$key1" => 1}]);
3796
+
3797
+$dbi = DBIx::Custom::Next->connect;
3798
+eval { $dbi->execute("drop table $table1") };
3799
+eval { $dbi->execute("drop table $table2") };
3800
+$dbi->execute($create_table1);
3801
+$dbi->execute($create_table2);
3802
+$dbi->insert({$key1 => 1, $key2 => 2}, table => $table1);
3803
+$dbi->insert({$key1 => 1, $key3 => 4}, table => $table2);
3804
+$dbi->insert({$key1 => 1, $key3 => 5}, table => $table2);
3805
+$result = $dbi->select(
3806
+    table => $table1,
3807
+    join => [
3808
+        "left outer join $table2 on $table2.$key2 = '4' and $table1.$key1 = $table2.$key1"
3809
+    ]
3810
+);
3811
+is_deeply($result->all, [{$key1 => 1, $key2 => 2}]);
3812
+$result = $dbi->select(
3813
+    table => $table1,
3814
+    column => [{$table2 => [$key3]}],
3815
+    join => [
3816
+        "left outer join $table2 on $table2.$key3 = '4' and $table1.$key1 = $table2.$key1"
3817
+    ]
3818
+);
3819
+is_deeply($result->all, [{"$table2.$key3" => 4}]);
3820
+$result = $dbi->select(
3821
+    table => $table1,
3822
+    column => [{$table2 => [$key3]}],
3823
+    join => [
3824
+        "left outer join $table2 on $table1.$key1 = $table2.$key1 and $table2.$key3 = '4'"
3825
+    ]
3826
+);
3827
+is_deeply($result->all, [{"$table2.$key3" => 4}]);
3828
+
3829
+$dbi = DBIx::Custom::Next->connect;
3830
+eval { $dbi->execute("drop table $table1") };
3831
+eval { $dbi->execute("drop table $table2") };
3832
+$dbi->execute($create_table1);
3833
+$dbi->execute($create_table2);
3834
+$dbi->insert({$key1 => 1, $key2 => 2}, table => $table1);
3835
+$dbi->insert({$key1 => 1, $key3 => 4}, table => $table2);
3836
+$dbi->insert({$key1 => 1, $key3 => 5}, table => $table2);
3837
+$result = $dbi->select(
3838
+    table => $table1,
3839
+    column => [{$table2 => [$key3]}],
3840
+    join => [
3841
+        {
3842
+            clause => "left outer join $table2 on $table2.$key3 = '4' and $table1.$key1 = $table2.$key1",
3843
+            table => [$table1, $table2]
3844
+        }
3845
+    ]
3846
+);
3847
+is_deeply($result->all, [{"$table2.$key3" => 4}]);
3848
+
3849
+$dbi = DBIx::Custom::Next->connect;
3850
+eval { $dbi->execute("drop table $table1") };
3851
+eval { $dbi->execute("drop table $table2") };
3852
+$dbi->execute($create_table1);
3853
+$dbi->execute($create_table2);
3854
+$dbi->insert({$key1 => 1, $key2 => 2}, table => $table1);
3855
+$dbi->insert({$key1 => 1, $key3 => 4}, table => $table2);
3856
+$dbi->insert({$key1 => 1, $key3 => 1}, table => $table2);
3857
+$result = $dbi->select(
3858
+    table => $table1,
3859
+    column => [{$table2 => [$key3]}],
3860
+    join => [
3861
+        "left outer join $table2 on $table1.$key1 = $table2.$key1 and $table2.$key3 > '3'"
3862
+    ]
3863
+);
3864
+is_deeply($result->all, [{"$table2.$key3" => 4}]);
3865
+
3866
+$dbi = DBIx::Custom::Next->connect;
3867
+eval { $dbi->execute("drop table $table1") };
3868
+eval { $dbi->execute("drop table $table2") };
3869
+$dbi->execute($create_table1);
3870
+$dbi->execute($create_table2);
3871
+$dbi->insert({$key1 => 1, $key2 => 2}, table => $table1);
3872
+$dbi->insert({$key1 => 1, $key3 => 4}, table => $table2);
3873
+$dbi->insert({$key1 => 1, $key3 => 1}, table => $table2);
3874
+$result = $dbi->select(
3875
+    table => $table1,
3876
+    column => [{$table2 => [$key3]}],
3877
+    join => [
3878
+        "left outer join $table2 on $table2.$key3 > '3' and $table1.$key1 = $table2.$key1"
3879
+    ]
3880
+);
3881
+is_deeply($result->all, [{"$table2.$key3" => 4}]);
3882
+
3883
+test 'columns';
3884
+$dbi = MyDBI1->connect;
3885
+$model = $dbi->model($table1);
3886
+
3887
+test 'count';
3888
+$dbi = DBIx::Custom::Next->connect;
3889
+eval { $dbi->execute("drop table $table1") };
3890
+$dbi->execute($create_table1);
3891
+$dbi->insert({$key1 => 1, $key2 => 2}, table => $table1);
3892
+$dbi->insert({$key1 => 1, $key2 => 3}, table => $table1);
3893
+is($dbi->count(table => $table1), 2);
3894
+is($dbi->count(table => $table1, where => {$key2 => 2}), 1);
3895
+$model = $dbi->create_model(table => $table1);
3896
+is($model->count, 2);
3897
+
3898
+1;
+19
t/next/common/MyDBI1.pm
... ...
@@ -0,0 +1,19 @@
1
+package MyDBI1;
2
+
3
+use strict;
4
+use warnings;
5
+
6
+use base 'DBIx::Custom::Next';
7
+
8
+sub connect {
9
+    my $self = shift->SUPER::connect(@_);
10
+    
11
+    $self->include_model(
12
+        MyModel1 => [
13
+            $self->table1,
14
+            $self->table2
15
+        ]
16
+    );
17
+}
18
+
19
+1;
+13
t/next/common/MyModel1/table1.pm
... ...
@@ -0,0 +1,13 @@
1
+package MyModel1::table1;
2
+
3
+use DBIx::Custom::Next::Model -base;
4
+
5
+sub insert {
6
+    my ($self, $param) = @_;
7
+    
8
+    return $self->SUPER::insert($param);
9
+}
10
+
11
+sub list { shift->select; }
12
+
13
+1;
+17
t/next/common/MyModel1/table2.pm
... ...
@@ -0,0 +1,17 @@
1
+package MyModel1::table2;
2
+
3
+use strict;
4
+use warnings;
5
+
6
+use base 'DBIx::Custom::Next::Model';
7
+
8
+
9
+sub insert {
10
+    my ($self, $param) = @_;
11
+    
12
+    return $self->SUPER::insert($param);
13
+}
14
+
15
+sub list { shift->select; }
16
+
17
+1;
+5
t/next/common/MyModel4.pm
... ...
@@ -0,0 +1,5 @@
1
+package MyModel4;
2
+
3
+use base 'DBIx::Custom::Next::Model';
4
+
5
+1;
+9
t/next/common/MyModel4/table1.pm
... ...
@@ -0,0 +1,9 @@
1
+package MyModel4::table1;
2
+
3
+use MyModel4 -base;
4
+
5
+has table => 'table1';
6
+
7
+sub list { shift->select }
8
+
9
+1;
+8
t/next/common/MyModel4/table2.pm
... ...
@@ -0,0 +1,8 @@
1
+package MyModel4::table2;
2
+
3
+use base 'MyModel4';
4
+
5
+sub insert { shift->SUPER::insert($_[0]) }
6
+sub list { shift->select }
7
+
8
+1;
+5
t/next/common/MyModel5.pm
... ...
@@ -0,0 +1,5 @@
1
+package MyModel5;
2
+
3
+use base 'DBIx::Custom::Next::Model';
4
+
5
+1;
+7
t/next/common/MyModel5/table1.pm
... ...
@@ -0,0 +1,7 @@
1
+package MyModel5::table1;
2
+
3
+use MyModel5 -base;
4
+
5
+has primary_key => sub { ['key1', 'key2'] };
6
+
7
+1;
+12
t/next/common/MyModel5/table2.pm
... ...
@@ -0,0 +1,12 @@
1
+package MyModel5::table2;
2
+
3
+use strict;
4
+use warnings;
5
+
6
+use base 'MyModel5';
7
+
8
+__PACKAGE__->attr(table => 'table2');
9
+
10
+__PACKAGE__->attr('primary_key' => sub { ['key1', 'key2'] });
11
+
12
+1;
+12
t/next/common/MyModel5/table3.pm
... ...
@@ -0,0 +1,12 @@
1
+package MyModel5::table3;
2
+
3
+use strict;
4
+use warnings;
5
+
6
+use base 'MyModel5';
7
+
8
+__PACKAGE__->attr(table => 'table3');
9
+
10
+__PACKAGE__->attr('primary_key' => sub { ['key1', 'key2'] });
11
+
12
+1;
+5
t/next/common/MyModel6.pm
... ...
@@ -0,0 +1,5 @@
1
+package MyModel6;
2
+
3
+use base 'DBIx::Custom::Next::Model';
4
+
5
+1;
+14
t/next/common/MyModel6/table1.pm
... ...
@@ -0,0 +1,14 @@
1
+package MyModel6::table1;
2
+
3
+use base 'MyModel6';
4
+
5
+__PACKAGE__->attr(
6
+    join => sub {
7
+        [
8
+            'left outer join table2 on table1.key1 = table2.key1'
9
+        ]
10
+    },
11
+    primary_key => sub { ['key1'] }
12
+);
13
+
14
+1;
+5
t/next/common/MyModel6/table2.pm
... ...
@@ -0,0 +1,5 @@
1
+package MyModel6::table2;
2
+
3
+use base 'MyModel6';
4
+
5
+1;
+11
t/next/common/MyModel6/table3.pm
... ...
@@ -0,0 +1,11 @@
1
+package MyModel6::table3;
2
+
3
+use base 'MyModel6';
4
+
5
+__PACKAGE__->attr(filter => sub {
6
+    [
7
+        key1 => {in => sub { uc $_[0] }}
8
+    ]
9
+});
10
+
11
+1;
+5
t/next/common/MyModel7.pm
... ...
@@ -0,0 +1,5 @@
1
+package MyModel7;
2
+
3
+use base 'DBIx::Custom::Next::Model';
4
+
5
+1;
+14
t/next/common/MyModel7/table1.pm
... ...
@@ -0,0 +1,14 @@
1
+package MyModel7::table1;
2
+
3
+use base 'MyModel7';
4
+
5
+__PACKAGE__->attr(
6
+    primary_key => sub { ['key1'] },
7
+    join => sub {
8
+        [
9
+            'left outer join table2 on table1.key1 = table2.key1'
10
+        ]
11
+    },
12
+);
13
+
14
+1;
+5
t/next/common/MyModel7/table2.pm
... ...
@@ -0,0 +1,5 @@
1
+package MyModel7::table2;
2
+
3
+use base 'MyModel7';
4
+
5
+1;
+4
t/next/common/MyModel8.pm
... ...
@@ -0,0 +1,4 @@
1
+package MyModel8;
2
+use DBIx::Custom::Next::Model -base;
3
+
4
+1;
+7
t/next/common/MyModel8/table1.pm
... ...
@@ -0,0 +1,7 @@
1
+package MyModel8::table1;
2
+use MyModel8 -base;
3
+
4
+has join => sub { ['left join table2 table2_alias on table1.key1 = table2_alias.key1'] };
5
+
6
+
7
+1;
+10
t/next/common/MyModel8/table2.pm
... ...
@@ -0,0 +1,10 @@
1
+package MyModel8::table2;
2
+use MyModel8 -base;
3
+
4
+has filter => sub {
5
+    {
6
+        key3 => {out => sub { $_[0] * 2}, in => sub { $_[0] * 3}, end => sub { $_[0] * 4 }}
7
+    }
8
+};
9
+
10
+1;
+19
t/next/common_uc/MyDBI1.pm
... ...
@@ -0,0 +1,19 @@
1
+package MyDBI1;
2
+
3
+use strict;
4
+use warnings;
5
+
6
+use base 'DBIx::Custom::Next';
7
+
8
+sub connect {
9
+    my $self = shift->SUPER::connect(@_);
10
+    
11
+    $self->include_model(
12
+        MyModel1 => [
13
+            $self->table1,
14
+            $self->table2
15
+        ]
16
+    );
17
+}
18
+
19
+1;
+13
t/next/common_uc/MyModel1/TABLE1.pm
... ...
@@ -0,0 +1,13 @@
1
+package MyModel1::TABLE1;
2
+
3
+use DBIx::Custom::Next::Model -base;
4
+
5
+sub insert {
6
+    my ($self, $param) = @_;
7
+    
8
+    return $self->SUPER::insert($param);
9
+}
10
+
11
+sub list { shift->select; }
12
+
13
+1;
+17
t/next/common_uc/MyModel1/TABLE2.pm
... ...
@@ -0,0 +1,17 @@
1
+package MyModel1::TABLE2;
2
+
3
+use strict;
4
+use warnings;
5
+
6
+use base 'DBIx::Custom::Next::Model';
7
+
8
+
9
+sub insert {
10
+    my ($self, $param) = @_;
11
+    
12
+    return $self->SUPER::insert($param);
13
+}
14
+
15
+sub list { shift->select; }
16
+
17
+1;
+5
t/next/common_uc/MyModel4.pm
... ...
@@ -0,0 +1,5 @@
1
+package MyModel4;
2
+
3
+use base 'DBIx::Custom::Next::Model';
4
+
5
+1;
+9
t/next/common_uc/MyModel4/TABLE1.pm
... ...
@@ -0,0 +1,9 @@
1
+package MyModel4::TABLE1;
2
+
3
+use MyModel4 -base;
4
+
5
+has table => 'TABLE1';
6
+
7
+sub list { shift->select }
8
+
9
+1;
+8
t/next/common_uc/MyModel4/TABLE2.pm
... ...
@@ -0,0 +1,8 @@
1
+package MyModel4::TABLE2;
2
+
3
+use base 'MyModel4';
4
+
5
+sub insert { shift->SUPER::insert($_[0]) }
6
+sub list { shift->select }
7
+
8
+1;
+5
t/next/common_uc/MyModel5.pm
... ...
@@ -0,0 +1,5 @@
1
+package MyModel5;
2
+
3
+use base 'DBIx::Custom::Next::Model';
4
+
5
+1;
+7
t/next/common_uc/MyModel5/TABLE1.pm
... ...
@@ -0,0 +1,7 @@
1
+package MyModel5::TABLE1;
2
+
3
+use MyModel5 -base;
4
+
5
+has primary_key => sub { ['KEY1', 'KEY2'] };
6
+
7
+1;
+12
t/next/common_uc/MyModel5/TABLE2.pm
... ...
@@ -0,0 +1,12 @@
1
+package MyModel5::TABLE2;
2
+
3
+use strict;
4
+use warnings;
5
+
6
+use base 'MyModel5';
7
+
8
+__PACKAGE__->attr(table => 'TABLE2');
9
+
10
+__PACKAGE__->attr('primary_key' => sub { ['KEY1', 'KEY2'] });
11
+
12
+1;
+12
t/next/common_uc/MyModel5/TABLE3.pm
... ...
@@ -0,0 +1,12 @@
1
+package MyModel5::TABLE3;
2
+
3
+use strict;
4
+use warnings;
5
+
6
+use base 'MyModel5';
7
+
8
+__PACKAGE__->attr(table => 'TABLE3');
9
+
10
+__PACKAGE__->attr('primary_key' => sub { ['KEY1', 'KEY2'] });
11
+
12
+1;
+5
t/next/common_uc/MyModel6.pm
... ...
@@ -0,0 +1,5 @@
1
+package MyModel6;
2
+
3
+use base 'DBIx::Custom::Next::Model';
4
+
5
+1;
+14
t/next/common_uc/MyModel6/TABLE1.pm
... ...
@@ -0,0 +1,14 @@
1
+package MyModel6::TABLE1;
2
+
3
+use base 'MyModel6';
4
+
5
+__PACKAGE__->attr(
6
+    join => sub {
7
+        [
8
+            'left outer join TABLE2 on TABLE1.KEY1 = TABLE2.KEY1'
9
+        ]
10
+    },
11
+    primary_key => sub { ['KEY1'] }
12
+);
13
+
14
+1;
+5
t/next/common_uc/MyModel6/TABLE2.pm
... ...
@@ -0,0 +1,5 @@
1
+package MyModel6::TABLE2;
2
+
3
+use base 'MyModel6';
4
+
5
+1;
+11
t/next/common_uc/MyModel6/TABLE3.pm
... ...
@@ -0,0 +1,11 @@
1
+package MyModel6::TABLE3;
2
+
3
+use base 'MyModel6';
4
+
5
+__PACKAGE__->attr(filter => sub {
6
+    [
7
+        KEY1 => {in => sub { uc $_[0] }}
8
+    ]
9
+});
10
+
11
+1;
+5
t/next/common_uc/MyModel7.pm
... ...
@@ -0,0 +1,5 @@
1
+package MyModel7;
2
+
3
+use base 'DBIx::Custom::Next::Model';
4
+
5
+1;
+14
t/next/common_uc/MyModel7/TABLE1.pm
... ...
@@ -0,0 +1,14 @@
1
+package MyModel7::TABLE1;
2
+
3
+use base 'MyModel7';
4
+
5
+__PACKAGE__->attr(
6
+    primary_key => sub { ['KEY1'] },
7
+    join => sub {
8
+        [
9
+            'left outer join TABLE2 on TABLE1.KEY1 = TABLE2.KEY1'
10
+        ]
11
+    },
12
+);
13
+
14
+1;
+5
t/next/common_uc/MyModel7/TABLE2.pm
... ...
@@ -0,0 +1,5 @@
1
+package MyModel7::TABLE2;
2
+
3
+use base 'MyModel7';
4
+
5
+1;
+4
t/next/common_uc/MyModel8.pm
... ...
@@ -0,0 +1,4 @@
1
+package MyModel8;
2
+use DBIx::Custom::Next::Model -base;
3
+
4
+1;
+7
t/next/common_uc/MyModel8/TABLE1.pm
... ...
@@ -0,0 +1,7 @@
1
+package MyModel8::TABLE1;
2
+use MyModel8 -base;
3
+
4
+has join => sub { ['left join TABLE2 TABLE2_ALIAS on TABLE1.KEY1 = TABLE2_ALIAS.KEY1'] };
5
+
6
+
7
+1;
+10
t/next/common_uc/MyModel8/TABLE2.pm
... ...
@@ -0,0 +1,10 @@
1
+package MyModel8::TABLE2;
2
+use MyModel8 -base;
3
+
4
+has filter => sub {
5
+    {
6
+        KEY3 => {out => sub { $_[0] * 2}, in => sub { $_[0] * 3}, end => sub { $_[0] * 4 }}
7
+    }
8
+};
9
+
10
+1;
+48
t/next/create_uppercase_module.pl
... ...
@@ -0,0 +1,48 @@
1
+use strict;
2
+use warnings;
3
+
4
+use FindBin;
5
+use File::Basename qw/basename fileparse/;
6
+use File::Copy 'copy';
7
+
8
+my $top = $FindBin::Bin;
9
+my $common = "$top/common";
10
+my $common_uc = "$top/common_uc";
11
+mkdir $common_uc unless -d $common_uc;
12
+
13
+my @modules = grep { -f $_ } glob("$common/*");
14
+for my $module (@modules) {
15
+    my $module_base = basename $module;
16
+    copy $module, "$common_uc/$module_base"
17
+      or die "Can't move module file: $!";
18
+}
19
+
20
+my @dirs = grep { -d $_ } glob("$FindBin::Bin/common/*");
21
+for my $dir (@dirs) {
22
+    my $base_dir = basename $dir;
23
+    my $model_dir_uc = "$common_uc/$base_dir";
24
+    mkdir $model_dir_uc unless -d $model_dir_uc;
25
+    
26
+    my @files = grep { /table\d\.pm/ } glob("$dir/*");
27
+    for my $file (@files) {
28
+    
29
+      my $content = do {
30
+        open my $fh, '<', $file;
31
+        local $/;
32
+        <$fh>;
33
+      };
34
+      
35
+      $content =~ s/table(\d)/TABLE$1/g;
36
+      $content =~ s/TABLE2_alias/TABLE2_ALIAS/g;
37
+      $content =~ s/key(\d)/KEY$1/g;
38
+      
39
+      my $base_name = (fileparse($file, qr/\..+$/))[0];
40
+      $base_name = uc $base_name;
41
+      my $new_file = "$common_uc/$base_dir/$base_name.pm";
42
+      
43
+      open my $fh, '>', $new_file
44
+        or die "Can't write file: $!";
45
+      
46
+      print $fh $content;
47
+    }
48
+}
+225
t/next/mysql.t
... ...
@@ -0,0 +1,225 @@
1
+use Test::More;
2
+use strict;
3
+use warnings;
4
+use utf8;
5
+
6
+use FindBin;
7
+use DBIx::Custom::Next;
8
+
9
+my $dbi;
10
+my $dsn;
11
+my $args;
12
+my $user = 'dbix_custom';
13
+my $password = 'dbix_custom';
14
+my $database = 'dbix_custom';
15
+
16
+$dsn = "dbi:mysql:database=$database";
17
+$args = {dsn => $dsn, user => $user, password => $password,};
18
+
19
+plan skip_all => 'mysql private test' unless -f "$FindBin::Bin/run/mysql2.run"
20
+  && eval { $dbi = DBIx::Custom::Next->connect($args); 1 };
21
+plan 'no_plan';
22
+
23
+$SIG{__WARN__} = sub { warn $_[0] unless $_[0] =~ /DEPRECATED/};
24
+
25
+require DBIx::Connector;
26
+
27
+# Function for test name
28
+sub test { print "# $_[0]\n" }
29
+
30
+# Varialbes for tests
31
+my $dbname;
32
+my $row;
33
+my $rows;
34
+my $result;
35
+my $model;
36
+
37
+test 'connect';
38
+eval {
39
+    $dbi = DBIx::Custom::Next->connect(
40
+        dsn => "dbi:mysql:database=$database;host=localhost;port=10000",
41
+        user => $user,
42
+        password => $password
43
+    );
44
+};
45
+ok(!$@);
46
+
47
+eval { $dbi->do('drop table table1') };
48
+$dbi->do('create table table1 (key1 varchar(255), key2 varchar(255)) engine=InnoDB');
49
+
50
+test 'update_or_insert';
51
+$dbi->delete_all(table => 'table1');
52
+$dbi->update_or_insert(
53
+    {key2 => 2},
54
+    table => 'table1',
55
+    id => 1,
56
+    primary_key => 'key1',
57
+    option => {
58
+        select => {append => 'for update'},
59
+        insert => {append => '    #'},
60
+        update => {append => '     #'}
61
+    }
62
+);
63
+
64
+$row = $dbi->select(id => 1, table => 'table1', primary_key => 'key1')->one;
65
+is_deeply($row, {key1 => 1, key2 => 2}, "basic");
66
+
67
+$dbi->update_or_insert(
68
+    {key2 => 3},
69
+    table => 'table1',
70
+    id => 1,
71
+    primary_key => 'key1',
72
+    option => {
73
+        select => {append => 'for update'},
74
+        insert => {append => '    #'},
75
+        update => {append => '     #'}
76
+    }
77
+);
78
+
79
+$row = $dbi->select(id => 1, table => 'table1', primary_key => 'key1')->one;
80
+is_deeply($row, {key1 => 1, key2 => 3}, "basic");
81
+
82
+$dbi->delete_all(table => 'table1');
83
+$model = $dbi->create_model(
84
+    table => 'table1',
85
+    primary_key => 'key1',
86
+);
87
+$model->update_or_insert(
88
+    {key2 => 2},
89
+    id => 1,
90
+    option => {
91
+        select => {append => 'for update'},
92
+        insert => {append => '    #'},
93
+        update => {append => '     #'}
94
+    }
95
+);
96
+$row = $dbi->select(id => 1, table => 'table1', primary_key => 'key1')->one;
97
+is_deeply($row, {key1 => 1, key2 => 2}, "basic");
98
+$model->update_or_insert(
99
+    {key2 => 3},
100
+    id => 1,
101
+    option => {
102
+        select => {append => 'for update'},
103
+        insert => {append => '    #'},
104
+        update => {append => '     #'}
105
+    }
106
+);
107
+$row = $dbi->select(id => 1, table => 'table1', primary_key => 'key1')->one;
108
+is_deeply($row, {key1 => 1, key2 => 3}, "basic");
109
+
110
+# Test memory leaks
111
+for (1 .. 300) {
112
+    $dbi = DBIx::Custom::Next->connect(
113
+        dsn => "dbi:mysql:database=$database;host=localhost;port=10000",
114
+        user => $user,
115
+        password => $password
116
+    );
117
+    $dbi->create_model(table => 'table1');
118
+    $dbi->create_model(table => 'table2');
119
+}
120
+
121
+test 'dbh';
122
+{
123
+    my $connector = DBIx::Connector->new(
124
+        "dbi:mysql:database=$database",
125
+        $user,
126
+        $password,
127
+        DBIx::Custom::Next->new->default_option
128
+    );
129
+
130
+    my $dbi = DBIx::Custom::Next->connect(connector => $connector);
131
+    $dbi->delete_all(table => 'table1');
132
+    $dbi->do('insert into table1 (key1, key2) values (1, 2)');
133
+    is($dbi->select(table => 'table1')->fetch_hash_first->{key1}, 1);
134
+    
135
+    $dbi = DBIx::Custom::Next->new;
136
+    $dbi->dbh('a');
137
+    is($dbi->{dbh}, 'a');
138
+}
139
+
140
+test 'transaction';
141
+test 'dbh';
142
+{
143
+    my $connector = DBIx::Connector->new(
144
+        "dbi:mysql:database=$database",
145
+        $user,
146
+        $password,
147
+        DBIx::Custom::Next->new->default_option
148
+    );
149
+
150
+    my $dbi = DBIx::Custom::Next->connect(connector => $connector);
151
+    $dbi->delete_all(table => 'table1');
152
+    
153
+    $dbi->connector->txn(sub {
154
+        $dbi->insert({key1 => 1, key2 => 2}, table => 'table1');
155
+        $dbi->insert({key1 => 3, key2 => 4}, table => 'table1');
156
+    });
157
+    is_deeply($dbi->select(table => 'table1')->fetch_hash_all,
158
+              [{key1 => 1, key2 => 2}, {key1 => 3, key2 => 4}]);
159
+
160
+    $dbi->delete_all(table => 'table1');
161
+    eval {
162
+        $dbi->connector->txn(sub {
163
+            $dbi->insert({key1 => 1, key2 => 2}, table => 'table1');
164
+            die "Error";
165
+            $dbi->insert({key1 => 3, key2 => 4}, table => 'table1');
166
+        });
167
+    };
168
+    is_deeply($dbi->select(table => 'table1')->fetch_hash_all,
169
+              []);
170
+}
171
+
172
+use DBIx::Custom::Next;
173
+use Scalar::Util 'blessed';
174
+{
175
+    my $dbi = DBIx::Custom::Next->connect(
176
+        user => $user,
177
+        password => $password,
178
+        dsn => "dbi:mysql:dbname=$database"
179
+    );
180
+    $dbi->connect;
181
+    
182
+    ok(blessed $dbi->dbh);
183
+    can_ok($dbi->dbh, qw/prepare/);
184
+    ok($dbi->dbh->{AutoCommit});
185
+    ok(!$dbi->dbh->{mysql_enable_utf8});
186
+}
187
+
188
+{
189
+    my $dbi = DBIx::Custom::Next->connect(
190
+        user => $user,
191
+        password => $password,
192
+        dsn => "dbi:mysql:dbname=$database",
193
+        option => {AutoCommit => 0, mysql_enable_utf8 => 1}
194
+    );
195
+    $dbi->connect;
196
+    ok(!$dbi->dbh->{AutoCommit});
197
+    #ok($dbi->dbh->{mysql_enable_utf8});
198
+}
199
+
200
+test 'fork';
201
+{
202
+    my $connector = DBIx::Connector->new(
203
+        "dbi:mysql:database=$database",
204
+        $user,
205
+        $password,
206
+        DBIx::Custom::Next->new->default_option
207
+    );
208
+    
209
+    my $dbi = DBIx::Custom::Next->new(connector => $connector);
210
+    $dbi->delete_all(table => 'table1');
211
+    $dbi->insert({key1 => 1, key2 => 2}, table => 'table1');
212
+    die "Can't fork" unless defined (my $pid = fork);
213
+
214
+    if ($pid) {
215
+        # Parent
216
+        my $result = $dbi->select(table => 'table1');
217
+        is_deeply($result->fetch_hash_first, {key1 => 1, key2 => 2});
218
+    }
219
+    else {
220
+        # Child
221
+        my $result = $dbi->select(table => 'table1');
222
+        die "Not OK" unless $result->fetch_hash_first->{key1} == 1;
223
+    }
224
+}
225
+
+65
t/next/mysql2.t
... ...
@@ -0,0 +1,65 @@
1
+use Test::More;
2
+use strict;
3
+use warnings;
4
+use utf8;
5
+
6
+use FindBin;
7
+use DBIx::Custom::Next;
8
+
9
+my $dbi;
10
+my $dsn;
11
+my $args;
12
+my $user = 'dbix_custom';
13
+my $password = 'dbix_custom';
14
+my $database = 'dbix_custom';
15
+
16
+$dsn = "dbi:mysql:database=$database";
17
+$args = {dsn => $dsn, user => $user, password => $password,};
18
+
19
+plan skip_all => 'mysql private test' unless -f "$FindBin::Bin/run/mysql2.run"
20
+  && eval { $dbi = DBIx::Custom::Next->connect($args); 1 };
21
+plan 'no_plan';
22
+
23
+$SIG{__WARN__} = sub { warn $_[0] unless $_[0] =~ /DEPRECATED/};
24
+
25
+
26
+require DBIx::Connector;
27
+
28
+# Function for test name
29
+sub test { print "# $_[0]\n" }
30
+
31
+# Varialbes for tests
32
+my $dbname;
33
+my $rows;
34
+my $result;
35
+
36
+$dbi = DBIx::Custom::Next->connect(
37
+    dsn => "dbi:mysql:database=$database",
38
+    user => $user,
39
+    password => $password
40
+);
41
+eval { $dbi->execute('drop table table1') };
42
+$dbi->execute('create table table1 (key1 varchar(255), key2 varchar(255))');
43
+
44
+test 'connector => 1';
45
+{
46
+    my $dbi = DBIx::Custom::Next->connect(dsn => $dsn, user => $user, password => $password,
47
+      option => {PrintError => 1}, connector => 1);
48
+    is(ref $dbi->connector, 'DBIx::Connector');
49
+    ok($dbi->dbh->{PrintError});
50
+    $dbi->delete_all(table => 'table1');
51
+    $dbi->insert({key1 => 1, key2 => 2}, table => 'table1');
52
+    die "Can't fork" unless defined (my $pid = fork);
53
+
54
+    if ($pid) {
55
+        # Parent
56
+        my $result = $dbi->select(table => 'table1');
57
+        is_deeply($result->fetch_hash_first, {key1 => 1, key2 => 2});
58
+    }
59
+    else {
60
+        # Child
61
+        my $result = $dbi->select(table => 'table1');
62
+        die "Not OK" unless $result->fetch_hash_first->{key1} == 1;
63
+    }
64
+}
65
+
+11
t/next/sqlite-quote.t
... ...
@@ -0,0 +1,11 @@
1
+# Change quote for tests
2
+use DBIx::Custom::Next;
3
+{
4
+    package DBIx::Custom::Next;
5
+    no warnings 'redefine';
6
+    sub quote { '""' }
7
+}
8
+
9
+use FindBin;
10
+
11
+require "$FindBin::Bin/sqlite.t";
+328
t/next/sqlite.t
... ...
@@ -0,0 +1,328 @@
1
+use Test::More;
2
+use strict;
3
+use warnings;
4
+use utf8;
5
+use Encode qw/encode_utf8 decode_utf8/;
6
+use FindBin;
7
+use lib "$FindBin::Bin/common";
8
+
9
+BEGIN {
10
+    eval { require DBD::SQLite; 1 }
11
+        or plan skip_all => 'DBD::SQLite required';
12
+    eval { DBD::SQLite->VERSION >= 1.25 }
13
+        or plan skip_all => 'DBD::SQLite >= 1.25 required';
14
+
15
+    plan 'no_plan';
16
+    use_ok('DBIx::Custom::Next');
17
+}
18
+
19
+$SIG{__WARN__} = sub { warn $_[0] unless $_[0] =~ /DEPRECATED/};
20
+sub test { print "# $_[0]\n" }
21
+
22
+use DBIx::Custom::Next;
23
+{
24
+    package DBIx::Custom::Next;
25
+    has dsn => sub { 'dbi:SQLite:dbname=:memory:' }
26
+}
27
+
28
+# Constant
29
+my $create_table1 = 'create table table1 (key1 varchar, key2 varchar);';
30
+my $create_table_quote = 'create table "table" ("select" varchar, "update" varchar)';
31
+my $q = '"';
32
+my $p = '"';
33
+
34
+# Variables
35
+my $dbi;
36
+my $result;
37
+my $row;
38
+my $rows;
39
+my $binary;
40
+my $model;
41
+
42
+# Prepare table
43
+$dbi = DBIx::Custom::Next->connect;
44
+
45
+
46
+### SQLite only test
47
+test 'option default';
48
+$dbi = DBIx::Custom::Next->new;
49
+is_deeply($dbi->option, {});
50
+
51
+
52
+test 'prefix';
53
+$dbi = DBIx::Custom::Next->connect;
54
+eval { $dbi->execute('drop table table1') };
55
+$dbi->execute('create table table1 (key1 varchar, key2 varchar, primary key(key1));');
56
+$dbi->insert({key1 => 1, key2 => 2}, table => 'table1');
57
+$dbi->insert({key1 => 1, key2 => 4}, table => 'table1', prefix => 'or replace');
58
+$result = $dbi->execute('select * from table1;');
59
+$rows   = $result->all;
60
+is_deeply($rows, [{key1 => 1, key2 => 4}], "basic");
61
+
62
+
63
+test 'insert created_at and updated_at scalar reference';
64
+$dbi = DBIx::Custom::Next->connect;
65
+eval { $dbi->execute('drop table table1') };
66
+$dbi->execute('create table table1 (key1, key2, key3)');
67
+$dbi->now(\"datetime('now')");
68
+$dbi->insert({key1 => \"datetime('now')"}, created_at => 'key2', updated_at => 'key3', table => 'table1');
69
+$result = $dbi->select(table => 'table1');
70
+$row   = $result->one;
71
+is($row->{key1}, $row->{key2});
72
+is($row->{key1}, $row->{key3});
73
+
74
+$dbi = DBIx::Custom::Next->connect;
75
+eval { $dbi->execute('drop table table1') };
76
+$dbi->execute('create table table1 (key1, key2, key3)');
77
+$dbi->now(\"datetime('now')");
78
+$model = $dbi->create_model(created_at => 'key2', updated_at => 'key3', table => 'table1');
79
+$model->insert({key1 => \"datetime('now')"});
80
+$result = $dbi->select(table => 'table1');
81
+$row = $result->one;
82
+is($row->{key1}, $row->{key2});
83
+is($row->{key1}, $row->{key3});
84
+
85
+test 'insert created_at and updated_at scalar reference';
86
+$dbi = DBIx::Custom::Next->connect;
87
+eval { $dbi->execute('drop table table1') };
88
+$dbi->execute('create table table1 (key1, key2, key3)');
89
+$dbi->now(\"datetime('now')");
90
+$dbi->insert({key1 => \"datetime('now')"}, created_at => 'key2', updated_at => 'key3', table => 'table1');
91
+$result = $dbi->select(table => 'table1');
92
+$row   = $result->one;
93
+is($row->{key1}, $row->{key2});
94
+is($row->{key1}, $row->{key3});
95
+
96
+test 'update updated_at scalar reference';
97
+$dbi = DBIx::Custom::Next->connect;
98
+eval { $dbi->execute('drop table table1') };
99
+$dbi->execute('create table table1 (key1, key2)');
100
+$dbi->now(\"datetime('now')");
101
+$dbi->insert({key1 => \"datetime('now')"}, updated_at => 'key2', table => 'table1');
102
+$result = $dbi->select(table => 'table1');
103
+$row   = $result->one;
104
+is($row->{key1}, $row->{key2});
105
+
106
+test 'update_or_insert created_at and updated_at';
107
+eval { $dbi->execute('drop table table1') };
108
+$dbi->execute('create table table1 (key1, key2, key3, key4)');
109
+$dbi->now(\"datetime('now')");
110
+$model = $dbi->create_model(created_at => 'key2', updated_at => 'key3', table => 'table1',
111
+primary_key => 'key4');
112
+$model->update_or_insert({key1 => \"datetime('now')"}, id => 1);
113
+$result = $model->select(table => 'table1', id => 1);
114
+$row = $result->one;
115
+is($row->{key1}, $row->{key2});
116
+is($row->{key1}, $row->{key3});
117
+
118
+$dbi = DBIx::Custom::Next->connect;
119
+eval { $dbi->execute('drop table table1') };
120
+$dbi->execute('create table table1 (key1, key2)');
121
+$dbi->now(\"datetime('now')");
122
+$model = $dbi->create_model(updated_at => 'key2', table => 'table1');
123
+$model->insert({key1 => \"datetime('now')"});
124
+$result = $dbi->select(table => 'table1');
125
+$row   = $result->one;
126
+is($row->{key1}, $row->{key2});
127
+
128
+test 'DBIX_CUSTOM_DEBUG ok';
129
+{
130
+    local $ENV{DBIX_CUSTOM_DEBUG} = 1;
131
+    $dbi = DBIx::Custom::Next->connect;
132
+    eval { $dbi->execute('drop table table1') };
133
+    my $error;
134
+    local $SIG{__WARN__} = sub {
135
+        $error = shift;
136
+    };
137
+    $dbi->execute('create table table1 (key1 varchar, key2 varchar, primary key(key1));');
138
+    ok($error);
139
+}
140
+
141
+test 'quote';
142
+$dbi = DBIx::Custom::Next->connect;
143
+$dbi->quote('"');
144
+eval { $dbi->execute("drop table ${q}table$p") };
145
+$dbi->execute($create_table_quote);
146
+$dbi->insert({select => 1}, table => 'table');
147
+$dbi->delete(table => 'table', where => {select => 1});
148
+$result = $dbi->execute("select * from ${q}table$p");
149
+$rows   = $result->all;
150
+is_deeply($rows, [], "quote");
151
+
152
+test 'finish statement handle';
153
+$dbi = DBIx::Custom::Next->connect;
154
+$dbi->execute($create_table1);
155
+$dbi->insert({key1 => 1, key2 => 2}, table => 'table1');
156
+$dbi->insert({key1 => 3, key2 => 4}, table => 'table1');
157
+
158
+$result = $dbi->select(table => 'table1');
159
+$row = $result->fetch_first;
160
+is_deeply($row, [1, 2], "row");
161
+$row = $result->fetch;
162
+ok(!$row, "finished");
163
+
164
+$result = $dbi->select(table => 'table1');
165
+$row = $result->fetch_hash_first;
166
+is_deeply($row, {key1 => 1, key2 => 2}, "row");
167
+$row = $result->fetch_hash;
168
+ok(!$row, "finished");
169
+
170
+$dbi->execute('create table table2 (key1, key2);');
171
+$result = $dbi->select(table => 'table2');
172
+$row = $result->fetch_hash_first;
173
+ok(!$row, "no row fetch");
174
+
175
+$dbi = DBIx::Custom::Next->connect;
176
+eval { $dbi->execute('drop table table1') };
177
+$dbi->execute($create_table1);
178
+$dbi->insert({key1 => 1, key2 => 2}, table => 'table1');
179
+$dbi->insert({key1 => 3, key2 => 4}, table => 'table1');
180
+$dbi->insert({key1 => 5, key2 => 6}, table => 'table1');
181
+$dbi->insert({key1 => 7, key2 => 8}, table => 'table1');
182
+$dbi->insert({key1 => 9, key2 => 10}, table => 'table1');
183
+$result = $dbi->select(table => 'table1');
184
+$rows = $result->fetch_multi(2);
185
+is_deeply($rows, [[1, 2],
186
+                  [3, 4]], "fetch_multi first");
187
+$rows = $result->fetch_multi(2);
188
+is_deeply($rows, [[5, 6],
189
+                  [7, 8]], "fetch_multi secound");
190
+$rows = $result->fetch_multi(2);
191
+is_deeply($rows, [[9, 10]], "fetch_multi third");
192
+$rows = $result->fetch_multi(2);
193
+ok(!$rows);
194
+
195
+$result = $dbi->select(table => 'table1');
196
+eval {$result->fetch_multi};
197
+like($@, qr/Row count must be specified/, "Not specified row count");
198
+
199
+$result = $dbi->select(table => 'table1');
200
+$rows = $result->fetch_hash_multi(2);
201
+is_deeply($rows, [{key1 => 1, key2 => 2},
202
+                  {key1 => 3, key2 => 4}], "fetch_multi first");
203
+$rows = $result->fetch_hash_multi(2);
204
+is_deeply($rows, [{key1 => 5, key2 => 6},
205
+                  {key1 => 7, key2 => 8}], "fetch_multi secound");
206
+$rows = $result->fetch_hash_multi(2);
207
+is_deeply($rows, [{key1 => 9, key2 => 10}], "fetch_multi third");
208
+$rows = $result->fetch_hash_multi(2);
209
+ok(!$rows);
210
+
211
+$result = $dbi->select(table => 'table1');
212
+eval {$result->fetch_hash_multi};
213
+like($@, qr/Row count must be specified/, "Not specified row count");
214
+
215
+test 'bind_type option';
216
+$binary = pack("I3", 1, 2, 3);
217
+$dbi = DBIx::Custom::Next->connect(option => {sqlite_unicode => 1});
218
+$dbi->execute('create table table1(key1, key2)');
219
+$dbi->insert({key1 => $binary, key2 => 'あ'}, table => 'table1', bind_type => [key1 => DBI::SQL_BLOB]);
220
+$result = $dbi->select(table => 'table1');
221
+$row   = $result->one;
222
+is_deeply($row, {key1 => $binary, key2 => 'あ'}, "basic");
223
+$result = $dbi->execute('select length(key1) as key1_length from table1');
224
+$row = $result->one;
225
+is($row->{key1_length}, length $binary);
226
+
227
+test 'type_rule from';
228
+$dbi = DBIx::Custom::Next->connect;
229
+$dbi->type_rule(
230
+    from1 => {
231
+        date => sub { uc $_[0] }
232
+    }
233
+);
234
+$dbi->execute("create table table1 (key1 Date, key2 datetime)");
235
+$dbi->insert({key1 => 'a'}, table => 'table1');
236
+$result = $dbi->select(table => 'table1');
237
+is($result->fetch_first->[0], 'A');
238
+
239
+$result = $dbi->select(table => 'table1');
240
+is($result->one->{key1}, 'A');
241
+
242
+test 'select limit';
243
+eval { $dbi->execute('drop table table1') };
244
+$dbi->execute($create_table1);
245
+$dbi->insert({key1 => 1, key2 => 2}, table => 'table1');
246
+$dbi->insert({key1 => 3, key2 => 4}, table => 'table1');
247
+$rows = $dbi->select(table => 'table1', append => "order by key1 desc limit 1")->all;
248
+is_deeply($rows, [{key1 => 3, key2 => 4}], "append statement");
249
+
250
+
251
+
252
+# DEPRECATED! test
253
+test 'filter __ expression';
254
+$dbi = DBIx::Custom::Next->connect;
255
+eval { $dbi->execute('drop table table2') };
256
+eval { $dbi->execute('drop table table3') };
257
+$dbi->execute('create table table2 (id, name, table3_id)');
258
+$dbi->execute('create table table3 (id, name)');
259
+
260
+$dbi->insert({id => 1, name => 'a', table3_id => 2}, table => 'table2');
261
+$dbi->insert({id => 2, name => 'b'}, table => 'table3');
262
+
263
+$result = $dbi->select(
264
+    table => 'table2',
265
+    join => "inner join table3 on table2.table3_id = table3.id",
266
+    column => ['table3.name as table3__name']
267
+);
268
+is($result->fetch_first->[0], 'b');
269
+
270
+$result = $dbi->select(
271
+    table => 'table2',
272
+    join => "inner join table3 on table2.table3_id = table3.id",
273
+    column => ['table3.name as table3__name']
274
+);
275
+is($result->fetch_first->[0], 'b');
276
+
277
+$result = $dbi->select(
278
+    table => 'table2',
279
+    join => "inner join table3 on table2.table3_id = table3.id",
280
+    column => ['table3.name as "table3.name"']
281
+);
282
+is($result->fetch_first->[0], 'b');
283
+
284
+test 'quote';
285
+$dbi = DBIx::Custom::Next->connect;
286
+eval { $dbi->execute("drop table ${q}table$p") };
287
+$dbi->quote('"');
288
+$dbi->execute($create_table_quote);
289
+$dbi->insert({select => 1}, table => 'table');
290
+$dbi->update({update => 2}, table => 'table', where => {'table.select' => 1});
291
+$result = $dbi->execute("select * from ${q}table$p");
292
+$rows   = $result->all;
293
+is_deeply($rows, [{select => 1, update => 2}]);
294
+
295
+test 'join function';
296
+$dbi = DBIx::Custom::Next->connect;
297
+eval { $dbi->execute("drop table table1") };
298
+eval { $dbi->execute("drop table table2") };
299
+$dbi->execute($create_table1);
300
+$dbi->execute("create table table2 (key1, key3)");
301
+$dbi->insert({key1 => 1, key2 => 2}, table => 'table1');
302
+$dbi->insert({key1 => 1, key3 => 4}, table => 'table2');
303
+$dbi->insert({key1 => 1, key3 => 1}, table => 'table2');
304
+$result = $dbi->select(
305
+    table => 'table1',
306
+    column => [{table2 => ['key3']}],
307
+    join => [
308
+        "left outer join table2 on coalesce(table1.key1, 0) = coalesce(table2.key1, 0) and table2.key3 > '3'"
309
+    ]
310
+);
311
+is_deeply($result->all, [{"table2.key3" => 4}]);
312
+
313
+$dbi = DBIx::Custom::Next->connect;
314
+eval { $dbi->execute("drop table table1") };
315
+eval { $dbi->execute("drop table table2") };
316
+$dbi->execute($create_table1);
317
+$dbi->execute("create table table2 (key1, key3)");
318
+$dbi->insert({key1 => 1, key2 => 2}, table => 'table1');
319
+$dbi->insert({key1 => 1, key3 => 4}, table => 'table2');
320
+$dbi->insert({key1 => 1, key3 => 1}, table => 'table2');
321
+$result = $dbi->select(
322
+    table => 'table1',
323
+    column => [{table2 => ['key3']}],
324
+    join => [
325
+        "left outer join table2 on table2.key3 > '3' and coalesce(table1.key1, 0) = coalesce(table2.key1, 0)"
326
+    ]
327
+);
328
+is_deeply($result->all, [{"table2.key3" => 4}]);