commit 136306a1fe3a79cc14e4fcbb38db7f93ecd64d4c Author: Onder Kalaci Date: Thu Feb 11 04:05:32 2016 +0200 Initial commit of Citus 5.0 diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 000000000..e3ee9cf5b --- /dev/null +++ b/.gitattributes @@ -0,0 +1,22 @@ +* whitespace=space-before-tab,trailing-space +*.[chly] whitespace=space-before-tab,trailing-space,indent-with-non-tab,tabwidth=4 +*.dsl whitespace=space-before-tab,trailing-space,tab-in-indent +*.patch -whitespace +*.pl whitespace=space-before-tab,trailing-space,tabwidth=4 +*.po whitespace=space-before-tab,trailing-space,tab-in-indent,-blank-at-eof +*.sgml whitespace=space-before-tab,trailing-space,tab-in-indent,-blank-at-eol +*.x[ms]l whitespace=space-before-tab,trailing-space,tab-in-indent + +# Avoid confusing ASCII underlines with leftover merge conflict markers +README conflict-marker-size=32 +README.* conflict-marker-size=32 + +# Certain data files that contain special whitespace, and other special cases +*.data -whitespace + +# Test output files that contain extra whitespace +*.out -whitespace +src/test/regress/output/*.source -whitespace + +# These files are maintained or generated elsewhere. We take them as is. +configure -whitespace diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..b4378137e --- /dev/null +++ b/.gitignore @@ -0,0 +1,38 @@ +# Global excludes across all subdirectories +*.o +*.so +*.so.[0-9] +*.so.[0-9].[0-9] +*.sl +*.sl.[0-9] +*.sl.[0-9].[0-9] +*.dylib +*.dll +*.a +*.mo +*.pot +objfiles.txt +.deps/ +*.gcno +*.gcda +*.gcov +*.gcov.out +lcov.info +coverage/ +*.vcproj +*.vcxproj +win32ver.rc +*.exe +lib*dll.def +lib*.pc + +# Local excludes in root directory +/config.log +/config.status +/pgsql.sln +/pgsql.sln.cache +/Debug/ +/Release/ +/autom4te.cache +/Makefile.global +/src/Makefile.custom diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 000000000..cfadb6246 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,15 @@ +sudo: required +dist: trusty +language: c +cache: apt +env: + matrix: + - PGVERSION=9.5 + - PGVERSION=9.4 +before_install: + - git clone --depth 1 https://github.com/citusdata/tools.git + - tools/travis/setup_apt.sh + - tools/travis/nuke_pg.sh +install: + - tools/travis/install_pg.sh +script: tools/travis/pg_travis_multi_test.sh diff --git a/Makefile b/Makefile new file mode 100644 index 000000000..e024ef4ff --- /dev/null +++ b/Makefile @@ -0,0 +1,49 @@ +# CitusDB toplevel Makefile + +citusdb_subdir = . +citusdb_top_builddir = . + +# Hint that configure should be run first +ifeq (,$(wildcard Makefile.global)) + $(error ./configure needs to be run before compiling CitusDB) +endif + +include Makefile.global + +all: extension csql + +# build extension +extension: + $(MAKE) -C src/backend/distributed/ all +install-extension: + $(MAKE) -C src/backend/distributed/ install +install-headers: + $(MKDIR_P) '$(includedir_server)/distributed/' +# generated headers are located in the build directory + $(INSTALL_DATA) src/include/citusdb_config.h '$(includedir_server)/' +# the rest in the source tree + $(INSTALL_DATA) $(citusdb_abs_srcdir)/src/include/distributed/*.h '$(includedir_server)/distributed/' +clean-extension: + $(MAKE) -C src/backend/distributed/ clean +.PHONY: extension install-extension clean-extension +# Add to generic targets +install: install-extension install-headers +clean: clean-extension + +# build csql binary +csql: + $(MAKE) -C src/bin/csql/ all +install-csql: + $(MAKE) -C src/bin/csql/ install +clean-csql: + $(MAKE) -C src/bin/csql/ clean +.PHONY: csql install-csql clean-csql +# Add to generic targets +install: install-csql +clean: clean-csql + +# depend on install for now +check: all install + $(MAKE) -C src/test/regress check-full + +.PHONY: all check install clean diff --git a/Makefile.global.in b/Makefile.global.in new file mode 100644 index 000000000..087072749 --- /dev/null +++ b/Makefile.global.in @@ -0,0 +1,61 @@ +# -*-makefile-*- +# @configure_input@ +# Makefile.global.in - Makefile to be included by all submakes +# +# This file is converted by configure into an actual Makefile, +# replacing the @varname@ placeholders by actual values. +# +# This files is intended to contain infrastructure needed by several +# makefiles, particulary central handling of compilation flags and +# rules. + +citusdb_abs_srcdir:=@abs_top_srcdir@/${citusdb_subdir} +citusdb_abs_top_srcdir:=@abs_top_srcdir@ +PG_CONFIG:=@PG_CONFIG@ +PGXS:=$(shell $(PG_CONFIG) --pgxs) + +# Support for VPATH builds (i.e. builds from outside the source tree) +vpath_build=@vpath_build@ +ifeq ($(vpath_build),yes) + VPATH:=$(citusdb_abs_srcdir) + USE_VPATH:=$(VPATH) +endif + +# CitusDB is built using PostgreSQL's pgxs +USE_PGXS=1 +include $(PGXS) + +# Remake Makefile.global from Makefile.global.in if the latter +# changed. In order to trigger this rule, the including file must +# write `include $(citusdb_top_builddir)/Makefile.global', not some +# shortcut thereof. This makes it less likely to accidentally run +# with some outdated Makefile.global. +# Make internally restarts whenever included Makefiles are +# regenerated. +$(citusdb_top_builddir)/Makefile.global: $(citusdb_top_builddir)/Makefile.global.in @top_srcdir@/configure $(citusdb_top_builddir)/config.status + cd @abs_top_builddir@ && ./config.status Makefile.global + +# Ensure configuration is generated by the most recent configure, +# useful for longer existing build directories. +$(citusdb_top_builddir)/config.status: @top_srcdir@/configure + cd @abs_top_builddir@ && ./config.status --recheck + +# Regenerate configure if configure.in changed +@top_srcdir@/configure: $(citusdb_abs_srcdir)/configure.in + cd ${citusdb_abs_srcdir} && ./autogen.sh + +# If specified via configure, replace the default compiler. Normally +# we'll build with the one postgres was built with. But it's useful to +# be able to use a different one, especially when building against +# distribution packages. +ifneq (@CC@,) + override CC=@CC@ +endif + +# Add options passed to configure or computed therein, to CFLAGS/CPPFLAGS/... +override CFLAGS += @CFLAGS@ @CITUS_CFLAGS@ +override CPPFLAGS := @CPPFLAGS@ -I '${citusdb_abs_top_srcdir}/src/include' $(CPPFLAGS) +override LDFLAGS += @LDFLAGS@ + +# optional file with user defined, additional, rules +-include ${citusdb_abs_srcdir}/src/Makefile.custom diff --git a/autogen.sh b/autogen.sh new file mode 100755 index 000000000..9db001b0f --- /dev/null +++ b/autogen.sh @@ -0,0 +1,7 @@ +#!/bin/bash +# +# autogen.sh converts configure.in to configure and creates +# citusdb_config.h.in. The resuting resulting files are checked into +# the SCM, to avoid everyone needing autoconf installed. + +autoreconf -f diff --git a/configure b/configure new file mode 100755 index 000000000..ce37e3d49 --- /dev/null +++ b/configure @@ -0,0 +1,4170 @@ +#! /bin/sh +# Guess values for system-dependent variables and create Makefiles. +# Generated by GNU Autoconf 2.69 for CitusDB 5.0. +# +# +# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. +# +# +# This configure script is free software; the Free Software Foundation +# gives unlimited permission to copy, distribute and modify it. +# +# Copyright (c) Copyright (c) 2012-2015, Citus Data, Inc. +## -------------------- ## +## M4sh Initialization. ## +## -------------------- ## + +# Be more Bourne compatible +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi + + +as_nl=' +' +export as_nl +# Printing a long string crashes Solaris 7 /usr/bin/printf. +as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo +# Prefer a ksh shell builtin over an external printf program on Solaris, +# but without wasting forks for bash or zsh. +if test -z "$BASH_VERSION$ZSH_VERSION" \ + && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='print -r --' + as_echo_n='print -rn --' +elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='printf %s\n' + as_echo_n='printf %s' +else + if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then + as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' + as_echo_n='/usr/ucb/echo -n' + else + as_echo_body='eval expr "X$1" : "X\\(.*\\)"' + as_echo_n_body='eval + arg=$1; + case $arg in #( + *"$as_nl"*) + expr "X$arg" : "X\\(.*\\)$as_nl"; + arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; + esac; + expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" + ' + export as_echo_n_body + as_echo_n='sh -c $as_echo_n_body as_echo' + fi + export as_echo_body + as_echo='sh -c $as_echo_body as_echo' +fi + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +as_myself= +case $0 in #(( + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break + done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + exit 1 +fi + +# Unset variables that we do not need and which cause bugs (e.g. in +# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" +# suppresses any "Segmentation fault" message there. '((' could +# trigger a bug in pdksh 5.2.14. +for as_var in BASH_ENV ENV MAIL MAILPATH +do eval test x\${$as_var+set} = xset \ + && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +LC_ALL=C +export LC_ALL +LANGUAGE=C +export LANGUAGE + +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +# Use a proper internal environment variable to ensure we don't fall + # into an infinite loop, continuously re-executing ourselves. + if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then + _as_can_reexec=no; export _as_can_reexec; + # We cannot yet assume a decent shell, so we have to provide a +# neutralization value for shells without unset; and this also +# works around shells that cannot unset nonexistent variables. +# Preserve -v and -x to the replacement shell. +BASH_ENV=/dev/null +ENV=/dev/null +(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV +case $- in # (((( + *v*x* | *x*v* ) as_opts=-vx ;; + *v* ) as_opts=-v ;; + *x* ) as_opts=-x ;; + * ) as_opts= ;; +esac +exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} +# Admittedly, this is quite paranoid, since all the known shells bail +# out after a failed `exec'. +$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 +as_fn_exit 255 + fi + # We don't want this to propagate to other subprocesses. + { _as_can_reexec=; unset _as_can_reexec;} +if test "x$CONFIG_SHELL" = x; then + as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which + # is contrary to our usage. Disable this feature. + alias -g '\${1+\"\$@\"}'='\"\$@\"' + setopt NO_GLOB_SUBST +else + case \`(set -o) 2>/dev/null\` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi +" + as_required="as_fn_return () { (exit \$1); } +as_fn_success () { as_fn_return 0; } +as_fn_failure () { as_fn_return 1; } +as_fn_ret_success () { return 0; } +as_fn_ret_failure () { return 1; } + +exitcode=0 +as_fn_success || { exitcode=1; echo as_fn_success failed.; } +as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } +as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } +as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } +if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : + +else + exitcode=1; echo positional parameters were not saved. +fi +test x\$exitcode = x0 || exit 1 +test -x / || exit 1" + as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO + as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO + eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && + test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1 +test \$(( 1 + 1 )) = 2 || exit 1" + if (eval "$as_required") 2>/dev/null; then : + as_have_required=yes +else + as_have_required=no +fi + if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : + +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +as_found=false +for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + as_found=: + case $as_dir in #( + /*) + for as_base in sh bash ksh sh5; do + # Try only shells that exist, to save several forks. + as_shell=$as_dir/$as_base + if { test -f "$as_shell" || test -f "$as_shell.exe"; } && + { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : + CONFIG_SHELL=$as_shell as_have_required=yes + if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : + break 2 +fi +fi + done;; + esac + as_found=false +done +$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && + { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : + CONFIG_SHELL=$SHELL as_have_required=yes +fi; } +IFS=$as_save_IFS + + + if test "x$CONFIG_SHELL" != x; then : + export CONFIG_SHELL + # We cannot yet assume a decent shell, so we have to provide a +# neutralization value for shells without unset; and this also +# works around shells that cannot unset nonexistent variables. +# Preserve -v and -x to the replacement shell. +BASH_ENV=/dev/null +ENV=/dev/null +(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV +case $- in # (((( + *v*x* | *x*v* ) as_opts=-vx ;; + *v* ) as_opts=-v ;; + *x* ) as_opts=-x ;; + * ) as_opts= ;; +esac +exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} +# Admittedly, this is quite paranoid, since all the known shells bail +# out after a failed `exec'. +$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 +exit 255 +fi + + if test x$as_have_required = xno; then : + $as_echo "$0: This script requires a shell more modern than all" + $as_echo "$0: the shells that I found on your system." + if test x${ZSH_VERSION+set} = xset ; then + $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" + $as_echo "$0: be upgraded to zsh 4.3.4 or later." + else + $as_echo "$0: Please tell bug-autoconf@gnu.org about your system, +$0: including any error possibly output before this +$0: message. Then install a modern shell, or manually run +$0: the script under such a shell if you do have one." + fi + exit 1 +fi +fi +fi +SHELL=${CONFIG_SHELL-/bin/sh} +export SHELL +# Unset more variables known to interfere with behavior of common tools. +CLICOLOR_FORCE= GREP_OPTIONS= +unset CLICOLOR_FORCE GREP_OPTIONS + +## --------------------- ## +## M4sh Shell Functions. ## +## --------------------- ## +# as_fn_unset VAR +# --------------- +# Portably unset VAR. +as_fn_unset () +{ + { eval $1=; unset $1;} +} +as_unset=as_fn_unset + +# as_fn_set_status STATUS +# ----------------------- +# Set $? to STATUS, without forking. +as_fn_set_status () +{ + return $1 +} # as_fn_set_status + +# as_fn_exit STATUS +# ----------------- +# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. +as_fn_exit () +{ + set +e + as_fn_set_status $1 + exit $1 +} # as_fn_exit + +# as_fn_mkdir_p +# ------------- +# Create "$as_dir" as a directory, including parents if necessary. +as_fn_mkdir_p () +{ + + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || eval $as_mkdir_p || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" + + +} # as_fn_mkdir_p + +# as_fn_executable_p FILE +# ----------------------- +# Test if FILE is an executable regular file. +as_fn_executable_p () +{ + test -f "$1" && test -x "$1" +} # as_fn_executable_p +# as_fn_append VAR VALUE +# ---------------------- +# Append the text in VALUE to the end of the definition contained in VAR. Take +# advantage of any shell optimizations that allow amortized linear growth over +# repeated appends, instead of the typical quadratic growth present in naive +# implementations. +if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : + eval 'as_fn_append () + { + eval $1+=\$2 + }' +else + as_fn_append () + { + eval $1=\$$1\$2 + } +fi # as_fn_append + +# as_fn_arith ARG... +# ------------------ +# Perform arithmetic evaluation on the ARGs, and store the result in the +# global $as_val. Take advantage of shells that can avoid forks. The arguments +# must be portable across $(()) and expr. +if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : + eval 'as_fn_arith () + { + as_val=$(( $* )) + }' +else + as_fn_arith () + { + as_val=`expr "$@" || test $? -eq 1` + } +fi # as_fn_arith + + +# as_fn_error STATUS ERROR [LINENO LOG_FD] +# ---------------------------------------- +# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are +# provided, also output the error to LOG_FD, referencing LINENO. Then exit the +# script with STATUS, using 1 if that was 0. +as_fn_error () +{ + as_status=$1; test $as_status -eq 0 && as_status=1 + if test "$4"; then + as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 + fi + $as_echo "$as_me: error: $2" >&2 + as_fn_exit $as_status +} # as_fn_error + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + + + as_lineno_1=$LINENO as_lineno_1a=$LINENO + as_lineno_2=$LINENO as_lineno_2a=$LINENO + eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && + test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { + # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) + sed -n ' + p + /[$]LINENO/= + ' <$as_myself | + sed ' + s/[$]LINENO.*/&-/ + t lineno + b + :lineno + N + :loop + s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ + t loop + s/-\n.*// + ' >$as_me.lineno && + chmod +x "$as_me.lineno" || + { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } + + # If we had to re-execute with $CONFIG_SHELL, we're ensured to have + # already done that, so ensure we don't try to do so again and fall + # in an infinite loop. This has already happened in practice. + _as_can_reexec=no; export _as_can_reexec + # Don't try to exec as it changes $[0], causing all sort of problems + # (the dirname of $[0] is not the place where we might find the + # original and so on. Autoconf is especially sensitive to this). + . "./$as_me.lineno" + # Exit status is that of the last command. + exit +} + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in #((((( +-n*) + case `echo 'xy\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + xy) ECHO_C='\c';; + *) echo `echo ksh88 bug on AIX 6.1` > /dev/null + ECHO_T=' ';; + esac;; +*) + ECHO_N='-n';; +esac + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir 2>/dev/null +fi +if (echo >conf$$.file) 2>/dev/null; then + if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -pR'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -pR' + elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln + else + as_ln_s='cp -pR' + fi +else + as_ln_s='cp -pR' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + +if mkdir -p . 2>/dev/null; then + as_mkdir_p='mkdir -p "$as_dir"' +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + +as_test_x='test -x' +as_executable_p=as_fn_executable_p + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + +test -n "$DJDIR" || exec 7<&0 &1 + +# Name of the host. +# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, +# so uname gets run too. +ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` + +# +# Initializations. +# +ac_default_prefix=/usr/local +ac_clean_files= +ac_config_libobj_dir=. +LIBOBJS= +cross_compiling=no +subdirs= +MFLAGS= +MAKEFLAGS= + +# Identity of this package. +PACKAGE_NAME='CitusDB' +PACKAGE_TARNAME='citusdb' +PACKAGE_VERSION='5.0' +PACKAGE_STRING='CitusDB 5.0' +PACKAGE_BUGREPORT='' +PACKAGE_URL='' + +ac_subst_vars='LTLIBOBJS +LIBOBJS +CITUS_CFLAGS +OBJEXT +EXEEXT +ac_ct_CC +CPPFLAGS +LDFLAGS +CFLAGS +CC +vpath_build +PATH +PG_CONFIG +SED +target_alias +host_alias +build_alias +LIBS +ECHO_T +ECHO_N +ECHO_C +DEFS +mandir +localedir +libdir +psdir +pdfdir +dvidir +htmldir +infodir +docdir +oldincludedir +includedir +localstatedir +sharedstatedir +sysconfdir +datadir +datarootdir +libexecdir +sbindir +bindir +program_transform_name +prefix +exec_prefix +PACKAGE_URL +PACKAGE_BUGREPORT +PACKAGE_STRING +PACKAGE_VERSION +PACKAGE_TARNAME +PACKAGE_NAME +PATH_SEPARATOR +SHELL' +ac_subst_files='' +ac_user_opts=' +enable_option_checking +' + ac_precious_vars='build_alias +host_alias +target_alias +PG_CONFIG +PATH +CC +CFLAGS +LDFLAGS +LIBS +CPPFLAGS' + + +# Initialize some variables set by options. +ac_init_help= +ac_init_version=false +ac_unrecognized_opts= +ac_unrecognized_sep= +# The variables have the same names as the options, with +# dashes changed to underlines. +cache_file=/dev/null +exec_prefix=NONE +no_create= +no_recursion= +prefix=NONE +program_prefix=NONE +program_suffix=NONE +program_transform_name=s,x,x, +silent= +site= +srcdir= +verbose= +x_includes=NONE +x_libraries=NONE + +# Installation directory options. +# These are left unexpanded so users can "make install exec_prefix=/foo" +# and all the variables that are supposed to be based on exec_prefix +# by default will actually change. +# Use braces instead of parens because sh, perl, etc. also accept them. +# (The list follows the same order as the GNU Coding Standards.) +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datarootdir='${prefix}/share' +datadir='${datarootdir}' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +includedir='${prefix}/include' +oldincludedir='/usr/include' +docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' +infodir='${datarootdir}/info' +htmldir='${docdir}' +dvidir='${docdir}' +pdfdir='${docdir}' +psdir='${docdir}' +libdir='${exec_prefix}/lib' +localedir='${datarootdir}/locale' +mandir='${datarootdir}/man' + +ac_prev= +ac_dashdash= +for ac_option +do + # If the previous option needs an argument, assign it. + if test -n "$ac_prev"; then + eval $ac_prev=\$ac_option + ac_prev= + continue + fi + + case $ac_option in + *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; + *=) ac_optarg= ;; + *) ac_optarg=yes ;; + esac + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case $ac_dashdash$ac_option in + --) + ac_dashdash=yes ;; + + -bindir | --bindir | --bindi | --bind | --bin | --bi) + ac_prev=bindir ;; + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) + bindir=$ac_optarg ;; + + -build | --build | --buil | --bui | --bu) + ac_prev=build_alias ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=*) + build_alias=$ac_optarg ;; + + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + cache_file=$ac_optarg ;; + + --config-cache | -C) + cache_file=config.cache ;; + + -datadir | --datadir | --datadi | --datad) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=*) + datadir=$ac_optarg ;; + + -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ + | --dataroo | --dataro | --datar) + ac_prev=datarootdir ;; + -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ + | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) + datarootdir=$ac_optarg ;; + + -disable-* | --disable-*) + ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid feature name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"enable_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval enable_$ac_useropt=no ;; + + -docdir | --docdir | --docdi | --doc | --do) + ac_prev=docdir ;; + -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) + docdir=$ac_optarg ;; + + -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) + ac_prev=dvidir ;; + -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) + dvidir=$ac_optarg ;; + + -enable-* | --enable-*) + ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid feature name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"enable_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval enable_$ac_useropt=\$ac_optarg ;; + + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ + | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ + | --exec | --exe | --ex) + ac_prev=exec_prefix ;; + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ + | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ + | --exec=* | --exe=* | --ex=*) + exec_prefix=$ac_optarg ;; + + -gas | --gas | --ga | --g) + # Obsolete; use --with-gas. + with_gas=yes ;; + + -help | --help | --hel | --he | -h) + ac_init_help=long ;; + -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) + ac_init_help=recursive ;; + -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) + ac_init_help=short ;; + + -host | --host | --hos | --ho) + ac_prev=host_alias ;; + -host=* | --host=* | --hos=* | --ho=*) + host_alias=$ac_optarg ;; + + -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) + ac_prev=htmldir ;; + -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ + | --ht=*) + htmldir=$ac_optarg ;; + + -includedir | --includedir | --includedi | --included | --include \ + | --includ | --inclu | --incl | --inc) + ac_prev=includedir ;; + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ + | --includ=* | --inclu=* | --incl=* | --inc=*) + includedir=$ac_optarg ;; + + -infodir | --infodir | --infodi | --infod | --info | --inf) + ac_prev=infodir ;; + -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) + infodir=$ac_optarg ;; + + -libdir | --libdir | --libdi | --libd) + ac_prev=libdir ;; + -libdir=* | --libdir=* | --libdi=* | --libd=*) + libdir=$ac_optarg ;; + + -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ + | --libexe | --libex | --libe) + ac_prev=libexecdir ;; + -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ + | --libexe=* | --libex=* | --libe=*) + libexecdir=$ac_optarg ;; + + -localedir | --localedir | --localedi | --localed | --locale) + ac_prev=localedir ;; + -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) + localedir=$ac_optarg ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst | --locals) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) + localstatedir=$ac_optarg ;; + + -mandir | --mandir | --mandi | --mand | --man | --ma | --m) + ac_prev=mandir ;; + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) + mandir=$ac_optarg ;; + + -nfp | --nfp | --nf) + # Obsolete; use --without-fp. + with_fp=no ;; + + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c | -n) + no_create=yes ;; + + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) + no_recursion=yes ;; + + -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ + | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ + | --oldin | --oldi | --old | --ol | --o) + ac_prev=oldincludedir ;; + -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ + | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ + | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) + oldincludedir=$ac_optarg ;; + + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + prefix=$ac_optarg ;; + + -program-prefix | --program-prefix | --program-prefi | --program-pref \ + | --program-pre | --program-pr | --program-p) + ac_prev=program_prefix ;; + -program-prefix=* | --program-prefix=* | --program-prefi=* \ + | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) + program_prefix=$ac_optarg ;; + + -program-suffix | --program-suffix | --program-suffi | --program-suff \ + | --program-suf | --program-su | --program-s) + ac_prev=program_suffix ;; + -program-suffix=* | --program-suffix=* | --program-suffi=* \ + | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) + program_suffix=$ac_optarg ;; + + -program-transform-name | --program-transform-name \ + | --program-transform-nam | --program-transform-na \ + | --program-transform-n | --program-transform- \ + | --program-transform | --program-transfor \ + | --program-transfo | --program-transf \ + | --program-trans | --program-tran \ + | --progr-tra | --program-tr | --program-t) + ac_prev=program_transform_name ;; + -program-transform-name=* | --program-transform-name=* \ + | --program-transform-nam=* | --program-transform-na=* \ + | --program-transform-n=* | --program-transform-=* \ + | --program-transform=* | --program-transfor=* \ + | --program-transfo=* | --program-transf=* \ + | --program-trans=* | --program-tran=* \ + | --progr-tra=* | --program-tr=* | --program-t=*) + program_transform_name=$ac_optarg ;; + + -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) + ac_prev=pdfdir ;; + -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) + pdfdir=$ac_optarg ;; + + -psdir | --psdir | --psdi | --psd | --ps) + ac_prev=psdir ;; + -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) + psdir=$ac_optarg ;; + + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ + | --sbi=* | --sb=*) + sbindir=$ac_optarg ;; + + -sharedstatedir | --sharedstatedir | --sharedstatedi \ + | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ + | --sharedst | --shareds | --shared | --share | --shar \ + | --sha | --sh) + ac_prev=sharedstatedir ;; + -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ + | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ + | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ + | --sha=* | --sh=*) + sharedstatedir=$ac_optarg ;; + + -site | --site | --sit) + ac_prev=site ;; + -site=* | --site=* | --sit=*) + site=$ac_optarg ;; + + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + srcdir=$ac_optarg ;; + + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ + | --syscon | --sysco | --sysc | --sys | --sy) + ac_prev=sysconfdir ;; + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) + sysconfdir=$ac_optarg ;; + + -target | --target | --targe | --targ | --tar | --ta | --t) + ac_prev=target_alias ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target_alias=$ac_optarg ;; + + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; + + -version | --version | --versio | --versi | --vers | -V) + ac_init_version=: ;; + + -with-* | --with-*) + ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid package name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"with_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval with_$ac_useropt=\$ac_optarg ;; + + -without-* | --without-*) + ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid package name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"with_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval with_$ac_useropt=no ;; + + --x) + # Obsolete; use --with-x. + with_x=yes ;; + + -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ + | --x-incl | --x-inc | --x-in | --x-i) + ac_prev=x_includes ;; + -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ + | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) + x_includes=$ac_optarg ;; + + -x-libraries | --x-libraries | --x-librarie | --x-librari \ + | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) + ac_prev=x_libraries ;; + -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ + | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) + x_libraries=$ac_optarg ;; + + -*) as_fn_error $? "unrecognized option: \`$ac_option' +Try \`$0 --help' for more information" + ;; + + *=*) + ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` + # Reject names that are not valid shell variable names. + case $ac_envvar in #( + '' | [0-9]* | *[!_$as_cr_alnum]* ) + as_fn_error $? "invalid variable name: \`$ac_envvar'" ;; + esac + eval $ac_envvar=\$ac_optarg + export $ac_envvar ;; + + *) + # FIXME: should be removed in autoconf 3.0. + $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 + expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && + $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 + : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}" + ;; + + esac +done + +if test -n "$ac_prev"; then + ac_option=--`echo $ac_prev | sed 's/_/-/g'` + as_fn_error $? "missing argument to $ac_option" +fi + +if test -n "$ac_unrecognized_opts"; then + case $enable_option_checking in + no) ;; + fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; + *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; + esac +fi + +# Check all directory arguments for consistency. +for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ + datadir sysconfdir sharedstatedir localstatedir includedir \ + oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ + libdir localedir mandir +do + eval ac_val=\$$ac_var + # Remove trailing slashes. + case $ac_val in + */ ) + ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` + eval $ac_var=\$ac_val;; + esac + # Be sure to have absolute directory names. + case $ac_val in + [\\/$]* | ?:[\\/]* ) continue;; + NONE | '' ) case $ac_var in *prefix ) continue;; esac;; + esac + as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" +done + +# There might be people who depend on the old broken behavior: `$host' +# used to hold the argument of --host etc. +# FIXME: To remove some day. +build=$build_alias +host=$host_alias +target=$target_alias + +# FIXME: To remove some day. +if test "x$host_alias" != x; then + if test "x$build_alias" = x; then + cross_compiling=maybe + elif test "x$build_alias" != "x$host_alias"; then + cross_compiling=yes + fi +fi + +ac_tool_prefix= +test -n "$host_alias" && ac_tool_prefix=$host_alias- + +test "$silent" = yes && exec 6>/dev/null + + +ac_pwd=`pwd` && test -n "$ac_pwd" && +ac_ls_di=`ls -di .` && +ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || + as_fn_error $? "working directory cannot be determined" +test "X$ac_ls_di" = "X$ac_pwd_ls_di" || + as_fn_error $? "pwd does not report name of working directory" + + +# Find the source files, if location was not specified. +if test -z "$srcdir"; then + ac_srcdir_defaulted=yes + # Try the directory containing this script, then the parent directory. + ac_confdir=`$as_dirname -- "$as_myself" || +$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_myself" : 'X\(//\)[^/]' \| \ + X"$as_myself" : 'X\(//\)$' \| \ + X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_myself" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + srcdir=$ac_confdir + if test ! -r "$srcdir/$ac_unique_file"; then + srcdir=.. + fi +else + ac_srcdir_defaulted=no +fi +if test ! -r "$srcdir/$ac_unique_file"; then + test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." + as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" +fi +ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" +ac_abs_confdir=`( + cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" + pwd)` +# When building in place, set srcdir=. +if test "$ac_abs_confdir" = "$ac_pwd"; then + srcdir=. +fi +# Remove unnecessary trailing slashes from srcdir. +# Double slashes in file names in object file debugging info +# mess up M-x gdb in Emacs. +case $srcdir in +*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; +esac +for ac_var in $ac_precious_vars; do + eval ac_env_${ac_var}_set=\${${ac_var}+set} + eval ac_env_${ac_var}_value=\$${ac_var} + eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} + eval ac_cv_env_${ac_var}_value=\$${ac_var} +done + +# +# Report the --help message. +# +if test "$ac_init_help" = "long"; then + # Omit some internal or obsolete options to make the list less imposing. + # This message is too long to be a string in the A/UX 3.1 sh. + cat <<_ACEOF +\`configure' configures CitusDB 5.0 to adapt to many kinds of systems. + +Usage: $0 [OPTION]... [VAR=VALUE]... + +To assign environment variables (e.g., CC, CFLAGS...), specify them as +VAR=VALUE. See below for descriptions of some of the useful variables. + +Defaults for the options are specified in brackets. + +Configuration: + -h, --help display this help and exit + --help=short display options specific to this package + --help=recursive display the short help of all the included packages + -V, --version display version information and exit + -q, --quiet, --silent do not print \`checking ...' messages + --cache-file=FILE cache test results in FILE [disabled] + -C, --config-cache alias for \`--cache-file=config.cache' + -n, --no-create do not create output files + --srcdir=DIR find the sources in DIR [configure dir or \`..'] + +Installation directories: + --prefix=PREFIX install architecture-independent files in PREFIX + [$ac_default_prefix] + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + [PREFIX] + +By default, \`make install' will install all the files in +\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify +an installation prefix other than \`$ac_default_prefix' using \`--prefix', +for instance \`--prefix=\$HOME'. + +For better control, use the options below. + +Fine tuning of the installation directories: + --bindir=DIR user executables [EPREFIX/bin] + --sbindir=DIR system admin executables [EPREFIX/sbin] + --libexecdir=DIR program executables [EPREFIX/libexec] + --sysconfdir=DIR read-only single-machine data [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] + --localstatedir=DIR modifiable single-machine data [PREFIX/var] + --libdir=DIR object code libraries [EPREFIX/lib] + --includedir=DIR C header files [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc [/usr/include] + --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] + --datadir=DIR read-only architecture-independent data [DATAROOTDIR] + --infodir=DIR info documentation [DATAROOTDIR/info] + --localedir=DIR locale-dependent data [DATAROOTDIR/locale] + --mandir=DIR man documentation [DATAROOTDIR/man] + --docdir=DIR documentation root [DATAROOTDIR/doc/citusdb] + --htmldir=DIR html documentation [DOCDIR] + --dvidir=DIR dvi documentation [DOCDIR] + --pdfdir=DIR pdf documentation [DOCDIR] + --psdir=DIR ps documentation [DOCDIR] +_ACEOF + + cat <<\_ACEOF +_ACEOF +fi + +if test -n "$ac_init_help"; then + case $ac_init_help in + short | recursive ) echo "Configuration of CitusDB 5.0:";; + esac + cat <<\_ACEOF + +Some influential environment variables: + PG_CONFIG Location to find pg_config for target PostgreSQL instalation + (default PATH) + PATH PATH for target PostgreSQL install pg_config + CC C compiler command + CFLAGS C compiler flags + LDFLAGS linker flags, e.g. -L if you have libraries in a + nonstandard directory + LIBS libraries to pass to the linker, e.g. -l + CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if + you have headers in a nonstandard directory + +Use these variables to override the choices made by `configure' or to help +it to find libraries and programs with nonstandard names/locations. + +Report bugs to the package provider. +_ACEOF +ac_status=$? +fi + +if test "$ac_init_help" = "recursive"; then + # If there are subdirs, report their specific --help. + for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue + test -d "$ac_dir" || + { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || + continue + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + cd "$ac_dir" || { ac_status=$?; continue; } + # Check for guested configure. + if test -f "$ac_srcdir/configure.gnu"; then + echo && + $SHELL "$ac_srcdir/configure.gnu" --help=recursive + elif test -f "$ac_srcdir/configure"; then + echo && + $SHELL "$ac_srcdir/configure" --help=recursive + else + $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 + fi || ac_status=$? + cd "$ac_pwd" || { ac_status=$?; break; } + done +fi + +test -n "$ac_init_help" && exit $ac_status +if $ac_init_version; then + cat <<\_ACEOF +CitusDB configure 5.0 +generated by GNU Autoconf 2.69 + +Copyright (C) 2012 Free Software Foundation, Inc. +This configure script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it. + +Copyright (c) Copyright (c) 2012-2015, Citus Data, Inc. +_ACEOF + exit +fi + +## ------------------------ ## +## Autoconf initialization. ## +## ------------------------ ## + +# ac_fn_c_try_compile LINENO +# -------------------------- +# Try to compile conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_compile () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext + if { { ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compile") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_compile +cat >config.log <<_ACEOF +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. + +It was created by CitusDB $as_me 5.0, which was +generated by GNU Autoconf 2.69. Invocation command line was + + $ $0 $@ + +_ACEOF +exec 5>>config.log +{ +cat <<_ASUNAME +## --------- ## +## Platform. ## +## --------- ## + +hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` + +/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` +/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` +/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` +/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` + +_ASUNAME + +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + $as_echo "PATH: $as_dir" + done +IFS=$as_save_IFS + +} >&5 + +cat >&5 <<_ACEOF + + +## ----------- ## +## Core tests. ## +## ----------- ## + +_ACEOF + + +# Keep a trace of the command line. +# Strip out --no-create and --no-recursion so they do not pile up. +# Strip out --silent because we don't want to record it for future runs. +# Also quote any args containing shell meta-characters. +# Make two passes to allow for proper duplicate-argument suppression. +ac_configure_args= +ac_configure_args0= +ac_configure_args1= +ac_must_keep_next=false +for ac_pass in 1 2 +do + for ac_arg + do + case $ac_arg in + -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + continue ;; + *\'*) + ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + case $ac_pass in + 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; + 2) + as_fn_append ac_configure_args1 " '$ac_arg'" + if test $ac_must_keep_next = true; then + ac_must_keep_next=false # Got value, back to normal. + else + case $ac_arg in + *=* | --config-cache | -C | -disable-* | --disable-* \ + | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ + | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ + | -with-* | --with-* | -without-* | --without-* | --x) + case "$ac_configure_args0 " in + "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; + esac + ;; + -* ) ac_must_keep_next=true ;; + esac + fi + as_fn_append ac_configure_args " '$ac_arg'" + ;; + esac + done +done +{ ac_configure_args0=; unset ac_configure_args0;} +{ ac_configure_args1=; unset ac_configure_args1;} + +# When interrupted or exit'd, cleanup temporary files, and complete +# config.log. We remove comments because anyway the quotes in there +# would cause problems or look ugly. +# WARNING: Use '\'' to represent an apostrophe within the trap. +# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. +trap 'exit_status=$? + # Save into config.log some information that might help in debugging. + { + echo + + $as_echo "## ---------------- ## +## Cache variables. ## +## ---------------- ##" + echo + # The following way of writing the cache mishandles newlines in values, +( + for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 +$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( + *) { eval $ac_var=; unset $ac_var;} ;; + esac ;; + esac + done + (set) 2>&1 | + case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + sed -n \ + "s/'\''/'\''\\\\'\'''\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" + ;; #( + *) + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) + echo + + $as_echo "## ----------------- ## +## Output variables. ## +## ----------------- ##" + echo + for ac_var in $ac_subst_vars + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + $as_echo "$ac_var='\''$ac_val'\''" + done | sort + echo + + if test -n "$ac_subst_files"; then + $as_echo "## ------------------- ## +## File substitutions. ## +## ------------------- ##" + echo + for ac_var in $ac_subst_files + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + $as_echo "$ac_var='\''$ac_val'\''" + done | sort + echo + fi + + if test -s confdefs.h; then + $as_echo "## ----------- ## +## confdefs.h. ## +## ----------- ##" + echo + cat confdefs.h + echo + fi + test "$ac_signal" != 0 && + $as_echo "$as_me: caught signal $ac_signal" + $as_echo "$as_me: exit $exit_status" + } >&5 + rm -f core *.core core.conftest.* && + rm -f -r conftest* confdefs* conf$$* $ac_clean_files && + exit $exit_status +' 0 +for ac_signal in 1 2 13 15; do + trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal +done +ac_signal=0 + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -f -r conftest* confdefs.h + +$as_echo "/* confdefs.h */" > confdefs.h + +# Predefined preprocessor variables. + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_NAME "$PACKAGE_NAME" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_TARNAME "$PACKAGE_TARNAME" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_VERSION "$PACKAGE_VERSION" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_STRING "$PACKAGE_STRING" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_URL "$PACKAGE_URL" +_ACEOF + + +# Let the site file select an alternate cache file if it wants to. +# Prefer an explicitly selected file to automatically selected ones. +ac_site_file1=NONE +ac_site_file2=NONE +if test -n "$CONFIG_SITE"; then + # We do not want a PATH search for config.site. + case $CONFIG_SITE in #(( + -*) ac_site_file1=./$CONFIG_SITE;; + */*) ac_site_file1=$CONFIG_SITE;; + *) ac_site_file1=./$CONFIG_SITE;; + esac +elif test "x$prefix" != xNONE; then + ac_site_file1=$prefix/share/config.site + ac_site_file2=$prefix/etc/config.site +else + ac_site_file1=$ac_default_prefix/share/config.site + ac_site_file2=$ac_default_prefix/etc/config.site +fi +for ac_site_file in "$ac_site_file1" "$ac_site_file2" +do + test "x$ac_site_file" = xNONE && continue + if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 +$as_echo "$as_me: loading site script $ac_site_file" >&6;} + sed 's/^/| /' "$ac_site_file" >&5 + . "$ac_site_file" \ + || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "failed to load site script $ac_site_file +See \`config.log' for more details" "$LINENO" 5; } + fi +done + +if test -r "$cache_file"; then + # Some versions of bash will fail to source /dev/null (special files + # actually), so we avoid doing that. DJGPP emulates it as a regular file. + if test /dev/null != "$cache_file" && test -f "$cache_file"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 +$as_echo "$as_me: loading cache $cache_file" >&6;} + case $cache_file in + [\\/]* | ?:[\\/]* ) . "$cache_file";; + *) . "./$cache_file";; + esac + fi +else + { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 +$as_echo "$as_me: creating cache $cache_file" >&6;} + >$cache_file +fi + +# Check that the precious variables saved in the cache have kept the same +# value. +ac_cache_corrupted=false +for ac_var in $ac_precious_vars; do + eval ac_old_set=\$ac_cv_env_${ac_var}_set + eval ac_new_set=\$ac_env_${ac_var}_set + eval ac_old_val=\$ac_cv_env_${ac_var}_value + eval ac_new_val=\$ac_env_${ac_var}_value + case $ac_old_set,$ac_new_set in + set,) + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 +$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,set) + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 +$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,);; + *) + if test "x$ac_old_val" != "x$ac_new_val"; then + # differences in whitespace do not lead to failure. + ac_old_val_w=`echo x $ac_old_val` + ac_new_val_w=`echo x $ac_new_val` + if test "$ac_old_val_w" != "$ac_new_val_w"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 +$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} + ac_cache_corrupted=: + else + { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 +$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} + eval $ac_var=\$ac_old_val + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 +$as_echo "$as_me: former value: \`$ac_old_val'" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 +$as_echo "$as_me: current value: \`$ac_new_val'" >&2;} + fi;; + esac + # Pass precious variables to config.status. + if test "$ac_new_set" = set; then + case $ac_new_val in + *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; + *) ac_arg=$ac_var=$ac_new_val ;; + esac + case " $ac_configure_args " in + *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. + *) as_fn_append ac_configure_args " '$ac_arg'" ;; + esac + fi +done +if $ac_cache_corrupted; then + { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 +$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} + as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 +fi +## -------------------- ## +## Main body of script. ## +## -------------------- ## + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a sed that does not truncate output" >&5 +$as_echo_n "checking for a sed that does not truncate output... " >&6; } +if ${ac_cv_path_SED+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/ + for ac_i in 1 2 3 4 5 6 7; do + ac_script="$ac_script$as_nl$ac_script" + done + echo "$ac_script" 2>/dev/null | sed 99q >conftest.sed + { ac_script=; unset ac_script;} + if test -z "$SED"; then + ac_path_SED_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in sed gsed; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_SED="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_SED" || continue +# Check for GNU ac_path_SED and select it if it is found. + # Check for GNU $ac_path_SED +case `"$ac_path_SED" --version 2>&1` in +*GNU*) + ac_cv_path_SED="$ac_path_SED" ac_path_SED_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo '' >> "conftest.nl" + "$ac_path_SED" -f conftest.sed < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_SED_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_SED="$ac_path_SED" + ac_path_SED_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_SED_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_SED"; then + as_fn_error $? "no acceptable sed could be found in \$PATH" "$LINENO" 5 + fi +else + ac_cv_path_SED=$SED +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_SED" >&5 +$as_echo "$ac_cv_path_SED" >&6; } + SED="$ac_cv_path_SED" + rm -f conftest.sed + + +# Locate pg_config binary + + + +if test -z "$PG_CONFIG"; then + # Extract the first word of "pg_config", so it can be a program name with args. +set dummy pg_config; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_PG_CONFIG+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $PG_CONFIG in + [\\/]* | ?:[\\/]*) + ac_cv_path_PG_CONFIG="$PG_CONFIG" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_PG_CONFIG="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +PG_CONFIG=$ac_cv_path_PG_CONFIG +if test -n "$PG_CONFIG"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PG_CONFIG" >&5 +$as_echo "$PG_CONFIG" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi + +if test -z "$PG_CONFIG"; then + as_fn_error $? "Could not find pg_config. Set PG_CONFIG or PATH." "$LINENO" 5 +fi + +# check we're building against a supported version of PostgreSQL +citusac_pg_config_version=$($PG_CONFIG --version 2>/dev/null) +version_num=$(echo "$citusac_pg_config_version"| + $SED -e 's/^PostgreSQL \([0-9]*\)\.\([0-9]*\)\([a-zA-Z0-9.]*\)$/\1.\2/') + +if test -z "$version_num"; then + as_fn_error $? "Could not detect PostgreSQL version from pg_config." "$LINENO" 5 +fi + +if test "$version_num" != '9.4' -a "$version_num" != '9.5'; then + as_fn_error $? "CitusDB is not compatible with the detected PostgreSQL version ${version_num}." "$LINENO" 5 +else + { $as_echo "$as_me:${as_lineno-$LINENO}: building against PostgreSQL $version_num" >&5 +$as_echo "$as_me: building against PostgreSQL $version_num" >&6;} +fi; + +# Check whether we're building inside the source tree, if not, prepare +# the build directory. +if test "$srcdir" -ef '.' ; then + vpath_build=no +else + vpath_build=yes + $as_echo_n "preparing build tree... " >&6 + citusac_abs_top_srcdir=`cd "$srcdir" && pwd` + $SHELL "$citusac_abs_top_srcdir/prep_buildtree" "$citusac_abs_top_srcdir" "." \ + || as_fn_error $? "failed" "$LINENO" 5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: done" >&5 +$as_echo "done" >&6; } +fi + + +# Allow to overwrite the C compiler, default to the one postgres was +# compiled with +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +if test -n "$ac_tool_prefix"; then + for ac_prog in $($PG_CONFIG --cc) + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$CC" && break + done +fi +if test -z "$CC"; then + ac_ct_CC=$CC + for ac_prog in $($PG_CONFIG --cc) +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_CC" && break +done + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +fi + + +test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "no acceptable C compiler found in \$PATH +See \`config.log' for more details" "$LINENO" 5; } + +# Provide some information about the compiler. +$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 +set X $ac_compile +ac_compiler=$2 +for ac_option in --version -v -V -qversion; do + { { ac_try="$ac_compiler $ac_option >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compiler $ac_option >&5") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + sed '10a\ +... rest of stderr output deleted ... + 10q' conftest.err >conftest.er1 + cat conftest.er1 >&5 + fi + rm -f conftest.er1 conftest.err + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } +done + +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out" +# Try to create an executable without -o first, disregard a.out. +# It will help us diagnose broken compilers, and finding out an intuition +# of exeext. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5 +$as_echo_n "checking whether the C compiler works... " >&6; } +ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` + +# The possible output files: +ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" + +ac_rmfiles= +for ac_file in $ac_files +do + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; + * ) ac_rmfiles="$ac_rmfiles $ac_file";; + esac +done +rm -f $ac_rmfiles + +if { { ac_try="$ac_link_default" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link_default") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. +# So ignore a value of `no', otherwise this would lead to `EXEEXT = no' +# in a Makefile. We should not override ac_cv_exeext if it was cached, +# so that the user can short-circuit this test for compilers unknown to +# Autoconf. +for ac_file in $ac_files '' +do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) + ;; + [ab].out ) + # We found the default executable, but exeext='' is most + # certainly right. + break;; + *.* ) + if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; + then :; else + ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + fi + # We set ac_cv_exeext here because the later test for it is not + # safe: cross compilers may not add the suffix if given an `-o' + # argument, so we may need to know it at that point already. + # Even if this section looks crufty: it has the advantage of + # actually working. + break;; + * ) + break;; + esac +done +test "$ac_cv_exeext" = no && ac_cv_exeext= + +else + ac_file='' +fi +if test -z "$ac_file"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +$as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error 77 "C compiler cannot create executables +See \`config.log' for more details" "$LINENO" 5; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5 +$as_echo_n "checking for C compiler default output file name... " >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 +$as_echo "$ac_file" >&6; } +ac_exeext=$ac_cv_exeext + +rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out +ac_clean_files=$ac_clean_files_save +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 +$as_echo_n "checking for suffix of executables... " >&6; } +if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + # If both `conftest.exe' and `conftest' are `present' (well, observable) +# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will +# work properly (i.e., refer to `conftest.exe'), while it won't with +# `rm'. +for ac_file in conftest.exe conftest conftest.*; do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; + *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + break;; + * ) break;; + esac +done +else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot compute suffix of executables: cannot compile and link +See \`config.log' for more details" "$LINENO" 5; } +fi +rm -f conftest conftest$ac_cv_exeext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 +$as_echo "$ac_cv_exeext" >&6; } + +rm -f conftest.$ac_ext +EXEEXT=$ac_cv_exeext +ac_exeext=$EXEEXT +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ +FILE *f = fopen ("conftest.out", "w"); + return ferror (f) || fclose (f) != 0; + + ; + return 0; +} +_ACEOF +ac_clean_files="$ac_clean_files conftest.out" +# Check that the compiler produces executables we can run. If not, either +# the compiler is broken, or we cross compile. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 +$as_echo_n "checking whether we are cross compiling... " >&6; } +if test "$cross_compiling" != yes; then + { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + if { ac_try='./conftest$ac_cv_exeext' + { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then + cross_compiling=no + else + if test "$cross_compiling" = maybe; then + cross_compiling=yes + else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot run C compiled programs. +If you meant to cross compile, use \`--host'. +See \`config.log' for more details" "$LINENO" 5; } + fi + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 +$as_echo "$cross_compiling" >&6; } + +rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out +ac_clean_files=$ac_clean_files_save +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 +$as_echo_n "checking for suffix of object files... " >&6; } +if ${ac_cv_objext+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.o conftest.obj +if { { ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compile") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + for ac_file in conftest.o conftest.obj conftest.*; do + test -f "$ac_file" || continue; + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; + *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` + break;; + esac +done +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot compute suffix of object files: cannot compile +See \`config.log' for more details" "$LINENO" 5; } +fi +rm -f conftest.$ac_cv_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 +$as_echo "$ac_cv_objext" >&6; } +OBJEXT=$ac_cv_objext +ac_objext=$OBJEXT +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 +$as_echo_n "checking whether we are using the GNU C compiler... " >&6; } +if ${ac_cv_c_compiler_gnu+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_compiler_gnu=yes +else + ac_compiler_gnu=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +ac_cv_c_compiler_gnu=$ac_compiler_gnu + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 +$as_echo "$ac_cv_c_compiler_gnu" >&6; } +if test $ac_compiler_gnu = yes; then + GCC=yes +else + GCC= +fi +ac_test_CFLAGS=${CFLAGS+set} +ac_save_CFLAGS=$CFLAGS +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 +$as_echo_n "checking whether $CC accepts -g... " >&6; } +if ${ac_cv_prog_cc_g+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_save_c_werror_flag=$ac_c_werror_flag + ac_c_werror_flag=yes + ac_cv_prog_cc_g=no + CFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_g=yes +else + CFLAGS="" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + +else + ac_c_werror_flag=$ac_save_c_werror_flag + CFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_g=yes +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_c_werror_flag=$ac_save_c_werror_flag +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 +$as_echo "$ac_cv_prog_cc_g" >&6; } +if test "$ac_test_CFLAGS" = set; then + CFLAGS=$ac_save_CFLAGS +elif test $ac_cv_prog_cc_g = yes; then + if test "$GCC" = yes; then + CFLAGS="-g -O2" + else + CFLAGS="-g" + fi +else + if test "$GCC" = yes; then + CFLAGS="-O2" + else + CFLAGS= + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 +$as_echo_n "checking for $CC option to accept ISO C89... " >&6; } +if ${ac_cv_prog_cc_c89+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_prog_cc_c89=no +ac_save_CC=$CC +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +struct stat; +/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ +struct buf { int x; }; +FILE * (*rcsopen) (struct buf *, struct stat *, int); +static char *e (p, i) + char **p; + int i; +{ + return p[i]; +} +static char *f (char * (*g) (char **, int), char **p, ...) +{ + char *s; + va_list v; + va_start (v,p); + s = g (p, va_arg (v,int)); + va_end (v); + return s; +} + +/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has + function prototypes and stuff, but not '\xHH' hex character constants. + These don't provoke an error unfortunately, instead are silently treated + as 'x'. The following induces an error, until -std is added to get + proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an + array size at least. It's necessary to write '\x00'==0 to get something + that's true only with -std. */ +int osf4_cc_array ['\x00' == 0 ? 1 : -1]; + +/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters + inside strings and character constants. */ +#define FOO(x) 'x' +int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; + +int test (int i, double x); +struct s1 {int (*f) (int a);}; +struct s2 {int (*f) (double a);}; +int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); +int argc; +char **argv; +int +main () +{ +return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; + ; + return 0; +} +_ACEOF +for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ + -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" +do + CC="$ac_save_CC $ac_arg" + if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_c89=$ac_arg +fi +rm -f core conftest.err conftest.$ac_objext + test "x$ac_cv_prog_cc_c89" != "xno" && break +done +rm -f conftest.$ac_ext +CC=$ac_save_CC + +fi +# AC_CACHE_VAL +case "x$ac_cv_prog_cc_c89" in + x) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 +$as_echo "none needed" >&6; } ;; + xno) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 +$as_echo "unsupported" >&6; } ;; + *) + CC="$CC $ac_cv_prog_cc_c89" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 +$as_echo "$ac_cv_prog_cc_c89" >&6; } ;; +esac +if test "x$ac_cv_prog_cc_c89" != xno; then : + +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +# check for a number of CFLAGS that make development easier + +# CITUSAC_PROG_CC_CFLAGS_OPT +# ----------------------- +# Given a string, check if the compiler supports the string as a +# command-line option. If it does, add the string to CFLAGS. +# CITUSAC_PROG_CC_CFLAGS_OPT + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC supports -Wall" >&5 +$as_echo_n "checking whether $CC supports -Wall... " >&6; } +if ${citusac_cv_prog_cc_cflags__Wall+:} false; then : + $as_echo_n "(cached) " >&6 +else + citusac_save_CFLAGS=$CFLAGS +CFLAGS="$citusac_save_CFLAGS -Wall" +ac_save_c_werror_flag=$ac_c_werror_flag +ac_c_werror_flag=yes +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + citusac_cv_prog_cc_cflags__Wall=yes +else + citusac_cv_prog_cc_cflags__Wall=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +ac_c_werror_flag=$ac_save_c_werror_flag +CFLAGS="$citusac_save_CFLAGS" +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $citusac_cv_prog_cc_cflags__Wall" >&5 +$as_echo "$citusac_cv_prog_cc_cflags__Wall" >&6; } +if test x"$citusac_cv_prog_cc_cflags__Wall" = x"yes"; then + CITUS_CFLAGS="$CITUS_CFLAGS -Wall" +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC supports -Wextra" >&5 +$as_echo_n "checking whether $CC supports -Wextra... " >&6; } +if ${citusac_cv_prog_cc_cflags__Wextra+:} false; then : + $as_echo_n "(cached) " >&6 +else + citusac_save_CFLAGS=$CFLAGS +CFLAGS="$citusac_save_CFLAGS -Wextra" +ac_save_c_werror_flag=$ac_c_werror_flag +ac_c_werror_flag=yes +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + citusac_cv_prog_cc_cflags__Wextra=yes +else + citusac_cv_prog_cc_cflags__Wextra=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +ac_c_werror_flag=$ac_save_c_werror_flag +CFLAGS="$citusac_save_CFLAGS" +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $citusac_cv_prog_cc_cflags__Wextra" >&5 +$as_echo "$citusac_cv_prog_cc_cflags__Wextra" >&6; } +if test x"$citusac_cv_prog_cc_cflags__Wextra" = x"yes"; then + CITUS_CFLAGS="$CITUS_CFLAGS -Wextra" +fi + +# disarm options included in the above, which are too noisy for now +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC supports -Wno-unused-parameter" >&5 +$as_echo_n "checking whether $CC supports -Wno-unused-parameter... " >&6; } +if ${citusac_cv_prog_cc_cflags__Wno_unused_parameter+:} false; then : + $as_echo_n "(cached) " >&6 +else + citusac_save_CFLAGS=$CFLAGS +CFLAGS="$citusac_save_CFLAGS -Wno-unused-parameter" +ac_save_c_werror_flag=$ac_c_werror_flag +ac_c_werror_flag=yes +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + citusac_cv_prog_cc_cflags__Wno_unused_parameter=yes +else + citusac_cv_prog_cc_cflags__Wno_unused_parameter=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +ac_c_werror_flag=$ac_save_c_werror_flag +CFLAGS="$citusac_save_CFLAGS" +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $citusac_cv_prog_cc_cflags__Wno_unused_parameter" >&5 +$as_echo "$citusac_cv_prog_cc_cflags__Wno_unused_parameter" >&6; } +if test x"$citusac_cv_prog_cc_cflags__Wno_unused_parameter" = x"yes"; then + CITUS_CFLAGS="$CITUS_CFLAGS -Wno-unused-parameter" +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC supports -Wno-sign-compare" >&5 +$as_echo_n "checking whether $CC supports -Wno-sign-compare... " >&6; } +if ${citusac_cv_prog_cc_cflags__Wno_sign_compare+:} false; then : + $as_echo_n "(cached) " >&6 +else + citusac_save_CFLAGS=$CFLAGS +CFLAGS="$citusac_save_CFLAGS -Wno-sign-compare" +ac_save_c_werror_flag=$ac_c_werror_flag +ac_c_werror_flag=yes +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + citusac_cv_prog_cc_cflags__Wno_sign_compare=yes +else + citusac_cv_prog_cc_cflags__Wno_sign_compare=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +ac_c_werror_flag=$ac_save_c_werror_flag +CFLAGS="$citusac_save_CFLAGS" +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $citusac_cv_prog_cc_cflags__Wno_sign_compare" >&5 +$as_echo "$citusac_cv_prog_cc_cflags__Wno_sign_compare" >&6; } +if test x"$citusac_cv_prog_cc_cflags__Wno_sign_compare" = x"yes"; then + CITUS_CFLAGS="$CITUS_CFLAGS -Wno-sign-compare" +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC supports -Wno-missing-field-initializers" >&5 +$as_echo_n "checking whether $CC supports -Wno-missing-field-initializers... " >&6; } +if ${citusac_cv_prog_cc_cflags__Wno_missing_field_initializers+:} false; then : + $as_echo_n "(cached) " >&6 +else + citusac_save_CFLAGS=$CFLAGS +CFLAGS="$citusac_save_CFLAGS -Wno-missing-field-initializers" +ac_save_c_werror_flag=$ac_c_werror_flag +ac_c_werror_flag=yes +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + citusac_cv_prog_cc_cflags__Wno_missing_field_initializers=yes +else + citusac_cv_prog_cc_cflags__Wno_missing_field_initializers=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +ac_c_werror_flag=$ac_save_c_werror_flag +CFLAGS="$citusac_save_CFLAGS" +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $citusac_cv_prog_cc_cflags__Wno_missing_field_initializers" >&5 +$as_echo "$citusac_cv_prog_cc_cflags__Wno_missing_field_initializers" >&6; } +if test x"$citusac_cv_prog_cc_cflags__Wno_missing_field_initializers" = x"yes"; then + CITUS_CFLAGS="$CITUS_CFLAGS -Wno-missing-field-initializers" +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC supports -Wno-clobbered" >&5 +$as_echo_n "checking whether $CC supports -Wno-clobbered... " >&6; } +if ${citusac_cv_prog_cc_cflags__Wno_clobbered+:} false; then : + $as_echo_n "(cached) " >&6 +else + citusac_save_CFLAGS=$CFLAGS +CFLAGS="$citusac_save_CFLAGS -Wno-clobbered" +ac_save_c_werror_flag=$ac_c_werror_flag +ac_c_werror_flag=yes +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + citusac_cv_prog_cc_cflags__Wno_clobbered=yes +else + citusac_cv_prog_cc_cflags__Wno_clobbered=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +ac_c_werror_flag=$ac_save_c_werror_flag +CFLAGS="$citusac_save_CFLAGS" +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $citusac_cv_prog_cc_cflags__Wno_clobbered" >&5 +$as_echo "$citusac_cv_prog_cc_cflags__Wno_clobbered" >&6; } +if test x"$citusac_cv_prog_cc_cflags__Wno_clobbered" = x"yes"; then + CITUS_CFLAGS="$CITUS_CFLAGS -Wno-clobbered" +fi + +# And add a few extra warnings +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC supports -Wdeclaration-after-statement" >&5 +$as_echo_n "checking whether $CC supports -Wdeclaration-after-statement... " >&6; } +if ${citusac_cv_prog_cc_cflags__Wdeclaration_after_statement+:} false; then : + $as_echo_n "(cached) " >&6 +else + citusac_save_CFLAGS=$CFLAGS +CFLAGS="$citusac_save_CFLAGS -Wdeclaration-after-statement" +ac_save_c_werror_flag=$ac_c_werror_flag +ac_c_werror_flag=yes +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + citusac_cv_prog_cc_cflags__Wdeclaration_after_statement=yes +else + citusac_cv_prog_cc_cflags__Wdeclaration_after_statement=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +ac_c_werror_flag=$ac_save_c_werror_flag +CFLAGS="$citusac_save_CFLAGS" +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $citusac_cv_prog_cc_cflags__Wdeclaration_after_statement" >&5 +$as_echo "$citusac_cv_prog_cc_cflags__Wdeclaration_after_statement" >&6; } +if test x"$citusac_cv_prog_cc_cflags__Wdeclaration_after_statement" = x"yes"; then + CITUS_CFLAGS="$CITUS_CFLAGS -Wdeclaration-after-statement" +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC supports -Wendif-labels" >&5 +$as_echo_n "checking whether $CC supports -Wendif-labels... " >&6; } +if ${citusac_cv_prog_cc_cflags__Wendif_labels+:} false; then : + $as_echo_n "(cached) " >&6 +else + citusac_save_CFLAGS=$CFLAGS +CFLAGS="$citusac_save_CFLAGS -Wendif-labels" +ac_save_c_werror_flag=$ac_c_werror_flag +ac_c_werror_flag=yes +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + citusac_cv_prog_cc_cflags__Wendif_labels=yes +else + citusac_cv_prog_cc_cflags__Wendif_labels=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +ac_c_werror_flag=$ac_save_c_werror_flag +CFLAGS="$citusac_save_CFLAGS" +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $citusac_cv_prog_cc_cflags__Wendif_labels" >&5 +$as_echo "$citusac_cv_prog_cc_cflags__Wendif_labels" >&6; } +if test x"$citusac_cv_prog_cc_cflags__Wendif_labels" = x"yes"; then + CITUS_CFLAGS="$CITUS_CFLAGS -Wendif-labels" +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC supports -Wmissing-format-attribute" >&5 +$as_echo_n "checking whether $CC supports -Wmissing-format-attribute... " >&6; } +if ${citusac_cv_prog_cc_cflags__Wmissing_format_attribute+:} false; then : + $as_echo_n "(cached) " >&6 +else + citusac_save_CFLAGS=$CFLAGS +CFLAGS="$citusac_save_CFLAGS -Wmissing-format-attribute" +ac_save_c_werror_flag=$ac_c_werror_flag +ac_c_werror_flag=yes +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + citusac_cv_prog_cc_cflags__Wmissing_format_attribute=yes +else + citusac_cv_prog_cc_cflags__Wmissing_format_attribute=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +ac_c_werror_flag=$ac_save_c_werror_flag +CFLAGS="$citusac_save_CFLAGS" +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $citusac_cv_prog_cc_cflags__Wmissing_format_attribute" >&5 +$as_echo "$citusac_cv_prog_cc_cflags__Wmissing_format_attribute" >&6; } +if test x"$citusac_cv_prog_cc_cflags__Wmissing_format_attribute" = x"yes"; then + CITUS_CFLAGS="$CITUS_CFLAGS -Wmissing-format-attribute" +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC supports -Wmissing-declarations" >&5 +$as_echo_n "checking whether $CC supports -Wmissing-declarations... " >&6; } +if ${citusac_cv_prog_cc_cflags__Wmissing_declarations+:} false; then : + $as_echo_n "(cached) " >&6 +else + citusac_save_CFLAGS=$CFLAGS +CFLAGS="$citusac_save_CFLAGS -Wmissing-declarations" +ac_save_c_werror_flag=$ac_c_werror_flag +ac_c_werror_flag=yes +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + citusac_cv_prog_cc_cflags__Wmissing_declarations=yes +else + citusac_cv_prog_cc_cflags__Wmissing_declarations=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +ac_c_werror_flag=$ac_save_c_werror_flag +CFLAGS="$citusac_save_CFLAGS" +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $citusac_cv_prog_cc_cflags__Wmissing_declarations" >&5 +$as_echo "$citusac_cv_prog_cc_cflags__Wmissing_declarations" >&6; } +if test x"$citusac_cv_prog_cc_cflags__Wmissing_declarations" = x"yes"; then + CITUS_CFLAGS="$CITUS_CFLAGS -Wmissing-declarations" +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC supports -Wmissing-prototypes" >&5 +$as_echo_n "checking whether $CC supports -Wmissing-prototypes... " >&6; } +if ${citusac_cv_prog_cc_cflags__Wmissing_prototypes+:} false; then : + $as_echo_n "(cached) " >&6 +else + citusac_save_CFLAGS=$CFLAGS +CFLAGS="$citusac_save_CFLAGS -Wmissing-prototypes" +ac_save_c_werror_flag=$ac_c_werror_flag +ac_c_werror_flag=yes +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + citusac_cv_prog_cc_cflags__Wmissing_prototypes=yes +else + citusac_cv_prog_cc_cflags__Wmissing_prototypes=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +ac_c_werror_flag=$ac_save_c_werror_flag +CFLAGS="$citusac_save_CFLAGS" +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $citusac_cv_prog_cc_cflags__Wmissing_prototypes" >&5 +$as_echo "$citusac_cv_prog_cc_cflags__Wmissing_prototypes" >&6; } +if test x"$citusac_cv_prog_cc_cflags__Wmissing_prototypes" = x"yes"; then + CITUS_CFLAGS="$CITUS_CFLAGS -Wmissing-prototypes" +fi + + +CITUS_CFLAGS="$CITUS_CFLAGS" + + +ac_config_files="$ac_config_files Makefile.global" + +ac_config_headers="$ac_config_headers src/include/citusdb_config.h" + + +cat >confcache <<\_ACEOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs, see configure's option --config-cache. +# It is not useful on other systems. If it contains results you don't +# want to keep, you may remove or edit it. +# +# config.status only pays attention to the cache file if you give it +# the --recheck option to rerun configure. +# +# `ac_cv_env_foo' variables (set or unset) will be overridden when +# loading this file, other *unset* `ac_cv_foo' will be assigned the +# following values. + +_ACEOF + +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, we kill variables containing newlines. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +( + for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 +$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( + *) { eval $ac_var=; unset $ac_var;} ;; + esac ;; + esac + done + + (set) 2>&1 | + case $as_nl`(ac_space=' '; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + # `set' does not quote correctly, so add quotes: double-quote + # substitution turns \\\\ into \\, and sed turns \\ into \. + sed -n \ + "s/'/'\\\\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" + ;; #( + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) | + sed ' + /^ac_cv_env_/b end + t clear + :clear + s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ + t end + s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ + :end' >>confcache +if diff "$cache_file" confcache >/dev/null 2>&1; then :; else + if test -w "$cache_file"; then + if test "x$cache_file" != "x/dev/null"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 +$as_echo "$as_me: updating cache $cache_file" >&6;} + if test ! -f "$cache_file" || test -h "$cache_file"; then + cat confcache >"$cache_file" + else + case $cache_file in #( + */* | ?:*) + mv -f confcache "$cache_file"$$ && + mv -f "$cache_file"$$ "$cache_file" ;; #( + *) + mv -f confcache "$cache_file" ;; + esac + fi + fi + else + { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 +$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} + fi +fi +rm -f confcache + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +DEFS=-DHAVE_CONFIG_H + +ac_libobjs= +ac_ltlibobjs= +U= +for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue + # 1. Remove the extension, and $U if already installed. + ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' + ac_i=`$as_echo "$ac_i" | sed "$ac_script"` + # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR + # will be set to the directory where LIBOBJS objects are built. + as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" + as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' +done +LIBOBJS=$ac_libobjs + +LTLIBOBJS=$ac_ltlibobjs + + + +: "${CONFIG_STATUS=./config.status}" +ac_write_fail=0 +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files $CONFIG_STATUS" +{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 +$as_echo "$as_me: creating $CONFIG_STATUS" >&6;} +as_write_fail=0 +cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 +#! $SHELL +# Generated by $as_me. +# Run this file to recreate the current configuration. +# Compiler output produced by configure, useful for debugging +# configure, is in config.log if it exists. + +debug=false +ac_cs_recheck=false +ac_cs_silent=false + +SHELL=\${CONFIG_SHELL-$SHELL} +export SHELL +_ASEOF +cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 +## -------------------- ## +## M4sh Initialization. ## +## -------------------- ## + +# Be more Bourne compatible +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi + + +as_nl=' +' +export as_nl +# Printing a long string crashes Solaris 7 /usr/bin/printf. +as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo +# Prefer a ksh shell builtin over an external printf program on Solaris, +# but without wasting forks for bash or zsh. +if test -z "$BASH_VERSION$ZSH_VERSION" \ + && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='print -r --' + as_echo_n='print -rn --' +elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='printf %s\n' + as_echo_n='printf %s' +else + if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then + as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' + as_echo_n='/usr/ucb/echo -n' + else + as_echo_body='eval expr "X$1" : "X\\(.*\\)"' + as_echo_n_body='eval + arg=$1; + case $arg in #( + *"$as_nl"*) + expr "X$arg" : "X\\(.*\\)$as_nl"; + arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; + esac; + expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" + ' + export as_echo_n_body + as_echo_n='sh -c $as_echo_n_body as_echo' + fi + export as_echo_body + as_echo='sh -c $as_echo_body as_echo' +fi + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +as_myself= +case $0 in #(( + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break + done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + exit 1 +fi + +# Unset variables that we do not need and which cause bugs (e.g. in +# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" +# suppresses any "Segmentation fault" message there. '((' could +# trigger a bug in pdksh 5.2.14. +for as_var in BASH_ENV ENV MAIL MAILPATH +do eval test x\${$as_var+set} = xset \ + && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +LC_ALL=C +export LC_ALL +LANGUAGE=C +export LANGUAGE + +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + + +# as_fn_error STATUS ERROR [LINENO LOG_FD] +# ---------------------------------------- +# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are +# provided, also output the error to LOG_FD, referencing LINENO. Then exit the +# script with STATUS, using 1 if that was 0. +as_fn_error () +{ + as_status=$1; test $as_status -eq 0 && as_status=1 + if test "$4"; then + as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 + fi + $as_echo "$as_me: error: $2" >&2 + as_fn_exit $as_status +} # as_fn_error + + +# as_fn_set_status STATUS +# ----------------------- +# Set $? to STATUS, without forking. +as_fn_set_status () +{ + return $1 +} # as_fn_set_status + +# as_fn_exit STATUS +# ----------------- +# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. +as_fn_exit () +{ + set +e + as_fn_set_status $1 + exit $1 +} # as_fn_exit + +# as_fn_unset VAR +# --------------- +# Portably unset VAR. +as_fn_unset () +{ + { eval $1=; unset $1;} +} +as_unset=as_fn_unset +# as_fn_append VAR VALUE +# ---------------------- +# Append the text in VALUE to the end of the definition contained in VAR. Take +# advantage of any shell optimizations that allow amortized linear growth over +# repeated appends, instead of the typical quadratic growth present in naive +# implementations. +if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : + eval 'as_fn_append () + { + eval $1+=\$2 + }' +else + as_fn_append () + { + eval $1=\$$1\$2 + } +fi # as_fn_append + +# as_fn_arith ARG... +# ------------------ +# Perform arithmetic evaluation on the ARGs, and store the result in the +# global $as_val. Take advantage of shells that can avoid forks. The arguments +# must be portable across $(()) and expr. +if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : + eval 'as_fn_arith () + { + as_val=$(( $* )) + }' +else + as_fn_arith () + { + as_val=`expr "$@" || test $? -eq 1` + } +fi # as_fn_arith + + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in #((((( +-n*) + case `echo 'xy\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + xy) ECHO_C='\c';; + *) echo `echo ksh88 bug on AIX 6.1` > /dev/null + ECHO_T=' ';; + esac;; +*) + ECHO_N='-n';; +esac + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir 2>/dev/null +fi +if (echo >conf$$.file) 2>/dev/null; then + if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -pR'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -pR' + elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln + else + as_ln_s='cp -pR' + fi +else + as_ln_s='cp -pR' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + + +# as_fn_mkdir_p +# ------------- +# Create "$as_dir" as a directory, including parents if necessary. +as_fn_mkdir_p () +{ + + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || eval $as_mkdir_p || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" + + +} # as_fn_mkdir_p +if mkdir -p . 2>/dev/null; then + as_mkdir_p='mkdir -p "$as_dir"' +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + + +# as_fn_executable_p FILE +# ----------------------- +# Test if FILE is an executable regular file. +as_fn_executable_p () +{ + test -f "$1" && test -x "$1" +} # as_fn_executable_p +as_test_x='test -x' +as_executable_p=as_fn_executable_p + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + +exec 6>&1 +## ----------------------------------- ## +## Main body of $CONFIG_STATUS script. ## +## ----------------------------------- ## +_ASEOF +test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# Save the log message, to keep $0 and so on meaningful, and to +# report actual input values of CONFIG_FILES etc. instead of their +# values after options handling. +ac_log=" +This file was extended by CitusDB $as_me 5.0, which was +generated by GNU Autoconf 2.69. Invocation command line was + + CONFIG_FILES = $CONFIG_FILES + CONFIG_HEADERS = $CONFIG_HEADERS + CONFIG_LINKS = $CONFIG_LINKS + CONFIG_COMMANDS = $CONFIG_COMMANDS + $ $0 $@ + +on `(hostname || uname -n) 2>/dev/null | sed 1q` +" + +_ACEOF + +case $ac_config_files in *" +"*) set x $ac_config_files; shift; ac_config_files=$*;; +esac + +case $ac_config_headers in *" +"*) set x $ac_config_headers; shift; ac_config_headers=$*;; +esac + + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +# Files that config.status was made for. +config_files="$ac_config_files" +config_headers="$ac_config_headers" + +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +ac_cs_usage="\ +\`$as_me' instantiates files and other configuration actions +from templates according to the current configuration. Unless the files +and actions are specified as TAGs, all are instantiated by default. + +Usage: $0 [OPTION]... [TAG]... + + -h, --help print this help, then exit + -V, --version print version number and configuration settings, then exit + --config print configuration, then exit + -q, --quiet, --silent + do not print progress messages + -d, --debug don't remove temporary files + --recheck update $as_me by reconfiguring in the same conditions + --file=FILE[:TEMPLATE] + instantiate the configuration file FILE + --header=FILE[:TEMPLATE] + instantiate the configuration header FILE + +Configuration files: +$config_files + +Configuration headers: +$config_headers + +Report bugs to the package provider." + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" +ac_cs_version="\\ +CitusDB config.status 5.0 +configured by $0, generated by GNU Autoconf 2.69, + with options \\"\$ac_cs_config\\" + +Copyright (C) 2012 Free Software Foundation, Inc. +This config.status script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it." + +ac_pwd='$ac_pwd' +srcdir='$srcdir' +test -n "\$AWK" || AWK=awk +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# The default lists apply if the user does not specify any file. +ac_need_defaults=: +while test $# != 0 +do + case $1 in + --*=?*) + ac_option=`expr "X$1" : 'X\([^=]*\)='` + ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` + ac_shift=: + ;; + --*=) + ac_option=`expr "X$1" : 'X\([^=]*\)='` + ac_optarg= + ac_shift=: + ;; + *) + ac_option=$1 + ac_optarg=$2 + ac_shift=shift + ;; + esac + + case $ac_option in + # Handling of the options. + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + ac_cs_recheck=: ;; + --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) + $as_echo "$ac_cs_version"; exit ;; + --config | --confi | --conf | --con | --co | --c ) + $as_echo "$ac_cs_config"; exit ;; + --debug | --debu | --deb | --de | --d | -d ) + debug=: ;; + --file | --fil | --fi | --f ) + $ac_shift + case $ac_optarg in + *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; + '') as_fn_error $? "missing file argument" ;; + esac + as_fn_append CONFIG_FILES " '$ac_optarg'" + ac_need_defaults=false;; + --header | --heade | --head | --hea ) + $ac_shift + case $ac_optarg in + *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + as_fn_append CONFIG_HEADERS " '$ac_optarg'" + ac_need_defaults=false;; + --he | --h) + # Conflict between --help and --header + as_fn_error $? "ambiguous option: \`$1' +Try \`$0 --help' for more information.";; + --help | --hel | -h ) + $as_echo "$ac_cs_usage"; exit ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil | --si | --s) + ac_cs_silent=: ;; + + # This is an error. + -*) as_fn_error $? "unrecognized option: \`$1' +Try \`$0 --help' for more information." ;; + + *) as_fn_append ac_config_targets " $1" + ac_need_defaults=false ;; + + esac + shift +done + +ac_configure_extra_args= + +if $ac_cs_silent; then + exec 6>/dev/null + ac_configure_extra_args="$ac_configure_extra_args --silent" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +if \$ac_cs_recheck; then + set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion + shift + \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 + CONFIG_SHELL='$SHELL' + export CONFIG_SHELL + exec "\$@" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +exec 5>>config.log +{ + echo + sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX +## Running $as_me. ## +_ASBOX + $as_echo "$ac_log" +} >&5 + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 + +# Handling of arguments. +for ac_config_target in $ac_config_targets +do + case $ac_config_target in + "Makefile.global") CONFIG_FILES="$CONFIG_FILES Makefile.global" ;; + "src/include/citusdb_config.h") CONFIG_HEADERS="$CONFIG_HEADERS src/include/citusdb_config.h" ;; + + *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; + esac +done + + +# If the user did not use the arguments to specify the items to instantiate, +# then the envvar interface is used. Set only those that are not. +# We use the long form for the default assignment because of an extremely +# bizarre bug on SunOS 4.1.3. +if $ac_need_defaults; then + test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files + test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers +fi + +# Have a temporary directory for convenience. Make it in the build tree +# simply because there is no reason against having it here, and in addition, +# creating and moving files from /tmp can sometimes cause problems. +# Hook for its removal unless debugging. +# Note that there is a small window in which the directory will not be cleaned: +# after its creation but before its name has been assigned to `$tmp'. +$debug || +{ + tmp= ac_tmp= + trap 'exit_status=$? + : "${ac_tmp:=$tmp}" + { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status +' 0 + trap 'as_fn_exit 1' 1 2 13 15 +} +# Create a (secure) tmp directory for tmp files. + +{ + tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && + test -d "$tmp" +} || +{ + tmp=./conf$$-$RANDOM + (umask 077 && mkdir "$tmp") +} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 +ac_tmp=$tmp + +# Set up the scripts for CONFIG_FILES section. +# No need to generate them if there are no CONFIG_FILES. +# This happens for instance with `./config.status config.h'. +if test -n "$CONFIG_FILES"; then + + +ac_cr=`echo X | tr X '\015'` +# On cygwin, bash can eat \r inside `` if the user requested igncr. +# But we know of no other shell where ac_cr would be empty at this +# point, so we can use a bashism as a fallback. +if test "x$ac_cr" = x; then + eval ac_cr=\$\'\\r\' +fi +ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` +if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then + ac_cs_awk_cr='\\r' +else + ac_cs_awk_cr=$ac_cr +fi + +echo 'BEGIN {' >"$ac_tmp/subs1.awk" && +_ACEOF + + +{ + echo "cat >conf$$subs.awk <<_ACEOF" && + echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && + echo "_ACEOF" +} >conf$$subs.sh || + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 +ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` +ac_delim='%!_!# ' +for ac_last_try in false false false false false :; do + . ./conf$$subs.sh || + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 + + ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` + if test $ac_delim_n = $ac_delim_num; then + break + elif $ac_last_try; then + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 + else + ac_delim="$ac_delim!$ac_delim _$ac_delim!! " + fi +done +rm -f conf$$subs.sh + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && +_ACEOF +sed -n ' +h +s/^/S["/; s/!.*/"]=/ +p +g +s/^[^!]*!// +:repl +t repl +s/'"$ac_delim"'$// +t delim +:nl +h +s/\(.\{148\}\)..*/\1/ +t more1 +s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ +p +n +b repl +:more1 +s/["\\]/\\&/g; s/^/"/; s/$/"\\/ +p +g +s/.\{148\}// +t nl +:delim +h +s/\(.\{148\}\)..*/\1/ +t more2 +s/["\\]/\\&/g; s/^/"/; s/$/"/ +p +b +:more2 +s/["\\]/\\&/g; s/^/"/; s/$/"\\/ +p +g +s/.\{148\}// +t delim +' >$CONFIG_STATUS || ac_write_fail=1 +rm -f conf$$subs.awk +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +_ACAWK +cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && + for (key in S) S_is_set[key] = 1 + FS = "" + +} +{ + line = $ 0 + nfields = split(line, field, "@") + substed = 0 + len = length(field[1]) + for (i = 2; i < nfields; i++) { + key = field[i] + keylen = length(key) + if (S_is_set[key]) { + value = S[key] + line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) + len += length(value) + length(field[++i]) + substed = 1 + } else + len += 1 + keylen + } + + print line +} + +_ACAWK +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then + sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" +else + cat +fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ + || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 +_ACEOF + +# VPATH may cause trouble with some makes, so we remove sole $(srcdir), +# ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and +# trailing colons and then remove the whole line if VPATH becomes empty +# (actually we leave an empty line to preserve line numbers). +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{ +h +s/// +s/^/:/ +s/[ ]*$/:/ +s/:\$(srcdir):/:/g +s/:\${srcdir}:/:/g +s/:@srcdir@:/:/g +s/^:*// +s/:*$// +x +s/\(=[ ]*\).*/\1/ +G +s/\n// +s/^[^=]*=[ ]*$// +}' +fi + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +fi # test -n "$CONFIG_FILES" + +# Set up the scripts for CONFIG_HEADERS section. +# No need to generate them if there are no CONFIG_HEADERS. +# This happens for instance with `./config.status Makefile'. +if test -n "$CONFIG_HEADERS"; then +cat >"$ac_tmp/defines.awk" <<\_ACAWK || +BEGIN { +_ACEOF + +# Transform confdefs.h into an awk script `defines.awk', embedded as +# here-document in config.status, that substitutes the proper values into +# config.h.in to produce config.h. + +# Create a delimiter string that does not exist in confdefs.h, to ease +# handling of long lines. +ac_delim='%!_!# ' +for ac_last_try in false false :; do + ac_tt=`sed -n "/$ac_delim/p" confdefs.h` + if test -z "$ac_tt"; then + break + elif $ac_last_try; then + as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5 + else + ac_delim="$ac_delim!$ac_delim _$ac_delim!! " + fi +done + +# For the awk script, D is an array of macro values keyed by name, +# likewise P contains macro parameters if any. Preserve backslash +# newline sequences. + +ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]* +sed -n ' +s/.\{148\}/&'"$ac_delim"'/g +t rset +:rset +s/^[ ]*#[ ]*define[ ][ ]*/ / +t def +d +:def +s/\\$// +t bsnl +s/["\\]/\\&/g +s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ +D["\1"]=" \3"/p +s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2"/p +d +:bsnl +s/["\\]/\\&/g +s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ +D["\1"]=" \3\\\\\\n"\\/p +t cont +s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p +t cont +d +:cont +n +s/.\{148\}/&'"$ac_delim"'/g +t clear +:clear +s/\\$// +t bsnlc +s/["\\]/\\&/g; s/^/"/; s/$/"/p +d +:bsnlc +s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p +b cont +' >$CONFIG_STATUS || ac_write_fail=1 + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 + for (key in D) D_is_set[key] = 1 + FS = "" +} +/^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ { + line = \$ 0 + split(line, arg, " ") + if (arg[1] == "#") { + defundef = arg[2] + mac1 = arg[3] + } else { + defundef = substr(arg[1], 2) + mac1 = arg[2] + } + split(mac1, mac2, "(") #) + macro = mac2[1] + prefix = substr(line, 1, index(line, defundef) - 1) + if (D_is_set[macro]) { + # Preserve the white space surrounding the "#". + print prefix "define", macro P[macro] D[macro] + next + } else { + # Replace #undef with comments. This is necessary, for example, + # in the case of _POSIX_SOURCE, which is predefined and required + # on some systems where configure will not decide to define it. + if (defundef == "undef") { + print "/*", prefix defundef, macro, "*/" + next + } + } +} +{ print } +_ACAWK +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 + as_fn_error $? "could not setup config headers machinery" "$LINENO" 5 +fi # test -n "$CONFIG_HEADERS" + + +eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS " +shift +for ac_tag +do + case $ac_tag in + :[FHLC]) ac_mode=$ac_tag; continue;; + esac + case $ac_mode$ac_tag in + :[FHL]*:*);; + :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; + :[FH]-) ac_tag=-:-;; + :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; + esac + ac_save_IFS=$IFS + IFS=: + set x $ac_tag + IFS=$ac_save_IFS + shift + ac_file=$1 + shift + + case $ac_mode in + :L) ac_source=$1;; + :[FH]) + ac_file_inputs= + for ac_f + do + case $ac_f in + -) ac_f="$ac_tmp/stdin";; + *) # Look for the file first in the build tree, then in the source tree + # (if the path is not absolute). The absolute path cannot be DOS-style, + # because $ac_f cannot contain `:'. + test -f "$ac_f" || + case $ac_f in + [\\/$]*) false;; + *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; + esac || + as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; + esac + case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac + as_fn_append ac_file_inputs " '$ac_f'" + done + + # Let's still pretend it is `configure' which instantiates (i.e., don't + # use $as_me), people would be surprised to read: + # /* config.h. Generated by config.status. */ + configure_input='Generated from '` + $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' + `' by configure.' + if test x"$ac_file" != x-; then + configure_input="$ac_file. $configure_input" + { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 +$as_echo "$as_me: creating $ac_file" >&6;} + fi + # Neutralize special characters interpreted by sed in replacement strings. + case $configure_input in #( + *\&* | *\|* | *\\* ) + ac_sed_conf_input=`$as_echo "$configure_input" | + sed 's/[\\\\&|]/\\\\&/g'`;; #( + *) ac_sed_conf_input=$configure_input;; + esac + + case $ac_tag in + *:-:* | *:-) cat >"$ac_tmp/stdin" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; + esac + ;; + esac + + ac_dir=`$as_dirname -- "$ac_file" || +$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$ac_file" : 'X\(//\)[^/]' \| \ + X"$ac_file" : 'X\(//\)$' \| \ + X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$ac_file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + as_dir="$ac_dir"; as_fn_mkdir_p + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + + case $ac_mode in + :F) + # + # CONFIG_FILE + # + +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# If the template does not know about datarootdir, expand it. +# FIXME: This hack should be removed a few years after 2.60. +ac_datarootdir_hack=; ac_datarootdir_seen= +ac_sed_dataroot=' +/datarootdir/ { + p + q +} +/@datadir@/p +/@docdir@/p +/@infodir@/p +/@localedir@/p +/@mandir@/p' +case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in +*datarootdir*) ac_datarootdir_seen=yes;; +*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 +$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 + ac_datarootdir_hack=' + s&@datadir@&$datadir&g + s&@docdir@&$docdir&g + s&@infodir@&$infodir&g + s&@localedir@&$localedir&g + s&@mandir@&$mandir&g + s&\\\${datarootdir}&$datarootdir&g' ;; +esac +_ACEOF + +# Neutralize VPATH when `$srcdir' = `.'. +# Shell code in configure.ac might set extrasub. +# FIXME: do we really want to maintain this feature? +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +ac_sed_extra="$ac_vpsub +$extrasub +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +:t +/@[a-zA-Z_][a-zA-Z_0-9]*@/!b +s|@configure_input@|$ac_sed_conf_input|;t t +s&@top_builddir@&$ac_top_builddir_sub&;t t +s&@top_build_prefix@&$ac_top_build_prefix&;t t +s&@srcdir@&$ac_srcdir&;t t +s&@abs_srcdir@&$ac_abs_srcdir&;t t +s&@top_srcdir@&$ac_top_srcdir&;t t +s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t +s&@builddir@&$ac_builddir&;t t +s&@abs_builddir@&$ac_abs_builddir&;t t +s&@abs_top_builddir@&$ac_abs_top_builddir&;t t +$ac_datarootdir_hack +" +eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ + >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + +test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && + { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && + { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ + "$ac_tmp/out"`; test -z "$ac_out"; } && + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined" >&5 +$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined" >&2;} + + rm -f "$ac_tmp/stdin" + case $ac_file in + -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; + *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; + esac \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + ;; + :H) + # + # CONFIG_HEADER + # + if test x"$ac_file" != x-; then + { + $as_echo "/* $configure_input */" \ + && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" + } >"$ac_tmp/config.h" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then + { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5 +$as_echo "$as_me: $ac_file is unchanged" >&6;} + else + rm -f "$ac_file" + mv "$ac_tmp/config.h" "$ac_file" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + fi + else + $as_echo "/* $configure_input */" \ + && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \ + || as_fn_error $? "could not create -" "$LINENO" 5 + fi + ;; + + + esac + +done # for ac_tag + + +as_fn_exit 0 +_ACEOF +ac_clean_files=$ac_clean_files_save + +test $ac_write_fail = 0 || + as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 + + +# configure is writing to config.log, and then calls config.status. +# config.status does its own redirection, appending to config.log. +# Unfortunately, on DOS this fails, as config.log is still kept open +# by configure, so config.status won't be able to write to it; its +# output is simply discarded. So we exec the FD to /dev/null, +# effectively closing config.log, so it can be properly (re)opened and +# appended to by config.status. When coming back to configure, we +# need to make the FD available again. +if test "$no_create" != yes; then + ac_cs_success=: + ac_config_status_args= + test "$silent" = yes && + ac_config_status_args="$ac_config_status_args --quiet" + exec 5>/dev/null + $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false + exec 5>>config.log + # Use ||, not &&, to avoid exiting from the if with $? = 1, which + # would make configure fail if this is the last instruction. + $ac_cs_success || as_fn_exit 1 +fi +if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 +$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} +fi + diff --git a/configure.in b/configure.in new file mode 100644 index 000000000..b3bacd4cc --- /dev/null +++ b/configure.in @@ -0,0 +1,109 @@ +# CitusDB autoconf input script. +# +# Converted into an actual configure script by autogen.sh. This +# conversion only has to be done when configure.in changes. To avoid +# everyone needing autoconf installed, the resulting files are checked +# into the SCM. + +AC_INIT([CitusDB], [5.0], [], [citusdb], []) +AC_COPYRIGHT([Copyright (c) Copyright (c) 2012-2015, Citus Data, Inc.]) + +AC_PROG_SED + +# Locate pg_config binary +AC_ARG_VAR([PG_CONFIG], [Location to find pg_config for target PostgreSQL instalation (default PATH)]) +AC_ARG_VAR([PATH], [PATH for target PostgreSQL install pg_config]) + +if test -z "$PG_CONFIG"; then + AC_PATH_PROG(PG_CONFIG, pg_config) +fi + +if test -z "$PG_CONFIG"; then + AC_MSG_ERROR([Could not find pg_config. Set PG_CONFIG or PATH.]) +fi + +# check we're building against a supported version of PostgreSQL +citusac_pg_config_version=$($PG_CONFIG --version 2>/dev/null) +version_num=$(echo "$citusac_pg_config_version"| + $SED -e 's/^PostgreSQL \([[0-9]]*\)\.\([[0-9]]*\)\([[a-zA-Z0-9.]]*\)$/\1.\2/') + +if test -z "$version_num"; then + AC_MSG_ERROR([Could not detect PostgreSQL version from pg_config.]) +fi + +if test "$version_num" != '9.4' -a "$version_num" != '9.5'; then + AC_MSG_ERROR([CitusDB is not compatible with the detected PostgreSQL version ${version_num}.]) +else + AC_MSG_NOTICE([building against PostgreSQL $version_num]) +fi; + +# Check whether we're building inside the source tree, if not, prepare +# the build directory. +if test "$srcdir" -ef '.' ; then + vpath_build=no +else + vpath_build=yes + _AS_ECHO_N([preparing build tree... ]) + citusac_abs_top_srcdir=`cd "$srcdir" && pwd` + $SHELL "$citusac_abs_top_srcdir/prep_buildtree" "$citusac_abs_top_srcdir" "." \ + || AC_MSG_ERROR(failed) + AC_MSG_RESULT(done) +fi +AC_SUBST(vpath_build) + +# Allow to overwrite the C compiler, default to the one postgres was +# compiled with +AC_PROG_CC([$($PG_CONFIG --cc)]) + +# check for a number of CFLAGS that make development easier + +# CITUSAC_PROG_CC_CFLAGS_OPT +# ----------------------- +# Given a string, check if the compiler supports the string as a +# command-line option. If it does, add the string to CFLAGS. +AC_DEFUN([CITUSAC_PROG_CC_CFLAGS_OPT], +[define([Ac_cachevar], [AS_TR_SH([citusac_cv_prog_cc_cflags_$1])])dnl +AC_CACHE_CHECK([whether $CC supports $1], [Ac_cachevar], +[citusac_save_CFLAGS=$CFLAGS +CFLAGS="$citusac_save_CFLAGS $1" +ac_save_c_werror_flag=$ac_c_werror_flag +ac_c_werror_flag=yes +_AC_COMPILE_IFELSE([AC_LANG_PROGRAM()], + [Ac_cachevar=yes], + [Ac_cachevar=no]) +ac_c_werror_flag=$ac_save_c_werror_flag +CFLAGS="$citusac_save_CFLAGS"]) +if test x"$Ac_cachevar" = x"yes"; then + CITUS_CFLAGS="$CITUS_CFLAGS $1" +fi +undefine([Ac_cachevar])dnl +])# CITUSAC_PROG_CC_CFLAGS_OPT + +CITUSAC_PROG_CC_CFLAGS_OPT([-Wall]) +CITUSAC_PROG_CC_CFLAGS_OPT([-Wextra]) +# disarm options included in the above, which are too noisy for now +CITUSAC_PROG_CC_CFLAGS_OPT([-Wno-unused-parameter]) +CITUSAC_PROG_CC_CFLAGS_OPT([-Wno-sign-compare]) +CITUSAC_PROG_CC_CFLAGS_OPT([-Wno-missing-field-initializers]) +CITUSAC_PROG_CC_CFLAGS_OPT([-Wno-clobbered]) +# And add a few extra warnings +CITUSAC_PROG_CC_CFLAGS_OPT([-Wdeclaration-after-statement]) +CITUSAC_PROG_CC_CFLAGS_OPT([-Wendif-labels]) +CITUSAC_PROG_CC_CFLAGS_OPT([-Wmissing-format-attribute]) +CITUSAC_PROG_CC_CFLAGS_OPT([-Wmissing-declarations]) +CITUSAC_PROG_CC_CFLAGS_OPT([-Wmissing-prototypes]) + +AC_SUBST(CITUS_CFLAGS, "$CITUS_CFLAGS") + +AC_CONFIG_FILES([Makefile.global]) +AC_CONFIG_HEADERS([src/include/citusdb_config.h]) +AH_TOP([ +/* + * citusdb_config.h.in is generated by autoconf/autoheader and + * converted into citusdb_config.h by configure. Include when code needs to + * depend on determinations made by configure. + * + * Do not manually edit! + */ +]) +AC_OUTPUT diff --git a/prep_buildtree b/prep_buildtree new file mode 100644 index 000000000..dcd7869d7 --- /dev/null +++ b/prep_buildtree @@ -0,0 +1,47 @@ +#! /bin/sh +# +# CitusDB copy of PostgreSQL's config/prep_buildtree +# +# This script prepares a CitusDB build tree for an out-of-tree/VPATH +# build. It is intended to be run by the configure script. + +me=`basename $0` + +help="\ +Usage: $me sourcetree [buildtree]" + +if test -z "$1"; then + echo "$help" 1>&2 + exit 1 +elif test x"$1" = x"--help"; then + echo "$help" + exit 0 +fi + +unset CDPATH + +sourcetree=`cd $1 && pwd` + +buildtree=`cd ${2:-'.'} && pwd` + +# We must not auto-create the subdirectories holding built documentation. +# If we did, it would interfere with installation of prebuilt docs from +# the source tree, if a VPATH build is done from a distribution tarball. +# See bug #5595. +for item in `find "$sourcetree" -type d \( \( -name CVS -prune \) -o \( -name .git -prune \) -o -print \) | grep -v "$sourcetree/doc/src/sgml/\+"`; do + subdir=`expr "$item" : "$sourcetree\(.*\)"` + if test ! -d "$buildtree/$subdir"; then + mkdir -p "$buildtree/$subdir" || exit 1 + fi +done + +for item in `find "$sourcetree" -not -path '*/.git/hg/*' \( -name Makefile -print -o -name GNUmakefile -print \)`; do + filename=`expr "$item" : "$sourcetree\(.*\)"` + if test ! -f "${item}.in"; then + if cmp "$item" "$buildtree/$filename" >/dev/null 2>&1; then : ; else + ln -fs "$item" "$buildtree/$filename" || exit 1 + fi + fi +done + +exit 0 diff --git a/src/backend/.gitignore b/src/backend/.gitignore new file mode 100644 index 000000000..e69de29bb diff --git a/src/backend/distributed/.gitignore b/src/backend/distributed/.gitignore new file mode 100644 index 000000000..b5abe3631 --- /dev/null +++ b/src/backend/distributed/.gitignore @@ -0,0 +1,13 @@ +# ==================== +# = Project-Specific = +# ==================== + +# regression test detritus +/log/ +/regression.diffs +/regression.out +/results/ +/tmp_check* + +# ignore latest install file +citusdb--5.0.sql diff --git a/src/backend/distributed/Makefile b/src/backend/distributed/Makefile new file mode 100644 index 000000000..ab24267ef --- /dev/null +++ b/src/backend/distributed/Makefile @@ -0,0 +1,33 @@ +# Makefile for the CitusDB extension + +citusdb_subdir = src/backend/distributed +citusdb_top_builddir = ../../.. + +MODULE_big = citusdb +EXTENSION = citusdb +EXTVERSION = 5.0 +DATA_built = $(EXTENSION)--$(EXTVERSION).sql +SCRIPTS = $(wildcard $(citusdb_top_builddir)/src/bin/scripts/*) + +# directories with source files +SUBDIRS = . commands executor master planner relay test utils worker + +# That patsubst rule searches all directories listed in SUBDIRS for .c +# files, and adds the corresponding .o files to OBJS +OBJS += \ + $(patsubst $(citusdb_abs_srcdir)/%.c,%.o,$(foreach dir,$(SUBDIRS), $(wildcard $(citusdb_abs_srcdir)/$(dir)/*.c))) + +# define build process for latest install file +$(EXTENSION)--$(EXTVERSION).sql: $(EXTENSION).sql + cat $^ > $@ + +# be explicit about the default target +all: + +NO_PGXS = 1 + +SHLIB_LINK = $(libpq) + +include $(citusdb_top_builddir)/Makefile.global + +override CPPFLAGS += -I$(libpq_srcdir) diff --git a/src/backend/distributed/citusdb.control b/src/backend/distributed/citusdb.control new file mode 100644 index 000000000..ae36339b5 --- /dev/null +++ b/src/backend/distributed/citusdb.control @@ -0,0 +1,6 @@ +# CitusDB extension +comment = 'CitusDB distributed database' +default_version = '5.0' +module_pathname = '$libdir/citusdb' +relocatable = false +schema = pg_catalog diff --git a/src/backend/distributed/citusdb.sql b/src/backend/distributed/citusdb.sql new file mode 100644 index 000000000..1090d5bd4 --- /dev/null +++ b/src/backend/distributed/citusdb.sql @@ -0,0 +1,497 @@ +/* citusdb.sql */ + +-- complain if script is sourced in psql, rather than via CREATE EXTENSION +\echo Use "CREATE EXTENSION citusdb" to load this file. \quit + +CREATE SCHEMA citusdb; + +-- Ensure CREATE EXTENSION is not run against an old citusdb data +-- directory, we're not compatible (due to the builtin functions/tables) +DO $$ +BEGIN + IF EXISTS(SELECT * FROM pg_proc WHERE proname = 'worker_apply_shard_ddl_command') THEN + RAISE 'cannot install citusdb extension in CitusDB 4 data directory'; + END IF; +END; +$$; + +/***************************************************************************** + * CitusDB data types + *****************************************************************************/ +CREATE TYPE citusdb.distribution_type AS ENUM ( + 'hash', + 'range', + 'append' +); + + +/***************************************************************************** + * CitusDB tables & corresponding indexes + *****************************************************************************/ +CREATE TABLE citusdb.pg_dist_partition( + logicalrelid Oid NOT NULL, + partmethod "char" NOT NULL, + partkey text NOT NULL +); +CREATE UNIQUE INDEX pg_dist_partition_logical_relid_index +ON citusdb.pg_dist_partition using btree(logicalrelid); +ALTER TABLE citusdb.pg_dist_partition SET SCHEMA pg_catalog; + +CREATE TABLE citusdb.pg_dist_shard( + logicalrelid oid NOT NULL, + shardid int8 NOT NULL, + shardstorage "char" NOT NULL, + shardalias text, + shardminvalue text, + shardmaxvalue text +); +CREATE UNIQUE INDEX pg_dist_shard_shardid_index +ON citusdb.pg_dist_shard using btree(shardid); +CREATE INDEX pg_dist_shard_logical_relid_index +ON citusdb.pg_dist_shard using btree(logicalrelid); +ALTER TABLE citusdb.pg_dist_shard SET SCHEMA pg_catalog; + +CREATE TABLE citusdb.pg_dist_shard_placement( + shardid int8 NOT NULL, + shardstate int4 NOT NULL, + shardlength int8 NOT NULL, + nodename text NOT NULL, + nodeport int8 NOT NULL +) WITH oids; +CREATE UNIQUE INDEX pg_dist_shard_placement_oid_index +ON citusdb.pg_dist_shard_placement using btree(oid); +CREATE INDEX pg_dist_shard_placement_shardid_index +ON citusdb.pg_dist_shard_placement using btree(shardid); +CREATE INDEX pg_dist_shard_placement_nodeid_index +ON citusdb.pg_dist_shard_placement using btree(nodename, nodeport); +ALTER TABLE citusdb.pg_dist_shard_placement SET SCHEMA pg_catalog; + + +/***************************************************************************** + * CitusDB sequences + *****************************************************************************/ + +/* + * Unternal sequence to generate 64-bit shard ids. These identifiers are then + * used to identify shards in the distributed database. + */ +CREATE SEQUENCE citusdb.pg_dist_shardid_seq + MINVALUE 102008 + NO CYCLE; +ALTER SEQUENCE citusdb.pg_dist_shardid_seq SET SCHEMA pg_catalog; + +/* + * internal sequence to generate 32-bit jobIds. These identifiers are then + * used to identify jobs in the distributed database; and they wrap at 32-bits + * to allow for slave nodes to independently execute their distributed jobs. + */ +CREATE SEQUENCE citusdb.pg_dist_jobid_seq + MINVALUE 2 /* first jobId reserved for clean up jobs */ + MAXVALUE 4294967296; +ALTER SEQUENCE citusdb.pg_dist_jobid_seq SET SCHEMA pg_catalog; + + +/***************************************************************************** + * CitusDB functions + *****************************************************************************/ + +/* For backward compatibility and ease of use create functions et al. in pg_catalog */ +SET search_path = 'pg_catalog'; + +/* master_* functions */ + +CREATE FUNCTION master_get_table_metadata(relation_name text, OUT logical_relid oid, + OUT part_storage_type "char", + OUT part_method "char", OUT part_key text, + OUT part_replica_count integer, + OUT part_max_size bigint, + OUT part_placement_policy integer) + RETURNS record + LANGUAGE C STABLE STRICT + AS 'MODULE_PATHNAME', $$master_get_table_metadata$$; +COMMENT ON FUNCTION master_get_table_metadata(relation_name text) + IS 'fetch metadata values for the table'; + +CREATE FUNCTION master_get_table_ddl_events(text) + RETURNS SETOF text + LANGUAGE C STRICT ROWS 100 + AS 'MODULE_PATHNAME', $$master_get_table_ddl_events$$; +COMMENT ON FUNCTION master_get_table_ddl_events(text) + IS 'fetch set of ddl statements for the table'; + +CREATE FUNCTION master_get_new_shardid() + RETURNS bigint + LANGUAGE C STRICT + AS 'MODULE_PATHNAME', $$master_get_new_shardid$$; +COMMENT ON FUNCTION master_get_new_shardid() + IS 'fetch unique shardId'; + +CREATE FUNCTION master_get_local_first_candidate_nodes(OUT node_name text, + OUT node_port bigint) + RETURNS SETOF record + LANGUAGE C STRICT ROWS 100 + AS 'MODULE_PATHNAME', $$master_get_local_first_candidate_nodes$$; +COMMENT ON FUNCTION master_get_local_first_candidate_nodes() + IS 'fetch set of candidate nodes for shard uploading choosing the local node first'; + +CREATE FUNCTION master_create_empty_shard(text) + RETURNS bigint + LANGUAGE C STRICT + AS 'MODULE_PATHNAME', $$master_create_empty_shard$$; +COMMENT ON FUNCTION master_create_empty_shard(text) + IS 'create an empty shard and shard placements for the table'; + +CREATE FUNCTION master_append_table_to_shard(bigint, text, text, integer) + RETURNS real + LANGUAGE C STRICT + AS 'MODULE_PATHNAME', $$master_append_table_to_shard$$; +COMMENT ON FUNCTION master_append_table_to_shard(bigint, text, text, integer) + IS 'append given table to all shard placements and update metadata'; + +CREATE FUNCTION master_apply_delete_command(text) + RETURNS integer + LANGUAGE C STRICT + AS 'MODULE_PATHNAME', $$master_apply_delete_command$$; +COMMENT ON FUNCTION master_apply_delete_command(text) + IS 'drop shards matching delete criteria and update metadata'; + +CREATE FUNCTION master_get_active_worker_nodes(OUT node_name text, OUT node_port bigint) + RETURNS SETOF record + LANGUAGE C STRICT ROWS 100 + AS 'MODULE_PATHNAME', $$master_get_active_worker_nodes$$; +COMMENT ON FUNCTION master_get_active_worker_nodes() + IS 'fetch set of active worker nodes'; + +CREATE FUNCTION master_get_round_robin_candidate_nodes(shard_id bigint, + OUT node_name text, + OUT node_port bigint) + RETURNS SETOF record + LANGUAGE C STRICT ROWS 100 + AS 'MODULE_PATHNAME', $$master_get_round_robin_candidate_nodes$$; +COMMENT ON FUNCTION master_get_round_robin_candidate_nodes(shard_id bigint) + IS 'fetch set of candidate nodes for shard uploading in round-robin manner'; + +CREATE FUNCTION master_create_distributed_table(table_name regclass, + distribution_column text, + distribution_method citusdb.distribution_type) + RETURNS void + LANGUAGE C STRICT + AS 'MODULE_PATHNAME', $$master_create_distributed_table$$; +COMMENT ON FUNCTION master_create_distributed_table(table_name regclass, + distribution_column text, + distribution_method citusdb.distribution_type) + IS 'define the table distribution functions'; + +-- define shard creation function for hash-partitioned tables +CREATE FUNCTION master_create_worker_shards(table_name text, shard_count integer, + replication_factor integer DEFAULT 2) +RETURNS void +AS 'MODULE_PATHNAME' +LANGUAGE C STRICT; + +/* task_tracker_* functions */ + +CREATE FUNCTION task_tracker_assign_task(bigint, integer, text) + RETURNS void + LANGUAGE C STRICT + AS 'MODULE_PATHNAME', $$task_tracker_assign_task$$; +COMMENT ON FUNCTION task_tracker_assign_task(bigint, integer, text) + IS 'assign a task to execute'; + +CREATE FUNCTION task_tracker_task_status(bigint, integer) + RETURNS integer + LANGUAGE C STRICT + AS 'MODULE_PATHNAME', $$task_tracker_task_status$$; +COMMENT ON FUNCTION task_tracker_task_status(bigint, integer) + IS 'check an assigned task''s execution status'; + +CREATE FUNCTION task_tracker_cleanup_job(bigint) + RETURNS void + LANGUAGE C STRICT + AS 'MODULE_PATHNAME', $$task_tracker_cleanup_job$$; +COMMENT ON FUNCTION task_tracker_cleanup_job(bigint) + IS 'clean up all tasks associated with a job'; + + +/* worker_* functions */ + +CREATE FUNCTION worker_fetch_partition_file(bigint, integer, integer, integer, text, + integer) + RETURNS void + LANGUAGE C STRICT + AS 'MODULE_PATHNAME', $$worker_fetch_partition_file$$; +COMMENT ON FUNCTION worker_fetch_partition_file(bigint, integer, integer, integer, text, + integer) + IS 'fetch partition file from remote node'; + +CREATE FUNCTION worker_fetch_query_results_file(bigint, integer, integer, text, integer) + RETURNS void + LANGUAGE C STRICT + AS 'MODULE_PATHNAME', $$worker_fetch_query_results_file$$; +COMMENT ON FUNCTION worker_fetch_query_results_file(bigint, integer, integer, text, + integer) + IS 'fetch query results file from remote node'; + +CREATE FUNCTION worker_fetch_foreign_file(text, bigint, text[], integer[]) + RETURNS void + LANGUAGE C STRICT + AS 'MODULE_PATHNAME', $$worker_fetch_foreign_file$$; +COMMENT ON FUNCTION worker_fetch_foreign_file(text, bigint, text[], integer[]) + IS 'fetch foreign file from remote node and apply file'; + +CREATE FUNCTION worker_fetch_regular_table(text, bigint, text[], integer[]) + RETURNS void + LANGUAGE C STRICT + AS 'MODULE_PATHNAME', $$worker_fetch_regular_table$$; +COMMENT ON FUNCTION worker_fetch_regular_table(text, bigint, text[], integer[]) + IS 'fetch PostgreSQL table from remote node'; + +CREATE FUNCTION worker_range_partition_table(bigint, integer, text, text, oid, anyarray) + RETURNS void + LANGUAGE C STRICT + AS 'MODULE_PATHNAME', $$worker_range_partition_table$$; +COMMENT ON FUNCTION worker_range_partition_table(bigint, integer, text, text, oid, + anyarray) + IS 'range partition query results'; + +CREATE FUNCTION worker_hash_partition_table(bigint, integer, text, text, oid, integer) + RETURNS void + LANGUAGE C STRICT + AS 'MODULE_PATHNAME', $$worker_hash_partition_table$$; +COMMENT ON FUNCTION worker_hash_partition_table(bigint, integer, text, text, oid, + integer) + IS 'hash partition query results'; + +CREATE FUNCTION worker_merge_files_into_table(bigint, integer, text[], text[]) + RETURNS void + LANGUAGE C STRICT + AS 'MODULE_PATHNAME', $$worker_merge_files_into_table$$; +COMMENT ON FUNCTION worker_merge_files_into_table(bigint, integer, text[], text[]) + IS 'merge files into a table'; + +CREATE FUNCTION worker_merge_files_and_run_query(bigint, integer, text, text) + RETURNS void + LANGUAGE C STRICT + AS 'MODULE_PATHNAME', $$worker_merge_files_and_run_query$$; +COMMENT ON FUNCTION worker_merge_files_and_run_query(bigint, integer, text, text) + IS 'merge files and run a reduce query on merged files'; + +CREATE FUNCTION worker_cleanup_job_schema_cache() + RETURNS void + LANGUAGE C STRICT + AS 'MODULE_PATHNAME', $$worker_cleanup_job_schema_cache$$; +COMMENT ON FUNCTION worker_cleanup_job_schema_cache() + IS 'cleanup all job schemas in current database'; + +CREATE FUNCTION worker_foreign_file_path(text) + RETURNS text + LANGUAGE C STRICT + AS 'MODULE_PATHNAME', $$worker_foreign_file_path$$; +COMMENT ON FUNCTION worker_foreign_file_path(text) + IS 'get a foreign table''s local file path'; + +CREATE FUNCTION worker_find_block_local_path(bigint, text[]) + RETURNS text + LANGUAGE C STRICT + AS 'MODULE_PATHNAME', $$worker_find_block_local_path$$; +COMMENT ON FUNCTION worker_find_block_local_path(bigint, text[]) + IS 'find an HDFS block''s local file path'; + +CREATE FUNCTION worker_apply_shard_ddl_command(bigint, text) + RETURNS void + LANGUAGE C STRICT + AS 'MODULE_PATHNAME', $$worker_apply_shard_ddl_command$$; +COMMENT ON FUNCTION worker_apply_shard_ddl_command(bigint, text) + IS 'extend ddl command with shardId and apply on database'; + +CREATE FUNCTION worker_append_table_to_shard(text, text, text, integer) + RETURNS void + LANGUAGE C STRICT + AS 'MODULE_PATHNAME', $$worker_append_table_to_shard$$; +COMMENT ON FUNCTION worker_append_table_to_shard(text, text, text, integer) + IS 'append a regular table''s contents to the shard'; + + +/* trigger functions */ + +CREATE OR REPLACE FUNCTION citusdb_drop_trigger() + RETURNS event_trigger + LANGUAGE plpgsql + SET search_path = pg_catalog + AS $cdbdt$ +DECLARE v_obj record; +BEGIN + FOR v_obj IN SELECT * FROM pg_event_trigger_dropped_objects() LOOP + IF v_obj.object_type <> 'table' THEN + CONTINUE; + END IF; + + -- nothing to do if not a distributed table + IF NOT EXISTS(SELECT * FROM pg_dist_partition WHERE logicalrelid = v_obj.objid) THEN + CONTINUE; + END IF; + + -- check if there's shards for the table, error out if so + IF EXISTS(SELECT * FROM pg_dist_shard WHERE logicalrelid = v_obj.objid) THEN + RAISE EXCEPTION USING + MESSAGE = 'cannot drop distributed table with existing shards', + HINT = $$Delete shards first using: $$ || + $$SELECT master_apply_delete_command('DELETE FROM $$ || + v_obj.object_identity || $$')$$; + END IF; + + -- delete partition entry + DELETE FROM pg_dist_partition WHERE logicalrelid = v_obj.objid; + IF NOT FOUND THEN + RAISE EXCEPTION 'could not find previously found pg_dist_partition entry'; + END IF; + + END LOOP; +END; +$cdbdt$; +COMMENT ON FUNCTION citusdb_drop_trigger() + IS 'perform checks and actions at the end of DROP actions'; + +CREATE FUNCTION master_dist_partition_cache_invalidate() + RETURNS trigger + LANGUAGE C + AS 'MODULE_PATHNAME', $$master_dist_partition_cache_invalidate$$; +COMMENT ON FUNCTION master_dist_partition_cache_invalidate() + IS 'register relcache invalidation for changed rows'; + +CREATE FUNCTION master_dist_shard_cache_invalidate() + RETURNS trigger + LANGUAGE C + AS 'MODULE_PATHNAME', $$master_dist_shard_cache_invalidate$$; +COMMENT ON FUNCTION master_dist_shard_cache_invalidate() + IS 'register relcache invalidation for changed rows'; + + +/* internal functions, not user accessible */ + +CREATE FUNCTION citusdb_extradata_container(INTERNAL) + RETURNS void + LANGUAGE C + AS 'MODULE_PATHNAME', $$citusdb_extradata_container$$; +COMMENT ON FUNCTION pg_catalog.citusdb_extradata_container(INTERNAL) + IS 'placeholder function to store additional data in postgres node trees'; + + +/***************************************************************************** + * CitusDB triggers + *****************************************************************************/ + +CREATE EVENT TRIGGER citusdb_cascade_to_partition + ON SQL_DROP + EXECUTE PROCEDURE citusdb_drop_trigger(); + +CREATE TRIGGER dist_partition_cache_invalidate + AFTER INSERT OR UPDATE OR DELETE + ON pg_catalog.pg_dist_partition + FOR EACH ROW EXECUTE PROCEDURE master_dist_partition_cache_invalidate(); + +CREATE TRIGGER dist_shard_cache_invalidate + AFTER INSERT OR UPDATE OR DELETE + ON pg_catalog.pg_dist_shard + FOR EACH ROW EXECUTE PROCEDURE master_dist_shard_cache_invalidate(); + + +/***************************************************************************** + * CitusDB aggregates + *****************************************************************************/ +CREATE AGGREGATE array_cat_agg(anyarray) (SFUNC = array_cat, STYPE = anyarray); +COMMENT ON AGGREGATE array_cat_agg(anyarray) + IS 'concatenate input arrays into a single array'; + + +/* + * Creates a temporary table exactly like the specified target table along with + * a trigger to redirect any INSERTed rows from the proxy to the underlying + * table. Users may optionally provide a sequence which will be incremented + * after each row that has been successfully proxied (useful for counting rows + * processed). Returns the name of the proxy table that was created. + */ +CREATE FUNCTION create_insert_proxy_for_table(target_table regclass, + sequence regclass DEFAULT NULL) +RETURNS text +AS $create_insert_proxy_for_table$ + DECLARE + temp_table_name text; + attr_names text[]; + attr_list text; + param_list text; + using_list text; + insert_command text; + -- templates to create dynamic functions, tables, and triggers + func_tmpl CONSTANT text := $$CREATE FUNCTION pg_temp.copy_to_insert() + RETURNS trigger + AS $copy_to_insert$ + BEGIN + EXECUTE %L USING %s; + PERFORM nextval(%L); + RETURN NULL; + END; + $copy_to_insert$ LANGUAGE plpgsql;$$; + table_tmpl CONSTANT text := $$CREATE TEMPORARY TABLE %I + (LIKE %s INCLUDING DEFAULTS)$$; + trigger_tmpl CONSTANT text := $$CREATE TRIGGER copy_to_insert + BEFORE INSERT ON %s FOR EACH ROW + EXECUTE PROCEDURE pg_temp.copy_to_insert()$$; + BEGIN + -- create name of temporary table using unqualified input table name + SELECT format('%s_insert_proxy', relname) + INTO STRICT temp_table_name + FROM pg_class + WHERE oid = target_table; + + -- get list of all attributes in table, we'll need shortly + SELECT array_agg(attname) + INTO STRICT attr_names + FROM pg_attribute + WHERE attrelid = target_table AND + attnum > 0 AND + NOT attisdropped; + + -- build fully specified column list and USING clause from attr. names + SELECT string_agg(quote_ident(attr_name), ','), + string_agg(format('NEW.%I', attr_name), ',') + INTO STRICT attr_list, + using_list + FROM unnest(attr_names) AS attr_name; + + -- build ($1, $2, $3)-style VALUE list to bind parameters + SELECT string_agg('$' || param_num, ',') + INTO STRICT param_list + FROM generate_series(1, array_length(attr_names, 1)) AS param_num; + + -- use the above lists to generate appropriate INSERT command + insert_command = format('INSERT INTO %s (%s) VALUES (%s)', target_table, + attr_list, param_list); + + -- use the command to make one-off trigger targeting specified table + EXECUTE format(func_tmpl, insert_command, using_list, sequence); + + -- create a temporary table exactly like the target table... + EXECUTE format(table_tmpl, temp_table_name, target_table); + + -- ... and install the trigger on that temporary table + EXECUTE format(trigger_tmpl, quote_ident(temp_table_name)::regclass); + + RETURN temp_table_name; + END; +$create_insert_proxy_for_table$ LANGUAGE plpgsql SET search_path = 'pg_catalog'; + +COMMENT ON FUNCTION create_insert_proxy_for_table(regclass, regclass) + IS 'create a proxy table that redirects INSERTed rows to a target table'; + +-- define shard repair function +CREATE FUNCTION master_copy_shard_placement(shard_id bigint, + source_node_name text, + source_node_port integer, + target_node_name text, + target_node_port integer) +RETURNS void +AS 'MODULE_PATHNAME' +LANGUAGE C STRICT; + +RESET search_path; diff --git a/src/backend/distributed/commands/create_distributed_table.c b/src/backend/distributed/commands/create_distributed_table.c new file mode 100644 index 000000000..b4a4c802b --- /dev/null +++ b/src/backend/distributed/commands/create_distributed_table.c @@ -0,0 +1,377 @@ +/*------------------------------------------------------------------------- + * + * create_distributed_relation.c + * Routines relation to the creation of distributed relations. + * + * Copyright (c) 2012-2015, Citus Data, Inc. + * + *------------------------------------------------------------------------- + */ + +#include "postgres.h" + +#include "access/genam.h" +#include "access/hash.h" +#include "access/heapam.h" +#include "access/htup.h" +#include "access/htup_details.h" +#include "access/nbtree.h" +#include "catalog/dependency.h" +#include "catalog/index.h" +#include "catalog/indexing.h" +#include "catalog/pg_am.h" +#include "catalog/pg_enum.h" +#include "catalog/pg_extension.h" +#include "catalog/pg_opclass.h" +#include "commands/defrem.h" +#include "commands/extension.h" +#include "distributed/master_metadata_utility.h" +#include "distributed/metadata_cache.h" +#include "distributed/pg_dist_partition.h" +#include "nodes/execnodes.h" +#include "nodes/nodeFuncs.h" +#include "nodes/pg_list.h" +#include "parser/parse_expr.h" +#include "parser/parse_node.h" +#include "parser/parse_relation.h" +#include "utils/builtins.h" +#include "utils/fmgroids.h" +#include "utils/lsyscache.h" +#include "utils/rel.h" +#include "utils/syscache.h" +#include "utils/inval.h" + + +/* local function forward declarations */ +static char LookupDistributionMethod(Oid distributionMethodOid); +static void RecordDistributedRelationDependencies(Oid distributedRelationId, + Node *distributionKey); +static Oid SupportFunctionForColumn(Var *partitionColumn, Oid accessMethodId, + int16 supportFunctionNumber); + + +/* exports for SQL callable functions */ +PG_FUNCTION_INFO_V1(master_create_distributed_table); + + +/* + * master_create_distributed_table accepts a table, distribution column and + * method and performs the corresponding catalog changes. + * + * XXX: We should perform more checks here to see if this table is fit for + * partitioning. At a minimum, we should validate the following: (i) this node + * runs as the master node, (ii) table does not make use of the inheritance + * mechanism, (iii) table does not own columns that are sequences, and (iv) + * table does not have collated columns. (v) table does not have + * preexisting content. + */ +Datum +master_create_distributed_table(PG_FUNCTION_ARGS) +{ + Oid distributedRelationId = PG_GETARG_OID(0); + text *distributionColumnText = PG_GETARG_TEXT_P(1); + Oid distributionMethodOid = PG_GETARG_OID(2); + + Relation distributedRelation = NULL; + char *distributedRelationName = NULL; + char relationKind = '\0'; + + Relation pgDistPartition = NULL; + char distributionMethod = LookupDistributionMethod(distributionMethodOid); + char *distributionColumnName = text_to_cstring(distributionColumnText); + Node *distributionKey = NULL; + Var *distributionColumn = NULL; + char *distributionKeyString = NULL; + + List *indexOidList = NIL; + ListCell *indexOidCell = NULL; + + HeapTuple newTuple = NULL; + Datum newValues[Natts_pg_dist_partition]; + bool newNulls[Natts_pg_dist_partition]; + + /* + * Lock target relation with an access exclusive lock - there's no way to + * make sense of this table until we've committed, and we don't want + * multiple backends manipulating this relation. + */ + distributedRelation = relation_open(distributedRelationId, AccessExclusiveLock); + distributedRelationName = RelationGetRelationName(distributedRelation); + + /* open system catalog and insert new tuple */ + pgDistPartition = heap_open(DistPartitionRelationId(), RowExclusiveLock); + + /* check that the relation is not already distributed */ + if (IsDistributedTable(distributedRelationId)) + { + ereport(ERROR, (errcode(ERRCODE_INVALID_TABLE_DEFINITION), + errmsg("table \"%s\" is already distributed", + distributedRelationName))); + } + + /* verify target relation is either regular or foreign table */ + relationKind = distributedRelation->rd_rel->relkind; + if (relationKind != RELKIND_RELATION && relationKind != RELKIND_FOREIGN_TABLE) + { + ereport(ERROR, (errcode(ERRCODE_WRONG_OBJECT_TYPE), + errmsg("cannot distribute relation: %s", + distributedRelationName), + errdetail("Distributed relations must be regular or " + "foreign tables."))); + } + + distributionKey = BuildDistributionKeyFromColumnName(distributedRelation, + distributionColumnName); + distributionKeyString = nodeToString(distributionKey); + + /* the distribution key should always be a Var for now */ + Assert(IsA(distributionKey, Var)); + distributionColumn = (Var *) distributionKey; + + /* check for support function needed by specified partition method */ + if (distributionMethod == DISTRIBUTE_BY_HASH) + { + Oid hashSupportFunction = SupportFunctionForColumn(distributionColumn, + HASH_AM_OID, HASHPROC); + if (hashSupportFunction == InvalidOid) + { + ereport(ERROR, (errcode(ERRCODE_UNDEFINED_FUNCTION), + errmsg("could not identify a hash function for type %s", + format_type_be(distributionColumn->vartype)), + errdatatype(distributionColumn->vartype), + errdetail("Partition column types must have a hash function " + "defined to use hash partitioning."))); + } + } + else if (distributionMethod == DISTRIBUTE_BY_RANGE) + { + Oid btreeSupportFunction = SupportFunctionForColumn(distributionColumn, + BTREE_AM_OID, BTORDER_PROC); + if (btreeSupportFunction == InvalidOid) + { + ereport(ERROR, + (errcode(ERRCODE_UNDEFINED_FUNCTION), + errmsg("could not identify a comparison function for type %s", + format_type_be(distributionColumn->vartype)), + errdatatype(distributionColumn->vartype), + errdetail("Partition column types must have a comparison function " + "defined to use range partitioning."))); + } + } + + /* + * Do not allow UNIQUE constraint and/or PRIMARY KEY on append partitioned tables, + * since currently there is no way of enforcing uniqueness for overlapping shards. + * + * Similarly, do not allow UNIQUE constraint and/or PRIMARY KEY if it does not + * include partition column. This check is important for two reasons. First, + * currently CitusDB does not enforce uniqueness constraint on multiple shards. + * Second, INSERT INTO .. ON CONFLICT (i.e., UPSERT) queries can be executed with no + * further check for constraints. + */ + indexOidList = RelationGetIndexList(distributedRelation); + foreach(indexOidCell, indexOidList) + { + Oid indexOid = lfirst_oid(indexOidCell); + Relation indexDesc = index_open(indexOid, RowExclusiveLock); + IndexInfo *indexInfo = NULL; + AttrNumber *attributeNumberArray = NULL; + bool hasDistributionColumn = false; + int attributeCount = 0; + int attributeIndex = 0; + + /* extract index key information from the index's pg_index info */ + indexInfo = BuildIndexInfo(indexDesc); + + /* only check unique indexes */ + if (indexInfo->ii_Unique == false) + { + index_close(indexDesc, NoLock); + continue; + } + + /* + * CitusDB cannot enforce uniqueness constraints with overlapping shards. Thus, + * emit a warning for unique indexes on append partitioned tables. + */ + if (distributionMethod == DISTRIBUTE_BY_APPEND) + { + ereport(WARNING, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("table \"%s\" has a unique constraint", + distributedRelationName), + errdetail("Unique constraints and primary keys on " + "append-partitioned tables cannot be enforced."), + errhint("Consider using hash partitioning."))); + } + + attributeCount = indexInfo->ii_NumIndexAttrs; + attributeNumberArray = indexInfo->ii_KeyAttrNumbers; + + for (attributeIndex = 0; attributeIndex < attributeCount; attributeIndex++) + { + AttrNumber attributeNumber = attributeNumberArray[attributeIndex]; + if (distributionColumn->varattno == attributeNumber) + { + hasDistributionColumn = true; + break; + } + } + + if (!hasDistributionColumn) + { + ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("cannot distribute relation: \"%s\"", + distributedRelationName), + errdetail("Distributed relations cannot have " + "UNIQUE constraints or PRIMARY KEYs that do not " + "include the partition column."))); + } + + index_close(indexDesc, NoLock); + } + + /* form new tuple for pg_dist_partition */ + memset(newValues, 0, sizeof(newValues)); + memset(newNulls, false, sizeof(newNulls)); + + newValues[Anum_pg_dist_partition_logicalrelid - 1] = + ObjectIdGetDatum(distributedRelationId); + newValues[Anum_pg_dist_partition_partmethod - 1] = + CharGetDatum(distributionMethod); + newValues[Anum_pg_dist_partition_partkey - 1] = + CStringGetTextDatum(distributionKeyString); + + newTuple = heap_form_tuple(RelationGetDescr(pgDistPartition), newValues, newNulls); + + /* finally insert tuple, build index entries & register cache invalidation */ + simple_heap_insert(pgDistPartition, newTuple); + CatalogUpdateIndexes(pgDistPartition, newTuple); + CacheInvalidateRelcacheByRelid(distributedRelationId); + + RecordDistributedRelationDependencies(distributedRelationId, distributionKey); + + heap_close(pgDistPartition, NoLock); + relation_close(distributedRelation, NoLock); + + PG_RETURN_VOID(); +} + + +/* + * RecordDistributedRelationDependencies creates the dependency entries + * necessary for a distributed relation in addition to the preexisting ones + * for a normal relation. + * + * We create one dependency from the (now distributed) relation to the citusdb + * extension to prevent the extension from being dropped while distributed + * tables exist. Furthermore a dependency from pg_dist_partition's + * distribution clause to the underlying columns is created, but it's marked + * as being owned by the relation itself. That means the entire table can be + * dropped, but the column itself can't. Neither can the type of the + * distribution column be changed (c.f. ATExecAlterColumnType). + */ +static void +RecordDistributedRelationDependencies(Oid distributedRelationId, Node *distributionKey) +{ + ObjectAddress relationAddr = { 0, 0, 0 }; + ObjectAddress citusExtensionAddr = { 0, 0, 0 }; + + relationAddr.classId = RelationRelationId; + relationAddr.objectId = distributedRelationId; + relationAddr.objectSubId = 0; + + citusExtensionAddr.classId = ExtensionRelationId; + citusExtensionAddr.objectId = get_extension_oid("citusdb", false); + citusExtensionAddr.objectSubId = 0; + + /* dependency from table entry to extension */ + recordDependencyOn(&relationAddr, &citusExtensionAddr, DEPENDENCY_NORMAL); + + /* make sure the distribution key column/expression does not just go away */ + recordDependencyOnSingleRelExpr(&relationAddr, distributionKey, distributedRelationId, + DEPENDENCY_NORMAL, DEPENDENCY_NORMAL); +} + + +/* + * LookupDistributionMethod maps the oids of citusdb.distribution_type enum + * values to pg_dist_partition.partmethod values. + * + * The passed in oid has to belong to a value of citusdb.distribution_type. + */ +static char +LookupDistributionMethod(Oid distributionMethodOid) +{ + HeapTuple enumTuple = NULL; + Form_pg_enum enumForm = NULL; + char distributionMethod = 0; + const char *enumLabel = NULL; + + enumTuple = SearchSysCache1(ENUMOID, ObjectIdGetDatum(distributionMethodOid)); + if (!HeapTupleIsValid(enumTuple)) + { + ereport(ERROR, (errmsg("invalid internal value for enum: %u", + distributionMethodOid))); + } + + enumForm = (Form_pg_enum) GETSTRUCT(enumTuple); + enumLabel = NameStr(enumForm->enumlabel); + + if (strncmp(enumLabel, "append", NAMEDATALEN) == 0) + { + distributionMethod = DISTRIBUTE_BY_APPEND; + } + else if (strncmp(enumLabel, "hash", NAMEDATALEN) == 0) + { + distributionMethod = DISTRIBUTE_BY_HASH; + } + else if (strncmp(enumLabel, "range", NAMEDATALEN) == 0) + { + distributionMethod = DISTRIBUTE_BY_RANGE; + } + else + { + ereport(ERROR, (errmsg("invalid label for enum: %s", enumLabel))); + } + + ReleaseSysCache(enumTuple); + + return distributionMethod; +} + + +/* + * SupportFunctionForColumn locates a support function given a column, an access method, + * and and id of a support function. This function returns InvalidOid if there is no + * support function for the operator class family of the column, but if the data type + * of the column has no default operator class whatsoever, this function errors out. + */ +static Oid +SupportFunctionForColumn(Var *partitionColumn, Oid accessMethodId, + int16 supportFunctionNumber) +{ + Oid operatorFamilyId = InvalidOid; + Oid supportFunctionOid = InvalidOid; + Oid operatorClassInputType = InvalidOid; + Oid columnOid = partitionColumn->vartype; + Oid operatorClassId = GetDefaultOpClass(columnOid, accessMethodId); + + /* currently only support using the default operator class */ + if (operatorClassId == InvalidOid) + { + ereport(ERROR, (errcode(ERRCODE_UNDEFINED_OBJECT), + errmsg("data type %s has no default operator class for specified" + " partition method", format_type_be(columnOid)), + errdatatype(columnOid), + errdetail("Partition column types must have a default operator" + " class defined."))); + } + + operatorFamilyId = get_opclass_family(operatorClassId); + operatorClassInputType = get_opclass_input_type(operatorClassId); + supportFunctionOid = get_opfamily_proc(operatorFamilyId, operatorClassInputType, + operatorClassInputType, + supportFunctionNumber); + + return supportFunctionOid; +} diff --git a/src/backend/distributed/commands/transmit.c b/src/backend/distributed/commands/transmit.c new file mode 100644 index 000000000..0ab90d0ef --- /dev/null +++ b/src/backend/distributed/commands/transmit.c @@ -0,0 +1,300 @@ +/*------------------------------------------------------------------------- + * + * transmit.c + * Routines for transmitting regular files between two nodes. + * + * Copyright (c) 2012-2015, Citus Data, Inc. + *------------------------------------------------------------------------- + */ + +#include "postgres.h" +#include "miscadmin.h" + +#include +#include +#include + +#include "distributed/relay_utility.h" +#include "distributed/transmit.h" +#include "libpq/libpq.h" +#include "libpq/pqformat.h" +#include "storage/fd.h" + + +/* Local functions forward declarations */ +static File FileOpenForTransmit(const char *filename, int fileFlags, int fileMode); +static void SendCopyInStart(void); +static void SendCopyOutStart(void); +static void SendCopyDone(void); +static void SendCopyData(StringInfo fileBuffer); +static bool ReceiveCopyData(StringInfo copyData); + + +/* + * ReceiveRegularFile receives data from stdin using the standard copy + * protocol. The function then creates or truncates a file with the given + * filename, and appends received data to this file. + */ +void +ReceiveRegularFile(const char *filename) +{ + StringInfo copyData = makeStringInfo(); + bool copyDone = false; + File fileDesc = -1; + const int fileFlags = (O_APPEND | O_CREAT | O_RDWR | O_TRUNC | PG_BINARY); + const int fileMode = (S_IRUSR | S_IWUSR); + + fileDesc = FileOpenForTransmit(filename, fileFlags, fileMode); + + SendCopyInStart(); + + copyDone = ReceiveCopyData(copyData); + while (!copyDone) + { + /* if received data has contents, append to regular file */ + if (copyData->len > 0) + { + int appended = FileWrite(fileDesc, copyData->data, copyData->len); + if (appended != copyData->len) + { + ereport(ERROR, (errcode_for_file_access(), + errmsg("could not append to received file: %m"))); + } + } + + resetStringInfo(copyData); + copyDone = ReceiveCopyData(copyData); + } + + FreeStringInfo(copyData); + FileClose(fileDesc); +} + + +/* + * SendRegularFile reads data from the given file, and sends these data to + * stdout using the standard copy protocol. After all file data are sent, the + * function ends the copy protocol and closes the file. + */ +void +SendRegularFile(const char *filename) +{ + File fileDesc = -1; + StringInfo fileBuffer = NULL; + int readBytes = -1; + const uint32 fileBufferSize = 32768; /* 32 KB */ + const int fileFlags = (O_RDONLY | PG_BINARY); + const int fileMode = 0; + + /* we currently do not check if the caller has permissions for this file */ + fileDesc = FileOpenForTransmit(filename, fileFlags, fileMode); + + /* + * We read file's contents into buffers of 32 KB. This buffer size is twice + * as large as Hadoop's default buffer size, and may later be configurable. + */ + fileBuffer = makeStringInfo(); + enlargeStringInfo(fileBuffer, fileBufferSize); + + SendCopyOutStart(); + + readBytes = FileRead(fileDesc, fileBuffer->data, fileBufferSize); + while (readBytes > 0) + { + fileBuffer->len = readBytes; + + SendCopyData(fileBuffer); + + resetStringInfo(fileBuffer); + readBytes = FileRead(fileDesc, fileBuffer->data, fileBufferSize); + } + + SendCopyDone(); + + FreeStringInfo(fileBuffer); + FileClose(fileDesc); +} + + +/* Helper function that deallocates string info object. */ +void +FreeStringInfo(StringInfo stringInfo) +{ + resetStringInfo(stringInfo); + + pfree(stringInfo->data); + pfree(stringInfo); +} + + +/* + * FileOpenForTransmit opens file with the given filename and flags. On success, + * the function returns the internal file handle for the opened file. On failure + * the function errors out. + */ +static File +FileOpenForTransmit(const char *filename, int fileFlags, int fileMode) +{ + File fileDesc = -1; + int fileStated = -1; + struct stat fileStat; + + fileStated = stat(filename, &fileStat); + if (fileStated >= 0) + { + if (S_ISDIR(fileStat.st_mode)) + { + ereport(ERROR, (errcode(ERRCODE_WRONG_OBJECT_TYPE), + errmsg("\"%s\" is a directory", filename))); + } + } + + fileDesc = PathNameOpenFile((char *) filename, fileFlags, fileMode); + if (fileDesc < 0) + { + ereport(ERROR, (errcode_for_file_access(), + errmsg("could not open file \"%s\": %m", filename))); + } + + return fileDesc; +} + + +/* + * SendCopyInStart sends the start copy in message to initiate receiving data + * from stdin. The frontend should now send copy data. + */ +static void +SendCopyInStart(void) +{ + StringInfoData copyInStart = { NULL, 0, 0, 0 }; + const char copyFormat = 1; /* binary copy format */ + int flushed = 0; + + pq_beginmessage(©InStart, 'G'); + pq_sendbyte(©InStart, copyFormat); + pq_sendint(©InStart, 0, 2); + pq_endmessage(©InStart); + + /* flush here to ensure that FE knows it can send data */ + flushed = pq_flush(); + if (flushed != 0) + { + ereport(WARNING, (errmsg("could not flush copy start data"))); + } +} + + +/* + * SendCopyOutStart sends the start copy out message to initiate sending data to + * stdout. After this message, the backend will continue by sending copy data. + */ +static void +SendCopyOutStart(void) +{ + StringInfoData copyOutStart = { NULL, 0, 0, 0 }; + const char copyFormat = 1; /* binary copy format */ + + pq_beginmessage(©OutStart, 'H'); + pq_sendbyte(©OutStart, copyFormat); + pq_sendint(©OutStart, 0, 2); + pq_endmessage(©OutStart); +} + + +/* Sends the copy-complete message. */ +static void +SendCopyDone(void) +{ + StringInfoData copyDone = { NULL, 0, 0, 0 }; + int flushed = 0; + + pq_beginmessage(©Done, 'c'); + pq_endmessage(©Done); + + /* flush here to signal to FE that we are done */ + flushed = pq_flush(); + if (flushed != 0) + { + ereport(WARNING, (errmsg("could not flush copy start data"))); + } +} + + +/* Sends the copy data message to stdout. */ +static void +SendCopyData(StringInfo fileBuffer) +{ + StringInfoData copyData = { NULL, 0, 0, 0 }; + + pq_beginmessage(©Data, 'd'); + pq_sendbytes(©Data, fileBuffer->data, fileBuffer->len); + pq_endmessage(©Data); +} + + +/* + * ReceiveCopyData receives one copy data message from stdin, and writes this + * message's contents into the given argument. The function then checks if the + * copy protocol has been completed, and if it has, the function returns true. + * If not, the function returns false indicating there are more data to read. + * If the received message does not conform to the copy protocol, the function + * mirrors copy.c's error behavior. + */ +static bool +ReceiveCopyData(StringInfo copyData) +{ + int messageType = 0; + int messageCopied = 0; + bool copyDone = true; + const int unlimitedSize = 0; + + HOLD_CANCEL_INTERRUPTS(); + pq_startmsgread(); + messageType = pq_getbyte(); + if (messageType == EOF) + { + ereport(ERROR, (errcode(ERRCODE_CONNECTION_FAILURE), + errmsg("unexpected EOF on client connection"))); + } + + /* consume the rest of message before checking for message type */ + messageCopied = pq_getmessage(copyData, unlimitedSize); + if (messageCopied == EOF) + { + ereport(ERROR, (errcode(ERRCODE_CONNECTION_FAILURE), + errmsg("unexpected EOF on client connection"))); + } + + RESUME_CANCEL_INTERRUPTS(); + + switch (messageType) + { + case 'd': /* CopyData */ + copyDone = false; + break; + case 'c': /* CopyDone */ + copyDone = true; + break; + case 'f': /* CopyFail */ + ereport(ERROR, (errcode(ERRCODE_QUERY_CANCELED), + errmsg("COPY data failed: %s", pq_getmsgstring(copyData)))); + break; + case 'H': /* Flush */ + case 'S': /* Sync */ + /* + * Ignore Flush/Sync for the convenience of client libraries (such + * as libpq) that may send those without noticing that the command + * they just sent was COPY. + */ + copyDone = false; + break; + default: + ereport(ERROR, (errcode(ERRCODE_PROTOCOL_VIOLATION), + errmsg("unexpected message type 0x%02X during COPY data", + messageType))); + break; + } + + return copyDone; +} diff --git a/src/backend/distributed/executor/multi_client_executor.c b/src/backend/distributed/executor/multi_client_executor.c new file mode 100644 index 000000000..e6b4ceef7 --- /dev/null +++ b/src/backend/distributed/executor/multi_client_executor.c @@ -0,0 +1,861 @@ +/*------------------------------------------------------------------------- + * + * multi_client_executor.c + * + * This file contains the libpq-specific parts of executing queries on remote + * nodes. + * + * Copyright (c) 2012, Citus Data, Inc. + * + * $Id$ + * + *------------------------------------------------------------------------- + */ + +#include "postgres.h" +#include "fmgr.h" +#include "libpq-fe.h" +#include "distributed/multi_client_executor.h" + +#include +#include + +#ifdef HAVE_POLL_H +#include +#endif +#ifdef HAVE_SYS_POLL_H +#include +#endif +#ifdef HAVE_SYS_SELECT_H +#include +#endif + + +/* Local pool to track active connections */ +static PGconn *ClientConnectionArray[MAX_CONNECTION_COUNT]; + +/* + * The value at any position on ClientPollingStatusArray is only defined when + * the corresponding ClientConnectionArray entry exists. + */ +static PostgresPollingStatusType ClientPollingStatusArray[MAX_CONNECTION_COUNT]; + + +/* Local functions forward declarations */ +static void ClearRemainingResults(PGconn *connection); +static bool ClientConnectionReady(PGconn *connection, + PostgresPollingStatusType pollingStatus); +static void ReportRemoteError(PGconn *connection, PGresult *result); +static void ReportConnectionError(PGconn *connection); +static char * ConnectionGetOptionValue(PGconn *connection, char *optionKeyword); + + +/* AllocateConnectionId returns a connection id from the connection pool. */ +static int32 +AllocateConnectionId(void) +{ + int32 connectionId = INVALID_CONNECTION_ID; + int32 connIndex = 0; + + /* allocate connectionId from connection pool */ + for (connIndex = 0; connIndex < MAX_CONNECTION_COUNT; connIndex++) + { + PGconn *connection = ClientConnectionArray[connIndex]; + if (connection == NULL) + { + connectionId = connIndex; + break; + } + } + + return connectionId; +} + + +/* + * MultiClientConnect synchronously tries to establish a connection. If it + * succeeds, it returns the connection id. Otherwise, it reports connection + * error and returns INVALID_CONNECTION_ID. + */ +int32 +MultiClientConnect(const char *nodeName, uint32 nodePort, const char *nodeDatabase) +{ + PGconn *connection = NULL; + char connInfoString[STRING_BUFFER_SIZE]; + ConnStatusType connStatusType = CONNECTION_OK; + + int32 connectionId = AllocateConnectionId(); + if (connectionId == INVALID_CONNECTION_ID) + { + ereport(WARNING, (errmsg("could not allocate connection in connection pool"))); + return connectionId; + } + + /* transcribe connection paremeters to string */ + snprintf(connInfoString, STRING_BUFFER_SIZE, CONN_INFO_TEMPLATE, + nodeName, nodePort, nodeDatabase, CLIENT_CONNECT_TIMEOUT); + + /* establish synchronous connection to worker node */ + connection = PQconnectdb(connInfoString); + connStatusType = PQstatus(connection); + + if (connStatusType == CONNECTION_OK) + { + ClientConnectionArray[connectionId] = connection; + } + else + { + ReportConnectionError(connection); + + PQfinish(connection); + connectionId = INVALID_CONNECTION_ID; + } + + return connectionId; +} + + +/* + * MultiClientConnectStart asynchronously tries to establish a connection. If it + * succeeds, it returns the connection id. Otherwise, it reports connection + * error and returns INVALID_CONNECTION_ID. + */ +int32 +MultiClientConnectStart(const char *nodeName, uint32 nodePort, const char *nodeDatabase) +{ + PGconn *connection = NULL; + char connInfoString[STRING_BUFFER_SIZE]; + ConnStatusType connStatusType = CONNECTION_BAD; + + int32 connectionId = AllocateConnectionId(); + if (connectionId == INVALID_CONNECTION_ID) + { + ereport(WARNING, (errmsg("could not allocate connection in connection pool"))); + return connectionId; + } + + /* transcribe connection paremeters to string */ + snprintf(connInfoString, STRING_BUFFER_SIZE, CONN_INFO_TEMPLATE, + nodeName, nodePort, nodeDatabase, CLIENT_CONNECT_TIMEOUT); + + /* prepare asynchronous request for worker node connection */ + connection = PQconnectStart(connInfoString); + connStatusType = PQstatus(connection); + + /* + * If prepared, we save the connection, and set its initial polling status + * to PGRES_POLLING_WRITING as specified in "Database Connection Control + * Functions" section of the PostgreSQL documentation. + */ + if (connStatusType != CONNECTION_BAD) + { + ClientConnectionArray[connectionId] = connection; + ClientPollingStatusArray[connectionId] = PGRES_POLLING_WRITING; + } + else + { + ReportConnectionError(connection); + + PQfinish(connection); + connectionId = INVALID_CONNECTION_ID; + } + + return connectionId; +} + + +/* MultiClientConnectPoll returns the status of client connection. */ +ConnectStatus +MultiClientConnectPoll(int32 connectionId) +{ + PGconn *connection = NULL; + PostgresPollingStatusType pollingStatus = PGRES_POLLING_OK; + ConnectStatus connectStatus = CLIENT_INVALID_CONNECT; + + Assert(connectionId != INVALID_CONNECTION_ID); + connection = ClientConnectionArray[connectionId]; + Assert(connection != NULL); + + pollingStatus = ClientPollingStatusArray[connectionId]; + if (pollingStatus == PGRES_POLLING_OK) + { + connectStatus = CLIENT_CONNECTION_READY; + } + else if (pollingStatus == PGRES_POLLING_READING) + { + bool readReady = ClientConnectionReady(connection, PGRES_POLLING_READING); + if (readReady) + { + ClientPollingStatusArray[connectionId] = PQconnectPoll(connection); + } + + connectStatus = CLIENT_CONNECTION_BUSY; + } + else if (pollingStatus == PGRES_POLLING_WRITING) + { + bool writeReady = ClientConnectionReady(connection, PGRES_POLLING_WRITING); + if (writeReady) + { + ClientPollingStatusArray[connectionId] = PQconnectPoll(connection); + } + + connectStatus = CLIENT_CONNECTION_BUSY; + } + else if (pollingStatus == PGRES_POLLING_FAILED) + { + ReportConnectionError(connection); + + connectStatus = CLIENT_CONNECTION_BAD; + } + + return connectStatus; +} + + +/* MultiClientDisconnect disconnects the connection. */ +void +MultiClientDisconnect(int32 connectionId) +{ + PGconn *connection = NULL; + const int InvalidPollingStatus = -1; + + Assert(connectionId != INVALID_CONNECTION_ID); + connection = ClientConnectionArray[connectionId]; + Assert(connection != NULL); + + PQfinish(connection); + + ClientConnectionArray[connectionId] = NULL; + ClientPollingStatusArray[connectionId] = InvalidPollingStatus; +} + + +/* + * MultiClientConnectionUp checks if the connection status is up, in other words, + * it is not bad. + */ +bool +MultiClientConnectionUp(int32 connectionId) +{ + PGconn *connection = NULL; + ConnStatusType connStatusType = CONNECTION_OK; + bool connectionUp = true; + + Assert(connectionId != INVALID_CONNECTION_ID); + connection = ClientConnectionArray[connectionId]; + Assert(connection != NULL); + + connStatusType = PQstatus(connection); + if (connStatusType == CONNECTION_BAD) + { + connectionUp = false; + } + + return connectionUp; +} + + +/* MultiClientSendQuery sends the given query over the given connection. */ +bool +MultiClientSendQuery(int32 connectionId, const char *query) +{ + PGconn *connection = NULL; + bool success = true; + int querySent = 0; + + Assert(connectionId != INVALID_CONNECTION_ID); + connection = ClientConnectionArray[connectionId]; + Assert(connection != NULL); + + querySent = PQsendQuery(connection, query); + if (querySent == 0) + { + char *errorMessage = PQerrorMessage(connection); + ereport(WARNING, (errmsg("could not send remote query \"%s\"", query), + errdetail("Client error: %s", errorMessage))); + + success = false; + } + + return success; +} + + +/* MultiClientCancel cancels the running query on the given connection. */ +bool +MultiClientCancel(int32 connectionId) +{ + PGconn *connection = NULL; + PGcancel *cancelObject = NULL; + int cancelSent = 0; + bool canceled = true; + char errorBuffer[STRING_BUFFER_SIZE]; + + Assert(connectionId != INVALID_CONNECTION_ID); + connection = ClientConnectionArray[connectionId]; + Assert(connection != NULL); + + cancelObject = PQgetCancel(connection); + + cancelSent = PQcancel(cancelObject, errorBuffer, sizeof(errorBuffer)); + if (cancelSent == 0) + { + ereport(WARNING, (errmsg("could not issue cancel request"), + errdetail("Client error: %s", errorBuffer))); + + canceled = false; + } + + PQfreeCancel(cancelObject); + + return canceled; +} + + +/* MultiClientResultStatus checks result status for an asynchronous query. */ +ResultStatus +MultiClientResultStatus(int32 connectionId) +{ + PGconn *connection = NULL; + int consumed = 0; + ConnStatusType connStatusType = CONNECTION_OK; + ResultStatus resultStatus = CLIENT_INVALID_RESULT_STATUS; + + Assert(connectionId != INVALID_CONNECTION_ID); + connection = ClientConnectionArray[connectionId]; + Assert(connection != NULL); + + connStatusType = PQstatus(connection); + if (connStatusType == CONNECTION_BAD) + { + ereport(WARNING, (errmsg("could not maintain connection to worker node"))); + return CLIENT_RESULT_UNAVAILABLE; + } + + /* consume input to allow status change */ + consumed = PQconsumeInput(connection); + if (consumed != 0) + { + int connectionBusy = PQisBusy(connection); + if (connectionBusy == 0) + { + resultStatus = CLIENT_RESULT_READY; + } + else + { + resultStatus = CLIENT_RESULT_BUSY; + } + } + else + { + ereport(WARNING, (errmsg("could not consume data from worker node"))); + resultStatus = CLIENT_RESULT_UNAVAILABLE; + } + + return resultStatus; +} + + +/* MultiClientQueryResult gets results for an asynchronous query. */ +bool +MultiClientQueryResult(int32 connectionId, void **queryResult, int *rowCount, + int *columnCount) +{ + PGconn *connection = NULL; + PGresult *result = NULL; + ConnStatusType connStatusType = CONNECTION_OK; + ExecStatusType resultStatus = PGRES_COMMAND_OK; + + Assert(connectionId != INVALID_CONNECTION_ID); + connection = ClientConnectionArray[connectionId]; + Assert(connection != NULL); + + connStatusType = PQstatus(connection); + if (connStatusType == CONNECTION_BAD) + { + ereport(WARNING, (errmsg("could not maintain connection to worker node"))); + return false; + } + + result = PQgetResult(connection); + resultStatus = PQresultStatus(result); + if (resultStatus == PGRES_TUPLES_OK) + { + (*queryResult) = (void **) result; + (*rowCount) = PQntuples(result); + (*columnCount) = PQnfields(result); + } + else + { + ReportRemoteError(connection, result); + PQclear(result); + } + + /* clear extra result objects */ + ClearRemainingResults(connection); + + return true; +} + + +/* + * MultiClientBatchResult returns results for a "batch" of queries, meaning a + * string containing multiple select statements separated by semicolons. This + * function should be called multiple times to retrieve the results for all the + * queries, until CLIENT_BATCH_QUERY_DONE is returned (even if a failure occurs). + * If a query in the batch fails, the remaining queries will not be executed. On + * success, queryResult, rowCount and columnCount will be set to the appropriate + * values. After use, queryResult should be cleared using ClientClearResult. + */ +BatchQueryStatus +MultiClientBatchResult(int32 connectionId, void **queryResult, int *rowCount, + int *columnCount) +{ + PGconn *connection = NULL; + PGresult *result = NULL; + ConnStatusType connStatusType = CONNECTION_OK; + ExecStatusType resultStatus = PGRES_COMMAND_OK; + BatchQueryStatus queryStatus = CLIENT_INVALID_BATCH_QUERY; + + Assert(connectionId != INVALID_CONNECTION_ID); + connection = ClientConnectionArray[connectionId]; + Assert(connection != NULL); + + /* set default result */ + (*queryResult) = NULL; + (*rowCount) = -1; + (*columnCount) = -1; + + connStatusType = PQstatus(connection); + if (connStatusType == CONNECTION_BAD) + { + ereport(WARNING, (errmsg("could not maintain connection to worker node"))); + return CLIENT_BATCH_QUERY_FAILED; + } + + result = PQgetResult(connection); + if (result == NULL) + { + return CLIENT_BATCH_QUERY_DONE; + } + + resultStatus = PQresultStatus(result); + if (resultStatus == PGRES_TUPLES_OK) + { + (*queryResult) = (void **) result; + (*rowCount) = PQntuples(result); + (*columnCount) = PQnfields(result); + queryStatus = CLIENT_BATCH_QUERY_CONTINUE; + } + else if (resultStatus == PGRES_COMMAND_OK) + { + (*queryResult) = (void **) result; + queryStatus = CLIENT_BATCH_QUERY_CONTINUE; + } + else + { + ReportRemoteError(connection, result); + PQclear(result); + queryStatus = CLIENT_BATCH_QUERY_FAILED; + } + + return queryStatus; +} + + +/* MultiClientGetValue returns the value of field at the given position. */ +char * +MultiClientGetValue(void *queryResult, int rowIndex, int columnIndex) +{ + char *value = PQgetvalue((PGresult *) queryResult, rowIndex, columnIndex); + return value; +} + + +/* MultiClientClearResult free's the memory associated with a PGresult. */ +void +MultiClientClearResult(void *queryResult) +{ + PQclear((PGresult *) queryResult); +} + + +/* MultiClientQueryStatus returns the query status. */ +QueryStatus +MultiClientQueryStatus(int32 connectionId) +{ + PGconn *connection = NULL; + PGresult *result = NULL; + int tupleCount = 0; + bool copyResults = false; + ConnStatusType connStatusType = CONNECTION_OK; + ExecStatusType resultStatus = PGRES_COMMAND_OK; + QueryStatus queryStatus = CLIENT_INVALID_QUERY; + + Assert(connectionId != INVALID_CONNECTION_ID); + connection = ClientConnectionArray[connectionId]; + Assert(connection != NULL); + + connStatusType = PQstatus(connection); + if (connStatusType == CONNECTION_BAD) + { + ereport(WARNING, (errmsg("could not maintain connection to worker node"))); + return CLIENT_QUERY_FAILED; + } + + /* + * We now read the result object and check its status. If the result object + * isn't ready yet (the caller didn't wait for the connection to be ready), + * we will block on this call. + */ + result = PQgetResult(connection); + resultStatus = PQresultStatus(result); + + if (resultStatus == PGRES_COMMAND_OK) + { + queryStatus = CLIENT_QUERY_DONE; + } + else if (resultStatus == PGRES_TUPLES_OK) + { + queryStatus = CLIENT_QUERY_DONE; + + /* + * We use the client executor to only issue a select query that returns + * a void value. We therefore should not have more than one value here. + */ + tupleCount = PQntuples(result); + Assert(tupleCount <= 1); + } + else if (resultStatus == PGRES_COPY_OUT) + { + queryStatus = CLIENT_QUERY_COPY; + copyResults = true; + } + else + { + queryStatus = CLIENT_QUERY_FAILED; + if (resultStatus == PGRES_COPY_IN) + { + copyResults = true; + } + + ReportRemoteError(connection, result); + } + + /* clear the result object */ + PQclear(result); + + /* + * When using the async query mechanism, we need to keep reading results + * until we get null. The exception to this rule is the copy protocol. + */ + if (!copyResults) + { + ClearRemainingResults(connection); + } + + return queryStatus; +} + + +/* MultiClientCopyData copies data from the file. */ +CopyStatus +MultiClientCopyData(int32 connectionId, int32 fileDescriptor) +{ + PGconn *connection = NULL; + char *receiveBuffer = NULL; + int consumed = 0; + int receiveLength = 0; + const int asynchronous = 1; + CopyStatus copyStatus = CLIENT_INVALID_COPY; + + Assert(connectionId != INVALID_CONNECTION_ID); + connection = ClientConnectionArray[connectionId]; + Assert(connection != NULL); + + /* + * Consume input to handle the case where previous copy operation might have + * received zero bytes. + */ + consumed = PQconsumeInput(connection); + if (consumed == 0) + { + ereport(WARNING, (errmsg("could not read data from worker node"))); + return CLIENT_COPY_FAILED; + } + + /* receive copy data message in an asynchronous manner */ + receiveLength = PQgetCopyData(connection, &receiveBuffer, asynchronous); + while (receiveLength > 0) + { + /* received copy data; append these data to file */ + int appended = -1; + errno = 0; + + appended = write(fileDescriptor, receiveBuffer, receiveLength); + if (appended != receiveLength) + { + /* if write didn't set errno, assume problem is no disk space */ + if (errno == 0) + { + errno = ENOSPC; + } + ereport(FATAL, (errcode_for_file_access(), + errmsg("could not append to copied file: %m"))); + } + + PQfreemem(receiveBuffer); + + receiveLength = PQgetCopyData(connection, &receiveBuffer, asynchronous); + } + + /* we now check the last received length returned by copy data */ + if (receiveLength == 0) + { + /* we cannot read more data without blocking */ + copyStatus = CLIENT_COPY_MORE; + } + else if (receiveLength == -1) + { + /* received copy done message */ + PGresult *result = PQgetResult(connection); + ExecStatusType resultStatus = PQresultStatus(result); + + if (resultStatus == PGRES_COMMAND_OK) + { + copyStatus = CLIENT_COPY_DONE; + } + else + { + copyStatus = CLIENT_COPY_FAILED; + + ReportRemoteError(connection, result); + } + + PQclear(result); + } + else if (receiveLength == -2) + { + /* received an error */ + copyStatus = CLIENT_COPY_FAILED; + + ReportConnectionError(connection); + } + + /* if copy out completed, make sure we drain all results from libpq */ + if (receiveLength < 0) + { + ClearRemainingResults(connection); + } + + return copyStatus; +} + + +/* + * ClearRemainingResults reads result objects from the connection until we get + * null, and clears these results. This is the last step in completing an async + * query. + */ +static void +ClearRemainingResults(PGconn *connection) +{ + PGresult *result = PQgetResult(connection); + while (result != NULL) + { + PQclear(result); + result = PQgetResult(connection); + } +} + + +/* + * ClientConnectionReady checks if the given connection is ready for non-blocking + * reads or writes. This function is loosely based on pqSocketCheck() at fe-misc.c + * and libpq_select() at libpqwalreceiver.c. + */ +static bool +ClientConnectionReady(PGconn *connection, PostgresPollingStatusType pollingStatus) +{ + bool clientConnectionReady = false; + int pollResult = 0; + + /* we use poll(2) if available, otherwise select(2) */ +#ifdef HAVE_POLL + int fileDescriptorCount = 1; + int immediateTimeout = 0; + int pollEventMask = 0; + struct pollfd pollFileDescriptor; + + if (pollingStatus == PGRES_POLLING_READING) + { + pollEventMask = POLLERR | POLLIN; + } + else if (pollingStatus == PGRES_POLLING_WRITING) + { + pollEventMask = POLLERR | POLLOUT; + } + + pollFileDescriptor.fd = PQsocket(connection); + pollFileDescriptor.events = pollEventMask; + pollFileDescriptor.revents = 0; + + pollResult = poll(&pollFileDescriptor, fileDescriptorCount, immediateTimeout); +#else /* !HAVE_POLL */ + + fd_set readFileDescriptorSet; + fd_set writeFileDescriptorSet; + fd_set exceptionFileDescriptorSet; + struct timeval immediateTimeout = {0, 0}; + int connectionFileDescriptor = PQsocket(connection); + + FD_ZERO(&readFileDescriptorSet); + FD_ZERO(&writeFileDescriptorSet); + FD_ZERO(&exceptionFileDescriptorSet); + + if (pollingStatus == PGRES_POLLING_READING) + { + FD_SET(connectionFileDescriptor, &exceptionFileDescriptorSet); + FD_SET(connectionFileDescriptor, &readFileDescriptorSet); + } + else if (pollingStatus == PGRES_POLLING_WRITING) + { + FD_SET(connectionFileDescriptor, &exceptionFileDescriptorSet); + FD_SET(connectionFileDescriptor, &writeFileDescriptorSet); + } + + pollResult = select(connectionFileDescriptor + 1, &readFileDescriptorSet, + &writeFileDescriptorSet, &exceptionFileDescriptorSet, + &immediateTimeout); +#endif /* HAVE_POLL */ + + if (pollResult > 0) + { + clientConnectionReady = true; + } + else if (pollResult == 0) + { + clientConnectionReady = false; + } + else if (pollResult < 0) + { + if (errno == EINTR) + { + /* + * If a signal was caught, we return false so the caller polls the + * connection again. + */ + clientConnectionReady = false; + } + else + { + /* + * poll() or select() can set errno to EFAULT (when socket is not + * contained in the calling program's address space), EBADF (invalid + * file descriptor), EINVAL (invalid arguments to select or poll), + * and ENOMEM (no space to allocate file descriptor tables). Out of + * these, only ENOMEM is likely here, and it is a fatal error, so we + * error out. + */ + Assert(errno == ENOMEM); + ereport(ERROR, (errcode_for_socket_access(), + errmsg("select()/poll() failed: %m"))); + } + } + + return clientConnectionReady; +} + + +/* + * ReportRemoteError retrieves various error fields from the a remote result and + * produces an error report at the WARNING level. + */ +static void +ReportRemoteError(PGconn *connection, PGresult *result) +{ + char *sqlStateString = PQresultErrorField(result, PG_DIAG_SQLSTATE); + char *remoteMessage = PQresultErrorField(result, PG_DIAG_MESSAGE_PRIMARY); + char *nodeName = ConnectionGetOptionValue(connection, "host"); + char *nodePort = ConnectionGetOptionValue(connection, "port"); + char *errorPrefix = "could not connect to node"; + int sqlState = ERRCODE_CONNECTION_FAILURE; + + if (sqlStateString != NULL) + { + sqlState = MAKE_SQLSTATE(sqlStateString[0], sqlStateString[1], sqlStateString[2], + sqlStateString[3], sqlStateString[4]); + + /* use more specific error prefix for result failures */ + if (sqlState != ERRCODE_CONNECTION_FAILURE) + { + errorPrefix = "could not receive query results from"; + } + } + + /* + * If the PGresult did not contain a message, the connection may provide a + * suitable top level one. At worst, this is an empty string. + */ + if (remoteMessage == NULL) + { + char *lastNewlineIndex = NULL; + + remoteMessage = PQerrorMessage(connection); + lastNewlineIndex = strrchr(remoteMessage, '\n'); + + /* trim trailing newline, if any */ + if (lastNewlineIndex != NULL) + { + *lastNewlineIndex = '\0'; + } + } + + ereport(WARNING, (errcode(sqlState), + errmsg("%s %s:%s", errorPrefix, nodeName, nodePort), + errdetail("Client error: %s", remoteMessage))); +} + + +/* + * ReportConnectionError raises a WARNING and reports that we could not + * establish the given connection. + */ +static void +ReportConnectionError(PGconn *connection) +{ + char *nodeName = ConnectionGetOptionValue(connection, "host"); + char *nodePort = ConnectionGetOptionValue(connection, "port"); + char *errorMessage = PQerrorMessage(connection); + + ereport(WARNING, (errcode(ERRCODE_CONNECTION_FAILURE), + errmsg("could not connect to node %s:%s", nodeName, nodePort), + errdetail("Client error: %s", errorMessage))); +} + + +/* + * ConnectionGetOptionValue inspects the provided connection for an option with + * a given keyword and returns a new palloc'd string with that options's value. + * The function returns NULL if the connection has no setting for an option with + * the provided keyword. + */ +static char * +ConnectionGetOptionValue(PGconn *connection, char *optionKeyword) +{ + char *optionValue = NULL; + PQconninfoOption *option = NULL; + PQconninfoOption *conninfoOptions = PQconninfo(connection); + + for (option = conninfoOptions; option->keyword != NULL; option++) + { + if (strncmp(option->keyword, optionKeyword, NAMEDATALEN) == 0) + { + optionValue = pstrdup(option->val); + } + } + + PQconninfoFree(conninfoOptions); + + return optionValue; +} diff --git a/src/backend/distributed/executor/multi_executor.c b/src/backend/distributed/executor/multi_executor.c new file mode 100644 index 000000000..25fd12640 --- /dev/null +++ b/src/backend/distributed/executor/multi_executor.c @@ -0,0 +1,278 @@ +/*------------------------------------------------------------------------- + * + * multi_executor.c + * + * Entrypoint into distributed query execution. + * + * Copyright (c) 2012-2015, Citus Data, Inc. + *------------------------------------------------------------------------- + */ + +#include "postgres.h" + +#include "miscadmin.h" + +#include "access/xact.h" +#include "catalog/dependency.h" +#include "catalog/namespace.h" +#include "distributed/multi_executor.h" +#include "distributed/multi_master_planner.h" +#include "distributed/multi_planner.h" +#include "distributed/multi_router_executor.h" +#include "distributed/multi_resowner.h" +#include "distributed/multi_server_executor.h" +#include "distributed/multi_utility.h" +#include "distributed/worker_protocol.h" +#include "executor/execdebug.h" +#include "storage/lmgr.h" +#include "tcop/utility.h" +#include "utils/snapmgr.h" + + +/* + * multi_ExecutorStart is a hook called at at the beginning of any execution + * of any query plan. + * + * If a distributed relation is the target of the query, perform some validity + * checks. If a legal statement, start the distributed execution. After that + * the to-be-executed query is replaced with the portion executing solely on + * the master. + */ +void +multi_ExecutorStart(QueryDesc *queryDesc, int eflags) +{ + PlannedStmt *planStatement = queryDesc->plannedstmt; + + if (HasCitusToplevelNode(planStatement)) + { + MultiPlan *multiPlan = GetMultiPlan(planStatement); + MultiExecutorType executorType = MULTI_EXECUTOR_INVALID_FIRST; + Job *workerJob = multiPlan->workerJob; + + executorType = JobExecutorType(multiPlan); + if (executorType == MULTI_EXECUTOR_ROUTER) + { + Task *task = NULL; + List *taskList = workerJob->taskList; + List *dependendJobList PG_USED_FOR_ASSERTS_ONLY = workerJob->dependedJobList; + List *workerTargetList = multiPlan->workerJob->jobQuery->targetList; + TupleDesc tupleDescriptor = ExecCleanTypeFromTL(workerTargetList, false); + + /* router executor can only execute distributed plans with a single task */ + Assert(list_length(taskList) == 1); + Assert(dependendJobList == NIL); + + task = (Task *) linitial(taskList); + + /* we need to set tupleDesc in executorStart */ + queryDesc->tupDesc = tupleDescriptor; + + /* drop into the router executor */ + RouterExecutorStart(queryDesc, eflags, task); + } + else + { + PlannedStmt *masterSelectPlan = MasterNodeSelectPlan(multiPlan); + CreateStmt *masterCreateStmt = MasterNodeCreateStatement(multiPlan); + List *masterCopyStmtList = MasterNodeCopyStatementList(multiPlan); + ListCell *masterCopyStmtCell = NULL; + RangeTblEntry *masterRangeTableEntry = NULL; + StringInfo jobDirectoryName = NULL; + + /* + * We create a directory on the master node to keep task execution results. + * We also register this directory for automatic cleanup on portal delete. + */ + jobDirectoryName = JobDirectoryName(workerJob->jobId); + CreateDirectory(jobDirectoryName); + + ResourceOwnerEnlargeJobDirectories(CurrentResourceOwner); + ResourceOwnerRememberJobDirectory(CurrentResourceOwner, workerJob->jobId); + + /* pick distributed executor to use */ + if (executorType == MULTI_EXECUTOR_REAL_TIME) + { + MultiRealTimeExecute(workerJob); + } + else if (executorType == MULTI_EXECUTOR_TASK_TRACKER) + { + MultiTaskTrackerExecute(workerJob); + } + + /* then create the result relation */ + ProcessUtility((Node *) masterCreateStmt, + "(temp table creation)", + PROCESS_UTILITY_QUERY, + NULL, + None_Receiver, + NULL); + + /* make the temporary table visible */ + CommandCounterIncrement(); + + /* now copy data from all the remote nodes into temp table */ + foreach(masterCopyStmtCell, masterCopyStmtList) + { + Node *masterCopyStmt = (Node *) lfirst(masterCopyStmtCell); + + Assert(IsA(masterCopyStmt, CopyStmt)); + + ProcessUtility(masterCopyStmt, + "(copy job)", + PROCESS_UTILITY_QUERY, + NULL, + None_Receiver, + NULL); + } + + /* make the copied contents visible */ + CommandCounterIncrement(); + + /* + * Update the QueryDesc's snapshot so it sees the table. That's not + * particularly pretty, but we don't have much of a choice. One might + * think we could unregister the snapshot, push a new active one, + * update it, register it, and be happy. That only works if it's only + * registered once though... + */ + queryDesc->snapshot->curcid = GetCurrentCommandId(false); + + /* + * Set the OID of the RTE used in the master select statement to point + * to the now created (and filled) temporary table. The target + * relation's oid is only known now. + */ + masterRangeTableEntry = + (RangeTblEntry *) linitial(masterSelectPlan->rtable); + masterRangeTableEntry->relid = + RelnameGetRelid(masterRangeTableEntry->eref->aliasname); + + /* + * Replace to-be-run query with the master select query. As the + * planned statement is now replaced we can't call GetMultiPlan() in + * the later hooks, so we set a flag marking this as a distributed + * statement running on the master. That e.g. allows us to drop the + * temp table later. + */ + queryDesc->plannedstmt = masterSelectPlan; + eflags |= EXEC_FLAG_CITUS_MASTER_SELECT; + } + + } + + /* if the execution is not done for router executor, drop into standard executor */ + if (queryDesc->estate == NULL || + !(queryDesc->estate->es_top_eflags & EXEC_FLAG_CITUS_ROUTER_EXECUTOR)) + { + standard_ExecutorStart(queryDesc, eflags); + } +} + + +/* Execute query plan. */ +void +multi_ExecutorRun(QueryDesc *queryDesc, ScanDirection direction, long count) +{ + int eflags = queryDesc->estate->es_top_eflags; + + if (eflags & EXEC_FLAG_CITUS_ROUTER_EXECUTOR) + { + Task *task = NULL; + PlannedStmt *planStatement = queryDesc->plannedstmt; + MultiPlan *multiPlan = GetMultiPlan(planStatement); + List *taskList = multiPlan->workerJob->taskList; + + /* router executor can only execute distributed plans with a single task */ + Assert(list_length(taskList) == 1); + + task = (Task *) linitial(taskList); + + /* drop into the router executor */ + RouterExecutorRun(queryDesc, direction, count, task); + } + else + { + /* drop into the standard executor */ + standard_ExecutorRun(queryDesc, direction, count); + } +} + + +/* Perform actions, like e.g. firing triggers, after the query has run. */ +void +multi_ExecutorFinish(QueryDesc *queryDesc) +{ + int eflags = queryDesc->estate->es_top_eflags; + + if (eflags & EXEC_FLAG_CITUS_ROUTER_EXECUTOR) + { + /* drop into the router executor */ + RouterExecutorFinish(queryDesc); + } + else + { + /* drop into the standard executor */ + standard_ExecutorFinish(queryDesc); + } +} + + +/* + * multi_ExecutorEnd is a hook called to deallocate resources used during + * query execution. + * + * If the query executed was the portion of a distributed query running on the + * master, remove the resources that were needed for distributed execution. + */ +void +multi_ExecutorEnd(QueryDesc *queryDesc) +{ + int eflags = queryDesc->estate->es_top_eflags; + + if (eflags & EXEC_FLAG_CITUS_ROUTER_EXECUTOR) + { + /* drop into the router executor */ + RouterExecutorEnd(queryDesc); + } + else + { + /* drop into the standard executor */ + standard_ExecutorEnd(queryDesc); + } + + /* + * Final step of a distributed query is executing the master node select + * query. We clean up the temp tables after executing it, if we already created it. + */ + if (eflags & EXEC_FLAG_CITUS_MASTER_SELECT) + { + PlannedStmt *planStatement = queryDesc->plannedstmt; + int savedLogMinMessages = 0; + int savedClientMinMessages = 0; + + RangeTblEntry *rangeTableEntry = linitial(planStatement->rtable); + Oid masterTableRelid = rangeTableEntry->relid; + + ObjectAddress masterTableObject = {InvalidOid, InvalidOid, 0}; + + masterTableObject.classId = RelationRelationId; + masterTableObject.objectId = masterTableRelid; + masterTableObject.objectSubId = 0; + + /* + * Temporarily change logging level to avoid DEBUG2 logging output by + * performDeletion. This avoids breaking the regression tests which + * use DEBUG2 logging. + */ + savedLogMinMessages = log_min_messages; + savedClientMinMessages = client_min_messages; + + log_min_messages = INFO; + client_min_messages = INFO; + + performDeletion(&masterTableObject, DROP_RESTRICT, PERFORM_DELETION_INTERNAL); + + log_min_messages = savedLogMinMessages; + client_min_messages = savedClientMinMessages; + } +} diff --git a/src/backend/distributed/executor/multi_real_time_executor.c b/src/backend/distributed/executor/multi_real_time_executor.c new file mode 100644 index 000000000..77436612c --- /dev/null +++ b/src/backend/distributed/executor/multi_real_time_executor.c @@ -0,0 +1,862 @@ +/*------------------------------------------------------------------------- + * + * multi_real_time_executor.c + * + * Routines for executing remote tasks as part of a distributed execution plan + * in real-time. These routines open up a separate connection for each task they + * need to execute, and therefore return their results faster. However, they can + * only handle as many tasks as the number of file descriptors (connections) + * available. They also can't handle execution primitives that need to write + * their results to intermediate files. + * + * Copyright (c) 2013, Citus Data, Inc. + * + * $Id$ + * + *------------------------------------------------------------------------- + */ + +#include "postgres.h" +#include "miscadmin.h" + +#include + +#include "commands/dbcommands.h" +#include "distributed/multi_client_executor.h" +#include "distributed/multi_physical_planner.h" +#include "distributed/multi_server_executor.h" +#include "distributed/worker_protocol.h" +#include "storage/fd.h" + + +/* Local functions forward declarations */ +static ConnectAction ManageTaskExecution(Task *task, TaskExecution *taskExecution); +static bool TaskExecutionReadyToStart(TaskExecution *taskExecution); +static bool TaskExecutionCompleted(TaskExecution *taskExecution); +static void CancelTaskExecutionIfActive(TaskExecution *taskExecution); +static void CancelRequestIfActive(TaskExecStatus taskStatus, int connectionId); + +/* Worker node state hash functions */ +static HTAB * WorkerHash(const char *workerHashName, List *workerNodeList); +static HTAB * WorkerHashCreate(const char *workerHashName, uint32 workerHashSize); +static WorkerNodeState * WorkerHashEnter(HTAB *workerHash, + char *nodeName, uint32 nodePort); +static WorkerNodeState * WorkerHashLookup(HTAB *workerHash, + const char *nodeName, uint32 nodePort); +static WorkerNodeState * LookupWorkerForTask(HTAB *workerHash, Task *task, + TaskExecution *taskExecution); + +/* Throttling functions */ +static bool WorkerConnectionsExhausted(WorkerNodeState *workerNodeState); +static bool MasterConnectionsExhausted(HTAB *workerHash); +static uint32 TotalOpenConnectionCount(HTAB *workerHash); +static void UpdateConnectionCounter(WorkerNodeState *workerNode, + ConnectAction connectAction); + + +/* + * MultiRealTimeExecute loops over the given tasks, and manages their execution + * until either one task permanently fails or all tasks successfully complete. + * The function opens up a connection for each task it needs to execute, and + * manages these tasks' execution in real-time. + */ +void +MultiRealTimeExecute(Job *job) +{ + List *taskList = job->taskList; + List *taskExecutionList = NIL; + ListCell *taskExecutionCell = NULL; + ListCell *taskCell = NULL; + uint32 failedTaskId = 0; + bool allTasksCompleted = false; + bool taskCompleted = false; + bool taskFailed = false; + + List *workerNodeList = NIL; + HTAB *workerHash = NULL; + const char *workerHashName = "Worker node hash"; + + workerNodeList = WorkerNodeList(); + workerHash = WorkerHash(workerHashName, workerNodeList); + + /* initialize task execution structures for remote execution */ + foreach(taskCell, taskList) + { + Task *task = (Task *) lfirst(taskCell); + + TaskExecution *taskExecution = InitTaskExecution(task, EXEC_TASK_CONNECT_START); + taskExecutionList = lappend(taskExecutionList, taskExecution); + } + + /* loop around until all tasks complete, one task fails, or user cancels */ + while ( !(allTasksCompleted || taskFailed || QueryCancelPending) ) + { + uint32 taskCount = list_length(taskList); + uint32 completedTaskCount = 0; + + /* loop around all tasks and manage them */ + ListCell *taskCell = NULL; + ListCell *taskExecutionCell = NULL; + + forboth(taskCell, taskList, taskExecutionCell, taskExecutionList) + { + Task *task = (Task *) lfirst(taskCell); + TaskExecution *taskExecution = (TaskExecution *) lfirst(taskExecutionCell); + ConnectAction connectAction = CONNECT_ACTION_NONE; + WorkerNodeState *workerNodeState = NULL; + + workerNodeState = LookupWorkerForTask(workerHash, task, taskExecution); + + /* in case the task is about to start, throttle if necessary */ + if (TaskExecutionReadyToStart(taskExecution) && + (WorkerConnectionsExhausted(workerNodeState) || + MasterConnectionsExhausted(workerHash))) + { + continue; + } + + /* call the function that performs the core task execution logic */ + connectAction = ManageTaskExecution(task, taskExecution); + + /* update the connection counter for throttling */ + UpdateConnectionCounter(workerNodeState, connectAction); + + /* + * If this task failed, we need to iterate over task executions, and + * manually clean out their client-side resources. Hence, we record + * the failure here instead of immediately erroring out. + */ + taskFailed = TaskExecutionFailed(taskExecution); + if (taskFailed) + { + failedTaskId = taskExecution->taskId; + break; + } + + taskCompleted = TaskExecutionCompleted(taskExecution); + if (taskCompleted) + { + completedTaskCount++; + } + } + + /* check if all tasks completed; otherwise sleep to avoid tight loop */ + if (completedTaskCount == taskCount) + { + allTasksCompleted = true; + } + else + { + long sleepIntervalPerCycle = RemoteTaskCheckInterval * 1000L; + pg_usleep(sleepIntervalPerCycle); + } + } + + /* + * We prevent cancel/die interrupts until we clean up connections to worker + * nodes. Note that for the above while loop, if the user Ctrl+C's a query + * and we emit a warning before looping to the beginning of the while loop, + * we will get canceled away before we can hold any interrupts. + */ + HOLD_INTERRUPTS(); + + /* cancel any active task executions */ + taskExecutionCell = NULL; + foreach(taskExecutionCell, taskExecutionList) + { + TaskExecution *taskExecution = (TaskExecution *) lfirst(taskExecutionCell); + CancelTaskExecutionIfActive(taskExecution); + } + + /* + * If cancel might have been sent, give remote backends some time to flush + * their responses. This avoids some broken pipe logs on the backend-side. + */ + if (taskFailed || QueryCancelPending) + { + long sleepInterval = RemoteTaskCheckInterval * 1000L; + pg_usleep(sleepInterval); + } + + /* close connections and open files */ + taskExecutionCell = NULL; + foreach(taskExecutionCell, taskExecutionList) + { + TaskExecution *taskExecution = (TaskExecution *) lfirst(taskExecutionCell); + CleanupTaskExecution(taskExecution); + } + + RESUME_INTERRUPTS(); + + /* + * If we previously broke out of the execution loop due to a task failure or + * user cancellation request, we can now safely emit an error message (all + * client-side resources have been cleared). + */ + if (taskFailed) + { + ereport(ERROR, (errmsg("failed to execute job " UINT64_FORMAT, job->jobId), + errdetail("Failure due to failed task %u", failedTaskId))); + } + else if (QueryCancelPending) + { + CHECK_FOR_INTERRUPTS(); + } +} + + +/* + * ManageTaskExecution manages all execution logic for the given task. For this, + * the function starts a new "execution" on a node, and tracks this execution's + * progress. On failure, the function restarts this execution on another node. + * Note that this function directly manages a task's execution by opening up a + * separate connection to the worker node for each execution. The function + * returns a ConnectAction enum indicating whether a connection has been opened + * or closed in this call. + */ +static ConnectAction +ManageTaskExecution(Task *task, TaskExecution *taskExecution) +{ + TaskExecStatus *taskStatusArray = taskExecution->taskStatusArray; + int32 *connectionIdArray = taskExecution->connectionIdArray; + int32 *fileDescriptorArray = taskExecution->fileDescriptorArray; + uint32 currentIndex = taskExecution->currentNodeIndex; + TaskExecStatus currentStatus = taskStatusArray[currentIndex]; + List *taskPlacementList = task->taskPlacementList; + ShardPlacement *taskPlacement = list_nth(taskPlacementList, currentIndex); + char *nodeName = taskPlacement->nodeName; + uint32 nodePort = taskPlacement->nodePort; + ConnectAction connectAction = CONNECT_ACTION_NONE; + + switch (currentStatus) + { + case EXEC_TASK_CONNECT_START: + { + int32 connectionId = INVALID_CONNECTION_ID; + char *nodeDatabase = NULL; + + /* we use the same database name on the master and worker nodes */ + nodeDatabase = get_database_name(MyDatabaseId); + + connectionId = MultiClientConnectStart(nodeName, nodePort, nodeDatabase); + connectionIdArray[currentIndex] = connectionId; + + /* if valid, poll the connection until the connection is initiated */ + if (connectionId != INVALID_CONNECTION_ID) + { + taskStatusArray[currentIndex] = EXEC_TASK_CONNECT_POLL; + taskExecution->connectPollCount = 0; + connectAction = CONNECT_ACTION_OPENED; + } + else + { + AdjustStateForFailure(taskExecution); + } + + break; + } + + case EXEC_TASK_CONNECT_POLL: + { + int32 connectionId = connectionIdArray[currentIndex]; + ConnectStatus pollStatus = MultiClientConnectPoll(connectionId); + + /* + * If the connection is established, we reset the data fetch counter and + * change our status to data fetching. + */ + if (pollStatus == CLIENT_CONNECTION_READY) + { + taskExecution->dataFetchTaskIndex = -1; + taskStatusArray[currentIndex] = EXEC_FETCH_TASK_LOOP; + } + else if (pollStatus == CLIENT_CONNECTION_BUSY) + { + taskStatusArray[currentIndex] = EXEC_TASK_CONNECT_POLL; + } + else if (pollStatus == CLIENT_CONNECTION_BAD) + { + taskStatusArray[currentIndex] = EXEC_TASK_FAILED; + } + + /* now check if we have been trying to connect for too long */ + taskExecution->connectPollCount++; + if (pollStatus == CLIENT_CONNECTION_BUSY) + { + uint32 maxCount = REMOTE_NODE_CONNECT_TIMEOUT / RemoteTaskCheckInterval; + uint32 currentCount = taskExecution->connectPollCount; + if (currentCount >= maxCount) + { + ereport(WARNING, (errmsg("could not establish asynchronous connection " + "after %u ms", REMOTE_NODE_CONNECT_TIMEOUT))); + + taskStatusArray[currentIndex] = EXEC_TASK_FAILED; + } + } + + break; + } + + case EXEC_TASK_FAILED: + { + /* + * On task failure, we close the connection. We also reset our execution + * status assuming that we might fail on all other worker nodes and come + * back to this failed node. In that case, we will retry the same fetch + * and compute task(s) on this node again. + */ + int32 connectionId = connectionIdArray[currentIndex]; + MultiClientDisconnect(connectionId); + connectionIdArray[currentIndex] = INVALID_CONNECTION_ID; + connectAction = CONNECT_ACTION_CLOSED; + + taskStatusArray[currentIndex] = EXEC_TASK_CONNECT_START; + + /* try next worker node */ + AdjustStateForFailure(taskExecution); + + break; + } + + case EXEC_FETCH_TASK_LOOP: + { + List *dataFetchTaskList = task->dependedTaskList; + int32 dataFetchTaskCount = list_length(dataFetchTaskList); + + /* move to the next data fetch task */ + taskExecution->dataFetchTaskIndex++; + + if (taskExecution->dataFetchTaskIndex < dataFetchTaskCount) + { + taskStatusArray[currentIndex] = EXEC_FETCH_TASK_START; + } + else + { + taskStatusArray[currentIndex] = EXEC_COMPUTE_TASK_START; + } + + break; + } + + case EXEC_FETCH_TASK_START: + { + List *dataFetchTaskList = task->dependedTaskList; + int32 dataFetchTaskIndex = taskExecution->dataFetchTaskIndex; + Task *dataFetchTask = (Task *) list_nth(dataFetchTaskList, dataFetchTaskIndex); + + char *dataFetchQuery = dataFetchTask->queryString; + int32 connectionId = connectionIdArray[currentIndex]; + + bool querySent = MultiClientSendQuery(connectionId, dataFetchQuery); + if (querySent) + { + taskStatusArray[currentIndex] = EXEC_FETCH_TASK_RUNNING; + } + else + { + taskStatusArray[currentIndex] = EXEC_TASK_FAILED; + } + + break; + } + + case EXEC_FETCH_TASK_RUNNING: + { + int32 connectionId = connectionIdArray[currentIndex]; + ResultStatus resultStatus = MultiClientResultStatus(connectionId); + QueryStatus queryStatus = CLIENT_INVALID_QUERY; + + /* check if query results are in progress or unavailable */ + if (resultStatus == CLIENT_RESULT_BUSY) + { + taskStatusArray[currentIndex] = EXEC_FETCH_TASK_RUNNING; + break; + } + else if (resultStatus == CLIENT_RESULT_UNAVAILABLE) + { + taskStatusArray[currentIndex] = EXEC_TASK_FAILED; + break; + } + + Assert(resultStatus == CLIENT_RESULT_READY); + + /* + * If the query executed successfully, loop onto the next data fetch + * task. Else if the query failed, try data fetching on another node. + */ + queryStatus = MultiClientQueryStatus(connectionId); + if (queryStatus == CLIENT_QUERY_DONE) + { + taskStatusArray[currentIndex] = EXEC_FETCH_TASK_LOOP; + } + else if (queryStatus == CLIENT_QUERY_FAILED) + { + taskStatusArray[currentIndex] = EXEC_TASK_FAILED; + } + else + { + ereport(FATAL, (errmsg("invalid query status: %d", queryStatus))); + } + + break; + } + + case EXEC_COMPUTE_TASK_START: + { + int32 connectionId = connectionIdArray[currentIndex]; + bool querySent = false; + + /* construct new query to copy query results to stdout */ + char *queryString = task->queryString; + StringInfo computeTaskQuery = makeStringInfo(); + if (BinaryMasterCopyFormat) + { + appendStringInfo(computeTaskQuery, COPY_QUERY_TO_STDOUT_BINARY, queryString); + } + else + { + appendStringInfo(computeTaskQuery, COPY_QUERY_TO_STDOUT_TEXT, queryString); + } + + querySent = MultiClientSendQuery(connectionId, computeTaskQuery->data); + if (querySent) + { + taskStatusArray[currentIndex] = EXEC_COMPUTE_TASK_RUNNING; + } + else + { + taskStatusArray[currentIndex] = EXEC_TASK_FAILED; + } + + break; + } + + case EXEC_COMPUTE_TASK_RUNNING: + { + int32 connectionId = connectionIdArray[currentIndex]; + ResultStatus resultStatus = MultiClientResultStatus(connectionId); + QueryStatus queryStatus = CLIENT_INVALID_QUERY; + + /* check if query results are in progress or unavailable */ + if (resultStatus == CLIENT_RESULT_BUSY) + { + taskStatusArray[currentIndex] = EXEC_COMPUTE_TASK_RUNNING; + break; + } + else if (resultStatus == CLIENT_RESULT_UNAVAILABLE) + { + taskStatusArray[currentIndex] = EXEC_TASK_FAILED; + break; + } + + Assert(resultStatus == CLIENT_RESULT_READY); + + /* check if our request to copy query results has been acknowledged */ + queryStatus = MultiClientQueryStatus(connectionId); + if (queryStatus == CLIENT_QUERY_COPY) + { + StringInfo jobDirectoryName = JobDirectoryName(task->jobId); + StringInfo taskFilename = TaskFilename(jobDirectoryName, task->taskId); + + char *filename = taskFilename->data; + int fileFlags = (O_APPEND | O_CREAT | O_RDWR | O_TRUNC | PG_BINARY); + int fileMode = (S_IRUSR | S_IWUSR); + + int32 fileDescriptor = BasicOpenFile(filename, fileFlags, fileMode); + if (fileDescriptor >= 0) + { + /* + * All files inside the job directory get automatically cleaned + * up on transaction commit or abort. + */ + fileDescriptorArray[currentIndex] = fileDescriptor; + taskStatusArray[currentIndex] = EXEC_COMPUTE_TASK_COPYING; + } + else + { + ereport(WARNING, (errcode_for_file_access(), + errmsg("could not open file \"%s\": %m", filename))); + + taskStatusArray[currentIndex] = EXEC_TASK_FAILED; + } + } + else if (queryStatus == CLIENT_QUERY_FAILED) + { + taskStatusArray[currentIndex] = EXEC_TASK_FAILED; + } + else + { + ereport(FATAL, (errmsg("invalid query status: %d", queryStatus))); + } + + break; + } + + case EXEC_COMPUTE_TASK_COPYING: + { + int32 connectionId = connectionIdArray[currentIndex]; + int32 fileDesc = fileDescriptorArray[currentIndex]; + int closed = -1; + + /* copy data from worker node, and write to local file */ + CopyStatus copyStatus = MultiClientCopyData(connectionId, fileDesc); + + /* if worker node will continue to send more data, keep reading */ + if (copyStatus == CLIENT_COPY_MORE) + { + taskStatusArray[currentIndex] = EXEC_COMPUTE_TASK_COPYING; + } + else if (copyStatus == CLIENT_COPY_DONE) + { + closed = close(fileDesc); + fileDescriptorArray[currentIndex] = -1; + + if (closed >= 0) + { + taskStatusArray[currentIndex] = EXEC_TASK_DONE; + + /* we are done executing; we no longer need the connection */ + MultiClientDisconnect(connectionId); + connectionIdArray[currentIndex] = INVALID_CONNECTION_ID; + connectAction = CONNECT_ACTION_CLOSED; + } + else + { + ereport(WARNING, (errcode_for_file_access(), + errmsg("could not close copied file: %m"))); + + taskStatusArray[currentIndex] = EXEC_TASK_FAILED; + } + } + else if (copyStatus == CLIENT_COPY_FAILED) + { + taskStatusArray[currentIndex] = EXEC_TASK_FAILED; + + closed = close(fileDesc); + fileDescriptorArray[currentIndex] = -1; + + if (closed < 0) + { + ereport(WARNING, (errcode_for_file_access(), + errmsg("could not close copy file: %m"))); + } + } + + break; + } + + case EXEC_TASK_DONE: + { + /* we are done with this task's execution */ + break; + } + + default: + { + /* we fatal here to avoid leaking client-side resources */ + ereport(FATAL, (errmsg("invalid execution status: %d", currentStatus))); + break; + } + } + + return connectAction; +} + + +/* Determines if the given task is ready to start. */ +static bool +TaskExecutionReadyToStart(TaskExecution *taskExecution) +{ + bool readyToStart = false; + TaskExecStatus *taskStatusArray = taskExecution->taskStatusArray; + uint32 currentIndex = taskExecution->currentNodeIndex; + TaskExecStatus taskStatus = taskStatusArray[currentIndex]; + + if (taskStatus == EXEC_TASK_CONNECT_START) + { + readyToStart = true; + } + + return readyToStart; +} + + +/* Determines if the given task successfully completed executing. */ +static bool +TaskExecutionCompleted(TaskExecution *taskExecution) +{ + bool completed = false; + uint32 nodeIndex = 0; + + for (nodeIndex = 0; nodeIndex < taskExecution->nodeCount; nodeIndex++) + { + TaskExecStatus taskStatus = taskExecution->taskStatusArray[nodeIndex]; + if (taskStatus == EXEC_TASK_DONE) + { + completed = true; + break; + } + } + + return completed; +} + + +/* Iterates over all open connections, and cancels any active requests. */ +static void +CancelTaskExecutionIfActive(TaskExecution *taskExecution) +{ + uint32 nodeIndex = 0; + for (nodeIndex = 0; nodeIndex < taskExecution->nodeCount; nodeIndex++) + { + int32 connectionId = taskExecution->connectionIdArray[nodeIndex]; + if (connectionId != INVALID_CONNECTION_ID) + { + TaskExecStatus *taskStatusArray = taskExecution->taskStatusArray; + TaskExecStatus taskStatus = taskStatusArray[nodeIndex]; + + CancelRequestIfActive(taskStatus, connectionId); + } + } +} + + +/* Helper function to cancel an ongoing request, if any. */ +static void +CancelRequestIfActive(TaskExecStatus taskStatus, int connectionId) +{ + /* + * We use the task status to determine if we have an active request being + * processed by the worker node. If we do, we send a cancellation request. + * Note that we don't cancel data fetch tasks, and allow them to complete. + */ + if (taskStatus == EXEC_COMPUTE_TASK_RUNNING) + { + ResultStatus resultStatus = MultiClientResultStatus(connectionId); + if (resultStatus == CLIENT_RESULT_BUSY) + { + MultiClientCancel(connectionId); + } + } + else if (taskStatus == EXEC_COMPUTE_TASK_COPYING) + { + MultiClientCancel(connectionId); + } +} + + +/* + * WorkerHash creates a worker node hash with the given name. The function + * then inserts one entry for each worker node in the given worker node + * list. + */ +static HTAB * +WorkerHash(const char *workerHashName, List *workerNodeList) +{ + uint32 workerHashSize = list_length(workerNodeList); + HTAB *workerHash = WorkerHashCreate(workerHashName, workerHashSize); + + ListCell *workerNodeCell = NULL; + foreach(workerNodeCell, workerNodeList) + { + WorkerNode *workerNode = (WorkerNode *) lfirst(workerNodeCell); + char *nodeName = workerNode->workerName; + uint32 nodePort = workerNode->workerPort; + + WorkerHashEnter(workerHash, nodeName, nodePort); + } + + return workerHash; +} + + +/* + * WorkerHashCreate allocates memory for a worker node hash, initializes an + * empty hash, and returns this hash. + */ +static HTAB * +WorkerHashCreate(const char *workerHashName, uint32 workerHashSize) +{ + HASHCTL info; + int hashFlags = 0; + HTAB *workerHash = NULL; + + memset(&info, 0, sizeof(info)); + info.keysize = WORKER_LENGTH + sizeof(uint32); + info.entrysize = sizeof(WorkerNodeState); + info.hash = tag_hash; + info.hcxt = CurrentMemoryContext; + hashFlags = (HASH_ELEM | HASH_FUNCTION | HASH_CONTEXT); + + workerHash = hash_create(workerHashName, workerHashSize, &info, hashFlags); + if (workerHash == NULL) + { + ereport(FATAL, (errcode(ERRCODE_OUT_OF_MEMORY), + errmsg("could not initialize worker node hash"))); + } + + return workerHash; +} + + +/* + * WorkerHashEnter creates a new worker node entry in the given worker node + * hash, and checks that the worker node entry has been properly created. + */ +static WorkerNodeState * +WorkerHashEnter(HTAB *workerHash, char *nodeName, uint32 nodePort) +{ + bool handleFound = false; + WorkerNodeState *workerNodeState = NULL; + WorkerNodeState workerNodeKey; + + memset(&workerNodeKey, 0, sizeof(WorkerNodeState)); + strlcpy(workerNodeKey.workerName, nodeName, WORKER_LENGTH); + workerNodeKey.workerPort = nodePort; + + workerNodeState = (WorkerNodeState *) hash_search(workerHash, (void *) &workerNodeKey, + HASH_ENTER, &handleFound); + if (handleFound) + { + ereport(WARNING, (errmsg("multiple worker node state entries for node: \"%s:%u\"", + nodeName, nodePort))); + } + + memcpy(workerNodeState, &workerNodeKey, sizeof(WorkerNodeState)); + workerNodeState->openConnectionCount = 0; + + return workerNodeState; +} + + +/* + * WorkerHashLookup looks for the worker node state that corresponds to the given + * node name and port number, and returns the found worker node state if any. + */ +static WorkerNodeState * +WorkerHashLookup(HTAB *workerHash, const char *nodeName, uint32 nodePort) +{ + bool handleFound = false; + WorkerNodeState *workerNodeState = NULL; + WorkerNodeState workerNodeKey; + + memset(&workerNodeKey, 0, sizeof(WorkerNodeState)); + strlcpy(workerNodeKey.workerName, nodeName, WORKER_LENGTH); + workerNodeKey.workerPort = nodePort; + + workerNodeState = (WorkerNodeState *) hash_search(workerHash, (void *) &workerNodeKey, + HASH_FIND, &handleFound); + if (workerNodeState == NULL) + { + ereport(ERROR, (errmsg("could not find worker node state for node \"%s:%u\"", + nodeName, nodePort))); + } + + return workerNodeState; +} + + +/* + * LookupWorkerForTask looks for the worker node state of the current worker + * node of a task execution. + */ +static WorkerNodeState * +LookupWorkerForTask(HTAB *workerHash, Task *task, TaskExecution *taskExecution) +{ + uint32 currentIndex = taskExecution->currentNodeIndex; + List *taskPlacementList = task->taskPlacementList; + ShardPlacement *taskPlacement = list_nth(taskPlacementList, currentIndex); + char *nodeName = taskPlacement->nodeName; + uint32 nodePort = taskPlacement->nodePort; + + WorkerNodeState *workerNodeState = WorkerHashLookup(workerHash, nodeName, nodePort); + + return workerNodeState; +} + + +/* + * WorkerConnectionsExhausted determines if the current query has exhausted the + * maximum number of open connections that can be made to a worker. + */ +static bool +WorkerConnectionsExhausted(WorkerNodeState *workerNodeState) +{ + bool reachedLimit = false; + + /* + * A worker cannot accept more than max_connections connections. If we have a + * small number of workers with many shards, then a single query could exhaust + * max_connections unless we throttle here. We use the value of max_connections + * on the master as a proxy for the worker configuration to avoid introducing a + * new configuration value. + */ + if (workerNodeState->openConnectionCount >= MaxConnections) + { + reachedLimit = true; + } + + return reachedLimit; +} + + +/* + * MasterConnectionsExhausted determines if the current query has exhausted + * the maximum number of connections the master process can make. + */ +static bool +MasterConnectionsExhausted(HTAB *workerHash) +{ + bool reachedLimit = false; + + uint32 maxConnectionCount = MaxMasterConnectionCount(); + uint32 totalConnectionCount = TotalOpenConnectionCount(workerHash); + if (totalConnectionCount >= maxConnectionCount) + { + reachedLimit = true; + } + + return reachedLimit; +} + + +/* + * TotalOpenConnectionCount counts the total number of open connections across all the + * workers. + */ +static uint32 +TotalOpenConnectionCount(HTAB *workerHash) +{ + uint32 connectionCount = 0; + WorkerNodeState *workerNodeState = NULL; + + HASH_SEQ_STATUS status; + hash_seq_init(&status, workerHash); + + workerNodeState = (WorkerNodeState *) hash_seq_search(&status); + while (workerNodeState != NULL) + { + connectionCount += workerNodeState->openConnectionCount; + workerNodeState = (WorkerNodeState *) hash_seq_search(&status); + } + + return connectionCount; +} + + +/* + * UpdateConnectionCounter updates the connection counter for a given worker + * node based on the specified connect action. + */ +static void +UpdateConnectionCounter(WorkerNodeState *workerNode, ConnectAction connectAction) +{ + if (connectAction == CONNECT_ACTION_OPENED) + { + workerNode->openConnectionCount++; + } + else if (connectAction == CONNECT_ACTION_CLOSED) + { + workerNode->openConnectionCount--; + } +} diff --git a/src/backend/distributed/executor/multi_router_executor.c b/src/backend/distributed/executor/multi_router_executor.c new file mode 100644 index 000000000..5a6cdd06e --- /dev/null +++ b/src/backend/distributed/executor/multi_router_executor.c @@ -0,0 +1,563 @@ +/* + * multi_router_executor.c + * + * Routines for executing remote tasks as part of a distributed execution plan + * with synchronous connections. The routines utilize the connection cache. + * Therefore, only a single connection is opened for each worker. Also, router + * executor does not require a master table and a master query. In other words, + * the results that are fetched from a single worker is sent to the output console + * directly. Lastly, router executor can only execute a single task. + * + * Copyright (c) 2012-2015, Citus Data, Inc. + */ + +#include "postgres.h" +#include "c.h" +#include "fmgr.h" +#include "funcapi.h" +#include "libpq-fe.h" +#include "miscadmin.h" + +#include "access/xact.h" +#include "distributed/connection_cache.h" +#include "distributed/listutils.h" +#include "distributed/multi_executor.h" +#include "distributed/multi_physical_planner.h" +#include "distributed/multi_router_executor.h" +#include "distributed/resource_lock.h" +#include "executor/executor.h" +#include "nodes/pg_list.h" +#include "utils/builtins.h" + +#include "utils/elog.h" +#include "utils/errcodes.h" +#include "utils/memutils.h" +#include "utils/palloc.h" + + +/* controls use of locks to enforce safe commutativity */ +bool AllModificationsCommutative = false; + + +static LOCKMODE CommutativityRuleToLockMode(CmdType commandType, bool upsertQuery); +static void AcquireExecutorShardLock(Task *task, LOCKMODE lockMode); +static int32 ExecuteDistributedModify(Task *task); +static void ExecuteSingleShardSelect(Task *task, EState *executorState, + TupleDesc tupleDescriptor, + DestReceiver *destination); +static bool SendQueryInSingleRowMode(PGconn *connection, char *query); +static bool StoreQueryResult(PGconn *connection, TupleDesc tupleDescriptor, + Tuplestorestate *tupleStore); + + +/* + * RouterExecutorStart sets up the executor state and queryDesc for router + * execution. + */ +void +RouterExecutorStart(QueryDesc *queryDesc, int eflags, Task *task) +{ + bool topLevel = true; + LOCKMODE lockMode = NoLock; + EState *executorState = NULL; + CmdType commandType = queryDesc->operation; + + /* ensure that the task is not NULL */ + Assert(task != NULL); + + /* disallow transactions and triggers during distributed commands */ + PreventTransactionChain(topLevel, "distributed commands"); + eflags |= EXEC_FLAG_SKIP_TRIGGERS; + + /* signal that it is a router execution */ + eflags |= EXEC_FLAG_CITUS_ROUTER_EXECUTOR; + + /* build empty executor state to obtain per-query memory context */ + executorState = CreateExecutorState(); + executorState->es_top_eflags = eflags; + executorState->es_instrument = queryDesc->instrument_options; + + queryDesc->estate = executorState; + +#if (PG_VERSION_NUM < 90500) + /* make sure that upsertQuery is false for versions that UPSERT is not available */ + Assert(task->upsertQuery == false); +#endif + + lockMode = CommutativityRuleToLockMode(commandType, task->upsertQuery); + + if (lockMode != NoLock) + { + AcquireExecutorShardLock(task, lockMode); + } +} + + +/* + * CommutativityRuleToLockMode determines the commutativity rule for the given + * command and returns the appropriate lock mode to enforce that rule. The + * function assumes a SELECT doesn't modify state and therefore is commutative + * with all other commands. The function also assumes that an INSERT commutes + * with another INSERT, but not with an UPDATE/DELETE/UPSERT; and an + * UPDATE/DELETE/UPSERT doesn't commute with an INSERT, UPDATE, DELETE or UPSERT. + * + * Note that the above comment defines INSERT INTO ... ON CONFLICT type of queries + * as an UPSERT. Since UPSERT is not defined as a separate command type in postgres, + * we have to pass it as a second parameter to the function. + * + * The above mapping is overridden entirely when all_modifications_commutative + * is set to true. In that case, all commands just claim a shared lock. This + * allows the shard repair logic to lock out modifications while permitting all + * commands to otherwise commute. + */ +static LOCKMODE +CommutativityRuleToLockMode(CmdType commandType, bool upsertQuery) +{ + LOCKMODE lockMode = NoLock; + + /* bypass commutativity checks when flag enabled */ + if (AllModificationsCommutative) + { + return ShareLock; + } + + if (commandType == CMD_SELECT) + { + lockMode = NoLock; + } + else if (upsertQuery) + { + lockMode = ExclusiveLock; + } + else if (commandType == CMD_INSERT) + { + lockMode = ShareLock; + } + else if (commandType == CMD_UPDATE || commandType == CMD_DELETE) + { + lockMode = ExclusiveLock; + } + else + { + ereport(ERROR, (errmsg("unrecognized operation code: %d", (int) commandType))); + } + + return lockMode; +} + + +/* + * AcquireExecutorShardLock: acquire shard lock needed for execution of + * a single task within a distributed plan. + */ +static void +AcquireExecutorShardLock(Task *task, LOCKMODE lockMode) +{ + int64 shardId = task->shardId; + + LockShardResource(shardId, lockMode); +} + + +/* + * RouterExecutorRun actually executes a single task on a worker. + */ +void +RouterExecutorRun(QueryDesc *queryDesc, ScanDirection direction, long count, Task *task) +{ + EState *estate = queryDesc->estate; + CmdType operation = queryDesc->operation; + MemoryContext oldcontext = NULL; + + Assert(estate != NULL); + Assert(!(estate->es_top_eflags & EXEC_FLAG_EXPLAIN_ONLY)); + Assert(task != NULL); + + /* we only support default scan direction and row fetch count */ + if (!ScanDirectionIsForward(direction)) + { + ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("scan directions other than forward scans " + "are unsupported"))); + } + if (count != 0) + { + ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("fetching rows from a query using a cursor " + "is unsupported"))); + } + + oldcontext = MemoryContextSwitchTo(estate->es_query_cxt); + + if (queryDesc->totaltime != NULL) + { + InstrStartNode(queryDesc->totaltime); + } + + if (operation == CMD_INSERT || operation == CMD_UPDATE || + operation == CMD_DELETE) + { + int32 affectedRowCount = ExecuteDistributedModify(task); + estate->es_processed = affectedRowCount; + } + else if (operation == CMD_SELECT) + { + DestReceiver *destination = queryDesc->dest; + TupleDesc resultTupleDescriptor = queryDesc->tupDesc; + + ExecuteSingleShardSelect(task, estate, resultTupleDescriptor, destination); + } + else + { + ereport(ERROR, (errmsg("unrecognized operation code: %d", + (int) operation))); + } + + if (queryDesc->totaltime != NULL) + { + InstrStopNode(queryDesc->totaltime, estate->es_processed); + } + + MemoryContextSwitchTo(oldcontext); + +} + +/* + * ExecuteDistributedModify is the main entry point for modifying distributed + * tables. A distributed modification is successful if any placement of the + * distributed table is successful. ExecuteDistributedModify returns the number + * of modified rows in that case and errors in all others. This function will + * also generate warnings for individual placement failures. + */ +static int32 +ExecuteDistributedModify(Task *task) +{ + int32 affectedTupleCount = -1; + ListCell *taskPlacementCell = NULL; + List *failedPlacementList = NIL; + ListCell *failedPlacementCell = NULL; + + foreach(taskPlacementCell, task->taskPlacementList) + { + ShardPlacement *taskPlacement = (ShardPlacement *) lfirst(taskPlacementCell); + char *nodeName = taskPlacement->nodeName; + int32 nodePort = taskPlacement->nodePort; + + PGconn *connection = NULL; + PGresult *result = NULL; + char *currentAffectedTupleString = NULL; + int32 currentAffectedTupleCount = -1; + + Assert(taskPlacement->shardState == FILE_FINALIZED); + + connection = GetConnection(nodeName, nodePort); + if (connection == NULL) + { + failedPlacementList = lappend(failedPlacementList, taskPlacement); + continue; + } + + result = PQexec(connection, task->queryString); + if (PQresultStatus(result) != PGRES_COMMAND_OK) + { + ReportRemoteError(connection, result); + PQclear(result); + + failedPlacementList = lappend(failedPlacementList, taskPlacement); + continue; + } + + currentAffectedTupleString = PQcmdTuples(result); + currentAffectedTupleCount = pg_atoi(currentAffectedTupleString, sizeof(int32), 0); + + if ((affectedTupleCount == -1) || + (affectedTupleCount == currentAffectedTupleCount)) + { + affectedTupleCount = currentAffectedTupleCount; + } + else + { + ereport(WARNING, (errmsg("modified %d tuples, but expected to modify %d", + currentAffectedTupleCount, affectedTupleCount), + errdetail("modified placement on %s:%d", + nodeName, nodePort))); + } + + PQclear(result); + } + + /* if all placements failed, error out */ + if (list_length(failedPlacementList) == list_length(task->taskPlacementList)) + { + ereport(ERROR, (errmsg("could not modify any active placements"))); + } + + /* otherwise, mark failed placements as inactive: they're stale */ + foreach(failedPlacementCell, failedPlacementList) + { + ShardPlacement *failedPlacement = (ShardPlacement *) lfirst(failedPlacementCell); + uint64 shardLength = 0; + + DeleteShardPlacementRow(failedPlacement->shardId, failedPlacement->nodeName, + failedPlacement->nodePort); + InsertShardPlacementRow(failedPlacement->shardId, FILE_INACTIVE, shardLength, + failedPlacement->nodeName, failedPlacement->nodePort); + } + + return affectedTupleCount; +} + + +/* + * ExecuteSingleShardSelect executes the remote select query and sends the + * resultant tuples to the given destination receiver. If the query fails on a + * given placement, the function attempts it on its replica. + */ +static void +ExecuteSingleShardSelect(Task *task, EState *executorState, + TupleDesc tupleDescriptor, DestReceiver *destination) +{ + Tuplestorestate *tupleStore = NULL; + bool resultsOK = false; + TupleTableSlot *tupleTableSlot = NULL; + + tupleStore = tuplestore_begin_heap(false, false, work_mem); + + resultsOK = ExecuteTaskAndStoreResults(task, tupleDescriptor, tupleStore); + if (!resultsOK) + { + ereport(ERROR, (errmsg("could not receive query results"))); + } + + tupleTableSlot = MakeSingleTupleTableSlot(tupleDescriptor); + + /* startup the tuple receiver */ + (*destination->rStartup)(destination, CMD_SELECT, tupleDescriptor); + + /* iterate over tuples in tuple store, and send them to destination */ + for (;;) + { + bool nextTuple = tuplestore_gettupleslot(tupleStore, true, false, tupleTableSlot); + if (!nextTuple) + { + break; + } + + (*destination->receiveSlot)(tupleTableSlot, destination); + executorState->es_processed++; + + ExecClearTuple(tupleTableSlot); + } + + /* shutdown the tuple receiver */ + (*destination->rShutdown)(destination); + + ExecDropSingleTupleTableSlot(tupleTableSlot); + + tuplestore_end(tupleStore); +} + + +/* + * ExecuteTaskAndStoreResults executes the task on the remote node, retrieves + * the results and stores them in the given tuple store. If the task fails on + * one of the placements, the function retries it on other placements. + */ +bool +ExecuteTaskAndStoreResults(Task *task, TupleDesc tupleDescriptor, + Tuplestorestate *tupleStore) +{ + bool resultsOK = false; + List *taskPlacementList = task->taskPlacementList; + ListCell *taskPlacementCell = NULL; + + /* + * Try to run the query to completion on one placement. If the query fails + * attempt the query on the next placement. + */ + foreach(taskPlacementCell, taskPlacementList) + { + ShardPlacement *taskPlacement = (ShardPlacement *) lfirst(taskPlacementCell); + char *nodeName = taskPlacement->nodeName; + int32 nodePort = taskPlacement->nodePort; + bool queryOK = false; + bool storedOK = false; + + PGconn *connection = GetConnection(nodeName, nodePort); + if (connection == NULL) + { + continue; + } + + queryOK = SendQueryInSingleRowMode(connection, task->queryString); + if (!queryOK) + { + PurgeConnection(connection); + continue; + } + + storedOK = StoreQueryResult(connection, tupleDescriptor, tupleStore); + if (storedOK) + { + resultsOK = true; + break; + } + else + { + tuplestore_clear(tupleStore); + PurgeConnection(connection); + } + } + + return resultsOK; +} + + +/* + * SendQueryInSingleRowMode sends the given query on the connection in an + * asynchronous way. The function also sets the single-row mode on the + * connection so that we receive results a row at a time. + */ +static bool +SendQueryInSingleRowMode(PGconn *connection, char *query) +{ + int querySent = 0; + int singleRowMode = 0; + + querySent = PQsendQuery(connection, query); + if (querySent == 0) + { + ReportRemoteError(connection, NULL); + return false; + } + + singleRowMode = PQsetSingleRowMode(connection); + if (singleRowMode == 0) + { + ReportRemoteError(connection, NULL); + return false; + } + + return true; +} + + +/* + * StoreQueryResult gets the query results from the given connection, builds + * tuples from the results and stores them in the given tuple-store. If the + * function can't receive query results, it returns false. Note that this + * function assumes the query has already been sent on the connection and the + * tuplestore has earlier been initialized. + */ +static bool +StoreQueryResult(PGconn *connection, TupleDesc tupleDescriptor, + Tuplestorestate *tupleStore) +{ + AttInMetadata *attributeInputMetadata = TupleDescGetAttInMetadata(tupleDescriptor); + uint32 expectedColumnCount = tupleDescriptor->natts; + char **columnArray = (char **) palloc0(expectedColumnCount * sizeof(char *)); + MemoryContext ioContext = AllocSetContextCreate(CurrentMemoryContext, + "StoreQueryResult", + ALLOCSET_DEFAULT_MINSIZE, + ALLOCSET_DEFAULT_INITSIZE, + ALLOCSET_DEFAULT_MAXSIZE); + + Assert(tupleStore != NULL); + + for (;;) + { + uint32 rowIndex = 0; + uint32 columnIndex = 0; + uint32 rowCount = 0; + uint32 columnCount = 0; + ExecStatusType resultStatus = 0; + + PGresult *result = PQgetResult(connection); + if (result == NULL) + { + break; + } + + resultStatus = PQresultStatus(result); + if ((resultStatus != PGRES_SINGLE_TUPLE) && (resultStatus != PGRES_TUPLES_OK)) + { + ReportRemoteError(connection, result); + PQclear(result); + + return false; + } + + rowCount = PQntuples(result); + columnCount = PQnfields(result); + Assert(columnCount == expectedColumnCount); + + for (rowIndex = 0; rowIndex < rowCount; rowIndex++) + { + HeapTuple heapTuple = NULL; + MemoryContext oldContext = NULL; + memset(columnArray, 0, columnCount * sizeof(char *)); + + for (columnIndex = 0; columnIndex < columnCount; columnIndex++) + { + if (PQgetisnull(result, rowIndex, columnIndex)) + { + columnArray[columnIndex] = NULL; + } + else + { + columnArray[columnIndex] = PQgetvalue(result, rowIndex, columnIndex); + } + } + + /* + * Switch to a temporary memory context that we reset after each tuple. This + * protects us from any memory leaks that might be present in I/O functions + * called by BuildTupleFromCStrings. + */ + oldContext = MemoryContextSwitchTo(ioContext); + + heapTuple = BuildTupleFromCStrings(attributeInputMetadata, columnArray); + + MemoryContextSwitchTo(oldContext); + + tuplestore_puttuple(tupleStore, heapTuple); + MemoryContextReset(ioContext); + } + + PQclear(result); + } + + pfree(columnArray); + + return true; +} + +/* +* RouterExecutorFinish cleans up after a distributed execution. +*/ +void +RouterExecutorFinish(QueryDesc *queryDesc) +{ + EState *estate = queryDesc->estate; + Assert(estate != NULL); + + estate->es_finished = true; +} + + +/* + * RouterExecutorEnd cleans up the executor state after a distributed + * execution. + */ +void +RouterExecutorEnd(QueryDesc *queryDesc) +{ + EState *estate = queryDesc->estate; + + Assert(estate != NULL); + Assert(estate->es_finished); + + FreeExecutorState(estate); + queryDesc->estate = NULL; + queryDesc->totaltime = NULL; +} diff --git a/src/backend/distributed/executor/multi_server_executor.c b/src/backend/distributed/executor/multi_server_executor.c new file mode 100644 index 000000000..1f143778d --- /dev/null +++ b/src/backend/distributed/executor/multi_server_executor.c @@ -0,0 +1,315 @@ +/*------------------------------------------------------------------------- + * + * multi_server_executor.c + * + * Function definitions for distributed task execution for real-time + * and task-tracker executors, and routines common to both. The common + * routines are implement backend-side logic; and they trigger executions + * on the client-side via function hooks that they load. + * + * Copyright (c) 2012, Citus Data, Inc. + * + * $Id$ + * + *------------------------------------------------------------------------- + */ + +#include "postgres.h" +#include "miscadmin.h" + +#include + +#include "distributed/multi_client_executor.h" +#include "distributed/multi_physical_planner.h" +#include "distributed/multi_resowner.h" +#include "distributed/multi_server_executor.h" +#include "distributed/worker_protocol.h" + + +int RemoteTaskCheckInterval = 100; /* per cycle sleep interval in millisecs */ +int TaskExecutorType = MULTI_EXECUTOR_REAL_TIME; /* distributed executor type */ +bool BinaryMasterCopyFormat = false; /* copy data from workers in binary format */ + + +/* + * JobExecutorType selects the executor type for the given multiPlan using the task + * executor type config value. The function then checks if the given multiPlan needs + * more resources than those provided to it by other config values, and issues + * warnings accordingly. If the selected executor type cannot execute the given + * multiPlan, the function errors out. + */ +MultiExecutorType +JobExecutorType(MultiPlan *multiPlan) +{ + Job *job = multiPlan->workerJob; + Query *masterQuery = multiPlan->masterQuery; + List *workerTaskList = job->taskList; + List *workerNodeList = WorkerNodeList(); + int taskCount = list_length(workerTaskList); + int workerNodeCount = list_length(workerNodeList); + double tasksPerNode = taskCount / ((double) workerNodeCount); + int dependedJobCount = list_length(job->dependedJobList); + + MultiExecutorType executorType = TaskExecutorType; + + /* check if the first task is a modify task, short-circuit if so */ + if (taskCount > 0) + { + Task *firstTask = (Task *) linitial(workerTaskList); + + if (firstTask->taskType == MODIFY_TASK) + { + return MULTI_EXECUTOR_ROUTER; + } + } + + if (executorType == MULTI_EXECUTOR_REAL_TIME) + { + double reasonableConnectionCount = 0; + + /* if we need to open too many connections per worker, warn the user */ + if (tasksPerNode >= MaxConnections) + { + ereport(WARNING, (errmsg("this query uses more connections than the " + "configured max_connections limit"), + errhint("Consider increasing max_connections or setting " + "citusdb.task_executor_type to " + "\"task-tracker\"."))); + } + + /* + * If we need to open too many outgoing connections, warn the user. + * The real-time executor caps the number of tasks it starts by the same limit, + * but we still issue this warning because it degrades performance. + */ + reasonableConnectionCount = MaxMasterConnectionCount(); + if (taskCount >= reasonableConnectionCount) + { + ereport(WARNING, (errmsg("this query uses more file descriptors than the " + "configured max_files_per_process limit"), + errhint("Consider increasing max_files_per_process or " + "setting citusdb.task_executor_type to " + "\"task-tracker\"."))); + } + + /* if we have repartition jobs with real time executor, error out */ + if (dependedJobCount > 0) + { + ereport(ERROR, (errmsg("cannot use real time executor with repartition jobs"), + errhint("Set citusdb.task_executor_type to " + "\"task-tracker\"."))); + } + } + else if (executorType == MULTI_EXECUTOR_TASK_TRACKER) + { + /* if we have more tasks per node than what can be tracked, warn the user */ + if (tasksPerNode >= MaxTrackedTasksPerNode) + { + ereport(WARNING, (errmsg("this query assigns more tasks per node than the " + "configured max_tracked_tasks_per_node limit"))); + } + } + else if (executorType == MULTI_EXECUTOR_ROUTER) + { + Task *workerTask = NULL; + List *workerDependentTaskList = NIL; + bool masterQueryHasAggregates = false; + + /* if we have repartition jobs with router executor, error out */ + if (dependedJobCount > 0) + { + ereport(ERROR, (errmsg("cannot use router executor with repartition jobs"), + errhint("Set citusdb.task_executor_type to " + "\"task-tracker\"."))); + } + + /* if the query hits more than one shards, error out*/ + if (taskCount != 1) + { + ereport(ERROR, (errmsg("cannot use router executor with queries that " + "hit multiple shards"), + errhint("Set citusdb.task_executor_type to \"real-time\" or " + "\"task-tracker\"."))); + } + + /* if the query has dependent data fetch tasks */ + workerTask = list_nth(workerTaskList, 0); + workerDependentTaskList = workerTask->dependedTaskList; + if (list_length(workerDependentTaskList) > 0) + { + ereport(ERROR, (errmsg("cannot use router executor with JOINs"), + errhint("Set citusdb.task_executor_type to \"real-time\" or " + "\"task-tracker\"."))); + } + + /* ORDER BY is always applied on the master table with the current planner */ + if (masterQuery != NULL && list_length(masterQuery->sortClause) > 0) + { + ereport(ERROR, (errmsg("cannot use router executor with ORDER BY clauses"), + errhint("Set citusdb.task_executor_type to \"real-time\" or " + "\"task-tracker\"."))); + } + + /* + * Note that worker query having an aggregate means that the master query should have either + * an aggregate or a function expression which has to be executed for the correct results. + */ + masterQueryHasAggregates = job->jobQuery->hasAggs; + if (masterQueryHasAggregates) + { + ereport(ERROR, (errmsg("cannot use router executor with aggregates"), + errhint("Set citusdb.task_executor_type to \"real-time\" or " + "\"task-tracker\"."))); + } + } + + return executorType; +} + + +/* + * MaxMasterConnectionCount returns the number of connections a master can open. + * A master cannot create more than a certain number of file descriptors (FDs). + * Every task requires 2 FDs, one file and one connection. Some FDs are taken by + * the VFD pool and there is currently no way to reclaim these before opening a + * connection. We therefore assume some FDs to be reserved for VFDs, based on + * observing a typical size of the pool on a CitusDB master. + */ +int +MaxMasterConnectionCount(void) +{ + return Max((max_files_per_process - RESERVED_FD_COUNT) / 2, 1); +} + + +/* + * RemoveJobDirectory gets automatically called at portal drop (end of query) or + * at transaction abort. The function removes the job directory and releases the + * associated job resource from the resource manager. + */ +void +RemoveJobDirectory(uint64 jobId) +{ + StringInfo jobDirectoryName = JobDirectoryName(jobId); + RemoveDirectory(jobDirectoryName); + + ResourceOwnerForgetJobDirectory(CurrentResourceOwner, jobId); +} + + +/* + * InitTaskExecution creates a task execution structure for the given task, and + * initializes execution related fields. + */ +TaskExecution * +InitTaskExecution(Task *task, TaskExecStatus initialTaskExecStatus) +{ + /* each task placement (assignment) corresponds to one worker node */ + uint32 nodeCount = list_length(task->taskPlacementList); + uint32 nodeIndex = 0; + + TaskExecution *taskExecution = palloc0(sizeof(TaskExecution)); + taskExecution->jobId = task->jobId; + taskExecution->taskId = task->taskId; + taskExecution->nodeCount = nodeCount; + taskExecution->connectPollCount = 0; + taskExecution->currentNodeIndex = 0; + taskExecution->dataFetchTaskIndex = -1; + taskExecution->failureCount = 0; + + taskExecution->taskStatusArray = palloc0(nodeCount * sizeof(TaskExecStatus)); + taskExecution->transmitStatusArray = palloc0(nodeCount * sizeof(TransmitExecStatus)); + taskExecution->connectionIdArray = palloc0(nodeCount * sizeof(int32)); + taskExecution->fileDescriptorArray = palloc0(nodeCount * sizeof(int32)); + + for (nodeIndex = 0; nodeIndex < nodeCount; nodeIndex++) + { + taskExecution->taskStatusArray[nodeIndex] = initialTaskExecStatus; + taskExecution->transmitStatusArray[nodeIndex] = EXEC_TRANSMIT_UNASSIGNED; + taskExecution->connectionIdArray[nodeIndex] = INVALID_CONNECTION_ID; + taskExecution->fileDescriptorArray[nodeIndex] = -1; + } + + return taskExecution; +} + + +/* + * CleanupTaskExecution iterates over all connections and file descriptors for + * the given task execution. The function first closes all open connections and + * file descriptors, and then frees memory allocated for the task execution. + */ +void +CleanupTaskExecution(TaskExecution *taskExecution) +{ + uint32 nodeIndex = 0; + for (nodeIndex = 0; nodeIndex < taskExecution->nodeCount; nodeIndex++) + { + int32 connectionId = taskExecution->connectionIdArray[nodeIndex]; + int32 fileDescriptor = taskExecution->fileDescriptorArray[nodeIndex]; + + /* close open connection */ + if (connectionId != INVALID_CONNECTION_ID) + { + MultiClientDisconnect(connectionId); + taskExecution->connectionIdArray[nodeIndex] = INVALID_CONNECTION_ID; + } + + /* close open file */ + if (fileDescriptor >= 0) + { + int closed = close(fileDescriptor); + taskExecution->fileDescriptorArray[nodeIndex] = -1; + + if (closed < 0) + { + ereport(WARNING, (errcode_for_file_access(), + errmsg("could not close copy file: %m"))); + } + } + } + + /* deallocate memory and reset all fields */ + pfree(taskExecution->taskStatusArray); + pfree(taskExecution->connectionIdArray); + pfree(taskExecution->fileDescriptorArray); + memset(taskExecution, 0, sizeof(TaskExecution)); +} + + +/* Determines if the given task exceeded its failure threshold. */ +bool +TaskExecutionFailed(TaskExecution *taskExecution) +{ + if (taskExecution->failureCount >= MAX_TASK_EXECUTION_FAILURES) + { + return true; + } + + return false; +} + + +/* + * AdjustStateForFailure increments the failure count for given task execution. + * The function also determines the next worker node that should be contacted + * for remote execution. + */ +void +AdjustStateForFailure(TaskExecution *taskExecution) +{ + int maxNodeIndex = taskExecution->nodeCount - 1; + Assert(maxNodeIndex >= 0); + + if (taskExecution->currentNodeIndex < maxNodeIndex) + { + taskExecution->currentNodeIndex++; /* try next worker node */ + } + else + { + taskExecution->currentNodeIndex = 0; /* go back to the first worker node */ + } + + taskExecution->dataFetchTaskIndex = -1; /* reset data fetch counter */ + taskExecution->failureCount++; /* record failure */ +} diff --git a/src/backend/distributed/executor/multi_task_tracker_executor.c b/src/backend/distributed/executor/multi_task_tracker_executor.c new file mode 100644 index 000000000..f67c82271 --- /dev/null +++ b/src/backend/distributed/executor/multi_task_tracker_executor.c @@ -0,0 +1,2880 @@ +/*------------------------------------------------------------------------- + * + * multi_task_tracker_executor.c + * + * Routines for executing remote tasks as part of a distributed execution plan + * using task trackers. These task trackers receive task assignments from this + * executor, and they manage task executions on worker nodes. The use of task + * trackers brings us two benefits: (a) distributed execution plans can scale + * out to many tasks, as the executor no longer needs to keep a connection open + * for each task, and (b) distributed execution plans can include map/reduce + * execution primitives, which involve writing intermediate results to files. + * + * Copyright (c) 2013, Citus Data, Inc. + * + * $Id$ + * + *------------------------------------------------------------------------- + */ + +#include "postgres.h" +#include "miscadmin.h" + +#include + +#include "commands/dbcommands.h" +#include "distributed/citus_nodes.h" +#include "distributed/multi_client_executor.h" +#include "distributed/multi_physical_planner.h" +#include "distributed/multi_server_executor.h" +#include "distributed/worker_protocol.h" +#include "storage/fd.h" +#include "utils/builtins.h" +#include "utils/hsearch.h" + + +int MaxAssignTaskBatchSize = 64; /* maximum number of tasks to assign per round */ + +/* TaskMapKey is used as a key in task hash */ +typedef struct TaskMapKey +{ + TaskType taskType; + uint64 jobId; + uint32 taskId; + +} TaskMapKey; + + +/* + * TaskMapEntry is used as entry in task hash. We need to keep a pointer + * of the task in the entry. + */ +typedef struct TaskMapEntry +{ + TaskMapKey key; + Task *task; + +} TaskMapEntry; + + +/* Local functions forward declarations to init tasks and trackers */ +static List * TaskAndExecutionList(List *jobTaskList); +static HTAB * TaskHashCreate(uint32 taskHashSize); +static Task * TaskHashEnter(HTAB *taskHash, Task *task); +static Task * TaskHashLookup(HTAB *trackerHash, TaskType taskType, uint64 jobId, + uint32 taskId); +static bool TopLevelTask(Task *task); +static bool TransmitExecutionCompleted(TaskExecution *taskExecution); +static HTAB * TrackerHash(const char *taskTrackerHashName, List *workerNodeList); +static HTAB * TrackerHashCreate(const char *taskTrackerHashName, + uint32 taskTrackerHashSize); +static TaskTracker * TrackerHashEnter(HTAB *taskTrackerHash, char *nodeName, + uint32 nodePort); +static void TrackerHashConnect(HTAB *taskTrackerHash); +static TrackerStatus TrackerConnectPoll(TaskTracker *taskTracker); +static TaskTracker * ResolveTaskTracker(HTAB *trackerHash, Task *task, + TaskExecution *taskExecution); +static TaskTracker * ResolveMapTaskTracker(HTAB *trackerHash, Task *task, + TaskExecution *taskExecution); +static TaskTracker * TrackerHashLookup(HTAB *trackerHash, const char *nodeName, + uint32 nodePort); + +/* Local functions forward declarations to manage tasks and their assignments */ +static TaskExecStatus ManageTaskExecution(TaskTracker *taskTracker, + TaskTracker *sourceTaskTracker, + Task *task, TaskExecution *taskExecution); +static TransmitExecStatus ManageTransmitExecution(TaskTracker *transmitTracker, Task *task, + TaskExecution *taskExecution); +static bool TaskExecutionsCompleted(List *taskList); +static StringInfo MapFetchTaskQueryString(Task *mapFetchTask, Task *mapTask); +static void TrackerQueueSqlTask(TaskTracker *taskTracker, Task *task); +static void TrackerQueueTask(TaskTracker *taskTracker, Task *task); +static StringInfo TaskAssignmentQuery(Task *task, char *queryString); +static TaskStatus TrackerTaskStatus(TaskTracker *taskTracker, Task *task); +static TrackerTaskState * TrackerTaskStateHashLookup(HTAB *taskStateHash, Task *task); +static bool TrackerHealthy(TaskTracker *taskTracker); +static void TrackerQueueFileTransmit(TaskTracker *transmitTracker, Task *task); +static TrackerTaskState * TaskStateHashEnter(HTAB *taskStateHash, uint64 jobId, + uint32 taskId); +static int32 TransmitTrackerConnectionId(TaskTracker *transmitTracker, Task *task); + +/* Local functions forward declarations to manage task failovers */ +static List * ConstrainedTaskList(List *taskAndExecutionList, Task *task); +static List * ConstrainedNonMergeTaskList(List *taskAndExecutionList, Task *task); +static List * UpstreamDependencyList(List *taskAndExecutionList, Task *searchedTask); +static List * ConstrainedMergeTaskList(List *taskAndExecutionList, Task *task); +static List * MergeTaskList(List *taskList); +static void ReassignTaskList(List *taskList); +static void ReassignMapFetchTaskList(List *mapFetchTaskList); +static List * ShardFetchTaskList(List *taskList); + +/* Local functions forward declarations to manage task trackers */ +static void ManageTaskTracker(TaskTracker *taskTracker); +static bool TrackerConnectionUp(TaskTracker *taskTracker); +static void TrackerReconnectPoll(TaskTracker *taskTracker); +static List * AssignQueuedTasks(TaskTracker *taskTracker); +static int32 NextRunningTaskIndex(List *assignedTaskList, int32 currentTaskIndex); +static TaskStatus TaskStatusQueryResponse(int32 connectionId); +static void ManageTransmitTracker(TaskTracker *transmitTracker); +static TrackerTaskState * NextQueuedFileTransmit(HTAB *taskStateHash); + +/* Local functions forward declarations to clean up tasks */ +static List * JobIdList(Job *job); +static void TrackerCleanupResources(HTAB *taskTrackerHash, HTAB *transmitTrackerHash, + List *jobIdList, List *taskList); +static void TrackerHashWaitActiveRequest(HTAB *taskTrackerHash); +static void TrackerHashCancelActiveRequest(HTAB *taskTrackerHash); +static Task * JobCleanupTask(uint64 jobId); +static void TrackerHashCleanupJob(HTAB *taskTrackerHash, Task *jobCleanupTask); +static void TrackerHashDisconnect(HTAB *taskTrackerHash); + + +/* + * MultiTaskTrackerExecute loops over given tasks, and manages their execution + * until either one task permanently fails or all tasks successfully complete. + * The function initializes connections to task trackers on worker nodes, and + * executes tasks through assigning them to these trackers. + */ +void +MultiTaskTrackerExecute(Job *job) +{ + List *jobTaskList = job->taskList; + List *taskAndExecutionList = NIL; + ListCell *taskAndExecutionCell = NULL; + uint32 taskTrackerCount = 0; + uint32 topLevelTaskCount = 0; + uint64 failedJobId = 0; + uint32 failedTaskId = 0; + bool allTasksCompleted = false; + bool taskFailed = false; + bool taskTransmitFailed = false; + bool clusterFailed = false; + + List *workerNodeList = NIL; + HTAB *taskTrackerHash = NULL; + HTAB *transmitTrackerHash = NULL; + const char *taskTrackerHashName = "Task Tracker Hash"; + const char *transmitTrackerHashName = "Transmit Tracker Hash"; + List *jobIdList = NIL; + + /* + * We walk over the task tree, and create a task execution struct for each + * task. We then associate the task with its execution and get back a list. + */ + taskAndExecutionList = TaskAndExecutionList(jobTaskList); + + /* + * We now count the number of "top level" tasks in the query tree. Once they + * complete, we'll need to fetch these tasks' results to the master node. + */ + foreach(taskAndExecutionCell, taskAndExecutionList) + { + Task *task = (Task *) lfirst(taskAndExecutionCell); + + bool topLevelTask = TopLevelTask(task); + if (topLevelTask) + { + topLevelTaskCount++; + } + } + + /* + * We get the list of worker nodes, and then create two hashes to manage our + * connections to these nodes. The first hash manages connections used for + * assigning and checking the status of tasks. The second (temporary) hash + * helps us in fetching results data from worker nodes to the master node. + */ + workerNodeList = WorkerNodeList(); + taskTrackerCount = (uint32) list_length(workerNodeList); + + taskTrackerHash = TrackerHash(taskTrackerHashName, workerNodeList); + transmitTrackerHash = TrackerHash(transmitTrackerHashName, workerNodeList); + + TrackerHashConnect(taskTrackerHash); + TrackerHashConnect(transmitTrackerHash); + + /* loop around until all tasks complete, one task fails, or user cancels */ + while ( !(allTasksCompleted || taskFailed || taskTransmitFailed || + clusterFailed || QueryCancelPending) ) + { + TaskTracker *taskTracker = NULL; + TaskTracker *transmitTracker = NULL; + HASH_SEQ_STATUS taskStatus; + HASH_SEQ_STATUS transmitStatus; + + uint32 completedTransmitCount = 0; + uint32 healthyTrackerCount = 0; + double acceptableHealthyTrackerCount = 0.0; + + /* first, loop around all tasks and manage them */ + ListCell *taskAndExecutionCell = NULL; + foreach(taskAndExecutionCell, taskAndExecutionList) + { + Task *task = (Task *) lfirst(taskAndExecutionCell); + TaskExecution *taskExecution = task->taskExecution; + TaskExecStatus taskExecutionStatus = 0; + + TaskTracker *execTaskTracker = ResolveTaskTracker(taskTrackerHash, + task, taskExecution); + TaskTracker *mapTaskTracker = ResolveMapTaskTracker(taskTrackerHash, + task, taskExecution); + Assert(execTaskTracker != NULL); + + /* call the function that performs the core task execution logic */ + taskExecutionStatus = ManageTaskExecution(execTaskTracker, mapTaskTracker, + task, taskExecution); + + /* + * If task cannot execute on this task/map tracker, we fail over all + * tasks in the same constraint group to the next task/map tracker. + */ + if (taskExecutionStatus == EXEC_TASK_TRACKER_FAILED) + { + List *taskList = NIL; + TaskTracker *transmitTracker = NULL; + + /* mark task tracker as failed, in case it isn't marked already */ + execTaskTracker->trackerFailureCount = MAX_TRACKER_FAILURE_COUNT; + + /* + * We may have already started to transmit task results to the + * master. When we reassign the transmits, we could leave the + * transmit tracker in an invalid state. So, we fail it too. + */ + transmitTracker = ResolveTaskTracker(transmitTrackerHash, + task, taskExecution); + transmitTracker->trackerFailureCount = MAX_TRACKER_FAILURE_COUNT; + + taskList = ConstrainedTaskList(taskAndExecutionList, task); + ReassignTaskList(taskList); + } + else if (taskExecutionStatus == EXEC_SOURCE_TASK_TRACKER_FAILED) + { + List *mapFetchTaskList = NIL; + List *mapTaskList = NIL; + + /* first resolve the map task this map fetch task depends on */ + Task *mapTask = (Task *) linitial(task->dependedTaskList); + Assert(task->taskType == MAP_OUTPUT_FETCH_TASK); + + mapFetchTaskList = UpstreamDependencyList(taskAndExecutionList, mapTask); + ReassignMapFetchTaskList(mapFetchTaskList); + + mapTaskList = ConstrainedTaskList(taskAndExecutionList, mapTask); + ReassignTaskList(mapTaskList); + } + + /* + * If this task permanently failed, we first need to manually clean + * out client-side resources for all task executions. We therefore + * record the failure here instead of immediately erroring out. + */ + taskFailed = TaskExecutionFailed(taskExecution); + if (taskFailed) + { + failedJobId = taskExecution->jobId; + failedTaskId = taskExecution->taskId; + break; + } + } + + /* second, loop around "top level" tasks to fetch their results */ + taskAndExecutionCell = NULL; + foreach(taskAndExecutionCell, taskAndExecutionList) + { + Task *task = (Task *) lfirst(taskAndExecutionCell); + TaskExecution *taskExecution = task->taskExecution; + TransmitExecStatus transmitExecutionStatus = 0; + + TaskTracker *execTransmitTracker = NULL; + bool transmitCompleted = false; + + /* + * We find the tasks that appear in the top level of the query tree, + * and start fetching their results to the master node. + */ + bool topLevelTask = TopLevelTask(task); + if (!topLevelTask) + { + continue; + } + + execTransmitTracker = ResolveTaskTracker(transmitTrackerHash, + task, taskExecution); + Assert(execTransmitTracker != NULL); + + /* call the function that fetches results for completed SQL tasks */ + transmitExecutionStatus = ManageTransmitExecution(execTransmitTracker, + task, taskExecution); + + /* + * If we cannot transmit SQL task's results to the master, we first + * force fail the corresponding task tracker. We then fail over all + * tasks in the constraint group to the next task/transmit tracker. + */ + if (transmitExecutionStatus == EXEC_TRANSMIT_TRACKER_FAILED) + { + List *taskList = NIL; + TaskTracker *taskTracker = NULL; + + taskTracker = ResolveTaskTracker(taskTrackerHash, + task, taskExecution); + taskTracker->trackerFailureCount = MAX_TRACKER_FAILURE_COUNT; + + taskList = ConstrainedTaskList(taskAndExecutionList, task); + ReassignTaskList(taskList); + } + + /* if task failed for good, record failure and break out of loop */ + taskTransmitFailed = TaskExecutionFailed(taskExecution); + if (taskTransmitFailed) + { + failedJobId = taskExecution->jobId; + failedTaskId = taskExecution->taskId; + break; + } + + transmitCompleted = TransmitExecutionCompleted(taskExecution); + if (transmitCompleted) + { + completedTransmitCount++; + } + } + + /* third, loop around task trackers and manage them */ + hash_seq_init(&taskStatus, taskTrackerHash); + hash_seq_init(&transmitStatus, transmitTrackerHash); + + taskTracker = (TaskTracker *) hash_seq_search(&taskStatus); + while (taskTracker != NULL) + { + bool trackerHealthy = TrackerHealthy(taskTracker); + if (trackerHealthy) + { + healthyTrackerCount++; + } + + ManageTaskTracker(taskTracker); + + taskTracker = (TaskTracker *) hash_seq_search(&taskStatus); + } + + transmitTracker = (TaskTracker *) hash_seq_search(&transmitStatus); + while (transmitTracker != NULL) + { + ManageTransmitTracker(transmitTracker); + + transmitTracker = (TaskTracker *) hash_seq_search(&transmitStatus); + } + + /* if more than half the trackers have failed, mark cluster as failed */ + acceptableHealthyTrackerCount = (double) taskTrackerCount / 2.0; + if (healthyTrackerCount < acceptableHealthyTrackerCount) + { + clusterFailed = true; + } + + /* check if we completed execution; otherwise sleep to avoid tight loop */ + if (completedTransmitCount == topLevelTaskCount) + { + allTasksCompleted = true; + } + else + { + long sleepIntervalPerCycle = RemoteTaskCheckInterval * 1000L; + pg_usleep(sleepIntervalPerCycle); + } + } + + /* + * We prevent cancel/die interrupts until we issue cleanup requests to task + * trackers and close open connections. Note that for the above while loop, + * if the user Ctrl+C's a query and we emit a warning before looping to the + * beginning of the while loop, we will get canceled away before we can hold + * any interrupts. + */ + HOLD_INTERRUPTS(); + + jobIdList = JobIdList(job); + + TrackerCleanupResources(taskTrackerHash, transmitTrackerHash, + jobIdList, taskAndExecutionList); + + RESUME_INTERRUPTS(); + + /* + * If we previously broke out of the execution loop due to a task failure or + * user cancellation request, we can now safely emit an error message. + */ + if (taskFailed) + { + ereport(ERROR, (errmsg("failed to execute job " UINT64_FORMAT, failedJobId), + errdetail("Failure due to failed task %u", failedTaskId))); + } + else if (clusterFailed) + { + ereport(ERROR, (errmsg("failed to execute job " UINT64_FORMAT, job->jobId), + errdetail("Too many task tracker failures"))); + } + else if (QueryCancelPending) + { + CHECK_FOR_INTERRUPTS(); + } +} + + +/* + * TaskAndExecutionList visits all tasks in the job tree, starting with the given + * job's task list. For each visited task, the function creates a task execution + * struct, associates the task execution with the task, and adds the task and its + * execution to a list. The function then returns the list. + */ +static List * +TaskAndExecutionList(List *jobTaskList) +{ + List *taskAndExecutionList = NIL; + List *taskQueue = NIL; + const int topLevelTaskHashSize = 32; + int taskHashSize = list_length(jobTaskList) * topLevelTaskHashSize; + HTAB *taskHash = TaskHashCreate(taskHashSize); + + /* + * We walk over the task tree using breadth-first search. For the search, we + * first queue top level tasks in the task tree. + */ + taskQueue = list_copy(jobTaskList); + while (taskQueue != NIL) + { + TaskExecution *taskExecution = NULL; + List *dependendTaskList = NIL; + ListCell *dependedTaskCell = NULL; + + /* pop first element from the task queue */ + Task *task = (Task *) linitial(taskQueue); + taskQueue = list_delete_first(taskQueue); + + /* create task execution and associate it with task */ + taskExecution = InitTaskExecution(task, EXEC_TASK_UNASSIGNED); + task->taskExecution = taskExecution; + + taskAndExecutionList = lappend(taskAndExecutionList, task); + + dependendTaskList = task->dependedTaskList; + + /* + * Push task node's children into the task queue, if and only if + * they're not already there. As task dependencies have to form a + * directed-acyclic-graph and are processed in a breadth-first search + * we can never re-encounter nodes we've already processed. + * + * While we're checking this, we can also fix the problem that + * copyObject() might have duplicated nodes in the graph - if a node + * isn't pushed to the graph because it is already planned to be + * visited, we can simply replace it with the copy. Note that, here + * we only consider dependend tasks. Since currently top level tasks + * cannot be on any dependend task list, we do not check them for duplicates. + * + * taskHash is used to reduce the complexity of keeping track of + * the tasks that are already encountered. + */ + foreach(dependedTaskCell, dependendTaskList) + { + Task *dependendTask = lfirst(dependedTaskCell); + Task *dependendTaskInHash = TaskHashLookup(taskHash, + dependendTask->taskType, + dependendTask->jobId, + dependendTask->taskId); + + /* + * If the dependend task encountered for the first time, add it to the hash. + * Also, add this task to the task queue. Note that, we do not need to + * add the tasks to the queue which are already encountered, because + * they are already added to the queue. + */ + if (!dependendTaskInHash) + { + dependendTaskInHash = TaskHashEnter(taskHash, dependendTask); + taskQueue = lappend(taskQueue, dependendTaskInHash); + } + + /* update dependedTaskList element to the one which is in the hash */ + lfirst(dependedTaskCell) = dependendTaskInHash; + } + } + + return taskAndExecutionList; +} + + +/* + * TaskHashCreate allocates memory for a task hash, initializes an + * empty hash, and returns this hash. + */ +static HTAB * +TaskHashCreate(uint32 taskHashSize) +{ + HASHCTL info; + const char *taskHashName = "Task Hash"; + int hashFlags = 0; + HTAB *taskHash = NULL; + + memset(&info, 0, sizeof(info)); + info.keysize = sizeof(TaskMapKey); + info.entrysize = sizeof(TaskMapEntry); + info.hash = tag_hash; + info.hcxt = CurrentMemoryContext; + hashFlags = (HASH_ELEM | HASH_FUNCTION | HASH_CONTEXT); + + taskHash = hash_create(taskHashName, taskHashSize, &info, hashFlags); + + return taskHash; +} + + +/* + * TaskHashEnter creates a reference to the task entry in the given task + * hash. The function errors-out if the same key exists multiple times. + */ +static Task * +TaskHashEnter(HTAB *taskHash, Task *task) +{ + void *hashKey = NULL; + TaskMapEntry *taskInTheHash = NULL; + bool handleFound = false; + + TaskMapKey taskKey; + memset(&taskKey, 0, sizeof(TaskMapKey)); + + taskKey.taskType = task->taskType; + taskKey.jobId = task->jobId; + taskKey.taskId = task->taskId; + + hashKey = (void *) &taskKey; + taskInTheHash = (TaskMapEntry *) hash_search(taskHash, hashKey, HASH_ENTER, + &handleFound); + + /* if same node appears twice, we error-out */ + if (handleFound) + { + ereport(ERROR, (errmsg("multiple entries for task: \"%d:%ld:%d\"", + task->taskType, task->jobId, task->taskId))); + } + + /* save the pointer to the original task in the hash */ + taskInTheHash->task = task; + + return task; +} + + +/* + * TaskHashLookup looks for the tasks that corresponds to the given + * taskType, jobId and taskId, and returns the found task, NULL otherwise. + */ +static Task * +TaskHashLookup(HTAB *taskHash, TaskType taskType, uint64 jobId, uint32 taskId) +{ + TaskMapEntry *taskEntry = NULL; + Task *task = NULL; + void *hashKey = NULL; + bool handleFound = false; + + TaskMapKey taskKey; + memset(&taskKey, 0, sizeof(TaskMapKey)); + + taskKey.taskType = taskType; + taskKey.jobId = jobId; + taskKey.taskId = taskId; + + hashKey = (void *) &taskKey; + taskEntry = (TaskMapEntry *) hash_search(taskHash, hashKey, HASH_FIND, &handleFound); + + if (taskEntry != NULL) + { + task = taskEntry->task; + } + + return task; +} + + +/* + * TopLevelTask checks if the given task appears at the top level of the task + * tree. In doing this, the function assumes the physical planner creates SQL + * tasks only for the top level job. + */ +static bool +TopLevelTask(Task *task) +{ + bool topLevelTask = false; + + /* + * SQL tasks can only appear at the top level in our query tree. Further, no + * other task type can appear at the top level in our tree. + */ + if (task->taskType == SQL_TASK) + { + topLevelTask = true; + } + + return topLevelTask; +} + + +/* Determines if the given transmit task successfully completed executing. */ +static bool +TransmitExecutionCompleted(TaskExecution *taskExecution) +{ + bool completed = false; + uint32 nodeIndex = 0; + + for (nodeIndex = 0; nodeIndex < taskExecution->nodeCount; nodeIndex++) + { + TransmitExecStatus *transmitStatusArray = taskExecution->transmitStatusArray; + + TransmitExecStatus transmitStatus = transmitStatusArray[nodeIndex]; + if (transmitStatus == EXEC_TRANSMIT_DONE) + { + completed = true; + break; + } + } + + return completed; +} + + +/* + * TrackerHash creates a task tracker hash with the given name. The function + * then inserts one task tracker entry for each node in the given worker node + * list, and initializes state for each task tracker. + */ +static HTAB * +TrackerHash(const char *taskTrackerHashName, List *workerNodeList) +{ + /* create task tracker hash */ + uint32 taskTrackerHashSize = list_length(workerNodeList); + HTAB *taskTrackerHash = TrackerHashCreate(taskTrackerHashName, taskTrackerHashSize); + + ListCell *workerNodeCell = NULL; + foreach(workerNodeCell, workerNodeList) + { + WorkerNode *workerNode = (WorkerNode *) lfirst(workerNodeCell); + char *nodeName = workerNode->workerName; + uint32 nodePort = workerNode->workerPort; + + TaskTracker *taskTracker = NULL; + char taskStateHashName[MAXPGPATH]; + HTAB *taskStateHash = NULL; + uint32 taskStateCount = 32; + int hashFlags = 0; + HASHCTL info; + + /* insert task tracker into the tracker hash */ + taskTracker = TrackerHashEnter(taskTrackerHash, nodeName, nodePort); + + /* for each task tracker, create hash to track its assigned tasks */ + snprintf(taskStateHashName, MAXPGPATH, + "Task Tracker \"%s:%u\" Task State Hash", nodeName, nodePort); + + memset(&info, 0, sizeof(info)); + info.keysize = sizeof(uint64) + sizeof(uint32); + info.entrysize = sizeof(TrackerTaskState); + info.hash = tag_hash; + info.hcxt = CurrentMemoryContext; + hashFlags = (HASH_ELEM | HASH_FUNCTION | HASH_CONTEXT); + + taskStateHash = hash_create(taskStateHashName, taskStateCount, &info, hashFlags); + if (taskStateHash == NULL) + { + ereport(FATAL, (errcode(ERRCODE_OUT_OF_MEMORY), + errmsg("could not initialize %s", taskStateHashName))); + } + + taskTracker->taskStateHash = taskStateHash; + } + + return taskTrackerHash; +} + + +/* + * TrackerHashCreate allocates memory for a task tracker hash, initializes an + * empty hash, and returns this hash. + */ +static HTAB * +TrackerHashCreate(const char *taskTrackerHashName, uint32 taskTrackerHashSize) +{ + HASHCTL info; + int hashFlags = 0; + HTAB *taskTrackerHash = NULL; + + memset(&info, 0, sizeof(info)); + info.keysize = WORKER_LENGTH + sizeof(uint32); + info.entrysize = sizeof(TaskTracker); + info.hash = tag_hash; + info.hcxt = CurrentMemoryContext; + hashFlags = (HASH_ELEM | HASH_FUNCTION | HASH_CONTEXT); + + taskTrackerHash = hash_create(taskTrackerHashName, taskTrackerHashSize, + &info, hashFlags); + if (taskTrackerHash == NULL) + { + ereport(FATAL, (errcode(ERRCODE_OUT_OF_MEMORY), + errmsg("could not initialize task tracker hash"))); + } + + return taskTrackerHash; +} + + +/* + * TrackerHashEnter creates a new task tracker entry in the given task tracker + * hash, and checks that the task tracker entry has been properly created. Note + * that the caller still needs to set the tracker's task state hash field. + */ +static TaskTracker * +TrackerHashEnter(HTAB *taskTrackerHash, char *nodeName, uint32 nodePort) +{ + TaskTracker *taskTracker = NULL; + void *hashKey = NULL; + bool handleFound = false; + + TaskTracker taskTrackerKey; + memset(&taskTrackerKey, 0, sizeof(TaskTracker)); + strlcpy(taskTrackerKey.workerName, nodeName, WORKER_LENGTH); + taskTrackerKey.workerPort = nodePort; + + hashKey = (void *) &taskTrackerKey; + taskTracker = (TaskTracker *) hash_search(taskTrackerHash, hashKey, + HASH_ENTER, &handleFound); + + /* if same node appears twice, we overwrite previous entry */ + if (handleFound) + { + ereport(WARNING, (errmsg("multiple entries for task tracker: \"%s:%u\"", + nodeName, nodePort))); + } + + /* init task tracker object with zeroed out task tracker key */ + memcpy(taskTracker, &taskTrackerKey, sizeof(TaskTracker)); + taskTracker->trackerStatus = TRACKER_CONNECT_START; + taskTracker->connectionId = INVALID_CONNECTION_ID; + taskTracker->currentTaskIndex = -1; + + return taskTracker; +} + + +/* + * TrackerHashConnect walks over each task tracker in the given hash and tries + * to open an asynchronous connection to it. The function then returns when we + * tried connecting to all task trackers and have either succeeded or failed for + * each one of them. + */ +static void +TrackerHashConnect(HTAB *taskTrackerHash) +{ + uint32 taskTrackerCount = (uint32) hash_get_num_entries(taskTrackerHash); + uint32 triedTrackerCount = 0; + + /* loop until we tried to connect to all task trackers */ + while (triedTrackerCount < taskTrackerCount) + { + TaskTracker *taskTracker = NULL; + HASH_SEQ_STATUS status; + long sleepIntervalPerCycle = 0; + + /* loop over the task tracker hash, and poll all trackers again */ + triedTrackerCount = 0; + hash_seq_init(&status, taskTrackerHash); + + taskTracker = (TaskTracker *) hash_seq_search(&status); + while (taskTracker != NULL) + { + TrackerStatus trackerStatus = TrackerConnectPoll(taskTracker); + if (trackerStatus == TRACKER_CONNECTED || + trackerStatus == TRACKER_CONNECTION_FAILED) + { + triedTrackerCount++; + } + + taskTracker = (TaskTracker *) hash_seq_search(&status); + } + + /* sleep to avoid tight loop */ + sleepIntervalPerCycle = RemoteTaskCheckInterval * 1000L; + pg_usleep(sleepIntervalPerCycle); + } +} + + +/* + * TrackerConnectPoll opens an asynchronous connection to the given task tracker + * and polls this connection's status on every call. The function also sets task + * tracker's internal state on success, and returns the most recent status for + * the connection. + */ +static TrackerStatus +TrackerConnectPoll(TaskTracker *taskTracker) +{ + switch (taskTracker->trackerStatus) + { + case TRACKER_CONNECT_START: + { + char *nodeName = taskTracker->workerName; + uint32 nodePort = taskTracker->workerPort; + char *nodeDatabase = get_database_name(MyDatabaseId); + + int32 connectionId = MultiClientConnectStart(nodeName, nodePort, nodeDatabase); + if (connectionId != INVALID_CONNECTION_ID) + { + taskTracker->connectionId = connectionId; + taskTracker->trackerStatus = TRACKER_CONNECT_POLL; + } + else + { + taskTracker->trackerStatus = TRACKER_CONNECTION_FAILED; + } + + break; + } + + case TRACKER_CONNECT_POLL: + { + int32 connectionId = taskTracker->connectionId; + + ConnectStatus pollStatus = MultiClientConnectPoll(connectionId); + if (pollStatus == CLIENT_CONNECTION_READY) + { + taskTracker->trackerStatus = TRACKER_CONNECTED; + } + else if (pollStatus == CLIENT_CONNECTION_BUSY) + { + taskTracker->trackerStatus = TRACKER_CONNECT_POLL; + } + else if (pollStatus == CLIENT_CONNECTION_BAD) + { + taskTracker->trackerStatus = TRACKER_CONNECTION_FAILED; + + MultiClientDisconnect(connectionId); + taskTracker->connectionId = INVALID_CONNECTION_ID; + } + + /* now check if we have been trying to connect for too long */ + taskTracker->connectPollCount++; + if (pollStatus == CLIENT_CONNECTION_BUSY) + { + uint32 maxCount = REMOTE_NODE_CONNECT_TIMEOUT / RemoteTaskCheckInterval; + uint32 currentCount = taskTracker->connectPollCount; + if (currentCount >= maxCount) + { + ereport(WARNING, (errmsg("could not establish asynchronous connection " + "after %u ms", REMOTE_NODE_CONNECT_TIMEOUT))); + + taskTracker->trackerStatus = TRACKER_CONNECTION_FAILED; + + MultiClientDisconnect(connectionId); + taskTracker->connectionId = INVALID_CONNECTION_ID; + } + } + + break; + } + + case TRACKER_CONNECTED: + case TRACKER_CONNECTION_FAILED: + { + /* if connected or failed to connect in previous pass, reset poll count */ + taskTracker->connectPollCount = 0; + break; + } + + default: + { + int trackerStatus = (int) taskTracker->trackerStatus; + ereport(FATAL, (errmsg("invalid task tracker status: %d", trackerStatus))); + break; + } + } + + return taskTracker->trackerStatus; +} + + +/* + * ResolveTaskTracker is a helper function that resolves the task tracker from + * the given task and task execution. The function first finds the worker node + * the given task is scheduled to, and resolves the corresponding task tracker. + */ +static TaskTracker * +ResolveTaskTracker(HTAB *trackerHash, Task *task, TaskExecution *taskExecution) +{ + List *taskPlacementList = task->taskPlacementList; + uint32 currentIndex = taskExecution->currentNodeIndex; + + ShardPlacement *taskPlacement = list_nth(taskPlacementList, currentIndex); + char *nodeName = taskPlacement->nodeName; + uint32 nodePort = taskPlacement->nodePort; + + /* look up in the tracker hash for the found node name/port */ + TaskTracker *taskTracker = TrackerHashLookup(trackerHash, nodeName, nodePort); + Assert(taskTracker != NULL); + + return taskTracker; +} + + +/* + * ResolveMapTaskTracker is a helper function that finds the downstream map task + * dependency from the given task, and then resolves the task tracker for this + * map task. + */ +static TaskTracker * +ResolveMapTaskTracker(HTAB *trackerHash, Task *task, TaskExecution *taskExecution) +{ + TaskTracker *mapTaskTracker = NULL; + Task *mapTask = NULL; + TaskExecution *mapTaskExecution = NULL; + + /* we only resolve source (map) task tracker for map output fetch tasks */ + if (task->taskType != MAP_OUTPUT_FETCH_TASK) + { + return NULL; + } + + Assert(task->dependedTaskList != NIL); + mapTask = (Task *) linitial(task->dependedTaskList); + mapTaskExecution = mapTask->taskExecution; + + mapTaskTracker = ResolveTaskTracker(trackerHash, mapTask, mapTaskExecution); + Assert(mapTaskTracker != NULL); + + return mapTaskTracker; +} + + +/* + * TrackerHashLookup looks for the task tracker that corresponds to the given + * node name and port number, and returns the found task tracker if any. + */ +static TaskTracker * +TrackerHashLookup(HTAB *trackerHash, const char *nodeName, uint32 nodePort) +{ + TaskTracker *taskTracker = NULL; + void *hashKey = NULL; + bool handleFound = false; + + TaskTracker taskTrackerKey; + memset(taskTrackerKey.workerName, 0, WORKER_LENGTH); + strlcpy(taskTrackerKey.workerName, nodeName, WORKER_LENGTH); + taskTrackerKey.workerPort = nodePort; + + hashKey = (void *) &taskTrackerKey; + taskTracker = (TaskTracker *) hash_search(trackerHash, hashKey, + HASH_FIND, &handleFound); + if (taskTracker == NULL || !handleFound) + { + ereport(ERROR, (errmsg("could not find task tracker for node \"%s:%u\"", + nodeName, nodePort))); + } + + return taskTracker; +} + + +/* + * ManageTaskExecution manages all execution logic for the given task. For this, + * the function checks if the task's downstream dependencies have completed. If + * they have, the function assigns the task to the task tracker proxy object, + * and regularly checks the task's execution status. + * + * If the task completes, the function changes task's status. Else if the task + * observes a connection related failure, the function retries the task on the + * same task tracker. Else if the task tracker isn't considered as healthy, the + * function signals to the caller that the task needs to be assigned to another + * task tracker. + */ +static TaskExecStatus +ManageTaskExecution(TaskTracker *taskTracker, TaskTracker *sourceTaskTracker, + Task *task, TaskExecution *taskExecution) +{ + TaskExecStatus *taskStatusArray = taskExecution->taskStatusArray; + uint32 currentNodeIndex = taskExecution->currentNodeIndex; + uint32 nextNodeIndex = 0; + + TaskExecStatus currentExecutionStatus = taskStatusArray[currentNodeIndex]; + TaskExecStatus nextExecutionStatus = EXEC_TASK_INVALID_FIRST; + + switch (currentExecutionStatus) + { + case EXEC_TASK_UNASSIGNED: + { + bool taskExecutionsCompleted = true; + TaskType taskType = TASK_TYPE_INVALID_FIRST; + + bool trackerHealthy = TrackerHealthy(taskTracker); + if (!trackerHealthy) + { + nextExecutionStatus = EXEC_TASK_TRACKER_FAILED; + break; + } + + /* + * We first retrieve this task's downstream dependencies, and then check + * if these dependencies' executions have completed. + */ + taskExecutionsCompleted = TaskExecutionsCompleted(task->dependedTaskList); + if (!taskExecutionsCompleted) + { + nextExecutionStatus = EXEC_TASK_UNASSIGNED; + break; + } + + /* if map fetch task, create query string from completed map task */ + taskType = task->taskType; + if (taskType == MAP_OUTPUT_FETCH_TASK) + { + StringInfo mapFetchTaskQueryString = NULL; + Task *mapTask = (Task *) linitial(task->dependedTaskList); + TaskExecution *mapTaskExecution = mapTask->taskExecution; + + mapFetchTaskQueryString = MapFetchTaskQueryString(task, mapTask); + task->queryString = mapFetchTaskQueryString->data; + taskExecution->querySourceNodeIndex = mapTaskExecution->currentNodeIndex; + } + + /* + * We finally queue this task for execution. Note that we queue sql and + * other tasks slightly differently. + */ + if (taskType == SQL_TASK) + { + TrackerQueueSqlTask(taskTracker, task); + } + else + { + TrackerQueueTask(taskTracker, task); + } + + nextExecutionStatus = EXEC_TASK_QUEUED; + break; + } + + case EXEC_TASK_QUEUED: + { + TaskStatus remoteTaskStatus = TASK_STATUS_INVALID_FIRST; + + bool trackerHealthy = TrackerHealthy(taskTracker); + if (!trackerHealthy) + { + nextExecutionStatus = EXEC_TASK_TRACKER_FAILED; + break; + } + + remoteTaskStatus = TrackerTaskStatus(taskTracker, task); + if (remoteTaskStatus == TASK_SUCCEEDED) + { + nextExecutionStatus = EXEC_TASK_DONE; + } + else if (remoteTaskStatus == TASK_CLIENT_SIDE_ASSIGN_FAILED || + remoteTaskStatus == TASK_CLIENT_SIDE_STATUS_FAILED) + { + nextExecutionStatus = EXEC_TASK_TRACKER_RETRY; + } + else if (remoteTaskStatus == TASK_PERMANENTLY_FAILED) + { + /* + * If a map output fetch task failed, we assume the problem lies with + * the map task (and the source task tracker it runs on). Otherwise, + * we assume the task tracker crashed, and fail over to the next task + * tracker. + */ + if (task->taskType == MAP_OUTPUT_FETCH_TASK) + { + nextExecutionStatus = EXEC_SOURCE_TASK_TRACKER_RETRY; + } + else + { + nextExecutionStatus = EXEC_TASK_TRACKER_FAILED; + } + } + else + { + /* assume task is still in progress */ + nextExecutionStatus = EXEC_TASK_QUEUED; + } + + break; + } + + case EXEC_TASK_TRACKER_RETRY: + { + bool trackerHealthy = false; + bool trackerConnectionUp = false; + + /* + * This case statement usually handles connection related issues. Some + * edge cases however, like a user sending a SIGTERM to the worker node, + * keep the connection open but disallow task assignments. We therefore + * need to track those as intermittent tracker failures here. + */ + trackerConnectionUp = TrackerConnectionUp(taskTracker); + if (trackerConnectionUp) + { + taskTracker->trackerFailureCount++; + } + + trackerHealthy = TrackerHealthy(taskTracker); + if (trackerHealthy) + { + TaskStatus remoteTaskStatus = TrackerTaskStatus(taskTracker, task); + if (remoteTaskStatus == TASK_CLIENT_SIDE_ASSIGN_FAILED) + { + nextExecutionStatus = EXEC_TASK_UNASSIGNED; + } + else if (remoteTaskStatus == TASK_CLIENT_SIDE_STATUS_FAILED) + { + nextExecutionStatus = EXEC_TASK_QUEUED; + } + } + else + { + nextExecutionStatus = EXEC_TASK_TRACKER_FAILED; + } + + break; + } + + case EXEC_SOURCE_TASK_TRACKER_RETRY: + { + Task *mapTask = (Task *) linitial(task->dependedTaskList); + TaskExecution *mapTaskExecution = mapTask->taskExecution; + uint32 sourceNodeIndex = mapTaskExecution->currentNodeIndex; + + bool sourceTrackerHealthy = false; + Assert(sourceTaskTracker != NULL); + Assert(task->taskType == MAP_OUTPUT_FETCH_TASK); + + /* + * As this map fetch task was running, another map fetch that depends on + * another map task might have failed. We would have then reassigned the + * map task and potentially other map tasks in its constraint group. So + * this map fetch's source node might have changed underneath us. If it + * did, we don't want to record a failure for the new source tracker. + */ + if (taskExecution->querySourceNodeIndex == sourceNodeIndex) + { + bool sourceTrackerConnectionUp = TrackerConnectionUp(sourceTaskTracker); + if (sourceTrackerConnectionUp) + { + sourceTaskTracker->trackerFailureCount++; + } + } + + sourceTrackerHealthy = TrackerHealthy(sourceTaskTracker); + if (sourceTrackerHealthy) + { + /* + * We change our status to unassigned. In that status, we queue an + * "update map fetch task" on the task tracker, and retry fetching + * the map task's output from the same source node. + */ + nextExecutionStatus = EXEC_TASK_UNASSIGNED; + } + else + { + nextExecutionStatus = EXEC_SOURCE_TASK_TRACKER_FAILED; + } + + break; + } + + case EXEC_TASK_TRACKER_FAILED: + case EXEC_SOURCE_TASK_TRACKER_FAILED: + { + /* + * These two cases exist to signal to the caller that we failed. In both + * cases, the caller is responsible for reassigning task(s) and running + * the appropriate recovery logic. + */ + nextExecutionStatus = EXEC_TASK_UNASSIGNED; + break; + } + + case EXEC_TASK_DONE: + { + /* we are done with this task's execution */ + nextExecutionStatus = EXEC_TASK_DONE; + break; + } + + default: + { + /* we fatal here to avoid leaking client-side resources */ + ereport(FATAL, (errmsg("invalid execution status: %d", currentExecutionStatus))); + break; + } + } + + /* update task execution's status for most recent task tracker */ + nextNodeIndex = taskExecution->currentNodeIndex; + taskStatusArray[nextNodeIndex] = nextExecutionStatus; + + return nextExecutionStatus; +} + + +/* + * ManageTransmitExecution manages logic to fetch the results of the given SQL + * task to the master node. For this, the function checks if the given SQL task + * has completed. If it has, the function starts the copy out protocol to fetch + * the task's results and write them to the local filesystem. When the transmit + * completes or fails, the function notes that by changing the transmit status. + */ +static TransmitExecStatus +ManageTransmitExecution(TaskTracker *transmitTracker, + Task *task, TaskExecution *taskExecution) +{ + int32 *fileDescriptorArray = taskExecution->fileDescriptorArray; + uint32 currentNodeIndex = taskExecution->currentNodeIndex; + uint32 nextNodeIndex = 0; + + TransmitExecStatus *transmitStatusArray = taskExecution->transmitStatusArray; + TransmitExecStatus currentTransmitStatus = transmitStatusArray[currentNodeIndex]; + TransmitExecStatus nextTransmitStatus = EXEC_TRANSMIT_INVALID_FIRST; + Assert(task->taskType == SQL_TASK); + + switch (currentTransmitStatus) + { + case EXEC_TRANSMIT_UNASSIGNED: + { + TaskExecStatus *taskStatusArray = taskExecution->taskStatusArray; + TaskExecStatus currentExecutionStatus = taskStatusArray[currentNodeIndex]; + bool trackerHealthy = false; + + /* if top level task's in progress, nothing to do */ + if (currentExecutionStatus != EXEC_TASK_DONE) + { + nextTransmitStatus = EXEC_TRANSMIT_UNASSIGNED; + break; + } + + trackerHealthy = TrackerHealthy(transmitTracker); + if (!trackerHealthy) + { + nextTransmitStatus = EXEC_TRANSMIT_TRACKER_FAILED; + break; + } + + TrackerQueueFileTransmit(transmitTracker, task); + nextTransmitStatus = EXEC_TRANSMIT_QUEUED; + break; + } + + case EXEC_TRANSMIT_QUEUED: + { + QueryStatus queryStatus = CLIENT_INVALID_QUERY; + int32 connectionId = INVALID_CONNECTION_ID; + TaskStatus taskStatus = TASK_STATUS_INVALID_FIRST; + + bool trackerHealthy = TrackerHealthy(transmitTracker); + if (!trackerHealthy) + { + nextTransmitStatus = EXEC_TRANSMIT_TRACKER_FAILED; + break; + } + + taskStatus = TrackerTaskStatus(transmitTracker, task); + if (taskStatus == TASK_FILE_TRANSMIT_QUEUED) + { + /* remain in queued status until tracker assigns this task */ + nextTransmitStatus = EXEC_TRANSMIT_QUEUED; + break; + } + else if (taskStatus == TASK_CLIENT_SIDE_TRANSMIT_FAILED) + { + nextTransmitStatus = EXEC_TRANSMIT_TRACKER_RETRY; + break; + } + + /* the open connection belongs to this task */ + connectionId = TransmitTrackerConnectionId(transmitTracker, task); + Assert(connectionId != INVALID_CONNECTION_ID); + Assert(taskStatus == TASK_ASSIGNED); + + /* start copy protocol */ + queryStatus = MultiClientQueryStatus(connectionId); + if (queryStatus == CLIENT_QUERY_COPY) + { + StringInfo jobDirectoryName = JobDirectoryName(task->jobId); + StringInfo taskFilename = TaskFilename(jobDirectoryName, task->taskId); + + char *filename = taskFilename->data; + int fileFlags = (O_APPEND | O_CREAT | O_RDWR | O_TRUNC | PG_BINARY); + int fileMode = (S_IRUSR | S_IWUSR); + + int32 fileDescriptor = BasicOpenFile(filename, fileFlags, fileMode); + if (fileDescriptor >= 0) + { + /* + * All files inside the job directory get automatically cleaned + * up on transaction commit or abort. + */ + fileDescriptorArray[currentNodeIndex] = fileDescriptor; + nextTransmitStatus = EXEC_TRANSMIT_COPYING; + } + else + { + ereport(WARNING, (errcode_for_file_access(), + errmsg("could not open file \"%s\": %m", filename))); + + nextTransmitStatus = EXEC_TRANSMIT_TRACKER_RETRY; + } + } + else + { + nextTransmitStatus = EXEC_TRANSMIT_TRACKER_RETRY; + } + + /* + * We use task tracker logic to manage file transmits as well, but that + * abstraction starts to leak after we drop into the copy protocol. To + * make our task tracker logic work, we need to "void" the tracker's + * connection if the transmit task failed in here. + */ + if (nextTransmitStatus == EXEC_TRANSMIT_TRACKER_RETRY) + { + transmitTracker->connectionBusy = false; + transmitTracker->connectionBusyOnTask = NULL; + } + + break; + } + + case EXEC_TRANSMIT_COPYING: + { + int32 fileDescriptor = fileDescriptorArray[currentNodeIndex]; + CopyStatus copyStatus = CLIENT_INVALID_COPY; + int closed = -1; + + /* the open connection belongs to this task */ + int32 connectionId = TransmitTrackerConnectionId(transmitTracker, task); + Assert(connectionId != INVALID_CONNECTION_ID); + + copyStatus = MultiClientCopyData(connectionId, fileDescriptor); + if (copyStatus == CLIENT_COPY_MORE) + { + /* worker node continues to send more data, keep reading */ + nextTransmitStatus = EXEC_TRANSMIT_COPYING; + break; + } + + /* we are done copying data */ + if (copyStatus == CLIENT_COPY_DONE) + { + closed = close(fileDescriptor); + fileDescriptorArray[currentNodeIndex] = -1; + + if (closed >= 0) + { + nextTransmitStatus = EXEC_TRANSMIT_DONE; + } + else + { + ereport(WARNING, (errcode_for_file_access(), + errmsg("could not close copied file: %m"))); + + nextTransmitStatus = EXEC_TRANSMIT_TRACKER_RETRY; + } + } + else if (copyStatus == CLIENT_COPY_FAILED) + { + nextTransmitStatus = EXEC_TRANSMIT_TRACKER_RETRY; + + closed = close(fileDescriptor); + fileDescriptorArray[currentNodeIndex] = -1; + + if (closed < 0) + { + ereport(WARNING, (errcode_for_file_access(), + errmsg("could not close copy file: %m"))); + } + } + + /* + * We use task tracker logic to manage file transmits as well, but that + * abstraction leaks after we drop into the copy protocol. To make it + * work, we reset transmit tracker's connection for next file transmit. + */ + transmitTracker->connectionBusy = false; + transmitTracker->connectionBusyOnTask = NULL; + + break; + } + + case EXEC_TRANSMIT_TRACKER_RETRY: + { + bool trackerHealthy = false; + bool trackerConnectionUp = false; + + /* + * The task tracker proxy handles connection errors. On the off chance + * that our connection is still up and the transmit tracker misbehaved, + * we capture this as an intermittent tracker failure. + */ + trackerConnectionUp = TrackerConnectionUp(transmitTracker); + if (trackerConnectionUp) + { + transmitTracker->trackerFailureCount++; + } + + trackerHealthy = TrackerHealthy(transmitTracker); + if (trackerHealthy) + { + nextTransmitStatus = EXEC_TRANSMIT_UNASSIGNED; + } + else + { + nextTransmitStatus = EXEC_TRANSMIT_TRACKER_FAILED; + } + + break; + } + + case EXEC_TRANSMIT_TRACKER_FAILED: + { + /* + * This case exists to signal to the caller that we failed. The caller + * is now responsible for reassigning the transmit task (and downstream + * SQL task dependencies) and running the appropriate recovery logic. + */ + nextTransmitStatus = EXEC_TRANSMIT_UNASSIGNED; + break; + } + + case EXEC_TRANSMIT_DONE: + { + /* we are done with fetching task results to the master node */ + nextTransmitStatus = EXEC_TRANSMIT_DONE; + break; + } + + default: + { + /* we fatal here to avoid leaking client-side resources */ + ereport(FATAL, (errmsg("invalid transmit status: %d", currentTransmitStatus))); + break; + } + } + + /* update file transmit status for most recent transmit tracker */ + nextNodeIndex = taskExecution->currentNodeIndex; + transmitStatusArray[nextNodeIndex] = nextTransmitStatus; + + return nextTransmitStatus; +} + + +/* + * TaskExecutionsCompleted checks if all task executions in the given task list + * have completed. If they have, the function returns true. Note that this + * function takes the list of tasks as an optimization over separately + * extracting a list of task executions, but it should only operate on task + * executions to preserve the abstraction. + */ +static bool +TaskExecutionsCompleted(List *taskList) +{ + bool taskExecutionsComplete = true; + ListCell *taskCell = NULL; + + foreach(taskCell, taskList) + { + Task *task = (Task *) lfirst(taskCell); + TaskExecution *taskExecution = task->taskExecution; + uint32 nodeIndex = taskExecution->currentNodeIndex; + + TaskExecStatus taskStatus = taskExecution->taskStatusArray[nodeIndex]; + if (taskStatus != EXEC_TASK_DONE) + { + taskExecutionsComplete = false; + break; + } + } + + return taskExecutionsComplete; +} + + +/* + * MapFetchTaskQueryString constructs the map fetch query string from the given + * map output fetch task and its downstream map task dependency. The constructed + * query string allows fetching the map task's partitioned output file from the + * worker node it's created to the worker node that will execute the merge task. + */ +static StringInfo +MapFetchTaskQueryString(Task *mapFetchTask, Task *mapTask) +{ + StringInfo mapFetchQueryString = NULL; + uint32 partitionFileId = mapFetchTask->partitionId; + uint32 mergeTaskId = mapFetchTask->upstreamTaskId; + + /* find the node name/port for map task's execution */ + List *mapTaskPlacementList = mapTask->taskPlacementList; + TaskExecution *mapTaskExecution = mapTask->taskExecution; + uint32 currentIndex = mapTaskExecution->currentNodeIndex; + + ShardPlacement *mapTaskPlacement = list_nth(mapTaskPlacementList, currentIndex); + char *mapTaskNodeName = mapTaskPlacement->nodeName; + uint32 mapTaskNodePort = mapTaskPlacement->nodePort; + + Assert(mapFetchTask->taskType == MAP_OUTPUT_FETCH_TASK); + Assert(mapTask->taskType == MAP_TASK); + + mapFetchQueryString = makeStringInfo(); + appendStringInfo(mapFetchQueryString, MAP_OUTPUT_FETCH_COMMAND, + mapTask->jobId, mapTask->taskId, partitionFileId, + mergeTaskId, /* fetch results to merge task */ + mapTaskNodeName, mapTaskNodePort); + + return mapFetchQueryString; +} + + +/* + * TrackerQueueSqlTask wraps a copy out command around the given task's query, + * creates a task assignment query from this copy out command, and then queues + * this assignment query in the given tracker's internal hash. The queued query + * will be assigned to the remote task tracker at a later time. + */ +static void +TrackerQueueSqlTask(TaskTracker *taskTracker, Task *task) +{ + HTAB *taskStateHash = taskTracker->taskStateHash; + TrackerTaskState *taskState = NULL; + StringInfo taskAssignmentQuery = NULL; + + /* + * We first wrap a copy out command around the original query string. This + * allows for the query's results to persist on the worker node after the + * query completes and for the executor to later use this persisted data. + */ + StringInfo jobDirectoryName = JobDirectoryName(task->jobId); + StringInfo taskFilename = TaskFilename(jobDirectoryName, task->taskId); + + StringInfo copyQueryString = makeStringInfo(); + + if (BinaryMasterCopyFormat) + { + appendStringInfo(copyQueryString, COPY_QUERY_TO_FILE_BINARY, + task->queryString, taskFilename->data); + } + else + { + appendStringInfo(copyQueryString, COPY_QUERY_TO_FILE_TEXT, + task->queryString, taskFilename->data); + } + + /* wrap a task assignment query outside the copy out query */ + taskAssignmentQuery = TaskAssignmentQuery(task, copyQueryString->data); + + taskState = TaskStateHashEnter(taskStateHash, task->jobId, task->taskId); + taskState->status = TASK_CLIENT_SIDE_QUEUED; + taskState->taskAssignmentQuery = taskAssignmentQuery; +} + + +/* + * TrackerQueueTask creates a task assignment query from the given task's query + * string, and then queues this assignment query in the given tracker's internal + * hash. The queued query will be assigned to the remote task tracker at a later + * time. + */ +static void +TrackerQueueTask(TaskTracker *taskTracker, Task *task) +{ + HTAB *taskStateHash = taskTracker->taskStateHash; + TrackerTaskState *taskState = NULL; + StringInfo taskAssignmentQuery = NULL; + + /* wrap a task assignment query outside the original query */ + taskAssignmentQuery = TaskAssignmentQuery(task, task->queryString); + + taskState = TaskStateHashEnter(taskStateHash, task->jobId, task->taskId); + taskState->status = TASK_CLIENT_SIDE_QUEUED; + taskState->taskAssignmentQuery = taskAssignmentQuery; +} + + +/* + * TaskAssignmentQuery escapes the given query string with quotes, and wraps + * this escaped query string inside a task assignment command. This way, the + * query can be assigned to the remote task tracker. + */ +static StringInfo +TaskAssignmentQuery(Task *task, char *queryString) +{ + StringInfo taskAssignmentQuery = NULL; + + /* quote the original query as a string literal */ + char *escapedQueryString = quote_literal_cstr(queryString); + + taskAssignmentQuery = makeStringInfo(); + appendStringInfo(taskAssignmentQuery, TASK_ASSIGNMENT_QUERY, + task->jobId, task->taskId, escapedQueryString); + + return taskAssignmentQuery; +} + + +/* + * TrackerTaskStatus returns the remote execution status of the given task. Note + * that the task must have already been queued with the task tracker for status + * checking to happen. + */ +static TaskStatus +TrackerTaskStatus(TaskTracker *taskTracker, Task *task) +{ + HTAB *taskStateHash = taskTracker->taskStateHash; + + TrackerTaskState *taskState = TrackerTaskStateHashLookup(taskStateHash, task); + if (taskState == NULL) + { + const char *nodeName = taskTracker->workerName; + uint32 nodePort = taskTracker->workerPort; + + ereport(ERROR, (errmsg("could not find task state for job " UINT64_FORMAT + " and task %u", task->jobId, task->taskId), + errdetail("Task tracker: \"%s:%u\"", nodeName, nodePort))); + } + + return taskState->status; +} + + +/* + * TrackerTaskStateHashLookup looks for the task state entry for the given task + * in the task tracker's state hash. The function then returns the found task + * state entry, if any. + */ +static TrackerTaskState * +TrackerTaskStateHashLookup(HTAB *taskStateHash, Task *task) +{ + TrackerTaskState *taskState = NULL; + void *hashKey = NULL; + bool handleFound = false; + + TrackerTaskState taskStateKey; + taskStateKey.jobId = task->jobId; + taskStateKey.taskId = task->taskId; + + hashKey = (void *) &taskStateKey; + taskState = (TrackerTaskState *) hash_search(taskStateHash, hashKey, + HASH_FIND, &handleFound); + + return taskState; +} + + +/* Checks if the given task tracker is considered as healthy. */ +static bool +TrackerHealthy(TaskTracker *taskTracker) +{ + bool trackerHealthy = false; + + if (taskTracker->trackerFailureCount < MAX_TRACKER_FAILURE_COUNT && + taskTracker->connectionFailureCount < MAX_TRACKER_FAILURE_COUNT) + { + trackerHealthy = true; + } + + return trackerHealthy; +} + + +/* + * TrackerQueueFileTransmit queues a file transmit request in the given task + * tracker's internal hash. The queued request will be served at a later time. + */ +static void +TrackerQueueFileTransmit(TaskTracker *transmitTracker, Task *task) +{ + HTAB *transmitStateHash = transmitTracker->taskStateHash; + TrackerTaskState *transmitState = NULL; + + transmitState = TaskStateHashEnter(transmitStateHash, task->jobId, task->taskId); + transmitState->status = TASK_FILE_TRANSMIT_QUEUED; +} + + +/* + * TaskStateHashEnter creates a new task state entry in the given task state + * hash, and checks that the task entry has been properly created. + */ +static TrackerTaskState * +TaskStateHashEnter(HTAB *taskStateHash, uint64 jobId, uint32 taskId) +{ + TrackerTaskState *taskState = NULL; + void *hashKey = NULL; + bool handleFound = false; + + TrackerTaskState taskStateKey; + taskStateKey.jobId = jobId; + taskStateKey.taskId = taskId; + + hashKey = (void *) &taskStateKey; + taskState = (TrackerTaskState *) hash_search(taskStateHash, hashKey, + HASH_ENTER, &handleFound); + + /* if same task queued twice, we overwrite previous entry */ + if (handleFound) + { + ereport(DEBUG1, (errmsg("multiple task state entries for job " + UINT64_FORMAT " and task %u", jobId, taskId))); + } + + /* init task state object */ + taskState->status = TASK_STATUS_INVALID_FIRST; + taskState->taskAssignmentQuery = NULL; + + return taskState; +} + + +/* + * TransmitTrackerConnectionId checks if the given tracker is transmitting the + * given task's results to the master node. If it is, the function returns the + * connectionId used in transmitting task results. If not, the function returns + * an invalid connectionId. + */ +static int32 +TransmitTrackerConnectionId(TaskTracker *transmitTracker, Task *task) +{ + int32 connectionId = INVALID_CONNECTION_ID; + + TrackerTaskState *transmitState = transmitTracker->connectionBusyOnTask; + if (transmitState != NULL) + { + /* we are transmitting results for this particular task */ + if (transmitState->jobId == task->jobId && + transmitState->taskId == task->taskId) + { + connectionId = transmitTracker->connectionId; + } + } + + return connectionId; +} + + +/* + * ConstrainedTaskList finds the given task's constraint group within the given + * task and execution list. We define a constraint group as all tasks that need + * to be assigned (or reassigned) to the same task tracker for query execution + * to complete. At a high level, compute tasks and their data fetch dependencies + * are part of the same constraint group. Also, the transitive closure of tasks + * that have the same merge task dependency are part of one constraint group. + */ +static List * +ConstrainedTaskList(List *taskAndExecutionList, Task *task) +{ + List *constrainedTaskList = NIL; + Task *constrainingTask = NULL; + List *mergeTaskList = NIL; + ListCell *mergeTaskCell = NULL; + List *upstreamTaskList = NIL; + ListCell *upstreamTaskCell = NULL; + + /* + * We first check if this task depends on any merge tasks. If it does *not*, + * the task's dependency list becomes our tiny constraint group. + */ + mergeTaskList = ConstrainedMergeTaskList(taskAndExecutionList, task); + if (mergeTaskList == NIL) + { + constrainedTaskList = ConstrainedNonMergeTaskList(taskAndExecutionList, task); + + return constrainedTaskList; + } + + /* we first add merge tasks and their dependencies to our constraint group */ + foreach(mergeTaskCell, mergeTaskList) + { + Task *mergeTask = (Task *) lfirst(mergeTaskCell); + List *dependedTaskList = mergeTask->dependedTaskList; + + constrainedTaskList = lappend(constrainedTaskList, mergeTask); + constrainedTaskList = TaskListConcatUnique(constrainedTaskList, dependedTaskList); + } + + /* + * We now pick the first merge task as our constraining task, and walk over + * the task list looking for any tasks that depend on the constraining merge + * task. Note that finding a task's upstream dependencies necessitates that + * we walk over all the tasks. If we want to optimize this later on, we can + * precompute a task list that excludes map fetch tasks. + */ + constrainingTask = (Task *) linitial(mergeTaskList); + + upstreamTaskList = UpstreamDependencyList(taskAndExecutionList, constrainingTask); + Assert(upstreamTaskList != NIL); + + foreach(upstreamTaskCell, upstreamTaskList) + { + Task *upstreamTask = (Task *) lfirst(upstreamTaskCell); + List *dependedTaskList = upstreamTask->dependedTaskList; + + /* + * We already added merge tasks to our constrained list. We therefore use + * concat unique to ensure they don't get appended for a second time. + */ + constrainedTaskList = TaskListAppendUnique(constrainedTaskList, upstreamTask); + constrainedTaskList = TaskListConcatUnique(constrainedTaskList, dependedTaskList); + } + + return constrainedTaskList; +} + + +/* + * ConstrainedNonMergeTaskList finds the constraint group for the given task, + * assuming that the given task doesn't have any merge task dependencies. This + * constraint group includes a compute task and its downstream data fetch task + * dependencies. + */ +static List * +ConstrainedNonMergeTaskList(List *taskAndExecutionList, Task *task) +{ + List *constrainedTaskList = NIL; + Task *upstreamTask = NULL; + List *dependedTaskList = NIL; + + TaskType taskType = task->taskType; + if (taskType == SQL_TASK || taskType == MAP_TASK) + { + upstreamTask = task; + dependedTaskList = upstreamTask->dependedTaskList; + } + else if (taskType == SHARD_FETCH_TASK) + { + List *upstreamTaskList = UpstreamDependencyList(taskAndExecutionList, task); + Assert(list_length(upstreamTaskList) == 1); + + upstreamTask = (Task *) linitial(upstreamTaskList); + dependedTaskList = upstreamTask->dependedTaskList; + } + Assert(upstreamTask != NULL); + + constrainedTaskList = list_make1(upstreamTask); + constrainedTaskList = list_concat(constrainedTaskList, dependedTaskList); + + return constrainedTaskList; +} + + +/* + * UpstreamDependencyList looks for the given task's upstream task dependencies + * in the given task and execution list. For this, the function walks across all + * tasks in the task list. This walk is expensive due to the number of map fetch + * tasks involved; and this function should be called sparingly. + */ +static List * +UpstreamDependencyList(List *taskAndExecutionList, Task *searchedTask) +{ + List *upstreamTaskList = NIL; + ListCell *taskAndExecutionCell = NULL; + + foreach(taskAndExecutionCell, taskAndExecutionList) + { + Task *upstreamTask = (Task *) lfirst(taskAndExecutionCell); + List *dependedTaskList = upstreamTask->dependedTaskList; + ListCell *dependedTaskCell = NULL; + + /* + * The given task and its upstream dependency cannot be of the same type. + * We perform this check as an optimization. This way, we can quickly + * skip over upstream map fetch tasks if we aren't looking for them. + */ + if (upstreamTask->taskType == searchedTask->taskType) + { + continue; + } + + /* + * We walk over the upstream task's dependency list, and check if any of + * them is the task we are looking for. + */ + foreach(dependedTaskCell, dependedTaskList) + { + Task *dependedTask = (Task *) lfirst(dependedTaskCell); + if (TasksEqual(dependedTask, searchedTask)) + { + upstreamTaskList = lappend(upstreamTaskList, upstreamTask); + } + } + } + + return upstreamTaskList; +} + + +/* + * ConstrainedMergeTaskList finds any merge task dependencies for the given task. + * Note that a given task may have zero, one, or two merge task dependencies. To + * resolve all dependencies, the function first looks at the task's type. Then, + * the function may need to find the task's parent, and resolve any merge task + * dependencies from that parent task. + */ +static List * +ConstrainedMergeTaskList(List *taskAndExecutionList, Task *task) +{ + List *constrainedMergeTaskList = NIL; + TaskType taskType = task->taskType; + + /* + * We find the list of constraining merge tasks for the given task. If the + * given task is a SQL or map task, we simply need to find its merge task + * dependencies -- if any. + */ + if (taskType == SQL_TASK || taskType == MAP_TASK) + { + constrainedMergeTaskList = MergeTaskList(task->dependedTaskList); + } + else if (taskType == SHARD_FETCH_TASK) + { + Task *upstreamTask = NULL; + List *upstreamTaskList = UpstreamDependencyList(taskAndExecutionList, task); + + /* + * A shard fetch task can only have one SQL/map task parent. We now get + * that parent. From the parent, we find any merge task dependencies. + */ + Assert(list_length(upstreamTaskList) == 1); + upstreamTask = (Task *) linitial(upstreamTaskList); + + constrainedMergeTaskList = MergeTaskList(upstreamTask->dependedTaskList); + } + else if (taskType == MAP_OUTPUT_FETCH_TASK) + { + List *taskList = UpstreamDependencyList(taskAndExecutionList, task); + Task *mergeTask = (Task *) linitial(taskList); + + /* + * Once we resolve the merge task, we use the exact same logic as below + * to find any other merge task in our constraint group. + */ + List *upstreamTaskList = UpstreamDependencyList(taskAndExecutionList, mergeTask); + Task *upstreamTask = (Task *) linitial(upstreamTaskList); + + constrainedMergeTaskList = MergeTaskList(upstreamTask->dependedTaskList); + } + else if (taskType == MERGE_TASK) + { + Task *upstreamTask = NULL; + List *upstreamTaskList = UpstreamDependencyList(taskAndExecutionList, task); + + /* + * A merge task can have multiple SQL/map task parents. We now get only + * one of those parents. We then search if the parent depends on another + * merge task besides us. + */ + Assert(upstreamTaskList != NIL); + upstreamTask = (Task *) linitial(upstreamTaskList); + + constrainedMergeTaskList = MergeTaskList(upstreamTask->dependedTaskList); + } + + return constrainedMergeTaskList; +} + + +/* + * MergeTaskList walks over the given task list, finds the merge tasks in the + * list, and returns the found tasks in a new list. + */ +static List * +MergeTaskList(List *taskList) +{ + List *mergeTaskList = NIL; + ListCell *taskCell = NULL; + + foreach(taskCell, taskList) + { + Task *task = (Task *) lfirst(taskCell); + if (task->taskType == MERGE_TASK) + { + mergeTaskList = lappend(mergeTaskList, task); + } + } + + return mergeTaskList; +} + + +/* + * ReassignTaskList walks over all tasks in the given task list, and reassigns + * each task's execution and transmit to the next worker node. This ensures that + * all tasks within the same constraint group are failed over to the next node + * together. The function also increments each task's failure counter. + */ +static void +ReassignTaskList(List *taskList) +{ + List *completedTaskList = NIL; + ListCell *taskCell = NULL; + + /* + * As an optimization, we first find the SQL tasks whose results we already + * fetched to the master node. We don't need to re-execute these SQL tasks + * or their shard fetch dependencies. + */ + foreach(taskCell, taskList) + { + Task *task = (Task *) lfirst(taskCell); + TaskExecution *taskExecution = task->taskExecution; + + bool transmitCompleted = TransmitExecutionCompleted(taskExecution); + if ((task->taskType == SQL_TASK) && transmitCompleted) + { + List *shardFetchTaskList = ShardFetchTaskList(task->dependedTaskList); + + completedTaskList = lappend(completedTaskList, task); + completedTaskList = TaskListUnion(completedTaskList, shardFetchTaskList); + } + } + + taskList = TaskListDifference(taskList, completedTaskList); + + taskCell = NULL; + foreach(taskCell, taskList) + { + Task *task = (Task *) lfirst(taskCell); + TaskExecution *taskExecution = task->taskExecution; + + uint32 currentNodeIndex = taskExecution->currentNodeIndex; + TaskExecStatus *taskStatusArray = taskExecution->taskStatusArray; + TransmitExecStatus *transmitStatusArray = taskExecution->transmitStatusArray; + + /* + * We reset current task statuses in case we fail on all other worker + * nodes and come back to this one. + */ + taskStatusArray[currentNodeIndex] = EXEC_TASK_UNASSIGNED; + transmitStatusArray[currentNodeIndex] = EXEC_TRANSMIT_UNASSIGNED; + + /* update node index to try next worker node */ + AdjustStateForFailure(taskExecution); + } +} + + +/* + * ReassignMapFetchTaskList walks over tasks in the given task list, and resets + * their task execution status. This ensures that all map output fetch tasks are + * retried after the node executing the map task has been failed over. + */ +static void +ReassignMapFetchTaskList(List *mapFetchTaskList) +{ + ListCell *mapFetchTaskCell = NULL; + foreach(mapFetchTaskCell, mapFetchTaskList) + { + Task *mapFetchTask = (Task *) lfirst(mapFetchTaskCell); + TaskExecution *mapFetchTaskExecution = mapFetchTask->taskExecution; + + TaskExecStatus *taskStatusArray = mapFetchTaskExecution->taskStatusArray; + uint32 currentNodeIndex = mapFetchTaskExecution->currentNodeIndex; + + /* + * We reassign to same task tracker knowing that the source task tracker + * (that we failed to fetch map output from) has changed. + */ + taskStatusArray[currentNodeIndex] = EXEC_TASK_UNASSIGNED; + } +} + + +/* + * ShardFetchTaskList walks over the given task list, finds the shard fetch tasks + * in the list, and returns the found tasks in a new list. + */ +static List * +ShardFetchTaskList(List *taskList) +{ + List *shardFetchTaskList = NIL; + ListCell *taskCell = NULL; + + foreach(taskCell, taskList) + { + Task *task = (Task *) lfirst(taskCell); + if (task->taskType == SHARD_FETCH_TASK) + { + shardFetchTaskList = lappend(shardFetchTaskList, task); + } + } + + return shardFetchTaskList; +} + + +/* + * ManageTaskTracker manages tasks assigned to the given task tracker. For this, + * the function coordinates access to the underlying connection. The function + * also: (1) synchronously assigns locally queued tasks to the task tracker, (2) + * issues an asynchronous task status query for one assigned task at a time, and + * (3) retrieves status query results for the previously issued status query. + */ +static void +ManageTaskTracker(TaskTracker *taskTracker) +{ + bool trackerConnectionUp = false; + bool trackerHealthy = false; + + trackerHealthy = TrackerHealthy(taskTracker); + if (!trackerHealthy) + { + return; + } + + trackerConnectionUp = TrackerConnectionUp(taskTracker); + if (!trackerConnectionUp) + { + TrackerReconnectPoll(taskTracker); /* try an async reconnect */ + return; + } + + /* + * (1) We first synchronously assign any pending new tasks. We also make + * sure not to block execution on one task tracker for a long time. + */ + if (!taskTracker->connectionBusy) + { + List *previousTaskList = taskTracker->assignedTaskList; + List *newTaskList = AssignQueuedTasks(taskTracker); + + taskTracker->assignedTaskList = list_concat(previousTaskList, newTaskList); + } + + /* + * (2) We find an assigned task. We then send an asynchronous query to check + * task's status. + */ + if (!taskTracker->connectionBusy) + { + List *assignedTaskList = taskTracker->assignedTaskList; + int32 currentTaskIndex = taskTracker->currentTaskIndex; + int32 nextTaskIndex = -1; + + nextTaskIndex = NextRunningTaskIndex(assignedTaskList, currentTaskIndex); + taskTracker->currentTaskIndex = nextTaskIndex; + + /* if we have a running task's index, check task's status */ + if (nextTaskIndex != -1) + { + int32 connectionId = taskTracker->connectionId; + TrackerTaskState *taskState = NULL; + StringInfo taskStatusQuery = NULL; + bool querySent = false; + + taskState = (TrackerTaskState *) list_nth(assignedTaskList, nextTaskIndex); + Assert(taskState != NULL); + + taskStatusQuery = makeStringInfo(); + appendStringInfo(taskStatusQuery, TASK_STATUS_QUERY, + taskState->jobId, taskState->taskId); + + querySent = MultiClientSendQuery(connectionId, taskStatusQuery->data); + if (querySent) + { + taskTracker->connectionBusy = true; + taskTracker->connectionBusyOnTask = taskState; + } + else + { + taskState->status = TASK_CLIENT_SIDE_STATUS_FAILED; + + taskTracker->connectionBusy = false; + taskTracker->connectionBusyOnTask = NULL; + } + } + } + + /* + * (3) check if results are ready for previously issued task status query + */ + if (taskTracker->connectionBusy) + { + int32 connectionId = taskTracker->connectionId; + ResultStatus resultStatus = CLIENT_INVALID_RESULT_STATUS; + TrackerTaskState *taskState = taskTracker->connectionBusyOnTask; + Assert(taskState != NULL); + + /* if connection is available, update task status accordingly */ + resultStatus = MultiClientResultStatus(connectionId); + if (resultStatus == CLIENT_RESULT_READY) + { + taskState->status = TaskStatusQueryResponse(connectionId); + } + else if (resultStatus == CLIENT_RESULT_UNAVAILABLE) + { + taskState->status = TASK_CLIENT_SIDE_STATUS_FAILED; + } + + /* if connection is available, give it back to the task tracker */ + if (resultStatus != CLIENT_RESULT_BUSY) + { + taskTracker->connectionBusy = false; + taskTracker->connectionBusyOnTask = NULL; + } + } +} + + +/* + * TrackerConnectionUp checks the most recent connection status for the given + * task tracker. The function returns true if the connection is still up. + */ +static bool +TrackerConnectionUp(TaskTracker *taskTracker) +{ + bool connectionUp = false; + + /* if we think we have a connection, check its most recent status */ + if (taskTracker->trackerStatus == TRACKER_CONNECTED) + { + connectionUp = MultiClientConnectionUp(taskTracker->connectionId); + } + + return connectionUp; +} + + +/* + * TrackerReconnectPoll checks if we have an open connection to the given task + * tracker. If not, the function opens an asynchronous connection to the task + * tracker and polls this connection's status on every call. The function also + * sets the task tracker's internal state. + */ +static void +TrackerReconnectPoll(TaskTracker *taskTracker) +{ + TrackerStatus currentStatus = taskTracker->trackerStatus; + if (currentStatus == TRACKER_CONNECTED) + { + bool connectionUp = MultiClientConnectionUp(taskTracker->connectionId); + if (connectionUp) + { + taskTracker->trackerStatus = TRACKER_CONNECTED; + } + else + { + taskTracker->trackerStatus = TRACKER_CONNECTION_FAILED; + + /* we lost the connection underneath us, clean it up */ + MultiClientDisconnect(taskTracker->connectionId); + taskTracker->connectionId = INVALID_CONNECTION_ID; + } + } + else if (currentStatus == TRACKER_CONNECT_START || + currentStatus == TRACKER_CONNECT_POLL) + { + taskTracker->trackerStatus = TrackerConnectPoll(taskTracker); + } + else if (currentStatus == TRACKER_CONNECTION_FAILED) + { + taskTracker->connectionFailureCount++; + taskTracker->connectPollCount = 0; + + taskTracker->trackerStatus = TRACKER_CONNECT_START; + } +} + + +/* + * AssignQueuedTasks walks over the given task tracker's task state hash, finds + * queued tasks in this hash, and synchronously assigns them to the given task + * tracker. The function then returns the list of newly assigned tasks. + */ +static List * +AssignQueuedTasks(TaskTracker *taskTracker) +{ + HTAB *taskStateHash = taskTracker->taskStateHash; + List *assignedTaskList = NIL; + uint32 taskAssignmentCount = 0; + List *tasksToAssignList = NIL; + StringInfo multiAssignQuery = makeStringInfo(); + int32 connectionId = taskTracker->connectionId; + + HASH_SEQ_STATUS status; + TrackerTaskState *taskState = NULL; + hash_seq_init(&status, taskStateHash); + + taskState = (TrackerTaskState *) hash_seq_search(&status); + while (taskState != NULL) + { + if (taskState->status == TASK_CLIENT_SIDE_QUEUED) + { + StringInfo taskAssignmentQuery = taskState->taskAssignmentQuery; + + if(taskAssignmentCount > 0) + { + appendStringInfo(multiAssignQuery, ";"); + } + + appendStringInfo(multiAssignQuery, "%s", taskAssignmentQuery->data); + + tasksToAssignList = lappend(tasksToAssignList, taskState); + taskAssignmentCount++; + if (taskAssignmentCount >= MaxAssignTaskBatchSize) + { + hash_seq_term(&status); + break; + } + } + + taskState = (TrackerTaskState *) hash_seq_search(&status); + } + + if(taskAssignmentCount > 0) + { + void *queryResult = NULL; + int rowCount = 0; + int columnCount = 0; + ListCell *taskCell = NULL; + + bool batchSuccess = MultiClientSendQuery(connectionId, multiAssignQuery->data); + + foreach(taskCell, tasksToAssignList) + { + TrackerTaskState *taskState = (TrackerTaskState *) lfirst(taskCell); + BatchQueryStatus queryStatus = CLIENT_INVALID_BATCH_QUERY; + + if (!batchSuccess) + { + taskState->status = TASK_CLIENT_SIDE_ASSIGN_FAILED; + continue; + } + + queryStatus = MultiClientBatchResult(connectionId, &queryResult, + &rowCount, &columnCount); + if (queryStatus == CLIENT_BATCH_QUERY_CONTINUE) + { + taskState->status = TASK_ASSIGNED; + assignedTaskList = lappend(assignedTaskList, taskState); + } + else + { + taskState->status = TASK_CLIENT_SIDE_ASSIGN_FAILED; + batchSuccess = false; + } + + MultiClientClearResult(queryResult); + } + + /* call MultiClientBatchResult one more time to finish reading results */ + MultiClientBatchResult(connectionId, &queryResult, &rowCount, &columnCount); + Assert(queryResult == NULL); + + list_free(tasksToAssignList); + } + + return assignedTaskList; +} + + +/* + * NextRunningTaskIndex walks over the tasks in the given list, and looks for a + * task that was still running as of the last time we checked. If such a task + * exists (before wrapping around the assigned task list), the function returns + * that task's index in the list. Else, the function returns -1 to signal either + * no such task exists or that the function may be called again to search from + * the beginning of the task list. + */ +static int32 +NextRunningTaskIndex(List *assignedTaskList, int32 currentTaskIndex) +{ + int32 nextTaskIndex = -1; + int32 lastTaskIndex = -1; + int32 assignedTaskIndex = 0; + ListCell *assignedTaskCell = NULL; + + int32 assignedTaskCount = list_length(assignedTaskList); + if (assignedTaskCount == 0) + { + return -1; + } + + lastTaskIndex = (assignedTaskCount - 1); + if (currentTaskIndex >= lastTaskIndex) + { + currentTaskIndex = -1; + } + + assignedTaskCell = NULL; + foreach(assignedTaskCell, assignedTaskList) + { + TrackerTaskState *assignedTask = (TrackerTaskState *) lfirst(assignedTaskCell); + TaskStatus taskStatus = assignedTask->status; + + /* task tracker retries tasks that only failed once (task_failed) */ + bool taskRunning = false; + if (taskStatus == TASK_ASSIGNED || taskStatus == TASK_SCHEDULED || + taskStatus == TASK_RUNNING || taskStatus == TASK_FAILED) + { + taskRunning = true; + } + + if (taskRunning && (assignedTaskIndex > currentTaskIndex)) + { + nextTaskIndex = assignedTaskIndex; + break; + } + + assignedTaskIndex++; + } + + /* + * We might have wrapped around the assigned task list and found nothing. If + * that's the case, we'll start looking from the beginning next time. + */ + return nextTaskIndex; +} + + +/* + * TaskStatusQueryResponse assumes that a task status query has been previously + * sent on the given connection, and reads the response for this status query. + */ +static TaskStatus +TaskStatusQueryResponse(int32 connectionId) +{ + TaskStatus taskStatus = TASK_STATUS_INVALID_FIRST; + void *queryResult = NULL; + int rowCount = 0; + int columnCount = 0; + + bool resultReceived = MultiClientQueryResult(connectionId, &queryResult, + &rowCount, &columnCount); + if (resultReceived) + { + char *valueString = MultiClientGetValue(queryResult, 0, 0); + if (valueString == NULL || (*valueString) == '\0') + { + taskStatus = TASK_PERMANENTLY_FAILED; + } + else + { + char *valueStringEnd = NULL; + errno = 0; + + taskStatus = strtoul(valueString, &valueStringEnd, 0); + if (errno != 0 || (*valueStringEnd) != '\0') + { + /* we couldn't parse received integer */ + taskStatus = TASK_PERMANENTLY_FAILED; + } + + Assert(taskStatus > TASK_STATUS_INVALID_FIRST); + Assert(taskStatus < TASK_STATUS_LAST); + } + } + else + { + taskStatus = TASK_CLIENT_SIDE_STATUS_FAILED; + } + + MultiClientClearResult(queryResult); + + return taskStatus; +} + + +/* + * ManageTransmitTracker manages access to the connection we opened to the worker + * node. If the connection is idle, and we have file transmit requests pending, + * the function picks a pending file transmit request, and starts the Copy Out + * protocol to copy the file's contents. + */ +static void +ManageTransmitTracker(TaskTracker *transmitTracker) +{ + TrackerTaskState *transmitState = NULL; + bool trackerHealthy = false; + bool trackerConnectionUp = false; + + trackerHealthy = TrackerHealthy(transmitTracker); + if (!trackerHealthy) + { + return; + } + + trackerConnectionUp = TrackerConnectionUp(transmitTracker); + if (!trackerConnectionUp) + { + TrackerReconnectPoll(transmitTracker); /* try an async reconnect */ + return; + } + + /* connection belongs to another file transmit */ + if (transmitTracker->connectionBusy) + { + return; + } + + transmitState = NextQueuedFileTransmit(transmitTracker->taskStateHash); + if (transmitState != NULL) + { + bool fileTransmitStarted = false; + int32 connectionId = transmitTracker->connectionId; + StringInfo jobDirectoryName = JobDirectoryName(transmitState->jobId); + StringInfo taskFilename = TaskFilename(jobDirectoryName, transmitState->taskId); + + StringInfo fileTransmitQuery = makeStringInfo(); + appendStringInfo(fileTransmitQuery, TRANSMIT_REGULAR_COMMAND, taskFilename->data); + + fileTransmitStarted = MultiClientSendQuery(connectionId, fileTransmitQuery->data); + if (fileTransmitStarted) + { + transmitState->status = TASK_ASSIGNED; + + transmitTracker->connectionBusy = true; + transmitTracker->connectionBusyOnTask = transmitState; + } + else + { + transmitState->status = TASK_CLIENT_SIDE_TRANSMIT_FAILED; + + transmitTracker->connectionBusy = false; + transmitTracker->connectionBusyOnTask = NULL; + } + } +} + + +/* + * NextQueuedFileTransmit walks over all tasks in the given hash, and looks for + * a file transmit task that has been queued, but not served yet. + */ +static TrackerTaskState * +NextQueuedFileTransmit(HTAB *taskStateHash) +{ + HASH_SEQ_STATUS status; + TrackerTaskState *taskState = NULL; + hash_seq_init(&status, taskStateHash); + + taskState = (TrackerTaskState *) hash_seq_search(&status); + while (taskState != NULL) + { + if (taskState->status == TASK_FILE_TRANSMIT_QUEUED) + { + hash_seq_term(&status); + break; + } + + taskState = (TrackerTaskState *) hash_seq_search(&status); + } + + return taskState; +} + + +/* + * JobIdList walks over all jobs in the given job tree and retrieves each job's + * identifier. The function then inserts these job identifiers in a new list and + * returns this list. + */ +static List * +JobIdList(Job *job) +{ + List *jobIdList = NIL; + List *jobQueue = NIL; + + /* + * We walk over the job tree using breadth-first search. For this, we first + * queue the root node, and then start traversing our search space. + */ + jobQueue = list_make1(job); + while (jobQueue != NIL) + { + uint64 *jobIdPointer = (uint64 *) palloc0(sizeof(uint64)); + List *jobChildrenList = NIL; + + Job *job = (Job *) linitial(jobQueue); + jobQueue = list_delete_first(jobQueue); + + (*jobIdPointer) = job->jobId; + jobIdList = lappend(jobIdList, jobIdPointer); + + /* prevent dependedJobList being modified on list_concat() call */ + jobChildrenList = list_copy(job->dependedJobList); + if (jobChildrenList != NIL) + { + jobQueue = list_concat(jobQueue, jobChildrenList); + } + } + + return jobIdList; +} + + +/* + * TrackerCleanupResources cleans up remote and local resources associated with + * the query. To clean up remote resources, the function cancels ongoing transmit + * tasks. It also waits for ongoing requests to the task trackers to complete + * before assigning "job clean up" tasks to them. To reclaim local resources, + * the function closes open file descriptors and disconnects from task trackers. + */ +static void +TrackerCleanupResources(HTAB *taskTrackerHash, HTAB *transmitTrackerHash, + List *jobIdList, List *taskList) +{ + ListCell *taskCell = NULL; + ListCell *jobIdCell = NULL; + + /* + * We are done with query execution. We now wait for open requests to the task + * trackers to complete and cancel any open requests to the transmit trackers. + */ + TrackerHashWaitActiveRequest(taskTrackerHash); + TrackerHashCancelActiveRequest(transmitTrackerHash); + + /* only close open files; open connections are owned by trackers */ + foreach(taskCell, taskList) + { + Task *task = (Task *) lfirst(taskCell); + TaskExecution *taskExecution = task->taskExecution; + + CleanupTaskExecution(taskExecution); + } + + /* + * For each executed job, we create a special task to clean up its resources + * on worker nodes, and send this clean-up task to all task trackers. + */ + foreach(jobIdCell, jobIdList) + { + uint64 *jobIdPointer = (uint64 *) lfirst(jobIdCell); + + Task *jobCleanupTask = JobCleanupTask(*jobIdPointer); + TrackerHashCleanupJob(taskTrackerHash, jobCleanupTask); + } + + TrackerHashDisconnect(taskTrackerHash); + TrackerHashDisconnect(transmitTrackerHash); +} + + +/* + * TrackerHashWaitActiveRequest walks over task trackers in the given hash, and + * checks if they have an ongoing request. If they do, the function waits for + * the request to complete. If the request completes successfully, the function + * frees the connection for future tasks. + */ +static void +TrackerHashWaitActiveRequest(HTAB *taskTrackerHash) +{ + TaskTracker *taskTracker = NULL; + HASH_SEQ_STATUS status; + hash_seq_init(&status, taskTrackerHash); + + taskTracker = (TaskTracker *) hash_seq_search(&status); + while (taskTracker != NULL) + { + bool trackerConnectionUp = TrackerConnectionUp(taskTracker); + + /* if we have an ongoing request, block until we have a response */ + if (trackerConnectionUp && taskTracker->connectionBusy) + { + QueryStatus queryStatus = MultiClientQueryStatus(taskTracker->connectionId); + if (queryStatus == CLIENT_QUERY_DONE) + { + taskTracker->connectionBusy = false; + taskTracker->connectionBusyOnTask = NULL; + } + } + + taskTracker = (TaskTracker *) hash_seq_search(&status); + } +} + + +/* + * TrackerHashCancelActiveRequest walks over task trackers in the given hash, + * and checks if they have an ongoing request. If they do, the function sends a + * cancel message on that connection. + */ +static void +TrackerHashCancelActiveRequest(HTAB *taskTrackerHash) +{ + TaskTracker *taskTracker = NULL; + HASH_SEQ_STATUS status; + hash_seq_init(&status, taskTrackerHash); + + taskTracker = (TaskTracker *) hash_seq_search(&status); + while (taskTracker != NULL) + { + bool trackerConnectionUp = TrackerConnectionUp(taskTracker); + + /* if we have an ongoing request, send cancel message */ + if (trackerConnectionUp && taskTracker->connectionBusy) + { + MultiClientCancel(taskTracker->connectionId); + } + + taskTracker = (TaskTracker *) hash_seq_search(&status); + } +} + + +/* + * JobCleanupTask creates a special task to clean up all resources associated + * with a given job on the worker node. The function then returns this task. + */ +static Task * +JobCleanupTask(uint64 jobId) +{ + Task *jobCleanupTask = NULL; + StringInfo jobCleanupQuery = NULL; + + jobCleanupQuery = makeStringInfo(); + appendStringInfo(jobCleanupQuery, JOB_CLEANUP_QUERY, jobId); + + jobCleanupTask = CitusMakeNode(Task); + jobCleanupTask->jobId = jobId; + jobCleanupTask->taskId = JOB_CLEANUP_TASK_ID; + jobCleanupTask->queryString = jobCleanupQuery->data; + + return jobCleanupTask; +} + + +/* + * TrackerHashCleanupJob walks over task trackers in the given hash, and assigns + * a job cleanup task to the tracker if the tracker's connection is available. + * The function then walks over task trackers to which it sent a cleanup task, + * checks the request's status, and emits an appropriate status message. + */ +static void +TrackerHashCleanupJob(HTAB *taskTrackerHash, Task *jobCleanupTask) +{ + uint64 jobId = jobCleanupTask->jobId; + List *taskTrackerList = NIL; + ListCell *taskTrackerCell = NULL; + long sleepInterval = 0; + const int minimumSleepInterval = 150; + + TaskTracker *taskTracker = NULL; + HASH_SEQ_STATUS status; + hash_seq_init(&status, taskTrackerHash); + + /* walk over task trackers and try to issue job clean up requests */ + taskTracker = (TaskTracker *) hash_seq_search(&status); + while (taskTracker != NULL) + { + bool trackerConnectionUp = TrackerConnectionUp(taskTracker); + if (trackerConnectionUp) + { + bool jobCleanupQuerySent = false; + + /* if we have a clear connection, send cleanup job */ + if (!taskTracker->connectionBusy) + { + StringInfo jobCleanupQuery = NULL; + + /* assign through task tracker to manage resource utilization */ + jobCleanupQuery = TaskAssignmentQuery(jobCleanupTask, + jobCleanupTask->queryString); + + jobCleanupQuerySent = MultiClientSendQuery(taskTracker->connectionId, + jobCleanupQuery->data); + } + + /* + * If cleanup query was sent, mark that the connection is busy and + * hold onto the task tracker to check status. + */ + if (jobCleanupQuerySent) + { + taskTracker->connectionBusy = true; + taskTrackerList = lappend(taskTrackerList, taskTracker); + } + else + { + const char *nodeName = taskTracker->workerName; + uint32 nodePort = taskTracker->workerPort; + + ereport(WARNING, (errmsg("could not assign cleanup query for job " + UINT64_FORMAT " to node \"%s:%u\"", + jobId, nodeName, nodePort))); + } + } + + taskTracker = (TaskTracker *) hash_seq_search(&status); + } + + /* give task trackers time to finish their clean up jobs */ + sleepInterval = Max(minimumSleepInterval, RemoteTaskCheckInterval * 2) * 1000L; + pg_usleep(sleepInterval); + + /* walk over task trackers to which we sent clean up requests */ + taskTrackerCell = NULL; + foreach(taskTrackerCell, taskTrackerList) + { + TaskTracker *taskTracker = (TaskTracker *) lfirst(taskTrackerCell); + int32 connectionId = taskTracker->connectionId; + const char *nodeName = taskTracker->workerName; + uint32 nodePort = taskTracker->workerPort; + + ResultStatus resultStatus = MultiClientResultStatus(connectionId); + if (resultStatus == CLIENT_RESULT_READY) + { + QueryStatus queryStatus = MultiClientQueryStatus(connectionId); + if (queryStatus == CLIENT_QUERY_DONE) + { + ereport(DEBUG4, (errmsg("completed cleanup query for job " UINT64_FORMAT + " on node \"%s:%u\"", jobId, nodeName, nodePort))); + + /* clear connection for future cleanup queries */ + taskTracker->connectionBusy = false; + } + else + { + ereport(WARNING, (errmsg("could not receive response for cleanup query " + "for job " UINT64_FORMAT " on node \"%s:%u\"", + jobId, nodeName, nodePort))); + } + } + else + { + ereport(WARNING, (errmsg("could not receive response for cleanup query " + "for job " UINT64_FORMAT " on node \"%s:%u\"", + jobId, nodeName, nodePort))); + } + } +} + + +/* + * TrackerHashDisconnect walks over task trackers in the given hash, and closes + * open connections to them. + */ +static void +TrackerHashDisconnect(HTAB *taskTrackerHash) +{ + TaskTracker *taskTracker = NULL; + HASH_SEQ_STATUS status; + hash_seq_init(&status, taskTrackerHash); + + taskTracker = (TaskTracker *) hash_seq_search(&status); + while (taskTracker != NULL) + { + if (taskTracker->connectionId != INVALID_CONNECTION_ID) + { + MultiClientDisconnect(taskTracker->connectionId); + taskTracker->connectionId = INVALID_CONNECTION_ID; + } + + taskTracker = (TaskTracker *) hash_seq_search(&status); + } +} diff --git a/src/backend/distributed/executor/multi_utility.c b/src/backend/distributed/executor/multi_utility.c new file mode 100644 index 000000000..ccd05c021 --- /dev/null +++ b/src/backend/distributed/executor/multi_utility.c @@ -0,0 +1,1057 @@ +/*------------------------------------------------------------------------- + * multi_utility.c + * CitusDB utility hook and related functionality. + * + * Copyright (c) 2012-2015, Citus Data, Inc. + *------------------------------------------------------------------------- + */ + +#include "postgres.h" +#include "miscadmin.h" + +#include "access/htup_details.h" +#include "catalog/catalog.h" +#include "catalog/index.h" +#include "catalog/namespace.h" +#include "commands/defrem.h" +#include "commands/tablecmds.h" +#include "distributed/master_protocol.h" +#include "distributed/metadata_cache.h" +#include "distributed/multi_utility.h" +#include "distributed/multi_join_order.h" +#include "distributed/transmit.h" +#include "distributed/worker_manager.h" +#include "distributed/worker_protocol.h" +#include "parser/parser.h" +#include "parser/parse_utilcmd.h" +#include "storage/lmgr.h" +#include "tcop/pquery.h" +#include "utils/builtins.h" +#include "utils/inval.h" +#include "utils/lsyscache.h" +#include "utils/rel.h" +#include "utils/syscache.h" + + +/* + * This struct defines the state for the callback for drop statements. + * It is copied as it is from commands/tablecmds.c in Postgres source. + */ +struct DropRelationCallbackState +{ + char relkind; + Oid heapOid; + bool concurrent; +}; + + +/* Local functions forward declarations for Transmit statement */ +static bool IsTransmitStmt(Node *parsetree); +static void VerifyTransmitStmt(CopyStmt *copyStatement); + +/* Local functions forward declarations for processing distributed table commands */ +static Node * ProcessCopyStmt(CopyStmt *copyStatement); +static Node * ProcessIndexStmt(IndexStmt *createIndexStatement, + const char *createIndexCommand); +static Node * ProcessDropIndexStmt(DropStmt *dropIndexStatement, + const char *dropIndexCommand); +static Node * ProcessAlterTableStmt(AlterTableStmt *alterTableStatement, + const char *alterTableCommand); + +/* Local functions forward declarations for unsupported command checks */ +static void ErrorIfUnsupportedIndexStmt(IndexStmt *createIndexStatement); +static void ErrorIfUnsupportedDropIndexStmt(DropStmt *dropIndexStatement); +static void ErrorIfUnsupportedAlterTableStmt(AlterTableStmt *alterTableStatement); +static void ErrorIfDistributedRenameStmt(RenameStmt *renameStatement); + +/* Local functions forward declarations for helper functions */ +static void WarnIfDropCitusExtension(DropStmt *dropStatement); +static bool IsAlterTableRenameStmt(RenameStmt *renameStatement); +static void ExecuteDistributedDDLCommand(Oid relationId, const char *ddlCommandString); +static bool ExecuteCommandOnWorkerShards(Oid relationId, const char *commandString, + List **failedPlacementList); +static bool AllFinalizedPlacementsAccessible(Oid relationId); +static void RangeVarCallbackForDropIndex(const RangeVar *rel, Oid relOid, Oid oldRelOid, + void *arg); + + +/* + * Utility for handling citusdb specific concerns around utility statements. + * + * There's two basic types of concerns here: + * 1) Intercept utility statements that run after distributed query + * execution. At this stage, the Create Table command for the master node's + * temporary table has been executed, and this table's relationId is + * visible to us. We can therefore update the relationId in master node's + * select query. + * 2) Handle utility statements on distributed tables that the core code can't + * handle. + */ +void +multi_ProcessUtility(Node *parsetree, + const char *queryString, + ProcessUtilityContext context, + ParamListInfo params, + DestReceiver *dest, + char *completionTag) +{ + /* + * TRANSMIT used to be separate command, but to avoid patching the grammar + * it's no overlaid onto COPY, but with FORMAT = 'transmit' instead of the + * normal FORMAT options. + */ + if (IsTransmitStmt(parsetree)) + { + CopyStmt *copyStatement = (CopyStmt *) parsetree; + + VerifyTransmitStmt(copyStatement); + + /* ->relation->relname is the target file in our overloaded COPY */ + if (copyStatement->is_from) + { + ReceiveRegularFile(copyStatement->relation->relname); + } + else + { + SendRegularFile(copyStatement->relation->relname); + } + + /* Don't execute the faux copy statement */ + return; + } + + if (IsA(parsetree, CopyStmt)) + { + parsetree = ProcessCopyStmt((CopyStmt *) parsetree); + } + + if (IsA(parsetree, IndexStmt)) + { + parsetree = ProcessIndexStmt((IndexStmt *) parsetree, queryString); + } + + if (IsA(parsetree, DropStmt)) + { + DropStmt *dropStatement = (DropStmt *) parsetree; + if (dropStatement->removeType == OBJECT_INDEX) + { + parsetree = ProcessDropIndexStmt(dropStatement, queryString); + } + else if (dropStatement->removeType == OBJECT_EXTENSION) + { + WarnIfDropCitusExtension(dropStatement); + } + } + + if (IsA(parsetree, AlterTableStmt)) + { + AlterTableStmt *alterTableStmt = (AlterTableStmt *) parsetree; + if (alterTableStmt->relkind == OBJECT_TABLE) + { + parsetree = ProcessAlterTableStmt(alterTableStmt, queryString); + } + } + + /* + * ALTER TABLE ... RENAME statements have their node type as RenameStmt and + * not AlterTableStmt. So, we intercept RenameStmt to tackle these commands. + */ + if (IsA(parsetree, RenameStmt)) + { + RenameStmt *renameStmt = (RenameStmt *) parsetree; + if (IsAlterTableRenameStmt(renameStmt)) + { + ErrorIfDistributedRenameStmt(renameStmt); + } + } + + /* + * Inform the user about potential caveats. + * + * To prevent failures in aborted transactions, CitusDBHasBeenLoaded() needs + * to be the second condition. See RelationIdGetRelation() which is called + * by CitusDBHasBeenLoaded(). + */ + if (IsA(parsetree, CreatedbStmt) && CitusDBHasBeenLoaded()) + { + ereport(NOTICE, (errmsg("CitusDB partially supports CREATE DATABASE for " + "distributed databases"), + errdetail("CitusDB does not propagate CREATE DATABASE " + "command to workers"), + errhint("You can manually create a database and its " + "extensions on workers."))); + } + else if (IsA(parsetree, CreateSchemaStmt) && CitusDBHasBeenLoaded()) + { + ereport(NOTICE, (errmsg("CitusDB partially supports CREATE SCHEMA " + "for distributed databases"), + errdetail("schema usage in joins and in some UDFs " + "provided by CitusDB are not supported yet"))); + } + else if (IsA(parsetree, CreateRoleStmt) && CitusDBHasBeenLoaded()) + { + ereport(NOTICE, (errmsg("CitusDB does not support CREATE ROLE/USER " + "for distributed databases"), + errdetail("Multiple roles are currently supported " + "only for local tables"))); + } + + /* now drop into standard process utility */ + standard_ProcessUtility(parsetree, queryString, context, + params, dest, completionTag); +} + + +/* + * WarnIfDropCitusExtension prints a WARNING if dropStatement includes dropping + * citusdb extension. + */ +static void +WarnIfDropCitusExtension(DropStmt *dropStatement) +{ + ListCell *dropStatementObject = NULL; + + Assert(dropStatement->removeType == OBJECT_EXTENSION); + + foreach(dropStatementObject, dropStatement->objects) + { + List *objectNameList = lfirst(dropStatementObject); + char *objectName = NameListToString(objectNameList); + + /* we're only concerned with the citusdb extension */ + if (strncmp("citusdb", objectName, NAMEDATALEN) == 0) + { + /* + * Warn the user about the possibility of invalid cache. Also, see + * function comment of CachedRelationLookup(). + */ + ereport(WARNING, (errmsg("could not clean the metadata cache on " + "DROP EXTENSION command"), + errhint("Reconnect to the server again."))); + } + } +} + + +/* Is the passed in statement a transmit statement? */ +static bool +IsTransmitStmt(Node *parsetree) +{ + if (IsA(parsetree, CopyStmt)) + { + CopyStmt *copyStatement = (CopyStmt *) parsetree; + ListCell *optionCell = NULL; + + /* Extract options from the statement node tree */ + foreach(optionCell, copyStatement->options) + { + DefElem *defel = (DefElem *) lfirst(optionCell); + + if (strncmp(defel->defname, "format", NAMEDATALEN) == 0 && + strncmp(defGetString(defel), "transmit", NAMEDATALEN) == 0) + { + return true; + } + } + } + + return false; +} + + +/* + * VerifyTransmitStmt checks that the passed in command is a valid transmit + * statement. Raise ERROR if not. + * + * Note that only 'toplevel' options in the CopyStmt struct are checked, and + * that verification of the target files existance is not done here. + */ +static void +VerifyTransmitStmt(CopyStmt *copyStatement) +{ + /* do some minimal option verification */ + if (copyStatement->relation == NULL || + copyStatement->relation->relname == NULL) + { + ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("FORMAT 'transmit' requires a target file"))); + } + + if (copyStatement->filename != NULL) + { + ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("FORMAT 'transmit' only accepts STDIN/STDOUT" + " as input/output"))); + } + + if (copyStatement->query != NULL || + copyStatement->attlist != NULL || + copyStatement->is_program) + { + ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("FORMAT 'transmit' does not accept query, attribute list" + " or PROGRAM parameters "))); + } +} + + +/* + * ProcessCopyStmt handles CitusDB specific concerns for COPY like supporting + * COPYing from distributed tables and preventing unsupported actions. + */ +static Node * +ProcessCopyStmt(CopyStmt *copyStatement) +{ + /* + * We first check if we have a "COPY (query) TO filename". If we do, copy doesn't + * accept relative file paths. However, SQL tasks that get assigned to worker nodes + * have relative paths. We therefore convert relative paths to absolute ones here. + */ + if (copyStatement->relation == NULL && + !copyStatement->is_from && + !copyStatement->is_program && + copyStatement->filename != NULL) + { + const char *filename = copyStatement->filename; + + if (!is_absolute_path(filename) && JobDirectoryElement(filename)) + { + copyStatement->filename = make_absolute_path(filename); + } + } + + /* + * We check whether a distributed relation is affected. For that, we need to open the + * relation. To prevent race conditions with later lookups, lock the table, and modify + * the rangevar to include the schema. + */ + if (copyStatement->relation != NULL) + { + Relation copiedRelation = NULL; + bool isDistributedRelation = false; + + copiedRelation = heap_openrv(copyStatement->relation, AccessShareLock); + + isDistributedRelation = IsDistributedTable(RelationGetRelid(copiedRelation)); + + /* ensure future lookups hit the same relation */ + copyStatement->relation->schemaname = get_namespace_name( + RelationGetNamespace(copiedRelation)); + + heap_close(copiedRelation, NoLock); + + if (isDistributedRelation) + { + if (copyStatement->is_from) + { + ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("cannot execute COPY FROM on a distributed table " + "on master node"))); + } + else if (!copyStatement->is_from) + { + /* + * The copy code only handles SELECTs in COPY ... TO on master tables, + * as that can be done non-invasively. To handle COPY master_rel TO + * the copy statement is replaced by a generated select statement. + */ + ColumnRef *allColumns = makeNode(ColumnRef); + SelectStmt *selectStmt = makeNode(SelectStmt); + ResTarget *selectTarget = makeNode(ResTarget); + + allColumns->fields = list_make1(makeNode(A_Star)); + allColumns->location = -1; + + selectTarget->name = NULL; + selectTarget->indirection = NIL; + selectTarget->val = (Node *) allColumns; + selectTarget->location = -1; + + selectStmt->targetList = list_make1(selectTarget); + selectStmt->fromClause = list_make1(copyObject(copyStatement->relation)); + + /* replace original statement */ + copyStatement = copyObject(copyStatement); + copyStatement->relation = NULL; + copyStatement->query = (Node *) selectStmt; + } + } + } + + return (Node *) copyStatement; +} + + +/* + * ProcessIndexStmt processes create index statements for distributed tables. + * The function first checks if the statement belongs to a distributed table + * or not. If it does, then it executes distributed logic for the command. + * + * The function returns the IndexStmt node for the command to be executed on the + * master node table. + */ +static Node * +ProcessIndexStmt(IndexStmt *createIndexStatement, const char *createIndexCommand) +{ + /* + * We first check whether a distributed relation is affected. For that, we need to + * open the relation. To prevent race conditions with later lookups, lock the table, + * and modify the rangevar to include the schema. + */ + if (createIndexStatement->relation != NULL) + { + Relation relation = NULL; + Oid relationId = InvalidOid; + bool isDistributedRelation = false; + char *namespaceName = NULL; + LOCKMODE lockmode = ShareLock; + + /* + * We don't support concurrently creating indexes for distributed + * tables, but till this point, we don't know if it is a regular or a + * distributed table. + */ + if (createIndexStatement->concurrent) + { + lockmode = ShareUpdateExclusiveLock; + } + + relation = heap_openrv(createIndexStatement->relation, lockmode); + relationId = RelationGetRelid(relation); + + isDistributedRelation = IsDistributedTable(relationId); + + /* ensure future lookups hit the same relation */ + namespaceName = get_namespace_name(RelationGetNamespace(relation)); + createIndexStatement->relation->schemaname = namespaceName; + + heap_close(relation, NoLock); + + if (isDistributedRelation) + { + ErrorIfUnsupportedIndexStmt(createIndexStatement); + + /* if it is supported, go ahead and execute the command */ + ExecuteDistributedDDLCommand(relationId, createIndexCommand); + } + } + + return (Node *) createIndexStatement; +} + + +/* + * ProcessDropIndexStmt processes drop index statements for distributed tables. + * The function first checks if the statement belongs to a distributed table + * or not. If it does, then it executes distributed logic for the command. + * + * The function returns the DropStmt node for the command to be executed on the + * master node table. + */ +static Node * +ProcessDropIndexStmt(DropStmt *dropIndexStatement, const char *dropIndexCommand) +{ + ListCell *dropObjectCell = NULL; + Oid distributedIndexId = InvalidOid; + Oid distributedRelationId = InvalidOid; + + Assert(dropIndexStatement->removeType == OBJECT_INDEX); + + /* check if any of the indexes being dropped belong to a distributed table */ + foreach(dropObjectCell, dropIndexStatement->objects) + { + Oid indexId = InvalidOid; + Oid relationId = InvalidOid; + bool isDistributedRelation = false; + struct DropRelationCallbackState state; + bool missingOK = true; + bool noWait = false; + LOCKMODE lockmode = AccessExclusiveLock; + + List *objectNameList = (List *) lfirst(dropObjectCell); + RangeVar *rangeVar = makeRangeVarFromNameList(objectNameList); + + /* + * We don't support concurrently dropping indexes for distributed + * tables, but till this point, we don't know if it is a regular or a + * distributed table. + */ + if (dropIndexStatement->concurrent) + { + lockmode = ShareUpdateExclusiveLock; + } + + /* + * The next few statements are based on RemoveRelations() in + * commands/tablecmds.c in Postgres source. + */ + AcceptInvalidationMessages(); + + state.relkind = RELKIND_INDEX; + state.heapOid = InvalidOid; + state.concurrent = dropIndexStatement->concurrent; + indexId = RangeVarGetRelidExtended(rangeVar, lockmode, missingOK, + noWait, RangeVarCallbackForDropIndex, + (void *) &state); + + /* + * If the index does not exist, we don't do anything here, and allow + * postgres to throw appropriate error or notice message later. + */ + if (!OidIsValid(indexId)) + { + continue; + } + + relationId = IndexGetRelation(indexId, false); + isDistributedRelation = IsDistributedTable(relationId); + if (isDistributedRelation) + { + distributedIndexId = indexId; + distributedRelationId = relationId; + break; + } + } + + if (OidIsValid(distributedIndexId)) + { + ErrorIfUnsupportedDropIndexStmt(dropIndexStatement); + + /* if it is supported, go ahead and execute the command */ + ExecuteDistributedDDLCommand(distributedRelationId, dropIndexCommand); + } + + return (Node *) dropIndexStatement; +} + + +/* + * ProcessAlterTableStmt processes alter table statements for distributed tables. + * The function first checks if the statement belongs to a distributed table + * or not. If it does, then it executes distributed logic for the command. + * + * The function returns the AlterTableStmt node for the command to be executed on the + * master node table. + */ +static Node * +ProcessAlterTableStmt(AlterTableStmt *alterTableStatement, const char *alterTableCommand) +{ + /* first check whether a distributed relation is affected */ + if (alterTableStatement->relation != NULL) + { + LOCKMODE lockmode = AlterTableGetLockLevel(alterTableStatement->cmds); + Oid relationId = AlterTableLookupRelation(alterTableStatement, lockmode); + if (OidIsValid(relationId)) + { + bool isDistributedRelation = IsDistributedTable(relationId); + if (isDistributedRelation) + { + ErrorIfUnsupportedAlterTableStmt(alterTableStatement); + + /* if it is supported, go ahead and execute the command */ + ExecuteDistributedDDLCommand(relationId, alterTableCommand); + } + } + } + + return (Node *) alterTableStatement; +} + + +/* + * ErrorIfUnsupportedIndexStmt checks if the corresponding index statement is + * supported for distributed tables and errors out if it is not. + */ +static void +ErrorIfUnsupportedIndexStmt(IndexStmt *createIndexStatement) +{ + if (createIndexStatement->tableSpace != NULL) + { + ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("specifying tablespaces with CREATE INDEX statements is " + "currently unsupported"))); + } + + if (createIndexStatement->unique) + { + ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("creating unique indexes on distributed tables is " + "currently unsupported"))); + } + + if (createIndexStatement->concurrent) + { + ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("creating indexes concurrently on distributed tables is " + "currently unsupported"))); + } +} + + +/* + * ErrorIfUnsupportedDropIndexStmt checks if the corresponding drop index statement is + * supported for distributed tables and errors out if it is not. + */ +static void +ErrorIfUnsupportedDropIndexStmt(DropStmt *dropIndexStatement) +{ + Assert(dropIndexStatement->removeType == OBJECT_INDEX); + + if (list_length(dropIndexStatement->objects) > 1) + { + ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("cannot drop multiple distributed objects in a " + "single command"), + errhint("Try dropping each object in a separate DROP " + "command."))); + } + + if (dropIndexStatement->concurrent) + { + ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("dropping indexes concurrently on distributed tables is " + "currently unsupported"))); + } +} + + +/* + * ErrorIfUnsupportedAlterTableStmt checks if the corresponding alter table statement + * is supported for distributed tables and errors out if it is not. Currently, + * only the following commands are supported. + * + * ALTER TABLE ADD|DROP COLUMN + * ALTER TABLE ALTER COLUMN SET DATA TYPE + * ALTER TABLE SET|DROP NOT NULL + * ALTER TABLE SET|DROP DEFAULT + */ +static void +ErrorIfUnsupportedAlterTableStmt(AlterTableStmt *alterTableStatement) +{ + List *commandList = alterTableStatement->cmds; + ListCell *commandCell = NULL; + + /* error out if any of the subcommands are unsupported */ + foreach(commandCell, commandList) + { + AlterTableCmd *command = (AlterTableCmd *) lfirst(commandCell); + AlterTableType alterTableType = command->subtype; + + switch (alterTableType) + { + case AT_AddColumn: + { + break; + } + + case AT_DropColumn: + case AT_ColumnDefault: + case AT_AlterColumnType: + case AT_SetNotNull: + case AT_DropNotNull: + { + /* error out if the alter table command is on the partition column */ + + Var *partitionColumn = NULL; + HeapTuple tuple = NULL; + char *alterColumnName = command->name; + + LOCKMODE lockmode = AlterTableGetLockLevel(alterTableStatement->cmds); + Oid relationId = AlterTableLookupRelation(alterTableStatement, lockmode); + if (!OidIsValid(relationId)) + { + continue; + } + + partitionColumn = PartitionKey(relationId); + + tuple = SearchSysCacheAttName(relationId, alterColumnName); + if (HeapTupleIsValid(tuple)) + { + Form_pg_attribute targetAttr = (Form_pg_attribute) GETSTRUCT(tuple); + if (targetAttr->attnum == partitionColumn->varattno) + { + ereport(ERROR, (errmsg("cannot execute ALTER TABLE command " + "involving partition column"))); + } + + ReleaseSysCache(tuple); + } + + break; + } + + default: + { + ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("alter table command is currently supported"), + errdetail("Only ADD|DROP COLUMN, SET|DROP NOT NULL," + " SET|DROP DEFAULT and TYPE subcommands are" + " supported."))); + } + } + } +} + + +/* + * ErrorIfDistributedRenameStmt errors out if the corresponding rename statement + * operates on a distributed table or its objects. + * + * Note: This function handles only those rename statements which operate on tables. + */ +static void +ErrorIfDistributedRenameStmt(RenameStmt *renameStatement) +{ + Oid relationId = InvalidOid; + bool isDistributedRelation = false; + + Assert(IsAlterTableRenameStmt(renameStatement)); + + /* + * The lock levels here should be same as the ones taken in + * RenameRelation(), renameatt() and RenameConstraint(). However, since all + * three statements have identical lock levels, we just use a single statement. + */ + relationId = RangeVarGetRelid(renameStatement->relation, AccessExclusiveLock, + renameStatement->missing_ok); + + /* + * If the table does not exist, we don't do anything here, and allow postgres to + * throw the appropriate error or notice message later. + */ + if (!OidIsValid(relationId)) + { + return; + } + + isDistributedRelation = IsDistributedTable(relationId); + if (isDistributedRelation) + { + ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("renaming distributed tables or their objects is " + "currently unsupported"))); + } +} + + +/* + * IsAlterTableRenameStmt returns true if the passed in RenameStmt operates on a + * distributed table or its objects. This includes: + * ALTER TABLE RENAME + * ALTER TABLE RENAME COLUMN + * ALTER TABLE RENAME CONSTRAINT + */ +static bool +IsAlterTableRenameStmt(RenameStmt *renameStmt) +{ + bool isAlterTableRenameStmt = false; + + if (renameStmt->renameType == OBJECT_TABLE) + { + isAlterTableRenameStmt = true; + } + else if (renameStmt->renameType == OBJECT_COLUMN && + renameStmt->relationType == OBJECT_TABLE) + { + isAlterTableRenameStmt = true; + } + +#if (PG_VERSION_NUM >=90500) + else if (renameStmt->renameType == OBJECT_TABCONSTRAINT) + { + isAlterTableRenameStmt = true; + } +#else + else if (renameStmt->renameType == OBJECT_CONSTRAINT && + renameStmt->relationType == OBJECT_TABLE) + { + isAlterTableRenameStmt = true; + } +#endif + + return isAlterTableRenameStmt; +} + + +/* + * ExecuteDistributedDDLCommand applies a given DDL command to the given + * distributed table. If the function is unable to access all the finalized + * shard placements, then it fails early and errors out. If the command + * successfully executed on any finalized shard placement, and failed on + * others, then it marks the placements on which execution failed as invalid. + */ +static void +ExecuteDistributedDDLCommand(Oid relationId, const char *ddlCommandString) +{ + List *failedPlacementList = NIL; + bool executionOK = false; + + bool allPlacementsAccessible = AllFinalizedPlacementsAccessible(relationId); + if (!allPlacementsAccessible) + { + ereport(ERROR, (errmsg("cannot execute command: %s", ddlCommandString), + errdetail("All finalized shard placements need to be accessible " + "to execute DDL commands on distributed tables."))); + } + + /* make sure we don't process cancel signals */ + HOLD_INTERRUPTS(); + + executionOK = ExecuteCommandOnWorkerShards(relationId, ddlCommandString, + &failedPlacementList); + + /* if command could not be executed on any finalized shard placement, error out */ + if (!executionOK) + { + ereport(ERROR, (errmsg("could not execute DDL command on worker node shards"))); + } + else + { + /* else, mark failed placements as inactive */ + ListCell *failedPlacementCell = NULL; + foreach(failedPlacementCell, failedPlacementList) + { + ShardPlacement *placement = (ShardPlacement *) lfirst(failedPlacementCell); + uint64 shardId = placement->shardId; + char *workerName = placement->nodeName; + uint32 workerPort = placement->nodePort; + uint64 oldShardLength = placement->shardLength; + + DeleteShardPlacementRow(shardId, workerName, workerPort); + InsertShardPlacementRow(shardId, FILE_INACTIVE, oldShardLength, + workerName, workerPort); + } + } + + if (QueryCancelPending) + { + ereport(WARNING, (errmsg("cancel requests are ignored during DDL commands"))); + QueryCancelPending = false; + } + + RESUME_INTERRUPTS(); +} + + +/* + * ExecuteCommandOnWorkerShards executes a given command on all the finalized + * shard placements of the given table. If the remote command errors out on the + * first attempted placement, the function returns false. Otherwise, it returns + * true. + * + * If the remote query errors out on the first attempted placement, it is very + * likely that the command is going to fail on other placements too. This is + * because most errors here will be PostgreSQL errors. Hence, the function fails + * fast to avoid marking a high number of placements as failed. If the command + * succeeds on at least one placement before failing on others, then the list of + * failed placements is returned in failedPlacementList. + * + * Note: There are certain errors which would occur on few nodes and not on the + * others. For example, adding a column with a type which exists on some nodes + * and not on the others. In that case, this function might still end up returning + * a large number of placements as failed. + */ +static bool +ExecuteCommandOnWorkerShards(Oid relationId, const char *commandString, + List **failedPlacementList) +{ + bool isFirstPlacement = true; + ListCell *shardCell = NULL; + List *shardList = NIL; + + shardList = LoadShardList(relationId); + foreach(shardCell, shardList) + { + List *shardPlacementList = NIL; + ListCell *shardPlacementCell = NULL; + uint64 *shardIdPointer = (uint64 *) lfirst(shardCell); + uint64 shardId = (*shardIdPointer); + + /* build the shard ddl command */ + char *escapedCommandString = quote_literal_cstr(commandString); + StringInfo applyCommand = makeStringInfo(); + appendStringInfo(applyCommand, WORKER_APPLY_SHARD_DDL_COMMAND, shardId, + escapedCommandString); + + shardPlacementList = FinalizedShardPlacementList(shardId); + foreach(shardPlacementCell, shardPlacementList) + { + ShardPlacement *placement = (ShardPlacement *) lfirst(shardPlacementCell); + char *workerName = placement->nodeName; + uint32 workerPort = placement->nodePort; + + List *queryResultList = ExecuteRemoteQuery(workerName, workerPort, + applyCommand); + if (queryResultList == NIL) + { + /* + * If we failed on the first placement, return false. We return + * here instead of exiting at the end to avoid breaking through + * multiple loops. + */ + if (isFirstPlacement) + { + return false; + } + + ereport(WARNING, (errmsg("could not apply command on shard " + UINT64_FORMAT " on node %s:%d", shardId, + workerName, workerPort), + errdetail("Shard placement will be marked as " + "inactive."))); + + *failedPlacementList = lappend(*failedPlacementList, placement); + } + else + { + ereport(DEBUG2, (errmsg("applied command on shard " UINT64_FORMAT " on " + "node %s:%d", shardId, workerName, workerPort))); + } + + isFirstPlacement = false; + } + + FreeStringInfo(applyCommand); + } + + return true; +} + + +/* + * AllFinalizedPlacementsAccessible returns true if all the finalized shard + * placements for a given relation are accessible. Otherwise, the function + * returns false. To do so, the function first gets a list of responsive + * worker nodes and then checks if all the finalized shard placements lie + * on those worker nodes. + */ +static bool +AllFinalizedPlacementsAccessible(Oid relationId) +{ + bool allPlacementsAccessible = true; + ListCell *shardCell = NULL; + List *responsiveNodeList = ResponsiveWorkerNodeList(); + + List *shardList = LoadShardList(relationId); + foreach(shardCell, shardList) + { + List *shardPlacementList = NIL; + ListCell *shardPlacementCell = NULL; + uint64 *shardIdPointer = (uint64 *) lfirst(shardCell); + uint64 shardId = (*shardIdPointer); + + shardPlacementList = FinalizedShardPlacementList(shardId); + foreach(shardPlacementCell, shardPlacementList) + { + ListCell *responsiveNodeCell = NULL; + bool placementAccessible = false; + ShardPlacement *placement = (ShardPlacement *) lfirst(shardPlacementCell); + + /* verify that the placement lies on one of the responsive worker nodes */ + foreach(responsiveNodeCell, responsiveNodeList) + { + WorkerNode *node = (WorkerNode *) lfirst(responsiveNodeCell); + if (strncmp(node->workerName, placement->nodeName, WORKER_LENGTH) == 0 && + node->workerPort == placement->nodePort) + { + placementAccessible = true; + break; + } + } + + if (!placementAccessible) + { + allPlacementsAccessible = false; + break; + } + } + + if (!allPlacementsAccessible) + { + break; + } + } + + return allPlacementsAccessible; +} + + +/* + * Before acquiring a table lock, check whether we have sufficient rights. + * In the case of DROP INDEX, also try to lock the table before the index. + * + * This code is heavily borrowed from RangeVarCallbackForDropRelation() in + * commands/tablecmds.c in Postgres source. We need this to ensure the right + * order of locking while dealing with DROP INDEX statments. + */ +static void +RangeVarCallbackForDropIndex(const RangeVar *rel, Oid relOid, Oid oldRelOid, void *arg) +{ + HeapTuple tuple; + struct DropRelationCallbackState *state; + char relkind; + Form_pg_class classform; + LOCKMODE heap_lockmode; + + state = (struct DropRelationCallbackState *) arg; + relkind = state->relkind; + heap_lockmode = state->concurrent ? + ShareUpdateExclusiveLock : AccessExclusiveLock; + + Assert(relkind == RELKIND_INDEX); + + /* + * If we previously locked some other index's heap, and the name we're + * looking up no longer refers to that relation, release the now-useless + * lock. + */ + if (relOid != oldRelOid && OidIsValid(state->heapOid)) + { + UnlockRelationOid(state->heapOid, heap_lockmode); + state->heapOid = InvalidOid; + } + + /* Didn't find a relation, so no need for locking or permission checks. */ + if (!OidIsValid(relOid)) + return; + + tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(relOid)); + if (!HeapTupleIsValid(tuple)) + return; /* concurrently dropped, so nothing to do */ + classform = (Form_pg_class) GETSTRUCT(tuple); + + if (classform->relkind != relkind) + { + ereport(ERROR, (errcode(ERRCODE_WRONG_OBJECT_TYPE), + errmsg("\"%s\" is not an index", rel->relname))); + } + + /* Allow DROP to either table owner or schema owner */ + if (!pg_class_ownercheck(relOid, GetUserId()) && + !pg_namespace_ownercheck(classform->relnamespace, GetUserId())) + aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CLASS, + rel->relname); + + if (!allowSystemTableMods && IsSystemClass(relOid, classform)) + ereport(ERROR, + (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), + errmsg("permission denied: \"%s\" is a system catalog", + rel->relname))); + + ReleaseSysCache(tuple); + + /* + * In DROP INDEX, attempt to acquire lock on the parent table before + * locking the index. index_drop() will need this anyway, and since + * regular queries lock tables before their indexes, we risk deadlock if + * we do it the other way around. No error if we don't find a pg_index + * entry, though --- the relation may have been dropped. + */ + if (relkind == RELKIND_INDEX && relOid != oldRelOid) + { + state->heapOid = IndexGetRelation(relOid, true); + if (OidIsValid(state->heapOid)) + LockRelationOid(state->heapOid, heap_lockmode); + } +} diff --git a/src/backend/distributed/master/master_create_shards.c b/src/backend/distributed/master/master_create_shards.c new file mode 100644 index 000000000..0617d8d59 --- /dev/null +++ b/src/backend/distributed/master/master_create_shards.c @@ -0,0 +1,234 @@ +/*------------------------------------------------------------------------- + * + * master_create_shards.c + * + * This file contains functions to distribute a table by creating shards for it + * across a set of worker nodes. + * + * Copyright (c) 2014-2015, Citus Data, Inc. + * + *------------------------------------------------------------------------- + */ + +#include "postgres.h" +#include "c.h" +#include "fmgr.h" +#include "libpq-fe.h" +#include "miscadmin.h" +#include "port.h" + +#include +#include +#include +#include +#include +#include + +#include "catalog/namespace.h" +#include "catalog/pg_class.h" +#include "distributed/connection_cache.h" +#include "distributed/listutils.h" +#include "distributed/master_metadata_utility.h" +#include "distributed/master_protocol.h" +#include "distributed/multi_join_order.h" +#include "distributed/pg_dist_partition.h" +#include "distributed/pg_dist_shard.h" +#include "distributed/resource_lock.h" +#include "distributed/worker_manager.h" +#include "lib/stringinfo.h" +#include "nodes/pg_list.h" +#include "nodes/primnodes.h" +#include "postmaster/postmaster.h" +#include "storage/fd.h" +#include "storage/lock.h" +#include "utils/builtins.h" +#include "utils/elog.h" +#include "utils/errcodes.h" +#include "utils/lsyscache.h" +#include "utils/palloc.h" + + +/* local function forward declarations */ +static void CheckHashPartitionedTable(Oid distributedTableId); +static text * IntegerToText(int32 value); + + +/* declarations for dynamic loading */ +PG_FUNCTION_INFO_V1(master_create_worker_shards); + + +/* + * master_create_worker_shards creates empty shards for the given table based + * on the specified number of initial shards. The function first gets a list of + * candidate nodes and issues DDL commands on the nodes to create empty shard + * placements on those nodes. The function then updates metadata on the master + * node to make this shard (and its placements) visible. Note that the function + * assumes the table is hash partitioned and calculates the min/max hash token + * ranges for each shard, giving them an equal split of the hash space. + */ +Datum +master_create_worker_shards(PG_FUNCTION_ARGS) +{ + text *tableNameText = PG_GETARG_TEXT_P(0); + int32 shardCount = PG_GETARG_INT32(1); + int32 replicationFactor = PG_GETARG_INT32(2); + + Oid distributedTableId = ResolveRelationId(tableNameText); + char relationKind = get_rel_relkind(distributedTableId); + char *tableName = text_to_cstring(tableNameText); + char shardStorageType = '\0'; + List *workerNodeList = NIL; + List *ddlCommandList = NIL; + int32 workerNodeCount = 0; + uint32 placementAttemptCount = 0; + uint64 hashTokenIncrement = 0; + List *existingShardList = NIL; + int64 shardIndex = 0; + + /* make sure table is hash partitioned */ + CheckHashPartitionedTable(distributedTableId); + + /* we plan to add shards: get an exclusive metadata lock */ + LockRelationDistributionMetadata(distributedTableId, ExclusiveLock); + + /* validate that shards haven't already been created for this table */ + existingShardList = LoadShardList(distributedTableId); + if (existingShardList != NIL) + { + ereport(ERROR, (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), + errmsg("table \"%s\" has already had shards created for it", + tableName))); + } + + /* make sure that at least one shard is specified */ + if (shardCount <= 0) + { + ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("shard_count must be positive"))); + } + + /* make sure that at least one replica is specified */ + if (replicationFactor <= 0) + { + ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("replication_factor must be positive"))); + } + + /* calculate the split of the hash space */ + hashTokenIncrement = HASH_TOKEN_COUNT / shardCount; + + /* load and sort the worker node list for deterministic placement */ + workerNodeList = WorkerNodeList(); + workerNodeList = SortList(workerNodeList, CompareWorkerNodes); + + /* make sure we don't process cancel signals until all shards are created */ + HOLD_INTERRUPTS(); + + /* retrieve the DDL commands for the table */ + ddlCommandList = GetTableDDLEvents(distributedTableId); + + workerNodeCount = list_length(workerNodeList); + if (replicationFactor > workerNodeCount) + { + ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("replication_factor (%d) exceeds number of worker nodes " + "(%d)", replicationFactor, workerNodeCount), + errhint("Add more worker nodes or try again with a lower " + "replication factor."))); + } + + /* if we have enough nodes, add an extra placement attempt for backup */ + placementAttemptCount = (uint32) replicationFactor; + if (workerNodeCount > replicationFactor) + { + placementAttemptCount++; + } + + /* set shard storage type according to relation type */ + if (relationKind == RELKIND_FOREIGN_TABLE) + { + shardStorageType = SHARD_STORAGE_FOREIGN; + } + else + { + shardStorageType = SHARD_STORAGE_TABLE; + } + + for (shardIndex = 0; shardIndex < shardCount; shardIndex++) + { + uint32 roundRobinNodeIndex = shardIndex % workerNodeCount; + + /* initialize the hash token space for this shard */ + text *minHashTokenText = NULL; + text *maxHashTokenText = NULL; + int32 shardMinHashToken = INT32_MIN + (shardIndex * hashTokenIncrement); + int32 shardMaxHashToken = shardMinHashToken + (hashTokenIncrement - 1); + Datum shardIdDatum = master_get_new_shardid(NULL); + int64 shardId = DatumGetInt64(shardIdDatum); + + /* if we are at the last shard, make sure the max token value is INT_MAX */ + if (shardIndex == (shardCount - 1)) + { + shardMaxHashToken = INT32_MAX; + } + + /* insert the shard metadata row along with its min/max values */ + minHashTokenText = IntegerToText(shardMinHashToken); + maxHashTokenText = IntegerToText(shardMaxHashToken); + + /* + * Grabbing the shard metadata lock isn't technically necessary since + * we already hold an exclusive lock on the partition table, but we'll + * acquire it for the sake of completeness. As we're adding new active + * placements, the mode must be exclusive. + */ + LockShardDistributionMetadata(shardId, ExclusiveLock); + + CreateShardPlacements(shardId, ddlCommandList, workerNodeList, + roundRobinNodeIndex, replicationFactor); + + InsertShardRow(distributedTableId, shardId, shardStorageType, + minHashTokenText, maxHashTokenText); + } + + if (QueryCancelPending) + { + ereport(WARNING, (errmsg("cancel requests are ignored during shard creation"))); + QueryCancelPending = false; + } + + RESUME_INTERRUPTS(); + + PG_RETURN_VOID(); +} + + +/* + * CheckHashPartitionedTable looks up the partition information for the given + * tableId and checks if the table is hash partitioned. If not, the function + * throws an error. + */ +static void +CheckHashPartitionedTable(Oid distributedTableId) +{ + char partitionType = PartitionMethod(distributedTableId); + if (partitionType != DISTRIBUTE_BY_HASH) + { + ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("unsupported table partition type: %c", partitionType))); + } +} + + +/* Helper function to convert an integer value to a text type */ +static text * +IntegerToText(int32 value) +{ + text *valueText = NULL; + StringInfo valueString = makeStringInfo(); + appendStringInfo(valueString, "%d", value); + + valueText = cstring_to_text(valueString->data); + + return valueText; +} diff --git a/src/backend/distributed/master/master_delete_protocol.c b/src/backend/distributed/master/master_delete_protocol.c new file mode 100644 index 000000000..35835c7d0 --- /dev/null +++ b/src/backend/distributed/master/master_delete_protocol.c @@ -0,0 +1,446 @@ +/*------------------------------------------------------------------------- + * + * master_delete_protocol.c + * + * Routine for deleting shards in the distributed cluster. This function takes + * in a delete command and deletes a shard if and only if all rows in the shard + * satisfy the conditions in the delete command. + * + * Copyright (c) 2014, Citus Data, Inc. + * + * $Id$ + * + *------------------------------------------------------------------------- + */ + + +#include "postgres.h" +#include "funcapi.h" +#include "miscadmin.h" + +#include "catalog/pg_class.h" +#include "commands/dbcommands.h" +#include "distributed/master_metadata_utility.h" +#include "distributed/master_protocol.h" +#include "distributed/metadata_cache.h" +#include "distributed/multi_client_executor.h" +#include "distributed/multi_physical_planner.h" +#include "distributed/multi_server_executor.h" +#include "distributed/pg_dist_partition.h" +#include "distributed/worker_protocol.h" +#include "optimizer/clauses.h" +#include "optimizer/predtest.h" +#include "optimizer/restrictinfo.h" +#include "optimizer/var.h" +#include "tcop/tcopprot.h" +#include "utils/builtins.h" +#include "utils/datum.h" +#include "utils/inval.h" +#include "utils/lsyscache.h" + + +/* Local functions forward declarations */ +static void CheckTableCount(Query *deleteQuery); +static void CheckDeleteCriteria(Node *deleteCriteria); +static void CheckPartitionColumn(Oid relationId, Node *whereClause); +static List * ShardsMatchingDeleteCriteria(Oid relationId, List *shardList, + Node *deleteCriteria); +static bool ExecuteRemoteCommand(const char *nodeName, uint32 nodePort, + StringInfo queryString); + + +/* exports for SQL callable functions */ +PG_FUNCTION_INFO_V1(master_apply_delete_command); + + +/* + * master_apply_delete_command takes in a delete command, finds shards that + * match the criteria defined in the delete command, drops the found shards from + * the worker nodes, and updates the corresponding metadata on the master node. + * This function drops a shard if and only if all rows in the shard satisfy + * the conditions in the delete command. Note that this function only accepts + * conditions on the partition key and if no condition is provided then all + * shards are deleted. + * + * We mark shard placements that we couldn't drop as to be deleted later. If a + * shard satisfies the given conditions, we delete it from shard metadata table + * even though related shard placements are not deleted. + */ +Datum +master_apply_delete_command(PG_FUNCTION_ARGS) +{ + text *queryText = PG_GETARG_TEXT_P(0); + char *queryString = text_to_cstring(queryText); + char *relationName = NULL; + text *relationNameText = NULL; + Oid relationId = InvalidOid; + List *shardIntervalList = NIL; + ListCell *shardIntervalCell = NULL; + List *deletableShardIntervalList = NIL; + List *queryTreeList = NIL; + Query *deleteQuery = NULL; + Node *whereClause = NULL; + Node *deleteCriteria = NULL; + Node *queryTreeNode = NULL; + DeleteStmt *deleteStatement = NULL; + int32 deleteCriteriaShardCount = 0; + LOCKTAG lockTag; + bool sessionLock = false; + bool dontWait = false; + char partitionMethod = 0; + + queryTreeNode = ParseTreeNode(queryString); + if (!IsA(queryTreeNode, DeleteStmt)) + { + ereport(ERROR, (errmsg("query \"%s\" is not a delete statement", + queryString))); + } + + deleteStatement = (DeleteStmt *) queryTreeNode; + relationName = deleteStatement->relation->relname; + relationNameText = cstring_to_text(relationName); + + relationId = ResolveRelationId(relationNameText); + CheckDistributedTable(relationId); + + queryTreeList = pg_analyze_and_rewrite(queryTreeNode, queryString, NULL, 0); + deleteQuery = (Query *) linitial(queryTreeList); + CheckTableCount(deleteQuery); + + /* get where clause and flatten it */ + whereClause = (Node *) deleteQuery->jointree->quals; + deleteCriteria = eval_const_expressions(NULL, whereClause); + + partitionMethod = PartitionMethod(relationId); + if ((partitionMethod == DISTRIBUTE_BY_HASH) && (deleteCriteria != NULL)) + { + ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("cannot delete from distributed table"), + errdetail("Delete statements on hash-partitioned tables " + "with where clause is not supported"))); + } + + CheckDeleteCriteria(deleteCriteria); + CheckPartitionColumn(relationId, deleteCriteria); + + /* acquire lock */ + SET_LOCKTAG_ADVISORY(lockTag, MyDatabaseId, relationId, 0, 0); + LockAcquire(&lockTag, ExclusiveLock, sessionLock, dontWait); + + shardIntervalList = LoadShardIntervalList(relationId); + + /* drop all shards if where clause is not present */ + if (deleteCriteria == NULL) + { + deletableShardIntervalList = shardIntervalList; + ereport(DEBUG2, (errmsg("dropping all shards for \"%s\"", relationName))); + } + else + { + deletableShardIntervalList = ShardsMatchingDeleteCriteria(relationId, + shardIntervalList, + deleteCriteria); + } + + foreach(shardIntervalCell, deletableShardIntervalList) + { + List *shardPlacementList = NIL; + List *droppedPlacementList = NIL; + List *lingeringPlacementList= NIL; + ListCell *shardPlacementCell = NULL; + ListCell *droppedPlacementCell = NULL; + ListCell *lingeringPlacementCell = NULL; + ShardInterval *shardInterval = (ShardInterval *) lfirst(shardIntervalCell); + uint64 shardId = shardInterval->shardId; + char *quotedShardName = NULL; + + /* if shard doesn't have an alias, extend regular table name */ + char *shardName = LoadShardAlias(relationId, shardId); + if (shardName == NULL) + { + shardName = get_rel_name(relationId); + AppendShardIdToName(&shardName, shardId); + } + + quotedShardName = quote_qualified_identifier(NULL, shardName); + + shardPlacementList = ShardPlacementList(shardId); + foreach(shardPlacementCell, shardPlacementList) + { + ShardPlacement *shardPlacement = (ShardPlacement *) lfirst(shardPlacementCell); + char *workerName = shardPlacement->nodeName; + uint32 workerPort = shardPlacement->nodePort; + bool dropSuccessful = false; + StringInfo workerDropQuery = makeStringInfo(); + + char tableType = get_rel_relkind(relationId); + if (tableType == RELKIND_RELATION) + { + appendStringInfo(workerDropQuery, DROP_REGULAR_TABLE_COMMAND, quotedShardName); + } + else if (tableType == RELKIND_FOREIGN_TABLE) + { + appendStringInfo(workerDropQuery, DROP_FOREIGN_TABLE_COMMAND, quotedShardName); + } + + dropSuccessful = ExecuteRemoteCommand(workerName, workerPort, workerDropQuery); + if (dropSuccessful) + { + droppedPlacementList = lappend(droppedPlacementList, shardPlacement); + } + else + { + lingeringPlacementList = lappend(lingeringPlacementList, shardPlacement); + } + } + + /* make sure we don't process cancel signals */ + HOLD_INTERRUPTS(); + + foreach(droppedPlacementCell, droppedPlacementList) + { + ShardPlacement *placement = (ShardPlacement *) lfirst(droppedPlacementCell); + char *workerName = placement->nodeName; + uint32 workerPort = placement->nodePort; + + DeleteShardPlacementRow(shardId, workerName, workerPort); + } + + /* mark shard placements that we couldn't drop as to be deleted */ + foreach(lingeringPlacementCell, lingeringPlacementList) + { + ShardPlacement *placement = (ShardPlacement *) lfirst(lingeringPlacementCell); + char *workerName = placement->nodeName; + uint32 workerPort = placement->nodePort; + uint64 oldShardLength = placement->shardLength; + + DeleteShardPlacementRow(shardId, workerName, workerPort); + InsertShardPlacementRow(shardId, FILE_TO_DELETE, oldShardLength, + workerName, workerPort); + + ereport(WARNING, (errmsg("could not delete shard \"%s\" on node " + "\"%s:%u\"", shardName, workerName, workerPort), + errdetail("Marking this shard placement for deletion"))); + } + + DeleteShardRow(shardId); + + if (QueryCancelPending) + { + ereport(WARNING, (errmsg("cancel requests are ignored during shard deletion"))); + QueryCancelPending = false; + } + + RESUME_INTERRUPTS(); + } + + deleteCriteriaShardCount = list_length(deletableShardIntervalList); + PG_RETURN_INT32(deleteCriteriaShardCount); +} + + +/* Checks that delete is only on one table. */ +static void +CheckTableCount(Query *deleteQuery) +{ + int rangeTableCount = list_length(deleteQuery->rtable); + if (rangeTableCount > 1) + { + ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("cannot delete from distributed table"), + errdetail("Delete on multiple tables is not supported"))); + } +} + + +/* Checks that delete criteria only consists of simple operator expressions. */ +static void +CheckDeleteCriteria(Node *deleteCriteria) +{ + bool simpleOpExpression = true; + + if (deleteCriteria == NULL) + { + return; + } + + if (is_opclause(deleteCriteria)) + { + simpleOpExpression = SimpleOpExpression((Expr *) deleteCriteria); + } + else if (IsA(deleteCriteria, BoolExpr)) + { + ListCell *opExpressionCell = NULL; + BoolExpr *deleteCriteriaExpression = (BoolExpr *) deleteCriteria; + List *opExpressionList = deleteCriteriaExpression->args; + + foreach(opExpressionCell, opExpressionList) + { + Expr *opExpression = (Expr *) lfirst(opExpressionCell); + if (!SimpleOpExpression(opExpression)) + { + simpleOpExpression = false; + break; + } + } + } + else + { + simpleOpExpression = false; + } + + if (!simpleOpExpression) + { + ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("cannot delete from distributed table"), + errdetail("Delete query has a complex operator expression"))); + } +} + + + /* + * CheckPartitionColumn checks that the given where clause is based only on the + * partition key of the given relation id. + */ +static void +CheckPartitionColumn(Oid relationId, Node *whereClause) +{ + Var *partitionColumn = PartitionKey(relationId); + ListCell *columnCell = NULL; + + List *columnList = pull_var_clause_default(whereClause); + foreach(columnCell, columnList) + { + Var *var = (Var *) lfirst(columnCell); + if (var->varattno != partitionColumn->varattno) + { + ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("cannot delete from distributed table"), + errdetail("Where clause includes a column other than " + "partition column"))); + } + } +} + + +/* + * ShardsMatchingDeleteCriteria selects shards to be deleted from the shard + * interval list based on the delete criteria, and returns selected shards in + * another list. We add a shard to the list if and only if all rows in the shard + * satisfy the delete criteria. Note that this function does not expect + * deleteCriteria to be NULL. + */ +static List * +ShardsMatchingDeleteCriteria(Oid relationId, List *shardIntervalList, + Node *deleteCriteria) +{ + List *dropShardIntervalList = NIL; + List *deleteCriteriaList = NIL; + ListCell *shardIntervalCell = NULL; + + /* build the base expression for constraint */ + Index rangeTableIndex = 1; + Var *partitionColumn = PartitionColumn(relationId, rangeTableIndex); + Node *baseConstraint = BuildBaseConstraint(partitionColumn); + + Assert(deleteCriteria != NULL); + deleteCriteriaList = list_make1(deleteCriteria); + + /* walk over shard list and check if shards can be dropped */ + foreach(shardIntervalCell, shardIntervalList) + { + ShardInterval *shardInterval = (ShardInterval *) lfirst(shardIntervalCell); + if (shardInterval->minValueExists && shardInterval->maxValueExists) + { + List *restrictInfoList = NIL; + bool dropShard = false; + BoolExpr *andExpr = NULL; + Expr *lessThanExpr = NULL; + Expr *greaterThanExpr = NULL; + RestrictInfo *lessThanRestrictInfo = NULL; + RestrictInfo *greaterThanRestrictInfo = NULL; + + /* set the min/max values in the base constraint */ + UpdateConstraint(baseConstraint, shardInterval); + + andExpr = (BoolExpr *) baseConstraint; + lessThanExpr = (Expr *) linitial(andExpr->args); + greaterThanExpr = (Expr *) lsecond(andExpr->args); + + lessThanRestrictInfo = make_simple_restrictinfo(lessThanExpr); + greaterThanRestrictInfo = make_simple_restrictinfo(greaterThanExpr); + + restrictInfoList = lappend(restrictInfoList, lessThanRestrictInfo); + restrictInfoList = lappend(restrictInfoList, greaterThanRestrictInfo); + + dropShard = predicate_implied_by(deleteCriteriaList, restrictInfoList); + if (dropShard) + { + dropShardIntervalList = lappend(dropShardIntervalList, shardInterval); + ereport(DEBUG2, (errmsg("delete criteria includes shardId " + UINT64_FORMAT, shardInterval->shardId))); + } + } + } + + return dropShardIntervalList; +} + + +/* + * ExecuteRemoteCommand executes the given SQL command. This command could be an + * Insert, Update, or Delete statement, or a utility command that returns + * nothing. If query is successfuly executed, the function returns true. + * Otherwise, it returns false. + */ +static bool +ExecuteRemoteCommand(const char *nodeName, uint32 nodePort, StringInfo queryString) +{ + char *nodeDatabase = get_database_name(MyDatabaseId); + int32 connectionId = -1; + QueryStatus queryStatus = CLIENT_INVALID_QUERY; + bool querySent = false; + bool queryReady = false; + bool queryDone = false; + + connectionId = MultiClientConnect(nodeName, nodePort, nodeDatabase); + if (connectionId == INVALID_CONNECTION_ID) + { + return false; + } + + querySent = MultiClientSendQuery(connectionId, queryString->data); + if (!querySent) + { + MultiClientDisconnect(connectionId); + return false; + } + + while (!queryReady) + { + ResultStatus resultStatus = MultiClientResultStatus(connectionId); + if (resultStatus == CLIENT_RESULT_READY) + { + queryReady = true; + } + else if (resultStatus == CLIENT_RESULT_BUSY) + { + long sleepIntervalPerCycle = RemoteTaskCheckInterval * 1000L; + pg_usleep(sleepIntervalPerCycle); + } + else + { + MultiClientDisconnect(connectionId); + return false; + } + } + + queryStatus = MultiClientQueryStatus(connectionId); + if (queryStatus == CLIENT_QUERY_DONE) + { + queryDone = true; + } + + MultiClientDisconnect(connectionId); + return queryDone; +} diff --git a/src/backend/distributed/master/master_metadata_utility.c b/src/backend/distributed/master/master_metadata_utility.c new file mode 100644 index 000000000..d8ac90997 --- /dev/null +++ b/src/backend/distributed/master/master_metadata_utility.c @@ -0,0 +1,587 @@ +/*------------------------------------------------------------------------- + * + * master_metadata_utility.c + * Routines for reading and modifying master node's metadata. + * + * Copyright (c) 2014, Citus Data, Inc. + * + * $Id$ + * + *------------------------------------------------------------------------- + */ + +#include "postgres.h" +#include "funcapi.h" + +#include "access/htup_details.h" +#include "access/xact.h" +#include "catalog/indexing.h" +#include "catalog/pg_type.h" +#include "distributed/citus_nodes.h" +#include "distributed/master_metadata_utility.h" +#include "distributed/metadata_cache.h" +#include "distributed/multi_join_order.h" +#include "distributed/multi_logical_optimizer.h" +#include "distributed/pg_dist_partition.h" +#include "distributed/pg_dist_shard.h" +#include "distributed/pg_dist_shard_placement.h" +#include "distributed/worker_manager.h" +#include "nodes/makefuncs.h" +#include "parser/scansup.h" +#include "utils/builtins.h" +#include "utils/datum.h" +#include "utils/fmgroids.h" +#include "utils/inval.h" +#include "utils/lsyscache.h" +#include "utils/rel.h" +#include "utils/syscache.h" +#include "utils/tqual.h" + + +/* Local functions forward declarations */ +static uint64 * AllocateUint64(uint64 value); + + +/* + * LoadShardIntervalList returns a list of shard intervals related for a given + * distributed table. The function returns an empty list if no shards can be + * found for the given relation. + */ +List * +LoadShardIntervalList(Oid relationId) +{ + DistTableCacheEntry *cacheEntry = DistributedTableCacheEntry(relationId); + List *shardList = NIL; + int i = 0; + + for (i = 0; i < cacheEntry->shardIntervalArrayLength; i++) + { + ShardInterval *newShardInterval = NULL; + newShardInterval = (ShardInterval *) palloc0(sizeof(ShardInterval)); + + CopyShardInterval(&cacheEntry->shardIntervalArray[i], newShardInterval); + + shardList = lappend(shardList, newShardInterval); + } + + return shardList; +} + + +/* + * LoadShardList reads list of shards for given relationId from pg_dist_shard, + * and returns the list of found shardIds. + */ +List * +LoadShardList(Oid relationId) +{ + DistTableCacheEntry *cacheEntry = DistributedTableCacheEntry(relationId); + List *shardList = NIL; + int i = 0; + + for (i = 0; i < cacheEntry->shardIntervalArrayLength; i++) + { + ShardInterval *currentShardInterval = &cacheEntry->shardIntervalArray[i]; + uint64 *shardIdPointer = AllocateUint64(currentShardInterval->shardId); + + shardList = lappend(shardList, shardIdPointer); + } + + return shardList; +} + + +/* Allocates eight bytes, and copies given value's contents those bytes. */ +static uint64 * +AllocateUint64(uint64 value) +{ + uint64 *allocatedValue = (uint64 *) palloc0(sizeof(uint64)); + Assert(sizeof(uint64) >= 8); + + (*allocatedValue) = value; + + return allocatedValue; +} + + +/* + * LoadShardAlias finds the row for given relation and shardId in pg_dist_shard, + * finds the shard alias in this row if any, and then deep copies this alias. + */ +char * +LoadShardAlias(Oid relationId, uint64 shardId) +{ + SysScanDesc scanDescriptor = NULL; + ScanKeyData scanKey[1]; + int scanKeyCount = 1; + HeapTuple heapTuple = NULL; + Datum shardAliasDatum = 0; + bool shardAliasNull = false; + char *shardAlias = NULL; + + Relation pgDistShard = heap_open(DistShardRelationId(), AccessShareLock); + TupleDesc tupleDescriptor = RelationGetDescr(pgDistShard); + + ScanKeyInit(&scanKey[0], Anum_pg_dist_shard_shardid, + BTEqualStrategyNumber, F_INT8EQ, Int64GetDatum(shardId)); + + scanDescriptor = systable_beginscan(pgDistShard, + DistShardShardidIndexId(), true, + NULL, scanKeyCount, scanKey); + + /* + * Normally, we should have at most one tuple here as we have a unique index + * on shardId. However, if users want to drop this uniqueness constraint, + * and look up the shardalias based on the relation and shardId pair, we + * still allow that. We don't have any users relaying on this feature. Thus, + * we may consider to remove this check. + */ + heapTuple = systable_getnext(scanDescriptor); + while (HeapTupleIsValid(heapTuple)) + { + Form_pg_dist_shard pgDistShardForm = (Form_pg_dist_shard) GETSTRUCT(heapTuple); + if (pgDistShardForm->logicalrelid == relationId) + { + break; + } + + heapTuple = systable_getnext(scanDescriptor); + } + + /* if no tuple found, error out */ + if (!HeapTupleIsValid(heapTuple)) + { + ereport(ERROR, (errmsg("could not find valid entry for relationId: %u " + "and shard " UINT64_FORMAT, relationId, shardId))); + } + + /* if shard alias exists, deep copy cstring */ + shardAliasDatum = heap_getattr(heapTuple, Anum_pg_dist_shard_shardalias, + tupleDescriptor, &shardAliasNull); + if (!shardAliasNull) + { + shardAlias = TextDatumGetCString(shardAliasDatum); + } + + systable_endscan(scanDescriptor); + heap_close(pgDistShard, AccessShareLock); + + return shardAlias; +} + + +/* + * CopyShardInterval copies fields from the specified source ShardInterval + * into the fields of the provided destination ShardInterval. + */ +void +CopyShardInterval(ShardInterval *srcInterval, ShardInterval *destInterval) +{ + destInterval->type = srcInterval->type; + destInterval->relationId = srcInterval->relationId; + destInterval->storageType = srcInterval->storageType; + destInterval->valueTypeId = srcInterval->valueTypeId; + destInterval->valueTypeLen = srcInterval->valueTypeLen; + destInterval->valueByVal = srcInterval->valueByVal; + destInterval->minValueExists = srcInterval->minValueExists; + destInterval->maxValueExists = srcInterval->maxValueExists; + destInterval->shardId = srcInterval->shardId; + + destInterval->minValue = 0; + if (destInterval->minValueExists) + { + destInterval->minValue = datumCopy(srcInterval->minValue, + srcInterval->valueByVal, + srcInterval->valueTypeLen); + } + + destInterval->maxValue = 0; + if (destInterval->maxValueExists) + { + destInterval->maxValue = datumCopy(srcInterval->maxValue, + srcInterval->valueByVal, + srcInterval->valueTypeLen); + } +} + + +/* + * ShardLength finds shard placements for the given shardId, extracts the length + * of a finalized shard, and returns the shard's length. This function errors + * out if we cannot find any finalized shard placements for the given shardId. + */ +uint64 +ShardLength(uint64 shardId) +{ + uint64 shardLength = 0; + + List *shardPlacementList = FinalizedShardPlacementList(shardId); + if (shardPlacementList == NIL) + { + ereport(ERROR, (errmsg("could not find length of shard " UINT64_FORMAT, shardId), + errdetail("Could not find any shard placements for the shard."))); + } + else + { + ShardPlacement *shardPlacement = (ShardPlacement *) linitial(shardPlacementList); + shardLength = shardPlacement->shardLength; + } + + return shardLength; +} + + +/* + * FinalizedShardPlacementList finds shard placements for the given shardId from + * system catalogs, chooses placements that are in finalized state, and returns + * these shard placements in a new list. + */ +List * +FinalizedShardPlacementList(uint64 shardId) +{ + List *finalizedPlacementList = NIL; + List *shardPlacementList = ShardPlacementList(shardId); + + ListCell *shardPlacementCell = NULL; + foreach(shardPlacementCell, shardPlacementList) + { + ShardPlacement *shardPlacement = (ShardPlacement *) lfirst(shardPlacementCell); + if (shardPlacement->shardState == FILE_FINALIZED) + { + finalizedPlacementList = lappend(finalizedPlacementList, shardPlacement); + } + } + + return finalizedPlacementList; +} + + +/* + * ShardPlacementList finds shard placements for the given shardId from system + * catalogs, converts these placements to their in-memory representation, and + * returns the converted shard placements in a new list. + */ +List * +ShardPlacementList(uint64 shardId) +{ + List *shardPlacementList = NIL; + Relation pgShardPlacement = NULL; + SysScanDesc scanDescriptor = NULL; + ScanKeyData scanKey[1]; + int scanKeyCount = 1; + bool indexOK = true; + HeapTuple heapTuple = NULL; + + pgShardPlacement = heap_open(DistShardPlacementRelationId(), AccessShareLock); + + ScanKeyInit(&scanKey[0], Anum_pg_dist_shard_placement_shardid, + BTEqualStrategyNumber, F_INT8EQ, Int64GetDatum(shardId)); + + scanDescriptor = systable_beginscan(pgShardPlacement, + DistShardPlacementShardidIndexId(), indexOK, + NULL, scanKeyCount, scanKey); + + heapTuple = systable_getnext(scanDescriptor); + while (HeapTupleIsValid(heapTuple)) + { + TupleDesc tupleDescriptor = RelationGetDescr(pgShardPlacement); + + ShardPlacement *placement = TupleToShardPlacement(tupleDescriptor, heapTuple); + shardPlacementList = lappend(shardPlacementList, placement); + + heapTuple = systable_getnext(scanDescriptor); + } + + systable_endscan(scanDescriptor); + heap_close(pgShardPlacement, AccessShareLock); + + /* if no shard placements are found, warn the user */ + if (shardPlacementList == NIL) + { + ereport(WARNING, (errmsg("could not find any shard placements for shardId " + UINT64_FORMAT, shardId))); + } + + return shardPlacementList; +} + + +/* + * TupleToShardPlacement takes in a heap tuple from pg_dist_shard_placement, and + * converts this tuple to an equivalent struct in memory. The function assumes + * the caller already has locks on the tuple, and doesn't perform any locking. + */ +ShardPlacement * +TupleToShardPlacement(TupleDesc tupleDescriptor, HeapTuple heapTuple) +{ + ShardPlacement *shardPlacement = NULL; + bool isNull = false; + + Oid tupleOid = HeapTupleGetOid(heapTuple); + Datum shardId = heap_getattr(heapTuple, Anum_pg_dist_shard_placement_shardid, + tupleDescriptor, &isNull); + Datum shardLength = heap_getattr(heapTuple, Anum_pg_dist_shard_placement_shardlength, + tupleDescriptor, &isNull); + Datum shardState = heap_getattr(heapTuple, Anum_pg_dist_shard_placement_shardstate, + tupleDescriptor, &isNull); + Datum nodeName = heap_getattr(heapTuple, Anum_pg_dist_shard_placement_nodename, + tupleDescriptor, &isNull); + Datum nodePort = heap_getattr(heapTuple, Anum_pg_dist_shard_placement_nodeport, + tupleDescriptor, &isNull); + + Assert(!HeapTupleHasNulls(heapTuple)); + + shardPlacement = CitusMakeNode(ShardPlacement); + shardPlacement->tupleOid = tupleOid; + shardPlacement->shardId = DatumGetInt64(shardId); + shardPlacement->shardLength = DatumGetInt64(shardLength); + shardPlacement->shardState = DatumGetUInt32(shardState); + shardPlacement->nodeName = TextDatumGetCString(nodeName); + shardPlacement->nodePort = DatumGetUInt32(nodePort); + + return shardPlacement; +} + + +/* + * InsertShardRow opens the shard system catalog, and inserts a new row with the + * given values into that system catalog. Note that we allow the user to pass in + * null min/max values in case they are creating an empty shard. + */ +void +InsertShardRow(Oid relationId, uint64 shardId, char storageType, + text *shardMinValue, text *shardMaxValue) +{ + Relation pgDistShard = NULL; + TupleDesc tupleDescriptor = NULL; + HeapTuple heapTuple = NULL; + Datum values[Natts_pg_dist_shard]; + bool isNulls[Natts_pg_dist_shard]; + + /* form new shard tuple */ + memset(values, 0, sizeof(values)); + memset(isNulls, false, sizeof(isNulls)); + + values[Anum_pg_dist_shard_logicalrelid - 1] = ObjectIdGetDatum(relationId); + values[Anum_pg_dist_shard_shardid - 1] = Int64GetDatum(shardId); + values[Anum_pg_dist_shard_shardstorage - 1] = CharGetDatum(storageType); + + /* check if shard min/max values are null */ + if (shardMinValue != NULL && shardMaxValue != NULL) + { + values[Anum_pg_dist_shard_shardminvalue - 1] = PointerGetDatum(shardMinValue); + values[Anum_pg_dist_shard_shardmaxvalue - 1] = PointerGetDatum(shardMaxValue); + + /* we always set shard alias to null */ + isNulls[Anum_pg_dist_shard_shardalias - 1] = true; + } + else + { + isNulls[Anum_pg_dist_shard_shardminvalue - 1] = true; + isNulls[Anum_pg_dist_shard_shardmaxvalue - 1] = true; + isNulls[Anum_pg_dist_shard_shardalias - 1] = true; + } + + /* open shard relation and insert new tuple */ + pgDistShard = heap_open(DistShardRelationId(), RowExclusiveLock); + + tupleDescriptor = RelationGetDescr(pgDistShard); + heapTuple = heap_form_tuple(tupleDescriptor, values, isNulls); + + simple_heap_insert(pgDistShard, heapTuple); + CatalogUpdateIndexes(pgDistShard, heapTuple); + CommandCounterIncrement(); + + /* close relation and invalidate previous cache entry */ + heap_close(pgDistShard, RowExclusiveLock); + CacheInvalidateRelcacheByRelid(relationId); +} + + +/* + * InsertShardPlacementRow opens the shard placement system catalog, and inserts + * a new row with the given values into that system catalog. + */ +void +InsertShardPlacementRow(uint64 shardId, char shardState, uint64 shardLength, + char *nodeName, uint32 nodePort) +{ + Relation pgDistShardPlacement = NULL; + TupleDesc tupleDescriptor = NULL; + HeapTuple heapTuple = NULL; + Datum values[Natts_pg_dist_shard_placement]; + bool isNulls[Natts_pg_dist_shard_placement]; + + /* form new shard placement tuple */ + memset(values, 0, sizeof(values)); + memset(isNulls, false, sizeof(isNulls)); + + values[Anum_pg_dist_shard_placement_shardid - 1] = Int64GetDatum(shardId); + values[Anum_pg_dist_shard_placement_shardstate - 1] = CharGetDatum(shardState); + values[Anum_pg_dist_shard_placement_shardlength - 1] = Int64GetDatum(shardLength); + values[Anum_pg_dist_shard_placement_nodename - 1] = CStringGetTextDatum(nodeName); + values[Anum_pg_dist_shard_placement_nodeport - 1] = UInt32GetDatum(nodePort); + + /* open shard placement relation and insert new tuple */ + pgDistShardPlacement = heap_open(DistShardPlacementRelationId(), RowExclusiveLock); + + tupleDescriptor = RelationGetDescr(pgDistShardPlacement); + heapTuple = heap_form_tuple(tupleDescriptor, values, isNulls); + + simple_heap_insert(pgDistShardPlacement, heapTuple); + CatalogUpdateIndexes(pgDistShardPlacement, heapTuple); + CommandCounterIncrement(); + + /* close relation */ + heap_close(pgDistShardPlacement, RowExclusiveLock); +} + + +/* + * DeleteShardRow opens the shard system catalog, finds the unique row that has + * the given shardId, and deletes this row. + */ +void +DeleteShardRow(uint64 shardId) +{ + Relation pgDistShard = NULL; + SysScanDesc scanDescriptor = NULL; + ScanKeyData scanKey[1]; + int scanKeyCount = 1; + bool indexOK = true; + HeapTuple heapTuple = NULL; + Form_pg_dist_shard pgDistShardForm = NULL; + Oid distributedRelationId = InvalidOid; + + pgDistShard = heap_open(DistShardRelationId(), RowExclusiveLock); + + ScanKeyInit(&scanKey[0], Anum_pg_dist_shard_shardid, + BTEqualStrategyNumber, F_INT8EQ, Int64GetDatum(shardId)); + + scanDescriptor = systable_beginscan(pgDistShard, + DistShardShardidIndexId(), indexOK, + NULL, scanKeyCount, scanKey); + + heapTuple = systable_getnext(scanDescriptor); + if (!HeapTupleIsValid(heapTuple)) + { + ereport(ERROR, (errmsg("could not find valid entry for shard " + UINT64_FORMAT, shardId))); + } + + pgDistShardForm = (Form_pg_dist_shard) GETSTRUCT(heapTuple); + distributedRelationId = pgDistShardForm->logicalrelid; + + simple_heap_delete(pgDistShard, &heapTuple->t_self); + CommandCounterIncrement(); + + systable_endscan(scanDescriptor); + heap_close(pgDistShard, RowExclusiveLock); + + /* invalidate previous cache entry */ + CacheInvalidateRelcacheByRelid(distributedRelationId); +} + + +/* + * DeleteShardPlacementRow opens the shard placement system catalog, finds the + * first (unique) row that corresponds to the given shardId and worker node, and + * deletes this row. + */ +void +DeleteShardPlacementRow(uint64 shardId, char *workerName, uint32 workerPort) +{ + Relation pgDistShardPlacement = NULL; + SysScanDesc scanDescriptor = NULL; + ScanKeyData scanKey[1]; + int scanKeyCount = 1; + bool indexOK = true; + HeapTuple heapTuple = NULL; + bool heapTupleFound = false; + + pgDistShardPlacement = heap_open(DistShardPlacementRelationId(), RowExclusiveLock); + + ScanKeyInit(&scanKey[0], Anum_pg_dist_shard_placement_shardid, + BTEqualStrategyNumber, F_INT8EQ, Int64GetDatum(shardId)); + + scanDescriptor = systable_beginscan(pgDistShardPlacement, + DistShardPlacementShardidIndexId(), indexOK, + NULL, scanKeyCount, scanKey); + + heapTuple = systable_getnext(scanDescriptor); + while (HeapTupleIsValid(heapTuple)) + { + TupleDesc tupleDescriptor = RelationGetDescr(pgDistShardPlacement); + + ShardPlacement *placement = TupleToShardPlacement(tupleDescriptor, heapTuple); + if (strncmp(placement->nodeName, workerName, WORKER_LENGTH) == 0 && + placement->nodePort == workerPort) + { + heapTupleFound = true; + break; + } + + heapTuple = systable_getnext(scanDescriptor); + } + + /* if we couldn't find the shard placement to delete, error out */ + if (!heapTupleFound) + { + ereport(ERROR, (errmsg("could not find valid entry for shard placement " + UINT64_FORMAT " on node \"%s:%u\"", + shardId, workerName, workerPort))); + } + + simple_heap_delete(pgDistShardPlacement, &heapTuple->t_self); + CommandCounterIncrement(); + + systable_endscan(scanDescriptor); + heap_close(pgDistShardPlacement, RowExclusiveLock); +} + + +/* + * BuildDistributionKeyFromColumnName builds a simple distribution key consisting + * only out of a reference to the column of name columnName. Errors out if the + * specified column does not exist or is not suitable to be used as a + * distribution column. + */ +Node * +BuildDistributionKeyFromColumnName(Relation distributedRelation, char *columnName) +{ + HeapTuple columnTuple = NULL; + Form_pg_attribute columnForm = NULL; + Var *column = NULL; + char *tableName = RelationGetRelationName(distributedRelation); + + /* it'd probably better to downcase identifiers consistent with SQL case folding */ + truncate_identifier(columnName, strlen(columnName), true); + + /* lookup column definition */ + columnTuple = SearchSysCacheAttName(RelationGetRelid(distributedRelation), + columnName); + if (!HeapTupleIsValid(columnTuple)) + { + ereport(ERROR, (errcode(ERRCODE_UNDEFINED_COLUMN), + errmsg("column \"%s\" of relation \"%s\" does not exist", + columnName, tableName))); + } + + columnForm = (Form_pg_attribute) GETSTRUCT(columnTuple); + + /* check if the column may be referenced in the distribution key */ + if (columnForm->attnum <= 0) + { + ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("cannot reference system column \"%s\" in relation \"%s\"", + columnName, tableName))); + } + + /* build Var referencing only the chosen distribution column */ + column = makeVar(1, columnForm->attnum, columnForm->atttypid, + columnForm->atttypmod, columnForm->attcollation, 0); + + ReleaseSysCache(columnTuple); + + return (Node *) column; +} diff --git a/src/backend/distributed/master/master_node_protocol.c b/src/backend/distributed/master/master_node_protocol.c new file mode 100644 index 000000000..fc9413666 --- /dev/null +++ b/src/backend/distributed/master/master_node_protocol.c @@ -0,0 +1,756 @@ +/*------------------------------------------------------------------------- + * + * master_node_protocol.c + * Routines for requesting information from the master node for creating or + * updating shards. + * + * Copyright (c) 2012, Citus Data, Inc. + * + * $Id$ + * + *------------------------------------------------------------------------- + */ + +#include "postgres.h" + +#include "funcapi.h" +#include "miscadmin.h" + +#include "access/htup_details.h" +#include "catalog/catalog.h" +#include "catalog/dependency.h" +#include "catalog/indexing.h" +#include "catalog/namespace.h" +#include "catalog/pg_index.h" +#include "catalog/pg_type.h" +#include "commands/sequence.h" +#include "distributed/citus_ruleutils.h" +#include "distributed/listutils.h" +#include "distributed/master_protocol.h" +#include "distributed/metadata_cache.h" +#include "distributed/multi_physical_planner.h" +#include "distributed/pg_dist_shard.h" +#include "distributed/pg_dist_partition.h" +#include "distributed/worker_manager.h" +#include "foreign/foreign.h" +#include "libpq/ip.h" +#include "libpq/libpq-be.h" +#include "nodes/pg_list.h" +#include "storage/lock.h" +#include "utils/builtins.h" +#include "utils/fmgroids.h" +#include "utils/lsyscache.h" +#if (PG_VERSION_NUM >= 90500) +#include "utils/ruleutils.h" +#endif +#include "utils/syscache.h" +#include "utils/tqual.h" + + +/* Shard related configuration */ +int ShardReplicationFactor = 2; /* desired replication factor for shards */ +int ShardMaxSize = 1048576; /* maximum size in KB one shard can grow to */ +int ShardPlacementPolicy = SHARD_PLACEMENT_ROUND_ROBIN; + + +static char * hostname_client_addr(void); +static Datum WorkerNodeGetDatum(WorkerNode *workerNode, TupleDesc tupleDescriptor); + + +/* exports for SQL callable functions */ +PG_FUNCTION_INFO_V1(master_get_table_metadata); +PG_FUNCTION_INFO_V1(master_get_table_ddl_events); +PG_FUNCTION_INFO_V1(master_get_new_shardid); +PG_FUNCTION_INFO_V1(master_get_local_first_candidate_nodes); +PG_FUNCTION_INFO_V1(master_get_round_robin_candidate_nodes); +PG_FUNCTION_INFO_V1(master_get_active_worker_nodes); + + +/* + * master_get_table_metadata takes in a relation name, and returns partition + * related metadata for the relation. These metadata are grouped and returned in + * a tuple, and are used by the caller when creating new shards. The function + * errors if given relation does not exist, or is not partitioned. + */ +Datum +master_get_table_metadata(PG_FUNCTION_ARGS) +{ + text *relationName = PG_GETARG_TEXT_P(0); + Oid relationId = ResolveRelationId(relationName); + + DistTableCacheEntry *partitionEntry = NULL; + TypeFuncClass resultTypeClass = 0; + Datum partitionKeyExpr = 0; + Datum partitionKey = 0; + Datum metadataDatum = 0; + HeapTuple metadataTuple = NULL; + TupleDesc metadataDescriptor = NULL; + uint64 shardMaxSizeInBytes = 0; + char relationType = 0; + char storageType = 0; + Datum values[TABLE_METADATA_FIELDS]; + bool isNulls[TABLE_METADATA_FIELDS]; + + /* find partition tuple for partitioned relation */ + partitionEntry = DistributedTableCacheEntry(relationId); + + /* create tuple descriptor for return value */ + resultTypeClass = get_call_result_type(fcinfo, NULL, &metadataDescriptor); + if (resultTypeClass != TYPEFUNC_COMPOSITE) + { + ereport(ERROR, (errmsg("return type must be a row type"))); + } + + /* get decompiled expression tree for partition key */ + partitionKeyExpr = + PointerGetDatum(cstring_to_text(partitionEntry->partitionKeyString)); + partitionKey = DirectFunctionCall2(pg_get_expr, partitionKeyExpr, + ObjectIdGetDatum(relationId)); + + /* form heap tuple for table metadata */ + memset(values, 0, sizeof(values)); + memset(isNulls, false, sizeof(isNulls)); + + shardMaxSizeInBytes = (int64) ShardMaxSize * 1024L; + + /* get storage type */ + relationType = get_rel_relkind(relationId); + if (relationType == RELKIND_RELATION) + { + storageType = SHARD_STORAGE_TABLE; + } + else if (relationType == RELKIND_FOREIGN_TABLE) + { + bool cstoreTable = CStoreTable(relationId); + if (cstoreTable) + { + storageType = SHARD_STORAGE_COLUMNAR; + } + else + { + storageType = SHARD_STORAGE_FOREIGN; + } + } + + values[0] = ObjectIdGetDatum(relationId); + values[1] = storageType; + values[2] = partitionEntry->partitionMethod; + values[3] = partitionKey; + values[4] = Int32GetDatum(ShardReplicationFactor); + values[5] = Int64GetDatum(shardMaxSizeInBytes); + values[6] = Int32GetDatum(ShardPlacementPolicy); + + metadataTuple = heap_form_tuple(metadataDescriptor, values, isNulls); + metadataDatum = HeapTupleGetDatum(metadataTuple); + + PG_RETURN_DATUM(metadataDatum); +} + + +/* + * CStoreTable returns true if the given relationId belongs to a foreign cstore + * table, otherwise it returns false. + */ +bool +CStoreTable(Oid relationId) +{ + bool cstoreTable = false; + + char relationKind = get_rel_relkind(relationId); + if (relationKind == RELKIND_FOREIGN_TABLE) + { + ForeignTable *foreignTable = GetForeignTable(relationId); + ForeignServer *server = GetForeignServer(foreignTable->serverid); + ForeignDataWrapper *foreignDataWrapper = GetForeignDataWrapper(server->fdwid); + + if (strncmp(foreignDataWrapper->fdwname, CSTORE_FDW_NAME, NAMEDATALEN) == 0) + { + cstoreTable = true; + } + } + + return cstoreTable; +} + + +/* + * master_get_table_ddl_events takes in a relation name, and returns the set of + * DDL commands needed to reconstruct the relation. The returned DDL commands + * are similar in flavor to schema definitions that pgdump returns. The function + * errors if given relation does not exist. + */ +Datum +master_get_table_ddl_events(PG_FUNCTION_ARGS) +{ + FuncCallContext *functionContext = NULL; + ListCell *tableDDLEventCell = NULL; + + /* + * On the very first call to this function, we first use the given relation + * name to get to the relation. We then recreate the list of DDL statements + * issued for this relation, and save the first statement's position in the + * function context. + */ + if (SRF_IS_FIRSTCALL()) + { + text *relationName = PG_GETARG_TEXT_P(0); + Oid relationId = ResolveRelationId(relationName); + + MemoryContext oldContext = NULL; + List *tableDDLEventList = NIL; + + /* create a function context for cross-call persistence */ + functionContext = SRF_FIRSTCALL_INIT(); + + /* switch to memory context appropriate for multiple function calls */ + oldContext = MemoryContextSwitchTo(functionContext->multi_call_memory_ctx); + + /* allocate DDL statements, and then save position in DDL statements */ + tableDDLEventList = GetTableDDLEvents(relationId); + tableDDLEventCell = list_head(tableDDLEventList); + + functionContext->user_fctx = tableDDLEventCell; + + MemoryContextSwitchTo(oldContext); + } + + /* + * On every call to this function, we get the current position in the + * statement list. We then iterate to the next position in the list and + * return the current statement, if we have not yet reached the end of + * list. + */ + functionContext = SRF_PERCALL_SETUP(); + + tableDDLEventCell = (ListCell *) functionContext->user_fctx; + if (tableDDLEventCell != NULL) + { + char *ddlStatement = (char *) lfirst(tableDDLEventCell); + text *ddlStatementText = cstring_to_text(ddlStatement); + + functionContext->user_fctx = lnext(tableDDLEventCell); + + SRF_RETURN_NEXT(functionContext, PointerGetDatum(ddlStatementText)); + } + else + { + SRF_RETURN_DONE(functionContext); + } +} + + +/* + * master_get_new_shardid allocates and returns a unique shardId for the shard + * to be created. This allocation occurs both in shared memory and in write + * ahead logs; writing to logs avoids the risk of having shardId collisions. + * + * Please note that the caller is still responsible for finalizing shard data + * and the shardId with the master node. Further note that this function relies + * on an internal sequence created in initdb to generate unique identifiers. + */ +Datum +master_get_new_shardid(PG_FUNCTION_ARGS) +{ + text *sequenceName = cstring_to_text(SHARDID_SEQUENCE_NAME); + Oid sequenceId = ResolveRelationId(sequenceName); + Datum sequenceIdDatum = ObjectIdGetDatum(sequenceId); + + /* generate new and unique shardId from sequence */ + Datum shardIdDatum = DirectFunctionCall1(nextval_oid, sequenceIdDatum); + int64 shardId = DatumGetInt64(shardIdDatum); + + PG_RETURN_INT64(shardId); +} + + +/* + * master_get_local_first_candidate_nodes returns a set of candidate host names + * and port numbers on which to place new shards. The function makes sure to + * always allocate the first candidate node as the node the caller is connecting + * from; and allocates additional nodes until the shard replication factor is + * met. The function errors if the caller's remote node name is not found in the + * membership list, or if the number of available nodes falls short of the + * replication factor. + */ +Datum +master_get_local_first_candidate_nodes(PG_FUNCTION_ARGS) +{ + FuncCallContext *functionContext = NULL; + uint32 desiredNodeCount = 0; + uint32 currentNodeCount = 0; + + if (SRF_IS_FIRSTCALL()) + { + MemoryContext oldContext = NULL; + TupleDesc tupleDescriptor = NULL; + uint32 liveNodeCount = 0; + bool hasOid = false; + + /* create a function context for cross-call persistence */ + functionContext = SRF_FIRSTCALL_INIT(); + + /* switch to memory context appropriate for multiple function calls */ + oldContext = MemoryContextSwitchTo(functionContext->multi_call_memory_ctx); + + functionContext->user_fctx = NIL; + functionContext->max_calls = ShardReplicationFactor; + + /* if enough live nodes, return an extra candidate node as backup */ + liveNodeCount = WorkerGetLiveNodeCount(); + if (liveNodeCount > ShardReplicationFactor) + { + functionContext->max_calls = ShardReplicationFactor + 1; + } + + /* + * This tuple descriptor must match the output parameters declared for + * the function in pg_proc. + */ + tupleDescriptor = CreateTemplateTupleDesc(CANDIDATE_NODE_FIELDS, hasOid); + TupleDescInitEntry(tupleDescriptor, (AttrNumber) 1, "node_name", + TEXTOID, -1, 0); + TupleDescInitEntry(tupleDescriptor, (AttrNumber) 2, "node_port", + INT8OID, -1, 0); + + functionContext->tuple_desc = BlessTupleDesc(tupleDescriptor); + + MemoryContextSwitchTo(oldContext); + } + + functionContext = SRF_PERCALL_SETUP(); + desiredNodeCount = functionContext->max_calls; + currentNodeCount = functionContext->call_cntr; + + if (currentNodeCount < desiredNodeCount) + { + MemoryContext oldContext = NULL; + List *currentNodeList = NIL; + WorkerNode *candidateNode = NULL; + Datum candidateDatum = 0; + + /* switch to memory context appropriate for multiple function calls */ + oldContext = MemoryContextSwitchTo(functionContext->multi_call_memory_ctx); + currentNodeList = functionContext->user_fctx; + + if (currentNodeCount == 0) + { + /* choose first candidate node to be the client's host */ + char *remoteHostname = hostname_client_addr(); + + /* if hostname is localhost.localdomain, change it to localhost */ + int nameCompare = strncmp(remoteHostname, "localhost.localdomain", + WORKER_LENGTH); + if (nameCompare == 0) + { + remoteHostname = pstrdup("localhost"); + } + + candidateNode = WorkerGetNodeWithName(remoteHostname); + if (candidateNode == NULL) + { + ereport(ERROR, (errmsg("could not find worker node for hostname: %s", + remoteHostname))); + } + } + else + { + /* find a candidate node different from those already selected */ + candidateNode = WorkerGetCandidateNode(currentNodeList); + if (candidateNode == NULL) + { + ereport(ERROR, (errmsg("could only find %u of %u required nodes", + currentNodeCount, desiredNodeCount))); + } + } + + currentNodeList = lappend(currentNodeList, candidateNode); + functionContext->user_fctx = currentNodeList; + + MemoryContextSwitchTo(oldContext); + + candidateDatum = WorkerNodeGetDatum(candidateNode, functionContext->tuple_desc); + + SRF_RETURN_NEXT(functionContext, candidateDatum); + } + else + { + SRF_RETURN_DONE(functionContext); + } +} + + +/* + * master_get_round_robin_candidate_nodes returns a set of candidate host names + * and port numbers on which to place new shards. The function uses the round + * robin policy to choose the nodes and tries to ensure that there is an even + * distribution of shards across the worker nodes. This function errors out if + * the number of available nodes falls short of the replication factor. + */ +Datum +master_get_round_robin_candidate_nodes(PG_FUNCTION_ARGS) +{ + uint64 shardId = PG_GETARG_INT64(0); + FuncCallContext *functionContext = NULL; + uint32 desiredNodeCount = 0; + uint32 currentNodeCount = 0; + + if (SRF_IS_FIRSTCALL()) + { + MemoryContext oldContext = NULL; + TupleDesc tupleDescriptor = NULL; + List *workerNodeList = NIL; + TypeFuncClass resultTypeClass = 0; + uint32 workerNodeCount = 0; + + /* create a function context for cross-call persistence */ + functionContext = SRF_FIRSTCALL_INIT(); + + /* switch to memory context appropriate for multiple function calls */ + oldContext = MemoryContextSwitchTo(functionContext->multi_call_memory_ctx); + + /* get the worker node list and sort it for determinism */ + workerNodeList = WorkerNodeList(); + workerNodeList = SortList(workerNodeList, CompareWorkerNodes); + + functionContext->user_fctx = workerNodeList; + functionContext->max_calls = ShardReplicationFactor; + + /* if we enough live nodes, return an extra candidate node as backup */ + workerNodeCount = (uint32) list_length(workerNodeList); + if (workerNodeCount > ShardReplicationFactor) + { + functionContext->max_calls = ShardReplicationFactor + 1; + } + + /* create tuple descriptor for return value */ + resultTypeClass = get_call_result_type(fcinfo, NULL, &tupleDescriptor); + if (resultTypeClass != TYPEFUNC_COMPOSITE) + { + ereport(ERROR, (errmsg("return type must be a row type"))); + } + + functionContext->tuple_desc = tupleDescriptor; + + MemoryContextSwitchTo(oldContext); + } + + functionContext = SRF_PERCALL_SETUP(); + desiredNodeCount = functionContext->max_calls; + currentNodeCount = functionContext->call_cntr; + + if (currentNodeCount < desiredNodeCount) + { + List *workerNodeList = functionContext->user_fctx; + WorkerNode *candidateNode = NULL; + Datum candidateDatum = 0; + + candidateNode = WorkerGetRoundRobinCandidateNode(workerNodeList, shardId, + currentNodeCount); + if (candidateNode == NULL) + { + ereport(ERROR, (errmsg("could only find %u of %u required nodes", + currentNodeCount, desiredNodeCount))); + } + + candidateDatum = WorkerNodeGetDatum(candidateNode, functionContext->tuple_desc); + + SRF_RETURN_NEXT(functionContext, candidateDatum); + } + else + { + SRF_RETURN_DONE(functionContext); + } +} + + +/* + * master_get_active_worker_nodes returns a set of active worker host names and + * port numbers in deterministic order. Currently we assume that all worker + * nodes in pg_worker_list.conf are active. + */ +Datum +master_get_active_worker_nodes(PG_FUNCTION_ARGS) +{ + FuncCallContext *functionContext = NULL; + uint32 workerNodeIndex = 0; + uint32 workerNodeCount = 0; + + if (SRF_IS_FIRSTCALL()) + { + MemoryContext oldContext = NULL; + List *workerNodeList = NIL; + uint32 workerNodeCount = 0; + TupleDesc tupleDescriptor = NULL; + bool hasOid = false; + + /* create a function context for cross-call persistence */ + functionContext = SRF_FIRSTCALL_INIT(); + + /* switch to memory context appropriate for multiple function calls */ + oldContext = MemoryContextSwitchTo(functionContext->multi_call_memory_ctx); + + workerNodeList = WorkerNodeList(); + workerNodeCount = (uint32) list_length(workerNodeList); + + functionContext->user_fctx = workerNodeList; + functionContext->max_calls = workerNodeCount; + + /* + * This tuple descriptor must match the output parameters declared for + * the function in pg_proc. + */ + tupleDescriptor = CreateTemplateTupleDesc(WORKER_NODE_FIELDS, hasOid); + TupleDescInitEntry(tupleDescriptor, (AttrNumber) 1, "node_name", + TEXTOID, -1, 0); + TupleDescInitEntry(tupleDescriptor, (AttrNumber) 2, "node_port", + INT8OID, -1, 0); + + functionContext->tuple_desc = BlessTupleDesc(tupleDescriptor); + + MemoryContextSwitchTo(oldContext); + } + + functionContext = SRF_PERCALL_SETUP(); + workerNodeIndex = functionContext->call_cntr; + workerNodeCount = functionContext->max_calls; + + if (workerNodeIndex < workerNodeCount) + { + List *workerNodeList = functionContext->user_fctx; + WorkerNode *workerNode = list_nth(workerNodeList, workerNodeIndex); + + Datum workerNodeDatum = WorkerNodeGetDatum(workerNode, + functionContext->tuple_desc); + + SRF_RETURN_NEXT(functionContext, workerNodeDatum); + } + else + { + SRF_RETURN_DONE(functionContext); + } +} + + +/* Finds the relationId from a potentially qualified relation name. */ +Oid +ResolveRelationId(text *relationName) +{ + List *relationNameList = NIL; + RangeVar *relation = NULL; + Oid relationId = InvalidOid; + bool failOK = false; /* error if relation cannot be found */ + + /* resolve relationId from passed in schema and relation name */ + relationNameList = textToQualifiedNameList(relationName); + relation = makeRangeVarFromNameList(relationNameList); + relationId = RangeVarGetRelid(relation, NoLock, failOK); + + return relationId; +} + + +/* + * GetTableDDLEvents takes in a relationId, and returns the list of DDL commands + * needed to reconstruct the relation. These DDL commands are all palloced; and + * include the table's schema definition, optional column storage and statistics + * definitions, and index and constraint defitions. + */ +List * +GetTableDDLEvents(Oid relationId) +{ + List *tableDDLEventList = NIL; + char tableType = 0; + char *tableSchemaDef = NULL; + char *tableColumnOptionsDef = NULL; + char *schemaName = NULL; + Oid schemaId = InvalidOid; + + Relation pgIndex = NULL; + SysScanDesc scanDescriptor = NULL; + ScanKeyData scanKey[1]; + int scanKeyCount = 1; + HeapTuple heapTuple = NULL; + + /* if foreign table, fetch extension and server definitions */ + tableType = get_rel_relkind(relationId); + if (tableType == RELKIND_FOREIGN_TABLE) + { + char *extensionDef = pg_get_extensiondef_string(relationId); + char *serverDef = pg_get_serverdef_string(relationId); + + if (extensionDef != NULL) + { + tableDDLEventList = lappend(tableDDLEventList, extensionDef); + } + tableDDLEventList = lappend(tableDDLEventList, serverDef); + } + + /* create schema if the table is not in the default namespace (public) */ + schemaId = get_rel_namespace(relationId); + schemaName = get_namespace_name(schemaId); + if (strncmp(schemaName, "public", NAMEDATALEN) != 0) + { + StringInfo schemaNameDef = makeStringInfo(); + appendStringInfo(schemaNameDef, CREATE_SCHEMA_COMMAND, schemaName); + + tableDDLEventList = lappend(tableDDLEventList, schemaNameDef->data); + } + + /* fetch table schema and column option definitions */ + tableSchemaDef = pg_get_tableschemadef_string(relationId); + tableColumnOptionsDef = pg_get_tablecolumnoptionsdef_string(relationId); + + tableDDLEventList = lappend(tableDDLEventList, tableSchemaDef); + if (tableColumnOptionsDef != NULL) + { + tableDDLEventList = lappend(tableDDLEventList, tableColumnOptionsDef); + } + + /* open system catalog and scan all indexes that belong to this table */ + pgIndex = heap_open(IndexRelationId, AccessShareLock); + + ScanKeyInit(&scanKey[0], Anum_pg_index_indrelid, + BTEqualStrategyNumber, F_OIDEQ, relationId); + + scanDescriptor = systable_beginscan(pgIndex, + IndexIndrelidIndexId, true, /* indexOK */ + NULL, scanKeyCount, scanKey); + + heapTuple = systable_getnext(scanDescriptor); + while (HeapTupleIsValid(heapTuple)) + { + Form_pg_index indexForm = (Form_pg_index) GETSTRUCT(heapTuple); + Oid indexId = indexForm->indexrelid; + bool isConstraint = false; + char *statementDef = NULL; + + /* + * A primary key index is always created by a constraint statement. + * A unique key index is created by a constraint if and only if the + * index has a corresponding constraint entry in pg_depend. Any other + * index form is never associated with a constraint. + */ + if (indexForm->indisprimary) + { + isConstraint = true; + } + else if (indexForm->indisunique) + { + Oid constraintId = get_index_constraint(indexId); + isConstraint = OidIsValid(constraintId); + } + else + { + isConstraint = false; + } + + /* get the corresponding constraint or index statement */ + if (isConstraint) + { + Oid constraintId = get_index_constraint(indexId); + Assert(constraintId != InvalidOid); + +#if (PG_VERSION_NUM >= 90500) + statementDef = pg_get_constraintdef_command(constraintId); +#else + statementDef = pg_get_constraintdef_string(constraintId); +#endif + } + else + { + statementDef = pg_get_indexdef_string(indexId); + } + + /* append found constraint or index definition to the list */ + tableDDLEventList = lappend(tableDDLEventList, statementDef); + + /* if table is clustered on this index, append definition to the list */ + if (indexForm->indisclustered) + { + char *clusteredDef = pg_get_indexclusterdef_string(indexId); + Assert(clusteredDef != NULL); + + tableDDLEventList = lappend(tableDDLEventList, clusteredDef); + } + + heapTuple = systable_getnext(scanDescriptor); + } + + /* clean up scan and close system catalog */ + systable_endscan(scanDescriptor); + heap_close(pgIndex, AccessShareLock); + + return tableDDLEventList; +} + + +/* + * hostname_client_addr allocates memory for the connecting client's fully + * qualified hostname, and returns this name. If there is no such connection or + * the connection is over Unix domain socket, the function errors. + */ +static char * +hostname_client_addr(void) +{ + Port *port = MyProcPort; + char *remoteHost = NULL; + int remoteHostLen = NI_MAXHOST; + int flags = NI_NAMEREQD; /* require fully qualified hostname */ + int nameFound = 0; + + if (port == NULL) + { + ereport(ERROR, (errmsg("cannot find tcp/ip connection to client"))); + } + + switch (port->raddr.addr.ss_family) + { + case AF_INET: +#ifdef HAVE_IPV6 + case AF_INET6: +#endif + break; + default: + ereport(ERROR, (errmsg("invalid address family in connection"))); + break; + } + + remoteHost = palloc0(remoteHostLen); + + nameFound = pg_getnameinfo_all(&port->raddr.addr, port->raddr.salen, + remoteHost, remoteHostLen, NULL, 0, flags); + if (nameFound != 0) + { + ereport(ERROR, (errmsg("could not resolve client hostname: %s", + gai_strerror(nameFound)))); + } + + return remoteHost; +} + + +/* + * WorkerNodeGetDatum converts the worker node passed to it into its datum + * representation. To do this, the function first creates the heap tuple from + * the worker node name and port. Then, the function converts the heap tuple + * into a datum and returns it. + */ +static Datum +WorkerNodeGetDatum(WorkerNode *workerNode, TupleDesc tupleDescriptor) +{ + Datum values[WORKER_NODE_FIELDS]; + bool isNulls[WORKER_NODE_FIELDS]; + HeapTuple workerNodeTuple = NULL; + Datum workerNodeDatum = 0; + + memset(values, 0, sizeof(values)); + memset(isNulls, false, sizeof(isNulls)); + + values[0] = CStringGetTextDatum(workerNode->workerName); + values[1] = Int64GetDatum((int64) workerNode->workerPort); + + workerNodeTuple = heap_form_tuple(tupleDescriptor, values, isNulls); + workerNodeDatum = HeapTupleGetDatum(workerNodeTuple); + + return workerNodeDatum; +} diff --git a/src/backend/distributed/master/master_repair_shards.c b/src/backend/distributed/master/master_repair_shards.c new file mode 100644 index 000000000..a8047771a --- /dev/null +++ b/src/backend/distributed/master/master_repair_shards.c @@ -0,0 +1,264 @@ +/*------------------------------------------------------------------------- + * + * master_repair_shards.c + * + * This file contains functions to repair unhealthy shard placements using data + * from healthy ones. + * + * Copyright (c) 2014-2015, Citus Data, Inc. + * + *------------------------------------------------------------------------- + */ + +#include "postgres.h" +#include "c.h" +#include "fmgr.h" +#include "miscadmin.h" + +#include + +#include "catalog/pg_class.h" +#include "distributed/connection_cache.h" +#include "distributed/master_protocol.h" +#include "distributed/metadata_cache.h" +#include "distributed/multi_router_executor.h" +#include "distributed/resource_lock.h" +#include "distributed/worker_manager.h" +#include "distributed/worker_protocol.h" +#include "lib/stringinfo.h" +#include "nodes/pg_list.h" +#include "storage/lock.h" +#include "utils/builtins.h" +#include "utils/elog.h" +#include "utils/errcodes.h" +#include "utils/lsyscache.h" +#include "utils/palloc.h" + + +/* local function forward declarations */ +static ShardPlacement * SearchShardPlacementInList(List *shardPlacementList, + text *nodeName, uint32 nodePort); +static List * RecreateTableDDLCommandList(Oid relationId); +static bool CopyDataFromFinalizedPlacement(Oid distributedTableId, int64 shardId, + ShardPlacement *healthyPlacement, + ShardPlacement *placementToRepair); + + +/* declarations for dynamic loading */ +PG_FUNCTION_INFO_V1(master_copy_shard_placement); + + +/* + * master_copy_shard_placement implements a user-facing UDF to copy data from + * a healthy (source) node to an inactive (target) node. To accomplish this it + * entirely recreates the table structure before copying all data. During this + * time all modifications are paused to the shard. After successful repair, the + * inactive placement is marked healthy and modifications may continue. If the + * repair fails at any point, this function throws an error, leaving the node + * in an unhealthy state. + */ +Datum +master_copy_shard_placement(PG_FUNCTION_ARGS) +{ + int64 shardId = PG_GETARG_INT64(0); + text *sourceNodeName = PG_GETARG_TEXT_P(1); + int32 sourceNodePort = PG_GETARG_INT32(2); + text *targetNodeName = PG_GETARG_TEXT_P(3); + int32 targetNodePort = PG_GETARG_INT32(4); + ShardInterval *shardInterval = LoadShardInterval(shardId); + Oid distributedTableId = shardInterval->relationId; + + List *shardPlacementList = NIL; + ShardPlacement *sourcePlacement = NULL; + ShardPlacement *targetPlacement = NULL; + WorkerNode *targetNode = NULL; + List *ddlCommandList = NIL; + bool dataCopied = false; + char relationKind = '\0'; + + /* + * By taking an exclusive lock on the shard, we both stop all modifications + * (INSERT, UPDATE, or DELETE) and prevent concurrent repair operations from + * being able to operate on this shard. + */ + LockShardResource(shardId, ExclusiveLock); + + /* + * We've stopped data modifications of this shard, but we plan to move + * a placement to the healthy state, so we need to grab a shard metadata + * lock (in exclusive mode) as well. + */ + LockShardDistributionMetadata(shardId, ExclusiveLock); + + shardPlacementList = ShardPlacementList(shardId); + sourcePlacement = SearchShardPlacementInList(shardPlacementList, sourceNodeName, + sourceNodePort); + if (sourcePlacement->shardState != FILE_FINALIZED) + { + ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("source placement must be in finalized state"))); + } + + targetPlacement = SearchShardPlacementInList(shardPlacementList, targetNodeName, + targetNodePort); + if (targetPlacement->shardState != FILE_INACTIVE) + { + ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("target placement must be in inactive state"))); + } + + relationKind = get_rel_relkind(distributedTableId); + if (relationKind == RELKIND_FOREIGN_TABLE) + { + ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("cannot repair shard"), + errdetail("Repairing shards backed by foreign tables is " + "not supported."))); + } + + targetNode = palloc0(sizeof(WorkerNode)); + targetNode->inWorkerFile = true; + strlcpy(targetNode->workerName, targetPlacement->nodeName, WORKER_LENGTH); + targetNode->workerPort = targetPlacement->nodePort; + + /* retrieve DDL commands needed to drop and recreate table*/ + ddlCommandList = RecreateTableDDLCommandList(distributedTableId); + + /* remove existing (unhealthy) placement row; CreateShardPlacements will recreate */ + DeleteShardPlacementRow(targetPlacement->shardId, targetPlacement->nodeName, + targetPlacement->nodePort); + + /* finally, drop/recreate remote table and add back row (in healthy state) */ + CreateShardPlacements(shardId, ddlCommandList, list_make1(targetNode), 0, 1); + + HOLD_INTERRUPTS(); + + dataCopied = CopyDataFromFinalizedPlacement(distributedTableId, shardId, + sourcePlacement, targetPlacement); + if (!dataCopied) + { + ereport(ERROR, (errmsg("could not copy shard data"), + errhint("Consult recent messages in the server logs for " + "details."))); + } + + RESUME_INTERRUPTS(); + + PG_RETURN_VOID(); +} + + +/* + * SearchShardPlacementInList searches a provided list for a shard placement + * with the specified node name and port. This function throws an error if no + * such placement exists in the provided list. + */ +static ShardPlacement * +SearchShardPlacementInList(List *shardPlacementList, text *nodeNameText, uint32 nodePort) +{ + ListCell *shardPlacementCell = NULL; + ShardPlacement *matchingPlacement = NULL; + char *nodeName = text_to_cstring(nodeNameText); + + foreach(shardPlacementCell, shardPlacementList) + { + ShardPlacement *shardPlacement = lfirst(shardPlacementCell); + + if (strncmp(nodeName, shardPlacement->nodeName, MAX_NODE_LENGTH) == 0 && + nodePort == shardPlacement->nodePort) + { + matchingPlacement = shardPlacement; + break; + } + } + + if (matchingPlacement == NULL) + { + ereport(ERROR, (errcode(ERRCODE_DATA_EXCEPTION), + errmsg("could not find placement matching \"%s:%d\"", + nodeName, nodePort), + errhint("Confirm the placement still exists and try again."))); + } + + return matchingPlacement; +} + + +/* + * RecreateTableDDLCommandList returns a list of DDL statements similar to that + * returned by GetTableDDLEvents except that the list begins with a "DROP TABLE" + * or "DROP FOREIGN TABLE" statement to facilitate total recreation of a placement. + */ +static List * +RecreateTableDDLCommandList(Oid relationId) +{ + char *relationName = get_rel_name(relationId); + StringInfo dropCommand = makeStringInfo(); + List *createCommandList = NIL; + List *dropCommandList = NIL; + List *recreateCommandList = NIL; + char relationKind = get_rel_relkind(relationId); + + /* build appropriate DROP command based on relation kind */ + if (relationKind == RELKIND_RELATION) + { + appendStringInfo(dropCommand, DROP_REGULAR_TABLE_COMMAND, + quote_identifier(relationName)); + } + else if (relationKind == RELKIND_FOREIGN_TABLE) + { + appendStringInfo(dropCommand, DROP_FOREIGN_TABLE_COMMAND, + quote_identifier(relationName)); + } + else + { + ereport(ERROR, (errcode(ERRCODE_WRONG_OBJECT_TYPE), + errmsg("repair target is not a regular or foreign table"))); + } + + dropCommandList = list_make1(dropCommand->data); + + createCommandList = GetTableDDLEvents(relationId); + + recreateCommandList = list_concat(dropCommandList, createCommandList); + + return recreateCommandList; +} + + +/* + * CopyDataFromFinalizedPlacement copies a the data for a shard (identified by + * a relation and shard identifier) from a healthy placement to one needing + * repair. The unhealthy placement must already have an empty relation in place + * to receive rows from the healthy placement. This function returns a boolean + * indicating success or failure. + */ +static bool +CopyDataFromFinalizedPlacement(Oid distributedTableId, int64 shardId, + ShardPlacement *healthyPlacement, + ShardPlacement *placementToRepair) +{ + char *relationName = get_rel_name(distributedTableId); + const char *shardName = NULL; + StringInfo copyRelationQuery = makeStringInfo(); + List *queryResultList = NIL; + bool copySuccessful = false; + + AppendShardIdToName(&relationName, shardId); + shardName = quote_identifier(relationName); + + appendStringInfo(copyRelationQuery, WORKER_APPEND_TABLE_TO_SHARD, + quote_literal_cstr(shardName), /* table to append */ + quote_literal_cstr(shardName), /* remote table name */ + quote_literal_cstr(healthyPlacement->nodeName), /* remote host */ + healthyPlacement->nodePort); /* remote port */ + + queryResultList = ExecuteRemoteQuery(placementToRepair->nodeName, + placementToRepair->nodePort, copyRelationQuery); + if (queryResultList != NIL) + { + copySuccessful = true; + } + + return copySuccessful; +} diff --git a/src/backend/distributed/master/master_stage_protocol.c b/src/backend/distributed/master/master_stage_protocol.c new file mode 100644 index 000000000..1c13237cc --- /dev/null +++ b/src/backend/distributed/master/master_stage_protocol.c @@ -0,0 +1,550 @@ +/*------------------------------------------------------------------------- + * + * master_stage_protocol.c + * + * Routines for staging PostgreSQL table data as shards into the distributed + * cluster. These user-defined functions are similar to the psql-side \stage + * command, but also differ from them in that users stage data from tables and + * not files, and that they can also append to existing shards. + * + * Copyright (c) 2013, Citus Data, Inc. + * + * $Id$ + * + *------------------------------------------------------------------------- + */ + +#include "postgres.h" +#include "funcapi.h" +#include "miscadmin.h" + +#include "access/htup_details.h" +#include "access/xact.h" +#include "catalog/indexing.h" +#include "distributed/master_metadata_utility.h" +#include "distributed/master_protocol.h" +#include "distributed/metadata_cache.h" +#include "distributed/multi_join_order.h" +#include "distributed/pg_dist_partition.h" +#include "distributed/pg_dist_shard.h" +#include "distributed/resource_lock.h" +#include "distributed/worker_manager.h" +#include "distributed/worker_protocol.h" +#include "utils/builtins.h" +#include "utils/fmgroids.h" +#include "utils/inval.h" +#include "utils/lsyscache.h" +#include "utils/syscache.h" +#include "utils/rel.h" +#include "utils/tqual.h" + + +/* Local functions forward declarations */ +static bool WorkerCreateShard(char *nodeName, uint32 nodePort, + uint64 shardId, List *ddlCommandList); +static bool WorkerShardStats(char *nodeName, uint32 nodePort, Oid relationId, + char *shardName, uint64 *shardLength, + text **shardMinValue, text **shardMaxValue); +static uint64 WorkerTableSize(char *nodeName, uint32 nodePort, char *tableName); +static StringInfo WorkerPartitionValue(char *nodeName, uint32 nodePort, Oid relationId, + char *shardName, char *selectQuery); + + +/* exports for SQL callable functions */ +PG_FUNCTION_INFO_V1(master_create_empty_shard); +PG_FUNCTION_INFO_V1(master_append_table_to_shard); + + +/* + * master_create_empty_shard creates an empty shard for the given distributed + * table. For this, the function first gets a list of candidate nodes, connects + * to these nodes, and issues DDL commands on the nodes to create empty shard + * placements. The function then updates metadata on the master node to make + * this shard (and its placements) visible. + */ +Datum +master_create_empty_shard(PG_FUNCTION_ARGS) +{ + text *relationNameText = PG_GETARG_TEXT_P(0); + char *relationName = text_to_cstring(relationNameText); + Datum shardIdDatum = 0; + int64 shardId = INVALID_SHARD_ID; + List *ddlEventList = NULL; + uint32 attemptableNodeCount = 0; + uint32 liveNodeCount = 0; + + uint32 candidateNodeCount = 0; + List *candidateNodeList = NIL; + text *nullMinValue = NULL; + text *nullMaxValue = NULL; + char tableType = 0; + char partitionMethod = 0; + + Oid relationId = ResolveRelationId(relationNameText); + CheckDistributedTable(relationId); + + tableType = get_rel_relkind(relationId); + if (tableType != RELKIND_RELATION) + { + ereport(ERROR, (errmsg("relation \"%s\" is not a regular table", relationName))); + } + + partitionMethod = PartitionMethod(relationId); + if (partitionMethod == DISTRIBUTE_BY_HASH) + { + ereport(ERROR, (errmsg("relation \"%s\" is a hash partitioned table", + relationName), + errdetail("We currently don't support creating shards " + "on hash-partitioned tables"))); + } + + /* generate new and unique shardId from sequence */ + shardIdDatum = master_get_new_shardid(NULL); + shardId = DatumGetInt64(shardIdDatum); + + /* get table DDL commands to replay on the worker node */ + ddlEventList = GetTableDDLEvents(relationId); + + /* if enough live nodes, add an extra candidate node as backup */ + attemptableNodeCount = ShardReplicationFactor; + liveNodeCount = WorkerGetLiveNodeCount(); + if (liveNodeCount > ShardReplicationFactor) + { + attemptableNodeCount = ShardReplicationFactor + 1; + } + + /* first retrieve a list of random nodes for shard placements */ + while (candidateNodeCount < attemptableNodeCount) + { + WorkerNode *candidateNode = WorkerGetCandidateNode(candidateNodeList); + if (candidateNode == NULL) + { + ereport(ERROR, (errmsg("could only find %u of %u possible nodes", + candidateNodeCount, attemptableNodeCount))); + } + + candidateNodeList = lappend(candidateNodeList, candidateNode); + candidateNodeCount++; + } + + CreateShardPlacements(shardId, ddlEventList, candidateNodeList, 0, + ShardReplicationFactor); + + InsertShardRow(relationId, shardId, SHARD_STORAGE_TABLE, nullMinValue, nullMaxValue); + + PG_RETURN_INT64(shardId); +} + + +/* + * master_append_table_to_shard appends the given table's contents to the given + * shard, and updates shard metadata on the master node. If the function fails + * to append table data to all shard placements, it doesn't update any metadata + * and errors out. Else if the function fails to append table data to some of + * the shard placements, it marks those placements as invalid. These invalid + * placements will get cleaned up during shard rebalancing. + */ +Datum +master_append_table_to_shard(PG_FUNCTION_ARGS) +{ + uint64 shardId = PG_GETARG_INT64(0); + text *sourceTableNameText = PG_GETARG_TEXT_P(1); + text *sourceNodeNameText = PG_GETARG_TEXT_P(2); + uint32 sourceNodePort = PG_GETARG_UINT32(3); + char *sourceTableName = text_to_cstring(sourceTableNameText); + char *sourceNodeName = text_to_cstring(sourceNodeNameText); + + char *shardName = NULL; + List *shardPlacementList = NIL; + List *succeededPlacementList = NIL; + List *failedPlacementList = NIL; + ListCell *shardPlacementCell = NULL; + ListCell *succeededPlacementCell = NULL; + ListCell *failedPlacementCell = NULL; + bool statsOK = false; + uint64 newShardLength = 0; + uint64 shardMaxSizeInBytes = 0; + float4 shardFillLevel = 0.0; + text *newMinValue = NULL; + text *newMaxValue = NULL; + char partitionMethod = 0; + + ShardInterval *shardInterval = LoadShardInterval(shardId); + Oid relationId = shardInterval->relationId; + + char storageType = shardInterval->storageType; + if (storageType != SHARD_STORAGE_TABLE) + { + ereport(ERROR, (errmsg("cannot append to shardId " UINT64_FORMAT, shardId), + errdetail("The underlying shard is not a regular table"))); + } + + partitionMethod = PartitionMethod(relationId); + if (partitionMethod == DISTRIBUTE_BY_HASH) + { + ereport(ERROR, (errmsg("cannot append to shardId " UINT64_FORMAT, shardId), + errdetail("We currently don't support appending to shards " + "in hash-partitioned tables"))); + } + + /* + * We lock on the shardId, but do not unlock. When the function returns, and + * the transaction for this function commits, this lock will automatically + * be released. This ensures appends to a shard happen in a serial manner. + */ + LockShardResource(shardId, AccessExclusiveLock); + + /* if shard doesn't have an alias, extend regular table name */ + shardName = LoadShardAlias(relationId, shardId); + if (shardName == NULL) + { + shardName = get_rel_name(relationId); + AppendShardIdToName(&shardName, shardId); + } + + shardPlacementList = FinalizedShardPlacementList(shardId); + if (shardPlacementList == NIL) + { + ereport(ERROR, (errmsg("could not find any shard placements for shardId " + UINT64_FORMAT, shardId), + errhint("Try running master_create_empty_shard() first"))); + } + + /* issue command to append table to each shard placement */ + foreach(shardPlacementCell, shardPlacementList) + { + ShardPlacement *shardPlacement = (ShardPlacement *) lfirst(shardPlacementCell); + char *workerName = shardPlacement->nodeName; + uint32 workerPort = shardPlacement->nodePort; + List *queryResultList = NIL; + + StringInfo workerAppendQuery = makeStringInfo(); + appendStringInfo(workerAppendQuery, WORKER_APPEND_TABLE_TO_SHARD, + quote_literal_cstr(shardName), + quote_literal_cstr(sourceTableName), + quote_literal_cstr(sourceNodeName), sourceNodePort); + + queryResultList = ExecuteRemoteQuery(workerName, workerPort, workerAppendQuery); + if (queryResultList != NIL) + { + succeededPlacementList = lappend(succeededPlacementList, shardPlacement); + } + else + { + failedPlacementList = lappend(failedPlacementList, shardPlacement); + } + } + + /* before updating metadata, check that we appended to at least one shard */ + if (succeededPlacementList == NIL) + { + ereport(ERROR, (errmsg("could not append table to any shard placement"))); + } + + /* make sure we don't process cancel signals */ + HOLD_INTERRUPTS(); + + /* mark shard placements that we couldn't append to as inactive */ + foreach(failedPlacementCell, failedPlacementList) + { + ShardPlacement *placement = (ShardPlacement *) lfirst(failedPlacementCell); + char *workerName = placement->nodeName; + uint32 workerPort = placement->nodePort; + uint64 oldShardLength = placement->shardLength; + + DeleteShardPlacementRow(shardId, workerName, workerPort); + InsertShardPlacementRow(shardId, FILE_INACTIVE, oldShardLength, + workerName, workerPort); + + ereport(WARNING, (errmsg("could not append table to shard \"%s\" on node " + "\"%s:%u\"", shardName, workerName, workerPort), + errdetail("Marking this shard placement as inactive"))); + } + + RESUME_INTERRUPTS(); + + /* get appended shard's statistics from a shard placement */ + foreach(succeededPlacementCell, succeededPlacementList) + { + ShardPlacement *placement = (ShardPlacement *) lfirst(succeededPlacementCell); + char *workerName = placement->nodeName; + uint32 workerPort = placement->nodePort; + + statsOK = WorkerShardStats(workerName, workerPort, relationId, shardName, + &newShardLength, &newMinValue, &newMaxValue); + if (statsOK) + { + break; + } + } + + /* + * If for some reason we appended data to a shard, but failed to retrieve + * statistics we just WARN here to avoid losing shard-state updates. Note + * that this means we will return 0 as the shard fill-factor, and this shard + * also won't be pruned as the statistics will be empty. If the failure was + * transient, a subsequent append call will fetch the correct statistics. + */ + if (!statsOK) + { + ereport(WARNING, (errmsg("could not get statistics for shard placement"), + errdetail("Setting shard statistics to NULL"))); + } + + /* make sure we don't process cancel signals */ + HOLD_INTERRUPTS(); + + /* update metadata for each shard placement we appended to */ + succeededPlacementCell = NULL; + foreach(succeededPlacementCell, succeededPlacementList) + { + ShardPlacement *placement = (ShardPlacement *) lfirst(succeededPlacementCell); + char *workerName = placement->nodeName; + uint32 workerPort = placement->nodePort; + + DeleteShardPlacementRow(shardId, workerName, workerPort); + InsertShardPlacementRow(shardId, FILE_FINALIZED, newShardLength, + workerName, workerPort); + } + + DeleteShardRow(shardId); + InsertShardRow(relationId, shardId, storageType, newMinValue, newMaxValue); + + if (QueryCancelPending) + { + ereport(WARNING, (errmsg("cancel requests are ignored during table appends"))); + QueryCancelPending = false; + } + + RESUME_INTERRUPTS(); + + /* calculate ratio of current shard size compared to shard max size */ + shardMaxSizeInBytes = (int64) ShardMaxSize * 1024L; + shardFillLevel = ((float4) newShardLength / (float4) shardMaxSizeInBytes); + + PG_RETURN_FLOAT4(shardFillLevel); +} + + +/* + * CheckDistributedTable checks if the given relationId corresponds to a + * distributed table. If it does not, the function errors out. + */ +void +CheckDistributedTable(Oid relationId) +{ + char *relationName = get_rel_name(relationId); + + /* check that the relationId belongs to a table */ + char tableType = get_rel_relkind(relationId); + if (!(tableType == RELKIND_RELATION || tableType == RELKIND_FOREIGN_TABLE)) + { + ereport(ERROR, (errmsg("relation \"%s\" is not a table", relationName))); + } + + if (!IsDistributedTable(relationId)) + { + ereport(ERROR, (errmsg("relation \"%s\" is not a distributed table", + relationName))); + } +} + + +/* + * CreateShardPlacements attempts to create a certain number of placements + * (provided by the replicationFactor argument) on the provided list of worker + * nodes. Beginning at the provided start index, DDL commands are attempted on + * worker nodes (via WorkerCreateShards). If there are more worker nodes than + * required for replication, one remote failure is tolerated. If the provided + * replication factor is not attained, an error is raised (placements remain on + * nodes if some DDL commands had been successful). + */ +void +CreateShardPlacements(int64 shardId, List *ddlEventList, List *workerNodeList, + int workerStartIndex, int replicationFactor) +{ + int attemptCount = replicationFactor; + int workerNodeCount = list_length(workerNodeList); + int placementsCreated = 0; + int attemptNumber = 0; + + /* if we have enough nodes, add an extra placement attempt for backup */ + if (workerNodeCount > replicationFactor) + { + attemptCount++; + } + + for (attemptNumber = 0; attemptNumber < attemptCount; attemptNumber++) + { + int workerNodeIndex = (workerStartIndex + attemptNumber) % workerNodeCount; + WorkerNode *workerNode = (WorkerNode *) list_nth(workerNodeList, workerNodeIndex); + char *nodeName = workerNode->workerName; + uint32 nodePort = workerNode->workerPort; + + bool created = WorkerCreateShard(nodeName, nodePort, shardId, ddlEventList); + if (created) + { + const RelayFileState shardState = FILE_FINALIZED; + const uint64 shardSize = 0; + + InsertShardPlacementRow(shardId, shardState, shardSize, nodeName, nodePort); + placementsCreated++; + } + else + { + ereport(WARNING, (errmsg("could not create shard on \"%s:%u\"", + nodeName, nodePort))); + } + + if (placementsCreated >= replicationFactor) + { + break; + } + } + + /* check if we created enough shard replicas */ + if (placementsCreated < replicationFactor) + { + ereport(ERROR, (errmsg("could only create %u of %u of required shard replicas", + placementsCreated, replicationFactor))); + } +} + + +/* + * WorkerCreateShard applies DDL commands for the given shardId to create the + * shard on the worker node. Note that this function opens a new connection for + * each DDL command, and could leave the shard in an half-initialized state. + */ +static bool +WorkerCreateShard(char *nodeName, uint32 nodePort, + uint64 shardId, List *ddlCommandList) +{ + bool shardCreated = true; + ListCell *ddlCommandCell = NULL; + + foreach(ddlCommandCell, ddlCommandList) + { + char *ddlCommand = (char *) lfirst(ddlCommandCell); + char *escapedDDLCommand = quote_literal_cstr(ddlCommand); + List *queryResultList = NIL; + + StringInfo applyDDLCommand = makeStringInfo(); + appendStringInfo(applyDDLCommand, WORKER_APPLY_SHARD_DDL_COMMAND, + shardId, escapedDDLCommand); + + queryResultList = ExecuteRemoteQuery(nodeName, nodePort, applyDDLCommand); + if (queryResultList == NIL) + { + shardCreated = false; + break; + } + } + + return shardCreated; +} + + +/* + * WorkerShardStats queries the worker node, and retrieves shard statistics that + * we assume have changed after new table data have been appended to the shard. + */ +static bool +WorkerShardStats(char *nodeName, uint32 nodePort, Oid relationId, char *shardName, + uint64 *shardLength, text **shardMinValue, text **shardMaxValue) +{ + bool shardStatsOK = true; + + PG_TRY(); + { + uint64 tableSize = WorkerTableSize(nodeName, nodePort, shardName); + StringInfo minValue = WorkerPartitionValue(nodeName, nodePort, relationId, + shardName, SHARD_MIN_VALUE_QUERY); + StringInfo maxValue = WorkerPartitionValue(nodeName, nodePort, relationId, + shardName, SHARD_MAX_VALUE_QUERY); + + (*shardLength) = tableSize; + (*shardMinValue) = cstring_to_text_with_len(minValue->data, minValue->len); + (*shardMaxValue) = cstring_to_text_with_len(maxValue->data, maxValue->len); + } + PG_CATCH(); + { + shardStatsOK = false; + } + PG_END_TRY(); + + return shardStatsOK; +} + + +/* + * WorkerTableSize queries the worker node to extract the disk space used by the + * given relation. The function assumes the relation represents a regular table. + */ +static uint64 +WorkerTableSize(char *nodeName, uint32 nodePort, char *tableName) +{ + uint64 tableSize = 0; + List *queryResultList = NIL; + StringInfo tableSizeString = NULL; + char *tableSizeStringEnd = NULL; + + StringInfo tableSizeQuery = makeStringInfo(); + appendStringInfo(tableSizeQuery, SHARD_TABLE_SIZE_QUERY, tableName); + + queryResultList = ExecuteRemoteQuery(nodeName, nodePort, tableSizeQuery); + if (queryResultList == NIL) + { + ereport(ERROR, (errmsg("could not receive table size from node " + "\"%s:%u\"", nodeName, nodePort))); + } + + tableSizeString = (StringInfo) linitial(queryResultList); + + errno = 0; + tableSize = strtoull(tableSizeString->data, &tableSizeStringEnd, 0); + if (errno != 0 || (*tableSizeStringEnd) != '\0') + { + ereport(ERROR, (errmsg("could not extract table size for table \"%s\"", + tableName))); + } + + return tableSize; +} + + +/* + * WorkerPartitionValue helps in extracting partition column's min or max value + * from the given shard. For this, the function resolves the given distributed + * relation's partition column, connects to the worker node, and runs a select + * query on the given shard. + */ +static StringInfo +WorkerPartitionValue(char *nodeName, uint32 nodePort, Oid relationId, + char *shardName, char *selectQuery) +{ + StringInfo partitionValue = NULL; + List *queryResultList = NIL; + uint32 unusedTableId = 1; + + Var *partitionColumn = PartitionColumn(relationId, unusedTableId); + char *partitionColumnName = get_attname(relationId, partitionColumn->varattno); + + StringInfo partitionValueQuery = makeStringInfo(); + appendStringInfo(partitionValueQuery, selectQuery, partitionColumnName, shardName); + + /* + * Note that the following call omits the partition column value's size, and + * simply casts the results to a (char *). If the user partitioned the table + * on a binary byte array, this approach fails and should be fixed. + */ + queryResultList = ExecuteRemoteQuery(nodeName, nodePort, partitionValueQuery); + if (queryResultList == NIL) + { + ereport(ERROR, (errmsg("could not receive shard min/max values from node " + "\"%s:%u\"", nodeName, nodePort))); + } + + partitionValue = (StringInfo) linitial(queryResultList); + return partitionValue; +} diff --git a/src/backend/distributed/master/pg_worker_list.conf.sample b/src/backend/distributed/master/pg_worker_list.conf.sample new file mode 100644 index 000000000..a9e5d740b --- /dev/null +++ b/src/backend/distributed/master/pg_worker_list.conf.sample @@ -0,0 +1,27 @@ +# ------------------------------------------ +# Citus Database Worker Node Membership List +# ------------------------------------------ +# +# This file contains list of worker node names; these names are used both for +# initializing the worker nodes, and later for communicating with them. Records +# in this file are in the following format: +# +# HOSTNAME [PORT] [RACK] +# +# (The uppercase items must be replaced by actual values.) +# +# HOSTNAME specifies the DNS resolvable host name for the worker node. In test +# environments, localhost may be used to loopback to the current node. +# +# PORT specifies the port number to connect to at the specified host. This value +# is optional; in its absence, the port configuration value is used as the +# default. +# +# RACK specifies the host's network location for the purposes of performing rack +# aware data distribution. This value is optional; in its absence, a generic +# value is used as the default. + +# Put your actual configuration here +# ---------------------------------- +# +# HOSTNAME [PORT] [RACK] diff --git a/src/backend/distributed/master/worker_node_manager.c b/src/backend/distributed/master/worker_node_manager.c new file mode 100644 index 000000000..9f015d5be --- /dev/null +++ b/src/backend/distributed/master/worker_node_manager.c @@ -0,0 +1,807 @@ +/*------------------------------------------------------------------------- + * + * worker_node_manager.c + * Routines for reading worker nodes from membership file, and allocating + * candidate nodes for shard placement. + * + * Copyright (c) 2012, Citus Data, Inc. + * + * $Id$ + * + *------------------------------------------------------------------------- + */ + +#include "postgres.h" +#include "miscadmin.h" + +#include "commands/dbcommands.h" +#include "distributed/worker_manager.h" +#include "distributed/multi_client_executor.h" +#include "libpq/hba.h" +#include "postmaster/postmaster.h" +#include "storage/fd.h" +#include "storage/ipc.h" +#include "storage/shmem.h" +#include "utils/guc.h" +#include "utils/hsearch.h" +#include "utils/memutils.h" + + +/* Config variables managed via guc.c */ +char *WorkerListFileName; /* location of pg_worker_list.conf */ +int MaxWorkerNodesTracked = 2048; /* determines worker node hash table size */ + +static HTAB *WorkerNodesHash = NULL; /* worker node hash in shared memory */ +static shmem_startup_hook_type prev_shmem_startup_hook = NULL; + + +/* Local functions forward declarations */ +static bool OddNumber(uint32 number); +static WorkerNode * FindRandomNodeNotInList(HTAB *WorkerNodesHash, + List *currentNodeList); +static bool ListMember(List *currentList, WorkerNode *workerNode); +static Size WorkerNodeShmemSize(void); +static void WorkerNodeShmemAndWorkerListInit(void); +static uint32 WorkerNodeHashCode(const void *key, Size keySize); +static int WorkerNodeCompare(const void *lhsKey, const void *rhsKey, Size keySize); +static List * ParseWorkerNodeFile(const char *workerNodeFilename); +static void ResetWorkerNodesHash(HTAB *WorkerNodesHash); +static bool WorkerNodeResponsive(const char *workerName, uint32 workerPort); + + +/* ------------------------------------------------------------ + * Worker node selection functions follow + * ------------------------------------------------------------ + */ + +/* + * WorkerGetCandidateNode takes in a list of worker nodes, and then allocates a + * new worker node. The allocation is performed according to the following + * policy: if the list is empty, a random node is allocated; if the list has one + * node (or an odd number of nodes), the new node is allocated on a different + * rack than the first node; and if the list has two nodes (or an even number of + * nodes), the new node is allocated on the same rack as the first node, but is + * different from all the nodes in the list. This node allocation policy ensures + * that shard locality is maintained within a rack, but no single rack failure + * can result in data loss. + * + * Note that the function returns null if the worker membership list does not + * contain enough nodes to allocate a new worker node. + */ +WorkerNode * +WorkerGetCandidateNode(List *currentNodeList) +{ + WorkerNode *workerNode = NULL; + bool wantSameRack = false; + uint32 tryCount = WORKER_RACK_TRIES; + uint32 tryIndex = 0; + + /* + * We check if the shard has already been placed on all nodes known to us. + * This check is rather defensive, and has the drawback of performing a full + * scan over the worker node hash for determining the number of live nodes. + */ + uint32 currentNodeCount = list_length(currentNodeList); + uint32 liveNodeCount = WorkerGetLiveNodeCount(); + if (currentNodeCount >= liveNodeCount) + { + return NULL; + } + + /* if current node list is empty, randomly pick one node and return */ + if (currentNodeCount == 0) + { + workerNode = FindRandomNodeNotInList(WorkerNodesHash, NIL); + return workerNode; + } + + /* + * If the current list has an odd number of nodes (1, 3, 5, etc), we want to + * place the shard on a different rack than the first node's rack. + * Otherwise, we want to place the shard on the same rack as the first node. + */ + if (OddNumber(currentNodeCount)) + { + wantSameRack = false; + } + else + { + wantSameRack = true; + } + + /* + * We try to find a worker node that fits our rack-aware placement strategy. + * If after a predefined number of tries, we still cannot find such a node, + * we simply give up and return the last worker node we found. + */ + for (tryIndex = 0; tryIndex < tryCount; tryIndex++) + { + WorkerNode *firstNode = (WorkerNode *) linitial(currentNodeList); + char *firstRack = firstNode->workerRack; + char *workerRack = NULL; + bool sameRack = false; + + workerNode = FindRandomNodeNotInList(WorkerNodesHash, currentNodeList); + workerRack = workerNode->workerRack; + + sameRack = (strncmp(workerRack, firstRack, WORKER_LENGTH) == 0); + if ((sameRack && wantSameRack) || (!sameRack && !wantSameRack)) + { + break; + } + } + + return workerNode; +} + + +/* + * WorkerGetRoundRobinCandidateNode takes in a list of worker nodes and returns + * a candidate worker node from that list. To select this node, this function + * uses the round-robin policy. An ideal round-robin implementation requires + * keeping shared state for shard placements; and we instead approximate our + * implementation by relying on the ever-increasing shardId. So, the first + * worker node selected will be the node at the (shardId MOD worker node count) + * index and the remaining candidate nodes will be the next nodes in the list. + * + * Note that the function returns null if the worker membership list does not + * contain enough nodes to place all replicas. + */ +WorkerNode * +WorkerGetRoundRobinCandidateNode(List *workerNodeList, uint64 shardId, + uint32 placementIndex) +{ + uint32 workerNodeCount = list_length(workerNodeList); + WorkerNode *candidateNode = NULL; + + if (placementIndex < workerNodeCount) + { + uint32 candidateNodeIndex = (shardId + placementIndex) % workerNodeCount; + candidateNode = (WorkerNode *) list_nth(workerNodeList, candidateNodeIndex); + } + + return candidateNode; +} + + +/* + * WorkerGetNodeWithName finds and returns a node from the membership list that + * has the given hostname. The function returns null if no such node exists. + */ +WorkerNode * +WorkerGetNodeWithName(const char *hostname) +{ + WorkerNode *workerNode = NULL; + + HASH_SEQ_STATUS status; + hash_seq_init(&status, WorkerNodesHash); + + workerNode = (WorkerNode *) hash_seq_search(&status); + while (workerNode != NULL) + { + if (workerNode->inWorkerFile) + { + int nameCompare = strncmp(workerNode->workerName, hostname, WORKER_LENGTH); + if (nameCompare == 0) + { + hash_seq_term(&status); + break; + } + } + + workerNode = (WorkerNode *) hash_seq_search(&status); + } + + return workerNode; +} + + +/* Returns the number of live nodes in the cluster. */ +uint32 +WorkerGetLiveNodeCount(void) +{ + WorkerNode *workerNode = NULL; + uint32 liveWorkerCount = 0; + + HASH_SEQ_STATUS status; + hash_seq_init(&status, WorkerNodesHash); + + workerNode = (WorkerNode *) hash_seq_search(&status); + while (workerNode != NULL) + { + if (workerNode->inWorkerFile) + { + liveWorkerCount++; + } + + workerNode = (WorkerNode *) hash_seq_search(&status); + } + + return liveWorkerCount; +} + + +/* Inserts the live worker nodes to a list, and returns the list. */ +List * +WorkerNodeList(void) +{ + List *workerNodeList = NIL; + WorkerNode *workerNode = NULL; + + HASH_SEQ_STATUS status; + hash_seq_init(&status, WorkerNodesHash); + + workerNode = (WorkerNode *) hash_seq_search(&status); + while (workerNode != NULL) + { + if (workerNode->inWorkerFile) + { + workerNodeList = lappend(workerNodeList, workerNode); + } + + workerNode = (WorkerNode *) hash_seq_search(&status); + } + + return workerNodeList; +} + + +/* + * WorkerNodeActive looks up a worker node with the given name and port number + * in the current membership list. If such a worker node exists, the function + * returns true. + */ +bool +WorkerNodeActive(const char *nodeName, uint32 nodePort) +{ + bool workerNodeActive = false; + bool handleFound = false; + WorkerNode *workerNode = NULL; + void *hashKey = NULL; + + WorkerNode *searchedNode = (WorkerNode *) palloc0(sizeof(WorkerNode)); + strlcpy(searchedNode->workerName, nodeName, WORKER_LENGTH); + searchedNode->workerPort = nodePort; + + hashKey = (void *) searchedNode; + workerNode = (WorkerNode *) hash_search(WorkerNodesHash, hashKey, + HASH_FIND, &handleFound); + if (workerNode != NULL) + { + if (workerNode->inWorkerFile) + { + workerNodeActive = true; + } + } + + return workerNodeActive; +} + + +/* Returns true if given number is odd; returns false otherwise. */ +static bool +OddNumber(uint32 number) +{ + bool oddNumber = ((number % 2) == 1); + return oddNumber; +} + + +/* + * FindRandomNodeNotInList finds a random node from the shared hash that is not + * a member of the current node list. The caller is responsible for making the + * necessary node count checks to ensure that such a node exists. + * + * Note that this function has a selection bias towards nodes whose positions in + * the shared hash are sequentially adjacent to the positions of nodes that are + * in the current node list. This bias follows from our decision to first pick a + * random node in the hash, and if that node is a member of the current list, to + * simply iterate to the next node in the hash. Overall, this approach trades in + * some selection bias for simplicity in design and for bounded execution time. + */ +static WorkerNode * +FindRandomNodeNotInList(HTAB *WorkerNodesHash, List *currentNodeList) +{ + WorkerNode *workerNode = NULL; + HASH_SEQ_STATUS status; + uint32 workerNodeCount = 0; + uint32 currentNodeCount = 0; + bool lookForWorkerNode = true; + uint32 workerPosition = 0; + uint32 workerIndex = 0; + + workerNodeCount = hash_get_num_entries(WorkerNodesHash); + currentNodeCount = list_length(currentNodeList); + Assert(workerNodeCount > currentNodeCount); + + /* + * We determine a random position within the worker hash between [1, N], + * assuming that the number of elements in the hash is N. We then get to + * this random position by iterating over the worker hash. Please note that + * the random seed has already been set by the postmaster when starting up. + */ + workerPosition = (random() % workerNodeCount) + 1; + hash_seq_init(&status, WorkerNodesHash); + + for (workerIndex = 0; workerIndex < workerPosition; workerIndex++) + { + workerNode = (WorkerNode *) hash_seq_search(&status); + } + + while (lookForWorkerNode) + { + bool listMember = ListMember(currentNodeList, workerNode); + + if (workerNode->inWorkerFile && !listMember) + { + lookForWorkerNode = false; + } + else + { + /* iterate to the next worker node in the hash */ + workerNode = (WorkerNode *) hash_seq_search(&status); + + /* reached end of hash; start from the beginning */ + if (workerNode == NULL) + { + hash_seq_init(&status, WorkerNodesHash); + workerNode = (WorkerNode *) hash_seq_search(&status); + } + } + } + + /* we stopped scanning before completion; therefore clean up scan */ + hash_seq_term(&status); + + return workerNode; +} + + +/* Checks if given worker node is a member of the current list. */ +static bool +ListMember(List *currentList, WorkerNode *workerNode) +{ + bool listMember = false; + Size keySize = WORKER_LENGTH + sizeof(uint32); + + ListCell *currentCell = NULL; + foreach(currentCell, currentList) + { + WorkerNode *currentNode = (WorkerNode *) lfirst(currentCell); + if (WorkerNodeCompare(workerNode, currentNode, keySize) == 0) + { + listMember = true; + } + } + + return listMember; +} + + +/* ------------------------------------------------------------ + * Worker node shared hash functions follow + * ------------------------------------------------------------ + */ + +/* Organize, at startup, that the resources for worker node management are allocated. */ +void +WorkerNodeRegister(void) +{ + RequestAddinShmemSpace(WorkerNodeShmemSize()); + + prev_shmem_startup_hook = shmem_startup_hook; + shmem_startup_hook = WorkerNodeShmemAndWorkerListInit; +} + + +/* Estimates the shared memory size used for managing worker nodes. */ +static Size +WorkerNodeShmemSize(void) +{ + Size size = 0; + Size hashSize = 0; + + hashSize = hash_estimate_size(MaxWorkerNodesTracked, sizeof(WorkerNode)); + size = add_size(size, hashSize); + + return size; +} + + +/* Initializes the shared memory used for managing worker nodes. */ +static void +WorkerNodeShmemAndWorkerListInit(void) +{ + HASHCTL info; + int hashFlags = 0; + long maxTableSize = 0; + long initTableSize = 0; + + maxTableSize = (long) MaxWorkerNodesTracked; + initTableSize = maxTableSize / 8; + + /* + * Allocate the control structure for the hash table that maps worker node + * name and port numbers (char[]:uint32) to general node membership and + * health information. + */ + memset(&info, 0, sizeof(info)); + info.keysize = WORKER_LENGTH + sizeof(uint32); + info.entrysize = sizeof(WorkerNode); + info.hash = WorkerNodeHashCode; + info.match = WorkerNodeCompare; + hashFlags = (HASH_ELEM | HASH_FUNCTION | HASH_COMPARE); + + WorkerNodesHash = ShmemInitHash("Worker Node Hash", + initTableSize, maxTableSize, + &info, hashFlags); + + /* + * Load the intial contents of the worker node hash table from the + * configuration file. + */ + LoadWorkerNodeList(WorkerListFileName); + + if (prev_shmem_startup_hook != NULL) + { + prev_shmem_startup_hook(); + } +} + + +/* + * WorkerNodeHashCode computes the hash code for a worker node from the node's + * host name and port number. Nodes that only differ by their rack locations + * hash to the same value. + */ +static uint32 +WorkerNodeHashCode(const void *key, Size keySize) +{ + const WorkerNode *worker = (const WorkerNode *) key; + const char *workerName = worker->workerName; + const uint32 *workerPort = &(worker->workerPort); + + /* standard hash function outlined in Effective Java, Item 8 */ + uint32 result = 17; + result = 37 * result + string_hash(workerName, WORKER_LENGTH); + result = 37 * result + tag_hash(workerPort, sizeof(uint32)); + return result; +} + + +/* + * CompareWorkerNodes compares two pointers to worker nodes using the exact + * same logic employed by WorkerNodeCompare. + */ +int +CompareWorkerNodes(const void *leftElement, const void *rightElement) +{ + const void *leftWorker = *((const void **) leftElement); + const void *rightWorker = *((const void **) rightElement); + int compare = 0; + Size ignoredKeySize = 0; + + compare = WorkerNodeCompare(leftWorker, rightWorker, ignoredKeySize); + + return compare; +} + + +/* + * WorkerNodeCompare compares two worker nodes by their host name and port + * number. Two nodes that only differ by their rack locations are considered to + * be equal to each other. + */ +static int +WorkerNodeCompare(const void *lhsKey, const void *rhsKey, Size keySize) +{ + const WorkerNode *workerLhs = (const WorkerNode *) lhsKey; + const WorkerNode *workerRhs = (const WorkerNode *) rhsKey; + + int nameCompare = 0; + int portCompare = 0; + + nameCompare = strncmp(workerLhs->workerName, workerRhs->workerName, WORKER_LENGTH); + if (nameCompare != 0) + { + return nameCompare; + } + + portCompare = workerLhs->workerPort - workerRhs->workerPort; + return portCompare; +} + + +/* + * LoadWorkerNodeList reads and parses given membership file, and loads worker + * nodes from this membership file into the shared hash. The function relies on + * hba.c's tokenization method for parsing, and therefore the membership file + * has the same syntax as other configuration files such as ph_hba.conf. + * + * Note that this function allows for reloading membership configuration files + * at runtime. When that happens, old worker nodes that do not appear in the + * file are marked as stale, but are still kept in the shared hash. + */ +void +LoadWorkerNodeList(const char *workerFilename) +{ + List *workerList = NIL; + ListCell *workerCell = NULL; + uint32 workerCount = 0; + + workerList = ParseWorkerNodeFile(workerFilename); + + workerCount = list_length(workerList); + if (workerCount > MaxWorkerNodesTracked) + { + ereport(FATAL, (errcode(ERRCODE_CONFIG_FILE_ERROR), + errmsg("worker node count: %u exceeds max allowed value: %d", + workerCount, MaxWorkerNodesTracked))); + } + else + { + ereport(INFO, (errmsg("reading nodes from worker file: %s", workerFilename))); + } + + /* before reading file's lines, reset worker node hash */ + ResetWorkerNodesHash(WorkerNodesHash); + + /* parse file lines */ + foreach(workerCell, workerList) + { + WorkerNode *workerNode = NULL; + WorkerNode *parsedNode = lfirst(workerCell); + void *hashKey = NULL; + bool handleFound = false; + + /* + * Search for the parsed worker node in the hash, and then insert parsed + * values. When searching, we make the hashKey point to the beginning of + * the parsed node; we previously set the key length and key comparison + * function to include both the node name and the port number. + */ + hashKey = (void *) parsedNode; + workerNode = (WorkerNode *) hash_search(WorkerNodesHash, hashKey, + HASH_ENTER, &handleFound); + + if (handleFound) + { + /* display notification if worker node's rack changed */ + char *oldWorkerRack = workerNode->workerRack; + char *newWorkerRack = parsedNode->workerRack; + + if (strncmp(oldWorkerRack, newWorkerRack, WORKER_LENGTH) != 0) + { + ereport(INFO, (errmsg("worker node: \"%s:%u\" changed rack location", + workerNode->workerName, workerNode->workerPort))); + } + + /* display warning if worker node already appeared in this file */ + if (workerNode->inWorkerFile) + { + ereport(WARNING, (errmsg("multiple lines for worker node: \"%s:%u\"", + workerNode->workerName, + workerNode->workerPort))); + } + } + + strlcpy(workerNode->workerName, parsedNode->workerName, WORKER_LENGTH); + strlcpy(workerNode->workerRack, parsedNode->workerRack, WORKER_LENGTH); + workerNode->workerPort = parsedNode->workerPort; + workerNode->inWorkerFile = parsedNode->inWorkerFile; + + pfree(parsedNode); + } +} + + +/* + * ParseWorkerNodeFile opens and parses the node name and node port from the + * specified configuration file. + */ +static List * +ParseWorkerNodeFile(const char *workerNodeFilename) +{ + FILE *workerFileStream = NULL; + List *workerNodeList = NIL; + char workerNodeLine[MAXPGPATH]; + char *workerFilePath = make_absolute_path(workerNodeFilename); + char *workerPatternTemplate = "%%%u[^# \t]%%*[ \t]%%%u[^# \t]%%*[ \t]%%%u[^# \t]"; + char workerLinePattern[1024]; + const int workerNameIndex = 0; + const int workerPortIndex = 1; + + memset(workerLinePattern, '\0', sizeof(workerLinePattern)); + + workerFileStream = AllocateFile(workerFilePath, PG_BINARY_R); + if (workerFileStream == NULL) + { + if (errno == ENOENT) + { + ereport(DEBUG1, (errmsg("worker list file located at \"%s\" is not present", + workerFilePath))); + } + else + { + ereport(ERROR, (errcode_for_file_access(), + errmsg("could not open worker list file \"%s\": %m", + workerFilePath))); + } + return NIL; + } + + /* build pattern to contain node name length limit */ + snprintf(workerLinePattern, sizeof(workerLinePattern), workerPatternTemplate, + WORKER_LENGTH, MAX_PORT_LENGTH, WORKER_LENGTH); + + while (fgets(workerNodeLine, sizeof(workerNodeLine), workerFileStream) != NULL) + { + const int workerLineLength = strnlen(workerNodeLine, MAXPGPATH); + WorkerNode *workerNode = NULL; + char *linePointer = NULL; + int32 nodePort = PostPortNumber; /* default port number */ + int fieldCount = 0; + bool lineIsInvalid = false; + char nodeName[WORKER_LENGTH + 1]; + char nodeRack[WORKER_LENGTH + 1]; + char nodePortString[MAX_PORT_LENGTH + 1]; + + memset(nodeName, '\0', sizeof(nodeName)); + strlcpy(nodeRack, WORKER_DEFAULT_RACK, sizeof(nodeRack)); + memset(nodePortString, '\0', sizeof(nodePortString)); + + if (workerLineLength == MAXPGPATH - 1) + { + ereport(ERROR, (errcode(ERRCODE_CONFIG_FILE_ERROR), + errmsg("worker node list file line exceeds the maximum " + "length of %d", MAXPGPATH))); + } + + /* trim trailing newlines preserved by fgets, if any */ + linePointer = workerNodeLine + workerLineLength - 1; + while (linePointer >= workerNodeLine && + (*linePointer == '\n' || *linePointer == '\r')) + { + *linePointer-- = '\0'; + } + + /* skip leading whitespace */ + for (linePointer = workerNodeLine; *linePointer; linePointer++) + { + if (!isspace((unsigned char) *linePointer)) + { + break; + } + } + + /* if the entire line is whitespace or a comment, skip it */ + if (*linePointer == '\0' || *linePointer == '#') + { + continue; + } + + /* parse line; node name is required, but port and rack are optional */ + fieldCount = sscanf(linePointer, workerLinePattern, + nodeName, nodePortString, nodeRack); + + /* adjust field count for zero based indexes */ + fieldCount--; + + /* raise error if no fields were assigned */ + if (fieldCount < workerNameIndex) + { + lineIsInvalid = true; + } + + /* no special treatment for nodeName: already parsed by sscanf */ + + /* if a second token was specified, convert to integer port */ + if (fieldCount >= workerPortIndex) + { + char *nodePortEnd = NULL; + + errno = 0; + nodePort = strtol(nodePortString, &nodePortEnd, 10); + + if (errno != 0 || (*nodePortEnd) != '\0' || nodePort <= 0) + { + lineIsInvalid = true; + } + } + + if (lineIsInvalid) + { + ereport(ERROR, (errcode(ERRCODE_CONFIG_FILE_ERROR), + errmsg("could not parse worker node line: %s", + workerNodeLine), + errhint("Lines in the worker node file must contain a valid " + "node name and, optionally, a positive port number. " + "Comments begin with a '#' character and extend to " + "the end of their line."))); + } + + /* allocate worker node structure and set fields */ + workerNode = (WorkerNode *) palloc0(sizeof(WorkerNode)); + + strlcpy(workerNode->workerName, nodeName, WORKER_LENGTH + 1); + strlcpy(workerNode->workerRack, nodeRack, WORKER_LENGTH + 1); + workerNode->workerPort = nodePort; + workerNode->inWorkerFile = true; + + workerNodeList = lappend(workerNodeList, workerNode); + } + + FreeFile(workerFileStream); + free(workerFilePath); + + return workerNodeList; +} + + +/* Marks all worker nodes in the shared hash as stale. */ +static void +ResetWorkerNodesHash(HTAB *WorkerNodesHash) +{ + WorkerNode *workerNode = NULL; + + HASH_SEQ_STATUS status; + hash_seq_init(&status, WorkerNodesHash); + + workerNode = (WorkerNode *) hash_seq_search(&status); + while (workerNode != NULL) + { + workerNode->inWorkerFile = false; + + workerNode = (WorkerNode *) hash_seq_search(&status); + } +} + + +/* ResponsiveWorkerNodeList returns a list of all responsive worker nodes */ +List * +ResponsiveWorkerNodeList(void) +{ + List *responsiveWorkerNodeList = NULL; + ListCell *workerNodeCell = NULL; + List *workerNodeList = WorkerNodeList(); + + foreach(workerNodeCell, workerNodeList) + { + bool workerNodeResponsive = false; + WorkerNode *workerNode = lfirst(workerNodeCell); + + workerNodeResponsive = WorkerNodeResponsive(workerNode->workerName, + workerNode->workerPort); + if (workerNodeResponsive) + { + responsiveWorkerNodeList = lappend(responsiveWorkerNodeList, workerNode); + } + } + + return responsiveWorkerNodeList; +} + + +/* + * WorkerNodeResponsive returns true if the given worker node is reponsive. + * Otherwise, it returns false. + * + * This function is based on worker_node_responsive function present in the + * shard rebalancer. + */ +static bool +WorkerNodeResponsive(const char *workerName, uint32 workerPort) +{ + bool workerNodeResponsive = false; + const char *databaseName = get_database_name(MyDatabaseId); + + int connectionId = MultiClientConnect(workerName, workerPort, databaseName); + if (connectionId != INVALID_CONNECTION_ID) + { + MultiClientDisconnect(connectionId); + + workerNodeResponsive = true; + } + + return workerNodeResponsive; +} diff --git a/src/backend/distributed/planner/modify_planner.c b/src/backend/distributed/planner/modify_planner.c new file mode 100644 index 000000000..15a08ea16 --- /dev/null +++ b/src/backend/distributed/planner/modify_planner.c @@ -0,0 +1,649 @@ +/*------------------------------------------------------------------------- + * + * modify_planner.c + * + * This file contains functions to plan distributed table modifications. + * + * Copyright (c) 2014-2016, Citus Data, Inc. + * + *------------------------------------------------------------------------- + */ + +#include "postgres.h" +#include "c.h" + +#include + +#if (PG_VERSION_NUM >= 90500 && PG_VERSION_NUM < 90600) +#include "access/stratnum.h" +#else +#include "access/skey.h" +#endif +#include "distributed/citus_nodes.h" +#include "distributed/master_metadata_utility.h" +#include "distributed/metadata_cache.h" +#include "distributed/modify_planner.h" /* IWYU pragma: keep */ +#include "distributed/multi_join_order.h" +#include "distributed/multi_logical_planner.h" +#include "distributed/multi_physical_planner.h" +#include "distributed/multi_router_executor.h" +#include "distributed/listutils.h" +#include "distributed/citus_ruleutils.h" +#include "distributed/relay_utility.h" +#include "distributed/resource_lock.h" +#include "executor/execdesc.h" +#include "lib/stringinfo.h" +#if (PG_VERSION_NUM >= 90500) +#include "nodes/makefuncs.h" +#endif +#include "nodes/nodeFuncs.h" +#include "nodes/nodes.h" +#include "nodes/parsenodes.h" +#include "nodes/pg_list.h" +#include "nodes/primnodes.h" +#include "optimizer/clauses.h" +#include "parser/parsetree.h" +#include "storage/lock.h" +#include "utils/elog.h" +#include "utils/errcodes.h" +#include "utils/lsyscache.h" +#include "utils/rel.h" +#include "utils/relcache.h" + + +/* planner functions forward declarations */ +static void ErrorIfQueryNotSupported(Query *queryTree); +static Task * DistributedModifyTask(Query *query); +#if (PG_VERSION_NUM >= 90500) +static OnConflictExpr * RebuildOnConflict(Oid relationId, + OnConflictExpr *originalOnConflict); +#endif +static Job * DistributedModifyJob(Query *query, Task *modifyTask); +static List * QueryRestrictList(Query *query); +static ShardInterval * DistributedModifyShardInterval(Query *query); +static Oid ExtractFirstDistributedTableId(Query *query); +static Const * ExtractPartitionValue(Query *query, Var *partitionColumn); + + +/* + * MultiModifyPlanCreate actually creates the distributed plan for execution + * of a distribution modification. It expects that the provided MultiTreeRoot + * is actually a Query object, which it uses directly to produce a MultiPlan. + */ +MultiPlan * +MultiModifyPlanCreate(Query *query) +{ + Task *modifyTask = NULL; + Job *modifyJob = NULL; + MultiPlan *multiPlan = NULL; + + ErrorIfQueryNotSupported(query); + + modifyTask = DistributedModifyTask(query); + + modifyJob = DistributedModifyJob(query, modifyTask); + + multiPlan = CitusMakeNode(MultiPlan); + multiPlan->workerJob = modifyJob; + multiPlan->masterQuery = NULL; + multiPlan->masterTableName = NULL; + + return multiPlan; +} + + +/* + * ErrorIfQueryNotSupported checks if the query contains unsupported features, + * and errors out if it does. + */ +static void +ErrorIfQueryNotSupported(Query *queryTree) +{ + Oid distributedTableId = ExtractFirstDistributedTableId(queryTree); + uint32 rangeTableId = 1; + Var *partitionColumn = PartitionColumn(distributedTableId, rangeTableId); + char partitionMethod = PartitionMethod(distributedTableId); + List *rangeTableList = NIL; + ListCell *rangeTableCell = NULL; + bool hasValuesScan = false; + uint32 queryTableCount = 0; + bool hasNonConstTargetEntryExprs = false; + bool hasNonConstQualExprs = false; + bool specifiesPartitionValue = false; +#if (PG_VERSION_NUM >= 90500) + ListCell *setTargetCell = NULL; + List *onConflictSet = NIL; + Node *arbiterWhere = NULL; + Node *onConflictWhere = NULL; +#endif + + CmdType commandType = queryTree->commandType; + Assert(commandType == CMD_INSERT || commandType == CMD_UPDATE || + commandType == CMD_DELETE); + + if (!(partitionMethod == DISTRIBUTE_BY_HASH || + partitionMethod == DISTRIBUTE_BY_RANGE)) + { + ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("cannot perform distributed planning for the given" + " modification"), + errdetail("Only hash- or range-partitioned tables may be the " + "target of distributed modifications"))); + } + + /* + * Reject subqueries which are in SELECT or WHERE clause. + * Queries which include subqueries in FROM clauses are rejected below. + */ + if (queryTree->hasSubLinks == true) + { + ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("cannot perform distributed planning for the given" + " modification"), + errdetail("Subqueries are not supported in distributed" + " modifications."))); + } + + /* reject queries which include CommonTableExpr */ + if (queryTree->cteList != NIL) + { + ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("cannot perform distributed planning for the given" + " modification"), + errdetail("Common table expressions are not supported in" + " distributed modifications."))); + } + + /* extract range table entries */ + ExtractRangeTableEntryWalker((Node *) queryTree, &rangeTableList); + + foreach(rangeTableCell, rangeTableList) + { + RangeTblEntry *rangeTableEntry = (RangeTblEntry *) lfirst(rangeTableCell); + if (rangeTableEntry->rtekind == RTE_RELATION) + { + queryTableCount++; + } + else if (rangeTableEntry->rtekind == RTE_VALUES) + { + hasValuesScan = true; + } + else + { + /* + * Error out for rangeTableEntries that we do not support. + * We do not explicitly specify "in FROM clause" in the error detail + * for the features that we do not support at all (SUBQUERY, JOIN). + * We do not need to check for RTE_CTE because all common table expressions + * are rejected above with queryTree->cteList check. + */ + char *rangeTableEntryErrorDetail = NULL; + if (rangeTableEntry->rtekind == RTE_SUBQUERY) + { + rangeTableEntryErrorDetail = "Subqueries are not supported in" + " distributed modifications."; + } + else if (rangeTableEntry->rtekind == RTE_JOIN) + { + rangeTableEntryErrorDetail = "Joins are not supported in distributed" + " modifications."; + } + else if (rangeTableEntry->rtekind == RTE_FUNCTION) + { + rangeTableEntryErrorDetail = "Functions must not appear in the FROM" + " clause of a distributed modifications."; + } + else + { + rangeTableEntryErrorDetail = "Unrecognized range table entry."; + } + + ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("cannot perform distributed planning for the given" + " modifications"), + errdetail("%s", rangeTableEntryErrorDetail))); + } + } + + /* + * Reject queries which involve joins. Note that UPSERTs are exceptional for this case. + * Queries like "INSERT INTO table_name ON CONFLICT DO UPDATE (col) SET other_col = ''" + * contains two range table entries, and we have to allow them. + */ + if (commandType != CMD_INSERT && queryTableCount != 1) + { + ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("cannot perform distributed planning for the given" + " modification"), + errdetail("Joins are not supported in distributed " + "modifications."))); + } + + /* reject queries which involve multi-row inserts */ + if (hasValuesScan) + { + ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("cannot perform distributed planning for the given" + " modification"), + errdetail("Multi-row INSERTs to distributed tables are not " + "supported."))); + } + + /* reject queries with a returning list */ + if (list_length(queryTree->returningList) > 0) + { + ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("cannot perform distributed planning for the given" + " modification"), + errdetail("RETURNING clauses are not supported in distributed " + "modifications."))); + } + + if (commandType == CMD_INSERT || commandType == CMD_UPDATE || + commandType == CMD_DELETE) + { + FromExpr *joinTree = NULL; + ListCell *targetEntryCell = NULL; + + foreach(targetEntryCell, queryTree->targetList) + { + TargetEntry *targetEntry = (TargetEntry *) lfirst(targetEntryCell); + + /* skip resjunk entries: UPDATE adds some for ctid, etc. */ + if (targetEntry->resjunk) + { + continue; + } + + if (!IsA(targetEntry->expr, Const)) + { + hasNonConstTargetEntryExprs = true; + } + + if (commandType == CMD_UPDATE && + targetEntry->resno == partitionColumn->varattno) + { + specifiesPartitionValue = true; + } + } + + joinTree = queryTree->jointree; + if (joinTree != NULL && contain_mutable_functions(joinTree->quals)) + { + hasNonConstQualExprs = true; + } + } + +#if (PG_VERSION_NUM >= 90500) + if (commandType == CMD_INSERT && queryTree->onConflict != NULL) + { + onConflictSet = queryTree->onConflict->onConflictSet; + arbiterWhere = queryTree->onConflict->arbiterWhere; + onConflictWhere = queryTree->onConflict->onConflictWhere; + } + + /* + * onConflictSet is expanded via expand_targetlist() on the standard planner. + * This ends up adding all the columns to the onConflictSet even if the user + * does not explicitly state the columns in the query. + * + * The following loop simply allows "DO UPDATE SET part_col = table.part_col" + * types of elements in the target list, which are added by expand_targetlist(). + * Any other attempt to update partition column value is forbidden. + */ + foreach(setTargetCell, onConflictSet) + { + TargetEntry *setTargetEntry = (TargetEntry *) lfirst(setTargetCell); + + if (setTargetEntry->resno == partitionColumn->varattno) + { + Expr *setExpr = setTargetEntry->expr; + if (IsA(setExpr, Var) && + ((Var *) setExpr)->varattno == partitionColumn->varattno) + { + specifiesPartitionValue = false; + } + else + { + specifiesPartitionValue = true; + } + } + else + { + /* + * Similarly, allow "DO UPDATE SET col_1 = table.col_1" types of + * target list elements. Note that, the following check allows + * "DO UPDATE SET col_1 = table.col_2", which is not harmful. + */ + if (IsA(setTargetEntry->expr, Var)) + { + continue; + } + else if (contain_mutable_functions((Node *) setTargetEntry->expr)) + { + hasNonConstTargetEntryExprs = true; + } + } + } + + /* error if either arbiter or on conflict WHERE contains a mutable function */ + if (contain_mutable_functions((Node *) arbiterWhere) || + contain_mutable_functions((Node *) onConflictWhere)) + { + hasNonConstQualExprs = true; + } +#endif + + if (hasNonConstTargetEntryExprs || hasNonConstQualExprs) + { + ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("cannot plan sharded modification containing values " + "which are not constants or constant expressions"))); + } + + if (specifiesPartitionValue) + { + ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("modifying the partition value of rows is not allowed"))); + } +} + + +/* + * DistributedModifyTask builds a Task to represent a modification performed by + * the provided query against the provided shard interval. This task contains + * shard-extended deparsed SQL to be run during execution. + */ +static Task * +DistributedModifyTask(Query *query) +{ + ShardInterval *shardInterval = DistributedModifyShardInterval(query); + uint64 shardId = shardInterval->shardId; + FromExpr *joinTree = NULL; + StringInfo queryString = makeStringInfo(); + Task *modifyTask = NULL; + bool upsertQuery = false; + + /* grab shared metadata lock to stop concurrent placement additions */ + LockShardDistributionMetadata(shardId, ShareLock); + + /* + * Convert the qualifiers to an explicitly and'd clause, which is needed + * before we deparse the query. This applies to SELECT, UPDATE and + * DELETE statements. + */ + joinTree = query->jointree; + if ((joinTree != NULL) && (joinTree->quals != NULL)) + { + Node *whereClause = joinTree->quals; + if (IsA(whereClause, List)) + { + joinTree->quals = (Node *) make_ands_explicit((List *) whereClause); + } + } + +#if (PG_VERSION_NUM >= 90500) + if (query->onConflict != NULL) + { + RangeTblEntry *rangeTableEntry = NULL; + Oid relationId = shardInterval->relationId; + + /* set the flag */ + upsertQuery = true; + + /* setting an alias simplifies deparsing of UPSERTs */ + rangeTableEntry = linitial(query->rtable); + if (rangeTableEntry->alias == NULL) + { + Alias *alias = makeAlias(UPSERT_ALIAS, NIL); + rangeTableEntry->alias = alias; + } + + /* some fields in onConflict expression needs to be updated for deparsing */ + query->onConflict = RebuildOnConflict(relationId, query->onConflict); + } +#else + /* always set to false for PG_VERSION_NUM < 90500 */ + upsertQuery = false; +#endif + + deparse_shard_query(query, shardInterval->relationId, shardId, queryString); + ereport(DEBUG4, (errmsg("distributed statement: %s", queryString->data))); + + modifyTask = CitusMakeNode(Task); + modifyTask->jobId = INVALID_JOB_ID; + modifyTask->taskId = INVALID_TASK_ID; + modifyTask->taskType = MODIFY_TASK; + modifyTask->queryString = queryString->data; + modifyTask->anchorShardId = shardId; + modifyTask->dependedTaskList = NIL; + modifyTask->upsertQuery = upsertQuery; + + return modifyTask; +} + + +#if (PG_VERSION_NUM >= 90500) +/* + * RebuildOnConflict rebuilds OnConflictExpr for correct deparsing. The function + * makes WHERE clause elements explicit and filters dropped columns + * from the target list. + */ +static OnConflictExpr * +RebuildOnConflict(Oid relationId, OnConflictExpr *originalOnConflict) +{ + OnConflictExpr *updatedOnConflict = copyObject(originalOnConflict); + Node *onConflictWhere = updatedOnConflict->onConflictWhere; + List *onConflictSet = updatedOnConflict->onConflictSet; + TupleDesc distributedRelationDesc = NULL; + ListCell *targetEntryCell = NULL; + List *filteredOnConflictSet = NIL; + Form_pg_attribute *tableAttributes = NULL; + Relation distributedRelation = RelationIdGetRelation(relationId); + + /* Convert onConflictWhere qualifiers to an explicitly and'd clause */ + updatedOnConflict->onConflictWhere = + (Node *) make_ands_explicit((List *) onConflictWhere); + + /* + * Here we handle dropped columns on the distributed table. onConflictSet + * includes the table attributes even if they are dropped, + * since the it is expanded via expand_targetlist() on standard planner. + */ + + /* get the relation tuple descriptor and table attributes */ + distributedRelationDesc = RelationGetDescr(distributedRelation); + tableAttributes = distributedRelationDesc->attrs; + + foreach(targetEntryCell, onConflictSet) + { + TargetEntry *targetEntry = (TargetEntry *) lfirst(targetEntryCell); + FormData_pg_attribute *tableAttribute = tableAttributes[targetEntry->resno -1]; + + /* skip dropped columns */ + if (tableAttribute->attisdropped) + { + continue; + } + + /* we only want to deparse non-dropped columns */ + filteredOnConflictSet = lappend(filteredOnConflictSet, targetEntry); + } + + /* close distributedRelation to prevent leaks */ + RelationClose(distributedRelation); + + /* set onConflictSet again with the filtered list */ + updatedOnConflict->onConflictSet = filteredOnConflictSet; + + return updatedOnConflict; +} +#endif + + +/* + * DistributedModifyJob creates a Job for the specified query to execute the + * provided modification task. Modification task placements are produced using + * the "first-replica" algorithm, except modifications run against all matching + * placements rather than just the first successful one. + */ +Job * +DistributedModifyJob(Query *query, Task *modifyTask) +{ + Job *modifyJob = NULL; + List *taskList = FirstReplicaAssignTaskList(list_make1(modifyTask)); + + modifyJob = CitusMakeNode(Job); + modifyJob->dependedJobList = NIL; + modifyJob->jobId = INVALID_JOB_ID; + modifyJob->subqueryPushdown = false; + modifyJob->jobQuery = query; + modifyJob->taskList = taskList; + + return modifyJob; +} + + +/* + * DistributedModifyShardInterval determines the single shard targeted by a + * provided distributed modification command. If no matching shards exist, or + * if the modification targets more than one one shard, this function raises + * an error. + */ +static ShardInterval * +DistributedModifyShardInterval(Query *query) +{ + List *restrictClauseList = NIL; + List *prunedShardList = NIL; + Index tableId = 1; + + Oid distributedTableId = ExtractFirstDistributedTableId(query); + List *shardIntervalList = NIL; + + /* error out if no shards exist for the table */ + shardIntervalList = LoadShardIntervalList(distributedTableId); + if (shardIntervalList == NIL) + { + char *relationName = get_rel_name(distributedTableId); + + ereport(ERROR, (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), + errmsg("could not find any shards for modification"), + errdetail("No shards exist for distributed table \"%s\".", + relationName), + errhint("Run master_create_worker_shards to create shards " + "and try again."))); + } + + restrictClauseList = QueryRestrictList(query); + prunedShardList = PruneShardList(distributedTableId, tableId, restrictClauseList, + shardIntervalList); + + if (list_length(prunedShardList) != 1) + { + ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("distributed modifications must target exactly one " + "shard"))); + } + + return (ShardInterval *) linitial(prunedShardList); +} + + +/* + * QueryRestrictList returns the restriction clauses for the query. For a SELECT + * statement these are the where-clause expressions. For INSERT statements we + * build an equality clause based on the partition-column and its supplied + * insert value. + */ +static List * +QueryRestrictList(Query *query) +{ + List *queryRestrictList = NIL; + CmdType commandType = query->commandType; + + if (commandType == CMD_INSERT) + { + /* build equality expression based on partition column value for row */ + Oid distributedTableId = ExtractFirstDistributedTableId(query); + uint32 rangeTableId = 1; + Var *partitionColumn = PartitionColumn(distributedTableId, rangeTableId); + Const *partitionValue = ExtractPartitionValue(query, partitionColumn); + + OpExpr *equalityExpr = MakeOpExpression(partitionColumn, BTEqualStrategyNumber); + + Node *rightOp = get_rightop((Expr *) equalityExpr); + Const *rightConst = (Const *) rightOp; + Assert(IsA(rightOp, Const)); + + rightConst->constvalue = partitionValue->constvalue; + rightConst->constisnull = partitionValue->constisnull; + rightConst->constbyval = partitionValue->constbyval; + + queryRestrictList = list_make1(equalityExpr); + } + else if (commandType == CMD_UPDATE || commandType == CMD_DELETE) + { + queryRestrictList = WhereClauseList(query->jointree); + } + + return queryRestrictList; +} + + +/* + * ExtractFirstDistributedTableId takes a given query, and finds the relationId + * for the first distributed table in that query. If the function cannot find a + * distributed table, it returns InvalidOid. + */ +static Oid +ExtractFirstDistributedTableId(Query *query) +{ + List *rangeTableList = NIL; + ListCell *rangeTableCell = NULL; + Oid distributedTableId = InvalidOid; + + /* extract range table entries */ + ExtractRangeTableEntryWalker((Node *) query, &rangeTableList); + + foreach(rangeTableCell, rangeTableList) + { + RangeTblEntry *rangeTableEntry = (RangeTblEntry *) lfirst(rangeTableCell); + + if (IsDistributedTable(rangeTableEntry->relid)) + { + distributedTableId = rangeTableEntry->relid; + break; + } + } + + return distributedTableId; +} + + +/* + * ExtractPartitionValue extracts the partition column value from a the target + * of a modification command. If a partition value is missing altogether or is + * NULL, this function throws an error. + */ +static Const * +ExtractPartitionValue(Query *query, Var *partitionColumn) +{ + Const *partitionValue = NULL; + TargetEntry *targetEntry = get_tle_by_resno(query->targetList, + partitionColumn->varattno); + if (targetEntry != NULL) + { + Assert(IsA(targetEntry->expr, Const)); + + partitionValue = (Const *) targetEntry->expr; + } + + if (partitionValue == NULL || partitionValue->constisnull) + { + ereport(ERROR, (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), + errmsg("cannot plan INSERT using row with NULL value " + "in partition column"))); + } + + return partitionValue; +} diff --git a/src/backend/distributed/planner/multi_explain.c b/src/backend/distributed/planner/multi_explain.c new file mode 100644 index 000000000..35e0ca79b --- /dev/null +++ b/src/backend/distributed/planner/multi_explain.c @@ -0,0 +1,108 @@ +/*------------------------------------------------------------------------- + * + * multi_explain.c + * CitusDB explain support. + * + * Copyright (c) 2012-2015, Citus Data, Inc. + *------------------------------------------------------------------------- + */ + +#include "postgres.h" + +#include "commands/prepare.h" +#include "distributed/citus_nodefuncs.h" +#include "distributed/multi_explain.h" +#include "distributed/multi_planner.h" +#include "distributed/multi_logical_optimizer.h" +#include "distributed/multi_physical_planner.h" +#include "nodes/print.h" +#include "optimizer/planner.h" +#include "tcop/tcopprot.h" + + +/* Config variables that enable printing distributed query plans */ +bool ExplainMultiLogicalPlan = false; +bool ExplainMultiPhysicalPlan = false; + + +/* + * MultiExplainOneQuery takes the given query, and checks if the query is local + * or distributed. If the query is local, the function runs the standard explain + * logic. If the query is distributed, the function looks up configuration and + * prints out the distributed logical and physical plans as appropriate. + */ +void +MultiExplainOneQuery(Query *query, IntoClause *into, ExplainState *es, + const char *queryString, ParamListInfo params) +{ + MultiTreeRoot *multiTree = NULL; + MultiPlan *multiPlan = NULL; + Query *queryCopy = NULL; + CmdType commandType = query->commandType; + + /* if local query, run the standard explain and return */ + bool localQuery = !NeedsDistributedPlanning(query); + if (localQuery) + { + PlannedStmt *plan = NULL; + instr_time planstart; + instr_time planduration; + + INSTR_TIME_SET_CURRENT(planstart); + + /* plan the query */ + plan = pg_plan_query(query, 0, params); + + INSTR_TIME_SET_CURRENT(planduration); + INSTR_TIME_SUBTRACT(planduration, planstart); + + /* run it (if needed) and produce output */ + ExplainOnePlan(plan, into, es, queryString, params, &planduration); + + return; + } + + /* error out early if the query is a modification */ + if (commandType == CMD_INSERT || commandType == CMD_UPDATE || + commandType == CMD_DELETE) + { + ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("cannot show execution plan for distributed modification"), + errdetail("EXPLAIN commands are unsupported for distributed " + "modifications."))); + } + + /* call standard planner to modify the query structure before multi planning */ + standard_planner(query, 0, params); + queryCopy = copyObject(query); + + /* create the logical and physical plan */ + multiTree = MultiLogicalPlanCreate(queryCopy); + MultiLogicalPlanOptimize(multiTree); + multiPlan = MultiPhysicalPlanCreate(multiTree); + + if (ExplainMultiLogicalPlan) + { + char *logicalPlanString = CitusNodeToString(multiTree); + char *formattedPlanString = pretty_format_node_dump(logicalPlanString); + + appendStringInfo(es->str, "logical plan:\n"); + appendStringInfo(es->str, "%s\n", formattedPlanString); + } + + if (ExplainMultiPhysicalPlan) + { + char *physicalPlanString = CitusNodeToString(multiPlan); + char *formattedPlanString = pretty_format_node_dump(physicalPlanString); + + appendStringInfo(es->str, "physical plan:\n"); + appendStringInfo(es->str, "%s\n", formattedPlanString); + } + + /* if explain printing isn't enabled, print error only after planning */ + if (!ExplainMultiLogicalPlan && !ExplainMultiPhysicalPlan) + { + appendStringInfo(es->str, "explain statements for distributed queries "); + appendStringInfo(es->str, "are currently unsupported\n"); + } +} diff --git a/src/backend/distributed/planner/multi_join_order.c b/src/backend/distributed/planner/multi_join_order.c new file mode 100644 index 000000000..e8cc68f07 --- /dev/null +++ b/src/backend/distributed/planner/multi_join_order.c @@ -0,0 +1,1544 @@ +/*------------------------------------------------------------------------- + * + * multi_join_order.c + * + * Routines for constructing the join order list using a rule-based approach. + * + * Copyright (c) 2012, Citus Data, Inc. + * + * $Id$ + * + *------------------------------------------------------------------------- + */ + +#include "postgres.h" +#include + +#include "access/nbtree.h" +#include "access/heapam.h" +#include "access/htup_details.h" +#include "distributed/metadata_cache.h" +#include "distributed/multi_join_order.h" +#include "distributed/multi_physical_planner.h" +#include "distributed/pg_dist_partition.h" +#include "distributed/worker_protocol.h" +#include "lib/stringinfo.h" +#include "optimizer/var.h" +#include "nodes/nodeFuncs.h" +#include "utils/builtins.h" +#include "utils/datum.h" +#include "utils/lsyscache.h" +#include "utils/rel.h" +#include "utils/syscache.h" + + +/* Config variables managed via guc.c */ +int LargeTableShardCount = 4; /* shard counts for a large table */ +bool LogMultiJoinOrder = false; /* print join order as a debugging aid */ + +/* Function pointer type definition for join rule evaluation functions */ +typedef JoinOrderNode * (*RuleEvalFunction) (JoinOrderNode *currentJoinNode, + TableEntry *candidateTable, + List *candidateShardList, + List *applicableJoinClauses, + JoinType joinType); + +static char * RuleNameArray[JOIN_RULE_LAST] = {0}; /* ordered join rule names */ +static RuleEvalFunction RuleEvalFunctionArray[JOIN_RULE_LAST] = {0}; /* join rules */ + + +/* Local functions forward declarations */ +static JoinOrderNode * CreateFirstJoinOrderNode(FromExpr *fromExpr, + List *tableEntryList); +static bool JoinExprListWalker(Node *node, List **joinList); +static bool ExtractLeftMostRangeTableIndex(Node *node, int *rangeTableIndex); +static List * MergeShardIntervals(List *leftShardIntervalList, + List *rightShardIntervalList, JoinType joinType); +static bool ShardIntervalsMatch(List *leftShardIntervalList, List *rightShardIntervalList); +static List * LoadSortedShardIntervalList(Oid relationId); +static List * JoinOrderForTable(TableEntry *firstTable, List *tableEntryList, + List *joinClauseList); +static List * BestJoinOrder(List *candidateJoinOrders); +static List * FewestOfJoinRuleType(List *candidateJoinOrders, JoinRuleType ruleType); +static uint32 JoinRuleTypeCount(List *joinOrder, JoinRuleType ruleTypeToCount); +static List * LatestLargeDataTransfer(List *candidateJoinOrders); +static void PrintJoinOrderList(List *joinOrder); +static uint32 LargeDataTransferLocation(List *joinOrder); +static List * TableEntryListDifference(List *lhsTableList, List *rhsTableList); +static TableEntry * FindTableEntry(List *tableEntryList, uint32 tableId); + +/* Local functions forward declarations for join evaluations */ +static JoinOrderNode * EvaluateJoinRules(List *joinedTableList, JoinOrderNode *currentJoinNode, + TableEntry *candidateTable, List *candidateShardList, + List *joinClauseList, JoinType joinType); +static List * RangeTableIdList(List *tableList); +static RuleEvalFunction JoinRuleEvalFunction(JoinRuleType ruleType); +static char * JoinRuleName(JoinRuleType ruleType); +static JoinOrderNode * BroadcastJoin(JoinOrderNode *joinNode, TableEntry *candidateTable, + List *candidateShardList, List *applicableJoinClauses, + JoinType joinType); +static JoinOrderNode * LocalJoin(JoinOrderNode *joinNode, TableEntry *candidateTable, + List *candidateShardList, List *applicableJoinClauses, + JoinType joinType); +static bool JoinOnColumns(Var *currentPartitioncolumn, Var *candidatePartitionColumn, + List *joinClauseList); +static JoinOrderNode * SinglePartitionJoin(JoinOrderNode *joinNode, TableEntry *candidateTable, + List *candidateShardList, List *applicableJoinClauses, + JoinType joinType); +static JoinOrderNode * DualPartitionJoin(JoinOrderNode *joinNode, TableEntry *candidateTable, + List *candidateShardList, List *applicableJoinClauses, + JoinType joinType); +static JoinOrderNode * CartesianProduct(JoinOrderNode *joinNode, TableEntry *candidateTable, + List *candidateShardList, List *applicableJoinClauses, + JoinType joinType); +static JoinOrderNode * MakeJoinOrderNode(TableEntry *tableEntry, JoinRuleType joinRuleType, + Var *partitionColumn, char partitionMethod); + + +/* + * FixedJoinOrderList returns a list of join order nodes for the query in the order + * specified by the user. This is used to handle join trees that contain OUTER joins. + * The regular JoinOrderList currently assumes that all joins are inner-joins and can + * thus be arbitrarily reordered, which is not the case for OUTER joins. At some point + * we should merge these two functions. + */ +List * +FixedJoinOrderList(FromExpr *fromExpr, List *tableEntryList) +{ + List *joinList = NIL; + ListCell * joinCell = NULL; + List *joinWhereClauseList = NIL; + List *joinOrderList = NIL; + List *joinedTableList = NIL; + JoinOrderNode *firstJoinNode = NULL; + JoinOrderNode *currentJoinNode = NULL; + + /* get the FROM section as a flattened list of JoinExpr nodes */ + joinList = JoinExprList(fromExpr); + + /* get the join clauses in the WHERE section for implicit joins */ + joinWhereClauseList = JoinClauseList((List *) fromExpr->quals); + + /* create join node for the first table */ + firstJoinNode = CreateFirstJoinOrderNode(fromExpr, tableEntryList); + + /* add first node to the join order */ + joinOrderList = list_make1(firstJoinNode); + joinedTableList = list_make1(firstJoinNode->tableEntry); + currentJoinNode = firstJoinNode; + + foreach(joinCell, joinList) + { + JoinExpr *joinExpr = (JoinExpr *) lfirst(joinCell); + List *onClauseList = list_copy((List *) joinExpr->quals); + List *joinClauseList = list_copy((List *) joinExpr->quals); + JoinType joinType = joinExpr->jointype; + RangeTblRef *nextRangeTableRef = NULL; + TableEntry *nextTable = NULL; + JoinOrderNode *nextJoinNode = NULL; + List *candidateShardList = NIL; + + /* get the table on the right hand side of the join */ + nextRangeTableRef = (RangeTblRef *) joinExpr->rarg; + nextTable = FindTableEntry(tableEntryList, nextRangeTableRef->rtindex); + + if (joinType == JOIN_INNER) + { + /* also consider WHERE clauses for INNER joins */ + joinClauseList = list_concat(joinClauseList, joinWhereClauseList); + } + + /* get the list of shards to check broadcast/local join possibility */ + candidateShardList = LoadSortedShardIntervalList(nextTable->relationId); + + /* find the best join rule type */ + nextJoinNode = EvaluateJoinRules(joinedTableList, currentJoinNode, + nextTable, candidateShardList, + joinClauseList, joinType); + + if (nextJoinNode->joinRuleType == BROADCAST_JOIN) + { + if (joinType == JOIN_RIGHT || joinType == JOIN_FULL) + { + /* the overall interval list is now the same as the right side */ + nextJoinNode->shardIntervalList = candidateShardList; + } + else if (list_length(candidateShardList) == 1) + { + /* the overall interval list is now the same as the left side */ + nextJoinNode->shardIntervalList = currentJoinNode->shardIntervalList; + } + else + { + ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("cannot perform distributed planning on this " + "query"), + errdetail("Cannot perform outer joins with broadcast " + "joins of more than 1 shard"), + errhint("Set citusdb.large_table_shard_count to 1"))); + } + } + else if (nextJoinNode->joinRuleType == LOCAL_PARTITION_JOIN) + { + /* shard interval lists must have 1-1 matching for local joins */ + bool shardIntervalsMatch = + ShardIntervalsMatch(currentJoinNode->shardIntervalList, + candidateShardList); + + if (shardIntervalsMatch) + { + nextJoinNode->shardIntervalList = + MergeShardIntervals(currentJoinNode->shardIntervalList, + candidateShardList, + joinType); + } + else + { + ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("cannot perform distributed planning on this " + "query"), + errdetail("Shards of relations in outer join queries " + "must have 1-to-1 shard partitioning"))); + + } + } + else + { + /* re-partitioning for OUTER joins is not implemented */ + ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("cannot perform distributed planning on this query"), + errdetail("Shards of relations in outer join queries must " + "have 1-to-1 shard partitioning"))); + } + + if (joinType != JOIN_INNER) + { + /* preserve non-join clauses for OUTER joins */ + nextJoinNode->joinClauseList = onClauseList; + } + + /* add next node to the join order */ + joinOrderList = lappend(joinOrderList, nextJoinNode); + joinedTableList = lappend(joinedTableList, nextTable); + currentJoinNode = nextJoinNode; + } + + if (LogMultiJoinOrder) + { + PrintJoinOrderList(joinOrderList); + } + + return joinOrderList; +} + + +/* + * CreateFirstJoinOrderNode creates the join order node for the left-most table in the + * join tree. + */ +static JoinOrderNode * +CreateFirstJoinOrderNode(FromExpr *fromExpr, List *tableEntryList) +{ + JoinOrderNode *firstJoinNode = NULL; + TableEntry *firstTable = NULL; + JoinRuleType firstJoinRule = JOIN_RULE_INVALID_FIRST; + Var *firstPartitionColumn = NULL; + char firstPartitionMethod = '\0'; + int rangeTableIndex = 0; + + ExtractLeftMostRangeTableIndex((Node *) fromExpr, &rangeTableIndex); + + firstTable = FindTableEntry(tableEntryList, rangeTableIndex); + + firstPartitionColumn = PartitionColumn(firstTable->relationId, + firstTable->rangeTableId); + firstPartitionMethod = PartitionMethod(firstTable->relationId); + + firstJoinNode = MakeJoinOrderNode(firstTable, firstJoinRule, + firstPartitionColumn, + firstPartitionMethod); + + firstJoinNode->shardIntervalList = + LoadSortedShardIntervalList(firstTable->relationId); + + return firstJoinNode; +} + + +/* + * JoinExprList flattens the JoinExpr nodes in the FROM expression and translate implicit + * joins to inner joins. This function does not consider (right-)nested joins. + */ +List * +JoinExprList(FromExpr *fromExpr) +{ + List *joinList = NIL; + List *fromList = fromExpr->fromlist; + ListCell *fromCell = NULL; + + foreach(fromCell, fromList) + { + Node *nextNode = (Node *) lfirst(fromCell); + + if (joinList != NIL) + { + /* multiple nodes in from clause, add an explicit join between them */ + JoinExpr *newJoinExpr = NULL; + RangeTblRef *nextRangeTableRef = NULL; + int nextRangeTableIndex = 0; + + /* find the left most range table in this node */ + ExtractLeftMostRangeTableIndex((Node *) fromExpr, &nextRangeTableIndex); + + nextRangeTableRef = makeNode(RangeTblRef); + nextRangeTableRef->rtindex = nextRangeTableIndex; + + /* join the previous node with nextRangeTableRef */ + newJoinExpr = makeNode(JoinExpr); + newJoinExpr->jointype = JOIN_INNER; + newJoinExpr->rarg = (Node *) nextRangeTableRef; + newJoinExpr->quals = NULL; + } + + JoinExprListWalker(nextNode, &joinList); + } + + return joinList; +} + + +/* + * JoinExprListWalker the JoinExpr nodes in a join tree in the order in which joins are + * to be executed. If there are no joins then no elements are added to joinList. + */ +static bool +JoinExprListWalker(Node *node, List **joinList) +{ + bool walkerResult = false; + + if (node == NULL) + { + return false; + } + + if (IsA(node, JoinExpr)) + { + JoinExpr *joinExpr = (JoinExpr *) node; + + walkerResult = JoinExprListWalker(joinExpr->larg, joinList); + + (*joinList) = lappend(*joinList, joinExpr); + } + else + { + walkerResult = expression_tree_walker(node, JoinExprListWalker, + joinList); + } + + return walkerResult; +} + + +/* + * ExtractLeftMostRangeTableIndex extracts the range table index of the left-most + * leaf in a join tree. + */ +static bool +ExtractLeftMostRangeTableIndex(Node *node, int *rangeTableIndex) +{ + bool walkerResult = false; + + Assert(node != NULL); + + if (IsA(node, JoinExpr)) + { + JoinExpr *joinExpr = (JoinExpr *) node; + + walkerResult = ExtractLeftMostRangeTableIndex(joinExpr->larg, rangeTableIndex); + } + else if (IsA(node, RangeTblRef)) + { + RangeTblRef *rangeTableRef = (RangeTblRef *) node; + + *rangeTableIndex = rangeTableRef->rtindex; + walkerResult = true; + } + else + { + walkerResult = expression_tree_walker(node, ExtractLeftMostRangeTableIndex, + rangeTableIndex); + } + + return walkerResult; +} + + +/* + * MergeShardIntervals merges given shard interval lists. It assumes that both lists + * have the same number of shard intervals, and each shard interval overlaps only with + * a corresponding shard interval from the other shard interval list. It uses union or + * intersection logic when merging two shard intervals depending on joinType. + */ +static List * +MergeShardIntervals(List *leftShardIntervalList, List *rightShardIntervalList, + JoinType joinType) +{ + FmgrInfo *comparisonFunction = NULL; + ShardInterval *firstShardInterval = NULL; + Oid typeId = InvalidOid; + bool typeByValue = false; + int typeLen = 0; + ListCell *leftShardIntervalCell = NULL; + ListCell *rightShardIntervalCell = NULL; + List *mergedShardIntervalList = NIL; + bool shardUnion = IS_OUTER_JOIN(joinType); + + Assert(list_length(leftShardIntervalList) > 0); + Assert(list_length(leftShardIntervalList) == list_length(rightShardIntervalList)); + + firstShardInterval = (ShardInterval *) linitial(leftShardIntervalList); + typeId = firstShardInterval->valueTypeId; + typeByValue = firstShardInterval->valueByVal; + typeLen = firstShardInterval->valueTypeLen; + + comparisonFunction = GetFunctionInfo(typeId, BTREE_AM_OID, BTORDER_PROC); + + forboth(leftShardIntervalCell, leftShardIntervalList, + rightShardIntervalCell, rightShardIntervalList) + { + ShardInterval *currentInterval = (ShardInterval *) lfirst(leftShardIntervalCell); + ShardInterval *nextInterval = (ShardInterval *) lfirst(rightShardIntervalCell); + ShardInterval *newShardInterval = NULL; + Datum currentMin = currentInterval->minValue; + Datum currentMax = currentInterval->maxValue; + + newShardInterval = (ShardInterval *) palloc0(sizeof(ShardInterval)); + CopyShardInterval(currentInterval, newShardInterval); + + if (nextInterval->minValueExists) + { + Datum nextMin = nextInterval->minValue; + Datum comparisonDatum = CompareCall2(comparisonFunction, currentMin, nextMin); + int comparisonResult = DatumGetInt32(comparisonDatum); + bool nextMinSmaller = comparisonResult > 0; + bool nextMinLarger = comparisonResult < 0; + + if ((shardUnion && nextMinSmaller) || + (!shardUnion && nextMinLarger)) + { + newShardInterval->minValue = datumCopy(nextMin, typeByValue, typeLen); + } + } + + if (nextInterval->maxValueExists) + { + Datum nextMax = nextInterval->maxValue; + Datum comparisonDatum = CompareCall2(comparisonFunction, currentMax, nextMax); + int comparisonResult = DatumGetInt32(comparisonDatum); + bool nextMaxLarger = comparisonResult < 0; + bool nextMaxSmaller = comparisonResult > 0; + + if ((shardUnion && nextMaxLarger) || + (!shardUnion && nextMaxSmaller) ) + { + newShardInterval->maxValue = datumCopy(nextMax, typeByValue, typeLen); + } + } + + mergedShardIntervalList = lappend(mergedShardIntervalList, newShardInterval); + } + + return mergedShardIntervalList; +} + + +/* + * LoadSortedShardIntervalList loads a list of shard intervals from the metadata + * and sorts the list by the minimum value of the intervals. + */ +static List * +LoadSortedShardIntervalList(Oid relationId) +{ + List *shardIntervalList = NIL; + int shardCount = 0; + int intervalIndex = 0; + ShardInterval **sortedShardIntervalArray = NULL; + List *sortedShardIntervalList = NIL; + + shardIntervalList = LoadShardIntervalList(relationId); + + shardCount = list_length(shardIntervalList); + if (shardCount <= 1) + { + return shardIntervalList; + } + + sortedShardIntervalArray = SortedShardIntervalArray(shardIntervalList); + + for (intervalIndex = 0; intervalIndex < shardCount; intervalIndex++) + { + ShardInterval *shardInterval = sortedShardIntervalArray[intervalIndex]; + + sortedShardIntervalList = lappend(sortedShardIntervalList, shardInterval); + } + + return sortedShardIntervalList; +} + + +/* + * JoinOnColumns determines whether two columns are joined by a given join clause + * list. + */ +static bool +JoinOnColumns(Var *currentColumn, Var *candidateColumn, List *joinClauseList) +{ + ListCell *joinClauseCell = NULL; + bool joinOnColumns = false; + + foreach(joinClauseCell, joinClauseList) + { + OpExpr *joinClause = (OpExpr *) lfirst(joinClauseCell); + Var *leftColumn = LeftColumn(joinClause); + Var *rightColumn = RightColumn(joinClause); + + /* check if both join columns and both partition key columns match */ + if (equal(leftColumn, currentColumn) && + equal(rightColumn, candidateColumn)) + { + joinOnColumns = true; + break; + } + if (equal(leftColumn, candidateColumn) && + equal(rightColumn, currentColumn)) + { + joinOnColumns = true; + break; + } + } + + return joinOnColumns; +} + + +/* + * ShardIntervalsMatch returns true if provided shard interval has one-to-one + * matching. Shards intervals must be not empty, and their intervals musht be in + * ascending order of range min values. Shard interval ranges said to be matched + * only if (1) they have same number of shards, (2) a shard interval on the left + * side overlaps with corresponding shard on the right side, (3) a shard interval + * on the right side does not overlap with any other shard. The function does not + * compare a left shard with every right shard. It compares the left shard with the + * previous and next shards of the corresponding shard to check they to not overlap + * for optimization purposes. + */ +static bool +ShardIntervalsMatch(List *leftShardIntervalList, List *rightShardIntervalList) +{ + int leftShardIntervalCount = list_length(leftShardIntervalList); + int rightShardIntervalCount = list_length(rightShardIntervalList); + ListCell *leftShardIntervalCell = NULL; + ListCell *rightShardIntervalCell = NULL; + ShardInterval *previousRightInterval = NULL; + + /* we do not support outer join queries on tables with no shards */ + if (leftShardIntervalCount == 0 || rightShardIntervalCount == 0) + { + return false; + } + + if (leftShardIntervalCount != rightShardIntervalCount) + { + return false; + } + + forboth(leftShardIntervalCell, leftShardIntervalList, + rightShardIntervalCell, rightShardIntervalList) + { + ShardInterval *leftInterval = (ShardInterval *) lfirst(leftShardIntervalCell); + ShardInterval *rightInterval = (ShardInterval *) lfirst(rightShardIntervalCell); + ListCell *nextRightIntervalCell = NULL; + + bool shardIntervalsIntersect = ShardIntervalsOverlap(leftInterval, rightInterval); + if (!shardIntervalsIntersect) + { + return false; + } + + /* + * Compare left interval with a previous right interval, they should not + * intersect. + */ + if (previousRightInterval != NULL) + { + shardIntervalsIntersect = ShardIntervalsOverlap(leftInterval, + previousRightInterval); + if (shardIntervalsIntersect) + { + return false; + } + } + + /* + * Compare left interval with a next right interval, they should not + * intersect. + */ + nextRightIntervalCell = lnext(rightShardIntervalCell); + if (nextRightIntervalCell != NULL) + { + ShardInterval *nextRightInterval = (ShardInterval *) lfirst(nextRightIntervalCell); + shardIntervalsIntersect = ShardIntervalsOverlap(leftInterval, + nextRightInterval); + if (shardIntervalsIntersect) + { + return false; + } + } + + previousRightInterval = rightInterval; + } + + return true; +} + + +/* + * JoinOrderList calculates the best join order and join rules that apply given + * the list of tables and join clauses. First, the function generates a set of + * candidate join orders, each with a different table as its first table. Then, + * the function chooses among these candidates the join order that transfers the + * least amount of data across the network, and returns this join order. + */ +List * +JoinOrderList(List *tableEntryList, List *joinClauseList) +{ + List *bestJoinOrder = NIL; + List *candidateJoinOrderList = NIL; + ListCell *tableEntryCell = NULL; + + foreach(tableEntryCell, tableEntryList) + { + TableEntry *startingTable = (TableEntry *) lfirst(tableEntryCell); + List *candidateJoinOrder = NIL; + + /* each candidate join order starts with a different table */ + candidateJoinOrder = JoinOrderForTable(startingTable, tableEntryList, + joinClauseList); + + candidateJoinOrderList = lappend(candidateJoinOrderList, candidateJoinOrder); + } + + bestJoinOrder = BestJoinOrder(candidateJoinOrderList); + + /* if logging is enabled, print join order */ + if (LogMultiJoinOrder) + { + PrintJoinOrderList(bestJoinOrder); + } + + return bestJoinOrder; +} + + +/* + * JoinOrderForTable creates a join order whose first element is the given first + * table. To determine each subsequent element in the join order, the function + * then chooses the table that has the lowest ranking join rule, and with which + * it can join the table to the previous table in the join order. The function + * repeats this until it determines all elements in the join order list, and + * returns this list. + */ +static List * +JoinOrderForTable(TableEntry *firstTable, List *tableEntryList, List *joinClauseList) +{ + JoinOrderNode *currentJoinNode = NULL; + JoinRuleType firstJoinRule = JOIN_RULE_INVALID_FIRST; + List *joinOrderList = NIL; + List *joinedTableList = NIL; + int joinedTableCount = 1; + int totalTableCount = list_length(tableEntryList); + + /* create join node for the first table */ + Oid firstRelationId = firstTable->relationId; + uint32 firstTableId = firstTable->rangeTableId; + Var *firstPartitionColumn = PartitionColumn(firstRelationId, firstTableId); + char firstPartitionMethod = PartitionMethod(firstRelationId); + + JoinOrderNode *firstJoinNode = MakeJoinOrderNode(firstTable, firstJoinRule, + firstPartitionColumn, + firstPartitionMethod); + + /* add first node to the join order */ + joinOrderList = list_make1(firstJoinNode); + joinedTableList = list_make1(firstTable); + currentJoinNode = firstJoinNode; + + /* loop until we join all remaining tables */ + while (joinedTableCount < totalTableCount) + { + List *pendingTableList = NIL; + ListCell *pendingTableCell = NULL; + JoinOrderNode *nextJoinNode = NULL; + TableEntry *nextJoinedTable = NULL; + JoinRuleType nextJoinRuleType = JOIN_RULE_LAST; + + pendingTableList = TableEntryListDifference(tableEntryList, joinedTableList); + + /* + * Iterate over all pending tables, and find the next best table to + * join. The best table is the one whose join rule requires the least + * amount of data transfer. + */ + foreach(pendingTableCell, pendingTableList) + { + TableEntry *pendingTable = (TableEntry *) lfirst(pendingTableCell); + JoinOrderNode *pendingJoinNode = NULL; + JoinRuleType pendingJoinRuleType = JOIN_RULE_LAST; + JoinType joinType = JOIN_INNER; + List *candidateShardList = LoadShardIntervalList(pendingTable->relationId); + + /* evaluate all join rules for this pending table */ + pendingJoinNode = EvaluateJoinRules(joinedTableList, currentJoinNode, + pendingTable, candidateShardList, + joinClauseList, joinType); + + /* if this rule is better than previous ones, keep it */ + pendingJoinRuleType = pendingJoinNode->joinRuleType; + if (pendingJoinRuleType < nextJoinRuleType) + { + nextJoinNode = pendingJoinNode; + nextJoinRuleType = pendingJoinRuleType; + } + } + + Assert(nextJoinNode != NULL); + nextJoinedTable = nextJoinNode->tableEntry; + + /* add next node to the join order */ + joinOrderList = lappend(joinOrderList, nextJoinNode); + joinedTableList = lappend(joinedTableList, nextJoinedTable); + currentJoinNode = nextJoinNode; + + joinedTableCount++; + } + + return joinOrderList; +} + + +/* + * BestJoinOrder takes in a list of candidate join orders, and determines the + * best join order among these candidates. The function uses two heuristics for + * this. First, the function chooses join orders that have the fewest number of + * join operators that cause large data transfers. Second, the function chooses + * join orders where large data transfers occur later in the execution. + */ +static List * +BestJoinOrder(List *candidateJoinOrders) +{ + List *bestJoinOrder = NULL; + uint32 ruleTypeIndex = 0; + uint32 highestValidIndex = JOIN_RULE_LAST - 1; + uint32 candidateCount = 0; + + /* + * We start with the highest ranking rule type (cartesian product), and walk + * over these rules in reverse order. For each rule type, we then keep join + * orders that only contain the fewest number of join rules of that type. + * + * For example, the algorithm chooses join orders like the following: + * (a) The algorithm prefers join orders with 2 cartesian products (CP) to + * those that have 3 or more, if there isn't a join order with fewer CPs. + * (b) Assuming that all join orders have the same number of CPs, the + * algorithm prefers join orders with 2 dual partitions (DP) to those that + * have 3 or more, if there isn't a join order with fewer DPs; and so + * forth. + */ + for (ruleTypeIndex = highestValidIndex; ruleTypeIndex > 0; ruleTypeIndex--) + { + JoinRuleType ruleType = (JoinRuleType) ruleTypeIndex; + + candidateJoinOrders = FewestOfJoinRuleType(candidateJoinOrders, ruleType); + } + + /* + * If there is a tie, we pick candidate join orders where large data + * transfers happen at later stages of query execution. This results in more + * data being filtered via joins, selections, and projections earlier on. + */ + candidateJoinOrders = LatestLargeDataTransfer(candidateJoinOrders); + + /* we should have at least one join order left after optimizations */ + candidateCount = list_length(candidateJoinOrders); + Assert(candidateCount > 0); + + /* + * If there still is a tie, we pick the join order whose relation appeared + * earliest in the query's range table entry list. + */ + bestJoinOrder = (List *) linitial(candidateJoinOrders); + + return bestJoinOrder; +} + + +/* + * FewestOfJoinRuleType finds join orders that have the fewest number of times + * the given join rule occurs in the candidate join orders, and filters all + * other join orders. For example, if four candidate join orders have a join + * rule appearing 3, 5, 3, and 6 times, only two join orders that have the join + * rule appearing 3 times will be returned. + */ +static List * +FewestOfJoinRuleType(List *candidateJoinOrders, JoinRuleType ruleType) +{ + List *fewestJoinOrders = NULL; + uint32 fewestRuleCount = INT_MAX; + ListCell *joinOrderCell = NULL; + + foreach(joinOrderCell, candidateJoinOrders) + { + List *joinOrder = (List *) lfirst(joinOrderCell); + uint32 ruleTypeCount = JoinRuleTypeCount(joinOrder, ruleType); + + if (ruleTypeCount == fewestRuleCount) + { + fewestJoinOrders = lappend(fewestJoinOrders, joinOrder); + } + else if (ruleTypeCount < fewestRuleCount) + { + fewestJoinOrders = list_make1(joinOrder); + fewestRuleCount = ruleTypeCount; + } + } + + return fewestJoinOrders; +} + + +/* Counts the number of times the given join rule occurs in the join order. */ +static uint32 +JoinRuleTypeCount(List *joinOrder, JoinRuleType ruleTypeToCount) +{ + uint32 ruleTypeCount = 0; + ListCell *joinOrderNodeCell = NULL; + + foreach(joinOrderNodeCell, joinOrder) + { + JoinOrderNode *joinOrderNode = (JoinOrderNode *) lfirst(joinOrderNodeCell); + + JoinRuleType ruleType = joinOrderNode->joinRuleType; + if (ruleType == ruleTypeToCount) + { + ruleTypeCount++; + } + } + + return ruleTypeCount; +} + + +/* + * LatestLargeDataTransfer finds and returns join orders where a large data + * transfer join rule occurs as late as possible in the join order. Late large + * data transfers result in more data being filtered before data gets shuffled + * in the network. + */ +static List * +LatestLargeDataTransfer(List *candidateJoinOrders) +{ + List *latestJoinOrders = NIL; + uint32 latestJoinLocation = 0; + ListCell *joinOrderCell = NULL; + + foreach(joinOrderCell, candidateJoinOrders) + { + List *joinOrder = (List *) lfirst(joinOrderCell); + uint32 joinRuleLocation = LargeDataTransferLocation(joinOrder); + + if (joinRuleLocation == latestJoinLocation) + { + latestJoinOrders = lappend(latestJoinOrders, joinOrder); + } + else if (joinRuleLocation > latestJoinLocation) + { + latestJoinOrders = list_make1(joinOrder); + latestJoinLocation = joinRuleLocation; + } + } + + return latestJoinOrders; +} + + +/* + * LargeDataTransferLocation finds the first location of a large data transfer + * join rule, and returns that location. If the join order does not have any + * large data transfer rules, the function returns one location past the end of + * the join order list. + */ +static uint32 +LargeDataTransferLocation(List *joinOrder) +{ + uint32 joinRuleLocation = 0; + ListCell *joinOrderNodeCell = NULL; + + foreach(joinOrderNodeCell, joinOrder) + { + JoinOrderNode *joinOrderNode = (JoinOrderNode *) lfirst(joinOrderNodeCell); + JoinRuleType joinRuleType = joinOrderNode->joinRuleType; + + /* we consider the following join rules to cause large data transfers */ + if (joinRuleType == SINGLE_PARTITION_JOIN || + joinRuleType == DUAL_PARTITION_JOIN || + joinRuleType == CARTESIAN_PRODUCT) + { + break; + } + + joinRuleLocation++; + } + + return joinRuleLocation; +} + + +/* Prints the join order list and join rules for debugging purposes. */ +static void +PrintJoinOrderList(List *joinOrder) +{ + StringInfo printBuffer = makeStringInfo(); + ListCell *joinOrderNodeCell = NULL; + bool firstJoinNode = true; + + foreach(joinOrderNodeCell, joinOrder) + { + JoinOrderNode *joinOrderNode = (JoinOrderNode *) lfirst(joinOrderNodeCell); + Oid relationId = joinOrderNode->tableEntry->relationId; + char *relationName = get_rel_name(relationId); + + if (firstJoinNode) + { + appendStringInfo(printBuffer, "[ \"%s\" ]", relationName); + firstJoinNode = false; + } + else + { + JoinRuleType ruleType = (JoinRuleType) joinOrderNode->joinRuleType; + char *ruleName = JoinRuleName(ruleType); + + appendStringInfo(printBuffer, "[ %s ", ruleName); + appendStringInfo(printBuffer, "\"%s\" ]", relationName); + } + } + + ereport(LOG, (errmsg("join order: %s", printBuffer->data))); +} + + +/* + * TableEntryListDifference returns a list containing table entries that are in + * the left-hand side table list, but not in the right-hand side table list. + */ +static List * +TableEntryListDifference(List *lhsTableList, List *rhsTableList) +{ + List *tableListDifference = NIL; + ListCell *lhsTableCell = NULL; + + foreach(lhsTableCell, lhsTableList) + { + TableEntry *lhsTableEntry = (TableEntry *) lfirst(lhsTableCell); + ListCell *rhsTableCell = NULL; + bool lhsTableEntryExists = false; + + foreach(rhsTableCell, rhsTableList) + { + TableEntry *rhsTableEntry = (TableEntry *) lfirst(rhsTableCell); + + if ((lhsTableEntry->relationId == rhsTableEntry->relationId) && + (lhsTableEntry->rangeTableId == rhsTableEntry->rangeTableId)) + { + lhsTableEntryExists = true; + } + } + + if (!lhsTableEntryExists) + { + tableListDifference = lappend(tableListDifference, lhsTableEntry); + } + } + + return tableListDifference; +} + + +/* + * Finds the table entry in tableEntryList with the given range table id. + */ +static TableEntry * +FindTableEntry(List *tableEntryList, uint32 tableId) +{ + ListCell *tableEntryCell = NULL; + + foreach(tableEntryCell, tableEntryList) + { + TableEntry *tableEntry = (TableEntry *) lfirst(tableEntryCell); + if (tableEntry->rangeTableId == tableId) + { + return tableEntry; + } + } + + return NULL; +} + + +/* + * EvaluateJoinRules takes in a list of already joined tables and a candidate + * next table, evaluates different join rules between the two tables, and finds + * the best join rule that applies. The function returns the applicable join + * order node which includes the join rule and the partition information. + */ +static JoinOrderNode * +EvaluateJoinRules(List *joinedTableList, JoinOrderNode *currentJoinNode, + TableEntry *candidateTable, List *candidateShardList, + List *joinClauseList, JoinType joinType) +{ + JoinOrderNode *nextJoinNode = NULL; + uint32 candidateTableId = 0; + List *joinedTableIdList = NIL; + List *applicableJoinClauses = NIL; + uint32 lowestValidIndex = JOIN_RULE_INVALID_FIRST + 1; + uint32 highestValidIndex = JOIN_RULE_LAST - 1; + uint32 ruleIndex = 0; + + /* + * We first find all applicable join clauses between already joined tables + * and the candidate table. + */ + joinedTableIdList = RangeTableIdList(joinedTableList); + candidateTableId = candidateTable->rangeTableId; + applicableJoinClauses = ApplicableJoinClauses(joinedTableIdList, candidateTableId, + joinClauseList); + + /* we then evaluate all join rules in order */ + for (ruleIndex = lowestValidIndex; ruleIndex <= highestValidIndex; ruleIndex++) + { + JoinRuleType ruleType = (JoinRuleType) ruleIndex; + RuleEvalFunction ruleEvalFunction = JoinRuleEvalFunction(ruleType); + + nextJoinNode = (*ruleEvalFunction) (currentJoinNode, + candidateTable, + candidateShardList, + applicableJoinClauses, + joinType); + + /* break after finding the first join rule that applies */ + if (nextJoinNode != NULL) + { + break; + } + } + + Assert(nextJoinNode != NULL); + nextJoinNode->joinType = joinType; + nextJoinNode->joinClauseList = applicableJoinClauses; + return nextJoinNode; +} + + +/* Extracts range table identifiers from the given table list, and returns them. */ +static List * +RangeTableIdList(List *tableList) +{ + List *rangeTableIdList = NIL; + ListCell *tableCell = NULL; + + foreach(tableCell, tableList) + { + TableEntry *tableEntry = (TableEntry *) lfirst(tableCell); + + uint32 rangeTableId = tableEntry->rangeTableId; + rangeTableIdList = lappend_int(rangeTableIdList, rangeTableId); + } + + return rangeTableIdList; +} + + +/* + * JoinRuleEvalFunction returns a function pointer for the rule evaluation + * function; this rule evaluation function corresponds to the given rule type. + * The function also initializes the rule evaluation function array in a static + * code block, if the array has not been initialized. + */ +static RuleEvalFunction +JoinRuleEvalFunction(JoinRuleType ruleType) +{ + static bool ruleEvalFunctionsInitialized = false; + RuleEvalFunction ruleEvalFunction = NULL; + + if (!ruleEvalFunctionsInitialized) + { + RuleEvalFunctionArray[BROADCAST_JOIN] = &BroadcastJoin; + RuleEvalFunctionArray[LOCAL_PARTITION_JOIN] = &LocalJoin; + RuleEvalFunctionArray[SINGLE_PARTITION_JOIN] = &SinglePartitionJoin; + RuleEvalFunctionArray[DUAL_PARTITION_JOIN] = &DualPartitionJoin; + RuleEvalFunctionArray[CARTESIAN_PRODUCT] = &CartesianProduct; + + ruleEvalFunctionsInitialized = true; + } + + ruleEvalFunction = RuleEvalFunctionArray[ruleType]; + Assert(ruleEvalFunction != NULL); + + return ruleEvalFunction; +} + + +/* Returns a string name for the given join rule type. */ +static char * +JoinRuleName(JoinRuleType ruleType) +{ + static bool ruleNamesInitialized = false; + char *ruleName = NULL; + + if (!ruleNamesInitialized) + { + /* use strdup() to be independent of memory contexts */ + RuleNameArray[BROADCAST_JOIN] = strdup("broadcast join"); + RuleNameArray[LOCAL_PARTITION_JOIN] = strdup("local partition join"); + RuleNameArray[SINGLE_PARTITION_JOIN] = strdup("single partition join"); + RuleNameArray[DUAL_PARTITION_JOIN] = strdup("dual partition join"); + RuleNameArray[CARTESIAN_PRODUCT] = strdup("cartesian product"); + + ruleNamesInitialized = true; + } + + ruleName = RuleNameArray[ruleType]; + Assert(ruleName != NULL); + + return ruleName; +} + + +/* + * BroadcastJoin evaluates if the candidate table is small enough to be + * broadcasted to all nodes in the system. If the table can be broadcasted, + * the function simply returns a join order node that includes the current + * partition key and method. Otherwise, the function returns null. + */ +static JoinOrderNode * +BroadcastJoin(JoinOrderNode *currentJoinNode, TableEntry *candidateTable, + List *candidateShardList, List *applicableJoinClauses, + JoinType joinType) +{ + JoinOrderNode *nextJoinNode = NULL; + int candidateShardCount = list_length(candidateShardList); + int leftShardCount = list_length(currentJoinNode->shardIntervalList); + int applicableJoinCount = list_length(applicableJoinClauses); + bool performBroadcastJoin = false; + + if (applicableJoinCount <= 0) + { + return NULL; + } + + /* + * If the table's shard count doesn't exceed the value specified in the + * configuration, then we assume table broadcasting is feasible. This assumption + * is valid only for inner joins. + * + * Left join requires candidate table to have single shard, right join requires + * existing (left) table to have single shard, full outer join requires both tables + * to have single shard. + */ + if (joinType == JOIN_INNER && candidateShardCount < LargeTableShardCount) + { + performBroadcastJoin = true; + } + else if ((joinType == JOIN_LEFT || joinType == JOIN_ANTI) && candidateShardCount == 1) + { + performBroadcastJoin = true; + } + else if (joinType == JOIN_RIGHT && leftShardCount == 1) + { + performBroadcastJoin = true; + } + else if (joinType == JOIN_FULL && leftShardCount == 1 && candidateShardCount == 1) + { + performBroadcastJoin = true; + } + + if (performBroadcastJoin) + { + nextJoinNode = MakeJoinOrderNode(candidateTable, BROADCAST_JOIN, + currentJoinNode->partitionColumn, + currentJoinNode->partitionMethod); + } + + return nextJoinNode; +} + + +/* + * LocalJoin takes the current partition key column and the candidate table's + * partition key column and the partition method for each table. The function + * then evaluates if tables in the join order and the candidate table can be + * joined locally, without any data transfers. If they can, the function returns + * a join order node for a local join. Otherwise, the function returns null. + */ +static JoinOrderNode * +LocalJoin(JoinOrderNode *currentJoinNode, TableEntry *candidateTable, + List *candidateShardList, List *applicableJoinClauses, + JoinType joinType) +{ + JoinOrderNode *nextJoinNode = NULL; + Oid relationId = candidateTable->relationId; + uint32 tableId = candidateTable->rangeTableId; + Var *candidatePartitionColumn = PartitionColumn(relationId, tableId); + Var *currentPartitionColumn = currentJoinNode->partitionColumn; + char candidatePartitionMethod = PartitionMethod(relationId); + char currentPartitionMethod = currentJoinNode->partitionMethod; + bool joinOnPartitionColumns = false; + + /* the partition method should be the same for a local join */ + if (currentPartitionMethod != candidatePartitionMethod) + { + return NULL; + } + + joinOnPartitionColumns = JoinOnColumns(currentPartitionColumn, + candidatePartitionColumn, + applicableJoinClauses); + if (joinOnPartitionColumns) + { + nextJoinNode = MakeJoinOrderNode(candidateTable, LOCAL_PARTITION_JOIN, + currentPartitionColumn, + currentPartitionMethod); + } + + return nextJoinNode; +} + + +/* + * SinglePartitionJoin takes the current and the candidate table's partition keys + * and methods. The function then evaluates if either "tables in the join order" + * or the candidate table is already partitioned on a join column. If they are, + * the function returns a join order node with the already partitioned column as + * the next partition key. Otherwise, the function returns null. + */ +static JoinOrderNode * +SinglePartitionJoin(JoinOrderNode *currentJoinNode, TableEntry *candidateTable, + List *candidateShardList, List *applicableJoinClauses, + JoinType joinType) +{ + JoinOrderNode *nextJoinNode = NULL; + Var *currentPartitionColumn = currentJoinNode->partitionColumn; + char currentPartitionMethod = currentJoinNode->partitionMethod; + + Oid relationId = candidateTable->relationId; + uint32 tableId = candidateTable->rangeTableId; + Var *candidatePartitionColumn = PartitionColumn(relationId, tableId); + char candidatePartitionMethod = PartitionMethod(relationId); + + /* outer joins are not supported yet */ + if (IS_OUTER_JOIN(joinType)) + { + return NULL; + } + + /* + * If we previously dual-hash re-partitioned the tables for a join, we + * currently don't allow a single-repartition join. + */ + if (currentPartitionMethod == REDISTRIBUTE_BY_HASH) + { + return NULL; + } + + if (currentPartitionMethod != DISTRIBUTE_BY_HASH) + { + OpExpr *joinClause = SinglePartitionJoinClause(currentPartitionColumn, + applicableJoinClauses); + + if (joinClause != NULL) + { + nextJoinNode = MakeJoinOrderNode(candidateTable, SINGLE_PARTITION_JOIN, + currentPartitionColumn, + currentPartitionMethod); + } + } + + /* evaluate re-partitioning the current table only if the rule didn't apply above */ + if (nextJoinNode == NULL && candidatePartitionMethod != DISTRIBUTE_BY_HASH) + { + OpExpr *joinClause = SinglePartitionJoinClause(candidatePartitionColumn, + applicableJoinClauses); + + if (joinClause != NULL) + { + nextJoinNode = MakeJoinOrderNode(candidateTable, SINGLE_PARTITION_JOIN, + candidatePartitionColumn, + candidatePartitionMethod); + } + } + + return nextJoinNode; +} + + +/* + * SinglePartitionJoinClause walks over the applicable join clause list, and + * finds an applicable join clause for the given partition column. If no such + * clause exists, the function returns NULL. + */ +OpExpr * +SinglePartitionJoinClause(Var *partitionColumn, List *applicableJoinClauses) +{ + OpExpr *joinClause = NULL; + ListCell *applicableJoinClauseCell = NULL; + + foreach(applicableJoinClauseCell, applicableJoinClauses) + { + OpExpr *applicableJoinClause = (OpExpr *) lfirst(applicableJoinClauseCell); + Var *leftColumn = LeftColumn(applicableJoinClause); + Var *rightColumn = RightColumn(applicableJoinClause); + + /* + * We first check if partition column matches either of the join columns + * and if it does, we then check if the join column types match. If the + * types are different, we will use different hash functions for the two + * column types, and will incorrectly repartition the data. + */ + if (equal(leftColumn, partitionColumn) || equal(rightColumn, partitionColumn)) + { + if (leftColumn->vartype == rightColumn->vartype) + { + joinClause = applicableJoinClause; + break; + } + else + { + ereport(DEBUG1, (errmsg("single partition column types do not match"))); + } + } + } + + return joinClause; +} + + +/* + * DualPartitionJoin evaluates if a join clause exists between "tables in the + * join order" and the candidate table. If such a clause exists, both tables can + * be repartitioned on the join column; and the function returns a join order + * node with the join column as the next partition key. Otherwise, the function + * returns null. + */ +static JoinOrderNode * +DualPartitionJoin(JoinOrderNode *currentJoinNode, TableEntry *candidateTable, + List *candidateShardList, List *applicableJoinClauses, + JoinType joinType) +{ + JoinOrderNode *nextJoinNode = NULL; + + OpExpr *joinClause = DualPartitionJoinClause(applicableJoinClauses); + if (joinClause) + { + Var *nextPartitionColumn = LeftColumn(joinClause); + nextJoinNode = MakeJoinOrderNode(candidateTable, DUAL_PARTITION_JOIN, + nextPartitionColumn, REDISTRIBUTE_BY_HASH); + } + + return nextJoinNode; +} + + +/* + * DualPartitionJoinClause walks over the applicable join clause list, and finds + * an applicable join clause for dual re-partitioning. If no such clause exists, + * the function returns NULL. + */ +OpExpr * +DualPartitionJoinClause(List *applicableJoinClauses) +{ + OpExpr *joinClause = NULL; + ListCell *applicableJoinClauseCell = NULL; + + foreach(applicableJoinClauseCell, applicableJoinClauses) + { + OpExpr *applicableJoinClause = (OpExpr *) lfirst(applicableJoinClauseCell); + Var *leftColumn = LeftColumn(applicableJoinClause); + Var *rightColumn = RightColumn(applicableJoinClause); + + /* we only need to check that the join column types match */ + if (leftColumn->vartype == rightColumn->vartype) + { + joinClause = applicableJoinClause; + break; + } + else + { + ereport(DEBUG1, (errmsg("dual partition column types do not match"))); + } + } + + return joinClause; +} + + +/* + * CartesianProduct always evaluates to true since all tables can be combined + * using a cartesian product operator. This function acts as a catch-all rule, + * in case none of the join rules apply. + */ +static JoinOrderNode * +CartesianProduct(JoinOrderNode *currentJoinNode, TableEntry *candidateTable, + List *candidateShardList, List *applicableJoinClauses, + JoinType joinType) +{ + JoinOrderNode *nextJoinNode = MakeJoinOrderNode(candidateTable, CARTESIAN_PRODUCT, + currentJoinNode->partitionColumn, + currentJoinNode->partitionMethod); + + return nextJoinNode; +} + + +/* Constructs and returns a join-order node with the given arguments */ +JoinOrderNode * +MakeJoinOrderNode(TableEntry *tableEntry, JoinRuleType joinRuleType, + Var *partitionColumn, char partitionMethod) +{ + JoinOrderNode *joinOrderNode = palloc0(sizeof(JoinOrderNode)); + joinOrderNode->tableEntry = tableEntry; + joinOrderNode->joinRuleType = joinRuleType; + joinOrderNode->joinType = JOIN_INNER; + joinOrderNode->partitionColumn = partitionColumn; + joinOrderNode->partitionMethod = partitionMethod; + joinOrderNode->joinClauseList = NIL; + + return joinOrderNode; +} + + +/* + * ApplicableJoinClauses finds all join clauses that apply between the given + * left table list and the right table, and returns these found join clauses. + */ +List * +ApplicableJoinClauses(List *leftTableIdList, uint32 rightTableId, List *joinClauseList) +{ + ListCell *joinClauseCell = NULL; + List *applicableJoinClauses = NIL; + + /* make sure joinClauseList contains only join clauses */ + joinClauseList = JoinClauseList(joinClauseList); + + foreach(joinClauseCell, joinClauseList) + { + OpExpr *joinClause = (OpExpr *) lfirst(joinClauseCell); + Var *joinLeftColumn = LeftColumn(joinClause); + Var *joinRightColumn = RightColumn(joinClause); + + uint32 joinLeftTableId = joinLeftColumn->varno; + uint32 joinRightTableId = joinRightColumn->varno; + + bool leftListHasJoinLeft = list_member_int(leftTableIdList, joinLeftTableId); + bool leftListHasJoinRight = list_member_int(leftTableIdList, joinRightTableId); + + if ((leftListHasJoinLeft && (rightTableId == joinRightTableId)) || + (leftListHasJoinRight && (rightTableId == joinLeftTableId))) + { + applicableJoinClauses = lappend(applicableJoinClauses, joinClause); + } + } + + return applicableJoinClauses; +} + + +/* Returns the left column in the given join clause. */ +Var * +LeftColumn(OpExpr *joinClause) +{ + List *argumentList = joinClause->args; + Node *leftArgument = (Node *) linitial(argumentList); + + List *varList = pull_var_clause_default(leftArgument); + Var *leftColumn = NULL; + + Assert(list_length(varList) == 1); + leftColumn = (Var *) linitial(varList); + + return leftColumn; +} + + +/* Returns the right column in the given join clause. */ +Var * +RightColumn(OpExpr *joinClause) +{ + List *argumentList = joinClause->args; + Node *rightArgument = (Node *) lsecond(argumentList); + + List *varList = pull_var_clause_default(rightArgument); + Var *rightColumn = NULL; + + Assert(list_length(varList) == 1); + rightColumn = (Var *) linitial(varList); + + return rightColumn; +} + + +/* + * PartitionColumn builds the partition column for the given relation, and sets + * the partition column's range table references to the given table identifier. + */ +Var * +PartitionColumn(Oid relationId, uint32 rangeTableId) +{ + Var *partitionColumn = PartitionKey(relationId); + partitionColumn->varno = rangeTableId; + partitionColumn->varnoold = rangeTableId; + + return partitionColumn; +} + + +/* + * PartitionKey returns the partition key column for the given relation. Note + * that in the context of distributed join and query planning, the callers of + * this function *must* set the partition key column's range table reference + * (varno) to match the table's location in the query range table list. + */ +Var * +PartitionKey(Oid relationId) +{ + DistTableCacheEntry *partitionEntry = DistributedTableCacheEntry(relationId); + + /* now obtain partition key and build the var node */ + Node *variableNode = stringToNode(partitionEntry->partitionKeyString); + + Var *partitionKey = (Var *) variableNode; + Assert(IsA(variableNode, Var)); + + return partitionKey; +} + + +/* Returns the partition method for the given relation. */ +char +PartitionMethod(Oid relationId) +{ + /* errors out if not a distributed table */ + DistTableCacheEntry *partitionEntry = DistributedTableCacheEntry(relationId); + + char partitionMethod = partitionEntry->partitionMethod; + + return partitionMethod; +} diff --git a/src/backend/distributed/planner/multi_logical_optimizer.c b/src/backend/distributed/planner/multi_logical_optimizer.c new file mode 100644 index 000000000..3aebfcb37 --- /dev/null +++ b/src/backend/distributed/planner/multi_logical_optimizer.c @@ -0,0 +1,4110 @@ +/*------------------------------------------------------------------------- + * + * multi_logical_optimizer.c + * Routines for optimizing logical plan trees based on multi-relational + * algebra. + * + * Copyright (c) 2012, Citus Data, Inc. + * + * $Id$ + * + *------------------------------------------------------------------------- + */ + +#include "postgres.h" +#include + +#include "access/genam.h" +#include "access/heapam.h" +#include "access/htup_details.h" +#include "access/nbtree.h" +#include "catalog/indexing.h" +#include "catalog/namespace.h" +#include "catalog/pg_aggregate.h" +#include "catalog/pg_am.h" +#include "catalog/pg_proc.h" +#include "catalog/pg_type.h" +#include "commands/extension.h" +#include "distributed/citus_nodes.h" +#include "distributed/multi_logical_optimizer.h" +#include "distributed/multi_logical_planner.h" +#include "distributed/multi_physical_planner.h" +#include "distributed/pg_dist_partition.h" +#include "distributed/worker_protocol.h" +#include "nodes/makefuncs.h" +#include "nodes/nodeFuncs.h" +#include "nodes/print.h" +#include "optimizer/clauses.h" +#include "optimizer/tlist.h" +#include "optimizer/var.h" +#include "parser/parse_coerce.h" +#include "parser/parse_oper.h" +#include "utils/builtins.h" +#include "utils/fmgroids.h" +#include "utils/lsyscache.h" +#include "utils/rel.h" +#include "utils/relcache.h" +#include "utils/syscache.h" +#include "utils/tqual.h" + + +/* Config variable managed via guc.c */ +int LimitClauseRowFetchCount = -1; /* number of rows to fetch from each task */ +double CountDistinctErrorRate = 0.0; /* precision of count(distinct) approximate */ + + +/* Local functions forward declarations */ +static MultiSelect * AndSelectNode(MultiSelect *selectNode); +static MultiSelect * OrSelectNode(MultiSelect *selectNode); +static List * OrSelectClauseList(List *selectClauseList); +static void PushDownNodeLoop(MultiUnaryNode *currentNode); +static void PullUpCollectLoop(MultiCollect *collectNode); +static void AddressProjectSpecialConditions(MultiProject *projectNode); +static List * ListCopyDeep(List *nodeList); +static PushDownStatus CanPushDown(MultiUnaryNode *parentNode); +static PullUpStatus CanPullUp(MultiUnaryNode *childNode); +static PushDownStatus Commutative(MultiUnaryNode *parentNode, + MultiUnaryNode *childNode); +static PushDownStatus Distributive(MultiUnaryNode *parentNode, + MultiBinaryNode *childNode); +static PullUpStatus Factorizable(MultiBinaryNode *parentNode, + MultiUnaryNode *childNode); +static List * SelectClauseTableIdList(List *selectClauseList); +static MultiUnaryNode * GenerateLeftNode(MultiUnaryNode *currentNode, + MultiBinaryNode *binaryNode); +static MultiUnaryNode * GenerateRightNode(MultiUnaryNode *currentNode, + MultiBinaryNode *binaryNode); +static MultiUnaryNode * GenerateNode(MultiUnaryNode *currentNode, MultiNode *childNode); +static List * TableIdListColumns(List *tableIdList, List *columnList); +static List * TableIdListSelectClauses(List *tableIdList, List *selectClauseList); +static void PushDownBelowUnaryChild(MultiUnaryNode *currentNode, + MultiUnaryNode *childNode); +static void PlaceUnaryNodeChild(MultiUnaryNode *unaryNode, MultiUnaryNode *childNode); +static void PlaceBinaryNodeLeftChild(MultiBinaryNode *binaryNode, + MultiUnaryNode *newLeftChildNode); +static void PlaceBinaryNodeRightChild(MultiBinaryNode *binaryNode, + MultiUnaryNode *newRightChildNode); +static void RemoveUnaryNode(MultiUnaryNode *unaryNode); +static void PullUpUnaryNode(MultiUnaryNode *unaryNode); +static void ParentSetNewChild(MultiNode *parentNode, MultiNode *oldChildNode, + MultiNode *newChildNode); + +/* Local functions forward declarations for aggregate expressions */ +static void ApplyExtendedOpNodes(MultiExtendedOp *originalNode, + MultiExtendedOp *masterNode, MultiExtendedOp *workerNode); +static void TransformSubqueryNode(MultiTable *subqueryNode); +static MultiExtendedOp * MasterExtendedOpNode(MultiExtendedOp *originalOpNode); +static Node * MasterAggregateMutator(Node *originalNode, AttrNumber *columnId); +static Expr * MasterAggregateExpression(Aggref *originalAggregate, AttrNumber *columnId); +static Expr * MasterAverageExpression(Oid sumAggregateType, Oid countAggregateType, + AttrNumber *columnId); +static Expr * AddTypeConversion(Node *originalAggregate, Node *newExpression); +static MultiExtendedOp * WorkerExtendedOpNode(MultiExtendedOp *originalOpNode); +static bool WorkerAggregateWalker(Node *node, List **newExpressionList); +static List * WorkerAggregateExpressionList(Aggref *originalAggregate); +static AggregateType GetAggregateType(Oid aggFunctionId); +static Oid AggregateArgumentType(Aggref *aggregate); +static Oid AggregateFunctionOid(const char *functionName, Oid inputType); + +/* Local functions forward declarations for count(distinct) approximations */ +static char * CountDistinctHashFunctionName(Oid argumentType); +static int CountDistinctStorageSize(double approximationErrorRate); +static Const * MakeIntegerConst(int32 integerValue); + +/* Local functions forward declarations for aggregate expression checks */ +static void ErrorIfContainsUnsupportedAggregate(MultiNode *logicalPlanNode); +static void ErrorIfUnsupportedArrayAggregate(Aggref *arrayAggregateExpression); +static void ErrorIfUnsupportedAggregateDistinct(Aggref *aggregateExpression, + MultiNode *logicalPlanNode); +static Var * AggregateDistinctColumn(Aggref *aggregateExpression); +static bool TablePartitioningSupportsDistinct(List *tableNodeList, MultiExtendedOp *opNode, + Var *distinctColumn); +static bool GroupedByColumn(List *groupClauseList, List *targetList, Var *column); + +/* Local functions forward declarations for subquery pushdown checks */ +static void ErrorIfContainsUnsupportedSubquery(MultiNode *logicalPlanNode); +static void ErrorIfCannotPushdownSubquery(Query *subqueryTree, bool outerQueryHasLimit); +static void ErrorIfUnsupportedTableCombination(Query *queryTree); +static void ErrorIfUnsupportedUnionQuery(Query *unionQuery); +static bool TargetListOnPartitionColumn(Query *query, List *targetEntryList); +static bool IsPartitionColumnRecursive(Expr *columnExpression, Query *query); +static FieldSelect * CompositeFieldRecursive(Expr *expression, Query *query); +static bool FullCompositeFieldList(List *compositeFieldList); +static Query * LateralQuery(Query *query); +static bool SupportedLateralQuery(Query *parentQuery, Query *lateralQuery); +static bool JoinOnPartitionColumn(Query *query); +static void ErrorIfUnsupportedShardDistribution(Query *query); +static List * RelationIdList(Query *query); +static bool CoPartitionedTables(List *firstShardList, List *secondShardList); +static bool ShardIntervalsEqual(ShardInterval *firstInterval, + ShardInterval *secondInterval); +static void ErrorIfUnsupportedFilters(Query *subquery); +static bool EqualOpExpressionLists(List *firstOpExpressionList, + List *secondOpExpressionList); + +/* Local functions forward declarations for limit clauses */ +static Node * WorkerLimitCount(MultiExtendedOp *originalOpNode); +static List * WorkerSortClauseList(MultiExtendedOp *originalOpNode); +static bool CanPushDownLimitApproximate(List *sortClauseList, List *targetList); +static bool HasOrderByAggregate(List *sortClauseList, List *targetList); +static bool HasOrderByAverage(List *sortClauseList, List *targetList); +static bool HasOrderByComplexExpression(List *sortClauseList, List *targetList); +static bool HasOrderByHllType(List *sortClauseList, List *targetList); + + +/* + * MultiLogicalPlanOptimize applies multi-relational algebra optimizations on + * the given logical plan tree. Specifically, the function applies four set of + * optimizations in a particular order. + * + * First, the function splits the search node into two nodes that contain And + * and Or clauses, and pushes down the node that contains And clauses. Second, + * the function pushes down the project node; this node either contains columns + * to return to the user, or aggregate expressions used by the aggregate node. + * Third, the function pulls up the collect operators in the tree. Fourth, the + * function finds the extended operator node, and splits this node into master + * and worker extended operator nodes. + */ +void +MultiLogicalPlanOptimize(MultiTreeRoot *multiLogicalPlan) +{ + bool hasOrderByHllType = false; + List *selectNodeList = NIL; + List *projectNodeList = NIL; + List *collectNodeList = NIL; + List *extendedOpNodeList = NIL; + List *tableNodeList = NIL; + ListCell *collectNodeCell = NULL; + ListCell *tableNodeCell = NULL; + MultiProject *projectNode = NULL; + MultiExtendedOp *extendedOpNode = NULL; + MultiExtendedOp *masterExtendedOpNode = NULL; + MultiExtendedOp *workerExtendedOpNode = NULL; + MultiNode *logicalPlanNode = (MultiNode *) multiLogicalPlan; + + /* check that we can optimize aggregates in the plan */ + ErrorIfContainsUnsupportedAggregate(logicalPlanNode); + + /* check that we can pushdown subquery in the plan */ + ErrorIfContainsUnsupportedSubquery(logicalPlanNode); + + /* + * If a select node exists, we use the idempower property to split the node + * into two nodes that contain And and Or clauses. If both And and Or nodes + * exist, we modify the tree in place to swap the original select node with + * And and Or nodes. We then push down the And select node if it exists. + */ + selectNodeList = FindNodesOfType(logicalPlanNode, T_MultiSelect); + if (selectNodeList != NIL) + { + MultiSelect *selectNode = (MultiSelect *) linitial(selectNodeList); + MultiSelect *andSelectNode = AndSelectNode(selectNode); + MultiSelect *orSelectNode = OrSelectNode(selectNode); + + if (andSelectNode != NULL && orSelectNode != NULL) + { + MultiNode *parentNode = ParentNode((MultiNode *) selectNode); + MultiNode *childNode = ChildNode((MultiUnaryNode *) selectNode); + Assert(UnaryOperator(parentNode)); + + SetChild((MultiUnaryNode *) parentNode, (MultiNode *) orSelectNode); + SetChild((MultiUnaryNode *) orSelectNode, (MultiNode *) andSelectNode); + SetChild((MultiUnaryNode *) andSelectNode, (MultiNode *) childNode); + } + else if (andSelectNode != NULL && orSelectNode == NULL) + { + andSelectNode = selectNode; /* no need to modify the tree */ + } + + if (andSelectNode != NULL) + { + PushDownNodeLoop((MultiUnaryNode *) andSelectNode); + } + } + + /* push down the multi project node */ + projectNodeList = FindNodesOfType(logicalPlanNode, T_MultiProject); + projectNode = (MultiProject *) linitial(projectNodeList); + PushDownNodeLoop((MultiUnaryNode *) projectNode); + + /* pull up collect nodes and merge duplicate collects */ + collectNodeList = FindNodesOfType(logicalPlanNode, T_MultiCollect); + foreach(collectNodeCell, collectNodeList) + { + MultiCollect *collectNode = (MultiCollect *) lfirst(collectNodeCell); + PullUpCollectLoop(collectNode); + } + + /* + * We split the extended operator node into its equivalent master and worker + * operator nodes; and if the extended operator has aggregates, we transform + * aggregate functions accordingly for the master and worker operator nodes. + * If we can push down the limit clause, we also add limit count and sort + * clause list to the worker operator node. We then push the worker operator + * node below the collect node. + */ + extendedOpNodeList = FindNodesOfType(logicalPlanNode, T_MultiExtendedOp); + extendedOpNode = (MultiExtendedOp *) linitial(extendedOpNodeList); + + masterExtendedOpNode = MasterExtendedOpNode(extendedOpNode); + workerExtendedOpNode = WorkerExtendedOpNode(extendedOpNode); + + ApplyExtendedOpNodes(extendedOpNode, masterExtendedOpNode, workerExtendedOpNode); + + tableNodeList = FindNodesOfType(logicalPlanNode, T_MultiTable); + foreach(tableNodeCell, tableNodeList) + { + MultiTable *tableNode = (MultiTable *) lfirst(tableNodeCell); + if (tableNode->relationId == SUBQUERY_RELATION_ID) + { + TransformSubqueryNode(tableNode); + } + } + + /* + * When enabled, count(distinct) approximation uses hll as the intermediate + * data type. We currently have a mismatch between hll target entry and sort + * clause's sortop oid, so we can't push an order by on the hll data type to + * the worker node. We check that here and error out if necessary. + */ + hasOrderByHllType = HasOrderByHllType(workerExtendedOpNode->sortClauseList, + workerExtendedOpNode->targetList); + if (hasOrderByHllType) + { + ereport(ERROR, (errmsg("cannot approximate count(distinct) and order by it"), + errhint("You might need to disable approximations for either " + "count(distinct) or limit through configuration."))); + } +} + + +/* + * AndSelectNode looks for AND clauses in the given select node. If they exist, + * the function returns these clauses in a new node. Otherwise, the function + * returns null. + */ +static MultiSelect * +AndSelectNode(MultiSelect *selectNode) +{ + MultiSelect *andSelectNode = NULL; + List *selectClauseList = selectNode->selectClauseList; + List *orSelectClauseList = OrSelectClauseList(selectClauseList); + + /* AND clauses are select clauses that are not OR clauses */ + List *andSelectClauseList = list_difference(selectClauseList, orSelectClauseList); + if (andSelectClauseList != NIL) + { + andSelectNode = CitusMakeNode(MultiSelect); + andSelectNode->selectClauseList = andSelectClauseList; + } + + return andSelectNode; +} + + +/* + * OrSelectNode looks for OR clauses in the given select node. If they exist, + * the function returns these clauses in a new node. Otherwise, the function + * returns null. + */ +static MultiSelect * +OrSelectNode(MultiSelect *selectNode) +{ + MultiSelect *orSelectNode = NULL; + List *selectClauseList = selectNode->selectClauseList; + List *orSelectClauseList = OrSelectClauseList(selectClauseList); + + if (orSelectClauseList != NIL) + { + orSelectNode = CitusMakeNode(MultiSelect); + orSelectNode->selectClauseList = orSelectClauseList; + } + + return orSelectNode; +} + + +/* + * OrSelectClauseList walks over the select clause list, and returns all clauses + * that have OR expressions in them. + */ +static List * +OrSelectClauseList(List *selectClauseList) +{ + List *orSelectClauseList = NIL; + ListCell *selectClauseCell = NULL; + + foreach(selectClauseCell, selectClauseList) + { + Node *selectClause = (Node *) lfirst(selectClauseCell); + bool orClause = or_clause(selectClause); + if (orClause) + { + orSelectClauseList = lappend(orSelectClauseList, selectClause); + } + } + + return orSelectClauseList; +} + + +/* + * PushDownNodeLoop pushes down the current node as far down the plan tree as + * possible. For this, the function first addresses any special conditions that + * may apply on the current node. Then, the function pushes down the current + * node if its child node is unary. If the child is binary, the function splits + * the current node into two nodes by applying generation rules, and recurses + * into itself to push down these two nodes. + */ +static void +PushDownNodeLoop(MultiUnaryNode *currentNode) +{ + MultiUnaryNode *projectNodeGenerated = NULL; + MultiUnaryNode *leftNodeGenerated = NULL; + MultiUnaryNode *rightNodeGenerated = NULL; + + PushDownStatus pushDownStatus = CanPushDown(currentNode); + while (pushDownStatus == PUSH_DOWN_VALID || + pushDownStatus == PUSH_DOWN_SPECIAL_CONDITIONS) + { + MultiNode *childNode = currentNode->childNode; + bool unaryChild = UnaryOperator(childNode); + bool binaryChild = BinaryOperator(childNode); + + /* + * We first check if we can use the idempower property to split the + * project node. We split at a partition node as it captures the + * minimal set of columns needed from a partition job. After the split + * we break from the loop and recursively call pushdown for the + * generated project node. + */ + MultiNode *parentNode = ParentNode((MultiNode *) currentNode); + CitusNodeTag currentNodeType = CitusNodeTag(currentNode); + CitusNodeTag parentNodeType = CitusNodeTag(parentNode); + + if (currentNodeType == T_MultiProject && parentNodeType == T_MultiPartition) + { + projectNodeGenerated = GenerateNode(currentNode, childNode); + PlaceUnaryNodeChild(currentNode, projectNodeGenerated); + + break; + } + + /* address any special conditions before we can perform the pushdown */ + if (pushDownStatus == PUSH_DOWN_SPECIAL_CONDITIONS) + { + MultiProject *projectNode = (MultiProject *) currentNode; + Assert(currentNodeType == T_MultiProject); + + AddressProjectSpecialConditions(projectNode); + } + + if (unaryChild) + { + MultiUnaryNode *unaryChildNode = (MultiUnaryNode *) childNode; + PushDownBelowUnaryChild(currentNode, unaryChildNode); + } + else if (binaryChild) + { + MultiBinaryNode *binaryChildNode = (MultiBinaryNode *) childNode; + leftNodeGenerated = GenerateLeftNode(currentNode, binaryChildNode); + rightNodeGenerated = GenerateRightNode(currentNode, binaryChildNode); + + /* push down the generated nodes below the binary child node */ + PlaceBinaryNodeLeftChild(binaryChildNode, leftNodeGenerated); + PlaceBinaryNodeRightChild(binaryChildNode, rightNodeGenerated); + + /* + * Remove the current node, and break out of the push down loop for + * the current node. Then, recurse into the push down function for + * the newly generated nodes. + */ + RemoveUnaryNode(currentNode); + break; + } + + pushDownStatus = CanPushDown(currentNode); + } + + /* recursively perform pushdown of any nodes generated in the loop */ + if (projectNodeGenerated != NULL) + { + PushDownNodeLoop(projectNodeGenerated); + } + if (leftNodeGenerated != NULL) + { + PushDownNodeLoop(leftNodeGenerated); + } + if (rightNodeGenerated != NULL) + { + PushDownNodeLoop(rightNodeGenerated); + } +} + + +/* + * PullUpCollectLoop pulls up the collect node as far up as possible in the plan + * tree. The function also merges two collect nodes that are direct descendants + * of each other by removing the given collect node from the tree. + */ +static void +PullUpCollectLoop(MultiCollect *collectNode) +{ + MultiNode *childNode = NULL; + MultiUnaryNode *currentNode = (MultiUnaryNode *) collectNode; + + PullUpStatus pullUpStatus = CanPullUp(currentNode); + while (pullUpStatus == PULL_UP_VALID) + { + PullUpUnaryNode(currentNode); + pullUpStatus = CanPullUp(currentNode); + } + + /* + * After pulling up the collect node, if we find that our child node is also + * a collect, we merge the two collect nodes together by removing this node. + */ + childNode = currentNode->childNode; + if (CitusIsA(childNode, MultiCollect)) + { + RemoveUnaryNode(currentNode); + } +} + + +/* + * AddressProjectSpecialConditions adds columns to the project node if necessary + * to make the node commutative and distributive with its child node. For this, + * the function checks for any special conditions between the project and child + * node, and determines the child node columns to add for the special conditions + * to apply. The function then adds these columns to the project node. + */ +static void +AddressProjectSpecialConditions(MultiProject *projectNode) +{ + MultiNode *childNode = ChildNode((MultiUnaryNode *) projectNode); + CitusNodeTag childNodeTag = CitusNodeTag(childNode); + List *childColumnList = NIL; + + /* + * We check if we need to include any child columns in the project node to + * address the following special conditions. + * + * SNC1: project node must include child node's projected columns, or + * SNC2: project node must include child node's partition column, or + * SNC3: project node must include child node's selection columns, or + * NSC1: project node must include child node's join columns. + */ + if (childNodeTag == T_MultiProject) + { + MultiProject *projectChildNode = (MultiProject *) childNode; + List *projectColumnList = projectChildNode->columnList; + + childColumnList = ListCopyDeep(projectColumnList); + } + else if (childNodeTag == T_MultiPartition) + { + MultiPartition *partitionNode = (MultiPartition *) childNode; + Var *partitionColumn = partitionNode->partitionColumn; + List *partitionColumnList = list_make1(partitionColumn); + + childColumnList = ListCopyDeep(partitionColumnList); + } + else if (childNodeTag == T_MultiSelect) + { + MultiSelect *selectNode = (MultiSelect *) childNode; + Node *selectClauseList = (Node *) selectNode->selectClauseList; + List *selectList = pull_var_clause_default(selectClauseList); + + childColumnList = ListCopyDeep(selectList); + } + else if (childNodeTag == T_MultiJoin) + { + MultiJoin *joinNode = (MultiJoin *) childNode; + Node *joinClauseList = (Node *) joinNode->joinClauseList; + List *joinList = pull_var_clause_default(joinClauseList); + + childColumnList = ListCopyDeep(joinList); + } + + /* + * If we need to include any child columns, then find the columns that are + * not already in the project column list, and add them. + */ + if (childColumnList != NIL) + { + List *projectColumnList = projectNode->columnList; + List *newColumnList = list_concat_unique(projectColumnList, childColumnList); + + projectNode->columnList = newColumnList; + } +} + + +/* Deep copies the given node list, and returns the deep copied list. */ +static List * +ListCopyDeep(List *nodeList) +{ + List *nodeCopyList = NIL; + ListCell *nodeCell = NULL; + + foreach(nodeCell, nodeList) + { + Node *node = (Node *) lfirst(nodeCell); + Node *nodeCopy = copyObject(node); + + nodeCopyList = lappend(nodeCopyList, nodeCopy); + } + + return nodeCopyList; +} + + +/* + * CanPushDown determines if a particular node can be moved below its child. The + * criteria for pushing down a node is determined by multi-relational algebra's + * rules for commutativity and distributivity. + */ +static PushDownStatus +CanPushDown(MultiUnaryNode *parentNode) +{ + PushDownStatus pushDownStatus = PUSH_DOWN_INVALID_FIRST; + MultiNode *childNode = parentNode->childNode; + bool unaryChild = UnaryOperator(childNode); + bool binaryChild = BinaryOperator(childNode); + + if (unaryChild) + { + pushDownStatus = Commutative(parentNode, (MultiUnaryNode *) childNode); + } + else if (binaryChild) + { + pushDownStatus = Distributive(parentNode, (MultiBinaryNode *) childNode); + } + + Assert(pushDownStatus != PUSH_DOWN_INVALID_FIRST); + return pushDownStatus; +} + + +/* + * CanPullUp determines if a particular node can be moved above its parent. The + * criteria for pulling up a node is determined by multi-relational algebra's + * rules for commutativity and factorizability. + */ +static PullUpStatus +CanPullUp(MultiUnaryNode *childNode) +{ + PullUpStatus pullUpStatus = PULL_UP_INVALID_FIRST; + MultiNode *parentNode = ParentNode((MultiNode *) childNode); + bool unaryParent = UnaryOperator(parentNode); + bool binaryParent = BinaryOperator(parentNode); + + if (unaryParent) + { + /* + * Evaluate if parent can be pushed down below the child node, since it + * is equivalent to pulling up the child above its parent. + */ + PushDownStatus parentPushDownStatus = PUSH_DOWN_INVALID_FIRST; + parentPushDownStatus = Commutative((MultiUnaryNode *) parentNode, childNode); + + if (parentPushDownStatus == PUSH_DOWN_VALID) + { + pullUpStatus = PULL_UP_VALID; + } + else + { + pullUpStatus = PULL_UP_NOT_VALID; + } + } + else if (binaryParent) + { + pullUpStatus = Factorizable((MultiBinaryNode *) parentNode, childNode); + } + + Assert(pullUpStatus != PULL_UP_INVALID_FIRST); + return pullUpStatus; +} + + +/* + * Commutative returns a status which denotes whether the given parent node can + * be pushed down below its child node using the commutative property. + */ +static PushDownStatus +Commutative(MultiUnaryNode *parentNode, MultiUnaryNode *childNode) +{ + PushDownStatus pushDownStatus = PUSH_DOWN_NOT_VALID; + CitusNodeTag parentNodeTag = CitusNodeTag(parentNode); + CitusNodeTag childNodeTag = CitusNodeTag(childNode); + + /* we cannot be commutative with non-query operators */ + if (childNodeTag == T_MultiTreeRoot || childNodeTag == T_MultiTable) + { + return PUSH_DOWN_NOT_VALID; + } + + /* first check for commutative operators and no special conditions */ + if ((parentNodeTag == T_MultiPartition && childNodeTag == T_MultiProject) || + (parentNodeTag == T_MultiPartition && childNodeTag == T_MultiPartition) || + (parentNodeTag == T_MultiPartition && childNodeTag == T_MultiSelect)) + { + pushDownStatus = PUSH_DOWN_VALID; + } + if ((parentNodeTag == T_MultiCollect && childNodeTag == T_MultiProject) || + (parentNodeTag == T_MultiCollect && childNodeTag == T_MultiCollect) || + (parentNodeTag == T_MultiCollect && childNodeTag == T_MultiSelect)) + { + pushDownStatus = PUSH_DOWN_VALID; + } + if (parentNodeTag == T_MultiSelect) + { + pushDownStatus = PUSH_DOWN_VALID; + } + if (parentNodeTag == T_MultiProject && childNodeTag == T_MultiCollect) + { + pushDownStatus = PUSH_DOWN_VALID; + } + + /* + * The project node is commutative with the below operators given that + * its special conditions apply. + */ + if ((parentNodeTag == T_MultiProject && childNodeTag == T_MultiProject) || + (parentNodeTag == T_MultiProject && childNodeTag == T_MultiPartition) || + (parentNodeTag == T_MultiProject && childNodeTag == T_MultiSelect) || + (parentNodeTag == T_MultiProject && childNodeTag == T_MultiJoin)) + { + pushDownStatus = PUSH_DOWN_SPECIAL_CONDITIONS; + } + + return pushDownStatus; +} + + +/* + * Distributive returns a status which denotes whether the given parent node can + * be pushed down below its binary child node using the distributive property. + */ +static PushDownStatus +Distributive(MultiUnaryNode *parentNode, MultiBinaryNode *childNode) +{ + PushDownStatus pushDownStatus = PUSH_DOWN_NOT_VALID; + CitusNodeTag parentNodeTag = CitusNodeTag(parentNode); + CitusNodeTag childNodeTag = CitusNodeTag(childNode); + + /* special condition checks for partition operator are not implemented */ + Assert(parentNodeTag != T_MultiPartition); + + /* + * The project node is distributive with the join operator given that its + * special conditions apply. + */ + if (parentNodeTag == T_MultiProject) + { + pushDownStatus = PUSH_DOWN_SPECIAL_CONDITIONS; + } + + /* collect node is distributive without special conditions */ + if ((parentNodeTag == T_MultiCollect && childNodeTag == T_MultiJoin) || + (parentNodeTag == T_MultiCollect && childNodeTag == T_MultiCartesianProduct)) + { + pushDownStatus = PUSH_DOWN_VALID; + } + + /* + * The select node is distributive with a binary operator if all tables in + * the select clauses are output by the binary child. The select clauses are + * individually AND'd; and therefore this check is sufficient to implement + * the NSC3 special condition in multi-relational algebra. + */ + if ((parentNodeTag == T_MultiSelect && childNodeTag == T_MultiJoin) || + (parentNodeTag == T_MultiSelect && childNodeTag == T_MultiCartesianProduct)) + { + MultiSelect *selectNode = (MultiSelect *) parentNode; + List *selectClauseList = selectNode->selectClauseList; + + List *selectTableIdList = SelectClauseTableIdList(selectClauseList); + List *childTableIdList = OutputTableIdList((MultiNode *) childNode); + + /* find tables that are in select clause list, but not in child list */ + List *diffList = list_difference_int(selectTableIdList, childTableIdList); + if (diffList == NIL) + { + pushDownStatus = PUSH_DOWN_VALID; + } + } + + return pushDownStatus; +} + + +/* + * Factorizable returns a status which denotes whether the given unary child + * node can be pulled up above its binary parent node using the factorizability + * property. The function currently performs this check only for collect node + * types; other node types have generation rules that are not yet implemented. + */ +static PullUpStatus +Factorizable(MultiBinaryNode *parentNode, MultiUnaryNode *childNode) +{ + PullUpStatus pullUpStatus = PULL_UP_NOT_VALID; + CitusNodeTag parentNodeTag = CitusNodeTag(parentNode); + CitusNodeTag childNodeTag = CitusNodeTag(childNode); + + /* + * The following nodes are factorizable with their parents, but we don't + * have their generation rules implemented. We therefore assert here. + */ + Assert(childNodeTag != T_MultiProject); + Assert(childNodeTag != T_MultiPartition); + Assert(childNodeTag != T_MultiSelect); + + if ((childNodeTag == T_MultiCollect && parentNodeTag == T_MultiJoin) || + (childNodeTag == T_MultiCollect && parentNodeTag == T_MultiCartesianProduct)) + { + pullUpStatus = PULL_UP_VALID; + } + + return pullUpStatus; +} + + +/* + * SelectClauseTableIdList finds the (range) table identifier for each select + * clause in the given list, and returns these identifiers in a new list. + */ +static List * +SelectClauseTableIdList(List *selectClauseList) +{ + List *tableIdList = NIL; + ListCell *selectClauseCell = NULL; + + foreach(selectClauseCell, selectClauseList) + { + Node *selectClause = (Node *) lfirst(selectClauseCell); + List *selectColumnList = pull_var_clause_default(selectClause); + Var *selectColumn = NULL; + int selectColumnTableId = 0; + + Assert(list_length(selectColumnList) > 0); + selectColumn = (Var *) linitial(selectColumnList); + selectColumnTableId = (int) selectColumn->varno; + + tableIdList = lappend_int(tableIdList, selectColumnTableId); + } + + return tableIdList; +} + + +/* + * GenerateLeftNode splits the current node over the binary node by applying the + * generation rule for distributivity in multi-relational algebra. After the + * split, the function returns the left node. + */ +static MultiUnaryNode * +GenerateLeftNode(MultiUnaryNode *currentNode, MultiBinaryNode *binaryNode) +{ + MultiNode *leftChildNode = binaryNode->leftChildNode; + MultiUnaryNode *leftNodeGenerated = GenerateNode(currentNode, leftChildNode); + + return leftNodeGenerated; +} + + +/* + * GenerateRightNode splits the current node over the binary node by applying + * the generation rule for distributivity in multi-relational algebra. After the + * split, the function returns the right node. + */ +static MultiUnaryNode * +GenerateRightNode(MultiUnaryNode *currentNode, MultiBinaryNode *binaryNode) +{ + MultiNode *rightChildNode = binaryNode->rightChildNode; + MultiUnaryNode *rightNodeGenerated = GenerateNode(currentNode, rightChildNode); + + return rightNodeGenerated; +} + + +/* + * GenerateNode determines the current node's type, and applies the relevant + * generation node for that node type. If the current node is a project node, + * the function creates a new project node with attributes that only have the + * child subtree's tables. Else if the current node is a select node, the + * function creates a new select node with select clauses that only belong to + * the tables output by the child node's subtree. + */ +static MultiUnaryNode * +GenerateNode(MultiUnaryNode *currentNode, MultiNode *childNode) +{ + MultiUnaryNode *generatedNode = NULL; + CitusNodeTag currentNodeType = CitusNodeTag(currentNode); + List *tableIdList = OutputTableIdList(childNode); + + if (currentNodeType == T_MultiProject) + { + MultiProject *projectNode = (MultiProject *) currentNode; + List *columnList = copyObject(projectNode->columnList); + + List *newColumnList = TableIdListColumns(tableIdList, columnList); + if (newColumnList != NIL) + { + MultiProject *newProjectNode = CitusMakeNode(MultiProject); + newProjectNode->columnList = newColumnList; + + generatedNode = (MultiUnaryNode *) newProjectNode; + } + } + else if (currentNodeType == T_MultiSelect) + { + MultiSelect *selectNode = (MultiSelect *) currentNode; + List *selectClauseList = copyObject(selectNode->selectClauseList); + List *newSelectClauseList = NIL; + + newSelectClauseList = TableIdListSelectClauses(tableIdList, selectClauseList); + if (newSelectClauseList != NIL) + { + MultiSelect *newSelectNode = CitusMakeNode(MultiSelect); + newSelectNode->selectClauseList = newSelectClauseList; + + generatedNode = (MultiUnaryNode *) newSelectNode; + } + } + + return generatedNode; +} + + +/* + * TableIdListColumns walks over the given column list, finds columns belonging + * to the given table id list, and returns the found columns in a new list. + */ +static List * +TableIdListColumns(List *tableIdList, List *columnList) +{ + List *tableColumnList = NIL; + ListCell *columnCell = NULL; + + foreach(columnCell, columnList) + { + Var *column = (Var *) lfirst(columnCell); + int columnTableId = (int) column->varno; + + bool tableListMember = list_member_int(tableIdList, columnTableId); + if (tableListMember) + { + tableColumnList = lappend(tableColumnList, column); + } + } + + return tableColumnList; +} + + +/* + * TableIdListSelectClauses walks over the given select clause list, finds the + * select clauses whose column references belong to the given table list, and + * returns the found clauses in a new list. + */ +static List * +TableIdListSelectClauses(List *tableIdList, List *selectClauseList) +{ + List *tableSelectClauseList = NIL; + ListCell *selectClauseCell = NULL; + + foreach(selectClauseCell, selectClauseList) + { + Node *selectClause = (Node *) lfirst(selectClauseCell); + List *selectColumnList = pull_var_clause_default(selectClause); + + Var *selectColumn = (Var *) linitial(selectColumnList); + int selectClauseTableId = (int) selectColumn->varno; + + bool tableIdListMember = list_member_int(tableIdList, selectClauseTableId); + if (tableIdListMember) + { + tableSelectClauseList = lappend(tableSelectClauseList, selectClause); + } + } + + return tableSelectClauseList; +} + + +/* Pushes down the current node below its unary child node. */ +static void +PushDownBelowUnaryChild(MultiUnaryNode *currentNode, MultiUnaryNode *childNode) +{ + MultiNode *parentNode = ParentNode((MultiNode *) currentNode); + MultiNode *childChildNode = ChildNode(childNode); + + /* current node's parent now points to the child node */ + ParentSetNewChild(parentNode, (MultiNode *) currentNode, (MultiNode *) childNode); + + /* current node's child becomes its parent */ + SetChild(childNode, (MultiNode *) currentNode); + + /* current node points to the child node's child */ + SetChild(currentNode, childChildNode); +} + + +/* + * PlaceUnaryNodeChild inserts the new node as a child node under the given + * unary node. The function also places the previous child node under the new + * child node. + */ +static void +PlaceUnaryNodeChild(MultiUnaryNode *unaryNode, MultiUnaryNode *newChildNode) +{ + MultiNode *oldChildNode = ChildNode(unaryNode); + + SetChild(unaryNode, (MultiNode *) newChildNode); + SetChild(newChildNode, oldChildNode); +} + + +/* + * PlaceBinaryNodeLeftChild inserts the new left child as the binary node's left + * child. The function also places the previous left child below the new child + * node. + */ +static void +PlaceBinaryNodeLeftChild(MultiBinaryNode *binaryNode, MultiUnaryNode *newLeftChildNode) +{ + if (newLeftChildNode == NULL) + { + return; + } + + SetChild(newLeftChildNode, binaryNode->leftChildNode); + SetLeftChild(binaryNode, (MultiNode *) newLeftChildNode); +} + + +/* + * PlaceBinaryNodeRightChild inserts the new right child as the binary node's + * right child. The function also places the previous right child below the new + * child node. + */ +static void +PlaceBinaryNodeRightChild(MultiBinaryNode *binaryNode, MultiUnaryNode *newRightChildNode) +{ + if (newRightChildNode == NULL) + { + return; + } + + SetChild(newRightChildNode, binaryNode->rightChildNode); + SetRightChild(binaryNode, (MultiNode *) newRightChildNode); +} + + +/* Removes the given unary node from the logical plan, and frees the node. */ +static void +RemoveUnaryNode(MultiUnaryNode *unaryNode) +{ + MultiNode *parentNode = ParentNode((MultiNode *) unaryNode); + MultiNode *childNode = ChildNode(unaryNode); + + /* set parent to directly point to unary node's child */ + ParentSetNewChild(parentNode, (MultiNode *) unaryNode, childNode); + + pfree(unaryNode); +} + + +/* Pulls up the given current node above its parent node. */ +static void +PullUpUnaryNode(MultiUnaryNode *unaryNode) +{ + MultiNode *parentNode = ParentNode((MultiNode *) unaryNode); + bool unaryParent = UnaryOperator(parentNode); + bool binaryParent = BinaryOperator(parentNode); + + if (unaryParent) + { + /* pulling up a node is the same as pushing down the node's unary parent */ + MultiUnaryNode *unaryParentNode = (MultiUnaryNode *) parentNode; + PushDownBelowUnaryChild(unaryParentNode, unaryNode); + } + else if (binaryParent) + { + MultiBinaryNode *binaryParentNode = (MultiBinaryNode *) parentNode; + MultiNode *parentParentNode = ParentNode((MultiNode *) binaryParentNode); + MultiNode *childNode = unaryNode->childNode; + + /* make the parent node point to the unary node's child node */ + if (binaryParentNode->leftChildNode == ((MultiNode *) unaryNode)) + { + SetLeftChild(binaryParentNode, childNode); + } + else + { + SetRightChild(binaryParentNode, childNode); + } + + /* make the parent parent node point to the unary node */ + ParentSetNewChild(parentParentNode, parentNode, (MultiNode *) unaryNode); + + /* make the unary node point to the (old) parent node */ + SetChild(unaryNode, parentNode); + } +} + + +/* + * ParentSetNewChild takes in the given parent node, and replaces the parent's + * old child node with the new child node. The function needs the old child node + * in case the parent is a binary node and the function needs to determine which + * side of the parent node the new child node needs to go to. + */ +static void +ParentSetNewChild(MultiNode *parentNode, MultiNode *oldChildNode, + MultiNode *newChildNode) +{ + bool unaryParent = UnaryOperator(parentNode); + bool binaryParent = BinaryOperator(parentNode); + + if (unaryParent) + { + MultiUnaryNode *unaryParentNode = (MultiUnaryNode *) parentNode; + SetChild(unaryParentNode, newChildNode); + } + else if (binaryParent) + { + MultiBinaryNode *binaryParentNode = (MultiBinaryNode *) parentNode; + + /* determine which side of the parent the old child is on */ + if (binaryParentNode->leftChildNode == oldChildNode) + { + SetLeftChild(binaryParentNode, newChildNode); + } + else + { + SetRightChild(binaryParentNode, newChildNode); + } + } +} + + +/* + * ApplyExtendedOpNodes replaces the original extended operator node with the + * master and worker extended operator nodes. The function then pushes down the + * worker node below the original node's child node. Note that for the push down + * to apply, the original node's child must be a collect node. + */ +static void +ApplyExtendedOpNodes(MultiExtendedOp *originalNode, MultiExtendedOp *masterNode, + MultiExtendedOp *workerNode) +{ + MultiNode *parentNode = ParentNode((MultiNode *) originalNode); + MultiNode *collectNode = ChildNode((MultiUnaryNode *) originalNode); + MultiNode *collectChildNode = ChildNode((MultiUnaryNode *) collectNode); + + /* original node's child must be a collect node */ + Assert(CitusIsA(collectNode, MultiCollect)); + Assert(UnaryOperator(parentNode)); + + /* swap the original aggregate node with the master extended node */ + SetChild((MultiUnaryNode *) parentNode, (MultiNode *) masterNode); + SetChild((MultiUnaryNode *) masterNode, (MultiNode *) collectNode); + + /* add the worker extended node below the collect node */ + SetChild((MultiUnaryNode *) collectNode, (MultiNode *) workerNode); + SetChild((MultiUnaryNode *) workerNode, (MultiNode *) collectChildNode); + + /* clean up the original extended operator node */ + pfree(originalNode); +} + + +/* + * TransformSubqueryNode splits the extended operator node under subquery + * multi table node into its equivalent master and worker operator nodes, and + * we transform aggregate functions accordingly for the master and worker + * operator nodes. We create a partition node based on the first group by + * column of the extended operator node and set it as the child of the master + * operator node. + */ +static void +TransformSubqueryNode(MultiTable *subqueryNode) +{ + MultiExtendedOp *extendedOpNode = + (MultiExtendedOp *) ChildNode((MultiUnaryNode *) subqueryNode); + MultiNode *collectNode = ChildNode((MultiUnaryNode *) extendedOpNode); + MultiNode *collectChildNode = ChildNode((MultiUnaryNode *) collectNode); + MultiExtendedOp *masterExtendedOpNode = MasterExtendedOpNode(extendedOpNode); + MultiExtendedOp *workerExtendedOpNode = WorkerExtendedOpNode(extendedOpNode); + MultiPartition *partitionNode = CitusMakeNode(MultiPartition); + + List *groupClauseList = extendedOpNode->groupClauseList; + List *targetEntryList = extendedOpNode->targetList; + List *groupTargetEntryList = GroupTargetEntryList(groupClauseList, targetEntryList); + TargetEntry *groupByTargetEntry = (TargetEntry *) linitial(groupTargetEntryList); + Expr *groupByExpression = groupByTargetEntry->expr; + + /* + * If group by is on a function expression, then we create a new column from + * function expression result type. Because later while creating partition + * tasks, we expect a column type to partition intermediate results. + * Note that we will only need partition type. So we set column type to + * result type of the function expression, and set other fields of column to + * default values. + */ + if (IsA(groupByExpression, Var)) + { + partitionNode->partitionColumn = (Var *) groupByExpression; + } + else if (IsA(groupByExpression, FuncExpr)) + { + FuncExpr *functionExpression = (FuncExpr *) groupByExpression; + Index tableId = 0; + AttrNumber columnAttributeNumber = InvalidAttrNumber; + Oid columnType = functionExpression->funcresulttype; + int32 columnTypeMod = -1; + Oid columnCollationOid = InvalidOid; + Index columnLevelSup = 0; + + Var *partitionColumn = makeVar(tableId, columnAttributeNumber, columnType, + columnTypeMod, columnCollationOid, columnLevelSup); + partitionNode->partitionColumn = partitionColumn; + } + else + { + ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("cannot run this subquery"), + errdetail("Currently only columns and function expressions " + "are allowed in group by expression of subqueries"))); + } + + SetChild((MultiUnaryNode *) subqueryNode, (MultiNode *) masterExtendedOpNode); + SetChild((MultiUnaryNode *) masterExtendedOpNode, (MultiNode *) partitionNode); + SetChild((MultiUnaryNode *) partitionNode, (MultiNode *) collectNode); + SetChild((MultiUnaryNode *) collectNode, (MultiNode *) workerExtendedOpNode); + SetChild((MultiUnaryNode *) workerExtendedOpNode, (MultiNode *) collectChildNode); +} + + +/* + * MasterExtendedOpNode creates the master extended operator node from the given + * target entries. The function walks over these target entries; and for entries + * with aggregates in them, this function calls the aggregate expression mutator + * function. + * + * Note that the function logically depends on the worker extended operator node + * function. If the target entry does not contain aggregate functions, we assume + * all work is done on the worker side, and create a column that references the + * worker nodes' results. + */ +static MultiExtendedOp * +MasterExtendedOpNode(MultiExtendedOp *originalOpNode) +{ + MultiExtendedOp *masterExtendedOpNode = NULL; + List *targetEntryList = originalOpNode->targetList; + List *newTargetEntryList = NIL; + ListCell *targetEntryCell = NULL; + AttrNumber columnId = 1; + + /* iterate over original target entries */ + foreach(targetEntryCell, targetEntryList) + { + TargetEntry *originalTargetEntry = (TargetEntry *) lfirst(targetEntryCell); + TargetEntry *newTargetEntry = copyObject(originalTargetEntry); + Expr *originalExpression = originalTargetEntry->expr; + Expr *newExpression = NULL; + + bool hasAggregates = contain_agg_clause((Node *) originalExpression); + if (hasAggregates) + { + Node *newNode = MasterAggregateMutator((Node*) originalExpression, + &columnId); + newExpression = (Expr *) newNode; + } + else + { + /* + * The expression does not have any aggregates. We simply make it + * reference the output generated by worker nodes. + */ + const uint32 masterTableId = 1; /* only one table on master node */ + + Var *column = makeVarFromTargetEntry(masterTableId, originalTargetEntry); + column->varattno = columnId; + column->varoattno = columnId; + columnId++; + + newExpression = (Expr *) column; + } + + newTargetEntry->expr = newExpression; + newTargetEntryList = lappend(newTargetEntryList, newTargetEntry); + } + + masterExtendedOpNode = CitusMakeNode(MultiExtendedOp); + masterExtendedOpNode->targetList = newTargetEntryList; + masterExtendedOpNode->groupClauseList = originalOpNode->groupClauseList; + masterExtendedOpNode->sortClauseList = originalOpNode->sortClauseList; + masterExtendedOpNode->limitCount = originalOpNode->limitCount; + + return masterExtendedOpNode; +} + + +/* + * MasterAggregateMutator walks over the original target entry expression, and + * creates the new expression tree to execute on the master node. The function + * transforms aggregates, and copies columns; and recurses into the expression + * mutator function for all other expression types. + * + * Please note that the recursive mutator function traverses the expression tree + * in depth first order. For this function to set attribute numbers correctly, + * WorkerAggregateWalker() *must* walk over the expression tree in the same + * depth first order. + */ +static Node * +MasterAggregateMutator(Node *originalNode, AttrNumber *columnId) +{ + Node *newNode = NULL; + if (originalNode == NULL) + { + return NULL; + } + + if (IsA(originalNode, Aggref)) + { + Aggref *originalAggregate = (Aggref *) originalNode; + Expr *newExpression = MasterAggregateExpression(originalAggregate, columnId); + + newNode = (Node *) newExpression; + } + else if (IsA(originalNode, Var)) + { + uint32 masterTableId = 1; /* one table on the master node */ + Var *newColumn = copyObject(originalNode); + newColumn->varno = masterTableId; + newColumn->varattno = (*columnId); + (*columnId)++; + + newNode = (Node *) newColumn; + } + else + { + newNode = expression_tree_mutator(originalNode, MasterAggregateMutator, + (void *) columnId); + } + + return newNode; +} + + +/* + * MasterAggregateExpression creates the master aggregate expression using the + * original aggregate and aggregate's type information. This function handles + * the average, count, and array_agg aggregates separately due to differences + * in these aggregate functions' transformations. + * + * Note that this function has implicit knowledge of the transformations applied + * for worker nodes on the original aggregate. The function uses this implicit + * knowledge to create the appropriate master function with correct data types. + */ +static Expr * +MasterAggregateExpression(Aggref *originalAggregate, AttrNumber *columnId) +{ + AggregateType aggregateType = GetAggregateType(originalAggregate->aggfnoid); + Expr *newMasterExpression = NULL; + Expr *typeConvertedExpression = NULL; + const uint32 masterTableId = 1; /* one table on the master node */ + const Index columnLevelsUp = 0; /* normal column */ + const AttrNumber argumentId = 1; /* our aggregates have single arguments */ + + if (aggregateType == AGGREGATE_COUNT && originalAggregate->aggdistinct && + CountDistinctErrorRate != DISABLE_DISTINCT_APPROXIMATION) + { + /* + * If enabled, we check for count(distinct) approximations before count + * distincts. For this, we first compute hll_add_agg(hll_hash(column) on + * worker nodes, and get hll values. We then gather hlls on the master + * node, and compute hll_cardinality(hll_union_agg(hll)). + */ + const int argCount = 1; + const int defaultTypeMod = -1; + + TargetEntry *hllTargetEntry = NULL; + Aggref *unionAggregate = NULL; + FuncExpr *cardinalityExpression = NULL; + + Oid unionFunctionId = FunctionOid(HLL_UNION_AGGREGATE_NAME, argCount); + Oid cardinalityFunctionId = FunctionOid(HLL_CARDINALITY_FUNC_NAME, argCount); + Oid cardinalityReturnType = get_func_rettype(cardinalityFunctionId); + + Oid hllType = TypenameGetTypid(HLL_TYPE_NAME); + Oid hllTypeCollationId = get_typcollation(hllType); + Var *hllColumn = makeVar(masterTableId, (*columnId), hllType, defaultTypeMod, + hllTypeCollationId, columnLevelsUp); + (*columnId)++; + + hllTargetEntry = makeTargetEntry((Expr *) hllColumn, argumentId, NULL, false); + + unionAggregate = makeNode(Aggref); + unionAggregate->aggfnoid = unionFunctionId; + unionAggregate->aggtype = hllType; + unionAggregate->args = list_make1(hllTargetEntry); + unionAggregate->aggkind = AGGKIND_NORMAL; + + cardinalityExpression = makeNode(FuncExpr); + cardinalityExpression->funcid = cardinalityFunctionId; + cardinalityExpression->funcresulttype = cardinalityReturnType; + cardinalityExpression->args = list_make1(unionAggregate); + + newMasterExpression = (Expr *) cardinalityExpression; + } + else if (aggregateType == AGGREGATE_AVERAGE) + { + /* + * If the original aggregate is an average, we first compute sum(colum) + * and count(column) on worker nodes. Then, we compute (sum(sum(column)) + * / sum(count(column))) on the master node. + */ + const char *sumAggregateName = AggregateNames[AGGREGATE_SUM]; + const char *countAggregateName = AggregateNames[AGGREGATE_COUNT]; + + Oid argumentType = AggregateArgumentType(originalAggregate); + + Oid sumFunctionId = AggregateFunctionOid(sumAggregateName, argumentType); + Oid countFunctionId = AggregateFunctionOid(countAggregateName, ANYOID); + + /* calculate the aggregate types that worker nodes are going to return */ + Oid workerSumReturnType = get_func_rettype(sumFunctionId); + Oid workerCountReturnType = get_func_rettype(countFunctionId); + + /* create the expression sum(sum(column) / sum(count(column))) */ + newMasterExpression = MasterAverageExpression(workerSumReturnType, + workerCountReturnType, + columnId); + } + else if (aggregateType == AGGREGATE_COUNT) + { + /* + * Count aggregates are handled in two steps. First, worker nodes report + * their count results. Then, the master node sums up these results. + */ + Var *column = NULL; + TargetEntry *columnTargetEntry = NULL; + + /* worker aggregate and original aggregate have the same return type */ + Oid workerReturnType = exprType((Node *) originalAggregate); + int32 workerReturnTypeMod = exprTypmod((Node *) originalAggregate); + Oid workerCollationId = exprCollation((Node *) originalAggregate); + + const char *sumAggregateName = AggregateNames[AGGREGATE_SUM]; + Oid sumFunctionId = AggregateFunctionOid(sumAggregateName, workerReturnType); + Oid masterReturnType = get_func_rettype(sumFunctionId); + + Aggref *newMasterAggregate = copyObject(originalAggregate); + newMasterAggregate->aggstar = false; + newMasterAggregate->aggdistinct = NULL; + newMasterAggregate->aggfnoid = sumFunctionId; + newMasterAggregate->aggtype = masterReturnType; + + column = makeVar(masterTableId, (*columnId), workerReturnType, + workerReturnTypeMod, workerCollationId, columnLevelsUp); + (*columnId)++; + + /* aggref expects its arguments to be wrapped in target entries */ + columnTargetEntry = makeTargetEntry((Expr *) column, argumentId, NULL, false); + newMasterAggregate->args = list_make1(columnTargetEntry); + + newMasterExpression = (Expr *) newMasterAggregate; + } + else if (aggregateType == AGGREGATE_ARRAY_AGG) + { + /* + * Array aggregates are handled in two steps. First, we compute array_agg() + * on the worker nodes. Then, we gather the arrays on the master and + * compute the array_cat_agg() aggregate on them to get the final array. + */ + Var *column = NULL; + TargetEntry *arrayCatAggArgument = NULL; + Aggref *newMasterAggregate = NULL; + Oid aggregateFunctionId = InvalidOid; + + /* worker aggregate and original aggregate have same return type */ + Oid workerReturnType = exprType((Node *) originalAggregate); + int32 workerReturnTypeMod = exprTypmod((Node *) originalAggregate); + Oid workerCollationId = exprCollation((Node *) originalAggregate); + + /* assert that we do not support array_agg() with distinct or order by */ + Assert(!originalAggregate->aggorder); + Assert(!originalAggregate->aggdistinct); + + /* array_cat_agg() takes anyarray as input */ + aggregateFunctionId = AggregateFunctionOid(ARRAY_CAT_AGGREGATE_NAME, + ANYARRAYOID); + + /* create argument for the array_cat_agg() aggregate */ + column = makeVar(masterTableId, (*columnId), workerReturnType, + workerReturnTypeMod, workerCollationId, columnLevelsUp); + arrayCatAggArgument = makeTargetEntry((Expr *) column, argumentId, NULL, false); + (*columnId)++; + + /* construct the master array_cat_agg() expression */ + newMasterAggregate = copyObject(originalAggregate); + newMasterAggregate->aggfnoid = aggregateFunctionId; + newMasterAggregate->args = list_make1(arrayCatAggArgument); + + newMasterExpression = (Expr *) newMasterAggregate; + } + else + { + /* + * All other aggregates are handled as they are. These include sum, min, + * and max. + */ + Var *column = NULL; + TargetEntry *columnTargetEntry = NULL; + + /* worker aggregate and original aggregate have the same return type */ + Oid workerReturnType = exprType((Node *) originalAggregate); + int32 workerReturnTypeMod = exprTypmod((Node *) originalAggregate); + Oid workerCollationId = exprCollation((Node *) originalAggregate); + + const char *aggregateName = AggregateNames[aggregateType]; + Oid aggregateFunctionId = AggregateFunctionOid(aggregateName, workerReturnType); + Oid masterReturnType = get_func_rettype(aggregateFunctionId); + + Aggref *newMasterAggregate = copyObject(originalAggregate); + newMasterAggregate->aggdistinct = NULL; + newMasterAggregate->aggfnoid = aggregateFunctionId; + newMasterAggregate->aggtype = masterReturnType; + + column = makeVar(masterTableId, (*columnId), workerReturnType, + workerReturnTypeMod, workerCollationId, columnLevelsUp); + (*columnId)++; + + /* aggref expects its arguments to be wrapped in target entries */ + columnTargetEntry = makeTargetEntry((Expr *) column, argumentId, NULL, false); + newMasterAggregate->args = list_make1(columnTargetEntry); + + newMasterExpression = (Expr *) newMasterAggregate; + } + + /* + * Aggregate functions could have changed the return type. If so, we wrap + * the new expression with a conversion function to make it have the same + * type as the original aggregate. We need this since functions like sorting + * and grouping have already been chosen based on the original type. + */ + typeConvertedExpression = AddTypeConversion((Node *) originalAggregate, + (Node *) newMasterExpression); + if (typeConvertedExpression != NULL) + { + newMasterExpression = typeConvertedExpression; + } + + return newMasterExpression; +} + + +/* + * MasterAverageExpression creates an expression of the form (sum(column1) / + * sum(column2)), where column1 is the sum of the original value, and column2 is + * the count of that value. This expression allows us to evaluate the average + * function over distributed data. + */ +static Expr * +MasterAverageExpression(Oid sumAggregateType, Oid countAggregateType, + AttrNumber *columnId) +{ + const char *sumAggregateName = AggregateNames[AGGREGATE_SUM]; + const uint32 masterTableId = 1; + const int32 defaultTypeMod = -1; + const Index defaultLevelsUp = 0; + const AttrNumber argumentId = 1; + + Oid sumTypeCollationId = get_typcollation(sumAggregateType); + Oid countTypeCollationId = get_typcollation(countAggregateType); + Var *firstColumn = NULL; + Var *secondColumn = NULL; + TargetEntry *firstTargetEntry = NULL; + TargetEntry *secondTargetEntry = NULL; + Aggref *firstSum = NULL; + Aggref *secondSum = NULL; + List *operatorNameList = NIL; + Expr *opExpr = NULL; + + /* create the first argument for sum(column1) */ + firstColumn = makeVar(masterTableId, (*columnId), sumAggregateType, + defaultTypeMod, sumTypeCollationId, defaultLevelsUp); + firstTargetEntry = makeTargetEntry((Expr *) firstColumn, argumentId, NULL, false); + (*columnId)++; + + firstSum = makeNode(Aggref); + firstSum->aggfnoid = AggregateFunctionOid(sumAggregateName, sumAggregateType); + firstSum->aggtype = get_func_rettype(firstSum->aggfnoid); + firstSum->args = list_make1(firstTargetEntry); + firstSum->aggkind = AGGKIND_NORMAL; + + /* create the second argument for sum(column2) */ + secondColumn = makeVar(masterTableId, (*columnId), countAggregateType, + defaultTypeMod, countTypeCollationId, defaultLevelsUp); + secondTargetEntry = makeTargetEntry((Expr *) secondColumn, argumentId, NULL, false); + (*columnId)++; + + secondSum = makeNode(Aggref); + secondSum->aggfnoid = AggregateFunctionOid(sumAggregateName, countAggregateType); + secondSum->aggtype = get_func_rettype(secondSum->aggfnoid); + secondSum->args = list_make1(secondTargetEntry); + secondSum->aggkind = AGGKIND_NORMAL; + + /* + * Build the division operator between these two aggregates. This function + * will convert the types of the aggregates if necessary. + */ + operatorNameList = list_make1(makeString(DIVISION_OPER_NAME)); + opExpr = make_op(NULL, operatorNameList, (Node *) firstSum, (Node *) secondSum, -1); + + return opExpr; +} + + +/* + * AddTypeConversion checks if the given expressions generate the same types. If + * they don't, the function adds a type conversion function on top of the new + * expression to have it generate the same type as the original aggregate. + */ +static Expr * +AddTypeConversion(Node *originalAggregate, Node *newExpression) +{ + Oid newTypeId = exprType(newExpression); + Oid originalTypeId = exprType(originalAggregate); + int32 originalTypeMod = exprTypmod(originalAggregate); + Node *typeConvertedExpression = NULL; + + /* nothing to do if the two types are the same */ + if (originalTypeId == newTypeId) + { + return NULL; + } + + /* otherwise, add a type conversion function */ + typeConvertedExpression = coerce_to_target_type(NULL, newExpression, newTypeId, + originalTypeId, originalTypeMod, + COERCION_EXPLICIT, + COERCE_EXPLICIT_CAST, -1); + Assert(typeConvertedExpression != NULL); + return (Expr *) typeConvertedExpression; +} + + +/* + * WorkerExtendedOpNode creates the worker extended operator node from the given + * target entries. The function walks over these target entries; and for entries + * with aggregates in them, this function calls the recursive aggregate walker + * function to create aggregates for the worker nodes. Also, the function checks + * if we can push down the limit to worker nodes; and if we can, sets the limit + * count and sort clause list fields in the new operator node. + */ +static MultiExtendedOp * +WorkerExtendedOpNode(MultiExtendedOp *originalOpNode) +{ + MultiExtendedOp *workerExtendedOpNode = NULL; + List *targetEntryList = originalOpNode->targetList; + List *newTargetEntryList = NIL; + ListCell *targetEntryCell = NULL; + AttrNumber targetProjectionNumber = 1; + + /* iterate over original target entries */ + foreach(targetEntryCell, targetEntryList) + { + TargetEntry *originalTargetEntry = (TargetEntry *) lfirst(targetEntryCell); + Expr *originalExpression = originalTargetEntry->expr; + List *newExpressionList = NIL; + ListCell *newExpressionCell = NULL; + + bool hasAggregates = contain_agg_clause((Node *) originalExpression); + if (hasAggregates) + { + WorkerAggregateWalker((Node *) originalExpression, &newExpressionList); + } + else + { + newExpressionList = list_make1(originalExpression); + } + + /* now create target entries for each new expression */ + foreach(newExpressionCell, newExpressionList) + { + Expr *newExpression = (Expr *) lfirst(newExpressionCell); + TargetEntry *newTargetEntry = copyObject(originalTargetEntry); + newTargetEntry->expr = newExpression; + + if (newTargetEntry->resname == NULL) + { + StringInfo columnNameString = makeStringInfo(); + appendStringInfo(columnNameString, WORKER_COLUMN_FORMAT, + targetProjectionNumber); + + newTargetEntry->resname = columnNameString->data; + } + + /* force resjunk to false as we may need this on the master */ + newTargetEntry->resjunk = false; + newTargetEntry->resno = targetProjectionNumber; + targetProjectionNumber++; + + newTargetEntryList = lappend(newTargetEntryList, newTargetEntry); + } + } + + workerExtendedOpNode = CitusMakeNode(MultiExtendedOp); + workerExtendedOpNode->targetList = newTargetEntryList; + workerExtendedOpNode->groupClauseList = originalOpNode->groupClauseList; + + /* if we can push down the limit, also set related fields */ + workerExtendedOpNode->limitCount = WorkerLimitCount(originalOpNode); + workerExtendedOpNode->sortClauseList = WorkerSortClauseList(originalOpNode); + + return workerExtendedOpNode; +} + + +/* + * WorkerAggregateWalker walks over the original target entry expression, and + * creates the list of expression trees (potentially more than one) to execute + * on the worker nodes. The function creates new expressions for aggregates and + * columns; and recurses into expression_tree_walker() for all other expression + * types. + */ +static bool +WorkerAggregateWalker(Node *node, List **newExpressionList) +{ + bool walkerResult = false; + if (node == NULL) + { + return false; + } + + if (IsA(node, Aggref)) + { + Aggref *originalAggregate = (Aggref *) node; + List *workerAggregateList = WorkerAggregateExpressionList(originalAggregate); + + (*newExpressionList) = list_concat(*newExpressionList, workerAggregateList); + } + else if (IsA(node, Var)) + { + Var *originalColumn = (Var *) node; + (*newExpressionList) = lappend(*newExpressionList, originalColumn); + } + else + { + walkerResult = expression_tree_walker(node, WorkerAggregateWalker, + (void *) newExpressionList); + } + + return walkerResult; +} + + +/* + * WorkerAggregateExpressionList takes in the original aggregate function, and + * determines the transformed aggregate functions to execute on worker nodes. + * The function then returns these aggregates in a list. + */ +static List * +WorkerAggregateExpressionList(Aggref *originalAggregate) +{ + AggregateType aggregateType = GetAggregateType(originalAggregate->aggfnoid); + List *workerAggregateList = NIL; + + if (aggregateType == AGGREGATE_COUNT && originalAggregate->aggdistinct && + CountDistinctErrorRate != DISABLE_DISTINCT_APPROXIMATION) + { + /* + * If the original aggregate is a count(distinct) approximation, we want + * to compute hll_add_agg(hll_hash(var), storageSize) on worker nodes. + */ + const AttrNumber firstArgumentId = 1; + const AttrNumber secondArgumentId = 2; + const int hashArgumentCount = 2; + const int addArgumentCount = 2; + + TargetEntry *hashedColumnArgument = NULL; + TargetEntry *storageSizeArgument = NULL; + List *addAggregateArgumentList = NIL; + Aggref *addAggregateFunction = NULL; + + /* init hll_hash() related variables */ + Oid argumentType = AggregateArgumentType(originalAggregate); + TargetEntry *argument = (TargetEntry *) linitial(originalAggregate->args); + Expr *argumentExpression = copyObject(argument->expr); + + char *hashFunctionName = CountDistinctHashFunctionName(argumentType); + Oid hashFunctionId = FunctionOid(hashFunctionName, hashArgumentCount); + Oid hashFunctionReturnType = get_func_rettype(hashFunctionId); + + /* init hll_add_agg() related variables */ + Oid addFunctionId = FunctionOid(HLL_ADD_AGGREGATE_NAME, addArgumentCount); + Oid hllType = TypenameGetTypid(HLL_TYPE_NAME); + int logOfStorageSize = CountDistinctStorageSize(CountDistinctErrorRate); + Const *logOfStorageSizeConst = MakeIntegerConst(logOfStorageSize); + + /* construct hll_hash() expression */ + FuncExpr *hashFunction = makeNode(FuncExpr); + hashFunction->funcid = hashFunctionId; + hashFunction->funcresulttype = hashFunctionReturnType; + hashFunction->args = list_make1(argumentExpression); + + /* construct hll_add_agg() expression */ + hashedColumnArgument = makeTargetEntry((Expr *) hashFunction, + firstArgumentId, NULL, false); + storageSizeArgument = makeTargetEntry((Expr *) logOfStorageSizeConst, + secondArgumentId, NULL, false); + addAggregateArgumentList = list_make2(hashedColumnArgument, storageSizeArgument); + + addAggregateFunction = makeNode(Aggref); + addAggregateFunction->aggfnoid = addFunctionId; + addAggregateFunction->aggtype = hllType; + addAggregateFunction->args = addAggregateArgumentList; + addAggregateFunction->aggkind = AGGKIND_NORMAL; + + workerAggregateList = lappend(workerAggregateList, addAggregateFunction); + } + else if (aggregateType == AGGREGATE_AVERAGE) + { + /* + * If the original aggregate is an average, we want to compute sum(var) + * and count(var) on worker nodes. + */ + Aggref *sumAggregate = copyObject(originalAggregate); + Aggref *countAggregate = copyObject(originalAggregate); + + /* extract function names for sum and count */ + const char *sumAggregateName = AggregateNames[AGGREGATE_SUM]; + const char *countAggregateName = AggregateNames[AGGREGATE_COUNT]; + + /* + * Find the type of the expression over which we execute the aggregate. + * We then need to find the right sum function for that type. + */ + Oid argumentType = AggregateArgumentType(originalAggregate); + + /* find function implementing sum over the original type */ + sumAggregate->aggfnoid = AggregateFunctionOid(sumAggregateName, argumentType); + sumAggregate->aggtype = get_func_rettype(sumAggregate->aggfnoid); + + /* count has any input type */ + countAggregate->aggfnoid = AggregateFunctionOid(countAggregateName, ANYOID); + countAggregate->aggtype = get_func_rettype(countAggregate->aggfnoid); + + workerAggregateList = lappend(workerAggregateList, sumAggregate); + workerAggregateList = lappend(workerAggregateList, countAggregate); + } + else + { + /* + * All other aggregates are sent as they are to the worker nodes. These + * aggregate functions include sum, count, min, max, and array_agg. + */ + Aggref *workerAggregate = copyObject(originalAggregate); + workerAggregateList = lappend(workerAggregateList, workerAggregate); + } + + return workerAggregateList; +} + + +/* + * GetAggregateType scans pg_catalog.pg_proc for the given aggregate oid, and + * finds the aggregate's name. The function then matches the aggregate's name to + * previously stored strings, and returns the appropriate aggregate type. + */ +static AggregateType +GetAggregateType(Oid aggFunctionId) +{ + char *aggregateProcName = NULL; + uint32 aggregateCount = 0; + uint32 aggregateIndex = 0; + bool found = false; + + /* look up the function name */ + aggregateProcName = get_func_name(aggFunctionId); + if (aggregateProcName == NULL) + { + ereport(ERROR, (errmsg("cache lookup failed for function %u", aggFunctionId))); + } + + aggregateCount = lengthof(AggregateNames); + for (aggregateIndex = 0; aggregateIndex < aggregateCount; aggregateIndex++) + { + const char *aggregateName = AggregateNames[aggregateIndex]; + if (strncmp(aggregateName, aggregateProcName, NAMEDATALEN) == 0) + { + found = true; + break; + } + } + + if (!found) + { + ereport(ERROR, (errmsg("unsupported aggregate function %s", aggregateProcName))); + } + + return aggregateIndex; +} + + +/* Extracts the type of the argument over which the aggregate is operating. */ +static Oid +AggregateArgumentType(Aggref *aggregate) +{ + List *argumentList = aggregate->args; + TargetEntry *argument = (TargetEntry *) linitial(argumentList); + Oid returnTypeId = exprType((Node *) argument->expr); + + /* We currently support aggregates with only one argument; assert that. */ + Assert(list_length(argumentList) == 1); + + return returnTypeId; +} + + +/* + * AggregateFunctionOid performs a reverse lookup on aggregate function name, + * and returns the corresponding aggregate function oid for the given function + * name and input type. + */ +static Oid +AggregateFunctionOid(const char *functionName, Oid inputType) +{ + Oid functionOid = InvalidOid; + Relation procRelation = NULL; + SysScanDesc scanDescriptor = NULL; + ScanKeyData scanKey[1]; + int scanKeyCount = 1; + HeapTuple heapTuple = NULL; + + procRelation = heap_open(ProcedureRelationId, AccessShareLock); + + ScanKeyInit(&scanKey[0], Anum_pg_proc_proname, + BTEqualStrategyNumber, F_NAMEEQ, CStringGetDatum(functionName)); + + scanDescriptor = systable_beginscan(procRelation, + ProcedureNameArgsNspIndexId, true, + NULL, scanKeyCount, scanKey); + + /* loop until we find the right function */ + heapTuple = systable_getnext(scanDescriptor); + while (HeapTupleIsValid(heapTuple)) + { + Form_pg_proc procForm = (Form_pg_proc) GETSTRUCT(heapTuple); + int argumentCount = procForm->pronargs; + + if (argumentCount == 1) + { + /* check if input type and found value type match */ + if (procForm->proargtypes.values[0] == inputType) + { + functionOid = HeapTupleGetOid(heapTuple); + break; + } + } + Assert(argumentCount <= 1); + + heapTuple = systable_getnext(scanDescriptor); + } + + if (functionOid == InvalidOid) + { + ereport(ERROR, (errmsg("no matching oid for function: %s", functionName))); + } + + systable_endscan(scanDescriptor); + heap_close(procRelation, AccessShareLock); + + return functionOid; +} + + +/* + * FunctionOid looks for a function that has the given name and the given number + * of arguments, and returns the corresponding function's oid. + */ +Oid +FunctionOid(const char *functionName, int argumentCount) +{ + FuncCandidateList functionList = NULL; + Oid functionOid = InvalidOid; + + List *qualifiedFunctionName = stringToQualifiedNameList(functionName); + List *argumentList = NIL; + const bool findVariadics = false; + const bool findDefaults = false; + const bool missingOK = true; + + functionList = FuncnameGetCandidates(qualifiedFunctionName, argumentCount, + argumentList, findVariadics, + findDefaults, missingOK); + + if (functionList == NULL) + { + ereport(ERROR, (errcode(ERRCODE_UNDEFINED_FUNCTION), + errmsg("function \"%s\" does not exist", functionName))); + } + else if (functionList->next != NULL) + { + ereport(ERROR, (errcode(ERRCODE_AMBIGUOUS_FUNCTION), + errmsg("more than one function named \"%s\"", functionName))); + } + + /* get function oid from function list's head */ + functionOid = functionList->oid; + return functionOid; +} + + +/* + * CountDistinctHashFunctionName resolves the hll_hash function name to use for + * the given input type, and returns this function name. + */ +static char * +CountDistinctHashFunctionName(Oid argumentType) +{ + char *hashFunctionName = NULL; + + /* resolve hash function name based on input argument type */ + switch (argumentType) + { + case INT4OID: + hashFunctionName = pstrdup(HLL_HASH_INTEGER_FUNC_NAME); + break; + + case INT8OID: + hashFunctionName = pstrdup(HLL_HASH_BIGINT_FUNC_NAME); + break; + + case TEXTOID: + case BPCHAROID: + case VARCHAROID: + hashFunctionName = pstrdup(HLL_HASH_TEXT_FUNC_NAME); + break; + + default: + hashFunctionName = pstrdup(HLL_HASH_ANY_FUNC_NAME); + break; + } + + return hashFunctionName; +} + + +/* + * CountDistinctStorageSize takes in the desired precision for count distinct + * approximations, and returns the log-base-2 of storage space needed for the + * HyperLogLog algorithm. + */ +static int +CountDistinctStorageSize(double approximationErrorRate) +{ + double desiredStorageSize = pow((1.04 / approximationErrorRate), 2); + double logOfDesiredStorageSize = log(desiredStorageSize) / log(2); + + /* keep log2(storage size) inside allowed range */ + int logOfStorageSize = (int) rint(logOfDesiredStorageSize); + if (logOfStorageSize < 4) + { + logOfStorageSize = 4; + } + else if (logOfStorageSize > 17) + { + logOfStorageSize = 17; + } + + return logOfStorageSize; +} + + +/* Makes an integer constant node from the given value, and returns that node. */ +static Const * +MakeIntegerConst(int32 integerValue) +{ + const int typeCollationId = get_typcollation(INT4OID); + const int16 typeLength = get_typlen(INT4OID); + const int32 typeModifier = -1; + const bool typeIsNull = false; + const bool typePassByValue = true; + + Datum integerDatum = Int32GetDatum(integerValue); + Const *integerConst = makeConst(INT4OID, typeModifier, typeCollationId, typeLength, + integerDatum, typeIsNull, typePassByValue); + + return integerConst; +} + + +/* + * ErrorIfContainsUnsupportedAggregate extracts aggregate expressions from the + * logical plan, walks over them and uses helper functions to check if we can + * transform these aggregate expressions and push them down to worker nodes. + * These helper functions error out if we cannot transform the aggregates. + */ +static void +ErrorIfContainsUnsupportedAggregate(MultiNode *logicalPlanNode) +{ + List *opNodeList = FindNodesOfType(logicalPlanNode, T_MultiExtendedOp); + MultiExtendedOp *extendedOpNode = (MultiExtendedOp *) linitial(opNodeList); + + List *targetList = extendedOpNode->targetList; + List *expressionList = pull_var_clause((Node *) targetList, PVC_INCLUDE_AGGREGATES, + PVC_REJECT_PLACEHOLDERS); + + ListCell *expressionCell = NULL; + foreach(expressionCell, expressionList) + { + Node *expression = (Node *) lfirst(expressionCell); + Aggref *aggregateExpression = NULL; + AggregateType aggregateType = AGGREGATE_INVALID_FIRST; + + /* only consider aggregate expressions */ + if (!IsA(expression, Aggref)) + { + continue; + } + + /* GetAggregateType errors out on unsupported aggregate types */ + aggregateExpression = (Aggref *) expression; + aggregateType = GetAggregateType(aggregateExpression->aggfnoid); + Assert(aggregateType != AGGREGATE_INVALID_FIRST); + + /* + * Check that we can transform the current aggregate expression. These + * functions error out on unsupported array_agg and aggregate (distinct) + * clauses. + */ + if (aggregateType == AGGREGATE_ARRAY_AGG) + { + ErrorIfUnsupportedArrayAggregate(aggregateExpression); + } + else if (aggregateExpression->aggdistinct) + { + ErrorIfUnsupportedAggregateDistinct(aggregateExpression, logicalPlanNode); + } + } +} + + +/* + * ErrorIfUnsupportedArrayAggregate checks if we can transform the array aggregate + * expression and push it down to the worker node. If we cannot transform the + * aggregate, this function errors. + */ +static void +ErrorIfUnsupportedArrayAggregate(Aggref *arrayAggregateExpression) +{ + /* if array_agg has order by, we error out */ + if (arrayAggregateExpression->aggorder) + { + ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("array_agg with order by is unsupported"))); + } + + /* if array_agg has distinct, we error out */ + if (arrayAggregateExpression->aggdistinct) + { + ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("array_agg (distinct) is unsupported"))); + } +} + + +/* + * ErrorIfUnsupportedAggregateDistinct checks if we can transform the aggregate + * (distinct expression) and push it down to the worker node. It handles count + * (distinct) separately to check if we can use distinct approximations. If we + * cannot transform the aggregate, this function errors. + */ +static void +ErrorIfUnsupportedAggregateDistinct(Aggref *aggregateExpression, + MultiNode *logicalPlanNode) +{ + char *errorDetail = NULL; + bool distinctSupported = true; + List *repartitionNodeList = NIL; + Var *distinctColumn = NULL; + + AggregateType aggregateType = GetAggregateType(aggregateExpression->aggfnoid); + + /* check if logical plan includes a subquery */ + List *subqueryMultiTableList = SubqueryMultiTableList(logicalPlanNode); + if (subqueryMultiTableList != NIL) + { + ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("cannot push down this subquery"), + errdetail("distinct in the outermost query is unsupported"))); + } + + /* if we have a count(distinct), and distinct approximation is enabled */ + if (aggregateType == AGGREGATE_COUNT && + CountDistinctErrorRate != DISABLE_DISTINCT_APPROXIMATION) + { + bool missingOK = true; + Oid distinctExtensionId = get_extension_oid(HLL_EXTENSION_NAME, missingOK); + + /* if extension for distinct approximation is loaded, we are good */ + if (distinctExtensionId != InvalidOid) + { + return; + } + else + { + ereport(ERROR, (errmsg("cannot compute count (distinct) approximation"), + errhint("You need to have the hll extension loaded."))); + } + } + + repartitionNodeList = FindNodesOfType(logicalPlanNode, T_MultiPartition); + if (repartitionNodeList != NIL) + { + distinctSupported = false; + errorDetail = "aggregate (distinct) with table repartitioning is unsupported"; + } + + distinctColumn = AggregateDistinctColumn(aggregateExpression); + if (distinctColumn == NULL) + { + distinctSupported = false; + errorDetail = "aggregate (distinct) on complex expressions is unsupported"; + } + else + { + List *tableNodeList = FindNodesOfType(logicalPlanNode, T_MultiTable); + + List *opNodeList = FindNodesOfType(logicalPlanNode, T_MultiExtendedOp); + MultiExtendedOp *extendedOpNode = (MultiExtendedOp *) linitial(opNodeList); + + bool supports = TablePartitioningSupportsDistinct(tableNodeList, extendedOpNode, + distinctColumn); + if (!supports) + { + distinctSupported = false; + errorDetail = "table partitioning is unsuitable for aggregate (distinct)"; + } + } + + /* if current aggregate expression isn't supported, error out */ + if (!distinctSupported) + { + if (aggregateType == AGGREGATE_COUNT) + { + ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("cannot compute aggregate (distinct)"), + errdetail("%s", errorDetail), + errhint("You can load the hll extension from contrib " + "packages and enable distinct approximations."))); + } + else + { + ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("cannot compute aggregate (distinct)"), + errdetail("%s", errorDetail))); + } + } +} + + +/* + * AggregateDistinctColumn checks if the given aggregate expression's distinct + * clause is on a single column. If it is, the function finds and returns that + * column. Otherwise, the function returns null. + */ +static Var * +AggregateDistinctColumn(Aggref *aggregateExpression) +{ + Var *aggregateColumn = NULL; + int aggregateArgumentCount = 0; + TargetEntry *aggregateTargetEntry = NULL; + + /* only consider aggregates with distincts */ + if (!aggregateExpression->aggdistinct) + { + return NULL; + } + + aggregateArgumentCount = list_length(aggregateExpression->args); + if (aggregateArgumentCount != 1) + { + return NULL; + } + + aggregateTargetEntry = (TargetEntry *) linitial(aggregateExpression->args); + if (!IsA(aggregateTargetEntry->expr, Var)) + { + return NULL; + } + + aggregateColumn = (Var *) aggregateTargetEntry->expr; + return aggregateColumn; +} + + +/* + * TablePartitioningSupportsDistinct walks over all tables in the given list and + * checks that each table's partitioning method is suitable for pushing down an + * aggregate (distinct) expression to worker nodes. For this, the function needs + * to check that task results do not overlap with one another on the distinct + * column. + */ +static bool +TablePartitioningSupportsDistinct(List *tableNodeList, MultiExtendedOp *opNode, + Var *distinctColumn) +{ + bool distinctSupported = true; + ListCell *tableNodeCell = NULL; + + foreach(tableNodeCell, tableNodeList) + { + MultiTable *tableNode = (MultiTable *) lfirst(tableNodeCell); + Oid relationId = tableNode->relationId; + bool tableDistinctSupported = false; + char partitionMethod = 0; + + /* if table has one shard, task results don't overlap */ + List *shardList = LoadShardList(relationId); + if (list_length(shardList) == 1) + { + continue; + } + + /* + * We need to check that task results don't overlap. We can only do this + * if table is range partitioned. + */ + partitionMethod = PartitionMethod(relationId); + if (partitionMethod == DISTRIBUTE_BY_RANGE) + { + Var *tablePartitionColumn = tableNode->partitionColumn; + bool groupedByPartitionColumn = false; + + /* if distinct is on table partition column, we can push it down */ + if (tablePartitionColumn->varno == distinctColumn->varno && + tablePartitionColumn->varattno == distinctColumn->varattno) + { + tableDistinctSupported = true; + } + + /* if results are grouped by partition column, we can push down */ + groupedByPartitionColumn = GroupedByColumn(opNode->groupClauseList, + opNode->targetList, + tablePartitionColumn); + if (groupedByPartitionColumn) + { + tableDistinctSupported = true; + } + } + + if (!tableDistinctSupported) + { + distinctSupported = false; + break; + } + } + + return distinctSupported; +} + + +/* + * GroupedByColumn walks over group clauses in the given list, and checks if any + * of the group clauses is on the given column. + */ +static bool +GroupedByColumn(List *groupClauseList, List *targetList, Var *column) +{ + bool groupedByColumn = false; + ListCell *groupClauseCell = NULL; + + foreach(groupClauseCell, groupClauseList) + { + SortGroupClause *groupClause = (SortGroupClause *) lfirst(groupClauseCell); + TargetEntry *groupTargetEntry = get_sortgroupclause_tle(groupClause, targetList); + + Expr *groupExpression = (Expr *) groupTargetEntry->expr; + if (IsA(groupExpression, Var)) + { + Var *groupColumn = (Var *) groupExpression; + if (groupColumn->varno == column->varno && + groupColumn->varattno == column->varattno) + { + groupedByColumn = true; + break; + } + } + } + + return groupedByColumn; +} + + +/* + * ErrorIfContainsUnsupportedSubquery extracts subquery multi table from the + * logical plan and uses helper functions to check if we can push down subquery + * to worker nodes. These helper functions error out if we cannot push down the + * the subquery. + */ +static void +ErrorIfContainsUnsupportedSubquery(MultiNode *logicalPlanNode) +{ + Query *subquery = NULL; + List *extendedOpNodeList = NIL; + MultiTable *multiTable = NULL; + MultiExtendedOp *extendedOpNode = NULL; + bool outerQueryHasLimit = false; + + /* check if logical plan includes a subquery */ + List *subqueryMultiTableList = SubqueryMultiTableList(logicalPlanNode); + if (subqueryMultiTableList == NIL) + { + return; + } + + /* currently in the planner we only allow one subquery in from-clause*/ + Assert(list_length(subqueryMultiTableList) == 1); + + multiTable = (MultiTable *) linitial(subqueryMultiTableList); + subquery = multiTable->subquery; + + extendedOpNodeList = FindNodesOfType(logicalPlanNode, T_MultiExtendedOp); + extendedOpNode = (MultiExtendedOp *) linitial(extendedOpNodeList); + + if (extendedOpNode->limitCount) + { + outerQueryHasLimit = true; + } + + ErrorIfCannotPushdownSubquery(subquery, outerQueryHasLimit); + ErrorIfUnsupportedShardDistribution(subquery); + ErrorIfUnsupportedFilters(subquery); +} + + +/* + * SubqueryMultiTableList extracts multi tables in the given logical plan tree + * and returns subquery multi tables in a new list. + */ +List * +SubqueryMultiTableList(MultiNode *multiNode) +{ + List *subqueryMultiTableList = NIL; + List *multiTableNodeList = FindNodesOfType(multiNode, T_MultiTable); + + ListCell *multiTableNodeCell = NULL; + foreach(multiTableNodeCell, multiTableNodeList) + { + MultiTable *multiTable = (MultiTable *) lfirst(multiTableNodeCell); + Query *subquery = multiTable->subquery; + + if (subquery != NULL) + { + subqueryMultiTableList = lappend(subqueryMultiTableList, multiTable); + } + } + + return subqueryMultiTableList; +} + + +/* + * ErrorIfCannotPushdownSubquery recursively checks if we can push down the given + * subquery to worker nodes. If we cannot push down the subquery, this function + * errors out. + * + * We can push down a subquery if it follows rules below. We support nested queries + * as long as they follow the same rules, and we recurse to validate each subquery + * for this given query. + * a. If there is an aggregate, it must be grouped on partition column. + * b. If there is a join, it must be between two regular tables or two subqueries. + * We don't support join between a regular table and a subquery. And columns on + * the join condition must be partition columns. + * c. If there is a distinct clause, it must be on the partition column. + * + * This function is very similar to ErrorIfQueryNotSupported() in logical + * planner, but we don't reuse it, because differently for subqueries we support + * a subset of distinct, union and left joins. + * + * Note that this list of checks is not exhaustive, there can be some cases + * which we let subquery to run but returned results would be wrong. Such as if + * a subquery has a group by on another subquery which includes order by with + * limit, we let this query to run, but results could be wrong depending on the + * features of underlying tables. + */ +static void +ErrorIfCannotPushdownSubquery(Query *subqueryTree, bool outerQueryHasLimit) +{ + bool preconditionsSatisfied = true; + char *errorDetail = NULL; + Query *lateralQuery = NULL; + List *subqueryEntryList = NIL; + ListCell *rangeTableEntryCell = NULL; + + ErrorIfUnsupportedTableCombination(subqueryTree); + + if (subqueryTree->hasSubLinks) + { + preconditionsSatisfied = false; + errorDetail = "Subqueries other than from-clause subqueries are unsupported"; + } + + if (subqueryTree->hasWindowFuncs) + { + preconditionsSatisfied = false; + errorDetail = "Window functions are currently unsupported"; + } + + if (subqueryTree->limitOffset) + { + preconditionsSatisfied = false; + errorDetail = "Limit Offset clause is currently unsupported"; + } + + if (subqueryTree->limitCount && !outerQueryHasLimit) + { + preconditionsSatisfied = false; + errorDetail = "Limit in subquery without limit in the outer query is unsupported"; + } + + if (subqueryTree->setOperations) + { + SetOperationStmt *setOperationStatement = + (SetOperationStmt *) subqueryTree->setOperations; + + if (setOperationStatement->op == SETOP_UNION) + { + ErrorIfUnsupportedUnionQuery(subqueryTree); + } + else + { + preconditionsSatisfied = false; + errorDetail = "Intersect and Except are currently unsupported"; + } + } + + if (subqueryTree->hasRecursive) + { + preconditionsSatisfied = false; + errorDetail = "Recursive queries are currently unsupported"; + } + + if (subqueryTree->cteList) + { + preconditionsSatisfied = false; + errorDetail = "Common Table Expressions are currently unsupported"; + } + + if (subqueryTree->hasForUpdate) + { + preconditionsSatisfied = false; + errorDetail = "For Update/Share commands are currently unsupported"; + } + + /* group clause list must include partition column */ + if (subqueryTree->groupClause) + { + List *groupClauseList = subqueryTree->groupClause; + List *targetEntryList = subqueryTree->targetList; + List *groupTargetEntryList = GroupTargetEntryList(groupClauseList, + targetEntryList); + bool groupOnPartitionColumn = TargetListOnPartitionColumn(subqueryTree, + groupTargetEntryList); + if (!groupOnPartitionColumn) + { + preconditionsSatisfied = false; + errorDetail = "Group by list without partition column is currently " + "unsupported"; + } + } + + /* we don't support aggregates without group by */ + if (subqueryTree->hasAggs && (subqueryTree->groupClause == NULL)) + { + preconditionsSatisfied = false; + errorDetail = "Aggregates without group by are currently unsupported"; + } + + /* having clause without group by on partition column is not supported */ + if (subqueryTree->havingQual && (subqueryTree->groupClause == NULL)) + { + preconditionsSatisfied = false; + errorDetail = "Having qual without group by on partition column is " + "currently unsupported"; + } + + /* + * Check if join is supported. We check lateral joins differently, because + * lateral join representation in query tree is a bit different than normal + * join queries. + */ + lateralQuery = LateralQuery(subqueryTree); + if (lateralQuery != NULL) + { + bool supportedLateralQuery = SupportedLateralQuery(subqueryTree, lateralQuery); + if (!supportedLateralQuery) + { + preconditionsSatisfied = false; + errorDetail = "This type of lateral query in subquery is currently " + "unsupported"; + } + } + else + { + List *joinTreeTableIndexList = NIL; + uint32 joiningTableCount = 0; + + ExtractRangeTableIndexWalker((Node*) subqueryTree->jointree, + &joinTreeTableIndexList); + joiningTableCount = list_length(joinTreeTableIndexList); + + /* if this is a join query, check if join clause is on partition columns */ + if ((joiningTableCount > 1)) + { + bool joinOnPartitionColumn = JoinOnPartitionColumn(subqueryTree); + if (!joinOnPartitionColumn) + { + preconditionsSatisfied = false; + errorDetail = "Relations need to be joining on partition columns"; + } + } + } + + /* distinct clause list must include partition column */ + if (subqueryTree->distinctClause) + { + List *distinctClauseList = subqueryTree->distinctClause; + List *targetEntryList = subqueryTree->targetList; + List *distinctTargetEntryList = GroupTargetEntryList(distinctClauseList, + targetEntryList); + bool distinctOnPartitionColumn = + TargetListOnPartitionColumn(subqueryTree, distinctTargetEntryList); + if (!distinctOnPartitionColumn) + { + preconditionsSatisfied = false; + errorDetail = "Distinct on columns without partition column is " + "currently unsupported"; + } + } + + /* finally check and error out if not satisfied */ + if (!preconditionsSatisfied) + { + ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("cannot push down this subquery"), + errdetail("%s", errorDetail))); + } + + /* recursively do same check for subqueries of this query */ + subqueryEntryList = SubqueryEntryList(subqueryTree); + foreach(rangeTableEntryCell, subqueryEntryList) + { + RangeTblEntry *rangeTableEntry = + (RangeTblEntry *) lfirst(rangeTableEntryCell); + + Query *innerSubquery = rangeTableEntry->subquery; + ErrorIfCannotPushdownSubquery(innerSubquery, outerQueryHasLimit); + } +} + + +/* + * ErrorIfUnsupportedTableCombination checks if the given query tree contains any + * unsupported range table combinations. For this, the function walks over all + * range tables in the join tree, and checks if they correspond to simple relations + * or subqueries. It also checks if there is a join between a regular table and + * a subquery and if join is on more than two range table entries. + */ +static void +ErrorIfUnsupportedTableCombination(Query *queryTree) +{ + List *rangeTableList = queryTree->rtable; + List *joinTreeTableIndexList = NIL; + ListCell *joinTreeTableIndexCell = NULL; + bool unsupporteTableCombination = false; + char *errorDetail = NULL; + uint32 relationRangeTableCount = 0; + uint32 subqueryRangeTableCount = 0; + + /* + * Extract all range table indexes from the join tree. Note that sub-queries + * that get pulled up by PostgreSQL don't appear in this join tree. + */ + ExtractRangeTableIndexWalker((Node*) queryTree->jointree, &joinTreeTableIndexList); + foreach(joinTreeTableIndexCell, joinTreeTableIndexList) + { + /* + * Join tree's range table index starts from 1 in the query tree. But, + * list indexes start from 0. + */ + int joinTreeTableIndex = lfirst_int(joinTreeTableIndexCell); + int rangeTableListIndex = joinTreeTableIndex - 1; + + RangeTblEntry *rangeTableEntry = + (RangeTblEntry *) list_nth(rangeTableList, rangeTableListIndex); + + /* + * Check if the range table in the join tree is a simple relation or a + * subquery. + */ + if (rangeTableEntry->rtekind == RTE_RELATION) + { + relationRangeTableCount++; + } + else if (rangeTableEntry->rtekind == RTE_SUBQUERY) + { + subqueryRangeTableCount++; + } + else + { + unsupporteTableCombination = true; + errorDetail = "Table expressions other than simple relations and " + "subqueries are currently unsupported"; + break; + } + } + + if ((subqueryRangeTableCount > 0) && (relationRangeTableCount > 0)) + { + unsupporteTableCombination = true; + errorDetail = "Joins between regular tables and subqueries are unsupported"; + } + + if ((relationRangeTableCount > 2) || (subqueryRangeTableCount > 2)) + { + unsupporteTableCombination = true; + errorDetail = "Joins between more than two relations and subqueries are " + "unsupported"; + } + + /* finally check and error out if not satisfied */ + if (unsupporteTableCombination) + { + ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("cannot push down this subquery"), + errdetail("%s", errorDetail))); + } +} + + +/* + * ErrorIfUnsupportedUnionQuery checks if the given union query is a supported + * one., otherwise it errors out. For these purpose it checks tree conditions; + * a. Are count of partition column filters same for union subqueries. + * b. Are target lists of union subquries include partition column. + * c. Is it a union clause without All option. + * + * Note that we check equality of filters in ErrorIfUnsupportedFilters(). We + * allow leaf queries not having a filter clause on the partition column. We + * check if a leaf query has a filter on the partition column, it must be same + * with other queries or if leaf query must not have any filter on the partition + * column, both are ok. Because joins and nested queries are transitive, it is + * enough one leaf query to have a filter on the partition column. But unions + * are not transitive, so here we check if they have same count of filters on + * the partition column. If count is more than 0, we already checked that they + * are same, of if count is 0 then both don't have any filter on the partition + * column. + */ +static void +ErrorIfUnsupportedUnionQuery(Query *unionQuery) +{ + bool supportedUnionQuery = true; + bool leftQueryOnPartitionColumn = false; + bool rightQueryOnPartitionColumn = false; + List *rangeTableList = unionQuery->rtable; + SetOperationStmt *unionStatement = (SetOperationStmt *) unionQuery->setOperations; + Query *leftQuery = NULL; + Query *rightQuery = NULL; + List *leftOpExpressionList = NIL; + List *rightOpExpressionList = NIL; + uint32 leftOpExpressionCount = 0; + uint32 rightOpExpressionCount = 0; + char *errorDetail = NULL; + + RangeTblRef *leftRangeTableReference = (RangeTblRef *) unionStatement->larg; + RangeTblRef *rightRangeTableReference = (RangeTblRef *) unionStatement->rarg; + + int leftTableIndex = leftRangeTableReference->rtindex - 1; + int rightTableIndex = rightRangeTableReference->rtindex - 1; + + RangeTblEntry *leftRangeTableEntry = (RangeTblEntry *) list_nth(rangeTableList, + leftTableIndex); + RangeTblEntry *rightRangeTableEntry = (RangeTblEntry *) list_nth(rangeTableList, + rightTableIndex); + + Assert(leftRangeTableEntry->rtekind == RTE_SUBQUERY); + Assert(rightRangeTableEntry->rtekind == RTE_SUBQUERY); + + leftQuery = leftRangeTableEntry->subquery; + rightQuery = rightRangeTableEntry->subquery; + + /* + * Check if subqueries of union have same count of filters on partition + * column. + */ + leftOpExpressionList = PartitionColumnOpExpressionList(leftQuery); + rightOpExpressionList = PartitionColumnOpExpressionList(rightQuery); + + leftOpExpressionCount = list_length(leftOpExpressionList); + rightOpExpressionCount = list_length(rightOpExpressionList); + + if (leftOpExpressionCount != rightOpExpressionCount) + { + supportedUnionQuery = false; + errorDetail = "Union clauses need to have same count of filters on " + "partition column"; + } + + /* check if union subqueries have partition column in their target lists */ + leftQueryOnPartitionColumn = TargetListOnPartitionColumn(leftQuery, + leftQuery->targetList); + rightQueryOnPartitionColumn = TargetListOnPartitionColumn(rightQuery, + rightQuery->targetList); + + if (!(leftQueryOnPartitionColumn && rightQueryOnPartitionColumn)) + { + supportedUnionQuery = false; + errorDetail = "Union clauses need to select partition columns"; + } + + /* check if it is a union all operation */ + if (unionStatement->all) + { + supportedUnionQuery = false; + errorDetail = "Union All clauses are currently unsupported"; + } + + /* finally check and error out if not satisfied */ + if (!supportedUnionQuery) + { + ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("cannot push down this subquery"), + errdetail("%s", errorDetail))); + } +} + + +/* + * GroupTargetEntryList walks over group clauses in the given list, finds + * matching target entries and return them in a new list. + */ +List * +GroupTargetEntryList(List *groupClauseList, List *targetEntryList) +{ + List *groupTargetEntryList = NIL; + ListCell *groupClauseCell = NULL; + + foreach(groupClauseCell, groupClauseList) + { + SortGroupClause *groupClause = (SortGroupClause *) lfirst(groupClauseCell); + TargetEntry *groupTargetEntry = + get_sortgroupclause_tle(groupClause, targetEntryList); + groupTargetEntryList = lappend(groupTargetEntryList, groupTargetEntry); + } + + return groupTargetEntryList; +} + + +/* + * TargetListOnPartitionColumn checks if at least one target list entry is on + * partition column. + */ +static bool +TargetListOnPartitionColumn(Query *query, List *targetEntryList) +{ + bool targetListOnPartitionColumn = false; + List *compositeFieldList = NIL; + + ListCell *targetEntryCell = NULL; + foreach(targetEntryCell, targetEntryList) + { + TargetEntry *targetEntry = (TargetEntry *) lfirst(targetEntryCell); + Expr *targetExpression = targetEntry->expr; + + bool isPartitionColumn = IsPartitionColumnRecursive(targetExpression, query); + if (isPartitionColumn) + { + FieldSelect *compositeField = CompositeFieldRecursive(targetExpression, + query); + if (compositeField) + { + compositeFieldList = lappend(compositeFieldList, compositeField); + } + else + { + targetListOnPartitionColumn = true; + break; + } + } + } + + /* check composite fields */ + if (!targetListOnPartitionColumn) + { + bool fullCompositeFieldList = FullCompositeFieldList(compositeFieldList); + if (fullCompositeFieldList) + { + targetListOnPartitionColumn = true; + } + } + + return targetListOnPartitionColumn; +} + + +/* + * IsPartitionColumnRecursive recursively checks if the given column is a partition + * column. If a column is referenced from a regular table, we directly check if + * it is a partition column. If a column is referenced from a subquery, then we + * recursively check that subquery until we reach the source of that column, and + * verify this column is a partition column. If a column is referenced from a + * join range table entry, then we resolve which join column it refers and + * recursively check this column with the same query. + * + * Note that if the given expression is a field of a composite type, then this + * function checks if this composite column is a partition column. + */ +static bool +IsPartitionColumnRecursive(Expr *columnExpression, Query *query) +{ + bool isPartitionColumn = false; + Var *candidateColumn = NULL; + List *rangetableList = query->rtable; + Index rangeTableEntryIndex = 0; + RangeTblEntry *rangeTableEntry = NULL; + + if (IsA(columnExpression, Var)) + { + candidateColumn = (Var *) columnExpression; + } + else if (IsA(columnExpression, FieldSelect)) + { + FieldSelect *compositeField = (FieldSelect *) columnExpression; + Expr *fieldExpression = compositeField->arg; + + if (IsA(fieldExpression, Var)) + { + candidateColumn = (Var *) fieldExpression; + } + else + { + ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("cannot push down this subquery"), + errdetail("Only references to column fields are supported"))); + } + } + + if (candidateColumn == NULL) + { + return false; + } + + rangeTableEntryIndex = candidateColumn->varno - 1; + rangeTableEntry = list_nth(rangetableList, rangeTableEntryIndex); + + if (rangeTableEntry->rtekind == RTE_RELATION) + { + Oid relationId = rangeTableEntry->relid; + Var *partitionColumn = PartitionKey(relationId); + + if (candidateColumn->varattno == partitionColumn->varattno) + { + isPartitionColumn = true; + } + } + else if (rangeTableEntry->rtekind == RTE_SUBQUERY) + { + Query *subquery = rangeTableEntry->subquery; + List *targetEntryList = subquery->targetList; + AttrNumber targetEntryIndex = candidateColumn->varattno - 1; + TargetEntry *subqueryTargetEntry = list_nth(targetEntryList, targetEntryIndex); + + Expr *subqueryExpression = subqueryTargetEntry->expr; + isPartitionColumn = IsPartitionColumnRecursive(subqueryExpression, subquery); + } + else if (rangeTableEntry->rtekind == RTE_JOIN) + { + List *joinColumnList = rangeTableEntry->joinaliasvars; + AttrNumber joinColumnIndex = candidateColumn->varattno - 1; + Expr *joinColumn = list_nth(joinColumnList, joinColumnIndex); + + isPartitionColumn = IsPartitionColumnRecursive(joinColumn, query); + } + + return isPartitionColumn; +} + + +/* + * CompositeFieldRecursive recursively finds composite field in the query tree + * referred by given expression. If expression does not refer to a composite + * field, then it returns NULL. + * + * If expression is a field select we directly return composite field. If it is + * a column is referenced from a subquery, then we recursively check that subquery + * until we reach the source of that column, and find composite field. If this + * column is referenced from join range table entry, then we resolve which join + * column it refers and recursively use this column with the same query. + */ +static FieldSelect * +CompositeFieldRecursive(Expr *expression, Query *query) +{ + FieldSelect *compositeField = NULL; + List *rangetableList = query->rtable; + Index rangeTableEntryIndex = 0; + RangeTblEntry *rangeTableEntry = NULL; + Var *candidateColumn = NULL; + + if (IsA(expression, FieldSelect)) + { + compositeField = (FieldSelect *) expression; + return compositeField; + } + + if (IsA(expression, Var)) + { + candidateColumn = (Var *) expression; + } + else + { + return NULL; + } + + rangeTableEntryIndex = candidateColumn->varno - 1; + rangeTableEntry = list_nth(rangetableList, rangeTableEntryIndex); + + if (rangeTableEntry->rtekind == RTE_SUBQUERY) + { + Query *subquery = rangeTableEntry->subquery; + List *targetEntryList = subquery->targetList; + AttrNumber targetEntryIndex = candidateColumn->varattno - 1; + TargetEntry *subqueryTargetEntry = list_nth(targetEntryList, targetEntryIndex); + + Expr *subqueryExpression = subqueryTargetEntry->expr; + compositeField = CompositeFieldRecursive(subqueryExpression, subquery); + } + else if (rangeTableEntry->rtekind == RTE_JOIN) + { + List *joinColumnList = rangeTableEntry->joinaliasvars; + AttrNumber joinColumnIndex = candidateColumn->varattno - 1; + Expr *joinColumn = list_nth(joinColumnList, joinColumnIndex); + + compositeField = CompositeFieldRecursive(joinColumn, query); + } + + return compositeField; +} + + +/* + * FullCompositeFieldList gets a composite field list, and checks if all fields + * of composite type are used in the list. + */ +static bool +FullCompositeFieldList(List *compositeFieldList) +{ + bool fullCompositeFieldList = true; + bool *compositeFieldArray = NULL; + uint32 compositeFieldCount = 0; + uint32 fieldIndex = 0; + + ListCell *fieldSelectCell = NULL; + foreach (fieldSelectCell, compositeFieldList) + { + FieldSelect *fieldSelect = (FieldSelect *) lfirst(fieldSelectCell); + uint32 compositeFieldIndex = 0; + + Expr *fieldExpression = fieldSelect->arg; + if (!IsA(fieldExpression, Var)) + { + continue; + } + + if (compositeFieldArray == NULL) + { + uint32 index = 0; + Var *compositeColumn = (Var *) fieldExpression; + Oid compositeTypeId = compositeColumn->vartype; + Oid compositeRelationId = get_typ_typrelid(compositeTypeId); + + /* get composite type attribute count */ + Relation relation = relation_open(compositeRelationId, AccessShareLock); + compositeFieldCount = relation->rd_att->natts; + compositeFieldArray = palloc0(compositeFieldCount * sizeof(bool)); + relation_close(relation, AccessShareLock); + + for (index = 0; index < compositeFieldCount; index++) + { + compositeFieldArray[index] = false; + } + } + + compositeFieldIndex = fieldSelect->fieldnum - 1; + compositeFieldArray[compositeFieldIndex] = true; + } + + for (fieldIndex = 0; fieldIndex < compositeFieldCount; fieldIndex++) + { + if (!compositeFieldArray[fieldIndex]) + { + fullCompositeFieldList = false; + } + } + + if (compositeFieldCount == 0) + { + fullCompositeFieldList = false; + } + + return fullCompositeFieldList; +} + + +/* + * LateralQuery walks over the given range table list and if there is a subquery + * columns with other sibling subquery. + */ +static Query * +LateralQuery(Query *query) +{ + Query *lateralQuery = NULL; + List *rangeTableList = query->rtable; + + ListCell *rangeTableCell = NULL; + foreach(rangeTableCell, rangeTableList) + { + RangeTblEntry *rangeTableEntry = (RangeTblEntry *) lfirst(rangeTableCell); + if (rangeTableEntry->rtekind == RTE_SUBQUERY && rangeTableEntry->lateral) + { + lateralQuery = rangeTableEntry->subquery; + break; + } + } + + return lateralQuery; +} + + +/* + * SupportedLateralQuery checks if the given lateral query is joined on partition + * columns with another siblings subquery. + */ +static bool +SupportedLateralQuery(Query *parentQuery, Query *lateralQuery) +{ + bool supportedLateralQuery = false; + List *outerCompositeFieldList = NIL; + List *localCompositeFieldList = NIL; + List *whereClauseList = WhereClauseList(lateralQuery->jointree); + + ListCell *whereClauseCell = NULL; + foreach(whereClauseCell, whereClauseList) + { + OpExpr *operatorExpression = NULL; + List *argumentList = NIL; + char *operatorName = NULL; + int equalsOperator = 0; + Expr *leftArgument = NULL; + Expr *rightArgument = NULL; + Expr *outerQueryExpression = NULL; + Expr *localQueryExpression = NULL; + Var *leftColumn = NULL; + Var *rightColumn = NULL; + bool outerColumnIsPartitionColumn = false; + bool localColumnIsPartitionColumn = false; + + Node *clause = (Node *) lfirst(whereClauseCell); + if (!IsA(clause, OpExpr)) + { + continue; + } + + operatorExpression = (OpExpr *) clause; + argumentList = operatorExpression->args; + + /* + * Join clauses must have two arguments. Note that logic here use to find + * join clauses is very similar to IsJoinClause(). But we are not able to + * reuse it, because it calls pull_var_clause_default() which in return + * deep down calls pull_var_clause_walker(), and this function errors out + * for variable level other than 0 which is the case for lateral joins. + */ + if (list_length(argumentList) != 2) + { + continue; + } + + /* + * We accept all column types that can be joined with an equals sign as + * valid. These include columns that have cross-type equals operators + * (such as int48eq) and columns that can be casted at run-time (such as + * from numeric to int4). + */ + operatorName = get_opname(operatorExpression->opno); + equalsOperator = strncmp(operatorName, EQUAL_OPERATOR_STRING, NAMEDATALEN); + if (equalsOperator != 0) + { + continue; + } + + /* get left and right side of the expression */ + leftArgument = (Expr *) linitial(argumentList); + rightArgument = (Expr *) lsecond(argumentList); + + if (IsA(leftArgument, Var)) + { + leftColumn = (Var *) leftArgument; + } + else if (IsA(leftArgument, FieldSelect)) + { + FieldSelect *fieldSelect = (FieldSelect *) leftArgument; + Expr *fieldExpression = fieldSelect->arg; + + if (!IsA(fieldExpression, Var)) + { + continue; + } + + leftColumn = (Var *) fieldExpression; + } + else + { + continue; + } + + if (IsA(rightArgument, Var)) + { + rightColumn = (Var *) rightArgument; + } + else if (IsA(rightArgument, FieldSelect)) + { + FieldSelect *fieldSelect = (FieldSelect *) rightArgument; + Expr *fieldExpression = fieldSelect->arg; + + if (!IsA(fieldExpression, Var)) + { + continue; + } + + rightColumn = (Var *) fieldExpression; + } + else + { + continue; + } + + if (leftColumn->varlevelsup == 1 && rightColumn->varlevelsup == 0) + { + outerQueryExpression = leftArgument; + localQueryExpression = rightArgument; + } + else if (leftColumn->varlevelsup == 0 && rightColumn->varlevelsup == 1) + { + outerQueryExpression = rightArgument; + localQueryExpression = leftArgument; + } + else + { + continue; + } + + outerColumnIsPartitionColumn = IsPartitionColumnRecursive(outerQueryExpression, + parentQuery); + localColumnIsPartitionColumn = IsPartitionColumnRecursive(localQueryExpression, + lateralQuery); + + if (outerColumnIsPartitionColumn && localColumnIsPartitionColumn) + { + FieldSelect *outerCompositeField = + CompositeFieldRecursive(outerQueryExpression, parentQuery); + FieldSelect *localCompositeField = + CompositeFieldRecursive(localQueryExpression, lateralQuery); + /* + * If partition colums are composite fields, add them to list to + * check later if all composite fields are used. + */ + if (outerCompositeField && localCompositeField) + { + outerCompositeFieldList = lappend(outerCompositeFieldList, + outerCompositeField); + localCompositeFieldList = lappend(localCompositeFieldList, + localCompositeField); + } + + /* if both sides are not composite fields, they are normal columns */ + if (!(outerCompositeField || localCompositeField)) + { + supportedLateralQuery = true; + break; + } + } + } + + /* check composite fields */ + if(!supportedLateralQuery) + { + bool outerFullCompositeFieldList = + FullCompositeFieldList(outerCompositeFieldList); + bool localFullCompositeFieldList = + FullCompositeFieldList(localCompositeFieldList); + + if (outerFullCompositeFieldList && localFullCompositeFieldList) + { + supportedLateralQuery = true; + } + } + + return supportedLateralQuery; +} + + +/* + * JoinOnPartitionColumn checks if both sides of at least one join clause are on + * partition columns. + */ +static bool +JoinOnPartitionColumn(Query *query) +{ + bool joinOnPartitionColumn = false; + List *leftCompositeFieldList = NIL; + List *rightCompositeFieldList = NIL; + List *whereClauseList = WhereClauseList(query->jointree); + List *joinClauseList = JoinClauseList(whereClauseList); + + ListCell *joinClauseCell = NULL; + foreach(joinClauseCell, joinClauseList) + { + OpExpr *joinClause = (OpExpr *) lfirst(joinClauseCell); + List *joinArgumentList = joinClause->args; + Expr *leftArgument = NULL; + Expr *rightArgument = NULL; + bool isLeftColumnPartitionColumn = false; + bool isRightColumnPartitionColumn = false; + + /* get left and right side of the expression */ + leftArgument = (Expr *) linitial(joinArgumentList); + rightArgument = (Expr *) lsecond(joinArgumentList); + + isLeftColumnPartitionColumn = IsPartitionColumnRecursive(leftArgument, query); + isRightColumnPartitionColumn = IsPartitionColumnRecursive(rightArgument, query); + + if (isLeftColumnPartitionColumn && isRightColumnPartitionColumn) + { + FieldSelect *leftCompositeField = + CompositeFieldRecursive(leftArgument, query); + FieldSelect *rightCompositeField = + CompositeFieldRecursive(rightArgument, query); + + /* + * If partition colums are composite fields, add them to list to + * check later if all composite fields are used. + */ + if(leftCompositeField && rightCompositeField) + { + leftCompositeFieldList = lappend(leftCompositeFieldList, + leftCompositeField); + rightCompositeFieldList = lappend(rightCompositeFieldList, + rightCompositeField); + } + + /* if both sides are not composite fields, they are normal columns */ + if(!(leftCompositeField && rightCompositeField)) + { + joinOnPartitionColumn = true; + break; + } + } + } + + /* check composite fields */ + if(!joinOnPartitionColumn) + { + bool leftFullCompositeFieldList = + FullCompositeFieldList(leftCompositeFieldList); + bool rightFullCompositeFieldList = + FullCompositeFieldList(rightCompositeFieldList); + + if (leftFullCompositeFieldList && rightFullCompositeFieldList) + { + joinOnPartitionColumn = true; + } + } + + return joinOnPartitionColumn; +} + + +/* + * ErrorIfUnsupportedShardDistribution gets list of relations in the given query + * and checks if two conditions below hold for them, otherwise it errors out. + * a. Every relation is distributed by range or hash. This means shards are + * disjoint based on the partition column. + * b. All relations have 1-to-1 shard partitioning between them. This means + * shard count for every relation is same and for every shard in a relation + * there is exactly one shard in other relations with same min/max values. + */ +static void +ErrorIfUnsupportedShardDistribution(Query *query) +{ + List *firstShardIntervalList = NIL; + List *relationIdList = RelationIdList(query); + ListCell *relationIdCell = NULL; + uint32 relationIndex = 0; + uint32 rangeDistributedRelationCount = 0; + uint32 hashDistributedRelationCount = 0; + + foreach(relationIdCell, relationIdList) + { + Oid relationId = lfirst_oid(relationIdCell); + char partitionMethod = PartitionMethod(relationId); + if (partitionMethod == DISTRIBUTE_BY_RANGE) + { + rangeDistributedRelationCount++; + } + else if (partitionMethod == DISTRIBUTE_BY_HASH) + { + hashDistributedRelationCount++; + } + else + { + ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("cannot push down this subquery"), + errdetail("Currently range and hash partitioned " + "relations are supported"))); + } + } + + if ((rangeDistributedRelationCount > 0) && (hashDistributedRelationCount > 0)) + { + ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("cannot push down this subquery"), + errdetail("A query including both range and hash " + "partitioned relations are unsupported"))); + } + + foreach(relationIdCell, relationIdList) + { + Oid relationId = lfirst_oid(relationIdCell); + List *currentShardIntervalList = LoadShardIntervalList(relationId); + bool coPartitionedTables = false; + + /* get shard list of first relation and continue for the next relation */ + if (relationIndex == 0) + { + firstShardIntervalList = currentShardIntervalList; + relationIndex++; + + continue; + } + + /* check if this table has 1-1 shard partitioning with first table */ + coPartitionedTables = CoPartitionedTables(firstShardIntervalList, + currentShardIntervalList); + if (!coPartitionedTables) + { + ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("cannot push down this subquery"), + errdetail("Shards of relations in subquery need to " + "have 1-to-1 shard partitioning"))); + } + } +} + + +/* + * RelationIdList returns list of unique relation ids in query tree. + */ +List * +RelationIdList(Query *query) +{ + List *rangeTableList = NIL; + List *tableEntryList = NIL; + List *relationIdList = NIL; + ListCell *tableEntryCell = NULL; + + ExtractRangeTableRelationWalker((Node *) query, &rangeTableList); + tableEntryList = TableEntryList(rangeTableList); + + foreach(tableEntryCell, tableEntryList) + { + TableEntry *tableEntry = (TableEntry *) lfirst(tableEntryCell); + Oid relationId = tableEntry->relationId; + + relationIdList = list_append_unique_oid(relationIdList, relationId); + } + + return relationIdList; +} + + +/* + * CoPartitionedTables checks if given shard lists have 1-to-1 shard partitioning. + * It first sorts both list according to shard interval minimum values. Then it + * compares every shard interval in order and if any pair of shard intervals are + * not equal it returns false. + */ +static bool +CoPartitionedTables(List *firstShardList, List *secondShardList) +{ + bool coPartitionedTables = true; + uint32 intervalIndex = 0; + ShardInterval **sortedFirstIntervalArray = NULL; + ShardInterval **sortedSecondIntervalArray = NULL; + + uint32 firstListShardCount = list_length(firstShardList); + uint32 secondListShardCount = list_length(secondShardList); + + if (firstListShardCount != secondListShardCount) + { + return false; + } + + /* if there are not any shards just return true */ + if (firstListShardCount == 0) + { + return true; + } + + sortedFirstIntervalArray = SortedShardIntervalArray(firstShardList); + sortedSecondIntervalArray = SortedShardIntervalArray(secondShardList); + + for (intervalIndex = 0; intervalIndex < firstListShardCount; intervalIndex++) + { + ShardInterval *firstInterval = sortedFirstIntervalArray[intervalIndex]; + ShardInterval *secondInterval = sortedSecondIntervalArray[intervalIndex]; + + bool shardIntervalsEqual = ShardIntervalsEqual(firstInterval, secondInterval); + if (!shardIntervalsEqual) + { + coPartitionedTables = false; + break; + } + } + + return coPartitionedTables; +} + + +/* + * ShardIntervalsEqual checks if given shard intervals have equal min/max values. + */ +static bool +ShardIntervalsEqual(ShardInterval *firstInterval, ShardInterval *secondInterval) +{ + Oid typeId = InvalidOid; + FmgrInfo *comparisonFunction = NULL; + bool shardIntervalsEqual = false; + Datum firstMin = 0; + Datum firstMax = 0; + Datum secondMin = 0; + Datum secondMax = 0; + + typeId = firstInterval->valueTypeId; + comparisonFunction = GetFunctionInfo(typeId, BTREE_AM_OID, BTORDER_PROC); + + firstMin = firstInterval->minValue; + firstMax = firstInterval->maxValue; + secondMin = secondInterval->minValue; + secondMax = secondInterval->maxValue; + + if (firstInterval->minValueExists && firstInterval->maxValueExists && + secondInterval->minValueExists && secondInterval->maxValueExists) + { + Datum minDatum = CompareCall2(comparisonFunction, firstMin, secondMin); + Datum maxDatum = CompareCall2(comparisonFunction, firstMax, secondMax); + int firstComparison = DatumGetInt32(minDatum); + int secondComparison = DatumGetInt32(maxDatum); + + if (firstComparison == 0 && secondComparison == 0) + { + shardIntervalsEqual = true; + } + } + + return shardIntervalsEqual; +} + + +/* + * ErrorIfUnsupportedFilters checks if all leaf queries in the given query have + * same filter on the partition column. Note that if there are queries without + * any filter on the partition column, they don't break this prerequisite. + */ +static void +ErrorIfUnsupportedFilters(Query *subquery) +{ + List *queryList = NIL; + ListCell *queryCell = NULL; + List *subqueryOpExpressionList = NIL; + List *relationIdList = RelationIdList(subquery); + + /* + * Get relation id of any relation in the subquery and create partiton column + * for this relation. We will use this column to replace columns on operator + * expressions on different tables. Then we compare these operator expressions + * to see if they consist of same operator and constant value. + */ + Oid relationId = linitial_oid(relationIdList); + Var *partitionColumn = PartitionColumn(relationId, 0); + + ExtractQueryWalker((Node *) subquery, &queryList); + foreach(queryCell, queryList) + { + Query *query = (Query *) lfirst(queryCell); + List *opExpressionList = NIL; + List *newOpExpressionList = NIL; + + bool leafQuery = LeafQuery(query); + if (!leafQuery) + { + continue; + } + + opExpressionList = PartitionColumnOpExpressionList(query); + if (opExpressionList == NIL) + { + continue; + } + + newOpExpressionList = ReplaceColumnsInOpExpressionList(opExpressionList, + partitionColumn); + + if (subqueryOpExpressionList == NIL) + { + subqueryOpExpressionList = newOpExpressionList; + } + else + { + bool equalOpExpressionLists = EqualOpExpressionLists(subqueryOpExpressionList, + newOpExpressionList); + if (!equalOpExpressionLists) + { + ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("cannot push down this subquery"), + errdetail("Currently all leaf queries need to " + "have same filters on partition column"))); + } + } + } +} + + +/* + * ExtractQueryWalker walks over a query, and finds all queries in the query + * tree and returns these queries. + */ +bool +ExtractQueryWalker(Node *node, List **queryList) +{ + bool walkerResult = false; + if (node == NULL) + { + return false; + } + + if (IsA(node, Query)) + { + Query *query = (Query *) node; + + (*queryList) = lappend(*queryList, query); + walkerResult = query_tree_walker(query, ExtractQueryWalker, queryList, + QTW_EXAMINE_RTES); + } + + return walkerResult; +} + + +/* + * LeafQuery checks if the given query is a leaf query. Leaf queries have only + * simple relations in the join tree. + */ +bool +LeafQuery(Query *queryTree) +{ + List *rangeTableList = queryTree->rtable; + List *joinTreeTableIndexList = NIL; + ListCell *joinTreeTableIndexCell = NULL; + bool leafQuery = true; + + /* + * Extract all range table indexes from the join tree. Note that sub-queries + * that get pulled up by PostgreSQL don't appear in this join tree. + */ + ExtractRangeTableIndexWalker((Node*) queryTree->jointree, &joinTreeTableIndexList); + foreach(joinTreeTableIndexCell, joinTreeTableIndexList) + { + /* + * Join tree's range table index starts from 1 in the query tree. But, + * list indexes start from 0. + */ + int joinTreeTableIndex = lfirst_int(joinTreeTableIndexCell); + int rangeTableListIndex = joinTreeTableIndex - 1; + + RangeTblEntry *rangeTableEntry = + (RangeTblEntry *) list_nth(rangeTableList, rangeTableListIndex); + + /* + * Check if the range table in the join tree is a simple relation. + */ + if (rangeTableEntry->rtekind != RTE_RELATION) + { + leafQuery = false; + } + } + + return leafQuery; +} + + +/* + * PartitionColumnOpExpressionList returns operator expressions which are on + * partition column in the query. This function walks over where clause list, + * finds operator expressions on partition column and returns them in a new list. + */ +List * +PartitionColumnOpExpressionList(Query *query) +{ + List *whereClauseList = WhereClauseList(query->jointree); + List *partitionColumnOpExpressionList = NIL; + + ListCell *whereClauseCell = NULL; + foreach(whereClauseCell, whereClauseList) + { + Node *whereNode = (Node *) lfirst(whereClauseCell); + Node *leftArgument = NULL; + Node *rightArgument = NULL; + OpExpr *whereClause = NULL; + List *argumentList = NIL; + List *rangetableList = NIL; + uint32 argumentCount = 0; + Var *candidatePartitionColumn = NULL; + Var *partitionColumn = NULL; + Index rangeTableEntryIndex = 0; + RangeTblEntry *rangeTableEntry = NULL; + Oid relationId = InvalidOid; + + if (!IsA(whereNode, OpExpr)) + { + continue; + } + + whereClause = (OpExpr *) whereNode; + argumentList = whereClause->args; + + /* + * Select clauses must have two arguments. Note that logic here use to + * find select clauses is very similar to IsSelectClause(). But we are + * not able to reuse it, because it calls pull_var_clause_default() + * which in return deep down calls pull_var_clause_walker(), and this + * function errors out for variable level other than 0 which is the case + * for lateral joins. + */ + argumentCount = list_length(argumentList); + if (argumentCount != 2) + { + continue; + } + + leftArgument = (Node *) linitial(argumentList); + rightArgument = (Node *) lsecond(argumentList); + + if (IsA(leftArgument, Var) && IsA(rightArgument, Const)) + { + candidatePartitionColumn = (Var *) leftArgument; + } + else if (IsA(leftArgument, Const) && IsA(leftArgument, Var)) + { + candidatePartitionColumn = (Var *) rightArgument; + } + else + { + continue; + } + + rangetableList = query->rtable; + rangeTableEntryIndex = candidatePartitionColumn->varno - 1; + rangeTableEntry = list_nth(rangetableList, rangeTableEntryIndex); + + Assert(rangeTableEntry->rtekind == RTE_RELATION); + + relationId = rangeTableEntry->relid; + partitionColumn = PartitionKey(relationId); + + if (candidatePartitionColumn->varattno == partitionColumn->varattno) + { + partitionColumnOpExpressionList = lappend(partitionColumnOpExpressionList, + whereClause); + } + } + + return partitionColumnOpExpressionList; +} + + +/* + * ReplaceColumnsInOpExpressionList walks over the given operator expression + * list and copies every one them, replaces columns with the given new column + * and finally returns new copies in a new list of operator expressions. + */ +List * +ReplaceColumnsInOpExpressionList(List *opExpressionList, Var *newColumn) +{ + List *newOpExpressionList = NIL; + + ListCell *opExpressionCell = NULL; + foreach(opExpressionCell, opExpressionList) + { + OpExpr *opExpression = (OpExpr *) lfirst(opExpressionCell); + OpExpr *copyOpExpression = (OpExpr *) copyObject(opExpression); + List *argumentList = copyOpExpression->args; + List *newArgumentList = NIL; + + Node *leftArgument = (Node *) linitial(argumentList); + Node *rightArgument = (Node *) lsecond(argumentList); + + if (IsA(leftArgument, Var)) + { + newArgumentList = list_make2(newColumn, rightArgument); + } + else if (IsA(leftArgument, Var)) + { + newArgumentList = list_make2(leftArgument, newColumn); + } + + copyOpExpression->args = newArgumentList; + newOpExpressionList = lappend(newOpExpressionList, copyOpExpression); + } + + return newOpExpressionList; +} + + +/* + * EqualOpExpressionLists checks if given two operator expression lists are + * equal. + */ +static bool +EqualOpExpressionLists(List *firstOpExpressionList, List *secondOpExpressionList) +{ + bool equalOpExpressionLists = false; + ListCell *firstOpExpressionCell = NULL; + uint32 equalOpExpressionCount = 0; + uint32 firstOpExpressionCount = list_length(firstOpExpressionList); + uint32 secondOpExpressionCount = list_length(secondOpExpressionList); + + if (firstOpExpressionCount != secondOpExpressionCount) + { + return false; + } + + foreach(firstOpExpressionCell, firstOpExpressionList) + { + OpExpr *firstOpExpression = (OpExpr *) lfirst(firstOpExpressionCell); + ListCell *secondOpExpressionCell = NULL; + + foreach(secondOpExpressionCell, secondOpExpressionList) + { + OpExpr *secondOpExpression = (OpExpr *) lfirst(secondOpExpressionCell); + bool equalExpressions = equal(firstOpExpression, secondOpExpression); + + if (equalExpressions) + { + equalOpExpressionCount++; + continue; + } + } + } + + if (equalOpExpressionCount == firstOpExpressionCount) + { + equalOpExpressionLists = true; + } + + return equalOpExpressionLists; +} + + +/* + * WorkerLimitCount checks if the given extended node contains a limit node, and + * if that node can be pushed down. For this, the function checks if this limit + * count or a meaningful approximation of it can be pushed down to worker nodes. + * If they can, the function returns the limit count. Otherwise, the function + * returns null. + */ +static Node * +WorkerLimitCount(MultiExtendedOp *originalOpNode) +{ + Node *workerLimitCount = NULL; + List *groupClauseList = originalOpNode->groupClauseList; + List *sortClauseList = originalOpNode->sortClauseList; + List *targetList = originalOpNode->targetList; + + /* no limit node to push down */ + if (originalOpNode->limitCount == NULL) + { + return NULL; + } + + /* + * If we don't have group by clauses, or if we have order by clauses without + * aggregates, we can push down the original limit. Else if we have order by + * clauses with commutative aggregates, we can push down approximate limits. + */ + if (groupClauseList == NIL) + { + workerLimitCount = originalOpNode->limitCount; + } + else if (sortClauseList != NIL) + { + bool orderByNonAggregates = !(HasOrderByAggregate(sortClauseList, targetList)); + bool canApproximate = CanPushDownLimitApproximate(sortClauseList, targetList); + + if (orderByNonAggregates) + { + workerLimitCount = originalOpNode->limitCount; + } + else if (canApproximate) + { + Const *workerLimitConst = (Const *) copyObject(originalOpNode->limitCount); + int64 workerLimitCountInt64 = (int64) LimitClauseRowFetchCount; + workerLimitConst->constvalue = Int64GetDatum(workerLimitCountInt64); + + workerLimitCount = (Node *) workerLimitConst; + } + } + + /* display debug message on limit push down */ + if (workerLimitCount != NULL) + { + Const *workerLimitConst = (Const *) workerLimitCount; + int64 workerLimitCountInt64 = DatumGetInt64(workerLimitConst->constvalue); + + ereport(DEBUG1, (errmsg("push down of limit count: " INT64_FORMAT, + workerLimitCountInt64))); + } + + return workerLimitCount; +} + + +/* + * WorkerSortClauseList first checks if the given extended node contains a limit + * that can be pushed down. If it does, the function then checks if we need to + * add any sorting and grouping clauses to the sort list we push down for the + * limit. If we do, the function adds these clauses and returns them. Otherwise, + * the function returns null. + */ +static List * +WorkerSortClauseList(MultiExtendedOp *originalOpNode) +{ + List *workerSortClauseList = NIL; + List *groupClauseList = originalOpNode->groupClauseList; + List *sortClauseList = originalOpNode->sortClauseList; + List *targetList = originalOpNode->targetList; + + /* if no limit node, no need to push down sort clauses */ + if (originalOpNode->limitCount == NULL) + { + return NIL; + } + + /* + * If we are pushing down the limit, push down any order by clauses. Also if + * we are pushing down the limit because the order by clauses don't have any + * aggregates, add group by clauses to the order by list. We do this because + * rows that belong to the same grouping may appear in different "offsets" + * in different task results. By ordering on the group by clause, we ensure + * that query results are consistent. + */ + if (groupClauseList == NIL) + { + workerSortClauseList = originalOpNode->sortClauseList; + } + else if (sortClauseList != NIL) + { + bool orderByNonAggregates = !(HasOrderByAggregate(sortClauseList, targetList)); + bool canApproximate = CanPushDownLimitApproximate(sortClauseList, targetList); + + if (orderByNonAggregates) + { + workerSortClauseList = list_copy(sortClauseList); + workerSortClauseList = list_concat(workerSortClauseList, groupClauseList); + } + else if (canApproximate) + { + workerSortClauseList = originalOpNode->sortClauseList; + } + } + + return workerSortClauseList; +} + + +/* + * CanPushDownLimitApproximate checks if we can push down the limit clause to + * the worker nodes, and get approximate and meaningful results. We can do this + * only when: (1) the user has enabled the limit approximation and (2) the query + * has order by clauses that are commutative. + */ +static bool +CanPushDownLimitApproximate(List *sortClauseList, List *targetList) +{ + bool canApproximate = false; + + /* user hasn't enabled the limit approximation */ + if (LimitClauseRowFetchCount == DISABLE_LIMIT_APPROXIMATION) + { + return false; + } + + if (sortClauseList != NIL) + { + bool orderByAverage = HasOrderByAverage(sortClauseList, targetList); + bool orderByComplex = HasOrderByComplexExpression(sortClauseList, targetList); + + /* + * If we don't have any order by average or any complex expressions with + * aggregates in them, we can meaningfully approximate. + */ + if (!orderByAverage && !orderByComplex) + { + canApproximate = true; + } + } + + return canApproximate; +} + + +/* + * HasOrderByAggregate walks over the given order by clauses, and checks if we + * have an order by an aggregate function. If we do, the function returns true. + */ +static bool +HasOrderByAggregate(List *sortClauseList, List *targetList) +{ + bool hasOrderByAggregate = false; + ListCell *sortClauseCell = NULL; + + foreach(sortClauseCell, sortClauseList) + { + SortGroupClause *sortClause = (SortGroupClause *) lfirst(sortClauseCell); + Node *sortExpression = get_sortgroupclause_expr(sortClause, targetList); + + bool containsAggregate = contain_agg_clause(sortExpression); + if (containsAggregate) + { + hasOrderByAggregate = true; + break; + } + } + + return hasOrderByAggregate; +} + + +/* + * HasOrderByAverage walks over the given order by clauses, and checks if we + * have an order by an average. If we do, the function returns true. + */ +static bool +HasOrderByAverage(List *sortClauseList, List *targetList) +{ + bool hasOrderByAverage = false; + ListCell *sortClauseCell = NULL; + + foreach(sortClauseCell, sortClauseList) + { + SortGroupClause *sortClause = (SortGroupClause *) lfirst(sortClauseCell); + Node *sortExpression = get_sortgroupclause_expr(sortClause, targetList); + + /* if sort expression is an aggregate, check its type */ + if (IsA(sortExpression, Aggref)) + { + Aggref *aggregate = (Aggref *) sortExpression; + + AggregateType aggregateType = GetAggregateType(aggregate->aggfnoid); + if (aggregateType == AGGREGATE_AVERAGE) + { + hasOrderByAverage = true; + break; + } + } + } + + return hasOrderByAverage; +} + + +/* + * HasOrderByComplexExpression walks over the given order by clauses, and checks + * if we have a nested expression that contains an aggregate function within it. + * If we do, the function returns true. + */ +static bool +HasOrderByComplexExpression(List *sortClauseList, List *targetList) +{ + bool hasOrderByComplexExpression = false; + ListCell *sortClauseCell = NULL; + + foreach(sortClauseCell, sortClauseList) + { + SortGroupClause *sortClause = (SortGroupClause *) lfirst(sortClauseCell); + Node *sortExpression = get_sortgroupclause_expr(sortClause, targetList); + bool nestedAggregate = false; + + /* simple aggregate functions are ok */ + if (IsA(sortExpression, Aggref)) + { + continue; + } + + nestedAggregate = contain_agg_clause(sortExpression); + if (nestedAggregate) + { + hasOrderByComplexExpression = true; + break; + } + } + + return hasOrderByComplexExpression; +} + + +/* + * HasOrderByHllType walks over the given order by clauses, and checks if any of + * those clauses operate on hll data type. If they do, the function returns true. + */ +static bool +HasOrderByHllType(List *sortClauseList, List *targetList) +{ + bool hasOrderByHllType = false; + Oid hllTypeId = TypenameGetTypid(HLL_TYPE_NAME); + + ListCell *sortClauseCell = NULL; + foreach(sortClauseCell, sortClauseList) + { + SortGroupClause *sortClause = (SortGroupClause *) lfirst(sortClauseCell); + Node *sortExpression = get_sortgroupclause_expr(sortClause, targetList); + + Oid sortColumnTypeId = exprType(sortExpression); + if (sortColumnTypeId == hllTypeId) + { + hasOrderByHllType = true; + break; + } + } + + return hasOrderByHllType; +} diff --git a/src/backend/distributed/planner/multi_logical_planner.c b/src/backend/distributed/planner/multi_logical_planner.c new file mode 100644 index 000000000..8f866c074 --- /dev/null +++ b/src/backend/distributed/planner/multi_logical_planner.c @@ -0,0 +1,1952 @@ +/*------------------------------------------------------------------------- + * + * multi_logical_planner.c + * + * Routines for constructing a logical plan tree from the given Query tree + * structure. This new logical plan is based on multi-relational algebra rules. + * + * Copyright (c) 2012, Citus Data, Inc. + * + * $Id$ + * + *------------------------------------------------------------------------- + */ + +#include "postgres.h" + +#include "access/nbtree.h" +#include "catalog/pg_am.h" +#include "commands/defrem.h" +#include "distributed/metadata_cache.h" +#include "distributed/multi_logical_optimizer.h" +#include "distributed/multi_logical_planner.h" +#include "distributed/multi_physical_planner.h" +#include "distributed/worker_protocol.h" +#include "nodes/makefuncs.h" +#include "nodes/nodeFuncs.h" +#include "optimizer/clauses.h" +#include "optimizer/prep.h" +#include "optimizer/tlist.h" +#include "optimizer/var.h" +#include "parser/parsetree.h" +#include "utils/datum.h" +#include "utils/lsyscache.h" +#include "utils/syscache.h" + + +/* Config variable managed via guc.c */ +bool SubqueryPushdown = false; /* is subquery pushdown enabled */ + + +/* Function pointer type definition for apply join rule functions */ +typedef MultiNode * (*RuleApplyFunction) (MultiNode *leftNode, MultiNode *rightNode, + Var *partitionColumn, JoinType joinType, + List *joinClauses); + +static RuleApplyFunction RuleApplyFunctionArray[JOIN_RULE_LAST] = {0}; /* join rules */ + +/* Local functions forward declarations */ +static MultiNode * MultiPlanTree(Query *queryTree); +static void ErrorIfQueryNotSupported(Query *queryTree); +static bool HasUnsupportedJoinWalker(Node *node, void *context); +static void ErrorIfSubqueryNotSupported(Query *subqueryTree); +#if (PG_VERSION_NUM >= 90500) +static bool HasTablesample(Query *queryTree); +#endif +static bool HasOuterJoin(Query *queryTree); +static bool HasOuterJoinWalker(Node *node, void *maxJoinLevel); +static bool HasComplexJoinOrder(Query *queryTree); +static bool HasComplexRangeTableType(Query *queryTree); +static void ValidateClauseList(List *clauseList); +static bool ExtractFromExpressionWalker(Node *node, List **qualifierList); +static bool IsJoinClause(Node *clause); +static List * MultiTableNodeList(List *tableEntryList, List *rangeTableList); +static List * AddMultiCollectNodes(List *tableNodeList); +static MultiNode * MultiJoinTree(List *joinOrderList, List *collectTableList, + List *joinClauseList); +static MultiCollect * CollectNodeForTable(List *collectTableList, uint32 rangeTableId); +static MultiSelect * MultiSelectNode(List *whereClauseList); +static bool IsSelectClause(Node *clause); +static MultiProject * MultiProjectNode(List *targetEntryList); +static MultiExtendedOp * MultiExtendedOpNode(Query *queryTree); + +/* Local functions forward declarations for applying joins */ +static MultiNode * ApplyJoinRule(MultiNode *leftNode, MultiNode *rightNode, + JoinRuleType ruleType, Var *partitionColumn, + JoinType joinType, List *joinClauseList); +static RuleApplyFunction JoinRuleApplyFunction(JoinRuleType ruleType); +static MultiNode * ApplyBroadcastJoin(MultiNode *leftNode, MultiNode *rightNode, + Var *partitionColumn, JoinType joinType, + List *joinClauses); +static MultiNode * ApplyLocalJoin(MultiNode *leftNode, MultiNode *rightNode, + Var *partitionColumn, JoinType joinType, + List *joinClauses); +static MultiNode * ApplySinglePartitionJoin(MultiNode *leftNode, MultiNode *rightNode, + Var *partitionColumn, JoinType joinType, + List *joinClauses); +static MultiNode * ApplyDualPartitionJoin(MultiNode *leftNode, MultiNode *rightNode, + Var *partitionColumn, JoinType joinType, + List *joinClauses); +static MultiNode * ApplyCartesianProduct(MultiNode *leftNode, MultiNode *rightNode, + Var *partitionColumn, JoinType joinType, + List *joinClauses); + +/* + * Local functions forward declarations for subquery pushdown. Note that these + * functions will be removed with upcoming subqery changes. + */ +static MultiNode * SubqueryPushdownMultiPlanTree(Query *queryTree, + List *subqueryEntryList); +static void ErrorIfSubqueryJoin(Query *queryTree); +static MultiTable * MultiSubqueryPushdownTable(RangeTblEntry *subqueryRangeTableEntry); + + +/* + * MultiLogicalPlanCreate takes in a parsed query tree, uses helper functions to + * create logical plan and adds a root node to top of it. + */ +MultiTreeRoot * +MultiLogicalPlanCreate(Query *queryTree) +{ + MultiNode *multiQueryNode = NULL; + MultiTreeRoot *rootNode = NULL; + + List *subqueryEntryList = SubqueryEntryList(queryTree); + if (subqueryEntryList != NIL) + { + if (SubqueryPushdown) + { + multiQueryNode = SubqueryPushdownMultiPlanTree(queryTree, subqueryEntryList); + } + else + { + ErrorIfSubqueryJoin(queryTree); + multiQueryNode = MultiPlanTree(queryTree); + } + } + else + { + multiQueryNode = MultiPlanTree(queryTree); + } + + /* add a root node to serve as the permanent handle to the tree */ + rootNode = CitusMakeNode(MultiTreeRoot); + SetChild((MultiUnaryNode *) rootNode, multiQueryNode); + + return rootNode; +} + + +/* + * SubqueryEntryList finds the subquery nodes in the range table entry list, and + * builds a list of subquery range table entries from these subquery nodes. Range + * table entry list also includes subqueries which are pulled up. We don't want + * to add pulled up subqueries to list, so we walk over join tree indexes and + * check range table entries referenced in the join tree. + */ +List * +SubqueryEntryList(Query *queryTree) +{ + List *rangeTableList = queryTree->rtable; + List *subqueryEntryList = NIL; + List *joinTreeTableIndexList = NIL; + ListCell *joinTreeTableIndexCell = NULL; + + /* + * Extract all range table indexes from the join tree. Note that here we + * only walk over range table entries at this level and do not recurse into + * subqueries. + */ + ExtractRangeTableIndexWalker((Node*) queryTree->jointree, &joinTreeTableIndexList); + foreach(joinTreeTableIndexCell, joinTreeTableIndexList) + { + /* + * Join tree's range table index starts from 1 in the query tree. But, + * list indexes start from 0. + */ + int joinTreeTableIndex = lfirst_int(joinTreeTableIndexCell); + int rangeTableListIndex = joinTreeTableIndex - 1; + RangeTblEntry *rangeTableEntry = + (RangeTblEntry *) list_nth(rangeTableList, rangeTableListIndex); + + if (rangeTableEntry->rtekind == RTE_SUBQUERY) + { + subqueryEntryList = lappend(subqueryEntryList, rangeTableEntry); + } + } + + return subqueryEntryList; +} + + +/* + * MultiPlanTree takes in a parsed query tree and uses that tree to construct a + * logical plan. This plan is based on multi-relational algebra. This function + * creates the logical plan in several steps. + * + * First, the function checks if there is a subquery. If there is a subquery + * it recursively creates nested multi trees. If this query has a subquery, the + * function does not create any join trees and jumps to last step. + * + * If there is no subquery, the function calculates the join order using tables + * in the query and join clauses between the tables. Second, the function + * starts building the logical plan from the bottom-up, and begins with the table + * and collect nodes. Third, the function builds the join tree using the join + * order information and table nodes. + * + * In the last step, the function adds the select, project, aggregate, sort, + * group, and limit nodes if they appear in the original query tree. + */ +static MultiNode * +MultiPlanTree(Query *queryTree) +{ + List *rangeTableList = queryTree->rtable; + List *targetEntryList = queryTree->targetList; + List *whereClauseList = NIL; + List *joinClauseList = NIL; + List *joinOrderList = NIL; + List *tableEntryList = NIL; + List *tableNodeList = NIL; + List *collectTableList = NIL; + List *subqueryEntryList = NIL; + MultiNode *joinTreeNode = NULL; + MultiSelect *selectNode = NULL; + MultiProject *projectNode = NULL; + MultiExtendedOp *extendedOpNode = NULL; + MultiNode *currentTopNode = NULL; + + /* verify we can perform distributed planning on this query */ + ErrorIfQueryNotSupported(queryTree); + + /* extract where clause qualifiers and verify we can plan for them */ + whereClauseList = WhereClauseList(queryTree->jointree); + ValidateClauseList(whereClauseList); + + /* + * If we have a subquery, build a multi table node for the subquery and + * add a collect node on top of the multi table node. + */ + subqueryEntryList = SubqueryEntryList(queryTree); + if (subqueryEntryList != NIL) + { + RangeTblEntry *subqueryRangeTableEntry = NULL; + MultiCollect *subqueryCollectNode = CitusMakeNode(MultiCollect); + MultiTable *subqueryNode = NULL; + MultiNode *subqueryExtendedNode = NULL; + Query *subqueryTree = NULL; + List *whereClauseColumnList = NIL; + List *targetListColumnList = NIL; + List *columnList = NIL; + ListCell *columnCell = NULL; + + subqueryRangeTableEntry = (RangeTblEntry *) linitial(subqueryEntryList); + subqueryTree = subqueryRangeTableEntry->subquery; + + /* check if subquery satisfies preconditons */ + ErrorIfSubqueryNotSupported(subqueryTree); + + /* check if subquery has joining tables */ + ErrorIfSubqueryJoin(subqueryTree); + + subqueryNode = CitusMakeNode(MultiTable); + subqueryNode->relationId = SUBQUERY_RELATION_ID; + subqueryNode->rangeTableId = SUBQUERY_RANGE_TABLE_ID; + subqueryNode->partitionColumn = NULL; + subqueryNode->alias = NULL; + subqueryNode->referenceNames = NULL; + + /* + * We disregard pulled subqueries. This changes order of range table list. + * We do not allow subquery joins, so we will have only one range table + * entry in range table list after dropping pulled subquery. For this + * reason, here we are updating columns in the most outer query for where + * clause list and target list accordingly. + */ + Assert(list_length(subqueryEntryList) == 1); + + whereClauseColumnList = pull_var_clause_default((Node *) whereClauseList); + targetListColumnList = pull_var_clause_default((Node *) targetEntryList); + + columnList = list_concat(whereClauseColumnList, targetListColumnList); + foreach(columnCell, columnList) + { + Var *column = (Var *) lfirst(columnCell); + column->varno = 1; + } + + /* recursively create child nested multitree */ + subqueryExtendedNode = MultiPlanTree(subqueryTree); + + SetChild((MultiUnaryNode *) subqueryCollectNode, (MultiNode *) subqueryNode); + SetChild((MultiUnaryNode *) subqueryNode, subqueryExtendedNode); + + currentTopNode = (MultiNode *) subqueryCollectNode; + } + else + { + bool hasOuterJoin = false; + /* + * We calculate the join order using the list of tables in the query and + * the join clauses between them. Note that this function owns the table + * entry list's memory, and JoinOrderList() shallow copies the list's + * elements. + */ + joinClauseList = JoinClauseList(whereClauseList); + tableEntryList = TableEntryList(rangeTableList); + + /* build the list of multi table nodes */ + tableNodeList = MultiTableNodeList(tableEntryList, rangeTableList); + + /* add collect nodes on top of the multi table nodes */ + collectTableList = AddMultiCollectNodes(tableNodeList); + + hasOuterJoin = HasOuterJoin(queryTree); + if (hasOuterJoin) + { + /* use the user-defined join order when there are outer joins */ + joinOrderList = FixedJoinOrderList(queryTree->jointree, tableEntryList); + } + else + { + /* find best join order for commutative inner joins */ + joinOrderList = JoinOrderList(tableEntryList, joinClauseList); + } + + /* build join tree using the join order and collected tables */ + joinTreeNode = MultiJoinTree(joinOrderList, collectTableList, joinClauseList); + + currentTopNode = joinTreeNode; + } + + Assert(currentTopNode != NULL); + + /* build select node if the query has selection criteria */ + selectNode = MultiSelectNode(whereClauseList); + if (selectNode != NULL) + { + SetChild((MultiUnaryNode *) selectNode, currentTopNode); + currentTopNode = (MultiNode *) selectNode; + } + + /* build project node for the columns to project */ + projectNode = MultiProjectNode(targetEntryList); + SetChild((MultiUnaryNode *) projectNode, currentTopNode); + currentTopNode = (MultiNode *) projectNode; + + /* + * We build the extended operator node to capture aggregate functions, group + * clauses, sort clauses, limit/offset clauses, and expressions. We need to + * distinguish between aggregates and expressions; and we address this later + * in the logical optimizer. + */ + extendedOpNode = MultiExtendedOpNode(queryTree); + SetChild((MultiUnaryNode *) extendedOpNode, currentTopNode); + currentTopNode = (MultiNode *) extendedOpNode; + + return currentTopNode; +} + + +/* + * ErrorIfQueryNotSupported checks that we can perform distributed planning for + * the given query. The checks in this function will be removed as we support + * more functionality in our distributed planning. + */ +static void +ErrorIfQueryNotSupported(Query *queryTree) +{ + char *errorDetail = NULL; +#if (PG_VERSION_NUM >= 90500) + bool hasTablesample = false; +#endif + bool hasUnsupportedJoin = false; + bool hasComplexJoinOrder = false; + bool hasComplexRangeTableType = false; + bool preconditionsSatisfied = true; + + if (queryTree->hasSubLinks) + { + preconditionsSatisfied = false; + errorDetail = "Subqueries other than in from-clause are currently unsupported"; + } + + if (queryTree->havingQual != NULL) + { + preconditionsSatisfied = false; + errorDetail = "Having qual is currently unsupported"; + } + + if (queryTree->hasWindowFuncs) + { + preconditionsSatisfied = false; + errorDetail = "Window functions are currently unsupported"; + } + + if (queryTree->limitOffset) + { + preconditionsSatisfied = false; + errorDetail = "Limit Offset clause is currently unsupported"; + } + + if (queryTree->setOperations) + { + preconditionsSatisfied = false; + errorDetail = "Union, Intersect, or Except are currently unsupported"; + } + + if (queryTree->hasRecursive) + { + preconditionsSatisfied = false; + errorDetail = "Recursive queries are currently unsupported"; + } + + if (queryTree->cteList) + { + preconditionsSatisfied = false; + errorDetail = "Common Table Expressions are currently unsupported"; + } + + if (queryTree->hasForUpdate) + { + preconditionsSatisfied = false; + errorDetail = "For Update/Share commands are currently unsupported"; + } + + if (queryTree->distinctClause) + { + preconditionsSatisfied = false; + errorDetail = "Distinct clause is currently unsupported"; + } + +#if (PG_VERSION_NUM >= 90500) + if (queryTree->groupingSets) + { + preconditionsSatisfied = false; + errorDetail = "Grouping sets, cube, and rollup is currently unsupported"; + } + + hasTablesample = HasTablesample(queryTree); + if (hasTablesample) + { + preconditionsSatisfied = false; + errorDetail = "Tablesample is currently unsupported"; + } +#endif + + hasUnsupportedJoin = HasUnsupportedJoinWalker((Node *) queryTree->jointree, NULL); + if (hasUnsupportedJoin) + { + preconditionsSatisfied = false; + errorDetail = "Join types other than inner/outer joins are currently unsupported"; + } + + hasComplexJoinOrder = HasComplexJoinOrder(queryTree); + if (hasComplexJoinOrder) + { + preconditionsSatisfied = false; + errorDetail = "Complex join orders are currently unsupported"; + } + + hasComplexRangeTableType = HasComplexRangeTableType(queryTree); + if (hasComplexRangeTableType) + { + preconditionsSatisfied = false; + errorDetail = "Complex table expressions are currently unsupported"; + } + + /* finally check and error out if not satisfied */ + if (!preconditionsSatisfied) + { + ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("cannot perform distributed planning on this query"), + errdetail("%s", errorDetail))); + } +} + + +#if (PG_VERSION_NUM >= 90500) +/* HasTablesample returns tree if the query contains tablesample */ +static bool +HasTablesample(Query *queryTree) +{ + List *rangeTableList = queryTree->rtable; + ListCell *rangeTableEntryCell = NULL; + bool hasTablesample = false; + + foreach(rangeTableEntryCell, rangeTableList) + { + RangeTblEntry *rangeTableEntry = lfirst(rangeTableEntryCell); + if (rangeTableEntry->tablesample) + { + hasTablesample = true; + break; + } + } + + return hasTablesample; +} +#endif + + +/* + * HasUnsupportedJoinWalker returns tree if the query contains an unsupported + * join type. We currently support inner, left, right, full and anti joins. + * Semi joins are not supported. A full description of these join types is + * included in nodes/nodes.h. + */ +static bool +HasUnsupportedJoinWalker(Node *node, void *context) +{ + bool hasUnsupportedJoin = false; + + if (node == NULL) + { + return false; + } + + if (IsA(node, JoinExpr)) + { + JoinExpr *joinExpr = (JoinExpr *) node; + JoinType joinType = joinExpr->jointype; + bool outerJoin = IS_OUTER_JOIN(joinType); + if (!outerJoin && joinType != JOIN_INNER) + { + hasUnsupportedJoin = true; + } + } + + if (!hasUnsupportedJoin) + { + hasUnsupportedJoin = expression_tree_walker(node, HasUnsupportedJoinWalker, + NULL); + } + + return hasUnsupportedJoin; +} + + +/* + * ErrorIfSubqueryNotSupported checks that we can perform distributed planning for + * the given subquery. + */ +static void ErrorIfSubqueryNotSupported(Query *subqueryTree) +{ + char *errorDetail = NULL; + bool preconditionsSatisfied = true; + + if (!subqueryTree->hasAggs) + { + preconditionsSatisfied = false; + errorDetail = "Subqueries without aggregates are not supported yet"; + } + + if (subqueryTree->groupClause == NIL) + { + preconditionsSatisfied = false; + errorDetail = "Subqueries without group by clause are not supported yet"; + } + + if (subqueryTree->sortClause != NULL) + { + preconditionsSatisfied = false; + errorDetail = "Subqueries with order by clause are not supported yet"; + } + + if (subqueryTree->limitCount != NULL) + { + preconditionsSatisfied = false; + errorDetail = "Subqueries with limit are not supported yet"; + } + + /* finally check and error out if not satisfied */ + if (!preconditionsSatisfied) + { + ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("cannot perform distributed planning on this query"), + errdetail("%s", errorDetail))); + } +} + + +/* + * HasOuterJoin returns true if query has a outer join. + */ +static bool +HasOuterJoin(Query *queryTree) +{ + bool hasOuterJoin = HasOuterJoinWalker((Node *) queryTree->jointree, NULL); + + return hasOuterJoin; +} + + +/* + * HasOuterJoinWalker returns true if the query has an outer join. The context + * parameter should be NULL. + */ +static bool +HasOuterJoinWalker(Node *node, void *context) +{ + + bool hasOuterJoin = false; + if (node == NULL) + { + return false; + } + + if (IsA(node, JoinExpr)) + { + JoinExpr *joinExpr = (JoinExpr *) node; + JoinType joinType = joinExpr->jointype; + if (IS_OUTER_JOIN(joinType)) + { + hasOuterJoin = true; + } + } + + if (!hasOuterJoin) + { + hasOuterJoin = expression_tree_walker(node, HasOuterJoinWalker, NULL); + } + + return hasOuterJoin; +} + + +/* + * HasComplexJoinOrder returns true if join tree is not a left-handed tree i.e. + * it has a join expression in at least one right argument. + */ +static bool +HasComplexJoinOrder(Query *queryTree) +{ + bool hasComplexJoinOrder = false; + List *joinList = NIL; + ListCell *joinCell = NULL; + + joinList = JoinExprList(queryTree->jointree); + foreach(joinCell, joinList) + { + JoinExpr *joinExpr = lfirst(joinCell); + if (IsA(joinExpr->rarg, JoinExpr)) + { + hasComplexJoinOrder = true; + break; + } + } + + return hasComplexJoinOrder; +} + + +/* + * HasComplexRangeTableType checks if the given query tree contains any complex + * range table types. For this, the function walks over all range tables in the + * join tree, and checks if they correspond to simple relations or subqueries. + * If they don't, the function assumes the query has complex range tables. + */ +static bool +HasComplexRangeTableType(Query *queryTree) +{ + List *rangeTableList = queryTree->rtable; + List *joinTreeTableIndexList = NIL; + ListCell *joinTreeTableIndexCell = NULL; + bool hasComplexRangeTableType = false; + + /* + * Extract all range table indexes from the join tree. Note that sub-queries + * that get pulled up by PostgreSQL don't appear in this join tree. + */ + ExtractRangeTableIndexWalker((Node*) queryTree->jointree, &joinTreeTableIndexList); + foreach(joinTreeTableIndexCell, joinTreeTableIndexList) + { + /* + * Join tree's range table index starts from 1 in the query tree. But, + * list indexes start from 0. + */ + int joinTreeTableIndex = lfirst_int(joinTreeTableIndexCell); + int rangeTableListIndex = joinTreeTableIndex - 1; + + RangeTblEntry *rangeTableEntry = + (RangeTblEntry *) list_nth(rangeTableList, rangeTableListIndex); + + /* + * Check if the range table in the join tree is a simple relation or a + * subquery. + */ + if (rangeTableEntry->rtekind != RTE_RELATION && + rangeTableEntry->rtekind != RTE_SUBQUERY) + { + hasComplexRangeTableType = true; + } + + /* + * Check if the subquery range table entry includes children inheritance. + * + * Note that PostgreSQL flattens out simple union all queries into an + * append relation, sets "inh" field of RangeTblEntry to true and deletes + * set operations. Here we check this for subqueries. + */ + if (rangeTableEntry->rtekind == RTE_SUBQUERY && rangeTableEntry->inh) + { + hasComplexRangeTableType = true; + } + } + + return hasComplexRangeTableType; +} + + +/* + * ExtractRangeTableIndexWalker walks over a join tree, and finds all range + * table indexes in that tree. + */ +bool +ExtractRangeTableIndexWalker(Node *node, List **rangeTableIndexList) +{ + bool walkerResult = false; + if (node == NULL) + { + return false; + } + + if (IsA(node, RangeTblRef)) + { + int rangeTableIndex = ((RangeTblRef *) node)->rtindex; + (*rangeTableIndexList) = lappend_int(*rangeTableIndexList, rangeTableIndex); + } + else + { + walkerResult = expression_tree_walker(node, ExtractRangeTableIndexWalker, + rangeTableIndexList); + } + + return walkerResult; +} + + +/* + * WhereClauseList walks over the FROM expression in the query tree, and builds + * a list of all clauses from the expression tree. The function checks for both + * implicitly and explicitly defined clauses. Explicit clauses are expressed as + * "SELECT ... FROM R1 INNER JOIN R2 ON R1.A = R2.A". Implicit joins differ in + * that they live in the WHERE clause, and are expressed as "SELECT ... FROM + * ... WHERE R1.a = R2.a". + */ +List * +WhereClauseList(FromExpr *fromExpr) +{ + FromExpr *fromExprCopy = copyObject(fromExpr); + List *whereClauseList = NIL; + + ExtractFromExpressionWalker((Node *) fromExprCopy, &whereClauseList); + + return whereClauseList; +} + + +/* + * ValidateClauseList walks over the given list of clauses, and checks that we + * can recognize all the clauses. This function ensures that we do not drop an + * unsupported clause type on the floor, and thus prevents erroneous results. + */ +static void +ValidateClauseList(List *clauseList) +{ + ListCell *clauseCell = NULL; + foreach(clauseCell, clauseList) + { + Node *clause = (Node *) lfirst(clauseCell); + + bool selectClause = IsSelectClause(clause); + bool joinClause = IsJoinClause(clause); + bool orClause = or_clause(clause); + + if (!(selectClause || joinClause || orClause)) + { + ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("unsupported clause type"))); + } + } +} + + +/* + * JoinClauseList finds the join clauses from the given where clause expression + * list, and returns them. The function does not iterate into nested OR clauses + * and relies on find_duplicate_ors() in the optimizer to pull up factorizable + * OR clauses. + */ +List * +JoinClauseList(List *whereClauseList) +{ + List *joinClauseList = NIL; + ListCell *whereClauseCell = NULL; + + foreach(whereClauseCell, whereClauseList) + { + Node *whereClause = (Node *) lfirst(whereClauseCell); + if (IsJoinClause(whereClause)) + { + joinClauseList = lappend(joinClauseList, whereClause); + } + } + + return joinClauseList; +} + + +/* + * ExtractFromExpressionWalker walks over a FROM expression, and finds all + * explicit qualifiers in the expression. The function looks at join and from + * expression nodes to find explicit qualifiers, and returns these qualifiers. + * + * Note that we check if the qualifier node in join and from expression nodes + * is a list node. If it is not a list node which is the case for subqueries, + * then we run eval_const_expressions(), canonicalize_qual() and make_ands_implicit() + * on the qualifier node and get a list of flattened implicitly AND'ed qualifier + * list. Actually in the planer phase of PostgreSQL these functions also run on + * subqueries but differently from the outermost query, they are run on a copy + * of parse tree and changes do not get persisted as modifications to the original + * query tree. + */ +static bool +ExtractFromExpressionWalker(Node *node, List **qualifierList) +{ + bool walkerResult = false; + if (node == NULL) + { + return false; + } + + /* + * Get qualifier lists of join and from expression nodes. Note that in the + * case of subqueries, PostgreSQL can skip simplifying, flattening and + * making ANDs implicit. If qualifiers node is not a list, then we run these + * preprocess routines on qualifiers node. + */ + if (IsA(node, JoinExpr)) + { + List *joinQualifierList = NIL; + JoinExpr *joinExpression = (JoinExpr *) node; + Node *joinQualifiersNode = joinExpression->quals; + + if (joinQualifiersNode != NULL) + { + if (IsA(joinQualifiersNode, List)) + { + joinQualifierList = (List *) joinQualifiersNode; + } + else + { + /* this part of code only run for subqueries */ + Node *joinClause = eval_const_expressions(NULL, joinQualifiersNode); + joinClause = (Node *) canonicalize_qual((Expr *) joinClause); + joinQualifierList = make_ands_implicit((Expr *) joinClause); + } + + (*qualifierList) = list_concat(*qualifierList, joinQualifierList); + } + } + else if (IsA(node, FromExpr)) + { + List *fromQualifierList = NIL; + FromExpr *fromExpression = (FromExpr *) node; + Node *fromQualifiersNode = fromExpression->quals; + + if (fromQualifiersNode != NULL) + { + if (IsA(fromQualifiersNode, List)) + { + fromQualifierList = (List *) fromQualifiersNode; + } + else + { + /* this part of code only run for subqueries */ + Node *fromClause = eval_const_expressions(NULL, fromQualifiersNode); + fromClause = (Node *) canonicalize_qual((Expr *) fromClause); + fromQualifierList = make_ands_implicit((Expr *) fromClause); + } + + (*qualifierList) = list_concat(*qualifierList, fromQualifierList); + } + } + + walkerResult = expression_tree_walker(node, ExtractFromExpressionWalker, + (void *) qualifierList); + + return walkerResult; +} + + +/* + * IsJoinClause determines if the given node is a join clause according to our + * criteria. Our criteria defines a join clause as an equi join operator between + * two columns that belong to two different tables. + */ +static bool +IsJoinClause(Node *clause) +{ + bool isJoinClause = false; + OpExpr *operatorExpression = NULL; + List *argumentList = NIL; + Node *leftArgument = NULL; + Node *rightArgument = NULL; + List *leftColumnList = NIL; + List *rightColumnList = NIL; + + if (!IsA(clause, OpExpr)) + { + return false; + } + + operatorExpression = (OpExpr *) clause; + argumentList = operatorExpression->args; + + /* join clauses must have two arguments */ + if (list_length(argumentList) != 2) + { + return false; + } + + /* get left and right side of the expression */ + leftArgument = (Node *) linitial(argumentList); + rightArgument = (Node *) lsecond(argumentList); + + leftColumnList = pull_var_clause_default(leftArgument); + rightColumnList = pull_var_clause_default(rightArgument); + + /* each side of the expression should have only one column */ + if ((list_length(leftColumnList) == 1) && (list_length(rightColumnList) == 1)) + { + Var *leftColumn = (Var *) linitial(leftColumnList); + Var *rightColumn = (Var *) linitial(rightColumnList); + bool equiJoin = false; + bool joinBetweenDifferentTables = false; + + /* + * We accept all column types that can be joined with an equals sign as + * valid. These include columns that have cross-type equals operators + * (such as int48eq) and columns that can be casted at run-time (such as + * from numeric to int4). + */ + char *operatorName = get_opname(operatorExpression->opno); + int equalsOperator = strncmp(operatorName, EQUAL_OPERATOR_STRING, NAMEDATALEN); + if (equalsOperator == 0) + { + equiJoin = true; + } + + if (leftColumn->varno != rightColumn->varno) + { + joinBetweenDifferentTables = true; + } + + /* codifies our logic for determining if this node is a join clause */ + if (equiJoin && joinBetweenDifferentTables) + { + isJoinClause = true; + } + } + + return isJoinClause; +} + + +/* + * TableEntryList finds the regular relation nodes in the range table entry + * list, and builds a list of table entries from these regular relation nodes. + */ +List * +TableEntryList(List *rangeTableList) +{ + List *tableEntryList = NIL; + ListCell *rangeTableCell = NULL; + uint32 tableId = 1; /* range table indices start at 1 */ + + foreach(rangeTableCell, rangeTableList) + { + RangeTblEntry *rangeTableEntry = (RangeTblEntry *) lfirst(rangeTableCell); + + if (rangeTableEntry->rtekind == RTE_RELATION) + { + TableEntry *tableEntry = (TableEntry *) palloc0(sizeof(TableEntry)); + tableEntry->relationId = rangeTableEntry->relid; + tableEntry->rangeTableId = tableId; + + tableEntryList = lappend(tableEntryList, tableEntry); + } + + /* + * Increment tableId regardless so that table entry's tableId remains + * congruent with column's range table reference (varno). + */ + tableId++; + } + + return tableEntryList; +} + + +/* + * MultiTableNodeList builds a list of MultiTable nodes from the given table + * entry list. A multi table node represents one entry from the range table + * list. These entries may belong to the same physical relation in the case of + * self-joins. + */ +static List * +MultiTableNodeList(List *tableEntryList, List *rangeTableList) +{ + List *tableNodeList = NIL; + ListCell *tableEntryCell = NULL; + + foreach(tableEntryCell, tableEntryList) + { + TableEntry *tableEntry = (TableEntry *) lfirst(tableEntryCell); + Oid relationId = tableEntry->relationId; + uint32 rangeTableId = tableEntry->rangeTableId; + Var *partitionColumn = PartitionColumn(relationId, rangeTableId); + RangeTblEntry *rangeTableEntry = rt_fetch(rangeTableId, rangeTableList); + + MultiTable *tableNode = CitusMakeNode(MultiTable); + tableNode->subquery = NULL; + tableNode->relationId = relationId; + tableNode->rangeTableId = rangeTableId; + tableNode->partitionColumn = partitionColumn; + tableNode->alias = rangeTableEntry->alias; + tableNode->referenceNames = rangeTableEntry->eref; + + tableNodeList = lappend(tableNodeList, tableNode); + } + + return tableNodeList; +} + + +/* Adds a MultiCollect node on top of each MultiTable node in the given list. */ +static List * +AddMultiCollectNodes(List *tableNodeList) +{ + List *collectTableList = NIL; + ListCell *tableNodeCell = NULL; + + foreach(tableNodeCell, tableNodeList) + { + MultiTable *tableNode = (MultiTable *) lfirst(tableNodeCell); + + MultiCollect *collectNode = CitusMakeNode(MultiCollect); + SetChild((MultiUnaryNode *) collectNode, (MultiNode *) tableNode); + + collectTableList = lappend(collectTableList, collectNode); + } + + return collectTableList; +} + + +/* + * MultiJoinTree takes in the join order information and the list of tables, and + * builds a join tree by applying the corresponding join rules. The function + * builds a left deep tree, as expressed by the join order list. + * + * The function starts by setting the first table as the top node in the join + * tree. Then, the function iterates over the list of tables, and builds a new + * join node between the top of the join tree and the next table in the list. + * At each iteration, the function sets the top of the join tree to the newly + * built list. This results in a left deep join tree, and the function returns + * this tree after every table in the list has been joined. + */ +static MultiNode * +MultiJoinTree(List *joinOrderList, List *collectTableList, List *joinWhereClauseList) +{ + MultiNode *currentTopNode = NULL; + ListCell *joinOrderCell = NULL; + bool firstJoinNode = true; + + foreach(joinOrderCell, joinOrderList) + { + JoinOrderNode *joinOrderNode = (JoinOrderNode *) lfirst(joinOrderCell); + uint32 joinTableId = joinOrderNode->tableEntry->rangeTableId; + MultiCollect *collectNode = CollectNodeForTable(collectTableList, joinTableId); + + if (firstJoinNode) + { + currentTopNode = (MultiNode *) collectNode; + firstJoinNode = false; + } + else + { + JoinRuleType joinRuleType = joinOrderNode->joinRuleType; + JoinType joinType = joinOrderNode->joinType; + Var *partitionColumn = joinOrderNode->partitionColumn; + MultiNode *newJoinNode = NULL; + List *joinClauseList = joinOrderNode->joinClauseList; + + /* + * Build a join node between the top of our join tree and the next + * table in the join order. + */ + newJoinNode = ApplyJoinRule(currentTopNode, (MultiNode *) collectNode, + joinRuleType, partitionColumn, joinType, + joinClauseList); + + /* the new join node becomes the top of our join tree */ + currentTopNode = newJoinNode; + } + } + + /* current top node points to the entire left deep join tree */ + return currentTopNode; +} + + +/* + * CollectNodeForTable finds the MultiCollect node whose MultiTable node has the + * given range table identifier. Note that this function expects each collect + * node in the given list to have one table node as its child. + */ +static MultiCollect * +CollectNodeForTable(List *collectTableList, uint32 rangeTableId) +{ + MultiCollect *collectNodeForTable = NULL; + ListCell *collectTableCell = NULL; + + foreach(collectTableCell, collectTableList) + { + MultiCollect *collectNode = (MultiCollect *) lfirst(collectTableCell); + + List *tableIdList = OutputTableIdList((MultiNode *) collectNode); + uint32 tableId = (uint32) linitial_int(tableIdList); + Assert(list_length(tableIdList) == 1); + + if (tableId == rangeTableId) + { + collectNodeForTable = collectNode; + break; + } + } + + Assert(collectNodeForTable != NULL); + return collectNodeForTable; +} + + +/* + * MultiSelectNode extracts the select clauses from the given where clause list, + * and builds a MultiSelect node from these clauses. If the expression tree does + * not have any select clauses, the function return null. + */ +static MultiSelect * +MultiSelectNode(List *whereClauseList) +{ + List *selectClauseList = NIL; + MultiSelect *selectNode = NULL; + + ListCell *whereClauseCell = NULL; + foreach(whereClauseCell, whereClauseList) + { + Node *whereClause = (Node *) lfirst(whereClauseCell); + if (IsSelectClause(whereClause) || or_clause(whereClause)) + { + selectClauseList = lappend(selectClauseList, whereClause); + } + } + + if (list_length(selectClauseList) > 0) + { + selectNode = CitusMakeNode(MultiSelect); + selectNode->selectClauseList = selectClauseList; + } + + return selectNode; +} + + +/* + * IsSelectClause determines if the given node is a select clause according to + * our criteria. Our criteria defines a select clause as an expression that has + * columns belonging to only one table. + */ +static bool +IsSelectClause(Node *clause) +{ + List *columnList = NIL; + ListCell *columnCell = NULL; + Var *firstColumn = NULL; + Index firstColumnTableId = 0; + bool isSelectClause = true; + + /* we currently consider the following nodes as select clauses */ + NodeTag nodeTag = nodeTag(clause); + if ( !(nodeTag == T_OpExpr || nodeTag == T_ScalarArrayOpExpr || + nodeTag == T_NullTest || nodeTag == T_BooleanTest) ) + { + return false; + } + + /* extract columns from the clause */ + columnList = pull_var_clause_default(clause); + if (list_length(columnList) == 0) + { + return false; + } + + /* get first column's tableId */ + firstColumn = (Var *) linitial(columnList); + firstColumnTableId = firstColumn->varno; + + /* check if all columns are from the same table */ + foreach(columnCell, columnList) + { + Var *column = (Var *) lfirst(columnCell); + if (column->varno != firstColumnTableId) + { + isSelectClause = false; + } + } + + return isSelectClause; +} + + +/* + * MultiProjectNode builds the project node using the target entry information + * from the query tree. The project node only encapsulates projected columns, + * and does not include aggregates, group clauses, or project expressions. + */ +static MultiProject * +MultiProjectNode(List *targetEntryList) +{ + MultiProject *projectNode = NULL; + List *uniqueColumnList = NIL; + List *columnList = NIL; + ListCell *columnCell = NULL; + + /* extract the list of columns and remove any duplicates */ + columnList = pull_var_clause_default((Node *) targetEntryList); + + foreach(columnCell, columnList) + { + Var *column = (Var *) lfirst(columnCell); + + uniqueColumnList = list_append_unique(uniqueColumnList, column); + } + + /* create project node with list of columns to project */ + projectNode = CitusMakeNode(MultiProject); + projectNode->columnList = uniqueColumnList; + + return projectNode; +} + + +/* Builds the extended operator node using fields from the given query tree. */ +static MultiExtendedOp * +MultiExtendedOpNode(Query *queryTree) +{ + MultiExtendedOp *extendedOpNode = CitusMakeNode(MultiExtendedOp); + extendedOpNode->targetList = queryTree->targetList; + extendedOpNode->groupClauseList = queryTree->groupClause; + extendedOpNode->sortClauseList = queryTree->sortClause; + extendedOpNode->limitCount = queryTree->limitCount; + extendedOpNode->limitOffset = queryTree->limitOffset; + + return extendedOpNode; +} + + +/* Helper function to return the parent node of the given node. */ +MultiNode * +ParentNode(MultiNode *multiNode) +{ + MultiNode *parentNode = multiNode->parentNode; + return parentNode; +} + + +/* Helper function to return the child of the given unary node. */ +MultiNode * +ChildNode(MultiUnaryNode *multiNode) +{ + MultiNode *childNode = multiNode->childNode; + return childNode; +} + + +/* Helper function to return the grand child of the given unary node. */ +MultiNode * +GrandChildNode(MultiUnaryNode *multiNode) +{ + MultiNode *childNode = ChildNode(multiNode); + MultiNode *grandChildNode = ChildNode((MultiUnaryNode *) childNode); + + return grandChildNode; +} + + +/* Sets the given child node as a child of the given unary parent node. */ +void +SetChild(MultiUnaryNode *parent, MultiNode *child) +{ + parent->childNode = child; + child->parentNode = (MultiNode *) parent; +} + + +/* Sets the given child node as a left child of the given parent node. */ +void +SetLeftChild(MultiBinaryNode *parent, MultiNode *leftChild) +{ + parent->leftChildNode = leftChild; + leftChild->parentNode = (MultiNode *) parent; +} + + +/* Sets the given child node as a right child of the given parent node. */ +void +SetRightChild(MultiBinaryNode *parent, MultiNode *rightChild) +{ + parent->rightChildNode = rightChild; + rightChild->parentNode = (MultiNode *) parent; +} + + +/* Returns true if the given node is a unary operator. */ +bool +UnaryOperator(MultiNode *node) +{ + bool unaryOperator = false; + + if (CitusIsA(node, MultiTreeRoot) || CitusIsA(node, MultiTable) || + CitusIsA(node, MultiCollect) || CitusIsA(node, MultiSelect) || + CitusIsA(node, MultiProject) || CitusIsA(node, MultiPartition) || + CitusIsA(node, MultiExtendedOp)) + { + unaryOperator = true; + } + + return unaryOperator; +} + + +/* Returns true if the given node is a binary operator. */ +bool +BinaryOperator(MultiNode *node) +{ + bool binaryOperator = false; + + if (CitusIsA(node, MultiJoin) || CitusIsA(node, MultiCartesianProduct)) + { + binaryOperator = true; + } + + return binaryOperator; +} + + +/* + * OutputTableIdList finds all table identifiers that are output by the given + * multi node, and returns these identifiers in a new list. + */ +List * +OutputTableIdList(MultiNode *multiNode) +{ + List *tableIdList = NIL; + List *tableNodeList = FindNodesOfType(multiNode, T_MultiTable); + ListCell *tableNodeCell = NULL; + + foreach(tableNodeCell, tableNodeList) + { + MultiTable *tableNode = (MultiTable *) lfirst(tableNodeCell); + int tableId = (int) tableNode->rangeTableId; + + if (tableId != SUBQUERY_RANGE_TABLE_ID) + { + tableIdList = lappend_int(tableIdList, tableId); + } + } + + return tableIdList; +} + + +/* + * FindNodesOfType takes in a given logical plan tree, and recursively traverses + * the tree in preorder. The function finds all nodes of requested type during + * the traversal, and returns them in a list. + */ +List * +FindNodesOfType(MultiNode *node, int type) +{ + List *nodeList = NIL; + int nodeType = T_Invalid; + + /* terminal condition for recursion */ + if (node == NULL) + { + return NIL; + } + + /* current node has expected node type */ + nodeType = CitusNodeTag(node); + if (nodeType == type) + { + nodeList = lappend(nodeList, node); + } + + if (UnaryOperator(node)) + { + MultiNode *childNode = ((MultiUnaryNode *) node)->childNode; + List *childNodeList = FindNodesOfType(childNode, type); + + nodeList = list_concat(nodeList, childNodeList); + } + else if (BinaryOperator(node)) + { + MultiNode *leftChildNode = ((MultiBinaryNode *) node)->leftChildNode; + MultiNode *rightChildNode = ((MultiBinaryNode *) node)->rightChildNode; + + List *leftChildNodeList = FindNodesOfType(leftChildNode, type); + List *rightChildNodeList = FindNodesOfType(rightChildNode, type); + + nodeList = list_concat(nodeList, leftChildNodeList); + nodeList = list_concat(nodeList, rightChildNodeList); + } + + return nodeList; +} + + +/* + * NeedsDistributedPlanning checks if the passed in query is a Select query + * running on partitioned relations. If it is, we start distributed planning. + */ +bool +NeedsDistributedPlanning(Query *queryTree) +{ + CmdType commandType = queryTree->commandType; + List *rangeTableList = NIL; + ListCell *rangeTableCell = NULL; + bool hasLocalRelation = false; + bool hasDistributedRelation = false; + + if (commandType != CMD_SELECT && commandType != CMD_INSERT && + commandType != CMD_UPDATE && commandType != CMD_DELETE) + { + return false; + } + + /* extract range table entries for simple relations only */ + ExtractRangeTableRelationWalker((Node *) queryTree, &rangeTableList); + + foreach(rangeTableCell, rangeTableList) + { + RangeTblEntry *rangeTableEntry = (RangeTblEntry *) lfirst(rangeTableCell); + + /* check if relation is local or distributed */ + Oid relationId = rangeTableEntry->relid; + + if (IsDistributedTable(relationId)) + { + hasDistributedRelation = true; + } + else + { + hasLocalRelation = true; + } + } + + /* users can't mix local and distributed relations in one query */ + if (hasLocalRelation && hasDistributedRelation) + { + ereport(ERROR, (errmsg("cannot plan queries that include both regular and " + "partitioned relations"))); + } + + return hasDistributedRelation; +} + + +/* + * ExtractRangeTableRelationWalker gathers all range table entries in a query + * and filters them to preserve only those of the RTE_RELATION type. + */ +bool +ExtractRangeTableRelationWalker(Node *node, List **rangeTableRelationList) +{ + List *rangeTableList = NIL; + ListCell *rangeTableCell = NULL; + bool walkIsComplete = ExtractRangeTableEntryWalker(node, &rangeTableList); + + foreach(rangeTableCell, rangeTableList) + { + RangeTblEntry *rangeTableEntry = (RangeTblEntry *) lfirst(rangeTableCell); + if (rangeTableEntry->rtekind == RTE_RELATION) + { + (*rangeTableRelationList) = lappend(*rangeTableRelationList, rangeTableEntry); + } + } + + return walkIsComplete; +} + + +/* + * ExtractRangeTableEntryWalker walks over a query tree, and finds all range + * table entries. For recursing into the query tree, this function uses the + * query tree walker since the expression tree walker doesn't recurse into + * sub-queries. + */ +bool +ExtractRangeTableEntryWalker(Node *node, List **rangeTableList) +{ + bool walkIsComplete = false; + if (node == NULL) + { + return false; + } + + if (IsA(node, RangeTblEntry)) + { + RangeTblEntry *rangeTable = (RangeTblEntry *) node; + (*rangeTableList) = lappend(*rangeTableList, rangeTable); + } + else if (IsA(node, Query)) + { + walkIsComplete = query_tree_walker((Query *) node, ExtractRangeTableEntryWalker, + rangeTableList, QTW_EXAMINE_RTES); + } + else + { + walkIsComplete = expression_tree_walker(node, ExtractRangeTableEntryWalker, + rangeTableList); + } + + return walkIsComplete; +} + + +/* + * pull_var_clause_default calls pull_var_clause with the most commonly used + * arguments for distributed planning. + */ +List * +pull_var_clause_default(Node *node) +{ + List *columnList = pull_var_clause(node, PVC_RECURSE_AGGREGATES, + PVC_REJECT_PLACEHOLDERS); + return columnList; +} + + +/* + * ApplyJoinRule finds the join rule application function that corresponds to + * the given join rule, and calls this function to create a new join node that + * joins the left and right nodes together. + */ +static MultiNode * +ApplyJoinRule(MultiNode *leftNode, MultiNode *rightNode, JoinRuleType ruleType, + Var *partitionColumn, JoinType joinType, List *joinClauseList) +{ + RuleApplyFunction ruleApplyFunction = NULL; + MultiNode *multiNode = NULL; + + List *applicableJoinClauses = NIL; + List *leftTableIdList = OutputTableIdList(leftNode); + List *rightTableIdList = OutputTableIdList(rightNode); + int rightTableIdCount = 0; + uint32 rightTableId = 0; + + rightTableIdCount = list_length(rightTableIdList); + Assert(rightTableIdCount == 1); + + /* find applicable join clauses between the left and right data sources */ + rightTableId = (uint32) linitial_int(rightTableIdList); + applicableJoinClauses = ApplicableJoinClauses(leftTableIdList, rightTableId, + joinClauseList); + + /* call the join rule application function to create the new join node */ + ruleApplyFunction = JoinRuleApplyFunction(ruleType); + multiNode = (*ruleApplyFunction) (leftNode, rightNode, partitionColumn, + joinType, applicableJoinClauses); + + if (joinType != JOIN_INNER && CitusIsA(multiNode, MultiJoin)) + { + MultiJoin *joinNode = (MultiJoin *) multiNode; + + /* preserve non-join clauses for OUTER joins */ + joinNode->joinClauseList = list_copy(joinClauseList); + } + + return multiNode; +} + + +/* + * JoinRuleApplyFunction returns a function pointer for the rule application + * function; this rule application function corresponds to the given rule type. + * This function also initializes the rule application function array in a + * static code block, if the array has not been initialized. + */ +static RuleApplyFunction +JoinRuleApplyFunction(JoinRuleType ruleType) +{ + static bool ruleApplyFunctionInitialized = false; + RuleApplyFunction ruleApplyFunction = NULL; + + if (!ruleApplyFunctionInitialized) + { + RuleApplyFunctionArray[BROADCAST_JOIN] = &ApplyBroadcastJoin; + RuleApplyFunctionArray[LOCAL_PARTITION_JOIN] = &ApplyLocalJoin; + RuleApplyFunctionArray[SINGLE_PARTITION_JOIN] = &ApplySinglePartitionJoin; + RuleApplyFunctionArray[DUAL_PARTITION_JOIN] = &ApplyDualPartitionJoin; + RuleApplyFunctionArray[CARTESIAN_PRODUCT] = &ApplyCartesianProduct; + + ruleApplyFunctionInitialized = true; + } + + ruleApplyFunction = RuleApplyFunctionArray[ruleType]; + Assert(ruleApplyFunction != NULL); + + return ruleApplyFunction; +} + + +/* + * ApplyBroadcastJoin creates a new MultiJoin node that joins the left and the + * right node. The new node uses the broadcast join rule to perform the join. + */ +static MultiNode * +ApplyBroadcastJoin(MultiNode *leftNode, MultiNode *rightNode, + Var *partitionColumn, JoinType joinType, + List *applicableJoinClauses) +{ + MultiJoin *joinNode = CitusMakeNode(MultiJoin); + joinNode->joinRuleType = BROADCAST_JOIN; + joinNode->joinType = joinType; + joinNode->joinClauseList = applicableJoinClauses; + + SetLeftChild((MultiBinaryNode *) joinNode, leftNode); + SetRightChild((MultiBinaryNode *) joinNode, rightNode); + + return (MultiNode *) joinNode; +} + + +/* + * ApplyLocalJoin creates a new MultiJoin node that joins the left and the right + * node. The new node uses the local join rule to perform the join. + */ +static MultiNode * +ApplyLocalJoin(MultiNode *leftNode, MultiNode *rightNode, + Var *partitionColumn, JoinType joinType, + List *applicableJoinClauses) +{ + MultiJoin *joinNode = CitusMakeNode(MultiJoin); + joinNode->joinRuleType = LOCAL_PARTITION_JOIN; + joinNode->joinType = joinType; + joinNode->joinClauseList = applicableJoinClauses; + + SetLeftChild((MultiBinaryNode *) joinNode, leftNode); + SetRightChild((MultiBinaryNode *) joinNode, rightNode); + + return (MultiNode *) joinNode; +} + + +/* + * ApplySinglePartitionJoin creates a new MultiJoin node that joins the left and + * right node. The function also adds a MultiPartition node on top of the node + * (left or right) that is not partitioned on the join column. + */ +static MultiNode * +ApplySinglePartitionJoin(MultiNode *leftNode, MultiNode *rightNode, + Var *partitionColumn, JoinType joinType, + List *applicableJoinClauses) +{ + OpExpr *joinClause = NULL; + Var *leftColumn = NULL; + Var *rightColumn = NULL; + List *rightTableIdList = NIL; + uint32 rightTableId = 0; + uint32 partitionTableId = partitionColumn->varno; + + /* create all operator structures up front */ + MultiJoin *joinNode = CitusMakeNode(MultiJoin); + MultiCollect *collectNode = CitusMakeNode(MultiCollect); + MultiPartition *partitionNode = CitusMakeNode(MultiPartition); + + /* + * We first find the appropriate join clause. Then, we compare the partition + * column against the join clause's columns. If one of the columns matches, + * we introduce a (re-)partition operator for the other column. + */ + joinClause = SinglePartitionJoinClause(partitionColumn, applicableJoinClauses); + Assert(joinClause != NULL); + + leftColumn = LeftColumn(joinClause); + rightColumn = RightColumn(joinClause); + + if (equal(partitionColumn, leftColumn)) + { + partitionNode->partitionColumn = rightColumn; + partitionNode->splitPointTableId = partitionTableId; + } + else if (equal(partitionColumn, rightColumn)) + { + partitionNode->partitionColumn = leftColumn; + partitionNode->splitPointTableId = partitionTableId; + } + + /* determine the node the partition operator goes on top of */ + rightTableIdList = OutputTableIdList(rightNode); + rightTableId = (uint32) linitial_int(rightTableIdList); + Assert(list_length(rightTableIdList) == 1); + + /* + * If the right child node is partitioned on the partition key column, we + * add the partition operator on the left child node; and vice versa. Then, + * we add a collect operator on top of the partition operator, and always + * make sure that we have at most one relation on the right-hand side. + */ + if (partitionTableId == rightTableId) + { + SetChild((MultiUnaryNode *) partitionNode, leftNode); + SetChild((MultiUnaryNode *) collectNode, (MultiNode *) partitionNode); + + SetLeftChild((MultiBinaryNode *) joinNode, (MultiNode *) collectNode); + SetRightChild((MultiBinaryNode *) joinNode, rightNode); + } + else + { + SetChild((MultiUnaryNode *) partitionNode, rightNode); + SetChild((MultiUnaryNode *) collectNode, (MultiNode *) partitionNode); + + SetLeftChild((MultiBinaryNode *) joinNode, leftNode); + SetRightChild((MultiBinaryNode *) joinNode, (MultiNode *) collectNode); + } + + /* finally set join operator fields */ + joinNode->joinRuleType = SINGLE_PARTITION_JOIN; + joinNode->joinType = joinType; + joinNode->joinClauseList = applicableJoinClauses; + + return (MultiNode *) joinNode; +} + + +/* + * ApplyDualPartitionJoin creates a new MultiJoin node that joins the left and + * right node. The function also adds two MultiPartition operators on top of + * both nodes to repartition these nodes' data on the join clause columns. + */ +static MultiNode * +ApplyDualPartitionJoin(MultiNode *leftNode, MultiNode *rightNode, + Var *partitionColumn, JoinType joinType, + List *applicableJoinClauses) +{ + MultiJoin *joinNode = NULL; + OpExpr *joinClause = NULL; + MultiPartition *leftPartitionNode = NULL; + MultiPartition *rightPartitionNode = NULL; + MultiCollect *leftCollectNode = NULL; + MultiCollect *rightCollectNode = NULL; + Var *leftColumn = NULL; + Var *rightColumn = NULL; + List *rightTableIdList = NIL; + uint32 rightTableId = 0; + + /* find the appropriate join clause */ + joinClause = DualPartitionJoinClause(applicableJoinClauses); + Assert(joinClause != NULL); + + leftColumn = LeftColumn(joinClause); + rightColumn = RightColumn(joinClause); + + rightTableIdList = OutputTableIdList(rightNode); + rightTableId = (uint32) linitial_int(rightTableIdList); + Assert(list_length(rightTableIdList) == 1); + + leftPartitionNode = CitusMakeNode(MultiPartition); + rightPartitionNode = CitusMakeNode(MultiPartition); + + /* find the partition node each join clause column belongs to */ + if (leftColumn->varno == rightTableId) + { + leftPartitionNode->partitionColumn = rightColumn; + rightPartitionNode->partitionColumn = leftColumn; + } + else + { + leftPartitionNode->partitionColumn = leftColumn; + rightPartitionNode->partitionColumn = rightColumn; + } + + /* add partition operators on top of left and right nodes */ + SetChild((MultiUnaryNode *) leftPartitionNode, leftNode); + SetChild((MultiUnaryNode *) rightPartitionNode, rightNode); + + /* add collect operators on top of the two partition operators */ + leftCollectNode = CitusMakeNode(MultiCollect); + rightCollectNode = CitusMakeNode(MultiCollect); + + SetChild((MultiUnaryNode *) leftCollectNode, (MultiNode *) leftPartitionNode); + SetChild((MultiUnaryNode *) rightCollectNode, (MultiNode *) rightPartitionNode); + + /* add join operator on top of the two collect operators */ + joinNode = CitusMakeNode(MultiJoin); + joinNode->joinRuleType = DUAL_PARTITION_JOIN; + joinNode->joinType = joinType; + joinNode->joinClauseList = applicableJoinClauses; + + SetLeftChild((MultiBinaryNode *) joinNode, (MultiNode *) leftCollectNode); + SetRightChild((MultiBinaryNode *) joinNode, (MultiNode *) rightCollectNode); + + return (MultiNode *) joinNode; +} + + +/* Creates a cartesian product node that joins the left and the right node. */ +static MultiNode * +ApplyCartesianProduct(MultiNode *leftNode, MultiNode *rightNode, + Var *partitionColumn, JoinType joinType, + List *applicableJoinClauses) +{ + MultiCartesianProduct *cartesianNode = CitusMakeNode(MultiCartesianProduct); + + SetLeftChild((MultiBinaryNode *) cartesianNode, leftNode); + SetRightChild((MultiBinaryNode *) cartesianNode, rightNode); + + return (MultiNode *) cartesianNode; +} + + +/* + * SubqueryPushdownMultiTree creates logical plan for subquery pushdown logic. + * Note that this logic will be changed in next iterations, so we decoupled it + * from other parts of code although it causes some code duplication. + */ +static MultiNode * +SubqueryPushdownMultiPlanTree(Query *queryTree, List *subqueryEntryList) +{ + List *targetEntryList = queryTree->targetList; + List *whereClauseList = NIL; + List *whereClauseColumnList = NIL; + List *targetListColumnList = NIL; + List *columnList = NIL; + ListCell *columnCell = NULL; + MultiCollect *subqueryCollectNode = CitusMakeNode(MultiCollect); + MultiTable *subqueryNode = NULL; + MultiSelect *selectNode = NULL; + MultiProject *projectNode = NULL; + MultiExtendedOp *extendedOpNode = NULL; + MultiNode *currentTopNode = NULL; + RangeTblEntry *subqueryRangeTableEntry = NULL; + + /* verify we can perform distributed planning on this query */ + ErrorIfQueryNotSupported(queryTree); + ErrorIfSubqueryJoin(queryTree); + + /* extract where clause qualifiers and verify we can plan for them */ + whereClauseList = WhereClauseList(queryTree->jointree); + ValidateClauseList(whereClauseList); + + /* + * We disregard pulled subqueries. This changes order of range table list. + * We do not allow subquery joins, so we will have only one range table + * entry in range table list after dropping pulled subquery. For this reason, + * here we are updating columns in the most outer query for where clause + * list and target list accordingly. + */ + Assert(list_length(subqueryEntryList) == 1); + + whereClauseColumnList = pull_var_clause_default((Node *) whereClauseList); + targetListColumnList = pull_var_clause_default((Node *) targetEntryList); + + columnList = list_concat(whereClauseColumnList, targetListColumnList); + foreach(columnCell, columnList) + { + Var *column = (Var *) lfirst(columnCell); + column->varno = 1; + } + + /* create multi node for the subquery */ + subqueryRangeTableEntry = (RangeTblEntry *) linitial(subqueryEntryList); + subqueryNode = MultiSubqueryPushdownTable(subqueryRangeTableEntry); + + SetChild((MultiUnaryNode *) subqueryCollectNode, (MultiNode *) subqueryNode); + currentTopNode = (MultiNode *) subqueryCollectNode; + + /* build select node if the query has selection criteria */ + selectNode = MultiSelectNode(whereClauseList); + if (selectNode != NULL) + { + SetChild((MultiUnaryNode *) selectNode, currentTopNode); + currentTopNode = (MultiNode *) selectNode; + } + + /* build project node for the columns to project */ + projectNode = MultiProjectNode(targetEntryList); + SetChild((MultiUnaryNode *) projectNode, currentTopNode); + currentTopNode = (MultiNode *) projectNode; + + /* + * We build the extended operator node to capture aggregate functions, group + * clauses, sort clauses, limit/offset clauses, and expressions. We need to + * distinguish between aggregates and expressions; and we address this later + * in the logical optimizer. + */ + extendedOpNode = MultiExtendedOpNode(queryTree); + SetChild((MultiUnaryNode *) extendedOpNode, currentTopNode); + currentTopNode = (MultiNode *) extendedOpNode; + + return currentTopNode; +} + + +/* + * ErrorIfSubqueryJoin errors out if the given query is a join query. Note that + * this function will not be required once we implement subquery joins. + */ +static void +ErrorIfSubqueryJoin(Query *queryTree) +{ + List *joinTreeTableIndexList = NIL; + uint32 joiningRangeTableCount = 0; + + /* + * Extract all range table indexes from the join tree. Note that sub-queries + * that get pulled up by PostgreSQL don't appear in this join tree. + */ + ExtractRangeTableIndexWalker((Node*) queryTree->jointree, &joinTreeTableIndexList); + joiningRangeTableCount = list_length(joinTreeTableIndexList); + + if (joiningRangeTableCount > 1) + { + ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("cannot perform distributed planning on this query"), + errdetail("Join in subqueries is not supported yet"))); + } +} + + +/* + * MultiSubqueryPushdownTable creates a MultiTable from the given subquery range + * table entry and returns it. Note that this sets subquery field of MultiTable + * to subquery of the given range table entry. + */ +static MultiTable * +MultiSubqueryPushdownTable(RangeTblEntry *subqueryRangeTableEntry) +{ + Query *subquery = subqueryRangeTableEntry->subquery; + + MultiTable *subqueryTableNode = CitusMakeNode(MultiTable); + subqueryTableNode->subquery = subquery; + subqueryTableNode->relationId = HEAP_ANALYTICS_SUBQUERY_RELATION_ID; + subqueryTableNode->rangeTableId = SUBQUERY_RANGE_TABLE_ID; + subqueryTableNode->partitionColumn = NULL; + subqueryTableNode->alias = subqueryRangeTableEntry->alias; + subqueryTableNode->referenceNames = subqueryRangeTableEntry->eref; + + return subqueryTableNode; +} diff --git a/src/backend/distributed/planner/multi_master_planner.c b/src/backend/distributed/planner/multi_master_planner.c new file mode 100644 index 000000000..88fda53a3 --- /dev/null +++ b/src/backend/distributed/planner/multi_master_planner.c @@ -0,0 +1,378 @@ +/*------------------------------------------------------------------------- + * + * multi_master_planner.c + * Routines for building create table and select into table statements on the + * master node. + * + * Copyright (c) 2012, Citus Data, Inc. + * + * $Id$ + * + *------------------------------------------------------------------------- + */ + +#include "postgres.h" + +#include "distributed/multi_master_planner.h" +#include "distributed/multi_physical_planner.h" +#include "distributed/multi_server_executor.h" +#include "distributed/worker_protocol.h" +#include "nodes/makefuncs.h" +#include "nodes/nodeFuncs.h" +#include "optimizer/clauses.h" +#include "optimizer/planmain.h" +#include "optimizer/tlist.h" +#include "optimizer/var.h" +#include "utils/builtins.h" +#include "utils/memutils.h" +#include "utils/rel.h" +#include "utils/syscache.h" + + +/* + * MasterTargetList uses the given worker target list's expressions, and creates + * a target target list for the master node. This master target list keeps the + * temporary table's columns on the master node. + */ +static List * +MasterTargetList(List *workerTargetList) +{ + List *masterTargetList = NIL; + const Index tableId = 1; + AttrNumber columnId = 1; + + ListCell *workerTargetCell = NULL; + foreach(workerTargetCell, workerTargetList) + { + TargetEntry *workerTargetEntry = (TargetEntry *) lfirst(workerTargetCell); + TargetEntry *masterTargetEntry = copyObject(workerTargetEntry); + + Var *masterColumn = makeVarFromTargetEntry(tableId, workerTargetEntry); + masterColumn->varattno = columnId; + masterColumn->varoattno = columnId; + columnId++; + + /* + * The master target entry has two pieces to it. The first piece is the + * target entry's expression, which we set to the newly created column. + * The second piece is sort and group clauses that we implicitly copy + * from the worker target entry. Note that any changes to worker target + * entry's sort and group clauses will *break* us here. + */ + masterTargetEntry->expr = (Expr *) masterColumn; + masterTargetList = lappend(masterTargetList, masterTargetEntry); + } + + return masterTargetList; +} + + +/* + * BuildCreateStatement builds the executable create statement for creating a + * temporary table on the master; and then returns this create statement. This + * function obtains the needed column type information from the target list. + */ +static CreateStmt * +BuildCreateStatement(char *masterTableName, List *masterTargetList, + List *masterColumnNameList) +{ + CreateStmt *createStatement = NULL; + RangeVar *relation = NULL; + char *relationName = NULL; + List *columnTypeList = NIL; + List *columnDefinitionList = NIL; + ListCell *masterTargetCell = NULL; + + /* build rangevar object for temporary table */ + relationName = masterTableName; + relation = makeRangeVar(NULL, relationName, -1); + relation->relpersistence = RELPERSISTENCE_TEMP; + + /* build the list of column types as cstrings */ + foreach(masterTargetCell, masterTargetList) + { + TargetEntry *targetEntry = (TargetEntry *) lfirst(masterTargetCell); + Var *column = (Var *) targetEntry->expr; + Oid columnTypeId = exprType((Node *) column); + int32 columnTypeMod = exprTypmod((Node *) column); + + char *columnTypeName = format_type_with_typemod(columnTypeId, columnTypeMod); + columnTypeList = lappend(columnTypeList, columnTypeName); + } + + /* build the column definition list */ + columnDefinitionList = ColumnDefinitionList(masterColumnNameList, columnTypeList); + + /* build the create statement */ + createStatement = CreateStatement(relation, columnDefinitionList); + + return createStatement; +} + + +/* + * BuildAggregatePlan creates and returns an aggregate plan. This aggregate plan + * builds aggreation and grouping operators (if any) that are to be executed on + * the master node. + */ +static Agg * +BuildAggregatePlan(Query *masterQuery, Plan *subPlan) +{ + Agg *aggregatePlan = NULL; + AggStrategy aggregateStrategy = AGG_PLAIN; + AggClauseCosts aggregateCosts; + AttrNumber *groupColumnIdArray = NULL; + List *aggregateTargetList = NIL; + List *groupColumnList = NIL; + List *columnList = NIL; + ListCell *columnCell = NULL; + Oid *groupColumnOpArray = NULL; + uint32 groupColumnCount = 0; + const long rowEstimate = 10; + + /* assert that we need to build an aggregate plan */ + Assert(masterQuery->hasAggs || masterQuery->groupClause); + + aggregateTargetList = masterQuery->targetList; + count_agg_clauses(NULL, (Node *) aggregateTargetList, &aggregateCosts); + + /* + * For upper level plans above the sequential scan, the planner expects the + * table id (varno) to be set to OUTER_VAR. + */ + columnList = pull_var_clause_default((Node *) aggregateTargetList); + foreach(columnCell, columnList) + { + Var *column = (Var *) lfirst(columnCell); + column->varno = OUTER_VAR; + } + + groupColumnList = masterQuery->groupClause; + groupColumnCount = list_length(groupColumnList); + + /* if we have grouping, then initialize appropriate information */ + if (groupColumnCount > 0) + { + if (!grouping_is_hashable(groupColumnList)) + { + ereport(ERROR, (errmsg("grouped column list cannot be hashed"))); + } + + /* switch to hashed aggregate strategy to allow grouping */ + aggregateStrategy = AGG_HASHED; + + /* get column indexes that are being grouped */ + groupColumnIdArray = extract_grouping_cols(groupColumnList, subPlan->targetlist); + groupColumnOpArray = extract_grouping_ops(groupColumnList); + } + + /* finally create the plan */ +#if (PG_VERSION_NUM >= 90500) + aggregatePlan = make_agg(NULL, aggregateTargetList, NIL, aggregateStrategy, + &aggregateCosts, groupColumnCount, groupColumnIdArray, + groupColumnOpArray, NIL, rowEstimate, subPlan); +#else + aggregatePlan = make_agg(NULL, aggregateTargetList, NIL, aggregateStrategy, + &aggregateCosts, groupColumnCount, groupColumnIdArray, + groupColumnOpArray, rowEstimate, subPlan); +#endif + + return aggregatePlan; +} + + +/* + * BuildSelectStatement builds the final select statement to run on the master + * node, before returning results to the user. The function first builds a scan + * statement for all results fetched to the master, and layers aggregation, sort + * and limit plans on top of the scan statement if necessary. + */ +static PlannedStmt * +BuildSelectStatement(Query *masterQuery, char *masterTableName, + List *masterTargetList) +{ + PlannedStmt *selectStatement = NULL; + RangeTblEntry *rangeTableEntry = NULL; + RangeTblEntry *queryRangeTableEntry = NULL; + SeqScan *sequentialScan = NULL; + Agg *aggregationPlan = NULL; + Plan *topLevelPlan = NULL; + + /* (1) make PlannedStmt and set basic information */ + selectStatement = makeNode(PlannedStmt); + selectStatement->canSetTag = true; + selectStatement->relationOids = NIL; /* to be filled in exec_Start */ + selectStatement->commandType = CMD_SELECT; + + /* prepare the range table entry for our temporary table */ + Assert(list_length(masterQuery->rtable) == 1); + queryRangeTableEntry = (RangeTblEntry *) linitial(masterQuery->rtable); + + rangeTableEntry = copyObject(queryRangeTableEntry); + rangeTableEntry->rtekind = RTE_RELATION; + rangeTableEntry->eref = makeAlias(masterTableName, NIL); + rangeTableEntry->relid = 0; /* to be filled in exec_Start */ + rangeTableEntry->inh = false; + rangeTableEntry->inFromCl = true; + + /* set the single element range table list */ + selectStatement->rtable = list_make1(rangeTableEntry); + + /* (2) build and initialize sequential scan node */ + sequentialScan = makeNode(SeqScan); + sequentialScan->scanrelid = 1; /* always one */ + + /* (3) add an aggregation plan if needed */ + if (masterQuery->hasAggs || masterQuery->groupClause) + { + sequentialScan->plan.targetlist = masterTargetList; + + aggregationPlan = BuildAggregatePlan(masterQuery, (Plan *) sequentialScan); + topLevelPlan = (Plan *) aggregationPlan; + } + else + { + /* otherwise set the final projections on the scan plan directly */ + sequentialScan->plan.targetlist = masterQuery->targetList; + topLevelPlan = (Plan *) sequentialScan; + } + + /* (4) add a sorting plan if needed */ + if (masterQuery->sortClause) + { + List *sortClauseList = masterQuery->sortClause; + Sort *sortPlan = make_sort_from_sortclauses(NULL, sortClauseList, topLevelPlan); + topLevelPlan = (Plan *) sortPlan; + } + + /* (5) add a limit plan if needed */ + if (masterQuery->limitCount) + { + Node *limitCount = masterQuery->limitCount; + Node *limitOffset = masterQuery->limitOffset; + int64 offsetEstimate = 0; + int64 countEstimate = 0; + + Limit *limitPlan = make_limit(topLevelPlan, limitOffset, limitCount, + offsetEstimate, countEstimate); + topLevelPlan = (Plan *) limitPlan; + } + + /* (6) finally set our top level plan in the plan tree */ + selectStatement->planTree = topLevelPlan; + + return selectStatement; +} + + +/* + * ValueToStringList walks over the given list of string value types, converts + * value types to cstrings, and adds these cstrings into a new list. + */ +static List * +ValueToStringList(List *valueList) +{ + List *stringList = NIL; + ListCell *valueCell = NULL; + + foreach(valueCell, valueList) + { + Value *value = (Value *) lfirst(valueCell); + char *stringValue = strVal(value); + + stringList = lappend(stringList, stringValue); + } + + return stringList; +} + + +/* + * MasterNodeCreateStatement takes in a multi plan, and constructs a statement + * to create a temporary table on the master node for final result + * aggregation. + */ +CreateStmt * +MasterNodeCreateStatement(MultiPlan *multiPlan) +{ + Query *masterQuery = multiPlan->masterQuery; + Job *workerJob = multiPlan->workerJob; + List *workerTargetList = workerJob->jobQuery->targetList; + List *rangeTableList = masterQuery->rtable; + char *tableName = multiPlan->masterTableName; + CreateStmt *createStatement = NULL; + + RangeTblEntry *rangeTableEntry = (RangeTblEntry *) linitial(rangeTableList); + List *columnNameValueList = rangeTableEntry->eref->colnames; + List *columnNameList = ValueToStringList(columnNameValueList); + List *targetList = MasterTargetList(workerTargetList); + + createStatement = BuildCreateStatement(tableName, targetList, columnNameList); + + return createStatement; +} + + +/* + * MasterNodeSelectPlan takes in a distributed plan, finds the master node query + * structure in that plan, and builds the final select plan to execute on the + * master node. Note that this select plan is executed after result files are + * retrieved from worker nodes and are merged into a temporary table. + */ +PlannedStmt * +MasterNodeSelectPlan(MultiPlan *multiPlan) +{ + Query *masterQuery = multiPlan->masterQuery; + char *tableName = multiPlan->masterTableName; + PlannedStmt *masterSelectPlan = NULL; + + Job *workerJob = multiPlan->workerJob; + List *workerTargetList = workerJob->jobQuery->targetList; + List *masterTargetList = MasterTargetList(workerTargetList); + + masterSelectPlan = BuildSelectStatement(masterQuery, tableName, masterTargetList); + + return masterSelectPlan; +} + + +/* + * MasterNodeCopyStatementList takes in a multi plan, and constructs + * statements that copy over worker task results to a temporary table on the + * master node. + */ +List * +MasterNodeCopyStatementList(MultiPlan *multiPlan) +{ + Job *workerJob = multiPlan->workerJob; + List *workerTaskList = workerJob->taskList; + char *tableName = multiPlan->masterTableName; + List *copyStatementList = NIL; + + ListCell *workerTaskCell = NULL; + foreach(workerTaskCell, workerTaskList) + { + Task *workerTask = (Task *) lfirst(workerTaskCell); + StringInfo jobDirectoryName = JobDirectoryName(workerTask->jobId); + StringInfo taskFilename = TaskFilename(jobDirectoryName, workerTask->taskId); + + RangeVar *relation = makeRangeVar(NULL, tableName, -1); + CopyStmt *copyStatement = makeNode(CopyStmt); + copyStatement->relation = relation; + copyStatement->is_from = true; + copyStatement->filename = taskFilename->data; + if (BinaryMasterCopyFormat) + { + DefElem *copyOption = makeDefElem("format", (Node *) makeString("binary")); + copyStatement->options = list_make1(copyOption); + } + else + { + copyStatement->options = NIL; + } + + copyStatementList = lappend(copyStatementList, copyStatement); + } + + return copyStatementList; +} diff --git a/src/backend/distributed/planner/multi_physical_planner.c b/src/backend/distributed/planner/multi_physical_planner.c new file mode 100644 index 000000000..1b4172d3a --- /dev/null +++ b/src/backend/distributed/planner/multi_physical_planner.c @@ -0,0 +1,5481 @@ +/*------------------------------------------------------------------------- + * + * multi_physical_planner.c + * Routines for creating physical plans from given multi-relational algebra + * trees. + * + * Copyright (c) 2012, Citus Data, Inc. + * + * $Id$ + * + *------------------------------------------------------------------------- + */ + +#include "postgres.h" + +#include + +#include "access/genam.h" +#include "access/hash.h" +#include "access/heapam.h" +#include "access/nbtree.h" +#include "access/skey.h" +#include "catalog/pg_am.h" +#include "catalog/pg_operator.h" +#include "catalog/pg_type.h" +#include "commands/defrem.h" +#include "commands/sequence.h" +#include "distributed/listutils.h" +#include "distributed/citus_nodefuncs.h" +#include "distributed/citus_nodes.h" +#include "distributed/citus_ruleutils.h" +#include "distributed/master_metadata_utility.h" +#include "distributed/master_protocol.h" +#include "distributed/metadata_cache.h" +#include "distributed/multi_logical_optimizer.h" +#include "distributed/multi_logical_planner.h" +#include "distributed/multi_physical_planner.h" +#include "distributed/pg_dist_partition.h" +#include "distributed/pg_dist_shard.h" +#include "distributed/task_tracker.h" +#include "distributed/worker_manager.h" +#include "distributed/worker_protocol.h" +#include "nodes/makefuncs.h" +#include "nodes/nodeFuncs.h" +#include "optimizer/clauses.h" +#include "optimizer/predtest.h" +#include "optimizer/restrictinfo.h" +#include "optimizer/var.h" +#include "parser/parse_relation.h" +#include "parser/parsetree.h" +#include "utils/builtins.h" +#include "utils/catcache.h" +#include "utils/fmgroids.h" +#include "utils/guc.h" +#include "utils/lsyscache.h" +#include "utils/memutils.h" +#include "utils/rel.h" +#include "utils/typcache.h" + + +/* Policy to use when assigning tasks to worker nodes */ +int TaskAssignmentPolicy = TASK_ASSIGNMENT_GREEDY; + + +/* + * OperatorCache is used for caching operator identifiers for given typeId, + * accessMethodId and strategyNumber. It is initialized to empty list as + * there are no items in the cache. + */ +static List *OperatorCache = NIL; + + +/* Local functions forward declarations for job creation */ +static Job * BuildJobTree(MultiTreeRoot *multiTree); +static MultiNode * LeftMostNode(MultiTreeRoot *multiTree); +static Oid RangePartitionJoinBaseRelationId(MultiJoin *joinNode); +static MultiTable * FindTableNode(MultiNode *multiNode, int rangeTableId); +static Query * BuildJobQuery(MultiNode *multiNode, List *dependedJobList); +static Query * BuildReduceQuery(MultiExtendedOp *extendedOpNode, List *dependedJobList); +static List * BaseRangeTableList(MultiNode *multiNode); +static List * QueryTargetList(MultiNode *multiNode); +static List * TargetEntryList(List *expressionList); +static List * QueryGroupClauseList(MultiNode *multiNode); +static List * QuerySelectClauseList(MultiNode *multiNode); +static List * QueryJoinClauseList(MultiNode *multiNode); +static List * QueryFromList(List *rangeTableList); +static Node * QueryJoinTree(MultiNode *multiNode, List *dependedJobList, + List **rangeTableList); +static RangeTblEntry * JoinRangeTableEntry(JoinExpr *joinExpr, List *dependedJobList, + List *rangeTableList); +static int ExtractRangeTableId(Node *node); +static void ExtractColumns(RangeTblEntry *rangeTableEntry, int rangeTableId, + List *dependedJobList, List **columnNames, List **columnVars); +static RangeTblEntry * DerivedRangeTableEntry(MultiNode *multiNode, List *columnNames, + List *tableIdList); +static List * DerivedColumnNameList(uint32 columnCount, uint64 generatingJobId); +static Query * BuildSubqueryJobQuery(MultiNode *multiNode); +static void UpdateColumnAttributes(Var *column, List *rangeTableList, + List *dependedJobList); +static Index NewTableId(Index originalTableId, List *rangeTableList); +static AttrNumber NewColumnId(Index originalTableId, AttrNumber originalColumnId, + RangeTblEntry *newRangeTableEntry, List *dependedJobList); +static Job * JobForRangeTable(List *jobList, RangeTblEntry *rangeTableEntry); +static Job * JobForTableIdList(List *jobList, List *searchedTableIdList); +static List * ChildNodeList(MultiNode *multiNode); +static uint64 UniqueJobId(void); +static Job * BuildJob(Query *jobQuery, List *dependedJobList); +static MapMergeJob * BuildMapMergeJob(Query *jobQuery, List *dependedJobList, + Var *partitionKey, PartitionType partitionType, + Oid baseRelationId, + BoundaryNodeJobType boundaryNodeJobType); +static uint32 HashPartitionCount(void); +static int CompareShardIntervals(const void *leftElement, const void *rightElement, + FmgrInfo *typeCompareFunction); +static ArrayType * SplitPointObject(ShardInterval **shardIntervalArray, + uint32 shardIntervalCount); + +/* Local functions forward declarations for task list creation */ +static Job * BuildJobTreeTaskList(Job *jobTree); +static List * SubquerySqlTaskList(Job *job); +static List * SqlTaskList(Job *job); +static bool DependsOnHashPartitionJob(Job *job); +static uint32 AnchorRangeTableId(List *rangeTableList); +static List * BaseRangeTableIdList(List *rangeTableList); +static List * AnchorRangeTableIdList(List *rangeTableList, List *baseRangeTableIdList); +static void AdjustColumnOldAttributes(List *expressionList); +static List * RangeTableFragmentsList(List *rangeTableList, List *whereClauseList, + List *dependedJobList); +static OperatorCacheEntry * LookupOperatorByType(Oid typeId, Oid accessMethodId, + int16 strategyNumber); +static Oid GetOperatorByType(Oid typeId, Oid accessMethodId, int16 strategyNumber); +static Node * HashableClauseMutator(Node *originalNode, Var *partitionColumn); +static bool OpExpressionContainsColumn(OpExpr *operatorExpression, Var *partitionColumn); +static Var * MakeInt4Column(void); +static Const * MakeInt4Constant(Datum constantValue); +static OpExpr * MakeHashedOperatorExpression(OpExpr *operatorExpression); +static OpExpr * MakeOpExpressionWithZeroConst(void); +static List * BuildRestrictInfoList(List *qualList); +static List * FragmentCombinationList(List *rangeTableFragmentsList, Query *jobQuery, + List *dependedJobList); +static JoinSequenceNode * JoinSequenceArray(List * rangeTableFragmentsList, + Query *jobQuery, List *dependedJobList); +static bool PartitionedOnColumn(Var *column, List *rangeTableList, List *dependedJobList); +static void CheckJoinBetweenColumns(OpExpr *joinClause); +static List * FindRangeTableFragmentsList(List *rangeTableFragmentsList, int taskId); +static bool JoinPrunable(RangeTableFragment *leftFragment, + RangeTableFragment *rightFragment); +static ShardInterval * FragmentInterval(RangeTableFragment *fragment); +static StringInfo FragmentIntervalString(ShardInterval *fragmentInterval); +static List * UniqueFragmentList(List *fragmentList); +static List * DataFetchTaskList(uint64 jobId, uint32 taskIdIndex, List *fragmentList); +static StringInfo NodeNameArrayString(List *workerNodeList); +static StringInfo NodePortArrayString(List *workerNodeList); +static StringInfo DatumArrayString(Datum *datumArray, uint32 datumCount, Oid datumTypeId); +static Task * CreateBasicTask(uint64 jobId, uint32 taskId, TaskType taskType, + char *queryString); +static void UpdateRangeTableAlias(List *rangeTableList, List *fragmentList); +static Alias * FragmentAlias(RangeTblEntry *rangeTableEntry, RangeTableFragment *fragment); +static uint64 AnchorShardId(List *fragmentList, uint32 anchorRangeTableId); +static List * PruneSqlTaskDependencies(List *sqlTaskList); +static List * AssignTaskList(List *sqlTaskList); +static bool HasMergeTaskDependencies(List *sqlTaskList); +static List * AssignAnchorShardTaskList(List *taskList); +static List * GreedyAssignTaskList(List *taskList); +static Task * GreedyAssignTask(WorkerNode *workerNode, List *taskList, + List *activeShardPlacementLists); +static List * RoundRobinAssignTaskList(List *taskList); +static List * RoundRobinReorder(Task *task, List *placementList); +static List * ReorderAndAssignTaskList(List *taskList, + List * (*reorderFunction) (Task *, List *)); +static int CompareTasksByShardId(const void *leftElement, const void *rightElement); +static List * ActiveShardPlacementLists(List *taskList); +static List * ActivePlacementList(List *placementList); +static List * LeftRotateList(List *list, uint32 rotateCount); +static List * FindDependedMergeTaskList(Task *sqlTask); +static List * AssignDualHashTaskList(List *taskList); +static int CompareTasksByTaskId(const void *leftElement, const void *rightElement); +static void AssignDataFetchDependencies(List *taskList); +static uint32 TaskListHighestTaskId(List *taskList); +static List * MapTaskList(MapMergeJob *mapMergeJob, List *filterTaskList); +static char * ColumnName(Var *column, List *rangeTableList); +static StringInfo SplitPointArrayString(ArrayType *splitPointObject, + Oid columnType, int32 columnTypeMod); +static List * MergeTaskList(MapMergeJob *mapMergeJob, List *mapTaskList, + uint32 taskIdIndex); +static StringInfo ColumnNameArrayString(uint32 columnCount, uint64 generatingJobId); +static StringInfo ColumnTypeArrayString(List *targetEntryList); +static StringInfo MergeTableQueryString(uint32 taskIdIndex, List *targetEntryList); +static StringInfo IntermediateTableQueryString(uint64 jobId, uint32 taskIdIndex, + Query *reduceQuery); +static uint32 FinalTargetEntryCount(List *targetEntryList); + + +/* + * MultiPhysicalPlanCreate is the entry point for physical plan generation. The + * function builds the physical plan; this plan includes the list of tasks to be + * executed on worker nodes, and the final query to run on the master node. + */ +MultiPlan * +MultiPhysicalPlanCreate(MultiTreeRoot *multiTree) +{ + MultiPlan *multiPlan = NULL; + StringInfo jobSchemaName = NULL; + Job *workerJob = NULL; + uint64 workerJobId = 0; + Query *masterQuery = NULL; + List *masterDependedJobList = NIL; + + /* build the worker job tree and check that we only one job in the tree */ + workerJob = BuildJobTree(multiTree); + + /* create the tree of executable tasks for the worker job */ + workerJob = BuildJobTreeTaskList(workerJob); + workerJobId = workerJob->jobId; + + /* get job schema name */ + jobSchemaName = JobSchemaName(workerJobId); + + /* build the final merge query to execute on the master */ + masterDependedJobList = list_make1(workerJob); + masterQuery = BuildJobQuery((MultiNode *) multiTree, masterDependedJobList); + + multiPlan = CitusMakeNode(MultiPlan); + multiPlan->workerJob = workerJob; + multiPlan->masterQuery = masterQuery; + multiPlan->masterTableName = jobSchemaName->data; + + return multiPlan; +} + + +/* + * BuildJobTree builds the physical job tree from the given logical plan tree. + * The function walks over the logical plan from the bottom up, finds boundaries + * for jobs, and creates the query structure for each job. The function also + * sets dependencies between jobs, and then returns the top level worker job. + */ +static Job * +BuildJobTree(MultiTreeRoot *multiTree) +{ + /* start building the tree from the deepest left node */ + MultiNode *leftMostNode = LeftMostNode(multiTree); + MultiNode *currentNode = leftMostNode; + MultiNode *parentNode = ParentNode(currentNode); + List *loopDependedJobList = NIL; + Job *topLevelJob = NULL; + + while (parentNode != NULL) + { + CitusNodeTag currentNodeType = CitusNodeTag(currentNode); + CitusNodeTag parentNodeType = CitusNodeTag(parentNode); + BoundaryNodeJobType boundaryNodeJobType = JOB_INVALID_FIRST; + + /* we first check if this node forms the boundary for a remote job */ + if (currentNodeType == T_MultiJoin) + { + MultiJoin *joinNode = (MultiJoin *) currentNode; + if (joinNode->joinRuleType == SINGLE_PARTITION_JOIN || + joinNode->joinRuleType == DUAL_PARTITION_JOIN) + { + boundaryNodeJobType = JOIN_MAP_MERGE_JOB; + } + } + else if (currentNodeType == T_MultiPartition && + parentNodeType == T_MultiExtendedOp) + { + boundaryNodeJobType = SUBQUERY_MAP_MERGE_JOB; + } + else if (currentNodeType == T_MultiCollect && + parentNodeType != T_MultiPartition) + { + boundaryNodeJobType = TOP_LEVEL_WORKER_JOB; + } + + /* + * If this node is at the boundary for a repartition or top level worker + * job, we build the corresponding job(s) and set their dependencies. + */ + if (boundaryNodeJobType == JOIN_MAP_MERGE_JOB) + { + MultiJoin *joinNode = (MultiJoin *) currentNode; + MultiNode *leftChildNode = joinNode->binaryNode.leftChildNode; + MultiNode *rightChildNode = joinNode->binaryNode.rightChildNode; + + PartitionType partitionType = PARTITION_INVALID_FIRST; + Oid baseRelationId = InvalidOid; + + if (joinNode->joinRuleType == SINGLE_PARTITION_JOIN) + { + partitionType = RANGE_PARTITION_TYPE; + baseRelationId = RangePartitionJoinBaseRelationId(joinNode); + } + else if (joinNode->joinRuleType == DUAL_PARTITION_JOIN) + { + partitionType = HASH_PARTITION_TYPE; + } + + if (CitusIsA(leftChildNode, MultiPartition)) + { + MultiPartition *partitionNode = (MultiPartition *) leftChildNode; + MultiNode *queryNode = GrandChildNode((MultiUnaryNode *) partitionNode); + Var *partitionKey = partitionNode->partitionColumn; + + /* build query and partition job */ + List *dependedJobList = list_copy(loopDependedJobList); + Query *jobQuery = BuildJobQuery(queryNode, dependedJobList); + + MapMergeJob *mapMergeJob = BuildMapMergeJob(jobQuery, dependedJobList, + partitionKey, partitionType, + baseRelationId, + JOIN_MAP_MERGE_JOB); + /* reset depended job list */ + loopDependedJobList = NIL; + loopDependedJobList = list_make1(mapMergeJob); + } + + if (CitusIsA(rightChildNode, MultiPartition)) + { + MultiPartition *partitionNode = (MultiPartition *) rightChildNode; + MultiNode *queryNode = GrandChildNode((MultiUnaryNode *) partitionNode); + Var *partitionKey = partitionNode->partitionColumn; + + /* + * The right query and right partition job do not depend on any + * jobs since our logical plan tree is left deep. + */ + Query *jobQuery = BuildJobQuery(queryNode, NIL); + MapMergeJob *mapMergeJob = BuildMapMergeJob(jobQuery, NIL, + partitionKey, partitionType, + baseRelationId, + JOIN_MAP_MERGE_JOB); + + /* append to the depended job list for on-going dependencies */ + loopDependedJobList = lappend(loopDependedJobList, mapMergeJob); + } + } + else if (boundaryNodeJobType == SUBQUERY_MAP_MERGE_JOB) + { + MultiPartition *partitionNode = (MultiPartition *) currentNode; + MultiNode *queryNode = GrandChildNode((MultiUnaryNode *) partitionNode); + Var *partitionKey = partitionNode->partitionColumn; + + /* build query and partition job */ + List *dependedJobList = list_copy(loopDependedJobList); + Query *jobQuery = BuildJobQuery(queryNode, dependedJobList); + + MapMergeJob *mapMergeJob = BuildMapMergeJob(jobQuery, dependedJobList, + partitionKey, HASH_PARTITION_TYPE, + InvalidOid, + SUBQUERY_MAP_MERGE_JOB); + + Query *reduceQuery = BuildReduceQuery((MultiExtendedOp *) parentNode, + list_make1(mapMergeJob)); + mapMergeJob->reduceQuery = reduceQuery; + + /* reset depended job list */ + loopDependedJobList = NIL; + loopDependedJobList = list_make1(mapMergeJob); + } + else if (boundaryNodeJobType == TOP_LEVEL_WORKER_JOB) + { + MultiNode *childNode = ChildNode((MultiUnaryNode *) currentNode); + List *dependedJobList = list_copy(loopDependedJobList); + bool subqueryPushdown = false; + + List *subqueryMultiTableList = SubqueryMultiTableList(childNode); + int subqueryCount = list_length(subqueryMultiTableList); + + if (subqueryCount > 0) + { + subqueryPushdown = true; + } + + /* + * Build top level query. If subquery pushdown is set, we use + * sligthly different version of BuildJobQuery(). They are similar + * but we don't need some parts of BuildJobQuery() for subquery + * pushdown such as updating column attributes etc. + */ + if (subqueryPushdown) + { + Query *topLevelQuery = BuildSubqueryJobQuery(childNode); + + topLevelJob = BuildJob(topLevelQuery, dependedJobList); + topLevelJob->subqueryPushdown = true; + } + else + { + Query *topLevelQuery = BuildJobQuery(childNode, dependedJobList); + + topLevelJob = BuildJob(topLevelQuery, dependedJobList); + } + } + + /* walk up the tree */ + currentNode = parentNode; + parentNode = ParentNode(currentNode); + } + + return topLevelJob; +} + + +/* + * LeftMostNode finds the deepest left node in the left-deep logical plan tree. + * We build the physical plan by traversing the logical plan from the bottom up; + * and this function helps us find the bottom of the logical tree. + */ +static MultiNode * +LeftMostNode(MultiTreeRoot *multiTree) +{ + MultiNode *currentNode = (MultiNode *) multiTree; + MultiNode *leftChildNode = ChildNode((MultiUnaryNode *) multiTree); + + while (leftChildNode != NULL) + { + currentNode = leftChildNode; + + if (UnaryOperator(currentNode)) + { + leftChildNode = ChildNode((MultiUnaryNode *) currentNode); + } + else if (BinaryOperator(currentNode)) + { + MultiBinaryNode *binaryNode = (MultiBinaryNode *) currentNode; + leftChildNode = binaryNode->leftChildNode; + } + } + + return currentNode; +} + + +/* + * RangePartitionJoinBaseRelationId finds partition node from join node, and + * returns base relation id of this node. Note that this function assumes that + * given join node is range partition join type. + */ +static Oid +RangePartitionJoinBaseRelationId(MultiJoin *joinNode) +{ + MultiPartition *partitionNode = NULL; + MultiTable *baseTable = NULL; + Index baseTableId = 0; + Oid baseRelationId = InvalidOid; + + MultiNode *leftChildNode = joinNode->binaryNode.leftChildNode; + MultiNode *rightChildNode = joinNode->binaryNode.rightChildNode; + + if (CitusIsA(leftChildNode, MultiPartition)) + { + partitionNode = (MultiPartition *) leftChildNode; + } + else if (CitusIsA(rightChildNode, MultiPartition)) + { + partitionNode = (MultiPartition *) rightChildNode; + } + + baseTableId = partitionNode->splitPointTableId; + baseTable = FindTableNode((MultiNode *) joinNode, baseTableId); + baseRelationId = baseTable->relationId; + + return baseRelationId; +} + + +/* + * FindTableNode walks over the given logical plan tree, and returns the table + * node that corresponds to the given range tableId. + */ +static MultiTable * +FindTableNode(MultiNode *multiNode, int rangeTableId) +{ + MultiTable *foundTableNode = NULL; + List *tableNodeList = FindNodesOfType(multiNode, T_MultiTable); + ListCell *tableNodeCell = NULL; + + foreach(tableNodeCell, tableNodeList) + { + MultiTable *tableNode = (MultiTable *) lfirst(tableNodeCell); + if (tableNode->rangeTableId == rangeTableId) + { + foundTableNode = tableNode; + break; + } + } + + Assert(foundTableNode != NULL); + return foundTableNode; +} + + +/* + * BuildJobQuery traverses the given logical plan tree, determines the job that + * corresponds to this part of the tree, and builds the query structure for that + * particular job. The function assumes that jobs, this particular job depends on, + * have already been built, as their output is needed to build the query. + */ +static Query * +BuildJobQuery(MultiNode *multiNode, List *dependedJobList) +{ + Query *jobQuery = NULL; + MultiNode *parentNode = NULL; + bool updateColumnAttributes = false; + List *rangeTableList = NIL; + List *targetList = NIL; + List *extendedOpNodeList = NIL; + List *sortClauseList = NIL; + List *groupClauseList = NIL; + List *selectClauseList = NIL; + List *columnList = NIL; + Node *limitCount = NULL; + Node *limitOffset = NULL; + ListCell *columnCell = NULL; + FromExpr *joinTree = NULL; + Node *joinRoot = NULL; + + /* we start building jobs from below the collect node */ + Assert(!CitusIsA(multiNode, MultiCollect)); + + /* + * First check if we are building a master/worker query. If we are building + * a worker query, we update the column attributes for target entries, select + * and join columns. Because if underlying query includes repartition joins, + * then we create multiple queries from a join. In this case, range table lists + * and column lists are subject to change. + * + * Note that we don't do this for master queries, as column attributes for + * master target entries are already set during the master/worker split. + */ + parentNode = ParentNode(multiNode); + if (parentNode != NULL) + { + updateColumnAttributes = true; + } + + /* + * If we are building this query on a repartitioned subquery job then we + * don't need to update column attributes. + */ + if(dependedJobList != NIL) + { + Job *job = (Job *) linitial(dependedJobList); + if (CitusIsA(job, MapMergeJob)) + { + MapMergeJob *mapMergeJob = (MapMergeJob *) job; + if (mapMergeJob->reduceQuery) + { + updateColumnAttributes = false; + } + } + } + + /* + * If we have an extended operator, then we copy the operator's target list. + * Otherwise, we use the target list based on the MultiProject node at this + * level in the query tree. + */ + extendedOpNodeList = FindNodesOfType(multiNode, T_MultiExtendedOp); + if (extendedOpNodeList != NIL) + { + MultiExtendedOp *extendedOp = (MultiExtendedOp *) linitial(extendedOpNodeList); + targetList = copyObject(extendedOp->targetList); + } + else + { + targetList = QueryTargetList(multiNode); + } + + /* build the join tree and the range table list */ + rangeTableList = BaseRangeTableList(multiNode); + joinRoot = QueryJoinTree(multiNode, dependedJobList, &rangeTableList); + + /* update the column attributes for target entries */ + if (updateColumnAttributes) + { + ListCell *columnCell = NULL; + List *columnList = pull_var_clause_default((Node *) targetList); + foreach(columnCell, columnList) + { + Var *column = (Var *) lfirst(columnCell); + UpdateColumnAttributes(column, rangeTableList, dependedJobList); + } + } + + /* extract limit count/offset and sort clauses */ + if (extendedOpNodeList != NIL) + { + MultiExtendedOp *extendedOp = (MultiExtendedOp *) linitial(extendedOpNodeList); + + limitCount = extendedOp->limitCount; + limitOffset = extendedOp->limitOffset; + sortClauseList = extendedOp->sortClauseList; + } + + /* build group clauses */ + groupClauseList = QueryGroupClauseList(multiNode); + + /* build the where clause list using select predicates */ + selectClauseList = QuerySelectClauseList(multiNode); + + /* set correct column attributes for select columns */ + if (updateColumnAttributes) + { + columnCell = NULL; + columnList = pull_var_clause_default((Node *) selectClauseList); + foreach(columnCell, columnList) + { + Var *column = (Var *) lfirst(columnCell); + UpdateColumnAttributes(column, rangeTableList, dependedJobList); + } + } + + /* + * Build the From/Where construct. We keep the where-clause list implicitly + * AND'd, since both partition and join pruning depends on the clauses being + * expressed as a list. + */ + joinTree = makeNode(FromExpr); + joinTree->quals = (Node *) list_copy(selectClauseList); + joinTree->fromlist = list_make1(joinRoot); + + /* build the query structure for this job */ + jobQuery = makeNode(Query); + jobQuery->commandType = CMD_SELECT; + jobQuery->querySource = QSRC_ORIGINAL; + jobQuery->canSetTag = true; + jobQuery->rtable = rangeTableList; + jobQuery->targetList = targetList; + jobQuery->jointree = joinTree; + jobQuery->sortClause = sortClauseList; + jobQuery->groupClause = groupClauseList; + jobQuery->limitOffset = limitOffset; + jobQuery->limitCount = limitCount; + jobQuery->hasAggs = contain_agg_clause((Node *) targetList); + + return jobQuery; +} + + +/* + * BuildReduceQuery traverses the given logical plan tree, determines the job that + * corresponds to this part of the tree, and builds the query structure for that + * particular job. The function assumes that jobs this particular job depends on + * have already been built, as their output is needed to build the query. + */ +static Query * +BuildReduceQuery(MultiExtendedOp *extendedOpNode, List *dependedJobList) +{ + Query *reduceQuery = NULL; + MultiNode *multiNode = (MultiNode *) extendedOpNode; + List *derivedRangeTableList = NIL; + List *targetList = NIL; + List *whereClauseList = NIL; + List *selectClauseList = NIL; + List *joinClauseList = NIL; + List *columnList = NIL; + ListCell *columnCell = NULL; + FromExpr *joinTree = NULL; + List *columnNameList = NIL; + RangeTblEntry *rangeTableEntry = NULL; + + Job *dependedJob = linitial(dependedJobList); + List *dependedTargetList = dependedJob->jobQuery->targetList; + uint32 columnCount = (uint32) list_length(dependedTargetList); + uint32 columnIndex = 0; + + for (columnIndex = 0; columnIndex < columnCount; columnIndex++) + { + Value *columnValue = NULL; + StringInfo columnNameString = makeStringInfo(); + + appendStringInfo(columnNameString, MERGE_COLUMN_FORMAT, columnIndex); + + columnValue = makeString(columnNameString->data); + columnNameList = lappend(columnNameList, columnValue); + } + + /* create a derived range table for the subtree below the collect */ + rangeTableEntry = DerivedRangeTableEntry(multiNode, columnNameList, + OutputTableIdList(multiNode)); + rangeTableEntry->eref->colnames = columnNameList; + ModifyRangeTblExtraData(rangeTableEntry, CITUS_RTE_SHARD, NULL, NULL, NULL); + derivedRangeTableList = lappend(derivedRangeTableList, rangeTableEntry); + + targetList = copyObject(extendedOpNode->targetList); + columnList = pull_var_clause_default((Node *) targetList); + + foreach(columnCell, columnList) + { + Var *column = (Var *) lfirst(columnCell); + Index originalTableId = column->varnoold; + + /* find the new table identifier */ + Index newTableId = NewTableId(originalTableId, derivedRangeTableList); + column->varno = newTableId; + } + + /* build the where clause list using select and join predicates */ + selectClauseList = QuerySelectClauseList((MultiNode *) extendedOpNode); + joinClauseList = QueryJoinClauseList((MultiNode *) extendedOpNode); + whereClauseList = list_concat(selectClauseList, joinClauseList); + + /* + * Build the From/Where construct. We keep the where-clause list implicitly + * AND'd, since both partition and join pruning depends on the clauses being + * expressed as a list. + */ + joinTree = makeNode(FromExpr); + joinTree->quals = (Node *) whereClauseList; + joinTree->fromlist = QueryFromList(derivedRangeTableList); + + /* build the query structure for this job */ + reduceQuery = makeNode(Query); + reduceQuery->commandType = CMD_SELECT; + reduceQuery->querySource = QSRC_ORIGINAL; + reduceQuery->canSetTag = true; + reduceQuery->rtable = derivedRangeTableList; + reduceQuery->targetList = targetList; + reduceQuery->jointree = joinTree; + reduceQuery->sortClause = extendedOpNode->sortClauseList; + reduceQuery->groupClause = extendedOpNode->groupClauseList; + reduceQuery->limitOffset = extendedOpNode->limitOffset; + reduceQuery->limitCount = extendedOpNode->limitCount; + reduceQuery->hasAggs = contain_agg_clause((Node *) targetList); + + return reduceQuery; +} + + +/* + * BaseRangeTableList returns the list of range table entries for base tables in + * the query. These base tables stand in contrast to derived tables generated by + * repartition jobs. Note that this function only considers base tables relevant + * to the current query, and does not visit nodes under the collect node. + */ +static List * +BaseRangeTableList(MultiNode *multiNode) +{ + List *baseRangeTableList = NIL; + List *pendingNodeList = list_make1(multiNode); + + while (pendingNodeList != NIL) + { + MultiNode *multiNode = (MultiNode *) linitial(pendingNodeList); + CitusNodeTag nodeType = CitusNodeTag(multiNode); + pendingNodeList = list_delete_first(pendingNodeList); + + if (nodeType == T_MultiTable) + { + /* + * We represent subqueries as MultiTables, and so for base table + * entries we skip the subquery ones. + */ + MultiTable *multiTable = (MultiTable *) multiNode; + if (multiTable->relationId != SUBQUERY_RELATION_ID && + multiTable->relationId != HEAP_ANALYTICS_SUBQUERY_RELATION_ID) + { + RangeTblEntry *rangeTableEntry = makeNode(RangeTblEntry); + rangeTableEntry->inFromCl = true; + rangeTableEntry->eref = multiTable->referenceNames; + rangeTableEntry->alias = multiTable->alias; + rangeTableEntry->relid = multiTable->relationId; + SetRangeTblExtraData(rangeTableEntry, CITUS_RTE_RELATION, NULL, NULL, + list_make1_int(multiTable->rangeTableId)); + + baseRangeTableList = lappend(baseRangeTableList, rangeTableEntry); + } + } + + /* do not visit nodes that belong to remote queries */ + if (nodeType != T_MultiCollect) + { + List *childNodeList = ChildNodeList(multiNode); + pendingNodeList = list_concat(pendingNodeList, childNodeList); + } + } + + return baseRangeTableList; +} + + +/* + * DerivedRangeTableEntry builds a range table entry for the derived table. This + * derived table either represents the output of a repartition job; or the data + * on worker nodes in case of the master node query. + */ +static RangeTblEntry * +DerivedRangeTableEntry(MultiNode *multiNode, List *columnList, List *tableIdList) +{ + RangeTblEntry *rangeTableEntry = makeNode(RangeTblEntry); + rangeTableEntry->inFromCl = true; + rangeTableEntry->eref = makeNode(Alias); + rangeTableEntry->eref->colnames = columnList; + + SetRangeTblExtraData(rangeTableEntry, CITUS_RTE_REMOTE_QUERY, NULL, NULL, + tableIdList); + + return rangeTableEntry; +} + + +/* + * DerivedColumnNameList builds a column name list for derived (intermediate) + * tables. These column names are then used when building the create stament + * query string for derived tables. + */ +static List * +DerivedColumnNameList(uint32 columnCount, uint64 generatingJobId) +{ + List *columnNameList = NIL; + uint32 columnIndex = 0; + + for (columnIndex = 0; columnIndex < columnCount; columnIndex++) + { + StringInfo columnName = makeStringInfo(); + Value *columnValue = NULL; + + appendStringInfo(columnName, "intermediate_column_"); + appendStringInfo(columnName, UINT64_FORMAT "_", generatingJobId); + appendStringInfo(columnName, "%u", columnIndex); + + columnValue = makeString(columnName->data); + columnNameList = lappend(columnNameList, columnValue); + } + + return columnNameList; +} + + +/* + * QueryTargetList returns the target entry list for the projected columns + * needed to evaluate the operators above the given multiNode. To do this, + * the function retrieves a list of all MultiProject nodes below the given + * node and picks the columns from the top-most MultiProject node, as this + * will be the minimal list of columns needed. Note that this function relies + * on a pre-order traversal of the operator tree by the function FindNodesOfType. + */ +static List * +QueryTargetList(MultiNode *multiNode) +{ + MultiProject *topProjectNode = NULL; + List *columnList = NIL; + List *queryTargetList = NIL; + + List *projectNodeList = FindNodesOfType(multiNode, T_MultiProject); + Assert(list_length(projectNodeList) > 0); + + topProjectNode = (MultiProject *) linitial(projectNodeList); + columnList = topProjectNode->columnList; + queryTargetList = TargetEntryList(columnList); + + Assert(queryTargetList != NIL); + return queryTargetList; +} + + +/* + * TargetEntryList creates a target entry for each expression in the given list, + * and returns the newly created target entries in a list. + */ +static List * +TargetEntryList(List *expressionList) +{ + List *targetEntryList = NIL; + ListCell *expressionCell = NULL; + + foreach(expressionCell, expressionList) + { + Expr *expression = (Expr *) lfirst(expressionCell); + + TargetEntry *targetEntry = makeTargetEntry(expression, + list_length(targetEntryList)+1, + NULL, false); + targetEntryList = lappend(targetEntryList, targetEntry); + } + + return targetEntryList; +} + + +/* + * QueryGroupClauseList extracts the group clause list from the logical plan. If + * no grouping clauses exist, the function returns an empty list. + */ +static List * +QueryGroupClauseList(MultiNode *multiNode) +{ + List *groupClauseList = NIL; + List *pendingNodeList = list_make1(multiNode); + + while (pendingNodeList != NIL) + { + MultiNode *multiNode = (MultiNode *) linitial(pendingNodeList); + CitusNodeTag nodeType = CitusNodeTag(multiNode); + pendingNodeList = list_delete_first(pendingNodeList); + + /* extract the group clause list from the extended operator */ + if (nodeType == T_MultiExtendedOp) + { + MultiExtendedOp *extendedOpNode = (MultiExtendedOp *) multiNode; + groupClauseList = extendedOpNode->groupClauseList; + } + + /* add children only if this node isn't a multi collect and multi table */ + if (nodeType != T_MultiCollect && nodeType != T_MultiTable) + { + List *childNodeList = ChildNodeList(multiNode); + pendingNodeList = list_concat(pendingNodeList, childNodeList); + } + } + + return groupClauseList; +} + + +/* + * QuerySelectClauseList traverses the given logical plan tree, and extracts all + * select clauses from the select nodes. Note that this function does not walk + * below a collect node; the clauses below the collect node apply to a remote + * query, and they would have been captured by the remote job we depend upon. + */ +static List * +QuerySelectClauseList(MultiNode *multiNode) +{ + List *selectClauseList = NIL; + List *pendingNodeList = list_make1(multiNode); + + while (pendingNodeList != NIL) + { + MultiNode *multiNode = (MultiNode *) linitial(pendingNodeList); + CitusNodeTag nodeType = CitusNodeTag(multiNode); + pendingNodeList = list_delete_first(pendingNodeList); + + /* extract select clauses from the multi select node */ + if (nodeType == T_MultiSelect) + { + MultiSelect *selectNode = (MultiSelect *) multiNode; + List *clauseList = copyObject(selectNode->selectClauseList); + selectClauseList = list_concat(selectClauseList, clauseList); + } + + /* add children only if this node isn't a multi collect */ + if (nodeType != T_MultiCollect) + { + List *childNodeList = ChildNodeList(multiNode); + pendingNodeList = list_concat(pendingNodeList, childNodeList); + } + } + + return selectClauseList; +} + + +/* + * QueryJoinClauseList traverses the given logical plan tree, and extracts all + * join clauses from the join nodes. Note that this function does not walk below + * a collect node; the clauses below the collect node apply to another query, + * and they would have been captured by the remote job we depend upon. + */ +static List * +QueryJoinClauseList(MultiNode *multiNode) +{ + List *joinClauseList = NIL; + List *pendingNodeList = list_make1(multiNode); + + while (pendingNodeList != NIL) + { + MultiNode *multiNode = (MultiNode *) linitial(pendingNodeList); + CitusNodeTag nodeType = CitusNodeTag(multiNode); + pendingNodeList = list_delete_first(pendingNodeList); + + /* extract join clauses from the multi join node */ + if (nodeType == T_MultiJoin) + { + MultiJoin *joinNode = (MultiJoin *) multiNode; + List *clauseList = copyObject(joinNode->joinClauseList); + joinClauseList = list_concat(joinClauseList, clauseList); + } + + /* add this node's children only if the node isn't a multi collect */ + if (nodeType != T_MultiCollect) + { + List *childNodeList = ChildNodeList(multiNode); + pendingNodeList = list_concat(pendingNodeList, childNodeList); + } + } + + return joinClauseList; +} + + +/* + * Create a tree of JoinExpr and RangeTblRef nodes for the job query from + * a given multiNode. If the tree contains MultiCollect or MultiJoin nodes, + * add corresponding entries to the range table list. We need to construct + * the entries at the same time as the tree to know the appropriate rtindex. + */ +static Node * +QueryJoinTree(MultiNode *multiNode, List *dependedJobList, List **rangeTableList) +{ + CitusNodeTag nodeType = CitusNodeTag(multiNode); + + switch (nodeType) + { + case T_MultiJoin: + { + MultiJoin *joinNode = (MultiJoin *) multiNode; + MultiBinaryNode *binaryNode = (MultiBinaryNode *) multiNode; + List *columnList = NIL; + ListCell *columnCell = NULL; + RangeTblEntry *rangeTableEntry = NULL; + JoinExpr *joinExpr = makeNode(JoinExpr); + joinExpr->jointype = joinNode->joinType; + joinExpr->isNatural = false; + joinExpr->larg = QueryJoinTree(binaryNode->leftChildNode, dependedJobList, + rangeTableList); + joinExpr->rarg = QueryJoinTree(binaryNode->rightChildNode, dependedJobList, + rangeTableList); + joinExpr->usingClause = NIL; + joinExpr->alias = NULL; + joinExpr->rtindex = list_length(*rangeTableList) + 1; + + /* + * PostgreSQL's optimizer may mark left joins as anti-joins, when there + * is an right-hand-join-key-is-null restriction, but there is no logic + * in ruleutils to deparse anti-joins, so we cannot construct a task + * query containing anti-joins. We therefore translate anti-joins back + * into left-joins. At some point, we may also want to use different + * join pruning logic for anti-joins. + * + * This approach would not work for anti-joins introduced via NOT EXISTS + * sublinks, but currently such queries are prevented by error checks in + * the logical planner. + */ + if (joinExpr->jointype == JOIN_ANTI) + { + joinExpr->jointype = JOIN_LEFT; + } + + rangeTableEntry = JoinRangeTableEntry(joinExpr, dependedJobList, + *rangeTableList); + *rangeTableList = lappend(*rangeTableList, rangeTableEntry); + + /* fix the column attributes in ON (...) clauses */ + columnList = pull_var_clause_default((Node *) joinNode->joinClauseList); + foreach (columnCell, columnList) + { + Var *column = (Var *) lfirst(columnCell); + UpdateColumnAttributes(column, *rangeTableList, dependedJobList); + + /* adjust our column old attributes for partition pruning to work */ + column->varnoold = column->varno; + column->varoattno = column->varattno; + } + + /* make AND clauses explicit after fixing them */ + joinExpr->quals = (Node *) make_ands_explicit(joinNode->joinClauseList); + + return (Node *) joinExpr; + } + + case T_MultiTable: + { + MultiTable *rangeTableNode = (MultiTable *) multiNode; + MultiUnaryNode *unaryNode = (MultiUnaryNode *) multiNode; + + if (unaryNode->childNode != NULL) + { + /* MultiTable is actually a subquery, return the query tree below */ + Node *childNode = QueryJoinTree(unaryNode->childNode, dependedJobList, + rangeTableList); + + return childNode; + } + else + { + RangeTblRef *rangeTableRef = makeNode(RangeTblRef); + uint32 rangeTableId = rangeTableNode->rangeTableId; + rangeTableRef->rtindex = NewTableId(rangeTableId, *rangeTableList); + + return (Node *) rangeTableRef; + } + } + + case T_MultiCollect: + { + List *tableIdList = OutputTableIdList(multiNode); + Job *dependedJob = JobForTableIdList(dependedJobList, tableIdList); + List *dependedTargetList = dependedJob->jobQuery->targetList; + + /* compute column names for the derived table */ + uint32 columnCount = (uint32) list_length(dependedTargetList); + List *columnNameList = DerivedColumnNameList(columnCount, dependedJob->jobId); + + RangeTblEntry *rangeTableEntry = DerivedRangeTableEntry(multiNode, columnNameList, + tableIdList); + RangeTblRef *rangeTableRef = makeNode(RangeTblRef); + + rangeTableRef->rtindex = list_length(*rangeTableList) + 1; + *rangeTableList = lappend(*rangeTableList, rangeTableEntry); + + return (Node *) rangeTableRef; + } + + case T_MultiCartesianProduct: + { + MultiBinaryNode *binaryNode = (MultiBinaryNode *) multiNode; + RangeTblEntry *rangeTableEntry = NULL; + + JoinExpr *joinExpr = makeNode(JoinExpr); + joinExpr->jointype = JOIN_INNER; + joinExpr->isNatural = false; + joinExpr->larg = QueryJoinTree(binaryNode->leftChildNode, dependedJobList, + rangeTableList); + joinExpr->rarg = QueryJoinTree(binaryNode->rightChildNode, dependedJobList, + rangeTableList); + joinExpr->usingClause = NIL; + joinExpr->alias = NULL; + joinExpr->quals = NULL; + joinExpr->rtindex = list_length(*rangeTableList) + 1; + + rangeTableEntry = JoinRangeTableEntry(joinExpr, dependedJobList, + *rangeTableList); + *rangeTableList = lappend(*rangeTableList, rangeTableEntry); + + return (Node *) joinExpr; + } + + case T_MultiTreeRoot: + case T_MultiSelect: + case T_MultiProject: + case T_MultiExtendedOp: + case T_MultiPartition: + { + MultiUnaryNode *unaryNode = (MultiUnaryNode *) multiNode; + Node *childNode = NULL; + + Assert(UnaryOperator(multiNode)); + + childNode = QueryJoinTree(unaryNode->childNode, dependedJobList, + rangeTableList); + + return childNode; + } + + default: + { + ereport(ERROR, (errmsg("unrecognized multi-node type: %d", nodeType))); + } + } +} + + +/* + * JoinRangeTableEntry builds a range table entry for a fully initialized JoinExpr node. + * The column names and vars are determined using expandRTE, analogous to + * transformFromClauseItem. + */ +static RangeTblEntry * +JoinRangeTableEntry(JoinExpr *joinExpr, List *dependedJobList, List *rangeTableList) +{ + RangeTblEntry *rangeTableEntry = makeNode(RangeTblEntry); + List *joinedColumnNames = NIL; + List *joinedColumnVars = NIL; + List *leftColumnNames = NIL; + List *leftColumnVars = NIL; + int leftRangeTableId = ExtractRangeTableId(joinExpr->larg); + RangeTblEntry *leftRTE = rt_fetch(leftRangeTableId, rangeTableList); + List *rightColumnNames = NIL; + List *rightColumnVars = NIL; + int rightRangeTableId = ExtractRangeTableId(joinExpr->rarg); + RangeTblEntry *rightRTE = rt_fetch(rightRangeTableId, rangeTableList); + + rangeTableEntry->rtekind = RTE_JOIN; + rangeTableEntry->relid = InvalidOid; + rangeTableEntry->inFromCl = true; + rangeTableEntry->alias = joinExpr->alias; + rangeTableEntry->jointype = joinExpr->jointype; + rangeTableEntry->subquery = NULL; + rangeTableEntry->eref = makeAlias("unnamed_join", NIL); + + ExtractColumns(leftRTE, leftRangeTableId, dependedJobList, + &leftColumnNames, &leftColumnVars); + ExtractColumns(rightRTE, rightRangeTableId, dependedJobList, + &rightColumnNames, &rightColumnVars); + + joinedColumnNames = list_concat(joinedColumnNames, leftColumnNames); + joinedColumnVars = list_concat(joinedColumnVars, leftColumnVars); + joinedColumnNames = list_concat(joinedColumnNames, rightColumnNames); + joinedColumnVars = list_concat(joinedColumnVars, rightColumnVars); + + rangeTableEntry->eref->colnames = joinedColumnNames; + rangeTableEntry->joinaliasvars = joinedColumnVars; + + return rangeTableEntry; +} + + +/* + * ExtractRangeTableId gets the range table id from a node that could + * either be a JoinExpr or RangeTblRef. + */ +static int +ExtractRangeTableId(Node *node) +{ + int rangeTableId = 0; + + if (IsA(node, JoinExpr)) + { + JoinExpr *joinExpr = (JoinExpr *) node; + rangeTableId = joinExpr->rtindex; + } + else if (IsA(node, RangeTblRef)) + { + RangeTblRef *rangeTableRef = (RangeTblRef *) node; + rangeTableId = rangeTableRef->rtindex; + } + + Assert(rangeTableId > 0); + + return rangeTableId; +} + + +/* + * ExtractColumns gets a list of column names and vars for a given range + * table entry using expandRTE. Since the range table entries in a job + * query are mocked RTE_FUNCTION entries, it first translates the RTE's + * to a form that expandRTE can handle. + */ +static void +ExtractColumns(RangeTblEntry *rangeTableEntry, int rangeTableId, List *dependedJobList, + List **columnNames, List **columnVars) +{ + RangeTblEntry *callingRTE = NULL; + + CitusRTEKind rangeTableKind = GetRangeTblKind(rangeTableEntry); + if (rangeTableKind == CITUS_RTE_JOIN) + { + /* + * For joins, we can call expandRTE directly. + */ + callingRTE = rangeTableEntry; + } + else if (rangeTableKind == CITUS_RTE_RELATION) + { + /* + * For distributed tables, we construct a regular table RTE to call + * expandRTE, which will extract columns from the distributed table + * schema. + */ + callingRTE = makeNode(RangeTblEntry); + callingRTE->rtekind = RTE_RELATION; + callingRTE->eref = rangeTableEntry->eref; + callingRTE->relid = rangeTableEntry->relid; + } + else if (rangeTableKind == CITUS_RTE_REMOTE_QUERY) + { + Job *dependedJob = JobForRangeTable(dependedJobList, rangeTableEntry); + Query *jobQuery = dependedJob->jobQuery; + + /* + * For re-partition jobs, we construct a subquery RTE to call expandRTE, + * which will extract the columns from the target list of the job query. + */ + callingRTE = makeNode(RangeTblEntry); + callingRTE->rtekind = RTE_SUBQUERY; + callingRTE->eref = rangeTableEntry->eref; + callingRTE->subquery = jobQuery; + } + else + { + ereport(ERROR, (errmsg("unsupported Citus RTE kind: %d", rangeTableKind))); + } + + expandRTE(callingRTE, rangeTableId, 0, -1, false, columnNames, columnVars); +} + + +/* + * QueryFromList creates the from list construct that is used for building the + * query's join tree. The function creates the from list by making a range table + * reference for each entry in the given range table list. + */ +static List * +QueryFromList(List *rangeTableList) +{ + List *fromList = NIL; + Index rangeTableIndex = 1; + int rangeTableCount = list_length(rangeTableList); + + for (rangeTableIndex = 1; rangeTableIndex <= rangeTableCount; rangeTableIndex++) + { + RangeTblRef *rangeTableReference = makeNode(RangeTblRef); + rangeTableReference->rtindex = rangeTableIndex; + + fromList = lappend(fromList, rangeTableReference); + } + + return fromList; +} + + +/* + * BuildSubqueryJobQuery traverses the given logical plan tree, finds MultiTable + * which represents the subquery. It builds the query structure by adding this + * subquery as it is to range table list of the query. + * + * Such as if user runs a query like this; + * + * SELECT avg(id) FROM ( + * SELECT ... FROM () + * ) + * + * then this function will build this worker query as keeping subquery as it is; + * + * SELECT sum(id), count(id) FROM ( + * SELECT ... FROM () + * ) + */ +static Query * +BuildSubqueryJobQuery(MultiNode *multiNode) +{ + Query *jobQuery = NULL; + Query *subquery = NULL; + MultiTable *multiTable = NULL; + RangeTblEntry *rangeTableEntry = NULL; + List *subqueryMultiTableList = NIL; + List *rangeTableList = NIL; + List *targetList = NIL; + List *extendedOpNodeList = NIL; + List *sortClauseList = NIL; + List *groupClauseList = NIL; + List *whereClauseList = NIL; + Node *limitCount = NULL; + Node *limitOffset = NULL; + FromExpr *joinTree = NULL; + + /* we start building jobs from below the collect node */ + Assert(!CitusIsA(multiNode, MultiCollect)); + + subqueryMultiTableList = SubqueryMultiTableList(multiNode); + Assert(list_length(subqueryMultiTableList) == 1); + + multiTable = (MultiTable *) linitial(subqueryMultiTableList); + subquery = multiTable->subquery; + + /* build subquery range table list */ + rangeTableEntry = makeNode(RangeTblEntry); + rangeTableEntry->rtekind = RTE_SUBQUERY; + rangeTableEntry->inFromCl = true; + rangeTableEntry->eref = multiTable->referenceNames; + rangeTableEntry->alias = multiTable->alias; + rangeTableEntry->subquery = subquery; + + rangeTableList = list_make1(rangeTableEntry); + + /* + * If we have an extended operator, then we copy the operator's target list. + * Otherwise, we use the target list based on the MultiProject node at this + * level in the query tree. + */ + extendedOpNodeList = FindNodesOfType(multiNode, T_MultiExtendedOp); + if (extendedOpNodeList != NIL) + { + MultiExtendedOp *extendedOp = (MultiExtendedOp *) linitial(extendedOpNodeList); + targetList = copyObject(extendedOp->targetList); + } + else + { + targetList = QueryTargetList(multiNode); + } + + /* extract limit count/offset and sort clauses */ + if (extendedOpNodeList != NIL) + { + MultiExtendedOp *extendedOp = (MultiExtendedOp *) linitial(extendedOpNodeList); + + limitCount = extendedOp->limitCount; + limitOffset = extendedOp->limitOffset; + sortClauseList = extendedOp->sortClauseList; + } + + /* build group clauses */ + groupClauseList = QueryGroupClauseList(multiNode); + + /* build the where clause list using select predicates */ + whereClauseList = QuerySelectClauseList(multiNode); + + /* + * Build the From/Where construct. We keep the where-clause list implicitly + * AND'd, since both partition and join pruning depends on the clauses being + * expressed as a list. + */ + joinTree = makeNode(FromExpr); + joinTree->quals = (Node *) whereClauseList; + joinTree->fromlist = QueryFromList(rangeTableList); + + /* build the query structure for this job */ + jobQuery = makeNode(Query); + jobQuery->commandType = CMD_SELECT; + jobQuery->querySource = QSRC_ORIGINAL; + jobQuery->canSetTag = true; + jobQuery->rtable = rangeTableList; + jobQuery->targetList = targetList; + jobQuery->jointree = joinTree; + jobQuery->sortClause = sortClauseList; + jobQuery->groupClause = groupClauseList; + jobQuery->limitOffset = limitOffset; + jobQuery->limitCount = limitCount; + jobQuery->hasAggs = contain_agg_clause((Node *) targetList); + + return jobQuery; +} + + +/* + * UpdateColumnAttributes updates the column's range table reference (varno) and + * column attribute number for the range table (varattno). The function uses the + * newly built range table list to update the given column's attributes. + */ +static void +UpdateColumnAttributes(Var *column, List *rangeTableList, List *dependedJobList) +{ + Index originalTableId = column->varnoold; + AttrNumber originalColumnId = column->varoattno; + + /* find the new table identifier */ + Index newTableId = NewTableId(originalTableId, rangeTableList); + AttrNumber newColumnId = originalColumnId; + + /* if this is a derived table, find the new column identifier */ + RangeTblEntry *newRangeTableEntry = rt_fetch(newTableId, rangeTableList); + if (GetRangeTblKind(newRangeTableEntry) == CITUS_RTE_REMOTE_QUERY) + { + newColumnId = NewColumnId(originalTableId, originalColumnId, + newRangeTableEntry, dependedJobList); + } + + column->varno = newTableId; + column->varattno = newColumnId; +} + + +/* + * NewTableId determines the new tableId for the query that is currently being + * built. In this query, the original tableId represents the order of the table + * in the initial parse tree. When queries involve repartitioning, we re-order + * tables; and the new tableId corresponds to this new table order. + */ +static Index +NewTableId(Index originalTableId, List *rangeTableList) +{ + Index newTableId = 0; + Index rangeTableIndex = 1; + ListCell *rangeTableCell = NULL; + + foreach(rangeTableCell, rangeTableList) + { + RangeTblEntry *rangeTableEntry = (RangeTblEntry *) lfirst(rangeTableCell); + List *originalTableIdList = NIL; + bool listMember = false; + + ExtractRangeTblExtraData(rangeTableEntry, NULL, NULL, NULL, &originalTableIdList); + + listMember = list_member_int(originalTableIdList, originalTableId); + if (listMember) + { + newTableId = rangeTableIndex; + break; + } + + rangeTableIndex++; + } + + return newTableId; +} + + +/* + * NewColumnId determines the new columnId for the query that is currently being + * built. In this query, the original columnId corresponds to the column in base + * tables. When the current query is a partition job and generates intermediate + * tables, the columns have a different order and the new columnId corresponds + * to this order. Please note that this function assumes columnIds for depended + * jobs have already been updated. + */ +static AttrNumber +NewColumnId(Index originalTableId, AttrNumber originalColumnId, + RangeTblEntry *newRangeTableEntry, List *dependedJobList) +{ + AttrNumber newColumnId = 1; + AttrNumber columnIndex = 1; + + Job *dependedJob = JobForRangeTable(dependedJobList, newRangeTableEntry); + List *targetEntryList = dependedJob->jobQuery->targetList; + + ListCell *targetEntryCell = NULL; + foreach(targetEntryCell, targetEntryList) + { + TargetEntry *targetEntry = (TargetEntry *) lfirst(targetEntryCell); + Expr *expression = targetEntry->expr; + + Var *column = (Var *) expression; + Assert(IsA(expression, Var)); + + /* + * Check against the *old* values for this column, as the new values + * would have been updated already. + */ + if (column->varnoold == originalTableId && + column->varoattno == originalColumnId) + { + newColumnId = columnIndex; + break; + } + + columnIndex++; + } + + return newColumnId; +} + + +/* + * JobForRangeTable returns the job that corresponds to the given range table + * entry. The function walks over jobs in the given job list, and compares each + * job's table list against the given range table entry's table list. When two + * table lists match, the function returns the matching job. Note that we call + * this function in practice when we need to determine which one of the jobs we + * depend upon corresponds to given range table entry. + */ +static Job * +JobForRangeTable(List *jobList, RangeTblEntry *rangeTableEntry) +{ + Job *searchedJob = NULL; + List *searchedTableIdList = NIL; + CitusRTEKind rangeTableKind; + + ExtractRangeTblExtraData(rangeTableEntry, &rangeTableKind, NULL, NULL, + &searchedTableIdList); + + Assert(rangeTableKind == CITUS_RTE_REMOTE_QUERY); + + searchedJob = JobForTableIdList(jobList, searchedTableIdList); + + return searchedJob; +} + + +/* + * JobForTableIdList returns the job that corresponds to the given + * tableIdList. The function walks over jobs in the given job list, and + * compares each job's table list against the given table list. When the + * two table lists match, the function returns the matching job. + */ +static Job * +JobForTableIdList(List *jobList, List *searchedTableIdList) +{ + Job *searchedJob = NULL; + ListCell *jobCell = NULL; + + foreach(jobCell, jobList) + { + Job *job = (Job *) lfirst(jobCell); + List *jobRangeTableList = job->jobQuery->rtable; + List *jobTableIdList = NIL; + ListCell *jobRangeTableCell = NULL; + List *lhsDiff = NIL; + List *rhsDiff = NIL; + + foreach(jobRangeTableCell, jobRangeTableList) + { + RangeTblEntry *jobRangeTable = (RangeTblEntry *) lfirst(jobRangeTableCell); + List *tableIdList = NIL; + + ExtractRangeTblExtraData(jobRangeTable, NULL, NULL, NULL, &tableIdList); + + /* copy the list since list_concat is destructive */ + tableIdList = list_copy(tableIdList); + jobTableIdList = list_concat(jobTableIdList, tableIdList); + } + + /* + * Check if the searched range table's tableIds and the current job's + * tableIds are the same. + */ + lhsDiff = list_difference_int(jobTableIdList, searchedTableIdList); + rhsDiff = list_difference_int(searchedTableIdList, jobTableIdList); + if (lhsDiff == NIL && rhsDiff == NIL) + { + searchedJob = job; + break; + } + } + + Assert(searchedJob != NULL); + return searchedJob; +} + + +/* Returns the list of children for the given multi node. */ +static List * +ChildNodeList(MultiNode *multiNode) +{ + List *childNodeList = NIL; + bool unaryNode = UnaryOperator(multiNode); + bool binaryNode = BinaryOperator(multiNode); + + /* relation table nodes don't have any children */ + if (CitusIsA(multiNode, MultiTable)) + { + MultiTable *multiTable = (MultiTable *) multiNode; + if (multiTable->relationId != SUBQUERY_RELATION_ID) + { + return NIL; + } + } + + if (unaryNode) + { + MultiUnaryNode *unaryNode = (MultiUnaryNode *) multiNode; + childNodeList = list_make1(unaryNode->childNode); + } + else if (binaryNode) + { + MultiBinaryNode *binaryNode = (MultiBinaryNode *) multiNode; + childNodeList = list_make2(binaryNode->leftChildNode, + binaryNode->rightChildNode); + } + + return childNodeList; +} + + +/* + * UniqueJobId allocates and returns a unique jobId for the job to be executed. + * This allocation occurs both in shared memory and in write ahead logs; writing + * to logs avoids the risk of having jobId collisions. + * + * Please note that the jobId sequence wraps around after 2^32 integers. This + * leaves the upper 32-bits to slave nodes and their jobs. + */ +static uint64 +UniqueJobId(void) +{ + text *sequenceName = cstring_to_text(JOBID_SEQUENCE_NAME); + Oid sequenceId = ResolveRelationId(sequenceName); + Datum sequenceIdDatum = ObjectIdGetDatum(sequenceId); + + /* generate new and unique jobId from sequence */ + Datum jobIdDatum = DirectFunctionCall1(nextval_oid, sequenceIdDatum); + int64 jobId = DatumGetInt64(jobIdDatum); + + return jobId; +} + + +/* Builds a job from the given job query and depended job list. */ +static Job * +BuildJob(Query *jobQuery, List *dependedJobList) +{ + Job *job = CitusMakeNode(Job); + job->jobId = UniqueJobId(); + job->jobQuery = jobQuery; + job->dependedJobList = dependedJobList; + + return job; +} + + +/* + * BuildMapMergeJob builds a MapMerge job from the given query and depended job + * list. The function then copies and updates the logical plan's partition + * column, and uses the join rule type to determine the physical repartitioning + * method to apply. + */ +static MapMergeJob * +BuildMapMergeJob(Query *jobQuery, List *dependedJobList, Var *partitionKey, + PartitionType partitionType, Oid baseRelationId, + BoundaryNodeJobType boundaryNodeJobType) +{ + MapMergeJob *mapMergeJob = NULL; + List *rangeTableList = jobQuery->rtable; + Var *partitionColumn = copyObject(partitionKey); + + /* update the logical partition key's table and column identifiers */ + if (boundaryNodeJobType != SUBQUERY_MAP_MERGE_JOB) + { + UpdateColumnAttributes(partitionColumn, rangeTableList, dependedJobList); + } + + mapMergeJob = CitusMakeNode(MapMergeJob); + mapMergeJob->job.jobId = UniqueJobId(); + mapMergeJob->job.jobQuery = jobQuery; + mapMergeJob->job.dependedJobList = dependedJobList; + mapMergeJob->partitionColumn = partitionColumn; + mapMergeJob->sortedShardIntervalArrayLength = 0; + + /* + * We assume dual partition join defaults to hash partitioning, and single + * partition join defaults to range partitioning. In practice, the join type + * should have no impact on the physical repartitioning (hash/range) method. + * If join type is not set, this means this job represents a subquery, and + * uses hash partitioning. + */ + if (partitionType == HASH_PARTITION_TYPE) + { + uint32 partitionCount = HashPartitionCount(); + + mapMergeJob->partitionType = HASH_PARTITION_TYPE; + mapMergeJob->partitionCount = partitionCount; + } + else if (partitionType == RANGE_PARTITION_TYPE) + { + /* build the split point object for the table on the right-hand side */ + List *shardIntervalList = LoadShardIntervalList(baseRelationId); + uint32 shardCount = (uint32) list_length(shardIntervalList); + ShardInterval **sortedShardIntervalArray = + SortedShardIntervalArray(shardIntervalList); + + /* this join-type currently doesn't work for hash partitioned tables */ + char basePartitionMethod = PartitionMethod(baseRelationId); + Assert(basePartitionMethod != DISTRIBUTE_BY_HASH); + + mapMergeJob->partitionType = RANGE_PARTITION_TYPE; + mapMergeJob->partitionCount = shardCount; + mapMergeJob->sortedShardIntervalArray = sortedShardIntervalArray; + mapMergeJob->sortedShardIntervalArrayLength = shardCount; + } + + return mapMergeJob; +} + + +/* + * HashPartitionCount returns the number of partition files we create for a hash + * partition task. The function follows Hadoop's method for picking the number + * of reduce tasks: 0.95 or 1.75 * node count * max reduces per node. We choose + * the lower constant 0.95 so that all tasks can start immediately, but round it + * to 1.0 so that we have a smooth number of partition tasks. + */ +static uint32 +HashPartitionCount(void) +{ + uint32 nodeCount = WorkerGetLiveNodeCount(); + double maxReduceTasksPerNode = MaxRunningTasksPerNode / 2.0; + + uint32 partitionCount = (uint32) rint(nodeCount * maxReduceTasksPerNode); + return partitionCount; +} + + +/* + * SortedShardIntervalArray returns a sorted array of shard intervals for shards + * in the given shard list. The array elements are sorted in in ascending order + * according to shard interval's minimum value. + */ +ShardInterval ** +SortedShardIntervalArray(List *shardIntervalList) +{ + FmgrInfo *typeCompareFunction = NULL; + ListCell *shardIntervalCell = NULL; + uint32 shardIntervalIndex = 0; + + ShardInterval **shardIntervalArray = NULL; + uint32 shardIntervalCount = (uint32) list_length(shardIntervalList); + Assert(shardIntervalCount > 0); + + /* allocate an array for sorted shard intervals */ + shardIntervalArray = palloc0(shardIntervalCount * sizeof(ShardInterval *)); + + /* fill in the array with shard intervals */ + foreach(shardIntervalCell, shardIntervalList) + { + ShardInterval *shardInterval = (ShardInterval *) lfirst(shardIntervalCell); + if (shardInterval->minValueExists && shardInterval->maxValueExists) + { + shardIntervalArray[shardIntervalIndex] = shardInterval; + } + else + { + ereport(ERROR, (errmsg("cannot range repartition shard " UINT64_FORMAT + " with missing min/max values", + shardInterval->shardId))); + } + + /* resolve the datum type and comparison function on first pass */ + if (shardIntervalIndex == 0) + { + Oid typeId = shardInterval->valueTypeId; + typeCompareFunction = GetFunctionInfo(typeId, BTREE_AM_OID, BTORDER_PROC); + } + shardIntervalIndex++; + } + + /* sort shard intervals by their minimum values in ascending order */ + qsort_arg(shardIntervalArray, shardIntervalCount, sizeof(ShardInterval *), + (qsort_arg_comparator) CompareShardIntervals, (void *) typeCompareFunction); + + return shardIntervalArray; +} + + +/* + * CompareShardIntervals acts as a helper function to compare two shard interval + * pointers by their minimum values, using the value's type comparison function. + */ +static int +CompareShardIntervals(const void *leftElement, const void *rightElement, + FmgrInfo *typeCompareFunction) +{ + ShardInterval **leftShardInterval = (ShardInterval **) leftElement; + ShardInterval **rightShardInterval = (ShardInterval **) rightElement; + + Datum leftDatum = (*leftShardInterval)->minValue; + Datum rightDatum = (*rightShardInterval)->minValue; + + Datum comparisonDatum = CompareCall2(typeCompareFunction, leftDatum, rightDatum); + int comparisonResult = DatumGetInt32(comparisonDatum); + + return comparisonResult; +} + + +/* + * SplitPointObject walks over shard intervals in the given array, extracts each + * shard interval's minimum value, sorts and inserts these minimum values into a + * new array. This sorted array is then used by the MapMerge job. + */ +static ArrayType * +SplitPointObject(ShardInterval **shardIntervalArray, uint32 shardIntervalCount) +{ + ArrayType *splitPointObject = NULL; + uint32 intervalIndex = 0; + Oid typeId = InvalidOid; + bool typeByValue = false; + char typeAlignment = 0; + int16 typeLength = 0; + + /* allocate an array for shard min values */ + uint32 minDatumCount = shardIntervalCount; + Datum *minDatumArray = palloc0(minDatumCount * sizeof(Datum)); + + for (intervalIndex = 0; intervalIndex < shardIntervalCount; intervalIndex++) + { + ShardInterval *shardInterval = shardIntervalArray[intervalIndex]; + minDatumArray[intervalIndex] = shardInterval->minValue; + Assert(shardInterval->minValueExists); + + /* resolve the datum type on the first pass */ + if (intervalIndex == 0) + { + typeId = shardInterval->valueTypeId; + } + } + + /* construct the split point object from the sorted array */ + get_typlenbyvalalign(typeId, &typeLength, &typeByValue, &typeAlignment); + splitPointObject = construct_array(minDatumArray, minDatumCount, typeId, + typeLength, typeByValue, typeAlignment); + + return splitPointObject; +} + +/* ------------------------------------------------------------ + * Functions that relate to building and assigning tasks follow + * ------------------------------------------------------------ + */ + +/* + * BuildJobTreeTaskList takes in the given job tree and walks over jobs in this + * tree bottom up. The function then creates tasks for each job in the tree, + * sets dependencies between tasks and their downstream dependencies and assigns + * tasks to worker nodes. + */ +static Job * +BuildJobTreeTaskList(Job *jobTree) +{ + List *flattenedJobList = NIL; + uint32 flattenedJobCount = 0; + int32 jobIndex = 0; + + /* + * We traverse the job tree in preorder, and append each visited job to our + * flattened list. This way, each job in our list appears before the jobs it + * depends on. + */ + List *jobStack = list_make1(jobTree); + while (jobStack != NIL) + { + Job *job = (Job *) llast(jobStack); + flattenedJobList = lappend(flattenedJobList, job); + + /* pop top element and push its children to the stack */ + jobStack = list_delete_ptr(jobStack, job); + jobStack = list_union_ptr(jobStack, job->dependedJobList); + } + + /* + * We walk the job list in reverse order to visit jobs bottom up. This way, + * we can create dependencies between tasks bottom up, and assign them to + * worker nodes accordingly. + */ + flattenedJobCount = (int32) list_length(flattenedJobList); + for (jobIndex = (flattenedJobCount - 1); jobIndex >= 0; jobIndex--) + { + Job *job = (Job *) list_nth(flattenedJobList, jobIndex); + List *sqlTaskList = NIL; + List *assignedSqlTaskList = NIL; + ListCell *assignedSqlTaskCell = NULL; + + /* create sql tasks for the job, and prune redundant data fetch tasks */ + if (job->subqueryPushdown) + { + sqlTaskList = SubquerySqlTaskList(job); + } + else + { + sqlTaskList = SqlTaskList(job); + } + + sqlTaskList = PruneSqlTaskDependencies(sqlTaskList); + + /* + * We first assign sql and merge tasks to worker nodes. Next, we assign + * sql tasks' data fetch dependencies. + */ + assignedSqlTaskList = AssignTaskList(sqlTaskList); + AssignDataFetchDependencies(assignedSqlTaskList); + + /* now assign merge task's data fetch dependencies */ + foreach(assignedSqlTaskCell, assignedSqlTaskList) + { + Task *assignedSqlTask = (Task *) lfirst(assignedSqlTaskCell); + List *assignedMergeTaskList = FindDependedMergeTaskList(assignedSqlTask); + + AssignDataFetchDependencies(assignedMergeTaskList); + } + + /* + * If we have a MapMerge job, the map tasks in this job wrap around the + * SQL tasks and their assignments. + */ + if (CitusIsA(job, MapMergeJob)) + { + MapMergeJob *mapMergeJob = (MapMergeJob *) job; + uint32 taskIdIndex = TaskListHighestTaskId(assignedSqlTaskList) + 1; + + List *mapTaskList = MapTaskList(mapMergeJob, assignedSqlTaskList); + List *mergeTaskList = MergeTaskList(mapMergeJob, mapTaskList, taskIdIndex); + + mapMergeJob->mapTaskList = mapTaskList; + mapMergeJob->mergeTaskList = mergeTaskList; + } + else + { + job->taskList = assignedSqlTaskList; + } + } + + return jobTree; +} + + +/* + * SubquerySqlTaskList creates a list of SQL tasks to execute the given subquery + * pushdown job. For this, it gets all range tables in the subquery tree, then + * walks over each range table in the list, gets shards for each range table, + * and prunes unneeded shards. Then for remaining shards, fragments are created + * and merged to create fragment combinations. For each created combination, the + * function builds a SQL task, and appends this task to a task list. + */ +static List * +SubquerySqlTaskList(Job *job) +{ + Query *subquery = job->jobQuery; + uint64 jobId = job->jobId; + List *sqlTaskList = NIL; + List *fragmentCombinationList = NIL; + List *opExpressionList = NIL; + List *queryList = NIL; + List *rangeTableList = NIL; + ListCell *fragmentCombinationCell = NULL; + ListCell *rangeTableCell = NULL; + ListCell *queryCell = NULL; + Node *whereClauseTree = NULL; + uint32 taskIdIndex = 1; /* 0 is reserved for invalid taskId */ + uint32 anchorRangeTableId = 0; + uint32 rangeTableIndex = 0; + const uint32 fragmentSize = sizeof(RangeTableFragment); + + /* find filters on partition columns */ + ExtractQueryWalker((Node *) subquery, &queryList); + foreach(queryCell, queryList) + { + Query *query = (Query *) lfirst(queryCell); + bool leafQuery = LeafQuery(query); + + if (!leafQuery) + { + continue; + } + + /* we have some filters on partition column */ + opExpressionList = PartitionColumnOpExpressionList(query); + if (opExpressionList != NIL) + { + break; + } + } + + /* get list of all range tables in subquery tree */ + ExtractRangeTableRelationWalker((Node *) subquery, &rangeTableList); + anchorRangeTableId = AnchorRangeTableId(rangeTableList); + + /* + * For each range table entry, first we prune shards for the relation + * referenced in the range table. Then we sort remaining shards and create + * fragments in this order and add these fragments to fragment combination + * list. + */ + foreach(rangeTableCell, rangeTableList) + { + RangeTblEntry *rangeTableEntry = (RangeTblEntry *) lfirst(rangeTableCell); + Oid relationId = rangeTableEntry->relid; + List *shardIntervalList = LoadShardIntervalList(relationId); + List *finalShardIntervalList = NIL; + ListCell *fragmentCombinationCell = NULL; + ShardInterval **sortedIntervalArray = NULL; + uint32 tableId = rangeTableIndex + 1; /* tableId starts from 1 */ + uint32 finalShardCount = 0; + uint32 shardIndex = 0; + + if (opExpressionList != NIL) + { + Var *partitionColumn = PartitionColumn(relationId, tableId); + List *whereClauseList = ReplaceColumnsInOpExpressionList(opExpressionList, + partitionColumn); + finalShardIntervalList = PruneShardList(relationId, tableId, whereClauseList, + shardIntervalList); + } + else + { + finalShardIntervalList = shardIntervalList; + } + + /* if all shards are pruned away, we return an empty task list */ + finalShardCount = list_length(finalShardIntervalList); + if (finalShardCount == 0) + { + return NIL; + } + + sortedIntervalArray = SortedShardIntervalArray(finalShardIntervalList); + fragmentCombinationCell = list_head(fragmentCombinationList); + + for (shardIndex = 0; shardIndex < finalShardCount; shardIndex++) + { + ShardInterval *shardInterval = sortedIntervalArray[shardIndex]; + + RangeTableFragment *shardFragment = palloc0(fragmentSize); + shardFragment->fragmentReference = &(shardInterval->shardId); + shardFragment->fragmentType = CITUS_RTE_RELATION; + shardFragment->rangeTableId = tableId; + + if (tableId == 1) + { + List *fragmentCombination = list_make1(shardFragment); + fragmentCombinationList = lappend(fragmentCombinationList, + fragmentCombination); + } + else + { + List *fragmentCombination = (List *) lfirst(fragmentCombinationCell); + fragmentCombination = lappend(fragmentCombination, shardFragment); + + /* get next fragment for the first relation list */ + fragmentCombinationCell = lnext(fragmentCombinationCell); + } + } + + rangeTableIndex++; + } + + /* + * Ands are made implicit during shard pruning, as predicate comparison and + * refutation depend on it being so. We need to make them explicit again so + * that the query string is generated as (...) AND (...) as opposed to + * (...), (...). + */ + whereClauseTree = (Node *) make_ands_explicit((List *) subquery->jointree->quals); + subquery->jointree->quals = whereClauseTree; + + /* create tasks from every fragment combination */ + foreach(fragmentCombinationCell, fragmentCombinationList) + { + List *fragmentCombination = (List *) lfirst(fragmentCombinationCell); + List *taskRangeTableList = NIL; + Query *taskQuery = copyObject(subquery); + Task *sqlTask = NULL; + StringInfo sqlQueryString = NULL; + + /* create tasks to fetch fragments required for the sql task */ + List *uniqueFragmentList = UniqueFragmentList(fragmentCombination); + List *dataFetchTaskList = DataFetchTaskList(jobId, taskIdIndex, + uniqueFragmentList); + int32 dataFetchTaskCount = list_length(dataFetchTaskList); + taskIdIndex += dataFetchTaskCount; + + ExtractRangeTableRelationWalker((Node *) taskQuery, &taskRangeTableList); + UpdateRangeTableAlias(taskRangeTableList, fragmentCombination); + + /* transform the updated task query to a SQL query string */ + sqlQueryString = makeStringInfo(); + pg_get_query_def(taskQuery, sqlQueryString); + + sqlTask = CreateBasicTask(jobId, taskIdIndex, SQL_TASK, sqlQueryString->data); + sqlTask->dependedTaskList = dataFetchTaskList; + + /* log the query string we generated */ + ereport(DEBUG4, (errmsg("generated sql query for job " UINT64_FORMAT + " and task %d", sqlTask->jobId, sqlTask->taskId), + errdetail("query string: \"%s\"", sqlQueryString->data))); + + sqlTask->anchorShardId = AnchorShardId(fragmentCombination, anchorRangeTableId); + + taskIdIndex++; + sqlTaskList = lappend(sqlTaskList, sqlTask); + } + + return sqlTaskList; +} + + +/* + * SqlTaskList creates a list of SQL tasks to execute the given job. For this, + * the function walks over each range table in the job's range table list, gets + * each range table's table fragments, and prunes unneeded table fragments. The + * function then joins table fragments from different range tables, and creates + * all fragment combinations. For each created combination, the function builds + * a SQL task, and appends this task to a task list. + */ +static List * +SqlTaskList(Job *job) +{ + List *sqlTaskList = NIL; + uint32 taskIdIndex = 1; /* 0 is reserved for invalid taskId */ + uint64 jobId = job->jobId; + bool anchorRangeTableBasedAssignment = false; + uint32 anchorRangeTableId = 0; + Node *whereClauseTree = NULL; + List *rangeTableFragmentsList = NIL; + List *fragmentCombinationList = NIL; + ListCell *fragmentCombinationCell = NULL; + + Query *jobQuery = job->jobQuery; + List *rangeTableList = jobQuery->rtable; + List *whereClauseList = (List *) jobQuery->jointree->quals; + List *dependedJobList = job->dependedJobList; + + /* + * If we don't depend on a hash partition, then we determine the largest + * table around which we build our queries. This reduces data fetching. + */ + bool dependsOnHashPartitionJob = DependsOnHashPartitionJob(job); + if (!dependsOnHashPartitionJob) + { + anchorRangeTableBasedAssignment = true; + anchorRangeTableId = AnchorRangeTableId(rangeTableList); + + Assert(anchorRangeTableId != 0); + Assert(anchorRangeTableId <= list_length(rangeTableList)); + } + + /* adjust our column old attributes for partition pruning to work */ + AdjustColumnOldAttributes(whereClauseList); + AdjustColumnOldAttributes(jobQuery->targetList); + + /* + * Ands are made implicit during shard pruning, as predicate comparison and + * refutation depend on it being so. We need to make them explicit again so + * that the query string is generated as (...) AND (...) as opposed to + * (...), (...). + */ + whereClauseTree = (Node *) make_ands_explicit((List *) jobQuery->jointree->quals); + jobQuery->jointree->quals = whereClauseTree; + + /* + * For each range table, we first get a list of their shards or merge tasks. + * We also apply partition pruning based on the selection criteria. If all + * range table fragments are pruned away, we return an empty task list. + */ + rangeTableFragmentsList = RangeTableFragmentsList(rangeTableList, whereClauseList, + dependedJobList); + if (rangeTableFragmentsList == NIL) + { + return NIL; + } + + /* + * We then generate fragment combinations according to how range tables join + * with each other (and apply join pruning). Each fragment combination then + * represents one SQL task's dependencies. + */ + fragmentCombinationList = FragmentCombinationList(rangeTableFragmentsList, + jobQuery, dependedJobList); + + fragmentCombinationCell = NULL; + foreach(fragmentCombinationCell, fragmentCombinationList) + { + List *fragmentCombination = (List *) lfirst(fragmentCombinationCell); + List *dataFetchTaskList = NIL; + int32 dataFetchTaskCount = 0; + StringInfo sqlQueryString = NULL; + Task *sqlTask = NULL; + Query *taskQuery = NULL; + List *fragmentRangeTableList = NIL; + + /* create tasks to fetch fragments required for the sql task */ + dataFetchTaskList = DataFetchTaskList(jobId, taskIdIndex, fragmentCombination); + dataFetchTaskCount = list_length(dataFetchTaskList); + taskIdIndex += dataFetchTaskCount; + + /* update range table entries with fragment aliases (in place) */ + taskQuery = copyObject(jobQuery); + fragmentRangeTableList = taskQuery->rtable; + UpdateRangeTableAlias(fragmentRangeTableList, fragmentCombination); + + /* transform the updated task query to a SQL query string */ + sqlQueryString = makeStringInfo(); + pg_get_query_def(taskQuery, sqlQueryString); + + sqlTask = CreateBasicTask(jobId, taskIdIndex, SQL_TASK, sqlQueryString->data); + sqlTask->dependedTaskList = dataFetchTaskList; + + /* log the query string we generated */ + ereport(DEBUG4, (errmsg("generated sql query for job " UINT64_FORMAT + " and task %d", sqlTask->jobId, sqlTask->taskId), + errdetail("query string: \"%s\"", sqlQueryString->data))); + + sqlTask->anchorShardId = INVALID_SHARD_ID; + if (anchorRangeTableBasedAssignment) + { + sqlTask->anchorShardId = AnchorShardId(fragmentCombination, + anchorRangeTableId); + } + + taskIdIndex++; + sqlTaskList = lappend(sqlTaskList, sqlTask); + } + + return sqlTaskList; +} + + +/* + * DependsOnHashPartitionJob checks if the given job depends on a hash + * partitioning job. + */ +static bool +DependsOnHashPartitionJob(Job *job) +{ + bool dependsOnHashPartitionJob = false; + List *dependedJobList = job->dependedJobList; + + uint32 dependedJobCount = (uint32) list_length(dependedJobList); + if (dependedJobCount > 0) + { + Job *dependedJob = (Job *) linitial(dependedJobList); + if (CitusIsA(dependedJob, MapMergeJob)) + { + MapMergeJob *mapMergeJob = (MapMergeJob *) dependedJob; + if (mapMergeJob->partitionType == HASH_PARTITION_TYPE) + { + dependsOnHashPartitionJob = true; + } + } + } + + return dependsOnHashPartitionJob; +} + + +/* + * AnchorRangeTableId determines the table around which we build our queries, + * and returns this table's range table id. We refer to this table as the anchor + * table, and make sure that the anchor table's shards are moved or cached only + * when absolutely necessary. + */ +static uint32 +AnchorRangeTableId(List *rangeTableList) +{ + uint32 anchorRangeTableId = 0; + uint64 maxTableSize = 0; + + /* + * We first filter anything but ordinary tables. Then, we pick the table(s) + * with the most number of shards as our anchor table. If multiple tables + * have the most number of shards, we have a draw. + */ + List *baseTableIdList = BaseRangeTableIdList(rangeTableList); + List *anchorTableIdList = AnchorRangeTableIdList(rangeTableList, baseTableIdList); + ListCell *anchorTableIdCell = NULL; + + int anchorTableIdCount = list_length(anchorTableIdList); + Assert(anchorTableIdCount > 0); + + if (anchorTableIdCount == 1) + { + anchorRangeTableId = (uint32) linitial_int(anchorTableIdList); + return anchorRangeTableId; + } + + /* + * If more than one table has the most number of shards, we break the draw + * by comparing table sizes and picking the table with the largest size. + */ + foreach(anchorTableIdCell, anchorTableIdList) + { + uint32 anchorTableId = (uint32) lfirst_int(anchorTableIdCell); + RangeTblEntry *tableEntry = rt_fetch(anchorTableId, rangeTableList); + uint64 tableSize = 0; + + List *shardList = LoadShardList(tableEntry->relid); + ListCell *shardCell = NULL; + + foreach(shardCell, shardList) + { + uint64 *shardIdPointer = (uint64 *) lfirst(shardCell); + uint64 shardId = (*shardIdPointer); + uint64 shardSize = ShardLength(shardId); + + tableSize += shardSize; + } + + if (tableSize > maxTableSize) + { + maxTableSize = tableSize; + anchorRangeTableId = anchorTableId; + } + } + + if (anchorRangeTableId == 0) + { + /* all tables have the same shard count and size 0, pick the first */ + anchorRangeTableId = (uint32) linitial_int(anchorTableIdList); + } + + return anchorRangeTableId; +} + + +/* + * BaseRangeTableIdList walks over range tables in the given range table list, + * finds range tables that correspond to base (non-repartitioned) tables, and + * returns these range tables' identifiers in a new list. + */ +static List * +BaseRangeTableIdList(List *rangeTableList) +{ + List *baseRangeTableIdList = NIL; + uint32 rangeTableId = 1; + + ListCell *rangeTableCell = NULL; + foreach(rangeTableCell, rangeTableList) + { + RangeTblEntry *rangeTableEntry = (RangeTblEntry *) lfirst(rangeTableCell); + if (GetRangeTblKind(rangeTableEntry) == CITUS_RTE_RELATION) + { + baseRangeTableIdList = lappend_int(baseRangeTableIdList, rangeTableId); + } + + rangeTableId++; + } + + return baseRangeTableIdList; +} + + +/* + * AnchorRangeTableIdList finds ordinary table(s) with the most number of shards + * and returns the corresponding range table id(s) in a list. + */ +static List * +AnchorRangeTableIdList(List *rangeTableList, List *baseRangeTableIdList) +{ + List *anchorTableIdList = NIL; + uint32 maxShardCount = 0; + ListCell *baseRangeTableIdCell = NULL; + + uint32 baseRangeTableCount = list_length(baseRangeTableIdList); + if (baseRangeTableCount == 1) + { + return baseRangeTableIdList; + } + + foreach(baseRangeTableIdCell, baseRangeTableIdList) + { + uint32 baseRangeTableId = (uint32) lfirst_int(baseRangeTableIdCell); + RangeTblEntry *tableEntry = rt_fetch(baseRangeTableId, rangeTableList); + List *shardList = LoadShardList(tableEntry->relid); + + uint32 shardCount = (uint32) list_length(shardList); + if (shardCount > maxShardCount) + { + anchorTableIdList = list_make1_int(baseRangeTableId); + maxShardCount = shardCount; + } + else if (shardCount == maxShardCount) + { + anchorTableIdList = lappend_int(anchorTableIdList, baseRangeTableId); + } + } + + return anchorTableIdList; +} + + +/* + * AdjustColumnOldAttributes adjust the old tableId (varnoold) and old columnId + * (varoattno), and sets them equal to the new values. We need this adjustment + * for partition pruning where we compare these columns with partition columns + * loaded from system catalogs. Since columns loaded from system catalogs always + * have the same old and new values, we also need to adjust column values here. + */ +static void +AdjustColumnOldAttributes(List *expressionList) +{ + List *columnList = pull_var_clause_default((Node *) expressionList); + ListCell *columnCell = NULL; + + foreach(columnCell, columnList) + { + Var *column = (Var *) lfirst(columnCell); + column->varnoold = column->varno; + column->varoattno = column->varattno; + } +} + + +/* + * RangeTableFragmentsList walks over range tables in the given range table list + * and for each table, the function creates a list of its fragments. A fragment + * in this list represents either a regular shard or a merge task. Once a list + * for each range table is constructed, the function applies partition pruning + * using the given where clause list. Then, the function appends the fragment + * list for each range table to a list of lists, and returns this list of lists. + */ +static List * +RangeTableFragmentsList(List *rangeTableList, List *whereClauseList, + List *dependedJobList) +{ + List *rangeTableFragmentsList = NIL; + uint32 rangeTableIndex = 0; + const uint32 fragmentSize = sizeof(RangeTableFragment); + + ListCell *rangeTableCell = NULL; + foreach(rangeTableCell, rangeTableList) + { + uint32 tableId = rangeTableIndex + 1; /* tableId starts from 1 */ + + RangeTblEntry *rangeTableEntry = (RangeTblEntry *) lfirst(rangeTableCell); + CitusRTEKind rangeTableKind = GetRangeTblKind(rangeTableEntry); + + if (rangeTableKind == CITUS_RTE_RELATION) + { + Oid relationId = rangeTableEntry->relid; + ListCell *shardIntervalCell = NULL; + List *shardFragmentList = NIL; + + List *shardIntervalList = LoadShardIntervalList(relationId); + List *prunedShardIntervalList = PruneShardList(relationId, tableId, + whereClauseList, + shardIntervalList); + + /* + * If we prune all shards for one table, query results will be empty. + * We can therefore return NIL for the task list here. + */ + if (prunedShardIntervalList == NIL) + { + return NIL; + } + + foreach(shardIntervalCell, prunedShardIntervalList) + { + ShardInterval *shardInterval = + (ShardInterval *) lfirst(shardIntervalCell); + + RangeTableFragment *shardFragment = palloc0(fragmentSize); + shardFragment->fragmentReference = &shardInterval->shardId; + shardFragment->fragmentType = CITUS_RTE_RELATION; + shardFragment->rangeTableId = tableId; + + shardFragmentList = lappend(shardFragmentList, shardFragment); + } + + rangeTableFragmentsList = lappend(rangeTableFragmentsList, + shardFragmentList); + } + else if (rangeTableKind == CITUS_RTE_REMOTE_QUERY) + { + MapMergeJob *dependedMapMergeJob = NULL; + List *mergeTaskFragmentList = NIL; + List *mergeTaskList = NIL; + ListCell *mergeTaskCell = NULL; + + Job *dependedJob = JobForRangeTable(dependedJobList, rangeTableEntry); + Assert(CitusIsA(dependedJob, MapMergeJob)); + + dependedMapMergeJob = (MapMergeJob *) dependedJob; + mergeTaskList = dependedMapMergeJob->mergeTaskList; + + /* if there are no tasks for the depended job, just return NIL */ + if (mergeTaskList == NIL) + { + return NIL; + } + + foreach(mergeTaskCell, mergeTaskList) + { + Task *mergeTask = (Task *) lfirst(mergeTaskCell); + + RangeTableFragment *mergeTaskFragment = palloc0(fragmentSize); + mergeTaskFragment->fragmentReference = mergeTask; + mergeTaskFragment->fragmentType = CITUS_RTE_REMOTE_QUERY; + mergeTaskFragment->rangeTableId = tableId; + + mergeTaskFragmentList = lappend(mergeTaskFragmentList, mergeTaskFragment); + } + + rangeTableFragmentsList = lappend(rangeTableFragmentsList, + mergeTaskFragmentList); + } + + rangeTableIndex++; + } + + return rangeTableFragmentsList; +} + + +/* + * PruneShardList prunes shard intervals from given list based on the selection criteria, + * and returns remaining shard intervals in another list. + */ +List * +PruneShardList(Oid relationId, Index tableId, List *whereClauseList, + List *shardIntervalList) +{ + List *remainingShardList = NIL; + ListCell *shardIntervalCell = NULL; + List *restrictInfoList = NIL; + Node *baseConstraint = NULL; + + Var *partitionColumn = PartitionColumn(relationId, tableId); + char partitionMethod = PartitionMethod(relationId); + + /* build the filter clause list for the partition method */ + if (partitionMethod == DISTRIBUTE_BY_HASH) + { + Node *hashedNode = HashableClauseMutator((Node *) whereClauseList, + partitionColumn); + + List *hashedClauseList = (List *) hashedNode; + restrictInfoList = BuildRestrictInfoList(hashedClauseList); + } + else + { + restrictInfoList = BuildRestrictInfoList(whereClauseList); + } + + /* override the partition column for hash partitioning */ + if (partitionMethod == DISTRIBUTE_BY_HASH) + { + partitionColumn = MakeInt4Column(); + } + + /* build the base expression for constraint */ + baseConstraint = BuildBaseConstraint(partitionColumn); + + /* walk over shard list and check if shards can be pruned */ + foreach(shardIntervalCell, shardIntervalList) + { + ShardInterval *shardInterval = (ShardInterval *) lfirst(shardIntervalCell); + List *constraintList = NIL; + bool shardPruned = false; + + if (shardInterval->minValueExists && shardInterval->maxValueExists) + { + /* set the min/max values in the base constraint */ + UpdateConstraint(baseConstraint, shardInterval); + constraintList = list_make1(baseConstraint); + + shardPruned = predicate_refuted_by(constraintList, restrictInfoList); + } + + if (shardPruned) + { + ereport(DEBUG2, (errmsg("predicate pruning for shardId " + UINT64_FORMAT, shardInterval->shardId))); + } + else + { + remainingShardList = lappend(remainingShardList, shardInterval); + } + } + + return remainingShardList; +} + + +/* + * BuildBaseConstraint builds and returns a base constraint. This constraint + * implements an expression in the form of (column <= max && column >= min), + * where column is the partition key, and min and max values represent a shard's + * min and max values. These shard values are filled in after the constraint is + * built. + */ +Node * +BuildBaseConstraint(Var *column) +{ + Node *baseConstraint = NULL; + OpExpr *lessThanExpr = NULL; + OpExpr *greaterThanExpr = NULL; + + /* Build these expressions with only one argument for now */ + lessThanExpr = MakeOpExpression(column, BTLessEqualStrategyNumber); + greaterThanExpr = MakeOpExpression(column, BTGreaterEqualStrategyNumber); + + /* Build base constaint as an and of two qual conditions */ + baseConstraint = make_and_qual((Node *) lessThanExpr, (Node *) greaterThanExpr); + + return baseConstraint; +} + + +/* + * MakeOpExpression builds an operator expression node. This operator expression + * implements the operator clause as defined by the variable and the strategy + * number. + */ +OpExpr * +MakeOpExpression(Var *variable, int16 strategyNumber) +{ + Oid typeId = variable->vartype; + Oid typeModId = variable->vartypmod; + Oid collationId = variable->varcollid; + + OperatorCacheEntry *operatorCacheEntry = NULL; + Oid accessMethodId = BTREE_AM_OID; + Oid operatorId = InvalidOid; + Oid operatorClassInputType = InvalidOid; + Const *constantValue = NULL; + OpExpr *expression = NULL; + char typeType = 0; + + operatorCacheEntry = LookupOperatorByType(typeId, accessMethodId, strategyNumber); + + operatorId = operatorCacheEntry->operatorId; + operatorClassInputType = operatorCacheEntry->operatorClassInputType; + typeType = operatorCacheEntry->typeType; + + /* + * Relabel variable if input type of default operator class is not equal to + * the variable type. Note that we don't relabel the variable if the default + * operator class variable type is a pseudo-type. + */ + if (operatorClassInputType != typeId && typeType != TYPTYPE_PSEUDO) + { + variable = (Var *) makeRelabelType((Expr *) variable, operatorClassInputType, + -1, collationId, COERCE_IMPLICIT_CAST); + } + + constantValue = makeNullConst(operatorClassInputType, typeModId, collationId); + + /* Now make the expression with the given variable and a null constant */ + expression = (OpExpr *) make_opclause(operatorId, + InvalidOid, /* no result type yet */ + false, /* no return set */ + (Expr *) variable, + (Expr *) constantValue, + InvalidOid, collationId); + + /* Set implementing function id and result type */ + expression->opfuncid = get_opcode(operatorId); + expression->opresulttype = get_func_rettype(expression->opfuncid); + + return expression; +} + + +/* + * LookupOperatorByType is a wrapper around GetOperatorByType(), + * operatorClassInputType() and get_typtype() functions that uses a cache to avoid + * multiple lookups of operators and its related fields within a single session by + * their types, access methods and strategy numbers. + * LookupOperatorByType function errors out if it cannot find corresponding + * default operator class with the given parameters on the system catalogs. + */ +static OperatorCacheEntry * +LookupOperatorByType(Oid typeId, Oid accessMethodId, int16 strategyNumber) +{ + OperatorCacheEntry *matchingCacheEntry = NULL; + ListCell *cacheEntryCell = NULL; + + /* search the cache */ + foreach(cacheEntryCell, OperatorCache) + { + OperatorCacheEntry *cacheEntry = lfirst(cacheEntryCell); + + if ((cacheEntry->typeId == typeId) && + (cacheEntry->accessMethodId == accessMethodId) && + (cacheEntry->strategyNumber == strategyNumber)) + { + matchingCacheEntry = cacheEntry; + break; + } + } + + /* if not found in the cache, call GetOperatorByType and put the result in cache */ + if (matchingCacheEntry == NULL) + { + MemoryContext oldContext = NULL; + Oid operatorClassId = GetDefaultOpClass(typeId, accessMethodId); + Oid operatorId = InvalidOid; + Oid operatorClassInputType = InvalidOid; + char typeType = InvalidOid; + + if (operatorClassId == InvalidOid) + { + /* if operatorId is invalid, error out */ + ereport(ERROR, (errmsg("cannot find default operator class for type:%d," + " access method: %d", typeId, accessMethodId))); + } + + /* fill the other fields to the cache */ + operatorId = GetOperatorByType(typeId, accessMethodId, strategyNumber); + operatorClassInputType = get_opclass_input_type(operatorClassId); + typeType = get_typtype(operatorClassInputType); + + /* make sure we've initialized CacheMemoryContext */ + if (CacheMemoryContext == NULL) + { + CreateCacheMemoryContext(); + } + + oldContext = MemoryContextSwitchTo(CacheMemoryContext); + + matchingCacheEntry = palloc0(sizeof(OperatorCacheEntry)); + matchingCacheEntry->typeId = typeId; + matchingCacheEntry->accessMethodId = accessMethodId; + matchingCacheEntry->strategyNumber = strategyNumber; + matchingCacheEntry->operatorId = operatorId; + matchingCacheEntry->operatorClassInputType = operatorClassInputType; + matchingCacheEntry->typeType = typeType; + + OperatorCache = lappend(OperatorCache, matchingCacheEntry); + + MemoryContextSwitchTo(oldContext); + } + + return matchingCacheEntry; +} + + +/* + * GetOperatorByType returns the operator oid for the given type, access method, + * and strategy number. + */ +static Oid +GetOperatorByType(Oid typeId, Oid accessMethodId, int16 strategyNumber) +{ + /* Get default operator class from pg_opclass */ + Oid operatorClassId = GetDefaultOpClass(typeId, accessMethodId); + + Oid operatorFamily = get_opclass_family(operatorClassId); + Oid operatorClassInputType = get_opclass_input_type(operatorClassId); + + /* Lookup for the operator with the desired input type in the family */ + Oid operatorId = get_opfamily_member(operatorFamily, operatorClassInputType, + operatorClassInputType, strategyNumber); + return operatorId; +} + + +/* + * SimpleOpExpression checks that given expression is a simple operator + * expression. A simple operator expression is a binary operator expression with + * operands of a var and a non-null constant. + */ +bool +SimpleOpExpression(Expr *clause) +{ + Node *leftOperand = NULL; + Node *rightOperand = NULL; + Const *constantClause = NULL; + + if (is_opclause(clause) && list_length(((OpExpr *) clause)->args) == 2) + { + leftOperand = get_leftop(clause); + rightOperand = get_rightop(clause); + } + else + { + return false; /* not a binary opclause */ + } + + if (IsA(rightOperand, Const) && IsA(leftOperand, Var)) + { + constantClause = (Const *) rightOperand; + } + else if (IsA(leftOperand, Const) && IsA(rightOperand, Var)) + { + constantClause = (Const *) leftOperand; + } + else + { + return false; + } + + if (constantClause->constisnull) + { + return false; + } + + return true; +} + + +/* + * HashableClauseMutator walks over the original where clause list, replaces + * hashable nodes with hashed versions and keeps other nodes as they are. + */ +static Node * +HashableClauseMutator(Node *originalNode, Var *partitionColumn) +{ + Node *newNode = NULL; + if (originalNode == NULL) + { + return NULL; + } + + if (IsA(originalNode, OpExpr)) + { + OpExpr *operatorExpression = (OpExpr *) originalNode; + bool hasPartitionColumn = false; + + Oid leftHashFunction = InvalidOid; + Oid rightHashFunction = InvalidOid; + bool hasHashFunction = get_op_hash_functions(operatorExpression->opno, + &leftHashFunction, + &rightHashFunction); + + bool simpleOpExpression = SimpleOpExpression((Expr *) operatorExpression); + if (simpleOpExpression) + { + hasPartitionColumn = OpExpressionContainsColumn(operatorExpression, + partitionColumn); + } + + if (hasHashFunction && hasPartitionColumn) + { + OpExpr *hashedOperatorExpression = + MakeHashedOperatorExpression((OpExpr *) originalNode); + newNode = (Node *) hashedOperatorExpression; + } + } + else if (IsA(originalNode, NullTest)) + { + NullTest *nullTest = (NullTest *) originalNode; + Var *column = NULL; + + Expr *nullTestOperand = nullTest->arg; + if (IsA(nullTestOperand, Var)) + { + column = (Var *) nullTestOperand; + } + + if ((column != NULL) && equal(column, partitionColumn) && + (nullTest->nulltesttype == IS_NULL)) + { + OpExpr *opExpressionWithZeroConst = MakeOpExpressionWithZeroConst(); + newNode = (Node *) opExpressionWithZeroConst; + } + } + else if (IsA(originalNode, ScalarArrayOpExpr)) + { + ereport(NOTICE, (errmsg("cannot use shard pruning with ANY (array expression)"), + errhint("Consider rewriting the expression with OR clauses."))); + } + + /* + * If this node is not hashable, continue walking down the expression tree + * to find and hash clauses which are eligible. + */ + if(newNode == NULL) + { + newNode = expression_tree_mutator(originalNode, HashableClauseMutator, + (void *) partitionColumn); + } + + return newNode; +} + + +/* + * OpExpressionContainsColumn checks if the operator expression contains the + * given partition column. We assume that given operator expression is a simple + * operator expression which means it is a binary operator expression with + * operands of a var and a non-null constant. + */ +static bool +OpExpressionContainsColumn(OpExpr *operatorExpression, Var *partitionColumn) +{ + Node *leftOperand = get_leftop((Expr *) operatorExpression); + Node *rightOperand = get_rightop((Expr *) operatorExpression); + Var *column = NULL; + + if (IsA(leftOperand, Var)) + { + column = (Var *) leftOperand; + } + else + { + column = (Var *) rightOperand; + } + + return equal(column, partitionColumn); +} + + +/* + * MakeHashedOperatorExpression creates a new operator expression with a column + * of int4 type and hashed constant value. + */ +static OpExpr * +MakeHashedOperatorExpression(OpExpr *operatorExpression) +{ + const Oid hashResultTypeId = INT4OID; + TypeCacheEntry *hashResultTypeEntry = NULL; + Oid operatorId = InvalidOid; + OpExpr *hashedExpression = NULL; + Var *hashedColumn = NULL; + Datum hashedValue = 0; + Const *hashedConstant = NULL; + FmgrInfo *hashFunction = NULL; + TypeCacheEntry *typeEntry = NULL; + + Node *leftOperand = get_leftop((Expr *) operatorExpression); + Node *rightOperand = get_rightop((Expr *) operatorExpression); + Const *constant = NULL; + + if (IsA(rightOperand, Const)) + { + constant = (Const *) rightOperand; + } + else + { + constant = (Const *) leftOperand; + } + + /* Load the operator from type cache */ + hashResultTypeEntry = lookup_type_cache(hashResultTypeId, TYPECACHE_EQ_OPR); + operatorId = hashResultTypeEntry->eq_opr; + + /* Get a column with int4 type */ + hashedColumn = MakeInt4Column(); + + /* Load the hash function from type cache */ + typeEntry = lookup_type_cache(constant->consttype, TYPECACHE_HASH_PROC_FINFO); + hashFunction = &(typeEntry->hash_proc_finfo); + if (!OidIsValid(hashFunction->fn_oid)) + { + ereport(ERROR, (errcode(ERRCODE_UNDEFINED_FUNCTION), + errmsg("could not identify a hash function for type %s", + format_type_be(constant->consttype)), + errdatatype(constant->consttype))); + } + + /* + * Note that any changes to PostgreSQL's hashing functions will change the + * new value created by this function. + */ + hashedValue = FunctionCall1(hashFunction, constant->constvalue); + hashedConstant = MakeInt4Constant(hashedValue); + + /* Now create the expression with modified partition column and hashed constant */ + hashedExpression = (OpExpr *) make_opclause(operatorId, + InvalidOid, /* no result type yet */ + false, /* no return set */ + (Expr *) hashedColumn, + (Expr *) hashedConstant, + InvalidOid, InvalidOid); + + /* Set implementing function id and result type */ + hashedExpression->opfuncid = get_opcode(operatorId); + hashedExpression->opresulttype = get_func_rettype(hashedExpression->opfuncid); + + return hashedExpression; +} + + +/* + * MakeInt4Column creates a column of int4 type with invalid table id and max + * attribute number. + */ +static Var * +MakeInt4Column() +{ + Index tableId = 0; + AttrNumber columnAttributeNumber = RESERVED_HASHED_COLUMN_ID; + Oid columnType = INT4OID; + int32 columnTypeMod = -1; + Oid columnCollationOid = InvalidOid; + Index columnLevelSup = 0; + + Var *int4Column = makeVar(tableId, columnAttributeNumber, columnType, + columnTypeMod, columnCollationOid, columnLevelSup); + return int4Column; +} + + +/* + * MakeInt4Constant creates a new constant of int4 type and assigns the given + * value as a constant value. + */ +static Const * +MakeInt4Constant(Datum constantValue) +{ + Oid constantType = INT4OID; + int32 constantTypeMode = -1; + Oid constantCollationId = InvalidOid; + int constantLength = sizeof(int32); + bool constantIsNull = false; + bool constantByValue = true; + + Const *int4Constant = makeConst(constantType, constantTypeMode, constantCollationId, + constantLength, constantValue, constantIsNull, + constantByValue); + return int4Constant; +} + + +/* + * MakeOpExpressionWithZeroConst creates a new operator expression with equality + * check to zero and returns it. + */ +static OpExpr * +MakeOpExpressionWithZeroConst() +{ + Var *int4Column = MakeInt4Column(); + OpExpr *operatorExpression = MakeOpExpression(int4Column, BTEqualStrategyNumber); + Const *constant = (Const *) get_rightop((Expr *) operatorExpression); + constant->constvalue = Int32GetDatum(0); + constant->constisnull = false; + + return operatorExpression; +} + + +/* + * BuildRestrictInfoList builds restrict info list using the selection criteria, + * and then return this list. Note that this function assumes there is only one + * relation for now. + */ +static List * +BuildRestrictInfoList(List *qualList) +{ + List *restrictInfoList = NIL; + ListCell *qualCell = NULL; + + foreach(qualCell, qualList) + { + RestrictInfo *restrictInfo = NULL; + Node *qualNode = (Node *) lfirst(qualCell); + + restrictInfo = make_simple_restrictinfo((Expr *) qualNode); + restrictInfoList = lappend(restrictInfoList, restrictInfo); + } + + return restrictInfoList; +} + + +/* Updates the base constraint with the given min/max values. */ +void +UpdateConstraint(Node *baseConstraint, ShardInterval *shardInterval) +{ + BoolExpr *andExpr = (BoolExpr *) baseConstraint; + Node *lessThanExpr = (Node *) linitial(andExpr->args); + Node *greaterThanExpr = (Node *) lsecond(andExpr->args); + + Node *minNode = get_rightop((Expr *) greaterThanExpr); /* right op */ + Node *maxNode = get_rightop((Expr *) lessThanExpr); /* right op */ + Const *minConstant = NULL; + Const *maxConstant = NULL; + + Assert(shardInterval != NULL); + Assert(shardInterval->minValueExists); + Assert(shardInterval->maxValueExists); + Assert(IsA(minNode, Const)); + Assert(IsA(maxNode, Const)); + + minConstant = (Const *) minNode; + maxConstant = (Const *) maxNode; + + minConstant->constvalue = shardInterval->minValue; + maxConstant->constvalue = shardInterval->maxValue; + + minConstant->constisnull = false; + maxConstant->constisnull = false; +} + + +/* + * FragmentCombinationList first builds an ordered sequence of range tables that + * join together. The function then iteratively adds fragments from each joined + * range table, and forms fragment combinations (lists) that cover all tables. + * While doing so, the function also performs join pruning to remove unnecessary + * fragment pairs. Last, the function adds each fragment combination (list) to a + * list, and returns this list. + */ +static List * +FragmentCombinationList(List *rangeTableFragmentsList, Query *jobQuery, + List *dependedJobList) +{ + List *fragmentCombinationList = NIL; + JoinSequenceNode *joinSequenceArray = NULL; + List *fragmentCombinationQueue = NIL; + List *emptyList = NIL; + + /* find a sequence that joins the range tables in the list */ + joinSequenceArray = JoinSequenceArray(rangeTableFragmentsList, jobQuery, + dependedJobList); + + /* + * We use breadth-first search with pruning to create fragment combinations. + * For this, we first queue the root node (an empty combination), and then + * start traversing our search space. + */ + fragmentCombinationQueue = lappend(fragmentCombinationQueue, emptyList); + while (fragmentCombinationQueue != NIL) + { + List *fragmentCombination = NIL; + int32 joinSequenceIndex = 0; + uint32 tableId = 0; + List *tableFragments = NIL; + ListCell *tableFragmentCell = NULL; + int32 joiningTableId = NON_PRUNABLE_JOIN; + int32 joiningTableSequenceIndex = -1; + int32 rangeTableCount = 0; + + /* pop first element from the fragment queue */ + fragmentCombination = linitial(fragmentCombinationQueue); + fragmentCombinationQueue = list_delete_first(fragmentCombinationQueue); + + /* + * If this combination covered all range tables in a join sequence, add + * this combination to our result set. + */ + joinSequenceIndex = list_length(fragmentCombination); + rangeTableCount = list_length(rangeTableFragmentsList); + if (joinSequenceIndex == rangeTableCount) + { + fragmentCombinationList = lappend(fragmentCombinationList, + fragmentCombination); + continue; + } + + /* find the next range table to add to our search space */ + tableId = joinSequenceArray[joinSequenceIndex].rangeTableId; + tableFragments = FindRangeTableFragmentsList(rangeTableFragmentsList, tableId); + + /* resolve sequence index for the previous range table we join against */ + joiningTableId = joinSequenceArray[joinSequenceIndex].joiningRangeTableId; + if (joiningTableId != NON_PRUNABLE_JOIN) + { + int32 sequenceIndex = 0; + for (sequenceIndex = 0; sequenceIndex < rangeTableCount; sequenceIndex++) + { + JoinSequenceNode *joinSequenceNode = &joinSequenceArray[sequenceIndex]; + if (joinSequenceNode->rangeTableId == joiningTableId) + { + joiningTableSequenceIndex = sequenceIndex; + break; + } + } + + Assert(joiningTableSequenceIndex != -1); + } + + /* + * We walk over each range table fragment, and check if we can prune out + * this fragment joining with the existing fragment combination. If we + * can't prune away, we create a new fragment combination and add it to + * our search space. + */ + foreach(tableFragmentCell, tableFragments) + { + RangeTableFragment *tableFragment = lfirst(tableFragmentCell); + bool joinPrunable = false; + + if (joiningTableId != NON_PRUNABLE_JOIN) + { + RangeTableFragment *joiningTableFragment = + list_nth(fragmentCombination, joiningTableSequenceIndex); + + joinPrunable = JoinPrunable(joiningTableFragment, tableFragment); + } + + /* if join can't be pruned, extend fragment combination and search */ + if (!joinPrunable) + { + List *newFragmentCombination = list_copy(fragmentCombination); + newFragmentCombination = lappend(newFragmentCombination, tableFragment); + + fragmentCombinationQueue = lappend(fragmentCombinationQueue, + newFragmentCombination); + } + } + } + + return fragmentCombinationList; +} + + +/* + * JoinSequenceArray walks over the join nodes in the job query and constructs a join + * sequence containing an entry for each joined table. The function then returns an + * array of join sequence nodes, in which each node contains the id of a table in the + * range table list and the id of a preceding table with which it is joined, if any. + */ +static JoinSequenceNode * +JoinSequenceArray(List *rangeTableFragmentsList, Query *jobQuery, List *dependedJobList) +{ + List *rangeTableList = jobQuery->rtable; + uint32 rangeTableCount = (uint32) list_length(rangeTableList); + uint32 sequenceNodeSize = sizeof(JoinSequenceNode); + uint32 joinedTableCount = 0; + List *joinedTableList = NIL; + List *joinExprList = NIL; + ListCell *joinExprCell = NULL; + uint32 firstRangeTableId = 1; + JoinSequenceNode *joinSequenceArray = palloc0(rangeTableCount * sequenceNodeSize); + + joinExprList = JoinExprList(jobQuery->jointree); + + /* pick first range table as starting table for the join sequence */ + if (list_length(joinExprList) > 0) + { + JoinExpr *firstExpr = (JoinExpr *) linitial(joinExprList); + RangeTblRef *leftTableRef = (RangeTblRef *) firstExpr->larg; + firstRangeTableId = leftTableRef->rtindex; + } + else + { + /* when there are no joins, the join sequence contains a node for the table */ + firstRangeTableId = 1; + } + + joinSequenceArray[joinedTableCount].rangeTableId = firstRangeTableId; + joinSequenceArray[joinedTableCount].joiningRangeTableId = NON_PRUNABLE_JOIN; + joinedTableCount++; + + foreach (joinExprCell, joinExprList) + { + JoinExpr *joinExpr = (JoinExpr *) lfirst(joinExprCell); + JoinType joinType = joinExpr->jointype; + RangeTblRef *rightTableRef = (RangeTblRef *) joinExpr->rarg; + JoinSequenceNode *nextJoinSequenceNode = NULL; + uint32 nextRangeTableId = rightTableRef->rtindex; + ListCell *nextJoinClauseCell = NULL; + Index existingRangeTableId = 0; + bool applyJoinPruning = false; + + List *nextJoinClauseList = make_ands_implicit((Expr *) joinExpr->quals); + + /* + * If next join clause list is empty, the user tried a cartesian product + * between tables. We don't support this functionality, and error out. + */ + if (nextJoinClauseList == NIL) + { + ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("cannot perform distributed planning on this query"), + errdetail("Cartesian products are currently unsupported"))); + } + + /* + * We now determine if we can apply join pruning between existing range + * tables and this new one. + */ + foreach(nextJoinClauseCell, nextJoinClauseList) + { + OpExpr *nextJoinClause = (OpExpr *) lfirst(nextJoinClauseCell); + Var *leftColumn = LeftColumn(nextJoinClause); + Var *rightColumn = RightColumn(nextJoinClause); + Index leftRangeTableId = leftColumn->varno; + Index rightRangeTableId = rightColumn->varno; + bool leftPartitioned = false; + bool rightPartitioned = false; + + /* + * We have a table from the existing join list joining with the next + * table. First resolve the existing table's range table id. + */ + if (leftRangeTableId == nextRangeTableId) + { + existingRangeTableId = rightRangeTableId; + } + else + { + existingRangeTableId = leftRangeTableId; + } + + /* + * Then, we check if we can apply join pruning between the existing + * range table and this new one. For this, columns need to have the + * same type and be the partition column for their respective tables. + */ + if (leftColumn->vartype != rightColumn->vartype) + { + continue; + } + + /* + * Check if this is a broadcast outer join, meaning the inner table has only + * 1 shard. + * + * Broadcast outer join is a special case. In a left join, we want to join + * every fragment on the left with the one fragment on the right to ensure + * that all results from the left are included. As an optimization, we could + * perform these joins with any empty set instead of an actual fragment, but + * in any case they must not be pruned. + */ + if (IS_OUTER_JOIN(joinType)) + { + int innerRangeTableId = 0; + List * tableFragments = NIL; + int fragmentCount = 0; + + if (joinType == JOIN_RIGHT) + { + innerRangeTableId = existingRangeTableId; + } + else + { + /* + * Note: For a full join the logical planner ensures a 1-1 mapping, + * thus it is sufficient to check one side. + */ + innerRangeTableId = nextRangeTableId; + } + + tableFragments = FindRangeTableFragmentsList(rangeTableFragmentsList, + innerRangeTableId); + fragmentCount = list_length(tableFragments); + if (fragmentCount == 1) + { + continue; + } + } + + leftPartitioned = PartitionedOnColumn(leftColumn, rangeTableList, + dependedJobList); + rightPartitioned = PartitionedOnColumn(rightColumn, rangeTableList, + dependedJobList); + if (leftPartitioned && rightPartitioned) + { + /* make sure this join clause references only simple columns */ + CheckJoinBetweenColumns(nextJoinClause); + + applyJoinPruning = true; + break; + } + } + + /* set next joining range table's info in the join sequence */ + nextJoinSequenceNode = &joinSequenceArray[joinedTableCount]; + if (applyJoinPruning) + { + nextJoinSequenceNode->rangeTableId = nextRangeTableId; + nextJoinSequenceNode->joiningRangeTableId = (int32) existingRangeTableId; + } + else + { + nextJoinSequenceNode->rangeTableId = nextRangeTableId; + nextJoinSequenceNode->joiningRangeTableId = NON_PRUNABLE_JOIN; + } + + joinedTableList = lappend_int(joinedTableList, nextRangeTableId); + joinedTableCount++; + } + + return joinSequenceArray; +} + + +/* + * PartitionedOnColumn finds the given column's range table entry, and checks if + * that range table is partitioned on the given column. + */ +static bool +PartitionedOnColumn(Var *column, List *rangeTableList, List *dependedJobList) +{ + bool partitionedOnColumn = false; + Index rangeTableId = column->varno; + RangeTblEntry *rangeTableEntry = rt_fetch(rangeTableId, rangeTableList); + + CitusRTEKind rangeTableType = GetRangeTblKind(rangeTableEntry); + if (rangeTableType == CITUS_RTE_RELATION) + { + Oid relationId = rangeTableEntry->relid; + Var *partitionColumn = PartitionColumn(relationId, rangeTableId); + + if (partitionColumn->varattno == column->varattno) + { + partitionedOnColumn = true; + } + } + else if (rangeTableType == CITUS_RTE_REMOTE_QUERY) + { + Job *job = JobForRangeTable(dependedJobList, rangeTableEntry); + MapMergeJob *mapMergeJob = (MapMergeJob *) job; + Var *partitionColumn = NULL; + Var *remoteRelationColumn = NULL; + TargetEntry *targetEntry = NULL; + + /* + * The column's current attribute number is it's location in the target + * list for the table represented by the remote query. We retrieve this + * value from the target list to compare against the partition column + * as stored in the job. + */ + List *targetEntryList = job->jobQuery->targetList; + int32 columnIndex = column->varattno - 1; + Assert(columnIndex >= 0); + Assert(columnIndex < list_length(targetEntryList)); + + targetEntry = (TargetEntry *) list_nth(targetEntryList, columnIndex); + remoteRelationColumn = (Var *) targetEntry->expr; + Assert(IsA(remoteRelationColumn, Var)); + + /* retrieve the partition column for the job */ + partitionColumn = mapMergeJob->partitionColumn; + if (partitionColumn->varattno == remoteRelationColumn->varattno) + { + partitionedOnColumn = true; + } + } + + return partitionedOnColumn; +} + + +/* Checks that the join clause references only simple columns. */ +static void +CheckJoinBetweenColumns(OpExpr *joinClause) +{ + List *argumentList = joinClause->args; + Node *leftArgument = (Node *) linitial(argumentList); + Node *rightArgument = (Node *) lsecond(argumentList); + + NodeTag leftArgumentType = nodeTag(leftArgument); + NodeTag rightArgumentType = nodeTag(rightArgument); + + if (leftArgumentType != T_Var || rightArgumentType != T_Var) + { + ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("cannot perform local joins that involve expressions"), + errdetail("local joins can be performed between columns only"))); + } +} + + +/* + * FindRangeTableFragmentsList walks over the given list of range table fragments + * and, returns the one with the given table id. + */ +static List * +FindRangeTableFragmentsList(List *rangeTableFragmentsList, int tableId) +{ + List *foundTableFragments = NIL; + ListCell *rangeTableFragmentsCell = NULL; + + foreach(rangeTableFragmentsCell, rangeTableFragmentsList) + { + List *tableFragments = (List *) lfirst(rangeTableFragmentsCell); + if (tableFragments != NIL) + { + RangeTableFragment *tableFragment = + (RangeTableFragment*) linitial(tableFragments); + if (tableFragment->rangeTableId == tableId) + { + foundTableFragments = tableFragments; + break; + } + } + } + + return foundTableFragments; +} + + +/* + * JoinPrunable checks if a join between the given left and right fragments can + * be pruned away, without performing the actual join. To do this, the function + * checks if we have a hash repartition join. If we do, the function determines + * pruning based on partitionIds. Else if we have a merge repartition join, the + * function checks if the two fragments have disjoint intervals. + */ +static bool +JoinPrunable(RangeTableFragment *leftFragment, RangeTableFragment *rightFragment) +{ + bool joinPrunable = false; + bool overlap = false; + ShardInterval *leftFragmentInterval = NULL; + ShardInterval *rightFragmentInterval = NULL; + + /* + * If both range tables are remote queries, we then have a hash repartition + * join. In that case, we can just prune away this join if left and right + * hand side fragments have the same partitionId. + */ + if (leftFragment->fragmentType == CITUS_RTE_REMOTE_QUERY && + rightFragment->fragmentType == CITUS_RTE_REMOTE_QUERY) + { + Task *leftMergeTask = (Task *) leftFragment->fragmentReference; + Task *rightMergeTask = (Task *) rightFragment->fragmentReference; + + if (leftMergeTask->partitionId != rightMergeTask->partitionId) + { + ereport(DEBUG2, (errmsg("join prunable for task partitionId %u and %u", + leftMergeTask->partitionId, + rightMergeTask->partitionId))); + return true; + } + else + { + return false; + } + } + + /* + * We have a range (re)partition join. We now get shard intervals for both + * fragments, and then check if these intervals overlap. + */ + leftFragmentInterval = FragmentInterval(leftFragment); + rightFragmentInterval = FragmentInterval(rightFragment); + + overlap = ShardIntervalsOverlap(leftFragmentInterval, rightFragmentInterval); + if (!overlap) + { + if (log_min_messages <= DEBUG2 || client_min_messages <= DEBUG2) + { + StringInfo leftString = FragmentIntervalString(leftFragmentInterval); + StringInfo rightString = FragmentIntervalString(rightFragmentInterval); + + ereport(DEBUG2, (errmsg("join prunable for intervals %s and %s", + leftString->data, rightString->data))); + } + + joinPrunable = true; + } + + return joinPrunable; +} + + +/* + * FragmentInterval takes the given fragment, and determines the range of data + * covered by this fragment. The function then returns this range (interval). + */ +static ShardInterval * +FragmentInterval(RangeTableFragment *fragment) +{ + ShardInterval *fragmentInterval = NULL; + if (fragment->fragmentType == CITUS_RTE_RELATION) + { + uint64 *shardId = (uint64 *) fragment->fragmentReference; + + fragmentInterval = LoadShardInterval(*shardId); + } + else if (fragment->fragmentType == CITUS_RTE_REMOTE_QUERY) + { + Task *mergeTask = (Task *) fragment->fragmentReference; + + fragmentInterval = mergeTask->shardInterval; + } + + return fragmentInterval; +} + + +/* Checks if the given shard intervals have overlapping ranges. */ +bool +ShardIntervalsOverlap(ShardInterval *firstInterval, ShardInterval *secondInterval) +{ + Oid typeId = InvalidOid; + FmgrInfo *comparisonFunction = NULL; + bool nonOverlap = false; + + Datum firstMin = 0; + Datum firstMax = 0; + Datum secondMin = 0; + Datum secondMax = 0; + + typeId = firstInterval->valueTypeId; + comparisonFunction = GetFunctionInfo(typeId, BTREE_AM_OID, BTORDER_PROC); + + firstMin = firstInterval->minValue; + firstMax = firstInterval->maxValue; + secondMin = secondInterval->minValue; + secondMax = secondInterval->maxValue; + + /* + * We need to have min/max values for both intervals first. Then, we assume + * two intervals i1 = [min1, max1] and i2 = [min2, max2] do not overlap if + * (max1 < min2) or (max2 < min1). For details, please see the explanation + * on overlapping intervals at http://www.rgrjr.com/emacs/overlap.html. + */ + if (firstInterval->minValueExists && firstInterval->maxValueExists && + secondInterval->minValueExists && secondInterval->maxValueExists) + { + Datum firstDatum = CompareCall2(comparisonFunction, firstMax, secondMin); + Datum secondDatum = CompareCall2(comparisonFunction, secondMax, firstMin); + int firstComparison = DatumGetInt32(firstDatum); + int secondComparison = DatumGetInt32(secondDatum); + + if (firstComparison < 0 || secondComparison < 0) + { + nonOverlap = true; + } + } + + return (!nonOverlap); +} + + +/* + * FragmentIntervalString takes the given fragment interval, and converts this + * interval into its string representation for use in debug messages. + */ +static StringInfo +FragmentIntervalString(ShardInterval *fragmentInterval) +{ + StringInfo fragmentIntervalString = NULL; + Oid typeId = fragmentInterval->valueTypeId; + Oid outputFunctionId = InvalidOid; + bool typeVariableLength = false; + FmgrInfo *outputFunction = NULL; + char *minValueString = NULL; + char *maxValueString = NULL; + + Assert(fragmentInterval->minValueExists); + Assert(fragmentInterval->maxValueExists); + + outputFunction = (FmgrInfo *) palloc0(sizeof(FmgrInfo)); + getTypeOutputInfo(typeId, &outputFunctionId, &typeVariableLength); + fmgr_info(outputFunctionId, outputFunction); + + minValueString = OutputFunctionCall(outputFunction, fragmentInterval->minValue); + maxValueString = OutputFunctionCall(outputFunction, fragmentInterval->maxValue); + + fragmentIntervalString = makeStringInfo(); + appendStringInfo(fragmentIntervalString, "[%s,%s]", minValueString, maxValueString); + + return fragmentIntervalString; +} + + +/* + * UniqueFragmentList walks over the given relation fragment list, compares + * shard ids, eliminate duplicates and returns a new fragment list of unique + * shard ids. Note that this is a helper function for subquery pushdown, and it + * is used to prevent creating multiple data fetch tasks for same shards. + */ +static List * +UniqueFragmentList(List *fragmentList) +{ + List *uniqueFragmentList = NIL; + ListCell *fragmentCell = NULL; + + foreach(fragmentCell, fragmentList) + { + uint64 *shardId = NULL; + bool shardIdAlreadyAdded = false; + ListCell *uniqueFragmentCell = NULL; + + RangeTableFragment *fragment = (RangeTableFragment *) lfirst(fragmentCell); + Assert(fragment->fragmentType == CITUS_RTE_RELATION); + + shardId = fragment->fragmentReference; + + foreach(uniqueFragmentCell, uniqueFragmentList) + { + RangeTableFragment *uniqueFragment = + (RangeTableFragment *) lfirst(uniqueFragmentCell); + uint64 *uniqueShardId = uniqueFragment->fragmentReference; + + if (*shardId == *uniqueShardId) + { + shardIdAlreadyAdded = true; + break; + } + } + + if (!shardIdAlreadyAdded) + { + uniqueFragmentList = lappend(uniqueFragmentList, fragment); + } + } + + return uniqueFragmentList; +} + + +/* + * DataFetchTaskList builds a data fetch task for every shard in the given shard + * list, appends these data fetch tasks into a list, and returns this list. + */ +static List * +DataFetchTaskList(uint64 jobId, uint32 taskIdIndex, List *fragmentList) +{ + List *dataFetchTaskList = NIL; + ListCell *fragmentCell = NULL; + + foreach(fragmentCell, fragmentList) + { + RangeTableFragment *fragment = (RangeTableFragment *) lfirst(fragmentCell); + if (fragment->fragmentType == CITUS_RTE_RELATION) + { + uint64 *shardId = fragment->fragmentReference; + StringInfo shardFetchQueryString = ShardFetchQueryString(*shardId); + + Task *shardFetchTask = CreateBasicTask(jobId, taskIdIndex, SHARD_FETCH_TASK, + shardFetchQueryString->data); + shardFetchTask->shardId = (*shardId); + + dataFetchTaskList = lappend(dataFetchTaskList, shardFetchTask); + taskIdIndex++; + } + else if (fragment->fragmentType == CITUS_RTE_REMOTE_QUERY) + { + Task *mergeTask = (Task *) fragment->fragmentReference; + char *undefinedQueryString = NULL; + + /* create merge fetch task and have it depend on the merge task */ + Task *mergeFetchTask = CreateBasicTask(jobId, taskIdIndex, MERGE_FETCH_TASK, + undefinedQueryString); + mergeFetchTask->dependedTaskList = list_make1(mergeTask); + + dataFetchTaskList = lappend(dataFetchTaskList, mergeFetchTask); + taskIdIndex++; + } + } + + return dataFetchTaskList; +} + + +/* + * ShardFetchQueryString constructs a query string to fetch the given shard from + * the shards' placements. + */ +StringInfo +ShardFetchQueryString(uint64 shardId) +{ + StringInfo shardFetchQuery = NULL; + uint64 shardLength = ShardLength(shardId); + + /* construct two array strings for node names and port numbers */ + List *shardPlacements = FinalizedShardPlacementList(shardId); + StringInfo nodeNameArrayString = NodeNameArrayString(shardPlacements); + StringInfo nodePortArrayString = NodePortArrayString(shardPlacements); + + /* check storage type to create the correct query string */ + ShardInterval *shardInterval = LoadShardInterval(shardId); + char storageType = shardInterval->storageType; + char *shardTableName = NULL; + + /* + * If user specified a shard alias in pg_dist_shard, error out and display a + * message explaining the limitation. + */ + char *shardAliasName = LoadShardAlias(shardInterval->relationId, shardId); + if (shardAliasName != NULL) + { + ereport(ERROR, (errmsg("cannot fetch shard " UINT64_FORMAT, shardId), + errdetail("Fetching shards with aliases is currently " + "unsupported"))); + } + else + { + /* construct the shard name */ + char *tableName = get_rel_name(shardInterval->relationId); + shardTableName = pstrdup(tableName); + AppendShardIdToName(&shardTableName, shardId); + } + + shardFetchQuery = makeStringInfo(); + if (storageType == SHARD_STORAGE_TABLE || storageType == SHARD_STORAGE_RELAY || + storageType == SHARD_STORAGE_COLUMNAR) + { + appendStringInfo(shardFetchQuery, TABLE_FETCH_COMMAND, + shardTableName, shardLength, + nodeNameArrayString->data, nodePortArrayString->data); + } + else if (storageType == SHARD_STORAGE_FOREIGN) + { + appendStringInfo(shardFetchQuery, FOREIGN_FETCH_COMMAND, + shardTableName, shardLength, + nodeNameArrayString->data, nodePortArrayString->data); + } + + return shardFetchQuery; +} + + +/* + * NodeNameArrayString extracts the node names from the given node list, stores + * these node names in an array, and returns the array's string representation. + */ +static StringInfo +NodeNameArrayString(List *shardPlacementList) +{ + StringInfo nodeNameArrayString = NULL; + ListCell *shardPlacementCell = NULL; + + uint32 nodeNameCount = (uint32) list_length(shardPlacementList); + Datum *nodeNameArray = palloc0(nodeNameCount * sizeof(Datum)); + uint32 nodeNameIndex = 0; + + foreach(shardPlacementCell, shardPlacementList) + { + ShardPlacement *shardPlacement = (ShardPlacement *) lfirst(shardPlacementCell); + Datum nodeName = CStringGetDatum(shardPlacement->nodeName); + + nodeNameArray[nodeNameIndex] = nodeName; + nodeNameIndex++; + } + + nodeNameArrayString = DatumArrayString(nodeNameArray, nodeNameCount, CSTRINGOID); + + return nodeNameArrayString; +} + + +/* + * NodePortArrayString extracts the node ports from the given node list, stores + * these node ports in an array, and returns the array's string representation. + */ +static StringInfo +NodePortArrayString(List *shardPlacementList) +{ + StringInfo nodePortArrayString = NULL; + ListCell *shardPlacementCell = NULL; + + uint32 nodePortCount = (uint32) list_length(shardPlacementList); + Datum *nodePortArray = palloc0(nodePortCount * sizeof(Datum)); + uint32 nodePortIndex = 0; + + foreach(shardPlacementCell, shardPlacementList) + { + ShardPlacement *shardPlacement = (ShardPlacement *) lfirst(shardPlacementCell); + Datum nodePort = UInt32GetDatum(shardPlacement->nodePort); + + nodePortArray[nodePortIndex] = nodePort; + nodePortIndex++; + } + + nodePortArrayString = DatumArrayString(nodePortArray, nodePortCount, INT4OID); + + return nodePortArrayString; +} + + +/* Helper function to return a datum array's external string representation. */ +static StringInfo +DatumArrayString(Datum *datumArray, uint32 datumCount, Oid datumTypeId) +{ + StringInfo arrayStringInfo = NULL; + FmgrInfo *arrayOutFunction = NULL; + ArrayType *arrayObject = NULL; + Datum arrayObjectDatum = 0; + Datum arrayStringDatum = 0; + char *arrayString = NULL; + int16 typeLength = 0; + bool typeByValue = false; + char typeAlignment = 0; + + /* construct the array object from the given array */ + get_typlenbyvalalign(datumTypeId, &typeLength, &typeByValue, &typeAlignment); + arrayObject = construct_array(datumArray, datumCount, datumTypeId, + typeLength, typeByValue, typeAlignment); + arrayObjectDatum = PointerGetDatum(arrayObject); + + /* convert the array object to its string representation */ + arrayOutFunction = (FmgrInfo *) palloc0(sizeof(FmgrInfo)); + fmgr_info(ARRAY_OUT_FUNC_ID, arrayOutFunction); + + arrayStringDatum = FunctionCall1(arrayOutFunction, arrayObjectDatum); + arrayString = DatumGetCString(arrayStringDatum); + + arrayStringInfo = makeStringInfo(); + appendStringInfo(arrayStringInfo, "%s", arrayString); + + return arrayStringInfo; +} + + +/* + * CreateBasicTask creates a task, initializes fields that are common to each task, + * and returns the created task. + */ +static Task * +CreateBasicTask(uint64 jobId, uint32 taskId, TaskType taskType, char *queryString) +{ + Task *task = CitusMakeNode(Task); + task->jobId = jobId; + task->taskId = taskId; + task->taskType = taskType; + task->queryString = queryString; + + return task; +} + + +/* + * UpdateRangeTableAlias walks over each fragment in the given fragment list, + * and creates an alias that represents the fragment name to be used in the + * query. The function then updates the corresponding range table entry with + * this alias. + */ +static void +UpdateRangeTableAlias(List *rangeTableList, List *fragmentList) +{ + ListCell *fragmentCell = NULL; + foreach(fragmentCell, fragmentList) + { + RangeTableFragment *fragment = (RangeTableFragment *) lfirst(fragmentCell); + Index rangeTableId = fragment->rangeTableId; + RangeTblEntry *rangeTableEntry = rt_fetch(rangeTableId, rangeTableList); + + Alias *fragmentAlias = FragmentAlias(rangeTableEntry, fragment); + rangeTableEntry->alias = fragmentAlias; + } +} + + +/* + * FragmentAlias creates an alias structure that captures the table fragment's + * name on the worker node. Each fragment represents either a regular shard, or + * a merge task. + */ +static Alias * +FragmentAlias(RangeTblEntry *rangeTableEntry, RangeTableFragment *fragment) +{ + Alias *alias = NULL; + char *aliasName = NULL; + char *schemaName = NULL; + char *fragmentName = NULL; + + CitusRTEKind fragmentType = fragment->fragmentType; + if (fragmentType == CITUS_RTE_RELATION) + { + char *shardAliasName = NULL; + uint64 *shardId = fragment->fragmentReference; + + Oid relationId = rangeTableEntry->relid; + char *relationName = get_rel_name(relationId); + + /* + * If the table is not in the default namespace (public), we include it in + * the fragment alias. + */ + Oid schemaId = get_rel_namespace(relationId); + schemaName = get_namespace_name(schemaId); + if (strncmp(schemaName, "public", NAMEDATALEN) == 0) + { + schemaName = NULL; + } + + aliasName = relationName; + + /* + * If user specified a shard name in pg_dist_shard, use that name in alias. + * Otherwise, set shard name in alias to _. + */ + shardAliasName = LoadShardAlias(relationId, *shardId); + if (shardAliasName != NULL) + { + fragmentName = shardAliasName; + } + else + { + char *shardName = pstrdup(relationName); + AppendShardIdToName(&shardName, *shardId); + + fragmentName = shardName; + } + } + else if (fragmentType == CITUS_RTE_REMOTE_QUERY) + { + Task *mergeTask = (Task *) fragment->fragmentReference; + uint64 jobId = mergeTask->jobId; + uint32 taskId = mergeTask->taskId; + + StringInfo jobSchemaName = JobSchemaName(jobId); + StringInfo taskTableName = TaskTableName(taskId); + + StringInfo aliasNameString = makeStringInfo(); + appendStringInfo(aliasNameString, "%s.%s", + jobSchemaName->data, taskTableName->data); + + aliasName = aliasNameString->data; + fragmentName = taskTableName->data; + schemaName = jobSchemaName->data; + } + + /* + * We need to set the aliasname to relation name, as pg_get_query_def() uses + * the relation name to disambiguate column names from different tables. + */ + alias = rangeTableEntry->alias; + if (alias == NULL) + { + alias = makeNode(Alias); + alias->aliasname = aliasName; + } + + ModifyRangeTblExtraData(rangeTableEntry, CITUS_RTE_SHARD, + schemaName, fragmentName, NIL); + + return alias; +} + +/* + * AnchorShardId walks over each fragment in the given fragment list, finds the + * fragment that corresponds to the given anchor range tableId, and returns this + * fragment's shard identifier. Note that the given tableId must correspond to a + * base relation. + */ +static uint64 +AnchorShardId(List *fragmentList, uint32 anchorRangeTableId) +{ + uint64 anchorShardId = INVALID_SHARD_ID; + ListCell *fragmentCell = NULL; + + foreach(fragmentCell, fragmentList) + { + RangeTableFragment *fragment = (RangeTableFragment *) lfirst(fragmentCell); + if (fragment->rangeTableId == anchorRangeTableId) + { + uint64 *shardIdPointer = NULL; + Assert(fragment->fragmentType == CITUS_RTE_RELATION); + + shardIdPointer = (uint64 *) fragment->fragmentReference; + anchorShardId = (*shardIdPointer); + break; + } + } + + Assert(anchorShardId != INVALID_SHARD_ID); + return anchorShardId; +} + + +/* + * PruneSqlTaskDependencies iterates over each sql task from the given sql task + * list, and prunes away any data fetch tasks which are redundant or not needed + * for the completion of that task. Specifically the function prunes away data + * fetch tasks for the anchor shard and any merge-fetch tasks, as the task + * assignment algorithm ensures co-location of these tasks. + */ +static List * +PruneSqlTaskDependencies(List *sqlTaskList) +{ + ListCell *sqlTaskCell = NULL; + foreach(sqlTaskCell, sqlTaskList) + { + Task *sqlTask = (Task *) lfirst(sqlTaskCell); + List *dependedTaskList = sqlTask->dependedTaskList; + List *prunedDependedTaskList = NIL; + + ListCell *dependedTaskCell = NULL; + foreach(dependedTaskCell, dependedTaskList) + { + Task *dataFetchTask = (Task *) lfirst(dependedTaskCell); + + /* + * If we have a shard fetch task for the anchor shard, or if we have + * a merge fetch task, our task assignment algorithm makes sure that + * the sql task is colocated with the anchor shard / merge task. We + * can therefore prune out this data fetch task. + */ + if (dataFetchTask->taskType == SHARD_FETCH_TASK && + dataFetchTask->shardId != sqlTask->anchorShardId) + { + prunedDependedTaskList = lappend(prunedDependedTaskList, dataFetchTask); + } + else if (dataFetchTask->taskType == MERGE_FETCH_TASK) + { + Task *mergeTaskReference = NULL; + List *mergeFetchDependencyList = dataFetchTask->dependedTaskList; + Assert(list_length(mergeFetchDependencyList) == 1); + + mergeTaskReference = (Task *) linitial(mergeFetchDependencyList); + prunedDependedTaskList = lappend(prunedDependedTaskList, + mergeTaskReference); + + ereport(DEBUG2, (errmsg("pruning merge fetch taskId %d", + dataFetchTask->taskId), + errdetail("Creating dependency on merge taskId %d", + mergeTaskReference->taskId))); + } + } + + sqlTask->dependedTaskList = prunedDependedTaskList; + } + + return sqlTaskList; +} + + +/* + * MapTaskList creates a list of map tasks for the given MapMerge job. For this, + * the function walks over each filter task (sql task) in the given filter task + * list, and wraps this task with a map function call. The map function call + * repartitions the filter task's output according to MapMerge job's parameters. + */ +static List * +MapTaskList(MapMergeJob *mapMergeJob, List *filterTaskList) +{ + List *mapTaskList = NIL; + Query *filterQuery = mapMergeJob->job.jobQuery; + List *rangeTableList = filterQuery->rtable; + ListCell *filterTaskCell = NULL; + Var *partitionColumn = mapMergeJob->partitionColumn; + Oid partitionColumnType = partitionColumn->vartype; + int32 partitionColumnTypeMod = partitionColumn->vartypmod; + char *partitionColumnName = NULL; + + List *groupClauseList = filterQuery->groupClause; + if (groupClauseList != NIL) + { + List *targetEntryList = filterQuery->targetList; + List *groupTargetEntryList = GroupTargetEntryList(groupClauseList, + targetEntryList); + TargetEntry *groupByTargetEntry = (TargetEntry *) linitial(groupTargetEntryList); + + partitionColumnName = groupByTargetEntry->resname; + } + else + { + partitionColumnName = ColumnName(partitionColumn, rangeTableList); + } + + foreach(filterTaskCell, filterTaskList) + { + Task *filterTask = (Task *) lfirst(filterTaskCell); + uint64 jobId = filterTask->jobId; + uint32 taskId = filterTask->taskId; + Task *mapTask = NULL; + + /* wrap repartition query string around filter query string */ + StringInfo mapQueryString = makeStringInfo(); + char *filterQueryString = filterTask->queryString; + char *filterQueryEscapedText = quote_literal_cstr(filterQueryString); + + PartitionType partitionType = mapMergeJob->partitionType; + if (partitionType == RANGE_PARTITION_TYPE) + { + ShardInterval **intervalArray = mapMergeJob->sortedShardIntervalArray; + uint32 intervalCount = mapMergeJob->partitionCount; + + ArrayType *splitPointObject = SplitPointObject(intervalArray, intervalCount); + StringInfo splitPointString = SplitPointArrayString(splitPointObject, + partitionColumnType, + partitionColumnTypeMod); + + appendStringInfo(mapQueryString, RANGE_PARTITION_COMMAND, jobId, taskId, + filterQueryEscapedText, partitionColumnName, + partitionColumnType, splitPointString->data); + } + else + { + uint32 partitionCount = mapMergeJob->partitionCount; + + appendStringInfo(mapQueryString, HASH_PARTITION_COMMAND, jobId, taskId, + filterQueryEscapedText, partitionColumnName, + partitionColumnType, partitionCount); + } + + /* convert filter query task into map task */ + mapTask = filterTask; + mapTask->queryString = mapQueryString->data; + mapTask->taskType = MAP_TASK; + + mapTaskList = lappend(mapTaskList, mapTask); + } + + return mapTaskList; +} + + +/* + * ColumnName resolves the given column's name. The given column could belong to + * a regular table or to an intermediate table formed to execute a distributed + * query. + */ +static char * +ColumnName(Var *column, List *rangeTableList) +{ + char *columnName = NULL; + Index tableId = column->varno; + AttrNumber columnNumber = column->varattno; + RangeTblEntry *rangeTableEntry = rt_fetch(tableId, rangeTableList); + + CitusRTEKind rangeTableKind = GetRangeTblKind(rangeTableEntry); + if (rangeTableKind == CITUS_RTE_REMOTE_QUERY) + { + Alias *referenceNames = rangeTableEntry->eref; + List *columnNameList = referenceNames->colnames; + int columnIndex = columnNumber - 1; + + Value *columnValue = (Value *) list_nth(columnNameList, columnIndex); + columnName = strVal(columnValue); + } + else if (rangeTableKind == CITUS_RTE_RELATION) + { + Oid relationId = rangeTableEntry->relid; + columnName = get_attname(relationId, columnNumber); + } + + Assert(columnName != NULL); + return columnName; +} + + +/* + * SplitPointArrayString takes the array representation of the given split point + * object, and converts this array (and array's typed elements) to their string + * representations. + */ +static StringInfo +SplitPointArrayString(ArrayType *splitPointObject, Oid columnType, int32 columnTypeMod) +{ + StringInfo splitPointArrayString = NULL; + Datum splitPointDatum = PointerGetDatum(splitPointObject); + Oid outputFunctionId = InvalidOid; + bool typeVariableLength = false; + FmgrInfo *arrayOutFunction = NULL; + char *arrayOutputText = NULL; + char *arrayOutputEscapedText = NULL; + char *arrayOutTypeName = NULL; + + Oid arrayOutType = get_array_type(columnType); + if (arrayOutType == InvalidOid) + { + char *columnTypeName = format_type_be(columnType); + ereport(ERROR, (errmsg("cannot range repartition table on column type %s", + columnTypeName))); + } + + arrayOutFunction = (FmgrInfo *) palloc0(sizeof(FmgrInfo)); + getTypeOutputInfo(arrayOutType, &outputFunctionId, &typeVariableLength); + fmgr_info(outputFunctionId, arrayOutFunction); + + arrayOutputText = OutputFunctionCall(arrayOutFunction, splitPointDatum); + arrayOutputEscapedText = quote_literal_cstr(arrayOutputText); + + /* add an explicit cast to array's string representation */ + arrayOutTypeName = format_type_with_typemod(arrayOutType, columnTypeMod); + + splitPointArrayString = makeStringInfo(); + appendStringInfo(splitPointArrayString, "%s::%s", + arrayOutputEscapedText, arrayOutTypeName); + + return splitPointArrayString; +} + + +/* + * MergeTaskList creates a list of merge tasks for the given MapMerge job. While + * doing this, the function also establishes dependencies between each merge + * task and its downstream map task dependencies by creating "map fetch" tasks. + */ +static List * +MergeTaskList(MapMergeJob *mapMergeJob, List *mapTaskList, uint32 taskIdIndex) +{ + List *mergeTaskList = NIL; + uint64 jobId = mapMergeJob->job.jobId; + uint32 partitionCount = mapMergeJob->partitionCount; + uint32 partitionId = 0; + uint32 initialPartitionId = 0; + + /* build column name and column type arrays (table schema) */ + Query *filterQuery = mapMergeJob->job.jobQuery; + List *targetEntryList = filterQuery->targetList; + + /* if all map tasks were pruned away, return NIL for merge tasks */ + if (mapTaskList == NIL) + { + return NIL; + } + + /* + * XXX: We currently ignore the 0th partition bucket that range partitioning + * generates. This bucket holds all values less than the minimum value or + * NULLs, both of which we can currently ignore. However, when we support + * range re-partitioned OUTER joins, we will need these rows for the + * relation whose rows are retained in the OUTER join. + */ + initialPartitionId = 0; + if (mapMergeJob->partitionType == RANGE_PARTITION_TYPE) + { + initialPartitionId = 1; + partitionCount = partitionCount + 1; + } + + /* build merge tasks and their associated "map output fetch" tasks */ + for (partitionId = initialPartitionId; partitionId < partitionCount; partitionId++) + { + Task *mergeTask = NULL; + List *mapOutputFetchTaskList = NIL; + ListCell *mapTaskCell = NULL; + uint32 mergeTaskId = taskIdIndex; + + Query *reduceQuery = mapMergeJob->reduceQuery; + if (reduceQuery == NULL) + { + uint32 columnCount = (uint32) list_length(targetEntryList); + StringInfo columnNames = ColumnNameArrayString(columnCount, jobId); + StringInfo columnTypes = ColumnTypeArrayString(targetEntryList); + + StringInfo mergeQueryString = makeStringInfo(); + appendStringInfo(mergeQueryString, MERGE_FILES_INTO_TABLE_COMMAND, + jobId, taskIdIndex, columnNames->data, columnTypes->data); + + /* create merge task */ + mergeTask = CreateBasicTask(jobId, mergeTaskId, MERGE_TASK, + mergeQueryString->data); + } + else + { + StringInfo mergeTableQueryString = + MergeTableQueryString(taskIdIndex, targetEntryList); + StringInfo intermediateTableQueryString = + IntermediateTableQueryString(jobId, taskIdIndex, reduceQuery); + + StringInfo mergeAndRunQueryString= makeStringInfo(); + appendStringInfo(mergeAndRunQueryString, MERGE_FILES_AND_RUN_QUERY_COMMAND, + jobId, taskIdIndex, mergeTableQueryString->data, + intermediateTableQueryString->data); + + mergeTask = CreateBasicTask(jobId, mergeTaskId, MERGE_TASK, + mergeAndRunQueryString->data); + } + + mergeTask->partitionId = partitionId; + taskIdIndex++; + + /* create tasks to fetch map outputs to this merge task */ + foreach(mapTaskCell, mapTaskList) + { + Task *mapTask = (Task *) lfirst(mapTaskCell); + + /* we need node names for the query, and we'll resolve them later */ + char *undefinedQueryString = NULL; + Task *mapOutputFetchTask = CreateBasicTask(jobId, taskIdIndex, + MAP_OUTPUT_FETCH_TASK, + undefinedQueryString); + mapOutputFetchTask->partitionId = partitionId; + mapOutputFetchTask->upstreamTaskId = mergeTaskId; + mapOutputFetchTask->dependedTaskList = list_make1(mapTask); + taskIdIndex++; + + mapOutputFetchTaskList = lappend(mapOutputFetchTaskList, mapOutputFetchTask); + } + + /* merge task depends on completion of fetch tasks */ + mergeTask->dependedTaskList = mapOutputFetchTaskList; + + /* if range repartitioned, each merge task represents an interval */ + if (mapMergeJob->partitionType == RANGE_PARTITION_TYPE) + { + int32 mergeTaskIntervalId = partitionId - 1; + ShardInterval **mergeTaskIntervals = mapMergeJob->sortedShardIntervalArray; + Assert(mergeTaskIntervalId >= 0); + + mergeTask->shardInterval = mergeTaskIntervals[mergeTaskIntervalId]; + } + + mergeTaskList = lappend(mergeTaskList, mergeTask); + } + + return mergeTaskList; +} + + +/* + * ColumnNameArrayString creates a list of column names for a merged table, and + * outputs this list of column names in their (array) string representation. + */ +static StringInfo +ColumnNameArrayString(uint32 columnCount, uint64 generatingJobId) +{ + StringInfo columnNameArrayString = NULL; + Datum *columnNameArray = palloc0(columnCount * sizeof(Datum)); + uint32 columnNameIndex = 0; + + /* build list of intermediate column names, generated by given jobId */ + List *columnNameList = DerivedColumnNameList(columnCount, generatingJobId); + + ListCell *columnNameCell = NULL; + foreach(columnNameCell, columnNameList) + { + Value *columnNameValue = (Value *) lfirst(columnNameCell); + char *columnNameString = strVal(columnNameValue); + Datum columnName = CStringGetDatum(columnNameString); + + columnNameArray[columnNameIndex] = columnName; + columnNameIndex++; + } + + columnNameArrayString = DatumArrayString(columnNameArray, columnCount, CSTRINGOID); + + return columnNameArrayString; +} + + +/* + * ColumnTypeArrayString resolves a list of column types for a merged table, and + * outputs this list of column types in their (array) string representation. + */ +static StringInfo +ColumnTypeArrayString(List *targetEntryList) +{ + StringInfo columnTypeArrayString = NULL; + ListCell *targetEntryCell = NULL; + + uint32 columnCount = (uint32) list_length(targetEntryList); + Datum *columnTypeArray = palloc0(columnCount * sizeof(Datum)); + uint32 columnTypeIndex = 0; + + foreach(targetEntryCell, targetEntryList) + { + TargetEntry *targetEntry = (TargetEntry *) lfirst(targetEntryCell); + Node *columnExpression = (Node *) targetEntry->expr; + Oid columnTypeId = exprType(columnExpression); + int32 columnTypeMod = exprTypmod(columnExpression); + + char *columnTypeName = format_type_with_typemod(columnTypeId, columnTypeMod); + Datum columnType = CStringGetDatum(columnTypeName); + + columnTypeArray[columnTypeIndex] = columnType; + columnTypeIndex++; + } + + columnTypeArrayString = DatumArrayString(columnTypeArray, columnCount, CSTRINGOID); + + return columnTypeArrayString; +} + + +/* + * AssignTaskList assigns locations to given tasks based on dependencies between + * tasks and configured task assignment policies. The function also handles the + * case where multiple SQL tasks depend on the same merge task, and makes sure + * that this group of multiple SQL tasks and the merge task are assigned to the + * same location. + */ +static List * +AssignTaskList(List *sqlTaskList) +{ + List *assignedSqlTaskList = NIL; + Task *firstSqlTask = NULL; + bool hasAnchorShardId = false; + bool hasMergeTaskDependencies = false; + ListCell *sqlTaskCell = NULL; + List *primarySqlTaskList = NIL; + ListCell *primarySqlTaskCell = NULL; + List *constrainedSqlTaskList = NIL; + ListCell *constrainedSqlTaskCell = NULL; + + /* no tasks to assign */ + if (sqlTaskList == NIL) + { + return NIL; + } + + firstSqlTask = (Task *) linitial(sqlTaskList); + if (firstSqlTask->anchorShardId != INVALID_SHARD_ID) + { + hasAnchorShardId = true; + } + + /* + * If these SQL tasks don't depend on any merge tasks, we can assign each + * one independently of the other. We therefore go ahead and assign these + * SQL tasks using the "anchor shard based" assignment algorithms. + */ + hasMergeTaskDependencies = HasMergeTaskDependencies(sqlTaskList); + if (!hasMergeTaskDependencies) + { + Assert(hasAnchorShardId); + + assignedSqlTaskList = AssignAnchorShardTaskList(sqlTaskList); + + return assignedSqlTaskList; + } + + /* + * SQL tasks can depend on merge tasks in one of two ways: (1) each SQL task + * depends on merge task(s) that no other SQL task depends upon, (2) several + * SQL tasks depend on the same merge task(s) and all need to be assigned to + * the same worker node. To handle the second case, we first pick a primary + * SQL task among those that depend on the same merge task, and assign it. + */ + foreach(sqlTaskCell, sqlTaskList) + { + Task *sqlTask = (Task *) lfirst(sqlTaskCell); + List *mergeTaskList = FindDependedMergeTaskList(sqlTask); + + Task *firstMergeTask = (Task *) linitial(mergeTaskList); + if (!firstMergeTask->assignmentConstrained) + { + firstMergeTask->assignmentConstrained = true; + + primarySqlTaskList = lappend(primarySqlTaskList, sqlTask); + } + } + + if (hasAnchorShardId) + { + primarySqlTaskList = AssignAnchorShardTaskList(primarySqlTaskList); + } + else + { + primarySqlTaskList = AssignDualHashTaskList(primarySqlTaskList); + } + + /* propagate SQL task assignments to the merge tasks we depend upon */ + foreach(primarySqlTaskCell, primarySqlTaskList) + { + Task *sqlTask = (Task *) lfirst(primarySqlTaskCell); + List *mergeTaskList = FindDependedMergeTaskList(sqlTask); + + ListCell *mergeTaskCell = NULL; + foreach(mergeTaskCell, mergeTaskList) + { + Task *mergeTask = (Task *) lfirst(mergeTaskCell); + Assert(mergeTask->taskPlacementList == NIL); + + mergeTask->taskPlacementList = list_copy(sqlTask->taskPlacementList); + } + + assignedSqlTaskList = lappend(assignedSqlTaskList, sqlTask); + } + + /* + * If we had a set of SQL tasks depending on the same merge task, we only + * assigned one SQL task from that set. We call the assigned SQL task the + * primary, and note that the remaining SQL tasks are constrained by the + * primary's task assignment. We propagate the primary's task assignment in + * each set to the remaining (constrained) tasks. + */ + constrainedSqlTaskList = TaskListDifference(sqlTaskList, primarySqlTaskList); + + foreach(constrainedSqlTaskCell, constrainedSqlTaskList) + { + Task *sqlTask = (Task *) lfirst(constrainedSqlTaskCell); + List *mergeTaskList = FindDependedMergeTaskList(sqlTask); + List *mergeTaskPlacementList = NIL; + + ListCell *mergeTaskCell = NULL; + foreach(mergeTaskCell, mergeTaskList) + { + Task *mergeTask = (Task *) lfirst(mergeTaskCell); + + /* + * If we have more than one merge task, both of them should have the + * same task placement list. + */ + mergeTaskPlacementList = mergeTask->taskPlacementList; + Assert(mergeTaskPlacementList != NIL); + + ereport(DEBUG3, (errmsg("propagating assignment from merge task %d " + "to constrained sql task %d", + mergeTask->taskId, sqlTask->taskId))); + } + + sqlTask->taskPlacementList = list_copy(mergeTaskPlacementList); + + assignedSqlTaskList = lappend(assignedSqlTaskList, sqlTask); + } + + return assignedSqlTaskList; +} + + +/* + * HasMergeTaskDependencies checks if sql tasks in the given sql task list have + * any dependencies on merge tasks. If they do, the function returns true. + */ +static bool +HasMergeTaskDependencies(List *sqlTaskList) +{ + bool hasMergeTaskDependencies = false; + Task *sqlTask = (Task *) linitial(sqlTaskList); + List *dependedTaskList = sqlTask->dependedTaskList; + + ListCell *dependedTaskCell = NULL; + foreach(dependedTaskCell, dependedTaskList) + { + Task *dependedTask = (Task *) lfirst(dependedTaskCell); + if (dependedTask->taskType == MERGE_TASK) + { + hasMergeTaskDependencies = true; + break; + } + } + + return hasMergeTaskDependencies; +} + + +/* Return true if two tasks are equal, false otherwise. */ +bool +TasksEqual(const Task *a, const Task *b) +{ + Assert(CitusIsA(a, Task)); + Assert(CitusIsA(b, Task)); + + if (a->taskType != b->taskType) + { + return false; + } + if (a->jobId != b->jobId) + { + return false; + } + if (a->taskId != b->taskId) + { + return false; + } + + return true; +} + + +/* + * TaskListAppendUnique returns a list that contains the elements of the + * input task list and appends the input task parameter if it doesn't already + * exists the list. + */ +List * +TaskListAppendUnique(List *list, Task *task) +{ + if (TaskListMember(list, task)) + { + return list; + } + + return lappend(list, task); +} + + +/* + * TaskListConcatUnique append to list1 each member of list2 that isn't + * already in list1. Whether an element is already a member of the list + * is determined via TaskListMember(). + */ +List * +TaskListConcatUnique(List *list1, List *list2) +{ + ListCell *taskCell = NULL; + + foreach(taskCell, list2) + { + Task *currentTask = (Task *) lfirst(taskCell); + + if (!TaskListMember(list1, currentTask)) + { + list1 = lappend(list1, currentTask); + } + } + + return list1; +} + + +/* Is the passed in Task a member of the list. */ +bool +TaskListMember(const List *taskList, const Task *task) +{ + const ListCell *taskCell = NULL; + + foreach(taskCell, taskList) + { + if (TasksEqual((Task *) lfirst(taskCell), task)) + { + return true; + } + } + + return false; +} + + +/* + * TaskListDifference returns a list that contains all the tasks in taskList1 + * that are not in taskList2. The returned list is freshly allocated via + * palloc(), but the cells themselves point to the same objects as the cells + * of the input lists. + */ +List * +TaskListDifference(const List *list1, const List *list2) +{ + const ListCell *taskCell = NULL; + List *resultList = NIL; + + if (list2 == NIL) + { + return list_copy(list1); + } + + foreach(taskCell, list1) + { + if (!TaskListMember(list2, lfirst(taskCell))) + { + resultList = lappend(resultList, lfirst(taskCell)); + } + } + + return resultList; +} + + +/* + * TaskListUnion generate the union of two tasks lists. This is calculated by + * copying list1 via list_copy(), then adding to it all the members of list2 + * that aren't already in list1. + */ +List * +TaskListUnion(const List *list1, const List *list2) +{ + const ListCell *taskCell = NULL; + List *resultList = NIL; + + resultList = list_copy(list1); + + foreach(taskCell, list2) + { + if (!TaskListMember(resultList, lfirst(taskCell))) + { + resultList = lappend(resultList, lfirst(taskCell)); + } + } + + return resultList; +} + + +/* + * AssignAnchorShardTaskList assigns locations to the given tasks based on the + * configured task assignment policy. The distributed executor later sends these + * tasks to their assigned locations for remote execution. + */ +static List * +AssignAnchorShardTaskList(List *taskList) +{ + List *assignedTaskList = NIL; + + /* choose task assignment policy based on config value */ + if (TaskAssignmentPolicy == TASK_ASSIGNMENT_GREEDY) + { + assignedTaskList = GreedyAssignTaskList(taskList); + } + else if (TaskAssignmentPolicy == TASK_ASSIGNMENT_FIRST_REPLICA) + { + assignedTaskList = FirstReplicaAssignTaskList(taskList); + } + else if (TaskAssignmentPolicy == TASK_ASSIGNMENT_ROUND_ROBIN) + { + assignedTaskList = RoundRobinAssignTaskList(taskList); + } + + Assert(assignedTaskList != NIL); + return assignedTaskList; +} + + +/* + * GreedyAssignTaskList uses a greedy algorithm similar to Hadoop's, and assigns + * locations to the given tasks. The ideal assignment algorithm balances three + * properties: (a) determinism, (b) even load distribution, and (c) consistency + * across similar task lists. To maintain these properties, the algorithm sorts + * all its input lists. + */ +static List * +GreedyAssignTaskList(List *taskList) +{ + List *assignedTaskList = NIL; + List *activeShardPlacementLists = NIL; + uint32 assignedTaskCount = 0; + uint32 taskCount = list_length(taskList); + + /* get the worker node list and sort the list */ + List *workerNodeList = WorkerNodeList(); + workerNodeList = SortList(workerNodeList, CompareWorkerNodes); + + /* + * We first sort tasks by their anchor shard id. We then walk over each task + * in the sorted list, get the task's anchor shard id, and look up the shard + * placements (locations) for this shard id. Next, we sort the placements by + * their insertion time, and append them to a new list. + */ + taskList = SortList(taskList, CompareTasksByShardId); + activeShardPlacementLists = ActiveShardPlacementLists(taskList); + + while (assignedTaskCount < taskCount) + { + ListCell *workerNodeCell = NULL; + uint32 loopStartTaskCount = assignedTaskCount; + + /* walk over each node and check if we can assign a task to it */ + foreach(workerNodeCell, workerNodeList) + { + WorkerNode *workerNode = (WorkerNode *) lfirst(workerNodeCell); + + Task *assignedTask = GreedyAssignTask(workerNode, taskList, + activeShardPlacementLists); + if (assignedTask != NULL) + { + assignedTaskList = lappend(assignedTaskList, assignedTask); + assignedTaskCount++; + } + } + + /* if we could not assign any new tasks, avoid looping forever */ + if (assignedTaskCount == loopStartTaskCount) + { + uint32 remainingTaskCount = taskCount - assignedTaskCount; + ereport(ERROR, (errmsg("failed to assign %u task(s) to worker nodes", + remainingTaskCount))); + } + } + + return assignedTaskList; +} + + +/* + * GreedyAssignTask tries to assign a task to the given worker node. To do this, + * the function walks over tasks' anchor shard ids, and finds the first set of + * nodes the shards were replicated to. If any of these replica nodes and the + * given worker node match, the corresponding task is assigned to that node. If + * not, the function goes on to search the second set of replicas and so forth. + * + * Note that this function has side-effects; when the function assigns a new + * task, it overwrites the corresponding task list pointer. + */ +static Task * +GreedyAssignTask(WorkerNode *workerNode, List *taskList, List *activeShardPlacementLists) +{ + Task *assignedTask = NULL; + List *taskPlacementList = NIL; + ShardPlacement *primaryPlacement = NULL; + uint32 rotatePlacementListBy = 0; + uint32 replicaIndex = 0; + uint32 replicaCount = ShardReplicationFactor; + const char *workerName = workerNode->workerName; + const uint32 workerPort = workerNode->workerPort; + + while ((assignedTask == NULL) && (replicaIndex < replicaCount)) + { + /* walk over all tasks and try to assign one */ + ListCell *taskCell = NULL; + ListCell *placementListCell = NULL; + + forboth(taskCell, taskList, placementListCell, activeShardPlacementLists) + { + Task *task = (Task *) lfirst(taskCell); + List *placementList = (List *) lfirst(placementListCell); + ShardPlacement *placement = NULL; + uint32 placementCount = 0; + + /* check if we already assigned this task */ + if (task == NULL) + { + continue; + } + + /* check if we have enough replicas */ + placementCount = list_length(placementList); + if (placementCount <= replicaIndex) + { + continue; + } + + placement = (ShardPlacement *) list_nth(placementList, replicaIndex); + if ((strncmp(placement->nodeName, workerName, WORKER_LENGTH) == 0) && + (placement->nodePort == workerPort)) + { + /* we found a task to assign to the given worker node */ + assignedTask = task; + taskPlacementList = placementList; + rotatePlacementListBy = replicaIndex; + + /* overwrite task list to signal that this task is assigned */ + taskCell->data.ptr_value = NULL; + break; + } + } + + /* go over the next set of shard replica placements */ + replicaIndex++; + } + + /* if we found a task placement list, rotate and assign task placements */ + if (assignedTask != NULL) + { + taskPlacementList = LeftRotateList(taskPlacementList, rotatePlacementListBy); + assignedTask->taskPlacementList = taskPlacementList; + + primaryPlacement = (ShardPlacement *) linitial(assignedTask->taskPlacementList); + ereport(DEBUG3, (errmsg("assigned task %u to node %s:%u", assignedTask->taskId, + primaryPlacement->nodeName, + primaryPlacement->nodePort))); + } + + return assignedTask; +} + + +/* + * FirstReplicaAssignTaskList assigns locations to the given tasks simply by + * looking at placements for a given shard. A particular task's assignments are + * then ordered by the insertion order of the relevant placements rows. In other + * words, a task for a specific shard is simply assigned to the first replica + * for that shard. This algorithm is extremely simple and intended for use when + * a customer has placed shards carefully and wants strong guarantees about + * which shards will be used by what nodes (i.e. for stronger memory residency + * guarantees). + */ +List * +FirstReplicaAssignTaskList(List *taskList) +{ + /* No additional reordering need take place for this algorithm */ + List * (*reorderFunction)(Task *, List *) = NULL; + + taskList = ReorderAndAssignTaskList(taskList, reorderFunction); + + return taskList; +} + + +/* + * RoundRobinAssignTaskList uses a round-robin algorithm to assign locations to + * the given tasks. An ideal round-robin implementation requires keeping shared + * state for task assignments; and we instead approximate our implementation by + * relying on the sequentially increasing jobId. For each task, we mod its jobId + * by the number of active shard placements, and ensure that we rotate between + * these placements across subsequent queries. + */ +static List * +RoundRobinAssignTaskList(List *taskList) +{ + taskList = ReorderAndAssignTaskList(taskList, RoundRobinReorder); + + return taskList; +} + +/* + * RoundRobinReorder implements the core of the round-robin assignment policy. + * It takes a task and placement list and rotates a copy of the placement list + * based on the task's jobId. The rotated copy is returned. + */ +static List * +RoundRobinReorder(Task *task, List *placementList) +{ + uint64 jobId = task->jobId; + uint32 activePlacementCount = list_length(placementList); + uint32 roundRobinIndex = (jobId % activePlacementCount); + + placementList = LeftRotateList(placementList, roundRobinIndex); + + return placementList; +} + + +/* + * ReorderAndAssignTaskList finds the placements for a task based on its anchor + * shard id and then sorts them by insertion time. If reorderFunction is given, + * it is used to reorder the placements list in a custom fashion (for instance, + * by rotation or shuffling). Returns the task list with placements assigned. + */ +static List * +ReorderAndAssignTaskList(List *taskList, List * (*reorderFunction)(Task *, List *)) +{ + List *assignedTaskList = NIL; + List *activeShardPlacementLists = NIL; + ListCell *taskCell = NULL; + ListCell *placementListCell = NULL; + uint32 unAssignedTaskCount = 0; + + /* + * We first sort tasks by their anchor shard id. We then sort placements for + * each anchor shard by the placement's insertion time. Note that we sort + * these lists just to make our policy more deterministic. + */ + taskList = SortList(taskList, CompareTasksByShardId); + activeShardPlacementLists = ActiveShardPlacementLists(taskList); + + forboth(taskCell, taskList, placementListCell, activeShardPlacementLists) + { + Task *task = (Task *) lfirst(taskCell); + List *placementList = (List *) lfirst(placementListCell); + + /* inactive placements are already filtered out */ + uint32 activePlacementCount = list_length(placementList); + if (activePlacementCount > 0) + { + ShardPlacement *primaryPlacement = NULL; + + if (reorderFunction != NULL) + { + placementList = reorderFunction(task, placementList); + } + task->taskPlacementList = placementList; + + primaryPlacement = (ShardPlacement *) linitial(task->taskPlacementList); + ereport(DEBUG3, (errmsg("assigned task %u to node %s:%u", task->taskId, + primaryPlacement->nodeName, + primaryPlacement->nodePort))); + + assignedTaskList = lappend(assignedTaskList, task); + } + else + { + unAssignedTaskCount++; + } + } + + /* if we have unassigned tasks, error out */ + if (unAssignedTaskCount > 0) + { + ereport(ERROR, (errmsg("failed to assign %u task(s) to worker nodes", + unAssignedTaskCount))); + } + + return assignedTaskList; +} + + +/* Helper function to compare two tasks by their anchor shardId. */ +static int +CompareTasksByShardId(const void *leftElement, const void *rightElement) +{ + const Task *leftTask = *((const Task **) leftElement); + const Task *rightTask = *((const Task **) rightElement); + + uint64 leftShardId = leftTask->anchorShardId; + uint64 rightShardId = rightTask->anchorShardId; + + /* we compare 64-bit integers, instead of casting their difference to int */ + if (leftShardId > rightShardId) + { + return 1; + } + else if (leftShardId < rightShardId) + { + return -1; + } + else + { + return 0; + } +} + + +/* + * ActiveShardPlacementLists finds the active shard placement list for each task in + * the given task list, sorts each shard placement list by tuple insertion time, + * and adds the sorted placement list into a new list of lists. The function also + * ensures a one-to-one mapping between each placement list in the new list of + * lists and each task in the given task list. + */ +static List * +ActiveShardPlacementLists(List *taskList) +{ + List *shardPlacementLists = NIL; + ListCell *taskCell = NULL; + + foreach(taskCell, taskList) + { + Task *task = (Task *) lfirst(taskCell); + uint64 anchorShardId = task->anchorShardId; + + List *shardPlacementList = FinalizedShardPlacementList(anchorShardId); + + /* filter out shard placements that reside in inactive nodes */ + List *activeShardPlacementList = ActivePlacementList(shardPlacementList); + + /* sort shard placements by their insertion time */ + activeShardPlacementList = SortList(activeShardPlacementList, CompareShardPlacements); + shardPlacementLists = lappend(shardPlacementLists, activeShardPlacementList); + } + + return shardPlacementLists; +} + + +/* + * CompareShardPlacements compares two shard placements by their tuple oid; this + * oid reflects the tuple's insertion order into pg_dist_shard_placement. + */ +int +CompareShardPlacements(const void *leftElement, const void *rightElement) +{ + const ShardPlacement *leftPlacement = *((const ShardPlacement **) leftElement); + const ShardPlacement *rightPlacement = *((const ShardPlacement **) rightElement); + + Oid leftTupleOid = leftPlacement->tupleOid; + Oid rightTupleOid = rightPlacement->tupleOid; + + /* tuples that are inserted earlier appear first */ + int tupleOidDiff = leftTupleOid - rightTupleOid; + return tupleOidDiff; +} + + +/* + * ActivePlacementList walks over shard placements in the given list, and finds + * the corresponding worker node for each placement. The function then checks if + * that worker node is active, and if it is, appends the placement to a new list. + * The function last returns the new placement list. + */ +static List * +ActivePlacementList(List *placementList) +{ + List *activePlacementList = NIL; + ListCell *placementCell = NULL; + + foreach(placementCell, placementList) + { + ShardPlacement *placement = (ShardPlacement *) lfirst(placementCell); + bool workerNodeActive = false; + + /* check if the worker node for this shard placement is active */ + workerNodeActive = WorkerNodeActive(placement->nodeName, placement->nodePort); + if (workerNodeActive) + { + activePlacementList = lappend(activePlacementList, placement); + } + } + + return activePlacementList; +} + + +/* + * LeftRotateList returns a copy of the given list that has been cyclically + * shifted to the left by the given rotation count. For this, the function + * repeatedly moves the list's first element to the end of the list, and + * then returns the newly rotated list. + */ +static List * +LeftRotateList(List *list, uint32 rotateCount) +{ + List *rotatedList = list_copy(list); + + uint32 rotateIndex = 0; + for (rotateIndex = 0; rotateIndex < rotateCount; rotateIndex++) + { + void *firstElement = linitial(rotatedList); + + rotatedList = list_delete_first(rotatedList); + rotatedList = lappend(rotatedList, firstElement); + } + + return rotatedList; +} + + +/* + * FindDependedMergeTaskList walks over the given task's depended task list, + * finds the merge tasks in the list, and returns those found tasks in a new + * list. + */ +static List * +FindDependedMergeTaskList(Task *sqlTask) +{ + List *dependedMergeTaskList = NIL; + List *dependedTaskList = sqlTask->dependedTaskList; + + ListCell *dependedTaskCell = NULL; + foreach(dependedTaskCell, dependedTaskList) + { + Task *dependedTask = (Task *) lfirst(dependedTaskCell); + if (dependedTask->taskType == MERGE_TASK) + { + dependedMergeTaskList = lappend(dependedMergeTaskList, dependedTask); + } + } + + return dependedMergeTaskList; +} + + +/* + * AssignDualHashTaskList uses a round-robin algorithm to assign locations to + * tasks; these tasks don't have any anchor shards and instead operate on (hash + * repartitioned) merged tables. + */ +static List * +AssignDualHashTaskList(List *taskList) +{ + List *assignedTaskList = NIL; + ListCell *taskCell = NULL; + Task *firstTask = (Task *) linitial(taskList); + uint64 jobId = firstTask->jobId; + uint32 assignedTaskIndex = 0; + + /* + * We start assigning tasks at an index determined by the jobId. This way, + * if subsequent jobs have a small number of tasks, we won't allocate the + * tasks to the same worker repeatedly. + */ + List *workerNodeList = WorkerNodeList(); + uint32 workerNodeCount = (uint32) list_length(workerNodeList); + uint32 beginningNodeIndex = jobId % workerNodeCount; + + /* sort worker node list and task list for deterministic results */ + workerNodeList = SortList(workerNodeList, CompareWorkerNodes); + taskList = SortList(taskList, CompareTasksByTaskId); + + foreach(taskCell, taskList) + { + Task *task = (Task *) lfirst(taskCell); + List *taskPlacementList = NIL; + ShardPlacement *primaryPlacement = NULL; + + uint32 replicaIndex = 0; + for (replicaIndex = 0; replicaIndex < ShardReplicationFactor; replicaIndex++) + { + uint32 assignmentOffset = beginningNodeIndex + assignedTaskIndex + replicaIndex; + uint32 assignmentIndex = assignmentOffset % workerNodeCount; + WorkerNode *workerNode = list_nth(workerNodeList, assignmentIndex); + + ShardPlacement *taskPlacement = CitusMakeNode(ShardPlacement); + taskPlacement->nodeName = pstrdup(workerNode->workerName); + taskPlacement->nodePort = workerNode->workerPort; + + taskPlacementList = lappend(taskPlacementList, taskPlacement); + } + + task->taskPlacementList = taskPlacementList; + + primaryPlacement = (ShardPlacement *) linitial(task->taskPlacementList); + ereport(DEBUG3, (errmsg("assigned task %u to node %s:%u", task->taskId, + primaryPlacement->nodeName, + primaryPlacement->nodePort))); + + assignedTaskList = lappend(assignedTaskList, task); + assignedTaskIndex++; + } + + return assignedTaskList; +} + + +/* Helper function to compare two tasks by their taskId. */ +static int +CompareTasksByTaskId(const void *leftElement, const void *rightElement) +{ + const Task *leftTask = *((const Task **) leftElement); + const Task *rightTask = *((const Task **) rightElement); + + uint32 leftTaskId = leftTask->taskId; + uint32 rightTaskId = rightTask->taskId; + + int taskIdDiff = leftTaskId - rightTaskId; + return taskIdDiff; +} + + +/* + * AssignDataFetchDependencies walks over tasks in the given sql or merge task + * list. The function then propagates worker node assignments from each sql or + * merge task to the task's data fetch dependencies. + */ +static void +AssignDataFetchDependencies(List *taskList) +{ + ListCell *taskCell = NULL; + foreach(taskCell, taskList) + { + Task *task = (Task *) lfirst(taskCell); + List *dependedTaskList = task->dependedTaskList; + ListCell *dependedTaskCell = NULL; + + Assert(task->taskPlacementList != NIL); + Assert(task->taskType == SQL_TASK || task->taskType == MERGE_TASK); + + foreach(dependedTaskCell, dependedTaskList) + { + Task *dependedTask = (Task *) lfirst(dependedTaskCell); + if (dependedTask->taskType == SHARD_FETCH_TASK || + dependedTask->taskType == MAP_OUTPUT_FETCH_TASK) + { + dependedTask->taskPlacementList = task->taskPlacementList; + } + } + } +} + + +/* + * TaskListHighestTaskId walks over tasks in the given task list, finds the task + * that has the largest taskId, and returns that taskId. + * + * Note: This function assumes that the depended taskId's are set before the + * taskId's for the given task list. + */ +static uint32 +TaskListHighestTaskId(List *taskList) +{ + uint32 highestTaskId = 0; + ListCell *taskCell = NULL; + + foreach(taskCell, taskList) + { + Task *task = (Task *) lfirst(taskCell); + if (task->taskId > highestTaskId) + { + highestTaskId = task->taskId; + } + } + + return highestTaskId; +} + + +/* + * MergeTableQueryString builds a query string which creates a merge task table + * within the job's schema, which should have already been created by the task + * tracker protocol. + */ +static StringInfo +MergeTableQueryString(uint32 taskIdIndex, List *targetEntryList) +{ + StringInfo taskTableName = TaskTableName(taskIdIndex); + StringInfo mergeTableQueryString = makeStringInfo(); + StringInfo mergeTableName = makeStringInfo(); + StringInfo columnsString = makeStringInfo(); + ListCell *targetEntryCell = NULL; + uint32 columnCount = 0; + uint32 columnIndex = 0; + + appendStringInfo(mergeTableName, "%s%s", taskTableName->data, MERGE_TABLE_SUFFIX); + + columnCount = (uint32) list_length(targetEntryList); + + foreach(targetEntryCell, targetEntryList) + { + TargetEntry *targetEntry = (TargetEntry *) lfirst(targetEntryCell); + Node *columnExpression = (Node *) targetEntry->expr; + Oid columnTypeId = exprType(columnExpression); + int32 columnTypeMod = exprTypmod(columnExpression); + char *columnName = NULL; + char *columnType = NULL; + + StringInfo columnNameString = makeStringInfo(); + appendStringInfo(columnNameString, MERGE_COLUMN_FORMAT, columnIndex); + + columnName = columnNameString->data; + columnType = format_type_with_typemod(columnTypeId, columnTypeMod); + + appendStringInfo(columnsString, "%s %s", columnName, columnType); + + columnIndex++; + if (columnIndex != columnCount) + { + appendStringInfo(columnsString, ", "); + } + } + + appendStringInfo(mergeTableQueryString, CREATE_TABLE_COMMAND, mergeTableName->data, + columnsString->data); + + return mergeTableQueryString; +} + + +/* + * IntermediateTableQueryString builds a query string which creates a task table + * by running reduce query on already created merge table. + */ +static StringInfo +IntermediateTableQueryString(uint64 jobId, uint32 taskIdIndex, Query *reduceQuery) +{ + StringInfo taskTableName = TaskTableName(taskIdIndex); + StringInfo intermediateTableQueryString = makeStringInfo(); + StringInfo mergeTableName = makeStringInfo(); + StringInfo columnsString = makeStringInfo(); + StringInfo taskReduceQueryString = makeStringInfo(); + Query *taskReduceQuery = copyObject(reduceQuery); + RangeTblEntry *rangeTableEntry = NULL; + Alias *referenceNames = NULL; + List *columnNames = NIL; + List *rangeTableList = NIL; + ListCell *columnNameCell = NULL; + uint32 columnCount = 0; + uint32 columnIndex = 0; + + columnCount = FinalTargetEntryCount(reduceQuery->targetList); + columnNames = DerivedColumnNameList(columnCount, jobId); + + foreach(columnNameCell, columnNames) + { + Value *columnNameValue = (Value *) lfirst(columnNameCell); + char *columnName = strVal(columnNameValue); + + appendStringInfo(columnsString, "%s", columnName); + + columnIndex++; + if (columnIndex != columnCount) + { + appendStringInfo(columnsString, ", "); + } + } + + appendStringInfo(mergeTableName, "%s%s", taskTableName->data, MERGE_TABLE_SUFFIX); + + rangeTableList = taskReduceQuery->rtable; + rangeTableEntry = (RangeTblEntry *) linitial(rangeTableList); + referenceNames = rangeTableEntry->eref; + referenceNames->aliasname = mergeTableName->data; + + rangeTableEntry->alias = rangeTableEntry->eref; + + ModifyRangeTblExtraData(rangeTableEntry, GetRangeTblKind(rangeTableEntry), + NULL, mergeTableName->data, NIL); + + pg_get_query_def(taskReduceQuery, taskReduceQueryString); + + appendStringInfo(intermediateTableQueryString, CREATE_TABLE_AS_COMMAND, + taskTableName->data, columnsString->data, + taskReduceQueryString->data); + + return intermediateTableQueryString; +} + + +/* + * FinalTargetEntryCount returns count of target entries in the final target + * entry list. + */ +static uint32 +FinalTargetEntryCount(List *targetEntryList) +{ + uint32 finalTargetEntryCount = 0; + ListCell *targetEntryCell = NULL; + + foreach(targetEntryCell, targetEntryList) + { + TargetEntry *targetEntry = (TargetEntry *) lfirst(targetEntryCell); + if (!targetEntry->resjunk) + { + finalTargetEntryCount++; + } + } + + return finalTargetEntryCount; +} diff --git a/src/backend/distributed/planner/multi_planner.c b/src/backend/distributed/planner/multi_planner.c new file mode 100644 index 000000000..93d05817e --- /dev/null +++ b/src/backend/distributed/planner/multi_planner.c @@ -0,0 +1,294 @@ +/*------------------------------------------------------------------------- + * + * multi_planner.c + * General CitusDB planner code. + * + * Copyright (c) 2012-2015, Citus Data, Inc. + *------------------------------------------------------------------------- + */ + +#include "postgres.h" + +#include + +#include "catalog/pg_type.h" + +#include "distributed/citus_nodefuncs.h" +#include "distributed/citus_nodes.h" +#include "distributed/metadata_cache.h" +#include "distributed/multi_planner.h" +#include "distributed/multi_logical_optimizer.h" +#include "distributed/multi_logical_planner.h" +#include "distributed/multi_physical_planner.h" +#include "distributed/modify_planner.h" + +#include "executor/executor.h" + +#include "optimizer/planner.h" + +#include "utils/memutils.h" + +/* local function forward declarations */ +static void CheckNodeIsDumpable(Node *node); + + +/* local function forward declarations */ +static MultiPlan * CreatePhysicalPlan(Query *parse); +static char * GetMultiPlanString(PlannedStmt *result); +static PlannedStmt * MultiQueryContainerNode(PlannedStmt *result, MultiPlan *multiPlan); + + +/* Distributed planner hook */ +PlannedStmt * +multi_planner(Query *parse, int cursorOptions, ParamListInfo boundParams) +{ + PlannedStmt *result = NULL; + + /* + * First call into standard planner. This is required because the CitusDB + * planner relies on parse tree transformations made by postgres' planner. + */ + result = standard_planner(parse, cursorOptions, boundParams); + + if (NeedsDistributedPlanning(parse)) + { + MemoryContext oldcontext = NULL; + MultiPlan *physicalPlan = NULL; + + /* Switch to top level message context */ + oldcontext = MemoryContextSwitchTo(MessageContext); + + physicalPlan = CreatePhysicalPlan(parse); + + /* store required data into the planned statement */ + result = MultiQueryContainerNode(result, physicalPlan); + + /* Now switch back to original context */ + MemoryContextSwitchTo(oldcontext); + } + + return result; +} + + +/* + * CreatePhysicalPlan encapsulates the logic needed to transform a particular + * query into a physical plan. For modifications, queries immediately enter + * the physical planning stage, since they are essentially "routed" to remote + * target shards. SELECT queries go through the full logical plan/optimize/ + * physical plan process needed to produce distributed query plans. + */ +static MultiPlan * +CreatePhysicalPlan(Query *parse) +{ + Query *parseCopy = copyObject(parse); + MultiPlan *physicalPlan = NULL; + CmdType commandType = parse->commandType; + + if (commandType == CMD_INSERT || commandType == CMD_UPDATE || + commandType == CMD_DELETE) + { + /* modifications go directly from a query to a physical plan */ + physicalPlan = MultiModifyPlanCreate(parse); + } + else + { + /* Create and optimize logical plan */ + MultiTreeRoot *logicalPlan = MultiLogicalPlanCreate(parseCopy); + MultiLogicalPlanOptimize(logicalPlan); + + /* + * This check is here to make it likely that all node types used in + * CitusDB are dumpable. Explain can dump logical and physical plans + * using the extended outfuncs infrastructure, but it's infeasible to + * test most plans. MultiQueryContainerNode always serializes the + * physical plan, so there's no need to check that separately. + */ + CheckNodeIsDumpable((Node *) logicalPlan); + + /* Create the physical plan */ + physicalPlan = MultiPhysicalPlanCreate(logicalPlan); + } + + return physicalPlan; +} + + +/* + * GetMultiPlan returns the associated MultiPlan for a PlannedStmt if the + * statement requires distributed execution, NULL otherwise. + */ +MultiPlan * +GetMultiPlan(PlannedStmt *result) +{ + char *serializedMultiPlan = NULL; + MultiPlan *multiPlan = NULL; + + serializedMultiPlan = GetMultiPlanString(result); + multiPlan = (MultiPlan *) CitusStringToNode(serializedMultiPlan); + Assert(CitusIsA(multiPlan, MultiPlan)); + + return multiPlan; +} + + +/* Does the passed in statement require distributed execution? */ +bool +HasCitusToplevelNode(PlannedStmt *result) +{ + /* + * Can't be a distributed query if the extension hasn't been loaded + * yet. Directly return false, part of the required infrastructure for + * further checks might not be present. + */ + if (!CitusDBHasBeenLoaded()) + { + return false; + } + + if (GetMultiPlanString(result) == NULL) + { + return false; + } + else + { + return true; + } +} + + +/* + * CreateCitusToplevelNode creates the top-level planTree node for a + * distributed statement. That top-level node is a) recognizable by the + * executor hooks, allowing them to redirect execution, b) contains the + * parameters required for distributed execution. + * + * The exact representation of the top-level node is an implementation detail + * which should not be referred to outside this file, as it's likely to become + * version dependant. Use GetMultiPlan() and HasCitusToplevelNode() to access. + * + * Internally the data is stored as arguments to a 'citus_extradata_container' + * function, which has to be removed from the really executed plan tree before + * query execution. + */ +static PlannedStmt * +MultiQueryContainerNode(PlannedStmt *result, MultiPlan *multiPlan) +{ + FunctionScan *fauxFunctionScan = NULL; + RangeTblFunction *fauxFunction = NULL; + FuncExpr *fauxFuncExpr = NULL; + Const *multiPlanData = NULL; + char *serializedPlan = NULL; + + /* pass multiPlan serialized as a constant function argument */ + serializedPlan = CitusNodeToString(multiPlan); + multiPlanData = makeNode(Const); + multiPlanData->consttype = CSTRINGOID; + multiPlanData->constlen = strlen(serializedPlan); + multiPlanData->constvalue = CStringGetDatum(serializedPlan); + multiPlanData->constbyval = false; + multiPlanData->location = -1; + + fauxFuncExpr = makeNode(FuncExpr); + fauxFuncExpr->funcid = CitusExtraDataContainerFuncId(); + fauxFuncExpr->funcretset = true; + fauxFuncExpr->location = -1; + + fauxFuncExpr->args = list_make1(multiPlanData); + fauxFunction = makeNode(RangeTblFunction); + fauxFunction->funcexpr = (Node *) fauxFuncExpr; + + fauxFunctionScan = makeNode(FunctionScan); + fauxFunctionScan->functions = lappend(fauxFunctionScan->functions, fauxFunction); + + /* + * Add set returning function to target list if the original (postgres + * created) plan doesn't support backward scans; doing so prevents + * backward scans being supported by the new plantree as well. This is + * ugly as hell, but until we can rely on custom scans (which can signal + * this via CUSTOMPATH_SUPPORT_BACKWARD_SCAN), there's not really a pretty + * method to achieve this. + * + * FIXME: This should really be done on the master select plan. + */ + if (!ExecSupportsBackwardScan(result->planTree)) + { + FuncExpr *funcExpr = makeNode(FuncExpr); + funcExpr->funcretset = true; + + fauxFunctionScan->scan.plan.targetlist = + lappend(fauxFunctionScan->scan.plan.targetlist, + funcExpr); + } + + result->planTree = (Plan *) fauxFunctionScan; + + return result; +} + + +/* + * GetMultiPlanString returns either NULL, if the plan is not a distributed + * one, or the string representing the distributed plan. + */ +static char * +GetMultiPlanString(PlannedStmt *result) +{ + FunctionScan *fauxFunctionScan = NULL; + RangeTblFunction *fauxFunction = NULL; + FuncExpr *fauxFuncExpr = NULL; + Const *multiPlanData = NULL; + + if (!IsA(result->planTree, FunctionScan)) + { + return NULL; + } + + fauxFunctionScan = (FunctionScan *) result->planTree; + + if (list_length(fauxFunctionScan->functions) != 1) + { + return NULL; + } + + fauxFunction = linitial(fauxFunctionScan->functions); + + if (!IsA(fauxFunction->funcexpr, FuncExpr)) + { + return NULL; + } + + fauxFuncExpr = (FuncExpr *) fauxFunction->funcexpr; + + if (fauxFuncExpr->funcid != CitusExtraDataContainerFuncId()) + { + return NULL; + } + + if (list_length(fauxFuncExpr->args) != 1) + { + ereport(ERROR, (errmsg("unexpected number of function arguments to " + "citusdb_extradata_container"))); + } + + multiPlanData = (Const *) linitial(fauxFuncExpr->args); + Assert(IsA(multiPlanData, Const)); + Assert(multiPlanData->consttype == CSTRINGOID); + + return DatumGetCString(multiPlanData->constvalue); +} + + +/* + * CheckNodeIsDumpable checks that the passed node can be dumped using + * CitusNodeToString(). As this checks is expensive, it's only active when + * assertions are enabled. + */ +static void +CheckNodeIsDumpable(Node *node) +{ +#ifdef USE_ASSERT_CHECKING + char *out = CitusNodeToString(node); + pfree(out); +#endif +} diff --git a/src/backend/distributed/relay/relay_event_utility.c b/src/backend/distributed/relay/relay_event_utility.c new file mode 100644 index 000000000..54f7a09a5 --- /dev/null +++ b/src/backend/distributed/relay/relay_event_utility.c @@ -0,0 +1,511 @@ +/*------------------------------------------------------------------------- + * + * relay_event_utility.c + * + * Routines for handling DDL statements that relate to relay files. These + * routines extend relation, index and constraint names in utility commands. + * + * Copyright (c) 2012, Citus Data, Inc. + * + * $Id$ + * + *------------------------------------------------------------------------- + */ + +#include "postgres.h" + +#include "access/genam.h" +#include "access/heapam.h" +#include "access/htup_details.h" +#include "access/skey.h" +#include "access/xact.h" +#include "catalog/indexing.h" +#include "catalog/namespace.h" +#include "catalog/pg_constraint.h" +#include "commands/defrem.h" +#include "distributed/relay_utility.h" +#include "nodes/parsenodes.h" +#include "parser/parse_utilcmd.h" +#include "storage/lock.h" +#include "tcop/utility.h" +#include "utils/fmgroids.h" +#include "utils/lsyscache.h" +#include "utils/tqual.h" + + +/* Local functions forward declarations */ +static bool TypeAddIndexConstraint(const AlterTableCmd *command); +static bool TypeDropIndexConstraint(const AlterTableCmd *command, + const RangeVar *relation, uint64 shardId); +static void AppendShardIdToConstraintName(AlterTableCmd *command, uint64 shardId); + + +/* + * RelayEventExtendNames extends relation names in the given parse tree for + * certain utility commands. The function more specifically extends table, + * sequence, and index names in the parse tree by appending the given shardId; + * thereby avoiding name collisions in the database among sharded tables. This + * function has the side effect of extending relation names in the parse tree. + */ +void +RelayEventExtendNames(Node *parseTree, uint64 shardId) +{ + /* we don't extend names in extension or schema commands */ + NodeTag nodeType = nodeTag(parseTree); + if (nodeType == T_CreateExtensionStmt || nodeType == T_CreateSchemaStmt) + { + return; + } + + switch (nodeType) + { + case T_AlterSeqStmt: + { + AlterSeqStmt *alterSeqStmt = (AlterSeqStmt *) parseTree; + char **sequenceName = &(alterSeqStmt->sequence->relname); + + AppendShardIdToName(sequenceName, shardId); + break; + } + + case T_AlterTableStmt: + { + /* + * We append shardId to the very end of table, sequence and index + * names to avoid name collisions. We usually do not touch + * constraint names, except for cases where they refer to index + * names. In those cases, we also append to constraint names. + */ + + AlterTableStmt *alterTableStmt = (AlterTableStmt *) parseTree; + char **relationName = &(alterTableStmt->relation->relname); + RangeVar *relation = alterTableStmt->relation; /* for constraints */ + + List *commandList = alterTableStmt->cmds; + ListCell *commandCell = NULL; + + /* first append shardId to base relation name */ + AppendShardIdToName(relationName, shardId); + + foreach(commandCell, commandList) + { + AlterTableCmd *command = (AlterTableCmd *) lfirst(commandCell); + + if (TypeAddIndexConstraint(command) || + TypeDropIndexConstraint(command, relation, shardId)) + { + AppendShardIdToConstraintName(command, shardId); + } + else if (command->subtype == AT_ClusterOn) + { + char **indexName = &(command->name); + AppendShardIdToName(indexName, shardId); + } + } + + break; + } + + case T_ClusterStmt: + { + ClusterStmt *clusterStmt = (ClusterStmt *) parseTree; + char **relationName = NULL; + + /* we do not support clustering the entire database */ + if (clusterStmt->relation == NULL) + { + ereport(ERROR, (errmsg("cannot extend name for multi-relation cluster"))); + } + + relationName = &(clusterStmt->relation->relname); + AppendShardIdToName(relationName, shardId); + + if (clusterStmt->indexname != NULL) + { + char **indexName = &(clusterStmt->indexname); + AppendShardIdToName(indexName, shardId); + } + + break; + } + + case T_CreateSeqStmt: + { + CreateSeqStmt *createSeqStmt = (CreateSeqStmt *) parseTree; + char **sequenceName = &(createSeqStmt->sequence->relname); + + AppendShardIdToName(sequenceName, shardId); + break; + } + + case T_CreateForeignServerStmt: + { + CreateForeignServerStmt *serverStmt = (CreateForeignServerStmt *) parseTree; + char **serverName = &(serverStmt->servername); + + AppendShardIdToName(serverName, shardId); + break; + } + + case T_CreateForeignTableStmt: + { + CreateForeignTableStmt *createStmt = (CreateForeignTableStmt *) parseTree; + char **serverName = &(createStmt->servername); + + AppendShardIdToName(serverName, shardId); + + /* + * Since CreateForeignTableStmt inherits from CreateStmt and any change + * performed on CreateStmt should be done here too, we simply *fall + * through* to avoid code repetition. + */ + } + + case T_CreateStmt: + { + CreateStmt *createStmt = (CreateStmt *) parseTree; + char **relationName = &(createStmt->relation->relname); + + AppendShardIdToName(relationName, shardId); + break; + } + + case T_DropStmt: + { + DropStmt *dropStmt = (DropStmt *) parseTree; + ObjectType objectType = dropStmt->removeType; + + if (objectType == OBJECT_TABLE || objectType == OBJECT_SEQUENCE || + objectType == OBJECT_INDEX || objectType == OBJECT_FOREIGN_TABLE || + objectType == OBJECT_FOREIGN_SERVER) + { + List *relationNameList = NULL; + int relationNameListLength = 0; + Value *relationNameValue = NULL; + char **relationName = NULL; + + uint32 dropCount = list_length(dropStmt->objects); + if (dropCount > 1) + { + ereport(ERROR, + (errmsg("cannot extend name for multiple drop objects"))); + } + + /* + * We now need to extend a single relation, sequence or index + * name. To be able to do this extension, we need to extract the + * names' addresses from the value objects they are stored in. + * Otherwise, the repalloc called in AppendShardIdToName() will + * not have the correct memory address for the name. + */ + + relationNameList = (List *) linitial(dropStmt->objects); + relationNameListLength = list_length(relationNameList); + + switch (relationNameListLength) + { + case 1: + relationNameValue = linitial(relationNameList); + break; + case 2: + relationNameValue = lsecond(relationNameList); + break; + case 3: + relationNameValue = lthird(relationNameList); + break; + default: + ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("improper relation name: \"%s\"", + NameListToString(relationNameList)))); + break; + } + + relationName = &(relationNameValue->val.str); + AppendShardIdToName(relationName, shardId); + } + else + { + ereport(WARNING, (errmsg("unsafe object type in drop statement"), + errdetail("Object type: %u", (uint32) objectType))); + } + + break; + } + + case T_IndexStmt: + { + IndexStmt *indexStmt = (IndexStmt *) parseTree; + char **relationName = &(indexStmt->relation->relname); + char **indexName = &(indexStmt->idxname); + + /* + * Concurrent index statements cannot run within a transaction block. + * Therefore, we do not support them. + */ + if (indexStmt->concurrent) + { + ereport(ERROR, (errmsg("cannot extend name for concurrent index"))); + } + + /* + * In the regular DDL execution code path (for non-sharded tables), + * if the index statement results from a table creation command, the + * indexName may be null. For sharded tables however, we intercept + * that code path and explicitly set the index name. Therefore, the + * index name in here cannot be null. + */ + if ((*indexName) == NULL) + { + ereport(ERROR, (errmsg("cannot extend name for null index name"))); + } + + AppendShardIdToName(relationName, shardId); + AppendShardIdToName(indexName, shardId); + break; + } + + case T_ReindexStmt: + { + ReindexStmt *reindexStmt = (ReindexStmt *) parseTree; + +#if (PG_VERSION_NUM >= 90500) + ReindexObjectType objectType = reindexStmt->kind; + if (objectType == REINDEX_OBJECT_TABLE || objectType == REINDEX_OBJECT_INDEX) + { + char **objectName = &(reindexStmt->relation->relname); + AppendShardIdToName(objectName, shardId); + } + else if (objectType == REINDEX_OBJECT_DATABASE) + { + ereport(ERROR, (errmsg("cannot extend name for multi-relation reindex"))); + } +#else + ObjectType objectType = reindexStmt->kind; + if (objectType == OBJECT_TABLE || objectType == OBJECT_INDEX) + { + char **objectName = &(reindexStmt->relation->relname); + AppendShardIdToName(objectName, shardId); + } + else if (objectType == OBJECT_DATABASE) + { + ereport(ERROR, (errmsg("cannot extend name for multi-relation reindex"))); + } +#endif + else + { + ereport(ERROR, (errmsg("invalid object type in reindex statement"), + errdetail("Object type: %u", (uint32) objectType))); + } + + break; + } + + case T_RenameStmt: + { + RenameStmt *renameStmt = (RenameStmt *) parseTree; + ObjectType objectType = renameStmt->renameType; + + if (objectType == OBJECT_TABLE || objectType == OBJECT_SEQUENCE || + objectType == OBJECT_INDEX) + { + char **oldRelationName = &(renameStmt->relation->relname); + char **newRelationName = &(renameStmt->newname); + + AppendShardIdToName(oldRelationName, shardId); + AppendShardIdToName(newRelationName, shardId); + } + else if (objectType == OBJECT_COLUMN || objectType == OBJECT_TRIGGER) + { + char **relationName = &(renameStmt->relation->relname); + + AppendShardIdToName(relationName, shardId); + } + else + { + ereport(WARNING, (errmsg("unsafe object type in rename statement"), + errdetail("Object type: %u", (uint32) objectType))); + } + + break; + } + + case T_TruncateStmt: + { + /* + * We currently do not support truncate statements. This is + * primarily because truncates allow implicit modifications to + * sequences through table column dependencies. As we have not + * determined our dependency model for sequences, we error here. + */ + ereport(ERROR, (errmsg("cannot extend name for truncate statement"))); + break; + } + + default: + { + ereport(WARNING, (errmsg("unsafe statement type in name extension"), + errdetail("Statement type: %u", (uint32) nodeType))); + break; + } + } +} + + +/* + * TypeAddIndexConstraint checks if the alter table command adds a constraint + * and if that constraint also results in an index creation. + */ +static bool +TypeAddIndexConstraint(const AlterTableCmd *command) +{ + if (command->subtype == AT_AddConstraint) + { + if (IsA(command->def, Constraint)) + { + Constraint *constraint = (Constraint *) command->def; + if (constraint->contype == CONSTR_PRIMARY || + constraint->contype == CONSTR_UNIQUE) + { + return true; + } + } + } + + return false; +} + + +/* + * TypeDropIndexConstraint checks if the alter table command drops a constraint + * and if that constraint also results in an index drop. Note that drop + * constraints do not have access to constraint type information; this is in + * contrast with add constraint commands. This function therefore performs + * additional system catalog lookups to determine if the drop constraint is + * associated with an index. + */ +static bool +TypeDropIndexConstraint(const AlterTableCmd *command, + const RangeVar *relation, uint64 shardId) +{ + Relation pgConstraint = NULL; + SysScanDesc scanDescriptor = NULL; + ScanKeyData scanKey[1]; + int scanKeyCount = 1; + HeapTuple heapTuple = NULL; + + char *searchedConstraintName = NULL; + bool indexConstraint = false; + Oid relationId = InvalidOid; + bool failOK = true; + + if (command->subtype != AT_DropConstraint) + { + return false; + } + + /* + * At this stage, our only option is performing a relationId lookup. We + * first find the relationId, and then scan the pg_constraints system + * catalog using this relationId. Finally, we check if the passed in + * constraint is for a primary key or unique index. + */ + relationId = RangeVarGetRelid(relation, NoLock, failOK); + if (!OidIsValid(relationId)) + { + /* overlook this error, it should be signaled later in the pipeline */ + return false; + } + + searchedConstraintName = pnstrdup(command->name, NAMEDATALEN); + AppendShardIdToName(&searchedConstraintName, shardId); + + pgConstraint = heap_open(ConstraintRelationId, AccessShareLock); + + ScanKeyInit(&scanKey[0], Anum_pg_constraint_conrelid, + BTEqualStrategyNumber, F_OIDEQ, ObjectIdGetDatum(relationId)); + + scanDescriptor = systable_beginscan(pgConstraint, + ConstraintRelidIndexId, true, /* indexOK */ + NULL, scanKeyCount, scanKey); + + heapTuple = systable_getnext(scanDescriptor); + while (HeapTupleIsValid(heapTuple)) + { + Form_pg_constraint constraintForm = (Form_pg_constraint) GETSTRUCT(heapTuple); + char *constraintName = NameStr(constraintForm->conname); + + if (strncmp(constraintName, searchedConstraintName, NAMEDATALEN) == 0) + { + /* we found the constraint, now check if it is for an index */ + if (constraintForm->contype == CONSTRAINT_PRIMARY || + constraintForm->contype == CONSTRAINT_UNIQUE) + { + indexConstraint = true; + } + + break; + } + + heapTuple = systable_getnext(scanDescriptor); + } + + systable_endscan(scanDescriptor); + heap_close(pgConstraint, AccessShareLock); + + pfree(searchedConstraintName); + + return indexConstraint; +} + + +/* + * AppendShardIdToConstraintName extends given constraint name with given + * shardId. Note that we only extend constraint names if they correspond to + * indexes, and the caller should verify that index correspondence before + * calling this function. + */ +static void +AppendShardIdToConstraintName(AlterTableCmd *command, uint64 shardId) +{ + if (command->subtype == AT_AddConstraint) + { + Constraint *constraint = (Constraint *) command->def; + char **constraintName = &(constraint->conname); + AppendShardIdToName(constraintName, shardId); + } + else if (command->subtype == AT_DropConstraint) + { + char **constraintName = &(command->name); + AppendShardIdToName(constraintName, shardId); + } +} + + +/* + * AppendShardIdToName appends shardId to the given name. The function takes in + * the name's address in order to reallocate memory for the name in the same + * memory context the name was originally created in. + */ +void +AppendShardIdToName(char **name, uint64 shardId) +{ + char extendedName[NAMEDATALEN]; + uint32 extendedNameLength = 0; + + snprintf(extendedName, NAMEDATALEN, "%s%c" UINT64_FORMAT, + (*name), SHARD_NAME_SEPARATOR, shardId); + + /* + * Parser should have already checked that the table name has enough space + * reserved for appending shardIds. Nonetheless, we perform an additional + * check here to verify that the appended name does not overflow. + */ + extendedNameLength = strlen(extendedName) + 1; + if (extendedNameLength >= NAMEDATALEN) + { + ereport(ERROR, (errmsg("shard name too long to extend: \"%s\"", (*name)))); + } + + (*name) = (char *) repalloc((*name), extendedNameLength); + snprintf((*name), extendedNameLength, "%s", extendedName); +} diff --git a/src/backend/distributed/shared_library_init.c b/src/backend/distributed/shared_library_init.c new file mode 100644 index 000000000..344665eb0 --- /dev/null +++ b/src/backend/distributed/shared_library_init.c @@ -0,0 +1,535 @@ +/*------------------------------------------------------------------------- + * + * shared_library_init.c + * Initialize CitusDB extension + * + * Copyright (c) 2012-2015, Citus Data, Inc. + *------------------------------------------------------------------------- + */ + +#include "postgres.h" + +#include +#include +#include + +#include "fmgr.h" +#include "miscadmin.h" + +#include "commands/explain.h" +#include "executor/executor.h" +#include "distributed/master_protocol.h" +#include "distributed/modify_planner.h" +#include "distributed/multi_executor.h" +#include "distributed/multi_explain.h" +#include "distributed/multi_join_order.h" +#include "distributed/multi_logical_optimizer.h" +#include "distributed/multi_planner.h" +#include "distributed/multi_router_executor.h" +#include "distributed/multi_server_executor.h" +#include "distributed/multi_utility.h" +#include "distributed/task_tracker.h" +#include "distributed/worker_manager.h" +#include "distributed/worker_protocol.h" +#include "postmaster/postmaster.h" +#include "optimizer/planner.h" +#include "utils/guc.h" +#include "utils/guc_tables.h" + +/* marks shared object as one loadable by the postgres version compiled against */ +PG_MODULE_MAGIC; + +void _PG_init(void); + +static void CreateRequiredDirectories(void); +static void RegisterCitusConfigVariables(void); +static void NormalizeWorkerListPath(void); + + +/* GUC enum definitions */ +static const struct config_enum_entry task_assignment_policy_options[] = { + {"greedy", TASK_ASSIGNMENT_GREEDY, false}, + {"first-replica", TASK_ASSIGNMENT_FIRST_REPLICA, false}, + {"round-robin", TASK_ASSIGNMENT_ROUND_ROBIN, false}, + {NULL, 0, false} +}; + +static const struct config_enum_entry task_executor_type_options[] = { + {"real-time", MULTI_EXECUTOR_REAL_TIME, false}, + {"task-tracker", MULTI_EXECUTOR_TASK_TRACKER, false}, + {"router", MULTI_EXECUTOR_ROUTER, false}, + {NULL, 0, false} +}; + +static const struct config_enum_entry shard_placement_policy_options[] = { + {"local-node-first", SHARD_PLACEMENT_LOCAL_NODE_FIRST, false}, + {"round-robin", SHARD_PLACEMENT_ROUND_ROBIN, false}, + {NULL, 0, false} +}; + + +/* shared library initialization function */ +void +_PG_init(void) +{ + if (!process_shared_preload_libraries_in_progress) + { + ereport(ERROR, (errmsg("CitusDB can only be loaded via shared_preload_libraries"), + errhint("Add citusdb to shared_preload_libraries."))); + } + + /* + * Perform checks before registering any hooks, to avoid erroring out in a + * partial state. + * + * In many cases (e.g. planner and utility hook, to run inside + * pg_stat_statements et. al.) we have to be loaded before other hooks + * (thus as the innermost/last running hook) to be able to do our + * duties. For simplicity insist that all hooks are previously unused. + */ + if (planner_hook != NULL || + ExplainOneQuery_hook != NULL || + ExecutorStart_hook != NULL || + ExecutorRun_hook != NULL || + ExecutorFinish_hook != NULL || + ExecutorEnd_hook != NULL || + ProcessUtility_hook != NULL) + { + ereport(ERROR, (errmsg("CitusDB has to be loaded first"), + errhint("Place citusdb at the beginning of " + "shared_preload_libraries."))); + } + + /* + * Extend the database directory structure before continuing with + * initialization - one of the later steps might require them to exist. + */ + CreateRequiredDirectories(); + + /* + * Register CitusDB configuration variables. Do so before intercepting + * hooks or calling initialization functions, in case we want to do the + * latter in a configuration dependent manner. + */ + RegisterCitusConfigVariables(); + + /* intercept planner */ + planner_hook = multi_planner; + + /* intercept explain */ + ExplainOneQuery_hook = MultiExplainOneQuery; + + /* intercept executor */ + ExecutorStart_hook = multi_ExecutorStart; + ExecutorRun_hook = multi_ExecutorRun; + ExecutorFinish_hook = multi_ExecutorFinish; + ExecutorEnd_hook = multi_ExecutorEnd; + + /* register utility hook */ + ProcessUtility_hook = multi_ProcessUtility; + + /* organize that task tracker is started once server is up */ + TaskTrackerRegister(); + + /* initialize worker node manager */ + WorkerNodeRegister(); +} + + +/* + * CreateRequiredDirectories - Create directories required for CitusDB to + * function. + * + * These used to be created by initdb, but that's not possible anymore. + */ +static void +CreateRequiredDirectories(void) +{ + int dirNo = 0; + const char *subdirs[] = { + "pg_foreign_file", + "pg_foreign_file/cached", + "base/pgsql_job_cache" + }; + + for (dirNo = 0; dirNo < lengthof(subdirs); dirNo++) + { + int ret = mkdir(subdirs[dirNo], S_IRWXU); + + if (ret != 0 && errno != EEXIST) + { + ereport(ERROR, (errcode_for_file_access(), + errmsg("could not create directory \"%s\": %m", + subdirs[dirNo]))); + } + } +} + + +/* Register CitusDB configuration variables. */ +static void +RegisterCitusConfigVariables(void) +{ + DefineCustomStringVariable( + "citusdb.worker_list_file", + gettext_noop("Sets the server's \"worker_list\" configuration file."), + NULL, + &WorkerListFileName, + NULL, + PGC_POSTMASTER, + GUC_SUPERUSER_ONLY, + NULL, NULL, NULL); + NormalizeWorkerListPath(); + + DefineCustomBoolVariable( + "citusdb.binary_master_copy_format", + gettext_noop("Use the binary master copy format."), + gettext_noop("When enabled, data is copied from workers to the master " + "in PostgreSQL's binary serialization format."), + &BinaryMasterCopyFormat, + false, + PGC_USERSET, + 0, + NULL, NULL, NULL); + + DefineCustomBoolVariable( + "citusdb.binary_worker_copy_format", + gettext_noop("Use the binary worker copy format."), + gettext_noop("When enabled, data is copied from workers to workers " + "in PostgreSQL's binary serialization format when " + "joining large tables."), + &BinaryWorkerCopyFormat, + false, + PGC_SIGHUP, + 0, + NULL, NULL, NULL); + + DefineCustomBoolVariable( + "citusdb.expire_cached_shards", + gettext_noop("Enables shard cache expiration if a shard's size on disk has changed. "), + gettext_noop("When appending to an existing shard, old data may still be cached on " + "other workers. This configuration entry activates automatic " + "expiration, but should not be used with manual updates to shards."), + &ExpireCachedShards, + false, + PGC_SIGHUP, + 0, + NULL, NULL, NULL); + + DefineCustomBoolVariable( + "citusdb.subquery_pushdown", + gettext_noop("Enables supported subquery pushdown to workers."), + NULL, + &SubqueryPushdown, + false, + PGC_USERSET, + 0, + NULL, NULL, NULL); + + DefineCustomBoolVariable( + "citusdb.log_multi_join_order", + gettext_noop("Logs the distributed join order to the server log."), + gettext_noop("We use this private configuration entry as a debugging aid. " + "If enabled, we print the distributed join order."), + &LogMultiJoinOrder, + false, + PGC_USERSET, + GUC_NO_SHOW_ALL, + NULL, NULL, NULL); + + DefineCustomBoolVariable( + "citusdb.explain_multi_logical_plan", + gettext_noop("Enables Explain to print out distributed logical plans."), + gettext_noop("We use this private configuration entry as a debugging aid. " + "If enabled, the Explain command prints out the optimized " + "logical plan for distributed queries."), + &ExplainMultiLogicalPlan, + false, + PGC_USERSET, + GUC_NO_SHOW_ALL, + NULL, NULL, NULL); + + DefineCustomBoolVariable( + "citusdb.explain_multi_physical_plan", + gettext_noop("Enables Explain to print out distributed physical plans."), + gettext_noop("We use this private configuration entry as a debugging aid. " + "If enabled, the Explain command prints out the physical " + "plan for distributed queries."), + &ExplainMultiPhysicalPlan, + false, + PGC_USERSET, + GUC_NO_SHOW_ALL, + NULL, NULL, NULL); + + DefineCustomBoolVariable( + "citusdb.all_modifications_commutative", + gettext_noop("Bypasses commutativity checks when enabled"), + NULL, + &AllModificationsCommutative, + false, + PGC_USERSET, + 0, + NULL, NULL, NULL); + + DefineCustomIntVariable( + "citusdb.shard_replication_factor", + gettext_noop("Sets the replication factor for shards."), + gettext_noop("Shards are replicated across nodes according to this " + "replication factor. Note that shards read this " + "configuration value at sharded table creation time, " + "and later reuse the initially read value."), + &ShardReplicationFactor, + 2, 1, 100, + PGC_USERSET, + 0, + NULL, NULL, NULL); + + DefineCustomIntVariable( + "citusdb.shard_max_size", + gettext_noop("Sets the maximum size a shard will grow before it gets split."), + gettext_noop("Shards store table and file data. When the source " + "file's size for one shard exceeds this configuration " + "value, the database ensures that either a new shard " + "gets created, or the current one gets split. Note that " + "shards read this configuration value at sharded table " + "creation time, and later reuse the initially read value."), + &ShardMaxSize, + 1048576, 256, INT_MAX, /* max allowed size not set to MAX_KILOBYTES on purpose */ + PGC_USERSET, + GUC_UNIT_KB, + NULL, NULL, NULL); + + DefineCustomIntVariable( + "citusdb.max_worker_nodes_tracked", + gettext_noop("Sets the maximum number of worker nodes that are tracked."), + gettext_noop("Worker nodes' network locations, their membership and " + "health status are tracked in a shared hash table on " + "the master node. This configuration value limits the " + "size of the hash table, and consequently the maximum " + "number of worker nodes that can be tracked."), + &MaxWorkerNodesTracked, + 2048, 8, INT_MAX, + PGC_POSTMASTER, + 0, + NULL, NULL, NULL); + + DefineCustomIntVariable( + "citusdb.remote_task_check_interval", + gettext_noop("Sets the frequency at which we check job statuses."), + gettext_noop("The master node assigns tasks to workers nodes, and " + "then regularly checks with them about each task's " + "progress. This configuration value sets the time " + "interval between two consequent checks."), + &RemoteTaskCheckInterval, + 10, 1, REMOTE_NODE_CONNECT_TIMEOUT, + PGC_USERSET, + GUC_UNIT_MS, + NULL, NULL, NULL); + + DefineCustomIntVariable( + "citusdb.task_tracker_delay", + gettext_noop("Task tracker sleep time between task management rounds."), + gettext_noop("The task tracker process wakes up regularly, walks over " + "all tasks assigned to it, and schedules and executes these " + "tasks. Then, the task tracker sleeps for a time period " + "before walking over these tasks again. This configuration " + "value determines the length of that sleeping period."), + &TaskTrackerDelay, + 200, 10, 100000, + PGC_SIGHUP, + GUC_UNIT_MS, + NULL, NULL, NULL); + + DefineCustomIntVariable( + "citusdb.max_assign_task_batch_size", + gettext_noop("Sets the maximum number of tasks to assign per round."), + gettext_noop("The master node synchronously assigns tasks to workers in " + "batches. Bigger batches allow for faster task assignment, " + "but it may take longer for all workers to get tasks " + "if the number of workers is large. This configuration " + "value controls the maximum batch size."), + &MaxAssignTaskBatchSize, + 64, 1, INT_MAX, + PGC_USERSET, + 0, + NULL, NULL, NULL); + + DefineCustomIntVariable( + "citusdb.max_tracked_tasks_per_node", + gettext_noop("Sets the maximum number of tracked tasks per node."), + gettext_noop("The task tracker processes keeps all assigned tasks in " + "a shared hash table, and schedules and executes these " + "tasks as appropriate. This configuration value limits " + "the size of the hash table, and therefore the maximum " + "number of tasks that can be tracked at any given time."), + &MaxTrackedTasksPerNode, + 1024, 8, INT_MAX, + PGC_POSTMASTER, + 0, + NULL, NULL, NULL); + + DefineCustomIntVariable( + "citusdb.max_running_tasks_per_node", + gettext_noop("Sets the maximum number of tasks to run concurrently per node."), + gettext_noop("The task tracker process schedules and executes the tasks " + "assigned to it as appropriate. This configuration value " + "sets the maximum number of tasks to execute concurrently " + "on one node at any given time."), + &MaxRunningTasksPerNode, + 8, 1, INT_MAX, + PGC_SIGHUP, + 0, + NULL, NULL, NULL); + + DefineCustomIntVariable( + "citusdb.partition_buffer_size", + gettext_noop("Sets the buffer size to use for partition operations."), + gettext_noop("Worker nodes allow for table data to be repartitioned " + "into multiple text files, much like Hadoop's Map " + "command. This configuration value sets the buffer size " + "to use per partition operation. After the buffer fills " + "up, we flush the repartitioned data into text files."), + &PartitionBufferSize, + 8192, 0, (INT_MAX / 1024), /* result stored in int variable */ + PGC_USERSET, + GUC_UNIT_KB, + NULL, NULL, NULL); + + DefineCustomIntVariable( + "citusdb.large_table_shard_count", + gettext_noop("The shard count threshold over which a table is considered large."), + gettext_noop("A distributed table is considered to be large if it has " + "more shards than the value specified here. This largeness " + "criteria is then used in picking a table join order during " + "distributed query planning."), + &LargeTableShardCount, + 4, 1, 10000, + PGC_USERSET, + 0, + NULL, NULL, NULL); + + DefineCustomIntVariable( + "citusdb.limit_clause_row_fetch_count", + gettext_noop("Number of rows to fetch per task for limit clause optimization."), + gettext_noop("Select queries get partitioned and executed as smaller " + "tasks. In some cases, select queries with limit clauses " + "may need to fetch all rows from each task to generate " + "results. In those cases, and where an approximation would " + "produce meaningful results, this configuration value sets " + "the number of rows to fetch from each task."), + &LimitClauseRowFetchCount, + -1, -1, INT_MAX, + PGC_USERSET, + 0, + NULL, NULL, NULL); + + DefineCustomRealVariable( + "citusdb.count_distinct_error_rate", + gettext_noop("Desired error rate when calculating count(distinct) " + "approximates using the postgresql-hll extension. " + "0.0 disables approximations for count(distinct); 1.0 " + "provides no guarantees about the accuracy of results."), + NULL, + &CountDistinctErrorRate, + 0.0, 0.0, 1.0, + PGC_USERSET, + 0, + NULL, NULL, NULL); + + DefineCustomEnumVariable( + "citusdb.task_assignment_policy", + gettext_noop("Sets the policy to use when assigning tasks to worker nodes."), + gettext_noop("The master node assigns tasks to worker nodes based on shard " + "locations. This configuration value specifies the policy to " + "use when making these assignments. The greedy policy aims to " + "evenly distribute tasks across worker nodes, first-replica just " + "assigns tasks in the order shard placements were created, " + "and the round-robin policy assigns tasks to worker nodes in " + "a round-robin fashion."), + &TaskAssignmentPolicy, + TASK_ASSIGNMENT_GREEDY, + task_assignment_policy_options, + PGC_USERSET, + 0, + NULL, NULL, NULL); + + DefineCustomEnumVariable( + "citusdb.task_executor_type", + gettext_noop("Sets the executor type to be used for distributed queries."), + gettext_noop("The master node chooses between three different executor types " + "when executing a distributed query. The router executor is " + "optimal for simple key-value lookups on a single shard. The " + "real-time executor is optimal for queries that involve " + "aggregations and/or co-located joins on multiple shards. The " + "task-tracker executor is optimal for long-running, complex " + "queries that touch thousands of shards and/or that involve " + "table repartitioning."), + &TaskExecutorType, + MULTI_EXECUTOR_REAL_TIME, + task_executor_type_options, + PGC_USERSET, + 0, + NULL, NULL, NULL); + + DefineCustomEnumVariable( + "citusdb.shard_placement_policy", + gettext_noop("Sets the policy to use when choosing nodes for shard placement."), + gettext_noop("The master node chooses which worker nodes to place new shards " + "on. This configuration value specifies the policy to use when " + "selecting these nodes. The local-node-first policy places the " + "first replica on the client node and chooses others randomly. " + "The round-robin policy aims to distribute shards evenly across " + "the cluster by selecting nodes in a round-robin fashion."), + &ShardPlacementPolicy, + SHARD_PLACEMENT_ROUND_ROBIN, shard_placement_policy_options, + PGC_USERSET, + 0, + NULL, NULL, NULL); + + /* warn about config items in the citusdb namespace that are not registered above */ + EmitWarningsOnPlaceholders("citusdb"); + /* Also warn about citus namespace, as that's a very likely misspelling */ + EmitWarningsOnPlaceholders("citus"); +} + + +/* + * NormalizeWorkerListPath converts the path configured via + * citusdb.worker_list_file into an absolute path, falling back to the default + * value if necessary. The previous value of the config variable is + * overwritten with the normalized value. + * + * NB: This has to be called before ChangeToDataDir() is called as otherwise + * the relative paths won't make much sense to the user anymore. + */ +static void +NormalizeWorkerListPath(void) +{ + char *absoluteFileName = NULL; + + if (WorkerListFileName != NULL) + { + absoluteFileName = make_absolute_path(WorkerListFileName); + } + else if (DataDir != NULL) + { + absoluteFileName = malloc(strlen(DataDir) + strlen(WORKER_LIST_FILENAME) + 2); + if (absoluteFileName == NULL) + ereport(FATAL, (errcode(ERRCODE_OUT_OF_MEMORY), + errmsg("out of memory"))); + + sprintf(absoluteFileName, "%s/%s", DataDir, WORKER_LIST_FILENAME); + } + else + { + ereport(FATAL, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("%s does not know where to find the \"worker_list_file\" " + "configuration file.\n" + "This can be specified as \"citusdb.worker_list_file\" in " + "\"%s\", or by the -D invocation option, or by the PGDATA " + "environment variable.\n", progname, ConfigFileName))); + } + + SetConfigOption("citusdb.worker_list_file", absoluteFileName, PGC_POSTMASTER, PGC_S_OVERRIDE); + free(absoluteFileName); +} diff --git a/src/backend/distributed/test/connection_cache.c b/src/backend/distributed/test/connection_cache.c new file mode 100644 index 000000000..25fcbf593 --- /dev/null +++ b/src/backend/distributed/test/connection_cache.c @@ -0,0 +1,170 @@ +/*------------------------------------------------------------------------- + * + * test/src/connection_cache.c + * + * This file contains functions to exercise CitusDB's connection hash + * functionality for purposes of unit testing. + * + * Copyright (c) 2014-2015, Citus Data, Inc. + * + *------------------------------------------------------------------------- + */ + +#include "postgres.h" +#include "c.h" +#include "fmgr.h" +#include "libpq-int.h" + +#include +#include + +#include "catalog/pg_type.h" +#include "distributed/connection_cache.h" +#include "distributed/test_helper_functions.h" /* IWYU pragma: keep */ +#include "utils/lsyscache.h" + + +/* local function forward declarations */ +static Datum ExtractIntegerDatum(char *input); + + +/* declarations for dynamic loading */ +PG_FUNCTION_INFO_V1(initialize_remote_temp_table); +PG_FUNCTION_INFO_V1(count_remote_temp_table_rows); +PG_FUNCTION_INFO_V1(get_and_purge_connection); +PG_FUNCTION_INFO_V1(set_connection_status_bad); + + +/* + * initialize_remote_temp_table connects to a specified host on a specified + * port and creates a temporary table with 100 rows. Because the table is + * temporary, it will be visible if a connection is reused but not if a new + * connection is opened to the node. + */ +Datum +initialize_remote_temp_table(PG_FUNCTION_ARGS) +{ + char *nodeName = PG_GETARG_CSTRING(0); + int32 nodePort = PG_GETARG_INT32(1); + PGresult *result = NULL; + + PGconn *connection = GetConnection(nodeName, nodePort); + if (connection == NULL) + { + PG_RETURN_BOOL(false); + } + + result = PQexec(connection, POPULATE_TEMP_TABLE); + if (PQresultStatus(result) != PGRES_COMMAND_OK) + { + ReportRemoteError(connection, result); + } + + PQclear(result); + + PG_RETURN_BOOL(true); +} + + +/* + * count_remote_temp_table_rows just returns the integer count of rows in the + * table created by initialize_remote_temp_table. If no such table exists, this + * function emits a warning and returns -1. + */ +Datum +count_remote_temp_table_rows(PG_FUNCTION_ARGS) +{ + char *nodeName = PG_GETARG_CSTRING(0); + int32 nodePort = PG_GETARG_INT32(1); + Datum count = Int32GetDatum(-1); + PGresult *result = NULL; + + PGconn *connection = GetConnection(nodeName, nodePort); + if (connection == NULL) + { + PG_RETURN_DATUM(count); + } + + result = PQexec(connection, COUNT_TEMP_TABLE); + if (PQresultStatus(result) != PGRES_TUPLES_OK) + { + ReportRemoteError(connection, result); + } + else + { + char *countText = PQgetvalue(result, 0, 0); + count = ExtractIntegerDatum(countText); + } + + PQclear(result); + + PG_RETURN_DATUM(count); +} + + +/* + * get_and_purge_connection first gets a connection using the provided hostname + * and port before immediately passing that connection to PurgeConnection. + * Simply a wrapper around PurgeConnection that uses hostname/port rather than + * PGconn. + */ +Datum +get_and_purge_connection(PG_FUNCTION_ARGS) +{ + char *nodeName = PG_GETARG_CSTRING(0); + int32 nodePort = PG_GETARG_INT32(1); + + PGconn *connection = GetConnection(nodeName, nodePort); + if (connection == NULL) + { + PG_RETURN_BOOL(false); + } + + PurgeConnection(connection); + + PG_RETURN_BOOL(true); +} + + +/* + * set_connection_status_bad does not remove the given connection from the connection hash. + * It only sets its status to CONNECTION_BAD. On success, it returns true. + */ +Datum +set_connection_status_bad(PG_FUNCTION_ARGS) +{ + char *nodeName = PG_GETARG_CSTRING(0); + int32 nodePort = PG_GETARG_INT32(1); + + PGconn *connection = GetConnection(nodeName, nodePort); + if (connection == NULL) + { + PG_RETURN_BOOL(false); + } + + /* set the connection status */ + connection->status = CONNECTION_BAD; + + PG_RETURN_BOOL(true); +} + + +/* + * ExtractIntegerDatum transforms an integer in textual form into a Datum. + */ +static Datum +ExtractIntegerDatum(char *input) +{ + Oid typIoFunc = InvalidOid; + Oid typIoParam = InvalidOid; + Datum intDatum = 0; + FmgrInfo fmgrInfo; + memset(&fmgrInfo, 0, sizeof(fmgrInfo)); + + getTypeInputInfo(INT4OID, &typIoFunc, &typIoParam); + fmgr_info(typIoFunc, &fmgrInfo); + + intDatum = InputFunctionCall(&fmgrInfo, input, typIoFunc, -1); + + return intDatum; +} diff --git a/src/backend/distributed/test/create_shards.c b/src/backend/distributed/test/create_shards.c new file mode 100644 index 000000000..e6b2b5762 --- /dev/null +++ b/src/backend/distributed/test/create_shards.c @@ -0,0 +1,69 @@ +/*------------------------------------------------------------------------- + * + * test/src/create_shards.c + * + * This file contains functions to exercise shard creation functionality + * within CitusDB. + * + * Copyright (c) 2014-2015, Citus Data, Inc. + * + *------------------------------------------------------------------------- + */ + +#include "postgres.h" +#include "c.h" +#include "fmgr.h" + +#include + +#include "distributed/listutils.h" +#include "distributed/test_helper_functions.h" /* IWYU pragma: keep */ +#include "lib/stringinfo.h" +#include "nodes/pg_list.h" + + +/* local function forward declarations */ +static int CompareStrings(const void *leftElement, const void *rightElement); + + +/* declarations for dynamic loading */ +PG_FUNCTION_INFO_V1(sort_names); + + +/* + * sort_names accepts three strings, places them in a list, then calls PGSSortList + * to test its sort functionality. Returns a string containing sorted lines. + */ +Datum +sort_names(PG_FUNCTION_ARGS) +{ + char *first = PG_GETARG_CSTRING(0); + char *second = PG_GETARG_CSTRING(1); + char *third = PG_GETARG_CSTRING(2); + List *nameList = SortList(list_make3(first, second, third), + (int (*)(const void *, const void *))(&CompareStrings)); + StringInfo sortedNames = makeStringInfo(); + + ListCell *nameCell = NULL; + foreach(nameCell, nameList) + { + char *name = lfirst(nameCell); + appendStringInfo(sortedNames, "%s\n", name); + } + + + PG_RETURN_CSTRING(sortedNames->data); +} + + +/* + * A simple wrapper around strcmp suitable for use with PGSSortList or qsort. + */ +static int +CompareStrings(const void *leftElement, const void *rightElement) +{ + const char *leftString = *((const char **) leftElement); + const char *rightString = *((const char **) rightElement); + + return strcmp(leftString, rightString); +} diff --git a/src/backend/distributed/test/distribution_metadata.c b/src/backend/distributed/test/distribution_metadata.c new file mode 100644 index 000000000..f54359a19 --- /dev/null +++ b/src/backend/distributed/test/distribution_metadata.c @@ -0,0 +1,365 @@ +/*------------------------------------------------------------------------- + * + * test/src/distribution_metadata.c + * + * This file contains functions to exercise distributed table metadata + * functionality within CitusDB. + * + * Copyright (c) 2014-2015, Citus Data, Inc. + * + *------------------------------------------------------------------------- + */ + +#include "postgres.h" +#include "c.h" +#include "fmgr.h" + +#include +#include + +#include "access/heapam.h" +#include "catalog/pg_type.h" +#include "distributed/master_metadata_utility.h" +#include "distributed/master_protocol.h" +#include "distributed/metadata_cache.h" +#include "distributed/multi_join_order.h" +#include "distributed/pg_dist_shard.h" +#include "distributed/resource_lock.h" +#include "distributed/test_helper_functions.h" /* IWYU pragma: keep */ +#include "lib/stringinfo.h" +#include "nodes/pg_list.h" +#include "nodes/primnodes.h" +#include "storage/lock.h" +#include "utils/array.h" +#include "utils/elog.h" +#include "utils/errcodes.h" +#include "utils/builtins.h" +#include "utils/palloc.h" + + +/* declarations for dynamic loading */ +PG_FUNCTION_INFO_V1(load_shard_id_array); +PG_FUNCTION_INFO_V1(load_shard_interval_array); +PG_FUNCTION_INFO_V1(load_shard_placement_array); +PG_FUNCTION_INFO_V1(partition_column_id); +PG_FUNCTION_INFO_V1(partition_type); +PG_FUNCTION_INFO_V1(is_distributed_table); +PG_FUNCTION_INFO_V1(column_name_to_column); +PG_FUNCTION_INFO_V1(column_name_to_column_id); +PG_FUNCTION_INFO_V1(create_monolithic_shard_row); +PG_FUNCTION_INFO_V1(create_healthy_local_shard_placement_row); +PG_FUNCTION_INFO_V1(delete_shard_placement_row); +PG_FUNCTION_INFO_V1(update_shard_placement_row_state); +PG_FUNCTION_INFO_V1(acquire_shared_shard_lock); + + +/* + * load_shard_id_array returns the shard identifiers for a particular + * distributed table as a bigint array. If the table is not distributed + * yet, the function errors-out. + */ +Datum +load_shard_id_array(PG_FUNCTION_ARGS) +{ + Oid distributedTableId = PG_GETARG_OID(0); + ArrayType *shardIdArrayType = NULL; + ListCell *shardCell = NULL; + int shardIdIndex = 0; + Oid shardIdTypeId = INT8OID; + + int shardIdCount = -1; + Datum *shardIdDatumArray = NULL; + List *shardList = LoadShardIntervalList(distributedTableId); + + shardIdCount = list_length(shardList); + shardIdDatumArray = palloc0(shardIdCount * sizeof(Datum)); + + foreach(shardCell, shardList) + { + ShardInterval *shardId = (ShardInterval *) lfirst(shardCell); + Datum shardIdDatum = Int64GetDatum(shardId->shardId); + + shardIdDatumArray[shardIdIndex] = shardIdDatum; + shardIdIndex++; + } + + shardIdArrayType = DatumArrayToArrayType(shardIdDatumArray, shardIdCount, + shardIdTypeId); + + PG_RETURN_ARRAYTYPE_P(shardIdArrayType); +} + + +/* + * load_shard_interval_array loads a shard interval using a provided identifier + * and returns a two-element array consisting of min/max values contained in + * that shard interval. If no such interval can be found, this function raises + * an error instead. + */ +Datum +load_shard_interval_array(PG_FUNCTION_ARGS) +{ + int64 shardId = PG_GETARG_INT64(0); + Oid expectedType PG_USED_FOR_ASSERTS_ONLY = get_fn_expr_argtype(fcinfo->flinfo, 1); + ShardInterval *shardInterval = LoadShardInterval(shardId); + Datum shardIntervalArray[] = { shardInterval->minValue, shardInterval->maxValue }; + ArrayType *shardIntervalArrayType = NULL; + + Assert(expectedType == shardInterval->valueTypeId); + + shardIntervalArrayType = DatumArrayToArrayType(shardIntervalArray, 2, + shardInterval->valueTypeId); + + PG_RETURN_ARRAYTYPE_P(shardIntervalArrayType); +} + + +/* + * load_shard_placement_array loads a shard interval using the provided ID + * and returns an array of strings containing the node name and port for each + * placement of the specified shard interval. If the second argument is true, + * only finalized placements are returned; otherwise, all are. If no such shard + * interval can be found, this function raises an error instead. + */ +Datum +load_shard_placement_array(PG_FUNCTION_ARGS) +{ + int64 shardId = PG_GETARG_INT64(0); + bool onlyFinalized = PG_GETARG_BOOL(1); + ArrayType *placementArrayType = NULL; + List *placementList = NIL; + ListCell *placementCell = NULL; + int placementCount = -1; + int placementIndex = 0; + Datum *placementDatumArray = NULL; + Oid placementTypeId = TEXTOID; + StringInfo placementInfo = makeStringInfo(); + + if (onlyFinalized) + { + placementList = FinalizedShardPlacementList(shardId); + } + else + { + placementList = ShardPlacementList(shardId); + } + + placementCount = list_length(placementList); + placementDatumArray = palloc0(placementCount * sizeof(Datum)); + + foreach(placementCell, placementList) + { + ShardPlacement *placement = (ShardPlacement *) lfirst(placementCell); + appendStringInfo(placementInfo, "%s:%d", placement->nodeName, + placement->nodePort); + + placementDatumArray[placementIndex] = CStringGetTextDatum(placementInfo->data); + placementIndex++; + resetStringInfo(placementInfo); + } + + placementArrayType = DatumArrayToArrayType(placementDatumArray, placementCount, + placementTypeId); + + PG_RETURN_ARRAYTYPE_P(placementArrayType); +} + + +/* + * partition_column_id simply finds a distributed table using the provided Oid + * and returns the column_id of its partition column. If the specified table is + * not distributed, this function raises an error instead. + */ +Datum +partition_column_id(PG_FUNCTION_ARGS) +{ + Oid distributedTableId = PG_GETARG_OID(0); + uint32 rangeTableId = 1; + Var *partitionColumn = PartitionColumn(distributedTableId, rangeTableId); + + PG_RETURN_INT16((int16) partitionColumn->varattno); +} + + +/* + * partition_type simply finds a distributed table using the provided Oid and + * returns the type of partitioning in use by that table. If the specified + * table is not distributed, this function raises an error instead. + */ +Datum +partition_type(PG_FUNCTION_ARGS) +{ + Oid distributedTableId = PG_GETARG_OID(0); + char partitionType = PartitionMethod(distributedTableId); + + PG_RETURN_CHAR(partitionType); +} + + +/* + * is_distributed_table simply returns whether a given table is distributed. No + * errors, just a boolean. + */ +Datum +is_distributed_table(PG_FUNCTION_ARGS) +{ + Oid distributedTableId = PG_GETARG_OID(0); + bool isDistributedTable = IsDistributedTable(distributedTableId); + + PG_RETURN_BOOL(isDistributedTable); +} + + +/* + * column_name_to_column is an internal UDF to obtain a textual representation + * of a particular column node (Var), given a relation identifier and column + * name. There is no requirement that the table be distributed; this function + * simply returns the textual representation of a Var representing a column. + * This function will raise an ERROR if no such column can be found or if the + * provided name refers to a system column. + */ +Datum +column_name_to_column(PG_FUNCTION_ARGS) +{ + Oid relationId = PG_GETARG_OID(0); + text *columnText = PG_GETARG_TEXT_P(1); + Relation relation = NULL; + char *columnName = text_to_cstring(columnText); + Var *column = NULL; + char *columnNodeString = NULL; + text *columnNodeText = NULL; + + relation = relation_open(relationId, AccessExclusiveLock); + + column = (Var *) BuildDistributionKeyFromColumnName(relation, columnName); + columnNodeString = nodeToString(column); + columnNodeText = cstring_to_text(columnNodeString); + + relation_close(relation, NoLock); + + PG_RETURN_TEXT_P(columnNodeText); +} + + +/* + * column_name_to_column_id takes a relation identifier and a name of a column + * in that relation and returns the index of that column in the relation. If + * the provided name is a system column or no column at all, this function will + * throw an error instead. + */ +Datum +column_name_to_column_id(PG_FUNCTION_ARGS) +{ + Oid distributedTableId = PG_GETARG_OID(0); + char *columnName = PG_GETARG_CSTRING(1); + Relation relation = NULL; + Var *column = NULL; + + relation = relation_open(distributedTableId, AccessExclusiveLock); + + column = (Var *) BuildDistributionKeyFromColumnName(relation, columnName); + + relation_close(relation, NoLock); + + PG_RETURN_INT16((int16) column->varattno); +} + + +/* + * create_monolithic_shard_row creates a single shard covering all possible + * hash values for a given table and inserts a row representing that shard + * into the backing store. It returns the primary key of the new row. + */ +Datum +create_monolithic_shard_row(PG_FUNCTION_ARGS) +{ + Oid distributedTableId = PG_GETARG_OID(0); + StringInfo minInfo = makeStringInfo(); + StringInfo maxInfo = makeStringInfo(); + Datum newShardIdDatum = master_get_new_shardid(NULL); + int64 newShardId = DatumGetInt64(newShardIdDatum); + text *maxInfoText = NULL; + text *minInfoText = NULL; + + appendStringInfo(minInfo, "%d", INT32_MIN); + appendStringInfo(maxInfo, "%d", INT32_MAX); + + minInfoText = cstring_to_text(minInfo->data); + maxInfoText = cstring_to_text(maxInfo->data); + + InsertShardRow(distributedTableId, newShardId, SHARD_STORAGE_TABLE, minInfoText, + maxInfoText); + + PG_RETURN_INT64(newShardId); +} + + +/* + * create_healthy_local_shard_placement_row inserts a row representing a + * finalized placement for localhost (on the default port) into the backing + * store. + */ +Datum +create_healthy_local_shard_placement_row(PG_FUNCTION_ARGS) +{ + int64 shardId = PG_GETARG_INT64(0); + int64 shardLength = 0; + + InsertShardPlacementRow(shardId, FILE_FINALIZED, shardLength, "localhost", 5432); + + PG_RETURN_VOID(); +} + + +/* + * delete_shard_placement_row removes a shard placement with the specified ID. + */ +Datum +delete_shard_placement_row(PG_FUNCTION_ARGS) +{ + int64 shardId = PG_GETARG_INT64(0); + text *hostName = PG_GETARG_TEXT_P(1); + int64 hostPort = PG_GETARG_INT64(2); + bool successful = true; + char *hostNameString = text_to_cstring(hostName); + + DeleteShardPlacementRow(shardId, hostNameString, hostPort); + + PG_RETURN_BOOL(successful); +} + + +/* + * update_shard_placement_row_state sets the state of the placement with the + * specified ID. + */ +Datum +update_shard_placement_row_state(PG_FUNCTION_ARGS) +{ + int64 shardId = PG_GETARG_INT64(0); + text *hostName = PG_GETARG_TEXT_P(1); + int64 hostPort = PG_GETARG_INT64(2); + RelayFileState shardState = (RelayFileState) PG_GETARG_INT32(3); + bool successful = true; + char *hostNameString = text_to_cstring(hostName); + uint64 shardLength = 0; + + DeleteShardPlacementRow(shardId, hostNameString, hostPort); + InsertShardPlacementRow(shardId, shardState, shardLength, hostNameString, hostPort); + + PG_RETURN_BOOL(successful); +} + + +/* + * acquire_shared_shard_lock grabs a shared lock for the specified shard. + */ +Datum +acquire_shared_shard_lock(PG_FUNCTION_ARGS) +{ + int64 shardId = PG_GETARG_INT64(0); + + LockShardResource(shardId, ShareLock); + + PG_RETURN_VOID(); +} diff --git a/src/backend/distributed/test/fake_fdw.c b/src/backend/distributed/test/fake_fdw.c new file mode 100644 index 000000000..883c77755 --- /dev/null +++ b/src/backend/distributed/test/fake_fdw.c @@ -0,0 +1,168 @@ +/*------------------------------------------------------------------------- + * + * test/src/fake_fdw.c + * + * This file contains a barebones FDW implementation, suitable for use in + * test code. Inspired by Andrew Dunstan's blackhole_fdw. + * + * Copyright (c) 2014-2015, Citus Data, Inc. + * + *------------------------------------------------------------------------- + */ + +#include "postgres.h" +#include "c.h" +#include "fmgr.h" + +#include + +#include "distributed/test_helper_functions.h" /* IWYU pragma: keep */ +#include "executor/tuptable.h" +#include "foreign/fdwapi.h" +#include "nodes/execnodes.h" +#include "nodes/nodes.h" +#include "nodes/pg_list.h" +#include "nodes/plannodes.h" +#include "nodes/relation.h" +#include "optimizer/pathnode.h" +#include "optimizer/planmain.h" +#include "optimizer/restrictinfo.h" +#include "utils/palloc.h" + +/* local function forward declarations */ +static void FakeGetForeignRelSize(PlannerInfo *root, RelOptInfo *baserel, + Oid foreigntableid); +static void FakeGetForeignPaths(PlannerInfo *root, RelOptInfo *baserel, + Oid foreigntableid); +#if (PG_VERSION_NUM >= 90300 && PG_VERSION_NUM < 90500) +static ForeignScan * FakeGetForeignPlan(PlannerInfo *root, RelOptInfo *baserel, + Oid foreigntableid, ForeignPath *best_path, + List *tlist, List *scan_clauses); +#else +static ForeignScan * FakeGetForeignPlan(PlannerInfo *root, RelOptInfo *baserel, + Oid foreigntableid, ForeignPath *best_path, + List *tlist, List *scan_clauses, + Plan *outer_plan); +#endif +static void FakeBeginForeignScan(ForeignScanState *node, int eflags); +static TupleTableSlot * FakeIterateForeignScan(ForeignScanState *node); +static void FakeReScanForeignScan(ForeignScanState *node); +static void FakeEndForeignScan(ForeignScanState *node); + + +/* declarations for dynamic loading */ +PG_FUNCTION_INFO_V1(fake_fdw_handler); + + +/* + * fake_fdw_handler populates an FdwRoutine with pointers to the functions + * implemented within this file. + */ +Datum +fake_fdw_handler(PG_FUNCTION_ARGS) +{ + FdwRoutine *fdwroutine = makeNode(FdwRoutine); + + fdwroutine->GetForeignRelSize = FakeGetForeignRelSize; + fdwroutine->GetForeignPaths = FakeGetForeignPaths; + fdwroutine->GetForeignPlan = FakeGetForeignPlan; + fdwroutine->BeginForeignScan = FakeBeginForeignScan; + fdwroutine->IterateForeignScan = FakeIterateForeignScan; + fdwroutine->ReScanForeignScan = FakeReScanForeignScan; + fdwroutine->EndForeignScan = FakeEndForeignScan; + + PG_RETURN_POINTER(fdwroutine); +} + + +/* + * FakeGetForeignRelSize populates baserel with a fake relation size. + */ +static void +FakeGetForeignRelSize(PlannerInfo *root, RelOptInfo *baserel, Oid foreigntableid) +{ + baserel->rows = 0; + baserel->fdw_private = (void *) palloc0(1); +} + + +/* + * FakeGetForeignPaths adds a single fake foreign path to baserel. + */ +static void +FakeGetForeignPaths(PlannerInfo *root, RelOptInfo *baserel, Oid foreigntableid) +{ + Cost startup_cost = 0; + Cost total_cost = startup_cost + baserel->rows; + +#if (PG_VERSION_NUM >= 90300 && PG_VERSION_NUM < 90500) + add_path(baserel, (Path *) create_foreignscan_path(root, baserel, baserel->rows, + startup_cost, total_cost, NIL, + NULL, NIL)); +#else + add_path(baserel, (Path *) create_foreignscan_path(root, baserel, baserel->rows, + startup_cost, total_cost, NIL, + NULL, NULL, NIL)); +#endif +} + + +/* + * FakeGetForeignPlan builds a fake foreign plan. + */ +#if (PG_VERSION_NUM >= 90300 && PG_VERSION_NUM < 90500) +static ForeignScan * +FakeGetForeignPlan(PlannerInfo *root, RelOptInfo *baserel, Oid foreigntableid, + ForeignPath *best_path, List *tlist, List *scan_clauses) +#else +static ForeignScan * +FakeGetForeignPlan(PlannerInfo *root, RelOptInfo *baserel, Oid foreigntableid, + ForeignPath *best_path, List *tlist, List *scan_clauses, + Plan *outer_plan) +#endif +{ + Index scan_relid = baserel->relid; + scan_clauses = extract_actual_clauses(scan_clauses, false); + + /* make_foreignscan has a different signature in 9.3 and 9.4 than in 9.5 */ +#if (PG_VERSION_NUM >= 90300 && PG_VERSION_NUM < 90500) + return make_foreignscan(tlist, scan_clauses, scan_relid, NIL, NIL); +#else + return make_foreignscan(tlist, scan_clauses, scan_relid, NIL, NIL, NIL, NIL, + outer_plan); +#endif +} + + +/* + * FakeBeginForeignScan begins the fake plan (i.e. does nothing). + */ +static void +FakeBeginForeignScan(ForeignScanState *node, int eflags) { } + + +/* + * FakeIterateForeignScan continues the fake plan (i.e. does nothing). + */ +static TupleTableSlot * +FakeIterateForeignScan(ForeignScanState *node) +{ + TupleTableSlot *slot = node->ss.ss_ScanTupleSlot; + ExecClearTuple(slot); + + return slot; +} + + +/* + * FakeReScanForeignScan restarts the fake plan (i.e. does nothing). + */ +static void +FakeReScanForeignScan(ForeignScanState *node) { } + + +/* + * FakeEndForeignScan ends the fake plan (i.e. does nothing). + */ +static void +FakeEndForeignScan(ForeignScanState *node) { } diff --git a/src/backend/distributed/test/generate_ddl_commands.c b/src/backend/distributed/test/generate_ddl_commands.c new file mode 100644 index 000000000..4cbc225cf --- /dev/null +++ b/src/backend/distributed/test/generate_ddl_commands.c @@ -0,0 +1,67 @@ +/*------------------------------------------------------------------------- + * + * test/src/generate_ddl_commands.c + * + * This file contains functions to exercise DDL generation functionality + * within CitusDB. + * + * Copyright (c) 2014-2015, Citus Data, Inc. + * + *------------------------------------------------------------------------- + */ + +#include "postgres.h" +#include "c.h" +#include "fmgr.h" + +#include + +#include "catalog/pg_type.h" +#include "distributed/master_protocol.h" +#include "distributed/test_helper_functions.h" /* IWYU pragma: keep */ +#include "lib/stringinfo.h" +#include "nodes/makefuncs.h" +#include "nodes/nodes.h" +#include "nodes/parsenodes.h" +#include "nodes/pg_list.h" +#include "nodes/value.h" +#include "utils/array.h" +#include "utils/builtins.h" +#include "utils/palloc.h" + + +/* declarations for dynamic loading */ +PG_FUNCTION_INFO_V1(table_ddl_command_array); + + +/* + * table_ddl_command_array returns an array of strings, each of which is a DDL + * command required to recreate a table (specified by OID). + */ +Datum +table_ddl_command_array(PG_FUNCTION_ARGS) +{ + Oid distributedTableId = PG_GETARG_OID(0); + ArrayType *ddlCommandArrayType = NULL; + List *ddlCommandList = GetTableDDLEvents(distributedTableId); + int ddlCommandCount = list_length(ddlCommandList); + Datum *ddlCommandDatumArray = palloc0(ddlCommandCount * sizeof(Datum)); + + ListCell *ddlCommandCell = NULL; + int ddlCommandIndex = 0; + Oid ddlCommandTypeId = TEXTOID; + + foreach(ddlCommandCell, ddlCommandList) + { + char *ddlCommand = (char *) lfirst(ddlCommandCell); + Datum ddlCommandDatum = CStringGetTextDatum(ddlCommand); + + ddlCommandDatumArray[ddlCommandIndex] = ddlCommandDatum; + ddlCommandIndex++; + } + + ddlCommandArrayType = DatumArrayToArrayType(ddlCommandDatumArray, ddlCommandCount, + ddlCommandTypeId); + + PG_RETURN_ARRAYTYPE_P(ddlCommandArrayType); +} diff --git a/src/backend/distributed/test/prune_shard_list.c b/src/backend/distributed/test/prune_shard_list.c new file mode 100644 index 000000000..f722a70ec --- /dev/null +++ b/src/backend/distributed/test/prune_shard_list.c @@ -0,0 +1,214 @@ +/*------------------------------------------------------------------------- + * + * test/src/create_shards.c + * + * This file contains functions to exercise shard creation functionality + * within CitusDB. + * + * Copyright (c) 2014-2015, Citus Data, Inc. + * + *------------------------------------------------------------------------- + */ + +#include "postgres.h" +#include "c.h" +#include "fmgr.h" + +#include + +#if (PG_VERSION_NUM >= 90500 && PG_VERSION_NUM < 90600) +#include "access/stratnum.h" +#else +#include "access/skey.h" +#endif +#include "catalog/pg_type.h" +#include "distributed/master_metadata_utility.h" +#include "distributed/multi_join_order.h" +#include "distributed/multi_physical_planner.h" +#include "distributed/resource_lock.h" +#include "distributed/test_helper_functions.h" /* IWYU pragma: keep */ +#include "nodes/pg_list.h" +#include "nodes/primnodes.h" +#include "nodes/nodes.h" +#include "optimizer/clauses.h" +#include "utils/array.h" +#include "utils/palloc.h" + + +/* local function forward declarations */ +static Expr * MakeTextPartitionExpression(Oid distributedTableId, text *value); +static ArrayType * PrunedShardIdsForTable(Oid distributedTableId, List *whereClauseList); + + +/* declarations for dynamic loading */ +PG_FUNCTION_INFO_V1(prune_using_no_values); +PG_FUNCTION_INFO_V1(prune_using_single_value); +PG_FUNCTION_INFO_V1(prune_using_either_value); +PG_FUNCTION_INFO_V1(prune_using_both_values); +PG_FUNCTION_INFO_V1(debug_equality_expression); + + +/* + * prune_using_no_values returns the shards for the specified distributed table + * after pruning using an empty clause list. + */ +Datum +prune_using_no_values(PG_FUNCTION_ARGS) +{ + Oid distributedTableId = PG_GETARG_OID(0); + List *whereClauseList = NIL; + ArrayType *shardIdArrayType = PrunedShardIdsForTable(distributedTableId, + whereClauseList); + + PG_RETURN_ARRAYTYPE_P(shardIdArrayType); +} + + +/* + * prune_using_single_value returns the shards for the specified distributed + * table after pruning using a single value provided by the caller. + */ +Datum +prune_using_single_value(PG_FUNCTION_ARGS) +{ + Oid distributedTableId = PG_GETARG_OID(0); + text *value = (PG_ARGISNULL(1)) ? NULL : PG_GETARG_TEXT_P(1); + Expr *equalityExpr = MakeTextPartitionExpression(distributedTableId, value); + List *whereClauseList = list_make1(equalityExpr); + ArrayType *shardIdArrayType = PrunedShardIdsForTable(distributedTableId, + whereClauseList); + + PG_RETURN_ARRAYTYPE_P(shardIdArrayType); +} + + +/* + * prune_using_either_value returns the shards for the specified distributed + * table after pruning using either of two values provided by the caller (OR). + */ +Datum +prune_using_either_value(PG_FUNCTION_ARGS) +{ + Oid distributedTableId = PG_GETARG_OID(0); + text *firstValue = PG_GETARG_TEXT_P(1); + text *secondValue = PG_GETARG_TEXT_P(2); + Expr *firstQual = MakeTextPartitionExpression(distributedTableId, firstValue); + Expr *secondQual = MakeTextPartitionExpression(distributedTableId, secondValue); + Expr *orClause = make_orclause(list_make2(firstQual, secondQual)); + List *whereClauseList = list_make1(orClause); + ArrayType *shardIdArrayType = PrunedShardIdsForTable(distributedTableId, + whereClauseList); + + PG_RETURN_ARRAYTYPE_P(shardIdArrayType); +} + + +/* + * prune_using_both_values returns the shards for the specified distributed + * table after pruning using both of the values provided by the caller (AND). + */ +Datum +prune_using_both_values(PG_FUNCTION_ARGS) +{ + Oid distributedTableId = PG_GETARG_OID(0); + text *firstValue = PG_GETARG_TEXT_P(1); + text *secondValue = PG_GETARG_TEXT_P(2); + Expr *firstQual = MakeTextPartitionExpression(distributedTableId, firstValue); + Expr *secondQual = MakeTextPartitionExpression(distributedTableId, secondValue); + + List *whereClauseList = list_make2(firstQual, secondQual); + ArrayType *shardIdArrayType = PrunedShardIdsForTable(distributedTableId, + whereClauseList); + + PG_RETURN_ARRAYTYPE_P(shardIdArrayType); +} + + +/* + * debug_equality_expression returns the textual representation of an equality + * expression generated by a call to MakeOpExpression. + */ +Datum +debug_equality_expression(PG_FUNCTION_ARGS) +{ + Oid distributedTableId = PG_GETARG_OID(0); + uint32 rangeTableId = 1; + Var *partitionColumn = PartitionColumn(distributedTableId, rangeTableId); + OpExpr *equalityExpression = MakeOpExpression(partitionColumn, BTEqualStrategyNumber); + + PG_RETURN_CSTRING(nodeToString(equalityExpression)); +} + + +/* + * MakeTextPartitionExpression returns an equality expression between the + * specified table's partition column and the provided values. + */ +static Expr * +MakeTextPartitionExpression(Oid distributedTableId, text *value) +{ + uint32 rangeTableId = 1; + Var *partitionColumn = PartitionColumn(distributedTableId, rangeTableId); + Expr *partitionExpression = NULL; + + if (value != NULL) + { + OpExpr *equalityExpr = MakeOpExpression(partitionColumn, BTEqualStrategyNumber); + Const *rightConst = (Const *) get_rightop((Expr *) equalityExpr); + + rightConst->constvalue = (Datum) value; + rightConst->constisnull = false; + rightConst->constbyval = false; + + partitionExpression = (Expr *) equalityExpr; + } + else + { + NullTest *nullTest = makeNode(NullTest); + nullTest->arg = (Expr *) partitionColumn; + nullTest->nulltesttype = IS_NULL; + + partitionExpression = (Expr *) nullTest; + } + + return partitionExpression; +} + + +/* + * PrunedShardIdsForTable loads the shard intervals for the specified table, + * prunes them using the provided clauses. It returns an ArrayType containing + * the shard identifiers, suitable for return from an SQL-facing function. + */ +static ArrayType * +PrunedShardIdsForTable(Oid distributedTableId, List *whereClauseList) +{ + ArrayType *shardIdArrayType = NULL; + ListCell *shardCell = NULL; + int shardIdIndex = 0; + Oid shardIdTypeId = INT8OID; + Index tableId = 1; + + List *shardList = LoadShardIntervalList(distributedTableId); + int shardIdCount = -1; + Datum *shardIdDatumArray = NULL; + + shardList = PruneShardList(distributedTableId, tableId, whereClauseList, shardList); + + shardIdCount = list_length(shardList); + shardIdDatumArray = palloc0(shardIdCount * sizeof(Datum)); + + foreach(shardCell, shardList) + { + ShardInterval *shardId = (ShardInterval *) lfirst(shardCell); + Datum shardIdDatum = Int64GetDatum(shardId->shardId); + + shardIdDatumArray[shardIdIndex] = shardIdDatum; + shardIdIndex++; + } + + shardIdArrayType = DatumArrayToArrayType(shardIdDatumArray, shardIdCount, + shardIdTypeId); + + return shardIdArrayType; +} diff --git a/src/backend/distributed/test/test_helper_functions.c b/src/backend/distributed/test/test_helper_functions.c new file mode 100644 index 000000000..bc463c4c6 --- /dev/null +++ b/src/backend/distributed/test/test_helper_functions.c @@ -0,0 +1,39 @@ +/*------------------------------------------------------------------------- + * + * test/src/test_helper_functions.c + * + * This file contains helper functions used in many CitusDB tests. + * + * Copyright (c) 2014-2015, Citus Data, Inc. + * + *------------------------------------------------------------------------- + */ + +#include "postgres.h" +#include "c.h" + +#include + +#include "distributed/test_helper_functions.h" /* IWYU pragma: keep */ +#include "utils/array.h" +#include "utils/lsyscache.h" + + +/* + * DatumArrayToArrayType converts the provided Datum array (of the specified + * length and type) into an ArrayType suitable for returning from a UDF. + */ +ArrayType * +DatumArrayToArrayType(Datum *datumArray, int datumCount, Oid datumTypeId) +{ + ArrayType *arrayObject = NULL; + int16 typeLength = 0; + bool typeByValue = false; + char typeAlignment = 0; + + get_typlenbyvalalign(datumTypeId, &typeLength, &typeByValue, &typeAlignment); + arrayObject = construct_array(datumArray, datumCount, datumTypeId, + typeLength, typeByValue, typeAlignment); + + return arrayObject; +} diff --git a/src/backend/distributed/utils/citus_nodefuncs.c b/src/backend/distributed/utils/citus_nodefuncs.c new file mode 100644 index 000000000..b3858cbdf --- /dev/null +++ b/src/backend/distributed/utils/citus_nodefuncs.c @@ -0,0 +1,304 @@ +/*------------------------------------------------------------------------- + * + * citus_nodefuncs.c + * Helper functions for dealing with nodes + * + * Copyright (c) 2012-2015, Citus Data, Inc. + * + *------------------------------------------------------------------------- + */ + +#include "postgres.h" + +#include "catalog/pg_type.h" +#include "distributed/citus_nodefuncs.h" +#include "distributed/metadata_cache.h" + + +/* exports for SQL callable functions */ +PG_FUNCTION_INFO_V1(citusdb_extradata_container); + + +/* + * SetRangeTblExtraData adds additional data to a RTE, overwriting previous + * values, if present. + * + * The data is stored as RTE_FUNCTION type RTE of a special + * citus_extradata_container function, with the extra data serialized into the + * function arguments. That works, because these RTEs aren't used by Postgres + * to any significant degree, and Citus' variant of ruleutils.c knows how to + * deal with these extended RTEs. Note that rte->eref needs to be set prior + * to calling SetRangeTblExtraData to ensure the funccolcount can be set + * correctly. + * + * NB: If used for postgres defined RTEKinds, fields specific to that RTEKind + * will not be handled by out/readfuncs.c. For the current uses that's ok. + */ +void +SetRangeTblExtraData(RangeTblEntry *rte, CitusRTEKind rteKind, + char *fragmentSchemaName, char *fragmentTableName, + List *tableIdList) +{ + RangeTblFunction *fauxFunction = NULL; + FuncExpr *fauxFuncExpr = NULL; + Const *rteKindData = NULL; + Const *fragmentSchemaData = NULL; + Const *fragmentTableData = NULL; + Const *tableIdListData = NULL; + + Assert(rte->eref && rte->eref->colnames != NIL); + + /* store RTE kind as a plain int4 */ + rteKindData = makeNode(Const); + rteKindData->consttype = INT4OID; + rteKindData->constlen = 4; + rteKindData->constvalue = Int32GetDatum(rteKind); + rteKindData->constbyval = true; + rteKindData->constisnull = false; + rteKindData->location = -1; + + /* store the fragment schema as a cstring */ + fragmentSchemaData = makeNode(Const); + fragmentSchemaData->consttype = CSTRINGOID; + fragmentSchemaData->constlen = -2; + fragmentSchemaData->constvalue = CStringGetDatum(fragmentSchemaName); + fragmentSchemaData->constbyval = false; + fragmentSchemaData->constisnull = fragmentSchemaName == NULL; + fragmentSchemaData->location = -1; + + /* store the fragment name as a cstring */ + fragmentTableData = makeNode(Const); + fragmentTableData->consttype = CSTRINGOID; + fragmentTableData->constlen = -2; + fragmentTableData->constvalue = CStringGetDatum(fragmentTableName); + fragmentTableData->constbyval = false; + fragmentTableData->constisnull = fragmentTableName == NULL; + fragmentTableData->location = -1; + + /* store the table id list as an array of integers: FIXME */ + tableIdListData = makeNode(Const); + tableIdListData->consttype = CSTRINGOID; + tableIdListData->constbyval = false; + tableIdListData->constlen = -2; + tableIdListData->location = -1; + + /* serialize tableIdList to a string, seems simplest that way */ + if (tableIdList != NIL) + { + char *serializedList = nodeToString(tableIdList); + tableIdListData->constisnull = false; + tableIdListData->constvalue = CStringGetDatum(serializedList); + } + else + { + tableIdListData->constisnull = true; + } + + /* create function expression to store our faux arguments in */ + fauxFuncExpr = makeNode(FuncExpr); + fauxFuncExpr->funcid = CitusExtraDataContainerFuncId(); + fauxFuncExpr->funcretset = true; + fauxFuncExpr->location = -1; + fauxFuncExpr->args = list_make4(rteKindData, fragmentSchemaData, + fragmentTableData, tableIdListData); + + fauxFunction = makeNode(RangeTblFunction); + fauxFunction->funcexpr = (Node *) fauxFuncExpr; + + /* set the column count to pass ruleutils checks, not used elsewhere */ + fauxFunction->funccolcount = list_length(rte->eref->colnames); + + rte->rtekind = RTE_FUNCTION; + rte->functions = list_make1(fauxFunction); +} + + +/* + * ExtractRangeTblExtraData extracts extra data stored for a range table entry + * that previously has been stored with + * Set/ModifyRangeTblExtraData. Parameters can be NULL if unintersting. It is + * valid to use the function on a RTE without extra data. + */ +void +ExtractRangeTblExtraData(RangeTblEntry *rte, CitusRTEKind *rteKind, + char **fragmentSchemaName, char **fragmentTableName, + List **tableIdList) +{ + RangeTblFunction *fauxFunction = NULL; + FuncExpr *fauxFuncExpr = NULL; + Const *tmpConst = NULL; + + /* set base rte kind first, so this can be used for 'non-extended' RTEs as well */ + if (rteKind != NULL) + { + *rteKind = (CitusRTEKind) rte->rtekind; + } + + /* reset values of optionally-present fields, will later be overwritten, if present */ + if (fragmentSchemaName != NULL) + { + *fragmentSchemaName = NULL; + } + + if (fragmentTableName != NULL) + { + *fragmentTableName = NULL; + } + + if (tableIdList != NULL) + { + *tableIdList = NIL; + } + + + /* only function RTEs have our special extra data */ + if (rte->rtekind != RTE_FUNCTION) + { + return; + } + + /* we only ever generate one argument */ + if (list_length(rte->functions) != 1) + { + return; + } + + /* should pretty much always be a FuncExpr, but be liberal in what we expect... */ + fauxFunction = linitial(rte->functions); + if (!IsA(fauxFunction->funcexpr, FuncExpr)) + { + return; + } + + fauxFuncExpr = (FuncExpr *) fauxFunction->funcexpr; + + /* + * There will never be a range table entry with this function id, but for + * the purpose of this file. + */ + if (fauxFuncExpr->funcid != CitusExtraDataContainerFuncId()) + { + return; + } + + /* + * Extra data for rtes is stored in the function arguments. The first + * argument stores the rtekind, second fragmentSchemaName, third + * fragmentTableName, fourth tableIdList. + */ + if (list_length(fauxFuncExpr->args) != 4) + { + ereport(ERROR, (errmsg("unexpected number of function arguments to " + "citusdb_extradata_container"))); + return; + } + + /* extract rteKind */ + tmpConst = (Const *) linitial(fauxFuncExpr->args); + Assert(IsA(tmpConst, Const)); + Assert(tmpConst->consttype == INT4OID); + if (rteKind != NULL) + { + *rteKind = DatumGetInt32(tmpConst->constvalue); + } + + /* extract fragmentSchemaName */ + tmpConst = (Const *) lsecond(fauxFuncExpr->args); + Assert(IsA(tmpConst, Const)); + Assert(tmpConst->consttype == CSTRINGOID); + if (fragmentSchemaName != NULL && !tmpConst->constisnull) + { + *fragmentSchemaName = DatumGetCString(tmpConst->constvalue); + } + + /* extract fragmentTableName */ + tmpConst = (Const *) lthird(fauxFuncExpr->args); + Assert(IsA(tmpConst, Const)); + Assert(tmpConst->consttype == CSTRINGOID); + if (fragmentTableName != NULL && !tmpConst->constisnull) + { + *fragmentTableName = DatumGetCString(tmpConst->constvalue); + } + + /* extract tableIdList, stored as a serialized integer list */ + tmpConst = (Const *) lfourth(fauxFuncExpr->args); + Assert(IsA(tmpConst, Const)); + Assert(tmpConst->consttype == CSTRINGOID); + if (tableIdList != NULL && !tmpConst->constisnull) + { + Node *deserializedList = stringToNode(DatumGetCString(tmpConst->constvalue)); + Assert(IsA(deserializedList, IntList)); + + *tableIdList = (List *) deserializedList; + } +} + + +/* + * ModifyRangeTblExtraData sets the RTE extra data fields for the passed + * fields, leaving the current values in place for the ones not specified. + * + * rteKind has to be specified, fragmentSchemaName, fragmentTableName, + * tableIdList can be set to NULL/NIL respectively to leave the current values + * in-place. + */ +void +ModifyRangeTblExtraData(RangeTblEntry *rte, CitusRTEKind rteKind, + char *fragmentSchemaName, char *fragmentTableName, + List *tableIdList) +{ + /* load existing values for the arguments not specifying a new value */ + ExtractRangeTblExtraData(rte, NULL, + fragmentSchemaName == NULL ? &fragmentSchemaName : NULL, + fragmentTableName == NULL ? &fragmentTableName : NULL, + tableIdList == NIL ? &tableIdList : NULL); + + SetRangeTblExtraData(rte, rteKind, + fragmentSchemaName, fragmentTableName, + tableIdList); +} + + +/* GetRangeTblKind returns rtekind of a RTE, be it an extended one or not. */ +CitusRTEKind +GetRangeTblKind(RangeTblEntry *rte) +{ + CitusRTEKind rteKind = CITUS_RTE_RELATION /* invalid */; + + switch(rte->rtekind) + { + /* directly rtekind if it's not possibly an extended RTE */ + case RTE_RELATION: + case RTE_SUBQUERY: + case RTE_JOIN: + case RTE_VALUES: + case RTE_CTE: + rteKind = (CitusRTEKind) rte->rtekind; + break; + case RTE_FUNCTION: + /* + * Extract extra data - correct even if a plain RTE_FUNCTION, not + * an extended one, ExtractRangeTblExtraData handles that case + * transparently. + */ + ExtractRangeTblExtraData(rte, &rteKind, NULL, NULL, NULL); + break; + } + + return rteKind; +} + + +/* + * citusdb_extradata_container is a placeholder function to store information + * needed by CitusDB in plain postgres node trees. Executor and other hooks + * should always intercept statements containing calls to this function. It's + * not actually SQL callable by the user because of an INTERNAL argument. + */ +Datum +citusdb_extradata_container(PG_FUNCTION_ARGS) +{ + ereport(ERROR, (errmsg("not supposed to get here, did you cheat?"))); + + PG_RETURN_NULL(); +} diff --git a/src/backend/distributed/utils/citus_outfuncs.c b/src/backend/distributed/utils/citus_outfuncs.c new file mode 100644 index 000000000..bb620987a --- /dev/null +++ b/src/backend/distributed/utils/citus_outfuncs.c @@ -0,0 +1,595 @@ +/*------------------------------------------------------------------------- + * + * citus_outfuncs.c + * Output functions for CitusDB tree nodes. + * + * Portions Copyright (c) 1996-2014, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * Portions Copyright (c) 2012-2015, Citus Data, Inc. + * + * NOTES + * This is a wrapper around postgres' nodeToString() that additionally + * supports CitusDB node types. + * + * Keep as closely aligned with the upstream version as possible. + * + *------------------------------------------------------------------------- + */ + +#include "postgres.h" + +#include + +#include "distributed/citus_nodefuncs.h" +#include "distributed/citus_nodes.h" +#include "distributed/multi_logical_planner.h" +#include "distributed/multi_physical_planner.h" +#include "distributed/master_metadata_utility.h" +#include "lib/stringinfo.h" +#include "nodes/plannodes.h" +#include "nodes/relation.h" +#include "utils/datum.h" + + +/* + * Macros to simplify output of different kinds of fields. Use these + * wherever possible to reduce the chance for silly typos. Note that these + * hard-wire conventions about the names of the local variables in an Out + * routine. + */ + +/* Write the label for the node type */ +#define WRITE_NODE_TYPE(nodelabel) \ + appendStringInfoString(str, nodelabel) + +/* Write an integer field (anything written as ":fldname %d") */ +#define WRITE_INT_FIELD(fldname) \ + appendStringInfo(str, " :" CppAsString(fldname) " %d", node->fldname) + +/* Write an unsigned integer field (anything written as ":fldname %u") */ +#define WRITE_UINT_FIELD(fldname) \ + appendStringInfo(str, " :" CppAsString(fldname) " %u", node->fldname) + +/* XXX: Citus: Write an unsigned 64-bit integer field */ +#define WRITE_UINT64_FIELD(fldname) \ + appendStringInfo(str, " :" CppAsString(fldname) " " UINT64_FORMAT, node->fldname) + +/* Write an OID field (don't hard-wire assumption that OID is same as uint) */ +#define WRITE_OID_FIELD(fldname) \ + appendStringInfo(str, " :" CppAsString(fldname) " %u", node->fldname) + +/* Write a long-integer field */ +#define WRITE_LONG_FIELD(fldname) \ + appendStringInfo(str, " :" CppAsString(fldname) " %ld", node->fldname) + +/* Write a char field (ie, one ascii character) */ +#define WRITE_CHAR_FIELD(fldname) \ + appendStringInfo(str, " :" CppAsString(fldname) " %c", node->fldname) + +/* Write an enumerated-type field as an integer code */ +#define WRITE_ENUM_FIELD(fldname, enumtype) \ + appendStringInfo(str, " :" CppAsString(fldname) " %d", \ + (int) node->fldname) + +/* Write a float field --- caller must give format to define precision */ +#define WRITE_FLOAT_FIELD(fldname,format) \ + appendStringInfo(str, " :" CppAsString(fldname) " " format, node->fldname) + +/* Write a boolean field */ +#define WRITE_BOOL_FIELD(fldname) \ + appendStringInfo(str, " :" CppAsString(fldname) " %s", \ + booltostr(node->fldname)) + +/* Write a character-string (possibly NULL) field */ +#define WRITE_STRING_FIELD(fldname) \ + (appendStringInfo(str, " :" CppAsString(fldname) " "), \ + _outToken(str, node->fldname)) + +/* Write a parse location field (actually same as INT case) */ +#define WRITE_LOCATION_FIELD(fldname) \ + appendStringInfo(str, " :" CppAsString(fldname) " %d", node->fldname) + +/* Write a Node field */ +#define WRITE_NODE_FIELD(fldname) \ + (appendStringInfo(str, " :" CppAsString(fldname) " "), \ + _outNode(str, node->fldname)) + +/* Write a bitmapset field */ +#define WRITE_BITMAPSET_FIELD(fldname) \ + (appendStringInfo(str, " :" CppAsString(fldname) " "), \ + _outBitmapset(str, node->fldname)) + + +#define booltostr(x) ((x) ? "true" : "false") + +static void _outNode(StringInfo str, const void *obj); + + +/* + * _outToken + * Convert an ordinary string (eg, an identifier) into a form that + * will be decoded back to a plain token by read.c's functions. + * + * If a null or empty string is given, it is encoded as "<>". + */ +static void +_outToken(StringInfo str, const char *s) +{ + if (s == NULL || *s == '\0') + { + appendStringInfoString(str, "<>"); + return; + } + + /* + * Look for characters or patterns that are treated specially by read.c + * (either in pg_strtok() or in nodeRead()), and therefore need a + * protective backslash. + */ + /* These characters only need to be quoted at the start of the string */ + if (*s == '<' || + *s == '\"' || + isdigit((unsigned char) *s) || + ((*s == '+' || *s == '-') && + (isdigit((unsigned char) s[1]) || s[1] == '.'))) + appendStringInfoChar(str, '\\'); + while (*s) + { + /* These chars must be backslashed anywhere in the string */ + if (*s == ' ' || *s == '\n' || *s == '\t' || + *s == '(' || *s == ')' || *s == '{' || *s == '}' || + *s == '\\') + appendStringInfoChar(str, '\\'); + appendStringInfoChar(str, *s++); + } +} + + +static void +_outList(StringInfo str, const List *node) +{ + const ListCell *lc; + + appendStringInfoChar(str, '('); + + if (IsA(node, IntList)) + appendStringInfoChar(str, 'i'); + else if (IsA(node, OidList)) + appendStringInfoChar(str, 'o'); + + foreach(lc, node) + { + /* + * For the sake of backward compatibility, we emit a slightly + * different whitespace format for lists of nodes vs. other types of + * lists. XXX: is this necessary? + */ + if (IsA(node, List)) + { + _outNode(str, lfirst(lc)); + if (lnext(lc)) + appendStringInfoChar(str, ' '); + } + else if (IsA(node, IntList)) + appendStringInfo(str, " %d", lfirst_int(lc)); + else if (IsA(node, OidList)) + appendStringInfo(str, " %u", lfirst_oid(lc)); + else + elog(ERROR, "unrecognized list node type: %d", + (int) node->type); + } + + appendStringInfoChar(str, ')'); +} + + +/* + * Print the value of a Datum given its type. + */ +static void +_outDatum(StringInfo str, Datum value, int typlen, bool typbyval) +{ + Size length, + i; + char *s; + + length = datumGetSize(value, typbyval, typlen); + + if (typbyval) + { + s = (char *) (&value); + appendStringInfo(str, "%u [ ", (unsigned int) length); + for (i = 0; i < (Size) sizeof(Datum); i++) + appendStringInfo(str, "%d ", (int) (s[i])); + appendStringInfoChar(str, ']'); + } + else + { + s = (char *) DatumGetPointer(value); + if (!PointerIsValid(s)) + appendStringInfoString(str, "0 [ ]"); + else + { + appendStringInfo(str, "%u [ ", (unsigned int) length); + for (i = 0; i < length; i++) + appendStringInfo(str, "%d ", (int) (s[i])); + appendStringInfoChar(str, ']'); + } + } +} + + +/***************************************************************************** + * Output routines for CitusDB node types + *****************************************************************************/ + +static void +_outMultiUnaryNode(StringInfo str, const MultiUnaryNode *node) +{ + WRITE_NODE_FIELD(childNode); +} + + +static void +_outMultiBinaryNode(StringInfo str, const MultiBinaryNode *node) +{ + WRITE_NODE_FIELD(leftChildNode); + WRITE_NODE_FIELD(rightChildNode); +} + + +static void +_outMultiTreeRoot(StringInfo str, const MultiTreeRoot *node) +{ + WRITE_NODE_TYPE("MULTITREEROOT"); + + _outMultiUnaryNode(str, (const MultiUnaryNode *) node); +} + + +static void +_outMultiPlan(StringInfo str, const MultiPlan *node) +{ + WRITE_NODE_TYPE("MULTIPLAN"); + + WRITE_NODE_FIELD(workerJob); + WRITE_NODE_FIELD(masterQuery); + WRITE_STRING_FIELD(masterTableName); +} + + +static void +_outMultiProject(StringInfo str, const MultiProject *node) +{ + WRITE_NODE_TYPE("MULTIPROJECT"); + + WRITE_NODE_FIELD(columnList); + + _outMultiUnaryNode(str, (const MultiUnaryNode *) node); +} + + +static void +_outMultiCollect(StringInfo str, const MultiCollect *node) +{ + WRITE_NODE_TYPE("MULTICOLLECT"); + + _outMultiUnaryNode(str, (const MultiUnaryNode *) node); +} + + +static void +_outMultiSelect(StringInfo str, const MultiSelect *node) +{ + WRITE_NODE_TYPE("MULTISELECT"); + + WRITE_NODE_FIELD(selectClauseList); + + _outMultiUnaryNode(str, (const MultiUnaryNode *) node); +} + + +static void +_outMultiTable(StringInfo str, const MultiTable *node) +{ + WRITE_NODE_TYPE("MULTITABLE"); + + WRITE_OID_FIELD(relationId); + WRITE_INT_FIELD(rangeTableId); + + _outMultiUnaryNode(str, (const MultiUnaryNode *) node); +} + + +static void +_outMultiJoin(StringInfo str, const MultiJoin *node) +{ + WRITE_NODE_TYPE("MULTIJOIN"); + + WRITE_NODE_FIELD(joinClauseList); + WRITE_ENUM_FIELD(joinRuleType, JoinRuleType); + WRITE_ENUM_FIELD(joinType, JoinType); + + _outMultiBinaryNode(str, (const MultiBinaryNode *) node); +} + + +static void +_outMultiPartition(StringInfo str, const MultiPartition *node) +{ + WRITE_NODE_TYPE("MULTIPARTITION"); + + WRITE_NODE_FIELD(partitionColumn); + + _outMultiUnaryNode(str, (const MultiUnaryNode *) node); +} + + +static void +_outMultiCartesianProduct(StringInfo str, const MultiCartesianProduct *node) +{ + WRITE_NODE_TYPE("MULTICARTESIANPRODUCT"); + + _outMultiBinaryNode(str, (const MultiBinaryNode *) node); +} + + + + +static void +_outMultiExtendedOp(StringInfo str, const MultiExtendedOp *node) +{ + WRITE_NODE_TYPE("MULTIEXTENDEDOP"); + + WRITE_NODE_FIELD(targetList); + WRITE_NODE_FIELD(groupClauseList); + WRITE_NODE_FIELD(sortClauseList); + WRITE_NODE_FIELD(limitCount); + WRITE_NODE_FIELD(limitOffset); + + _outMultiUnaryNode(str, (const MultiUnaryNode *) node); +} + +static void +_outJobInfo(StringInfo str, const Job *node) +{ + WRITE_UINT64_FIELD(jobId); + WRITE_NODE_FIELD(jobQuery); + WRITE_NODE_FIELD(taskList); + WRITE_NODE_FIELD(dependedJobList); + WRITE_BOOL_FIELD(subqueryPushdown); +} + + +static void +_outJob(StringInfo str, const Job *node) +{ + WRITE_NODE_TYPE("JOB"); + + _outJobInfo(str, node); +} + + +static void +_outShardInterval(StringInfo str, const ShardInterval *node) +{ + WRITE_NODE_TYPE("SHARDINTERVAL"); + + WRITE_OID_FIELD(relationId); + WRITE_CHAR_FIELD(storageType); + WRITE_OID_FIELD(valueTypeId); + WRITE_INT_FIELD(valueTypeLen); + WRITE_BOOL_FIELD(valueByVal); + WRITE_BOOL_FIELD(minValueExists); + WRITE_BOOL_FIELD(maxValueExists); + + appendStringInfoString(str, " :minValue "); + if (!node->minValueExists) + appendStringInfoString(str, "<>"); + else + _outDatum(str, node->minValue, node->valueTypeLen, node->valueByVal); + + appendStringInfoString(str, " :maxValue "); + if (!node->maxValueExists) + appendStringInfoString(str, "<>"); + else + _outDatum(str, node->maxValue, node->valueTypeLen, node->valueByVal); + + WRITE_UINT64_FIELD(shardId); +} + + +static void +_outMapMergeJob(StringInfo str, const MapMergeJob *node) +{ + int arrayLength = node->sortedShardIntervalArrayLength; + int i; + + WRITE_NODE_TYPE("MAPMERGEJOB"); + + _outJobInfo(str, (Job *) node); + WRITE_NODE_FIELD(reduceQuery); + WRITE_ENUM_FIELD(partitionType, PartitionType); + WRITE_NODE_FIELD(partitionColumn); + WRITE_UINT_FIELD(partitionCount); + WRITE_INT_FIELD(sortedShardIntervalArrayLength); + + for (i = 0; i < arrayLength; ++i) + { + ShardInterval *writeElement = node->sortedShardIntervalArray[i]; + + _outShardInterval(str, writeElement); + } + + WRITE_NODE_FIELD(mapTaskList); + WRITE_NODE_FIELD(mergeTaskList); +} + + +static void +_outShardPlacement(StringInfo str, const ShardPlacement *node) +{ + WRITE_NODE_TYPE("SHARDPLACEMENT"); + + WRITE_OID_FIELD(tupleOid); + WRITE_UINT64_FIELD(shardId); + WRITE_UINT64_FIELD(shardLength); + WRITE_ENUM_FIELD(shardState, RelayFileState); + WRITE_STRING_FIELD(nodeName); + WRITE_UINT_FIELD(nodePort); +} + + +static void +_outTask(StringInfo str, const Task *node) +{ + WRITE_NODE_TYPE("TASK"); + + WRITE_ENUM_FIELD(taskType, TaskType); + WRITE_UINT64_FIELD(jobId); + WRITE_UINT_FIELD(taskId); + WRITE_STRING_FIELD(queryString); + WRITE_UINT64_FIELD(anchorShardId); + WRITE_NODE_FIELD(taskPlacementList); + WRITE_NODE_FIELD(dependedTaskList); + WRITE_UINT_FIELD(partitionId); + WRITE_UINT_FIELD(upstreamTaskId); + WRITE_NODE_FIELD(shardInterval); + WRITE_BOOL_FIELD(assignmentConstrained); + WRITE_NODE_FIELD(taskExecution); + WRITE_BOOL_FIELD(upsertQuery); +} + + +/* + * _outNode - + * converts a Node into ascii string and append it to 'str' + */ +static void +_outNode(StringInfo str, const void *obj) +{ + if (obj == NULL) + { + appendStringInfoString(str, "<>"); + return; + } + + + switch (CitusNodeTag(obj)) + { + case T_List: + case T_IntList: + case T_OidList: + _outList(str, obj); + break; + + case T_MultiTreeRoot: + appendStringInfoChar(str, '{'); + _outMultiTreeRoot(str, obj); + appendStringInfoChar(str, '}'); + break; + + case T_MultiProject: + appendStringInfoChar(str, '{'); + _outMultiProject(str, obj); + appendStringInfoChar(str, '}'); + break; + + case T_MultiCollect: + appendStringInfoChar(str, '{'); + _outMultiCollect(str, obj); + appendStringInfoChar(str, '}'); + break; + + case T_MultiSelect: + appendStringInfoChar(str, '{'); + _outMultiSelect(str, obj); + appendStringInfoChar(str, '}'); + break; + + case T_MultiTable: + appendStringInfoChar(str, '{'); + _outMultiTable(str, obj); + appendStringInfoChar(str, '}'); + break; + + case T_MultiJoin: + appendStringInfoChar(str, '{'); + _outMultiJoin(str, obj); + appendStringInfoChar(str, '}'); + break; + + case T_MultiPartition: + appendStringInfoChar(str, '{'); + _outMultiPartition(str, obj); + appendStringInfoChar(str, '}'); + break; + + case T_MultiCartesianProduct: + appendStringInfoChar(str, '{'); + _outMultiCartesianProduct(str, obj); + appendStringInfoChar(str, '}'); + break; + + case T_MultiExtendedOp: + appendStringInfoChar(str, '{'); + _outMultiExtendedOp(str, obj); + appendStringInfoChar(str, '}'); + break; + + case T_Job: + appendStringInfoChar(str, '{'); + _outJob(str, obj); + appendStringInfoChar(str, '}'); + break; + + case T_MapMergeJob: + appendStringInfoChar(str, '{'); + _outMapMergeJob(str, obj); + appendStringInfoChar(str, '}'); + break; + + case T_MultiPlan: + appendStringInfoChar(str, '{'); + _outMultiPlan(str, obj); + appendStringInfoChar(str, '}'); + break; + + case T_Task: + appendStringInfoChar(str, '{'); + _outTask(str, obj); + appendStringInfoChar(str, '}'); + break; + + case T_ShardInterval: + appendStringInfoChar(str, '{'); + _outShardInterval(str, obj); + appendStringInfoChar(str, '}'); + break; + + case T_ShardPlacement: + appendStringInfoChar(str, '{'); + _outShardPlacement(str, obj); + appendStringInfoChar(str, '}'); + break; + + default: + /* fall back into postgres' normal nodeToString machinery */ + appendStringInfoString(str, nodeToString(obj)); + } +} + + +/* + * CitusNodeToString - + * returns the ascii representation of the Node as a palloc'd string + */ +char * +CitusNodeToString(const void *obj) +{ + StringInfoData str; + + initStringInfo(&str); + _outNode(&str, obj); + return str.data; +} diff --git a/src/backend/distributed/utils/citus_read.c b/src/backend/distributed/utils/citus_read.c new file mode 100644 index 000000000..5720013fc --- /dev/null +++ b/src/backend/distributed/utils/citus_read.c @@ -0,0 +1,348 @@ +/*------------------------------------------------------------------------- + * + * citus_read.c + * Citus version of postgres' read.c, using a different state variable for + * citus_pg_strtok. + * + * Portions Copyright (c) 1996-2014, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * Portions Copyright (c) 2012-2015, Citus Data, Inc. + * + * NOTES + * Unfortunately we have to copy this file as the state variable for + * pg_strtok is not externally accessible. That prevents creating a a + * version of stringToNode() that calls CitusNodeRead() instead of + * nodeRead(). Luckily these functions seldomly change. + * + * Keep as closely aligned with the upstream version as possible. + * + *------------------------------------------------------------------------- + */ + +#include "postgres.h" + +#include + +#include "nodes/pg_list.h" +#include "nodes/readfuncs.h" +#include "distributed/citus_nodefuncs.h" +#include "nodes/value.h" + + +/* Static state for citus_pg_strtok */ +static char *citus_pg_strtok_ptr = NULL; + + +/* + * CitusStringToNode - + * returns a Node with a given legal ASCII representation + */ +void * +CitusStringToNode(char *str) +{ + char *save_strtok; + void *retval; + + /* + * We save and restore the pre-existing state of citus_pg_strtok. This makes the + * world safe for re-entrant invocation of stringToNode, without incurring + * a lot of notational overhead by having to pass the next-character + * pointer around through all the readfuncs.c code. + */ + save_strtok = citus_pg_strtok_ptr; + + citus_pg_strtok_ptr = str; /* point citus_pg_strtok at the string to read */ + + retval = CitusNodeRead(NULL, 0); /* do the reading */ + + citus_pg_strtok_ptr = save_strtok; + + return retval; +} + +/* + * citus_pg_strtok is a copy of postgres' pg_strtok routine, referencing + * citus_pg_strtok_ptr instead of pg_strtok_ptr as state. +*/ +char * +citus_pg_strtok(int *length) +{ + char *local_str; /* working pointer to string */ + char *ret_str; /* start of token to return */ + + local_str = citus_pg_strtok_ptr; + + while (*local_str == ' ' || *local_str == '\n' || *local_str == '\t') + local_str++; + + if (*local_str == '\0') + { + *length = 0; + citus_pg_strtok_ptr = local_str; + return NULL; /* no more tokens */ + } + + /* + * Now pointing at start of next token. + */ + ret_str = local_str; + + if (*local_str == '(' || *local_str == ')' || + *local_str == '{' || *local_str == '}') + { + /* special 1-character token */ + local_str++; + } + else + { + /* Normal token, possibly containing backslashes */ + while (*local_str != '\0' && + *local_str != ' ' && *local_str != '\n' && + *local_str != '\t' && + *local_str != '(' && *local_str != ')' && + *local_str != '{' && *local_str != '}') + { + if (*local_str == '\\' && local_str[1] != '\0') + local_str += 2; + else + local_str++; + } + } + + *length = local_str - ret_str; + + /* Recognize special case for "empty" token */ + if (*length == 2 && ret_str[0] == '<' && ret_str[1] == '>') + *length = 0; + + citus_pg_strtok_ptr = local_str; + + return ret_str; +} + +#define RIGHT_PAREN (1000000 + 1) +#define LEFT_PAREN (1000000 + 2) +#define LEFT_BRACE (1000000 + 3) +#define OTHER_TOKEN (1000000 + 4) + +/* + * nodeTokenType - + * returns the type of the node token contained in token. + * It returns one of the following valid NodeTags: + * T_Integer, T_Float, T_String, T_BitString + * and some of its own: + * RIGHT_PAREN, LEFT_PAREN, LEFT_BRACE, OTHER_TOKEN + * + * Assumption: the ascii representation is legal + */ +static NodeTag +nodeTokenType(char *token, int length) +{ + NodeTag retval; + char *numptr; + int numlen; + + /* + * Check if the token is a number + */ + numptr = token; + numlen = length; + if (*numptr == '+' || *numptr == '-') + numptr++, numlen--; + if ((numlen > 0 && isdigit((unsigned char) *numptr)) || + (numlen > 1 && *numptr == '.' && isdigit((unsigned char) numptr[1]))) + { + /* + * Yes. Figure out whether it is integral or float; this requires + * both a syntax check and a range check. strtol() can do both for us. + * We know the token will end at a character that strtol will stop at, + * so we do not need to modify the string. + */ + long val; + char *endptr; + + errno = 0; + val = strtol(token, &endptr, 10); + (void) val; /* avoid compiler warning if unused */ + if (endptr != token + length || errno == ERANGE +#ifdef HAVE_LONG_INT_64 + /* if long > 32 bits, check for overflow of int4 */ + || val != (long) ((int32) val) +#endif + ) + return T_Float; + return T_Integer; + } + + /* + * these three cases do not need length checks, since citus_pg_strtok() will + * always treat them as single-byte tokens + */ + else if (*token == '(') + retval = LEFT_PAREN; + else if (*token == ')') + retval = RIGHT_PAREN; + else if (*token == '{') + retval = LEFT_BRACE; + else if (*token == '\"' && length > 1 && token[length - 1] == '\"') + retval = T_String; + else if (*token == 'b') + retval = T_BitString; + else + retval = OTHER_TOKEN; + return retval; +} + + +/* + * CitusNodeRead is an adapted copy of postgres' nodeRead routine, using + * citus_pg_strtok_ptr instead of pg_strtok_ptr. + */ +void * +CitusNodeRead(char *token, int tok_len) +{ + Node *result; + NodeTag type; + + if (token == NULL) /* need to read a token? */ + { + token = citus_pg_strtok(&tok_len); + + if (token == NULL) /* end of input */ + return NULL; + } + + type = nodeTokenType(token, tok_len); + + switch ((int) type) + { + case LEFT_BRACE: + result = CitusParseNodeString(); + token = citus_pg_strtok(&tok_len); + if (token == NULL || token[0] != '}') + elog(ERROR, "did not find '}' at end of input node"); + break; + case LEFT_PAREN: + { + List *l = NIL; + + /*---------- + * Could be an integer list: (i int int ...) + * or an OID list: (o int int ...) + * or a list of nodes/values: (node node ...) + *---------- + */ + token = citus_pg_strtok(&tok_len); + if (token == NULL) + elog(ERROR, "unterminated List structure"); + if (tok_len == 1 && token[0] == 'i') + { + /* List of integers */ + for (;;) + { + int val; + char *endptr; + + token = citus_pg_strtok(&tok_len); + if (token == NULL) + elog(ERROR, "unterminated List structure"); + if (token[0] == ')') + break; + val = (int) strtol(token, &endptr, 10); + if (endptr != token + tok_len) + elog(ERROR, "unrecognized integer: \"%.*s\"", + tok_len, token); + l = lappend_int(l, val); + } + } + else if (tok_len == 1 && token[0] == 'o') + { + /* List of OIDs */ + for (;;) + { + Oid val; + char *endptr; + + token = citus_pg_strtok(&tok_len); + if (token == NULL) + elog(ERROR, "unterminated List structure"); + if (token[0] == ')') + break; + val = (Oid) strtoul(token, &endptr, 10); + if (endptr != token + tok_len) + elog(ERROR, "unrecognized OID: \"%.*s\"", + tok_len, token); + l = lappend_oid(l, val); + } + } + else + { + /* List of other node types */ + for (;;) + { + /* We have already scanned next token... */ + if (token[0] == ')') + break; + l = lappend(l, CitusNodeRead(token, tok_len)); + token = citus_pg_strtok(&tok_len); + if (token == NULL) + elog(ERROR, "unterminated List structure"); + } + } + result = (Node *) l; + break; + } + case RIGHT_PAREN: + elog(ERROR, "unexpected right parenthesis"); + result = NULL; /* keep compiler happy */ + break; + case OTHER_TOKEN: + if (tok_len == 0) + { + /* must be "<>" --- represents a null pointer */ + result = NULL; + } + else + { + elog(ERROR, "unrecognized token: \"%.*s\"", tok_len, token); + result = NULL; /* keep compiler happy */ + } + break; + case T_Integer: + + /* + * we know that the token terminates on a char atol will stop at + */ + result = (Node *) makeInteger(atol(token)); + break; + case T_Float: + { + char *fval = (char *) palloc(tok_len + 1); + + memcpy(fval, token, tok_len); + fval[tok_len] = '\0'; + result = (Node *) makeFloat(fval); + } + break; + case T_String: + /* need to remove leading and trailing quotes, and backslashes */ + result = (Node *) makeString(debackslash(token + 1, tok_len - 2)); + break; + case T_BitString: + { + char *val = palloc(tok_len); + + /* skip leading 'b' */ + memcpy(val, token + 1, tok_len - 1); + val[tok_len - 1] = '\0'; + result = (Node *) makeBitString(val); + break; + } + default: + elog(ERROR, "unrecognized node type: %d", (int) type); + result = NULL; /* keep compiler happy */ + break; + } + + return (void *) result; +} diff --git a/src/backend/distributed/utils/citus_readfuncs_94.c b/src/backend/distributed/utils/citus_readfuncs_94.c new file mode 100644 index 000000000..ace76bb3a --- /dev/null +++ b/src/backend/distributed/utils/citus_readfuncs_94.c @@ -0,0 +1,1642 @@ +/*------------------------------------------------------------------------- + * + * citus_readfuncs.c + * CitusDB adapted reader functions for Citus & Postgres tree nodes + * + * Portions Copyright (c) 1996-2014, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * Portions Copyright (c) 2012-2015, Citus Data, Inc. + * + *------------------------------------------------------------------------- + */ + +#include "postgres.h" + +#if (PG_VERSION_NUM >= 90400 && PG_VERSION_NUM < 90500) + +#include + +#include "distributed/citus_nodefuncs.h" +#include "distributed/master_metadata_utility.h" +#include "distributed/multi_logical_planner.h" +#include "distributed/multi_physical_planner.h" +#include "nodes/parsenodes.h" +#include "nodes/readfuncs.h" + + +/* + * Macros to simplify reading of different kinds of fields. Use these + * wherever possible to reduce the chance for silly typos. Note that these + * hard-wire conventions about the names of the local variables in a Read + * routine. + */ + +/* Macros for declaring appropriate local variables */ + +/* A few guys need only local_node */ +#define READ_LOCALS_NO_FIELDS(nodeTypeName) \ + nodeTypeName *local_node = CitusMakeNode(nodeTypeName) + +/* And a few guys need only the citus_pg_strtok support fields */ +#define READ_TEMP_LOCALS() \ + char *token; \ + int length + +/* ... but most need both */ +#define READ_LOCALS(nodeTypeName) \ + READ_LOCALS_NO_FIELDS(nodeTypeName); \ + READ_TEMP_LOCALS() + +/* Read an integer field (anything written as ":fldname %d") */ +#define READ_INT_FIELD(fldname) \ + token = citus_pg_strtok(&length); /* skip :fldname */ \ + token = citus_pg_strtok(&length); /* get field value */ \ + local_node->fldname = atoi(token) + +/* Read an unsigned integer field (anything written as ":fldname %u") */ +#define READ_UINT_FIELD(fldname) \ + token = citus_pg_strtok(&length); /* skip :fldname */ \ + token = citus_pg_strtok(&length); /* get field value */ \ + local_node->fldname = atoui(token) + +/* XXX: CITUS Read an uint64 field (anything written as ":fldname %u") */ +#define READ_UINT64_FIELD(fldname) \ + token = citus_pg_strtok(&length); /* skip :fldname */ \ + token = citus_pg_strtok(&length); /* get field value */ \ + local_node->fldname = atoull(token) + +/* Read an OID field (don't hard-wire assumption that OID is same as uint) */ +#define READ_OID_FIELD(fldname) \ + token = citus_pg_strtok(&length); /* skip :fldname */ \ + token = citus_pg_strtok(&length); /* get field value */ \ + local_node->fldname = atooid(token) + +/* Read a char field (ie, one ascii character) */ +#define READ_CHAR_FIELD(fldname) \ + token = citus_pg_strtok(&length); /* skip :fldname */ \ + token = citus_pg_strtok(&length); /* get field value */ \ + local_node->fldname = token[0] + +/* Read an enumerated-type field that was written as an integer code */ +#define READ_ENUM_FIELD(fldname, enumtype) \ + token = citus_pg_strtok(&length); /* skip :fldname */ \ + token = citus_pg_strtok(&length); /* get field value */ \ + local_node->fldname = (enumtype) atoi(token) + +/* Read a float field */ +#define READ_FLOAT_FIELD(fldname) \ + token = citus_pg_strtok(&length); /* skip :fldname */ \ + token = citus_pg_strtok(&length); /* get field value */ \ + local_node->fldname = atof(token) + +/* Read a boolean field */ +#define READ_BOOL_FIELD(fldname) \ + token = citus_pg_strtok(&length); /* skip :fldname */ \ + token = citus_pg_strtok(&length); /* get field value */ \ + local_node->fldname = strtobool(token) + +/* Read a character-string field */ +#define READ_STRING_FIELD(fldname) \ + token = citus_pg_strtok(&length); /* skip :fldname */ \ + token = citus_pg_strtok(&length); /* get field value */ \ + local_node->fldname = nullable_string(token, length) + +/* Read a parse location field (and throw away the value, per notes above) */ +#define READ_LOCATION_FIELD(fldname) \ + token = citus_pg_strtok(&length); /* skip :fldname */ \ + token = citus_pg_strtok(&length); /* get field value */ \ + (void) token; /* in case not used elsewhere */ \ + local_node->fldname = -1 /* set field to "unknown" */ + +/* Read a Node field XXX: Citus: replaced call to nodeRead with CitusNodeRead */ +#define READ_NODE_FIELD(fldname) \ + token = citus_pg_strtok(&length); /* skip :fldname */ \ + (void) token; /* in case not used elsewhere */ \ + local_node->fldname = CitusNodeRead(NULL, 0) + +/* Read a bitmapset field */ +#define READ_BITMAPSET_FIELD(fldname) \ + token = citus_pg_strtok(&length); /* skip :fldname */ \ + (void) token; /* in case not used elsewhere */ \ + local_node->fldname = _readBitmapset() + + +/* Routine exit */ +#define READ_DONE() \ + return local_node + + +/* + * NOTE: use atoi() to read values written with %d, or atoui() to read + * values written with %u in outfuncs.c. An exception is OID values, + * for which use atooid(). (As of 7.1, outfuncs.c writes OIDs as %u, + * but this will probably change in the future.) + */ +#define atoui(x) ((unsigned int) strtoul((x), NULL, 10)) + +#define atooid(x) ((Oid) strtoul((x), NULL, 10)) + +/* XXX: Citus */ +#define atoull(x) ((uint64) strtoull((x), NULL, 10)) + +#define strtobool(x) ((*(x) == 't') ? true : false) + +#define nullable_string(token,length) \ + ((length) == 0 ? NULL : debackslash(token, length)) + + +static Datum readDatum(bool typbyval); + +/* + * _readBitmapset + */ +static Bitmapset * +_readBitmapset(void) +{ + Bitmapset *result = NULL; + + READ_TEMP_LOCALS(); + + token = citus_pg_strtok(&length); + if (token == NULL) + elog(ERROR, "incomplete Bitmapset structure"); + if (length != 1 || token[0] != '(') + elog(ERROR, "unrecognized token: \"%.*s\"", length, token); + + token = citus_pg_strtok(&length); + if (token == NULL) + elog(ERROR, "incomplete Bitmapset structure"); + if (length != 1 || token[0] != 'b') + elog(ERROR, "unrecognized token: \"%.*s\"", length, token); + + for (;;) + { + int val; + char *endptr; + + token = citus_pg_strtok(&length); + if (token == NULL) + elog(ERROR, "unterminated Bitmapset structure"); + if (length == 1 && token[0] == ')') + break; + val = (int) strtol(token, &endptr, 10); + if (endptr != token + length) + elog(ERROR, "unrecognized integer: \"%.*s\"", length, token); + result = bms_add_member(result, val); + } + + return result; +} + + +/* + * _readQuery + */ +static Query * +_readQuery(void) +{ + READ_LOCALS(Query); + + READ_ENUM_FIELD(commandType, CmdType); + READ_ENUM_FIELD(querySource, QuerySource); + local_node->queryId = 0; /* not saved in output format */ + READ_BOOL_FIELD(canSetTag); + READ_NODE_FIELD(utilityStmt); + READ_INT_FIELD(resultRelation); + READ_BOOL_FIELD(hasAggs); + READ_BOOL_FIELD(hasWindowFuncs); + READ_BOOL_FIELD(hasSubLinks); + READ_BOOL_FIELD(hasDistinctOn); + READ_BOOL_FIELD(hasRecursive); + READ_BOOL_FIELD(hasModifyingCTE); + READ_BOOL_FIELD(hasForUpdate); + READ_NODE_FIELD(cteList); + READ_NODE_FIELD(rtable); + READ_NODE_FIELD(jointree); + READ_NODE_FIELD(targetList); + READ_NODE_FIELD(withCheckOptions); + READ_NODE_FIELD(returningList); + READ_NODE_FIELD(groupClause); + READ_NODE_FIELD(havingQual); + READ_NODE_FIELD(windowClause); + READ_NODE_FIELD(distinctClause); + READ_NODE_FIELD(sortClause); + READ_NODE_FIELD(limitOffset); + READ_NODE_FIELD(limitCount); + READ_NODE_FIELD(rowMarks); + READ_NODE_FIELD(setOperations); + READ_NODE_FIELD(constraintDeps); + + READ_DONE(); +} + +/* + * _readNotifyStmt + */ +static NotifyStmt * +_readNotifyStmt(void) +{ + READ_LOCALS(NotifyStmt); + + READ_STRING_FIELD(conditionname); + READ_STRING_FIELD(payload); + + READ_DONE(); +} + +/* + * _readDeclareCursorStmt + */ +static DeclareCursorStmt * +_readDeclareCursorStmt(void) +{ + READ_LOCALS(DeclareCursorStmt); + + READ_STRING_FIELD(portalname); + READ_INT_FIELD(options); + READ_NODE_FIELD(query); + + READ_DONE(); +} + +/* + * _readWithCheckOption + */ +static WithCheckOption * +_readWithCheckOption(void) +{ + READ_LOCALS(WithCheckOption); + + READ_STRING_FIELD(viewname); + READ_NODE_FIELD(qual); + READ_BOOL_FIELD(cascaded); + + READ_DONE(); +} + +/* + * _readSortGroupClause + */ +static SortGroupClause * +_readSortGroupClause(void) +{ + READ_LOCALS(SortGroupClause); + + READ_UINT_FIELD(tleSortGroupRef); + READ_OID_FIELD(eqop); + READ_OID_FIELD(sortop); + READ_BOOL_FIELD(nulls_first); + READ_BOOL_FIELD(hashable); + + READ_DONE(); +} + +/* + * _readWindowClause + */ +static WindowClause * +_readWindowClause(void) +{ + READ_LOCALS(WindowClause); + + READ_STRING_FIELD(name); + READ_STRING_FIELD(refname); + READ_NODE_FIELD(partitionClause); + READ_NODE_FIELD(orderClause); + READ_INT_FIELD(frameOptions); + READ_NODE_FIELD(startOffset); + READ_NODE_FIELD(endOffset); + READ_UINT_FIELD(winref); + READ_BOOL_FIELD(copiedOrder); + + READ_DONE(); +} + +/* + * _readRowMarkClause + */ +static RowMarkClause * +_readRowMarkClause(void) +{ + READ_LOCALS(RowMarkClause); + + READ_UINT_FIELD(rti); + READ_ENUM_FIELD(strength, LockClauseStrength); + READ_BOOL_FIELD(noWait); + READ_BOOL_FIELD(pushedDown); + + READ_DONE(); +} + +/* + * _readCommonTableExpr + */ +static CommonTableExpr * +_readCommonTableExpr(void) +{ + READ_LOCALS(CommonTableExpr); + + READ_STRING_FIELD(ctename); + READ_NODE_FIELD(aliascolnames); + READ_NODE_FIELD(ctequery); + READ_LOCATION_FIELD(location); + READ_BOOL_FIELD(cterecursive); + READ_INT_FIELD(cterefcount); + READ_NODE_FIELD(ctecolnames); + READ_NODE_FIELD(ctecoltypes); + READ_NODE_FIELD(ctecoltypmods); + READ_NODE_FIELD(ctecolcollations); + + READ_DONE(); +} + +/* + * _readSetOperationStmt + */ +static SetOperationStmt * +_readSetOperationStmt(void) +{ + READ_LOCALS(SetOperationStmt); + + READ_ENUM_FIELD(op, SetOperation); + READ_BOOL_FIELD(all); + READ_NODE_FIELD(larg); + READ_NODE_FIELD(rarg); + READ_NODE_FIELD(colTypes); + READ_NODE_FIELD(colTypmods); + READ_NODE_FIELD(colCollations); + READ_NODE_FIELD(groupClauses); + + READ_DONE(); +} + + +/* + * Stuff from primnodes.h. + */ + +static Alias * +_readAlias(void) +{ + READ_LOCALS(Alias); + + READ_STRING_FIELD(aliasname); + READ_NODE_FIELD(colnames); + + READ_DONE(); +} + +static RangeVar * +_readRangeVar(void) +{ + READ_LOCALS(RangeVar); + + local_node->catalogname = NULL; /* not currently saved in output + * format */ + + READ_STRING_FIELD(schemaname); + READ_STRING_FIELD(relname); + READ_ENUM_FIELD(inhOpt, InhOption); + READ_CHAR_FIELD(relpersistence); + READ_NODE_FIELD(alias); + READ_LOCATION_FIELD(location); + + READ_DONE(); +} + +static IntoClause * +_readIntoClause(void) +{ + READ_LOCALS(IntoClause); + + READ_NODE_FIELD(rel); + READ_NODE_FIELD(colNames); + READ_NODE_FIELD(options); + READ_ENUM_FIELD(onCommit, OnCommitAction); + READ_STRING_FIELD(tableSpaceName); + READ_NODE_FIELD(viewQuery); + READ_BOOL_FIELD(skipData); + + READ_DONE(); +} + +/* + * _readVar + */ +static Var * +_readVar(void) +{ + READ_LOCALS(Var); + + READ_UINT_FIELD(varno); + READ_INT_FIELD(varattno); + READ_OID_FIELD(vartype); + READ_INT_FIELD(vartypmod); + READ_OID_FIELD(varcollid); + READ_UINT_FIELD(varlevelsup); + READ_UINT_FIELD(varnoold); + READ_INT_FIELD(varoattno); + READ_LOCATION_FIELD(location); + + READ_DONE(); +} + +/* + * _readConst + */ +static Const * +_readConst(void) +{ + READ_LOCALS(Const); + + READ_OID_FIELD(consttype); + READ_INT_FIELD(consttypmod); + READ_OID_FIELD(constcollid); + READ_INT_FIELD(constlen); + READ_BOOL_FIELD(constbyval); + READ_BOOL_FIELD(constisnull); + READ_LOCATION_FIELD(location); + + token = citus_pg_strtok(&length); /* skip :constvalue */ + if (local_node->constisnull) + token = citus_pg_strtok(&length); /* skip "<>" */ + else + local_node->constvalue = readDatum(local_node->constbyval); + + READ_DONE(); +} + +/* + * _readParam + */ +static Param * +_readParam(void) +{ + READ_LOCALS(Param); + + READ_ENUM_FIELD(paramkind, ParamKind); + READ_INT_FIELD(paramid); + READ_OID_FIELD(paramtype); + READ_INT_FIELD(paramtypmod); + READ_OID_FIELD(paramcollid); + READ_LOCATION_FIELD(location); + + READ_DONE(); +} + +/* + * _readAggref + */ +static Aggref * +_readAggref(void) +{ + READ_LOCALS(Aggref); + + READ_OID_FIELD(aggfnoid); + READ_OID_FIELD(aggtype); + READ_OID_FIELD(aggcollid); + READ_OID_FIELD(inputcollid); + READ_NODE_FIELD(aggdirectargs); + READ_NODE_FIELD(args); + READ_NODE_FIELD(aggorder); + READ_NODE_FIELD(aggdistinct); + READ_NODE_FIELD(aggfilter); + READ_BOOL_FIELD(aggstar); + READ_BOOL_FIELD(aggvariadic); + READ_CHAR_FIELD(aggkind); + READ_UINT_FIELD(agglevelsup); + READ_LOCATION_FIELD(location); + + READ_DONE(); +} + +/* + * _readWindowFunc + */ +static WindowFunc * +_readWindowFunc(void) +{ + READ_LOCALS(WindowFunc); + + READ_OID_FIELD(winfnoid); + READ_OID_FIELD(wintype); + READ_OID_FIELD(wincollid); + READ_OID_FIELD(inputcollid); + READ_NODE_FIELD(args); + READ_NODE_FIELD(aggfilter); + READ_UINT_FIELD(winref); + READ_BOOL_FIELD(winstar); + READ_BOOL_FIELD(winagg); + READ_LOCATION_FIELD(location); + + READ_DONE(); +} + +/* + * _readArrayRef + */ +static ArrayRef * +_readArrayRef(void) +{ + READ_LOCALS(ArrayRef); + + READ_OID_FIELD(refarraytype); + READ_OID_FIELD(refelemtype); + READ_INT_FIELD(reftypmod); + READ_OID_FIELD(refcollid); + READ_NODE_FIELD(refupperindexpr); + READ_NODE_FIELD(reflowerindexpr); + READ_NODE_FIELD(refexpr); + READ_NODE_FIELD(refassgnexpr); + + READ_DONE(); +} + +/* + * _readFuncExpr + */ +static FuncExpr * +_readFuncExpr(void) +{ + READ_LOCALS(FuncExpr); + + READ_OID_FIELD(funcid); + READ_OID_FIELD(funcresulttype); + READ_BOOL_FIELD(funcretset); + READ_BOOL_FIELD(funcvariadic); + READ_ENUM_FIELD(funcformat, CoercionForm); + READ_OID_FIELD(funccollid); + READ_OID_FIELD(inputcollid); + READ_NODE_FIELD(args); + READ_LOCATION_FIELD(location); + + READ_DONE(); +} + +/* + * _readNamedArgExpr + */ +static NamedArgExpr * +_readNamedArgExpr(void) +{ + READ_LOCALS(NamedArgExpr); + + READ_NODE_FIELD(arg); + READ_STRING_FIELD(name); + READ_INT_FIELD(argnumber); + READ_LOCATION_FIELD(location); + + READ_DONE(); +} + +/* + * _readOpExpr + */ +static OpExpr * +_readOpExpr(void) +{ + READ_LOCALS(OpExpr); + + READ_OID_FIELD(opno); + READ_OID_FIELD(opfuncid); + + /* + * The opfuncid is stored in the textual format primarily for debugging + * and documentation reasons. We want to always read it as zero to force + * it to be re-looked-up in the pg_operator entry. This ensures that + * stored rules don't have hidden dependencies on operators' functions. + * (We don't currently support an ALTER OPERATOR command, but might + * someday.) + */ + local_node->opfuncid = InvalidOid; + + READ_OID_FIELD(opresulttype); + READ_BOOL_FIELD(opretset); + READ_OID_FIELD(opcollid); + READ_OID_FIELD(inputcollid); + READ_NODE_FIELD(args); + READ_LOCATION_FIELD(location); + + READ_DONE(); +} + +/* + * _readDistinctExpr + */ +static DistinctExpr * +_readDistinctExpr(void) +{ + READ_LOCALS(DistinctExpr); + + READ_OID_FIELD(opno); + READ_OID_FIELD(opfuncid); + + /* + * The opfuncid is stored in the textual format primarily for debugging + * and documentation reasons. We want to always read it as zero to force + * it to be re-looked-up in the pg_operator entry. This ensures that + * stored rules don't have hidden dependencies on operators' functions. + * (We don't currently support an ALTER OPERATOR command, but might + * someday.) + */ + local_node->opfuncid = InvalidOid; + + READ_OID_FIELD(opresulttype); + READ_BOOL_FIELD(opretset); + READ_OID_FIELD(opcollid); + READ_OID_FIELD(inputcollid); + READ_NODE_FIELD(args); + READ_LOCATION_FIELD(location); + + READ_DONE(); +} + +/* + * _readNullIfExpr + */ +static NullIfExpr * +_readNullIfExpr(void) +{ + READ_LOCALS(NullIfExpr); + + READ_OID_FIELD(opno); + READ_OID_FIELD(opfuncid); + + /* + * The opfuncid is stored in the textual format primarily for debugging + * and documentation reasons. We want to always read it as zero to force + * it to be re-looked-up in the pg_operator entry. This ensures that + * stored rules don't have hidden dependencies on operators' functions. + * (We don't currently support an ALTER OPERATOR command, but might + * someday.) + */ + local_node->opfuncid = InvalidOid; + + READ_OID_FIELD(opresulttype); + READ_BOOL_FIELD(opretset); + READ_OID_FIELD(opcollid); + READ_OID_FIELD(inputcollid); + READ_NODE_FIELD(args); + READ_LOCATION_FIELD(location); + + READ_DONE(); +} + +/* + * _readScalarArrayOpExpr + */ +static ScalarArrayOpExpr * +_readScalarArrayOpExpr(void) +{ + READ_LOCALS(ScalarArrayOpExpr); + + READ_OID_FIELD(opno); + READ_OID_FIELD(opfuncid); + + /* + * The opfuncid is stored in the textual format primarily for debugging + * and documentation reasons. We want to always read it as zero to force + * it to be re-looked-up in the pg_operator entry. This ensures that + * stored rules don't have hidden dependencies on operators' functions. + * (We don't currently support an ALTER OPERATOR command, but might + * someday.) + */ + local_node->opfuncid = InvalidOid; + + READ_BOOL_FIELD(useOr); + READ_OID_FIELD(inputcollid); + READ_NODE_FIELD(args); + READ_LOCATION_FIELD(location); + + READ_DONE(); +} + +/* + * _readBoolExpr + */ +static BoolExpr * +_readBoolExpr(void) +{ + READ_LOCALS(BoolExpr); + + /* do-it-yourself enum representation */ + token = citus_pg_strtok(&length); /* skip :boolop */ + token = citus_pg_strtok(&length); /* get field value */ + if (strncmp(token, "and", 3) == 0) + local_node->boolop = AND_EXPR; + else if (strncmp(token, "or", 2) == 0) + local_node->boolop = OR_EXPR; + else if (strncmp(token, "not", 3) == 0) + local_node->boolop = NOT_EXPR; + else + elog(ERROR, "unrecognized boolop \"%.*s\"", length, token); + + READ_NODE_FIELD(args); + READ_LOCATION_FIELD(location); + + READ_DONE(); +} + +/* + * _readSubLink + */ +static SubLink * +_readSubLink(void) +{ + READ_LOCALS(SubLink); + + READ_ENUM_FIELD(subLinkType, SubLinkType); + READ_NODE_FIELD(testexpr); + READ_NODE_FIELD(operName); + READ_NODE_FIELD(subselect); + READ_LOCATION_FIELD(location); + + READ_DONE(); +} + +/* + * _readSubPlan is not needed since it doesn't appear in stored rules. + */ + +/* + * _readFieldSelect + */ +static FieldSelect * +_readFieldSelect(void) +{ + READ_LOCALS(FieldSelect); + + READ_NODE_FIELD(arg); + READ_INT_FIELD(fieldnum); + READ_OID_FIELD(resulttype); + READ_INT_FIELD(resulttypmod); + READ_OID_FIELD(resultcollid); + + READ_DONE(); +} + +/* + * _readFieldStore + */ +static FieldStore * +_readFieldStore(void) +{ + READ_LOCALS(FieldStore); + + READ_NODE_FIELD(arg); + READ_NODE_FIELD(newvals); + READ_NODE_FIELD(fieldnums); + READ_OID_FIELD(resulttype); + + READ_DONE(); +} + +/* + * _readRelabelType + */ +static RelabelType * +_readRelabelType(void) +{ + READ_LOCALS(RelabelType); + + READ_NODE_FIELD(arg); + READ_OID_FIELD(resulttype); + READ_INT_FIELD(resulttypmod); + READ_OID_FIELD(resultcollid); + READ_ENUM_FIELD(relabelformat, CoercionForm); + READ_LOCATION_FIELD(location); + + READ_DONE(); +} + +/* + * _readCoerceViaIO + */ +static CoerceViaIO * +_readCoerceViaIO(void) +{ + READ_LOCALS(CoerceViaIO); + + READ_NODE_FIELD(arg); + READ_OID_FIELD(resulttype); + READ_OID_FIELD(resultcollid); + READ_ENUM_FIELD(coerceformat, CoercionForm); + READ_LOCATION_FIELD(location); + + READ_DONE(); +} + +/* + * _readArrayCoerceExpr + */ +static ArrayCoerceExpr * +_readArrayCoerceExpr(void) +{ + READ_LOCALS(ArrayCoerceExpr); + + READ_NODE_FIELD(arg); + READ_OID_FIELD(elemfuncid); + READ_OID_FIELD(resulttype); + READ_INT_FIELD(resulttypmod); + READ_OID_FIELD(resultcollid); + READ_BOOL_FIELD(isExplicit); + READ_ENUM_FIELD(coerceformat, CoercionForm); + READ_LOCATION_FIELD(location); + + READ_DONE(); +} + +/* + * _readConvertRowtypeExpr + */ +static ConvertRowtypeExpr * +_readConvertRowtypeExpr(void) +{ + READ_LOCALS(ConvertRowtypeExpr); + + READ_NODE_FIELD(arg); + READ_OID_FIELD(resulttype); + READ_ENUM_FIELD(convertformat, CoercionForm); + READ_LOCATION_FIELD(location); + + READ_DONE(); +} + +/* + * _readCollateExpr + */ +static CollateExpr * +_readCollateExpr(void) +{ + READ_LOCALS(CollateExpr); + + READ_NODE_FIELD(arg); + READ_OID_FIELD(collOid); + READ_LOCATION_FIELD(location); + + READ_DONE(); +} + +/* + * _readCaseExpr + */ +static CaseExpr * +_readCaseExpr(void) +{ + READ_LOCALS(CaseExpr); + + READ_OID_FIELD(casetype); + READ_OID_FIELD(casecollid); + READ_NODE_FIELD(arg); + READ_NODE_FIELD(args); + READ_NODE_FIELD(defresult); + READ_LOCATION_FIELD(location); + + READ_DONE(); +} + +/* + * _readCaseWhen + */ +static CaseWhen * +_readCaseWhen(void) +{ + READ_LOCALS(CaseWhen); + + READ_NODE_FIELD(expr); + READ_NODE_FIELD(result); + READ_LOCATION_FIELD(location); + + READ_DONE(); +} + +/* + * _readCaseTestExpr + */ +static CaseTestExpr * +_readCaseTestExpr(void) +{ + READ_LOCALS(CaseTestExpr); + + READ_OID_FIELD(typeId); + READ_INT_FIELD(typeMod); + READ_OID_FIELD(collation); + + READ_DONE(); +} + +/* + * _readArrayExpr + */ +static ArrayExpr * +_readArrayExpr(void) +{ + READ_LOCALS(ArrayExpr); + + READ_OID_FIELD(array_typeid); + READ_OID_FIELD(array_collid); + READ_OID_FIELD(element_typeid); + READ_NODE_FIELD(elements); + READ_BOOL_FIELD(multidims); + READ_LOCATION_FIELD(location); + + READ_DONE(); +} + +/* + * _readRowExpr + */ +static RowExpr * +_readRowExpr(void) +{ + READ_LOCALS(RowExpr); + + READ_NODE_FIELD(args); + READ_OID_FIELD(row_typeid); + READ_ENUM_FIELD(row_format, CoercionForm); + READ_NODE_FIELD(colnames); + READ_LOCATION_FIELD(location); + + READ_DONE(); +} + +/* + * _readRowCompareExpr + */ +static RowCompareExpr * +_readRowCompareExpr(void) +{ + READ_LOCALS(RowCompareExpr); + + READ_ENUM_FIELD(rctype, RowCompareType); + READ_NODE_FIELD(opnos); + READ_NODE_FIELD(opfamilies); + READ_NODE_FIELD(inputcollids); + READ_NODE_FIELD(largs); + READ_NODE_FIELD(rargs); + + READ_DONE(); +} + +/* + * _readCoalesceExpr + */ +static CoalesceExpr * +_readCoalesceExpr(void) +{ + READ_LOCALS(CoalesceExpr); + + READ_OID_FIELD(coalescetype); + READ_OID_FIELD(coalescecollid); + READ_NODE_FIELD(args); + READ_LOCATION_FIELD(location); + + READ_DONE(); +} + +/* + * _readMinMaxExpr + */ +static MinMaxExpr * +_readMinMaxExpr(void) +{ + READ_LOCALS(MinMaxExpr); + + READ_OID_FIELD(minmaxtype); + READ_OID_FIELD(minmaxcollid); + READ_OID_FIELD(inputcollid); + READ_ENUM_FIELD(op, MinMaxOp); + READ_NODE_FIELD(args); + READ_LOCATION_FIELD(location); + + READ_DONE(); +} + +/* + * _readXmlExpr + */ +static XmlExpr * +_readXmlExpr(void) +{ + READ_LOCALS(XmlExpr); + + READ_ENUM_FIELD(op, XmlExprOp); + READ_STRING_FIELD(name); + READ_NODE_FIELD(named_args); + READ_NODE_FIELD(arg_names); + READ_NODE_FIELD(args); + READ_ENUM_FIELD(xmloption, XmlOptionType); + READ_OID_FIELD(type); + READ_INT_FIELD(typmod); + READ_LOCATION_FIELD(location); + + READ_DONE(); +} + +/* + * _readNullTest + */ +static NullTest * +_readNullTest(void) +{ + READ_LOCALS(NullTest); + + READ_NODE_FIELD(arg); + READ_ENUM_FIELD(nulltesttype, NullTestType); + READ_BOOL_FIELD(argisrow); + + READ_DONE(); +} + +/* + * _readBooleanTest + */ +static BooleanTest * +_readBooleanTest(void) +{ + READ_LOCALS(BooleanTest); + + READ_NODE_FIELD(arg); + READ_ENUM_FIELD(booltesttype, BoolTestType); + + READ_DONE(); +} + +/* + * _readCoerceToDomain + */ +static CoerceToDomain * +_readCoerceToDomain(void) +{ + READ_LOCALS(CoerceToDomain); + + READ_NODE_FIELD(arg); + READ_OID_FIELD(resulttype); + READ_INT_FIELD(resulttypmod); + READ_OID_FIELD(resultcollid); + READ_ENUM_FIELD(coercionformat, CoercionForm); + READ_LOCATION_FIELD(location); + + READ_DONE(); +} + +/* + * _readCoerceToDomainValue + */ +static CoerceToDomainValue * +_readCoerceToDomainValue(void) +{ + READ_LOCALS(CoerceToDomainValue); + + READ_OID_FIELD(typeId); + READ_INT_FIELD(typeMod); + READ_OID_FIELD(collation); + READ_LOCATION_FIELD(location); + + READ_DONE(); +} + +/* + * _readSetToDefault + */ +static SetToDefault * +_readSetToDefault(void) +{ + READ_LOCALS(SetToDefault); + + READ_OID_FIELD(typeId); + READ_INT_FIELD(typeMod); + READ_OID_FIELD(collation); + READ_LOCATION_FIELD(location); + + READ_DONE(); +} + +/* + * _readCurrentOfExpr + */ +static CurrentOfExpr * +_readCurrentOfExpr(void) +{ + READ_LOCALS(CurrentOfExpr); + + READ_UINT_FIELD(cvarno); + READ_STRING_FIELD(cursor_name); + READ_INT_FIELD(cursor_param); + + READ_DONE(); +} + +/* + * _readTargetEntry + */ +static TargetEntry * +_readTargetEntry(void) +{ + READ_LOCALS(TargetEntry); + + READ_NODE_FIELD(expr); + READ_INT_FIELD(resno); + READ_STRING_FIELD(resname); + READ_UINT_FIELD(ressortgroupref); + READ_OID_FIELD(resorigtbl); + READ_INT_FIELD(resorigcol); + READ_BOOL_FIELD(resjunk); + + READ_DONE(); +} + +/* + * _readRangeTblRef + */ +static RangeTblRef * +_readRangeTblRef(void) +{ + READ_LOCALS(RangeTblRef); + + READ_INT_FIELD(rtindex); + + READ_DONE(); +} + +/* + * _readJoinExpr + */ +static JoinExpr * +_readJoinExpr(void) +{ + READ_LOCALS(JoinExpr); + + READ_ENUM_FIELD(jointype, JoinType); + READ_BOOL_FIELD(isNatural); + READ_NODE_FIELD(larg); + READ_NODE_FIELD(rarg); + READ_NODE_FIELD(usingClause); + READ_NODE_FIELD(quals); + READ_NODE_FIELD(alias); + READ_INT_FIELD(rtindex); + + READ_DONE(); +} + +/* + * _readFromExpr + */ +static FromExpr * +_readFromExpr(void) +{ + READ_LOCALS(FromExpr); + + READ_NODE_FIELD(fromlist); + READ_NODE_FIELD(quals); + + READ_DONE(); +} + + +/* + * Stuff from parsenodes.h. + */ + +/* + * _readRangeTblEntry + */ +static RangeTblEntry * +_readRangeTblEntry(void) +{ + READ_LOCALS(RangeTblEntry); + + /* put alias + eref first to make dump more legible */ + READ_NODE_FIELD(alias); + READ_NODE_FIELD(eref); + READ_ENUM_FIELD(rtekind, RTEKind); + + switch (local_node->rtekind) + { + case RTE_RELATION: + READ_OID_FIELD(relid); + READ_CHAR_FIELD(relkind); + break; + case RTE_SUBQUERY: + READ_NODE_FIELD(subquery); + READ_BOOL_FIELD(security_barrier); + break; + case RTE_JOIN: + READ_ENUM_FIELD(jointype, JoinType); + READ_NODE_FIELD(joinaliasvars); + break; + case RTE_FUNCTION: + READ_NODE_FIELD(functions); + READ_BOOL_FIELD(funcordinality); + break; + case RTE_VALUES: + READ_NODE_FIELD(values_lists); + READ_NODE_FIELD(values_collations); + break; + case RTE_CTE: + READ_STRING_FIELD(ctename); + READ_UINT_FIELD(ctelevelsup); + READ_BOOL_FIELD(self_reference); + READ_NODE_FIELD(ctecoltypes); + READ_NODE_FIELD(ctecoltypmods); + READ_NODE_FIELD(ctecolcollations); + break; + default: + elog(ERROR, "unrecognized RTE kind: %d", + (int) local_node->rtekind); + break; + } + + READ_BOOL_FIELD(lateral); + READ_BOOL_FIELD(inh); + READ_BOOL_FIELD(inFromCl); + READ_UINT_FIELD(requiredPerms); + READ_OID_FIELD(checkAsUser); + READ_BITMAPSET_FIELD(selectedCols); + READ_BITMAPSET_FIELD(modifiedCols); + READ_NODE_FIELD(securityQuals); + + READ_DONE(); +} + +/* + * _readRangeTblFunction + */ +static RangeTblFunction * +_readRangeTblFunction(void) +{ + READ_LOCALS(RangeTblFunction); + + READ_NODE_FIELD(funcexpr); + READ_INT_FIELD(funccolcount); + READ_NODE_FIELD(funccolnames); + READ_NODE_FIELD(funccoltypes); + READ_NODE_FIELD(funccoltypmods); + READ_NODE_FIELD(funccolcollations); + READ_BITMAPSET_FIELD(funcparams); + + READ_DONE(); +} + + +/* XXX: BEGIN Citus Nodes */ + +static void +_readJobInfo(Job *local_node) +{ + READ_TEMP_LOCALS(); + + READ_UINT64_FIELD(jobId); + READ_NODE_FIELD(jobQuery); + READ_NODE_FIELD(taskList); + READ_NODE_FIELD(dependedJobList); + READ_BOOL_FIELD(subqueryPushdown); +} + + +static Job * +_readJob(void) +{ + READ_LOCALS_NO_FIELDS(Job); + + _readJobInfo(local_node); + + READ_DONE(); +} + + +static MultiPlan * +_readMultiPlan(void) +{ + READ_LOCALS(MultiPlan); + + READ_NODE_FIELD(workerJob); + READ_NODE_FIELD(masterQuery); + READ_STRING_FIELD(masterTableName); + + READ_DONE(); +} + + +static ShardInterval * +_readShardInterval(void) +{ + READ_LOCALS(ShardInterval); + + + READ_OID_FIELD(relationId); + READ_CHAR_FIELD(storageType); + READ_OID_FIELD(valueTypeId); + READ_INT_FIELD(valueTypeLen); + READ_BOOL_FIELD(valueByVal); + READ_BOOL_FIELD(minValueExists); + READ_BOOL_FIELD(maxValueExists); + + token = citus_pg_strtok(&length); /* skip :minValue */ + if (!local_node->minValueExists) + token = citus_pg_strtok(&length); /* skip "<>" */ + else + local_node->minValue = readDatum(local_node->valueByVal); + + token = citus_pg_strtok(&length); /* skip :maxValue */ + if (!local_node->minValueExists) + token = citus_pg_strtok(&length); /* skip "<>" */ + else + local_node->maxValue = readDatum(local_node->valueByVal); + + READ_UINT64_FIELD(shardId); + + READ_DONE(); +} + + +static MapMergeJob * +_readMapMergeJob(void) +{ + int arrayLength; + int i; + + READ_LOCALS(MapMergeJob); + + _readJobInfo(&local_node->job); + + READ_NODE_FIELD(reduceQuery); + READ_ENUM_FIELD(partitionType, PartitionType); + READ_NODE_FIELD(partitionColumn); + READ_UINT_FIELD(partitionCount); + READ_INT_FIELD(sortedShardIntervalArrayLength); + + arrayLength = local_node->sortedShardIntervalArrayLength; + + /* now build & read sortedShardIntervalArray */ + local_node->sortedShardIntervalArray = + (ShardInterval**) palloc(arrayLength * sizeof(ShardInterval *)); + + for (i = 0; i < arrayLength; ++i) + { + local_node->sortedShardIntervalArray[i] = _readShardInterval(); + } + + READ_NODE_FIELD(mapTaskList); + READ_NODE_FIELD(mergeTaskList); + + READ_DONE(); +} + + +static ShardPlacement * +_readShardPlacement(void) +{ + READ_LOCALS(ShardPlacement); + + READ_OID_FIELD(tupleOid); + READ_UINT64_FIELD(shardId); + READ_UINT64_FIELD(shardLength); + READ_ENUM_FIELD(shardState, RelayFileState); + READ_STRING_FIELD(nodeName); + READ_UINT_FIELD(nodePort); + + READ_DONE(); +} + + +static Task * +_readTask(void) +{ + READ_LOCALS(Task); + + READ_ENUM_FIELD(taskType, TaskType); + READ_UINT64_FIELD(jobId); + READ_UINT_FIELD(taskId); + READ_STRING_FIELD(queryString); + READ_UINT64_FIELD(anchorShardId); + READ_NODE_FIELD(taskPlacementList); + READ_NODE_FIELD(dependedTaskList); + READ_UINT_FIELD(partitionId); + READ_UINT_FIELD(upstreamTaskId); + READ_NODE_FIELD(shardInterval); + READ_BOOL_FIELD(assignmentConstrained); + READ_NODE_FIELD(taskExecution); + READ_BOOL_FIELD(upsertQuery); + + READ_DONE(); +} + + +/* XXX: END Citus Nodes */ + + +/* + * readDatum + * + * Given a string representation of a constant, recreate the appropriate + * Datum. The string representation embeds length info, but not byValue, + * so we must be told that. + */ +static Datum +readDatum(bool typbyval) +{ + Size length, + i; + int tokenLength; + char *token; + Datum res; + char *s; + + /* + * read the actual length of the value + */ + token = citus_pg_strtok(&tokenLength); + length = atoui(token); + + token = citus_pg_strtok(&tokenLength); /* read the '[' */ + if (token == NULL || token[0] != '[') + elog(ERROR, "expected \"[\" to start datum, but got \"%s\"; length = %zu", + token ? (const char *) token : "[NULL]", length); + + if (typbyval) + { + if (length > (Size) sizeof(Datum)) + elog(ERROR, "byval datum but length = %zu", length); + res = (Datum) 0; + s = (char *) (&res); + for (i = 0; i < (Size) sizeof(Datum); i++) + { + token = citus_pg_strtok(&tokenLength); + s[i] = (char) atoi(token); + } + } + else if (length <= 0) + res = (Datum) NULL; + else + { + s = (char *) palloc(length); + for (i = 0; i < length; i++) + { + token = citus_pg_strtok(&tokenLength); + s[i] = (char) atoi(token); + } + res = PointerGetDatum(s); + } + + token = citus_pg_strtok(&tokenLength); /* read the ']' */ + if (token == NULL || token[0] != ']') + elog(ERROR, "expected \"]\" to end datum, but got \"%s\"; length = %zu", + token ? (const char *) token : "[NULL]", length); + + return res; +} + + +/* + * parseNodeString + * + * Given a character string representing a node tree, parseNodeString creates + * the internal node structure. + * + * The string to be read must already have been loaded into citus_pg_strtok(). + */ +Node * +CitusParseNodeString(void) +{ + void *return_value; + + READ_TEMP_LOCALS(); + + token = citus_pg_strtok(&length); + +#define MATCH(tokname, namelen) \ + (length == namelen && memcmp(token, tokname, namelen) == 0) + + if (MATCH("QUERY", 5)) + return_value = _readQuery(); + else if (MATCH("WITHCHECKOPTION", 15)) + return_value = _readWithCheckOption(); + else if (MATCH("SORTGROUPCLAUSE", 15)) + return_value = _readSortGroupClause(); + else if (MATCH("WINDOWCLAUSE", 12)) + return_value = _readWindowClause(); + else if (MATCH("ROWMARKCLAUSE", 13)) + return_value = _readRowMarkClause(); + else if (MATCH("COMMONTABLEEXPR", 15)) + return_value = _readCommonTableExpr(); + else if (MATCH("SETOPERATIONSTMT", 16)) + return_value = _readSetOperationStmt(); + else if (MATCH("ALIAS", 5)) + return_value = _readAlias(); + else if (MATCH("RANGEVAR", 8)) + return_value = _readRangeVar(); + else if (MATCH("INTOCLAUSE", 10)) + return_value = _readIntoClause(); + else if (MATCH("VAR", 3)) + return_value = _readVar(); + else if (MATCH("CONST", 5)) + return_value = _readConst(); + else if (MATCH("PARAM", 5)) + return_value = _readParam(); + else if (MATCH("AGGREF", 6)) + return_value = _readAggref(); + else if (MATCH("WINDOWFUNC", 10)) + return_value = _readWindowFunc(); + else if (MATCH("ARRAYREF", 8)) + return_value = _readArrayRef(); + else if (MATCH("FUNCEXPR", 8)) + return_value = _readFuncExpr(); + else if (MATCH("NAMEDARGEXPR", 12)) + return_value = _readNamedArgExpr(); + else if (MATCH("OPEXPR", 6)) + return_value = _readOpExpr(); + else if (MATCH("DISTINCTEXPR", 12)) + return_value = _readDistinctExpr(); + else if (MATCH("NULLIFEXPR", 10)) + return_value = _readNullIfExpr(); + else if (MATCH("SCALARARRAYOPEXPR", 17)) + return_value = _readScalarArrayOpExpr(); + else if (MATCH("BOOLEXPR", 8)) + return_value = _readBoolExpr(); + else if (MATCH("SUBLINK", 7)) + return_value = _readSubLink(); + else if (MATCH("FIELDSELECT", 11)) + return_value = _readFieldSelect(); + else if (MATCH("FIELDSTORE", 10)) + return_value = _readFieldStore(); + else if (MATCH("RELABELTYPE", 11)) + return_value = _readRelabelType(); + else if (MATCH("COERCEVIAIO", 11)) + return_value = _readCoerceViaIO(); + else if (MATCH("ARRAYCOERCEEXPR", 15)) + return_value = _readArrayCoerceExpr(); + else if (MATCH("CONVERTROWTYPEEXPR", 18)) + return_value = _readConvertRowtypeExpr(); + else if (MATCH("COLLATE", 7)) + return_value = _readCollateExpr(); + else if (MATCH("CASE", 4)) + return_value = _readCaseExpr(); + else if (MATCH("WHEN", 4)) + return_value = _readCaseWhen(); + else if (MATCH("CASETESTEXPR", 12)) + return_value = _readCaseTestExpr(); + else if (MATCH("ARRAY", 5)) + return_value = _readArrayExpr(); + else if (MATCH("ROW", 3)) + return_value = _readRowExpr(); + else if (MATCH("ROWCOMPARE", 10)) + return_value = _readRowCompareExpr(); + else if (MATCH("COALESCE", 8)) + return_value = _readCoalesceExpr(); + else if (MATCH("MINMAX", 6)) + return_value = _readMinMaxExpr(); + else if (MATCH("XMLEXPR", 7)) + return_value = _readXmlExpr(); + else if (MATCH("NULLTEST", 8)) + return_value = _readNullTest(); + else if (MATCH("BOOLEANTEST", 11)) + return_value = _readBooleanTest(); + else if (MATCH("COERCETODOMAIN", 14)) + return_value = _readCoerceToDomain(); + else if (MATCH("COERCETODOMAINVALUE", 19)) + return_value = _readCoerceToDomainValue(); + else if (MATCH("SETTODEFAULT", 12)) + return_value = _readSetToDefault(); + else if (MATCH("CURRENTOFEXPR", 13)) + return_value = _readCurrentOfExpr(); + else if (MATCH("TARGETENTRY", 11)) + return_value = _readTargetEntry(); + else if (MATCH("RANGETBLREF", 11)) + return_value = _readRangeTblRef(); + else if (MATCH("JOINEXPR", 8)) + return_value = _readJoinExpr(); + else if (MATCH("FROMEXPR", 8)) + return_value = _readFromExpr(); + else if (MATCH("RTE", 3)) + return_value = _readRangeTblEntry(); + else if (MATCH("RANGETBLFUNCTION", 16)) + return_value = _readRangeTblFunction(); + else if (MATCH("NOTIFY", 6)) + return_value = _readNotifyStmt(); + else if (MATCH("DECLARECURSOR", 13)) + return_value = _readDeclareCursorStmt(); +/* XXX: BEGIN Citus Nodes */ + else if (MATCH("MULTIPLAN", 9)) + return_value = _readMultiPlan(); + else if (MATCH("JOB", 3)) + return_value = _readJob(); + else if (MATCH("SHARDINTERVAL", 13)) + return_value = _readShardInterval(); + else if (MATCH("MAPMERGEJOB", 11)) + return_value = _readMapMergeJob(); + else if (MATCH("SHARDPLACEMENT", 14)) + return_value = _readShardPlacement(); + else if (MATCH("TASK", 4)) + return_value = _readTask(); +/* XXX: END Citus Nodes */ + else + { + elog(ERROR, "badly formatted node string \"%.32s\"...", token); + return_value = NULL; /* keep compiler quiet */ + } + + return (Node *) return_value; +} + +#endif diff --git a/src/backend/distributed/utils/citus_readfuncs_95.c b/src/backend/distributed/utils/citus_readfuncs_95.c new file mode 100644 index 000000000..84866f632 --- /dev/null +++ b/src/backend/distributed/utils/citus_readfuncs_95.c @@ -0,0 +1,1741 @@ +/*------------------------------------------------------------------------- + * + * citus_readfuncs.c + * CitusDB adapted reader functions for Citus & Postgres tree nodes + * + * Portions Copyright (c) 1996-2014, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * Portions Copyright (c) 2012-2015, Citus Data, Inc. + * + *------------------------------------------------------------------------- + */ +#include "postgres.h" + +#if (PG_VERSION_NUM >= 90500 && PG_VERSION_NUM < 90600) + +#include + +#include "distributed/citus_nodefuncs.h" +#include "distributed/master_metadata_utility.h" +#include "distributed/multi_logical_planner.h" +#include "distributed/multi_physical_planner.h" +#include "nodes/parsenodes.h" +#include "nodes/readfuncs.h" + + +/* + * Macros to simplify reading of different kinds of fields. Use these + * wherever possible to reduce the chance for silly typos. Note that these + * hard-wire conventions about the names of the local variables in a Read + * routine. + */ + +/* Macros for declaring appropriate local variables */ + +/* A few guys need only local_node */ +#define READ_LOCALS_NO_FIELDS(nodeTypeName) \ + nodeTypeName *local_node = CitusMakeNode(nodeTypeName) + +/* And a few guys need only the citus_pg_strtok support fields */ +#define READ_TEMP_LOCALS() \ + char *token; \ + int length + +/* ... but most need both */ +#define READ_LOCALS(nodeTypeName) \ + READ_LOCALS_NO_FIELDS(nodeTypeName); \ + READ_TEMP_LOCALS() + +/* Read an integer field (anything written as ":fldname %d") */ +#define READ_INT_FIELD(fldname) \ + token = citus_pg_strtok(&length); /* skip :fldname */ \ + token = citus_pg_strtok(&length); /* get field value */ \ + local_node->fldname = atoi(token) + +/* Read an unsigned integer field (anything written as ":fldname %u") */ +#define READ_UINT_FIELD(fldname) \ + token = citus_pg_strtok(&length); /* skip :fldname */ \ + token = citus_pg_strtok(&length); /* get field value */ \ + local_node->fldname = atoui(token) + +/* XXX: CITUS Read an uint64 field (anything written as ":fldname %u") */ +#define READ_UINT64_FIELD(fldname) \ + token = citus_pg_strtok(&length); /* skip :fldname */ \ + token = citus_pg_strtok(&length); /* get field value */ \ + local_node->fldname = atoull(token) + +/* Read an OID field (don't hard-wire assumption that OID is same as uint) */ +#define READ_OID_FIELD(fldname) \ + token = citus_pg_strtok(&length); /* skip :fldname */ \ + token = citus_pg_strtok(&length); /* get field value */ \ + local_node->fldname = atooid(token) + +/* Read a char field (ie, one ascii character) */ +#define READ_CHAR_FIELD(fldname) \ + token = citus_pg_strtok(&length); /* skip :fldname */ \ + token = citus_pg_strtok(&length); /* get field value */ \ + local_node->fldname = token[0] + +/* Read an enumerated-type field that was written as an integer code */ +#define READ_ENUM_FIELD(fldname, enumtype) \ + token = citus_pg_strtok(&length); /* skip :fldname */ \ + token = citus_pg_strtok(&length); /* get field value */ \ + local_node->fldname = (enumtype) atoi(token) + +/* Read a float field */ +#define READ_FLOAT_FIELD(fldname) \ + token = citus_pg_strtok(&length); /* skip :fldname */ \ + token = citus_pg_strtok(&length); /* get field value */ \ + local_node->fldname = atof(token) + +/* Read a boolean field */ +#define READ_BOOL_FIELD(fldname) \ + token = citus_pg_strtok(&length); /* skip :fldname */ \ + token = citus_pg_strtok(&length); /* get field value */ \ + local_node->fldname = strtobool(token) + +/* Read a character-string field */ +#define READ_STRING_FIELD(fldname) \ + token = citus_pg_strtok(&length); /* skip :fldname */ \ + token = citus_pg_strtok(&length); /* get field value */ \ + local_node->fldname = nullable_string(token, length) + +/* Read a parse location field (and throw away the value, per notes above) */ +#define READ_LOCATION_FIELD(fldname) \ + token = citus_pg_strtok(&length); /* skip :fldname */ \ + token = citus_pg_strtok(&length); /* get field value */ \ + (void) token; /* in case not used elsewhere */ \ + local_node->fldname = -1 /* set field to "unknown" */ + +/* Read a Node field XXX: Citus: replaced call to nodeRead with CitusNodeRead */ +#define READ_NODE_FIELD(fldname) \ + token = citus_pg_strtok(&length); /* skip :fldname */ \ + (void) token; /* in case not used elsewhere */ \ + local_node->fldname = CitusNodeRead(NULL, 0) + +/* Read a bitmapset field */ +#define READ_BITMAPSET_FIELD(fldname) \ + token = citus_pg_strtok(&length); /* skip :fldname */ \ + (void) token; /* in case not used elsewhere */ \ + local_node->fldname = _readBitmapset() + + +/* Routine exit */ +#define READ_DONE() \ + return local_node + + +/* + * NOTE: use atoi() to read values written with %d, or atoui() to read + * values written with %u in outfuncs.c. An exception is OID values, + * for which use atooid(). (As of 7.1, outfuncs.c writes OIDs as %u, + * but this will probably change in the future.) + */ +#define atoui(x) ((unsigned int) strtoul((x), NULL, 10)) + +#define atooid(x) ((Oid) strtoul((x), NULL, 10)) + +/* XXX: Citus */ +#define atoull(x) ((uint64) strtoull((x), NULL, 10)) + +#define strtobool(x) ((*(x) == 't') ? true : false) + +#define nullable_string(token,length) \ + ((length) == 0 ? NULL : debackslash(token, length)) + + +static Datum readDatum(bool typbyval); + +/* + * _readBitmapset + */ +static Bitmapset * +_readBitmapset(void) +{ + Bitmapset *result = NULL; + + READ_TEMP_LOCALS(); + + token = citus_pg_strtok(&length); + if (token == NULL) + elog(ERROR, "incomplete Bitmapset structure"); + if (length != 1 || token[0] != '(') + elog(ERROR, "unrecognized token: \"%.*s\"", length, token); + + token = citus_pg_strtok(&length); + if (token == NULL) + elog(ERROR, "incomplete Bitmapset structure"); + if (length != 1 || token[0] != 'b') + elog(ERROR, "unrecognized token: \"%.*s\"", length, token); + + for (;;) + { + int val; + char *endptr; + + token = citus_pg_strtok(&length); + if (token == NULL) + elog(ERROR, "unterminated Bitmapset structure"); + if (length == 1 && token[0] == ')') + break; + val = (int) strtol(token, &endptr, 10); + if (endptr != token + length) + elog(ERROR, "unrecognized integer: \"%.*s\"", length, token); + result = bms_add_member(result, val); + } + + return result; +} + + +/* + * _readQuery + */ +static Query * +_readQuery(void) +{ + READ_LOCALS(Query); + + READ_ENUM_FIELD(commandType, CmdType); + READ_ENUM_FIELD(querySource, QuerySource); + local_node->queryId = 0; /* not saved in output format */ + READ_BOOL_FIELD(canSetTag); + READ_NODE_FIELD(utilityStmt); + READ_INT_FIELD(resultRelation); + READ_BOOL_FIELD(hasAggs); + READ_BOOL_FIELD(hasWindowFuncs); + READ_BOOL_FIELD(hasSubLinks); + READ_BOOL_FIELD(hasDistinctOn); + READ_BOOL_FIELD(hasRecursive); + READ_BOOL_FIELD(hasModifyingCTE); + READ_BOOL_FIELD(hasForUpdate); + READ_BOOL_FIELD(hasRowSecurity); + READ_NODE_FIELD(cteList); + READ_NODE_FIELD(rtable); + READ_NODE_FIELD(jointree); + READ_NODE_FIELD(targetList); + READ_NODE_FIELD(onConflict); + READ_NODE_FIELD(returningList); + READ_NODE_FIELD(groupClause); + READ_NODE_FIELD(groupingSets); + READ_NODE_FIELD(havingQual); + READ_NODE_FIELD(windowClause); + READ_NODE_FIELD(distinctClause); + READ_NODE_FIELD(sortClause); + READ_NODE_FIELD(limitOffset); + READ_NODE_FIELD(limitCount); + READ_NODE_FIELD(rowMarks); + READ_NODE_FIELD(setOperations); + READ_NODE_FIELD(constraintDeps); + + READ_DONE(); +} + +/* + * _readNotifyStmt + */ +static NotifyStmt * +_readNotifyStmt(void) +{ + READ_LOCALS(NotifyStmt); + + READ_STRING_FIELD(conditionname); + READ_STRING_FIELD(payload); + + READ_DONE(); +} + +/* + * _readDeclareCursorStmt + */ +static DeclareCursorStmt * +_readDeclareCursorStmt(void) +{ + READ_LOCALS(DeclareCursorStmt); + + READ_STRING_FIELD(portalname); + READ_INT_FIELD(options); + READ_NODE_FIELD(query); + + READ_DONE(); +} + +/* + * _readWithCheckOption + */ +static WithCheckOption * +_readWithCheckOption(void) +{ + READ_LOCALS(WithCheckOption); + + READ_ENUM_FIELD(kind, WCOKind); + READ_STRING_FIELD(relname); + READ_STRING_FIELD(polname); + READ_NODE_FIELD(qual); + READ_BOOL_FIELD(cascaded); + + READ_DONE(); +} + +/* + * _readSortGroupClause + */ +static SortGroupClause * +_readSortGroupClause(void) +{ + READ_LOCALS(SortGroupClause); + + READ_UINT_FIELD(tleSortGroupRef); + READ_OID_FIELD(eqop); + READ_OID_FIELD(sortop); + READ_BOOL_FIELD(nulls_first); + READ_BOOL_FIELD(hashable); + + READ_DONE(); +} + +/* + * _readGroupingSet + */ +static GroupingSet * +_readGroupingSet(void) +{ + READ_LOCALS(GroupingSet); + + READ_ENUM_FIELD(kind, GroupingSetKind); + READ_NODE_FIELD(content); + READ_LOCATION_FIELD(location); + + READ_DONE(); +} + +/* + * _readWindowClause + */ +static WindowClause * +_readWindowClause(void) +{ + READ_LOCALS(WindowClause); + + READ_STRING_FIELD(name); + READ_STRING_FIELD(refname); + READ_NODE_FIELD(partitionClause); + READ_NODE_FIELD(orderClause); + READ_INT_FIELD(frameOptions); + READ_NODE_FIELD(startOffset); + READ_NODE_FIELD(endOffset); + READ_UINT_FIELD(winref); + READ_BOOL_FIELD(copiedOrder); + + READ_DONE(); +} + +/* + * _readRowMarkClause + */ +static RowMarkClause * +_readRowMarkClause(void) +{ + READ_LOCALS(RowMarkClause); + + READ_UINT_FIELD(rti); + READ_ENUM_FIELD(strength, LockClauseStrength); + READ_ENUM_FIELD(waitPolicy, LockWaitPolicy); + READ_BOOL_FIELD(pushedDown); + + READ_DONE(); +} + +/* + * _readCommonTableExpr + */ +static CommonTableExpr * +_readCommonTableExpr(void) +{ + READ_LOCALS(CommonTableExpr); + + READ_STRING_FIELD(ctename); + READ_NODE_FIELD(aliascolnames); + READ_NODE_FIELD(ctequery); + READ_LOCATION_FIELD(location); + READ_BOOL_FIELD(cterecursive); + READ_INT_FIELD(cterefcount); + READ_NODE_FIELD(ctecolnames); + READ_NODE_FIELD(ctecoltypes); + READ_NODE_FIELD(ctecoltypmods); + READ_NODE_FIELD(ctecolcollations); + + READ_DONE(); +} + +/* + * _readSetOperationStmt + */ +static SetOperationStmt * +_readSetOperationStmt(void) +{ + READ_LOCALS(SetOperationStmt); + + READ_ENUM_FIELD(op, SetOperation); + READ_BOOL_FIELD(all); + READ_NODE_FIELD(larg); + READ_NODE_FIELD(rarg); + READ_NODE_FIELD(colTypes); + READ_NODE_FIELD(colTypmods); + READ_NODE_FIELD(colCollations); + READ_NODE_FIELD(groupClauses); + + READ_DONE(); +} + + +/* + * Stuff from primnodes.h. + */ + +static Alias * +_readAlias(void) +{ + READ_LOCALS(Alias); + + READ_STRING_FIELD(aliasname); + READ_NODE_FIELD(colnames); + + READ_DONE(); +} + +static RangeVar * +_readRangeVar(void) +{ + READ_LOCALS(RangeVar); + + local_node->catalogname = NULL; /* not currently saved in output + * format */ + + READ_STRING_FIELD(schemaname); + READ_STRING_FIELD(relname); + READ_ENUM_FIELD(inhOpt, InhOption); + READ_CHAR_FIELD(relpersistence); + READ_NODE_FIELD(alias); + READ_LOCATION_FIELD(location); + + READ_DONE(); +} + +static IntoClause * +_readIntoClause(void) +{ + READ_LOCALS(IntoClause); + + READ_NODE_FIELD(rel); + READ_NODE_FIELD(colNames); + READ_NODE_FIELD(options); + READ_ENUM_FIELD(onCommit, OnCommitAction); + READ_STRING_FIELD(tableSpaceName); + READ_NODE_FIELD(viewQuery); + READ_BOOL_FIELD(skipData); + + READ_DONE(); +} + +/* + * _readVar + */ +static Var * +_readVar(void) +{ + READ_LOCALS(Var); + + READ_UINT_FIELD(varno); + READ_INT_FIELD(varattno); + READ_OID_FIELD(vartype); + READ_INT_FIELD(vartypmod); + READ_OID_FIELD(varcollid); + READ_UINT_FIELD(varlevelsup); + READ_UINT_FIELD(varnoold); + READ_INT_FIELD(varoattno); + READ_LOCATION_FIELD(location); + + READ_DONE(); +} + +/* + * _readConst + */ +static Const * +_readConst(void) +{ + READ_LOCALS(Const); + + READ_OID_FIELD(consttype); + READ_INT_FIELD(consttypmod); + READ_OID_FIELD(constcollid); + READ_INT_FIELD(constlen); + READ_BOOL_FIELD(constbyval); + READ_BOOL_FIELD(constisnull); + READ_LOCATION_FIELD(location); + + token = citus_pg_strtok(&length); /* skip :constvalue */ + if (local_node->constisnull) + token = citus_pg_strtok(&length); /* skip "<>" */ + else + local_node->constvalue = readDatum(local_node->constbyval); + + READ_DONE(); +} + +/* + * _readParam + */ +static Param * +_readParam(void) +{ + READ_LOCALS(Param); + + READ_ENUM_FIELD(paramkind, ParamKind); + READ_INT_FIELD(paramid); + READ_OID_FIELD(paramtype); + READ_INT_FIELD(paramtypmod); + READ_OID_FIELD(paramcollid); + READ_LOCATION_FIELD(location); + + READ_DONE(); +} + +/* + * _readAggref + */ +static Aggref * +_readAggref(void) +{ + READ_LOCALS(Aggref); + + READ_OID_FIELD(aggfnoid); + READ_OID_FIELD(aggtype); + READ_OID_FIELD(aggcollid); + READ_OID_FIELD(inputcollid); + READ_NODE_FIELD(aggdirectargs); + READ_NODE_FIELD(args); + READ_NODE_FIELD(aggorder); + READ_NODE_FIELD(aggdistinct); + READ_NODE_FIELD(aggfilter); + READ_BOOL_FIELD(aggstar); + READ_BOOL_FIELD(aggvariadic); + READ_CHAR_FIELD(aggkind); + READ_UINT_FIELD(agglevelsup); + READ_LOCATION_FIELD(location); + + READ_DONE(); +} + +/* + * _readGroupingFunc + */ +static GroupingFunc * +_readGroupingFunc(void) +{ + READ_LOCALS(GroupingFunc); + + READ_NODE_FIELD(args); + READ_NODE_FIELD(refs); + READ_NODE_FIELD(cols); + READ_UINT_FIELD(agglevelsup); + READ_LOCATION_FIELD(location); + + READ_DONE(); +} + +/* + * _readWindowFunc + */ +static WindowFunc * +_readWindowFunc(void) +{ + READ_LOCALS(WindowFunc); + + READ_OID_FIELD(winfnoid); + READ_OID_FIELD(wintype); + READ_OID_FIELD(wincollid); + READ_OID_FIELD(inputcollid); + READ_NODE_FIELD(args); + READ_NODE_FIELD(aggfilter); + READ_UINT_FIELD(winref); + READ_BOOL_FIELD(winstar); + READ_BOOL_FIELD(winagg); + READ_LOCATION_FIELD(location); + + READ_DONE(); +} + +/* + * _readArrayRef + */ +static ArrayRef * +_readArrayRef(void) +{ + READ_LOCALS(ArrayRef); + + READ_OID_FIELD(refarraytype); + READ_OID_FIELD(refelemtype); + READ_INT_FIELD(reftypmod); + READ_OID_FIELD(refcollid); + READ_NODE_FIELD(refupperindexpr); + READ_NODE_FIELD(reflowerindexpr); + READ_NODE_FIELD(refexpr); + READ_NODE_FIELD(refassgnexpr); + + READ_DONE(); +} + +/* + * _readFuncExpr + */ +static FuncExpr * +_readFuncExpr(void) +{ + READ_LOCALS(FuncExpr); + + READ_OID_FIELD(funcid); + READ_OID_FIELD(funcresulttype); + READ_BOOL_FIELD(funcretset); + READ_BOOL_FIELD(funcvariadic); + READ_ENUM_FIELD(funcformat, CoercionForm); + READ_OID_FIELD(funccollid); + READ_OID_FIELD(inputcollid); + READ_NODE_FIELD(args); + READ_LOCATION_FIELD(location); + + READ_DONE(); +} + +/* + * _readNamedArgExpr + */ +static NamedArgExpr * +_readNamedArgExpr(void) +{ + READ_LOCALS(NamedArgExpr); + + READ_NODE_FIELD(arg); + READ_STRING_FIELD(name); + READ_INT_FIELD(argnumber); + READ_LOCATION_FIELD(location); + + READ_DONE(); +} + +/* + * _readOpExpr + */ +static OpExpr * +_readOpExpr(void) +{ + READ_LOCALS(OpExpr); + + READ_OID_FIELD(opno); + READ_OID_FIELD(opfuncid); + + /* + * The opfuncid is stored in the textual format primarily for debugging + * and documentation reasons. We want to always read it as zero to force + * it to be re-looked-up in the pg_operator entry. This ensures that + * stored rules don't have hidden dependencies on operators' functions. + * (We don't currently support an ALTER OPERATOR command, but might + * someday.) + */ + local_node->opfuncid = InvalidOid; + + READ_OID_FIELD(opresulttype); + READ_BOOL_FIELD(opretset); + READ_OID_FIELD(opcollid); + READ_OID_FIELD(inputcollid); + READ_NODE_FIELD(args); + READ_LOCATION_FIELD(location); + + READ_DONE(); +} + +/* + * _readDistinctExpr + */ +static DistinctExpr * +_readDistinctExpr(void) +{ + READ_LOCALS(DistinctExpr); + + READ_OID_FIELD(opno); + READ_OID_FIELD(opfuncid); + + /* + * The opfuncid is stored in the textual format primarily for debugging + * and documentation reasons. We want to always read it as zero to force + * it to be re-looked-up in the pg_operator entry. This ensures that + * stored rules don't have hidden dependencies on operators' functions. + * (We don't currently support an ALTER OPERATOR command, but might + * someday.) + */ + local_node->opfuncid = InvalidOid; + + READ_OID_FIELD(opresulttype); + READ_BOOL_FIELD(opretset); + READ_OID_FIELD(opcollid); + READ_OID_FIELD(inputcollid); + READ_NODE_FIELD(args); + READ_LOCATION_FIELD(location); + + READ_DONE(); +} + +/* + * _readNullIfExpr + */ +static NullIfExpr * +_readNullIfExpr(void) +{ + READ_LOCALS(NullIfExpr); + + READ_OID_FIELD(opno); + READ_OID_FIELD(opfuncid); + + /* + * The opfuncid is stored in the textual format primarily for debugging + * and documentation reasons. We want to always read it as zero to force + * it to be re-looked-up in the pg_operator entry. This ensures that + * stored rules don't have hidden dependencies on operators' functions. + * (We don't currently support an ALTER OPERATOR command, but might + * someday.) + */ + local_node->opfuncid = InvalidOid; + + READ_OID_FIELD(opresulttype); + READ_BOOL_FIELD(opretset); + READ_OID_FIELD(opcollid); + READ_OID_FIELD(inputcollid); + READ_NODE_FIELD(args); + READ_LOCATION_FIELD(location); + + READ_DONE(); +} + +/* + * _readScalarArrayOpExpr + */ +static ScalarArrayOpExpr * +_readScalarArrayOpExpr(void) +{ + READ_LOCALS(ScalarArrayOpExpr); + + READ_OID_FIELD(opno); + READ_OID_FIELD(opfuncid); + + /* + * The opfuncid is stored in the textual format primarily for debugging + * and documentation reasons. We want to always read it as zero to force + * it to be re-looked-up in the pg_operator entry. This ensures that + * stored rules don't have hidden dependencies on operators' functions. + * (We don't currently support an ALTER OPERATOR command, but might + * someday.) + */ + local_node->opfuncid = InvalidOid; + + READ_BOOL_FIELD(useOr); + READ_OID_FIELD(inputcollid); + READ_NODE_FIELD(args); + READ_LOCATION_FIELD(location); + + READ_DONE(); +} + +/* + * _readBoolExpr + */ +static BoolExpr * +_readBoolExpr(void) +{ + READ_LOCALS(BoolExpr); + + /* do-it-yourself enum representation */ + token = citus_pg_strtok(&length); /* skip :boolop */ + token = citus_pg_strtok(&length); /* get field value */ + if (strncmp(token, "and", 3) == 0) + local_node->boolop = AND_EXPR; + else if (strncmp(token, "or", 2) == 0) + local_node->boolop = OR_EXPR; + else if (strncmp(token, "not", 3) == 0) + local_node->boolop = NOT_EXPR; + else + elog(ERROR, "unrecognized boolop \"%.*s\"", length, token); + + READ_NODE_FIELD(args); + READ_LOCATION_FIELD(location); + + READ_DONE(); +} + +/* + * _readSubLink + */ +static SubLink * +_readSubLink(void) +{ + READ_LOCALS(SubLink); + + READ_ENUM_FIELD(subLinkType, SubLinkType); + READ_INT_FIELD(subLinkId); + READ_NODE_FIELD(testexpr); + READ_NODE_FIELD(operName); + READ_NODE_FIELD(subselect); + READ_LOCATION_FIELD(location); + + READ_DONE(); +} + +/* + * _readSubPlan is not needed since it doesn't appear in stored rules. + */ + +/* + * _readFieldSelect + */ +static FieldSelect * +_readFieldSelect(void) +{ + READ_LOCALS(FieldSelect); + + READ_NODE_FIELD(arg); + READ_INT_FIELD(fieldnum); + READ_OID_FIELD(resulttype); + READ_INT_FIELD(resulttypmod); + READ_OID_FIELD(resultcollid); + + READ_DONE(); +} + +/* + * _readFieldStore + */ +static FieldStore * +_readFieldStore(void) +{ + READ_LOCALS(FieldStore); + + READ_NODE_FIELD(arg); + READ_NODE_FIELD(newvals); + READ_NODE_FIELD(fieldnums); + READ_OID_FIELD(resulttype); + + READ_DONE(); +} + +/* + * _readRelabelType + */ +static RelabelType * +_readRelabelType(void) +{ + READ_LOCALS(RelabelType); + + READ_NODE_FIELD(arg); + READ_OID_FIELD(resulttype); + READ_INT_FIELD(resulttypmod); + READ_OID_FIELD(resultcollid); + READ_ENUM_FIELD(relabelformat, CoercionForm); + READ_LOCATION_FIELD(location); + + READ_DONE(); +} + +/* + * _readCoerceViaIO + */ +static CoerceViaIO * +_readCoerceViaIO(void) +{ + READ_LOCALS(CoerceViaIO); + + READ_NODE_FIELD(arg); + READ_OID_FIELD(resulttype); + READ_OID_FIELD(resultcollid); + READ_ENUM_FIELD(coerceformat, CoercionForm); + READ_LOCATION_FIELD(location); + + READ_DONE(); +} + +/* + * _readArrayCoerceExpr + */ +static ArrayCoerceExpr * +_readArrayCoerceExpr(void) +{ + READ_LOCALS(ArrayCoerceExpr); + + READ_NODE_FIELD(arg); + READ_OID_FIELD(elemfuncid); + READ_OID_FIELD(resulttype); + READ_INT_FIELD(resulttypmod); + READ_OID_FIELD(resultcollid); + READ_BOOL_FIELD(isExplicit); + READ_ENUM_FIELD(coerceformat, CoercionForm); + READ_LOCATION_FIELD(location); + + READ_DONE(); +} + +/* + * _readConvertRowtypeExpr + */ +static ConvertRowtypeExpr * +_readConvertRowtypeExpr(void) +{ + READ_LOCALS(ConvertRowtypeExpr); + + READ_NODE_FIELD(arg); + READ_OID_FIELD(resulttype); + READ_ENUM_FIELD(convertformat, CoercionForm); + READ_LOCATION_FIELD(location); + + READ_DONE(); +} + +/* + * _readCollateExpr + */ +static CollateExpr * +_readCollateExpr(void) +{ + READ_LOCALS(CollateExpr); + + READ_NODE_FIELD(arg); + READ_OID_FIELD(collOid); + READ_LOCATION_FIELD(location); + + READ_DONE(); +} + +/* + * _readCaseExpr + */ +static CaseExpr * +_readCaseExpr(void) +{ + READ_LOCALS(CaseExpr); + + READ_OID_FIELD(casetype); + READ_OID_FIELD(casecollid); + READ_NODE_FIELD(arg); + READ_NODE_FIELD(args); + READ_NODE_FIELD(defresult); + READ_LOCATION_FIELD(location); + + READ_DONE(); +} + +/* + * _readCaseWhen + */ +static CaseWhen * +_readCaseWhen(void) +{ + READ_LOCALS(CaseWhen); + + READ_NODE_FIELD(expr); + READ_NODE_FIELD(result); + READ_LOCATION_FIELD(location); + + READ_DONE(); +} + +/* + * _readCaseTestExpr + */ +static CaseTestExpr * +_readCaseTestExpr(void) +{ + READ_LOCALS(CaseTestExpr); + + READ_OID_FIELD(typeId); + READ_INT_FIELD(typeMod); + READ_OID_FIELD(collation); + + READ_DONE(); +} + +/* + * _readArrayExpr + */ +static ArrayExpr * +_readArrayExpr(void) +{ + READ_LOCALS(ArrayExpr); + + READ_OID_FIELD(array_typeid); + READ_OID_FIELD(array_collid); + READ_OID_FIELD(element_typeid); + READ_NODE_FIELD(elements); + READ_BOOL_FIELD(multidims); + READ_LOCATION_FIELD(location); + + READ_DONE(); +} + +/* + * _readRowExpr + */ +static RowExpr * +_readRowExpr(void) +{ + READ_LOCALS(RowExpr); + + READ_NODE_FIELD(args); + READ_OID_FIELD(row_typeid); + READ_ENUM_FIELD(row_format, CoercionForm); + READ_NODE_FIELD(colnames); + READ_LOCATION_FIELD(location); + + READ_DONE(); +} + +/* + * _readRowCompareExpr + */ +static RowCompareExpr * +_readRowCompareExpr(void) +{ + READ_LOCALS(RowCompareExpr); + + READ_ENUM_FIELD(rctype, RowCompareType); + READ_NODE_FIELD(opnos); + READ_NODE_FIELD(opfamilies); + READ_NODE_FIELD(inputcollids); + READ_NODE_FIELD(largs); + READ_NODE_FIELD(rargs); + + READ_DONE(); +} + +/* + * _readCoalesceExpr + */ +static CoalesceExpr * +_readCoalesceExpr(void) +{ + READ_LOCALS(CoalesceExpr); + + READ_OID_FIELD(coalescetype); + READ_OID_FIELD(coalescecollid); + READ_NODE_FIELD(args); + READ_LOCATION_FIELD(location); + + READ_DONE(); +} + +/* + * _readMinMaxExpr + */ +static MinMaxExpr * +_readMinMaxExpr(void) +{ + READ_LOCALS(MinMaxExpr); + + READ_OID_FIELD(minmaxtype); + READ_OID_FIELD(minmaxcollid); + READ_OID_FIELD(inputcollid); + READ_ENUM_FIELD(op, MinMaxOp); + READ_NODE_FIELD(args); + READ_LOCATION_FIELD(location); + + READ_DONE(); +} + +/* + * _readXmlExpr + */ +static XmlExpr * +_readXmlExpr(void) +{ + READ_LOCALS(XmlExpr); + + READ_ENUM_FIELD(op, XmlExprOp); + READ_STRING_FIELD(name); + READ_NODE_FIELD(named_args); + READ_NODE_FIELD(arg_names); + READ_NODE_FIELD(args); + READ_ENUM_FIELD(xmloption, XmlOptionType); + READ_OID_FIELD(type); + READ_INT_FIELD(typmod); + READ_LOCATION_FIELD(location); + + READ_DONE(); +} + +/* + * _readNullTest + */ +static NullTest * +_readNullTest(void) +{ + READ_LOCALS(NullTest); + + READ_NODE_FIELD(arg); + READ_ENUM_FIELD(nulltesttype, NullTestType); + READ_BOOL_FIELD(argisrow); + READ_LOCATION_FIELD(location); + + READ_DONE(); +} + +/* + * _readBooleanTest + */ +static BooleanTest * +_readBooleanTest(void) +{ + READ_LOCALS(BooleanTest); + + READ_NODE_FIELD(arg); + READ_ENUM_FIELD(booltesttype, BoolTestType); + READ_LOCATION_FIELD(location); + + READ_DONE(); +} + +/* + * _readCoerceToDomain + */ +static CoerceToDomain * +_readCoerceToDomain(void) +{ + READ_LOCALS(CoerceToDomain); + + READ_NODE_FIELD(arg); + READ_OID_FIELD(resulttype); + READ_INT_FIELD(resulttypmod); + READ_OID_FIELD(resultcollid); + READ_ENUM_FIELD(coercionformat, CoercionForm); + READ_LOCATION_FIELD(location); + + READ_DONE(); +} + +/* + * _readCoerceToDomainValue + */ +static CoerceToDomainValue * +_readCoerceToDomainValue(void) +{ + READ_LOCALS(CoerceToDomainValue); + + READ_OID_FIELD(typeId); + READ_INT_FIELD(typeMod); + READ_OID_FIELD(collation); + READ_LOCATION_FIELD(location); + + READ_DONE(); +} + +/* + * _readSetToDefault + */ +static SetToDefault * +_readSetToDefault(void) +{ + READ_LOCALS(SetToDefault); + + READ_OID_FIELD(typeId); + READ_INT_FIELD(typeMod); + READ_OID_FIELD(collation); + READ_LOCATION_FIELD(location); + + READ_DONE(); +} + +/* + * _readCurrentOfExpr + */ +static CurrentOfExpr * +_readCurrentOfExpr(void) +{ + READ_LOCALS(CurrentOfExpr); + + READ_UINT_FIELD(cvarno); + READ_STRING_FIELD(cursor_name); + READ_INT_FIELD(cursor_param); + + READ_DONE(); +} + +/* + * _readInferenceElem + */ +static InferenceElem * +_readInferenceElem(void) +{ + READ_LOCALS(InferenceElem); + + READ_NODE_FIELD(expr); + READ_OID_FIELD(infercollid); + READ_OID_FIELD(inferopclass); + + READ_DONE(); +} + +/* + * _readTargetEntry + */ +static TargetEntry * +_readTargetEntry(void) +{ + READ_LOCALS(TargetEntry); + + READ_NODE_FIELD(expr); + READ_INT_FIELD(resno); + READ_STRING_FIELD(resname); + READ_UINT_FIELD(ressortgroupref); + READ_OID_FIELD(resorigtbl); + READ_INT_FIELD(resorigcol); + READ_BOOL_FIELD(resjunk); + + READ_DONE(); +} + +/* + * _readRangeTblRef + */ +static RangeTblRef * +_readRangeTblRef(void) +{ + READ_LOCALS(RangeTblRef); + + READ_INT_FIELD(rtindex); + + READ_DONE(); +} + +/* + * _readJoinExpr + */ +static JoinExpr * +_readJoinExpr(void) +{ + READ_LOCALS(JoinExpr); + + READ_ENUM_FIELD(jointype, JoinType); + READ_BOOL_FIELD(isNatural); + READ_NODE_FIELD(larg); + READ_NODE_FIELD(rarg); + READ_NODE_FIELD(usingClause); + READ_NODE_FIELD(quals); + READ_NODE_FIELD(alias); + READ_INT_FIELD(rtindex); + + READ_DONE(); +} + +/* + * _readFromExpr + */ +static FromExpr * +_readFromExpr(void) +{ + READ_LOCALS(FromExpr); + + READ_NODE_FIELD(fromlist); + READ_NODE_FIELD(quals); + + READ_DONE(); +} + +/* + * _readOnConflictExpr + */ +static OnConflictExpr * +_readOnConflictExpr(void) +{ + READ_LOCALS(OnConflictExpr); + + READ_ENUM_FIELD(action, OnConflictAction); + READ_NODE_FIELD(arbiterElems); + READ_NODE_FIELD(arbiterWhere); + READ_OID_FIELD(constraint); + READ_NODE_FIELD(onConflictSet); + READ_NODE_FIELD(onConflictWhere); + READ_INT_FIELD(exclRelIndex); + READ_NODE_FIELD(exclRelTlist); + + READ_DONE(); +} + +/* + * Stuff from parsenodes.h. + */ + +/* + * _readRangeTblEntry + */ +static RangeTblEntry * +_readRangeTblEntry(void) +{ + READ_LOCALS(RangeTblEntry); + + /* put alias + eref first to make dump more legible */ + READ_NODE_FIELD(alias); + READ_NODE_FIELD(eref); + READ_ENUM_FIELD(rtekind, RTEKind); + + switch (local_node->rtekind) + { + case RTE_RELATION: + READ_OID_FIELD(relid); + READ_CHAR_FIELD(relkind); + READ_NODE_FIELD(tablesample); + break; + case RTE_SUBQUERY: + READ_NODE_FIELD(subquery); + READ_BOOL_FIELD(security_barrier); + break; + case RTE_JOIN: + READ_ENUM_FIELD(jointype, JoinType); + READ_NODE_FIELD(joinaliasvars); + break; + case RTE_FUNCTION: + READ_NODE_FIELD(functions); + READ_BOOL_FIELD(funcordinality); + break; + case RTE_VALUES: + READ_NODE_FIELD(values_lists); + READ_NODE_FIELD(values_collations); + break; + case RTE_CTE: + READ_STRING_FIELD(ctename); + READ_UINT_FIELD(ctelevelsup); + READ_BOOL_FIELD(self_reference); + READ_NODE_FIELD(ctecoltypes); + READ_NODE_FIELD(ctecoltypmods); + READ_NODE_FIELD(ctecolcollations); + break; + default: + elog(ERROR, "unrecognized RTE kind: %d", + (int) local_node->rtekind); + break; + } + + READ_BOOL_FIELD(lateral); + READ_BOOL_FIELD(inh); + READ_BOOL_FIELD(inFromCl); + READ_UINT_FIELD(requiredPerms); + READ_OID_FIELD(checkAsUser); + READ_BITMAPSET_FIELD(selectedCols); + READ_BITMAPSET_FIELD(insertedCols); + READ_BITMAPSET_FIELD(updatedCols); + READ_NODE_FIELD(securityQuals); + + READ_DONE(); +} + +/* + * _readRangeTblFunction + */ +static RangeTblFunction * +_readRangeTblFunction(void) +{ + READ_LOCALS(RangeTblFunction); + + READ_NODE_FIELD(funcexpr); + READ_INT_FIELD(funccolcount); + READ_NODE_FIELD(funccolnames); + READ_NODE_FIELD(funccoltypes); + READ_NODE_FIELD(funccoltypmods); + READ_NODE_FIELD(funccolcollations); + READ_BITMAPSET_FIELD(funcparams); + + READ_DONE(); +} + +/* + * _readTableSampleClause + */ +static TableSampleClause * +_readTableSampleClause(void) +{ + READ_LOCALS(TableSampleClause); + + READ_OID_FIELD(tsmhandler); + READ_NODE_FIELD(args); + READ_NODE_FIELD(repeatable); + + READ_DONE(); +} + + +/* XXX: BEGIN Citus Nodes */ + +static void +_readJobInfo(Job *local_node) +{ + READ_TEMP_LOCALS(); + + READ_UINT64_FIELD(jobId); + READ_NODE_FIELD(jobQuery); + READ_NODE_FIELD(taskList); + READ_NODE_FIELD(dependedJobList); + READ_BOOL_FIELD(subqueryPushdown); +} + + +static Job * +_readJob(void) +{ + READ_LOCALS_NO_FIELDS(Job); + + _readJobInfo(local_node); + + READ_DONE(); +} + + +static MultiPlan * +_readMultiPlan(void) +{ + READ_LOCALS(MultiPlan); + + READ_NODE_FIELD(workerJob); + READ_NODE_FIELD(masterQuery); + READ_STRING_FIELD(masterTableName); + + READ_DONE(); +} + + +static ShardInterval * +_readShardInterval(void) +{ + READ_LOCALS(ShardInterval); + + + READ_OID_FIELD(relationId); + READ_CHAR_FIELD(storageType); + READ_OID_FIELD(valueTypeId); + READ_INT_FIELD(valueTypeLen); + READ_BOOL_FIELD(valueByVal); + READ_BOOL_FIELD(minValueExists); + READ_BOOL_FIELD(maxValueExists); + + token = citus_pg_strtok(&length); /* skip :minValue */ + if (!local_node->minValueExists) + token = citus_pg_strtok(&length); /* skip "<>" */ + else + local_node->minValue = readDatum(local_node->valueByVal); + + token = citus_pg_strtok(&length); /* skip :maxValue */ + if (!local_node->minValueExists) + token = citus_pg_strtok(&length); /* skip "<>" */ + else + local_node->maxValue = readDatum(local_node->valueByVal); + + READ_UINT64_FIELD(shardId); + + READ_DONE(); +} + + +static MapMergeJob * +_readMapMergeJob(void) +{ + int arrayLength; + int i; + + READ_LOCALS(MapMergeJob); + + _readJobInfo(&local_node->job); + + READ_NODE_FIELD(reduceQuery); + READ_ENUM_FIELD(partitionType, PartitionType); + READ_NODE_FIELD(partitionColumn); + READ_UINT_FIELD(partitionCount); + READ_INT_FIELD(sortedShardIntervalArrayLength); + + arrayLength = local_node->sortedShardIntervalArrayLength; + + /* now build & read sortedShardIntervalArray */ + local_node->sortedShardIntervalArray = + (ShardInterval**) palloc(arrayLength * sizeof(ShardInterval *)); + + for (i = 0; i < arrayLength; ++i) + { + local_node->sortedShardIntervalArray[i] = _readShardInterval(); + } + + READ_NODE_FIELD(mapTaskList); + READ_NODE_FIELD(mergeTaskList); + + READ_DONE(); +} + + +static ShardPlacement * +_readShardPlacement(void) +{ + READ_LOCALS(ShardPlacement); + + READ_OID_FIELD(tupleOid); + READ_UINT64_FIELD(shardId); + READ_UINT64_FIELD(shardLength); + READ_ENUM_FIELD(shardState, RelayFileState); + READ_STRING_FIELD(nodeName); + READ_UINT_FIELD(nodePort); + + READ_DONE(); +} + + +static Task * +_readTask(void) +{ + READ_LOCALS(Task); + + READ_ENUM_FIELD(taskType, TaskType); + READ_UINT64_FIELD(jobId); + READ_UINT_FIELD(taskId); + READ_STRING_FIELD(queryString); + READ_UINT64_FIELD(anchorShardId); + READ_NODE_FIELD(taskPlacementList); + READ_NODE_FIELD(dependedTaskList); + READ_UINT_FIELD(partitionId); + READ_UINT_FIELD(upstreamTaskId); + READ_NODE_FIELD(shardInterval); + READ_BOOL_FIELD(assignmentConstrained); + READ_NODE_FIELD(taskExecution); + READ_BOOL_FIELD(upsertQuery); + + READ_DONE(); +} + + +/* XXX: END Citus Nodes */ + + +/* + * readDatum + * + * Given a string representation of a constant, recreate the appropriate + * Datum. The string representation embeds length info, but not byValue, + * so we must be told that. + */ +static Datum +readDatum(bool typbyval) +{ + Size length, + i; + int tokenLength; + char *token; + Datum res; + char *s; + + /* + * read the actual length of the value + */ + token = citus_pg_strtok(&tokenLength); + length = atoui(token); + + token = citus_pg_strtok(&tokenLength); /* read the '[' */ + if (token == NULL || token[0] != '[') + elog(ERROR, "expected \"[\" to start datum, but got \"%s\"; length = %zu", + token ? (const char *) token : "[NULL]", length); + + if (typbyval) + { + if (length > (Size) sizeof(Datum)) + elog(ERROR, "byval datum but length = %zu", length); + res = (Datum) 0; + s = (char *) (&res); + for (i = 0; i < (Size) sizeof(Datum); i++) + { + token = citus_pg_strtok(&tokenLength); + s[i] = (char) atoi(token); + } + } + else if (length <= 0) + res = (Datum) NULL; + else + { + s = (char *) palloc(length); + for (i = 0; i < length; i++) + { + token = citus_pg_strtok(&tokenLength); + s[i] = (char) atoi(token); + } + res = PointerGetDatum(s); + } + + token = citus_pg_strtok(&tokenLength); /* read the ']' */ + if (token == NULL || token[0] != ']') + elog(ERROR, "expected \"]\" to end datum, but got \"%s\"; length = %zu", + token ? (const char *) token : "[NULL]", length); + + return res; +} + + +/* + * parseNodeString + * + * Given a character string representing a node tree, parseNodeString creates + * the internal node structure. + * + * The string to be read must already have been loaded into citus_pg_strtok(). + */ +Node * +CitusParseNodeString(void) +{ + void *return_value; + + READ_TEMP_LOCALS(); + + token = citus_pg_strtok(&length); + +#define MATCH(tokname, namelen) \ + (length == namelen && memcmp(token, tokname, namelen) == 0) + + if (MATCH("QUERY", 5)) + return_value = _readQuery(); + else if (MATCH("WITHCHECKOPTION", 15)) + return_value = _readWithCheckOption(); + else if (MATCH("SORTGROUPCLAUSE", 15)) + return_value = _readSortGroupClause(); + else if (MATCH("GROUPINGSET", 11)) + return_value = _readGroupingSet(); + else if (MATCH("WINDOWCLAUSE", 12)) + return_value = _readWindowClause(); + else if (MATCH("ROWMARKCLAUSE", 13)) + return_value = _readRowMarkClause(); + else if (MATCH("COMMONTABLEEXPR", 15)) + return_value = _readCommonTableExpr(); + else if (MATCH("SETOPERATIONSTMT", 16)) + return_value = _readSetOperationStmt(); + else if (MATCH("ALIAS", 5)) + return_value = _readAlias(); + else if (MATCH("RANGEVAR", 8)) + return_value = _readRangeVar(); + else if (MATCH("INTOCLAUSE", 10)) + return_value = _readIntoClause(); + else if (MATCH("VAR", 3)) + return_value = _readVar(); + else if (MATCH("CONST", 5)) + return_value = _readConst(); + else if (MATCH("PARAM", 5)) + return_value = _readParam(); + else if (MATCH("AGGREF", 6)) + return_value = _readAggref(); + else if (MATCH("GROUPINGFUNC", 12)) + return_value = _readGroupingFunc(); + else if (MATCH("WINDOWFUNC", 10)) + return_value = _readWindowFunc(); + else if (MATCH("ARRAYREF", 8)) + return_value = _readArrayRef(); + else if (MATCH("FUNCEXPR", 8)) + return_value = _readFuncExpr(); + else if (MATCH("NAMEDARGEXPR", 12)) + return_value = _readNamedArgExpr(); + else if (MATCH("OPEXPR", 6)) + return_value = _readOpExpr(); + else if (MATCH("DISTINCTEXPR", 12)) + return_value = _readDistinctExpr(); + else if (MATCH("NULLIFEXPR", 10)) + return_value = _readNullIfExpr(); + else if (MATCH("SCALARARRAYOPEXPR", 17)) + return_value = _readScalarArrayOpExpr(); + else if (MATCH("BOOLEXPR", 8)) + return_value = _readBoolExpr(); + else if (MATCH("SUBLINK", 7)) + return_value = _readSubLink(); + else if (MATCH("FIELDSELECT", 11)) + return_value = _readFieldSelect(); + else if (MATCH("FIELDSTORE", 10)) + return_value = _readFieldStore(); + else if (MATCH("RELABELTYPE", 11)) + return_value = _readRelabelType(); + else if (MATCH("COERCEVIAIO", 11)) + return_value = _readCoerceViaIO(); + else if (MATCH("ARRAYCOERCEEXPR", 15)) + return_value = _readArrayCoerceExpr(); + else if (MATCH("CONVERTROWTYPEEXPR", 18)) + return_value = _readConvertRowtypeExpr(); + else if (MATCH("COLLATE", 7)) + return_value = _readCollateExpr(); + else if (MATCH("CASE", 4)) + return_value = _readCaseExpr(); + else if (MATCH("WHEN", 4)) + return_value = _readCaseWhen(); + else if (MATCH("CASETESTEXPR", 12)) + return_value = _readCaseTestExpr(); + else if (MATCH("ARRAY", 5)) + return_value = _readArrayExpr(); + else if (MATCH("ROW", 3)) + return_value = _readRowExpr(); + else if (MATCH("ROWCOMPARE", 10)) + return_value = _readRowCompareExpr(); + else if (MATCH("COALESCE", 8)) + return_value = _readCoalesceExpr(); + else if (MATCH("MINMAX", 6)) + return_value = _readMinMaxExpr(); + else if (MATCH("XMLEXPR", 7)) + return_value = _readXmlExpr(); + else if (MATCH("NULLTEST", 8)) + return_value = _readNullTest(); + else if (MATCH("BOOLEANTEST", 11)) + return_value = _readBooleanTest(); + else if (MATCH("COERCETODOMAIN", 14)) + return_value = _readCoerceToDomain(); + else if (MATCH("COERCETODOMAINVALUE", 19)) + return_value = _readCoerceToDomainValue(); + else if (MATCH("SETTODEFAULT", 12)) + return_value = _readSetToDefault(); + else if (MATCH("CURRENTOFEXPR", 13)) + return_value = _readCurrentOfExpr(); + else if (MATCH("INFERENCEELEM", 13)) + return_value = _readInferenceElem(); + else if (MATCH("TARGETENTRY", 11)) + return_value = _readTargetEntry(); + else if (MATCH("RANGETBLREF", 11)) + return_value = _readRangeTblRef(); + else if (MATCH("JOINEXPR", 8)) + return_value = _readJoinExpr(); + else if (MATCH("FROMEXPR", 8)) + return_value = _readFromExpr(); + else if (MATCH("ONCONFLICTEXPR", 14)) + return_value = _readOnConflictExpr(); + else if (MATCH("RTE", 3)) + return_value = _readRangeTblEntry(); + else if (MATCH("RANGETBLFUNCTION", 16)) + return_value = _readRangeTblFunction(); + else if (MATCH("TABLESAMPLECLAUSE", 17)) + return_value = _readTableSampleClause(); + else if (MATCH("NOTIFY", 6)) + return_value = _readNotifyStmt(); + else if (MATCH("DECLARECURSOR", 13)) + return_value = _readDeclareCursorStmt(); +/* XXX: BEGIN Citus Nodes */ + else if (MATCH("MULTIPLAN", 9)) + return_value = _readMultiPlan(); + else if (MATCH("JOB", 3)) + return_value = _readJob(); + else if (MATCH("SHARDINTERVAL", 13)) + return_value = _readShardInterval(); + else if (MATCH("MAPMERGEJOB", 11)) + return_value = _readMapMergeJob(); + else if (MATCH("SHARDPLACEMENT", 14)) + return_value = _readShardPlacement(); + else if (MATCH("TASK", 4)) + return_value = _readTask(); +/* XXX: END Citus Nodes */ + else + { + elog(ERROR, "badly formatted node string \"%.32s\"...", token); + return_value = NULL; /* keep compiler quiet */ + } + + return (Node *) return_value; +} + +#endif diff --git a/src/backend/distributed/utils/citus_ruleutils.c b/src/backend/distributed/utils/citus_ruleutils.c new file mode 100644 index 000000000..ad1ac7332 --- /dev/null +++ b/src/backend/distributed/utils/citus_ruleutils.c @@ -0,0 +1,560 @@ +/*------------------------------------------------------------------------- + * + * citus_ruleutils.c + * Version independent ruleutils wrapper + * + * Copyright (c) 2012-2015, Citus Data, Inc. + *------------------------------------------------------------------------- + */ + +#include "postgres.h" + +#include +#include + +#include "access/htup_details.h" +#include "access/sysattr.h" +#include "catalog/dependency.h" +#include "catalog/indexing.h" +#include "catalog/pg_aggregate.h" +#include "catalog/pg_extension.h" +#include "catalog/pg_foreign_data_wrapper.h" +#include "catalog/pg_opclass.h" +#include "catalog/pg_operator.h" +#include "catalog/pg_proc.h" +#include "catalog/pg_type.h" +#include "distributed/citus_nodefuncs.h" +#include "distributed/citus_ruleutils.h" +#include "commands/defrem.h" +#include "commands/extension.h" +#include "foreign/foreign.h" +#include "funcapi.h" +#include "mb/pg_wchar.h" +#include "miscadmin.h" +#include "nodes/makefuncs.h" +#include "nodes/nodeFuncs.h" +#include "optimizer/tlist.h" +#include "parser/keywords.h" +#include "parser/parse_agg.h" +#include "parser/parse_func.h" +#include "parser/parse_oper.h" +#include "parser/parser.h" +#include "parser/parsetree.h" +#include "rewrite/rewriteHandler.h" +#include "utils/builtins.h" +#include "utils/fmgroids.h" +#include "utils/lsyscache.h" +#include "utils/rel.h" +#if (PG_VERSION_NUM >= 90500) +#include "utils/ruleutils.h" +#endif +#include "utils/syscache.h" +#include "utils/typcache.h" +#include "utils/xml.h" + +static Oid get_extension_schema(Oid ext_oid); +static void AppendOptionListToString(StringInfo stringData, List *options); + +/* + * pg_get_extensiondef_string finds the foreign data wrapper that corresponds to + * the given foreign tableId, and checks if an extension owns this foreign data + * wrapper. If it does, the function returns the extension's definition. If not, + * the function returns null. + */ +char * +pg_get_extensiondef_string(Oid tableRelationId) +{ + ForeignTable *foreignTable = GetForeignTable(tableRelationId); + ForeignServer *server = GetForeignServer(foreignTable->serverid); + ForeignDataWrapper *foreignDataWrapper = GetForeignDataWrapper(server->fdwid); + StringInfoData buffer = { NULL, 0, 0, 0 }; + + Oid classId = ForeignDataWrapperRelationId; + Oid objectId = server->fdwid; + + Oid extensionId = getExtensionOfObject(classId, objectId); + if (OidIsValid(extensionId)) + { + char *extensionName = get_extension_name(extensionId); + Oid extensionSchemaId = get_extension_schema(extensionId); + char *extensionSchema = get_namespace_name(extensionSchemaId); + + initStringInfo(&buffer); + appendStringInfo(&buffer, "CREATE EXTENSION IF NOT EXISTS %s WITH SCHEMA %s", + quote_identifier(extensionName), + quote_identifier(extensionSchema)); + } + else + { + ereport(NOTICE, (errmsg("foreign-data wrapper \"%s\" does not have an " + "extension defined", foreignDataWrapper->fdwname))); + } + + return (buffer.data); +} + + +/* + * get_extension_schema - given an extension OID, fetch its extnamespace + * + * Returns InvalidOid if no such extension. + */ +static Oid +get_extension_schema(Oid ext_oid) +{ + Oid result; + Relation rel; + SysScanDesc scandesc; + HeapTuple tuple; + ScanKeyData entry[1]; + + rel = heap_open(ExtensionRelationId, AccessShareLock); + + ScanKeyInit(&entry[0], + ObjectIdAttributeNumber, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(ext_oid)); + + scandesc = systable_beginscan(rel, ExtensionOidIndexId, true, + NULL, 1, entry); + + tuple = systable_getnext(scandesc); + + /* We assume that there can be at most one matching tuple */ + if (HeapTupleIsValid(tuple)) + result = ((Form_pg_extension) GETSTRUCT(tuple))->extnamespace; + else + result = InvalidOid; + + systable_endscan(scandesc); + + heap_close(rel, AccessShareLock); + + return result; +} + + +/* + * pg_get_serverdef_string finds the foreign server that corresponds to the + * given foreign tableId, and returns this server's definition. + */ +char * +pg_get_serverdef_string(Oid tableRelationId) +{ + ForeignTable *foreignTable = GetForeignTable(tableRelationId); + ForeignServer *server = GetForeignServer(foreignTable->serverid); + ForeignDataWrapper *foreignDataWrapper = GetForeignDataWrapper(server->fdwid); + + StringInfoData buffer = { NULL, 0, 0, 0 }; + initStringInfo(&buffer); + + appendStringInfo(&buffer, "CREATE SERVER %s", quote_identifier(server->servername)); + if (server->servertype != NULL) + { + appendStringInfo(&buffer, " TYPE %s", + quote_literal_cstr(server->servertype)); + } + if (server->serverversion != NULL) + { + appendStringInfo(&buffer, " VERSION %s", + quote_literal_cstr(server->serverversion)); + } + + appendStringInfo(&buffer, " FOREIGN DATA WRAPPER %s", + quote_identifier(foreignDataWrapper->fdwname)); + + /* append server options, if any */ + AppendOptionListToString(&buffer, server->options); + + return (buffer.data); +} + + +/* + * AppendOptionListToString converts the option list to its textual format, and + * appends this text to the given string buffer. + */ +static void +AppendOptionListToString(StringInfo stringBuffer, List *optionList) +{ + if (optionList != NIL) + { + ListCell *optionCell = NULL; + bool firstOptionPrinted = false; + + appendStringInfo(stringBuffer, " OPTIONS ("); + + foreach(optionCell, optionList) + { + DefElem *option = (DefElem*) lfirst(optionCell); + char *optionName = option->defname; + char *optionValue = defGetString(option); + + if (firstOptionPrinted) + { + appendStringInfo(stringBuffer, ", "); + } + firstOptionPrinted = true; + + appendStringInfo(stringBuffer, "%s ", quote_identifier(optionName)); + appendStringInfo(stringBuffer, "%s", quote_literal_cstr(optionValue)); + } + + appendStringInfo(stringBuffer, ")"); + } +} + + +/* + * pg_get_tableschemadef_string returns the definition of a given table. This + * definition includes table's schema, default column values, not null and check + * constraints. The definition does not include constraints that trigger index + * creations; specifically, unique and primary key constraints are excluded. + */ +char * +pg_get_tableschemadef_string(Oid tableRelationId) +{ + Relation relation = NULL; + char *relationName = NULL; + char relationKind = 0; + TupleDesc tupleDescriptor = NULL; + TupleConstr *tupleConstraints = NULL; + int attributeIndex = 0; + bool firstAttributePrinted = false; + AttrNumber defaultValueIndex = 0; + AttrNumber constraintIndex = 0; + AttrNumber constraintCount = 0; + StringInfoData buffer = { NULL, 0, 0, 0 }; + + /* + * Instead of retrieving values from system catalogs as other functions in + * ruleutils.c do, we follow an unusual approach here: we open the relation, + * and fetch the relation's tuple descriptor. We do this because the tuple + * descriptor already contains information harnessed from pg_attrdef, + * pg_attribute, pg_constraint, and pg_class; and therefore using the + * descriptor saves us from a lot of additional work. + */ + relation = relation_open(tableRelationId, AccessShareLock); + relationName = generate_relation_name(tableRelationId, NIL); + + relationKind = relation->rd_rel->relkind; + if (relationKind != RELKIND_RELATION && relationKind != RELKIND_FOREIGN_TABLE) + { + ereport(ERROR, (errcode(ERRCODE_WRONG_OBJECT_TYPE), + errmsg("%s is not a regular or foreign table", relationName))); + } + + initStringInfo(&buffer); + if (relationKind == RELKIND_RELATION) + { + appendStringInfo(&buffer, "CREATE TABLE %s (", relationName); + } + else + { + appendStringInfo(&buffer, "CREATE FOREIGN TABLE %s (", relationName); + } + + /* + * Iterate over the table's columns. If a particular column is not dropped + * and is not inherited from another table, print the column's name and its + * formatted type. + */ + tupleDescriptor = RelationGetDescr(relation); + tupleConstraints = tupleDescriptor->constr; + + for (attributeIndex = 0; attributeIndex < tupleDescriptor->natts; attributeIndex++) + { + Form_pg_attribute attributeForm = tupleDescriptor->attrs[attributeIndex]; + const char *attributeName = NULL; + const char *attributeTypeName = NULL; + + if (!attributeForm->attisdropped && attributeForm->attinhcount == 0) + { + if (firstAttributePrinted) + { + appendStringInfoString(&buffer, ", "); + } + firstAttributePrinted = true; + + attributeName = NameStr(attributeForm->attname); + appendStringInfo(&buffer, "%s ", quote_identifier(attributeName)); + + attributeTypeName = format_type_with_typemod(attributeForm->atttypid, + attributeForm->atttypmod); + appendStringInfoString(&buffer, attributeTypeName); + + /* if this column has a default value, append the default value */ + if (attributeForm->atthasdef) + { + AttrDefault *defaultValueList = NULL; + AttrDefault *defaultValue = NULL; + + Node *defaultNode = NULL; + List *defaultContext = NULL; + char *defaultString = NULL; + + Assert(tupleConstraints != NULL); + + defaultValueList = tupleConstraints->defval; + Assert(defaultValueList != NULL); + + defaultValue = &(defaultValueList[defaultValueIndex]); + defaultValueIndex++; + + Assert(defaultValue->adnum == (attributeIndex + 1)); + Assert(defaultValueIndex <= tupleConstraints->num_defval); + + /* convert expression to node tree, and prepare deparse context */ + defaultNode = (Node *) stringToNode(defaultValue->adbin); + defaultContext = deparse_context_for(relationName, tableRelationId); + + /* deparse default value string */ + defaultString = deparse_expression(defaultNode, defaultContext, + false, false); + + appendStringInfo(&buffer, " DEFAULT %s", defaultString); + } + + /* if this column has a not null constraint, append the constraint */ + if (attributeForm->attnotnull) + { + appendStringInfoString(&buffer, " NOT NULL"); + } + } + } + + /* + * Now check if the table has any constraints. If it does, set the number of + * check constraints here. Then iterate over all check constraints and print + * them. + */ + if (tupleConstraints != NULL) + { + constraintCount = tupleConstraints->num_check; + } + + for (constraintIndex = 0; constraintIndex < constraintCount; constraintIndex++) + { + ConstrCheck *checkConstraintList = tupleConstraints->check; + ConstrCheck *checkConstraint = &(checkConstraintList[constraintIndex]); + + Node *checkNode = NULL; + List *checkContext = NULL; + char *checkString = NULL; + + /* if an attribute or constraint has been printed, format properly */ + if (firstAttributePrinted || constraintIndex > 0) + { + appendStringInfoString(&buffer, ", "); + } + + appendStringInfo(&buffer, "CONSTRAINT %s CHECK ", + quote_identifier(checkConstraint->ccname)); + + /* convert expression to node tree, and prepare deparse context */ + checkNode = (Node *) stringToNode(checkConstraint->ccbin); + checkContext = deparse_context_for(relationName, tableRelationId); + + /* deparse check constraint string */ + checkString = deparse_expression(checkNode, checkContext, false, false); + + appendStringInfoString(&buffer, checkString); + } + + /* close create table's outer parentheses */ + appendStringInfoString(&buffer, ")"); + + /* + * If the relation is a foreign table, append the server name and options to + * the create table statement. + */ + if (relationKind == RELKIND_FOREIGN_TABLE) + { + ForeignTable *foreignTable = GetForeignTable(tableRelationId); + ForeignServer *foreignServer = GetForeignServer(foreignTable->serverid); + + char *serverName = foreignServer->servername; + appendStringInfo(&buffer, " SERVER %s", quote_identifier(serverName)); + AppendOptionListToString(&buffer, foreignTable->options); + } + + relation_close(relation, AccessShareLock); + + return (buffer.data); +} + + +/* + * pg_get_tablecolumnoptionsdef_string returns column storage type and column + * statistics definitions for given table, _if_ these definitions differ from + * their default values. The function returns null if all columns use default + * values for their storage types and statistics. + */ +char * +pg_get_tablecolumnoptionsdef_string(Oid tableRelationId) +{ + Relation relation = NULL; + char *relationName = NULL; + char relationKind = 0; + TupleDesc tupleDescriptor = NULL; + AttrNumber attributeIndex = 0; + char *columnOptionStatement = NULL; + List *columnOptionList = NIL; + ListCell *columnOptionCell = NULL; + bool firstOptionPrinted = false; + StringInfoData buffer = { NULL, 0, 0, 0 }; + + /* + * Instead of retrieving values from system catalogs, we open the relation, + * and use the relation's tuple descriptor to access attribute information. + * This is primarily to maintain symmetry with pg_get_tableschemadef. + */ + relation = relation_open(tableRelationId, AccessShareLock); + relationName = generate_relation_name(tableRelationId, NIL); + + relationKind = relation->rd_rel->relkind; + if (relationKind != RELKIND_RELATION && relationKind != RELKIND_FOREIGN_TABLE) + { + ereport(ERROR, (errcode(ERRCODE_WRONG_OBJECT_TYPE), + errmsg("%s is not a regular or foreign table", relationName))); + } + + /* + * Iterate over the table's columns. If a particular column is not dropped + * and is not inherited from another table, check if column storage or + * statistics statements need to be printed. + */ + tupleDescriptor = RelationGetDescr(relation); + + for (attributeIndex = 0; attributeIndex < tupleDescriptor->natts; attributeIndex++) + { + Form_pg_attribute attributeForm = tupleDescriptor->attrs[attributeIndex]; + char *attributeName = NameStr(attributeForm->attname); + char defaultStorageType = get_typstorage(attributeForm->atttypid); + + if (!attributeForm->attisdropped && attributeForm->attinhcount == 0) + { + /* + * If the user changed the column's default storage type, create + * alter statement and add statement to a list for later processing. + */ + if (attributeForm->attstorage != defaultStorageType) + { + char *storageName = 0; + StringInfoData statement = { NULL, 0, 0, 0 }; + initStringInfo(&statement); + + switch (attributeForm->attstorage) + { + case 'p': + storageName = "PLAIN"; + break; + case 'e': + storageName = "EXTERNAL"; + break; + case 'm': + storageName = "MAIN"; + break; + case 'x': + storageName = "EXTENDED"; + break; + default: + ereport(ERROR, (errmsg("unrecognized storage type: %c", + attributeForm->attstorage))); + break; + } + + appendStringInfo(&statement, "ALTER COLUMN %s ", + quote_identifier(attributeName)); + appendStringInfo(&statement, "SET STORAGE %s", storageName); + + columnOptionList = lappend(columnOptionList, statement.data); + } + + /* + * If the user changed the column's statistics target, create + * alter statement and add statement to a list for later processing. + */ + if (attributeForm->attstattarget >= 0) + { + StringInfoData statement = { NULL, 0, 0, 0 }; + initStringInfo(&statement); + + appendStringInfo(&statement, "ALTER COLUMN %s ", + quote_identifier(attributeName)); + appendStringInfo(&statement, "SET STATISTICS %d", + attributeForm->attstattarget); + + columnOptionList = lappend(columnOptionList, statement.data); + } + } + } + + /* + * Iterate over column storage and statistics statements that we created, + * and append them to a single alter table statement. + */ + foreach(columnOptionCell, columnOptionList) + { + if (!firstOptionPrinted) + { + initStringInfo(&buffer); + appendStringInfo(&buffer, "ALTER TABLE ONLY %s ", + generate_relation_name(tableRelationId, NIL)); + } + else + { + appendStringInfoString(&buffer, ", "); + } + firstOptionPrinted = true; + + columnOptionStatement = (char *) lfirst(columnOptionCell); + appendStringInfoString(&buffer, columnOptionStatement); + + pfree(columnOptionStatement); + } + + list_free(columnOptionList); + relation_close(relation, AccessShareLock); + + return (buffer.data); +} + + +/* + * pg_get_indexclusterdef_string returns the definition of a cluster statement + * for given index. The function returns null if the table is not clustered on + * given index. + */ +char * +pg_get_indexclusterdef_string(Oid indexRelationId) +{ + HeapTuple indexTuple = NULL; + Form_pg_index indexForm = NULL; + Oid tableRelationId = InvalidOid; + StringInfoData buffer = { NULL, 0, 0, 0 }; + + indexTuple = SearchSysCache(INDEXRELID, ObjectIdGetDatum(indexRelationId), 0, 0, 0); + if (!HeapTupleIsValid(indexTuple)) + { + ereport(ERROR, (errmsg("cache lookup failed for index %u", indexRelationId))); + } + + indexForm = (Form_pg_index) GETSTRUCT(indexTuple); + tableRelationId = indexForm->indrelid; + + /* check if the table is clustered on this index */ + if (indexForm->indisclustered) + { + char *tableName = generate_relation_name(tableRelationId, NIL); + char *indexName = get_rel_name(indexRelationId); /* needs to be quoted */ + + initStringInfo(&buffer); + appendStringInfo(&buffer, "ALTER TABLE %s CLUSTER ON %s", + tableName, quote_identifier(indexName)); + } + + ReleaseSysCache(indexTuple); + + return (buffer.data); +} diff --git a/src/backend/distributed/utils/connection_cache.c b/src/backend/distributed/utils/connection_cache.c new file mode 100644 index 000000000..4281a4a59 --- /dev/null +++ b/src/backend/distributed/utils/connection_cache.c @@ -0,0 +1,334 @@ +/*------------------------------------------------------------------------- + * + * connection_cache.c + * + * This file contains functions to implement a connection hash. + * + * Copyright (c) 2014-2015, Citus Data, Inc. + * + *------------------------------------------------------------------------- + */ + +#include "postgres.h" /* IWYU pragma: keep */ +#include "c.h" +#include "libpq-fe.h" +#include "miscadmin.h" + + +#include +#include + +#include "commands/dbcommands.h" +#include "distributed/connection_cache.h" +#include "lib/stringinfo.h" +#include "mb/pg_wchar.h" +#include "utils/builtins.h" +#include "utils/elog.h" +#include "utils/errcodes.h" +#include "utils/hsearch.h" +#include "utils/memutils.h" +#include "utils/palloc.h" + + +/* + * NodeConnectionHash is the connection hash itself. It begins uninitialized. + * The first call to GetConnection triggers hash creation. + */ +static HTAB *NodeConnectionHash = NULL; + + +/* local function forward declarations */ +static HTAB * CreateNodeConnectionHash(void); +static PGconn * ConnectToNode(char *nodeName, char *nodePort); +static char * ConnectionGetOptionValue(PGconn *connection, char *optionKeyword); + + +/* + * GetConnection returns a PGconn which can be used to execute queries on a + * remote PostgreSQL server. If no suitable connection to the specified node on + * the specified port yet exists, the function establishes a new connection and + * returns that. + * + * Returned connections are guaranteed to be in the CONNECTION_OK state. If the + * requested connection cannot be established, or if it was previously created + * but is now in an unrecoverable bad state, this function returns NULL. + * + * This function throws an error if a hostname over 255 characters is provided. + */ +PGconn * +GetConnection(char *nodeName, int32 nodePort) +{ + PGconn *connection = NULL; + NodeConnectionKey nodeConnectionKey; + NodeConnectionEntry *nodeConnectionEntry = NULL; + bool entryFound = false; + bool needNewConnection = true; + + /* check input */ + if (strnlen(nodeName, MAX_NODE_LENGTH + 1) > MAX_NODE_LENGTH) + { + ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("hostname exceeds the maximum length of %d", + MAX_NODE_LENGTH))); + } + + /* if first call, initialize the connection hash */ + if (NodeConnectionHash == NULL) + { + NodeConnectionHash = CreateNodeConnectionHash(); + } + + memset(&nodeConnectionKey, 0, sizeof(nodeConnectionKey)); + strncpy(nodeConnectionKey.nodeName, nodeName, MAX_NODE_LENGTH); + nodeConnectionKey.nodePort = nodePort; + + nodeConnectionEntry = hash_search(NodeConnectionHash, &nodeConnectionKey, + HASH_FIND, &entryFound); + if (entryFound) + { + connection = nodeConnectionEntry->connection; + if (PQstatus(connection) == CONNECTION_OK) + { + needNewConnection = false; + } + else + { + PurgeConnection(connection); + } + } + + if (needNewConnection) + { + StringInfo nodePortString = makeStringInfo(); + appendStringInfo(nodePortString, "%d", nodePort); + + connection = ConnectToNode(nodeName, nodePortString->data); + if (connection != NULL) + { + nodeConnectionEntry = hash_search(NodeConnectionHash, &nodeConnectionKey, + HASH_ENTER, &entryFound); + nodeConnectionEntry->connection = connection; + } + } + + return connection; +} + + +/* + * PurgeConnection removes the given connection from the connection hash and + * closes it using PQfinish. If our hash does not contain the given connection, + * this method simply prints a warning and exits. + */ +void +PurgeConnection(PGconn *connection) +{ + NodeConnectionKey nodeConnectionKey; + NodeConnectionEntry *nodeConnectionEntry = NULL; + bool entryFound = false; + char *nodeNameString = NULL; + char *nodePortString = NULL; + + nodeNameString = ConnectionGetOptionValue(connection, "host"); + if (nodeNameString == NULL) + { + ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("connection is missing host option"))); + } + + nodePortString = ConnectionGetOptionValue(connection, "port"); + if (nodePortString == NULL) + { + ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("connection is missing port option"))); + } + + memset(&nodeConnectionKey, 0, sizeof(nodeConnectionKey)); + strncpy(nodeConnectionKey.nodeName, nodeNameString, MAX_NODE_LENGTH); + nodeConnectionKey.nodePort = pg_atoi(nodePortString, sizeof(int32), 0); + + pfree(nodeNameString); + pfree(nodePortString); + + nodeConnectionEntry = hash_search(NodeConnectionHash, &nodeConnectionKey, + HASH_REMOVE, &entryFound); + if (entryFound) + { + /* + * It's possible the provided connection matches the host and port for + * an entry in the hash without being precisely the same connection. In + * that case, we will want to close the hash's connection (because the + * entry has already been removed) in addition to the provided one. + */ + if (nodeConnectionEntry->connection != connection) + { + ereport(WARNING, (errmsg("hash entry for \"%s:%d\" contained different " + "connection than that provided by caller", + nodeConnectionKey.nodeName, + nodeConnectionKey.nodePort))); + PQfinish(nodeConnectionEntry->connection); + } + } + else + { + ereport(WARNING, (errcode(ERRCODE_NO_DATA), + errmsg("could not find hash entry for connection to \"%s:%d\"", + nodeConnectionKey.nodeName, + nodeConnectionKey.nodePort))); + } + + PQfinish(connection); +} + + +/* + * ReportRemoteError retrieves various error fields from the a remote result and + * produces an error report at the WARNING level. + */ +void +ReportRemoteError(PGconn *connection, PGresult *result) +{ + char *sqlStateString = PQresultErrorField(result, PG_DIAG_SQLSTATE); + char *remoteMessage = PQresultErrorField(result, PG_DIAG_MESSAGE_PRIMARY); + char *nodeName = ConnectionGetOptionValue(connection, "host"); + char *nodePort = ConnectionGetOptionValue(connection, "port"); + char *errorPrefix = "Connection failed to"; + int sqlState = ERRCODE_CONNECTION_FAILURE; + + if (sqlStateString != NULL) + { + sqlState = MAKE_SQLSTATE(sqlStateString[0], sqlStateString[1], sqlStateString[2], + sqlStateString[3], sqlStateString[4]); + + /* use more specific error prefix for result failures */ + if (sqlState != ERRCODE_CONNECTION_FAILURE) + { + errorPrefix = "Bad result from"; + } + } + + /* + * If the PGresult did not contain a message, the connection may provide a + * suitable top level one. At worst, this is an empty string. + */ + if (remoteMessage == NULL) + { + char *lastNewlineIndex = NULL; + + remoteMessage = PQerrorMessage(connection); + lastNewlineIndex = strrchr(remoteMessage, '\n'); + + /* trim trailing newline, if any */ + if (lastNewlineIndex != NULL) + { + *lastNewlineIndex = '\0'; + } + } + + ereport(WARNING, (errcode(sqlState), + errmsg("%s %s:%s", errorPrefix, nodeName, nodePort), + errdetail("Remote message: %s", remoteMessage))); +} + + +/* + * CreateNodeConnectionHash returns a newly created hash table suitable for + * storing unlimited connections indexed by node name and port. + */ +static HTAB * +CreateNodeConnectionHash(void) +{ + HTAB *nodeConnectionHash = NULL; + HASHCTL info; + int hashFlags = 0; + + memset(&info, 0, sizeof(info)); + info.keysize = sizeof(NodeConnectionKey); + info.entrysize = sizeof(NodeConnectionEntry); + info.hash = tag_hash; + info.hcxt = CacheMemoryContext; + hashFlags = (HASH_ELEM | HASH_FUNCTION | HASH_CONTEXT); + + nodeConnectionHash = hash_create("citusdb connection cache", 32, &info, hashFlags); + + return nodeConnectionHash; +} + + +/* + * ConnectToNode opens a connection to a remote PostgreSQL server. The function + * configures the connection's fallback application name to 'citusdb' and sets + * the remote encoding to match the local one. This function requires that the + * port be specified as a string for easier use with libpq functions. + * + * We attempt to connect up to MAX_CONNECT_ATTEMPT times. After that we give up + * and return NULL. + */ +static PGconn * +ConnectToNode(char *nodeName, char *nodePort) +{ + PGconn *connection = NULL; + const char *clientEncoding = GetDatabaseEncodingName(); + const char *dbname = get_database_name(MyDatabaseId); + int attemptIndex = 0; + + const char *keywordArray[] = { + "host", "port", "fallback_application_name", + "client_encoding", "connect_timeout", "dbname", NULL + }; + const char *valueArray[] = { + nodeName, nodePort, "citusdb", clientEncoding, + CLIENT_CONNECT_TIMEOUT_SECONDS, dbname, NULL + }; + + Assert(sizeof(keywordArray) == sizeof(valueArray)); + + for (attemptIndex = 0; attemptIndex < MAX_CONNECT_ATTEMPTS; attemptIndex++) + { + connection = PQconnectdbParams(keywordArray, valueArray, false); + if (PQstatus(connection) == CONNECTION_OK) + { + break; + } + else + { + /* warn if still erroring on final attempt */ + if (attemptIndex == MAX_CONNECT_ATTEMPTS - 1) + { + ReportRemoteError(connection, NULL); + } + + PQfinish(connection); + connection = NULL; + } + } + + return connection; +} + + +/* + * ConnectionGetOptionValue inspects the provided connection for an option with + * a given keyword and returns a new palloc'd string with that options's value. + * The function returns NULL if the connection has no setting for an option with + * the provided keyword. + */ +static char * +ConnectionGetOptionValue(PGconn *connection, char *optionKeyword) +{ + char *optionValue = NULL; + PQconninfoOption *conninfoOptions = PQconninfo(connection); + PQconninfoOption *option = NULL; + + for (option = conninfoOptions; option->keyword != NULL; option++) + { + if (strncmp(option->keyword, optionKeyword, NAMEDATALEN) == 0) + { + optionValue = pstrdup(option->val); + } + } + + PQconninfoFree(conninfoOptions); + + return optionValue; +} diff --git a/src/backend/distributed/utils/listutils.c b/src/backend/distributed/utils/listutils.c new file mode 100644 index 000000000..6b7ab7a01 --- /dev/null +++ b/src/backend/distributed/utils/listutils.c @@ -0,0 +1,62 @@ +/*------------------------------------------------------------------------- + * + * listutils.c + * + * This file contains functions to perform useful operations on lists. + * + * Copyright (c) 2014-2015, Citus Data, Inc. + * + *------------------------------------------------------------------------- + */ + +#include "postgres.h" +#include "c.h" +#include "port.h" + +#include "distributed/listutils.h" +#include "nodes/pg_list.h" +#include "utils/memutils.h" + + +/* + * SortList takes in a list of void pointers, and sorts these pointers (and the + * values they point to) by applying the given comparison function. The function + * then returns the sorted list of pointers. + * + * Because the input list is a list of pointers, and because qsort expects to + * compare pointers to the list elements, the provided comparison function must + * compare pointers to pointers to elements. In addition, this sort function + * naturally exhibits the same lack of stability exhibited by qsort. See that + * function's man page for more details. + */ +List * +SortList(List *pointerList, int (*comparisonFunction)(const void *, const void *)) +{ + List *sortedList = NIL; + uint32 arrayIndex = 0; + uint32 arraySize = (uint32) list_length(pointerList); + void **array = (void **) palloc0(arraySize * sizeof(void *)); + + ListCell *pointerCell = NULL; + foreach(pointerCell, pointerList) + { + void *pointer = lfirst(pointerCell); + array[arrayIndex] = pointer; + + arrayIndex++; + } + + /* sort the array of pointers using the comparison function */ + qsort(array, arraySize, sizeof(void *), comparisonFunction); + + /* convert the sorted array of pointers back to a sorted list */ + for (arrayIndex = 0; arrayIndex < arraySize; arrayIndex++) + { + void *sortedPointer = array[arrayIndex]; + sortedList = lappend(sortedList, sortedPointer); + } + + pfree(array); + + return sortedList; +} diff --git a/src/backend/distributed/utils/metadata_cache.c b/src/backend/distributed/utils/metadata_cache.c new file mode 100644 index 000000000..868b11313 --- /dev/null +++ b/src/backend/distributed/utils/metadata_cache.c @@ -0,0 +1,929 @@ +/*------------------------------------------------------------------------- + * + * metadata_cache.c + * Distributed table metadata cache + * + * Copyright (c) 2012-2015, Citus Data, Inc. + *------------------------------------------------------------------------- + */ + +#include "postgres.h" + +#include "access/genam.h" +#include "access/heapam.h" +#include "access/htup_details.h" +#include "catalog/indexing.h" +#include "catalog/pg_namespace.h" +#include "catalog/pg_type.h" +#include "commands/extension.h" +#include "commands/trigger.h" +#include "distributed/master_metadata_utility.h" +#include "distributed/metadata_cache.h" +#include "distributed/pg_dist_partition.h" +#include "distributed/pg_dist_shard.h" +#include "parser/parse_func.h" +#include "utils/builtins.h" +#include "utils/catcache.h" +#include "utils/datum.h" +#include "utils/hsearch.h" +#include "utils/inval.h" +#include "utils/fmgroids.h" +#include "utils/lsyscache.h" +#include "utils/rel.h" +#include "utils/relfilenodemap.h" +#include "utils/relmapper.h" +#include "utils/syscache.h" + + +/* Hash table for informations about each partition */ +static HTAB *DistTableCacheHash = NULL; + +/* built first time through in InitializePartitionCache */ +static ScanKeyData DistPartitionScanKey[1]; +static ScanKeyData DistShardScanKey[1]; + + +/* local function forward declarations */ +static DistTableCacheEntry * LookupDistTableCacheEntry(Oid relationId); +static void InitializeDistTableCache(void); +static void ResetDistTableCacheEntry(DistTableCacheEntry *cacheEntry); +static void InvalidateDistRelationCacheCallback(Datum argument, Oid relationId); +static HeapTuple LookupDistPartitionTuple(Oid relationId); +static List * LookupDistShardTuples(Oid relationId); +static void GetPartitionTypeInputInfo(char *partitionKeyString, char partitionMethod, + Oid *intervalTypeId, int32 *intervalTypeMod); +static ShardInterval * TupleToShardInterval(HeapTuple heapTuple, + TupleDesc tupleDescriptor, Oid intervalTypeId, + int32 intervalTypeMod); +static void CachedRelationLookup(const char *relationName, Oid *cachedOid); + + +/* exports for SQL callable functions */ +PG_FUNCTION_INFO_V1(master_dist_partition_cache_invalidate); +PG_FUNCTION_INFO_V1(master_dist_shard_cache_invalidate); + + +/* + * IsDistributedTable returns whether relationId is a distributed relation or + * not. + */ +bool +IsDistributedTable(Oid relationId) +{ + DistTableCacheEntry *cacheEntry = NULL; + + /* + * Can't be a distributed relation if the extension hasn't been loaded + * yet. As we can't do lookups in nonexistent tables, directly return + * false. + */ + if (!CitusDBHasBeenLoaded()) + { + return false; + } + + cacheEntry = LookupDistTableCacheEntry(relationId); + + return cacheEntry->isDistributedTable; +} + +/* + * LoadShardInterval reads shard metadata for given shardId from pg_dist_shard, + * and converts min/max values in these metadata to their properly typed datum + * representations. The function then allocates a structure that stores the read + * and converted values, and returns this structure. + */ +ShardInterval * +LoadShardInterval(uint64 shardId) +{ + ShardInterval *shardInterval; + SysScanDesc scanDescriptor = NULL; + ScanKeyData scanKey[1]; + int scanKeyCount = 1; + HeapTuple heapTuple = NULL; + Form_pg_dist_shard shardForm = NULL; + DistTableCacheEntry *partitionEntry; + Oid intervalTypeId = InvalidOid; + int32 intervalTypeMod = -1; + + Relation pgDistShard = heap_open(DistShardRelationId(), AccessShareLock); + TupleDesc tupleDescriptor = RelationGetDescr(pgDistShard); + + ScanKeyInit(&scanKey[0], Anum_pg_dist_shard_shardid, + BTEqualStrategyNumber, F_INT8EQ, Int64GetDatum(shardId)); + + scanDescriptor = systable_beginscan(pgDistShard, + DistShardShardidIndexId(), true, + NULL, scanKeyCount, scanKey); + + heapTuple = systable_getnext(scanDescriptor); + if (!HeapTupleIsValid(heapTuple)) + { + ereport(ERROR, (errmsg("could not find valid entry for shard " + UINT64_FORMAT, shardId))); + } + + shardForm = (Form_pg_dist_shard) GETSTRUCT(heapTuple); + partitionEntry = DistributedTableCacheEntry(shardForm->logicalrelid); + + GetPartitionTypeInputInfo(partitionEntry->partitionKeyString, + partitionEntry->partitionMethod, &intervalTypeId, + &intervalTypeMod); + + shardInterval = TupleToShardInterval(heapTuple, tupleDescriptor, intervalTypeId, + intervalTypeMod); + + systable_endscan(scanDescriptor); + heap_close(pgDistShard, AccessShareLock); + + return shardInterval; +} + +/* + * DistributedTableCacheEntry looks up a pg_dist_partition entry for a + * relation. + * + * Errors out if no relation matching the criteria could be found. + */ +DistTableCacheEntry * +DistributedTableCacheEntry(Oid distributedRelationId) +{ + DistTableCacheEntry *cacheEntry = NULL; + + /* + * Can't be a distributed relation if the extension hasn't been loaded + * yet. As we can't do lookups in nonexistent tables, directly return NULL + * here. + */ + if (!CitusDBHasBeenLoaded()) + { + return NULL; + } + + cacheEntry = LookupDistTableCacheEntry(distributedRelationId); + + if (cacheEntry->isDistributedTable) + { + return cacheEntry; + } + else + { + ereport(ERROR, (errmsg("relation %u is not distributed", + distributedRelationId))); + } +} + + +/* + * LookupDistTableCacheEntry returns the distributed table metadata for the + * passed relationId. For efficiency it caches lookups. + */ +static DistTableCacheEntry * +LookupDistTableCacheEntry(Oid relationId) +{ + DistTableCacheEntry *cacheEntry = NULL; + bool foundInCache = false; + HeapTuple distPartitionTuple = NULL; + char *partitionKeyString = NULL; + char partitionMethod = 0; + List *distShardTupleList = NIL; + int shardIntervalArrayLength = 0; + ShardInterval *shardIntervalArray = NULL; + void *hashKey = (void *) &relationId; + + if (DistTableCacheHash == NULL) + { + InitializeDistTableCache(); + } + + cacheEntry = hash_search(DistTableCacheHash, hashKey, HASH_FIND, &foundInCache); + + /* return valid matches */ + if ((cacheEntry != NULL) && (cacheEntry->isValid)) + { + return cacheEntry; + } + + /* free the content of old, invalid, entries */ + if (cacheEntry != NULL) + { + ResetDistTableCacheEntry(cacheEntry); + } + + distPartitionTuple = LookupDistPartitionTuple(relationId); + if (distPartitionTuple != NULL) + { + Form_pg_dist_partition partitionForm = + (Form_pg_dist_partition) GETSTRUCT(distPartitionTuple); + Datum partitionKeyDatum = PointerGetDatum(&partitionForm->partkey); + + MemoryContext oldContext = MemoryContextSwitchTo(CacheMemoryContext); + + partitionKeyString = TextDatumGetCString(partitionKeyDatum); + partitionMethod = partitionForm->partmethod; + + MemoryContextSwitchTo(oldContext); + + heap_freetuple(distPartitionTuple); + } + + distShardTupleList = LookupDistShardTuples(relationId); + shardIntervalArrayLength = list_length(distShardTupleList); + if (shardIntervalArrayLength > 0) + { + Relation distShardRelation = heap_open(DistShardRelationId(), AccessShareLock); + TupleDesc distShardTupleDesc = RelationGetDescr(distShardRelation); + ListCell *distShardTupleCell = NULL; + int arrayIndex = 0; + Oid intervalTypeId = InvalidOid; + int32 intervalTypeMod = -1; + + GetPartitionTypeInputInfo(partitionKeyString, partitionMethod, &intervalTypeId, + &intervalTypeMod); + + shardIntervalArray = MemoryContextAllocZero(CacheMemoryContext, + shardIntervalArrayLength * + sizeof(ShardInterval)); + + foreach(distShardTupleCell, distShardTupleList) + { + HeapTuple shardTuple = lfirst(distShardTupleCell); + ShardInterval *shardInterval = TupleToShardInterval(shardTuple, + distShardTupleDesc, + intervalTypeId, + intervalTypeMod); + MemoryContext oldContext = MemoryContextSwitchTo(CacheMemoryContext); + + CopyShardInterval(shardInterval, &shardIntervalArray[arrayIndex]); + + MemoryContextSwitchTo(oldContext); + + heap_freetuple(shardTuple); + + arrayIndex++; + } + + heap_close(distShardRelation, AccessShareLock); + } + + cacheEntry = hash_search(DistTableCacheHash, hashKey, HASH_ENTER, NULL); + + /* zero out entry, but not the key part */ + memset(((char *) cacheEntry) + sizeof(Oid), 0, + sizeof(DistTableCacheEntry) - sizeof(Oid)); + + if (distPartitionTuple == NULL) + { + cacheEntry->isValid = true; + cacheEntry->isDistributedTable = false; + } + else + { + cacheEntry->isValid = true; + cacheEntry->isDistributedTable = true; + cacheEntry->partitionKeyString = partitionKeyString; + cacheEntry->partitionMethod = partitionMethod; + cacheEntry->shardIntervalArrayLength = shardIntervalArrayLength; + cacheEntry->shardIntervalArray = shardIntervalArray; + } + + return cacheEntry; +} + + +/* + * CitusDBHasBeenLoaded returns true if the citusdb extension has been created + * in the current database and the extension script has been executed. Otherwise, + * it returns false. The result is cached as this is called very frequently. + * + * NB: The way this is cached means the result will be wrong after the + * extension is dropped. A reconnect fixes that though, so that seems + * acceptable. + */ +bool +CitusDBHasBeenLoaded(void) +{ + static bool extensionLoaded = false; + + /* recheck presence until citusdb has been loaded */ + if (!extensionLoaded) + { + bool extensionPresent = false; + bool extensionScriptExecuted = true; + + Oid extensionOid = get_extension_oid("citusdb", true); + if (extensionOid != InvalidOid) + { + extensionPresent = true; + } + + if (extensionPresent) + { + /* check if CitusDB extension objects are still being created */ + if (creating_extension && CurrentExtensionObject == extensionOid) + { + extensionScriptExecuted = false; + } + } + + extensionLoaded = extensionPresent && extensionScriptExecuted; + } + + return extensionLoaded; +} + + +/* return oid of pg_dist_shard relation */ +Oid +DistShardRelationId(void) +{ + static Oid cachedOid = InvalidOid; + + CachedRelationLookup("pg_dist_shard", &cachedOid); + + return cachedOid; +} + + +/* return oid of pg_dist_shard_placement relation */ +Oid +DistShardPlacementRelationId(void) +{ + static Oid cachedOid = InvalidOid; + + CachedRelationLookup("pg_dist_shard_placement", &cachedOid); + + return cachedOid; +} + + +/* return oid of pg_dist_partition relation */ +Oid +DistPartitionRelationId(void) +{ + static Oid cachedOid = InvalidOid; + + CachedRelationLookup("pg_dist_partition", &cachedOid); + + return cachedOid; +} + + +/* return oid of pg_dist_partition_logical_relid_index index */ +Oid +DistPartitionLogicalRelidIndexId(void) +{ + static Oid cachedOid = InvalidOid; + + CachedRelationLookup("pg_dist_partition_logical_relid_index", &cachedOid); + + return cachedOid; +} + + +/* return oid of pg_dist_shard_logical_relid_index index */ +Oid +DistShardLogicalRelidIndexId(void) +{ + static Oid cachedOid = InvalidOid; + + CachedRelationLookup("pg_dist_shard_logical_relid_index", &cachedOid); + + return cachedOid; +} + + +/* return oid of pg_dist_shard_shardid_index index */ +Oid +DistShardShardidIndexId(void) +{ + static Oid cachedOid = InvalidOid; + + CachedRelationLookup("pg_dist_shard_shardid_index", &cachedOid); + + return cachedOid; +} + + +/* return oid of pg_dist_shard_placement_shardid_index */ +Oid +DistShardPlacementShardidIndexId(void) +{ + static Oid cachedOid = InvalidOid; + + CachedRelationLookup("pg_dist_shard_placement_shardid_index", &cachedOid); + + return cachedOid; +} + + +/* return oid of the citus_extradata_container(internal) function */ +Oid +CitusExtraDataContainerFuncId(void) +{ + static Oid cachedOid = 0; + List *nameList = NIL; + Oid paramOids[1] = { INTERNALOID }; + + if (cachedOid == InvalidOid) + { + nameList = list_make2(makeString("pg_catalog"), + makeString("citusdb_extradata_container")); + cachedOid = LookupFuncName(nameList, 1, paramOids, false); + } + + return cachedOid; +} + + +/* + * master_dist_partition_cache_invalidate is a trigger function that performs + * relcache invalidations when the contents of pg_dist_partition are changed + * on the SQL level. + */ +Datum +master_dist_partition_cache_invalidate(PG_FUNCTION_ARGS) +{ + TriggerData *triggerData = (TriggerData *) fcinfo->context; + HeapTuple newTuple = NULL; + HeapTuple oldTuple = NULL; + Oid oldLogicalRelationId = InvalidOid; + Oid newLogicalRelationId = InvalidOid; + + if (!CALLED_AS_TRIGGER(fcinfo)) + { + ereport(ERROR, (errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED), + errmsg("must be called as trigger"))); + } + + newTuple = triggerData->tg_newtuple; + oldTuple = triggerData->tg_trigtuple; + + /* collect logicalrelid for OLD and NEW tuple */ + if (oldTuple != NULL) + { + Form_pg_dist_partition distPart = (Form_pg_dist_partition) GETSTRUCT(oldTuple); + + oldLogicalRelationId = distPart->logicalrelid; + } + + if (newTuple != NULL) + { + Form_pg_dist_partition distPart = (Form_pg_dist_partition) GETSTRUCT(newTuple); + + newLogicalRelationId = distPart->logicalrelid; + } + + /* + * Invalidate relcache for the relevant relation(s). In theory + * logicalrelid should never change, but it doesn't hurt to be + * paranoid. We ignore the case that there's no corresponding pg_class + * entry - that happens if the pg_dist_partition tuple is deleted after + * the relation has been dropped. + */ + if (oldLogicalRelationId != InvalidOid && + oldLogicalRelationId != newLogicalRelationId) + { + HeapTuple oldClassTuple = + SearchSysCache1(RELOID, ObjectIdGetDatum(oldLogicalRelationId)); + + if (HeapTupleIsValid(oldClassTuple)) + { + CacheInvalidateRelcacheByTuple(oldClassTuple); + ReleaseSysCache(oldClassTuple); + } + } + + if (newLogicalRelationId != InvalidOid) + { + HeapTuple newClassTuple = + SearchSysCache1(RELOID, ObjectIdGetDatum(newLogicalRelationId)); + + if (HeapTupleIsValid(newClassTuple)) + { + CacheInvalidateRelcacheByTuple(newClassTuple); + ReleaseSysCache(newClassTuple); + } + } + + PG_RETURN_DATUM(PointerGetDatum(NULL)); +} + + +/* + * master_dist_shard_cache_invalidate is a trigger function that performs + * relcache invalidations when the contents of pg_dist_shard are changed + * on the SQL level. + */ +Datum +master_dist_shard_cache_invalidate(PG_FUNCTION_ARGS) +{ + TriggerData *triggerData = (TriggerData *) fcinfo->context; + HeapTuple newTuple = NULL; + HeapTuple oldTuple = NULL; + Oid oldLogicalRelationId = InvalidOid; + Oid newLogicalRelationId = InvalidOid; + + if (!CALLED_AS_TRIGGER(fcinfo)) + { + ereport(ERROR, (errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED), + errmsg("must be called as trigger"))); + } + + newTuple = triggerData->tg_newtuple; + oldTuple = triggerData->tg_trigtuple; + + /* collect logicalrelid for OLD and NEW tuple */ + if (oldTuple != NULL) + { + Form_pg_dist_shard distShard = (Form_pg_dist_shard) GETSTRUCT(oldTuple); + + oldLogicalRelationId = distShard->logicalrelid; + } + + if (newTuple != NULL) + { + Form_pg_dist_shard distShard = (Form_pg_dist_shard) GETSTRUCT(newTuple); + + newLogicalRelationId = distShard->logicalrelid; + } + + /* + * Invalidate relcache for the relevant relation(s). In theory + * logicalrelid should never change, but it doesn't hurt to be + * paranoid. We ignore the case that there's no corresponding pg_class + * entry - that happens if the pg_dist_shard tuple is deleted after + * the relation has been dropped. + */ + if (oldLogicalRelationId != InvalidOid && + oldLogicalRelationId != newLogicalRelationId) + { + HeapTuple oldClassTuple = + SearchSysCache1(RELOID, ObjectIdGetDatum(oldLogicalRelationId)); + + if (HeapTupleIsValid(oldClassTuple)) + { + CacheInvalidateRelcacheByTuple(oldClassTuple); + ReleaseSysCache(oldClassTuple); + } + } + + if (newLogicalRelationId != InvalidOid) + { + HeapTuple newClassTuple = + SearchSysCache1(RELOID, ObjectIdGetDatum(newLogicalRelationId)); + + if (HeapTupleIsValid(newClassTuple)) + { + CacheInvalidateRelcacheByTuple(newClassTuple); + ReleaseSysCache(newClassTuple); + } + } + + PG_RETURN_DATUM(PointerGetDatum(NULL)); +} + + +/* initialize the infrastructure for the metadata cache */ +static void +InitializeDistTableCache(void) +{ + HASHCTL info; + + /* make sure we've initialized CacheMemoryContext */ + if (CacheMemoryContext == NULL) + { + CreateCacheMemoryContext(); + } + + /* build initial scan keys, copied for every relation scan */ + memset(&DistPartitionScanKey, 0, sizeof(DistPartitionScanKey)); + + fmgr_info_cxt(F_OIDEQ, + &DistPartitionScanKey[0].sk_func, + CacheMemoryContext); + DistPartitionScanKey[0].sk_strategy = BTEqualStrategyNumber; + DistPartitionScanKey[0].sk_subtype = InvalidOid; + DistPartitionScanKey[0].sk_collation = InvalidOid; + DistPartitionScanKey[0].sk_attno = Anum_pg_dist_partition_logicalrelid; + + memset(&DistShardScanKey, 0, sizeof(DistShardScanKey)); + + fmgr_info_cxt(F_OIDEQ, + &DistShardScanKey[0].sk_func, + CacheMemoryContext); + DistShardScanKey[0].sk_strategy = BTEqualStrategyNumber; + DistShardScanKey[0].sk_subtype = InvalidOid; + DistShardScanKey[0].sk_collation = InvalidOid; + DistShardScanKey[0].sk_attno = Anum_pg_dist_shard_logicalrelid; + + /* initialize the hash table */ + MemSet(&info, 0, sizeof(info)); + info.keysize = sizeof(Oid); + info.entrysize = sizeof(DistTableCacheEntry); + info.hash = tag_hash; + DistTableCacheHash = + hash_create("Distributed Relation Cache", 32, &info, + HASH_ELEM | HASH_FUNCTION); + + /* Watch for invalidation events. */ + CacheRegisterRelcacheCallback(InvalidateDistRelationCacheCallback, + (Datum) 0); +} + + +/* + * ResetDistTableCacheEntry frees any out-of-band memory used by a cache entry, + * but does not free the entry itself. + */ +void +ResetDistTableCacheEntry(DistTableCacheEntry *cacheEntry) +{ + if (cacheEntry->partitionKeyString != NULL) + { + pfree(cacheEntry->partitionKeyString); + cacheEntry->partitionKeyString = NULL; + } + + if (cacheEntry->shardIntervalArrayLength > 0) + { + int i = 0; + + for (i = 0; i < cacheEntry->shardIntervalArrayLength; i++) + { + ShardInterval *shardInterval = &cacheEntry->shardIntervalArray[i]; + bool valueByVal = shardInterval->valueByVal; + + if (!valueByVal) + { + if (shardInterval->minValueExists) + { + pfree(DatumGetPointer(shardInterval->minValue)); + } + + if (shardInterval->maxValueExists) + { + pfree(DatumGetPointer(shardInterval->maxValue)); + } + } + } + + pfree(cacheEntry->shardIntervalArray); + cacheEntry->shardIntervalArray = NULL; + cacheEntry->shardIntervalArrayLength = 0; + } +} + + +/* + * InvalidateDistRelationCacheCallback flushes cache entries when a relation + * is updated (or flushes the entire cache). + */ +static void +InvalidateDistRelationCacheCallback(Datum argument, Oid relationId) +{ + /* invalidate either entire cache or a specific entry */ + if (relationId == InvalidOid) + { + DistTableCacheEntry *cacheEntry = NULL; + HASH_SEQ_STATUS status; + + hash_seq_init(&status, DistTableCacheHash); + + while ((cacheEntry = (DistTableCacheEntry *) hash_seq_search(&status)) != NULL) + { + cacheEntry->isValid = false; + } + } + else + { + void *hashKey = (void *) &relationId; + bool foundInCache = false; + + DistTableCacheEntry *cacheEntry = hash_search(DistTableCacheHash, hashKey, + HASH_FIND, &foundInCache); + if (foundInCache) + { + cacheEntry->isValid = false; + } + } +} + + +/* + * LookupDistPartitionTuple searches pg_dist_partition for relationId's entry + * and returns that or, if no matching entry was found, NULL. + */ +static HeapTuple +LookupDistPartitionTuple(Oid relationId) +{ + Relation pgDistPartition = NULL; + HeapTuple distPartitionTuple = NULL; + HeapTuple currentPartitionTuple = NULL; + SysScanDesc scanDescriptor; + ScanKeyData scanKey[1]; + + pgDistPartition = heap_open(DistPartitionRelationId(), AccessShareLock); + + /* copy scankey to local copy, it will be modified during the scan */ + memcpy(scanKey, DistPartitionScanKey, sizeof(DistPartitionScanKey)); + + /* set scan arguments */ + scanKey[0].sk_argument = ObjectIdGetDatum(relationId); + + scanDescriptor = systable_beginscan(pgDistPartition, + DistPartitionLogicalRelidIndexId(), + true, NULL, 1, scanKey); + + currentPartitionTuple = systable_getnext(scanDescriptor); + if (HeapTupleIsValid(currentPartitionTuple)) + { + Assert(!HeapTupleHasNulls(currentPartitionTuple)); + + distPartitionTuple = heap_copytuple(currentPartitionTuple); + } + + systable_endscan(scanDescriptor); + + heap_close(pgDistPartition, NoLock); + + return distPartitionTuple; +} + + +/* + * LookupDistShardTuples returns a list of all dist_shard tuples for the + * specified relation. + */ +static List * +LookupDistShardTuples(Oid relationId) +{ + Relation pgDistShard = NULL; + List *distShardTupleList = NIL; + HeapTuple currentShardTuple = NULL; + SysScanDesc scanDescriptor; + ScanKeyData scanKey[1]; + + pgDistShard = heap_open(DistShardRelationId(), AccessShareLock); + + /* copy scankey to local copy, it will be modified during the scan */ + memcpy(scanKey, DistShardScanKey, sizeof(DistShardScanKey)); + + /* set scan arguments */ + scanKey[0].sk_argument = ObjectIdGetDatum(relationId); + + scanDescriptor = systable_beginscan(pgDistShard, DistShardLogicalRelidIndexId(), true, + NULL, 1, scanKey); + + currentShardTuple = systable_getnext(scanDescriptor); + while (HeapTupleIsValid(currentShardTuple)) + { + HeapTuple shardTupleCopy = heap_copytuple(currentShardTuple); + distShardTupleList = lappend(distShardTupleList, shardTupleCopy); + + currentShardTuple = systable_getnext(scanDescriptor); + } + + systable_endscan(scanDescriptor); + heap_close(pgDistShard, AccessShareLock); + + return distShardTupleList; +} + + +/* + * GetPartitionTypeInputInfo populates output parameters with the interval type + * identifier and modifier for the specified partition key/method combination. + */ +static void +GetPartitionTypeInputInfo(char *partitionKeyString, char partitionMethod, + Oid *intervalTypeId, int32 *intervalTypeMod) +{ + *intervalTypeId = InvalidOid; + *intervalTypeMod = -1; + + switch (partitionMethod) + { + case DISTRIBUTE_BY_APPEND: + case DISTRIBUTE_BY_RANGE: + { + Node *partitionNode = stringToNode(partitionKeyString); + Var *partitionColumn = (Var *) partitionNode; + Assert(IsA(partitionNode, Var)); + + *intervalTypeId = partitionColumn->vartype; + *intervalTypeMod = partitionColumn->vartypmod; + break; + } + + case DISTRIBUTE_BY_HASH: + { + *intervalTypeId = INT4OID; + break; + } + + default: + { + ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("unsupported table partition type: %c", + partitionMethod))); + } + } +} + + +/* + * TupleToShardInterval transforms the specified dist_shard tuple into a new + * ShardInterval using the provided descriptor and partition type information. + */ +static ShardInterval * +TupleToShardInterval(HeapTuple heapTuple, TupleDesc tupleDescriptor, Oid intervalTypeId, + int32 intervalTypeMod) +{ + ShardInterval *shardInterval = NULL; + bool isNull = false; + bool minValueNull = false; + bool maxValueNull = false; + Oid inputFunctionId = InvalidOid; + Oid typeIoParam = InvalidOid; + Datum relationIdDatum = heap_getattr(heapTuple, Anum_pg_dist_shard_logicalrelid, + tupleDescriptor, &isNull); + Datum shardIdDatum = heap_getattr(heapTuple, Anum_pg_dist_shard_shardid, + tupleDescriptor, &isNull); + Datum storageTypeDatum = heap_getattr(heapTuple, Anum_pg_dist_shard_shardstorage, + tupleDescriptor, &isNull); + + Datum minValueTextDatum = heap_getattr(heapTuple, Anum_pg_dist_shard_shardminvalue, + tupleDescriptor, &minValueNull); + Datum maxValueTextDatum = heap_getattr(heapTuple, Anum_pg_dist_shard_shardmaxvalue, + tupleDescriptor, &maxValueNull); + + Oid relationId = DatumGetObjectId(relationIdDatum); + int64 shardId = DatumGetInt64(shardIdDatum); + char storageType = DatumGetChar(storageTypeDatum); + Datum minValue = 0; + Datum maxValue = 0; + bool minValueExists = false; + bool maxValueExists = false; + int16 intervalTypeLen = 0; + bool intervalByVal = false; + char intervalAlign = '0'; + char intervalDelim = '0'; + + if (!minValueNull && !maxValueNull) + { + char *minValueString = TextDatumGetCString(minValueTextDatum); + char *maxValueString = TextDatumGetCString(maxValueTextDatum); + + /* TODO: move this up the call stack to avoid per-tuple invocation? */ + get_type_io_data(intervalTypeId, IOFunc_input, &intervalTypeLen, &intervalByVal, + &intervalAlign, &intervalDelim, &typeIoParam, &inputFunctionId); + + /* finally convert min/max values to their actual types */ + minValue = OidInputFunctionCall(inputFunctionId, minValueString, + typeIoParam, intervalTypeMod); + maxValue = OidInputFunctionCall(inputFunctionId, maxValueString, + typeIoParam, intervalTypeMod); + + minValueExists = true; + maxValueExists = true; + } + + shardInterval = CitusMakeNode(ShardInterval); + shardInterval->relationId = relationId; + shardInterval->storageType = storageType; + shardInterval->valueTypeId = intervalTypeId; + shardInterval->valueTypeLen = intervalTypeLen; + shardInterval->valueByVal = intervalByVal; + shardInterval->minValueExists = minValueExists; + shardInterval->maxValueExists = maxValueExists; + shardInterval->minValue = minValue; + shardInterval->maxValue = maxValue; + shardInterval->shardId = shardId; + + return shardInterval; +} + + +/* + * CachedRelationLookup performs a cached lookup for the relation + * relationName, with the result cached in *cachedOid. + * + * NB: The way this is cached means the result will be wrong after the + * extension is dropped and reconnect. A reconnect fixes that though, so that + * seems acceptable. + */ +static void +CachedRelationLookup(const char *relationName, Oid *cachedOid) +{ + if (*cachedOid == InvalidOid) + { + *cachedOid = get_relname_relid(relationName, PG_CATALOG_NAMESPACE); + + if (*cachedOid == InvalidOid) + { + ereport(ERROR, (errmsg("cache lookup failed for %s, called to early?", + relationName))); + } + } +} diff --git a/src/backend/distributed/utils/multi_resowner.c b/src/backend/distributed/utils/multi_resowner.c new file mode 100644 index 000000000..80aecf7e5 --- /dev/null +++ b/src/backend/distributed/utils/multi_resowner.c @@ -0,0 +1,148 @@ +/*------------------------------------------------------------------------- + * + * multi_resowner.c + * CitusDB resource owner integration + * + * An extension can't directly add members to ResourceOwnerData. Instead we + * have to use the resource owner callback mechanism. Right now it's + * sufficient to have an array of referenced resources - there bascially are + * never more than a handful of entries, if that. If that changes we should + * probably rather use a hash table using the pointer value of the resource + * owner as key. + * + * Copyright (c) 2012-2015, Citus Data, Inc. + *------------------------------------------------------------------------- + */ + +#include "postgres.h" + +#include "distributed/multi_server_executor.h" +#include "utils/memutils.h" +#include "utils/resowner_private.h" +#include "distributed/multi_resowner.h" + + +typedef struct JobDirectoryEntry { + ResourceOwner owner; + uint64 jobId; +} JobDirectoryEntry; + + +static bool RegisteredResownerCallback = false; +JobDirectoryEntry *RegisteredJobDirectories = NULL; +size_t NumRegisteredJobDirectories = 0; +size_t NumAllocatedJobDirectories = 0; + + +/* + * Resource owner callback - release resources still held by the resource + * owner. + */ +static void +MultiResourceOwnerReleaseCallback(ResourceReleasePhase phase, + bool isCommit, + bool isTopLevel, + void *arg) +{ + int lastJobIndex = NumRegisteredJobDirectories - 1; + int jobIndex = 0; + + if (phase == RESOURCE_RELEASE_AFTER_LOCKS) + { + /* + * Remove all remaining job directories, after locks have been + * released. + */ + for (jobIndex = lastJobIndex; jobIndex >= 0; jobIndex--) + { + JobDirectoryEntry *entry = &RegisteredJobDirectories[jobIndex]; + + if (entry->owner == CurrentResourceOwner) + { + RemoveJobDirectory(entry->jobId); + } + } + } +} + + +/* + * ResourceOwnerEnlargeJobDirectories makes sure that there is space to + * reference at least one more job directory for the resource owner. Note that + * we only expect one job directory per portal, but we still use an array + * here. + * + * This function is separate from the one actually inserting an entry because + * if we run out of memory, it's critical to do so *before* acquiring the + * resource. + */ +void +ResourceOwnerEnlargeJobDirectories(ResourceOwner owner) +{ + int newMax = 0; + + /* ensure callback is registered */ + if (!RegisteredResownerCallback) + { + RegisterResourceReleaseCallback(MultiResourceOwnerReleaseCallback, NULL); + RegisteredResownerCallback = true; + } + + if (RegisteredJobDirectories == NULL) + { + newMax = 16; + RegisteredJobDirectories = (JobDirectoryEntry *) + MemoryContextAlloc(TopMemoryContext, newMax * sizeof(JobDirectoryEntry)); + NumAllocatedJobDirectories = newMax; + } + else if (NumRegisteredJobDirectories + 1 > NumAllocatedJobDirectories) + { + newMax = NumAllocatedJobDirectories * 2; + RegisteredJobDirectories = (JobDirectoryEntry *) + repalloc(RegisteredJobDirectories, newMax * sizeof(JobDirectoryEntry)); + NumAllocatedJobDirectories = newMax; + } +} + + +/* Remembers that a temporary job directory is owned by a resource owner. */ +void +ResourceOwnerRememberJobDirectory(ResourceOwner owner, uint64 jobId) +{ + JobDirectoryEntry *entry = NULL; + + Assert(NumRegisteredJobDirectories + 1 <= NumAllocatedJobDirectories); + entry = &RegisteredJobDirectories[NumRegisteredJobDirectories]; + entry->owner = owner; + entry->jobId = jobId; + NumRegisteredJobDirectories++; +} + + +/* Forgets that a temporary job directory is owned by a resource owner. */ +void +ResourceOwnerForgetJobDirectory(ResourceOwner owner, uint64 jobId) +{ + int lastJobIndex = NumRegisteredJobDirectories - 1; + int jobIndex = 0; + + for (jobIndex = lastJobIndex; jobIndex >= 0; jobIndex--) + { + JobDirectoryEntry *entry = &RegisteredJobDirectories[jobIndex]; + + if (entry->owner == owner && entry->jobId == jobId) + { + /* move all later entries one up */ + while (jobIndex < lastJobIndex) + { + RegisteredJobDirectories[jobIndex] = RegisteredJobDirectories[jobIndex + 1]; + jobIndex++; + } + NumRegisteredJobDirectories = lastJobIndex; + return; + } + } + + elog(ERROR, "jobId " UINT64_FORMAT " is not owned by resource owner %p", + jobId, owner); +} diff --git a/src/backend/distributed/utils/resource_lock.c b/src/backend/distributed/utils/resource_lock.c new file mode 100644 index 000000000..a2552d46b --- /dev/null +++ b/src/backend/distributed/utils/resource_lock.c @@ -0,0 +1,118 @@ +/*------------------------------------------------------------------------- + * + * resource_lock.c + * Locking Infrastructure for CitusDB. + * + * To avoid introducing a new type of locktag - that then could not be + * displayed by core functionality - we reuse advisory locks. If we'd just + * reused them directly we'd run into danger conflicting with user-defined + * advisory locks, but luckily advisory locks only two values for 'field4' in + * the locktag. + * + * Copyright (c) 2012-2015, Citus Data, Inc. + *------------------------------------------------------------------------- + */ + +#include "postgres.h" + +#include "miscadmin.h" + +#include "distributed/resource_lock.h" +#include "storage/lmgr.h" + + +/* + * LockShardDistributionMetadata returns after grabbing a lock for distribution + * metadata related to the specified shard, blocking if required. ExclusiveLock + * and ShareLock modes are supported. Any locks acquired using this method are + * released at transaction end. + */ +void +LockShardDistributionMetadata(int64 shardId, LOCKMODE lockMode) +{ + LOCKTAG tag; + const bool sessionLock = false; + const bool dontWait = false; + + SET_LOCKTAG_SHARD_METADATA_RESOURCE(tag, MyDatabaseId, shardId); + + (void) LockAcquire(&tag, lockMode, sessionLock, dontWait); +} + + +/* + * LockRelationDistributionMetadata returns after getting a the lock used for a + * relation's distribution metadata, blocking if required. Only ExclusiveLock + * and ShareLock modes are supported. Any locks acquired using this method are + * released at transaction end. + */ +void +LockRelationDistributionMetadata(Oid relationId, LOCKMODE lockMode) +{ + Assert(lockMode == ExclusiveLock || lockMode == ShareLock); + + (void) LockRelationOid(relationId, lockMode); +} + + +/* + * LockShardResource acquires a lock needed to modify data on a remote shard. + * This task may be assigned to multiple backends at the same time, so the lock + * manages any concurrency issues associated with shard file fetching and DML + * command execution. + */ +void +LockShardResource(uint64 shardId, LOCKMODE lockmode) +{ + LOCKTAG tag; + const bool sessionLock = false; + const bool dontWait = false; + + SET_LOCKTAG_SHARD_RESOURCE(tag, MyDatabaseId, shardId); + + (void) LockAcquire(&tag, lockmode, sessionLock, dontWait); +} + + +/* Releases the lock associated with the relay file fetching/DML task. */ +void +UnlockShardResource(uint64 shardId, LOCKMODE lockmode) +{ + LOCKTAG tag; + const bool sessionLock = false; + + SET_LOCKTAG_SHARD_RESOURCE(tag, MyDatabaseId, shardId); + + LockRelease(&tag, lockmode, sessionLock); +} + + +/* + * LockJobResource acquires a lock for creating resources associated with the + * given jobId. This resource is typically a job schema (namespace), and less + * commonly a partition task directory. + */ +void +LockJobResource(uint64 jobId, LOCKMODE lockmode) +{ + LOCKTAG tag; + const bool sessionLock = false; + const bool dontWait = false; + + SET_LOCKTAG_JOB_RESOURCE(tag, MyDatabaseId, jobId); + + (void) LockAcquire(&tag, lockmode, sessionLock, dontWait); +} + + +/* Releases the lock for resources associated with the given job id. */ +void +UnlockJobResource(uint64 jobId, LOCKMODE lockmode) +{ + LOCKTAG tag; + const bool sessionLock = false; + + SET_LOCKTAG_JOB_RESOURCE(tag, MyDatabaseId, jobId); + + LockRelease(&tag, lockmode, sessionLock); +} diff --git a/src/backend/distributed/utils/ruleutils_94.c b/src/backend/distributed/utils/ruleutils_94.c new file mode 100644 index 000000000..7dc0edcb1 --- /dev/null +++ b/src/backend/distributed/utils/ruleutils_94.c @@ -0,0 +1,6675 @@ +/*------------------------------------------------------------------------- + * + * ruleutils_94.c + * Additional, non core exposed, functions to convert stored + * expressions/querytrees back to source text + * + * Portions Copyright (c) 1996-2014, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * + * IDENTIFICATION + * src/backend/distributed/utils/ruleutils_94.c + * + * This needs to be closely in sync with the core code. + *------------------------------------------------------------------------- + */ + +#include "postgres.h" + +#if (PG_VERSION_NUM >= 90400 && PG_VERSION_NUM < 90500) + +#include +#include + +#include "access/htup_details.h" +#include "access/sysattr.h" +#include "catalog/dependency.h" +#include "catalog/indexing.h" +#include "catalog/pg_aggregate.h" +#include "catalog/pg_extension.h" +#include "catalog/pg_foreign_data_wrapper.h" +#include "catalog/pg_operator.h" +#include "catalog/pg_proc.h" +#include "catalog/pg_type.h" +#include "distributed/citus_nodefuncs.h" +#include "distributed/citus_ruleutils.h" +#include "distributed/relay_utility.h" +#include "commands/defrem.h" +#include "commands/extension.h" +#include "foreign/foreign.h" +#include "funcapi.h" +#include "miscadmin.h" +#include "nodes/makefuncs.h" +#include "nodes/nodeFuncs.h" +#include "optimizer/tlist.h" +#include "parser/keywords.h" +#include "parser/parse_agg.h" +#include "parser/parse_func.h" +#include "parser/parse_oper.h" +#include "parser/parser.h" +#include "parser/parsetree.h" +#include "rewrite/rewriteHandler.h" +#include "utils/builtins.h" +#include "utils/fmgroids.h" +#include "utils/lsyscache.h" +#include "utils/rel.h" +#include "utils/syscache.h" +#include "utils/typcache.h" +#include "utils/xml.h" + + +/* ---------- + * Pretty formatting constants + * ---------- + */ + +/* Indent counts */ +#define PRETTYINDENT_STD 8 +#define PRETTYINDENT_JOIN 4 +#define PRETTYINDENT_VAR 4 + +#define PRETTYINDENT_LIMIT 40 /* wrap limit */ + +/* Pretty flags */ +#define PRETTYFLAG_PAREN 1 +#define PRETTYFLAG_INDENT 2 + +/* Default line length for pretty-print wrapping: 0 means wrap always */ +#define WRAP_COLUMN_DEFAULT 0 + +/* macro to test if pretty action needed */ +#define PRETTY_PAREN(context) ((context)->prettyFlags & PRETTYFLAG_PAREN) +#define PRETTY_INDENT(context) ((context)->prettyFlags & PRETTYFLAG_INDENT) + + +/* ---------- + * Local data types + * ---------- + */ + +/* Context info needed for invoking a recursive querytree display routine */ +typedef struct +{ + StringInfo buf; /* output buffer to append to */ + List *namespaces; /* List of deparse_namespace nodes */ + List *windowClause; /* Current query level's WINDOW clause */ + List *windowTList; /* targetlist for resolving WINDOW clause */ + int prettyFlags; /* enabling of pretty-print functions */ + int wrapColumn; /* max line length, or -1 for no limit */ + int indentLevel; /* current indent level for prettyprint */ + bool varprefix; /* TRUE to print prefixes on Vars */ + Oid distrelid; /* the distributed table being modified, if valid */ + int64 shardid; /* a distributed table's shardid, if positive */ +} deparse_context; + +/* + * Each level of query context around a subtree needs a level of Var namespace. + * A Var having varlevelsup=N refers to the N'th item (counting from 0) in + * the current context's namespaces list. + * + * The rangetable is the list of actual RTEs from the query tree, and the + * cte list is the list of actual CTEs. + * + * rtable_names holds the alias name to be used for each RTE (either a C + * string, or NULL for nameless RTEs such as unnamed joins). + * rtable_columns holds the column alias names to be used for each RTE. + * + * In some cases we need to make names of merged JOIN USING columns unique + * across the whole query, not only per-RTE. If so, unique_using is TRUE + * and using_names is a list of C strings representing names already assigned + * to USING columns. + * + * When deparsing plan trees, there is always just a single item in the + * deparse_namespace list (since a plan tree never contains Vars with + * varlevelsup > 0). We store the PlanState node that is the immediate + * parent of the expression to be deparsed, as well as a list of that + * PlanState's ancestors. In addition, we store its outer and inner subplan + * state nodes, as well as their plan nodes' targetlists, and the indextlist + * if the current PlanState is an IndexOnlyScanState. (These fields could + * be derived on-the-fly from the current PlanState, but it seems notationally + * clearer to set them up as separate fields.) + */ +typedef struct +{ + List *rtable; /* List of RangeTblEntry nodes */ + List *rtable_names; /* Parallel list of names for RTEs */ + List *rtable_columns; /* Parallel list of deparse_columns structs */ + List *ctes; /* List of CommonTableExpr nodes */ + /* Workspace for column alias assignment: */ + bool unique_using; /* Are we making USING names globally unique */ + List *using_names; /* List of assigned names for USING columns */ + /* Remaining fields are used only when deparsing a Plan tree: */ + PlanState *planstate; /* immediate parent of current expression */ + List *ancestors; /* ancestors of planstate */ + PlanState *outer_planstate; /* outer subplan state, or NULL if none */ + PlanState *inner_planstate; /* inner subplan state, or NULL if none */ + List *outer_tlist; /* referent for OUTER_VAR Vars */ + List *inner_tlist; /* referent for INNER_VAR Vars */ + List *index_tlist; /* referent for INDEX_VAR Vars */ +} deparse_namespace; + +/* + * Per-relation data about column alias names. + * + * Selecting aliases is unreasonably complicated because of the need to dump + * rules/views whose underlying tables may have had columns added, deleted, or + * renamed since the query was parsed. We must nonetheless print the rule/view + * in a form that can be reloaded and will produce the same results as before. + * + * For each RTE used in the query, we must assign column aliases that are + * unique within that RTE. SQL does not require this of the original query, + * but due to factors such as *-expansion we need to be able to uniquely + * reference every column in a decompiled query. As long as we qualify all + * column references, per-RTE uniqueness is sufficient for that. + * + * However, we can't ensure per-column name uniqueness for unnamed join RTEs, + * since they just inherit column names from their input RTEs, and we can't + * rename the columns at the join level. Most of the time this isn't an issue + * because we don't need to reference the join's output columns as such; we + * can reference the input columns instead. That approach can fail for merged + * JOIN USING columns, however, so when we have one of those in an unnamed + * join, we have to make that column's alias globally unique across the whole + * query to ensure it can be referenced unambiguously. + * + * Another problem is that a JOIN USING clause requires the columns to be + * merged to have the same aliases in both input RTEs, and that no other + * columns in those RTEs or their children conflict with the USING names. + * To handle that, we do USING-column alias assignment in a recursive + * traversal of the query's jointree. When descending through a JOIN with + * USING, we preassign the USING column names to the child columns, overriding + * other rules for column alias assignment. We also mark each RTE with a list + * of all USING column names selected for joins containing that RTE, so that + * when we assign other columns' aliases later, we can avoid conflicts. + * + * Another problem is that if a JOIN's input tables have had columns added or + * deleted since the query was parsed, we must generate a column alias list + * for the join that matches the current set of input columns --- otherwise, a + * change in the number of columns in the left input would throw off matching + * of aliases to columns of the right input. Thus, positions in the printable + * column alias list are not necessarily one-for-one with varattnos of the + * JOIN, so we need a separate new_colnames[] array for printing purposes. + */ +typedef struct +{ + /* + * colnames is an array containing column aliases to use for columns that + * existed when the query was parsed. Dropped columns have NULL entries. + * This array can be directly indexed by varattno to get a Var's name. + * + * Non-NULL entries are guaranteed unique within the RTE, *except* when + * this is for an unnamed JOIN RTE. In that case we merely copy up names + * from the two input RTEs. + * + * During the recursive descent in set_using_names(), forcible assignment + * of a child RTE's column name is represented by pre-setting that element + * of the child's colnames array. So at that stage, NULL entries in this + * array just mean that no name has been preassigned, not necessarily that + * the column is dropped. + */ + int num_cols; /* length of colnames[] array */ + char **colnames; /* array of C strings and NULLs */ + + /* + * new_colnames is an array containing column aliases to use for columns + * that would exist if the query was re-parsed against the current + * definitions of its base tables. This is what to print as the column + * alias list for the RTE. This array does not include dropped columns, + * but it will include columns added since original parsing. Indexes in + * it therefore have little to do with current varattno values. As above, + * entries are unique unless this is for an unnamed JOIN RTE. (In such an + * RTE, we never actually print this array, but we must compute it anyway + * for possible use in computing column names of upper joins.) The + * parallel array is_new_col marks which of these columns are new since + * original parsing. Entries with is_new_col false must match the + * non-NULL colnames entries one-for-one. + */ + int num_new_cols; /* length of new_colnames[] array */ + char **new_colnames; /* array of C strings */ + bool *is_new_col; /* array of bool flags */ + + /* This flag tells whether we should actually print a column alias list */ + bool printaliases; + + /* This list has all names used as USING names in joins above this RTE */ + List *parentUsing; /* names assigned to parent merged columns */ + + /* + * If this struct is for a JOIN RTE, we fill these fields during the + * set_using_names() pass to describe its relationship to its child RTEs. + * + * leftattnos and rightattnos are arrays with one entry per existing + * output column of the join (hence, indexable by join varattno). For a + * simple reference to a column of the left child, leftattnos[i] is the + * child RTE's attno and rightattnos[i] is zero; and conversely for a + * column of the right child. But for merged columns produced by JOIN + * USING/NATURAL JOIN, both leftattnos[i] and rightattnos[i] are nonzero. + * Also, if the column has been dropped, both are zero. + * + * If it's a JOIN USING, usingNames holds the alias names selected for the + * merged columns (these might be different from the original USING list, + * if we had to modify names to achieve uniqueness). + */ + int leftrti; /* rangetable index of left child */ + int rightrti; /* rangetable index of right child */ + int *leftattnos; /* left-child varattnos of join cols, or 0 */ + int *rightattnos; /* right-child varattnos of join cols, or 0 */ + List *usingNames; /* names assigned to merged columns */ +} deparse_columns; + +/* This macro is analogous to rt_fetch(), but for deparse_columns structs */ +#define deparse_columns_fetch(rangetable_index, dpns) \ + ((deparse_columns *) list_nth((dpns)->rtable_columns, (rangetable_index)-1)) + +/* ---------- + * Local functions + * + * Most of these functions used to use fixed-size buffers to build their + * results. Now, they take an (already initialized) StringInfo object + * as a parameter, and append their text output to its contents. + * ---------- + */ +static void set_rtable_names(deparse_namespace *dpns, List *parent_namespaces, + Bitmapset *rels_used); +static bool refname_is_unique(char *refname, deparse_namespace *dpns, + List *parent_namespaces); +static void set_deparse_for_query(deparse_namespace *dpns, Query *query, + List *parent_namespaces); +static bool has_dangerous_join_using(deparse_namespace *dpns, Node *jtnode); +static void set_using_names(deparse_namespace *dpns, Node *jtnode, + List *parentUsing); +static void set_relation_column_names(deparse_namespace *dpns, + RangeTblEntry *rte, + deparse_columns *colinfo); +static void set_join_column_names(deparse_namespace *dpns, RangeTblEntry *rte, + deparse_columns *colinfo); +static bool colname_is_unique(char *colname, deparse_namespace *dpns, + deparse_columns *colinfo); +static char *make_colname_unique(char *colname, deparse_namespace *dpns, + deparse_columns *colinfo); +static void expand_colnames_array_to(deparse_columns *colinfo, int n); +static void identify_join_columns(JoinExpr *j, RangeTblEntry *jrte, + deparse_columns *colinfo); +static void flatten_join_using_qual(Node *qual, + List **leftvars, List **rightvars); +static char *get_rtable_name(int rtindex, deparse_context *context); +static void set_deparse_planstate(deparse_namespace *dpns, PlanState *ps); +static void push_child_plan(deparse_namespace *dpns, PlanState *ps, + deparse_namespace *save_dpns); +static void pop_child_plan(deparse_namespace *dpns, + deparse_namespace *save_dpns); +static void push_ancestor_plan(deparse_namespace *dpns, ListCell *ancestor_cell, + deparse_namespace *save_dpns); +static void pop_ancestor_plan(deparse_namespace *dpns, + deparse_namespace *save_dpns); +static void get_query_def(Query *query, StringInfo buf, List *parentnamespace, + TupleDesc resultDesc, + int prettyFlags, int wrapColumn, int startIndent); +static void get_query_def_extended(Query *query, StringInfo buf, + List *parentnamespace, Oid distrelid, int64 shardid, + TupleDesc resultDesc, int prettyFlags, int wrapColumn, + int startIndent); +static void get_values_def(List *values_lists, deparse_context *context); +static void get_with_clause(Query *query, deparse_context *context); +static void get_select_query_def(Query *query, deparse_context *context, + TupleDesc resultDesc); +static void get_insert_query_def(Query *query, deparse_context *context); +static void get_update_query_def(Query *query, deparse_context *context); +static void get_delete_query_def(Query *query, deparse_context *context); +static void get_utility_query_def(Query *query, deparse_context *context); +static void get_basic_select_query(Query *query, deparse_context *context, + TupleDesc resultDesc); +static void get_target_list(List *targetList, deparse_context *context, + TupleDesc resultDesc); +static void get_setop_query(Node *setOp, Query *query, + deparse_context *context, + TupleDesc resultDesc); +static Node *get_rule_sortgroupclause(SortGroupClause *srt, List *tlist, + bool force_colno, + deparse_context *context); +static void get_rule_orderby(List *orderList, List *targetList, + bool force_colno, deparse_context *context); +static void get_rule_windowclause(Query *query, deparse_context *context); +static void get_rule_windowspec(WindowClause *wc, List *targetList, + deparse_context *context); +static char *get_variable(Var *var, int levelsup, bool istoplevel, + deparse_context *context); +static Node *find_param_referent(Param *param, deparse_context *context, + deparse_namespace **dpns_p, ListCell **ancestor_cell_p); +static void get_parameter(Param *param, deparse_context *context); +static const char *get_simple_binary_op_name(OpExpr *expr); +static bool isSimpleNode(Node *node, Node *parentNode, int prettyFlags); +static void appendContextKeyword(deparse_context *context, const char *str, + int indentBefore, int indentAfter, int indentPlus); +static void removeStringInfoSpaces(StringInfo str); +static void get_rule_expr(Node *node, deparse_context *context, + bool showimplicit); +static void get_oper_expr(OpExpr *expr, deparse_context *context); +static void get_func_expr(FuncExpr *expr, deparse_context *context, + bool showimplicit); +static void get_agg_expr(Aggref *aggref, deparse_context *context); +static void get_windowfunc_expr(WindowFunc *wfunc, deparse_context *context); +static void get_coercion_expr(Node *arg, deparse_context *context, + Oid resulttype, int32 resulttypmod, + Node *parentNode); +static void get_const_expr(Const *constval, deparse_context *context, + int showtype); +static void get_const_collation(Const *constval, deparse_context *context); +static void simple_quote_literal(StringInfo buf, const char *val); +static void get_sublink_expr(SubLink *sublink, deparse_context *context); +static void get_from_clause(Query *query, const char *prefix, + deparse_context *context); +static void get_from_clause_item(Node *jtnode, Query *query, + deparse_context *context); +static void get_column_alias_list(deparse_columns *colinfo, + deparse_context *context); +static void get_from_clause_coldeflist(RangeTblFunction *rtfunc, + deparse_columns *colinfo, + deparse_context *context); +static Node *processIndirection(Node *node, deparse_context *context, + bool printit); +static void printSubscripts(ArrayRef *aref, deparse_context *context); +static char *get_relation_name(Oid relid); +static char *generate_relation_or_shard_name(Oid relid, Oid distrelid, + int64 shardid, List *namespaces); +static char *generate_fragment_name(char *schemaName, char *tableName); +static char *generate_function_name(Oid funcid, int nargs, + List *argnames, Oid *argtypes, + bool has_variadic, bool *use_variadic_p); +static char *generate_operator_name(Oid operid, Oid arg1, Oid arg2); + +#define only_marker(rte) ((rte)->inh ? "" : "ONLY ") + + +/* + * pg_get_query_def parses back one query tree, and outputs the resulting query + * string into given buffer. + */ +void +pg_get_query_def(Query *query, StringInfo buffer) +{ + get_query_def(query, buffer, NIL, NULL, 0, WRAP_COLUMN_DEFAULT, 0); +} + + +/* + * set_rtable_names: select RTE aliases to be used in printing a query + * + * We fill in dpns->rtable_names with a list of names that is one-for-one with + * the already-filled dpns->rtable list. Each RTE name is unique among those + * in the new namespace plus any ancestor namespaces listed in + * parent_namespaces. + * + * If rels_used isn't NULL, only RTE indexes listed in it are given aliases. + * + * Note that this function is only concerned with relation names, not column + * names. + */ +static void +set_rtable_names(deparse_namespace *dpns, List *parent_namespaces, + Bitmapset *rels_used) +{ + ListCell *lc; + int rtindex = 1; + + dpns->rtable_names = NIL; + foreach(lc, dpns->rtable) + { + RangeTblEntry *rte = (RangeTblEntry *) lfirst(lc); + char *refname; + + if (rels_used && !bms_is_member(rtindex, rels_used)) + { + /* Ignore unreferenced RTE */ + refname = NULL; + } + else if (rte->alias) + { + /* If RTE has a user-defined alias, prefer that */ + refname = rte->alias->aliasname; + } + else if (rte->rtekind == RTE_RELATION) + { + /* Use the current actual name of the relation */ + refname = get_rel_name(rte->relid); + } + else if (rte->rtekind == RTE_JOIN) + { + /* Unnamed join has no refname */ + refname = NULL; + } + else + { + /* Otherwise use whatever the parser assigned */ + refname = rte->eref->aliasname; + } + + /* + * If the selected name isn't unique, append digits to make it so + */ + if (refname && + !refname_is_unique(refname, dpns, parent_namespaces)) + { + char *modname = (char *) palloc(strlen(refname) + 32); + int i = 0; + + do + { + sprintf(modname, "%s_%d", refname, ++i); + } while (!refname_is_unique(modname, dpns, parent_namespaces)); + refname = modname; + } + + dpns->rtable_names = lappend(dpns->rtable_names, refname); + rtindex++; + } +} + +/* + * refname_is_unique: is refname distinct from all already-chosen RTE names? + */ +static bool +refname_is_unique(char *refname, deparse_namespace *dpns, + List *parent_namespaces) +{ + ListCell *lc; + + foreach(lc, dpns->rtable_names) + { + char *oldname = (char *) lfirst(lc); + + if (oldname && strcmp(oldname, refname) == 0) + return false; + } + foreach(lc, parent_namespaces) + { + deparse_namespace *olddpns = (deparse_namespace *) lfirst(lc); + ListCell *lc2; + + foreach(lc2, olddpns->rtable_names) + { + char *oldname = (char *) lfirst(lc2); + + if (oldname && strcmp(oldname, refname) == 0) + return false; + } + } + return true; +} + +/* + * set_deparse_for_query: set up deparse_namespace for deparsing a Query tree + * + * For convenience, this is defined to initialize the deparse_namespace struct + * from scratch. + */ +static void +set_deparse_for_query(deparse_namespace *dpns, Query *query, + List *parent_namespaces) +{ + ListCell *lc; + ListCell *lc2; + + /* Initialize *dpns and fill rtable/ctes links */ + memset(dpns, 0, sizeof(deparse_namespace)); + dpns->rtable = query->rtable; + dpns->ctes = query->cteList; + + /* Assign a unique relation alias to each RTE */ + set_rtable_names(dpns, parent_namespaces, NULL); + + /* Initialize dpns->rtable_columns to contain zeroed structs */ + dpns->rtable_columns = NIL; + while (list_length(dpns->rtable_columns) < list_length(dpns->rtable)) + dpns->rtable_columns = lappend(dpns->rtable_columns, + palloc0(sizeof(deparse_columns))); + + /* If it's a utility query, it won't have a jointree */ + if (query->jointree) + { + /* Detect whether global uniqueness of USING names is needed */ + dpns->unique_using = + has_dangerous_join_using(dpns, (Node *) query->jointree); + + /* + * Select names for columns merged by USING, via a recursive pass over + * the query jointree. + */ + set_using_names(dpns, (Node *) query->jointree, NIL); + } + + /* + * Now assign remaining column aliases for each RTE. We do this in a + * linear scan of the rtable, so as to process RTEs whether or not they + * are in the jointree (we mustn't miss NEW.*, INSERT target relations, + * etc). JOIN RTEs must be processed after their children, but this is + * okay because they appear later in the rtable list than their children + * (cf Asserts in identify_join_columns()). + */ + forboth(lc, dpns->rtable, lc2, dpns->rtable_columns) + { + RangeTblEntry *rte = (RangeTblEntry *) lfirst(lc); + deparse_columns *colinfo = (deparse_columns *) lfirst(lc2); + + if (rte->rtekind == RTE_JOIN) + set_join_column_names(dpns, rte, colinfo); + else + set_relation_column_names(dpns, rte, colinfo); + } +} + +/* + * has_dangerous_join_using: search jointree for unnamed JOIN USING + * + * Merged columns of a JOIN USING may act differently from either of the input + * columns, either because they are merged with COALESCE (in a FULL JOIN) or + * because an implicit coercion of the underlying input column is required. + * In such a case the column must be referenced as a column of the JOIN not as + * a column of either input. And this is problematic if the join is unnamed + * (alias-less): we cannot qualify the column's name with an RTE name, since + * there is none. (Forcibly assigning an alias to the join is not a solution, + * since that will prevent legal references to tables below the join.) + * To ensure that every column in the query is unambiguously referenceable, + * we must assign such merged columns names that are globally unique across + * the whole query, aliasing other columns out of the way as necessary. + * + * Because the ensuing re-aliasing is fairly damaging to the readability of + * the query, we don't do this unless we have to. So, we must pre-scan + * the join tree to see if we have to, before starting set_using_names(). + */ +static bool +has_dangerous_join_using(deparse_namespace *dpns, Node *jtnode) +{ + if (IsA(jtnode, RangeTblRef)) + { + /* nothing to do here */ + } + else if (IsA(jtnode, FromExpr)) + { + FromExpr *f = (FromExpr *) jtnode; + ListCell *lc; + + foreach(lc, f->fromlist) + { + if (has_dangerous_join_using(dpns, (Node *) lfirst(lc))) + return true; + } + } + else if (IsA(jtnode, JoinExpr)) + { + JoinExpr *j = (JoinExpr *) jtnode; + + /* Is it an unnamed JOIN with USING? */ + if (j->alias == NULL && j->usingClause) + { + /* + * Yes, so check each join alias var to see if any of them are not + * simple references to underlying columns. If so, we have a + * dangerous situation and must pick unique aliases. + */ + RangeTblEntry *jrte = rt_fetch(j->rtindex, dpns->rtable); + ListCell *lc; + + foreach(lc, jrte->joinaliasvars) + { + Var *aliasvar = (Var *) lfirst(lc); + + if (aliasvar != NULL && !IsA(aliasvar, Var)) + return true; + } + } + + /* Nope, but inspect children */ + if (has_dangerous_join_using(dpns, j->larg)) + return true; + if (has_dangerous_join_using(dpns, j->rarg)) + return true; + } + else + elog(ERROR, "unrecognized node type: %d", + (int) nodeTag(jtnode)); + return false; +} + +/* + * set_using_names: select column aliases to be used for merged USING columns + * + * We do this during a recursive descent of the query jointree. + * dpns->unique_using must already be set to determine the global strategy. + * + * Column alias info is saved in the dpns->rtable_columns list, which is + * assumed to be filled with pre-zeroed deparse_columns structs. + * + * parentUsing is a list of all USING aliases assigned in parent joins of + * the current jointree node. (The passed-in list must not be modified.) + */ +static void +set_using_names(deparse_namespace *dpns, Node *jtnode, List *parentUsing) +{ + if (IsA(jtnode, RangeTblRef)) + { + /* nothing to do now */ + } + else if (IsA(jtnode, FromExpr)) + { + FromExpr *f = (FromExpr *) jtnode; + ListCell *lc; + + foreach(lc, f->fromlist) + set_using_names(dpns, (Node *) lfirst(lc), parentUsing); + } + else if (IsA(jtnode, JoinExpr)) + { + JoinExpr *j = (JoinExpr *) jtnode; + RangeTblEntry *rte = rt_fetch(j->rtindex, dpns->rtable); + deparse_columns *colinfo = deparse_columns_fetch(j->rtindex, dpns); + int *leftattnos; + int *rightattnos; + deparse_columns *leftcolinfo; + deparse_columns *rightcolinfo; + int i; + ListCell *lc; + + /* Get info about the shape of the join */ + identify_join_columns(j, rte, colinfo); + leftattnos = colinfo->leftattnos; + rightattnos = colinfo->rightattnos; + + /* Look up the not-yet-filled-in child deparse_columns structs */ + leftcolinfo = deparse_columns_fetch(colinfo->leftrti, dpns); + rightcolinfo = deparse_columns_fetch(colinfo->rightrti, dpns); + + /* + * If this join is unnamed, then we cannot substitute new aliases at + * this level, so any name requirements pushed down to here must be + * pushed down again to the children. + */ + if (rte->alias == NULL) + { + for (i = 0; i < colinfo->num_cols; i++) + { + char *colname = colinfo->colnames[i]; + + if (colname == NULL) + continue; + + /* Push down to left column, unless it's a system column */ + if (leftattnos[i] > 0) + { + expand_colnames_array_to(leftcolinfo, leftattnos[i]); + leftcolinfo->colnames[leftattnos[i] - 1] = colname; + } + + /* Same on the righthand side */ + if (rightattnos[i] > 0) + { + expand_colnames_array_to(rightcolinfo, rightattnos[i]); + rightcolinfo->colnames[rightattnos[i] - 1] = colname; + } + } + } + + /* + * If there's a USING clause, select the USING column names and push + * those names down to the children. We have two strategies: + * + * If dpns->unique_using is TRUE, we force all USING names to be + * unique across the whole query level. In principle we'd only need + * the names of dangerous USING columns to be globally unique, but to + * safely assign all USING names in a single pass, we have to enforce + * the same uniqueness rule for all of them. However, if a USING + * column's name has been pushed down from the parent, we should use + * it as-is rather than making a uniqueness adjustment. This is + * necessary when we're at an unnamed join, and it creates no risk of + * ambiguity. Also, if there's a user-written output alias for a + * merged column, we prefer to use that rather than the input name; + * this simplifies the logic and seems likely to lead to less aliasing + * overall. + * + * If dpns->unique_using is FALSE, we only need USING names to be + * unique within their own join RTE. We still need to honor + * pushed-down names, though. + * + * Though significantly different in results, these two strategies are + * implemented by the same code, with only the difference of whether + * to put assigned names into dpns->using_names. + */ + if (j->usingClause) + { + /* Copy the input parentUsing list so we don't modify it */ + parentUsing = list_copy(parentUsing); + + /* USING names must correspond to the first join output columns */ + expand_colnames_array_to(colinfo, list_length(j->usingClause)); + i = 0; + foreach(lc, j->usingClause) + { + char *colname = strVal(lfirst(lc)); + + /* Assert it's a merged column */ + Assert(leftattnos[i] != 0 && rightattnos[i] != 0); + + /* Adopt passed-down name if any, else select unique name */ + if (colinfo->colnames[i] != NULL) + colname = colinfo->colnames[i]; + else + { + /* Prefer user-written output alias if any */ + if (rte->alias && i < list_length(rte->alias->colnames)) + colname = strVal(list_nth(rte->alias->colnames, i)); + /* Make it appropriately unique */ + colname = make_colname_unique(colname, dpns, colinfo); + if (dpns->unique_using) + dpns->using_names = lappend(dpns->using_names, + colname); + /* Save it as output column name, too */ + colinfo->colnames[i] = colname; + } + + /* Remember selected names for use later */ + colinfo->usingNames = lappend(colinfo->usingNames, colname); + parentUsing = lappend(parentUsing, colname); + + /* Push down to left column, unless it's a system column */ + if (leftattnos[i] > 0) + { + expand_colnames_array_to(leftcolinfo, leftattnos[i]); + leftcolinfo->colnames[leftattnos[i] - 1] = colname; + } + + /* Same on the righthand side */ + if (rightattnos[i] > 0) + { + expand_colnames_array_to(rightcolinfo, rightattnos[i]); + rightcolinfo->colnames[rightattnos[i] - 1] = colname; + } + + i++; + } + } + + /* Mark child deparse_columns structs with correct parentUsing info */ + leftcolinfo->parentUsing = parentUsing; + rightcolinfo->parentUsing = parentUsing; + + /* Now recursively assign USING column names in children */ + set_using_names(dpns, j->larg, parentUsing); + set_using_names(dpns, j->rarg, parentUsing); + } + else + elog(ERROR, "unrecognized node type: %d", + (int) nodeTag(jtnode)); +} + +/* + * set_relation_column_names: select column aliases for a non-join RTE + * + * Column alias info is saved in *colinfo, which is assumed to be pre-zeroed. + * If any colnames entries are already filled in, those override local + * choices. + */ +static void +set_relation_column_names(deparse_namespace *dpns, RangeTblEntry *rte, + deparse_columns *colinfo) +{ + int ncolumns; + char **real_colnames; + bool changed_any; + int noldcolumns; + int i; + int j; + + /* + * Extract the RTE's "real" column names. This is comparable to + * get_rte_attribute_name, except that it's important to disregard dropped + * columns. We put NULL into the array for a dropped column. + */ + if (rte->rtekind == RTE_RELATION) + { + /* Relation --- look to the system catalogs for up-to-date info */ + Relation rel; + TupleDesc tupdesc; + + rel = relation_open(rte->relid, AccessShareLock); + tupdesc = RelationGetDescr(rel); + + ncolumns = tupdesc->natts; + real_colnames = (char **) palloc(ncolumns * sizeof(char *)); + + for (i = 0; i < ncolumns; i++) + { + if (tupdesc->attrs[i]->attisdropped) + real_colnames[i] = NULL; + else + real_colnames[i] = pstrdup(NameStr(tupdesc->attrs[i]->attname)); + } + relation_close(rel, AccessShareLock); + } + else + { + /* Otherwise use the column names from eref */ + ListCell *lc; + + ncolumns = list_length(rte->eref->colnames); + real_colnames = (char **) palloc(ncolumns * sizeof(char *)); + + i = 0; + foreach(lc, rte->eref->colnames) + { + /* + * If the column name shown in eref is an empty string, then it's + * a column that was dropped at the time of parsing the query, so + * treat it as dropped. + */ + char *cname = strVal(lfirst(lc)); + + if (cname[0] == '\0') + cname = NULL; + real_colnames[i] = cname; + i++; + } + } + + /* + * Ensure colinfo->colnames has a slot for each column. (It could be long + * enough already, if we pushed down a name for the last column.) Note: + * it's possible that there are now more columns than there were when the + * query was parsed, ie colnames could be longer than rte->eref->colnames. + * We must assign unique aliases to the new columns too, else there could + * be unresolved conflicts when the view/rule is reloaded. + */ + expand_colnames_array_to(colinfo, ncolumns); + Assert(colinfo->num_cols == ncolumns); + + /* + * Make sufficiently large new_colnames and is_new_col arrays, too. + * + * Note: because we leave colinfo->num_new_cols zero until after the loop, + * colname_is_unique will not consult that array, which is fine because it + * would only be duplicate effort. + */ + colinfo->new_colnames = (char **) palloc(ncolumns * sizeof(char *)); + colinfo->is_new_col = (bool *) palloc(ncolumns * sizeof(bool)); + + /* + * Scan the columns, select a unique alias for each one, and store it in + * colinfo->colnames and colinfo->new_colnames. The former array has NULL + * entries for dropped columns, the latter omits them. Also mark + * new_colnames entries as to whether they are new since parse time; this + * is the case for entries beyond the length of rte->eref->colnames. + */ + noldcolumns = list_length(rte->eref->colnames); + changed_any = false; + j = 0; + for (i = 0; i < ncolumns; i++) + { + char *real_colname = real_colnames[i]; + char *colname = colinfo->colnames[i]; + + /* Skip dropped columns */ + if (real_colname == NULL) + { + Assert(colname == NULL); /* colnames[i] is already NULL */ + continue; + } + + /* If alias already assigned, that's what to use */ + if (colname == NULL) + { + /* If user wrote an alias, prefer that over real column name */ + if (rte->alias && i < list_length(rte->alias->colnames)) + colname = strVal(list_nth(rte->alias->colnames, i)); + else + colname = real_colname; + + /* Unique-ify and insert into colinfo */ + colname = make_colname_unique(colname, dpns, colinfo); + + colinfo->colnames[i] = colname; + } + + /* Put names of non-dropped columns in new_colnames[] too */ + colinfo->new_colnames[j] = colname; + /* And mark them as new or not */ + colinfo->is_new_col[j] = (i >= noldcolumns); + j++; + + /* Remember if any assigned aliases differ from "real" name */ + if (!changed_any && strcmp(colname, real_colname) != 0) + changed_any = true; + } + + /* + * Set correct length for new_colnames[] array. (Note: if columns have + * been added, colinfo->num_cols includes them, which is not really quite + * right but is harmless, since any new columns must be at the end where + * they won't affect varattnos of pre-existing columns.) + */ + colinfo->num_new_cols = j; + + /* + * For a relation RTE, we need only print the alias column names if any + * are different from the underlying "real" names. For a function RTE, + * always emit a complete column alias list; this is to protect against + * possible instability of the default column names (eg, from altering + * parameter names). For other RTE types, print if we changed anything OR + * if there were user-written column aliases (since the latter would be + * part of the underlying "reality"). + */ + if (rte->rtekind == RTE_RELATION) + colinfo->printaliases = changed_any; + else if (rte->rtekind == RTE_FUNCTION) + colinfo->printaliases = true; + else if (rte->alias && rte->alias->colnames != NIL) + colinfo->printaliases = true; + else + colinfo->printaliases = changed_any; +} + +/* + * set_join_column_names: select column aliases for a join RTE + * + * Column alias info is saved in *colinfo, which is assumed to be pre-zeroed. + * If any colnames entries are already filled in, those override local + * choices. Also, names for USING columns were already chosen by + * set_using_names(). We further expect that column alias selection has been + * completed for both input RTEs. + */ +static void +set_join_column_names(deparse_namespace *dpns, RangeTblEntry *rte, + deparse_columns *colinfo) +{ + deparse_columns *leftcolinfo; + deparse_columns *rightcolinfo; + bool changed_any; + int noldcolumns; + int nnewcolumns; + Bitmapset *leftmerged = NULL; + Bitmapset *rightmerged = NULL; + int i; + int j; + int ic; + int jc; + + /* Look up the previously-filled-in child deparse_columns structs */ + leftcolinfo = deparse_columns_fetch(colinfo->leftrti, dpns); + rightcolinfo = deparse_columns_fetch(colinfo->rightrti, dpns); + + /* + * Ensure colinfo->colnames has a slot for each column. (It could be long + * enough already, if we pushed down a name for the last column.) Note: + * it's possible that one or both inputs now have more columns than there + * were when the query was parsed, but we'll deal with that below. We + * only need entries in colnames for pre-existing columns. + */ + noldcolumns = list_length(rte->eref->colnames); + expand_colnames_array_to(colinfo, noldcolumns); + Assert(colinfo->num_cols == noldcolumns); + + /* + * Scan the join output columns, select an alias for each one, and store + * it in colinfo->colnames. If there are USING columns, set_using_names() + * already selected their names, so we can start the loop at the first + * non-merged column. + */ + changed_any = false; + for (i = list_length(colinfo->usingNames); i < noldcolumns; i++) + { + char *colname = colinfo->colnames[i]; + char *real_colname; + + /* Ignore dropped column (only possible for non-merged column) */ + if (colinfo->leftattnos[i] == 0 && colinfo->rightattnos[i] == 0) + { + Assert(colname == NULL); + continue; + } + + /* Get the child column name */ + if (colinfo->leftattnos[i] > 0) + real_colname = leftcolinfo->colnames[colinfo->leftattnos[i] - 1]; + else if (colinfo->rightattnos[i] > 0) + real_colname = rightcolinfo->colnames[colinfo->rightattnos[i] - 1]; + else + { + /* We're joining system columns --- use eref name */ + real_colname = strVal(list_nth(rte->eref->colnames, i)); + } + Assert(real_colname != NULL); + + /* In an unnamed join, just report child column names as-is */ + if (rte->alias == NULL) + { + colinfo->colnames[i] = real_colname; + continue; + } + + /* If alias already assigned, that's what to use */ + if (colname == NULL) + { + /* If user wrote an alias, prefer that over real column name */ + if (rte->alias && i < list_length(rte->alias->colnames)) + colname = strVal(list_nth(rte->alias->colnames, i)); + else + colname = real_colname; + + /* Unique-ify and insert into colinfo */ + colname = make_colname_unique(colname, dpns, colinfo); + + colinfo->colnames[i] = colname; + } + + /* Remember if any assigned aliases differ from "real" name */ + if (!changed_any && strcmp(colname, real_colname) != 0) + changed_any = true; + } + + /* + * Calculate number of columns the join would have if it were re-parsed + * now, and create storage for the new_colnames and is_new_col arrays. + * + * Note: colname_is_unique will be consulting new_colnames[] during the + * loops below, so its not-yet-filled entries must be zeroes. + */ + nnewcolumns = leftcolinfo->num_new_cols + rightcolinfo->num_new_cols - + list_length(colinfo->usingNames); + colinfo->num_new_cols = nnewcolumns; + colinfo->new_colnames = (char **) palloc0(nnewcolumns * sizeof(char *)); + colinfo->is_new_col = (bool *) palloc0(nnewcolumns * sizeof(bool)); + + /* + * Generating the new_colnames array is a bit tricky since any new columns + * added since parse time must be inserted in the right places. This code + * must match the parser, which will order a join's columns as merged + * columns first (in USING-clause order), then non-merged columns from the + * left input (in attnum order), then non-merged columns from the right + * input (ditto). If one of the inputs is itself a join, its columns will + * be ordered according to the same rule, which means newly-added columns + * might not be at the end. We can figure out what's what by consulting + * the leftattnos and rightattnos arrays plus the input is_new_col arrays. + * + * In these loops, i indexes leftattnos/rightattnos (so it's join varattno + * less one), j indexes new_colnames/is_new_col, and ic/jc have similar + * meanings for the current child RTE. + */ + + /* Handle merged columns; they are first and can't be new */ + i = j = 0; + while (i < noldcolumns && + colinfo->leftattnos[i] != 0 && + colinfo->rightattnos[i] != 0) + { + /* column name is already determined and known unique */ + colinfo->new_colnames[j] = colinfo->colnames[i]; + colinfo->is_new_col[j] = false; + + /* build bitmapsets of child attnums of merged columns */ + if (colinfo->leftattnos[i] > 0) + leftmerged = bms_add_member(leftmerged, colinfo->leftattnos[i]); + if (colinfo->rightattnos[i] > 0) + rightmerged = bms_add_member(rightmerged, colinfo->rightattnos[i]); + + i++, j++; + } + + /* Handle non-merged left-child columns */ + ic = 0; + for (jc = 0; jc < leftcolinfo->num_new_cols; jc++) + { + char *child_colname = leftcolinfo->new_colnames[jc]; + + if (!leftcolinfo->is_new_col[jc]) + { + /* Advance ic to next non-dropped old column of left child */ + while (ic < leftcolinfo->num_cols && + leftcolinfo->colnames[ic] == NULL) + ic++; + Assert(ic < leftcolinfo->num_cols); + ic++; + /* If it is a merged column, we already processed it */ + if (bms_is_member(ic, leftmerged)) + continue; + /* Else, advance i to the corresponding existing join column */ + while (i < colinfo->num_cols && + colinfo->colnames[i] == NULL) + i++; + Assert(i < colinfo->num_cols); + Assert(ic == colinfo->leftattnos[i]); + /* Use the already-assigned name of this column */ + colinfo->new_colnames[j] = colinfo->colnames[i]; + i++; + } + else + { + /* + * Unique-ify the new child column name and assign, unless we're + * in an unnamed join, in which case just copy + */ + if (rte->alias != NULL) + { + colinfo->new_colnames[j] = + make_colname_unique(child_colname, dpns, colinfo); + if (!changed_any && + strcmp(colinfo->new_colnames[j], child_colname) != 0) + changed_any = true; + } + else + colinfo->new_colnames[j] = child_colname; + } + + colinfo->is_new_col[j] = leftcolinfo->is_new_col[jc]; + j++; + } + + /* Handle non-merged right-child columns in exactly the same way */ + ic = 0; + for (jc = 0; jc < rightcolinfo->num_new_cols; jc++) + { + char *child_colname = rightcolinfo->new_colnames[jc]; + + if (!rightcolinfo->is_new_col[jc]) + { + /* Advance ic to next non-dropped old column of right child */ + while (ic < rightcolinfo->num_cols && + rightcolinfo->colnames[ic] == NULL) + ic++; + Assert(ic < rightcolinfo->num_cols); + ic++; + /* If it is a merged column, we already processed it */ + if (bms_is_member(ic, rightmerged)) + continue; + /* Else, advance i to the corresponding existing join column */ + while (i < colinfo->num_cols && + colinfo->colnames[i] == NULL) + i++; + Assert(i < colinfo->num_cols); + Assert(ic == colinfo->rightattnos[i]); + /* Use the already-assigned name of this column */ + colinfo->new_colnames[j] = colinfo->colnames[i]; + i++; + } + else + { + /* + * Unique-ify the new child column name and assign, unless we're + * in an unnamed join, in which case just copy + */ + if (rte->alias != NULL) + { + colinfo->new_colnames[j] = + make_colname_unique(child_colname, dpns, colinfo); + if (!changed_any && + strcmp(colinfo->new_colnames[j], child_colname) != 0) + changed_any = true; + } + else + colinfo->new_colnames[j] = child_colname; + } + + colinfo->is_new_col[j] = rightcolinfo->is_new_col[jc]; + j++; + } + + /* Assert we processed the right number of columns */ +#ifdef USE_ASSERT_CHECKING + while (i < colinfo->num_cols && colinfo->colnames[i] == NULL) + i++; + Assert(i == colinfo->num_cols); + Assert(j == nnewcolumns); +#endif + + /* + * For a named join, print column aliases if we changed any from the child + * names. Unnamed joins cannot print aliases. + */ + if (rte->alias != NULL) + colinfo->printaliases = changed_any; + else + colinfo->printaliases = false; +} + +/* + * colname_is_unique: is colname distinct from already-chosen column names? + * + * dpns is query-wide info, colinfo is for the column's RTE + */ +static bool +colname_is_unique(char *colname, deparse_namespace *dpns, + deparse_columns *colinfo) +{ + int i; + ListCell *lc; + + /* Check against already-assigned column aliases within RTE */ + for (i = 0; i < colinfo->num_cols; i++) + { + char *oldname = colinfo->colnames[i]; + + if (oldname && strcmp(oldname, colname) == 0) + return false; + } + + /* + * If we're building a new_colnames array, check that too (this will be + * partially but not completely redundant with the previous checks) + */ + for (i = 0; i < colinfo->num_new_cols; i++) + { + char *oldname = colinfo->new_colnames[i]; + + if (oldname && strcmp(oldname, colname) == 0) + return false; + } + + /* Also check against USING-column names that must be globally unique */ + foreach(lc, dpns->using_names) + { + char *oldname = (char *) lfirst(lc); + + if (strcmp(oldname, colname) == 0) + return false; + } + + /* Also check against names already assigned for parent-join USING cols */ + foreach(lc, colinfo->parentUsing) + { + char *oldname = (char *) lfirst(lc); + + if (strcmp(oldname, colname) == 0) + return false; + } + + return true; +} + +/* + * make_colname_unique: modify colname if necessary to make it unique + * + * dpns is query-wide info, colinfo is for the column's RTE + */ +static char * +make_colname_unique(char *colname, deparse_namespace *dpns, + deparse_columns *colinfo) +{ + /* + * If the selected name isn't unique, append digits to make it so + */ + if (!colname_is_unique(colname, dpns, colinfo)) + { + char *modname = (char *) palloc(strlen(colname) + 32); + int i = 0; + + do + { + sprintf(modname, "%s_%d", colname, ++i); + } while (!colname_is_unique(modname, dpns, colinfo)); + colname = modname; + } + return colname; +} + +/* + * expand_colnames_array_to: make colinfo->colnames at least n items long + * + * Any added array entries are initialized to zero. + */ +static void +expand_colnames_array_to(deparse_columns *colinfo, int n) +{ + if (n > colinfo->num_cols) + { + if (colinfo->colnames == NULL) + colinfo->colnames = (char **) palloc0(n * sizeof(char *)); + else + { + colinfo->colnames = (char **) repalloc(colinfo->colnames, + n * sizeof(char *)); + memset(colinfo->colnames + colinfo->num_cols, 0, + (n - colinfo->num_cols) * sizeof(char *)); + } + colinfo->num_cols = n; + } +} + +/* + * identify_join_columns: figure out where columns of a join come from + * + * Fills the join-specific fields of the colinfo struct, except for + * usingNames which is filled later. + */ +static void +identify_join_columns(JoinExpr *j, RangeTblEntry *jrte, + deparse_columns *colinfo) +{ + int numjoincols; + int i; + ListCell *lc; + + /* Extract left/right child RT indexes */ + if (IsA(j->larg, RangeTblRef)) + colinfo->leftrti = ((RangeTblRef *) j->larg)->rtindex; + else if (IsA(j->larg, JoinExpr)) + colinfo->leftrti = ((JoinExpr *) j->larg)->rtindex; + else + elog(ERROR, "unrecognized node type in jointree: %d", + (int) nodeTag(j->larg)); + if (IsA(j->rarg, RangeTblRef)) + colinfo->rightrti = ((RangeTblRef *) j->rarg)->rtindex; + else if (IsA(j->rarg, JoinExpr)) + colinfo->rightrti = ((JoinExpr *) j->rarg)->rtindex; + else + elog(ERROR, "unrecognized node type in jointree: %d", + (int) nodeTag(j->rarg)); + + /* Assert children will be processed earlier than join in second pass */ + Assert(colinfo->leftrti < j->rtindex); + Assert(colinfo->rightrti < j->rtindex); + + /* Initialize result arrays with zeroes */ + numjoincols = list_length(jrte->joinaliasvars); + Assert(numjoincols == list_length(jrte->eref->colnames)); + colinfo->leftattnos = (int *) palloc0(numjoincols * sizeof(int)); + colinfo->rightattnos = (int *) palloc0(numjoincols * sizeof(int)); + + /* Scan the joinaliasvars list to identify simple column references */ + i = 0; + foreach(lc, jrte->joinaliasvars) + { + Var *aliasvar = (Var *) lfirst(lc); + + /* get rid of any implicit coercion above the Var */ + aliasvar = (Var *) strip_implicit_coercions((Node *) aliasvar); + + if (aliasvar == NULL) + { + /* It's a dropped column; nothing to do here */ + } + else if (IsA(aliasvar, Var)) + { + Assert(aliasvar->varlevelsup == 0); + Assert(aliasvar->varattno != 0); + if (aliasvar->varno == colinfo->leftrti) + colinfo->leftattnos[i] = aliasvar->varattno; + else if (aliasvar->varno == colinfo->rightrti) + colinfo->rightattnos[i] = aliasvar->varattno; + else + elog(ERROR, "unexpected varno %d in JOIN RTE", + aliasvar->varno); + } + else if (IsA(aliasvar, CoalesceExpr)) + { + /* + * It's a merged column in FULL JOIN USING. Ignore it for now and + * let the code below identify the merged columns. + */ + } + else + elog(ERROR, "unrecognized node type in join alias vars: %d", + (int) nodeTag(aliasvar)); + + i++; + } + + /* + * If there's a USING clause, deconstruct the join quals to identify the + * merged columns. This is a tad painful but if we cannot rely on the + * column names, there is no other representation of which columns were + * joined by USING. (Unless the join type is FULL, we can't tell from the + * joinaliasvars list which columns are merged.) Note: we assume that the + * merged columns are the first output column(s) of the join. + */ + if (j->usingClause) + { + List *leftvars = NIL; + List *rightvars = NIL; + ListCell *lc2; + + /* Extract left- and right-side Vars from the qual expression */ + flatten_join_using_qual(j->quals, &leftvars, &rightvars); + Assert(list_length(leftvars) == list_length(j->usingClause)); + Assert(list_length(rightvars) == list_length(j->usingClause)); + + /* Mark the output columns accordingly */ + i = 0; + forboth(lc, leftvars, lc2, rightvars) + { + Var *leftvar = (Var *) lfirst(lc); + Var *rightvar = (Var *) lfirst(lc2); + + Assert(leftvar->varlevelsup == 0); + Assert(leftvar->varattno != 0); + if (leftvar->varno != colinfo->leftrti) + elog(ERROR, "unexpected varno %d in JOIN USING qual", + leftvar->varno); + colinfo->leftattnos[i] = leftvar->varattno; + + Assert(rightvar->varlevelsup == 0); + Assert(rightvar->varattno != 0); + if (rightvar->varno != colinfo->rightrti) + elog(ERROR, "unexpected varno %d in JOIN USING qual", + rightvar->varno); + colinfo->rightattnos[i] = rightvar->varattno; + + i++; + } + } +} + +/* + * flatten_join_using_qual: extract Vars being joined from a JOIN/USING qual + * + * We assume that transformJoinUsingClause won't have produced anything except + * AND nodes, equality operator nodes, and possibly implicit coercions, and + * that the AND node inputs match left-to-right with the original USING list. + * + * Caller must initialize the result lists to NIL. + */ +static void +flatten_join_using_qual(Node *qual, List **leftvars, List **rightvars) +{ + if (IsA(qual, BoolExpr)) + { + /* Handle AND nodes by recursion */ + BoolExpr *b = (BoolExpr *) qual; + ListCell *lc; + + Assert(b->boolop == AND_EXPR); + foreach(lc, b->args) + { + flatten_join_using_qual((Node *) lfirst(lc), + leftvars, rightvars); + } + } + else if (IsA(qual, OpExpr)) + { + /* Otherwise we should have an equality operator */ + OpExpr *op = (OpExpr *) qual; + Var *var; + + if (list_length(op->args) != 2) + elog(ERROR, "unexpected unary operator in JOIN/USING qual"); + /* Arguments should be Vars with perhaps implicit coercions */ + var = (Var *) strip_implicit_coercions((Node *) linitial(op->args)); + if (!IsA(var, Var)) + elog(ERROR, "unexpected node type in JOIN/USING qual: %d", + (int) nodeTag(var)); + *leftvars = lappend(*leftvars, var); + var = (Var *) strip_implicit_coercions((Node *) lsecond(op->args)); + if (!IsA(var, Var)) + elog(ERROR, "unexpected node type in JOIN/USING qual: %d", + (int) nodeTag(var)); + *rightvars = lappend(*rightvars, var); + } + else + { + /* Perhaps we have an implicit coercion to boolean? */ + Node *q = strip_implicit_coercions(qual); + + if (q != qual) + flatten_join_using_qual(q, leftvars, rightvars); + else + elog(ERROR, "unexpected node type in JOIN/USING qual: %d", + (int) nodeTag(qual)); + } +} + +/* + * get_rtable_name: convenience function to get a previously assigned RTE alias + * + * The RTE must belong to the topmost namespace level in "context". + */ +static char * +get_rtable_name(int rtindex, deparse_context *context) +{ + deparse_namespace *dpns = (deparse_namespace *) linitial(context->namespaces); + + Assert(rtindex > 0 && rtindex <= list_length(dpns->rtable_names)); + return (char *) list_nth(dpns->rtable_names, rtindex - 1); +} + +/* + * set_deparse_planstate: set up deparse_namespace to parse subexpressions + * of a given PlanState node + * + * This sets the planstate, outer_planstate, inner_planstate, outer_tlist, + * inner_tlist, and index_tlist fields. Caller is responsible for adjusting + * the ancestors list if necessary. Note that the rtable and ctes fields do + * not need to change when shifting attention to different plan nodes in a + * single plan tree. + */ +static void +set_deparse_planstate(deparse_namespace *dpns, PlanState *ps) +{ + dpns->planstate = ps; + + /* + * We special-case Append and MergeAppend to pretend that the first child + * plan is the OUTER referent; we have to interpret OUTER Vars in their + * tlists according to one of the children, and the first one is the most + * natural choice. Likewise special-case ModifyTable to pretend that the + * first child plan is the OUTER referent; this is to support RETURNING + * lists containing references to non-target relations. + */ + if (IsA(ps, AppendState)) + dpns->outer_planstate = ((AppendState *) ps)->appendplans[0]; + else if (IsA(ps, MergeAppendState)) + dpns->outer_planstate = ((MergeAppendState *) ps)->mergeplans[0]; + else if (IsA(ps, ModifyTableState)) + dpns->outer_planstate = ((ModifyTableState *) ps)->mt_plans[0]; + else + dpns->outer_planstate = outerPlanState(ps); + + if (dpns->outer_planstate) + dpns->outer_tlist = dpns->outer_planstate->plan->targetlist; + else + dpns->outer_tlist = NIL; + + /* + * For a SubqueryScan, pretend the subplan is INNER referent. (We don't + * use OUTER because that could someday conflict with the normal meaning.) + * Likewise, for a CteScan, pretend the subquery's plan is INNER referent. + */ + if (IsA(ps, SubqueryScanState)) + dpns->inner_planstate = ((SubqueryScanState *) ps)->subplan; + else if (IsA(ps, CteScanState)) + dpns->inner_planstate = ((CteScanState *) ps)->cteplanstate; + else + dpns->inner_planstate = innerPlanState(ps); + + if (dpns->inner_planstate) + dpns->inner_tlist = dpns->inner_planstate->plan->targetlist; + else + dpns->inner_tlist = NIL; + + /* index_tlist is set only if it's an IndexOnlyScan */ + if (IsA(ps->plan, IndexOnlyScan)) + dpns->index_tlist = ((IndexOnlyScan *) ps->plan)->indextlist; + else + dpns->index_tlist = NIL; +} + +/* + * push_child_plan: temporarily transfer deparsing attention to a child plan + * + * When expanding an OUTER_VAR or INNER_VAR reference, we must adjust the + * deparse context in case the referenced expression itself uses + * OUTER_VAR/INNER_VAR. We modify the top stack entry in-place to avoid + * affecting levelsup issues (although in a Plan tree there really shouldn't + * be any). + * + * Caller must provide a local deparse_namespace variable to save the + * previous state for pop_child_plan. + */ +static void +push_child_plan(deparse_namespace *dpns, PlanState *ps, + deparse_namespace *save_dpns) +{ + /* Save state for restoration later */ + *save_dpns = *dpns; + + /* Link current plan node into ancestors list */ + dpns->ancestors = lcons(dpns->planstate, dpns->ancestors); + + /* Set attention on selected child */ + set_deparse_planstate(dpns, ps); +} + +/* + * pop_child_plan: undo the effects of push_child_plan + */ +static void +pop_child_plan(deparse_namespace *dpns, deparse_namespace *save_dpns) +{ + List *ancestors; + + /* Get rid of ancestors list cell added by push_child_plan */ + ancestors = list_delete_first(dpns->ancestors); + + /* Restore fields changed by push_child_plan */ + *dpns = *save_dpns; + + /* Make sure dpns->ancestors is right (may be unnecessary) */ + dpns->ancestors = ancestors; +} + +/* + * push_ancestor_plan: temporarily transfer deparsing attention to an + * ancestor plan + * + * When expanding a Param reference, we must adjust the deparse context + * to match the plan node that contains the expression being printed; + * otherwise we'd fail if that expression itself contains a Param or + * OUTER_VAR/INNER_VAR/INDEX_VAR variable. + * + * The target ancestor is conveniently identified by the ListCell holding it + * in dpns->ancestors. + * + * Caller must provide a local deparse_namespace variable to save the + * previous state for pop_ancestor_plan. + */ +static void +push_ancestor_plan(deparse_namespace *dpns, ListCell *ancestor_cell, + deparse_namespace *save_dpns) +{ + PlanState *ps = (PlanState *) lfirst(ancestor_cell); + List *ancestors; + + /* Save state for restoration later */ + *save_dpns = *dpns; + + /* Build a new ancestor list with just this node's ancestors */ + ancestors = NIL; + while ((ancestor_cell = lnext(ancestor_cell)) != NULL) + ancestors = lappend(ancestors, lfirst(ancestor_cell)); + dpns->ancestors = ancestors; + + /* Set attention on selected ancestor */ + set_deparse_planstate(dpns, ps); +} + +/* + * pop_ancestor_plan: undo the effects of push_ancestor_plan + */ +static void +pop_ancestor_plan(deparse_namespace *dpns, deparse_namespace *save_dpns) +{ + /* Free the ancestor list made in push_ancestor_plan */ + list_free(dpns->ancestors); + + /* Restore fields changed by push_ancestor_plan */ + *dpns = *save_dpns; +} + + +/* ---------- + * deparse_shard_query - Parse back a query for execution on a shard + * + * Builds an SQL string to perform the provided query on a specific shard and + * places this string into the provided buffer. + * ---------- + */ +void +deparse_shard_query(Query *query, Oid distrelid, int64 shardid, + StringInfo buffer) +{ + get_query_def_extended(query, buffer, NIL, distrelid, shardid, NULL, 0, + WRAP_COLUMN_DEFAULT, 0); +} + + +/* ---------- + * get_query_def - Parse back one query parsetree + * + * If resultDesc is not NULL, then it is the output tuple descriptor for + * the view represented by a SELECT query. + * ---------- + */ +static void +get_query_def(Query *query, StringInfo buf, List *parentnamespace, + TupleDesc resultDesc, + int prettyFlags, int wrapColumn, int startIndent) +{ + get_query_def_extended(query, buf, parentnamespace, InvalidOid, 0, resultDesc, + prettyFlags, wrapColumn, startIndent); +} + + +/* ---------- + * get_query_def_extended - Parse back one query parsetree, optionally + * with extension using a shard identifier. + * + * If distrelid is valid and shardid is positive, the provided shardid is added + * any time the provided relid is deparsed, so that the query may be executed + * on a placement for the given shard. + * ---------- + */ +static void +get_query_def_extended(Query *query, StringInfo buf, List *parentnamespace, + Oid distrelid, int64 shardid, TupleDesc resultDesc, + int prettyFlags, int wrapColumn, int startIndent) +{ + deparse_context context; + deparse_namespace dpns; + + /* Guard against excessively long or deeply-nested queries */ + CHECK_FOR_INTERRUPTS(); + check_stack_depth(); + + /* + * Before we begin to examine the query, acquire locks on referenced + * relations, and fix up deleted columns in JOIN RTEs. This ensures + * consistent results. Note we assume it's OK to scribble on the passed + * querytree! + * + * We are only deparsing the query (we are not about to execute it), so we + * only need AccessShareLock on the relations it mentions. + */ + AcquireRewriteLocks(query, false, false); + + context.buf = buf; + context.namespaces = lcons(&dpns, list_copy(parentnamespace)); + context.windowClause = NIL; + context.windowTList = NIL; + context.varprefix = (parentnamespace != NIL || + list_length(query->rtable) != 1); + context.prettyFlags = prettyFlags; + context.wrapColumn = wrapColumn; + context.indentLevel = startIndent; + context.distrelid = distrelid; + context.shardid = shardid; + + set_deparse_for_query(&dpns, query, parentnamespace); + + switch (query->commandType) + { + case CMD_SELECT: + get_select_query_def(query, &context, resultDesc); + break; + + case CMD_UPDATE: + get_update_query_def(query, &context); + break; + + case CMD_INSERT: + get_insert_query_def(query, &context); + break; + + case CMD_DELETE: + get_delete_query_def(query, &context); + break; + + case CMD_NOTHING: + appendStringInfoString(buf, "NOTHING"); + break; + + case CMD_UTILITY: + get_utility_query_def(query, &context); + break; + + default: + elog(ERROR, "unrecognized query command type: %d", + query->commandType); + break; + } +} + +/* ---------- + * get_values_def - Parse back a VALUES list + * ---------- + */ +static void +get_values_def(List *values_lists, deparse_context *context) +{ + StringInfo buf = context->buf; + bool first_list = true; + ListCell *vtl; + + appendStringInfoString(buf, "VALUES "); + + foreach(vtl, values_lists) + { + List *sublist = (List *) lfirst(vtl); + bool first_col = true; + ListCell *lc; + + if (first_list) + first_list = false; + else + appendStringInfoString(buf, ", "); + + appendStringInfoChar(buf, '('); + foreach(lc, sublist) + { + Node *col = (Node *) lfirst(lc); + + if (first_col) + first_col = false; + else + appendStringInfoChar(buf, ','); + + /* + * Strip any top-level nodes representing indirection assignments, + * then print the result. + */ + get_rule_expr(processIndirection(col, context, false), + context, false); + } + appendStringInfoChar(buf, ')'); + } +} + +/* ---------- + * get_with_clause - Parse back a WITH clause + * ---------- + */ +static void +get_with_clause(Query *query, deparse_context *context) +{ + StringInfo buf = context->buf; + const char *sep; + ListCell *l; + + if (query->cteList == NIL) + return; + + if (PRETTY_INDENT(context)) + { + context->indentLevel += PRETTYINDENT_STD; + appendStringInfoChar(buf, ' '); + } + + if (query->hasRecursive) + sep = "WITH RECURSIVE "; + else + sep = "WITH "; + foreach(l, query->cteList) + { + CommonTableExpr *cte = (CommonTableExpr *) lfirst(l); + + appendStringInfoString(buf, sep); + appendStringInfoString(buf, quote_identifier(cte->ctename)); + if (cte->aliascolnames) + { + bool first = true; + ListCell *col; + + appendStringInfoChar(buf, '('); + foreach(col, cte->aliascolnames) + { + if (first) + first = false; + else + appendStringInfoString(buf, ", "); + appendStringInfoString(buf, + quote_identifier(strVal(lfirst(col)))); + } + appendStringInfoChar(buf, ')'); + } + appendStringInfoString(buf, " AS ("); + if (PRETTY_INDENT(context)) + appendContextKeyword(context, "", 0, 0, 0); + get_query_def((Query *) cte->ctequery, buf, context->namespaces, NULL, + context->prettyFlags, context->wrapColumn, + context->indentLevel); + if (PRETTY_INDENT(context)) + appendContextKeyword(context, "", 0, 0, 0); + appendStringInfoChar(buf, ')'); + sep = ", "; + } + + if (PRETTY_INDENT(context)) + { + context->indentLevel -= PRETTYINDENT_STD; + appendContextKeyword(context, "", 0, 0, 0); + } + else + appendStringInfoChar(buf, ' '); +} + +/* ---------- + * get_select_query_def - Parse back a SELECT parsetree + * ---------- + */ +static void +get_select_query_def(Query *query, deparse_context *context, + TupleDesc resultDesc) +{ + StringInfo buf = context->buf; + List *save_windowclause; + List *save_windowtlist; + bool force_colno; + ListCell *l; + + /* Insert the WITH clause if given */ + get_with_clause(query, context); + + /* Set up context for possible window functions */ + save_windowclause = context->windowClause; + context->windowClause = query->windowClause; + save_windowtlist = context->windowTList; + context->windowTList = query->targetList; + + /* + * If the Query node has a setOperations tree, then it's the top level of + * a UNION/INTERSECT/EXCEPT query; only the WITH, ORDER BY and LIMIT + * fields are interesting in the top query itself. + */ + if (query->setOperations) + { + get_setop_query(query->setOperations, query, context, resultDesc); + /* ORDER BY clauses must be simple in this case */ + force_colno = true; + } + else + { + get_basic_select_query(query, context, resultDesc); + force_colno = false; + } + + /* Add the ORDER BY clause if given */ + if (query->sortClause != NIL) + { + appendContextKeyword(context, " ORDER BY ", + -PRETTYINDENT_STD, PRETTYINDENT_STD, 1); + get_rule_orderby(query->sortClause, query->targetList, + force_colno, context); + } + + /* Add the LIMIT clause if given */ + if (query->limitOffset != NULL) + { + appendContextKeyword(context, " OFFSET ", + -PRETTYINDENT_STD, PRETTYINDENT_STD, 0); + get_rule_expr(query->limitOffset, context, false); + } + if (query->limitCount != NULL) + { + appendContextKeyword(context, " LIMIT ", + -PRETTYINDENT_STD, PRETTYINDENT_STD, 0); + if (IsA(query->limitCount, Const) && + ((Const *) query->limitCount)->constisnull) + appendStringInfoString(buf, "ALL"); + else + get_rule_expr(query->limitCount, context, false); + } + + /* Add FOR [KEY] UPDATE/SHARE clauses if present */ + if (query->hasForUpdate) + { + foreach(l, query->rowMarks) + { + RowMarkClause *rc = (RowMarkClause *) lfirst(l); + + /* don't print implicit clauses */ + if (rc->pushedDown) + continue; + + switch (rc->strength) + { + case LCS_FORKEYSHARE: + appendContextKeyword(context, " FOR KEY SHARE", + -PRETTYINDENT_STD, PRETTYINDENT_STD, 0); + break; + case LCS_FORSHARE: + appendContextKeyword(context, " FOR SHARE", + -PRETTYINDENT_STD, PRETTYINDENT_STD, 0); + break; + case LCS_FORNOKEYUPDATE: + appendContextKeyword(context, " FOR NO KEY UPDATE", + -PRETTYINDENT_STD, PRETTYINDENT_STD, 0); + break; + case LCS_FORUPDATE: + appendContextKeyword(context, " FOR UPDATE", + -PRETTYINDENT_STD, PRETTYINDENT_STD, 0); + break; + } + + appendStringInfo(buf, " OF %s", + quote_identifier(get_rtable_name(rc->rti, + context))); + if (rc->noWait) + appendStringInfoString(buf, " NOWAIT"); + } + } + + context->windowClause = save_windowclause; + context->windowTList = save_windowtlist; +} + +/* + * Detect whether query looks like SELECT ... FROM VALUES(); + * if so, return the VALUES RTE. Otherwise return NULL. + */ +static RangeTblEntry * +get_simple_values_rte(Query *query) +{ + RangeTblEntry *result = NULL; + ListCell *lc; + + /* + * We want to return TRUE even if the Query also contains OLD or NEW rule + * RTEs. So the idea is to scan the rtable and see if there is only one + * inFromCl RTE that is a VALUES RTE. + */ + foreach(lc, query->rtable) + { + RangeTblEntry *rte = (RangeTblEntry *) lfirst(lc); + + if (rte->rtekind == RTE_VALUES && rte->inFromCl) + { + if (result) + return NULL; /* multiple VALUES (probably not possible) */ + result = rte; + } + else if (rte->rtekind == RTE_RELATION && !rte->inFromCl) + continue; /* ignore rule entries */ + else + return NULL; /* something else -> not simple VALUES */ + } + + /* + * We don't need to check the targetlist in any great detail, because + * parser/analyze.c will never generate a "bare" VALUES RTE --- they only + * appear inside auto-generated sub-queries with very restricted + * structure. However, DefineView might have modified the tlist by + * injecting new column aliases; so compare tlist resnames against the + * RTE's names to detect that. + */ + if (result) + { + ListCell *lcn; + + if (list_length(query->targetList) != list_length(result->eref->colnames)) + return NULL; /* this probably cannot happen */ + forboth(lc, query->targetList, lcn, result->eref->colnames) + { + TargetEntry *tle = (TargetEntry *) lfirst(lc); + char *cname = strVal(lfirst(lcn)); + + if (tle->resjunk) + return NULL; /* this probably cannot happen */ + if (tle->resname == NULL || strcmp(tle->resname, cname) != 0) + return NULL; /* column name has been changed */ + } + } + + return result; +} + +static void +get_basic_select_query(Query *query, deparse_context *context, + TupleDesc resultDesc) +{ + StringInfo buf = context->buf; + RangeTblEntry *values_rte; + char *sep; + ListCell *l; + + if (PRETTY_INDENT(context)) + { + context->indentLevel += PRETTYINDENT_STD; + appendStringInfoChar(buf, ' '); + } + + /* + * If the query looks like SELECT * FROM (VALUES ...), then print just the + * VALUES part. This reverses what transformValuesClause() did at parse + * time. + */ + values_rte = get_simple_values_rte(query); + if (values_rte) + { + get_values_def(values_rte->values_lists, context); + return; + } + + /* + * Build up the query string - first we say SELECT + */ + appendStringInfoString(buf, "SELECT"); + + /* Add the DISTINCT clause if given */ + if (query->distinctClause != NIL) + { + if (query->hasDistinctOn) + { + appendStringInfoString(buf, " DISTINCT ON ("); + sep = ""; + foreach(l, query->distinctClause) + { + SortGroupClause *srt = (SortGroupClause *) lfirst(l); + + appendStringInfoString(buf, sep); + get_rule_sortgroupclause(srt, query->targetList, + false, context); + sep = ", "; + } + appendStringInfoChar(buf, ')'); + } + else + appendStringInfoString(buf, " DISTINCT"); + } + + /* Then we tell what to select (the targetlist) */ + get_target_list(query->targetList, context, resultDesc); + + /* Add the FROM clause if needed */ + get_from_clause(query, " FROM ", context); + + /* Add the WHERE clause if given */ + if (query->jointree->quals != NULL) + { + appendContextKeyword(context, " WHERE ", + -PRETTYINDENT_STD, PRETTYINDENT_STD, 1); + get_rule_expr(query->jointree->quals, context, false); + } + + /* Add the GROUP BY clause if given */ + if (query->groupClause != NULL) + { + appendContextKeyword(context, " GROUP BY ", + -PRETTYINDENT_STD, PRETTYINDENT_STD, 1); + sep = ""; + foreach(l, query->groupClause) + { + SortGroupClause *grp = (SortGroupClause *) lfirst(l); + + appendStringInfoString(buf, sep); + get_rule_sortgroupclause(grp, query->targetList, + false, context); + sep = ", "; + } + } + + /* Add the HAVING clause if given */ + if (query->havingQual != NULL) + { + appendContextKeyword(context, " HAVING ", + -PRETTYINDENT_STD, PRETTYINDENT_STD, 0); + get_rule_expr(query->havingQual, context, false); + } + + /* Add the WINDOW clause if needed */ + if (query->windowClause != NIL) + get_rule_windowclause(query, context); +} + +/* ---------- + * get_target_list - Parse back a SELECT target list + * + * This is also used for RETURNING lists in INSERT/UPDATE/DELETE. + * ---------- + */ +static void +get_target_list(List *targetList, deparse_context *context, + TupleDesc resultDesc) +{ + StringInfo buf = context->buf; + StringInfoData targetbuf; + bool last_was_multiline = false; + char *sep; + int colno; + ListCell *l; + + /* we use targetbuf to hold each TLE's text temporarily */ + initStringInfo(&targetbuf); + + sep = " "; + colno = 0; + foreach(l, targetList) + { + TargetEntry *tle = (TargetEntry *) lfirst(l); + char *colname; + char *attname; + + if (tle->resjunk) + continue; /* ignore junk entries */ + + appendStringInfoString(buf, sep); + sep = ", "; + colno++; + + /* + * Put the new field text into targetbuf so we can decide after we've + * got it whether or not it needs to go on a new line. + */ + resetStringInfo(&targetbuf); + context->buf = &targetbuf; + + /* + * We special-case Var nodes rather than using get_rule_expr. This is + * needed because get_rule_expr will display a whole-row Var as + * "foo.*", which is the preferred notation in most contexts, but at + * the top level of a SELECT list it's not right (the parser will + * expand that notation into multiple columns, yielding behavior + * different from a whole-row Var). We need to call get_variable + * directly so that we can tell it to do the right thing. + */ + if (tle->expr && IsA(tle->expr, Var)) + { + attname = get_variable((Var *) tle->expr, 0, true, context); + } + else + { + get_rule_expr((Node *) tle->expr, context, true); + /* We'll show the AS name unless it's this: */ + attname = "?column?"; + } + + /* + * Figure out what the result column should be called. In the context + * of a view, use the view's tuple descriptor (so as to pick up the + * effects of any column RENAME that's been done on the view). + * Otherwise, just use what we can find in the TLE. + */ + if (resultDesc && colno <= resultDesc->natts) + colname = NameStr(resultDesc->attrs[colno - 1]->attname); + else + colname = tle->resname; + + /* Show AS unless the column's name is correct as-is */ + if (colname) /* resname could be NULL */ + { + if (attname == NULL || strcmp(attname, colname) != 0) + appendStringInfo(&targetbuf, " AS %s", quote_identifier(colname)); + } + + /* Restore context's output buffer */ + context->buf = buf; + + /* Consider line-wrapping if enabled */ + if (PRETTY_INDENT(context) && context->wrapColumn >= 0) + { + int leading_nl_pos; + + /* Does the new field start with a new line? */ + if (targetbuf.len > 0 && targetbuf.data[0] == '\n') + leading_nl_pos = 0; + else + leading_nl_pos = -1; + + /* If so, we shouldn't add anything */ + if (leading_nl_pos >= 0) + { + /* instead, remove any trailing spaces currently in buf */ + removeStringInfoSpaces(buf); + } + else + { + char *trailing_nl; + + /* Locate the start of the current line in the output buffer */ + trailing_nl = strrchr(buf->data, '\n'); + if (trailing_nl == NULL) + trailing_nl = buf->data; + else + trailing_nl++; + + /* + * Add a newline, plus some indentation, if the new field is + * not the first and either the new field would cause an + * overflow or the last field used more than one line. + */ + if (colno > 1 && + ((strlen(trailing_nl) + targetbuf.len > context->wrapColumn) || + last_was_multiline)) + appendContextKeyword(context, "", -PRETTYINDENT_STD, + PRETTYINDENT_STD, PRETTYINDENT_VAR); + } + + /* Remember this field's multiline status for next iteration */ + last_was_multiline = + (strchr(targetbuf.data + leading_nl_pos + 1, '\n') != NULL); + } + + /* Add the new field */ + appendStringInfoString(buf, targetbuf.data); + } + + /* clean up */ + pfree(targetbuf.data); +} + +static void +get_setop_query(Node *setOp, Query *query, deparse_context *context, + TupleDesc resultDesc) +{ + StringInfo buf = context->buf; + bool need_paren; + + /* Guard against excessively long or deeply-nested queries */ + CHECK_FOR_INTERRUPTS(); + check_stack_depth(); + + if (IsA(setOp, RangeTblRef)) + { + RangeTblRef *rtr = (RangeTblRef *) setOp; + RangeTblEntry *rte = rt_fetch(rtr->rtindex, query->rtable); + Query *subquery = rte->subquery; + + Assert(subquery != NULL); + Assert(subquery->setOperations == NULL); + /* Need parens if WITH, ORDER BY, FOR UPDATE, or LIMIT; see gram.y */ + need_paren = (subquery->cteList || + subquery->sortClause || + subquery->rowMarks || + subquery->limitOffset || + subquery->limitCount); + if (need_paren) + appendStringInfoChar(buf, '('); + get_query_def(subquery, buf, context->namespaces, resultDesc, + context->prettyFlags, context->wrapColumn, + context->indentLevel); + if (need_paren) + appendStringInfoChar(buf, ')'); + } + else if (IsA(setOp, SetOperationStmt)) + { + SetOperationStmt *op = (SetOperationStmt *) setOp; + int subindent; + + /* + * We force parens when nesting two SetOperationStmts, except when the + * lefthand input is another setop of the same kind. Syntactically, + * we could omit parens in rather more cases, but it seems best to use + * parens to flag cases where the setop operator changes. If we use + * parens, we also increase the indentation level for the child query. + * + * There are some cases in which parens are needed around a leaf query + * too, but those are more easily handled at the next level down (see + * code above). + */ + if (IsA(op->larg, SetOperationStmt)) + { + SetOperationStmt *lop = (SetOperationStmt *) op->larg; + + if (op->op == lop->op && op->all == lop->all) + need_paren = false; + else + need_paren = true; + } + else + need_paren = false; + + if (need_paren) + { + appendStringInfoChar(buf, '('); + subindent = PRETTYINDENT_STD; + appendContextKeyword(context, "", subindent, 0, 0); + } + else + subindent = 0; + + get_setop_query(op->larg, query, context, resultDesc); + + if (need_paren) + appendContextKeyword(context, ") ", -subindent, 0, 0); + else if (PRETTY_INDENT(context)) + appendContextKeyword(context, "", -subindent, 0, 0); + else + appendStringInfoChar(buf, ' '); + + switch (op->op) + { + case SETOP_UNION: + appendStringInfoString(buf, "UNION "); + break; + case SETOP_INTERSECT: + appendStringInfoString(buf, "INTERSECT "); + break; + case SETOP_EXCEPT: + appendStringInfoString(buf, "EXCEPT "); + break; + default: + elog(ERROR, "unrecognized set op: %d", + (int) op->op); + } + if (op->all) + appendStringInfoString(buf, "ALL "); + + /* Always parenthesize if RHS is another setop */ + need_paren = IsA(op->rarg, SetOperationStmt); + + /* + * The indentation code here is deliberately a bit different from that + * for the lefthand input, because we want the line breaks in + * different places. + */ + if (need_paren) + { + appendStringInfoChar(buf, '('); + subindent = PRETTYINDENT_STD; + } + else + subindent = 0; + appendContextKeyword(context, "", subindent, 0, 0); + + get_setop_query(op->rarg, query, context, resultDesc); + + if (PRETTY_INDENT(context)) + context->indentLevel -= subindent; + if (need_paren) + appendContextKeyword(context, ")", 0, 0, 0); + } + else + { + elog(ERROR, "unrecognized node type: %d", + (int) nodeTag(setOp)); + } +} + +/* + * Display a sort/group clause. + * + * Also returns the expression tree, so caller need not find it again. + */ +static Node * +get_rule_sortgroupclause(SortGroupClause *srt, List *tlist, bool force_colno, + deparse_context *context) +{ + StringInfo buf = context->buf; + TargetEntry *tle; + Node *expr; + + tle = get_sortgroupclause_tle(srt, tlist); + expr = (Node *) tle->expr; + + /* + * Use column-number form if requested by caller. Otherwise, if + * expression is a constant, force it to be dumped with an explicit cast + * as decoration --- this is because a simple integer constant is + * ambiguous (and will be misinterpreted by findTargetlistEntry()) if we + * dump it without any decoration. Otherwise, just dump the expression + * normally. + */ + if (force_colno) + { + Assert(!tle->resjunk); + appendStringInfo(buf, "%d", tle->resno); + } + else if (expr && IsA(expr, Const)) + get_const_expr((Const *) expr, context, 1); + else + get_rule_expr(expr, context, true); + + return expr; +} + +/* + * Display an ORDER BY list. + */ +static void +get_rule_orderby(List *orderList, List *targetList, + bool force_colno, deparse_context *context) +{ + StringInfo buf = context->buf; + const char *sep; + ListCell *l; + + sep = ""; + foreach(l, orderList) + { + SortGroupClause *srt = (SortGroupClause *) lfirst(l); + Node *sortexpr; + Oid sortcoltype; + TypeCacheEntry *typentry; + + appendStringInfoString(buf, sep); + sortexpr = get_rule_sortgroupclause(srt, targetList, + force_colno, context); + sortcoltype = exprType(sortexpr); + /* See whether operator is default < or > for datatype */ + typentry = lookup_type_cache(sortcoltype, + TYPECACHE_LT_OPR | TYPECACHE_GT_OPR); + if (srt->sortop == typentry->lt_opr) + { + /* ASC is default, so emit nothing for it */ + if (srt->nulls_first) + appendStringInfoString(buf, " NULLS FIRST"); + } + else if (srt->sortop == typentry->gt_opr) + { + appendStringInfoString(buf, " DESC"); + /* DESC defaults to NULLS FIRST */ + if (!srt->nulls_first) + appendStringInfoString(buf, " NULLS LAST"); + } + else + { + appendStringInfo(buf, " USING %s", + generate_operator_name(srt->sortop, + sortcoltype, + sortcoltype)); + /* be specific to eliminate ambiguity */ + if (srt->nulls_first) + appendStringInfoString(buf, " NULLS FIRST"); + else + appendStringInfoString(buf, " NULLS LAST"); + } + sep = ", "; + } +} + +/* + * Display a WINDOW clause. + * + * Note that the windowClause list might contain only anonymous window + * specifications, in which case we should print nothing here. + */ +static void +get_rule_windowclause(Query *query, deparse_context *context) +{ + StringInfo buf = context->buf; + const char *sep; + ListCell *l; + + sep = NULL; + foreach(l, query->windowClause) + { + WindowClause *wc = (WindowClause *) lfirst(l); + + if (wc->name == NULL) + continue; /* ignore anonymous windows */ + + if (sep == NULL) + appendContextKeyword(context, " WINDOW ", + -PRETTYINDENT_STD, PRETTYINDENT_STD, 1); + else + appendStringInfoString(buf, sep); + + appendStringInfo(buf, "%s AS ", quote_identifier(wc->name)); + + get_rule_windowspec(wc, query->targetList, context); + + sep = ", "; + } +} + +/* + * Display a window definition + */ +static void +get_rule_windowspec(WindowClause *wc, List *targetList, + deparse_context *context) +{ + StringInfo buf = context->buf; + bool needspace = false; + const char *sep; + ListCell *l; + + appendStringInfoChar(buf, '('); + if (wc->refname) + { + appendStringInfoString(buf, quote_identifier(wc->refname)); + needspace = true; + } + /* partition clauses are always inherited, so only print if no refname */ + if (wc->partitionClause && !wc->refname) + { + if (needspace) + appendStringInfoChar(buf, ' '); + appendStringInfoString(buf, "PARTITION BY "); + sep = ""; + foreach(l, wc->partitionClause) + { + SortGroupClause *grp = (SortGroupClause *) lfirst(l); + + appendStringInfoString(buf, sep); + get_rule_sortgroupclause(grp, targetList, + false, context); + sep = ", "; + } + needspace = true; + } + /* print ordering clause only if not inherited */ + if (wc->orderClause && !wc->copiedOrder) + { + if (needspace) + appendStringInfoChar(buf, ' '); + appendStringInfoString(buf, "ORDER BY "); + get_rule_orderby(wc->orderClause, targetList, false, context); + needspace = true; + } + /* framing clause is never inherited, so print unless it's default */ + if (wc->frameOptions & FRAMEOPTION_NONDEFAULT) + { + if (needspace) + appendStringInfoChar(buf, ' '); + if (wc->frameOptions & FRAMEOPTION_RANGE) + appendStringInfoString(buf, "RANGE "); + else if (wc->frameOptions & FRAMEOPTION_ROWS) + appendStringInfoString(buf, "ROWS "); + else + Assert(false); + if (wc->frameOptions & FRAMEOPTION_BETWEEN) + appendStringInfoString(buf, "BETWEEN "); + if (wc->frameOptions & FRAMEOPTION_START_UNBOUNDED_PRECEDING) + appendStringInfoString(buf, "UNBOUNDED PRECEDING "); + else if (wc->frameOptions & FRAMEOPTION_START_CURRENT_ROW) + appendStringInfoString(buf, "CURRENT ROW "); + else if (wc->frameOptions & FRAMEOPTION_START_VALUE) + { + get_rule_expr(wc->startOffset, context, false); + if (wc->frameOptions & FRAMEOPTION_START_VALUE_PRECEDING) + appendStringInfoString(buf, " PRECEDING "); + else if (wc->frameOptions & FRAMEOPTION_START_VALUE_FOLLOWING) + appendStringInfoString(buf, " FOLLOWING "); + else + Assert(false); + } + else + Assert(false); + if (wc->frameOptions & FRAMEOPTION_BETWEEN) + { + appendStringInfoString(buf, "AND "); + if (wc->frameOptions & FRAMEOPTION_END_UNBOUNDED_FOLLOWING) + appendStringInfoString(buf, "UNBOUNDED FOLLOWING "); + else if (wc->frameOptions & FRAMEOPTION_END_CURRENT_ROW) + appendStringInfoString(buf, "CURRENT ROW "); + else if (wc->frameOptions & FRAMEOPTION_END_VALUE) + { + get_rule_expr(wc->endOffset, context, false); + if (wc->frameOptions & FRAMEOPTION_END_VALUE_PRECEDING) + appendStringInfoString(buf, " PRECEDING "); + else if (wc->frameOptions & FRAMEOPTION_END_VALUE_FOLLOWING) + appendStringInfoString(buf, " FOLLOWING "); + else + Assert(false); + } + else + Assert(false); + } + /* we will now have a trailing space; remove it */ + buf->len--; + } + appendStringInfoChar(buf, ')'); +} + +/* ---------- + * get_insert_query_def - Parse back an INSERT parsetree + * ---------- + */ +static void +get_insert_query_def(Query *query, deparse_context *context) +{ + StringInfo buf = context->buf; + RangeTblEntry *select_rte = NULL; + RangeTblEntry *values_rte = NULL; + RangeTblEntry *rte; + char *sep; + ListCell *values_cell; + ListCell *l; + List *strippedexprs; + + /* Insert the WITH clause if given */ + get_with_clause(query, context); + + /* + * If it's an INSERT ... SELECT or multi-row VALUES, there will be a + * single RTE for the SELECT or VALUES. Plain VALUES has neither. + */ + foreach(l, query->rtable) + { + rte = (RangeTblEntry *) lfirst(l); + + if (rte->rtekind == RTE_SUBQUERY) + { + if (select_rte) + elog(ERROR, "too many subquery RTEs in INSERT"); + select_rte = rte; + } + + if (rte->rtekind == RTE_VALUES) + { + if (values_rte) + elog(ERROR, "too many values RTEs in INSERT"); + values_rte = rte; + } + } + if (select_rte && values_rte) + elog(ERROR, "both subquery and values RTEs in INSERT"); + + /* + * Start the query with INSERT INTO relname + */ + rte = rt_fetch(query->resultRelation, query->rtable); + Assert(rte->rtekind == RTE_RELATION); + + if (PRETTY_INDENT(context)) + { + context->indentLevel += PRETTYINDENT_STD; + appendStringInfoChar(buf, ' '); + } + appendStringInfo(buf, "INSERT INTO %s ", + generate_relation_or_shard_name(rte->relid, + context->distrelid, + context->shardid, NIL)); + + /* + * Add the insert-column-names list. To handle indirection properly, we + * need to look for indirection nodes in the top targetlist (if it's + * INSERT ... SELECT or INSERT ... single VALUES), or in the first + * expression list of the VALUES RTE (if it's INSERT ... multi VALUES). We + * assume that all the expression lists will have similar indirection in + * the latter case. + */ + if (values_rte) + values_cell = list_head((List *) linitial(values_rte->values_lists)); + else + values_cell = NULL; + strippedexprs = NIL; + sep = ""; + if (query->targetList) + appendStringInfoChar(buf, '('); + foreach(l, query->targetList) + { + TargetEntry *tle = (TargetEntry *) lfirst(l); + + if (tle->resjunk) + continue; /* ignore junk entries */ + + appendStringInfoString(buf, sep); + sep = ", "; + + /* + * Put out name of target column; look in the catalogs, not at + * tle->resname, since resname will fail to track RENAME. + */ + appendStringInfoString(buf, + quote_identifier(get_relid_attribute_name(rte->relid, + tle->resno))); + + /* + * Print any indirection needed (subfields or subscripts), and strip + * off the top-level nodes representing the indirection assignments. + */ + if (values_cell) + { + /* we discard the stripped expression in this case */ + processIndirection((Node *) lfirst(values_cell), context, true); + values_cell = lnext(values_cell); + } + else + { + /* we keep a list of the stripped expressions in this case */ + strippedexprs = lappend(strippedexprs, + processIndirection((Node *) tle->expr, + context, true)); + } + } + if (query->targetList) + appendStringInfoString(buf, ") "); + + if (select_rte) + { + /* Add the SELECT */ + get_query_def(select_rte->subquery, buf, NIL, NULL, + context->prettyFlags, context->wrapColumn, + context->indentLevel); + } + else if (values_rte) + { + /* Add the multi-VALUES expression lists */ + get_values_def(values_rte->values_lists, context); + } + else if (strippedexprs) + { + /* Add the single-VALUES expression list */ + appendContextKeyword(context, "VALUES (", + -PRETTYINDENT_STD, PRETTYINDENT_STD, 2); + get_rule_expr((Node *) strippedexprs, context, false); + appendStringInfoChar(buf, ')'); + } + else + { + /* No expressions, so it must be DEFAULT VALUES */ + appendStringInfoString(buf, "DEFAULT VALUES"); + } + + /* Add RETURNING if present */ + if (query->returningList) + { + appendContextKeyword(context, " RETURNING", + -PRETTYINDENT_STD, PRETTYINDENT_STD, 1); + get_target_list(query->returningList, context, NULL); + } +} + + +/* ---------- + * get_update_query_def - Parse back an UPDATE parsetree + * ---------- + */ +static void +get_update_query_def(Query *query, deparse_context *context) +{ + StringInfo buf = context->buf; + char *sep; + RangeTblEntry *rte; + ListCell *l; + + /* Insert the WITH clause if given */ + get_with_clause(query, context); + + /* + * Start the query with UPDATE relname SET + */ + rte = rt_fetch(query->resultRelation, query->rtable); + Assert(rte->rtekind == RTE_RELATION); + if (PRETTY_INDENT(context)) + { + appendStringInfoChar(buf, ' '); + context->indentLevel += PRETTYINDENT_STD; + } + appendStringInfo(buf, "UPDATE %s%s", + only_marker(rte), + generate_relation_or_shard_name(rte->relid, + context->distrelid, + context->shardid, NIL)); + if (rte->alias != NULL) + appendStringInfo(buf, " %s", + quote_identifier(rte->alias->aliasname)); + appendStringInfoString(buf, " SET "); + + /* Add the comma separated list of 'attname = value' */ + sep = ""; + foreach(l, query->targetList) + { + TargetEntry *tle = (TargetEntry *) lfirst(l); + Node *expr; + + if (tle->resjunk) + continue; /* ignore junk entries */ + + appendStringInfoString(buf, sep); + sep = ", "; + + /* + * Put out name of target column; look in the catalogs, not at + * tle->resname, since resname will fail to track RENAME. + */ + appendStringInfoString(buf, + quote_identifier(get_relid_attribute_name(rte->relid, + tle->resno))); + + /* + * Print any indirection needed (subfields or subscripts), and strip + * off the top-level nodes representing the indirection assignments. + */ + expr = processIndirection((Node *) tle->expr, context, true); + + appendStringInfoString(buf, " = "); + + get_rule_expr(expr, context, false); + } + + /* Add the FROM clause if needed */ + get_from_clause(query, " FROM ", context); + + /* Add a WHERE clause if given */ + if (query->jointree->quals != NULL) + { + appendContextKeyword(context, " WHERE ", + -PRETTYINDENT_STD, PRETTYINDENT_STD, 1); + get_rule_expr(query->jointree->quals, context, false); + } + + /* Add RETURNING if present */ + if (query->returningList) + { + appendContextKeyword(context, " RETURNING", + -PRETTYINDENT_STD, PRETTYINDENT_STD, 1); + get_target_list(query->returningList, context, NULL); + } +} + + +/* ---------- + * get_delete_query_def - Parse back a DELETE parsetree + * ---------- + */ +static void +get_delete_query_def(Query *query, deparse_context *context) +{ + StringInfo buf = context->buf; + RangeTblEntry *rte; + + /* Insert the WITH clause if given */ + get_with_clause(query, context); + + /* + * Start the query with DELETE FROM relname + */ + rte = rt_fetch(query->resultRelation, query->rtable); + Assert(rte->rtekind == RTE_RELATION); + if (PRETTY_INDENT(context)) + { + appendStringInfoChar(buf, ' '); + context->indentLevel += PRETTYINDENT_STD; + } + appendStringInfo(buf, "DELETE FROM %s%s", + only_marker(rte), + generate_relation_or_shard_name(rte->relid, + context->distrelid, + context->shardid, NIL)); + if (rte->alias != NULL) + appendStringInfo(buf, " %s", + quote_identifier(rte->alias->aliasname)); + + /* Add the USING clause if given */ + get_from_clause(query, " USING ", context); + + /* Add a WHERE clause if given */ + if (query->jointree->quals != NULL) + { + appendContextKeyword(context, " WHERE ", + -PRETTYINDENT_STD, PRETTYINDENT_STD, 1); + get_rule_expr(query->jointree->quals, context, false); + } + + /* Add RETURNING if present */ + if (query->returningList) + { + appendContextKeyword(context, " RETURNING", + -PRETTYINDENT_STD, PRETTYINDENT_STD, 1); + get_target_list(query->returningList, context, NULL); + } +} + + +/* ---------- + * get_utility_query_def - Parse back a UTILITY parsetree + * ---------- + */ +static void +get_utility_query_def(Query *query, deparse_context *context) +{ + StringInfo buf = context->buf; + + if (query->utilityStmt && IsA(query->utilityStmt, NotifyStmt)) + { + NotifyStmt *stmt = (NotifyStmt *) query->utilityStmt; + + appendContextKeyword(context, "", + 0, PRETTYINDENT_STD, 1); + appendStringInfo(buf, "NOTIFY %s", + quote_identifier(stmt->conditionname)); + if (stmt->payload) + { + appendStringInfoString(buf, ", "); + simple_quote_literal(buf, stmt->payload); + } + } + else + { + /* Currently only NOTIFY utility commands can appear in rules */ + elog(ERROR, "unexpected utility statement type"); + } +} + + +/* + * Display a Var appropriately. + * + * In some cases (currently only when recursing into an unnamed join) + * the Var's varlevelsup has to be interpreted with respect to a context + * above the current one; levelsup indicates the offset. + * + * If istoplevel is TRUE, the Var is at the top level of a SELECT's + * targetlist, which means we need special treatment of whole-row Vars. + * Instead of the normal "tab.*", we'll print "tab.*::typename", which is a + * dirty hack to prevent "tab.*" from being expanded into multiple columns. + * (The parser will strip the useless coercion, so no inefficiency is added in + * dump and reload.) We used to print just "tab" in such cases, but that is + * ambiguous and will yield the wrong result if "tab" is also a plain column + * name in the query. + * + * Returns the attname of the Var, or NULL if the Var has no attname (because + * it is a whole-row Var or a subplan output reference). + */ +static char * +get_variable(Var *var, int levelsup, bool istoplevel, deparse_context *context) +{ + StringInfo buf = context->buf; + RangeTblEntry *rte; + AttrNumber attnum; + int netlevelsup; + deparse_namespace *dpns; + deparse_columns *colinfo; + char *refname; + char *attname; + + /* Find appropriate nesting depth */ + netlevelsup = var->varlevelsup + levelsup; + if (netlevelsup >= list_length(context->namespaces)) + elog(ERROR, "bogus varlevelsup: %d offset %d", + var->varlevelsup, levelsup); + dpns = (deparse_namespace *) list_nth(context->namespaces, + netlevelsup); + + /* + * Try to find the relevant RTE in this rtable. In a plan tree, it's + * likely that varno is OUTER_VAR or INNER_VAR, in which case we must dig + * down into the subplans, or INDEX_VAR, which is resolved similarly. Also + * find the aliases previously assigned for this RTE. + */ + if (var->varno >= 1 && var->varno <= list_length(dpns->rtable)) + { + rte = rt_fetch(var->varno, dpns->rtable); + refname = (char *) list_nth(dpns->rtable_names, var->varno - 1); + colinfo = deparse_columns_fetch(var->varno, dpns); + attnum = var->varattno; + } + else if (var->varno == OUTER_VAR && dpns->outer_tlist) + { + TargetEntry *tle; + deparse_namespace save_dpns; + + tle = get_tle_by_resno(dpns->outer_tlist, var->varattno); + if (!tle) + elog(ERROR, "bogus varattno for OUTER_VAR var: %d", var->varattno); + + Assert(netlevelsup == 0); + push_child_plan(dpns, dpns->outer_planstate, &save_dpns); + + /* + * Force parentheses because our caller probably assumed a Var is a + * simple expression. + */ + if (!IsA(tle->expr, Var)) + appendStringInfoChar(buf, '('); + get_rule_expr((Node *) tle->expr, context, true); + if (!IsA(tle->expr, Var)) + appendStringInfoChar(buf, ')'); + + pop_child_plan(dpns, &save_dpns); + return NULL; + } + else if (var->varno == INNER_VAR && dpns->inner_tlist) + { + TargetEntry *tle; + deparse_namespace save_dpns; + + tle = get_tle_by_resno(dpns->inner_tlist, var->varattno); + if (!tle) + elog(ERROR, "bogus varattno for INNER_VAR var: %d", var->varattno); + + Assert(netlevelsup == 0); + push_child_plan(dpns, dpns->inner_planstate, &save_dpns); + + /* + * Force parentheses because our caller probably assumed a Var is a + * simple expression. + */ + if (!IsA(tle->expr, Var)) + appendStringInfoChar(buf, '('); + get_rule_expr((Node *) tle->expr, context, true); + if (!IsA(tle->expr, Var)) + appendStringInfoChar(buf, ')'); + + pop_child_plan(dpns, &save_dpns); + return NULL; + } + else if (var->varno == INDEX_VAR && dpns->index_tlist) + { + TargetEntry *tle; + + tle = get_tle_by_resno(dpns->index_tlist, var->varattno); + if (!tle) + elog(ERROR, "bogus varattno for INDEX_VAR var: %d", var->varattno); + + Assert(netlevelsup == 0); + + /* + * Force parentheses because our caller probably assumed a Var is a + * simple expression. + */ + if (!IsA(tle->expr, Var)) + appendStringInfoChar(buf, '('); + get_rule_expr((Node *) tle->expr, context, true); + if (!IsA(tle->expr, Var)) + appendStringInfoChar(buf, ')'); + + return NULL; + } + else + { + elog(ERROR, "bogus varno: %d", var->varno); + return NULL; /* keep compiler quiet */ + } + + /* + * The planner will sometimes emit Vars referencing resjunk elements of a + * subquery's target list (this is currently only possible if it chooses + * to generate a "physical tlist" for a SubqueryScan or CteScan node). + * Although we prefer to print subquery-referencing Vars using the + * subquery's alias, that's not possible for resjunk items since they have + * no alias. So in that case, drill down to the subplan and print the + * contents of the referenced tlist item. This works because in a plan + * tree, such Vars can only occur in a SubqueryScan or CteScan node, and + * we'll have set dpns->inner_planstate to reference the child plan node. + */ + if ((rte->rtekind == RTE_SUBQUERY || rte->rtekind == RTE_CTE) && + attnum > list_length(rte->eref->colnames) && + dpns->inner_planstate) + { + TargetEntry *tle; + deparse_namespace save_dpns; + + tle = get_tle_by_resno(dpns->inner_tlist, var->varattno); + if (!tle) + elog(ERROR, "bogus varattno for subquery var: %d", var->varattno); + + Assert(netlevelsup == 0); + push_child_plan(dpns, dpns->inner_planstate, &save_dpns); + + /* + * Force parentheses because our caller probably assumed a Var is a + * simple expression. + */ + if (!IsA(tle->expr, Var)) + appendStringInfoChar(buf, '('); + get_rule_expr((Node *) tle->expr, context, true); + if (!IsA(tle->expr, Var)) + appendStringInfoChar(buf, ')'); + + pop_child_plan(dpns, &save_dpns); + return NULL; + } + + /* + * If it's an unnamed join, look at the expansion of the alias variable. + * If it's a simple reference to one of the input vars, then recursively + * print the name of that var instead. When it's not a simple reference, + * we have to just print the unqualified join column name. (This can only + * happen with "dangerous" merged columns in a JOIN USING; we took pains + * previously to make the unqualified column name unique in such cases.) + * + * This wouldn't work in decompiling plan trees, because we don't store + * joinaliasvars lists after planning; but a plan tree should never + * contain a join alias variable. + */ + if (rte->rtekind == RTE_JOIN && rte->alias == NULL) + { + if (rte->joinaliasvars == NIL) + elog(ERROR, "cannot decompile join alias var in plan tree"); + if (attnum > 0) + { + Var *aliasvar; + + aliasvar = (Var *) list_nth(rte->joinaliasvars, attnum - 1); + /* we intentionally don't strip implicit coercions here */ + if (aliasvar && IsA(aliasvar, Var)) + { + return get_variable(aliasvar, var->varlevelsup + levelsup, + istoplevel, context); + } + } + + /* + * Unnamed join has no refname. (Note: since it's unnamed, there is + * no way the user could have referenced it to create a whole-row Var + * for it. So we don't have to cover that case below.) + */ + Assert(refname == NULL); + } + + if (attnum == InvalidAttrNumber) + attname = NULL; + else if (attnum > 0) + { + /* Get column name to use from the colinfo struct */ + Assert(attnum <= colinfo->num_cols); + attname = colinfo->colnames[attnum - 1]; + Assert(attname != NULL); + } + else + { + /* System column - name is fixed, get it from the catalog */ + attname = get_rte_attribute_name(rte, attnum); + } + + if (refname && (context->varprefix || attname == NULL)) + { + appendStringInfoString(buf, quote_identifier(refname)); + appendStringInfoChar(buf, '.'); + } + if (attname) + appendStringInfoString(buf, quote_identifier(attname)); + else + { + appendStringInfoChar(buf, '*'); + if (istoplevel) + appendStringInfo(buf, "::%s", + format_type_with_typemod(var->vartype, + var->vartypmod)); + } + + return attname; +} + + +/* + * Get the name of a field of an expression of composite type. The + * expression is usually a Var, but we handle other cases too. + * + * levelsup is an extra offset to interpret the Var's varlevelsup correctly. + * + * This is fairly straightforward when the expression has a named composite + * type; we need only look up the type in the catalogs. However, the type + * could also be RECORD. Since no actual table or view column is allowed to + * have type RECORD, a Var of type RECORD must refer to a JOIN or FUNCTION RTE + * or to a subquery output. We drill down to find the ultimate defining + * expression and attempt to infer the field name from it. We ereport if we + * can't determine the name. + * + * Similarly, a PARAM of type RECORD has to refer to some expression of + * a determinable composite type. + */ +static const char * +get_name_for_var_field(Var *var, int fieldno, + int levelsup, deparse_context *context) +{ + RangeTblEntry *rte; + AttrNumber attnum; + int netlevelsup; + deparse_namespace *dpns; + TupleDesc tupleDesc; + Node *expr; + + /* + * If it's a RowExpr that was expanded from a whole-row Var, use the + * column names attached to it. + */ + if (IsA(var, RowExpr)) + { + RowExpr *r = (RowExpr *) var; + + if (fieldno > 0 && fieldno <= list_length(r->colnames)) + return strVal(list_nth(r->colnames, fieldno - 1)); + } + + /* + * If it's a Param of type RECORD, try to find what the Param refers to. + */ + if (IsA(var, Param)) + { + Param *param = (Param *) var; + ListCell *ancestor_cell; + + expr = find_param_referent(param, context, &dpns, &ancestor_cell); + if (expr) + { + /* Found a match, so recurse to decipher the field name */ + deparse_namespace save_dpns; + const char *result; + + push_ancestor_plan(dpns, ancestor_cell, &save_dpns); + result = get_name_for_var_field((Var *) expr, fieldno, + 0, context); + pop_ancestor_plan(dpns, &save_dpns); + return result; + } + } + + /* + * If it's a Var of type RECORD, we have to find what the Var refers to; + * if not, we can use get_expr_result_type. If that fails, we try + * lookup_rowtype_tupdesc, which will probably fail too, but will ereport + * an acceptable message. + */ + if (!IsA(var, Var) || + var->vartype != RECORDOID) + { + if (get_expr_result_type((Node *) var, NULL, &tupleDesc) != TYPEFUNC_COMPOSITE) + tupleDesc = lookup_rowtype_tupdesc_copy(exprType((Node *) var), + exprTypmod((Node *) var)); + Assert(tupleDesc); + /* Got the tupdesc, so we can extract the field name */ + Assert(fieldno >= 1 && fieldno <= tupleDesc->natts); + return NameStr(tupleDesc->attrs[fieldno - 1]->attname); + } + + /* Find appropriate nesting depth */ + netlevelsup = var->varlevelsup + levelsup; + if (netlevelsup >= list_length(context->namespaces)) + elog(ERROR, "bogus varlevelsup: %d offset %d", + var->varlevelsup, levelsup); + dpns = (deparse_namespace *) list_nth(context->namespaces, + netlevelsup); + + /* + * Try to find the relevant RTE in this rtable. In a plan tree, it's + * likely that varno is OUTER_VAR or INNER_VAR, in which case we must dig + * down into the subplans, or INDEX_VAR, which is resolved similarly. + */ + if (var->varno >= 1 && var->varno <= list_length(dpns->rtable)) + { + rte = rt_fetch(var->varno, dpns->rtable); + attnum = var->varattno; + } + else if (var->varno == OUTER_VAR && dpns->outer_tlist) + { + TargetEntry *tle; + deparse_namespace save_dpns; + const char *result; + + tle = get_tle_by_resno(dpns->outer_tlist, var->varattno); + if (!tle) + elog(ERROR, "bogus varattno for OUTER_VAR var: %d", var->varattno); + + Assert(netlevelsup == 0); + push_child_plan(dpns, dpns->outer_planstate, &save_dpns); + + result = get_name_for_var_field((Var *) tle->expr, fieldno, + levelsup, context); + + pop_child_plan(dpns, &save_dpns); + return result; + } + else if (var->varno == INNER_VAR && dpns->inner_tlist) + { + TargetEntry *tle; + deparse_namespace save_dpns; + const char *result; + + tle = get_tle_by_resno(dpns->inner_tlist, var->varattno); + if (!tle) + elog(ERROR, "bogus varattno for INNER_VAR var: %d", var->varattno); + + Assert(netlevelsup == 0); + push_child_plan(dpns, dpns->inner_planstate, &save_dpns); + + result = get_name_for_var_field((Var *) tle->expr, fieldno, + levelsup, context); + + pop_child_plan(dpns, &save_dpns); + return result; + } + else if (var->varno == INDEX_VAR && dpns->index_tlist) + { + TargetEntry *tle; + const char *result; + + tle = get_tle_by_resno(dpns->index_tlist, var->varattno); + if (!tle) + elog(ERROR, "bogus varattno for INDEX_VAR var: %d", var->varattno); + + Assert(netlevelsup == 0); + + result = get_name_for_var_field((Var *) tle->expr, fieldno, + levelsup, context); + + return result; + } + else + { + elog(ERROR, "bogus varno: %d", var->varno); + return NULL; /* keep compiler quiet */ + } + + if (attnum == InvalidAttrNumber) + { + /* Var is whole-row reference to RTE, so select the right field */ + return get_rte_attribute_name(rte, fieldno); + } + + /* + * This part has essentially the same logic as the parser's + * expandRecordVariable() function, but we are dealing with a different + * representation of the input context, and we only need one field name + * not a TupleDesc. Also, we need special cases for finding subquery and + * CTE subplans when deparsing Plan trees. + */ + expr = (Node *) var; /* default if we can't drill down */ + + switch (rte->rtekind) + { + case RTE_RELATION: + case RTE_VALUES: + + /* + * This case should not occur: a column of a table or values list + * shouldn't have type RECORD. Fall through and fail (most + * likely) at the bottom. + */ + break; + case RTE_SUBQUERY: + /* Subselect-in-FROM: examine sub-select's output expr */ + { + if (rte->subquery) + { + TargetEntry *ste = get_tle_by_resno(rte->subquery->targetList, + attnum); + + if (ste == NULL || ste->resjunk) + elog(ERROR, "subquery %s does not have attribute %d", + rte->eref->aliasname, attnum); + expr = (Node *) ste->expr; + if (IsA(expr, Var)) + { + /* + * Recurse into the sub-select to see what its Var + * refers to. We have to build an additional level of + * namespace to keep in step with varlevelsup in the + * subselect. + */ + deparse_namespace mydpns; + const char *result; + + set_deparse_for_query(&mydpns, rte->subquery, + context->namespaces); + + context->namespaces = lcons(&mydpns, + context->namespaces); + + result = get_name_for_var_field((Var *) expr, fieldno, + 0, context); + + context->namespaces = + list_delete_first(context->namespaces); + + return result; + } + /* else fall through to inspect the expression */ + } + else + { + /* + * We're deparsing a Plan tree so we don't have complete + * RTE entries (in particular, rte->subquery is NULL). But + * the only place we'd see a Var directly referencing a + * SUBQUERY RTE is in a SubqueryScan plan node, and we can + * look into the child plan's tlist instead. + */ + TargetEntry *tle; + deparse_namespace save_dpns; + const char *result; + + if (!dpns->inner_planstate) + elog(ERROR, "failed to find plan for subquery %s", + rte->eref->aliasname); + tle = get_tle_by_resno(dpns->inner_tlist, attnum); + if (!tle) + elog(ERROR, "bogus varattno for subquery var: %d", + attnum); + Assert(netlevelsup == 0); + push_child_plan(dpns, dpns->inner_planstate, &save_dpns); + + result = get_name_for_var_field((Var *) tle->expr, fieldno, + levelsup, context); + + pop_child_plan(dpns, &save_dpns); + return result; + } + } + break; + case RTE_JOIN: + /* Join RTE --- recursively inspect the alias variable */ + if (rte->joinaliasvars == NIL) + elog(ERROR, "cannot decompile join alias var in plan tree"); + Assert(attnum > 0 && attnum <= list_length(rte->joinaliasvars)); + expr = (Node *) list_nth(rte->joinaliasvars, attnum - 1); + Assert(expr != NULL); + /* we intentionally don't strip implicit coercions here */ + if (IsA(expr, Var)) + return get_name_for_var_field((Var *) expr, fieldno, + var->varlevelsup + levelsup, + context); + /* else fall through to inspect the expression */ + break; + case RTE_FUNCTION: + + /* + * We couldn't get here unless a function is declared with one of + * its result columns as RECORD, which is not allowed. + */ + break; + case RTE_CTE: + /* CTE reference: examine subquery's output expr */ + { + CommonTableExpr *cte = NULL; + Index ctelevelsup; + ListCell *lc; + + /* + * Try to find the referenced CTE using the namespace stack. + */ + ctelevelsup = rte->ctelevelsup + netlevelsup; + if (ctelevelsup >= list_length(context->namespaces)) + lc = NULL; + else + { + deparse_namespace *ctedpns; + + ctedpns = (deparse_namespace *) + list_nth(context->namespaces, ctelevelsup); + foreach(lc, ctedpns->ctes) + { + cte = (CommonTableExpr *) lfirst(lc); + if (strcmp(cte->ctename, rte->ctename) == 0) + break; + } + } + if (lc != NULL) + { + Query *ctequery = (Query *) cte->ctequery; + TargetEntry *ste = get_tle_by_resno(GetCTETargetList(cte), + attnum); + + if (ste == NULL || ste->resjunk) + elog(ERROR, "subquery %s does not have attribute %d", + rte->eref->aliasname, attnum); + expr = (Node *) ste->expr; + if (IsA(expr, Var)) + { + /* + * Recurse into the CTE to see what its Var refers to. + * We have to build an additional level of namespace + * to keep in step with varlevelsup in the CTE. + * Furthermore it could be an outer CTE, so we may + * have to delete some levels of namespace. + */ + List *save_nslist = context->namespaces; + List *new_nslist; + deparse_namespace mydpns; + const char *result; + + set_deparse_for_query(&mydpns, ctequery, + context->namespaces); + + new_nslist = list_copy_tail(context->namespaces, + ctelevelsup); + context->namespaces = lcons(&mydpns, new_nslist); + + result = get_name_for_var_field((Var *) expr, fieldno, + 0, context); + + context->namespaces = save_nslist; + + return result; + } + /* else fall through to inspect the expression */ + } + else + { + /* + * We're deparsing a Plan tree so we don't have a CTE + * list. But the only place we'd see a Var directly + * referencing a CTE RTE is in a CteScan plan node, and we + * can look into the subplan's tlist instead. + */ + TargetEntry *tle; + deparse_namespace save_dpns; + const char *result; + + if (!dpns->inner_planstate) + elog(ERROR, "failed to find plan for CTE %s", + rte->eref->aliasname); + tle = get_tle_by_resno(dpns->inner_tlist, attnum); + if (!tle) + elog(ERROR, "bogus varattno for subquery var: %d", + attnum); + Assert(netlevelsup == 0); + push_child_plan(dpns, dpns->inner_planstate, &save_dpns); + + result = get_name_for_var_field((Var *) tle->expr, fieldno, + levelsup, context); + + pop_child_plan(dpns, &save_dpns); + return result; + } + } + break; + } + + /* + * We now have an expression we can't expand any more, so see if + * get_expr_result_type() can do anything with it. If not, pass to + * lookup_rowtype_tupdesc() which will probably fail, but will give an + * appropriate error message while failing. + */ + if (get_expr_result_type(expr, NULL, &tupleDesc) != TYPEFUNC_COMPOSITE) + tupleDesc = lookup_rowtype_tupdesc_copy(exprType(expr), + exprTypmod(expr)); + Assert(tupleDesc); + /* Got the tupdesc, so we can extract the field name */ + Assert(fieldno >= 1 && fieldno <= tupleDesc->natts); + return NameStr(tupleDesc->attrs[fieldno - 1]->attname); +} + +/* + * Try to find the referenced expression for a PARAM_EXEC Param that might + * reference a parameter supplied by an upper NestLoop or SubPlan plan node. + * + * If successful, return the expression and set *dpns_p and *ancestor_cell_p + * appropriately for calling push_ancestor_plan(). If no referent can be + * found, return NULL. + */ +static Node * +find_param_referent(Param *param, deparse_context *context, + deparse_namespace **dpns_p, ListCell **ancestor_cell_p) +{ + /* Initialize output parameters to prevent compiler warnings */ + *dpns_p = NULL; + *ancestor_cell_p = NULL; + + /* + * If it's a PARAM_EXEC parameter, look for a matching NestLoopParam or + * SubPlan argument. This will necessarily be in some ancestor of the + * current expression's PlanState. + */ + if (param->paramkind == PARAM_EXEC) + { + deparse_namespace *dpns; + PlanState *child_ps; + bool in_same_plan_level; + ListCell *lc; + + dpns = (deparse_namespace *) linitial(context->namespaces); + child_ps = dpns->planstate; + in_same_plan_level = true; + + foreach(lc, dpns->ancestors) + { + PlanState *ps = (PlanState *) lfirst(lc); + ListCell *lc2; + + /* + * NestLoops transmit params to their inner child only; also, once + * we've crawled up out of a subplan, this couldn't possibly be + * the right match. + */ + if (IsA(ps, NestLoopState) && + child_ps == innerPlanState(ps) && + in_same_plan_level) + { + NestLoop *nl = (NestLoop *) ps->plan; + + foreach(lc2, nl->nestParams) + { + NestLoopParam *nlp = (NestLoopParam *) lfirst(lc2); + + if (nlp->paramno == param->paramid) + { + /* Found a match, so return it */ + *dpns_p = dpns; + *ancestor_cell_p = lc; + return (Node *) nlp->paramval; + } + } + } + + /* + * Check to see if we're crawling up from a subplan. + */ + foreach(lc2, ps->subPlan) + { + SubPlanState *sstate = (SubPlanState *) lfirst(lc2); + SubPlan *subplan = (SubPlan *) sstate->xprstate.expr; + ListCell *lc3; + ListCell *lc4; + + if (child_ps != sstate->planstate) + continue; + + /* Matched subplan, so check its arguments */ + forboth(lc3, subplan->parParam, lc4, subplan->args) + { + int paramid = lfirst_int(lc3); + Node *arg = (Node *) lfirst(lc4); + + if (paramid == param->paramid) + { + /* Found a match, so return it */ + *dpns_p = dpns; + *ancestor_cell_p = lc; + return arg; + } + } + + /* Keep looking, but we are emerging from a subplan. */ + in_same_plan_level = false; + break; + } + + /* + * Likewise check to see if we're emerging from an initplan. + * Initplans never have any parParams, so no need to search that + * list, but we need to know if we should reset + * in_same_plan_level. + */ + foreach(lc2, ps->initPlan) + { + SubPlanState *sstate = (SubPlanState *) lfirst(lc2); + + if (child_ps != sstate->planstate) + continue; + + /* No parameters to be had here. */ + Assert(((SubPlan *) sstate->xprstate.expr)->parParam == NIL); + + /* Keep looking, but we are emerging from an initplan. */ + in_same_plan_level = false; + break; + } + + /* No luck, crawl up to next ancestor */ + child_ps = ps; + } + } + + /* No referent found */ + return NULL; +} + +/* + * Display a Param appropriately. + */ +static void +get_parameter(Param *param, deparse_context *context) +{ + Node *expr; + deparse_namespace *dpns; + ListCell *ancestor_cell; + + /* + * If it's a PARAM_EXEC parameter, try to locate the expression from which + * the parameter was computed. Note that failing to find a referent isn't + * an error, since the Param might well be a subplan output rather than an + * input. + */ + expr = find_param_referent(param, context, &dpns, &ancestor_cell); + if (expr) + { + /* Found a match, so print it */ + deparse_namespace save_dpns; + bool save_varprefix; + bool need_paren; + + /* Switch attention to the ancestor plan node */ + push_ancestor_plan(dpns, ancestor_cell, &save_dpns); + + /* + * Force prefixing of Vars, since they won't belong to the relation + * being scanned in the original plan node. + */ + save_varprefix = context->varprefix; + context->varprefix = true; + + /* + * A Param's expansion is typically a Var, Aggref, or upper-level + * Param, which wouldn't need extra parentheses. Otherwise, insert + * parens to ensure the expression looks atomic. + */ + need_paren = !(IsA(expr, Var) || + IsA(expr, Aggref) || + IsA(expr, Param)); + if (need_paren) + appendStringInfoChar(context->buf, '('); + + get_rule_expr(expr, context, false); + + if (need_paren) + appendStringInfoChar(context->buf, ')'); + + context->varprefix = save_varprefix; + + pop_ancestor_plan(dpns, &save_dpns); + + return; + } + + /* + * Not PARAM_EXEC, or couldn't find referent: just print $N. + */ + appendStringInfo(context->buf, "$%d", param->paramid); +} + +/* + * get_simple_binary_op_name + * + * helper function for isSimpleNode + * will return single char binary operator name, or NULL if it's not + */ +static const char * +get_simple_binary_op_name(OpExpr *expr) +{ + List *args = expr->args; + + if (list_length(args) == 2) + { + /* binary operator */ + Node *arg1 = (Node *) linitial(args); + Node *arg2 = (Node *) lsecond(args); + const char *op; + + op = generate_operator_name(expr->opno, exprType(arg1), exprType(arg2)); + if (strlen(op) == 1) + return op; + } + return NULL; +} + + +/* + * isSimpleNode - check if given node is simple (doesn't need parenthesizing) + * + * true : simple in the context of parent node's type + * false : not simple + */ +static bool +isSimpleNode(Node *node, Node *parentNode, int prettyFlags) +{ + if (!node) + return false; + + switch (nodeTag(node)) + { + case T_Var: + case T_Const: + case T_Param: + case T_CoerceToDomainValue: + case T_SetToDefault: + case T_CurrentOfExpr: + /* single words: always simple */ + return true; + + case T_ArrayRef: + case T_ArrayExpr: + case T_RowExpr: + case T_CoalesceExpr: + case T_MinMaxExpr: + case T_XmlExpr: + case T_NullIfExpr: + case T_Aggref: + case T_WindowFunc: + case T_FuncExpr: + /* function-like: name(..) or name[..] */ + return true; + + /* CASE keywords act as parentheses */ + case T_CaseExpr: + return true; + + case T_FieldSelect: + + /* + * appears simple since . has top precedence, unless parent is + * T_FieldSelect itself! + */ + return (IsA(parentNode, FieldSelect) ? false : true); + + case T_FieldStore: + + /* + * treat like FieldSelect (probably doesn't matter) + */ + return (IsA(parentNode, FieldStore) ? false : true); + + case T_CoerceToDomain: + /* maybe simple, check args */ + return isSimpleNode((Node *) ((CoerceToDomain *) node)->arg, + node, prettyFlags); + case T_RelabelType: + return isSimpleNode((Node *) ((RelabelType *) node)->arg, + node, prettyFlags); + case T_CoerceViaIO: + return isSimpleNode((Node *) ((CoerceViaIO *) node)->arg, + node, prettyFlags); + case T_ArrayCoerceExpr: + return isSimpleNode((Node *) ((ArrayCoerceExpr *) node)->arg, + node, prettyFlags); + case T_ConvertRowtypeExpr: + return isSimpleNode((Node *) ((ConvertRowtypeExpr *) node)->arg, + node, prettyFlags); + + case T_OpExpr: + { + /* depends on parent node type; needs further checking */ + if (prettyFlags & PRETTYFLAG_PAREN && IsA(parentNode, OpExpr)) + { + const char *op; + const char *parentOp; + bool is_lopriop; + bool is_hipriop; + bool is_lopriparent; + bool is_hipriparent; + + op = get_simple_binary_op_name((OpExpr *) node); + if (!op) + return false; + + /* We know only the basic operators + - and * / % */ + is_lopriop = (strchr("+-", *op) != NULL); + is_hipriop = (strchr("*/%", *op) != NULL); + if (!(is_lopriop || is_hipriop)) + return false; + + parentOp = get_simple_binary_op_name((OpExpr *) parentNode); + if (!parentOp) + return false; + + is_lopriparent = (strchr("+-", *parentOp) != NULL); + is_hipriparent = (strchr("*/%", *parentOp) != NULL); + if (!(is_lopriparent || is_hipriparent)) + return false; + + if (is_hipriop && is_lopriparent) + return true; /* op binds tighter than parent */ + + if (is_lopriop && is_hipriparent) + return false; + + /* + * Operators are same priority --- can skip parens only if + * we have (a - b) - c, not a - (b - c). + */ + if (node == (Node *) linitial(((OpExpr *) parentNode)->args)) + return true; + + return false; + } + /* else do the same stuff as for T_SubLink et al. */ + /* FALL THROUGH */ + } + + case T_SubLink: + case T_NullTest: + case T_BooleanTest: + case T_DistinctExpr: + switch (nodeTag(parentNode)) + { + case T_FuncExpr: + { + /* special handling for casts */ + CoercionForm type = ((FuncExpr *) parentNode)->funcformat; + + if (type == COERCE_EXPLICIT_CAST || + type == COERCE_IMPLICIT_CAST) + return false; + return true; /* own parentheses */ + } + case T_BoolExpr: /* lower precedence */ + case T_ArrayRef: /* other separators */ + case T_ArrayExpr: /* other separators */ + case T_RowExpr: /* other separators */ + case T_CoalesceExpr: /* own parentheses */ + case T_MinMaxExpr: /* own parentheses */ + case T_XmlExpr: /* own parentheses */ + case T_NullIfExpr: /* other separators */ + case T_Aggref: /* own parentheses */ + case T_WindowFunc: /* own parentheses */ + case T_CaseExpr: /* other separators */ + return true; + default: + return false; + } + + case T_BoolExpr: + switch (nodeTag(parentNode)) + { + case T_BoolExpr: + if (prettyFlags & PRETTYFLAG_PAREN) + { + BoolExprType type; + BoolExprType parentType; + + type = ((BoolExpr *) node)->boolop; + parentType = ((BoolExpr *) parentNode)->boolop; + switch (type) + { + case NOT_EXPR: + case AND_EXPR: + if (parentType == AND_EXPR || parentType == OR_EXPR) + return true; + break; + case OR_EXPR: + if (parentType == OR_EXPR) + return true; + break; + } + } + return false; + case T_FuncExpr: + { + /* special handling for casts */ + CoercionForm type = ((FuncExpr *) parentNode)->funcformat; + + if (type == COERCE_EXPLICIT_CAST || + type == COERCE_IMPLICIT_CAST) + return false; + return true; /* own parentheses */ + } + case T_ArrayRef: /* other separators */ + case T_ArrayExpr: /* other separators */ + case T_RowExpr: /* other separators */ + case T_CoalesceExpr: /* own parentheses */ + case T_MinMaxExpr: /* own parentheses */ + case T_XmlExpr: /* own parentheses */ + case T_NullIfExpr: /* other separators */ + case T_Aggref: /* own parentheses */ + case T_WindowFunc: /* own parentheses */ + case T_CaseExpr: /* other separators */ + return true; + default: + return false; + } + + default: + break; + } + /* those we don't know: in dubio complexo */ + return false; +} + + +/* + * appendContextKeyword - append a keyword to buffer + * + * If prettyPrint is enabled, perform a line break, and adjust indentation. + * Otherwise, just append the keyword. + */ +static void +appendContextKeyword(deparse_context *context, const char *str, + int indentBefore, int indentAfter, int indentPlus) +{ + StringInfo buf = context->buf; + + if (PRETTY_INDENT(context)) + { + int indentAmount; + + context->indentLevel += indentBefore; + + /* remove any trailing spaces currently in the buffer ... */ + removeStringInfoSpaces(buf); + /* ... then add a newline and some spaces */ + appendStringInfoChar(buf, '\n'); + + if (context->indentLevel < PRETTYINDENT_LIMIT) + indentAmount = Max(context->indentLevel, 0) + indentPlus; + else + { + /* + * If we're indented more than PRETTYINDENT_LIMIT characters, try + * to conserve horizontal space by reducing the per-level + * indentation. For best results the scale factor here should + * divide all the indent amounts that get added to indentLevel + * (PRETTYINDENT_STD, etc). It's important that the indentation + * not grow unboundedly, else deeply-nested trees use O(N^2) + * whitespace; so we also wrap modulo PRETTYINDENT_LIMIT. + */ + indentAmount = PRETTYINDENT_LIMIT + + (context->indentLevel - PRETTYINDENT_LIMIT) / + (PRETTYINDENT_STD / 2); + indentAmount %= PRETTYINDENT_LIMIT; + /* scale/wrap logic affects indentLevel, but not indentPlus */ + indentAmount += indentPlus; + } + appendStringInfoSpaces(buf, indentAmount); + + appendStringInfoString(buf, str); + + context->indentLevel += indentAfter; + if (context->indentLevel < 0) + context->indentLevel = 0; + } + else + appendStringInfoString(buf, str); +} + +/* + * removeStringInfoSpaces - delete trailing spaces from a buffer. + * + * Possibly this should move to stringinfo.c at some point. + */ +static void +removeStringInfoSpaces(StringInfo str) +{ + while (str->len > 0 && str->data[str->len - 1] == ' ') + str->data[--(str->len)] = '\0'; +} + + +/* + * get_rule_expr_paren - deparse expr using get_rule_expr, + * embracing the string with parentheses if necessary for prettyPrint. + * + * Never embrace if prettyFlags=0, because it's done in the calling node. + * + * Any node that does *not* embrace its argument node by sql syntax (with + * parentheses, non-operator keywords like CASE/WHEN/ON, or comma etc) should + * use get_rule_expr_paren instead of get_rule_expr so parentheses can be + * added. + */ +static void +get_rule_expr_paren(Node *node, deparse_context *context, + bool showimplicit, Node *parentNode) +{ + bool need_paren; + + need_paren = PRETTY_PAREN(context) && + !isSimpleNode(node, parentNode, context->prettyFlags); + + if (need_paren) + appendStringInfoChar(context->buf, '('); + + get_rule_expr(node, context, showimplicit); + + if (need_paren) + appendStringInfoChar(context->buf, ')'); +} + + +/* ---------- + * get_rule_expr - Parse back an expression + * + * Note: showimplicit determines whether we display any implicit cast that + * is present at the top of the expression tree. It is a passed argument, + * not a field of the context struct, because we change the value as we + * recurse down into the expression. In general we suppress implicit casts + * when the result type is known with certainty (eg, the arguments of an + * OR must be boolean). We display implicit casts for arguments of functions + * and operators, since this is needed to be certain that the same function + * or operator will be chosen when the expression is re-parsed. + * ---------- + */ +static void +get_rule_expr(Node *node, deparse_context *context, + bool showimplicit) +{ + StringInfo buf = context->buf; + + if (node == NULL) + return; + + /* Guard against excessively long or deeply-nested queries */ + CHECK_FOR_INTERRUPTS(); + check_stack_depth(); + + /* + * Each level of get_rule_expr must emit an indivisible term + * (parenthesized if necessary) to ensure result is reparsed into the same + * expression tree. The only exception is that when the input is a List, + * we emit the component items comma-separated with no surrounding + * decoration; this is convenient for most callers. + */ + switch (nodeTag(node)) + { + case T_Var: + (void) get_variable((Var *) node, 0, false, context); + break; + + case T_Const: + get_const_expr((Const *) node, context, 0); + break; + + case T_Param: + get_parameter((Param *) node, context); + break; + + case T_Aggref: + get_agg_expr((Aggref *) node, context); + break; + + case T_WindowFunc: + get_windowfunc_expr((WindowFunc *) node, context); + break; + + case T_ArrayRef: + { + ArrayRef *aref = (ArrayRef *) node; + bool need_parens; + + /* + * If the argument is a CaseTestExpr, we must be inside a + * FieldStore, ie, we are assigning to an element of an array + * within a composite column. Since we already punted on + * displaying the FieldStore's target information, just punt + * here too, and display only the assignment source + * expression. + */ + if (IsA(aref->refexpr, CaseTestExpr)) + { + Assert(aref->refassgnexpr); + get_rule_expr((Node *) aref->refassgnexpr, + context, showimplicit); + break; + } + + /* + * Parenthesize the argument unless it's a simple Var or a + * FieldSelect. (In particular, if it's another ArrayRef, we + * *must* parenthesize to avoid confusion.) + */ + need_parens = !IsA(aref->refexpr, Var) && + !IsA(aref->refexpr, FieldSelect); + if (need_parens) + appendStringInfoChar(buf, '('); + get_rule_expr((Node *) aref->refexpr, context, showimplicit); + if (need_parens) + appendStringInfoChar(buf, ')'); + + /* + * If there's a refassgnexpr, we want to print the node in the + * format "array[subscripts] := refassgnexpr". This is not + * legal SQL, so decompilation of INSERT or UPDATE statements + * should always use processIndirection as part of the + * statement-level syntax. We should only see this when + * EXPLAIN tries to print the targetlist of a plan resulting + * from such a statement. + */ + if (aref->refassgnexpr) + { + Node *refassgnexpr; + + /* + * Use processIndirection to print this node's subscripts + * as well as any additional field selections or + * subscripting in immediate descendants. It returns the + * RHS expr that is actually being "assigned". + */ + refassgnexpr = processIndirection(node, context, true); + appendStringInfoString(buf, " := "); + get_rule_expr(refassgnexpr, context, showimplicit); + } + else + { + /* Just an ordinary array fetch, so print subscripts */ + printSubscripts(aref, context); + } + } + break; + + case T_FuncExpr: + get_func_expr((FuncExpr *) node, context, showimplicit); + break; + + case T_NamedArgExpr: + { + NamedArgExpr *na = (NamedArgExpr *) node; + + appendStringInfo(buf, "%s := ", quote_identifier(na->name)); + get_rule_expr((Node *) na->arg, context, showimplicit); + } + break; + + case T_OpExpr: + get_oper_expr((OpExpr *) node, context); + break; + + case T_DistinctExpr: + { + DistinctExpr *expr = (DistinctExpr *) node; + List *args = expr->args; + Node *arg1 = (Node *) linitial(args); + Node *arg2 = (Node *) lsecond(args); + + if (!PRETTY_PAREN(context)) + appendStringInfoChar(buf, '('); + get_rule_expr_paren(arg1, context, true, node); + appendStringInfoString(buf, " IS DISTINCT FROM "); + get_rule_expr_paren(arg2, context, true, node); + if (!PRETTY_PAREN(context)) + appendStringInfoChar(buf, ')'); + } + break; + + case T_NullIfExpr: + { + NullIfExpr *nullifexpr = (NullIfExpr *) node; + + appendStringInfoString(buf, "NULLIF("); + get_rule_expr((Node *) nullifexpr->args, context, true); + appendStringInfoChar(buf, ')'); + } + break; + + case T_ScalarArrayOpExpr: + { + ScalarArrayOpExpr *expr = (ScalarArrayOpExpr *) node; + List *args = expr->args; + Node *arg1 = (Node *) linitial(args); + Node *arg2 = (Node *) lsecond(args); + + if (!PRETTY_PAREN(context)) + appendStringInfoChar(buf, '('); + get_rule_expr_paren(arg1, context, true, node); + appendStringInfo(buf, " %s %s (", + generate_operator_name(expr->opno, + exprType(arg1), + get_base_element_type(exprType(arg2))), + expr->useOr ? "ANY" : "ALL"); + get_rule_expr_paren(arg2, context, true, node); + appendStringInfoChar(buf, ')'); + if (!PRETTY_PAREN(context)) + appendStringInfoChar(buf, ')'); + } + break; + + case T_BoolExpr: + { + BoolExpr *expr = (BoolExpr *) node; + Node *first_arg = linitial(expr->args); + ListCell *arg = lnext(list_head(expr->args)); + + switch (expr->boolop) + { + case AND_EXPR: + if (!PRETTY_PAREN(context)) + appendStringInfoChar(buf, '('); + get_rule_expr_paren(first_arg, context, + false, node); + while (arg) + { + appendStringInfoString(buf, " AND "); + get_rule_expr_paren((Node *) lfirst(arg), context, + false, node); + arg = lnext(arg); + } + if (!PRETTY_PAREN(context)) + appendStringInfoChar(buf, ')'); + break; + + case OR_EXPR: + if (!PRETTY_PAREN(context)) + appendStringInfoChar(buf, '('); + get_rule_expr_paren(first_arg, context, + false, node); + while (arg) + { + appendStringInfoString(buf, " OR "); + get_rule_expr_paren((Node *) lfirst(arg), context, + false, node); + arg = lnext(arg); + } + if (!PRETTY_PAREN(context)) + appendStringInfoChar(buf, ')'); + break; + + case NOT_EXPR: + if (!PRETTY_PAREN(context)) + appendStringInfoChar(buf, '('); + appendStringInfoString(buf, "NOT "); + get_rule_expr_paren(first_arg, context, + false, node); + if (!PRETTY_PAREN(context)) + appendStringInfoChar(buf, ')'); + break; + + default: + elog(ERROR, "unrecognized boolop: %d", + (int) expr->boolop); + } + } + break; + + case T_SubLink: + get_sublink_expr((SubLink *) node, context); + break; + + case T_SubPlan: + { + SubPlan *subplan = (SubPlan *) node; + + /* + * We cannot see an already-planned subplan in rule deparsing, + * only while EXPLAINing a query plan. We don't try to + * reconstruct the original SQL, just reference the subplan + * that appears elsewhere in EXPLAIN's result. + */ + if (subplan->useHashTable) + appendStringInfo(buf, "(hashed %s)", subplan->plan_name); + else + appendStringInfo(buf, "(%s)", subplan->plan_name); + } + break; + + case T_AlternativeSubPlan: + { + AlternativeSubPlan *asplan = (AlternativeSubPlan *) node; + ListCell *lc; + + /* As above, this can only happen during EXPLAIN */ + appendStringInfoString(buf, "(alternatives: "); + foreach(lc, asplan->subplans) + { + SubPlan *splan = (SubPlan *) lfirst(lc); + + Assert(IsA(splan, SubPlan)); + if (splan->useHashTable) + appendStringInfo(buf, "hashed %s", splan->plan_name); + else + appendStringInfoString(buf, splan->plan_name); + if (lnext(lc)) + appendStringInfoString(buf, " or "); + } + appendStringInfoChar(buf, ')'); + } + break; + + case T_FieldSelect: + { + FieldSelect *fselect = (FieldSelect *) node; + Node *arg = (Node *) fselect->arg; + int fno = fselect->fieldnum; + const char *fieldname; + bool need_parens; + + /* + * Parenthesize the argument unless it's an ArrayRef or + * another FieldSelect. Note in particular that it would be + * WRONG to not parenthesize a Var argument; simplicity is not + * the issue here, having the right number of names is. + */ + need_parens = !IsA(arg, ArrayRef) &&!IsA(arg, FieldSelect); + if (need_parens) + appendStringInfoChar(buf, '('); + get_rule_expr(arg, context, true); + if (need_parens) + appendStringInfoChar(buf, ')'); + + /* + * Get and print the field name. + */ + fieldname = get_name_for_var_field((Var *) arg, fno, + 0, context); + appendStringInfo(buf, ".%s", quote_identifier(fieldname)); + } + break; + + case T_FieldStore: + { + FieldStore *fstore = (FieldStore *) node; + bool need_parens; + + /* + * There is no good way to represent a FieldStore as real SQL, + * so decompilation of INSERT or UPDATE statements should + * always use processIndirection as part of the + * statement-level syntax. We should only get here when + * EXPLAIN tries to print the targetlist of a plan resulting + * from such a statement. The plan case is even harder than + * ordinary rules would be, because the planner tries to + * collapse multiple assignments to the same field or subfield + * into one FieldStore; so we can see a list of target fields + * not just one, and the arguments could be FieldStores + * themselves. We don't bother to try to print the target + * field names; we just print the source arguments, with a + * ROW() around them if there's more than one. This isn't + * terribly complete, but it's probably good enough for + * EXPLAIN's purposes; especially since anything more would be + * either hopelessly confusing or an even poorer + * representation of what the plan is actually doing. + */ + need_parens = (list_length(fstore->newvals) != 1); + if (need_parens) + appendStringInfoString(buf, "ROW("); + get_rule_expr((Node *) fstore->newvals, context, showimplicit); + if (need_parens) + appendStringInfoChar(buf, ')'); + } + break; + + case T_RelabelType: + { + RelabelType *relabel = (RelabelType *) node; + Node *arg = (Node *) relabel->arg; + + if (relabel->relabelformat == COERCE_IMPLICIT_CAST && + !showimplicit) + { + /* don't show the implicit cast */ + get_rule_expr_paren(arg, context, false, node); + } + else + { + get_coercion_expr(arg, context, + relabel->resulttype, + relabel->resulttypmod, + node); + } + } + break; + + case T_CoerceViaIO: + { + CoerceViaIO *iocoerce = (CoerceViaIO *) node; + Node *arg = (Node *) iocoerce->arg; + + if (iocoerce->coerceformat == COERCE_IMPLICIT_CAST && + !showimplicit) + { + /* don't show the implicit cast */ + get_rule_expr_paren(arg, context, false, node); + } + else + { + get_coercion_expr(arg, context, + iocoerce->resulttype, + -1, + node); + } + } + break; + + case T_ArrayCoerceExpr: + { + ArrayCoerceExpr *acoerce = (ArrayCoerceExpr *) node; + Node *arg = (Node *) acoerce->arg; + + if (acoerce->coerceformat == COERCE_IMPLICIT_CAST && + !showimplicit) + { + /* don't show the implicit cast */ + get_rule_expr_paren(arg, context, false, node); + } + else + { + get_coercion_expr(arg, context, + acoerce->resulttype, + acoerce->resulttypmod, + node); + } + } + break; + + case T_ConvertRowtypeExpr: + { + ConvertRowtypeExpr *convert = (ConvertRowtypeExpr *) node; + Node *arg = (Node *) convert->arg; + + if (convert->convertformat == COERCE_IMPLICIT_CAST && + !showimplicit) + { + /* don't show the implicit cast */ + get_rule_expr_paren(arg, context, false, node); + } + else + { + get_coercion_expr(arg, context, + convert->resulttype, -1, + node); + } + } + break; + + case T_CollateExpr: + { + CollateExpr *collate = (CollateExpr *) node; + Node *arg = (Node *) collate->arg; + + if (!PRETTY_PAREN(context)) + appendStringInfoChar(buf, '('); + get_rule_expr_paren(arg, context, showimplicit, node); + appendStringInfo(buf, " COLLATE %s", + generate_collation_name(collate->collOid)); + if (!PRETTY_PAREN(context)) + appendStringInfoChar(buf, ')'); + } + break; + + case T_CaseExpr: + { + CaseExpr *caseexpr = (CaseExpr *) node; + ListCell *temp; + + appendContextKeyword(context, "CASE", + 0, PRETTYINDENT_VAR, 0); + if (caseexpr->arg) + { + appendStringInfoChar(buf, ' '); + get_rule_expr((Node *) caseexpr->arg, context, true); + } + foreach(temp, caseexpr->args) + { + CaseWhen *when = (CaseWhen *) lfirst(temp); + Node *w = (Node *) when->expr; + + if (caseexpr->arg) + { + /* + * The parser should have produced WHEN clauses of the + * form "CaseTestExpr = RHS", possibly with an + * implicit coercion inserted above the CaseTestExpr. + * For accurate decompilation of rules it's essential + * that we show just the RHS. However in an + * expression that's been through the optimizer, the + * WHEN clause could be almost anything (since the + * equality operator could have been expanded into an + * inline function). If we don't recognize the form + * of the WHEN clause, just punt and display it as-is. + */ + if (IsA(w, OpExpr)) + { + List *args = ((OpExpr *) w)->args; + + if (list_length(args) == 2 && + IsA(strip_implicit_coercions(linitial(args)), + CaseTestExpr)) + w = (Node *) lsecond(args); + } + } + + if (!PRETTY_INDENT(context)) + appendStringInfoChar(buf, ' '); + appendContextKeyword(context, "WHEN ", + 0, 0, 0); + get_rule_expr(w, context, false); + appendStringInfoString(buf, " THEN "); + get_rule_expr((Node *) when->result, context, true); + } + if (!PRETTY_INDENT(context)) + appendStringInfoChar(buf, ' '); + appendContextKeyword(context, "ELSE ", + 0, 0, 0); + get_rule_expr((Node *) caseexpr->defresult, context, true); + if (!PRETTY_INDENT(context)) + appendStringInfoChar(buf, ' '); + appendContextKeyword(context, "END", + -PRETTYINDENT_VAR, 0, 0); + } + break; + + case T_CaseTestExpr: + { + /* + * Normally we should never get here, since for expressions + * that can contain this node type we attempt to avoid + * recursing to it. But in an optimized expression we might + * be unable to avoid that (see comments for CaseExpr). If we + * do see one, print it as CASE_TEST_EXPR. + */ + appendStringInfoString(buf, "CASE_TEST_EXPR"); + } + break; + + case T_ArrayExpr: + { + ArrayExpr *arrayexpr = (ArrayExpr *) node; + + appendStringInfoString(buf, "ARRAY["); + get_rule_expr((Node *) arrayexpr->elements, context, true); + appendStringInfoChar(buf, ']'); + + /* + * If the array isn't empty, we assume its elements are + * coerced to the desired type. If it's empty, though, we + * need an explicit coercion to the array type. + */ + if (arrayexpr->elements == NIL) + appendStringInfo(buf, "::%s", + format_type_with_typemod(arrayexpr->array_typeid, -1)); + } + break; + + case T_RowExpr: + { + RowExpr *rowexpr = (RowExpr *) node; + TupleDesc tupdesc = NULL; + ListCell *arg; + int i; + char *sep; + + /* + * If it's a named type and not RECORD, we may have to skip + * dropped columns and/or claim there are NULLs for added + * columns. + */ + if (rowexpr->row_typeid != RECORDOID) + { + tupdesc = lookup_rowtype_tupdesc(rowexpr->row_typeid, -1); + Assert(list_length(rowexpr->args) <= tupdesc->natts); + } + + /* + * SQL99 allows "ROW" to be omitted when there is more than + * one column, but for simplicity we always print it. + */ + appendStringInfoString(buf, "ROW("); + sep = ""; + i = 0; + foreach(arg, rowexpr->args) + { + Node *e = (Node *) lfirst(arg); + + if (tupdesc == NULL || + !tupdesc->attrs[i]->attisdropped) + { + appendStringInfoString(buf, sep); + get_rule_expr(e, context, true); + sep = ", "; + } + i++; + } + if (tupdesc != NULL) + { + while (i < tupdesc->natts) + { + if (!tupdesc->attrs[i]->attisdropped) + { + appendStringInfoString(buf, sep); + appendStringInfoString(buf, "NULL"); + sep = ", "; + } + i++; + } + + ReleaseTupleDesc(tupdesc); + } + appendStringInfoChar(buf, ')'); + if (rowexpr->row_format == COERCE_EXPLICIT_CAST) + appendStringInfo(buf, "::%s", + format_type_with_typemod(rowexpr->row_typeid, -1)); + } + break; + + case T_RowCompareExpr: + { + RowCompareExpr *rcexpr = (RowCompareExpr *) node; + ListCell *arg; + char *sep; + + /* + * SQL99 allows "ROW" to be omitted when there is more than + * one column, but for simplicity we always print it. + */ + appendStringInfoString(buf, "(ROW("); + sep = ""; + foreach(arg, rcexpr->largs) + { + Node *e = (Node *) lfirst(arg); + + appendStringInfoString(buf, sep); + get_rule_expr(e, context, true); + sep = ", "; + } + + /* + * We assume that the name of the first-column operator will + * do for all the rest too. This is definitely open to + * failure, eg if some but not all operators were renamed + * since the construct was parsed, but there seems no way to + * be perfect. + */ + appendStringInfo(buf, ") %s ROW(", + generate_operator_name(linitial_oid(rcexpr->opnos), + exprType(linitial(rcexpr->largs)), + exprType(linitial(rcexpr->rargs)))); + sep = ""; + foreach(arg, rcexpr->rargs) + { + Node *e = (Node *) lfirst(arg); + + appendStringInfoString(buf, sep); + get_rule_expr(e, context, true); + sep = ", "; + } + appendStringInfoString(buf, "))"); + } + break; + + case T_CoalesceExpr: + { + CoalesceExpr *coalesceexpr = (CoalesceExpr *) node; + + appendStringInfoString(buf, "COALESCE("); + get_rule_expr((Node *) coalesceexpr->args, context, true); + appendStringInfoChar(buf, ')'); + } + break; + + case T_MinMaxExpr: + { + MinMaxExpr *minmaxexpr = (MinMaxExpr *) node; + + switch (minmaxexpr->op) + { + case IS_GREATEST: + appendStringInfoString(buf, "GREATEST("); + break; + case IS_LEAST: + appendStringInfoString(buf, "LEAST("); + break; + } + get_rule_expr((Node *) minmaxexpr->args, context, true); + appendStringInfoChar(buf, ')'); + } + break; + + case T_XmlExpr: + { + XmlExpr *xexpr = (XmlExpr *) node; + bool needcomma = false; + ListCell *arg; + ListCell *narg; + Const *con; + + switch (xexpr->op) + { + case IS_XMLCONCAT: + appendStringInfoString(buf, "XMLCONCAT("); + break; + case IS_XMLELEMENT: + appendStringInfoString(buf, "XMLELEMENT("); + break; + case IS_XMLFOREST: + appendStringInfoString(buf, "XMLFOREST("); + break; + case IS_XMLPARSE: + appendStringInfoString(buf, "XMLPARSE("); + break; + case IS_XMLPI: + appendStringInfoString(buf, "XMLPI("); + break; + case IS_XMLROOT: + appendStringInfoString(buf, "XMLROOT("); + break; + case IS_XMLSERIALIZE: + appendStringInfoString(buf, "XMLSERIALIZE("); + break; + case IS_DOCUMENT: + break; + } + if (xexpr->op == IS_XMLPARSE || xexpr->op == IS_XMLSERIALIZE) + { + if (xexpr->xmloption == XMLOPTION_DOCUMENT) + appendStringInfoString(buf, "DOCUMENT "); + else + appendStringInfoString(buf, "CONTENT "); + } + if (xexpr->name) + { + appendStringInfo(buf, "NAME %s", + quote_identifier(map_xml_name_to_sql_identifier(xexpr->name))); + needcomma = true; + } + if (xexpr->named_args) + { + if (xexpr->op != IS_XMLFOREST) + { + if (needcomma) + appendStringInfoString(buf, ", "); + appendStringInfoString(buf, "XMLATTRIBUTES("); + needcomma = false; + } + forboth(arg, xexpr->named_args, narg, xexpr->arg_names) + { + Node *e = (Node *) lfirst(arg); + char *argname = strVal(lfirst(narg)); + + if (needcomma) + appendStringInfoString(buf, ", "); + get_rule_expr((Node *) e, context, true); + appendStringInfo(buf, " AS %s", + quote_identifier(map_xml_name_to_sql_identifier(argname))); + needcomma = true; + } + if (xexpr->op != IS_XMLFOREST) + appendStringInfoChar(buf, ')'); + } + if (xexpr->args) + { + if (needcomma) + appendStringInfoString(buf, ", "); + switch (xexpr->op) + { + case IS_XMLCONCAT: + case IS_XMLELEMENT: + case IS_XMLFOREST: + case IS_XMLPI: + case IS_XMLSERIALIZE: + /* no extra decoration needed */ + get_rule_expr((Node *) xexpr->args, context, true); + break; + case IS_XMLPARSE: + Assert(list_length(xexpr->args) == 2); + + get_rule_expr((Node *) linitial(xexpr->args), + context, true); + + con = (Const *) lsecond(xexpr->args); + Assert(IsA(con, Const)); + Assert(!con->constisnull); + if (DatumGetBool(con->constvalue)) + appendStringInfoString(buf, + " PRESERVE WHITESPACE"); + else + appendStringInfoString(buf, + " STRIP WHITESPACE"); + break; + case IS_XMLROOT: + Assert(list_length(xexpr->args) == 3); + + get_rule_expr((Node *) linitial(xexpr->args), + context, true); + + appendStringInfoString(buf, ", VERSION "); + con = (Const *) lsecond(xexpr->args); + if (IsA(con, Const) && + con->constisnull) + appendStringInfoString(buf, "NO VALUE"); + else + get_rule_expr((Node *) con, context, false); + + con = (Const *) lthird(xexpr->args); + Assert(IsA(con, Const)); + if (con->constisnull) + /* suppress STANDALONE NO VALUE */ ; + else + { + switch (DatumGetInt32(con->constvalue)) + { + case XML_STANDALONE_YES: + appendStringInfoString(buf, + ", STANDALONE YES"); + break; + case XML_STANDALONE_NO: + appendStringInfoString(buf, + ", STANDALONE NO"); + break; + case XML_STANDALONE_NO_VALUE: + appendStringInfoString(buf, + ", STANDALONE NO VALUE"); + break; + default: + break; + } + } + break; + case IS_DOCUMENT: + get_rule_expr_paren((Node *) xexpr->args, context, false, node); + break; + } + + } + if (xexpr->op == IS_XMLSERIALIZE) + appendStringInfo(buf, " AS %s", + format_type_with_typemod(xexpr->type, + xexpr->typmod)); + if (xexpr->op == IS_DOCUMENT) + appendStringInfoString(buf, " IS DOCUMENT"); + else + appendStringInfoChar(buf, ')'); + } + break; + + case T_NullTest: + { + NullTest *ntest = (NullTest *) node; + + if (!PRETTY_PAREN(context)) + appendStringInfoChar(buf, '('); + get_rule_expr_paren((Node *) ntest->arg, context, true, node); + switch (ntest->nulltesttype) + { + case IS_NULL: + appendStringInfoString(buf, " IS NULL"); + break; + case IS_NOT_NULL: + appendStringInfoString(buf, " IS NOT NULL"); + break; + default: + elog(ERROR, "unrecognized nulltesttype: %d", + (int) ntest->nulltesttype); + } + if (!PRETTY_PAREN(context)) + appendStringInfoChar(buf, ')'); + } + break; + + case T_BooleanTest: + { + BooleanTest *btest = (BooleanTest *) node; + + if (!PRETTY_PAREN(context)) + appendStringInfoChar(buf, '('); + get_rule_expr_paren((Node *) btest->arg, context, false, node); + switch (btest->booltesttype) + { + case IS_TRUE: + appendStringInfoString(buf, " IS TRUE"); + break; + case IS_NOT_TRUE: + appendStringInfoString(buf, " IS NOT TRUE"); + break; + case IS_FALSE: + appendStringInfoString(buf, " IS FALSE"); + break; + case IS_NOT_FALSE: + appendStringInfoString(buf, " IS NOT FALSE"); + break; + case IS_UNKNOWN: + appendStringInfoString(buf, " IS UNKNOWN"); + break; + case IS_NOT_UNKNOWN: + appendStringInfoString(buf, " IS NOT UNKNOWN"); + break; + default: + elog(ERROR, "unrecognized booltesttype: %d", + (int) btest->booltesttype); + } + if (!PRETTY_PAREN(context)) + appendStringInfoChar(buf, ')'); + } + break; + + case T_CoerceToDomain: + { + CoerceToDomain *ctest = (CoerceToDomain *) node; + Node *arg = (Node *) ctest->arg; + + if (ctest->coercionformat == COERCE_IMPLICIT_CAST && + !showimplicit) + { + /* don't show the implicit cast */ + get_rule_expr(arg, context, false); + } + else + { + get_coercion_expr(arg, context, + ctest->resulttype, + ctest->resulttypmod, + node); + } + } + break; + + case T_CoerceToDomainValue: + appendStringInfoString(buf, "VALUE"); + break; + + case T_SetToDefault: + appendStringInfoString(buf, "DEFAULT"); + break; + + case T_CurrentOfExpr: + { + CurrentOfExpr *cexpr = (CurrentOfExpr *) node; + + if (cexpr->cursor_name) + appendStringInfo(buf, "CURRENT OF %s", + quote_identifier(cexpr->cursor_name)); + else + appendStringInfo(buf, "CURRENT OF $%d", + cexpr->cursor_param); + } + break; + + case T_List: + { + char *sep; + ListCell *l; + + sep = ""; + foreach(l, (List *) node) + { + appendStringInfoString(buf, sep); + get_rule_expr((Node *) lfirst(l), context, showimplicit); + sep = ", "; + } + } + break; + + default: + elog(ERROR, "unrecognized node type: %d", (int) nodeTag(node)); + break; + } +} + + +/* + * get_oper_expr - Parse back an OpExpr node + */ +static void +get_oper_expr(OpExpr *expr, deparse_context *context) +{ + StringInfo buf = context->buf; + Oid opno = expr->opno; + List *args = expr->args; + + if (!PRETTY_PAREN(context)) + appendStringInfoChar(buf, '('); + if (list_length(args) == 2) + { + /* binary operator */ + Node *arg1 = (Node *) linitial(args); + Node *arg2 = (Node *) lsecond(args); + + get_rule_expr_paren(arg1, context, true, (Node *) expr); + appendStringInfo(buf, " %s ", + generate_operator_name(opno, + exprType(arg1), + exprType(arg2))); + get_rule_expr_paren(arg2, context, true, (Node *) expr); + } + else + { + /* unary operator --- but which side? */ + Node *arg = (Node *) linitial(args); + HeapTuple tp; + Form_pg_operator optup; + + tp = SearchSysCache1(OPEROID, ObjectIdGetDatum(opno)); + if (!HeapTupleIsValid(tp)) + elog(ERROR, "cache lookup failed for operator %u", opno); + optup = (Form_pg_operator) GETSTRUCT(tp); + switch (optup->oprkind) + { + case 'l': + appendStringInfo(buf, "%s ", + generate_operator_name(opno, + InvalidOid, + exprType(arg))); + get_rule_expr_paren(arg, context, true, (Node *) expr); + break; + case 'r': + get_rule_expr_paren(arg, context, true, (Node *) expr); + appendStringInfo(buf, " %s", + generate_operator_name(opno, + exprType(arg), + InvalidOid)); + break; + default: + elog(ERROR, "bogus oprkind: %d", optup->oprkind); + } + ReleaseSysCache(tp); + } + if (!PRETTY_PAREN(context)) + appendStringInfoChar(buf, ')'); +} + +/* + * get_func_expr - Parse back a FuncExpr node + */ +static void +get_func_expr(FuncExpr *expr, deparse_context *context, + bool showimplicit) +{ + StringInfo buf = context->buf; + Oid funcoid = expr->funcid; + Oid argtypes[FUNC_MAX_ARGS]; + int nargs; + List *argnames; + bool use_variadic; + ListCell *l; + + /* + * If the function call came from an implicit coercion, then just show the + * first argument --- unless caller wants to see implicit coercions. + */ + if (expr->funcformat == COERCE_IMPLICIT_CAST && !showimplicit) + { + get_rule_expr_paren((Node *) linitial(expr->args), context, + false, (Node *) expr); + return; + } + + /* + * If the function call came from a cast, then show the first argument + * plus an explicit cast operation. + */ + if (expr->funcformat == COERCE_EXPLICIT_CAST || + expr->funcformat == COERCE_IMPLICIT_CAST) + { + Node *arg = linitial(expr->args); + Oid rettype = expr->funcresulttype; + int32 coercedTypmod; + + /* Get the typmod if this is a length-coercion function */ + (void) exprIsLengthCoercion((Node *) expr, &coercedTypmod); + + get_coercion_expr(arg, context, + rettype, coercedTypmod, + (Node *) expr); + + return; + } + + /* + * Normal function: display as proname(args). First we need to extract + * the argument datatypes. + */ + if (list_length(expr->args) > FUNC_MAX_ARGS) + ereport(ERROR, + (errcode(ERRCODE_TOO_MANY_ARGUMENTS), + errmsg("too many arguments"))); + nargs = 0; + argnames = NIL; + foreach(l, expr->args) + { + Node *arg = (Node *) lfirst(l); + + if (IsA(arg, NamedArgExpr)) + argnames = lappend(argnames, ((NamedArgExpr *) arg)->name); + argtypes[nargs] = exprType(arg); + nargs++; + } + + appendStringInfo(buf, "%s(", + generate_function_name(funcoid, nargs, + argnames, argtypes, + expr->funcvariadic, + &use_variadic)); + nargs = 0; + foreach(l, expr->args) + { + if (nargs++ > 0) + appendStringInfoString(buf, ", "); + if (use_variadic && lnext(l) == NULL) + appendStringInfoString(buf, "VARIADIC "); + get_rule_expr((Node *) lfirst(l), context, true); + } + appendStringInfoChar(buf, ')'); +} + +/* + * get_agg_expr - Parse back an Aggref node + */ +static void +get_agg_expr(Aggref *aggref, deparse_context *context) +{ + StringInfo buf = context->buf; + Oid argtypes[FUNC_MAX_ARGS]; + int nargs; + bool use_variadic; + + /* Extract the argument types as seen by the parser */ + nargs = get_aggregate_argtypes(aggref, argtypes); + + /* Print the aggregate name, schema-qualified if needed */ + appendStringInfo(buf, "%s(%s", + generate_function_name(aggref->aggfnoid, nargs, + NIL, argtypes, + aggref->aggvariadic, + &use_variadic), + (aggref->aggdistinct != NIL) ? "DISTINCT " : ""); + + if (AGGKIND_IS_ORDERED_SET(aggref->aggkind)) + { + /* + * Ordered-set aggregates do not use "*" syntax. Also, we needn't + * worry about inserting VARIADIC. So we can just dump the direct + * args as-is. + */ + Assert(!aggref->aggvariadic); + get_rule_expr((Node *) aggref->aggdirectargs, context, true); + Assert(aggref->aggorder != NIL); + appendStringInfoString(buf, ") WITHIN GROUP (ORDER BY "); + get_rule_orderby(aggref->aggorder, aggref->args, false, context); + } + else + { + /* aggstar can be set only in zero-argument aggregates */ + if (aggref->aggstar) + appendStringInfoChar(buf, '*'); + else + { + ListCell *l; + int i; + + i = 0; + foreach(l, aggref->args) + { + TargetEntry *tle = (TargetEntry *) lfirst(l); + Node *arg = (Node *) tle->expr; + + Assert(!IsA(arg, NamedArgExpr)); + if (tle->resjunk) + continue; + if (i++ > 0) + appendStringInfoString(buf, ", "); + if (use_variadic && i == nargs) + appendStringInfoString(buf, "VARIADIC "); + get_rule_expr(arg, context, true); + } + } + + if (aggref->aggorder != NIL) + { + appendStringInfoString(buf, " ORDER BY "); + get_rule_orderby(aggref->aggorder, aggref->args, false, context); + } + } + + if (aggref->aggfilter != NULL) + { + appendStringInfoString(buf, ") FILTER (WHERE "); + get_rule_expr((Node *) aggref->aggfilter, context, false); + } + + appendStringInfoChar(buf, ')'); +} + +/* + * get_windowfunc_expr - Parse back a WindowFunc node + */ +static void +get_windowfunc_expr(WindowFunc *wfunc, deparse_context *context) +{ + StringInfo buf = context->buf; + Oid argtypes[FUNC_MAX_ARGS]; + int nargs; + List *argnames; + ListCell *l; + + if (list_length(wfunc->args) > FUNC_MAX_ARGS) + ereport(ERROR, + (errcode(ERRCODE_TOO_MANY_ARGUMENTS), + errmsg("too many arguments"))); + nargs = 0; + argnames = NIL; + foreach(l, wfunc->args) + { + Node *arg = (Node *) lfirst(l); + + if (IsA(arg, NamedArgExpr)) + argnames = lappend(argnames, ((NamedArgExpr *) arg)->name); + argtypes[nargs] = exprType(arg); + nargs++; + } + + appendStringInfo(buf, "%s(", + generate_function_name(wfunc->winfnoid, nargs, + argnames, argtypes, + false, NULL)); + /* winstar can be set only in zero-argument aggregates */ + if (wfunc->winstar) + appendStringInfoChar(buf, '*'); + else + get_rule_expr((Node *) wfunc->args, context, true); + + if (wfunc->aggfilter != NULL) + { + appendStringInfoString(buf, ") FILTER (WHERE "); + get_rule_expr((Node *) wfunc->aggfilter, context, false); + } + + appendStringInfoString(buf, ") OVER "); + + foreach(l, context->windowClause) + { + WindowClause *wc = (WindowClause *) lfirst(l); + + if (wc->winref == wfunc->winref) + { + if (wc->name) + appendStringInfoString(buf, quote_identifier(wc->name)); + else + get_rule_windowspec(wc, context->windowTList, context); + break; + } + } + if (l == NULL) + { + if (context->windowClause) + elog(ERROR, "could not find window clause for winref %u", + wfunc->winref); + + /* + * In EXPLAIN, we don't have window context information available, so + * we have to settle for this: + */ + appendStringInfoString(buf, "(?)"); + } +} + +/* ---------- + * get_coercion_expr + * + * Make a string representation of a value coerced to a specific type + * ---------- + */ +static void +get_coercion_expr(Node *arg, deparse_context *context, + Oid resulttype, int32 resulttypmod, + Node *parentNode) +{ + StringInfo buf = context->buf; + + /* + * Since parse_coerce.c doesn't immediately collapse application of + * length-coercion functions to constants, what we'll typically see in + * such cases is a Const with typmod -1 and a length-coercion function + * right above it. Avoid generating redundant output. However, beware of + * suppressing casts when the user actually wrote something like + * 'foo'::text::char(3). + */ + if (arg && IsA(arg, Const) && + ((Const *) arg)->consttype == resulttype && + ((Const *) arg)->consttypmod == -1) + { + /* Show the constant without normal ::typename decoration */ + get_const_expr((Const *) arg, context, -1); + } + else + { + if (!PRETTY_PAREN(context)) + appendStringInfoChar(buf, '('); + get_rule_expr_paren(arg, context, false, parentNode); + if (!PRETTY_PAREN(context)) + appendStringInfoChar(buf, ')'); + } + appendStringInfo(buf, "::%s", + format_type_with_typemod(resulttype, resulttypmod)); +} + +/* ---------- + * get_const_expr + * + * Make a string representation of a Const + * + * showtype can be -1 to never show "::typename" decoration, or +1 to always + * show it, or 0 to show it only if the constant wouldn't be assumed to be + * the right type by default. + * + * If the Const's collation isn't default for its type, show that too. + * This can only happen in trees that have been through constant-folding. + * We assume we don't need to do this when showtype is -1. + * ---------- + */ +static void +get_const_expr(Const *constval, deparse_context *context, int showtype) +{ + StringInfo buf = context->buf; + Oid typoutput; + bool typIsVarlena; + char *extval; + bool isfloat = false; + bool needlabel; + + if (constval->constisnull) + { + /* + * Always label the type of a NULL constant to prevent misdecisions + * about type when reparsing. + */ + appendStringInfoString(buf, "NULL"); + if (showtype >= 0) + { + appendStringInfo(buf, "::%s", + format_type_with_typemod(constval->consttype, + constval->consttypmod)); + get_const_collation(constval, context); + } + return; + } + + getTypeOutputInfo(constval->consttype, + &typoutput, &typIsVarlena); + + extval = OidOutputFunctionCall(typoutput, constval->constvalue); + + switch (constval->consttype) + { + case INT2OID: + case INT4OID: + case INT8OID: + case OIDOID: + case FLOAT4OID: + case FLOAT8OID: + case NUMERICOID: + { + /* + * These types are printed without quotes unless they contain + * values that aren't accepted by the scanner unquoted (e.g., + * 'NaN'). Note that strtod() and friends might accept NaN, + * so we can't use that to test. + * + * In reality we only need to defend against infinity and NaN, + * so we need not get too crazy about pattern matching here. + * + * There is a special-case gotcha: if the constant is signed, + * we need to parenthesize it, else the parser might see a + * leading plus/minus as binding less tightly than adjacent + * operators --- particularly, the cast that we might attach + * below. + */ + if (strspn(extval, "0123456789+-eE.") == strlen(extval)) + { + if (extval[0] == '+' || extval[0] == '-') + appendStringInfo(buf, "(%s)", extval); + else + appendStringInfoString(buf, extval); + if (strcspn(extval, "eE.") != strlen(extval)) + isfloat = true; /* it looks like a float */ + } + else + appendStringInfo(buf, "'%s'", extval); + } + break; + + case BITOID: + case VARBITOID: + appendStringInfo(buf, "B'%s'", extval); + break; + + case BOOLOID: + if (strcmp(extval, "t") == 0) + appendStringInfoString(buf, "true"); + else + appendStringInfoString(buf, "false"); + break; + + default: + simple_quote_literal(buf, extval); + break; + } + + pfree(extval); + + if (showtype < 0) + return; + + /* + * For showtype == 0, append ::typename unless the constant will be + * implicitly typed as the right type when it is read in. + * + * XXX this code has to be kept in sync with the behavior of the parser, + * especially make_const. + */ + switch (constval->consttype) + { + case BOOLOID: + case INT4OID: + case UNKNOWNOID: + /* These types can be left unlabeled */ + needlabel = false; + break; + case NUMERICOID: + + /* + * Float-looking constants will be typed as numeric, but if + * there's a specific typmod we need to show it. + */ + needlabel = !isfloat || (constval->consttypmod >= 0); + break; + default: + needlabel = true; + break; + } + if (needlabel || showtype > 0) + appendStringInfo(buf, "::%s", + format_type_with_typemod(constval->consttype, + constval->consttypmod)); + + get_const_collation(constval, context); +} + +/* + * helper for get_const_expr: append COLLATE if needed + */ +static void +get_const_collation(Const *constval, deparse_context *context) +{ + StringInfo buf = context->buf; + + if (OidIsValid(constval->constcollid)) + { + Oid typcollation = get_typcollation(constval->consttype); + + if (constval->constcollid != typcollation) + { + appendStringInfo(buf, " COLLATE %s", + generate_collation_name(constval->constcollid)); + } + } +} + +/* + * simple_quote_literal - Format a string as a SQL literal, append to buf + */ +static void +simple_quote_literal(StringInfo buf, const char *val) +{ + const char *valptr; + + /* + * We form the string literal according to the prevailing setting of + * standard_conforming_strings; we never use E''. User is responsible for + * making sure result is used correctly. + */ + appendStringInfoChar(buf, '\''); + for (valptr = val; *valptr; valptr++) + { + char ch = *valptr; + + if (SQL_STR_DOUBLE(ch, !standard_conforming_strings)) + appendStringInfoChar(buf, ch); + appendStringInfoChar(buf, ch); + } + appendStringInfoChar(buf, '\''); +} + + +/* ---------- + * get_sublink_expr - Parse back a sublink + * ---------- + */ +static void +get_sublink_expr(SubLink *sublink, deparse_context *context) +{ + StringInfo buf = context->buf; + Query *query = (Query *) (sublink->subselect); + char *opname = NULL; + bool need_paren; + + if (sublink->subLinkType == ARRAY_SUBLINK) + appendStringInfoString(buf, "ARRAY("); + else + appendStringInfoChar(buf, '('); + + /* + * Note that we print the name of only the first operator, when there are + * multiple combining operators. This is an approximation that could go + * wrong in various scenarios (operators in different schemas, renamed + * operators, etc) but there is not a whole lot we can do about it, since + * the syntax allows only one operator to be shown. + */ + if (sublink->testexpr) + { + if (IsA(sublink->testexpr, OpExpr)) + { + /* single combining operator */ + OpExpr *opexpr = (OpExpr *) sublink->testexpr; + + get_rule_expr(linitial(opexpr->args), context, true); + opname = generate_operator_name(opexpr->opno, + exprType(linitial(opexpr->args)), + exprType(lsecond(opexpr->args))); + } + else if (IsA(sublink->testexpr, BoolExpr)) + { + /* multiple combining operators, = or <> cases */ + char *sep; + ListCell *l; + + appendStringInfoChar(buf, '('); + sep = ""; + foreach(l, ((BoolExpr *) sublink->testexpr)->args) + { + OpExpr *opexpr = (OpExpr *) lfirst(l); + + Assert(IsA(opexpr, OpExpr)); + appendStringInfoString(buf, sep); + get_rule_expr(linitial(opexpr->args), context, true); + if (!opname) + opname = generate_operator_name(opexpr->opno, + exprType(linitial(opexpr->args)), + exprType(lsecond(opexpr->args))); + sep = ", "; + } + appendStringInfoChar(buf, ')'); + } + else if (IsA(sublink->testexpr, RowCompareExpr)) + { + /* multiple combining operators, < <= > >= cases */ + RowCompareExpr *rcexpr = (RowCompareExpr *) sublink->testexpr; + + appendStringInfoChar(buf, '('); + get_rule_expr((Node *) rcexpr->largs, context, true); + opname = generate_operator_name(linitial_oid(rcexpr->opnos), + exprType(linitial(rcexpr->largs)), + exprType(linitial(rcexpr->rargs))); + appendStringInfoChar(buf, ')'); + } + else + elog(ERROR, "unrecognized testexpr type: %d", + (int) nodeTag(sublink->testexpr)); + } + + need_paren = true; + + switch (sublink->subLinkType) + { + case EXISTS_SUBLINK: + appendStringInfoString(buf, "EXISTS "); + break; + + case ANY_SUBLINK: + if (strcmp(opname, "=") == 0) /* Represent = ANY as IN */ + appendStringInfoString(buf, " IN "); + else + appendStringInfo(buf, " %s ANY ", opname); + break; + + case ALL_SUBLINK: + appendStringInfo(buf, " %s ALL ", opname); + break; + + case ROWCOMPARE_SUBLINK: + appendStringInfo(buf, " %s ", opname); + break; + + case EXPR_SUBLINK: + case ARRAY_SUBLINK: + need_paren = false; + break; + + case CTE_SUBLINK: /* shouldn't occur in a SubLink */ + default: + elog(ERROR, "unrecognized sublink type: %d", + (int) sublink->subLinkType); + break; + } + + if (need_paren) + appendStringInfoChar(buf, '('); + + get_query_def(query, buf, context->namespaces, NULL, + context->prettyFlags, context->wrapColumn, + context->indentLevel); + + if (need_paren) + appendStringInfoString(buf, "))"); + else + appendStringInfoChar(buf, ')'); +} + + +/* ---------- + * get_from_clause - Parse back a FROM clause + * + * "prefix" is the keyword that denotes the start of the list of FROM + * elements. It is FROM when used to parse back SELECT and UPDATE, but + * is USING when parsing back DELETE. + * ---------- + */ +static void +get_from_clause(Query *query, const char *prefix, deparse_context *context) +{ + StringInfo buf = context->buf; + bool first = true; + ListCell *l; + + /* + * We use the query's jointree as a guide to what to print. However, we + * must ignore auto-added RTEs that are marked not inFromCl. (These can + * only appear at the top level of the jointree, so it's sufficient to + * check here.) This check also ensures we ignore the rule pseudo-RTEs + * for NEW and OLD. + */ + foreach(l, query->jointree->fromlist) + { + Node *jtnode = (Node *) lfirst(l); + + if (IsA(jtnode, RangeTblRef)) + { + int varno = ((RangeTblRef *) jtnode)->rtindex; + RangeTblEntry *rte = rt_fetch(varno, query->rtable); + + if (!rte->inFromCl) + continue; + } + + if (first) + { + appendContextKeyword(context, prefix, + -PRETTYINDENT_STD, PRETTYINDENT_STD, 2); + first = false; + + get_from_clause_item(jtnode, query, context); + } + else + { + StringInfoData itembuf; + + appendStringInfoString(buf, ", "); + + /* + * Put the new FROM item's text into itembuf so we can decide + * after we've got it whether or not it needs to go on a new line. + */ + initStringInfo(&itembuf); + context->buf = &itembuf; + + get_from_clause_item(jtnode, query, context); + + /* Restore context's output buffer */ + context->buf = buf; + + /* Consider line-wrapping if enabled */ + if (PRETTY_INDENT(context) && context->wrapColumn >= 0) + { + /* Does the new item start with a new line? */ + if (itembuf.len > 0 && itembuf.data[0] == '\n') + { + /* If so, we shouldn't add anything */ + /* instead, remove any trailing spaces currently in buf */ + removeStringInfoSpaces(buf); + } + else + { + char *trailing_nl; + + /* Locate the start of the current line in the buffer */ + trailing_nl = strrchr(buf->data, '\n'); + if (trailing_nl == NULL) + trailing_nl = buf->data; + else + trailing_nl++; + + /* + * Add a newline, plus some indentation, if the new item + * would cause an overflow. + */ + if (strlen(trailing_nl) + itembuf.len > context->wrapColumn) + appendContextKeyword(context, "", -PRETTYINDENT_STD, + PRETTYINDENT_STD, + PRETTYINDENT_VAR); + } + } + + /* Add the new item */ + appendStringInfoString(buf, itembuf.data); + + /* clean up */ + pfree(itembuf.data); + } + } +} + +static void +get_from_clause_item(Node *jtnode, Query *query, deparse_context *context) +{ + StringInfo buf = context->buf; + deparse_namespace *dpns = (deparse_namespace *) linitial(context->namespaces); + + if (IsA(jtnode, RangeTblRef)) + { + int varno = ((RangeTblRef *) jtnode)->rtindex; + RangeTblEntry *rte = rt_fetch(varno, query->rtable); + char *refname = get_rtable_name(varno, context); + deparse_columns *colinfo = deparse_columns_fetch(varno, dpns); + RangeTblFunction *rtfunc1 = NULL; + bool printalias; + + if (rte->lateral) + appendStringInfoString(buf, "LATERAL "); + + /* Print the FROM item proper */ + switch (rte->rtekind) + { + case RTE_RELATION: + /* Normal relation RTE */ + appendStringInfo(buf, "%s%s", + only_marker(rte), + generate_relation_or_shard_name(rte->relid, + context->distrelid, + context->shardid, + context->namespaces)); + break; + case RTE_SUBQUERY: + /* Subquery RTE */ + appendStringInfoChar(buf, '('); + get_query_def(rte->subquery, buf, context->namespaces, NULL, + context->prettyFlags, context->wrapColumn, + context->indentLevel); + appendStringInfoChar(buf, ')'); + break; + case RTE_FUNCTION: + /* if it's a shard, do differently */ + if (GetRangeTblKind(rte) == CITUS_RTE_SHARD) + { + char *fragmentSchemaName = NULL; + char *fragmentTableName = NULL; + + ExtractRangeTblExtraData(rte, NULL, &fragmentSchemaName, &fragmentTableName, NULL); + + /* Use schema and table name from the remote alias */ + appendStringInfoString(buf, + generate_fragment_name(fragmentSchemaName, + fragmentTableName)); + break; + } + + /* Function RTE */ + rtfunc1 = (RangeTblFunction *) linitial(rte->functions); + + /* + * Omit ROWS FROM() syntax for just one function, unless it + * has both a coldeflist and WITH ORDINALITY. If it has both, + * we must use ROWS FROM() syntax to avoid ambiguity about + * whether the coldeflist includes the ordinality column. + */ + if (list_length(rte->functions) == 1 && + (rtfunc1->funccolnames == NIL || !rte->funcordinality)) + { + get_rule_expr(rtfunc1->funcexpr, context, true); + /* we'll print the coldeflist below, if it has one */ + } + else + { + bool all_unnest; + ListCell *lc; + + /* + * If all the function calls in the list are to unnest, + * and none need a coldeflist, then collapse the list back + * down to UNNEST(args). (If we had more than one + * built-in unnest function, this would get more + * difficult.) + * + * XXX This is pretty ugly, since it makes not-terribly- + * future-proof assumptions about what the parser would do + * with the output; but the alternative is to emit our + * nonstandard ROWS FROM() notation for what might have + * been a perfectly spec-compliant multi-argument + * UNNEST(). + */ + all_unnest = true; + foreach(lc, rte->functions) + { + RangeTblFunction *rtfunc = (RangeTblFunction *) lfirst(lc); + + if (!IsA(rtfunc->funcexpr, FuncExpr) || + ((FuncExpr *) rtfunc->funcexpr)->funcid != F_ARRAY_UNNEST || + rtfunc->funccolnames != NIL) + { + all_unnest = false; + break; + } + } + + if (all_unnest) + { + List *allargs = NIL; + + foreach(lc, rte->functions) + { + RangeTblFunction *rtfunc = (RangeTblFunction *) lfirst(lc); + List *args = ((FuncExpr *) rtfunc->funcexpr)->args; + + allargs = list_concat(allargs, list_copy(args)); + } + + appendStringInfoString(buf, "UNNEST("); + get_rule_expr((Node *) allargs, context, true); + appendStringInfoChar(buf, ')'); + } + else + { + int funcno = 0; + + appendStringInfoString(buf, "ROWS FROM("); + foreach(lc, rte->functions) + { + RangeTblFunction *rtfunc = (RangeTblFunction *) lfirst(lc); + + if (funcno > 0) + appendStringInfoString(buf, ", "); + get_rule_expr(rtfunc->funcexpr, context, true); + if (rtfunc->funccolnames != NIL) + { + /* Reconstruct the column definition list */ + appendStringInfoString(buf, " AS "); + get_from_clause_coldeflist(rtfunc, + NULL, + context); + } + funcno++; + } + appendStringInfoChar(buf, ')'); + } + /* prevent printing duplicate coldeflist below */ + rtfunc1 = NULL; + } + if (rte->funcordinality) + appendStringInfoString(buf, " WITH ORDINALITY"); + break; + case RTE_VALUES: + /* Values list RTE */ + appendStringInfoChar(buf, '('); + get_values_def(rte->values_lists, context); + appendStringInfoChar(buf, ')'); + break; + case RTE_CTE: + appendStringInfoString(buf, quote_identifier(rte->ctename)); + break; + default: + elog(ERROR, "unrecognized RTE kind: %d", (int) rte->rtekind); + break; + } + + /* Print the relation alias, if needed */ + printalias = false; + if (rte->alias != NULL) + { + /* Always print alias if user provided one */ + printalias = true; + } + else if (colinfo->printaliases) + { + /* Always print alias if we need to print column aliases */ + printalias = true; + } + else if (rte->rtekind == RTE_RELATION) + { + /* + * No need to print alias if it's same as relation name (this + * would normally be the case, but not if set_rtable_names had to + * resolve a conflict). + */ + if (strcmp(refname, get_relation_name(rte->relid)) != 0) + printalias = true; + } + else if (rte->rtekind == RTE_FUNCTION) + { + /* + * For a function RTE, always print alias. This covers possible + * renaming of the function and/or instability of the + * FigureColname rules for things that aren't simple functions. + * Note we'd need to force it anyway for the columndef list case. + */ + printalias = true; + } + else if (rte->rtekind == RTE_VALUES) + { + /* Alias is syntactically required for VALUES */ + printalias = true; + } + else if (rte->rtekind == RTE_CTE) + { + /* + * No need to print alias if it's same as CTE name (this would + * normally be the case, but not if set_rtable_names had to + * resolve a conflict). + */ + if (strcmp(refname, rte->ctename) != 0) + printalias = true; + } + if (printalias) + appendStringInfo(buf, " %s", quote_identifier(refname)); + + /* Print the column definitions or aliases, if needed */ + if (rtfunc1 && rtfunc1->funccolnames != NIL) + { + /* Reconstruct the columndef list, which is also the aliases */ + get_from_clause_coldeflist(rtfunc1, colinfo, context); + } + else if (GetRangeTblKind(rte) != CITUS_RTE_SHARD) + { + /* Else print column aliases as needed */ + get_column_alias_list(colinfo, context); + } + } + else if (IsA(jtnode, JoinExpr)) + { + JoinExpr *j = (JoinExpr *) jtnode; + deparse_columns *colinfo = deparse_columns_fetch(j->rtindex, dpns); + bool need_paren_on_right; + + need_paren_on_right = PRETTY_PAREN(context) && + !IsA(j->rarg, RangeTblRef) && + !(IsA(j->rarg, JoinExpr) &&((JoinExpr *) j->rarg)->alias != NULL); + + if (!PRETTY_PAREN(context) || j->alias != NULL) + appendStringInfoChar(buf, '('); + + get_from_clause_item(j->larg, query, context); + + switch (j->jointype) + { + case JOIN_INNER: + if (j->quals) + appendContextKeyword(context, " JOIN ", + -PRETTYINDENT_STD, + PRETTYINDENT_STD, + PRETTYINDENT_JOIN); + else + appendContextKeyword(context, " CROSS JOIN ", + -PRETTYINDENT_STD, + PRETTYINDENT_STD, + PRETTYINDENT_JOIN); + break; + case JOIN_LEFT: + appendContextKeyword(context, " LEFT JOIN ", + -PRETTYINDENT_STD, + PRETTYINDENT_STD, + PRETTYINDENT_JOIN); + break; + case JOIN_FULL: + appendContextKeyword(context, " FULL JOIN ", + -PRETTYINDENT_STD, + PRETTYINDENT_STD, + PRETTYINDENT_JOIN); + break; + case JOIN_RIGHT: + appendContextKeyword(context, " RIGHT JOIN ", + -PRETTYINDENT_STD, + PRETTYINDENT_STD, + PRETTYINDENT_JOIN); + break; + default: + elog(ERROR, "unrecognized join type: %d", + (int) j->jointype); + } + + if (need_paren_on_right) + appendStringInfoChar(buf, '('); + get_from_clause_item(j->rarg, query, context); + if (need_paren_on_right) + appendStringInfoChar(buf, ')'); + + if (j->usingClause) + { + ListCell *lc; + bool first = true; + + appendStringInfoString(buf, " USING ("); + /* Use the assigned names, not what's in usingClause */ + foreach(lc, colinfo->usingNames) + { + char *colname = (char *) lfirst(lc); + + if (first) + first = false; + else + appendStringInfoString(buf, ", "); + appendStringInfoString(buf, quote_identifier(colname)); + } + appendStringInfoChar(buf, ')'); + } + else if (j->quals) + { + appendStringInfoString(buf, " ON "); + if (!PRETTY_PAREN(context)) + appendStringInfoChar(buf, '('); + get_rule_expr(j->quals, context, false); + if (!PRETTY_PAREN(context)) + appendStringInfoChar(buf, ')'); + } + + if (!PRETTY_PAREN(context) || j->alias != NULL) + appendStringInfoChar(buf, ')'); + + /* Yes, it's correct to put alias after the right paren ... */ + if (j->alias != NULL) + { + appendStringInfo(buf, " %s", + quote_identifier(j->alias->aliasname)); + get_column_alias_list(colinfo, context); + } + } + else + elog(ERROR, "unrecognized node type: %d", + (int) nodeTag(jtnode)); +} + +/* + * get_column_alias_list - print column alias list for an RTE + * + * Caller must already have printed the relation's alias name. + */ +static void +get_column_alias_list(deparse_columns *colinfo, deparse_context *context) +{ + StringInfo buf = context->buf; + int i; + bool first = true; + + /* Don't print aliases if not needed */ + if (!colinfo->printaliases) + return; + + for (i = 0; i < colinfo->num_new_cols; i++) + { + char *colname = colinfo->new_colnames[i]; + + if (first) + { + appendStringInfoChar(buf, '('); + first = false; + } + else + appendStringInfoString(buf, ", "); + appendStringInfoString(buf, quote_identifier(colname)); + } + if (!first) + appendStringInfoChar(buf, ')'); +} + +/* + * get_from_clause_coldeflist - reproduce FROM clause coldeflist + * + * When printing a top-level coldeflist (which is syntactically also the + * relation's column alias list), use column names from colinfo. But when + * printing a coldeflist embedded inside ROWS FROM(), we prefer to use the + * original coldeflist's names, which are available in rtfunc->funccolnames. + * Pass NULL for colinfo to select the latter behavior. + * + * The coldeflist is appended immediately (no space) to buf. Caller is + * responsible for ensuring that an alias or AS is present before it. + */ +static void +get_from_clause_coldeflist(RangeTblFunction *rtfunc, + deparse_columns *colinfo, + deparse_context *context) +{ + StringInfo buf = context->buf; + ListCell *l1; + ListCell *l2; + ListCell *l3; + ListCell *l4; + int i; + + appendStringInfoChar(buf, '('); + + /* there's no forfour(), so must chase one list the hard way */ + i = 0; + l4 = list_head(rtfunc->funccolnames); + forthree(l1, rtfunc->funccoltypes, + l2, rtfunc->funccoltypmods, + l3, rtfunc->funccolcollations) + { + Oid atttypid = lfirst_oid(l1); + int32 atttypmod = lfirst_int(l2); + Oid attcollation = lfirst_oid(l3); + char *attname; + + if (colinfo) + attname = colinfo->colnames[i]; + else + attname = strVal(lfirst(l4)); + + Assert(attname); /* shouldn't be any dropped columns here */ + + if (i > 0) + appendStringInfoString(buf, ", "); + appendStringInfo(buf, "%s %s", + quote_identifier(attname), + format_type_with_typemod(atttypid, atttypmod)); + if (OidIsValid(attcollation) && + attcollation != get_typcollation(atttypid)) + appendStringInfo(buf, " COLLATE %s", + generate_collation_name(attcollation)); + + l4 = lnext(l4); + i++; + } + + appendStringInfoChar(buf, ')'); +} + +/* + * processIndirection - take care of array and subfield assignment + * + * We strip any top-level FieldStore or assignment ArrayRef nodes that + * appear in the input, and return the subexpression that's to be assigned. + * If printit is true, we also print out the appropriate decoration for the + * base column name (that the caller just printed). + */ +static Node * +processIndirection(Node *node, deparse_context *context, bool printit) +{ + StringInfo buf = context->buf; + + for (;;) + { + if (node == NULL) + break; + if (IsA(node, FieldStore)) + { + FieldStore *fstore = (FieldStore *) node; + Oid typrelid; + char *fieldname; + + /* lookup tuple type */ + typrelid = get_typ_typrelid(fstore->resulttype); + if (!OidIsValid(typrelid)) + elog(ERROR, "argument type %s of FieldStore is not a tuple type", + format_type_be(fstore->resulttype)); + + /* + * Print the field name. There should only be one target field in + * stored rules. There could be more than that in executable + * target lists, but this function cannot be used for that case. + */ + Assert(list_length(fstore->fieldnums) == 1); + fieldname = get_relid_attribute_name(typrelid, + linitial_int(fstore->fieldnums)); + if (printit) + appendStringInfo(buf, ".%s", quote_identifier(fieldname)); + + /* + * We ignore arg since it should be an uninteresting reference to + * the target column or subcolumn. + */ + node = (Node *) linitial(fstore->newvals); + } + else if (IsA(node, ArrayRef)) + { + ArrayRef *aref = (ArrayRef *) node; + + if (aref->refassgnexpr == NULL) + break; + if (printit) + printSubscripts(aref, context); + + /* + * We ignore refexpr since it should be an uninteresting reference + * to the target column or subcolumn. + */ + node = (Node *) aref->refassgnexpr; + } + else + break; + } + + return node; +} + +static void +printSubscripts(ArrayRef *aref, deparse_context *context) +{ + StringInfo buf = context->buf; + ListCell *lowlist_item; + ListCell *uplist_item; + + lowlist_item = list_head(aref->reflowerindexpr); /* could be NULL */ + foreach(uplist_item, aref->refupperindexpr) + { + appendStringInfoChar(buf, '['); + if (lowlist_item) + { + get_rule_expr((Node *) lfirst(lowlist_item), context, false); + appendStringInfoChar(buf, ':'); + lowlist_item = lnext(lowlist_item); + } + get_rule_expr((Node *) lfirst(uplist_item), context, false); + appendStringInfoChar(buf, ']'); + } +} + +/* + * get_relation_name + * Get the unqualified name of a relation specified by OID + * + * This differs from the underlying get_rel_name() function in that it will + * throw error instead of silently returning NULL if the OID is bad. + */ +static char * +get_relation_name(Oid relid) +{ + char *relname = get_rel_name(relid); + + if (!relname) + elog(ERROR, "cache lookup failed for relation %u", relid); + return relname; +} + +/* + * generate_relation_or_shard_name + * Compute the name to display for a relation or shard + * + * If the provided relid is equal to the provided distrelid, this function + * returns a shard-extended relation name; otherwise, it falls through to a + * simple generate_relation_name call. + */ +static char * +generate_relation_or_shard_name(Oid relid, Oid distrelid, int64 shardid, + List *namespaces) +{ + char *relname = NULL; + + if (relid == distrelid) + { + /* XXX: this is where we would--but don't yet--handle schema-prefixing */ + relname = get_relation_name(relid); + + if (shardid > 0) + { + AppendShardIdToName(&relname, shardid); + + relname = (char *) quote_identifier(relname); + } + } + else + { + relname = generate_relation_name(relid, namespaces); + } + + return relname; +} + +/* + * generate_relation_name + * Compute the name to display for a relation specified by OID + * + * The result includes all necessary quoting and schema-prefixing. + * + * If namespaces isn't NIL, it must be a list of deparse_namespace nodes. + * We will forcibly qualify the relation name if it equals any CTE name + * visible in the namespace list. + */ +char * +generate_relation_name(Oid relid, List *namespaces) +{ + HeapTuple tp; + Form_pg_class reltup; + bool need_qual; + ListCell *nslist; + char *relname; + char *nspname; + char *result; + + tp = SearchSysCache1(RELOID, ObjectIdGetDatum(relid)); + if (!HeapTupleIsValid(tp)) + elog(ERROR, "cache lookup failed for relation %u", relid); + reltup = (Form_pg_class) GETSTRUCT(tp); + relname = NameStr(reltup->relname); + + /* Check for conflicting CTE name */ + need_qual = false; + foreach(nslist, namespaces) + { + deparse_namespace *dpns = (deparse_namespace *) lfirst(nslist); + ListCell *ctlist; + + foreach(ctlist, dpns->ctes) + { + CommonTableExpr *cte = (CommonTableExpr *) lfirst(ctlist); + + if (strcmp(cte->ctename, relname) == 0) + { + need_qual = true; + break; + } + } + if (need_qual) + break; + } + + /* Otherwise, qualify the name if not visible in search path */ + if (!need_qual) + need_qual = !RelationIsVisible(relid); + + if (need_qual) + nspname = get_namespace_name(reltup->relnamespace); + else + nspname = NULL; + + result = quote_qualified_identifier(nspname, relname); + + ReleaseSysCache(tp); + + return result; +} + +/* + * generate_fragment_name + * Compute the name to display for a shard or merged table + * + * The result includes all necessary quoting and schema-prefixing. The schema + * name can be NULL for regular shards. For merged tables, they are always + * declared within a job-specific schema, and therefore can't have null schema + * names. + */ +static char * +generate_fragment_name(char *schemaName, char *tableName) +{ + StringInfo fragmentNameString = makeStringInfo(); + + if (schemaName != NULL) + { + appendStringInfo(fragmentNameString, "%s.%s", quote_identifier(schemaName), + quote_identifier(tableName)); + } + else + { + appendStringInfoString(fragmentNameString, quote_identifier(tableName)); + } + + return fragmentNameString->data; +} + +/* + * generate_function_name + * Compute the name to display for a function specified by OID, + * given that it is being called with the specified actual arg names and + * types. (Those matter because of ambiguous-function resolution rules.) + * + * If we're dealing with a potentially variadic function (in practice, this + * means a FuncExpr or Aggref, not some other way of calling a function), then + * has_variadic must specify whether variadic arguments have been merged, + * and *use_variadic_p will be set to indicate whether to print VARIADIC in + * the output. For non-FuncExpr cases, has_variadic should be FALSE and + * use_variadic_p can be NULL. + * + * The result includes all necessary quoting and schema-prefixing. + */ +static char * +generate_function_name(Oid funcid, int nargs, List *argnames, Oid *argtypes, + bool has_variadic, bool *use_variadic_p) +{ + char *result; + HeapTuple proctup; + Form_pg_proc procform; + char *proname; + bool use_variadic; + char *nspname; + FuncDetailCode p_result; + Oid p_funcid; + Oid p_rettype; + bool p_retset; + int p_nvargs; + Oid p_vatype; + Oid *p_true_typeids; + + proctup = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid)); + if (!HeapTupleIsValid(proctup)) + elog(ERROR, "cache lookup failed for function %u", funcid); + procform = (Form_pg_proc) GETSTRUCT(proctup); + proname = NameStr(procform->proname); + + /* + * Determine whether VARIADIC should be printed. We must do this first + * since it affects the lookup rules in func_get_detail(). + * + * Currently, we always print VARIADIC if the function has a merged + * variadic-array argument. Note that this is always the case for + * functions taking a VARIADIC argument type other than VARIADIC ANY. + * + * In principle, if VARIADIC wasn't originally specified and the array + * actual argument is deconstructable, we could print the array elements + * separately and not print VARIADIC, thus more nearly reproducing the + * original input. For the moment that seems like too much complication + * for the benefit, and anyway we do not know whether VARIADIC was + * originally specified if it's a non-ANY type. + */ + if (use_variadic_p) + { + /* Parser should not have set funcvariadic unless fn is variadic */ + Assert(!has_variadic || OidIsValid(procform->provariadic)); + use_variadic = has_variadic; + *use_variadic_p = use_variadic; + } + else + { + Assert(!has_variadic); + use_variadic = false; + } + + /* + * The idea here is to schema-qualify only if the parser would fail to + * resolve the correct function given the unqualified func name with the + * specified argtypes and VARIADIC flag. + */ + p_result = func_get_detail(list_make1(makeString(proname)), + NIL, argnames, nargs, argtypes, + !use_variadic, true, + &p_funcid, &p_rettype, + &p_retset, &p_nvargs, &p_vatype, + &p_true_typeids, NULL); + if ((p_result == FUNCDETAIL_NORMAL || + p_result == FUNCDETAIL_AGGREGATE || + p_result == FUNCDETAIL_WINDOWFUNC) && + p_funcid == funcid) + nspname = NULL; + else + nspname = get_namespace_name(procform->pronamespace); + + result = quote_qualified_identifier(nspname, proname); + + ReleaseSysCache(proctup); + + return result; +} + +/* + * generate_operator_name + * Compute the name to display for an operator specified by OID, + * given that it is being called with the specified actual arg types. + * (Arg types matter because of ambiguous-operator resolution rules. + * Pass InvalidOid for unused arg of a unary operator.) + * + * The result includes all necessary quoting and schema-prefixing, + * plus the OPERATOR() decoration needed to use a qualified operator name + * in an expression. + */ +static char * +generate_operator_name(Oid operid, Oid arg1, Oid arg2) +{ + StringInfoData buf; + HeapTuple opertup; + Form_pg_operator operform; + char *oprname; + char *nspname; + Operator p_result; + + initStringInfo(&buf); + + opertup = SearchSysCache1(OPEROID, ObjectIdGetDatum(operid)); + if (!HeapTupleIsValid(opertup)) + elog(ERROR, "cache lookup failed for operator %u", operid); + operform = (Form_pg_operator) GETSTRUCT(opertup); + oprname = NameStr(operform->oprname); + + /* + * The idea here is to schema-qualify only if the parser would fail to + * resolve the correct operator given the unqualified op name with the + * specified argtypes. + */ + switch (operform->oprkind) + { + case 'b': + p_result = oper(NULL, list_make1(makeString(oprname)), arg1, arg2, + true, -1); + break; + case 'l': + p_result = left_oper(NULL, list_make1(makeString(oprname)), arg2, + true, -1); + break; + case 'r': + p_result = right_oper(NULL, list_make1(makeString(oprname)), arg1, + true, -1); + break; + default: + elog(ERROR, "unrecognized oprkind: %d", operform->oprkind); + p_result = NULL; /* keep compiler quiet */ + break; + } + + if (p_result != NULL && oprid(p_result) == operid) + nspname = NULL; + else + { + nspname = get_namespace_name(operform->oprnamespace); + appendStringInfo(&buf, "OPERATOR(%s.", quote_identifier(nspname)); + } + + appendStringInfoString(&buf, oprname); + + if (nspname) + appendStringInfoChar(&buf, ')'); + + if (p_result != NULL) + ReleaseSysCache(p_result); + + ReleaseSysCache(opertup); + + return buf.data; +} + +#endif /* (PG_VERSION_NUM >= 90400 && PG_VERSION_NUM < 90500) */ diff --git a/src/backend/distributed/utils/ruleutils_95.c b/src/backend/distributed/utils/ruleutils_95.c new file mode 100644 index 000000000..ee68f1e3a --- /dev/null +++ b/src/backend/distributed/utils/ruleutils_95.c @@ -0,0 +1,7276 @@ +/*------------------------------------------------------------------------- + * + * citus_ruleutils.c + * Additional, non core exposed, functions to convert stored + * expressions/querytrees back to source text + * + * Portions Copyright (c) 1996-2014, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * + * IDENTIFICATION + * src/backend/distributed/utils/citus_ruleutils.c + * + * This needs to be closely in sync with the core code. + *------------------------------------------------------------------------- + */ + +#include "postgres.h" + +#if (PG_VERSION_NUM >= 90500 && PG_VERSION_NUM < 90600) + +#include +#include + +#include "access/htup_details.h" +#include "access/sysattr.h" +#include "catalog/dependency.h" +#include "catalog/indexing.h" +#include "catalog/pg_aggregate.h" +#include "catalog/pg_extension.h" +#include "catalog/pg_foreign_data_wrapper.h" +#include "catalog/pg_opclass.h" +#include "catalog/pg_operator.h" +#include "catalog/pg_proc.h" +#include "catalog/pg_type.h" +#include "distributed/citus_nodefuncs.h" +#include "distributed/citus_ruleutils.h" +#include "commands/defrem.h" +#include "commands/extension.h" +#include "foreign/foreign.h" +#include "funcapi.h" +#include "mb/pg_wchar.h" +#include "miscadmin.h" +#include "nodes/makefuncs.h" +#include "nodes/nodeFuncs.h" +#include "optimizer/tlist.h" +#include "parser/keywords.h" +#include "parser/parse_agg.h" +#include "parser/parse_func.h" +#include "parser/parse_oper.h" +#include "parser/parser.h" +#include "parser/parsetree.h" +#include "rewrite/rewriteHandler.h" +#include "utils/builtins.h" +#include "utils/fmgroids.h" +#include "utils/lsyscache.h" +#include "utils/rel.h" +#include "utils/ruleutils.h" +#include "utils/syscache.h" +#include "utils/typcache.h" +#include "utils/xml.h" + + +/* ---------- + * Pretty formatting constants + * ---------- + */ + +/* Indent counts */ +#define PRETTYINDENT_STD 8 +#define PRETTYINDENT_JOIN 4 +#define PRETTYINDENT_VAR 4 + +#define PRETTYINDENT_LIMIT 40 /* wrap limit */ + +/* Pretty flags */ +#define PRETTYFLAG_PAREN 1 +#define PRETTYFLAG_INDENT 2 + +/* Default line length for pretty-print wrapping: 0 means wrap always */ +#define WRAP_COLUMN_DEFAULT 0 + +/* macro to test if pretty action needed */ +#define PRETTY_PAREN(context) ((context)->prettyFlags & PRETTYFLAG_PAREN) +#define PRETTY_INDENT(context) ((context)->prettyFlags & PRETTYFLAG_INDENT) + + +/* ---------- + * Local data types + * ---------- + */ + +/* Context info needed for invoking a recursive querytree display routine */ +typedef struct +{ + StringInfo buf; /* output buffer to append to */ + List *namespaces; /* List of deparse_namespace nodes */ + List *windowClause; /* Current query level's WINDOW clause */ + List *windowTList; /* targetlist for resolving WINDOW clause */ + int prettyFlags; /* enabling of pretty-print functions */ + int wrapColumn; /* max line length, or -1 for no limit */ + int indentLevel; /* current indent level for prettyprint */ + bool varprefix; /* TRUE to print prefixes on Vars */ + Oid distrelid; /* the distributed table being modified, if valid */ + int64 shardid; /* a distributed table's shardid, if positive */ + ParseExprKind special_exprkind; /* set only for exprkinds needing + * special handling */ +} deparse_context; + +/* + * Each level of query context around a subtree needs a level of Var namespace. + * A Var having varlevelsup=N refers to the N'th item (counting from 0) in + * the current context's namespaces list. + * + * The rangetable is the list of actual RTEs from the query tree, and the + * cte list is the list of actual CTEs. + * + * rtable_names holds the alias name to be used for each RTE (either a C + * string, or NULL for nameless RTEs such as unnamed joins). + * rtable_columns holds the column alias names to be used for each RTE. + * + * In some cases we need to make names of merged JOIN USING columns unique + * across the whole query, not only per-RTE. If so, unique_using is TRUE + * and using_names is a list of C strings representing names already assigned + * to USING columns. + * + * When deparsing plan trees, there is always just a single item in the + * deparse_namespace list (since a plan tree never contains Vars with + * varlevelsup > 0). We store the PlanState node that is the immediate + * parent of the expression to be deparsed, as well as a list of that + * PlanState's ancestors. In addition, we store its outer and inner subplan + * state nodes, as well as their plan nodes' targetlists, and the index tlist + * if the current plan node might contain INDEX_VAR Vars. (These fields could + * be derived on-the-fly from the current PlanState, but it seems notationally + * clearer to set them up as separate fields.) + */ +typedef struct +{ + List *rtable; /* List of RangeTblEntry nodes */ + List *rtable_names; /* Parallel list of names for RTEs */ + List *rtable_columns; /* Parallel list of deparse_columns structs */ + List *ctes; /* List of CommonTableExpr nodes */ + /* Workspace for column alias assignment: */ + bool unique_using; /* Are we making USING names globally unique */ + List *using_names; /* List of assigned names for USING columns */ + /* Remaining fields are used only when deparsing a Plan tree: */ + PlanState *planstate; /* immediate parent of current expression */ + List *ancestors; /* ancestors of planstate */ + PlanState *outer_planstate; /* outer subplan state, or NULL if none */ + PlanState *inner_planstate; /* inner subplan state, or NULL if none */ + List *outer_tlist; /* referent for OUTER_VAR Vars */ + List *inner_tlist; /* referent for INNER_VAR Vars */ + List *index_tlist; /* referent for INDEX_VAR Vars */ +} deparse_namespace; + +/* + * Per-relation data about column alias names. + * + * Selecting aliases is unreasonably complicated because of the need to dump + * rules/views whose underlying tables may have had columns added, deleted, or + * renamed since the query was parsed. We must nonetheless print the rule/view + * in a form that can be reloaded and will produce the same results as before. + * + * For each RTE used in the query, we must assign column aliases that are + * unique within that RTE. SQL does not require this of the original query, + * but due to factors such as *-expansion we need to be able to uniquely + * reference every column in a decompiled query. As long as we qualify all + * column references, per-RTE uniqueness is sufficient for that. + * + * However, we can't ensure per-column name uniqueness for unnamed join RTEs, + * since they just inherit column names from their input RTEs, and we can't + * rename the columns at the join level. Most of the time this isn't an issue + * because we don't need to reference the join's output columns as such; we + * can reference the input columns instead. That approach can fail for merged + * JOIN USING columns, however, so when we have one of those in an unnamed + * join, we have to make that column's alias globally unique across the whole + * query to ensure it can be referenced unambiguously. + * + * Another problem is that a JOIN USING clause requires the columns to be + * merged to have the same aliases in both input RTEs, and that no other + * columns in those RTEs or their children conflict with the USING names. + * To handle that, we do USING-column alias assignment in a recursive + * traversal of the query's jointree. When descending through a JOIN with + * USING, we preassign the USING column names to the child columns, overriding + * other rules for column alias assignment. We also mark each RTE with a list + * of all USING column names selected for joins containing that RTE, so that + * when we assign other columns' aliases later, we can avoid conflicts. + * + * Another problem is that if a JOIN's input tables have had columns added or + * deleted since the query was parsed, we must generate a column alias list + * for the join that matches the current set of input columns --- otherwise, a + * change in the number of columns in the left input would throw off matching + * of aliases to columns of the right input. Thus, positions in the printable + * column alias list are not necessarily one-for-one with varattnos of the + * JOIN, so we need a separate new_colnames[] array for printing purposes. + */ +typedef struct +{ + /* + * colnames is an array containing column aliases to use for columns that + * existed when the query was parsed. Dropped columns have NULL entries. + * This array can be directly indexed by varattno to get a Var's name. + * + * Non-NULL entries are guaranteed unique within the RTE, *except* when + * this is for an unnamed JOIN RTE. In that case we merely copy up names + * from the two input RTEs. + * + * During the recursive descent in set_using_names(), forcible assignment + * of a child RTE's column name is represented by pre-setting that element + * of the child's colnames array. So at that stage, NULL entries in this + * array just mean that no name has been preassigned, not necessarily that + * the column is dropped. + */ + int num_cols; /* length of colnames[] array */ + char **colnames; /* array of C strings and NULLs */ + + /* + * new_colnames is an array containing column aliases to use for columns + * that would exist if the query was re-parsed against the current + * definitions of its base tables. This is what to print as the column + * alias list for the RTE. This array does not include dropped columns, + * but it will include columns added since original parsing. Indexes in + * it therefore have little to do with current varattno values. As above, + * entries are unique unless this is for an unnamed JOIN RTE. (In such an + * RTE, we never actually print this array, but we must compute it anyway + * for possible use in computing column names of upper joins.) The + * parallel array is_new_col marks which of these columns are new since + * original parsing. Entries with is_new_col false must match the + * non-NULL colnames entries one-for-one. + */ + int num_new_cols; /* length of new_colnames[] array */ + char **new_colnames; /* array of C strings */ + bool *is_new_col; /* array of bool flags */ + + /* This flag tells whether we should actually print a column alias list */ + bool printaliases; + + /* This list has all names used as USING names in joins above this RTE */ + List *parentUsing; /* names assigned to parent merged columns */ + + /* + * If this struct is for a JOIN RTE, we fill these fields during the + * set_using_names() pass to describe its relationship to its child RTEs. + * + * leftattnos and rightattnos are arrays with one entry per existing + * output column of the join (hence, indexable by join varattno). For a + * simple reference to a column of the left child, leftattnos[i] is the + * child RTE's attno and rightattnos[i] is zero; and conversely for a + * column of the right child. But for merged columns produced by JOIN + * USING/NATURAL JOIN, both leftattnos[i] and rightattnos[i] are nonzero. + * Also, if the column has been dropped, both are zero. + * + * If it's a JOIN USING, usingNames holds the alias names selected for the + * merged columns (these might be different from the original USING list, + * if we had to modify names to achieve uniqueness). + */ + int leftrti; /* rangetable index of left child */ + int rightrti; /* rangetable index of right child */ + int *leftattnos; /* left-child varattnos of join cols, or 0 */ + int *rightattnos; /* right-child varattnos of join cols, or 0 */ + List *usingNames; /* names assigned to merged columns */ +} deparse_columns; + +/* This macro is analogous to rt_fetch(), but for deparse_columns structs */ +#define deparse_columns_fetch(rangetable_index, dpns) \ + ((deparse_columns *) list_nth((dpns)->rtable_columns, (rangetable_index)-1)) + +/* + * Entry in set_rtable_names' hash table + */ +typedef struct +{ + char name[NAMEDATALEN]; /* Hash key --- must be first */ + int counter; /* Largest addition used so far for name */ +} NameHashEntry; + + +/* ---------- + * Local functions + * + * Most of these functions used to use fixed-size buffers to build their + * results. Now, they take an (already initialized) StringInfo object + * as a parameter, and append their text output to its contents. + * ---------- + */ +static void set_rtable_names(deparse_namespace *dpns, List *parent_namespaces, + Bitmapset *rels_used); +static void set_deparse_for_query(deparse_namespace *dpns, Query *query, + List *parent_namespaces); +static bool has_dangerous_join_using(deparse_namespace *dpns, Node *jtnode); +static void set_using_names(deparse_namespace *dpns, Node *jtnode, + List *parentUsing); +static void set_relation_column_names(deparse_namespace *dpns, + RangeTblEntry *rte, + deparse_columns *colinfo); +static void set_join_column_names(deparse_namespace *dpns, RangeTblEntry *rte, + deparse_columns *colinfo); +static bool colname_is_unique(char *colname, deparse_namespace *dpns, + deparse_columns *colinfo); +static char *make_colname_unique(char *colname, deparse_namespace *dpns, + deparse_columns *colinfo); +static void expand_colnames_array_to(deparse_columns *colinfo, int n); +static void identify_join_columns(JoinExpr *j, RangeTblEntry *jrte, + deparse_columns *colinfo); +static void flatten_join_using_qual(Node *qual, + List **leftvars, List **rightvars); +static char *get_rtable_name(int rtindex, deparse_context *context); +static void set_deparse_planstate(deparse_namespace *dpns, PlanState *ps); +static void push_child_plan(deparse_namespace *dpns, PlanState *ps, + deparse_namespace *save_dpns); +static void pop_child_plan(deparse_namespace *dpns, + deparse_namespace *save_dpns); +static void push_ancestor_plan(deparse_namespace *dpns, ListCell *ancestor_cell, + deparse_namespace *save_dpns); +static void pop_ancestor_plan(deparse_namespace *dpns, + deparse_namespace *save_dpns); +static void get_query_def(Query *query, StringInfo buf, List *parentnamespace, + TupleDesc resultDesc, + int prettyFlags, int wrapColumn, int startIndent); +static void get_query_def_extended(Query *query, StringInfo buf, + List *parentnamespace, Oid distrelid, int64 shardid, + TupleDesc resultDesc, int prettyFlags, int wrapColumn, + int startIndent); +static void get_values_def(List *values_lists, deparse_context *context); +static void get_with_clause(Query *query, deparse_context *context); +static void get_select_query_def(Query *query, deparse_context *context, + TupleDesc resultDesc); +static void get_insert_query_def(Query *query, deparse_context *context); +static void get_update_query_def(Query *query, deparse_context *context); +static void get_update_query_targetlist_def(Query *query, List *targetList, + deparse_context *context, + RangeTblEntry *rte); +static void get_delete_query_def(Query *query, deparse_context *context); +static void get_utility_query_def(Query *query, deparse_context *context); +static void get_basic_select_query(Query *query, deparse_context *context, + TupleDesc resultDesc); +static void get_target_list(List *targetList, deparse_context *context, + TupleDesc resultDesc); +static void get_setop_query(Node *setOp, Query *query, + deparse_context *context, + TupleDesc resultDesc); +static Node *get_rule_sortgroupclause(Index ref, List *tlist, + bool force_colno, + deparse_context *context); +static void get_rule_groupingset(GroupingSet *gset, List *targetlist, + bool omit_parens, deparse_context *context); +static void get_rule_orderby(List *orderList, List *targetList, + bool force_colno, deparse_context *context); +static void get_rule_windowclause(Query *query, deparse_context *context); +static void get_rule_windowspec(WindowClause *wc, List *targetList, + deparse_context *context); +static char *get_variable(Var *var, int levelsup, bool istoplevel, + deparse_context *context); +static Node *find_param_referent(Param *param, deparse_context *context, + deparse_namespace **dpns_p, ListCell **ancestor_cell_p); +static void get_parameter(Param *param, deparse_context *context); +static const char *get_simple_binary_op_name(OpExpr *expr); +static bool isSimpleNode(Node *node, Node *parentNode, int prettyFlags); +static void appendContextKeyword(deparse_context *context, const char *str, + int indentBefore, int indentAfter, int indentPlus); +static void removeStringInfoSpaces(StringInfo str); +static void get_rule_expr(Node *node, deparse_context *context, + bool showimplicit); +static void get_rule_expr_toplevel(Node *node, deparse_context *context, + bool showimplicit); +static void get_oper_expr(OpExpr *expr, deparse_context *context); +static void get_func_expr(FuncExpr *expr, deparse_context *context, + bool showimplicit); +static void get_agg_expr(Aggref *aggref, deparse_context *context); +static void get_windowfunc_expr(WindowFunc *wfunc, deparse_context *context); +static void get_coercion_expr(Node *arg, deparse_context *context, + Oid resulttype, int32 resulttypmod, + Node *parentNode); +static void get_const_expr(Const *constval, deparse_context *context, + int showtype); +static void get_const_collation(Const *constval, deparse_context *context); +static void simple_quote_literal(StringInfo buf, const char *val); +static void get_sublink_expr(SubLink *sublink, deparse_context *context); +static void get_from_clause(Query *query, const char *prefix, + deparse_context *context); +static void get_from_clause_item(Node *jtnode, Query *query, + deparse_context *context); +static void get_column_alias_list(deparse_columns *colinfo, + deparse_context *context); +static void get_from_clause_coldeflist(RangeTblFunction *rtfunc, + deparse_columns *colinfo, + deparse_context *context); +static void get_tablesample_def(TableSampleClause *tablesample, + deparse_context *context); +static void get_opclass_name(Oid opclass, Oid actual_datatype, + StringInfo buf); +static Node *processIndirection(Node *node, deparse_context *context, + bool printit); +static void printSubscripts(ArrayRef *aref, deparse_context *context); +static char *get_relation_name(Oid relid); +static char *generate_relation_or_shard_name(Oid relid, Oid distrelid, + int64 shardid, List *namespaces); +static char *generate_fragment_name(char *schemaName, char *tableName); +static char *generate_function_name(Oid funcid, int nargs, + List *argnames, Oid *argtypes, + bool has_variadic, bool *use_variadic_p, + ParseExprKind special_exprkind); +static char *generate_operator_name(Oid operid, Oid arg1, Oid arg2); + +#define only_marker(rte) ((rte)->inh ? "" : "ONLY ") + + + +/* + * pg_get_query_def parses back one query tree, and outputs the resulting query + * string into given buffer. + */ +void +pg_get_query_def(Query *query, StringInfo buffer) +{ + get_query_def(query, buffer, NIL, NULL, 0, WRAP_COLUMN_DEFAULT, 0); +} + + +/* + * set_rtable_names: select RTE aliases to be used in printing a query + * + * We fill in dpns->rtable_names with a list of names that is one-for-one with + * the already-filled dpns->rtable list. Each RTE name is unique among those + * in the new namespace plus any ancestor namespaces listed in + * parent_namespaces. + * + * If rels_used isn't NULL, only RTE indexes listed in it are given aliases. + * + * Note that this function is only concerned with relation names, not column + * names. + */ +static void +set_rtable_names(deparse_namespace *dpns, List *parent_namespaces, + Bitmapset *rels_used) +{ + HASHCTL hash_ctl; + HTAB *names_hash; + NameHashEntry *hentry; + bool found; + int rtindex; + ListCell *lc; + + dpns->rtable_names = NIL; + /* nothing more to do if empty rtable */ + if (dpns->rtable == NIL) + return; + + /* + * We use a hash table to hold known names, so that this process is O(N) + * not O(N^2) for N names. + */ + MemSet(&hash_ctl, 0, sizeof(hash_ctl)); + hash_ctl.keysize = NAMEDATALEN; + hash_ctl.entrysize = sizeof(NameHashEntry); + hash_ctl.hcxt = CurrentMemoryContext; + names_hash = hash_create("set_rtable_names names", + list_length(dpns->rtable), + &hash_ctl, + HASH_ELEM | HASH_CONTEXT); + /* Preload the hash table with names appearing in parent_namespaces */ + foreach(lc, parent_namespaces) + { + deparse_namespace *olddpns = (deparse_namespace *) lfirst(lc); + ListCell *lc2; + + foreach(lc2, olddpns->rtable_names) + { + char *oldname = (char *) lfirst(lc2); + + if (oldname == NULL) + continue; + hentry = (NameHashEntry *) hash_search(names_hash, + oldname, + HASH_ENTER, + &found); + /* we do not complain about duplicate names in parent namespaces */ + hentry->counter = 0; + } + } + + /* Now we can scan the rtable */ + rtindex = 1; + foreach(lc, dpns->rtable) + { + RangeTblEntry *rte = (RangeTblEntry *) lfirst(lc); + char *refname; + + /* Just in case this takes an unreasonable amount of time ... */ + CHECK_FOR_INTERRUPTS(); + + if (rels_used && !bms_is_member(rtindex, rels_used)) + { + /* Ignore unreferenced RTE */ + refname = NULL; + } + else if (rte->alias) + { + /* If RTE has a user-defined alias, prefer that */ + refname = rte->alias->aliasname; + } + else if (rte->rtekind == RTE_RELATION) + { + /* Use the current actual name of the relation */ + refname = get_rel_name(rte->relid); + } + else if (rte->rtekind == RTE_JOIN) + { + /* Unnamed join has no refname */ + refname = NULL; + } + else + { + /* Otherwise use whatever the parser assigned */ + refname = rte->eref->aliasname; + } + + /* + * If the selected name isn't unique, append digits to make it so, and + * make a new hash entry for it once we've got a unique name. For a + * very long input name, we might have to truncate to stay within + * NAMEDATALEN. + */ + if (refname) + { + hentry = (NameHashEntry *) hash_search(names_hash, + refname, + HASH_ENTER, + &found); + if (found) + { + /* Name already in use, must choose a new one */ + int refnamelen = strlen(refname); + char *modname = (char *) palloc(refnamelen + 16); + NameHashEntry *hentry2; + + do + { + hentry->counter++; + for (;;) + { + /* + * We avoid using %.*s here because it can misbehave + * if the data is not valid in what libc thinks is the + * prevailing encoding. + */ + memcpy(modname, refname, refnamelen); + sprintf(modname + refnamelen, "_%d", hentry->counter); + if (strlen(modname) < NAMEDATALEN) + break; + /* drop chars from refname to keep all the digits */ + refnamelen = pg_mbcliplen(refname, refnamelen, + refnamelen - 1); + } + hentry2 = (NameHashEntry *) hash_search(names_hash, + modname, + HASH_ENTER, + &found); + } while (found); + hentry2->counter = 0; /* init new hash entry */ + refname = modname; + } + else + { + /* Name not previously used, need only initialize hentry */ + hentry->counter = 0; + } + } + + dpns->rtable_names = lappend(dpns->rtable_names, refname); + rtindex++; + } + + hash_destroy(names_hash); +} + +/* + * set_deparse_for_query: set up deparse_namespace for deparsing a Query tree + * + * For convenience, this is defined to initialize the deparse_namespace struct + * from scratch. + */ +static void +set_deparse_for_query(deparse_namespace *dpns, Query *query, + List *parent_namespaces) +{ + ListCell *lc; + ListCell *lc2; + + /* Initialize *dpns and fill rtable/ctes links */ + memset(dpns, 0, sizeof(deparse_namespace)); + dpns->rtable = query->rtable; + dpns->ctes = query->cteList; + + /* Assign a unique relation alias to each RTE */ + set_rtable_names(dpns, parent_namespaces, NULL); + + /* Initialize dpns->rtable_columns to contain zeroed structs */ + dpns->rtable_columns = NIL; + while (list_length(dpns->rtable_columns) < list_length(dpns->rtable)) + dpns->rtable_columns = lappend(dpns->rtable_columns, + palloc0(sizeof(deparse_columns))); + + /* If it's a utility query, it won't have a jointree */ + if (query->jointree) + { + /* Detect whether global uniqueness of USING names is needed */ + dpns->unique_using = + has_dangerous_join_using(dpns, (Node *) query->jointree); + + /* + * Select names for columns merged by USING, via a recursive pass over + * the query jointree. + */ + set_using_names(dpns, (Node *) query->jointree, NIL); + } + + /* + * Now assign remaining column aliases for each RTE. We do this in a + * linear scan of the rtable, so as to process RTEs whether or not they + * are in the jointree (we mustn't miss NEW.*, INSERT target relations, + * etc). JOIN RTEs must be processed after their children, but this is + * okay because they appear later in the rtable list than their children + * (cf Asserts in identify_join_columns()). + */ + forboth(lc, dpns->rtable, lc2, dpns->rtable_columns) + { + RangeTblEntry *rte = (RangeTblEntry *) lfirst(lc); + deparse_columns *colinfo = (deparse_columns *) lfirst(lc2); + + if (rte->rtekind == RTE_JOIN) + set_join_column_names(dpns, rte, colinfo); + else + set_relation_column_names(dpns, rte, colinfo); + } +} + +/* + * has_dangerous_join_using: search jointree for unnamed JOIN USING + * + * Merged columns of a JOIN USING may act differently from either of the input + * columns, either because they are merged with COALESCE (in a FULL JOIN) or + * because an implicit coercion of the underlying input column is required. + * In such a case the column must be referenced as a column of the JOIN not as + * a column of either input. And this is problematic if the join is unnamed + * (alias-less): we cannot qualify the column's name with an RTE name, since + * there is none. (Forcibly assigning an alias to the join is not a solution, + * since that will prevent legal references to tables below the join.) + * To ensure that every column in the query is unambiguously referenceable, + * we must assign such merged columns names that are globally unique across + * the whole query, aliasing other columns out of the way as necessary. + * + * Because the ensuing re-aliasing is fairly damaging to the readability of + * the query, we don't do this unless we have to. So, we must pre-scan + * the join tree to see if we have to, before starting set_using_names(). + */ +static bool +has_dangerous_join_using(deparse_namespace *dpns, Node *jtnode) +{ + if (IsA(jtnode, RangeTblRef)) + { + /* nothing to do here */ + } + else if (IsA(jtnode, FromExpr)) + { + FromExpr *f = (FromExpr *) jtnode; + ListCell *lc; + + foreach(lc, f->fromlist) + { + if (has_dangerous_join_using(dpns, (Node *) lfirst(lc))) + return true; + } + } + else if (IsA(jtnode, JoinExpr)) + { + JoinExpr *j = (JoinExpr *) jtnode; + + /* Is it an unnamed JOIN with USING? */ + if (j->alias == NULL && j->usingClause) + { + /* + * Yes, so check each join alias var to see if any of them are not + * simple references to underlying columns. If so, we have a + * dangerous situation and must pick unique aliases. + */ + RangeTblEntry *jrte = rt_fetch(j->rtindex, dpns->rtable); + ListCell *lc; + + foreach(lc, jrte->joinaliasvars) + { + Var *aliasvar = (Var *) lfirst(lc); + + if (aliasvar != NULL && !IsA(aliasvar, Var)) + return true; + } + } + + /* Nope, but inspect children */ + if (has_dangerous_join_using(dpns, j->larg)) + return true; + if (has_dangerous_join_using(dpns, j->rarg)) + return true; + } + else + elog(ERROR, "unrecognized node type: %d", + (int) nodeTag(jtnode)); + return false; +} + +/* + * set_using_names: select column aliases to be used for merged USING columns + * + * We do this during a recursive descent of the query jointree. + * dpns->unique_using must already be set to determine the global strategy. + * + * Column alias info is saved in the dpns->rtable_columns list, which is + * assumed to be filled with pre-zeroed deparse_columns structs. + * + * parentUsing is a list of all USING aliases assigned in parent joins of + * the current jointree node. (The passed-in list must not be modified.) + */ +static void +set_using_names(deparse_namespace *dpns, Node *jtnode, List *parentUsing) +{ + if (IsA(jtnode, RangeTblRef)) + { + /* nothing to do now */ + } + else if (IsA(jtnode, FromExpr)) + { + FromExpr *f = (FromExpr *) jtnode; + ListCell *lc; + + foreach(lc, f->fromlist) + set_using_names(dpns, (Node *) lfirst(lc), parentUsing); + } + else if (IsA(jtnode, JoinExpr)) + { + JoinExpr *j = (JoinExpr *) jtnode; + RangeTblEntry *rte = rt_fetch(j->rtindex, dpns->rtable); + deparse_columns *colinfo = deparse_columns_fetch(j->rtindex, dpns); + int *leftattnos; + int *rightattnos; + deparse_columns *leftcolinfo; + deparse_columns *rightcolinfo; + int i; + ListCell *lc; + + /* Get info about the shape of the join */ + identify_join_columns(j, rte, colinfo); + leftattnos = colinfo->leftattnos; + rightattnos = colinfo->rightattnos; + + /* Look up the not-yet-filled-in child deparse_columns structs */ + leftcolinfo = deparse_columns_fetch(colinfo->leftrti, dpns); + rightcolinfo = deparse_columns_fetch(colinfo->rightrti, dpns); + + /* + * If this join is unnamed, then we cannot substitute new aliases at + * this level, so any name requirements pushed down to here must be + * pushed down again to the children. + */ + if (rte->alias == NULL) + { + for (i = 0; i < colinfo->num_cols; i++) + { + char *colname = colinfo->colnames[i]; + + if (colname == NULL) + continue; + + /* Push down to left column, unless it's a system column */ + if (leftattnos[i] > 0) + { + expand_colnames_array_to(leftcolinfo, leftattnos[i]); + leftcolinfo->colnames[leftattnos[i] - 1] = colname; + } + + /* Same on the righthand side */ + if (rightattnos[i] > 0) + { + expand_colnames_array_to(rightcolinfo, rightattnos[i]); + rightcolinfo->colnames[rightattnos[i] - 1] = colname; + } + } + } + + /* + * If there's a USING clause, select the USING column names and push + * those names down to the children. We have two strategies: + * + * If dpns->unique_using is TRUE, we force all USING names to be + * unique across the whole query level. In principle we'd only need + * the names of dangerous USING columns to be globally unique, but to + * safely assign all USING names in a single pass, we have to enforce + * the same uniqueness rule for all of them. However, if a USING + * column's name has been pushed down from the parent, we should use + * it as-is rather than making a uniqueness adjustment. This is + * necessary when we're at an unnamed join, and it creates no risk of + * ambiguity. Also, if there's a user-written output alias for a + * merged column, we prefer to use that rather than the input name; + * this simplifies the logic and seems likely to lead to less aliasing + * overall. + * + * If dpns->unique_using is FALSE, we only need USING names to be + * unique within their own join RTE. We still need to honor + * pushed-down names, though. + * + * Though significantly different in results, these two strategies are + * implemented by the same code, with only the difference of whether + * to put assigned names into dpns->using_names. + */ + if (j->usingClause) + { + /* Copy the input parentUsing list so we don't modify it */ + parentUsing = list_copy(parentUsing); + + /* USING names must correspond to the first join output columns */ + expand_colnames_array_to(colinfo, list_length(j->usingClause)); + i = 0; + foreach(lc, j->usingClause) + { + char *colname = strVal(lfirst(lc)); + + /* Assert it's a merged column */ + Assert(leftattnos[i] != 0 && rightattnos[i] != 0); + + /* Adopt passed-down name if any, else select unique name */ + if (colinfo->colnames[i] != NULL) + colname = colinfo->colnames[i]; + else + { + /* Prefer user-written output alias if any */ + if (rte->alias && i < list_length(rte->alias->colnames)) + colname = strVal(list_nth(rte->alias->colnames, i)); + /* Make it appropriately unique */ + colname = make_colname_unique(colname, dpns, colinfo); + if (dpns->unique_using) + dpns->using_names = lappend(dpns->using_names, + colname); + /* Save it as output column name, too */ + colinfo->colnames[i] = colname; + } + + /* Remember selected names for use later */ + colinfo->usingNames = lappend(colinfo->usingNames, colname); + parentUsing = lappend(parentUsing, colname); + + /* Push down to left column, unless it's a system column */ + if (leftattnos[i] > 0) + { + expand_colnames_array_to(leftcolinfo, leftattnos[i]); + leftcolinfo->colnames[leftattnos[i] - 1] = colname; + } + + /* Same on the righthand side */ + if (rightattnos[i] > 0) + { + expand_colnames_array_to(rightcolinfo, rightattnos[i]); + rightcolinfo->colnames[rightattnos[i] - 1] = colname; + } + + i++; + } + } + + /* Mark child deparse_columns structs with correct parentUsing info */ + leftcolinfo->parentUsing = parentUsing; + rightcolinfo->parentUsing = parentUsing; + + /* Now recursively assign USING column names in children */ + set_using_names(dpns, j->larg, parentUsing); + set_using_names(dpns, j->rarg, parentUsing); + } + else + elog(ERROR, "unrecognized node type: %d", + (int) nodeTag(jtnode)); +} + +/* + * set_relation_column_names: select column aliases for a non-join RTE + * + * Column alias info is saved in *colinfo, which is assumed to be pre-zeroed. + * If any colnames entries are already filled in, those override local + * choices. + */ +static void +set_relation_column_names(deparse_namespace *dpns, RangeTblEntry *rte, + deparse_columns *colinfo) +{ + int ncolumns; + char **real_colnames; + bool changed_any; + int noldcolumns; + int i; + int j; + + /* + * Extract the RTE's "real" column names. This is comparable to + * get_rte_attribute_name, except that it's important to disregard dropped + * columns. We put NULL into the array for a dropped column. + */ + if (rte->rtekind == RTE_RELATION) + { + /* Relation --- look to the system catalogs for up-to-date info */ + Relation rel; + TupleDesc tupdesc; + + rel = relation_open(rte->relid, AccessShareLock); + tupdesc = RelationGetDescr(rel); + + ncolumns = tupdesc->natts; + real_colnames = (char **) palloc(ncolumns * sizeof(char *)); + + for (i = 0; i < ncolumns; i++) + { + if (tupdesc->attrs[i]->attisdropped) + real_colnames[i] = NULL; + else + real_colnames[i] = pstrdup(NameStr(tupdesc->attrs[i]->attname)); + } + relation_close(rel, AccessShareLock); + } + else + { + /* Otherwise use the column names from eref */ + ListCell *lc; + + ncolumns = list_length(rte->eref->colnames); + real_colnames = (char **) palloc(ncolumns * sizeof(char *)); + + i = 0; + foreach(lc, rte->eref->colnames) + { + /* + * If the column name shown in eref is an empty string, then it's + * a column that was dropped at the time of parsing the query, so + * treat it as dropped. + */ + char *cname = strVal(lfirst(lc)); + + if (cname[0] == '\0') + cname = NULL; + real_colnames[i] = cname; + i++; + } + } + + /* + * Ensure colinfo->colnames has a slot for each column. (It could be long + * enough already, if we pushed down a name for the last column.) Note: + * it's possible that there are now more columns than there were when the + * query was parsed, ie colnames could be longer than rte->eref->colnames. + * We must assign unique aliases to the new columns too, else there could + * be unresolved conflicts when the view/rule is reloaded. + */ + expand_colnames_array_to(colinfo, ncolumns); + Assert(colinfo->num_cols == ncolumns); + + /* + * Make sufficiently large new_colnames and is_new_col arrays, too. + * + * Note: because we leave colinfo->num_new_cols zero until after the loop, + * colname_is_unique will not consult that array, which is fine because it + * would only be duplicate effort. + */ + colinfo->new_colnames = (char **) palloc(ncolumns * sizeof(char *)); + colinfo->is_new_col = (bool *) palloc(ncolumns * sizeof(bool)); + + /* + * Scan the columns, select a unique alias for each one, and store it in + * colinfo->colnames and colinfo->new_colnames. The former array has NULL + * entries for dropped columns, the latter omits them. Also mark + * new_colnames entries as to whether they are new since parse time; this + * is the case for entries beyond the length of rte->eref->colnames. + */ + noldcolumns = list_length(rte->eref->colnames); + changed_any = false; + j = 0; + for (i = 0; i < ncolumns; i++) + { + char *real_colname = real_colnames[i]; + char *colname = colinfo->colnames[i]; + + /* Skip dropped columns */ + if (real_colname == NULL) + { + Assert(colname == NULL); /* colnames[i] is already NULL */ + continue; + } + + /* If alias already assigned, that's what to use */ + if (colname == NULL) + { + /* If user wrote an alias, prefer that over real column name */ + if (rte->alias && i < list_length(rte->alias->colnames)) + colname = strVal(list_nth(rte->alias->colnames, i)); + else + colname = real_colname; + + /* Unique-ify and insert into colinfo */ + colname = make_colname_unique(colname, dpns, colinfo); + + colinfo->colnames[i] = colname; + } + + /* Put names of non-dropped columns in new_colnames[] too */ + colinfo->new_colnames[j] = colname; + /* And mark them as new or not */ + colinfo->is_new_col[j] = (i >= noldcolumns); + j++; + + /* Remember if any assigned aliases differ from "real" name */ + if (!changed_any && strcmp(colname, real_colname) != 0) + changed_any = true; + } + + /* + * Set correct length for new_colnames[] array. (Note: if columns have + * been added, colinfo->num_cols includes them, which is not really quite + * right but is harmless, since any new columns must be at the end where + * they won't affect varattnos of pre-existing columns.) + */ + colinfo->num_new_cols = j; + + /* + * For a relation RTE, we need only print the alias column names if any + * are different from the underlying "real" names. For a function RTE, + * always emit a complete column alias list; this is to protect against + * possible instability of the default column names (eg, from altering + * parameter names). For other RTE types, print if we changed anything OR + * if there were user-written column aliases (since the latter would be + * part of the underlying "reality"). + */ + if (rte->rtekind == RTE_RELATION) + colinfo->printaliases = changed_any; + else if (rte->rtekind == RTE_FUNCTION) + colinfo->printaliases = true; + else if (rte->alias && rte->alias->colnames != NIL) + colinfo->printaliases = true; + else + colinfo->printaliases = changed_any; +} + +/* + * set_join_column_names: select column aliases for a join RTE + * + * Column alias info is saved in *colinfo, which is assumed to be pre-zeroed. + * If any colnames entries are already filled in, those override local + * choices. Also, names for USING columns were already chosen by + * set_using_names(). We further expect that column alias selection has been + * completed for both input RTEs. + */ +static void +set_join_column_names(deparse_namespace *dpns, RangeTblEntry *rte, + deparse_columns *colinfo) +{ + deparse_columns *leftcolinfo; + deparse_columns *rightcolinfo; + bool changed_any; + int noldcolumns; + int nnewcolumns; + Bitmapset *leftmerged = NULL; + Bitmapset *rightmerged = NULL; + int i; + int j; + int ic; + int jc; + + /* Look up the previously-filled-in child deparse_columns structs */ + leftcolinfo = deparse_columns_fetch(colinfo->leftrti, dpns); + rightcolinfo = deparse_columns_fetch(colinfo->rightrti, dpns); + + /* + * Ensure colinfo->colnames has a slot for each column. (It could be long + * enough already, if we pushed down a name for the last column.) Note: + * it's possible that one or both inputs now have more columns than there + * were when the query was parsed, but we'll deal with that below. We + * only need entries in colnames for pre-existing columns. + */ + noldcolumns = list_length(rte->eref->colnames); + expand_colnames_array_to(colinfo, noldcolumns); + Assert(colinfo->num_cols == noldcolumns); + + /* + * Scan the join output columns, select an alias for each one, and store + * it in colinfo->colnames. If there are USING columns, set_using_names() + * already selected their names, so we can start the loop at the first + * non-merged column. + */ + changed_any = false; + for (i = list_length(colinfo->usingNames); i < noldcolumns; i++) + { + char *colname = colinfo->colnames[i]; + char *real_colname; + + /* Ignore dropped column (only possible for non-merged column) */ + if (colinfo->leftattnos[i] == 0 && colinfo->rightattnos[i] == 0) + { + Assert(colname == NULL); + continue; + } + + /* Get the child column name */ + if (colinfo->leftattnos[i] > 0) + real_colname = leftcolinfo->colnames[colinfo->leftattnos[i] - 1]; + else if (colinfo->rightattnos[i] > 0) + real_colname = rightcolinfo->colnames[colinfo->rightattnos[i] - 1]; + else + { + /* We're joining system columns --- use eref name */ + real_colname = strVal(list_nth(rte->eref->colnames, i)); + } + Assert(real_colname != NULL); + + /* In an unnamed join, just report child column names as-is */ + if (rte->alias == NULL) + { + colinfo->colnames[i] = real_colname; + continue; + } + + /* If alias already assigned, that's what to use */ + if (colname == NULL) + { + /* If user wrote an alias, prefer that over real column name */ + if (rte->alias && i < list_length(rte->alias->colnames)) + colname = strVal(list_nth(rte->alias->colnames, i)); + else + colname = real_colname; + + /* Unique-ify and insert into colinfo */ + colname = make_colname_unique(colname, dpns, colinfo); + + colinfo->colnames[i] = colname; + } + + /* Remember if any assigned aliases differ from "real" name */ + if (!changed_any && strcmp(colname, real_colname) != 0) + changed_any = true; + } + + /* + * Calculate number of columns the join would have if it were re-parsed + * now, and create storage for the new_colnames and is_new_col arrays. + * + * Note: colname_is_unique will be consulting new_colnames[] during the + * loops below, so its not-yet-filled entries must be zeroes. + */ + nnewcolumns = leftcolinfo->num_new_cols + rightcolinfo->num_new_cols - + list_length(colinfo->usingNames); + colinfo->num_new_cols = nnewcolumns; + colinfo->new_colnames = (char **) palloc0(nnewcolumns * sizeof(char *)); + colinfo->is_new_col = (bool *) palloc0(nnewcolumns * sizeof(bool)); + + /* + * Generating the new_colnames array is a bit tricky since any new columns + * added since parse time must be inserted in the right places. This code + * must match the parser, which will order a join's columns as merged + * columns first (in USING-clause order), then non-merged columns from the + * left input (in attnum order), then non-merged columns from the right + * input (ditto). If one of the inputs is itself a join, its columns will + * be ordered according to the same rule, which means newly-added columns + * might not be at the end. We can figure out what's what by consulting + * the leftattnos and rightattnos arrays plus the input is_new_col arrays. + * + * In these loops, i indexes leftattnos/rightattnos (so it's join varattno + * less one), j indexes new_colnames/is_new_col, and ic/jc have similar + * meanings for the current child RTE. + */ + + /* Handle merged columns; they are first and can't be new */ + i = j = 0; + while (i < noldcolumns && + colinfo->leftattnos[i] != 0 && + colinfo->rightattnos[i] != 0) + { + /* column name is already determined and known unique */ + colinfo->new_colnames[j] = colinfo->colnames[i]; + colinfo->is_new_col[j] = false; + + /* build bitmapsets of child attnums of merged columns */ + if (colinfo->leftattnos[i] > 0) + leftmerged = bms_add_member(leftmerged, colinfo->leftattnos[i]); + if (colinfo->rightattnos[i] > 0) + rightmerged = bms_add_member(rightmerged, colinfo->rightattnos[i]); + + i++, j++; + } + + /* Handle non-merged left-child columns */ + ic = 0; + for (jc = 0; jc < leftcolinfo->num_new_cols; jc++) + { + char *child_colname = leftcolinfo->new_colnames[jc]; + + if (!leftcolinfo->is_new_col[jc]) + { + /* Advance ic to next non-dropped old column of left child */ + while (ic < leftcolinfo->num_cols && + leftcolinfo->colnames[ic] == NULL) + ic++; + Assert(ic < leftcolinfo->num_cols); + ic++; + /* If it is a merged column, we already processed it */ + if (bms_is_member(ic, leftmerged)) + continue; + /* Else, advance i to the corresponding existing join column */ + while (i < colinfo->num_cols && + colinfo->colnames[i] == NULL) + i++; + Assert(i < colinfo->num_cols); + Assert(ic == colinfo->leftattnos[i]); + /* Use the already-assigned name of this column */ + colinfo->new_colnames[j] = colinfo->colnames[i]; + i++; + } + else + { + /* + * Unique-ify the new child column name and assign, unless we're + * in an unnamed join, in which case just copy + */ + if (rte->alias != NULL) + { + colinfo->new_colnames[j] = + make_colname_unique(child_colname, dpns, colinfo); + if (!changed_any && + strcmp(colinfo->new_colnames[j], child_colname) != 0) + changed_any = true; + } + else + colinfo->new_colnames[j] = child_colname; + } + + colinfo->is_new_col[j] = leftcolinfo->is_new_col[jc]; + j++; + } + + /* Handle non-merged right-child columns in exactly the same way */ + ic = 0; + for (jc = 0; jc < rightcolinfo->num_new_cols; jc++) + { + char *child_colname = rightcolinfo->new_colnames[jc]; + + if (!rightcolinfo->is_new_col[jc]) + { + /* Advance ic to next non-dropped old column of right child */ + while (ic < rightcolinfo->num_cols && + rightcolinfo->colnames[ic] == NULL) + ic++; + Assert(ic < rightcolinfo->num_cols); + ic++; + /* If it is a merged column, we already processed it */ + if (bms_is_member(ic, rightmerged)) + continue; + /* Else, advance i to the corresponding existing join column */ + while (i < colinfo->num_cols && + colinfo->colnames[i] == NULL) + i++; + Assert(i < colinfo->num_cols); + Assert(ic == colinfo->rightattnos[i]); + /* Use the already-assigned name of this column */ + colinfo->new_colnames[j] = colinfo->colnames[i]; + i++; + } + else + { + /* + * Unique-ify the new child column name and assign, unless we're + * in an unnamed join, in which case just copy + */ + if (rte->alias != NULL) + { + colinfo->new_colnames[j] = + make_colname_unique(child_colname, dpns, colinfo); + if (!changed_any && + strcmp(colinfo->new_colnames[j], child_colname) != 0) + changed_any = true; + } + else + colinfo->new_colnames[j] = child_colname; + } + + colinfo->is_new_col[j] = rightcolinfo->is_new_col[jc]; + j++; + } + + /* Assert we processed the right number of columns */ +#ifdef USE_ASSERT_CHECKING + while (i < colinfo->num_cols && colinfo->colnames[i] == NULL) + i++; + Assert(i == colinfo->num_cols); + Assert(j == nnewcolumns); +#endif + + /* + * For a named join, print column aliases if we changed any from the child + * names. Unnamed joins cannot print aliases. + */ + if (rte->alias != NULL) + colinfo->printaliases = changed_any; + else + colinfo->printaliases = false; +} + +/* + * colname_is_unique: is colname distinct from already-chosen column names? + * + * dpns is query-wide info, colinfo is for the column's RTE + */ +static bool +colname_is_unique(char *colname, deparse_namespace *dpns, + deparse_columns *colinfo) +{ + int i; + ListCell *lc; + + /* Check against already-assigned column aliases within RTE */ + for (i = 0; i < colinfo->num_cols; i++) + { + char *oldname = colinfo->colnames[i]; + + if (oldname && strcmp(oldname, colname) == 0) + return false; + } + + /* + * If we're building a new_colnames array, check that too (this will be + * partially but not completely redundant with the previous checks) + */ + for (i = 0; i < colinfo->num_new_cols; i++) + { + char *oldname = colinfo->new_colnames[i]; + + if (oldname && strcmp(oldname, colname) == 0) + return false; + } + + /* Also check against USING-column names that must be globally unique */ + foreach(lc, dpns->using_names) + { + char *oldname = (char *) lfirst(lc); + + if (strcmp(oldname, colname) == 0) + return false; + } + + /* Also check against names already assigned for parent-join USING cols */ + foreach(lc, colinfo->parentUsing) + { + char *oldname = (char *) lfirst(lc); + + if (strcmp(oldname, colname) == 0) + return false; + } + + return true; +} + +/* + * make_colname_unique: modify colname if necessary to make it unique + * + * dpns is query-wide info, colinfo is for the column's RTE + */ +static char * +make_colname_unique(char *colname, deparse_namespace *dpns, + deparse_columns *colinfo) +{ + /* + * If the selected name isn't unique, append digits to make it so. For a + * very long input name, we might have to truncate to stay within + * NAMEDATALEN. + */ + if (!colname_is_unique(colname, dpns, colinfo)) + { + int colnamelen = strlen(colname); + char *modname = (char *) palloc(colnamelen + 16); + int i = 0; + + do + { + i++; + for (;;) + { + /* + * We avoid using %.*s here because it can misbehave if the + * data is not valid in what libc thinks is the prevailing + * encoding. + */ + memcpy(modname, colname, colnamelen); + sprintf(modname + colnamelen, "_%d", i); + if (strlen(modname) < NAMEDATALEN) + break; + /* drop chars from colname to keep all the digits */ + colnamelen = pg_mbcliplen(colname, colnamelen, + colnamelen - 1); + } + } while (!colname_is_unique(modname, dpns, colinfo)); + colname = modname; + } + return colname; +} + +/* + * expand_colnames_array_to: make colinfo->colnames at least n items long + * + * Any added array entries are initialized to zero. + */ +static void +expand_colnames_array_to(deparse_columns *colinfo, int n) +{ + if (n > colinfo->num_cols) + { + if (colinfo->colnames == NULL) + colinfo->colnames = (char **) palloc0(n * sizeof(char *)); + else + { + colinfo->colnames = (char **) repalloc(colinfo->colnames, + n * sizeof(char *)); + memset(colinfo->colnames + colinfo->num_cols, 0, + (n - colinfo->num_cols) * sizeof(char *)); + } + colinfo->num_cols = n; + } +} + +/* + * identify_join_columns: figure out where columns of a join come from + * + * Fills the join-specific fields of the colinfo struct, except for + * usingNames which is filled later. + */ +static void +identify_join_columns(JoinExpr *j, RangeTblEntry *jrte, + deparse_columns *colinfo) +{ + int numjoincols; + int i; + ListCell *lc; + + /* Extract left/right child RT indexes */ + if (IsA(j->larg, RangeTblRef)) + colinfo->leftrti = ((RangeTblRef *) j->larg)->rtindex; + else if (IsA(j->larg, JoinExpr)) + colinfo->leftrti = ((JoinExpr *) j->larg)->rtindex; + else + elog(ERROR, "unrecognized node type in jointree: %d", + (int) nodeTag(j->larg)); + if (IsA(j->rarg, RangeTblRef)) + colinfo->rightrti = ((RangeTblRef *) j->rarg)->rtindex; + else if (IsA(j->rarg, JoinExpr)) + colinfo->rightrti = ((JoinExpr *) j->rarg)->rtindex; + else + elog(ERROR, "unrecognized node type in jointree: %d", + (int) nodeTag(j->rarg)); + + /* Assert children will be processed earlier than join in second pass */ + Assert(colinfo->leftrti < j->rtindex); + Assert(colinfo->rightrti < j->rtindex); + + /* Initialize result arrays with zeroes */ + numjoincols = list_length(jrte->joinaliasvars); + Assert(numjoincols == list_length(jrte->eref->colnames)); + colinfo->leftattnos = (int *) palloc0(numjoincols * sizeof(int)); + colinfo->rightattnos = (int *) palloc0(numjoincols * sizeof(int)); + + /* Scan the joinaliasvars list to identify simple column references */ + i = 0; + foreach(lc, jrte->joinaliasvars) + { + Var *aliasvar = (Var *) lfirst(lc); + + /* get rid of any implicit coercion above the Var */ + aliasvar = (Var *) strip_implicit_coercions((Node *) aliasvar); + + if (aliasvar == NULL) + { + /* It's a dropped column; nothing to do here */ + } + else if (IsA(aliasvar, Var)) + { + Assert(aliasvar->varlevelsup == 0); + Assert(aliasvar->varattno != 0); + if (aliasvar->varno == colinfo->leftrti) + colinfo->leftattnos[i] = aliasvar->varattno; + else if (aliasvar->varno == colinfo->rightrti) + colinfo->rightattnos[i] = aliasvar->varattno; + else + elog(ERROR, "unexpected varno %d in JOIN RTE", + aliasvar->varno); + } + else if (IsA(aliasvar, CoalesceExpr)) + { + /* + * It's a merged column in FULL JOIN USING. Ignore it for now and + * let the code below identify the merged columns. + */ + } + else + elog(ERROR, "unrecognized node type in join alias vars: %d", + (int) nodeTag(aliasvar)); + + i++; + } + + /* + * If there's a USING clause, deconstruct the join quals to identify the + * merged columns. This is a tad painful but if we cannot rely on the + * column names, there is no other representation of which columns were + * joined by USING. (Unless the join type is FULL, we can't tell from the + * joinaliasvars list which columns are merged.) Note: we assume that the + * merged columns are the first output column(s) of the join. + */ + if (j->usingClause) + { + List *leftvars = NIL; + List *rightvars = NIL; + ListCell *lc2; + + /* Extract left- and right-side Vars from the qual expression */ + flatten_join_using_qual(j->quals, &leftvars, &rightvars); + Assert(list_length(leftvars) == list_length(j->usingClause)); + Assert(list_length(rightvars) == list_length(j->usingClause)); + + /* Mark the output columns accordingly */ + i = 0; + forboth(lc, leftvars, lc2, rightvars) + { + Var *leftvar = (Var *) lfirst(lc); + Var *rightvar = (Var *) lfirst(lc2); + + Assert(leftvar->varlevelsup == 0); + Assert(leftvar->varattno != 0); + if (leftvar->varno != colinfo->leftrti) + elog(ERROR, "unexpected varno %d in JOIN USING qual", + leftvar->varno); + colinfo->leftattnos[i] = leftvar->varattno; + + Assert(rightvar->varlevelsup == 0); + Assert(rightvar->varattno != 0); + if (rightvar->varno != colinfo->rightrti) + elog(ERROR, "unexpected varno %d in JOIN USING qual", + rightvar->varno); + colinfo->rightattnos[i] = rightvar->varattno; + + i++; + } + } +} + +/* + * flatten_join_using_qual: extract Vars being joined from a JOIN/USING qual + * + * We assume that transformJoinUsingClause won't have produced anything except + * AND nodes, equality operator nodes, and possibly implicit coercions, and + * that the AND node inputs match left-to-right with the original USING list. + * + * Caller must initialize the result lists to NIL. + */ +static void +flatten_join_using_qual(Node *qual, List **leftvars, List **rightvars) +{ + if (IsA(qual, BoolExpr)) + { + /* Handle AND nodes by recursion */ + BoolExpr *b = (BoolExpr *) qual; + ListCell *lc; + + Assert(b->boolop == AND_EXPR); + foreach(lc, b->args) + { + flatten_join_using_qual((Node *) lfirst(lc), + leftvars, rightvars); + } + } + else if (IsA(qual, OpExpr)) + { + /* Otherwise we should have an equality operator */ + OpExpr *op = (OpExpr *) qual; + Var *var; + + if (list_length(op->args) != 2) + elog(ERROR, "unexpected unary operator in JOIN/USING qual"); + /* Arguments should be Vars with perhaps implicit coercions */ + var = (Var *) strip_implicit_coercions((Node *) linitial(op->args)); + if (!IsA(var, Var)) + elog(ERROR, "unexpected node type in JOIN/USING qual: %d", + (int) nodeTag(var)); + *leftvars = lappend(*leftvars, var); + var = (Var *) strip_implicit_coercions((Node *) lsecond(op->args)); + if (!IsA(var, Var)) + elog(ERROR, "unexpected node type in JOIN/USING qual: %d", + (int) nodeTag(var)); + *rightvars = lappend(*rightvars, var); + } + else + { + /* Perhaps we have an implicit coercion to boolean? */ + Node *q = strip_implicit_coercions(qual); + + if (q != qual) + flatten_join_using_qual(q, leftvars, rightvars); + else + elog(ERROR, "unexpected node type in JOIN/USING qual: %d", + (int) nodeTag(qual)); + } +} + +/* + * get_rtable_name: convenience function to get a previously assigned RTE alias + * + * The RTE must belong to the topmost namespace level in "context". + */ +static char * +get_rtable_name(int rtindex, deparse_context *context) +{ + deparse_namespace *dpns = (deparse_namespace *) linitial(context->namespaces); + + Assert(rtindex > 0 && rtindex <= list_length(dpns->rtable_names)); + return (char *) list_nth(dpns->rtable_names, rtindex - 1); +} + +/* + * set_deparse_planstate: set up deparse_namespace to parse subexpressions + * of a given PlanState node + * + * This sets the planstate, outer_planstate, inner_planstate, outer_tlist, + * inner_tlist, and index_tlist fields. Caller is responsible for adjusting + * the ancestors list if necessary. Note that the rtable and ctes fields do + * not need to change when shifting attention to different plan nodes in a + * single plan tree. + */ +static void +set_deparse_planstate(deparse_namespace *dpns, PlanState *ps) +{ + dpns->planstate = ps; + + /* + * We special-case Append and MergeAppend to pretend that the first child + * plan is the OUTER referent; we have to interpret OUTER Vars in their + * tlists according to one of the children, and the first one is the most + * natural choice. Likewise special-case ModifyTable to pretend that the + * first child plan is the OUTER referent; this is to support RETURNING + * lists containing references to non-target relations. + */ + if (IsA(ps, AppendState)) + dpns->outer_planstate = ((AppendState *) ps)->appendplans[0]; + else if (IsA(ps, MergeAppendState)) + dpns->outer_planstate = ((MergeAppendState *) ps)->mergeplans[0]; + else if (IsA(ps, ModifyTableState)) + dpns->outer_planstate = ((ModifyTableState *) ps)->mt_plans[0]; + else + dpns->outer_planstate = outerPlanState(ps); + + if (dpns->outer_planstate) + dpns->outer_tlist = dpns->outer_planstate->plan->targetlist; + else + dpns->outer_tlist = NIL; + + /* + * For a SubqueryScan, pretend the subplan is INNER referent. (We don't + * use OUTER because that could someday conflict with the normal meaning.) + * Likewise, for a CteScan, pretend the subquery's plan is INNER referent. + * For ON CONFLICT .. UPDATE we just need the inner tlist to point to the + * excluded expression's tlist. (Similar to the SubqueryScan we don't want + * to reuse OUTER, it's used for RETURNING in some modify table cases, + * although not INSERT .. CONFLICT). + */ + if (IsA(ps, SubqueryScanState)) + dpns->inner_planstate = ((SubqueryScanState *) ps)->subplan; + else if (IsA(ps, CteScanState)) + dpns->inner_planstate = ((CteScanState *) ps)->cteplanstate; + else if (IsA(ps, ModifyTableState)) + dpns->inner_planstate = ps; + else + dpns->inner_planstate = innerPlanState(ps); + + if (IsA(ps, ModifyTableState)) + dpns->inner_tlist = ((ModifyTableState *) ps)->mt_excludedtlist; + else if (dpns->inner_planstate) + dpns->inner_tlist = dpns->inner_planstate->plan->targetlist; + else + dpns->inner_tlist = NIL; + + /* Set up referent for INDEX_VAR Vars, if needed */ + if (IsA(ps->plan, IndexOnlyScan)) + dpns->index_tlist = ((IndexOnlyScan *) ps->plan)->indextlist; + else if (IsA(ps->plan, ForeignScan)) + dpns->index_tlist = ((ForeignScan *) ps->plan)->fdw_scan_tlist; + else if (IsA(ps->plan, CustomScan)) + dpns->index_tlist = ((CustomScan *) ps->plan)->custom_scan_tlist; + else + dpns->index_tlist = NIL; +} + +/* + * push_child_plan: temporarily transfer deparsing attention to a child plan + * + * When expanding an OUTER_VAR or INNER_VAR reference, we must adjust the + * deparse context in case the referenced expression itself uses + * OUTER_VAR/INNER_VAR. We modify the top stack entry in-place to avoid + * affecting levelsup issues (although in a Plan tree there really shouldn't + * be any). + * + * Caller must provide a local deparse_namespace variable to save the + * previous state for pop_child_plan. + */ +static void +push_child_plan(deparse_namespace *dpns, PlanState *ps, + deparse_namespace *save_dpns) +{ + /* Save state for restoration later */ + *save_dpns = *dpns; + + /* Link current plan node into ancestors list */ + dpns->ancestors = lcons(dpns->planstate, dpns->ancestors); + + /* Set attention on selected child */ + set_deparse_planstate(dpns, ps); +} + +/* + * pop_child_plan: undo the effects of push_child_plan + */ +static void +pop_child_plan(deparse_namespace *dpns, deparse_namespace *save_dpns) +{ + List *ancestors; + + /* Get rid of ancestors list cell added by push_child_plan */ + ancestors = list_delete_first(dpns->ancestors); + + /* Restore fields changed by push_child_plan */ + *dpns = *save_dpns; + + /* Make sure dpns->ancestors is right (may be unnecessary) */ + dpns->ancestors = ancestors; +} + +/* + * push_ancestor_plan: temporarily transfer deparsing attention to an + * ancestor plan + * + * When expanding a Param reference, we must adjust the deparse context + * to match the plan node that contains the expression being printed; + * otherwise we'd fail if that expression itself contains a Param or + * OUTER_VAR/INNER_VAR/INDEX_VAR variable. + * + * The target ancestor is conveniently identified by the ListCell holding it + * in dpns->ancestors. + * + * Caller must provide a local deparse_namespace variable to save the + * previous state for pop_ancestor_plan. + */ +static void +push_ancestor_plan(deparse_namespace *dpns, ListCell *ancestor_cell, + deparse_namespace *save_dpns) +{ + PlanState *ps = (PlanState *) lfirst(ancestor_cell); + List *ancestors; + + /* Save state for restoration later */ + *save_dpns = *dpns; + + /* Build a new ancestor list with just this node's ancestors */ + ancestors = NIL; + while ((ancestor_cell = lnext(ancestor_cell)) != NULL) + ancestors = lappend(ancestors, lfirst(ancestor_cell)); + dpns->ancestors = ancestors; + + /* Set attention on selected ancestor */ + set_deparse_planstate(dpns, ps); +} + +/* + * pop_ancestor_plan: undo the effects of push_ancestor_plan + */ +static void +pop_ancestor_plan(deparse_namespace *dpns, deparse_namespace *save_dpns) +{ + /* Free the ancestor list made in push_ancestor_plan */ + list_free(dpns->ancestors); + + /* Restore fields changed by push_ancestor_plan */ + *dpns = *save_dpns; +} + + +/* ---------- + * deparse_shard_query - Parse back a query for execution on a shard + * + * Builds an SQL string to perform the provided query on a specific shard and + * places this string into the provided buffer. + * ---------- + */ +void +deparse_shard_query(Query *query, Oid distrelid, int64 shardid, + StringInfo buffer) +{ + get_query_def_extended(query, buffer, NIL, distrelid, shardid, NULL, 0, + WRAP_COLUMN_DEFAULT, 0); +} + + +/* ---------- + * get_query_def - Parse back one query parsetree + * + * If resultDesc is not NULL, then it is the output tuple descriptor for + * the view represented by a SELECT query. + * ---------- + */ +static void +get_query_def(Query *query, StringInfo buf, List *parentnamespace, + TupleDesc resultDesc, + int prettyFlags, int wrapColumn, int startIndent) +{ + get_query_def_extended(query, buf, parentnamespace, InvalidOid, 0, resultDesc, + prettyFlags, wrapColumn, startIndent); +} + + +/* ---------- + * get_query_def_extended - Parse back one query parsetree, optionally + * with extension using a shard identifier. + * + * If distrelid is valid and shardid is positive, the provided shardid is added + * any time the provided relid is deparsed, so that the query may be executed + * on a placement for the given shard. + * ---------- + */ +static void +get_query_def_extended(Query *query, StringInfo buf, List *parentnamespace, + Oid distrelid, int64 shardid, TupleDesc resultDesc, + int prettyFlags, int wrapColumn, int startIndent) +{ + deparse_context context; + deparse_namespace dpns; + + /* Guard against excessively long or deeply-nested queries */ + CHECK_FOR_INTERRUPTS(); + check_stack_depth(); + + /* + * Before we begin to examine the query, acquire locks on referenced + * relations, and fix up deleted columns in JOIN RTEs. This ensures + * consistent results. Note we assume it's OK to scribble on the passed + * querytree! + * + * We are only deparsing the query (we are not about to execute it), so we + * only need AccessShareLock on the relations it mentions. + */ + AcquireRewriteLocks(query, false, false); + + context.buf = buf; + context.namespaces = lcons(&dpns, list_copy(parentnamespace)); + context.windowClause = NIL; + context.windowTList = NIL; + context.varprefix = (parentnamespace != NIL || + list_length(query->rtable) != 1); + context.prettyFlags = prettyFlags; + context.wrapColumn = wrapColumn; + context.indentLevel = startIndent; + context.special_exprkind = EXPR_KIND_NONE; + context.distrelid = distrelid; + context.shardid = shardid; + + set_deparse_for_query(&dpns, query, parentnamespace); + + switch (query->commandType) + { + case CMD_SELECT: + get_select_query_def(query, &context, resultDesc); + break; + + case CMD_UPDATE: + get_update_query_def(query, &context); + break; + + case CMD_INSERT: + get_insert_query_def(query, &context); + break; + + case CMD_DELETE: + get_delete_query_def(query, &context); + break; + + case CMD_NOTHING: + appendStringInfoString(buf, "NOTHING"); + break; + + case CMD_UTILITY: + get_utility_query_def(query, &context); + break; + + default: + elog(ERROR, "unrecognized query command type: %d", + query->commandType); + break; + } +} + +/* ---------- + * get_values_def - Parse back a VALUES list + * ---------- + */ +static void +get_values_def(List *values_lists, deparse_context *context) +{ + StringInfo buf = context->buf; + bool first_list = true; + ListCell *vtl; + + appendStringInfoString(buf, "VALUES "); + + foreach(vtl, values_lists) + { + List *sublist = (List *) lfirst(vtl); + bool first_col = true; + ListCell *lc; + + if (first_list) + first_list = false; + else + appendStringInfoString(buf, ", "); + + appendStringInfoChar(buf, '('); + foreach(lc, sublist) + { + Node *col = (Node *) lfirst(lc); + + if (first_col) + first_col = false; + else + appendStringInfoChar(buf, ','); + + /* + * Strip any top-level nodes representing indirection assignments, + * then print the result. Whole-row Vars need special treatment. + */ + get_rule_expr_toplevel(processIndirection(col, context, false), + context, false); + } + appendStringInfoChar(buf, ')'); + } +} + +/* ---------- + * get_with_clause - Parse back a WITH clause + * ---------- + */ +static void +get_with_clause(Query *query, deparse_context *context) +{ + StringInfo buf = context->buf; + const char *sep; + ListCell *l; + + if (query->cteList == NIL) + return; + + if (PRETTY_INDENT(context)) + { + context->indentLevel += PRETTYINDENT_STD; + appendStringInfoChar(buf, ' '); + } + + if (query->hasRecursive) + sep = "WITH RECURSIVE "; + else + sep = "WITH "; + foreach(l, query->cteList) + { + CommonTableExpr *cte = (CommonTableExpr *) lfirst(l); + + appendStringInfoString(buf, sep); + appendStringInfoString(buf, quote_identifier(cte->ctename)); + if (cte->aliascolnames) + { + bool first = true; + ListCell *col; + + appendStringInfoChar(buf, '('); + foreach(col, cte->aliascolnames) + { + if (first) + first = false; + else + appendStringInfoString(buf, ", "); + appendStringInfoString(buf, + quote_identifier(strVal(lfirst(col)))); + } + appendStringInfoChar(buf, ')'); + } + appendStringInfoString(buf, " AS ("); + if (PRETTY_INDENT(context)) + appendContextKeyword(context, "", 0, 0, 0); + get_query_def((Query *) cte->ctequery, buf, context->namespaces, NULL, + context->prettyFlags, context->wrapColumn, + context->indentLevel); + if (PRETTY_INDENT(context)) + appendContextKeyword(context, "", 0, 0, 0); + appendStringInfoChar(buf, ')'); + sep = ", "; + } + + if (PRETTY_INDENT(context)) + { + context->indentLevel -= PRETTYINDENT_STD; + appendContextKeyword(context, "", 0, 0, 0); + } + else + appendStringInfoChar(buf, ' '); +} + +/* ---------- + * get_select_query_def - Parse back a SELECT parsetree + * ---------- + */ +static void +get_select_query_def(Query *query, deparse_context *context, + TupleDesc resultDesc) +{ + StringInfo buf = context->buf; + List *save_windowclause; + List *save_windowtlist; + bool force_colno; + ListCell *l; + + /* Insert the WITH clause if given */ + get_with_clause(query, context); + + /* Set up context for possible window functions */ + save_windowclause = context->windowClause; + context->windowClause = query->windowClause; + save_windowtlist = context->windowTList; + context->windowTList = query->targetList; + + /* + * If the Query node has a setOperations tree, then it's the top level of + * a UNION/INTERSECT/EXCEPT query; only the WITH, ORDER BY and LIMIT + * fields are interesting in the top query itself. + */ + if (query->setOperations) + { + get_setop_query(query->setOperations, query, context, resultDesc); + /* ORDER BY clauses must be simple in this case */ + force_colno = true; + } + else + { + get_basic_select_query(query, context, resultDesc); + force_colno = false; + } + + /* Add the ORDER BY clause if given */ + if (query->sortClause != NIL) + { + appendContextKeyword(context, " ORDER BY ", + -PRETTYINDENT_STD, PRETTYINDENT_STD, 1); + get_rule_orderby(query->sortClause, query->targetList, + force_colno, context); + } + + /* Add the LIMIT clause if given */ + if (query->limitOffset != NULL) + { + appendContextKeyword(context, " OFFSET ", + -PRETTYINDENT_STD, PRETTYINDENT_STD, 0); + get_rule_expr(query->limitOffset, context, false); + } + if (query->limitCount != NULL) + { + appendContextKeyword(context, " LIMIT ", + -PRETTYINDENT_STD, PRETTYINDENT_STD, 0); + if (IsA(query->limitCount, Const) && + ((Const *) query->limitCount)->constisnull) + appendStringInfoString(buf, "ALL"); + else + get_rule_expr(query->limitCount, context, false); + } + + /* Add FOR [KEY] UPDATE/SHARE clauses if present */ + if (query->hasForUpdate) + { + foreach(l, query->rowMarks) + { + RowMarkClause *rc = (RowMarkClause *) lfirst(l); + + /* don't print implicit clauses */ + if (rc->pushedDown) + continue; + + switch (rc->strength) + { + case LCS_NONE: + /* we intentionally throw an error for LCS_NONE */ + elog(ERROR, "unrecognized LockClauseStrength %d", + (int) rc->strength); + break; + case LCS_FORKEYSHARE: + appendContextKeyword(context, " FOR KEY SHARE", + -PRETTYINDENT_STD, PRETTYINDENT_STD, 0); + break; + case LCS_FORSHARE: + appendContextKeyword(context, " FOR SHARE", + -PRETTYINDENT_STD, PRETTYINDENT_STD, 0); + break; + case LCS_FORNOKEYUPDATE: + appendContextKeyword(context, " FOR NO KEY UPDATE", + -PRETTYINDENT_STD, PRETTYINDENT_STD, 0); + break; + case LCS_FORUPDATE: + appendContextKeyword(context, " FOR UPDATE", + -PRETTYINDENT_STD, PRETTYINDENT_STD, 0); + break; + } + + appendStringInfo(buf, " OF %s", + quote_identifier(get_rtable_name(rc->rti, + context))); + if (rc->waitPolicy == LockWaitError) + appendStringInfoString(buf, " NOWAIT"); + else if (rc->waitPolicy == LockWaitSkip) + appendStringInfoString(buf, " SKIP LOCKED"); + } + } + + context->windowClause = save_windowclause; + context->windowTList = save_windowtlist; +} + +/* + * Detect whether query looks like SELECT ... FROM VALUES(); + * if so, return the VALUES RTE. Otherwise return NULL. + */ +static RangeTblEntry * +get_simple_values_rte(Query *query) +{ + RangeTblEntry *result = NULL; + ListCell *lc; + + /* + * We want to return TRUE even if the Query also contains OLD or NEW rule + * RTEs. So the idea is to scan the rtable and see if there is only one + * inFromCl RTE that is a VALUES RTE. + */ + foreach(lc, query->rtable) + { + RangeTblEntry *rte = (RangeTblEntry *) lfirst(lc); + + if (rte->rtekind == RTE_VALUES && rte->inFromCl) + { + if (result) + return NULL; /* multiple VALUES (probably not possible) */ + result = rte; + } + else if (rte->rtekind == RTE_RELATION && !rte->inFromCl) + continue; /* ignore rule entries */ + else + return NULL; /* something else -> not simple VALUES */ + } + + /* + * We don't need to check the targetlist in any great detail, because + * parser/analyze.c will never generate a "bare" VALUES RTE --- they only + * appear inside auto-generated sub-queries with very restricted + * structure. However, DefineView might have modified the tlist by + * injecting new column aliases; so compare tlist resnames against the + * RTE's names to detect that. + */ + if (result) + { + ListCell *lcn; + + if (list_length(query->targetList) != list_length(result->eref->colnames)) + return NULL; /* this probably cannot happen */ + forboth(lc, query->targetList, lcn, result->eref->colnames) + { + TargetEntry *tle = (TargetEntry *) lfirst(lc); + char *cname = strVal(lfirst(lcn)); + + if (tle->resjunk) + return NULL; /* this probably cannot happen */ + if (tle->resname == NULL || strcmp(tle->resname, cname) != 0) + return NULL; /* column name has been changed */ + } + } + + return result; +} + +static void +get_basic_select_query(Query *query, deparse_context *context, + TupleDesc resultDesc) +{ + StringInfo buf = context->buf; + RangeTblEntry *values_rte; + char *sep; + ListCell *l; + + if (PRETTY_INDENT(context)) + { + context->indentLevel += PRETTYINDENT_STD; + appendStringInfoChar(buf, ' '); + } + + /* + * If the query looks like SELECT * FROM (VALUES ...), then print just the + * VALUES part. This reverses what transformValuesClause() did at parse + * time. + */ + values_rte = get_simple_values_rte(query); + if (values_rte) + { + get_values_def(values_rte->values_lists, context); + return; + } + + /* + * Build up the query string - first we say SELECT + */ + appendStringInfoString(buf, "SELECT"); + + /* Add the DISTINCT clause if given */ + if (query->distinctClause != NIL) + { + if (query->hasDistinctOn) + { + appendStringInfoString(buf, " DISTINCT ON ("); + sep = ""; + foreach(l, query->distinctClause) + { + SortGroupClause *srt = (SortGroupClause *) lfirst(l); + + appendStringInfoString(buf, sep); + get_rule_sortgroupclause(srt->tleSortGroupRef, query->targetList, + false, context); + sep = ", "; + } + appendStringInfoChar(buf, ')'); + } + else + appendStringInfoString(buf, " DISTINCT"); + } + + /* Then we tell what to select (the targetlist) */ + get_target_list(query->targetList, context, resultDesc); + + /* Add the FROM clause if needed */ + get_from_clause(query, " FROM ", context); + + /* Add the WHERE clause if given */ + if (query->jointree->quals != NULL) + { + appendContextKeyword(context, " WHERE ", + -PRETTYINDENT_STD, PRETTYINDENT_STD, 1); + get_rule_expr(query->jointree->quals, context, false); + } + + /* Add the GROUP BY clause if given */ + if (query->groupClause != NULL || query->groupingSets != NULL) + { + ParseExprKind save_exprkind; + + appendContextKeyword(context, " GROUP BY ", + -PRETTYINDENT_STD, PRETTYINDENT_STD, 1); + + save_exprkind = context->special_exprkind; + context->special_exprkind = EXPR_KIND_GROUP_BY; + + if (query->groupingSets == NIL) + { + sep = ""; + foreach(l, query->groupClause) + { + SortGroupClause *grp = (SortGroupClause *) lfirst(l); + + appendStringInfoString(buf, sep); + get_rule_sortgroupclause(grp->tleSortGroupRef, query->targetList, + false, context); + sep = ", "; + } + } + else + { + sep = ""; + foreach(l, query->groupingSets) + { + GroupingSet *grp = lfirst(l); + + appendStringInfoString(buf, sep); + get_rule_groupingset(grp, query->targetList, true, context); + sep = ", "; + } + } + + context->special_exprkind = save_exprkind; + } + + /* Add the HAVING clause if given */ + if (query->havingQual != NULL) + { + appendContextKeyword(context, " HAVING ", + -PRETTYINDENT_STD, PRETTYINDENT_STD, 0); + get_rule_expr(query->havingQual, context, false); + } + + /* Add the WINDOW clause if needed */ + if (query->windowClause != NIL) + get_rule_windowclause(query, context); +} + +/* ---------- + * get_target_list - Parse back a SELECT target list + * + * This is also used for RETURNING lists in INSERT/UPDATE/DELETE. + * ---------- + */ +static void +get_target_list(List *targetList, deparse_context *context, + TupleDesc resultDesc) +{ + StringInfo buf = context->buf; + StringInfoData targetbuf; + bool last_was_multiline = false; + char *sep; + int colno; + ListCell *l; + + /* we use targetbuf to hold each TLE's text temporarily */ + initStringInfo(&targetbuf); + + sep = " "; + colno = 0; + foreach(l, targetList) + { + TargetEntry *tle = (TargetEntry *) lfirst(l); + char *colname; + char *attname; + + if (tle->resjunk) + continue; /* ignore junk entries */ + + appendStringInfoString(buf, sep); + sep = ", "; + colno++; + + /* + * Put the new field text into targetbuf so we can decide after we've + * got it whether or not it needs to go on a new line. + */ + resetStringInfo(&targetbuf); + context->buf = &targetbuf; + + /* + * We special-case Var nodes rather than using get_rule_expr. This is + * needed because get_rule_expr will display a whole-row Var as + * "foo.*", which is the preferred notation in most contexts, but at + * the top level of a SELECT list it's not right (the parser will + * expand that notation into multiple columns, yielding behavior + * different from a whole-row Var). We need to call get_variable + * directly so that we can tell it to do the right thing, and so that + * we can get the attribute name which is the default AS label. + */ + if (tle->expr && (IsA(tle->expr, Var))) + { + attname = get_variable((Var *) tle->expr, 0, true, context); + } + else + { + get_rule_expr((Node *) tle->expr, context, true); + /* We'll show the AS name unless it's this: */ + attname = "?column?"; + } + + /* + * Figure out what the result column should be called. In the context + * of a view, use the view's tuple descriptor (so as to pick up the + * effects of any column RENAME that's been done on the view). + * Otherwise, just use what we can find in the TLE. + */ + if (resultDesc && colno <= resultDesc->natts) + colname = NameStr(resultDesc->attrs[colno - 1]->attname); + else + colname = tle->resname; + + /* Show AS unless the column's name is correct as-is */ + if (colname) /* resname could be NULL */ + { + if (attname == NULL || strcmp(attname, colname) != 0) + appendStringInfo(&targetbuf, " AS %s", quote_identifier(colname)); + } + + /* Restore context's output buffer */ + context->buf = buf; + + /* Consider line-wrapping if enabled */ + if (PRETTY_INDENT(context) && context->wrapColumn >= 0) + { + int leading_nl_pos; + + /* Does the new field start with a new line? */ + if (targetbuf.len > 0 && targetbuf.data[0] == '\n') + leading_nl_pos = 0; + else + leading_nl_pos = -1; + + /* If so, we shouldn't add anything */ + if (leading_nl_pos >= 0) + { + /* instead, remove any trailing spaces currently in buf */ + removeStringInfoSpaces(buf); + } + else + { + char *trailing_nl; + + /* Locate the start of the current line in the output buffer */ + trailing_nl = strrchr(buf->data, '\n'); + if (trailing_nl == NULL) + trailing_nl = buf->data; + else + trailing_nl++; + + /* + * Add a newline, plus some indentation, if the new field is + * not the first and either the new field would cause an + * overflow or the last field used more than one line. + */ + if (colno > 1 && + ((strlen(trailing_nl) + targetbuf.len > context->wrapColumn) || + last_was_multiline)) + appendContextKeyword(context, "", -PRETTYINDENT_STD, + PRETTYINDENT_STD, PRETTYINDENT_VAR); + } + + /* Remember this field's multiline status for next iteration */ + last_was_multiline = + (strchr(targetbuf.data + leading_nl_pos + 1, '\n') != NULL); + } + + /* Add the new field */ + appendStringInfoString(buf, targetbuf.data); + } + + /* clean up */ + pfree(targetbuf.data); +} + +static void +get_setop_query(Node *setOp, Query *query, deparse_context *context, + TupleDesc resultDesc) +{ + StringInfo buf = context->buf; + bool need_paren; + + /* Guard against excessively long or deeply-nested queries */ + CHECK_FOR_INTERRUPTS(); + check_stack_depth(); + + if (IsA(setOp, RangeTblRef)) + { + RangeTblRef *rtr = (RangeTblRef *) setOp; + RangeTblEntry *rte = rt_fetch(rtr->rtindex, query->rtable); + Query *subquery = rte->subquery; + + Assert(subquery != NULL); + Assert(subquery->setOperations == NULL); + /* Need parens if WITH, ORDER BY, FOR UPDATE, or LIMIT; see gram.y */ + need_paren = (subquery->cteList || + subquery->sortClause || + subquery->rowMarks || + subquery->limitOffset || + subquery->limitCount); + if (need_paren) + appendStringInfoChar(buf, '('); + get_query_def(subquery, buf, context->namespaces, resultDesc, + context->prettyFlags, context->wrapColumn, + context->indentLevel); + if (need_paren) + appendStringInfoChar(buf, ')'); + } + else if (IsA(setOp, SetOperationStmt)) + { + SetOperationStmt *op = (SetOperationStmt *) setOp; + int subindent; + + /* + * We force parens when nesting two SetOperationStmts, except when the + * lefthand input is another setop of the same kind. Syntactically, + * we could omit parens in rather more cases, but it seems best to use + * parens to flag cases where the setop operator changes. If we use + * parens, we also increase the indentation level for the child query. + * + * There are some cases in which parens are needed around a leaf query + * too, but those are more easily handled at the next level down (see + * code above). + */ + if (IsA(op->larg, SetOperationStmt)) + { + SetOperationStmt *lop = (SetOperationStmt *) op->larg; + + if (op->op == lop->op && op->all == lop->all) + need_paren = false; + else + need_paren = true; + } + else + need_paren = false; + + if (need_paren) + { + appendStringInfoChar(buf, '('); + subindent = PRETTYINDENT_STD; + appendContextKeyword(context, "", subindent, 0, 0); + } + else + subindent = 0; + + get_setop_query(op->larg, query, context, resultDesc); + + if (need_paren) + appendContextKeyword(context, ") ", -subindent, 0, 0); + else if (PRETTY_INDENT(context)) + appendContextKeyword(context, "", -subindent, 0, 0); + else + appendStringInfoChar(buf, ' '); + + switch (op->op) + { + case SETOP_UNION: + appendStringInfoString(buf, "UNION "); + break; + case SETOP_INTERSECT: + appendStringInfoString(buf, "INTERSECT "); + break; + case SETOP_EXCEPT: + appendStringInfoString(buf, "EXCEPT "); + break; + default: + elog(ERROR, "unrecognized set op: %d", + (int) op->op); + } + if (op->all) + appendStringInfoString(buf, "ALL "); + + /* Always parenthesize if RHS is another setop */ + need_paren = IsA(op->rarg, SetOperationStmt); + + /* + * The indentation code here is deliberately a bit different from that + * for the lefthand input, because we want the line breaks in + * different places. + */ + if (need_paren) + { + appendStringInfoChar(buf, '('); + subindent = PRETTYINDENT_STD; + } + else + subindent = 0; + appendContextKeyword(context, "", subindent, 0, 0); + + get_setop_query(op->rarg, query, context, resultDesc); + + if (PRETTY_INDENT(context)) + context->indentLevel -= subindent; + if (need_paren) + appendContextKeyword(context, ")", 0, 0, 0); + } + else + { + elog(ERROR, "unrecognized node type: %d", + (int) nodeTag(setOp)); + } +} + +/* + * Display a sort/group clause. + * + * Also returns the expression tree, so caller need not find it again. + */ +static Node * +get_rule_sortgroupclause(Index ref, List *tlist, bool force_colno, + deparse_context *context) +{ + StringInfo buf = context->buf; + TargetEntry *tle; + Node *expr; + + tle = get_sortgroupref_tle(ref, tlist); + expr = (Node *) tle->expr; + + /* + * Use column-number form if requested by caller. Otherwise, if + * expression is a constant, force it to be dumped with an explicit cast + * as decoration --- this is because a simple integer constant is + * ambiguous (and will be misinterpreted by findTargetlistEntry()) if we + * dump it without any decoration. If it's anything more complex than a + * simple Var, then force extra parens around it, to ensure it can't be + * misinterpreted as a cube() or rollup() construct. + */ + if (force_colno) + { + Assert(!tle->resjunk); + appendStringInfo(buf, "%d", tle->resno); + } + else if (expr && IsA(expr, Const)) + get_const_expr((Const *) expr, context, 1); + else if (!expr || IsA(expr, Var)) + get_rule_expr(expr, context, true); + else + { + /* + * We must force parens for function-like expressions even if + * PRETTY_PAREN is off, since those are the ones in danger of + * misparsing. For other expressions we need to force them only if + * PRETTY_PAREN is on, since otherwise the expression will output them + * itself. (We can't skip the parens.) + */ + bool need_paren = (PRETTY_PAREN(context) + || IsA(expr, FuncExpr) + ||IsA(expr, Aggref) + ||IsA(expr, WindowFunc)); + + if (need_paren) + appendStringInfoString(context->buf, "("); + get_rule_expr(expr, context, true); + if (need_paren) + appendStringInfoString(context->buf, ")"); + } + + return expr; +} + +/* + * Display a GroupingSet + */ +static void +get_rule_groupingset(GroupingSet *gset, List *targetlist, + bool omit_parens, deparse_context *context) +{ + ListCell *l; + StringInfo buf = context->buf; + bool omit_child_parens = true; + char *sep = ""; + + switch (gset->kind) + { + case GROUPING_SET_EMPTY: + appendStringInfoString(buf, "()"); + return; + + case GROUPING_SET_SIMPLE: + { + if (!omit_parens || list_length(gset->content) != 1) + appendStringInfoString(buf, "("); + + foreach(l, gset->content) + { + Index ref = lfirst_int(l); + + appendStringInfoString(buf, sep); + get_rule_sortgroupclause(ref, targetlist, + false, context); + sep = ", "; + } + + if (!omit_parens || list_length(gset->content) != 1) + appendStringInfoString(buf, ")"); + } + return; + + case GROUPING_SET_ROLLUP: + appendStringInfoString(buf, "ROLLUP("); + break; + case GROUPING_SET_CUBE: + appendStringInfoString(buf, "CUBE("); + break; + case GROUPING_SET_SETS: + appendStringInfoString(buf, "GROUPING SETS ("); + omit_child_parens = false; + break; + } + + foreach(l, gset->content) + { + appendStringInfoString(buf, sep); + get_rule_groupingset(lfirst(l), targetlist, omit_child_parens, context); + sep = ", "; + } + + appendStringInfoString(buf, ")"); +} + +/* + * Display an ORDER BY list. + */ +static void +get_rule_orderby(List *orderList, List *targetList, + bool force_colno, deparse_context *context) +{ + StringInfo buf = context->buf; + const char *sep; + ListCell *l; + + sep = ""; + foreach(l, orderList) + { + SortGroupClause *srt = (SortGroupClause *) lfirst(l); + Node *sortexpr; + Oid sortcoltype; + TypeCacheEntry *typentry; + + appendStringInfoString(buf, sep); + sortexpr = get_rule_sortgroupclause(srt->tleSortGroupRef, targetList, + force_colno, context); + sortcoltype = exprType(sortexpr); + /* See whether operator is default < or > for datatype */ + typentry = lookup_type_cache(sortcoltype, + TYPECACHE_LT_OPR | TYPECACHE_GT_OPR); + if (srt->sortop == typentry->lt_opr) + { + /* ASC is default, so emit nothing for it */ + if (srt->nulls_first) + appendStringInfoString(buf, " NULLS FIRST"); + } + else if (srt->sortop == typentry->gt_opr) + { + appendStringInfoString(buf, " DESC"); + /* DESC defaults to NULLS FIRST */ + if (!srt->nulls_first) + appendStringInfoString(buf, " NULLS LAST"); + } + else + { + appendStringInfo(buf, " USING %s", + generate_operator_name(srt->sortop, + sortcoltype, + sortcoltype)); + /* be specific to eliminate ambiguity */ + if (srt->nulls_first) + appendStringInfoString(buf, " NULLS FIRST"); + else + appendStringInfoString(buf, " NULLS LAST"); + } + sep = ", "; + } +} + +/* + * Display a WINDOW clause. + * + * Note that the windowClause list might contain only anonymous window + * specifications, in which case we should print nothing here. + */ +static void +get_rule_windowclause(Query *query, deparse_context *context) +{ + StringInfo buf = context->buf; + const char *sep; + ListCell *l; + + sep = NULL; + foreach(l, query->windowClause) + { + WindowClause *wc = (WindowClause *) lfirst(l); + + if (wc->name == NULL) + continue; /* ignore anonymous windows */ + + if (sep == NULL) + appendContextKeyword(context, " WINDOW ", + -PRETTYINDENT_STD, PRETTYINDENT_STD, 1); + else + appendStringInfoString(buf, sep); + + appendStringInfo(buf, "%s AS ", quote_identifier(wc->name)); + + get_rule_windowspec(wc, query->targetList, context); + + sep = ", "; + } +} + +/* + * Display a window definition + */ +static void +get_rule_windowspec(WindowClause *wc, List *targetList, + deparse_context *context) +{ + StringInfo buf = context->buf; + bool needspace = false; + const char *sep; + ListCell *l; + + appendStringInfoChar(buf, '('); + if (wc->refname) + { + appendStringInfoString(buf, quote_identifier(wc->refname)); + needspace = true; + } + /* partition clauses are always inherited, so only print if no refname */ + if (wc->partitionClause && !wc->refname) + { + if (needspace) + appendStringInfoChar(buf, ' '); + appendStringInfoString(buf, "PARTITION BY "); + sep = ""; + foreach(l, wc->partitionClause) + { + SortGroupClause *grp = (SortGroupClause *) lfirst(l); + + appendStringInfoString(buf, sep); + get_rule_sortgroupclause(grp->tleSortGroupRef, targetList, + false, context); + sep = ", "; + } + needspace = true; + } + /* print ordering clause only if not inherited */ + if (wc->orderClause && !wc->copiedOrder) + { + if (needspace) + appendStringInfoChar(buf, ' '); + appendStringInfoString(buf, "ORDER BY "); + get_rule_orderby(wc->orderClause, targetList, false, context); + needspace = true; + } + /* framing clause is never inherited, so print unless it's default */ + if (wc->frameOptions & FRAMEOPTION_NONDEFAULT) + { + if (needspace) + appendStringInfoChar(buf, ' '); + if (wc->frameOptions & FRAMEOPTION_RANGE) + appendStringInfoString(buf, "RANGE "); + else if (wc->frameOptions & FRAMEOPTION_ROWS) + appendStringInfoString(buf, "ROWS "); + else + Assert(false); + if (wc->frameOptions & FRAMEOPTION_BETWEEN) + appendStringInfoString(buf, "BETWEEN "); + if (wc->frameOptions & FRAMEOPTION_START_UNBOUNDED_PRECEDING) + appendStringInfoString(buf, "UNBOUNDED PRECEDING "); + else if (wc->frameOptions & FRAMEOPTION_START_CURRENT_ROW) + appendStringInfoString(buf, "CURRENT ROW "); + else if (wc->frameOptions & FRAMEOPTION_START_VALUE) + { + get_rule_expr(wc->startOffset, context, false); + if (wc->frameOptions & FRAMEOPTION_START_VALUE_PRECEDING) + appendStringInfoString(buf, " PRECEDING "); + else if (wc->frameOptions & FRAMEOPTION_START_VALUE_FOLLOWING) + appendStringInfoString(buf, " FOLLOWING "); + else + Assert(false); + } + else + Assert(false); + if (wc->frameOptions & FRAMEOPTION_BETWEEN) + { + appendStringInfoString(buf, "AND "); + if (wc->frameOptions & FRAMEOPTION_END_UNBOUNDED_FOLLOWING) + appendStringInfoString(buf, "UNBOUNDED FOLLOWING "); + else if (wc->frameOptions & FRAMEOPTION_END_CURRENT_ROW) + appendStringInfoString(buf, "CURRENT ROW "); + else if (wc->frameOptions & FRAMEOPTION_END_VALUE) + { + get_rule_expr(wc->endOffset, context, false); + if (wc->frameOptions & FRAMEOPTION_END_VALUE_PRECEDING) + appendStringInfoString(buf, " PRECEDING "); + else if (wc->frameOptions & FRAMEOPTION_END_VALUE_FOLLOWING) + appendStringInfoString(buf, " FOLLOWING "); + else + Assert(false); + } + else + Assert(false); + } + /* we will now have a trailing space; remove it */ + buf->len--; + } + appendStringInfoChar(buf, ')'); +} + +/* ---------- + * get_insert_query_def - Parse back an INSERT parsetree + * ---------- + */ +static void +get_insert_query_def(Query *query, deparse_context *context) +{ + StringInfo buf = context->buf; + RangeTblEntry *select_rte = NULL; + RangeTblEntry *values_rte = NULL; + RangeTblEntry *rte; + char *sep; + ListCell *values_cell; + ListCell *l; + List *strippedexprs; + + /* Insert the WITH clause if given */ + get_with_clause(query, context); + + /* + * If it's an INSERT ... SELECT or multi-row VALUES, there will be a + * single RTE for the SELECT or VALUES. Plain VALUES has neither. + */ + foreach(l, query->rtable) + { + rte = (RangeTblEntry *) lfirst(l); + + if (rte->rtekind == RTE_SUBQUERY) + { + if (select_rte) + elog(ERROR, "too many subquery RTEs in INSERT"); + select_rte = rte; + } + + if (rte->rtekind == RTE_VALUES) + { + if (values_rte) + elog(ERROR, "too many values RTEs in INSERT"); + values_rte = rte; + } + } + if (select_rte && values_rte) + elog(ERROR, "both subquery and values RTEs in INSERT"); + + /* + * Start the query with INSERT INTO relname + */ + rte = rt_fetch(query->resultRelation, query->rtable); + Assert(rte->rtekind == RTE_RELATION); + + if (PRETTY_INDENT(context)) + { + context->indentLevel += PRETTYINDENT_STD; + appendStringInfoChar(buf, ' '); + } + appendStringInfo(buf, "INSERT INTO %s ", + generate_relation_or_shard_name(rte->relid, + context->distrelid, + context->shardid, NIL)); + /* INSERT requires AS keyword for target alias */ + if (rte->alias != NULL) + appendStringInfo(buf, "AS %s ", + quote_identifier(rte->alias->aliasname)); + + /* + * Add the insert-column-names list. To handle indirection properly, we + * need to look for indirection nodes in the top targetlist (if it's + * INSERT ... SELECT or INSERT ... single VALUES), or in the first + * expression list of the VALUES RTE (if it's INSERT ... multi VALUES). We + * assume that all the expression lists will have similar indirection in + * the latter case. + */ + if (values_rte) + values_cell = list_head((List *) linitial(values_rte->values_lists)); + else + values_cell = NULL; + strippedexprs = NIL; + sep = ""; + if (query->targetList) + appendStringInfoChar(buf, '('); + foreach(l, query->targetList) + { + TargetEntry *tle = (TargetEntry *) lfirst(l); + + if (tle->resjunk) + continue; /* ignore junk entries */ + + appendStringInfoString(buf, sep); + sep = ", "; + + /* + * Put out name of target column; look in the catalogs, not at + * tle->resname, since resname will fail to track RENAME. + */ + appendStringInfoString(buf, + quote_identifier(get_relid_attribute_name(rte->relid, + tle->resno))); + + /* + * Print any indirection needed (subfields or subscripts), and strip + * off the top-level nodes representing the indirection assignments. + */ + if (values_cell) + { + /* we discard the stripped expression in this case */ + processIndirection((Node *) lfirst(values_cell), context, true); + values_cell = lnext(values_cell); + } + else + { + /* we keep a list of the stripped expressions in this case */ + strippedexprs = lappend(strippedexprs, + processIndirection((Node *) tle->expr, + context, true)); + } + } + if (query->targetList) + appendStringInfoString(buf, ") "); + + if (select_rte) + { + /* Add the SELECT */ + get_query_def(select_rte->subquery, buf, NIL, NULL, + context->prettyFlags, context->wrapColumn, + context->indentLevel); + } + else if (values_rte) + { + /* Add the multi-VALUES expression lists */ + get_values_def(values_rte->values_lists, context); + } + else if (strippedexprs) + { + /* Add the single-VALUES expression list */ + appendContextKeyword(context, "VALUES (", + -PRETTYINDENT_STD, PRETTYINDENT_STD, 2); + get_rule_expr((Node *) strippedexprs, context, false); + appendStringInfoChar(buf, ')'); + } + else + { + /* No expressions, so it must be DEFAULT VALUES */ + appendStringInfoString(buf, "DEFAULT VALUES"); + } + + /* Add ON CONFLICT if present */ + if (query->onConflict) + { + OnConflictExpr *confl = query->onConflict; + + appendStringInfoString(buf, " ON CONFLICT"); + + if (confl->arbiterElems) + { + /* Add the single-VALUES expression list */ + appendStringInfoChar(buf, '('); + get_rule_expr((Node *) confl->arbiterElems, context, false); + appendStringInfoChar(buf, ')'); + + /* Add a WHERE clause (for partial indexes) if given */ + if (confl->arbiterWhere != NULL) + { + bool varprefixInitialValue = context->varprefix; + + appendContextKeyword(context, " WHERE ", + -PRETTYINDENT_STD, PRETTYINDENT_STD, 1); + + /* + * Postgres deparses arbiter WHERE clauses incorrectly. It adds + * varprefix to the arbiter WHERE clause, for which Postgres parser + * errors out. Thus, we temporarily set varprefix to false. + */ + context->varprefix = false; + + get_rule_expr(confl->arbiterWhere, context, false); + + /* now set the varprefix back to its initial value */ + context->varprefix = varprefixInitialValue; + } + } + else if (confl->constraint != InvalidOid) + { + char *constraint = get_constraint_name(confl->constraint); + int64 shardId = context->shardid; + + if (shardId > 0) + { + AppendShardIdToName(&constraint, shardId); + } + + appendStringInfo(buf, " ON CONSTRAINT %s", + quote_qualified_identifier(NULL, constraint)); + } + + if (confl->action == ONCONFLICT_NOTHING) + { + appendStringInfoString(buf, " DO NOTHING"); + } + else + { + appendStringInfoString(buf, " DO UPDATE SET "); + /* Deparse targetlist */ + get_update_query_targetlist_def(query, confl->onConflictSet, + context, rte); + + /* Add a WHERE clause if given */ + if (confl->onConflictWhere != NULL) + { + appendContextKeyword(context, " WHERE ", + -PRETTYINDENT_STD, PRETTYINDENT_STD, 1); + get_rule_expr(confl->onConflictWhere, context, false); + } + } + } + + /* Add RETURNING if present */ + if (query->returningList) + { + appendContextKeyword(context, " RETURNING", + -PRETTYINDENT_STD, PRETTYINDENT_STD, 1); + get_target_list(query->returningList, context, NULL); + } +} + + +/* ---------- + * get_update_query_def - Parse back an UPDATE parsetree + * ---------- + */ +static void +get_update_query_def(Query *query, deparse_context *context) +{ + StringInfo buf = context->buf; + RangeTblEntry *rte; + + /* Insert the WITH clause if given */ + get_with_clause(query, context); + + /* + * Start the query with UPDATE relname SET + */ + rte = rt_fetch(query->resultRelation, query->rtable); + Assert(rte->rtekind == RTE_RELATION); + if (PRETTY_INDENT(context)) + { + appendStringInfoChar(buf, ' '); + context->indentLevel += PRETTYINDENT_STD; + } + appendStringInfo(buf, "UPDATE %s%s", + only_marker(rte), + generate_relation_or_shard_name(rte->relid, + context->distrelid, + context->shardid, NIL)); + if (rte->alias != NULL) + appendStringInfo(buf, " %s", + quote_identifier(rte->alias->aliasname)); + appendStringInfoString(buf, " SET "); + + /* Deparse targetlist */ + get_update_query_targetlist_def(query, query->targetList, context, rte); + + /* Add the FROM clause if needed */ + get_from_clause(query, " FROM ", context); + + /* Add a WHERE clause if given */ + if (query->jointree->quals != NULL) + { + appendContextKeyword(context, " WHERE ", + -PRETTYINDENT_STD, PRETTYINDENT_STD, 1); + get_rule_expr(query->jointree->quals, context, false); + } + + /* Add RETURNING if present */ + if (query->returningList) + { + appendContextKeyword(context, " RETURNING", + -PRETTYINDENT_STD, PRETTYINDENT_STD, 1); + get_target_list(query->returningList, context, NULL); + } +} + + +/* ---------- + * get_update_query_targetlist_def - Parse back an UPDATE targetlist + * ---------- + */ +static void +get_update_query_targetlist_def(Query *query, List *targetList, + deparse_context *context, RangeTblEntry *rte) +{ + StringInfo buf = context->buf; + ListCell *l; + ListCell *next_ma_cell; + int remaining_ma_columns; + const char *sep; + SubLink *cur_ma_sublink; + List *ma_sublinks; + + /* + * Prepare to deal with MULTIEXPR assignments: collect the source SubLinks + * into a list. We expect them to appear, in ID order, in resjunk tlist + * entries. + */ + ma_sublinks = NIL; + if (query->hasSubLinks) /* else there can't be any */ + { + foreach(l, targetList) + { + TargetEntry *tle = (TargetEntry *) lfirst(l); + + if (tle->resjunk && IsA(tle->expr, SubLink)) + { + SubLink *sl = (SubLink *) tle->expr; + + if (sl->subLinkType == MULTIEXPR_SUBLINK) + { + ma_sublinks = lappend(ma_sublinks, sl); + Assert(sl->subLinkId == list_length(ma_sublinks)); + } + } + } + } + next_ma_cell = list_head(ma_sublinks); + cur_ma_sublink = NULL; + remaining_ma_columns = 0; + + /* Add the comma separated list of 'attname = value' */ + sep = ""; + foreach(l, targetList) + { + TargetEntry *tle = (TargetEntry *) lfirst(l); + Node *expr; + + if (tle->resjunk) + continue; /* ignore junk entries */ + + /* Emit separator (OK whether we're in multiassignment or not) */ + appendStringInfoString(buf, sep); + sep = ", "; + + /* + * Check to see if we're starting a multiassignment group: if so, + * output a left paren. + */ + if (next_ma_cell != NULL && cur_ma_sublink == NULL) + { + /* + * We must dig down into the expr to see if it's a PARAM_MULTIEXPR + * Param. That could be buried under FieldStores and ArrayRefs + * (cf processIndirection()), and underneath those there could be + * an implicit type coercion. + */ + expr = (Node *) tle->expr; + while (expr) + { + if (IsA(expr, FieldStore)) + { + FieldStore *fstore = (FieldStore *) expr; + + expr = (Node *) linitial(fstore->newvals); + } + else if (IsA(expr, ArrayRef)) + { + ArrayRef *aref = (ArrayRef *) expr; + + if (aref->refassgnexpr == NULL) + break; + expr = (Node *) aref->refassgnexpr; + } + else + break; + } + expr = strip_implicit_coercions(expr); + + if (expr && IsA(expr, Param) && + ((Param *) expr)->paramkind == PARAM_MULTIEXPR) + { + cur_ma_sublink = (SubLink *) lfirst(next_ma_cell); + next_ma_cell = lnext(next_ma_cell); + remaining_ma_columns = count_nonjunk_tlist_entries( + ((Query *) cur_ma_sublink->subselect)->targetList); + Assert(((Param *) expr)->paramid == + ((cur_ma_sublink->subLinkId << 16) | 1)); + appendStringInfoChar(buf, '('); + } + } + + /* + * Put out name of target column; look in the catalogs, not at + * tle->resname, since resname will fail to track RENAME. + */ + appendStringInfoString(buf, + quote_identifier(get_relid_attribute_name(rte->relid, + tle->resno))); + + /* + * Print any indirection needed (subfields or subscripts), and strip + * off the top-level nodes representing the indirection assignments. + */ + expr = processIndirection((Node *) tle->expr, context, true); + + /* + * If we're in a multiassignment, skip printing anything more, unless + * this is the last column; in which case, what we print should be the + * sublink, not the Param. + */ + if (cur_ma_sublink != NULL) + { + if (--remaining_ma_columns > 0) + continue; /* not the last column of multiassignment */ + appendStringInfoChar(buf, ')'); + expr = (Node *) cur_ma_sublink; + cur_ma_sublink = NULL; + } + + appendStringInfoString(buf, " = "); + + get_rule_expr(expr, context, false); + } +} + + +/* ---------- + * get_delete_query_def - Parse back a DELETE parsetree + * ---------- + */ +static void +get_delete_query_def(Query *query, deparse_context *context) +{ + StringInfo buf = context->buf; + RangeTblEntry *rte; + + /* Insert the WITH clause if given */ + get_with_clause(query, context); + + /* + * Start the query with DELETE FROM relname + */ + rte = rt_fetch(query->resultRelation, query->rtable); + Assert(rte->rtekind == RTE_RELATION); + if (PRETTY_INDENT(context)) + { + appendStringInfoChar(buf, ' '); + context->indentLevel += PRETTYINDENT_STD; + } + appendStringInfo(buf, "DELETE FROM %s%s", + only_marker(rte), + generate_relation_or_shard_name(rte->relid, + context->distrelid, + context->shardid, NIL)); + if (rte->alias != NULL) + appendStringInfo(buf, " %s", + quote_identifier(rte->alias->aliasname)); + + /* Add the USING clause if given */ + get_from_clause(query, " USING ", context); + + /* Add a WHERE clause if given */ + if (query->jointree->quals != NULL) + { + appendContextKeyword(context, " WHERE ", + -PRETTYINDENT_STD, PRETTYINDENT_STD, 1); + get_rule_expr(query->jointree->quals, context, false); + } + + /* Add RETURNING if present */ + if (query->returningList) + { + appendContextKeyword(context, " RETURNING", + -PRETTYINDENT_STD, PRETTYINDENT_STD, 1); + get_target_list(query->returningList, context, NULL); + } +} + + +/* ---------- + * get_utility_query_def - Parse back a UTILITY parsetree + * ---------- + */ +static void +get_utility_query_def(Query *query, deparse_context *context) +{ + StringInfo buf = context->buf; + + if (query->utilityStmt && IsA(query->utilityStmt, NotifyStmt)) + { + NotifyStmt *stmt = (NotifyStmt *) query->utilityStmt; + + appendContextKeyword(context, "", + 0, PRETTYINDENT_STD, 1); + appendStringInfo(buf, "NOTIFY %s", + quote_identifier(stmt->conditionname)); + if (stmt->payload) + { + appendStringInfoString(buf, ", "); + simple_quote_literal(buf, stmt->payload); + } + } + else + { + /* Currently only NOTIFY utility commands can appear in rules */ + elog(ERROR, "unexpected utility statement type"); + } +} + + +/* + * Display a Var appropriately. + * + * In some cases (currently only when recursing into an unnamed join) + * the Var's varlevelsup has to be interpreted with respect to a context + * above the current one; levelsup indicates the offset. + * + * If istoplevel is TRUE, the Var is at the top level of a SELECT's + * targetlist, which means we need special treatment of whole-row Vars. + * Instead of the normal "tab.*", we'll print "tab.*::typename", which is a + * dirty hack to prevent "tab.*" from being expanded into multiple columns. + * (The parser will strip the useless coercion, so no inefficiency is added in + * dump and reload.) We used to print just "tab" in such cases, but that is + * ambiguous and will yield the wrong result if "tab" is also a plain column + * name in the query. + * + * Returns the attname of the Var, or NULL if the Var has no attname (because + * it is a whole-row Var or a subplan output reference). + */ +static char * +get_variable(Var *var, int levelsup, bool istoplevel, deparse_context *context) +{ + StringInfo buf = context->buf; + RangeTblEntry *rte; + AttrNumber attnum; + int netlevelsup; + deparse_namespace *dpns; + deparse_columns *colinfo; + char *refname; + char *attname; + + /* Find appropriate nesting depth */ + netlevelsup = var->varlevelsup + levelsup; + if (netlevelsup >= list_length(context->namespaces)) + elog(ERROR, "bogus varlevelsup: %d offset %d", + var->varlevelsup, levelsup); + dpns = (deparse_namespace *) list_nth(context->namespaces, + netlevelsup); + + /* + * Try to find the relevant RTE in this rtable. In a plan tree, it's + * likely that varno is OUTER_VAR or INNER_VAR, in which case we must dig + * down into the subplans, or INDEX_VAR, which is resolved similarly. Also + * find the aliases previously assigned for this RTE. + */ + if (var->varno >= 1 && var->varno <= list_length(dpns->rtable)) + { + rte = rt_fetch(var->varno, dpns->rtable); + refname = (char *) list_nth(dpns->rtable_names, var->varno - 1); + colinfo = deparse_columns_fetch(var->varno, dpns); + attnum = var->varattno; + } + else if (var->varno == OUTER_VAR && dpns->outer_tlist) + { + TargetEntry *tle; + deparse_namespace save_dpns; + + tle = get_tle_by_resno(dpns->outer_tlist, var->varattno); + if (!tle) + elog(ERROR, "bogus varattno for OUTER_VAR var: %d", var->varattno); + + Assert(netlevelsup == 0); + push_child_plan(dpns, dpns->outer_planstate, &save_dpns); + + /* + * Force parentheses because our caller probably assumed a Var is a + * simple expression. + */ + if (!IsA(tle->expr, Var)) + appendStringInfoChar(buf, '('); + get_rule_expr((Node *) tle->expr, context, true); + if (!IsA(tle->expr, Var)) + appendStringInfoChar(buf, ')'); + + pop_child_plan(dpns, &save_dpns); + return NULL; + } + else if (var->varno == INNER_VAR && dpns->inner_tlist) + { + TargetEntry *tle; + deparse_namespace save_dpns; + + tle = get_tle_by_resno(dpns->inner_tlist, var->varattno); + if (!tle) + elog(ERROR, "bogus varattno for INNER_VAR var: %d", var->varattno); + + Assert(netlevelsup == 0); + push_child_plan(dpns, dpns->inner_planstate, &save_dpns); + + /* + * Force parentheses because our caller probably assumed a Var is a + * simple expression. + */ + if (!IsA(tle->expr, Var)) + appendStringInfoChar(buf, '('); + get_rule_expr((Node *) tle->expr, context, true); + if (!IsA(tle->expr, Var)) + appendStringInfoChar(buf, ')'); + + pop_child_plan(dpns, &save_dpns); + return NULL; + } + else if (var->varno == INDEX_VAR && dpns->index_tlist) + { + TargetEntry *tle; + + tle = get_tle_by_resno(dpns->index_tlist, var->varattno); + if (!tle) + elog(ERROR, "bogus varattno for INDEX_VAR var: %d", var->varattno); + + Assert(netlevelsup == 0); + + /* + * Force parentheses because our caller probably assumed a Var is a + * simple expression. + */ + if (!IsA(tle->expr, Var)) + appendStringInfoChar(buf, '('); + get_rule_expr((Node *) tle->expr, context, true); + if (!IsA(tle->expr, Var)) + appendStringInfoChar(buf, ')'); + + return NULL; + } + else + { + elog(ERROR, "bogus varno: %d", var->varno); + return NULL; /* keep compiler quiet */ + } + + /* + * The planner will sometimes emit Vars referencing resjunk elements of a + * subquery's target list (this is currently only possible if it chooses + * to generate a "physical tlist" for a SubqueryScan or CteScan node). + * Although we prefer to print subquery-referencing Vars using the + * subquery's alias, that's not possible for resjunk items since they have + * no alias. So in that case, drill down to the subplan and print the + * contents of the referenced tlist item. This works because in a plan + * tree, such Vars can only occur in a SubqueryScan or CteScan node, and + * we'll have set dpns->inner_planstate to reference the child plan node. + */ + if ((rte->rtekind == RTE_SUBQUERY || rte->rtekind == RTE_CTE) && + attnum > list_length(rte->eref->colnames) && + dpns->inner_planstate) + { + TargetEntry *tle; + deparse_namespace save_dpns; + + tle = get_tle_by_resno(dpns->inner_tlist, var->varattno); + if (!tle) + elog(ERROR, "bogus varattno for subquery var: %d", var->varattno); + + Assert(netlevelsup == 0); + push_child_plan(dpns, dpns->inner_planstate, &save_dpns); + + /* + * Force parentheses because our caller probably assumed a Var is a + * simple expression. + */ + if (!IsA(tle->expr, Var)) + appendStringInfoChar(buf, '('); + get_rule_expr((Node *) tle->expr, context, true); + if (!IsA(tle->expr, Var)) + appendStringInfoChar(buf, ')'); + + pop_child_plan(dpns, &save_dpns); + return NULL; + } + + /* + * If it's an unnamed join, look at the expansion of the alias variable. + * If it's a simple reference to one of the input vars, then recursively + * print the name of that var instead. When it's not a simple reference, + * we have to just print the unqualified join column name. (This can only + * happen with "dangerous" merged columns in a JOIN USING; we took pains + * previously to make the unqualified column name unique in such cases.) + * + * This wouldn't work in decompiling plan trees, because we don't store + * joinaliasvars lists after planning; but a plan tree should never + * contain a join alias variable. + */ + if (rte->rtekind == RTE_JOIN && rte->alias == NULL) + { + if (rte->joinaliasvars == NIL) + elog(ERROR, "cannot decompile join alias var in plan tree"); + if (attnum > 0) + { + Var *aliasvar; + + aliasvar = (Var *) list_nth(rte->joinaliasvars, attnum - 1); + /* we intentionally don't strip implicit coercions here */ + if (aliasvar && IsA(aliasvar, Var)) + { + return get_variable(aliasvar, var->varlevelsup + levelsup, + istoplevel, context); + } + } + + /* + * Unnamed join has no refname. (Note: since it's unnamed, there is + * no way the user could have referenced it to create a whole-row Var + * for it. So we don't have to cover that case below.) + */ + Assert(refname == NULL); + } + + if (attnum == InvalidAttrNumber) + attname = NULL; + else if (attnum > 0) + { + /* Get column name to use from the colinfo struct */ + Assert(attnum <= colinfo->num_cols); + attname = colinfo->colnames[attnum - 1]; + Assert(attname != NULL); + } + else + { + /* System column - name is fixed, get it from the catalog */ + attname = get_rte_attribute_name(rte, attnum); + } + + if (refname && (context->varprefix || attname == NULL)) + { + appendStringInfoString(buf, quote_identifier(refname)); + appendStringInfoChar(buf, '.'); + } + if (attname) + appendStringInfoString(buf, quote_identifier(attname)); + else + { + appendStringInfoChar(buf, '*'); + if (istoplevel) + appendStringInfo(buf, "::%s", + format_type_with_typemod(var->vartype, + var->vartypmod)); + } + + return attname; +} + + +/* + * Get the name of a field of an expression of composite type. The + * expression is usually a Var, but we handle other cases too. + * + * levelsup is an extra offset to interpret the Var's varlevelsup correctly. + * + * This is fairly straightforward when the expression has a named composite + * type; we need only look up the type in the catalogs. However, the type + * could also be RECORD. Since no actual table or view column is allowed to + * have type RECORD, a Var of type RECORD must refer to a JOIN or FUNCTION RTE + * or to a subquery output. We drill down to find the ultimate defining + * expression and attempt to infer the field name from it. We ereport if we + * can't determine the name. + * + * Similarly, a PARAM of type RECORD has to refer to some expression of + * a determinable composite type. + */ +static const char * +get_name_for_var_field(Var *var, int fieldno, + int levelsup, deparse_context *context) +{ + RangeTblEntry *rte; + AttrNumber attnum; + int netlevelsup; + deparse_namespace *dpns; + TupleDesc tupleDesc; + Node *expr; + + /* + * If it's a RowExpr that was expanded from a whole-row Var, use the + * column names attached to it. + */ + if (IsA(var, RowExpr)) + { + RowExpr *r = (RowExpr *) var; + + if (fieldno > 0 && fieldno <= list_length(r->colnames)) + return strVal(list_nth(r->colnames, fieldno - 1)); + } + + /* + * If it's a Param of type RECORD, try to find what the Param refers to. + */ + if (IsA(var, Param)) + { + Param *param = (Param *) var; + ListCell *ancestor_cell; + + expr = find_param_referent(param, context, &dpns, &ancestor_cell); + if (expr) + { + /* Found a match, so recurse to decipher the field name */ + deparse_namespace save_dpns; + const char *result; + + push_ancestor_plan(dpns, ancestor_cell, &save_dpns); + result = get_name_for_var_field((Var *) expr, fieldno, + 0, context); + pop_ancestor_plan(dpns, &save_dpns); + return result; + } + } + + /* + * If it's a Var of type RECORD, we have to find what the Var refers to; + * if not, we can use get_expr_result_type. If that fails, we try + * lookup_rowtype_tupdesc, which will probably fail too, but will ereport + * an acceptable message. + */ + if (!IsA(var, Var) || + var->vartype != RECORDOID) + { + if (get_expr_result_type((Node *) var, NULL, &tupleDesc) != TYPEFUNC_COMPOSITE) + tupleDesc = lookup_rowtype_tupdesc_copy(exprType((Node *) var), + exprTypmod((Node *) var)); + Assert(tupleDesc); + /* Got the tupdesc, so we can extract the field name */ + Assert(fieldno >= 1 && fieldno <= tupleDesc->natts); + return NameStr(tupleDesc->attrs[fieldno - 1]->attname); + } + + /* Find appropriate nesting depth */ + netlevelsup = var->varlevelsup + levelsup; + if (netlevelsup >= list_length(context->namespaces)) + elog(ERROR, "bogus varlevelsup: %d offset %d", + var->varlevelsup, levelsup); + dpns = (deparse_namespace *) list_nth(context->namespaces, + netlevelsup); + + /* + * Try to find the relevant RTE in this rtable. In a plan tree, it's + * likely that varno is OUTER_VAR or INNER_VAR, in which case we must dig + * down into the subplans, or INDEX_VAR, which is resolved similarly. + */ + if (var->varno >= 1 && var->varno <= list_length(dpns->rtable)) + { + rte = rt_fetch(var->varno, dpns->rtable); + attnum = var->varattno; + } + else if (var->varno == OUTER_VAR && dpns->outer_tlist) + { + TargetEntry *tle; + deparse_namespace save_dpns; + const char *result; + + tle = get_tle_by_resno(dpns->outer_tlist, var->varattno); + if (!tle) + elog(ERROR, "bogus varattno for OUTER_VAR var: %d", var->varattno); + + Assert(netlevelsup == 0); + push_child_plan(dpns, dpns->outer_planstate, &save_dpns); + + result = get_name_for_var_field((Var *) tle->expr, fieldno, + levelsup, context); + + pop_child_plan(dpns, &save_dpns); + return result; + } + else if (var->varno == INNER_VAR && dpns->inner_tlist) + { + TargetEntry *tle; + deparse_namespace save_dpns; + const char *result; + + tle = get_tle_by_resno(dpns->inner_tlist, var->varattno); + if (!tle) + elog(ERROR, "bogus varattno for INNER_VAR var: %d", var->varattno); + + Assert(netlevelsup == 0); + push_child_plan(dpns, dpns->inner_planstate, &save_dpns); + + result = get_name_for_var_field((Var *) tle->expr, fieldno, + levelsup, context); + + pop_child_plan(dpns, &save_dpns); + return result; + } + else if (var->varno == INDEX_VAR && dpns->index_tlist) + { + TargetEntry *tle; + const char *result; + + tle = get_tle_by_resno(dpns->index_tlist, var->varattno); + if (!tle) + elog(ERROR, "bogus varattno for INDEX_VAR var: %d", var->varattno); + + Assert(netlevelsup == 0); + + result = get_name_for_var_field((Var *) tle->expr, fieldno, + levelsup, context); + + return result; + } + else + { + elog(ERROR, "bogus varno: %d", var->varno); + return NULL; /* keep compiler quiet */ + } + + if (attnum == InvalidAttrNumber) + { + /* Var is whole-row reference to RTE, so select the right field */ + return get_rte_attribute_name(rte, fieldno); + } + + /* + * This part has essentially the same logic as the parser's + * expandRecordVariable() function, but we are dealing with a different + * representation of the input context, and we only need one field name + * not a TupleDesc. Also, we need special cases for finding subquery and + * CTE subplans when deparsing Plan trees. + */ + expr = (Node *) var; /* default if we can't drill down */ + + switch (rte->rtekind) + { + case RTE_RELATION: + case RTE_VALUES: + + /* + * This case should not occur: a column of a table or values list + * shouldn't have type RECORD. Fall through and fail (most + * likely) at the bottom. + */ + break; + case RTE_SUBQUERY: + /* Subselect-in-FROM: examine sub-select's output expr */ + { + if (rte->subquery) + { + TargetEntry *ste = get_tle_by_resno(rte->subquery->targetList, + attnum); + + if (ste == NULL || ste->resjunk) + elog(ERROR, "subquery %s does not have attribute %d", + rte->eref->aliasname, attnum); + expr = (Node *) ste->expr; + if (IsA(expr, Var)) + { + /* + * Recurse into the sub-select to see what its Var + * refers to. We have to build an additional level of + * namespace to keep in step with varlevelsup in the + * subselect. + */ + deparse_namespace mydpns; + const char *result; + + set_deparse_for_query(&mydpns, rte->subquery, + context->namespaces); + + context->namespaces = lcons(&mydpns, + context->namespaces); + + result = get_name_for_var_field((Var *) expr, fieldno, + 0, context); + + context->namespaces = + list_delete_first(context->namespaces); + + return result; + } + /* else fall through to inspect the expression */ + } + else + { + /* + * We're deparsing a Plan tree so we don't have complete + * RTE entries (in particular, rte->subquery is NULL). But + * the only place we'd see a Var directly referencing a + * SUBQUERY RTE is in a SubqueryScan plan node, and we can + * look into the child plan's tlist instead. + */ + TargetEntry *tle; + deparse_namespace save_dpns; + const char *result; + + if (!dpns->inner_planstate) + elog(ERROR, "failed to find plan for subquery %s", + rte->eref->aliasname); + tle = get_tle_by_resno(dpns->inner_tlist, attnum); + if (!tle) + elog(ERROR, "bogus varattno for subquery var: %d", + attnum); + Assert(netlevelsup == 0); + push_child_plan(dpns, dpns->inner_planstate, &save_dpns); + + result = get_name_for_var_field((Var *) tle->expr, fieldno, + levelsup, context); + + pop_child_plan(dpns, &save_dpns); + return result; + } + } + break; + case RTE_JOIN: + /* Join RTE --- recursively inspect the alias variable */ + if (rte->joinaliasvars == NIL) + elog(ERROR, "cannot decompile join alias var in plan tree"); + Assert(attnum > 0 && attnum <= list_length(rte->joinaliasvars)); + expr = (Node *) list_nth(rte->joinaliasvars, attnum - 1); + Assert(expr != NULL); + /* we intentionally don't strip implicit coercions here */ + if (IsA(expr, Var)) + return get_name_for_var_field((Var *) expr, fieldno, + var->varlevelsup + levelsup, + context); + /* else fall through to inspect the expression */ + break; + case RTE_FUNCTION: + + /* + * We couldn't get here unless a function is declared with one of + * its result columns as RECORD, which is not allowed. + */ + break; + case RTE_CTE: + /* CTE reference: examine subquery's output expr */ + { + CommonTableExpr *cte = NULL; + Index ctelevelsup; + ListCell *lc; + + /* + * Try to find the referenced CTE using the namespace stack. + */ + ctelevelsup = rte->ctelevelsup + netlevelsup; + if (ctelevelsup >= list_length(context->namespaces)) + lc = NULL; + else + { + deparse_namespace *ctedpns; + + ctedpns = (deparse_namespace *) + list_nth(context->namespaces, ctelevelsup); + foreach(lc, ctedpns->ctes) + { + cte = (CommonTableExpr *) lfirst(lc); + if (strcmp(cte->ctename, rte->ctename) == 0) + break; + } + } + if (lc != NULL) + { + Query *ctequery = (Query *) cte->ctequery; + TargetEntry *ste = get_tle_by_resno(GetCTETargetList(cte), + attnum); + + if (ste == NULL || ste->resjunk) + elog(ERROR, "subquery %s does not have attribute %d", + rte->eref->aliasname, attnum); + expr = (Node *) ste->expr; + if (IsA(expr, Var)) + { + /* + * Recurse into the CTE to see what its Var refers to. + * We have to build an additional level of namespace + * to keep in step with varlevelsup in the CTE. + * Furthermore it could be an outer CTE, so we may + * have to delete some levels of namespace. + */ + List *save_nslist = context->namespaces; + List *new_nslist; + deparse_namespace mydpns; + const char *result; + + set_deparse_for_query(&mydpns, ctequery, + context->namespaces); + + new_nslist = list_copy_tail(context->namespaces, + ctelevelsup); + context->namespaces = lcons(&mydpns, new_nslist); + + result = get_name_for_var_field((Var *) expr, fieldno, + 0, context); + + context->namespaces = save_nslist; + + return result; + } + /* else fall through to inspect the expression */ + } + else + { + /* + * We're deparsing a Plan tree so we don't have a CTE + * list. But the only place we'd see a Var directly + * referencing a CTE RTE is in a CteScan plan node, and we + * can look into the subplan's tlist instead. + */ + TargetEntry *tle; + deparse_namespace save_dpns; + const char *result; + + if (!dpns->inner_planstate) + elog(ERROR, "failed to find plan for CTE %s", + rte->eref->aliasname); + tle = get_tle_by_resno(dpns->inner_tlist, attnum); + if (!tle) + elog(ERROR, "bogus varattno for subquery var: %d", + attnum); + Assert(netlevelsup == 0); + push_child_plan(dpns, dpns->inner_planstate, &save_dpns); + + result = get_name_for_var_field((Var *) tle->expr, fieldno, + levelsup, context); + + pop_child_plan(dpns, &save_dpns); + return result; + } + } + break; + } + + /* + * We now have an expression we can't expand any more, so see if + * get_expr_result_type() can do anything with it. If not, pass to + * lookup_rowtype_tupdesc() which will probably fail, but will give an + * appropriate error message while failing. + */ + if (get_expr_result_type(expr, NULL, &tupleDesc) != TYPEFUNC_COMPOSITE) + tupleDesc = lookup_rowtype_tupdesc_copy(exprType(expr), + exprTypmod(expr)); + Assert(tupleDesc); + /* Got the tupdesc, so we can extract the field name */ + Assert(fieldno >= 1 && fieldno <= tupleDesc->natts); + return NameStr(tupleDesc->attrs[fieldno - 1]->attname); +} + +/* + * Try to find the referenced expression for a PARAM_EXEC Param that might + * reference a parameter supplied by an upper NestLoop or SubPlan plan node. + * + * If successful, return the expression and set *dpns_p and *ancestor_cell_p + * appropriately for calling push_ancestor_plan(). If no referent can be + * found, return NULL. + */ +static Node * +find_param_referent(Param *param, deparse_context *context, + deparse_namespace **dpns_p, ListCell **ancestor_cell_p) +{ + /* Initialize output parameters to prevent compiler warnings */ + *dpns_p = NULL; + *ancestor_cell_p = NULL; + + /* + * If it's a PARAM_EXEC parameter, look for a matching NestLoopParam or + * SubPlan argument. This will necessarily be in some ancestor of the + * current expression's PlanState. + */ + if (param->paramkind == PARAM_EXEC) + { + deparse_namespace *dpns; + PlanState *child_ps; + bool in_same_plan_level; + ListCell *lc; + + dpns = (deparse_namespace *) linitial(context->namespaces); + child_ps = dpns->planstate; + in_same_plan_level = true; + + foreach(lc, dpns->ancestors) + { + PlanState *ps = (PlanState *) lfirst(lc); + ListCell *lc2; + + /* + * NestLoops transmit params to their inner child only; also, once + * we've crawled up out of a subplan, this couldn't possibly be + * the right match. + */ + if (IsA(ps, NestLoopState) && + child_ps == innerPlanState(ps) && + in_same_plan_level) + { + NestLoop *nl = (NestLoop *) ps->plan; + + foreach(lc2, nl->nestParams) + { + NestLoopParam *nlp = (NestLoopParam *) lfirst(lc2); + + if (nlp->paramno == param->paramid) + { + /* Found a match, so return it */ + *dpns_p = dpns; + *ancestor_cell_p = lc; + return (Node *) nlp->paramval; + } + } + } + + /* + * Check to see if we're crawling up from a subplan. + */ + foreach(lc2, ps->subPlan) + { + SubPlanState *sstate = (SubPlanState *) lfirst(lc2); + SubPlan *subplan = (SubPlan *) sstate->xprstate.expr; + ListCell *lc3; + ListCell *lc4; + + if (child_ps != sstate->planstate) + continue; + + /* Matched subplan, so check its arguments */ + forboth(lc3, subplan->parParam, lc4, subplan->args) + { + int paramid = lfirst_int(lc3); + Node *arg = (Node *) lfirst(lc4); + + if (paramid == param->paramid) + { + /* Found a match, so return it */ + *dpns_p = dpns; + *ancestor_cell_p = lc; + return arg; + } + } + + /* Keep looking, but we are emerging from a subplan. */ + in_same_plan_level = false; + break; + } + + /* + * Likewise check to see if we're emerging from an initplan. + * Initplans never have any parParams, so no need to search that + * list, but we need to know if we should reset + * in_same_plan_level. + */ + foreach(lc2, ps->initPlan) + { + SubPlanState *sstate = (SubPlanState *) lfirst(lc2); + + if (child_ps != sstate->planstate) + continue; + + /* No parameters to be had here. */ + Assert(((SubPlan *) sstate->xprstate.expr)->parParam == NIL); + + /* Keep looking, but we are emerging from an initplan. */ + in_same_plan_level = false; + break; + } + + /* No luck, crawl up to next ancestor */ + child_ps = ps; + } + } + + /* No referent found */ + return NULL; +} + +/* + * Display a Param appropriately. + */ +static void +get_parameter(Param *param, deparse_context *context) +{ + Node *expr; + deparse_namespace *dpns; + ListCell *ancestor_cell; + + /* + * If it's a PARAM_EXEC parameter, try to locate the expression from which + * the parameter was computed. Note that failing to find a referent isn't + * an error, since the Param might well be a subplan output rather than an + * input. + */ + expr = find_param_referent(param, context, &dpns, &ancestor_cell); + if (expr) + { + /* Found a match, so print it */ + deparse_namespace save_dpns; + bool save_varprefix; + bool need_paren; + + /* Switch attention to the ancestor plan node */ + push_ancestor_plan(dpns, ancestor_cell, &save_dpns); + + /* + * Force prefixing of Vars, since they won't belong to the relation + * being scanned in the original plan node. + */ + save_varprefix = context->varprefix; + context->varprefix = true; + + /* + * A Param's expansion is typically a Var, Aggref, or upper-level + * Param, which wouldn't need extra parentheses. Otherwise, insert + * parens to ensure the expression looks atomic. + */ + need_paren = !(IsA(expr, Var) || + IsA(expr, Aggref) || + IsA(expr, Param)); + if (need_paren) + appendStringInfoChar(context->buf, '('); + + get_rule_expr(expr, context, false); + + if (need_paren) + appendStringInfoChar(context->buf, ')'); + + context->varprefix = save_varprefix; + + pop_ancestor_plan(dpns, &save_dpns); + + return; + } + + /* + * Not PARAM_EXEC, or couldn't find referent: just print $N. + */ + appendStringInfo(context->buf, "$%d", param->paramid); +} + +/* + * get_simple_binary_op_name + * + * helper function for isSimpleNode + * will return single char binary operator name, or NULL if it's not + */ +static const char * +get_simple_binary_op_name(OpExpr *expr) +{ + List *args = expr->args; + + if (list_length(args) == 2) + { + /* binary operator */ + Node *arg1 = (Node *) linitial(args); + Node *arg2 = (Node *) lsecond(args); + const char *op; + + op = generate_operator_name(expr->opno, exprType(arg1), exprType(arg2)); + if (strlen(op) == 1) + return op; + } + return NULL; +} + + +/* + * isSimpleNode - check if given node is simple (doesn't need parenthesizing) + * + * true : simple in the context of parent node's type + * false : not simple + */ +static bool +isSimpleNode(Node *node, Node *parentNode, int prettyFlags) +{ + if (!node) + return false; + + switch (nodeTag(node)) + { + case T_Var: + case T_Const: + case T_Param: + case T_CoerceToDomainValue: + case T_SetToDefault: + case T_CurrentOfExpr: + /* single words: always simple */ + return true; + + case T_ArrayRef: + case T_ArrayExpr: + case T_RowExpr: + case T_CoalesceExpr: + case T_MinMaxExpr: + case T_XmlExpr: + case T_NullIfExpr: + case T_Aggref: + case T_WindowFunc: + case T_FuncExpr: + /* function-like: name(..) or name[..] */ + return true; + + /* CASE keywords act as parentheses */ + case T_CaseExpr: + return true; + + case T_FieldSelect: + + /* + * appears simple since . has top precedence, unless parent is + * T_FieldSelect itself! + */ + return (IsA(parentNode, FieldSelect) ? false : true); + + case T_FieldStore: + + /* + * treat like FieldSelect (probably doesn't matter) + */ + return (IsA(parentNode, FieldStore) ? false : true); + + case T_CoerceToDomain: + /* maybe simple, check args */ + return isSimpleNode((Node *) ((CoerceToDomain *) node)->arg, + node, prettyFlags); + case T_RelabelType: + return isSimpleNode((Node *) ((RelabelType *) node)->arg, + node, prettyFlags); + case T_CoerceViaIO: + return isSimpleNode((Node *) ((CoerceViaIO *) node)->arg, + node, prettyFlags); + case T_ArrayCoerceExpr: + return isSimpleNode((Node *) ((ArrayCoerceExpr *) node)->arg, + node, prettyFlags); + case T_ConvertRowtypeExpr: + return isSimpleNode((Node *) ((ConvertRowtypeExpr *) node)->arg, + node, prettyFlags); + + case T_OpExpr: + { + /* depends on parent node type; needs further checking */ + if (prettyFlags & PRETTYFLAG_PAREN && IsA(parentNode, OpExpr)) + { + const char *op; + const char *parentOp; + bool is_lopriop; + bool is_hipriop; + bool is_lopriparent; + bool is_hipriparent; + + op = get_simple_binary_op_name((OpExpr *) node); + if (!op) + return false; + + /* We know only the basic operators + - and * / % */ + is_lopriop = (strchr("+-", *op) != NULL); + is_hipriop = (strchr("*/%", *op) != NULL); + if (!(is_lopriop || is_hipriop)) + return false; + + parentOp = get_simple_binary_op_name((OpExpr *) parentNode); + if (!parentOp) + return false; + + is_lopriparent = (strchr("+-", *parentOp) != NULL); + is_hipriparent = (strchr("*/%", *parentOp) != NULL); + if (!(is_lopriparent || is_hipriparent)) + return false; + + if (is_hipriop && is_lopriparent) + return true; /* op binds tighter than parent */ + + if (is_lopriop && is_hipriparent) + return false; + + /* + * Operators are same priority --- can skip parens only if + * we have (a - b) - c, not a - (b - c). + */ + if (node == (Node *) linitial(((OpExpr *) parentNode)->args)) + return true; + + return false; + } + /* else do the same stuff as for T_SubLink et al. */ + /* FALL THROUGH */ + } + + case T_SubLink: + case T_NullTest: + case T_BooleanTest: + case T_DistinctExpr: + switch (nodeTag(parentNode)) + { + case T_FuncExpr: + { + /* special handling for casts */ + CoercionForm type = ((FuncExpr *) parentNode)->funcformat; + + if (type == COERCE_EXPLICIT_CAST || + type == COERCE_IMPLICIT_CAST) + return false; + return true; /* own parentheses */ + } + case T_BoolExpr: /* lower precedence */ + case T_ArrayRef: /* other separators */ + case T_ArrayExpr: /* other separators */ + case T_RowExpr: /* other separators */ + case T_CoalesceExpr: /* own parentheses */ + case T_MinMaxExpr: /* own parentheses */ + case T_XmlExpr: /* own parentheses */ + case T_NullIfExpr: /* other separators */ + case T_Aggref: /* own parentheses */ + case T_WindowFunc: /* own parentheses */ + case T_CaseExpr: /* other separators */ + return true; + default: + return false; + } + + case T_BoolExpr: + switch (nodeTag(parentNode)) + { + case T_BoolExpr: + if (prettyFlags & PRETTYFLAG_PAREN) + { + BoolExprType type; + BoolExprType parentType; + + type = ((BoolExpr *) node)->boolop; + parentType = ((BoolExpr *) parentNode)->boolop; + switch (type) + { + case NOT_EXPR: + case AND_EXPR: + if (parentType == AND_EXPR || parentType == OR_EXPR) + return true; + break; + case OR_EXPR: + if (parentType == OR_EXPR) + return true; + break; + } + } + return false; + case T_FuncExpr: + { + /* special handling for casts */ + CoercionForm type = ((FuncExpr *) parentNode)->funcformat; + + if (type == COERCE_EXPLICIT_CAST || + type == COERCE_IMPLICIT_CAST) + return false; + return true; /* own parentheses */ + } + case T_ArrayRef: /* other separators */ + case T_ArrayExpr: /* other separators */ + case T_RowExpr: /* other separators */ + case T_CoalesceExpr: /* own parentheses */ + case T_MinMaxExpr: /* own parentheses */ + case T_XmlExpr: /* own parentheses */ + case T_NullIfExpr: /* other separators */ + case T_Aggref: /* own parentheses */ + case T_WindowFunc: /* own parentheses */ + case T_CaseExpr: /* other separators */ + return true; + default: + return false; + } + + default: + break; + } + /* those we don't know: in dubio complexo */ + return false; +} + + +/* + * appendContextKeyword - append a keyword to buffer + * + * If prettyPrint is enabled, perform a line break, and adjust indentation. + * Otherwise, just append the keyword. + */ +static void +appendContextKeyword(deparse_context *context, const char *str, + int indentBefore, int indentAfter, int indentPlus) +{ + StringInfo buf = context->buf; + + if (PRETTY_INDENT(context)) + { + int indentAmount; + + context->indentLevel += indentBefore; + + /* remove any trailing spaces currently in the buffer ... */ + removeStringInfoSpaces(buf); + /* ... then add a newline and some spaces */ + appendStringInfoChar(buf, '\n'); + + if (context->indentLevel < PRETTYINDENT_LIMIT) + indentAmount = Max(context->indentLevel, 0) + indentPlus; + else + { + /* + * If we're indented more than PRETTYINDENT_LIMIT characters, try + * to conserve horizontal space by reducing the per-level + * indentation. For best results the scale factor here should + * divide all the indent amounts that get added to indentLevel + * (PRETTYINDENT_STD, etc). It's important that the indentation + * not grow unboundedly, else deeply-nested trees use O(N^2) + * whitespace; so we also wrap modulo PRETTYINDENT_LIMIT. + */ + indentAmount = PRETTYINDENT_LIMIT + + (context->indentLevel - PRETTYINDENT_LIMIT) / + (PRETTYINDENT_STD / 2); + indentAmount %= PRETTYINDENT_LIMIT; + /* scale/wrap logic affects indentLevel, but not indentPlus */ + indentAmount += indentPlus; + } + appendStringInfoSpaces(buf, indentAmount); + + appendStringInfoString(buf, str); + + context->indentLevel += indentAfter; + if (context->indentLevel < 0) + context->indentLevel = 0; + } + else + appendStringInfoString(buf, str); +} + +/* + * removeStringInfoSpaces - delete trailing spaces from a buffer. + * + * Possibly this should move to stringinfo.c at some point. + */ +static void +removeStringInfoSpaces(StringInfo str) +{ + while (str->len > 0 && str->data[str->len - 1] == ' ') + str->data[--(str->len)] = '\0'; +} + + +/* + * get_rule_expr_paren - deparse expr using get_rule_expr, + * embracing the string with parentheses if necessary for prettyPrint. + * + * Never embrace if prettyFlags=0, because it's done in the calling node. + * + * Any node that does *not* embrace its argument node by sql syntax (with + * parentheses, non-operator keywords like CASE/WHEN/ON, or comma etc) should + * use get_rule_expr_paren instead of get_rule_expr so parentheses can be + * added. + */ +static void +get_rule_expr_paren(Node *node, deparse_context *context, + bool showimplicit, Node *parentNode) +{ + bool need_paren; + + need_paren = PRETTY_PAREN(context) && + !isSimpleNode(node, parentNode, context->prettyFlags); + + if (need_paren) + appendStringInfoChar(context->buf, '('); + + get_rule_expr(node, context, showimplicit); + + if (need_paren) + appendStringInfoChar(context->buf, ')'); +} + + +/* ---------- + * get_rule_expr - Parse back an expression + * + * Note: showimplicit determines whether we display any implicit cast that + * is present at the top of the expression tree. It is a passed argument, + * not a field of the context struct, because we change the value as we + * recurse down into the expression. In general we suppress implicit casts + * when the result type is known with certainty (eg, the arguments of an + * OR must be boolean). We display implicit casts for arguments of functions + * and operators, since this is needed to be certain that the same function + * or operator will be chosen when the expression is re-parsed. + * ---------- + */ +static void +get_rule_expr(Node *node, deparse_context *context, + bool showimplicit) +{ + StringInfo buf = context->buf; + + if (node == NULL) + return; + + /* Guard against excessively long or deeply-nested queries */ + CHECK_FOR_INTERRUPTS(); + check_stack_depth(); + + /* + * Each level of get_rule_expr must emit an indivisible term + * (parenthesized if necessary) to ensure result is reparsed into the same + * expression tree. The only exception is that when the input is a List, + * we emit the component items comma-separated with no surrounding + * decoration; this is convenient for most callers. + */ + switch (nodeTag(node)) + { + case T_Var: + (void) get_variable((Var *) node, 0, false, context); + break; + + case T_Const: + get_const_expr((Const *) node, context, 0); + break; + + case T_Param: + get_parameter((Param *) node, context); + break; + + case T_Aggref: + get_agg_expr((Aggref *) node, context); + break; + + case T_GroupingFunc: + { + GroupingFunc *gexpr = (GroupingFunc *) node; + + appendStringInfoString(buf, "GROUPING("); + get_rule_expr((Node *) gexpr->args, context, true); + appendStringInfoChar(buf, ')'); + } + break; + + case T_WindowFunc: + get_windowfunc_expr((WindowFunc *) node, context); + break; + + case T_ArrayRef: + { + ArrayRef *aref = (ArrayRef *) node; + bool need_parens; + + /* + * If the argument is a CaseTestExpr, we must be inside a + * FieldStore, ie, we are assigning to an element of an array + * within a composite column. Since we already punted on + * displaying the FieldStore's target information, just punt + * here too, and display only the assignment source + * expression. + */ + if (IsA(aref->refexpr, CaseTestExpr)) + { + Assert(aref->refassgnexpr); + get_rule_expr((Node *) aref->refassgnexpr, + context, showimplicit); + break; + } + + /* + * Parenthesize the argument unless it's a simple Var or a + * FieldSelect. (In particular, if it's another ArrayRef, we + * *must* parenthesize to avoid confusion.) + */ + need_parens = !IsA(aref->refexpr, Var) && + !IsA(aref->refexpr, FieldSelect); + if (need_parens) + appendStringInfoChar(buf, '('); + get_rule_expr((Node *) aref->refexpr, context, showimplicit); + if (need_parens) + appendStringInfoChar(buf, ')'); + + /* + * If there's a refassgnexpr, we want to print the node in the + * format "array[subscripts] := refassgnexpr". This is not + * legal SQL, so decompilation of INSERT or UPDATE statements + * should always use processIndirection as part of the + * statement-level syntax. We should only see this when + * EXPLAIN tries to print the targetlist of a plan resulting + * from such a statement. + */ + if (aref->refassgnexpr) + { + Node *refassgnexpr; + + /* + * Use processIndirection to print this node's subscripts + * as well as any additional field selections or + * subscripting in immediate descendants. It returns the + * RHS expr that is actually being "assigned". + */ + refassgnexpr = processIndirection(node, context, true); + appendStringInfoString(buf, " := "); + get_rule_expr(refassgnexpr, context, showimplicit); + } + else + { + /* Just an ordinary array fetch, so print subscripts */ + printSubscripts(aref, context); + } + } + break; + + case T_FuncExpr: + get_func_expr((FuncExpr *) node, context, showimplicit); + break; + + case T_NamedArgExpr: + { + NamedArgExpr *na = (NamedArgExpr *) node; + + appendStringInfo(buf, "%s => ", quote_identifier(na->name)); + get_rule_expr((Node *) na->arg, context, showimplicit); + } + break; + + case T_OpExpr: + get_oper_expr((OpExpr *) node, context); + break; + + case T_DistinctExpr: + { + DistinctExpr *expr = (DistinctExpr *) node; + List *args = expr->args; + Node *arg1 = (Node *) linitial(args); + Node *arg2 = (Node *) lsecond(args); + + if (!PRETTY_PAREN(context)) + appendStringInfoChar(buf, '('); + get_rule_expr_paren(arg1, context, true, node); + appendStringInfoString(buf, " IS DISTINCT FROM "); + get_rule_expr_paren(arg2, context, true, node); + if (!PRETTY_PAREN(context)) + appendStringInfoChar(buf, ')'); + } + break; + + case T_NullIfExpr: + { + NullIfExpr *nullifexpr = (NullIfExpr *) node; + + appendStringInfoString(buf, "NULLIF("); + get_rule_expr((Node *) nullifexpr->args, context, true); + appendStringInfoChar(buf, ')'); + } + break; + + case T_ScalarArrayOpExpr: + { + ScalarArrayOpExpr *expr = (ScalarArrayOpExpr *) node; + List *args = expr->args; + Node *arg1 = (Node *) linitial(args); + Node *arg2 = (Node *) lsecond(args); + + if (!PRETTY_PAREN(context)) + appendStringInfoChar(buf, '('); + get_rule_expr_paren(arg1, context, true, node); + appendStringInfo(buf, " %s %s (", + generate_operator_name(expr->opno, + exprType(arg1), + get_base_element_type(exprType(arg2))), + expr->useOr ? "ANY" : "ALL"); + get_rule_expr_paren(arg2, context, true, node); + appendStringInfoChar(buf, ')'); + if (!PRETTY_PAREN(context)) + appendStringInfoChar(buf, ')'); + } + break; + + case T_BoolExpr: + { + BoolExpr *expr = (BoolExpr *) node; + Node *first_arg = linitial(expr->args); + ListCell *arg = lnext(list_head(expr->args)); + + switch (expr->boolop) + { + case AND_EXPR: + if (!PRETTY_PAREN(context)) + appendStringInfoChar(buf, '('); + get_rule_expr_paren(first_arg, context, + false, node); + while (arg) + { + appendStringInfoString(buf, " AND "); + get_rule_expr_paren((Node *) lfirst(arg), context, + false, node); + arg = lnext(arg); + } + if (!PRETTY_PAREN(context)) + appendStringInfoChar(buf, ')'); + break; + + case OR_EXPR: + if (!PRETTY_PAREN(context)) + appendStringInfoChar(buf, '('); + get_rule_expr_paren(first_arg, context, + false, node); + while (arg) + { + appendStringInfoString(buf, " OR "); + get_rule_expr_paren((Node *) lfirst(arg), context, + false, node); + arg = lnext(arg); + } + if (!PRETTY_PAREN(context)) + appendStringInfoChar(buf, ')'); + break; + + case NOT_EXPR: + if (!PRETTY_PAREN(context)) + appendStringInfoChar(buf, '('); + appendStringInfoString(buf, "NOT "); + get_rule_expr_paren(first_arg, context, + false, node); + if (!PRETTY_PAREN(context)) + appendStringInfoChar(buf, ')'); + break; + + default: + elog(ERROR, "unrecognized boolop: %d", + (int) expr->boolop); + } + } + break; + + case T_SubLink: + get_sublink_expr((SubLink *) node, context); + break; + + case T_SubPlan: + { + SubPlan *subplan = (SubPlan *) node; + + /* + * We cannot see an already-planned subplan in rule deparsing, + * only while EXPLAINing a query plan. We don't try to + * reconstruct the original SQL, just reference the subplan + * that appears elsewhere in EXPLAIN's result. + */ + if (subplan->useHashTable) + appendStringInfo(buf, "(hashed %s)", subplan->plan_name); + else + appendStringInfo(buf, "(%s)", subplan->plan_name); + } + break; + + case T_AlternativeSubPlan: + { + AlternativeSubPlan *asplan = (AlternativeSubPlan *) node; + ListCell *lc; + + /* As above, this can only happen during EXPLAIN */ + appendStringInfoString(buf, "(alternatives: "); + foreach(lc, asplan->subplans) + { + SubPlan *splan = (SubPlan *) lfirst(lc); + + Assert(IsA(splan, SubPlan)); + if (splan->useHashTable) + appendStringInfo(buf, "hashed %s", splan->plan_name); + else + appendStringInfoString(buf, splan->plan_name); + if (lnext(lc)) + appendStringInfoString(buf, " or "); + } + appendStringInfoChar(buf, ')'); + } + break; + + case T_FieldSelect: + { + FieldSelect *fselect = (FieldSelect *) node; + Node *arg = (Node *) fselect->arg; + int fno = fselect->fieldnum; + const char *fieldname; + bool need_parens; + + /* + * Parenthesize the argument unless it's an ArrayRef or + * another FieldSelect. Note in particular that it would be + * WRONG to not parenthesize a Var argument; simplicity is not + * the issue here, having the right number of names is. + */ + need_parens = !IsA(arg, ArrayRef) &&!IsA(arg, FieldSelect); + if (need_parens) + appendStringInfoChar(buf, '('); + get_rule_expr(arg, context, true); + if (need_parens) + appendStringInfoChar(buf, ')'); + + /* + * Get and print the field name. + */ + fieldname = get_name_for_var_field((Var *) arg, fno, + 0, context); + appendStringInfo(buf, ".%s", quote_identifier(fieldname)); + } + break; + + case T_FieldStore: + { + FieldStore *fstore = (FieldStore *) node; + bool need_parens; + + /* + * There is no good way to represent a FieldStore as real SQL, + * so decompilation of INSERT or UPDATE statements should + * always use processIndirection as part of the + * statement-level syntax. We should only get here when + * EXPLAIN tries to print the targetlist of a plan resulting + * from such a statement. The plan case is even harder than + * ordinary rules would be, because the planner tries to + * collapse multiple assignments to the same field or subfield + * into one FieldStore; so we can see a list of target fields + * not just one, and the arguments could be FieldStores + * themselves. We don't bother to try to print the target + * field names; we just print the source arguments, with a + * ROW() around them if there's more than one. This isn't + * terribly complete, but it's probably good enough for + * EXPLAIN's purposes; especially since anything more would be + * either hopelessly confusing or an even poorer + * representation of what the plan is actually doing. + */ + need_parens = (list_length(fstore->newvals) != 1); + if (need_parens) + appendStringInfoString(buf, "ROW("); + get_rule_expr((Node *) fstore->newvals, context, showimplicit); + if (need_parens) + appendStringInfoChar(buf, ')'); + } + break; + + case T_RelabelType: + { + RelabelType *relabel = (RelabelType *) node; + Node *arg = (Node *) relabel->arg; + + if (relabel->relabelformat == COERCE_IMPLICIT_CAST && + !showimplicit) + { + /* don't show the implicit cast */ + get_rule_expr_paren(arg, context, false, node); + } + else + { + get_coercion_expr(arg, context, + relabel->resulttype, + relabel->resulttypmod, + node); + } + } + break; + + case T_CoerceViaIO: + { + CoerceViaIO *iocoerce = (CoerceViaIO *) node; + Node *arg = (Node *) iocoerce->arg; + + if (iocoerce->coerceformat == COERCE_IMPLICIT_CAST && + !showimplicit) + { + /* don't show the implicit cast */ + get_rule_expr_paren(arg, context, false, node); + } + else + { + get_coercion_expr(arg, context, + iocoerce->resulttype, + -1, + node); + } + } + break; + + case T_ArrayCoerceExpr: + { + ArrayCoerceExpr *acoerce = (ArrayCoerceExpr *) node; + Node *arg = (Node *) acoerce->arg; + + if (acoerce->coerceformat == COERCE_IMPLICIT_CAST && + !showimplicit) + { + /* don't show the implicit cast */ + get_rule_expr_paren(arg, context, false, node); + } + else + { + get_coercion_expr(arg, context, + acoerce->resulttype, + acoerce->resulttypmod, + node); + } + } + break; + + case T_ConvertRowtypeExpr: + { + ConvertRowtypeExpr *convert = (ConvertRowtypeExpr *) node; + Node *arg = (Node *) convert->arg; + + if (convert->convertformat == COERCE_IMPLICIT_CAST && + !showimplicit) + { + /* don't show the implicit cast */ + get_rule_expr_paren(arg, context, false, node); + } + else + { + get_coercion_expr(arg, context, + convert->resulttype, -1, + node); + } + } + break; + + case T_CollateExpr: + { + CollateExpr *collate = (CollateExpr *) node; + Node *arg = (Node *) collate->arg; + + if (!PRETTY_PAREN(context)) + appendStringInfoChar(buf, '('); + get_rule_expr_paren(arg, context, showimplicit, node); + appendStringInfo(buf, " COLLATE %s", + generate_collation_name(collate->collOid)); + if (!PRETTY_PAREN(context)) + appendStringInfoChar(buf, ')'); + } + break; + + case T_CaseExpr: + { + CaseExpr *caseexpr = (CaseExpr *) node; + ListCell *temp; + + appendContextKeyword(context, "CASE", + 0, PRETTYINDENT_VAR, 0); + if (caseexpr->arg) + { + appendStringInfoChar(buf, ' '); + get_rule_expr((Node *) caseexpr->arg, context, true); + } + foreach(temp, caseexpr->args) + { + CaseWhen *when = (CaseWhen *) lfirst(temp); + Node *w = (Node *) when->expr; + + if (caseexpr->arg) + { + /* + * The parser should have produced WHEN clauses of the + * form "CaseTestExpr = RHS", possibly with an + * implicit coercion inserted above the CaseTestExpr. + * For accurate decompilation of rules it's essential + * that we show just the RHS. However in an + * expression that's been through the optimizer, the + * WHEN clause could be almost anything (since the + * equality operator could have been expanded into an + * inline function). If we don't recognize the form + * of the WHEN clause, just punt and display it as-is. + */ + if (IsA(w, OpExpr)) + { + List *args = ((OpExpr *) w)->args; + + if (list_length(args) == 2 && + IsA(strip_implicit_coercions(linitial(args)), + CaseTestExpr)) + w = (Node *) lsecond(args); + } + } + + if (!PRETTY_INDENT(context)) + appendStringInfoChar(buf, ' '); + appendContextKeyword(context, "WHEN ", + 0, 0, 0); + get_rule_expr(w, context, false); + appendStringInfoString(buf, " THEN "); + get_rule_expr((Node *) when->result, context, true); + } + if (!PRETTY_INDENT(context)) + appendStringInfoChar(buf, ' '); + appendContextKeyword(context, "ELSE ", + 0, 0, 0); + get_rule_expr((Node *) caseexpr->defresult, context, true); + if (!PRETTY_INDENT(context)) + appendStringInfoChar(buf, ' '); + appendContextKeyword(context, "END", + -PRETTYINDENT_VAR, 0, 0); + } + break; + + case T_CaseTestExpr: + { + /* + * Normally we should never get here, since for expressions + * that can contain this node type we attempt to avoid + * recursing to it. But in an optimized expression we might + * be unable to avoid that (see comments for CaseExpr). If we + * do see one, print it as CASE_TEST_EXPR. + */ + appendStringInfoString(buf, "CASE_TEST_EXPR"); + } + break; + + case T_ArrayExpr: + { + ArrayExpr *arrayexpr = (ArrayExpr *) node; + + appendStringInfoString(buf, "ARRAY["); + get_rule_expr((Node *) arrayexpr->elements, context, true); + appendStringInfoChar(buf, ']'); + + /* + * If the array isn't empty, we assume its elements are + * coerced to the desired type. If it's empty, though, we + * need an explicit coercion to the array type. + */ + if (arrayexpr->elements == NIL) + appendStringInfo(buf, "::%s", + format_type_with_typemod(arrayexpr->array_typeid, -1)); + } + break; + + case T_RowExpr: + { + RowExpr *rowexpr = (RowExpr *) node; + TupleDesc tupdesc = NULL; + ListCell *arg; + int i; + char *sep; + + /* + * If it's a named type and not RECORD, we may have to skip + * dropped columns and/or claim there are NULLs for added + * columns. + */ + if (rowexpr->row_typeid != RECORDOID) + { + tupdesc = lookup_rowtype_tupdesc(rowexpr->row_typeid, -1); + Assert(list_length(rowexpr->args) <= tupdesc->natts); + } + + /* + * SQL99 allows "ROW" to be omitted when there is more than + * one column, but for simplicity we always print it. + */ + appendStringInfoString(buf, "ROW("); + sep = ""; + i = 0; + foreach(arg, rowexpr->args) + { + Node *e = (Node *) lfirst(arg); + + if (tupdesc == NULL || + !tupdesc->attrs[i]->attisdropped) + { + appendStringInfoString(buf, sep); + /* Whole-row Vars need special treatment here */ + get_rule_expr_toplevel(e, context, true); + sep = ", "; + } + i++; + } + if (tupdesc != NULL) + { + while (i < tupdesc->natts) + { + if (!tupdesc->attrs[i]->attisdropped) + { + appendStringInfoString(buf, sep); + appendStringInfoString(buf, "NULL"); + sep = ", "; + } + i++; + } + + ReleaseTupleDesc(tupdesc); + } + appendStringInfoChar(buf, ')'); + if (rowexpr->row_format == COERCE_EXPLICIT_CAST) + appendStringInfo(buf, "::%s", + format_type_with_typemod(rowexpr->row_typeid, -1)); + } + break; + + case T_RowCompareExpr: + { + RowCompareExpr *rcexpr = (RowCompareExpr *) node; + ListCell *arg; + char *sep; + + /* + * SQL99 allows "ROW" to be omitted when there is more than + * one column, but for simplicity we always print it. + */ + appendStringInfoString(buf, "(ROW("); + sep = ""; + foreach(arg, rcexpr->largs) + { + Node *e = (Node *) lfirst(arg); + + appendStringInfoString(buf, sep); + get_rule_expr(e, context, true); + sep = ", "; + } + + /* + * We assume that the name of the first-column operator will + * do for all the rest too. This is definitely open to + * failure, eg if some but not all operators were renamed + * since the construct was parsed, but there seems no way to + * be perfect. + */ + appendStringInfo(buf, ") %s ROW(", + generate_operator_name(linitial_oid(rcexpr->opnos), + exprType(linitial(rcexpr->largs)), + exprType(linitial(rcexpr->rargs)))); + sep = ""; + foreach(arg, rcexpr->rargs) + { + Node *e = (Node *) lfirst(arg); + + appendStringInfoString(buf, sep); + get_rule_expr(e, context, true); + sep = ", "; + } + appendStringInfoString(buf, "))"); + } + break; + + case T_CoalesceExpr: + { + CoalesceExpr *coalesceexpr = (CoalesceExpr *) node; + + appendStringInfoString(buf, "COALESCE("); + get_rule_expr((Node *) coalesceexpr->args, context, true); + appendStringInfoChar(buf, ')'); + } + break; + + case T_MinMaxExpr: + { + MinMaxExpr *minmaxexpr = (MinMaxExpr *) node; + + switch (minmaxexpr->op) + { + case IS_GREATEST: + appendStringInfoString(buf, "GREATEST("); + break; + case IS_LEAST: + appendStringInfoString(buf, "LEAST("); + break; + } + get_rule_expr((Node *) minmaxexpr->args, context, true); + appendStringInfoChar(buf, ')'); + } + break; + + case T_XmlExpr: + { + XmlExpr *xexpr = (XmlExpr *) node; + bool needcomma = false; + ListCell *arg; + ListCell *narg; + Const *con; + + switch (xexpr->op) + { + case IS_XMLCONCAT: + appendStringInfoString(buf, "XMLCONCAT("); + break; + case IS_XMLELEMENT: + appendStringInfoString(buf, "XMLELEMENT("); + break; + case IS_XMLFOREST: + appendStringInfoString(buf, "XMLFOREST("); + break; + case IS_XMLPARSE: + appendStringInfoString(buf, "XMLPARSE("); + break; + case IS_XMLPI: + appendStringInfoString(buf, "XMLPI("); + break; + case IS_XMLROOT: + appendStringInfoString(buf, "XMLROOT("); + break; + case IS_XMLSERIALIZE: + appendStringInfoString(buf, "XMLSERIALIZE("); + break; + case IS_DOCUMENT: + break; + } + if (xexpr->op == IS_XMLPARSE || xexpr->op == IS_XMLSERIALIZE) + { + if (xexpr->xmloption == XMLOPTION_DOCUMENT) + appendStringInfoString(buf, "DOCUMENT "); + else + appendStringInfoString(buf, "CONTENT "); + } + if (xexpr->name) + { + appendStringInfo(buf, "NAME %s", + quote_identifier(map_xml_name_to_sql_identifier(xexpr->name))); + needcomma = true; + } + if (xexpr->named_args) + { + if (xexpr->op != IS_XMLFOREST) + { + if (needcomma) + appendStringInfoString(buf, ", "); + appendStringInfoString(buf, "XMLATTRIBUTES("); + needcomma = false; + } + forboth(arg, xexpr->named_args, narg, xexpr->arg_names) + { + Node *e = (Node *) lfirst(arg); + char *argname = strVal(lfirst(narg)); + + if (needcomma) + appendStringInfoString(buf, ", "); + get_rule_expr((Node *) e, context, true); + appendStringInfo(buf, " AS %s", + quote_identifier(map_xml_name_to_sql_identifier(argname))); + needcomma = true; + } + if (xexpr->op != IS_XMLFOREST) + appendStringInfoChar(buf, ')'); + } + if (xexpr->args) + { + if (needcomma) + appendStringInfoString(buf, ", "); + switch (xexpr->op) + { + case IS_XMLCONCAT: + case IS_XMLELEMENT: + case IS_XMLFOREST: + case IS_XMLPI: + case IS_XMLSERIALIZE: + /* no extra decoration needed */ + get_rule_expr((Node *) xexpr->args, context, true); + break; + case IS_XMLPARSE: + Assert(list_length(xexpr->args) == 2); + + get_rule_expr((Node *) linitial(xexpr->args), + context, true); + + con = (Const *) lsecond(xexpr->args); + Assert(IsA(con, Const)); + Assert(!con->constisnull); + if (DatumGetBool(con->constvalue)) + appendStringInfoString(buf, + " PRESERVE WHITESPACE"); + else + appendStringInfoString(buf, + " STRIP WHITESPACE"); + break; + case IS_XMLROOT: + Assert(list_length(xexpr->args) == 3); + + get_rule_expr((Node *) linitial(xexpr->args), + context, true); + + appendStringInfoString(buf, ", VERSION "); + con = (Const *) lsecond(xexpr->args); + if (IsA(con, Const) && + con->constisnull) + appendStringInfoString(buf, "NO VALUE"); + else + get_rule_expr((Node *) con, context, false); + + con = (Const *) lthird(xexpr->args); + Assert(IsA(con, Const)); + if (con->constisnull) + /* suppress STANDALONE NO VALUE */ ; + else + { + switch (DatumGetInt32(con->constvalue)) + { + case XML_STANDALONE_YES: + appendStringInfoString(buf, + ", STANDALONE YES"); + break; + case XML_STANDALONE_NO: + appendStringInfoString(buf, + ", STANDALONE NO"); + break; + case XML_STANDALONE_NO_VALUE: + appendStringInfoString(buf, + ", STANDALONE NO VALUE"); + break; + default: + break; + } + } + break; + case IS_DOCUMENT: + get_rule_expr_paren((Node *) xexpr->args, context, false, node); + break; + } + + } + if (xexpr->op == IS_XMLSERIALIZE) + appendStringInfo(buf, " AS %s", + format_type_with_typemod(xexpr->type, + xexpr->typmod)); + if (xexpr->op == IS_DOCUMENT) + appendStringInfoString(buf, " IS DOCUMENT"); + else + appendStringInfoChar(buf, ')'); + } + break; + + case T_NullTest: + { + NullTest *ntest = (NullTest *) node; + + if (!PRETTY_PAREN(context)) + appendStringInfoChar(buf, '('); + get_rule_expr_paren((Node *) ntest->arg, context, true, node); + switch (ntest->nulltesttype) + { + case IS_NULL: + appendStringInfoString(buf, " IS NULL"); + break; + case IS_NOT_NULL: + appendStringInfoString(buf, " IS NOT NULL"); + break; + default: + elog(ERROR, "unrecognized nulltesttype: %d", + (int) ntest->nulltesttype); + } + if (!PRETTY_PAREN(context)) + appendStringInfoChar(buf, ')'); + } + break; + + case T_BooleanTest: + { + BooleanTest *btest = (BooleanTest *) node; + + if (!PRETTY_PAREN(context)) + appendStringInfoChar(buf, '('); + get_rule_expr_paren((Node *) btest->arg, context, false, node); + switch (btest->booltesttype) + { + case IS_TRUE: + appendStringInfoString(buf, " IS TRUE"); + break; + case IS_NOT_TRUE: + appendStringInfoString(buf, " IS NOT TRUE"); + break; + case IS_FALSE: + appendStringInfoString(buf, " IS FALSE"); + break; + case IS_NOT_FALSE: + appendStringInfoString(buf, " IS NOT FALSE"); + break; + case IS_UNKNOWN: + appendStringInfoString(buf, " IS UNKNOWN"); + break; + case IS_NOT_UNKNOWN: + appendStringInfoString(buf, " IS NOT UNKNOWN"); + break; + default: + elog(ERROR, "unrecognized booltesttype: %d", + (int) btest->booltesttype); + } + if (!PRETTY_PAREN(context)) + appendStringInfoChar(buf, ')'); + } + break; + + case T_CoerceToDomain: + { + CoerceToDomain *ctest = (CoerceToDomain *) node; + Node *arg = (Node *) ctest->arg; + + if (ctest->coercionformat == COERCE_IMPLICIT_CAST && + !showimplicit) + { + /* don't show the implicit cast */ + get_rule_expr(arg, context, false); + } + else + { + get_coercion_expr(arg, context, + ctest->resulttype, + ctest->resulttypmod, + node); + } + } + break; + + case T_CoerceToDomainValue: + appendStringInfoString(buf, "VALUE"); + break; + + case T_SetToDefault: + appendStringInfoString(buf, "DEFAULT"); + break; + + case T_CurrentOfExpr: + { + CurrentOfExpr *cexpr = (CurrentOfExpr *) node; + + if (cexpr->cursor_name) + appendStringInfo(buf, "CURRENT OF %s", + quote_identifier(cexpr->cursor_name)); + else + appendStringInfo(buf, "CURRENT OF $%d", + cexpr->cursor_param); + } + break; + + case T_InferenceElem: + { + InferenceElem *iexpr = (InferenceElem *) node; + bool varprefix = context->varprefix; + bool need_parens; + + /* + * InferenceElem can only refer to target relation, so a + * prefix is never useful. + */ + context->varprefix = false; + + /* + * Parenthesize the element unless it's a simple Var or a bare + * function call. Follows pg_get_indexdef_worker(). + */ + need_parens = !IsA(iexpr->expr, Var); + if (IsA(iexpr->expr, FuncExpr) && + ((FuncExpr *) iexpr->expr)->funcformat == + COERCE_EXPLICIT_CALL) + need_parens = false; + + if (need_parens) + appendStringInfoChar(buf, '('); + get_rule_expr((Node *) iexpr->expr, + context, false); + if (need_parens) + appendStringInfoChar(buf, ')'); + + context->varprefix = varprefix; + + if (iexpr->infercollid) + appendStringInfo(buf, " COLLATE %s", + generate_collation_name(iexpr->infercollid)); + + /* Add the operator class name, if not default */ + if (iexpr->inferopclass) + { + Oid inferopclass = iexpr->inferopclass; + Oid inferopcinputtype = get_opclass_input_type(iexpr->inferopclass); + + get_opclass_name(inferopclass, inferopcinputtype, buf); + } + } + break; + + case T_List: + { + char *sep; + ListCell *l; + + sep = ""; + foreach(l, (List *) node) + { + appendStringInfoString(buf, sep); + get_rule_expr((Node *) lfirst(l), context, showimplicit); + sep = ", "; + } + } + break; + + default: + elog(ERROR, "unrecognized node type: %d", (int) nodeTag(node)); + break; + } +} + +/* + * get_rule_expr_toplevel - Parse back a toplevel expression + * + * Same as get_rule_expr(), except that if the expr is just a Var, we pass + * istoplevel = true not false to get_variable(). This causes whole-row Vars + * to get printed with decoration that will prevent expansion of "*". + * We need to use this in contexts such as ROW() and VALUES(), where the + * parser would expand "foo.*" appearing at top level. (In principle we'd + * use this in get_target_list() too, but that has additional worries about + * whether to print AS, so it needs to invoke get_variable() directly anyway.) + */ +static void +get_rule_expr_toplevel(Node *node, deparse_context *context, + bool showimplicit) +{ + if (node && IsA(node, Var)) + (void) get_variable((Var *) node, 0, true, context); + else + get_rule_expr(node, context, showimplicit); +} + + +/* + * get_oper_expr - Parse back an OpExpr node + */ +static void +get_oper_expr(OpExpr *expr, deparse_context *context) +{ + StringInfo buf = context->buf; + Oid opno = expr->opno; + List *args = expr->args; + + if (!PRETTY_PAREN(context)) + appendStringInfoChar(buf, '('); + if (list_length(args) == 2) + { + /* binary operator */ + Node *arg1 = (Node *) linitial(args); + Node *arg2 = (Node *) lsecond(args); + + get_rule_expr_paren(arg1, context, true, (Node *) expr); + appendStringInfo(buf, " %s ", + generate_operator_name(opno, + exprType(arg1), + exprType(arg2))); + get_rule_expr_paren(arg2, context, true, (Node *) expr); + } + else + { + /* unary operator --- but which side? */ + Node *arg = (Node *) linitial(args); + HeapTuple tp; + Form_pg_operator optup; + + tp = SearchSysCache1(OPEROID, ObjectIdGetDatum(opno)); + if (!HeapTupleIsValid(tp)) + elog(ERROR, "cache lookup failed for operator %u", opno); + optup = (Form_pg_operator) GETSTRUCT(tp); + switch (optup->oprkind) + { + case 'l': + appendStringInfo(buf, "%s ", + generate_operator_name(opno, + InvalidOid, + exprType(arg))); + get_rule_expr_paren(arg, context, true, (Node *) expr); + break; + case 'r': + get_rule_expr_paren(arg, context, true, (Node *) expr); + appendStringInfo(buf, " %s", + generate_operator_name(opno, + exprType(arg), + InvalidOid)); + break; + default: + elog(ERROR, "bogus oprkind: %d", optup->oprkind); + } + ReleaseSysCache(tp); + } + if (!PRETTY_PAREN(context)) + appendStringInfoChar(buf, ')'); +} + +/* + * get_func_expr - Parse back a FuncExpr node + */ +static void +get_func_expr(FuncExpr *expr, deparse_context *context, + bool showimplicit) +{ + StringInfo buf = context->buf; + Oid funcoid = expr->funcid; + Oid argtypes[FUNC_MAX_ARGS]; + int nargs; + List *argnames; + bool use_variadic; + ListCell *l; + + /* + * If the function call came from an implicit coercion, then just show the + * first argument --- unless caller wants to see implicit coercions. + */ + if (expr->funcformat == COERCE_IMPLICIT_CAST && !showimplicit) + { + get_rule_expr_paren((Node *) linitial(expr->args), context, + false, (Node *) expr); + return; + } + + /* + * If the function call came from a cast, then show the first argument + * plus an explicit cast operation. + */ + if (expr->funcformat == COERCE_EXPLICIT_CAST || + expr->funcformat == COERCE_IMPLICIT_CAST) + { + Node *arg = linitial(expr->args); + Oid rettype = expr->funcresulttype; + int32 coercedTypmod; + + /* Get the typmod if this is a length-coercion function */ + (void) exprIsLengthCoercion((Node *) expr, &coercedTypmod); + + get_coercion_expr(arg, context, + rettype, coercedTypmod, + (Node *) expr); + + return; + } + + /* + * Normal function: display as proname(args). First we need to extract + * the argument datatypes. + */ + if (list_length(expr->args) > FUNC_MAX_ARGS) + ereport(ERROR, + (errcode(ERRCODE_TOO_MANY_ARGUMENTS), + errmsg("too many arguments"))); + nargs = 0; + argnames = NIL; + foreach(l, expr->args) + { + Node *arg = (Node *) lfirst(l); + + if (IsA(arg, NamedArgExpr)) + argnames = lappend(argnames, ((NamedArgExpr *) arg)->name); + argtypes[nargs] = exprType(arg); + nargs++; + } + + appendStringInfo(buf, "%s(", + generate_function_name(funcoid, nargs, + argnames, argtypes, + expr->funcvariadic, + &use_variadic, + context->special_exprkind)); + nargs = 0; + foreach(l, expr->args) + { + if (nargs++ > 0) + appendStringInfoString(buf, ", "); + if (use_variadic && lnext(l) == NULL) + appendStringInfoString(buf, "VARIADIC "); + get_rule_expr((Node *) lfirst(l), context, true); + } + appendStringInfoChar(buf, ')'); +} + +/* + * get_agg_expr - Parse back an Aggref node + */ +static void +get_agg_expr(Aggref *aggref, deparse_context *context) +{ + StringInfo buf = context->buf; + Oid argtypes[FUNC_MAX_ARGS]; + int nargs; + bool use_variadic; + + /* Extract the argument types as seen by the parser */ + nargs = get_aggregate_argtypes(aggref, argtypes); + + /* Print the aggregate name, schema-qualified if needed */ + appendStringInfo(buf, "%s(%s", + generate_function_name(aggref->aggfnoid, nargs, + NIL, argtypes, + aggref->aggvariadic, + &use_variadic, + context->special_exprkind), + (aggref->aggdistinct != NIL) ? "DISTINCT " : ""); + + if (AGGKIND_IS_ORDERED_SET(aggref->aggkind)) + { + /* + * Ordered-set aggregates do not use "*" syntax. Also, we needn't + * worry about inserting VARIADIC. So we can just dump the direct + * args as-is. + */ + Assert(!aggref->aggvariadic); + get_rule_expr((Node *) aggref->aggdirectargs, context, true); + Assert(aggref->aggorder != NIL); + appendStringInfoString(buf, ") WITHIN GROUP (ORDER BY "); + get_rule_orderby(aggref->aggorder, aggref->args, false, context); + } + else + { + /* aggstar can be set only in zero-argument aggregates */ + if (aggref->aggstar) + appendStringInfoChar(buf, '*'); + else + { + ListCell *l; + int i; + + i = 0; + foreach(l, aggref->args) + { + TargetEntry *tle = (TargetEntry *) lfirst(l); + Node *arg = (Node *) tle->expr; + + Assert(!IsA(arg, NamedArgExpr)); + if (tle->resjunk) + continue; + if (i++ > 0) + appendStringInfoString(buf, ", "); + if (use_variadic && i == nargs) + appendStringInfoString(buf, "VARIADIC "); + get_rule_expr(arg, context, true); + } + } + + if (aggref->aggorder != NIL) + { + appendStringInfoString(buf, " ORDER BY "); + get_rule_orderby(aggref->aggorder, aggref->args, false, context); + } + } + + if (aggref->aggfilter != NULL) + { + appendStringInfoString(buf, ") FILTER (WHERE "); + get_rule_expr((Node *) aggref->aggfilter, context, false); + } + + appendStringInfoChar(buf, ')'); +} + +/* + * get_windowfunc_expr - Parse back a WindowFunc node + */ +static void +get_windowfunc_expr(WindowFunc *wfunc, deparse_context *context) +{ + StringInfo buf = context->buf; + Oid argtypes[FUNC_MAX_ARGS]; + int nargs; + List *argnames; + ListCell *l; + + if (list_length(wfunc->args) > FUNC_MAX_ARGS) + ereport(ERROR, + (errcode(ERRCODE_TOO_MANY_ARGUMENTS), + errmsg("too many arguments"))); + nargs = 0; + argnames = NIL; + foreach(l, wfunc->args) + { + Node *arg = (Node *) lfirst(l); + + if (IsA(arg, NamedArgExpr)) + argnames = lappend(argnames, ((NamedArgExpr *) arg)->name); + argtypes[nargs] = exprType(arg); + nargs++; + } + + appendStringInfo(buf, "%s(", + generate_function_name(wfunc->winfnoid, nargs, + argnames, argtypes, + false, NULL, + context->special_exprkind)); + /* winstar can be set only in zero-argument aggregates */ + if (wfunc->winstar) + appendStringInfoChar(buf, '*'); + else + get_rule_expr((Node *) wfunc->args, context, true); + + if (wfunc->aggfilter != NULL) + { + appendStringInfoString(buf, ") FILTER (WHERE "); + get_rule_expr((Node *) wfunc->aggfilter, context, false); + } + + appendStringInfoString(buf, ") OVER "); + + foreach(l, context->windowClause) + { + WindowClause *wc = (WindowClause *) lfirst(l); + + if (wc->winref == wfunc->winref) + { + if (wc->name) + appendStringInfoString(buf, quote_identifier(wc->name)); + else + get_rule_windowspec(wc, context->windowTList, context); + break; + } + } + if (l == NULL) + { + if (context->windowClause) + elog(ERROR, "could not find window clause for winref %u", + wfunc->winref); + + /* + * In EXPLAIN, we don't have window context information available, so + * we have to settle for this: + */ + appendStringInfoString(buf, "(?)"); + } +} + +/* ---------- + * get_coercion_expr + * + * Make a string representation of a value coerced to a specific type + * ---------- + */ +static void +get_coercion_expr(Node *arg, deparse_context *context, + Oid resulttype, int32 resulttypmod, + Node *parentNode) +{ + StringInfo buf = context->buf; + + /* + * Since parse_coerce.c doesn't immediately collapse application of + * length-coercion functions to constants, what we'll typically see in + * such cases is a Const with typmod -1 and a length-coercion function + * right above it. Avoid generating redundant output. However, beware of + * suppressing casts when the user actually wrote something like + * 'foo'::text::char(3). + * + * Note: it might seem that we are missing the possibility of needing to + * print a COLLATE clause for such a Const. However, a Const could only + * have nondefault collation in a post-constant-folding tree, in which the + * length coercion would have been folded too. See also the special + * handling of CollateExpr in coerce_to_target_type(): any collation + * marking will be above the coercion node, not below it. + */ + if (arg && IsA(arg, Const) && + ((Const *) arg)->consttype == resulttype && + ((Const *) arg)->consttypmod == -1) + { + /* Show the constant without normal ::typename decoration */ + get_const_expr((Const *) arg, context, -1); + } + else + { + if (!PRETTY_PAREN(context)) + appendStringInfoChar(buf, '('); + get_rule_expr_paren(arg, context, false, parentNode); + if (!PRETTY_PAREN(context)) + appendStringInfoChar(buf, ')'); + } + appendStringInfo(buf, "::%s", + format_type_with_typemod(resulttype, resulttypmod)); +} + +/* ---------- + * get_const_expr + * + * Make a string representation of a Const + * + * showtype can be -1 to never show "::typename" decoration, or +1 to always + * show it, or 0 to show it only if the constant wouldn't be assumed to be + * the right type by default. + * + * If the Const's collation isn't default for its type, show that too. + * We mustn't do this when showtype is -1 (since that means the caller will + * print "::typename", and we can't put a COLLATE clause in between). It's + * caller's responsibility that collation isn't missed in such cases. + * ---------- + */ +static void +get_const_expr(Const *constval, deparse_context *context, int showtype) +{ + StringInfo buf = context->buf; + Oid typoutput; + bool typIsVarlena; + char *extval; + bool needlabel = false; + + if (constval->constisnull) + { + /* + * Always label the type of a NULL constant to prevent misdecisions + * about type when reparsing. + */ + appendStringInfoString(buf, "NULL"); + if (showtype >= 0) + { + appendStringInfo(buf, "::%s", + format_type_with_typemod(constval->consttype, + constval->consttypmod)); + get_const_collation(constval, context); + } + return; + } + + getTypeOutputInfo(constval->consttype, + &typoutput, &typIsVarlena); + + extval = OidOutputFunctionCall(typoutput, constval->constvalue); + + switch (constval->consttype) + { + case INT4OID: + + /* + * INT4 can be printed without any decoration, unless it is + * negative; in that case print it as '-nnn'::integer to ensure + * that the output will re-parse as a constant, not as a constant + * plus operator. In most cases we could get away with printing + * (-nnn) instead, because of the way that gram.y handles negative + * literals; but that doesn't work for INT_MIN, and it doesn't + * seem that much prettier anyway. + */ + if (extval[0] != '-') + appendStringInfoString(buf, extval); + else + { + appendStringInfo(buf, "'%s'", extval); + needlabel = true; /* we must attach a cast */ + } + break; + + case NUMERICOID: + + /* + * NUMERIC can be printed without quotes if it looks like a float + * constant (not an integer, and not Infinity or NaN) and doesn't + * have a leading sign (for the same reason as for INT4). + */ + if (isdigit((unsigned char) extval[0]) && + strcspn(extval, "eE.") != strlen(extval)) + { + appendStringInfoString(buf, extval); + } + else + { + appendStringInfo(buf, "'%s'", extval); + needlabel = true; /* we must attach a cast */ + } + break; + + case BITOID: + case VARBITOID: + appendStringInfo(buf, "B'%s'", extval); + break; + + case BOOLOID: + if (strcmp(extval, "t") == 0) + appendStringInfoString(buf, "true"); + else + appendStringInfoString(buf, "false"); + break; + + default: + simple_quote_literal(buf, extval); + break; + } + + pfree(extval); + + if (showtype < 0) + return; + + /* + * For showtype == 0, append ::typename unless the constant will be + * implicitly typed as the right type when it is read in. + * + * XXX this code has to be kept in sync with the behavior of the parser, + * especially make_const. + */ + switch (constval->consttype) + { + case BOOLOID: + case UNKNOWNOID: + /* These types can be left unlabeled */ + needlabel = false; + break; + case INT4OID: + /* We determined above whether a label is needed */ + break; + case NUMERICOID: + + /* + * Float-looking constants will be typed as numeric, which we + * checked above; but if there's a nondefault typmod we need to + * show it. + */ + needlabel |= (constval->consttypmod >= 0); + break; + default: + needlabel = true; + break; + } + if (needlabel || showtype > 0) + appendStringInfo(buf, "::%s", + format_type_with_typemod(constval->consttype, + constval->consttypmod)); + + get_const_collation(constval, context); +} + +/* + * helper for get_const_expr: append COLLATE if needed + */ +static void +get_const_collation(Const *constval, deparse_context *context) +{ + StringInfo buf = context->buf; + + if (OidIsValid(constval->constcollid)) + { + Oid typcollation = get_typcollation(constval->consttype); + + if (constval->constcollid != typcollation) + { + appendStringInfo(buf, " COLLATE %s", + generate_collation_name(constval->constcollid)); + } + } +} + +/* + * simple_quote_literal - Format a string as a SQL literal, append to buf + */ +static void +simple_quote_literal(StringInfo buf, const char *val) +{ + const char *valptr; + + /* + * We form the string literal according to the prevailing setting of + * standard_conforming_strings; we never use E''. User is responsible for + * making sure result is used correctly. + */ + appendStringInfoChar(buf, '\''); + for (valptr = val; *valptr; valptr++) + { + char ch = *valptr; + + if (SQL_STR_DOUBLE(ch, !standard_conforming_strings)) + appendStringInfoChar(buf, ch); + appendStringInfoChar(buf, ch); + } + appendStringInfoChar(buf, '\''); +} + + +/* ---------- + * get_sublink_expr - Parse back a sublink + * ---------- + */ +static void +get_sublink_expr(SubLink *sublink, deparse_context *context) +{ + StringInfo buf = context->buf; + Query *query = (Query *) (sublink->subselect); + char *opname = NULL; + bool need_paren; + + if (sublink->subLinkType == ARRAY_SUBLINK) + appendStringInfoString(buf, "ARRAY("); + else + appendStringInfoChar(buf, '('); + + /* + * Note that we print the name of only the first operator, when there are + * multiple combining operators. This is an approximation that could go + * wrong in various scenarios (operators in different schemas, renamed + * operators, etc) but there is not a whole lot we can do about it, since + * the syntax allows only one operator to be shown. + */ + if (sublink->testexpr) + { + if (IsA(sublink->testexpr, OpExpr)) + { + /* single combining operator */ + OpExpr *opexpr = (OpExpr *) sublink->testexpr; + + get_rule_expr(linitial(opexpr->args), context, true); + opname = generate_operator_name(opexpr->opno, + exprType(linitial(opexpr->args)), + exprType(lsecond(opexpr->args))); + } + else if (IsA(sublink->testexpr, BoolExpr)) + { + /* multiple combining operators, = or <> cases */ + char *sep; + ListCell *l; + + appendStringInfoChar(buf, '('); + sep = ""; + foreach(l, ((BoolExpr *) sublink->testexpr)->args) + { + OpExpr *opexpr = (OpExpr *) lfirst(l); + + Assert(IsA(opexpr, OpExpr)); + appendStringInfoString(buf, sep); + get_rule_expr(linitial(opexpr->args), context, true); + if (!opname) + opname = generate_operator_name(opexpr->opno, + exprType(linitial(opexpr->args)), + exprType(lsecond(opexpr->args))); + sep = ", "; + } + appendStringInfoChar(buf, ')'); + } + else if (IsA(sublink->testexpr, RowCompareExpr)) + { + /* multiple combining operators, < <= > >= cases */ + RowCompareExpr *rcexpr = (RowCompareExpr *) sublink->testexpr; + + appendStringInfoChar(buf, '('); + get_rule_expr((Node *) rcexpr->largs, context, true); + opname = generate_operator_name(linitial_oid(rcexpr->opnos), + exprType(linitial(rcexpr->largs)), + exprType(linitial(rcexpr->rargs))); + appendStringInfoChar(buf, ')'); + } + else + elog(ERROR, "unrecognized testexpr type: %d", + (int) nodeTag(sublink->testexpr)); + } + + need_paren = true; + + switch (sublink->subLinkType) + { + case EXISTS_SUBLINK: + appendStringInfoString(buf, "EXISTS "); + break; + + case ANY_SUBLINK: + if (strcmp(opname, "=") == 0) /* Represent = ANY as IN */ + appendStringInfoString(buf, " IN "); + else + appendStringInfo(buf, " %s ANY ", opname); + break; + + case ALL_SUBLINK: + appendStringInfo(buf, " %s ALL ", opname); + break; + + case ROWCOMPARE_SUBLINK: + appendStringInfo(buf, " %s ", opname); + break; + + case EXPR_SUBLINK: + case MULTIEXPR_SUBLINK: + case ARRAY_SUBLINK: + need_paren = false; + break; + + case CTE_SUBLINK: /* shouldn't occur in a SubLink */ + default: + elog(ERROR, "unrecognized sublink type: %d", + (int) sublink->subLinkType); + break; + } + + if (need_paren) + appendStringInfoChar(buf, '('); + + get_query_def(query, buf, context->namespaces, NULL, + context->prettyFlags, context->wrapColumn, + context->indentLevel); + + if (need_paren) + appendStringInfoString(buf, "))"); + else + appendStringInfoChar(buf, ')'); +} + + +/* ---------- + * get_from_clause - Parse back a FROM clause + * + * "prefix" is the keyword that denotes the start of the list of FROM + * elements. It is FROM when used to parse back SELECT and UPDATE, but + * is USING when parsing back DELETE. + * ---------- + */ +static void +get_from_clause(Query *query, const char *prefix, deparse_context *context) +{ + StringInfo buf = context->buf; + bool first = true; + ListCell *l; + + /* + * We use the query's jointree as a guide to what to print. However, we + * must ignore auto-added RTEs that are marked not inFromCl. (These can + * only appear at the top level of the jointree, so it's sufficient to + * check here.) This check also ensures we ignore the rule pseudo-RTEs + * for NEW and OLD. + */ + foreach(l, query->jointree->fromlist) + { + Node *jtnode = (Node *) lfirst(l); + + if (IsA(jtnode, RangeTblRef)) + { + int varno = ((RangeTblRef *) jtnode)->rtindex; + RangeTblEntry *rte = rt_fetch(varno, query->rtable); + + if (!rte->inFromCl) + continue; + } + + if (first) + { + appendContextKeyword(context, prefix, + -PRETTYINDENT_STD, PRETTYINDENT_STD, 2); + first = false; + + get_from_clause_item(jtnode, query, context); + } + else + { + StringInfoData itembuf; + + appendStringInfoString(buf, ", "); + + /* + * Put the new FROM item's text into itembuf so we can decide + * after we've got it whether or not it needs to go on a new line. + */ + initStringInfo(&itembuf); + context->buf = &itembuf; + + get_from_clause_item(jtnode, query, context); + + /* Restore context's output buffer */ + context->buf = buf; + + /* Consider line-wrapping if enabled */ + if (PRETTY_INDENT(context) && context->wrapColumn >= 0) + { + /* Does the new item start with a new line? */ + if (itembuf.len > 0 && itembuf.data[0] == '\n') + { + /* If so, we shouldn't add anything */ + /* instead, remove any trailing spaces currently in buf */ + removeStringInfoSpaces(buf); + } + else + { + char *trailing_nl; + + /* Locate the start of the current line in the buffer */ + trailing_nl = strrchr(buf->data, '\n'); + if (trailing_nl == NULL) + trailing_nl = buf->data; + else + trailing_nl++; + + /* + * Add a newline, plus some indentation, if the new item + * would cause an overflow. + */ + if (strlen(trailing_nl) + itembuf.len > context->wrapColumn) + appendContextKeyword(context, "", -PRETTYINDENT_STD, + PRETTYINDENT_STD, + PRETTYINDENT_VAR); + } + } + + /* Add the new item */ + appendStringInfoString(buf, itembuf.data); + + /* clean up */ + pfree(itembuf.data); + } + } +} + +static void +get_from_clause_item(Node *jtnode, Query *query, deparse_context *context) +{ + StringInfo buf = context->buf; + deparse_namespace *dpns = (deparse_namespace *) linitial(context->namespaces); + + if (IsA(jtnode, RangeTblRef)) + { + int varno = ((RangeTblRef *) jtnode)->rtindex; + RangeTblEntry *rte = rt_fetch(varno, query->rtable); + char *refname = get_rtable_name(varno, context); + deparse_columns *colinfo = deparse_columns_fetch(varno, dpns); + RangeTblFunction *rtfunc1 = NULL; + bool printalias; + + if (rte->lateral) + appendStringInfoString(buf, "LATERAL "); + + /* Print the FROM item proper */ + switch (rte->rtekind) + { + case RTE_RELATION: + /* Normal relation RTE */ + appendStringInfo(buf, "%s%s", + only_marker(rte), + generate_relation_or_shard_name(rte->relid, + context->distrelid, + context->shardid, + context->namespaces)); + break; + case RTE_SUBQUERY: + /* Subquery RTE */ + appendStringInfoChar(buf, '('); + get_query_def(rte->subquery, buf, context->namespaces, NULL, + context->prettyFlags, context->wrapColumn, + context->indentLevel); + appendStringInfoChar(buf, ')'); + break; + case RTE_FUNCTION: + /* if it's a shard, do differently */ + if (GetRangeTblKind(rte) == CITUS_RTE_SHARD) + { + char *fragmentSchemaName = NULL; + char *fragmentTableName = NULL; + + ExtractRangeTblExtraData(rte, NULL, &fragmentSchemaName, &fragmentTableName, NULL); + + /* Use schema and table name from the remote alias */ + appendStringInfoString(buf, + generate_fragment_name(fragmentSchemaName, + fragmentTableName)); + break; + } + + /* Function RTE */ + rtfunc1 = (RangeTblFunction *) linitial(rte->functions); + + /* + * Omit ROWS FROM() syntax for just one function, unless it + * has both a coldeflist and WITH ORDINALITY. If it has both, + * we must use ROWS FROM() syntax to avoid ambiguity about + * whether the coldeflist includes the ordinality column. + */ + if (list_length(rte->functions) == 1 && + (rtfunc1->funccolnames == NIL || !rte->funcordinality)) + { + get_rule_expr(rtfunc1->funcexpr, context, true); + /* we'll print the coldeflist below, if it has one */ + } + else + { + bool all_unnest; + ListCell *lc; + + /* + * If all the function calls in the list are to unnest, + * and none need a coldeflist, then collapse the list back + * down to UNNEST(args). (If we had more than one + * built-in unnest function, this would get more + * difficult.) + * + * XXX This is pretty ugly, since it makes not-terribly- + * future-proof assumptions about what the parser would do + * with the output; but the alternative is to emit our + * nonstandard ROWS FROM() notation for what might have + * been a perfectly spec-compliant multi-argument + * UNNEST(). + */ + all_unnest = true; + foreach(lc, rte->functions) + { + RangeTblFunction *rtfunc = (RangeTblFunction *) lfirst(lc); + + if (!IsA(rtfunc->funcexpr, FuncExpr) || + ((FuncExpr *) rtfunc->funcexpr)->funcid != F_ARRAY_UNNEST || + rtfunc->funccolnames != NIL) + { + all_unnest = false; + break; + } + } + + if (all_unnest) + { + List *allargs = NIL; + + foreach(lc, rte->functions) + { + RangeTblFunction *rtfunc = (RangeTblFunction *) lfirst(lc); + List *args = ((FuncExpr *) rtfunc->funcexpr)->args; + + allargs = list_concat(allargs, list_copy(args)); + } + + appendStringInfoString(buf, "UNNEST("); + get_rule_expr((Node *) allargs, context, true); + appendStringInfoChar(buf, ')'); + } + else + { + int funcno = 0; + + appendStringInfoString(buf, "ROWS FROM("); + foreach(lc, rte->functions) + { + RangeTblFunction *rtfunc = (RangeTblFunction *) lfirst(lc); + + if (funcno > 0) + appendStringInfoString(buf, ", "); + get_rule_expr(rtfunc->funcexpr, context, true); + if (rtfunc->funccolnames != NIL) + { + /* Reconstruct the column definition list */ + appendStringInfoString(buf, " AS "); + get_from_clause_coldeflist(rtfunc, + NULL, + context); + } + funcno++; + } + appendStringInfoChar(buf, ')'); + } + /* prevent printing duplicate coldeflist below */ + rtfunc1 = NULL; + } + if (rte->funcordinality) + appendStringInfoString(buf, " WITH ORDINALITY"); + break; + case RTE_VALUES: + /* Values list RTE */ + appendStringInfoChar(buf, '('); + get_values_def(rte->values_lists, context); + appendStringInfoChar(buf, ')'); + break; + case RTE_CTE: + appendStringInfoString(buf, quote_identifier(rte->ctename)); + break; + default: + elog(ERROR, "unrecognized RTE kind: %d", (int) rte->rtekind); + break; + } + + /* Print the relation alias, if needed */ + printalias = false; + if (rte->alias != NULL) + { + /* Always print alias if user provided one */ + printalias = true; + } + else if (colinfo->printaliases) + { + /* Always print alias if we need to print column aliases */ + printalias = true; + } + else if (rte->rtekind == RTE_RELATION) + { + /* + * No need to print alias if it's same as relation name (this + * would normally be the case, but not if set_rtable_names had to + * resolve a conflict). + */ + if (strcmp(refname, get_relation_name(rte->relid)) != 0) + printalias = true; + } + else if (rte->rtekind == RTE_FUNCTION) + { + /* + * For a function RTE, always print alias. This covers possible + * renaming of the function and/or instability of the + * FigureColname rules for things that aren't simple functions. + * Note we'd need to force it anyway for the columndef list case. + */ + printalias = true; + } + else if (rte->rtekind == RTE_VALUES) + { + /* Alias is syntactically required for VALUES */ + printalias = true; + } + else if (rte->rtekind == RTE_CTE) + { + /* + * No need to print alias if it's same as CTE name (this would + * normally be the case, but not if set_rtable_names had to + * resolve a conflict). + */ + if (strcmp(refname, rte->ctename) != 0) + printalias = true; + } + if (printalias) + appendStringInfo(buf, " %s", quote_identifier(refname)); + + /* Print the column definitions or aliases, if needed */ + if (rtfunc1 && rtfunc1->funccolnames != NIL) + { + /* Reconstruct the columndef list, which is also the aliases */ + get_from_clause_coldeflist(rtfunc1, colinfo, context); + } + else if (GetRangeTblKind(rte) != CITUS_RTE_SHARD) + { + /* Else print column aliases as needed */ + get_column_alias_list(colinfo, context); + } + + /* Tablesample clause must go after any alias */ + if (rte->rtekind == RTE_RELATION && rte->tablesample) + get_tablesample_def(rte->tablesample, context); + } + else if (IsA(jtnode, JoinExpr)) + { + JoinExpr *j = (JoinExpr *) jtnode; + deparse_columns *colinfo = deparse_columns_fetch(j->rtindex, dpns); + bool need_paren_on_right; + + need_paren_on_right = PRETTY_PAREN(context) && + !IsA(j->rarg, RangeTblRef) && + !(IsA(j->rarg, JoinExpr) &&((JoinExpr *) j->rarg)->alias != NULL); + + if (!PRETTY_PAREN(context) || j->alias != NULL) + appendStringInfoChar(buf, '('); + + get_from_clause_item(j->larg, query, context); + + switch (j->jointype) + { + case JOIN_INNER: + if (j->quals) + appendContextKeyword(context, " JOIN ", + -PRETTYINDENT_STD, + PRETTYINDENT_STD, + PRETTYINDENT_JOIN); + else + appendContextKeyword(context, " CROSS JOIN ", + -PRETTYINDENT_STD, + PRETTYINDENT_STD, + PRETTYINDENT_JOIN); + break; + case JOIN_LEFT: + appendContextKeyword(context, " LEFT JOIN ", + -PRETTYINDENT_STD, + PRETTYINDENT_STD, + PRETTYINDENT_JOIN); + break; + case JOIN_FULL: + appendContextKeyword(context, " FULL JOIN ", + -PRETTYINDENT_STD, + PRETTYINDENT_STD, + PRETTYINDENT_JOIN); + break; + case JOIN_RIGHT: + appendContextKeyword(context, " RIGHT JOIN ", + -PRETTYINDENT_STD, + PRETTYINDENT_STD, + PRETTYINDENT_JOIN); + break; + default: + elog(ERROR, "unrecognized join type: %d", + (int) j->jointype); + } + + if (need_paren_on_right) + appendStringInfoChar(buf, '('); + get_from_clause_item(j->rarg, query, context); + if (need_paren_on_right) + appendStringInfoChar(buf, ')'); + + if (j->usingClause) + { + ListCell *lc; + bool first = true; + + appendStringInfoString(buf, " USING ("); + /* Use the assigned names, not what's in usingClause */ + foreach(lc, colinfo->usingNames) + { + char *colname = (char *) lfirst(lc); + + if (first) + first = false; + else + appendStringInfoString(buf, ", "); + appendStringInfoString(buf, quote_identifier(colname)); + } + appendStringInfoChar(buf, ')'); + } + else if (j->quals) + { + appendStringInfoString(buf, " ON "); + if (!PRETTY_PAREN(context)) + appendStringInfoChar(buf, '('); + get_rule_expr(j->quals, context, false); + if (!PRETTY_PAREN(context)) + appendStringInfoChar(buf, ')'); + } + + if (!PRETTY_PAREN(context) || j->alias != NULL) + appendStringInfoChar(buf, ')'); + + /* Yes, it's correct to put alias after the right paren ... */ + if (j->alias != NULL) + { + appendStringInfo(buf, " %s", + quote_identifier(j->alias->aliasname)); + get_column_alias_list(colinfo, context); + } + } + else + elog(ERROR, "unrecognized node type: %d", + (int) nodeTag(jtnode)); +} + +/* + * get_column_alias_list - print column alias list for an RTE + * + * Caller must already have printed the relation's alias name. + */ +static void +get_column_alias_list(deparse_columns *colinfo, deparse_context *context) +{ + StringInfo buf = context->buf; + int i; + bool first = true; + + /* Don't print aliases if not needed */ + if (!colinfo->printaliases) + return; + + for (i = 0; i < colinfo->num_new_cols; i++) + { + char *colname = colinfo->new_colnames[i]; + + if (first) + { + appendStringInfoChar(buf, '('); + first = false; + } + else + appendStringInfoString(buf, ", "); + appendStringInfoString(buf, quote_identifier(colname)); + } + if (!first) + appendStringInfoChar(buf, ')'); +} + +/* + * get_from_clause_coldeflist - reproduce FROM clause coldeflist + * + * When printing a top-level coldeflist (which is syntactically also the + * relation's column alias list), use column names from colinfo. But when + * printing a coldeflist embedded inside ROWS FROM(), we prefer to use the + * original coldeflist's names, which are available in rtfunc->funccolnames. + * Pass NULL for colinfo to select the latter behavior. + * + * The coldeflist is appended immediately (no space) to buf. Caller is + * responsible for ensuring that an alias or AS is present before it. + */ +static void +get_from_clause_coldeflist(RangeTblFunction *rtfunc, + deparse_columns *colinfo, + deparse_context *context) +{ + StringInfo buf = context->buf; + ListCell *l1; + ListCell *l2; + ListCell *l3; + ListCell *l4; + int i; + + appendStringInfoChar(buf, '('); + + /* there's no forfour(), so must chase one list the hard way */ + i = 0; + l4 = list_head(rtfunc->funccolnames); + forthree(l1, rtfunc->funccoltypes, + l2, rtfunc->funccoltypmods, + l3, rtfunc->funccolcollations) + { + Oid atttypid = lfirst_oid(l1); + int32 atttypmod = lfirst_int(l2); + Oid attcollation = lfirst_oid(l3); + char *attname; + + if (colinfo) + attname = colinfo->colnames[i]; + else + attname = strVal(lfirst(l4)); + + Assert(attname); /* shouldn't be any dropped columns here */ + + if (i > 0) + appendStringInfoString(buf, ", "); + appendStringInfo(buf, "%s %s", + quote_identifier(attname), + format_type_with_typemod(atttypid, atttypmod)); + if (OidIsValid(attcollation) && + attcollation != get_typcollation(atttypid)) + appendStringInfo(buf, " COLLATE %s", + generate_collation_name(attcollation)); + + l4 = lnext(l4); + i++; + } + + appendStringInfoChar(buf, ')'); +} + +/* + * get_tablesample_def - print a TableSampleClause + */ +static void +get_tablesample_def(TableSampleClause *tablesample, deparse_context *context) +{ + StringInfo buf = context->buf; + Oid argtypes[1]; + int nargs; + ListCell *l; + + /* + * We should qualify the handler's function name if it wouldn't be + * resolved by lookup in the current search path. + */ + argtypes[0] = INTERNALOID; + appendStringInfo(buf, " TABLESAMPLE %s (", + generate_function_name(tablesample->tsmhandler, 1, + NIL, argtypes, + false, NULL, EXPR_KIND_NONE)); + + nargs = 0; + foreach(l, tablesample->args) + { + if (nargs++ > 0) + appendStringInfoString(buf, ", "); + get_rule_expr((Node *) lfirst(l), context, false); + } + appendStringInfoChar(buf, ')'); + + if (tablesample->repeatable != NULL) + { + appendStringInfoString(buf, " REPEATABLE ("); + get_rule_expr((Node *) tablesample->repeatable, context, false); + appendStringInfoChar(buf, ')'); + } +} + +/* + * get_opclass_name - fetch name of an index operator class + * + * The opclass name is appended (after a space) to buf. + * + * Output is suppressed if the opclass is the default for the given + * actual_datatype. (If you don't want this behavior, just pass + * InvalidOid for actual_datatype.) + */ +static void +get_opclass_name(Oid opclass, Oid actual_datatype, + StringInfo buf) +{ + HeapTuple ht_opc; + Form_pg_opclass opcrec; + char *opcname; + char *nspname; + + ht_opc = SearchSysCache1(CLAOID, ObjectIdGetDatum(opclass)); + if (!HeapTupleIsValid(ht_opc)) + elog(ERROR, "cache lookup failed for opclass %u", opclass); + opcrec = (Form_pg_opclass) GETSTRUCT(ht_opc); + + if (!OidIsValid(actual_datatype) || + GetDefaultOpClass(actual_datatype, opcrec->opcmethod) != opclass) + { + /* Okay, we need the opclass name. Do we need to qualify it? */ + opcname = NameStr(opcrec->opcname); + if (OpclassIsVisible(opclass)) + appendStringInfo(buf, " %s", quote_identifier(opcname)); + else + { + nspname = get_namespace_name(opcrec->opcnamespace); + appendStringInfo(buf, " %s.%s", + quote_identifier(nspname), + quote_identifier(opcname)); + } + } + ReleaseSysCache(ht_opc); +} + +/* + * processIndirection - take care of array and subfield assignment + * + * We strip any top-level FieldStore or assignment ArrayRef nodes that + * appear in the input, and return the subexpression that's to be assigned. + * If printit is true, we also print out the appropriate decoration for the + * base column name (that the caller just printed). + */ +static Node * +processIndirection(Node *node, deparse_context *context, bool printit) +{ + StringInfo buf = context->buf; + + for (;;) + { + if (node == NULL) + break; + if (IsA(node, FieldStore)) + { + FieldStore *fstore = (FieldStore *) node; + Oid typrelid; + char *fieldname; + + /* lookup tuple type */ + typrelid = get_typ_typrelid(fstore->resulttype); + if (!OidIsValid(typrelid)) + elog(ERROR, "argument type %s of FieldStore is not a tuple type", + format_type_be(fstore->resulttype)); + + /* + * Print the field name. There should only be one target field in + * stored rules. There could be more than that in executable + * target lists, but this function cannot be used for that case. + */ + Assert(list_length(fstore->fieldnums) == 1); + fieldname = get_relid_attribute_name(typrelid, + linitial_int(fstore->fieldnums)); + if (printit) + appendStringInfo(buf, ".%s", quote_identifier(fieldname)); + + /* + * We ignore arg since it should be an uninteresting reference to + * the target column or subcolumn. + */ + node = (Node *) linitial(fstore->newvals); + } + else if (IsA(node, ArrayRef)) + { + ArrayRef *aref = (ArrayRef *) node; + + if (aref->refassgnexpr == NULL) + break; + if (printit) + printSubscripts(aref, context); + + /* + * We ignore refexpr since it should be an uninteresting reference + * to the target column or subcolumn. + */ + node = (Node *) aref->refassgnexpr; + } + else + break; + } + + return node; +} + +static void +printSubscripts(ArrayRef *aref, deparse_context *context) +{ + StringInfo buf = context->buf; + ListCell *lowlist_item; + ListCell *uplist_item; + + lowlist_item = list_head(aref->reflowerindexpr); /* could be NULL */ + foreach(uplist_item, aref->refupperindexpr) + { + appendStringInfoChar(buf, '['); + if (lowlist_item) + { + get_rule_expr((Node *) lfirst(lowlist_item), context, false); + appendStringInfoChar(buf, ':'); + lowlist_item = lnext(lowlist_item); + } + get_rule_expr((Node *) lfirst(uplist_item), context, false); + appendStringInfoChar(buf, ']'); + } +} + +/* + * get_relation_name + * Get the unqualified name of a relation specified by OID + * + * This differs from the underlying get_rel_name() function in that it will + * throw error instead of silently returning NULL if the OID is bad. + */ +static char * +get_relation_name(Oid relid) +{ + char *relname = get_rel_name(relid); + + if (!relname) + elog(ERROR, "cache lookup failed for relation %u", relid); + return relname; +} + +/* + * generate_relation_or_shard_name + * Compute the name to display for a relation or shard + * + * If the provided relid is equal to the provided distrelid, this function + * returns a shard-extended relation name; otherwise, it falls through to a + * simple generate_relation_name call. + */ +static char * +generate_relation_or_shard_name(Oid relid, Oid distrelid, int64 shardid, + List *namespaces) +{ + char *relname = NULL; + + if (relid == distrelid) + { + /* XXX: this is where we would--but don't yet--handle schema-prefixing */ + relname = get_relation_name(relid); + + if (shardid > 0) + { + AppendShardIdToName(&relname, shardid); + + relname = (char *) quote_identifier(relname); + } + } + else + { + relname = generate_relation_name(relid, namespaces); + } + + return relname; +} + +/* + * generate_relation_name + * Compute the name to display for a relation specified by OID + * + * The result includes all necessary quoting and schema-prefixing. + * + * If namespaces isn't NIL, it must be a list of deparse_namespace nodes. + * We will forcibly qualify the relation name if it equals any CTE name + * visible in the namespace list. + */ +char * +generate_relation_name(Oid relid, List *namespaces) +{ + HeapTuple tp; + Form_pg_class reltup; + bool need_qual; + ListCell *nslist; + char *relname; + char *nspname; + char *result; + + tp = SearchSysCache1(RELOID, ObjectIdGetDatum(relid)); + if (!HeapTupleIsValid(tp)) + elog(ERROR, "cache lookup failed for relation %u", relid); + reltup = (Form_pg_class) GETSTRUCT(tp); + relname = NameStr(reltup->relname); + + /* Check for conflicting CTE name */ + need_qual = false; + foreach(nslist, namespaces) + { + deparse_namespace *dpns = (deparse_namespace *) lfirst(nslist); + ListCell *ctlist; + + foreach(ctlist, dpns->ctes) + { + CommonTableExpr *cte = (CommonTableExpr *) lfirst(ctlist); + + if (strcmp(cte->ctename, relname) == 0) + { + need_qual = true; + break; + } + } + if (need_qual) + break; + } + + /* Otherwise, qualify the name if not visible in search path */ + if (!need_qual) + need_qual = !RelationIsVisible(relid); + + if (need_qual) + nspname = get_namespace_name(reltup->relnamespace); + else + nspname = NULL; + + result = quote_qualified_identifier(nspname, relname); + + ReleaseSysCache(tp); + + return result; +} + +/* + * generate_fragment_name + * Compute the name to display for a shard or merged table + * + * The result includes all necessary quoting and schema-prefixing. The schema + * name can be NULL for regular shards. For merged tables, they are always + * declared within a job-specific schema, and therefore can't have null schema + * names. + */ +static char * +generate_fragment_name(char *schemaName, char *tableName) +{ + StringInfo fragmentNameString = makeStringInfo(); + + if (schemaName != NULL) + { + appendStringInfo(fragmentNameString, "%s.%s", quote_identifier(schemaName), + quote_identifier(tableName)); + } + else + { + appendStringInfoString(fragmentNameString, quote_identifier(tableName)); + } + + return fragmentNameString->data; +} + +/* + * generate_function_name + * Compute the name to display for a function specified by OID, + * given that it is being called with the specified actual arg names and + * types. (Those matter because of ambiguous-function resolution rules.) + * + * If we're dealing with a potentially variadic function (in practice, this + * means a FuncExpr or Aggref, not some other way of calling a function), then + * has_variadic must specify whether variadic arguments have been merged, + * and *use_variadic_p will be set to indicate whether to print VARIADIC in + * the output. For non-FuncExpr cases, has_variadic should be FALSE and + * use_variadic_p can be NULL. + * + * The result includes all necessary quoting and schema-prefixing. + */ +static char * +generate_function_name(Oid funcid, int nargs, List *argnames, Oid *argtypes, + bool has_variadic, bool *use_variadic_p, + ParseExprKind special_exprkind) +{ + char *result; + HeapTuple proctup; + Form_pg_proc procform; + char *proname; + bool use_variadic; + char *nspname; + FuncDetailCode p_result; + Oid p_funcid; + Oid p_rettype; + bool p_retset; + int p_nvargs; + Oid p_vatype; + Oid *p_true_typeids; + bool force_qualify = false; + + proctup = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid)); + if (!HeapTupleIsValid(proctup)) + elog(ERROR, "cache lookup failed for function %u", funcid); + procform = (Form_pg_proc) GETSTRUCT(proctup); + proname = NameStr(procform->proname); + + /* + * Due to parser hacks to avoid needing to reserve CUBE, we need to force + * qualification in some special cases. + */ + if (special_exprkind == EXPR_KIND_GROUP_BY) + { + if (strcmp(proname, "cube") == 0 || strcmp(proname, "rollup") == 0) + force_qualify = true; + } + + /* + * Determine whether VARIADIC should be printed. We must do this first + * since it affects the lookup rules in func_get_detail(). + * + * Currently, we always print VARIADIC if the function has a merged + * variadic-array argument. Note that this is always the case for + * functions taking a VARIADIC argument type other than VARIADIC ANY. + * + * In principle, if VARIADIC wasn't originally specified and the array + * actual argument is deconstructable, we could print the array elements + * separately and not print VARIADIC, thus more nearly reproducing the + * original input. For the moment that seems like too much complication + * for the benefit, and anyway we do not know whether VARIADIC was + * originally specified if it's a non-ANY type. + */ + if (use_variadic_p) + { + /* Parser should not have set funcvariadic unless fn is variadic */ + Assert(!has_variadic || OidIsValid(procform->provariadic)); + use_variadic = has_variadic; + *use_variadic_p = use_variadic; + } + else + { + Assert(!has_variadic); + use_variadic = false; + } + + /* + * The idea here is to schema-qualify only if the parser would fail to + * resolve the correct function given the unqualified func name with the + * specified argtypes and VARIADIC flag. But if we already decided to + * force qualification, then we can skip the lookup and pretend we didn't + * find it. + */ + if (!force_qualify) + p_result = func_get_detail(list_make1(makeString(proname)), + NIL, argnames, nargs, argtypes, + !use_variadic, true, + &p_funcid, &p_rettype, + &p_retset, &p_nvargs, &p_vatype, + &p_true_typeids, NULL); + else + { + p_result = FUNCDETAIL_NOTFOUND; + p_funcid = InvalidOid; + } + + if ((p_result == FUNCDETAIL_NORMAL || + p_result == FUNCDETAIL_AGGREGATE || + p_result == FUNCDETAIL_WINDOWFUNC) && + p_funcid == funcid) + nspname = NULL; + else + nspname = get_namespace_name(procform->pronamespace); + + result = quote_qualified_identifier(nspname, proname); + + ReleaseSysCache(proctup); + + return result; +} + +/* + * generate_operator_name + * Compute the name to display for an operator specified by OID, + * given that it is being called with the specified actual arg types. + * (Arg types matter because of ambiguous-operator resolution rules. + * Pass InvalidOid for unused arg of a unary operator.) + * + * The result includes all necessary quoting and schema-prefixing, + * plus the OPERATOR() decoration needed to use a qualified operator name + * in an expression. + */ +static char * +generate_operator_name(Oid operid, Oid arg1, Oid arg2) +{ + StringInfoData buf; + HeapTuple opertup; + Form_pg_operator operform; + char *oprname; + char *nspname; + Operator p_result; + + initStringInfo(&buf); + + opertup = SearchSysCache1(OPEROID, ObjectIdGetDatum(operid)); + if (!HeapTupleIsValid(opertup)) + elog(ERROR, "cache lookup failed for operator %u", operid); + operform = (Form_pg_operator) GETSTRUCT(opertup); + oprname = NameStr(operform->oprname); + + /* + * The idea here is to schema-qualify only if the parser would fail to + * resolve the correct operator given the unqualified op name with the + * specified argtypes. + */ + switch (operform->oprkind) + { + case 'b': + p_result = oper(NULL, list_make1(makeString(oprname)), arg1, arg2, + true, -1); + break; + case 'l': + p_result = left_oper(NULL, list_make1(makeString(oprname)), arg2, + true, -1); + break; + case 'r': + p_result = right_oper(NULL, list_make1(makeString(oprname)), arg1, + true, -1); + break; + default: + elog(ERROR, "unrecognized oprkind: %d", operform->oprkind); + p_result = NULL; /* keep compiler quiet */ + break; + } + + if (p_result != NULL && oprid(p_result) == operid) + nspname = NULL; + else + { + nspname = get_namespace_name(operform->oprnamespace); + appendStringInfo(&buf, "OPERATOR(%s.", quote_identifier(nspname)); + } + + appendStringInfoString(&buf, oprname); + + if (nspname) + appendStringInfoChar(&buf, ')'); + + if (p_result != NULL) + ReleaseSysCache(p_result); + + ReleaseSysCache(opertup); + + return buf.data; +} + +#endif diff --git a/src/backend/distributed/worker/task_tracker.c b/src/backend/distributed/worker/task_tracker.c new file mode 100644 index 000000000..b8a6bde6a --- /dev/null +++ b/src/backend/distributed/worker/task_tracker.c @@ -0,0 +1,1095 @@ +/*------------------------------------------------------------------------- + * + * task_tracker.c + * + * The task tracker background process runs on every worker node. The process + * wakes up at regular intervals, reads information from a shared hash, and + * checks if any new tasks are assigned to this node. If they are, the process + * runs task-specific logic, and sends queries to the postmaster for execution. + * The task tracker then tracks the execution of these queries, and updates the + * shared hash with task progress information. + * + * The task tracker is started by the postmaster when the startup process + * finishes. The process remains alive until the postmaster commands it to + * terminate. Normal termination is by SIGTERM, which instructs the task tracker + * to exit(0). Emergency termination is by SIGQUIT; like any backend, the task + * tracker will simply abort and exit on SIGQUIT. + * + * For details on how the task tracker manages resources during process start-up + * and shutdown, please see the writeboard on our Basecamp project website. + * + * Copyright (c) 2012, Citus Data, Inc. + * + * $Id$ + * + *------------------------------------------------------------------------- + */ + +#include "postgres.h" +#include "miscadmin.h" +#include + +#include "commands/dbcommands.h" +#include "distributed/multi_client_executor.h" +#include "distributed/multi_server_executor.h" +#include "distributed/task_tracker.h" +#include "distributed/transmit.h" +#include "distributed/worker_protocol.h" +#include "libpq/hba.h" +#include "libpq/pqsignal.h" +#include "lib/stringinfo.h" +#include "postmaster/bgworker.h" +#include "postmaster/postmaster.h" +#include "storage/fd.h" +#include "storage/ipc.h" +#include "storage/lwlock.h" +#include "storage/pmsignal.h" +#include "storage/proc.h" +#include "storage/shmem.h" +#include "utils/guc.h" +#include "utils/memutils.h" + + +int TaskTrackerDelay = 200; /* process sleep interval in millisecs */ +int MaxRunningTasksPerNode = 16; /* max number of running tasks */ +int MaxTrackedTasksPerNode = 1024; /* max number of tracked tasks */ +WorkerTasksSharedStateData *WorkerTasksSharedState; /* shared memory state */ + +static shmem_startup_hook_type prev_shmem_startup_hook = NULL; + +/* Flags set by interrupt handlers for later service in the main loop */ +static volatile sig_atomic_t got_SIGHUP = false; +static volatile sig_atomic_t got_SIGTERM = false; + +/* initialization forward declarations */ +static void TaskTrackerMain(Datum main_arg); +static Size TaskTrackerShmemSize(void); +static void TaskTrackerShmemInit(void); + +/* Signal handler forward declarations */ +static void TrackerSigHupHandler(SIGNAL_ARGS); +static void TrackerShutdownHandler(SIGNAL_ARGS); + +/* Local functions forward declarations */ +static void TrackerCleanupJobDirectories(void); +static void TrackerCleanupJobSchemas(void); +static void TrackerCleanupConnections(HTAB *WorkerTasksHash); +static void TrackerRegisterShutDown(HTAB *WorkerTasksHash); +static void TrackerDelayLoop(void); +static List *SchedulableTaskList(HTAB *WorkerTasksHash); +static WorkerTask * SchedulableTaskPriorityQueue(HTAB *WorkerTasksHash); +static uint32 CountTasksMatchingCriteria(HTAB *WorkerTasksHash, + bool (*CriteriaFunction) (WorkerTask *)); +static bool RunningTask(WorkerTask *workerTask); +static bool SchedulableTask(WorkerTask *workerTask); +static int CompareTasksByTime(const void *first, const void *second); +static void ScheduleWorkerTasks(HTAB *WorkerTasksHash, List *schedulableTaskList); +static void ManageWorkerTasksHash(HTAB *WorkerTasksHash); +static void ManageWorkerTask(WorkerTask *workerTask, HTAB *WorkerTasksHash); +static void RemoveWorkerTask(WorkerTask *workerTask, HTAB *WorkerTasksHash); +static void CreateJobDirectoryIfNotExists(uint64 jobId); +static int32 ConnectToLocalBackend(const char *databaseName); + + +/* Organize, at startup, that the task tracker is started */ +void +TaskTrackerRegister(void) +{ + BackgroundWorker worker; + + /* organize and register initialization of required shared memory */ + RequestAddinShmemSpace(TaskTrackerShmemSize()); + RequestAddinLWLocks(1); + + prev_shmem_startup_hook = shmem_startup_hook; + shmem_startup_hook = TaskTrackerShmemInit; + + /* and that the task tracker is started as background worker */ + memset(&worker, 0, sizeof(worker)); + worker.bgw_flags = BGWORKER_SHMEM_ACCESS; + worker.bgw_start_time = BgWorkerStart_ConsistentState; + worker.bgw_restart_time = 1; + worker.bgw_main = TaskTrackerMain; + worker.bgw_notify_pid = 0; + snprintf(worker.bgw_name, BGW_MAXLEN, "task tracker"); + + RegisterBackgroundWorker(&worker); +} + + +/* Main entry point for task tracker process. */ +static void +TaskTrackerMain(Datum main_arg) +{ + MemoryContext TaskTrackerContext = NULL; + sigjmp_buf local_sigjmp_buf; + static bool processStartUp = true; + + /* Properly accept or ignore signals the postmaster might send us */ + pqsignal(SIGHUP, TrackerSigHupHandler); /* set flag to read config file */ + pqsignal(SIGTERM, TrackerShutdownHandler); /* request shutdown */ + + /* We're now ready to receive signals */ + BackgroundWorkerUnblockSignals(); + + /* + * Create a memory context that we will do all our work in. We do this so + * that we can reset the context during error recovery and thereby avoid + * possible memory leaks. + */ + TaskTrackerContext = AllocSetContextCreate(TopMemoryContext, "Task Tracker", + ALLOCSET_DEFAULT_MINSIZE, + ALLOCSET_DEFAULT_INITSIZE, + ALLOCSET_DEFAULT_MAXSIZE); + MemoryContextSwitchTo(TaskTrackerContext); + + /* + * If an exception is encountered, processing resumes here. The motivation + * for this code block is outlined in postgres.c, and the code itself is + * heavily based on bgwriter.c. + * + * In most error scenarios, we will not drop here: the task tracker process + * offloads all work to backend processes, and checks the completion of work + * through the client executor library. We will therefore only come here if + * we have inconsistencies in the shared hash and need to signal an error. + */ + if (sigsetjmp(local_sigjmp_buf, 1) != 0) + { + /* Since we are not using PG_TRY, we must reset error stack by hand */ + error_context_stack = NULL; + + /* Prevents interrupts while cleaning up */ + HOLD_INTERRUPTS(); + + /* Report the error to the server log */ + EmitErrorReport(); + + /* + * These operations are just a minimal subset of AbortTransaction(). + * We do not have many resources to worry about; we only have a shared + * hash and an LWLock guarding that hash. + */ + LWLockReleaseAll(); + AtEOXact_Files(); + AtEOXact_HashTables(false); + + /* + * Now return to normal top-level context, and clear ErrorContext for + * next time. + */ + MemoryContextSwitchTo(TaskTrackerContext); + FlushErrorState(); + + /* Flush any leaked data in the top-level context */ + MemoryContextResetAndDeleteChildren(TaskTrackerContext); + + /* Now we can allow interrupts again */ + RESUME_INTERRUPTS(); + + /* + * Sleep at least 1 second after any error. A write error is likely to + * be repeated, and we don't want to be filling the error logs as fast + * as we can. + */ + pg_usleep(1000000L); + } + + /* We can now handle ereport(ERROR) */ + PG_exception_stack = &local_sigjmp_buf; + + /* + * We run validation and cache cleanup functions as this process is starting + * up. If these functions throw an error, we won't try running them again. + */ + if (processStartUp) + { + processStartUp = false; + + /* clean up old files in the job cache */ + TrackerCleanupJobDirectories(); + + /* clean up schemas in the job cache */ + TrackerCleanupJobSchemas(); + } + + /* Loop forever */ + for (;;) + { + /* + * Emergency bailout if postmaster has died. This is to avoid the + * necessity for manual cleanup of all postmaster children. + * + * XXX: Note that PostgreSQL background processes no longer nap between + * their loops, but instead uses latches to wake up when necessary. We + * should switch to using latches in here too, and have the task tracker + * assign function notify us when there is a new task. + */ + if (!PostmasterIsAlive()) + { + exit(1); + } + + /* Process any requests or signals received recently */ + if (got_SIGHUP) + { + got_SIGHUP = false; + + /* reload postgres configuration files */ + ProcessConfigFile(PGC_SIGHUP); + + /* + * Reload worker membership file. For now we do that in the task + * tracker because that's currently the only background worker in + * CitusDB. And only background workers allow us to safely + * register a SIGHUP handler. + */ + LoadWorkerNodeList(WorkerListFileName); + } + if (got_SIGTERM) + { + /* + * From here on, reporting errors should end with exit(1), and not + * send control back to the sigsetjmp block above. + */ + ExitOnAnyError = true; + + /* Close open connections to local backends */ + TrackerCleanupConnections(WorkerTasksSharedState->taskHash); + + /* Add a sentinel task to the shared hash to mark shutdown */ + TrackerRegisterShutDown(WorkerTasksSharedState->taskHash); + + /* Normal exit from the task tracker is here */ + proc_exit(0); + } + + /* Call the function that does the actual work */ + ManageWorkerTasksHash(WorkerTasksSharedState->taskHash); + + /* Sleep for the configured time */ + TrackerDelayLoop(); + } +} + + +/* + * WorkerTasksHashEnter creates a new worker task in the shared hash, and + * performs checks for this task. Note that the caller still needs to initialize + * the worker task's fields, and hold the appopriate locks for the shared hash. + */ +WorkerTask * +WorkerTasksHashEnter(uint64 jobId, uint32 taskId) +{ + WorkerTask *workerTask = NULL; + void *hashKey = NULL; + bool handleFound = false; + + WorkerTask searchTask; + searchTask.jobId = jobId; + searchTask.taskId = taskId; + + hashKey = (void *) &searchTask; + workerTask = (WorkerTask *) hash_search(WorkerTasksSharedState->taskHash, hashKey, + HASH_ENTER_NULL, &handleFound); + if (workerTask == NULL) + { + ereport(ERROR, (errcode(ERRCODE_OUT_OF_MEMORY), + errmsg("out of shared memory"), + errhint("Try increasing citusdb.max_tracked_tasks_per_node."))); + } + + /* check that we do not have the same task assigned twice to this node */ + if (handleFound) + { + ereport(ERROR, (errmsg("cannot assign an already assigned task"), + errdetail("Task jobId: " UINT64_FORMAT " and taskId: %u", + jobId, taskId))); + } + + return workerTask; +} + + +/* + * WorkerTasksHashFind looks up the worker task with the given identifiers in + * the shared hash. Note that the caller still needs to hold the appropriate + * locks for the shared hash. + */ +WorkerTask * +WorkerTasksHashFind(uint64 jobId, uint32 taskId) +{ + WorkerTask *workerTask = NULL; + void *hashKey = NULL; + + WorkerTask searchTask; + searchTask.jobId = jobId; + searchTask.taskId = taskId; + + hashKey = (void *) &searchTask; + workerTask = (WorkerTask *) hash_search(WorkerTasksSharedState->taskHash, hashKey, + HASH_FIND, NULL); + + return workerTask; +} + + +/* + * TrackerCleanupJobDirectories cleans up all files in the job cache directory + * as part of this process's start-up logic. The task tracker process manages + * both tasks in the shared hash and these tasks' output files. When the task + * tracker needs to shutdown, all shared hash entries are deleted, but the + * associated files cannot be cleaned up safely. We therefore perform this + * cleanup when the process restarts. + */ +static void +TrackerCleanupJobDirectories(void) +{ + /* use the default tablespace in {datadir}/base */ + StringInfo jobCacheDirectory = makeStringInfo(); + appendStringInfo(jobCacheDirectory, "base/%s", PG_JOB_CACHE_DIR); + + RemoveDirectory(jobCacheDirectory); + CreateDirectory(jobCacheDirectory); + + FreeStringInfo(jobCacheDirectory); +} + + +/* + * TrackerCleanupJobSchemas creates and assigns tasks to remove job schemas and + * all tables within these schemas. These job schemas are currently created by + * merge tasks, and may linger if the database shuts down before the jobs get + * cleaned up. This function then runs during process start-up, and creates one + * task per database to remove lingering job schemas, if any. + */ +static void +TrackerCleanupJobSchemas(void) +{ + /* + * XXX: We previously called DatabaseNameList() to read the list of database + * names here. This function read the database names from the flat database + * file; this file was deprecated on Aug 31, 2009. We hence need to rewrite + * this function to read from pg_database directly. + */ + List *databaseNameList = NIL; + ListCell *databaseNameCell = NULL; + const uint64 jobId = RESERVED_JOB_ID; + uint32 taskIndex = 1; + + LWLockAcquire(WorkerTasksSharedState->taskHashLock, LW_EXCLUSIVE); + + foreach(databaseNameCell, databaseNameList) + { + char *databaseName = (char *) lfirst(databaseNameCell); + WorkerTask *cleanupTask = NULL; + + /* template0 database does not accept connections */ + int skipDatabaseName = strncmp(databaseName, TEMPLATE0_NAME, NAMEDATALEN); + if (skipDatabaseName == 0) + { + continue; + } + + /* + * We create cleanup tasks since we can't remove schemas within the task + * tracker process. We also assign high priorities to these tasks so + * that they get scheduled before everyone else. + */ + cleanupTask = WorkerTasksHashEnter(jobId, taskIndex); + cleanupTask->assignedAt = HIGH_PRIORITY_TASK_TIME; + cleanupTask->taskStatus = TASK_ASSIGNED; + + strncpy(cleanupTask->taskCallString, JOB_SCHEMA_CLEANUP, TASK_CALL_STRING_SIZE); + strncpy(cleanupTask->databaseName, databaseName, NAMEDATALEN); + + /* zero out all other fields */ + cleanupTask->connectionId = INVALID_CONNECTION_ID; + cleanupTask->failureCount = 0; + + taskIndex++; + } + + LWLockRelease(WorkerTasksSharedState->taskHashLock); + + if (databaseNameList != NIL) + { + list_free_deep(databaseNameList); + } +} + + +/* + * TrackerCleanupConnections closes all open connections to backends during + * process shutdown. This signals to the backends that their connections are + * gone and stops them from logging pipe-related warning messages. + */ +static void +TrackerCleanupConnections(HTAB *WorkerTasksHash) +{ + HASH_SEQ_STATUS status; + WorkerTask *currentTask = NULL; + + hash_seq_init(&status, WorkerTasksHash); + + currentTask = (WorkerTask *) hash_seq_search(&status); + while (currentTask != NULL) + { + if (currentTask->connectionId != INVALID_CONNECTION_ID) + { + MultiClientDisconnect(currentTask->connectionId); + currentTask->connectionId = INVALID_CONNECTION_ID; + } + + currentTask = (WorkerTask *) hash_seq_search(&status); + } +} + + +/* + * TrackerRegisterShutDown enters a special marker task to the shared hash. This + * marker task indicates to "task protocol processes" that we are shutting down + * and that they shouldn't accept new task assignments. + */ +static void +TrackerRegisterShutDown(HTAB *WorkerTasksHash) +{ + uint64 jobId = RESERVED_JOB_ID; + uint32 taskId = SHUTDOWN_MARKER_TASK_ID; + WorkerTask *shutdownMarkerTask = NULL; + + LWLockAcquire(WorkerTasksSharedState->taskHashLock, LW_EXCLUSIVE); + + shutdownMarkerTask = WorkerTasksHashEnter(jobId, taskId); + shutdownMarkerTask->taskStatus = TASK_SUCCEEDED; + shutdownMarkerTask->connectionId = INVALID_CONNECTION_ID; + + LWLockRelease(WorkerTasksSharedState->taskHashLock); +} + + +/* Sleeps either for the configured time or until a signal is received. */ +static void +TrackerDelayLoop(void) +{ + const long SignalCheckInterval = 1000000L; /* check signal every second */ + + /* + * On some platforms, signals do not interrupt the sleep. To ensure we + * respond promptly when someone signals us, we break down the sleep into + * 1-second increments, and check for interrupts after each nap. + */ + long trackerDelay = TaskTrackerDelay * 1000L; + while (trackerDelay > (SignalCheckInterval - 1)) + { + if (got_SIGHUP || got_SIGTERM) + { + break; + } + pg_usleep(SignalCheckInterval); + trackerDelay -= SignalCheckInterval; + } + if (!(got_SIGHUP || got_SIGTERM)) + { + pg_usleep(trackerDelay); + } +} + +/* ------------------------------------------------------------ + * Signal handling and shared hash initialization functions follow + * ------------------------------------------------------------ + */ + +/* SIGHUP: set flag to re-read config file at next convenient time */ +static void +TrackerSigHupHandler(SIGNAL_ARGS) +{ + int save_errno = errno; + + got_SIGHUP = true; + if (MyProc != NULL) + { + SetLatch(&MyProc->procLatch); + } + + errno = save_errno; +} + + +/* SIGTERM: set flag for main loop to exit normally */ +static void +TrackerShutdownHandler(SIGNAL_ARGS) +{ + int save_errno = errno; + + got_SIGTERM = true; + if (MyProc != NULL) + { + SetLatch(&MyProc->procLatch); + } + + errno = save_errno; +} + + +/* Estimates the shared memory size used for keeping track of tasks. */ +static Size +TaskTrackerShmemSize(void) +{ + Size size = 0; + Size hashSize = 0; + + size = add_size(size, sizeof(WorkerTasksSharedStateData)); + + hashSize = hash_estimate_size(MaxTrackedTasksPerNode, sizeof(WorkerTask)); + size = add_size(size, hashSize); + + return size; +} + + +/* Initializes the shared memory used for keeping track of tasks. */ +static void +TaskTrackerShmemInit(void) +{ + bool alreadyInitialized = false; + HASHCTL info; + int hashFlags = 0; + long maxTableSize = 0; + long initTableSize = 0; + + maxTableSize = (long) MaxTrackedTasksPerNode; + initTableSize = maxTableSize / 8; + + /* + * Allocate the control structure for the hash table that maps unique task + * identifiers (uint64:uint32) to general task information, as well as the + * parameters needed to run the task. + */ + memset(&info, 0, sizeof(info)); + info.keysize = sizeof(uint64) + sizeof(uint32); + info.entrysize = sizeof(WorkerTask); + info.hash = tag_hash; + hashFlags = (HASH_ELEM | HASH_FUNCTION); + + /* + * Currently the lock isn't required because allocation only happens at + * startup in postmaster, but it doesn't hurt, and makes things more + * consistent with other extensions. + */ + LWLockAcquire(AddinShmemInitLock, LW_EXCLUSIVE); + + /* allocate struct containing task tracker related shared state */ + WorkerTasksSharedState = (WorkerTasksSharedStateData *) + ShmemInitStruct("Worker Task Control", + sizeof(WorkerTasksSharedStateData), + &alreadyInitialized); + + if (!alreadyInitialized) + { + /* allocate lwlock protecting the task tracker hash table */ + WorkerTasksSharedState->taskHashLock = LWLockAssign(); + } + + /* allocate hash table */ + WorkerTasksSharedState->taskHash = + ShmemInitHash("Worker Task Hash", + initTableSize, maxTableSize, + &info, hashFlags); + + LWLockRelease(AddinShmemInitLock); + + Assert(WorkerTasksSharedState->taskHash != NULL); + Assert(WorkerTasksSharedState->taskHashLock != NULL); + + if (prev_shmem_startup_hook != NULL) + { + prev_shmem_startup_hook(); + } +} + +/* ------------------------------------------------------------ + * Task scheduling and management functions follow + * ------------------------------------------------------------ + */ + +/* + * SchedulableTaskList calculates the number of tasks to schedule at this given + * moment, and creates a deep-copied list containing that many tasks. The tasks + * in the list are sorted according to a priority criteria, currently the task's + * assignment time. Note that this function expects the caller to hold a read + * lock over the shared hash. + */ +static List * +SchedulableTaskList(HTAB *WorkerTasksHash) +{ + List *schedulableTaskList = NIL; + WorkerTask *schedulableTaskQueue = NULL; + uint32 runningTaskCount = 0; + uint32 schedulableTaskCount = 0; + uint32 tasksToScheduleCount = 0; + uint32 queueIndex = 0; + + runningTaskCount = CountTasksMatchingCriteria(WorkerTasksHash, &RunningTask); + if (runningTaskCount >= MaxRunningTasksPerNode) + { + return NIL; /* we already have enough tasks running */ + } + + schedulableTaskCount = CountTasksMatchingCriteria(WorkerTasksHash, &SchedulableTask); + if (schedulableTaskCount == 0) + { + return NIL; /* we do not have any new tasks to schedule */ + } + + tasksToScheduleCount = MaxRunningTasksPerNode - runningTaskCount; + if (tasksToScheduleCount > schedulableTaskCount) + { + tasksToScheduleCount = schedulableTaskCount; + } + + /* get all schedulable tasks ordered according to a priority criteria */ + schedulableTaskQueue = SchedulableTaskPriorityQueue(WorkerTasksHash); + + for (queueIndex = 0; queueIndex < tasksToScheduleCount; queueIndex++) + { + WorkerTask *schedulableTask = (WorkerTask *) palloc0(sizeof(WorkerTask)); + schedulableTask->jobId = schedulableTaskQueue[queueIndex].jobId; + schedulableTask->taskId = schedulableTaskQueue[queueIndex].taskId; + + schedulableTaskList = lappend(schedulableTaskList, schedulableTask); + } + + /* free priority queue */ + pfree(schedulableTaskQueue); + + return schedulableTaskList; +} + + +/* + * SchedulableTaskPriorityQueue allocates an array containing all schedulable + * tasks in the shared hash, orders these tasks according to a sorting criteria, + * and returns the sorted array. + */ +static WorkerTask * +SchedulableTaskPriorityQueue(HTAB *WorkerTasksHash) +{ + HASH_SEQ_STATUS status; + WorkerTask *currentTask = NULL; + WorkerTask *priorityQueue = NULL; + uint32 queueSize = 0; + uint32 queueIndex = 0; + + /* our priority queue size equals to the number of schedulable tasks */ + queueSize = CountTasksMatchingCriteria(WorkerTasksHash, &SchedulableTask); + if (queueSize == 0) + { + return NULL; + } + + /* allocate an array of tasks for our priority queue */ + priorityQueue = (WorkerTask *) palloc0(sizeof(WorkerTask) * queueSize); + + /* copy tasks in the shared hash to the priority queue */ + hash_seq_init(&status, WorkerTasksHash); + + currentTask = (WorkerTask *) hash_seq_search(&status); + while (currentTask != NULL) + { + if (SchedulableTask(currentTask)) + { + /* tasks in the priority queue only need the first three fields */ + priorityQueue[queueIndex].jobId = currentTask->jobId; + priorityQueue[queueIndex].taskId = currentTask->taskId; + priorityQueue[queueIndex].assignedAt = currentTask->assignedAt; + + queueIndex++; + } + + currentTask = (WorkerTask *) hash_seq_search(&status); + } + + /* now order elements in the queue according to our sorting criterion */ + qsort(priorityQueue, queueSize, sizeof(WorkerTask), CompareTasksByTime); + + return priorityQueue; +} + + +/* Counts the number of tasks that match the given criteria function. */ +static uint32 +CountTasksMatchingCriteria(HTAB *WorkerTasksHash, + bool (*CriteriaFunction) (WorkerTask *)) +{ + HASH_SEQ_STATUS status; + WorkerTask *currentTask = NULL; + uint32 taskCount = 0; + + hash_seq_init(&status, WorkerTasksHash); + + currentTask = (WorkerTask *) hash_seq_search(&status); + while (currentTask != NULL) + { + bool matchesCriteria = (*CriteriaFunction) (currentTask); + if (matchesCriteria) + { + taskCount++; + } + + currentTask = (WorkerTask *) hash_seq_search(&status); + } + + return taskCount; +} + + +/* Checks if the worker task is running. */ +static bool +RunningTask(WorkerTask *workerTask) +{ + TaskStatus currentStatus = workerTask->taskStatus; + if (currentStatus == TASK_RUNNING) + { + return true; + } + + return false; +} + + +/* Checks if the worker task can be scheduled to run. */ +static bool +SchedulableTask(WorkerTask *workerTask) +{ + TaskStatus currentStatus = workerTask->taskStatus; + if (currentStatus == TASK_ASSIGNED) + { + return true; + } + + return false; +} + + +/* Comparison function to compare two worker tasks by their assignment times. */ +static int +CompareTasksByTime(const void *first, const void *second) +{ + WorkerTask *firstTask = (WorkerTask *) first; + WorkerTask *secondTask = (WorkerTask *) second; + + /* tasks that are assigned earlier have higher priority */ + int timeDiff = firstTask->assignedAt - secondTask->assignedAt; + return timeDiff; +} + + +/* + * ScheduleWorkerTasks takes a list of tasks to schedule, and for each task in + * the list, finds and schedules the corresponding task from the shared hash. + * Note that this function expects the caller to hold an exclusive lock over the + * shared hash. + */ +static void +ScheduleWorkerTasks(HTAB *WorkerTasksHash, List *schedulableTaskList) +{ + ListCell *schedulableTaskCell = NULL; + foreach(schedulableTaskCell, schedulableTaskList) + { + WorkerTask *schedulableTask = (WorkerTask *) lfirst(schedulableTaskCell); + WorkerTask *taskToSchedule = NULL; + void *hashKey = (void *) schedulableTask; + + taskToSchedule = (WorkerTask *) hash_search(WorkerTasksHash, hashKey, + HASH_FIND, NULL); + + /* if task is null, the shared hash is in an incosistent state */ + if (taskToSchedule == NULL) + { + ereport(ERROR, (errmsg("could not find the worker task to schedule"), + errdetail("Task jobId: " UINT64_FORMAT " and taskId: %u", + schedulableTask->jobId, schedulableTask->taskId))); + } + + /* + * After determining the set of tasks to schedule, we release the hash's + * shared lock for a short time period. We then re-acquire the lock in + * exclusive mode. We therefore need to check if this task has been + * canceled in the meantime. + */ + if (taskToSchedule->taskStatus != TASK_CANCEL_REQUESTED) + { + Assert(SchedulableTask(taskToSchedule)); + + taskToSchedule->taskStatus = TASK_SCHEDULED; + } + else + { + ereport(INFO, (errmsg("the worker task to schedule has been canceled"), + errdetail("Task jobId: " UINT64_FORMAT " and taskId: %u", + schedulableTask->jobId, schedulableTask->taskId))); + } + } +} + + +/* Manages the scheduling and execution of all tasks in the shared hash. */ +static void +ManageWorkerTasksHash(HTAB *WorkerTasksHash) +{ + HASH_SEQ_STATUS status; + List *schedulableTaskList = NIL; + WorkerTask *currentTask = NULL; + + /* ask the scheduler if we have new tasks to schedule */ + LWLockAcquire(WorkerTasksSharedState->taskHashLock, LW_SHARED); + schedulableTaskList = SchedulableTaskList(WorkerTasksHash); + LWLockRelease(WorkerTasksSharedState->taskHashLock); + + LWLockAcquire(WorkerTasksSharedState->taskHashLock, LW_EXCLUSIVE); + + /* schedule new tasks if we have any */ + if (schedulableTaskList != NIL) + { + ScheduleWorkerTasks(WorkerTasksHash, schedulableTaskList); + list_free_deep(schedulableTaskList); + } + + /* now iterate over all tasks, and manage them */ + hash_seq_init(&status, WorkerTasksHash); + + currentTask = (WorkerTask *) hash_seq_search(&status); + while (currentTask != NULL) + { + ManageWorkerTask(currentTask, WorkerTasksHash); + + /* + * Typically, we delete worker tasks in the task tracker protocol + * process. This task however was canceled mid-query, and the protocol + * process asked us to remove it from the shared hash. + */ + if (currentTask->taskStatus == TASK_TO_REMOVE) + { + RemoveWorkerTask(currentTask, WorkerTasksHash); + } + + currentTask = (WorkerTask *) hash_seq_search(&status); + } + + LWLockRelease(WorkerTasksSharedState->taskHashLock); +} + + +/* + * ManageWorkerTask manages the execution of the worker task. More specifically, + * the function connects to a local backend, sends the query associated with the + * task, and oversees the query's execution. Note that this function expects the + * caller to hold an exclusive lock over the shared hash. + */ +static void +ManageWorkerTask(WorkerTask *workerTask, HTAB *WorkerTasksHash) +{ + switch (workerTask->taskStatus) + { + case TASK_ASSIGNED: + { + break; /* nothing to do until the task gets scheduled */ + } + + case TASK_SCHEDULED: + { + /* create the job output directory if it does not exist */ + CreateJobDirectoryIfNotExists(workerTask->jobId); + + /* the task is ready to run; connect to local backend */ + workerTask->connectionId = ConnectToLocalBackend(workerTask->databaseName); + + if (workerTask->connectionId != INVALID_CONNECTION_ID) + { + bool taskSent = MultiClientSendQuery(workerTask->connectionId, + workerTask->taskCallString); + if (taskSent) + { + workerTask->taskStatus = TASK_RUNNING; + } + else + { + workerTask->taskStatus = TASK_FAILED; + workerTask->failureCount++; + + MultiClientDisconnect(workerTask->connectionId); + workerTask->connectionId = INVALID_CONNECTION_ID; + } + } + else + { + workerTask->taskStatus = TASK_FAILED; + workerTask->failureCount++; + } + + break; + } + + case TASK_RUNNING: + { + int32 connectionId = workerTask->connectionId; + ResultStatus resultStatus = MultiClientResultStatus(connectionId); + + /* check if query results are ready, in progress, or unavailable */ + if (resultStatus == CLIENT_RESULT_READY) + { + QueryStatus queryStatus = MultiClientQueryStatus(connectionId); + if (queryStatus == CLIENT_QUERY_DONE) + { + workerTask->taskStatus = TASK_SUCCEEDED; + } + else if (queryStatus == CLIENT_QUERY_FAILED) + { + workerTask->taskStatus = TASK_FAILED; + workerTask->failureCount++; + } + else + { + ereport(FATAL, (errmsg("invalid query status: %d", queryStatus))); + } + } + else if (resultStatus == CLIENT_RESULT_BUSY) + { + workerTask->taskStatus = TASK_RUNNING; + } + else if (resultStatus == CLIENT_RESULT_UNAVAILABLE) + { + workerTask->taskStatus = TASK_FAILED; + workerTask->failureCount++; + } + + /* clean up the connection if we are done with the task */ + if (resultStatus != CLIENT_RESULT_BUSY) + { + MultiClientDisconnect(workerTask->connectionId); + workerTask->connectionId = INVALID_CONNECTION_ID; + } + + break; + } + + case TASK_FAILED: + { + if (workerTask->failureCount < MAX_TASK_FAILURE_COUNT) + { + workerTask->taskStatus = TASK_ASSIGNED; + } + else + { + workerTask->taskStatus = TASK_PERMANENTLY_FAILED; + } + + break; + } + + case TASK_PERMANENTLY_FAILED: + case TASK_SUCCEEDED: + { + break; + } + + case TASK_CANCEL_REQUESTED: + { + /* + * If this task is responsible for cleaning up the shared hash, we + * give the task more time instead of canceling it. The reason this + * task is marked for cancellation is that its file descriptor needs + * to be reclaimed after the clean up completes. + */ + if (workerTask->taskId == JOB_CLEANUP_TASK_ID) + { + workerTask->taskStatus = TASK_CANCELED; + break; + } + + if (workerTask->connectionId != INVALID_CONNECTION_ID) + { + int32 connectionId = workerTask->connectionId; + + ResultStatus status = MultiClientResultStatus(connectionId); + if (status == CLIENT_RESULT_BUSY) + { + MultiClientCancel(connectionId); + } + } + + /* give the backend some time to flush its response */ + workerTask->taskStatus = TASK_CANCELED; + break; + } + + case TASK_CANCELED: + { + if (workerTask->connectionId != INVALID_CONNECTION_ID) + { + MultiClientDisconnect(workerTask->connectionId); + workerTask->connectionId = INVALID_CONNECTION_ID; + } + + workerTask->taskStatus = TASK_TO_REMOVE; + break; + } + + case TASK_TO_REMOVE: + default: + { + /* we fatal here to avoid leaking client-side resources */ + ereport(FATAL, (errmsg("invalid task status: %d", workerTask->taskStatus))); + break; + } + } + + Assert(workerTask->failureCount <= MAX_TASK_FAILURE_COUNT); +} + + +/* Wrapper function to remove the worker task from the shared hash. */ +static void +RemoveWorkerTask(WorkerTask *workerTask, HTAB *WorkerTasksHash) +{ + void *hashKey = (void *) workerTask; + + WorkerTask *taskRemoved = hash_search(WorkerTasksHash, hashKey, HASH_REMOVE, NULL); + if (taskRemoved == NULL) + { + ereport(FATAL, (errmsg("worker task hash corrupted"))); + } +} + + +/* Wrapper function to create the job directory if it does not already exist. */ +static void +CreateJobDirectoryIfNotExists(uint64 jobId) +{ + StringInfo jobDirectoryName = JobDirectoryName(jobId); + + bool jobDirectoryExists = DirectoryExists(jobDirectoryName); + if (!jobDirectoryExists) + { + CreateDirectory(jobDirectoryName); + } + + FreeStringInfo(jobDirectoryName); +} + + +/* Wrapper function to inititate connection to local backend. */ +static int32 +ConnectToLocalBackend(const char *databaseName) +{ + const char *nodeName = LOCAL_HOST_NAME; + const uint32 nodePort = PostPortNumber; + + /* + * Our client library currently only handles TCP sockets. We therefore do + * not use Unix domain sockets here. + */ + int32 connectionId = MultiClientConnect(nodeName, nodePort, databaseName); + + return connectionId; +} diff --git a/src/backend/distributed/worker/task_tracker_protocol.c b/src/backend/distributed/worker/task_tracker_protocol.c new file mode 100644 index 000000000..84115f441 --- /dev/null +++ b/src/backend/distributed/worker/task_tracker_protocol.c @@ -0,0 +1,387 @@ +/*------------------------------------------------------------------------- + * + * task_tracker_protocol.c + * + * The task tracker background process runs on every worker node. The following + * routines allow for the master node to assign tasks to the task tracker, check + * these tasks' statuses, and remove these tasks when they are no longer needed. + * + * Copyright (c) 2012, Citus Data, Inc. + * + * $Id$ + * + *------------------------------------------------------------------------- + */ + +#include "postgres.h" +#include "funcapi.h" +#include "miscadmin.h" + +#include + +#include "access/xact.h" +#include "commands/dbcommands.h" +#include "commands/schemacmds.h" +#include "distributed/multi_client_executor.h" +#include "distributed/multi_server_executor.h" +#include "distributed/resource_lock.h" +#include "distributed/task_tracker.h" +#include "distributed/task_tracker_protocol.h" +#include "distributed/worker_protocol.h" +#include "storage/lwlock.h" +#include "storage/pmsignal.h" +#include "utils/builtins.h" + + +/* Local functions forward declarations */ +static bool TaskTrackerRunning(void); +static void CreateJobSchema(StringInfo schemaName); +static void CreateTask(uint64 jobId, uint32 taskId, char *taskCallString); +static void UpdateTask(WorkerTask *workerTask, char *taskCallString); +static void CleanupTask(WorkerTask *workerTask); + + +/* exports for SQL callable functions */ +PG_FUNCTION_INFO_V1(task_tracker_assign_task); +PG_FUNCTION_INFO_V1(task_tracker_task_status); +PG_FUNCTION_INFO_V1(task_tracker_cleanup_job); + + +/* + * task_tracker_assign_task creates a new task in the shared hash or updates an + * already existing task. The function also creates a schema for the job if it + * doesn't already exist. + */ +Datum +task_tracker_assign_task(PG_FUNCTION_ARGS) +{ + uint64 jobId = PG_GETARG_INT64(0); + uint32 taskId = PG_GETARG_UINT32(1); + text *taskCallStringText = PG_GETARG_TEXT_P(2); + + StringInfo jobSchemaName = JobSchemaName(jobId); + bool schemaExists = false; + + WorkerTask *workerTask = NULL; + char *taskCallString = text_to_cstring(taskCallStringText); + uint32 taskCallStringLength = strlen(taskCallString); + + /* check that we have a running task tracker on this host */ + bool taskTrackerRunning = TaskTrackerRunning(); + if (!taskTrackerRunning) + { + ereport(ERROR, (errcode(ERRCODE_CANNOT_CONNECT_NOW), + errmsg("the task tracker has been disabled or shut down"))); + } + + /* check that we have enough space in our shared hash for this string */ + if (taskCallStringLength >= TASK_CALL_STRING_SIZE) + { + ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("task call string exceeds maximum assignable length"))); + } + + /* + * If the schema does not exist, we create it. However, the schema does not + * become visible to other processes until the transaction commits, and we + * therefore do not release the resource lock in this case. Otherwise, the + * schema is already visible, and we immediately release the resource lock. + */ + LockJobResource(jobId, AccessExclusiveLock); + schemaExists = JobSchemaExists(jobSchemaName); + if (!schemaExists) + { + /* lock gets automatically released upon return from this function */ + CreateJobSchema(jobSchemaName); + } + else + { + UnlockJobResource(jobId, AccessExclusiveLock); + } + + LWLockAcquire(WorkerTasksSharedState->taskHashLock, LW_EXCLUSIVE); + + /* check if we already have the task in our shared hash */ + workerTask = WorkerTasksHashFind(jobId, taskId); + if (workerTask == NULL) + { + CreateTask(jobId, taskId, taskCallString); + } + else + { + UpdateTask(workerTask, taskCallString); + } + + LWLockRelease(WorkerTasksSharedState->taskHashLock); + + PG_RETURN_VOID(); +} + + +/* Returns the task status of an already existing task. */ +Datum +task_tracker_task_status(PG_FUNCTION_ARGS) +{ + uint64 jobId = PG_GETARG_INT64(0); + uint32 taskId = PG_GETARG_UINT32(1); + + WorkerTask *workerTask = NULL; + uint32 taskStatus = 0; + + bool taskTrackerRunning = TaskTrackerRunning(); + if (taskTrackerRunning) + { + LWLockAcquire(WorkerTasksSharedState->taskHashLock, LW_SHARED); + + workerTask = WorkerTasksHashFind(jobId, taskId); + if (workerTask == NULL) + { + ereport(ERROR, (errmsg("could not find the worker task"), + errdetail("Task jobId: " UINT64_FORMAT " and taskId: %u", + jobId, taskId))); + } + + taskStatus = (uint32) workerTask->taskStatus; + + LWLockRelease(WorkerTasksSharedState->taskHashLock); + } + else + { + ereport(ERROR, (errcode(ERRCODE_CANNOT_CONNECT_NOW), + errmsg("the task tracker has been disabled or shut down"))); + } + + PG_RETURN_UINT32(taskStatus); +} + + +/* + * task_tracker_cleanup_job finds all tasks for the given job, and cleans up + * files, connections, and shared hash enties associated with these tasks. + */ +Datum +task_tracker_cleanup_job(PG_FUNCTION_ARGS) +{ + uint64 jobId = PG_GETARG_INT64(0); + + HASH_SEQ_STATUS status; + WorkerTask *currentTask = NULL; + StringInfo jobDirectoryName = NULL; + StringInfo jobSchemaName = NULL; + + /* + * We first clean up any open connections, and remove tasks belonging to + * this job from the shared hash. + */ + LWLockAcquire(WorkerTasksSharedState->taskHashLock, LW_EXCLUSIVE); + + hash_seq_init(&status, WorkerTasksSharedState->taskHash); + + currentTask = (WorkerTask *) hash_seq_search(&status); + while (currentTask != NULL) + { + if (currentTask->jobId == jobId) + { + CleanupTask(currentTask); + } + + currentTask = (WorkerTask *) hash_seq_search(&status); + } + + LWLockRelease(WorkerTasksSharedState->taskHashLock); + + /* + * We then delete the job directory and schema, if they exist. This cleans + * up all intermediate files and tables allocated for the job. Note that the + * schema drop call can block if another process is creating the schema or + * writing to a table within the schema. + */ + jobDirectoryName = JobDirectoryName(jobId); + RemoveDirectory(jobDirectoryName); + + LockJobResource(jobId, AccessExclusiveLock); + jobSchemaName = JobSchemaName(jobId); + RemoveJobSchema(jobSchemaName); + UnlockJobResource(jobId, AccessExclusiveLock); + + PG_RETURN_VOID(); +} + + +/* + * TaskTrackerRunning checks if the task tracker process is running. To do this, + * the function checks if the task tracker is configured to start up, and infers + * from shared memory that the tracker hasn't received a shut down request. + */ +static bool +TaskTrackerRunning(void) +{ + WorkerTask *workerTask = NULL; + bool postmasterAlive = true; + bool taskTrackerRunning = true; + + /* if postmaster shut down, infer task tracker shut down from it */ + postmasterAlive = PostmasterIsAlive(); + if (!postmasterAlive) + { + return false; + } + + /* + * When the task tracker receives a termination signal, it inserts a special + * marker task to the shared hash. We need to look up this marker task since + * the postmaster doesn't send a terminate signal to running backends. + */ + LWLockAcquire(WorkerTasksSharedState->taskHashLock, LW_SHARED); + + workerTask = WorkerTasksHashFind(RESERVED_JOB_ID, SHUTDOWN_MARKER_TASK_ID); + if (workerTask != NULL) + { + taskTrackerRunning = false; + } + + LWLockRelease(WorkerTasksSharedState->taskHashLock); + + return taskTrackerRunning; +} + + +/* + * CreateJobSchema creates a job schema with the given schema name. Note that + * this function ensures that our pg_ prefixed schema names can be created. + * Further note that the created schema does not become visible to other + * processes until the transaction commits. + */ +static void +CreateJobSchema(StringInfo schemaName) +{ + const char *queryString = NULL; + bool oldAllowSystemTableMods = false; + + CreateSchemaStmt *createSchemaStmt = makeNode(CreateSchemaStmt); + createSchemaStmt->schemaname = schemaName->data; +#if (PG_VERSION_NUM >= 90500) + createSchemaStmt->authrole = NULL; +#else + createSchemaStmt->authid = NULL; +#endif + createSchemaStmt->schemaElts = NIL; + + /* allow schema names that start with pg_ */ + oldAllowSystemTableMods = allowSystemTableMods; + allowSystemTableMods = true; + + CreateSchemaCommand(createSchemaStmt, queryString); + CommandCounterIncrement(); + allowSystemTableMods = oldAllowSystemTableMods; +} + + +/* + * CreateTask creates a new task in shared hash, initializes the task, and sets + * the task to assigned state. Note that this function expects the caller to + * hold an exclusive lock over the shared hash. + */ +static void +CreateTask(uint64 jobId, uint32 taskId, char *taskCallString) +{ + WorkerTask *workerTask = NULL; + uint32 assignmentTime = 0; + char *databaseName = get_database_name(MyDatabaseId); + + /* increase task priority for cleanup tasks */ + assignmentTime = (uint32) time(NULL); + if (taskId == JOB_CLEANUP_TASK_ID) + { + assignmentTime = HIGH_PRIORITY_TASK_TIME; + } + + /* enter the worker task into shared hash and initialize the task */ + workerTask = WorkerTasksHashEnter(jobId, taskId); + workerTask->assignedAt = assignmentTime; + strncpy(workerTask->taskCallString, taskCallString, TASK_CALL_STRING_SIZE); + + workerTask->taskStatus = TASK_ASSIGNED; + workerTask->connectionId = INVALID_CONNECTION_ID; + workerTask->failureCount = 0; + strncpy(workerTask->databaseName, databaseName, NAMEDATALEN); +} + + +/* + * UpdateTask updates the call string text for an already existing task. Note + * that this function expects the caller to hold an exclusive lock over the + * shared hash. + */ +static void +UpdateTask(WorkerTask *workerTask, char *taskCallString) +{ + TaskStatus taskStatus = TASK_STATUS_INVALID_FIRST; + + taskStatus = workerTask->taskStatus; + Assert(taskStatus != TASK_STATUS_INVALID_FIRST); + + /* + * 1. If the task has succeeded or has been canceled, we don't do anything. + * 2. If the task has permanently failed, we update the task call string, + * reset the failure count, and change the task's status to schedulable. + * 3. If the task is in conduit, we update the task call string, and reset + * the failure count. + */ + if (taskStatus == TASK_SUCCEEDED || taskStatus == TASK_CANCEL_REQUESTED || + taskStatus == TASK_CANCELED) + { + ; /* nothing to do */ + } + else if (taskStatus == TASK_PERMANENTLY_FAILED) + { + strncpy(workerTask->taskCallString, taskCallString, TASK_CALL_STRING_SIZE); + workerTask->failureCount = 0; + workerTask->taskStatus = TASK_ASSIGNED; + } + else + { + strncpy(workerTask->taskCallString, taskCallString, TASK_CALL_STRING_SIZE); + workerTask->failureCount = 0; + } +} + + +/* Cleans up connection and shared hash entry associated with the given task. */ +static void +CleanupTask(WorkerTask *workerTask) +{ + WorkerTask *taskRemoved = NULL; + void *hashKey = (void *) workerTask; + + /* + * If the connection is still valid, the master node decided to terminate + * the task prematurely. This can happen when the user wants to cancel the + * query, or when a speculatively executed task finishes elsewhere and the + * query completes. + */ + if (workerTask->connectionId != INVALID_CONNECTION_ID) + { + /* + * The task tracker process owns the connections to local backends, and + * we cannot interefere with those connections from another process. We + * therefore ask the task tracker to clean up the connection and to + * remove the task from the shared hash. Note that one of the cleaned up + * tasks will always be the clean-up task itself. + */ + ereport(DEBUG3, (errmsg("requesting cancel for worker task"), + errdetail("Task jobId: " UINT64_FORMAT " and taskId: %u", + workerTask->jobId, workerTask->taskId))); + + workerTask->taskStatus = TASK_CANCEL_REQUESTED; + return; + } + + /* remove the task from the shared hash */ + taskRemoved = hash_search(WorkerTasksSharedState->taskHash, hashKey, HASH_REMOVE, + NULL); + if (taskRemoved == NULL) + { + ereport(FATAL, (errmsg("worker task hash corrupted"))); + } +} diff --git a/src/backend/distributed/worker/worker_data_fetch_protocol.c b/src/backend/distributed/worker/worker_data_fetch_protocol.c new file mode 100644 index 000000000..0e5b68a1d --- /dev/null +++ b/src/backend/distributed/worker/worker_data_fetch_protocol.c @@ -0,0 +1,1076 @@ +/*------------------------------------------------------------------------- + * + * worker_data_fetch_protocol.c + * + * Routines for fetching remote resources from other nodes to this worker node, + * and materializing these resources on this node if necessary. + * + * Copyright (c) 2012, Citus Data, Inc. + * + * $Id$ + * + *------------------------------------------------------------------------- + */ + +#include "postgres.h" +#include "funcapi.h" +#include "miscadmin.h" +#include +#include + +#include "access/xact.h" +#include "catalog/dependency.h" +#include "catalog/namespace.h" +#include "commands/copy.h" +#include "commands/dbcommands.h" +#include "distributed/master_protocol.h" +#include "distributed/multi_client_executor.h" +#include "distributed/multi_logical_optimizer.h" +#include "distributed/multi_server_executor.h" +#include "distributed/relay_utility.h" +#include "distributed/resource_lock.h" +#include "distributed/task_tracker.h" +#include "distributed/worker_protocol.h" +#include "nodes/makefuncs.h" +#include "storage/lmgr.h" +#include "tcop/tcopprot.h" +#include "tcop/utility.h" +#include "utils/builtins.h" +#include "utils/lsyscache.h" + + +/* Config variable managed via guc.c */ +bool ExpireCachedShards = false; + + +/* Local functions forward declarations */ +static void FetchRegularFile(const char *nodeName, uint32 nodePort, + StringInfo remoteFilename, StringInfo localFilename); +static bool ReceiveRegularFile(const char *nodeName, uint32 nodePort, + StringInfo transmitCommand, StringInfo filePath); +static void ReceiveResourceCleanup(int32 connectionId, const char *filename, + int32 fileDescriptor); +static void DeleteFile(const char *filename); +static void FetchTableCommon(text *tableName, uint64 remoteTableSize, + ArrayType *nodeNameObject, ArrayType *nodePortObject, + bool (*FetchTableFunction) (const char *, uint32, StringInfo)); +static uint64 LocalTableSize(Oid relationId); +static uint64 ExtractShardId(StringInfo tableName); +static bool FetchRegularTable(const char *nodeName, uint32 nodePort, StringInfo tableName); +static bool FetchForeignTable(const char *nodeName, uint32 nodePort, StringInfo tableName); +static List * TableDDLCommandList(const char *nodeName, uint32 nodePort, + StringInfo tableName); +static StringInfo ForeignFilePath(const char *nodeName, uint32 nodePort, + StringInfo tableName); +static bool check_log_statement(List *stmt_list); + + +/* exports for SQL callable functions */ +PG_FUNCTION_INFO_V1(worker_fetch_partition_file); +PG_FUNCTION_INFO_V1(worker_fetch_query_results_file); +PG_FUNCTION_INFO_V1(worker_apply_shard_ddl_command); +PG_FUNCTION_INFO_V1(worker_fetch_regular_table); +PG_FUNCTION_INFO_V1(worker_fetch_foreign_file); +PG_FUNCTION_INFO_V1(worker_append_table_to_shard); + + +/* + * worker_fetch_partition_file fetches a partition file from the remote node. + * The function assumes an upstream compute task depends on this partition file, + * and therefore directly fetches the file into the upstream task's directory. + */ +Datum +worker_fetch_partition_file(PG_FUNCTION_ARGS) +{ + uint64 jobId = PG_GETARG_INT64(0); + uint32 partitionTaskId = PG_GETARG_UINT32(1); + uint32 partitionFileId = PG_GETARG_UINT32(2); + uint32 upstreamTaskId = PG_GETARG_UINT32(3); + text *nodeNameText = PG_GETARG_TEXT_P(4); + uint32 nodePort = PG_GETARG_UINT32(5); + char *nodeName = NULL; + + /* remote filename is // */ + StringInfo remoteDirectoryName = TaskDirectoryName(jobId, partitionTaskId); + StringInfo remoteFilename = PartitionFilename(remoteDirectoryName, partitionFileId); + + /* local filename is // */ + StringInfo taskDirectoryName = TaskDirectoryName(jobId, upstreamTaskId); + StringInfo taskFilename = TaskFilename(taskDirectoryName, partitionTaskId); + + /* + * If we are the first function to fetch a file for the upstream task, the + * task directory does not exist. We then lock and create the directory. + */ + bool taskDirectoryExists = DirectoryExists(taskDirectoryName); + if (!taskDirectoryExists) + { + InitTaskDirectory(jobId, upstreamTaskId); + } + + nodeName = text_to_cstring(nodeNameText); + FetchRegularFile(nodeName, nodePort, remoteFilename, taskFilename); + + PG_RETURN_VOID(); +} + + +/* + * worker_fetch_query_results_file fetches a query results file from the remote + * node. The function assumes an upstream compute task depends on this query + * results file, and therefore directly fetches the file into the upstream + * task's directory. + */ +Datum +worker_fetch_query_results_file(PG_FUNCTION_ARGS) +{ + uint64 jobId = PG_GETARG_INT64(0); + uint32 queryTaskId = PG_GETARG_UINT32(1); + uint32 upstreamTaskId = PG_GETARG_UINT32(2); + text *nodeNameText = PG_GETARG_TEXT_P(3); + uint32 nodePort = PG_GETARG_UINT32(4); + char *nodeName = NULL; + + /* remote filename is / */ + StringInfo remoteDirectoryName = JobDirectoryName(jobId); + StringInfo remoteFilename = TaskFilename(remoteDirectoryName, queryTaskId); + + /* local filename is // */ + StringInfo taskDirectoryName = TaskDirectoryName(jobId, upstreamTaskId); + StringInfo taskFilename = TaskFilename(taskDirectoryName, queryTaskId); + + /* + * If we are the first function to fetch a file for the upstream task, the + * task directory does not exist. We then lock and create the directory. + */ + bool taskDirectoryExists = DirectoryExists(taskDirectoryName); + if (!taskDirectoryExists) + { + InitTaskDirectory(jobId, upstreamTaskId); + } + + nodeName = text_to_cstring(nodeNameText); + FetchRegularFile(nodeName, nodePort, remoteFilename, taskFilename); + + PG_RETURN_VOID(); +} + + +/* Constructs a standardized task file path for given directory and task id. */ +StringInfo +TaskFilename(StringInfo directoryName, uint32 taskId) +{ + StringInfo taskFilename = makeStringInfo(); + appendStringInfo(taskFilename, "%s/%s%0*u", + directoryName->data, + TASK_FILE_PREFIX, MIN_TASK_FILENAME_WIDTH, taskId); + + return taskFilename; +} + + +/* Helper function to transfer the remote file in an idempotent manner. */ +static void +FetchRegularFile(const char *nodeName, uint32 nodePort, + StringInfo remoteFilename, StringInfo localFilename) +{ + StringInfo attemptFilename = NULL; + StringInfo transmitCommand = NULL; + uint32 randomId = (uint32) random(); + bool received = false; + int renamed = 0; + + /* + * We create an attempt file to signal that the file is still in transit. We + * further append a random id to the filename to handle the unexpected case + * of another process concurrently fetching the same file. + */ + attemptFilename = makeStringInfo(); + appendStringInfo(attemptFilename, "%s_%0*u%s", localFilename->data, + MIN_TASK_FILENAME_WIDTH, randomId, ATTEMPT_FILE_SUFFIX); + + transmitCommand = makeStringInfo(); + appendStringInfo(transmitCommand, TRANSMIT_REGULAR_COMMAND, remoteFilename->data); + + received = ReceiveRegularFile(nodeName, nodePort, transmitCommand, attemptFilename); + if (!received) + { + ereport(ERROR, (errmsg("could not receive file \"%s\" from %s:%u", + remoteFilename->data, nodeName, nodePort))); + } + + /* atomically rename the attempt file */ + renamed = rename(attemptFilename->data, localFilename->data); + if (renamed != 0) + { + ereport(ERROR, (errcode_for_file_access(), + errmsg("could not rename file \"%s\" to \"%s\": %m", + attemptFilename->data, localFilename->data))); + } +} + + +/* + * ReceiveRegularFile creates a local file at the given file path, and connects + * to remote database that has the given node name and port number. The function + * then issues the given transmit command using client-side logic (libpq), reads + * the remote file's contents, and appends these contents to the local file. On + * success, the function returns success; on failure, it cleans up all resources + * and returns false. + */ +static bool +ReceiveRegularFile(const char *nodeName, uint32 nodePort, + StringInfo transmitCommand, StringInfo filePath) +{ + int32 fileDescriptor = -1; + char filename[MAXPGPATH]; + int closed = -1; + const int fileFlags = (O_APPEND | O_CREAT | O_RDWR | O_TRUNC | PG_BINARY); + const int fileMode = (S_IRUSR | S_IWUSR); + + QueryStatus queryStatus = CLIENT_INVALID_QUERY; + int32 connectionId = INVALID_CONNECTION_ID; + char *nodeDatabase = NULL; + bool querySent = false; + bool queryReady = false; + bool copyDone = false; + + /* create local file to append remote data to */ + snprintf(filename, MAXPGPATH, "%s", filePath->data); + + fileDescriptor = BasicOpenFile(filename, fileFlags, fileMode); + if (fileDescriptor < 0) + { + ereport(WARNING, (errcode_for_file_access(), + errmsg("could not open file \"%s\": %m", filePath->data))); + + return false; + } + + /* we use the same database name on the master and worker nodes */ + nodeDatabase = get_database_name(MyDatabaseId); + + /* connect to remote node */ + connectionId = MultiClientConnect(nodeName, nodePort, nodeDatabase); + if (connectionId == INVALID_CONNECTION_ID) + { + ReceiveResourceCleanup(connectionId, filename, fileDescriptor); + + return false; + } + + /* send request to remote node to start transmitting data */ + querySent = MultiClientSendQuery(connectionId, transmitCommand->data); + if (!querySent) + { + ReceiveResourceCleanup(connectionId, filename, fileDescriptor); + + return false; + } + + /* loop until the remote node acknowledges our transmit request */ + while (!queryReady) + { + ResultStatus resultStatus = MultiClientResultStatus(connectionId); + if (resultStatus == CLIENT_RESULT_READY) + { + queryReady = true; + } + else if (resultStatus == CLIENT_RESULT_BUSY) + { + /* remote node did not respond; wait for longer */ + long sleepIntervalPerCycle = RemoteTaskCheckInterval * 1000L; + pg_usleep(sleepIntervalPerCycle); + } + else + { + ReceiveResourceCleanup(connectionId, filename, fileDescriptor); + + return false; + } + } + + /* check query response is as expected */ + queryStatus = MultiClientQueryStatus(connectionId); + if (queryStatus != CLIENT_QUERY_COPY) + { + ReceiveResourceCleanup(connectionId, filename, fileDescriptor); + + return false; + } + + /* loop until we receive and append all the data from remote node */ + while (!copyDone) + { + CopyStatus copyStatus = MultiClientCopyData(connectionId, fileDescriptor); + if (copyStatus == CLIENT_COPY_DONE) + { + copyDone = true; + } + else if (copyStatus == CLIENT_COPY_MORE) + { + ; /* remote node will continue to send more data */ + } + else + { + ReceiveResourceCleanup(connectionId, filename, fileDescriptor); + + return false; + } + } + + /* we are done executing; release the connection and the file handle */ + MultiClientDisconnect(connectionId); + + closed = close(fileDescriptor); + if (closed < 0) + { + ereport(WARNING, (errcode_for_file_access(), + errmsg("could not close file \"%s\": %m", filename))); + + /* if we failed to close file, try to delete it before erroring out */ + DeleteFile(filename); + + return false; + } + + /* we successfully received the remote file */ + ereport(DEBUG2, (errmsg("received remote file \"%s\"", filename))); + + return true; +} + + +/* + * ReceiveResourceCleanup gets called if an error occurs during file receiving. + * The function closes the connection, and closes and deletes the local file. + */ +static void +ReceiveResourceCleanup(int32 connectionId, const char *filename, int32 fileDescriptor) +{ + if (connectionId != INVALID_CONNECTION_ID) + { + MultiClientDisconnect(connectionId); + } + + if (fileDescriptor != -1) + { + int closed = -1; + int deleted = -1; + + closed = close(fileDescriptor); + if (closed < 0) + { + ereport(WARNING, (errcode_for_file_access(), + errmsg("could not close file \"%s\": %m", filename))); + } + + deleted = unlink(filename); + if (deleted != 0) + { + ereport(WARNING, (errcode_for_file_access(), + errmsg("could not delete file \"%s\": %m", filename))); + } + } +} + + +/* Deletes file with the given filename. */ +static void +DeleteFile(const char *filename) +{ + int deleted = unlink(filename); + if (deleted != 0) + { + ereport(WARNING, (errcode_for_file_access(), + errmsg("could not delete file \"%s\": %m", filename))); + } +} + + +/* + * worker_apply_shard_ddl_command extends table, index, or constraint names in + * the given DDL command. The function then applies this extended DDL command + * against the database. + */ +Datum +worker_apply_shard_ddl_command(PG_FUNCTION_ARGS) +{ + uint64 shardId = PG_GETARG_INT64(0); + text *ddlCommandText = PG_GETARG_TEXT_P(1); + + const char *ddlCommand = text_to_cstring(ddlCommandText); + Node *ddlCommandNode = ParseTreeNode(ddlCommand); + + /* extend names in ddl command and apply extended command */ + RelayEventExtendNames(ddlCommandNode, shardId); + ProcessUtility(ddlCommandNode, ddlCommand, PROCESS_UTILITY_TOPLEVEL, + NULL, None_Receiver, NULL); + + PG_RETURN_VOID(); +} + + +/* + * worker_fetch_regular_table caches the given PostgreSQL table on the local + * node. The function caches this table by trying the given list of node names + * and node ports in sequential order. On success, the function simply returns. + */ +Datum +worker_fetch_regular_table(PG_FUNCTION_ARGS) +{ + text *regularTableName = PG_GETARG_TEXT_P(0); + uint64 generationStamp = PG_GETARG_INT64(1); + ArrayType *nodeNameObject = PG_GETARG_ARRAYTYPE_P(2); + ArrayType *nodePortObject = PG_GETARG_ARRAYTYPE_P(3); + + /* + * Run common logic to fetch the remote table, and use the provided function + * pointer to perform the actual table fetching. + */ + FetchTableCommon(regularTableName, generationStamp, + nodeNameObject, nodePortObject, &FetchRegularTable); + + PG_RETURN_VOID(); +} + + +/* + * worker_fetch_foreign_file caches the given file-backed foreign table on the + * local node. The function caches this table by trying the given list of node + * names and node ports in sequential order. On success, the function returns. + */ +Datum +worker_fetch_foreign_file(PG_FUNCTION_ARGS) +{ + text *foreignTableName = PG_GETARG_TEXT_P(0); + uint64 foreignFileSize = PG_GETARG_INT64(1); + ArrayType *nodeNameObject = PG_GETARG_ARRAYTYPE_P(2); + ArrayType *nodePortObject = PG_GETARG_ARRAYTYPE_P(3); + + /* + * Run common logic to fetch the remote table, and use the provided function + * pointer to perform the actual table fetching. + */ + FetchTableCommon(foreignTableName, foreignFileSize, + nodeNameObject, nodePortObject, &FetchForeignTable); + + PG_RETURN_VOID(); +} + + +/* + * FetchTableCommon executes common logic that wraps around the actual data + * fetching function. This common logic includes ensuring that only one process + * tries to fetch this table at any given time, and that data fetch operations + * are retried in case of node failures. + */ +static void +FetchTableCommon(text *tableNameText, uint64 remoteTableSize, + ArrayType *nodeNameObject, ArrayType *nodePortObject, + bool (*FetchTableFunction) (const char *, uint32, StringInfo)) +{ + StringInfo tableName = NULL; + char *tableNameCString = NULL; + uint64 shardId = INVALID_SHARD_ID; + Oid relationId = InvalidOid; + uint32 nodeIndex = 0; + bool tableFetched = false; + + Datum *nodeNameArray = DeconstructArrayObject(nodeNameObject); + Datum *nodePortArray = DeconstructArrayObject(nodePortObject); + int32 nodeNameCount = ArrayObjectCount(nodeNameObject); + int32 nodePortCount = ArrayObjectCount(nodePortObject); + + /* we should have the same number of node names and port numbers */ + if (nodeNameCount != nodePortCount) + { + ereport(ERROR, (errmsg("node name array size: %d and node port array size: %d" + " do not match", nodeNameCount, nodePortCount))); + } + + tableName = makeStringInfo(); + tableNameCString = text_to_cstring(tableNameText); + appendStringInfoString(tableName, tableNameCString); + + /* + * We lock on the shardId, but do not unlock. When the function returns, and + * the transaction for this function commits, this lock will automatically + * be released. This ensures that concurrent caching commands will see the + * newly created table when they acquire the lock (in read committed mode). + */ + shardId = ExtractShardId(tableName); + LockShardResource(shardId, AccessExclusiveLock); + + /* check if we already fetched the table */ + relationId = RelnameGetRelid(tableName->data); + if (relationId != InvalidOid) + { + uint64 localTableSize = 0; + + if (!ExpireCachedShards) + { + return; + } + + /* + * Check if the cached shard has the same size on disk as it has as on + * the placement (is up to date). + * + * Note 1: performing updates or deletes on the original shard leads to + * inconsistent sizes between different databases in which case the data + * would be fetched every time, or worse, the placement would get into + * a deadlock when it tries to fetch from itself while holding the lock. + * Therefore, this option is disabled by default. + * + * Note 2: when appending data to a shard, the size on disk only + * increases when a new page is added (the next 8kB block). + */ + localTableSize = LocalTableSize(relationId); + + if (remoteTableSize > localTableSize) + { + /* table is not up to date, drop the table */ + ObjectAddress tableObject = {InvalidOid, InvalidOid, 0}; + + tableObject.classId = RelationRelationId; + tableObject.objectId = relationId; + tableObject.objectSubId = 0; + + performDeletion(&tableObject, DROP_RESTRICT, PERFORM_DELETION_INTERNAL); + } + else + { + /* table is up to date */ + return; + } + } + + /* loop until we fetch the table or try all nodes */ + while (!tableFetched && (nodeIndex < nodeNameCount)) + { + Datum nodeNameDatum = nodeNameArray[nodeIndex]; + Datum nodePortDatum = nodePortArray[nodeIndex]; + char *nodeName = TextDatumGetCString(nodeNameDatum); + uint32 nodePort = DatumGetUInt32(nodePortDatum); + + tableFetched = (*FetchTableFunction) (nodeName, nodePort, tableName); + + nodeIndex++; + } + + /* error out if we tried all nodes and could not fetch the table */ + if (!tableFetched) + { + ereport(ERROR, (errmsg("could not fetch relation: \"%s\"", tableName->data))); + } +} + + +/* LocalTableSize returns the size on disk of the given table. */ +static uint64 +LocalTableSize(Oid relationId) +{ + uint64 tableSize = 0; + char relationType = 0; + Datum relationIdDatum = ObjectIdGetDatum(relationId); + + relationType = get_rel_relkind(relationId); + if (relationType == RELKIND_RELATION) + { + Datum tableSizeDatum = DirectFunctionCall1(pg_table_size, relationIdDatum); + + tableSize = DatumGetInt64(tableSizeDatum); + } + else if (relationType == RELKIND_FOREIGN_TABLE) + { + bool cstoreTable = CStoreTable(relationId); + if (cstoreTable) + { + const int tableSizeArgumentCount = 1; + Oid tableSizeFunctionOid = FunctionOid(CSTORE_TABLE_SIZE_FUNCTION_NAME, + tableSizeArgumentCount); + Datum tableSizeDatum = OidFunctionCall1(tableSizeFunctionOid, + relationIdDatum); + + tableSize = DatumGetInt64(tableSizeDatum); + } + else + { + char *relationName = get_rel_name(relationId); + struct stat fileStat; + int statOK = 0; + + StringInfo localFilePath = makeStringInfo(); + appendStringInfo(localFilePath, FOREIGN_CACHED_FILE_PATH, relationName); + + /* extract the file size using stat, analogous to pg_stat_file */ + statOK = stat(localFilePath->data, &fileStat); + if (statOK < 0) + { + ereport(ERROR, (errcode_for_file_access(), + errmsg("could not stat file \"%s\": %m", + localFilePath->data))); + } + + tableSize = (uint64) fileStat.st_size; + } + } + else + { + char *relationName = get_rel_name(relationId); + + ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("cannot get size for table \"%s\"", relationName), + errdetail("Only regular and foreign tables are supported."))); + } + + return tableSize; +} + + +/* Extracts shard id from the given table name, and returns it. */ +static uint64 +ExtractShardId(StringInfo tableName) +{ + uint64 shardId = 0; + char *shardIdString = NULL; + char *shardIdStringEnd = NULL; + + /* find the last underscore and increment for shardId string */ + shardIdString = strrchr(tableName->data, SHARD_NAME_SEPARATOR); + if (shardIdString == NULL) + { + ereport(ERROR, (errmsg("could not extract shardId from table name \"%s\"", + tableName->data))); + } + shardIdString++; + +#ifdef HAVE_STRTOULL + errno = 0; + shardId = strtoull(shardIdString, &shardIdStringEnd, 0); + + if (errno != 0 || (*shardIdStringEnd != '\0')) + { + ereport(ERROR, (errmsg("could not extract shardId from table name \"%s\"", + tableName->data))); + } +#else + ereport(ERROR, (errmsg("could not extract shardId from table name"), + errhint("Your platform does not support strtoull()"))); +#endif + + return shardId; +} + + +/* + * FetchRegularTable fetches the given table's data using the copy out command. + * The function then fetches the DDL commands necessary to create this table's + * replica, and locally applies these DDL commands. Last, the function copies + * the fetched table data into the created table; and on success, returns true. + * On failure due to connectivity issues with remote node, the function returns + * false. On other types of failures, the function errors out. + */ +static bool +FetchRegularTable(const char *nodeName, uint32 nodePort, StringInfo tableName) +{ + StringInfo localFilePath = NULL; + StringInfo remoteCopyCommand = NULL; + List *ddlCommandList = NIL; + ListCell *ddlCommandCell = NULL; + CopyStmt *localCopyCommand = NULL; + RangeVar *localTable = NULL; + uint64 shardId = 0; + bool received = false; + char *quotedTableName = NULL; + StringInfo queryString = NULL; + const char *schemaName = NULL; + + /* copy remote table's data to this node in an idempotent manner */ + shardId = ExtractShardId(tableName); + localFilePath = makeStringInfo(); + appendStringInfo(localFilePath, "base/%s/%s" UINT64_FORMAT, + PG_JOB_CACHE_DIR, TABLE_FILE_PREFIX, shardId); + + quotedTableName = quote_qualified_identifier(schemaName, tableName->data); + remoteCopyCommand = makeStringInfo(); + appendStringInfo(remoteCopyCommand, COPY_OUT_COMMAND, quotedTableName); + + received = ReceiveRegularFile(nodeName, nodePort, remoteCopyCommand, localFilePath); + if (!received) + { + return false; + } + + /* fetch the ddl commands needed to create the table */ + ddlCommandList = TableDDLCommandList(nodeName, nodePort, tableName); + if (ddlCommandList == NIL) + { + return false; + } + + /* + * Apply DDL commands against the database. Note that on failure from here + * on, we immediately error out instead of returning false. + */ + foreach(ddlCommandCell, ddlCommandList) + { + StringInfo ddlCommand = (StringInfo) lfirst(ddlCommandCell); + Node *ddlCommandNode = ParseTreeNode(ddlCommand->data); + + ProcessUtility(ddlCommandNode, ddlCommand->data, PROCESS_UTILITY_TOPLEVEL, + NULL, None_Receiver, NULL); + CommandCounterIncrement(); + } + + /* + * Copy local file into the relation. We call ProcessUtility() instead of + * directly calling DoCopy() because some extensions (e.g. cstore_fdw) hook + * into process utility to provide their custom COPY behavior. + */ + localTable = makeRangeVar((char *) schemaName, tableName->data, -1); + localCopyCommand = CopyStatement(localTable, localFilePath->data); + + queryString = makeStringInfo(); + appendStringInfo(queryString, COPY_IN_COMMAND, quotedTableName, localFilePath->data); + + ProcessUtility((Node *) localCopyCommand, queryString->data, + PROCESS_UTILITY_TOPLEVEL, NULL, None_Receiver, NULL); + + /* finally delete the temporary file we created */ + DeleteFile(localFilePath->data); + + return true; +} + + +/* + * FetchForeignTable fetches the foreign file for the given table name from the + * remote node. The function then fetches the DDL commands needed to create the + * table, and applies these DDL commands locally to create the foreign table. + * On success, the function returns true. On failure due to connectivity issues + * with remote node, the function returns false. On failure due to applying DDL + * commands against the local database, the function errors out. + */ +static bool +FetchForeignTable(const char *nodeName, uint32 nodePort, StringInfo tableName) +{ + StringInfo localFilePath = NULL; + StringInfo remoteFilePath = NULL; + StringInfo transmitCommand = NULL; + StringInfo alterTableCommand = NULL; + bool received = false; + List *ddlCommandList = NIL; + ListCell *ddlCommandCell = NULL; + + /* fetch foreign file to this node in an idempotent manner */ + localFilePath = makeStringInfo(); + appendStringInfo(localFilePath, FOREIGN_CACHED_FILE_PATH, tableName->data); + + remoteFilePath = ForeignFilePath(nodeName, nodePort, tableName); + if (remoteFilePath == NULL) + { + return false; + } + + transmitCommand = makeStringInfo(); + appendStringInfo(transmitCommand, TRANSMIT_REGULAR_COMMAND, remoteFilePath->data); + + received = ReceiveRegularFile(nodeName, nodePort, transmitCommand, localFilePath); + if (!received) + { + return false; + } + + /* fetch the ddl commands needed to create the table */ + ddlCommandList = TableDDLCommandList(nodeName, nodePort, tableName); + if (ddlCommandList == NIL) + { + return false; + } + + alterTableCommand = makeStringInfo(); + appendStringInfo(alterTableCommand, SET_FOREIGN_TABLE_FILENAME, + tableName->data, localFilePath->data); + + ddlCommandList = lappend(ddlCommandList, alterTableCommand); + + /* + * Apply DDL commands against the database. Note that on failure here, we + * immediately error out instead of returning false. + */ + foreach(ddlCommandCell, ddlCommandList) + { + StringInfo ddlCommand = (StringInfo) lfirst(ddlCommandCell); + Node *ddlCommandNode = ParseTreeNode(ddlCommand->data); + + ProcessUtility(ddlCommandNode, ddlCommand->data, PROCESS_UTILITY_TOPLEVEL, + NULL, None_Receiver, NULL); + CommandCounterIncrement(); + } + + return true; +} + + +/* + * TableDDLCommandList takes in the given table name, and fetches the list of + * DDL commands used in creating the table. If an error occurs during fetching, + * the function returns an empty list. + */ +static List * +TableDDLCommandList(const char *nodeName, uint32 nodePort, StringInfo tableName) +{ + List *ddlCommandList = NIL; + StringInfo queryString = NULL; + + queryString = makeStringInfo(); + appendStringInfo(queryString, GET_TABLE_DDL_EVENTS, tableName->data); + + ddlCommandList = ExecuteRemoteQuery(nodeName, nodePort, queryString); + return ddlCommandList; +} + + +/* + * ForeignFilePath takes in the foreign table name, and fetches this table's + * remote file path. If an error occurs during fetching, the function returns + * null. + */ +static StringInfo +ForeignFilePath(const char *nodeName, uint32 nodePort, StringInfo tableName) +{ + List *foreignPathList = NIL; + StringInfo foreignPathCommand = NULL; + StringInfo foreignPath = NULL; + + foreignPathCommand = makeStringInfo(); + appendStringInfo(foreignPathCommand, FOREIGN_FILE_PATH_COMMAND, tableName->data); + + foreignPathList = ExecuteRemoteQuery(nodeName, nodePort, foreignPathCommand); + if (foreignPathList != NIL) + { + foreignPath = (StringInfo) linitial(foreignPathList); + } + + return foreignPath; +} + + +/* + * ExecuteRemoteQuery executes the given query, copies the query's results to a + * sorted list, and returns this list. The function assumes that query results + * have a single column, and asserts on that assumption. If results are empty, + * or an error occurs during query runtime, the function returns an empty list. + */ +List * +ExecuteRemoteQuery(const char *nodeName, uint32 nodePort, StringInfo queryString) +{ + char *nodeDatabase = get_database_name(MyDatabaseId); + int32 connectionId = -1; + bool querySent = false; + bool queryReady = false; + bool queryOK = false; + void *queryResult = NULL; + int rowCount = 0; + int rowIndex = 0; + int columnCount = 0; + List *resultList = NIL; + + connectionId = MultiClientConnect(nodeName, nodePort, nodeDatabase); + if (connectionId == INVALID_CONNECTION_ID) + { + return NIL; + } + + querySent = MultiClientSendQuery(connectionId, queryString->data); + if (!querySent) + { + MultiClientDisconnect(connectionId); + return NIL; + } + + while (!queryReady) + { + ResultStatus resultStatus = MultiClientResultStatus(connectionId); + if (resultStatus == CLIENT_RESULT_READY) + { + queryReady = true; + } + else if (resultStatus == CLIENT_RESULT_BUSY) + { + long sleepIntervalPerCycle = RemoteTaskCheckInterval * 1000L; + pg_usleep(sleepIntervalPerCycle); + } + else + { + MultiClientDisconnect(connectionId); + return NIL; + } + } + + queryOK = MultiClientQueryResult(connectionId, &queryResult, &rowCount, &columnCount); + if (!queryOK) + { + MultiClientDisconnect(connectionId); + return NIL; + } + + for (rowIndex = 0; rowIndex < rowCount; rowIndex++) + { + const int columnIndex = 0; + char *rowValue = MultiClientGetValue(queryResult, rowIndex, columnIndex); + + StringInfo rowValueString = makeStringInfo(); + appendStringInfoString(rowValueString, rowValue); + + Assert(columnCount == 1); + resultList = lappend(resultList, rowValueString); + } + + MultiClientClearResult(queryResult); + MultiClientDisconnect(connectionId); + + return resultList; +} + + +/* + * Parses the given DDL command, and returns the tree node for parsed command. + */ +Node * +ParseTreeNode(const char *ddlCommand) +{ + Node *parseTreeNode = NULL; + List *parseTreeList = NULL; + uint32 parseTreeCount = 0; + + parseTreeList = pg_parse_query(ddlCommand); + + /* log immediately if dictated by log statement */ + if (check_log_statement(parseTreeList)) + { + ereport(LOG, (errmsg("statement: %s", ddlCommand), errhidestmt(true))); + } + + parseTreeCount = list_length(parseTreeList); + if (parseTreeCount != 1) + { + ereport(ERROR, (errmsg("cannot execute multiple utility events"))); + } + + /* + * xact.c rejects certain commands that are unsafe to run inside transaction + * blocks. Since we only apply commands that relate to creating tables and + * those commands are safe, we can safely set the ProcessUtilityContext to + * PROCESS_UTILITY_TOPLEVEL. + */ + parseTreeNode = (Node *) linitial(parseTreeList); + + return parseTreeNode; +} + + +/* + * worker_append_table_to_shard fetches the given remote table's data into the + * local file system. The function then appends this file data into the given + * shard. + */ +Datum +worker_append_table_to_shard(PG_FUNCTION_ARGS) +{ + text *shardNameText = PG_GETARG_TEXT_P(0); + text *remoteTableNameText = PG_GETARG_TEXT_P(1); + text *nodeNameText = PG_GETARG_TEXT_P(2); + uint32 nodePort = PG_GETARG_UINT32(3); + + char *shardName = text_to_cstring(shardNameText); + char *remoteTableName = text_to_cstring(remoteTableNameText); + char *nodeName = text_to_cstring(nodeNameText); + + StringInfo shardNameString = NULL; + StringInfo localFilePath = NULL; + StringInfo remoteCopyCommand = NULL; + CopyStmt *localCopyCommand = NULL; + RangeVar *localTable = NULL; + uint64 copiedRowCount = 0; + uint64 shardId = INVALID_SHARD_ID; + bool received = false; + char *quotedTableName = NULL; + const char *queryString = NULL; + const char *schemaName = NULL; + + /* copy remote table's data to this node */ + shardNameString = makeStringInfo(); + appendStringInfoString(shardNameString, shardName); + + /* + * We lock on the shardId, but do not unlock. When the function returns, and + * the transaction for this function commits, this lock will automatically + * be released. This ensures appends to a shard happen in a serial manner. + */ + shardId = ExtractShardId(shardNameString); + LockShardResource(shardId, AccessExclusiveLock); + + localFilePath = makeStringInfo(); + appendStringInfo(localFilePath, "base/%s/%s" UINT64_FORMAT, + PG_JOB_CACHE_DIR, TABLE_FILE_PREFIX, shardId); + + quotedTableName = quote_qualified_identifier(NULL, remoteTableName); + remoteCopyCommand = makeStringInfo(); + appendStringInfo(remoteCopyCommand, COPY_OUT_COMMAND, quotedTableName); + + received = ReceiveRegularFile(nodeName, nodePort, remoteCopyCommand, localFilePath); + if (!received) + { + ereport(ERROR, (errmsg("could not copy table \"%s\" from \"%s:%u\"", + remoteTableName, nodeName, nodePort))); + } + + /* copy local file into the given shard */ + localTable = makeRangeVar((char *) schemaName, shardNameString->data, -1); + localCopyCommand = CopyStatement(localTable, localFilePath->data); + + DoCopy(localCopyCommand, queryString, &copiedRowCount); + (void) copiedRowCount; + + /* finally delete the temporary file we created */ + DeleteFile(localFilePath->data); + + PG_RETURN_VOID(); +} + + +/* + * check_log_statement is a copy of postgres' check_log_statement function and + * returns whether a statement ought to be logged or not. + */ +static bool +check_log_statement(List *statementList) +{ + ListCell *statementCell; + + if (log_statement == LOGSTMT_NONE) + { + return false; + } + + if (log_statement == LOGSTMT_ALL) + { + return true; + } + + /* else we have to inspect the statement(s) to see whether to log */ + foreach(statementCell, statementList) + { + Node *statement = (Node *) lfirst(statementCell); + + if (GetCommandLogLevel(statement) <= log_statement) + { + return true; + } + } + + return false; +} diff --git a/src/backend/distributed/worker/worker_file_access_protocol.c b/src/backend/distributed/worker/worker_file_access_protocol.c new file mode 100644 index 000000000..04deb2881 --- /dev/null +++ b/src/backend/distributed/worker/worker_file_access_protocol.c @@ -0,0 +1,87 @@ +/*------------------------------------------------------------------------- + * + * worker_file_access_protocol.c + * + * Routines for accessing file related information on this worker node. + * + * Copyright (c) 2012, Citus Data, Inc. + * + * $Id$ + * + *------------------------------------------------------------------------- + */ + +#include "postgres.h" +#include "funcapi.h" + +#include "commands/defrem.h" +#include "distributed/master_protocol.h" +#include "distributed/worker_protocol.h" +#include "foreign/foreign.h" +#include "utils/builtins.h" +#include "utils/lsyscache.h" + + +/* exports for SQL callable functions */ +PG_FUNCTION_INFO_V1(worker_foreign_file_path); +PG_FUNCTION_INFO_V1(worker_find_block_local_path); + + +/* + * worker_foreign_file_path resolves the foreign table for the given table name, + * and extracts and returns the file path associated with that foreign table. + */ +Datum +worker_foreign_file_path(PG_FUNCTION_ARGS) +{ + text *foreignTableName = PG_GETARG_TEXT_P(0); + text *foreignFilePath = NULL; + Oid relationId = ResolveRelationId(foreignTableName); + ForeignTable *foreignTable = GetForeignTable(relationId); + + ListCell *optionCell = NULL; + foreach(optionCell, foreignTable->options) + { + DefElem *option = (DefElem *) lfirst(optionCell); + char *optionName = option->defname; + + int compareResult = strncmp(optionName, FOREIGN_FILENAME_OPTION, MAXPGPATH); + if (compareResult == 0) + { + char *optionValue = defGetString(option); + foreignFilePath = cstring_to_text(optionValue); + break; + } + } + + /* check that we found the filename option */ + if (foreignFilePath == NULL) + { + char *relationName = get_rel_name(relationId); + ereport(ERROR, (errmsg("could not find filename for foreign table: \"%s\"", + relationName))); + } + + PG_RETURN_TEXT_P(foreignFilePath); +} + + +/* + * Protocol declaration for a function whose future implementation will find the + * given HDFS block's local file path. + */ +Datum +worker_find_block_local_path(PG_FUNCTION_ARGS) +{ + int64 blockId = PG_GETARG_INT64(0); + ArrayType *dataDirectoryObject = PG_GETARG_ARRAYTYPE_P(1); + + /* keep the compiler silent */ + (void) blockId; + (void) dataDirectoryObject; + + ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("called function is currently unsupported"))); + + PG_RETURN_TEXT_P(NULL); +} diff --git a/src/backend/distributed/worker/worker_merge_protocol.c b/src/backend/distributed/worker/worker_merge_protocol.c new file mode 100644 index 000000000..ee829e342 --- /dev/null +++ b/src/backend/distributed/worker/worker_merge_protocol.c @@ -0,0 +1,547 @@ +/*------------------------------------------------------------------------- + * + * worker_merge_protocol.c + * + * Routines for merging partitioned files into a single file or table. Merging + * files is one of the threee distributed execution primitives that we apply on + * worker nodes. + * + * Copyright (c) 2012, Citus Data, Inc. + * + * $Id$ + * + *------------------------------------------------------------------------- + */ + +#include "postgres.h" +#include "funcapi.h" +#include "miscadmin.h" + +#ifdef HAVE_INTTYPES_H +#include +#endif + +#include "access/htup_details.h" +#include "access/xact.h" +#include "catalog/dependency.h" +#include "catalog/pg_namespace.h" +#include "commands/copy.h" +#include "commands/tablecmds.h" +#include "distributed/worker_protocol.h" +#include "executor/spi.h" +#include "nodes/makefuncs.h" +#include "parser/parse_type.h" +#include "storage/lmgr.h" +#include "utils/acl.h" +#include "utils/builtins.h" +#include "utils/snapmgr.h" +#include "utils/syscache.h" +#include "utils/tqual.h" + + +/* Local functions forward declarations */ +static List * ArrayObjectToCStringList(ArrayType *arrayObject); +static void CreateTaskTable(StringInfo schemaName, StringInfo relationName, + List *columnNameList, List *columnTypeList); +static void CopyTaskFilesFromDirectory(StringInfo schemaName, StringInfo relationName, + StringInfo sourceDirectoryName); + + +/* exports for SQL callable functions */ +PG_FUNCTION_INFO_V1(worker_merge_files_into_table); +PG_FUNCTION_INFO_V1(worker_merge_files_and_run_query); +PG_FUNCTION_INFO_V1(worker_cleanup_job_schema_cache); + + +/* + * worker_merge_files_into_table creates a task table within the job's schema, + * which should have already been created by the task tracker protocol, and + * copies files in its task directory into this table. If the schema doesn't + * exist, the function defaults to the 'public' schema. Note that, unlike + * partitioning functions, this function is not always idempotent. On success, + * the function creates the table and loads data, and subsequent calls to the + * function error out because the table already exist. On failure, the task + * table creation commands are rolled back, and the function can be called + * again. + */ +Datum +worker_merge_files_into_table(PG_FUNCTION_ARGS) +{ + uint64 jobId = PG_GETARG_INT64(0); + uint32 taskId = PG_GETARG_UINT32(1); + ArrayType *columnNameObject = PG_GETARG_ARRAYTYPE_P(2); + ArrayType *columnTypeObject = PG_GETARG_ARRAYTYPE_P(3); + + StringInfo jobSchemaName = JobSchemaName(jobId); + StringInfo taskTableName = TaskTableName(taskId); + StringInfo taskDirectoryName = TaskDirectoryName(jobId, taskId); + bool schemaExists = false; + List *columnNameList = NIL; + List *columnTypeList = NIL; + + /* we should have the same number of column names and types */ + int32 columnNameCount = ArrayObjectCount(columnNameObject); + int32 columnTypeCount = ArrayObjectCount(columnTypeObject); + if (columnNameCount != columnTypeCount) + { + ereport(ERROR, (errmsg("column name array size: %d and type array size: %d" + " do not match", columnNameCount, columnTypeCount))); + } + + /* + * If the schema for the job isn't already created by the task tracker + * protocol, we fall to using the default 'public' schema. + */ + schemaExists = JobSchemaExists(jobSchemaName); + if (!schemaExists) + { + resetStringInfo(jobSchemaName); + appendStringInfoString(jobSchemaName, "public"); + } + + /* create the task table and copy files into the table */ + columnNameList = ArrayObjectToCStringList(columnNameObject); + columnTypeList = ArrayObjectToCStringList(columnTypeObject); + + CreateTaskTable(jobSchemaName, taskTableName, columnNameList, columnTypeList); + + CopyTaskFilesFromDirectory(jobSchemaName, taskTableName, taskDirectoryName); + + PG_RETURN_VOID(); +} + + +/* + * worker_merge_files_and_run_query creates a merge task table within the job's + * schema, which should have already been created by the task tracker protocol. + * It copies files in its task directory into this table. Then it runs final + * query to create result table of the job. + * + * Note that here we followed a different approach to create a task table for merge + * files than worker_merge_files_into_table(). In future we should unify these + * two approaches. For this purpose creating a directory_fdw extension and using + * it would make sense. Then we can merge files with a query or without query + * through directory_fdw. + */ +Datum +worker_merge_files_and_run_query(PG_FUNCTION_ARGS) +{ + uint64 jobId = PG_GETARG_INT64(0); + uint32 taskId = PG_GETARG_UINT32(1); + text *createMergeTableQueryText = PG_GETARG_TEXT_P(2); + text *createIntermediateTableQueryText = PG_GETARG_TEXT_P(3); + + const char *createMergeTableQuery = text_to_cstring(createMergeTableQueryText); + const char *createIntermediateTableQuery = + text_to_cstring(createIntermediateTableQueryText); + + StringInfo taskDirectoryName = TaskDirectoryName(jobId, taskId); + StringInfo jobSchemaName = JobSchemaName(jobId); + StringInfo intermediateTableName = TaskTableName(taskId); + StringInfo mergeTableName = makeStringInfo(); + StringInfo setSearchPathString = makeStringInfo(); + bool schemaExists = false; + int connected = 0; + int setSearchPathResult = 0; + int createMergeTableResult = 0; + int createIntermediateTableResult = 0; + int finished = 0; + + /* + * If the schema for the job isn't already created by the task tracker + * protocol, we fall to using the default 'public' schema. + */ + schemaExists = JobSchemaExists(jobSchemaName); + if (!schemaExists) + { + resetStringInfo(jobSchemaName); + appendStringInfoString(jobSchemaName, "public"); + } + + appendStringInfo(setSearchPathString, SET_SEARCH_PATH_COMMAND, jobSchemaName->data); + + connected = SPI_connect(); + if (connected != SPI_OK_CONNECT) + { + ereport(ERROR, (errmsg("could not connect to SPI manager"))); + } + + setSearchPathResult = SPI_exec(setSearchPathString->data, 0); + if (setSearchPathResult < 0) + { + ereport(ERROR, (errmsg("execution was not successful \"%s\"", + setSearchPathString->data))); + } + + createMergeTableResult = SPI_exec(createMergeTableQuery, 0); + if (createMergeTableResult < 0) + { + ereport(ERROR, (errmsg("execution was not successful \"%s\"", + createMergeTableQuery))); + } + + appendStringInfo(mergeTableName, "%s%s", intermediateTableName->data, + MERGE_TABLE_SUFFIX); + CopyTaskFilesFromDirectory(jobSchemaName, mergeTableName, taskDirectoryName); + + createIntermediateTableResult = SPI_exec(createIntermediateTableQuery, 0); + if (createIntermediateTableResult < 0) + { + ereport(ERROR, (errmsg("execution was not successful \"%s\"", + createIntermediateTableQuery))); + } + + finished = SPI_finish(); + if (finished != SPI_OK_FINISH) + { + ereport(ERROR, (errmsg("could not disconnect from SPI manager"))); + } + + PG_RETURN_VOID(); +} + + +/* + * worker_cleanup_job_schema_cache walks over all schemas in the database, and + * removes schemas whose names start with the job schema prefix. Note that this + * function does not perform any locking; we expect it to be called at process + * start-up time before any merge tasks are run. Further note that this function + * runs within the scope of a particular database (template1, postgres) and can + * only delete schemas within that database. + */ +Datum +worker_cleanup_job_schema_cache(PG_FUNCTION_ARGS) +{ + Relation pgNamespace = NULL; + HeapScanDesc scanDescriptor = NULL; + ScanKey scanKey = NULL; + int scanKeyCount = 0; + HeapTuple heapTuple = NULL; + + pgNamespace = heap_open(NamespaceRelationId, AccessExclusiveLock); + scanDescriptor = heap_beginscan_catalog(pgNamespace, scanKeyCount, scanKey); + + heapTuple = heap_getnext(scanDescriptor, ForwardScanDirection); + while (HeapTupleIsValid(heapTuple)) + { + Form_pg_namespace schemaForm = (Form_pg_namespace) GETSTRUCT(heapTuple); + char *schemaName = NameStr(schemaForm->nspname); + + char *jobSchemaFound = strstr(schemaName, JOB_SCHEMA_PREFIX); + if (jobSchemaFound != NULL) + { + StringInfo jobSchemaName = makeStringInfo(); + appendStringInfoString(jobSchemaName, schemaName); + + RemoveJobSchema(jobSchemaName); + } + + heapTuple = heap_getnext(scanDescriptor, ForwardScanDirection); + } + + heap_endscan(scanDescriptor); + heap_close(pgNamespace, AccessExclusiveLock); + + PG_RETURN_VOID(); +} + + +/* Constructs a standardized job schema name for the given job id. */ +StringInfo +JobSchemaName(uint64 jobId) +{ + /* + * We need to apply padding on our 64-bit job id, and therefore cannot use + * UINT64_FORMAT here. + */ +#ifdef HAVE_INTTYPES_H + StringInfo jobSchemaName = makeStringInfo(); + appendStringInfo(jobSchemaName, "%s%0*"PRIu64, + JOB_SCHEMA_PREFIX, MIN_JOB_DIRNAME_WIDTH, jobId); +#else + StringInfo jobSchemaName = makeStringInfo(); + appendStringInfo(jobSchemaName, "%s%0*llu", + JOB_SCHEMA_PREFIX, MIN_JOB_DIRNAME_WIDTH, jobId); +#endif + + return jobSchemaName; +} + + +/* Constructs a standardized task table name for the given task id. */ +StringInfo +TaskTableName(uint32 taskId) +{ + StringInfo taskTableName = makeStringInfo(); + appendStringInfo(taskTableName, "%s%0*u", + TASK_TABLE_PREFIX, MIN_TASK_FILENAME_WIDTH, taskId); + + return taskTableName; +} + + +/* Creates a list of cstrings from a single dimensional array object. */ +static List * +ArrayObjectToCStringList(ArrayType *arrayObject) +{ + List *cstringList = NIL; + Datum *datumArray = DeconstructArrayObject(arrayObject); + int32 arraySize = ArrayObjectCount(arrayObject); + + int32 arrayIndex = 0; + for (arrayIndex = 0; arrayIndex < arraySize; arrayIndex++) + { + Datum datum = datumArray[arrayIndex]; + char *cstring = TextDatumGetCString(datum); + + cstringList = lappend(cstringList, cstring); + } + + Assert(cstringList != NIL); + return cstringList; +} + + +/* Checks if a schema with the given schema name exists. */ +bool +JobSchemaExists(StringInfo schemaName) +{ + Datum schemaNameDatum = CStringGetDatum(schemaName->data); + bool schemaExists = SearchSysCacheExists(NAMESPACENAME, schemaNameDatum, 0, 0, 0); + + return schemaExists; +} + + +/* Removes the schema and all tables within the schema, if the schema exists. */ +void +RemoveJobSchema(StringInfo schemaName) +{ + Datum schemaNameDatum = CStringGetDatum(schemaName->data); + Oid schemaId = InvalidOid; + + schemaId = GetSysCacheOid(NAMESPACENAME, schemaNameDatum, 0, 0, 0); + if (OidIsValid(schemaId)) + { + ObjectAddress schemaObject = { 0, 0, 0 }; + bool showNotices = false; + + bool permissionsOK = pg_namespace_ownercheck(schemaId, GetUserId()); + if (!permissionsOK) + { + aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_NAMESPACE, schemaName->data); + } + + schemaObject.classId = NamespaceRelationId; + schemaObject.objectId = schemaId; + schemaObject.objectSubId = 0; + + /* + * We first delete all tables in this schema. Rather than relying on the + * schema command, we call the dependency mechanism directly so that we + * can suppress notice messages that are typically displayed during + * cascading deletes. + */ + deleteWhatDependsOn(&schemaObject, showNotices); + CommandCounterIncrement(); + + /* drop the empty schema */ + performDeletion(&schemaObject, DROP_RESTRICT, 0); + CommandCounterIncrement(); + } + else + { + ereport(DEBUG2, (errmsg("schema \"%s\" does not exist, skipping", + schemaName->data))); + } +} + + +/* Creates a simple table that only defines columns, in the given schema. */ +static void +CreateTaskTable(StringInfo schemaName, StringInfo relationName, + List *columnNameList, List *columnTypeList) +{ + CreateStmt *createStatement = NULL; + RangeVar *relation = NULL; + List *columnDefinitionList = NIL; + Oid relationId = InvalidOid; +#if (PG_VERSION_NUM >= 90500) + ObjectAddress relationObject; +#endif + + Assert(schemaName != NULL); + Assert(relationName != NULL); + + /* + * This new relation doesn't log to WAL, as the table creation and data copy + * statements occur in the same transaction. Still, we want to make the + * relation unlogged once we upgrade to PostgreSQL 9.1. + */ + relation = makeRangeVar(schemaName->data, relationName->data, -1); + columnDefinitionList = ColumnDefinitionList(columnNameList, columnTypeList); + + createStatement = CreateStatement(relation, columnDefinitionList); + +#if (PG_VERSION_NUM >= 90500) + relationObject = DefineRelation(createStatement, RELKIND_RELATION, InvalidOid, NULL); + relationId = relationObject.objectId; +#else + relationId = DefineRelation(createStatement, RELKIND_RELATION, InvalidOid); +#endif + + Assert(relationId != InvalidOid); + CommandCounterIncrement(); +} + + +/* + * ColumnDefinitionList creates and returns a list of column definition objects + * from two lists of column names and types. As an example, this function takes + * in two single elements lists: "l_quantity" and "decimal(15, 2)". The function + * then returns a list with one column definition, where the column's name is + * l_quantity, its type is numeric, and the type modifier represents (15, 2). + */ +List * +ColumnDefinitionList(List *columnNameList, List *columnTypeList) +{ + List *columnDefinitionList = NIL; + ListCell *columnNameCell = NULL; + ListCell *columnTypeCell = NULL; + + forboth(columnNameCell, columnNameList, columnTypeCell, columnTypeList) + { + const char *columnName = (const char *) lfirst(columnNameCell); + const char *columnType = (const char *) lfirst(columnTypeCell); + + /* + * We should have a SQL compatible column type declaration; we first + * convert this type to PostgreSQL's type identifiers and modifiers. + */ + Oid columnTypeId = InvalidOid; + int32 columnTypeMod = -1; + bool missingOK = false; + TypeName *typeName = NULL; + ColumnDef *columnDefinition = NULL; + + parseTypeString(columnType, &columnTypeId, &columnTypeMod, missingOK); + typeName = makeTypeNameFromOid(columnTypeId, columnTypeMod); + + /* we then create the column definition */ + columnDefinition = makeNode(ColumnDef); + columnDefinition->colname = (char *) columnName; + columnDefinition->typeName = typeName; + columnDefinition->is_local = true; + columnDefinition->is_not_null = false; + columnDefinition->raw_default = NULL; + columnDefinition->cooked_default = NULL; + columnDefinition->constraints = NIL; + + columnDefinitionList = lappend(columnDefinitionList, columnDefinition); + } + + return columnDefinitionList; +} + + +/* + * CreateStatement creates and initializes a simple table create statement that + * only has column definitions. + */ +CreateStmt * +CreateStatement(RangeVar *relation, List *columnDefinitionList) +{ + CreateStmt *createStatement = makeNode(CreateStmt); + createStatement->relation = relation; + createStatement->tableElts = columnDefinitionList; + createStatement->inhRelations = NIL; + createStatement->constraints = NIL; + createStatement->options = NIL; + createStatement->oncommit = ONCOMMIT_NOOP; + createStatement->tablespacename = NULL; + createStatement->if_not_exists = false; + + return createStatement; +} + + +/* + * CopyTaskFilesFromDirectory finds all files in the given directory, except for + * those having an attempt suffix. The function then copies these files into the + * database table identified by the given schema and table name. + */ +static void +CopyTaskFilesFromDirectory(StringInfo schemaName, StringInfo relationName, + StringInfo sourceDirectoryName) +{ + const char *directoryName = sourceDirectoryName->data; + struct dirent *directoryEntry = NULL; + uint64 copiedRowTotal = 0; + + DIR *directory = AllocateDir(directoryName); + if (directory == NULL) + { + ereport(ERROR, (errcode_for_file_access(), + errmsg("could not open directory \"%s\": %m", directoryName))); + } + + directoryEntry = ReadDir(directory, directoryName); + for (; directoryEntry != NULL; directoryEntry = ReadDir(directory, directoryName)) + { + const char *baseFilename = directoryEntry->d_name; + const char *queryString = NULL; + StringInfo fullFilename = NULL; + RangeVar *relation = NULL; + CopyStmt *copyStatement = NULL; + uint64 copiedRowCount = 0; + + /* if system file or lingering task file, skip it */ + if (strncmp(baseFilename, ".", MAXPGPATH) == 0 || + strncmp(baseFilename, "..", MAXPGPATH) == 0 || + strstr(baseFilename, ATTEMPT_FILE_SUFFIX) != NULL) + { + continue; + } + + fullFilename = makeStringInfo(); + appendStringInfo(fullFilename, "%s/%s", directoryName, baseFilename); + + /* build relation object and copy statement */ + relation = makeRangeVar(schemaName->data, relationName->data, -1); + copyStatement = CopyStatement(relation, fullFilename->data); + if (BinaryWorkerCopyFormat) + { + DefElem *copyOption = makeDefElem("format", (Node *) makeString("binary")); + copyStatement->options = list_make1(copyOption); + } + + DoCopy(copyStatement, queryString, &copiedRowCount); + copiedRowTotal += copiedRowCount; + CommandCounterIncrement(); + } + + ereport(DEBUG2, (errmsg("copied " UINT64_FORMAT " rows into table: \"%s.%s\"", + copiedRowTotal, schemaName->data, relationName->data))); + + FreeDir(directory); +} + + +/* + * CopyStatement creates and initializes a copy statement to read the given + * file's contents into the given table, using copy's standard text format. + */ +CopyStmt * +CopyStatement(RangeVar *relation, char *sourceFilename) +{ + CopyStmt *copyStatement = makeNode(CopyStmt); + copyStatement->relation = relation; + copyStatement->query = NULL; + copyStatement->attlist = NIL; + copyStatement->options = NIL; + copyStatement->is_from = true; + copyStatement->is_program = false; + copyStatement->filename = sourceFilename; + + return copyStatement; +} diff --git a/src/backend/distributed/worker/worker_partition_protocol.c b/src/backend/distributed/worker/worker_partition_protocol.c new file mode 100644 index 000000000..c6578295b --- /dev/null +++ b/src/backend/distributed/worker/worker_partition_protocol.c @@ -0,0 +1,1395 @@ +/*------------------------------------------------------------------------- + * + * worker_partition_protocol.c + * + * Routines for partitioning table data into multiple files. Table partitioning + * is one of the three distributed execution primitives that we apply on worker + * nodes; and when partitioning data, we follow Hadoop's naming conventions as + * much as possible. + * + * Copyright (c) 2012, Citus Data, Inc. + * + * $Id$ + * + *------------------------------------------------------------------------- + */ + +#include "postgres.h" +#include "funcapi.h" + +#include +#include +#ifdef HAVE_INTTYPES_H +#include +#endif + +#include "access/hash.h" +#include "access/htup_details.h" +#include "access/nbtree.h" +#include "catalog/pg_collation.h" +#include "commands/copy.h" +#include "commands/defrem.h" +#include "distributed/resource_lock.h" +#include "distributed/transmit.h" +#include "distributed/worker_protocol.h" +#include "executor/spi.h" +#include "mb/pg_wchar.h" +#include "storage/lmgr.h" +#include "utils/builtins.h" +#include "utils/lsyscache.h" +#include "utils/memutils.h" + + +/* Config variables managed via guc.c */ +bool BinaryWorkerCopyFormat = false; /* binary format for copying between workers */ +int PartitionBufferSize = 16384; /* total partitioning buffer size in KB */ + +/* Local variables */ +static const char BinarySignature[11] = "PGCOPY\n\377\r\n\0"; +static uint32 FileBufferSizeInBytes = 0; /* file buffer size to init later */ + + +/* Local functions forward declarations */ +static StringInfo InitTaskAttemptDirectory(uint64 jobId, uint32 taskId); +static uint32 FileBufferSize(int partitionBufferSizeInKB, uint32 fileCount); +static FileOutputStream * OpenPartitionFiles(StringInfo directoryName, uint32 fileCount); +static void ClosePartitionFiles(FileOutputStream *partitionFileArray, uint32 fileCount); +static void RenameDirectory(StringInfo oldDirectoryName, StringInfo newDirectoryName); +static void FileOutputStreamWrite(FileOutputStream file, StringInfo dataToWrite); +static void FileOutputStreamFlush(FileOutputStream file); +static void FilterAndPartitionTable(const char *filterQuery, + const char *columnName, Oid columnType, + uint32 (*PartitionIdFunction) (Datum, const void *), + const void *partitionIdContext, + FileOutputStream *partitionFileArray, + uint32 fileCount); +static int ColumnIndex(TupleDesc rowDescriptor, const char *columnName); +static FmgrInfo * ColumnOutputFunctions(TupleDesc rowDescriptor, bool binaryFormat); +static PartialCopyState InitRowOutputState(void); +static void ClearRowOutputState(PartialCopyState copyState); +static void OutputRow(HeapTuple row, TupleDesc rowDescriptor, + PartialCopyState rowOutputState, FmgrInfo *columnOutputFunctions); +static void OutputBinaryHeaders(FileOutputStream *partitionFileArray, uint32 fileCount); +static void OutputBinaryFooters(FileOutputStream *partitionFileArray, uint32 fileCount); +static void CopySendData(PartialCopyState outputState, const void *databuf, int datasize); +static void CopySendString(PartialCopyState outputState, const char *str); +static void CopySendChar(PartialCopyState outputState, char c); +static void CopySendInt32(PartialCopyState outputState, int32 val); +static void CopySendInt16(PartialCopyState outputState, int16 val); +static void CopyAttributeOutText(PartialCopyState outputState, char *string); +static inline void CopyFlushOutput(PartialCopyState outputState, + char *start, char *pointer); +static uint32 RangePartitionId(Datum partitionValue, const void *context); +static uint32 HashPartitionId(Datum partitionValue, const void *context); + + +/* exports for SQL callable functions */ +PG_FUNCTION_INFO_V1(worker_range_partition_table); +PG_FUNCTION_INFO_V1(worker_hash_partition_table); + + +/* + * worker_range_partition_table executes the given filter query, repartitions + * the filter query's results on a partitioning column, and writes the resulting + * rows to a set of text files on local disk. The function then atomically + * renames the directory in which the text files live to ensure deterministic + * behavior. + * + * This function applies range partitioning through the use of a function + * pointer and a range context object; for details, see RangePartitionId(). + */ +Datum +worker_range_partition_table(PG_FUNCTION_ARGS) +{ + uint64 jobId = PG_GETARG_INT64(0); + uint32 taskId = PG_GETARG_UINT32(1); + text *filterQueryText = PG_GETARG_TEXT_P(2); + text *partitionColumnText = PG_GETARG_TEXT_P(3); + Oid partitionColumnType = PG_GETARG_OID(4); + ArrayType *splitPointObject = PG_GETARG_ARRAYTYPE_P(5); + + const char *filterQuery = text_to_cstring(filterQueryText); + const char *partitionColumn = text_to_cstring(partitionColumnText); + + RangePartitionContext *partitionContext = NULL; + FmgrInfo *comparisonFunction = NULL; + Datum *splitPointArray = NULL; + int32 splitPointCount = 0; + uint32 fileCount = 0; + StringInfo taskDirectory = NULL; + StringInfo taskAttemptDirectory = NULL; + FileOutputStream *partitionFileArray = NULL; + + /* first check that array element's and partition column's types match */ + Oid splitPointType = ARR_ELEMTYPE(splitPointObject); + if (splitPointType != partitionColumnType) + { + ereport(ERROR, (errmsg("partition column type %u and split point type %u " + "do not match", partitionColumnType, splitPointType))); + } + + /* use column's type information to get the comparison function */ + comparisonFunction = GetFunctionInfo(partitionColumnType, + BTREE_AM_OID, BTORDER_PROC); + + /* deserialize split points into their array representation */ + splitPointArray = DeconstructArrayObject(splitPointObject); + splitPointCount = ArrayObjectCount(splitPointObject); + fileCount = splitPointCount + 1; /* range partitioning needs an extra bucket */ + + /* create range partition context object */ + partitionContext = palloc0(sizeof(RangePartitionContext)); + partitionContext->comparisonFunction = comparisonFunction; + partitionContext->splitPointArray = splitPointArray; + partitionContext->splitPointCount = splitPointCount; + + /* init directories and files to write the partitioned data to */ + taskDirectory = InitTaskDirectory(jobId, taskId); + taskAttemptDirectory = InitTaskAttemptDirectory(jobId, taskId); + + partitionFileArray = OpenPartitionFiles(taskAttemptDirectory, fileCount); + FileBufferSizeInBytes = FileBufferSize(PartitionBufferSize, fileCount); + + /* call the partitioning function that does the actual work */ + FilterAndPartitionTable(filterQuery, partitionColumn, partitionColumnType, + &RangePartitionId, (const void *) partitionContext, + partitionFileArray, fileCount); + + /* close partition files and atomically rename (commit) them */ + ClosePartitionFiles(partitionFileArray, fileCount); + RemoveDirectory(taskDirectory); + RenameDirectory(taskAttemptDirectory, taskDirectory); + + PG_RETURN_VOID(); +} + + +/* + * worker_hash_partition_table executes the given filter query, repartitions the + * filter query's results on a partitioning column, and writes the resulting + * rows to a set of text files on local disk. The function then atomically + * renames the directory in which the text files live to ensure deterministic + * behavior. + * + * This function applies hash partitioning through the use of a function pointer + * and a hash context object; for details, see HashPartitionId(). + */ +Datum +worker_hash_partition_table(PG_FUNCTION_ARGS) +{ + uint64 jobId = PG_GETARG_INT64(0); + uint32 taskId = PG_GETARG_UINT32(1); + text *filterQueryText = PG_GETARG_TEXT_P(2); + text *partitionColumnText = PG_GETARG_TEXT_P(3); + Oid partitionColumnType = PG_GETARG_OID(4); + uint32 partitionCount = PG_GETARG_UINT32(5); + + const char *filterQuery = text_to_cstring(filterQueryText); + const char *partitionColumn = text_to_cstring(partitionColumnText); + + HashPartitionContext *partitionContext = NULL; + FmgrInfo *hashFunction = NULL; + StringInfo taskDirectory = NULL; + StringInfo taskAttemptDirectory = NULL; + FileOutputStream *partitionFileArray = NULL; + uint32 fileCount = partitionCount; + + /* use column's type information to get the hashing function */ + hashFunction = GetFunctionInfo(partitionColumnType, HASH_AM_OID, HASHPROC); + + /* create hash partition context object */ + partitionContext = palloc0(sizeof(HashPartitionContext)); + partitionContext->hashFunction = hashFunction; + partitionContext->partitionCount = partitionCount; + + /* init directories and files to write the partitioned data to */ + taskDirectory = InitTaskDirectory(jobId, taskId); + taskAttemptDirectory = InitTaskAttemptDirectory(jobId, taskId); + + partitionFileArray = OpenPartitionFiles(taskAttemptDirectory, fileCount); + FileBufferSizeInBytes = FileBufferSize(PartitionBufferSize, fileCount); + + /* call the partitioning function that does the actual work */ + FilterAndPartitionTable(filterQuery, partitionColumn, partitionColumnType, + &HashPartitionId, (const void *) partitionContext, + partitionFileArray, fileCount); + + /* close partition files and atomically rename (commit) them */ + ClosePartitionFiles(partitionFileArray, fileCount); + RemoveDirectory(taskDirectory); + RenameDirectory(taskAttemptDirectory, taskDirectory); + + PG_RETURN_VOID(); +} + + +/* + * GetFunctionInfo first resolves the operator for the given data type, access + * method, and support procedure. The function then uses the resolved operator's + * identifier to fill in a function manager object, and returns this object. + */ +FmgrInfo * +GetFunctionInfo(Oid typeId, Oid accessMethodId, int16 procedureId) +{ + FmgrInfo *functionInfo = (FmgrInfo *) palloc0(sizeof(FmgrInfo)); + + /* get default operator class from pg_opclass for datum type */ + Oid operatorClassId = GetDefaultOpClass(typeId, accessMethodId); + + Oid operatorFamilyId = get_opclass_family(operatorClassId); + Oid operatorClassInputType = get_opclass_input_type(operatorClassId); + + Oid operatorId = get_opfamily_proc(operatorFamilyId, operatorClassInputType, + operatorClassInputType, procedureId); + + if (operatorId == InvalidOid) + { + ereport(ERROR, (errmsg("could not find function for data typeId %u", typeId))); + } + + /* fill in the FmgrInfo struct using the operatorId */ + fmgr_info(operatorId, functionInfo); + + return functionInfo; +} + + +/* + * DeconstructArrayObject takes in a single dimensional array, and deserializes + * this array's members into an array of datum objects. The function then + * returns this datum array. + */ +Datum * +DeconstructArrayObject(ArrayType *arrayObject) +{ + Datum *datumArray = NULL; + bool *datumArrayNulls = NULL; + int datumArrayLength = 0; + + Oid typeId = InvalidOid; + bool typeByVal = false; + char typeAlign = 0; + int16 typeLength = 0; + + bool arrayHasNull = ARR_HASNULL(arrayObject); + if (arrayHasNull) + { + ereport(ERROR, (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED), + errmsg("worker array object cannot contain null values"))); + } + + typeId = ARR_ELEMTYPE(arrayObject); + get_typlenbyvalalign(typeId, &typeLength, &typeByVal, &typeAlign); + + deconstruct_array(arrayObject, typeId, typeLength, typeByVal, typeAlign, + &datumArray, &datumArrayNulls, &datumArrayLength); + + return datumArray; +} + + +/* + * ArrayObjectCount takes in a single dimensional array, and returns the number + * of elements in this array. + */ +int32 +ArrayObjectCount(ArrayType *arrayObject) +{ + int32 dimensionCount = ARR_NDIM(arrayObject); + int32 *dimensionLengthArray = ARR_DIMS(arrayObject); + int32 arrayLength = 0; + + /* we currently allow split point arrays to have only one subarray */ + Assert(dimensionCount == 1); + + arrayLength = ArrayGetNItems(dimensionCount, dimensionLengthArray); + if (arrayLength <= 0) + { + ereport(ERROR, (errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR), + errmsg("worker array object cannot be empty"))); + } + + return arrayLength; +} + + +/* + * InitTaskDirectory creates a job and task directory using given identifiers, + * if these directories do not already exist. The function then returns the task + * directory's name. + */ +StringInfo +InitTaskDirectory(uint64 jobId, uint32 taskId) +{ + bool jobDirectoryExists = false; + bool taskDirectoryExists = false; + + /* + * If the task tracker assigned this task (regular case), the tracker should + * have already created the job directory. + */ + StringInfo jobDirectoryName = JobDirectoryName(jobId); + StringInfo taskDirectoryName = TaskDirectoryName(jobId, taskId); + + LockJobResource(jobId, AccessExclusiveLock); + + jobDirectoryExists = DirectoryExists(jobDirectoryName); + if (!jobDirectoryExists) + { + CreateDirectory(jobDirectoryName); + } + + taskDirectoryExists = DirectoryExists(taskDirectoryName); + if (!taskDirectoryExists) + { + CreateDirectory(taskDirectoryName); + } + + UnlockJobResource(jobId, AccessExclusiveLock); + + return taskDirectoryName; +} + + +/* + * InitTaskAttemptDirectory finds a task attempt directory that is not taken, + * and creates that directory. The function then returns the task attempt + * directory's name. + */ +static StringInfo +InitTaskAttemptDirectory(uint64 jobId, uint32 taskId) +{ + StringInfo taskDirectoryName = TaskDirectoryName(jobId, taskId); + uint32 randomId = (uint32) random(); + + /* + * We should have only one process executing this task. Still, we append a + * random id just in case. + */ + StringInfo taskAttemptDirectoryName = makeStringInfo(); + appendStringInfo(taskAttemptDirectoryName, "%s_%0*u", + taskDirectoryName->data, MIN_TASK_FILENAME_WIDTH, randomId); + + /* + * If this task previously failed, and gets re-executed and improbably draws + * the same randomId, the task will fail to create the directory. + */ + CreateDirectory(taskAttemptDirectoryName); + + return taskAttemptDirectoryName; +} + + +/* Calculates and returns the buffer size to use for each file. */ +static uint32 +FileBufferSize(int partitionBufferSizeInKB, uint32 fileCount) +{ + double partitionBufferSize = (double) partitionBufferSizeInKB * 1024.0; + uint32 fileBufferSize = (uint32) rint(partitionBufferSize / fileCount); + + return fileBufferSize; +} + + +/* + * OpenPartitionFiles takes in a directory name and file count, and opens new + * partition files in this directory. The names for these new files are modeled + * after Hadoop's naming conventions for map files. These file names, virtual + * file descriptors, and file buffers are stored together in file output stream + * objects. These objects are then returned in an array from this function. + */ +static FileOutputStream * +OpenPartitionFiles(StringInfo directoryName, uint32 fileCount) +{ + FileOutputStream *partitionFileArray = NULL; + File fileDescriptor = 0; + uint32 fileIndex = 0; + const int fileFlags = (O_APPEND | O_CREAT | O_RDWR | PG_BINARY); + const int fileMode = (S_IRUSR | S_IWUSR); + + partitionFileArray = palloc0(fileCount * sizeof(FileOutputStream)); + + for (fileIndex = 0; fileIndex < fileCount; fileIndex++) + { + StringInfo filePath = PartitionFilename(directoryName, fileIndex); + + fileDescriptor = PathNameOpenFile(filePath->data, fileFlags, fileMode); + if (fileDescriptor < 0) + { + ereport(ERROR, (errcode_for_file_access(), + errmsg("could not open file \"%s\": %m", filePath->data))); + } + + partitionFileArray[fileIndex].fileDescriptor = fileDescriptor; + partitionFileArray[fileIndex].fileBuffer = makeStringInfo(); + partitionFileArray[fileIndex].filePath = filePath; + } + + return partitionFileArray; +} + + +/* + * ClosePartitionFiles walks over each file output stream object, and flushes + * any remaining data in the file's buffer. The function then closes the file, + * and deletes any allocated memory for the file stream object. + */ +static void +ClosePartitionFiles(FileOutputStream *partitionFileArray, uint32 fileCount) +{ + uint32 fileIndex = 0; + for (fileIndex = 0; fileIndex < fileCount; fileIndex++) + { + FileOutputStream partitionFile = partitionFileArray[fileIndex]; + + FileOutputStreamFlush(partitionFile); + + FileClose(partitionFile.fileDescriptor); + FreeStringInfo(partitionFile.fileBuffer); + FreeStringInfo(partitionFile.filePath); + } + + pfree(partitionFileArray); +} + + +/* Constructs a standardized job directory path for the given job id. */ +StringInfo +JobDirectoryName(uint64 jobId) +{ + /* + * We use the default tablespace in {datadir}/base. Further, we need to + * apply padding on our 64-bit job id, and hence can't use UINT64_FORMAT. + */ +#ifdef HAVE_INTTYPES_H + StringInfo jobDirectoryName = makeStringInfo(); + appendStringInfo(jobDirectoryName, "base/%s/%s%0*"PRIu64, + PG_JOB_CACHE_DIR, JOB_DIRECTORY_PREFIX, + MIN_JOB_DIRNAME_WIDTH, jobId); +#else + StringInfo jobDirectoryName = makeStringInfo(); + appendStringInfo(jobDirectoryName, "base/%s/%s%0*llu", + PG_JOB_CACHE_DIR, JOB_DIRECTORY_PREFIX, + MIN_JOB_DIRNAME_WIDTH, jobId); +#endif + + return jobDirectoryName; +} + + +/* Constructs a standardized task directory path for given job and task ids. */ +StringInfo +TaskDirectoryName(uint64 jobId, uint32 taskId) +{ + StringInfo jobDirectoryName = JobDirectoryName(jobId); + + StringInfo taskDirectoryName = makeStringInfo(); + appendStringInfo(taskDirectoryName, "%s/%s%0*u", + jobDirectoryName->data, + TASK_FILE_PREFIX, MIN_TASK_FILENAME_WIDTH, taskId); + + return taskDirectoryName; +} + + +/* Constructs a standardized partition file path for given directory and id. */ +StringInfo +PartitionFilename(StringInfo directoryName, uint32 partitionId) +{ + StringInfo partitionFilename = makeStringInfo(); + appendStringInfo(partitionFilename, "%s/%s%0*u", + directoryName->data, + PARTITION_FILE_PREFIX, MIN_PARTITION_FILENAME_WIDTH, partitionId); + + return partitionFilename; +} + + +/* + * JobDirectoryElement takes in a filename, and checks if this name lives in the + * directory path that is used for task output files. Note that this function's + * implementation is coupled with JobDirectoryName(). + */ +bool +JobDirectoryElement(const char *filename) +{ + bool directoryElement = false; + char *directoryPathFound = NULL; + + StringInfo directoryPath = makeStringInfo(); + appendStringInfo(directoryPath, "base/%s/%s", PG_JOB_CACHE_DIR, JOB_DIRECTORY_PREFIX); + + directoryPathFound = strstr(filename, directoryPath->data); + if (directoryPathFound != NULL) + { + directoryElement = true; + } + + pfree(directoryPath); + + return directoryElement; +} + + +/* Checks if a directory exists for the given directory name. */ +bool +DirectoryExists(StringInfo directoryName) +{ + bool directoryExists = true; + struct stat directoryStat; + + int statOK = stat(directoryName->data, &directoryStat); + if (statOK == 0) + { + /* file already exists; just assert that it is a directory */ + Assert(S_ISDIR(directoryStat.st_mode)); + } + else + { + if (errno == ENOENT) + { + directoryExists = false; + } + else + { + ereport(ERROR, (errcode_for_file_access(), + errmsg("could not stat directory \"%s\": %m", + directoryName->data))); + } + } + + return directoryExists; +} + + +/* Creates a new directory with the given directory name. */ +void +CreateDirectory(StringInfo directoryName) +{ + int makeOK = mkdir(directoryName->data, S_IRWXU); + if (makeOK != 0) + { + ereport(ERROR, (errcode_for_file_access(), + errmsg("could not create directory \"%s\": %m", + directoryName->data))); + } +} + + +/* + * RemoveDirectory first checks if the given directory exists. If it does, the + * function recursively deletes the contents of the given directory, and then + * deletes the directory itself. This function is modeled on the Boost file + * system library's remove_all() method. + */ +void +RemoveDirectory(StringInfo filename) +{ + struct stat fileStat; + int removed = 0; + + int fileStated = stat(filename->data, &fileStat); + if (fileStated < 0) + { + if (errno == ENOENT) + { + return; /* if file does not exist, return */ + } + else + { + ereport(ERROR, (errcode_for_file_access(), + errmsg("could not stat file \"%s\": %m", filename->data))); + } + } + + /* + * If this is a directory, iterate over all its contents and for each + * content, recurse into this function. Also, make sure that we do not + * recurse into symbolic links. + */ + if (S_ISDIR(fileStat.st_mode) && !S_ISLNK(fileStat.st_mode)) + { + const char *directoryName = filename->data; + struct dirent *directoryEntry = NULL; + + DIR *directory = AllocateDir(directoryName); + if (directory == NULL) + { + ereport(ERROR, (errcode_for_file_access(), + errmsg("could not open directory \"%s\": %m", + directoryName))); + } + + directoryEntry = ReadDir(directory, directoryName); + for (; directoryEntry != NULL; directoryEntry = ReadDir(directory, directoryName)) + { + const char *baseFilename = directoryEntry->d_name; + StringInfo fullFilename = NULL; + + /* if system file, skip it */ + if (strncmp(baseFilename, ".", MAXPGPATH) == 0 || + strncmp(baseFilename, "..", MAXPGPATH) == 0) + { + continue; + } + + fullFilename = makeStringInfo(); + appendStringInfo(fullFilename, "%s/%s", directoryName, baseFilename); + + RemoveDirectory(fullFilename); + + FreeStringInfo(fullFilename); + } + + FreeDir(directory); + } + + /* we now have an empty directory or a regular file, remove it */ + if (S_ISDIR(fileStat.st_mode)) + { + removed = rmdir(filename->data); + } + else + { + removed = unlink(filename->data); + } + + if (removed != 0) + { + ereport(ERROR, (errcode_for_file_access(), + errmsg("could not remove file \"%s\": %m", filename->data))); + } +} + + +/* Moves directory from old path to the new one. */ +static void +RenameDirectory(StringInfo oldDirectoryName, StringInfo newDirectoryName) +{ + int renamed = rename(oldDirectoryName->data, newDirectoryName->data); + if (renamed != 0) + { + ereport(ERROR, (errcode_for_file_access(), + errmsg("could not rename directory \"%s\" to \"%s\": %m", + oldDirectoryName->data, newDirectoryName->data))); + } +} + + +/* + * FileOutputStreamWrite appends given data to file stream's internal buffers. + * The function then checks if buffered data exceeds preconfigured buffer size; + * if so, the function flushes the buffer to the underlying file. + */ +static void +FileOutputStreamWrite(FileOutputStream file, StringInfo dataToWrite) +{ + StringInfo fileBuffer = file.fileBuffer; + uint32 newBufferSize = fileBuffer->len + dataToWrite->len; + + appendBinaryStringInfo(fileBuffer, dataToWrite->data, dataToWrite->len); + + if (newBufferSize > FileBufferSizeInBytes) + { + FileOutputStreamFlush(file); + + resetStringInfo(fileBuffer); + } +} + + +/* Flushes data buffered in the file stream object to the underlying file. */ +static void +FileOutputStreamFlush(FileOutputStream file) +{ + StringInfo fileBuffer = file.fileBuffer; + int written = 0; + + errno = 0; + written = FileWrite(file.fileDescriptor, fileBuffer->data, fileBuffer->len); + if (written != fileBuffer->len) + { + ereport(ERROR, (errcode_for_file_access(), + errmsg("could not write %d bytes to partition file \"%s\"", + fileBuffer->len, file.filePath->data))); + } +} + + +/* + * FilterAndPartitionTable executes a given SQL query, and iterates over query + * results in a read-only fashion. For each resulting row, the function applies + * the partitioning function and determines the partition identifier. Then, the + * function chooses the partition file corresponding to this identifier, and + * serializes the row into this file using the copy command's text format. + */ +static void +FilterAndPartitionTable(const char *filterQuery, + const char *partitionColumnName, Oid partitionColumnType, + uint32 (*PartitionIdFunction) (Datum, const void *), + const void *partitionIdContext, + FileOutputStream *partitionFileArray, + uint32 fileCount) +{ + PartialCopyState rowOutputState = NULL; + FmgrInfo *columnOutputFunctions = NULL; + int partitionColumnIndex = 0; + Oid partitionColumnTypeId = InvalidOid; + Portal queryPortal = NULL; + int connected = 0; + int finished = 0; + + const char *noPortalName = NULL; + const bool readOnly = true; + const bool fetchForward = true; + const int noCursorOptions = 0; + const int prefetchCount = ROW_PREFETCH_COUNT; + + connected = SPI_connect(); + if (connected != SPI_OK_CONNECT) + { + ereport(ERROR, (errmsg("could not connect to SPI manager"))); + } + + queryPortal = SPI_cursor_open_with_args(noPortalName, filterQuery, + 0, NULL, NULL, NULL, /* no arguments */ + readOnly, noCursorOptions); + if (queryPortal == NULL) + { + ereport(ERROR, (errmsg("could not open implicit cursor for query \"%s\"", + filterQuery))); + } + + rowOutputState = InitRowOutputState(); + + SPI_cursor_fetch(queryPortal, fetchForward, prefetchCount); + if (SPI_processed > 0) + { + TupleDesc rowDescriptor = SPI_tuptable->tupdesc; + partitionColumnIndex = ColumnIndex(rowDescriptor, partitionColumnName); + + partitionColumnTypeId = SPI_gettypeid(rowDescriptor, partitionColumnIndex); + if (partitionColumnType != partitionColumnTypeId) + { + ereport(ERROR, (errmsg("partition column types %u and %u do not match", + partitionColumnTypeId, partitionColumnType))); + } + + columnOutputFunctions = ColumnOutputFunctions(rowDescriptor, + rowOutputState->binary); + } + + if (BinaryWorkerCopyFormat) + { + OutputBinaryHeaders(partitionFileArray, fileCount); + } + + while (SPI_processed > 0) + { + int rowIndex = 0; + for (rowIndex = 0; rowIndex < SPI_processed; rowIndex++) + { + HeapTuple row = SPI_tuptable->vals[rowIndex]; + TupleDesc rowDescriptor = SPI_tuptable->tupdesc; + FileOutputStream partitionFile = { 0, 0, 0 }; + StringInfo rowText = NULL; + Datum partitionKey = 0; + bool partitionKeyNull = false; + uint32 partitionId = 0; + + partitionKey = SPI_getbinval(row, rowDescriptor, + partitionColumnIndex, &partitionKeyNull); + + /* + * If we have a partition key, we compute its bucket. Else if we have + * a null key, we then put this tuple into the 0th bucket. Note that + * the 0th bucket may hold other tuples as well, such as tuples whose + * partition keys hash to the value 0. + */ + if (!partitionKeyNull) + { + partitionId = (*PartitionIdFunction) (partitionKey, partitionIdContext); + } + else + { + partitionId = 0; + } + + OutputRow(row, rowDescriptor, rowOutputState, columnOutputFunctions); + rowText = rowOutputState->fe_msgbuf; + + partitionFile = partitionFileArray[partitionId]; + FileOutputStreamWrite(partitionFile, rowText); + + resetStringInfo(rowText); + } + + SPI_freetuptable(SPI_tuptable); + + SPI_cursor_fetch(queryPortal, fetchForward, prefetchCount); + } + + SPI_cursor_close(queryPortal); + + if (BinaryWorkerCopyFormat) + { + OutputBinaryFooters(partitionFileArray, fileCount); + } + + /* delete row output memory context */ + ClearRowOutputState(rowOutputState); + + finished = SPI_finish(); + if (finished != SPI_OK_FINISH) + { + ereport(ERROR, (errmsg("could not disconnect from SPI manager"))); + } +} + + +/* + * Determines the column number for the given column name. The column number + * count starts at 1. + */ +static int +ColumnIndex(TupleDesc rowDescriptor, const char *columnName) +{ + int columnIndex = SPI_fnumber(rowDescriptor, columnName); + if (columnIndex == SPI_ERROR_NOATTRIBUTE) + { + ereport(ERROR, (errcode(ERRCODE_UNDEFINED_COLUMN), + errmsg("could not find column name \"%s\"", columnName))); + } + + Assert(columnIndex >= 1); + return columnIndex; +} + + +/* + * ColumnOutputFunctions walks over a table's columns, and finds each column's + * type information. The function then resolves each type's output function, + * and stores and returns these output functions in an array. + */ +static FmgrInfo * +ColumnOutputFunctions(TupleDesc rowDescriptor, bool binaryFormat) +{ + uint32 columnCount = (uint32) rowDescriptor->natts; + FmgrInfo *columnOutputFunctions = palloc0(columnCount * sizeof(FmgrInfo)); + + uint32 columnIndex = 0; + for (columnIndex = 0; columnIndex < columnCount; columnIndex++) + { + FmgrInfo *currentOutputFunction = &columnOutputFunctions[columnIndex]; + Form_pg_attribute currentColumn = rowDescriptor->attrs[columnIndex]; + Oid columnTypeId = currentColumn->atttypid; + Oid outputFunctionId = InvalidOid; + bool typeVariableLength = false; + + if (binaryFormat) + { + getTypeBinaryOutputInfo(columnTypeId, &outputFunctionId, &typeVariableLength); + } + else + { + getTypeOutputInfo(columnTypeId, &outputFunctionId, &typeVariableLength); + } + + Assert(currentColumn->attisdropped == false); + + fmgr_info(outputFunctionId, currentOutputFunction); + } + + return columnOutputFunctions; +} + + +/* + * InitRowOutputState creates and initializes a copy state object. This object + * is internal to the copy command's implementation in Postgres; and we refactor + * and refer to it here to avoid code duplication. We also only initialize the + * fields needed for writing row data to text files, and skip the other fields. + * + * Note that the default field values used in commands/copy.c and this function + * must match one another. Therefore, any changes to the default values in the + * copy command must be propagated to this function. + */ +static PartialCopyState +InitRowOutputState(void) +{ + PartialCopyState rowOutputState = + (PartialCopyState) palloc0(sizeof(PartialCopyStateData)); + + int fileEncoding = pg_get_client_encoding(); + int databaseEncoding = GetDatabaseEncoding(); + int databaseEncodingMaxLength = pg_database_encoding_max_length(); + + /* initialize defaults for printing null values */ + char *nullPrint = pstrdup("\\N"); + int nullPrintLen = strlen(nullPrint); + char *nullPrintClient = pg_server_to_any(nullPrint, nullPrintLen, fileEncoding); + + /* set default text output characters */ + rowOutputState->null_print = nullPrint; + rowOutputState->null_print_client = nullPrintClient; + rowOutputState->delim = pstrdup("\t"); + + rowOutputState->binary = BinaryWorkerCopyFormat; + + /* set encoding conversion information */ + rowOutputState->file_encoding = fileEncoding; + + if (PG_ENCODING_IS_CLIENT_ONLY(fileEncoding)) + { + ereport(ERROR, (errmsg("cannot repartition into encoding caller cannot " + "receive"))); + } + + /* set up transcoding information and default text output characters */ + if ( (fileEncoding != databaseEncoding) || (databaseEncodingMaxLength > 1) ) + { + rowOutputState->need_transcoding = true; + } + else + { + rowOutputState->need_transcoding = false; + } + + /* + * Create a temporary memory context that we can reset once per row to + * recover palloc'd memory. This avoids any problems with leaks inside data + * type output routines, and should be faster than retail pfree's anyway. + */ + rowOutputState->rowcontext = AllocSetContextCreate(CurrentMemoryContext, + "WorkerRowOutputContext", + ALLOCSET_DEFAULT_MINSIZE, + ALLOCSET_DEFAULT_INITSIZE, + ALLOCSET_DEFAULT_MAXSIZE); + + /* allocate the message buffer to use for serializing a row */ + rowOutputState->fe_msgbuf = makeStringInfo(); + + return rowOutputState; +} + + +/* Clears copy state used for outputting row data. */ +static void +ClearRowOutputState(PartialCopyState rowOutputState) +{ + Assert(rowOutputState != NULL); + + MemoryContextDelete(rowOutputState->rowcontext); + + FreeStringInfo(rowOutputState->fe_msgbuf); + + pfree(rowOutputState->null_print_client); + pfree(rowOutputState->delim); + + pfree(rowOutputState); +} + + +/* + * OutputRow serializes one row using the column output functions, + * and appends the data to the row output state object's message buffer. + * This function is modeled after the CopyOneRowTo() function in + * commands/copy.c, but only implements a subset of that functionality. + */ +static void +OutputRow(HeapTuple row, TupleDesc rowDescriptor, + PartialCopyState rowOutputState, FmgrInfo *columnOutputFunctions) +{ + MemoryContext oldContext = NULL; + uint32 columnIndex = 0; + + uint32 columnCount = (uint32) rowDescriptor->natts; + Datum *valueArray = (Datum *) palloc0(columnCount * sizeof(Datum)); + bool *isNullArray = (bool *) palloc0(columnCount * sizeof(bool)); + + /* deconstruct the tuple; this is faster than repeated heap_getattr */ + heap_deform_tuple(row, rowDescriptor, valueArray, isNullArray); + + /* reset previous tuple's output data, and the temporary memory context */ + resetStringInfo(rowOutputState->fe_msgbuf); + + MemoryContextReset(rowOutputState->rowcontext); + oldContext = MemoryContextSwitchTo(rowOutputState->rowcontext); + + if (rowOutputState->binary) + { + CopySendInt16(rowOutputState, rowDescriptor->natts); + } + + for (columnIndex = 0; columnIndex < columnCount; columnIndex++) + { + Datum value = valueArray[columnIndex]; + bool isNull = isNullArray[columnIndex]; + bool lastColumn = false; + + if (rowOutputState->binary) + { + if (!isNull) + { + FmgrInfo *outputFunctionPointer = &columnOutputFunctions[columnIndex]; + bytea *outputBytes = SendFunctionCall(outputFunctionPointer, value); + + CopySendInt32(rowOutputState, VARSIZE(outputBytes) - VARHDRSZ); + CopySendData(rowOutputState, VARDATA(outputBytes), + VARSIZE(outputBytes) - VARHDRSZ); + } + else + { + CopySendInt32(rowOutputState, -1); + } + } + else + { + if (!isNull) + { + FmgrInfo *outputFunctionPointer = &columnOutputFunctions[columnIndex]; + char *columnText = OutputFunctionCall(outputFunctionPointer, value); + + CopyAttributeOutText(rowOutputState, columnText); + } + else + { + CopySendString(rowOutputState, rowOutputState->null_print_client); + } + + lastColumn = ((columnIndex+1) == columnCount); + if (!lastColumn) + { + CopySendChar(rowOutputState, rowOutputState->delim[0]); + } + } + } + + if (!rowOutputState->binary) + { + /* append default line termination string depending on the platform */ +#ifndef WIN32 + CopySendChar(rowOutputState, '\n'); +#else + CopySendString(rowOutputState, "\r\n"); +#endif + } + + MemoryContextSwitchTo(oldContext); + + pfree(valueArray); + pfree(isNullArray); +} + + +/* + * Write the header of postgres' binary serialization format to each partition file. + * This function is used when binary_worker_copy_format is enabled. + */ +static void +OutputBinaryHeaders(FileOutputStream *partitionFileArray, uint32 fileCount) +{ + uint32 fileIndex = 0; + for (fileIndex = 0; fileIndex < fileCount; fileIndex++) + { + /* Generate header for a binary copy */ + const int32 zero = 0; + FileOutputStream partitionFile = {0, 0, 0}; + PartialCopyStateData headerOutputStateData; + PartialCopyState headerOutputState = (PartialCopyState) &headerOutputStateData; + + memset(headerOutputState, 0, sizeof(PartialCopyStateData)); + headerOutputState->fe_msgbuf = makeStringInfo(); + + /* Signature */ + CopySendData(headerOutputState, BinarySignature, 11); + + /* Flags field (no OIDs) */ + CopySendInt32(headerOutputState, zero); + + /* No header extension */ + CopySendInt32(headerOutputState, zero); + + partitionFile = partitionFileArray[fileIndex]; + FileOutputStreamWrite(partitionFile, headerOutputState->fe_msgbuf); + } +} + + +/* + * Write the footer of postgres' binary serialization format to each partition file. + * This function is used when binary_worker_copy_format is enabled. + */ +static void +OutputBinaryFooters(FileOutputStream *partitionFileArray, uint32 fileCount) +{ + uint32 fileIndex = 0; + for (fileIndex = 0; fileIndex < fileCount; fileIndex++) + { + /* Generate footer for a binary copy */ + int16 negative = -1; + FileOutputStream partitionFile = {0, 0, 0}; + PartialCopyStateData footerOutputStateData; + PartialCopyState footerOutputState = (PartialCopyState) &footerOutputStateData; + + memset(footerOutputState, 0, sizeof(PartialCopyStateData)); + footerOutputState->fe_msgbuf = makeStringInfo(); + + CopySendInt16(footerOutputState, negative); + + partitionFile = partitionFileArray[fileIndex]; + FileOutputStreamWrite(partitionFile, footerOutputState->fe_msgbuf); + } +} + + +/* Append data to the copy buffer in outputState */ +static void +CopySendData(PartialCopyState outputState, const void *databuf, int datasize) +{ + appendBinaryStringInfo(outputState->fe_msgbuf, databuf, datasize); +} + + +/* Append a striong to the copy buffer in outputState. */ +static void +CopySendString(PartialCopyState outputState, const char *str) +{ + appendBinaryStringInfo(outputState->fe_msgbuf, str, strlen(str)); +} + + +/* Append a char to the copy buffer in outputState. */ +static void +CopySendChar(PartialCopyState outputState, char c) +{ + appendStringInfoCharMacro(outputState->fe_msgbuf, c); +} + + +/* Append an int32 to the copy buffer in outputState. */ +static void +CopySendInt32(PartialCopyState outputState, int32 val) +{ + uint32 buf = htonl((uint32) val); + CopySendData(outputState, &buf, sizeof(buf)); +} + + +/* Append an int16 to the copy buffer in outputState. */ +static void +CopySendInt16(PartialCopyState outputState, int16 val) +{ + uint16 buf = htons((uint16) val); + CopySendData(outputState, &buf, sizeof(buf)); +} + + +/* + * Send text representation of one column, with conversion and escaping. + * + * NB: This function is based on commands/copy.c and doesn't fully conform to + * our coding style. The function should be kept in sync with copy.c. + */ +static void +CopyAttributeOutText(PartialCopyState cstate, char *string) +{ + char *pointer = NULL; + char *start = NULL; + char c = '\0'; + char delimc = cstate->delim[0]; + + if (cstate->need_transcoding) + { + pointer = pg_server_to_any(string, strlen(string), cstate->file_encoding); + } + else + { + pointer = string; + } + + /* + * We have to grovel through the string searching for control characters + * and instances of the delimiter character. In most cases, though, these + * are infrequent. To avoid overhead from calling CopySendData once per + * character, we dump out all characters between escaped characters in a + * single call. The loop invariant is that the data from "start" to "pointer" + * can be sent literally, but hasn't yet been. + * + * As all encodings here are safe, i.e. backend supported ones, we can + * skip doing pg_encoding_mblen(), because in valid backend encodings, + * extra bytes of a multibyte character never look like ASCII. + */ + start = pointer; + while ((c = *pointer) != '\0') + { + if ((unsigned char) c < (unsigned char) 0x20) + { + /* + * \r and \n must be escaped, the others are traditional. We + * prefer to dump these using the C-like notation, rather than + * a backslash and the literal character, because it makes the + * dump file a bit more proof against Microsoftish data + * mangling. + */ + switch (c) + { + case '\b': + c = 'b'; + break; + case '\f': + c = 'f'; + break; + case '\n': + c = 'n'; + break; + case '\r': + c = 'r'; + break; + case '\t': + c = 't'; + break; + case '\v': + c = 'v'; + break; + default: + /* If it's the delimiter, must backslash it */ + if (c == delimc) + break; + /* All ASCII control chars are length 1 */ + pointer++; + continue; /* fall to end of loop */ + } + /* if we get here, we need to convert the control char */ + CopyFlushOutput(cstate, start, pointer); + CopySendChar(cstate, '\\'); + CopySendChar(cstate, c); + start = ++pointer; /* do not include char in next run */ + } + else if (c == '\\' || c == delimc) + { + CopyFlushOutput(cstate, start, pointer); + CopySendChar(cstate, '\\'); + start = pointer++; /* we include char in next run */ + } + else + { + pointer++; + } + } + + CopyFlushOutput(cstate, start, pointer); +} + + +/* Helper function to send pending copy output */ +static inline void +CopyFlushOutput(PartialCopyState cstate, char *start, char *pointer) +{ + if (pointer > start) + { + CopySendData(cstate, start, pointer - start); + } +} + + +/* Helper function that invokes a function with the default collation oid. */ +Datum +CompareCall2(FmgrInfo *functionInfo, Datum leftArgument, Datum rightArgument) +{ + Datum result = FunctionCall2Coll(functionInfo, DEFAULT_COLLATION_OID, + leftArgument, rightArgument); + return result; +} + + +/* + * RangePartitionId determines the partition number for the given data value + * by applying range partitioning. More specifically, the function takes in a + * data value and an array of sorted split points, and performs a binary search + * within that array to determine the bucket the data value falls into. The + * function then returns that bucket number. + * + * Note that we employ a version of binary search known as upper_bound; this + * ensures that all null values fall into the zeroth bucket and that we maintain + * full compatibility with the semantics of Hadoop's TotalOrderPartitioner. + */ +static uint32 +RangePartitionId(Datum partitionValue, const void *context) +{ + RangePartitionContext *rangePartitionContext = (RangePartitionContext *) context; + FmgrInfo *comparisonFunction = rangePartitionContext->comparisonFunction; + Datum *pointArray = rangePartitionContext->splitPointArray; + int32 currentLength = rangePartitionContext->splitPointCount; + int32 halfLength = 0; + uint32 firstIndex = 0; + + /* + * We implement a binary search variant known as upper_bound. This variant + * gives us the semantics we need for partitioned joins; and is also used by + * Hadoop's TotalOrderPartitioner. To implement this variant, we rely on SGI + * STL v3.3's source code for upper_bound(). Note that elements in the point + * array cannot be null. + */ + while (currentLength > 0) + { + uint32 middleIndex = 0; + Datum middlePoint = 0; + Datum comparisonDatum = 0; + int comparisonResult = 0; + + halfLength = currentLength >> 1; + middleIndex = firstIndex; + middleIndex += halfLength; + + middlePoint = pointArray[middleIndex]; + + comparisonDatum = CompareCall2(comparisonFunction, partitionValue, middlePoint); + comparisonResult = DatumGetInt32(comparisonDatum); + + /* if partition value is less than middle point */ + if (comparisonResult < 0) + { + currentLength = halfLength; + } + else + { + firstIndex = middleIndex; + firstIndex++; + currentLength = currentLength - halfLength - 1; + } + } + + return firstIndex; +} + + +/* + * HashPartitionId determines the partition number for the given data value + * using hash partitioning. More specifically, the function returns zero if the + * given data value is null. If not, the function applies the standard Postgres + * hashing function for the given data type, and mods the hashed result with the + * number of partitions. The function then returns the modded number as the + * partition number. + * + * Note that any changes to PostgreSQL's hashing functions will reshuffle the + * entire distribution created by this function. For a discussion of this issue, + * see Google "PL/Proxy Users: Hash Functions Have Changed in PostgreSQL 8.4." + */ +static uint32 +HashPartitionId(Datum partitionValue, const void *context) +{ + HashPartitionContext *hashPartitionContext = (HashPartitionContext *) context; + FmgrInfo *hashFunction = hashPartitionContext->hashFunction; + uint32 partitionCount = hashPartitionContext->partitionCount; + Datum hashDatum = 0; + uint32 hashResult = 0; + uint32 hashPartitionId = 0; + + /* hash functions return unsigned 32-bit integers */ + hashDatum = FunctionCall1(hashFunction, partitionValue); + hashResult = DatumGetUInt32(hashDatum); + hashPartitionId = (hashResult % partitionCount); + + return hashPartitionId; +} diff --git a/src/bin/csql/.gitignore b/src/bin/csql/.gitignore new file mode 100644 index 000000000..ea0a3a77a --- /dev/null +++ b/src/bin/csql/.gitignore @@ -0,0 +1,2 @@ +/psqlscan.c +/csql diff --git a/src/bin/csql/Makefile b/src/bin/csql/Makefile new file mode 100644 index 000000000..cbfe7c01f --- /dev/null +++ b/src/bin/csql/Makefile @@ -0,0 +1,40 @@ +#------------------------------------------------------------------------- +# +# Makefile for src/bin/csql +# +# Portions Copyright (c) 1996-2014, PostgreSQL Global Development Group +# Portions Copyright (c) 1994, Regents of the University of California +# +# src/bin/csql/Makefile +# +#------------------------------------------------------------------------- + +citusdb_subdir = src/bin/csql +citusdb_top_builddir = ../../.. + +PROGRAM = csql + +PGFILEDESC = "csql - the CitusDB interactive terminal" +PGAPPICON=win32 + +OBJS =command.o common.o help.o input.o stringutils.o mainloop.o copy.o \ + copy_options.o stage.o \ + startup.o prompt.o variables.o large_obj.o print.o describe.o \ + tab-complete.o mbprint.o dumputils.o keywords.o kwlookup.o \ + sql_help.o \ + $(WIN32RES) + +PG_LIBS = $(libpq) + +include $(citusdb_top_builddir)/Makefile.global + +override CPPFLAGS += -I$(libpq_srcdir) -I$(top_srcdir)/src/bin/csql + +# psqlscan is compiled as part of mainloop +mainloop.o: psqlscan.c +psqlscan.c: FLEXFLAGS = -Cfe -p -p +psqlscan.c: FLEX_NO_BACKUP=yes + +clean: csql-clean +csql-clean: + rm -f csql$(X) $(OBJS) psqlscan.c lex.backup diff --git a/src/bin/csql/command.c b/src/bin/csql/command.c new file mode 100644 index 000000000..826ee3555 --- /dev/null +++ b/src/bin/csql/command.c @@ -0,0 +1,3282 @@ +/* + * psql - the PostgreSQL interactive terminal + * + * Copyright (c) 2000-2015, PostgreSQL Global Development Group + * + * src/bin/psql/command.c + */ +#include "postgres_fe.h" +#include "command.h" + +#ifdef __BORLANDC__ /* needed for BCC */ +#undef mkdir +#endif + +#include +#include +#ifdef HAVE_PWD_H +#include +#endif +#ifndef WIN32 +#include /* for umask() */ +#include /* for stat() */ +#include /* open() flags */ +#include /* for geteuid(), getpid(), stat() */ +#else +#include +#include +#include +#include +#include /* for umask() */ +#include /* for stat() */ +#endif + +#if (PG_VERSION_NUM >= 90400 && PG_VERSION_NUM < 90500) +#ifdef USE_SSL +#include +#endif /* USE_SSL */ +#endif /* (PG_VERSION_NUM >= 90400 && PG_VERSION_NUM < 90500) */ + +#include "portability/instr_time.h" + +#include "libpq-fe.h" +#include "pqexpbuffer.h" +#include "dumputils.h" + +#include "common.h" +#include "copy.h" +#include "describe.h" +#include "help.h" +#include "input.h" +#include "large_obj.h" +#include "mainloop.h" +#include "print.h" +#include "psqlscan.h" +#include "settings.h" +#include "stage.h" +#include "variables.h" + + +/* functions for use in this file */ +static backslashResult exec_command(const char *cmd, + PsqlScanState scan_state, + PQExpBuffer query_buf); +static bool do_edit(const char *filename_arg, PQExpBuffer query_buf, + int lineno, bool *edited); +static bool do_connect(char *dbname, char *user, char *host, char *port); +static bool do_shell(const char *command); +static bool do_watch(PQExpBuffer query_buf, long sleep); +static bool lookup_function_oid(const char *desc, Oid *foid); +static bool get_create_function_cmd(Oid oid, PQExpBuffer buf); +static int strip_lineno_from_funcdesc(char *func); +static void minimal_error_message(PGresult *res); + +static void printSSLInfo(void); +static bool printPsetInfo(const char *param, struct printQueryOpt *popt); +static char *pset_value_string(const char *param, struct printQueryOpt *popt); + +#ifdef WIN32 +static void checkWin32Codepage(void); +#endif + + + +/*---------- + * HandleSlashCmds: + * + * Handles all the different commands that start with '\'. + * Ordinarily called by MainLoop(). + * + * scan_state is a lexer working state that is set to continue scanning + * just after the '\'. The lexer is advanced past the command and all + * arguments on return. + * + * 'query_buf' contains the query-so-far, which may be modified by + * execution of the backslash command (for example, \r clears it). + * query_buf can be NULL if there is no query so far. + * + * Returns a status code indicating what action is desired, see command.h. + *---------- + */ + +backslashResult +HandleSlashCmds(PsqlScanState scan_state, + PQExpBuffer query_buf) +{ + backslashResult status = PSQL_CMD_SKIP_LINE; + char *cmd; + char *arg; + + Assert(scan_state != NULL); + + /* Parse off the command name */ + cmd = psql_scan_slash_command(scan_state); + + /* And try to execute it */ + status = exec_command(cmd, scan_state, query_buf); + + if (status == PSQL_CMD_UNKNOWN) + { + if (pset.cur_cmd_interactive) + psql_error("Invalid command \\%s. Try \\? for help.\n", cmd); + else + psql_error("invalid command \\%s\n", cmd); + status = PSQL_CMD_ERROR; + } + + if (status != PSQL_CMD_ERROR) + { + /* eat any remaining arguments after a valid command */ + /* note we suppress evaluation of backticks here */ + while ((arg = psql_scan_slash_option(scan_state, + OT_NO_EVAL, NULL, false))) + { + psql_error("\\%s: extra argument \"%s\" ignored\n", cmd, arg); + free(arg); + } + } + else + { + /* silently throw away rest of line after an erroneous command */ + while ((arg = psql_scan_slash_option(scan_state, + OT_WHOLE_LINE, NULL, false))) + free(arg); + } + + /* if there is a trailing \\, swallow it */ + psql_scan_slash_command_end(scan_state); + + free(cmd); + + /* some commands write to queryFout, so make sure output is sent */ + fflush(pset.queryFout); + + return status; +} + +/* + * Read and interpret an argument to the \connect slash command. + */ +static char * +read_connect_arg(PsqlScanState scan_state) +{ + char *result; + char quote; + + /* + * Ideally we should treat the arguments as SQL identifiers. But for + * backwards compatibility with 7.2 and older pg_dump files, we have to + * take unquoted arguments verbatim (don't downcase them). For now, + * double-quoted arguments may be stripped of double quotes (as if SQL + * identifiers). By 7.4 or so, pg_dump files can be expected to + * double-quote all mixed-case \connect arguments, and then we can get rid + * of OT_SQLIDHACK. + */ + result = psql_scan_slash_option(scan_state, OT_SQLIDHACK, "e, true); + + if (!result) + return NULL; + + if (quote) + return result; + + if (*result == '\0' || strcmp(result, "-") == 0) + return NULL; + + return result; +} + + +/* + * Subroutine to actually try to execute a backslash command. + */ +static backslashResult +exec_command(const char *cmd, + PsqlScanState scan_state, + PQExpBuffer query_buf) +{ + bool success = true; /* indicate here if the command ran ok or + * failed */ + backslashResult status = PSQL_CMD_SKIP_LINE; + + /* + * \a -- toggle field alignment This makes little sense but we keep it + * around. + */ + if (strcmp(cmd, "a") == 0) + { + if (pset.popt.topt.format != PRINT_ALIGNED) + success = do_pset("format", "aligned", &pset.popt, pset.quiet); + else + success = do_pset("format", "unaligned", &pset.popt, pset.quiet); + } + + /* \C -- override table title (formerly change HTML caption) */ + else if (strcmp(cmd, "C") == 0) + { + char *opt = psql_scan_slash_option(scan_state, + OT_NORMAL, NULL, true); + + success = do_pset("title", opt, &pset.popt, pset.quiet); + free(opt); + } + + /* + * \c or \connect -- connect to database using the specified parameters. + * + * \c dbname user host port + * + * If any of these parameters are omitted or specified as '-', the current + * value of the parameter will be used instead. If the parameter has no + * current value, the default value for that parameter will be used. Some + * examples: + * + * \c - - hst Connect to current database on current port of host + * "hst" as current user. \c - usr - prt Connect to current database on + * "prt" port of current host as user "usr". \c dbs Connect to + * "dbs" database on current port of current host as current user. + */ + else if (strcmp(cmd, "c") == 0 || strcmp(cmd, "connect") == 0) + { + char *opt1, + *opt2, + *opt3, + *opt4; + + opt1 = read_connect_arg(scan_state); + opt2 = read_connect_arg(scan_state); + opt3 = read_connect_arg(scan_state); + opt4 = read_connect_arg(scan_state); + + success = do_connect(opt1, opt2, opt3, opt4); + + free(opt1); + free(opt2); + free(opt3); + free(opt4); + } + + /* \cd */ + else if (strcmp(cmd, "cd") == 0) + { + char *opt = psql_scan_slash_option(scan_state, + OT_NORMAL, NULL, true); + char *dir; + + if (opt) + dir = opt; + else + { +#ifndef WIN32 + struct passwd *pw; + uid_t user_id = geteuid(); + + errno = 0; /* clear errno before call */ + pw = getpwuid(user_id); + if (!pw) + { + psql_error("could not get home directory for user ID %ld: %s\n", + (long) user_id, + errno ? strerror(errno) : _("user does not exist")); + exit(EXIT_FAILURE); + } + dir = pw->pw_dir; +#else /* WIN32 */ + + /* + * On Windows, 'cd' without arguments prints the current + * directory, so if someone wants to code this here instead... + */ + dir = "/"; +#endif /* WIN32 */ + } + + if (chdir(dir) == -1) + { + psql_error("\\%s: could not change directory to \"%s\": %s\n", + cmd, dir, strerror(errno)); + success = false; + } + + if (opt) + free(opt); + } + + /* \conninfo -- display information about the current connection */ + else if (strcmp(cmd, "conninfo") == 0) + { + char *db = PQdb(pset.db); + + if (db == NULL) + printf(_("You are currently not connected to a database.\n")); + else + { + char *host; + PQconninfoOption *connOptions; + PQconninfoOption *option; + + host = PQhost(pset.db); + if (host == NULL) + host = DEFAULT_PGSOCKET_DIR; + /* A usable "hostaddr" overrides the basic sense of host. */ + connOptions = PQconninfo(pset.db); + if (connOptions == NULL) + { + psql_error("out of memory\n"); + exit(EXIT_FAILURE); + } + for (option = connOptions; option && option->keyword; option++) + if (strcmp(option->keyword, "hostaddr") == 0) + { + if (option->val != NULL && option->val[0] != '\0') + host = option->val; + break; + } + + /* If the host is an absolute path, the connection is via socket */ + if (is_absolute_path(host)) + printf(_("You are connected to database \"%s\" as user \"%s\" via socket in \"%s\" at port \"%s\".\n"), + db, PQuser(pset.db), host, PQport(pset.db)); + else + printf(_("You are connected to database \"%s\" as user \"%s\" on host \"%s\" at port \"%s\".\n"), + db, PQuser(pset.db), host, PQport(pset.db)); + printSSLInfo(); + + PQconninfoFree(connOptions); + } + } + + /* \copy */ + else if (pg_strcasecmp(cmd, "copy") == 0) + { + char *opt = psql_scan_slash_option(scan_state, + OT_WHOLE_LINE, NULL, false); + + success = do_copy(opt); + free(opt); + } + + /* \copyright */ + else if (strcmp(cmd, "copyright") == 0) + print_copyright(); + + /* \d* commands */ + else if (cmd[0] == 'd') + { + char *pattern; + bool show_verbose, + show_system; + + /* We don't do SQLID reduction on the pattern yet */ + pattern = psql_scan_slash_option(scan_state, + OT_NORMAL, NULL, true); + + show_verbose = strchr(cmd, '+') ? true : false; + show_system = strchr(cmd, 'S') ? true : false; + + switch (cmd[1]) + { + case '\0': + case '+': + case 'S': + if (pattern) + success = describeTableDetails(pattern, show_verbose, show_system); + else + /* standard listing of interesting things */ + success = listTables("tvmsE", NULL, show_verbose, show_system); + break; + case 'a': + success = describeAggregates(pattern, show_verbose, show_system); + break; + case 'b': + success = describeTablespaces(pattern, show_verbose); + break; + case 'c': + success = listConversions(pattern, show_verbose, show_system); + break; + case 'C': + success = listCasts(pattern, show_verbose); + break; + case 'd': + if (strncmp(cmd, "ddp", 3) == 0) + success = listDefaultACLs(pattern); + else + success = objectDescription(pattern, show_system); + break; + case 'D': + success = listDomains(pattern, show_verbose, show_system); + break; + case 'f': /* function subsystem */ + switch (cmd[2]) + { + case '\0': + case '+': + case 'S': + case 'a': + case 'n': + case 't': + case 'w': + success = describeFunctions(&cmd[2], pattern, show_verbose, show_system); + break; + default: + status = PSQL_CMD_UNKNOWN; + break; + } + break; + case 'g': + /* no longer distinct from \du */ + success = describeRoles(pattern, show_verbose); + break; + case 'l': + success = do_lo_list(); + break; + case 'L': + success = listLanguages(pattern, show_verbose, show_system); + break; + case 'n': + success = listSchemas(pattern, show_verbose, show_system); + break; + case 'o': + success = describeOperators(pattern, show_verbose, show_system); + break; + case 'O': + success = listCollations(pattern, show_verbose, show_system); + break; + case 'p': + success = permissionsList(pattern); + break; + case 'T': + success = describeTypes(pattern, show_verbose, show_system); + break; + case 't': + case 'v': + case 'm': + case 'i': + case 's': + case 'E': + success = listTables(&cmd[1], pattern, show_verbose, show_system); + break; + case 'r': + if (cmd[2] == 'd' && cmd[3] == 's') + { + char *pattern2 = NULL; + + if (pattern) + pattern2 = psql_scan_slash_option(scan_state, + OT_NORMAL, NULL, true); + success = listDbRoleSettings(pattern, pattern2); + } + else + success = PSQL_CMD_UNKNOWN; + break; + case 'u': + success = describeRoles(pattern, show_verbose); + break; + case 'F': /* text search subsystem */ + switch (cmd[2]) + { + case '\0': + case '+': + success = listTSConfigs(pattern, show_verbose); + break; + case 'p': + success = listTSParsers(pattern, show_verbose); + break; + case 'd': + success = listTSDictionaries(pattern, show_verbose); + break; + case 't': + success = listTSTemplates(pattern, show_verbose); + break; + default: + status = PSQL_CMD_UNKNOWN; + break; + } + break; + case 'e': /* SQL/MED subsystem */ + switch (cmd[2]) + { + case 's': + success = listForeignServers(pattern, show_verbose); + break; + case 'u': + success = listUserMappings(pattern, show_verbose); + break; + case 'w': + success = listForeignDataWrappers(pattern, show_verbose); + break; + case 't': + success = listForeignTables(pattern, show_verbose); + break; + default: + status = PSQL_CMD_UNKNOWN; + break; + } + break; + case 'x': /* Extensions */ + if (show_verbose) + success = listExtensionContents(pattern); + else + success = listExtensions(pattern); + break; + case 'y': /* Event Triggers */ + success = listEventTriggers(pattern, show_verbose); + break; + default: + status = PSQL_CMD_UNKNOWN; + } + + if (pattern) + free(pattern); + } + + + /* + * \e or \edit -- edit the current query buffer, or edit a file and make + * it the query buffer + */ + else if (strcmp(cmd, "e") == 0 || strcmp(cmd, "edit") == 0) + { + if (!query_buf) + { + psql_error("no query buffer\n"); + status = PSQL_CMD_ERROR; + } + else + { + char *fname; + char *ln = NULL; + int lineno = -1; + + fname = psql_scan_slash_option(scan_state, + OT_NORMAL, NULL, true); + if (fname) + { + /* try to get separate lineno arg */ + ln = psql_scan_slash_option(scan_state, + OT_NORMAL, NULL, true); + if (ln == NULL) + { + /* only one arg; maybe it is lineno not fname */ + if (fname[0] && + strspn(fname, "0123456789") == strlen(fname)) + { + /* all digits, so assume it is lineno */ + ln = fname; + fname = NULL; + } + } + } + if (ln) + { + lineno = atoi(ln); + if (lineno < 1) + { + psql_error("invalid line number: %s\n", ln); + status = PSQL_CMD_ERROR; + } + } + if (status != PSQL_CMD_ERROR) + { + expand_tilde(&fname); + if (fname) + canonicalize_path(fname); + if (do_edit(fname, query_buf, lineno, NULL)) + status = PSQL_CMD_NEWEDIT; + else + status = PSQL_CMD_ERROR; + } + if (fname) + free(fname); + if (ln) + free(ln); + } + } + + /* + * \ef -- edit the named function, or present a blank CREATE FUNCTION + * template if no argument is given + */ + else if (strcmp(cmd, "ef") == 0) + { + int lineno = -1; + + if (pset.sversion < 80400) + { + psql_error("The server (version %d.%d) does not support editing function source.\n", + pset.sversion / 10000, (pset.sversion / 100) % 100); + status = PSQL_CMD_ERROR; + } + else if (!query_buf) + { + psql_error("no query buffer\n"); + status = PSQL_CMD_ERROR; + } + else + { + char *func; + Oid foid = InvalidOid; + + func = psql_scan_slash_option(scan_state, + OT_WHOLE_LINE, NULL, true); + lineno = strip_lineno_from_funcdesc(func); + if (lineno == 0) + { + /* error already reported */ + status = PSQL_CMD_ERROR; + } + else if (!func) + { + /* set up an empty command to fill in */ + printfPQExpBuffer(query_buf, + "CREATE FUNCTION ( )\n" + " RETURNS \n" + " LANGUAGE \n" + " -- common options: IMMUTABLE STABLE STRICT SECURITY DEFINER\n" + "AS $function$\n" + "\n$function$\n"); + } + else if (!lookup_function_oid(func, &foid)) + { + /* error already reported */ + status = PSQL_CMD_ERROR; + } + else if (!get_create_function_cmd(foid, query_buf)) + { + /* error already reported */ + status = PSQL_CMD_ERROR; + } + else if (lineno > 0) + { + /* + * lineno "1" should correspond to the first line of the + * function body. We expect that pg_get_functiondef() will + * emit that on a line beginning with "AS ", and that there + * can be no such line before the real start of the function + * body. Increment lineno by the number of lines before that + * line, so that it becomes relative to the first line of the + * function definition. + */ + const char *lines = query_buf->data; + + while (*lines != '\0') + { + if (strncmp(lines, "AS ", 3) == 0) + break; + lineno++; + /* find start of next line */ + lines = strchr(lines, '\n'); + if (!lines) + break; + lines++; + } + } + + if (func) + free(func); + } + + if (status != PSQL_CMD_ERROR) + { + bool edited = false; + + if (!do_edit(NULL, query_buf, lineno, &edited)) + status = PSQL_CMD_ERROR; + else if (!edited) + puts(_("No changes")); + else + status = PSQL_CMD_NEWEDIT; + } + } + + /* \echo and \qecho */ + else if (strcmp(cmd, "echo") == 0 || strcmp(cmd, "qecho") == 0) + { + char *value; + char quoted; + bool no_newline = false; + bool first = true; + FILE *fout; + + if (strcmp(cmd, "qecho") == 0) + fout = pset.queryFout; + else + fout = stdout; + + while ((value = psql_scan_slash_option(scan_state, + OT_NORMAL, "ed, false))) + { + if (!quoted && strcmp(value, "-n") == 0) + no_newline = true; + else + { + if (first) + first = false; + else + fputc(' ', fout); + fputs(value, fout); + } + free(value); + } + if (!no_newline) + fputs("\n", fout); + } + + /* \encoding -- set/show client side encoding */ + else if (strcmp(cmd, "encoding") == 0) + { + char *encoding = psql_scan_slash_option(scan_state, + OT_NORMAL, NULL, false); + + if (!encoding) + { + /* show encoding */ + puts(pg_encoding_to_char(pset.encoding)); + } + else + { + /* set encoding */ + if (PQsetClientEncoding(pset.db, encoding) == -1) + psql_error("%s: invalid encoding name or conversion procedure not found\n", encoding); + else + { + /* save encoding info into psql internal data */ + pset.encoding = PQclientEncoding(pset.db); + pset.popt.topt.encoding = pset.encoding; + SetVariable(pset.vars, "ENCODING", + pg_encoding_to_char(pset.encoding)); + } + free(encoding); + } + } + + /* \f -- change field separator */ + else if (strcmp(cmd, "f") == 0) + { + char *fname = psql_scan_slash_option(scan_state, + OT_NORMAL, NULL, false); + + success = do_pset("fieldsep", fname, &pset.popt, pset.quiet); + free(fname); + } + + /* \g [filename] -- send query, optionally with output to file/pipe */ + else if (strcmp(cmd, "g") == 0) + { + char *fname = psql_scan_slash_option(scan_state, + OT_FILEPIPE, NULL, false); + + if (!fname) + pset.gfname = NULL; + else + { + expand_tilde(&fname); + pset.gfname = pg_strdup(fname); + } + free(fname); + status = PSQL_CMD_SEND; + } + + /* \gset [prefix] -- send query and store result into variables */ + else if (strcmp(cmd, "gset") == 0) + { + char *prefix = psql_scan_slash_option(scan_state, + OT_NORMAL, NULL, false); + + if (prefix) + pset.gset_prefix = prefix; + else + { + /* we must set a non-NULL prefix to trigger storing */ + pset.gset_prefix = pg_strdup(""); + } + /* gset_prefix is freed later */ + status = PSQL_CMD_SEND; + } + + /* help */ + else if (strcmp(cmd, "h") == 0 || strcmp(cmd, "help") == 0) + { + char *opt = psql_scan_slash_option(scan_state, + OT_WHOLE_LINE, NULL, false); + size_t len; + + /* strip any trailing spaces and semicolons */ + if (opt) + { + len = strlen(opt); + while (len > 0 && + (isspace((unsigned char) opt[len - 1]) + || opt[len - 1] == ';')) + opt[--len] = '\0'; + } + + helpSQL(opt, pset.popt.topt.pager); + free(opt); + } + + /* HTML mode */ + else if (strcmp(cmd, "H") == 0 || strcmp(cmd, "html") == 0) + { + if (pset.popt.topt.format != PRINT_HTML) + success = do_pset("format", "html", &pset.popt, pset.quiet); + else + success = do_pset("format", "aligned", &pset.popt, pset.quiet); + } + + + /* \i and \ir include files */ + else if (strcmp(cmd, "i") == 0 || strcmp(cmd, "include") == 0 + || strcmp(cmd, "ir") == 0 || strcmp(cmd, "include_relative") == 0) + { + char *fname = psql_scan_slash_option(scan_state, + OT_NORMAL, NULL, true); + + if (!fname) + { + psql_error("\\%s: missing required argument\n", cmd); + success = false; + } + else + { + bool include_relative; + + include_relative = (strcmp(cmd, "ir") == 0 + || strcmp(cmd, "include_relative") == 0); + expand_tilde(&fname); + success = (process_file(fname, false, include_relative) == EXIT_SUCCESS); + free(fname); + } + } + + /* \l is list databases */ + else if (strcmp(cmd, "l") == 0 || strcmp(cmd, "list") == 0 || + strcmp(cmd, "l+") == 0 || strcmp(cmd, "list+") == 0) + { + char *pattern; + bool show_verbose; + + pattern = psql_scan_slash_option(scan_state, + OT_NORMAL, NULL, true); + + show_verbose = strchr(cmd, '+') ? true : false; + + success = listAllDbs(pattern, show_verbose); + + if (pattern) + free(pattern); + } + + /* + * large object things + */ + else if (strncmp(cmd, "lo_", 3) == 0) + { + char *opt1, + *opt2; + + opt1 = psql_scan_slash_option(scan_state, + OT_NORMAL, NULL, true); + opt2 = psql_scan_slash_option(scan_state, + OT_NORMAL, NULL, true); + + if (strcmp(cmd + 3, "export") == 0) + { + if (!opt2) + { + psql_error("\\%s: missing required argument\n", cmd); + success = false; + } + else + { + expand_tilde(&opt2); + success = do_lo_export(opt1, opt2); + } + } + + else if (strcmp(cmd + 3, "import") == 0) + { + if (!opt1) + { + psql_error("\\%s: missing required argument\n", cmd); + success = false; + } + else + { + expand_tilde(&opt1); + success = do_lo_import(opt1, opt2); + } + } + + else if (strcmp(cmd + 3, "list") == 0) + success = do_lo_list(); + + else if (strcmp(cmd + 3, "unlink") == 0) + { + if (!opt1) + { + psql_error("\\%s: missing required argument\n", cmd); + success = false; + } + else + success = do_lo_unlink(opt1); + } + + else + status = PSQL_CMD_UNKNOWN; + + free(opt1); + free(opt2); + } + + + /* \o -- set query output */ + else if (strcmp(cmd, "o") == 0 || strcmp(cmd, "out") == 0) + { + char *fname = psql_scan_slash_option(scan_state, + OT_FILEPIPE, NULL, true); + + expand_tilde(&fname); + success = setQFout(fname); + free(fname); + } + + /* \p prints the current query buffer */ + else if (strcmp(cmd, "p") == 0 || strcmp(cmd, "print") == 0) + { + if (query_buf && query_buf->len > 0) + puts(query_buf->data); + else if (!pset.quiet) + puts(_("Query buffer is empty.")); + fflush(stdout); + } + + /* \password -- set user password */ + else if (strcmp(cmd, "password") == 0) + { + char *pw1; + char *pw2; + + pw1 = simple_prompt("Enter new password: ", 100, false); + pw2 = simple_prompt("Enter it again: ", 100, false); + + if (strcmp(pw1, pw2) != 0) + { + psql_error("Passwords didn't match.\n"); + success = false; + } + else + { + char *opt0 = psql_scan_slash_option(scan_state, OT_SQLID, NULL, true); + char *user; + char *encrypted_password; + + if (opt0) + user = opt0; + else + user = PQuser(pset.db); + + encrypted_password = PQencryptPassword(pw1, user); + + if (!encrypted_password) + { + psql_error("Password encryption failed.\n"); + success = false; + } + else + { + PQExpBufferData buf; + PGresult *res; + + initPQExpBuffer(&buf); + printfPQExpBuffer(&buf, "ALTER USER %s PASSWORD ", + fmtId(user)); + appendStringLiteralConn(&buf, encrypted_password, pset.db); + res = PSQLexec(buf.data); + termPQExpBuffer(&buf); + if (!res) + success = false; + else + PQclear(res); + PQfreemem(encrypted_password); + } + + if (opt0) + free(opt0); + } + + free(pw1); + free(pw2); + } + + /* \prompt -- prompt and set variable */ + else if (strcmp(cmd, "prompt") == 0) + { + char *opt, + *prompt_text = NULL; + char *arg1, + *arg2; + + arg1 = psql_scan_slash_option(scan_state, OT_NORMAL, NULL, false); + arg2 = psql_scan_slash_option(scan_state, OT_NORMAL, NULL, false); + + if (!arg1) + { + psql_error("\\%s: missing required argument\n", cmd); + success = false; + } + else + { + char *result; + + if (arg2) + { + prompt_text = arg1; + opt = arg2; + } + else + opt = arg1; + + if (!pset.inputfile) + result = simple_prompt(prompt_text, 4096, true); + else + { + if (prompt_text) + { + fputs(prompt_text, stdout); + fflush(stdout); + } + result = gets_fromFile(stdin); + } + + if (!SetVariable(pset.vars, opt, result)) + { + psql_error("\\%s: error while setting variable\n", cmd); + success = false; + } + + free(result); + if (prompt_text) + free(prompt_text); + free(opt); + } + } + + /* \pset -- set printing parameters */ + else if (strcmp(cmd, "pset") == 0) + { + char *opt0 = psql_scan_slash_option(scan_state, + OT_NORMAL, NULL, false); + char *opt1 = psql_scan_slash_option(scan_state, + OT_NORMAL, NULL, false); + + if (!opt0) + { + /* list all variables */ + + int i; + static const char *const my_list[] = { + "border", "columns", "expanded", "fieldsep", "fieldsep_zero", + "footer", "format", "linestyle", "null", + "numericlocale", "pager", "pager_min_lines", + "recordsep", "recordsep_zero", + "tableattr", "title", "tuples_only", + "unicode_border_linestyle", + "unicode_column_linestyle", + "unicode_header_linestyle", + NULL + }; + + for (i = 0; my_list[i] != NULL; i++) + { + char *val = pset_value_string(my_list[i], &pset.popt); + + printf("%-24s %s\n", my_list[i], val); + free(val); + } + + success = true; + } + else + success = do_pset(opt0, opt1, &pset.popt, pset.quiet); + + free(opt0); + free(opt1); + } + + /* \q or \quit */ + else if (strcmp(cmd, "q") == 0 || strcmp(cmd, "quit") == 0) + status = PSQL_CMD_TERMINATE; + + /* reset(clear) the buffer */ + else if (strcmp(cmd, "r") == 0 || strcmp(cmd, "reset") == 0) + { + resetPQExpBuffer(query_buf); + psql_scan_reset(scan_state); + if (!pset.quiet) + puts(_("Query buffer reset (cleared).")); + } + + /* \s save history in a file or show it on the screen */ + else if (strcmp(cmd, "s") == 0) + { + char *fname = psql_scan_slash_option(scan_state, + OT_NORMAL, NULL, true); + + expand_tilde(&fname); + success = printHistory(fname, pset.popt.topt.pager); + if (success && !pset.quiet && fname) + printf(_("Wrote history to file \"%s\".\n"), fname); + if (!fname) + putchar('\n'); + free(fname); + } + + /* \set -- generalized set variable/option command */ + else if (strcmp(cmd, "set") == 0) + { + char *opt0 = psql_scan_slash_option(scan_state, + OT_NORMAL, NULL, false); + + if (!opt0) + { + /* list all variables */ + PrintVariables(pset.vars); + success = true; + } + else + { + /* + * Set variable to the concatenation of the arguments. + */ + char *newval; + char *opt; + + opt = psql_scan_slash_option(scan_state, + OT_NORMAL, NULL, false); + newval = pg_strdup(opt ? opt : ""); + free(opt); + + while ((opt = psql_scan_slash_option(scan_state, + OT_NORMAL, NULL, false))) + { + newval = pg_realloc(newval, strlen(newval) + strlen(opt) + 1); + strcat(newval, opt); + free(opt); + } + + if (!SetVariable(pset.vars, opt0, newval)) + { + psql_error("\\%s: error while setting variable\n", cmd); + success = false; + } + free(newval); + } + free(opt0); + } + + + /* \setenv -- set environment command */ + else if (strcmp(cmd, "setenv") == 0) + { + char *envvar = psql_scan_slash_option(scan_state, + OT_NORMAL, NULL, false); + char *envval = psql_scan_slash_option(scan_state, + OT_NORMAL, NULL, false); + + if (!envvar) + { + psql_error("\\%s: missing required argument\n", cmd); + success = false; + } + else if (strchr(envvar, '=') != NULL) + { + psql_error("\\%s: environment variable name must not contain \"=\"\n", + cmd); + success = false; + } + else if (!envval) + { + /* No argument - unset the environment variable */ + unsetenv(envvar); + success = true; + } + else + { + /* Set variable to the value of the next argument */ + char *newval; + + newval = psprintf("%s=%s", envvar, envval); + putenv(newval); + success = true; + + /* + * Do not free newval here, it will screw up the environment if + * you do. See putenv man page for details. That means we leak a + * bit of memory here, but not enough to worry about. + */ + } + free(envvar); + free(envval); + } + + /* \sf -- show a function's source code */ + else if (strcmp(cmd, "sf") == 0 || strcmp(cmd, "sf+") == 0) + { + bool show_linenumbers = (strcmp(cmd, "sf+") == 0); + PQExpBuffer func_buf; + char *func; + Oid foid = InvalidOid; + + func_buf = createPQExpBuffer(); + func = psql_scan_slash_option(scan_state, + OT_WHOLE_LINE, NULL, true); + if (pset.sversion < 80400) + { + psql_error("The server (version %d.%d) does not support showing function source.\n", + pset.sversion / 10000, (pset.sversion / 100) % 100); + status = PSQL_CMD_ERROR; + } + else if (!func) + { + psql_error("function name is required\n"); + status = PSQL_CMD_ERROR; + } + else if (!lookup_function_oid(func, &foid)) + { + /* error already reported */ + status = PSQL_CMD_ERROR; + } + else if (!get_create_function_cmd(foid, func_buf)) + { + /* error already reported */ + status = PSQL_CMD_ERROR; + } + else + { + FILE *output; + bool is_pager; + + /* Select output stream: stdout, pager, or file */ + if (pset.queryFout == stdout) + { + /* count lines in function to see if pager is needed */ + int lineno = 0; + const char *lines = func_buf->data; + + while (*lines != '\0') + { + lineno++; + /* find start of next line */ + lines = strchr(lines, '\n'); + if (!lines) + break; + lines++; + } + + output = PageOutput(lineno, &(pset.popt.topt)); + is_pager = true; + } + else + { + /* use previously set output file, without pager */ + output = pset.queryFout; + is_pager = false; + } + + if (show_linenumbers) + { + bool in_header = true; + int lineno = 0; + char *lines = func_buf->data; + + /* + * lineno "1" should correspond to the first line of the + * function body. We expect that pg_get_functiondef() will + * emit that on a line beginning with "AS ", and that there + * can be no such line before the real start of the function + * body. + * + * Note that this loop scribbles on func_buf. + */ + while (*lines != '\0') + { + char *eol; + + if (in_header && strncmp(lines, "AS ", 3) == 0) + in_header = false; + /* increment lineno only for body's lines */ + if (!in_header) + lineno++; + + /* find and mark end of current line */ + eol = strchr(lines, '\n'); + if (eol != NULL) + *eol = '\0'; + + /* show current line as appropriate */ + if (in_header) + fprintf(output, " %s\n", lines); + else + fprintf(output, "%-7d %s\n", lineno, lines); + + /* advance to next line, if any */ + if (eol == NULL) + break; + lines = ++eol; + } + } + else + { + /* just send the function definition to output */ + fputs(func_buf->data, output); + } + + if (is_pager) + ClosePager(output); + } + + if (func) + free(func); + destroyPQExpBuffer(func_buf); + } + + /* \stage */ + else if (pg_strcasecmp(cmd, "stage") == 0) + { + /* + * The stage command augments psql's copy command with data loading + * functionality for sharded databases. Specifically, the client first + * contacts the master node and fetches shard and node metadata. Then, + * the client coordinates the loading of data to remote nodes. + */ + instr_time startTime; + char *stageCommand = NULL; + + if (pset.timing) + { + INSTR_TIME_SET_CURRENT(startTime); + } + + /* read the rest of line; do not strip away quotes or semicolons */ + stageCommand = psql_scan_slash_option(scan_state, + OT_WHOLE_LINE, NULL, false); + + success = DoStageData(stageCommand); + + if (pset.timing && success) + { + instr_time endTime; + instr_time elapsedTime; + + INSTR_TIME_SET_CURRENT(endTime); + INSTR_TIME_SET_ZERO(elapsedTime); + + INSTR_TIME_ACCUM_DIFF(elapsedTime, endTime, startTime); + printf(_("Time: %.3f ms\n"), INSTR_TIME_GET_MILLISEC(elapsedTime)); + } + + free(stageCommand); + } + + /* \t -- turn off headers and row count */ + else if (strcmp(cmd, "t") == 0) + { + char *opt = psql_scan_slash_option(scan_state, + OT_NORMAL, NULL, true); + + success = do_pset("tuples_only", opt, &pset.popt, pset.quiet); + free(opt); + } + + /* \T -- define html attributes */ + else if (strcmp(cmd, "T") == 0) + { + char *value = psql_scan_slash_option(scan_state, + OT_NORMAL, NULL, false); + + success = do_pset("tableattr", value, &pset.popt, pset.quiet); + free(value); + } + + /* \timing -- toggle timing of queries */ + else if (strcmp(cmd, "timing") == 0) + { + char *opt = psql_scan_slash_option(scan_state, + OT_NORMAL, NULL, false); + + if (opt) + pset.timing = ParseVariableBool(opt, "\\timing"); + else + pset.timing = !pset.timing; + if (!pset.quiet) + { + if (pset.timing) + puts(_("Timing is on.")); + else + puts(_("Timing is off.")); + } + free(opt); + } + + /* \unset */ + else if (strcmp(cmd, "unset") == 0) + { + char *opt = psql_scan_slash_option(scan_state, + OT_NORMAL, NULL, false); + + if (!opt) + { + psql_error("\\%s: missing required argument\n", cmd); + success = false; + } + else if (!SetVariable(pset.vars, opt, NULL)) + { + psql_error("\\%s: error while setting variable\n", cmd); + success = false; + } + free(opt); + } + + /* \w -- write query buffer to file */ + else if (strcmp(cmd, "w") == 0 || strcmp(cmd, "write") == 0) + { + FILE *fd = NULL; + bool is_pipe = false; + char *fname = NULL; + + if (!query_buf) + { + psql_error("no query buffer\n"); + status = PSQL_CMD_ERROR; + } + else + { + fname = psql_scan_slash_option(scan_state, + OT_FILEPIPE, NULL, true); + expand_tilde(&fname); + + if (!fname) + { + psql_error("\\%s: missing required argument\n", cmd); + success = false; + } + else + { + if (fname[0] == '|') + { + is_pipe = true; + disable_sigpipe_trap(); + fd = popen(&fname[1], "w"); + } + else + { + canonicalize_path(fname); + fd = fopen(fname, "w"); + } + if (!fd) + { + psql_error("%s: %s\n", fname, strerror(errno)); + success = false; + } + } + } + + if (fd) + { + int result; + + if (query_buf && query_buf->len > 0) + fprintf(fd, "%s\n", query_buf->data); + + if (is_pipe) + result = pclose(fd); + else + result = fclose(fd); + + if (result == EOF) + { + psql_error("%s: %s\n", fname, strerror(errno)); + success = false; + } + } + + if (is_pipe) + restore_sigpipe_trap(); + + free(fname); + } + + /* \watch -- execute a query every N seconds */ + else if (strcmp(cmd, "watch") == 0) + { + char *opt = psql_scan_slash_option(scan_state, + OT_NORMAL, NULL, true); + long sleep = 2; + + /* Convert optional sleep-length argument */ + if (opt) + { + sleep = strtol(opt, NULL, 10); + if (sleep <= 0) + sleep = 1; + free(opt); + } + + success = do_watch(query_buf, sleep); + + /* Reset the query buffer as though for \r */ + resetPQExpBuffer(query_buf); + psql_scan_reset(scan_state); + } + + /* \x -- set or toggle expanded table representation */ + else if (strcmp(cmd, "x") == 0) + { + char *opt = psql_scan_slash_option(scan_state, + OT_NORMAL, NULL, true); + + success = do_pset("expanded", opt, &pset.popt, pset.quiet); + free(opt); + } + + /* \z -- list table rights (equivalent to \dp) */ + else if (strcmp(cmd, "z") == 0) + { + char *pattern = psql_scan_slash_option(scan_state, + OT_NORMAL, NULL, true); + + success = permissionsList(pattern); + if (pattern) + free(pattern); + } + + /* \! -- shell escape */ + else if (strcmp(cmd, "!") == 0) + { + char *opt = psql_scan_slash_option(scan_state, + OT_WHOLE_LINE, NULL, false); + + success = do_shell(opt); + free(opt); + } + + /* \? -- slash command help */ + else if (strcmp(cmd, "?") == 0) + { + char *opt0 = psql_scan_slash_option(scan_state, + OT_NORMAL, NULL, false); + + if (!opt0 || strcmp(opt0, "commands") == 0) + slashUsage(pset.popt.topt.pager); + else if (strcmp(opt0, "options") == 0) + usage(pset.popt.topt.pager); + else if (strcmp(opt0, "variables") == 0) + helpVariables(pset.popt.topt.pager); + else + slashUsage(pset.popt.topt.pager); + } + +#if 0 + + /* + * These commands don't do anything. I just use them to test the parser. + */ + else if (strcmp(cmd, "void") == 0 || strcmp(cmd, "#") == 0) + { + int i = 0; + char *value; + + while ((value = psql_scan_slash_option(scan_state, + OT_NORMAL, NULL, true))) + { + psql_error("+ opt(%d) = |%s|\n", i++, value); + free(value); + } + } +#endif + + else + status = PSQL_CMD_UNKNOWN; + + if (!success) + status = PSQL_CMD_ERROR; + + return status; +} + +/* + * Ask the user for a password; 'username' is the username the + * password is for, if one has been explicitly specified. Returns a + * malloc'd string. + */ +static char * +prompt_for_password(const char *username) +{ + char *result; + + if (username == NULL) + result = simple_prompt("Password: ", 100, false); + else + { + char *prompt_text; + + prompt_text = psprintf(_("Password for user %s: "), username); + result = simple_prompt(prompt_text, 100, false); + free(prompt_text); + } + + return result; +} + +static bool +param_is_newly_set(const char *old_val, const char *new_val) +{ + if (new_val == NULL) + return false; + + if (old_val == NULL || strcmp(old_val, new_val) != 0) + return true; + + return false; +} + +/* + * do_connect -- handler for \connect + * + * Connects to a database with given parameters. If there exists an + * established connection, NULL values will be replaced with the ones + * in the current connection. Otherwise NULL will be passed for that + * parameter to PQconnectdbParams(), so the libpq defaults will be used. + * + * In interactive mode, if connection fails with the given parameters, + * the old connection will be kept. + */ +static bool +do_connect(char *dbname, char *user, char *host, char *port) +{ + PGconn *o_conn = pset.db, + *n_conn; + char *password = NULL; + bool keep_password; + bool has_connection_string; + + if (!o_conn && (!dbname || !user || !host || !port)) + { + /* + * We don't know the supplied connection parameters and don't want to + * connect to the wrong database by using defaults, so require all + * parameters to be specified. + */ + psql_error("All connection parameters must be supplied because no " + "database connection exists\n"); + return false; + } + + /* grab values from the old connection, unless supplied by caller */ + if (!user) + user = PQuser(o_conn); + if (!host) + host = PQhost(o_conn); + if (!port) + port = PQport(o_conn); + + has_connection_string = + dbname ? recognized_connection_string(dbname) : false; + + /* + * Any change in the parameters read above makes us discard the password. + * We also discard it if we're to use a conninfo rather than the + * positional syntax. Note that currently, PQhost() can return NULL for a + * default Unix-socket connection, so we have to allow NULL for host. + */ + if (has_connection_string) + keep_password = false; + else + keep_password = + (user && PQuser(o_conn) && strcmp(user, PQuser(o_conn)) == 0) && + ((host && PQhost(o_conn) && strcmp(host, PQhost(o_conn)) == 0) || + (host == NULL && PQhost(o_conn) == NULL)) && + (port && PQport(o_conn) && strcmp(port, PQport(o_conn)) == 0); + + /* + * Grab dbname from old connection unless supplied by caller. No password + * discard if this changes: passwords aren't (usually) database-specific. + */ + if (!dbname) + dbname = PQdb(o_conn); + + /* + * If the user asked to be prompted for a password, ask for one now. If + * not, use the password from the old connection, provided the username + * etc have not changed. Otherwise, try to connect without a password + * first, and then ask for a password if needed. + * + * XXX: this behavior leads to spurious connection attempts recorded in + * the postmaster's log. But libpq offers no API that would let us obtain + * a password and then continue with the first connection attempt. + */ + if (pset.getPassword == TRI_YES) + { + password = prompt_for_password(user); + } + else if (o_conn && keep_password) + { + password = PQpass(o_conn); + if (password && *password) + password = pg_strdup(password); + else + password = NULL; + } + + while (true) + { +#define PARAMS_ARRAY_SIZE 8 + const char **keywords = pg_malloc(PARAMS_ARRAY_SIZE * sizeof(*keywords)); + const char **values = pg_malloc(PARAMS_ARRAY_SIZE * sizeof(*values)); + int paramnum = 0; + + keywords[0] = "dbname"; + values[0] = dbname; + + if (!has_connection_string) + { + keywords[++paramnum] = "host"; + values[paramnum] = host; + keywords[++paramnum] = "port"; + values[paramnum] = port; + keywords[++paramnum] = "user"; + values[paramnum] = user; + } + keywords[++paramnum] = "password"; + values[paramnum] = password; + keywords[++paramnum] = "fallback_application_name"; + values[paramnum] = pset.progname; + keywords[++paramnum] = "client_encoding"; + values[paramnum] = (pset.notty || getenv("PGCLIENTENCODING")) ? NULL : "auto"; + + /* add array terminator */ + keywords[++paramnum] = NULL; + values[paramnum] = NULL; + + n_conn = PQconnectdbParams(keywords, values, true); + + pg_free(keywords); + pg_free(values); + + /* We can immediately discard the password -- no longer needed */ + if (password) + pg_free(password); + + if (PQstatus(n_conn) == CONNECTION_OK) + break; + + /* + * Connection attempt failed; either retry the connection attempt with + * a new password, or give up. + */ + if (!password && PQconnectionNeedsPassword(n_conn) && pset.getPassword != TRI_NO) + { + PQfinish(n_conn); + password = prompt_for_password(user); + continue; + } + + /* + * Failed to connect to the database. In interactive mode, keep the + * previous connection to the DB; in scripting mode, close our + * previous connection as well. + */ + if (pset.cur_cmd_interactive) + { + psql_error("%s", PQerrorMessage(n_conn)); + + /* pset.db is left unmodified */ + if (o_conn) + psql_error("Previous connection kept\n"); + } + else + { + psql_error("\\connect: %s", PQerrorMessage(n_conn)); + if (o_conn) + { + PQfinish(o_conn); + pset.db = NULL; + } + } + + PQfinish(n_conn); + return false; + } + + /* + * Replace the old connection with the new one, and update + * connection-dependent variables. + */ + PQsetNoticeProcessor(n_conn, NoticeProcessor, NULL); + pset.db = n_conn; + SyncVariables(); + connection_warnings(false); /* Must be after SyncVariables */ + + /* Tell the user about the new connection */ + if (!pset.quiet) + { + if (!o_conn || + param_is_newly_set(PQhost(o_conn), PQhost(pset.db)) || + param_is_newly_set(PQport(o_conn), PQport(pset.db))) + { + char *host = PQhost(pset.db); + + if (host == NULL) + host = DEFAULT_PGSOCKET_DIR; + /* If the host is an absolute path, the connection is via socket */ + if (is_absolute_path(host)) + printf(_("You are now connected to database \"%s\" as user \"%s\" via socket in \"%s\" at port \"%s\".\n"), + PQdb(pset.db), PQuser(pset.db), host, PQport(pset.db)); + else + printf(_("You are now connected to database \"%s\" as user \"%s\" on host \"%s\" at port \"%s\".\n"), + PQdb(pset.db), PQuser(pset.db), host, PQport(pset.db)); + } + else + printf(_("You are now connected to database \"%s\" as user \"%s\".\n"), + PQdb(pset.db), PQuser(pset.db)); + } + + if (o_conn) + PQfinish(o_conn); + return true; +} + + +void +connection_warnings(bool in_startup) +{ + if (!pset.quiet && !pset.notty) + { + int client_ver = PG_VERSION_NUM; + + if (pset.sversion != client_ver) + { + const char *server_version; + char server_ver_str[16]; + + /* Try to get full text form, might include "devel" etc */ + server_version = PQparameterStatus(pset.db, "server_version"); + if (!server_version) + { + snprintf(server_ver_str, sizeof(server_ver_str), + "%d.%d.%d", + pset.sversion / 10000, + (pset.sversion / 100) % 100, + pset.sversion % 100); + server_version = server_ver_str; + } + + printf(_("%s (%s, server %s)\n"), + pset.progname, PG_VERSION, server_version); + } + /* For version match, only print psql banner on startup. */ + else if (in_startup) + printf("%s (%s)\n", pset.progname, PG_VERSION); + + if (pset.sversion / 100 > client_ver / 100) + printf(_("WARNING: %s major version %d.%d, server major version %d.%d.\n" + " Some psql features might not work.\n"), + pset.progname, client_ver / 10000, (client_ver / 100) % 100, + pset.sversion / 10000, (pset.sversion / 100) % 100); + +#ifdef WIN32 + checkWin32Codepage(); +#endif + printSSLInfo(); + } +} + + +/* + * printSSLInfo + * + * Prints information about the current SSL connection, if SSL is in use + */ +#if (PG_VERSION_NUM >= 90500) +static void +printSSLInfo(void) +{ + const char *protocol; + const char *cipher; + const char *bits; + const char *compression; + + if (!PQsslInUse(pset.db)) + return; /* no SSL */ + + protocol = PQsslAttribute(pset.db, "protocol"); + cipher = PQsslAttribute(pset.db, "cipher"); + bits = PQsslAttribute(pset.db, "key_bits"); + compression = PQsslAttribute(pset.db, "compression"); + + printf(_("SSL connection (protocol: %s, cipher: %s, bits: %s, compression: %s)\n"), + protocol ? protocol : _("unknown"), + cipher ? cipher : _("unknown"), + bits ? bits : _("unknown"), + (compression && strcmp(compression, "off") != 0) ? _("on") : _("off")); +} +#else +static void +printSSLInfo(void) +{ +#ifdef USE_SSL + int sslbits = -1; + SSL *ssl; + + ssl = PQgetssl(pset.db); + if (!ssl) + return; /* no SSL */ + + SSL_get_cipher_bits(ssl, &sslbits); + printf(_("SSL connection (protocol: %s, cipher: %s, bits: %d, compression: %s)\n"), + SSL_get_version(ssl), SSL_get_cipher(ssl), sslbits, + SSL_get_current_compression(ssl) ? _("on") : _("off")); +#else + + /* + * If psql is compiled without SSL but is using a libpq with SSL, we + * cannot figure out the specifics about the connection. But we know it's + * SSL secured. + */ + if (PQgetssl(pset.db)) + printf(_("SSL connection (unknown cipher)\n")); +#endif /* USE_SSL */ +} +#endif + +/* + * checkWin32Codepage + * + * Prints a warning when win32 console codepage differs from Windows codepage + */ +#ifdef WIN32 +static void +checkWin32Codepage(void) +{ + unsigned int wincp, + concp; + + wincp = GetACP(); + concp = GetConsoleCP(); + if (wincp != concp) + { + printf(_("WARNING: Console code page (%u) differs from Windows code page (%u)\n" + " 8-bit characters might not work correctly. See psql reference\n" + " page \"Notes for Windows users\" for details.\n"), + concp, wincp); + } +} +#endif + + +/* + * SyncVariables + * + * Make psql's internal variables agree with connection state upon + * establishing a new connection. + */ +void +SyncVariables(void) +{ + /* get stuff from connection */ + pset.encoding = PQclientEncoding(pset.db); + pset.popt.topt.encoding = pset.encoding; + pset.sversion = PQserverVersion(pset.db); + + SetVariable(pset.vars, "DBNAME", PQdb(pset.db)); + SetVariable(pset.vars, "USER", PQuser(pset.db)); + SetVariable(pset.vars, "HOST", PQhost(pset.db)); + SetVariable(pset.vars, "PORT", PQport(pset.db)); + SetVariable(pset.vars, "ENCODING", pg_encoding_to_char(pset.encoding)); + + /* send stuff to it, too */ + PQsetErrorVerbosity(pset.db, pset.verbosity); +} + +/* + * UnsyncVariables + * + * Clear variables that should be not be set when there is no connection. + */ +void +UnsyncVariables(void) +{ + SetVariable(pset.vars, "DBNAME", NULL); + SetVariable(pset.vars, "USER", NULL); + SetVariable(pset.vars, "HOST", NULL); + SetVariable(pset.vars, "PORT", NULL); + SetVariable(pset.vars, "ENCODING", NULL); +} + + +/* + * do_edit -- handler for \e + * + * If you do not specify a filename, the current query buffer will be copied + * into a temporary one. + */ +static bool +editFile(const char *fname, int lineno) +{ + const char *editorName; + const char *editor_lineno_arg = NULL; + char *sys; + int result; + + Assert(fname != NULL); + + /* Find an editor to use */ + editorName = getenv("PSQL_EDITOR"); + if (!editorName) + editorName = getenv("EDITOR"); + if (!editorName) + editorName = getenv("VISUAL"); + if (!editorName) + editorName = DEFAULT_EDITOR; + + /* Get line number argument, if we need it. */ + if (lineno > 0) + { + editor_lineno_arg = getenv("PSQL_EDITOR_LINENUMBER_ARG"); +#ifdef DEFAULT_EDITOR_LINENUMBER_ARG + if (!editor_lineno_arg) + editor_lineno_arg = DEFAULT_EDITOR_LINENUMBER_ARG; +#endif + if (!editor_lineno_arg) + { + psql_error("environment variable PSQL_EDITOR_LINENUMBER_ARG must be set to specify a line number\n"); + return false; + } + } + + /* + * On Unix the EDITOR value should *not* be quoted, since it might include + * switches, eg, EDITOR="pico -t"; it's up to the user to put quotes in it + * if necessary. But this policy is not very workable on Windows, due to + * severe brain damage in their command shell plus the fact that standard + * program paths include spaces. + */ +#ifndef WIN32 + if (lineno > 0) + sys = psprintf("exec %s %s%d '%s'", + editorName, editor_lineno_arg, lineno, fname); + else + sys = psprintf("exec %s '%s'", + editorName, fname); +#else + if (lineno > 0) + sys = psprintf("\"%s\" %s%d \"%s\"", + editorName, editor_lineno_arg, lineno, fname); + else + sys = psprintf("\"%s\" \"%s\"", + editorName, fname); +#endif + result = system(sys); + if (result == -1) + psql_error("could not start editor \"%s\"\n", editorName); + else if (result == 127) + psql_error("could not start /bin/sh\n"); + free(sys); + + return result == 0; +} + + +/* call this one */ +static bool +do_edit(const char *filename_arg, PQExpBuffer query_buf, + int lineno, bool *edited) +{ + char fnametmp[MAXPGPATH]; + FILE *stream = NULL; + const char *fname; + bool error = false; + int fd; + + struct stat before, + after; + + if (filename_arg) + fname = filename_arg; + else + { + /* make a temp file to edit */ +#ifndef WIN32 + const char *tmpdir = getenv("TMPDIR"); + + if (!tmpdir) + tmpdir = "/tmp"; +#else + char tmpdir[MAXPGPATH]; + int ret; + + ret = GetTempPath(MAXPGPATH, tmpdir); + if (ret == 0 || ret > MAXPGPATH) + { + psql_error("could not locate temporary directory: %s\n", + !ret ? strerror(errno) : ""); + return false; + } + + /* + * No canonicalize_path() here. EDIT.EXE run from CMD.EXE prepends the + * current directory to the supplied path unless we use only + * backslashes, so we do that. + */ +#endif +#ifndef WIN32 + snprintf(fnametmp, sizeof(fnametmp), "%s%spsql.edit.%d.sql", tmpdir, + "/", (int) getpid()); +#else + snprintf(fnametmp, sizeof(fnametmp), "%s%spsql.edit.%d.sql", tmpdir, + "" /* trailing separator already present */ , (int) getpid()); +#endif + + fname = (const char *) fnametmp; + + fd = open(fname, O_WRONLY | O_CREAT | O_EXCL, 0600); + if (fd != -1) + stream = fdopen(fd, "w"); + + if (fd == -1 || !stream) + { + psql_error("could not open temporary file \"%s\": %s\n", fname, strerror(errno)); + error = true; + } + else + { + unsigned int ql = query_buf->len; + + if (ql == 0 || query_buf->data[ql - 1] != '\n') + { + appendPQExpBufferChar(query_buf, '\n'); + ql++; + } + + if (fwrite(query_buf->data, 1, ql, stream) != ql) + { + psql_error("%s: %s\n", fname, strerror(errno)); + + if (fclose(stream) != 0) + psql_error("%s: %s\n", fname, strerror(errno)); + + if (remove(fname) != 0) + psql_error("%s: %s\n", fname, strerror(errno)); + + error = true; + } + else if (fclose(stream) != 0) + { + psql_error("%s: %s\n", fname, strerror(errno)); + if (remove(fname) != 0) + psql_error("%s: %s\n", fname, strerror(errno)); + error = true; + } + } + } + + if (!error && stat(fname, &before) != 0) + { + psql_error("%s: %s\n", fname, strerror(errno)); + error = true; + } + + /* call editor */ + if (!error) + error = !editFile(fname, lineno); + + if (!error && stat(fname, &after) != 0) + { + psql_error("%s: %s\n", fname, strerror(errno)); + error = true; + } + + if (!error && before.st_mtime != after.st_mtime) + { + stream = fopen(fname, PG_BINARY_R); + if (!stream) + { + psql_error("%s: %s\n", fname, strerror(errno)); + error = true; + } + else + { + /* read file back into query_buf */ + char line[1024]; + + resetPQExpBuffer(query_buf); + while (fgets(line, sizeof(line), stream) != NULL) + appendPQExpBufferStr(query_buf, line); + + if (ferror(stream)) + { + psql_error("%s: %s\n", fname, strerror(errno)); + error = true; + } + else if (edited) + { + *edited = true; + } + + fclose(stream); + } + } + + /* remove temp file */ + if (!filename_arg) + { + if (remove(fname) == -1) + { + psql_error("%s: %s\n", fname, strerror(errno)); + error = true; + } + } + + return !error; +} + + + +/* + * process_file + * + * Reads commands from filename and passes them to the main processing loop. + * Handler for \i and \ir, but can be used for other things as well. Returns + * MainLoop() error code. + * + * If use_relative_path is true and filename is not an absolute path, then open + * the file from where the currently processed file (if any) is located. + */ +int +process_file(char *filename, bool single_txn, bool use_relative_path) +{ + FILE *fd; + int result; + char *oldfilename; + char relpath[MAXPGPATH]; + PGresult *res; + + if (!filename) + { + fd = stdin; + filename = NULL; + } + else if (strcmp(filename, "-") != 0) + { + canonicalize_path(filename); + + /* + * If we were asked to resolve the pathname relative to the location + * of the currently executing script, and there is one, and this is a + * relative pathname, then prepend all but the last pathname component + * of the current script to this pathname. + */ + if (use_relative_path && pset.inputfile && + !is_absolute_path(filename) && !has_drive_prefix(filename)) + { + strlcpy(relpath, pset.inputfile, sizeof(relpath)); + get_parent_directory(relpath); + join_path_components(relpath, relpath, filename); + canonicalize_path(relpath); + + filename = relpath; + } + + fd = fopen(filename, PG_BINARY_R); + + if (!fd) + { + psql_error("%s: %s\n", filename, strerror(errno)); + return EXIT_FAILURE; + } + } + else + { + fd = stdin; + filename = ""; /* for future error messages */ + } + + oldfilename = pset.inputfile; + pset.inputfile = filename; + + if (single_txn) + { + if ((res = PSQLexec("BEGIN")) == NULL) + { + if (pset.on_error_stop) + { + result = EXIT_USER; + goto error; + } + } + else + PQclear(res); + } + + result = MainLoop(fd); + + if (single_txn) + { + if ((res = PSQLexec("COMMIT")) == NULL) + { + if (pset.on_error_stop) + { + result = EXIT_USER; + goto error; + } + } + else + PQclear(res); + } + +error: + if (fd != stdin) + fclose(fd); + + pset.inputfile = oldfilename; + return result; +} + + + +static const char * +_align2string(enum printFormat in) +{ + switch (in) + { + case PRINT_NOTHING: + return "nothing"; + break; + case PRINT_UNALIGNED: + return "unaligned"; + break; + case PRINT_ALIGNED: + return "aligned"; + break; + case PRINT_WRAPPED: + return "wrapped"; + break; + case PRINT_HTML: + return "html"; + break; + case PRINT_ASCIIDOC: + return "asciidoc"; + break; + case PRINT_LATEX: + return "latex"; + break; + case PRINT_LATEX_LONGTABLE: + return "latex-longtable"; + break; + case PRINT_TROFF_MS: + return "troff-ms"; + break; + } + return "unknown"; +} + +/* + * Parse entered Unicode linestyle. If ok, update *linestyle and return + * true, else return false. + */ +static bool +set_unicode_line_style(const char *value, size_t vallen, + unicode_linestyle *linestyle) +{ + if (pg_strncasecmp("single", value, vallen) == 0) + *linestyle = UNICODE_LINESTYLE_SINGLE; + else if (pg_strncasecmp("double", value, vallen) == 0) + *linestyle = UNICODE_LINESTYLE_DOUBLE; + else + return false; + return true; +} + +static const char * +_unicode_linestyle2string(int linestyle) +{ + switch (linestyle) + { + case UNICODE_LINESTYLE_SINGLE: + return "single"; + break; + case UNICODE_LINESTYLE_DOUBLE: + return "double"; + break; + } + return "unknown"; +} + +/* + * do_pset + * + */ +bool +do_pset(const char *param, const char *value, printQueryOpt *popt, bool quiet) +{ + size_t vallen = 0; + + Assert(param != NULL); + + if (value) + vallen = strlen(value); + + /* set format */ + if (strcmp(param, "format") == 0) + { + if (!value) + ; + else if (pg_strncasecmp("unaligned", value, vallen) == 0) + popt->topt.format = PRINT_UNALIGNED; + else if (pg_strncasecmp("aligned", value, vallen) == 0) + popt->topt.format = PRINT_ALIGNED; + else if (pg_strncasecmp("wrapped", value, vallen) == 0) + popt->topt.format = PRINT_WRAPPED; + else if (pg_strncasecmp("html", value, vallen) == 0) + popt->topt.format = PRINT_HTML; + else if (pg_strncasecmp("asciidoc", value, vallen) == 0) + popt->topt.format = PRINT_ASCIIDOC; + else if (pg_strncasecmp("latex", value, vallen) == 0) + popt->topt.format = PRINT_LATEX; + else if (pg_strncasecmp("latex-longtable", value, vallen) == 0) + popt->topt.format = PRINT_LATEX_LONGTABLE; + else if (pg_strncasecmp("troff-ms", value, vallen) == 0) + popt->topt.format = PRINT_TROFF_MS; + else + { + psql_error("\\pset: allowed formats are unaligned, aligned, wrapped, html, asciidoc, latex, latex-longtable, troff-ms\n"); + return false; + } + + } + + /* set table line style */ + else if (strcmp(param, "linestyle") == 0) + { + if (!value) + ; + else if (pg_strncasecmp("ascii", value, vallen) == 0) + popt->topt.line_style = &pg_asciiformat; + else if (pg_strncasecmp("old-ascii", value, vallen) == 0) + popt->topt.line_style = &pg_asciiformat_old; + else if (pg_strncasecmp("unicode", value, vallen) == 0) + popt->topt.line_style = &pg_utf8format; + else + { + psql_error("\\pset: allowed line styles are ascii, old-ascii, unicode\n"); + return false; + } + + } + + /* set unicode border line style */ + else if (strcmp(param, "unicode_border_linestyle") == 0) + { + if (!value) + ; + else if (set_unicode_line_style(value, vallen, + &popt->topt.unicode_border_linestyle)) + refresh_utf8format(&(popt->topt)); + else + { + psql_error("\\pset: allowed Unicode border line styles are single, double\n"); + return false; + } + } + + /* set unicode column line style */ + else if (strcmp(param, "unicode_column_linestyle") == 0) + { + if (!value) + ; + else if (set_unicode_line_style(value, vallen, + &popt->topt.unicode_column_linestyle)) + refresh_utf8format(&(popt->topt)); + else + { + psql_error("\\pset: allowed Unicode column line styles are single, double\n"); + return false; + } + } + + /* set unicode header line style */ + else if (strcmp(param, "unicode_header_linestyle") == 0) + { + if (!value) + ; + else if (set_unicode_line_style(value, vallen, + &popt->topt.unicode_header_linestyle)) + refresh_utf8format(&(popt->topt)); + else + { + psql_error("\\pset: allowed Unicode header line styles are single, double\n"); + return false; + } + } + + /* set border style/width */ + else if (strcmp(param, "border") == 0) + { + if (value) + popt->topt.border = atoi(value); + + } + + /* set expanded/vertical mode */ + else if (strcmp(param, "x") == 0 || + strcmp(param, "expanded") == 0 || + strcmp(param, "vertical") == 0) + { + if (value && pg_strcasecmp(value, "auto") == 0) + popt->topt.expanded = 2; + else if (value) + popt->topt.expanded = ParseVariableBool(value, param); + else + popt->topt.expanded = !popt->topt.expanded; + } + + /* locale-aware numeric output */ + else if (strcmp(param, "numericlocale") == 0) + { + if (value) + popt->topt.numericLocale = ParseVariableBool(value, param); + else + popt->topt.numericLocale = !popt->topt.numericLocale; + } + + /* null display */ + else if (strcmp(param, "null") == 0) + { + if (value) + { + free(popt->nullPrint); + popt->nullPrint = pg_strdup(value); + } + } + + /* field separator for unaligned text */ + else if (strcmp(param, "fieldsep") == 0) + { + if (value) + { + free(popt->topt.fieldSep.separator); + popt->topt.fieldSep.separator = pg_strdup(value); + popt->topt.fieldSep.separator_zero = false; + } + } + + else if (strcmp(param, "fieldsep_zero") == 0) + { + free(popt->topt.fieldSep.separator); + popt->topt.fieldSep.separator = NULL; + popt->topt.fieldSep.separator_zero = true; + } + + /* record separator for unaligned text */ + else if (strcmp(param, "recordsep") == 0) + { + if (value) + { + free(popt->topt.recordSep.separator); + popt->topt.recordSep.separator = pg_strdup(value); + popt->topt.recordSep.separator_zero = false; + } + } + + else if (strcmp(param, "recordsep_zero") == 0) + { + free(popt->topt.recordSep.separator); + popt->topt.recordSep.separator = NULL; + popt->topt.recordSep.separator_zero = true; + } + + /* toggle between full and tuples-only format */ + else if (strcmp(param, "t") == 0 || strcmp(param, "tuples_only") == 0) + { + if (value) + popt->topt.tuples_only = ParseVariableBool(value, param); + else + popt->topt.tuples_only = !popt->topt.tuples_only; + } + + /* set title override */ + else if (strcmp(param, "title") == 0) + { + free(popt->title); + if (!value) + popt->title = NULL; + else + popt->title = pg_strdup(value); + } + + /* set HTML table tag options */ + else if (strcmp(param, "T") == 0 || strcmp(param, "tableattr") == 0) + { + free(popt->topt.tableAttr); + if (!value) + popt->topt.tableAttr = NULL; + else + popt->topt.tableAttr = pg_strdup(value); + } + + /* toggle use of pager */ + else if (strcmp(param, "pager") == 0) + { + if (value && pg_strcasecmp(value, "always") == 0) + popt->topt.pager = 2; + else if (value) + { + if (ParseVariableBool(value, param)) + popt->topt.pager = 1; + else + popt->topt.pager = 0; + } + else if (popt->topt.pager == 1) + popt->topt.pager = 0; + else + popt->topt.pager = 1; + } + + /* set minimum lines for pager use */ + else if (strcmp(param, "pager_min_lines") == 0) + { + if (value) + popt->topt.pager_min_lines = atoi(value); + } + + /* disable "(x rows)" footer */ + else if (strcmp(param, "footer") == 0) + { + if (value) + popt->topt.default_footer = ParseVariableBool(value, param); + else + popt->topt.default_footer = !popt->topt.default_footer; + } + + /* set border style/width */ + else if (strcmp(param, "columns") == 0) + { + if (value) + popt->topt.columns = atoi(value); + } + else + { + psql_error("\\pset: unknown option: %s\n", param); + return false; + } + + if (!quiet) + printPsetInfo(param, &pset.popt); + + return true; +} + + +static bool +printPsetInfo(const char *param, struct printQueryOpt *popt) +{ + Assert(param != NULL); + + /* show border style/width */ + if (strcmp(param, "border") == 0) + printf(_("Border style is %d.\n"), popt->topt.border); + + /* show the target width for the wrapped format */ + else if (strcmp(param, "columns") == 0) + { + if (!popt->topt.columns) + printf(_("Target width is unset.\n")); + else + printf(_("Target width is %d.\n"), popt->topt.columns); + } + + /* show expanded/vertical mode */ + else if (strcmp(param, "x") == 0 || strcmp(param, "expanded") == 0 || strcmp(param, "vertical") == 0) + { + if (popt->topt.expanded == 1) + printf(_("Expanded display is on.\n")); + else if (popt->topt.expanded == 2) + printf(_("Expanded display is used automatically.\n")); + else + printf(_("Expanded display is off.\n")); + } + + /* show field separator for unaligned text */ + else if (strcmp(param, "fieldsep") == 0) + { + if (popt->topt.fieldSep.separator_zero) + printf(_("Field separator is zero byte.\n")); + else + printf(_("Field separator is \"%s\".\n"), + popt->topt.fieldSep.separator); + } + + else if (strcmp(param, "fieldsep_zero") == 0) + { + printf(_("Field separator is zero byte.\n")); + } + + /* show disable "(x rows)" footer */ + else if (strcmp(param, "footer") == 0) + { + if (popt->topt.default_footer) + printf(_("Default footer is on.\n")); + else + printf(_("Default footer is off.\n")); + } + + /* show format */ + else if (strcmp(param, "format") == 0) + { + printf(_("Output format is %s.\n"), _align2string(popt->topt.format)); + } + + /* show table line style */ + else if (strcmp(param, "linestyle") == 0) + { + printf(_("Line style is %s.\n"), + get_line_style(&popt->topt)->name); + } + + /* show null display */ + else if (strcmp(param, "null") == 0) + { + printf(_("Null display is \"%s\".\n"), + popt->nullPrint ? popt->nullPrint : ""); + } + + /* show locale-aware numeric output */ + else if (strcmp(param, "numericlocale") == 0) + { + if (popt->topt.numericLocale) + printf(_("Locale-adjusted numeric output is on.\n")); + else + printf(_("Locale-adjusted numeric output is off.\n")); + } + + /* show toggle use of pager */ + else if (strcmp(param, "pager") == 0) + { + if (popt->topt.pager == 1) + printf(_("Pager is used for long output.\n")); + else if (popt->topt.pager == 2) + printf(_("Pager is always used.\n")); + else + printf(_("Pager usage is off.\n")); + } + + /* show minimum lines for pager use */ + else if (strcmp(param, "pager_min_lines") == 0) + { + printf(ngettext("Pager won't be used for less than %d line.\n", + "Pager won't be used for less than %d lines.\n", + popt->topt.pager_min_lines), + popt->topt.pager_min_lines); + } + + /* show record separator for unaligned text */ + else if (strcmp(param, "recordsep") == 0) + { + if (popt->topt.recordSep.separator_zero) + printf(_("Record separator is zero byte.\n")); + else if (strcmp(popt->topt.recordSep.separator, "\n") == 0) + printf(_("Record separator is .\n")); + else + printf(_("Record separator is \"%s\".\n"), + popt->topt.recordSep.separator); + } + + else if (strcmp(param, "recordsep_zero") == 0) + { + printf(_("Record separator is zero byte.\n")); + } + + /* show HTML table tag options */ + else if (strcmp(param, "T") == 0 || strcmp(param, "tableattr") == 0) + { + if (popt->topt.tableAttr) + printf(_("Table attributes are \"%s\".\n"), + popt->topt.tableAttr); + else + printf(_("Table attributes unset.\n")); + } + + /* show title override */ + else if (strcmp(param, "title") == 0) + { + if (popt->title) + printf(_("Title is \"%s\".\n"), popt->title); + else + printf(_("Title is unset.\n")); + } + + /* show toggle between full and tuples-only format */ + else if (strcmp(param, "t") == 0 || strcmp(param, "tuples_only") == 0) + { + if (popt->topt.tuples_only) + printf(_("Tuples only is on.\n")); + else + printf(_("Tuples only is off.\n")); + } + + /* Unicode style formatting */ + else if (strcmp(param, "unicode_border_linestyle") == 0) + { + printf(_("Unicode border line style is \"%s\".\n"), + _unicode_linestyle2string(popt->topt.unicode_border_linestyle)); + } + + else if (strcmp(param, "unicode_column_linestyle") == 0) + { + printf(_("Unicode column line style is \"%s\".\n"), + _unicode_linestyle2string(popt->topt.unicode_column_linestyle)); + } + + else if (strcmp(param, "unicode_header_linestyle") == 0) + { + printf(_("Unicode header line style is \"%s\".\n"), + _unicode_linestyle2string(popt->topt.unicode_header_linestyle)); + } + + else + { + psql_error("\\pset: unknown option: %s\n", param); + return false; + } + + return true; +} + + +static const char * +pset_bool_string(bool val) +{ + return val ? "on" : "off"; +} + + +static char * +pset_quoted_string(const char *str) +{ + char *ret = pg_malloc(strlen(str) * 2 + 3); + char *r = ret; + + *r++ = '\''; + + for (; *str; str++) + { + if (*str == '\n') + { + *r++ = '\\'; + *r++ = 'n'; + } + else if (*str == '\'') + { + *r++ = '\\'; + *r++ = '\''; + } + else + *r++ = *str; + } + + *r++ = '\''; + *r = '\0'; + + return ret; +} + + +/* + * Return a malloc'ed string for the \pset value. + * + * Note that for some string parameters, print.c distinguishes between unset + * and empty string, but for others it doesn't. This function should produce + * output that produces the correct setting when fed back into \pset. + */ +static char * +pset_value_string(const char *param, struct printQueryOpt *popt) +{ + Assert(param != NULL); + + if (strcmp(param, "border") == 0) + return psprintf("%d", popt->topt.border); + else if (strcmp(param, "columns") == 0) + return psprintf("%d", popt->topt.columns); + else if (strcmp(param, "expanded") == 0) + return pstrdup(popt->topt.expanded == 2 + ? "auto" + : pset_bool_string(popt->topt.expanded)); + else if (strcmp(param, "fieldsep") == 0) + return pset_quoted_string(popt->topt.fieldSep.separator + ? popt->topt.fieldSep.separator + : ""); + else if (strcmp(param, "fieldsep_zero") == 0) + return pstrdup(pset_bool_string(popt->topt.fieldSep.separator_zero)); + else if (strcmp(param, "footer") == 0) + return pstrdup(pset_bool_string(popt->topt.default_footer)); + else if (strcmp(param, "format") == 0) + return psprintf("%s", _align2string(popt->topt.format)); + else if (strcmp(param, "linestyle") == 0) + return psprintf("%s", get_line_style(&popt->topt)->name); + else if (strcmp(param, "null") == 0) + return pset_quoted_string(popt->nullPrint + ? popt->nullPrint + : ""); + else if (strcmp(param, "numericlocale") == 0) + return pstrdup(pset_bool_string(popt->topt.numericLocale)); + else if (strcmp(param, "pager") == 0) + return psprintf("%d", popt->topt.pager); + else if (strcmp(param, "pager_min_lines") == 0) + return psprintf("%d", popt->topt.pager_min_lines); + else if (strcmp(param, "recordsep") == 0) + return pset_quoted_string(popt->topt.recordSep.separator + ? popt->topt.recordSep.separator + : ""); + else if (strcmp(param, "recordsep_zero") == 0) + return pstrdup(pset_bool_string(popt->topt.recordSep.separator_zero)); + else if (strcmp(param, "tableattr") == 0) + return popt->topt.tableAttr ? pset_quoted_string(popt->topt.tableAttr) : pstrdup(""); + else if (strcmp(param, "title") == 0) + return popt->title ? pset_quoted_string(popt->title) : pstrdup(""); + else if (strcmp(param, "tuples_only") == 0) + return pstrdup(pset_bool_string(popt->topt.tuples_only)); + else if (strcmp(param, "unicode_border_linestyle") == 0) + return pstrdup(_unicode_linestyle2string(popt->topt.unicode_border_linestyle)); + else if (strcmp(param, "unicode_column_linestyle") == 0) + return pstrdup(_unicode_linestyle2string(popt->topt.unicode_column_linestyle)); + else if (strcmp(param, "unicode_header_linestyle") == 0) + return pstrdup(_unicode_linestyle2string(popt->topt.unicode_header_linestyle)); + else + return pstrdup("ERROR"); +} + + + +#ifndef WIN32 +#define DEFAULT_SHELL "/bin/sh" +#else +/* + * CMD.EXE is in different places in different Win32 releases so we + * have to rely on the path to find it. + */ +#define DEFAULT_SHELL "cmd.exe" +#endif + +static bool +do_shell(const char *command) +{ + int result; + + if (!command) + { + char *sys; + const char *shellName; + + shellName = getenv("SHELL"); +#ifdef WIN32 + if (shellName == NULL) + shellName = getenv("COMSPEC"); +#endif + if (shellName == NULL) + shellName = DEFAULT_SHELL; + + /* See EDITOR handling comment for an explanation */ +#ifndef WIN32 + sys = psprintf("exec %s", shellName); +#else + sys = psprintf("\"%s\"", shellName); +#endif + result = system(sys); + free(sys); + } + else + result = system(command); + + if (result == 127 || result == -1) + { + psql_error("\\!: failed\n"); + return false; + } + return true; +} + +/* + * do_watch -- handler for \watch + * + * We break this out of exec_command to avoid having to plaster "volatile" + * onto a bunch of exec_command's variables to silence stupider compilers. + */ +static bool +do_watch(PQExpBuffer query_buf, long sleep) +{ + printQueryOpt myopt = pset.popt; + char title[50]; + + if (!query_buf || query_buf->len <= 0) + { + psql_error(_("\\watch cannot be used with an empty query\n")); + return false; + } + + /* + * Set up rendering options, in particular, disable the pager, because + * nobody wants to be prompted while watching the output of 'watch'. + */ + myopt.topt.pager = 0; + + for (;;) + { + int res; + time_t timer; + long i; + + /* + * Prepare title for output. XXX would it be better to use the time + * of completion of the command? + */ + timer = time(NULL); + snprintf(title, sizeof(title), _("Watch every %lds\t%s"), + sleep, asctime(localtime(&timer))); + myopt.title = title; + + /* Run the query and print out the results */ + res = PSQLexecWatch(query_buf->data, &myopt); + + /* + * PSQLexecWatch handles the case where we can no longer repeat the + * query, and returns 0 or -1. + */ + if (res == 0) + break; + if (res == -1) + return false; + + /* + * Set up cancellation of 'watch' via SIGINT. We redo this each time + * through the loop since it's conceivable something inside + * PSQLexecWatch could change sigint_interrupt_jmp. + */ + if (sigsetjmp(sigint_interrupt_jmp, 1) != 0) + break; + + /* + * Enable 'watch' cancellations and wait a while before running the + * query again. Break the sleep into short intervals since pg_usleep + * isn't interruptible on some platforms. + */ + sigint_interrupt_enabled = true; + for (i = 0; i < sleep; i++) + { + pg_usleep(1000000L); + if (cancel_pressed) + break; + } + sigint_interrupt_enabled = false; + } + + return true; +} + +/* + * a little code borrowed from PSQLexec() to manage ECHO_HIDDEN output. + * returns true unless we have ECHO_HIDDEN_NOEXEC. + */ +static bool +lookup_function_echo_hidden(char *query) +{ + if (pset.echo_hidden != PSQL_ECHO_HIDDEN_OFF) + { + printf(_("********* QUERY **********\n" + "%s\n" + "**************************\n\n"), query); + fflush(stdout); + if (pset.logfile) + { + fprintf(pset.logfile, + _("********* QUERY **********\n" + "%s\n" + "**************************\n\n"), query); + fflush(pset.logfile); + } + + if (pset.echo_hidden == PSQL_ECHO_HIDDEN_NOEXEC) + return false; + } + return true; +} + +/* + * This function takes a function description, e.g. "x" or "x(int)", and + * issues a query on the given connection to retrieve the function's OID + * using a cast to regproc or regprocedure (as appropriate). The result, + * if there is one, is returned at *foid. Note that we'll fail if the + * function doesn't exist OR if there are multiple matching candidates + * OR if there's something syntactically wrong with the function description; + * unfortunately it can be hard to tell the difference. + */ +static bool +lookup_function_oid(const char *desc, Oid *foid) +{ + bool result = true; + PQExpBuffer query; + PGresult *res; + + query = createPQExpBuffer(); + appendPQExpBufferStr(query, "SELECT "); + appendStringLiteralConn(query, desc, pset.db); + appendPQExpBuffer(query, "::pg_catalog.%s::pg_catalog.oid", + strchr(desc, '(') ? "regprocedure" : "regproc"); + if (!lookup_function_echo_hidden(query->data)) + { + destroyPQExpBuffer(query); + return false; + } + res = PQexec(pset.db, query->data); + if (PQresultStatus(res) == PGRES_TUPLES_OK && PQntuples(res) == 1) + *foid = atooid(PQgetvalue(res, 0, 0)); + else + { + minimal_error_message(res); + result = false; + } + + PQclear(res); + destroyPQExpBuffer(query); + + return result; +} + +/* + * Fetches the "CREATE OR REPLACE FUNCTION ..." command that describes the + * function with the given OID. If successful, the result is stored in buf. + */ +static bool +get_create_function_cmd(Oid oid, PQExpBuffer buf) +{ + bool result = true; + PQExpBuffer query; + PGresult *res; + + query = createPQExpBuffer(); + printfPQExpBuffer(query, "SELECT pg_catalog.pg_get_functiondef(%u)", oid); + + if (!lookup_function_echo_hidden(query->data)) + { + destroyPQExpBuffer(query); + return false; + } + res = PQexec(pset.db, query->data); + if (PQresultStatus(res) == PGRES_TUPLES_OK && PQntuples(res) == 1) + { + resetPQExpBuffer(buf); + appendPQExpBufferStr(buf, PQgetvalue(res, 0, 0)); + } + else + { + minimal_error_message(res); + result = false; + } + + PQclear(res); + destroyPQExpBuffer(query); + + return result; +} + +/* + * If the given argument of \ef ends with a line number, delete the line + * number from the argument string and return it as an integer. (We need + * this kluge because we're too lazy to parse \ef's function name argument + * carefully --- we just slop it up in OT_WHOLE_LINE mode.) + * + * Returns -1 if no line number is present, 0 on error, or a positive value + * on success. + */ +static int +strip_lineno_from_funcdesc(char *func) +{ + char *c; + int lineno; + + if (!func || func[0] == '\0') + return -1; + + c = func + strlen(func) - 1; + + /* + * This business of parsing backwards is dangerous as can be in a + * multibyte environment: there is no reason to believe that we are + * looking at the first byte of a character, nor are we necessarily + * working in a "safe" encoding. Fortunately the bitpatterns we are + * looking for are unlikely to occur as non-first bytes, but beware of + * trying to expand the set of cases that can be recognized. We must + * guard the macros by using isascii() first, too. + */ + + /* skip trailing whitespace */ + while (c > func && isascii((unsigned char) *c) && isspace((unsigned char) *c)) + c--; + + /* must have a digit as last non-space char */ + if (c == func || !isascii((unsigned char) *c) || !isdigit((unsigned char) *c)) + return -1; + + /* find start of digit string */ + while (c > func && isascii((unsigned char) *c) && isdigit((unsigned char) *c)) + c--; + + /* digits must be separated from func name by space or closing paren */ + /* notice also that we are not allowing an empty func name ... */ + if (c == func || !isascii((unsigned char) *c) || + !(isspace((unsigned char) *c) || *c == ')')) + return -1; + + /* parse digit string */ + c++; + lineno = atoi(c); + if (lineno < 1) + { + psql_error("invalid line number: %s\n", c); + return 0; + } + + /* strip digit string from func */ + *c = '\0'; + + return lineno; +} + +/* + * Report just the primary error; this is to avoid cluttering the output + * with, for instance, a redisplay of the internally generated query + */ +static void +minimal_error_message(PGresult *res) +{ + PQExpBuffer msg; + const char *fld; + + msg = createPQExpBuffer(); + + fld = PQresultErrorField(res, PG_DIAG_SEVERITY); + if (fld) + printfPQExpBuffer(msg, "%s: ", fld); + else + printfPQExpBuffer(msg, "ERROR: "); + fld = PQresultErrorField(res, PG_DIAG_MESSAGE_PRIMARY); + if (fld) + appendPQExpBufferStr(msg, fld); + else + appendPQExpBufferStr(msg, "(not available)"); + appendPQExpBufferStr(msg, "\n"); + + psql_error("%s", msg->data); + + destroyPQExpBuffer(msg); +} diff --git a/src/bin/csql/command.h b/src/bin/csql/command.h new file mode 100644 index 000000000..54385e8f8 --- /dev/null +++ b/src/bin/csql/command.h @@ -0,0 +1,43 @@ +/* + * psql - the PostgreSQL interactive terminal + * + * Copyright (c) 2000-2015, PostgreSQL Global Development Group + * + * src/bin/psql/command.h + */ +#ifndef COMMAND_H +#define COMMAND_H + +#include "print.h" +#include "psqlscan.h" + + +typedef enum _backslashResult +{ + PSQL_CMD_UNKNOWN = 0, /* not done parsing yet (internal only) */ + PSQL_CMD_SEND, /* query complete; send off */ + PSQL_CMD_SKIP_LINE, /* keep building query */ + PSQL_CMD_TERMINATE, /* quit program */ + PSQL_CMD_NEWEDIT, /* query buffer was changed (e.g., via \e) */ + PSQL_CMD_ERROR /* the execution of the backslash command + * resulted in an error */ +} backslashResult; + + +extern backslashResult HandleSlashCmds(PsqlScanState scan_state, + PQExpBuffer query_buf); + +extern int process_file(char *filename, bool single_txn, bool use_relative_path); + +extern bool do_pset(const char *param, + const char *value, + printQueryOpt *popt, + bool quiet); + +extern void connection_warnings(bool in_startup); + +extern void SyncVariables(void); + +extern void UnsyncVariables(void); + +#endif /* COMMAND_H */ diff --git a/src/bin/csql/common.c b/src/bin/csql/common.c new file mode 100644 index 000000000..dc00a3c7f --- /dev/null +++ b/src/bin/csql/common.c @@ -0,0 +1,1903 @@ +/* + * psql - the PostgreSQL interactive terminal + * + * Copyright (c) 2000-2015, PostgreSQL Global Development Group + * + * src/bin/psql/common.c + */ +#include "postgres_fe.h" +#include "common.h" + +#include +#include +#include +#ifndef WIN32 +#include /* for write() */ +#else +#include /* for _write() */ +#include +#endif + +#include "portability/instr_time.h" + +#include "settings.h" +#include "command.h" +#include "copy.h" +#include "mbprint.h" + + +static bool ExecQueryUsingCursor(const char *query, double *elapsed_msec); +static bool command_no_begin(const char *query); +static bool is_select_command(const char *query); + + +/* + * openQueryOutputFile --- attempt to open a query output file + * + * fname == NULL selects stdout, else an initial '|' selects a pipe, + * else plain file. + * + * Returns output file pointer into *fout, and is-a-pipe flag into *is_pipe. + * Caller is responsible for adjusting SIGPIPE state if it's a pipe. + * + * On error, reports suitable error message and returns FALSE. + */ +bool +openQueryOutputFile(const char *fname, FILE **fout, bool *is_pipe) +{ + if (!fname || fname[0] == '\0') + { + *fout = stdout; + *is_pipe = false; + } + else if (*fname == '|') + { + *fout = popen(fname + 1, "w"); + *is_pipe = true; + } + else + { + *fout = fopen(fname, "w"); + *is_pipe = false; + } + + if (*fout == NULL) + { + psql_error("%s: %s\n", fname, strerror(errno)); + return false; + } + + return true; +} + +/* + * setQFout + * -- handler for -o command line option and \o command + * + * On success, updates pset with the new output file and returns true. + * On failure, returns false without changing pset state. + */ +bool +setQFout(const char *fname) +{ + FILE *fout; + bool is_pipe; + + /* First make sure we can open the new output file/pipe */ + if (!openQueryOutputFile(fname, &fout, &is_pipe)) + return false; + + /* Close old file/pipe */ + if (pset.queryFout && pset.queryFout != stdout && pset.queryFout != stderr) + { + if (pset.queryFoutPipe) + pclose(pset.queryFout); + else + fclose(pset.queryFout); + } + + pset.queryFout = fout; + pset.queryFoutPipe = is_pipe; + + /* Adjust SIGPIPE handling appropriately: ignore signal if is_pipe */ + set_sigpipe_trap_state(is_pipe); + restore_sigpipe_trap(); + + return true; +} + + +/* + * Error reporting for scripts. Errors should look like + * psql:filename:lineno: message + */ +void +psql_error(const char *fmt,...) +{ + va_list ap; + + fflush(stdout); + if (pset.queryFout && pset.queryFout != stdout) + fflush(pset.queryFout); + + if (pset.inputfile) + fprintf(stderr, "%s:%s:" UINT64_FORMAT ": ", pset.progname, pset.inputfile, pset.lineno); + va_start(ap, fmt); + vfprintf(stderr, _(fmt), ap); + va_end(ap); +} + + + +/* + * for backend Notice messages (INFO, WARNING, etc) + */ +void +NoticeProcessor(void *arg, const char *message) +{ + (void) arg; /* not used */ + psql_error("%s", message); +} + + + +/* + * Code to support query cancellation + * + * Before we start a query, we enable the SIGINT signal catcher to send a + * cancel request to the backend. Note that sending the cancel directly from + * the signal handler is safe because PQcancel() is written to make it + * so. We use write() to report to stderr because it's better to use simple + * facilities in a signal handler. + * + * On win32, the signal canceling happens on a separate thread, because + * that's how SetConsoleCtrlHandler works. The PQcancel function is safe + * for this (unlike PQrequestCancel). However, a CRITICAL_SECTION is required + * to protect the PGcancel structure against being changed while the signal + * thread is using it. + * + * SIGINT is supposed to abort all long-running psql operations, not only + * database queries. In most places, this is accomplished by checking + * cancel_pressed during long-running loops. However, that won't work when + * blocked on user input (in readline() or fgets()). In those places, we + * set sigint_interrupt_enabled TRUE while blocked, instructing the signal + * catcher to longjmp through sigint_interrupt_jmp. We assume readline and + * fgets are coded to handle possible interruption. (XXX currently this does + * not work on win32, so control-C is less useful there) + */ +volatile bool sigint_interrupt_enabled = false; + +sigjmp_buf sigint_interrupt_jmp; + +static PGcancel *volatile cancelConn = NULL; + +#ifdef WIN32 +static CRITICAL_SECTION cancelConnLock; +#endif + +/* Used from signal handlers, no buffering */ +#define write_stderr(str) write(fileno(stderr), str, strlen(str)) + + +#ifndef WIN32 + +static void +handle_sigint(SIGNAL_ARGS) +{ + int save_errno = errno; + int rc; + char errbuf[256]; + + /* if we are waiting for input, longjmp out of it */ + if (sigint_interrupt_enabled) + { + sigint_interrupt_enabled = false; + siglongjmp(sigint_interrupt_jmp, 1); + } + + /* else, set cancel flag to stop any long-running loops */ + cancel_pressed = true; + + /* and send QueryCancel if we are processing a database query */ + if (cancelConn != NULL) + { + if (PQcancel(cancelConn, errbuf, sizeof(errbuf))) + { + rc = write_stderr("Cancel request sent\n"); + (void) rc; /* ignore errors, nothing we can do here */ + } + else + { + rc = write_stderr("Could not send cancel request: "); + (void) rc; /* ignore errors, nothing we can do here */ + rc = write_stderr(errbuf); + (void) rc; /* ignore errors, nothing we can do here */ + } + } + + errno = save_errno; /* just in case the write changed it */ +} + +void +setup_cancel_handler(void) +{ + pqsignal(SIGINT, handle_sigint); +} +#else /* WIN32 */ + +static BOOL WINAPI +consoleHandler(DWORD dwCtrlType) +{ + char errbuf[256]; + + if (dwCtrlType == CTRL_C_EVENT || + dwCtrlType == CTRL_BREAK_EVENT) + { + /* + * Can't longjmp here, because we are in wrong thread :-( + */ + + /* set cancel flag to stop any long-running loops */ + cancel_pressed = true; + + /* and send QueryCancel if we are processing a database query */ + EnterCriticalSection(&cancelConnLock); + if (cancelConn != NULL) + { + if (PQcancel(cancelConn, errbuf, sizeof(errbuf))) + write_stderr("Cancel request sent\n"); + else + { + write_stderr("Could not send cancel request: "); + write_stderr(errbuf); + } + } + LeaveCriticalSection(&cancelConnLock); + + return TRUE; + } + else + /* Return FALSE for any signals not being handled */ + return FALSE; +} + +void +setup_cancel_handler(void) +{ + InitializeCriticalSection(&cancelConnLock); + + SetConsoleCtrlHandler(consoleHandler, TRUE); +} +#endif /* WIN32 */ + + +/* ConnectionUp + * + * Returns whether our backend connection is still there. + */ +static bool +ConnectionUp(void) +{ + return PQstatus(pset.db) != CONNECTION_BAD; +} + + + +/* CheckConnection + * + * Verify that we still have a good connection to the backend, and if not, + * see if it can be restored. + * + * Returns true if either the connection was still there, or it could be + * restored successfully; false otherwise. If, however, there was no + * connection and the session is non-interactive, this will exit the program + * with a code of EXIT_BADCONN. + */ +static bool +CheckConnection(void) +{ + bool OK; + + OK = ConnectionUp(); + if (!OK) + { + if (!pset.cur_cmd_interactive) + { + psql_error("connection to server was lost\n"); + exit(EXIT_BADCONN); + } + + psql_error("The connection to the server was lost. Attempting reset: "); + PQreset(pset.db); + OK = ConnectionUp(); + if (!OK) + { + psql_error("Failed.\n"); + PQfinish(pset.db); + pset.db = NULL; + ResetCancelConn(); + UnsyncVariables(); + } + else + psql_error("Succeeded.\n"); + } + + return OK; +} + + + +/* + * SetCancelConn + * + * Set cancelConn to point to the current database connection. + */ +void +SetCancelConn(void) +{ + PGcancel *oldCancelConn; + +#ifdef WIN32 + EnterCriticalSection(&cancelConnLock); +#endif + + /* Free the old one if we have one */ + oldCancelConn = cancelConn; + /* be sure handle_sigint doesn't use pointer while freeing */ + cancelConn = NULL; + + if (oldCancelConn != NULL) + PQfreeCancel(oldCancelConn); + + cancelConn = PQgetCancel(pset.db); + +#ifdef WIN32 + LeaveCriticalSection(&cancelConnLock); +#endif +} + + +/* + * ResetCancelConn + * + * Free the current cancel connection, if any, and set to NULL. + */ +void +ResetCancelConn(void) +{ + PGcancel *oldCancelConn; + +#ifdef WIN32 + EnterCriticalSection(&cancelConnLock); +#endif + + oldCancelConn = cancelConn; + /* be sure handle_sigint doesn't use pointer while freeing */ + cancelConn = NULL; + + if (oldCancelConn != NULL) + PQfreeCancel(oldCancelConn); + +#ifdef WIN32 + LeaveCriticalSection(&cancelConnLock); +#endif +} + + +/* + * AcceptResult + * + * Checks whether a result is valid, giving an error message if necessary; + * and ensures that the connection to the backend is still up. + * + * Returns true for valid result, false for error state. + */ +static bool +AcceptResult(const PGresult *result) +{ + bool OK; + + if (!result) + OK = false; + else + switch (PQresultStatus(result)) + { + case PGRES_COMMAND_OK: + case PGRES_TUPLES_OK: + case PGRES_EMPTY_QUERY: + case PGRES_COPY_IN: + case PGRES_COPY_OUT: + /* Fine, do nothing */ + OK = true; + break; + + case PGRES_BAD_RESPONSE: + case PGRES_NONFATAL_ERROR: + case PGRES_FATAL_ERROR: + OK = false; + break; + + default: + OK = false; + psql_error("unexpected PQresultStatus: %d\n", + PQresultStatus(result)); + break; + } + + if (!OK) + { + const char *error = PQerrorMessage(pset.db); + + if (strlen(error)) + psql_error("%s", error); + + CheckConnection(); + } + + return OK; +} + + + +/* + * PSQLexec + * + * This is the way to send "backdoor" queries (those not directly entered + * by the user). It is subject to -E but not -e. + * + * Caller is responsible for handling the ensuing processing if a COPY + * command is sent. + * + * Note: we don't bother to check PQclientEncoding; it is assumed that no + * caller uses this path to issue "SET CLIENT_ENCODING". + */ +PGresult * +PSQLexec(const char *query) +{ + PGresult *res; + + if (!pset.db) + { + psql_error("You are currently not connected to a database.\n"); + return NULL; + } + + if (pset.echo_hidden != PSQL_ECHO_HIDDEN_OFF) + { + printf(_("********* QUERY **********\n" + "%s\n" + "**************************\n\n"), query); + fflush(stdout); + if (pset.logfile) + { + fprintf(pset.logfile, + _("********* QUERY **********\n" + "%s\n" + "**************************\n\n"), query); + fflush(pset.logfile); + } + + if (pset.echo_hidden == PSQL_ECHO_HIDDEN_NOEXEC) + return NULL; + } + + SetCancelConn(); + + res = PQexec(pset.db, query); + + ResetCancelConn(); + + if (!AcceptResult(res)) + { + PQclear(res); + res = NULL; + } + + return res; +} + + +/* + * PSQLexecWatch + * + * This function is used for \watch command to send the query to + * the server and print out the results. + * + * Returns 1 if the query executed successfully, 0 if it cannot be repeated, + * e.g., because of the interrupt, -1 on error. + */ +int +PSQLexecWatch(const char *query, const printQueryOpt *opt) +{ + PGresult *res; + double elapsed_msec = 0; + instr_time before; + instr_time after; + + if (!pset.db) + { + psql_error("You are currently not connected to a database.\n"); + return 0; + } + + SetCancelConn(); + + if (pset.timing) + INSTR_TIME_SET_CURRENT(before); + + res = PQexec(pset.db, query); + + ResetCancelConn(); + + if (!AcceptResult(res)) + { + PQclear(res); + return 0; + } + + if (pset.timing) + { + INSTR_TIME_SET_CURRENT(after); + INSTR_TIME_SUBTRACT(after, before); + elapsed_msec = INSTR_TIME_GET_MILLISEC(after); + } + + /* + * If SIGINT is sent while the query is processing, the interrupt will be + * consumed. The user's intention, though, is to cancel the entire watch + * process, so detect a sent cancellation request and exit in this case. + */ + if (cancel_pressed) + { + PQclear(res); + return 0; + } + + switch (PQresultStatus(res)) + { + case PGRES_TUPLES_OK: + printQuery(res, opt, pset.queryFout, false, pset.logfile); + break; + + case PGRES_COMMAND_OK: + fprintf(pset.queryFout, "%s\n%s\n\n", opt->title, PQcmdStatus(res)); + break; + + case PGRES_EMPTY_QUERY: + psql_error(_("\\watch cannot be used with an empty query\n")); + PQclear(res); + return -1; + + case PGRES_COPY_OUT: + case PGRES_COPY_IN: + case PGRES_COPY_BOTH: + psql_error(_("\\watch cannot be used with COPY\n")); + PQclear(res); + return -1; + + default: + psql_error(_("unexpected result status for \\watch\n")); + PQclear(res); + return -1; + } + + PQclear(res); + + fflush(pset.queryFout); + + /* Possible microtiming output */ + if (pset.timing) + printf(_("Time: %.3f ms\n"), elapsed_msec); + + return 1; +} + + +/* + * PrintNotifications: check for asynchronous notifications, and print them out + */ +static void +PrintNotifications(void) +{ + PGnotify *notify; + + while ((notify = PQnotifies(pset.db))) + { + /* for backward compatibility, only show payload if nonempty */ + if (notify->extra[0]) + fprintf(pset.queryFout, _("Asynchronous notification \"%s\" with payload \"%s\" received from server process with PID %d.\n"), + notify->relname, notify->extra, notify->be_pid); + else + fprintf(pset.queryFout, _("Asynchronous notification \"%s\" received from server process with PID %d.\n"), + notify->relname, notify->be_pid); + fflush(pset.queryFout); + PQfreemem(notify); + } +} + + +/* + * PrintQueryTuples: assuming query result is OK, print its tuples + * + * Returns true if successful, false otherwise. + */ +static bool +PrintQueryTuples(const PGresult *results) +{ + printQueryOpt my_popt = pset.popt; + + /* write output to \g argument, if any */ + if (pset.gfname) + { + FILE *fout; + bool is_pipe; + + if (!openQueryOutputFile(pset.gfname, &fout, &is_pipe)) + return false; + if (is_pipe) + disable_sigpipe_trap(); + + printQuery(results, &my_popt, fout, false, pset.logfile); + + if (is_pipe) + { + pclose(fout); + restore_sigpipe_trap(); + } + else + fclose(fout); + } + else + printQuery(results, &my_popt, pset.queryFout, false, pset.logfile); + + return true; +} + + +/* + * StoreQueryTuple: assuming query result is OK, save data into variables + * + * Returns true if successful, false otherwise. + */ +static bool +StoreQueryTuple(const PGresult *result) +{ + bool success = true; + + if (PQntuples(result) < 1) + { + psql_error("no rows returned for \\gset\n"); + success = false; + } + else if (PQntuples(result) > 1) + { + psql_error("more than one row returned for \\gset\n"); + success = false; + } + else + { + int i; + + for (i = 0; i < PQnfields(result); i++) + { + char *colname = PQfname(result, i); + char *varname; + char *value; + + /* concate prefix and column name */ + varname = psprintf("%s%s", pset.gset_prefix, colname); + + if (!PQgetisnull(result, 0, i)) + value = PQgetvalue(result, 0, i); + else + { + /* for NULL value, unset rather than set the variable */ + value = NULL; + } + + if (!SetVariable(pset.vars, varname, value)) + { + psql_error("could not set variable \"%s\"\n", varname); + free(varname); + success = false; + break; + } + + free(varname); + } + } + + return success; +} + + +/* + * ProcessResult: utility function for use by SendQuery() only + * + * When our command string contained a COPY FROM STDIN or COPY TO STDOUT, + * PQexec() has stopped at the PGresult associated with the first such + * command. In that event, we'll marshal data for the COPY and then cycle + * through any subsequent PGresult objects. + * + * When the command string contained no such COPY command, this function + * degenerates to an AcceptResult() call. + * + * Changes its argument to point to the last PGresult of the command string, + * or NULL if that result was for a COPY TO STDOUT. (Returning NULL prevents + * the command status from being printed, which we want in that case so that + * the status line doesn't get taken as part of the COPY data.) + * + * Returns true on complete success, false otherwise. Possible failure modes + * include purely client-side problems; check the transaction status for the + * server-side opinion. + */ +static bool +ProcessResult(PGresult **results) +{ + bool success = true; + bool first_cycle = true; + uint64 copySizeUnlimited = 0; + + for (;;) + { + ExecStatusType result_status; + bool is_copy; + PGresult *next_result; + + if (!AcceptResult(*results)) + { + /* + * Failure at this point is always a server-side failure or a + * failure to submit the command string. Either way, we're + * finished with this command string. + */ + success = false; + break; + } + + result_status = PQresultStatus(*results); + switch (result_status) + { + case PGRES_EMPTY_QUERY: + case PGRES_COMMAND_OK: + case PGRES_TUPLES_OK: + is_copy = false; + break; + + case PGRES_COPY_OUT: + case PGRES_COPY_IN: + is_copy = true; + break; + + default: + /* AcceptResult() should have caught anything else. */ + is_copy = false; + psql_error("unexpected PQresultStatus: %d\n", result_status); + break; + } + + if (is_copy) + { + /* + * Marshal the COPY data. Either subroutine will get the + * connection out of its COPY state, then call PQresultStatus() + * once and report any error. + * + * If pset.copyStream is set, use that as data source/sink, + * otherwise use queryFout or cur_cmd_source as appropriate. + */ + FILE *copystream = pset.copyStream; + PGresult *copy_result; + + SetCancelConn(); + if (result_status == PGRES_COPY_OUT) + { + if (!copystream) + copystream = pset.queryFout; + success = handleCopyOut(pset.db, + copystream, + ©_result) && success; + + /* + * Suppress status printing if the report would go to the same + * place as the COPY data just went. Note this doesn't + * prevent error reporting, since handleCopyOut did that. + */ + if (copystream == pset.queryFout) + { + PQclear(copy_result); + copy_result = NULL; + } + } + else + { + if (!copystream) + copystream = pset.cur_cmd_source; + success = handleCopyIn(pset.db, copystream, + PQbinaryTuples(*results), ©_result, + copySizeUnlimited) && success; + } + ResetCancelConn(); + + /* + * Replace the PGRES_COPY_OUT/IN result with COPY command's exit + * status, or with NULL if we want to suppress printing anything. + */ + PQclear(*results); + *results = copy_result; + } + else if (first_cycle) + { + /* fast path: no COPY commands; PQexec visited all results */ + break; + } + + /* + * Check PQgetResult() again. In the typical case of a single-command + * string, it will return NULL. Otherwise, we'll have other results + * to process that may include other COPYs. We keep the last result. + */ + next_result = PQgetResult(pset.db); + if (!next_result) + break; + + PQclear(*results); + *results = next_result; + first_cycle = false; + } + + /* may need this to recover from conn loss during COPY */ + if (!first_cycle && !CheckConnection()) + return false; + + return success; +} + + +/* + * PrintQueryStatus: report command status as required + * + * Note: Utility function for use by PrintQueryResults() only. + */ +static void +PrintQueryStatus(PGresult *results) +{ + char buf[16]; + + if (!pset.quiet) + { + if (pset.popt.topt.format == PRINT_HTML) + { + fputs("

", pset.queryFout); + html_escaped_print(PQcmdStatus(results), pset.queryFout); + fputs("

\n", pset.queryFout); + } + else + fprintf(pset.queryFout, "%s\n", PQcmdStatus(results)); + } + + if (pset.logfile) + fprintf(pset.logfile, "%s\n", PQcmdStatus(results)); + + snprintf(buf, sizeof(buf), "%u", (unsigned int) PQoidValue(results)); + SetVariable(pset.vars, "LASTOID", buf); +} + + +/* + * PrintQueryResults: print out (or store) query results as required + * + * Note: Utility function for use by SendQuery() only. + * + * Returns true if the query executed successfully, false otherwise. + */ +static bool +PrintQueryResults(PGresult *results) +{ + bool success; + const char *cmdstatus; + + if (!results) + return false; + + switch (PQresultStatus(results)) + { + case PGRES_TUPLES_OK: + /* store or print the data ... */ + if (pset.gset_prefix) + success = StoreQueryTuple(results); + else + success = PrintQueryTuples(results); + /* if it's INSERT/UPDATE/DELETE RETURNING, also print status */ + cmdstatus = PQcmdStatus(results); + if (strncmp(cmdstatus, "INSERT", 6) == 0 || + strncmp(cmdstatus, "UPDATE", 6) == 0 || + strncmp(cmdstatus, "DELETE", 6) == 0) + PrintQueryStatus(results); + break; + + case PGRES_COMMAND_OK: + PrintQueryStatus(results); + success = true; + break; + + case PGRES_EMPTY_QUERY: + success = true; + break; + + case PGRES_COPY_OUT: + case PGRES_COPY_IN: + /* nothing to do here */ + success = true; + break; + + case PGRES_BAD_RESPONSE: + case PGRES_NONFATAL_ERROR: + case PGRES_FATAL_ERROR: + success = false; + break; + + default: + success = false; + psql_error("unexpected PQresultStatus: %d\n", + PQresultStatus(results)); + break; + } + + fflush(pset.queryFout); + + return success; +} + + +/* + * SendQuery: send the query string to the backend + * (and print out results) + * + * Note: This is the "front door" way to send a query. That is, use it to + * send queries actually entered by the user. These queries will be subject to + * single step mode. + * To send "back door" queries (generated by slash commands, etc.) in a + * controlled way, use PSQLexec(). + * + * Returns true if the query executed successfully, false otherwise. + */ +bool +SendQuery(const char *query) +{ + PGresult *results; + PGTransactionStatusType transaction_status; + double elapsed_msec = 0; + bool OK = false; + bool on_error_rollback_savepoint = false; + static bool on_error_rollback_warning = false; + + if (!pset.db) + { + psql_error("You are currently not connected to a database.\n"); + goto sendquery_cleanup; + } + + if (pset.singlestep) + { + char buf[3]; + + printf(_("***(Single step mode: verify command)*******************************************\n" + "%s\n" + "***(press return to proceed or enter x and return to cancel)********************\n"), + query); + fflush(stdout); + if (fgets(buf, sizeof(buf), stdin) != NULL) + if (buf[0] == 'x') + goto sendquery_cleanup; + } + else if (pset.echo == PSQL_ECHO_QUERIES) + { + puts(query); + fflush(stdout); + } + + if (pset.logfile) + { + fprintf(pset.logfile, + _("********* QUERY **********\n" + "%s\n" + "**************************\n\n"), query); + fflush(pset.logfile); + } + + SetCancelConn(); + + transaction_status = PQtransactionStatus(pset.db); + + if (transaction_status == PQTRANS_IDLE && + !pset.autocommit && + !command_no_begin(query)) + { + results = PQexec(pset.db, "BEGIN"); + if (PQresultStatus(results) != PGRES_COMMAND_OK) + { + psql_error("%s", PQerrorMessage(pset.db)); + PQclear(results); + ResetCancelConn(); + goto sendquery_cleanup; + } + PQclear(results); + transaction_status = PQtransactionStatus(pset.db); + } + + if (transaction_status == PQTRANS_INTRANS && + pset.on_error_rollback != PSQL_ERROR_ROLLBACK_OFF && + (pset.cur_cmd_interactive || + pset.on_error_rollback == PSQL_ERROR_ROLLBACK_ON)) + { + if (on_error_rollback_warning == false && pset.sversion < 80000) + { + psql_error("The server (version %d.%d) does not support savepoints for ON_ERROR_ROLLBACK.\n", + pset.sversion / 10000, (pset.sversion / 100) % 100); + on_error_rollback_warning = true; + } + else + { + results = PQexec(pset.db, "SAVEPOINT pg_psql_temporary_savepoint"); + if (PQresultStatus(results) != PGRES_COMMAND_OK) + { + psql_error("%s", PQerrorMessage(pset.db)); + PQclear(results); + ResetCancelConn(); + goto sendquery_cleanup; + } + PQclear(results); + on_error_rollback_savepoint = true; + } + } + + if (pset.fetch_count <= 0 || !is_select_command(query)) + { + /* Default fetch-it-all-and-print mode */ + instr_time before, + after; + + if (pset.timing) + INSTR_TIME_SET_CURRENT(before); + + results = PQexec(pset.db, query); + + /* these operations are included in the timing result: */ + ResetCancelConn(); + OK = ProcessResult(&results); + + if (pset.timing) + { + INSTR_TIME_SET_CURRENT(after); + INSTR_TIME_SUBTRACT(after, before); + elapsed_msec = INSTR_TIME_GET_MILLISEC(after); + } + + /* but printing results isn't: */ + if (OK && results) + OK = PrintQueryResults(results); + } + else + { + /* Fetch-in-segments mode */ + OK = ExecQueryUsingCursor(query, &elapsed_msec); + ResetCancelConn(); + results = NULL; /* PQclear(NULL) does nothing */ + } + + if (!OK && pset.echo == PSQL_ECHO_ERRORS) + psql_error("STATEMENT: %s\n", query); + + /* If we made a temporary savepoint, possibly release/rollback */ + if (on_error_rollback_savepoint) + { + const char *svptcmd = NULL; + + transaction_status = PQtransactionStatus(pset.db); + + switch (transaction_status) + { + case PQTRANS_INERROR: + /* We always rollback on an error */ + svptcmd = "ROLLBACK TO pg_psql_temporary_savepoint"; + break; + + case PQTRANS_IDLE: + /* If they are no longer in a transaction, then do nothing */ + break; + + case PQTRANS_INTRANS: + + /* + * Do nothing if they are messing with savepoints themselves: + * If the user did RELEASE or ROLLBACK, our savepoint is gone. + * If they issued a SAVEPOINT, releasing ours would remove + * theirs. + */ + if (results && + (strcmp(PQcmdStatus(results), "SAVEPOINT") == 0 || + strcmp(PQcmdStatus(results), "RELEASE") == 0 || + strcmp(PQcmdStatus(results), "ROLLBACK") == 0)) + svptcmd = NULL; + else + svptcmd = "RELEASE pg_psql_temporary_savepoint"; + break; + + case PQTRANS_ACTIVE: + case PQTRANS_UNKNOWN: + default: + OK = false; + /* PQTRANS_UNKNOWN is expected given a broken connection. */ + if (transaction_status != PQTRANS_UNKNOWN || ConnectionUp()) + psql_error("unexpected transaction status (%d)\n", + transaction_status); + break; + } + + if (svptcmd) + { + PGresult *svptres; + + svptres = PQexec(pset.db, svptcmd); + if (PQresultStatus(svptres) != PGRES_COMMAND_OK) + { + psql_error("%s", PQerrorMessage(pset.db)); + PQclear(svptres); + OK = false; + + PQclear(results); + ResetCancelConn(); + goto sendquery_cleanup; + } + PQclear(svptres); + } + } + + PQclear(results); + + /* Possible microtiming output */ + if (pset.timing) + printf(_("Time: %.3f ms\n"), elapsed_msec); + + /* check for events that may occur during query execution */ + + if (pset.encoding != PQclientEncoding(pset.db) && + PQclientEncoding(pset.db) >= 0) + { + /* track effects of SET CLIENT_ENCODING */ + pset.encoding = PQclientEncoding(pset.db); + pset.popt.topt.encoding = pset.encoding; + SetVariable(pset.vars, "ENCODING", + pg_encoding_to_char(pset.encoding)); + } + + PrintNotifications(); + + /* perform cleanup that should occur after any attempted query */ + +sendquery_cleanup: + + /* reset \g's output-to-filename trigger */ + if (pset.gfname) + { + free(pset.gfname); + pset.gfname = NULL; + } + + /* reset \gset trigger */ + if (pset.gset_prefix) + { + free(pset.gset_prefix); + pset.gset_prefix = NULL; + } + + return OK; +} + + +/* + * ExecQueryUsingCursor: run a SELECT-like query using a cursor + * + * This feature allows result sets larger than RAM to be dealt with. + * + * Returns true if the query executed successfully, false otherwise. + * + * If pset.timing is on, total query time (exclusive of result-printing) is + * stored into *elapsed_msec. + */ +static bool +ExecQueryUsingCursor(const char *query, double *elapsed_msec) +{ + bool OK = true; + PGresult *results; + PQExpBufferData buf; + printQueryOpt my_popt = pset.popt; + FILE *fout; + bool is_pipe; + bool is_pager = false; + bool started_txn = false; + int ntuples; + int fetch_count; + char fetch_cmd[64]; + instr_time before, + after; + int flush_error; + + *elapsed_msec = 0; + + /* initialize print options for partial table output */ + my_popt.topt.start_table = true; + my_popt.topt.stop_table = false; + my_popt.topt.prior_records = 0; + + if (pset.timing) + INSTR_TIME_SET_CURRENT(before); + + /* if we're not in a transaction, start one */ + if (PQtransactionStatus(pset.db) == PQTRANS_IDLE) + { + results = PQexec(pset.db, "BEGIN"); + OK = AcceptResult(results) && + (PQresultStatus(results) == PGRES_COMMAND_OK); + PQclear(results); + if (!OK) + return false; + started_txn = true; + } + + /* Send DECLARE CURSOR */ + initPQExpBuffer(&buf); + appendPQExpBuffer(&buf, "DECLARE _psql_cursor NO SCROLL CURSOR FOR\n%s", + query); + + results = PQexec(pset.db, buf.data); + OK = AcceptResult(results) && + (PQresultStatus(results) == PGRES_COMMAND_OK); + PQclear(results); + termPQExpBuffer(&buf); + if (!OK) + goto cleanup; + + if (pset.timing) + { + INSTR_TIME_SET_CURRENT(after); + INSTR_TIME_SUBTRACT(after, before); + *elapsed_msec += INSTR_TIME_GET_MILLISEC(after); + } + + /* + * In \gset mode, we force the fetch count to be 2, so that we will throw + * the appropriate error if the query returns more than one row. + */ + if (pset.gset_prefix) + fetch_count = 2; + else + fetch_count = pset.fetch_count; + + snprintf(fetch_cmd, sizeof(fetch_cmd), + "FETCH FORWARD %d FROM _psql_cursor", + fetch_count); + + /* prepare to write output to \g argument, if any */ + if (pset.gfname) + { + if (!openQueryOutputFile(pset.gfname, &fout, &is_pipe)) + { + OK = false; + goto cleanup; + } + if (is_pipe) + disable_sigpipe_trap(); + } + else + { + fout = pset.queryFout; + is_pipe = false; /* doesn't matter */ + } + + /* clear any pre-existing error indication on the output stream */ + clearerr(fout); + + for (;;) + { + if (pset.timing) + INSTR_TIME_SET_CURRENT(before); + + /* get fetch_count tuples at a time */ + results = PQexec(pset.db, fetch_cmd); + + if (pset.timing) + { + INSTR_TIME_SET_CURRENT(after); + INSTR_TIME_SUBTRACT(after, before); + *elapsed_msec += INSTR_TIME_GET_MILLISEC(after); + } + + if (PQresultStatus(results) != PGRES_TUPLES_OK) + { + /* shut down pager before printing error message */ + if (is_pager) + { + ClosePager(fout); + is_pager = false; + } + + OK = AcceptResult(results); + Assert(!OK); + PQclear(results); + break; + } + + if (pset.gset_prefix) + { + /* StoreQueryTuple will complain if not exactly one row */ + OK = StoreQueryTuple(results); + PQclear(results); + break; + } + + ntuples = PQntuples(results); + + if (ntuples < fetch_count) + { + /* this is the last result set, so allow footer decoration */ + my_popt.topt.stop_table = true; + } + else if (fout == stdout && !is_pager) + { + /* + * If query requires multiple result sets, hack to ensure that + * only one pager instance is used for the whole mess + */ + fout = PageOutput(INT_MAX, &(my_popt.topt)); + is_pager = true; + } + + printQuery(results, &my_popt, fout, is_pager, pset.logfile); + + PQclear(results); + + /* after the first result set, disallow header decoration */ + my_popt.topt.start_table = false; + my_popt.topt.prior_records += ntuples; + + /* + * Make sure to flush the output stream, so intermediate results are + * visible to the client immediately. We check the results because if + * the pager dies/exits/etc, there's no sense throwing more data at + * it. + */ + flush_error = fflush(fout); + + /* + * Check if we are at the end, if a cancel was pressed, or if there + * were any errors either trying to flush out the results, or more + * generally on the output stream at all. If we hit any errors + * writing things to the stream, we presume $PAGER has disappeared and + * stop bothering to pull down more data. + */ + if (ntuples < fetch_count || cancel_pressed || flush_error || + ferror(fout)) + break; + } + + if (pset.gfname) + { + /* close \g argument file/pipe */ + if (is_pipe) + { + pclose(fout); + restore_sigpipe_trap(); + } + else + fclose(fout); + } + else if (is_pager) + { + /* close transient pager */ + ClosePager(fout); + } + +cleanup: + if (pset.timing) + INSTR_TIME_SET_CURRENT(before); + + /* + * We try to close the cursor on either success or failure, but on failure + * ignore the result (it's probably just a bleat about being in an aborted + * transaction) + */ + results = PQexec(pset.db, "CLOSE _psql_cursor"); + if (OK) + { + OK = AcceptResult(results) && + (PQresultStatus(results) == PGRES_COMMAND_OK); + } + PQclear(results); + + if (started_txn) + { + results = PQexec(pset.db, OK ? "COMMIT" : "ROLLBACK"); + OK &= AcceptResult(results) && + (PQresultStatus(results) == PGRES_COMMAND_OK); + PQclear(results); + } + + if (pset.timing) + { + INSTR_TIME_SET_CURRENT(after); + INSTR_TIME_SUBTRACT(after, before); + *elapsed_msec += INSTR_TIME_GET_MILLISEC(after); + } + + return OK; +} + + +/* + * Advance the given char pointer over white space and SQL comments. + */ +static const char * +skip_white_space(const char *query) +{ + int cnestlevel = 0; /* slash-star comment nest level */ + + while (*query) + { + int mblen = PQmblen(query, pset.encoding); + + /* + * Note: we assume the encoding is a superset of ASCII, so that for + * example "query[0] == '/'" is meaningful. However, we do NOT assume + * that the second and subsequent bytes of a multibyte character + * couldn't look like ASCII characters; so it is critical to advance + * by mblen, not 1, whenever we haven't exactly identified the + * character we are skipping over. + */ + if (isspace((unsigned char) *query)) + query += mblen; + else if (query[0] == '/' && query[1] == '*') + { + cnestlevel++; + query += 2; + } + else if (cnestlevel > 0 && query[0] == '*' && query[1] == '/') + { + cnestlevel--; + query += 2; + } + else if (cnestlevel == 0 && query[0] == '-' && query[1] == '-') + { + query += 2; + + /* + * We have to skip to end of line since any slash-star inside the + * -- comment does NOT start a slash-star comment. + */ + while (*query) + { + if (*query == '\n') + { + query++; + break; + } + query += PQmblen(query, pset.encoding); + } + } + else if (cnestlevel > 0) + query += mblen; + else + break; /* found first token */ + } + + return query; +} + + +/* + * Check whether a command is one of those for which we should NOT start + * a new transaction block (ie, send a preceding BEGIN). + * + * These include the transaction control statements themselves, plus + * certain statements that the backend disallows inside transaction blocks. + */ +static bool +command_no_begin(const char *query) +{ + int wordlen; + + /* + * First we must advance over any whitespace and comments. + */ + query = skip_white_space(query); + + /* + * Check word length (since "beginx" is not "begin"). + */ + wordlen = 0; + while (isalpha((unsigned char) query[wordlen])) + wordlen += PQmblen(&query[wordlen], pset.encoding); + + /* + * Transaction control commands. These should include every keyword that + * gives rise to a TransactionStmt in the backend grammar, except for the + * savepoint-related commands. + * + * (We assume that START must be START TRANSACTION, since there is + * presently no other "START foo" command.) + */ + if (wordlen == 5 && pg_strncasecmp(query, "abort", 5) == 0) + return true; + if (wordlen == 5 && pg_strncasecmp(query, "begin", 5) == 0) + return true; + if (wordlen == 5 && pg_strncasecmp(query, "start", 5) == 0) + return true; + if (wordlen == 6 && pg_strncasecmp(query, "commit", 6) == 0) + return true; + if (wordlen == 3 && pg_strncasecmp(query, "end", 3) == 0) + return true; + if (wordlen == 8 && pg_strncasecmp(query, "rollback", 8) == 0) + return true; + if (wordlen == 7 && pg_strncasecmp(query, "prepare", 7) == 0) + { + /* PREPARE TRANSACTION is a TC command, PREPARE foo is not */ + query += wordlen; + + query = skip_white_space(query); + + wordlen = 0; + while (isalpha((unsigned char) query[wordlen])) + wordlen += PQmblen(&query[wordlen], pset.encoding); + + if (wordlen == 11 && pg_strncasecmp(query, "transaction", 11) == 0) + return true; + return false; + } + + /* + * Commands not allowed within transactions. The statements checked for + * here should be exactly those that call PreventTransactionChain() in the + * backend. + */ + if (wordlen == 6 && pg_strncasecmp(query, "vacuum", 6) == 0) + return true; + if (wordlen == 7 && pg_strncasecmp(query, "cluster", 7) == 0) + { + /* CLUSTER with any arguments is allowed in transactions */ + query += wordlen; + + query = skip_white_space(query); + + if (isalpha((unsigned char) query[0])) + return false; /* has additional words */ + return true; /* it's CLUSTER without arguments */ + } + + if (wordlen == 6 && pg_strncasecmp(query, "create", 6) == 0) + { + query += wordlen; + + query = skip_white_space(query); + + wordlen = 0; + while (isalpha((unsigned char) query[wordlen])) + wordlen += PQmblen(&query[wordlen], pset.encoding); + + if (wordlen == 8 && pg_strncasecmp(query, "database", 8) == 0) + return true; + if (wordlen == 10 && pg_strncasecmp(query, "tablespace", 10) == 0) + return true; + + /* CREATE [UNIQUE] INDEX CONCURRENTLY isn't allowed in xacts */ + if (wordlen == 6 && pg_strncasecmp(query, "unique", 6) == 0) + { + query += wordlen; + + query = skip_white_space(query); + + wordlen = 0; + while (isalpha((unsigned char) query[wordlen])) + wordlen += PQmblen(&query[wordlen], pset.encoding); + } + + if (wordlen == 5 && pg_strncasecmp(query, "index", 5) == 0) + { + query += wordlen; + + query = skip_white_space(query); + + wordlen = 0; + while (isalpha((unsigned char) query[wordlen])) + wordlen += PQmblen(&query[wordlen], pset.encoding); + + if (wordlen == 12 && pg_strncasecmp(query, "concurrently", 12) == 0) + return true; + } + + return false; + } + + if (wordlen == 5 && pg_strncasecmp(query, "alter", 5) == 0) + { + query += wordlen; + + query = skip_white_space(query); + + wordlen = 0; + while (isalpha((unsigned char) query[wordlen])) + wordlen += PQmblen(&query[wordlen], pset.encoding); + + /* ALTER SYSTEM isn't allowed in xacts */ + if (wordlen == 6 && pg_strncasecmp(query, "system", 6) == 0) + return true; + + return false; + } + + /* + * Note: these tests will match DROP SYSTEM and REINDEX TABLESPACE, which + * aren't really valid commands so we don't care much. The other four + * possible matches are correct. + */ + if ((wordlen == 4 && pg_strncasecmp(query, "drop", 4) == 0) || + (wordlen == 7 && pg_strncasecmp(query, "reindex", 7) == 0)) + { + query += wordlen; + + query = skip_white_space(query); + + wordlen = 0; + while (isalpha((unsigned char) query[wordlen])) + wordlen += PQmblen(&query[wordlen], pset.encoding); + + if (wordlen == 8 && pg_strncasecmp(query, "database", 8) == 0) + return true; + if (wordlen == 6 && pg_strncasecmp(query, "system", 6) == 0) + return true; + if (wordlen == 10 && pg_strncasecmp(query, "tablespace", 10) == 0) + return true; + + /* DROP INDEX CONCURRENTLY isn't allowed in xacts */ + if (wordlen == 5 && pg_strncasecmp(query, "index", 5) == 0) + { + query += wordlen; + + query = skip_white_space(query); + + wordlen = 0; + while (isalpha((unsigned char) query[wordlen])) + wordlen += PQmblen(&query[wordlen], pset.encoding); + + if (wordlen == 12 && pg_strncasecmp(query, "concurrently", 12) == 0) + return true; + + return false; + } + + return false; + } + + /* DISCARD ALL isn't allowed in xacts, but other variants are allowed. */ + if (wordlen == 7 && pg_strncasecmp(query, "discard", 7) == 0) + { + query += wordlen; + + query = skip_white_space(query); + + wordlen = 0; + while (isalpha((unsigned char) query[wordlen])) + wordlen += PQmblen(&query[wordlen], pset.encoding); + + if (wordlen == 3 && pg_strncasecmp(query, "all", 3) == 0) + return true; + return false; + } + + return false; +} + + +/* + * Check whether the specified command is a SELECT (or VALUES). + */ +static bool +is_select_command(const char *query) +{ + int wordlen; + + /* + * First advance over any whitespace, comments and left parentheses. + */ + for (;;) + { + query = skip_white_space(query); + if (query[0] == '(') + query++; + else + break; + } + + /* + * Check word length (since "selectx" is not "select"). + */ + wordlen = 0; + while (isalpha((unsigned char) query[wordlen])) + wordlen += PQmblen(&query[wordlen], pset.encoding); + + if (wordlen == 6 && pg_strncasecmp(query, "select", 6) == 0) + return true; + + if (wordlen == 6 && pg_strncasecmp(query, "values", 6) == 0) + return true; + + return false; +} + + +/* + * Test if the current user is a database superuser. + * + * Note: this will correctly detect superuserness only with a protocol-3.0 + * or newer backend; otherwise it will always say "false". + */ +bool +is_superuser(void) +{ + const char *val; + + if (!pset.db) + return false; + + val = PQparameterStatus(pset.db, "is_superuser"); + + if (val && strcmp(val, "on") == 0) + return true; + + return false; +} + + +/* + * Test if the current session uses standard string literals. + * + * Note: With a pre-protocol-3.0 connection this will always say "false", + * which should be the right answer. + */ +bool +standard_strings(void) +{ + const char *val; + + if (!pset.db) + return false; + + val = PQparameterStatus(pset.db, "standard_conforming_strings"); + + if (val && strcmp(val, "on") == 0) + return true; + + return false; +} + + +/* + * Return the session user of the current connection. + * + * Note: this will correctly detect the session user only with a + * protocol-3.0 or newer backend; otherwise it will return the + * connection user. + */ +const char * +session_username(void) +{ + const char *val; + + if (!pset.db) + return NULL; + + val = PQparameterStatus(pset.db, "session_authorization"); + if (val) + return val; + else + return PQuser(pset.db); +} + + +/* expand_tilde + * + * substitute '~' with HOME or '~username' with username's home dir + * + */ +void +expand_tilde(char **filename) +{ + if (!filename || !(*filename)) + return; + + /* + * WIN32 doesn't use tilde expansion for file names. Also, it uses tilde + * for short versions of long file names, though the tilde is usually + * toward the end, not at the beginning. + */ +#ifndef WIN32 + + /* try tilde expansion */ + if (**filename == '~') + { + char *fn; + char oldp, + *p; + struct passwd *pw; + char home[MAXPGPATH]; + + fn = *filename; + *home = '\0'; + + p = fn + 1; + while (*p != '/' && *p != '\0') + p++; + + oldp = *p; + *p = '\0'; + + if (*(fn + 1) == '\0') + get_home_path(home); /* ~ or ~/ only */ + else if ((pw = getpwnam(fn + 1)) != NULL) + strlcpy(home, pw->pw_dir, sizeof(home)); /* ~user */ + + *p = oldp; + if (strlen(home) != 0) + { + char *newfn; + + newfn = psprintf("%s%s", home, p); + free(fn); + *filename = newfn; + } + } +#endif + + return; +} + +/* + * Checks if connection string starts with either of the valid URI prefix + * designators. + * + * Returns the URI prefix length, 0 if the string doesn't contain a URI prefix. + * + * XXX This is a duplicate of the eponymous libpq function. + */ +static int +uri_prefix_length(const char *connstr) +{ + /* The connection URI must start with either of the following designators: */ + static const char uri_designator[] = "postgresql://"; + static const char short_uri_designator[] = "postgres://"; + + if (strncmp(connstr, uri_designator, + sizeof(uri_designator) - 1) == 0) + return sizeof(uri_designator) - 1; + + if (strncmp(connstr, short_uri_designator, + sizeof(short_uri_designator) - 1) == 0) + return sizeof(short_uri_designator) - 1; + + return 0; +} + +/* + * Recognized connection string either starts with a valid URI prefix or + * contains a "=" in it. + * + * Must be consistent with parse_connection_string: anything for which this + * returns true should at least look like it's parseable by that routine. + * + * XXX This is a duplicate of the eponymous libpq function. + */ +bool +recognized_connection_string(const char *connstr) +{ + return uri_prefix_length(connstr) != 0 || strchr(connstr, '=') != NULL; +} diff --git a/src/bin/csql/common.h b/src/bin/csql/common.h new file mode 100644 index 000000000..bb5fd01cf --- /dev/null +++ b/src/bin/csql/common.h @@ -0,0 +1,59 @@ +/* + * psql - the PostgreSQL interactive terminal + * + * Copyright (c) 2000-2015, PostgreSQL Global Development Group + * + * src/bin/psql/common.h + */ +#ifndef COMMON_H +#define COMMON_H + +#include "postgres_fe.h" +#include +#include "libpq-fe.h" + +#include "print.h" + +#define atooid(x) ((Oid) strtoul((x), NULL, 10)) + +extern bool openQueryOutputFile(const char *fname, FILE **fout, bool *is_pipe); +extern bool setQFout(const char *fname); + +#if (PG_VERSION_NUM >= 90500) +extern void psql_error(const char *fmt,...) pg_attribute_printf(1, 2); +#else +extern void +psql_error(const char *fmt,...) +/* This lets gcc check the format string for consistency. */ +__attribute__((format(PG_PRINTF_ATTRIBUTE, 1, 2))); +#endif + +extern void NoticeProcessor(void *arg, const char *message); + +extern volatile bool sigint_interrupt_enabled; + +extern sigjmp_buf sigint_interrupt_jmp; + +extern volatile bool cancel_pressed; + +/* Note: cancel_pressed is defined in print.c, see that file for reasons */ + +extern void setup_cancel_handler(void); + +extern void SetCancelConn(void); +extern void ResetCancelConn(void); + +extern PGresult *PSQLexec(const char *query); +extern int PSQLexecWatch(const char *query, const printQueryOpt *opt); + +extern bool SendQuery(const char *query); + +extern bool is_superuser(void); +extern bool standard_strings(void); +extern const char *session_username(void); + +extern void expand_tilde(char **filename); + +extern bool recognized_connection_string(const char *connstr); + +#endif /* COMMON_H */ diff --git a/src/bin/csql/copy.c b/src/bin/csql/copy.c new file mode 100644 index 000000000..52a4bf8b8 --- /dev/null +++ b/src/bin/csql/copy.c @@ -0,0 +1,595 @@ +/* + * psql - the PostgreSQL interactive terminal + * + * Copyright (c) 2000-2015, PostgreSQL Global Development Group + * + * src/bin/psql/copy.c + */ +#include "postgres_fe.h" +#include "copy.h" + +#include +#include +#ifndef WIN32 +#include /* for isatty */ +#else +#include /* I think */ +#endif + +#include "libpq-fe.h" +#include "pqexpbuffer.h" +#include "dumputils.h" + +#include "settings.h" +#include "common.h" +#include "prompt.h" + + +/* + * Execute a \copy command (frontend copy). We have to open a file (or execute + * a command), then submit a COPY query to the backend and either feed it data + * from the file or route its response into the file. + */ +bool +do_copy(const char *args) +{ + copy_options *options = NULL; + PQExpBufferData query = { NULL, 0, 0 }; + FILE *copystream = NULL; + bool success = false; + bool fileClosed = false; + + /* parse options */ + options = parse_slash_copy(args); + + if (!options) + return false; + + /* open file stream to copy data into or out of */ + copystream = OpenCopyStream(options); + if (copystream == NULL) + { + free_copy_options(options); + + return false; + } + + /* build the command we will send to the backend */ + initPQExpBuffer(&query); + printfPQExpBuffer(&query, "COPY "); + appendPQExpBufferStr(&query, options->before_tofrom); + if (options->from) + appendPQExpBufferStr(&query, " FROM STDIN "); + else + appendPQExpBufferStr(&query, " TO STDOUT "); + if (options->after_tofrom) + appendPQExpBufferStr(&query, options->after_tofrom); + + /* run it like a user command, but with copystream as data source/sink */ + pset.copyStream = copystream; + success = SendQuery(query.data); + pset.copyStream = NULL; + termPQExpBuffer(&query); + + /* close file stream */ + fileClosed = CloseCopyStream(options, copystream); + if (!fileClosed) + { + success = false; + } + + free_copy_options(options); + return success; +} + + +/* + * HandleCopyData executes client-side copy data protocols by dispatching the + * call to the appropriate copy protocol function. On successful execution of + * the protocol, the function returns true. Otherwise, the function returns + * false. + * + * Please note that we refactored this function from a previous version (v9.1) + * of PostgreSQL so that copy.c and stage.c could share the same code path. Now + * that do_copy uses SendQuery(), we should move or re-refactor this function. + */ +bool +HandleCopyData(PGconn *connection, ExecStatusType copyStatus, bool copyIsBinary, + FILE *copyStream, uint64 copySizeLimit) +{ + ExecStatusType drainStatus = 0; + PGresult *drainResult = NULL; + bool copyOK = true; + + if (copyStatus == PGRES_COPY_OUT) + { + SetCancelConn(); + copyOK = handleCopyOut(connection, copyStream, &drainResult); + ResetCancelConn(); + } + else if (copyStatus == PGRES_COPY_IN) + { + SetCancelConn(); + copyOK = handleCopyIn(connection, copyStream, copyIsBinary, + &drainResult, copySizeLimit); + ResetCancelConn(); + } + else if (copyStatus == PGRES_BAD_RESPONSE || + copyStatus == PGRES_NONFATAL_ERROR || + copyStatus == PGRES_FATAL_ERROR) + { + psql_error("\\copy: %s", PQerrorMessage(connection)); + copyOK = false; + } + else + { + psql_error("\\copy: unexpected response (%d)\n", copyStatus); + copyOK = false; + } + + PQclear(drainResult); + + /* + * Make sure we drain all results from libpq. Otherwise, the connection may + * still be in ASYNC_BUSY state, leading to false readings in get_prompt(). + */ + drainResult = PQgetResult(connection); + while (drainResult != NULL) + { + copyOK = false; + + drainStatus = PQresultStatus(drainResult); + psql_error("\\copy: unexpected response (%d)\n", drainStatus); + + /* if we are still in COPY IN state, try to get out of it */ + if (drainStatus == PGRES_COPY_IN) + { + PQputCopyEnd(connection, _("trying to exit copy mode")); + } + + PQclear(drainResult); + drainResult = PQgetResult(connection); + } + + return copyOK; +} + + +/* Opens input or output stream to be used during copy command. */ +FILE * +OpenCopyStream(const copy_options *options) +{ + FILE *copyStream = NULL; + + /* prepare to read or write the target file */ + if (options->file && !options->program) + canonicalize_path(options->file); + + if (options->from) + { + if (options->file) + { + if (options->program) + { + fflush(stdout); + fflush(stderr); + errno = 0; + copyStream = popen(options->file, PG_BINARY_R); + } + else + copyStream = fopen(options->file, PG_BINARY_R); + } + else if (!options->psql_inout) + copyStream = pset.cur_cmd_source; + else + copyStream = stdin; + } + else + { + if (options->file) + { + if (options->program) + { + fflush(stdout); + fflush(stderr); + errno = 0; +#ifndef WIN32 + pqsignal(SIGPIPE, SIG_IGN); +#endif + copyStream = popen(options->file, PG_BINARY_W); + } + else + copyStream = fopen(options->file, PG_BINARY_W); + } + else if (!options->psql_inout) + copyStream = pset.queryFout; + else + copyStream = stdout; + } + + if (!copyStream) + { + if (options->program) + psql_error("could not execute command \"%s\": %s\n", + options->file, strerror(errno)); + else + psql_error("%s: %s\n", + options->file, strerror(errno)); + + return NULL; + } + + if (!options->program) + { + struct stat st; + int result; + + /* make sure the specified file is not a directory */ + if ((result = fstat(fileno(copyStream), &st)) < 0) + psql_error("could not stat file \"%s\": %s\n", + options->file, strerror(errno)); + + if (result == 0 && S_ISDIR(st.st_mode)) + psql_error("%s: cannot copy from/to a directory\n", + options->file); + + if (result < 0 || S_ISDIR(st.st_mode)) + { + fclose(copyStream); + + return NULL; + } + } + + return copyStream; +} + + +/* Closes file stream used during copy command, if any. */ +bool +CloseCopyStream(const copy_options *options, FILE *copyStream) +{ + bool success = true; + + if (options->file != NULL) + { + if (options->program) + { + int pclose_rc = pclose(copyStream); + + if (pclose_rc != 0) + { + if (pclose_rc < 0) + psql_error("could not close pipe to external command: %s\n", + strerror(errno)); + else + { + char *reason = wait_result_to_str(pclose_rc); + + psql_error("%s: %s\n", options->file, + reason ? reason : ""); + if (reason) + free(reason); + } + success = false; + } +#ifndef WIN32 + pqsignal(SIGPIPE, SIG_DFL); +#endif + } + else + { + if (fclose(copyStream) != 0) + { + psql_error("%s: %s\n", options->file, strerror(errno)); + success = false; + } + } + } + + return success; +} + + +/* + * Functions for handling COPY IN/OUT data transfer. + * + * If you want to use COPY TO STDOUT/FROM STDIN in your application, + * this is the code to steal ;) + */ + +/* + * handleCopyOut + * receives data as a result of a COPY ... TO STDOUT command + * + * conn should be a database connection that you just issued COPY TO on + * and got back a PGRES_COPY_OUT result. + * copystream is the file stream for the data to go to. + * The final status for the COPY is returned into *res (but note + * we already reported the error, if it's not a success result). + * + * result is true if successful, false if not. + */ +bool +handleCopyOut(PGconn *conn, FILE *copystream, PGresult **res) +{ + bool OK = true; + char *buf; + int ret; + + for (;;) + { + ret = PQgetCopyData(conn, &buf, 0); + + if (ret < 0) + break; /* done or server/connection error */ + + if (buf) + { + if (OK && fwrite(buf, 1, ret, copystream) != ret) + { + psql_error("could not write COPY data: %s\n", + strerror(errno)); + /* complain only once, keep reading data from server */ + OK = false; + } + PQfreemem(buf); + } + } + + if (OK && fflush(copystream)) + { + psql_error("could not write COPY data: %s\n", + strerror(errno)); + OK = false; + } + + if (ret == -2) + { + psql_error("COPY data transfer failed: %s", PQerrorMessage(conn)); + OK = false; + } + + /* + * Check command status and return to normal libpq state. + * + * If for some reason libpq is still reporting PGRES_COPY_OUT state, we + * would like to forcibly exit that state, since our caller would be + * unable to distinguish that situation from reaching the next COPY in a + * command string that happened to contain two consecutive COPY TO STDOUT + * commands. However, libpq provides no API for doing that, and in + * principle it's a libpq bug anyway if PQgetCopyData() returns -1 or -2 + * but hasn't exited COPY_OUT state internally. So we ignore the + * possibility here. + */ + *res = PQgetResult(conn); + if (PQresultStatus(*res) != PGRES_COMMAND_OK) + { + psql_error("%s", PQerrorMessage(conn)); + OK = false; + } + + return OK; +} + +/* + * handleCopyIn + * sends data to complete a COPY ... FROM STDIN command + * + * conn should be a database connection that you just issued COPY FROM on + * and got back a PGRES_COPY_IN result. + * copystream is the file stream to read the data from. + * isbinary can be set from PQbinaryTuples(). + * The final status for the COPY is returned into *res (but note + * we already reported the error, if it's not a success result). + * + * result is true if successful, false if not. + */ + +/* read chunk size for COPY IN - size set to double that of Hadoop's default */ +#define COPYBUFSIZ 32768 + +bool +handleCopyIn(PGconn *conn, FILE *copystream, bool isbinary, + PGresult **res, uint64 copySizeLimit) +{ + bool OK; + const char *prompt; + char buf[COPYBUFSIZ]; + uint64 bytesCopied = 0; + + /* + * Establish longjmp destination for exiting from wait-for-input. (This is + * only effective while sigint_interrupt_enabled is TRUE.) + */ + if (sigsetjmp(sigint_interrupt_jmp, 1) != 0) + { + /* got here with longjmp */ + + /* Terminate data transfer */ + PQputCopyEnd(conn, + (PQprotocolVersion(conn) < 3) ? NULL : + _("canceled by user")); + + OK = false; + goto copyin_cleanup; + } + + /* Prompt if interactive input */ + if (isatty(fileno(copystream))) + { + if (!pset.quiet) + puts(_("Enter data to be copied followed by a newline.\n" + "End with a backslash and a period on a line by itself.")); + prompt = get_prompt(PROMPT_COPY); + } + else + prompt = NULL; + + OK = true; + + if (isbinary) + { + /* interactive input probably silly, but give one prompt anyway */ + if (prompt) + { + fputs(prompt, stdout); + fflush(stdout); + } + + for (;;) + { + int buflen; + + /* enable longjmp while waiting for input */ + sigint_interrupt_enabled = true; + + buflen = fread(buf, 1, COPYBUFSIZ, copystream); + + sigint_interrupt_enabled = false; + + if (buflen <= 0) + break; + + if (PQputCopyData(conn, buf, buflen) <= 0) + { + OK = false; + break; + } + + /* if size limit is set, copy at most that many bytes*/ + bytesCopied += buflen; + if (copySizeLimit > 0 && bytesCopied >= copySizeLimit) + { + break; + } + } + } + else + { + bool copydone = false; + + while (!copydone) + { /* for each input line ... */ + bool firstload; + bool linedone; + + if (prompt) + { + fputs(prompt, stdout); + fflush(stdout); + } + + firstload = true; + linedone = false; + + while (!linedone) + { /* for each bufferload in line ... */ + int linelen = 0; + char *fgresult; + + /* enable longjmp while waiting for input */ + sigint_interrupt_enabled = true; + + fgresult = fgets(buf, sizeof(buf), copystream); + + sigint_interrupt_enabled = false; + + if (!fgresult) + { + copydone = true; + break; + } + + linelen = strlen(buf); + + /* current line is done? */ + if (linelen > 0 && buf[linelen - 1] == '\n') + linedone = true; + + /* check for EOF marker, but not on a partial line */ + if (firstload) + { + /* + * This code erroneously assumes '\.' on a line alone + * inside a quoted CSV string terminates the \copy. + * http://www.postgresql.org/message-id/E1TdNVQ-0001ju-GO@w + * rigleys.postgresql.org + */ + if (strcmp(buf, "\\.\n") == 0 || + strcmp(buf, "\\.\r\n") == 0) + { + copydone = true; + break; + } + + firstload = false; + } + + if (PQputCopyData(conn, buf, linelen) <= 0) + { + OK = false; + copydone = true; + break; + } + else + { + bytesCopied += linelen; + } + } + + if (copystream == pset.cur_cmd_source) + pset.lineno++; + + /* if size limit is set, copy at most that many bytes */ + if (copySizeLimit > 0 && bytesCopied >= copySizeLimit) + { + break; + } + } + } + + /* Check for read error */ + if (ferror(copystream)) + OK = false; + + /* + * Terminate data transfer. We can't send an error message if we're using + * protocol version 2. + */ + if (PQputCopyEnd(conn, + (OK || PQprotocolVersion(conn) < 3) ? NULL : + _("aborted because of read failure")) <= 0) + OK = false; + +copyin_cleanup: + + /* + * Check command status and return to normal libpq state. + * + * We do not want to return with the status still PGRES_COPY_IN: our + * caller would be unable to distinguish that situation from reaching the + * next COPY in a command string that happened to contain two consecutive + * COPY FROM STDIN commands. We keep trying PQputCopyEnd() in the hope + * it'll work eventually. (What's actually likely to happen is that in + * attempting to flush the data, libpq will eventually realize that the + * connection is lost. But that's fine; it will get us out of COPY_IN + * state, which is what we need.) + */ + while (*res = PQgetResult(conn), PQresultStatus(*res) == PGRES_COPY_IN) + { + OK = false; + PQclear(*res); + /* We can't send an error message if we're using protocol version 2 */ + PQputCopyEnd(conn, + (PQprotocolVersion(conn) < 3) ? NULL : + _("trying to exit copy mode")); + } + if (PQresultStatus(*res) != PGRES_COMMAND_OK) + { + psql_error("%s", PQerrorMessage(conn)); + OK = false; + } + + return OK; +} diff --git a/src/bin/csql/copy.h b/src/bin/csql/copy.h new file mode 100644 index 000000000..d127e61fb --- /dev/null +++ b/src/bin/csql/copy.h @@ -0,0 +1,33 @@ +/* + * psql - the PostgreSQL interactive terminal + * + * Copyright (c) 2000-2015, PostgreSQL Global Development Group + * + * src/bin/psql/copy.h + */ +#ifndef COPY_H +#define COPY_H + +#include "libpq-fe.h" + +#include "copy_options.h" +#include "pqexpbuffer.h" + + +/* handler for \copy */ +extern bool do_copy(const char *args); + +/* lower level processors for copy in/out streams */ + +extern bool handleCopyOut(PGconn *conn, FILE *copystream, + PGresult **res); +extern bool handleCopyIn(PGconn *conn, FILE *copystream, bool isbinary, + PGresult **res, uint64 copySizeLimit); + +/* Function declarations shared between copy and stage commands */ +bool HandleCopyData(PGconn *connection, ExecStatusType copyStatus, + bool copyIsBinary, FILE *copyStream, uint64 copySizeLimit); +FILE * OpenCopyStream(const copy_options *options); +bool CloseCopyStream(const copy_options *options, FILE *copyStream); + +#endif diff --git a/src/bin/csql/copy_options.c b/src/bin/csql/copy_options.c new file mode 100644 index 000000000..357ae726c --- /dev/null +++ b/src/bin/csql/copy_options.c @@ -0,0 +1,312 @@ +/* + * csql - the CitusDB interactive terminal + * copy_options.c + * Routines for parsing copy and stage meta commands. + * + * Copyright (c) 2012, Citus Data, Inc. + * + * $Id$ + */ + +#include "postgres_fe.h" +#include "copy_options.h" + +#include "common.h" +#include "settings.h" +#include "stringutils.h" + + +/* Concatenates "more" onto "var", and frees the original value of *var. */ +static void +xstrcat(char **var, const char *more) +{ + char *newvar; + + newvar = psprintf("%s%s", *var, more); + free(*var); + *var = newvar; +} + + +/* + * parse_slash_copy parses copy options from the given meta-command line. The + * function then returns a dynamically allocated structure with the options, or + * Null on parsing error. + */ +copy_options * +parse_slash_copy(const char *args) +{ + struct copy_options *result; + char *token; + const char *whitespace = " \t\n\r"; + char nonstd_backslash = standard_strings() ? 0 : '\\'; + + if (!args) + { + psql_error("\\copy: arguments required\n"); + return NULL; + } + + result = pg_malloc0(sizeof(struct copy_options)); + + result->before_tofrom = pg_strdup(""); /* initialize for appending */ + + token = strtokx(args, whitespace, ".,()", "\"", + 0, false, false, pset.encoding); + if (!token) + goto error; + + /* The following can be removed when we drop 7.3 syntax support */ + if (pg_strcasecmp(token, "binary") == 0) + { + xstrcat(&result->before_tofrom, token); + token = strtokx(NULL, whitespace, ".,()", "\"", + 0, false, false, pset.encoding); + if (!token) + goto error; + } + + /* Handle COPY (SELECT) case */ + if (token[0] == '(') + { + int parens = 1; + + while (parens > 0) + { + xstrcat(&result->before_tofrom, " "); + xstrcat(&result->before_tofrom, token); + token = strtokx(NULL, whitespace, "()", "\"'", + nonstd_backslash, true, false, pset.encoding); + if (!token) + goto error; + if (token[0] == '(') + parens++; + else if (token[0] == ')') + parens--; + } + } + + xstrcat(&result->before_tofrom, " "); + xstrcat(&result->before_tofrom, token); + token = strtokx(NULL, whitespace, ".,()", "\"", + 0, false, false, pset.encoding); + if (!token) + goto error; + + /* + * strtokx() will not have returned a multi-character token starting with + * '.', so we don't need strcmp() here. Likewise for '(', etc, below. + */ + if (token[0] == '.') + { + /* handle schema . table */ + xstrcat(&result->before_tofrom, token); + token = strtokx(NULL, whitespace, ".,()", "\"", + 0, false, false, pset.encoding); + if (!token) + goto error; + xstrcat(&result->before_tofrom, token); + token = strtokx(NULL, whitespace, ".,()", "\"", + 0, false, false, pset.encoding); + if (!token) + goto error; + } + + if (token[0] == '(') + { + /* handle parenthesized column list */ + for (;;) + { + xstrcat(&result->before_tofrom, " "); + xstrcat(&result->before_tofrom, token); + token = strtokx(NULL, whitespace, "()", "\"", + 0, false, false, pset.encoding); + if (!token) + goto error; + if (token[0] == ')') + break; + } + xstrcat(&result->before_tofrom, " "); + xstrcat(&result->before_tofrom, token); + token = strtokx(NULL, whitespace, ".,()", "\"", + 0, false, false, pset.encoding); + if (!token) + goto error; + } + + if (pg_strcasecmp(token, "from") == 0) + result->from = true; + else if (pg_strcasecmp(token, "to") == 0) + result->from = false; + else + goto error; + + /* { 'filename' | PROGRAM 'command' | STDIN | STDOUT | PSTDIN | PSTDOUT } */ + token = strtokx(NULL, whitespace, ";", "'", + 0, false, false, pset.encoding); + if (!token) + goto error; + + if (pg_strcasecmp(token, "program") == 0) + { + int toklen; + + token = strtokx(NULL, whitespace, ";", "'", + 0, false, false, pset.encoding); + if (!token) + goto error; + + /* + * The shell command must be quoted. This isn't fool-proof, but + * catches most quoting errors. + */ + toklen = strlen(token); + if (token[0] != '\'' || toklen < 2 || token[toklen - 1] != '\'') + goto error; + + strip_quotes(token, '\'', 0, pset.encoding); + + result->program = true; + result->file = pg_strdup(token); + } + else if (pg_strcasecmp(token, "stdin") == 0 || + pg_strcasecmp(token, "stdout") == 0) + { + result->file = NULL; + } + else if (pg_strcasecmp(token, "pstdin") == 0 || + pg_strcasecmp(token, "pstdout") == 0) + { + result->psql_inout = true; + result->file = NULL; + } + else + { + /* filename can be optionally quoted */ + strip_quotes(token, '\'', 0, pset.encoding); + result->file = pg_strdup(token); + expand_tilde(&result->file); + } + + /* Collect the rest of the line (COPY options) */ + token = strtokx(NULL, "", NULL, NULL, + 0, false, false, pset.encoding); + if (token) + result->after_tofrom = pg_strdup(token); + + /* set data staging options to null */ + result->tableName = NULL; + result->columnList = NULL; + + return result; + +error: + if (token) + psql_error("\\copy: parse error at \"%s\"\n", token); + else + psql_error("\\copy: parse error at end of line\n"); + free_copy_options(result); + + return NULL; +} + + +/* Frees copy options. */ +void +free_copy_options(copy_options * ptr) +{ + if (!ptr) + return; + free(ptr->before_tofrom); + free(ptr->after_tofrom); + free(ptr->file); + free(ptr->tableName); + free(ptr->columnList); + free(ptr); +} + + +/* + * ParseStageOptions takes the given copy options, parses the additional options + * needed for the \stage command, and sets them in the copy options structure. + * The additional parsed options are the table name and the column list. + */ +copy_options * +ParseStageOptions(copy_options *copyOptions) +{ + copy_options *stageOptions = NULL; + const char *whitespace = " \t\n\r"; + char *tableName = NULL; + char *columnList = NULL; + char *token = NULL; + + const char *beforeToFrom = copyOptions->before_tofrom; + Assert(beforeToFrom != NULL); + + token = strtokx(beforeToFrom, whitespace, ".,()", "\"", + 0, false, false, pset.encoding); + + /* + * We should have errored out earlier if the token were null. Similarly, we + * should have errored out on the "\stage (select) to" case. + */ + Assert(token != NULL); + Assert(token[0] != '('); + + /* we do not support PostgreSQL's 7.3 syntax */ + if (pg_strcasecmp(token, "binary") == 0) + { + psql_error("\\stage: binary keyword before to/from is not supported\n"); + Assert(false); + } + + /* init table name and append either the table name or schema name */ + tableName = pg_strdup(""); + xstrcat(&tableName, token); + + /* check for the schema.table use case */ + token = strtokx(NULL, whitespace, ".,()", "\"", 0, false, false, pset.encoding); + + if (token != NULL && token[0] == '.') + { + /* append the dot token */ + xstrcat(&tableName, token); + + token = strtokx(NULL, whitespace, ".,()", "\"", 0, false, false, pset.encoding); + Assert(token != NULL); + + /* append the table name token */ + xstrcat(&tableName, token); + + token = strtokx(NULL, whitespace, ".,()", "\"", 0, false, false, pset.encoding); + } + + /* check for the column list use case */ + if (token != NULL && token[0] == '(') + { + /* init column list, and add columns */ + columnList = pg_strdup(""); + for (;;) + { + xstrcat(&columnList, " "); + xstrcat(&columnList, token); + + token = strtokx(NULL, whitespace, "()", "\"", 0, false, false, pset.encoding); + Assert(token != NULL); + + if (token[0] == ')') + { + break; + } + } + xstrcat(&columnList, " "); + xstrcat(&columnList, token); + } + + /* finally set additional stage options */ + stageOptions = copyOptions; + stageOptions->tableName = tableName; + stageOptions->columnList = columnList; + + return stageOptions; +} diff --git a/src/bin/csql/copy_options.h b/src/bin/csql/copy_options.h new file mode 100644 index 000000000..07a3aeb09 --- /dev/null +++ b/src/bin/csql/copy_options.h @@ -0,0 +1,60 @@ +/* + * csql - the CitusDB interactive terminal + * copy_options.h + * Shared declarations for parsing copy and stage meta-commands. The stage + * meta-command borrows from copy's syntax, but does not yet support + * outputting table data to a file. Further, the stage command reuses copy's + * declarations to maintain compatibility with the copy command. + * + * Copyright (c) 2012, Citus Data, Inc. + * + * $Id$ + */ + +#ifndef COPY_OPTIONS_H +#define COPY_OPTIONS_H + +#include "libpq-fe.h" + + +/* + * The documented syntax is: + * \copy tablename [(columnlist)] from|to filename [options] + * \copy ( select stmt ) to filename [options] + * + * where 'filename' can be one of the following: + * '' | PROGRAM '' | stdin | stdout | pstdout | pstdout + * + * An undocumented fact is that you can still write BINARY before the + * tablename; this is a hangover from the pre-7.3 syntax. The options + * syntax varies across backend versions, but we avoid all that mess + * by just transmitting the stuff after the filename literally. + * + * table name can be double-quoted and can have a schema part. + * column names can be double-quoted. + * filename can be single-quoted like SQL literals. + * command must be single-quoted like SQL literals. + * + * returns a malloc'ed structure with the options, or NULL on parsing error + */ +typedef struct copy_options +{ + char *before_tofrom; /* COPY string before TO/FROM */ + char *after_tofrom; /* COPY string after TO/FROM filename */ + char *file; /* NULL = stdin/stdout */ + bool program; /* is 'file' a program to popen? */ + bool psql_inout; /* true = use psql stdin/stdout */ + bool from; /* true = FROM, false = TO */ + + char *tableName; /* table name to stage data to */ + char *columnList; /* optional column list used in staging */ +} copy_options; + + +/* Function declarations for parsing and freeing copy options */ +copy_options * parse_slash_copy(const char *args); +void free_copy_options(copy_options * ptr); +copy_options * ParseStageOptions(copy_options *copyOptions); + + +#endif /* COPY_OPTIONS_H */ diff --git a/src/bin/csql/create_help.pl b/src/bin/csql/create_help.pl new file mode 100644 index 000000000..bbebe522f --- /dev/null +++ b/src/bin/csql/create_help.pl @@ -0,0 +1,214 @@ +#! /usr/bin/perl -w + +################################################################# +# create_help.pl -- converts SGML docs to internal psql help +# +# Copyright (c) 2000-2015, PostgreSQL Global Development Group +# +# src/bin/psql/create_help.pl +################################################################# + +# +# This script automatically generates the help on SQL in psql from +# the SGML docs. So far the format of the docs was consistent +# enough that this worked, but this here is by no means an SGML +# parser. +# +# Call: perl create_help.pl docdir sql_help +# The name of the header file doesn't matter to this script, but it +# sure does matter to the rest of the source. +# + +use strict; + +my $docdir = $ARGV[0] or die "$0: missing required argument: docdir\n"; +my $hfile = $ARGV[1] . '.h' + or die "$0: missing required argument: output file\n"; +my $cfile = $ARGV[1] . '.c'; + +my $hfilebasename; +if ($hfile =~ m!.*/([^/]+)$!) +{ + $hfilebasename = $1; +} +else +{ + $hfilebasename = $hfile; +} + +my $define = $hfilebasename; +$define =~ tr/a-z/A-Z/; +$define =~ s/\W/_/g; + +opendir(DIR, $docdir) + or die "$0: could not open documentation source dir '$docdir': $!\n"; +open(HFILE, ">$hfile") + or die "$0: could not open output file '$hfile': $!\n"; +open(CFILE, ">$cfile") + or die "$0: could not open output file '$cfile': $!\n"; + +print HFILE "/* + * *** Do not change this file by hand. It is automatically + * *** generated from the DocBook documentation. + * + * generated by + * $^X $0 @ARGV + * + */ + +#ifndef $define +#define $define + +#define N_(x) (x) /* gettext noop */ + +#include \"postgres_fe.h\" +#include \"pqexpbuffer.h\" + +struct _helpStruct +{ + const char *cmd; /* the command name */ + const char *help; /* the help associated with it */ + void (*syntaxfunc)(PQExpBuffer); /* function that prints the syntax associated with it */ + int nl_count; /* number of newlines in syntax (for pager) */ +}; + +"; + +print CFILE "/* + * *** Do not change this file by hand. It is automatically + * *** generated from the DocBook documentation. + * + * generated by + * $^X $0 @ARGV + * + */ + +#include \"$hfile\" + +"; + +my $maxlen = 0; + +my %entries; + +foreach my $file (sort readdir DIR) +{ + my (@cmdnames, $cmddesc, $cmdsynopsis); + $file =~ /\.sgml$/ or next; + + open(FILE, "$docdir/$file") or next; + my $filecontent = join('', ); + close FILE; + + # Ignore files that are not for SQL language statements + $filecontent =~ + m!\s*SQL - Language Statements\s*!i + or next; + + # Collect multiple refnames + LOOP: + { + $filecontent =~ m!\G.*?\s*([a-z ]+?)\s*!cgis + and push @cmdnames, $1 + and redo LOOP; + } + $filecontent =~ m!\s*(.+?)\s*!is + and $cmddesc = $1; + $filecontent =~ m!\s*(.+?)\s*!is + and $cmdsynopsis = $1; + + if (@cmdnames && $cmddesc && $cmdsynopsis) + { + s/\"/\\"/g foreach @cmdnames; + + $cmddesc =~ s/<[^>]+>//g; + $cmddesc =~ s/\s+/ /g; + $cmddesc =~ s/\"/\\"/g; + + my @params = (); + + my $nl_count = () = $cmdsynopsis =~ /\n/g; + + $cmdsynopsis =~ m!! + and die "$0:$file: null end tag not supported in synopsis\n"; + $cmdsynopsis =~ s/%/%%/g; + + while ($cmdsynopsis =~ m!<(\w+)[^>]*>(.+?)]*>!) + { + my $match = $2; + $match =~ s/<[^>]+>//g; + $match =~ s/%%/%/g; + push @params, $match; + $cmdsynopsis =~ s!<(\w+)[^>]*>.+?]*>!%s!; + } + $cmdsynopsis =~ s/\r?\n/\\n/g; + $cmdsynopsis =~ s/\"/\\"/g; + + foreach my $cmdname (@cmdnames) + { + $entries{$cmdname} = { + cmddesc => $cmddesc, + cmdsynopsis => $cmdsynopsis, + params => \@params, + nl_count => $nl_count }; + $maxlen = + ($maxlen >= length $cmdname) ? $maxlen : length $cmdname; + } + } + else + { + die "$0: parsing file '$file' failed (N='@cmdnames' D='$cmddesc')\n"; + } +} + +foreach (sort keys %entries) +{ + my $prefix = "\t" x 5 . ' '; + my $id = $_; + $id =~ s/ /_/g; + my $synopsis = "\"$entries{$_}{cmdsynopsis}\""; + $synopsis =~ s/\\n/\\n"\n$prefix"/g; + my @args = + ("buf", $synopsis, map("_(\"$_\")", @{ $entries{$_}{params} })); + print HFILE "extern void sql_help_$id(PQExpBuffer buf);\n"; + print CFILE "void +sql_help_$id(PQExpBuffer buf) +{ +\tappendPQExpBuffer(" . join(",\n$prefix", @args) . "); +} + +"; +} + +print HFILE " + +static const struct _helpStruct QL_HELP[] = { +"; +foreach (sort keys %entries) +{ + my $id = $_; + $id =~ s/ /_/g; + print HFILE " { \"$_\", + N_(\"$entries{$_}{cmddesc}\"), + sql_help_$id, + $entries{$_}{nl_count} }, + +"; +} + +print HFILE " + { NULL, NULL, NULL } /* End of list marker */ +}; + + +#define QL_HELP_COUNT " + . scalar(keys %entries) . " /* number of help items */ +#define QL_MAX_CMD_LEN $maxlen /* largest strlen(cmd) */ + + +#endif /* $define */ +"; + +close CFILE; +close HFILE; +closedir DIR; diff --git a/src/bin/csql/describe.c b/src/bin/csql/describe.c new file mode 100644 index 000000000..bb59bc236 --- /dev/null +++ b/src/bin/csql/describe.c @@ -0,0 +1,4613 @@ +/* + * psql - the PostgreSQL interactive terminal + * + * Support for the various \d ("describe") commands. Note that the current + * expectation is that all functions in this file will succeed when working + * with servers of versions 7.4 and up. It's okay to omit irrelevant + * information for an old server, but not to fail outright. + * + * Copyright (c) 2000-2015, PostgreSQL Global Development Group + * + * src/bin/psql/describe.c + */ +#include "postgres_fe.h" + +#include + +#include "catalog/pg_default_acl.h" + +#include "common.h" +#include "describe.h" +#include "dumputils.h" +#include "mbprint.h" +#include "print.h" +#include "settings.h" +#include "variables.h" + + +static bool describeOneTableDetails(const char *schemaname, + const char *relationname, + const char *oid, + bool verbose); +static void add_tablespace_footer(printTableContent *const cont, char relkind, + Oid tablespace, const bool newline); +static void add_role_attribute(PQExpBuffer buf, const char *const str); +static bool listTSParsersVerbose(const char *pattern); +static bool describeOneTSParser(const char *oid, const char *nspname, + const char *prsname); +static bool listTSConfigsVerbose(const char *pattern); +static bool describeOneTSConfig(const char *oid, const char *nspname, + const char *cfgname, + const char *pnspname, const char *prsname); +static void printACLColumn(PQExpBuffer buf, const char *colname); +static bool listOneExtensionContents(const char *extname, const char *oid); + + +/*---------------- + * Handlers for various slash commands displaying some sort of list + * of things in the database. + * + * Note: try to format the queries to look nice in -E output. + *---------------- + */ + + +/* \da + * Takes an optional regexp to select particular aggregates + */ +bool +describeAggregates(const char *pattern, bool verbose, bool showSystem) +{ + PQExpBufferData buf; + PGresult *res; + printQueryOpt myopt = pset.popt; + + initPQExpBuffer(&buf); + + printfPQExpBuffer(&buf, + "SELECT n.nspname as \"%s\",\n" + " p.proname AS \"%s\",\n" + " pg_catalog.format_type(p.prorettype, NULL) AS \"%s\",\n", + gettext_noop("Schema"), + gettext_noop("Name"), + gettext_noop("Result data type")); + + if (pset.sversion >= 80400) + appendPQExpBuffer(&buf, + " CASE WHEN p.pronargs = 0\n" + " THEN CAST('*' AS pg_catalog.text)\n" + " ELSE pg_catalog.pg_get_function_arguments(p.oid)\n" + " END AS \"%s\",\n", + gettext_noop("Argument data types")); + else if (pset.sversion >= 80200) + appendPQExpBuffer(&buf, + " CASE WHEN p.pronargs = 0\n" + " THEN CAST('*' AS pg_catalog.text)\n" + " ELSE\n" + " pg_catalog.array_to_string(ARRAY(\n" + " SELECT\n" + " pg_catalog.format_type(p.proargtypes[s.i], NULL)\n" + " FROM\n" + " pg_catalog.generate_series(0, pg_catalog.array_upper(p.proargtypes, 1)) AS s(i)\n" + " ), ', ')\n" + " END AS \"%s\",\n", + gettext_noop("Argument data types")); + else + appendPQExpBuffer(&buf, + " pg_catalog.format_type(p.proargtypes[0], NULL) AS \"%s\",\n", + gettext_noop("Argument data types")); + + appendPQExpBuffer(&buf, + " pg_catalog.obj_description(p.oid, 'pg_proc') as \"%s\"\n" + "FROM pg_catalog.pg_proc p\n" + " LEFT JOIN pg_catalog.pg_namespace n ON n.oid = p.pronamespace\n" + "WHERE p.proisagg\n", + gettext_noop("Description")); + + if (!showSystem && !pattern) + appendPQExpBufferStr(&buf, " AND n.nspname <> 'pg_catalog'\n" + " AND n.nspname <> 'information_schema'\n"); + + processSQLNamePattern(pset.db, &buf, pattern, true, false, + "n.nspname", "p.proname", NULL, + "pg_catalog.pg_function_is_visible(p.oid)"); + + appendPQExpBufferStr(&buf, "ORDER BY 1, 2, 4;"); + + res = PSQLexec(buf.data); + termPQExpBuffer(&buf); + if (!res) + return false; + + myopt.nullPrint = NULL; + myopt.title = _("List of aggregate functions"); + myopt.translate_header = true; + + printQuery(res, &myopt, pset.queryFout, false, pset.logfile); + + PQclear(res); + return true; +} + +/* \db + * Takes an optional regexp to select particular tablespaces + */ +bool +describeTablespaces(const char *pattern, bool verbose) +{ + PQExpBufferData buf; + PGresult *res; + printQueryOpt myopt = pset.popt; + + if (pset.sversion < 80000) + { + psql_error("The server (version %d.%d) does not support tablespaces.\n", + pset.sversion / 10000, (pset.sversion / 100) % 100); + return true; + } + + initPQExpBuffer(&buf); + + if (pset.sversion >= 90200) + printfPQExpBuffer(&buf, + "SELECT spcname AS \"%s\",\n" + " pg_catalog.pg_get_userbyid(spcowner) AS \"%s\",\n" + " pg_catalog.pg_tablespace_location(oid) AS \"%s\"", + gettext_noop("Name"), + gettext_noop("Owner"), + gettext_noop("Location")); + else + printfPQExpBuffer(&buf, + "SELECT spcname AS \"%s\",\n" + " pg_catalog.pg_get_userbyid(spcowner) AS \"%s\",\n" + " spclocation AS \"%s\"", + gettext_noop("Name"), + gettext_noop("Owner"), + gettext_noop("Location")); + + if (verbose) + { + appendPQExpBufferStr(&buf, ",\n "); + printACLColumn(&buf, "spcacl"); + } + + if (verbose && pset.sversion >= 90000) + appendPQExpBuffer(&buf, + ",\n spcoptions AS \"%s\"", + gettext_noop("Options")); + + if (verbose && pset.sversion >= 90200) + appendPQExpBuffer(&buf, + ",\n pg_catalog.pg_size_pretty(pg_catalog.pg_tablespace_size(oid)) AS \"%s\"", + gettext_noop("Size")); + + if (verbose && pset.sversion >= 80200) + appendPQExpBuffer(&buf, + ",\n pg_catalog.shobj_description(oid, 'pg_tablespace') AS \"%s\"", + gettext_noop("Description")); + + appendPQExpBufferStr(&buf, + "\nFROM pg_catalog.pg_tablespace\n"); + + processSQLNamePattern(pset.db, &buf, pattern, false, false, + NULL, "spcname", NULL, + NULL); + + appendPQExpBufferStr(&buf, "ORDER BY 1;"); + + res = PSQLexec(buf.data); + termPQExpBuffer(&buf); + if (!res) + return false; + + myopt.nullPrint = NULL; + myopt.title = _("List of tablespaces"); + myopt.translate_header = true; + + printQuery(res, &myopt, pset.queryFout, false, pset.logfile); + + PQclear(res); + return true; +} + + +/* \df + * Takes an optional regexp to select particular functions. + * + * As with \d, you can specify the kinds of functions you want: + * + * a for aggregates + * n for normal + * t for trigger + * w for window + * + * and you can mix and match these in any order. + */ +bool +describeFunctions(const char *functypes, const char *pattern, bool verbose, bool showSystem) +{ + bool showAggregate = strchr(functypes, 'a') != NULL; + bool showNormal = strchr(functypes, 'n') != NULL; + bool showTrigger = strchr(functypes, 't') != NULL; + bool showWindow = strchr(functypes, 'w') != NULL; + bool have_where; + PQExpBufferData buf; + PGresult *res; + printQueryOpt myopt = pset.popt; + static const bool translate_columns[] = {false, false, false, false, true, true, true, false, false, false, false}; + + if (strlen(functypes) != strspn(functypes, "antwS+")) + { + psql_error("\\df only takes [antwS+] as options\n"); + return true; + } + + if (showWindow && pset.sversion < 80400) + { + psql_error("\\df does not take a \"w\" option with server version %d.%d\n", + pset.sversion / 10000, (pset.sversion / 100) % 100); + return true; + } + + if (!showAggregate && !showNormal && !showTrigger && !showWindow) + { + showAggregate = showNormal = showTrigger = true; + if (pset.sversion >= 80400) + showWindow = true; + } + + initPQExpBuffer(&buf); + + printfPQExpBuffer(&buf, + "SELECT n.nspname as \"%s\",\n" + " p.proname as \"%s\",\n", + gettext_noop("Schema"), + gettext_noop("Name")); + + if (pset.sversion >= 80400) + appendPQExpBuffer(&buf, + " pg_catalog.pg_get_function_result(p.oid) as \"%s\",\n" + " pg_catalog.pg_get_function_arguments(p.oid) as \"%s\",\n" + " CASE\n" + " WHEN p.proisagg THEN '%s'\n" + " WHEN p.proiswindow THEN '%s'\n" + " WHEN p.prorettype = 'pg_catalog.trigger'::pg_catalog.regtype THEN '%s'\n" + " ELSE '%s'\n" + " END as \"%s\"", + gettext_noop("Result data type"), + gettext_noop("Argument data types"), + /* translator: "agg" is short for "aggregate" */ + gettext_noop("agg"), + gettext_noop("window"), + gettext_noop("trigger"), + gettext_noop("normal"), + gettext_noop("Type")); + else if (pset.sversion >= 80100) + appendPQExpBuffer(&buf, + " CASE WHEN p.proretset THEN 'SETOF ' ELSE '' END ||\n" + " pg_catalog.format_type(p.prorettype, NULL) as \"%s\",\n" + " CASE WHEN proallargtypes IS NOT NULL THEN\n" + " pg_catalog.array_to_string(ARRAY(\n" + " SELECT\n" + " CASE\n" + " WHEN p.proargmodes[s.i] = 'i' THEN ''\n" + " WHEN p.proargmodes[s.i] = 'o' THEN 'OUT '\n" + " WHEN p.proargmodes[s.i] = 'b' THEN 'INOUT '\n" + " WHEN p.proargmodes[s.i] = 'v' THEN 'VARIADIC '\n" + " END ||\n" + " CASE\n" + " WHEN COALESCE(p.proargnames[s.i], '') = '' THEN ''\n" + " ELSE p.proargnames[s.i] || ' ' \n" + " END ||\n" + " pg_catalog.format_type(p.proallargtypes[s.i], NULL)\n" + " FROM\n" + " pg_catalog.generate_series(1, pg_catalog.array_upper(p.proallargtypes, 1)) AS s(i)\n" + " ), ', ')\n" + " ELSE\n" + " pg_catalog.array_to_string(ARRAY(\n" + " SELECT\n" + " CASE\n" + " WHEN COALESCE(p.proargnames[s.i+1], '') = '' THEN ''\n" + " ELSE p.proargnames[s.i+1] || ' '\n" + " END ||\n" + " pg_catalog.format_type(p.proargtypes[s.i], NULL)\n" + " FROM\n" + " pg_catalog.generate_series(0, pg_catalog.array_upper(p.proargtypes, 1)) AS s(i)\n" + " ), ', ')\n" + " END AS \"%s\",\n" + " CASE\n" + " WHEN p.proisagg THEN '%s'\n" + " WHEN p.prorettype = 'pg_catalog.trigger'::pg_catalog.regtype THEN '%s'\n" + " ELSE '%s'\n" + " END AS \"%s\"", + gettext_noop("Result data type"), + gettext_noop("Argument data types"), + /* translator: "agg" is short for "aggregate" */ + gettext_noop("agg"), + gettext_noop("trigger"), + gettext_noop("normal"), + gettext_noop("Type")); + else + appendPQExpBuffer(&buf, + " CASE WHEN p.proretset THEN 'SETOF ' ELSE '' END ||\n" + " pg_catalog.format_type(p.prorettype, NULL) as \"%s\",\n" + " pg_catalog.oidvectortypes(p.proargtypes) as \"%s\",\n" + " CASE\n" + " WHEN p.proisagg THEN '%s'\n" + " WHEN p.prorettype = 'pg_catalog.trigger'::pg_catalog.regtype THEN '%s'\n" + " ELSE '%s'\n" + " END AS \"%s\"", + gettext_noop("Result data type"), + gettext_noop("Argument data types"), + /* translator: "agg" is short for "aggregate" */ + gettext_noop("agg"), + gettext_noop("trigger"), + gettext_noop("normal"), + gettext_noop("Type")); + + if (verbose) + appendPQExpBuffer(&buf, + ",\n CASE WHEN prosecdef THEN '%s' ELSE '%s' END AS \"%s\"" + ",\n CASE\n" + " WHEN p.provolatile = 'i' THEN '%s'\n" + " WHEN p.provolatile = 's' THEN '%s'\n" + " WHEN p.provolatile = 'v' THEN '%s'\n" + " END as \"%s\"" + ",\n pg_catalog.pg_get_userbyid(p.proowner) as \"%s\",\n" + " l.lanname as \"%s\",\n" + " p.prosrc as \"%s\",\n" + " pg_catalog.obj_description(p.oid, 'pg_proc') as \"%s\"", + gettext_noop("definer"), + gettext_noop("invoker"), + gettext_noop("Security"), + gettext_noop("immutable"), + gettext_noop("stable"), + gettext_noop("volatile"), + gettext_noop("Volatility"), + gettext_noop("Owner"), + gettext_noop("Language"), + gettext_noop("Source code"), + gettext_noop("Description")); + + appendPQExpBufferStr(&buf, + "\nFROM pg_catalog.pg_proc p" + "\n LEFT JOIN pg_catalog.pg_namespace n ON n.oid = p.pronamespace\n"); + + if (verbose) + appendPQExpBufferStr(&buf, + " LEFT JOIN pg_catalog.pg_language l ON l.oid = p.prolang\n"); + + have_where = false; + + /* filter by function type, if requested */ + if (showNormal && showAggregate && showTrigger && showWindow) + /* Do nothing */ ; + else if (showNormal) + { + if (!showAggregate) + { + if (have_where) + appendPQExpBufferStr(&buf, " AND "); + else + { + appendPQExpBufferStr(&buf, "WHERE "); + have_where = true; + } + appendPQExpBufferStr(&buf, "NOT p.proisagg\n"); + } + if (!showTrigger) + { + if (have_where) + appendPQExpBufferStr(&buf, " AND "); + else + { + appendPQExpBufferStr(&buf, "WHERE "); + have_where = true; + } + appendPQExpBufferStr(&buf, "p.prorettype <> 'pg_catalog.trigger'::pg_catalog.regtype\n"); + } + if (!showWindow && pset.sversion >= 80400) + { + if (have_where) + appendPQExpBufferStr(&buf, " AND "); + else + { + appendPQExpBufferStr(&buf, "WHERE "); + have_where = true; + } + appendPQExpBufferStr(&buf, "NOT p.proiswindow\n"); + } + } + else + { + bool needs_or = false; + + appendPQExpBufferStr(&buf, "WHERE (\n "); + have_where = true; + /* Note: at least one of these must be true ... */ + if (showAggregate) + { + appendPQExpBufferStr(&buf, "p.proisagg\n"); + needs_or = true; + } + if (showTrigger) + { + if (needs_or) + appendPQExpBufferStr(&buf, " OR "); + appendPQExpBufferStr(&buf, + "p.prorettype = 'pg_catalog.trigger'::pg_catalog.regtype\n"); + needs_or = true; + } + if (showWindow) + { + if (needs_or) + appendPQExpBufferStr(&buf, " OR "); + appendPQExpBufferStr(&buf, "p.proiswindow\n"); + needs_or = true; + } + appendPQExpBufferStr(&buf, " )\n"); + } + + processSQLNamePattern(pset.db, &buf, pattern, have_where, false, + "n.nspname", "p.proname", NULL, + "pg_catalog.pg_function_is_visible(p.oid)"); + + if (!showSystem && !pattern) + appendPQExpBufferStr(&buf, " AND n.nspname <> 'pg_catalog'\n" + " AND n.nspname <> 'information_schema'\n"); + + appendPQExpBufferStr(&buf, "ORDER BY 1, 2, 4;"); + + res = PSQLexec(buf.data); + termPQExpBuffer(&buf); + if (!res) + return false; + + myopt.nullPrint = NULL; + myopt.title = _("List of functions"); + myopt.translate_header = true; + myopt.translate_columns = translate_columns; + myopt.n_translate_columns = lengthof(translate_columns); + + printQuery(res, &myopt, pset.queryFout, false, pset.logfile); + + PQclear(res); + return true; +} + + + +/* + * \dT + * describe types + */ +bool +describeTypes(const char *pattern, bool verbose, bool showSystem) +{ + PQExpBufferData buf; + PGresult *res; + printQueryOpt myopt = pset.popt; + + initPQExpBuffer(&buf); + + printfPQExpBuffer(&buf, + "SELECT n.nspname as \"%s\",\n" + " pg_catalog.format_type(t.oid, NULL) AS \"%s\",\n", + gettext_noop("Schema"), + gettext_noop("Name")); + if (verbose) + appendPQExpBuffer(&buf, + " t.typname AS \"%s\",\n" + " CASE WHEN t.typrelid != 0\n" + " THEN CAST('tuple' AS pg_catalog.text)\n" + " WHEN t.typlen < 0\n" + " THEN CAST('var' AS pg_catalog.text)\n" + " ELSE CAST(t.typlen AS pg_catalog.text)\n" + " END AS \"%s\",\n", + gettext_noop("Internal name"), + gettext_noop("Size")); + if (verbose && pset.sversion >= 80300) + { + appendPQExpBufferStr(&buf, + " pg_catalog.array_to_string(\n" + " ARRAY(\n" + " SELECT e.enumlabel\n" + " FROM pg_catalog.pg_enum e\n" + " WHERE e.enumtypid = t.oid\n"); + + if (pset.sversion >= 90100) + appendPQExpBufferStr(&buf, + " ORDER BY e.enumsortorder\n"); + else + appendPQExpBufferStr(&buf, + " ORDER BY e.oid\n"); + + appendPQExpBuffer(&buf, + " ),\n" + " E'\\n'\n" + " ) AS \"%s\",\n", + gettext_noop("Elements")); + } + if (verbose) + { + appendPQExpBuffer(&buf, + " pg_catalog.pg_get_userbyid(t.typowner) AS \"%s\",\n", + gettext_noop("Owner")); + } + if (verbose && pset.sversion >= 90200) + { + printACLColumn(&buf, "t.typacl"); + appendPQExpBufferStr(&buf, ",\n "); + } + + appendPQExpBuffer(&buf, + " pg_catalog.obj_description(t.oid, 'pg_type') as \"%s\"\n", + gettext_noop("Description")); + + appendPQExpBufferStr(&buf, "FROM pg_catalog.pg_type t\n" + " LEFT JOIN pg_catalog.pg_namespace n ON n.oid = t.typnamespace\n"); + + /* + * do not include complex types (typrelid!=0) unless they are standalone + * composite types + */ + appendPQExpBufferStr(&buf, "WHERE (t.typrelid = 0 "); + appendPQExpBufferStr(&buf, "OR (SELECT c.relkind = 'c' FROM pg_catalog.pg_class c " + "WHERE c.oid = t.typrelid))\n"); + + /* + * do not include array types (before 8.3 we have to use the assumption + * that their names start with underscore) + */ + if (pset.sversion >= 80300) + appendPQExpBufferStr(&buf, " AND NOT EXISTS(SELECT 1 FROM pg_catalog.pg_type el WHERE el.oid = t.typelem AND el.typarray = t.oid)\n"); + else + appendPQExpBufferStr(&buf, " AND t.typname !~ '^_'\n"); + + if (!showSystem && !pattern) + appendPQExpBufferStr(&buf, " AND n.nspname <> 'pg_catalog'\n" + " AND n.nspname <> 'information_schema'\n"); + + /* Match name pattern against either internal or external name */ + processSQLNamePattern(pset.db, &buf, pattern, true, false, + "n.nspname", "t.typname", + "pg_catalog.format_type(t.oid, NULL)", + "pg_catalog.pg_type_is_visible(t.oid)"); + + appendPQExpBufferStr(&buf, "ORDER BY 1, 2;"); + + res = PSQLexec(buf.data); + termPQExpBuffer(&buf); + if (!res) + return false; + + myopt.nullPrint = NULL; + myopt.title = _("List of data types"); + myopt.translate_header = true; + + printQuery(res, &myopt, pset.queryFout, false, pset.logfile); + + PQclear(res); + return true; +} + + +/* \do + * Describe operators + */ +bool +describeOperators(const char *pattern, bool verbose, bool showSystem) +{ + PQExpBufferData buf; + PGresult *res; + printQueryOpt myopt = pset.popt; + + initPQExpBuffer(&buf); + + /* + * Note: before Postgres 9.1, we did not assign comments to any built-in + * operators, preferring to let the comment on the underlying function + * suffice. The coalesce() on the obj_description() calls below supports + * this convention by providing a fallback lookup of a comment on the + * operator's function. As of 9.1 there is a policy that every built-in + * operator should have a comment; so the coalesce() is no longer + * necessary so far as built-in operators are concerned. We keep it + * anyway, for now, because (1) third-party modules may still be following + * the old convention, and (2) we'd need to do it anyway when talking to a + * pre-9.1 server. + */ + + printfPQExpBuffer(&buf, + "SELECT n.nspname as \"%s\",\n" + " o.oprname AS \"%s\",\n" + " CASE WHEN o.oprkind='l' THEN NULL ELSE pg_catalog.format_type(o.oprleft, NULL) END AS \"%s\",\n" + " CASE WHEN o.oprkind='r' THEN NULL ELSE pg_catalog.format_type(o.oprright, NULL) END AS \"%s\",\n" + " pg_catalog.format_type(o.oprresult, NULL) AS \"%s\",\n", + gettext_noop("Schema"), + gettext_noop("Name"), + gettext_noop("Left arg type"), + gettext_noop("Right arg type"), + gettext_noop("Result type")); + + if (verbose) + appendPQExpBuffer(&buf, + " o.oprcode AS \"%s\",\n", + gettext_noop("Function")); + + appendPQExpBuffer(&buf, + " coalesce(pg_catalog.obj_description(o.oid, 'pg_operator'),\n" + " pg_catalog.obj_description(o.oprcode, 'pg_proc')) AS \"%s\"\n" + "FROM pg_catalog.pg_operator o\n" + " LEFT JOIN pg_catalog.pg_namespace n ON n.oid = o.oprnamespace\n", + gettext_noop("Description")); + + if (!showSystem && !pattern) + appendPQExpBufferStr(&buf, "WHERE n.nspname <> 'pg_catalog'\n" + " AND n.nspname <> 'information_schema'\n"); + + processSQLNamePattern(pset.db, &buf, pattern, !showSystem && !pattern, true, + "n.nspname", "o.oprname", NULL, + "pg_catalog.pg_operator_is_visible(o.oid)"); + + appendPQExpBufferStr(&buf, "ORDER BY 1, 2, 3, 4;"); + + res = PSQLexec(buf.data); + termPQExpBuffer(&buf); + if (!res) + return false; + + myopt.nullPrint = NULL; + myopt.title = _("List of operators"); + myopt.translate_header = true; + + printQuery(res, &myopt, pset.queryFout, false, pset.logfile); + + PQclear(res); + return true; +} + + +/* + * listAllDbs + * + * for \l, \list, and -l switch + */ +bool +listAllDbs(const char *pattern, bool verbose) +{ + PGresult *res; + PQExpBufferData buf; + printQueryOpt myopt = pset.popt; + + initPQExpBuffer(&buf); + + printfPQExpBuffer(&buf, + "SELECT d.datname as \"%s\",\n" + " pg_catalog.pg_get_userbyid(d.datdba) as \"%s\",\n" + " pg_catalog.pg_encoding_to_char(d.encoding) as \"%s\",\n", + gettext_noop("Name"), + gettext_noop("Owner"), + gettext_noop("Encoding")); + if (pset.sversion >= 80400) + appendPQExpBuffer(&buf, + " d.datcollate as \"%s\",\n" + " d.datctype as \"%s\",\n", + gettext_noop("Collate"), + gettext_noop("Ctype")); + appendPQExpBufferStr(&buf, " "); + printACLColumn(&buf, "d.datacl"); + if (verbose && pset.sversion >= 80200) + appendPQExpBuffer(&buf, + ",\n CASE WHEN pg_catalog.has_database_privilege(d.datname, 'CONNECT')\n" + " THEN pg_catalog.pg_size_pretty(pg_catalog.pg_database_size(d.datname))\n" + " ELSE 'No Access'\n" + " END as \"%s\"", + gettext_noop("Size")); + if (verbose && pset.sversion >= 80000) + appendPQExpBuffer(&buf, + ",\n t.spcname as \"%s\"", + gettext_noop("Tablespace")); + if (verbose && pset.sversion >= 80200) + appendPQExpBuffer(&buf, + ",\n pg_catalog.shobj_description(d.oid, 'pg_database') as \"%s\"", + gettext_noop("Description")); + appendPQExpBufferStr(&buf, + "\nFROM pg_catalog.pg_database d\n"); + if (verbose && pset.sversion >= 80000) + appendPQExpBufferStr(&buf, + " JOIN pg_catalog.pg_tablespace t on d.dattablespace = t.oid\n"); + + if (pattern) + processSQLNamePattern(pset.db, &buf, pattern, false, false, + NULL, "d.datname", NULL, NULL); + + appendPQExpBufferStr(&buf, "ORDER BY 1;"); + res = PSQLexec(buf.data); + termPQExpBuffer(&buf); + if (!res) + return false; + + myopt.nullPrint = NULL; + myopt.title = _("List of databases"); + myopt.translate_header = true; + + printQuery(res, &myopt, pset.queryFout, false, pset.logfile); + + PQclear(res); + return true; +} + + +/* + * List Tables' Grant/Revoke Permissions + * \z (now also \dp -- perhaps more mnemonic) + */ +bool +permissionsList(const char *pattern) +{ + PQExpBufferData buf; + PGresult *res; + printQueryOpt myopt = pset.popt; + static const bool translate_columns[] = {false, false, true, false, false, false}; + + initPQExpBuffer(&buf); + + /* + * we ignore indexes and toast tables since they have no meaningful rights + */ + printfPQExpBuffer(&buf, + "SELECT n.nspname as \"%s\",\n" + " c.relname as \"%s\",\n" + " CASE c.relkind" + " WHEN 'r' THEN '%s'" + " WHEN 'v' THEN '%s'" + " WHEN 'm' THEN '%s'" + " WHEN 'S' THEN '%s'" + " WHEN 'f' THEN '%s'" + " END as \"%s\",\n" + " ", + gettext_noop("Schema"), + gettext_noop("Name"), + gettext_noop("table"), + gettext_noop("view"), + gettext_noop("materialized view"), + gettext_noop("sequence"), + gettext_noop("foreign table"), + gettext_noop("Type")); + + printACLColumn(&buf, "c.relacl"); + + if (pset.sversion >= 80400) + appendPQExpBuffer(&buf, + ",\n pg_catalog.array_to_string(ARRAY(\n" + " SELECT attname || E':\\n ' || pg_catalog.array_to_string(attacl, E'\\n ')\n" + " FROM pg_catalog.pg_attribute a\n" + " WHERE attrelid = c.oid AND NOT attisdropped AND attacl IS NOT NULL\n" + " ), E'\\n') AS \"%s\"", + gettext_noop("Column privileges")); + + if (pset.sversion >= 90500) + appendPQExpBuffer(&buf, + ",\n pg_catalog.array_to_string(ARRAY(\n" + " SELECT polname\n" + " || CASE WHEN polcmd != '*' THEN\n" + " E' (' || polcmd || E'):'\n" + " ELSE E':' \n" + " END\n" + " || CASE WHEN polqual IS NOT NULL THEN\n" + " E'\\n (u): ' || pg_catalog.pg_get_expr(polqual, polrelid)\n" + " ELSE E''\n" + " END\n" + " || CASE WHEN polwithcheck IS NOT NULL THEN\n" + " E'\\n (c): ' || pg_catalog.pg_get_expr(polwithcheck, polrelid)\n" + " ELSE E''\n" + " END" + " || CASE WHEN polroles <> '{0}' THEN\n" + " E'\\n to: ' || pg_catalog.array_to_string(\n" + " ARRAY(\n" + " SELECT rolname\n" + " FROM pg_catalog.pg_roles\n" + " WHERE oid = ANY (polroles)\n" + " ORDER BY 1\n" + " ), E', ')\n" + " ELSE E''\n" + " END\n" + " FROM pg_catalog.pg_policy pol\n" + " WHERE polrelid = c.oid), E'\\n')\n" + " AS \"%s\"", + gettext_noop("Policies")); + + appendPQExpBufferStr(&buf, "\nFROM pg_catalog.pg_class c\n" + " LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace\n" + "WHERE c.relkind IN ('r', 'v', 'm', 'S', 'f')\n"); + + /* + * Unless a schema pattern is specified, we suppress system and temp + * tables, since they normally aren't very interesting from a permissions + * point of view. You can see 'em by explicit request though, eg with \z + * pg_catalog.* + */ + processSQLNamePattern(pset.db, &buf, pattern, true, false, + "n.nspname", "c.relname", NULL, + "n.nspname !~ '^pg_' AND pg_catalog.pg_table_is_visible(c.oid)"); + + appendPQExpBufferStr(&buf, "ORDER BY 1, 2;"); + + res = PSQLexec(buf.data); + if (!res) + { + termPQExpBuffer(&buf); + return false; + } + + myopt.nullPrint = NULL; + printfPQExpBuffer(&buf, _("Access privileges")); + myopt.title = buf.data; + myopt.translate_header = true; + myopt.translate_columns = translate_columns; + myopt.n_translate_columns = lengthof(translate_columns); + + printQuery(res, &myopt, pset.queryFout, false, pset.logfile); + + termPQExpBuffer(&buf); + PQclear(res); + return true; +} + + +/* + * \ddp + * + * List Default ACLs. The pattern can match either schema or role name. + */ +bool +listDefaultACLs(const char *pattern) +{ + PQExpBufferData buf; + PGresult *res; + printQueryOpt myopt = pset.popt; + static const bool translate_columns[] = {false, false, true, false}; + + if (pset.sversion < 90000) + { + psql_error("The server (version %d.%d) does not support altering default privileges.\n", + pset.sversion / 10000, (pset.sversion / 100) % 100); + return true; + } + + initPQExpBuffer(&buf); + + printfPQExpBuffer(&buf, + "SELECT pg_catalog.pg_get_userbyid(d.defaclrole) AS \"%s\",\n" + " n.nspname AS \"%s\",\n" + " CASE d.defaclobjtype WHEN '%c' THEN '%s' WHEN '%c' THEN '%s' WHEN '%c' THEN '%s' WHEN '%c' THEN '%s' END AS \"%s\",\n" + " ", + gettext_noop("Owner"), + gettext_noop("Schema"), + DEFACLOBJ_RELATION, + gettext_noop("table"), + DEFACLOBJ_SEQUENCE, + gettext_noop("sequence"), + DEFACLOBJ_FUNCTION, + gettext_noop("function"), + DEFACLOBJ_TYPE, + gettext_noop("type"), + gettext_noop("Type")); + + printACLColumn(&buf, "d.defaclacl"); + + appendPQExpBufferStr(&buf, "\nFROM pg_catalog.pg_default_acl d\n" + " LEFT JOIN pg_catalog.pg_namespace n ON n.oid = d.defaclnamespace\n"); + + processSQLNamePattern(pset.db, &buf, pattern, false, false, + NULL, + "n.nspname", + "pg_catalog.pg_get_userbyid(d.defaclrole)", + NULL); + + appendPQExpBufferStr(&buf, "ORDER BY 1, 2, 3;"); + + res = PSQLexec(buf.data); + if (!res) + { + termPQExpBuffer(&buf); + return false; + } + + myopt.nullPrint = NULL; + printfPQExpBuffer(&buf, _("Default access privileges")); + myopt.title = buf.data; + myopt.translate_header = true; + myopt.translate_columns = translate_columns; + myopt.n_translate_columns = lengthof(translate_columns); + + printQuery(res, &myopt, pset.queryFout, false, pset.logfile); + + termPQExpBuffer(&buf); + PQclear(res); + return true; +} + + +/* + * Get object comments + * + * \dd [foo] + * + * Note: This command only lists comments for object types which do not have + * their comments displayed by their own backslash commands. The following + * types of objects will be displayed: constraint, operator class, + * operator family, rule, and trigger. + * + */ +bool +objectDescription(const char *pattern, bool showSystem) +{ + PQExpBufferData buf; + PGresult *res; + printQueryOpt myopt = pset.popt; + static const bool translate_columns[] = {false, false, true, false}; + + initPQExpBuffer(&buf); + + appendPQExpBuffer(&buf, + "SELECT DISTINCT tt.nspname AS \"%s\", tt.name AS \"%s\", tt.object AS \"%s\", d.description AS \"%s\"\n" + "FROM (\n", + gettext_noop("Schema"), + gettext_noop("Name"), + gettext_noop("Object"), + gettext_noop("Description")); + + /* Table constraint descriptions */ + appendPQExpBuffer(&buf, + " SELECT pgc.oid as oid, pgc.tableoid AS tableoid,\n" + " n.nspname as nspname,\n" + " CAST(pgc.conname AS pg_catalog.text) as name," + " CAST('%s' AS pg_catalog.text) as object\n" + " FROM pg_catalog.pg_constraint pgc\n" + " JOIN pg_catalog.pg_class c " + "ON c.oid = pgc.conrelid\n" + " LEFT JOIN pg_catalog.pg_namespace n " + " ON n.oid = c.relnamespace\n", + gettext_noop("table constraint")); + + if (!showSystem && !pattern) + appendPQExpBufferStr(&buf, "WHERE n.nspname <> 'pg_catalog'\n" + " AND n.nspname <> 'information_schema'\n"); + + processSQLNamePattern(pset.db, &buf, pattern, !showSystem && !pattern, + false, "n.nspname", "pgc.conname", NULL, + "pg_catalog.pg_table_is_visible(c.oid)"); + + /* Domain constraint descriptions */ + appendPQExpBuffer(&buf, + "UNION ALL\n" + " SELECT pgc.oid as oid, pgc.tableoid AS tableoid,\n" + " n.nspname as nspname,\n" + " CAST(pgc.conname AS pg_catalog.text) as name," + " CAST('%s' AS pg_catalog.text) as object\n" + " FROM pg_catalog.pg_constraint pgc\n" + " JOIN pg_catalog.pg_type t " + "ON t.oid = pgc.contypid\n" + " LEFT JOIN pg_catalog.pg_namespace n " + " ON n.oid = t.typnamespace\n", + gettext_noop("domain constraint")); + + if (!showSystem && !pattern) + appendPQExpBufferStr(&buf, "WHERE n.nspname <> 'pg_catalog'\n" + " AND n.nspname <> 'information_schema'\n"); + + processSQLNamePattern(pset.db, &buf, pattern, !showSystem && !pattern, + false, "n.nspname", "pgc.conname", NULL, + "pg_catalog.pg_type_is_visible(t.oid)"); + + + /* + * pg_opclass.opcmethod only available in 8.3+ + */ + if (pset.sversion >= 80300) + { + /* Operator class descriptions */ + appendPQExpBuffer(&buf, + "UNION ALL\n" + " SELECT o.oid as oid, o.tableoid as tableoid,\n" + " n.nspname as nspname,\n" + " CAST(o.opcname AS pg_catalog.text) as name,\n" + " CAST('%s' AS pg_catalog.text) as object\n" + " FROM pg_catalog.pg_opclass o\n" + " JOIN pg_catalog.pg_am am ON " + "o.opcmethod = am.oid\n" + " JOIN pg_catalog.pg_namespace n ON " + "n.oid = o.opcnamespace\n", + gettext_noop("operator class")); + + if (!showSystem && !pattern) + appendPQExpBufferStr(&buf, " AND n.nspname <> 'pg_catalog'\n" + " AND n.nspname <> 'information_schema'\n"); + + processSQLNamePattern(pset.db, &buf, pattern, true, false, + "n.nspname", "o.opcname", NULL, + "pg_catalog.pg_opclass_is_visible(o.oid)"); + } + + /* + * although operator family comments have been around since 8.3, + * pg_opfamily_is_visible is only available in 9.2+ + */ + if (pset.sversion >= 90200) + { + /* Operator family descriptions */ + appendPQExpBuffer(&buf, + "UNION ALL\n" + " SELECT opf.oid as oid, opf.tableoid as tableoid,\n" + " n.nspname as nspname,\n" + " CAST(opf.opfname AS pg_catalog.text) AS name,\n" + " CAST('%s' AS pg_catalog.text) as object\n" + " FROM pg_catalog.pg_opfamily opf\n" + " JOIN pg_catalog.pg_am am " + "ON opf.opfmethod = am.oid\n" + " JOIN pg_catalog.pg_namespace n " + "ON opf.opfnamespace = n.oid\n", + gettext_noop("operator family")); + + if (!showSystem && !pattern) + appendPQExpBufferStr(&buf, " AND n.nspname <> 'pg_catalog'\n" + " AND n.nspname <> 'information_schema'\n"); + + processSQLNamePattern(pset.db, &buf, pattern, true, false, + "n.nspname", "opf.opfname", NULL, + "pg_catalog.pg_opfamily_is_visible(opf.oid)"); + } + + /* Rule descriptions (ignore rules for views) */ + appendPQExpBuffer(&buf, + "UNION ALL\n" + " SELECT r.oid as oid, r.tableoid as tableoid,\n" + " n.nspname as nspname,\n" + " CAST(r.rulename AS pg_catalog.text) as name," + " CAST('%s' AS pg_catalog.text) as object\n" + " FROM pg_catalog.pg_rewrite r\n" + " JOIN pg_catalog.pg_class c ON c.oid = r.ev_class\n" + " LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace\n" + " WHERE r.rulename != '_RETURN'\n", + gettext_noop("rule")); + + if (!showSystem && !pattern) + appendPQExpBufferStr(&buf, " AND n.nspname <> 'pg_catalog'\n" + " AND n.nspname <> 'information_schema'\n"); + + processSQLNamePattern(pset.db, &buf, pattern, true, false, + "n.nspname", "r.rulename", NULL, + "pg_catalog.pg_table_is_visible(c.oid)"); + + /* Trigger descriptions */ + appendPQExpBuffer(&buf, + "UNION ALL\n" + " SELECT t.oid as oid, t.tableoid as tableoid,\n" + " n.nspname as nspname,\n" + " CAST(t.tgname AS pg_catalog.text) as name," + " CAST('%s' AS pg_catalog.text) as object\n" + " FROM pg_catalog.pg_trigger t\n" + " JOIN pg_catalog.pg_class c ON c.oid = t.tgrelid\n" + " LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace\n", + gettext_noop("trigger")); + + if (!showSystem && !pattern) + appendPQExpBufferStr(&buf, "WHERE n.nspname <> 'pg_catalog'\n" + " AND n.nspname <> 'information_schema'\n"); + + processSQLNamePattern(pset.db, &buf, pattern, !showSystem && !pattern, false, + "n.nspname", "t.tgname", NULL, + "pg_catalog.pg_table_is_visible(c.oid)"); + + appendPQExpBufferStr(&buf, + ") AS tt\n" + " JOIN pg_catalog.pg_description d ON (tt.oid = d.objoid AND tt.tableoid = d.classoid AND d.objsubid = 0)\n"); + + appendPQExpBufferStr(&buf, "ORDER BY 1, 2, 3;"); + + res = PSQLexec(buf.data); + termPQExpBuffer(&buf); + if (!res) + return false; + + myopt.nullPrint = NULL; + myopt.title = _("Object descriptions"); + myopt.translate_header = true; + myopt.translate_columns = translate_columns; + myopt.n_translate_columns = lengthof(translate_columns); + + printQuery(res, &myopt, pset.queryFout, false, pset.logfile); + + PQclear(res); + return true; +} + + +/* + * describeTableDetails (for \d) + * + * This routine finds the tables to be displayed, and calls + * describeOneTableDetails for each one. + * + * verbose: if true, this is \d+ + */ +bool +describeTableDetails(const char *pattern, bool verbose, bool showSystem) +{ + PQExpBufferData buf; + PGresult *res; + int i; + + initPQExpBuffer(&buf); + + printfPQExpBuffer(&buf, + "SELECT c.oid,\n" + " n.nspname,\n" + " c.relname\n" + "FROM pg_catalog.pg_class c\n" + " LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace\n"); + + if (!showSystem && !pattern) + appendPQExpBufferStr(&buf, "WHERE n.nspname <> 'pg_catalog'\n" + " AND n.nspname <> 'information_schema'\n"); + + processSQLNamePattern(pset.db, &buf, pattern, !showSystem && !pattern, false, + "n.nspname", "c.relname", NULL, + "pg_catalog.pg_table_is_visible(c.oid)"); + + appendPQExpBufferStr(&buf, "ORDER BY 2, 3;"); + + res = PSQLexec(buf.data); + termPQExpBuffer(&buf); + if (!res) + return false; + + if (PQntuples(res) == 0) + { + if (!pset.quiet) + psql_error("Did not find any relation named \"%s\".\n", + pattern); + PQclear(res); + return false; + } + + for (i = 0; i < PQntuples(res); i++) + { + const char *oid; + const char *nspname; + const char *relname; + + oid = PQgetvalue(res, i, 0); + nspname = PQgetvalue(res, i, 1); + relname = PQgetvalue(res, i, 2); + + if (!describeOneTableDetails(nspname, relname, oid, verbose)) + { + PQclear(res); + return false; + } + if (cancel_pressed) + { + PQclear(res); + return false; + } + } + + PQclear(res); + return true; +} + +/* + * describeOneTableDetails (for \d) + * + * Unfortunately, the information presented here is so complicated that it + * cannot be done in a single query. So we have to assemble the printed table + * by hand and pass it to the underlying printTable() function. + */ +static bool +describeOneTableDetails(const char *schemaname, + const char *relationname, + const char *oid, + bool verbose) +{ + PQExpBufferData buf; + PGresult *res = NULL; + printTableOpt myopt = pset.popt.topt; + printTableContent cont; + bool printTableInitialized = false; + int i; + char *view_def = NULL; + char *headers[9]; + char **seq_values = NULL; + char **modifiers = NULL; + char **ptr; + PQExpBufferData title; + PQExpBufferData tmpbuf; + int cols; + int numrows = 0; + struct + { + int16 checks; + char relkind; + bool hasindex; + bool hasrules; + bool hastriggers; + bool rowsecurity; + bool forcerowsecurity; + bool hasoids; + Oid tablespace; + char *reloptions; + char *reloftype; + char relpersistence; + char relreplident; + } tableinfo; + bool show_modifiers = false; + bool retval; + + retval = false; + + myopt.default_footer = false; + /* This output looks confusing in expanded mode. */ + myopt.expanded = false; + + initPQExpBuffer(&buf); + initPQExpBuffer(&title); + initPQExpBuffer(&tmpbuf); + + /* Get general table info */ + if (pset.sversion >= 90500) + { + printfPQExpBuffer(&buf, + "SELECT c.relchecks, c.relkind, c.relhasindex, c.relhasrules, " + "c.relhastriggers, c.relrowsecurity, c.relforcerowsecurity, " + "c.relhasoids, %s, c.reltablespace, " + "CASE WHEN c.reloftype = 0 THEN '' ELSE c.reloftype::pg_catalog.regtype::pg_catalog.text END, " + "c.relpersistence, c.relreplident\n" + "FROM pg_catalog.pg_class c\n " + "LEFT JOIN pg_catalog.pg_class tc ON (c.reltoastrelid = tc.oid)\n" + "WHERE c.oid = '%s';", + (verbose ? + "pg_catalog.array_to_string(c.reloptions || " + "array(select 'toast.' || x from pg_catalog.unnest(tc.reloptions) x), ', ')\n" + : "''"), + oid); + } + else if (pset.sversion >= 90400) + { + printfPQExpBuffer(&buf, + "SELECT c.relchecks, c.relkind, c.relhasindex, c.relhasrules, " + "c.relhastriggers, false, false, c.relhasoids, " + "%s, c.reltablespace, " + "CASE WHEN c.reloftype = 0 THEN '' ELSE c.reloftype::pg_catalog.regtype::pg_catalog.text END, " + "c.relpersistence, c.relreplident\n" + "FROM pg_catalog.pg_class c\n " + "LEFT JOIN pg_catalog.pg_class tc ON (c.reltoastrelid = tc.oid)\n" + "WHERE c.oid = '%s';", + (verbose ? + "pg_catalog.array_to_string(c.reloptions || " + "array(select 'toast.' || x from pg_catalog.unnest(tc.reloptions) x), ', ')\n" + : "''"), + oid); + } + else if (pset.sversion >= 90100) + { + printfPQExpBuffer(&buf, + "SELECT c.relchecks, c.relkind, c.relhasindex, c.relhasrules, " + "c.relhastriggers, false, false, c.relhasoids, " + "%s, c.reltablespace, " + "CASE WHEN c.reloftype = 0 THEN '' ELSE c.reloftype::pg_catalog.regtype::pg_catalog.text END, " + "c.relpersistence\n" + "FROM pg_catalog.pg_class c\n " + "LEFT JOIN pg_catalog.pg_class tc ON (c.reltoastrelid = tc.oid)\n" + "WHERE c.oid = '%s';", + (verbose ? + "pg_catalog.array_to_string(c.reloptions || " + "array(select 'toast.' || x from pg_catalog.unnest(tc.reloptions) x), ', ')\n" + : "''"), + oid); + } + else if (pset.sversion >= 90000) + { + printfPQExpBuffer(&buf, + "SELECT c.relchecks, c.relkind, c.relhasindex, c.relhasrules, " + "c.relhastriggers, false, false, c.relhasoids, " + "%s, c.reltablespace, " + "CASE WHEN c.reloftype = 0 THEN '' ELSE c.reloftype::pg_catalog.regtype::pg_catalog.text END\n" + "FROM pg_catalog.pg_class c\n " + "LEFT JOIN pg_catalog.pg_class tc ON (c.reltoastrelid = tc.oid)\n" + "WHERE c.oid = '%s';", + (verbose ? + "pg_catalog.array_to_string(c.reloptions || " + "array(select 'toast.' || x from pg_catalog.unnest(tc.reloptions) x), ', ')\n" + : "''"), + oid); + } + else if (pset.sversion >= 80400) + { + printfPQExpBuffer(&buf, + "SELECT c.relchecks, c.relkind, c.relhasindex, c.relhasrules, " + "c.relhastriggers, false, false, c.relhasoids, " + "%s, c.reltablespace\n" + "FROM pg_catalog.pg_class c\n " + "LEFT JOIN pg_catalog.pg_class tc ON (c.reltoastrelid = tc.oid)\n" + "WHERE c.oid = '%s';", + (verbose ? + "pg_catalog.array_to_string(c.reloptions || " + "array(select 'toast.' || x from pg_catalog.unnest(tc.reloptions) x), ', ')\n" + : "''"), + oid); + } + else if (pset.sversion >= 80200) + { + printfPQExpBuffer(&buf, + "SELECT relchecks, relkind, relhasindex, relhasrules, " + "reltriggers <> 0, false, false, relhasoids, " + "%s, reltablespace\n" + "FROM pg_catalog.pg_class WHERE oid = '%s';", + (verbose ? + "pg_catalog.array_to_string(reloptions, E', ')" : "''"), + oid); + } + else if (pset.sversion >= 80000) + { + printfPQExpBuffer(&buf, + "SELECT relchecks, relkind, relhasindex, relhasrules, " + "reltriggers <> 0, false, false, relhasoids, " + "'', reltablespace\n" + "FROM pg_catalog.pg_class WHERE oid = '%s';", + oid); + } + else + { + printfPQExpBuffer(&buf, + "SELECT relchecks, relkind, relhasindex, relhasrules, " + "reltriggers <> 0, false, false, relhasoids, " + "'', ''\n" + "FROM pg_catalog.pg_class WHERE oid = '%s';", + oid); + } + + res = PSQLexec(buf.data); + if (!res) + goto error_return; + + /* Did we get anything? */ + if (PQntuples(res) == 0) + { + if (!pset.quiet) + psql_error("Did not find any relation with OID %s.\n", oid); + goto error_return; + } + + tableinfo.checks = atoi(PQgetvalue(res, 0, 0)); + tableinfo.relkind = *(PQgetvalue(res, 0, 1)); + tableinfo.hasindex = strcmp(PQgetvalue(res, 0, 2), "t") == 0; + tableinfo.hasrules = strcmp(PQgetvalue(res, 0, 3), "t") == 0; + tableinfo.hastriggers = strcmp(PQgetvalue(res, 0, 4), "t") == 0; + tableinfo.rowsecurity = strcmp(PQgetvalue(res, 0, 5), "t") == 0; + tableinfo.forcerowsecurity = strcmp(PQgetvalue(res, 0, 6), "t") == 0; + tableinfo.hasoids = strcmp(PQgetvalue(res, 0, 7), "t") == 0; + tableinfo.reloptions = (pset.sversion >= 80200) ? + pg_strdup(PQgetvalue(res, 0, 8)) : NULL; + tableinfo.tablespace = (pset.sversion >= 80000) ? + atooid(PQgetvalue(res, 0, 9)) : 0; + tableinfo.reloftype = (pset.sversion >= 90000 && + strcmp(PQgetvalue(res, 0, 10), "") != 0) ? + pg_strdup(PQgetvalue(res, 0, 10)) : NULL; + tableinfo.relpersistence = (pset.sversion >= 90100) ? + *(PQgetvalue(res, 0, 11)) : 0; + tableinfo.relreplident = (pset.sversion >= 90400) ? + *(PQgetvalue(res, 0, 12)) : 'd'; + PQclear(res); + res = NULL; + + /* + * If it's a sequence, fetch its values and store into an array that will + * be used later. + */ + if (tableinfo.relkind == 'S') + { + printfPQExpBuffer(&buf, "SELECT * FROM %s", fmtId(schemaname)); + /* must be separate because fmtId isn't reentrant */ + appendPQExpBuffer(&buf, ".%s;", fmtId(relationname)); + + res = PSQLexec(buf.data); + if (!res) + goto error_return; + + seq_values = pg_malloc((PQnfields(res) + 1) * sizeof(*seq_values)); + + for (i = 0; i < PQnfields(res); i++) + seq_values[i] = pg_strdup(PQgetvalue(res, 0, i)); + seq_values[i] = NULL; + + PQclear(res); + res = NULL; + } + + /* + * Get column info + * + * You need to modify value of "firstvcol" which will be defined below if + * you are adding column(s) preceding to verbose-only columns. + */ + printfPQExpBuffer(&buf, "SELECT a.attname,"); + appendPQExpBufferStr(&buf, "\n pg_catalog.format_type(a.atttypid, a.atttypmod)," + "\n (SELECT substring(pg_catalog.pg_get_expr(d.adbin, d.adrelid) for 128)" + "\n FROM pg_catalog.pg_attrdef d" + "\n WHERE d.adrelid = a.attrelid AND d.adnum = a.attnum AND a.atthasdef)," + "\n a.attnotnull, a.attnum,"); + if (pset.sversion >= 90100) + appendPQExpBufferStr(&buf, "\n (SELECT c.collname FROM pg_catalog.pg_collation c, pg_catalog.pg_type t\n" + " WHERE c.oid = a.attcollation AND t.oid = a.atttypid AND a.attcollation <> t.typcollation) AS attcollation"); + else + appendPQExpBufferStr(&buf, "\n NULL AS attcollation"); + if (tableinfo.relkind == 'i') + appendPQExpBufferStr(&buf, ",\n pg_catalog.pg_get_indexdef(a.attrelid, a.attnum, TRUE) AS indexdef"); + else + appendPQExpBufferStr(&buf, ",\n NULL AS indexdef"); + if (tableinfo.relkind == 'f' && pset.sversion >= 90200) + appendPQExpBufferStr(&buf, ",\n CASE WHEN attfdwoptions IS NULL THEN '' ELSE " + " '(' || array_to_string(ARRAY(SELECT quote_ident(option_name) || ' ' || quote_literal(option_value) FROM " + " pg_options_to_table(attfdwoptions)), ', ') || ')' END AS attfdwoptions"); + else + appendPQExpBufferStr(&buf, ",\n NULL AS attfdwoptions"); + if (verbose) + { + appendPQExpBufferStr(&buf, ",\n a.attstorage"); + appendPQExpBufferStr(&buf, ",\n CASE WHEN a.attstattarget=-1 THEN NULL ELSE a.attstattarget END AS attstattarget"); + + /* + * In 9.0+, we have column comments for: relations, views, composite + * types, and foreign tables (c.f. CommentObject() in comment.c). + */ + if (tableinfo.relkind == 'r' || tableinfo.relkind == 'v' || + tableinfo.relkind == 'm' || + tableinfo.relkind == 'f' || tableinfo.relkind == 'c') + appendPQExpBufferStr(&buf, ", pg_catalog.col_description(a.attrelid, a.attnum)"); + } + + appendPQExpBufferStr(&buf, "\nFROM pg_catalog.pg_attribute a"); + appendPQExpBuffer(&buf, "\nWHERE a.attrelid = '%s' AND a.attnum > 0 AND NOT a.attisdropped", oid); + appendPQExpBufferStr(&buf, "\nORDER BY a.attnum;"); + + res = PSQLexec(buf.data); + if (!res) + goto error_return; + numrows = PQntuples(res); + + /* Make title */ + switch (tableinfo.relkind) + { + case 'r': + if (tableinfo.relpersistence == 'u') + printfPQExpBuffer(&title, _("Unlogged table \"%s.%s\""), + schemaname, relationname); + else + printfPQExpBuffer(&title, _("Table \"%s.%s\""), + schemaname, relationname); + break; + case 'v': + printfPQExpBuffer(&title, _("View \"%s.%s\""), + schemaname, relationname); + break; + case 'm': + if (tableinfo.relpersistence == 'u') + printfPQExpBuffer(&title, _("Unlogged materialized view \"%s.%s\""), + schemaname, relationname); + else + printfPQExpBuffer(&title, _("Materialized view \"%s.%s\""), + schemaname, relationname); + break; + case 'S': + printfPQExpBuffer(&title, _("Sequence \"%s.%s\""), + schemaname, relationname); + break; + case 'i': + if (tableinfo.relpersistence == 'u') + printfPQExpBuffer(&title, _("Unlogged index \"%s.%s\""), + schemaname, relationname); + else + printfPQExpBuffer(&title, _("Index \"%s.%s\""), + schemaname, relationname); + break; + case 's': + /* not used as of 8.2, but keep it for backwards compatibility */ + printfPQExpBuffer(&title, _("Special relation \"%s.%s\""), + schemaname, relationname); + break; + case 't': + printfPQExpBuffer(&title, _("TOAST table \"%s.%s\""), + schemaname, relationname); + break; + case 'c': + printfPQExpBuffer(&title, _("Composite type \"%s.%s\""), + schemaname, relationname); + break; + case 'f': + printfPQExpBuffer(&title, _("Foreign table \"%s.%s\""), + schemaname, relationname); + break; + default: + /* untranslated unknown relkind */ + printfPQExpBuffer(&title, "?%c? \"%s.%s\"", + tableinfo.relkind, schemaname, relationname); + break; + } + + /* Set the number of columns, and their names */ + headers[0] = gettext_noop("Column"); + headers[1] = gettext_noop("Type"); + cols = 2; + + if (tableinfo.relkind == 'r' || tableinfo.relkind == 'v' || + tableinfo.relkind == 'm' || + tableinfo.relkind == 'f' || tableinfo.relkind == 'c') + { + show_modifiers = true; + headers[cols++] = gettext_noop("Modifiers"); + modifiers = pg_malloc0((numrows + 1) * sizeof(*modifiers)); + } + + if (tableinfo.relkind == 'S') + headers[cols++] = gettext_noop("Value"); + + if (tableinfo.relkind == 'i') + headers[cols++] = gettext_noop("Definition"); + + if (tableinfo.relkind == 'f' && pset.sversion >= 90200) + headers[cols++] = gettext_noop("FDW Options"); + + if (verbose) + { + headers[cols++] = gettext_noop("Storage"); + if (tableinfo.relkind == 'r' || tableinfo.relkind == 'm' || + tableinfo.relkind == 'f') + headers[cols++] = gettext_noop("Stats target"); + /* Column comments, if the relkind supports this feature. */ + if (tableinfo.relkind == 'r' || tableinfo.relkind == 'v' || + tableinfo.relkind == 'm' || + tableinfo.relkind == 'c' || tableinfo.relkind == 'f') + headers[cols++] = gettext_noop("Description"); + } + + printTableInit(&cont, &myopt, title.data, cols, numrows); + printTableInitialized = true; + + for (i = 0; i < cols; i++) + printTableAddHeader(&cont, headers[i], true, 'l'); + + /* Check if table is a view or materialized view */ + if ((tableinfo.relkind == 'v' || tableinfo.relkind == 'm') && verbose) + { + PGresult *result; + + printfPQExpBuffer(&buf, + "SELECT pg_catalog.pg_get_viewdef('%s'::pg_catalog.oid, true);", + oid); + result = PSQLexec(buf.data); + if (!result) + goto error_return; + + if (PQntuples(result) > 0) + view_def = pg_strdup(PQgetvalue(result, 0, 0)); + + PQclear(result); + } + + /* Generate table cells to be printed */ + for (i = 0; i < numrows; i++) + { + /* Column */ + printTableAddCell(&cont, PQgetvalue(res, i, 0), false, false); + + /* Type */ + printTableAddCell(&cont, PQgetvalue(res, i, 1), false, false); + + /* Modifiers: collate, not null, default */ + if (show_modifiers) + { + resetPQExpBuffer(&tmpbuf); + + if (!PQgetisnull(res, i, 5)) + { + if (tmpbuf.len > 0) + appendPQExpBufferChar(&tmpbuf, ' '); + appendPQExpBuffer(&tmpbuf, _("collate %s"), + PQgetvalue(res, i, 5)); + } + + if (strcmp(PQgetvalue(res, i, 3), "t") == 0) + { + if (tmpbuf.len > 0) + appendPQExpBufferChar(&tmpbuf, ' '); + appendPQExpBufferStr(&tmpbuf, _("not null")); + } + + /* handle "default" here */ + /* (note: above we cut off the 'default' string at 128) */ + if (strlen(PQgetvalue(res, i, 2)) != 0) + { + if (tmpbuf.len > 0) + appendPQExpBufferChar(&tmpbuf, ' '); + /* translator: default values of column definitions */ + appendPQExpBuffer(&tmpbuf, _("default %s"), + PQgetvalue(res, i, 2)); + } + + modifiers[i] = pg_strdup(tmpbuf.data); + printTableAddCell(&cont, modifiers[i], false, false); + } + + /* Value: for sequences only */ + if (tableinfo.relkind == 'S') + printTableAddCell(&cont, seq_values[i], false, false); + + /* Expression for index column */ + if (tableinfo.relkind == 'i') + printTableAddCell(&cont, PQgetvalue(res, i, 6), false, false); + + /* FDW options for foreign table column, only for 9.2 or later */ + if (tableinfo.relkind == 'f' && pset.sversion >= 90200) + printTableAddCell(&cont, PQgetvalue(res, i, 7), false, false); + + /* Storage and Description */ + if (verbose) + { + int firstvcol = 8; + char *storage = PQgetvalue(res, i, firstvcol); + + /* these strings are literal in our syntax, so not translated. */ + printTableAddCell(&cont, (storage[0] == 'p' ? "plain" : + (storage[0] == 'm' ? "main" : + (storage[0] == 'x' ? "extended" : + (storage[0] == 'e' ? "external" : + "???")))), + false, false); + + /* Statistics target, if the relkind supports this feature */ + if (tableinfo.relkind == 'r' || tableinfo.relkind == 'm' || + tableinfo.relkind == 'f') + { + printTableAddCell(&cont, PQgetvalue(res, i, firstvcol + 1), + false, false); + } + + /* Column comments, if the relkind supports this feature. */ + if (tableinfo.relkind == 'r' || tableinfo.relkind == 'v' || + tableinfo.relkind == 'm' || + tableinfo.relkind == 'c' || tableinfo.relkind == 'f') + printTableAddCell(&cont, PQgetvalue(res, i, firstvcol + 2), + false, false); + } + } + + /* Make footers */ + if (tableinfo.relkind == 'i') + { + /* Footer information about an index */ + PGresult *result; + + printfPQExpBuffer(&buf, + "SELECT i.indisunique, i.indisprimary, i.indisclustered, "); + if (pset.sversion >= 80200) + appendPQExpBufferStr(&buf, "i.indisvalid,\n"); + else + appendPQExpBufferStr(&buf, "true AS indisvalid,\n"); + if (pset.sversion >= 90000) + appendPQExpBufferStr(&buf, + " (NOT i.indimmediate) AND " + "EXISTS (SELECT 1 FROM pg_catalog.pg_constraint " + "WHERE conrelid = i.indrelid AND " + "conindid = i.indexrelid AND " + "contype IN ('p','u','x') AND " + "condeferrable) AS condeferrable,\n" + " (NOT i.indimmediate) AND " + "EXISTS (SELECT 1 FROM pg_catalog.pg_constraint " + "WHERE conrelid = i.indrelid AND " + "conindid = i.indexrelid AND " + "contype IN ('p','u','x') AND " + "condeferred) AS condeferred,\n"); + else + appendPQExpBufferStr(&buf, + " false AS condeferrable, false AS condeferred,\n"); + + if (pset.sversion >= 90400) + appendPQExpBuffer(&buf, "i.indisreplident,\n"); + else + appendPQExpBuffer(&buf, "false AS indisreplident,\n"); + + appendPQExpBuffer(&buf, " a.amname, c2.relname, " + "pg_catalog.pg_get_expr(i.indpred, i.indrelid, true)\n" + "FROM pg_catalog.pg_index i, pg_catalog.pg_class c, pg_catalog.pg_class c2, pg_catalog.pg_am a\n" + "WHERE i.indexrelid = c.oid AND c.oid = '%s' AND c.relam = a.oid\n" + "AND i.indrelid = c2.oid;", + oid); + + result = PSQLexec(buf.data); + if (!result) + goto error_return; + else if (PQntuples(result) != 1) + { + PQclear(result); + goto error_return; + } + else + { + char *indisunique = PQgetvalue(result, 0, 0); + char *indisprimary = PQgetvalue(result, 0, 1); + char *indisclustered = PQgetvalue(result, 0, 2); + char *indisvalid = PQgetvalue(result, 0, 3); + char *deferrable = PQgetvalue(result, 0, 4); + char *deferred = PQgetvalue(result, 0, 5); + char *indisreplident = PQgetvalue(result, 0, 6); + char *indamname = PQgetvalue(result, 0, 7); + char *indtable = PQgetvalue(result, 0, 8); + char *indpred = PQgetvalue(result, 0, 9); + + if (strcmp(indisprimary, "t") == 0) + printfPQExpBuffer(&tmpbuf, _("primary key, ")); + else if (strcmp(indisunique, "t") == 0) + printfPQExpBuffer(&tmpbuf, _("unique, ")); + else + resetPQExpBuffer(&tmpbuf); + appendPQExpBuffer(&tmpbuf, "%s, ", indamname); + + /* we assume here that index and table are in same schema */ + appendPQExpBuffer(&tmpbuf, _("for table \"%s.%s\""), + schemaname, indtable); + + if (strlen(indpred)) + appendPQExpBuffer(&tmpbuf, _(", predicate (%s)"), indpred); + + if (strcmp(indisclustered, "t") == 0) + appendPQExpBufferStr(&tmpbuf, _(", clustered")); + + if (strcmp(indisvalid, "t") != 0) + appendPQExpBufferStr(&tmpbuf, _(", invalid")); + + if (strcmp(deferrable, "t") == 0) + appendPQExpBufferStr(&tmpbuf, _(", deferrable")); + + if (strcmp(deferred, "t") == 0) + appendPQExpBufferStr(&tmpbuf, _(", initially deferred")); + + if (strcmp(indisreplident, "t") == 0) + appendPQExpBuffer(&tmpbuf, _(", replica identity")); + + printTableAddFooter(&cont, tmpbuf.data); + add_tablespace_footer(&cont, tableinfo.relkind, + tableinfo.tablespace, true); + } + + PQclear(result); + } + else if (tableinfo.relkind == 'S') + { + /* Footer information about a sequence */ + PGresult *result = NULL; + + /* Get the column that owns this sequence */ + printfPQExpBuffer(&buf, "SELECT pg_catalog.quote_ident(nspname) || '.' ||" + "\n pg_catalog.quote_ident(relname) || '.' ||" + "\n pg_catalog.quote_ident(attname)" + "\nFROM pg_catalog.pg_class c" + "\nINNER JOIN pg_catalog.pg_depend d ON c.oid=d.refobjid" + "\nINNER JOIN pg_catalog.pg_namespace n ON n.oid=c.relnamespace" + "\nINNER JOIN pg_catalog.pg_attribute a ON (" + "\n a.attrelid=c.oid AND" + "\n a.attnum=d.refobjsubid)" + "\nWHERE d.classid='pg_catalog.pg_class'::pg_catalog.regclass" + "\n AND d.refclassid='pg_catalog.pg_class'::pg_catalog.regclass" + "\n AND d.objid=%s" + "\n AND d.deptype='a'", + oid); + + result = PSQLexec(buf.data); + if (!result) + goto error_return; + else if (PQntuples(result) == 1) + { + printfPQExpBuffer(&buf, _("Owned by: %s"), + PQgetvalue(result, 0, 0)); + printTableAddFooter(&cont, buf.data); + } + + /* + * If we get no rows back, don't show anything (obviously). We should + * never get more than one row back, but if we do, just ignore it and + * don't print anything. + */ + PQclear(result); + } + else if (tableinfo.relkind == 'r' || tableinfo.relkind == 'm' || + tableinfo.relkind == 'f') + { + /* Footer information about a table */ + PGresult *result = NULL; + int tuples = 0; + + /* print indexes */ + if (tableinfo.hasindex) + { + printfPQExpBuffer(&buf, + "SELECT c2.relname, i.indisprimary, i.indisunique, i.indisclustered, "); + if (pset.sversion >= 80200) + appendPQExpBufferStr(&buf, "i.indisvalid, "); + else + appendPQExpBufferStr(&buf, "true as indisvalid, "); + appendPQExpBufferStr(&buf, "pg_catalog.pg_get_indexdef(i.indexrelid, 0, true),\n "); + if (pset.sversion >= 90000) + appendPQExpBufferStr(&buf, + "pg_catalog.pg_get_constraintdef(con.oid, true), " + "contype, condeferrable, condeferred"); + else + appendPQExpBufferStr(&buf, + "null AS constraintdef, null AS contype, " + "false AS condeferrable, false AS condeferred"); + if (pset.sversion >= 90400) + appendPQExpBufferStr(&buf, ", i.indisreplident"); + else + appendPQExpBufferStr(&buf, ", false AS indisreplident"); + if (pset.sversion >= 80000) + appendPQExpBufferStr(&buf, ", c2.reltablespace"); + appendPQExpBufferStr(&buf, + "\nFROM pg_catalog.pg_class c, pg_catalog.pg_class c2, pg_catalog.pg_index i\n"); + if (pset.sversion >= 90000) + appendPQExpBufferStr(&buf, + " LEFT JOIN pg_catalog.pg_constraint con ON (conrelid = i.indrelid AND conindid = i.indexrelid AND contype IN ('p','u','x'))\n"); + appendPQExpBuffer(&buf, + "WHERE c.oid = '%s' AND c.oid = i.indrelid AND i.indexrelid = c2.oid\n" + "ORDER BY i.indisprimary DESC, i.indisunique DESC, c2.relname;", + oid); + result = PSQLexec(buf.data); + if (!result) + goto error_return; + else + tuples = PQntuples(result); + + if (tuples > 0) + { + printTableAddFooter(&cont, _("Indexes:")); + for (i = 0; i < tuples; i++) + { + /* untranslated index name */ + printfPQExpBuffer(&buf, " \"%s\"", + PQgetvalue(result, i, 0)); + + /* If exclusion constraint, print the constraintdef */ + if (strcmp(PQgetvalue(result, i, 7), "x") == 0) + { + appendPQExpBuffer(&buf, " %s", + PQgetvalue(result, i, 6)); + } + else + { + const char *indexdef; + const char *usingpos; + + /* Label as primary key or unique (but not both) */ + if (strcmp(PQgetvalue(result, i, 1), "t") == 0) + appendPQExpBufferStr(&buf, " PRIMARY KEY,"); + else if (strcmp(PQgetvalue(result, i, 2), "t") == 0) + { + if (strcmp(PQgetvalue(result, i, 7), "u") == 0) + appendPQExpBufferStr(&buf, " UNIQUE CONSTRAINT,"); + else + appendPQExpBufferStr(&buf, " UNIQUE,"); + } + + /* Everything after "USING" is echoed verbatim */ + indexdef = PQgetvalue(result, i, 5); + usingpos = strstr(indexdef, " USING "); + if (usingpos) + indexdef = usingpos + 7; + appendPQExpBuffer(&buf, " %s", indexdef); + + /* Need these for deferrable PK/UNIQUE indexes */ + if (strcmp(PQgetvalue(result, i, 8), "t") == 0) + appendPQExpBufferStr(&buf, " DEFERRABLE"); + + if (strcmp(PQgetvalue(result, i, 9), "t") == 0) + appendPQExpBufferStr(&buf, " INITIALLY DEFERRED"); + } + + /* Add these for all cases */ + if (strcmp(PQgetvalue(result, i, 3), "t") == 0) + appendPQExpBufferStr(&buf, " CLUSTER"); + + if (strcmp(PQgetvalue(result, i, 4), "t") != 0) + appendPQExpBufferStr(&buf, " INVALID"); + + if (strcmp(PQgetvalue(result, i, 10), "t") == 0) + appendPQExpBuffer(&buf, " REPLICA IDENTITY"); + + printTableAddFooter(&cont, buf.data); + + /* Print tablespace of the index on the same line */ + if (pset.sversion >= 80000) + add_tablespace_footer(&cont, 'i', + atooid(PQgetvalue(result, i, 11)), + false); + } + } + PQclear(result); + } + + /* print table (and column) check constraints */ + if (tableinfo.checks) + { + printfPQExpBuffer(&buf, + "SELECT r.conname, " + "pg_catalog.pg_get_constraintdef(r.oid, true)\n" + "FROM pg_catalog.pg_constraint r\n" + "WHERE r.conrelid = '%s' AND r.contype = 'c'\n" + "ORDER BY 1;", + oid); + result = PSQLexec(buf.data); + if (!result) + goto error_return; + else + tuples = PQntuples(result); + + if (tuples > 0) + { + printTableAddFooter(&cont, _("Check constraints:")); + for (i = 0; i < tuples; i++) + { + /* untranslated contraint name and def */ + printfPQExpBuffer(&buf, " \"%s\" %s", + PQgetvalue(result, i, 0), + PQgetvalue(result, i, 1)); + + printTableAddFooter(&cont, buf.data); + } + } + PQclear(result); + } + + /* print foreign-key constraints (there are none if no triggers) */ + if (tableinfo.hastriggers) + { + printfPQExpBuffer(&buf, + "SELECT conname,\n" + " pg_catalog.pg_get_constraintdef(r.oid, true) as condef\n" + "FROM pg_catalog.pg_constraint r\n" + "WHERE r.conrelid = '%s' AND r.contype = 'f' ORDER BY 1;", + oid); + result = PSQLexec(buf.data); + if (!result) + goto error_return; + else + tuples = PQntuples(result); + + if (tuples > 0) + { + printTableAddFooter(&cont, _("Foreign-key constraints:")); + for (i = 0; i < tuples; i++) + { + /* untranslated constraint name and def */ + printfPQExpBuffer(&buf, " \"%s\" %s", + PQgetvalue(result, i, 0), + PQgetvalue(result, i, 1)); + + printTableAddFooter(&cont, buf.data); + } + } + PQclear(result); + } + + /* print incoming foreign-key references (none if no triggers) */ + if (tableinfo.hastriggers) + { + printfPQExpBuffer(&buf, + "SELECT conname, conrelid::pg_catalog.regclass,\n" + " pg_catalog.pg_get_constraintdef(c.oid, true) as condef\n" + "FROM pg_catalog.pg_constraint c\n" + "WHERE c.confrelid = '%s' AND c.contype = 'f' ORDER BY 1;", + oid); + result = PSQLexec(buf.data); + if (!result) + goto error_return; + else + tuples = PQntuples(result); + + if (tuples > 0) + { + printTableAddFooter(&cont, _("Referenced by:")); + for (i = 0; i < tuples; i++) + { + printfPQExpBuffer(&buf, " TABLE \"%s\" CONSTRAINT \"%s\" %s", + PQgetvalue(result, i, 1), + PQgetvalue(result, i, 0), + PQgetvalue(result, i, 2)); + + printTableAddFooter(&cont, buf.data); + } + } + PQclear(result); + } + + /* print any row-level policies */ + if (pset.sversion >= 90500) + { + printfPQExpBuffer(&buf, + "SELECT pol.polname,\n" + "CASE WHEN pol.polroles = '{0}' THEN NULL ELSE array_to_string(array(select rolname from pg_roles where oid = any (pol.polroles) order by 1),',') END,\n" + "pg_catalog.pg_get_expr(pol.polqual, pol.polrelid),\n" + "pg_catalog.pg_get_expr(pol.polwithcheck, pol.polrelid),\n" + "CASE pol.polcmd \n" + "WHEN 'r' THEN 'SELECT'\n" + "WHEN 'a' THEN 'INSERT'\n" + "WHEN 'w' THEN 'UPDATE'\n" + "WHEN 'd' THEN 'DELETE'\n" + "WHEN '*' THEN 'ALL'\n" + "END AS cmd\n" + "FROM pg_catalog.pg_policy pol\n" + "WHERE pol.polrelid = '%s' ORDER BY 1;", + oid); + + result = PSQLexec(buf.data); + if (!result) + goto error_return; + else + tuples = PQntuples(result); + + /* + * Handle cases where RLS is enabled and there are policies, or + * there aren't policies, or RLS isn't enabled but there are + * policies + */ + if (tableinfo.rowsecurity && !tableinfo.forcerowsecurity && tuples > 0) + printTableAddFooter(&cont, _("Policies:")); + + if (tableinfo.rowsecurity && tableinfo.forcerowsecurity && tuples > 0) + printTableAddFooter(&cont, _("Policies (forced row security enabled):")); + + if (tableinfo.rowsecurity && !tableinfo.forcerowsecurity && tuples == 0) + printTableAddFooter(&cont, _("Policies (row security enabled): (none)")); + + if (tableinfo.rowsecurity && tableinfo.forcerowsecurity && tuples == 0) + printTableAddFooter(&cont, _("Policies (forced row security enabled): (none)")); + + if (!tableinfo.rowsecurity && tuples > 0) + printTableAddFooter(&cont, _("Policies (row security disabled):")); + + /* Might be an empty set - that's ok */ + for (i = 0; i < tuples; i++) + { + printfPQExpBuffer(&buf, " POLICY \"%s\"", + PQgetvalue(result, i, 0)); + + if (!PQgetisnull(result, i, 4)) + appendPQExpBuffer(&buf, " FOR %s", + PQgetvalue(result, i, 4)); + + if (!PQgetisnull(result, i, 1)) + { + appendPQExpBuffer(&buf, "\n TO %s", + PQgetvalue(result, i, 1)); + } + + if (!PQgetisnull(result, i, 2)) + appendPQExpBuffer(&buf, "\n USING (%s)", + PQgetvalue(result, i, 2)); + + if (!PQgetisnull(result, i, 3)) + appendPQExpBuffer(&buf, "\n WITH CHECK (%s)", + PQgetvalue(result, i, 3)); + + printTableAddFooter(&cont, buf.data); + + } + PQclear(result); + } + + /* print rules */ + if (tableinfo.hasrules && tableinfo.relkind != 'm') + { + if (pset.sversion >= 80300) + { + printfPQExpBuffer(&buf, + "SELECT r.rulename, trim(trailing ';' from pg_catalog.pg_get_ruledef(r.oid, true)), " + "ev_enabled\n" + "FROM pg_catalog.pg_rewrite r\n" + "WHERE r.ev_class = '%s' ORDER BY 1;", + oid); + } + else + { + printfPQExpBuffer(&buf, + "SELECT r.rulename, trim(trailing ';' from pg_catalog.pg_get_ruledef(r.oid, true)), " + "'O'::char AS ev_enabled\n" + "FROM pg_catalog.pg_rewrite r\n" + "WHERE r.ev_class = '%s' ORDER BY 1;", + oid); + } + result = PSQLexec(buf.data); + if (!result) + goto error_return; + else + tuples = PQntuples(result); + + if (tuples > 0) + { + bool have_heading; + int category; + + for (category = 0; category < 4; category++) + { + have_heading = false; + + for (i = 0; i < tuples; i++) + { + const char *ruledef; + bool list_rule = false; + + switch (category) + { + case 0: + if (*PQgetvalue(result, i, 2) == 'O') + list_rule = true; + break; + case 1: + if (*PQgetvalue(result, i, 2) == 'D') + list_rule = true; + break; + case 2: + if (*PQgetvalue(result, i, 2) == 'A') + list_rule = true; + break; + case 3: + if (*PQgetvalue(result, i, 2) == 'R') + list_rule = true; + break; + } + if (!list_rule) + continue; + + if (!have_heading) + { + switch (category) + { + case 0: + printfPQExpBuffer(&buf, _("Rules:")); + break; + case 1: + printfPQExpBuffer(&buf, _("Disabled rules:")); + break; + case 2: + printfPQExpBuffer(&buf, _("Rules firing always:")); + break; + case 3: + printfPQExpBuffer(&buf, _("Rules firing on replica only:")); + break; + } + printTableAddFooter(&cont, buf.data); + have_heading = true; + } + + /* Everything after "CREATE RULE" is echoed verbatim */ + ruledef = PQgetvalue(result, i, 1); + ruledef += 12; + printfPQExpBuffer(&buf, " %s", ruledef); + printTableAddFooter(&cont, buf.data); + } + } + } + PQclear(result); + } + } + + if (view_def) + { + PGresult *result = NULL; + + /* Footer information about a view */ + printTableAddFooter(&cont, _("View definition:")); + printTableAddFooter(&cont, view_def); + + /* print rules */ + if (tableinfo.hasrules) + { + printfPQExpBuffer(&buf, + "SELECT r.rulename, trim(trailing ';' from pg_catalog.pg_get_ruledef(r.oid, true))\n" + "FROM pg_catalog.pg_rewrite r\n" + "WHERE r.ev_class = '%s' AND r.rulename != '_RETURN' ORDER BY 1;", + oid); + result = PSQLexec(buf.data); + if (!result) + goto error_return; + + if (PQntuples(result) > 0) + { + printTableAddFooter(&cont, _("Rules:")); + for (i = 0; i < PQntuples(result); i++) + { + const char *ruledef; + + /* Everything after "CREATE RULE" is echoed verbatim */ + ruledef = PQgetvalue(result, i, 1); + ruledef += 12; + + printfPQExpBuffer(&buf, " %s", ruledef); + printTableAddFooter(&cont, buf.data); + } + } + PQclear(result); + } + } + + /* + * Print triggers next, if any (but only user-defined triggers). This + * could apply to either a table or a view. + */ + if (tableinfo.hastriggers) + { + PGresult *result; + int tuples; + + printfPQExpBuffer(&buf, + "SELECT t.tgname, " + "pg_catalog.pg_get_triggerdef(t.oid%s), " + "t.tgenabled, %s\n" + "FROM pg_catalog.pg_trigger t\n" + "WHERE t.tgrelid = '%s' AND ", + (pset.sversion >= 90000 ? ", true" : ""), + (pset.sversion >= 90000 ? "t.tgisinternal" : + pset.sversion >= 80300 ? + "t.tgconstraint <> 0 AS tgisinternal" : + "false AS tgisinternal"), oid); + if (pset.sversion >= 90000) + /* display/warn about disabled internal triggers */ + appendPQExpBuffer(&buf, "(NOT t.tgisinternal OR (t.tgisinternal AND t.tgenabled = 'D'))"); + else if (pset.sversion >= 80300) + appendPQExpBufferStr(&buf, "(t.tgconstraint = 0 OR (t.tgconstraint <> 0 AND t.tgenabled = 'D'))"); + else + appendPQExpBufferStr(&buf, + "(NOT tgisconstraint " + " OR NOT EXISTS" + " (SELECT 1 FROM pg_catalog.pg_depend d " + " JOIN pg_catalog.pg_constraint c ON (d.refclassid = c.tableoid AND d.refobjid = c.oid) " + " WHERE d.classid = t.tableoid AND d.objid = t.oid AND d.deptype = 'i' AND c.contype = 'f'))"); + appendPQExpBufferStr(&buf, "\nORDER BY 1;"); + + result = PSQLexec(buf.data); + if (!result) + goto error_return; + else + tuples = PQntuples(result); + + if (tuples > 0) + { + bool have_heading; + int category; + + /* + * split the output into 4 different categories. Enabled triggers, + * disabled triggers and the two special ALWAYS and REPLICA + * configurations. + */ + for (category = 0; category <= 4; category++) + { + have_heading = false; + for (i = 0; i < tuples; i++) + { + bool list_trigger; + const char *tgdef; + const char *usingpos; + const char *tgenabled; + const char *tgisinternal; + + /* + * Check if this trigger falls into the current category + */ + tgenabled = PQgetvalue(result, i, 2); + tgisinternal = PQgetvalue(result, i, 3); + list_trigger = false; + switch (category) + { + case 0: + if (*tgenabled == 'O' || *tgenabled == 't') + list_trigger = true; + break; + case 1: + if ((*tgenabled == 'D' || *tgenabled == 'f') && + *tgisinternal == 'f') + list_trigger = true; + break; + case 2: + if ((*tgenabled == 'D' || *tgenabled == 'f') && + *tgisinternal == 't') + list_trigger = true; + break; + case 3: + if (*tgenabled == 'A') + list_trigger = true; + break; + case 4: + if (*tgenabled == 'R') + list_trigger = true; + break; + } + if (list_trigger == false) + continue; + + /* Print the category heading once */ + if (have_heading == false) + { + switch (category) + { + case 0: + printfPQExpBuffer(&buf, _("Triggers:")); + break; + case 1: + if (pset.sversion >= 80300) + printfPQExpBuffer(&buf, _("Disabled user triggers:")); + else + printfPQExpBuffer(&buf, _("Disabled triggers:")); + break; + case 2: + printfPQExpBuffer(&buf, _("Disabled internal triggers:")); + break; + case 3: + printfPQExpBuffer(&buf, _("Triggers firing always:")); + break; + case 4: + printfPQExpBuffer(&buf, _("Triggers firing on replica only:")); + break; + + } + printTableAddFooter(&cont, buf.data); + have_heading = true; + } + + /* Everything after "TRIGGER" is echoed verbatim */ + tgdef = PQgetvalue(result, i, 1); + usingpos = strstr(tgdef, " TRIGGER "); + if (usingpos) + tgdef = usingpos + 9; + + printfPQExpBuffer(&buf, " %s", tgdef); + printTableAddFooter(&cont, buf.data); + } + } + } + PQclear(result); + } + + /* + * Finish printing the footer information about a table. + */ + if (tableinfo.relkind == 'r' || tableinfo.relkind == 'm' || + tableinfo.relkind == 'f') + { + PGresult *result; + int tuples; + + /* print foreign server name */ + if (tableinfo.relkind == 'f') + { + char *ftoptions; + + /* Footer information about foreign table */ + printfPQExpBuffer(&buf, + "SELECT s.srvname,\n" + " array_to_string(ARRAY(SELECT " + " quote_ident(option_name) || ' ' || " + " quote_literal(option_value) FROM " + " pg_options_to_table(ftoptions)), ', ') " + "FROM pg_catalog.pg_foreign_table f,\n" + " pg_catalog.pg_foreign_server s\n" + "WHERE f.ftrelid = %s AND s.oid = f.ftserver;", + oid); + result = PSQLexec(buf.data); + if (!result) + goto error_return; + else if (PQntuples(result) != 1) + { + PQclear(result); + goto error_return; + } + + /* Print server name */ + printfPQExpBuffer(&buf, "Server: %s", + PQgetvalue(result, 0, 0)); + printTableAddFooter(&cont, buf.data); + + /* Print per-table FDW options, if any */ + ftoptions = PQgetvalue(result, 0, 1); + if (ftoptions && ftoptions[0] != '\0') + { + printfPQExpBuffer(&buf, "FDW Options: (%s)", ftoptions); + printTableAddFooter(&cont, buf.data); + } + PQclear(result); + } + + /* print inherited tables */ + printfPQExpBuffer(&buf, "SELECT c.oid::pg_catalog.regclass FROM pg_catalog.pg_class c, pg_catalog.pg_inherits i WHERE c.oid=i.inhparent AND i.inhrelid = '%s' ORDER BY inhseqno;", oid); + + result = PSQLexec(buf.data); + if (!result) + goto error_return; + else + { + const char *s = _("Inherits"); + int sw = pg_wcswidth(s, strlen(s), pset.encoding); + + tuples = PQntuples(result); + + for (i = 0; i < tuples; i++) + { + if (i == 0) + printfPQExpBuffer(&buf, "%s: %s", + s, PQgetvalue(result, i, 0)); + else + printfPQExpBuffer(&buf, "%*s %s", + sw, "", PQgetvalue(result, i, 0)); + if (i < tuples - 1) + appendPQExpBufferChar(&buf, ','); + + printTableAddFooter(&cont, buf.data); + } + + PQclear(result); + } + + /* print child tables */ + if (pset.sversion >= 80300) + printfPQExpBuffer(&buf, "SELECT c.oid::pg_catalog.regclass FROM pg_catalog.pg_class c, pg_catalog.pg_inherits i WHERE c.oid=i.inhrelid AND i.inhparent = '%s' ORDER BY c.oid::pg_catalog.regclass::pg_catalog.text;", oid); + else + printfPQExpBuffer(&buf, "SELECT c.oid::pg_catalog.regclass FROM pg_catalog.pg_class c, pg_catalog.pg_inherits i WHERE c.oid=i.inhrelid AND i.inhparent = '%s' ORDER BY c.relname;", oid); + + result = PSQLexec(buf.data); + if (!result) + goto error_return; + else + tuples = PQntuples(result); + + if (!verbose) + { + /* print the number of child tables, if any */ + if (tuples > 0) + { + printfPQExpBuffer(&buf, _("Number of child tables: %d (Use \\d+ to list them.)"), tuples); + printTableAddFooter(&cont, buf.data); + } + } + else + { + /* display the list of child tables */ + const char *ct = _("Child tables"); + int ctw = pg_wcswidth(ct, strlen(ct), pset.encoding); + + for (i = 0; i < tuples; i++) + { + if (i == 0) + printfPQExpBuffer(&buf, "%s: %s", + ct, PQgetvalue(result, i, 0)); + else + printfPQExpBuffer(&buf, "%*s %s", + ctw, "", PQgetvalue(result, i, 0)); + if (i < tuples - 1) + appendPQExpBufferChar(&buf, ','); + + printTableAddFooter(&cont, buf.data); + } + } + PQclear(result); + + /* Table type */ + if (tableinfo.reloftype) + { + printfPQExpBuffer(&buf, _("Typed table of type: %s"), tableinfo.reloftype); + printTableAddFooter(&cont, buf.data); + } + + if (verbose && (tableinfo.relkind == 'r' || tableinfo.relkind == 'm') && + + /* + * No need to display default values; we already display a REPLICA + * IDENTITY marker on indexes. + */ + tableinfo.relreplident != 'i' && + ((strcmp(schemaname, "pg_catalog") != 0 && tableinfo.relreplident != 'd') || + (strcmp(schemaname, "pg_catalog") == 0 && tableinfo.relreplident != 'n'))) + { + const char *s = _("Replica Identity"); + + printfPQExpBuffer(&buf, "%s: %s", + s, + tableinfo.relreplident == 'f' ? "FULL" : + tableinfo.relreplident == 'n' ? "NOTHING" : + "???"); + + printTableAddFooter(&cont, buf.data); + } + + /* OIDs, if verbose and not a materialized view */ + if (verbose && tableinfo.relkind != 'm' && tableinfo.hasoids) + printTableAddFooter(&cont, _("Has OIDs: yes")); + + /* Tablespace info */ + add_tablespace_footer(&cont, tableinfo.relkind, tableinfo.tablespace, + true); + } + + /* reloptions, if verbose */ + if (verbose && + tableinfo.reloptions && tableinfo.reloptions[0] != '\0') + { + const char *t = _("Options"); + + printfPQExpBuffer(&buf, "%s: %s", t, tableinfo.reloptions); + printTableAddFooter(&cont, buf.data); + } + + printTable(&cont, pset.queryFout, false, pset.logfile); + + retval = true; + +error_return: + + /* clean up */ + if (printTableInitialized) + printTableCleanup(&cont); + termPQExpBuffer(&buf); + termPQExpBuffer(&title); + termPQExpBuffer(&tmpbuf); + + if (seq_values) + { + for (ptr = seq_values; *ptr; ptr++) + free(*ptr); + free(seq_values); + } + + if (modifiers) + { + for (ptr = modifiers; *ptr; ptr++) + free(*ptr); + free(modifiers); + } + + if (view_def) + free(view_def); + + if (res) + PQclear(res); + + return retval; +} + +/* + * Add a tablespace description to a footer. If 'newline' is true, it is added + * in a new line; otherwise it's appended to the current value of the last + * footer. + */ +static void +add_tablespace_footer(printTableContent *const cont, char relkind, + Oid tablespace, const bool newline) +{ + /* relkinds for which we support tablespaces */ + if (relkind == 'r' || relkind == 'm' || relkind == 'i') + { + /* + * We ignore the database default tablespace so that users not using + * tablespaces don't need to know about them. This case also covers + * pre-8.0 servers, for which tablespace will always be 0. + */ + if (tablespace != 0) + { + PGresult *result = NULL; + PQExpBufferData buf; + + initPQExpBuffer(&buf); + printfPQExpBuffer(&buf, + "SELECT spcname FROM pg_catalog.pg_tablespace\n" + "WHERE oid = '%u';", tablespace); + result = PSQLexec(buf.data); + if (!result) + return; + /* Should always be the case, but.... */ + if (PQntuples(result) > 0) + { + if (newline) + { + /* Add the tablespace as a new footer */ + printfPQExpBuffer(&buf, _("Tablespace: \"%s\""), + PQgetvalue(result, 0, 0)); + printTableAddFooter(cont, buf.data); + } + else + { + /* Append the tablespace to the latest footer */ + printfPQExpBuffer(&buf, "%s", cont->footer->data); + + /*------- + translator: before this string there's an index description like + '"foo_pkey" PRIMARY KEY, btree (a)' */ + appendPQExpBuffer(&buf, _(", tablespace \"%s\""), + PQgetvalue(result, 0, 0)); + printTableSetFooter(cont, buf.data); + } + } + PQclear(result); + termPQExpBuffer(&buf); + } + } +} + +/* + * \du or \dg + * + * Describes roles. Any schema portion of the pattern is ignored. + */ +bool +describeRoles(const char *pattern, bool verbose) +{ + PQExpBufferData buf; + PGresult *res; + printTableContent cont; + printTableOpt myopt = pset.popt.topt; + int ncols = 3; + int nrows = 0; + int i; + int conns; + const char align = 'l'; + char **attr; + + myopt.default_footer = false; + + initPQExpBuffer(&buf); + + if (pset.sversion >= 80100) + { + printfPQExpBuffer(&buf, + "SELECT r.rolname, r.rolsuper, r.rolinherit,\n" + " r.rolcreaterole, r.rolcreatedb, r.rolcanlogin,\n" + " r.rolconnlimit, r.rolvaliduntil,\n" + " ARRAY(SELECT b.rolname\n" + " FROM pg_catalog.pg_auth_members m\n" + " JOIN pg_catalog.pg_roles b ON (m.roleid = b.oid)\n" + " WHERE m.member = r.oid) as memberof"); + + if (verbose && pset.sversion >= 80200) + { + appendPQExpBufferStr(&buf, "\n, pg_catalog.shobj_description(r.oid, 'pg_authid') AS description"); + ncols++; + } + if (pset.sversion >= 90100) + { + appendPQExpBufferStr(&buf, "\n, r.rolreplication"); + } + + if (pset.sversion >= 90500) + { + appendPQExpBufferStr(&buf, "\n, r.rolbypassrls"); + } + + appendPQExpBufferStr(&buf, "\nFROM pg_catalog.pg_roles r\n"); + + processSQLNamePattern(pset.db, &buf, pattern, false, false, + NULL, "r.rolname", NULL, NULL); + } + else + { + printfPQExpBuffer(&buf, + "SELECT u.usename AS rolname,\n" + " u.usesuper AS rolsuper,\n" + " true AS rolinherit, false AS rolcreaterole,\n" + " u.usecreatedb AS rolcreatedb, true AS rolcanlogin,\n" + " -1 AS rolconnlimit," + " u.valuntil as rolvaliduntil,\n" + " ARRAY(SELECT g.groname FROM pg_catalog.pg_group g WHERE u.usesysid = ANY(g.grolist)) as memberof" + "\nFROM pg_catalog.pg_user u\n"); + + processSQLNamePattern(pset.db, &buf, pattern, false, false, + NULL, "u.usename", NULL, NULL); + } + + appendPQExpBufferStr(&buf, "ORDER BY 1;"); + + res = PSQLexec(buf.data); + if (!res) + return false; + + nrows = PQntuples(res); + attr = pg_malloc0((nrows + 1) * sizeof(*attr)); + + printTableInit(&cont, &myopt, _("List of roles"), ncols, nrows); + + printTableAddHeader(&cont, gettext_noop("Role name"), true, align); + printTableAddHeader(&cont, gettext_noop("Attributes"), true, align); + printTableAddHeader(&cont, gettext_noop("Member of"), true, align); + + if (verbose && pset.sversion >= 80200) + printTableAddHeader(&cont, gettext_noop("Description"), true, align); + + for (i = 0; i < nrows; i++) + { + printTableAddCell(&cont, PQgetvalue(res, i, 0), false, false); + + resetPQExpBuffer(&buf); + if (strcmp(PQgetvalue(res, i, 1), "t") == 0) + add_role_attribute(&buf, _("Superuser")); + + if (strcmp(PQgetvalue(res, i, 2), "t") != 0) + add_role_attribute(&buf, _("No inheritance")); + + if (strcmp(PQgetvalue(res, i, 3), "t") == 0) + add_role_attribute(&buf, _("Create role")); + + if (strcmp(PQgetvalue(res, i, 4), "t") == 0) + add_role_attribute(&buf, _("Create DB")); + + if (strcmp(PQgetvalue(res, i, 5), "t") != 0) + add_role_attribute(&buf, _("Cannot login")); + + if (pset.sversion >= 90100) + if (strcmp(PQgetvalue(res, i, (verbose ? 10 : 9)), "t") == 0) + add_role_attribute(&buf, _("Replication")); + + if (pset.sversion >= 90500) + if (strcmp(PQgetvalue(res, i, (verbose ? 11 : 10)), "t") == 0) + add_role_attribute(&buf, _("Bypass RLS")); + + conns = atoi(PQgetvalue(res, i, 6)); + if (conns >= 0) + { + if (buf.len > 0) + appendPQExpBufferChar(&buf, '\n'); + + if (conns == 0) + appendPQExpBufferStr(&buf, _("No connections")); + else + appendPQExpBuffer(&buf, ngettext("%d connection", + "%d connections", + conns), + conns); + } + + if (strcmp(PQgetvalue(res, i, 7), "") != 0) + { + if (buf.len > 0) + appendPQExpBufferStr(&buf, "\n"); + appendPQExpBufferStr(&buf, _("Password valid until ")); + appendPQExpBufferStr(&buf, PQgetvalue(res, i, 7)); + } + + attr[i] = pg_strdup(buf.data); + + printTableAddCell(&cont, attr[i], false, false); + + printTableAddCell(&cont, PQgetvalue(res, i, 8), false, false); + + if (verbose && pset.sversion >= 80200) + printTableAddCell(&cont, PQgetvalue(res, i, 9), false, false); + } + termPQExpBuffer(&buf); + + printTable(&cont, pset.queryFout, false, pset.logfile); + printTableCleanup(&cont); + + for (i = 0; i < nrows; i++) + free(attr[i]); + free(attr); + + PQclear(res); + return true; +} + +static void +add_role_attribute(PQExpBuffer buf, const char *const str) +{ + if (buf->len > 0) + appendPQExpBufferStr(buf, ", "); + + appendPQExpBufferStr(buf, str); +} + +/* + * \drds + */ +bool +listDbRoleSettings(const char *pattern, const char *pattern2) +{ + PQExpBufferData buf; + PGresult *res; + printQueryOpt myopt = pset.popt; + + initPQExpBuffer(&buf); + + if (pset.sversion >= 90000) + { + bool havewhere; + + printfPQExpBuffer(&buf, "SELECT rolname AS \"%s\", datname AS \"%s\",\n" + "pg_catalog.array_to_string(setconfig, E'\\n') AS \"%s\"\n" + "FROM pg_db_role_setting AS s\n" + "LEFT JOIN pg_database ON pg_database.oid = setdatabase\n" + "LEFT JOIN pg_roles ON pg_roles.oid = setrole\n", + gettext_noop("Role"), + gettext_noop("Database"), + gettext_noop("Settings")); + havewhere = processSQLNamePattern(pset.db, &buf, pattern, false, false, + NULL, "pg_roles.rolname", NULL, NULL); + processSQLNamePattern(pset.db, &buf, pattern2, havewhere, false, + NULL, "pg_database.datname", NULL, NULL); + appendPQExpBufferStr(&buf, "ORDER BY 1, 2;"); + } + else + { + fprintf(pset.queryFout, + _("No per-database role settings support in this server version.\n")); + return false; + } + + res = PSQLexec(buf.data); + if (!res) + return false; + + if (PQntuples(res) == 0 && !pset.quiet) + { + if (pattern) + fprintf(pset.queryFout, _("No matching settings found.\n")); + else + fprintf(pset.queryFout, _("No settings found.\n")); + } + else + { + myopt.nullPrint = NULL; + myopt.title = _("List of settings"); + myopt.translate_header = true; + + printQuery(res, &myopt, pset.queryFout, false, pset.logfile); + } + + PQclear(res); + resetPQExpBuffer(&buf); + return true; +} + + +/* + * listTables() + * + * handler for \dt, \di, etc. + * + * tabtypes is an array of characters, specifying what info is desired: + * t - tables + * i - indexes + * v - views + * m - materialized views + * s - sequences + * E - foreign table (Note: different from 'f', the relkind value) + * (any order of the above is fine) + * If tabtypes is empty, we default to \dtvsE. + */ +bool +listTables(const char *tabtypes, const char *pattern, bool verbose, bool showSystem) +{ + bool showTables = strchr(tabtypes, 't') != NULL; + bool showIndexes = strchr(tabtypes, 'i') != NULL; + bool showViews = strchr(tabtypes, 'v') != NULL; + bool showMatViews = strchr(tabtypes, 'm') != NULL; + bool showSeq = strchr(tabtypes, 's') != NULL; + bool showForeign = strchr(tabtypes, 'E') != NULL; + + PQExpBufferData buf; + PGresult *res; + printQueryOpt myopt = pset.popt; + static const bool translate_columns[] = {false, false, true, false, false, false, false}; + + if (!(showTables || showIndexes || showViews || showMatViews || showSeq || showForeign)) + showTables = showViews = showMatViews = showSeq = showForeign = true; + + initPQExpBuffer(&buf); + + /* + * Note: as of Pg 8.2, we no longer use relkind 's', but we keep it here + * for backwards compatibility. + */ + printfPQExpBuffer(&buf, + "SELECT n.nspname as \"%s\",\n" + " c.relname as \"%s\",\n" + " CASE c.relkind" + " WHEN 'r' THEN '%s'" + " WHEN 'v' THEN '%s'" + " WHEN 'm' THEN '%s'" + " WHEN 'i' THEN '%s'" + " WHEN 'S' THEN '%s'" + " WHEN 's' THEN '%s'" + " WHEN 'f' THEN '%s'" + " END as \"%s\",\n" + " pg_catalog.pg_get_userbyid(c.relowner) as \"%s\"", + gettext_noop("Schema"), + gettext_noop("Name"), + gettext_noop("table"), + gettext_noop("view"), + gettext_noop("materialized view"), + gettext_noop("index"), + gettext_noop("sequence"), + gettext_noop("special"), + gettext_noop("foreign table"), + gettext_noop("Type"), + gettext_noop("Owner")); + + if (showIndexes) + appendPQExpBuffer(&buf, + ",\n c2.relname as \"%s\"", + gettext_noop("Table")); + + if (verbose) + { + /* + * As of PostgreSQL 9.0, use pg_table_size() to show a more acurate + * size of a table, including FSM, VM and TOAST tables. + */ + if (pset.sversion >= 90000) + appendPQExpBuffer(&buf, + ",\n pg_catalog.pg_size_pretty(pg_catalog.pg_table_size(c.oid)) as \"%s\"", + gettext_noop("Size")); + else if (pset.sversion >= 80100) + appendPQExpBuffer(&buf, + ",\n pg_catalog.pg_size_pretty(pg_catalog.pg_relation_size(c.oid)) as \"%s\"", + gettext_noop("Size")); + + appendPQExpBuffer(&buf, + ",\n pg_catalog.obj_description(c.oid, 'pg_class') as \"%s\"", + gettext_noop("Description")); + } + + appendPQExpBufferStr(&buf, + "\nFROM pg_catalog.pg_class c" + "\n LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace"); + if (showIndexes) + appendPQExpBufferStr(&buf, + "\n LEFT JOIN pg_catalog.pg_index i ON i.indexrelid = c.oid" + "\n LEFT JOIN pg_catalog.pg_class c2 ON i.indrelid = c2.oid"); + + appendPQExpBufferStr(&buf, "\nWHERE c.relkind IN ("); + if (showTables) + appendPQExpBufferStr(&buf, "'r',"); + if (showViews) + appendPQExpBufferStr(&buf, "'v',"); + if (showMatViews) + appendPQExpBufferStr(&buf, "'m',"); + if (showIndexes) + appendPQExpBufferStr(&buf, "'i',"); + if (showSeq) + appendPQExpBufferStr(&buf, "'S',"); + if (showSystem || pattern) + appendPQExpBufferStr(&buf, "'s',"); /* was RELKIND_SPECIAL in <= + * 8.1 */ + if (showForeign) + appendPQExpBufferStr(&buf, "'f',"); + + appendPQExpBufferStr(&buf, "''"); /* dummy */ + appendPQExpBufferStr(&buf, ")\n"); + + if (!showSystem && !pattern) + appendPQExpBufferStr(&buf, " AND n.nspname <> 'pg_catalog'\n" + " AND n.nspname <> 'information_schema'\n"); + + /* + * TOAST objects are suppressed unconditionally. Since we don't provide + * any way to select relkind 't' above, we would never show toast tables + * in any case; it seems a bit confusing to allow their indexes to be + * shown. Use plain \d if you really need to look at a TOAST table/index. + */ + appendPQExpBufferStr(&buf, " AND n.nspname !~ '^pg_toast'\n"); + + processSQLNamePattern(pset.db, &buf, pattern, true, false, + "n.nspname", "c.relname", NULL, + "pg_catalog.pg_table_is_visible(c.oid)"); + + appendPQExpBufferStr(&buf, "ORDER BY 1,2;"); + + res = PSQLexec(buf.data); + termPQExpBuffer(&buf); + if (!res) + return false; + + if (PQntuples(res) == 0 && !pset.quiet) + { + if (pattern) + fprintf(pset.queryFout, _("No matching relations found.\n")); + else + fprintf(pset.queryFout, _("No relations found.\n")); + } + else + { + myopt.nullPrint = NULL; + myopt.title = _("List of relations"); + myopt.translate_header = true; + myopt.translate_columns = translate_columns; + myopt.n_translate_columns = lengthof(translate_columns); + + printQuery(res, &myopt, pset.queryFout, false, pset.logfile); + } + + PQclear(res); + return true; +} + + +/* + * \dL + * + * Describes languages. + */ +bool +listLanguages(const char *pattern, bool verbose, bool showSystem) +{ + PQExpBufferData buf; + PGresult *res; + printQueryOpt myopt = pset.popt; + + initPQExpBuffer(&buf); + + printfPQExpBuffer(&buf, + "SELECT l.lanname AS \"%s\",\n", + gettext_noop("Name")); + if (pset.sversion >= 80300) + appendPQExpBuffer(&buf, + " pg_catalog.pg_get_userbyid(l.lanowner) as \"%s\",\n", + gettext_noop("Owner")); + + appendPQExpBuffer(&buf, + " l.lanpltrusted AS \"%s\"", + gettext_noop("Trusted")); + + if (verbose) + { + appendPQExpBuffer(&buf, + ",\n NOT l.lanispl AS \"%s\",\n" + " l.lanplcallfoid::regprocedure AS \"%s\",\n" + " l.lanvalidator::regprocedure AS \"%s\",\n ", + gettext_noop("Internal Language"), + gettext_noop("Call Handler"), + gettext_noop("Validator")); + if (pset.sversion >= 90000) + appendPQExpBuffer(&buf, "l.laninline::regprocedure AS \"%s\",\n ", + gettext_noop("Inline Handler")); + printACLColumn(&buf, "l.lanacl"); + } + + appendPQExpBuffer(&buf, + ",\n d.description AS \"%s\"" + "\nFROM pg_catalog.pg_language l\n" + "LEFT JOIN pg_catalog.pg_description d\n" + " ON d.classoid = l.tableoid AND d.objoid = l.oid\n" + " AND d.objsubid = 0\n", + gettext_noop("Description")); + + if (pattern) + processSQLNamePattern(pset.db, &buf, pattern, false, false, + NULL, "l.lanname", NULL, NULL); + + if (!showSystem && !pattern) + appendPQExpBufferStr(&buf, "WHERE l.lanplcallfoid != 0\n"); + + + appendPQExpBufferStr(&buf, "ORDER BY 1;"); + + res = PSQLexec(buf.data); + termPQExpBuffer(&buf); + if (!res) + return false; + + myopt.nullPrint = NULL; + myopt.title = _("List of languages"); + myopt.translate_header = true; + + printQuery(res, &myopt, pset.queryFout, false, pset.logfile); + + PQclear(res); + return true; +} + + +/* + * \dD + * + * Describes domains. + */ +bool +listDomains(const char *pattern, bool verbose, bool showSystem) +{ + PQExpBufferData buf; + PGresult *res; + printQueryOpt myopt = pset.popt; + + initPQExpBuffer(&buf); + + printfPQExpBuffer(&buf, + "SELECT n.nspname as \"%s\",\n" + " t.typname as \"%s\",\n" + " pg_catalog.format_type(t.typbasetype, t.typtypmod) as \"%s\",\n" + " TRIM(LEADING\n", + gettext_noop("Schema"), + gettext_noop("Name"), + gettext_noop("Type")); + + if (pset.sversion >= 90100) + appendPQExpBufferStr(&buf, + " COALESCE((SELECT ' collate ' || c.collname FROM pg_catalog.pg_collation c, pg_catalog.pg_type bt\n" + " WHERE c.oid = t.typcollation AND bt.oid = t.typbasetype AND t.typcollation <> bt.typcollation), '') ||\n"); + appendPQExpBuffer(&buf, + " CASE WHEN t.typnotnull THEN ' not null' ELSE '' END ||\n" + " CASE WHEN t.typdefault IS NOT NULL THEN ' default ' || t.typdefault ELSE '' END\n" + " ) as \"%s\",\n" + " pg_catalog.array_to_string(ARRAY(\n" + " SELECT pg_catalog.pg_get_constraintdef(r.oid, true) FROM pg_catalog.pg_constraint r WHERE t.oid = r.contypid\n" + " ), ' ') as \"%s\"", + gettext_noop("Modifier"), + gettext_noop("Check")); + + if (verbose) + { + if (pset.sversion >= 90200) + { + appendPQExpBufferStr(&buf, ",\n "); + printACLColumn(&buf, "t.typacl"); + } + appendPQExpBuffer(&buf, + ",\n d.description as \"%s\"", + gettext_noop("Description")); + } + + appendPQExpBufferStr(&buf, + "\nFROM pg_catalog.pg_type t\n" + " LEFT JOIN pg_catalog.pg_namespace n ON n.oid = t.typnamespace\n"); + + if (verbose) + appendPQExpBufferStr(&buf, + " LEFT JOIN pg_catalog.pg_description d " + "ON d.classoid = t.tableoid AND d.objoid = t.oid " + "AND d.objsubid = 0\n"); + + appendPQExpBufferStr(&buf, "WHERE t.typtype = 'd'\n"); + + if (!showSystem && !pattern) + appendPQExpBufferStr(&buf, " AND n.nspname <> 'pg_catalog'\n" + " AND n.nspname <> 'information_schema'\n"); + + processSQLNamePattern(pset.db, &buf, pattern, true, false, + "n.nspname", "t.typname", NULL, + "pg_catalog.pg_type_is_visible(t.oid)"); + + appendPQExpBufferStr(&buf, "ORDER BY 1, 2;"); + + res = PSQLexec(buf.data); + termPQExpBuffer(&buf); + if (!res) + return false; + + myopt.nullPrint = NULL; + myopt.title = _("List of domains"); + myopt.translate_header = true; + + printQuery(res, &myopt, pset.queryFout, false, pset.logfile); + + PQclear(res); + return true; +} + +/* + * \dc + * + * Describes conversions. + */ +bool +listConversions(const char *pattern, bool verbose, bool showSystem) +{ + PQExpBufferData buf; + PGresult *res; + printQueryOpt myopt = pset.popt; + static const bool translate_columns[] = + {false, false, false, false, true, false}; + + initPQExpBuffer(&buf); + + printfPQExpBuffer(&buf, + "SELECT n.nspname AS \"%s\",\n" + " c.conname AS \"%s\",\n" + " pg_catalog.pg_encoding_to_char(c.conforencoding) AS \"%s\",\n" + " pg_catalog.pg_encoding_to_char(c.contoencoding) AS \"%s\",\n" + " CASE WHEN c.condefault THEN '%s'\n" + " ELSE '%s' END AS \"%s\"", + gettext_noop("Schema"), + gettext_noop("Name"), + gettext_noop("Source"), + gettext_noop("Destination"), + gettext_noop("yes"), gettext_noop("no"), + gettext_noop("Default?")); + + if (verbose) + appendPQExpBuffer(&buf, + ",\n d.description AS \"%s\"", + gettext_noop("Description")); + + appendPQExpBufferStr(&buf, + "\nFROM pg_catalog.pg_conversion c\n" + " JOIN pg_catalog.pg_namespace n " + "ON n.oid = c.connamespace\n"); + + if (verbose) + appendPQExpBufferStr(&buf, + "LEFT JOIN pg_catalog.pg_description d " + "ON d.classoid = c.tableoid\n" + " AND d.objoid = c.oid " + "AND d.objsubid = 0\n"); + + appendPQExpBufferStr(&buf, "WHERE true\n"); + + if (!showSystem && !pattern) + appendPQExpBufferStr(&buf, " AND n.nspname <> 'pg_catalog'\n" + " AND n.nspname <> 'information_schema'\n"); + + processSQLNamePattern(pset.db, &buf, pattern, true, false, + "n.nspname", "c.conname", NULL, + "pg_catalog.pg_conversion_is_visible(c.oid)"); + + appendPQExpBufferStr(&buf, "ORDER BY 1, 2;"); + + res = PSQLexec(buf.data); + termPQExpBuffer(&buf); + if (!res) + return false; + + myopt.nullPrint = NULL; + myopt.title = _("List of conversions"); + myopt.translate_header = true; + myopt.translate_columns = translate_columns; + myopt.n_translate_columns = lengthof(translate_columns); + + printQuery(res, &myopt, pset.queryFout, false, pset.logfile); + + PQclear(res); + return true; +} + +/* + * \dy + * + * Describes Event Triggers. + */ +bool +listEventTriggers(const char *pattern, bool verbose) +{ + PQExpBufferData buf; + PGresult *res; + printQueryOpt myopt = pset.popt; + static const bool translate_columns[] = + {false, false, false, true, false, false, false}; + + initPQExpBuffer(&buf); + + printfPQExpBuffer(&buf, + "SELECT evtname as \"%s\", " + "evtevent as \"%s\", " + "pg_catalog.pg_get_userbyid(e.evtowner) as \"%s\",\n" + " case evtenabled when 'O' then '%s'" + " when 'R' then '%s'" + " when 'A' then '%s'" + " when 'D' then '%s' end as \"%s\",\n" + " e.evtfoid::pg_catalog.regproc as \"%s\", " + "pg_catalog.array_to_string(array(select x" + " from pg_catalog.unnest(evttags) as t(x)), ', ') as \"%s\"", + gettext_noop("Name"), + gettext_noop("Event"), + gettext_noop("Owner"), + gettext_noop("enabled"), + gettext_noop("replica"), + gettext_noop("always"), + gettext_noop("disabled"), + gettext_noop("Enabled"), + gettext_noop("Procedure"), + gettext_noop("Tags")); + if (verbose) + appendPQExpBuffer(&buf, + ",\npg_catalog.obj_description(e.oid, 'pg_event_trigger') as \"%s\"", + gettext_noop("Description")); + appendPQExpBufferStr(&buf, + "\nFROM pg_catalog.pg_event_trigger e "); + + processSQLNamePattern(pset.db, &buf, pattern, false, false, + NULL, "evtname", NULL, NULL); + + appendPQExpBufferStr(&buf, "ORDER BY 1"); + + res = PSQLexec(buf.data); + termPQExpBuffer(&buf); + if (!res) + return false; + + myopt.nullPrint = NULL; + myopt.title = _("List of event triggers"); + myopt.translate_header = true; + myopt.translate_columns = translate_columns; + myopt.n_translate_columns = lengthof(translate_columns); + + printQuery(res, &myopt, pset.queryFout, false, pset.logfile); + + PQclear(res); + return true; +} + +/* + * \dC + * + * Describes casts. + */ +bool +listCasts(const char *pattern, bool verbose) +{ + PQExpBufferData buf; + PGresult *res; + printQueryOpt myopt = pset.popt; + static const bool translate_columns[] = {false, false, false, true, false}; + + initPQExpBuffer(&buf); + + /* + * We need a left join to pg_proc for binary casts; the others are just + * paranoia. Also note that we don't attempt to localize '(binary + * coercible)', because there's too much risk of gettext translating a + * function name that happens to match some string in the PO database. + */ + printfPQExpBuffer(&buf, + "SELECT pg_catalog.format_type(castsource, NULL) AS \"%s\",\n" + " pg_catalog.format_type(casttarget, NULL) AS \"%s\",\n" + " CASE WHEN castfunc = 0 THEN '(binary coercible)'\n" + " ELSE p.proname\n" + " END as \"%s\",\n" + " CASE WHEN c.castcontext = 'e' THEN '%s'\n" + " WHEN c.castcontext = 'a' THEN '%s'\n" + " ELSE '%s'\n" + " END as \"%s\"", + gettext_noop("Source type"), + gettext_noop("Target type"), + gettext_noop("Function"), + gettext_noop("no"), + gettext_noop("in assignment"), + gettext_noop("yes"), + gettext_noop("Implicit?")); + + if (verbose) + appendPQExpBuffer(&buf, + ",\n d.description AS \"%s\"\n", + gettext_noop("Description")); + + appendPQExpBufferStr(&buf, + "FROM pg_catalog.pg_cast c LEFT JOIN pg_catalog.pg_proc p\n" + " ON c.castfunc = p.oid\n" + " LEFT JOIN pg_catalog.pg_type ts\n" + " ON c.castsource = ts.oid\n" + " LEFT JOIN pg_catalog.pg_namespace ns\n" + " ON ns.oid = ts.typnamespace\n" + " LEFT JOIN pg_catalog.pg_type tt\n" + " ON c.casttarget = tt.oid\n" + " LEFT JOIN pg_catalog.pg_namespace nt\n" + " ON nt.oid = tt.typnamespace\n"); + + if (verbose) + appendPQExpBufferStr(&buf, + " LEFT JOIN pg_catalog.pg_description d\n" + " ON d.classoid = c.tableoid AND d.objoid = " + "c.oid AND d.objsubid = 0\n"); + + appendPQExpBufferStr(&buf, "WHERE ( (true"); + + /* + * Match name pattern against either internal or external name of either + * castsource or casttarget + */ + processSQLNamePattern(pset.db, &buf, pattern, true, false, + "ns.nspname", "ts.typname", + "pg_catalog.format_type(ts.oid, NULL)", + "pg_catalog.pg_type_is_visible(ts.oid)"); + + appendPQExpBufferStr(&buf, ") OR (true"); + + processSQLNamePattern(pset.db, &buf, pattern, true, false, + "nt.nspname", "tt.typname", + "pg_catalog.format_type(tt.oid, NULL)", + "pg_catalog.pg_type_is_visible(tt.oid)"); + + appendPQExpBufferStr(&buf, ") )\nORDER BY 1, 2;"); + + res = PSQLexec(buf.data); + termPQExpBuffer(&buf); + if (!res) + return false; + + myopt.nullPrint = NULL; + myopt.title = _("List of casts"); + myopt.translate_header = true; + myopt.translate_columns = translate_columns; + myopt.n_translate_columns = lengthof(translate_columns); + + printQuery(res, &myopt, pset.queryFout, false, pset.logfile); + + PQclear(res); + return true; +} + +/* + * \dO + * + * Describes collations. + */ +bool +listCollations(const char *pattern, bool verbose, bool showSystem) +{ + PQExpBufferData buf; + PGresult *res; + printQueryOpt myopt = pset.popt; + static const bool translate_columns[] = {false, false, false, false, false}; + + if (pset.sversion < 90100) + { + psql_error("The server (version %d.%d) does not support collations.\n", + pset.sversion / 10000, (pset.sversion / 100) % 100); + return true; + } + + initPQExpBuffer(&buf); + + printfPQExpBuffer(&buf, + "SELECT n.nspname AS \"%s\",\n" + " c.collname AS \"%s\",\n" + " c.collcollate AS \"%s\",\n" + " c.collctype AS \"%s\"", + gettext_noop("Schema"), + gettext_noop("Name"), + gettext_noop("Collate"), + gettext_noop("Ctype")); + + if (verbose) + appendPQExpBuffer(&buf, + ",\n pg_catalog.obj_description(c.oid, 'pg_collation') AS \"%s\"", + gettext_noop("Description")); + + appendPQExpBufferStr(&buf, + "\nFROM pg_catalog.pg_collation c, pg_catalog.pg_namespace n\n" + "WHERE n.oid = c.collnamespace\n"); + + if (!showSystem && !pattern) + appendPQExpBufferStr(&buf, " AND n.nspname <> 'pg_catalog'\n" + " AND n.nspname <> 'information_schema'\n"); + + /* + * Hide collations that aren't usable in the current database's encoding. + * If you think to change this, note that pg_collation_is_visible rejects + * unusable collations, so you will need to hack name pattern processing + * somehow to avoid inconsistent behavior. + */ + appendPQExpBufferStr(&buf, " AND c.collencoding IN (-1, pg_catalog.pg_char_to_encoding(pg_catalog.getdatabaseencoding()))\n"); + + processSQLNamePattern(pset.db, &buf, pattern, true, false, + "n.nspname", "c.collname", NULL, + "pg_catalog.pg_collation_is_visible(c.oid)"); + + appendPQExpBufferStr(&buf, "ORDER BY 1, 2;"); + + res = PSQLexec(buf.data); + termPQExpBuffer(&buf); + if (!res) + return false; + + myopt.nullPrint = NULL; + myopt.title = _("List of collations"); + myopt.translate_header = true; + myopt.translate_columns = translate_columns; + myopt.n_translate_columns = lengthof(translate_columns); + + printQuery(res, &myopt, pset.queryFout, false, pset.logfile); + + PQclear(res); + return true; +} + +/* + * \dn + * + * Describes schemas (namespaces) + */ +bool +listSchemas(const char *pattern, bool verbose, bool showSystem) +{ + PQExpBufferData buf; + PGresult *res; + printQueryOpt myopt = pset.popt; + + initPQExpBuffer(&buf); + printfPQExpBuffer(&buf, + "SELECT n.nspname AS \"%s\",\n" + " pg_catalog.pg_get_userbyid(n.nspowner) AS \"%s\"", + gettext_noop("Name"), + gettext_noop("Owner")); + + if (verbose) + { + appendPQExpBufferStr(&buf, ",\n "); + printACLColumn(&buf, "n.nspacl"); + appendPQExpBuffer(&buf, + ",\n pg_catalog.obj_description(n.oid, 'pg_namespace') AS \"%s\"", + gettext_noop("Description")); + } + + appendPQExpBuffer(&buf, + "\nFROM pg_catalog.pg_namespace n\n"); + + if (!showSystem && !pattern) + appendPQExpBufferStr(&buf, + "WHERE n.nspname !~ '^pg_' AND n.nspname <> 'information_schema'\n"); + + processSQLNamePattern(pset.db, &buf, pattern, + !showSystem && !pattern, false, + NULL, "n.nspname", NULL, + NULL); + + appendPQExpBufferStr(&buf, "ORDER BY 1;"); + + res = PSQLexec(buf.data); + termPQExpBuffer(&buf); + if (!res) + return false; + + myopt.nullPrint = NULL; + myopt.title = _("List of schemas"); + myopt.translate_header = true; + + printQuery(res, &myopt, pset.queryFout, false, pset.logfile); + + PQclear(res); + return true; +} + + +/* + * \dFp + * list text search parsers + */ +bool +listTSParsers(const char *pattern, bool verbose) +{ + PQExpBufferData buf; + PGresult *res; + printQueryOpt myopt = pset.popt; + + if (pset.sversion < 80300) + { + psql_error("The server (version %d.%d) does not support full text search.\n", + pset.sversion / 10000, (pset.sversion / 100) % 100); + return true; + } + + if (verbose) + return listTSParsersVerbose(pattern); + + initPQExpBuffer(&buf); + + printfPQExpBuffer(&buf, + "SELECT \n" + " n.nspname as \"%s\",\n" + " p.prsname as \"%s\",\n" + " pg_catalog.obj_description(p.oid, 'pg_ts_parser') as \"%s\"\n" + "FROM pg_catalog.pg_ts_parser p \n" + "LEFT JOIN pg_catalog.pg_namespace n ON n.oid = p.prsnamespace\n", + gettext_noop("Schema"), + gettext_noop("Name"), + gettext_noop("Description") + ); + + processSQLNamePattern(pset.db, &buf, pattern, false, false, + "n.nspname", "p.prsname", NULL, + "pg_catalog.pg_ts_parser_is_visible(p.oid)"); + + appendPQExpBufferStr(&buf, "ORDER BY 1, 2;"); + + res = PSQLexec(buf.data); + termPQExpBuffer(&buf); + if (!res) + return false; + + myopt.nullPrint = NULL; + myopt.title = _("List of text search parsers"); + myopt.translate_header = true; + + printQuery(res, &myopt, pset.queryFout, false, pset.logfile); + + PQclear(res); + return true; +} + +/* + * full description of parsers + */ +static bool +listTSParsersVerbose(const char *pattern) +{ + PQExpBufferData buf; + PGresult *res; + int i; + + initPQExpBuffer(&buf); + + printfPQExpBuffer(&buf, + "SELECT p.oid, \n" + " n.nspname, \n" + " p.prsname \n" + "FROM pg_catalog.pg_ts_parser p\n" + "LEFT JOIN pg_catalog.pg_namespace n ON n.oid = p.prsnamespace\n" + ); + + processSQLNamePattern(pset.db, &buf, pattern, false, false, + "n.nspname", "p.prsname", NULL, + "pg_catalog.pg_ts_parser_is_visible(p.oid)"); + + appendPQExpBufferStr(&buf, "ORDER BY 1, 2;"); + + res = PSQLexec(buf.data); + termPQExpBuffer(&buf); + if (!res) + return false; + + if (PQntuples(res) == 0) + { + if (!pset.quiet) + psql_error("Did not find any text search parser named \"%s\".\n", + pattern); + PQclear(res); + return false; + } + + for (i = 0; i < PQntuples(res); i++) + { + const char *oid; + const char *nspname = NULL; + const char *prsname; + + oid = PQgetvalue(res, i, 0); + if (!PQgetisnull(res, i, 1)) + nspname = PQgetvalue(res, i, 1); + prsname = PQgetvalue(res, i, 2); + + if (!describeOneTSParser(oid, nspname, prsname)) + { + PQclear(res); + return false; + } + + if (cancel_pressed) + { + PQclear(res); + return false; + } + } + + PQclear(res); + return true; +} + +static bool +describeOneTSParser(const char *oid, const char *nspname, const char *prsname) +{ + PQExpBufferData buf; + PGresult *res; + char title[1024]; + printQueryOpt myopt = pset.popt; + static const bool translate_columns[] = {true, false, false}; + + initPQExpBuffer(&buf); + + printfPQExpBuffer(&buf, + "SELECT '%s' AS \"%s\", \n" + " p.prsstart::pg_catalog.regproc AS \"%s\", \n" + " pg_catalog.obj_description(p.prsstart, 'pg_proc') as \"%s\" \n" + " FROM pg_catalog.pg_ts_parser p \n" + " WHERE p.oid = '%s' \n" + "UNION ALL \n" + "SELECT '%s', \n" + " p.prstoken::pg_catalog.regproc, \n" + " pg_catalog.obj_description(p.prstoken, 'pg_proc') \n" + " FROM pg_catalog.pg_ts_parser p \n" + " WHERE p.oid = '%s' \n" + "UNION ALL \n" + "SELECT '%s', \n" + " p.prsend::pg_catalog.regproc, \n" + " pg_catalog.obj_description(p.prsend, 'pg_proc') \n" + " FROM pg_catalog.pg_ts_parser p \n" + " WHERE p.oid = '%s' \n" + "UNION ALL \n" + "SELECT '%s', \n" + " p.prsheadline::pg_catalog.regproc, \n" + " pg_catalog.obj_description(p.prsheadline, 'pg_proc') \n" + " FROM pg_catalog.pg_ts_parser p \n" + " WHERE p.oid = '%s' \n" + "UNION ALL \n" + "SELECT '%s', \n" + " p.prslextype::pg_catalog.regproc, \n" + " pg_catalog.obj_description(p.prslextype, 'pg_proc') \n" + " FROM pg_catalog.pg_ts_parser p \n" + " WHERE p.oid = '%s';", + gettext_noop("Start parse"), + gettext_noop("Method"), + gettext_noop("Function"), + gettext_noop("Description"), + oid, + gettext_noop("Get next token"), + oid, + gettext_noop("End parse"), + oid, + gettext_noop("Get headline"), + oid, + gettext_noop("Get token types"), + oid); + + res = PSQLexec(buf.data); + termPQExpBuffer(&buf); + if (!res) + return false; + + myopt.nullPrint = NULL; + if (nspname) + sprintf(title, _("Text search parser \"%s.%s\""), nspname, prsname); + else + sprintf(title, _("Text search parser \"%s\""), prsname); + myopt.title = title; + myopt.footers = NULL; + myopt.topt.default_footer = false; + myopt.translate_header = true; + myopt.translate_columns = translate_columns; + myopt.n_translate_columns = lengthof(translate_columns); + + printQuery(res, &myopt, pset.queryFout, false, pset.logfile); + + PQclear(res); + + initPQExpBuffer(&buf); + + printfPQExpBuffer(&buf, + "SELECT t.alias as \"%s\", \n" + " t.description as \"%s\" \n" + "FROM pg_catalog.ts_token_type( '%s'::pg_catalog.oid ) as t \n" + "ORDER BY 1;", + gettext_noop("Token name"), + gettext_noop("Description"), + oid); + + res = PSQLexec(buf.data); + termPQExpBuffer(&buf); + if (!res) + return false; + + myopt.nullPrint = NULL; + if (nspname) + sprintf(title, _("Token types for parser \"%s.%s\""), nspname, prsname); + else + sprintf(title, _("Token types for parser \"%s\""), prsname); + myopt.title = title; + myopt.footers = NULL; + myopt.topt.default_footer = true; + myopt.translate_header = true; + myopt.translate_columns = NULL; + myopt.n_translate_columns = 0; + + printQuery(res, &myopt, pset.queryFout, false, pset.logfile); + + PQclear(res); + return true; +} + + +/* + * \dFd + * list text search dictionaries + */ +bool +listTSDictionaries(const char *pattern, bool verbose) +{ + PQExpBufferData buf; + PGresult *res; + printQueryOpt myopt = pset.popt; + + if (pset.sversion < 80300) + { + psql_error("The server (version %d.%d) does not support full text search.\n", + pset.sversion / 10000, (pset.sversion / 100) % 100); + return true; + } + + initPQExpBuffer(&buf); + + printfPQExpBuffer(&buf, + "SELECT \n" + " n.nspname as \"%s\",\n" + " d.dictname as \"%s\",\n", + gettext_noop("Schema"), + gettext_noop("Name")); + + if (verbose) + { + appendPQExpBuffer(&buf, + " ( SELECT COALESCE(nt.nspname, '(null)')::pg_catalog.text || '.' || t.tmplname FROM \n" + " pg_catalog.pg_ts_template t \n" + " LEFT JOIN pg_catalog.pg_namespace nt ON nt.oid = t.tmplnamespace \n" + " WHERE d.dicttemplate = t.oid ) AS \"%s\", \n" + " d.dictinitoption as \"%s\", \n", + gettext_noop("Template"), + gettext_noop("Init options")); + } + + appendPQExpBuffer(&buf, + " pg_catalog.obj_description(d.oid, 'pg_ts_dict') as \"%s\"\n", + gettext_noop("Description")); + + appendPQExpBufferStr(&buf, "FROM pg_catalog.pg_ts_dict d\n" + "LEFT JOIN pg_catalog.pg_namespace n ON n.oid = d.dictnamespace\n"); + + processSQLNamePattern(pset.db, &buf, pattern, false, false, + "n.nspname", "d.dictname", NULL, + "pg_catalog.pg_ts_dict_is_visible(d.oid)"); + + appendPQExpBufferStr(&buf, "ORDER BY 1, 2;"); + + res = PSQLexec(buf.data); + termPQExpBuffer(&buf); + if (!res) + return false; + + myopt.nullPrint = NULL; + myopt.title = _("List of text search dictionaries"); + myopt.translate_header = true; + + printQuery(res, &myopt, pset.queryFout, false, pset.logfile); + + PQclear(res); + return true; +} + + +/* + * \dFt + * list text search templates + */ +bool +listTSTemplates(const char *pattern, bool verbose) +{ + PQExpBufferData buf; + PGresult *res; + printQueryOpt myopt = pset.popt; + + if (pset.sversion < 80300) + { + psql_error("The server (version %d.%d) does not support full text search.\n", + pset.sversion / 10000, (pset.sversion / 100) % 100); + return true; + } + + initPQExpBuffer(&buf); + + if (verbose) + printfPQExpBuffer(&buf, + "SELECT \n" + " n.nspname AS \"%s\",\n" + " t.tmplname AS \"%s\",\n" + " t.tmplinit::pg_catalog.regproc AS \"%s\",\n" + " t.tmpllexize::pg_catalog.regproc AS \"%s\",\n" + " pg_catalog.obj_description(t.oid, 'pg_ts_template') AS \"%s\"\n", + gettext_noop("Schema"), + gettext_noop("Name"), + gettext_noop("Init"), + gettext_noop("Lexize"), + gettext_noop("Description")); + else + printfPQExpBuffer(&buf, + "SELECT \n" + " n.nspname AS \"%s\",\n" + " t.tmplname AS \"%s\",\n" + " pg_catalog.obj_description(t.oid, 'pg_ts_template') AS \"%s\"\n", + gettext_noop("Schema"), + gettext_noop("Name"), + gettext_noop("Description")); + + appendPQExpBufferStr(&buf, "FROM pg_catalog.pg_ts_template t\n" + "LEFT JOIN pg_catalog.pg_namespace n ON n.oid = t.tmplnamespace\n"); + + processSQLNamePattern(pset.db, &buf, pattern, false, false, + "n.nspname", "t.tmplname", NULL, + "pg_catalog.pg_ts_template_is_visible(t.oid)"); + + appendPQExpBufferStr(&buf, "ORDER BY 1, 2;"); + + res = PSQLexec(buf.data); + termPQExpBuffer(&buf); + if (!res) + return false; + + myopt.nullPrint = NULL; + myopt.title = _("List of text search templates"); + myopt.translate_header = true; + + printQuery(res, &myopt, pset.queryFout, false, pset.logfile); + + PQclear(res); + return true; +} + + +/* + * \dF + * list text search configurations + */ +bool +listTSConfigs(const char *pattern, bool verbose) +{ + PQExpBufferData buf; + PGresult *res; + printQueryOpt myopt = pset.popt; + + if (pset.sversion < 80300) + { + psql_error("The server (version %d.%d) does not support full text search.\n", + pset.sversion / 10000, (pset.sversion / 100) % 100); + return true; + } + + if (verbose) + return listTSConfigsVerbose(pattern); + + initPQExpBuffer(&buf); + + printfPQExpBuffer(&buf, + "SELECT \n" + " n.nspname as \"%s\",\n" + " c.cfgname as \"%s\",\n" + " pg_catalog.obj_description(c.oid, 'pg_ts_config') as \"%s\"\n" + "FROM pg_catalog.pg_ts_config c\n" + "LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.cfgnamespace \n", + gettext_noop("Schema"), + gettext_noop("Name"), + gettext_noop("Description") + ); + + processSQLNamePattern(pset.db, &buf, pattern, false, false, + "n.nspname", "c.cfgname", NULL, + "pg_catalog.pg_ts_config_is_visible(c.oid)"); + + appendPQExpBufferStr(&buf, "ORDER BY 1, 2;"); + + res = PSQLexec(buf.data); + termPQExpBuffer(&buf); + if (!res) + return false; + + myopt.nullPrint = NULL; + myopt.title = _("List of text search configurations"); + myopt.translate_header = true; + + printQuery(res, &myopt, pset.queryFout, false, pset.logfile); + + PQclear(res); + return true; +} + +static bool +listTSConfigsVerbose(const char *pattern) +{ + PQExpBufferData buf; + PGresult *res; + int i; + + initPQExpBuffer(&buf); + + printfPQExpBuffer(&buf, + "SELECT c.oid, c.cfgname,\n" + " n.nspname, \n" + " p.prsname, \n" + " np.nspname as pnspname \n" + "FROM pg_catalog.pg_ts_config c \n" + " LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.cfgnamespace, \n" + " pg_catalog.pg_ts_parser p \n" + " LEFT JOIN pg_catalog.pg_namespace np ON np.oid = p.prsnamespace \n" + "WHERE p.oid = c.cfgparser\n" + ); + + processSQLNamePattern(pset.db, &buf, pattern, true, false, + "n.nspname", "c.cfgname", NULL, + "pg_catalog.pg_ts_config_is_visible(c.oid)"); + + appendPQExpBufferStr(&buf, "ORDER BY 3, 2;"); + + res = PSQLexec(buf.data); + termPQExpBuffer(&buf); + if (!res) + return false; + + if (PQntuples(res) == 0) + { + if (!pset.quiet) + psql_error("Did not find any text search configuration named \"%s\".\n", + pattern); + PQclear(res); + return false; + } + + for (i = 0; i < PQntuples(res); i++) + { + const char *oid; + const char *cfgname; + const char *nspname = NULL; + const char *prsname; + const char *pnspname = NULL; + + oid = PQgetvalue(res, i, 0); + cfgname = PQgetvalue(res, i, 1); + if (!PQgetisnull(res, i, 2)) + nspname = PQgetvalue(res, i, 2); + prsname = PQgetvalue(res, i, 3); + if (!PQgetisnull(res, i, 4)) + pnspname = PQgetvalue(res, i, 4); + + if (!describeOneTSConfig(oid, nspname, cfgname, pnspname, prsname)) + { + PQclear(res); + return false; + } + + if (cancel_pressed) + { + PQclear(res); + return false; + } + } + + PQclear(res); + return true; +} + +static bool +describeOneTSConfig(const char *oid, const char *nspname, const char *cfgname, + const char *pnspname, const char *prsname) +{ + PQExpBufferData buf, + title; + PGresult *res; + printQueryOpt myopt = pset.popt; + + initPQExpBuffer(&buf); + + printfPQExpBuffer(&buf, + "SELECT \n" + " ( SELECT t.alias FROM \n" + " pg_catalog.ts_token_type(c.cfgparser) AS t \n" + " WHERE t.tokid = m.maptokentype ) AS \"%s\", \n" + " pg_catalog.btrim( \n" + " ARRAY( SELECT mm.mapdict::pg_catalog.regdictionary \n" + " FROM pg_catalog.pg_ts_config_map AS mm \n" + " WHERE mm.mapcfg = m.mapcfg AND mm.maptokentype = m.maptokentype \n" + " ORDER BY mapcfg, maptokentype, mapseqno \n" + " ) :: pg_catalog.text , \n" + " '{}') AS \"%s\" \n" + "FROM pg_catalog.pg_ts_config AS c, pg_catalog.pg_ts_config_map AS m \n" + "WHERE c.oid = '%s' AND m.mapcfg = c.oid \n" + "GROUP BY m.mapcfg, m.maptokentype, c.cfgparser \n" + "ORDER BY 1;", + gettext_noop("Token"), + gettext_noop("Dictionaries"), + oid); + + res = PSQLexec(buf.data); + termPQExpBuffer(&buf); + if (!res) + return false; + + initPQExpBuffer(&title); + + if (nspname) + appendPQExpBuffer(&title, _("Text search configuration \"%s.%s\""), + nspname, cfgname); + else + appendPQExpBuffer(&title, _("Text search configuration \"%s\""), + cfgname); + + if (pnspname) + appendPQExpBuffer(&title, _("\nParser: \"%s.%s\""), + pnspname, prsname); + else + appendPQExpBuffer(&title, _("\nParser: \"%s\""), + prsname); + + myopt.nullPrint = NULL; + myopt.title = title.data; + myopt.footers = NULL; + myopt.topt.default_footer = false; + myopt.translate_header = true; + + printQuery(res, &myopt, pset.queryFout, false, pset.logfile); + + termPQExpBuffer(&title); + + PQclear(res); + return true; +} + + +/* + * \dew + * + * Describes foreign-data wrappers + */ +bool +listForeignDataWrappers(const char *pattern, bool verbose) +{ + PQExpBufferData buf; + PGresult *res; + printQueryOpt myopt = pset.popt; + + if (pset.sversion < 80400) + { + psql_error("The server (version %d.%d) does not support foreign-data wrappers.\n", + pset.sversion / 10000, (pset.sversion / 100) % 100); + return true; + } + + initPQExpBuffer(&buf); + printfPQExpBuffer(&buf, + "SELECT fdw.fdwname AS \"%s\",\n" + " pg_catalog.pg_get_userbyid(fdw.fdwowner) AS \"%s\",\n", + gettext_noop("Name"), + gettext_noop("Owner")); + if (pset.sversion >= 90100) + appendPQExpBuffer(&buf, + " fdw.fdwhandler::pg_catalog.regproc AS \"%s\",\n", + gettext_noop("Handler")); + appendPQExpBuffer(&buf, + " fdw.fdwvalidator::pg_catalog.regproc AS \"%s\"", + gettext_noop("Validator")); + + if (verbose) + { + appendPQExpBufferStr(&buf, ",\n "); + printACLColumn(&buf, "fdwacl"); + appendPQExpBuffer(&buf, + ",\n CASE WHEN fdwoptions IS NULL THEN '' ELSE " + " '(' || array_to_string(ARRAY(SELECT " + " quote_ident(option_name) || ' ' || " + " quote_literal(option_value) FROM " + " pg_options_to_table(fdwoptions)), ', ') || ')' " + " END AS \"%s\"", + gettext_noop("FDW Options")); + + if (pset.sversion >= 90100) + appendPQExpBuffer(&buf, + ",\n d.description AS \"%s\" ", + gettext_noop("Description")); + } + + appendPQExpBufferStr(&buf, "\nFROM pg_catalog.pg_foreign_data_wrapper fdw\n"); + + if (verbose && pset.sversion >= 90100) + appendPQExpBufferStr(&buf, + "LEFT JOIN pg_catalog.pg_description d\n" + " ON d.classoid = fdw.tableoid " + "AND d.objoid = fdw.oid AND d.objsubid = 0\n"); + + processSQLNamePattern(pset.db, &buf, pattern, false, false, + NULL, "fdwname", NULL, NULL); + + appendPQExpBufferStr(&buf, "ORDER BY 1;"); + + res = PSQLexec(buf.data); + termPQExpBuffer(&buf); + if (!res) + return false; + + myopt.nullPrint = NULL; + myopt.title = _("List of foreign-data wrappers"); + myopt.translate_header = true; + + printQuery(res, &myopt, pset.queryFout, false, pset.logfile); + + PQclear(res); + return true; +} + +/* + * \des + * + * Describes foreign servers. + */ +bool +listForeignServers(const char *pattern, bool verbose) +{ + PQExpBufferData buf; + PGresult *res; + printQueryOpt myopt = pset.popt; + + if (pset.sversion < 80400) + { + psql_error("The server (version %d.%d) does not support foreign servers.\n", + pset.sversion / 10000, (pset.sversion / 100) % 100); + return true; + } + + initPQExpBuffer(&buf); + printfPQExpBuffer(&buf, + "SELECT s.srvname AS \"%s\",\n" + " pg_catalog.pg_get_userbyid(s.srvowner) AS \"%s\",\n" + " f.fdwname AS \"%s\"", + gettext_noop("Name"), + gettext_noop("Owner"), + gettext_noop("Foreign-data wrapper")); + + if (verbose) + { + appendPQExpBufferStr(&buf, ",\n "); + printACLColumn(&buf, "s.srvacl"); + appendPQExpBuffer(&buf, + ",\n" + " s.srvtype AS \"%s\",\n" + " s.srvversion AS \"%s\",\n" + " CASE WHEN srvoptions IS NULL THEN '' ELSE " + " '(' || array_to_string(ARRAY(SELECT " + " quote_ident(option_name) || ' ' || " + " quote_literal(option_value) FROM " + " pg_options_to_table(srvoptions)), ', ') || ')' " + " END AS \"%s\",\n" + " d.description AS \"%s\"", + gettext_noop("Type"), + gettext_noop("Version"), + gettext_noop("FDW Options"), + gettext_noop("Description")); + } + + appendPQExpBufferStr(&buf, + "\nFROM pg_catalog.pg_foreign_server s\n" + " JOIN pg_catalog.pg_foreign_data_wrapper f ON f.oid=s.srvfdw\n"); + + if (verbose) + appendPQExpBufferStr(&buf, + "LEFT JOIN pg_description d\n " + "ON d.classoid = s.tableoid AND d.objoid = s.oid " + "AND d.objsubid = 0\n"); + + processSQLNamePattern(pset.db, &buf, pattern, false, false, + NULL, "s.srvname", NULL, NULL); + + appendPQExpBufferStr(&buf, "ORDER BY 1;"); + + res = PSQLexec(buf.data); + termPQExpBuffer(&buf); + if (!res) + return false; + + myopt.nullPrint = NULL; + myopt.title = _("List of foreign servers"); + myopt.translate_header = true; + + printQuery(res, &myopt, pset.queryFout, false, pset.logfile); + + PQclear(res); + return true; +} + +/* + * \deu + * + * Describes user mappings. + */ +bool +listUserMappings(const char *pattern, bool verbose) +{ + PQExpBufferData buf; + PGresult *res; + printQueryOpt myopt = pset.popt; + + if (pset.sversion < 80400) + { + psql_error("The server (version %d.%d) does not support user mappings.\n", + pset.sversion / 10000, (pset.sversion / 100) % 100); + return true; + } + + initPQExpBuffer(&buf); + printfPQExpBuffer(&buf, + "SELECT um.srvname AS \"%s\",\n" + " um.usename AS \"%s\"", + gettext_noop("Server"), + gettext_noop("User name")); + + if (verbose) + appendPQExpBuffer(&buf, + ",\n CASE WHEN umoptions IS NULL THEN '' ELSE " + " '(' || array_to_string(ARRAY(SELECT " + " quote_ident(option_name) || ' ' || " + " quote_literal(option_value) FROM " + " pg_options_to_table(umoptions)), ', ') || ')' " + " END AS \"%s\"", + gettext_noop("FDW Options")); + + appendPQExpBufferStr(&buf, "\nFROM pg_catalog.pg_user_mappings um\n"); + + processSQLNamePattern(pset.db, &buf, pattern, false, false, + NULL, "um.srvname", "um.usename", NULL); + + appendPQExpBufferStr(&buf, "ORDER BY 1, 2;"); + + res = PSQLexec(buf.data); + termPQExpBuffer(&buf); + if (!res) + return false; + + myopt.nullPrint = NULL; + myopt.title = _("List of user mappings"); + myopt.translate_header = true; + + printQuery(res, &myopt, pset.queryFout, false, pset.logfile); + + PQclear(res); + return true; +} + +/* + * \det + * + * Describes foreign tables. + */ +bool +listForeignTables(const char *pattern, bool verbose) +{ + PQExpBufferData buf; + PGresult *res; + printQueryOpt myopt = pset.popt; + + if (pset.sversion < 90100) + { + psql_error("The server (version %d.%d) does not support foreign tables.\n", + pset.sversion / 10000, (pset.sversion / 100) % 100); + return true; + } + + initPQExpBuffer(&buf); + printfPQExpBuffer(&buf, + "SELECT n.nspname AS \"%s\",\n" + " c.relname AS \"%s\",\n" + " s.srvname AS \"%s\"", + gettext_noop("Schema"), + gettext_noop("Table"), + gettext_noop("Server")); + + if (verbose) + appendPQExpBuffer(&buf, + ",\n CASE WHEN ftoptions IS NULL THEN '' ELSE " + " '(' || array_to_string(ARRAY(SELECT " + " quote_ident(option_name) || ' ' || " + " quote_literal(option_value) FROM " + " pg_options_to_table(ftoptions)), ', ') || ')' " + " END AS \"%s\",\n" + " d.description AS \"%s\"", + gettext_noop("FDW Options"), + gettext_noop("Description")); + + appendPQExpBufferStr(&buf, + "\nFROM pg_catalog.pg_foreign_table ft\n" + " INNER JOIN pg_catalog.pg_class c" + " ON c.oid = ft.ftrelid\n" + " INNER JOIN pg_catalog.pg_namespace n" + " ON n.oid = c.relnamespace\n" + " INNER JOIN pg_catalog.pg_foreign_server s" + " ON s.oid = ft.ftserver\n"); + if (verbose) + appendPQExpBufferStr(&buf, + " LEFT JOIN pg_catalog.pg_description d\n" + " ON d.classoid = c.tableoid AND " + "d.objoid = c.oid AND d.objsubid = 0\n"); + + processSQLNamePattern(pset.db, &buf, pattern, false, false, + NULL, "n.nspname", "c.relname", NULL); + + appendPQExpBufferStr(&buf, "ORDER BY 1, 2;"); + + res = PSQLexec(buf.data); + termPQExpBuffer(&buf); + if (!res) + return false; + + myopt.nullPrint = NULL; + myopt.title = _("List of foreign tables"); + myopt.translate_header = true; + + printQuery(res, &myopt, pset.queryFout, false, pset.logfile); + + PQclear(res); + return true; +} + +/* + * \dx + * + * Briefly describes installed extensions. + */ +bool +listExtensions(const char *pattern) +{ + PQExpBufferData buf; + PGresult *res; + printQueryOpt myopt = pset.popt; + + if (pset.sversion < 90100) + { + psql_error("The server (version %d.%d) does not support extensions.\n", + pset.sversion / 10000, (pset.sversion / 100) % 100); + return true; + } + + initPQExpBuffer(&buf); + printfPQExpBuffer(&buf, + "SELECT e.extname AS \"%s\", " + "e.extversion AS \"%s\", n.nspname AS \"%s\", c.description AS \"%s\"\n" + "FROM pg_catalog.pg_extension e " + "LEFT JOIN pg_catalog.pg_namespace n ON n.oid = e.extnamespace " + "LEFT JOIN pg_catalog.pg_description c ON c.objoid = e.oid " + "AND c.classoid = 'pg_catalog.pg_extension'::pg_catalog.regclass\n", + gettext_noop("Name"), + gettext_noop("Version"), + gettext_noop("Schema"), + gettext_noop("Description")); + + processSQLNamePattern(pset.db, &buf, pattern, + false, false, + NULL, "e.extname", NULL, + NULL); + + appendPQExpBufferStr(&buf, "ORDER BY 1;"); + + res = PSQLexec(buf.data); + termPQExpBuffer(&buf); + if (!res) + return false; + + myopt.nullPrint = NULL; + myopt.title = _("List of installed extensions"); + myopt.translate_header = true; + + printQuery(res, &myopt, pset.queryFout, false, pset.logfile); + + PQclear(res); + return true; +} + +/* + * \dx+ + * + * List contents of installed extensions. + */ +bool +listExtensionContents(const char *pattern) +{ + PQExpBufferData buf; + PGresult *res; + int i; + + if (pset.sversion < 90100) + { + psql_error("The server (version %d.%d) does not support extensions.\n", + pset.sversion / 10000, (pset.sversion / 100) % 100); + return true; + } + + initPQExpBuffer(&buf); + printfPQExpBuffer(&buf, + "SELECT e.extname, e.oid\n" + "FROM pg_catalog.pg_extension e\n"); + + processSQLNamePattern(pset.db, &buf, pattern, + false, false, + NULL, "e.extname", NULL, + NULL); + + appendPQExpBufferStr(&buf, "ORDER BY 1;"); + + res = PSQLexec(buf.data); + termPQExpBuffer(&buf); + if (!res) + return false; + + if (PQntuples(res) == 0) + { + if (!pset.quiet) + { + if (pattern) + psql_error("Did not find any extension named \"%s\".\n", + pattern); + else + psql_error("Did not find any extensions.\n"); + } + PQclear(res); + return false; + } + + for (i = 0; i < PQntuples(res); i++) + { + const char *extname; + const char *oid; + + extname = PQgetvalue(res, i, 0); + oid = PQgetvalue(res, i, 1); + + if (!listOneExtensionContents(extname, oid)) + { + PQclear(res); + return false; + } + if (cancel_pressed) + { + PQclear(res); + return false; + } + } + + PQclear(res); + return true; +} + +static bool +listOneExtensionContents(const char *extname, const char *oid) +{ + PQExpBufferData buf; + PGresult *res; + char title[1024]; + printQueryOpt myopt = pset.popt; + + initPQExpBuffer(&buf); + printfPQExpBuffer(&buf, + "SELECT pg_catalog.pg_describe_object(classid, objid, 0) AS \"%s\"\n" + "FROM pg_catalog.pg_depend\n" + "WHERE refclassid = 'pg_catalog.pg_extension'::pg_catalog.regclass AND refobjid = '%s' AND deptype = 'e'\n" + "ORDER BY 1;", + gettext_noop("Object Description"), + oid); + + res = PSQLexec(buf.data); + termPQExpBuffer(&buf); + if (!res) + return false; + + myopt.nullPrint = NULL; + snprintf(title, sizeof(title), _("Objects in extension \"%s\""), extname); + myopt.title = title; + myopt.translate_header = true; + + printQuery(res, &myopt, pset.queryFout, false, pset.logfile); + + PQclear(res); + return true; +} + +/* + * printACLColumn + * + * Helper function for consistently formatting ACL (privilege) columns. + * The proper targetlist entry is appended to buf. Note lack of any + * whitespace or comma decoration. + */ +static void +printACLColumn(PQExpBuffer buf, const char *colname) +{ + if (pset.sversion >= 80100) + appendPQExpBuffer(buf, + "pg_catalog.array_to_string(%s, E'\\n') AS \"%s\"", + colname, gettext_noop("Access privileges")); + else + appendPQExpBuffer(buf, + "pg_catalog.array_to_string(%s, '\\n') AS \"%s\"", + colname, gettext_noop("Access privileges")); +} diff --git a/src/bin/csql/describe.h b/src/bin/csql/describe.h new file mode 100644 index 000000000..822e71ae4 --- /dev/null +++ b/src/bin/csql/describe.h @@ -0,0 +1,102 @@ +/* + * psql - the PostgreSQL interactive terminal + * + * Copyright (c) 2000-2015, PostgreSQL Global Development Group + * + * src/bin/psql/describe.h + */ +#ifndef DESCRIBE_H +#define DESCRIBE_H + + +/* \da */ +extern bool describeAggregates(const char *pattern, bool verbose, bool showSystem); + +/* \db */ +extern bool describeTablespaces(const char *pattern, bool verbose); + +/* \df, \dfa, \dfn, \dft, \dfw, etc. */ +extern bool describeFunctions(const char *functypes, const char *pattern, bool verbose, bool showSystem); + +/* \dT */ +extern bool describeTypes(const char *pattern, bool verbose, bool showSystem); + +/* \do */ +extern bool describeOperators(const char *pattern, bool verbose, bool showSystem); + +/* \du, \dg */ +extern bool describeRoles(const char *pattern, bool verbose); + +/* \drds */ +extern bool listDbRoleSettings(const char *pattern1, const char *pattern2); + +/* \z (or \dp) */ +extern bool permissionsList(const char *pattern); + +/* \ddp */ +extern bool listDefaultACLs(const char *pattern); + +/* \dd */ +extern bool objectDescription(const char *pattern, bool showSystem); + +/* \d foo */ +extern bool describeTableDetails(const char *pattern, bool verbose, bool showSystem); + +/* \dF */ +extern bool listTSConfigs(const char *pattern, bool verbose); + +/* \dFp */ +extern bool listTSParsers(const char *pattern, bool verbose); + +/* \dFd */ +extern bool listTSDictionaries(const char *pattern, bool verbose); + +/* \dFt */ +extern bool listTSTemplates(const char *pattern, bool verbose); + +/* \l */ +extern bool listAllDbs(const char *pattern, bool verbose); + +/* \dt, \di, \ds, \dS, etc. */ +extern bool listTables(const char *tabtypes, const char *pattern, bool verbose, bool showSystem); + +/* \dD */ +extern bool listDomains(const char *pattern, bool verbose, bool showSystem); + +/* \dc */ +extern bool listConversions(const char *pattern, bool verbose, bool showSystem); + +/* \dC */ +extern bool listCasts(const char *pattern, bool verbose); + +/* \dO */ +extern bool listCollations(const char *pattern, bool verbose, bool showSystem); + +/* \dn */ +extern bool listSchemas(const char *pattern, bool verbose, bool showSystem); + +/* \dew */ +extern bool listForeignDataWrappers(const char *pattern, bool verbose); + +/* \des */ +extern bool listForeignServers(const char *pattern, bool verbose); + +/* \deu */ +extern bool listUserMappings(const char *pattern, bool verbose); + +/* \det */ +extern bool listForeignTables(const char *pattern, bool verbose); + +/* \dL */ +extern bool listLanguages(const char *pattern, bool verbose, bool showSystem); + +/* \dx */ +extern bool listExtensions(const char *pattern); + +/* \dx+ */ +extern bool listExtensionContents(const char *pattern); + +/* \dy */ +extern bool listEventTriggers(const char *pattern, bool verbose); + +#endif /* DESCRIBE_H */ diff --git a/src/bin/csql/dumputils.c b/src/bin/csql/dumputils.c new file mode 100644 index 000000000..d7506e119 --- /dev/null +++ b/src/bin/csql/dumputils.c @@ -0,0 +1,1243 @@ +/*------------------------------------------------------------------------- + * + * Utility routines for SQL dumping + * Basically this is stuff that is useful in both pg_dump and pg_dumpall. + * Lately it's also being used by psql and bin/scripts/ ... + * + * + * Portions Copyright (c) 1996-2015, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * src/bin/pg_dump/dumputils.c + * + *------------------------------------------------------------------------- + */ +#include "postgres_fe.h" + +#include + +#include "dumputils.h" + +#include "parser/keywords.h" + + +/* Globals from keywords.c */ +extern const ScanKeyword FEScanKeywords[]; +extern const int NumFEScanKeywords; + +#define supports_grant_options(version) ((version) >= 70400) + +static bool parseAclItem(const char *item, const char *type, + const char *name, const char *subname, int remoteVersion, + PQExpBuffer grantee, PQExpBuffer grantor, + PQExpBuffer privs, PQExpBuffer privswgo); +static char *copyAclUserName(PQExpBuffer output, char *input); +static void AddAcl(PQExpBuffer aclbuf, const char *keyword, + const char *subname); +static PQExpBuffer defaultGetLocalPQExpBuffer(void); + +/* Globals exported by this file */ +int quote_all_identifiers = 0; +PQExpBuffer (*getLocalPQExpBuffer) (void) = defaultGetLocalPQExpBuffer; + +/* + * Returns a temporary PQExpBuffer, valid until the next call to the function. + * This is used by fmtId and fmtQualifiedId. + * + * Non-reentrant and non-thread-safe but reduces memory leakage. You can + * replace this with a custom version by setting the getLocalPQExpBuffer + * function pointer. + */ +static PQExpBuffer +defaultGetLocalPQExpBuffer(void) +{ + static PQExpBuffer id_return = NULL; + + if (id_return) /* first time through? */ + { + /* same buffer, just wipe contents */ + resetPQExpBuffer(id_return); + } + else + { + /* new buffer */ + id_return = createPQExpBuffer(); + } + + return id_return; +} + +/* + * Quotes input string if it's not a legitimate SQL identifier as-is. + * + * Note that the returned string must be used before calling fmtId again, + * since we re-use the same return buffer each time. + */ +const char * +fmtId(const char *rawid) +{ + PQExpBuffer id_return = getLocalPQExpBuffer(); + + const char *cp; + bool need_quotes = false; + + /* + * These checks need to match the identifier production in scan.l. Don't + * use islower() etc. + */ + if (quote_all_identifiers) + need_quotes = true; + /* slightly different rules for first character */ + else if (!((rawid[0] >= 'a' && rawid[0] <= 'z') || rawid[0] == '_')) + need_quotes = true; + else + { + /* otherwise check the entire string */ + for (cp = rawid; *cp; cp++) + { + if (!((*cp >= 'a' && *cp <= 'z') + || (*cp >= '0' && *cp <= '9') + || (*cp == '_'))) + { + need_quotes = true; + break; + } + } + } + + if (!need_quotes) + { + /* + * Check for keyword. We quote keywords except for unreserved ones. + * (In some cases we could avoid quoting a col_name or type_func_name + * keyword, but it seems much harder than it's worth to tell that.) + * + * Note: ScanKeywordLookup() does case-insensitive comparison, but + * that's fine, since we already know we have all-lower-case. + */ + const ScanKeyword *keyword = ScanKeywordLookup(rawid, + FEScanKeywords, + NumFEScanKeywords); + + if (keyword != NULL && keyword->category != UNRESERVED_KEYWORD) + need_quotes = true; + } + + if (!need_quotes) + { + /* no quoting needed */ + appendPQExpBufferStr(id_return, rawid); + } + else + { + appendPQExpBufferChar(id_return, '\"'); + for (cp = rawid; *cp; cp++) + { + /* + * Did we find a double-quote in the string? Then make this a + * double double-quote per SQL99. Before, we put in a + * backslash/double-quote pair. - thomas 2000-08-05 + */ + if (*cp == '\"') + appendPQExpBufferChar(id_return, '\"'); + appendPQExpBufferChar(id_return, *cp); + } + appendPQExpBufferChar(id_return, '\"'); + } + + return id_return->data; +} + +/* + * fmtQualifiedId - convert a qualified name to the proper format for + * the source database. + * + * Like fmtId, use the result before calling again. + * + * Since we call fmtId and it also uses getThreadLocalPQExpBuffer() we cannot + * use it until we're finished with calling fmtId(). + */ +const char * +fmtQualifiedId(int remoteVersion, const char *schema, const char *id) +{ + PQExpBuffer id_return; + PQExpBuffer lcl_pqexp = createPQExpBuffer(); + + /* Suppress schema name if fetching from pre-7.3 DB */ + if (remoteVersion >= 70300 && schema && *schema) + { + appendPQExpBuffer(lcl_pqexp, "%s.", fmtId(schema)); + } + appendPQExpBufferStr(lcl_pqexp, fmtId(id)); + + id_return = getLocalPQExpBuffer(); + + appendPQExpBufferStr(id_return, lcl_pqexp->data); + destroyPQExpBuffer(lcl_pqexp); + + return id_return->data; +} + +/* + * Convert a string value to an SQL string literal and append it to + * the given buffer. We assume the specified client_encoding and + * standard_conforming_strings settings. + * + * This is essentially equivalent to libpq's PQescapeStringInternal, + * except for the output buffer structure. We need it in situations + * where we do not have a PGconn available. Where we do, + * appendStringLiteralConn is a better choice. + */ +void +appendStringLiteral(PQExpBuffer buf, const char *str, + int encoding, bool std_strings) +{ + size_t length = strlen(str); + const char *source = str; + char *target; + + if (!enlargePQExpBuffer(buf, 2 * length + 2)) + return; + + target = buf->data + buf->len; + *target++ = '\''; + + while (*source != '\0') + { + char c = *source; + int len; + int i; + + /* Fast path for plain ASCII */ + if (!IS_HIGHBIT_SET(c)) + { + /* Apply quoting if needed */ + if (SQL_STR_DOUBLE(c, !std_strings)) + *target++ = c; + /* Copy the character */ + *target++ = c; + source++; + continue; + } + + /* Slow path for possible multibyte characters */ + len = PQmblen(source, encoding); + + /* Copy the character */ + for (i = 0; i < len; i++) + { + if (*source == '\0') + break; + *target++ = *source++; + } + + /* + * If we hit premature end of string (ie, incomplete multibyte + * character), try to pad out to the correct length with spaces. We + * may not be able to pad completely, but we will always be able to + * insert at least one pad space (since we'd not have quoted a + * multibyte character). This should be enough to make a string that + * the server will error out on. + */ + if (i < len) + { + char *stop = buf->data + buf->maxlen - 2; + + for (; i < len; i++) + { + if (target >= stop) + break; + *target++ = ' '; + } + break; + } + } + + /* Write the terminating quote and NUL character. */ + *target++ = '\''; + *target = '\0'; + + buf->len = target - buf->data; +} + + +/* + * Convert a string value to an SQL string literal and append it to + * the given buffer. Encoding and string syntax rules are as indicated + * by current settings of the PGconn. + */ +void +appendStringLiteralConn(PQExpBuffer buf, const char *str, PGconn *conn) +{ + size_t length = strlen(str); + + /* + * XXX This is a kluge to silence escape_string_warning in our utility + * programs. It should go away someday. + */ + if (strchr(str, '\\') != NULL && PQserverVersion(conn) >= 80100) + { + /* ensure we are not adjacent to an identifier */ + if (buf->len > 0 && buf->data[buf->len - 1] != ' ') + appendPQExpBufferChar(buf, ' '); + appendPQExpBufferChar(buf, ESCAPE_STRING_SYNTAX); + appendStringLiteral(buf, str, PQclientEncoding(conn), false); + return; + } + /* XXX end kluge */ + + if (!enlargePQExpBuffer(buf, 2 * length + 2)) + return; + appendPQExpBufferChar(buf, '\''); + buf->len += PQescapeStringConn(conn, buf->data + buf->len, + str, length, NULL); + appendPQExpBufferChar(buf, '\''); +} + + +/* + * Convert a string value to a dollar quoted literal and append it to + * the given buffer. If the dqprefix parameter is not NULL then the + * dollar quote delimiter will begin with that (after the opening $). + * + * No escaping is done at all on str, in compliance with the rules + * for parsing dollar quoted strings. Also, we need not worry about + * encoding issues. + */ +void +appendStringLiteralDQ(PQExpBuffer buf, const char *str, const char *dqprefix) +{ + static const char suffixes[] = "_XXXXXXX"; + int nextchar = 0; + PQExpBuffer delimBuf = createPQExpBuffer(); + + /* start with $ + dqprefix if not NULL */ + appendPQExpBufferChar(delimBuf, '$'); + if (dqprefix) + appendPQExpBufferStr(delimBuf, dqprefix); + + /* + * Make sure we choose a delimiter which (without the trailing $) is not + * present in the string being quoted. We don't check with the trailing $ + * because a string ending in $foo must not be quoted with $foo$. + */ + while (strstr(str, delimBuf->data) != NULL) + { + appendPQExpBufferChar(delimBuf, suffixes[nextchar++]); + nextchar %= sizeof(suffixes) - 1; + } + + /* add trailing $ */ + appendPQExpBufferChar(delimBuf, '$'); + + /* quote it and we are all done */ + appendPQExpBufferStr(buf, delimBuf->data); + appendPQExpBufferStr(buf, str); + appendPQExpBufferStr(buf, delimBuf->data); + + destroyPQExpBuffer(delimBuf); +} + + +/* + * Convert a bytea value (presented as raw bytes) to an SQL string literal + * and append it to the given buffer. We assume the specified + * standard_conforming_strings setting. + * + * This is needed in situations where we do not have a PGconn available. + * Where we do, PQescapeByteaConn is a better choice. + */ +void +appendByteaLiteral(PQExpBuffer buf, const unsigned char *str, size_t length, + bool std_strings) +{ + const unsigned char *source = str; + char *target; + + static const char hextbl[] = "0123456789abcdef"; + + /* + * This implementation is hard-wired to produce hex-format output. We do + * not know the server version the output will be loaded into, so making + * an intelligent format choice is impossible. It might be better to + * always use the old escaped format. + */ + if (!enlargePQExpBuffer(buf, 2 * length + 5)) + return; + + target = buf->data + buf->len; + *target++ = '\''; + if (!std_strings) + *target++ = '\\'; + *target++ = '\\'; + *target++ = 'x'; + + while (length-- > 0) + { + unsigned char c = *source++; + + *target++ = hextbl[(c >> 4) & 0xF]; + *target++ = hextbl[c & 0xF]; + } + + /* Write the terminating quote and NUL character. */ + *target++ = '\''; + *target = '\0'; + + buf->len = target - buf->data; +} + + +/* + * Deconstruct the text representation of a 1-dimensional Postgres array + * into individual items. + * + * On success, returns true and sets *itemarray and *nitems to describe + * an array of individual strings. On parse failure, returns false; + * *itemarray may exist or be NULL. + * + * NOTE: free'ing itemarray is sufficient to deallocate the working storage. + */ +bool +parsePGArray(const char *atext, char ***itemarray, int *nitems) +{ + int inputlen; + char **items; + char *strings; + int curitem; + + /* + * We expect input in the form of "{item,item,item}" where any item is + * either raw data, or surrounded by double quotes (in which case embedded + * characters including backslashes and quotes are backslashed). + * + * We build the result as an array of pointers followed by the actual + * string data, all in one malloc block for convenience of deallocation. + * The worst-case storage need is not more than one pointer and one + * character for each input character (consider "{,,,,,,,,,,}"). + */ + *itemarray = NULL; + *nitems = 0; + inputlen = strlen(atext); + if (inputlen < 2 || atext[0] != '{' || atext[inputlen - 1] != '}') + return false; /* bad input */ + items = (char **) malloc(inputlen * (sizeof(char *) + sizeof(char))); + if (items == NULL) + return false; /* out of memory */ + *itemarray = items; + strings = (char *) (items + inputlen); + + atext++; /* advance over initial '{' */ + curitem = 0; + while (*atext != '}') + { + if (*atext == '\0') + return false; /* premature end of string */ + items[curitem] = strings; + while (*atext != '}' && *atext != ',') + { + if (*atext == '\0') + return false; /* premature end of string */ + if (*atext != '"') + *strings++ = *atext++; /* copy unquoted data */ + else + { + /* process quoted substring */ + atext++; + while (*atext != '"') + { + if (*atext == '\0') + return false; /* premature end of string */ + if (*atext == '\\') + { + atext++; + if (*atext == '\0') + return false; /* premature end of string */ + } + *strings++ = *atext++; /* copy quoted data */ + } + atext++; + } + } + *strings++ = '\0'; + if (*atext == ',') + atext++; + curitem++; + } + if (atext[1] != '\0') + return false; /* bogus syntax (embedded '}') */ + *nitems = curitem; + return true; +} + + +/* + * Build GRANT/REVOKE command(s) for an object. + * + * name: the object name, in the form to use in the commands (already quoted) + * subname: the sub-object name, if any (already quoted); NULL if none + * type: the object type (as seen in GRANT command: must be one of + * TABLE, SEQUENCE, FUNCTION, LANGUAGE, SCHEMA, DATABASE, TABLESPACE, + * FOREIGN DATA WRAPPER, SERVER, or LARGE OBJECT) + * acls: the ACL string fetched from the database + * owner: username of object owner (will be passed through fmtId); can be + * NULL or empty string to indicate "no owner known" + * prefix: string to prefix to each generated command; typically empty + * remoteVersion: version of database + * + * Returns TRUE if okay, FALSE if could not parse the acl string. + * The resulting commands (if any) are appended to the contents of 'sql'. + * + * Note: when processing a default ACL, prefix is "ALTER DEFAULT PRIVILEGES " + * or something similar, and name is an empty string. + * + * Note: beware of passing a fmtId() result directly as 'name' or 'subname', + * since this routine uses fmtId() internally. + */ +bool +buildACLCommands(const char *name, const char *subname, + const char *type, const char *acls, const char *owner, + const char *prefix, int remoteVersion, + PQExpBuffer sql) +{ + bool ok = true; + char **aclitems; + int naclitems; + int i; + PQExpBuffer grantee, + grantor, + privs, + privswgo; + PQExpBuffer firstsql, + secondsql; + bool found_owner_privs = false; + + if (strlen(acls) == 0) + return true; /* object has default permissions */ + + /* treat empty-string owner same as NULL */ + if (owner && *owner == '\0') + owner = NULL; + + if (!parsePGArray(acls, &aclitems, &naclitems)) + { + if (aclitems) + free(aclitems); + return false; + } + + grantee = createPQExpBuffer(); + grantor = createPQExpBuffer(); + privs = createPQExpBuffer(); + privswgo = createPQExpBuffer(); + + /* + * At the end, these two will be pasted together to form the result. But + * the owner privileges need to go before the other ones to keep the + * dependencies valid. In recent versions this is normally the case, but + * in old versions they come after the PUBLIC privileges and that results + * in problems if we need to run REVOKE on the owner privileges. + */ + firstsql = createPQExpBuffer(); + secondsql = createPQExpBuffer(); + + /* + * Always start with REVOKE ALL FROM PUBLIC, so that we don't have to + * wire-in knowledge about the default public privileges for different + * kinds of objects. + */ + appendPQExpBuffer(firstsql, "%sREVOKE ALL", prefix); + if (subname) + appendPQExpBuffer(firstsql, "(%s)", subname); + appendPQExpBuffer(firstsql, " ON %s %s FROM PUBLIC;\n", type, name); + + /* + * We still need some hacking though to cover the case where new default + * public privileges are added in new versions: the REVOKE ALL will revoke + * them, leading to behavior different from what the old version had, + * which is generally not what's wanted. So add back default privs if the + * source database is too old to have had that particular priv. + */ + if (remoteVersion < 80200 && strcmp(type, "DATABASE") == 0) + { + /* database CONNECT priv didn't exist before 8.2 */ + appendPQExpBuffer(firstsql, "%sGRANT CONNECT ON %s %s TO PUBLIC;\n", + prefix, type, name); + } + + /* Scan individual ACL items */ + for (i = 0; i < naclitems; i++) + { + if (!parseAclItem(aclitems[i], type, name, subname, remoteVersion, + grantee, grantor, privs, privswgo)) + { + ok = false; + break; + } + + if (grantor->len == 0 && owner) + printfPQExpBuffer(grantor, "%s", owner); + + if (privs->len > 0 || privswgo->len > 0) + { + if (owner + && strcmp(grantee->data, owner) == 0 + && strcmp(grantor->data, owner) == 0) + { + found_owner_privs = true; + + /* + * For the owner, the default privilege level is ALL WITH + * GRANT OPTION (only ALL prior to 7.4). + */ + if (supports_grant_options(remoteVersion) + ? strcmp(privswgo->data, "ALL") != 0 + : strcmp(privs->data, "ALL") != 0) + { + appendPQExpBuffer(firstsql, "%sREVOKE ALL", prefix); + if (subname) + appendPQExpBuffer(firstsql, "(%s)", subname); + appendPQExpBuffer(firstsql, " ON %s %s FROM %s;\n", + type, name, fmtId(grantee->data)); + if (privs->len > 0) + appendPQExpBuffer(firstsql, + "%sGRANT %s ON %s %s TO %s;\n", + prefix, privs->data, type, name, + fmtId(grantee->data)); + if (privswgo->len > 0) + appendPQExpBuffer(firstsql, + "%sGRANT %s ON %s %s TO %s WITH GRANT OPTION;\n", + prefix, privswgo->data, type, name, + fmtId(grantee->data)); + } + } + else + { + /* + * Otherwise can assume we are starting from no privs. + */ + if (grantor->len > 0 + && (!owner || strcmp(owner, grantor->data) != 0)) + appendPQExpBuffer(secondsql, "SET SESSION AUTHORIZATION %s;\n", + fmtId(grantor->data)); + + if (privs->len > 0) + { + appendPQExpBuffer(secondsql, "%sGRANT %s ON %s %s TO ", + prefix, privs->data, type, name); + if (grantee->len == 0) + appendPQExpBufferStr(secondsql, "PUBLIC;\n"); + else if (strncmp(grantee->data, "group ", + strlen("group ")) == 0) + appendPQExpBuffer(secondsql, "GROUP %s;\n", + fmtId(grantee->data + strlen("group "))); + else + appendPQExpBuffer(secondsql, "%s;\n", fmtId(grantee->data)); + } + if (privswgo->len > 0) + { + appendPQExpBuffer(secondsql, "%sGRANT %s ON %s %s TO ", + prefix, privswgo->data, type, name); + if (grantee->len == 0) + appendPQExpBufferStr(secondsql, "PUBLIC"); + else if (strncmp(grantee->data, "group ", + strlen("group ")) == 0) + appendPQExpBuffer(secondsql, "GROUP %s", + fmtId(grantee->data + strlen("group "))); + else + appendPQExpBufferStr(secondsql, fmtId(grantee->data)); + appendPQExpBufferStr(secondsql, " WITH GRANT OPTION;\n"); + } + + if (grantor->len > 0 + && (!owner || strcmp(owner, grantor->data) != 0)) + appendPQExpBufferStr(secondsql, "RESET SESSION AUTHORIZATION;\n"); + } + } + } + + /* + * If we didn't find any owner privs, the owner must have revoked 'em all + */ + if (!found_owner_privs && owner) + { + appendPQExpBuffer(firstsql, "%sREVOKE ALL", prefix); + if (subname) + appendPQExpBuffer(firstsql, "(%s)", subname); + appendPQExpBuffer(firstsql, " ON %s %s FROM %s;\n", + type, name, fmtId(owner)); + } + + destroyPQExpBuffer(grantee); + destroyPQExpBuffer(grantor); + destroyPQExpBuffer(privs); + destroyPQExpBuffer(privswgo); + + appendPQExpBuffer(sql, "%s%s", firstsql->data, secondsql->data); + destroyPQExpBuffer(firstsql); + destroyPQExpBuffer(secondsql); + + free(aclitems); + + return ok; +} + +/* + * Build ALTER DEFAULT PRIVILEGES command(s) for single pg_default_acl entry. + * + * type: the object type (TABLES, FUNCTIONS, etc) + * nspname: schema name, or NULL for global default privileges + * acls: the ACL string fetched from the database + * owner: username of privileges owner (will be passed through fmtId) + * remoteVersion: version of database + * + * Returns TRUE if okay, FALSE if could not parse the acl string. + * The resulting commands (if any) are appended to the contents of 'sql'. + */ +bool +buildDefaultACLCommands(const char *type, const char *nspname, + const char *acls, const char *owner, + int remoteVersion, + PQExpBuffer sql) +{ + bool result; + PQExpBuffer prefix; + + prefix = createPQExpBuffer(); + + /* + * We incorporate the target role directly into the command, rather than + * playing around with SET ROLE or anything like that. This is so that a + * permissions error leads to nothing happening, rather than changing + * default privileges for the wrong user. + */ + appendPQExpBuffer(prefix, "ALTER DEFAULT PRIVILEGES FOR ROLE %s ", + fmtId(owner)); + if (nspname) + appendPQExpBuffer(prefix, "IN SCHEMA %s ", fmtId(nspname)); + + result = buildACLCommands("", NULL, + type, acls, owner, + prefix->data, remoteVersion, + sql); + + destroyPQExpBuffer(prefix); + + return result; +} + +/* + * This will parse an aclitem string, having the general form + * username=privilegecodes/grantor + * or + * group groupname=privilegecodes/grantor + * (the /grantor part will not be present if pre-7.4 database). + * + * The returned grantee string will be the dequoted username or groupname + * (preceded with "group " in the latter case). The returned grantor is + * the dequoted grantor name or empty. Privilege characters are decoded + * and split between privileges with grant option (privswgo) and without + * (privs). + * + * Note: for cross-version compatibility, it's important to use ALL when + * appropriate. + */ +static bool +parseAclItem(const char *item, const char *type, + const char *name, const char *subname, int remoteVersion, + PQExpBuffer grantee, PQExpBuffer grantor, + PQExpBuffer privs, PQExpBuffer privswgo) +{ + char *buf; + bool all_with_go = true; + bool all_without_go = true; + char *eqpos; + char *slpos; + char *pos; + + buf = strdup(item); + if (!buf) + return false; + + /* user or group name is string up to = */ + eqpos = copyAclUserName(grantee, buf); + if (*eqpos != '=') + { + free(buf); + return false; + } + + /* grantor may be listed after / */ + slpos = strchr(eqpos + 1, '/'); + if (slpos) + { + *slpos++ = '\0'; + slpos = copyAclUserName(grantor, slpos); + if (*slpos != '\0') + { + free(buf); + return false; + } + } + else + resetPQExpBuffer(grantor); + + /* privilege codes */ +#define CONVERT_PRIV(code, keywd) \ +do { \ + if ((pos = strchr(eqpos + 1, code))) \ + { \ + if (*(pos + 1) == '*') \ + { \ + AddAcl(privswgo, keywd, subname); \ + all_without_go = false; \ + } \ + else \ + { \ + AddAcl(privs, keywd, subname); \ + all_with_go = false; \ + } \ + } \ + else \ + all_with_go = all_without_go = false; \ +} while (0) + + resetPQExpBuffer(privs); + resetPQExpBuffer(privswgo); + + if (strcmp(type, "TABLE") == 0 || strcmp(type, "SEQUENCE") == 0 || + strcmp(type, "TABLES") == 0 || strcmp(type, "SEQUENCES") == 0) + { + CONVERT_PRIV('r', "SELECT"); + + if (strcmp(type, "SEQUENCE") == 0 || + strcmp(type, "SEQUENCES") == 0) + /* sequence only */ + CONVERT_PRIV('U', "USAGE"); + else + { + /* table only */ + CONVERT_PRIV('a', "INSERT"); + if (remoteVersion >= 70200) + CONVERT_PRIV('x', "REFERENCES"); + /* rest are not applicable to columns */ + if (subname == NULL) + { + if (remoteVersion >= 70200) + { + CONVERT_PRIV('d', "DELETE"); + CONVERT_PRIV('t', "TRIGGER"); + } + if (remoteVersion >= 80400) + CONVERT_PRIV('D', "TRUNCATE"); + } + } + + /* UPDATE */ + if (remoteVersion >= 70200 || + strcmp(type, "SEQUENCE") == 0 || + strcmp(type, "SEQUENCES") == 0) + CONVERT_PRIV('w', "UPDATE"); + else + /* 7.0 and 7.1 have a simpler worldview */ + CONVERT_PRIV('w', "UPDATE,DELETE"); + } + else if (strcmp(type, "FUNCTION") == 0 || + strcmp(type, "FUNCTIONS") == 0) + CONVERT_PRIV('X', "EXECUTE"); + else if (strcmp(type, "LANGUAGE") == 0) + CONVERT_PRIV('U', "USAGE"); + else if (strcmp(type, "SCHEMA") == 0) + { + CONVERT_PRIV('C', "CREATE"); + CONVERT_PRIV('U', "USAGE"); + } + else if (strcmp(type, "DATABASE") == 0) + { + CONVERT_PRIV('C', "CREATE"); + CONVERT_PRIV('c', "CONNECT"); + CONVERT_PRIV('T', "TEMPORARY"); + } + else if (strcmp(type, "TABLESPACE") == 0) + CONVERT_PRIV('C', "CREATE"); + else if (strcmp(type, "TYPE") == 0 || + strcmp(type, "TYPES") == 0) + CONVERT_PRIV('U', "USAGE"); + else if (strcmp(type, "FOREIGN DATA WRAPPER") == 0) + CONVERT_PRIV('U', "USAGE"); + else if (strcmp(type, "FOREIGN SERVER") == 0) + CONVERT_PRIV('U', "USAGE"); + else if (strcmp(type, "FOREIGN TABLE") == 0) + CONVERT_PRIV('r', "SELECT"); + else if (strcmp(type, "LARGE OBJECT") == 0) + { + CONVERT_PRIV('r', "SELECT"); + CONVERT_PRIV('w', "UPDATE"); + } + else + abort(); + +#undef CONVERT_PRIV + + if (all_with_go) + { + resetPQExpBuffer(privs); + printfPQExpBuffer(privswgo, "ALL"); + if (subname) + appendPQExpBuffer(privswgo, "(%s)", subname); + } + else if (all_without_go) + { + resetPQExpBuffer(privswgo); + printfPQExpBuffer(privs, "ALL"); + if (subname) + appendPQExpBuffer(privs, "(%s)", subname); + } + + free(buf); + + return true; +} + +/* + * Transfer a user or group name starting at *input into the output buffer, + * dequoting if needed. Returns a pointer to just past the input name. + * The name is taken to end at an unquoted '=' or end of string. + */ +static char * +copyAclUserName(PQExpBuffer output, char *input) +{ + resetPQExpBuffer(output); + + while (*input && *input != '=') + { + /* + * If user name isn't quoted, then just add it to the output buffer + */ + if (*input != '"') + appendPQExpBufferChar(output, *input++); + else + { + /* Otherwise, it's a quoted username */ + input++; + /* Loop until we come across an unescaped quote */ + while (!(*input == '"' && *(input + 1) != '"')) + { + if (*input == '\0') + return input; /* really a syntax error... */ + + /* + * Quoting convention is to escape " as "". Keep this code in + * sync with putid() in backend's acl.c. + */ + if (*input == '"' && *(input + 1) == '"') + input++; + appendPQExpBufferChar(output, *input++); + } + input++; + } + } + return input; +} + +/* + * Append a privilege keyword to a keyword list, inserting comma if needed. + */ +static void +AddAcl(PQExpBuffer aclbuf, const char *keyword, const char *subname) +{ + if (aclbuf->len > 0) + appendPQExpBufferChar(aclbuf, ','); + appendPQExpBufferStr(aclbuf, keyword); + if (subname) + appendPQExpBuffer(aclbuf, "(%s)", subname); +} + + +/* + * processSQLNamePattern + * + * Scan a wildcard-pattern string and generate appropriate WHERE clauses + * to limit the set of objects returned. The WHERE clauses are appended + * to the already-partially-constructed query in buf. Returns whether + * any clause was added. + * + * conn: connection query will be sent to (consulted for escaping rules). + * buf: output parameter. + * pattern: user-specified pattern option, or NULL if none ("*" is implied). + * have_where: true if caller already emitted "WHERE" (clauses will be ANDed + * onto the existing WHERE clause). + * force_escape: always quote regexp special characters, even outside + * double quotes (else they are quoted only between double quotes). + * schemavar: name of query variable to match against a schema-name pattern. + * Can be NULL if no schema. + * namevar: name of query variable to match against an object-name pattern. + * altnamevar: NULL, or name of an alternative variable to match against name. + * visibilityrule: clause to use if we want to restrict to visible objects + * (for example, "pg_catalog.pg_table_is_visible(p.oid)"). Can be NULL. + * + * Formatting note: the text already present in buf should end with a newline. + * The appended text, if any, will end with one too. + */ +bool +processSQLNamePattern(PGconn *conn, PQExpBuffer buf, const char *pattern, + bool have_where, bool force_escape, + const char *schemavar, const char *namevar, + const char *altnamevar, const char *visibilityrule) +{ + PQExpBufferData schemabuf; + PQExpBufferData namebuf; + int encoding = PQclientEncoding(conn); + bool inquotes; + const char *cp; + int i; + bool added_clause = false; + +#define WHEREAND() \ + (appendPQExpBufferStr(buf, have_where ? " AND " : "WHERE "), \ + have_where = true, added_clause = true) + + if (pattern == NULL) + { + /* Default: select all visible objects */ + if (visibilityrule) + { + WHEREAND(); + appendPQExpBuffer(buf, "%s\n", visibilityrule); + } + return added_clause; + } + + initPQExpBuffer(&schemabuf); + initPQExpBuffer(&namebuf); + + /* + * Parse the pattern, converting quotes and lower-casing unquoted letters. + * Also, adjust shell-style wildcard characters into regexp notation. + * + * We surround the pattern with "^(...)$" to force it to match the whole + * string, as per SQL practice. We have to have parens in case the string + * contains "|", else the "^" and "$" will be bound into the first and + * last alternatives which is not what we want. + * + * Note: the result of this pass is the actual regexp pattern(s) we want + * to execute. Quoting/escaping into SQL literal format will be done + * below using appendStringLiteralConn(). + */ + appendPQExpBufferStr(&namebuf, "^("); + + inquotes = false; + cp = pattern; + + while (*cp) + { + char ch = *cp; + + if (ch == '"') + { + if (inquotes && cp[1] == '"') + { + /* emit one quote, stay in inquotes mode */ + appendPQExpBufferChar(&namebuf, '"'); + cp++; + } + else + inquotes = !inquotes; + cp++; + } + else if (!inquotes && isupper((unsigned char) ch)) + { + appendPQExpBufferChar(&namebuf, + pg_tolower((unsigned char) ch)); + cp++; + } + else if (!inquotes && ch == '*') + { + appendPQExpBufferStr(&namebuf, ".*"); + cp++; + } + else if (!inquotes && ch == '?') + { + appendPQExpBufferChar(&namebuf, '.'); + cp++; + } + else if (!inquotes && ch == '.') + { + /* Found schema/name separator, move current pattern to schema */ + resetPQExpBuffer(&schemabuf); + appendPQExpBufferStr(&schemabuf, namebuf.data); + resetPQExpBuffer(&namebuf); + appendPQExpBufferStr(&namebuf, "^("); + cp++; + } + else if (ch == '$') + { + /* + * Dollar is always quoted, whether inside quotes or not. The + * reason is that it's allowed in SQL identifiers, so there's a + * significant use-case for treating it literally, while because + * we anchor the pattern automatically there is no use-case for + * having it possess its regexp meaning. + */ + appendPQExpBufferStr(&namebuf, "\\$"); + cp++; + } + else + { + /* + * Ordinary data character, transfer to pattern + * + * Inside double quotes, or at all times if force_escape is true, + * quote regexp special characters with a backslash to avoid + * regexp errors. Outside quotes, however, let them pass through + * as-is; this lets knowledgeable users build regexp expressions + * that are more powerful than shell-style patterns. + */ + if ((inquotes || force_escape) && + strchr("|*+?()[]{}.^$\\", ch)) + appendPQExpBufferChar(&namebuf, '\\'); + i = PQmblen(cp, encoding); + while (i-- && *cp) + { + appendPQExpBufferChar(&namebuf, *cp); + cp++; + } + } + } + + /* + * Now decide what we need to emit. Note there will be a leading "^(" in + * the patterns in any case. + */ + if (namebuf.len > 2) + { + /* We have a name pattern, so constrain the namevar(s) */ + + appendPQExpBufferStr(&namebuf, ")$"); + /* Optimize away a "*" pattern */ + if (strcmp(namebuf.data, "^(.*)$") != 0) + { + WHEREAND(); + if (altnamevar) + { + appendPQExpBuffer(buf, "(%s ~ ", namevar); + appendStringLiteralConn(buf, namebuf.data, conn); + appendPQExpBuffer(buf, "\n OR %s ~ ", altnamevar); + appendStringLiteralConn(buf, namebuf.data, conn); + appendPQExpBufferStr(buf, ")\n"); + } + else + { + appendPQExpBuffer(buf, "%s ~ ", namevar); + appendStringLiteralConn(buf, namebuf.data, conn); + appendPQExpBufferChar(buf, '\n'); + } + } + } + + if (schemabuf.len > 2) + { + /* We have a schema pattern, so constrain the schemavar */ + + appendPQExpBufferStr(&schemabuf, ")$"); + /* Optimize away a "*" pattern */ + if (strcmp(schemabuf.data, "^(.*)$") != 0 && schemavar) + { + WHEREAND(); + appendPQExpBuffer(buf, "%s ~ ", schemavar); + appendStringLiteralConn(buf, schemabuf.data, conn); + appendPQExpBufferChar(buf, '\n'); + } + } + else + { + /* No schema pattern given, so select only visible objects */ + if (visibilityrule) + { + WHEREAND(); + appendPQExpBuffer(buf, "%s\n", visibilityrule); + } + } + + termPQExpBuffer(&schemabuf); + termPQExpBuffer(&namebuf); + + return added_clause; +#undef WHEREAND +} + +/* + * buildShSecLabelQuery + * + * Build a query to retrieve security labels for a shared object. + */ +void +buildShSecLabelQuery(PGconn *conn, const char *catalog_name, uint32 objectId, + PQExpBuffer sql) +{ + appendPQExpBuffer(sql, + "SELECT provider, label FROM pg_catalog.pg_shseclabel " + "WHERE classoid = '%s'::pg_catalog.regclass AND " + "objoid = %u", catalog_name, objectId); +} + +/* + * emitShSecLabels + * + * Format security label data retrieved by the query generated in + * buildShSecLabelQuery. + */ +void +emitShSecLabels(PGconn *conn, PGresult *res, PQExpBuffer buffer, + const char *target, const char *objname) +{ + int i; + + for (i = 0; i < PQntuples(res); i++) + { + char *provider = PQgetvalue(res, i, 0); + char *label = PQgetvalue(res, i, 1); + + /* must use fmtId result before calling it again */ + appendPQExpBuffer(buffer, + "SECURITY LABEL FOR %s ON %s", + fmtId(provider), target); + appendPQExpBuffer(buffer, + " %s IS ", + fmtId(objname)); + appendStringLiteralConn(buffer, label, conn); + appendPQExpBufferStr(buffer, ";\n"); + } +} + + +void +simple_string_list_append(SimpleStringList *list, const char *val) +{ + SimpleStringListCell *cell; + + cell = (SimpleStringListCell *) + pg_malloc(offsetof(SimpleStringListCell, val) +strlen(val) + 1); + + cell->next = NULL; + strcpy(cell->val, val); + + if (list->tail) + list->tail->next = cell; + else + list->head = cell; + list->tail = cell; +} + +bool +simple_string_list_member(SimpleStringList *list, const char *val) +{ + SimpleStringListCell *cell; + + for (cell = list->head; cell; cell = cell->next) + { + if (strcmp(cell->val, val) == 0) + return true; + } + return false; +} diff --git a/src/bin/csql/help.c b/src/bin/csql/help.c new file mode 100644 index 000000000..10304564e --- /dev/null +++ b/src/bin/csql/help.c @@ -0,0 +1,572 @@ +/* + * psql - the PostgreSQL interactive terminal + * + * Copyright (c) 2000-2015, PostgreSQL Global Development Group + * + * src/bin/psql/help.c + */ +#include "postgres_fe.h" + +#ifndef WIN32 +#include /* (ditto) */ +#include /* for geteuid() */ +#else +#include +#endif + +#ifndef WIN32 +#include /* for ioctl() */ +#endif + +#ifdef HAVE_TERMIOS_H +#include +#endif + +#include "common.h" +#include "common/username.h" +#include "help.h" +#include "input.h" +#include "settings.h" +#include "sql_help.h" + + +/* + * PLEASE: + * If you change something in this file, also make the same changes + * in the DocBook documentation, file ref/psql-ref.sgml. If you don't + * know how to do it, please find someone who can help you. + */ + + +/* + * usage + * + * print out command line arguments + */ +#define ON(var) (var ? _("on") : _("off")) + +void +usage(unsigned short int pager) +{ + const char *env; + const char *user; + char *errstr; + FILE *output; + + /* Find default user, in case we need it. */ + user = getenv("PGUSER"); + if (!user) + { + user = get_user_name(&errstr); + if (!user) + { + psql_error("%s\n", errstr); + exit(EXIT_FAILURE); + } + } + + output = PageOutput(59, pager ? &(pset.popt.topt) : NULL); + + printf(_("csql is the CitusDB interactive terminal.\n\n")); + fprintf(output, _("Usage:\n")); + printf(_(" csql [OPTION]... [DBNAME [USERNAME]]\n\n")); + + fprintf(output, _("General options:\n")); + /* Display default database */ + env = getenv("PGDATABASE"); + if (!env) + env = user; + fprintf(output, _(" -c, --command=COMMAND run only single command (SQL or internal) and exit\n")); + fprintf(output, _(" -d, --dbname=DBNAME database name to connect to (default: \"%s\")\n"), env); + fprintf(output, _(" -f, --file=FILENAME execute commands from file, then exit\n")); + fprintf(output, _(" -l, --list list available databases, then exit\n")); + fprintf(output, _(" -v, --set=, --variable=NAME=VALUE\n" + " set psql variable NAME to VALUE\n" + " (e.g., -v ON_ERROR_STOP=1)\n")); + fprintf(output, _(" -V, --version output version information, then exit\n")); + fprintf(output, _(" -X, --no-psqlrc do not read startup file (~/.psqlrc)\n")); + fprintf(output, _(" -1 (\"one\"), --single-transaction\n" + " execute as a single transaction (if non-interactive)\n")); + fprintf(output, _(" -?, --help[=options] show this help, then exit\n")); + fprintf(output, _(" --help=commands list backslash commands, then exit\n")); + fprintf(output, _(" --help=variables list special variables, then exit\n")); + + fprintf(output, _("\nInput and output options:\n")); + fprintf(output, _(" -a, --echo-all echo all input from script\n")); + fprintf(output, _(" -b, --echo-errors echo failed commands\n")); + fprintf(output, _(" -e, --echo-queries echo commands sent to server\n")); + fprintf(output, _(" -E, --echo-hidden display queries that internal commands generate\n")); + fprintf(output, _(" -L, --log-file=FILENAME send session log to file\n")); + fprintf(output, _(" -n, --no-readline disable enhanced command line editing (readline)\n")); + fprintf(output, _(" -o, --output=FILENAME send query results to file (or |pipe)\n")); + fprintf(output, _(" -q, --quiet run quietly (no messages, only query output)\n")); + fprintf(output, _(" -s, --single-step single-step mode (confirm each query)\n")); + fprintf(output, _(" -S, --single-line single-line mode (end of line terminates SQL command)\n")); + + fprintf(output, _("\nOutput format options:\n")); + fprintf(output, _(" -A, --no-align unaligned table output mode\n")); + fprintf(output, _(" -F, --field-separator=STRING\n" + " field separator for unaligned output (default: \"%s\")\n"), + DEFAULT_FIELD_SEP); + fprintf(output, _(" -H, --html HTML table output mode\n")); + fprintf(output, _(" -P, --pset=VAR[=ARG] set printing option VAR to ARG (see \\pset command)\n")); + fprintf(output, _(" -R, --record-separator=STRING\n" + " record separator for unaligned output (default: newline)\n")); + fprintf(output, _(" -t, --tuples-only print rows only\n")); + fprintf(output, _(" -T, --table-attr=TEXT set HTML table tag attributes (e.g., width, border)\n")); + fprintf(output, _(" -x, --expanded turn on expanded table output\n")); + fprintf(output, _(" -z, --field-separator-zero\n" + " set field separator for unaligned output to zero byte\n")); + fprintf(output, _(" -0, --record-separator-zero\n" + " set record separator for unaligned output to zero byte\n")); + + fprintf(output, _("\nConnection options:\n")); + /* Display default host */ + env = getenv("PGHOST"); + fprintf(output, _(" -h, --host=HOSTNAME database server host or socket directory (default: \"%s\")\n"), + env ? env : _("local socket")); + /* Display default port */ + env = getenv("PGPORT"); + fprintf(output, _(" -p, --port=PORT database server port (default: \"%s\")\n"), + env ? env : DEF_PGPORT_STR); + /* Display default user */ + env = getenv("PGUSER"); + if (!env) + env = user; + fprintf(output, _(" -U, --username=USERNAME database user name (default: \"%s\")\n"), env); + fprintf(output, _(" -w, --no-password never prompt for password\n")); + fprintf(output, _(" -W, --password force password prompt (should happen automatically)\n")); + + fprintf(output, _("\nFor more information, type \"\\?\" (for internal commands) or \"\\help\" (for SQL\n" + "commands) from within psql, or consult the psql section in the PostgreSQL\n" + "documentation.\n\n")); + fprintf(output, _("Report bugs to .\n")); + + ClosePager(output); +} + + +/* + * slashUsage + * + * print out help for the backslash commands + */ +void +slashUsage(unsigned short int pager) +{ + FILE *output; + char *currdb; + + currdb = PQdb(pset.db); + + output = PageOutput(103, pager ? &(pset.popt.topt) : NULL); + + /* if you add/remove a line here, change the row count above */ + + fprintf(output, _("General\n")); + fprintf(output, _(" \\copyright show PostgreSQL usage and distribution terms\n")); + fprintf(output, _(" \\g [FILE] or ; execute query (and send results to file or |pipe)\n")); + fprintf(output, _(" \\gset [PREFIX] execute query and store results in psql variables\n")); + fprintf(output, _(" \\q quit psql\n")); + fprintf(output, _(" \\watch [SEC] execute query every SEC seconds\n")); + fprintf(output, "\n"); + + fprintf(output, _("Help\n")); + + fprintf(output, _(" \\? [commands] show help on backslash commands\n")); + fprintf(output, _(" \\? options show help on psql command-line options\n")); + fprintf(output, _(" \\? variables show help on special variables\n")); + fprintf(output, _(" \\h [NAME] help on syntax of SQL commands, * for all commands\n")); + fprintf(output, "\n"); + + fprintf(output, _("Query Buffer\n")); + fprintf(output, _(" \\e [FILE] [LINE] edit the query buffer (or file) with external editor\n")); + fprintf(output, _(" \\ef [FUNCNAME [LINE]] edit function definition with external editor\n")); + fprintf(output, _(" \\p show the contents of the query buffer\n")); + fprintf(output, _(" \\r reset (clear) the query buffer\n")); +#ifdef USE_READLINE + fprintf(output, _(" \\s [FILE] display history or save it to file\n")); +#endif + fprintf(output, _(" \\w FILE write query buffer to file\n")); + fprintf(output, "\n"); + + fprintf(output, _("Input/Output\n")); + fprintf(output, _(" \\copy ... perform SQL COPY with data stream to the client host\n")); + fprintf(output, _(" \\echo [STRING] write string to standard output\n")); + fprintf(output, _(" \\i FILE execute commands from file\n")); + fprintf(output, _(" \\ir FILE as \\i, but relative to location of current script\n")); + fprintf(output, _(" \\o [FILE] send all query results to file or |pipe\n")); + fprintf(output, _(" \\qecho [STRING] write string to query output stream (see \\o)\n")); + fprintf(output, "\n"); + + fprintf(output, _("Informational\n")); + fprintf(output, _(" (options: S = show system objects, + = additional detail)\n")); + fprintf(output, _(" \\d[S+] list tables, views, and sequences\n")); + fprintf(output, _(" \\d[S+] NAME describe table, view, sequence, or index\n")); + fprintf(output, _(" \\da[S] [PATTERN] list aggregates\n")); + fprintf(output, _(" \\db[+] [PATTERN] list tablespaces\n")); + fprintf(output, _(" \\dc[S+] [PATTERN] list conversions\n")); + fprintf(output, _(" \\dC[+] [PATTERN] list casts\n")); + fprintf(output, _(" \\dd[S] [PATTERN] show object descriptions not displayed elsewhere\n")); + fprintf(output, _(" \\ddp [PATTERN] list default privileges\n")); + fprintf(output, _(" \\dD[S+] [PATTERN] list domains\n")); + fprintf(output, _(" \\det[+] [PATTERN] list foreign tables\n")); + fprintf(output, _(" \\des[+] [PATTERN] list foreign servers\n")); + fprintf(output, _(" \\deu[+] [PATTERN] list user mappings\n")); + fprintf(output, _(" \\dew[+] [PATTERN] list foreign-data wrappers\n")); + fprintf(output, _(" \\df[antw][S+] [PATRN] list [only agg/normal/trigger/window] functions\n")); + fprintf(output, _(" \\dF[+] [PATTERN] list text search configurations\n")); + fprintf(output, _(" \\dFd[+] [PATTERN] list text search dictionaries\n")); + fprintf(output, _(" \\dFp[+] [PATTERN] list text search parsers\n")); + fprintf(output, _(" \\dFt[+] [PATTERN] list text search templates\n")); + fprintf(output, _(" \\dg[+] [PATTERN] list roles\n")); + fprintf(output, _(" \\di[S+] [PATTERN] list indexes\n")); + fprintf(output, _(" \\dl list large objects, same as \\lo_list\n")); + fprintf(output, _(" \\dL[S+] [PATTERN] list procedural languages\n")); + fprintf(output, _(" \\dm[S+] [PATTERN] list materialized views\n")); + fprintf(output, _(" \\dn[S+] [PATTERN] list schemas\n")); + fprintf(output, _(" \\do[S] [PATTERN] list operators\n")); + fprintf(output, _(" \\dO[S+] [PATTERN] list collations\n")); + fprintf(output, _(" \\dp [PATTERN] list table, view, and sequence access privileges\n")); + fprintf(output, _(" \\drds [PATRN1 [PATRN2]] list per-database role settings\n")); + fprintf(output, _(" \\ds[S+] [PATTERN] list sequences\n")); + fprintf(output, _(" \\dt[S+] [PATTERN] list tables\n")); + fprintf(output, _(" \\dT[S+] [PATTERN] list data types\n")); + fprintf(output, _(" \\du[+] [PATTERN] list roles\n")); + fprintf(output, _(" \\dv[S+] [PATTERN] list views\n")); + fprintf(output, _(" \\dE[S+] [PATTERN] list foreign tables\n")); + fprintf(output, _(" \\dx[+] [PATTERN] list extensions\n")); + fprintf(output, _(" \\dy [PATTERN] list event triggers\n")); + fprintf(output, _(" \\l[+] [PATTERN] list databases\n")); + fprintf(output, _(" \\sf[+] FUNCNAME show a function's definition\n")); + fprintf(output, _(" \\z [PATTERN] same as \\dp\n")); + fprintf(output, "\n"); + + fprintf(output, _("Formatting\n")); + fprintf(output, _(" \\a toggle between unaligned and aligned output mode\n")); + fprintf(output, _(" \\C [STRING] set table title, or unset if none\n")); + fprintf(output, _(" \\f [STRING] show or set field separator for unaligned query output\n")); + fprintf(output, _(" \\H toggle HTML output mode (currently %s)\n"), + ON(pset.popt.topt.format == PRINT_HTML)); + fprintf(output, _(" \\pset [NAME [VALUE]] set table output option\n" + " (NAME := {format|border|expanded|fieldsep|fieldsep_zero|footer|null|\n" + " numericlocale|recordsep|recordsep_zero|tuples_only|title|tableattr|pager|\n" + " unicode_border_linestyle|unicode_column_linestyle|unicode_header_linestyle})\n")); + fprintf(output, _(" \\t [on|off] show only rows (currently %s)\n"), + ON(pset.popt.topt.tuples_only)); + fprintf(output, _(" \\T [STRING] set HTML
tag attributes, or unset if none\n")); + fprintf(output, _(" \\x [on|off|auto] toggle expanded output (currently %s)\n"), + pset.popt.topt.expanded == 2 ? "auto" : ON(pset.popt.topt.expanded)); + fprintf(output, "\n"); + + fprintf(output, _("Connection\n")); + if (currdb) + fprintf(output, _(" \\c[onnect] {[DBNAME|- USER|- HOST|- PORT|-] | conninfo}\n" + " connect to new database (currently \"%s\")\n"), + currdb); + else + fprintf(output, _(" \\c[onnect] {[DBNAME|- USER|- HOST|- PORT|-] | conninfo}\n" + " connect to new database (currently no connection)\n")); + fprintf(output, _(" \\encoding [ENCODING] show or set client encoding\n")); + fprintf(output, _(" \\password [USERNAME] securely change the password for a user\n")); + fprintf(output, _(" \\conninfo display information about current connection\n")); + fprintf(output, "\n"); + + fprintf(output, _("Operating System\n")); + fprintf(output, _(" \\cd [DIR] change the current working directory\n")); + fprintf(output, _(" \\setenv NAME [VALUE] set or unset environment variable\n")); + fprintf(output, _(" \\timing [on|off] toggle timing of commands (currently %s)\n"), + ON(pset.timing)); + fprintf(output, _(" \\! [COMMAND] execute command in shell or start interactive shell\n")); + fprintf(output, "\n"); + + fprintf(output, _("Variables\n")); + fprintf(output, _(" \\prompt [TEXT] NAME prompt user to set internal variable\n")); + fprintf(output, _(" \\set [NAME [VALUE]] set internal variable, or list all if no parameters\n")); + fprintf(output, _(" \\unset NAME unset (delete) internal variable\n")); + fprintf(output, "\n"); + + fprintf(output, _("Large Objects\n")); + fprintf(output, _(" \\lo_export LOBOID FILE\n" + " \\lo_import FILE [COMMENT]\n" + " \\lo_list\n" + " \\lo_unlink LOBOID large object operations\n")); + + ClosePager(output); +} + + +/* + * helpVariables + * + * show list of available variables (options) from command line + */ +void +helpVariables(unsigned short int pager) +{ + FILE *output; + + output = PageOutput(85, pager ? &(pset.popt.topt) : NULL); + + fprintf(output, _("List of specially treated variables\n\n")); + + fprintf(output, _("psql variables:\n")); + fprintf(output, _("Usage:\n")); + fprintf(output, _(" psql --set=NAME=VALUE\n or \\set NAME VALUE inside psql\n\n")); + + fprintf(output, _(" AUTOCOMMIT if set, successful SQL commands are automatically committed\n")); + fprintf(output, _(" COMP_KEYWORD_CASE determines the case used to complete SQL key words\n" + " [lower, upper, preserve-lower, preserve-upper]\n")); + fprintf(output, _(" DBNAME the currently connected database name\n")); + fprintf(output, _(" ECHO controls what input is written to standard output\n" + " [all, errors, none, queries]\n")); + fprintf(output, _(" ECHO_HIDDEN if set, display internal queries executed by backslash commands;\n" + " if set to \"noexec\", just show without execution\n")); + fprintf(output, _(" ENCODING current client character set encoding\n")); + fprintf(output, _(" FETCH_COUNT the number of result rows to fetch and display at a time\n" + " (default: 0=unlimited)\n")); + fprintf(output, _(" HISTCONTROL controls command history [ignorespace, ignoredups, ignoreboth]\n")); + fprintf(output, _(" HISTFILE file name used to store the command history\n")); + fprintf(output, _(" HISTSIZE the number of commands to store in the command history\n")); + fprintf(output, _(" HOST the currently connected database server host\n")); + fprintf(output, _(" IGNOREEOF if unset, sending an EOF to interactive session terminates application\n")); + fprintf(output, _(" LASTOID value of the last affected OID\n")); + fprintf(output, _(" ON_ERROR_ROLLBACK if set, an error doesn't stop a transaction (uses implicit savepoints)\n")); + fprintf(output, _(" ON_ERROR_STOP stop batch execution after error\n")); + fprintf(output, _(" PORT server port of the current connection\n")); + fprintf(output, _(" PROMPT1 specifies the standard psql prompt\n")); + fprintf(output, _(" PROMPT2 specifies the prompt used when a statement continues from a previous line\n")); + fprintf(output, _(" PROMPT3 specifies the prompt used during COPY ... FROM STDIN\n")); + fprintf(output, _(" QUIET run quietly (same as -q option)\n")); + fprintf(output, _(" SINGLELINE end of line terminates SQL command mode (same as -S option)\n")); + fprintf(output, _(" SINGLESTEP single-step mode (same as -s option)\n")); + fprintf(output, _(" USER the currently connected database user\n")); + fprintf(output, _(" VERBOSITY controls verbosity of error reports [default, verbose, terse]\n")); + + fprintf(output, _("\nDisplay settings:\n")); + fprintf(output, _("Usage:\n")); + fprintf(output, _(" psql --pset=NAME[=VALUE]\n or \\pset NAME [VALUE] inside psql\n\n")); + + fprintf(output, _(" border border style (number)\n")); + fprintf(output, _(" columns target width for the wrapped format\n")); + fprintf(output, _(" expanded (or x) expanded output [on, off, auto]\n")); + fprintf(output, _(" fieldsep field separator for unaligned output (default \"%s\")\n"), DEFAULT_FIELD_SEP); + fprintf(output, _(" fieldsep_zero set field separator for unaligned output to zero byte\n")); + fprintf(output, _(" format set output format [unaligned, aligned, wrapped, html, asciidoc, ...]\n")); + fprintf(output, _(" footer enable or disable display of the table footer [on, off]\n")); + fprintf(output, _(" linestyle set the border line drawing style [ascii, old-ascii, unicode]\n")); + fprintf(output, _(" null set the string to be printed in place of a null value\n")); + fprintf(output, _(" numericlocale enable or disable display of a locale-specific character to separate\n" + " groups of digits [on, off]\n")); + fprintf(output, _(" pager control when an external pager is used [yes, no, always]\n")); + fprintf(output, _(" recordsep record (line) separator for unaligned output\n")); + fprintf(output, _(" recordsep_zero set record separator for unaligned output to zero byte\n")); + fprintf(output, _(" tableattr (or T) specify attributes for table tag in html format or proportional\n" + " column widths for left-aligned data types in latex-longtable format\n")); + fprintf(output, _(" title set the table title for any subsequently printed tables\n")); + fprintf(output, _(" tuples_only if set, only actual table data is shown\n")); + fprintf(output, _(" unicode_border_linestyle\n" + " unicode_column_linestyle\n" + " unicode_header_linestyle\n" + " set the style of Unicode line drawing [single, double]\n")); + + fprintf(output, _("\nEnvironment variables:\n")); + fprintf(output, _("Usage:\n")); + +#ifndef WIN32 + fprintf(output, _(" NAME=VALUE [NAME=VALUE] psql ...\n or \\setenv NAME [VALUE] inside psql\n\n")); +#else + fprintf(output, _(" set NAME=VALUE\n psql ...\n or \\setenv NAME [VALUE] inside psql\n\n")); +#endif + + fprintf(output, _(" COLUMNS number of columns for wrapped format\n")); + fprintf(output, _(" PAGER name of external pager program\n")); + fprintf(output, _(" PGAPPNAME same as the application_name connection parameter\n")); + fprintf(output, _(" PGDATABASE same as the dbname connection parameter\n")); + fprintf(output, _(" PGHOST same as the host connection parameter\n")); + fprintf(output, _(" PGPORT same as the port connection parameter\n")); + fprintf(output, _(" PGUSER same as the user connection parameter\n")); + fprintf(output, _(" PGPASSWORD connection password (not recommended)\n")); + fprintf(output, _(" PGPASSFILE password file name\n")); + fprintf(output, _(" PSQL_EDITOR, EDITOR, VISUAL\n" + " editor used by the \\e and \\ef commands\n")); + fprintf(output, _(" PSQL_EDITOR_LINENUMBER_ARG\n" + " how to specify a line number when invoking the editor\n")); + fprintf(output, _(" PSQL_HISTORY alternative location for the command history file\n")); + fprintf(output, _(" PSQLRC alternative location for the user's .psqlrc file\n")); + fprintf(output, _(" SHELL shell used by the \\! command\n")); + fprintf(output, _(" TMPDIR directory for temporary files\n")); + + ClosePager(output); +} + + +/* + * helpSQL -- help with SQL commands + * + * Note: we assume caller removed any trailing spaces in "topic". + */ +void +helpSQL(const char *topic, unsigned short int pager) +{ +#define VALUE_OR_NULL(a) ((a) ? (a) : "") + + if (!topic || strlen(topic) == 0) + { + /* Print all the available command names */ + int screen_width; + int ncolumns; + int nrows; + FILE *output; + int i; + int j; + +#ifdef TIOCGWINSZ + struct winsize screen_size; + + if (ioctl(fileno(stdout), TIOCGWINSZ, &screen_size) == -1) + screen_width = 80; /* ioctl failed, assume 80 */ + else + screen_width = screen_size.ws_col; +#else + screen_width = 80; /* default assumption */ +#endif + + ncolumns = (screen_width - 3) / (QL_MAX_CMD_LEN + 1); + ncolumns = Max(ncolumns, 1); + nrows = (QL_HELP_COUNT + (ncolumns - 1)) / ncolumns; + + output = PageOutput(nrows + 1, pager ? &(pset.popt.topt) : NULL); + + fputs(_("Available help:\n"), output); + + for (i = 0; i < nrows; i++) + { + fprintf(output, " "); + for (j = 0; j < ncolumns - 1; j++) + fprintf(output, "%-*s", + QL_MAX_CMD_LEN + 1, + VALUE_OR_NULL(QL_HELP[i + j * nrows].cmd)); + if (i + j * nrows < QL_HELP_COUNT) + fprintf(output, "%s", + VALUE_OR_NULL(QL_HELP[i + j * nrows].cmd)); + fputc('\n', output); + } + + ClosePager(output); + } + else + { + int i, + j, + x = 0; + bool help_found = false; + FILE *output = NULL; + size_t len, + wordlen; + int nl_count = 0; + + /* + * We first try exact match, then first + second words, then first + * word only. + */ + len = strlen(topic); + + for (x = 1; x <= 3; x++) + { + if (x > 1) /* Nothing on first pass - try the opening + * word(s) */ + { + wordlen = j = 1; + while (topic[j] != ' ' && j++ < len) + wordlen++; + if (x == 2) + { + j++; + while (topic[j] != ' ' && j++ <= len) + wordlen++; + } + if (wordlen >= len) /* Don't try again if the same word */ + { + if (!output) + output = PageOutput(nl_count, pager ? &(pset.popt.topt) : NULL); + break; + } + len = wordlen; + } + + /* Count newlines for pager */ + for (i = 0; QL_HELP[i].cmd; i++) + { + if (pg_strncasecmp(topic, QL_HELP[i].cmd, len) == 0 || + strcmp(topic, "*") == 0) + { + nl_count += 5 + QL_HELP[i].nl_count; + + /* If we have an exact match, exit. Fixes \h SELECT */ + if (pg_strcasecmp(topic, QL_HELP[i].cmd) == 0) + break; + } + } + + if (!output) + output = PageOutput(nl_count, pager ? &(pset.popt.topt) : NULL); + + for (i = 0; QL_HELP[i].cmd; i++) + { + if (pg_strncasecmp(topic, QL_HELP[i].cmd, len) == 0 || + strcmp(topic, "*") == 0) + { + PQExpBufferData buffer; + + initPQExpBuffer(&buffer); + QL_HELP[i].syntaxfunc(&buffer); + help_found = true; + fprintf(output, _("Command: %s\n" + "Description: %s\n" + "Syntax:\n%s\n\n"), + QL_HELP[i].cmd, + _(QL_HELP[i].help), + buffer.data); + /* If we have an exact match, exit. Fixes \h SELECT */ + if (pg_strcasecmp(topic, QL_HELP[i].cmd) == 0) + break; + } + } + if (help_found) /* Don't keep trying if we got a match */ + break; + } + + if (!help_found) + fprintf(output, _("No help available for \"%s\".\nTry \\h with no arguments to see available help.\n"), topic); + + ClosePager(output); + } +} + + + +void +print_copyright(void) +{ + puts( + "PostgreSQL Database Management System\n" + "(formerly known as Postgres, then as Postgres95)\n\n" + "Portions Copyright (c) 1996-2015, PostgreSQL Global Development Group\n\n" + "Portions Copyright (c) 1994, The Regents of the University of California\n\n" + "Permission to use, copy, modify, and distribute this software and its\n" + "documentation for any purpose, without fee, and without a written agreement\n" + "is hereby granted, provided that the above copyright notice and this\n" + "paragraph and the following two paragraphs appear in all copies.\n\n" + "IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR\n" + "DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING\n" + "LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS\n" + "DOCUMENTATION, EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE\n" + "POSSIBILITY OF SUCH DAMAGE.\n\n" + "THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,\n" + "INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY\n" + "AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS\n" + "ON AN \"AS IS\" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO\n" + "PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.\n" + ); +} diff --git a/src/bin/csql/help.h b/src/bin/csql/help.h new file mode 100644 index 000000000..0fc4f6708 --- /dev/null +++ b/src/bin/csql/help.h @@ -0,0 +1,21 @@ +/* + * psql - the PostgreSQL interactive terminal + * + * Copyright (c) 2000-2015, PostgreSQL Global Development Group + * + * src/bin/psql/help.h + */ +#ifndef HELP_H +#define HELP_H + +void usage(unsigned short int pager); + +void slashUsage(unsigned short int pager); + +void helpVariables(unsigned short int pager); + +void helpSQL(const char *topic, unsigned short int pager); + +void print_copyright(void); + +#endif diff --git a/src/bin/csql/input.c b/src/bin/csql/input.c new file mode 100644 index 000000000..2bc065adc --- /dev/null +++ b/src/bin/csql/input.c @@ -0,0 +1,539 @@ +/* + * psql - the PostgreSQL interactive terminal + * + * Copyright (c) 2000-2015, PostgreSQL Global Development Group + * + * src/bin/psql/input.c + */ +#include "postgres_fe.h" + +#ifndef WIN32 +#include +#endif +#include +#include + +#include "input.h" +#include "settings.h" +#include "tab-complete.h" +#include "common.h" + +#ifndef WIN32 +#define PSQLHISTORY ".psql_history" +#else +#define PSQLHISTORY "psql_history" +#endif + +/* Runtime options for turning off readline and history */ +/* (of course there is no runtime command for doing that :) */ +#ifdef USE_READLINE +static bool useReadline; +static bool useHistory; + +static char *psql_history; + +static int history_lines_added; + + +/* + * Preserve newlines in saved queries by mapping '\n' to NL_IN_HISTORY + * + * It is assumed NL_IN_HISTORY will never be entered by the user + * nor appear inside a multi-byte string. 0x00 is not properly + * handled by the readline routines so it can not be used + * for this purpose. + */ +#define NL_IN_HISTORY 0x01 +#endif + +static void finishInput(void); + + +/* + * gets_interactive() + * + * Gets a line of interactive input, using readline if desired. + * The result is a malloc'd string. + * + * Caller *must* have set up sigint_interrupt_jmp before calling. + */ +char * +gets_interactive(const char *prompt) +{ +#ifdef USE_READLINE + if (useReadline) + { + char *result; + + /* + * Some versions of readline don't notice SIGWINCH signals that arrive + * when not actively reading input. The simplest fix is to always + * re-read the terminal size. This leaves a window for SIGWINCH to be + * missed between here and where readline() enables libreadline's + * signal handler, but that's probably short enough to be ignored. + */ +#ifdef HAVE_RL_RESET_SCREEN_SIZE + rl_reset_screen_size(); +#endif + + /* Enable SIGINT to longjmp to sigint_interrupt_jmp */ + sigint_interrupt_enabled = true; + + /* On some platforms, readline is declared as readline(char *) */ + result = readline((char *) prompt); + + /* Disable SIGINT again */ + sigint_interrupt_enabled = false; + + return result; + } +#endif + + fputs(prompt, stdout); + fflush(stdout); + return gets_fromFile(stdin); +} + + +/* + * Append the line to the history buffer, making sure there is a trailing '\n' + */ +void +pg_append_history(const char *s, PQExpBuffer history_buf) +{ +#ifdef USE_READLINE + if (useHistory && s) + { + appendPQExpBufferStr(history_buf, s); + if (!s[0] || s[strlen(s) - 1] != '\n') + appendPQExpBufferChar(history_buf, '\n'); + } +#endif +} + + +/* + * Emit accumulated history entry to readline's history mechanism, + * then reset the buffer to empty. + * + * Note: we write nothing if history_buf is empty, so extra calls to this + * function don't hurt. There must have been at least one line added by + * pg_append_history before we'll do anything. + */ +void +pg_send_history(PQExpBuffer history_buf) +{ +#ifdef USE_READLINE + static char *prev_hist = NULL; + + char *s = history_buf->data; + int i; + + /* Trim any trailing \n's (OK to scribble on history_buf) */ + for (i = strlen(s) - 1; i >= 0 && s[i] == '\n'; i--) + ; + s[i + 1] = '\0'; + + if (useHistory && s[0]) + { + if (((pset.histcontrol & hctl_ignorespace) && + s[0] == ' ') || + ((pset.histcontrol & hctl_ignoredups) && + prev_hist && strcmp(s, prev_hist) == 0)) + { + /* Ignore this line as far as history is concerned */ + } + else + { + /* Save each previous line for ignoredups processing */ + if (prev_hist) + free(prev_hist); + prev_hist = pg_strdup(s); + /* And send it to readline */ + add_history(s); + /* Count lines added to history for use later */ + history_lines_added++; + } + } + + resetPQExpBuffer(history_buf); +#endif +} + + +/* + * gets_fromFile + * + * Gets a line of noninteractive input from a file (which could be stdin). + * The result is a malloc'd string, or NULL on EOF or input error. + * + * Caller *must* have set up sigint_interrupt_jmp before calling. + * + * Note: we re-use a static PQExpBuffer for each call. This is to avoid + * leaking memory if interrupted by SIGINT. + */ +char * +gets_fromFile(FILE *source) +{ + static PQExpBuffer buffer = NULL; + + char line[1024]; + + if (buffer == NULL) /* first time through? */ + buffer = createPQExpBuffer(); + else + resetPQExpBuffer(buffer); + + for (;;) + { + char *result; + + /* Enable SIGINT to longjmp to sigint_interrupt_jmp */ + sigint_interrupt_enabled = true; + + /* Get some data */ + result = fgets(line, sizeof(line), source); + + /* Disable SIGINT again */ + sigint_interrupt_enabled = false; + + /* EOF or error? */ + if (result == NULL) + { + if (ferror(source)) + { + psql_error("could not read from input file: %s\n", + strerror(errno)); + return NULL; + } + break; + } + + appendPQExpBufferStr(buffer, line); + + if (PQExpBufferBroken(buffer)) + { + psql_error("out of memory\n"); + return NULL; + } + + /* EOL? */ + if (buffer->data[buffer->len - 1] == '\n') + { + buffer->data[buffer->len - 1] = '\0'; + return pg_strdup(buffer->data); + } + } + + if (buffer->len > 0) /* EOF after reading some bufferload(s) */ + return pg_strdup(buffer->data); + + /* EOF, so return null */ + return NULL; +} + + +#ifdef USE_READLINE + +/* + * Macros to iterate over each element of the history list in order + * + * You would think this would be simple enough, but in its inimitable fashion + * libedit has managed to break it: in libreadline we must use next_history() + * to go from oldest to newest, but in libedit we must use previous_history(). + * To detect what to do, we make a trial call of previous_history(): if it + * fails, then either next_history() is what to use, or there's zero or one + * history entry so that it doesn't matter which direction we go. + * + * In case that wasn't disgusting enough: the code below is not as obvious as + * it might appear. In some libedit releases history_set_pos(0) fails until + * at least one add_history() call has been done. This is not an issue for + * printHistory() or encode_history(), which cannot be invoked before that has + * happened. In decode_history(), that's not so, and what actually happens is + * that we are sitting on the newest entry to start with, previous_history() + * fails, and we iterate over all the entries using next_history(). So the + * decode_history() loop iterates over the entries in the wrong order when + * using such a libedit release, and if there were another attempt to use + * BEGIN_ITERATE_HISTORY() before some add_history() call had happened, it + * wouldn't work. Fortunately we don't care about either of those things. + * + * Usage pattern is: + * + * BEGIN_ITERATE_HISTORY(varname); + * { + * loop body referencing varname->line; + * } + * END_ITERATE_HISTORY(); + */ +#define BEGIN_ITERATE_HISTORY(VARNAME) \ + do { \ + HIST_ENTRY *VARNAME; \ + bool use_prev_; \ + \ + history_set_pos(0); \ + use_prev_ = (previous_history() != NULL); \ + history_set_pos(0); \ + for (VARNAME = current_history(); VARNAME != NULL; \ + VARNAME = use_prev_ ? previous_history() : next_history()) \ + { \ + (void) 0 + +#define END_ITERATE_HISTORY() \ + } \ + } while(0) + + +/* + * Convert newlines to NL_IN_HISTORY for safe saving in readline history file + */ +static void +encode_history(void) +{ + BEGIN_ITERATE_HISTORY(cur_hist); + { + char *cur_ptr; + + /* some platforms declare HIST_ENTRY.line as const char * */ + for (cur_ptr = (char *) cur_hist->line; *cur_ptr; cur_ptr++) + { + if (*cur_ptr == '\n') + *cur_ptr = NL_IN_HISTORY; + } + } + END_ITERATE_HISTORY(); +} + +/* + * Reverse the above encoding + */ +static void +decode_history(void) +{ + BEGIN_ITERATE_HISTORY(cur_hist); + { + char *cur_ptr; + + /* some platforms declare HIST_ENTRY.line as const char * */ + for (cur_ptr = (char *) cur_hist->line; *cur_ptr; cur_ptr++) + { + if (*cur_ptr == NL_IN_HISTORY) + *cur_ptr = '\n'; + } + } + END_ITERATE_HISTORY(); +} +#endif /* USE_READLINE */ + + +/* + * Put any startup stuff related to input in here. It's good to maintain + * abstraction this way. + * + * The only "flag" right now is 1 for use readline & history. + */ +void +initializeInput(int flags) +{ +#ifdef USE_READLINE + if (flags & 1) + { + const char *histfile; + char home[MAXPGPATH]; + + useReadline = true; + + /* these two things must be done in this order: */ + initialize_readline(); + rl_initialize(); + + useHistory = true; + using_history(); + history_lines_added = 0; + + histfile = GetVariable(pset.vars, "HISTFILE"); + + if (histfile == NULL) + { + char *envhist; + + envhist = getenv("PSQL_HISTORY"); + if (envhist != NULL && strlen(envhist) > 0) + histfile = envhist; + } + + if (histfile == NULL) + { + if (get_home_path(home)) + psql_history = psprintf("%s/%s", home, PSQLHISTORY); + } + else + { + psql_history = pg_strdup(histfile); + expand_tilde(&psql_history); + } + + if (psql_history) + { + read_history(psql_history); + decode_history(); + } + } +#endif + + atexit(finishInput); +} + + +/* + * This function saves the readline history when psql exits. + * + * fname: pathname of history file. (Should really be "const char *", + * but some ancient versions of readline omit the const-decoration.) + * + * max_lines: if >= 0, limit history file to that many entries. + */ +#ifdef USE_READLINE +static bool +saveHistory(char *fname, int max_lines) +{ + int errnum; + + /* + * Suppressing the write attempt when HISTFILE is set to /dev/null may + * look like a negligible optimization, but it's necessary on e.g. Darwin, + * where write_history will fail because it tries to chmod the target + * file. + */ + if (strcmp(fname, DEVNULL) != 0) + { + /* + * Encode \n, since otherwise readline will reload multiline history + * entries as separate lines. (libedit doesn't really need this, but + * we do it anyway since it's too hard to tell which implementation we + * are using.) + */ + encode_history(); + + /* + * On newer versions of libreadline, truncate the history file as + * needed and then append what we've added. This avoids overwriting + * history from other concurrent sessions (although there are still + * race conditions when two sessions exit at about the same time). If + * we don't have those functions, fall back to write_history(). + */ +#if defined(HAVE_HISTORY_TRUNCATE_FILE) && defined(HAVE_APPEND_HISTORY) + { + int nlines; + int fd; + + /* truncate previous entries if needed */ + if (max_lines >= 0) + { + nlines = Max(max_lines - history_lines_added, 0); + (void) history_truncate_file(fname, nlines); + } + /* append_history fails if file doesn't already exist :-( */ + fd = open(fname, O_CREAT | O_WRONLY | PG_BINARY, 0600); + if (fd >= 0) + close(fd); + /* append the appropriate number of lines */ + if (max_lines >= 0) + nlines = Min(max_lines, history_lines_added); + else + nlines = history_lines_added; + errnum = append_history(nlines, fname); + if (errnum == 0) + return true; + } +#else /* don't have append support */ + { + /* truncate what we have ... */ + if (max_lines >= 0) + stifle_history(max_lines); + /* ... and overwrite file. Tough luck for concurrent sessions. */ + errnum = write_history(fname); + if (errnum == 0) + return true; + } +#endif + + psql_error("could not save history to file \"%s\": %s\n", + fname, strerror(errnum)); + } + return false; +} +#endif + + + +/* + * Print history to the specified file, or to the console if fname is NULL + * (psql \s command) + * + * We used to use saveHistory() for this purpose, but that doesn't permit + * use of a pager; moreover libedit's implementation behaves incompatibly + * (preferring to encode its output) and may fail outright when the target + * file is specified as /dev/tty. + */ +bool +printHistory(const char *fname, unsigned short int pager) +{ +#ifdef USE_READLINE + FILE *output; + bool is_pager; + + if (!useHistory) + return false; + + if (fname == NULL) + { + /* use pager, if enabled, when printing to console */ + output = PageOutput(INT_MAX, pager ? &(pset.popt.topt) : NULL); + is_pager = true; + } + else + { + output = fopen(fname, "w"); + if (output == NULL) + { + psql_error("could not save history to file \"%s\": %s\n", + fname, strerror(errno)); + return false; + } + is_pager = false; + } + + BEGIN_ITERATE_HISTORY(cur_hist); + { + fprintf(output, "%s\n", cur_hist->line); + } + END_ITERATE_HISTORY(); + + if (is_pager) + ClosePager(output); + else + fclose(output); + + return true; +#else + psql_error("history is not supported by this installation\n"); + return false; +#endif +} + + +static void +finishInput(void) +{ +#ifdef USE_READLINE + if (useHistory && psql_history) + { + int hist_size; + + hist_size = GetVariableNum(pset.vars, "HISTSIZE", 500, -1, true); + (void) saveHistory(psql_history, hist_size); + free(psql_history); + psql_history = NULL; + } +#endif +} diff --git a/src/bin/csql/input.h b/src/bin/csql/input.h new file mode 100644 index 000000000..abd7012d1 --- /dev/null +++ b/src/bin/csql/input.h @@ -0,0 +1,51 @@ +/* + * psql - the PostgreSQL interactive terminal + * + * Copyright (c) 2000-2015, PostgreSQL Global Development Group + * + * src/bin/psql/input.h + */ +#ifndef INPUT_H +#define INPUT_H + +/* + * If some other file needs to have access to readline/history, include this + * file and save yourself all this work. + * + * USE_READLINE is the definite pointers regarding existence or not. + */ +#ifdef HAVE_LIBREADLINE +#define USE_READLINE 1 + +#if defined(HAVE_READLINE_READLINE_H) +#include +#if defined(HAVE_READLINE_HISTORY_H) +#include +#endif +#elif defined(HAVE_EDITLINE_READLINE_H) +#include +#if defined(HAVE_EDITLINE_HISTORY_H) +#include +#endif +#elif defined(HAVE_READLINE_H) +#include +#if defined(HAVE_HISTORY_H) +#include +#endif +#endif /* HAVE_READLINE_READLINE_H, etc */ +#endif /* HAVE_LIBREADLINE */ + +#include "pqexpbuffer.h" + + +char *gets_interactive(const char *prompt); +char *gets_fromFile(FILE *source); + +void initializeInput(int flags); + +bool printHistory(const char *fname, unsigned short int pager); + +void pg_append_history(const char *s, PQExpBuffer history_buf); +void pg_send_history(PQExpBuffer history_buf); + +#endif /* INPUT_H */ diff --git a/src/bin/csql/keywords.c b/src/bin/csql/keywords.c new file mode 100644 index 000000000..5775cad0f --- /dev/null +++ b/src/bin/csql/keywords.c @@ -0,0 +1,30 @@ +/*------------------------------------------------------------------------- + * + * keywords.c + * lexical token lookup for key words in PostgreSQL + * + * + * Portions Copyright (c) 1996-2015, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * + * IDENTIFICATION + * src/bin/pg_dump/keywords.c + * + *------------------------------------------------------------------------- + */ +#include "postgres_fe.h" + +#include "parser/keywords.h" + +/* + * We don't need the token number, so leave it out to avoid requiring other + * backend headers. + */ +#define PG_KEYWORD(a,b,c) {a,0,c}, + +const ScanKeyword FEScanKeywords[] = { +#include "parser/kwlist.h" +}; + +const int NumFEScanKeywords = lengthof(FEScanKeywords); diff --git a/src/bin/csql/kwlookup.c b/src/bin/csql/kwlookup.c new file mode 100644 index 000000000..85ba4bd74 --- /dev/null +++ b/src/bin/csql/kwlookup.c @@ -0,0 +1,89 @@ +/*------------------------------------------------------------------------- + * + * kwlookup.c + * lexical token lookup for key words in PostgreSQL + * + * NB - this file is also used by ECPG and several frontend programs in + * src/bin/ including pg_dump and psql + * + * Portions Copyright (c) 1996-2015, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * + * IDENTIFICATION + * src/backend/parser/kwlookup.c + * + *------------------------------------------------------------------------- + */ + +/* use c.h so this can be built as either frontend or backend */ +#include "c.h" + +#include + +#include "parser/keywords.h" + +/* + * ScanKeywordLookup - see if a given word is a keyword + * + * Returns a pointer to the ScanKeyword table entry, or NULL if no match. + * + * The match is done case-insensitively. Note that we deliberately use a + * dumbed-down case conversion that will only translate 'A'-'Z' into 'a'-'z', + * even if we are in a locale where tolower() would produce more or different + * translations. This is to conform to the SQL99 spec, which says that + * keywords are to be matched in this way even though non-keyword identifiers + * receive a different case-normalization mapping. + */ +const ScanKeyword * +ScanKeywordLookup(const char *text, + const ScanKeyword *keywords, + int num_keywords) +{ + int len, + i; + char word[NAMEDATALEN]; + const ScanKeyword *low; + const ScanKeyword *high; + + len = strlen(text); + /* We assume all keywords are shorter than NAMEDATALEN. */ + if (len >= NAMEDATALEN) + return NULL; + + /* + * Apply an ASCII-only downcasing. We must not use tolower() since it may + * produce the wrong translation in some locales (eg, Turkish). + */ + for (i = 0; i < len; i++) + { + char ch = text[i]; + + if (ch >= 'A' && ch <= 'Z') + ch += 'a' - 'A'; + word[i] = ch; + } + word[len] = '\0'; + + /* + * Now do a binary search using plain strcmp() comparison. + */ + low = keywords; + high = keywords + (num_keywords - 1); + while (low <= high) + { + const ScanKeyword *middle; + int difference; + + middle = low + (high - low) / 2; + difference = strcmp(middle->name, word); + if (difference == 0) + return middle; + else if (difference < 0) + low = middle + 1; + else + high = middle - 1; + } + + return NULL; +} diff --git a/src/bin/csql/large_obj.c b/src/bin/csql/large_obj.c new file mode 100644 index 000000000..f6221c290 --- /dev/null +++ b/src/bin/csql/large_obj.c @@ -0,0 +1,321 @@ +/* + * psql - the PostgreSQL interactive terminal + * + * Copyright (c) 2000-2015, PostgreSQL Global Development Group + * + * src/bin/psql/large_obj.c + */ +#include "postgres_fe.h" +#include "large_obj.h" + + +#include "settings.h" +#include "common.h" + +#if (PG_VERSION_NUM >= 90500) +static void print_lo_result(const char *fmt,...) pg_attribute_printf(1, 2); +#else +static void +print_lo_result(const char *fmt,...) +__attribute__((format(PG_PRINTF_ATTRIBUTE, 1, 2))); +#endif + +static void +print_lo_result(const char *fmt,...) +{ + va_list ap; + + if (!pset.quiet) + { + if (pset.popt.topt.format == PRINT_HTML) + fputs("

", pset.queryFout); + + va_start(ap, fmt); + vfprintf(pset.queryFout, fmt, ap); + va_end(ap); + + if (pset.popt.topt.format == PRINT_HTML) + fputs("

\n", pset.queryFout); + else + fputs("\n", pset.queryFout); + } + + if (pset.logfile) + { + va_start(ap, fmt); + vfprintf(pset.logfile, fmt, ap); + va_end(ap); + fputs("\n", pset.logfile); + } +} + + +/* + * Prepare to do a large-object operation. We *must* be inside a transaction + * block for all these operations, so start one if needed. + * + * Returns TRUE if okay, FALSE if failed. *own_transaction is set to indicate + * if we started our own transaction or not. + */ +static bool +start_lo_xact(const char *operation, bool *own_transaction) +{ + PGTransactionStatusType tstatus; + PGresult *res; + + *own_transaction = false; + + if (!pset.db) + { + psql_error("%s: not connected to a database\n", operation); + return false; + } + + tstatus = PQtransactionStatus(pset.db); + + switch (tstatus) + { + case PQTRANS_IDLE: + /* need to start our own xact */ + if (!(res = PSQLexec("BEGIN"))) + return false; + PQclear(res); + *own_transaction = true; + break; + case PQTRANS_INTRANS: + /* use the existing xact */ + break; + case PQTRANS_INERROR: + psql_error("%s: current transaction is aborted\n", operation); + return false; + default: + psql_error("%s: unknown transaction status\n", operation); + return false; + } + + return true; +} + +/* + * Clean up after a successful LO operation + */ +static bool +finish_lo_xact(const char *operation, bool own_transaction) +{ + PGresult *res; + + if (own_transaction && pset.autocommit) + { + /* close out our own xact */ + if (!(res = PSQLexec("COMMIT"))) + { + res = PSQLexec("ROLLBACK"); + PQclear(res); + return false; + } + PQclear(res); + } + + return true; +} + +/* + * Clean up after a failed LO operation + */ +static bool +fail_lo_xact(const char *operation, bool own_transaction) +{ + PGresult *res; + + if (own_transaction && pset.autocommit) + { + /* close out our own xact */ + res = PSQLexec("ROLLBACK"); + PQclear(res); + } + + return false; /* always */ +} + + +/* + * do_lo_export() + * + * Write a large object to a file + */ +bool +do_lo_export(const char *loid_arg, const char *filename_arg) +{ + int status; + bool own_transaction; + + if (!start_lo_xact("\\lo_export", &own_transaction)) + return false; + + SetCancelConn(); + status = lo_export(pset.db, atooid(loid_arg), filename_arg); + ResetCancelConn(); + + /* of course this status is documented nowhere :( */ + if (status != 1) + { + psql_error("%s", PQerrorMessage(pset.db)); + return fail_lo_xact("\\lo_export", own_transaction); + } + + if (!finish_lo_xact("\\lo_export", own_transaction)) + return false; + + print_lo_result("lo_export"); + + return true; +} + + +/* + * do_lo_import() + * + * Copy large object from file to database + */ +bool +do_lo_import(const char *filename_arg, const char *comment_arg) +{ + PGresult *res; + Oid loid; + char oidbuf[32]; + bool own_transaction; + + if (!start_lo_xact("\\lo_import", &own_transaction)) + return false; + + SetCancelConn(); + loid = lo_import(pset.db, filename_arg); + ResetCancelConn(); + + if (loid == InvalidOid) + { + psql_error("%s", PQerrorMessage(pset.db)); + return fail_lo_xact("\\lo_import", own_transaction); + } + + /* insert description if given */ + if (comment_arg) + { + char *cmdbuf; + char *bufptr; + size_t slen = strlen(comment_arg); + + cmdbuf = malloc(slen * 2 + 256); + if (!cmdbuf) + return fail_lo_xact("\\lo_import", own_transaction); + sprintf(cmdbuf, "COMMENT ON LARGE OBJECT %u IS '", loid); + bufptr = cmdbuf + strlen(cmdbuf); + bufptr += PQescapeStringConn(pset.db, bufptr, comment_arg, slen, NULL); + strcpy(bufptr, "'"); + + if (!(res = PSQLexec(cmdbuf))) + { + free(cmdbuf); + return fail_lo_xact("\\lo_import", own_transaction); + } + + PQclear(res); + free(cmdbuf); + } + + if (!finish_lo_xact("\\lo_import", own_transaction)) + return false; + + print_lo_result("lo_import %u", loid); + + sprintf(oidbuf, "%u", loid); + SetVariable(pset.vars, "LASTOID", oidbuf); + + return true; +} + + +/* + * do_lo_unlink() + * + * removes a large object out of the database + */ +bool +do_lo_unlink(const char *loid_arg) +{ + int status; + Oid loid = atooid(loid_arg); + bool own_transaction; + + if (!start_lo_xact("\\lo_unlink", &own_transaction)) + return false; + + SetCancelConn(); + status = lo_unlink(pset.db, loid); + ResetCancelConn(); + + if (status == -1) + { + psql_error("%s", PQerrorMessage(pset.db)); + return fail_lo_xact("\\lo_unlink", own_transaction); + } + + if (!finish_lo_xact("\\lo_unlink", own_transaction)) + return false; + + print_lo_result("lo_unlink %u", loid); + + return true; +} + + + +/* + * do_lo_list() + * + * Show all large objects in database with comments + */ +bool +do_lo_list(void) +{ + PGresult *res; + char buf[1024]; + printQueryOpt myopt = pset.popt; + + if (pset.sversion >= 90000) + { + snprintf(buf, sizeof(buf), + "SELECT oid as \"%s\",\n" + " pg_catalog.pg_get_userbyid(lomowner) as \"%s\",\n" + " pg_catalog.obj_description(oid, 'pg_largeobject') as \"%s\"\n" + " FROM pg_catalog.pg_largeobject_metadata " + " ORDER BY oid", + gettext_noop("ID"), + gettext_noop("Owner"), + gettext_noop("Description")); + } + else + { + snprintf(buf, sizeof(buf), + "SELECT loid as \"%s\",\n" + " pg_catalog.obj_description(loid, 'pg_largeobject') as \"%s\"\n" + "FROM (SELECT DISTINCT loid FROM pg_catalog.pg_largeobject) x\n" + "ORDER BY 1", + gettext_noop("ID"), + gettext_noop("Description")); + } + + res = PSQLexec(buf); + if (!res) + return false; + + myopt.topt.tuples_only = false; + myopt.nullPrint = NULL; + myopt.title = _("Large objects"); + myopt.translate_header = true; + + printQuery(res, &myopt, pset.queryFout, false, pset.logfile); + + PQclear(res); + return true; +} diff --git a/src/bin/csql/large_obj.h b/src/bin/csql/large_obj.h new file mode 100644 index 000000000..3d3780197 --- /dev/null +++ b/src/bin/csql/large_obj.h @@ -0,0 +1,16 @@ +/* + * psql - the PostgreSQL interactive terminal + * + * Copyright (c) 2000-2015, PostgreSQL Global Development Group + * + * src/bin/psql/large_obj.h + */ +#ifndef LARGE_OBJ_H +#define LARGE_OBJ_H + +bool do_lo_export(const char *loid_arg, const char *filename_arg); +bool do_lo_import(const char *filename_arg, const char *comment_arg); +bool do_lo_unlink(const char *loid_arg); +bool do_lo_list(void); + +#endif /* LARGE_OBJ_H */ diff --git a/src/bin/csql/mainloop.c b/src/bin/csql/mainloop.c new file mode 100644 index 000000000..507dd5986 --- /dev/null +++ b/src/bin/csql/mainloop.c @@ -0,0 +1,462 @@ +/* + * psql - the PostgreSQL interactive terminal + * + * Copyright (c) 2000-2015, PostgreSQL Global Development Group + * + * src/bin/psql/mainloop.c + */ +#include "postgres_fe.h" +#include "mainloop.h" + + +#include "command.h" +#include "common.h" +#include "input.h" +#include "settings.h" + +#include "mb/pg_wchar.h" + + +/* + * Main processing loop for reading lines of input + * and sending them to the backend. + * + * This loop is re-entrant. May be called by \i command + * which reads input from a file. + */ +int +MainLoop(FILE *source) +{ + PsqlScanState scan_state; /* lexer working state */ + volatile PQExpBuffer query_buf; /* buffer for query being accumulated */ + volatile PQExpBuffer previous_buf; /* if there isn't anything in the new + * buffer yet, use this one for \e, + * etc. */ + PQExpBuffer history_buf; /* earlier lines of a multi-line command, not + * yet saved to readline history */ + char *line; /* current line of input */ + int added_nl_pos; + bool success; + bool line_saved_in_history; + volatile int successResult = EXIT_SUCCESS; + volatile backslashResult slashCmdStatus = PSQL_CMD_UNKNOWN; + volatile promptStatus_t prompt_status = PROMPT_READY; + volatile int count_eof = 0; + volatile bool die_on_error = false; + + /* Save the prior command source */ + FILE *prev_cmd_source; + bool prev_cmd_interactive; + uint64 prev_lineno; + + /* Save old settings */ + prev_cmd_source = pset.cur_cmd_source; + prev_cmd_interactive = pset.cur_cmd_interactive; + prev_lineno = pset.lineno; + + /* Establish new source */ + pset.cur_cmd_source = source; + pset.cur_cmd_interactive = ((source == stdin) && !pset.notty); + pset.lineno = 0; + pset.stmt_lineno = 1; + + /* Create working state */ + scan_state = psql_scan_create(); + + query_buf = createPQExpBuffer(); + previous_buf = createPQExpBuffer(); + history_buf = createPQExpBuffer(); + if (PQExpBufferBroken(query_buf) || + PQExpBufferBroken(previous_buf) || + PQExpBufferBroken(history_buf)) + { + psql_error("out of memory\n"); + exit(EXIT_FAILURE); + } + + /* main loop to get queries and execute them */ + while (successResult == EXIT_SUCCESS) + { + /* + * Clean up after a previous Control-C + */ + if (cancel_pressed) + { + if (!pset.cur_cmd_interactive) + { + /* + * You get here if you stopped a script with Ctrl-C. + */ + successResult = EXIT_USER; + break; + } + + cancel_pressed = false; + } + + /* + * Establish longjmp destination for exiting from wait-for-input. We + * must re-do this each time through the loop for safety, since the + * jmpbuf might get changed during command execution. + */ + if (sigsetjmp(sigint_interrupt_jmp, 1) != 0) + { + /* got here with longjmp */ + + /* reset parsing state */ + psql_scan_finish(scan_state); + psql_scan_reset(scan_state); + resetPQExpBuffer(query_buf); + resetPQExpBuffer(history_buf); + count_eof = 0; + slashCmdStatus = PSQL_CMD_UNKNOWN; + prompt_status = PROMPT_READY; + pset.stmt_lineno = 1; + cancel_pressed = false; + + if (pset.cur_cmd_interactive) + putc('\n', stdout); + else + { + successResult = EXIT_USER; + break; + } + } + + fflush(stdout); + + /* + * get another line + */ + if (pset.cur_cmd_interactive) + { + /* May need to reset prompt, eg after \r command */ + if (query_buf->len == 0) + prompt_status = PROMPT_READY; + line = gets_interactive(get_prompt(prompt_status)); + } + else + { + line = gets_fromFile(source); + if (!line && ferror(source)) + successResult = EXIT_FAILURE; + } + + /* + * query_buf holds query already accumulated. line is the malloc'd + * new line of input (note it must be freed before looping around!) + */ + + /* No more input. Time to quit, or \i done */ + if (line == NULL) + { + if (pset.cur_cmd_interactive) + { + /* This tries to mimic bash's IGNOREEOF feature. */ + count_eof++; + + if (count_eof < GetVariableNum(pset.vars, "IGNOREEOF", 0, 10, false)) + { + if (!pset.quiet) + printf(_("Use \"\\q\" to leave %s.\n"), pset.progname); + continue; + } + + puts(pset.quiet ? "" : "\\q"); + } + break; + } + + count_eof = 0; + + pset.lineno++; + + /* ignore UTF-8 Unicode byte-order mark */ + if (pset.lineno == 1 && pset.encoding == PG_UTF8 && strncmp(line, "\xef\xbb\xbf", 3) == 0) + memmove(line, line + 3, strlen(line + 3) + 1); + + /* Detect attempts to run custom-format dumps as SQL scripts */ + if (pset.lineno == 1 && !pset.cur_cmd_interactive && + strncmp(line, "PGDMP", 5) == 0) + { + free(line); + puts(_("The input is a PostgreSQL custom-format dump.\n" + "Use the pg_restore command-line client to restore this dump to a database.\n")); + fflush(stdout); + successResult = EXIT_FAILURE; + break; + } + + /* no further processing of empty lines, unless within a literal */ + if (line[0] == '\0' && !psql_scan_in_quote(scan_state)) + { + free(line); + continue; + } + + /* A request for help? Be friendly and give them some guidance */ + if (pset.cur_cmd_interactive && query_buf->len == 0 && + pg_strncasecmp(line, "help", 4) == 0 && + (line[4] == '\0' || line[4] == ';' || isspace((unsigned char) line[4]))) + { + free(line); + puts(_("You are using csql, the command-line interface to CitusDB.")); + printf(_("Type: \\copyright for distribution terms\n" + " \\h for help with SQL commands\n" + " \\? for help with csql commands\n" + " \\g or terminate with semicolon to execute query\n" + " \\q to quit\n")); + + fflush(stdout); + continue; + } + + /* echo back if flag is set, unless interactive */ + if (pset.echo == PSQL_ECHO_ALL && !pset.cur_cmd_interactive) + { + puts(line); + fflush(stdout); + } + + /* insert newlines into query buffer between source lines */ + if (query_buf->len > 0) + { + appendPQExpBufferChar(query_buf, '\n'); + added_nl_pos = query_buf->len; + } + else + added_nl_pos = -1; /* flag we didn't add one */ + + /* Setting this will not have effect until next line. */ + die_on_error = pset.on_error_stop; + + /* + * Parse line, looking for command separators. + */ + psql_scan_setup(scan_state, line, strlen(line)); + success = true; + line_saved_in_history = false; + + while (success || !die_on_error) + { + PsqlScanResult scan_result; + promptStatus_t prompt_tmp = prompt_status; + size_t pos_in_query; + char *tmp_line; + + pos_in_query = query_buf->len; + scan_result = psql_scan(scan_state, query_buf, &prompt_tmp); + prompt_status = prompt_tmp; + + if (PQExpBufferBroken(query_buf)) + { + psql_error("out of memory\n"); + exit(EXIT_FAILURE); + } + + /* + * Increase statement line number counter for each linebreak added + * to the query buffer by the last psql_scan() call. There only + * will be ones to add when navigating to a statement in + * readline's history containing newlines. + */ + tmp_line = query_buf->data + pos_in_query; + while (*tmp_line != '\0') + { + if (*(tmp_line++) == '\n') + pset.stmt_lineno++; + } + + if (scan_result == PSCAN_EOL) + pset.stmt_lineno++; + + /* + * Send command if semicolon found, or if end of line and we're in + * single-line mode. + */ + if (scan_result == PSCAN_SEMICOLON || + (scan_result == PSCAN_EOL && pset.singleline)) + { + /* + * Save query in history. We use history_buf to accumulate + * multi-line queries into a single history entry. + */ + if (pset.cur_cmd_interactive && !line_saved_in_history) + { + pg_append_history(line, history_buf); + pg_send_history(history_buf); + line_saved_in_history = true; + } + + /* execute query */ + success = SendQuery(query_buf->data); + slashCmdStatus = success ? PSQL_CMD_SEND : PSQL_CMD_ERROR; + pset.stmt_lineno = 1; + + /* transfer query to previous_buf by pointer-swapping */ + { + PQExpBuffer swap_buf = previous_buf; + + previous_buf = query_buf; + query_buf = swap_buf; + } + resetPQExpBuffer(query_buf); + + added_nl_pos = -1; + /* we need not do psql_scan_reset() here */ + } + else if (scan_result == PSCAN_BACKSLASH) + { + /* handle backslash command */ + + /* + * If we added a newline to query_buf, and nothing else has + * been inserted in query_buf by the lexer, then strip off the + * newline again. This avoids any change to query_buf when a + * line contains only a backslash command. Also, in this + * situation we force out any previous lines as a separate + * history entry; we don't want SQL and backslash commands + * intermixed in history if at all possible. + */ + if (query_buf->len == added_nl_pos) + { + query_buf->data[--query_buf->len] = '\0'; + pg_send_history(history_buf); + } + added_nl_pos = -1; + + /* save backslash command in history */ + if (pset.cur_cmd_interactive && !line_saved_in_history) + { + pg_append_history(line, history_buf); + pg_send_history(history_buf); + line_saved_in_history = true; + } + + /* execute backslash command */ + slashCmdStatus = HandleSlashCmds(scan_state, + query_buf->len > 0 ? + query_buf : previous_buf); + + success = slashCmdStatus != PSQL_CMD_ERROR; + pset.stmt_lineno = 1; + + if ((slashCmdStatus == PSQL_CMD_SEND || slashCmdStatus == PSQL_CMD_NEWEDIT) && + query_buf->len == 0) + { + /* copy previous buffer to current for handling */ + appendPQExpBufferStr(query_buf, previous_buf->data); + } + + if (slashCmdStatus == PSQL_CMD_SEND) + { + success = SendQuery(query_buf->data); + + /* transfer query to previous_buf by pointer-swapping */ + { + PQExpBuffer swap_buf = previous_buf; + + previous_buf = query_buf; + query_buf = swap_buf; + } + resetPQExpBuffer(query_buf); + + /* flush any paren nesting info after forced send */ + psql_scan_reset(scan_state); + } + else if (slashCmdStatus == PSQL_CMD_NEWEDIT) + { + /* rescan query_buf as new input */ + psql_scan_finish(scan_state); + free(line); + line = pg_strdup(query_buf->data); + resetPQExpBuffer(query_buf); + /* reset parsing state since we are rescanning whole line */ + psql_scan_reset(scan_state); + psql_scan_setup(scan_state, line, strlen(line)); + line_saved_in_history = false; + prompt_status = PROMPT_READY; + } + else if (slashCmdStatus == PSQL_CMD_TERMINATE) + break; + } + + /* fall out of loop if lexer reached EOL */ + if (scan_result == PSCAN_INCOMPLETE || + scan_result == PSCAN_EOL) + break; + } + + /* Add line to pending history if we didn't execute anything yet */ + if (pset.cur_cmd_interactive && !line_saved_in_history) + pg_append_history(line, history_buf); + + psql_scan_finish(scan_state); + free(line); + + if (slashCmdStatus == PSQL_CMD_TERMINATE) + { + successResult = EXIT_SUCCESS; + break; + } + + if (!pset.cur_cmd_interactive) + { + if (!success && die_on_error) + successResult = EXIT_USER; + /* Have we lost the db connection? */ + else if (!pset.db) + successResult = EXIT_BADCONN; + } + } /* while !endoffile/session */ + + /* + * Process query at the end of file without a semicolon + */ + if (query_buf->len > 0 && !pset.cur_cmd_interactive && + successResult == EXIT_SUCCESS) + { + /* save query in history */ + if (pset.cur_cmd_interactive) + pg_send_history(history_buf); + + /* execute query */ + success = SendQuery(query_buf->data); + + if (!success && die_on_error) + successResult = EXIT_USER; + else if (pset.db == NULL) + successResult = EXIT_BADCONN; + } + + /* + * Let's just make real sure the SIGINT handler won't try to use + * sigint_interrupt_jmp after we exit this routine. If there is an outer + * MainLoop instance, it will reset sigint_interrupt_jmp to point to + * itself at the top of its loop, before any further interactive input + * happens. + */ + sigint_interrupt_enabled = false; + + destroyPQExpBuffer(query_buf); + destroyPQExpBuffer(previous_buf); + destroyPQExpBuffer(history_buf); + + psql_scan_destroy(scan_state); + + pset.cur_cmd_source = prev_cmd_source; + pset.cur_cmd_interactive = prev_cmd_interactive; + pset.lineno = prev_lineno; + + return successResult; +} /* MainLoop() */ + + +/* + * psqlscan.c is #include'd here instead of being compiled on its own. + * This is because we need postgres_fe.h to be read before any system + * include files, else things tend to break on platforms that have + * multiple infrastructures for stdio.h and so on. flex is absolutely + * uncooperative about that, so we can't compile psqlscan.c on its own. + */ +#include "psqlscan.c" diff --git a/src/bin/csql/mainloop.h b/src/bin/csql/mainloop.h new file mode 100644 index 000000000..8f1325c4f --- /dev/null +++ b/src/bin/csql/mainloop.h @@ -0,0 +1,15 @@ +/* + * psql - the PostgreSQL interactive terminal + * + * Copyright (c) 2000-2015, PostgreSQL Global Development Group + * + * src/bin/psql/mainloop.h + */ +#ifndef MAINLOOP_H +#define MAINLOOP_H + +#include "postgres_fe.h" + +int MainLoop(FILE *source); + +#endif /* MAINLOOP_H */ diff --git a/src/bin/csql/mbprint.c b/src/bin/csql/mbprint.c new file mode 100644 index 000000000..e29c61902 --- /dev/null +++ b/src/bin/csql/mbprint.c @@ -0,0 +1,398 @@ +/* + * psql - the PostgreSQL interactive terminal + * + * Copyright (c) 2000-2015, PostgreSQL Global Development Group + * + * src/bin/psql/mbprint.c + * + * XXX this file does not really belong in psql/. Perhaps move to libpq? + * It also seems that the mbvalidate function is redundant with existing + * functionality. + */ + +#include "postgres_fe.h" +#include "mbprint.h" +#ifndef PGSCRIPTS +#include "settings.h" +#endif + +/* + * To avoid version-skew problems, this file must not use declarations + * from pg_wchar.h: the encoding IDs we are dealing with are determined + * by the libpq.so we are linked with, and that might not match the + * numbers we see at compile time. (If this file were inside libpq, + * the problem would go away...) + * + * Hence, we have our own definition of pg_wchar, and we get the values + * of any needed encoding IDs on-the-fly. + */ + +typedef unsigned int pg_wchar; + +static int +pg_get_utf8_id(void) +{ + static int utf8_id = -1; + + if (utf8_id < 0) + utf8_id = pg_char_to_encoding("utf8"); + return utf8_id; +} + +#define PG_UTF8 pg_get_utf8_id() + + +/* + * Convert a UTF-8 character to a Unicode code point. + * This is a one-character version of pg_utf2wchar_with_len. + * + * No error checks here, c must point to a long-enough string. + */ +static pg_wchar +utf8_to_unicode(const unsigned char *c) +{ + if ((*c & 0x80) == 0) + return (pg_wchar) c[0]; + else if ((*c & 0xe0) == 0xc0) + return (pg_wchar) (((c[0] & 0x1f) << 6) | + (c[1] & 0x3f)); + else if ((*c & 0xf0) == 0xe0) + return (pg_wchar) (((c[0] & 0x0f) << 12) | + ((c[1] & 0x3f) << 6) | + (c[2] & 0x3f)); + else if ((*c & 0xf8) == 0xf0) + return (pg_wchar) (((c[0] & 0x07) << 18) | + ((c[1] & 0x3f) << 12) | + ((c[2] & 0x3f) << 6) | + (c[3] & 0x3f)); + else + /* that is an invalid code on purpose */ + return 0xffffffff; +} + + +/* + * Unicode 3.1 compliant validation : for each category, it checks the + * combination of each byte to make sure it maps to a valid range. It also + * returns -1 for the following UCS values: ucs > 0x10ffff ucs & 0xfffe = + * 0xfffe 0xfdd0 < ucs < 0xfdef ucs & 0xdb00 = 0xd800 (surrogates) + */ +static int +utf_charcheck(const unsigned char *c) +{ + if ((*c & 0x80) == 0) + return 1; + else if ((*c & 0xe0) == 0xc0) + { + /* two-byte char */ + if (((c[1] & 0xc0) == 0x80) && ((c[0] & 0x1f) > 0x01)) + return 2; + return -1; + } + else if ((*c & 0xf0) == 0xe0) + { + /* three-byte char */ + if (((c[1] & 0xc0) == 0x80) && + (((c[0] & 0x0f) != 0x00) || ((c[1] & 0x20) == 0x20)) && + ((c[2] & 0xc0) == 0x80)) + { + int z = c[0] & 0x0f; + int yx = ((c[1] & 0x3f) << 6) | (c[0] & 0x3f); + int lx = yx & 0x7f; + + /* check 0xfffe/0xffff, 0xfdd0..0xfedf range, surrogates */ + if (((z == 0x0f) && + (((yx & 0xffe) == 0xffe) || + (((yx & 0xf80) == 0xd80) && (lx >= 0x30) && (lx <= 0x4f)))) || + ((z == 0x0d) && ((yx & 0xb00) == 0x800))) + return -1; + return 3; + } + return -1; + } + else if ((*c & 0xf8) == 0xf0) + { + int u = ((c[0] & 0x07) << 2) | ((c[1] & 0x30) >> 4); + + /* four-byte char */ + if (((c[1] & 0xc0) == 0x80) && + (u > 0x00) && (u <= 0x10) && + ((c[2] & 0xc0) == 0x80) && ((c[3] & 0xc0) == 0x80)) + { + /* test for 0xzzzzfffe/0xzzzzfffff */ + if (((c[1] & 0x0f) == 0x0f) && ((c[2] & 0x3f) == 0x3f) && + ((c[3] & 0x3e) == 0x3e)) + return -1; + return 4; + } + return -1; + } + return -1; +} + + +static void +mb_utf_validate(unsigned char *pwcs) +{ + unsigned char *p = pwcs; + + while (*pwcs) + { + int len; + + if ((len = utf_charcheck(pwcs)) > 0) + { + if (p != pwcs) + { + int i; + + for (i = 0; i < len; i++) + *p++ = *pwcs++; + } + else + { + pwcs += len; + p += len; + } + } + else + /* we skip the char */ + pwcs++; + } + if (p != pwcs) + *p = '\0'; +} + +/* + * public functions : wcswidth and mbvalidate + */ + +/* + * pg_wcswidth is the dumb display-width function. + * It assumes that everything will appear on one line. + * OTOH it is easier to use than pg_wcssize if this applies to you. + */ +int +pg_wcswidth(const char *pwcs, size_t len, int encoding) +{ + int width = 0; + + while (len > 0) + { + int chlen, + chwidth; + + chlen = PQmblen(pwcs, encoding); + if (len < (size_t) chlen) + break; /* Invalid string */ + + chwidth = PQdsplen(pwcs, encoding); + if (chwidth > 0) + width += chwidth; + + pwcs += chlen; + len -= chlen; + } + return width; +} + +/* + * pg_wcssize takes the given string in the given encoding and returns three + * values: + * result_width: Width in display characters of the longest line in string + * result_height: Number of lines in display output + * result_format_size: Number of bytes required to store formatted + * representation of string + * + * This MUST be kept in sync with pg_wcsformat! + */ +void +pg_wcssize(const unsigned char *pwcs, size_t len, int encoding, + int *result_width, int *result_height, int *result_format_size) +{ + int w, + chlen = 0, + linewidth = 0; + int width = 0; + int height = 1; + int format_size = 0; + + for (; *pwcs && len > 0; pwcs += chlen) + { + chlen = PQmblen((const char *) pwcs, encoding); + if (len < (size_t) chlen) + break; + w = PQdsplen((const char *) pwcs, encoding); + + if (chlen == 1) /* single-byte char */ + { + if (*pwcs == '\n') /* Newline */ + { + if (linewidth > width) + width = linewidth; + linewidth = 0; + height += 1; + format_size += 1; /* For NUL char */ + } + else if (*pwcs == '\r') /* Linefeed */ + { + linewidth += 2; + format_size += 2; + } + else if (*pwcs == '\t') /* Tab */ + { + do + { + linewidth++; + format_size++; + } while (linewidth % 8 != 0); + } + else if (w < 0) /* Other control char */ + { + linewidth += 4; + format_size += 4; + } + else /* Output it as-is */ + { + linewidth += w; + format_size += 1; + } + } + else if (w < 0) /* Non-ascii control char */ + { + linewidth += 6; /* \u0000 */ + format_size += 6; + } + else /* All other chars */ + { + linewidth += w; + format_size += chlen; + } + len -= chlen; + } + if (linewidth > width) + width = linewidth; + format_size += 1; /* For NUL char */ + + /* Set results */ + if (result_width) + *result_width = width; + if (result_height) + *result_height = height; + if (result_format_size) + *result_format_size = format_size; +} + +/* + * Format a string into one or more "struct lineptr" lines. + * lines[i].ptr == NULL indicates the end of the array. + * + * This MUST be kept in sync with pg_wcssize! + */ +void +pg_wcsformat(const unsigned char *pwcs, size_t len, int encoding, + struct lineptr * lines, int count) +{ + int w, + chlen = 0; + int linewidth = 0; + unsigned char *ptr = lines->ptr; /* Pointer to data area */ + + for (; *pwcs && len > 0; pwcs += chlen) + { + chlen = PQmblen((const char *) pwcs, encoding); + if (len < (size_t) chlen) + break; + w = PQdsplen((const char *) pwcs, encoding); + + if (chlen == 1) /* single-byte char */ + { + if (*pwcs == '\n') /* Newline */ + { + *ptr++ = '\0'; + lines->width = linewidth; + linewidth = 0; + lines++; + count--; + if (count <= 0) + exit(1); /* Screwup */ + + /* make next line point to remaining memory */ + lines->ptr = ptr; + } + else if (*pwcs == '\r') /* Linefeed */ + { + strcpy((char *) ptr, "\\r"); + linewidth += 2; + ptr += 2; + } + else if (*pwcs == '\t') /* Tab */ + { + do + { + *ptr++ = ' '; + linewidth++; + } while (linewidth % 8 != 0); + } + else if (w < 0) /* Other control char */ + { + sprintf((char *) ptr, "\\x%02X", *pwcs); + linewidth += 4; + ptr += 4; + } + else /* Output it as-is */ + { + linewidth += w; + *ptr++ = *pwcs; + } + } + else if (w < 0) /* Non-ascii control char */ + { + if (encoding == PG_UTF8) + sprintf((char *) ptr, "\\u%04X", utf8_to_unicode(pwcs)); + else + { + /* + * This case cannot happen in the current code because only + * UTF-8 signals multibyte control characters. But we may need + * to support it at some stage + */ + sprintf((char *) ptr, "\\u????"); + } + ptr += 6; + linewidth += 6; + } + else /* All other chars */ + { + int i; + + for (i = 0; i < chlen; i++) + *ptr++ = pwcs[i]; + linewidth += w; + } + len -= chlen; + } + lines->width = linewidth; + *ptr++ = '\0'; /* Terminate formatted string */ + + if (count <= 0) + exit(1); /* Screwup */ + + (lines + 1)->ptr = NULL; /* terminate line array */ +} + +unsigned char * +mbvalidate(unsigned char *pwcs, int encoding) +{ + if (encoding == PG_UTF8) + mb_utf_validate(pwcs); + else + { + /* + * other encodings needing validation should add their own routines + * here + */ + } + + return pwcs; +} diff --git a/src/bin/csql/mbprint.h b/src/bin/csql/mbprint.h new file mode 100644 index 000000000..01064d310 --- /dev/null +++ b/src/bin/csql/mbprint.h @@ -0,0 +1,18 @@ +/* src/bin/psql/mbprint.h */ +#ifndef MBPRINT_H +#define MBPRINT_H + + +struct lineptr +{ + unsigned char *ptr; + int width; +}; + +extern unsigned char *mbvalidate(unsigned char *pwcs, int encoding); +extern int pg_wcswidth(const char *pwcs, size_t len, int encoding); +extern void pg_wcsformat(const unsigned char *pwcs, size_t len, int encoding, struct lineptr * lines, int count); +extern void pg_wcssize(const unsigned char *pwcs, size_t len, int encoding, + int *width, int *height, int *format_size); + +#endif /* MBPRINT_H */ diff --git a/src/bin/csql/print.c b/src/bin/csql/print.c new file mode 100644 index 000000000..05d4b3162 --- /dev/null +++ b/src/bin/csql/print.c @@ -0,0 +1,3495 @@ +/* + * psql - the PostgreSQL interactive terminal + * + * Copyright (c) 2000-2015, PostgreSQL Global Development Group + * + * src/bin/psql/print.c + */ +#include "postgres_fe.h" + +#include +#include +#include +#include + +#ifndef WIN32 +#include /* for ioctl() */ +#endif + +#ifdef HAVE_TERMIOS_H +#include +#endif + +#include + +#include "catalog/pg_type.h" + +#include "common.h" +#include "mbprint.h" +#include "print.h" + +/* + * We define the cancel_pressed flag in this file, rather than common.c where + * it naturally belongs, because this file is also used by non-psql programs + * (see the bin/scripts/ directory). In those programs cancel_pressed will + * never become set and will have no effect. + * + * Note: print.c's general strategy for when to check cancel_pressed is to do + * so at completion of each row of output. + */ +volatile bool cancel_pressed = false; + +/* + * Likewise, the sigpipe_trap and pager open/close functions are here rather + * than in common.c so that this file can be used by non-psql programs. + */ +static bool always_ignore_sigpipe = false; + + +/* info for locale-aware numeric formatting; set up by setDecimalLocale() */ +static char *decimal_point; +static int groupdigits; +static char *thousands_sep; + +static char default_footer[100]; +static printTableFooter default_footer_cell = {default_footer, NULL}; + +/* Line style control structures */ +const printTextFormat pg_asciiformat = +{ + "ascii", + { + {"-", "+", "+", "+"}, + {"-", "+", "+", "+"}, + {"-", "+", "+", "+"}, + {"", "|", "|", "|"} + }, + "|", + "|", + "|", + " ", + "+", + " ", + "+", + ".", + ".", + true +}; + +const printTextFormat pg_asciiformat_old = +{ + "old-ascii", + { + {"-", "+", "+", "+"}, + {"-", "+", "+", "+"}, + {"-", "+", "+", "+"}, + {"", "|", "|", "|"} + }, + ":", + ";", + " ", + "+", + " ", + " ", + " ", + " ", + " ", + false +}; + +/* Default unicode linestyle format */ +const printTextFormat pg_utf8format; + +typedef struct unicodeStyleRowFormat +{ + const char *horizontal; + const char *vertical_and_right[2]; + const char *vertical_and_left[2]; +} unicodeStyleRowFormat; + +typedef struct unicodeStyleColumnFormat +{ + const char *vertical; + const char *vertical_and_horizontal[2]; + const char *up_and_horizontal[2]; + const char *down_and_horizontal[2]; +} unicodeStyleColumnFormat; + +typedef struct unicodeStyleBorderFormat +{ + const char *up_and_right; + const char *vertical; + const char *down_and_right; + const char *horizontal; + const char *down_and_left; + const char *left_and_right; +} unicodeStyleBorderFormat; + +typedef struct unicodeStyleFormat +{ + unicodeStyleRowFormat row_style[2]; + unicodeStyleColumnFormat column_style[2]; + unicodeStyleBorderFormat border_style[2]; + const char *header_nl_left; + const char *header_nl_right; + const char *nl_left; + const char *nl_right; + const char *wrap_left; + const char *wrap_right; + bool wrap_right_border; +} unicodeStyleFormat; + +const unicodeStyleFormat unicode_style = { + { + { + /* ─ */ + "\342\224\200", + /* ├╟ */ + {"\342\224\234", "\342\225\237"}, + /* ┤╢ */ + {"\342\224\244", "\342\225\242"}, + }, + { + /* ═ */ + "\342\225\220", + /* ╞╠ */ + {"\342\225\236", "\342\225\240"}, + /* ╡╣ */ + {"\342\225\241", "\342\225\243"}, + }, + }, + { + { + /* │ */ + "\342\224\202", + /* ┼╪ */ + {"\342\224\274", "\342\225\252"}, + /* ┴╧ */ + {"\342\224\264", "\342\225\247"}, + /* ┬╤ */ + {"\342\224\254", "\342\225\244"}, + }, + { + /* ║ */ + "\342\225\221", + /* ╫╬ */ + {"\342\225\253", "\342\225\254"}, + /* ╨╩ */ + {"\342\225\250", "\342\225\251"}, + /* ╥╦ */ + {"\342\225\245", "\342\225\246"}, + }, + }, + { + /* └│┌─┐┘ */ + {"\342\224\224", "\342\224\202", "\342\224\214", "\342\224\200", "\342\224\220", "\342\224\230"}, + /* ╚║╔═╗╝ */ + {"\342\225\232", "\342\225\221", "\342\225\224", "\342\225\220", "\342\225\227", "\342\225\235"}, + }, + " ", + "\342\206\265", /* ↵ */ + " ", + "\342\206\265", /* ↵ */ + "\342\200\246", /* … */ + "\342\200\246", /* … */ + true +}; + + +/* Local functions */ +static int strlen_max_width(unsigned char *str, int *target_width, int encoding); +static void IsPagerNeeded(const printTableContent *cont, int extra_lines, bool expanded, + FILE **fout, bool *is_pager); + +static void print_aligned_vertical(const printTableContent *cont, + FILE *fout, bool is_pager); + + +/* Count number of digits in integral part of number */ +static int +integer_digits(const char *my_str) +{ + /* ignoring any sign ... */ + if (my_str[0] == '-' || my_str[0] == '+') + my_str++; + /* ... count initial integral digits */ + return strspn(my_str, "0123456789"); +} + +/* Compute additional length required for locale-aware numeric output */ +static int +additional_numeric_locale_len(const char *my_str) +{ + int int_len = integer_digits(my_str), + len = 0; + + /* Account for added thousands_sep instances */ + if (int_len > groupdigits) + len += ((int_len - 1) / groupdigits) * strlen(thousands_sep); + + /* Account for possible additional length of decimal_point */ + if (strchr(my_str, '.') != NULL) + len += strlen(decimal_point) - 1; + + return len; +} + +/* + * Format a numeric value per current LC_NUMERIC locale setting + * + * Returns the appropriately formatted string in a new allocated block, + * caller must free. + * + * setDecimalLocale() must have been called earlier. + */ +static char * +format_numeric_locale(const char *my_str) +{ + char *new_str; + int new_len, + int_len, + leading_digits, + i, + new_str_pos; + + /* + * If the string doesn't look like a number, return it unchanged. This + * check is essential to avoid mangling already-localized "money" values. + */ + if (strspn(my_str, "0123456789+-.eE") != strlen(my_str)) + return pg_strdup(my_str); + + new_len = strlen(my_str) + additional_numeric_locale_len(my_str); + new_str = pg_malloc(new_len + 1); + new_str_pos = 0; + int_len = integer_digits(my_str); + + /* number of digits in first thousands group */ + leading_digits = int_len % groupdigits; + if (leading_digits == 0) + leading_digits = groupdigits; + + /* process sign */ + if (my_str[0] == '-' || my_str[0] == '+') + { + new_str[new_str_pos++] = my_str[0]; + my_str++; + } + + /* process integer part of number */ + for (i = 0; i < int_len; i++) + { + /* Time to insert separator? */ + if (i > 0 && --leading_digits == 0) + { + strcpy(&new_str[new_str_pos], thousands_sep); + new_str_pos += strlen(thousands_sep); + leading_digits = groupdigits; + } + new_str[new_str_pos++] = my_str[i]; + } + + /* handle decimal point if any */ + if (my_str[i] == '.') + { + strcpy(&new_str[new_str_pos], decimal_point); + new_str_pos += strlen(decimal_point); + i++; + } + + /* copy the rest (fractional digits and/or exponent, and \0 terminator) */ + strcpy(&new_str[new_str_pos], &my_str[i]); + + /* assert we didn't underestimate new_len (an overestimate is OK) */ + Assert(strlen(new_str) <= new_len); + + return new_str; +} + + +/* + * fputnbytes: print exactly N bytes to a file + * + * We avoid using %.*s here because it can misbehave if the data + * is not valid in what libc thinks is the prevailing encoding. + */ +static void +fputnbytes(FILE *f, const char *str, size_t n) +{ + while (n-- > 0) + fputc(*str++, f); +} + + +static void +print_separator(struct separator sep, FILE *fout) +{ + if (sep.separator_zero) + fputc('\000', fout); + else if (sep.separator) + fputs(sep.separator, fout); +} + + +/* + * Return the list of explicitly-requested footers or, when applicable, the + * default "(xx rows)" footer. Always omit the default footer when given + * non-default footers, "\pset footer off", or a specific instruction to that + * effect from a calling backslash command. Vertical formats number each row, + * making the default footer redundant; they do not call this function. + * + * The return value may point to static storage; do not keep it across calls. + */ +static printTableFooter * +footers_with_default(const printTableContent *cont) +{ + if (cont->footers == NULL && cont->opt->default_footer) + { + unsigned long total_records; + + total_records = cont->opt->prior_records + cont->nrows; + snprintf(default_footer, sizeof(default_footer), + ngettext("(%lu row)", "(%lu rows)", total_records), + total_records); + + return &default_footer_cell; + } + else + return cont->footers; +} + + +/*************************/ +/* Unaligned text */ +/*************************/ + + +static void +print_unaligned_text(const printTableContent *cont, FILE *fout) +{ + bool opt_tuples_only = cont->opt->tuples_only; + unsigned int i; + const char *const * ptr; + bool need_recordsep = false; + + if (cancel_pressed) + return; + + if (cont->opt->start_table) + { + /* print title */ + if (!opt_tuples_only && cont->title) + { + fputs(cont->title, fout); + print_separator(cont->opt->recordSep, fout); + } + + /* print headers */ + if (!opt_tuples_only) + { + for (ptr = cont->headers; *ptr; ptr++) + { + if (ptr != cont->headers) + print_separator(cont->opt->fieldSep, fout); + fputs(*ptr, fout); + } + need_recordsep = true; + } + } + else + /* assume continuing printout */ + need_recordsep = true; + + /* print cells */ + for (i = 0, ptr = cont->cells; *ptr; i++, ptr++) + { + if (need_recordsep) + { + print_separator(cont->opt->recordSep, fout); + need_recordsep = false; + if (cancel_pressed) + break; + } + fputs(*ptr, fout); + + if ((i + 1) % cont->ncolumns) + print_separator(cont->opt->fieldSep, fout); + else + need_recordsep = true; + } + + /* print footers */ + if (cont->opt->stop_table) + { + printTableFooter *footers = footers_with_default(cont); + + if (!opt_tuples_only && footers != NULL && !cancel_pressed) + { + printTableFooter *f; + + for (f = footers; f; f = f->next) + { + if (need_recordsep) + { + print_separator(cont->opt->recordSep, fout); + need_recordsep = false; + } + fputs(f->data, fout); + need_recordsep = true; + } + } + + /* + * The last record is terminated by a newline, independent of the set + * record separator. But when the record separator is a zero byte, we + * use that (compatible with find -print0 and xargs). + */ + if (need_recordsep) + { + if (cont->opt->recordSep.separator_zero) + print_separator(cont->opt->recordSep, fout); + else + fputc('\n', fout); + } + } +} + + +static void +print_unaligned_vertical(const printTableContent *cont, FILE *fout) +{ + bool opt_tuples_only = cont->opt->tuples_only; + unsigned int i; + const char *const * ptr; + bool need_recordsep = false; + + if (cancel_pressed) + return; + + if (cont->opt->start_table) + { + /* print title */ + if (!opt_tuples_only && cont->title) + { + fputs(cont->title, fout); + need_recordsep = true; + } + } + else + /* assume continuing printout */ + need_recordsep = true; + + /* print records */ + for (i = 0, ptr = cont->cells; *ptr; i++, ptr++) + { + if (need_recordsep) + { + /* record separator is 2 occurrences of recordsep in this mode */ + print_separator(cont->opt->recordSep, fout); + print_separator(cont->opt->recordSep, fout); + need_recordsep = false; + if (cancel_pressed) + break; + } + + fputs(cont->headers[i % cont->ncolumns], fout); + print_separator(cont->opt->fieldSep, fout); + fputs(*ptr, fout); + + if ((i + 1) % cont->ncolumns) + print_separator(cont->opt->recordSep, fout); + else + need_recordsep = true; + } + + if (cont->opt->stop_table) + { + /* print footers */ + if (!opt_tuples_only && cont->footers != NULL && !cancel_pressed) + { + printTableFooter *f; + + print_separator(cont->opt->recordSep, fout); + for (f = cont->footers; f; f = f->next) + { + print_separator(cont->opt->recordSep, fout); + fputs(f->data, fout); + } + } + + /* see above in print_unaligned_text() */ + if (need_recordsep) + { + if (cont->opt->recordSep.separator_zero) + print_separator(cont->opt->recordSep, fout); + else + fputc('\n', fout); + } + } +} + + +/********************/ +/* Aligned text */ +/********************/ + + +/* draw "line" */ +static void +_print_horizontal_line(const unsigned int ncolumns, const unsigned int *widths, + unsigned short border, printTextRule pos, + const printTextFormat *format, + FILE *fout) +{ + const printTextLineFormat *lformat = &format->lrule[pos]; + unsigned int i, + j; + + if (border == 1) + fputs(lformat->hrule, fout); + else if (border == 2) + fprintf(fout, "%s%s", lformat->leftvrule, lformat->hrule); + + for (i = 0; i < ncolumns; i++) + { + for (j = 0; j < widths[i]; j++) + fputs(lformat->hrule, fout); + + if (i < ncolumns - 1) + { + if (border == 0) + fputc(' ', fout); + else + fprintf(fout, "%s%s%s", lformat->hrule, + lformat->midvrule, lformat->hrule); + } + } + + if (border == 2) + fprintf(fout, "%s%s", lformat->hrule, lformat->rightvrule); + else if (border == 1) + fputs(lformat->hrule, fout); + + fputc('\n', fout); +} + + +/* + * Print pretty boxes around cells. + */ +static void +print_aligned_text(const printTableContent *cont, FILE *fout, bool is_pager) +{ + bool opt_tuples_only = cont->opt->tuples_only; + int encoding = cont->opt->encoding; + unsigned short opt_border = cont->opt->border; + const printTextFormat *format = get_line_style(cont->opt); + const printTextLineFormat *dformat = &format->lrule[PRINT_RULE_DATA]; + + unsigned int col_count = 0, + cell_count = 0; + + unsigned int i, + j; + + unsigned int *width_header, + *max_width, + *width_wrap, + *width_average; + unsigned int *max_nl_lines, /* value split by newlines */ + *curr_nl_line, + *max_bytes; + unsigned char **format_buf; + unsigned int width_total; + unsigned int total_header_width; + unsigned int extra_row_output_lines = 0; + unsigned int extra_output_lines = 0; + + const char *const * ptr; + + struct lineptr **col_lineptrs; /* pointers to line pointer per column */ + + bool *header_done; /* Have all header lines been output? */ + int *bytes_output; /* Bytes output for column value */ + printTextLineWrap *wrap; /* Wrap status for each column */ + int output_columns = 0; /* Width of interactive console */ + bool is_local_pager = false; + + if (cancel_pressed) + return; + + if (opt_border > 2) + opt_border = 2; + + if (cont->ncolumns > 0) + { + col_count = cont->ncolumns; + width_header = pg_malloc0(col_count * sizeof(*width_header)); + width_average = pg_malloc0(col_count * sizeof(*width_average)); + max_width = pg_malloc0(col_count * sizeof(*max_width)); + width_wrap = pg_malloc0(col_count * sizeof(*width_wrap)); + max_nl_lines = pg_malloc0(col_count * sizeof(*max_nl_lines)); + curr_nl_line = pg_malloc0(col_count * sizeof(*curr_nl_line)); + col_lineptrs = pg_malloc0(col_count * sizeof(*col_lineptrs)); + max_bytes = pg_malloc0(col_count * sizeof(*max_bytes)); + format_buf = pg_malloc0(col_count * sizeof(*format_buf)); + header_done = pg_malloc0(col_count * sizeof(*header_done)); + bytes_output = pg_malloc0(col_count * sizeof(*bytes_output)); + wrap = pg_malloc0(col_count * sizeof(*wrap)); + } + else + { + width_header = NULL; + width_average = NULL; + max_width = NULL; + width_wrap = NULL; + max_nl_lines = NULL; + curr_nl_line = NULL; + col_lineptrs = NULL; + max_bytes = NULL; + format_buf = NULL; + header_done = NULL; + bytes_output = NULL; + wrap = NULL; + } + + /* scan all column headers, find maximum width and max max_nl_lines */ + for (i = 0; i < col_count; i++) + { + int width, + nl_lines, + bytes_required; + + pg_wcssize((const unsigned char *) cont->headers[i], strlen(cont->headers[i]), + encoding, &width, &nl_lines, &bytes_required); + if (width > max_width[i]) + max_width[i] = width; + if (nl_lines > max_nl_lines[i]) + max_nl_lines[i] = nl_lines; + if (bytes_required > max_bytes[i]) + max_bytes[i] = bytes_required; + if (nl_lines > extra_row_output_lines) + extra_row_output_lines = nl_lines; + + width_header[i] = width; + } + /* Add height of tallest header column */ + extra_output_lines += extra_row_output_lines; + extra_row_output_lines = 0; + + /* scan all cells, find maximum width, compute cell_count */ + for (i = 0, ptr = cont->cells; *ptr; ptr++, i++, cell_count++) + { + int width, + nl_lines, + bytes_required; + + pg_wcssize((const unsigned char *) *ptr, strlen(*ptr), encoding, + &width, &nl_lines, &bytes_required); + + if (width > max_width[i % col_count]) + max_width[i % col_count] = width; + if (nl_lines > max_nl_lines[i % col_count]) + max_nl_lines[i % col_count] = nl_lines; + if (bytes_required > max_bytes[i % col_count]) + max_bytes[i % col_count] = bytes_required; + + width_average[i % col_count] += width; + } + + /* If we have rows, compute average */ + if (col_count != 0 && cell_count != 0) + { + int rows = cell_count / col_count; + + for (i = 0; i < col_count; i++) + width_average[i] /= rows; + } + + /* adjust the total display width based on border style */ + if (opt_border == 0) + width_total = col_count; + else if (opt_border == 1) + width_total = col_count * 3 - ((col_count > 0) ? 1 : 0); + else + width_total = col_count * 3 + 1; + total_header_width = width_total; + + for (i = 0; i < col_count; i++) + { + width_total += max_width[i]; + total_header_width += width_header[i]; + } + + /* + * At this point: max_width[] contains the max width of each column, + * max_nl_lines[] contains the max number of lines in each column, + * max_bytes[] contains the maximum storage space for formatting strings, + * width_total contains the giant width sum. Now we allocate some memory + * for line pointers. + */ + for (i = 0; i < col_count; i++) + { + /* Add entry for ptr == NULL array termination */ + col_lineptrs[i] = pg_malloc0((max_nl_lines[i] + 1) * + sizeof(**col_lineptrs)); + + format_buf[i] = pg_malloc(max_bytes[i] + 1); + + col_lineptrs[i]->ptr = format_buf[i]; + } + + /* Default word wrap to the full width, i.e. no word wrap */ + for (i = 0; i < col_count; i++) + width_wrap[i] = max_width[i]; + + /* + * Choose target output width: \pset columns, or $COLUMNS, or ioctl + */ + if (cont->opt->columns > 0) + output_columns = cont->opt->columns; + else if ((fout == stdout && isatty(fileno(stdout))) || is_pager) + { + if (cont->opt->env_columns > 0) + output_columns = cont->opt->env_columns; +#ifdef TIOCGWINSZ + else + { + struct winsize screen_size; + + if (ioctl(fileno(stdout), TIOCGWINSZ, &screen_size) != -1) + output_columns = screen_size.ws_col; + } +#endif + } + + if (cont->opt->format == PRINT_WRAPPED) + { + /* + * Optional optimized word wrap. Shrink columns with a high max/avg + * ratio. Slightly bias against wider columns. (Increases chance a + * narrow column will fit in its cell.) If available columns is + * positive... and greater than the width of the unshrinkable column + * headers + */ + if (output_columns > 0 && output_columns >= total_header_width) + { + /* While there is still excess width... */ + while (width_total > output_columns) + { + double max_ratio = 0; + int worst_col = -1; + + /* + * Find column that has the highest ratio of its maximum width + * compared to its average width. This tells us which column + * will produce the fewest wrapped values if shortened. + * width_wrap starts as equal to max_width. + */ + for (i = 0; i < col_count; i++) + { + if (width_average[i] && width_wrap[i] > width_header[i]) + { + /* Penalize wide columns by 1% of their width */ + double ratio; + + ratio = (double) width_wrap[i] / width_average[i] + + max_width[i] * 0.01; + if (ratio > max_ratio) + { + max_ratio = ratio; + worst_col = i; + } + } + } + + /* Exit loop if we can't squeeze any more. */ + if (worst_col == -1) + break; + + /* Decrease width of target column by one. */ + width_wrap[worst_col]--; + width_total--; + } + } + } + + /* + * If in expanded auto mode, we have now calculated the expected width, so + * we can now escape to vertical mode if necessary. + */ + if (cont->opt->expanded == 2 && output_columns > 0 && + (output_columns < total_header_width || output_columns < width_total)) + { + print_aligned_vertical(cont, fout, is_pager); + goto cleanup; + } + + /* If we wrapped beyond the display width, use the pager */ + if (!is_pager && fout == stdout && output_columns > 0 && + (output_columns < total_header_width || output_columns < width_total)) + { + fout = PageOutput(INT_MAX, cont->opt); /* force pager */ + is_pager = is_local_pager = true; + } + + /* Check if newlines or our wrapping now need the pager */ + if (!is_pager && fout == stdout) + { + /* scan all cells, find maximum width, compute cell_count */ + for (i = 0, ptr = cont->cells; *ptr; ptr++, cell_count++) + { + int width, + nl_lines, + bytes_required; + + pg_wcssize((const unsigned char *) *ptr, strlen(*ptr), encoding, + &width, &nl_lines, &bytes_required); + + /* + * A row can have both wrapping and newlines that cause it to + * display across multiple lines. We check for both cases below. + */ + if (width > 0 && width_wrap[i]) + { + unsigned int extra_lines; + + /* don't count the first line of nl_lines - it's not "extra" */ + extra_lines = ((width - 1) / width_wrap[i]) + nl_lines - 1; + if (extra_lines > extra_row_output_lines) + extra_row_output_lines = extra_lines; + } + + /* i is the current column number: increment with wrap */ + if (++i >= col_count) + { + i = 0; + /* At last column of each row, add tallest column height */ + extra_output_lines += extra_row_output_lines; + extra_row_output_lines = 0; + } + } + IsPagerNeeded(cont, extra_output_lines, false, &fout, &is_pager); + is_local_pager = is_pager; + } + + /* time to output */ + if (cont->opt->start_table) + { + /* print title */ + if (cont->title && !opt_tuples_only) + { + int width, + height; + + pg_wcssize((const unsigned char *) cont->title, strlen(cont->title), + encoding, &width, &height, NULL); + if (width >= width_total) + /* Aligned */ + fprintf(fout, "%s\n", cont->title); + else + /* Centered */ + fprintf(fout, "%-*s%s\n", (width_total - width) / 2, "", + cont->title); + } + + /* print headers */ + if (!opt_tuples_only) + { + int more_col_wrapping; + int curr_nl_line; + + if (opt_border == 2) + _print_horizontal_line(col_count, width_wrap, opt_border, + PRINT_RULE_TOP, format, fout); + + for (i = 0; i < col_count; i++) + pg_wcsformat((const unsigned char *) cont->headers[i], + strlen(cont->headers[i]), encoding, + col_lineptrs[i], max_nl_lines[i]); + + more_col_wrapping = col_count; + curr_nl_line = 0; + memset(header_done, false, col_count * sizeof(bool)); + while (more_col_wrapping) + { + if (opt_border == 2) + fputs(dformat->leftvrule, fout); + + for (i = 0; i < cont->ncolumns; i++) + { + struct lineptr *this_line = col_lineptrs[i] + curr_nl_line; + unsigned int nbspace; + + if (opt_border != 0 || + (!format->wrap_right_border && i > 0)) + fputs(curr_nl_line ? format->header_nl_left : " ", + fout); + + if (!header_done[i]) + { + nbspace = width_wrap[i] - this_line->width; + + /* centered */ + fprintf(fout, "%-*s%s%-*s", + nbspace / 2, "", this_line->ptr, (nbspace + 1) / 2, ""); + + if (!(this_line + 1)->ptr) + { + more_col_wrapping--; + header_done[i] = 1; + } + } + else + fprintf(fout, "%*s", width_wrap[i], ""); + + if (opt_border != 0 || format->wrap_right_border) + fputs(!header_done[i] ? format->header_nl_right : " ", + fout); + + if (opt_border != 0 && col_count > 0 && i < col_count - 1) + fputs(dformat->midvrule, fout); + } + curr_nl_line++; + + if (opt_border == 2) + fputs(dformat->rightvrule, fout); + fputc('\n', fout); + } + + _print_horizontal_line(col_count, width_wrap, opt_border, + PRINT_RULE_MIDDLE, format, fout); + } + } + + /* print cells, one loop per row */ + for (i = 0, ptr = cont->cells; *ptr; i += col_count, ptr += col_count) + { + bool more_lines; + + if (cancel_pressed) + break; + + /* + * Format each cell. + */ + for (j = 0; j < col_count; j++) + { + pg_wcsformat((const unsigned char *) ptr[j], strlen(ptr[j]), encoding, + col_lineptrs[j], max_nl_lines[j]); + curr_nl_line[j] = 0; + } + + memset(bytes_output, 0, col_count * sizeof(int)); + + /* + * Each time through this loop, one display line is output. It can + * either be a full value or a partial value if embedded newlines + * exist or if 'format=wrapping' mode is enabled. + */ + do + { + more_lines = false; + + /* left border */ + if (opt_border == 2) + fputs(dformat->leftvrule, fout); + + /* for each column */ + for (j = 0; j < col_count; j++) + { + /* We have a valid array element, so index it */ + struct lineptr *this_line = &col_lineptrs[j][curr_nl_line[j]]; + int bytes_to_output; + int chars_to_output = width_wrap[j]; + bool finalspaces = (opt_border == 2 || + (col_count > 0 && j < col_count - 1)); + + /* Print left-hand wrap or newline mark */ + if (opt_border != 0) + { + if (wrap[j] == PRINT_LINE_WRAP_WRAP) + fputs(format->wrap_left, fout); + else if (wrap[j] == PRINT_LINE_WRAP_NEWLINE) + fputs(format->nl_left, fout); + else + fputc(' ', fout); + } + + if (!this_line->ptr) + { + /* Past newline lines so just pad for other columns */ + if (finalspaces) + fprintf(fout, "%*s", chars_to_output, ""); + } + else + { + /* Get strlen() of the characters up to width_wrap */ + bytes_to_output = + strlen_max_width(this_line->ptr + bytes_output[j], + &chars_to_output, encoding); + + /* + * If we exceeded width_wrap, it means the display width + * of a single character was wider than our target width. + * In that case, we have to pretend we are only printing + * the target display width and make the best of it. + */ + if (chars_to_output > width_wrap[j]) + chars_to_output = width_wrap[j]; + + if (cont->aligns[j] == 'r') /* Right aligned cell */ + { + /* spaces first */ + fprintf(fout, "%*s", width_wrap[j] - chars_to_output, ""); + fputnbytes(fout, + (char *) (this_line->ptr + bytes_output[j]), + bytes_to_output); + } + else /* Left aligned cell */ + { + /* spaces second */ + fputnbytes(fout, + (char *) (this_line->ptr + bytes_output[j]), + bytes_to_output); + } + + bytes_output[j] += bytes_to_output; + + /* Do we have more text to wrap? */ + if (*(this_line->ptr + bytes_output[j]) != '\0') + more_lines = true; + else + { + /* Advance to next newline line */ + curr_nl_line[j]++; + if (col_lineptrs[j][curr_nl_line[j]].ptr != NULL) + more_lines = true; + bytes_output[j] = 0; + } + } + + /* Determine next line's wrap status for this column */ + wrap[j] = PRINT_LINE_WRAP_NONE; + if (col_lineptrs[j][curr_nl_line[j]].ptr != NULL) + { + if (bytes_output[j] != 0) + wrap[j] = PRINT_LINE_WRAP_WRAP; + else if (curr_nl_line[j] != 0) + wrap[j] = PRINT_LINE_WRAP_NEWLINE; + } + + /* + * If left-aligned, pad out remaining space if needed (not + * last column, and/or wrap marks required). + */ + if (cont->aligns[j] != 'r') /* Left aligned cell */ + { + if (finalspaces || + wrap[j] == PRINT_LINE_WRAP_WRAP || + wrap[j] == PRINT_LINE_WRAP_NEWLINE) + fprintf(fout, "%*s", + width_wrap[j] - chars_to_output, ""); + } + + /* Print right-hand wrap or newline mark */ + if (wrap[j] == PRINT_LINE_WRAP_WRAP) + fputs(format->wrap_right, fout); + else if (wrap[j] == PRINT_LINE_WRAP_NEWLINE) + fputs(format->nl_right, fout); + else if (opt_border == 2 || (col_count > 0 && j < col_count - 1)) + fputc(' ', fout); + + /* Print column divider, if not the last column */ + if (opt_border != 0 && (col_count > 0 && j < col_count - 1)) + { + if (wrap[j + 1] == PRINT_LINE_WRAP_WRAP) + fputs(format->midvrule_wrap, fout); + else if (wrap[j + 1] == PRINT_LINE_WRAP_NEWLINE) + fputs(format->midvrule_nl, fout); + else if (col_lineptrs[j + 1][curr_nl_line[j + 1]].ptr == NULL) + fputs(format->midvrule_blank, fout); + else + fputs(dformat->midvrule, fout); + } + } + + /* end-of-row border */ + if (opt_border == 2) + fputs(dformat->rightvrule, fout); + fputc('\n', fout); + + } while (more_lines); + } + + if (cont->opt->stop_table) + { + printTableFooter *footers = footers_with_default(cont); + + if (opt_border == 2 && !cancel_pressed) + _print_horizontal_line(col_count, width_wrap, opt_border, + PRINT_RULE_BOTTOM, format, fout); + + /* print footers */ + if (footers && !opt_tuples_only && !cancel_pressed) + { + printTableFooter *f; + + for (f = footers; f; f = f->next) + fprintf(fout, "%s\n", f->data); + } + + fputc('\n', fout); + } + +cleanup: + /* clean up */ + for (i = 0; i < col_count; i++) + { + free(col_lineptrs[i]); + free(format_buf[i]); + } + free(width_header); + free(width_average); + free(max_width); + free(width_wrap); + free(max_nl_lines); + free(curr_nl_line); + free(col_lineptrs); + free(max_bytes); + free(format_buf); + free(header_done); + free(bytes_output); + free(wrap); + + if (is_local_pager) + ClosePager(fout); +} + + +static void +print_aligned_vertical_line(const printTextFormat *format, + const unsigned short opt_border, + unsigned long record, + unsigned int hwidth, + unsigned int dwidth, + printTextRule pos, + FILE *fout) +{ + const printTextLineFormat *lformat = &format->lrule[pos]; + unsigned int i; + int reclen = 0; + + if (opt_border == 2) + fprintf(fout, "%s%s", lformat->leftvrule, lformat->hrule); + else if (opt_border == 1) + fputs(lformat->hrule, fout); + + if (record) + { + if (opt_border == 0) + reclen = fprintf(fout, "* Record %lu", record); + else + reclen = fprintf(fout, "[ RECORD %lu ]", record); + } + if (opt_border != 2) + reclen++; + if (reclen < 0) + reclen = 0; + for (i = reclen; i < hwidth; i++) + fputs(opt_border > 0 ? lformat->hrule : " ", fout); + reclen -= hwidth; + + if (opt_border > 0) + { + if (reclen-- <= 0) + fputs(lformat->hrule, fout); + if (reclen-- <= 0) + fputs(lformat->midvrule, fout); + if (reclen-- <= 0) + fputs(lformat->hrule, fout); + } + else + { + if (reclen-- <= 0) + fputc(' ', fout); + } + if (reclen < 0) + reclen = 0; + for (i = reclen; i < dwidth; i++) + fputs(opt_border > 0 ? lformat->hrule : " ", fout); + if (opt_border == 2) + fprintf(fout, "%s%s", lformat->hrule, lformat->rightvrule); + fputc('\n', fout); +} + +static void +print_aligned_vertical(const printTableContent *cont, + FILE *fout, bool is_pager) +{ + bool opt_tuples_only = cont->opt->tuples_only; + unsigned short opt_border = cont->opt->border; + const printTextFormat *format = get_line_style(cont->opt); + const printTextLineFormat *dformat = &format->lrule[PRINT_RULE_DATA]; + int encoding = cont->opt->encoding; + unsigned long record = cont->opt->prior_records + 1; + const char *const * ptr; + unsigned int i, + hwidth = 0, + dwidth = 0, + hheight = 1, + dheight = 1, + hformatsize = 0, + dformatsize = 0; + struct lineptr *hlineptr, + *dlineptr; + bool is_local_pager = false, + hmultiline = false, + dmultiline = false; + int output_columns = 0; /* Width of interactive console */ + + if (cancel_pressed) + return; + + if (opt_border > 2) + opt_border = 2; + + if (cont->cells[0] == NULL && cont->opt->start_table && + cont->opt->stop_table) + { + printTableFooter *footers = footers_with_default(cont); + + if (!opt_tuples_only && !cancel_pressed && footers) + { + printTableFooter *f; + + for (f = footers; f; f = f->next) + fprintf(fout, "%s\n", f->data); + } + + fputc('\n', fout); + + return; + } + + /* + * Deal with the pager here instead of in printTable(), because we could + * get here via print_aligned_text() in expanded auto mode, and so we have + * to recalculate the pager requirement based on vertical output. + */ + if (!is_pager) + { + IsPagerNeeded(cont, 0, true, &fout, &is_pager); + is_local_pager = is_pager; + } + + /* Find the maximum dimensions for the headers */ + for (i = 0; i < cont->ncolumns; i++) + { + int width, + height, + fs; + + pg_wcssize((const unsigned char *) cont->headers[i], strlen(cont->headers[i]), + encoding, &width, &height, &fs); + if (width > hwidth) + hwidth = width; + if (height > hheight) + { + hheight = height; + hmultiline = true; + } + if (fs > hformatsize) + hformatsize = fs; + } + + /* find longest data cell */ + for (i = 0, ptr = cont->cells; *ptr; ptr++, i++) + { + int width, + height, + fs; + + pg_wcssize((const unsigned char *) *ptr, strlen(*ptr), encoding, + &width, &height, &fs); + if (width > dwidth) + dwidth = width; + if (height > dheight) + { + dheight = height; + dmultiline = true; + } + if (fs > dformatsize) + dformatsize = fs; + } + + /* + * We now have all the information we need to setup the formatting + * structures + */ + dlineptr = pg_malloc((sizeof(*dlineptr)) * (dheight + 1)); + hlineptr = pg_malloc((sizeof(*hlineptr)) * (hheight + 1)); + + dlineptr->ptr = pg_malloc(dformatsize); + hlineptr->ptr = pg_malloc(hformatsize); + + if (cont->opt->start_table) + { + /* print title */ + if (!opt_tuples_only && cont->title) + fprintf(fout, "%s\n", cont->title); + } + + /* + * Choose target output width: \pset columns, or $COLUMNS, or ioctl + */ + if (cont->opt->columns > 0) + output_columns = cont->opt->columns; + else if ((fout == stdout && isatty(fileno(stdout))) || is_pager) + { + if (cont->opt->env_columns > 0) + output_columns = cont->opt->env_columns; +#ifdef TIOCGWINSZ + else + { + struct winsize screen_size; + + if (ioctl(fileno(stdout), TIOCGWINSZ, &screen_size) != -1) + output_columns = screen_size.ws_col; + } +#endif + } + + /* + * Calculate available width for data in wrapped mode + */ + if (cont->opt->format == PRINT_WRAPPED) + { + unsigned int swidth, + rwidth = 0, + newdwidth; + + if (opt_border == 0) + { + /* + * For border = 0, one space in the middle. (If we discover we + * need to wrap, the spacer column will be replaced by a wrap + * marker, and we'll make room below for another wrap marker at + * the end of the line. But for now, assume no wrap is needed.) + */ + swidth = 1; + + /* We might need a column for header newline markers, too */ + if (hmultiline) + swidth++; + } + else if (opt_border == 1) + { + /* + * For border = 1, two spaces and a vrule in the middle. (As + * above, we might need one more column for a wrap marker.) + */ + swidth = 3; + + /* We might need a column for left header newline markers, too */ + if (hmultiline && (format == &pg_asciiformat_old)) + swidth++; + } + else + { + /* + * For border = 2, two more for the vrules at the beginning and + * end of the lines, plus spacer columns adjacent to these. (We + * won't need extra columns for wrap/newline markers, we'll just + * repurpose the spacers.) + */ + swidth = 7; + } + + /* Reserve a column for data newline indicators, too, if needed */ + if (dmultiline && + opt_border < 2 && format != &pg_asciiformat_old) + swidth++; + + /* Determine width required for record header lines */ + if (!opt_tuples_only) + { + if (cont->nrows > 0) + rwidth = 1 + (int) log10(cont->nrows); + if (opt_border == 0) + rwidth += 9; /* "* RECORD " */ + else if (opt_border == 1) + rwidth += 12; /* "-[ RECORD ]" */ + else + rwidth += 15; /* "+-[ RECORD ]-+" */ + } + + /* We might need to do the rest of the calculation twice */ + for (;;) + { + unsigned int width; + + /* Total width required to not wrap data */ + width = hwidth + swidth + dwidth; + /* ... and not the header lines, either */ + if (width < rwidth) + width = rwidth; + + if (output_columns > 0) + { + unsigned int min_width; + + /* Minimum acceptable width: room for just 3 columns of data */ + min_width = hwidth + swidth + 3; + /* ... but not less than what the record header lines need */ + if (min_width < rwidth) + min_width = rwidth; + + if (output_columns >= width) + { + /* Plenty of room, use native data width */ + /* (but at least enough for the record header lines) */ + newdwidth = width - hwidth - swidth; + } + else if (output_columns < min_width) + { + /* Set data width to match min_width */ + newdwidth = min_width - hwidth - swidth; + } + else + { + /* Set data width to match output_columns */ + newdwidth = output_columns - hwidth - swidth; + } + } + else + { + /* Don't know the wrap limit, so use native data width */ + /* (but at least enough for the record header lines) */ + newdwidth = width - hwidth - swidth; + } + + /* + * If we will need to wrap data and didn't already allocate a data + * newline/wrap marker column, do so and recompute. + */ + if (newdwidth < dwidth && !dmultiline && + opt_border < 2 && format != &pg_asciiformat_old) + { + dmultiline = true; + swidth++; + } + else + break; + } + + dwidth = newdwidth; + } + + /* print records */ + for (i = 0, ptr = cont->cells; *ptr; i++, ptr++) + { + printTextRule pos; + int dline, + hline, + dcomplete, + hcomplete, + offset, + chars_to_output; + + if (cancel_pressed) + break; + + if (i == 0) + pos = PRINT_RULE_TOP; + else + pos = PRINT_RULE_MIDDLE; + + /* Print record header (e.g. "[ RECORD N ]") above each record */ + if (i % cont->ncolumns == 0) + { + unsigned int lhwidth = hwidth; + + if ((opt_border < 2) && + (hmultiline) && + (format == &pg_asciiformat_old)) + lhwidth++; /* for newline indicators */ + + if (!opt_tuples_only) + print_aligned_vertical_line(format, opt_border, record++, + lhwidth, dwidth, pos, fout); + else if (i != 0 || !cont->opt->start_table || opt_border == 2) + print_aligned_vertical_line(format, opt_border, 0, lhwidth, + dwidth, pos, fout); + } + + /* Format the header */ + pg_wcsformat((const unsigned char *) cont->headers[i % cont->ncolumns], + strlen(cont->headers[i % cont->ncolumns]), + encoding, hlineptr, hheight); + /* Format the data */ + pg_wcsformat((const unsigned char *) *ptr, strlen(*ptr), encoding, + dlineptr, dheight); + + /* + * Loop through header and data in parallel dealing with newlines and + * wrapped lines until they're both exhausted + */ + dline = hline = 0; + dcomplete = hcomplete = 0; + offset = 0; + chars_to_output = dlineptr[dline].width; + while (!dcomplete || !hcomplete) + { + /* Left border */ + if (opt_border == 2) + fprintf(fout, "%s", dformat->leftvrule); + + /* Header (never wrapped so just need to deal with newlines) */ + if (!hcomplete) + { + int swidth = hwidth, + target_width = hwidth; + + /* + * Left spacer or new line indicator + */ + if ((opt_border == 2) || + (hmultiline && (format == &pg_asciiformat_old))) + fputs(hline ? format->header_nl_left : " ", fout); + + /* + * Header text + */ + strlen_max_width(hlineptr[hline].ptr, &target_width, + encoding); + fprintf(fout, "%-s", hlineptr[hline].ptr); + + /* + * Spacer + */ + swidth -= target_width; + if (swidth > 0) + fprintf(fout, "%*s", swidth, " "); + + /* + * New line indicator or separator's space + */ + if (hlineptr[hline + 1].ptr) + { + /* More lines after this one due to a newline */ + if ((opt_border > 0) || + (hmultiline && (format != &pg_asciiformat_old))) + fputs(format->header_nl_right, fout); + hline++; + } + else + { + /* This was the last line of the header */ + if ((opt_border > 0) || + (hmultiline && (format != &pg_asciiformat_old))) + fputs(" ", fout); + hcomplete = 1; + } + } + else + { + unsigned int swidth = hwidth + opt_border; + + if ((opt_border < 2) && + (hmultiline) && + (format == &pg_asciiformat_old)) + swidth++; + + if ((opt_border == 0) && + (format != &pg_asciiformat_old) && + (hmultiline)) + swidth++; + + fprintf(fout, "%*s", swidth, " "); + } + + /* Separator */ + if (opt_border > 0) + { + if (offset) + fputs(format->midvrule_wrap, fout); + else if (dline == 0) + fputs(dformat->midvrule, fout); + else + fputs(format->midvrule_nl, fout); + } + + /* Data */ + if (!dcomplete) + { + int target_width = dwidth, + bytes_to_output, + swidth = dwidth; + + /* + * Left spacer or wrap indicator + */ + fputs(offset == 0 ? " " : format->wrap_left, fout); + + /* + * Data text + */ + bytes_to_output = strlen_max_width(dlineptr[dline].ptr + offset, + &target_width, encoding); + fputnbytes(fout, (char *) (dlineptr[dline].ptr + offset), + bytes_to_output); + + chars_to_output -= target_width; + offset += bytes_to_output; + + /* Spacer */ + swidth -= target_width; + + if (chars_to_output) + { + /* continuing a wrapped column */ + if ((opt_border > 1) || + (dmultiline && (format != &pg_asciiformat_old))) + { + if (swidth > 0) + fprintf(fout, "%*s", swidth, " "); + fputs(format->wrap_right, fout); + } + } + else if (dlineptr[dline + 1].ptr) + { + /* reached a newline in the column */ + if ((opt_border > 1) || + (dmultiline && (format != &pg_asciiformat_old))) + { + if (swidth > 0) + fprintf(fout, "%*s", swidth, " "); + fputs(format->nl_right, fout); + } + dline++; + offset = 0; + chars_to_output = dlineptr[dline].width; + } + else + { + /* reached the end of the cell */ + if (opt_border > 1) + { + if (swidth > 0) + fprintf(fout, "%*s", swidth, " "); + fputs(" ", fout); + } + dcomplete = 1; + } + + /* Right border */ + if (opt_border == 2) + fputs(dformat->rightvrule, fout); + + fputs("\n", fout); + } + else + { + /* + * data exhausted (this can occur if header is longer than the + * data due to newlines in the header) + */ + if (opt_border < 2) + fputs("\n", fout); + else + fprintf(fout, "%*s %s\n", dwidth, "", dformat->rightvrule); + } + } + } + + if (cont->opt->stop_table) + { + if (opt_border == 2 && !cancel_pressed) + print_aligned_vertical_line(format, opt_border, 0, hwidth, dwidth, + PRINT_RULE_BOTTOM, fout); + + /* print footers */ + if (!opt_tuples_only && cont->footers != NULL && !cancel_pressed) + { + printTableFooter *f; + + if (opt_border < 2) + fputc('\n', fout); + for (f = cont->footers; f; f = f->next) + fprintf(fout, "%s\n", f->data); + } + + fputc('\n', fout); + } + + free(hlineptr->ptr); + free(dlineptr->ptr); + free(hlineptr); + free(dlineptr); + + if (is_local_pager) + ClosePager(fout); +} + + +/**********************/ +/* HTML printing ******/ +/**********************/ + + +void +html_escaped_print(const char *in, FILE *fout) +{ + const char *p; + bool leading_space = true; + + for (p = in; *p; p++) + { + switch (*p) + { + case '&': + fputs("&", fout); + break; + case '<': + fputs("<", fout); + break; + case '>': + fputs(">", fout); + break; + case '\n': + fputs("
\n", fout); + break; + case '"': + fputs(""", fout); + break; + case ' ': + /* protect leading space, for EXPLAIN output */ + if (leading_space) + fputs(" ", fout); + else + fputs(" ", fout); + break; + default: + fputc(*p, fout); + } + if (*p != ' ') + leading_space = false; + } +} + + +static void +print_html_text(const printTableContent *cont, FILE *fout) +{ + bool opt_tuples_only = cont->opt->tuples_only; + unsigned short opt_border = cont->opt->border; + const char *opt_table_attr = cont->opt->tableAttr; + unsigned int i; + const char *const * ptr; + + if (cancel_pressed) + return; + + if (cont->opt->start_table) + { + fprintf(fout, "
\n", fout); + + /* print title */ + if (!opt_tuples_only && cont->title) + { + fputs(" \n", fout); + } + + /* print headers */ + if (!opt_tuples_only) + { + fputs(" \n", fout); + for (ptr = cont->headers; *ptr; ptr++) + { + fputs(" \n", fout); + } + fputs(" \n", fout); + } + } + + /* print cells */ + for (i = 0, ptr = cont->cells; *ptr; i++, ptr++) + { + if (i % cont->ncolumns == 0) + { + if (cancel_pressed) + break; + fputs(" \n", fout); + } + + fprintf(fout, " \n", fout); + + if ((i + 1) % cont->ncolumns == 0) + fputs(" \n", fout); + } + + if (cont->opt->stop_table) + { + printTableFooter *footers = footers_with_default(cont); + + fputs("
", fout); + html_escaped_print(cont->title, fout); + fputs("
", fout); + html_escaped_print(*ptr, fout); + fputs("
", cont->aligns[(i) % cont->ncolumns] == 'r' ? "right" : "left"); + /* is string only whitespace? */ + if ((*ptr)[strspn(*ptr, " \t")] == '\0') + fputs("  ", fout); + else + html_escaped_print(*ptr, fout); + + fputs("
\n", fout); + + /* print footers */ + if (!opt_tuples_only && footers != NULL && !cancel_pressed) + { + printTableFooter *f; + + fputs("

", fout); + for (f = footers; f; f = f->next) + { + html_escaped_print(f->data, fout); + fputs("
\n", fout); + } + fputs("

", fout); + } + + fputc('\n', fout); + } +} + + +static void +print_html_vertical(const printTableContent *cont, FILE *fout) +{ + bool opt_tuples_only = cont->opt->tuples_only; + unsigned short opt_border = cont->opt->border; + const char *opt_table_attr = cont->opt->tableAttr; + unsigned long record = cont->opt->prior_records + 1; + unsigned int i; + const char *const * ptr; + + if (cancel_pressed) + return; + + if (cont->opt->start_table) + { + fprintf(fout, "\n", fout); + + /* print title */ + if (!opt_tuples_only && cont->title) + { + fputs(" \n", fout); + } + } + + /* print records */ + for (i = 0, ptr = cont->cells; *ptr; i++, ptr++) + { + if (i % cont->ncolumns == 0) + { + if (cancel_pressed) + break; + if (!opt_tuples_only) + fprintf(fout, + "\n \n", + record++); + else + fputs("\n \n", fout); + } + fputs(" \n" + " \n", fout); + + fprintf(fout, " \n \n", fout); + } + + if (cont->opt->stop_table) + { + fputs("
", fout); + html_escaped_print(cont->title, fout); + fputs("
Record %lu
 
", fout); + html_escaped_print(cont->headers[i % cont->ncolumns], fout); + fputs("", cont->aligns[i % cont->ncolumns] == 'r' ? "right" : "left"); + /* is string only whitespace? */ + if ((*ptr)[strspn(*ptr, " \t")] == '\0') + fputs("  ", fout); + else + html_escaped_print(*ptr, fout); + + fputs("
\n", fout); + + /* print footers */ + if (!opt_tuples_only && cont->footers != NULL && !cancel_pressed) + { + printTableFooter *f; + + fputs("

", fout); + for (f = cont->footers; f; f = f->next) + { + html_escaped_print(f->data, fout); + fputs("
\n", fout); + } + fputs("

", fout); + } + + fputc('\n', fout); + } +} + + +/*************************/ +/* ASCIIDOC */ +/*************************/ + +static void +asciidoc_escaped_print(const char *in, FILE *fout) +{ + const char *p; + + for (p = in; *p; p++) + { + switch (*p) + { + case '|': + fputs("\\|", fout); + break; + default: + fputc(*p, fout); + } + } +} + +static void +print_asciidoc_text(const printTableContent *cont, FILE *fout) +{ + bool opt_tuples_only = cont->opt->tuples_only; + unsigned short opt_border = cont->opt->border; + unsigned int i; + const char *const * ptr; + + if (cancel_pressed) + return; + + if (cont->opt->start_table) + { + /* print table in new paragraph - enforce preliminary new line */ + fputs("\n", fout); + + /* print title */ + if (!opt_tuples_only && cont->title) + { + fputs(".", fout); + fputs(cont->title, fout); + fputs("\n", fout); + } + + /* print table [] header definition */ + fprintf(fout, "[%scols=\"", !opt_tuples_only ? "options=\"header\"," : ""); + for (i = 0; i < cont->ncolumns; i++) + { + if (i != 0) + fputs(",", fout); + fprintf(fout, "%s", cont->aligns[(i) % cont->ncolumns] == 'r' ? ">l" : "headers; *ptr; ptr++) + { + if (ptr != cont->headers) + fputs(" ", fout); + fputs("^l|", fout); + asciidoc_escaped_print(*ptr, fout); + } + fputs("\n", fout); + } + } + + /* print cells */ + for (i = 0, ptr = cont->cells; *ptr; i++, ptr++) + { + if (i % cont->ncolumns == 0) + { + if (cancel_pressed) + break; + } + + if (i % cont->ncolumns != 0) + fputs(" ", fout); + fputs("|", fout); + + /* protect against needless spaces */ + if ((*ptr)[strspn(*ptr, " \t")] == '\0') + { + if ((i + 1) % cont->ncolumns != 0) + fputs(" ", fout); + } + else + asciidoc_escaped_print(*ptr, fout); + + if ((i + 1) % cont->ncolumns == 0) + fputs("\n", fout); + } + + fputs("|====\n", fout); + + if (cont->opt->stop_table) + { + printTableFooter *footers = footers_with_default(cont); + + /* print footers */ + if (!opt_tuples_only && footers != NULL && !cancel_pressed) + { + printTableFooter *f; + + fputs("\n....\n", fout); + for (f = footers; f; f = f->next) + { + fputs(f->data, fout); + fputs("\n", fout); + } + fputs("....\n", fout); + } + } +} + +static void +print_asciidoc_vertical(const printTableContent *cont, FILE *fout) +{ + bool opt_tuples_only = cont->opt->tuples_only; + unsigned short opt_border = cont->opt->border; + unsigned long record = cont->opt->prior_records + 1; + unsigned int i; + const char *const * ptr; + + if (cancel_pressed) + return; + + if (cont->opt->start_table) + { + /* print table in new paragraph - enforce preliminary new line */ + fputs("\n", fout); + + /* print title */ + if (!opt_tuples_only && cont->title) + { + fputs(".", fout); + fputs(cont->title, fout); + fputs("\n", fout); + } + + /* print table [] header definition */ + fputs("[cols=\"h,l\"", fout); + switch (opt_border) + { + case 0: + fputs(",frame=\"none\",grid=\"none\"", fout); + break; + case 1: + fputs(",frame=\"none\"", fout); + break; + case 2: + fputs(",frame=\"all\",grid=\"all\"", fout); + break; + } + fputs("]\n", fout); + fputs("|====\n", fout); + } + + /* print records */ + for (i = 0, ptr = cont->cells; *ptr; i++, ptr++) + { + if (i % cont->ncolumns == 0) + { + if (cancel_pressed) + break; + if (!opt_tuples_only) + fprintf(fout, + "2+^|Record %lu\n", + record++); + else + fputs("2+|\n", fout); + } + + fputs("headers[i % cont->ncolumns], fout); + + fprintf(fout, " %s|", cont->aligns[i % cont->ncolumns] == 'r' ? ">l" : "opt->stop_table) + { + /* print footers */ + if (!opt_tuples_only && cont->footers != NULL && !cancel_pressed) + { + printTableFooter *f; + + fputs("\n....\n", fout); + for (f = cont->footers; f; f = f->next) + { + fputs(f->data, fout); + fputs("\n", fout); + } + fputs("....\n", fout); + } + } +} + +/*************************/ +/* LaTeX */ +/*************************/ + + +static void +latex_escaped_print(const char *in, FILE *fout) +{ + const char *p; + + for (p = in; *p; p++) + switch (*p) + { + case '&': + fputs("\\&", fout); + break; + case '%': + fputs("\\%", fout); + break; + case '$': + fputs("\\$", fout); + break; + case '_': + fputs("\\_", fout); + break; + case '{': + fputs("\\{", fout); + break; + case '}': + fputs("\\}", fout); + break; + case '\\': + fputs("\\backslash", fout); + break; + case '\n': + fputs("\\\\", fout); + break; + default: + fputc(*p, fout); + } +} + + +static void +print_latex_text(const printTableContent *cont, FILE *fout) +{ + bool opt_tuples_only = cont->opt->tuples_only; + unsigned short opt_border = cont->opt->border; + unsigned int i; + const char *const * ptr; + + if (cancel_pressed) + return; + + if (opt_border > 3) + opt_border = 3; + + if (cont->opt->start_table) + { + /* print title */ + if (!opt_tuples_only && cont->title) + { + fputs("\\begin{center}\n", fout); + latex_escaped_print(cont->title, fout); + fputs("\n\\end{center}\n\n", fout); + } + + /* begin environment and set alignments and borders */ + fputs("\\begin{tabular}{", fout); + + if (opt_border >= 2) + fputs("| ", fout); + for (i = 0; i < cont->ncolumns; i++) + { + fputc(*(cont->aligns + i), fout); + if (opt_border != 0 && i < cont->ncolumns - 1) + fputs(" | ", fout); + } + if (opt_border >= 2) + fputs(" |", fout); + + fputs("}\n", fout); + + if (!opt_tuples_only && opt_border >= 2) + fputs("\\hline\n", fout); + + /* print headers */ + if (!opt_tuples_only) + { + for (i = 0, ptr = cont->headers; i < cont->ncolumns; i++, ptr++) + { + if (i != 0) + fputs(" & ", fout); + fputs("\\textit{", fout); + latex_escaped_print(*ptr, fout); + fputc('}', fout); + } + fputs(" \\\\\n", fout); + fputs("\\hline\n", fout); + } + } + + /* print cells */ + for (i = 0, ptr = cont->cells; *ptr; i++, ptr++) + { + latex_escaped_print(*ptr, fout); + + if ((i + 1) % cont->ncolumns == 0) + { + fputs(" \\\\\n", fout); + if (opt_border == 3) + fputs("\\hline\n", fout); + if (cancel_pressed) + break; + } + else + fputs(" & ", fout); + } + + if (cont->opt->stop_table) + { + printTableFooter *footers = footers_with_default(cont); + + if (opt_border == 2) + fputs("\\hline\n", fout); + + fputs("\\end{tabular}\n\n\\noindent ", fout); + + /* print footers */ + if (footers && !opt_tuples_only && !cancel_pressed) + { + printTableFooter *f; + + for (f = footers; f; f = f->next) + { + latex_escaped_print(f->data, fout); + fputs(" \\\\\n", fout); + } + } + + fputc('\n', fout); + } +} + + +static void +print_latex_longtable_text(const printTableContent *cont, FILE *fout) +{ + bool opt_tuples_only = cont->opt->tuples_only; + unsigned short opt_border = cont->opt->border; + unsigned int i; + const char *opt_table_attr = cont->opt->tableAttr; + const char *next_opt_table_attr_char = opt_table_attr; + const char *last_opt_table_attr_char = NULL; + const char *const * ptr; + + if (cancel_pressed) + return; + + if (opt_border > 3) + opt_border = 3; + + if (cont->opt->start_table) + { + /* begin environment and set alignments and borders */ + fputs("\\begin{longtable}{", fout); + + if (opt_border >= 2) + fputs("| ", fout); + + for (i = 0; i < cont->ncolumns; i++) + { + /* longtable supports either a width (p) or an alignment (l/r) */ + /* Are we left-justified and was a proportional width specified? */ + if (*(cont->aligns + i) == 'l' && opt_table_attr) + { +#define LONGTABLE_WHITESPACE " \t\n" + + /* advance over whitespace */ + next_opt_table_attr_char += strspn(next_opt_table_attr_char, + LONGTABLE_WHITESPACE); + /* We have a value? */ + if (next_opt_table_attr_char[0] != '\0') + { + fputs("p{", fout); + fwrite(next_opt_table_attr_char, strcspn(next_opt_table_attr_char, + LONGTABLE_WHITESPACE), 1, fout); + last_opt_table_attr_char = next_opt_table_attr_char; + next_opt_table_attr_char += strcspn(next_opt_table_attr_char, + LONGTABLE_WHITESPACE); + fputs("\\textwidth}", fout); + } + /* use previous value */ + else if (last_opt_table_attr_char != NULL) + { + fputs("p{", fout); + fwrite(last_opt_table_attr_char, strcspn(last_opt_table_attr_char, + LONGTABLE_WHITESPACE), 1, fout); + fputs("\\textwidth}", fout); + } + else + fputc('l', fout); + } + else + fputc(*(cont->aligns + i), fout); + + if (opt_border != 0 && i < cont->ncolumns - 1) + fputs(" | ", fout); + } + + if (opt_border >= 2) + fputs(" |", fout); + + fputs("}\n", fout); + + /* print headers */ + if (!opt_tuples_only) + { + /* firsthead */ + if (opt_border >= 2) + fputs("\\toprule\n", fout); + for (i = 0, ptr = cont->headers; i < cont->ncolumns; i++, ptr++) + { + if (i != 0) + fputs(" & ", fout); + fputs("\\small\\textbf{\\textit{", fout); + latex_escaped_print(*ptr, fout); + fputs("}}", fout); + } + fputs(" \\\\\n", fout); + fputs("\\midrule\n\\endfirsthead\n", fout); + + /* secondary heads */ + if (opt_border >= 2) + fputs("\\toprule\n", fout); + for (i = 0, ptr = cont->headers; i < cont->ncolumns; i++, ptr++) + { + if (i != 0) + fputs(" & ", fout); + fputs("\\small\\textbf{\\textit{", fout); + latex_escaped_print(*ptr, fout); + fputs("}}", fout); + } + fputs(" \\\\\n", fout); + /* If the line under the row already appeared, don't do another */ + if (opt_border != 3) + fputs("\\midrule\n", fout); + fputs("\\endhead\n", fout); + + /* table name, caption? */ + if (!opt_tuples_only && cont->title) + { + /* Don't output if we are printing a line under each row */ + if (opt_border == 2) + fputs("\\bottomrule\n", fout); + fputs("\\caption[", fout); + latex_escaped_print(cont->title, fout); + fputs(" (Continued)]{", fout); + latex_escaped_print(cont->title, fout); + fputs("}\n\\endfoot\n", fout); + if (opt_border == 2) + fputs("\\bottomrule\n", fout); + fputs("\\caption[", fout); + latex_escaped_print(cont->title, fout); + fputs("]{", fout); + latex_escaped_print(cont->title, fout); + fputs("}\n\\endlastfoot\n", fout); + } + /* output bottom table line? */ + else if (opt_border >= 2) + { + fputs("\\bottomrule\n\\endfoot\n", fout); + fputs("\\bottomrule\n\\endlastfoot\n", fout); + } + } + } + + /* print cells */ + for (i = 0, ptr = cont->cells; *ptr; i++, ptr++) + { + /* Add a line under each row? */ + if (i != 0 && i % cont->ncolumns != 0) + fputs("\n&\n", fout); + fputs("\\raggedright{", fout); + latex_escaped_print(*ptr, fout); + fputc('}', fout); + if ((i + 1) % cont->ncolumns == 0) + { + fputs(" \\tabularnewline\n", fout); + if (opt_border == 3) + fputs(" \\hline\n", fout); + } + if (cancel_pressed) + break; + } + + if (cont->opt->stop_table) + fputs("\\end{longtable}\n", fout); +} + + +static void +print_latex_vertical(const printTableContent *cont, FILE *fout) +{ + bool opt_tuples_only = cont->opt->tuples_only; + unsigned short opt_border = cont->opt->border; + unsigned long record = cont->opt->prior_records + 1; + unsigned int i; + const char *const * ptr; + + if (cancel_pressed) + return; + + if (opt_border > 2) + opt_border = 2; + + if (cont->opt->start_table) + { + /* print title */ + if (!opt_tuples_only && cont->title) + { + fputs("\\begin{center}\n", fout); + latex_escaped_print(cont->title, fout); + fputs("\n\\end{center}\n\n", fout); + } + + /* begin environment and set alignments and borders */ + fputs("\\begin{tabular}{", fout); + if (opt_border == 0) + fputs("cl", fout); + else if (opt_border == 1) + fputs("c|l", fout); + else if (opt_border == 2) + fputs("|c|l|", fout); + fputs("}\n", fout); + } + + /* print records */ + for (i = 0, ptr = cont->cells; *ptr; i++, ptr++) + { + /* new record */ + if (i % cont->ncolumns == 0) + { + if (cancel_pressed) + break; + if (!opt_tuples_only) + { + if (opt_border == 2) + { + fputs("\\hline\n", fout); + fprintf(fout, "\\multicolumn{2}{|c|}{\\textit{Record %lu}} \\\\\n", record++); + } + else + fprintf(fout, "\\multicolumn{2}{c}{\\textit{Record %lu}} \\\\\n", record++); + } + if (opt_border >= 1) + fputs("\\hline\n", fout); + } + + latex_escaped_print(cont->headers[i % cont->ncolumns], fout); + fputs(" & ", fout); + latex_escaped_print(*ptr, fout); + fputs(" \\\\\n", fout); + } + + if (cont->opt->stop_table) + { + if (opt_border == 2) + fputs("\\hline\n", fout); + + fputs("\\end{tabular}\n\n\\noindent ", fout); + + /* print footers */ + if (cont->footers && !opt_tuples_only && !cancel_pressed) + { + printTableFooter *f; + + for (f = cont->footers; f; f = f->next) + { + latex_escaped_print(f->data, fout); + fputs(" \\\\\n", fout); + } + } + + fputc('\n', fout); + } +} + + +/*************************/ +/* Troff -ms */ +/*************************/ + + +static void +troff_ms_escaped_print(const char *in, FILE *fout) +{ + const char *p; + + for (p = in; *p; p++) + switch (*p) + { + case '\\': + fputs("\\(rs", fout); + break; + default: + fputc(*p, fout); + } +} + + +static void +print_troff_ms_text(const printTableContent *cont, FILE *fout) +{ + bool opt_tuples_only = cont->opt->tuples_only; + unsigned short opt_border = cont->opt->border; + unsigned int i; + const char *const * ptr; + + if (cancel_pressed) + return; + + if (opt_border > 2) + opt_border = 2; + + if (cont->opt->start_table) + { + /* print title */ + if (!opt_tuples_only && cont->title) + { + fputs(".LP\n.DS C\n", fout); + troff_ms_escaped_print(cont->title, fout); + fputs("\n.DE\n", fout); + } + + /* begin environment and set alignments and borders */ + fputs(".LP\n.TS\n", fout); + if (opt_border == 2) + fputs("center box;\n", fout); + else + fputs("center;\n", fout); + + for (i = 0; i < cont->ncolumns; i++) + { + fputc(*(cont->aligns + i), fout); + if (opt_border > 0 && i < cont->ncolumns - 1) + fputs(" | ", fout); + } + fputs(".\n", fout); + + /* print headers */ + if (!opt_tuples_only) + { + for (i = 0, ptr = cont->headers; i < cont->ncolumns; i++, ptr++) + { + if (i != 0) + fputc('\t', fout); + fputs("\\fI", fout); + troff_ms_escaped_print(*ptr, fout); + fputs("\\fP", fout); + } + fputs("\n_\n", fout); + } + } + + /* print cells */ + for (i = 0, ptr = cont->cells; *ptr; i++, ptr++) + { + troff_ms_escaped_print(*ptr, fout); + + if ((i + 1) % cont->ncolumns == 0) + { + fputc('\n', fout); + if (cancel_pressed) + break; + } + else + fputc('\t', fout); + } + + if (cont->opt->stop_table) + { + printTableFooter *footers = footers_with_default(cont); + + fputs(".TE\n.DS L\n", fout); + + /* print footers */ + if (footers && !opt_tuples_only && !cancel_pressed) + { + printTableFooter *f; + + for (f = footers; f; f = f->next) + { + troff_ms_escaped_print(f->data, fout); + fputc('\n', fout); + } + } + + fputs(".DE\n", fout); + } +} + + +static void +print_troff_ms_vertical(const printTableContent *cont, FILE *fout) +{ + bool opt_tuples_only = cont->opt->tuples_only; + unsigned short opt_border = cont->opt->border; + unsigned long record = cont->opt->prior_records + 1; + unsigned int i; + const char *const * ptr; + unsigned short current_format = 0; /* 0=none, 1=header, 2=body */ + + if (cancel_pressed) + return; + + if (opt_border > 2) + opt_border = 2; + + if (cont->opt->start_table) + { + /* print title */ + if (!opt_tuples_only && cont->title) + { + fputs(".LP\n.DS C\n", fout); + troff_ms_escaped_print(cont->title, fout); + fputs("\n.DE\n", fout); + } + + /* begin environment and set alignments and borders */ + fputs(".LP\n.TS\n", fout); + if (opt_border == 2) + fputs("center box;\n", fout); + else + fputs("center;\n", fout); + + /* basic format */ + if (opt_tuples_only) + fputs("c l;\n", fout); + } + else + current_format = 2; /* assume tuples printed already */ + + /* print records */ + for (i = 0, ptr = cont->cells; *ptr; i++, ptr++) + { + /* new record */ + if (i % cont->ncolumns == 0) + { + if (cancel_pressed) + break; + if (!opt_tuples_only) + { + if (current_format != 1) + { + if (opt_border == 2 && record > 1) + fputs("_\n", fout); + if (current_format != 0) + fputs(".T&\n", fout); + fputs("c s.\n", fout); + current_format = 1; + } + fprintf(fout, "\\fIRecord %lu\\fP\n", record++); + } + if (opt_border >= 1) + fputs("_\n", fout); + } + + if (!opt_tuples_only) + { + if (current_format != 2) + { + if (current_format != 0) + fputs(".T&\n", fout); + if (opt_border != 1) + fputs("c l.\n", fout); + else + fputs("c | l.\n", fout); + current_format = 2; + } + } + + troff_ms_escaped_print(cont->headers[i % cont->ncolumns], fout); + fputc('\t', fout); + troff_ms_escaped_print(*ptr, fout); + + fputc('\n', fout); + } + + if (cont->opt->stop_table) + { + fputs(".TE\n.DS L\n", fout); + + /* print footers */ + if (cont->footers && !opt_tuples_only && !cancel_pressed) + { + printTableFooter *f; + + for (f = cont->footers; f; f = f->next) + { + troff_ms_escaped_print(f->data, fout); + fputc('\n', fout); + } + } + + fputs(".DE\n", fout); + } +} + + +/********************************/ +/* Public functions */ +/********************************/ + + +/* + * disable_sigpipe_trap + * + * Turn off SIGPIPE interrupt --- call this before writing to a temporary + * query output file that is a pipe. + * + * No-op on Windows, where there's no SIGPIPE interrupts. + */ +void +disable_sigpipe_trap(void) +{ +#ifndef WIN32 + pqsignal(SIGPIPE, SIG_IGN); +#endif +} + +/* + * restore_sigpipe_trap + * + * Restore normal SIGPIPE interrupt --- call this when done writing to a + * temporary query output file that was (or might have been) a pipe. + * + * Note: within psql, we enable SIGPIPE interrupts unless the permanent query + * output file is a pipe, in which case they should be kept off. This + * approach works only because psql is not currently complicated enough to + * have nested usages of short-lived output files. Otherwise we'd probably + * need a genuine save-and-restore-state approach; but for now, that would be + * useless complication. In non-psql programs, this always enables SIGPIPE. + * + * No-op on Windows, where there's no SIGPIPE interrupts. + */ +void +restore_sigpipe_trap(void) +{ +#ifndef WIN32 + pqsignal(SIGPIPE, always_ignore_sigpipe ? SIG_IGN : SIG_DFL); +#endif +} + +/* + * set_sigpipe_trap_state + * + * Set the trap state that restore_sigpipe_trap should restore to. + */ +void +set_sigpipe_trap_state(bool ignore) +{ + always_ignore_sigpipe = ignore; +} + + +/* + * PageOutput + * + * Tests if pager is needed and returns appropriate FILE pointer. + * + * If the topt argument is NULL no pager is used. + */ +FILE * +PageOutput(int lines, const printTableOpt *topt) +{ + /* check whether we need / can / are supposed to use pager */ + if (topt && topt->pager && isatty(fileno(stdin)) && isatty(fileno(stdout))) + { +#ifdef TIOCGWINSZ + unsigned short int pager = topt->pager; + int min_lines = topt->pager_min_lines; + int result; + struct winsize screen_size; + + result = ioctl(fileno(stdout), TIOCGWINSZ, &screen_size); + + /* >= accounts for a one-line prompt */ + if (result == -1 + || (lines >= screen_size.ws_row && lines >= min_lines) + || pager > 1) +#endif + { + const char *pagerprog; + FILE *pagerpipe; + + pagerprog = getenv("PAGER"); + if (!pagerprog) + pagerprog = DEFAULT_PAGER; + disable_sigpipe_trap(); + pagerpipe = popen(pagerprog, "w"); + if (pagerpipe) + return pagerpipe; + } + } + + return stdout; +} + +/* + * ClosePager + * + * Close previously opened pager pipe, if any + */ +void +ClosePager(FILE *pagerpipe) +{ + if (pagerpipe && pagerpipe != stdout) + { + /* + * If printing was canceled midstream, warn about it. + * + * Some pagers like less use Ctrl-C as part of their command set. Even + * so, we abort our processing and warn the user what we did. If the + * pager quit as a result of the SIGINT, this message won't go + * anywhere ... + */ + if (cancel_pressed) + fprintf(pagerpipe, _("Interrupted\n")); + + pclose(pagerpipe); + restore_sigpipe_trap(); + } +} + +/* + * Initialise a table contents struct. + * Must be called before any other printTable method is used. + * + * The title is not duplicated; the caller must ensure that the buffer + * is available for the lifetime of the printTableContent struct. + * + * If you call this, you must call printTableCleanup once you're done with the + * table. + */ +void +printTableInit(printTableContent *const content, const printTableOpt *opt, + const char *title, const int ncolumns, const int nrows) +{ + content->opt = opt; + content->title = title; + content->ncolumns = ncolumns; + content->nrows = nrows; + + content->headers = pg_malloc0((ncolumns + 1) * sizeof(*content->headers)); + + content->cells = pg_malloc0((ncolumns * nrows + 1) * sizeof(*content->cells)); + + content->cellmustfree = NULL; + content->footers = NULL; + + content->aligns = pg_malloc0((ncolumns + 1) * sizeof(*content->align)); + + content->header = content->headers; + content->cell = content->cells; + content->footer = content->footers; + content->align = content->aligns; + content->cellsadded = 0; +} + +/* + * Add a header to the table. + * + * Headers are not duplicated; you must ensure that the header string is + * available for the lifetime of the printTableContent struct. + * + * If translate is true, the function will pass the header through gettext. + * Otherwise, the header will not be translated. + * + * align is either 'l' or 'r', and specifies the alignment for cells in this + * column. + */ +void +printTableAddHeader(printTableContent *const content, char *header, + const bool translate, const char align) +{ +#ifndef ENABLE_NLS + (void) translate; /* unused parameter */ +#endif + + if (content->header >= content->headers + content->ncolumns) + { + fprintf(stderr, _("Cannot add header to table content: " + "column count of %d exceeded.\n"), + content->ncolumns); + exit(EXIT_FAILURE); + } + + *content->header = (char *) mbvalidate((unsigned char *) header, + content->opt->encoding); +#ifdef ENABLE_NLS + if (translate) + *content->header = _(*content->header); +#endif + content->header++; + + *content->align = align; + content->align++; +} + +/* + * Add a cell to the table. + * + * Cells are not duplicated; you must ensure that the cell string is available + * for the lifetime of the printTableContent struct. + * + * If translate is true, the function will pass the cell through gettext. + * Otherwise, the cell will not be translated. + * + * If mustfree is true, the cell string is freed by printTableCleanup(). + * Note: Automatic freeing of translatable strings is not supported. + */ +void +printTableAddCell(printTableContent *const content, char *cell, + const bool translate, const bool mustfree) +{ +#ifndef ENABLE_NLS + (void) translate; /* unused parameter */ +#endif + + if (content->cellsadded >= content->ncolumns * content->nrows) + { + fprintf(stderr, _("Cannot add cell to table content: " + "total cell count of %d exceeded.\n"), + content->ncolumns * content->nrows); + exit(EXIT_FAILURE); + } + + *content->cell = (char *) mbvalidate((unsigned char *) cell, + content->opt->encoding); + +#ifdef ENABLE_NLS + if (translate) + *content->cell = _(*content->cell); +#endif + + if (mustfree) + { + if (content->cellmustfree == NULL) + content->cellmustfree = + pg_malloc0((content->ncolumns * content->nrows + 1) * sizeof(bool)); + + content->cellmustfree[content->cellsadded] = true; + } + content->cell++; + content->cellsadded++; +} + +/* + * Add a footer to the table. + * + * Footers are added as elements of a singly-linked list, and the content is + * strdup'd, so there is no need to keep the original footer string around. + * + * Footers are never translated by the function. If you want the footer + * translated you must do so yourself, before calling printTableAddFooter. The + * reason this works differently to headers and cells is that footers tend to + * be made of up individually translated components, rather than being + * translated as a whole. + */ +void +printTableAddFooter(printTableContent *const content, const char *footer) +{ + printTableFooter *f; + + f = pg_malloc0(sizeof(*f)); + f->data = pg_strdup(footer); + + if (content->footers == NULL) + content->footers = f; + else + content->footer->next = f; + + content->footer = f; +} + +/* + * Change the content of the last-added footer. + * + * The current contents of the last-added footer are freed, and replaced by the + * content given in *footer. If there was no previous footer, add a new one. + * + * The content is strdup'd, so there is no need to keep the original string + * around. + */ +void +printTableSetFooter(printTableContent *const content, const char *footer) +{ + if (content->footers != NULL) + { + free(content->footer->data); + content->footer->data = pg_strdup(footer); + } + else + printTableAddFooter(content, footer); +} + +/* + * Free all memory allocated to this struct. + * + * Once this has been called, the struct is unusable unless you pass it to + * printTableInit() again. + */ +void +printTableCleanup(printTableContent *const content) +{ + if (content->cellmustfree) + { + int i; + + for (i = 0; i < content->nrows * content->ncolumns; i++) + { + if (content->cellmustfree[i]) + free((char *) content->cells[i]); + } + free(content->cellmustfree); + content->cellmustfree = NULL; + } + free(content->headers); + free(content->cells); + free(content->aligns); + + content->opt = NULL; + content->title = NULL; + content->headers = NULL; + content->cells = NULL; + content->aligns = NULL; + content->header = NULL; + content->cell = NULL; + content->align = NULL; + + if (content->footers) + { + for (content->footer = content->footers; content->footer;) + { + printTableFooter *f; + + f = content->footer; + content->footer = f->next; + free(f->data); + free(f); + } + } + content->footers = NULL; + content->footer = NULL; +} + +/* + * IsPagerNeeded + * + * Setup pager if required + */ +static void +IsPagerNeeded(const printTableContent *cont, int extra_lines, bool expanded, + FILE **fout, bool *is_pager) +{ + if (*fout == stdout) + { + int lines; + + if (expanded) + lines = (cont->ncolumns + 1) * cont->nrows; + else + lines = cont->nrows + 1; + + if (!cont->opt->tuples_only) + { + printTableFooter *f; + + /* + * FIXME -- this is slightly bogus: it counts the number of + * footers, not the number of lines in them. + */ + for (f = cont->footers; f; f = f->next) + lines++; + } + + *fout = PageOutput(lines + extra_lines, cont->opt); + *is_pager = (*fout != stdout); + } + else + *is_pager = false; +} + +/* + * Use this to print any table in the supported formats. + * + * cont: table data and formatting options + * fout: where to print to + * is_pager: true if caller has already redirected fout to be a pager pipe + * flog: if not null, also print the table there (for --log-file option) + */ +void +printTable(const printTableContent *cont, + FILE *fout, bool is_pager, FILE *flog) +{ + bool is_local_pager = false; + + if (cancel_pressed) + return; + + if (cont->opt->format == PRINT_NOTHING) + return; + + /* print_aligned_*() handle the pager themselves */ + if (!is_pager && + cont->opt->format != PRINT_ALIGNED && + cont->opt->format != PRINT_WRAPPED) + { + IsPagerNeeded(cont, 0, (cont->opt->expanded == 1), &fout, &is_pager); + is_local_pager = is_pager; + } + + /* print the stuff */ + + if (flog) + print_aligned_text(cont, flog, false); + + switch (cont->opt->format) + { + case PRINT_UNALIGNED: + if (cont->opt->expanded == 1) + print_unaligned_vertical(cont, fout); + else + print_unaligned_text(cont, fout); + break; + case PRINT_ALIGNED: + case PRINT_WRAPPED: + + /* + * In expanded-auto mode, force vertical if a pager is passed in; + * else we may make different decisions for different hunks of the + * query result. + */ + if (cont->opt->expanded == 1 || + (cont->opt->expanded == 2 && is_pager)) + print_aligned_vertical(cont, fout, is_pager); + else + print_aligned_text(cont, fout, is_pager); + break; + case PRINT_HTML: + if (cont->opt->expanded == 1) + print_html_vertical(cont, fout); + else + print_html_text(cont, fout); + break; + case PRINT_ASCIIDOC: + if (cont->opt->expanded == 1) + print_asciidoc_vertical(cont, fout); + else + print_asciidoc_text(cont, fout); + break; + case PRINT_LATEX: + if (cont->opt->expanded == 1) + print_latex_vertical(cont, fout); + else + print_latex_text(cont, fout); + break; + case PRINT_LATEX_LONGTABLE: + if (cont->opt->expanded == 1) + print_latex_vertical(cont, fout); + else + print_latex_longtable_text(cont, fout); + break; + case PRINT_TROFF_MS: + if (cont->opt->expanded == 1) + print_troff_ms_vertical(cont, fout); + else + print_troff_ms_text(cont, fout); + break; + default: + fprintf(stderr, _("invalid output format (internal error): %d"), + cont->opt->format); + exit(EXIT_FAILURE); + } + + if (is_local_pager) + ClosePager(fout); +} + +/* + * Use this to print query results + * + * result: result of a successful query + * opt: formatting options + * fout: where to print to + * is_pager: true if caller has already redirected fout to be a pager pipe + * flog: if not null, also print the data there (for --log-file option) + */ +void +printQuery(const PGresult *result, const printQueryOpt *opt, + FILE *fout, bool is_pager, FILE *flog) +{ + printTableContent cont; + int i, + r, + c; + + if (cancel_pressed) + return; + + printTableInit(&cont, &opt->topt, opt->title, + PQnfields(result), PQntuples(result)); + + /* Assert caller supplied enough translate_columns[] entries */ + Assert(opt->translate_columns == NULL || + opt->n_translate_columns >= cont.ncolumns); + + for (i = 0; i < cont.ncolumns; i++) + { + char align; + Oid ftype = PQftype(result, i); + + switch (ftype) + { + case INT2OID: + case INT4OID: + case INT8OID: + case FLOAT4OID: + case FLOAT8OID: + case NUMERICOID: + case OIDOID: + case XIDOID: + case CIDOID: + case CASHOID: + align = 'r'; + break; + default: + align = 'l'; + break; + } + + printTableAddHeader(&cont, PQfname(result, i), + opt->translate_header, align); + } + + /* set cells */ + for (r = 0; r < cont.nrows; r++) + { + for (c = 0; c < cont.ncolumns; c++) + { + char *cell; + bool mustfree = false; + bool translate; + + if (PQgetisnull(result, r, c)) + cell = opt->nullPrint ? opt->nullPrint : ""; + else + { + cell = PQgetvalue(result, r, c); + if (cont.aligns[c] == 'r' && opt->topt.numericLocale) + { + cell = format_numeric_locale(cell); + mustfree = true; + } + } + + translate = (opt->translate_columns && opt->translate_columns[c]); + printTableAddCell(&cont, cell, translate, mustfree); + } + } + + /* set footers */ + if (opt->footers) + { + char **footer; + + for (footer = opt->footers; *footer; footer++) + printTableAddFooter(&cont, *footer); + } + + printTable(&cont, fout, is_pager, flog); + printTableCleanup(&cont); +} + + +void +setDecimalLocale(void) +{ + struct lconv *extlconv; + + extlconv = localeconv(); + + /* Don't accept an empty decimal_point string */ + if (*extlconv->decimal_point) + decimal_point = pg_strdup(extlconv->decimal_point); + else + decimal_point = "."; /* SQL output standard */ + + /* + * Although the Open Group standard allows locales to supply more than one + * group width, we consider only the first one, and we ignore any attempt + * to suppress grouping by specifying CHAR_MAX. As in the backend's + * cash.c, we must apply a range check to avoid being fooled by variant + * CHAR_MAX values. + */ + groupdigits = *extlconv->grouping; + if (groupdigits <= 0 || groupdigits > 6) + groupdigits = 3; /* most common */ + + /* Don't accept an empty thousands_sep string, either */ + /* similar code exists in formatting.c */ + if (*extlconv->thousands_sep) + thousands_sep = pg_strdup(extlconv->thousands_sep); + /* Make sure thousands separator doesn't match decimal point symbol. */ + else if (strcmp(decimal_point, ",") != 0) + thousands_sep = ","; + else + thousands_sep = "."; +} + +/* get selected or default line style */ +const printTextFormat * +get_line_style(const printTableOpt *opt) +{ + /* + * Note: this function mainly exists to preserve the convention that a + * printTableOpt struct can be initialized to zeroes to get default + * behavior. + */ + if (opt->line_style != NULL) + return opt->line_style; + else + return &pg_asciiformat; +} + +void +refresh_utf8format(const printTableOpt *opt) +{ + printTextFormat *popt = (printTextFormat *) &pg_utf8format; + + const unicodeStyleBorderFormat *border; + const unicodeStyleRowFormat *header; + const unicodeStyleColumnFormat *column; + + popt->name = "unicode"; + + border = &unicode_style.border_style[opt->unicode_border_linestyle]; + header = &unicode_style.row_style[opt->unicode_header_linestyle]; + column = &unicode_style.column_style[opt->unicode_column_linestyle]; + + popt->lrule[PRINT_RULE_TOP].hrule = border->horizontal; + popt->lrule[PRINT_RULE_TOP].leftvrule = border->down_and_right; + popt->lrule[PRINT_RULE_TOP].midvrule = column->down_and_horizontal[opt->unicode_border_linestyle]; + popt->lrule[PRINT_RULE_TOP].rightvrule = border->down_and_left; + + popt->lrule[PRINT_RULE_MIDDLE].hrule = header->horizontal; + popt->lrule[PRINT_RULE_MIDDLE].leftvrule = header->vertical_and_right[opt->unicode_border_linestyle]; + popt->lrule[PRINT_RULE_MIDDLE].midvrule = column->vertical_and_horizontal[opt->unicode_header_linestyle]; + popt->lrule[PRINT_RULE_MIDDLE].rightvrule = header->vertical_and_left[opt->unicode_border_linestyle]; + + popt->lrule[PRINT_RULE_BOTTOM].hrule = border->horizontal; + popt->lrule[PRINT_RULE_BOTTOM].leftvrule = border->up_and_right; + popt->lrule[PRINT_RULE_BOTTOM].midvrule = column->up_and_horizontal[opt->unicode_border_linestyle]; + popt->lrule[PRINT_RULE_BOTTOM].rightvrule = border->left_and_right; + + /* N/A */ + popt->lrule[PRINT_RULE_DATA].hrule = ""; + popt->lrule[PRINT_RULE_DATA].leftvrule = border->vertical; + popt->lrule[PRINT_RULE_DATA].midvrule = column->vertical; + popt->lrule[PRINT_RULE_DATA].rightvrule = border->vertical; + + popt->midvrule_nl = column->vertical; + popt->midvrule_wrap = column->vertical; + popt->midvrule_blank = column->vertical; + + /* Same for all unicode today */ + popt->header_nl_left = unicode_style.header_nl_left; + popt->header_nl_right = unicode_style.header_nl_right; + popt->nl_left = unicode_style.nl_left; + popt->nl_right = unicode_style.nl_right; + popt->wrap_left = unicode_style.wrap_left; + popt->wrap_right = unicode_style.wrap_right; + popt->wrap_right_border = unicode_style.wrap_right_border; + + return; +} + +/* + * Compute the byte distance to the end of the string or *target_width + * display character positions, whichever comes first. Update *target_width + * to be the number of display character positions actually filled. + */ +static int +strlen_max_width(unsigned char *str, int *target_width, int encoding) +{ + unsigned char *start = str; + unsigned char *end = str + strlen((char *) str); + int curr_width = 0; + + while (str < end) + { + int char_width = PQdsplen((char *) str, encoding); + + /* + * If the display width of the new character causes the string to + * exceed its target width, skip it and return. However, if this is + * the first character of the string (curr_width == 0), we have to + * accept it. + */ + if (*target_width < curr_width + char_width && curr_width != 0) + break; + + curr_width += char_width; + + str += PQmblen((char *) str, encoding); + } + + *target_width = curr_width; + + return str - start; +} diff --git a/src/bin/csql/print.h b/src/bin/csql/print.h new file mode 100644 index 000000000..fd5659842 --- /dev/null +++ b/src/bin/csql/print.h @@ -0,0 +1,206 @@ +/* + * psql - the PostgreSQL interactive terminal + * + * Copyright (c) 2000-2015, PostgreSQL Global Development Group + * + * src/bin/psql/print.h + */ +#ifndef PRINT_H +#define PRINT_H + +#include "libpq-fe.h" + + +enum printFormat +{ + PRINT_NOTHING = 0, /* to make sure someone initializes this */ + PRINT_UNALIGNED, + PRINT_ALIGNED, + PRINT_WRAPPED, + PRINT_HTML, + PRINT_ASCIIDOC, + PRINT_LATEX, + PRINT_LATEX_LONGTABLE, + PRINT_TROFF_MS + /* add your favourite output format here ... */ +}; + +typedef struct printTextLineFormat +{ + /* Line drawing characters to be used in various contexts */ + const char *hrule; /* horizontal line character */ + const char *leftvrule; /* left vertical line (+horizontal) */ + const char *midvrule; /* intra-column vertical line (+horizontal) */ + const char *rightvrule; /* right vertical line (+horizontal) */ +} printTextLineFormat; + +typedef enum printTextRule +{ + /* Additional context for selecting line drawing characters */ + PRINT_RULE_TOP, /* top horizontal line */ + PRINT_RULE_MIDDLE, /* intra-data horizontal line */ + PRINT_RULE_BOTTOM, /* bottom horizontal line */ + PRINT_RULE_DATA /* data line (hrule is unused here) */ +} printTextRule; + +typedef enum printTextLineWrap +{ + /* Line wrapping conditions */ + PRINT_LINE_WRAP_NONE, /* No wrapping */ + PRINT_LINE_WRAP_WRAP, /* Wraparound due to overlength line */ + PRINT_LINE_WRAP_NEWLINE /* Newline in data */ +} printTextLineWrap; + +typedef struct printTextFormat +{ + /* A complete line style */ + const char *name; /* for display purposes */ + printTextLineFormat lrule[4]; /* indexed by enum printTextRule */ + const char *midvrule_nl; /* vertical line for continue after newline */ + const char *midvrule_wrap; /* vertical line for wrapped data */ + const char *midvrule_blank; /* vertical line for blank data */ + const char *header_nl_left; /* left mark after newline */ + const char *header_nl_right; /* right mark for newline */ + const char *nl_left; /* left mark after newline */ + const char *nl_right; /* right mark for newline */ + const char *wrap_left; /* left mark after wrapped data */ + const char *wrap_right; /* right mark for wrapped data */ + bool wrap_right_border; /* use right-hand border for wrap + * marks when border=0? */ +} printTextFormat; + +typedef enum unicode_linestyle +{ + UNICODE_LINESTYLE_SINGLE = 0, + UNICODE_LINESTYLE_DOUBLE +} unicode_linestyle; + +struct separator +{ + char *separator; + bool separator_zero; +}; + +typedef struct printTableOpt +{ + enum printFormat format; /* see enum above */ + unsigned short int expanded;/* expanded/vertical output (if supported by + * output format); 0=no, 1=yes, 2=auto */ + unsigned short int border; /* Print a border around the table. 0=none, + * 1=dividing lines, 2=full */ + unsigned short int pager; /* use pager for output (if to stdout and + * stdout is a tty) 0=off 1=on 2=always */ + int pager_min_lines;/* don't use pager unless there are at least + * this many lines */ + bool tuples_only; /* don't output headers, row counts, etc. */ + bool start_table; /* print start decoration, eg */ + bool stop_table; /* print stop decoration, eg
*/ + bool default_footer; /* allow "(xx rows)" default footer */ + unsigned long prior_records; /* start offset for record counters */ + const printTextFormat *line_style; /* line style (NULL for default) */ + struct separator fieldSep; /* field separator for unaligned text mode */ + struct separator recordSep; /* record separator for unaligned text mode */ + bool numericLocale; /* locale-aware numeric units separator and + * decimal marker */ + char *tableAttr; /* attributes for HTML */ + int encoding; /* character encoding */ + int env_columns; /* $COLUMNS on psql start, 0 is unset */ + int columns; /* target width for wrapped format */ + unicode_linestyle unicode_border_linestyle; + unicode_linestyle unicode_column_linestyle; + unicode_linestyle unicode_header_linestyle; +} printTableOpt; + +/* + * Table footers are implemented as a singly-linked list. + * + * This is so that you don't need to know the number of footers in order to + * initialise the printTableContent struct, which is very convenient when + * preparing complex footers (as in describeOneTableDetails). + */ +typedef struct printTableFooter +{ + char *data; + struct printTableFooter *next; +} printTableFooter; + +/* + * The table content struct holds all the information which will be displayed + * by printTable(). + */ +typedef struct printTableContent +{ + const printTableOpt *opt; + const char *title; /* May be NULL */ + int ncolumns; /* Specified in Init() */ + int nrows; /* Specified in Init() */ + const char **headers; /* NULL-terminated array of header strings */ + const char **header; /* Pointer to the last added header */ + const char **cells; /* NULL-terminated array of cell content + * strings */ + const char **cell; /* Pointer to the last added cell */ + long cellsadded; /* Number of cells added this far */ + bool *cellmustfree; /* true for cells that need to be free()d */ + printTableFooter *footers; /* Pointer to the first footer */ + printTableFooter *footer; /* Pointer to the last added footer */ + char *aligns; /* Array of alignment specifiers; 'l' or 'r', + * one per column */ + char *align; /* Pointer to the last added alignment */ +} printTableContent; + +typedef struct printQueryOpt +{ + printTableOpt topt; /* the options above */ + char *nullPrint; /* how to print null entities */ + bool quote; /* quote all values as much as possible */ + char *title; /* override title */ + char **footers; /* override footer (default is "(xx rows)") */ + bool translate_header; /* do gettext on column headers */ + const bool *translate_columns; /* translate_columns[i-1] => do + * gettext on col i */ + int n_translate_columns; /* length of translate_columns[] */ +} printQueryOpt; + + +extern const printTextFormat pg_asciiformat; +extern const printTextFormat pg_asciiformat_old; +extern const printTextFormat pg_utf8format; + + +extern void disable_sigpipe_trap(void); +extern void restore_sigpipe_trap(void); +extern void set_sigpipe_trap_state(bool ignore); + +extern FILE *PageOutput(int lines, const printTableOpt *topt); +extern void ClosePager(FILE *pagerpipe); + +extern void html_escaped_print(const char *in, FILE *fout); + +extern void printTableInit(printTableContent *const content, + const printTableOpt *opt, const char *title, + const int ncolumns, const int nrows); +extern void printTableAddHeader(printTableContent *const content, + char *header, const bool translate, const char align); +extern void printTableAddCell(printTableContent *const content, + char *cell, const bool translate, const bool mustfree); +extern void printTableAddFooter(printTableContent *const content, + const char *footer); +extern void printTableSetFooter(printTableContent *const content, + const char *footer); +extern void printTableCleanup(printTableContent *const content); +extern void printTable(const printTableContent *cont, + FILE *fout, bool is_pager, FILE *flog); +extern void printQuery(const PGresult *result, const printQueryOpt *opt, + FILE *fout, bool is_pager, FILE *flog); + +extern void setDecimalLocale(void); +extern const printTextFormat *get_line_style(const printTableOpt *opt); +extern void refresh_utf8format(const printTableOpt *opt); + +#ifndef __CYGWIN__ +#define DEFAULT_PAGER "more" +#else +#define DEFAULT_PAGER "less" +#endif + +#endif /* PRINT_H */ diff --git a/src/bin/csql/prompt.c b/src/bin/csql/prompt.c new file mode 100644 index 000000000..89842673f --- /dev/null +++ b/src/bin/csql/prompt.c @@ -0,0 +1,325 @@ +/* + * psql - the PostgreSQL interactive terminal + * + * Copyright (c) 2000-2015, PostgreSQL Global Development Group + * + * src/bin/psql/prompt.c + */ +#include "postgres_fe.h" + +#ifdef WIN32 +#include +#include +#endif + +#ifdef HAVE_UNIX_SOCKETS +#include +#include +#endif + +#include "common.h" +#include "input.h" +#include "prompt.h" +#include "settings.h" + + +/*-------------------------- + * get_prompt + * + * Returns a statically allocated prompt made by interpolating certain + * tcsh style escape sequences into pset.vars "PROMPT1|2|3". + * (might not be completely multibyte safe) + * + * Defined interpolations are: + * %M - database server "hostname.domainname", "[local]" for AF_UNIX + * sockets, "[local:/dir/name]" if not default + * %m - like %M, but hostname only (before first dot), or always "[local]" + * %> - database server port number + * %n - database user name + * %/ - current database + * %~ - like %/ but "~" when database name equals user name + * %# - "#" if superuser, ">" otherwise + * %R - in prompt1 normally =, or ^ if single line mode, + * or a ! if session is not connected to a database; + * in prompt2 -, *, ', or "; + * in prompt3 nothing + * %x - transaction status: empty, *, !, ? (unknown or no connection) + * %l - The line number inside the current statement, starting from 1. + * %? - the error code of the last query (not yet implemented) + * %% - a percent sign + * + * %[0-9] - the character with the given decimal code + * %0[0-7] - the character with the given octal code + * %0x[0-9A-Fa-f] - the character with the given hexadecimal code + * + * %`command` - The result of executing command in /bin/sh with trailing + * newline stripped. + * %:name: - The value of the psql variable 'name' + * (those will not be rescanned for more escape sequences!) + * + * %[ ... %] - tell readline that the contained text is invisible + * + * If the application-wide prompts become NULL somehow, the returned string + * will be empty (not NULL!). + *-------------------------- + */ + +char * +get_prompt(promptStatus_t status) +{ +#define MAX_PROMPT_SIZE 256 + static char destination[MAX_PROMPT_SIZE + 1]; + char buf[MAX_PROMPT_SIZE + 1]; + bool esc = false; + const char *p; + const char *prompt_string = "? "; + + switch (status) + { + case PROMPT_READY: + prompt_string = pset.prompt1; + break; + + case PROMPT_CONTINUE: + case PROMPT_SINGLEQUOTE: + case PROMPT_DOUBLEQUOTE: + case PROMPT_DOLLARQUOTE: + case PROMPT_COMMENT: + case PROMPT_PAREN: + prompt_string = pset.prompt2; + break; + + case PROMPT_COPY: + prompt_string = pset.prompt3; + break; + } + + destination[0] = '\0'; + + for (p = prompt_string; + *p && strlen(destination) < sizeof(destination) - 1; + p++) + { + memset(buf, 0, sizeof(buf)); + if (esc) + { + switch (*p) + { + /* Current database */ + case '/': + if (pset.db) + strlcpy(buf, PQdb(pset.db), sizeof(buf)); + break; + case '~': + if (pset.db) + { + const char *var; + + if (strcmp(PQdb(pset.db), PQuser(pset.db)) == 0 || + ((var = getenv("PGDATABASE")) && strcmp(var, PQdb(pset.db)) == 0)) + strlcpy(buf, "~", sizeof(buf)); + else + strlcpy(buf, PQdb(pset.db), sizeof(buf)); + } + break; + + /* DB server hostname (long/short) */ + case 'M': + case 'm': + if (pset.db) + { + const char *host = PQhost(pset.db); + + /* INET socket */ + if (host && host[0] && !is_absolute_path(host)) + { + strlcpy(buf, host, sizeof(buf)); + if (*p == 'm') + buf[strcspn(buf, ".")] = '\0'; + } +#ifdef HAVE_UNIX_SOCKETS + /* UNIX socket */ + else + { + if (!host + || strcmp(host, DEFAULT_PGSOCKET_DIR) == 0 + || *p == 'm') + strlcpy(buf, "[local]", sizeof(buf)); + else + snprintf(buf, sizeof(buf), "[local:%s]", host); + } +#endif + } + break; + /* DB server port number */ + case '>': + if (pset.db && PQport(pset.db)) + strlcpy(buf, PQport(pset.db), sizeof(buf)); + break; + /* DB server user name */ + case 'n': + if (pset.db) + strlcpy(buf, session_username(), sizeof(buf)); + break; + + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + *buf = (char) strtol(p, (char **) &p, 8); + --p; + break; + case 'R': + switch (status) + { + case PROMPT_READY: + if (!pset.db) + buf[0] = '!'; + else if (!pset.singleline) + buf[0] = '='; + else + buf[0] = '^'; + break; + case PROMPT_CONTINUE: + buf[0] = '-'; + break; + case PROMPT_SINGLEQUOTE: + buf[0] = '\''; + break; + case PROMPT_DOUBLEQUOTE: + buf[0] = '"'; + break; + case PROMPT_DOLLARQUOTE: + buf[0] = '$'; + break; + case PROMPT_COMMENT: + buf[0] = '*'; + break; + case PROMPT_PAREN: + buf[0] = '('; + break; + default: + buf[0] = '\0'; + break; + } + break; + + case 'x': + if (!pset.db) + buf[0] = '?'; + else + switch (PQtransactionStatus(pset.db)) + { + case PQTRANS_IDLE: + buf[0] = '\0'; + break; + case PQTRANS_ACTIVE: + case PQTRANS_INTRANS: + buf[0] = '*'; + break; + case PQTRANS_INERROR: + buf[0] = '!'; + break; + default: + buf[0] = '?'; + break; + } + break; + + case 'l': + snprintf(buf, sizeof(buf), UINT64_FORMAT, pset.stmt_lineno); + break; + + case '?': + /* not here yet */ + break; + + case '#': + if (is_superuser()) + buf[0] = '#'; + else + buf[0] = '>'; + break; + + /* execute command */ + case '`': + { + FILE *fd; + char *file = pg_strdup(p + 1); + int cmdend; + + cmdend = strcspn(file, "`"); + file[cmdend] = '\0'; + fd = popen(file, "r"); + if (fd) + { + if (fgets(buf, sizeof(buf), fd) == NULL) + buf[0] = '\0'; + pclose(fd); + } + if (strlen(buf) > 0 && buf[strlen(buf) - 1] == '\n') + buf[strlen(buf) - 1] = '\0'; + free(file); + p += cmdend + 1; + break; + } + + /* interpolate variable */ + case ':': + { + char *name; + const char *val; + int nameend; + + name = pg_strdup(p + 1); + nameend = strcspn(name, ":"); + name[nameend] = '\0'; + val = GetVariable(pset.vars, name); + if (val) + strlcpy(buf, val, sizeof(buf)); + free(name); + p += nameend + 1; + break; + } + + case '[': + case ']': +#if defined(USE_READLINE) && defined(RL_PROMPT_START_IGNORE) + + /* + * readline >=4.0 undocumented feature: non-printing + * characters in prompt strings must be marked as such, in + * order to properly display the line during editing. + */ + buf[0] = (*p == '[') ? RL_PROMPT_START_IGNORE : RL_PROMPT_END_IGNORE; + buf[1] = '\0'; +#endif /* USE_READLINE */ + break; + + default: + buf[0] = *p; + buf[1] = '\0'; + break; + + } + esc = false; + } + else if (*p == '%') + esc = true; + else + { + buf[0] = *p; + buf[1] = '\0'; + esc = false; + } + + if (!esc) + strlcat(destination, buf, sizeof(destination)); + } + + return destination; +} diff --git a/src/bin/csql/prompt.h b/src/bin/csql/prompt.h new file mode 100644 index 000000000..e3f6ce55b --- /dev/null +++ b/src/bin/csql/prompt.h @@ -0,0 +1,25 @@ +/* + * psql - the PostgreSQL interactive terminal + * + * Copyright (c) 2000-2015, PostgreSQL Global Development Group + * + * src/bin/psql/prompt.h + */ +#ifndef PROMPT_H +#define PROMPT_H + +typedef enum _promptStatus +{ + PROMPT_READY, + PROMPT_CONTINUE, + PROMPT_COMMENT, + PROMPT_SINGLEQUOTE, + PROMPT_DOUBLEQUOTE, + PROMPT_DOLLARQUOTE, + PROMPT_PAREN, + PROMPT_COPY +} promptStatus_t; + +char *get_prompt(promptStatus_t status); + +#endif /* PROMPT_H */ diff --git a/src/bin/csql/psqlrc.sample b/src/bin/csql/psqlrc.sample new file mode 100644 index 000000000..8152cace2 --- /dev/null +++ b/src/bin/csql/psqlrc.sample @@ -0,0 +1,8 @@ +-- +-- system-wide psql configuration file +-- +-- This file is read before the .psqlrc file in the user's home directory. +-- +-- Copy this to your installation's sysconf directory and rename it psqlrc. +-- The sysconf directory can be identified via "pg_config --sysconfdir". +-- diff --git a/src/bin/csql/psqlscan.h b/src/bin/csql/psqlscan.h new file mode 100644 index 000000000..55070ca46 --- /dev/null +++ b/src/bin/csql/psqlscan.h @@ -0,0 +1,64 @@ +/* + * psql - the PostgreSQL interactive terminal + * + * Copyright (c) 2000-2015, PostgreSQL Global Development Group + * + * src/bin/psql/psqlscan.h + */ +#ifndef PSQLSCAN_H +#define PSQLSCAN_H + +#include "pqexpbuffer.h" + +#include "prompt.h" + + +/* Abstract type for lexer's internal state */ +typedef struct PsqlScanStateData *PsqlScanState; + +/* Termination states for psql_scan() */ +typedef enum +{ + PSCAN_SEMICOLON, /* found command-ending semicolon */ + PSCAN_BACKSLASH, /* found backslash command */ + PSCAN_INCOMPLETE, /* end of line, SQL statement incomplete */ + PSCAN_EOL /* end of line, SQL possibly complete */ +} PsqlScanResult; + +/* Different ways for scan_slash_option to handle parameter words */ +enum slash_option_type +{ + OT_NORMAL, /* normal case */ + OT_SQLID, /* treat as SQL identifier */ + OT_SQLIDHACK, /* SQL identifier, but don't downcase */ + OT_FILEPIPE, /* it's a filename or pipe */ + OT_WHOLE_LINE, /* just snarf the rest of the line */ + OT_NO_EVAL /* no expansion of backticks or variables */ +}; + + +extern PsqlScanState psql_scan_create(void); +extern void psql_scan_destroy(PsqlScanState state); + +extern void psql_scan_setup(PsqlScanState state, + const char *line, int line_len); +extern void psql_scan_finish(PsqlScanState state); + +extern PsqlScanResult psql_scan(PsqlScanState state, + PQExpBuffer query_buf, + promptStatus_t *prompt); + +extern void psql_scan_reset(PsqlScanState state); + +extern bool psql_scan_in_quote(PsqlScanState state); + +extern char *psql_scan_slash_command(PsqlScanState state); + +extern char *psql_scan_slash_option(PsqlScanState state, + enum slash_option_type type, + char *quote, + bool semicolon); + +extern void psql_scan_slash_command_end(PsqlScanState state); + +#endif /* PSQLSCAN_H */ diff --git a/src/bin/csql/psqlscan.l b/src/bin/csql/psqlscan.l new file mode 100644 index 000000000..be059abd8 --- /dev/null +++ b/src/bin/csql/psqlscan.l @@ -0,0 +1,1988 @@ +%{ +/*------------------------------------------------------------------------- + * + * psqlscan.l + * lexical scanner for psql + * + * This code is mainly needed to determine where the end of a SQL statement + * is: we are looking for semicolons that are not within quotes, comments, + * or parentheses. The most reliable way to handle this is to borrow the + * backend's flex lexer rules, lock, stock, and barrel. The rules below + * are (except for a few) the same as the backend's, but their actions are + * just ECHO whereas the backend's actions generally do other things. + * + * XXX The rules in this file must be kept in sync with the backend lexer!!! + * + * XXX Avoid creating backtracking cases --- see the backend lexer for info. + * + * The most difficult aspect of this code is that we need to work in multibyte + * encodings that are not ASCII-safe. A "safe" encoding is one in which each + * byte of a multibyte character has the high bit set (it's >= 0x80). Since + * all our lexing rules treat all high-bit-set characters alike, we don't + * really need to care whether such a byte is part of a sequence or not. + * In an "unsafe" encoding, we still expect the first byte of a multibyte + * sequence to be >= 0x80, but later bytes might not be. If we scan such + * a sequence as-is, the lexing rules could easily be fooled into matching + * such bytes to ordinary ASCII characters. Our solution for this is to + * substitute 0xFF for each non-first byte within the data presented to flex. + * The flex rules will then pass the FF's through unmolested. The emit() + * subroutine is responsible for looking back to the original string and + * replacing FF's with the corresponding original bytes. + * + * Portions Copyright (c) 1996-2015, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * IDENTIFICATION + * src/bin/psql/psqlscan.l + * + *------------------------------------------------------------------------- + */ +#include "postgres_fe.h" + +#include "psqlscan.h" + +#include + +#include "common.h" +#include "settings.h" +#include "variables.h" + + +/* + * We use a stack of flex buffers to handle substitution of psql variables. + * Each stacked buffer contains the as-yet-unread text from one psql variable. + * When we pop the stack all the way, we resume reading from the outer buffer + * identified by scanbufhandle. + */ +typedef struct StackElem +{ + YY_BUFFER_STATE buf; /* flex input control structure */ + char *bufstring; /* data actually being scanned by flex */ + char *origstring; /* copy of original data, if needed */ + char *varname; /* name of variable providing data, or NULL */ + struct StackElem *next; +} StackElem; + +/* + * All working state of the lexer must be stored in PsqlScanStateData + * between calls. This allows us to have multiple open lexer operations, + * which is needed for nested include files. The lexer itself is not + * recursive, but it must be re-entrant. + */ +typedef struct PsqlScanStateData +{ + StackElem *buffer_stack; /* stack of variable expansion buffers */ + /* + * These variables always refer to the outer buffer, never to any + * stacked variable-expansion buffer. + */ + YY_BUFFER_STATE scanbufhandle; + char *scanbuf; /* start of outer-level input buffer */ + const char *scanline; /* current input line at outer level */ + + /* safe_encoding, curline, refline are used by emit() to replace FFs */ + int encoding; /* encoding being used now */ + bool safe_encoding; /* is current encoding "safe"? */ + const char *curline; /* actual flex input string for cur buf */ + const char *refline; /* original data for cur buffer */ + + /* + * All this state lives across successive input lines, until explicitly + * reset by psql_scan_reset. + */ + int start_state; /* saved YY_START */ + int paren_depth; /* depth of nesting in parentheses */ + int xcdepth; /* depth of nesting in slash-star comments */ + char *dolqstart; /* current $foo$ quote start string */ +} PsqlScanStateData; + +static PsqlScanState cur_state; /* current state while active */ + +static PQExpBuffer output_buf; /* current output buffer */ + +/* these variables do not need to be saved across calls */ +static enum slash_option_type option_type; +static char *option_quote; +static int unquoted_option_chars; +static int backtick_start_offset; + + +/* Return values from yylex() */ +#define LEXRES_EOL 0 /* end of input */ +#define LEXRES_SEMI 1 /* command-terminating semicolon found */ +#define LEXRES_BACKSLASH 2 /* backslash command start */ +#define LEXRES_OK 3 /* OK completion of backslash argument */ + + +static void evaluate_backtick(void); +static void push_new_buffer(const char *newstr, const char *varname); +static void pop_buffer_stack(PsqlScanState state); +static bool var_is_current_source(PsqlScanState state, const char *varname); +static YY_BUFFER_STATE prepare_buffer(const char *txt, int len, + char **txtcopy); +static void emit(const char *txt, int len); +static char *extract_substring(const char *txt, int len); +static void escape_variable(bool as_ident); + +#define ECHO emit(yytext, yyleng) + +%} + +%option 8bit +%option never-interactive +%option nodefault +%option noinput +%option nounput +%option noyywrap +%option warn + +/* + * All of the following definitions and rules should exactly match + * src/backend/parser/scan.l so far as the flex patterns are concerned. + * The rule bodies are just ECHO as opposed to what the backend does, + * however. (But be sure to duplicate code that affects the lexing process, + * such as BEGIN().) Also, psqlscan uses a single <> rule whereas + * scan.l has a separate one for each exclusive state. + */ + +/* + * OK, here is a short description of lex/flex rules behavior. + * The longest pattern which matches an input string is always chosen. + * For equal-length patterns, the first occurring in the rules list is chosen. + * INITIAL is the starting state, to which all non-conditional rules apply. + * Exclusive states change parsing rules while the state is active. When in + * an exclusive state, only those rules defined for that state apply. + * + * We use exclusive states for quoted strings, extended comments, + * and to eliminate parsing troubles for numeric strings. + * Exclusive states: + * bit string literal + * extended C-style comments + * delimited identifiers (double-quoted identifiers) + * hexadecimal numeric string + * standard quoted strings + * extended quoted strings (support backslash escape sequences) + * $foo$ quoted strings + * quoted identifier with Unicode escapes + * end of a quoted identifier with Unicode escapes, UESCAPE can follow + * quoted string with Unicode escapes + * end of a quoted string with Unicode escapes, UESCAPE can follow + * + * Note: we intentionally don't mimic the backend's state; we have + * no need to distinguish it from state, and no good way to get out + * of it in error cases. The backend just throws yyerror() in those + * cases, but that's not an option here. + */ + +%x xb +%x xc +%x xd +%x xh +%x xe +%x xq +%x xdolq +%x xui +%x xuiend +%x xus +%x xusend +/* Additional exclusive states for psql only: lex backslash commands */ +%x xslashcmd +%x xslashargstart +%x xslasharg +%x xslashquote +%x xslashbackquote +%x xslashdquote +%x xslashwholeline +%x xslashend + +/* + * In order to make the world safe for Windows and Mac clients as well as + * Unix ones, we accept either \n or \r as a newline. A DOS-style \r\n + * sequence will be seen as two successive newlines, but that doesn't cause + * any problems. Comments that start with -- and extend to the next + * newline are treated as equivalent to a single whitespace character. + * + * NOTE a fine point: if there is no newline following --, we will absorb + * everything to the end of the input as a comment. This is correct. Older + * versions of Postgres failed to recognize -- as a comment if the input + * did not end with a newline. + * + * XXX perhaps \f (formfeed) should be treated as a newline as well? + * + * XXX if you change the set of whitespace characters, fix scanner_isspace() + * to agree, and see also the plpgsql lexer. + */ + +space [ \t\n\r\f] +horiz_space [ \t\f] +newline [\n\r] +non_newline [^\n\r] + +comment ("--"{non_newline}*) + +whitespace ({space}+|{comment}) + +/* + * SQL requires at least one newline in the whitespace separating + * string literals that are to be concatenated. Silly, but who are we + * to argue? Note that {whitespace_with_newline} should not have * after + * it, whereas {whitespace} should generally have a * after it... + */ + +special_whitespace ({space}+|{comment}{newline}) +horiz_whitespace ({horiz_space}|{comment}) +whitespace_with_newline ({horiz_whitespace}*{newline}{special_whitespace}*) + +/* + * To ensure that {quotecontinue} can be scanned without having to back up + * if the full pattern isn't matched, we include trailing whitespace in + * {quotestop}. This matches all cases where {quotecontinue} fails to match, + * except for {quote} followed by whitespace and just one "-" (not two, + * which would start a {comment}). To cover that we have {quotefail}. + * The actions for {quotestop} and {quotefail} must throw back characters + * beyond the quote proper. + */ +quote ' +quotestop {quote}{whitespace}* +quotecontinue {quote}{whitespace_with_newline}{quote} +quotefail {quote}{whitespace}*"-" + +/* Bit string + * It is tempting to scan the string for only those characters + * which are allowed. However, this leads to silently swallowed + * characters if illegal characters are included in the string. + * For example, if xbinside is [01] then B'ABCD' is interpreted + * as a zero-length string, and the ABCD' is lost! + * Better to pass the string forward and let the input routines + * validate the contents. + */ +xbstart [bB]{quote} +xbinside [^']* + +/* Hexadecimal number */ +xhstart [xX]{quote} +xhinside [^']* + +/* National character */ +xnstart [nN]{quote} + +/* Quoted string that allows backslash escapes */ +xestart [eE]{quote} +xeinside [^\\']+ +xeescape [\\][^0-7] +xeoctesc [\\][0-7]{1,3} +xehexesc [\\]x[0-9A-Fa-f]{1,2} +xeunicode [\\](u[0-9A-Fa-f]{4}|U[0-9A-Fa-f]{8}) +xeunicodefail [\\](u[0-9A-Fa-f]{0,3}|U[0-9A-Fa-f]{0,7}) + +/* Extended quote + * xqdouble implements embedded quote, '''' + */ +xqstart {quote} +xqdouble {quote}{quote} +xqinside [^']+ + +/* $foo$ style quotes ("dollar quoting") + * The quoted string starts with $foo$ where "foo" is an optional string + * in the form of an identifier, except that it may not contain "$", + * and extends to the first occurrence of an identical string. + * There is *no* processing of the quoted text. + * + * {dolqfailed} is an error rule to avoid scanner backup when {dolqdelim} + * fails to match its trailing "$". + */ +dolq_start [A-Za-z\200-\377_] +dolq_cont [A-Za-z\200-\377_0-9] +dolqdelim \$({dolq_start}{dolq_cont}*)?\$ +dolqfailed \${dolq_start}{dolq_cont}* +dolqinside [^$]+ + +/* Double quote + * Allows embedded spaces and other special characters into identifiers. + */ +dquote \" +xdstart {dquote} +xdstop {dquote} +xddouble {dquote}{dquote} +xdinside [^"]+ + +/* Unicode escapes */ +uescape [uU][eE][sS][cC][aA][pP][eE]{whitespace}*{quote}[^']{quote} +/* error rule to avoid backup */ +uescapefail [uU][eE][sS][cC][aA][pP][eE]{whitespace}*"-"|[uU][eE][sS][cC][aA][pP][eE]{whitespace}*{quote}[^']|[uU][eE][sS][cC][aA][pP][eE]{whitespace}*{quote}|[uU][eE][sS][cC][aA][pP][eE]{whitespace}*|[uU][eE][sS][cC][aA][pP]|[uU][eE][sS][cC][aA]|[uU][eE][sS][cC]|[uU][eE][sS]|[uU][eE]|[uU] + +/* Quoted identifier with Unicode escapes */ +xuistart [uU]&{dquote} + +/* Quoted string with Unicode escapes */ +xusstart [uU]&{quote} + +/* Optional UESCAPE after a quoted string or identifier with Unicode escapes. */ +xustop1 {uescapefail}? +xustop2 {uescape} + +/* error rule to avoid backup */ +xufailed [uU]& + + +/* C-style comments + * + * The "extended comment" syntax closely resembles allowable operator syntax. + * The tricky part here is to get lex to recognize a string starting with + * slash-star as a comment, when interpreting it as an operator would produce + * a longer match --- remember lex will prefer a longer match! Also, if we + * have something like plus-slash-star, lex will think this is a 3-character + * operator whereas we want to see it as a + operator and a comment start. + * The solution is two-fold: + * 1. append {op_chars}* to xcstart so that it matches as much text as + * {operator} would. Then the tie-breaker (first matching rule of same + * length) ensures xcstart wins. We put back the extra stuff with yyless() + * in case it contains a star-slash that should terminate the comment. + * 2. In the operator rule, check for slash-star within the operator, and + * if found throw it back with yyless(). This handles the plus-slash-star + * problem. + * Dash-dash comments have similar interactions with the operator rule. + */ +xcstart \/\*{op_chars}* +xcstop \*+\/ +xcinside [^*/]+ + +digit [0-9] +ident_start [A-Za-z\200-\377_] +ident_cont [A-Za-z\200-\377_0-9\$] + +identifier {ident_start}{ident_cont}* + +/* Assorted special-case operators and operator-like tokens */ +typecast "::" +dot_dot \.\. +colon_equals ":=" +equals_greater "=>" +less_equals "<=" +greater_equals ">=" +less_greater "<>" +not_equals "!=" + +/* + * "self" is the set of chars that should be returned as single-character + * tokens. "op_chars" is the set of chars that can make up "Op" tokens, + * which can be one or more characters long (but if a single-char token + * appears in the "self" set, it is not to be returned as an Op). Note + * that the sets overlap, but each has some chars that are not in the other. + * + * If you change either set, adjust the character lists appearing in the + * rule for "operator"! + */ +self [,()\[\].;\:\+\-\*\/\%\^\<\>\=] +op_chars [\~\!\@\#\^\&\|\`\?\+\-\*\/\%\<\>\=] +operator {op_chars}+ + +/* we no longer allow unary minus in numbers. + * instead we pass it separately to parser. there it gets + * coerced via doNegate() -- Leon aug 20 1999 + * + * {decimalfail} is used because we would like "1..10" to lex as 1, dot_dot, 10. + * + * {realfail1} and {realfail2} are added to prevent the need for scanner + * backup when the {real} rule fails to match completely. + */ + +integer {digit}+ +decimal (({digit}*\.{digit}+)|({digit}+\.{digit}*)) +decimalfail {digit}+\.\. +real ({integer}|{decimal})[Ee][-+]?{digit}+ +realfail1 ({integer}|{decimal})[Ee] +realfail2 ({integer}|{decimal})[Ee][-+] + +param \${integer} + +/* psql-specific: characters allowed in variable names */ +variable_char [A-Za-z\200-\377_0-9] + +other . + +/* + * Dollar quoted strings are totally opaque, and no escaping is done on them. + * Other quoted strings must allow some special characters such as single-quote + * and newline. + * Embedded single-quotes are implemented both in the SQL standard + * style of two adjacent single quotes "''" and in the Postgres/Java style + * of escaped-quote "\'". + * Other embedded escaped characters are matched explicitly and the leading + * backslash is dropped from the string. + * Note that xcstart must appear before operator, as explained above! + * Also whitespace (comment) must appear before operator. + */ + +%% + +{whitespace} { + /* + * Note that the whitespace rule includes both true + * whitespace and single-line ("--" style) comments. + * We suppress whitespace at the start of the query + * buffer. We also suppress all single-line comments, + * which is pretty dubious but is the historical + * behavior. + */ + if (!(output_buf->len == 0 || yytext[0] == '-')) + ECHO; + } + +{xcstart} { + cur_state->xcdepth = 0; + BEGIN(xc); + /* Put back any characters past slash-star; see above */ + yyless(2); + ECHO; + } + +{xcstart} { + cur_state->xcdepth++; + /* Put back any characters past slash-star; see above */ + yyless(2); + ECHO; + } + +{xcstop} { + if (cur_state->xcdepth <= 0) + { + BEGIN(INITIAL); + } + else + cur_state->xcdepth--; + ECHO; + } + +{xcinside} { + ECHO; + } + +{op_chars} { + ECHO; + } + +\*+ { + ECHO; + } + +{xbstart} { + BEGIN(xb); + ECHO; + } +{quotestop} | +{quotefail} { + yyless(1); + BEGIN(INITIAL); + ECHO; + } +{xhinside} | +{xbinside} { + ECHO; + } +{quotecontinue} | +{quotecontinue} { + ECHO; + } + +{xhstart} { + /* Hexadecimal bit type. + * At some point we should simply pass the string + * forward to the parser and label it there. + * In the meantime, place a leading "x" on the string + * to mark it for the input routine as a hex string. + */ + BEGIN(xh); + ECHO; + } +{quotestop} | +{quotefail} { + yyless(1); + BEGIN(INITIAL); + ECHO; + } + +{xnstart} { + yyless(1); /* eat only 'n' this time */ + ECHO; + } + +{xqstart} { + if (standard_strings()) + BEGIN(xq); + else + BEGIN(xe); + ECHO; + } +{xestart} { + BEGIN(xe); + ECHO; + } +{xusstart} { + BEGIN(xus); + ECHO; + } +{quotestop} | +{quotefail} { + yyless(1); + BEGIN(INITIAL); + ECHO; + } +{quotestop} | +{quotefail} { + yyless(1); + BEGIN(xusend); + ECHO; + } +{whitespace} { + ECHO; + } +{other} | +{xustop1} { + yyless(0); + BEGIN(INITIAL); + ECHO; + } +{xustop2} { + BEGIN(INITIAL); + ECHO; + } +{xqdouble} { + ECHO; + } +{xqinside} { + ECHO; + } +{xeinside} { + ECHO; + } +{xeunicode} { + ECHO; + } +{xeunicodefail} { + ECHO; + } +{xeescape} { + ECHO; + } +{xeoctesc} { + ECHO; + } +{xehexesc} { + ECHO; + } +{quotecontinue} { + ECHO; + } +. { + /* This is only needed for \ just before EOF */ + ECHO; + } + +{dolqdelim} { + cur_state->dolqstart = pg_strdup(yytext); + BEGIN(xdolq); + ECHO; + } +{dolqfailed} { + /* throw back all but the initial "$" */ + yyless(1); + ECHO; + } +{dolqdelim} { + if (strcmp(yytext, cur_state->dolqstart) == 0) + { + free(cur_state->dolqstart); + cur_state->dolqstart = NULL; + BEGIN(INITIAL); + } + else + { + /* + * When we fail to match $...$ to dolqstart, transfer + * the $... part to the output, but put back the final + * $ for rescanning. Consider $delim$...$junk$delim$ + */ + yyless(yyleng-1); + } + ECHO; + } +{dolqinside} { + ECHO; + } +{dolqfailed} { + ECHO; + } +. { + /* This is only needed for $ inside the quoted text */ + ECHO; + } + +{xdstart} { + BEGIN(xd); + ECHO; + } +{xuistart} { + BEGIN(xui); + ECHO; + } +{xdstop} { + BEGIN(INITIAL); + ECHO; + } +{dquote} { + yyless(1); + BEGIN(xuiend); + ECHO; + } +{whitespace} { + ECHO; + } +{other} | +{xustop1} { + yyless(0); + BEGIN(INITIAL); + ECHO; + } +{xustop2} { + BEGIN(INITIAL); + ECHO; + } +{xddouble} { + ECHO; + } +{xdinside} { + ECHO; + } + +{xufailed} { + /* throw back all but the initial u/U */ + yyless(1); + ECHO; + } + +{typecast} { + ECHO; + } + +{dot_dot} { + ECHO; + } + +{colon_equals} { + ECHO; + } + +{equals_greater} { + ECHO; + } + +{less_equals} { + ECHO; + } + +{greater_equals} { + ECHO; + } + +{less_greater} { + ECHO; + } + +{not_equals} { + ECHO; + } + + /* + * These rules are specific to psql --- they implement parenthesis + * counting and detection of command-ending semicolon. These must + * appear before the {self} rule so that they take precedence over it. + */ + +"(" { + cur_state->paren_depth++; + ECHO; + } + +")" { + if (cur_state->paren_depth > 0) + cur_state->paren_depth--; + ECHO; + } + +";" { + ECHO; + if (cur_state->paren_depth == 0) + { + /* Terminate lexing temporarily */ + return LEXRES_SEMI; + } + } + + /* + * psql-specific rules to handle backslash commands and variable + * substitution. We want these before {self}, also. + */ + +"\\"[;:] { + /* Force a semicolon or colon into the query buffer */ + emit(yytext + 1, 1); + } + +"\\" { + /* Terminate lexing temporarily */ + return LEXRES_BACKSLASH; + } + +:{variable_char}+ { + /* Possible psql variable substitution */ + char *varname; + const char *value; + + varname = extract_substring(yytext + 1, yyleng - 1); + value = GetVariable(pset.vars, varname); + + if (value) + { + /* It is a variable, check for recursion */ + if (var_is_current_source(cur_state, varname)) + { + /* Recursive expansion --- don't go there */ + psql_error("skipping recursive expansion of variable \"%s\"\n", + varname); + /* Instead copy the string as is */ + ECHO; + } + else + { + /* OK, perform substitution */ + push_new_buffer(value, varname); + /* yy_scan_string already made buffer active */ + } + } + else + { + /* + * if the variable doesn't exist we'll copy the + * string as is + */ + ECHO; + } + + free(varname); + } + +:'{variable_char}+' { + escape_variable(false); + } + +:\"{variable_char}+\" { + escape_variable(true); + } + + /* + * These rules just avoid the need for scanner backup if one of the + * two rules above fails to match completely. + */ + +:'{variable_char}* { + /* Throw back everything but the colon */ + yyless(1); + ECHO; + } + +:\"{variable_char}* { + /* Throw back everything but the colon */ + yyless(1); + ECHO; + } + + /* + * Back to backend-compatible rules. + */ + +{self} { + ECHO; + } + +{operator} { + /* + * Check for embedded slash-star or dash-dash; those + * are comment starts, so operator must stop there. + * Note that slash-star or dash-dash at the first + * character will match a prior rule, not this one. + */ + int nchars = yyleng; + char *slashstar = strstr(yytext, "/*"); + char *dashdash = strstr(yytext, "--"); + + if (slashstar && dashdash) + { + /* if both appear, take the first one */ + if (slashstar > dashdash) + slashstar = dashdash; + } + else if (!slashstar) + slashstar = dashdash; + if (slashstar) + nchars = slashstar - yytext; + + /* + * For SQL compatibility, '+' and '-' cannot be the + * last char of a multi-char operator unless the operator + * contains chars that are not in SQL operators. + * The idea is to lex '=-' as two operators, but not + * to forbid operator names like '?-' that could not be + * sequences of SQL operators. + */ + while (nchars > 1 && + (yytext[nchars-1] == '+' || + yytext[nchars-1] == '-')) + { + int ic; + + for (ic = nchars-2; ic >= 0; ic--) + { + if (strchr("~!@#^&|`?%", yytext[ic])) + break; + } + if (ic >= 0) + break; /* found a char that makes it OK */ + nchars--; /* else remove the +/-, and check again */ + } + + if (nchars < yyleng) + { + /* Strip the unwanted chars from the token */ + yyless(nchars); + } + ECHO; + } + +{param} { + ECHO; + } + +{integer} { + ECHO; + } +{decimal} { + ECHO; + } +{decimalfail} { + /* throw back the .., and treat as integer */ + yyless(yyleng-2); + ECHO; + } +{real} { + ECHO; + } +{realfail1} { + /* + * throw back the [Ee], and treat as {decimal}. Note + * that it is possible the input is actually {integer}, + * but since this case will almost certainly lead to a + * syntax error anyway, we don't bother to distinguish. + */ + yyless(yyleng-1); + ECHO; + } +{realfail2} { + /* throw back the [Ee][+-], and proceed as above */ + yyless(yyleng-2); + ECHO; + } + + +{identifier} { + ECHO; + } + +{other} { + ECHO; + } + + + /* + * Everything from here down is psql-specific. + */ + +<> { + StackElem *stackelem = cur_state->buffer_stack; + + if (stackelem == NULL) + return LEXRES_EOL; /* end of input reached */ + + /* + * We were expanding a variable, so pop the inclusion + * stack and keep lexing + */ + pop_buffer_stack(cur_state); + + stackelem = cur_state->buffer_stack; + if (stackelem != NULL) + { + yy_switch_to_buffer(stackelem->buf); + cur_state->curline = stackelem->bufstring; + cur_state->refline = stackelem->origstring ? stackelem->origstring : stackelem->bufstring; + } + else + { + yy_switch_to_buffer(cur_state->scanbufhandle); + cur_state->curline = cur_state->scanbuf; + cur_state->refline = cur_state->scanline; + } + } + + /* + * Exclusive lexer states to handle backslash command lexing + */ + +{ + /* command name ends at whitespace or backslash; eat all else */ + +{space}|"\\" { + yyless(0); + return LEXRES_OK; + } + +{other} { ECHO; } + +} + +{ + /* + * Discard any whitespace before argument, then go to xslasharg state. + * An exception is that "|" is only special at start of argument, so we + * check for it here. + */ + +{space}+ { } + +"|" { + if (option_type == OT_FILEPIPE) + { + /* treat like whole-string case */ + ECHO; + BEGIN(xslashwholeline); + } + else + { + /* vertical bar is not special otherwise */ + yyless(0); + BEGIN(xslasharg); + } + } + +{other} { + yyless(0); + BEGIN(xslasharg); + } + +} + +{ + /* + * Default processing of text in a slash command's argument. + * + * Note: unquoted_option_chars counts the number of characters at the + * end of the argument that were not subject to any form of quoting. + * psql_scan_slash_option needs this to strip trailing semicolons safely. + */ + +{space}|"\\" { + /* + * Unquoted space is end of arg; do not eat. Likewise + * backslash is end of command or next command, do not eat + * + * XXX this means we can't conveniently accept options + * that include unquoted backslashes; therefore, option + * processing that encourages use of backslashes is rather + * broken. + */ + yyless(0); + return LEXRES_OK; + } + +{quote} { + *option_quote = '\''; + unquoted_option_chars = 0; + BEGIN(xslashquote); + } + +"`" { + backtick_start_offset = output_buf->len; + *option_quote = '`'; + unquoted_option_chars = 0; + BEGIN(xslashbackquote); + } + +{dquote} { + ECHO; + *option_quote = '"'; + unquoted_option_chars = 0; + BEGIN(xslashdquote); + } + +:{variable_char}+ { + /* Possible psql variable substitution */ + if (option_type == OT_NO_EVAL) + ECHO; + else + { + char *varname; + const char *value; + + varname = extract_substring(yytext + 1, yyleng - 1); + value = GetVariable(pset.vars, varname); + free(varname); + + /* + * The variable value is just emitted without any + * further examination. This is consistent with the + * pre-8.0 code behavior, if not with the way that + * variables are handled outside backslash commands. + * Note that we needn't guard against recursion here. + */ + if (value) + appendPQExpBufferStr(output_buf, value); + else + ECHO; + + *option_quote = ':'; + } + unquoted_option_chars = 0; + } + +:'{variable_char}+' { + if (option_type == OT_NO_EVAL) + ECHO; + else + { + escape_variable(false); + *option_quote = ':'; + } + unquoted_option_chars = 0; + } + + +:\"{variable_char}+\" { + if (option_type == OT_NO_EVAL) + ECHO; + else + { + escape_variable(true); + *option_quote = ':'; + } + unquoted_option_chars = 0; + } + +:'{variable_char}* { + /* Throw back everything but the colon */ + yyless(1); + unquoted_option_chars++; + ECHO; + } + +:\"{variable_char}* { + /* Throw back everything but the colon */ + yyless(1); + unquoted_option_chars++; + ECHO; + } + +{other} { + unquoted_option_chars++; + ECHO; + } + +} + +{ + /* + * single-quoted text: copy literally except for '' and backslash + * sequences + */ + +{quote} { BEGIN(xslasharg); } + +{xqdouble} { appendPQExpBufferChar(output_buf, '\''); } + +"\\n" { appendPQExpBufferChar(output_buf, '\n'); } +"\\t" { appendPQExpBufferChar(output_buf, '\t'); } +"\\b" { appendPQExpBufferChar(output_buf, '\b'); } +"\\r" { appendPQExpBufferChar(output_buf, '\r'); } +"\\f" { appendPQExpBufferChar(output_buf, '\f'); } + +{xeoctesc} { + /* octal case */ + appendPQExpBufferChar(output_buf, + (char) strtol(yytext + 1, NULL, 8)); + } + +{xehexesc} { + /* hex case */ + appendPQExpBufferChar(output_buf, + (char) strtol(yytext + 2, NULL, 16)); + } + +"\\". { emit(yytext + 1, 1); } + +{other}|\n { ECHO; } + +} + +{ + /* + * backticked text: copy everything until next backquote, then evaluate. + * + * XXX Possible future behavioral change: substitute for :VARIABLE? + */ + +"`" { + /* In NO_EVAL mode, don't evaluate the command */ + if (option_type != OT_NO_EVAL) + evaluate_backtick(); + BEGIN(xslasharg); + } + +{other}|\n { ECHO; } + +} + +{ + /* double-quoted text: copy verbatim, including the double quotes */ + +{dquote} { + ECHO; + BEGIN(xslasharg); + } + +{other}|\n { ECHO; } + +} + +{ + /* copy everything until end of input line */ + /* but suppress leading whitespace */ + +{space}+ { + if (output_buf->len > 0) + ECHO; + } + +{other} { ECHO; } + +} + +{ + /* at end of command, eat a double backslash, but not anything else */ + +"\\\\" { return LEXRES_OK; } + +{other}|\n { + yyless(0); + return LEXRES_OK; + } + +} + +%% + +/* + * Create a lexer working state struct. + */ +PsqlScanState +psql_scan_create(void) +{ + PsqlScanState state; + + state = (PsqlScanStateData *) pg_malloc0(sizeof(PsqlScanStateData)); + + psql_scan_reset(state); + + return state; +} + +/* + * Destroy a lexer working state struct, releasing all resources. + */ +void +psql_scan_destroy(PsqlScanState state) +{ + psql_scan_finish(state); + + psql_scan_reset(state); + + free(state); +} + +/* + * Set up to perform lexing of the given input line. + * + * The text at *line, extending for line_len bytes, will be scanned by + * subsequent calls to the psql_scan routines. psql_scan_finish should + * be called when scanning is complete. Note that the lexer retains + * a pointer to the storage at *line --- this string must not be altered + * or freed until after psql_scan_finish is called. + */ +void +psql_scan_setup(PsqlScanState state, + const char *line, int line_len) +{ + /* Mustn't be scanning already */ + Assert(state->scanbufhandle == NULL); + Assert(state->buffer_stack == NULL); + + /* Do we need to hack the character set encoding? */ + state->encoding = pset.encoding; + state->safe_encoding = pg_valid_server_encoding_id(state->encoding); + + /* needed for prepare_buffer */ + cur_state = state; + + /* Set up flex input buffer with appropriate translation and padding */ + state->scanbufhandle = prepare_buffer(line, line_len, + &state->scanbuf); + state->scanline = line; + + /* Set lookaside data in case we have to map unsafe encoding */ + state->curline = state->scanbuf; + state->refline = state->scanline; +} + +/* + * Do lexical analysis of SQL command text. + * + * The text previously passed to psql_scan_setup is scanned, and appended + * (possibly with transformation) to query_buf. + * + * The return value indicates the condition that stopped scanning: + * + * PSCAN_SEMICOLON: found a command-ending semicolon. (The semicolon is + * transferred to query_buf.) The command accumulated in query_buf should + * be executed, then clear query_buf and call again to scan the remainder + * of the line. + * + * PSCAN_BACKSLASH: found a backslash that starts a psql special command. + * Any previous data on the line has been transferred to query_buf. + * The caller will typically next call psql_scan_slash_command(), + * perhaps psql_scan_slash_option(), and psql_scan_slash_command_end(). + * + * PSCAN_INCOMPLETE: the end of the line was reached, but we have an + * incomplete SQL command. *prompt is set to the appropriate prompt type. + * + * PSCAN_EOL: the end of the line was reached, and there is no lexical + * reason to consider the command incomplete. The caller may or may not + * choose to send it. *prompt is set to the appropriate prompt type if + * the caller chooses to collect more input. + * + * In the PSCAN_INCOMPLETE and PSCAN_EOL cases, psql_scan_finish() should + * be called next, then the cycle may be repeated with a fresh input line. + * + * In all cases, *prompt is set to an appropriate prompt type code for the + * next line-input operation. + */ +PsqlScanResult +psql_scan(PsqlScanState state, + PQExpBuffer query_buf, + promptStatus_t *prompt) +{ + PsqlScanResult result; + int lexresult; + + /* Must be scanning already */ + Assert(state->scanbufhandle != NULL); + + /* Set up static variables that will be used by yylex */ + cur_state = state; + output_buf = query_buf; + + if (state->buffer_stack != NULL) + yy_switch_to_buffer(state->buffer_stack->buf); + else + yy_switch_to_buffer(state->scanbufhandle); + + BEGIN(state->start_state); + + /* And lex. */ + lexresult = yylex(); + + /* Update static vars back to the state struct */ + state->start_state = YY_START; + + /* + * Check termination state and return appropriate result info. + */ + switch (lexresult) + { + case LEXRES_EOL: /* end of input */ + switch (state->start_state) + { + /* This switch must cover all non-slash-command states. */ + case INITIAL: + case xuiend: /* we treat these like INITIAL */ + case xusend: + if (state->paren_depth > 0) + { + result = PSCAN_INCOMPLETE; + *prompt = PROMPT_PAREN; + } + else if (query_buf->len > 0) + { + result = PSCAN_EOL; + *prompt = PROMPT_CONTINUE; + } + else + { + /* never bother to send an empty buffer */ + result = PSCAN_INCOMPLETE; + *prompt = PROMPT_READY; + } + break; + case xb: + result = PSCAN_INCOMPLETE; + *prompt = PROMPT_SINGLEQUOTE; + break; + case xc: + result = PSCAN_INCOMPLETE; + *prompt = PROMPT_COMMENT; + break; + case xd: + result = PSCAN_INCOMPLETE; + *prompt = PROMPT_DOUBLEQUOTE; + break; + case xh: + result = PSCAN_INCOMPLETE; + *prompt = PROMPT_SINGLEQUOTE; + break; + case xe: + result = PSCAN_INCOMPLETE; + *prompt = PROMPT_SINGLEQUOTE; + break; + case xq: + result = PSCAN_INCOMPLETE; + *prompt = PROMPT_SINGLEQUOTE; + break; + case xdolq: + result = PSCAN_INCOMPLETE; + *prompt = PROMPT_DOLLARQUOTE; + break; + case xui: + result = PSCAN_INCOMPLETE; + *prompt = PROMPT_DOUBLEQUOTE; + break; + case xus: + result = PSCAN_INCOMPLETE; + *prompt = PROMPT_SINGLEQUOTE; + break; + default: + /* can't get here */ + fprintf(stderr, "invalid YY_START\n"); + exit(1); + } + break; + case LEXRES_SEMI: /* semicolon */ + result = PSCAN_SEMICOLON; + *prompt = PROMPT_READY; + break; + case LEXRES_BACKSLASH: /* backslash */ + result = PSCAN_BACKSLASH; + *prompt = PROMPT_READY; + break; + default: + /* can't get here */ + fprintf(stderr, "invalid yylex result\n"); + exit(1); + } + + return result; +} + +/* + * Clean up after scanning a string. This flushes any unread input and + * releases resources (but not the PsqlScanState itself). Note however + * that this does not reset the lexer scan state; that can be done by + * psql_scan_reset(), which is an orthogonal operation. + * + * It is legal to call this when not scanning anything (makes it easier + * to deal with error recovery). + */ +void +psql_scan_finish(PsqlScanState state) +{ + /* Drop any incomplete variable expansions. */ + while (state->buffer_stack != NULL) + pop_buffer_stack(state); + + /* Done with the outer scan buffer, too */ + if (state->scanbufhandle) + yy_delete_buffer(state->scanbufhandle); + state->scanbufhandle = NULL; + if (state->scanbuf) + free(state->scanbuf); + state->scanbuf = NULL; +} + +/* + * Reset lexer scanning state to start conditions. This is appropriate + * for executing \r psql commands (or any other time that we discard the + * prior contents of query_buf). It is not, however, necessary to do this + * when we execute and clear the buffer after getting a PSCAN_SEMICOLON or + * PSCAN_EOL scan result, because the scan state must be INITIAL when those + * conditions are returned. + * + * Note that this is unrelated to flushing unread input; that task is + * done by psql_scan_finish(). + */ +void +psql_scan_reset(PsqlScanState state) +{ + state->start_state = INITIAL; + state->paren_depth = 0; + state->xcdepth = 0; /* not really necessary */ + if (state->dolqstart) + free(state->dolqstart); + state->dolqstart = NULL; +} + +/* + * Return true if lexer is currently in an "inside quotes" state. + * + * This is pretty grotty but is needed to preserve the old behavior + * that mainloop.c drops blank lines not inside quotes without even + * echoing them. + */ +bool +psql_scan_in_quote(PsqlScanState state) +{ + return state->start_state != INITIAL; +} + +/* + * Scan the command name of a psql backslash command. This should be called + * after psql_scan() returns PSCAN_BACKSLASH. It is assumed that the input + * has been consumed through the leading backslash. + * + * The return value is a malloc'd copy of the command name, as parsed off + * from the input. + */ +char * +psql_scan_slash_command(PsqlScanState state) +{ + PQExpBufferData mybuf; + + /* Must be scanning already */ + Assert(state->scanbufhandle != NULL); + + /* Build a local buffer that we'll return the data of */ + initPQExpBuffer(&mybuf); + + /* Set up static variables that will be used by yylex */ + cur_state = state; + output_buf = &mybuf; + + if (state->buffer_stack != NULL) + yy_switch_to_buffer(state->buffer_stack->buf); + else + yy_switch_to_buffer(state->scanbufhandle); + + BEGIN(xslashcmd); + + /* And lex. */ + yylex(); + + /* There are no possible errors in this lex state... */ + + return mybuf.data; +} + +/* + * Parse off the next argument for a backslash command, and return it as a + * malloc'd string. If there are no more arguments, returns NULL. + * + * type tells what processing, if any, to perform on the option string; + * for example, if it's a SQL identifier, we want to downcase any unquoted + * letters. + * + * if quote is not NULL, *quote is set to 0 if no quoting was found, else + * the last quote symbol used in the argument. + * + * if semicolon is true, unquoted trailing semicolon(s) that would otherwise + * be taken as part of the option string will be stripped. + * + * NOTE: the only possible syntax errors for backslash options are unmatched + * quotes, which are detected when we run out of input. Therefore, on a + * syntax error we just throw away the string and return NULL; there is no + * need to worry about flushing remaining input. + */ +char * +psql_scan_slash_option(PsqlScanState state, + enum slash_option_type type, + char *quote, + bool semicolon) +{ + PQExpBufferData mybuf; + int lexresult PG_USED_FOR_ASSERTS_ONLY; + char local_quote; + + /* Must be scanning already */ + Assert(state->scanbufhandle != NULL); + + if (quote == NULL) + quote = &local_quote; + *quote = 0; + + /* Build a local buffer that we'll return the data of */ + initPQExpBuffer(&mybuf); + + /* Set up static variables that will be used by yylex */ + cur_state = state; + output_buf = &mybuf; + option_type = type; + option_quote = quote; + unquoted_option_chars = 0; + + if (state->buffer_stack != NULL) + yy_switch_to_buffer(state->buffer_stack->buf); + else + yy_switch_to_buffer(state->scanbufhandle); + + if (type == OT_WHOLE_LINE) + BEGIN(xslashwholeline); + else + BEGIN(xslashargstart); + + /* And lex. */ + lexresult = yylex(); + + /* + * Check the lex result: we should have gotten back either LEXRES_OK + * or LEXRES_EOL (the latter indicating end of string). If we were inside + * a quoted string, as indicated by YY_START, EOL is an error. + */ + Assert(lexresult == LEXRES_EOL || lexresult == LEXRES_OK); + + switch (YY_START) + { + case xslashargstart: + /* empty arg */ + break; + case xslasharg: + /* Strip any unquoted trailing semi-colons if requested */ + if (semicolon) + { + while (unquoted_option_chars-- > 0 && + mybuf.len > 0 && + mybuf.data[mybuf.len - 1] == ';') + { + mybuf.data[--mybuf.len] = '\0'; + } + } + + /* + * If SQL identifier processing was requested, then we strip out + * excess double quotes and downcase unquoted letters. + * Doubled double-quotes become output double-quotes, per spec. + * + * Note that a string like FOO"BAR"BAZ will be converted to + * fooBARbaz; this is somewhat inconsistent with the SQL spec, + * which would have us parse it as several identifiers. But + * for psql's purposes, we want a string like "foo"."bar" to + * be treated as one option, so there's little choice. + */ + if (type == OT_SQLID || type == OT_SQLIDHACK) + { + bool inquotes = false; + char *cp = mybuf.data; + + while (*cp) + { + if (*cp == '"') + { + if (inquotes && cp[1] == '"') + { + /* Keep the first quote, remove the second */ + cp++; + } + inquotes = !inquotes; + /* Collapse out quote at *cp */ + memmove(cp, cp + 1, strlen(cp)); + mybuf.len--; + /* do not advance cp */ + } + else + { + if (!inquotes && type == OT_SQLID) + *cp = pg_tolower((unsigned char) *cp); + cp += PQmblen(cp, pset.encoding); + } + } + } + break; + case xslashquote: + case xslashbackquote: + case xslashdquote: + /* must have hit EOL inside quotes */ + psql_error("unterminated quoted string\n"); + termPQExpBuffer(&mybuf); + return NULL; + case xslashwholeline: + /* always okay */ + break; + default: + /* can't get here */ + fprintf(stderr, "invalid YY_START\n"); + exit(1); + } + + /* + * An unquoted empty argument isn't possible unless we are at end of + * command. Return NULL instead. + */ + if (mybuf.len == 0 && *quote == 0) + { + termPQExpBuffer(&mybuf); + return NULL; + } + + /* Else return the completed string. */ + return mybuf.data; +} + +/* + * Eat up any unused \\ to complete a backslash command. + */ +void +psql_scan_slash_command_end(PsqlScanState state) +{ + /* Must be scanning already */ + Assert(state->scanbufhandle != NULL); + + /* Set up static variables that will be used by yylex */ + cur_state = state; + output_buf = NULL; + + if (state->buffer_stack != NULL) + yy_switch_to_buffer(state->buffer_stack->buf); + else + yy_switch_to_buffer(state->scanbufhandle); + + BEGIN(xslashend); + + /* And lex. */ + yylex(); + + /* There are no possible errors in this lex state... */ +} + +/* + * Evaluate a backticked substring of a slash command's argument. + * + * The portion of output_buf starting at backtick_start_offset is evaluated + * as a shell command and then replaced by the command's output. + */ +static void +evaluate_backtick(void) +{ + char *cmd = output_buf->data + backtick_start_offset; + PQExpBufferData cmd_output; + FILE *fd; + bool error = false; + char buf[512]; + size_t result; + + initPQExpBuffer(&cmd_output); + + fd = popen(cmd, PG_BINARY_R); + if (!fd) + { + psql_error("%s: %s\n", cmd, strerror(errno)); + error = true; + } + + if (!error) + { + do + { + result = fread(buf, 1, sizeof(buf), fd); + if (ferror(fd)) + { + psql_error("%s: %s\n", cmd, strerror(errno)); + error = true; + break; + } + appendBinaryPQExpBuffer(&cmd_output, buf, result); + } while (!feof(fd)); + } + + if (fd && pclose(fd) == -1) + { + psql_error("%s: %s\n", cmd, strerror(errno)); + error = true; + } + + if (PQExpBufferDataBroken(cmd_output)) + { + psql_error("%s: out of memory\n", cmd); + error = true; + } + + /* Now done with cmd, delete it from output_buf */ + output_buf->len = backtick_start_offset; + output_buf->data[output_buf->len] = '\0'; + + /* If no error, transfer result to output_buf */ + if (!error) + { + /* strip any trailing newline */ + if (cmd_output.len > 0 && + cmd_output.data[cmd_output.len - 1] == '\n') + cmd_output.len--; + appendBinaryPQExpBuffer(output_buf, cmd_output.data, cmd_output.len); + } + + termPQExpBuffer(&cmd_output); +} + +/* + * Push the given string onto the stack of stuff to scan. + * + * cur_state must point to the active PsqlScanState. + * + * NOTE SIDE EFFECT: the new buffer is made the active flex input buffer. + */ +static void +push_new_buffer(const char *newstr, const char *varname) +{ + StackElem *stackelem; + + stackelem = (StackElem *) pg_malloc(sizeof(StackElem)); + + /* + * In current usage, the passed varname points at the current flex + * input buffer; we must copy it before calling prepare_buffer() + * because that will change the buffer state. + */ + stackelem->varname = varname ? pg_strdup(varname) : NULL; + + stackelem->buf = prepare_buffer(newstr, strlen(newstr), + &stackelem->bufstring); + cur_state->curline = stackelem->bufstring; + if (cur_state->safe_encoding) + { + stackelem->origstring = NULL; + cur_state->refline = stackelem->bufstring; + } + else + { + stackelem->origstring = pg_strdup(newstr); + cur_state->refline = stackelem->origstring; + } + stackelem->next = cur_state->buffer_stack; + cur_state->buffer_stack = stackelem; +} + +/* + * Pop the topmost buffer stack item (there must be one!) + * + * NB: after this, the flex input state is unspecified; caller must + * switch to an appropriate buffer to continue lexing. + */ +static void +pop_buffer_stack(PsqlScanState state) +{ + StackElem *stackelem = state->buffer_stack; + + state->buffer_stack = stackelem->next; + yy_delete_buffer(stackelem->buf); + free(stackelem->bufstring); + if (stackelem->origstring) + free(stackelem->origstring); + if (stackelem->varname) + free(stackelem->varname); + free(stackelem); +} + +/* + * Check if specified variable name is the source for any string + * currently being scanned + */ +static bool +var_is_current_source(PsqlScanState state, const char *varname) +{ + StackElem *stackelem; + + for (stackelem = state->buffer_stack; + stackelem != NULL; + stackelem = stackelem->next) + { + if (stackelem->varname && strcmp(stackelem->varname, varname) == 0) + return true; + } + return false; +} + +/* + * Set up a flex input buffer to scan the given data. We always make a + * copy of the data. If working in an unsafe encoding, the copy has + * multibyte sequences replaced by FFs to avoid fooling the lexer rules. + * + * cur_state must point to the active PsqlScanState. + * + * NOTE SIDE EFFECT: the new buffer is made the active flex input buffer. + */ +static YY_BUFFER_STATE +prepare_buffer(const char *txt, int len, char **txtcopy) +{ + char *newtxt; + + /* Flex wants two \0 characters after the actual data */ + newtxt = pg_malloc(len + 2); + *txtcopy = newtxt; + newtxt[len] = newtxt[len + 1] = YY_END_OF_BUFFER_CHAR; + + if (cur_state->safe_encoding) + memcpy(newtxt, txt, len); + else + { + /* Gotta do it the hard way */ + int i = 0; + + while (i < len) + { + int thislen = PQmblen(txt + i, cur_state->encoding); + + /* first byte should always be okay... */ + newtxt[i] = txt[i]; + i++; + while (--thislen > 0 && i < len) + newtxt[i++] = (char) 0xFF; + } + } + + return yy_scan_buffer(newtxt, len + 2); +} + +/* + * emit() --- body for ECHO macro + * + * NB: this must be used for ALL and ONLY the text copied from the flex + * input data. If you pass it something that is not part of the yytext + * string, you are making a mistake. Internally generated text can be + * appended directly to output_buf. + */ +static void +emit(const char *txt, int len) +{ + if (cur_state->safe_encoding) + appendBinaryPQExpBuffer(output_buf, txt, len); + else + { + /* Gotta do it the hard way */ + const char *reference = cur_state->refline; + int i; + + reference += (txt - cur_state->curline); + + for (i = 0; i < len; i++) + { + char ch = txt[i]; + + if (ch == (char) 0xFF) + ch = reference[i]; + appendPQExpBufferChar(output_buf, ch); + } + } +} + +/* + * extract_substring --- fetch the true value of (part of) the current token + * + * This is like emit(), except that the data is returned as a malloc'd string + * rather than being pushed directly to output_buf. + */ +static char * +extract_substring(const char *txt, int len) +{ + char *result = (char *) pg_malloc(len + 1); + + if (cur_state->safe_encoding) + memcpy(result, txt, len); + else + { + /* Gotta do it the hard way */ + const char *reference = cur_state->refline; + int i; + + reference += (txt - cur_state->curline); + + for (i = 0; i < len; i++) + { + char ch = txt[i]; + + if (ch == (char) 0xFF) + ch = reference[i]; + result[i] = ch; + } + } + result[len] = '\0'; + return result; +} + +/* + * escape_variable --- process :'VARIABLE' or :"VARIABLE" + * + * If the variable name is found, escape its value using the appropriate + * quoting method and emit the value to output_buf. (Since the result is + * surely quoted, there is never any reason to rescan it.) If we don't + * find the variable or the escaping function fails, emit the token as-is. + */ +static void +escape_variable(bool as_ident) +{ + char *varname; + const char *value; + + /* Variable lookup. */ + varname = extract_substring(yytext + 2, yyleng - 3); + value = GetVariable(pset.vars, varname); + free(varname); + + /* Escaping. */ + if (value) + { + if (!pset.db) + psql_error("can't escape without active connection\n"); + else + { + char *escaped_value; + + if (as_ident) + escaped_value = + PQescapeIdentifier(pset.db, value, strlen(value)); + else + escaped_value = + PQescapeLiteral(pset.db, value, strlen(value)); + + if (escaped_value == NULL) + { + const char *error = PQerrorMessage(pset.db); + + psql_error("%s", error); + } + else + { + appendPQExpBufferStr(output_buf, escaped_value); + PQfreemem(escaped_value); + return; + } + } + } + + /* + * If we reach this point, some kind of error has occurred. Emit the + * original text into the output buffer. + */ + emit(yytext, yyleng); +} diff --git a/src/bin/csql/settings.h b/src/bin/csql/settings.h new file mode 100644 index 000000000..d34dc2806 --- /dev/null +++ b/src/bin/csql/settings.h @@ -0,0 +1,149 @@ +/* + * psql - the PostgreSQL interactive terminal + * + * Copyright (c) 2000-2015, PostgreSQL Global Development Group + * + * src/bin/psql/settings.h + */ +#ifndef SETTINGS_H +#define SETTINGS_H + + +#include "variables.h" +#include "print.h" + +#define DEFAULT_FIELD_SEP "|" +#define DEFAULT_RECORD_SEP "\n" + +#if defined(WIN32) || defined(__CYGWIN__) +#define DEFAULT_EDITOR "notepad.exe" +/* no DEFAULT_EDITOR_LINENUMBER_ARG for Notepad */ +#else +#define DEFAULT_EDITOR "vi" +#define DEFAULT_EDITOR_LINENUMBER_ARG "+" +#endif + +#define DEFAULT_PROMPT1 "%/%R%# " +#define DEFAULT_PROMPT2 "%/%R%# " +#define DEFAULT_PROMPT3 ">> " + +/* + * Note: these enums should generally be chosen so that zero corresponds + * to the default behavior. + */ + +typedef enum +{ + PSQL_ECHO_NONE, + PSQL_ECHO_QUERIES, + PSQL_ECHO_ERRORS, + PSQL_ECHO_ALL +} PSQL_ECHO; + +typedef enum +{ + PSQL_ECHO_HIDDEN_OFF, + PSQL_ECHO_HIDDEN_ON, + PSQL_ECHO_HIDDEN_NOEXEC +} PSQL_ECHO_HIDDEN; + +typedef enum +{ + PSQL_ERROR_ROLLBACK_OFF, + PSQL_ERROR_ROLLBACK_INTERACTIVE, + PSQL_ERROR_ROLLBACK_ON +} PSQL_ERROR_ROLLBACK; + +typedef enum +{ + PSQL_COMP_CASE_PRESERVE_UPPER, + PSQL_COMP_CASE_PRESERVE_LOWER, + PSQL_COMP_CASE_UPPER, + PSQL_COMP_CASE_LOWER +} PSQL_COMP_CASE; + +typedef enum +{ + hctl_none = 0, + hctl_ignorespace = 1, + hctl_ignoredups = 2, + hctl_ignoreboth = hctl_ignorespace | hctl_ignoredups +} HistControl; + +enum trivalue +{ + TRI_DEFAULT, + TRI_NO, + TRI_YES +}; + +typedef struct _psqlSettings +{ + PGconn *db; /* connection to backend */ + int encoding; /* client_encoding */ + FILE *queryFout; /* where to send the query results */ + bool queryFoutPipe; /* queryFout is from a popen() */ + + FILE *copyStream; /* Stream to read/write for \copy command */ + + printQueryOpt popt; + + char *gfname; /* one-shot file output argument for \g */ + char *gset_prefix; /* one-shot prefix argument for \gset */ + + bool notty; /* stdin or stdout is not a tty (as determined + * on startup) */ + enum trivalue getPassword; /* prompt the user for a username and password */ + FILE *cur_cmd_source; /* describe the status of the current main + * loop */ + bool cur_cmd_interactive; + int sversion; /* backend server version */ + const char *progname; /* in case you renamed psql */ + char *inputfile; /* file being currently processed, if any */ + uint64 lineno; /* also for error reporting */ + uint64 stmt_lineno; /* line number inside the current statement */ + + bool timing; /* enable timing of all queries */ + + FILE *logfile; /* session log file handle */ + + VariableSpace vars; /* "shell variable" repository */ + + /* + * The remaining fields are set by assign hooks associated with entries in + * "vars". They should not be set directly except by those hook + * functions. + */ + bool autocommit; + bool on_error_stop; + bool quiet; + bool singleline; + bool singlestep; + int fetch_count; + PSQL_ECHO echo; + PSQL_ECHO_HIDDEN echo_hidden; + PSQL_ERROR_ROLLBACK on_error_rollback; + PSQL_COMP_CASE comp_case; + HistControl histcontrol; + const char *prompt1; + const char *prompt2; + const char *prompt3; + PGVerbosity verbosity; /* current error verbosity level */ +} PsqlSettings; + +extern PsqlSettings pset; + + +#ifndef EXIT_SUCCESS +#define EXIT_SUCCESS 0 +#endif + +#ifndef EXIT_FAILURE +#define EXIT_FAILURE 1 +#endif + +#define EXIT_BADCONN 2 + +#define EXIT_USER 3 + +#endif diff --git a/src/bin/csql/sql_help.c b/src/bin/csql/sql_help.c new file mode 100644 index 000000000..02b05e676 --- /dev/null +++ b/src/bin/csql/sql_help.c @@ -0,0 +1,4052 @@ +/* + * *** Do not change this file by hand. It is automatically + * *** generated from the DocBook documentation. + * + * generated by + * /usr/bin/perl create_help.pl ../../../doc/src/sgml/ref sql_help + * + */ + +#include "sql_help.h" + +void +sql_help_ABORT(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "ABORT [ WORK | TRANSACTION ]"); +} + +void +sql_help_ALTER_AGGREGATE(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "ALTER AGGREGATE %s ( %s ) RENAME TO %s\n" + "ALTER AGGREGATE %s ( %s )\n" + " OWNER TO { %s | CURRENT_USER | SESSION_USER }\n" + "ALTER AGGREGATE %s ( %s ) SET SCHEMA %s\n" + "\n" + "%s\n" + "\n" + "* |\n" + "[ %s ] [ %s ] %s [ , ... ] |\n" + "[ [ %s ] [ %s ] %s [ , ... ] ] ORDER BY [ %s ] [ %s ] %s [ , ... ]", + _("name"), + _("aggregate_signature"), + _("new_name"), + _("name"), + _("aggregate_signature"), + _("new_owner"), + _("name"), + _("aggregate_signature"), + _("new_schema"), + _("where aggregate_signature is:"), + _("argmode"), + _("argname"), + _("argtype"), + _("argmode"), + _("argname"), + _("argtype"), + _("argmode"), + _("argname"), + _("argtype")); +} + +void +sql_help_ALTER_COLLATION(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "ALTER COLLATION %s RENAME TO %s\n" + "ALTER COLLATION %s OWNER TO { %s | CURRENT_USER | SESSION_USER }\n" + "ALTER COLLATION %s SET SCHEMA %s", + _("name"), + _("new_name"), + _("name"), + _("new_owner"), + _("name"), + _("new_schema")); +} + +void +sql_help_ALTER_CONVERSION(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "ALTER CONVERSION %s RENAME TO %s\n" + "ALTER CONVERSION %s OWNER TO { %s | CURRENT_USER | SESSION_USER }\n" + "ALTER CONVERSION %s SET SCHEMA %s", + _("name"), + _("new_name"), + _("name"), + _("new_owner"), + _("name"), + _("new_schema")); +} + +void +sql_help_ALTER_DATABASE(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "ALTER DATABASE %s [ [ WITH ] %s [ ... ] ]\n" + "\n" + "%s\n" + "\n" + " ALLOW_CONNECTIONS %s\n" + " CONNECTION LIMIT %s\n" + " IS_TEMPLATE %s\n" + "\n" + "ALTER DATABASE %s RENAME TO %s\n" + "\n" + "ALTER DATABASE %s OWNER TO { %s | CURRENT_USER | SESSION_USER }\n" + "\n" + "ALTER DATABASE %s SET TABLESPACE %s\n" + "\n" + "ALTER DATABASE %s SET %s { TO | = } { %s | DEFAULT }\n" + "ALTER DATABASE %s SET %s FROM CURRENT\n" + "ALTER DATABASE %s RESET %s\n" + "ALTER DATABASE %s RESET ALL", + _("name"), + _("option"), + _("where option can be:"), + _("allowconn"), + _("connlimit"), + _("istemplate"), + _("name"), + _("new_name"), + _("name"), + _("new_owner"), + _("name"), + _("new_tablespace"), + _("name"), + _("configuration_parameter"), + _("value"), + _("name"), + _("configuration_parameter"), + _("name"), + _("configuration_parameter"), + _("name")); +} + +void +sql_help_ALTER_DEFAULT_PRIVILEGES(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "ALTER DEFAULT PRIVILEGES\n" + " [ FOR { ROLE | USER } %s [, ...] ]\n" + " [ IN SCHEMA %s [, ...] ]\n" + " %s\n" + "\n" + "%s\n" + "\n" + "GRANT { { SELECT | INSERT | UPDATE | DELETE | TRUNCATE | REFERENCES | TRIGGER }\n" + " [, ...] | ALL [ PRIVILEGES ] }\n" + " ON TABLES\n" + " TO { [ GROUP ] %s | PUBLIC } [, ...] [ WITH GRANT OPTION ]\n" + "\n" + "GRANT { { USAGE | SELECT | UPDATE }\n" + " [, ...] | ALL [ PRIVILEGES ] }\n" + " ON SEQUENCES\n" + " TO { [ GROUP ] %s | PUBLIC } [, ...] [ WITH GRANT OPTION ]\n" + "\n" + "GRANT { EXECUTE | ALL [ PRIVILEGES ] }\n" + " ON FUNCTIONS\n" + " TO { [ GROUP ] %s | PUBLIC } [, ...] [ WITH GRANT OPTION ]\n" + "\n" + "GRANT { USAGE | ALL [ PRIVILEGES ] }\n" + " ON TYPES\n" + " TO { [ GROUP ] %s | PUBLIC } [, ...] [ WITH GRANT OPTION ]\n" + "\n" + "REVOKE [ GRANT OPTION FOR ]\n" + " { { SELECT | INSERT | UPDATE | DELETE | TRUNCATE | REFERENCES | TRIGGER }\n" + " [, ...] | ALL [ PRIVILEGES ] }\n" + " ON TABLES\n" + " FROM { [ GROUP ] %s | PUBLIC } [, ...]\n" + " [ CASCADE | RESTRICT ]\n" + "\n" + "REVOKE [ GRANT OPTION FOR ]\n" + " { { USAGE | SELECT | UPDATE }\n" + " [, ...] | ALL [ PRIVILEGES ] }\n" + " ON SEQUENCES\n" + " FROM { [ GROUP ] %s | PUBLIC } [, ...]\n" + " [ CASCADE | RESTRICT ]\n" + "\n" + "REVOKE [ GRANT OPTION FOR ]\n" + " { EXECUTE | ALL [ PRIVILEGES ] }\n" + " ON FUNCTIONS\n" + " FROM { [ GROUP ] %s | PUBLIC } [, ...]\n" + " [ CASCADE | RESTRICT ]\n" + "\n" + "REVOKE [ GRANT OPTION FOR ]\n" + " { USAGE | ALL [ PRIVILEGES ] }\n" + " ON TYPES\n" + " FROM { [ GROUP ] %s | PUBLIC } [, ...]\n" + " [ CASCADE | RESTRICT ]", + _("target_role"), + _("schema_name"), + _("abbreviated_grant_or_revoke"), + _("where abbreviated_grant_or_revoke is one of:"), + _("role_name"), + _("role_name"), + _("role_name"), + _("role_name"), + _("role_name"), + _("role_name"), + _("role_name"), + _("role_name")); +} + +void +sql_help_ALTER_DOMAIN(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "ALTER DOMAIN %s\n" + " { SET DEFAULT %s | DROP DEFAULT }\n" + "ALTER DOMAIN %s\n" + " { SET | DROP } NOT NULL\n" + "ALTER DOMAIN %s\n" + " ADD %s [ NOT VALID ]\n" + "ALTER DOMAIN %s\n" + " DROP CONSTRAINT [ IF EXISTS ] %s [ RESTRICT | CASCADE ]\n" + "ALTER DOMAIN %s\n" + " RENAME CONSTRAINT %s TO %s\n" + "ALTER DOMAIN %s\n" + " VALIDATE CONSTRAINT %s\n" + "ALTER DOMAIN %s\n" + " OWNER TO { %s | CURRENT_USER | SESSION_USER }\n" + "ALTER DOMAIN %s\n" + " RENAME TO %s\n" + "ALTER DOMAIN %s\n" + " SET SCHEMA %s", + _("name"), + _("expression"), + _("name"), + _("name"), + _("domain_constraint"), + _("name"), + _("constraint_name"), + _("name"), + _("constraint_name"), + _("new_constraint_name"), + _("name"), + _("constraint_name"), + _("name"), + _("new_owner"), + _("name"), + _("new_name"), + _("name"), + _("new_schema")); +} + +void +sql_help_ALTER_EVENT_TRIGGER(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "ALTER EVENT TRIGGER %s DISABLE\n" + "ALTER EVENT TRIGGER %s ENABLE [ REPLICA | ALWAYS ]\n" + "ALTER EVENT TRIGGER %s OWNER TO { %s | CURRENT_USER | SESSION_USER }\n" + "ALTER EVENT TRIGGER %s RENAME TO %s", + _("name"), + _("name"), + _("name"), + _("new_owner"), + _("name"), + _("new_name")); +} + +void +sql_help_ALTER_EXTENSION(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "ALTER EXTENSION %s UPDATE [ TO %s ]\n" + "ALTER EXTENSION %s SET SCHEMA %s\n" + "ALTER EXTENSION %s ADD %s\n" + "ALTER EXTENSION %s DROP %s\n" + "\n" + "%s\n" + "\n" + " AGGREGATE %s ( %s ) |\n" + " CAST (%s AS %s) |\n" + " COLLATION %s |\n" + " CONVERSION %s |\n" + " DOMAIN %s |\n" + " EVENT TRIGGER %s |\n" + " FOREIGN DATA WRAPPER %s |\n" + " FOREIGN TABLE %s |\n" + " FUNCTION %s ( [ [ %s ] [ %s ] %s [, ...] ] ) |\n" + " MATERIALIZED VIEW %s |\n" + " OPERATOR %s (%s, %s) |\n" + " OPERATOR CLASS %s USING %s |\n" + " OPERATOR FAMILY %s USING %s |\n" + " [ PROCEDURAL ] LANGUAGE %s |\n" + " SCHEMA %s |\n" + " SEQUENCE %s |\n" + " SERVER %s |\n" + " TABLE %s |\n" + " TEXT SEARCH CONFIGURATION %s |\n" + " TEXT SEARCH DICTIONARY %s |\n" + " TEXT SEARCH PARSER %s |\n" + " TEXT SEARCH TEMPLATE %s |\n" + " TRANSFORM FOR %s LANGUAGE %s |\n" + " TYPE %s |\n" + " VIEW %s\n" + "\n" + "%s\n" + "\n" + "* |\n" + "[ %s ] [ %s ] %s [ , ... ] |\n" + "[ [ %s ] [ %s ] %s [ , ... ] ] ORDER BY [ %s ] [ %s ] %s [ , ... ]", + _("name"), + _("new_version"), + _("name"), + _("new_schema"), + _("name"), + _("member_object"), + _("name"), + _("member_object"), + _("where member_object is:"), + _("aggregate_name"), + _("aggregate_signature"), + _("source_type"), + _("target_type"), + _("object_name"), + _("object_name"), + _("object_name"), + _("object_name"), + _("object_name"), + _("object_name"), + _("function_name"), + _("argmode"), + _("argname"), + _("argtype"), + _("object_name"), + _("operator_name"), + _("left_type"), + _("right_type"), + _("object_name"), + _("index_method"), + _("object_name"), + _("index_method"), + _("object_name"), + _("object_name"), + _("object_name"), + _("object_name"), + _("object_name"), + _("object_name"), + _("object_name"), + _("object_name"), + _("object_name"), + _("type_name"), + _("lang_name"), + _("object_name"), + _("object_name"), + _("and aggregate_signature is:"), + _("argmode"), + _("argname"), + _("argtype"), + _("argmode"), + _("argname"), + _("argtype"), + _("argmode"), + _("argname"), + _("argtype")); +} + +void +sql_help_ALTER_FOREIGN_DATA_WRAPPER(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "ALTER FOREIGN DATA WRAPPER %s\n" + " [ HANDLER %s | NO HANDLER ]\n" + " [ VALIDATOR %s | NO VALIDATOR ]\n" + " [ OPTIONS ( [ ADD | SET | DROP ] %s ['%s'] [, ... ]) ]\n" + "ALTER FOREIGN DATA WRAPPER %s OWNER TO { %s | CURRENT_USER | SESSION_USER }\n" + "ALTER FOREIGN DATA WRAPPER %s RENAME TO %s", + _("name"), + _("handler_function"), + _("validator_function"), + _("option"), + _("value"), + _("name"), + _("new_owner"), + _("name"), + _("new_name")); +} + +void +sql_help_ALTER_FOREIGN_TABLE(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "ALTER FOREIGN TABLE [ IF EXISTS ] [ ONLY ] %s [ * ]\n" + " %s [, ... ]\n" + "ALTER FOREIGN TABLE [ IF EXISTS ] [ ONLY ] %s [ * ]\n" + " RENAME [ COLUMN ] %s TO %s\n" + "ALTER FOREIGN TABLE [ IF EXISTS ] %s\n" + " RENAME TO %s\n" + "ALTER FOREIGN TABLE [ IF EXISTS ] %s\n" + " SET SCHEMA %s\n" + "\n" + "%s\n" + "\n" + " ADD [ COLUMN ] %s %s [ COLLATE %s ] [ %s [ ... ] ]\n" + " DROP [ COLUMN ] [ IF EXISTS ] %s [ RESTRICT | CASCADE ]\n" + " ALTER [ COLUMN ] %s [ SET DATA ] TYPE %s [ COLLATE %s ]\n" + " ALTER [ COLUMN ] %s SET DEFAULT %s\n" + " ALTER [ COLUMN ] %s DROP DEFAULT\n" + " ALTER [ COLUMN ] %s { SET | DROP } NOT NULL\n" + " ALTER [ COLUMN ] %s SET STATISTICS %s\n" + " ALTER [ COLUMN ] %s SET ( %s = %s [, ... ] )\n" + " ALTER [ COLUMN ] %s RESET ( %s [, ... ] )\n" + " ALTER [ COLUMN ] %s SET STORAGE { PLAIN | EXTERNAL | EXTENDED | MAIN }\n" + " ALTER [ COLUMN ] %s OPTIONS ( [ ADD | SET | DROP ] %s ['%s'] [, ... ])\n" + " ADD %s [ NOT VALID ]\n" + " VALIDATE CONSTRAINT %s\n" + " DROP CONSTRAINT [ IF EXISTS ] %s [ RESTRICT | CASCADE ]\n" + " DISABLE TRIGGER [ %s | ALL | USER ]\n" + " ENABLE TRIGGER [ %s | ALL | USER ]\n" + " ENABLE REPLICA TRIGGER %s\n" + " ENABLE ALWAYS TRIGGER %s\n" + " SET WITH OIDS\n" + " SET WITHOUT OIDS\n" + " INHERIT %s\n" + " NO INHERIT %s\n" + " OWNER TO { %s | CURRENT_USER | SESSION_USER }\n" + " OPTIONS ( [ ADD | SET | DROP ] %s ['%s'] [, ... ])", + _("name"), + _("action"), + _("name"), + _("column_name"), + _("new_column_name"), + _("name"), + _("new_name"), + _("name"), + _("new_schema"), + _("where action is one of:"), + _("column_name"), + _("data_type"), + _("collation"), + _("column_constraint"), + _("column_name"), + _("column_name"), + _("data_type"), + _("collation"), + _("column_name"), + _("expression"), + _("column_name"), + _("column_name"), + _("column_name"), + _("integer"), + _("column_name"), + _("attribute_option"), + _("value"), + _("column_name"), + _("attribute_option"), + _("column_name"), + _("column_name"), + _("option"), + _("value"), + _("table_constraint"), + _("constraint_name"), + _("constraint_name"), + _("trigger_name"), + _("trigger_name"), + _("trigger_name"), + _("trigger_name"), + _("parent_table"), + _("parent_table"), + _("new_owner"), + _("option"), + _("value")); +} + +void +sql_help_ALTER_FUNCTION(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "ALTER FUNCTION %s ( [ [ %s ] [ %s ] %s [, ...] ] )\n" + " %s [ ... ] [ RESTRICT ]\n" + "ALTER FUNCTION %s ( [ [ %s ] [ %s ] %s [, ...] ] )\n" + " RENAME TO %s\n" + "ALTER FUNCTION %s ( [ [ %s ] [ %s ] %s [, ...] ] )\n" + " OWNER TO { %s | CURRENT_USER | SESSION_USER }\n" + "ALTER FUNCTION %s ( [ [ %s ] [ %s ] %s [, ...] ] )\n" + " SET SCHEMA %s\n" + "\n" + "%s\n" + "\n" + " CALLED ON NULL INPUT | RETURNS NULL ON NULL INPUT | STRICT\n" + " IMMUTABLE | STABLE | VOLATILE | [ NOT ] LEAKPROOF\n" + " [ EXTERNAL ] SECURITY INVOKER | [ EXTERNAL ] SECURITY DEFINER\n" + " COST %s\n" + " ROWS %s\n" + " SET %s { TO | = } { %s | DEFAULT }\n" + " SET %s FROM CURRENT\n" + " RESET %s\n" + " RESET ALL", + _("name"), + _("argmode"), + _("argname"), + _("argtype"), + _("action"), + _("name"), + _("argmode"), + _("argname"), + _("argtype"), + _("new_name"), + _("name"), + _("argmode"), + _("argname"), + _("argtype"), + _("new_owner"), + _("name"), + _("argmode"), + _("argname"), + _("argtype"), + _("new_schema"), + _("where action is one of:"), + _("execution_cost"), + _("result_rows"), + _("configuration_parameter"), + _("value"), + _("configuration_parameter"), + _("configuration_parameter")); +} + +void +sql_help_ALTER_GROUP(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "ALTER GROUP %s ADD USER %s [, ... ]\n" + "ALTER GROUP %s DROP USER %s [, ... ]\n" + "\n" + "%s\n" + "\n" + " %s\n" + " | CURRENT_USER\n" + " | SESSION_USER\n" + "\n" + "ALTER GROUP %s RENAME TO %s", + _("role_specification"), + _("user_name"), + _("role_specification"), + _("user_name"), + _("where role_specification can be:"), + _("role_name"), + _("group_name"), + _("new_name")); +} + +void +sql_help_ALTER_INDEX(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "ALTER INDEX [ IF EXISTS ] %s RENAME TO %s\n" + "ALTER INDEX [ IF EXISTS ] %s SET TABLESPACE %s\n" + "ALTER INDEX [ IF EXISTS ] %s SET ( %s = %s [, ... ] )\n" + "ALTER INDEX [ IF EXISTS ] %s RESET ( %s [, ... ] )\n" + "ALTER INDEX ALL IN TABLESPACE %s [ OWNED BY %s [, ... ] ]\n" + " SET TABLESPACE %s [ NOWAIT ]", + _("name"), + _("new_name"), + _("name"), + _("tablespace_name"), + _("name"), + _("storage_parameter"), + _("value"), + _("name"), + _("storage_parameter"), + _("name"), + _("role_name"), + _("new_tablespace")); +} + +void +sql_help_ALTER_LANGUAGE(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "ALTER [ PROCEDURAL ] LANGUAGE %s RENAME TO %s\n" + "ALTER [ PROCEDURAL ] LANGUAGE %s OWNER TO { %s | CURRENT_USER | SESSION_USER }", + _("name"), + _("new_name"), + _("name"), + _("new_owner")); +} + +void +sql_help_ALTER_LARGE_OBJECT(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "ALTER LARGE OBJECT %s OWNER TO { %s | CURRENT_USER | SESSION_USER }", + _("large_object_oid"), + _("new_owner")); +} + +void +sql_help_ALTER_MATERIALIZED_VIEW(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "ALTER MATERIALIZED VIEW [ IF EXISTS ] %s\n" + " %s [, ... ]\n" + "ALTER MATERIALIZED VIEW [ IF EXISTS ] %s\n" + " RENAME [ COLUMN ] %s TO %s\n" + "ALTER MATERIALIZED VIEW [ IF EXISTS ] %s\n" + " RENAME TO %s\n" + "ALTER MATERIALIZED VIEW [ IF EXISTS ] %s\n" + " SET SCHEMA %s\n" + "ALTER MATERIALIZED VIEW ALL IN TABLESPACE %s [ OWNED BY %s [, ... ] ]\n" + " SET TABLESPACE %s [ NOWAIT ]\n" + "\n" + "%s\n" + "\n" + " ALTER [ COLUMN ] %s SET STATISTICS %s\n" + " ALTER [ COLUMN ] %s SET ( %s = %s [, ... ] )\n" + " ALTER [ COLUMN ] %s RESET ( %s [, ... ] )\n" + " ALTER [ COLUMN ] %s SET STORAGE { PLAIN | EXTERNAL | EXTENDED | MAIN }\n" + " CLUSTER ON %s\n" + " SET WITHOUT CLUSTER\n" + " SET ( %s = %s [, ... ] )\n" + " RESET ( %s [, ... ] )\n" + " OWNER TO { %s | CURRENT_USER | SESSION_USER }\n" + " SET TABLESPACE %s", + _("name"), + _("action"), + _("name"), + _("column_name"), + _("new_column_name"), + _("name"), + _("new_name"), + _("name"), + _("new_schema"), + _("name"), + _("role_name"), + _("new_tablespace"), + _("where action is one of:"), + _("column_name"), + _("integer"), + _("column_name"), + _("attribute_option"), + _("value"), + _("column_name"), + _("attribute_option"), + _("column_name"), + _("index_name"), + _("storage_parameter"), + _("value"), + _("storage_parameter"), + _("new_owner"), + _("new_tablespace")); +} + +void +sql_help_ALTER_OPERATOR(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "ALTER OPERATOR %s ( { %s | NONE } , { %s | NONE } )\n" + " OWNER TO { %s | CURRENT_USER | SESSION_USER }\n" + "\n" + "ALTER OPERATOR %s ( { %s | NONE } , { %s | NONE } )\n" + " SET SCHEMA %s", + _("name"), + _("left_type"), + _("right_type"), + _("new_owner"), + _("name"), + _("left_type"), + _("right_type"), + _("new_schema")); +} + +void +sql_help_ALTER_OPERATOR_CLASS(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "ALTER OPERATOR CLASS %s USING %s\n" + " RENAME TO %s\n" + "\n" + "ALTER OPERATOR CLASS %s USING %s\n" + " OWNER TO { %s | CURRENT_USER | SESSION_USER }\n" + "\n" + "ALTER OPERATOR CLASS %s USING %s\n" + " SET SCHEMA %s", + _("name"), + _("index_method"), + _("new_name"), + _("name"), + _("index_method"), + _("new_owner"), + _("name"), + _("index_method"), + _("new_schema")); +} + +void +sql_help_ALTER_OPERATOR_FAMILY(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "ALTER OPERATOR FAMILY %s USING %s ADD\n" + " { OPERATOR %s %s ( %s, %s )\n" + " [ FOR SEARCH | FOR ORDER BY %s ]\n" + " | FUNCTION %s [ ( %s [ , %s ] ) ]\n" + " %s ( %s [, ...] )\n" + " } [, ... ]\n" + "\n" + "ALTER OPERATOR FAMILY %s USING %s DROP\n" + " { OPERATOR %s ( %s [ , %s ] )\n" + " | FUNCTION %s ( %s [ , %s ] )\n" + " } [, ... ]\n" + "\n" + "ALTER OPERATOR FAMILY %s USING %s\n" + " RENAME TO %s\n" + "\n" + "ALTER OPERATOR FAMILY %s USING %s\n" + " OWNER TO { %s | CURRENT_USER | SESSION_USER }\n" + "\n" + "ALTER OPERATOR FAMILY %s USING %s\n" + " SET SCHEMA %s", + _("name"), + _("index_method"), + _("strategy_number"), + _("operator_name"), + _("op_type"), + _("op_type"), + _("sort_family_name"), + _("support_number"), + _("op_type"), + _("op_type"), + _("function_name"), + _("argument_type"), + _("name"), + _("index_method"), + _("strategy_number"), + _("op_type"), + _("op_type"), + _("support_number"), + _("op_type"), + _("op_type"), + _("name"), + _("index_method"), + _("new_name"), + _("name"), + _("index_method"), + _("new_owner"), + _("name"), + _("index_method"), + _("new_schema")); +} + +void +sql_help_ALTER_POLICY(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "ALTER POLICY %s ON %s RENAME TO %s\n" + "\n" + "ALTER POLICY %s ON %s\n" + " [ TO { %s | PUBLIC | CURRENT_USER | SESSION_USER } [, ...] ]\n" + " [ USING ( %s ) ]\n" + " [ WITH CHECK ( %s ) ]", + _("name"), + _("table_name"), + _("new_name"), + _("name"), + _("table_name"), + _("role_name"), + _("using_expression"), + _("check_expression")); +} + +void +sql_help_ALTER_ROLE(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "ALTER ROLE %s [ WITH ] %s [ ... ]\n" + "\n" + "%s\n" + "\n" + " SUPERUSER | NOSUPERUSER\n" + " | CREATEDB | NOCREATEDB\n" + " | CREATEROLE | NOCREATEROLE\n" + " | CREATEUSER | NOCREATEUSER\n" + " | INHERIT | NOINHERIT\n" + " | LOGIN | NOLOGIN\n" + " | REPLICATION | NOREPLICATION\n" + " | BYPASSRLS | NOBYPASSRLS\n" + " | CONNECTION LIMIT %s\n" + " | [ ENCRYPTED | UNENCRYPTED ] PASSWORD '%s'\n" + " | VALID UNTIL '%s'\n" + "\n" + "ALTER ROLE %s RENAME TO %s\n" + "\n" + "ALTER ROLE { %s | ALL } [ IN DATABASE %s ] SET %s { TO | = } { %s | DEFAULT }\n" + "ALTER ROLE { %s | ALL } [ IN DATABASE %s ] SET %s FROM CURRENT\n" + "ALTER ROLE { %s | ALL } [ IN DATABASE %s ] RESET %s\n" + "ALTER ROLE { %s | ALL } [ IN DATABASE %s ] RESET ALL\n" + "\n" + "%s\n" + "\n" + " [ GROUP ] %s\n" + " | CURRENT_USER\n" + " | SESSION_USER", + _("role_specification"), + _("option"), + _("where option can be:"), + _("connlimit"), + _("password"), + _("timestamp"), + _("name"), + _("new_name"), + _("role_specification"), + _("database_name"), + _("configuration_parameter"), + _("value"), + _("role_specification"), + _("database_name"), + _("configuration_parameter"), + _("role_specification"), + _("database_name"), + _("configuration_parameter"), + _("role_specification"), + _("database_name"), + _("where role_specification can be:"), + _("role_name")); +} + +void +sql_help_ALTER_RULE(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "ALTER RULE %s ON %s RENAME TO %s", + _("name"), + _("table_name"), + _("new_name")); +} + +void +sql_help_ALTER_SCHEMA(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "ALTER SCHEMA %s RENAME TO %s\n" + "ALTER SCHEMA %s OWNER TO { %s | CURRENT_USER | SESSION_USER }", + _("name"), + _("new_name"), + _("name"), + _("new_owner")); +} + +void +sql_help_ALTER_SEQUENCE(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "ALTER SEQUENCE [ IF EXISTS ] %s [ INCREMENT [ BY ] %s ]\n" + " [ MINVALUE %s | NO MINVALUE ] [ MAXVALUE %s | NO MAXVALUE ]\n" + " [ START [ WITH ] %s ]\n" + " [ RESTART [ [ WITH ] %s ] ]\n" + " [ CACHE %s ] [ [ NO ] CYCLE ]\n" + " [ OWNED BY { %s.%s | NONE } ]\n" + "ALTER SEQUENCE [ IF EXISTS ] %s OWNER TO { %s | CURRENT_USER | SESSION_USER }\n" + "ALTER SEQUENCE [ IF EXISTS ] %s RENAME TO %s\n" + "ALTER SEQUENCE [ IF EXISTS ] %s SET SCHEMA %s", + _("name"), + _("increment"), + _("minvalue"), + _("maxvalue"), + _("start"), + _("restart"), + _("cache"), + _("table_name"), + _("column_name"), + _("name"), + _("new_owner"), + _("name"), + _("new_name"), + _("name"), + _("new_schema")); +} + +void +sql_help_ALTER_SERVER(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "ALTER SERVER %s [ VERSION '%s' ]\n" + " [ OPTIONS ( [ ADD | SET | DROP ] %s ['%s'] [, ... ] ) ]\n" + "ALTER SERVER %s OWNER TO { %s | CURRENT_USER | SESSION_USER }\n" + "ALTER SERVER %s RENAME TO %s", + _("name"), + _("new_version"), + _("option"), + _("value"), + _("name"), + _("new_owner"), + _("name"), + _("new_name")); +} + +void +sql_help_ALTER_SYSTEM(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "ALTER SYSTEM SET %s { TO | = } { %s | '%s' | DEFAULT }\n" + "\n" + "ALTER SYSTEM RESET %s\n" + "ALTER SYSTEM RESET ALL", + _("configuration_parameter"), + _("value"), + _("value"), + _("configuration_parameter")); +} + +void +sql_help_ALTER_TABLE(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "ALTER TABLE [ IF EXISTS ] [ ONLY ] %s [ * ]\n" + " %s [, ... ]\n" + "ALTER TABLE [ IF EXISTS ] [ ONLY ] %s [ * ]\n" + " RENAME [ COLUMN ] %s TO %s\n" + "ALTER TABLE [ IF EXISTS ] [ ONLY ] %s [ * ]\n" + " RENAME CONSTRAINT %s TO %s\n" + "ALTER TABLE [ IF EXISTS ] %s\n" + " RENAME TO %s\n" + "ALTER TABLE [ IF EXISTS ] %s\n" + " SET SCHEMA %s\n" + "ALTER TABLE ALL IN TABLESPACE %s [ OWNED BY %s [, ... ] ]\n" + " SET TABLESPACE %s [ NOWAIT ]\n" + "\n" + "%s\n" + "\n" + " ADD [ COLUMN ] %s %s [ COLLATE %s ] [ %s [ ... ] ]\n" + " DROP [ COLUMN ] [ IF EXISTS ] %s [ RESTRICT | CASCADE ]\n" + " ALTER [ COLUMN ] %s [ SET DATA ] TYPE %s [ COLLATE %s ] [ USING %s ]\n" + " ALTER [ COLUMN ] %s SET DEFAULT %s\n" + " ALTER [ COLUMN ] %s DROP DEFAULT\n" + " ALTER [ COLUMN ] %s { SET | DROP } NOT NULL\n" + " ALTER [ COLUMN ] %s SET STATISTICS %s\n" + " ALTER [ COLUMN ] %s SET ( %s = %s [, ... ] )\n" + " ALTER [ COLUMN ] %s RESET ( %s [, ... ] )\n" + " ALTER [ COLUMN ] %s SET STORAGE { PLAIN | EXTERNAL | EXTENDED | MAIN }\n" + " ADD %s [ NOT VALID ]\n" + " ADD %s\n" + " ALTER CONSTRAINT %s [ DEFERRABLE | NOT DEFERRABLE ] [ INITIALLY DEFERRED | INITIALLY IMMEDIATE ]\n" + " VALIDATE CONSTRAINT %s\n" + " DROP CONSTRAINT [ IF EXISTS ] %s [ RESTRICT | CASCADE ]\n" + " DISABLE TRIGGER [ %s | ALL | USER ]\n" + " ENABLE TRIGGER [ %s | ALL | USER ]\n" + " ENABLE REPLICA TRIGGER %s\n" + " ENABLE ALWAYS TRIGGER %s\n" + " DISABLE RULE %s\n" + " ENABLE RULE %s\n" + " ENABLE REPLICA RULE %s\n" + " ENABLE ALWAYS RULE %s\n" + " DISABLE ROW LEVEL SECURITY\n" + " ENABLE ROW LEVEL SECURITY\n" + " FORCE ROW LEVEL SECURITY\n" + " NO FORCE ROW LEVEL SECURITY\n" + " CLUSTER ON %s\n" + " SET WITHOUT CLUSTER\n" + " SET WITH OIDS\n" + " SET WITHOUT OIDS\n" + " SET TABLESPACE %s\n" + " SET { LOGGED | UNLOGGED }\n" + " SET ( %s = %s [, ... ] )\n" + " RESET ( %s [, ... ] )\n" + " INHERIT %s\n" + " NO INHERIT %s\n" + " OF %s\n" + " NOT OF\n" + " OWNER TO { %s | CURRENT_USER | SESSION_USER }\n" + " REPLICA IDENTITY { DEFAULT | USING INDEX %s | FULL | NOTHING }\n" + "\n" + "%s\n" + "\n" + " [ CONSTRAINT %s ]\n" + " { UNIQUE | PRIMARY KEY } USING INDEX %s\n" + " [ DEFERRABLE | NOT DEFERRABLE ] [ INITIALLY DEFERRED | INITIALLY IMMEDIATE ]", + _("name"), + _("action"), + _("name"), + _("column_name"), + _("new_column_name"), + _("name"), + _("constraint_name"), + _("new_constraint_name"), + _("name"), + _("new_name"), + _("name"), + _("new_schema"), + _("name"), + _("role_name"), + _("new_tablespace"), + _("where action is one of:"), + _("column_name"), + _("data_type"), + _("collation"), + _("column_constraint"), + _("column_name"), + _("column_name"), + _("data_type"), + _("collation"), + _("expression"), + _("column_name"), + _("expression"), + _("column_name"), + _("column_name"), + _("column_name"), + _("integer"), + _("column_name"), + _("attribute_option"), + _("value"), + _("column_name"), + _("attribute_option"), + _("column_name"), + _("table_constraint"), + _("table_constraint_using_index"), + _("constraint_name"), + _("constraint_name"), + _("constraint_name"), + _("trigger_name"), + _("trigger_name"), + _("trigger_name"), + _("trigger_name"), + _("rewrite_rule_name"), + _("rewrite_rule_name"), + _("rewrite_rule_name"), + _("rewrite_rule_name"), + _("index_name"), + _("new_tablespace"), + _("storage_parameter"), + _("value"), + _("storage_parameter"), + _("parent_table"), + _("parent_table"), + _("type_name"), + _("new_owner"), + _("index_name"), + _("and table_constraint_using_index is:"), + _("constraint_name"), + _("index_name")); +} + +void +sql_help_ALTER_TABLESPACE(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "ALTER TABLESPACE %s RENAME TO %s\n" + "ALTER TABLESPACE %s OWNER TO { %s | CURRENT_USER | SESSION_USER }\n" + "ALTER TABLESPACE %s SET ( %s = %s [, ... ] )\n" + "ALTER TABLESPACE %s RESET ( %s [, ... ] )", + _("name"), + _("new_name"), + _("name"), + _("new_owner"), + _("name"), + _("tablespace_option"), + _("value"), + _("name"), + _("tablespace_option")); +} + +void +sql_help_ALTER_TEXT_SEARCH_CONFIGURATION(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "ALTER TEXT SEARCH CONFIGURATION %s\n" + " ADD MAPPING FOR %s [, ... ] WITH %s [, ... ]\n" + "ALTER TEXT SEARCH CONFIGURATION %s\n" + " ALTER MAPPING FOR %s [, ... ] WITH %s [, ... ]\n" + "ALTER TEXT SEARCH CONFIGURATION %s\n" + " ALTER MAPPING REPLACE %s WITH %s\n" + "ALTER TEXT SEARCH CONFIGURATION %s\n" + " ALTER MAPPING FOR %s [, ... ] REPLACE %s WITH %s\n" + "ALTER TEXT SEARCH CONFIGURATION %s\n" + " DROP MAPPING [ IF EXISTS ] FOR %s [, ... ]\n" + "ALTER TEXT SEARCH CONFIGURATION %s RENAME TO %s\n" + "ALTER TEXT SEARCH CONFIGURATION %s OWNER TO { %s | CURRENT_USER | SESSION_USER }\n" + "ALTER TEXT SEARCH CONFIGURATION %s SET SCHEMA %s", + _("name"), + _("token_type"), + _("dictionary_name"), + _("name"), + _("token_type"), + _("dictionary_name"), + _("name"), + _("old_dictionary"), + _("new_dictionary"), + _("name"), + _("token_type"), + _("old_dictionary"), + _("new_dictionary"), + _("name"), + _("token_type"), + _("name"), + _("new_name"), + _("name"), + _("new_owner"), + _("name"), + _("new_schema")); +} + +void +sql_help_ALTER_TEXT_SEARCH_DICTIONARY(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "ALTER TEXT SEARCH DICTIONARY %s (\n" + " %s [ = %s ] [, ... ]\n" + ")\n" + "ALTER TEXT SEARCH DICTIONARY %s RENAME TO %s\n" + "ALTER TEXT SEARCH DICTIONARY %s OWNER TO { %s | CURRENT_USER | SESSION_USER }\n" + "ALTER TEXT SEARCH DICTIONARY %s SET SCHEMA %s", + _("name"), + _("option"), + _("value"), + _("name"), + _("new_name"), + _("name"), + _("new_owner"), + _("name"), + _("new_schema")); +} + +void +sql_help_ALTER_TEXT_SEARCH_PARSER(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "ALTER TEXT SEARCH PARSER %s RENAME TO %s\n" + "ALTER TEXT SEARCH PARSER %s SET SCHEMA %s", + _("name"), + _("new_name"), + _("name"), + _("new_schema")); +} + +void +sql_help_ALTER_TEXT_SEARCH_TEMPLATE(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "ALTER TEXT SEARCH TEMPLATE %s RENAME TO %s\n" + "ALTER TEXT SEARCH TEMPLATE %s SET SCHEMA %s", + _("name"), + _("new_name"), + _("name"), + _("new_schema")); +} + +void +sql_help_ALTER_TRIGGER(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "ALTER TRIGGER %s ON %s RENAME TO %s", + _("name"), + _("table_name"), + _("new_name")); +} + +void +sql_help_ALTER_TYPE(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "ALTER TYPE %s %s [, ... ]\n" + "ALTER TYPE %s OWNER TO { %s | CURRENT_USER | SESSION_USER }\n" + "ALTER TYPE %s RENAME ATTRIBUTE %s TO %s [ CASCADE | RESTRICT ]\n" + "ALTER TYPE %s RENAME TO %s\n" + "ALTER TYPE %s SET SCHEMA %s\n" + "ALTER TYPE %s ADD VALUE [ IF NOT EXISTS ] %s [ { BEFORE | AFTER } %s ]\n" + "\n" + "%s\n" + "\n" + " ADD ATTRIBUTE %s %s [ COLLATE %s ] [ CASCADE | RESTRICT ]\n" + " DROP ATTRIBUTE [ IF EXISTS ] %s [ CASCADE | RESTRICT ]\n" + " ALTER ATTRIBUTE %s [ SET DATA ] TYPE %s [ COLLATE %s ] [ CASCADE | RESTRICT ]", + _("name"), + _("action"), + _("name"), + _("new_owner"), + _("name"), + _("attribute_name"), + _("new_attribute_name"), + _("name"), + _("new_name"), + _("name"), + _("new_schema"), + _("name"), + _("new_enum_value"), + _("existing_enum_value"), + _("where action is one of:"), + _("attribute_name"), + _("data_type"), + _("collation"), + _("attribute_name"), + _("attribute_name"), + _("data_type"), + _("collation")); +} + +void +sql_help_ALTER_USER(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "ALTER USER %s [ WITH ] %s [ ... ]\n" + "\n" + "%s\n" + "\n" + " SUPERUSER | NOSUPERUSER\n" + " | CREATEDB | NOCREATEDB\n" + " | CREATEROLE | NOCREATEROLE\n" + " | CREATEUSER | NOCREATEUSER\n" + " | INHERIT | NOINHERIT\n" + " | LOGIN | NOLOGIN\n" + " | REPLICATION | NOREPLICATION\n" + " | CONNECTION LIMIT %s\n" + " | [ ENCRYPTED | UNENCRYPTED ] PASSWORD '%s'\n" + " | VALID UNTIL '%s'\n" + "\n" + "ALTER USER %s RENAME TO %s\n" + "\n" + "ALTER USER %s SET %s { TO | = } { %s | DEFAULT }\n" + "ALTER USER %s SET %s FROM CURRENT\n" + "ALTER USER %s RESET %s\n" + "ALTER USER %s RESET ALL\n" + "\n" + "%s\n" + "\n" + " [ GROUP ] %s\n" + " | CURRENT_USER\n" + " | SESSION_USER", + _("role_specification"), + _("option"), + _("where option can be:"), + _("connlimit"), + _("password"), + _("timestamp"), + _("name"), + _("new_name"), + _("role_specification"), + _("configuration_parameter"), + _("value"), + _("role_specification"), + _("configuration_parameter"), + _("role_specification"), + _("configuration_parameter"), + _("role_specification"), + _("where role_specification can be:"), + _("role_name")); +} + +void +sql_help_ALTER_USER_MAPPING(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "ALTER USER MAPPING FOR { %s | USER | CURRENT_USER | SESSION_USER | PUBLIC }\n" + " SERVER %s\n" + " OPTIONS ( [ ADD | SET | DROP ] %s ['%s'] [, ... ] )", + _("user_name"), + _("server_name"), + _("option"), + _("value")); +} + +void +sql_help_ALTER_VIEW(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "ALTER VIEW [ IF EXISTS ] %s ALTER [ COLUMN ] %s SET DEFAULT %s\n" + "ALTER VIEW [ IF EXISTS ] %s ALTER [ COLUMN ] %s DROP DEFAULT\n" + "ALTER VIEW [ IF EXISTS ] %s OWNER TO { %s | CURRENT_USER | SESSION_USER }\n" + "ALTER VIEW [ IF EXISTS ] %s RENAME TO %s\n" + "ALTER VIEW [ IF EXISTS ] %s SET SCHEMA %s\n" + "ALTER VIEW [ IF EXISTS ] %s SET ( %s [= %s] [, ... ] )\n" + "ALTER VIEW [ IF EXISTS ] %s RESET ( %s [, ... ] )", + _("name"), + _("column_name"), + _("expression"), + _("name"), + _("column_name"), + _("name"), + _("new_owner"), + _("name"), + _("new_name"), + _("name"), + _("new_schema"), + _("name"), + _("view_option_name"), + _("view_option_value"), + _("name"), + _("view_option_name")); +} + +void +sql_help_ANALYZE(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "ANALYZE [ VERBOSE ] [ %s [ ( %s [, ...] ) ] ]", + _("table_name"), + _("column_name")); +} + +void +sql_help_BEGIN(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "BEGIN [ WORK | TRANSACTION ] [ %s [, ...] ]\n" + "\n" + "%s\n" + "\n" + " ISOLATION LEVEL { SERIALIZABLE | REPEATABLE READ | READ COMMITTED | READ UNCOMMITTED }\n" + " READ WRITE | READ ONLY\n" + " [ NOT ] DEFERRABLE", + _("transaction_mode"), + _("where transaction_mode is one of:")); +} + +void +sql_help_CHECKPOINT(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "CHECKPOINT"); +} + +void +sql_help_CLOSE(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "CLOSE { %s | ALL }", + _("name")); +} + +void +sql_help_CLUSTER(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "CLUSTER [VERBOSE] %s [ USING %s ]\n" + "CLUSTER [VERBOSE]", + _("table_name"), + _("index_name")); +} + +void +sql_help_COMMENT(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "COMMENT ON\n" + "{\n" + " AGGREGATE %s ( %s ) |\n" + " CAST (%s AS %s) |\n" + " COLLATION %s |\n" + " COLUMN %s.%s |\n" + " CONSTRAINT %s ON %s |\n" + " CONSTRAINT %s ON DOMAIN %s |\n" + " CONVERSION %s |\n" + " DATABASE %s |\n" + " DOMAIN %s |\n" + " EXTENSION %s |\n" + " EVENT TRIGGER %s |\n" + " FOREIGN DATA WRAPPER %s |\n" + " FOREIGN TABLE %s |\n" + " FUNCTION %s ( [ [ %s ] [ %s ] %s [, ...] ] ) |\n" + " INDEX %s |\n" + " LARGE OBJECT %s |\n" + " MATERIALIZED VIEW %s |\n" + " OPERATOR %s (%s, %s) |\n" + " OPERATOR CLASS %s USING %s |\n" + " OPERATOR FAMILY %s USING %s |\n" + " POLICY %s ON %s |\n" + " [ PROCEDURAL ] LANGUAGE %s |\n" + " ROLE %s |\n" + " RULE %s ON %s |\n" + " SCHEMA %s |\n" + " SEQUENCE %s |\n" + " SERVER %s |\n" + " TABLE %s |\n" + " TABLESPACE %s |\n" + " TEXT SEARCH CONFIGURATION %s |\n" + " TEXT SEARCH DICTIONARY %s |\n" + " TEXT SEARCH PARSER %s |\n" + " TEXT SEARCH TEMPLATE %s |\n" + " TRANSFORM FOR %s LANGUAGE %s |\n" + " TRIGGER %s ON %s |\n" + " TYPE %s |\n" + " VIEW %s\n" + "} IS '%s'\n" + "\n" + "%s\n" + "\n" + "* |\n" + "[ %s ] [ %s ] %s [ , ... ] |\n" + "[ [ %s ] [ %s ] %s [ , ... ] ] ORDER BY [ %s ] [ %s ] %s [ , ... ]", + _("aggregate_name"), + _("aggregate_signature"), + _("source_type"), + _("target_type"), + _("object_name"), + _("relation_name"), + _("column_name"), + _("constraint_name"), + _("table_name"), + _("constraint_name"), + _("domain_name"), + _("object_name"), + _("object_name"), + _("object_name"), + _("object_name"), + _("object_name"), + _("object_name"), + _("object_name"), + _("function_name"), + _("argmode"), + _("argname"), + _("argtype"), + _("object_name"), + _("large_object_oid"), + _("object_name"), + _("operator_name"), + _("left_type"), + _("right_type"), + _("object_name"), + _("index_method"), + _("object_name"), + _("index_method"), + _("policy_name"), + _("table_name"), + _("object_name"), + _("object_name"), + _("rule_name"), + _("table_name"), + _("object_name"), + _("object_name"), + _("object_name"), + _("object_name"), + _("object_name"), + _("object_name"), + _("object_name"), + _("object_name"), + _("object_name"), + _("type_name"), + _("lang_name"), + _("trigger_name"), + _("table_name"), + _("object_name"), + _("object_name"), + _("text"), + _("where aggregate_signature is:"), + _("argmode"), + _("argname"), + _("argtype"), + _("argmode"), + _("argname"), + _("argtype"), + _("argmode"), + _("argname"), + _("argtype")); +} + +void +sql_help_COMMIT(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "COMMIT [ WORK | TRANSACTION ]"); +} + +void +sql_help_COMMIT_PREPARED(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "COMMIT PREPARED %s", + _("transaction_id")); +} + +void +sql_help_COPY(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "COPY %s [ ( %s [, ...] ) ]\n" + " FROM { '%s' | PROGRAM '%s' | STDIN }\n" + " [ [ WITH ] ( %s [, ...] ) ]\n" + "\n" + "COPY { %s [ ( %s [, ...] ) ] | ( %s ) }\n" + " TO { '%s' | PROGRAM '%s' | STDOUT }\n" + " [ [ WITH ] ( %s [, ...] ) ]\n" + "\n" + "%s\n" + "\n" + " FORMAT %s\n" + " OIDS [ %s ]\n" + " FREEZE [ %s ]\n" + " DELIMITER '%s'\n" + " NULL '%s'\n" + " HEADER [ %s ]\n" + " QUOTE '%s'\n" + " ESCAPE '%s'\n" + " FORCE_QUOTE { ( %s [, ...] ) | * }\n" + " FORCE_NOT_NULL ( %s [, ...] )\n" + " FORCE_NULL ( %s [, ...] )\n" + " ENCODING '%s'", + _("table_name"), + _("column_name"), + _("filename"), + _("command"), + _("option"), + _("table_name"), + _("column_name"), + _("query"), + _("filename"), + _("command"), + _("option"), + _("where option can be one of:"), + _("format_name"), + _("boolean"), + _("boolean"), + _("delimiter_character"), + _("null_string"), + _("boolean"), + _("quote_character"), + _("escape_character"), + _("column_name"), + _("column_name"), + _("column_name"), + _("encoding_name")); +} + +void +sql_help_CREATE_AGGREGATE(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "CREATE AGGREGATE %s ( [ %s ] [ %s ] %s [ , ... ] ) (\n" + " SFUNC = %s,\n" + " STYPE = %s\n" + " [ , SSPACE = %s ]\n" + " [ , FINALFUNC = %s ]\n" + " [ , FINALFUNC_EXTRA ]\n" + " [ , INITCOND = %s ]\n" + " [ , MSFUNC = %s ]\n" + " [ , MINVFUNC = %s ]\n" + " [ , MSTYPE = %s ]\n" + " [ , MSSPACE = %s ]\n" + " [ , MFINALFUNC = %s ]\n" + " [ , MFINALFUNC_EXTRA ]\n" + " [ , MINITCOND = %s ]\n" + " [ , SORTOP = %s ]\n" + ")\n" + "\n" + "CREATE AGGREGATE %s ( [ [ %s ] [ %s ] %s [ , ... ] ]\n" + " ORDER BY [ %s ] [ %s ] %s [ , ... ] ) (\n" + " SFUNC = %s,\n" + " STYPE = %s\n" + " [ , SSPACE = %s ]\n" + " [ , FINALFUNC = %s ]\n" + " [ , FINALFUNC_EXTRA ]\n" + " [ , INITCOND = %s ]\n" + " [ , HYPOTHETICAL ]\n" + ")\n" + "\n" + "%s\n" + "\n" + "CREATE AGGREGATE %s (\n" + " BASETYPE = %s,\n" + " SFUNC = %s,\n" + " STYPE = %s\n" + " [ , SSPACE = %s ]\n" + " [ , FINALFUNC = %s ]\n" + " [ , FINALFUNC_EXTRA ]\n" + " [ , INITCOND = %s ]\n" + " [ , MSFUNC = %s ]\n" + " [ , MINVFUNC = %s ]\n" + " [ , MSTYPE = %s ]\n" + " [ , MSSPACE = %s ]\n" + " [ , MFINALFUNC = %s ]\n" + " [ , MFINALFUNC_EXTRA ]\n" + " [ , MINITCOND = %s ]\n" + " [ , SORTOP = %s ]\n" + ")", + _("name"), + _("argmode"), + _("argname"), + _("arg_data_type"), + _("sfunc"), + _("state_data_type"), + _("state_data_size"), + _("ffunc"), + _("initial_condition"), + _("msfunc"), + _("minvfunc"), + _("mstate_data_type"), + _("mstate_data_size"), + _("mffunc"), + _("minitial_condition"), + _("sort_operator"), + _("name"), + _("argmode"), + _("argname"), + _("arg_data_type"), + _("argmode"), + _("argname"), + _("arg_data_type"), + _("sfunc"), + _("state_data_type"), + _("state_data_size"), + _("ffunc"), + _("initial_condition"), + _("or the old syntax"), + _("name"), + _("base_type"), + _("sfunc"), + _("state_data_type"), + _("state_data_size"), + _("ffunc"), + _("initial_condition"), + _("msfunc"), + _("minvfunc"), + _("mstate_data_type"), + _("mstate_data_size"), + _("mffunc"), + _("minitial_condition"), + _("sort_operator")); +} + +void +sql_help_CREATE_CAST(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "CREATE CAST (%s AS %s)\n" + " WITH FUNCTION %s (%s [, ...])\n" + " [ AS ASSIGNMENT | AS IMPLICIT ]\n" + "\n" + "CREATE CAST (%s AS %s)\n" + " WITHOUT FUNCTION\n" + " [ AS ASSIGNMENT | AS IMPLICIT ]\n" + "\n" + "CREATE CAST (%s AS %s)\n" + " WITH INOUT\n" + " [ AS ASSIGNMENT | AS IMPLICIT ]", + _("source_type"), + _("target_type"), + _("function_name"), + _("argument_type"), + _("source_type"), + _("target_type"), + _("source_type"), + _("target_type")); +} + +void +sql_help_CREATE_COLLATION(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "CREATE COLLATION %s (\n" + " [ LOCALE = %s, ]\n" + " [ LC_COLLATE = %s, ]\n" + " [ LC_CTYPE = %s ]\n" + ")\n" + "CREATE COLLATION %s FROM %s", + _("name"), + _("locale"), + _("lc_collate"), + _("lc_ctype"), + _("name"), + _("existing_collation")); +} + +void +sql_help_CREATE_CONVERSION(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "CREATE [ DEFAULT ] CONVERSION %s\n" + " FOR %s TO %s FROM %s", + _("name"), + _("source_encoding"), + _("dest_encoding"), + _("function_name")); +} + +void +sql_help_CREATE_DATABASE(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "CREATE DATABASE %s\n" + " [ [ WITH ] [ OWNER [=] %s ]\n" + " [ TEMPLATE [=] %s ]\n" + " [ ENCODING [=] %s ]\n" + " [ LC_COLLATE [=] %s ]\n" + " [ LC_CTYPE [=] %s ]\n" + " [ TABLESPACE [=] %s ]\n" + " [ ALLOW_CONNECTIONS [=] %s ]\n" + " [ CONNECTION LIMIT [=] %s ] ]\n" + " [ IS_TEMPLATE [=] %s ]", + _("name"), + _("user_name"), + _("template"), + _("encoding"), + _("lc_collate"), + _("lc_ctype"), + _("tablespace_name"), + _("allowconn"), + _("connlimit"), + _("istemplate")); +} + +void +sql_help_CREATE_DOMAIN(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "CREATE DOMAIN %s [ AS ] %s\n" + " [ COLLATE %s ]\n" + " [ DEFAULT %s ]\n" + " [ %s [ ... ] ]\n" + "\n" + "%s\n" + "\n" + "[ CONSTRAINT %s ]\n" + "{ NOT NULL | NULL | CHECK (%s) }", + _("name"), + _("data_type"), + _("collation"), + _("expression"), + _("constraint"), + _("where constraint is:"), + _("constraint_name"), + _("expression")); +} + +void +sql_help_CREATE_EVENT_TRIGGER(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "CREATE EVENT TRIGGER %s\n" + " ON %s\n" + " [ WHEN %s IN (filter_value [, ... ]) [ AND ... ] ]\n" + " EXECUTE PROCEDURE %s()", + _("name"), + _("event"), + _("filter_variable"), + _("function_name")); +} + +void +sql_help_CREATE_EXTENSION(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "CREATE EXTENSION [ IF NOT EXISTS ] %s\n" + " [ WITH ] [ SCHEMA %s ]\n" + " [ VERSION %s ]\n" + " [ FROM %s ]", + _("extension_name"), + _("schema_name"), + _("version"), + _("old_version")); +} + +void +sql_help_CREATE_FOREIGN_DATA_WRAPPER(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "CREATE FOREIGN DATA WRAPPER %s\n" + " [ HANDLER %s | NO HANDLER ]\n" + " [ VALIDATOR %s | NO VALIDATOR ]\n" + " [ OPTIONS ( %s '%s' [, ... ] ) ]", + _("name"), + _("handler_function"), + _("validator_function"), + _("option"), + _("value")); +} + +void +sql_help_CREATE_FOREIGN_TABLE(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "CREATE FOREIGN TABLE [ IF NOT EXISTS ] %s ( [\n" + " { %s %s [ OPTIONS ( %s '%s' [, ... ] ) ] [ COLLATE %s ] [ %s [ ... ] ]\n" + " | %s }\n" + " [, ... ]\n" + "] )\n" + "[ INHERITS ( %s [, ... ] ) ]\n" + " SERVER %s\n" + "[ OPTIONS ( %s '%s' [, ... ] ) ]\n" + "\n" + "%s\n" + "\n" + "[ CONSTRAINT %s ]\n" + "{ NOT NULL |\n" + " NULL |\n" + " CHECK ( %s ) [ NO INHERIT ] |\n" + " DEFAULT %s }\n" + "\n" + "%s\n" + "\n" + "[ CONSTRAINT %s ]\n" + "CHECK ( %s ) [ NO INHERIT ]", + _("table_name"), + _("column_name"), + _("data_type"), + _("option"), + _("value"), + _("collation"), + _("column_constraint"), + _("table_constraint"), + _("parent_table"), + _("server_name"), + _("option"), + _("value"), + _("where column_constraint is:"), + _("constraint_name"), + _("expression"), + _("default_expr"), + _("and table_constraint is:"), + _("constraint_name"), + _("expression")); +} + +void +sql_help_CREATE_FUNCTION(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "CREATE [ OR REPLACE ] FUNCTION\n" + " %s ( [ [ %s ] [ %s ] %s [ { DEFAULT | = } %s ] [, ...] ] )\n" + " [ RETURNS %s\n" + " | RETURNS TABLE ( %s %s [, ...] ) ]\n" + " { LANGUAGE %s\n" + " | TRANSFORM { FOR TYPE %s } [, ... ]\n" + " | WINDOW\n" + " | IMMUTABLE | STABLE | VOLATILE | [ NOT ] LEAKPROOF\n" + " | CALLED ON NULL INPUT | RETURNS NULL ON NULL INPUT | STRICT\n" + " | [ EXTERNAL ] SECURITY INVOKER | [ EXTERNAL ] SECURITY DEFINER\n" + " | COST %s\n" + " | ROWS %s\n" + " | SET %s { TO %s | = %s | FROM CURRENT }\n" + " | AS '%s'\n" + " | AS '%s', '%s'\n" + " } ...\n" + " [ WITH ( %s [, ...] ) ]", + _("name"), + _("argmode"), + _("argname"), + _("argtype"), + _("default_expr"), + _("rettype"), + _("column_name"), + _("column_type"), + _("lang_name"), + _("type_name"), + _("execution_cost"), + _("result_rows"), + _("configuration_parameter"), + _("value"), + _("value"), + _("definition"), + _("obj_file"), + _("link_symbol"), + _("attribute")); +} + +void +sql_help_CREATE_GROUP(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "CREATE GROUP %s [ [ WITH ] %s [ ... ] ]\n" + "\n" + "%s\n" + "\n" + " SUPERUSER | NOSUPERUSER\n" + " | CREATEDB | NOCREATEDB\n" + " | CREATEROLE | NOCREATEROLE\n" + " | CREATEUSER | NOCREATEUSER\n" + " | INHERIT | NOINHERIT\n" + " | LOGIN | NOLOGIN\n" + " | [ ENCRYPTED | UNENCRYPTED ] PASSWORD '%s'\n" + " | VALID UNTIL '%s'\n" + " | IN ROLE %s [, ...]\n" + " | IN GROUP %s [, ...]\n" + " | ROLE %s [, ...]\n" + " | ADMIN %s [, ...]\n" + " | USER %s [, ...]\n" + " | SYSID %s", + _("name"), + _("option"), + _("where option can be:"), + _("password"), + _("timestamp"), + _("role_name"), + _("role_name"), + _("role_name"), + _("role_name"), + _("role_name"), + _("uid")); +} + +void +sql_help_CREATE_INDEX(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "CREATE [ UNIQUE ] INDEX [ CONCURRENTLY ] [ [ IF NOT EXISTS ] %s ] ON %s [ USING %s ]\n" + " ( { %s | ( %s ) } [ COLLATE %s ] [ %s ] [ ASC | DESC ] [ NULLS { FIRST | LAST } ] [, ...] )\n" + " [ WITH ( %s = %s [, ... ] ) ]\n" + " [ TABLESPACE %s ]\n" + " [ WHERE %s ]", + _("name"), + _("table_name"), + _("method"), + _("column_name"), + _("expression"), + _("collation"), + _("opclass"), + _("storage_parameter"), + _("value"), + _("tablespace_name"), + _("predicate")); +} + +void +sql_help_CREATE_LANGUAGE(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "CREATE [ OR REPLACE ] [ PROCEDURAL ] LANGUAGE %s\n" + "CREATE [ OR REPLACE ] [ TRUSTED ] [ PROCEDURAL ] LANGUAGE %s\n" + " HANDLER %s [ INLINE %s ] [ VALIDATOR %s ]", + _("name"), + _("name"), + _("call_handler"), + _("inline_handler"), + _("valfunction")); +} + +void +sql_help_CREATE_MATERIALIZED_VIEW(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "CREATE MATERIALIZED VIEW [ IF NOT EXISTS ] %s\n" + " [ (%s [, ...] ) ]\n" + " [ WITH ( %s [= %s] [, ... ] ) ]\n" + " [ TABLESPACE %s ]\n" + " AS %s\n" + " [ WITH [ NO ] DATA ]", + _("table_name"), + _("column_name"), + _("storage_parameter"), + _("value"), + _("tablespace_name"), + _("query")); +} + +void +sql_help_CREATE_OPERATOR(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "CREATE OPERATOR %s (\n" + " PROCEDURE = %s\n" + " [, LEFTARG = %s ] [, RIGHTARG = %s ]\n" + " [, COMMUTATOR = %s ] [, NEGATOR = %s ]\n" + " [, RESTRICT = %s ] [, JOIN = %s ]\n" + " [, HASHES ] [, MERGES ]\n" + ")", + _("name"), + _("function_name"), + _("left_type"), + _("right_type"), + _("com_op"), + _("neg_op"), + _("res_proc"), + _("join_proc")); +} + +void +sql_help_CREATE_OPERATOR_CLASS(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "CREATE OPERATOR CLASS %s [ DEFAULT ] FOR TYPE %s\n" + " USING %s [ FAMILY %s ] AS\n" + " { OPERATOR %s %s [ ( %s, %s ) ] [ FOR SEARCH | FOR ORDER BY %s ]\n" + " | FUNCTION %s [ ( %s [ , %s ] ) ] %s ( %s [, ...] )\n" + " | STORAGE %s\n" + " } [, ... ]", + _("name"), + _("data_type"), + _("index_method"), + _("family_name"), + _("strategy_number"), + _("operator_name"), + _("op_type"), + _("op_type"), + _("sort_family_name"), + _("support_number"), + _("op_type"), + _("op_type"), + _("function_name"), + _("argument_type"), + _("storage_type")); +} + +void +sql_help_CREATE_OPERATOR_FAMILY(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "CREATE OPERATOR FAMILY %s USING %s", + _("name"), + _("index_method")); +} + +void +sql_help_CREATE_POLICY(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "CREATE POLICY %s ON %s\n" + " [ FOR { ALL | SELECT | INSERT | UPDATE | DELETE } ]\n" + " [ TO { %s | PUBLIC | CURRENT_USER | SESSION_USER } [, ...] ]\n" + " [ USING ( %s ) ]\n" + " [ WITH CHECK ( %s ) ]", + _("name"), + _("table_name"), + _("role_name"), + _("using_expression"), + _("check_expression")); +} + +void +sql_help_CREATE_ROLE(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "CREATE ROLE %s [ [ WITH ] %s [ ... ] ]\n" + "\n" + "%s\n" + "\n" + " SUPERUSER | NOSUPERUSER\n" + " | CREATEDB | NOCREATEDB\n" + " | CREATEROLE | NOCREATEROLE\n" + " | CREATEUSER | NOCREATEUSER\n" + " | INHERIT | NOINHERIT\n" + " | LOGIN | NOLOGIN\n" + " | REPLICATION | NOREPLICATION\n" + " | BYPASSRLS | NOBYPASSRLS\n" + " | CONNECTION LIMIT %s\n" + " | [ ENCRYPTED | UNENCRYPTED ] PASSWORD '%s'\n" + " | VALID UNTIL '%s'\n" + " | IN ROLE %s [, ...]\n" + " | IN GROUP %s [, ...]\n" + " | ROLE %s [, ...]\n" + " | ADMIN %s [, ...]\n" + " | USER %s [, ...]\n" + " | SYSID %s", + _("name"), + _("option"), + _("where option can be:"), + _("connlimit"), + _("password"), + _("timestamp"), + _("role_name"), + _("role_name"), + _("role_name"), + _("role_name"), + _("role_name"), + _("uid")); +} + +void +sql_help_CREATE_RULE(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "CREATE [ OR REPLACE ] RULE %s AS ON %s\n" + " TO %s [ WHERE %s ]\n" + " DO [ ALSO | INSTEAD ] { NOTHING | %s | ( %s ; %s ... ) }\n" + "\n" + "%s\n" + "\n" + " SELECT | INSERT | UPDATE | DELETE", + _("name"), + _("event"), + _("table_name"), + _("condition"), + _("command"), + _("command"), + _("command"), + _("where event can be one of:")); +} + +void +sql_help_CREATE_SCHEMA(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "CREATE SCHEMA %s [ AUTHORIZATION %s ] [ %s [ ... ] ]\n" + "CREATE SCHEMA AUTHORIZATION %s [ %s [ ... ] ]\n" + "CREATE SCHEMA IF NOT EXISTS %s [ AUTHORIZATION %s ]\n" + "CREATE SCHEMA IF NOT EXISTS AUTHORIZATION %s\n" + "\n" + "%s\n" + "\n" + " [ GROUP ] %s\n" + " | CURRENT_USER\n" + " | SESSION_USER", + _("schema_name"), + _("role_specification"), + _("schema_element"), + _("role_specification"), + _("schema_element"), + _("schema_name"), + _("role_specification"), + _("role_specification"), + _("where role_specification can be:"), + _("user_name")); +} + +void +sql_help_CREATE_SEQUENCE(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "CREATE [ TEMPORARY | TEMP ] SEQUENCE [ IF NOT EXISTS ] %s [ INCREMENT [ BY ] %s ]\n" + " [ MINVALUE %s | NO MINVALUE ] [ MAXVALUE %s | NO MAXVALUE ]\n" + " [ START [ WITH ] %s ] [ CACHE %s ] [ [ NO ] CYCLE ]\n" + " [ OWNED BY { %s.%s | NONE } ]", + _("name"), + _("increment"), + _("minvalue"), + _("maxvalue"), + _("start"), + _("cache"), + _("table_name"), + _("column_name")); +} + +void +sql_help_CREATE_SERVER(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "CREATE SERVER %s [ TYPE '%s' ] [ VERSION '%s' ]\n" + " FOREIGN DATA WRAPPER %s\n" + " [ OPTIONS ( %s '%s' [, ... ] ) ]", + _("server_name"), + _("server_type"), + _("server_version"), + _("fdw_name"), + _("option"), + _("value")); +} + +void +sql_help_CREATE_TABLE(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } | UNLOGGED ] TABLE [ IF NOT EXISTS ] %s ( [\n" + " { %s %s [ COLLATE %s ] [ %s [ ... ] ]\n" + " | %s\n" + " | LIKE %s [ %s ... ] }\n" + " [, ... ]\n" + "] )\n" + "[ INHERITS ( %s [, ... ] ) ]\n" + "[ WITH ( %s [= %s] [, ... ] ) | WITH OIDS | WITHOUT OIDS ]\n" + "[ ON COMMIT { PRESERVE ROWS | DELETE ROWS | DROP } ]\n" + "[ TABLESPACE %s ]\n" + "\n" + "CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } | UNLOGGED ] TABLE [ IF NOT EXISTS ] %s\n" + " OF %s [ (\n" + " { %s WITH OPTIONS [ %s [ ... ] ]\n" + " | %s }\n" + " [, ... ]\n" + ") ]\n" + "[ WITH ( %s [= %s] [, ... ] ) | WITH OIDS | WITHOUT OIDS ]\n" + "[ ON COMMIT { PRESERVE ROWS | DELETE ROWS | DROP } ]\n" + "[ TABLESPACE %s ]\n" + "\n" + "%s\n" + "\n" + "[ CONSTRAINT %s ]\n" + "{ NOT NULL |\n" + " NULL |\n" + " CHECK ( %s ) [ NO INHERIT ] |\n" + " DEFAULT %s |\n" + " UNIQUE %s |\n" + " PRIMARY KEY %s |\n" + " REFERENCES %s [ ( %s ) ] [ MATCH FULL | MATCH PARTIAL | MATCH SIMPLE ]\n" + " [ ON DELETE %s ] [ ON UPDATE %s ] }\n" + "[ DEFERRABLE | NOT DEFERRABLE ] [ INITIALLY DEFERRED | INITIALLY IMMEDIATE ]\n" + "\n" + "%s\n" + "\n" + "[ CONSTRAINT %s ]\n" + "{ CHECK ( %s ) [ NO INHERIT ] |\n" + " UNIQUE ( %s [, ... ] ) %s |\n" + " PRIMARY KEY ( %s [, ... ] ) %s |\n" + " EXCLUDE [ USING %s ] ( %s WITH %s [, ... ] ) %s [ WHERE ( %s ) ] |\n" + " FOREIGN KEY ( %s [, ... ] ) REFERENCES %s [ ( %s [, ... ] ) ]\n" + " [ MATCH FULL | MATCH PARTIAL | MATCH SIMPLE ] [ ON DELETE %s ] [ ON UPDATE %s ] }\n" + "[ DEFERRABLE | NOT DEFERRABLE ] [ INITIALLY DEFERRED | INITIALLY IMMEDIATE ]\n" + "\n" + "%s\n" + "\n" + "{ INCLUDING | EXCLUDING } { DEFAULTS | CONSTRAINTS | INDEXES | STORAGE | COMMENTS | ALL }\n" + "\n" + "%s\n" + "\n" + "[ WITH ( %s [= %s] [, ... ] ) ]\n" + "[ USING INDEX TABLESPACE %s ]\n" + "\n" + "%s\n" + "\n" + "{ %s | ( %s ) } [ %s ] [ ASC | DESC ] [ NULLS { FIRST | LAST } ]", + _("table_name"), + _("column_name"), + _("data_type"), + _("collation"), + _("column_constraint"), + _("table_constraint"), + _("source_table"), + _("like_option"), + _("parent_table"), + _("storage_parameter"), + _("value"), + _("tablespace_name"), + _("table_name"), + _("type_name"), + _("column_name"), + _("column_constraint"), + _("table_constraint"), + _("storage_parameter"), + _("value"), + _("tablespace_name"), + _("where column_constraint is:"), + _("constraint_name"), + _("expression"), + _("default_expr"), + _("index_parameters"), + _("index_parameters"), + _("reftable"), + _("refcolumn"), + _("action"), + _("action"), + _("and table_constraint is:"), + _("constraint_name"), + _("expression"), + _("column_name"), + _("index_parameters"), + _("column_name"), + _("index_parameters"), + _("index_method"), + _("exclude_element"), + _("operator"), + _("index_parameters"), + _("predicate"), + _("column_name"), + _("reftable"), + _("refcolumn"), + _("action"), + _("action"), + _("and like_option is:"), + _("index_parameters in UNIQUE, PRIMARY KEY, and EXCLUDE constraints are:"), + _("storage_parameter"), + _("value"), + _("tablespace_name"), + _("exclude_element in an EXCLUDE constraint is:"), + _("column_name"), + _("expression"), + _("opclass")); +} + +void +sql_help_CREATE_TABLE_AS(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } | UNLOGGED ] TABLE [ IF NOT EXISTS ] %s\n" + " [ (%s [, ...] ) ]\n" + " [ WITH ( %s [= %s] [, ... ] ) | WITH OIDS | WITHOUT OIDS ]\n" + " [ ON COMMIT { PRESERVE ROWS | DELETE ROWS | DROP } ]\n" + " [ TABLESPACE %s ]\n" + " AS %s\n" + " [ WITH [ NO ] DATA ]", + _("table_name"), + _("column_name"), + _("storage_parameter"), + _("value"), + _("tablespace_name"), + _("query")); +} + +void +sql_help_CREATE_TABLESPACE(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "CREATE TABLESPACE %s\n" + " [ OWNER { %s | CURRENT_USER | SESSION_USER } ]\n" + " LOCATION '%s'\n" + " [ WITH ( %s = %s [, ... ] ) ]", + _("tablespace_name"), + _("new_owner"), + _("directory"), + _("tablespace_option"), + _("value")); +} + +void +sql_help_CREATE_TEXT_SEARCH_CONFIGURATION(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "CREATE TEXT SEARCH CONFIGURATION %s (\n" + " PARSER = %s |\n" + " COPY = %s\n" + ")", + _("name"), + _("parser_name"), + _("source_config")); +} + +void +sql_help_CREATE_TEXT_SEARCH_DICTIONARY(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "CREATE TEXT SEARCH DICTIONARY %s (\n" + " TEMPLATE = %s\n" + " [, %s = %s [, ... ]]\n" + ")", + _("name"), + _("template"), + _("option"), + _("value")); +} + +void +sql_help_CREATE_TEXT_SEARCH_PARSER(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "CREATE TEXT SEARCH PARSER %s (\n" + " START = %s ,\n" + " GETTOKEN = %s ,\n" + " END = %s ,\n" + " LEXTYPES = %s\n" + " [, HEADLINE = %s ]\n" + ")", + _("name"), + _("start_function"), + _("gettoken_function"), + _("end_function"), + _("lextypes_function"), + _("headline_function")); +} + +void +sql_help_CREATE_TEXT_SEARCH_TEMPLATE(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "CREATE TEXT SEARCH TEMPLATE %s (\n" + " [ INIT = %s , ]\n" + " LEXIZE = %s\n" + ")", + _("name"), + _("init_function"), + _("lexize_function")); +} + +void +sql_help_CREATE_TRANSFORM(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "CREATE [ OR REPLACE ] TRANSFORM FOR %s LANGUAGE %s (\n" + " FROM SQL WITH FUNCTION %s (%s [, ...]),\n" + " TO SQL WITH FUNCTION %s (%s [, ...])\n" + ");", + _("type_name"), + _("lang_name"), + _("from_sql_function_name"), + _("argument_type"), + _("to_sql_function_name"), + _("argument_type")); +} + +void +sql_help_CREATE_TRIGGER(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "CREATE [ CONSTRAINT ] TRIGGER %s { BEFORE | AFTER | INSTEAD OF } { %s [ OR ... ] }\n" + " ON %s\n" + " [ FROM %s ]\n" + " [ NOT DEFERRABLE | [ DEFERRABLE ] [ INITIALLY IMMEDIATE | INITIALLY DEFERRED ] ]\n" + " [ FOR [ EACH ] { ROW | STATEMENT } ]\n" + " [ WHEN ( %s ) ]\n" + " EXECUTE PROCEDURE %s ( %s )\n" + "\n" + "%s\n" + "\n" + " INSERT\n" + " UPDATE [ OF %s [, ... ] ]\n" + " DELETE\n" + " TRUNCATE", + _("name"), + _("event"), + _("table_name"), + _("referenced_table_name"), + _("condition"), + _("function_name"), + _("arguments"), + _("where event can be one of:"), + _("column_name")); +} + +void +sql_help_CREATE_TYPE(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "CREATE TYPE %s AS\n" + " ( [ %s %s [ COLLATE %s ] [, ... ] ] )\n" + "\n" + "CREATE TYPE %s AS ENUM\n" + " ( [ '%s' [, ... ] ] )\n" + "\n" + "CREATE TYPE %s AS RANGE (\n" + " SUBTYPE = %s\n" + " [ , SUBTYPE_OPCLASS = %s ]\n" + " [ , COLLATION = %s ]\n" + " [ , CANONICAL = %s ]\n" + " [ , SUBTYPE_DIFF = %s ]\n" + ")\n" + "\n" + "CREATE TYPE %s (\n" + " INPUT = %s,\n" + " OUTPUT = %s\n" + " [ , RECEIVE = %s ]\n" + " [ , SEND = %s ]\n" + " [ , TYPMOD_IN = %s ]\n" + " [ , TYPMOD_OUT = %s ]\n" + " [ , ANALYZE = %s ]\n" + " [ , INTERNALLENGTH = { %s | VARIABLE } ]\n" + " [ , PASSEDBYVALUE ]\n" + " [ , ALIGNMENT = %s ]\n" + " [ , STORAGE = %s ]\n" + " [ , LIKE = %s ]\n" + " [ , CATEGORY = %s ]\n" + " [ , PREFERRED = %s ]\n" + " [ , DEFAULT = %s ]\n" + " [ , ELEMENT = %s ]\n" + " [ , DELIMITER = %s ]\n" + " [ , COLLATABLE = %s ]\n" + ")\n" + "\n" + "CREATE TYPE %s", + _("name"), + _("attribute_name"), + _("data_type"), + _("collation"), + _("name"), + _("label"), + _("name"), + _("subtype"), + _("subtype_operator_class"), + _("collation"), + _("canonical_function"), + _("subtype_diff_function"), + _("name"), + _("input_function"), + _("output_function"), + _("receive_function"), + _("send_function"), + _("type_modifier_input_function"), + _("type_modifier_output_function"), + _("analyze_function"), + _("internallength"), + _("alignment"), + _("storage"), + _("like_type"), + _("category"), + _("preferred"), + _("default"), + _("element"), + _("delimiter"), + _("collatable"), + _("name")); +} + +void +sql_help_CREATE_USER(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "CREATE USER %s [ [ WITH ] %s [ ... ] ]\n" + "\n" + "%s\n" + "\n" + " SUPERUSER | NOSUPERUSER\n" + " | CREATEDB | NOCREATEDB\n" + " | CREATEROLE | NOCREATEROLE\n" + " | CREATEUSER | NOCREATEUSER\n" + " | INHERIT | NOINHERIT\n" + " | LOGIN | NOLOGIN\n" + " | REPLICATION | NOREPLICATION\n" + " | CONNECTION LIMIT %s\n" + " | [ ENCRYPTED | UNENCRYPTED ] PASSWORD '%s'\n" + " | VALID UNTIL '%s'\n" + " | IN ROLE %s [, ...]\n" + " | IN GROUP %s [, ...]\n" + " | ROLE %s [, ...]\n" + " | ADMIN %s [, ...]\n" + " | USER %s [, ...]\n" + " | SYSID %s", + _("name"), + _("option"), + _("where option can be:"), + _("connlimit"), + _("password"), + _("timestamp"), + _("role_name"), + _("role_name"), + _("role_name"), + _("role_name"), + _("role_name"), + _("uid")); +} + +void +sql_help_CREATE_USER_MAPPING(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "CREATE USER MAPPING FOR { %s | USER | CURRENT_USER | PUBLIC }\n" + " SERVER %s\n" + " [ OPTIONS ( %s '%s' [ , ... ] ) ]", + _("user_name"), + _("server_name"), + _("option"), + _("value")); +} + +void +sql_help_CREATE_VIEW(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "CREATE [ OR REPLACE ] [ TEMP | TEMPORARY ] [ RECURSIVE ] VIEW %s [ ( %s [, ...] ) ]\n" + " [ WITH ( %s [= %s] [, ... ] ) ]\n" + " AS %s\n" + " [ WITH [ CASCADED | LOCAL ] CHECK OPTION ]", + _("name"), + _("column_name"), + _("view_option_name"), + _("view_option_value"), + _("query")); +} + +void +sql_help_DEALLOCATE(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "DEALLOCATE [ PREPARE ] { %s | ALL }", + _("name")); +} + +void +sql_help_DECLARE(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "DECLARE %s [ BINARY ] [ INSENSITIVE ] [ [ NO ] SCROLL ]\n" + " CURSOR [ { WITH | WITHOUT } HOLD ] FOR %s", + _("name"), + _("query")); +} + +void +sql_help_DELETE(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "[ WITH [ RECURSIVE ] %s [, ...] ]\n" + "DELETE FROM [ ONLY ] %s [ * ] [ [ AS ] %s ]\n" + " [ USING %s ]\n" + " [ WHERE %s | WHERE CURRENT OF %s ]\n" + " [ RETURNING * | %s [ [ AS ] %s ] [, ...] ]", + _("with_query"), + _("table_name"), + _("alias"), + _("using_list"), + _("condition"), + _("cursor_name"), + _("output_expression"), + _("output_name")); +} + +void +sql_help_DISCARD(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "DISCARD { ALL | PLANS | SEQUENCES | TEMPORARY | TEMP }"); +} + +void +sql_help_DO(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "DO [ LANGUAGE %s ] %s", + _("lang_name"), + _("code")); +} + +void +sql_help_DROP_AGGREGATE(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "DROP AGGREGATE [ IF EXISTS ] %s ( %s ) [ CASCADE | RESTRICT ]\n" + "\n" + "%s\n" + "\n" + "* |\n" + "[ %s ] [ %s ] %s [ , ... ] |\n" + "[ [ %s ] [ %s ] %s [ , ... ] ] ORDER BY [ %s ] [ %s ] %s [ , ... ]", + _("name"), + _("aggregate_signature"), + _("where aggregate_signature is:"), + _("argmode"), + _("argname"), + _("argtype"), + _("argmode"), + _("argname"), + _("argtype"), + _("argmode"), + _("argname"), + _("argtype")); +} + +void +sql_help_DROP_CAST(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "DROP CAST [ IF EXISTS ] (%s AS %s) [ CASCADE | RESTRICT ]", + _("source_type"), + _("target_type")); +} + +void +sql_help_DROP_COLLATION(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "DROP COLLATION [ IF EXISTS ] %s [ CASCADE | RESTRICT ]", + _("name")); +} + +void +sql_help_DROP_CONVERSION(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "DROP CONVERSION [ IF EXISTS ] %s [ CASCADE | RESTRICT ]", + _("name")); +} + +void +sql_help_DROP_DATABASE(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "DROP DATABASE [ IF EXISTS ] %s", + _("name")); +} + +void +sql_help_DROP_DOMAIN(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "DROP DOMAIN [ IF EXISTS ] %s [, ...] [ CASCADE | RESTRICT ]", + _("name")); +} + +void +sql_help_DROP_EVENT_TRIGGER(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "DROP EVENT TRIGGER [ IF EXISTS ] %s [ CASCADE | RESTRICT ]", + _("name")); +} + +void +sql_help_DROP_EXTENSION(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "DROP EXTENSION [ IF EXISTS ] %s [, ...] [ CASCADE | RESTRICT ]", + _("name")); +} + +void +sql_help_DROP_FOREIGN_DATA_WRAPPER(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "DROP FOREIGN DATA WRAPPER [ IF EXISTS ] %s [ CASCADE | RESTRICT ]", + _("name")); +} + +void +sql_help_DROP_FOREIGN_TABLE(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "DROP FOREIGN TABLE [ IF EXISTS ] %s [, ...] [ CASCADE | RESTRICT ]", + _("name")); +} + +void +sql_help_DROP_FUNCTION(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "DROP FUNCTION [ IF EXISTS ] %s ( [ [ %s ] [ %s ] %s [, ...] ] )\n" + " [ CASCADE | RESTRICT ]", + _("name"), + _("argmode"), + _("argname"), + _("argtype")); +} + +void +sql_help_DROP_GROUP(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "DROP GROUP [ IF EXISTS ] %s [, ...]", + _("name")); +} + +void +sql_help_DROP_INDEX(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "DROP INDEX [ CONCURRENTLY ] [ IF EXISTS ] %s [, ...] [ CASCADE | RESTRICT ]", + _("name")); +} + +void +sql_help_DROP_LANGUAGE(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "DROP [ PROCEDURAL ] LANGUAGE [ IF EXISTS ] %s [ CASCADE | RESTRICT ]", + _("name")); +} + +void +sql_help_DROP_MATERIALIZED_VIEW(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "DROP MATERIALIZED VIEW [ IF EXISTS ] %s [, ...] [ CASCADE | RESTRICT ]", + _("name")); +} + +void +sql_help_DROP_OPERATOR(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "DROP OPERATOR [ IF EXISTS ] %s ( { %s | NONE } , { %s | NONE } ) [ CASCADE | RESTRICT ]", + _("name"), + _("left_type"), + _("right_type")); +} + +void +sql_help_DROP_OPERATOR_CLASS(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "DROP OPERATOR CLASS [ IF EXISTS ] %s USING %s [ CASCADE | RESTRICT ]", + _("name"), + _("index_method")); +} + +void +sql_help_DROP_OPERATOR_FAMILY(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "DROP OPERATOR FAMILY [ IF EXISTS ] %s USING %s [ CASCADE | RESTRICT ]", + _("name"), + _("index_method")); +} + +void +sql_help_DROP_OWNED(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "DROP OWNED BY { %s | CURRENT_USER | SESSION_USER } [, ...] [ CASCADE | RESTRICT ]", + _("name")); +} + +void +sql_help_DROP_POLICY(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "DROP POLICY [ IF EXISTS ] %s ON %s", + _("name"), + _("table_name")); +} + +void +sql_help_DROP_ROLE(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "DROP ROLE [ IF EXISTS ] %s [, ...]", + _("name")); +} + +void +sql_help_DROP_RULE(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "DROP RULE [ IF EXISTS ] %s ON %s [ CASCADE | RESTRICT ]", + _("name"), + _("table_name")); +} + +void +sql_help_DROP_SCHEMA(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "DROP SCHEMA [ IF EXISTS ] %s [, ...] [ CASCADE | RESTRICT ]", + _("name")); +} + +void +sql_help_DROP_SEQUENCE(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "DROP SEQUENCE [ IF EXISTS ] %s [, ...] [ CASCADE | RESTRICT ]", + _("name")); +} + +void +sql_help_DROP_SERVER(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "DROP SERVER [ IF EXISTS ] %s [ CASCADE | RESTRICT ]", + _("name")); +} + +void +sql_help_DROP_TABLE(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "DROP TABLE [ IF EXISTS ] %s [, ...] [ CASCADE | RESTRICT ]", + _("name")); +} + +void +sql_help_DROP_TABLESPACE(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "DROP TABLESPACE [ IF EXISTS ] %s", + _("name")); +} + +void +sql_help_DROP_TEXT_SEARCH_CONFIGURATION(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "DROP TEXT SEARCH CONFIGURATION [ IF EXISTS ] %s [ CASCADE | RESTRICT ]", + _("name")); +} + +void +sql_help_DROP_TEXT_SEARCH_DICTIONARY(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "DROP TEXT SEARCH DICTIONARY [ IF EXISTS ] %s [ CASCADE | RESTRICT ]", + _("name")); +} + +void +sql_help_DROP_TEXT_SEARCH_PARSER(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "DROP TEXT SEARCH PARSER [ IF EXISTS ] %s [ CASCADE | RESTRICT ]", + _("name")); +} + +void +sql_help_DROP_TEXT_SEARCH_TEMPLATE(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "DROP TEXT SEARCH TEMPLATE [ IF EXISTS ] %s [ CASCADE | RESTRICT ]", + _("name")); +} + +void +sql_help_DROP_TRANSFORM(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "DROP TRANSFORM [ IF EXISTS ] FOR %s LANGUAGE %s", + _("type_name"), + _("lang_name")); +} + +void +sql_help_DROP_TRIGGER(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "DROP TRIGGER [ IF EXISTS ] %s ON %s [ CASCADE | RESTRICT ]", + _("name"), + _("table_name")); +} + +void +sql_help_DROP_TYPE(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "DROP TYPE [ IF EXISTS ] %s [, ...] [ CASCADE | RESTRICT ]", + _("name")); +} + +void +sql_help_DROP_USER(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "DROP USER [ IF EXISTS ] %s [, ...]", + _("name")); +} + +void +sql_help_DROP_USER_MAPPING(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "DROP USER MAPPING [ IF EXISTS ] FOR { %s | USER | CURRENT_USER | PUBLIC } SERVER %s", + _("user_name"), + _("server_name")); +} + +void +sql_help_DROP_VIEW(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "DROP VIEW [ IF EXISTS ] %s [, ...] [ CASCADE | RESTRICT ]", + _("name")); +} + +void +sql_help_END(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "END [ WORK | TRANSACTION ]"); +} + +void +sql_help_EXECUTE(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "EXECUTE %s [ ( %s [, ...] ) ]", + _("name"), + _("parameter")); +} + +void +sql_help_EXPLAIN(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "EXPLAIN [ ( %s [, ...] ) ] %s\n" + "EXPLAIN [ ANALYZE ] [ VERBOSE ] %s\n" + "\n" + "%s\n" + "\n" + " ANALYZE [ %s ]\n" + " VERBOSE [ %s ]\n" + " COSTS [ %s ]\n" + " BUFFERS [ %s ]\n" + " TIMING [ %s ]\n" + " FORMAT { TEXT | XML | JSON | YAML }", + _("option"), + _("statement"), + _("statement"), + _("where option can be one of:"), + _("boolean"), + _("boolean"), + _("boolean"), + _("boolean"), + _("boolean")); +} + +void +sql_help_FETCH(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "FETCH [ %s [ FROM | IN ] ] %s\n" + "\n" + "%s\n" + "\n" + " NEXT\n" + " PRIOR\n" + " FIRST\n" + " LAST\n" + " ABSOLUTE %s\n" + " RELATIVE %s\n" + " %s\n" + " ALL\n" + " FORWARD\n" + " FORWARD %s\n" + " FORWARD ALL\n" + " BACKWARD\n" + " BACKWARD %s\n" + " BACKWARD ALL", + _("direction"), + _("cursor_name"), + _("where direction can be empty or one of:"), + _("count"), + _("count"), + _("count"), + _("count"), + _("count")); +} + +void +sql_help_GRANT(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "GRANT { { SELECT | INSERT | UPDATE | DELETE | TRUNCATE | REFERENCES | TRIGGER }\n" + " [, ...] | ALL [ PRIVILEGES ] }\n" + " ON { [ TABLE ] %s [, ...]\n" + " | ALL TABLES IN SCHEMA %s [, ...] }\n" + " TO %s [, ...] [ WITH GRANT OPTION ]\n" + "\n" + "GRANT { { SELECT | INSERT | UPDATE | REFERENCES } ( %s [, ...] )\n" + " [, ...] | ALL [ PRIVILEGES ] ( %s [, ...] ) }\n" + " ON [ TABLE ] %s [, ...]\n" + " TO %s [, ...] [ WITH GRANT OPTION ]\n" + "\n" + "GRANT { { USAGE | SELECT | UPDATE }\n" + " [, ...] | ALL [ PRIVILEGES ] }\n" + " ON { SEQUENCE %s [, ...]\n" + " | ALL SEQUENCES IN SCHEMA %s [, ...] }\n" + " TO %s [, ...] [ WITH GRANT OPTION ]\n" + "\n" + "GRANT { { CREATE | CONNECT | TEMPORARY | TEMP } [, ...] | ALL [ PRIVILEGES ] }\n" + " ON DATABASE %s [, ...]\n" + " TO %s [, ...] [ WITH GRANT OPTION ]\n" + "\n" + "GRANT { USAGE | ALL [ PRIVILEGES ] }\n" + " ON DOMAIN %s [, ...]\n" + " TO %s [, ...] [ WITH GRANT OPTION ]\n" + "\n" + "GRANT { USAGE | ALL [ PRIVILEGES ] }\n" + " ON FOREIGN DATA WRAPPER %s [, ...]\n" + " TO %s [, ...] [ WITH GRANT OPTION ]\n" + "\n" + "GRANT { USAGE | ALL [ PRIVILEGES ] }\n" + " ON FOREIGN SERVER %s [, ...]\n" + " TO %s [, ...] [ WITH GRANT OPTION ]\n" + "\n" + "GRANT { EXECUTE | ALL [ PRIVILEGES ] }\n" + " ON { FUNCTION %s ( [ [ %s ] [ %s ] %s [, ...] ] ) [, ...]\n" + " | ALL FUNCTIONS IN SCHEMA %s [, ...] }\n" + " TO %s [, ...] [ WITH GRANT OPTION ]\n" + "\n" + "GRANT { USAGE | ALL [ PRIVILEGES ] }\n" + " ON LANGUAGE %s [, ...]\n" + " TO %s [, ...] [ WITH GRANT OPTION ]\n" + "\n" + "GRANT { { SELECT | UPDATE } [, ...] | ALL [ PRIVILEGES ] }\n" + " ON LARGE OBJECT %s [, ...]\n" + " TO %s [, ...] [ WITH GRANT OPTION ]\n" + "\n" + "GRANT { { CREATE | USAGE } [, ...] | ALL [ PRIVILEGES ] }\n" + " ON SCHEMA %s [, ...]\n" + " TO %s [, ...] [ WITH GRANT OPTION ]\n" + "\n" + "GRANT { CREATE | ALL [ PRIVILEGES ] }\n" + " ON TABLESPACE %s [, ...]\n" + " TO %s [, ...] [ WITH GRANT OPTION ]\n" + "\n" + "GRANT { USAGE | ALL [ PRIVILEGES ] }\n" + " ON TYPE %s [, ...]\n" + " TO %s [, ...] [ WITH GRANT OPTION ]\n" + "\n" + "%s\n" + "\n" + " [ GROUP ] %s\n" + " | PUBLIC\n" + " | CURRENT_USER\n" + " | SESSION_USER\n" + "\n" + "GRANT %s [, ...] TO %s [, ...] [ WITH ADMIN OPTION ]", + _("table_name"), + _("schema_name"), + _("role_specification"), + _("column_name"), + _("column_name"), + _("table_name"), + _("role_specification"), + _("sequence_name"), + _("schema_name"), + _("role_specification"), + _("database_name"), + _("role_specification"), + _("domain_name"), + _("role_specification"), + _("fdw_name"), + _("role_specification"), + _("server_name"), + _("role_specification"), + _("function_name"), + _("argmode"), + _("arg_name"), + _("arg_type"), + _("schema_name"), + _("role_specification"), + _("lang_name"), + _("role_specification"), + _("loid"), + _("role_specification"), + _("schema_name"), + _("role_specification"), + _("tablespace_name"), + _("role_specification"), + _("type_name"), + _("role_specification"), + _("where role_specification can be:"), + _("role_name"), + _("role_name"), + _("role_name")); +} + +void +sql_help_IMPORT_FOREIGN_SCHEMA(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "IMPORT FOREIGN SCHEMA %s\n" + " [ { LIMIT TO | EXCEPT } ( %s [, ...] ) ]\n" + " FROM SERVER %s\n" + " INTO %s\n" + " [ OPTIONS ( %s '%s' [, ... ] ) ]", + _("remote_schema"), + _("table_name"), + _("server_name"), + _("local_schema"), + _("option"), + _("value")); +} + +void +sql_help_INSERT(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "[ WITH [ RECURSIVE ] %s [, ...] ]\n" + "INSERT INTO %s [ AS %s ] [ ( %s [, ...] ) ]\n" + " { DEFAULT VALUES | VALUES ( { %s | DEFAULT } [, ...] ) [, ...] | %s }\n" + " [ ON CONFLICT [ %s ] %s ]\n" + " [ RETURNING * | %s [ [ AS ] %s ] [, ...] ]\n" + "\n" + "%s\n" + "\n" + " ( { %s | ( %s ) } [ COLLATE %s ] [ %s ] [, ...] ) [ WHERE %s ]\n" + " ON CONSTRAINT %s\n" + "\n" + "%s\n" + "\n" + " DO NOTHING\n" + " DO UPDATE SET { %s = { %s | DEFAULT } |\n" + " ( %s [, ...] ) = ( { %s | DEFAULT } [, ...] ) |\n" + " ( %s [, ...] ) = ( %s )\n" + " } [, ...]\n" + " [ WHERE %s ]", + _("with_query"), + _("table_name"), + _("alias"), + _("column_name"), + _("expression"), + _("query"), + _("conflict_target"), + _("conflict_action"), + _("output_expression"), + _("output_name"), + _("where conflict_target can be one of:"), + _("index_column_name"), + _("index_expression"), + _("collation"), + _("opclass"), + _("index_predicate"), + _("constraint_name"), + _("and conflict_action is one of:"), + _("column_name"), + _("expression"), + _("column_name"), + _("expression"), + _("column_name"), + _("sub-SELECT"), + _("condition")); +} + +void +sql_help_LISTEN(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "LISTEN %s", + _("channel")); +} + +void +sql_help_LOAD(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "LOAD '%s'", + _("filename")); +} + +void +sql_help_LOCK(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "LOCK [ TABLE ] [ ONLY ] %s [ * ] [, ...] [ IN %s MODE ] [ NOWAIT ]\n" + "\n" + "%s\n" + "\n" + " ACCESS SHARE | ROW SHARE | ROW EXCLUSIVE | SHARE UPDATE EXCLUSIVE\n" + " | SHARE | SHARE ROW EXCLUSIVE | EXCLUSIVE | ACCESS EXCLUSIVE", + _("name"), + _("lockmode"), + _("where lockmode is one of:")); +} + +void +sql_help_MOVE(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "MOVE [ %s [ FROM | IN ] ] %s\n" + "\n" + "%s\n" + "\n" + " NEXT\n" + " PRIOR\n" + " FIRST\n" + " LAST\n" + " ABSOLUTE %s\n" + " RELATIVE %s\n" + " %s\n" + " ALL\n" + " FORWARD\n" + " FORWARD %s\n" + " FORWARD ALL\n" + " BACKWARD\n" + " BACKWARD %s\n" + " BACKWARD ALL", + _("direction"), + _("cursor_name"), + _("where direction can be empty or one of:"), + _("count"), + _("count"), + _("count"), + _("count"), + _("count")); +} + +void +sql_help_NOTIFY(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "NOTIFY %s [ , %s ]", + _("channel"), + _("payload")); +} + +void +sql_help_PREPARE(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "PREPARE %s [ ( %s [, ...] ) ] AS %s", + _("name"), + _("data_type"), + _("statement")); +} + +void +sql_help_PREPARE_TRANSACTION(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "PREPARE TRANSACTION %s", + _("transaction_id")); +} + +void +sql_help_REASSIGN_OWNED(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "REASSIGN OWNED BY { %s | CURRENT_USER | SESSION_USER } [, ...]\n" + " TO { %s | CURRENT_USER | SESSION_USER }", + _("old_role"), + _("new_role")); +} + +void +sql_help_REFRESH_MATERIALIZED_VIEW(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "REFRESH MATERIALIZED VIEW [ CONCURRENTLY ] %s\n" + " [ WITH [ NO ] DATA ]", + _("name")); +} + +void +sql_help_REINDEX(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "REINDEX [ ( { VERBOSE } [, ...] ) ] { INDEX | TABLE | SCHEMA | DATABASE | SYSTEM } %s", + _("name")); +} + +void +sql_help_RELEASE_SAVEPOINT(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "RELEASE [ SAVEPOINT ] %s", + _("savepoint_name")); +} + +void +sql_help_RESET(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "RESET %s\n" + "RESET ALL", + _("configuration_parameter")); +} + +void +sql_help_REVOKE(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "REVOKE [ GRANT OPTION FOR ]\n" + " { { SELECT | INSERT | UPDATE | DELETE | TRUNCATE | REFERENCES | TRIGGER }\n" + " [, ...] | ALL [ PRIVILEGES ] }\n" + " ON { [ TABLE ] %s [, ...]\n" + " | ALL TABLES IN SCHEMA %s [, ...] }\n" + " FROM { [ GROUP ] %s | PUBLIC } [, ...]\n" + " [ CASCADE | RESTRICT ]\n" + "\n" + "REVOKE [ GRANT OPTION FOR ]\n" + " { { SELECT | INSERT | UPDATE | REFERENCES } ( %s [, ...] )\n" + " [, ...] | ALL [ PRIVILEGES ] ( %s [, ...] ) }\n" + " ON [ TABLE ] %s [, ...]\n" + " FROM { [ GROUP ] %s | PUBLIC } [, ...]\n" + " [ CASCADE | RESTRICT ]\n" + "\n" + "REVOKE [ GRANT OPTION FOR ]\n" + " { { USAGE | SELECT | UPDATE }\n" + " [, ...] | ALL [ PRIVILEGES ] }\n" + " ON { SEQUENCE %s [, ...]\n" + " | ALL SEQUENCES IN SCHEMA %s [, ...] }\n" + " FROM { [ GROUP ] %s | PUBLIC } [, ...]\n" + " [ CASCADE | RESTRICT ]\n" + "\n" + "REVOKE [ GRANT OPTION FOR ]\n" + " { { CREATE | CONNECT | TEMPORARY | TEMP } [, ...] | ALL [ PRIVILEGES ] }\n" + " ON DATABASE %s [, ...]\n" + " FROM { [ GROUP ] %s | PUBLIC } [, ...]\n" + " [ CASCADE | RESTRICT ]\n" + "\n" + "REVOKE [ GRANT OPTION FOR ]\n" + " { USAGE | ALL [ PRIVILEGES ] }\n" + " ON DOMAIN %s [, ...]\n" + " FROM { [ GROUP ] %s | PUBLIC } [, ...]\n" + " [ CASCADE | RESTRICT ]\n" + "\n" + "REVOKE [ GRANT OPTION FOR ]\n" + " { USAGE | ALL [ PRIVILEGES ] }\n" + " ON FOREIGN DATA WRAPPER %s [, ...]\n" + " FROM { [ GROUP ] %s | PUBLIC } [, ...]\n" + " [ CASCADE | RESTRICT ]\n" + "\n" + "REVOKE [ GRANT OPTION FOR ]\n" + " { USAGE | ALL [ PRIVILEGES ] }\n" + " ON FOREIGN SERVER %s [, ...]\n" + " FROM { [ GROUP ] %s | PUBLIC } [, ...]\n" + " [ CASCADE | RESTRICT ]\n" + "\n" + "REVOKE [ GRANT OPTION FOR ]\n" + " { EXECUTE | ALL [ PRIVILEGES ] }\n" + " ON { FUNCTION %s ( [ [ %s ] [ %s ] %s [, ...] ] ) [, ...]\n" + " | ALL FUNCTIONS IN SCHEMA %s [, ...] }\n" + " FROM { [ GROUP ] %s | PUBLIC } [, ...]\n" + " [ CASCADE | RESTRICT ]\n" + "\n" + "REVOKE [ GRANT OPTION FOR ]\n" + " { USAGE | ALL [ PRIVILEGES ] }\n" + " ON LANGUAGE %s [, ...]\n" + " FROM { [ GROUP ] %s | PUBLIC } [, ...]\n" + " [ CASCADE | RESTRICT ]\n" + "\n" + "REVOKE [ GRANT OPTION FOR ]\n" + " { { SELECT | UPDATE } [, ...] | ALL [ PRIVILEGES ] }\n" + " ON LARGE OBJECT %s [, ...]\n" + " FROM { [ GROUP ] %s | PUBLIC } [, ...]\n" + " [ CASCADE | RESTRICT ]\n" + "\n" + "REVOKE [ GRANT OPTION FOR ]\n" + " { { CREATE | USAGE } [, ...] | ALL [ PRIVILEGES ] }\n" + " ON SCHEMA %s [, ...]\n" + " FROM { [ GROUP ] %s | PUBLIC } [, ...]\n" + " [ CASCADE | RESTRICT ]\n" + "\n" + "REVOKE [ GRANT OPTION FOR ]\n" + " { CREATE | ALL [ PRIVILEGES ] }\n" + " ON TABLESPACE %s [, ...]\n" + " FROM { [ GROUP ] %s | PUBLIC } [, ...]\n" + " [ CASCADE | RESTRICT ]\n" + "\n" + "REVOKE [ GRANT OPTION FOR ]\n" + " { USAGE | ALL [ PRIVILEGES ] }\n" + " ON TYPE %s [, ...]\n" + " FROM { [ GROUP ] %s | PUBLIC } [, ...]\n" + " [ CASCADE | RESTRICT ]\n" + "\n" + "REVOKE [ ADMIN OPTION FOR ]\n" + " %s [, ...] FROM %s [, ...]\n" + " [ CASCADE | RESTRICT ]", + _("table_name"), + _("schema_name"), + _("role_name"), + _("column_name"), + _("column_name"), + _("table_name"), + _("role_name"), + _("sequence_name"), + _("schema_name"), + _("role_name"), + _("database_name"), + _("role_name"), + _("domain_name"), + _("role_name"), + _("fdw_name"), + _("role_name"), + _("server_name"), + _("role_name"), + _("function_name"), + _("argmode"), + _("arg_name"), + _("arg_type"), + _("schema_name"), + _("role_name"), + _("lang_name"), + _("role_name"), + _("loid"), + _("role_name"), + _("schema_name"), + _("role_name"), + _("tablespace_name"), + _("role_name"), + _("type_name"), + _("role_name"), + _("role_name"), + _("role_name")); +} + +void +sql_help_ROLLBACK(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "ROLLBACK [ WORK | TRANSACTION ]"); +} + +void +sql_help_ROLLBACK_PREPARED(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "ROLLBACK PREPARED %s", + _("transaction_id")); +} + +void +sql_help_ROLLBACK_TO_SAVEPOINT(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "ROLLBACK [ WORK | TRANSACTION ] TO [ SAVEPOINT ] %s", + _("savepoint_name")); +} + +void +sql_help_SAVEPOINT(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "SAVEPOINT %s", + _("savepoint_name")); +} + +void +sql_help_SECURITY_LABEL(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "SECURITY LABEL [ FOR %s ] ON\n" + "{\n" + " TABLE %s |\n" + " COLUMN %s.%s |\n" + " AGGREGATE %s ( %s ) |\n" + " DATABASE %s |\n" + " DOMAIN %s |\n" + " EVENT TRIGGER %s |\n" + " FOREIGN TABLE %s\n" + " FUNCTION %s ( [ [ %s ] [ %s ] %s [, ...] ] ) |\n" + " LARGE OBJECT %s |\n" + " MATERIALIZED VIEW %s |\n" + " [ PROCEDURAL ] LANGUAGE %s |\n" + " ROLE %s |\n" + " SCHEMA %s |\n" + " SEQUENCE %s |\n" + " TABLESPACE %s |\n" + " TYPE %s |\n" + " VIEW %s\n" + "} IS '%s'\n" + "\n" + "%s\n" + "\n" + "* |\n" + "[ %s ] [ %s ] %s [ , ... ] |\n" + "[ [ %s ] [ %s ] %s [ , ... ] ] ORDER BY [ %s ] [ %s ] %s [ , ... ]", + _("provider"), + _("object_name"), + _("table_name"), + _("column_name"), + _("aggregate_name"), + _("aggregate_signature"), + _("object_name"), + _("object_name"), + _("object_name"), + _("object_name"), + _("function_name"), + _("argmode"), + _("argname"), + _("argtype"), + _("large_object_oid"), + _("object_name"), + _("object_name"), + _("object_name"), + _("object_name"), + _("object_name"), + _("object_name"), + _("object_name"), + _("object_name"), + _("label"), + _("where aggregate_signature is:"), + _("argmode"), + _("argname"), + _("argtype"), + _("argmode"), + _("argname"), + _("argtype"), + _("argmode"), + _("argname"), + _("argtype")); +} + +void +sql_help_SELECT(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "[ WITH [ RECURSIVE ] %s [, ...] ]\n" + "SELECT [ ALL | DISTINCT [ ON ( %s [, ...] ) ] ]\n" + " [ * | %s [ [ AS ] %s ] [, ...] ]\n" + " [ FROM %s [, ...] ]\n" + " [ WHERE %s ]\n" + " [ GROUP BY %s [, ...] ]\n" + " [ HAVING %s [, ...] ]\n" + " [ WINDOW %s AS ( %s ) [, ...] ]\n" + " [ { UNION | INTERSECT | EXCEPT } [ ALL | DISTINCT ] %s ]\n" + " [ ORDER BY %s [ ASC | DESC | USING %s ] [ NULLS { FIRST | LAST } ] [, ...] ]\n" + " [ LIMIT { %s | ALL } ]\n" + " [ OFFSET %s [ ROW | ROWS ] ]\n" + " [ FETCH { FIRST | NEXT } [ %s ] { ROW | ROWS } ONLY ]\n" + " [ FOR { UPDATE | NO KEY UPDATE | SHARE | KEY SHARE } [ OF %s [, ...] ] [ NOWAIT | SKIP LOCKED ] [...] ]\n" + "\n" + "%s\n" + "\n" + " [ ONLY ] %s [ * ] [ [ AS ] %s [ ( %s [, ...] ) ] ]\n" + " [ TABLESAMPLE %s ( %s [, ...] ) [ REPEATABLE ( %s ) ] ]\n" + " [ LATERAL ] ( %s ) [ AS ] %s [ ( %s [, ...] ) ]\n" + " %s [ [ AS ] %s [ ( %s [, ...] ) ] ]\n" + " [ LATERAL ] %s ( [ %s [, ...] ] )\n" + " [ WITH ORDINALITY ] [ [ AS ] %s [ ( %s [, ...] ) ] ]\n" + " [ LATERAL ] %s ( [ %s [, ...] ] ) [ AS ] %s ( %s [, ...] )\n" + " [ LATERAL ] %s ( [ %s [, ...] ] ) AS ( %s [, ...] )\n" + " [ LATERAL ] ROWS FROM( %s ( [ %s [, ...] ] ) [ AS ( %s [, ...] ) ] [, ...] )\n" + " [ WITH ORDINALITY ] [ [ AS ] %s [ ( %s [, ...] ) ] ]\n" + " %s [ NATURAL ] %s %s [ ON %s | USING ( %s [, ...] ) ]\n" + "\n" + "%s\n" + "\n" + " ( )\n" + " %s\n" + " ( %s [, ...] )\n" + " ROLLUP ( { %s | ( %s [, ...] ) } [, ...] )\n" + " CUBE ( { %s | ( %s [, ...] ) } [, ...] )\n" + " GROUPING SETS ( %s [, ...] )\n" + "\n" + "%s\n" + "\n" + " %s [ ( %s [, ...] ) ] AS ( %s | %s | %s | %s | %s )\n" + "\n" + "TABLE [ ONLY ] %s [ * ]", + _("with_query"), + _("expression"), + _("expression"), + _("output_name"), + _("from_item"), + _("condition"), + _("grouping_element"), + _("condition"), + _("window_name"), + _("window_definition"), + _("select"), + _("expression"), + _("operator"), + _("count"), + _("start"), + _("count"), + _("table_name"), + _("where from_item can be one of:"), + _("table_name"), + _("alias"), + _("column_alias"), + _("sampling_method"), + _("argument"), + _("seed"), + _("select"), + _("alias"), + _("column_alias"), + _("with_query_name"), + _("alias"), + _("column_alias"), + _("function_name"), + _("argument"), + _("alias"), + _("column_alias"), + _("function_name"), + _("argument"), + _("alias"), + _("column_definition"), + _("function_name"), + _("argument"), + _("column_definition"), + _("function_name"), + _("argument"), + _("column_definition"), + _("alias"), + _("column_alias"), + _("from_item"), + _("join_type"), + _("from_item"), + _("join_condition"), + _("join_column"), + _("and grouping_element can be one of:"), + _("expression"), + _("expression"), + _("expression"), + _("expression"), + _("expression"), + _("expression"), + _("grouping_element"), + _("and with_query is:"), + _("with_query_name"), + _("column_name"), + _("select"), + _("values"), + _("insert"), + _("update"), + _("delete"), + _("table_name")); +} + +void +sql_help_SELECT_INTO(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "[ WITH [ RECURSIVE ] %s [, ...] ]\n" + "SELECT [ ALL | DISTINCT [ ON ( %s [, ...] ) ] ]\n" + " * | %s [ [ AS ] %s ] [, ...]\n" + " INTO [ TEMPORARY | TEMP | UNLOGGED ] [ TABLE ] %s\n" + " [ FROM %s [, ...] ]\n" + " [ WHERE %s ]\n" + " [ GROUP BY %s [, ...] ]\n" + " [ HAVING %s [, ...] ]\n" + " [ WINDOW %s AS ( %s ) [, ...] ]\n" + " [ { UNION | INTERSECT | EXCEPT } [ ALL | DISTINCT ] %s ]\n" + " [ ORDER BY %s [ ASC | DESC | USING %s ] [ NULLS { FIRST | LAST } ] [, ...] ]\n" + " [ LIMIT { %s | ALL } ]\n" + " [ OFFSET %s [ ROW | ROWS ] ]\n" + " [ FETCH { FIRST | NEXT } [ %s ] { ROW | ROWS } ONLY ]\n" + " [ FOR { UPDATE | SHARE } [ OF %s [, ...] ] [ NOWAIT ] [...] ]", + _("with_query"), + _("expression"), + _("expression"), + _("output_name"), + _("new_table"), + _("from_item"), + _("condition"), + _("expression"), + _("condition"), + _("window_name"), + _("window_definition"), + _("select"), + _("expression"), + _("operator"), + _("count"), + _("start"), + _("count"), + _("table_name")); +} + +void +sql_help_SET(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "SET [ SESSION | LOCAL ] %s { TO | = } { %s | '%s' | DEFAULT }\n" + "SET [ SESSION | LOCAL ] TIME ZONE { %s | LOCAL | DEFAULT }", + _("configuration_parameter"), + _("value"), + _("value"), + _("timezone")); +} + +void +sql_help_SET_CONSTRAINTS(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "SET CONSTRAINTS { ALL | %s [, ...] } { DEFERRED | IMMEDIATE }", + _("name")); +} + +void +sql_help_SET_ROLE(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "SET [ SESSION | LOCAL ] ROLE %s\n" + "SET [ SESSION | LOCAL ] ROLE NONE\n" + "RESET ROLE", + _("role_name")); +} + +void +sql_help_SET_SESSION_AUTHORIZATION(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "SET [ SESSION | LOCAL ] SESSION AUTHORIZATION %s\n" + "SET [ SESSION | LOCAL ] SESSION AUTHORIZATION DEFAULT\n" + "RESET SESSION AUTHORIZATION", + _("user_name")); +} + +void +sql_help_SET_TRANSACTION(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "SET TRANSACTION %s [, ...]\n" + "SET TRANSACTION SNAPSHOT %s\n" + "SET SESSION CHARACTERISTICS AS TRANSACTION %s [, ...]\n" + "\n" + "%s\n" + "\n" + " ISOLATION LEVEL { SERIALIZABLE | REPEATABLE READ | READ COMMITTED | READ UNCOMMITTED }\n" + " READ WRITE | READ ONLY\n" + " [ NOT ] DEFERRABLE", + _("transaction_mode"), + _("snapshot_id"), + _("transaction_mode"), + _("where transaction_mode is one of:")); +} + +void +sql_help_SHOW(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "SHOW %s\n" + "SHOW ALL", + _("name")); +} + +void +sql_help_START_TRANSACTION(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "START TRANSACTION [ %s [, ...] ]\n" + "\n" + "%s\n" + "\n" + " ISOLATION LEVEL { SERIALIZABLE | REPEATABLE READ | READ COMMITTED | READ UNCOMMITTED }\n" + " READ WRITE | READ ONLY\n" + " [ NOT ] DEFERRABLE", + _("transaction_mode"), + _("where transaction_mode is one of:")); +} + +void +sql_help_TABLE(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "[ WITH [ RECURSIVE ] %s [, ...] ]\n" + "SELECT [ ALL | DISTINCT [ ON ( %s [, ...] ) ] ]\n" + " [ * | %s [ [ AS ] %s ] [, ...] ]\n" + " [ FROM %s [, ...] ]\n" + " [ WHERE %s ]\n" + " [ GROUP BY %s [, ...] ]\n" + " [ HAVING %s [, ...] ]\n" + " [ WINDOW %s AS ( %s ) [, ...] ]\n" + " [ { UNION | INTERSECT | EXCEPT } [ ALL | DISTINCT ] %s ]\n" + " [ ORDER BY %s [ ASC | DESC | USING %s ] [ NULLS { FIRST | LAST } ] [, ...] ]\n" + " [ LIMIT { %s | ALL } ]\n" + " [ OFFSET %s [ ROW | ROWS ] ]\n" + " [ FETCH { FIRST | NEXT } [ %s ] { ROW | ROWS } ONLY ]\n" + " [ FOR { UPDATE | NO KEY UPDATE | SHARE | KEY SHARE } [ OF %s [, ...] ] [ NOWAIT | SKIP LOCKED ] [...] ]\n" + "\n" + "%s\n" + "\n" + " [ ONLY ] %s [ * ] [ [ AS ] %s [ ( %s [, ...] ) ] ]\n" + " [ TABLESAMPLE %s ( %s [, ...] ) [ REPEATABLE ( %s ) ] ]\n" + " [ LATERAL ] ( %s ) [ AS ] %s [ ( %s [, ...] ) ]\n" + " %s [ [ AS ] %s [ ( %s [, ...] ) ] ]\n" + " [ LATERAL ] %s ( [ %s [, ...] ] )\n" + " [ WITH ORDINALITY ] [ [ AS ] %s [ ( %s [, ...] ) ] ]\n" + " [ LATERAL ] %s ( [ %s [, ...] ] ) [ AS ] %s ( %s [, ...] )\n" + " [ LATERAL ] %s ( [ %s [, ...] ] ) AS ( %s [, ...] )\n" + " [ LATERAL ] ROWS FROM( %s ( [ %s [, ...] ] ) [ AS ( %s [, ...] ) ] [, ...] )\n" + " [ WITH ORDINALITY ] [ [ AS ] %s [ ( %s [, ...] ) ] ]\n" + " %s [ NATURAL ] %s %s [ ON %s | USING ( %s [, ...] ) ]\n" + "\n" + "%s\n" + "\n" + " ( )\n" + " %s\n" + " ( %s [, ...] )\n" + " ROLLUP ( { %s | ( %s [, ...] ) } [, ...] )\n" + " CUBE ( { %s | ( %s [, ...] ) } [, ...] )\n" + " GROUPING SETS ( %s [, ...] )\n" + "\n" + "%s\n" + "\n" + " %s [ ( %s [, ...] ) ] AS ( %s | %s | %s | %s | %s )\n" + "\n" + "TABLE [ ONLY ] %s [ * ]", + _("with_query"), + _("expression"), + _("expression"), + _("output_name"), + _("from_item"), + _("condition"), + _("grouping_element"), + _("condition"), + _("window_name"), + _("window_definition"), + _("select"), + _("expression"), + _("operator"), + _("count"), + _("start"), + _("count"), + _("table_name"), + _("where from_item can be one of:"), + _("table_name"), + _("alias"), + _("column_alias"), + _("sampling_method"), + _("argument"), + _("seed"), + _("select"), + _("alias"), + _("column_alias"), + _("with_query_name"), + _("alias"), + _("column_alias"), + _("function_name"), + _("argument"), + _("alias"), + _("column_alias"), + _("function_name"), + _("argument"), + _("alias"), + _("column_definition"), + _("function_name"), + _("argument"), + _("column_definition"), + _("function_name"), + _("argument"), + _("column_definition"), + _("alias"), + _("column_alias"), + _("from_item"), + _("join_type"), + _("from_item"), + _("join_condition"), + _("join_column"), + _("and grouping_element can be one of:"), + _("expression"), + _("expression"), + _("expression"), + _("expression"), + _("expression"), + _("expression"), + _("grouping_element"), + _("and with_query is:"), + _("with_query_name"), + _("column_name"), + _("select"), + _("values"), + _("insert"), + _("update"), + _("delete"), + _("table_name")); +} + +void +sql_help_TRUNCATE(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "TRUNCATE [ TABLE ] [ ONLY ] %s [ * ] [, ... ]\n" + " [ RESTART IDENTITY | CONTINUE IDENTITY ] [ CASCADE | RESTRICT ]", + _("name")); +} + +void +sql_help_UNLISTEN(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "UNLISTEN { %s | * }", + _("channel")); +} + +void +sql_help_UPDATE(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "[ WITH [ RECURSIVE ] %s [, ...] ]\n" + "UPDATE [ ONLY ] %s [ * ] [ [ AS ] %s ]\n" + " SET { %s = { %s | DEFAULT } |\n" + " ( %s [, ...] ) = ( { %s | DEFAULT } [, ...] ) |\n" + " ( %s [, ...] ) = ( %s )\n" + " } [, ...]\n" + " [ FROM %s ]\n" + " [ WHERE %s | WHERE CURRENT OF %s ]\n" + " [ RETURNING * | %s [ [ AS ] %s ] [, ...] ]", + _("with_query"), + _("table_name"), + _("alias"), + _("column_name"), + _("expression"), + _("column_name"), + _("expression"), + _("column_name"), + _("sub-SELECT"), + _("from_list"), + _("condition"), + _("cursor_name"), + _("output_expression"), + _("output_name")); +} + +void +sql_help_VACUUM(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "VACUUM [ ( { FULL | FREEZE | VERBOSE | ANALYZE } [, ...] ) ] [ %s [ (%s [, ...] ) ] ]\n" + "VACUUM [ FULL ] [ FREEZE ] [ VERBOSE ] [ %s ]\n" + "VACUUM [ FULL ] [ FREEZE ] [ VERBOSE ] ANALYZE [ %s [ (%s [, ...] ) ] ]", + _("table_name"), + _("column_name"), + _("table_name"), + _("table_name"), + _("column_name")); +} + +void +sql_help_VALUES(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "VALUES ( %s [, ...] ) [, ...]\n" + " [ ORDER BY %s [ ASC | DESC | USING %s ] [, ...] ]\n" + " [ LIMIT { %s | ALL } ]\n" + " [ OFFSET %s [ ROW | ROWS ] ]\n" + " [ FETCH { FIRST | NEXT } [ %s ] { ROW | ROWS } ONLY ]", + _("expression"), + _("sort_expression"), + _("operator"), + _("count"), + _("start"), + _("count")); +} + +void +sql_help_WITH(PQExpBuffer buf) +{ + appendPQExpBuffer(buf, + "[ WITH [ RECURSIVE ] %s [, ...] ]\n" + "SELECT [ ALL | DISTINCT [ ON ( %s [, ...] ) ] ]\n" + " [ * | %s [ [ AS ] %s ] [, ...] ]\n" + " [ FROM %s [, ...] ]\n" + " [ WHERE %s ]\n" + " [ GROUP BY %s [, ...] ]\n" + " [ HAVING %s [, ...] ]\n" + " [ WINDOW %s AS ( %s ) [, ...] ]\n" + " [ { UNION | INTERSECT | EXCEPT } [ ALL | DISTINCT ] %s ]\n" + " [ ORDER BY %s [ ASC | DESC | USING %s ] [ NULLS { FIRST | LAST } ] [, ...] ]\n" + " [ LIMIT { %s | ALL } ]\n" + " [ OFFSET %s [ ROW | ROWS ] ]\n" + " [ FETCH { FIRST | NEXT } [ %s ] { ROW | ROWS } ONLY ]\n" + " [ FOR { UPDATE | NO KEY UPDATE | SHARE | KEY SHARE } [ OF %s [, ...] ] [ NOWAIT | SKIP LOCKED ] [...] ]\n" + "\n" + "%s\n" + "\n" + " [ ONLY ] %s [ * ] [ [ AS ] %s [ ( %s [, ...] ) ] ]\n" + " [ TABLESAMPLE %s ( %s [, ...] ) [ REPEATABLE ( %s ) ] ]\n" + " [ LATERAL ] ( %s ) [ AS ] %s [ ( %s [, ...] ) ]\n" + " %s [ [ AS ] %s [ ( %s [, ...] ) ] ]\n" + " [ LATERAL ] %s ( [ %s [, ...] ] )\n" + " [ WITH ORDINALITY ] [ [ AS ] %s [ ( %s [, ...] ) ] ]\n" + " [ LATERAL ] %s ( [ %s [, ...] ] ) [ AS ] %s ( %s [, ...] )\n" + " [ LATERAL ] %s ( [ %s [, ...] ] ) AS ( %s [, ...] )\n" + " [ LATERAL ] ROWS FROM( %s ( [ %s [, ...] ] ) [ AS ( %s [, ...] ) ] [, ...] )\n" + " [ WITH ORDINALITY ] [ [ AS ] %s [ ( %s [, ...] ) ] ]\n" + " %s [ NATURAL ] %s %s [ ON %s | USING ( %s [, ...] ) ]\n" + "\n" + "%s\n" + "\n" + " ( )\n" + " %s\n" + " ( %s [, ...] )\n" + " ROLLUP ( { %s | ( %s [, ...] ) } [, ...] )\n" + " CUBE ( { %s | ( %s [, ...] ) } [, ...] )\n" + " GROUPING SETS ( %s [, ...] )\n" + "\n" + "%s\n" + "\n" + " %s [ ( %s [, ...] ) ] AS ( %s | %s | %s | %s | %s )\n" + "\n" + "TABLE [ ONLY ] %s [ * ]", + _("with_query"), + _("expression"), + _("expression"), + _("output_name"), + _("from_item"), + _("condition"), + _("grouping_element"), + _("condition"), + _("window_name"), + _("window_definition"), + _("select"), + _("expression"), + _("operator"), + _("count"), + _("start"), + _("count"), + _("table_name"), + _("where from_item can be one of:"), + _("table_name"), + _("alias"), + _("column_alias"), + _("sampling_method"), + _("argument"), + _("seed"), + _("select"), + _("alias"), + _("column_alias"), + _("with_query_name"), + _("alias"), + _("column_alias"), + _("function_name"), + _("argument"), + _("alias"), + _("column_alias"), + _("function_name"), + _("argument"), + _("alias"), + _("column_definition"), + _("function_name"), + _("argument"), + _("column_definition"), + _("function_name"), + _("argument"), + _("column_definition"), + _("alias"), + _("column_alias"), + _("from_item"), + _("join_type"), + _("from_item"), + _("join_condition"), + _("join_column"), + _("and grouping_element can be one of:"), + _("expression"), + _("expression"), + _("expression"), + _("expression"), + _("expression"), + _("expression"), + _("grouping_element"), + _("and with_query is:"), + _("with_query_name"), + _("column_name"), + _("select"), + _("values"), + _("insert"), + _("update"), + _("delete"), + _("table_name")); +} + diff --git a/src/bin/csql/sql_help.h b/src/bin/csql/sql_help.h new file mode 100644 index 000000000..3aac3ce7a --- /dev/null +++ b/src/bin/csql/sql_help.h @@ -0,0 +1,1040 @@ +/* + * *** Do not change this file by hand. It is automatically + * *** generated from the DocBook documentation. + * + * generated by + * /usr/bin/perl create_help.pl ../../../doc/src/sgml/ref sql_help + * + */ + +#ifndef SQL_HELP_H +#define SQL_HELP_H + +#define N_(x) (x) /* gettext noop */ + +#include "postgres_fe.h" +#include "pqexpbuffer.h" + +struct _helpStruct +{ + const char *cmd; /* the command name */ + const char *help; /* the help associated with it */ + void (*syntaxfunc)(PQExpBuffer); /* function that prints the syntax associated with it */ + int nl_count; /* number of newlines in syntax (for pager) */ +}; + +extern void sql_help_ABORT(PQExpBuffer buf); +extern void sql_help_ALTER_AGGREGATE(PQExpBuffer buf); +extern void sql_help_ALTER_COLLATION(PQExpBuffer buf); +extern void sql_help_ALTER_CONVERSION(PQExpBuffer buf); +extern void sql_help_ALTER_DATABASE(PQExpBuffer buf); +extern void sql_help_ALTER_DEFAULT_PRIVILEGES(PQExpBuffer buf); +extern void sql_help_ALTER_DOMAIN(PQExpBuffer buf); +extern void sql_help_ALTER_EVENT_TRIGGER(PQExpBuffer buf); +extern void sql_help_ALTER_EXTENSION(PQExpBuffer buf); +extern void sql_help_ALTER_FOREIGN_DATA_WRAPPER(PQExpBuffer buf); +extern void sql_help_ALTER_FOREIGN_TABLE(PQExpBuffer buf); +extern void sql_help_ALTER_FUNCTION(PQExpBuffer buf); +extern void sql_help_ALTER_GROUP(PQExpBuffer buf); +extern void sql_help_ALTER_INDEX(PQExpBuffer buf); +extern void sql_help_ALTER_LANGUAGE(PQExpBuffer buf); +extern void sql_help_ALTER_LARGE_OBJECT(PQExpBuffer buf); +extern void sql_help_ALTER_MATERIALIZED_VIEW(PQExpBuffer buf); +extern void sql_help_ALTER_OPERATOR(PQExpBuffer buf); +extern void sql_help_ALTER_OPERATOR_CLASS(PQExpBuffer buf); +extern void sql_help_ALTER_OPERATOR_FAMILY(PQExpBuffer buf); +extern void sql_help_ALTER_POLICY(PQExpBuffer buf); +extern void sql_help_ALTER_ROLE(PQExpBuffer buf); +extern void sql_help_ALTER_RULE(PQExpBuffer buf); +extern void sql_help_ALTER_SCHEMA(PQExpBuffer buf); +extern void sql_help_ALTER_SEQUENCE(PQExpBuffer buf); +extern void sql_help_ALTER_SERVER(PQExpBuffer buf); +extern void sql_help_ALTER_SYSTEM(PQExpBuffer buf); +extern void sql_help_ALTER_TABLE(PQExpBuffer buf); +extern void sql_help_ALTER_TABLESPACE(PQExpBuffer buf); +extern void sql_help_ALTER_TEXT_SEARCH_CONFIGURATION(PQExpBuffer buf); +extern void sql_help_ALTER_TEXT_SEARCH_DICTIONARY(PQExpBuffer buf); +extern void sql_help_ALTER_TEXT_SEARCH_PARSER(PQExpBuffer buf); +extern void sql_help_ALTER_TEXT_SEARCH_TEMPLATE(PQExpBuffer buf); +extern void sql_help_ALTER_TRIGGER(PQExpBuffer buf); +extern void sql_help_ALTER_TYPE(PQExpBuffer buf); +extern void sql_help_ALTER_USER(PQExpBuffer buf); +extern void sql_help_ALTER_USER_MAPPING(PQExpBuffer buf); +extern void sql_help_ALTER_VIEW(PQExpBuffer buf); +extern void sql_help_ANALYZE(PQExpBuffer buf); +extern void sql_help_BEGIN(PQExpBuffer buf); +extern void sql_help_CHECKPOINT(PQExpBuffer buf); +extern void sql_help_CLOSE(PQExpBuffer buf); +extern void sql_help_CLUSTER(PQExpBuffer buf); +extern void sql_help_COMMENT(PQExpBuffer buf); +extern void sql_help_COMMIT(PQExpBuffer buf); +extern void sql_help_COMMIT_PREPARED(PQExpBuffer buf); +extern void sql_help_COPY(PQExpBuffer buf); +extern void sql_help_CREATE_AGGREGATE(PQExpBuffer buf); +extern void sql_help_CREATE_CAST(PQExpBuffer buf); +extern void sql_help_CREATE_COLLATION(PQExpBuffer buf); +extern void sql_help_CREATE_CONVERSION(PQExpBuffer buf); +extern void sql_help_CREATE_DATABASE(PQExpBuffer buf); +extern void sql_help_CREATE_DOMAIN(PQExpBuffer buf); +extern void sql_help_CREATE_EVENT_TRIGGER(PQExpBuffer buf); +extern void sql_help_CREATE_EXTENSION(PQExpBuffer buf); +extern void sql_help_CREATE_FOREIGN_DATA_WRAPPER(PQExpBuffer buf); +extern void sql_help_CREATE_FOREIGN_TABLE(PQExpBuffer buf); +extern void sql_help_CREATE_FUNCTION(PQExpBuffer buf); +extern void sql_help_CREATE_GROUP(PQExpBuffer buf); +extern void sql_help_CREATE_INDEX(PQExpBuffer buf); +extern void sql_help_CREATE_LANGUAGE(PQExpBuffer buf); +extern void sql_help_CREATE_MATERIALIZED_VIEW(PQExpBuffer buf); +extern void sql_help_CREATE_OPERATOR(PQExpBuffer buf); +extern void sql_help_CREATE_OPERATOR_CLASS(PQExpBuffer buf); +extern void sql_help_CREATE_OPERATOR_FAMILY(PQExpBuffer buf); +extern void sql_help_CREATE_POLICY(PQExpBuffer buf); +extern void sql_help_CREATE_ROLE(PQExpBuffer buf); +extern void sql_help_CREATE_RULE(PQExpBuffer buf); +extern void sql_help_CREATE_SCHEMA(PQExpBuffer buf); +extern void sql_help_CREATE_SEQUENCE(PQExpBuffer buf); +extern void sql_help_CREATE_SERVER(PQExpBuffer buf); +extern void sql_help_CREATE_TABLE(PQExpBuffer buf); +extern void sql_help_CREATE_TABLE_AS(PQExpBuffer buf); +extern void sql_help_CREATE_TABLESPACE(PQExpBuffer buf); +extern void sql_help_CREATE_TEXT_SEARCH_CONFIGURATION(PQExpBuffer buf); +extern void sql_help_CREATE_TEXT_SEARCH_DICTIONARY(PQExpBuffer buf); +extern void sql_help_CREATE_TEXT_SEARCH_PARSER(PQExpBuffer buf); +extern void sql_help_CREATE_TEXT_SEARCH_TEMPLATE(PQExpBuffer buf); +extern void sql_help_CREATE_TRANSFORM(PQExpBuffer buf); +extern void sql_help_CREATE_TRIGGER(PQExpBuffer buf); +extern void sql_help_CREATE_TYPE(PQExpBuffer buf); +extern void sql_help_CREATE_USER(PQExpBuffer buf); +extern void sql_help_CREATE_USER_MAPPING(PQExpBuffer buf); +extern void sql_help_CREATE_VIEW(PQExpBuffer buf); +extern void sql_help_DEALLOCATE(PQExpBuffer buf); +extern void sql_help_DECLARE(PQExpBuffer buf); +extern void sql_help_DELETE(PQExpBuffer buf); +extern void sql_help_DISCARD(PQExpBuffer buf); +extern void sql_help_DO(PQExpBuffer buf); +extern void sql_help_DROP_AGGREGATE(PQExpBuffer buf); +extern void sql_help_DROP_CAST(PQExpBuffer buf); +extern void sql_help_DROP_COLLATION(PQExpBuffer buf); +extern void sql_help_DROP_CONVERSION(PQExpBuffer buf); +extern void sql_help_DROP_DATABASE(PQExpBuffer buf); +extern void sql_help_DROP_DOMAIN(PQExpBuffer buf); +extern void sql_help_DROP_EVENT_TRIGGER(PQExpBuffer buf); +extern void sql_help_DROP_EXTENSION(PQExpBuffer buf); +extern void sql_help_DROP_FOREIGN_DATA_WRAPPER(PQExpBuffer buf); +extern void sql_help_DROP_FOREIGN_TABLE(PQExpBuffer buf); +extern void sql_help_DROP_FUNCTION(PQExpBuffer buf); +extern void sql_help_DROP_GROUP(PQExpBuffer buf); +extern void sql_help_DROP_INDEX(PQExpBuffer buf); +extern void sql_help_DROP_LANGUAGE(PQExpBuffer buf); +extern void sql_help_DROP_MATERIALIZED_VIEW(PQExpBuffer buf); +extern void sql_help_DROP_OPERATOR(PQExpBuffer buf); +extern void sql_help_DROP_OPERATOR_CLASS(PQExpBuffer buf); +extern void sql_help_DROP_OPERATOR_FAMILY(PQExpBuffer buf); +extern void sql_help_DROP_OWNED(PQExpBuffer buf); +extern void sql_help_DROP_POLICY(PQExpBuffer buf); +extern void sql_help_DROP_ROLE(PQExpBuffer buf); +extern void sql_help_DROP_RULE(PQExpBuffer buf); +extern void sql_help_DROP_SCHEMA(PQExpBuffer buf); +extern void sql_help_DROP_SEQUENCE(PQExpBuffer buf); +extern void sql_help_DROP_SERVER(PQExpBuffer buf); +extern void sql_help_DROP_TABLE(PQExpBuffer buf); +extern void sql_help_DROP_TABLESPACE(PQExpBuffer buf); +extern void sql_help_DROP_TEXT_SEARCH_CONFIGURATION(PQExpBuffer buf); +extern void sql_help_DROP_TEXT_SEARCH_DICTIONARY(PQExpBuffer buf); +extern void sql_help_DROP_TEXT_SEARCH_PARSER(PQExpBuffer buf); +extern void sql_help_DROP_TEXT_SEARCH_TEMPLATE(PQExpBuffer buf); +extern void sql_help_DROP_TRANSFORM(PQExpBuffer buf); +extern void sql_help_DROP_TRIGGER(PQExpBuffer buf); +extern void sql_help_DROP_TYPE(PQExpBuffer buf); +extern void sql_help_DROP_USER(PQExpBuffer buf); +extern void sql_help_DROP_USER_MAPPING(PQExpBuffer buf); +extern void sql_help_DROP_VIEW(PQExpBuffer buf); +extern void sql_help_END(PQExpBuffer buf); +extern void sql_help_EXECUTE(PQExpBuffer buf); +extern void sql_help_EXPLAIN(PQExpBuffer buf); +extern void sql_help_FETCH(PQExpBuffer buf); +extern void sql_help_GRANT(PQExpBuffer buf); +extern void sql_help_IMPORT_FOREIGN_SCHEMA(PQExpBuffer buf); +extern void sql_help_INSERT(PQExpBuffer buf); +extern void sql_help_LISTEN(PQExpBuffer buf); +extern void sql_help_LOAD(PQExpBuffer buf); +extern void sql_help_LOCK(PQExpBuffer buf); +extern void sql_help_MOVE(PQExpBuffer buf); +extern void sql_help_NOTIFY(PQExpBuffer buf); +extern void sql_help_PREPARE(PQExpBuffer buf); +extern void sql_help_PREPARE_TRANSACTION(PQExpBuffer buf); +extern void sql_help_REASSIGN_OWNED(PQExpBuffer buf); +extern void sql_help_REFRESH_MATERIALIZED_VIEW(PQExpBuffer buf); +extern void sql_help_REINDEX(PQExpBuffer buf); +extern void sql_help_RELEASE_SAVEPOINT(PQExpBuffer buf); +extern void sql_help_RESET(PQExpBuffer buf); +extern void sql_help_REVOKE(PQExpBuffer buf); +extern void sql_help_ROLLBACK(PQExpBuffer buf); +extern void sql_help_ROLLBACK_PREPARED(PQExpBuffer buf); +extern void sql_help_ROLLBACK_TO_SAVEPOINT(PQExpBuffer buf); +extern void sql_help_SAVEPOINT(PQExpBuffer buf); +extern void sql_help_SECURITY_LABEL(PQExpBuffer buf); +extern void sql_help_SELECT(PQExpBuffer buf); +extern void sql_help_SELECT_INTO(PQExpBuffer buf); +extern void sql_help_SET(PQExpBuffer buf); +extern void sql_help_SET_CONSTRAINTS(PQExpBuffer buf); +extern void sql_help_SET_ROLE(PQExpBuffer buf); +extern void sql_help_SET_SESSION_AUTHORIZATION(PQExpBuffer buf); +extern void sql_help_SET_TRANSACTION(PQExpBuffer buf); +extern void sql_help_SHOW(PQExpBuffer buf); +extern void sql_help_START_TRANSACTION(PQExpBuffer buf); +extern void sql_help_TABLE(PQExpBuffer buf); +extern void sql_help_TRUNCATE(PQExpBuffer buf); +extern void sql_help_UNLISTEN(PQExpBuffer buf); +extern void sql_help_UPDATE(PQExpBuffer buf); +extern void sql_help_VACUUM(PQExpBuffer buf); +extern void sql_help_VALUES(PQExpBuffer buf); +extern void sql_help_WITH(PQExpBuffer buf); + + +static const struct _helpStruct QL_HELP[] = { + { "ABORT", + N_("abort the current transaction"), + sql_help_ABORT, + 0 }, + + { "ALTER AGGREGATE", + N_("change the definition of an aggregate function"), + sql_help_ALTER_AGGREGATE, + 9 }, + + { "ALTER COLLATION", + N_("change the definition of a collation"), + sql_help_ALTER_COLLATION, + 2 }, + + { "ALTER CONVERSION", + N_("change the definition of a conversion"), + sql_help_ALTER_CONVERSION, + 2 }, + + { "ALTER DATABASE", + N_("change a database"), + sql_help_ALTER_DATABASE, + 17 }, + + { "ALTER DEFAULT PRIVILEGES", + N_("define default access privileges"), + sql_help_ALTER_DEFAULT_PRIVILEGES, + 49 }, + + { "ALTER DOMAIN", + N_("change the definition of a domain"), + sql_help_ALTER_DOMAIN, + 17 }, + + { "ALTER EVENT TRIGGER", + N_("change the definition of an event trigger"), + sql_help_ALTER_EVENT_TRIGGER, + 3 }, + + { "ALTER EXTENSION", + N_("change the definition of an extension"), + sql_help_ALTER_EXTENSION, + 37 }, + + { "ALTER FOREIGN DATA WRAPPER", + N_("change the definition of a foreign-data wrapper"), + sql_help_ALTER_FOREIGN_DATA_WRAPPER, + 5 }, + + { "ALTER FOREIGN TABLE", + N_("change the definition of a foreign table"), + sql_help_ALTER_FOREIGN_TABLE, + 34 }, + + { "ALTER FUNCTION", + N_("change the definition of a function"), + sql_help_ALTER_FUNCTION, + 19 }, + + { "ALTER GROUP", + N_("change role name or membership"), + sql_help_ALTER_GROUP, + 9 }, + + { "ALTER INDEX", + N_("change the definition of an index"), + sql_help_ALTER_INDEX, + 5 }, + + { "ALTER LANGUAGE", + N_("change the definition of a procedural language"), + sql_help_ALTER_LANGUAGE, + 1 }, + + { "ALTER LARGE OBJECT", + N_("change the definition of a large object"), + sql_help_ALTER_LARGE_OBJECT, + 0 }, + + { "ALTER MATERIALIZED VIEW", + N_("change the definition of a materialized view"), + sql_help_ALTER_MATERIALIZED_VIEW, + 22 }, + + { "ALTER OPERATOR", + N_("change the definition of an operator"), + sql_help_ALTER_OPERATOR, + 4 }, + + { "ALTER OPERATOR CLASS", + N_("change the definition of an operator class"), + sql_help_ALTER_OPERATOR_CLASS, + 7 }, + + { "ALTER OPERATOR FAMILY", + N_("change the definition of an operator family"), + sql_help_ALTER_OPERATOR_FAMILY, + 19 }, + + { "ALTER POLICY", + N_("change the definition of a row level security policy"), + sql_help_ALTER_POLICY, + 5 }, + + { "ALTER ROLE", + N_("change a database role"), + sql_help_ALTER_ROLE, + 27 }, + + { "ALTER RULE", + N_("change the definition of a rule"), + sql_help_ALTER_RULE, + 0 }, + + { "ALTER SCHEMA", + N_("change the definition of a schema"), + sql_help_ALTER_SCHEMA, + 1 }, + + { "ALTER SEQUENCE", + N_("change the definition of a sequence generator"), + sql_help_ALTER_SEQUENCE, + 8 }, + + { "ALTER SERVER", + N_("change the definition of a foreign server"), + sql_help_ALTER_SERVER, + 3 }, + + { "ALTER SYSTEM", + N_("change a server configuration parameter"), + sql_help_ALTER_SYSTEM, + 3 }, + + { "ALTER TABLE", + N_("change the definition of a table"), + sql_help_ALTER_TABLE, + 61 }, + + { "ALTER TABLESPACE", + N_("change the definition of a tablespace"), + sql_help_ALTER_TABLESPACE, + 3 }, + + { "ALTER TEXT SEARCH CONFIGURATION", + N_("change the definition of a text search configuration"), + sql_help_ALTER_TEXT_SEARCH_CONFIGURATION, + 12 }, + + { "ALTER TEXT SEARCH DICTIONARY", + N_("change the definition of a text search dictionary"), + sql_help_ALTER_TEXT_SEARCH_DICTIONARY, + 5 }, + + { "ALTER TEXT SEARCH PARSER", + N_("change the definition of a text search parser"), + sql_help_ALTER_TEXT_SEARCH_PARSER, + 1 }, + + { "ALTER TEXT SEARCH TEMPLATE", + N_("change the definition of a text search template"), + sql_help_ALTER_TEXT_SEARCH_TEMPLATE, + 1 }, + + { "ALTER TRIGGER", + N_("change the definition of a trigger"), + sql_help_ALTER_TRIGGER, + 0 }, + + { "ALTER TYPE", + N_("change the definition of a type"), + sql_help_ALTER_TYPE, + 11 }, + + { "ALTER USER", + N_("change a database role"), + sql_help_ALTER_USER, + 26 }, + + { "ALTER USER MAPPING", + N_("change the definition of a user mapping"), + sql_help_ALTER_USER_MAPPING, + 2 }, + + { "ALTER VIEW", + N_("change the definition of a view"), + sql_help_ALTER_VIEW, + 6 }, + + { "ANALYZE", + N_("collect statistics about a database"), + sql_help_ANALYZE, + 0 }, + + { "BEGIN", + N_("start a transaction block"), + sql_help_BEGIN, + 6 }, + + { "CHECKPOINT", + N_("force a transaction log checkpoint"), + sql_help_CHECKPOINT, + 0 }, + + { "CLOSE", + N_("close a cursor"), + sql_help_CLOSE, + 0 }, + + { "CLUSTER", + N_("cluster a table according to an index"), + sql_help_CLUSTER, + 1 }, + + { "COMMENT", + N_("define or change the comment of an object"), + sql_help_COMMENT, + 45 }, + + { "COMMIT", + N_("commit the current transaction"), + sql_help_COMMIT, + 0 }, + + { "COMMIT PREPARED", + N_("commit a transaction that was earlier prepared for two-phase commit"), + sql_help_COMMIT_PREPARED, + 0 }, + + { "COPY", + N_("copy data between a file and a table"), + sql_help_COPY, + 21 }, + + { "CREATE AGGREGATE", + N_("define a new aggregate function"), + sql_help_CREATE_AGGREGATE, + 46 }, + + { "CREATE CAST", + N_("define a new cast"), + sql_help_CREATE_CAST, + 10 }, + + { "CREATE COLLATION", + N_("define a new collation"), + sql_help_CREATE_COLLATION, + 5 }, + + { "CREATE CONVERSION", + N_("define a new encoding conversion"), + sql_help_CREATE_CONVERSION, + 1 }, + + { "CREATE DATABASE", + N_("create a new database"), + sql_help_CREATE_DATABASE, + 9 }, + + { "CREATE DOMAIN", + N_("define a new domain"), + sql_help_CREATE_DOMAIN, + 8 }, + + { "CREATE EVENT TRIGGER", + N_("define a new event trigger"), + sql_help_CREATE_EVENT_TRIGGER, + 3 }, + + { "CREATE EXTENSION", + N_("install an extension"), + sql_help_CREATE_EXTENSION, + 3 }, + + { "CREATE FOREIGN DATA WRAPPER", + N_("define a new foreign-data wrapper"), + sql_help_CREATE_FOREIGN_DATA_WRAPPER, + 3 }, + + { "CREATE FOREIGN TABLE", + N_("define a new foreign table"), + sql_help_CREATE_FOREIGN_TABLE, + 20 }, + + { "CREATE FUNCTION", + N_("define a new function"), + sql_help_CREATE_FUNCTION, + 16 }, + + { "CREATE GROUP", + N_("define a new database role"), + sql_help_CREATE_GROUP, + 17 }, + + { "CREATE INDEX", + N_("define a new index"), + sql_help_CREATE_INDEX, + 4 }, + + { "CREATE LANGUAGE", + N_("define a new procedural language"), + sql_help_CREATE_LANGUAGE, + 2 }, + + { "CREATE MATERIALIZED VIEW", + N_("define a new materialized view"), + sql_help_CREATE_MATERIALIZED_VIEW, + 5 }, + + { "CREATE OPERATOR", + N_("define a new operator"), + sql_help_CREATE_OPERATOR, + 6 }, + + { "CREATE OPERATOR CLASS", + N_("define a new operator class"), + sql_help_CREATE_OPERATOR_CLASS, + 5 }, + + { "CREATE OPERATOR FAMILY", + N_("define a new operator family"), + sql_help_CREATE_OPERATOR_FAMILY, + 0 }, + + { "CREATE POLICY", + N_("define a new row level security policy for a table"), + sql_help_CREATE_POLICY, + 4 }, + + { "CREATE ROLE", + N_("define a new database role"), + sql_help_CREATE_ROLE, + 20 }, + + { "CREATE RULE", + N_("define a new rewrite rule"), + sql_help_CREATE_RULE, + 6 }, + + { "CREATE SCHEMA", + N_("define a new schema"), + sql_help_CREATE_SCHEMA, + 9 }, + + { "CREATE SEQUENCE", + N_("define a new sequence generator"), + sql_help_CREATE_SEQUENCE, + 3 }, + + { "CREATE SERVER", + N_("define a new foreign server"), + sql_help_CREATE_SERVER, + 2 }, + + { "CREATE TABLE", + N_("define a new table"), + sql_help_CREATE_TABLE, + 56 }, + + { "CREATE TABLE AS", + N_("define a new table from the results of a query"), + sql_help_CREATE_TABLE_AS, + 6 }, + + { "CREATE TABLESPACE", + N_("define a new tablespace"), + sql_help_CREATE_TABLESPACE, + 3 }, + + { "CREATE TEXT SEARCH CONFIGURATION", + N_("define a new text search configuration"), + sql_help_CREATE_TEXT_SEARCH_CONFIGURATION, + 3 }, + + { "CREATE TEXT SEARCH DICTIONARY", + N_("define a new text search dictionary"), + sql_help_CREATE_TEXT_SEARCH_DICTIONARY, + 3 }, + + { "CREATE TEXT SEARCH PARSER", + N_("define a new text search parser"), + sql_help_CREATE_TEXT_SEARCH_PARSER, + 6 }, + + { "CREATE TEXT SEARCH TEMPLATE", + N_("define a new text search template"), + sql_help_CREATE_TEXT_SEARCH_TEMPLATE, + 3 }, + + { "CREATE TRANSFORM", + N_("define a new transform"), + sql_help_CREATE_TRANSFORM, + 3 }, + + { "CREATE TRIGGER", + N_("define a new trigger"), + sql_help_CREATE_TRIGGER, + 13 }, + + { "CREATE TYPE", + N_("define a new data type"), + sql_help_CREATE_TYPE, + 35 }, + + { "CREATE USER", + N_("define a new database role"), + sql_help_CREATE_USER, + 19 }, + + { "CREATE USER MAPPING", + N_("define a new mapping of a user to a foreign server"), + sql_help_CREATE_USER_MAPPING, + 2 }, + + { "CREATE VIEW", + N_("define a new view"), + sql_help_CREATE_VIEW, + 3 }, + + { "DEALLOCATE", + N_("deallocate a prepared statement"), + sql_help_DEALLOCATE, + 0 }, + + { "DECLARE", + N_("define a cursor"), + sql_help_DECLARE, + 1 }, + + { "DELETE", + N_("delete rows of a table"), + sql_help_DELETE, + 4 }, + + { "DISCARD", + N_("discard session state"), + sql_help_DISCARD, + 0 }, + + { "DO", + N_("execute an anonymous code block"), + sql_help_DO, + 0 }, + + { "DROP AGGREGATE", + N_("remove an aggregate function"), + sql_help_DROP_AGGREGATE, + 6 }, + + { "DROP CAST", + N_("remove a cast"), + sql_help_DROP_CAST, + 0 }, + + { "DROP COLLATION", + N_("remove a collation"), + sql_help_DROP_COLLATION, + 0 }, + + { "DROP CONVERSION", + N_("remove a conversion"), + sql_help_DROP_CONVERSION, + 0 }, + + { "DROP DATABASE", + N_("remove a database"), + sql_help_DROP_DATABASE, + 0 }, + + { "DROP DOMAIN", + N_("remove a domain"), + sql_help_DROP_DOMAIN, + 0 }, + + { "DROP EVENT TRIGGER", + N_("remove an event trigger"), + sql_help_DROP_EVENT_TRIGGER, + 0 }, + + { "DROP EXTENSION", + N_("remove an extension"), + sql_help_DROP_EXTENSION, + 0 }, + + { "DROP FOREIGN DATA WRAPPER", + N_("remove a foreign-data wrapper"), + sql_help_DROP_FOREIGN_DATA_WRAPPER, + 0 }, + + { "DROP FOREIGN TABLE", + N_("remove a foreign table"), + sql_help_DROP_FOREIGN_TABLE, + 0 }, + + { "DROP FUNCTION", + N_("remove a function"), + sql_help_DROP_FUNCTION, + 1 }, + + { "DROP GROUP", + N_("remove a database role"), + sql_help_DROP_GROUP, + 0 }, + + { "DROP INDEX", + N_("remove an index"), + sql_help_DROP_INDEX, + 0 }, + + { "DROP LANGUAGE", + N_("remove a procedural language"), + sql_help_DROP_LANGUAGE, + 0 }, + + { "DROP MATERIALIZED VIEW", + N_("remove a materialized view"), + sql_help_DROP_MATERIALIZED_VIEW, + 0 }, + + { "DROP OPERATOR", + N_("remove an operator"), + sql_help_DROP_OPERATOR, + 0 }, + + { "DROP OPERATOR CLASS", + N_("remove an operator class"), + sql_help_DROP_OPERATOR_CLASS, + 0 }, + + { "DROP OPERATOR FAMILY", + N_("remove an operator family"), + sql_help_DROP_OPERATOR_FAMILY, + 0 }, + + { "DROP OWNED", + N_("remove database objects owned by a database role"), + sql_help_DROP_OWNED, + 0 }, + + { "DROP POLICY", + N_("remove a row level security policy from a table"), + sql_help_DROP_POLICY, + 0 }, + + { "DROP ROLE", + N_("remove a database role"), + sql_help_DROP_ROLE, + 0 }, + + { "DROP RULE", + N_("remove a rewrite rule"), + sql_help_DROP_RULE, + 0 }, + + { "DROP SCHEMA", + N_("remove a schema"), + sql_help_DROP_SCHEMA, + 0 }, + + { "DROP SEQUENCE", + N_("remove a sequence"), + sql_help_DROP_SEQUENCE, + 0 }, + + { "DROP SERVER", + N_("remove a foreign server descriptor"), + sql_help_DROP_SERVER, + 0 }, + + { "DROP TABLE", + N_("remove a table"), + sql_help_DROP_TABLE, + 0 }, + + { "DROP TABLESPACE", + N_("remove a tablespace"), + sql_help_DROP_TABLESPACE, + 0 }, + + { "DROP TEXT SEARCH CONFIGURATION", + N_("remove a text search configuration"), + sql_help_DROP_TEXT_SEARCH_CONFIGURATION, + 0 }, + + { "DROP TEXT SEARCH DICTIONARY", + N_("remove a text search dictionary"), + sql_help_DROP_TEXT_SEARCH_DICTIONARY, + 0 }, + + { "DROP TEXT SEARCH PARSER", + N_("remove a text search parser"), + sql_help_DROP_TEXT_SEARCH_PARSER, + 0 }, + + { "DROP TEXT SEARCH TEMPLATE", + N_("remove a text search template"), + sql_help_DROP_TEXT_SEARCH_TEMPLATE, + 0 }, + + { "DROP TRANSFORM", + N_("remove a transform"), + sql_help_DROP_TRANSFORM, + 0 }, + + { "DROP TRIGGER", + N_("remove a trigger"), + sql_help_DROP_TRIGGER, + 0 }, + + { "DROP TYPE", + N_("remove a data type"), + sql_help_DROP_TYPE, + 0 }, + + { "DROP USER", + N_("remove a database role"), + sql_help_DROP_USER, + 0 }, + + { "DROP USER MAPPING", + N_("remove a user mapping for a foreign server"), + sql_help_DROP_USER_MAPPING, + 0 }, + + { "DROP VIEW", + N_("remove a view"), + sql_help_DROP_VIEW, + 0 }, + + { "END", + N_("commit the current transaction"), + sql_help_END, + 0 }, + + { "EXECUTE", + N_("execute a prepared statement"), + sql_help_EXECUTE, + 0 }, + + { "EXPLAIN", + N_("show the execution plan of a statement"), + sql_help_EXPLAIN, + 10 }, + + { "FETCH", + N_("retrieve rows from a query using a cursor"), + sql_help_FETCH, + 17 }, + + { "GRANT", + N_("define access privileges"), + sql_help_GRANT, + 65 }, + + { "IMPORT FOREIGN SCHEMA", + N_("import table definitions from a foreign server"), + sql_help_IMPORT_FOREIGN_SCHEMA, + 4 }, + + { "INSERT", + N_("create new rows in a table"), + sql_help_INSERT, + 18 }, + + { "LISTEN", + N_("listen for a notification"), + sql_help_LISTEN, + 0 }, + + { "LOAD", + N_("load a shared library file"), + sql_help_LOAD, + 0 }, + + { "LOCK", + N_("lock a table"), + sql_help_LOCK, + 5 }, + + { "MOVE", + N_("position a cursor"), + sql_help_MOVE, + 17 }, + + { "NOTIFY", + N_("generate a notification"), + sql_help_NOTIFY, + 0 }, + + { "PREPARE", + N_("prepare a statement for execution"), + sql_help_PREPARE, + 0 }, + + { "PREPARE TRANSACTION", + N_("prepare the current transaction for two-phase commit"), + sql_help_PREPARE_TRANSACTION, + 0 }, + + { "REASSIGN OWNED", + N_("change the ownership of database objects owned by a database role"), + sql_help_REASSIGN_OWNED, + 1 }, + + { "REFRESH MATERIALIZED VIEW", + N_("replace the contents of a materialized view"), + sql_help_REFRESH_MATERIALIZED_VIEW, + 1 }, + + { "REINDEX", + N_("rebuild indexes"), + sql_help_REINDEX, + 0 }, + + { "RELEASE SAVEPOINT", + N_("destroy a previously defined savepoint"), + sql_help_RELEASE_SAVEPOINT, + 0 }, + + { "RESET", + N_("restore the value of a run-time parameter to the default value"), + sql_help_RESET, + 1 }, + + { "REVOKE", + N_("remove access privileges"), + sql_help_REVOKE, + 86 }, + + { "ROLLBACK", + N_("abort the current transaction"), + sql_help_ROLLBACK, + 0 }, + + { "ROLLBACK PREPARED", + N_("cancel a transaction that was earlier prepared for two-phase commit"), + sql_help_ROLLBACK_PREPARED, + 0 }, + + { "ROLLBACK TO SAVEPOINT", + N_("roll back to a savepoint"), + sql_help_ROLLBACK_TO_SAVEPOINT, + 0 }, + + { "SAVEPOINT", + N_("define a new savepoint within the current transaction"), + sql_help_SAVEPOINT, + 0 }, + + { "SECURITY LABEL", + N_("define or change a security label applied to an object"), + sql_help_SECURITY_LABEL, + 25 }, + + { "SELECT", + N_("retrieve rows from a table or view"), + sql_help_SELECT, + 42 }, + + { "SELECT INTO", + N_("define a new table from the results of a query"), + sql_help_SELECT_INTO, + 14 }, + + { "SET", + N_("change a run-time parameter"), + sql_help_SET, + 1 }, + + { "SET CONSTRAINTS", + N_("set constraint check timing for the current transaction"), + sql_help_SET_CONSTRAINTS, + 0 }, + + { "SET ROLE", + N_("set the current user identifier of the current session"), + sql_help_SET_ROLE, + 2 }, + + { "SET SESSION AUTHORIZATION", + N_("set the session user identifier and the current user identifier of the current session"), + sql_help_SET_SESSION_AUTHORIZATION, + 2 }, + + { "SET TRANSACTION", + N_("set the characteristics of the current transaction"), + sql_help_SET_TRANSACTION, + 8 }, + + { "SHOW", + N_("show the value of a run-time parameter"), + sql_help_SHOW, + 1 }, + + { "START TRANSACTION", + N_("start a transaction block"), + sql_help_START_TRANSACTION, + 6 }, + + { "TABLE", + N_("retrieve rows from a table or view"), + sql_help_TABLE, + 42 }, + + { "TRUNCATE", + N_("empty a table or set of tables"), + sql_help_TRUNCATE, + 1 }, + + { "UNLISTEN", + N_("stop listening for a notification"), + sql_help_UNLISTEN, + 0 }, + + { "UPDATE", + N_("update rows of a table"), + sql_help_UPDATE, + 8 }, + + { "VACUUM", + N_("garbage-collect and optionally analyze a database"), + sql_help_VACUUM, + 2 }, + + { "VALUES", + N_("compute a set of rows"), + sql_help_VALUES, + 4 }, + + { "WITH", + N_("retrieve rows from a table or view"), + sql_help_WITH, + 42 }, + + + { NULL, NULL, NULL } /* End of list marker */ +}; + + +#define QL_HELP_COUNT 167 /* number of help items */ +#define QL_MAX_CMD_LEN 32 /* largest strlen(cmd) */ + + +#endif /* SQL_HELP_H */ diff --git a/src/bin/csql/stage.c b/src/bin/csql/stage.c new file mode 100644 index 000000000..1863b8bcb --- /dev/null +++ b/src/bin/csql/stage.c @@ -0,0 +1,1785 @@ +/* + * csql - the CitusDB interactive terminal + * stage.c + * Helper routines to execute the csql meta-command \stage. These routines + * communicate with the master and worker nodes; and create new shards and + * upload data into them. + * + * Copyright (c) 2012, Citus Data, Inc. + * + * $Id$ + */ + +#include +#include + +#include "libpq-int.h" +#include "libpq/ip.h" +#include "common.h" +#include "copy.h" +#include "distributed/pg_dist_partition.h" +#include "settings.h" +#include "stage.h" + + +/* Local functions forward declarations */ +static bool FileSize(char *filename, uint64 *fileSize); +static PGconn * ConnectToWorkerNode(const char *nodeName, uint32 nodePort, + const char *nodeDatabase); +static PGresult * ExecuteRemoteCommand(PGconn *remoteConnection, const char *remoteCommand, + const char **parameterValues, int parameterCount); +static TableMetadata * InitTableMetadata(const char *tableName); +static ShardMetadata * InitShardMetadata(int shardPlacementPolicy); +static void FreeTableMetadata(TableMetadata *tableMetadata); +static void FreeShardMetadata(ShardMetadata *shardMetadata); +static void FreeShardMetadataList(ShardMetadata **shardMetadataList); +static void FreeCommonStageData(copy_options *stageOptions, TableMetadata *tableMetadata, + ShardMetadata **shardMetadataList); +static bool ColumnarTableOptionsOK(Oid relationOid); +static char * ExtendTablename(const char *baseTablename, uint64 shardId); +static uint64 GetValueUint64(const PGresult *result, int rowNumber, int columnNumber); +static bool MasterGetTableMetadata(const char *tableName, TableMetadata *tableMetadata); +static bool MasterGetTableDDLEvents(const char *tableName, TableMetadata *tableMetadata); +static bool MasterGetNewShardId(ShardMetadata *shardMetadata); +static bool MasterGetCandidateNodes(ShardMetadata *shardMetadata, int shardPlacementPolicy); +static bool MasterInsertShardRow(uint32 logicalRelid, char storageType, + const ShardMetadata *shardMetadata); +static bool MasterInsertPlacementRows(const ShardMetadata *shardMetadata); +static bool MasterInsertShardMetadata(uint32 logicalRelid, char storageType, + ShardMetadata **shardMetadataList); +static bool IssueTransactionCommand(PGconn *connection, const char *command); +static bool StageTableData(PGconn *workerNode, uint64 shardId, + TableMetadata *tableMetadata, copy_options *stageOptions, + uint64 currentFileOffset, uint64 *nextFileOffset); +static bool StageForeignData(PGconn *workerNode, uint64 shardId, + TableMetadata *tableMetaData, copy_options *stageOptions); +static bool CreateRegularTable(PGconn *workerNode, int64 shardId, + TableMetadata *tableMetadata); +static bool CreateForeignTable(PGconn *workerNode, uint64 shardId, + TableMetadata *tableMetaData, const char *tableName, + const char *filePath); +static bool ApplyShardDDLCommand(PGconn *workerNode, uint64 shardId, const char *command); +static bool TransmitTableData(PGconn *workerNode, uint64 shardId, + uint64 shardMaxSize, copy_options *stageOptions, + uint64 currentFileOffset, uint64 *nextFileOffset); +static bool TransmitFile(PGconn *workerNode, const char *localPath, const char *remotePath); +static bool FileStreamOK(const copy_options *stageOptions); +static PQExpBuffer CreateCopyQueryString(const char *tableName, const char *columnList, + const char *afterToFrom); +static int64 ShardTableSize(PGconn *workerNode, const char *tablename, uint64 shardId); +static int64 ShardFileSize(PGconn *workerNode, const char *tablename, uint64 shardId); +static int64 ShardColumnarTableSize(PGconn *workerNode, const char *tablename, + uint64 shardId); +static bool ShardMinMaxValues(PGconn *workerNode, const char *tablename, + const char *partitionKey, ShardMetadata *shardMetadata); + + +/* + * DoStageData augments psql's copy meta-command with data loading functionality + * for sharded databases. The function parses given command options, determines + * the table name, and then retrieves table related metadata from the master. + * + * The function later breaks input data into shards of fixed sizes, and uploads + * these shards in a loop. In this loop, the function asks the master node to + * create metadata for a new shard and return shard metadata. The function then + * uses these metadata, contacts worker nodes, and creates shards on them. + * + * Once all shards are created and staged (and all input data consumed), the + * function finalizes shard metadata with the master, and returns true. In case + * of a failure, the function aborts from finalizing shard metadata, and returns + * false. + */ +bool +DoStageData(const char *stageCommand) +{ + TableMetadata *tableMetadata = NULL; + copy_options *copyOptions = NULL; + copy_options *stageOptions = NULL; + ShardMetadata *shardMetadataList[MAX_SHARD_UPLOADS]; + uint32 shardCount = 0; + uint32 shardIndex = 0; + uint64 fileSize = 0; + uint64 currentFileOffset = 0; + uint64 nextFileOffset = 0; + char tableStorageType = 0; + char partitionMethod = 0; + bool metadataOK = false; + bool fileOK = false; + + /* parse the stage command, and validate its options */ + copyOptions = parse_slash_copy(stageCommand); + if (copyOptions == NULL) + { + return false; + } + else if (copyOptions->from == false) + { + psql_error("\\stage: staging tablename to filename unsupported\n"); + free_copy_options(copyOptions); + + return false; + } + else if (copyOptions->file == NULL) + { + /* extending this function to read data from stdin should be easy */ + psql_error("\\stage: staging currently supports file inputs only\n"); + free_copy_options(copyOptions); + + return false; + } + + /* parse in the additional options needed for staging */ + stageOptions = ParseStageOptions(copyOptions); + + /* get file size */ + fileOK = FileSize(stageOptions->file, &fileSize); + if (!fileOK) + { + free_copy_options(stageOptions); + return false; + } + + /* allocate and retrieve table related metadata */ + tableMetadata = InitTableMetadata(stageOptions->tableName); + if (tableMetadata == NULL) + { + free_copy_options(stageOptions); + return false; + } + + /* check that options specified by the user are reasonable */ + tableStorageType = tableMetadata->tableStorageType; + if (tableStorageType == STORAGE_TYPE_FOREIGN) + { + if (stageOptions->after_tofrom != NULL) + { + psql_error("\\stage: options for foreign tables are not supported\n"); + free_copy_options(stageOptions); + FreeTableMetadata(tableMetadata); + + return false; + } + } + + /* check that we are not staging into a hash partitioned table */ + partitionMethod = tableMetadata->partitionMethod; + if (partitionMethod == DISTRIBUTE_BY_HASH) + { + psql_error("\\stage: staging data into hash partitioned tables is not " + "supported\n"); + free_copy_options(stageOptions); + FreeTableMetadata(tableMetadata); + + return false; + } + + /* check that the foreign table options are suitable for the \stage command */ + if (tableStorageType == STORAGE_TYPE_COLUMNAR) + { + bool tableOptionsOK = ColumnarTableOptionsOK(tableMetadata->logicalRelid); + if (!tableOptionsOK) + { + return false; /* error message already displayed */ + } + } + + memset(shardMetadataList, 0, sizeof(shardMetadataList)); + shardCount = (fileSize / tableMetadata->shardMaxSize) + 1; + + /* foreign files may be compressed, and we can't split them yet */ + if (tableStorageType == STORAGE_TYPE_FOREIGN) + { + shardCount = 1; + } + + if (shardCount > MAX_SHARD_UPLOADS) + { + psql_error("\\stage: cannot stage more than %u shards\n", MAX_SHARD_UPLOADS); + free_copy_options(stageOptions); + FreeTableMetadata(tableMetadata); + + return false; + } + + /* while more file data left, continue to create and upload shards */ + while (currentFileOffset < fileSize) + { + ShardMetadata *shardMetadata = NULL; + const char *tableName = stageOptions->tableName; + const char *dbName = PQdb(pset.db); + char shardIdString[MAXPGPATH]; + uint64 shardId = 0; + uint32 nodeIndex = 0; + uint32 stageCount = 0; + + /* + * Allocate and retrieve metadata for new shard on the basis of the shard + * placement policy. + */ + shardMetadata = InitShardMetadata(tableMetadata->shardPlacementPolicy); + if (shardMetadata == NULL) + { + /* + * For now, we simply abort staging by not finalizing shard metadata + * on the master. This leaves invisible shard data on worker nodes. + */ + FreeCommonStageData(stageOptions, tableMetadata, shardMetadataList); + + return false; /* abort immediately */ + } + + /* save allocated shard metadata */ + shardMetadataList[shardIndex] = shardMetadata; + shardIndex++; + + shardId = shardMetadata->shardId; + snprintf(shardIdString, MAXPGPATH, UINT64_FORMAT, shardId); + + /* + * We now have table and shard metadata, and can start uploading shard + * data to remote nodes. For this, we need to upload replicas to a + * predetermined number of remote nodes. If we fail to create and upload + * shards on a remote node, or to fetch shard statistics from it, we + * retry with the next node in the list. If we aren't able to stage to + * enough nodes, we error out. + */ + for (nodeIndex = 0; nodeIndex < shardMetadata->nodeCount; nodeIndex++) + { + char *remoteNodeName = shardMetadata->nodeNameList[nodeIndex]; + uint32 remoteNodePort = shardMetadata->nodePortList[nodeIndex]; + + PGconn *remoteNode = NULL; + bool shardReplicaCreated = false; + bool shardStageFailed = false; + bool minMaxOK = false; + int64 shardSize = 0; + + remoteNode = ConnectToWorkerNode(remoteNodeName, remoteNodePort, dbName); + if (remoteNode == NULL) + { + shardMetadata->nodeStageList[nodeIndex] = false; + continue; + } + + if (tableStorageType == STORAGE_TYPE_TABLE || + tableStorageType == STORAGE_TYPE_COLUMNAR) + { + shardReplicaCreated = StageTableData(remoteNode, shardId, tableMetadata, + stageOptions, currentFileOffset, + &nextFileOffset); + } + else if (tableStorageType == STORAGE_TYPE_FOREIGN) + { + shardReplicaCreated = StageForeignData(remoteNode, shardId, + tableMetadata, stageOptions); + nextFileOffset = fileSize; + } + + if (!shardReplicaCreated) + { + shardStageFailed = true; + } + + /* if this is the first successful shard replica, fetch stats from it */ + if (!shardStageFailed && stageCount == 0) + { + /* fetch shard size */ + if (tableStorageType == STORAGE_TYPE_TABLE) + { + shardSize = ShardTableSize(remoteNode, tableName, shardId); + } + else if (tableStorageType == STORAGE_TYPE_FOREIGN) + { + shardSize = ShardFileSize(remoteNode, tableName, shardId); + } + else if (tableStorageType == STORAGE_TYPE_COLUMNAR) + { + shardSize = ShardColumnarTableSize(remoteNode, tableName, shardId); + } + + /* fetch partition key's min/max values in shard */ + minMaxOK = ShardMinMaxValues(remoteNode, tableName, + tableMetadata->partitionKey, shardMetadata); + + if (shardSize >= 0 && minMaxOK) + { + shardMetadata->shardSize = shardSize; + } + else + { + shardStageFailed = true; + } + } + + if (shardStageFailed) + { + shardMetadata->nodeStageList[nodeIndex] = false; + } + else + { + shardMetadata->nodeStageList[nodeIndex] = true; + stageCount++; + } + + PQfinish(remoteNode); + + if (stageCount == tableMetadata->shardReplicaCount) + { + break; + } + } + + /* check that we staged data to enough nodes */ + if (stageCount < tableMetadata->shardReplicaCount) + { + psql_error("\\stage: failed to replicate shard to enough replicas\n"); + + FreeCommonStageData(stageOptions, tableMetadata, shardMetadataList); + + return false; + } + + /* update current file offset */ + currentFileOffset = nextFileOffset; + + } /* while more file data left for sharding */ + + /* + * At this stage, we have all file data staged into shards. We now finalize + * these shards by uploading their metadata information to the master. + */ + metadataOK = MasterInsertShardMetadata(tableMetadata->logicalRelid, + tableStorageType, shardMetadataList); + + /* clean up */ + FreeCommonStageData(stageOptions, tableMetadata, shardMetadataList); + + return metadataOK; +} + + +/* Canonicalize given file name, and determine file's size. */ +static bool +FileSize(char *filename, uint64 *fileSize) +{ + struct stat fileStat; + + canonicalize_path(filename); + if (stat(filename, &fileStat) < 0) + { + psql_error("%s: %s\n", filename, strerror(errno)); + return false; + } + + (*fileSize) = fileStat.st_size; + + return true; +} + + +/* + * ConnectToWorkerNode establishes connection to the worker node, and returns + * the connection. If connection to the node fails, the function returns null. + */ +static PGconn * +ConnectToWorkerNode(const char *nodeName, uint32 nodePort, const char *nodeDatabase) +{ + PGconn *workerNode = NULL; + const char *nodeOptions = NULL; + const char *nodeTty = NULL; + char nodePortString[MAXPGPATH]; + char connInfoString[MAXPGPATH]; + + /* transcribe port number and connection info to their string values */ + snprintf(nodePortString, MAXPGPATH, "%u", nodePort); + snprintf(connInfoString, MAXPGPATH, CONN_INFO_TEMPLATE, + nodeDatabase, CLIENT_CONNECT_TIMEOUT); + + workerNode = PQsetdb(nodeName, nodePortString, nodeOptions, nodeTty, connInfoString); + + if (PQstatus(workerNode) != CONNECTION_OK) + { + psql_error("worker node connection failed with %s", PQerrorMessage(workerNode)); + + PQfinish(workerNode); + workerNode = NULL; + } + + return workerNode; +} + + +/* + * ExecuteRemoteCommand executes commands on given remote node. The function + * uses the text protocol both for parameters and results; and on success + * returns the results object. On failure, the function emits an error message, + * clears results and returns null. + */ +static PGresult * +ExecuteRemoteCommand(PGconn *remoteConnection, const char *remoteCommand, + const char **parameterValues, int parameterCount) +{ + PGresult *result = NULL; + + const Oid *parameterType = NULL; /* let the backend deduce type */ + const int *parameterLength = NULL; /* text params do not need length */ + const int *parameterFormat = NULL; /* text params have Null by default */ + const int resultFormat = 0; /* ask for results in text format */ + + result = PQexecParams(remoteConnection, remoteCommand, + parameterCount, parameterType, parameterValues, + parameterLength, parameterFormat, resultFormat); + + if (PQresultStatus(result) != PGRES_COMMAND_OK && + PQresultStatus(result) != PGRES_TUPLES_OK) + { + psql_error("remote command \"%s\" failed with %s", + remoteCommand, PQerrorMessage(remoteConnection)); + PQclear(result); + + return NULL; + } + + return result; +} + + +/* + * InitTableMetadata allocates memory for table related metadata, and then + * executes remote calls on the master to initialize these metadata. On success, + * the function returns the fully initialized table metadata; on failure, it + * returns null. + */ +static TableMetadata * +InitTableMetadata(const char *tableName) +{ + TableMetadata *tableMetadata = NULL; + bool commandOK = true; + + tableMetadata = (TableMetadata *) pg_malloc0(sizeof(TableMetadata)); + + commandOK = MasterGetTableMetadata(tableName, tableMetadata); + if (!commandOK) + { + FreeTableMetadata(tableMetadata); + return NULL; + } + + commandOK = MasterGetTableDDLEvents(tableName, tableMetadata); + if (!commandOK) + { + FreeTableMetadata(tableMetadata); + return NULL; + } + + return tableMetadata; +} + + +/* Frees memory allocated to table metadata structure. */ +static void +FreeTableMetadata(TableMetadata *tableMetadata) +{ + if (tableMetadata->ddlEventList != NULL) + { + uint32 eventIndex = 0; + uint32 eventCount = tableMetadata->ddlEventCount; + + for (eventIndex = 0; eventIndex < eventCount; eventIndex++) + { + char *ddlEvent = tableMetadata->ddlEventList[eventIndex]; + + free(ddlEvent); + ddlEvent = NULL; + } + } + + free(tableMetadata->ddlEventList); + free(tableMetadata->partitionKey); + + free(tableMetadata); +} + + +/* + * InitShardMetadata allocates memory for shard metadata, and then executes + * remote calls on the master to initialize these metadata. On success, the + * function returns the fully initialized shard metadata; on failure, it returns + * null. + */ +static ShardMetadata * +InitShardMetadata(int shardPlacementPolicy) +{ + ShardMetadata *shardMetadata = NULL; + uint32 nodeCount = 0; + bool commandOK = true; + + shardMetadata = (ShardMetadata *) pg_malloc0(sizeof(ShardMetadata)); + + commandOK = MasterGetNewShardId(shardMetadata); + if (!commandOK) + { + FreeShardMetadata(shardMetadata); + return NULL; + } + + commandOK = MasterGetCandidateNodes(shardMetadata, shardPlacementPolicy); + if (!commandOK) + { + FreeShardMetadata(shardMetadata); + return NULL; + } + + nodeCount = shardMetadata->nodeCount; + shardMetadata->nodeStageList = (bool *) pg_malloc0(nodeCount * sizeof(bool)); + shardMetadata->shardMinValue = NULL; + shardMetadata->shardMaxValue = NULL; + shardMetadata->shardSize = 0; + + return shardMetadata; +} + + +/* Frees memory allocated to shard metadata structure. */ +static void +FreeShardMetadata(ShardMetadata *shardMetadata) +{ + if (shardMetadata->nodeNameList != NULL) + { + uint32 nodeIndex = 0; + uint32 nodeCount = shardMetadata->nodeCount; + + for (nodeIndex = 0; nodeIndex < nodeCount; nodeIndex++) + { + char *nodeName = shardMetadata->nodeNameList[nodeIndex]; + + free(nodeName); + nodeName = NULL; + } + } + + free(shardMetadata->nodeNameList); + free(shardMetadata->nodePortList); + + free(shardMetadata->nodeStageList); + free(shardMetadata->shardMinValue); + free(shardMetadata->shardMaxValue); + + free(shardMetadata); +} + + +/* Frees memory allocated to all shard metadata structures in given list. */ +static void +FreeShardMetadataList(ShardMetadata **shardMetadataList) +{ + uint32 listIndex = 0; + for (listIndex = 0; listIndex < MAX_SHARD_UPLOADS; listIndex++) + { + ShardMetadata *shardMetadata = shardMetadataList[listIndex]; + if (shardMetadata != NULL) + { + FreeShardMetadata(shardMetadata); + shardMetadata = NULL; + } + } +} + + +/* Frees memory common to all staging operations. */ +static void +FreeCommonStageData(copy_options *stageOptions, TableMetadata *tableMetadata, + ShardMetadata **shardMetadataList) +{ + free_copy_options(stageOptions); + FreeTableMetadata(tableMetadata); + FreeShardMetadataList(shardMetadataList); +} + + +/* + * ColumnarTableOptionsOK checks if the foreign table options for the distributed + * cstore_fdw table are suitable for staging or not. It returns true if they are + * and false if they are not. + */ +static bool +ColumnarTableOptionsOK(Oid relationOid) +{ + PGconn *masterNode = pset.db; + PGresult *queryResult = NULL; + ExecStatusType queryStatus = 0; + bool optionsOK = true; + + PQExpBuffer queryString = createPQExpBuffer(); + appendPQExpBuffer(queryString, GET_COLUMNAR_TABLE_FILENAME_OPTION, relationOid); + + /* get the filename option for the given cstore_fdw table */ + queryResult = PQexec(masterNode, queryString->data); + + queryStatus = PQresultStatus(queryResult); + if (queryStatus == PGRES_TUPLES_OK) + { + int tupleCount = PQntuples(queryResult); + Assert(tupleCount <= 1); + if (tupleCount == 1) + { + /* + * Since the result has one row, it implies that the filename + * option was specified, which is not allowed for distributed + * cstore_fdw tables. So, we error out. + */ + psql_error("\\stage: filename option is not allowed for distributed " + "columnar tables\n"); + optionsOK = false; + } + } + else + { + psql_error("\\stage: %s", PQerrorMessage(masterNode)); + optionsOK = false; + } + + PQclear(queryResult); + destroyPQExpBuffer(queryString); + + return optionsOK; +} + + +/* + * ExtendTablename appends shardId to given tablename, and returns extended name + * in a dynamically allocated string. + */ +static char * +ExtendTablename(const char *baseTablename, uint64 shardId) +{ + char *extendedTablename = (char *) pg_malloc0(NAMEDATALEN); + + snprintf(extendedTablename, NAMEDATALEN, "%s%c" UINT64_FORMAT, + baseTablename, SHARD_NAME_SEPARATOR, shardId); + + return extendedTablename; +} + + +/* Helper method that converts result value string to 64-bit unsigned integer. */ +static uint64 +GetValueUint64(const PGresult *result, int rowNumber, int columnNumber) +{ + char *valueString = NULL; + char *valueStringEnd = NULL; + uint64 value = 0; + + valueString = PQgetvalue(result, rowNumber, columnNumber); + if (valueString == NULL || (*valueString) == '\0') + { + return INVALID_UINT64; + } + + errno = 0; + value = strtoull(valueString, &valueStringEnd, 0); + + if (errno != 0 || (*valueStringEnd) != '\0') + { + return INVALID_UINT64; + } + + /* Server returned values for staging should never equal to "0". */ + Assert(value != INVALID_UINT64); + + return value; +} + + +/* + * MasterGetTableMetadata fetches from the master metadata related to a + * particular table. The function then parses relevant fields, assigns them to + * master metadata, and on success returns true. On failure, the function + * returns false. + */ +static bool +MasterGetTableMetadata(const char *tableName, TableMetadata *tableMetadata) +{ + const char *remoteCommand = MASTER_GET_TABLE_METADATA; + const char *parameterValue[1] = { tableName }; + const int parameterCount = 1; + int logicalRelidIndex = 0; + int partStorageTypeIndex = 0; + int partMethodIndex = 0; + int partKeyIndex = 0; + int partReplicaCountIndex = 0; + int partMaxSizeIndex = 0; + int partPlacementPolicyIndex = 0; + + PGconn *masterNode = pset.db; + PGresult *result = NULL; + char *tableStorageType = NULL; + char *partitionMethod = NULL; + char *partitionKey = NULL; + int partitionKeyLength = 0; + uint64 logicalRelid = 0; + uint64 shardReplicaCount = 0; + uint64 shardMaxSize = 0; + uint64 shardPlacementPolicy = 0; + + /* fetch table metadata for partitioning */ + result = ExecuteRemoteCommand(masterNode, remoteCommand, + parameterValue, parameterCount); + if (result == NULL) + { + return false; /* error message already displayed */ + } + + /* find column numbers associated with column names */ + logicalRelidIndex = PQfnumber(result, LOGICAL_RELID_FIELD); + partStorageTypeIndex = PQfnumber(result, PART_STORAGE_TYPE_FIELD); + partMethodIndex = PQfnumber(result, PART_METHOD_FIELD); + partKeyIndex = PQfnumber(result, PART_KEY_FIELD); + partReplicaCountIndex = PQfnumber(result, PART_REPLICA_COUNT_FIELD); + partMaxSizeIndex = PQfnumber(result, PART_MAX_SIZE_FIELD); + partPlacementPolicyIndex = PQfnumber(result, PART_PLACEMENT_POLICY_FIELD); + + /* fetch variable length response */ + partitionKey = PQgetvalue(result, 0, partKeyIndex); + partitionKeyLength = PQgetlength(result, 0, partKeyIndex); + + /* fetch fixed length responses and convert those that are integers */ + tableStorageType = PQgetvalue(result, 0, partStorageTypeIndex); + partitionMethod = PQgetvalue(result, 0, partMethodIndex); + logicalRelid = GetValueUint64(result, 0, logicalRelidIndex); + shardReplicaCount = GetValueUint64(result, 0, partReplicaCountIndex); + shardMaxSize = GetValueUint64(result, 0, partMaxSizeIndex); + shardPlacementPolicy = GetValueUint64(result, 0, partPlacementPolicyIndex); + + if (partitionKeyLength <= 0 || logicalRelid == INVALID_UINT64 || + shardReplicaCount == INVALID_UINT64 || shardMaxSize == INVALID_UINT64 || + shardPlacementPolicy == INVALID_UINT64) + { + psql_error("remote command \"%s:%s\" failed with invalid table metadata\n", + remoteCommand, tableName); + PQclear(result); + + return false; + } + + /* set metadata related to the table */ + tableMetadata->partitionKey = (char *) pg_malloc0(partitionKeyLength + 1); + strncpy(tableMetadata->partitionKey, partitionKey, partitionKeyLength + 1); + + tableMetadata->tableStorageType = tableStorageType[0]; + tableMetadata->partitionMethod = partitionMethod[0]; + tableMetadata->logicalRelid = (uint32) logicalRelid; + tableMetadata->shardReplicaCount = (uint32) shardReplicaCount; + tableMetadata->shardMaxSize = (uint64) shardMaxSize; + tableMetadata->shardPlacementPolicy = (uint32) shardPlacementPolicy; + + PQclear(result); + + return true; +} + + +/* + * MasterGetTableDDLEvents fetches from the master a list of DDL events that + * relate to a particular table. The function then deep copies these DDL events + * to metadata, and on success returns true. On failure, the function returns + * false. + */ +static bool +MasterGetTableDDLEvents(const char *tableName, TableMetadata *tableMetadata) +{ + const char *remoteCommand = MASTER_GET_TABLE_DDL_EVENTS; + const char *parameterValue[1] = { tableName }; + const int parameterCount = 1; + + PGconn *masterNode = pset.db; + PGresult *result = NULL; + int ddlEventCount = 0; + int ddlEventIndex = 0; + + /* fetch DDL events needed for table creation */ + result = ExecuteRemoteCommand(masterNode, remoteCommand, + parameterValue, parameterCount); + if (result == NULL) + { + return false; + } + + /* check that we have at least one DDL event */ + ddlEventCount = PQntuples(result); + if (ddlEventCount <= 0) + { + psql_error("remote command \"%s:%s\" failed to fetch DDL events\n", + remoteCommand, tableName); + PQclear(result); + + return false; + } + + /* allocate memory for DDL event list in metadata */ + tableMetadata->ddlEventList = (char **) pg_malloc0(ddlEventCount * sizeof(char *)); + tableMetadata->ddlEventCount = ddlEventCount; + + /* walk over fetched DDL event list, and assign them to metadata */ + for (ddlEventIndex = 0; ddlEventIndex < ddlEventCount; ddlEventIndex++) + { + char *ddlEvent = NULL; + char *ddlEventValue = PQgetvalue(result, ddlEventIndex, 0); + int ddlEventLength = PQgetlength(result, ddlEventIndex, 0); + + if (ddlEventLength <= 0) + { + psql_error("remote command \"%s:%s\" fetched empty DDL event\n", + remoteCommand, tableName); + PQclear(result); + + return false; + } + + /* deep copy DDL event and assign to metadata */ + ddlEvent = (char *) pg_malloc0(ddlEventLength + 1); + strncpy(ddlEvent, ddlEventValue, ddlEventLength + 1); + + tableMetadata->ddlEventList[ddlEventIndex] = ddlEvent; + } + + PQclear(result); + + return true; +} + + +/* + * MasterGetNewShardId fetches from the master a global shardId for the new + * shard to be created. The function then sets the shardId field in metadata, + * and on success returns true. On failure, the function returns false. + */ +static bool +MasterGetNewShardId(ShardMetadata *shardMetadata) +{ + const char *remoteCommand = MASTER_GET_NEW_SHARDID; + const char **parameterValue = NULL; + const int parameterCount = 0; + + PGconn *masterNode = pset.db; + PGresult *result = NULL; + uint64 shardId = 0; + + /* fetch unique shardId for shard to be created */ + result = ExecuteRemoteCommand(masterNode, remoteCommand, + parameterValue, parameterCount); + if (result == NULL) + { + return false; + } + + /* get shard value string and convert it to 64-bit integer */ + shardId = GetValueUint64(result, 0, 0); + if (shardId == INVALID_UINT64) + { + psql_error("remote command \"%s\" failed with invalid shardId\n", + remoteCommand); + PQclear(result); + + return false; + } + + /* set metadata shardId; clear results */ + shardMetadata->shardId = shardId; + PQclear(result); + + return true; +} + + +/* + * MasterGetCandidateNodes fetches from the master a list of worker node names + * and port numbers for staging (uploading) shard data on the basis of the + * shard placement policy passed to it. The function then parses and deep copies + * these node names and port numbers to metadata, and on success returns true. + * On failure, the function returns false. + */ +static bool +MasterGetCandidateNodes(ShardMetadata *shardMetadata, int shardPlacementPolicy) +{ + const char *remoteCommand = NULL; + const char **parameterValue = NULL; + int parameterCount = 0; + char shardIdString[NAMEDATALEN]; + int nodeNameIndex = 0; + int nodePortIndex = 0; + + PGconn *masterNode = pset.db; + PGresult *result = NULL; + int nodeCount = 0; + int nodeIndex = 0; + + /* + * We choose the remote command for fetching node names and node ports, and the + * parameters to be passed to it on the basis of the shard placement policy. + */ + Assert(shardPlacementPolicy == SHARD_PLACEMENT_LOCAL_NODE_FIRST || + shardPlacementPolicy == SHARD_PLACEMENT_ROUND_ROBIN); + if (shardPlacementPolicy == SHARD_PLACEMENT_LOCAL_NODE_FIRST) + { + remoteCommand = MASTER_GET_LOCAL_FIRST_CANDIDATE_NODES; + parameterCount = 0; + + /* + * The master uses its connection's remote socket address to determine + * the client's hostname. The master then uses this hostname to allocate + * the first candidate node in the local node first policy. For all of + * this to happen, we should have connected to the master over TCP/IP. + */ + if (masterNode->laddr.addr.ss_family != AF_INET && + masterNode->laddr.addr.ss_family != AF_INET6) + { + psql_error("remote command \"%s\" needs TCP/IP connection to master node\n", + remoteCommand); + + return false; + } + } + else if (shardPlacementPolicy == SHARD_PLACEMENT_ROUND_ROBIN) + { + remoteCommand = MASTER_GET_ROUND_ROBIN_CANDIDATE_NODES; + parameterCount = 1; + + /* convert parameter to its string representation */ + snprintf(shardIdString, NAMEDATALEN, UINT64_FORMAT, shardMetadata->shardId); + + parameterValue = (const char **) pg_malloc0(parameterCount * sizeof(char *)); + parameterValue[0] = shardIdString; + } + + /* fetch worker node name/port list for uploading shard data */ + result = ExecuteRemoteCommand(masterNode, remoteCommand, + parameterValue, parameterCount); + + if (parameterValue != NULL) + { + free(parameterValue); + } + + if (result == NULL) + { + return false; + } + + /* find column numbers associated with column names */ + nodeNameIndex = PQfnumber(result, NODE_NAME_FIELD); + nodePortIndex = PQfnumber(result, NODE_PORT_FIELD); + if (nodeNameIndex < 0 || nodePortIndex < 0) + { + psql_error("remote command \"%s\" failed with invalid response\n", + remoteCommand); + PQclear(result); + + return false; + } + + nodeCount = PQntuples(result); + if (nodeCount <= 0) + { + psql_error("remote command \"%s\" failed to fetch worker nodes\n", + remoteCommand); + PQclear(result); + + return false; + } + + /* allocate memory for node name/port list in metadata */ + shardMetadata->nodeNameList = (char **) pg_malloc0(nodeCount * sizeof(char *)); + shardMetadata->nodePortList = (uint32 *) pg_malloc0(nodeCount * sizeof(uint32)); + shardMetadata->nodeCount = nodeCount; + + /* walk over fetched node name/port list, and assign them to metadata */ + for (nodeIndex = 0; nodeIndex < nodeCount; nodeIndex++) + { + char *nodeName = NULL; + uint64 nodePort = 0; + + char *nodeNameValue = PQgetvalue(result, nodeIndex, nodeNameIndex); + int nodeNameLength = PQgetlength(result, nodeIndex, nodeNameIndex); + + if (nodeNameLength <= 0) + { + psql_error("remote command \"%s\" fetched empty node name\n", + remoteCommand); + PQclear(result); + + return false; + } + + /* deep copy node name and assign to metadata */ + nodeName = (char *) pg_malloc0(nodeNameLength + 1); + strncpy(nodeName, nodeNameValue, nodeNameLength + 1); + + shardMetadata->nodeNameList[nodeIndex] = nodeName; + + /* convert port value string to 64-bit integer, and assign to metadata */ + nodePort = GetValueUint64(result, nodeIndex, nodePortIndex); + if (nodePort == INVALID_UINT64) + { + psql_error("remote command \"%s\" failed to fetch valid port number\n", + remoteCommand); + PQclear(result); + + return false; + } + + shardMetadata->nodePortList[nodeIndex] = (uint32) nodePort; + } + + PQclear(result); + + return true; +} + + +/* Executes command on the master to insert shard tuple to pg_dist_shard. */ +static bool +MasterInsertShardRow(uint32 logicalRelid, char storageType, + const ShardMetadata *shardMetadata) +{ + const char *remoteCommand = MASTER_INSERT_SHARD_ROW; + const char *parameterValue[5]; + const int parameterCount = 5; + char logicalRelidString[NAMEDATALEN]; + char shardIdString[NAMEDATALEN]; + char storageTypeString[NAMEDATALEN]; + + PGconn *masterNode = pset.db; + PGresult *result = NULL; + + /* convert parameters to their string representations */ + snprintf(logicalRelidString, NAMEDATALEN, "%u", logicalRelid); + snprintf(shardIdString, NAMEDATALEN, UINT64_FORMAT, shardMetadata->shardId); + snprintf(storageTypeString, NAMEDATALEN, "%c", storageType); + + parameterValue[0] = logicalRelidString; + parameterValue[1] = shardIdString; + parameterValue[2] = storageTypeString; + parameterValue[3] = shardMetadata->shardMinValue; + parameterValue[4] = shardMetadata->shardMaxValue; + + /* insert shard metadata to master's system catalogs */ + result = ExecuteRemoteCommand(masterNode, remoteCommand, + parameterValue, parameterCount); + if (result == NULL) + { + return false; + } + + PQclear(result); + return true; +} + + +/* + * MasterInsertPlacementRows executes commands on the master node to insert + * shard placement tuples to pg_dist_shard_placement. + */ +static bool +MasterInsertPlacementRows(const ShardMetadata *shardMetadata) +{ + const char *remoteCommand = MASTER_INSERT_PLACEMENT_ROW; + const char *parameterValue[5]; + const int parameterCount = 5; + char shardIdString[NAMEDATALEN]; + char shardLengthString[NAMEDATALEN]; + char nodePortString[NAMEDATALEN]; + + PGconn *masterNode = pset.db; + PGresult *result = NULL; + uint32 nodeIndex = 0; + + /* convert parameters to their string representations */ + snprintf(shardIdString, NAMEDATALEN, UINT64_FORMAT, shardMetadata->shardId); + snprintf(shardLengthString, NAMEDATALEN, UINT64_FORMAT, shardMetadata->shardSize); + + parameterValue[0] = shardIdString; + parameterValue[1] = FILE_FINALIZED; + parameterValue[2] = shardLengthString; + + for (nodeIndex = 0; nodeIndex < shardMetadata->nodeCount; nodeIndex++) + { + bool staged = shardMetadata->nodeStageList[nodeIndex]; + if (staged) + { + char *nodeName = shardMetadata->nodeNameList[nodeIndex]; + uint32 nodePort = shardMetadata->nodePortList[nodeIndex]; + + /* convert parameter to its string representation */ + snprintf(nodePortString, NAMEDATALEN, "%u", nodePort); + + parameterValue[3] = nodeName; + parameterValue[4] = nodePortString; + + result = ExecuteRemoteCommand(masterNode, remoteCommand, + parameterValue, parameterCount); + if (result == NULL) + { + return false; + } + + PQclear(result); + } + } + + return true; +} + + +/* + * MasterInsertShardMetadata finalizes with the master metadata for all shards + * staged to worker nodes. The function executes shard metadata insert commands + * within a single transaction so that either all or none of the metadata are + * finalized. On success, the function commits the transaction and returns true. + * On failure, the function rolls back the transaction and returns false. + */ +static bool +MasterInsertShardMetadata(uint32 logicalRelid, char storageType, + ShardMetadata **shardMetadataList) +{ + PGconn *masterNode = pset.db; + uint32 listIndex = 0; + bool issued = true; + bool metadataOK = true; + + issued = IssueTransactionCommand(masterNode, BEGIN_COMMAND); + if (!issued) + { + return false; + } + + for (listIndex = 0; listIndex < MAX_SHARD_UPLOADS; listIndex++) + { + ShardMetadata *shardMetadata = shardMetadataList[listIndex]; + if (shardMetadata != NULL) + { + bool shardRowOK = MasterInsertShardRow(logicalRelid, storageType, + shardMetadata); + bool workerRowOK = MasterInsertPlacementRows(shardMetadata); + + if (!shardRowOK || !workerRowOK) + { + IssueTransactionCommand(masterNode, ROLLBACK_COMMAND); + + metadataOK = false; + break; + } + } + } + + if (metadataOK) + { + issued = IssueTransactionCommand(masterNode, COMMIT_COMMAND); + if (!issued) + { + return false; + } + } + + return metadataOK; +} + + +/* Issues given transaction command on the remote node. */ +static bool +IssueTransactionCommand(PGconn *connection, const char *command) +{ + PGresult *result = PQexec(connection, command); + ExecStatusType resultStatus = PQresultStatus(result); + + if (resultStatus != PGRES_COMMAND_OK) + { + psql_error("%s", PQerrorMessage(connection)); + PQclear(result); + + return false; + } + + PQclear(result); + return true; +} + + +/* + * StageTableData creates the table on the remote node, and then uses the + * copy protocol to upload data to the table. On success, the function updates + * given file offset, commits the transaction, and returns true. On failure, the + * function rolls back the transaction and returns false. + */ +static bool +StageTableData(PGconn *workerNode, uint64 shardId, + TableMetadata *tableMetadata, copy_options *stageOptions, + uint64 currentFileOffset, uint64 *nextFileOffset) +{ + bool issued = false; + bool createOK = false; + bool transmitOK = false; + + /* start explicit transaction; this also skips WAL-logging */ + issued = IssueTransactionCommand(workerNode, BEGIN_COMMAND); + if (!issued) + { + return false; + } + + createOK = CreateRegularTable(workerNode, shardId, tableMetadata); + if (!createOK) + { + IssueTransactionCommand(workerNode, ROLLBACK_COMMAND); + return false; + } + + transmitOK = TransmitTableData(workerNode, shardId, tableMetadata->shardMaxSize, + stageOptions, currentFileOffset, nextFileOffset); + if (!transmitOK) + { + IssueTransactionCommand(workerNode, ROLLBACK_COMMAND); + return false; + } + + issued = IssueTransactionCommand(workerNode, COMMIT_COMMAND); + if (!issued) + { + return false; + } + + return true; +} + + +/* + * StageForeignData determines the remote file path to upload the given file, + * creates the foreign table on the remote node, and uploads the file to the + * remote node at the determined path. Then, it commits the transaction and + * returns true. On failure, the function rolls back the transaction and + * returns false. + */ +static bool +StageForeignData(PGconn *workerNode, uint64 shardId, TableMetadata *tableMetadata, + copy_options *stageOptions) +{ + bool issued = false; + bool transmitOK = false; + bool createOK = false; + + char remoteFilePath[MAXPGPATH]; + char *extendedTableName = ExtendTablename(stageOptions->tableName, shardId); + snprintf(remoteFilePath, MAXPGPATH, "%s/%s", FOREIGN_CACHED_DIR, extendedTableName); + free(extendedTableName); + + /* start explicit transaction */ + issued = IssueTransactionCommand(workerNode, BEGIN_COMMAND); + if (!issued) + { + return false; + } + + createOK = CreateForeignTable(workerNode, shardId, tableMetadata, + stageOptions->tableName, remoteFilePath); + if (!createOK) + { + IssueTransactionCommand(workerNode, ROLLBACK_COMMAND); + return false; + } + + transmitOK = TransmitFile(workerNode, stageOptions->file, remoteFilePath); + if (!transmitOK) + { + IssueTransactionCommand(workerNode, ROLLBACK_COMMAND); + return false; + } + + issued = IssueTransactionCommand(workerNode, COMMIT_COMMAND); + if (!issued) + { + return false; + } + + return true; +} + + +/* + * CreateRegularTable executes DDL commands to create the table on the worker + * node. On success the function returns true, otherwise it returns false. + */ +static bool +CreateRegularTable(PGconn *workerNode, int64 shardId, TableMetadata *tableMetadata) +{ + bool createOK = true; + const uint32 ddlEventCount = tableMetadata->ddlEventCount; + uint32 ddlEventIndex = 0; + + /* execute DDL statements on remote node to create table and indexes */ + for (ddlEventIndex = 0; ddlEventIndex < ddlEventCount; ddlEventIndex++) + { + char *ddlEvent = tableMetadata->ddlEventList[ddlEventIndex]; + + bool ddlApplied = ApplyShardDDLCommand(workerNode, shardId, ddlEvent); + if (!ddlApplied) + { + createOK = false; + break; + } + } + + return createOK; +} + + +/* + * CreateForeignTable executes DDL commands to create the foreign table on the + * worker node, and then sets the foreign table's filename to the given file + * path. On success the function returns true, otherwise it returns false. + */ +static bool +CreateForeignTable(PGconn *workerNode, uint64 shardId, TableMetadata *tableMetaData, + const char *tableName, const char *filePath) +{ + bool createOK = false; + bool alterQueryOK = true; + PQExpBuffer alterQueryString = NULL; + uint32 ddlEventIndex = 0; + uint32 ddlEventCount = tableMetaData->ddlEventCount; + + /* replay DDL commands to create foreign table */ + for (ddlEventIndex = 0; ddlEventIndex < ddlEventCount; ddlEventIndex++) + { + char *ddlEvent = tableMetaData->ddlEventList[ddlEventIndex]; + + bool ddlApplied = ApplyShardDDLCommand(workerNode, shardId, ddlEvent); + if (!ddlApplied) + { + return false; + } + } + + /* then issue DDL command to set foreign table's file path */ + alterQueryString = createPQExpBuffer(); + appendPQExpBuffer(alterQueryString, SET_FOREIGN_TABLE_FILENAME, + tableName, filePath); + + alterQueryOK = ApplyShardDDLCommand(workerNode, shardId, alterQueryString->data); + if (alterQueryOK) + { + createOK = true; + } + + destroyPQExpBuffer(alterQueryString); + + return createOK; +} + + +/* + * ApplyShardDDLCommand calls remote function on the worker node to extend the + * given ddl command with the shardId, and apply this extended command on the + * worker database. The function then returns its success status. + */ +static bool +ApplyShardDDLCommand(PGconn *workerNode, uint64 shardId, const char *ddlCommand) +{ + const char *remoteCommand = APPLY_SHARD_DDL_COMMAND; + const char *parameterValue[2]; + const int parameterCount = 2; + PGresult *ddlResult = NULL; + + char shardIdString[NAMEDATALEN]; + snprintf(shardIdString, NAMEDATALEN, UINT64_FORMAT, shardId); + + parameterValue[0] = shardIdString; + parameterValue[1] = ddlCommand; + + ddlResult = ExecuteRemoteCommand(workerNode, remoteCommand, + parameterValue, parameterCount); + if (ddlResult == NULL) + { + return false; + } + + PQclear(ddlResult); + return true; +} + + +/* + * TransmitTableData uploads data from the local file to the remote table using + * the copy protocol. On success, the function updates given file offset and + * returns true. On failure, it returns false. + */ +static bool +TransmitTableData(PGconn *workerNode, uint64 shardId, + uint64 shardMaxSize, copy_options *stageOptions, + uint64 currentFileOffset, uint64 *nextFileOffset) +{ + bool transmitOK = true; + bool fileOK = true; + bool closeFileOK = true; + int seeked = 0; + + PQExpBuffer queryString = NULL; + PGresult *copyResult = NULL; + ExecStatusType copyStatus = 0; + bool copyIsBinary = false; + FILE *stageStream = NULL; + char *extendedTablename = NULL; + + /* if file doesn't exists, return immediately */ + fileOK = FileStreamOK((const copy_options *) stageOptions); + if (!fileOK) + { + return false; + } + + /* open a file stream to stage data from, and seek to given file offset */ + stageStream = OpenCopyStream(stageOptions); + if (stageStream == NULL) + { + return false; + } + + seeked = fseeko(stageStream, (off_t) (currentFileOffset), SEEK_SET); + if (seeked < 0) + { + psql_error("%s: %s\n", stageOptions->file, strerror(errno)); + return false; + } + + /* extend table name with shardId for the query */ + extendedTablename = ExtendTablename(stageOptions->tableName, shardId); + + /* + * Now start staging data to the worker table. For this, we first form the + * query string, and then execute the query over the copy protocol. + */ + queryString = CreateCopyQueryString(extendedTablename, stageOptions->columnList, + stageOptions->after_tofrom); + + copyResult = PQexec(workerNode, queryString->data); + + copyStatus = PQresultStatus(copyResult); + copyIsBinary = (bool) PQbinaryTuples(copyResult); + + transmitOK = HandleCopyData(workerNode, copyStatus, copyIsBinary, + stageStream, shardMaxSize); + + /* clean up after remote query */ + PQclear(copyResult); + destroyPQExpBuffer(queryString); + free(extendedTablename); + + /* determine new offset in file */ + if (transmitOK && stageOptions->file != NULL) + { + int64 nextStreamOffset = ftello(stageStream); + if (nextStreamOffset < 0) + { + psql_error("%s: %s\n", stageOptions->file, strerror(errno)); + transmitOK = false; + } + else + { + Assert(nextStreamOffset >= currentFileOffset); + (*nextFileOffset) = nextStreamOffset; + } + } + + closeFileOK = CloseCopyStream(stageOptions, stageStream); + if (!closeFileOK) + { + transmitOK = false; + } + + return transmitOK; +} + + +/* + * TransmitFile uploads file on the local path to the given remote file path on + * worker node. The function uses the copy protocol to upload data, and then + * returns its success status. + */ +static bool +TransmitFile(PGconn *workerNode, const char *localPath, const char *remotePath) +{ + const uint64 copySizeUnlimited = 0; + FILE *transmitStream = NULL; + PQExpBuffer queryString = NULL; + PGresult *copyResult = NULL; + ExecStatusType copyStatus = 0; + bool copyIsBinary = false; + bool transmitOK = false; + int closeStatus = 0; + + transmitStream = fopen(localPath, PG_BINARY_R); + if (transmitStream == NULL) + { + psql_error("%s: %s\n", localPath, strerror(errno)); + + return false; + } + + queryString = createPQExpBuffer(); + appendPQExpBuffer(queryString, TRANSMIT_REGULAR_COMMAND, remotePath); + + /* execute remote query to start uploading data over copy protocol */ + copyResult = PQexec(workerNode, queryString->data); + copyStatus = PQresultStatus(copyResult); + copyIsBinary = (bool) PQbinaryTuples(copyResult); + + PQclear(copyResult); + destroyPQExpBuffer(queryString); + + transmitOK = HandleCopyData(workerNode, copyStatus, copyIsBinary, + transmitStream, copySizeUnlimited); + if (!transmitOK) + { + return false; + } + + closeStatus = fclose(transmitStream); + if (closeStatus != 0) + { + psql_error("%s: %s\n", localPath, strerror(errno)); + + return false; + } + + return true; +} + + +/* Checks if a stream can be opened from the given stage options. */ +static bool +FileStreamOK(const copy_options *stageOptions) +{ + FILE *fileStream = OpenCopyStream(stageOptions); + if (fileStream == NULL) + { + return false; + } + + CloseCopyStream(stageOptions, fileStream); + + return true; +} + + +/* Creates query string for copy command from the given staging options. */ +static PQExpBuffer +CreateCopyQueryString(const char *tableName, const char *columnList, + const char *afterToFrom) +{ + PQExpBuffer queryString = createPQExpBuffer(); + + printfPQExpBuffer(queryString, "COPY "); + appendPQExpBuffer(queryString, "%s ", tableName); + + if (columnList != NULL) + { + appendPQExpBuffer(queryString, "%s ", columnList); + } + + appendPQExpBuffer(queryString, "FROM STDIN "); + + if (afterToFrom != NULL) + { + appendPQExpBufferStr(queryString, afterToFrom); + } + + return queryString; +} + + +/* + * ShardTableSize executes a command on the worker node to determine the size of + * the table representing the shard. On success, the function returns the table + * size on disk. On failure, the function returns -1. + */ +static int64 +ShardTableSize(PGconn *workerNode, const char *tablename, uint64 shardId) +{ + PGresult *result = NULL; + char remoteCommand[MAXPGPATH]; + char *extendedTablename = NULL; + int64 shardTableSize = -1; + + extendedTablename = ExtendTablename(tablename, shardId); + snprintf(remoteCommand, MAXPGPATH, SHARD_TABLE_SIZE_COMMAND, extendedTablename); + + result = PQexec(workerNode, remoteCommand); + if (result == NULL) + { + PQclear(result); + free(extendedTablename); + + return -1; + } + + shardTableSize = (int64) GetValueUint64(result, 0, 0); + if (shardTableSize <= 0) + { + psql_error("remote command \"%s\" fetched invalid table size\n", remoteCommand); + PQclear(result); + free(extendedTablename); + + return -1; + } + + PQclear(result); + free(extendedTablename); + + return shardTableSize; +} + + +/* + * ShardFileSize executes a command on the worker node to determine the size of + * the foreign file represneting the shard. On success, the function returns the + * file size on disk. On failure, the function returns -1. + */ +static int64 +ShardFileSize(PGconn *workerNode, const char *tablename, uint64 shardId) +{ + int64 tableSize = -1; + char remoteFilePath[MAXPGPATH]; + char remoteCommand[MAXPGPATH]; + PGresult *result = NULL; + + char *extendedTableName = ExtendTablename(tablename, shardId); + snprintf(remoteFilePath, MAXPGPATH, "%s/%s", FOREIGN_CACHED_DIR, extendedTableName); + free(extendedTableName); + + snprintf(remoteCommand, MAXPGPATH, REMOTE_FILE_SIZE_COMMAND, remoteFilePath); + + result = PQexec(workerNode, remoteCommand); + if (result == NULL) + { + PQclear(result); + return -1; + } + + tableSize = (int64) GetValueUint64(result, 0, 0); + if (tableSize <= 0) + { + psql_error("remote command \"%s\" fetched invalid table size\n", remoteCommand); + PQclear(result); + + return -1; + } + + PQclear(result); + + return tableSize; +} + + +/* + * ShardColumnarTableSize executes a command on the worker node to determine the + * size of the cstore_fdw table representing the shard. On success, the function + * returns the table size on disk. On failure, the function returns -1. + */ +static int64 +ShardColumnarTableSize(PGconn *workerNode, const char *tablename, uint64 shardId) +{ + PGresult *result = NULL; + char remoteCommand[MAXPGPATH]; + char *extendedTablename = NULL; + int64 shardTableSize = -1; + + extendedTablename = ExtendTablename(tablename, shardId); + snprintf(remoteCommand, MAXPGPATH, SHARD_COLUMNAR_TABLE_SIZE_COMMAND, + extendedTablename); + + result = PQexec(workerNode, remoteCommand); + if (result == NULL) + { + PQclear(result); + free(extendedTablename); + + return -1; + } + + shardTableSize = (int64) GetValueUint64(result, 0, 0); + if (shardTableSize <= 0) + { + psql_error("remote command \"%s\" fetched invalid table size\n", remoteCommand); + PQclear(result); + free(extendedTablename); + + return -1; + } + + PQclear(result); + free(extendedTablename); + + return shardTableSize; +} + + +/* + * ShardMinMaxValues executes command on the worker node to determine minimum + * and maximum values for partition key expression. On successful execution, the + * function sets min and max values in shard metadata and returns true. On + * failure, the function returns false. + */ +static bool +ShardMinMaxValues(PGconn *workerNode, const char *tablename, + const char *partitionKey, ShardMetadata *shardMetadata) +{ + const int MinValueIndex = 0; + const int MaxValueIndex = 1; + + PGresult *result = NULL; + char remoteCommand[MAXPGPATH]; + char *extendedTablename = NULL; + char *minValue = NULL; + char *maxValue = NULL; + int minValueLength = 0; + int maxValueLength = 0; + + extendedTablename = ExtendTablename(tablename, shardMetadata->shardId); + snprintf(remoteCommand, MAXPGPATH, SHARD_MIN_MAX_COMMAND, + partitionKey, partitionKey, extendedTablename); + + result = PQexec(workerNode, remoteCommand); + if (result == NULL) + { + PQclear(result); + free(extendedTablename); + + return false; + } + + minValue = PQgetvalue(result, 0, MinValueIndex); + maxValue = PQgetvalue(result, 0, MaxValueIndex); + + minValueLength = PQgetlength(result, 0, MinValueIndex); + maxValueLength = PQgetlength(result, 0, MaxValueIndex); + + if (minValueLength <= 0 || maxValueLength <= 0) + { + psql_error("remote command \"%s\" fetched empty min/max values\n", + remoteCommand); + PQclear(result); + free(extendedTablename); + + return false; + } + + shardMetadata->shardMinValue = (char *) pg_malloc0(minValueLength + 1); + shardMetadata->shardMaxValue = (char *) pg_malloc0(maxValueLength + 1); + + strncpy(shardMetadata->shardMinValue, minValue, minValueLength + 1); + strncpy(shardMetadata->shardMaxValue, maxValue, maxValueLength + 1); + + PQclear(result); + free(extendedTablename); + + return true; +} diff --git a/src/bin/csql/stage.h b/src/bin/csql/stage.h new file mode 100644 index 000000000..01575f886 --- /dev/null +++ b/src/bin/csql/stage.h @@ -0,0 +1,133 @@ +/* + * csql - the CitusDB interactive terminal + * stage.h + * Declarations for the csql meta-command \stage. These declarations define a + * protocol for the client to communicate to the master and worker nodes. + * + * Copyright (c) 2012, Citus Data, Inc. + * + * $Id$ + */ + +#ifndef STAGE_H +#define STAGE_H + +#include "postgres_fe.h" + + +/* Server returned values never equal to zero. */ +#define INVALID_UINT64 0 +#define MAX_SHARD_UPLOADS 256 +#define SHARD_NAME_SEPARATOR '_' + +/* Connection parameters set to enable connect timeouts in seconds. */ +#define CONN_INFO_TEMPLATE "dbname=%s connect_timeout=%u" +#define CLIENT_CONNECT_TIMEOUT 20 + +/* Transaction related commands used in talking to the master and primary. */ +#define BEGIN_COMMAND "BEGIN" +#define COMMIT_COMMAND "COMMIT" +#define ROLLBACK_COMMAND "ROLLBACK" + +/* Names of remote function calls to execute on the master. */ +#define MASTER_GET_TABLE_METADATA "SELECT * FROM master_get_table_metadata($1::text)" +#define MASTER_GET_TABLE_DDL_EVENTS "SELECT * FROM master_get_table_ddl_events($1::text)" +#define MASTER_GET_NEW_SHARDID "SELECT * FROM master_get_new_shardid()" +#define MASTER_GET_LOCAL_FIRST_CANDIDATE_NODES "SELECT * FROM \ + master_get_local_first_candidate_nodes()" +#define MASTER_GET_ROUND_ROBIN_CANDIDATE_NODES "SELECT * FROM \ + master_get_round_robin_candidate_nodes($1::int8)" + +#define MASTER_INSERT_SHARD_ROW "INSERT INTO pg_dist_shard \ + (logicalrelid, shardid, shardstorage, shardminvalue, shardmaxvalue) VALUES \ + ($1::oid, $2::int8, $3::char, $4::text, $5::text)" +#define MASTER_INSERT_PLACEMENT_ROW "INSERT INTO pg_dist_shard_placement \ + (shardid, shardstate, shardlength, nodename, nodeport) VALUES \ + ($1::int8, $2::int4, $3::int8, $4::text, $5::int4)" + +/* Column names used to identify response fields as returned from the master. */ +#define LOGICAL_RELID_FIELD "logical_relid" +#define PART_STORAGE_TYPE_FIELD "part_storage_type" +#define PART_METHOD_FIELD "part_method" +#define PART_KEY_FIELD "part_key" +#define PART_REPLICA_COUNT_FIELD "part_replica_count" +#define PART_MAX_SIZE_FIELD "part_max_size" +#define PART_PLACEMENT_POLICY_FIELD "part_placement_policy" +#define NODE_NAME_FIELD "node_name" +#define NODE_PORT_FIELD "node_port" + +/* the tablename in the overloaded COPY statement is the to-be-transferred file */ +#define TRANSMIT_REGULAR_COMMAND "COPY \"%s\" FROM STDIN WITH (format 'transmit')" +#define SHARD_MIN_MAX_COMMAND "SELECT min(%s), max(%s) FROM %s" +#define SHARD_TABLE_SIZE_COMMAND "SELECT pg_table_size('%s')" +#define SET_FOREIGN_TABLE_FILENAME "ALTER FOREIGN TABLE %s OPTIONS (SET filename '%s')" +#define GET_COLUMNAR_TABLE_FILENAME_OPTION "SELECT * FROM \ + (SELECT (pg_options_to_table(ftoptions)).* FROM pg_foreign_table \ + WHERE ftrelid = %u) AS Q WHERE option_name = 'filename';" +#define APPLY_SHARD_DDL_COMMAND "SELECT * FROM worker_apply_shard_ddl_command \ + ($1::int8, $2::text)" +#define REMOTE_FILE_SIZE_COMMAND "SELECT size FROM pg_stat_file('%s')" +#define SHARD_COLUMNAR_TABLE_SIZE_COMMAND "SELECT cstore_table_size('%s')" + +/* Types that define table storage type and shard state. */ +#define STORAGE_TYPE_TABLE 't' +#define STORAGE_TYPE_FOREIGN 'f' +#define STORAGE_TYPE_COLUMNAR 'c' +#define FILE_FINALIZED "1" + +/* Shard placement policy types. */ +#define SHARD_PLACEMENT_LOCAL_NODE_FIRST 1 +#define SHARD_PLACEMENT_ROUND_ROBIN 2 + +/* Directory to put foreign table files on secondary nodes. */ +#define FOREIGN_CACHED_DIR "pg_foreign_file/cached" + + +/* + * TableMetadata keeps table related metadata to which the user requested to + * stage data. These metadata are retrieved from the master as read-only; and + * are cached and reused as new shards are created. + */ +typedef struct TableMetadata +{ + uint32 logicalRelid; /* table's relationId on the master */ + char tableStorageType; /* relay file, foreign table, or table */ + char partitionMethod; /* table's partition method */ + char *partitionKey; /* partition key expression */ + uint32 shardReplicaCount; /* shard replication factor */ + uint64 shardMaxSize; /* create new shard when shard reaches max size */ + uint32 shardPlacementPolicy; /* policy to use when choosing nodes to place shards */ + + char **ddlEventList; /* DDL statements used for creating new shard */ + uint32 ddlEventCount; /* DDL statement count; statement list size */ + +} TableMetadata; + + +/* + * ShardMetadata keeps metadata related to one shard for which we are currently + * staging data. Some parts of these metadata are retrieved from the master as + * read-only (shardId, node names and port numbers); and other parts are updated + * by the client as we stage data to clients (shard size and stage statuses). + */ +typedef struct ShardMetadata +{ + uint64 shardId; /* global shardId; created on the master node */ + + char **nodeNameList; /* candidate node name list for shard uploading */ + uint32 *nodePortList; /* candidate node port list for shard uploading */ + uint32 nodeCount; /* candidate node count; node list size */ + bool *nodeStageList; /* shard uploaded to corresponding candidate node? */ + + char *shardMinValue; /* partition key's minimum value in shard */ + char *shardMaxValue; /* partition key's maximum value in shard */ + uint64 shardSize; /* shard size; updated during staging */ + +} ShardMetadata; + + +/* Function declaration for staging data to remote nodes */ +bool DoStageData(const char *stageCommand); + + +#endif /* STAGE_H */ diff --git a/src/bin/csql/startup.c b/src/bin/csql/startup.c new file mode 100644 index 000000000..8b1777e24 --- /dev/null +++ b/src/bin/csql/startup.c @@ -0,0 +1,896 @@ +/* + * psql - the PostgreSQL interactive terminal + * + * Copyright (c) 2000-2015, PostgreSQL Global Development Group + * + * src/bin/psql/startup.c + */ +#include "postgres_fe.h" + +#include + +#ifndef WIN32 +#include +#else /* WIN32 */ +#include +#include +#endif /* WIN32 */ + +#include "getopt_long.h" + +#include + +#include "command.h" +#include "common.h" +#include "describe.h" +#include "help.h" +#include "input.h" +#include "mainloop.h" +#include "print.h" +#include "settings.h" + + + +/* + * Global psql options + */ +PsqlSettings pset; + +#ifndef WIN32 +#define SYSPSQLRC "psqlrc" +#define PSQLRC ".psqlrc" +#else +#define SYSPSQLRC "psqlrc" +#define PSQLRC "psqlrc.conf" +#endif + +/* + * Structures to pass information between the option parsing routine + * and the main function + */ +enum _actions +{ + ACT_NOTHING = 0, + ACT_SINGLE_SLASH, + ACT_LIST_DB, + ACT_SINGLE_QUERY, + ACT_FILE +}; + +struct adhoc_opts +{ + char *dbname; + char *host; + char *port; + char *username; + char *logfilename; + enum _actions action; + char *action_string; + bool no_readline; + bool no_psqlrc; + bool single_txn; +}; + +static void parse_psql_options(int argc, char *argv[], + struct adhoc_opts * options); +static void process_psqlrc(char *argv0); +static void process_psqlrc_file(char *filename); +static void showVersion(void); +static void EstablishVariableSpace(void); + +#define NOPAGER 0 + +/* + * + * main + * + */ +int +main(int argc, char *argv[]) +{ + struct adhoc_opts options; + int successResult; + char *password = NULL; + char *password_prompt = NULL; + bool new_pass; + + set_pglocale_pgservice(argv[0], PG_TEXTDOMAIN("psql")); + + if (argc > 1) + { + if ((strcmp(argv[1], "-?") == 0) || (argc == 2 && (strcmp(argv[1], "--help") == 0))) + { + usage(NOPAGER); + exit(EXIT_SUCCESS); + } + if (strcmp(argv[1], "--version") == 0 || strcmp(argv[1], "-V") == 0) + { + showVersion(); + exit(EXIT_SUCCESS); + } + } + +#ifdef WIN32 + setvbuf(stderr, NULL, _IONBF, 0); +#endif + + pset.progname = get_progname(argv[0]); + + pset.db = NULL; + setDecimalLocale(); + pset.encoding = PQenv2encoding(); + pset.queryFout = stdout; + pset.queryFoutPipe = false; + pset.copyStream = NULL; + pset.cur_cmd_source = stdin; + pset.cur_cmd_interactive = false; + + /* We rely on unmentioned fields of pset.popt to start out 0/false/NULL */ + pset.popt.topt.format = PRINT_ALIGNED; + pset.popt.topt.border = 1; + pset.popt.topt.pager = 1; + pset.popt.topt.pager_min_lines = 0; + pset.popt.topt.start_table = true; + pset.popt.topt.stop_table = true; + pset.popt.topt.default_footer = true; + + pset.popt.topt.unicode_border_linestyle = UNICODE_LINESTYLE_SINGLE; + pset.popt.topt.unicode_column_linestyle = UNICODE_LINESTYLE_SINGLE; + pset.popt.topt.unicode_header_linestyle = UNICODE_LINESTYLE_SINGLE; + + refresh_utf8format(&(pset.popt.topt)); + + /* We must get COLUMNS here before readline() sets it */ + pset.popt.topt.env_columns = getenv("COLUMNS") ? atoi(getenv("COLUMNS")) : 0; + + pset.notty = (!isatty(fileno(stdin)) || !isatty(fileno(stdout))); + + pset.getPassword = TRI_DEFAULT; + + EstablishVariableSpace(); + + SetVariable(pset.vars, "VERSION", PG_VERSION_STR); + + /* Default values for variables */ + SetVariableBool(pset.vars, "AUTOCOMMIT"); + SetVariable(pset.vars, "VERBOSITY", "default"); + SetVariable(pset.vars, "PROMPT1", DEFAULT_PROMPT1); + SetVariable(pset.vars, "PROMPT2", DEFAULT_PROMPT2); + SetVariable(pset.vars, "PROMPT3", DEFAULT_PROMPT3); + + parse_psql_options(argc, argv, &options); + + /* + * If no action was specified and we're in non-interactive mode, treat it + * as if the user had specified "-f -". This lets single-transaction mode + * work in this case. + */ + if (options.action == ACT_NOTHING && pset.notty) + { + options.action = ACT_FILE; + options.action_string = NULL; + } + + /* Bail out if -1 was specified but will be ignored. */ + if (options.single_txn && options.action != ACT_FILE && options.action == ACT_NOTHING) + { + fprintf(stderr, _("%s: -1 can only be used in non-interactive mode\n"), pset.progname); + exit(EXIT_FAILURE); + } + + if (!pset.popt.topt.fieldSep.separator && + !pset.popt.topt.fieldSep.separator_zero) + { + pset.popt.topt.fieldSep.separator = pg_strdup(DEFAULT_FIELD_SEP); + pset.popt.topt.fieldSep.separator_zero = false; + } + if (!pset.popt.topt.recordSep.separator && + !pset.popt.topt.recordSep.separator_zero) + { + pset.popt.topt.recordSep.separator = pg_strdup(DEFAULT_RECORD_SEP); + pset.popt.topt.recordSep.separator_zero = false; + } + + if (options.username == NULL) + password_prompt = pg_strdup(_("Password: ")); + else + password_prompt = psprintf(_("Password for user %s: "), + options.username); + + if (pset.getPassword == TRI_YES) + password = simple_prompt(password_prompt, 100, false); + + /* loop until we have a password if requested by backend */ + do + { +#define PARAMS_ARRAY_SIZE 8 + const char **keywords = pg_malloc(PARAMS_ARRAY_SIZE * sizeof(*keywords)); + const char **values = pg_malloc(PARAMS_ARRAY_SIZE * sizeof(*values)); + + keywords[0] = "host"; + values[0] = options.host; + keywords[1] = "port"; + values[1] = options.port; + keywords[2] = "user"; + values[2] = options.username; + keywords[3] = "password"; + values[3] = password; + keywords[4] = "dbname"; + values[4] = (options.action == ACT_LIST_DB && + options.dbname == NULL) ? + "postgres" : options.dbname; + keywords[5] = "fallback_application_name"; + values[5] = pset.progname; + keywords[6] = "client_encoding"; + values[6] = (pset.notty || getenv("PGCLIENTENCODING")) ? NULL : "auto"; + keywords[7] = NULL; + values[7] = NULL; + + new_pass = false; + pset.db = PQconnectdbParams(keywords, values, true); + free(keywords); + free(values); + + if (PQstatus(pset.db) == CONNECTION_BAD && + PQconnectionNeedsPassword(pset.db) && + password == NULL && + pset.getPassword != TRI_NO) + { + PQfinish(pset.db); + password = simple_prompt(password_prompt, 100, false); + new_pass = true; + } + } while (new_pass); + + free(password); + free(password_prompt); + + if (PQstatus(pset.db) == CONNECTION_BAD) + { + fprintf(stderr, "%s: %s", pset.progname, PQerrorMessage(pset.db)); + PQfinish(pset.db); + exit(EXIT_BADCONN); + } + + setup_cancel_handler(); + + PQsetNoticeProcessor(pset.db, NoticeProcessor, NULL); + + SyncVariables(); + + if (options.action == ACT_LIST_DB) + { + int success; + + if (!options.no_psqlrc) + process_psqlrc(argv[0]); + + success = listAllDbs(NULL, false); + PQfinish(pset.db); + exit(success ? EXIT_SUCCESS : EXIT_FAILURE); + } + + if (options.logfilename) + { + pset.logfile = fopen(options.logfilename, "a"); + if (!pset.logfile) + { + fprintf(stderr, _("%s: could not open log file \"%s\": %s\n"), + pset.progname, options.logfilename, strerror(errno)); + exit(EXIT_FAILURE); + } + } + + /* + * Now find something to do + */ + + /* + * process file given by -f + */ + if (options.action == ACT_FILE) + { + if (!options.no_psqlrc) + process_psqlrc(argv[0]); + + successResult = process_file(options.action_string, options.single_txn, false); + } + + /* + * process slash command if one was given to -c + */ + else if (options.action == ACT_SINGLE_SLASH) + { + PsqlScanState scan_state; + + if (pset.echo == PSQL_ECHO_ALL) + puts(options.action_string); + + scan_state = psql_scan_create(); + psql_scan_setup(scan_state, + options.action_string, + strlen(options.action_string)); + + successResult = HandleSlashCmds(scan_state, NULL) != PSQL_CMD_ERROR + ? EXIT_SUCCESS : EXIT_FAILURE; + + psql_scan_destroy(scan_state); + } + + /* + * If the query given to -c was a normal one, send it + */ + else if (options.action == ACT_SINGLE_QUERY) + { + if (pset.echo == PSQL_ECHO_ALL) + puts(options.action_string); + + successResult = SendQuery(options.action_string) + ? EXIT_SUCCESS : EXIT_FAILURE; + } + + /* + * or otherwise enter interactive main loop + */ + else + { + if (!options.no_psqlrc) + process_psqlrc(argv[0]); + + connection_warnings(true); + if (!pset.quiet) + printf(_("Type \"help\" for help.\n\n")); + initializeInput(options.no_readline ? 0 : 1); + successResult = MainLoop(stdin); + } + + /* clean up */ + if (pset.logfile) + fclose(pset.logfile); + PQfinish(pset.db); + setQFout(NULL); + + return successResult; +} + + +/* + * Parse command line options + */ + +static void +parse_psql_options(int argc, char *argv[], struct adhoc_opts * options) +{ + static struct option long_options[] = + { + {"echo-all", no_argument, NULL, 'a'}, + {"no-align", no_argument, NULL, 'A'}, + {"command", required_argument, NULL, 'c'}, + {"dbname", required_argument, NULL, 'd'}, + {"echo-queries", no_argument, NULL, 'e'}, + {"echo-errors", no_argument, NULL, 'b'}, + {"echo-hidden", no_argument, NULL, 'E'}, + {"file", required_argument, NULL, 'f'}, + {"field-separator", required_argument, NULL, 'F'}, + {"field-separator-zero", no_argument, NULL, 'z'}, + {"host", required_argument, NULL, 'h'}, + {"html", no_argument, NULL, 'H'}, + {"list", no_argument, NULL, 'l'}, + {"log-file", required_argument, NULL, 'L'}, + {"no-readline", no_argument, NULL, 'n'}, + {"single-transaction", no_argument, NULL, '1'}, + {"output", required_argument, NULL, 'o'}, + {"port", required_argument, NULL, 'p'}, + {"pset", required_argument, NULL, 'P'}, + {"quiet", no_argument, NULL, 'q'}, + {"record-separator", required_argument, NULL, 'R'}, + {"record-separator-zero", no_argument, NULL, '0'}, + {"single-step", no_argument, NULL, 's'}, + {"single-line", no_argument, NULL, 'S'}, + {"tuples-only", no_argument, NULL, 't'}, + {"table-attr", required_argument, NULL, 'T'}, + {"username", required_argument, NULL, 'U'}, + {"set", required_argument, NULL, 'v'}, + {"variable", required_argument, NULL, 'v'}, + {"version", no_argument, NULL, 'V'}, + {"no-password", no_argument, NULL, 'w'}, + {"password", no_argument, NULL, 'W'}, + {"expanded", no_argument, NULL, 'x'}, + {"no-psqlrc", no_argument, NULL, 'X'}, + {"help", optional_argument, NULL, 1}, + {NULL, 0, NULL, 0} + }; + + int optindex; + int c; + + memset(options, 0, sizeof *options); + + while ((c = getopt_long(argc, argv, "aAbc:d:eEf:F:h:HlL:no:p:P:qR:sStT:U:v:VwWxXz?01", + long_options, &optindex)) != -1) + { + switch (c) + { + case 'a': + SetVariable(pset.vars, "ECHO", "all"); + break; + case 'A': + pset.popt.topt.format = PRINT_UNALIGNED; + break; + case 'b': + SetVariable(pset.vars, "ECHO", "errors"); + break; + case 'c': + options->action_string = pg_strdup(optarg); + if (optarg[0] == '\\') + { + options->action = ACT_SINGLE_SLASH; + options->action_string++; + } + else + options->action = ACT_SINGLE_QUERY; + break; + case 'd': + options->dbname = pg_strdup(optarg); + break; + case 'e': + SetVariable(pset.vars, "ECHO", "queries"); + break; + case 'E': + SetVariableBool(pset.vars, "ECHO_HIDDEN"); + break; + case 'f': + options->action = ACT_FILE; + options->action_string = pg_strdup(optarg); + break; + case 'F': + pset.popt.topt.fieldSep.separator = pg_strdup(optarg); + pset.popt.topt.fieldSep.separator_zero = false; + break; + case 'h': + options->host = pg_strdup(optarg); + break; + case 'H': + pset.popt.topt.format = PRINT_HTML; + break; + case 'l': + options->action = ACT_LIST_DB; + break; + case 'L': + options->logfilename = pg_strdup(optarg); + break; + case 'n': + options->no_readline = true; + break; + case 'o': + if (!setQFout(optarg)) + exit(EXIT_FAILURE); + break; + case 'p': + options->port = pg_strdup(optarg); + break; + case 'P': + { + char *value; + char *equal_loc; + bool result; + + value = pg_strdup(optarg); + equal_loc = strchr(value, '='); + if (!equal_loc) + result = do_pset(value, NULL, &pset.popt, true); + else + { + *equal_loc = '\0'; + result = do_pset(value, equal_loc + 1, &pset.popt, true); + } + + if (!result) + { + fprintf(stderr, _("%s: could not set printing parameter \"%s\"\n"), pset.progname, value); + exit(EXIT_FAILURE); + } + + free(value); + break; + } + case 'q': + SetVariableBool(pset.vars, "QUIET"); + break; + case 'R': + pset.popt.topt.recordSep.separator = pg_strdup(optarg); + pset.popt.topt.recordSep.separator_zero = false; + break; + case 's': + SetVariableBool(pset.vars, "SINGLESTEP"); + break; + case 'S': + SetVariableBool(pset.vars, "SINGLELINE"); + break; + case 't': + pset.popt.topt.tuples_only = true; + break; + case 'T': + pset.popt.topt.tableAttr = pg_strdup(optarg); + break; + case 'U': + options->username = pg_strdup(optarg); + break; + case 'v': + { + char *value; + char *equal_loc; + + value = pg_strdup(optarg); + equal_loc = strchr(value, '='); + if (!equal_loc) + { + if (!DeleteVariable(pset.vars, value)) + { + fprintf(stderr, _("%s: could not delete variable \"%s\"\n"), + pset.progname, value); + exit(EXIT_FAILURE); + } + } + else + { + *equal_loc = '\0'; + if (!SetVariable(pset.vars, value, equal_loc + 1)) + { + fprintf(stderr, _("%s: could not set variable \"%s\"\n"), + pset.progname, value); + exit(EXIT_FAILURE); + } + } + + free(value); + break; + } + case 'V': + showVersion(); + exit(EXIT_SUCCESS); + case 'w': + pset.getPassword = TRI_NO; + break; + case 'W': + pset.getPassword = TRI_YES; + break; + case 'x': + pset.popt.topt.expanded = true; + break; + case 'X': + options->no_psqlrc = true; + break; + case 'z': + pset.popt.topt.fieldSep.separator_zero = true; + break; + case '0': + pset.popt.topt.recordSep.separator_zero = true; + break; + case '1': + options->single_txn = true; + break; + case '?': + /* Actual help option given */ + if (strcmp(argv[optind - 1], "-?") == 0) + { + usage(NOPAGER); + exit(EXIT_SUCCESS); + } + /* unknown option reported by getopt */ + else + goto unknown_option; + break; + case 1: + { + if (!optarg || strcmp(optarg, "options") == 0) + usage(NOPAGER); + else if (optarg && strcmp(optarg, "commands") == 0) + slashUsage(NOPAGER); + else if (optarg && strcmp(optarg, "variables") == 0) + helpVariables(NOPAGER); + else + goto unknown_option; + + exit(EXIT_SUCCESS); + } + break; + default: + unknown_option: + fprintf(stderr, _("Try \"%s --help\" for more information.\n"), + pset.progname); + exit(EXIT_FAILURE); + break; + } + } + + /* + * if we still have arguments, use it as the database name and username + */ + while (argc - optind >= 1) + { + if (!options->dbname) + options->dbname = argv[optind]; + else if (!options->username) + options->username = argv[optind]; + else if (!pset.quiet) + fprintf(stderr, _("%s: warning: extra command-line argument \"%s\" ignored\n"), + pset.progname, argv[optind]); + + optind++; + } +} + + +/* + * Load .psqlrc file, if found. + */ +static void +process_psqlrc(char *argv0) +{ + char home[MAXPGPATH]; + char rc_file[MAXPGPATH]; + char my_exec_path[MAXPGPATH]; + char etc_path[MAXPGPATH]; + char *envrc = getenv("PSQLRC"); + + if (find_my_exec(argv0, my_exec_path) < 0) + { + fprintf(stderr, _("%s: could not find own program executable\n"), argv0); + exit(EXIT_FAILURE); + } + + get_etc_path(my_exec_path, etc_path); + + snprintf(rc_file, MAXPGPATH, "%s/%s", etc_path, SYSPSQLRC); + process_psqlrc_file(rc_file); + + if (envrc != NULL && strlen(envrc) > 0) + { + /* might need to free() this */ + char *envrc_alloc = pstrdup(envrc); + + expand_tilde(&envrc_alloc); + process_psqlrc_file(envrc_alloc); + } + else if (get_home_path(home)) + { + snprintf(rc_file, MAXPGPATH, "%s/%s", home, PSQLRC); + process_psqlrc_file(rc_file); + } +} + + + +static void +process_psqlrc_file(char *filename) +{ + char *psqlrc_minor, + *psqlrc_major; + +#if defined(WIN32) && (!defined(__MINGW32__)) +#define R_OK 4 +#endif + + psqlrc_minor = psprintf("%s-%s", filename, PG_VERSION); + psqlrc_major = psprintf("%s-%s", filename, PG_MAJORVERSION); + + /* check for minor version first, then major, then no version */ + if (access(psqlrc_minor, R_OK) == 0) + (void) process_file(psqlrc_minor, false, false); + else if (access(psqlrc_major, R_OK) == 0) + (void) process_file(psqlrc_major, false, false); + else if (access(filename, R_OK) == 0) + (void) process_file(filename, false, false); + + free(psqlrc_minor); + free(psqlrc_major); +} + + + +/* showVersion + * + * This output format is intended to match GNU standards. + */ +static void +showVersion(void) +{ + puts("psql (PostgreSQL) " PG_VERSION); +} + + + +/* + * Assign hooks for psql variables. + * + * This isn't an amazingly good place for them, but neither is anywhere else. + */ + +static void +autocommit_hook(const char *newval) +{ + pset.autocommit = ParseVariableBool(newval, "AUTOCOMMIT"); +} + +static void +on_error_stop_hook(const char *newval) +{ + pset.on_error_stop = ParseVariableBool(newval, "ON_ERROR_STOP"); +} + +static void +quiet_hook(const char *newval) +{ + pset.quiet = ParseVariableBool(newval, "QUIET"); +} + +static void +singleline_hook(const char *newval) +{ + pset.singleline = ParseVariableBool(newval, "SINGLELINE"); +} + +static void +singlestep_hook(const char *newval) +{ + pset.singlestep = ParseVariableBool(newval, "SINGLESTEP"); +} + +static void +fetch_count_hook(const char *newval) +{ + pset.fetch_count = ParseVariableNum(newval, -1, -1, false); +} + +static void +echo_hook(const char *newval) +{ + if (newval == NULL) + pset.echo = PSQL_ECHO_NONE; + else if (pg_strcasecmp(newval, "queries") == 0) + pset.echo = PSQL_ECHO_QUERIES; + else if (pg_strcasecmp(newval, "errors") == 0) + pset.echo = PSQL_ECHO_ERRORS; + else if (pg_strcasecmp(newval, "all") == 0) + pset.echo = PSQL_ECHO_ALL; + else if (pg_strcasecmp(newval, "none") == 0) + pset.echo = PSQL_ECHO_NONE; + else + { + psql_error("unrecognized value \"%s\" for \"%s\"; assuming \"%s\"\n", + newval, "ECHO", "none"); + pset.echo = PSQL_ECHO_NONE; + } +} + +static void +echo_hidden_hook(const char *newval) +{ + if (newval == NULL) + pset.echo_hidden = PSQL_ECHO_HIDDEN_OFF; + else if (pg_strcasecmp(newval, "noexec") == 0) + pset.echo_hidden = PSQL_ECHO_HIDDEN_NOEXEC; + else if (ParseVariableBool(newval, "ECHO_HIDDEN")) + pset.echo_hidden = PSQL_ECHO_HIDDEN_ON; + else /* ParseVariableBool printed msg if needed */ + pset.echo_hidden = PSQL_ECHO_HIDDEN_OFF; +} + +static void +on_error_rollback_hook(const char *newval) +{ + if (newval == NULL) + pset.on_error_rollback = PSQL_ERROR_ROLLBACK_OFF; + else if (pg_strcasecmp(newval, "interactive") == 0) + pset.on_error_rollback = PSQL_ERROR_ROLLBACK_INTERACTIVE; + else if (ParseVariableBool(newval, "ON_ERROR_ROLLBACK")) + pset.on_error_rollback = PSQL_ERROR_ROLLBACK_ON; + else /* ParseVariableBool printed msg if needed */ + pset.on_error_rollback = PSQL_ERROR_ROLLBACK_OFF; +} + +static void +comp_keyword_case_hook(const char *newval) +{ + if (newval == NULL) + pset.comp_case = PSQL_COMP_CASE_PRESERVE_UPPER; + else if (pg_strcasecmp(newval, "preserve-upper") == 0) + pset.comp_case = PSQL_COMP_CASE_PRESERVE_UPPER; + else if (pg_strcasecmp(newval, "preserve-lower") == 0) + pset.comp_case = PSQL_COMP_CASE_PRESERVE_LOWER; + else if (pg_strcasecmp(newval, "upper") == 0) + pset.comp_case = PSQL_COMP_CASE_UPPER; + else if (pg_strcasecmp(newval, "lower") == 0) + pset.comp_case = PSQL_COMP_CASE_LOWER; + else + { + psql_error("unrecognized value \"%s\" for \"%s\"; assuming \"%s\"\n", + newval, "COMP_KEYWORD_CASE", "preserve-upper"); + pset.comp_case = PSQL_COMP_CASE_PRESERVE_UPPER; + } +} + +static void +histcontrol_hook(const char *newval) +{ + if (newval == NULL) + pset.histcontrol = hctl_none; + else if (pg_strcasecmp(newval, "ignorespace") == 0) + pset.histcontrol = hctl_ignorespace; + else if (pg_strcasecmp(newval, "ignoredups") == 0) + pset.histcontrol = hctl_ignoredups; + else if (pg_strcasecmp(newval, "ignoreboth") == 0) + pset.histcontrol = hctl_ignoreboth; + else if (pg_strcasecmp(newval, "none") == 0) + pset.histcontrol = hctl_none; + else + { + psql_error("unrecognized value \"%s\" for \"%s\"; assuming \"%s\"\n", + newval, "HISTCONTROL", "none"); + pset.histcontrol = hctl_none; + } +} + +static void +prompt1_hook(const char *newval) +{ + pset.prompt1 = newval ? newval : ""; +} + +static void +prompt2_hook(const char *newval) +{ + pset.prompt2 = newval ? newval : ""; +} + +static void +prompt3_hook(const char *newval) +{ + pset.prompt3 = newval ? newval : ""; +} + +static void +verbosity_hook(const char *newval) +{ + if (newval == NULL) + pset.verbosity = PQERRORS_DEFAULT; + else if (pg_strcasecmp(newval, "default") == 0) + pset.verbosity = PQERRORS_DEFAULT; + else if (pg_strcasecmp(newval, "terse") == 0) + pset.verbosity = PQERRORS_TERSE; + else if (pg_strcasecmp(newval, "verbose") == 0) + pset.verbosity = PQERRORS_VERBOSE; + else + { + psql_error("unrecognized value \"%s\" for \"%s\"; assuming \"%s\"\n", + newval, "VERBOSITY", "default"); + pset.verbosity = PQERRORS_DEFAULT; + } + + if (pset.db) + PQsetErrorVerbosity(pset.db, pset.verbosity); +} + + +static void +EstablishVariableSpace(void) +{ + pset.vars = CreateVariableSpace(); + + SetVariableAssignHook(pset.vars, "AUTOCOMMIT", autocommit_hook); + SetVariableAssignHook(pset.vars, "ON_ERROR_STOP", on_error_stop_hook); + SetVariableAssignHook(pset.vars, "QUIET", quiet_hook); + SetVariableAssignHook(pset.vars, "SINGLELINE", singleline_hook); + SetVariableAssignHook(pset.vars, "SINGLESTEP", singlestep_hook); + SetVariableAssignHook(pset.vars, "FETCH_COUNT", fetch_count_hook); + SetVariableAssignHook(pset.vars, "ECHO", echo_hook); + SetVariableAssignHook(pset.vars, "ECHO_HIDDEN", echo_hidden_hook); + SetVariableAssignHook(pset.vars, "ON_ERROR_ROLLBACK", on_error_rollback_hook); + SetVariableAssignHook(pset.vars, "COMP_KEYWORD_CASE", comp_keyword_case_hook); + SetVariableAssignHook(pset.vars, "HISTCONTROL", histcontrol_hook); + SetVariableAssignHook(pset.vars, "PROMPT1", prompt1_hook); + SetVariableAssignHook(pset.vars, "PROMPT2", prompt2_hook); + SetVariableAssignHook(pset.vars, "PROMPT3", prompt3_hook); + SetVariableAssignHook(pset.vars, "VERBOSITY", verbosity_hook); +} diff --git a/src/bin/csql/stringutils.c b/src/bin/csql/stringutils.c new file mode 100644 index 000000000..5d613eb38 --- /dev/null +++ b/src/bin/csql/stringutils.c @@ -0,0 +1,340 @@ +/* + * psql - the PostgreSQL interactive terminal + * + * Copyright (c) 2000-2015, PostgreSQL Global Development Group + * + * src/bin/psql/stringutils.c + */ +#include "postgres_fe.h" + +#include + +#include "common.h" +#include "stringutils.h" + + +/* + * Replacement for strtok() (a.k.a. poor man's flex) + * + * Splits a string into tokens, returning one token per call, then NULL + * when no more tokens exist in the given string. + * + * The calling convention is similar to that of strtok, but with more + * frammishes. + * + * s - string to parse, if NULL continue parsing the last string + * whitespace - set of whitespace characters that separate tokens + * delim - set of non-whitespace separator characters (or NULL) + * quote - set of characters that can quote a token (NULL if none) + * escape - character that can quote quotes (0 if none) + * e_strings - if TRUE, treat E'...' syntax as a valid token + * del_quotes - if TRUE, strip quotes from the returned token, else return + * it exactly as found in the string + * encoding - the active character-set encoding + * + * Characters in 'delim', if any, will be returned as single-character + * tokens unless part of a quoted token. + * + * Double occurrences of the quoting character are always taken to represent + * a single quote character in the data. If escape isn't 0, then escape + * followed by anything (except \0) is a data character too. + * + * The combination of e_strings and del_quotes both TRUE is not currently + * handled. This could be fixed but it's not needed anywhere at the moment. + * + * Note that the string s is _not_ overwritten in this implementation. + * + * NB: it's okay to vary delim, quote, and escape from one call to the + * next on a single source string, but changing whitespace is a bad idea + * since you might lose data. + */ +char * +strtokx(const char *s, + const char *whitespace, + const char *delim, + const char *quote, + char escape, + bool e_strings, + bool del_quotes, + int encoding) +{ + static char *storage = NULL;/* store the local copy of the users string + * here */ + static char *string = NULL; /* pointer into storage where to continue on + * next call */ + + /* variously abused variables: */ + unsigned int offset; + char *start; + char *p; + + if (s) + { + free(storage); + + /* + * We may need extra space to insert delimiter nulls for adjacent + * tokens. 2X the space is a gross overestimate, but it's unlikely + * that this code will be used on huge strings anyway. + */ + storage = pg_malloc(2 * strlen(s) + 1); + strcpy(storage, s); + string = storage; + } + + if (!storage) + return NULL; + + /* skip leading whitespace */ + offset = strspn(string, whitespace); + start = &string[offset]; + + /* end of string reached? */ + if (*start == '\0') + { + /* technically we don't need to free here, but we're nice */ + free(storage); + storage = NULL; + string = NULL; + return NULL; + } + + /* test if delimiter character */ + if (delim && strchr(delim, *start)) + { + /* + * If not at end of string, we need to insert a null to terminate the + * returned token. We can just overwrite the next character if it + * happens to be in the whitespace set ... otherwise move over the + * rest of the string to make room. (This is why we allocated extra + * space above). + */ + p = start + 1; + if (*p != '\0') + { + if (!strchr(whitespace, *p)) + memmove(p + 1, p, strlen(p) + 1); + *p = '\0'; + string = p + 1; + } + else + { + /* at end of string, so no extra work */ + string = p; + } + + return start; + } + + /* check for E string */ + p = start; + if (e_strings && + (*p == 'E' || *p == 'e') && + p[1] == '\'') + { + quote = "'"; + escape = '\\'; /* if std strings before, not any more */ + p++; + } + + /* test if quoting character */ + if (quote && strchr(quote, *p)) + { + /* okay, we have a quoted token, now scan for the closer */ + char thisquote = *p++; + + for (; *p; p += PQmblen(p, encoding)) + { + if (*p == escape && p[1] != '\0') + p++; /* process escaped anything */ + else if (*p == thisquote && p[1] == thisquote) + p++; /* process doubled quote */ + else if (*p == thisquote) + { + p++; /* skip trailing quote */ + break; + } + } + + /* + * If not at end of string, we need to insert a null to terminate the + * returned token. See notes above. + */ + if (*p != '\0') + { + if (!strchr(whitespace, *p)) + memmove(p + 1, p, strlen(p) + 1); + *p = '\0'; + string = p + 1; + } + else + { + /* at end of string, so no extra work */ + string = p; + } + + /* Clean up the token if caller wants that */ + if (del_quotes) + strip_quotes(start, thisquote, escape, encoding); + + return start; + } + + /* + * Otherwise no quoting character. Scan till next whitespace, delimiter + * or quote. NB: at this point, *start is known not to be '\0', + * whitespace, delim, or quote, so we will consume at least one character. + */ + offset = strcspn(start, whitespace); + + if (delim) + { + unsigned int offset2 = strcspn(start, delim); + + if (offset > offset2) + offset = offset2; + } + + if (quote) + { + unsigned int offset2 = strcspn(start, quote); + + if (offset > offset2) + offset = offset2; + } + + p = start + offset; + + /* + * If not at end of string, we need to insert a null to terminate the + * returned token. See notes above. + */ + if (*p != '\0') + { + if (!strchr(whitespace, *p)) + memmove(p + 1, p, strlen(p) + 1); + *p = '\0'; + string = p + 1; + } + else + { + /* at end of string, so no extra work */ + string = p; + } + + return start; +} + + +/* + * strip_quotes + * + * Remove quotes from the string at *source. Leading and trailing occurrences + * of 'quote' are removed; embedded double occurrences of 'quote' are reduced + * to single occurrences; if 'escape' is not 0 then 'escape' removes special + * significance of next character. + * + * Note that the source string is overwritten in-place. + */ +void +strip_quotes(char *source, char quote, char escape, int encoding) +{ + char *src; + char *dst; + + Assert(source != NULL); + Assert(quote != '\0'); + + src = dst = source; + + if (*src && *src == quote) + src++; /* skip leading quote */ + + while (*src) + { + char c = *src; + int i; + + if (c == quote && src[1] == '\0') + break; /* skip trailing quote */ + else if (c == quote && src[1] == quote) + src++; /* process doubled quote */ + else if (c == escape && src[1] != '\0') + src++; /* process escaped character */ + + i = PQmblen(src, encoding); + while (i--) + *dst++ = *src++; + } + + *dst = '\0'; +} + + +/* + * quote_if_needed + * + * Opposite of strip_quotes(). If "source" denotes itself literally without + * quoting or escaping, returns NULL. Otherwise, returns a malloc'd copy with + * quoting and escaping applied: + * + * source - string to parse + * entails_quote - any of these present? need outer quotes + * quote - doubled within string, affixed to both ends + * escape - doubled within string + * encoding - the active character-set encoding + * + * Do not use this as a substitute for PQescapeStringConn(). Use it for + * strings to be parsed by strtokx() or psql_scan_slash_option(). + */ +char * +quote_if_needed(const char *source, const char *entails_quote, + char quote, char escape, int encoding) +{ + const char *src; + char *ret; + char *dst; + bool need_quotes = false; + + Assert(source != NULL); + Assert(quote != '\0'); + + src = source; + dst = ret = pg_malloc(2 * strlen(src) + 3); /* excess */ + + *dst++ = quote; + + while (*src) + { + char c = *src; + int i; + + if (c == quote) + { + need_quotes = true; + *dst++ = quote; + } + else if (c == escape) + { + need_quotes = true; + *dst++ = escape; + } + else if (strchr(entails_quote, c)) + need_quotes = true; + + i = PQmblen(src, encoding); + while (i--) + *dst++ = *src++; + } + + *dst++ = quote; + *dst = '\0'; + + if (!need_quotes) + { + free(ret); + ret = NULL; + } + + return ret; +} diff --git a/src/bin/csql/stringutils.h b/src/bin/csql/stringutils.h new file mode 100644 index 000000000..562b3bd85 --- /dev/null +++ b/src/bin/csql/stringutils.h @@ -0,0 +1,27 @@ +/* + * psql - the PostgreSQL interactive terminal + * + * Copyright (c) 2000-2015, PostgreSQL Global Development Group + * + * src/bin/psql/stringutils.h + */ +#ifndef STRINGUTILS_H +#define STRINGUTILS_H + +/* The cooler version of strtok() which knows about quotes and doesn't + * overwrite your input */ +extern char *strtokx(const char *s, + const char *whitespace, + const char *delim, + const char *quote, + char escape, + bool e_strings, + bool del_quotes, + int encoding); + +extern void strip_quotes(char *source, char quote, char escape, int encoding); + +extern char *quote_if_needed(const char *source, const char *entails_quote, + char quote, char escape, int encoding); + +#endif /* STRINGUTILS_H */ diff --git a/src/bin/csql/tab-complete.c b/src/bin/csql/tab-complete.c new file mode 100644 index 000000000..44d7a4f05 --- /dev/null +++ b/src/bin/csql/tab-complete.c @@ -0,0 +1,4719 @@ +/* + * psql - the PostgreSQL interactive terminal + * + * Copyright (c) 2000-2015, PostgreSQL Global Development Group + * + * src/bin/psql/tab-complete.c + */ + +/*---------------------------------------------------------------------- + * This file implements a somewhat more sophisticated readline "TAB + * completion" in psql. It is not intended to be AI, to replace + * learning SQL, or to relieve you from thinking about what you're + * doing. Also it does not always give you all the syntactically legal + * completions, only those that are the most common or the ones that + * the programmer felt most like implementing. + * + * CAVEAT: Tab completion causes queries to be sent to the backend. + * The number of tuples returned gets limited, in most default + * installations to 1000, but if you still don't like this prospect, + * you can turn off tab completion in your ~/.inputrc (or else + * ${INPUTRC}) file so: + * + * $if psql + * set disable-completion on + * $endif + * + * See `man 3 readline' or `info readline' for the full details. Also, + * hence the + * + * BUGS: + * + * - If you split your queries across lines, this whole thing gets + * confused. (To fix this, one would have to read psql's query + * buffer rather than readline's line buffer, which would require + * some major revisions of things.) + * + * - Table or attribute names with spaces in it may confuse it. + * + * - Quotes, parenthesis, and other funny characters are not handled + * all that gracefully. + *---------------------------------------------------------------------- + */ + +#include "postgres_fe.h" +#include "tab-complete.h" +#include "input.h" + +/* If we don't have this, we might as well forget about the whole thing: */ +#ifdef USE_READLINE + +#include +#include "libpq-fe.h" +#include "pqexpbuffer.h" +#include "common.h" +#include "settings.h" +#include "stringutils.h" + +#ifdef HAVE_RL_FILENAME_COMPLETION_FUNCTION +#define filename_completion_function rl_filename_completion_function +#else +/* missing in some header files */ +extern char *filename_completion_function(); +#endif + +#ifdef HAVE_RL_COMPLETION_MATCHES +#define completion_matches rl_completion_matches +#endif + +/* word break characters */ +#define WORD_BREAKS "\t\n@$><=;|&{() " + +/* + * This struct is used to define "schema queries", which are custom-built + * to obtain possibly-schema-qualified names of database objects. There is + * enough similarity in the structure that we don't want to repeat it each + * time. So we put the components of each query into this struct and + * assemble them with the common boilerplate in _complete_from_query(). + */ +typedef struct SchemaQuery +{ + /* + * Name of catalog or catalogs to be queried, with alias, eg. + * "pg_catalog.pg_class c". Note that "pg_namespace n" will be added. + */ + const char *catname; + + /* + * Selection condition --- only rows meeting this condition are candidates + * to display. If catname mentions multiple tables, include the necessary + * join condition here. For example, "c.relkind = 'r'". Write NULL (not + * an empty string) if not needed. + */ + const char *selcondition; + + /* + * Visibility condition --- which rows are visible without schema + * qualification? For example, "pg_catalog.pg_table_is_visible(c.oid)". + */ + const char *viscondition; + + /* + * Namespace --- name of field to join to pg_namespace.oid. For example, + * "c.relnamespace". + */ + const char *namespace; + + /* + * Result --- the appropriately-quoted name to return, in the case of an + * unqualified name. For example, "pg_catalog.quote_ident(c.relname)". + */ + const char *result; + + /* + * In some cases a different result must be used for qualified names. + * Enter that here, or write NULL if result can be used. + */ + const char *qualresult; +} SchemaQuery; + + +/* Store maximum number of records we want from database queries + * (implemented via SELECT ... LIMIT xx). + */ +static int completion_max_records; + +/* + * Communication variables set by COMPLETE_WITH_FOO macros and then used by + * the completion callback functions. Ugly but there is no better way. + */ +static const char *completion_charp; /* to pass a string */ +static const char *const * completion_charpp; /* to pass a list of strings */ +static const char *completion_info_charp; /* to pass a second string */ +static const char *completion_info_charp2; /* to pass a third string */ +static const SchemaQuery *completion_squery; /* to pass a SchemaQuery */ +static bool completion_case_sensitive; /* completion is case sensitive */ + +/* + * A few macros to ease typing. You can use these to complete the given + * string with + * 1) The results from a query you pass it. (Perhaps one of those below?) + * 2) The results from a schema query you pass it. + * 3) The items from a null-pointer-terminated list. + * 4) A string constant. + * 5) The list of attributes of the given table (possibly schema-qualified). + * 6/ The list of arguments to the given function (possibly schema-qualified). + */ +#define COMPLETE_WITH_QUERY(query) \ +do { \ + completion_charp = query; \ + matches = completion_matches(text, complete_from_query); \ +} while (0) + +#define COMPLETE_WITH_SCHEMA_QUERY(query, addon) \ +do { \ + completion_squery = &(query); \ + completion_charp = addon; \ + matches = completion_matches(text, complete_from_schema_query); \ +} while (0) + +#define COMPLETE_WITH_LIST_CS(list) \ +do { \ + completion_charpp = list; \ + completion_case_sensitive = true; \ + matches = completion_matches(text, complete_from_list); \ +} while (0) + +#define COMPLETE_WITH_LIST(list) \ +do { \ + completion_charpp = list; \ + completion_case_sensitive = false; \ + matches = completion_matches(text, complete_from_list); \ +} while (0) + +#define COMPLETE_WITH_CONST(string) \ +do { \ + completion_charp = string; \ + completion_case_sensitive = false; \ + matches = completion_matches(text, complete_from_const); \ +} while (0) + +#define COMPLETE_WITH_ATTR(relation, addon) \ +do { \ + char *_completion_schema; \ + char *_completion_table; \ +\ + _completion_schema = strtokx(relation, " \t\n\r", ".", "\"", 0, \ + false, false, pset.encoding); \ + (void) strtokx(NULL, " \t\n\r", ".", "\"", 0, \ + false, false, pset.encoding); \ + _completion_table = strtokx(NULL, " \t\n\r", ".", "\"", 0, \ + false, false, pset.encoding); \ + if (_completion_table == NULL) \ + { \ + completion_charp = Query_for_list_of_attributes addon; \ + completion_info_charp = relation; \ + } \ + else \ + { \ + completion_charp = Query_for_list_of_attributes_with_schema addon; \ + completion_info_charp = _completion_table; \ + completion_info_charp2 = _completion_schema; \ + } \ + matches = completion_matches(text, complete_from_query); \ +} while (0) + +#define COMPLETE_WITH_FUNCTION_ARG(function) \ +do { \ + char *_completion_schema; \ + char *_completion_function; \ +\ + _completion_schema = strtokx(function, " \t\n\r", ".", "\"", 0, \ + false, false, pset.encoding); \ + (void) strtokx(NULL, " \t\n\r", ".", "\"", 0, \ + false, false, pset.encoding); \ + _completion_function = strtokx(NULL, " \t\n\r", ".", "\"", 0, \ + false, false, pset.encoding); \ + if (_completion_function == NULL) \ + { \ + completion_charp = Query_for_list_of_arguments; \ + completion_info_charp = function; \ + } \ + else \ + { \ + completion_charp = Query_for_list_of_arguments_with_schema; \ + completion_info_charp = _completion_function; \ + completion_info_charp2 = _completion_schema; \ + } \ + matches = completion_matches(text, complete_from_query); \ +} while (0) + +/* + * Assembly instructions for schema queries + */ + +static const SchemaQuery Query_for_list_of_aggregates = { + /* catname */ + "pg_catalog.pg_proc p", + /* selcondition */ + "p.proisagg", + /* viscondition */ + "pg_catalog.pg_function_is_visible(p.oid)", + /* namespace */ + "p.pronamespace", + /* result */ + "pg_catalog.quote_ident(p.proname)", + /* qualresult */ + NULL +}; + +static const SchemaQuery Query_for_list_of_datatypes = { + /* catname */ + "pg_catalog.pg_type t", + /* selcondition --- ignore table rowtypes and array types */ + "(t.typrelid = 0 " + " OR (SELECT c.relkind = 'c' FROM pg_catalog.pg_class c WHERE c.oid = t.typrelid)) " + "AND t.typname !~ '^_'", + /* viscondition */ + "pg_catalog.pg_type_is_visible(t.oid)", + /* namespace */ + "t.typnamespace", + /* result */ + "pg_catalog.format_type(t.oid, NULL)", + /* qualresult */ + "pg_catalog.quote_ident(t.typname)" +}; + +static const SchemaQuery Query_for_list_of_domains = { + /* catname */ + "pg_catalog.pg_type t", + /* selcondition */ + "t.typtype = 'd'", + /* viscondition */ + "pg_catalog.pg_type_is_visible(t.oid)", + /* namespace */ + "t.typnamespace", + /* result */ + "pg_catalog.quote_ident(t.typname)", + /* qualresult */ + NULL +}; + +static const SchemaQuery Query_for_list_of_functions = { + /* catname */ + "pg_catalog.pg_proc p", + /* selcondition */ + NULL, + /* viscondition */ + "pg_catalog.pg_function_is_visible(p.oid)", + /* namespace */ + "p.pronamespace", + /* result */ + "pg_catalog.quote_ident(p.proname)", + /* qualresult */ + NULL +}; + +static const SchemaQuery Query_for_list_of_indexes = { + /* catname */ + "pg_catalog.pg_class c", + /* selcondition */ + "c.relkind IN ('i')", + /* viscondition */ + "pg_catalog.pg_table_is_visible(c.oid)", + /* namespace */ + "c.relnamespace", + /* result */ + "pg_catalog.quote_ident(c.relname)", + /* qualresult */ + NULL +}; + +static const SchemaQuery Query_for_list_of_sequences = { + /* catname */ + "pg_catalog.pg_class c", + /* selcondition */ + "c.relkind IN ('S')", + /* viscondition */ + "pg_catalog.pg_table_is_visible(c.oid)", + /* namespace */ + "c.relnamespace", + /* result */ + "pg_catalog.quote_ident(c.relname)", + /* qualresult */ + NULL +}; + +static const SchemaQuery Query_for_list_of_foreign_tables = { + /* catname */ + "pg_catalog.pg_class c", + /* selcondition */ + "c.relkind IN ('f')", + /* viscondition */ + "pg_catalog.pg_table_is_visible(c.oid)", + /* namespace */ + "c.relnamespace", + /* result */ + "pg_catalog.quote_ident(c.relname)", + /* qualresult */ + NULL +}; + +static const SchemaQuery Query_for_list_of_tables = { + /* catname */ + "pg_catalog.pg_class c", + /* selcondition */ + "c.relkind IN ('r')", + /* viscondition */ + "pg_catalog.pg_table_is_visible(c.oid)", + /* namespace */ + "c.relnamespace", + /* result */ + "pg_catalog.quote_ident(c.relname)", + /* qualresult */ + NULL +}; + +static const SchemaQuery Query_for_list_of_constraints_with_schema = { + /* catname */ + "pg_catalog.pg_constraint c", + /* selcondition */ + "c.conrelid <> 0", + /* viscondition */ + "true", /* there is no pg_constraint_is_visible */ + /* namespace */ + "c.connamespace", + /* result */ + "pg_catalog.quote_ident(c.conname)", + /* qualresult */ + NULL +}; + +/* Relations supporting INSERT, UPDATE or DELETE */ +static const SchemaQuery Query_for_list_of_updatables = { + /* catname */ + "pg_catalog.pg_class c", + /* selcondition */ + "c.relkind IN ('r', 'f', 'v')", + /* viscondition */ + "pg_catalog.pg_table_is_visible(c.oid)", + /* namespace */ + "c.relnamespace", + /* result */ + "pg_catalog.quote_ident(c.relname)", + /* qualresult */ + NULL +}; + +static const SchemaQuery Query_for_list_of_relations = { + /* catname */ + "pg_catalog.pg_class c", + /* selcondition */ + NULL, + /* viscondition */ + "pg_catalog.pg_table_is_visible(c.oid)", + /* namespace */ + "c.relnamespace", + /* result */ + "pg_catalog.quote_ident(c.relname)", + /* qualresult */ + NULL +}; + +static const SchemaQuery Query_for_list_of_tsvmf = { + /* catname */ + "pg_catalog.pg_class c", + /* selcondition */ + "c.relkind IN ('r', 'S', 'v', 'm', 'f')", + /* viscondition */ + "pg_catalog.pg_table_is_visible(c.oid)", + /* namespace */ + "c.relnamespace", + /* result */ + "pg_catalog.quote_ident(c.relname)", + /* qualresult */ + NULL +}; + +static const SchemaQuery Query_for_list_of_tmf = { + /* catname */ + "pg_catalog.pg_class c", + /* selcondition */ + "c.relkind IN ('r', 'm', 'f')", + /* viscondition */ + "pg_catalog.pg_table_is_visible(c.oid)", + /* namespace */ + "c.relnamespace", + /* result */ + "pg_catalog.quote_ident(c.relname)", + /* qualresult */ + NULL +}; + +static const SchemaQuery Query_for_list_of_tm = { + /* catname */ + "pg_catalog.pg_class c", + /* selcondition */ + "c.relkind IN ('r', 'm')", + /* viscondition */ + "pg_catalog.pg_table_is_visible(c.oid)", + /* namespace */ + "c.relnamespace", + /* result */ + "pg_catalog.quote_ident(c.relname)", + /* qualresult */ + NULL +}; + +static const SchemaQuery Query_for_list_of_views = { + /* catname */ + "pg_catalog.pg_class c", + /* selcondition */ + "c.relkind IN ('v')", + /* viscondition */ + "pg_catalog.pg_table_is_visible(c.oid)", + /* namespace */ + "c.relnamespace", + /* result */ + "pg_catalog.quote_ident(c.relname)", + /* qualresult */ + NULL +}; + +static const SchemaQuery Query_for_list_of_matviews = { + /* catname */ + "pg_catalog.pg_class c", + /* selcondition */ + "c.relkind IN ('m')", + /* viscondition */ + "pg_catalog.pg_table_is_visible(c.oid)", + /* namespace */ + "c.relnamespace", + /* result */ + "pg_catalog.quote_ident(c.relname)", + /* qualresult */ + NULL +}; + + +/* + * Queries to get lists of names of various kinds of things, possibly + * restricted to names matching a partially entered name. In these queries, + * the first %s will be replaced by the text entered so far (suitably escaped + * to become a SQL literal string). %d will be replaced by the length of the + * string (in unescaped form). A second and third %s, if present, will be + * replaced by a suitably-escaped version of the string provided in + * completion_info_charp. A fourth and fifth %s are similarly replaced by + * completion_info_charp2. + * + * Beware that the allowed sequences of %s and %d are determined by + * _complete_from_query(). + */ + +#define Query_for_list_of_attributes \ +"SELECT pg_catalog.quote_ident(attname) "\ +" FROM pg_catalog.pg_attribute a, pg_catalog.pg_class c "\ +" WHERE c.oid = a.attrelid "\ +" AND a.attnum > 0 "\ +" AND NOT a.attisdropped "\ +" AND substring(pg_catalog.quote_ident(attname),1,%d)='%s' "\ +" AND (pg_catalog.quote_ident(relname)='%s' "\ +" OR '\"' || relname || '\"'='%s') "\ +" AND pg_catalog.pg_table_is_visible(c.oid)" + +#define Query_for_list_of_attributes_with_schema \ +"SELECT pg_catalog.quote_ident(attname) "\ +" FROM pg_catalog.pg_attribute a, pg_catalog.pg_class c, pg_catalog.pg_namespace n "\ +" WHERE c.oid = a.attrelid "\ +" AND n.oid = c.relnamespace "\ +" AND a.attnum > 0 "\ +" AND NOT a.attisdropped "\ +" AND substring(pg_catalog.quote_ident(attname),1,%d)='%s' "\ +" AND (pg_catalog.quote_ident(relname)='%s' "\ +" OR '\"' || relname || '\"' ='%s') "\ +" AND (pg_catalog.quote_ident(nspname)='%s' "\ +" OR '\"' || nspname || '\"' ='%s') " + +#define Query_for_list_of_template_databases \ +"SELECT pg_catalog.quote_ident(datname) FROM pg_catalog.pg_database "\ +" WHERE substring(pg_catalog.quote_ident(datname),1,%d)='%s' AND datistemplate" + +#define Query_for_list_of_databases \ +"SELECT pg_catalog.quote_ident(datname) FROM pg_catalog.pg_database "\ +" WHERE substring(pg_catalog.quote_ident(datname),1,%d)='%s'" + +#define Query_for_list_of_tablespaces \ +"SELECT pg_catalog.quote_ident(spcname) FROM pg_catalog.pg_tablespace "\ +" WHERE substring(pg_catalog.quote_ident(spcname),1,%d)='%s'" + +#define Query_for_list_of_encodings \ +" SELECT DISTINCT pg_catalog.pg_encoding_to_char(conforencoding) "\ +" FROM pg_catalog.pg_conversion "\ +" WHERE substring(pg_catalog.pg_encoding_to_char(conforencoding),1,%d)=UPPER('%s')" + +#define Query_for_list_of_languages \ +"SELECT pg_catalog.quote_ident(lanname) "\ +" FROM pg_catalog.pg_language "\ +" WHERE lanname != 'internal' "\ +" AND substring(pg_catalog.quote_ident(lanname),1,%d)='%s'" + +#define Query_for_list_of_schemas \ +"SELECT pg_catalog.quote_ident(nspname) FROM pg_catalog.pg_namespace "\ +" WHERE substring(pg_catalog.quote_ident(nspname),1,%d)='%s'" + +#define Query_for_list_of_alter_system_set_vars \ +"SELECT name FROM "\ +" (SELECT pg_catalog.lower(name) AS name FROM pg_catalog.pg_settings "\ +" WHERE context != 'internal') ss "\ +" WHERE substring(name,1,%d)='%s'"\ +" UNION ALL SELECT 'all' ss" + +#define Query_for_list_of_set_vars \ +"SELECT name FROM "\ +" (SELECT pg_catalog.lower(name) AS name FROM pg_catalog.pg_settings "\ +" WHERE context IN ('user', 'superuser') "\ +" UNION ALL SELECT 'constraints' "\ +" UNION ALL SELECT 'transaction' "\ +" UNION ALL SELECT 'session' "\ +" UNION ALL SELECT 'role' "\ +" UNION ALL SELECT 'tablespace' "\ +" UNION ALL SELECT 'all') ss "\ +" WHERE substring(name,1,%d)='%s'" + +#define Query_for_list_of_show_vars \ +"SELECT name FROM "\ +" (SELECT pg_catalog.lower(name) AS name FROM pg_catalog.pg_settings "\ +" UNION ALL SELECT 'session authorization' "\ +" UNION ALL SELECT 'all') ss "\ +" WHERE substring(name,1,%d)='%s'" + +#define Query_for_list_of_roles \ +" SELECT pg_catalog.quote_ident(rolname) "\ +" FROM pg_catalog.pg_roles "\ +" WHERE substring(pg_catalog.quote_ident(rolname),1,%d)='%s'" + +#define Query_for_list_of_grant_roles \ +" SELECT pg_catalog.quote_ident(rolname) "\ +" FROM pg_catalog.pg_roles "\ +" WHERE substring(pg_catalog.quote_ident(rolname),1,%d)='%s'"\ +" UNION ALL SELECT 'PUBLIC'" + +/* the silly-looking length condition is just to eat up the current word */ +#define Query_for_table_owning_index \ +"SELECT pg_catalog.quote_ident(c1.relname) "\ +" FROM pg_catalog.pg_class c1, pg_catalog.pg_class c2, pg_catalog.pg_index i"\ +" WHERE c1.oid=i.indrelid and i.indexrelid=c2.oid"\ +" and (%d = pg_catalog.length('%s'))"\ +" and pg_catalog.quote_ident(c2.relname)='%s'"\ +" and pg_catalog.pg_table_is_visible(c2.oid)" + +/* the silly-looking length condition is just to eat up the current word */ +#define Query_for_index_of_table \ +"SELECT pg_catalog.quote_ident(c2.relname) "\ +" FROM pg_catalog.pg_class c1, pg_catalog.pg_class c2, pg_catalog.pg_index i"\ +" WHERE c1.oid=i.indrelid and i.indexrelid=c2.oid"\ +" and (%d = pg_catalog.length('%s'))"\ +" and pg_catalog.quote_ident(c1.relname)='%s'"\ +" and pg_catalog.pg_table_is_visible(c2.oid)" + +/* the silly-looking length condition is just to eat up the current word */ +#define Query_for_constraint_of_table \ +"SELECT pg_catalog.quote_ident(conname) "\ +" FROM pg_catalog.pg_class c1, pg_catalog.pg_constraint con "\ +" WHERE c1.oid=conrelid and (%d = pg_catalog.length('%s'))"\ +" and pg_catalog.quote_ident(c1.relname)='%s'"\ +" and pg_catalog.pg_table_is_visible(c1.oid)" + +#define Query_for_all_table_constraints \ +"SELECT pg_catalog.quote_ident(conname) "\ +" FROM pg_catalog.pg_constraint c "\ +" WHERE c.conrelid <> 0 " + +/* the silly-looking length condition is just to eat up the current word */ +#define Query_for_constraint_of_type \ +"SELECT pg_catalog.quote_ident(conname) "\ +" FROM pg_catalog.pg_type t, pg_catalog.pg_constraint con "\ +" WHERE t.oid=contypid and (%d = pg_catalog.length('%s'))"\ +" and pg_catalog.quote_ident(t.typname)='%s'"\ +" and pg_catalog.pg_type_is_visible(t.oid)" + +/* the silly-looking length condition is just to eat up the current word */ +#define Query_for_list_of_tables_for_constraint \ +"SELECT pg_catalog.quote_ident(relname) "\ +" FROM pg_catalog.pg_class"\ +" WHERE (%d = pg_catalog.length('%s'))"\ +" AND oid IN "\ +" (SELECT conrelid FROM pg_catalog.pg_constraint "\ +" WHERE pg_catalog.quote_ident(conname)='%s')" + +/* the silly-looking length condition is just to eat up the current word */ +#define Query_for_rule_of_table \ +"SELECT pg_catalog.quote_ident(rulename) "\ +" FROM pg_catalog.pg_class c1, pg_catalog.pg_rewrite "\ +" WHERE c1.oid=ev_class and (%d = pg_catalog.length('%s'))"\ +" and pg_catalog.quote_ident(c1.relname)='%s'"\ +" and pg_catalog.pg_table_is_visible(c1.oid)" + +/* the silly-looking length condition is just to eat up the current word */ +#define Query_for_list_of_tables_for_rule \ +"SELECT pg_catalog.quote_ident(relname) "\ +" FROM pg_catalog.pg_class"\ +" WHERE (%d = pg_catalog.length('%s'))"\ +" AND oid IN "\ +" (SELECT ev_class FROM pg_catalog.pg_rewrite "\ +" WHERE pg_catalog.quote_ident(rulename)='%s')" + +/* the silly-looking length condition is just to eat up the current word */ +#define Query_for_trigger_of_table \ +"SELECT pg_catalog.quote_ident(tgname) "\ +" FROM pg_catalog.pg_class c1, pg_catalog.pg_trigger "\ +" WHERE c1.oid=tgrelid and (%d = pg_catalog.length('%s'))"\ +" and pg_catalog.quote_ident(c1.relname)='%s'"\ +" and pg_catalog.pg_table_is_visible(c1.oid)"\ +" and not tgisinternal" + +/* the silly-looking length condition is just to eat up the current word */ +#define Query_for_list_of_tables_for_trigger \ +"SELECT pg_catalog.quote_ident(relname) "\ +" FROM pg_catalog.pg_class"\ +" WHERE (%d = pg_catalog.length('%s'))"\ +" AND oid IN "\ +" (SELECT tgrelid FROM pg_catalog.pg_trigger "\ +" WHERE pg_catalog.quote_ident(tgname)='%s')" + +#define Query_for_list_of_ts_configurations \ +"SELECT pg_catalog.quote_ident(cfgname) FROM pg_catalog.pg_ts_config "\ +" WHERE substring(pg_catalog.quote_ident(cfgname),1,%d)='%s'" + +#define Query_for_list_of_ts_dictionaries \ +"SELECT pg_catalog.quote_ident(dictname) FROM pg_catalog.pg_ts_dict "\ +" WHERE substring(pg_catalog.quote_ident(dictname),1,%d)='%s'" + +#define Query_for_list_of_ts_parsers \ +"SELECT pg_catalog.quote_ident(prsname) FROM pg_catalog.pg_ts_parser "\ +" WHERE substring(pg_catalog.quote_ident(prsname),1,%d)='%s'" + +#define Query_for_list_of_ts_templates \ +"SELECT pg_catalog.quote_ident(tmplname) FROM pg_catalog.pg_ts_template "\ +" WHERE substring(pg_catalog.quote_ident(tmplname),1,%d)='%s'" + +#define Query_for_list_of_fdws \ +" SELECT pg_catalog.quote_ident(fdwname) "\ +" FROM pg_catalog.pg_foreign_data_wrapper "\ +" WHERE substring(pg_catalog.quote_ident(fdwname),1,%d)='%s'" + +#define Query_for_list_of_servers \ +" SELECT pg_catalog.quote_ident(srvname) "\ +" FROM pg_catalog.pg_foreign_server "\ +" WHERE substring(pg_catalog.quote_ident(srvname),1,%d)='%s'" + +#define Query_for_list_of_user_mappings \ +" SELECT pg_catalog.quote_ident(usename) "\ +" FROM pg_catalog.pg_user_mappings "\ +" WHERE substring(pg_catalog.quote_ident(usename),1,%d)='%s'" + +#define Query_for_list_of_access_methods \ +" SELECT pg_catalog.quote_ident(amname) "\ +" FROM pg_catalog.pg_am "\ +" WHERE substring(pg_catalog.quote_ident(amname),1,%d)='%s'" + +/* the silly-looking length condition is just to eat up the current word */ +#define Query_for_list_of_arguments \ +"SELECT pg_catalog.oidvectortypes(proargtypes)||')' "\ +" FROM pg_catalog.pg_proc "\ +" WHERE (%d = pg_catalog.length('%s'))"\ +" AND (pg_catalog.quote_ident(proname)='%s'"\ +" OR '\"' || proname || '\"'='%s') "\ +" AND (pg_catalog.pg_function_is_visible(pg_proc.oid))" + +/* the silly-looking length condition is just to eat up the current word */ +#define Query_for_list_of_arguments_with_schema \ +"SELECT pg_catalog.oidvectortypes(proargtypes)||')' "\ +" FROM pg_catalog.pg_proc p, pg_catalog.pg_namespace n "\ +" WHERE (%d = pg_catalog.length('%s'))"\ +" AND n.oid = p.pronamespace "\ +" AND (pg_catalog.quote_ident(proname)='%s' "\ +" OR '\"' || proname || '\"' ='%s') "\ +" AND (pg_catalog.quote_ident(nspname)='%s' "\ +" OR '\"' || nspname || '\"' ='%s') " + +#define Query_for_list_of_extensions \ +" SELECT pg_catalog.quote_ident(extname) "\ +" FROM pg_catalog.pg_extension "\ +" WHERE substring(pg_catalog.quote_ident(extname),1,%d)='%s'" + +#define Query_for_list_of_available_extensions \ +" SELECT pg_catalog.quote_ident(name) "\ +" FROM pg_catalog.pg_available_extensions "\ +" WHERE substring(pg_catalog.quote_ident(name),1,%d)='%s' AND installed_version IS NULL" + +#define Query_for_list_of_prepared_statements \ +" SELECT pg_catalog.quote_ident(name) "\ +" FROM pg_catalog.pg_prepared_statements "\ +" WHERE substring(pg_catalog.quote_ident(name),1,%d)='%s'" + +#define Query_for_list_of_event_triggers \ +" SELECT pg_catalog.quote_ident(evtname) "\ +" FROM pg_catalog.pg_event_trigger "\ +" WHERE substring(pg_catalog.quote_ident(evtname),1,%d)='%s'" + +#define Query_for_list_of_tablesample_methods \ +" SELECT pg_catalog.quote_ident(proname) "\ +" FROM pg_catalog.pg_proc "\ +" WHERE prorettype = 'pg_catalog.tsm_handler'::pg_catalog.regtype AND "\ +" proargtypes[0] = 'pg_catalog.internal'::pg_catalog.regtype AND "\ +" substring(pg_catalog.quote_ident(proname),1,%d)='%s'" + +#define Query_for_list_of_policies \ +" SELECT pg_catalog.quote_ident(polname) "\ +" FROM pg_catalog.pg_policy "\ +" WHERE substring(pg_catalog.quote_ident(polname),1,%d)='%s'" + +#define Query_for_list_of_tables_for_policy \ +"SELECT pg_catalog.quote_ident(relname) "\ +" FROM pg_catalog.pg_class"\ +" WHERE (%d = pg_catalog.length('%s'))"\ +" AND oid IN "\ +" (SELECT polrelid FROM pg_catalog.pg_policy "\ +" WHERE pg_catalog.quote_ident(polname)='%s')" + +/* + * This is a list of all "things" in Pgsql, which can show up after CREATE or + * DROP; and there is also a query to get a list of them. + */ + +typedef struct +{ + const char *name; + const char *query; /* simple query, or NULL */ + const SchemaQuery *squery; /* schema query, or NULL */ + const bits32 flags; /* visibility flags, see below */ +} pgsql_thing_t; + +#define THING_NO_CREATE (1 << 0) /* should not show up after CREATE */ +#define THING_NO_DROP (1 << 1) /* should not show up after DROP */ +#define THING_NO_SHOW (THING_NO_CREATE | THING_NO_DROP) + +static const pgsql_thing_t words_after_create[] = { + {"AGGREGATE", NULL, &Query_for_list_of_aggregates}, + {"CAST", NULL, NULL}, /* Casts have complex structures for names, so + * skip it */ + {"COLLATION", "SELECT pg_catalog.quote_ident(collname) FROM pg_catalog.pg_collation WHERE collencoding IN (-1, pg_catalog.pg_char_to_encoding(pg_catalog.getdatabaseencoding())) AND substring(pg_catalog.quote_ident(collname),1,%d)='%s'"}, + + /* + * CREATE CONSTRAINT TRIGGER is not supported here because it is designed + * to be used only by pg_dump. + */ + {"CONFIGURATION", Query_for_list_of_ts_configurations, NULL, THING_NO_SHOW}, + {"CONVERSION", "SELECT pg_catalog.quote_ident(conname) FROM pg_catalog.pg_conversion WHERE substring(pg_catalog.quote_ident(conname),1,%d)='%s'"}, + {"DATABASE", Query_for_list_of_databases}, + {"DICTIONARY", Query_for_list_of_ts_dictionaries, NULL, THING_NO_SHOW}, + {"DOMAIN", NULL, &Query_for_list_of_domains}, + {"EVENT TRIGGER", NULL, NULL}, + {"EXTENSION", Query_for_list_of_extensions}, + {"FOREIGN DATA WRAPPER", NULL, NULL}, + {"FOREIGN TABLE", NULL, NULL}, + {"FUNCTION", NULL, &Query_for_list_of_functions}, + {"GROUP", Query_for_list_of_roles}, + {"LANGUAGE", Query_for_list_of_languages}, + {"INDEX", NULL, &Query_for_list_of_indexes}, + {"MATERIALIZED VIEW", NULL, NULL}, + {"OPERATOR", NULL, NULL}, /* Querying for this is probably not such a + * good idea. */ + {"OWNED", NULL, NULL, THING_NO_CREATE}, /* for DROP OWNED BY ... */ + {"PARSER", Query_for_list_of_ts_parsers, NULL, THING_NO_SHOW}, + {"POLICY", NULL, NULL}, + {"ROLE", Query_for_list_of_roles}, + {"RULE", "SELECT pg_catalog.quote_ident(rulename) FROM pg_catalog.pg_rules WHERE substring(pg_catalog.quote_ident(rulename),1,%d)='%s'"}, + {"SCHEMA", Query_for_list_of_schemas}, + {"SEQUENCE", NULL, &Query_for_list_of_sequences}, + {"SERVER", Query_for_list_of_servers}, + {"TABLE", NULL, &Query_for_list_of_tables}, + {"TABLESPACE", Query_for_list_of_tablespaces}, + {"TEMP", NULL, NULL, THING_NO_DROP}, /* for CREATE TEMP TABLE ... */ + {"TEMPLATE", Query_for_list_of_ts_templates, NULL, THING_NO_SHOW}, + {"TEXT SEARCH", NULL, NULL}, + {"TRIGGER", "SELECT pg_catalog.quote_ident(tgname) FROM pg_catalog.pg_trigger WHERE substring(pg_catalog.quote_ident(tgname),1,%d)='%s' AND NOT tgisinternal"}, + {"TYPE", NULL, &Query_for_list_of_datatypes}, + {"UNIQUE", NULL, NULL, THING_NO_DROP}, /* for CREATE UNIQUE INDEX ... */ + {"UNLOGGED", NULL, NULL, THING_NO_DROP}, /* for CREATE UNLOGGED TABLE + * ... */ + {"USER", Query_for_list_of_roles}, + {"USER MAPPING FOR", NULL, NULL}, + {"VIEW", NULL, &Query_for_list_of_views}, + {NULL} /* end of list */ +}; + + +/* Forward declaration of functions */ +static char **psql_completion(const char *text, int start, int end); +static char *create_command_generator(const char *text, int state); +static char *drop_command_generator(const char *text, int state); +static char *complete_from_query(const char *text, int state); +static char *complete_from_schema_query(const char *text, int state); +static char *_complete_from_query(int is_schema_query, + const char *text, int state); +static char *complete_from_list(const char *text, int state); +static char *complete_from_const(const char *text, int state); +static void append_variable_names(char ***varnames, int *nvars, + int *maxvars, const char *varname, + const char *prefix, const char *suffix); +static char **complete_from_variables(const char *text, + const char *prefix, const char *suffix, bool need_value); +static char *complete_from_files(const char *text, int state); + +static char *pg_strdup_keyword_case(const char *s, const char *ref); +static PGresult *exec_query(const char *query); + +static void get_previous_words(int point, char **previous_words, int nwords); + +#ifdef NOT_USED +static char *quote_file_name(char *text, int match_type, char *quote_pointer); +static char *dequote_file_name(char *text, char quote_char); +#endif + + +/* + * Initialize the readline library for our purposes. + */ +void +initialize_readline(void) +{ + rl_readline_name = (char *) pset.progname; + rl_attempted_completion_function = psql_completion; + + rl_basic_word_break_characters = WORD_BREAKS; + + completion_max_records = 1000; + + /* + * There is a variable rl_completion_query_items for this but apparently + * it's not defined everywhere. + */ +} + + +/* + * The completion function. + * + * According to readline spec this gets passed the text entered so far and its + * start and end positions in the readline buffer. The return value is some + * partially obscure list format that can be generated by readline's + * completion_matches() function, so we don't have to worry about it. + */ +static char ** +psql_completion(const char *text, int start, int end) +{ + /* This is the variable we'll return. */ + char **matches = NULL; + + /* This array will contain some scannage of the input line. */ + char *previous_words[6]; + + /* For compactness, we use these macros to reference previous_words[]. */ +#define prev_wd (previous_words[0]) +#define prev2_wd (previous_words[1]) +#define prev3_wd (previous_words[2]) +#define prev4_wd (previous_words[3]) +#define prev5_wd (previous_words[4]) +#define prev6_wd (previous_words[5]) + + static const char *const sql_commands[] = { + "ABORT", "ALTER", "ANALYZE", "BEGIN", "CHECKPOINT", "CLOSE", "CLUSTER", + "COMMENT", "COMMIT", "COPY", "CREATE", "DEALLOCATE", "DECLARE", + "DELETE FROM", "DISCARD", "DO", "DROP", "END", "EXECUTE", "EXPLAIN", + "FETCH", "GRANT", "IMPORT", "INSERT", "LISTEN", "LOAD", "LOCK", + "MOVE", "NOTIFY", "PREPARE", + "REASSIGN", "REFRESH", "REINDEX", "RELEASE", "RESET", "REVOKE", "ROLLBACK", + "SAVEPOINT", "SECURITY LABEL", "SELECT", "SET", "SHOW", "START", + "TABLE", "TRUNCATE", "UNLISTEN", "UPDATE", "VACUUM", "VALUES", "WITH", + NULL + }; + + static const char *const backslash_commands[] = { + "\\a", "\\connect", "\\conninfo", "\\C", "\\cd", "\\copy", "\\copyright", + "\\d", "\\da", "\\db", "\\dc", "\\dC", "\\dd", "\\ddp", "\\dD", + "\\des", "\\det", "\\deu", "\\dew", "\\dE", "\\df", + "\\dF", "\\dFd", "\\dFp", "\\dFt", "\\dg", "\\di", "\\dl", "\\dL", + "\\dm", "\\dn", "\\do", "\\dO", "\\dp", "\\drds", "\\ds", "\\dS", + "\\dt", "\\dT", "\\dv", "\\du", "\\dx", "\\dy", + "\\e", "\\echo", "\\ef", "\\encoding", + "\\f", "\\g", "\\gset", "\\h", "\\help", "\\H", "\\i", "\\ir", "\\l", + "\\lo_import", "\\lo_export", "\\lo_list", "\\lo_unlink", + "\\o", "\\p", "\\password", "\\prompt", "\\pset", "\\q", "\\qecho", "\\r", + "\\s", "\\set", "\\setenv", "\\sf", "\\t", "\\T", + "\\timing", "\\unset", "\\x", "\\w", "\\watch", "\\z", "\\!", NULL + }; + + (void) end; /* not used */ + +#ifdef HAVE_RL_COMPLETION_APPEND_CHARACTER + rl_completion_append_character = ' '; +#endif + + /* Clear a few things. */ + completion_charp = NULL; + completion_charpp = NULL; + completion_info_charp = NULL; + completion_info_charp2 = NULL; + + /* + * Scan the input line before our current position for the last few words. + * According to those we'll make some smart decisions on what the user is + * probably intending to type. + */ + get_previous_words(start, previous_words, lengthof(previous_words)); + + /* If a backslash command was started, continue */ + if (text[0] == '\\') + COMPLETE_WITH_LIST_CS(backslash_commands); + + /* Variable interpolation */ + else if (text[0] == ':' && text[1] != ':') + { + if (text[1] == '\'') + matches = complete_from_variables(text, ":'", "'", true); + else if (text[1] == '"') + matches = complete_from_variables(text, ":\"", "\"", true); + else + matches = complete_from_variables(text, ":", "", true); + } + + /* If no previous word, suggest one of the basic sql commands */ + else if (prev_wd[0] == '\0') + COMPLETE_WITH_LIST(sql_commands); + +/* CREATE */ + /* complete with something you can create */ + else if (pg_strcasecmp(prev_wd, "CREATE") == 0) + matches = completion_matches(text, create_command_generator); + +/* DROP, but not DROP embedded in other commands */ + /* complete with something you can drop */ + else if (pg_strcasecmp(prev_wd, "DROP") == 0 && + prev2_wd[0] == '\0') + matches = completion_matches(text, drop_command_generator); + +/* ALTER */ + + /* ALTER TABLE */ + else if (pg_strcasecmp(prev2_wd, "ALTER") == 0 && + pg_strcasecmp(prev_wd, "TABLE") == 0) + { + COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, + "UNION SELECT 'ALL IN TABLESPACE'"); + } + + /* + * complete with what you can alter (TABLE, GROUP, USER, ...) unless we're + * in ALTER TABLE sth ALTER + */ + else if (pg_strcasecmp(prev_wd, "ALTER") == 0 && + pg_strcasecmp(prev3_wd, "TABLE") != 0) + { + static const char *const list_ALTER[] = + {"AGGREGATE", "COLLATION", "CONVERSION", "DATABASE", "DEFAULT PRIVILEGES", "DOMAIN", + "EVENT TRIGGER", "EXTENSION", "FOREIGN DATA WRAPPER", "FOREIGN TABLE", "FUNCTION", + "GROUP", "INDEX", "LANGUAGE", "LARGE OBJECT", "MATERIALIZED VIEW", "OPERATOR", + "POLICY", "ROLE", "RULE", "SCHEMA", "SERVER", "SEQUENCE", "SYSTEM", "TABLE", + "TABLESPACE", "TEXT SEARCH", "TRIGGER", "TYPE", + "USER", "USER MAPPING FOR", "VIEW", NULL}; + + COMPLETE_WITH_LIST(list_ALTER); + } + /* ALTER TABLE,INDEX,MATERIALIZED VIEW ALL IN TABLESPACE xxx */ + else if (pg_strcasecmp(prev4_wd, "ALL") == 0 && + pg_strcasecmp(prev3_wd, "IN") == 0 && + pg_strcasecmp(prev2_wd, "TABLESPACE") == 0) + { + static const char *const list_ALTERALLINTSPC[] = + {"SET TABLESPACE", "OWNED BY", NULL}; + + COMPLETE_WITH_LIST(list_ALTERALLINTSPC); + } + /* ALTER TABLE,INDEX,MATERIALIZED VIEW ALL IN TABLESPACE xxx OWNED BY */ + else if (pg_strcasecmp(prev6_wd, "ALL") == 0 && + pg_strcasecmp(prev5_wd, "IN") == 0 && + pg_strcasecmp(prev4_wd, "TABLESPACE") == 0 && + pg_strcasecmp(prev2_wd, "OWNED") == 0 && + pg_strcasecmp(prev_wd, "BY") == 0) + { + COMPLETE_WITH_QUERY(Query_for_list_of_roles); + } + /* ALTER TABLE,INDEX,MATERIALIZED VIEW ALL IN TABLESPACE xxx OWNED BY xxx */ + else if (pg_strcasecmp(prev6_wd, "IN") == 0 && + pg_strcasecmp(prev5_wd, "TABLESPACE") == 0 && + pg_strcasecmp(prev3_wd, "OWNED") == 0 && + pg_strcasecmp(prev2_wd, "BY") == 0) + { + COMPLETE_WITH_CONST("SET TABLESPACE"); + } + /* ALTER AGGREGATE,FUNCTION */ + else if (pg_strcasecmp(prev3_wd, "ALTER") == 0 && + (pg_strcasecmp(prev2_wd, "AGGREGATE") == 0 || + pg_strcasecmp(prev2_wd, "FUNCTION") == 0)) + COMPLETE_WITH_CONST("("); + /* ALTER AGGREGATE,FUNCTION (...) */ + else if (pg_strcasecmp(prev4_wd, "ALTER") == 0 && + (pg_strcasecmp(prev3_wd, "AGGREGATE") == 0 || + pg_strcasecmp(prev3_wd, "FUNCTION") == 0)) + { + if (prev_wd[strlen(prev_wd) - 1] == ')') + { + static const char *const list_ALTERAGG[] = + {"OWNER TO", "RENAME TO", "SET SCHEMA", NULL}; + + COMPLETE_WITH_LIST(list_ALTERAGG); + } + else + COMPLETE_WITH_FUNCTION_ARG(prev2_wd); + } + + /* ALTER SCHEMA */ + else if (pg_strcasecmp(prev3_wd, "ALTER") == 0 && + pg_strcasecmp(prev2_wd, "SCHEMA") == 0) + { + static const char *const list_ALTERGEN[] = + {"OWNER TO", "RENAME TO", NULL}; + + COMPLETE_WITH_LIST(list_ALTERGEN); + } + + /* ALTER COLLATION */ + else if (pg_strcasecmp(prev3_wd, "ALTER") == 0 && + pg_strcasecmp(prev2_wd, "COLLATION") == 0) + { + static const char *const list_ALTERGEN[] = + {"OWNER TO", "RENAME TO", "SET SCHEMA", NULL}; + + COMPLETE_WITH_LIST(list_ALTERGEN); + } + + /* ALTER CONVERSION */ + else if (pg_strcasecmp(prev3_wd, "ALTER") == 0 && + pg_strcasecmp(prev2_wd, "CONVERSION") == 0) + { + static const char *const list_ALTERGEN[] = + {"OWNER TO", "RENAME TO", "SET SCHEMA", NULL}; + + COMPLETE_WITH_LIST(list_ALTERGEN); + } + + /* ALTER DATABASE */ + else if (pg_strcasecmp(prev3_wd, "ALTER") == 0 && + pg_strcasecmp(prev2_wd, "DATABASE") == 0) + { + static const char *const list_ALTERDATABASE[] = + {"RESET", "SET", "OWNER TO", "RENAME TO", "IS_TEMPLATE", + "ALLOW_CONNECTIONS", "CONNECTION LIMIT", NULL}; + + COMPLETE_WITH_LIST(list_ALTERDATABASE); + } + + /* ALTER EVENT TRIGGER */ + else if (pg_strcasecmp(prev3_wd, "ALTER") == 0 && + pg_strcasecmp(prev2_wd, "EVENT") == 0 && + pg_strcasecmp(prev_wd, "TRIGGER") == 0) + { + COMPLETE_WITH_QUERY(Query_for_list_of_event_triggers); + } + + /* ALTER EVENT TRIGGER */ + else if (pg_strcasecmp(prev4_wd, "ALTER") == 0 && + pg_strcasecmp(prev3_wd, "EVENT") == 0 && + pg_strcasecmp(prev2_wd, "TRIGGER") == 0) + { + static const char *const list_ALTER_EVENT_TRIGGER[] = + {"DISABLE", "ENABLE", "OWNER TO", "RENAME TO", NULL}; + + COMPLETE_WITH_LIST(list_ALTER_EVENT_TRIGGER); + } + + /* ALTER EVENT TRIGGER ENABLE */ + else if (pg_strcasecmp(prev5_wd, "ALTER") == 0 && + pg_strcasecmp(prev4_wd, "EVENT") == 0 && + pg_strcasecmp(prev3_wd, "TRIGGER") == 0 && + pg_strcasecmp(prev_wd, "ENABLE") == 0) + { + static const char *const list_ALTER_EVENT_TRIGGER_ENABLE[] = + {"REPLICA", "ALWAYS", NULL}; + + COMPLETE_WITH_LIST(list_ALTER_EVENT_TRIGGER_ENABLE); + } + + /* ALTER EXTENSION */ + else if (pg_strcasecmp(prev3_wd, "ALTER") == 0 && + pg_strcasecmp(prev2_wd, "EXTENSION") == 0) + { + static const char *const list_ALTEREXTENSION[] = + {"ADD", "DROP", "UPDATE", "SET SCHEMA", NULL}; + + COMPLETE_WITH_LIST(list_ALTEREXTENSION); + } + + /* ALTER FOREIGN */ + else if (pg_strcasecmp(prev2_wd, "ALTER") == 0 && + pg_strcasecmp(prev_wd, "FOREIGN") == 0) + { + static const char *const list_ALTER_FOREIGN[] = + {"DATA WRAPPER", "TABLE", NULL}; + + COMPLETE_WITH_LIST(list_ALTER_FOREIGN); + } + + /* ALTER FOREIGN DATA WRAPPER */ + else if (pg_strcasecmp(prev5_wd, "ALTER") == 0 && + pg_strcasecmp(prev4_wd, "FOREIGN") == 0 && + pg_strcasecmp(prev3_wd, "DATA") == 0 && + pg_strcasecmp(prev2_wd, "WRAPPER") == 0) + { + static const char *const list_ALTER_FDW[] = + {"HANDLER", "VALIDATOR", "OPTIONS", "OWNER TO", NULL}; + + COMPLETE_WITH_LIST(list_ALTER_FDW); + } + + /* ALTER FOREIGN TABLE */ + else if (pg_strcasecmp(prev4_wd, "ALTER") == 0 && + pg_strcasecmp(prev3_wd, "FOREIGN") == 0 && + pg_strcasecmp(prev2_wd, "TABLE") == 0) + { + static const char *const list_ALTER_FOREIGN_TABLE[] = + {"ADD", "ALTER", "DISABLE TRIGGER", "DROP", "ENABLE", "INHERIT", + "NO INHERIT", "OPTIONS", "OWNER TO", "RENAME", "SET", + "VALIDATE CONSTRAINT", NULL}; + + COMPLETE_WITH_LIST(list_ALTER_FOREIGN_TABLE); + } + + /* ALTER INDEX */ + else if (pg_strcasecmp(prev2_wd, "ALTER") == 0 && + pg_strcasecmp(prev_wd, "INDEX") == 0) + { + COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes, + "UNION SELECT 'ALL IN TABLESPACE'"); + } + /* ALTER INDEX */ + else if (pg_strcasecmp(prev3_wd, "ALTER") == 0 && + pg_strcasecmp(prev2_wd, "INDEX") == 0) + { + static const char *const list_ALTERINDEX[] = + {"OWNER TO", "RENAME TO", "SET", "RESET", NULL}; + + COMPLETE_WITH_LIST(list_ALTERINDEX); + } + /* ALTER INDEX SET */ + else if (pg_strcasecmp(prev4_wd, "ALTER") == 0 && + pg_strcasecmp(prev3_wd, "INDEX") == 0 && + pg_strcasecmp(prev_wd, "SET") == 0) + { + static const char *const list_ALTERINDEXSET[] = + {"(", "TABLESPACE", NULL}; + + COMPLETE_WITH_LIST(list_ALTERINDEXSET); + } + /* ALTER INDEX RESET */ + else if (pg_strcasecmp(prev4_wd, "ALTER") == 0 && + pg_strcasecmp(prev3_wd, "INDEX") == 0 && + pg_strcasecmp(prev_wd, "RESET") == 0) + COMPLETE_WITH_CONST("("); + /* ALTER INDEX SET|RESET ( */ + else if (pg_strcasecmp(prev5_wd, "ALTER") == 0 && + pg_strcasecmp(prev4_wd, "INDEX") == 0 && + (pg_strcasecmp(prev2_wd, "SET") == 0 || + pg_strcasecmp(prev2_wd, "RESET") == 0) && + pg_strcasecmp(prev_wd, "(") == 0) + { + static const char *const list_INDEXOPTIONS[] = + {"fillfactor", "fastupdate", "gin_pending_list_limit", NULL}; + + COMPLETE_WITH_LIST(list_INDEXOPTIONS); + } + + /* ALTER LANGUAGE */ + else if (pg_strcasecmp(prev3_wd, "ALTER") == 0 && + pg_strcasecmp(prev2_wd, "LANGUAGE") == 0) + { + static const char *const list_ALTERLANGUAGE[] = + {"OWNER TO", "RENAME TO", NULL}; + + COMPLETE_WITH_LIST(list_ALTERLANGUAGE); + } + + /* ALTER LARGE OBJECT */ + else if (pg_strcasecmp(prev4_wd, "ALTER") == 0 && + pg_strcasecmp(prev3_wd, "LARGE") == 0 && + pg_strcasecmp(prev2_wd, "OBJECT") == 0) + { + static const char *const list_ALTERLARGEOBJECT[] = + {"OWNER TO", NULL}; + + COMPLETE_WITH_LIST(list_ALTERLARGEOBJECT); + } + + /* ALTER MATERIALIZED VIEW */ + else if (pg_strcasecmp(prev3_wd, "ALTER") == 0 && + pg_strcasecmp(prev2_wd, "MATERIALIZED") == 0 && + pg_strcasecmp(prev_wd, "VIEW") == 0) + { + COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_matviews, + "UNION SELECT 'ALL IN TABLESPACE'"); + } + + /* ALTER USER,ROLE */ + else if (pg_strcasecmp(prev3_wd, "ALTER") == 0 && + !(pg_strcasecmp(prev2_wd, "USER") == 0 && pg_strcasecmp(prev_wd, "MAPPING") == 0) && + (pg_strcasecmp(prev2_wd, "USER") == 0 || + pg_strcasecmp(prev2_wd, "ROLE") == 0)) + { + static const char *const list_ALTERUSER[] = + {"BYPASSRLS", "CONNECTION LIMIT", "CREATEDB", "CREATEROLE", + "CREATEUSER", "ENCRYPTED", "INHERIT", "LOGIN", "NOBYPASSRLS", + "NOCREATEDB", "NOCREATEROLE", "NOCREATEUSER", "NOINHERIT", + "NOLOGIN", "NOREPLICATION", "NOSUPERUSER", "PASSWORD", "RENAME TO", + "REPLICATION", "RESET", "SET", "SUPERUSER", "UNENCRYPTED", + "VALID UNTIL", "WITH", NULL}; + + COMPLETE_WITH_LIST(list_ALTERUSER); + } + + /* ALTER USER,ROLE WITH */ + else if ((pg_strcasecmp(prev4_wd, "ALTER") == 0 && + (pg_strcasecmp(prev3_wd, "USER") == 0 || + pg_strcasecmp(prev3_wd, "ROLE") == 0) && + pg_strcasecmp(prev_wd, "WITH") == 0)) + { + /* Similar to the above, but don't complete "WITH" again. */ + static const char *const list_ALTERUSER_WITH[] = + {"BYPASSRLS", "CONNECTION LIMIT", "CREATEDB", "CREATEROLE", + "CREATEUSER", "ENCRYPTED", "INHERIT", "LOGIN", "NOBYPASSRLS", + "NOCREATEDB", "NOCREATEROLE", "NOCREATEUSER", "NOINHERIT", + "NOLOGIN", "NOREPLICATION", "NOSUPERUSER", "PASSWORD", "RENAME TO", + "REPLICATION", "RESET", "SET", "SUPERUSER", "UNENCRYPTED", + "VALID UNTIL", NULL}; + + COMPLETE_WITH_LIST(list_ALTERUSER_WITH); + } + + /* complete ALTER USER,ROLE ENCRYPTED,UNENCRYPTED with PASSWORD */ + else if (pg_strcasecmp(prev4_wd, "ALTER") == 0 && + (pg_strcasecmp(prev3_wd, "ROLE") == 0 || pg_strcasecmp(prev3_wd, "USER") == 0) && + (pg_strcasecmp(prev_wd, "ENCRYPTED") == 0 || pg_strcasecmp(prev_wd, "UNENCRYPTED") == 0)) + { + COMPLETE_WITH_CONST("PASSWORD"); + } + /* ALTER DEFAULT PRIVILEGES */ + else if (pg_strcasecmp(prev3_wd, "ALTER") == 0 && + pg_strcasecmp(prev2_wd, "DEFAULT") == 0 && + pg_strcasecmp(prev_wd, "PRIVILEGES") == 0) + { + static const char *const list_ALTER_DEFAULT_PRIVILEGES[] = + {"FOR ROLE", "FOR USER", "IN SCHEMA", NULL}; + + COMPLETE_WITH_LIST(list_ALTER_DEFAULT_PRIVILEGES); + } + /* ALTER DEFAULT PRIVILEGES FOR */ + else if (pg_strcasecmp(prev4_wd, "ALTER") == 0 && + pg_strcasecmp(prev3_wd, "DEFAULT") == 0 && + pg_strcasecmp(prev2_wd, "PRIVILEGES") == 0 && + pg_strcasecmp(prev_wd, "FOR") == 0) + { + static const char *const list_ALTER_DEFAULT_PRIVILEGES_FOR[] = + {"ROLE", "USER", NULL}; + + COMPLETE_WITH_LIST(list_ALTER_DEFAULT_PRIVILEGES_FOR); + } + /* ALTER DEFAULT PRIVILEGES { FOR ROLE ... | IN SCHEMA ... } */ + else if (pg_strcasecmp(prev5_wd, "DEFAULT") == 0 && + pg_strcasecmp(prev4_wd, "PRIVILEGES") == 0 && + (pg_strcasecmp(prev3_wd, "FOR") == 0 || + pg_strcasecmp(prev3_wd, "IN") == 0)) + { + static const char *const list_ALTER_DEFAULT_PRIVILEGES_REST[] = + {"GRANT", "REVOKE", NULL}; + + COMPLETE_WITH_LIST(list_ALTER_DEFAULT_PRIVILEGES_REST); + } + /* ALTER DOMAIN */ + else if (pg_strcasecmp(prev3_wd, "ALTER") == 0 && + pg_strcasecmp(prev2_wd, "DOMAIN") == 0) + { + static const char *const list_ALTERDOMAIN[] = + {"ADD", "DROP", "OWNER TO", "RENAME", "SET", "VALIDATE CONSTRAINT", NULL}; + + COMPLETE_WITH_LIST(list_ALTERDOMAIN); + } + /* ALTER DOMAIN DROP */ + else if (pg_strcasecmp(prev4_wd, "ALTER") == 0 && + pg_strcasecmp(prev3_wd, "DOMAIN") == 0 && + pg_strcasecmp(prev_wd, "DROP") == 0) + { + static const char *const list_ALTERDOMAIN2[] = + {"CONSTRAINT", "DEFAULT", "NOT NULL", NULL}; + + COMPLETE_WITH_LIST(list_ALTERDOMAIN2); + } + /* ALTER DOMAIN DROP|RENAME|VALIDATE CONSTRAINT */ + else if (pg_strcasecmp(prev5_wd, "ALTER") == 0 && + pg_strcasecmp(prev4_wd, "DOMAIN") == 0 && + (pg_strcasecmp(prev2_wd, "DROP") == 0 || + pg_strcasecmp(prev2_wd, "RENAME") == 0 || + pg_strcasecmp(prev2_wd, "VALIDATE") == 0) && + pg_strcasecmp(prev_wd, "CONSTRAINT") == 0) + { + completion_info_charp = prev3_wd; + COMPLETE_WITH_QUERY(Query_for_constraint_of_type); + } + /* ALTER DOMAIN RENAME */ + else if (pg_strcasecmp(prev4_wd, "ALTER") == 0 && + pg_strcasecmp(prev3_wd, "DOMAIN") == 0 && + pg_strcasecmp(prev_wd, "RENAME") == 0) + { + static const char *const list_ALTERDOMAIN[] = + {"CONSTRAINT", "TO", NULL}; + + COMPLETE_WITH_LIST(list_ALTERDOMAIN); + } + /* ALTER DOMAIN RENAME CONSTRAINT */ + else if (pg_strcasecmp(prev5_wd, "DOMAIN") == 0 && + pg_strcasecmp(prev3_wd, "RENAME") == 0 && + pg_strcasecmp(prev2_wd, "CONSTRAINT") == 0) + COMPLETE_WITH_CONST("TO"); + + /* ALTER DOMAIN SET */ + else if (pg_strcasecmp(prev4_wd, "ALTER") == 0 && + pg_strcasecmp(prev3_wd, "DOMAIN") == 0 && + pg_strcasecmp(prev_wd, "SET") == 0) + { + static const char *const list_ALTERDOMAIN3[] = + {"DEFAULT", "NOT NULL", "SCHEMA", NULL}; + + COMPLETE_WITH_LIST(list_ALTERDOMAIN3); + } + /* ALTER SEQUENCE */ + else if (pg_strcasecmp(prev3_wd, "ALTER") == 0 && + pg_strcasecmp(prev2_wd, "SEQUENCE") == 0) + { + static const char *const list_ALTERSEQUENCE[] = + {"INCREMENT", "MINVALUE", "MAXVALUE", "RESTART", "NO", "CACHE", "CYCLE", + "SET SCHEMA", "OWNED BY", "OWNER TO", "RENAME TO", NULL}; + + COMPLETE_WITH_LIST(list_ALTERSEQUENCE); + } + /* ALTER SEQUENCE NO */ + else if (pg_strcasecmp(prev4_wd, "ALTER") == 0 && + pg_strcasecmp(prev3_wd, "SEQUENCE") == 0 && + pg_strcasecmp(prev_wd, "NO") == 0) + { + static const char *const list_ALTERSEQUENCE2[] = + {"MINVALUE", "MAXVALUE", "CYCLE", NULL}; + + COMPLETE_WITH_LIST(list_ALTERSEQUENCE2); + } + /* ALTER SERVER */ + else if (pg_strcasecmp(prev3_wd, "ALTER") == 0 && + pg_strcasecmp(prev2_wd, "SERVER") == 0) + { + static const char *const list_ALTER_SERVER[] = + {"VERSION", "OPTIONS", "OWNER TO", NULL}; + + COMPLETE_WITH_LIST(list_ALTER_SERVER); + } + /* ALTER SYSTEM SET, RESET, RESET ALL */ + else if (pg_strcasecmp(prev2_wd, "ALTER") == 0 && + pg_strcasecmp(prev_wd, "SYSTEM") == 0) + { + static const char *const list_ALTERSYSTEM[] = + {"SET", "RESET", NULL}; + + COMPLETE_WITH_LIST(list_ALTERSYSTEM); + } + /* ALTER SYSTEM SET|RESET */ + else if (pg_strcasecmp(prev3_wd, "ALTER") == 0 && + pg_strcasecmp(prev2_wd, "SYSTEM") == 0 && + (pg_strcasecmp(prev_wd, "SET") == 0 || + pg_strcasecmp(prev_wd, "RESET") == 0)) + COMPLETE_WITH_QUERY(Query_for_list_of_alter_system_set_vars); + /* ALTER VIEW */ + else if (pg_strcasecmp(prev3_wd, "ALTER") == 0 && + pg_strcasecmp(prev2_wd, "VIEW") == 0) + { + static const char *const list_ALTERVIEW[] = + {"ALTER COLUMN", "OWNER TO", "RENAME TO", "SET SCHEMA", NULL}; + + COMPLETE_WITH_LIST(list_ALTERVIEW); + } + /* ALTER MATERIALIZED VIEW */ + else if (pg_strcasecmp(prev4_wd, "ALTER") == 0 && + pg_strcasecmp(prev3_wd, "MATERIALIZED") == 0 && + pg_strcasecmp(prev2_wd, "VIEW") == 0) + { + static const char *const list_ALTERMATVIEW[] = + {"ALTER COLUMN", "OWNER TO", "RENAME TO", "SET SCHEMA", NULL}; + + COMPLETE_WITH_LIST(list_ALTERMATVIEW); + } + + /* ALTER POLICY */ + else if (pg_strcasecmp(prev2_wd, "ALTER") == 0 && + pg_strcasecmp(prev_wd, "POLICY") == 0) + COMPLETE_WITH_QUERY(Query_for_list_of_policies); + /* ALTER POLICY ON */ + else if (pg_strcasecmp(prev3_wd, "ALTER") == 0 && + pg_strcasecmp(prev2_wd, "POLICY") == 0) + COMPLETE_WITH_CONST("ON"); + /* ALTER POLICY ON
*/ + else if (pg_strcasecmp(prev4_wd, "ALTER") == 0 && + pg_strcasecmp(prev3_wd, "POLICY") == 0 && + pg_strcasecmp(prev_wd, "ON") == 0) + { + completion_info_charp = prev2_wd; + COMPLETE_WITH_QUERY(Query_for_list_of_tables_for_policy); + } + /* ALTER POLICY ON
- show options */ + else if (pg_strcasecmp(prev5_wd, "ALTER") == 0 && + pg_strcasecmp(prev4_wd, "POLICY") == 0 && + pg_strcasecmp(prev2_wd, "ON") == 0) + { + static const char *const list_ALTERPOLICY[] = + {"RENAME TO", "TO", "USING", "WITH CHECK", NULL}; + + COMPLETE_WITH_LIST(list_ALTERPOLICY); + } + /* ALTER POLICY ON
TO */ + else if (pg_strcasecmp(prev6_wd, "ALTER") == 0 && + pg_strcasecmp(prev5_wd, "POLICY") == 0 && + pg_strcasecmp(prev3_wd, "ON") == 0 && + pg_strcasecmp(prev_wd, "TO") == 0) + COMPLETE_WITH_QUERY(Query_for_list_of_grant_roles); + /* ALTER POLICY ON
USING ( */ + else if (pg_strcasecmp(prev6_wd, "ALTER") == 0 && + pg_strcasecmp(prev5_wd, "POLICY") == 0 && + pg_strcasecmp(prev3_wd, "ON") == 0 && + pg_strcasecmp(prev_wd, "USING") == 0) + COMPLETE_WITH_CONST("("); + /* ALTER POLICY ON
WITH CHECK ( */ + else if (pg_strcasecmp(prev6_wd, "POLICY") == 0 && + pg_strcasecmp(prev4_wd, "ON") == 0 && + pg_strcasecmp(prev2_wd, "WITH") == 0 && + pg_strcasecmp(prev_wd, "CHECK") == 0) + COMPLETE_WITH_CONST("("); + + /* ALTER RULE , add ON */ + else if (pg_strcasecmp(prev3_wd, "ALTER") == 0 && + pg_strcasecmp(prev2_wd, "RULE") == 0) + COMPLETE_WITH_CONST("ON"); + + /* If we have ALTER RULE ON, then add the correct tablename */ + else if (pg_strcasecmp(prev4_wd, "ALTER") == 0 && + pg_strcasecmp(prev3_wd, "RULE") == 0 && + pg_strcasecmp(prev_wd, "ON") == 0) + { + completion_info_charp = prev2_wd; + COMPLETE_WITH_QUERY(Query_for_list_of_tables_for_rule); + } + + /* ALTER RULE ON */ + else if (pg_strcasecmp(prev5_wd, "ALTER") == 0 && + pg_strcasecmp(prev4_wd, "RULE") == 0) + COMPLETE_WITH_CONST("RENAME TO"); + + /* ALTER TRIGGER , add ON */ + else if (pg_strcasecmp(prev3_wd, "ALTER") == 0 && + pg_strcasecmp(prev2_wd, "TRIGGER") == 0) + COMPLETE_WITH_CONST("ON"); + + else if (pg_strcasecmp(prev4_wd, "ALTER") == 0 && + pg_strcasecmp(prev3_wd, "TRIGGER") == 0) + { + completion_info_charp = prev2_wd; + COMPLETE_WITH_QUERY(Query_for_list_of_tables_for_trigger); + } + + /* + * If we have ALTER TRIGGER ON, then add the correct tablename + */ + else if (pg_strcasecmp(prev4_wd, "ALTER") == 0 && + pg_strcasecmp(prev3_wd, "TRIGGER") == 0 && + pg_strcasecmp(prev_wd, "ON") == 0) + COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL); + + /* ALTER TRIGGER ON */ + else if (pg_strcasecmp(prev5_wd, "ALTER") == 0 && + pg_strcasecmp(prev4_wd, "TRIGGER") == 0 && + pg_strcasecmp(prev2_wd, "ON") == 0) + COMPLETE_WITH_CONST("RENAME TO"); + + /* + * If we detect ALTER TABLE , suggest sub commands + */ + else if (pg_strcasecmp(prev3_wd, "ALTER") == 0 && + pg_strcasecmp(prev2_wd, "TABLE") == 0) + { + static const char *const list_ALTER2[] = + {"ADD", "ALTER", "CLUSTER ON", "DISABLE", "DROP", "ENABLE", "INHERIT", + "NO INHERIT", "RENAME", "RESET", "OWNER TO", "SET", + "VALIDATE CONSTRAINT", "REPLICA IDENTITY", NULL}; + + COMPLETE_WITH_LIST(list_ALTER2); + } + /* ALTER TABLE xxx ENABLE */ + else if (pg_strcasecmp(prev4_wd, "ALTER") == 0 && + pg_strcasecmp(prev3_wd, "TABLE") == 0 && + pg_strcasecmp(prev_wd, "ENABLE") == 0) + { + static const char *const list_ALTERENABLE[] = + {"ALWAYS", "REPLICA", "ROW LEVEL SECURITY", "RULE", "TRIGGER", NULL}; + + COMPLETE_WITH_LIST(list_ALTERENABLE); + } + else if (pg_strcasecmp(prev4_wd, "TABLE") == 0 && + pg_strcasecmp(prev2_wd, "ENABLE") == 0 && + (pg_strcasecmp(prev_wd, "REPLICA") == 0 || + pg_strcasecmp(prev_wd, "ALWAYS") == 0)) + { + static const char *const list_ALTERENABLE2[] = + {"RULE", "TRIGGER", NULL}; + + COMPLETE_WITH_LIST(list_ALTERENABLE2); + } + else if (pg_strcasecmp(prev5_wd, "ALTER") == 0 && + pg_strcasecmp(prev4_wd, "TABLE") == 0 && + pg_strcasecmp(prev2_wd, "ENABLE") == 0 && + pg_strcasecmp(prev_wd, "RULE") == 0) + { + completion_info_charp = prev3_wd; + COMPLETE_WITH_QUERY(Query_for_rule_of_table); + } + else if (pg_strcasecmp(prev6_wd, "ALTER") == 0 && + pg_strcasecmp(prev5_wd, "TABLE") == 0 && + pg_strcasecmp(prev3_wd, "ENABLE") == 0 && + pg_strcasecmp(prev_wd, "RULE") == 0) + { + completion_info_charp = prev4_wd; + COMPLETE_WITH_QUERY(Query_for_rule_of_table); + } + else if (pg_strcasecmp(prev5_wd, "ALTER") == 0 && + pg_strcasecmp(prev4_wd, "TABLE") == 0 && + pg_strcasecmp(prev2_wd, "ENABLE") == 0 && + pg_strcasecmp(prev_wd, "TRIGGER") == 0) + { + completion_info_charp = prev3_wd; + COMPLETE_WITH_QUERY(Query_for_trigger_of_table); + } + else if (pg_strcasecmp(prev6_wd, "ALTER") == 0 && + pg_strcasecmp(prev5_wd, "TABLE") == 0 && + pg_strcasecmp(prev3_wd, "ENABLE") == 0 && + pg_strcasecmp(prev_wd, "TRIGGER") == 0) + { + completion_info_charp = prev4_wd; + COMPLETE_WITH_QUERY(Query_for_trigger_of_table); + } + /* ALTER TABLE xxx INHERIT */ + else if (pg_strcasecmp(prev4_wd, "ALTER") == 0 && + pg_strcasecmp(prev3_wd, "TABLE") == 0 && + pg_strcasecmp(prev_wd, "INHERIT") == 0) + { + COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, ""); + } + /* ALTER TABLE xxx NO INHERIT */ + else if (pg_strcasecmp(prev5_wd, "ALTER") == 0 && + pg_strcasecmp(prev4_wd, "TABLE") == 0 && + pg_strcasecmp(prev2_wd, "NO") == 0 && + pg_strcasecmp(prev_wd, "INHERIT") == 0) + { + COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, ""); + } + /* ALTER TABLE xxx DISABLE */ + else if (pg_strcasecmp(prev4_wd, "ALTER") == 0 && + pg_strcasecmp(prev3_wd, "TABLE") == 0 && + pg_strcasecmp(prev_wd, "DISABLE") == 0) + { + static const char *const list_ALTERDISABLE[] = + {"ROW LEVEL SECURITY", "RULE", "TRIGGER", NULL}; + + COMPLETE_WITH_LIST(list_ALTERDISABLE); + } + else if (pg_strcasecmp(prev5_wd, "ALTER") == 0 && + pg_strcasecmp(prev4_wd, "TABLE") == 0 && + pg_strcasecmp(prev2_wd, "DISABLE") == 0 && + pg_strcasecmp(prev_wd, "RULE") == 0) + { + completion_info_charp = prev3_wd; + COMPLETE_WITH_QUERY(Query_for_rule_of_table); + } + else if (pg_strcasecmp(prev5_wd, "ALTER") == 0 && + pg_strcasecmp(prev4_wd, "TABLE") == 0 && + pg_strcasecmp(prev2_wd, "DISABLE") == 0 && + pg_strcasecmp(prev_wd, "TRIGGER") == 0) + { + completion_info_charp = prev3_wd; + COMPLETE_WITH_QUERY(Query_for_trigger_of_table); + } + else if (pg_strcasecmp(prev4_wd, "DISABLE") == 0 && + pg_strcasecmp(prev3_wd, "ROW") == 0 && + pg_strcasecmp(prev2_wd, "LEVEL") == 0 && + pg_strcasecmp(prev_wd, "SECURITY") == 0) + { + static const char *const list_DISABLERLS[] = + {"CASCADE", NULL}; + + COMPLETE_WITH_LIST(list_DISABLERLS); + } + + /* ALTER TABLE xxx ALTER */ + else if (pg_strcasecmp(prev4_wd, "ALTER") == 0 && + pg_strcasecmp(prev3_wd, "TABLE") == 0 && + pg_strcasecmp(prev_wd, "ALTER") == 0) + COMPLETE_WITH_ATTR(prev2_wd, " UNION SELECT 'COLUMN' UNION SELECT 'CONSTRAINT'"); + + /* ALTER TABLE xxx RENAME */ + else if (pg_strcasecmp(prev4_wd, "ALTER") == 0 && + pg_strcasecmp(prev3_wd, "TABLE") == 0 && + pg_strcasecmp(prev_wd, "RENAME") == 0) + COMPLETE_WITH_ATTR(prev2_wd, " UNION SELECT 'COLUMN' UNION SELECT 'CONSTRAINT' UNION SELECT 'TO'"); + + /* + * If we have TABLE ALTER COLUMN|RENAME COLUMN, provide list of + * columns + */ + else if (pg_strcasecmp(prev4_wd, "TABLE") == 0 && + (pg_strcasecmp(prev2_wd, "ALTER") == 0 || + pg_strcasecmp(prev2_wd, "RENAME") == 0) && + pg_strcasecmp(prev_wd, "COLUMN") == 0) + COMPLETE_WITH_ATTR(prev3_wd, ""); + + /* ALTER TABLE xxx RENAME yyy */ + else if (pg_strcasecmp(prev4_wd, "TABLE") == 0 && + pg_strcasecmp(prev2_wd, "RENAME") == 0 && + pg_strcasecmp(prev_wd, "CONSTRAINT") != 0 && + pg_strcasecmp(prev_wd, "TO") != 0) + COMPLETE_WITH_CONST("TO"); + + /* ALTER TABLE xxx RENAME COLUMN/CONSTRAINT yyy */ + else if (pg_strcasecmp(prev5_wd, "TABLE") == 0 && + pg_strcasecmp(prev3_wd, "RENAME") == 0 && + (pg_strcasecmp(prev2_wd, "COLUMN") == 0 || + pg_strcasecmp(prev2_wd, "CONSTRAINT") == 0) && + pg_strcasecmp(prev_wd, "TO") != 0) + COMPLETE_WITH_CONST("TO"); + + /* If we have TABLE DROP, provide COLUMN or CONSTRAINT */ + else if (pg_strcasecmp(prev3_wd, "TABLE") == 0 && + pg_strcasecmp(prev_wd, "DROP") == 0) + { + static const char *const list_TABLEDROP[] = + {"COLUMN", "CONSTRAINT", NULL}; + + COMPLETE_WITH_LIST(list_TABLEDROP); + } + /* If we have ALTER TABLE DROP COLUMN, provide list of columns */ + else if (pg_strcasecmp(prev5_wd, "ALTER") == 0 && + pg_strcasecmp(prev4_wd, "TABLE") == 0 && + pg_strcasecmp(prev2_wd, "DROP") == 0 && + pg_strcasecmp(prev_wd, "COLUMN") == 0) + COMPLETE_WITH_ATTR(prev3_wd, ""); + + /* + * If we have ALTER TABLE ALTER|DROP|RENAME|VALIDATE CONSTRAINT, + * provide list of constraints + */ + else if (pg_strcasecmp(prev5_wd, "ALTER") == 0 && + pg_strcasecmp(prev4_wd, "TABLE") == 0 && + (pg_strcasecmp(prev2_wd, "ALTER") == 0 || + pg_strcasecmp(prev2_wd, "DROP") == 0 || + pg_strcasecmp(prev2_wd, "RENAME") == 0 || + pg_strcasecmp(prev2_wd, "VALIDATE") == 0) && + pg_strcasecmp(prev_wd, "CONSTRAINT") == 0) + { + completion_info_charp = prev3_wd; + COMPLETE_WITH_QUERY(Query_for_constraint_of_table); + } + /* ALTER TABLE ALTER [COLUMN] */ + else if ((pg_strcasecmp(prev3_wd, "ALTER") == 0 && + pg_strcasecmp(prev2_wd, "COLUMN") == 0) || + (pg_strcasecmp(prev4_wd, "TABLE") == 0 && + pg_strcasecmp(prev2_wd, "ALTER") == 0)) + { + static const char *const list_COLUMNALTER[] = + {"TYPE", "SET", "RESET", "DROP", NULL}; + + COMPLETE_WITH_LIST(list_COLUMNALTER); + } + /* ALTER TABLE ALTER [COLUMN] SET */ + else if (((pg_strcasecmp(prev4_wd, "ALTER") == 0 && + pg_strcasecmp(prev3_wd, "COLUMN") == 0) || + (pg_strcasecmp(prev5_wd, "TABLE") == 0 && + pg_strcasecmp(prev3_wd, "ALTER") == 0)) && + pg_strcasecmp(prev_wd, "SET") == 0) + { + static const char *const list_COLUMNSET[] = + {"(", "DEFAULT", "NOT NULL", "STATISTICS", "STORAGE", NULL}; + + COMPLETE_WITH_LIST(list_COLUMNSET); + } + /* ALTER TABLE ALTER [COLUMN] SET ( */ + else if (((pg_strcasecmp(prev5_wd, "ALTER") == 0 && + pg_strcasecmp(prev4_wd, "COLUMN") == 0) || + pg_strcasecmp(prev4_wd, "ALTER") == 0) && + pg_strcasecmp(prev2_wd, "SET") == 0 && + pg_strcasecmp(prev_wd, "(") == 0) + { + static const char *const list_COLUMNOPTIONS[] = + {"n_distinct", "n_distinct_inherited", NULL}; + + COMPLETE_WITH_LIST(list_COLUMNOPTIONS); + } + /* ALTER TABLE ALTER [COLUMN] SET STORAGE */ + else if (((pg_strcasecmp(prev5_wd, "ALTER") == 0 && + pg_strcasecmp(prev4_wd, "COLUMN") == 0) || + pg_strcasecmp(prev4_wd, "ALTER") == 0) && + pg_strcasecmp(prev2_wd, "SET") == 0 && + pg_strcasecmp(prev_wd, "STORAGE") == 0) + { + static const char *const list_COLUMNSTORAGE[] = + {"PLAIN", "EXTERNAL", "EXTENDED", "MAIN", NULL}; + + COMPLETE_WITH_LIST(list_COLUMNSTORAGE); + } + /* ALTER TABLE ALTER [COLUMN] DROP */ + else if (((pg_strcasecmp(prev4_wd, "ALTER") == 0 && + pg_strcasecmp(prev3_wd, "COLUMN") == 0) || + (pg_strcasecmp(prev5_wd, "TABLE") == 0 && + pg_strcasecmp(prev3_wd, "ALTER") == 0)) && + pg_strcasecmp(prev_wd, "DROP") == 0) + { + static const char *const list_COLUMNDROP[] = + {"DEFAULT", "NOT NULL", NULL}; + + COMPLETE_WITH_LIST(list_COLUMNDROP); + } + else if (pg_strcasecmp(prev3_wd, "TABLE") == 0 && + pg_strcasecmp(prev_wd, "CLUSTER") == 0) + COMPLETE_WITH_CONST("ON"); + else if (pg_strcasecmp(prev4_wd, "TABLE") == 0 && + pg_strcasecmp(prev2_wd, "CLUSTER") == 0 && + pg_strcasecmp(prev_wd, "ON") == 0) + { + completion_info_charp = prev3_wd; + COMPLETE_WITH_QUERY(Query_for_index_of_table); + } + /* If we have TABLE SET, provide list of attributes and '(' */ + else if (pg_strcasecmp(prev3_wd, "TABLE") == 0 && + pg_strcasecmp(prev_wd, "SET") == 0) + { + static const char *const list_TABLESET[] = + {"(", "LOGGED", "SCHEMA", "TABLESPACE", "UNLOGGED", "WITH", "WITHOUT", NULL}; + + COMPLETE_WITH_LIST(list_TABLESET); + } + /* If we have TABLE SET TABLESPACE provide a list of tablespaces */ + else if (pg_strcasecmp(prev4_wd, "TABLE") == 0 && + pg_strcasecmp(prev2_wd, "SET") == 0 && + pg_strcasecmp(prev_wd, "TABLESPACE") == 0) + COMPLETE_WITH_QUERY(Query_for_list_of_tablespaces); + /* If we have TABLE SET WITHOUT provide CLUSTER or OIDS */ + else if (pg_strcasecmp(prev4_wd, "TABLE") == 0 && + pg_strcasecmp(prev2_wd, "SET") == 0 && + pg_strcasecmp(prev_wd, "WITHOUT") == 0) + { + static const char *const list_TABLESET2[] = + {"CLUSTER", "OIDS", NULL}; + + COMPLETE_WITH_LIST(list_TABLESET2); + } + /* ALTER TABLE RESET */ + else if (pg_strcasecmp(prev3_wd, "TABLE") == 0 && + pg_strcasecmp(prev_wd, "RESET") == 0) + COMPLETE_WITH_CONST("("); + /* ALTER TABLE SET|RESET ( */ + else if (pg_strcasecmp(prev4_wd, "TABLE") == 0 && + (pg_strcasecmp(prev2_wd, "SET") == 0 || + pg_strcasecmp(prev2_wd, "RESET") == 0) && + pg_strcasecmp(prev_wd, "(") == 0) + { + static const char *const list_TABLEOPTIONS[] = + { + "autovacuum_analyze_scale_factor", + "autovacuum_analyze_threshold", + "autovacuum_enabled", + "autovacuum_freeze_max_age", + "autovacuum_freeze_min_age", + "autovacuum_freeze_table_age", + "autovacuum_multixact_freeze_max_age", + "autovacuum_multixact_freeze_min_age", + "autovacuum_multixact_freeze_table_age", + "autovacuum_vacuum_cost_delay", + "autovacuum_vacuum_cost_limit", + "autovacuum_vacuum_scale_factor", + "autovacuum_vacuum_threshold", + "fillfactor", + "log_autovacuum_min_duration", + "toast.autovacuum_enabled", + "toast.autovacuum_freeze_max_age", + "toast.autovacuum_freeze_min_age", + "toast.autovacuum_freeze_table_age", + "toast.autovacuum_multixact_freeze_max_age", + "toast.autovacuum_multixact_freeze_min_age", + "toast.autovacuum_multixact_freeze_table_age", + "toast.autovacuum_vacuum_cost_delay", + "toast.autovacuum_vacuum_cost_limit", + "toast.autovacuum_vacuum_scale_factor", + "toast.autovacuum_vacuum_threshold", + "toast.log_autovacuum_min_duration", + "user_catalog_table", + NULL + }; + + COMPLETE_WITH_LIST(list_TABLEOPTIONS); + } + else if (pg_strcasecmp(prev4_wd, "REPLICA") == 0 && + pg_strcasecmp(prev3_wd, "IDENTITY") == 0 && + pg_strcasecmp(prev2_wd, "USING") == 0 && + pg_strcasecmp(prev_wd, "INDEX") == 0) + { + completion_info_charp = prev5_wd; + COMPLETE_WITH_QUERY(Query_for_index_of_table); + } + else if (pg_strcasecmp(prev5_wd, "TABLE") == 0 && + pg_strcasecmp(prev3_wd, "REPLICA") == 0 && + pg_strcasecmp(prev2_wd, "IDENTITY") == 0 && + pg_strcasecmp(prev_wd, "USING") == 0) + { + COMPLETE_WITH_CONST("INDEX"); + } + else if (pg_strcasecmp(prev4_wd, "TABLE") == 0 && + pg_strcasecmp(prev2_wd, "REPLICA") == 0 && + pg_strcasecmp(prev_wd, "IDENTITY") == 0) + { + static const char *const list_REPLICAID[] = + {"FULL", "NOTHING", "DEFAULT", "USING", NULL}; + + COMPLETE_WITH_LIST(list_REPLICAID); + } + else if (pg_strcasecmp(prev3_wd, "TABLE") == 0 && + pg_strcasecmp(prev_wd, "REPLICA") == 0) + { + COMPLETE_WITH_CONST("IDENTITY"); + } + + /* ALTER TABLESPACE with RENAME TO, OWNER TO, SET, RESET */ + else if (pg_strcasecmp(prev3_wd, "ALTER") == 0 && + pg_strcasecmp(prev2_wd, "TABLESPACE") == 0) + { + static const char *const list_ALTERTSPC[] = + {"RENAME TO", "OWNER TO", "SET", "RESET", NULL}; + + COMPLETE_WITH_LIST(list_ALTERTSPC); + } + /* ALTER TABLESPACE SET|RESET */ + else if (pg_strcasecmp(prev4_wd, "ALTER") == 0 && + pg_strcasecmp(prev3_wd, "TABLESPACE") == 0 && + (pg_strcasecmp(prev_wd, "SET") == 0 || + pg_strcasecmp(prev_wd, "RESET") == 0)) + COMPLETE_WITH_CONST("("); + /* ALTER TABLESPACE SET|RESET ( */ + else if (pg_strcasecmp(prev5_wd, "ALTER") == 0 && + pg_strcasecmp(prev4_wd, "TABLESPACE") == 0 && + (pg_strcasecmp(prev2_wd, "SET") == 0 || + pg_strcasecmp(prev2_wd, "RESET") == 0) && + pg_strcasecmp(prev_wd, "(") == 0) + { + static const char *const list_TABLESPACEOPTIONS[] = + {"seq_page_cost", "random_page_cost", NULL}; + + COMPLETE_WITH_LIST(list_TABLESPACEOPTIONS); + } + + /* ALTER TEXT SEARCH */ + else if (pg_strcasecmp(prev3_wd, "ALTER") == 0 && + pg_strcasecmp(prev2_wd, "TEXT") == 0 && + pg_strcasecmp(prev_wd, "SEARCH") == 0) + { + static const char *const list_ALTERTEXTSEARCH[] = + {"CONFIGURATION", "DICTIONARY", "PARSER", "TEMPLATE", NULL}; + + COMPLETE_WITH_LIST(list_ALTERTEXTSEARCH); + } + else if (pg_strcasecmp(prev5_wd, "ALTER") == 0 && + pg_strcasecmp(prev4_wd, "TEXT") == 0 && + pg_strcasecmp(prev3_wd, "SEARCH") == 0 && + (pg_strcasecmp(prev2_wd, "TEMPLATE") == 0 || + pg_strcasecmp(prev2_wd, "PARSER") == 0)) + { + static const char *const list_ALTERTEXTSEARCH2[] = + {"RENAME TO", "SET SCHEMA", NULL}; + + COMPLETE_WITH_LIST(list_ALTERTEXTSEARCH2); + } + + else if (pg_strcasecmp(prev5_wd, "ALTER") == 0 && + pg_strcasecmp(prev4_wd, "TEXT") == 0 && + pg_strcasecmp(prev3_wd, "SEARCH") == 0 && + pg_strcasecmp(prev2_wd, "DICTIONARY") == 0) + { + static const char *const list_ALTERTEXTSEARCH3[] = + {"OWNER TO", "RENAME TO", "SET SCHEMA", NULL}; + + COMPLETE_WITH_LIST(list_ALTERTEXTSEARCH3); + } + + else if (pg_strcasecmp(prev5_wd, "ALTER") == 0 && + pg_strcasecmp(prev4_wd, "TEXT") == 0 && + pg_strcasecmp(prev3_wd, "SEARCH") == 0 && + pg_strcasecmp(prev2_wd, "CONFIGURATION") == 0) + { + static const char *const list_ALTERTEXTSEARCH4[] = + {"ADD MAPPING FOR", "ALTER MAPPING", "DROP MAPPING FOR", "OWNER TO", "RENAME TO", "SET SCHEMA", NULL}; + + COMPLETE_WITH_LIST(list_ALTERTEXTSEARCH4); + } + + /* complete ALTER TYPE with actions */ + else if (pg_strcasecmp(prev3_wd, "ALTER") == 0 && + pg_strcasecmp(prev2_wd, "TYPE") == 0) + { + static const char *const list_ALTERTYPE[] = + {"ADD ATTRIBUTE", "ADD VALUE", "ALTER ATTRIBUTE", "DROP ATTRIBUTE", + "OWNER TO", "RENAME", "SET SCHEMA", NULL}; + + COMPLETE_WITH_LIST(list_ALTERTYPE); + } + /* complete ALTER TYPE ADD with actions */ + else if (pg_strcasecmp(prev4_wd, "ALTER") == 0 && + pg_strcasecmp(prev3_wd, "TYPE") == 0 && + pg_strcasecmp(prev_wd, "ADD") == 0) + { + static const char *const list_ALTERTYPE[] = + {"ATTRIBUTE", "VALUE", NULL}; + + COMPLETE_WITH_LIST(list_ALTERTYPE); + } + /* ALTER TYPE RENAME */ + else if (pg_strcasecmp(prev4_wd, "ALTER") == 0 && + pg_strcasecmp(prev3_wd, "TYPE") == 0 && + pg_strcasecmp(prev_wd, "RENAME") == 0) + { + static const char *const list_ALTERTYPE[] = + {"ATTRIBUTE", "TO", NULL}; + + COMPLETE_WITH_LIST(list_ALTERTYPE); + } + /* ALTER TYPE xxx RENAME ATTRIBUTE yyy */ + else if (pg_strcasecmp(prev5_wd, "TYPE") == 0 && + pg_strcasecmp(prev3_wd, "RENAME") == 0 && + pg_strcasecmp(prev2_wd, "ATTRIBUTE") == 0) + COMPLETE_WITH_CONST("TO"); + + /* + * If we have TYPE ALTER/DROP/RENAME ATTRIBUTE, provide list of + * attributes + */ + else if (pg_strcasecmp(prev4_wd, "TYPE") == 0 && + (pg_strcasecmp(prev2_wd, "ALTER") == 0 || + pg_strcasecmp(prev2_wd, "DROP") == 0 || + pg_strcasecmp(prev2_wd, "RENAME") == 0) && + pg_strcasecmp(prev_wd, "ATTRIBUTE") == 0) + COMPLETE_WITH_ATTR(prev3_wd, ""); + /* ALTER TYPE ALTER ATTRIBUTE */ + else if ((pg_strcasecmp(prev3_wd, "ALTER") == 0 && + pg_strcasecmp(prev2_wd, "ATTRIBUTE") == 0)) + { + COMPLETE_WITH_CONST("TYPE"); + } + /* complete ALTER GROUP */ + else if (pg_strcasecmp(prev3_wd, "ALTER") == 0 && + pg_strcasecmp(prev2_wd, "GROUP") == 0) + { + static const char *const list_ALTERGROUP[] = + {"ADD USER", "DROP USER", "RENAME TO", NULL}; + + COMPLETE_WITH_LIST(list_ALTERGROUP); + } + /* complete ALTER GROUP ADD|DROP with USER */ + else if (pg_strcasecmp(prev4_wd, "ALTER") == 0 && + pg_strcasecmp(prev3_wd, "GROUP") == 0 && + (pg_strcasecmp(prev_wd, "ADD") == 0 || + pg_strcasecmp(prev_wd, "DROP") == 0)) + COMPLETE_WITH_CONST("USER"); + /* complete {ALTER} GROUP ADD|DROP USER with a user name */ + else if (pg_strcasecmp(prev4_wd, "GROUP") == 0 && + (pg_strcasecmp(prev2_wd, "ADD") == 0 || + pg_strcasecmp(prev2_wd, "DROP") == 0) && + pg_strcasecmp(prev_wd, "USER") == 0) + COMPLETE_WITH_QUERY(Query_for_list_of_roles); + +/* BEGIN, END, ABORT */ + else if (pg_strcasecmp(prev_wd, "BEGIN") == 0 || + pg_strcasecmp(prev_wd, "END") == 0 || + pg_strcasecmp(prev_wd, "ABORT") == 0) + { + static const char *const list_TRANS[] = + {"WORK", "TRANSACTION", NULL}; + + COMPLETE_WITH_LIST(list_TRANS); + } +/* COMMIT */ + else if (pg_strcasecmp(prev_wd, "COMMIT") == 0) + { + static const char *const list_COMMIT[] = + {"WORK", "TRANSACTION", "PREPARED", NULL}; + + COMPLETE_WITH_LIST(list_COMMIT); + } +/* RELEASE SAVEPOINT */ + else if (pg_strcasecmp(prev_wd, "RELEASE") == 0) + COMPLETE_WITH_CONST("SAVEPOINT"); +/* ROLLBACK*/ + else if (pg_strcasecmp(prev_wd, "ROLLBACK") == 0) + { + static const char *const list_TRANS[] = + {"WORK", "TRANSACTION", "TO SAVEPOINT", "PREPARED", NULL}; + + COMPLETE_WITH_LIST(list_TRANS); + } +/* CLUSTER */ + + /* + * If the previous word is CLUSTER and not WITHOUT produce list of tables + */ + else if (pg_strcasecmp(prev_wd, "CLUSTER") == 0 && + pg_strcasecmp(prev2_wd, "WITHOUT") != 0) + COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm, "UNION SELECT 'VERBOSE'"); + + /* + * If the previous words are CLUSTER VERBOSE produce list of tables + */ + else if (pg_strcasecmp(prev_wd, "VERBOSE") == 0 && + pg_strcasecmp(prev2_wd, "CLUSTER") == 0) + COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm, NULL); + + /* If we have CLUSTER , then add "USING" */ + else if (pg_strcasecmp(prev2_wd, "CLUSTER") == 0 && + pg_strcasecmp(prev_wd, "ON") != 0 && + pg_strcasecmp(prev_wd, "VERBOSE") != 0) + { + COMPLETE_WITH_CONST("USING"); + } + /* If we have CLUSTER VERBOSE , then add "USING" */ + else if (pg_strcasecmp(prev3_wd, "CLUSTER") == 0 && + pg_strcasecmp(prev2_wd, "VERBOSE") == 0) + { + COMPLETE_WITH_CONST("USING"); + } + + /* + * If we have CLUSTER USING, then add the index as well. + */ + else if (pg_strcasecmp(prev3_wd, "CLUSTER") == 0 && + pg_strcasecmp(prev_wd, "USING") == 0) + { + completion_info_charp = prev2_wd; + COMPLETE_WITH_QUERY(Query_for_index_of_table); + } + + /* + * If we have CLUSTER VERBOSE USING, then add the index as well. + */ + else if (pg_strcasecmp(prev4_wd, "CLUSTER") == 0 && + pg_strcasecmp(prev3_wd, "VERBOSE") == 0 && + pg_strcasecmp(prev_wd, "USING") == 0) + { + completion_info_charp = prev2_wd; + COMPLETE_WITH_QUERY(Query_for_index_of_table); + } + +/* COMMENT */ + else if (pg_strcasecmp(prev_wd, "COMMENT") == 0) + COMPLETE_WITH_CONST("ON"); + else if (pg_strcasecmp(prev2_wd, "COMMENT") == 0 && + pg_strcasecmp(prev_wd, "ON") == 0) + { + static const char *const list_COMMENT[] = + {"CAST", "COLLATION", "CONVERSION", "DATABASE", "EVENT TRIGGER", "EXTENSION", + "FOREIGN DATA WRAPPER", "FOREIGN TABLE", + "SERVER", "INDEX", "LANGUAGE", "POLICY", "RULE", "SCHEMA", "SEQUENCE", + "TABLE", "TYPE", "VIEW", "MATERIALIZED VIEW", "COLUMN", "AGGREGATE", "FUNCTION", + "OPERATOR", "TRIGGER", "CONSTRAINT", "DOMAIN", "LARGE OBJECT", + "TABLESPACE", "TEXT SEARCH", "ROLE", NULL}; + + COMPLETE_WITH_LIST(list_COMMENT); + } + else if (pg_strcasecmp(prev3_wd, "COMMENT") == 0 && + pg_strcasecmp(prev2_wd, "ON") == 0 && + pg_strcasecmp(prev_wd, "FOREIGN") == 0) + { + static const char *const list_TRANS2[] = + {"DATA WRAPPER", "TABLE", NULL}; + + COMPLETE_WITH_LIST(list_TRANS2); + } + else if (pg_strcasecmp(prev4_wd, "COMMENT") == 0 && + pg_strcasecmp(prev3_wd, "ON") == 0 && + pg_strcasecmp(prev2_wd, "TEXT") == 0 && + pg_strcasecmp(prev_wd, "SEARCH") == 0) + { + static const char *const list_TRANS2[] = + {"CONFIGURATION", "DICTIONARY", "PARSER", "TEMPLATE", NULL}; + + COMPLETE_WITH_LIST(list_TRANS2); + } + else if (pg_strcasecmp(prev3_wd, "COMMENT") == 0 && + pg_strcasecmp(prev2_wd, "ON") == 0 && + pg_strcasecmp(prev_wd, "CONSTRAINT") == 0) + { + COMPLETE_WITH_QUERY(Query_for_all_table_constraints); + } + else if (pg_strcasecmp(prev4_wd, "COMMENT") == 0 && + pg_strcasecmp(prev3_wd, "ON") == 0 && + pg_strcasecmp(prev2_wd, "CONSTRAINT") == 0) + { + COMPLETE_WITH_CONST("ON"); + } + else if (pg_strcasecmp(prev5_wd, "COMMENT") == 0 && + pg_strcasecmp(prev4_wd, "ON") == 0 && + pg_strcasecmp(prev3_wd, "CONSTRAINT") == 0 && + pg_strcasecmp(prev_wd, "ON") == 0) + { + completion_info_charp = prev2_wd; + COMPLETE_WITH_QUERY(Query_for_list_of_tables_for_constraint); + } + else if (pg_strcasecmp(prev4_wd, "COMMENT") == 0 && + pg_strcasecmp(prev3_wd, "ON") == 0 && + pg_strcasecmp(prev2_wd, "MATERIALIZED") == 0 && + pg_strcasecmp(prev_wd, "VIEW") == 0) + { + COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_matviews, NULL); + } + else if (pg_strcasecmp(prev4_wd, "COMMENT") == 0 && + pg_strcasecmp(prev3_wd, "ON") == 0 && + pg_strcasecmp(prev2_wd, "EVENT") == 0 && + pg_strcasecmp(prev_wd, "TRIGGER") == 0) + { + COMPLETE_WITH_QUERY(Query_for_list_of_event_triggers); + } + else if (((pg_strcasecmp(prev4_wd, "COMMENT") == 0 && + pg_strcasecmp(prev3_wd, "ON") == 0) || + (pg_strcasecmp(prev5_wd, "COMMENT") == 0 && + pg_strcasecmp(prev4_wd, "ON") == 0) || + (pg_strcasecmp(prev6_wd, "COMMENT") == 0 && + pg_strcasecmp(prev5_wd, "ON") == 0)) && + pg_strcasecmp(prev_wd, "IS") != 0) + COMPLETE_WITH_CONST("IS"); + +/* COPY */ + + /* + * If we have COPY [BINARY] (which you'd have to type yourself), offer + * list of tables (Also cover the analogous backslash command) + */ + else if (pg_strcasecmp(prev_wd, "COPY") == 0 || + pg_strcasecmp(prev_wd, "\\copy") == 0 || + (pg_strcasecmp(prev2_wd, "COPY") == 0 && + pg_strcasecmp(prev_wd, "BINARY") == 0)) + COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL); + /* If we have COPY|BINARY , complete it with "TO" or "FROM" */ + else if (pg_strcasecmp(prev2_wd, "COPY") == 0 || + pg_strcasecmp(prev2_wd, "\\copy") == 0 || + pg_strcasecmp(prev2_wd, "BINARY") == 0) + { + static const char *const list_FROMTO[] = + {"FROM", "TO", NULL}; + + COMPLETE_WITH_LIST(list_FROMTO); + } + /* If we have COPY|BINARY FROM|TO, complete with filename */ + else if ((pg_strcasecmp(prev3_wd, "COPY") == 0 || + pg_strcasecmp(prev3_wd, "\\copy") == 0 || + pg_strcasecmp(prev3_wd, "BINARY") == 0) && + (pg_strcasecmp(prev_wd, "FROM") == 0 || + pg_strcasecmp(prev_wd, "TO") == 0)) + { + completion_charp = ""; + matches = completion_matches(text, complete_from_files); + } + + /* Handle COPY|BINARY FROM|TO filename */ + else if ((pg_strcasecmp(prev4_wd, "COPY") == 0 || + pg_strcasecmp(prev4_wd, "\\copy") == 0 || + pg_strcasecmp(prev4_wd, "BINARY") == 0) && + (pg_strcasecmp(prev2_wd, "FROM") == 0 || + pg_strcasecmp(prev2_wd, "TO") == 0)) + { + static const char *const list_COPY[] = + {"BINARY", "OIDS", "DELIMITER", "NULL", "CSV", "ENCODING", NULL}; + + COMPLETE_WITH_LIST(list_COPY); + } + + /* Handle COPY|BINARY FROM|TO filename CSV */ + else if (pg_strcasecmp(prev_wd, "CSV") == 0 && + (pg_strcasecmp(prev3_wd, "FROM") == 0 || + pg_strcasecmp(prev3_wd, "TO") == 0)) + { + static const char *const list_CSV[] = + {"HEADER", "QUOTE", "ESCAPE", "FORCE QUOTE", "FORCE NOT NULL", NULL}; + + COMPLETE_WITH_LIST(list_CSV); + } + + /* CREATE DATABASE */ + else if (pg_strcasecmp(prev3_wd, "CREATE") == 0 && + pg_strcasecmp(prev2_wd, "DATABASE") == 0) + { + static const char *const list_DATABASE[] = + {"OWNER", "TEMPLATE", "ENCODING", "TABLESPACE", "IS_TEMPLATE", + "ALLOW_CONNECTIONS", "CONNECTION LIMIT", "LC_COLLATE", "LC_CTYPE", + NULL}; + + COMPLETE_WITH_LIST(list_DATABASE); + } + + else if (pg_strcasecmp(prev4_wd, "CREATE") == 0 && + pg_strcasecmp(prev3_wd, "DATABASE") == 0 && + pg_strcasecmp(prev_wd, "TEMPLATE") == 0) + COMPLETE_WITH_QUERY(Query_for_list_of_template_databases); + + /* CREATE EXTENSION */ + /* Complete with available extensions rather than installed ones. */ + else if (pg_strcasecmp(prev2_wd, "CREATE") == 0 && + pg_strcasecmp(prev_wd, "EXTENSION") == 0) + COMPLETE_WITH_QUERY(Query_for_list_of_available_extensions); + /* CREATE EXTENSION */ + else if (pg_strcasecmp(prev3_wd, "CREATE") == 0 && + pg_strcasecmp(prev2_wd, "EXTENSION") == 0) + COMPLETE_WITH_CONST("WITH SCHEMA"); + + /* CREATE FOREIGN */ + else if (pg_strcasecmp(prev2_wd, "CREATE") == 0 && + pg_strcasecmp(prev_wd, "FOREIGN") == 0) + { + static const char *const list_CREATE_FOREIGN[] = + {"DATA WRAPPER", "TABLE", NULL}; + + COMPLETE_WITH_LIST(list_CREATE_FOREIGN); + } + + /* CREATE FOREIGN DATA WRAPPER */ + else if (pg_strcasecmp(prev5_wd, "CREATE") == 0 && + pg_strcasecmp(prev4_wd, "FOREIGN") == 0 && + pg_strcasecmp(prev3_wd, "DATA") == 0 && + pg_strcasecmp(prev2_wd, "WRAPPER") == 0) + { + static const char *const list_CREATE_FOREIGN_DATA_WRAPPER[] = + {"HANDLER", "VALIDATOR", NULL}; + + COMPLETE_WITH_LIST(list_CREATE_FOREIGN_DATA_WRAPPER); + } + + /* CREATE INDEX */ + /* First off we complete CREATE UNIQUE with "INDEX" */ + else if (pg_strcasecmp(prev2_wd, "CREATE") == 0 && + pg_strcasecmp(prev_wd, "UNIQUE") == 0) + COMPLETE_WITH_CONST("INDEX"); + /* If we have CREATE|UNIQUE INDEX, then add "ON" and existing indexes */ + else if (pg_strcasecmp(prev_wd, "INDEX") == 0 && + (pg_strcasecmp(prev2_wd, "CREATE") == 0 || + pg_strcasecmp(prev2_wd, "UNIQUE") == 0)) + COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes, + " UNION SELECT 'ON'" + " UNION SELECT 'CONCURRENTLY'"); + /* Complete ... INDEX [] ON with a list of tables */ + else if ((pg_strcasecmp(prev3_wd, "INDEX") == 0 || + pg_strcasecmp(prev2_wd, "INDEX") == 0 || + pg_strcasecmp(prev2_wd, "CONCURRENTLY") == 0) && + pg_strcasecmp(prev_wd, "ON") == 0) + COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm, NULL); + /* If we have CREATE|UNIQUE INDEX CONCURRENTLY, then add "ON" */ + else if ((pg_strcasecmp(prev3_wd, "INDEX") == 0 || + pg_strcasecmp(prev2_wd, "INDEX") == 0) && + pg_strcasecmp(prev_wd, "CONCURRENTLY") == 0) + COMPLETE_WITH_CONST("ON"); + /* If we have CREATE|UNIQUE INDEX , then add "ON" or "CONCURRENTLY" */ + else if ((pg_strcasecmp(prev3_wd, "CREATE") == 0 || + pg_strcasecmp(prev3_wd, "UNIQUE") == 0) && + pg_strcasecmp(prev2_wd, "INDEX") == 0) + { + static const char *const list_CREATE_INDEX[] = + {"CONCURRENTLY", "ON", NULL}; + + COMPLETE_WITH_LIST(list_CREATE_INDEX); + } + + /* + * Complete INDEX ON
with a list of table columns (which + * should really be in parens) + */ + else if ((pg_strcasecmp(prev4_wd, "INDEX") == 0 || + pg_strcasecmp(prev3_wd, "INDEX") == 0 || + pg_strcasecmp(prev3_wd, "CONCURRENTLY") == 0) && + pg_strcasecmp(prev2_wd, "ON") == 0) + { + static const char *const list_CREATE_INDEX2[] = + {"(", "USING", NULL}; + + COMPLETE_WITH_LIST(list_CREATE_INDEX2); + } + else if ((pg_strcasecmp(prev5_wd, "INDEX") == 0 || + pg_strcasecmp(prev4_wd, "INDEX") == 0 || + pg_strcasecmp(prev4_wd, "CONCURRENTLY") == 0) && + pg_strcasecmp(prev3_wd, "ON") == 0 && + pg_strcasecmp(prev_wd, "(") == 0) + COMPLETE_WITH_ATTR(prev2_wd, ""); + /* same if you put in USING */ + else if (pg_strcasecmp(prev5_wd, "ON") == 0 && + pg_strcasecmp(prev3_wd, "USING") == 0 && + pg_strcasecmp(prev_wd, "(") == 0) + COMPLETE_WITH_ATTR(prev4_wd, ""); + /* Complete USING with an index method */ + else if ((pg_strcasecmp(prev6_wd, "INDEX") == 0 || + pg_strcasecmp(prev5_wd, "INDEX") == 0 || + pg_strcasecmp(prev4_wd, "INDEX") == 0) && + pg_strcasecmp(prev3_wd, "ON") == 0 && + pg_strcasecmp(prev_wd, "USING") == 0) + COMPLETE_WITH_QUERY(Query_for_list_of_access_methods); + else if (pg_strcasecmp(prev4_wd, "ON") == 0 && + (!(pg_strcasecmp(prev6_wd, "POLICY") == 0) && + !(pg_strcasecmp(prev4_wd, "FOR") == 0)) && + pg_strcasecmp(prev2_wd, "USING") == 0) + COMPLETE_WITH_CONST("("); + + /* CREATE POLICY */ + /* Complete "CREATE POLICY ON" */ + else if (pg_strcasecmp(prev3_wd, "CREATE") == 0 && + pg_strcasecmp(prev2_wd, "POLICY") == 0) + COMPLETE_WITH_CONST("ON"); + /* Complete "CREATE POLICY ON
" */ + else if (pg_strcasecmp(prev4_wd, "CREATE") == 0 && + pg_strcasecmp(prev3_wd, "POLICY") == 0 && + pg_strcasecmp(prev_wd, "ON") == 0) + COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL); + /* Complete "CREATE POLICY ON
FOR|TO|USING|WITH CHECK" */ + else if (pg_strcasecmp(prev5_wd, "CREATE") == 0 && + pg_strcasecmp(prev4_wd, "POLICY") == 0 && + pg_strcasecmp(prev2_wd, "ON") == 0) + { + static const char *const list_POLICYOPTIONS[] = + {"FOR", "TO", "USING", "WITH CHECK", NULL}; + + COMPLETE_WITH_LIST(list_POLICYOPTIONS); + } + + /* + * Complete "CREATE POLICY ON
FOR + * ALL|SELECT|INSERT|UPDATE|DELETE" + */ + else if (pg_strcasecmp(prev6_wd, "CREATE") == 0 && + pg_strcasecmp(prev5_wd, "POLICY") == 0 && + pg_strcasecmp(prev3_wd, "ON") == 0 && + pg_strcasecmp(prev_wd, "FOR") == 0) + { + static const char *const list_POLICYCMDS[] = + {"ALL", "SELECT", "INSERT", "UPDATE", "DELETE", NULL}; + + COMPLETE_WITH_LIST(list_POLICYCMDS); + } + /* Complete "CREATE POLICY ON
FOR INSERT TO|WITH CHECK" */ + else if (pg_strcasecmp(prev6_wd, "POLICY") == 0 && + pg_strcasecmp(prev4_wd, "ON") == 0 && + pg_strcasecmp(prev2_wd, "FOR") == 0 && + pg_strcasecmp(prev_wd, "INSERT") == 0) + { + static const char *const list_POLICYOPTIONS[] = + {"TO", "WITH CHECK", NULL}; + + COMPLETE_WITH_LIST(list_POLICYOPTIONS); + } + + /* + * Complete "CREATE POLICY ON
FOR SELECT TO|USING" Complete + * "CREATE POLICY ON
FOR DELETE TO|USING" + */ + else if (pg_strcasecmp(prev6_wd, "POLICY") == 0 && + pg_strcasecmp(prev4_wd, "ON") == 0 && + pg_strcasecmp(prev2_wd, "FOR") == 0 && + (pg_strcasecmp(prev_wd, "SELECT") == 0 || + pg_strcasecmp(prev_wd, "DELETE") == 0)) + { + static const char *const list_POLICYOPTIONS[] = + {"TO", "USING", NULL}; + + COMPLETE_WITH_LIST(list_POLICYOPTIONS); + } + + /* + * Complete "CREATE POLICY ON
FOR ALL TO|USING|WITH CHECK" + * Complete "CREATE POLICY ON
FOR UPDATE TO|USING|WITH + * CHECK" + */ + else if (pg_strcasecmp(prev6_wd, "POLICY") == 0 && + pg_strcasecmp(prev4_wd, "ON") == 0 && + pg_strcasecmp(prev2_wd, "FOR") == 0 && + (pg_strcasecmp(prev_wd, "ALL") == 0 || + pg_strcasecmp(prev_wd, "UPDATE") == 0)) + { + static const char *const list_POLICYOPTIONS[] = + {"TO", "USING", "WITH CHECK", NULL}; + + COMPLETE_WITH_LIST(list_POLICYOPTIONS); + } + /* Complete "CREATE POLICY ON
TO " */ + else if (pg_strcasecmp(prev6_wd, "CREATE") == 0 && + pg_strcasecmp(prev5_wd, "POLICY") == 0 && + pg_strcasecmp(prev3_wd, "ON") == 0 && + pg_strcasecmp(prev_wd, "TO") == 0) + COMPLETE_WITH_QUERY(Query_for_list_of_grant_roles); + /* Complete "CREATE POLICY ON
USING (" */ + else if (pg_strcasecmp(prev6_wd, "CREATE") == 0 && + pg_strcasecmp(prev5_wd, "POLICY") == 0 && + pg_strcasecmp(prev3_wd, "ON") == 0 && + pg_strcasecmp(prev_wd, "USING") == 0) + COMPLETE_WITH_CONST("("); + +/* CREATE RULE */ + /* Complete "CREATE RULE " with "AS" */ + else if (pg_strcasecmp(prev3_wd, "CREATE") == 0 && + pg_strcasecmp(prev2_wd, "RULE") == 0) + COMPLETE_WITH_CONST("AS"); + /* Complete "CREATE RULE AS with "ON" */ + else if (pg_strcasecmp(prev4_wd, "CREATE") == 0 && + pg_strcasecmp(prev3_wd, "RULE") == 0 && + pg_strcasecmp(prev_wd, "AS") == 0) + COMPLETE_WITH_CONST("ON"); + /* Complete "RULE * AS ON" with SELECT|UPDATE|DELETE|INSERT */ + else if (pg_strcasecmp(prev4_wd, "RULE") == 0 && + pg_strcasecmp(prev2_wd, "AS") == 0 && + pg_strcasecmp(prev_wd, "ON") == 0) + { + static const char *const rule_events[] = + {"SELECT", "UPDATE", "INSERT", "DELETE", NULL}; + + COMPLETE_WITH_LIST(rule_events); + } + /* Complete "AS ON " with a "TO" */ + else if (pg_strcasecmp(prev3_wd, "AS") == 0 && + pg_strcasecmp(prev2_wd, "ON") == 0 && + (pg_toupper((unsigned char) prev_wd[4]) == 'T' || + pg_toupper((unsigned char) prev_wd[5]) == 'T')) + COMPLETE_WITH_CONST("TO"); + /* Complete "AS ON TO" with a table name */ + else if (pg_strcasecmp(prev4_wd, "AS") == 0 && + pg_strcasecmp(prev3_wd, "ON") == 0 && + pg_strcasecmp(prev_wd, "TO") == 0) + COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL); + +/* CREATE SERVER */ + else if (pg_strcasecmp(prev3_wd, "CREATE") == 0 && + pg_strcasecmp(prev2_wd, "SERVER") == 0) + { + static const char *const list_CREATE_SERVER[] = + {"TYPE", "VERSION", "FOREIGN DATA WRAPPER", NULL}; + + COMPLETE_WITH_LIST(list_CREATE_SERVER); + } + +/* CREATE TABLE */ + /* Complete "CREATE TEMP/TEMPORARY" with the possible temp objects */ + else if (pg_strcasecmp(prev2_wd, "CREATE") == 0 && + (pg_strcasecmp(prev_wd, "TEMP") == 0 || + pg_strcasecmp(prev_wd, "TEMPORARY") == 0)) + { + static const char *const list_TEMP[] = + {"SEQUENCE", "TABLE", "VIEW", NULL}; + + COMPLETE_WITH_LIST(list_TEMP); + } + /* Complete "CREATE UNLOGGED" with TABLE */ + else if (pg_strcasecmp(prev2_wd, "CREATE") == 0 && + pg_strcasecmp(prev_wd, "UNLOGGED") == 0) + { + static const char *const list_UNLOGGED[] = + {"TABLE", "MATERIALIZED VIEW", NULL}; + + COMPLETE_WITH_LIST(list_UNLOGGED); + } + +/* CREATE TABLESPACE */ + else if (pg_strcasecmp(prev3_wd, "CREATE") == 0 && + pg_strcasecmp(prev2_wd, "TABLESPACE") == 0) + { + static const char *const list_CREATETABLESPACE[] = + {"OWNER", "LOCATION", NULL}; + + COMPLETE_WITH_LIST(list_CREATETABLESPACE); + } + /* Complete CREATE TABLESPACE name OWNER name with "LOCATION" */ + else if (pg_strcasecmp(prev5_wd, "CREATE") == 0 && + pg_strcasecmp(prev4_wd, "TABLESPACE") == 0 && + pg_strcasecmp(prev2_wd, "OWNER") == 0) + { + COMPLETE_WITH_CONST("LOCATION"); + } + +/* CREATE TEXT SEARCH */ + else if (pg_strcasecmp(prev3_wd, "CREATE") == 0 && + pg_strcasecmp(prev2_wd, "TEXT") == 0 && + pg_strcasecmp(prev_wd, "SEARCH") == 0) + { + static const char *const list_CREATETEXTSEARCH[] = + {"CONFIGURATION", "DICTIONARY", "PARSER", "TEMPLATE", NULL}; + + COMPLETE_WITH_LIST(list_CREATETEXTSEARCH); + } + else if (pg_strcasecmp(prev4_wd, "TEXT") == 0 && + pg_strcasecmp(prev3_wd, "SEARCH") == 0 && + pg_strcasecmp(prev2_wd, "CONFIGURATION") == 0) + COMPLETE_WITH_CONST("("); + +/* CREATE TRIGGER */ + /* complete CREATE TRIGGER with BEFORE,AFTER */ + else if (pg_strcasecmp(prev3_wd, "CREATE") == 0 && + pg_strcasecmp(prev2_wd, "TRIGGER") == 0) + { + static const char *const list_CREATETRIGGER[] = + {"BEFORE", "AFTER", "INSTEAD OF", NULL}; + + COMPLETE_WITH_LIST(list_CREATETRIGGER); + } + /* complete CREATE TRIGGER BEFORE,AFTER with an event */ + else if (pg_strcasecmp(prev4_wd, "CREATE") == 0 && + pg_strcasecmp(prev3_wd, "TRIGGER") == 0 && + (pg_strcasecmp(prev_wd, "BEFORE") == 0 || + pg_strcasecmp(prev_wd, "AFTER") == 0)) + { + static const char *const list_CREATETRIGGER_EVENTS[] = + {"INSERT", "DELETE", "UPDATE", "TRUNCATE", NULL}; + + COMPLETE_WITH_LIST(list_CREATETRIGGER_EVENTS); + } + /* complete CREATE TRIGGER INSTEAD OF with an event */ + else if (pg_strcasecmp(prev5_wd, "CREATE") == 0 && + pg_strcasecmp(prev4_wd, "TRIGGER") == 0 && + pg_strcasecmp(prev2_wd, "INSTEAD") == 0 && + pg_strcasecmp(prev_wd, "OF") == 0) + { + static const char *const list_CREATETRIGGER_EVENTS[] = + {"INSERT", "DELETE", "UPDATE", NULL}; + + COMPLETE_WITH_LIST(list_CREATETRIGGER_EVENTS); + } + /* complete CREATE TRIGGER BEFORE,AFTER sth with OR,ON */ + else if ((pg_strcasecmp(prev5_wd, "CREATE") == 0 && + pg_strcasecmp(prev4_wd, "TRIGGER") == 0 && + (pg_strcasecmp(prev2_wd, "BEFORE") == 0 || + pg_strcasecmp(prev2_wd, "AFTER") == 0)) || + (pg_strcasecmp(prev5_wd, "TRIGGER") == 0 && + pg_strcasecmp(prev3_wd, "INSTEAD") == 0 && + pg_strcasecmp(prev2_wd, "OF") == 0)) + { + static const char *const list_CREATETRIGGER2[] = + {"ON", "OR", NULL}; + + COMPLETE_WITH_LIST(list_CREATETRIGGER2); + } + + /* + * complete CREATE TRIGGER BEFORE,AFTER event ON with a list of + * tables + */ + else if (pg_strcasecmp(prev5_wd, "TRIGGER") == 0 && + (pg_strcasecmp(prev3_wd, "BEFORE") == 0 || + pg_strcasecmp(prev3_wd, "AFTER") == 0) && + pg_strcasecmp(prev_wd, "ON") == 0) + COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL); + /* complete CREATE TRIGGER ... INSTEAD OF event ON with a list of views */ + else if (pg_strcasecmp(prev4_wd, "INSTEAD") == 0 && + pg_strcasecmp(prev3_wd, "OF") == 0 && + pg_strcasecmp(prev_wd, "ON") == 0) + COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_views, NULL); + /* complete CREATE TRIGGER ... EXECUTE with PROCEDURE */ + else if (pg_strcasecmp(prev_wd, "EXECUTE") == 0 && + !(pg_strcasecmp(prev2_wd, "GRANT") == 0 && prev3_wd[0] == '\0') && + prev2_wd[0] != '\0') + COMPLETE_WITH_CONST("PROCEDURE"); + +/* CREATE ROLE,USER,GROUP */ + else if (pg_strcasecmp(prev3_wd, "CREATE") == 0 && + !(pg_strcasecmp(prev2_wd, "USER") == 0 && pg_strcasecmp(prev_wd, "MAPPING") == 0) && + (pg_strcasecmp(prev2_wd, "ROLE") == 0 || + pg_strcasecmp(prev2_wd, "GROUP") == 0 || pg_strcasecmp(prev2_wd, "USER") == 0)) + { + static const char *const list_CREATEROLE[] = + {"ADMIN", "BYPASSRLS", "CONNECTION LIMIT", "CREATEDB", "CREATEROLE", + "CREATEUSER", "ENCRYPTED", "IN", "INHERIT", "LOGIN", "NOBYPASSRLS", + "NOCREATEDB", "NOCREATEROLE", "NOCREATEUSER", "NOINHERIT", + "NOLOGIN", "NOREPLICATION", "NOSUPERUSER", "PASSWORD", + "REPLICATION", "ROLE", "SUPERUSER", "SYSID", "UNENCRYPTED", + "VALID UNTIL", "WITH", NULL}; + + COMPLETE_WITH_LIST(list_CREATEROLE); + } + +/* CREATE ROLE,USER,GROUP WITH */ + else if ((pg_strcasecmp(prev4_wd, "CREATE") == 0 && + (pg_strcasecmp(prev3_wd, "ROLE") == 0 || + pg_strcasecmp(prev3_wd, "GROUP") == 0 || + pg_strcasecmp(prev3_wd, "USER") == 0) && + pg_strcasecmp(prev_wd, "WITH") == 0)) + { + /* Similar to the above, but don't complete "WITH" again. */ + static const char *const list_CREATEROLE_WITH[] = + {"ADMIN", "BYPASSRLS", "CONNECTION LIMIT", "CREATEDB", "CREATEROLE", + "CREATEUSER", "ENCRYPTED", "IN", "INHERIT", "LOGIN", "NOBYPASSRLS", + "NOCREATEDB", "NOCREATEROLE", "NOCREATEUSER", "NOINHERIT", + "NOLOGIN", "NOREPLICATION", "NOSUPERUSER", "PASSWORD", + "REPLICATION", "ROLE", "SUPERUSER", "SYSID", "UNENCRYPTED", + "VALID UNTIL", NULL}; + + COMPLETE_WITH_LIST(list_CREATEROLE_WITH); + } + + /* + * complete CREATE ROLE,USER,GROUP ENCRYPTED,UNENCRYPTED with + * PASSWORD + */ + else if (pg_strcasecmp(prev4_wd, "CREATE") == 0 && + (pg_strcasecmp(prev3_wd, "ROLE") == 0 || + pg_strcasecmp(prev3_wd, "GROUP") == 0 || pg_strcasecmp(prev3_wd, "USER") == 0) && + (pg_strcasecmp(prev_wd, "ENCRYPTED") == 0 || pg_strcasecmp(prev_wd, "UNENCRYPTED") == 0)) + { + COMPLETE_WITH_CONST("PASSWORD"); + } + /* complete CREATE ROLE,USER,GROUP IN with ROLE,GROUP */ + else if (pg_strcasecmp(prev4_wd, "CREATE") == 0 && + (pg_strcasecmp(prev3_wd, "ROLE") == 0 || + pg_strcasecmp(prev3_wd, "GROUP") == 0 || pg_strcasecmp(prev3_wd, "USER") == 0) && + pg_strcasecmp(prev_wd, "IN") == 0) + { + static const char *const list_CREATEROLE3[] = + {"GROUP", "ROLE", NULL}; + + COMPLETE_WITH_LIST(list_CREATEROLE3); + } + +/* CREATE VIEW */ + /* Complete CREATE VIEW with AS */ + else if (pg_strcasecmp(prev3_wd, "CREATE") == 0 && + pg_strcasecmp(prev2_wd, "VIEW") == 0) + COMPLETE_WITH_CONST("AS"); + /* Complete "CREATE VIEW AS with "SELECT" */ + else if (pg_strcasecmp(prev4_wd, "CREATE") == 0 && + pg_strcasecmp(prev3_wd, "VIEW") == 0 && + pg_strcasecmp(prev_wd, "AS") == 0) + COMPLETE_WITH_CONST("SELECT"); + +/* CREATE MATERIALIZED VIEW */ + else if (pg_strcasecmp(prev2_wd, "CREATE") == 0 && + pg_strcasecmp(prev_wd, "MATERIALIZED") == 0) + COMPLETE_WITH_CONST("VIEW"); + /* Complete CREATE MATERIALIZED VIEW with AS */ + else if (pg_strcasecmp(prev4_wd, "CREATE") == 0 && + pg_strcasecmp(prev3_wd, "MATERIALIZED") == 0 && + pg_strcasecmp(prev2_wd, "VIEW") == 0) + COMPLETE_WITH_CONST("AS"); + /* Complete "CREATE MATERIALIZED VIEW AS with "SELECT" */ + else if (pg_strcasecmp(prev5_wd, "CREATE") == 0 && + pg_strcasecmp(prev4_wd, "MATERIALIZED") == 0 && + pg_strcasecmp(prev3_wd, "VIEW") == 0 && + pg_strcasecmp(prev_wd, "AS") == 0) + COMPLETE_WITH_CONST("SELECT"); + +/* CREATE EVENT TRIGGER */ + else if (pg_strcasecmp(prev2_wd, "CREATE") == 0 && + pg_strcasecmp(prev_wd, "EVENT") == 0) + COMPLETE_WITH_CONST("TRIGGER"); + /* Complete CREATE EVENT TRIGGER with ON */ + else if (pg_strcasecmp(prev4_wd, "CREATE") == 0 && + pg_strcasecmp(prev3_wd, "EVENT") == 0 && + pg_strcasecmp(prev2_wd, "TRIGGER") == 0) + COMPLETE_WITH_CONST("ON"); + /* Complete CREATE EVENT TRIGGER ON with event_type */ + else if (pg_strcasecmp(prev5_wd, "CREATE") == 0 && + pg_strcasecmp(prev4_wd, "EVENT") == 0 && + pg_strcasecmp(prev3_wd, "TRIGGER") == 0 && + pg_strcasecmp(prev_wd, "ON") == 0) + { + static const char *const list_CREATE_EVENT_TRIGGER_ON[] = + {"ddl_command_start", "ddl_command_end", "sql_drop", NULL}; + + COMPLETE_WITH_LIST(list_CREATE_EVENT_TRIGGER_ON); + } + +/* DECLARE */ + else if (pg_strcasecmp(prev2_wd, "DECLARE") == 0) + { + static const char *const list_DECLARE[] = + {"BINARY", "INSENSITIVE", "SCROLL", "NO SCROLL", "CURSOR", NULL}; + + COMPLETE_WITH_LIST(list_DECLARE); + } + +/* CURSOR */ + else if (pg_strcasecmp(prev_wd, "CURSOR") == 0) + { + static const char *const list_DECLARECURSOR[] = + {"WITH HOLD", "WITHOUT HOLD", "FOR", NULL}; + + COMPLETE_WITH_LIST(list_DECLARECURSOR); + } + + +/* DELETE */ + + /* + * Complete DELETE with FROM (only if the word before that is not "ON" + * (cf. rules) or "BEFORE" or "AFTER" (cf. triggers) or GRANT) + */ + else if (pg_strcasecmp(prev_wd, "DELETE") == 0 && + !(pg_strcasecmp(prev2_wd, "ON") == 0 || + pg_strcasecmp(prev2_wd, "GRANT") == 0 || + pg_strcasecmp(prev2_wd, "BEFORE") == 0 || + pg_strcasecmp(prev2_wd, "AFTER") == 0)) + COMPLETE_WITH_CONST("FROM"); + /* Complete DELETE FROM with a list of tables */ + else if (pg_strcasecmp(prev2_wd, "DELETE") == 0 && + pg_strcasecmp(prev_wd, "FROM") == 0) + COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_updatables, NULL); + /* Complete DELETE FROM
*/ + else if (pg_strcasecmp(prev3_wd, "DELETE") == 0 && + pg_strcasecmp(prev2_wd, "FROM") == 0) + { + static const char *const list_DELETE[] = + {"USING", "WHERE", NULL}; + + COMPLETE_WITH_LIST(list_DELETE); + } + /* XXX: implement tab completion for DELETE ... USING */ + +/* DISCARD */ + else if (pg_strcasecmp(prev_wd, "DISCARD") == 0) + { + static const char *const list_DISCARD[] = + {"ALL", "PLANS", "SEQUENCES", "TEMP", NULL}; + + COMPLETE_WITH_LIST(list_DISCARD); + } + +/* DO */ + + /* + * Complete DO with LANGUAGE. + */ + else if (pg_strcasecmp(prev_wd, "DO") == 0) + { + static const char *const list_DO[] = + {"LANGUAGE", NULL}; + + COMPLETE_WITH_LIST(list_DO); + } + +/* DROP (when not the previous word) */ + /* DROP AGGREGATE */ + else if (pg_strcasecmp(prev3_wd, "DROP") == 0 && + pg_strcasecmp(prev2_wd, "AGGREGATE") == 0) + COMPLETE_WITH_CONST("("); + + /* DROP object with CASCADE / RESTRICT */ + else if ((pg_strcasecmp(prev3_wd, "DROP") == 0 && + (pg_strcasecmp(prev2_wd, "COLLATION") == 0 || + pg_strcasecmp(prev2_wd, "CONVERSION") == 0 || + pg_strcasecmp(prev2_wd, "DOMAIN") == 0 || + pg_strcasecmp(prev2_wd, "EXTENSION") == 0 || + pg_strcasecmp(prev2_wd, "FUNCTION") == 0 || + pg_strcasecmp(prev2_wd, "INDEX") == 0 || + pg_strcasecmp(prev2_wd, "LANGUAGE") == 0 || + pg_strcasecmp(prev2_wd, "SCHEMA") == 0 || + pg_strcasecmp(prev2_wd, "SEQUENCE") == 0 || + pg_strcasecmp(prev2_wd, "SERVER") == 0 || + pg_strcasecmp(prev2_wd, "TABLE") == 0 || + pg_strcasecmp(prev2_wd, "TYPE") == 0 || + pg_strcasecmp(prev2_wd, "VIEW") == 0)) || + (pg_strcasecmp(prev4_wd, "DROP") == 0 && + pg_strcasecmp(prev3_wd, "AGGREGATE") == 0 && + prev_wd[strlen(prev_wd) - 1] == ')') || + (pg_strcasecmp(prev4_wd, "DROP") == 0 && + pg_strcasecmp(prev3_wd, "EVENT") == 0 && + pg_strcasecmp(prev2_wd, "TRIGGER") == 0) || + (pg_strcasecmp(prev5_wd, "DROP") == 0 && + pg_strcasecmp(prev4_wd, "FOREIGN") == 0 && + pg_strcasecmp(prev3_wd, "DATA") == 0 && + pg_strcasecmp(prev2_wd, "WRAPPER") == 0) || + (pg_strcasecmp(prev5_wd, "DROP") == 0 && + pg_strcasecmp(prev4_wd, "TEXT") == 0 && + pg_strcasecmp(prev3_wd, "SEARCH") == 0 && + (pg_strcasecmp(prev2_wd, "CONFIGURATION") == 0 || + pg_strcasecmp(prev2_wd, "DICTIONARY") == 0 || + pg_strcasecmp(prev2_wd, "PARSER") == 0 || + pg_strcasecmp(prev2_wd, "TEMPLATE") == 0)) + ) + { + if (pg_strcasecmp(prev3_wd, "DROP") == 0 && + pg_strcasecmp(prev2_wd, "FUNCTION") == 0) + { + COMPLETE_WITH_CONST("("); + } + else + { + static const char *const list_DROPCR[] = + {"CASCADE", "RESTRICT", NULL}; + + COMPLETE_WITH_LIST(list_DROPCR); + } + } + else if (pg_strcasecmp(prev2_wd, "DROP") == 0 && + pg_strcasecmp(prev_wd, "FOREIGN") == 0) + { + static const char *const drop_CREATE_FOREIGN[] = + {"DATA WRAPPER", "TABLE", NULL}; + + COMPLETE_WITH_LIST(drop_CREATE_FOREIGN); + } + + /* DROP MATERIALIZED VIEW */ + else if (pg_strcasecmp(prev2_wd, "DROP") == 0 && + pg_strcasecmp(prev_wd, "MATERIALIZED") == 0) + { + COMPLETE_WITH_CONST("VIEW"); + } + else if (pg_strcasecmp(prev3_wd, "DROP") == 0 && + pg_strcasecmp(prev2_wd, "MATERIALIZED") == 0 && + pg_strcasecmp(prev_wd, "VIEW") == 0) + { + COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_matviews, NULL); + } + + else if (pg_strcasecmp(prev4_wd, "DROP") == 0 && + (pg_strcasecmp(prev3_wd, "AGGREGATE") == 0 || + pg_strcasecmp(prev3_wd, "FUNCTION") == 0) && + pg_strcasecmp(prev_wd, "(") == 0) + COMPLETE_WITH_FUNCTION_ARG(prev2_wd); + /* DROP OWNED BY */ + else if (pg_strcasecmp(prev2_wd, "DROP") == 0 && + pg_strcasecmp(prev_wd, "OWNED") == 0) + COMPLETE_WITH_CONST("BY"); + else if (pg_strcasecmp(prev3_wd, "DROP") == 0 && + pg_strcasecmp(prev2_wd, "OWNED") == 0 && + pg_strcasecmp(prev_wd, "BY") == 0) + COMPLETE_WITH_QUERY(Query_for_list_of_roles); + else if (pg_strcasecmp(prev3_wd, "DROP") == 0 && + pg_strcasecmp(prev2_wd, "TEXT") == 0 && + pg_strcasecmp(prev_wd, "SEARCH") == 0) + { + + static const char *const list_ALTERTEXTSEARCH[] = + {"CONFIGURATION", "DICTIONARY", "PARSER", "TEMPLATE", NULL}; + + COMPLETE_WITH_LIST(list_ALTERTEXTSEARCH); + } + + /* DROP TRIGGER */ + else if (pg_strcasecmp(prev3_wd, "DROP") == 0 && + pg_strcasecmp(prev2_wd, "TRIGGER") == 0) + { + COMPLETE_WITH_CONST("ON"); + } + else if (pg_strcasecmp(prev4_wd, "DROP") == 0 && + pg_strcasecmp(prev3_wd, "TRIGGER") == 0 && + pg_strcasecmp(prev_wd, "ON") == 0) + { + completion_info_charp = prev2_wd; + COMPLETE_WITH_QUERY(Query_for_list_of_tables_for_trigger); + } + else if (pg_strcasecmp(prev5_wd, "DROP") == 0 && + pg_strcasecmp(prev4_wd, "TRIGGER") == 0 && + pg_strcasecmp(prev2_wd, "ON") == 0) + { + static const char *const list_DROPCR[] = + {"CASCADE", "RESTRICT", NULL}; + + COMPLETE_WITH_LIST(list_DROPCR); + } + + /* DROP EVENT TRIGGER */ + else if (pg_strcasecmp(prev2_wd, "DROP") == 0 && + pg_strcasecmp(prev_wd, "EVENT") == 0) + { + COMPLETE_WITH_CONST("TRIGGER"); + } + else if (pg_strcasecmp(prev3_wd, "DROP") == 0 && + pg_strcasecmp(prev2_wd, "EVENT") == 0 && + pg_strcasecmp(prev_wd, "TRIGGER") == 0) + { + COMPLETE_WITH_QUERY(Query_for_list_of_event_triggers); + } + + /* DROP POLICY */ + else if (pg_strcasecmp(prev2_wd, "DROP") == 0 && + pg_strcasecmp(prev_wd, "POLICY") == 0) + { + COMPLETE_WITH_QUERY(Query_for_list_of_policies); + } + /* DROP POLICY ON */ + else if (pg_strcasecmp(prev3_wd, "DROP") == 0 && + pg_strcasecmp(prev2_wd, "POLICY") == 0) + { + COMPLETE_WITH_CONST("ON"); + } + /* DROP POLICY ON
*/ + else if (pg_strcasecmp(prev4_wd, "DROP") == 0 && + pg_strcasecmp(prev3_wd, "POLICY") == 0 && + pg_strcasecmp(prev_wd, "ON") == 0) + { + completion_info_charp = prev2_wd; + COMPLETE_WITH_QUERY(Query_for_list_of_tables_for_policy); + } + + /* DROP RULE */ + else if (pg_strcasecmp(prev3_wd, "DROP") == 0 && + pg_strcasecmp(prev2_wd, "RULE") == 0) + { + COMPLETE_WITH_CONST("ON"); + } + else if (pg_strcasecmp(prev4_wd, "DROP") == 0 && + pg_strcasecmp(prev3_wd, "RULE") == 0 && + pg_strcasecmp(prev_wd, "ON") == 0) + { + completion_info_charp = prev2_wd; + COMPLETE_WITH_QUERY(Query_for_list_of_tables_for_rule); + } + else if (pg_strcasecmp(prev5_wd, "DROP") == 0 && + pg_strcasecmp(prev4_wd, "RULE") == 0 && + pg_strcasecmp(prev2_wd, "ON") == 0) + { + static const char *const list_DROPCR[] = + {"CASCADE", "RESTRICT", NULL}; + + COMPLETE_WITH_LIST(list_DROPCR); + } + +/* EXECUTE, but not EXECUTE embedded in other commands */ + else if (pg_strcasecmp(prev_wd, "EXECUTE") == 0 && + prev2_wd[0] == '\0') + COMPLETE_WITH_QUERY(Query_for_list_of_prepared_statements); + +/* EXPLAIN */ + + /* + * Complete EXPLAIN [ANALYZE] [VERBOSE] with list of EXPLAIN-able commands + */ + else if (pg_strcasecmp(prev_wd, "EXPLAIN") == 0) + { + static const char *const list_EXPLAIN[] = + {"SELECT", "INSERT", "DELETE", "UPDATE", "DECLARE", "ANALYZE", "VERBOSE", NULL}; + + COMPLETE_WITH_LIST(list_EXPLAIN); + } + else if (pg_strcasecmp(prev2_wd, "EXPLAIN") == 0 && + pg_strcasecmp(prev_wd, "ANALYZE") == 0) + { + static const char *const list_EXPLAIN[] = + {"SELECT", "INSERT", "DELETE", "UPDATE", "DECLARE", "VERBOSE", NULL}; + + COMPLETE_WITH_LIST(list_EXPLAIN); + } + else if ((pg_strcasecmp(prev2_wd, "EXPLAIN") == 0 && + pg_strcasecmp(prev_wd, "VERBOSE") == 0) || + (pg_strcasecmp(prev3_wd, "EXPLAIN") == 0 && + pg_strcasecmp(prev2_wd, "ANALYZE") == 0 && + pg_strcasecmp(prev_wd, "VERBOSE") == 0)) + { + static const char *const list_EXPLAIN[] = + {"SELECT", "INSERT", "DELETE", "UPDATE", "DECLARE", NULL}; + + COMPLETE_WITH_LIST(list_EXPLAIN); + } + +/* FETCH && MOVE */ + /* Complete FETCH with one of FORWARD, BACKWARD, RELATIVE */ + else if (pg_strcasecmp(prev_wd, "FETCH") == 0 || + pg_strcasecmp(prev_wd, "MOVE") == 0) + { + static const char *const list_FETCH1[] = + {"ABSOLUTE", "BACKWARD", "FORWARD", "RELATIVE", NULL}; + + COMPLETE_WITH_LIST(list_FETCH1); + } + /* Complete FETCH with one of ALL, NEXT, PRIOR */ + else if (pg_strcasecmp(prev2_wd, "FETCH") == 0 || + pg_strcasecmp(prev2_wd, "MOVE") == 0) + { + static const char *const list_FETCH2[] = + {"ALL", "NEXT", "PRIOR", NULL}; + + COMPLETE_WITH_LIST(list_FETCH2); + } + + /* + * Complete FETCH with "FROM" or "IN". These are equivalent, + * but we may as well tab-complete both: perhaps some users prefer one + * variant or the other. + */ + else if (pg_strcasecmp(prev3_wd, "FETCH") == 0 || + pg_strcasecmp(prev3_wd, "MOVE") == 0) + { + static const char *const list_FROMIN[] = + {"FROM", "IN", NULL}; + + COMPLETE_WITH_LIST(list_FROMIN); + } + +/* FOREIGN DATA WRAPPER */ + /* applies in ALTER/DROP FDW and in CREATE SERVER */ + else if (pg_strcasecmp(prev4_wd, "CREATE") != 0 && + pg_strcasecmp(prev3_wd, "FOREIGN") == 0 && + pg_strcasecmp(prev2_wd, "DATA") == 0 && + pg_strcasecmp(prev_wd, "WRAPPER") == 0) + COMPLETE_WITH_QUERY(Query_for_list_of_fdws); + +/* FOREIGN TABLE */ + else if (pg_strcasecmp(prev3_wd, "CREATE") != 0 && + pg_strcasecmp(prev2_wd, "FOREIGN") == 0 && + pg_strcasecmp(prev_wd, "TABLE") == 0) + COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_foreign_tables, NULL); + +/* GRANT && REVOKE */ + /* Complete GRANT/REVOKE with a list of roles and privileges */ + else if (pg_strcasecmp(prev_wd, "GRANT") == 0 || + pg_strcasecmp(prev_wd, "REVOKE") == 0) + { + COMPLETE_WITH_QUERY(Query_for_list_of_roles + " UNION SELECT 'SELECT'" + " UNION SELECT 'INSERT'" + " UNION SELECT 'UPDATE'" + " UNION SELECT 'DELETE'" + " UNION SELECT 'TRUNCATE'" + " UNION SELECT 'REFERENCES'" + " UNION SELECT 'TRIGGER'" + " UNION SELECT 'CREATE'" + " UNION SELECT 'CONNECT'" + " UNION SELECT 'TEMPORARY'" + " UNION SELECT 'EXECUTE'" + " UNION SELECT 'USAGE'" + " UNION SELECT 'ALL'"); + } + + /* + * Complete GRANT/REVOKE with "ON", GRANT/REVOKE with + * TO/FROM + */ + else if (pg_strcasecmp(prev2_wd, "GRANT") == 0 || + pg_strcasecmp(prev2_wd, "REVOKE") == 0) + { + if (pg_strcasecmp(prev_wd, "SELECT") == 0 + || pg_strcasecmp(prev_wd, "INSERT") == 0 + || pg_strcasecmp(prev_wd, "UPDATE") == 0 + || pg_strcasecmp(prev_wd, "DELETE") == 0 + || pg_strcasecmp(prev_wd, "TRUNCATE") == 0 + || pg_strcasecmp(prev_wd, "REFERENCES") == 0 + || pg_strcasecmp(prev_wd, "TRIGGER") == 0 + || pg_strcasecmp(prev_wd, "CREATE") == 0 + || pg_strcasecmp(prev_wd, "CONNECT") == 0 + || pg_strcasecmp(prev_wd, "TEMPORARY") == 0 + || pg_strcasecmp(prev_wd, "TEMP") == 0 + || pg_strcasecmp(prev_wd, "EXECUTE") == 0 + || pg_strcasecmp(prev_wd, "USAGE") == 0 + || pg_strcasecmp(prev_wd, "ALL") == 0) + COMPLETE_WITH_CONST("ON"); + else + { + if (pg_strcasecmp(prev2_wd, "GRANT") == 0) + COMPLETE_WITH_CONST("TO"); + else + COMPLETE_WITH_CONST("FROM"); + } + } + + /* + * Complete GRANT/REVOKE ON with a list of tables, views, sequences, + * and indexes + * + * keywords DATABASE, FUNCTION, LANGUAGE, SCHEMA added to query result via + * UNION; seems to work intuitively + * + * Note: GRANT/REVOKE can get quite complex; tab-completion as implemented + * here will only work if the privilege list contains exactly one + * privilege + */ + else if ((pg_strcasecmp(prev3_wd, "GRANT") == 0 || + pg_strcasecmp(prev3_wd, "REVOKE") == 0) && + pg_strcasecmp(prev_wd, "ON") == 0) + COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tsvmf, + " UNION SELECT 'DATABASE'" + " UNION SELECT 'DOMAIN'" + " UNION SELECT 'FOREIGN DATA WRAPPER'" + " UNION SELECT 'FOREIGN SERVER'" + " UNION SELECT 'FUNCTION'" + " UNION SELECT 'LANGUAGE'" + " UNION SELECT 'LARGE OBJECT'" + " UNION SELECT 'SCHEMA'" + " UNION SELECT 'TABLESPACE'" + " UNION SELECT 'TYPE'"); + else if ((pg_strcasecmp(prev4_wd, "GRANT") == 0 || + pg_strcasecmp(prev4_wd, "REVOKE") == 0) && + pg_strcasecmp(prev2_wd, "ON") == 0 && + pg_strcasecmp(prev_wd, "FOREIGN") == 0) + { + static const char *const list_privilege_foreign[] = + {"DATA WRAPPER", "SERVER", NULL}; + + COMPLETE_WITH_LIST(list_privilege_foreign); + } + + /* Complete "GRANT/REVOKE * ON * " with "TO/FROM" */ + else if ((pg_strcasecmp(prev4_wd, "GRANT") == 0 || + pg_strcasecmp(prev4_wd, "REVOKE") == 0) && + pg_strcasecmp(prev2_wd, "ON") == 0) + { + if (pg_strcasecmp(prev_wd, "DATABASE") == 0) + COMPLETE_WITH_QUERY(Query_for_list_of_databases); + else if (pg_strcasecmp(prev_wd, "DOMAIN") == 0) + COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_domains, NULL); + else if (pg_strcasecmp(prev_wd, "FUNCTION") == 0) + COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_functions, NULL); + else if (pg_strcasecmp(prev_wd, "LANGUAGE") == 0) + COMPLETE_WITH_QUERY(Query_for_list_of_languages); + else if (pg_strcasecmp(prev_wd, "SCHEMA") == 0) + COMPLETE_WITH_QUERY(Query_for_list_of_schemas); + else if (pg_strcasecmp(prev_wd, "TABLESPACE") == 0) + COMPLETE_WITH_QUERY(Query_for_list_of_tablespaces); + else if (pg_strcasecmp(prev_wd, "TYPE") == 0) + COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_datatypes, NULL); + else if (pg_strcasecmp(prev4_wd, "GRANT") == 0) + COMPLETE_WITH_CONST("TO"); + else + COMPLETE_WITH_CONST("FROM"); + } + + /* Complete "GRANT/REVOKE * ON * TO/FROM" with username, GROUP, or PUBLIC */ + else if (pg_strcasecmp(prev5_wd, "GRANT") == 0 && + pg_strcasecmp(prev3_wd, "ON") == 0) + { + if (pg_strcasecmp(prev_wd, "TO") == 0) + COMPLETE_WITH_QUERY(Query_for_list_of_grant_roles); + else + COMPLETE_WITH_CONST("TO"); + } + else if (pg_strcasecmp(prev5_wd, "REVOKE") == 0 && + pg_strcasecmp(prev3_wd, "ON") == 0) + { + if (pg_strcasecmp(prev_wd, "FROM") == 0) + COMPLETE_WITH_QUERY(Query_for_list_of_grant_roles); + else + COMPLETE_WITH_CONST("FROM"); + } + + /* Complete "GRANT/REVOKE * TO/FROM" with username, GROUP, or PUBLIC */ + else if (pg_strcasecmp(prev3_wd, "GRANT") == 0 && + pg_strcasecmp(prev_wd, "TO") == 0) + { + COMPLETE_WITH_QUERY(Query_for_list_of_grant_roles); + } + else if (pg_strcasecmp(prev3_wd, "REVOKE") == 0 && + pg_strcasecmp(prev_wd, "FROM") == 0) + { + COMPLETE_WITH_QUERY(Query_for_list_of_grant_roles); + } + +/* GROUP BY */ + else if (pg_strcasecmp(prev3_wd, "FROM") == 0 && + pg_strcasecmp(prev_wd, "GROUP") == 0) + COMPLETE_WITH_CONST("BY"); + +/* IMPORT FOREIGN SCHEMA */ + else if (pg_strcasecmp(prev_wd, "IMPORT") == 0) + COMPLETE_WITH_CONST("FOREIGN SCHEMA"); + else if (pg_strcasecmp(prev2_wd, "IMPORT") == 0 && + pg_strcasecmp(prev_wd, "FOREIGN") == 0) + COMPLETE_WITH_CONST("SCHEMA"); + +/* INSERT */ + /* Complete INSERT with "INTO" */ + else if (pg_strcasecmp(prev_wd, "INSERT") == 0) + COMPLETE_WITH_CONST("INTO"); + /* Complete INSERT INTO with table names */ + else if (pg_strcasecmp(prev2_wd, "INSERT") == 0 && + pg_strcasecmp(prev_wd, "INTO") == 0) + COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_updatables, NULL); + /* Complete "INSERT INTO
(" with attribute names */ + else if (pg_strcasecmp(prev4_wd, "INSERT") == 0 && + pg_strcasecmp(prev3_wd, "INTO") == 0 && + pg_strcasecmp(prev_wd, "(") == 0) + COMPLETE_WITH_ATTR(prev2_wd, ""); + + /* + * Complete INSERT INTO
with "(" or "VALUES" or "SELECT" or + * "TABLE" or "DEFAULT VALUES" + */ + else if (pg_strcasecmp(prev3_wd, "INSERT") == 0 && + pg_strcasecmp(prev2_wd, "INTO") == 0) + { + static const char *const list_INSERT[] = + {"(", "DEFAULT VALUES", "SELECT", "TABLE", "VALUES", NULL}; + + COMPLETE_WITH_LIST(list_INSERT); + } + + /* + * Complete INSERT INTO
(attribs) with "VALUES" or "SELECT" or + * "TABLE" + */ + else if (pg_strcasecmp(prev4_wd, "INSERT") == 0 && + pg_strcasecmp(prev3_wd, "INTO") == 0 && + prev_wd[strlen(prev_wd) - 1] == ')') + { + static const char *const list_INSERT[] = + {"SELECT", "TABLE", "VALUES", NULL}; + + COMPLETE_WITH_LIST(list_INSERT); + } + + /* Insert an open parenthesis after "VALUES" */ + else if (pg_strcasecmp(prev_wd, "VALUES") == 0 && + pg_strcasecmp(prev2_wd, "DEFAULT") != 0) + COMPLETE_WITH_CONST("("); + +/* LOCK */ + /* Complete LOCK [TABLE] with a list of tables */ + else if (pg_strcasecmp(prev_wd, "LOCK") == 0) + COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, + " UNION SELECT 'TABLE'"); + else if (pg_strcasecmp(prev_wd, "TABLE") == 0 && + pg_strcasecmp(prev2_wd, "LOCK") == 0) + COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, ""); + + /* For the following, handle the case of a single table only for now */ + + /* Complete LOCK [TABLE]
with "IN" */ + else if ((pg_strcasecmp(prev2_wd, "LOCK") == 0 && + pg_strcasecmp(prev_wd, "TABLE") != 0) || + (pg_strcasecmp(prev2_wd, "TABLE") == 0 && + pg_strcasecmp(prev3_wd, "LOCK") == 0)) + COMPLETE_WITH_CONST("IN"); + + /* Complete LOCK [TABLE]
IN with a lock mode */ + else if (pg_strcasecmp(prev_wd, "IN") == 0 && + (pg_strcasecmp(prev3_wd, "LOCK") == 0 || + (pg_strcasecmp(prev3_wd, "TABLE") == 0 && + pg_strcasecmp(prev4_wd, "LOCK") == 0))) + { + static const char *const lock_modes[] = + {"ACCESS SHARE MODE", + "ROW SHARE MODE", "ROW EXCLUSIVE MODE", + "SHARE UPDATE EXCLUSIVE MODE", "SHARE MODE", + "SHARE ROW EXCLUSIVE MODE", + "EXCLUSIVE MODE", "ACCESS EXCLUSIVE MODE", NULL}; + + COMPLETE_WITH_LIST(lock_modes); + } + +/* NOTIFY */ + else if (pg_strcasecmp(prev_wd, "NOTIFY") == 0) + COMPLETE_WITH_QUERY("SELECT pg_catalog.quote_ident(channel) FROM pg_catalog.pg_listening_channels() AS channel WHERE substring(pg_catalog.quote_ident(channel),1,%d)='%s'"); + +/* OPTIONS */ + else if (pg_strcasecmp(prev_wd, "OPTIONS") == 0) + COMPLETE_WITH_CONST("("); + +/* OWNER TO - complete with available roles */ + else if (pg_strcasecmp(prev2_wd, "OWNER") == 0 && + pg_strcasecmp(prev_wd, "TO") == 0) + COMPLETE_WITH_QUERY(Query_for_list_of_roles); + +/* ORDER BY */ + else if (pg_strcasecmp(prev3_wd, "FROM") == 0 && + pg_strcasecmp(prev_wd, "ORDER") == 0) + COMPLETE_WITH_CONST("BY"); + else if (pg_strcasecmp(prev4_wd, "FROM") == 0 && + pg_strcasecmp(prev2_wd, "ORDER") == 0 && + pg_strcasecmp(prev_wd, "BY") == 0) + COMPLETE_WITH_ATTR(prev3_wd, ""); + +/* PREPARE xx AS */ + else if (pg_strcasecmp(prev_wd, "AS") == 0 && + pg_strcasecmp(prev3_wd, "PREPARE") == 0) + { + static const char *const list_PREPARE[] = + {"SELECT", "UPDATE", "INSERT", "DELETE", NULL}; + + COMPLETE_WITH_LIST(list_PREPARE); + } + +/* + * PREPARE TRANSACTION is missing on purpose. It's intended for transaction + * managers, not for manual use in interactive sessions. + */ + +/* REASSIGN OWNED BY xxx TO yyy */ + else if (pg_strcasecmp(prev_wd, "REASSIGN") == 0) + COMPLETE_WITH_CONST("OWNED"); + else if (pg_strcasecmp(prev_wd, "OWNED") == 0 && + pg_strcasecmp(prev2_wd, "REASSIGN") == 0) + COMPLETE_WITH_CONST("BY"); + else if (pg_strcasecmp(prev_wd, "BY") == 0 && + pg_strcasecmp(prev2_wd, "OWNED") == 0 && + pg_strcasecmp(prev3_wd, "REASSIGN") == 0) + COMPLETE_WITH_QUERY(Query_for_list_of_roles); + else if (pg_strcasecmp(prev2_wd, "BY") == 0 && + pg_strcasecmp(prev3_wd, "OWNED") == 0 && + pg_strcasecmp(prev4_wd, "REASSIGN") == 0) + COMPLETE_WITH_CONST("TO"); + else if (pg_strcasecmp(prev_wd, "TO") == 0 && + pg_strcasecmp(prev3_wd, "BY") == 0 && + pg_strcasecmp(prev4_wd, "OWNED") == 0 && + pg_strcasecmp(prev5_wd, "REASSIGN") == 0) + COMPLETE_WITH_QUERY(Query_for_list_of_roles); + +/* REFRESH MATERIALIZED VIEW */ + else if (pg_strcasecmp(prev_wd, "REFRESH") == 0) + COMPLETE_WITH_CONST("MATERIALIZED VIEW"); + else if (pg_strcasecmp(prev2_wd, "REFRESH") == 0 && + pg_strcasecmp(prev_wd, "MATERIALIZED") == 0) + COMPLETE_WITH_CONST("VIEW"); + else if (pg_strcasecmp(prev3_wd, "REFRESH") == 0 && + pg_strcasecmp(prev2_wd, "MATERIALIZED") == 0 && + pg_strcasecmp(prev_wd, "VIEW") == 0) + COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_matviews, + " UNION SELECT 'CONCURRENTLY'"); + else if (pg_strcasecmp(prev4_wd, "REFRESH") == 0 && + pg_strcasecmp(prev3_wd, "MATERIALIZED") == 0 && + pg_strcasecmp(prev2_wd, "VIEW") == 0 && + pg_strcasecmp(prev_wd, "CONCURRENTLY") == 0) + COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_matviews, NULL); + else if (pg_strcasecmp(prev4_wd, "REFRESH") == 0 && + pg_strcasecmp(prev3_wd, "MATERIALIZED") == 0 && + pg_strcasecmp(prev2_wd, "VIEW") == 0) + COMPLETE_WITH_CONST("WITH"); + else if (pg_strcasecmp(prev5_wd, "REFRESH") == 0 && + pg_strcasecmp(prev4_wd, "MATERIALIZED") == 0 && + pg_strcasecmp(prev3_wd, "VIEW") == 0 && + pg_strcasecmp(prev2_wd, "CONCURRENTLY") == 0) + COMPLETE_WITH_CONST("WITH DATA"); + else if (pg_strcasecmp(prev5_wd, "REFRESH") == 0 && + pg_strcasecmp(prev4_wd, "MATERIALIZED") == 0 && + pg_strcasecmp(prev3_wd, "VIEW") == 0 && + pg_strcasecmp(prev_wd, "WITH") == 0) + { + static const char *const list_WITH_DATA[] = + {"NO DATA", "DATA", NULL}; + + COMPLETE_WITH_LIST(list_WITH_DATA); + } + else if (pg_strcasecmp(prev6_wd, "REFRESH") == 0 && + pg_strcasecmp(prev5_wd, "MATERIALIZED") == 0 && + pg_strcasecmp(prev4_wd, "VIEW") == 0 && + pg_strcasecmp(prev3_wd, "CONCURRENTLY") == 0 && + pg_strcasecmp(prev_wd, "WITH") == 0) + COMPLETE_WITH_CONST("DATA"); + else if (pg_strcasecmp(prev6_wd, "REFRESH") == 0 && + pg_strcasecmp(prev5_wd, "MATERIALIZED") == 0 && + pg_strcasecmp(prev4_wd, "VIEW") == 0 && + pg_strcasecmp(prev2_wd, "WITH") == 0 && + pg_strcasecmp(prev_wd, "NO") == 0) + COMPLETE_WITH_CONST("DATA"); + +/* REINDEX */ + else if (pg_strcasecmp(prev_wd, "REINDEX") == 0) + { + static const char *const list_REINDEX[] = + {"TABLE", "INDEX", "SYSTEM", "SCHEMA", "DATABASE", NULL}; + + COMPLETE_WITH_LIST(list_REINDEX); + } + else if (pg_strcasecmp(prev2_wd, "REINDEX") == 0) + { + if (pg_strcasecmp(prev_wd, "TABLE") == 0) + COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm, NULL); + else if (pg_strcasecmp(prev_wd, "INDEX") == 0) + COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes, NULL); + else if (pg_strcasecmp(prev_wd, "SCHEMA") == 0) + COMPLETE_WITH_QUERY(Query_for_list_of_schemas); + else if (pg_strcasecmp(prev_wd, "SYSTEM") == 0 || + pg_strcasecmp(prev_wd, "DATABASE") == 0) + COMPLETE_WITH_QUERY(Query_for_list_of_databases); + } + +/* SECURITY LABEL */ + else if (pg_strcasecmp(prev_wd, "SECURITY") == 0) + COMPLETE_WITH_CONST("LABEL"); + else if (pg_strcasecmp(prev2_wd, "SECURITY") == 0 && + pg_strcasecmp(prev_wd, "LABEL") == 0) + { + static const char *const list_SECURITY_LABEL_preposition[] = + {"ON", "FOR"}; + + COMPLETE_WITH_LIST(list_SECURITY_LABEL_preposition); + } + else if (pg_strcasecmp(prev4_wd, "SECURITY") == 0 && + pg_strcasecmp(prev3_wd, "LABEL") == 0 && + pg_strcasecmp(prev2_wd, "FOR") == 0) + COMPLETE_WITH_CONST("ON"); + else if ((pg_strcasecmp(prev3_wd, "SECURITY") == 0 && + pg_strcasecmp(prev2_wd, "LABEL") == 0 && + pg_strcasecmp(prev_wd, "ON") == 0) || + (pg_strcasecmp(prev5_wd, "SECURITY") == 0 && + pg_strcasecmp(prev4_wd, "LABEL") == 0 && + pg_strcasecmp(prev3_wd, "FOR") == 0 && + pg_strcasecmp(prev_wd, "ON") == 0)) + { + static const char *const list_SECURITY_LABEL[] = + {"LANGUAGE", "SCHEMA", "SEQUENCE", "TABLE", "TYPE", "VIEW", + "MATERIALIZED VIEW", "COLUMN", "AGGREGATE", "FUNCTION", "DOMAIN", + "LARGE OBJECT", NULL}; + + COMPLETE_WITH_LIST(list_SECURITY_LABEL); + } + else if (pg_strcasecmp(prev5_wd, "SECURITY") == 0 && + pg_strcasecmp(prev4_wd, "LABEL") == 0 && + pg_strcasecmp(prev3_wd, "ON") == 0) + COMPLETE_WITH_CONST("IS"); + +/* SELECT */ + /* naah . . . */ + +/* SET, RESET, SHOW */ + /* Complete with a variable name */ + else if ((pg_strcasecmp(prev_wd, "SET") == 0 && + pg_strcasecmp(prev3_wd, "UPDATE") != 0) || + pg_strcasecmp(prev_wd, "RESET") == 0) + COMPLETE_WITH_QUERY(Query_for_list_of_set_vars); + else if (pg_strcasecmp(prev_wd, "SHOW") == 0) + COMPLETE_WITH_QUERY(Query_for_list_of_show_vars); + /* Complete "SET TRANSACTION" */ + else if ((pg_strcasecmp(prev2_wd, "SET") == 0 && + pg_strcasecmp(prev_wd, "TRANSACTION") == 0) + || (pg_strcasecmp(prev2_wd, "START") == 0 + && pg_strcasecmp(prev_wd, "TRANSACTION") == 0) + || (pg_strcasecmp(prev2_wd, "BEGIN") == 0 + && pg_strcasecmp(prev_wd, "WORK") == 0) + || (pg_strcasecmp(prev2_wd, "BEGIN") == 0 + && pg_strcasecmp(prev_wd, "TRANSACTION") == 0) + || (pg_strcasecmp(prev4_wd, "SESSION") == 0 + && pg_strcasecmp(prev3_wd, "CHARACTERISTICS") == 0 + && pg_strcasecmp(prev2_wd, "AS") == 0 + && pg_strcasecmp(prev_wd, "TRANSACTION") == 0)) + { + static const char *const my_list[] = + {"ISOLATION LEVEL", "READ", NULL}; + + COMPLETE_WITH_LIST(my_list); + } + else if ((pg_strcasecmp(prev3_wd, "SET") == 0 + || pg_strcasecmp(prev3_wd, "BEGIN") == 0 + || pg_strcasecmp(prev3_wd, "START") == 0 + || (pg_strcasecmp(prev4_wd, "CHARACTERISTICS") == 0 + && pg_strcasecmp(prev3_wd, "AS") == 0)) + && (pg_strcasecmp(prev2_wd, "TRANSACTION") == 0 + || pg_strcasecmp(prev2_wd, "WORK") == 0) + && pg_strcasecmp(prev_wd, "ISOLATION") == 0) + COMPLETE_WITH_CONST("LEVEL"); + else if ((pg_strcasecmp(prev4_wd, "SET") == 0 + || pg_strcasecmp(prev4_wd, "BEGIN") == 0 + || pg_strcasecmp(prev4_wd, "START") == 0 + || pg_strcasecmp(prev4_wd, "AS") == 0) + && (pg_strcasecmp(prev3_wd, "TRANSACTION") == 0 + || pg_strcasecmp(prev3_wd, "WORK") == 0) + && pg_strcasecmp(prev2_wd, "ISOLATION") == 0 + && pg_strcasecmp(prev_wd, "LEVEL") == 0) + { + static const char *const my_list[] = + {"READ", "REPEATABLE", "SERIALIZABLE", NULL}; + + COMPLETE_WITH_LIST(my_list); + } + else if ((pg_strcasecmp(prev4_wd, "TRANSACTION") == 0 || + pg_strcasecmp(prev4_wd, "WORK") == 0) && + pg_strcasecmp(prev3_wd, "ISOLATION") == 0 && + pg_strcasecmp(prev2_wd, "LEVEL") == 0 && + pg_strcasecmp(prev_wd, "READ") == 0) + { + static const char *const my_list[] = + {"UNCOMMITTED", "COMMITTED", NULL}; + + COMPLETE_WITH_LIST(my_list); + } + else if ((pg_strcasecmp(prev4_wd, "TRANSACTION") == 0 || + pg_strcasecmp(prev4_wd, "WORK") == 0) && + pg_strcasecmp(prev3_wd, "ISOLATION") == 0 && + pg_strcasecmp(prev2_wd, "LEVEL") == 0 && + pg_strcasecmp(prev_wd, "REPEATABLE") == 0) + COMPLETE_WITH_CONST("READ"); + else if ((pg_strcasecmp(prev3_wd, "SET") == 0 || + pg_strcasecmp(prev3_wd, "BEGIN") == 0 || + pg_strcasecmp(prev3_wd, "START") == 0 || + pg_strcasecmp(prev3_wd, "AS") == 0) && + (pg_strcasecmp(prev2_wd, "TRANSACTION") == 0 || + pg_strcasecmp(prev2_wd, "WORK") == 0) && + pg_strcasecmp(prev_wd, "READ") == 0) + { + static const char *const my_list[] = + {"ONLY", "WRITE", NULL}; + + COMPLETE_WITH_LIST(my_list); + } + /* SET CONSTRAINTS */ + else if (pg_strcasecmp(prev2_wd, "SET") == 0 && + pg_strcasecmp(prev_wd, "CONSTRAINTS") == 0) + { + COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_constraints_with_schema, "UNION SELECT 'ALL'"); + } + /* Complete SET CONSTRAINTS with DEFERRED|IMMEDIATE */ + else if (pg_strcasecmp(prev3_wd, "SET") == 0 && + pg_strcasecmp(prev2_wd, "CONSTRAINTS") == 0) + { + static const char *const constraint_list[] = + {"DEFERRED", "IMMEDIATE", NULL}; + + COMPLETE_WITH_LIST(constraint_list); + } + /* Complete SET ROLE */ + else if (pg_strcasecmp(prev2_wd, "SET") == 0 && + pg_strcasecmp(prev_wd, "ROLE") == 0) + COMPLETE_WITH_QUERY(Query_for_list_of_roles); + /* Complete SET SESSION with AUTHORIZATION or CHARACTERISTICS... */ + else if (pg_strcasecmp(prev2_wd, "SET") == 0 && + pg_strcasecmp(prev_wd, "SESSION") == 0) + { + static const char *const my_list[] = + {"AUTHORIZATION", "CHARACTERISTICS AS TRANSACTION", NULL}; + + COMPLETE_WITH_LIST(my_list); + } + /* Complete SET SESSION AUTHORIZATION with username */ + else if (pg_strcasecmp(prev3_wd, "SET") == 0 + && pg_strcasecmp(prev2_wd, "SESSION") == 0 + && pg_strcasecmp(prev_wd, "AUTHORIZATION") == 0) + COMPLETE_WITH_QUERY(Query_for_list_of_roles " UNION SELECT 'DEFAULT'"); + /* Complete RESET SESSION with AUTHORIZATION */ + else if (pg_strcasecmp(prev2_wd, "RESET") == 0 && + pg_strcasecmp(prev_wd, "SESSION") == 0) + COMPLETE_WITH_CONST("AUTHORIZATION"); + /* Complete SET with "TO" */ + else if (pg_strcasecmp(prev2_wd, "SET") == 0 && + pg_strcasecmp(prev4_wd, "UPDATE") != 0 && + pg_strcasecmp(prev_wd, "TABLESPACE") != 0 && + pg_strcasecmp(prev_wd, "SCHEMA") != 0 && + prev_wd[strlen(prev_wd) - 1] != ')' && + prev_wd[strlen(prev_wd) - 1] != '=' && + pg_strcasecmp(prev4_wd, "DOMAIN") != 0) + COMPLETE_WITH_CONST("TO"); + /* Suggest possible variable values */ + else if (pg_strcasecmp(prev3_wd, "SET") == 0 && + (pg_strcasecmp(prev_wd, "TO") == 0 || strcmp(prev_wd, "=") == 0)) + { + if (pg_strcasecmp(prev2_wd, "DateStyle") == 0) + { + static const char *const my_list[] = + {"ISO", "SQL", "Postgres", "German", + "YMD", "DMY", "MDY", + "US", "European", "NonEuropean", + "DEFAULT", NULL}; + + COMPLETE_WITH_LIST(my_list); + } + else if (pg_strcasecmp(prev2_wd, "IntervalStyle") == 0) + { + static const char *const my_list[] = + {"postgres", "postgres_verbose", "sql_standard", "iso_8601", NULL}; + + COMPLETE_WITH_LIST(my_list); + } + else if (pg_strcasecmp(prev2_wd, "GEQO") == 0) + { + static const char *const my_list[] = + {"ON", "OFF", "DEFAULT", NULL}; + + COMPLETE_WITH_LIST(my_list); + } + else if (pg_strcasecmp(prev2_wd, "search_path") == 0) + { + COMPLETE_WITH_QUERY(Query_for_list_of_schemas + " AND nspname not like 'pg\\_toast%%' " + " AND nspname not like 'pg\\_temp%%' " + " UNION SELECT 'DEFAULT' "); + } + else + { + static const char *const my_list[] = + {"DEFAULT", NULL}; + + COMPLETE_WITH_LIST(my_list); + } + } + +/* START TRANSACTION */ + else if (pg_strcasecmp(prev_wd, "START") == 0) + COMPLETE_WITH_CONST("TRANSACTION"); + +/* TABLE, but not TABLE embedded in other commands */ + else if (pg_strcasecmp(prev_wd, "TABLE") == 0 && + prev2_wd[0] == '\0') + COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_relations, NULL); + +/* TABLESAMPLE */ + else if (pg_strcasecmp(prev_wd, "TABLESAMPLE") == 0) + COMPLETE_WITH_QUERY(Query_for_list_of_tablesample_methods); + + else if (pg_strcasecmp(prev2_wd, "TABLESAMPLE") == 0) + COMPLETE_WITH_CONST("("); + +/* TRUNCATE */ + else if (pg_strcasecmp(prev_wd, "TRUNCATE") == 0) + COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL); + +/* UNLISTEN */ + else if (pg_strcasecmp(prev_wd, "UNLISTEN") == 0) + COMPLETE_WITH_QUERY("SELECT pg_catalog.quote_ident(channel) FROM pg_catalog.pg_listening_channels() AS channel WHERE substring(pg_catalog.quote_ident(channel),1,%d)='%s' UNION SELECT '*'"); + +/* UPDATE */ + /* If prev. word is UPDATE suggest a list of tables */ + else if (pg_strcasecmp(prev_wd, "UPDATE") == 0) + COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_updatables, NULL); + /* Complete UPDATE
with "SET" */ + else if (pg_strcasecmp(prev2_wd, "UPDATE") == 0) + COMPLETE_WITH_CONST("SET"); + + /* + * If the previous word is SET (and it wasn't caught above as the _first_ + * word) the word before it was (hopefully) a table name and we'll now + * make a list of attributes. + */ + else if (pg_strcasecmp(prev_wd, "SET") == 0) + COMPLETE_WITH_ATTR(prev2_wd, ""); + +/* UPDATE xx SET yy = */ + else if (pg_strcasecmp(prev2_wd, "SET") == 0 && + pg_strcasecmp(prev4_wd, "UPDATE") == 0) + COMPLETE_WITH_CONST("="); + +/* USER MAPPING */ + else if ((pg_strcasecmp(prev3_wd, "ALTER") == 0 || + pg_strcasecmp(prev3_wd, "CREATE") == 0 || + pg_strcasecmp(prev3_wd, "DROP") == 0) && + pg_strcasecmp(prev2_wd, "USER") == 0 && + pg_strcasecmp(prev_wd, "MAPPING") == 0) + COMPLETE_WITH_CONST("FOR"); + else if (pg_strcasecmp(prev4_wd, "CREATE") == 0 && + pg_strcasecmp(prev3_wd, "USER") == 0 && + pg_strcasecmp(prev2_wd, "MAPPING") == 0 && + pg_strcasecmp(prev_wd, "FOR") == 0) + COMPLETE_WITH_QUERY(Query_for_list_of_roles + " UNION SELECT 'CURRENT_USER'" + " UNION SELECT 'PUBLIC'" + " UNION SELECT 'USER'"); + else if ((pg_strcasecmp(prev4_wd, "ALTER") == 0 || + pg_strcasecmp(prev4_wd, "DROP") == 0) && + pg_strcasecmp(prev3_wd, "USER") == 0 && + pg_strcasecmp(prev2_wd, "MAPPING") == 0 && + pg_strcasecmp(prev_wd, "FOR") == 0) + COMPLETE_WITH_QUERY(Query_for_list_of_user_mappings); + else if ((pg_strcasecmp(prev5_wd, "CREATE") == 0 || + pg_strcasecmp(prev5_wd, "ALTER") == 0 || + pg_strcasecmp(prev5_wd, "DROP") == 0) && + pg_strcasecmp(prev4_wd, "USER") == 0 && + pg_strcasecmp(prev3_wd, "MAPPING") == 0 && + pg_strcasecmp(prev2_wd, "FOR") == 0) + COMPLETE_WITH_CONST("SERVER"); + +/* + * VACUUM [ FULL | FREEZE ] [ VERBOSE ] [ table ] + * VACUUM [ FULL | FREEZE ] [ VERBOSE ] ANALYZE [ table [ (column [, ...] ) ] ] + */ + else if (pg_strcasecmp(prev_wd, "VACUUM") == 0) + COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm, + " UNION SELECT 'FULL'" + " UNION SELECT 'FREEZE'" + " UNION SELECT 'ANALYZE'" + " UNION SELECT 'VERBOSE'"); + else if (pg_strcasecmp(prev2_wd, "VACUUM") == 0 && + (pg_strcasecmp(prev_wd, "FULL") == 0 || + pg_strcasecmp(prev_wd, "FREEZE") == 0)) + COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm, + " UNION SELECT 'ANALYZE'" + " UNION SELECT 'VERBOSE'"); + else if (pg_strcasecmp(prev3_wd, "VACUUM") == 0 && + pg_strcasecmp(prev_wd, "ANALYZE") == 0 && + (pg_strcasecmp(prev2_wd, "FULL") == 0 || + pg_strcasecmp(prev2_wd, "FREEZE") == 0)) + COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm, + " UNION SELECT 'VERBOSE'"); + else if (pg_strcasecmp(prev3_wd, "VACUUM") == 0 && + pg_strcasecmp(prev_wd, "VERBOSE") == 0 && + (pg_strcasecmp(prev2_wd, "FULL") == 0 || + pg_strcasecmp(prev2_wd, "FREEZE") == 0)) + COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm, + " UNION SELECT 'ANALYZE'"); + else if (pg_strcasecmp(prev2_wd, "VACUUM") == 0 && + pg_strcasecmp(prev_wd, "VERBOSE") == 0) + COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm, + " UNION SELECT 'ANALYZE'"); + else if (pg_strcasecmp(prev2_wd, "VACUUM") == 0 && + pg_strcasecmp(prev_wd, "ANALYZE") == 0) + COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm, + " UNION SELECT 'VERBOSE'"); + else if ((pg_strcasecmp(prev_wd, "ANALYZE") == 0 && + pg_strcasecmp(prev2_wd, "VERBOSE") == 0) || + (pg_strcasecmp(prev_wd, "VERBOSE") == 0 && + pg_strcasecmp(prev2_wd, "ANALYZE") == 0)) + COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tm, NULL); + +/* WITH [RECURSIVE] */ + + /* + * Only match when WITH is the first word, as WITH may appear in many + * other contexts. + */ + else if (pg_strcasecmp(prev_wd, "WITH") == 0 && + prev2_wd[0] == '\0') + COMPLETE_WITH_CONST("RECURSIVE"); + +/* ANALYZE */ + /* If the previous word is ANALYZE, produce list of tables */ + else if (pg_strcasecmp(prev_wd, "ANALYZE") == 0) + COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tmf, NULL); + +/* WHERE */ + /* Simple case of the word before the where being the table name */ + else if (pg_strcasecmp(prev_wd, "WHERE") == 0) + COMPLETE_WITH_ATTR(prev2_wd, ""); + +/* ... FROM ... */ +/* TODO: also include SRF ? */ + else if (pg_strcasecmp(prev_wd, "FROM") == 0 && + pg_strcasecmp(prev3_wd, "COPY") != 0 && + pg_strcasecmp(prev3_wd, "\\copy") != 0) + COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tsvmf, NULL); + +/* ... JOIN ... */ + else if (pg_strcasecmp(prev_wd, "JOIN") == 0) + COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tsvmf, NULL); + +/* Backslash commands */ +/* TODO: \dc \dd \dl */ + else if (strcmp(prev_wd, "\\?") == 0) + { + static const char *const my_list[] = + {"commands", "options", "variables", NULL}; + + COMPLETE_WITH_LIST_CS(my_list); + } + else if (strcmp(prev_wd, "\\connect") == 0 || strcmp(prev_wd, "\\c") == 0) + { + if (!recognized_connection_string(text)) + COMPLETE_WITH_QUERY(Query_for_list_of_databases); + } + else if (strcmp(prev2_wd, "\\connect") == 0 || strcmp(prev2_wd, "\\c") == 0) + { + if (!recognized_connection_string(prev_wd)) + COMPLETE_WITH_QUERY(Query_for_list_of_roles); + } + else if (strncmp(prev_wd, "\\da", strlen("\\da")) == 0) + COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_aggregates, NULL); + else if (strncmp(prev_wd, "\\db", strlen("\\db")) == 0) + COMPLETE_WITH_QUERY(Query_for_list_of_tablespaces); + else if (strncmp(prev_wd, "\\dD", strlen("\\dD")) == 0) + COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_domains, NULL); + else if (strncmp(prev_wd, "\\des", strlen("\\des")) == 0) + COMPLETE_WITH_QUERY(Query_for_list_of_servers); + else if (strncmp(prev_wd, "\\deu", strlen("\\deu")) == 0) + COMPLETE_WITH_QUERY(Query_for_list_of_user_mappings); + else if (strncmp(prev_wd, "\\dew", strlen("\\dew")) == 0) + COMPLETE_WITH_QUERY(Query_for_list_of_fdws); + + else if (strncmp(prev_wd, "\\df", strlen("\\df")) == 0) + COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_functions, NULL); + else if (strncmp(prev_wd, "\\dFd", strlen("\\dFd")) == 0) + COMPLETE_WITH_QUERY(Query_for_list_of_ts_dictionaries); + else if (strncmp(prev_wd, "\\dFp", strlen("\\dFp")) == 0) + COMPLETE_WITH_QUERY(Query_for_list_of_ts_parsers); + else if (strncmp(prev_wd, "\\dFt", strlen("\\dFt")) == 0) + COMPLETE_WITH_QUERY(Query_for_list_of_ts_templates); + /* must be at end of \dF */ + else if (strncmp(prev_wd, "\\dF", strlen("\\dF")) == 0) + COMPLETE_WITH_QUERY(Query_for_list_of_ts_configurations); + + else if (strncmp(prev_wd, "\\di", strlen("\\di")) == 0) + COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_indexes, NULL); + else if (strncmp(prev_wd, "\\dL", strlen("\\dL")) == 0) + COMPLETE_WITH_QUERY(Query_for_list_of_languages); + else if (strncmp(prev_wd, "\\dn", strlen("\\dn")) == 0) + COMPLETE_WITH_QUERY(Query_for_list_of_schemas); + else if (strncmp(prev_wd, "\\dp", strlen("\\dp")) == 0 + || strncmp(prev_wd, "\\z", strlen("\\z")) == 0) + COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tsvmf, NULL); + else if (strncmp(prev_wd, "\\ds", strlen("\\ds")) == 0) + COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_sequences, NULL); + else if (strncmp(prev_wd, "\\dt", strlen("\\dt")) == 0) + COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL); + else if (strncmp(prev_wd, "\\dT", strlen("\\dT")) == 0) + COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_datatypes, NULL); + else if (strncmp(prev_wd, "\\du", strlen("\\du")) == 0 + || (strncmp(prev_wd, "\\dg", strlen("\\dg")) == 0)) + COMPLETE_WITH_QUERY(Query_for_list_of_roles); + else if (strncmp(prev_wd, "\\dv", strlen("\\dv")) == 0) + COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_views, NULL); + else if (strncmp(prev_wd, "\\dx", strlen("\\dx")) == 0) + COMPLETE_WITH_QUERY(Query_for_list_of_extensions); + else if (strncmp(prev_wd, "\\dm", strlen("\\dm")) == 0) + COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_matviews, NULL); + else if (strncmp(prev_wd, "\\dE", strlen("\\dE")) == 0) + COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_foreign_tables, NULL); + else if (strncmp(prev_wd, "\\dy", strlen("\\dy")) == 0) + COMPLETE_WITH_QUERY(Query_for_list_of_event_triggers); + + /* must be at end of \d list */ + else if (strncmp(prev_wd, "\\d", strlen("\\d")) == 0) + COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_relations, NULL); + + else if (strcmp(prev_wd, "\\ef") == 0) + COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_functions, NULL); + + else if (strcmp(prev_wd, "\\encoding") == 0) + COMPLETE_WITH_QUERY(Query_for_list_of_encodings); + else if (strcmp(prev_wd, "\\h") == 0 || strcmp(prev_wd, "\\help") == 0) + COMPLETE_WITH_LIST(sql_commands); + else if (strcmp(prev_wd, "\\password") == 0) + COMPLETE_WITH_QUERY(Query_for_list_of_roles); + else if (strcmp(prev_wd, "\\pset") == 0) + { + static const char *const my_list[] = + {"border", "columns", "expanded", "fieldsep", "fieldsep_zero", + "footer", "format", "linestyle", "null", "numericlocale", + "pager", "recordsep", "recordsep_zero", "tableattr", "title", + "tuples_only", "unicode_border_linestyle", + "unicode_column_linestyle", "unicode_header_linestyle", NULL}; + + COMPLETE_WITH_LIST_CS(my_list); + } + else if (strcmp(prev2_wd, "\\pset") == 0) + { + if (strcmp(prev_wd, "format") == 0) + { + static const char *const my_list[] = + {"unaligned", "aligned", "wrapped", "html", "asciidoc", + "latex", "latex-longtable", "troff-ms", NULL}; + + COMPLETE_WITH_LIST_CS(my_list); + } + else if (strcmp(prev_wd, "linestyle") == 0) + { + static const char *const my_list[] = + {"ascii", "old-ascii", "unicode", NULL}; + + COMPLETE_WITH_LIST_CS(my_list); + } + else if (strcmp(prev_wd, "unicode_border_linestyle") == 0 || + strcmp(prev_wd, "unicode_column_linestyle") == 0 || + strcmp(prev_wd, "unicode_header_linestyle") == 0) + { + static const char *const my_list[] = + {"single", "double", NULL}; + + COMPLETE_WITH_LIST_CS(my_list); + + } + } + else if (strcmp(prev_wd, "\\unset") == 0) + { + matches = complete_from_variables(text, "", "", true); + } + else if (strcmp(prev_wd, "\\set") == 0) + { + matches = complete_from_variables(text, "", "", false); + } + else if (strcmp(prev2_wd, "\\set") == 0) + { + static const char *const boolean_value_list[] = + {"on", "off", NULL}; + + if (strcmp(prev_wd, "AUTOCOMMIT") == 0) + COMPLETE_WITH_LIST_CS(boolean_value_list); + else if (strcmp(prev_wd, "COMP_KEYWORD_CASE") == 0) + { + static const char *const my_list[] = + {"lower", "upper", "preserve-lower", "preserve-upper", NULL}; + + COMPLETE_WITH_LIST_CS(my_list); + } + else if (strcmp(prev_wd, "ECHO") == 0) + { + static const char *const my_list[] = + {"errors", "queries", "all", "none", NULL}; + + COMPLETE_WITH_LIST_CS(my_list); + } + else if (strcmp(prev_wd, "ECHO_HIDDEN") == 0) + { + static const char *const my_list[] = + {"noexec", "off", "on", NULL}; + + COMPLETE_WITH_LIST_CS(my_list); + } + else if (strcmp(prev_wd, "HISTCONTROL") == 0) + { + static const char *const my_list[] = + {"ignorespace", "ignoredups", "ignoreboth", "none", NULL}; + + COMPLETE_WITH_LIST_CS(my_list); + } + else if (strcmp(prev_wd, "ON_ERROR_ROLLBACK") == 0) + { + static const char *const my_list[] = + {"on", "off", "interactive", NULL}; + + COMPLETE_WITH_LIST_CS(my_list); + } + else if (strcmp(prev_wd, "ON_ERROR_STOP") == 0) + COMPLETE_WITH_LIST_CS(boolean_value_list); + else if (strcmp(prev_wd, "QUIET") == 0) + COMPLETE_WITH_LIST_CS(boolean_value_list); + else if (strcmp(prev_wd, "SINGLELINE") == 0) + COMPLETE_WITH_LIST_CS(boolean_value_list); + else if (strcmp(prev_wd, "SINGLESTEP") == 0) + COMPLETE_WITH_LIST_CS(boolean_value_list); + else if (strcmp(prev_wd, "VERBOSITY") == 0) + { + static const char *const my_list[] = + {"default", "verbose", "terse", NULL}; + + COMPLETE_WITH_LIST_CS(my_list); + } + } + else if (strcmp(prev_wd, "\\sf") == 0 || strcmp(prev_wd, "\\sf+") == 0) + COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_functions, NULL); + else if (strcmp(prev_wd, "\\cd") == 0 || + strcmp(prev_wd, "\\e") == 0 || strcmp(prev_wd, "\\edit") == 0 || + strcmp(prev_wd, "\\g") == 0 || + strcmp(prev_wd, "\\i") == 0 || strcmp(prev_wd, "\\include") == 0 || + strcmp(prev_wd, "\\ir") == 0 || strcmp(prev_wd, "\\include_relative") == 0 || + strcmp(prev_wd, "\\o") == 0 || strcmp(prev_wd, "\\out") == 0 || + strcmp(prev_wd, "\\s") == 0 || + strcmp(prev_wd, "\\w") == 0 || strcmp(prev_wd, "\\write") == 0 || + strcmp(prev_wd, "\\lo_import") == 0 + ) + { + completion_charp = "\\"; + matches = completion_matches(text, complete_from_files); + } + + /* + * Finally, we look through the list of "things", such as TABLE, INDEX and + * check if that was the previous word. If so, execute the query to get a + * list of them. + */ + else + { + int i; + + for (i = 0; words_after_create[i].name; i++) + { + if (pg_strcasecmp(prev_wd, words_after_create[i].name) == 0) + { + if (words_after_create[i].query) + COMPLETE_WITH_QUERY(words_after_create[i].query); + else if (words_after_create[i].squery) + COMPLETE_WITH_SCHEMA_QUERY(*words_after_create[i].squery, + NULL); + break; + } + } + } + + /* + * If we still don't have anything to match we have to fabricate some sort + * of default list. If we were to just return NULL, readline automatically + * attempts filename completion, and that's usually no good. + */ + if (matches == NULL) + { + COMPLETE_WITH_CONST(""); +#ifdef HAVE_RL_COMPLETION_APPEND_CHARACTER + rl_completion_append_character = '\0'; +#endif + } + + /* free storage */ + { + int i; + + for (i = 0; i < lengthof(previous_words); i++) + free(previous_words[i]); + } + + /* Return our Grand List O' Matches */ + return matches; +} + + +/* + * GENERATOR FUNCTIONS + * + * These functions do all the actual work of completing the input. They get + * passed the text so far and the count how many times they have been called + * so far with the same text. + * If you read the above carefully, you'll see that these don't get called + * directly but through the readline interface. + * The return value is expected to be the full completion of the text, going + * through a list each time, or NULL if there are no more matches. The string + * will be free()'d by readline, so you must run it through strdup() or + * something of that sort. + */ + +/* + * Common routine for create_command_generator and drop_command_generator. + * Entries that have 'excluded' flags are not returned. + */ +static char * +create_or_drop_command_generator(const char *text, int state, bits32 excluded) +{ + static int list_index, + string_length; + const char *name; + + /* If this is the first time for this completion, init some values */ + if (state == 0) + { + list_index = 0; + string_length = strlen(text); + } + + /* find something that matches */ + while ((name = words_after_create[list_index++].name)) + { + if ((pg_strncasecmp(name, text, string_length) == 0) && + !(words_after_create[list_index - 1].flags & excluded)) + return pg_strdup_keyword_case(name, text); + } + /* if nothing matches, return NULL */ + return NULL; +} + +/* + * This one gives you one from a list of things you can put after CREATE + * as defined above. + */ +static char * +create_command_generator(const char *text, int state) +{ + return create_or_drop_command_generator(text, state, THING_NO_CREATE); +} + +/* + * This function gives you a list of things you can put after a DROP command. + */ +static char * +drop_command_generator(const char *text, int state) +{ + return create_or_drop_command_generator(text, state, THING_NO_DROP); +} + +/* The following two functions are wrappers for _complete_from_query */ + +static char * +complete_from_query(const char *text, int state) +{ + return _complete_from_query(0, text, state); +} + +static char * +complete_from_schema_query(const char *text, int state) +{ + return _complete_from_query(1, text, state); +} + + +/* + * This creates a list of matching things, according to a query pointed to + * by completion_charp. + * The query can be one of two kinds: + * + * 1. A simple query which must contain a %d and a %s, which will be replaced + * by the string length of the text and the text itself. The query may also + * have up to four more %s in it; the first two such will be replaced by the + * value of completion_info_charp, the next two by the value of + * completion_info_charp2. + * + * 2. A schema query used for completion of both schema and relation names. + * These are more complex and must contain in the following order: + * %d %s %d %s %d %s %s %d %s + * where %d is the string length of the text and %s the text itself. + * + * It is assumed that strings should be escaped to become SQL literals + * (that is, what is in the query is actually ... '%s' ...) + * + * See top of file for examples of both kinds of query. + */ +static char * +_complete_from_query(int is_schema_query, const char *text, int state) +{ + static int list_index, + string_length; + static PGresult *result = NULL; + + /* + * If this is the first time for this completion, we fetch a list of our + * "things" from the backend. + */ + if (state == 0) + { + PQExpBufferData query_buffer; + char *e_text; + char *e_info_charp; + char *e_info_charp2; + + list_index = 0; + string_length = strlen(text); + + /* Free any prior result */ + PQclear(result); + result = NULL; + + /* Set up suitably-escaped copies of textual inputs */ + e_text = pg_malloc(string_length * 2 + 1); + PQescapeString(e_text, text, string_length); + + if (completion_info_charp) + { + size_t charp_len; + + charp_len = strlen(completion_info_charp); + e_info_charp = pg_malloc(charp_len * 2 + 1); + PQescapeString(e_info_charp, completion_info_charp, + charp_len); + } + else + e_info_charp = NULL; + + if (completion_info_charp2) + { + size_t charp_len; + + charp_len = strlen(completion_info_charp2); + e_info_charp2 = pg_malloc(charp_len * 2 + 1); + PQescapeString(e_info_charp2, completion_info_charp2, + charp_len); + } + else + e_info_charp2 = NULL; + + initPQExpBuffer(&query_buffer); + + if (is_schema_query) + { + /* completion_squery gives us the pieces to assemble */ + const char *qualresult = completion_squery->qualresult; + + if (qualresult == NULL) + qualresult = completion_squery->result; + + /* Get unqualified names matching the input-so-far */ + appendPQExpBuffer(&query_buffer, "SELECT %s FROM %s WHERE ", + completion_squery->result, + completion_squery->catname); + if (completion_squery->selcondition) + appendPQExpBuffer(&query_buffer, "%s AND ", + completion_squery->selcondition); + appendPQExpBuffer(&query_buffer, "substring(%s,1,%d)='%s'", + completion_squery->result, + string_length, e_text); + appendPQExpBuffer(&query_buffer, " AND %s", + completion_squery->viscondition); + + /* + * When fetching relation names, suppress system catalogs unless + * the input-so-far begins with "pg_". This is a compromise + * between not offering system catalogs for completion at all, and + * having them swamp the result when the input is just "p". + */ + if (strcmp(completion_squery->catname, + "pg_catalog.pg_class c") == 0 && + strncmp(text, "pg_", 3) !=0) + { + appendPQExpBufferStr(&query_buffer, + " AND c.relnamespace <> (SELECT oid FROM" + " pg_catalog.pg_namespace WHERE nspname = 'pg_catalog')"); + } + + /* + * Add in matching schema names, but only if there is more than + * one potential match among schema names. + */ + appendPQExpBuffer(&query_buffer, "\nUNION\n" + "SELECT pg_catalog.quote_ident(n.nspname) || '.' " + "FROM pg_catalog.pg_namespace n " + "WHERE substring(pg_catalog.quote_ident(n.nspname) || '.',1,%d)='%s'", + string_length, e_text); + appendPQExpBuffer(&query_buffer, + " AND (SELECT pg_catalog.count(*)" + " FROM pg_catalog.pg_namespace" + " WHERE substring(pg_catalog.quote_ident(nspname) || '.',1,%d) =" + " substring('%s',1,pg_catalog.length(pg_catalog.quote_ident(nspname))+1)) > 1", + string_length, e_text); + + /* + * Add in matching qualified names, but only if there is exactly + * one schema matching the input-so-far. + */ + appendPQExpBuffer(&query_buffer, "\nUNION\n" + "SELECT pg_catalog.quote_ident(n.nspname) || '.' || %s " + "FROM %s, pg_catalog.pg_namespace n " + "WHERE %s = n.oid AND ", + qualresult, + completion_squery->catname, + completion_squery->namespace); + if (completion_squery->selcondition) + appendPQExpBuffer(&query_buffer, "%s AND ", + completion_squery->selcondition); + appendPQExpBuffer(&query_buffer, "substring(pg_catalog.quote_ident(n.nspname) || '.' || %s,1,%d)='%s'", + qualresult, + string_length, e_text); + + /* + * This condition exploits the single-matching-schema rule to + * speed up the query + */ + appendPQExpBuffer(&query_buffer, + " AND substring(pg_catalog.quote_ident(n.nspname) || '.',1,%d) =" + " substring('%s',1,pg_catalog.length(pg_catalog.quote_ident(n.nspname))+1)", + string_length, e_text); + appendPQExpBuffer(&query_buffer, + " AND (SELECT pg_catalog.count(*)" + " FROM pg_catalog.pg_namespace" + " WHERE substring(pg_catalog.quote_ident(nspname) || '.',1,%d) =" + " substring('%s',1,pg_catalog.length(pg_catalog.quote_ident(nspname))+1)) = 1", + string_length, e_text); + + /* If an addon query was provided, use it */ + if (completion_charp) + appendPQExpBuffer(&query_buffer, "\n%s", completion_charp); + } + else + { + /* completion_charp is an sprintf-style format string */ + appendPQExpBuffer(&query_buffer, completion_charp, + string_length, e_text, + e_info_charp, e_info_charp, + e_info_charp2, e_info_charp2); + } + + /* Limit the number of records in the result */ + appendPQExpBuffer(&query_buffer, "\nLIMIT %d", + completion_max_records); + + result = exec_query(query_buffer.data); + + termPQExpBuffer(&query_buffer); + free(e_text); + if (e_info_charp) + free(e_info_charp); + if (e_info_charp2) + free(e_info_charp2); + } + + /* Find something that matches */ + if (result && PQresultStatus(result) == PGRES_TUPLES_OK) + { + const char *item; + + while (list_index < PQntuples(result) && + (item = PQgetvalue(result, list_index++, 0))) + if (pg_strncasecmp(text, item, string_length) == 0) + return pg_strdup(item); + } + + /* If nothing matches, free the db structure and return null */ + PQclear(result); + result = NULL; + return NULL; +} + + +/* + * This function returns in order one of a fixed, NULL pointer terminated list + * of strings (if matching). This can be used if there are only a fixed number + * SQL words that can appear at certain spot. + */ +static char * +complete_from_list(const char *text, int state) +{ + static int string_length, + list_index, + matches; + static bool casesensitive; + const char *item; + + /* need to have a list */ + Assert(completion_charpp != NULL); + + /* Initialization */ + if (state == 0) + { + list_index = 0; + string_length = strlen(text); + casesensitive = completion_case_sensitive; + matches = 0; + } + + while ((item = completion_charpp[list_index++])) + { + /* First pass is case sensitive */ + if (casesensitive && strncmp(text, item, string_length) == 0) + { + matches++; + return pg_strdup(item); + } + + /* Second pass is case insensitive, don't bother counting matches */ + if (!casesensitive && pg_strncasecmp(text, item, string_length) == 0) + { + if (completion_case_sensitive) + return pg_strdup(item); + else + + /* + * If case insensitive matching was requested initially, + * adjust the case according to setting. + */ + return pg_strdup_keyword_case(item, text); + } + } + + /* + * No matches found. If we're not case insensitive already, lets switch to + * being case insensitive and try again + */ + if (casesensitive && matches == 0) + { + casesensitive = false; + list_index = 0; + state++; + return complete_from_list(text, state); + } + + /* If no more matches, return null. */ + return NULL; +} + + +/* + * This function returns one fixed string the first time even if it doesn't + * match what's there, and nothing the second time. This should be used if + * there is only one possibility that can appear at a certain spot, so + * misspellings will be overwritten. The string to be passed must be in + * completion_charp. + */ +static char * +complete_from_const(const char *text, int state) +{ + Assert(completion_charp != NULL); + if (state == 0) + { + if (completion_case_sensitive) + return pg_strdup(completion_charp); + else + + /* + * If case insensitive matching was requested initially, adjust + * the case according to setting. + */ + return pg_strdup_keyword_case(completion_charp, text); + } + else + return NULL; +} + + +/* + * This function appends the variable name with prefix and suffix to + * the variable names array. + */ +static void +append_variable_names(char ***varnames, int *nvars, + int *maxvars, const char *varname, + const char *prefix, const char *suffix) +{ + if (*nvars >= *maxvars) + { + *maxvars *= 2; + *varnames = (char **) pg_realloc(*varnames, + ((*maxvars) + 1) * sizeof(char *)); + } + + (*varnames)[(*nvars)++] = psprintf("%s%s%s", prefix, varname, suffix); +} + + +/* + * This function supports completion with the name of a psql variable. + * The variable names can be prefixed and suffixed with additional text + * to support quoting usages. If need_value is true, only the variables + * that have the set values are picked up. + */ +static char ** +complete_from_variables(const char *text, const char *prefix, const char *suffix, + bool need_value) +{ + char **matches; + char **varnames; + int nvars = 0; + int maxvars = 100; + int i; + struct _variable *ptr; + + static const char *const known_varnames[] = { + "AUTOCOMMIT", "COMP_KEYWORD_CASE", "DBNAME", "ECHO", "ECHO_HIDDEN", + "ENCODING", "FETCH_COUNT", "HISTCONTROL", "HISTFILE", "HISTSIZE", + "HOST", "IGNOREEOF", "LASTOID", "ON_ERROR_ROLLBACK", "ON_ERROR_STOP", + "PORT", "PROMPT1", "PROMPT2", "PROMPT3", "QUIET", "SINGLELINE", + "SINGLESTEP", "USER", "VERBOSITY", NULL + }; + + varnames = (char **) pg_malloc((maxvars + 1) * sizeof(char *)); + + if (!need_value) + { + for (i = 0; known_varnames[i] && nvars < maxvars; i++) + append_variable_names(&varnames, &nvars, &maxvars, + known_varnames[i], prefix, suffix); + } + + for (ptr = pset.vars->next; ptr; ptr = ptr->next) + { + if (need_value && !(ptr->value)) + continue; + for (i = 0; known_varnames[i]; i++) /* remove duplicate entry */ + { + if (strcmp(ptr->name, known_varnames[i]) == 0) + continue; + } + append_variable_names(&varnames, &nvars, &maxvars, ptr->name, + prefix, suffix); + } + + varnames[nvars] = NULL; + COMPLETE_WITH_LIST_CS((const char *const *) varnames); + + for (i = 0; i < nvars; i++) + free(varnames[i]); + free(varnames); + + return matches; +} + + +/* + * This function wraps rl_filename_completion_function() to strip quotes from + * the input before searching for matches and to quote any matches for which + * the consuming command will require it. + */ +static char * +complete_from_files(const char *text, int state) +{ + static const char *unquoted_text; + char *unquoted_match; + char *ret = NULL; + + if (state == 0) + { + /* Initialization: stash the unquoted input. */ + unquoted_text = strtokx(text, "", NULL, "'", *completion_charp, + false, true, pset.encoding); + /* expect a NULL return for the empty string only */ + if (!unquoted_text) + { + Assert(*text == '\0'); + unquoted_text = text; + } + } + + unquoted_match = filename_completion_function(unquoted_text, state); + if (unquoted_match) + { + /* + * Caller sets completion_charp to a zero- or one-character string + * containing the escape character. This is necessary since \copy has + * no escape character, but every other backslash command recognizes + * "\" as an escape character. Since we have only two callers, don't + * bother providing a macro to simplify this. + */ + ret = quote_if_needed(unquoted_match, " \t\r\n\"`", + '\'', *completion_charp, pset.encoding); + if (ret) + free(unquoted_match); + else + ret = unquoted_match; + } + + return ret; +} + + +/* HELPER FUNCTIONS */ + + +/* + * Make a pg_strdup copy of s and convert the case according to + * COMP_KEYWORD_CASE setting, using ref as the text that was already entered. + */ +static char * +pg_strdup_keyword_case(const char *s, const char *ref) +{ + char *ret, + *p; + unsigned char first = ref[0]; + + ret = pg_strdup(s); + + if (pset.comp_case == PSQL_COMP_CASE_LOWER || + ((pset.comp_case == PSQL_COMP_CASE_PRESERVE_LOWER || + pset.comp_case == PSQL_COMP_CASE_PRESERVE_UPPER) && islower(first)) || + (pset.comp_case == PSQL_COMP_CASE_PRESERVE_LOWER && !isalpha(first))) + { + for (p = ret; *p; p++) + *p = pg_tolower((unsigned char) *p); + } + else + { + for (p = ret; *p; p++) + *p = pg_toupper((unsigned char) *p); + } + + return ret; +} + + +/* + * Execute a query and report any errors. This should be the preferred way of + * talking to the database in this file. + */ +static PGresult * +exec_query(const char *query) +{ + PGresult *result; + + if (query == NULL || !pset.db || PQstatus(pset.db) != CONNECTION_OK) + return NULL; + + result = PQexec(pset.db, query); + + if (PQresultStatus(result) != PGRES_TUPLES_OK) + { +#ifdef NOT_USED + psql_error("tab completion query failed: %s\nQuery was:\n%s\n", + PQerrorMessage(pset.db), query); +#endif + PQclear(result); + result = NULL; + } + + return result; +} + + +/* + * Return the nwords word(s) before point. Words are returned right to left, + * that is, previous_words[0] gets the last word before point. + * If we run out of words, remaining array elements are set to empty strings. + * Each array element is filled with a malloc'd string. + */ +static void +get_previous_words(int point, char **previous_words, int nwords) +{ + const char *buf = rl_line_buffer; /* alias */ + int i; + + /* first we look for a non-word char before the current point */ + for (i = point - 1; i >= 0; i--) + if (strchr(WORD_BREAKS, buf[i])) + break; + point = i; + + while (nwords-- > 0) + { + int start, + end; + char *s; + + /* now find the first non-space which then constitutes the end */ + end = -1; + for (i = point; i >= 0; i--) + { + if (!isspace((unsigned char) buf[i])) + { + end = i; + break; + } + } + + /* + * If no end found we return an empty string, because there is no word + * before the point + */ + if (end < 0) + { + point = end; + s = pg_strdup(""); + } + else + { + /* + * Otherwise we now look for the start. The start is either the + * last character before any word-break character going backwards + * from the end, or it's simply character 0. We also handle open + * quotes and parentheses. + */ + bool inquotes = false; + int parentheses = 0; + + for (start = end; start > 0; start--) + { + if (buf[start] == '"') + inquotes = !inquotes; + if (!inquotes) + { + if (buf[start] == ')') + parentheses++; + else if (buf[start] == '(') + { + if (--parentheses <= 0) + break; + } + else if (parentheses == 0 && + strchr(WORD_BREAKS, buf[start - 1])) + break; + } + } + + point = start - 1; + + /* make a copy of chars from start to end inclusive */ + s = pg_malloc(end - start + 2); + strlcpy(s, &buf[start], end - start + 2); + } + + *previous_words++ = s; + } +} + +#ifdef NOT_USED + +/* + * Surround a string with single quotes. This works for both SQL and + * psql internal. Currently disabled because it is reported not to + * cooperate with certain versions of readline. + */ +static char * +quote_file_name(char *text, int match_type, char *quote_pointer) +{ + char *s; + size_t length; + + (void) quote_pointer; /* not used */ + + length = strlen(text) +(match_type == SINGLE_MATCH ? 3 : 2); + s = pg_malloc(length); + s[0] = '\''; + strcpy(s + 1, text); + if (match_type == SINGLE_MATCH) + s[length - 2] = '\''; + s[length - 1] = '\0'; + return s; +} + +static char * +dequote_file_name(char *text, char quote_char) +{ + char *s; + size_t length; + + if (!quote_char) + return pg_strdup(text); + + length = strlen(text); + s = pg_malloc(length - 2 + 1); + strlcpy(s, text +1, length - 2 + 1); + + return s; +} +#endif /* NOT_USED */ + +#endif /* USE_READLINE */ diff --git a/src/bin/csql/tab-complete.h b/src/bin/csql/tab-complete.h new file mode 100644 index 000000000..9dcd7e742 --- /dev/null +++ b/src/bin/csql/tab-complete.h @@ -0,0 +1,15 @@ +/* + * psql - the PostgreSQL interactive terminal + * + * Copyright (c) 2000-2015, PostgreSQL Global Development Group + * + * src/bin/psql/tab-complete.h + */ +#ifndef TAB_COMPLETE_H +#define TAB_COMPLETE_H + +#include "postgres_fe.h" + +void initialize_readline(void); + +#endif diff --git a/src/bin/csql/variables.c b/src/bin/csql/variables.c new file mode 100644 index 000000000..b9a3dfad3 --- /dev/null +++ b/src/bin/csql/variables.c @@ -0,0 +1,305 @@ +/* + * psql - the PostgreSQL interactive terminal + * + * Copyright (c) 2000-2015, PostgreSQL Global Development Group + * + * src/bin/psql/variables.c + */ +#include "postgres_fe.h" + +#include "common.h" +#include "variables.h" + + +/* + * Check whether a variable's name is allowed. + * + * We allow any non-ASCII character, as well as ASCII letters, digits, and + * underscore. Keep this in sync with the definition of variable_char in + * psqlscan.l. + */ +static bool +valid_variable_name(const char *name) +{ + const unsigned char *ptr = (const unsigned char *) name; + + /* Mustn't be zero-length */ + if (*ptr == '\0') + return false; + + while (*ptr) + { + if (IS_HIGHBIT_SET(*ptr) || + strchr("ABCDEFGHIJKLMNOPQRSTUVWXYZ" "abcdefghijklmnopqrstuvwxyz" + "_0123456789", *ptr) != NULL) + ptr++; + else + return false; + } + + return true; +} + +/* + * A "variable space" is represented by an otherwise-unused struct _variable + * that serves as list header. + */ +VariableSpace +CreateVariableSpace(void) +{ + struct _variable *ptr; + + ptr = pg_malloc(sizeof *ptr); + ptr->name = NULL; + ptr->value = NULL; + ptr->assign_hook = NULL; + ptr->next = NULL; + + return ptr; +} + +const char * +GetVariable(VariableSpace space, const char *name) +{ + struct _variable *current; + + if (!space) + return NULL; + + for (current = space->next; current; current = current->next) + { + if (strcmp(current->name, name) == 0) + { + /* this is correct answer when value is NULL, too */ + return current->value; + } + } + + return NULL; +} + +/* + * Try to interpret "value" as boolean value. + * + * Valid values are: true, false, yes, no, on, off, 1, 0; as well as unique + * prefixes thereof. + * + * "name" is the name of the variable we're assigning to, to use in error + * report if any. Pass name == NULL to suppress the error report. + */ +bool +ParseVariableBool(const char *value, const char *name) +{ + size_t len; + + if (value == NULL) + return false; /* not set -> assume "off" */ + + len = strlen(value); + + if (pg_strncasecmp(value, "true", len) == 0) + return true; + else if (pg_strncasecmp(value, "false", len) == 0) + return false; + else if (pg_strncasecmp(value, "yes", len) == 0) + return true; + else if (pg_strncasecmp(value, "no", len) == 0) + return false; + /* 'o' is not unique enough */ + else if (pg_strncasecmp(value, "on", (len > 2 ? len : 2)) == 0) + return true; + else if (pg_strncasecmp(value, "off", (len > 2 ? len : 2)) == 0) + return false; + else if (pg_strcasecmp(value, "1") == 0) + return true; + else if (pg_strcasecmp(value, "0") == 0) + return false; + else + { + /* NULL is treated as false, so a non-matching value is 'true' */ + if (name) + psql_error("unrecognized value \"%s\" for \"%s\"; assuming \"%s\"\n", + value, name, "on"); + return true; + } +} + + +/* + * Read numeric variable, or defaultval if it is not set, or faultval if its + * value is not a valid numeric string. If allowtrail is false, this will + * include the case where there are trailing characters after the number. + */ +int +ParseVariableNum(const char *val, + int defaultval, + int faultval, + bool allowtrail) +{ + int result; + + if (!val) + result = defaultval; + else if (!val[0]) + result = faultval; + else + { + char *end; + + result = strtol(val, &end, 0); + if (!allowtrail && *end) + result = faultval; + } + + return result; +} + +int +GetVariableNum(VariableSpace space, + const char *name, + int defaultval, + int faultval, + bool allowtrail) +{ + const char *val; + + val = GetVariable(space, name); + return ParseVariableNum(val, defaultval, faultval, allowtrail); +} + +void +PrintVariables(VariableSpace space) +{ + struct _variable *ptr; + + if (!space) + return; + + for (ptr = space->next; ptr; ptr = ptr->next) + { + if (ptr->value) + printf("%s = '%s'\n", ptr->name, ptr->value); + if (cancel_pressed) + break; + } +} + +bool +SetVariable(VariableSpace space, const char *name, const char *value) +{ + struct _variable *current, + *previous; + + if (!space) + return false; + + if (!valid_variable_name(name)) + return false; + + if (!value) + return DeleteVariable(space, name); + + for (previous = space, current = space->next; + current; + previous = current, current = current->next) + { + if (strcmp(current->name, name) == 0) + { + /* found entry, so update */ + if (current->value) + free(current->value); + current->value = pg_strdup(value); + if (current->assign_hook) + (*current->assign_hook) (current->value); + return true; + } + } + + /* not present, make new entry */ + current = pg_malloc(sizeof *current); + current->name = pg_strdup(name); + current->value = pg_strdup(value); + current->assign_hook = NULL; + current->next = NULL; + previous->next = current; + return true; +} + +/* + * This both sets a hook function, and calls it on the current value (if any) + */ +bool +SetVariableAssignHook(VariableSpace space, const char *name, VariableAssignHook hook) +{ + struct _variable *current, + *previous; + + if (!space) + return false; + + if (!valid_variable_name(name)) + return false; + + for (previous = space, current = space->next; + current; + previous = current, current = current->next) + { + if (strcmp(current->name, name) == 0) + { + /* found entry, so update */ + current->assign_hook = hook; + (*hook) (current->value); + return true; + } + } + + /* not present, make new entry */ + current = pg_malloc(sizeof *current); + current->name = pg_strdup(name); + current->value = NULL; + current->assign_hook = hook; + current->next = NULL; + previous->next = current; + (*hook) (NULL); + return true; +} + +bool +SetVariableBool(VariableSpace space, const char *name) +{ + return SetVariable(space, name, "on"); +} + +bool +DeleteVariable(VariableSpace space, const char *name) +{ + struct _variable *current, + *previous; + + if (!space) + return false; + + for (previous = space, current = space->next; + current; + previous = current, current = current->next) + { + if (strcmp(current->name, name) == 0) + { + if (current->value) + free(current->value); + current->value = NULL; + /* Physically delete only if no hook function to remember */ + if (current->assign_hook) + (*current->assign_hook) (NULL); + else + { + previous->next = current->next; + free(current->name); + free(current); + } + return true; + } + } + + return true; +} diff --git a/src/bin/csql/variables.h b/src/bin/csql/variables.h new file mode 100644 index 000000000..c071846d9 --- /dev/null +++ b/src/bin/csql/variables.h @@ -0,0 +1,56 @@ +/* + * psql - the PostgreSQL interactive terminal + * + * Copyright (c) 2000-2015, PostgreSQL Global Development Group + * + * src/bin/psql/variables.h + */ +#ifndef VARIABLES_H +#define VARIABLES_H + +/* + * This implements a sort of variable repository. One could also think of it + * as a cheap version of an associative array. In each one of these + * datastructures you can store name/value pairs. There can also be an + * "assign hook" function that is called whenever the variable's value is + * changed. + * + * An "unset" operation causes the hook to be called with newval == NULL. + * + * Note: if value == NULL then the variable is logically unset, but we are + * keeping the struct around so as not to forget about its hook function. + */ +typedef void (*VariableAssignHook) (const char *newval); + +struct _variable +{ + char *name; + char *value; + VariableAssignHook assign_hook; + struct _variable *next; +}; + +typedef struct _variable *VariableSpace; + +VariableSpace CreateVariableSpace(void); +const char *GetVariable(VariableSpace space, const char *name); + +bool ParseVariableBool(const char *value, const char *name); +int ParseVariableNum(const char *val, + int defaultval, + int faultval, + bool allowtrail); +int GetVariableNum(VariableSpace space, + const char *name, + int defaultval, + int faultval, + bool allowtrail); + +void PrintVariables(VariableSpace space); + +bool SetVariable(VariableSpace space, const char *name, const char *value); +bool SetVariableAssignHook(VariableSpace space, const char *name, VariableAssignHook hook); +bool SetVariableBool(VariableSpace space, const char *name); +bool DeleteVariable(VariableSpace space, const char *name); + +#endif /* VARIABLES_H */ diff --git a/src/bin/scripts/copy_to_distributed_table b/src/bin/scripts/copy_to_distributed_table new file mode 100755 index 000000000..8e81c345b --- /dev/null +++ b/src/bin/scripts/copy_to_distributed_table @@ -0,0 +1,169 @@ +#!/usr/bin/env bash + +# make bash behave +set -euo pipefail +IFS=$'\n\t' + +# constants +stdout=1 +stderr=2 +success=0 +badusage=64 +noinput=66 + +# default values for certain options +format='text' +schema='public' + +# we'll append to this string to build options list +options='OIDS false, FREEZE false' + +# outputs usage message on specified device before exiting with provided status +usage() { + cat << 'E_O_USAGE' >&"$1" +usage: copy_to_distributed_table [-BCTHh] [-c encoding] [-d delimiter] + [-e escape] [-n null] [-q quote] [-s schema] filename tablename + + B : use binary format for input + C : use CSV format for input + T : use text format for input + H : specifies file contains header line to be ignored + h : print this help message + + c : specifies file is encoded using `encoding` + Default: the current client encoding + d : specifies the character used to separate columns + Default: a tab character in text format, a comma in CSV format + e : specifies the character used to escape quotes + Default: the same as the `quote` value (quotes within data are doubled) + n : specifies the string that represents a null value + Default: \N in text format, an unquoted empty string in CSV format + q : specifies the quoting character to be used when a data value is quoted + Default: double-quote + s : specifies the schema in which the target table resides + Default: 'public' + +copy_to_distributed_table outputs the total number of rows successfully copied +to the distributed table, counted from the beginning of the input file. +E_O_USAGE + + exit $2; +} + +# process flags +while getopts ':BCc:d:e:Hhn:q:s:T' o; do + case "${o}" in + B) + format='binary' + ;; + C) + format='csv' + ;; + c) + encoding=`echo ${OPTARG} | sed s/\'/\'\'/g` + options="${options}, ENCODING '${encoding}'" + ;; + d) + delimiter=`echo ${OPTARG} | sed s/\'/\'\'/g` + options="${options}, DELIMITER '${delimiter}'" + ;; + e) + escape=`echo ${OPTARG} | sed s/\'/\'\'/g` + options="${options}, ESCAPE '${escape}'" + ;; + H) + options="${options}, HEADER true" + ;; + h) + usage $stdout $success + ;; + n) + null=`echo ${OPTARG} | sed s/\'/\'\'/g` + options="${options}, NULL '${null}'" + ;; + q) + quote=`echo ${OPTARG} | sed s/\'/\'\'/g` + options="${options}, QUOTE '${quote}'" + ;; + s) + # we'll escape schema in psql itself + schema=${OPTARG} + ;; + T) + format='text' + ;; + *) + echo "$0: illegal option -- ${OPTARG}" >&2 + usage $stderr $badusage + ;; + esac +done +shift $((OPTIND-1)) + +if [ "$#" -ne 2 ]; then + usage $stderr $badusage +fi + +# append format to options and extract file/table names +options="${options}, FORMAT ${format}" +filename=$1 +tablename=$2 + +# validate inputs +if [ -d "${filename}" ]; then + echo "$0: ${filename}: Is a directory" >&2 + exit $noinput +elif [ ! -e "${filename}" ]; then + echo "$0: ${filename}: No such file" >&2 + exit $noinput +elif [ ! -r "${filename}" ]; then + echo "$0: ${filename}: Permission denied" >&2 + exit $noinput +fi + +# invoke psql, ignoring .psqlrc and passing the following heredoc +psql -X -vtable="${tablename}" -vfile="${filename}" \ + -vschema="${schema}" -voptions="${options}" << 'E_O_SQL' +-- only print values, left-align them, and don't rollback or stop on error +\set QUIET on +\set ON_ERROR_ROLLBACK off +\pset format unaligned +\pset tuples_only on +\set ON_ERROR_STOP on + +-- squelch all output until COPY completes +\o /dev/null + +-- Use a session-bound counter to keep track of the number of rows inserted: we +-- can't roll back so we need to tell the user how many rows were inserted. Due +-- to the trigger implementation, the COPY will report zero rows, so we count +-- them manually for a better experience. +CREATE TEMPORARY SEQUENCE rows_inserted MINVALUE 0 CACHE 100000; + +-- initialize counter to zero +SELECT nextval('rows_inserted'); + +-- get qualified table name +SELECT format('%I.%I', :'schema', :'table') AS target +\gset + +-- create insert proxy and save name; pass in sequence +SELECT create_insert_proxy_for_table(:'target', 'rows_inserted') AS proxy +\gset + +-- don't stop if copy errors out: continue to print file name and row count +\set ON_ERROR_STOP off + +-- \copy doesn't allow variable substitution, so do it ourselves... +SELECT format('\copy pg_temp.%I from %L with (%s)', + :'proxy', :'file', :'options') AS copy_cmd +\gset + +-- ... then execute the result +:copy_cmd + +-- reconnect STDOUT to display row count +\o + +SELECT currval('rows_inserted'); +E_O_SQL diff --git a/src/include/.gitignore b/src/include/.gitignore new file mode 100644 index 000000000..30f297ab7 --- /dev/null +++ b/src/include/.gitignore @@ -0,0 +1,4 @@ +/stamp-h +/stamp-ext-h +/citusdb_config.h +/citusdb_config.h.in~ diff --git a/src/include/citusdb_config.h.in b/src/include/citusdb_config.h.in new file mode 100644 index 000000000..61ced741c --- /dev/null +++ b/src/include/citusdb_config.h.in @@ -0,0 +1,29 @@ +/* src/include/citusdb_config.h.in. Generated from configure.in by autoheader. */ + + +/* + * citusdb_config.h.in is generated by autoconf/autoheader and + * converted into citusdb_config.h by configure. Include when code needs to + * depend on determinations made by configure. + * + * Do not manually edit! + */ + + +/* Define to the address where bug reports for this package should be sent. */ +#undef PACKAGE_BUGREPORT + +/* Define to the full name of this package. */ +#undef PACKAGE_NAME + +/* Define to the full name and version of this package. */ +#undef PACKAGE_STRING + +/* Define to the one symbol short name of this package. */ +#undef PACKAGE_TARNAME + +/* Define to the home page for this package. */ +#undef PACKAGE_URL + +/* Define to the version of this package. */ +#undef PACKAGE_VERSION diff --git a/src/include/distributed/citus_nodefuncs.h b/src/include/distributed/citus_nodefuncs.h new file mode 100644 index 000000000..cd273d587 --- /dev/null +++ b/src/include/distributed/citus_nodefuncs.h @@ -0,0 +1,42 @@ +/*------------------------------------------------------------------------- + * + * citus_nodefuncs.h + * Node (de-)serialization support for CitusDB. + * + * Copyright (c) 2012-2015, Citus Data, Inc. + * + *------------------------------------------------------------------------- + */ + +#ifndef CITUS_NODEFUNCS_H +#define CITUS_NODEFUNCS_H + +#include "distributed/multi_physical_planner.h" +#include "nodes/nodes.h" +#include "nodes/parsenodes.h" + +/* citus_nodefuncs.c */ +extern void SetRangeTblExtraData(RangeTblEntry *rte, CitusRTEKind rteKind, + char *fragmentSchemaName, char *fragmentTableName, + List *tableIdList); +extern void ModifyRangeTblExtraData(RangeTblEntry *rte, CitusRTEKind rteKind, + char *fragmentSchemaName, char *fragmentTableName, + List *tableIdList); +extern void ExtractRangeTblExtraData(RangeTblEntry *rte, CitusRTEKind *rteKind, + char **fragmentSchemaName, char **fragmentTableName, + List **tableIdList); +extern CitusRTEKind GetRangeTblKind(RangeTblEntry *rte); + +/* citus_outfuncs.c */ +extern char * CitusNodeToString(const void *obj); + +/* citus_read.c */ +extern void * CitusStringToNode(char *str); +extern char * citus_pg_strtok(int *length); +extern void * CitusNodeRead(char *token, int tok_len); + +/* citus_readfuncs.c */ +extern Node * CitusParseNodeString(void); + + +#endif /* CITUS_NODEFUNCS_H */ diff --git a/src/include/distributed/citus_nodes.h b/src/include/distributed/citus_nodes.h new file mode 100644 index 000000000..05a536cf0 --- /dev/null +++ b/src/include/distributed/citus_nodes.h @@ -0,0 +1,73 @@ +/*------------------------------------------------------------------------- + * + * citus_nodes.h + * Additional node types, and related infrastructure, for CitusDB. + * + * Copyright (c) 2012-2015, Citus Data, Inc. + * + *------------------------------------------------------------------------- + */ + +#ifndef CITUS_NODES_H +#define CITUS_NODES_H + + +/* + * Citus Node Tags + * + * These have to be distinct from the ideas used in postgres' nodes.h + */ +typedef enum CitusNodeTag +{ + T_MultiNode = 1200, /* FIXME: perhaps use something less predicable? */ + T_MultiTreeRoot, + T_MultiProject, + T_MultiCollect, + T_MultiSelect, + T_MultiTable, + T_MultiJoin, + T_MultiPartition, + T_MultiCartesianProduct, + T_MultiExtendedOp, + T_Job, + T_MapMergeJob, + T_MultiPlan, + T_Task, + T_ShardInterval, + T_ShardPlacement +} CitusNodeTag; + + +/* + * nodeTag equivalent that returns the node tag for both citus and postgres + * node tag types. Needs to return int as there's no type that covers both + * postgres and citus node values. + */ +#define CitusNodeTag(nodeptr) (*((const int*)(nodeptr))) + + +/* + * IsA equivalent that compares node tags as integers, not as enum values. + */ +#define CitusIsA(nodeptr,_type_) (CitusNodeTag(nodeptr) == T_##_type_) + + +/* CitusDB variant of newNode(), don't use directly. */ +#define CitusNewNode(size, tag) \ +({ Node *_result; \ + AssertMacro((size) >= sizeof(Node)); /* need the tag, at least */ \ + _result = (Node *) palloc0fast(size); \ + _result->type = (int) (tag); \ + _result; \ +}) + + +/* + * CitusMakeNode is CitusDB variant of makeNode(). Use it to create nodes of + * the types listed in the CitusNodeTag enum and plain NodeTag. Initializes + * memory, besides the node tag, to 0. + */ +#define CitusMakeNode(_type_) ((_type_ *) CitusNewNode(sizeof(_type_),T_##_type_)) + + +#endif /* CITUS_NODES_H */ diff --git a/src/include/distributed/citus_ruleutils.h b/src/include/distributed/citus_ruleutils.h new file mode 100644 index 000000000..0f2402748 --- /dev/null +++ b/src/include/distributed/citus_ruleutils.h @@ -0,0 +1,31 @@ +/*------------------------------------------------------------------------- + * + * citus_ruleutils.h + * CitusDB ruleutils wrapper functions and exported PostgreSQL ruleutils + * functions. + * + * Copyright (c) 2012-2015, Citus Data, Inc. + *------------------------------------------------------------------------- + */ + +#ifndef CITUS_RULEUTILS_H +#define CITUS_RULEUTILS_H + +#include "lib/stringinfo.h" +#include "nodes/parsenodes.h" + + +/* Function declarations for version independent CitusDB ruleutils wrapper functions */ +extern char *pg_get_extensiondef_string(Oid tableRelationId); +extern char *pg_get_serverdef_string(Oid tableRelationId); +extern char *pg_get_tableschemadef_string(Oid tableRelationId); +extern char *pg_get_tablecolumnoptionsdef_string(Oid tableRelationId); +extern char *pg_get_indexclusterdef_string(Oid indexRelationId); + +/* Function declarations for version dependent PostgreSQL ruleutils functions */ +extern void pg_get_query_def(Query *query, StringInfo buffer); +extern void deparse_shard_query(Query *query, Oid distrelid, int64 shardid, StringInfo buffer); +extern char *generate_relation_name(Oid relid, List *namespaces); + + +#endif /* CITUS_RULEUTILS_H */ diff --git a/src/include/distributed/connection_cache.h b/src/include/distributed/connection_cache.h new file mode 100644 index 000000000..2a1f997d6 --- /dev/null +++ b/src/include/distributed/connection_cache.h @@ -0,0 +1,59 @@ +/*------------------------------------------------------------------------- + * + * connection_cache.h + * + * Declarations for public functions and types related to connection hash + * functionality. + * + * Copyright (c) 2014-2015, Citus Data, Inc. + * + *------------------------------------------------------------------------- + */ + +#ifndef CONNECTION_CACHE_H +#define CONNECTION_CACHE_H + +#include "c.h" +#include "libpq-fe.h" + + +/* maximum duration to wait for connection */ +#define CLIENT_CONNECT_TIMEOUT_SECONDS "5" + +/* maximum (textual) lengths of hostname and port */ +#define MAX_NODE_LENGTH 255 +#define MAX_PORT_LENGTH 10 + +/* times to attempt connection (or reconnection) */ +#define MAX_CONNECT_ATTEMPTS 2 + +/* SQL statement for testing */ +#define TEST_SQL "DO $$ BEGIN RAISE EXCEPTION 'Raised remotely!'; END $$" + + +/* + * NodeConnectionKey acts as the key to index into the (process-local) hash + * keeping track of open connections. Node name and port are sufficient. + */ +typedef struct NodeConnectionKey +{ + char nodeName[MAX_NODE_LENGTH + 1]; /* hostname of host to connect to */ + int32 nodePort; /* port of host to connect to */ +} NodeConnectionKey; + + +/* NodeConnectionEntry keeps track of connections themselves. */ +typedef struct NodeConnectionEntry +{ + NodeConnectionKey cacheKey; /* hash entry key */ + PGconn *connection; /* connection to remote server, if any */ +} NodeConnectionEntry; + + +/* function declarations for obtaining and using a connection */ +extern PGconn * GetConnection(char *nodeName, int32 nodePort); +extern void PurgeConnection(PGconn *connection); +extern void ReportRemoteError(PGconn *connection, PGresult *result); + + +#endif /* CONNECTION_CACHE_H */ diff --git a/src/include/distributed/listutils.h b/src/include/distributed/listutils.h new file mode 100644 index 000000000..3e9cd3917 --- /dev/null +++ b/src/include/distributed/listutils.h @@ -0,0 +1,26 @@ +/*------------------------------------------------------------------------- + * + * listutils.h + * + * Declarations for public utility functions related to lists. + * + * Copyright (c) 2014-2015, Citus Data, Inc. + * + *------------------------------------------------------------------------- + */ + +#ifndef CITUSDB_LISTUTILS_H +#define CITUSDB_LISTUTILS_H + +#include "postgres.h" +#include "c.h" + +#include "nodes/pg_list.h" + + +/* utility functions declaration shared within this module */ +extern List * SortList(List *pointerList, + int (*ComparisonFunction)(const void *, const void *)); + + +#endif /* CITUSDB_LISTUTILS_H */ diff --git a/src/include/distributed/master_metadata_utility.h b/src/include/distributed/master_metadata_utility.h new file mode 100644 index 000000000..b3cfb6548 --- /dev/null +++ b/src/include/distributed/master_metadata_utility.h @@ -0,0 +1,82 @@ +/*------------------------------------------------------------------------- + * + * master_metadata_utility.h + * Type and function declarations used for reading and modifying master + * node's metadata. + * + * Copyright (c) 2014, Citus Data, Inc. + * + * $Id$ + * + *------------------------------------------------------------------------- + */ + +#ifndef MASTER_METADATA_UTILITY_H +#define MASTER_METADATA_UTILITY_H + +#include "access/htup.h" +#include "access/tupdesc.h" +#include "distributed/citus_nodes.h" +#include "distributed/relay_utility.h" +#include "utils/relcache.h" + + +/* total number of hash tokens (2^32) */ +#define HASH_TOKEN_COUNT INT64CONST(4294967296UL) + +/* In-memory representation of a typed tuple in pg_dist_shard. */ +typedef struct ShardInterval +{ + CitusNodeTag type; + Oid relationId; + char storageType; + Oid valueTypeId; /* min/max value datum's typeId */ + int valueTypeLen; /* min/max value datum's typelen */ + bool valueByVal; /* min/max value datum's byval */ + bool minValueExists; + bool maxValueExists; + Datum minValue; /* a shard's typed min value datum */ + Datum maxValue; /* a shard's typed max value datum */ + uint64 shardId; + +} ShardInterval; + + +/* In-memory representation of a tuple in pg_dist_shard_placement. */ +typedef struct ShardPlacement +{ + CitusNodeTag type; + Oid tupleOid; /* unique oid that implies this row's insertion order */ + uint64 shardId; + uint64 shardLength; + RelayFileState shardState; + char *nodeName; + uint32 nodePort; + +} ShardPlacement; + + +/* Function declarations to read shard and shard placement data */ +extern List * LoadShardIntervalList(Oid relationId); +extern List * LoadShardList(Oid relationId); +extern char * LoadShardAlias(Oid relationId, uint64 shardId); +extern void CopyShardInterval(ShardInterval *srcInterval, ShardInterval *destInterval); +extern uint64 ShardLength(uint64 shardId); +extern List * FinalizedShardPlacementList(uint64 shardId); +extern List * ShardPlacementList(uint64 shardId); +extern ShardPlacement * TupleToShardPlacement(TupleDesc tupleDesc, + HeapTuple heapTuple); + +/* Function declarations to modify shard and shard placement data */ +extern void InsertShardRow(Oid relationId, uint64 shardId, char storageType, + text *shardMinValue, text *shardMaxValue); +extern void InsertShardPlacementRow(uint64 shardId, char shardState, uint64 shardLength, + char *nodeName, uint32 nodePort); +extern void DeleteShardRow(uint64 shardId); +extern void DeleteShardPlacementRow(uint64 shardId, char *workerName, uint32 workerPort); + +/* Remaining metadata utility functions */ +extern Node * BuildDistributionKeyFromColumnName(Relation distributedRelation, + char *columnName); + +#endif /* MASTER_METADATA_UTILITY_H */ diff --git a/src/include/distributed/master_protocol.h b/src/include/distributed/master_protocol.h new file mode 100644 index 000000000..f39ce865b --- /dev/null +++ b/src/include/distributed/master_protocol.h @@ -0,0 +1,108 @@ +/*------------------------------------------------------------------------- + * + * master_protocol.h + * Header for shared declarations for access to master node data. These data + * are used to create new shards or update existing ones. + * + * Copyright (c) 2012, Citus Data, Inc. + * + * $Id$ + * + *------------------------------------------------------------------------- + */ + +#ifndef MASTER_PROTOCOL_H +#define MASTER_PROTOCOL_H + +#include "fmgr.h" +#include "nodes/pg_list.h" + + +/* + * In our distributed database, we need a mechanism to make remote procedure + * calls between clients, the master node, and worker nodes. These remote calls + * require serializing and deserializing values and function signatures between + * nodes; and for these, we currently use PostgreSQL's built-in type and + * function definition system. This approach is by no means ideal however; and + * our implementation: (i) cannot perform compile-time type checks, (ii) + * requires additional effort when upgrading to new function signatures, and + * (iii) hides argument and return value names and types behind complicated + * pg_proc.h definitions. + * + * An ideal implementation should overcome these problems, and make it much + * easier to pass values back and forth between nodes. One such implementation + * that comes close to ideal is Google's Protocol Buffers. Nonetheless, we do + * not use it in here as its inclusion requires changes to PostgreSQL's make + * system, and a native C version is currently unavailable. + */ + + +/* Number of tuple fields that master node functions return */ +#define TABLE_METADATA_FIELDS 7 +#define CANDIDATE_NODE_FIELDS 2 +#define WORKER_NODE_FIELDS 2 + +/* Name of columnar foreign data wrapper */ +#define CSTORE_FDW_NAME "cstore_fdw" + +/* ShardId sequence name as defined in initdb.c */ +#define SHARDID_SEQUENCE_NAME "pg_dist_shardid_seq" + +/* Remote call definitions to help with data staging and deletion */ +#define WORKER_APPLY_SHARD_DDL_COMMAND "SELECT worker_apply_shard_ddl_command \ + ("UINT64_FORMAT", %s)" +#define WORKER_APPEND_TABLE_TO_SHARD "SELECT worker_append_table_to_shard \ + (%s, %s, %s, %u)" +#define SHARD_MIN_VALUE_QUERY "SELECT min(%s) FROM %s" +#define SHARD_MAX_VALUE_QUERY "SELECT max(%s) FROM %s" +#define SHARD_TABLE_SIZE_QUERY "SELECT pg_table_size('%s')" +#define DROP_REGULAR_TABLE_COMMAND "DROP TABLE IF EXISTS %s" +#define DROP_FOREIGN_TABLE_COMMAND "DROP FOREIGN TABLE IF EXISTS %s" +#define CREATE_SCHEMA_COMMAND "CREATE SCHEMA IF NOT EXISTS %s" + + +/* Enumeration that defines the shard placement policy to use while staging */ +typedef enum +{ + SHARD_PLACEMENT_INVALID_FIRST = 0, + SHARD_PLACEMENT_LOCAL_NODE_FIRST = 1, + SHARD_PLACEMENT_ROUND_ROBIN = 2 + +} ShardPlacementPolicyType; + + +/* Config variables managed via guc.c */ +extern int ShardReplicationFactor; +extern int ShardMaxSize; +extern int ShardPlacementPolicy; + + +/* Function declarations local to the distributed module */ +extern bool CStoreTable(Oid relationId); +extern Oid ResolveRelationId(text *relationName); +extern List * GetTableDDLEvents(Oid relationId); +extern void CheckDistributedTable(Oid relationId); +extern void CreateShardPlacements(int64 shardId, List *ddlEventList, + List *workerNodeList, int workerStartIndex, + int replicationFactor); + +/* Function declarations for generating metadata for shard creation */ +extern Datum master_get_table_metadata(PG_FUNCTION_ARGS); +extern Datum master_get_table_ddl_events(PG_FUNCTION_ARGS); +extern Datum master_get_new_shardid(PG_FUNCTION_ARGS); +extern Datum master_get_local_first_candidate_nodes(PG_FUNCTION_ARGS); +extern Datum master_get_round_robin_candidate_nodes(PG_FUNCTION_ARGS); +extern Datum master_get_active_worker_nodes(PG_FUNCTION_ARGS); + +/* Function declarations to help with data staging and deletion */ +extern Datum master_create_empty_shard(PG_FUNCTION_ARGS); +extern Datum master_append_table_to_shard(PG_FUNCTION_ARGS); +extern Datum master_apply_delete_command(PG_FUNCTION_ARGS); + +/* function declarations for shard creation functionality */ +extern Datum master_create_worker_shards(PG_FUNCTION_ARGS); + +/* function declarations for shard repair functionality */ +extern Datum master_copy_shard_placement(PG_FUNCTION_ARGS); + +#endif /* MASTER_PROTOCOL_H */ diff --git a/src/include/distributed/metadata_cache.h b/src/include/distributed/metadata_cache.h new file mode 100644 index 000000000..0c002b8da --- /dev/null +++ b/src/include/distributed/metadata_cache.h @@ -0,0 +1,65 @@ +/*------------------------------------------------------------------------- + * + * metadata_cache.h + * Executor support for CitusDB. + * + * Copyright (c) 2012-2015, Citus Data, Inc. + * + *------------------------------------------------------------------------- + */ + +#ifndef METADATA_CACHE_H +#define METADATA_CACHE_H + +#include "distributed/master_metadata_utility.h" +#include "distributed/pg_dist_partition.h" + + +/* + * Representation of a table's metadata that is frequently used for + * distributed execution. Cached. + */ +typedef struct +{ + /* lookup key - must be first. A pg_class.oid oid. */ + Oid relationId; + + /* + * Has an invalidation been received for this entry, requiring a rebuild + * of the cache entry? + */ + bool isValid; + + bool isDistributedTable; + + /* pg_dist_partition metadata for this table */ + char *partitionKeyString; + char partitionMethod; + + /* pg_dist_shard metadata (variable-length ShardInterval array) for this table */ + int shardIntervalArrayLength; + ShardInterval *shardIntervalArray; +} DistTableCacheEntry; + + +extern bool IsDistributedTable(Oid relationId); +extern ShardInterval * LoadShardInterval(uint64 shardId); +extern DistTableCacheEntry * DistributedTableCacheEntry(Oid distributedRelationId); + +extern bool CitusDBHasBeenLoaded(void); + +/* relation oids */ +extern Oid DistPartitionRelationId(void); +extern Oid DistShardRelationId(void); +extern Oid DistShardPlacementRelationId(void); + +/* index oids */ +extern Oid DistPartitionLogicalRelidIndexId(void); +extern Oid DistShardLogicalRelidIndexId(void); +extern Oid DistShardShardidIndexId(void); +extern Oid DistShardPlacementShardidIndexId(void); + +/* function oids */ +extern Oid CitusExtraDataContainerFuncId(void); + +#endif /* METADATA_CACHE_H */ diff --git a/src/include/distributed/modify_planner.h b/src/include/distributed/modify_planner.h new file mode 100644 index 000000000..3e52cfa5a --- /dev/null +++ b/src/include/distributed/modify_planner.h @@ -0,0 +1,34 @@ +/*------------------------------------------------------------------------- + * + * modify_planner.h + * + * Declarations for public functions and types related to modify planning. + * + * Copyright (c) 2014-2016, Citus Data, Inc. + * + *------------------------------------------------------------------------- + */ + +#ifndef MODIFY_PLANNER_H +#define MODIFY_PLANNER_H + +#include "c.h" + +#include "distributed/multi_logical_planner.h" +#include "distributed/multi_physical_planner.h" +#include "nodes/parsenodes.h" + + +/* values used by jobs and tasks which do not require identifiers */ +#define INVALID_JOB_ID 0 +#define INVALID_TASK_ID 0 + +#if (PG_VERSION_NUM >= 90500) +/* reserved alias name for UPSERTs */ +#define UPSERT_ALIAS "citus_table_alias" +#endif + + +extern MultiPlan * MultiModifyPlanCreate(Query *query); + +#endif /* MODIFY_PLANNER_H */ diff --git a/src/include/distributed/multi_client_executor.h b/src/include/distributed/multi_client_executor.h new file mode 100644 index 000000000..470b53673 --- /dev/null +++ b/src/include/distributed/multi_client_executor.h @@ -0,0 +1,101 @@ +/*------------------------------------------------------------------------- + * + * multi_client_executor.h + * Type and function pointer declarations for executing client-side (libpq) + * logic. + * + * Copyright (c) 2012, Citus Data, Inc. + * + * $Id$ + * + *------------------------------------------------------------------------- + */ + +#ifndef MULTI_CLIENT_EXECUTOR_H +#define MULTI_CLIENT_EXECUTOR_H + + +#define INVALID_CONNECTION_ID -1 /* identifies an invalid connection */ +#define CLIENT_CONNECT_TIMEOUT 5 /* connection timeout in seconds */ +#define MAX_CONNECTION_COUNT 2048 /* simultaneous client connection count */ +#define STRING_BUFFER_SIZE 1024 /* buffer size for character arrays */ +#define CONN_INFO_TEMPLATE "host=%s port=%u dbname=%s connect_timeout=%u" + + +/* Enumeration to track one client connection's status */ +typedef enum +{ + CLIENT_INVALID_CONNECT = 0, + CLIENT_CONNECTION_BAD = 1, + CLIENT_CONNECTION_BUSY = 2, + CLIENT_CONNECTION_READY = 3 + +} ConnectStatus; + + +/* Enumeration to see if we can read query results without blocking */ +typedef enum +{ + CLIENT_INVALID_RESULT_STATUS = 0, + CLIENT_RESULT_UNAVAILABLE = 1, + CLIENT_RESULT_BUSY = 2, + CLIENT_RESULT_READY = 3 + +} ResultStatus; + + +/* Enumeration to track one execution query's status on the client */ +typedef enum +{ + CLIENT_INVALID_QUERY = 0, + CLIENT_QUERY_FAILED = 1, + CLIENT_QUERY_DONE = 2, + CLIENT_QUERY_COPY = 3 + +} QueryStatus; + + +/* Enumeration to track one copy query's status on the client */ +typedef enum +{ + CLIENT_INVALID_COPY = 0, + CLIENT_COPY_MORE = 1, + CLIENT_COPY_FAILED = 2, + CLIENT_COPY_DONE = 3 + +} CopyStatus; + + +/* Enumeration to track the status of a query in a batch on the client */ +typedef enum +{ + CLIENT_INVALID_BATCH_QUERY = 0, + CLIENT_BATCH_QUERY_FAILED = 1, + CLIENT_BATCH_QUERY_CONTINUE = 2, + CLIENT_BATCH_QUERY_DONE = 3 + +} BatchQueryStatus; + + +/* Function declarations for executing client-side (libpq) logic. */ +extern int32 MultiClientConnect(const char *nodeName, uint32 nodePort, + const char *nodeDatabase); +extern int32 MultiClientConnectStart(const char *nodeName, uint32 nodePort, + const char *nodeDatabase); +extern ConnectStatus MultiClientConnectPoll(int32 connectionId); +extern void MultiClientDisconnect(int32 connectionId); +extern bool MultiClientConnectionUp(int32 connectionId); +extern bool MultiClientSendQuery(int32 connectionId, const char *query); +extern bool MultiClientCancel(int32 connectionId); +extern ResultStatus MultiClientResultStatus(int32 connectionId); +extern QueryStatus MultiClientQueryStatus(int32 connectionId); +extern CopyStatus MultiClientCopyData(int32 connectionId, int32 fileDescriptor); +extern bool MultiClientQueryResult(int32 connectionId, void **queryResult, + int *rowCount, int *columnCount); +extern BatchQueryStatus MultiClientBatchResult(int32 connectionId, void **queryResult, + int *rowCount, int *columnCount); +extern char * MultiClientGetValue(void *queryResult, int rowIndex, int columnIndex); +extern void MultiClientClearResult(void *queryResult); + + +#endif /* MULTI_CLIENT_EXECUTOR_H */ diff --git a/src/include/distributed/multi_executor.h b/src/include/distributed/multi_executor.h new file mode 100644 index 000000000..bcf22fe2e --- /dev/null +++ b/src/include/distributed/multi_executor.h @@ -0,0 +1,26 @@ +/*------------------------------------------------------------------------- + * + * multi_executor.h + * Executor support for CitusDB. + * + * Copyright (c) 2012-2015, Citus Data, Inc. + *------------------------------------------------------------------------- + */ + +#ifndef MULTI_EXECUTOR_H +#define MULTI_EXECUTOR_H + +#include "executor/execdesc.h" +#include "nodes/parsenodes.h" + +/* signal currently executed statement is a master select statement or router execution */ +#define EXEC_FLAG_CITUS_MASTER_SELECT 0x100 +#define EXEC_FLAG_CITUS_ROUTER_EXECUTOR 0x200 + +extern void multi_ExecutorStart(QueryDesc *queryDesc, int eflags); +extern void multi_ExecutorRun(QueryDesc *queryDesc, + ScanDirection direction, long count); +extern void multi_ExecutorFinish(QueryDesc *queryDesc); +extern void multi_ExecutorEnd(QueryDesc *queryDesc); + +#endif /* MULTI_EXECUTOR_H */ diff --git a/src/include/distributed/multi_explain.h b/src/include/distributed/multi_explain.h new file mode 100644 index 000000000..71ed52948 --- /dev/null +++ b/src/include/distributed/multi_explain.h @@ -0,0 +1,22 @@ +/*------------------------------------------------------------------------- + * + * multi_explain.h + * Explain support for CitusDB. + * + * Copyright (c) 2012-2015, Citus Data, Inc. + *------------------------------------------------------------------------- + */ + +#ifndef MULTI_EXPLAIN_H +#define MULTI_EXPLAIN_H + +#include "executor/executor.h" + +/* Config variables managed via guc.c to explain distributed query plans */ +extern bool ExplainMultiLogicalPlan; +extern bool ExplainMultiPhysicalPlan; + +extern void MultiExplainOneQuery(Query *query, IntoClause *into, ExplainState *es, + const char *queryString, ParamListInfo params); + +#endif /* MULTI_EXPLAIN_H */ diff --git a/src/include/distributed/multi_join_order.h b/src/include/distributed/multi_join_order.h new file mode 100644 index 000000000..cccde6917 --- /dev/null +++ b/src/include/distributed/multi_join_order.h @@ -0,0 +1,100 @@ +/*------------------------------------------------------------------------- + * + * multi_join_order.h + * + * Type and function declarations for determining a left-only join order for a + * distributed query plan. + * + * Copyright (c) 2012, Citus Data, Inc. + * + * $Id$ + * + *------------------------------------------------------------------------- + */ + +#ifndef MULTI_JOIN_ORDER_H +#define MULTI_JOIN_ORDER_H + +#include "nodes/pg_list.h" +#include "nodes/primnodes.h" + + +/* + * JoinRuleType determines the type of the join rule that applies between two + * tables or row sources. The rule types are ordered below according to their + * costs, with the cheapes rule appearing at the top. Note that changing the + * order of these enums *will* change the order in which the rules are applied. + */ +typedef enum JoinRuleType +{ + JOIN_RULE_INVALID_FIRST = 0, + BROADCAST_JOIN = 1, + LOCAL_PARTITION_JOIN = 2, + SINGLE_PARTITION_JOIN = 3, + DUAL_PARTITION_JOIN = 4, + CARTESIAN_PRODUCT = 5, + + /* + * Add new join rule types above this comment. After adding, you must also + * update these arrays: RuleEvalFunctionArray, RuleApplyFunctionArray, and + * RuleNameArray. + */ + JOIN_RULE_LAST + +} JoinRuleType; + + +/* + * TableEntry represents a table used when determining the join order. A table + * entry corresponds to an ordinary relation reference (RTE_RELATION) in the + * query range table list. + */ +typedef struct TableEntry +{ + Oid relationId; + uint32 rangeTableId; + +} TableEntry; + + +/* + * JoinOrderNode represents an element in the join order list; and this list + * keeps the total join order for a distributed query. The first node in this + * list later becomes the leftmost table in the join tree, and the successive + * elements in the list are the joining tables in the left-deep tree. + */ +typedef struct JoinOrderNode +{ + TableEntry *tableEntry; /* this node's relation and range table id */ + JoinRuleType joinRuleType; /* not relevant for the first table */ + JoinType joinType; /* not relevant for the first table */ + Var *partitionColumn; /* not relevant for the first table */ + char partitionMethod; + List *joinClauseList; /* not relevant for the first table */ + List *shardIntervalList; + +} JoinOrderNode; + + +/* Config variables managed via guc.c */ +extern int LargeTableShardCount; +extern bool LogMultiJoinOrder; + + +/* Function declaration for determining table join orders */ +extern List * FixedJoinOrderList(FromExpr *fromExpr, List *tableEntryList); +extern List * JoinExprList(FromExpr *fromExpr); +extern List * JoinOrderList(List *rangeTableEntryList, List *joinClauseList); +extern List * ApplicableJoinClauses(List *leftTableIdList, uint32 rightTableId, + List *joinClauseList); +extern OpExpr * SinglePartitionJoinClause(Var *partitionColumn, + List *applicableJoinClauses); +extern OpExpr * DualPartitionJoinClause(List *applicableJoinClauses); +extern Var * LeftColumn(OpExpr *joinClause); +extern Var * RightColumn(OpExpr *joinClause); +extern Var * PartitionColumn(Oid relationId, uint32 rangeTableId); +extern Var * PartitionKey(Oid relationId); +extern char PartitionMethod(Oid relationId); + + +#endif /* MULTI_JOIN_ORDER_H */ diff --git a/src/include/distributed/multi_logical_optimizer.h b/src/include/distributed/multi_logical_optimizer.h new file mode 100644 index 000000000..f8c145751 --- /dev/null +++ b/src/include/distributed/multi_logical_optimizer.h @@ -0,0 +1,127 @@ +/*------------------------------------------------------------------------- + * + * multi_logical_optimizer.h + * Type and function declarations for optimizing multi-relation based logical + * plans. + * + * Copyright (c) 2012, Citus Data, Inc. + * + * $Id$ + * + *------------------------------------------------------------------------- + */ + +#ifndef MULTI_LOGICAL_OPTIMIZER_H +#define MULTI_LOGICAL_OPTIMIZER_H + +#include "distributed/master_metadata_utility.h" +#include "distributed/multi_logical_planner.h" + + +/* Definitions local to logical plan optimizer */ +#define DIVISION_OPER_NAME "/" +#define DISABLE_LIMIT_APPROXIMATION -1 +#define DISABLE_DISTINCT_APPROXIMATION 0.0 +#define ARRAY_CAT_AGGREGATE_NAME "array_cat_agg" +#define WORKER_COLUMN_FORMAT "worker_column_%d" + +/* Definitions related to count(distinct) approximations */ +#define HLL_EXTENSION_NAME "hll" +#define HLL_TYPE_NAME "hll" +#define HLL_HASH_INTEGER_FUNC_NAME "hll_hash_integer" +#define HLL_HASH_BIGINT_FUNC_NAME "hll_hash_bigint" +#define HLL_HASH_TEXT_FUNC_NAME "hll_hash_text" +#define HLL_HASH_ANY_FUNC_NAME "hll_hash_any" +#define HLL_ADD_AGGREGATE_NAME "hll_add_agg" +#define HLL_UNION_AGGREGATE_NAME "hll_union_agg" +#define HLL_CARDINALITY_FUNC_NAME "hll_cardinality" + + +/* + * AggregateType represents an aggregate function's type, where the function is + * used in the context of a query. We use this function type to determine how to + * modify the plan when creating the logical distributed plan. + * + * Please note that the order of values in this enumeration is tied to the order + * of elements in the following AggregateNames array. This order needs to be + * preserved. + */ +typedef enum +{ + AGGREGATE_INVALID_FIRST = 0, + AGGREGATE_AVERAGE = 1, + AGGREGATE_MIN = 2, + AGGREGATE_MAX = 3, + AGGREGATE_SUM = 4, + AGGREGATE_COUNT = 5, + AGGREGATE_ARRAY_AGG = 6 + +} AggregateType; + + +/* + * PushDownStatus indicates whether a node can be pushed down below its child + * using the commutative and distributive relational algebraic properties. + */ +typedef enum +{ + PUSH_DOWN_INVALID_FIRST = 0, + PUSH_DOWN_VALID = 1, + PUSH_DOWN_NOT_VALID = 2, + PUSH_DOWN_SPECIAL_CONDITIONS = 3 + +} PushDownStatus; + + +/* + * PullUpStatus indicates whether a node can be pulled up above its parent using + * the commutative and factorizable relational algebraic properties. + */ +typedef enum +{ + PULL_UP_INVALID_FIRST = 0, + PULL_UP_VALID = 1, + PULL_UP_NOT_VALID = 2 + +} PullUpStatus; + + +/* + * AggregateNames is an array that stores cstring names for aggregate functions; + * these cstring names act as an intermediary when mapping aggregate function + * oids to AggregateType enumerations. For this mapping to occur, we use the + * aggregate function oid to find the corresponding cstring name in pg_proc. We + * then compare that name against entries in this array, and return the + * appropriate AggregateType value. + * + * Please note that the order of elements in this array is tied to the order of + * values in the preceding AggregateType enum. This order needs to be preserved. + */ +static const char * const AggregateNames[] = { "invalid", "avg", "min", "max", + "sum", "count", "array_agg" }; + + +/* Config variable managed via guc.c */ +extern int LimitClauseRowFetchCount; +extern double CountDistinctErrorRate; + + +/* Function declaration for optimizing logical plans */ +extern void MultiLogicalPlanOptimize(MultiTreeRoot *multiTree); + +/* Function declaration for getting partition method for the given relation */ +extern char PartitionMethod(Oid relationId); + +/* Function declaration for getting oid for the given function name */ +extern Oid FunctionOid(const char *functionName, int argumentCount); + +/* Function declaration for helper functions in subquery pushdown */ +extern List * SubqueryMultiTableList(MultiNode *multiNode); +extern List * GroupTargetEntryList(List *groupClauseList, List *targetEntryList); +extern bool ExtractQueryWalker(Node *node, List **queryList); +extern bool LeafQuery(Query *queryTree); +extern List * PartitionColumnOpExpressionList(Query *query); +extern List * ReplaceColumnsInOpExpressionList(List *opExpressionList, Var *newColumn); + + +#endif /* MULTI_LOGICAL_OPTIMIZER_H */ diff --git a/src/include/distributed/multi_logical_planner.h b/src/include/distributed/multi_logical_planner.h new file mode 100644 index 000000000..15b0cba07 --- /dev/null +++ b/src/include/distributed/multi_logical_planner.h @@ -0,0 +1,217 @@ +/*------------------------------------------------------------------------- + * + * multi_logical_planner.h + * Type declarations for multi-relational algebra operators, and function + * declarations for building logical plans over distributed relations. + * + * Copyright (c) 2012, Citus Data, Inc. + * + * $Id$ + * + *------------------------------------------------------------------------- + */ + +#ifndef MULTI_LOGICAL_PLANNER_H +#define MULTI_LOGICAL_PLANNER_H + +#include "distributed/citus_nodes.h" +#include "distributed/multi_join_order.h" +#include "nodes/nodes.h" +#include "nodes/primnodes.h" +#include "nodes/parsenodes.h" +#include "nodes/pg_list.h" + + +/* Defines the operator string used for equi joins */ +#define EQUAL_OPERATOR_STRING "=" +#define SUBQUERY_RANGE_TABLE_ID -1 +#define SUBQUERY_RELATION_ID 10000 +#define HEAP_ANALYTICS_SUBQUERY_RELATION_ID 10001 + + +/* + * MultiNode represents the base node type for all multi-relational algebra + * nodes. By creating this base node, we can simulate inheritance and represent + * derived operator nodes as a MultiNode type. A similar structure to simulate + * inheritance is also used in PostgreSQL's plan nodes. + */ +typedef struct MultiNode +{ + CitusNodeTag type; + + struct MultiNode *parentNode; + /* child node(s) are defined in unary and binary nodes */ + +} MultiNode; + + +/* Represents unary nodes that have only one child */ +typedef struct MultiUnaryNode +{ + MultiNode node; + + struct MultiNode *childNode; + +} MultiUnaryNode; + + +/* Represents binary nodes that have two children */ +typedef struct MultiBinaryNode +{ + MultiNode node; + + struct MultiNode *leftChildNode; + struct MultiNode *rightChildNode; + +} MultiBinaryNode; + + +/* + * MultiTreeRoot keeps a pointer to the root node in the multi-relational + * operator tree. This node is always on the top of every logical plan. + */ +typedef struct MultiTreeRoot +{ + MultiUnaryNode unaryNode; + +} MultiTreeRoot; + + +/* + * MultiTable represents a partitioned table in a logical query plan. Note that + * this node does not represent a query operator, and differs from the nodes + * that follow in that sense. + */ +typedef struct MultiTable +{ + MultiUnaryNode unaryNode; + Oid relationId; + int rangeTableId; + Var *partitionColumn; + Alias *alias; + Alias *referenceNames; + Query *subquery; /* this field is only valid for non-relation subquery types */ + +} MultiTable; + + +/* Defines the columns to project in multi-relational algebra */ +typedef struct MultiProject +{ + MultiUnaryNode unaryNode; + List *columnList; + +} MultiProject; + + +/* + * MultiCollect defines the Collect operator in multi-relational algebra. This + * operator collects data from remote nodes; the collected data are output from + * the query operator that is beneath this Collect in the logical query tree. + */ +typedef struct MultiCollect +{ + MultiUnaryNode unaryNode; + +} MultiCollect; + + +/* + * MultiSelect defines the MultiSelect operator in multi-relational algebra. + * This operator contains select predicates which apply to a selected logical + * relation. + */ +typedef struct MultiSelect +{ + MultiUnaryNode unaryNode; + List *selectClauseList; + +} MultiSelect; + + +/* + * MultiJoin joins the output of two query operators that are beneath it in the + * query tree. The operator also keeps the join rule that applies between the + * two operators, and the partition key to use if the join is distributed. + */ +typedef struct MultiJoin +{ + MultiBinaryNode binaryNode; + List *joinClauseList; + JoinRuleType joinRuleType; + JoinType joinType; + +} MultiJoin; + + +/* Defines the (re-)Partition operator in multi-relational algebra */ +typedef struct MultiPartition +{ + MultiUnaryNode unaryNode; + Var *partitionColumn; + uint32 splitPointTableId; + +} MultiPartition; + + +/* Defines the CartesianProduct operator in multi-relational algebra */ +typedef struct MultiCartesianProduct +{ + MultiBinaryNode binaryNode; + +} MultiCartesianProduct; + + +/* + * MultiExtendedOp defines a set of extended operators that operate on columns + * in relational algebra. This node allows us to distinguish between operations + * in the master and worker nodes, and also captures the following: + * + * (1) Aggregate functions such as sums or averages; + * (2) Grouping of attributes; these groupings may also be tied to aggregates; + * (3) Extended projection expressions including columns, arithmetic and string + * functions; + * (4) User's intented display information, such as column display order; + * (5) Sort clauses on columns, expressions, or aggregates; and + * (6) Limit count and offset clause. + */ +typedef struct MultiExtendedOp +{ + MultiUnaryNode unaryNode; + List *targetList; + List *groupClauseList; + List *sortClauseList; + Node *limitCount; + Node *limitOffset; + +} MultiExtendedOp; + + +/* Config variables managed via guc.c */ +extern bool SubqueryPushdown; + + +/* Function declarations for building logical plans */ +extern MultiTreeRoot * MultiLogicalPlanCreate(Query *queryTree); +extern bool NeedsDistributedPlanning(Query *queryTree); +extern MultiNode * ParentNode(MultiNode *multiNode); +extern MultiNode * ChildNode(MultiUnaryNode *multiNode); +extern MultiNode * GrandChildNode(MultiUnaryNode *multiNode); +extern void SetChild(MultiUnaryNode *parent, MultiNode *child); +extern void SetLeftChild(MultiBinaryNode *parent, MultiNode *leftChild); +extern void SetRightChild(MultiBinaryNode *parent, MultiNode *rightChild); +extern bool UnaryOperator(MultiNode *node); +extern bool BinaryOperator(MultiNode *node); +extern List * OutputTableIdList(MultiNode *multiNode); +extern List * FindNodesOfType(MultiNode *node, int type); +extern List * JoinClauseList(List *whereClauseList); +extern List * SubqueryEntryList(Query *queryTree); +extern bool ExtractRangeTableIndexWalker(Node *node, List **rangeTableIndexList); +extern List * WhereClauseList(FromExpr *fromExpr); +extern List * TableEntryList(List *rangeTableList); +extern bool ExtractRangeTableRelationWalker(Node *node, List **rangeTableList); +extern bool ExtractRangeTableEntryWalker(Node *node, List **rangeTableList); +extern List * pull_var_clause_default(Node *node); + + +#endif /* MULTI_LOGICAL_PLANNER_H */ diff --git a/src/include/distributed/multi_master_planner.h b/src/include/distributed/multi_master_planner.h new file mode 100644 index 000000000..a50841993 --- /dev/null +++ b/src/include/distributed/multi_master_planner.h @@ -0,0 +1,28 @@ +/*------------------------------------------------------------------------- + * + * multi_master_planner.h + * Function declarations for building planned statements; these statements + * are then executed on the master node. + * + * Copyright (c) 2012, Citus Data, Inc. + * + * $Id$ + * + *------------------------------------------------------------------------- + */ + +#ifndef MULTI_MASTER_PLANNER_H +#define MULTI_MASTER_PLANNER_H + +#include "lib/stringinfo.h" +#include "nodes/parsenodes.h" +#include "nodes/plannodes.h" + + +/* Function declarations for building local plans on the master node */ +struct MultiPlan; +extern CreateStmt * MasterNodeCreateStatement(struct MultiPlan *multiPlan); +extern List * MasterNodeCopyStatementList(struct MultiPlan *multiPlan); +extern PlannedStmt * MasterNodeSelectPlan(struct MultiPlan *multiPlan); + +#endif /* MULTI_MASTER_PLANNER_H */ diff --git a/src/include/distributed/multi_physical_planner.h b/src/include/distributed/multi_physical_planner.h new file mode 100644 index 000000000..09d28e952 --- /dev/null +++ b/src/include/distributed/multi_physical_planner.h @@ -0,0 +1,260 @@ +/*------------------------------------------------------------------------- + * + * multi_physical_planner.h + * Type and function declarations used in creating the distributed execution + * plan. + * + * Copyright (c) 2012, Citus Data, Inc. + * + * $Id$ + * + *------------------------------------------------------------------------- + */ + +#ifndef MULTI_PHYSICAL_PLANNER_H +#define MULTI_PHYSICAL_PLANNER_H + +#include "distributed/citus_nodes.h" +#include "distributed/master_metadata_utility.h" +#include "distributed/multi_logical_planner.h" +#include "lib/stringinfo.h" +#include "nodes/parsenodes.h" +#include "utils/array.h" + + +/* Definitions local to the physical planner */ +#define JOBID_SEQUENCE_NAME "pg_dist_jobid_seq" +#define ARRAY_OUT_FUNC_ID 751 +#define NON_PRUNABLE_JOIN -1 +#define RESERVED_HASHED_COLUMN_ID MaxAttrNumber +#define MERGE_COLUMN_FORMAT "merge_column_%u" +#define TABLE_FETCH_COMMAND "SELECT worker_fetch_regular_table \ + ('%s', " UINT64_FORMAT ", '%s', '%s')" +#define FOREIGN_FETCH_COMMAND "SELECT worker_fetch_foreign_file \ + ('%s', " UINT64_FORMAT ", '%s', '%s')" +#define MAP_OUTPUT_FETCH_COMMAND "SELECT worker_fetch_partition_file \ + (" UINT64_FORMAT ", %u, %u, %u, '%s', %u)" +#define RANGE_PARTITION_COMMAND "SELECT worker_range_partition_table \ + (" UINT64_FORMAT ", %d, %s, '%s', %d, %s)" +#define HASH_PARTITION_COMMAND "SELECT worker_hash_partition_table \ + (" UINT64_FORMAT ", %d, %s, '%s', %d, %d)" +#define MERGE_FILES_INTO_TABLE_COMMAND "SELECT worker_merge_files_into_table \ + (" UINT64_FORMAT ", %d, '%s', '%s')" +#define MERGE_FILES_AND_RUN_QUERY_COMMAND "SELECT worker_merge_files_and_run_query(" UINT64_FORMAT ", %d, '%s', '%s')" + + +typedef enum CitusRTEKind +{ + CITUS_RTE_RELATION = RTE_RELATION, /* ordinary relation reference */ + CITUS_RTE_SUBQUERY = RTE_SUBQUERY, /* subquery in FROM */ + CITUS_RTE_JOIN = RTE_JOIN, /* join */ + CITUS_RTE_FUNCTION = RTE_FUNCTION, /* function in FROM */ + CITUS_RTE_VALUES = RTE_VALUES, /* VALUES (), (), ... */ + CITUS_RTE_CTE = RTE_CTE, /* common table expr (WITH list element) */ + CITUS_RTE_SHARD, + CITUS_RTE_REMOTE_QUERY +} CitusRTEKind; + + +/* Enumeration that defines the partition type for a remote job */ +typedef enum +{ + PARTITION_INVALID_FIRST = 0, + RANGE_PARTITION_TYPE = 1, + HASH_PARTITION_TYPE = 2 + +} PartitionType; + + +/* Enumeration that defines different task types */ +typedef enum +{ + TASK_TYPE_INVALID_FIRST = 0, + SQL_TASK = 1, + MAP_TASK = 2, + MERGE_TASK = 3, + SHARD_FETCH_TASK = 4, + MAP_OUTPUT_FETCH_TASK = 5, + MERGE_FETCH_TASK = 6, + MODIFY_TASK = 7 + +} TaskType; + + +/* Enumeration that defines the task assignment policy to use */ +typedef enum +{ + TASK_ASSIGNMENT_INVALID_FIRST = 0, + TASK_ASSIGNMENT_GREEDY = 1, + TASK_ASSIGNMENT_ROUND_ROBIN = 2, + TASK_ASSIGNMENT_FIRST_REPLICA = 3 + +} TaskAssignmentPolicyType; + + +/* Enumeration that defines different job types */ +typedef enum +{ + JOB_INVALID_FIRST = 0, + JOIN_MAP_MERGE_JOB = 1, + SUBQUERY_MAP_MERGE_JOB = 2, + TOP_LEVEL_WORKER_JOB = 3 + +} BoundaryNodeJobType; + + +/* + * Job represents a logical unit of work that contains one set of data transfers + * in our physical plan. The physical planner maps each SQL query into one or + * more jobs depending on the query's complexity, and sets dependencies between + * these jobs. Each job consists of multiple executable tasks; and these tasks + * either operate on base shards, or repartitioned tables. + */ +typedef struct Job +{ + CitusNodeTag type; + uint64 jobId; + Query *jobQuery; + List *taskList; + List *dependedJobList; + bool subqueryPushdown; +} Job; + + +/* Defines a repartitioning job and holds additional related data. */ +typedef struct MapMergeJob +{ + Job job; + Query *reduceQuery; + PartitionType partitionType; + Var *partitionColumn; + uint32 partitionCount; + int sortedShardIntervalArrayLength; + ShardInterval **sortedShardIntervalArray; /* only applies to range partitioning */ + List *mapTaskList; + List *mergeTaskList; + +} MapMergeJob; + + +/* + * Task represents an executable unit of work. We conceptualize our tasks into + * compute and data fetch task types. SQL, map, and merge tasks are considered + * as compute tasks; and shard fetch, map fetch, and merge fetch tasks are data + * fetch tasks. We also forward declare the task execution struct here to avoid + * including the executor header files. + */ +typedef struct TaskExecution TaskExecution; + +typedef struct Task +{ + CitusNodeTag type; + TaskType taskType; + uint64 jobId; + uint32 taskId; + char *queryString; + uint64 anchorShardId; /* only applies to compute tasks */ + List *taskPlacementList; /* only applies to compute tasks */ + List *dependedTaskList; /* only applies to compute tasks */ + + uint32 partitionId; + uint32 upstreamTaskId; /* only applies to data fetch tasks */ + ShardInterval *shardInterval; /* only applies to merge tasks */ + bool assignmentConstrained; /* only applies to merge tasks */ + uint64 shardId; /* only applies to shard fetch tasks */ + TaskExecution *taskExecution; /* used by task tracker executor */ + bool upsertQuery; /* only applies to modify tasks */ + +} Task; + + +/* + * RangeTableFragment represents a fragment of a range table. This fragment + * could be a regular shard or a merged table formed in a MapMerge job. + */ +typedef struct RangeTableFragment +{ + CitusRTEKind fragmentType; + void *fragmentReference; + uint32 rangeTableId; + +} RangeTableFragment; + + +/* + * JoinSequenceNode represents a range table in an ordered sequence of tables + * joined together. This representation helps build combinations of all range + * table fragments during task generation. + */ +typedef struct JoinSequenceNode +{ + uint32 rangeTableId; + int32 joiningRangeTableId; + +} JoinSequenceNode; + + +/* + * MultiPlan + */ +typedef struct MultiPlan +{ + CitusNodeTag type; + Job *workerJob; + Query *masterQuery; + char *masterTableName; + +} MultiPlan; + + +/* OperatorCacheEntry contains information for each element in OperatorCache */ +typedef struct OperatorCacheEntry +{ + /* cache key consists of typeId, accessMethodId and strategyNumber */ + Oid typeId; + Oid accessMethodId; + int16 strategyNumber; + Oid operatorId; + Oid operatorClassInputType; + char typeType; +} OperatorCacheEntry; + + +/* Config variable managed via guc.c */ +extern int TaskAssignmentPolicy; + +/* Function declarations for building physical plans and constructing queries */ +extern MultiPlan * MultiPhysicalPlanCreate(MultiTreeRoot *multiTree); +extern StringInfo ShardFetchQueryString(uint64 shardId); + +/* Function declarations for shard pruning */ +extern List * PruneShardList(Oid relationId, Index tableId, List *whereClauseList, + List *shardList); +extern OpExpr * MakeOpExpression(Var *variable, int16 strategyNumber); + +/* + * Function declarations for building, updating constraints and simple operator + * expression check. + */ +extern Node * BuildBaseConstraint(Var *column); +extern void UpdateConstraint(Node *baseConstraint, ShardInterval *shardInterval); +extern bool SimpleOpExpression(Expr *clause); + +extern int CompareShardPlacements(const void *leftElement, const void *rightElement); + +/* Function declarations for sorting shards. */ +extern ShardInterval ** SortedShardIntervalArray(List *shardList); +extern bool ShardIntervalsOverlap(ShardInterval *firstInterval, + ShardInterval *secondInterval); + +/* function declarations for Task and Task list operations */ +extern bool TasksEqual(const Task *a, const Task *b); +extern List * TaskListAppendUnique(List *list, Task *task); +extern List * TaskListConcatUnique(List *list1, List *list2); +extern bool TaskListMember(const List *taskList, const Task *task); +extern List * TaskListDifference(const List *list1, const List *list2); +extern List * TaskListUnion(const List *list1, const List *list2); +extern List * FirstReplicaAssignTaskList(List *taskList); + + +#endif /* MULTI_PHYSICAL_PLANNER_H */ diff --git a/src/include/distributed/multi_planner.h b/src/include/distributed/multi_planner.h new file mode 100644 index 000000000..a14b2b65e --- /dev/null +++ b/src/include/distributed/multi_planner.h @@ -0,0 +1,23 @@ +/*------------------------------------------------------------------------- + * + * multi_planner.h + * General CitusDB planner code. + * + * Copyright (c) 2012-2015, Citus Data, Inc. + *------------------------------------------------------------------------- + */ + +#ifndef MULTI_PLANNER_H +#define MULTI_PLANNER_H + +#include "nodes/plannodes.h" +#include "nodes/relation.h" + +extern PlannedStmt *multi_planner(Query *parse, int cursorOptions, + ParamListInfo boundParams); + +extern bool HasCitusToplevelNode(PlannedStmt *planStatement); +struct MultiPlan; +extern struct MultiPlan * GetMultiPlan(PlannedStmt *planStatement); + +#endif /* MULTI_PLANNER_H */ diff --git a/src/include/distributed/multi_resowner.h b/src/include/distributed/multi_resowner.h new file mode 100644 index 000000000..195e2d9f0 --- /dev/null +++ b/src/include/distributed/multi_resowner.h @@ -0,0 +1,21 @@ +/*------------------------------------------------------------------------- + * + * multi_resowner.h + * CitusDB resource owner integration. + * + * Copyright (c) 2012-2015, Citus Data, Inc. + *------------------------------------------------------------------------- + */ +#ifndef MULTI_RESOWNER_H +#define MULTI_RESOWNER_H + +#include "utils/resowner.h" + +/* resowner functions for temporary job directory management */ +extern void ResourceOwnerEnlargeJobDirectories(ResourceOwner owner); +extern void ResourceOwnerRememberJobDirectory(ResourceOwner owner, + uint64 jobId); +extern void ResourceOwnerForgetJobDirectory(ResourceOwner owner, + uint64 jobId); + +#endif /* MULTI_RESOWNER_H */ diff --git a/src/include/distributed/multi_router_executor.h b/src/include/distributed/multi_router_executor.h new file mode 100644 index 000000000..b2400071e --- /dev/null +++ b/src/include/distributed/multi_router_executor.h @@ -0,0 +1,26 @@ +/* + * multi_router_executor.h + * + * Function declarations used in executing distributed execution + * plan. + * + */ + +#ifndef MULTI_ROUTER_EXECUTOR_H_ +#define MULTI_ROUTER_EXECUTOR_H_ + +#include "distributed/multi_physical_planner.h" +#include "executor/execdesc.h" + +extern bool AllModificationsCommutative; + + +extern void RouterExecutorStart(QueryDesc *queryDesc, int eflags, Task *task); +extern void RouterExecutorRun(QueryDesc *queryDesc, ScanDirection direction, long count, + Task *task); +extern bool ExecuteTaskAndStoreResults(Task *task, TupleDesc tupleDescriptor, + Tuplestorestate *tupleStore); +extern void RouterExecutorFinish(QueryDesc *queryDesc); +extern void RouterExecutorEnd(QueryDesc *queryDesc); + +#endif /* MULTI_ROUTER_EXECUTOR_H_ */ diff --git a/src/include/distributed/multi_server_executor.h b/src/include/distributed/multi_server_executor.h new file mode 100644 index 000000000..83105cc54 --- /dev/null +++ b/src/include/distributed/multi_server_executor.h @@ -0,0 +1,212 @@ +/*------------------------------------------------------------------------- + * + * multi_server_executor.h + * Type and function declarations for executing remote jobs from a backend; + * the ensemble of these jobs form the distributed execution plan. + * + * Copyright (c) 2012, Citus Data, Inc. + * + * $Id$ + * + *------------------------------------------------------------------------- + */ + +#ifndef MULTI_SERVER_EXECUTOR_H +#define MULTI_SERVER_EXECUTOR_H + +#include "distributed/multi_physical_planner.h" +#include "distributed/task_tracker.h" +#include "distributed/worker_manager.h" + + +#define MAX_TASK_EXECUTION_FAILURES 3 /* allowed failure count for one task */ +#define MAX_TRACKER_FAILURE_COUNT 3 /* allowed failure count for one tracker */ +#define REMOTE_NODE_CONNECT_TIMEOUT 4000 /* async connect timeout in ms */ +#define RESERVED_FD_COUNT 64 /* file descriptors unavailable to executor */ + +/* copy out query results */ +#define COPY_QUERY_TO_STDOUT_TEXT "COPY (%s) TO STDOUT" +#define COPY_QUERY_TO_STDOUT_BINARY "COPY (%s) TO STDOUT WITH (FORMAT binary)" +#define COPY_QUERY_TO_FILE_TEXT "COPY (%s) TO '%s'" +#define COPY_QUERY_TO_FILE_BINARY "COPY (%s) TO '%s' WITH (FORMAT binary)" + +/* Task tracker executor related defines */ +#define TASK_ASSIGNMENT_QUERY "SELECT task_tracker_assign_task \ + ("UINT64_FORMAT", %u, %s)" +#define TASK_STATUS_QUERY "SELECT task_tracker_task_status("UINT64_FORMAT", %u)" +#define JOB_CLEANUP_QUERY "SELECT task_tracker_cleanup_job("UINT64_FORMAT")" +#define JOB_CLEANUP_TASK_ID INT_MAX + + +/* Enumeration to track one task's execution status */ +typedef enum +{ + EXEC_TASK_INVALID_FIRST = 0, + EXEC_TASK_CONNECT_START = 1, + EXEC_TASK_CONNECT_POLL = 2, + EXEC_TASK_FAILED = 3, + EXEC_FETCH_TASK_LOOP = 4, + EXEC_FETCH_TASK_START = 5, + EXEC_FETCH_TASK_RUNNING = 6, + EXEC_COMPUTE_TASK_START = 7, + EXEC_COMPUTE_TASK_RUNNING = 8, + EXEC_COMPUTE_TASK_COPYING = 9, + EXEC_TASK_DONE = 10, + + /* used for task tracker executor */ + EXEC_TASK_UNASSIGNED = 11, + EXEC_TASK_QUEUED = 12, + EXEC_TASK_TRACKER_RETRY = 13, + EXEC_TASK_TRACKER_FAILED = 14, + EXEC_SOURCE_TASK_TRACKER_RETRY = 15, + EXEC_SOURCE_TASK_TRACKER_FAILED = 16 + +} TaskExecStatus; + + +/* Enumeration to track file transmits to the master node */ +typedef enum +{ + EXEC_TRANSMIT_INVALID_FIRST = 0, + EXEC_TRANSMIT_UNASSIGNED = 1, + EXEC_TRANSMIT_QUEUED = 2, + EXEC_TRANSMIT_COPYING = 3, + EXEC_TRANSMIT_TRACKER_RETRY = 4, + EXEC_TRANSMIT_TRACKER_FAILED = 5, + EXEC_TRANSMIT_DONE = 6 + +} TransmitExecStatus; + + +/* Enumeration to track a task tracker's connection status */ +typedef enum +{ + TRACKER_STATUS_INVALID_FIRST = 0, + TRACKER_CONNECT_START = 1, + TRACKER_CONNECT_POLL = 2, + TRACKER_CONNECTED = 3, + TRACKER_CONNECTION_FAILED = 4 + +} TrackerStatus; + + +/* Enumeration that represents distributed executor types */ +typedef enum +{ + MULTI_EXECUTOR_INVALID_FIRST = 0, + MULTI_EXECUTOR_REAL_TIME = 1, + MULTI_EXECUTOR_TASK_TRACKER = 2, + MULTI_EXECUTOR_ROUTER = 3 + +} MultiExecutorType; + + +/* Enumeration that represents a (dis)connect action taken */ +typedef enum +{ + CONNECT_ACTION_NONE = 0, + CONNECT_ACTION_OPENED = 1, + CONNECT_ACTION_CLOSED = 2 + +} ConnectAction; + + +/* + * TaskExecution holds state that relates to a task's execution. In the case of + * the real-time executor, this struct encapsulates all information necessary to + * run the task. The task tracker executor however manages its connection logic + * elsewhere, and doesn't use connection related fields defined in here. + */ +struct TaskExecution +{ + uint64 jobId; + uint32 taskId; + + TaskExecStatus *taskStatusArray; + TransmitExecStatus *transmitStatusArray; + int32 *connectionIdArray; + int32 *fileDescriptorArray; + uint32 connectPollCount; + uint32 nodeCount; + uint32 currentNodeIndex; + uint32 querySourceNodeIndex; /* only applies to map fetch tasks */ + int32 dataFetchTaskIndex; + uint32 failureCount; + +}; + + +/* + * TrackerTaskState represents a task's execution status on a particular task + * tracker. This state augments task execution state in that it is associated + * with execution on a particular task tracker. + */ +typedef struct TrackerTaskState +{ + uint64 jobId; + uint32 taskId; + TaskStatus status; + StringInfo taskAssignmentQuery; + +} TrackerTaskState; + + +/* + * TaskTracker keeps connection and task related state for a task tracker. The + * task tracker executor then uses this state to open and manage a connection to + * the task tracker; and assign and check status of tasks over this connection. + */ +typedef struct TaskTracker +{ + uint32 workerPort; /* node's port; part of hash table key */ + char workerName[WORKER_LENGTH]; /* node's name; part of hash table key */ + TrackerStatus trackerStatus; + int32 connectionId; + uint32 connectPollCount; + uint32 connectionFailureCount; + uint32 trackerFailureCount; + + HTAB *taskStateHash; + List *assignedTaskList; + int32 currentTaskIndex; + bool connectionBusy; + TrackerTaskState *connectionBusyOnTask; + +} TaskTracker; + + +/* + * WorkerNodeState keeps state for a worker node. The real-time executor uses this to + * keep track of the number of open connections to a worker node. + */ +typedef struct WorkerNodeState +{ + uint32 workerPort; + char workerName[WORKER_LENGTH]; + uint32 openConnectionCount; + +} WorkerNodeState; + + +/* Config variable managed via guc.c */ +extern int RemoteTaskCheckInterval; +extern int MaxAssignTaskBatchSize; +extern int TaskExecutorType; +extern bool BinaryMasterCopyFormat; + + +/* Function declarations for distributed execution */ +extern void MultiRealTimeExecute(Job *job); +extern void MultiTaskTrackerExecute(Job *job); + +/* Function declarations common to more than one executor */ +extern MultiExecutorType JobExecutorType(MultiPlan *multiPlan); +extern void RemoveJobDirectory(uint64 jobId); +extern TaskExecution * InitTaskExecution(Task *task, TaskExecStatus initialStatus); +extern void CleanupTaskExecution(TaskExecution *taskExecution); +extern bool TaskExecutionFailed(TaskExecution *taskExecution); +extern void AdjustStateForFailure(TaskExecution *taskExecution); +extern int MaxMasterConnectionCount(void); + + +#endif /* MULTI_SERVER_EXECUTOR_H */ diff --git a/src/include/distributed/multi_utility.h b/src/include/distributed/multi_utility.h new file mode 100644 index 000000000..0a50b5b08 --- /dev/null +++ b/src/include/distributed/multi_utility.h @@ -0,0 +1,21 @@ +/*------------------------------------------------------------------------- + * + * multi_utility.h + * CitusDB utility hook and related functionality. + * + * Copyright (c) 2012-2015, Citus Data, Inc. + *------------------------------------------------------------------------- + */ + +#ifndef MULTI_UTILITY_H +#define MULTI_UTILITY_H + +#include "tcop/utility.h" + + +extern void multi_ProcessUtility(Node *parsetree, const char *queryString, + ProcessUtilityContext context, ParamListInfo params, + DestReceiver *dest, char *completionTag); + + +#endif /* MULTI_UTILITY_H */ diff --git a/src/include/distributed/pg_dist_partition.h b/src/include/distributed/pg_dist_partition.h new file mode 100644 index 000000000..d3db82638 --- /dev/null +++ b/src/include/distributed/pg_dist_partition.h @@ -0,0 +1,52 @@ +/*------------------------------------------------------------------------- + * + * pg_dist_partition.h + * definition of the system "remote partition" relation (pg_dist_partition). + * + * This table keeps metadata on logical tables that the user requested remote + * partitioning for (smaller physical tables that we partition data to are + * handled in another system catalog). + * + * Copyright (c) 2012-2015, Citus Data, Inc. + * + *------------------------------------------------------------------------- + */ + +#ifndef PG_DIST_PARTITION_H +#define PG_DIST_PARTITION_H + +/* ---------------- + * pg_dist_partition definition. + * ---------------- + */ +typedef struct FormData_pg_dist_partition +{ + Oid logicalrelid; /* logical relation id; references pg_class oid */ + char partmethod; /* partition method; see codes below */ + text partkey; /* partition key expression */ +} FormData_pg_dist_partition; + +/* ---------------- + * Form_pg_dist_partitions corresponds to a pointer to a tuple with + * the format of pg_dist_partitions relation. + * ---------------- + */ +typedef FormData_pg_dist_partition *Form_pg_dist_partition; + +/* ---------------- + * compiler constants for pg_dist_partitions + * ---------------- + */ +#define Natts_pg_dist_partition 3 +#define Anum_pg_dist_partition_logicalrelid 1 +#define Anum_pg_dist_partition_partmethod 2 +#define Anum_pg_dist_partition_partkey 3 + +/* valid values for partmethod include append, hash, and range */ +#define DISTRIBUTE_BY_APPEND 'a' +#define DISTRIBUTE_BY_HASH 'h' +#define DISTRIBUTE_BY_RANGE 'r' +#define REDISTRIBUTE_BY_HASH 'x' + + +#endif /* PG_DIST_PARTITION_H */ diff --git a/src/include/distributed/pg_dist_shard.h b/src/include/distributed/pg_dist_shard.h new file mode 100644 index 000000000..dfe1c86c7 --- /dev/null +++ b/src/include/distributed/pg_dist_shard.h @@ -0,0 +1,64 @@ +/*------------------------------------------------------------------------- + * + * pg_dist_shard.h + * definition of the "shard" relation (pg_dist_shard). + * + * This table maps logical tables to their remote partitions (from this point + * on, we use the terms remote partition and shard interchangeably). All changes + * concerning the creation, deletion, merging, and split of remote partitions + * reference this table. + * + * Copyright (c) 2012-2015, Citus Data, Inc. + * + *------------------------------------------------------------------------- + */ + +#ifndef PG_DIST_SHARD_H +#define PG_DIST_SHARD_H + +/* ---------------- + * pg_dist_shard definition. + * ---------------- + */ +typedef struct FormData_pg_dist_shard +{ + Oid logicalrelid; /* logical relation id; references pg_class oid */ + int64 shardid; /* global shardId representing remote partition */ + char shardstorage; /* shard storage type; see codes below */ +#ifdef CATALOG_VARLEN /* variable-length fields start here */ + text shardalias; /* user specified table name for shard, if any */ + text shardminvalue; /* partition key's minimum value in shard */ + text shardmaxvalue; /* partition key's maximum value in shard */ +#endif +} FormData_pg_dist_shard; + +/* ---------------- + * Form_pg_dist_shards corresponds to a pointer to a tuple with + * the format of pg_dist_shards relation. + * ---------------- + */ +typedef FormData_pg_dist_shard *Form_pg_dist_shard; + +/* ---------------- + * compiler constants for pg_dist_shards + * ---------------- + */ +#define Natts_pg_dist_shard 6 +#define Anum_pg_dist_shard_logicalrelid 1 +#define Anum_pg_dist_shard_shardid 2 +#define Anum_pg_dist_shard_shardstorage 3 +#define Anum_pg_dist_shard_shardalias 4 +#define Anum_pg_dist_shard_shardminvalue 5 +#define Anum_pg_dist_shard_shardmaxvalue 6 + +/* + * Valid values for shard storage types include relay file, foreign table, + * (standard) table and columnar table. Relay file types are currently unused. + */ +#define SHARD_STORAGE_RELAY 'r' +#define SHARD_STORAGE_FOREIGN 'f' +#define SHARD_STORAGE_TABLE 't' +#define SHARD_STORAGE_COLUMNAR 'c' + + +#endif /* PG_DIST_SHARD_H */ diff --git a/src/include/distributed/pg_dist_shard_placement.h b/src/include/distributed/pg_dist_shard_placement.h new file mode 100644 index 000000000..505daffa2 --- /dev/null +++ b/src/include/distributed/pg_dist_shard_placement.h @@ -0,0 +1,54 @@ +/*------------------------------------------------------------------------- + * + * pg_dist_shard_placement.h + * definition of the "server" relation (pg_dist_shard_placement). + * + * This table keeps information on remote shards and their whereabouts on the + * master node. The table's contents are updated and used as follows: (i) the + * worker nodes send periodic reports about the shards they contain, and (ii) + * the master reconciles these shard reports, and determines outdated, under- + * and over-replicated shards. + * + * Copyright (c) 2012-2015, Citus Data, Inc. + * + *------------------------------------------------------------------------- + */ + +#ifndef PG_DIST_SHARD_PLACEMENT_H +#define PG_DIST_SHARD_PLACEMENT_H + +/* ---------------- + * pg_dist_shard_placement definition. + * ---------------- + */ +typedef struct FormData_pg_dist_shard_placement +{ + int64 shardid; /* global shardId on remote node */ + int32 shardstate; /* shard state on remote node; see RelayFileState */ + int64 shardlength; /* shard length on remote node; stored as bigint */ +#ifdef CATALOG_VARLEN /* variable-length fields start here */ + text nodename; /* remote node's host name */ + int32 nodeport; /* remote node's port number */ +#endif +} FormData_pg_dist_shard_placement; + +/* ---------------- + * Form_pg_dist_shard_placement corresponds to a pointer to a tuple with + * the format of pg_dist_shard_placement relation. + * ---------------- + */ +typedef FormData_pg_dist_shard_placement *Form_pg_dist_shard_placement; + +/* ---------------- + * compiler constants for pg_dist_shard_placement + * ---------------- + */ +#define Natts_pg_dist_shard_placement 5 +#define Anum_pg_dist_shard_placement_shardid 1 +#define Anum_pg_dist_shard_placement_shardstate 2 +#define Anum_pg_dist_shard_placement_shardlength 3 +#define Anum_pg_dist_shard_placement_nodename 4 +#define Anum_pg_dist_shard_placement_nodeport 5 + + +#endif /* PG_DIST_SHARD_PLACEMENT_H */ diff --git a/src/include/distributed/relay_utility.h b/src/include/distributed/relay_utility.h new file mode 100644 index 000000000..592f61632 --- /dev/null +++ b/src/include/distributed/relay_utility.h @@ -0,0 +1,47 @@ +/*------------------------------------------------------------------------- + * + * relay_utility.h + * + * Header and type declarations that extend relation, index and constraint names + * with the appropriate shard identifiers. + * + * Copyright (c) 2012, Citus Data, Inc. + * + * $Id:$ + * + *------------------------------------------------------------------------- + */ + +#ifndef RELAY_UTILITY_H +#define RELAY_UTILITY_H + +#include "nodes/nodes.h" + + +/* Shard name and identifier related defines */ +#define SHARD_NAME_SEPARATOR '_' +#define INVALID_SHARD_ID 0 + + +/* + * RelayFileState represents last known states of shards on a given node. We + * currently only have shards in finalized or cached state; and set this state + * after shards are sucessfully staged or cached. + */ +typedef enum +{ + FILE_INVALID_FIRST = 0, + FILE_FINALIZED = 1, + FILE_CACHED = 2, + FILE_INACTIVE = 3, + FILE_TO_DELETE = 4 + +} RelayFileState; + + +/* Function declarations to extend names in DDL commands */ +extern void RelayEventExtendNames(Node *parseTree, uint64 shardId); +extern void AppendShardIdToName(char **name, uint64 shardId); + + +#endif /* RELAY_UTILITY_H */ diff --git a/src/include/distributed/resource_lock.h b/src/include/distributed/resource_lock.h new file mode 100644 index 000000000..6c1c8ffcf --- /dev/null +++ b/src/include/distributed/resource_lock.h @@ -0,0 +1,77 @@ +/*------------------------------------------------------------------------- + * + * resource_lock.h + * Locking Infrastructure for CitusDB. + * + * Copyright (c) 2012-2015, Citus Data, Inc. + *------------------------------------------------------------------------- + */ + +#ifndef RESOURCE_LOCK_H +#define RESOURCE_LOCK_H + +#include "postgres.h" /* IWYU pragma: keep */ +#include "c.h" + +#include "storage/lock.h" + + +/* + * Postgres' advisory locks use 'field4' to discern between different kind of + * advisory locks. Only 1 and 2 are used allowing us to define non-conflicting + * lock methods. + * + * In case postgres starts to use additional values, CitusDB's values + * will have to be changed. That just requires re-compiling and a restart. + */ +typedef enum AdvisoryLocktagClass +{ + /* values defined in postgres' lockfuncs.c */ + ADV_LOCKTAG_CLASS_INT64 = 1, + ADV_LOCKTAG_CLASS_INT32 = 2, + /* CitusDB lock types */ + ADV_LOCKTAG_CLASS_CITUS_SHARD_METADATA = 4, + ADV_LOCKTAG_CLASS_CITUS_SHARD = 5, + ADV_LOCKTAG_CLASS_CITUS_JOB = 6 +} AdvisoryLocktagClass; + + +/* reuse advisory lock, but with different, unused field 4 (4)*/ +#define SET_LOCKTAG_SHARD_METADATA_RESOURCE(tag, db, shardid) \ + SET_LOCKTAG_ADVISORY(tag, \ + db, \ + (uint32) ((shardid) >> 32), \ + (uint32) (shardid), \ + ADV_LOCKTAG_CLASS_CITUS_SHARD_METADATA) + +/* reuse advisory lock, but with different, unused field 4 (5)*/ +#define SET_LOCKTAG_SHARD_RESOURCE(tag, db, shardid) \ + SET_LOCKTAG_ADVISORY(tag, \ + db, \ + (uint32) ((shardid) >> 32), \ + (uint32) (shardid), \ + ADV_LOCKTAG_CLASS_CITUS_SHARD) + +/* reuse advisory lock, but with different, unused field 4 (6) */ +#define SET_LOCKTAG_JOB_RESOURCE(tag, db, jobid) \ + SET_LOCKTAG_ADVISORY(tag, \ + db, \ + (uint32) ((jobid) >> 32), \ + (uint32) (jobid), \ + ADV_LOCKTAG_CLASS_CITUS_JOB) + + +/* Lock shard/relation metadata for safe modifications */ +extern void LockShardDistributionMetadata(int64 shardId, LOCKMODE lockMode); +extern void LockRelationDistributionMetadata(Oid relationId, LOCKMODE lockMode); + +/* Lock shard data, for DML commands or remote fetches */ +extern void LockShardResource(uint64 shardId, LOCKMODE lockmode); +extern void UnlockShardResource(uint64 shardId, LOCKMODE lockmode); + +/* Lock a job schema or partition task directory */ +extern void LockJobResource(uint64 jobId, LOCKMODE lockmode); +extern void UnlockJobResource(uint64 jobId, LOCKMODE lockmode); + + +#endif /* RESOURCE_LOCK_H */ diff --git a/src/include/distributed/task_tracker.h b/src/include/distributed/task_tracker.h new file mode 100644 index 000000000..ad41b8589 --- /dev/null +++ b/src/include/distributed/task_tracker.h @@ -0,0 +1,122 @@ +/*------------------------------------------------------------------------- + * + * task_tracker.h + * + * Header and type declarations for coordinating execution of tasks and data + * source transfers on worker nodes. + * + * Copyright (c) 2012, Citus Data, Inc. + * + * $Id$ + * + *------------------------------------------------------------------------- + */ + +#ifndef TASK_TRACKER_H +#define TASK_TRACKER_H + +#include "storage/lwlock.h" +#include "utils/hsearch.h" + + +#define HIGH_PRIORITY_TASK_TIME 1 /* assignment time for high priority tasks */ +#define RESERVED_JOB_ID 1 /* reserved for cleanup and shutdown tasks */ +#define SHUTDOWN_MARKER_TASK_ID UINT_MAX /* used to identify task tracker shutdown */ +#define MAX_TASK_FAILURE_COUNT 2 /* allowed failure count for one task */ +#define LOCAL_HOST_NAME "localhost" /* connect to local backends using this name */ +#define TASK_CALL_STRING_SIZE 12288 /* max length of task call string */ +#define TEMPLATE0_NAME "template0" /* skip job schema cleanup for template0 */ +#define JOB_SCHEMA_CLEANUP "SELECT worker_cleanup_job_schema_cache()" + + +/* + * TaskStatus represents execution status of worker tasks. The assigned and + * cancel requested statuses are set by the master node; all other statuses are + * assigned by the task tracker as the worker task makes progress. + */ +typedef enum +{ + TASK_STATUS_INVALID_FIRST = 0, + TASK_ASSIGNED = 1, /* master node and task tracker */ + TASK_SCHEDULED = 2, + TASK_RUNNING = 3, + TASK_FAILED = 4, + TASK_PERMANENTLY_FAILED = 5, + TASK_SUCCEEDED = 6, + TASK_CANCEL_REQUESTED = 7, /* master node only */ + TASK_CANCELED = 8, + TASK_TO_REMOVE = 9, + + /* + * The master node's executor uses the following statuses to fully represent + * the execution status of worker tasks, as they are perceived by the master + * node. These statuses in fact don't belong with the task tracker. + */ + TASK_CLIENT_SIDE_QUEUED = 10, + TASK_CLIENT_SIDE_ASSIGN_FAILED = 11, + TASK_CLIENT_SIDE_STATUS_FAILED = 12, + TASK_FILE_TRANSMIT_QUEUED = 13, + TASK_CLIENT_SIDE_TRANSMIT_FAILED = 14, + + /* + * Add new task status types above this comment. Existing types, except for + * TASK_STATUS_LAST, should never have their numbers changed. + */ + TASK_STATUS_LAST + +} TaskStatus; + + +/* + * WorkerTask keeps shared memory state for tasks. At a high level, each worker + * task holds onto three different types of state: (a) state assigned by the + * master node, (b) state initialized by the protocol process at task assignment + * time, and (c) state internal to the task tracker process that changes as the + * task make progress. + */ +typedef struct WorkerTask +{ + uint64 jobId; /* job id (upper 32-bits reserved); part of hash table key */ + uint32 taskId; /* task id; part of hash table key */ + uint32 assignedAt; /* task assignment time in epoch seconds */ + + char taskCallString[TASK_CALL_STRING_SIZE]; /* query or function call string */ + TaskStatus taskStatus; /* task's current execution status */ + char databaseName[NAMEDATALEN]; /* name to use for local backend connection */ + int32 connectionId; /* connection id to local backend */ + uint32 failureCount; /* number of task failures */ + +} WorkerTask; + + +/* + * WorkerTasksControlData contains task tracker state shared between + * processes. + */ +typedef struct WorkerTasksSharedStateData +{ + /* Hash table shared by the task tracker and task tracker protocol functions */ + HTAB *taskHash; + /* Lock protecting workerNodesHash */ + LWLock *taskHashLock; +} WorkerTasksSharedStateData; + + +/* Config variables managed via guc.c */ +extern int TaskTrackerDelay; +extern int MaxTrackedTasksPerNode; +extern int MaxRunningTasksPerNode; + +/* State shared by the task tracker and task tracker protocol functions */ +extern WorkerTasksSharedStateData *WorkerTasksSharedState; + + +/* Function declarations local to the worker module */ +extern WorkerTask * WorkerTasksHashEnter(uint64 jobId, uint32 taskId); +extern WorkerTask * WorkerTasksHashFind(uint64 jobId, uint32 taskId); + +/* Function declarations for starting up and running the task tracker */ +extern void TaskTrackerRegister(void); + + +#endif /* TASK_TRACKER_H */ diff --git a/src/include/distributed/task_tracker_protocol.h b/src/include/distributed/task_tracker_protocol.h new file mode 100644 index 000000000..b0a6e5ecd --- /dev/null +++ b/src/include/distributed/task_tracker_protocol.h @@ -0,0 +1,28 @@ +/*------------------------------------------------------------------------- + * + * task_tracker_protocol.h + * + * Header and type declarations for assigning tasks to and removing tasks from + * the task tracker running on this node. + * + * Copyright (c) 2012, Citus Data, Inc. + * + * $Id$ + * + *------------------------------------------------------------------------- + */ + +#ifndef TASK_TRACKER_PROTOCOL_H +#define TASK_TRACKER_PROTOCOL_H + +#include "fmgr.h" + + +/* Function declarations for distributed task management */ +extern Datum task_tracker_assign_task(PG_FUNCTION_ARGS); +extern Datum task_tracker_update_data_fetch_task(PG_FUNCTION_ARGS); +extern Datum task_tracker_task_status(PG_FUNCTION_ARGS); +extern Datum task_tracker_cleanup_job(PG_FUNCTION_ARGS); + + +#endif /* TASK_TRACKER_PROTOCOL_H */ diff --git a/src/include/distributed/test_helper_functions.h b/src/include/distributed/test_helper_functions.h new file mode 100644 index 000000000..1d304bd4d --- /dev/null +++ b/src/include/distributed/test_helper_functions.h @@ -0,0 +1,73 @@ +/*------------------------------------------------------------------------- + * + * test/include/test_helper_functions.h + * + * Declarations for public functions and types related to unit testing + * functionality. + * + * Copyright (c) 2014-2015, Citus Data, Inc. + * + *------------------------------------------------------------------------- + */ + +#ifndef CITUSDB_TEST_HELPER_FUNCTIONS_H +#define CITUSDB_TEST_HELPER_FUNCTIONS_H + +#include "postgres.h" +#include "c.h" +#include "fmgr.h" + +#include "utils/array.h" + + +/* SQL statements for testing */ +#define POPULATE_TEMP_TABLE "CREATE TEMPORARY TABLE numbers " \ + "AS SELECT * FROM generate_series(1, 100);" +#define COUNT_TEMP_TABLE "SELECT COUNT(*) FROM numbers;" + + +/* function declarations for generic test functions */ +extern ArrayType * DatumArrayToArrayType(Datum *datumArray, int datumCount, + Oid datumTypeId); + +/* fake FDW for use in tests */ +extern Datum fake_fdw_handler(PG_FUNCTION_ARGS); + +/* function declarations for exercising connection functions */ +extern Datum initialize_remote_temp_table(PG_FUNCTION_ARGS); +extern Datum count_remote_temp_table_rows(PG_FUNCTION_ARGS); +extern Datum get_and_purge_connection(PG_FUNCTION_ARGS); +extern Datum set_connection_status_bad(PG_FUNCTION_ARGS); + +/* function declarations for exercising metadata functions */ +extern Datum load_shard_id_array(PG_FUNCTION_ARGS); +extern Datum load_shard_interval_array(PG_FUNCTION_ARGS); +extern Datum load_shard_placement_array(PG_FUNCTION_ARGS); +extern Datum partition_column_id(PG_FUNCTION_ARGS); +extern Datum partition_type(PG_FUNCTION_ARGS); +extern Datum is_distributed_table(PG_FUNCTION_ARGS); +extern Datum distributed_tables_exist(PG_FUNCTION_ARGS); +extern Datum column_name_to_column(PG_FUNCTION_ARGS); +extern Datum column_name_to_column_id(PG_FUNCTION_ARGS); +extern Datum create_monolithic_shard_row(PG_FUNCTION_ARGS); +extern Datum create_healthy_local_shard_placement_row(PG_FUNCTION_ARGS); +extern Datum delete_shard_placement_row(PG_FUNCTION_ARGS); +extern Datum update_shard_placement_row_state(PG_FUNCTION_ARGS); +extern Datum next_shard_id(PG_FUNCTION_ARGS); +extern Datum acquire_shared_shard_lock(PG_FUNCTION_ARGS); + +/* function declarations for exercising ddl generation functions */ +extern Datum table_ddl_command_array(PG_FUNCTION_ARGS); + +/* function declarations for exercising shard creation functions */ +extern Datum sort_names(PG_FUNCTION_ARGS); + +/* function declarations for exercising shard pruning functions */ +extern Datum prune_using_no_values(PG_FUNCTION_ARGS); +extern Datum prune_using_single_value(PG_FUNCTION_ARGS); +extern Datum prune_using_either_value(PG_FUNCTION_ARGS); +extern Datum prune_using_both_values(PG_FUNCTION_ARGS); +extern Datum debug_equality_expression(PG_FUNCTION_ARGS); + + +#endif /* CITUSDB_TEST_HELPER_FUNCTIONS_H */ diff --git a/src/include/distributed/transmit.h b/src/include/distributed/transmit.h new file mode 100644 index 000000000..88daecf3b --- /dev/null +++ b/src/include/distributed/transmit.h @@ -0,0 +1,25 @@ +/*------------------------------------------------------------------------- + * + * transmit.h + * Shared declarations for transmitting files between remote nodes. + * + * Copyright (c) 2012-2015, Citus Data, Inc. + * + *------------------------------------------------------------------------- + */ + +#ifndef TRANSMIT_H +#define TRANSMIT_H + +#include "lib/stringinfo.h" + + +/* Function declarations for transmitting files between two nodes */ +extern void ReceiveRegularFile(const char *filename); +extern void SendRegularFile(const char *filename); + +/* Function declaration local to commands and worker modules */ +extern void FreeStringInfo(StringInfo stringInfo); + + +#endif /* TRANSMIT_H */ diff --git a/src/include/distributed/worker_manager.h b/src/include/distributed/worker_manager.h new file mode 100644 index 000000000..57a38194a --- /dev/null +++ b/src/include/distributed/worker_manager.h @@ -0,0 +1,78 @@ +/*------------------------------------------------------------------------- + * + * worker_manager.h + * Header and type declarations for managing worker nodes and for placing + * shards on worker nodes in an intelligent manner. + * + * Copyright (c) 2012, Citus Data, Inc. + * + * $Id$ + * + *------------------------------------------------------------------------- + */ + +#ifndef WORKER_MANAGER_H +#define WORKER_MANAGER_H + +#include "nodes/pg_list.h" + + +/* Worker node name's maximum length */ +#define WORKER_LENGTH 256 + +/* Maximum length of worker port number (represented as string) */ +#define MAX_PORT_LENGTH 10 + +/* default filename for citusdb.worker_list_file */ +#define WORKER_LIST_FILENAME "pg_worker_list.conf" + +/* Implementation specific definitions used in finding worker nodes */ +#define WORKER_RACK_TRIES 5 +#define WORKER_DEFAULT_RACK "default" + + +/* + * WorkerNode keeps shared memory state for active and temporarily failed worker + * nodes. Permanently failed or departed nodes on the other hand are eventually + * purged from the shared hash. In the current implementation, the distinction + * between active, temporarily failed, and permanently departed nodes is made + * based on the node's presence in the membership file; only nodes in this file + * appear in the shared hash. In the future, worker nodes will report their + * health status to the master via heartbeats, and these heartbeats along with + * membership information will be used to determine a worker node's liveliness. + */ +typedef struct WorkerNode +{ + uint32 workerPort; /* node's port; part of hash table key */ + char workerName[WORKER_LENGTH]; /* node's name; part of hash table key */ + char workerRack[WORKER_LENGTH]; /* node's network location */ + + bool inWorkerFile; /* is node in current membership file? */ + +} WorkerNode; + + +/* Config variables managed via guc.c */ +extern int MaxWorkerNodesTracked; +extern char *WorkerListFileName; + + +/* Function declarations for finding worker nodes to place shards on */ +extern WorkerNode * WorkerGetCandidateNode(List *currentNodeList); +extern WorkerNode * WorkerGetRoundRobinCandidateNode(List *workerNodeList, + uint64 shardId, + uint32 placementIndex); +extern WorkerNode * WorkerGetNodeWithName(const char *hostname); +extern uint32 WorkerGetLiveNodeCount(void); +extern List * WorkerNodeList(void); +extern bool WorkerNodeActive(const char *nodeName, uint32 nodePort); +extern List * ResponsiveWorkerNodeList(void); + +/* Function declarations for loading into shared hash tables */ +extern void WorkerNodeRegister(void); +extern void LoadWorkerNodeList(const char *workerFilename); + +/* Function declarations for worker node utilities */ +extern int CompareWorkerNodes(const void *leftElement, const void *rightElement); + +#endif /* WORKER_MANAGER_H */ diff --git a/src/include/distributed/worker_protocol.h b/src/include/distributed/worker_protocol.h new file mode 100644 index 000000000..e797b7396 --- /dev/null +++ b/src/include/distributed/worker_protocol.h @@ -0,0 +1,174 @@ +/*------------------------------------------------------------------------- + * + * worker_protocol.h + * Header for shared declarations that are used for caching remote resources + * on worker nodes, and also for applying distributed execution primitives. + * + * Copyright (c) 2012, Citus Data, Inc. + * + * $Id$ + * + *------------------------------------------------------------------------- + */ + +#ifndef WORKER_PROTOCOL_H +#define WORKER_PROTOCOL_H + +#include "fmgr.h" +#include "lib/stringinfo.h" +#include "nodes/parsenodes.h" +#include "storage/fd.h" +#include "utils/array.h" + + +/* Number of rows to prefetch when reading data with a cursor */ +#define ROW_PREFETCH_COUNT 50 + +/* Directory, file, table name, and UDF related defines for distributed tasks */ +#define PG_JOB_CACHE_DIR "pgsql_job_cache" +#define JOB_DIRECTORY_PREFIX "job_" +#define JOB_SCHEMA_PREFIX "pg_merge_job_" +#define TASK_FILE_PREFIX "task_" +#define TASK_TABLE_PREFIX "task_" +#define TABLE_FILE_PREFIX "table_" +#define PARTITION_FILE_PREFIX "p_" +#define ATTEMPT_FILE_SUFFIX ".attempt" +#define MERGE_TABLE_SUFFIX "_merge" +#define MIN_JOB_DIRNAME_WIDTH 4 +#define MIN_TASK_FILENAME_WIDTH 6 +#define MIN_PARTITION_FILENAME_WIDTH 5 +#define FOREIGN_FILENAME_OPTION "filename" +#define CSTORE_TABLE_SIZE_FUNCTION_NAME "cstore_table_size" + +/* Defines used for fetching files and tables */ +/* the tablename in the overloaded COPY statement is the to-be-transferred file */ +#define TRANSMIT_REGULAR_COMMAND "COPY \"%s\" TO STDOUT WITH (format 'transmit')" +#define COPY_OUT_COMMAND "COPY %s TO STDOUT" +#define COPY_IN_COMMAND "COPY %s FROM '%s'" + +/* Defines that relate to fetching foreign tables */ +#define FOREIGN_CACHED_FILE_PATH "pg_foreign_file/cached/%s" +#define GET_TABLE_DDL_EVENTS "SELECT master_get_table_ddl_events('%s')" +#define SET_FOREIGN_TABLE_FILENAME "ALTER FOREIGN TABLE %s OPTIONS (SET filename '%s')" +#define FOREIGN_FILE_PATH_COMMAND "SELECT worker_foreign_file_path('%s')" +#define SET_SEARCH_PATH_COMMAND "SET search_path TO %s" +#define CREATE_TABLE_COMMAND "CREATE TABLE %s (%s)" +#define CREATE_TABLE_AS_COMMAND "CREATE TABLE %s (%s) AS (%s)" + + +/* + * RangePartitionContext keeps range re-partitioning related data. The Btree + * comparison function is set according to the partitioned column's data type. + */ +typedef struct RangePartitionContext +{ + FmgrInfo *comparisonFunction; + Datum *splitPointArray; + int32 splitPointCount; + +} RangePartitionContext; + + +/* + * HashPartitionContext keeps hash re-partitioning related data. The hashing + * function is set according to the partitioned column's data type. + */ +typedef struct HashPartitionContext +{ + FmgrInfo *hashFunction; + uint32 partitionCount; + +} HashPartitionContext; + + +/* + * A smaller version of copy.c's CopyStateData, trimmed to the elements + * necessary for re-partition jobs. While it'd be a bit nicer to share code, + * it'd require changing core postgres code. + */ +typedef struct PartialCopyStateData +{ + StringInfo fe_msgbuf; /* used for all dests during COPY TO, only for + * dest == COPY_NEW_FE in COPY FROM */ + int file_encoding; /* file or remote side's character encoding */ + bool need_transcoding; /* file encoding diff from server? */ + bool binary; /* binary format? */ + char *null_print; /* NULL marker string (server encoding!) */ + char *null_print_client; /* same converted to file encoding */ + char *delim; /* column delimiter (must be 1 byte) */ + + MemoryContext rowcontext; /* per-row evaluation context */ +} PartialCopyStateData; + +typedef struct PartialCopyStateData *PartialCopyState; + + +/* + * FileOutputStream helps buffer write operations to a file; these writes are + * then regularly flushed to the underlying file. This structure differs from + * standard file output streams in that it keeps a larger buffer, and only + * supports appending data to virtual file descriptors. + */ +typedef struct FileOutputStream +{ + File fileDescriptor; + StringInfo fileBuffer; + StringInfo filePath; + +} FileOutputStream; + + +/* Config variables managed via guc.c */ +extern int PartitionBufferSize; +extern bool ExpireCachedShards; +extern bool BinaryWorkerCopyFormat; + + +/* Function declarations local to the worker module */ +extern StringInfo JobSchemaName(uint64 jobId); +extern StringInfo TaskTableName(uint32 taskId); +extern bool JobSchemaExists(StringInfo schemaName); +extern StringInfo JobDirectoryName(uint64 jobId); +extern StringInfo TaskDirectoryName(uint64 jobId, uint32 taskId); +extern StringInfo PartitionFilename(StringInfo directoryName, uint32 partitionId); +extern bool JobDirectoryElement(const char *filename); +extern bool DirectoryExists(StringInfo directoryName); +extern void CreateDirectory(StringInfo directoryName); +extern void RemoveDirectory(StringInfo filename); +extern StringInfo InitTaskDirectory(uint64 jobId, uint32 taskId); +extern void RemoveJobSchema(StringInfo schemaName); +extern Datum * DeconstructArrayObject(ArrayType *arrayObject); +extern int32 ArrayObjectCount(ArrayType *arrayObject); +extern FmgrInfo * GetFunctionInfo(Oid typeId, Oid accessMethodId, int16 procedureId); + +/* Function declarations shared with the master planner */ +extern StringInfo TaskFilename(StringInfo directoryName, uint32 taskId); +extern List * ExecuteRemoteQuery(const char *nodeName, uint32 nodePort, + StringInfo queryString); +extern List * ColumnDefinitionList(List *columnNameList, List *columnTypeList); +extern CreateStmt * CreateStatement(RangeVar *relation, List *columnDefinitionList); +extern CopyStmt * CopyStatement(RangeVar *relation, char *sourceFilename); +extern Datum CompareCall2(FmgrInfo *funcInfo, Datum leftArgument, Datum rightArgument); + +/* Function declaration for parsing tree node */ +extern Node * ParseTreeNode(const char *ddlCommand); + +/* Function declarations for applying distributed execution primitives */ +extern Datum worker_fetch_partition_file(PG_FUNCTION_ARGS); +extern Datum worker_fetch_query_results_file(PG_FUNCTION_ARGS); +extern Datum worker_apply_shard_ddl_command(PG_FUNCTION_ARGS); +extern Datum worker_range_partition_table(PG_FUNCTION_ARGS); +extern Datum worker_hash_partition_table(PG_FUNCTION_ARGS); +extern Datum worker_merge_files_into_table(PG_FUNCTION_ARGS); +extern Datum worker_merge_files_and_run_query(PG_FUNCTION_ARGS); +extern Datum worker_cleanup_job_schema_cache(PG_FUNCTION_ARGS); + +/* Function declarations for fetching regular and foreign tables */ +extern Datum worker_fetch_foreign_file(PG_FUNCTION_ARGS); +extern Datum worker_fetch_regular_table(PG_FUNCTION_ARGS); +extern Datum worker_append_table_to_shard(PG_FUNCTION_ARGS); +extern Datum worker_foreign_file_path(PG_FUNCTION_ARGS); +extern Datum worker_find_block_local_path(PG_FUNCTION_ARGS); + + +#endif /* WORKER_PROTOCOL_H */ diff --git a/src/include/dumputils.h b/src/include/dumputils.h new file mode 100644 index 000000000..b387aa195 --- /dev/null +++ b/src/include/dumputils.h @@ -0,0 +1,73 @@ +/*------------------------------------------------------------------------- + * + * Utility routines for SQL dumping + * Basically this is stuff that is useful in both pg_dump and pg_dumpall. + * Lately it's also being used by psql and bin/scripts/ ... + * + * + * Portions Copyright (c) 1996-2014, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * src/bin/pg_dump/dumputils.h + * + *------------------------------------------------------------------------- + */ + +#ifndef DUMPUTILS_H +#define DUMPUTILS_H + +#include "libpq-fe.h" +#include "pqexpbuffer.h" + +typedef struct SimpleStringListCell +{ + struct SimpleStringListCell *next; + char val[1]; /* VARIABLE LENGTH FIELD */ +} SimpleStringListCell; + +typedef struct SimpleStringList +{ + SimpleStringListCell *head; + SimpleStringListCell *tail; +} SimpleStringList; + + +extern int quote_all_identifiers; +extern PQExpBuffer (*getLocalPQExpBuffer) (void); + +extern const char *fmtId(const char *identifier); +extern const char *fmtQualifiedId(int remoteVersion, + const char *schema, const char *id); +extern void appendStringLiteral(PQExpBuffer buf, const char *str, + int encoding, bool std_strings); +extern void appendStringLiteralConn(PQExpBuffer buf, const char *str, + PGconn *conn); +extern void appendStringLiteralDQ(PQExpBuffer buf, const char *str, + const char *dqprefix); +extern void appendByteaLiteral(PQExpBuffer buf, + const unsigned char *str, size_t length, + bool std_strings); +extern bool parsePGArray(const char *atext, char ***itemarray, int *nitems); +extern bool buildACLCommands(const char *name, const char *subname, + const char *type, const char *acls, const char *owner, + const char *prefix, int remoteVersion, + PQExpBuffer sql); +extern bool buildDefaultACLCommands(const char *type, const char *nspname, + const char *acls, const char *owner, + int remoteVersion, + PQExpBuffer sql); +extern bool processSQLNamePattern(PGconn *conn, PQExpBuffer buf, + const char *pattern, + bool have_where, bool force_escape, + const char *schemavar, const char *namevar, + const char *altnamevar, const char *visibilityrule); +extern void buildShSecLabelQuery(PGconn *conn, const char *catalog_name, + uint32 objectId, PQExpBuffer sql); +extern void emitShSecLabels(PGconn *conn, PGresult *res, + PQExpBuffer buffer, const char *target, const char *objname); +extern void set_dump_section(const char *arg, int *dumpSections); + +extern void simple_string_list_append(SimpleStringList *list, const char *val); +extern bool simple_string_list_member(SimpleStringList *list, const char *val); + +#endif /* DUMPUTILS_H */ diff --git a/src/test/regress/.gitignore b/src/test/regress/.gitignore new file mode 100644 index 000000000..7573addc9 --- /dev/null +++ b/src/test/regress/.gitignore @@ -0,0 +1,7 @@ +# Local binaries +/pg_regress + +# Generated subdirectories +/tmp_check/ +/results/ +/log/ diff --git a/src/test/regress/Makefile b/src/test/regress/Makefile new file mode 100644 index 000000000..2b9ef7078 --- /dev/null +++ b/src/test/regress/Makefile @@ -0,0 +1,74 @@ +# Makefile for tests of the CitusDB extension + +citusdb_subdir = src/test/regress +citusdb_top_builddir = ../../.. + +include $(citusdb_top_builddir)/Makefile.global + +# ensure MAJORVERSION is defined (missing in older versions) +ifndef MAJORVERSION +MAJORVERSION := $(basename $(VERSION)) +endif + +## +## CitusDB regression support +## +MULTI_INSTALLDIR=$(CURDIR)/tmp_check/install +pg_regress_multi_check = $(PERL) $(citusdb_abs_srcdir)/pg_regress_multi.pl --pgxsdir="$(pgxsdir)" --bindir="$(bindir)" --libdir="$(libdir)" --majorversion="$(MAJORVERSION)" +MULTI_REGRESS_OPTS = --inputdir=$(citusdb_abs_srcdir) $(pg_regress_locale_flags) + +# XXX: Can't actually do useful testruns against install - $libdir +# etc will point to the directory configured during postgres' +# build. We could copy the installed tree around, but that's quite +# likely to be mixed with other binaries and such... +cleandir-main: +### echo rm -rf '$(CURDIR)'/tmp_check/install +### +tempinstall-main: cleandir-main +#### mkdir -p $(MULTI_INSTALLDIR) +### $(MAKE) DESTDIR=$(MULTI_INSTALLDIR) -C $(citusdb_top_builddir) install > tmp_check/install.log 2>&1 + +# Test input and expected files. These are created by pg_regress itself, so we +# don't have a rule to create them. We do need rules to clean them however. +input_files := $(patsubst $(citusdb_abs_srcdir)/input/%.source,sql/%.sql, $(wildcard $(citusdb_abs_srcdir)/input/*.source)) +output_files := $(patsubst $(citusdb_abs_srcdir)/output/%.source,expected/%.out, $(wildcard $(citusdb_abs_srcdir)/output/*.source)) + +# have make check actually run all tests, but keep check-full as an +# intermediate, for muscle memory backward compatibility. +check: check-full +# check-full triggers all tests that ought to be run routinely +check-full: check-multi check-multi-task-tracker check-multi-binary check-worker check-multi-fdw + +# using pg_regress_multi_check unnecessarily starts up multiple nodes, which isn't needed +# for check-worker. But that's harmless besides a few cycles. +check-worker: all + $(pg_regress_multi_check) --load-extension=citusdb \ + -- $(MULTI_REGRESS_OPTS) --schedule=$(citusdb_abs_srcdir)/worker_schedule $(EXTRA_TESTS) + +check-multi: all tempinstall-main + $(pg_regress_multi_check) --load-extension=citusdb \ + -- $(MULTI_REGRESS_OPTS) --schedule=$(citusdb_abs_srcdir)/multi_schedule $(EXTRA_TESTS) + +check-multi-fdw: all tempinstall-main + $(pg_regress_multi_check) --load-extension=citusdb --load-extension=file_fdw -- \ + $(MULTI_REGRESS_OPTS) --schedule=$(citusdb_abs_srcdir)/multi_fdw_schedule $(EXTRA_TESTS) + +check-multi-hll: all tempinstall-main + $(pg_regress_multi_check) --load-extension=citusdb --load-extension=hll -- \ + $(MULTI_REGRESS_OPTS) $(EXTRA_TESTS) multi_create_table multi_master_protocol multi_stage_data multi_agg_approximate_distinct + +check-multi-task-tracker: all tempinstall-main + $(pg_regress_multi_check) --load-extension=citusdb \ + --server-option=citusdb.task_executor_type=task-tracker \ + --server-option=citusdb.task_tracker_delay=50ms \ + --server-option=citusdb.large_table_shard_count=1 \ + -- $(MULTI_REGRESS_OPTS) --schedule=$(citusdb_abs_srcdir)/multi_schedule $(EXTRA_TESTS) + +check-multi-binary: all tempinstall-main + $(pg_regress_multi_check) --load-extension=citusdb \ + --server-option=citusdb.binary_worker_copy_format=on \ + -- $(MULTI_REGRESS_OPTS) --schedule=$(citusdb_abs_srcdir)/multi_schedule $(EXTRA_TESTS) + +clean distclean maintainer-clean: + rm -f $(output_files) $(input_files) + rm -rf tmp_check/ diff --git a/src/test/regress/data/agg.data b/src/test/regress/data/agg.data new file mode 100644 index 000000000..d92c7df4d --- /dev/null +++ b/src/test/regress/data/agg.data @@ -0,0 +1,4 @@ +56 7.8 +100 99.097 +0 0.09561 +42 324.78 diff --git a/src/test/regress/data/agg_type.data b/src/test/regress/data/agg_type.data new file mode 100644 index 000000000..1cde4535c --- /dev/null +++ b/src/test/regress/data/agg_type.data @@ -0,0 +1,4 @@ +1.0 2.343 23.44 +2.0 3.544 324.4 +3.0 3.5666 2332.9 +4.5 6.34343 2332.9 diff --git a/src/test/regress/data/customer-1-10.data b/src/test/regress/data/customer-1-10.data new file mode 100644 index 000000000..7ef2c9ef6 --- /dev/null +++ b/src/test/regress/data/customer-1-10.data @@ -0,0 +1,10 @@ +1|Customer#000000001|IVhzIApeRb ot,c,E|15|25-989-741-2988|711.56|BUILDING|to the even, regular platelets. regular, ironic epitaphs nag e +2|Customer#000000002|XSTf4,NCwDVaWNe6tEgvwfmRchLXak|13|23-768-687-3665|121.65|AUTOMOBILE|l accounts. blithely ironic theodolites integrate boldly: caref +3|Customer#000000003|MG9kdTD2WBHm|1|11-719-748-3364|7498.12|AUTOMOBILE| deposits eat slyly ironic, even instructions. express foxes detect slyly. blithely even accounts abov +4|Customer#000000004|XxVSJsLAGtn|4|14-128-190-5944|2866.83|MACHINERY| requests. final, regular ideas sleep final accou +5|Customer#000000005|KvpyuHCplrB84WgAiGV6sYpZq7Tj|3|13-750-942-6364|794.47|HOUSEHOLD|n accounts will have to unwind. foxes cajole accor +6|Customer#000000006|sKZz0CsnMD7mp4Xd0YrBvx,LREYKUWAh yVn|20|30-114-968-4951|7638.57|AUTOMOBILE|tions. even deposits boost according to the slyly bold packages. final accounts cajole requests. furious +7|Customer#000000007|TcGe5gaZNgVePxU5kRrvXBfkasDTea|18|28-190-982-9759|9561.95|AUTOMOBILE|ainst the ironic, express theodolites. express, even pinto beans among the exp +8|Customer#000000008|I0B10bB0AymmC, 0PrRYBCP1yGJ8xcBPmWhl5|17|27-147-574-9335|6819.74|BUILDING|among the slyly regular theodolites kindle blithely courts. carefully even theodolites haggle slyly along the ide +9|Customer#000000009|xKiAFTjUsCuxfeleNqefumTrjS|8|18-338-906-3675|8324.07|FURNITURE|r theodolites according to the requests wake thinly excuses: pending requests haggle furiousl +10|Customer#000000010|6LrEaV6KR6PLVcgl2ArL Q3rqzLzcT1 v2|5|15-741-346-9870|2753.54|HOUSEHOLD|es regular deposits haggle. fur diff --git a/src/test/regress/data/customer-1-15.data b/src/test/regress/data/customer-1-15.data new file mode 100644 index 000000000..ad81215ef --- /dev/null +++ b/src/test/regress/data/customer-1-15.data @@ -0,0 +1,15 @@ +1|Customer#000000001|IVhzIApeRb ot,c,E|15|25-989-741-2988|711.56|BUILDING|to the even, regular platelets. regular, ironic epitaphs nag e +2|Customer#000000002|XSTf4,NCwDVaWNe6tEgvwfmRchLXak|13|23-768-687-3665|121.65|AUTOMOBILE|l accounts. blithely ironic theodolites integrate boldly: caref +3|Customer#000000003|MG9kdTD2WBHm|1|11-719-748-3364|7498.12|AUTOMOBILE| deposits eat slyly ironic, even instructions. express foxes detect slyly. blithely even accounts abov +4|Customer#000000004|XxVSJsLAGtn|4|14-128-190-5944|2866.83|MACHINERY| requests. final, regular ideas sleep final accou +5|Customer#000000005|KvpyuHCplrB84WgAiGV6sYpZq7Tj|3|13-750-942-6364|794.47|HOUSEHOLD|n accounts will have to unwind. foxes cajole accor +6|Customer#000000006|sKZz0CsnMD7mp4Xd0YrBvx,LREYKUWAh yVn|20|30-114-968-4951|7638.57|AUTOMOBILE|tions. even deposits boost according to the slyly bold packages. final accounts cajole requests. furious +7|Customer#000000007|TcGe5gaZNgVePxU5kRrvXBfkasDTea|18|28-190-982-9759|9561.95|AUTOMOBILE|ainst the ironic, express theodolites. express, even pinto beans among the exp +8|Customer#000000008|I0B10bB0AymmC, 0PrRYBCP1yGJ8xcBPmWhl5|17|27-147-574-9335|6819.74|BUILDING|among the slyly regular theodolites kindle blithely courts. carefully even theodolites haggle slyly along the ide +9|Customer#000000009|xKiAFTjUsCuxfeleNqefumTrjS|8|18-338-906-3675|8324.07|FURNITURE|r theodolites according to the requests wake thinly excuses: pending requests haggle furiousl +10|Customer#000000010|6LrEaV6KR6PLVcgl2ArL Q3rqzLzcT1 v2|5|15-741-346-9870|2753.54|HOUSEHOLD|es regular deposits haggle. fur +11|Customer#000000011|PkWS 3HlXqwTuzrKg633BEi|23|33-464-151-3439|-272.60|BUILDING|ckages. requests sleep slyly. quickly even pinto beans promise above the slyly regular pinto beans. +12|Customer#000000012|9PWKuhzT4Zr1Q|13|23-791-276-1263|3396.49|HOUSEHOLD| to the carefully final braids. blithely regular requests nag. ironic theodolites boost quickly along +13|Customer#000000013|nsXQu0oVjD7PM659uC3SRSp|3|13-761-547-5974|3857.34|BUILDING|ounts sleep carefully after the close frays. carefully bold notornis use ironic requests. blithely +14|Customer#000000014|KXkletMlL2JQEA |1|11-845-129-3851|5266.30|FURNITURE|, ironic packages across the unus +15|Customer#000000015|YtWggXoOLdwdo7b0y,BZaGUQMLJMX1Y,EC,6Dn|23|33-687-542-7601|2788.52|HOUSEHOLD| platelets. regular deposits detect asymptotes. blithely unusual packages nag slyly at the fluf diff --git a/src/test/regress/data/customer-1-20.data b/src/test/regress/data/customer-1-20.data new file mode 100644 index 000000000..e6469e20b --- /dev/null +++ b/src/test/regress/data/customer-1-20.data @@ -0,0 +1,21 @@ +1|Customer#000000001|IVhzIApeRb ot,c,E|15|25-989-741-2988|711.56|BUILDING|to the even, regular platelets. regular, ironic epitaphs nag e +2|Customer#000000002|XSTf4,NCwDVaWNe6tEgvwfmRchLXak|13|23-768-687-3665|121.65|AUTOMOBILE|l accounts. blithely ironic theodolites integrate boldly: caref +3|Customer#000000003|MG9kdTD2WBHm|1|11-719-748-3364|7498.12|AUTOMOBILE| deposits eat slyly ironic, even instructions. express foxes detect slyly. blithely even accounts abov +4|Customer#000000004|XxVSJsLAGtn|4|14-128-190-5944|2866.83|MACHINERY| requests. final, regular ideas sleep final accou +5|Customer#000000005|KvpyuHCplrB84WgAiGV6sYpZq7Tj|3|13-750-942-6364|794.47|HOUSEHOLD|n accounts will have to unwind. foxes cajole accor +6|Customer#000000006|sKZz0CsnMD7mp4Xd0YrBvx,LREYKUWAh yVn|20|30-114-968-4951|7638.57|AUTOMOBILE|tions. even deposits boost according to the slyly bold packages. final accounts cajole requests. furious +7|Customer#000000007|TcGe5gaZNgVePxU5kRrvXBfkasDTea|18|28-190-982-9759|9561.95|AUTOMOBILE|ainst the ironic, express theodolites. express, even pinto beans among the exp +8|Customer#000000008|I0B10bB0AymmC, 0PrRYBCP1yGJ8xcBPmWhl5|17|27-147-574-9335|6819.74|BUILDING|among the slyly regular theodolites kindle blithely courts. carefully even theodolites haggle slyly along the ide +9|Customer#000000009|xKiAFTjUsCuxfeleNqefumTrjS|8|18-338-906-3675|8324.07|FURNITURE|r theodolites according to the requests wake thinly excuses: pending requests haggle furiousl +10|Customer#000000010|6LrEaV6KR6PLVcgl2ArL Q3rqzLzcT1 v2|5|15-741-346-9870|2753.54|HOUSEHOLD|es regular deposits haggle. fur +11|Customer#000000011|PkWS 3HlXqwTuzrKg633BEi|23|33-464-151-3439|-272.60|BUILDING|ckages. requests sleep slyly. quickly even pinto beans promise above the slyly regular pinto beans. +12|Customer#000000012|9PWKuhzT4Zr1Q|13|23-791-276-1263|3396.49|HOUSEHOLD| to the carefully final braids. blithely regular requests nag. ironic theodolites boost quickly along +13|Customer#000000013|nsXQu0oVjD7PM659uC3SRSp|3|13-761-547-5974|3857.34|BUILDING|ounts sleep carefully after the close frays. carefully bold notornis use ironic requests. blithely +14|Customer#000000014|KXkletMlL2JQEA |1|11-845-129-3851|5266.30|FURNITURE|, ironic packages across the unus +15|Customer#000000015|YtWggXoOLdwdo7b0y,BZaGUQMLJMX1Y,EC,6Dn|23|33-687-542-7601|2788.52|HOUSEHOLD| platelets. regular deposits detect asymptotes. blithely unusual packages nag slyly at the fluf +15|Customer#000000015|YtWggXoOLdwdo7b0y,BZaGUQMLJMX1Y,EC,6Dn|23|33-687-542-7601|2788.52|HOUSEHOLD| platelets. regular deposits detect asymptotes. blithely unusual packages nag slyly at the fluf +16|Customer#000000016|cYiaeMLZSMAOQ2 d0W,|10|20-781-609-3107|4681.03|FURNITURE|kly silent courts. thinly regular theodolites sleep fluffily after +17|Customer#000000017|izrh 6jdqtp2eqdtbkswDD8SG4SzXruMfIXyR7|2|12-970-682-3487|6.34|AUTOMOBILE|packages wake! blithely even pint +18|Customer#000000018|3txGO AiuFux3zT0Z9NYaFRnZt|6|16-155-215-1315|5494.43|BUILDING|s sleep. carefully even instructions nag furiously alongside of t +19|Customer#000000019|uc,3bHIx84H,wdrmLOjVsiqXCq2tr|18|28-396-526-5053|8914.71|HOUSEHOLD| nag. furiously careful packages are slyly at the accounts. furiously regular in +20|Customer#000000020|JrPk8Pqplj4Ne|22|32-957-234-8742|7603.40|FURNITURE|g alongside of the special excuses-- fluffily enticing packages wake diff --git a/src/test/regress/data/customer-1-30.data b/src/test/regress/data/customer-1-30.data new file mode 100644 index 000000000..fc2717aa2 --- /dev/null +++ b/src/test/regress/data/customer-1-30.data @@ -0,0 +1,30 @@ +1|Customer#000000001|IVhzIApeRb ot,c,E|15|25-989-741-2988|711.56|BUILDING|to the even, regular platelets. regular, ironic epitaphs nag e +2|Customer#000000002|XSTf4,NCwDVaWNe6tEgvwfmRchLXak|13|23-768-687-3665|121.65|AUTOMOBILE|l accounts. blithely ironic theodolites integrate boldly: caref +3|Customer#000000003|MG9kdTD2WBHm|1|11-719-748-3364|7498.12|AUTOMOBILE| deposits eat slyly ironic, even instructions. express foxes detect slyly. blithely even accounts abov +4|Customer#000000004|XxVSJsLAGtn|4|14-128-190-5944|2866.83|MACHINERY| requests. final, regular ideas sleep final accou +5|Customer#000000005|KvpyuHCplrB84WgAiGV6sYpZq7Tj|3|13-750-942-6364|794.47|HOUSEHOLD|n accounts will have to unwind. foxes cajole accor +6|Customer#000000006|sKZz0CsnMD7mp4Xd0YrBvx,LREYKUWAh yVn|20|30-114-968-4951|7638.57|AUTOMOBILE|tions. even deposits boost according to the slyly bold packages. final accounts cajole requests. furious +7|Customer#000000007|TcGe5gaZNgVePxU5kRrvXBfkasDTea|18|28-190-982-9759|9561.95|AUTOMOBILE|ainst the ironic, express theodolites. express, even pinto beans among the exp +8|Customer#000000008|I0B10bB0AymmC, 0PrRYBCP1yGJ8xcBPmWhl5|17|27-147-574-9335|6819.74|BUILDING|among the slyly regular theodolites kindle blithely courts. carefully even theodolites haggle slyly along the ide +9|Customer#000000009|xKiAFTjUsCuxfeleNqefumTrjS|8|18-338-906-3675|8324.07|FURNITURE|r theodolites according to the requests wake thinly excuses: pending requests haggle furiousl +10|Customer#000000010|6LrEaV6KR6PLVcgl2ArL Q3rqzLzcT1 v2|5|15-741-346-9870|2753.54|HOUSEHOLD|es regular deposits haggle. fur +11|Customer#000000011|PkWS 3HlXqwTuzrKg633BEi|23|33-464-151-3439|-272.60|BUILDING|ckages. requests sleep slyly. quickly even pinto beans promise above the slyly regular pinto beans. +12|Customer#000000012|9PWKuhzT4Zr1Q|13|23-791-276-1263|3396.49|HOUSEHOLD| to the carefully final braids. blithely regular requests nag. ironic theodolites boost quickly along +13|Customer#000000013|nsXQu0oVjD7PM659uC3SRSp|3|13-761-547-5974|3857.34|BUILDING|ounts sleep carefully after the close frays. carefully bold notornis use ironic requests. blithely +14|Customer#000000014|KXkletMlL2JQEA |1|11-845-129-3851|5266.30|FURNITURE|, ironic packages across the unus +15|Customer#000000015|YtWggXoOLdwdo7b0y,BZaGUQMLJMX1Y,EC,6Dn|23|33-687-542-7601|2788.52|HOUSEHOLD| platelets. regular deposits detect asymptotes. blithely unusual packages nag slyly at the fluf +16|Customer#000000016|cYiaeMLZSMAOQ2 d0W,|10|20-781-609-3107|4681.03|FURNITURE|kly silent courts. thinly regular theodolites sleep fluffily after +17|Customer#000000017|izrh 6jdqtp2eqdtbkswDD8SG4SzXruMfIXyR7|2|12-970-682-3487|6.34|AUTOMOBILE|packages wake! blithely even pint +18|Customer#000000018|3txGO AiuFux3zT0Z9NYaFRnZt|6|16-155-215-1315|5494.43|BUILDING|s sleep. carefully even instructions nag furiously alongside of t +19|Customer#000000019|uc,3bHIx84H,wdrmLOjVsiqXCq2tr|18|28-396-526-5053|8914.71|HOUSEHOLD| nag. furiously careful packages are slyly at the accounts. furiously regular in +20|Customer#000000020|JrPk8Pqplj4Ne|22|32-957-234-8742|7603.40|FURNITURE|g alongside of the special excuses-- fluffily enticing packages wake +21|Customer#000000021|XYmVpr9yAHDEn|8|18-902-614-8344|1428.25|MACHINERY| quickly final accounts integrate blithely furiously u +22|Customer#000000022|QI6p41,FNs5k7RZoCCVPUTkUdYpB|3|13-806-545-9701|591.98|MACHINERY|s nod furiously above the furiously ironic ideas. +23|Customer#000000023|OdY W13N7Be3OC5MpgfmcYss0Wn6TKT|3|13-312-472-8245|3332.02|HOUSEHOLD|deposits. special deposits cajole slyly. fluffily special deposits about the furiously +24|Customer#000000024|HXAFgIAyjxtdqwimt13Y3OZO 4xeLe7U8PqG|13|23-127-851-8031|9255.67|MACHINERY|into beans. fluffily final ideas haggle fluffily +25|Customer#000000025|Hp8GyFQgGHFYSilH5tBfe|12|22-603-468-3533|7133.70|FURNITURE|y. accounts sleep ruthlessly according to the regular theodolites. unusual instructions sleep. ironic, final +26|Customer#000000026|8ljrc5ZeMl7UciP|22|32-363-455-4837|5182.05|AUTOMOBILE|c requests use furiously ironic requests. slyly ironic dependencies us +27|Customer#000000027|IS8GIyxpBrLpMT0u7|3|13-137-193-2709|5679.84|BUILDING| about the carefully ironic pinto beans. accoun +28|Customer#000000028|iVyg0daQ,Tha8x2WPWA9m2529m|8|18-774-241-1462|1007.18|FURNITURE| along the regular deposits. furiously final pac +29|Customer#000000029|sJ5adtfyAkCK63df2,vF25zyQMVYE34uh|0|10-773-203-7342|7618.27|FURNITURE|its after the carefully final platelets x-ray against +30|Customer#000000030|nJDsELGAavU63Jl0c5NKsKfL8rIJQQkQnYL2QJY|1|11-764-165-5076|9321.01|BUILDING|lithely final requests. furiously unusual account diff --git a/src/test/regress/data/customer-11-20.data b/src/test/regress/data/customer-11-20.data new file mode 100644 index 000000000..3ff2e8e3d --- /dev/null +++ b/src/test/regress/data/customer-11-20.data @@ -0,0 +1,10 @@ +11|Customer#000000011|PkWS 3HlXqwTuzrKg633BEi|23|33-464-151-3439|-272.60|BUILDING|ckages. requests sleep slyly. quickly even pinto beans promise above the slyly regular pinto beans. +12|Customer#000000012|9PWKuhzT4Zr1Q|13|23-791-276-1263|3396.49|HOUSEHOLD| to the carefully final braids. blithely regular requests nag. ironic theodolites boost quickly along +13|Customer#000000013|nsXQu0oVjD7PM659uC3SRSp|3|13-761-547-5974|3857.34|BUILDING|ounts sleep carefully after the close frays. carefully bold notornis use ironic requests. blithely +14|Customer#000000014|KXkletMlL2JQEA |1|11-845-129-3851|5266.30|FURNITURE|, ironic packages across the unus +15|Customer#000000015|YtWggXoOLdwdo7b0y,BZaGUQMLJMX1Y,EC,6Dn|23|33-687-542-7601|2788.52|HOUSEHOLD| platelets. regular deposits detect asymptotes. blithely unusual packages nag slyly at the fluf +16|Customer#000000016|cYiaeMLZSMAOQ2 d0W,|10|20-781-609-3107|4681.03|FURNITURE|kly silent courts. thinly regular theodolites sleep fluffily after +17|Customer#000000017|izrh 6jdqtp2eqdtbkswDD8SG4SzXruMfIXyR7|2|12-970-682-3487|6.34|AUTOMOBILE|packages wake! blithely even pint +18|Customer#000000018|3txGO AiuFux3zT0Z9NYaFRnZt|6|16-155-215-1315|5494.43|BUILDING|s sleep. carefully even instructions nag furiously alongside of t +19|Customer#000000019|uc,3bHIx84H,wdrmLOjVsiqXCq2tr|18|28-396-526-5053|8914.71|HOUSEHOLD| nag. furiously careful packages are slyly at the accounts. furiously regular in +20|Customer#000000020|JrPk8Pqplj4Ne|22|32-957-234-8742|7603.40|FURNITURE|g alongside of the special excuses-- fluffily enticing packages wake diff --git a/src/test/regress/data/customer-21-30.data b/src/test/regress/data/customer-21-30.data new file mode 100644 index 000000000..16a711675 --- /dev/null +++ b/src/test/regress/data/customer-21-30.data @@ -0,0 +1,10 @@ +21|Customer#000000021|XYmVpr9yAHDEn|8|18-902-614-8344|1428.25|MACHINERY| quickly final accounts integrate blithely furiously u +22|Customer#000000022|QI6p41,FNs5k7RZoCCVPUTkUdYpB|3|13-806-545-9701|591.98|MACHINERY|s nod furiously above the furiously ironic ideas. +23|Customer#000000023|OdY W13N7Be3OC5MpgfmcYss0Wn6TKT|3|13-312-472-8245|3332.02|HOUSEHOLD|deposits. special deposits cajole slyly. fluffily special deposits about the furiously +24|Customer#000000024|HXAFgIAyjxtdqwimt13Y3OZO 4xeLe7U8PqG|13|23-127-851-8031|9255.67|MACHINERY|into beans. fluffily final ideas haggle fluffily +25|Customer#000000025|Hp8GyFQgGHFYSilH5tBfe|12|22-603-468-3533|7133.70|FURNITURE|y. accounts sleep ruthlessly according to the regular theodolites. unusual instructions sleep. ironic, final +26|Customer#000000026|8ljrc5ZeMl7UciP|22|32-363-455-4837|5182.05|AUTOMOBILE|c requests use furiously ironic requests. slyly ironic dependencies us +27|Customer#000000027|IS8GIyxpBrLpMT0u7|3|13-137-193-2709|5679.84|BUILDING| about the carefully ironic pinto beans. accoun +28|Customer#000000028|iVyg0daQ,Tha8x2WPWA9m2529m|8|18-774-241-1462|1007.18|FURNITURE| along the regular deposits. furiously final pac +29|Customer#000000029|sJ5adtfyAkCK63df2,vF25zyQMVYE34uh|0|10-773-203-7342|7618.27|FURNITURE|its after the carefully final platelets x-ray against +30|Customer#000000030|nJDsELGAavU63Jl0c5NKsKfL8rIJQQkQnYL2QJY|1|11-764-165-5076|9321.01|BUILDING|lithely final requests. furiously unusual account diff --git a/src/test/regress/data/customer.1.data b/src/test/regress/data/customer.1.data new file mode 100644 index 000000000..9848e43ef --- /dev/null +++ b/src/test/regress/data/customer.1.data @@ -0,0 +1,1000 @@ +1|Customer#000000001|IVhzIApeRb ot,c,E|15|25-989-741-2988|711.56|BUILDING|to the even, regular platelets. regular, ironic epitaphs nag e +2|Customer#000000002|XSTf4,NCwDVaWNe6tEgvwfmRchLXak|13|23-768-687-3665|121.65|AUTOMOBILE|l accounts. blithely ironic theodolites integrate boldly: caref +3|Customer#000000003|MG9kdTD2WBHm|1|11-719-748-3364|7498.12|AUTOMOBILE| deposits eat slyly ironic, even instructions. express foxes detect slyly. blithely even accounts abov +4|Customer#000000004|XxVSJsLAGtn|4|14-128-190-5944|2866.83|MACHINERY| requests. final, regular ideas sleep final accou +5|Customer#000000005|KvpyuHCplrB84WgAiGV6sYpZq7Tj|3|13-750-942-6364|794.47|HOUSEHOLD|n accounts will have to unwind. foxes cajole accor +6|Customer#000000006|sKZz0CsnMD7mp4Xd0YrBvx,LREYKUWAh yVn|20|30-114-968-4951|7638.57|AUTOMOBILE|tions. even deposits boost according to the slyly bold packages. final accounts cajole requests. furious +7|Customer#000000007|TcGe5gaZNgVePxU5kRrvXBfkasDTea|18|28-190-982-9759|9561.95|AUTOMOBILE|ainst the ironic, express theodolites. express, even pinto beans among the exp +8|Customer#000000008|I0B10bB0AymmC, 0PrRYBCP1yGJ8xcBPmWhl5|17|27-147-574-9335|6819.74|BUILDING|among the slyly regular theodolites kindle blithely courts. carefully even theodolites haggle slyly along the ide +9|Customer#000000009|xKiAFTjUsCuxfeleNqefumTrjS|8|18-338-906-3675|8324.07|FURNITURE|r theodolites according to the requests wake thinly excuses: pending requests haggle furiousl +10|Customer#000000010|6LrEaV6KR6PLVcgl2ArL Q3rqzLzcT1 v2|5|15-741-346-9870|2753.54|HOUSEHOLD|es regular deposits haggle. fur +11|Customer#000000011|PkWS 3HlXqwTuzrKg633BEi|23|33-464-151-3439|-272.60|BUILDING|ckages. requests sleep slyly. quickly even pinto beans promise above the slyly regular pinto beans. +12|Customer#000000012|9PWKuhzT4Zr1Q|13|23-791-276-1263|3396.49|HOUSEHOLD| to the carefully final braids. blithely regular requests nag. ironic theodolites boost quickly along +13|Customer#000000013|nsXQu0oVjD7PM659uC3SRSp|3|13-761-547-5974|3857.34|BUILDING|ounts sleep carefully after the close frays. carefully bold notornis use ironic requests. blithely +14|Customer#000000014|KXkletMlL2JQEA |1|11-845-129-3851|5266.30|FURNITURE|, ironic packages across the unus +15|Customer#000000015|YtWggXoOLdwdo7b0y,BZaGUQMLJMX1Y,EC,6Dn|23|33-687-542-7601|2788.52|HOUSEHOLD| platelets. regular deposits detect asymptotes. blithely unusual packages nag slyly at the fluf +16|Customer#000000016|cYiaeMLZSMAOQ2 d0W,|10|20-781-609-3107|4681.03|FURNITURE|kly silent courts. thinly regular theodolites sleep fluffily after +17|Customer#000000017|izrh 6jdqtp2eqdtbkswDD8SG4SzXruMfIXyR7|2|12-970-682-3487|6.34|AUTOMOBILE|packages wake! blithely even pint +18|Customer#000000018|3txGO AiuFux3zT0Z9NYaFRnZt|6|16-155-215-1315|5494.43|BUILDING|s sleep. carefully even instructions nag furiously alongside of t +19|Customer#000000019|uc,3bHIx84H,wdrmLOjVsiqXCq2tr|18|28-396-526-5053|8914.71|HOUSEHOLD| nag. furiously careful packages are slyly at the accounts. furiously regular in +20|Customer#000000020|JrPk8Pqplj4Ne|22|32-957-234-8742|7603.40|FURNITURE|g alongside of the special excuses-- fluffily enticing packages wake +21|Customer#000000021|XYmVpr9yAHDEn|8|18-902-614-8344|1428.25|MACHINERY| quickly final accounts integrate blithely furiously u +22|Customer#000000022|QI6p41,FNs5k7RZoCCVPUTkUdYpB|3|13-806-545-9701|591.98|MACHINERY|s nod furiously above the furiously ironic ideas. +23|Customer#000000023|OdY W13N7Be3OC5MpgfmcYss0Wn6TKT|3|13-312-472-8245|3332.02|HOUSEHOLD|deposits. special deposits cajole slyly. fluffily special deposits about the furiously +24|Customer#000000024|HXAFgIAyjxtdqwimt13Y3OZO 4xeLe7U8PqG|13|23-127-851-8031|9255.67|MACHINERY|into beans. fluffily final ideas haggle fluffily +25|Customer#000000025|Hp8GyFQgGHFYSilH5tBfe|12|22-603-468-3533|7133.70|FURNITURE|y. accounts sleep ruthlessly according to the regular theodolites. unusual instructions sleep. ironic, final +26|Customer#000000026|8ljrc5ZeMl7UciP|22|32-363-455-4837|5182.05|AUTOMOBILE|c requests use furiously ironic requests. slyly ironic dependencies us +27|Customer#000000027|IS8GIyxpBrLpMT0u7|3|13-137-193-2709|5679.84|BUILDING| about the carefully ironic pinto beans. accoun +28|Customer#000000028|iVyg0daQ,Tha8x2WPWA9m2529m|8|18-774-241-1462|1007.18|FURNITURE| along the regular deposits. furiously final pac +29|Customer#000000029|sJ5adtfyAkCK63df2,vF25zyQMVYE34uh|0|10-773-203-7342|7618.27|FURNITURE|its after the carefully final platelets x-ray against +30|Customer#000000030|nJDsELGAavU63Jl0c5NKsKfL8rIJQQkQnYL2QJY|1|11-764-165-5076|9321.01|BUILDING|lithely final requests. furiously unusual account +31|Customer#000000031|LUACbO0viaAv6eXOAebryDB xjVst|23|33-197-837-7094|5236.89|HOUSEHOLD|s use among the blithely pending depo +32|Customer#000000032|jD2xZzi UmId,DCtNBLXKj9q0Tlp2iQ6ZcO3J|15|25-430-914-2194|3471.53|BUILDING|cial ideas. final, furious requests across the e +33|Customer#000000033|qFSlMuLucBmx9xnn5ib2csWUweg D|17|27-375-391-1280|-78.56|AUTOMOBILE|s. slyly regular accounts are furiously. carefully pending requests +34|Customer#000000034|Q6G9wZ6dnczmtOx509xgE,M2KV|15|25-344-968-5422|8589.70|HOUSEHOLD|nder against the even, pending accounts. even +35|Customer#000000035|TEjWGE4nBzJL2|17|27-566-888-7431|1228.24|HOUSEHOLD|requests. special, express requests nag slyly furiousl +36|Customer#000000036|3TvCzjuPzpJ0,DdJ8kW5U|21|31-704-669-5769|4987.27|BUILDING|haggle. enticing, quiet platelets grow quickly bold sheaves. carefully regular acc +37|Customer#000000037|7EV4Pwh,3SboctTWt|8|18-385-235-7162|-917.75|FURNITURE|ilent packages are carefully among the deposits. furiousl +38|Customer#000000038|a5Ee5e9568R8RLP 2ap7|12|22-306-880-7212|6345.11|HOUSEHOLD|lar excuses. closely even asymptotes cajole blithely excuses. carefully silent pinto beans sleep carefully fin +39|Customer#000000039|nnbRg,Pvy33dfkorYE FdeZ60|2|12-387-467-6509|6264.31|AUTOMOBILE|tions. slyly silent excuses slee +40|Customer#000000040|gOnGWAyhSV1ofv|3|13-652-915-8939|1335.30|BUILDING|rges impress after the slyly ironic courts. foxes are. blithely +41|Customer#000000041|IM9mzmyoxeBmvNw8lA7G3Ydska2nkZF|10|20-917-711-4011|270.95|HOUSEHOLD|ly regular accounts hang bold, silent packages. unusual foxes haggle slyly above the special, final depo +42|Customer#000000042|ziSrvyyBke|5|15-416-330-4175|8727.01|BUILDING|ssly according to the pinto beans: carefully special requests across the even, pending accounts wake special +43|Customer#000000043|ouSbjHk8lh5fKX3zGso3ZSIj9Aa3PoaFd|19|29-316-665-2897|9904.28|MACHINERY|ial requests: carefully pending foxes detect quickly. carefully final courts cajole quickly. carefully +44|Customer#000000044|Oi,dOSPwDu4jo4x,,P85E0dmhZGvNtBwi|16|26-190-260-5375|7315.94|AUTOMOBILE|r requests around the unusual, bold a +45|Customer#000000045|4v3OcpFgoOmMG,CbnF,4mdC|9|19-715-298-9917|9983.38|AUTOMOBILE|nto beans haggle slyly alongside of t +46|Customer#000000046|eaTXWWm10L9|6|16-357-681-2007|5744.59|AUTOMOBILE|ctions. accounts sleep furiously even requests. regular, regular accounts cajole blithely around the final pa +47|Customer#000000047|b0UgocSqEW5 gdVbhNT|2|12-427-271-9466|274.58|BUILDING|ions. express, ironic instructions sleep furiously ironic ideas. furi +48|Customer#000000048|0UU iPhBupFvemNB|0|10-508-348-5882|3792.50|BUILDING|re fluffily pending foxes. pending, bold platelets sleep slyly. even platelets cajo +49|Customer#000000049|cNgAeX7Fqrdf7HQN9EwjUa4nxT,68L FKAxzl|10|20-908-631-4424|4573.94|FURNITURE|nusual foxes! fluffily pending packages maintain to the regular +50|Customer#000000050|9SzDYlkzxByyJ1QeTI o|6|16-658-112-3221|4266.13|MACHINERY|ts. furiously ironic accounts cajole furiously slyly ironic dinos. +51|Customer#000000051|uR,wEaiTvo4|12|22-344-885-4251|855.87|FURNITURE|eposits. furiously regular requests integrate carefully packages. furious +52|Customer#000000052|7 QOqGqqSy9jfV51BC71jcHJSD0|11|21-186-284-5998|5630.28|HOUSEHOLD|ic platelets use evenly even accounts. stealthy theodolites cajole furiou +53|Customer#000000053|HnaxHzTfFTZs8MuCpJyTbZ47Cm4wFOOgib|15|25-168-852-5363|4113.64|HOUSEHOLD|ar accounts are. even foxes are blithely. fluffily pending deposits boost +54|Customer#000000054|,k4vf 5vECGWFy,hosTE,|4|14-776-370-4745|868.90|AUTOMOBILE|sual, silent accounts. furiously express accounts cajole special deposits. final, final accounts use furi +55|Customer#000000055|zIRBR4KNEl HzaiV3a i9n6elrxzDEh8r8pDom|10|20-180-440-8525|4572.11|MACHINERY|ully unusual packages wake bravely bold packages. unusual requests boost deposits! blithely ironic packages ab +56|Customer#000000056|BJYZYJQk4yD5B|10|20-895-685-6920|6530.86|FURNITURE|. notornis wake carefully. carefully fluffy requests are furiously even accounts. slyly expre +57|Customer#000000057|97XYbsuOPRXPWU|21|31-835-306-1650|4151.93|AUTOMOBILE|ove the carefully special packages. even, unusual deposits sleep slyly pend +58|Customer#000000058|g9ap7Dk1Sv9fcXEWjpMYpBZIRUohi T|13|23-244-493-2508|6478.46|HOUSEHOLD|ideas. ironic ideas affix furiously express, final instructions. regular excuses use quickly e +59|Customer#000000059|zLOCP0wh92OtBihgspOGl4|1|11-355-584-3112|3458.60|MACHINERY|ously final packages haggle blithely after the express deposits. furiou +60|Customer#000000060|FyodhjwMChsZmUz7Jz0H|12|22-480-575-5866|2741.87|MACHINERY|latelets. blithely unusual courts boost furiously about the packages. blithely final instruct +61|Customer#000000061|9kndve4EAJxhg3veF BfXr7AqOsT39o gtqjaYE|17|27-626-559-8599|1536.24|FURNITURE|egular packages shall have to impress along the +62|Customer#000000062|upJK2Dnw13,|7|17-361-978-7059|595.61|MACHINERY|kly special dolphins. pinto beans are slyly. quickly regular accounts are furiously a +63|Customer#000000063|IXRSpVWWZraKII|21|31-952-552-9584|9331.13|AUTOMOBILE|ithely even accounts detect slyly above the fluffily ir +64|Customer#000000064|MbCeGY20kaKK3oalJD,OT|3|13-558-731-7204|-646.64|BUILDING|structions after the quietly ironic theodolites cajole be +65|Customer#000000065|RGT yzQ0y4l0H90P783LG4U95bXQFDRXbWa1sl,X|23|33-733-623-5267|8795.16|AUTOMOBILE|y final foxes serve carefully. theodolites are carefully. pending i +66|Customer#000000066|XbsEqXH1ETbJYYtA1A|22|32-213-373-5094|242.77|HOUSEHOLD|le slyly accounts. carefully silent packages benea +67|Customer#000000067|rfG0cOgtr5W8 xILkwp9fpCS8|9|19-403-114-4356|8166.59|MACHINERY|indle furiously final, even theodo +68|Customer#000000068|o8AibcCRkXvQFh8hF,7o|12|22-918-832-2411|6853.37|HOUSEHOLD| pending pinto beans impress realms. final dependencies +69|Customer#000000069|Ltx17nO9Wwhtdbe9QZVxNgP98V7xW97uvSH1prEw|9|19-225-978-5670|1709.28|HOUSEHOLD|thely final ideas around the quickly final dependencies affix carefully quickly final theodolites. final accounts c +70|Customer#000000070|mFowIuhnHjp2GjCiYYavkW kUwOjIaTCQ|22|32-828-107-2832|4867.52|FURNITURE|fter the special asymptotes. ideas after the unusual frets cajole quickly regular pinto be +71|Customer#000000071|TlGalgdXWBmMV,6agLyWYDyIz9MKzcY8gl,w6t1B|7|17-710-812-5403|-611.19|HOUSEHOLD|g courts across the regular, final pinto beans are blithely pending ac +72|Customer#000000072|putjlmskxE,zs,HqeIA9Wqu7dhgH5BVCwDwHHcf|2|12-759-144-9689|-362.86|FURNITURE|ithely final foxes sleep always quickly bold accounts. final wat +73|Customer#000000073|8IhIxreu4Ug6tt5mog4|0|10-473-439-3214|4288.50|BUILDING|usual, unusual packages sleep busily along the furiou +74|Customer#000000074|IkJHCA3ZThF7qL7VKcrU nRLl,kylf |4|14-199-862-7209|2764.43|MACHINERY|onic accounts. blithely slow packages would haggle carefully. qui +75|Customer#000000075|Dh 6jZ,cwxWLKQfRKkiGrzv6pm|18|28-247-803-9025|6684.10|AUTOMOBILE| instructions cajole even, even deposits. finally bold deposits use above the even pains. slyl +76|Customer#000000076|m3sbCvjMOHyaOofH,e UkGPtqc4|0|10-349-718-3044|5745.33|FURNITURE|pecial deposits. ironic ideas boost blithely according to the closely ironic theodolites! furiously final deposits n +77|Customer#000000077|4tAE5KdMFGD4byHtXF92vx|17|27-269-357-4674|1738.87|BUILDING|uffily silent requests. carefully ironic asymptotes among the ironic hockey players are carefully bli +78|Customer#000000078|HBOta,ZNqpg3U2cSL0kbrftkPwzX|9|19-960-700-9191|7136.97|FURNITURE|ests. blithely bold pinto beans h +79|Customer#000000079|n5hH2ftkVRwW8idtD,BmM2|15|25-147-850-4166|5121.28|MACHINERY|es. packages haggle furiously. regular, special requests poach after the quickly express ideas. blithely pending re +80|Customer#000000080|K,vtXp8qYB |0|10-267-172-7101|7383.53|FURNITURE|tect among the dependencies. bold accounts engage closely even pinto beans. ca +81|Customer#000000081|SH6lPA7JiiNC6dNTrR|20|30-165-277-3269|2023.71|BUILDING|r packages. fluffily ironic requests cajole fluffily. ironically regular theodolit +82|Customer#000000082|zhG3EZbap4c992Gj3bK,3Ne,Xn|18|28-159-442-5305|9468.34|AUTOMOBILE|s wake. bravely regular accounts are furiously. regula +83|Customer#000000083|HnhTNB5xpnSF20JBH4Ycs6psVnkC3RDf|22|32-817-154-4122|6463.51|BUILDING|ccording to the quickly bold warhorses. final, regular foxes integrate carefully. bold packages nag blithely ev +84|Customer#000000084|lpXz6Fwr9945rnbtMc8PlueilS1WmASr CB|11|21-546-818-3802|5174.71|FURNITURE|ly blithe foxes. special asymptotes haggle blithely against the furiously regular depo +85|Customer#000000085|siRerlDwiolhYR 8FgksoezycLj|5|15-745-585-8219|3386.64|FURNITURE|ronic ideas use above the slowly pendin +86|Customer#000000086|US6EGGHXbTTXPL9SBsxQJsuvy|0|10-677-951-2353|3306.32|HOUSEHOLD|quests. pending dugouts are carefully aroun +87|Customer#000000087|hgGhHVSWQl 6jZ6Ev|23|33-869-884-7053|6327.54|FURNITURE|hely ironic requests integrate according to the ironic accounts. slyly regular pla +88|Customer#000000088|wtkjBN9eyrFuENSMmMFlJ3e7jE5KXcg|16|26-516-273-2566|8031.44|AUTOMOBILE|s are quickly above the quickly ironic instructions; even requests about the carefully final deposi +89|Customer#000000089|dtR, y9JQWUO6FoJExyp8whOU|14|24-394-451-5404|1530.76|FURNITURE|counts are slyly beyond the slyly final accounts. quickly final ideas wake. r +90|Customer#000000090|QxCzH7VxxYUWwfL7|16|26-603-491-1238|7354.23|BUILDING|sly across the furiously even +91|Customer#000000091|S8OMYFrpHwoNHaGBeuS6E 6zhHGZiprw1b7 q|8|18-239-400-3677|4643.14|AUTOMOBILE|onic accounts. fluffily silent pinto beans boost blithely according to the fluffily exp +92|Customer#000000092|obP PULk2LH LqNF,K9hcbNqnLAkJVsl5xqSrY,|2|12-446-416-8471|1182.91|MACHINERY|. pinto beans hang slyly final deposits. ac +93|Customer#000000093|EHXBr2QGdh|7|17-359-388-5266|2182.52|MACHINERY|press deposits. carefully regular platelets r +94|Customer#000000094|IfVNIN9KtkScJ9dUjK3Pg5gY1aFeaXewwf|9|19-953-499-8833|5500.11|HOUSEHOLD|latelets across the bold, final requests sleep according to the fluffily bold accounts. unusual deposits amon +95|Customer#000000095|EU0xvmWvOmUUn5J,2z85DQyG7QCJ9Xq7|15|25-923-255-2929|5327.38|MACHINERY|ithely. ruthlessly final requests wake slyly alongside of the furiously silent pinto beans. even the +96|Customer#000000096|vWLOrmXhRR|8|18-422-845-1202|6323.92|AUTOMOBILE|press requests believe furiously. carefully final instructions snooze carefully. +97|Customer#000000097|OApyejbhJG,0Iw3j rd1M|17|27-588-919-5638|2164.48|AUTOMOBILE|haggle slyly. bold, special ideas are blithely above the thinly bold theo +98|Customer#000000098|7yiheXNSpuEAwbswDW|12|22-885-845-6889|-551.37|BUILDING|ages. furiously pending accounts are quickly carefully final foxes: busily pe +99|Customer#000000099|szsrOiPtCHVS97Lt|15|25-515-237-9232|4088.65|HOUSEHOLD|cajole slyly about the regular theodolites! furiously bold requests nag along the pending, regular packages. somas +100|Customer#000000100|fptUABXcmkC5Wx|20|30-749-445-4907|9889.89|FURNITURE|was furiously fluffily quiet deposits. silent, pending requests boost against +101|Customer#000000101|sMmL2rNeHDltovSm Y|2|12-514-298-3699|7470.96|MACHINERY| sleep. pending packages detect slyly ironic pack +102|Customer#000000102|UAtflJ06 fn9zBfKjInkQZlWtqaA|19|29-324-978-8538|8462.17|BUILDING|ously regular dependencies nag among the furiously express dinos. blithely final +103|Customer#000000103|8KIsQX4LJ7QMsj6DrtFtXu0nUEdV,8a|9|19-216-107-2107|2757.45|BUILDING|furiously pending notornis boost slyly around the blithely ironic ideas? final, even instructions cajole fl +104|Customer#000000104|9mcCK L7rt0SwiYtrbO88DiZS7U d7M|10|20-966-284-8065|-588.38|FURNITURE|rate carefully slyly special pla +105|Customer#000000105|4iSJe4L SPjg7kJj98Yz3z0B|10|20-793-553-6417|9091.82|MACHINERY|l pains cajole even accounts. quietly final instructi +106|Customer#000000106|xGCOEAUjUNG|1|11-751-989-4627|3288.42|MACHINERY|lose slyly. ironic accounts along the evenly regular theodolites wake about the special, final gifts. +107|Customer#000000107|Zwg64UZ,q7GRqo3zm7P1tZIRshBDz|15|25-336-529-9919|2514.15|AUTOMOBILE|counts cajole slyly. regular requests wake. furiously regular deposits about the blithely final fo +108|Customer#000000108|GPoeEvpKo1|5|15-908-619-7526|2259.38|BUILDING|refully ironic deposits sleep. regular, unusual requests wake slyly +109|Customer#000000109|OOOkYBgCMzgMQXUmkocoLb56rfrdWp2NE2c|16|26-992-422-8153|-716.10|BUILDING|es. fluffily final dependencies sleep along the blithely even pinto beans. final deposits haggle furiously furiou +110|Customer#000000110|mymPfgphaYXNYtk|10|20-893-536-2069|7462.99|AUTOMOBILE|nto beans cajole around the even, final deposits. quickly bold packages according to the furiously regular dept +111|Customer#000000111|CBSbPyOWRorloj2TBvrK9qp9tHBs|22|32-582-283-7528|6505.26|MACHINERY|ly unusual instructions detect fluffily special deposits-- theodolites nag carefully during the ironic dependencies +112|Customer#000000112|RcfgG3bO7QeCnfjqJT1|19|29-233-262-8382|2953.35|FURNITURE|rmanently unusual multipliers. blithely ruthless deposits are furiously along the +113|Customer#000000113|eaOl5UBXIvdY57rglaIzqvfPD,MYfK|12|22-302-930-4756|2912.00|BUILDING|usly regular theodolites boost furiously doggedly pending instructio +114|Customer#000000114|xAt 5f5AlFIU|14|24-805-212-7646|1027.46|FURNITURE|der the carefully express theodolites are after the packages. packages are. bli +115|Customer#000000115|0WFt1IXENmUT2BgbsB0ShVKJZt0HCBCbFl0aHc|8|18-971-699-1843|7508.92|HOUSEHOLD|sits haggle above the carefully ironic theodolite +116|Customer#000000116|yCuVxIgsZ3,qyK2rloThy3u|16|26-632-309-5792|8403.99|BUILDING|as. quickly final sauternes haggle slyly carefully even packages. brave, ironic pinto beans are above the furious +117|Customer#000000117|uNhM,PzsRA3S,5Y Ge5Npuhi|24|34-403-631-3505|3950.83|FURNITURE|affix. instructions are furiously sl +118|Customer#000000118|OVnFuHygK9wx3xpg8|18|28-639-943-7051|3582.37|AUTOMOBILE|uick packages alongside of the furiously final deposits haggle above the fluffily even foxes. blithely dogged dep +119|Customer#000000119|M1ETOIecuvH8DtM0Y0nryXfW|7|17-697-919-8406|3930.35|FURNITURE|express ideas. blithely ironic foxes thrash. special acco +120|Customer#000000120|zBNna00AEInqyO1|12|22-291-534-1571|363.75|MACHINERY| quickly. slyly ironic requests cajole blithely furiously final dependen +121|Customer#000000121|tv nCR2YKupGN73mQudO|17|27-411-990-2959|6428.32|BUILDING|uriously stealthy ideas. carefully final courts use carefully +122|Customer#000000122|yp5slqoNd26lAENZW3a67wSfXA6hTF|3|13-702-694-4520|7865.46|HOUSEHOLD| the special packages hinder blithely around the permanent requests. bold depos +123|Customer#000000123|YsOnaaER8MkvK5cpf4VSlq|5|15-817-151-1168|5897.83|BUILDING|ependencies. regular, ironic requests are fluffily regu +124|Customer#000000124|aTbyVAW5tCd,v09O|18|28-183-750-7809|1842.49|AUTOMOBILE|le fluffily even dependencies. quietly s +125|Customer#000000125|,wSZXdVR xxIIfm9s8ITyLl3kgjT6UC07GY0Y|19|29-261-996-3120|-234.12|FURNITURE|x-ray finally after the packages? regular requests c +126|Customer#000000126|ha4EHmbx3kg DYCsP6DFeUOmavtQlHhcfaqr|22|32-755-914-7592|1001.39|HOUSEHOLD|s about the even instructions boost carefully furiously ironic pearls. ruthless, +127|Customer#000000127|Xyge4DX2rXKxXyye1Z47LeLVEYMLf4Bfcj|21|31-101-672-2951|9280.71|MACHINERY|ic, unusual theodolites nod silently after the final, ironic instructions: pending r +128|Customer#000000128|AmKUMlJf2NRHcKGmKjLS|4|14-280-874-8044|-986.96|HOUSEHOLD|ing packages integrate across the slyly unusual dugouts. blithely silent ideas sublate carefully. blithely expr +129|Customer#000000129|q7m7rbMM0BpaCdmxloCgBDRCleXsXkdD8kf|7|17-415-148-7416|9127.27|HOUSEHOLD| unusual deposits boost carefully furiously silent ideas. pending accounts cajole slyly across +130|Customer#000000130|RKPx2OfZy0Vn 8wGWZ7F2EAvmMORl1k8iH|9|19-190-993-9281|5073.58|HOUSEHOLD|ix slowly. express packages along the furiously ironic requests integrate daringly deposits. fur +131|Customer#000000131|jyN6lAjb1FtH10rMC,XzlWyCBrg75|11|21-840-210-3572|8595.53|HOUSEHOLD|jole special packages. furiously final dependencies about the furiously speci +132|Customer#000000132|QM5YabAsTLp9|4|14-692-150-9717|162.57|HOUSEHOLD|uickly carefully special theodolites. carefully regular requests against the blithely unusual instructions +133|Customer#000000133|IMCuXdpIvdkYO92kgDGuyHgojcUs88p|17|27-408-997-8430|2314.67|AUTOMOBILE|t packages. express pinto beans are blithely along the unusual, even theodolites. silent packages use fu +134|Customer#000000134|sUiZ78QCkTQPICKpA9OBzkUp2FM|11|21-200-159-5932|4608.90|BUILDING|yly fluffy foxes boost final ideas. b +135|Customer#000000135|oZK,oC0 fdEpqUML|19|29-399-293-6241|8732.91|FURNITURE| the slyly final accounts. deposits cajole carefully. carefully sly packag +136|Customer#000000136|QoLsJ0v5C1IQbh,DS1|7|17-501-210-4726|-842.39|FURNITURE|ackages sleep ironic, final courts. even requests above the blithely bold requests g +137|Customer#000000137|cdW91p92rlAEHgJafqYyxf1Q|16|26-777-409-5654|7838.30|HOUSEHOLD|carefully regular theodolites use. silent dolphins cajo +138|Customer#000000138|5uyLAeY7HIGZqtu66Yn08f|5|15-394-860-4589|430.59|MACHINERY|ts doze on the busy ideas. regular +139|Customer#000000139|3ElvBwudHKL02732YexGVFVt |9|19-140-352-1403|7897.78|MACHINERY|nstructions. quickly ironic ideas are carefully. bold, +140|Customer#000000140|XRqEPiKgcETII,iOLDZp5jA|4|14-273-885-6505|9963.15|MACHINERY|ies detect slyly ironic accounts. slyly ironic theodolites hag +141|Customer#000000141|5IW,WROVnikc3l7DwiUDGQNGsLBGOL6Dc0|1|11-936-295-6204|6706.14|FURNITURE|packages nag furiously. carefully unusual accounts snooze according to the fluffily regular pinto beans. slyly spec +142|Customer#000000142|AnJ5lxtLjioClr2khl9pb8NLxG2,|9|19-407-425-2584|2209.81|AUTOMOBILE|. even, express theodolites upo +143|Customer#000000143|681r22uL452zqk 8By7I9o9enQfx0|16|26-314-406-7725|2186.50|MACHINERY|across the blithely unusual requests haggle theodo +144|Customer#000000144|VxYZ3ebhgbltnetaGjNC8qCccjYU05 fePLOno8y|1|11-717-379-4478|6417.31|MACHINERY|ges. slyly regular accounts are slyly. bold, idle reque +145|Customer#000000145|kQjHmt2kcec cy3hfMh969u|13|23-562-444-8454|9748.93|HOUSEHOLD|ests? express, express instructions use. blithely fina +146|Customer#000000146|GdxkdXG9u7iyI1,,y5tq4ZyrcEy|3|13-835-723-3223|3328.68|FURNITURE|ffily regular dinos are slyly unusual requests. slyly specia +147|Customer#000000147|6VvIwbVdmcsMzuu,C84GtBWPaipGfi7DV|18|28-803-187-4335|8071.40|AUTOMOBILE|ress packages above the blithely regular packages sleep fluffily blithely ironic accounts. +148|Customer#000000148|BhSPlEWGvIJyT9swk vCWE|11|21-562-498-6636|2135.60|HOUSEHOLD|ing to the carefully ironic requests. carefully regular dependencies about the theodolites wake furious +149|Customer#000000149|3byTHCp2mNLPigUrrq|19|29-797-439-6760|8959.65|AUTOMOBILE|al instructions haggle against the slyly bold w +150|Customer#000000150|zeoGShTjCwGPplOWFkLURrh41O0AZ8dwNEEN4 |18|28-328-564-7630|3849.48|MACHINERY|ole blithely among the furiously pending packages. furiously bold ideas wake fluffily ironic idea +151|Customer#000000151|LlyEtNEXT6kkZ,kGP46H|19|29-433-197-6339|5187.02|HOUSEHOLD|regular dugouts: blithely even dolphins cajole furiously carefull +152|Customer#000000152|PDrllSkScKLh4lr19gmUZnK|8|18-585-850-3926|1215.18|BUILDING|ously ironic accounts. furiously even accounts accord +153|Customer#000000153|kDzx11sIjjWJm1|6|16-342-316-2815|5454.26|HOUSEHOLD|promise carefully. unusual deposits x-ray. carefully regular tithes u +154|Customer#000000154|2LAlU fDHkOqbXjHHDqw1mJQNC|19|29-522-835-6914|4695.12|FURNITURE|nic packages haggle blithely across the +155|Customer#000000155|l,sSphiStMgdrxpxi|0|10-566-282-8705|5902.85|AUTOMOBILE| sleep ironic, bold requests. regular packages on the quiet dependencies +156|Customer#000000156|5OS0edX2Y6B1cf9wJNuOQWgrrZccXk9|9|19-723-913-3943|9302.95|AUTOMOBILE| regular foxes above the theodolites haggle +157|Customer#000000157|HGEouzCcFrNd nBAdsCRjsMxKOvYZdbwA7he5w9v|15|25-207-442-1556|9768.73|BUILDING| pinto beans against the carefully bold requests wake quickly alongside of the final accounts. accounts +158|Customer#000000158|2HaYxi0J1620aoI1CdFyrW,rWOy|10|20-383-680-1329|6160.95|AUTOMOBILE|ecoys. fluffily quick requests use flu +159|Customer#000000159|KotsdDO6EHnysVu922s6pjZpG,vlT|10|20-888-668-2668|2060.06|HOUSEHOLD|cingly express somas haggle above the theodolites. pinto beans use special theodolites. theodolites sleep +160|Customer#000000160|5soVQ3dOCRBWBS|13|23-428-666-4806|4363.17|MACHINERY|olites. silently ironic accounts cajole furious +161|Customer#000000161|2oRkx,NtjFUh|7|17-805-718-2449|3714.06|MACHINERY|ptotes nag carefully instructions. silent accounts are. furiously even accounts alongside +162|Customer#000000162|JE398sXZt2QuKXfJd7poNpyQFLFtth|8|18-131-101-2267|6268.99|MACHINERY|accounts along the doggedly special asymptotes boost blithely during the quickly regular theodolites. slyly +163|Customer#000000163|OgrGcOnm4whd0f|21|31-863-349-4121|2948.61|FURNITURE| nag furiously furiously final requests. slyly s +164|Customer#000000164|YDW51PBWLXLnbQlKC|4|14-565-638-9768|208.45|HOUSEHOLD|ironic, special pinto beans. ironic +165|Customer#000000165|8pc6kwBmwBdEnfVP53aqL9DM4LymC4|0|10-927-209-5601|3349.92|HOUSEHOLD| requests. final ideas cajole quickly at the special, ironic acco +166|Customer#000000166|15HWGtwoP77EJfd95HxtMSTZUelV8NOKne2|10|20-320-530-5920|2042.21|FURNITURE|the packages. blithely final packages are furiously unusual asymptotes. regular frets promise carefully u +167|Customer#000000167|QNc2eOlRIzL6jpthwgDuB866uCIUPiOX|5|15-288-395-5501|1468.09|AUTOMOBILE|espite the ironic excuses. furiously final deposits wake slyly. slyly ex +168|Customer#000000168|GDcL5qU86P8,oaTwVBCLE6asM8rlxpE,211uziU|12|22-354-984-5361|-808.56|FURNITURE|blithely final accounts sleep quickly along the regular ideas. furiously sly foxes nag across the +169|Customer#000000169|NjhmHa7xrcjE|18|28-362-499-3728|4483.83|FURNITURE|fully unusual pinto beans. blithely express asymptotes lose carefully regular instructions? accounts b +170|Customer#000000170|5QmxmYubNhn6HAgLwTvphevM3OmpZTGsM|15|25-879-984-9818|7687.89|BUILDING| regular requests. carefully regu +171|Customer#000000171|RIhjJCrth89EU7xRSvN|7|17-513-603-7451|2379.91|MACHINERY|ly furiously final requests. slyly final requests wake silently pending, silent accounts. exp +172|Customer#000000172|KwgdKUL1G2WacsMNF50yX|22|32-178-964-1847|1134.40|MACHINERY|losely regular, unusual instructions. +173|Customer#000000173|Aue7KVz,FinSHpov Vk5ed,wSQ2BRSioJ0|9|19-443-196-8008|845.84|BUILDING|s pinto beans use thinly slyly regular packages. instructions print along the s +174|Customer#000000174|R5 fCPMSeDXtUpp5Ax|23|33-845-455-8799|1944.73|FURNITURE|oldly even requests haggle quickly blithely ironic accounts. idly final foxes doze slyly pending dep +175|Customer#000000175|8YK1ZyTqoY3wMWnExl4itPMLL793GpEZb6T|10|20-427-617-9922|1975.35|FURNITURE|ly final platelets are final pinto b +176|Customer#000000176|9hBepY2uz88HlCqToOLgeU770u81FeL|13|23-432-942-8830|-375.76|FURNITURE|uriously. final requests sleep ironic packages. quickly +177|Customer#000000177|6wzEKPyZE9dmBCJZ8e7x7fiiK,k|1|11-917-786-9955|7457.50|BUILDING|nal dolphins: blithely bold gifts wake slyly afte +178|Customer#000000178|p HUSDg8Cgan4Fj8Drvcdz4gi4dSqV0a7n 0ag|21|31-436-268-6327|2272.50|FURNITURE|unts. blithely regular dependencies kindle pending deposits. quietly express deposits wake above the Tiresias-- ex +179|Customer#000000179|djez3CWg0nnCiu60jsF|4|14-703-953-2987|-43.08|MACHINERY|st furiously. idly regular instructions wake fluffily slyl +180|Customer#000000180|DSGW3RFoYJE opVw,Y3wGCGcNULZi|13|23-678-802-2105|-92.58|FURNITURE|lar accounts sublate above the slyly final +181|Customer#000000181|YNviWd WrRkZvSw1OxIewBq|9|19-653-305-8440|3929.96|FURNITURE|final requests cajole furiously acro +182|Customer#000000182|tdwvgepG316CCTHtMaF8Q|3|13-199-211-9023|4810.22|AUTOMOBILE|quickly against the blithely even deposits; epitaphs unwind quickly along the carefully regular excuses. furio +183|Customer#000000183|aMAB2QSb8 86MAx|22|32-771-279-8154|4419.89|HOUSEHOLD|sual accounts across the slyl +184|Customer#000000184|uoOpBuRr42f1WIqnVYAhxbAA9bkK6HUGpOt|21|31-739-340-5476|170.46|AUTOMOBILE|hely according to the furiously unusual accounts. furiously bold platele +185|Customer#000000185|iHXzQgienOQ|5|15-760-572-8760|2788.76|BUILDING|t the ironic accounts. fluffily regular requests wake slyly ironic pinto beans. slyly unusu +186|Customer#000000186|BeVr6MzaobBENXRBC8pmOmkByMJI|3|13-518-743-2576|8737.50|HOUSEHOLD|e slyly final dependencies. unusual instructions against the carefully pending instructions boost quickly +187|Customer#000000187|OIlgR6oIRXV5g63q5YGudCjRD8kpod2p|4|14-716-294-6674|-774.22|FURNITURE|r deposits. carefully silent packages after the fluffily even instructio +188|Customer#000000188|58Srs6gEEoD3ZfwgXDM1OayRiaSY6K9YsveWwV|5|15-613-528-7811|9533.37|BUILDING|st slyly special platelets. bold, +189|Customer#000000189|r51HSq Rg8wQgF1CBfG1Vbye3GK|22|32-980-348-1114|-594.05|MACHINERY|sly express patterns. ideas on the regular d +190|Customer#000000190|F2X,GhSqLz8k u0gWsirsraFaEDEo6vIGtOTaO1T|11|21-730-373-8193|1657.46|AUTOMOBILE|uickly-- fluffily pending instructions boo +191|Customer#000000191|P1eCXsPWkv2y6ENQv|16|26-811-707-6869|2945.16|BUILDING|o beans hinder slyly bold accounts. +192|Customer#000000192|rDmB2c9d1BJQ y6R9jTx86YI77D|10|20-750-712-2481|8239.96|MACHINERY|ely unusual packages are fluffily +193|Customer#000000193|dUT4dtsPTZ6ZpkWLc,KGJCHY6JDJgPFH4|23|33-182-978-6287|8024.55|MACHINERY|y even theodolites. final foxes print along the final pinto beans. theodoli +194|Customer#000000194|mksKhdWuQ1pjbc4yffHp8rRmLOMcJ|16|26-597-636-3003|6696.49|HOUSEHOLD|quickly across the fluffily dogged requests. regular platelets around the ironic, even requests cajole quickl +195|Customer#000000195|WiqQD8hscyKekjMcSBA7AX 0AbxvBV|22|32-757-684-6845|4873.91|AUTOMOBILE| should detect blithely. quickly even packages above the deposits wak +196|Customer#000000196|68RstNo6a2B|18|28-135-177-2472|7760.33|FURNITURE|accounts wake. express instructions according to the s +197|Customer#000000197|UeVqssepNuXmtZ38D|1|11-107-312-6585|9860.22|AUTOMOBILE|ickly final accounts cajole. furiously re +198|Customer#000000198|,7fcZHIUn,fUaQtK8U,Q8|1|11-237-758-6141|3824.76|AUTOMOBILE|tions. slyly ironic waters wa +199|Customer#000000199|lBU3xll,a7e9TYm3 UyjDPCVMvnHKpq,9HW1X|4|14-136-924-5232|7654.31|FURNITURE|fully busy pinto beans. packages cajole around the express, bold packages! quickly ironic tithes +200|Customer#000000200|x1 H5c66DUgH2pgNTJhw6eZKgrAz|16|26-472-302-4189|9967.60|BUILDING|e after the ironic, even realms. fluffily regular packages doze-- courts haggle carefully! blithely +201|Customer#000000201|yWLtmd5usyjsCvyL1QJsBorC|2|12-759-183-9859|4614.40|MACHINERY| blithely even packages sleep carefully bold, unus +202|Customer#000000202|Q0uJ1frCbi9yvu|7|17-905-805-4635|2237.64|AUTOMOBILE|fully along the carefully pending Tiresias; special packages along the carefully special deposits try to +203|Customer#000000203|2fRlubh lWRinCs1nimADdn|1|11-886-563-6149|7960.63|MACHINERY| packages are. requests integrate regularly across th +204|Customer#000000204|7U7u2KryFP|6|16-761-837-4820|-627.76|BUILDING|ages. accounts wake slyly. dolphins nag blithely. final, regular requests haggle blithely furiously even +205|Customer#000000205|jOTQBGb nhfBMu3,LIN62WogLDBO0w|12|22-356-437-1311|7161.52|BUILDING| furiously pending accounts. ideas along the slyly final deposits cajole blithel +206|Customer#000000206|xsg,ehRHS5OKqyBR5YtoPm8myz|9|19-976-832-3312|-274.79|AUTOMOBILE| the carefully regular foxes. regular accounts wake furiously braids. bold ideas are carefu +207|Customer#000000207|ewz5JNnxJPmPGY|21|31-562-675-6475|-439.98|AUTOMOBILE|n theodolites against the evenly even requests boost carefully pinto beans! fi +208|Customer#000000208|Abye1MwcNfY0KO6yqv,Wwe|19|29-859-139-6234|6239.89|MACHINERY|le carefully according to the quickly silent packages. quickly ironic packages affix according to the ruthles +209|Customer#000000209|iBvmxOZV3qXMYQW3W4Oo7YFhdV|16|26-207-121-7721|8873.46|FURNITURE|deposits. furiously regular ideas across the quietly regular accounts cajole about the express packages. quickly reg +210|Customer#000000210|13cFL9sG1nrGERURN9WZI0|20|30-876-248-9750|7250.14|HOUSEHOLD|nusual instructions sleep regular acc +211|Customer#000000211|URhlVPzz4FqXem|13|23-965-335-9471|4198.72|BUILDING|furiously regular foxes boost fluffily special ideas. carefully regular dependencies are. slyly ironic +212|Customer#000000212|19U0iZ3GtDdrsn|7|17-382-405-4333|957.58|BUILDING|symptotes are blithely special pinto beans. blithely ironic +213|Customer#000000213|NpqMYBhBcWk8mnEta|24|34-768-700-9764|9987.71|HOUSEHOLD|al deposits. final instructions boost carefully. even deposits sleep quickly. furiously regul +214|Customer#000000214|MpCwhcLrbcIM7AeKS9tRM09by|8|18-180-678-6165|1526.59|MACHINERY|grow. fluffily regular pinto beans according to the regular accounts affix quickly pe +215|Customer#000000215|8H76xbBhde HY70BrYqGEFmVPXqlm8pgjjxh|9|19-564-446-4758|3379.20|FURNITURE|al pinto beans. ironic foxes serve. i +216|Customer#000000216|LXH7wSv4I6GG6TAkLOyLcMh559a8Y|21|31-296-111-5448|-776.08|FURNITURE|hely at the pending warhorses; blithe +217|Customer#000000217|YIy05RMdthrXqdfnNKud|23|33-159-298-3849|378.33|AUTOMOBILE|ven frays wake according to the carefully +218|Customer#000000218| V1FCIeSseuyNGYfHS Rx0,sc4IsBfReV|4|14-480-931-8567|9541.19|MACHINERY|lar courts. furiously pending dependencies cajole blithely? fluffily regular deposits cajol +219|Customer#000000219|eTjiL01eyoKiAe2WQoz3EpPg2lvSLeOu2X2wyxK|11|21-159-138-6090|9858.57|AUTOMOBILE|ckly multipliers. carefully eve +220|Customer#000000220|TbUHVhkttz|16|26-201-301-7371|9131.64|BUILDING| even, even accounts are. ironic +221|Customer#000000221|ripNyyPOewg8AahnZlsM|16|26-351-738-1001|1609.39|BUILDING| instructions above the regular requests cajole packages. pending, even +222|Customer#000000222|gAPkFjwxX1Zq 2Yq6 FIfLdJ4yUOt4Al7DL18Ou|1|11-722-672-5418|8893.76|BUILDING|regular accounts haggle furiously around the c +223|Customer#000000223|ftau6Pk,brboMyEl,,kFm|20|30-193-643-1517|7476.20|BUILDING|al, regular requests run furiously blithely silent packages. blithely ironic accounts across the furious +224|Customer#000000224|4tCJvf30WagGfacqcAqmfCptu2cbMVcj2M7Y0W|15|25-224-867-3668|8465.15|BUILDING|counts. bold packages doubt according to the furiously pending packages. bold, regular pinto beans +225|Customer#000000225|2HFk1E0fmqs|13|23-979-183-7021|8893.20|AUTOMOBILE|ages boost among the special foxes. quiet, final foxes lose carefully about the furiously unusual th +226|Customer#000000226|ToEmqB90fM TkLqyEgX8MJ8T8NkK|3|13-452-318-7709|9008.61|AUTOMOBILE|ic packages. ideas cajole furiously slyly special theodolites: carefully express pinto beans acco +227|Customer#000000227|7wlpEBswtXBPNODASgCUt8OZQ|13|23-951-816-2439|1808.23|MACHINERY|lar, ironic pinto beans use! quickly regular theodolites maintain slyly pending pac +228|Customer#000000228|A1Zvuxjdpt8TZP6i41H3fn9csGqOJUm5x0NIS1LA|20|30-435-915-1603|6868.12|FURNITURE| blithely ironic theodolites +229|Customer#000000229|Sbvjxgmwy4u6Ks1FH7lxo7toMmeU5dG|1|11-243-298-4029|7568.07|BUILDING|bold accounts haggle furiously even deposits. regular instruct +230|Customer#000000230|CnR8xt3MYqID0tiHwYh|21|31-744-950-8047|1682.83|MACHINERY|c decoys impress even deposits. thinly final asymptotes +231|Customer#000000231|WFOhG9Z9ohRdsyuYnPvBSv|10|20-825-880-1065|283.55|BUILDING|ly final deposits. fluffily ironic requests wake carefully carefully regular accounts. quickly sp +232|Customer#000000232|oA9o,3YOXu2rzKONdd,cxpqCFXUv5kuxBYKp|22|32-283-563-2674|554.71|HOUSEHOLD|ges sleep. final, bold theodolites are quickly final packages. furiously ironic packages are slyly fi +233|Customer#000000233|mFm45wZ7rV4VIbEE1F4|3|13-574-104-3221|3998.24|FURNITURE|st the special instructions. theodolites detect blithely according +234|Customer#000000234|ILyuJbixVmrNEVxsfQOMFxByySs|18|28-243-424-1393|8383.51|AUTOMOBILE| fluffily regular ideas play s +235|Customer#000000235|bp0rIBMh4fMdQnHBmMnB|3|13-350-790-6416|754.41|AUTOMOBILE|hely ruthless instructions again +236|Customer#000000236|kcW,mM0rhIstAcVaol1,6DVkS FPKlhY|14|24-808-967-4503|5384.59|AUTOMOBILE|te slyly along the requests. carefully final requests sleep slyly blithe frets. furiously ruthless dep +237|Customer#000000237|R dtznB5ocPPo|19|29-414-970-5238|-160.02|HOUSEHOLD|regular pinto beans sleep furiously ironically silent theodolites. quickly ironic courts after the deposits sleep f +238|Customer#000000238|tE0lVKK3tz5AG2 Hal2XHwE485g5MX7|16|26-307-925-1236|3482.32|HOUSEHOLD|uffily ironic theodolites are. regular, regular ideas cajole according to the blithely pending epitaphs. slyly +239|Customer#000000239|w8eRmMOmUTjVOkucbfcGDh2AqCixTOC|9|19-699-117-6988|5398.77|FURNITURE|uctions. furiously even dolphins haggle fluffily according to the furiously regular dep +240|Customer#000000240|SXfeEOwRZsXArtY3C5UWqXgLcJBAMmaynaTJs8|9|19-756-548-7835|7139.68|MACHINERY|al accounts about the slyly pending p +241|Customer#000000241|FBuwHkPR450PvnZnAezcaeMaS,hX3Ifdk|9|19-344-614-2207|6569.34|AUTOMOBILE| across the enticingly even requests. blithely iro +242|Customer#000000242|apgzK3HWAjKHFteJ16Tg3OERViesqBbx|3|13-324-350-3564|1975.41|MACHINERY|riously ironic pinto beans cajole silently. regular foxes wake slyly. bravely +243|Customer#000000243|te2FOn8xJzJinZc|7|17-297-684-7972|620.73|AUTOMOBILE|nic deposits. evenly pending deposits boost fluffily careful +244|Customer#000000244|FBVbCpEVaFaP8KogqQO2VuXeVx|15|25-621-225-8173|2506.38|HOUSEHOLD|encies. requests nag carefully. regularly final accounts h +245|Customer#000000245|IseFIO7jTGPTzAdZPoO2X4VX48Hy|12|22-952-232-2729|3720.15|MACHINERY|s. regular foxes against the s +246|Customer#000000246|WrRUR0ds6iypmopww9y9t0NJBRbke78qJm|15|25-608-618-2590|9584.96|AUTOMOBILE| requests shall have to integrate furiously pending courts. sil +247|Customer#000000247|N8q4W4QQG2mHY47Dg6|20|30-151-905-3513|8495.92|HOUSEHOLD|es affix furiously regular deposits. blithely ironic asymptotes after the blithely e +248|Customer#000000248|mgT15r8asLyaED|10|20-447-727-8914|8908.35|FURNITURE|s detect blithely. blithely pending dolphins along the fluffily final accounts haggle fu +249|Customer#000000249|0XE2fhX7j2uivaHBrFuRl1NoJnaTSIQT|3|13-226-455-7727|-234.01|MACHINERY|its are after the special deposits. ironic, final deposits against the slyl +250|Customer#000000250|9hif3yif6z8w8pW88F755PU7uz|16|26-464-852-1461|2869.97|FURNITURE|s. slyly unusual instructions cajole quickly carefully bold dep +251|Customer#000000251|Z9fdQmv07C3k hxwt9nchhuQiqC4wox85se8EW7L|13|23-975-623-5949|9585.32|HOUSEHOLD|fully blithely regular requests. fluffily even dugouts detect furiously final ideas. sometimes ironic depos +252|Customer#000000252|db1bPFF xUkJYzvE3cBtqYeDn2 u|16|26-330-347-9201|3561.74|FURNITURE|ngside of the pending foxes. furiously ironic requests wake. blithely ironic acco +253|Customer#000000253|naGyIRPFPH E|15|25-461-140-9884|9139.52|AUTOMOBILE| regular deposits sleep against the accounts. foxes cajole carefully special +254|Customer#000000254|vQ,pEzMQaFgJzK4TJ2eA|1|11-451-622-6325|1915.35|MACHINERY|equests. carefully ironic deposits detect carefully abo +255|Customer#000000255|I8Wz9sJBZTnEFG08lhcbfTZq3S|3|13-924-679-8287|3196.07|BUILDING|ges mold. bold, regular courts boost furiously at the +256|Customer#000000256|eJ6AggYh80JMEzZNwYK4CIC2flT|10|20-229-271-4429|1299.92|HOUSEHOLD|ld boost about the carefully ironic foxes. slyly special packages cajole alongside of the slyly final accounts. q +257|Customer#000000257|LyIa26EXYaSU|7|17-816-687-2155|-339.85|AUTOMOBILE|s cajole quickly along the ironic pinto beans: even, regular foxes are +258|Customer#000000258|7VbADek8qYezQYotxNUmnNI|12|22-278-425-9944|6022.27|MACHINERY|about the regular, bold accounts; pending packages use furiously stealthy warhorses. bold accounts sleep fur +259|Customer#000000259|kwh9i86Wj1Zq14nwTdhxapIkLEI|5|15-907-674-2046|3335.29|HOUSEHOLD|furiously unusual instructions. s +260|Customer#000000260|CrHY2zx4vner4|1|11-708-529-9446|9196.11|MACHINERY|carefully. furiously bold accounts nag furiously carefully regular accounts-- final decoys prin +261|Customer#000000261|dXkVi8qahjP|12|22-494-898-7855|7094.22|AUTOMOBILE|he special instructions integrate carefully final request +262|Customer#000000262|DcUOAFBxMu8oGKvIqbDx7xgeZ|4|14-698-169-5201|1561.80|AUTOMOBILE|ress packages above the ironic accounts are against the ironic pinto beans. carefully final accoun +263|Customer#000000263|Y2pxeGWkTyaq,0RCzIbZ3|1|11-276-906-3193|1162.03|FURNITURE|usly ironic theodolites cajole furiously. final ep +264|Customer#000000264|24Akixb4hqpRD|11|21-881-683-3829|3195.83|MACHINERY|ular packages cajole blithely a +265|Customer#000000265|sthiqpj6CPAKbD7BBSz9ulRuF9d,ebfaiTc|17|27-716-734-2046|8275.80|MACHINERY|lar, ironic platelets. furiously unu +266|Customer#000000266|VSIEruiMdDvjDaTQxkuK60Yw3AGxO|0|10-474-243-3974|5481.00|HOUSEHOLD|ccounts. quickly ironic excuses after the regular foxes wake along the ironic, fina +267|Customer#000000267|el7 bYzj1USp6T5i3KpfZ43jKegbdO,Jd69|15|25-402-954-8909|3166.94|AUTOMOBILE| detect slyly alongside of the foxes. closely regular pinto beans nag quickly of the blithely bold r +268|Customer#000000268|tkSLQoOpfOa601itad05EcN0UmhjZXdyKRc0r|3|13-720-469-5207|6821.01|MACHINERY|press ideas print quickly. fluffily unusual deposits use blithely eve +269|Customer#000000269|J7kLF9iPOQA 7CVwAmQRpwfZPDJ2q5Seu2Vj1gh|14|24-570-874-6232|7667.35|MACHINERY| close packages-- quickly regular instructions sleep. carefully +270|Customer#000000270|,rdHVwNKXKAgREU|7|17-241-806-3530|9192.50|AUTOMOBILE|ldly final instructions mold carefully along the ironic accounts. +271|Customer#000000271|O,HceV3 XE77Yx|6|16-621-282-5689|1490.35|MACHINERY|ly pending deposits cajole slyly sl +272|Customer#000000272| YDjKpjXEe0A6rDE|2|12-324-877-9650|-746.03|MACHINERY|he regular requests. slyly special +273|Customer#000000273|sOA,alhAw1juArjRLOd|2|12-197-772-5736|-675.05|FURNITURE|ng frets sleep. slyly express dolphins doubt ironically ironic accounts. final de +274|Customer#000000274|adesXwNumnPqsKgsE1groEAwdKNgZ|19|29-330-389-1442|4425.42|FURNITURE|gular dependencies. ironic foxes haggle du +275|Customer#000000275|M1UCTKrZLOgSyr|22|32-194-864-6861|5067.31|AUTOMOBILE|y regular deposits. fluffily ironic packages cajole along the +276|Customer#000000276|iSWxETEMKe5cF|16|26-716-357-3851|2292.67|AUTOMOBILE|eans. even, ironic accounts affix sl +277|Customer#000000277|BWGsQevHk0BfRJV3RRB ElFc|23|33-696-831-5394|8876.10|BUILDING|phins; bold, final accounts print. carefully silent +278|Customer#000000278|4jqLjG 2aeYMFEJi|20|30-445-570-5841|7621.56|BUILDING| pending, express requests cajole carefully special packages. blithely pending accounts affix furiously. fluffily +279|Customer#000000279|9t2Wo1jK1TYnDGg6ODSMGf1W9hRT3F3VK5zxJOC|9|19-220-605-9025|9663.23|AUTOMOBILE|l platelets sleep fluffily against the fluffily enticing excuses. blithely special requests wake somet +280|Customer#000000280|3fDiGmN64En0ei|11|21-537-461-3965|3952.84|BUILDING|accounts. quiet deposits sleep. slyly even instructions detect about the blithely bold instru +281|Customer#000000281|x5gJ8IGm2Fo9Jigt|6|16-809-382-6446|4361.70|BUILDING|fully quiet ideas detect quickly even packages. regular instructions accor +282|Customer#000000282|wcCc, y1996DnOwnXu1i|18|28-251-599-2415|1125.45|HOUSEHOLD|ole daringly against the carefully ir +283|Customer#000000283|jysHDuTKUKYEjdBhtI LqTttTp 7i2kvx1 O3A|7|17-111-303-1282|4450.03|AUTOMOBILE|y alongside of the accounts. slyly express dependencies wake quickly above the carefully ironic package +284|Customer#000000284|2ZgAkaBgb6aigORfIfUd3kHbPi42|6|16-161-235-2690|593.52|AUTOMOBILE|lar gifts. carefully even deposits boost! furiously even braids use afte +285|Customer#000000285|ApUL7bgFMUXGXewpoQyQOSnLeL9Vc1rrkW |20|30-235-130-1313|7276.72|FURNITURE|dolphins after the slyly ironic packages boost furiously among the furiously pending theodolites. bl +286|Customer#000000286|7 7uVDrpkWuozyEd|22|32-274-308-4633|-109.73|HOUSEHOLD|ly special accounts haggle slyly slyly fluffy req +287|Customer#000000287|KTsaTAJRC0eMYkyFm7EK3eeamHs7s|4|14-330-840-6321|1734.18|MACHINERY|requests. bold, silent depths lose f +288|Customer#000000288|eEs5rwc9AOJaKhvV|2|12-674-136-5397|5339.43|HOUSEHOLD| furiously about the carefully ironic packages. express reques +289|Customer#000000289|NUilehg0nVOkK3K1SW0,BAHCeST2JqKzuTMoGS|10|20-456-773-7693|-215.75|AUTOMOBILE|ending foxes across the carefully +290|Customer#000000290|8OlPT9G 8UqVXmVZNbmxVTPO8|4|14-458-625-5633|1811.35|MACHINERY|sts. blithely pending requests sleep fluffily on the regular excuses. carefully expre +291|Customer#000000291|ZlLNbGxnQYMubQ9K|8|18-657-656-2318|4261.68|HOUSEHOLD|e slyly silent deposits. bold deposits haggle slyly special packages. furiously bold requests cajole carefully abo +292|Customer#000000292|hCXh3vxC4uje9|11|21-457-910-2923|2975.43|HOUSEHOLD|usly regular, ironic accounts. blithely regular platelets are carefully. blithely unusual ideas affi +293|Customer#000000293|7ynwX7lZ3o2cmAWSkKAc3edKa 8yT|2|12-887-984-5485|-43.79|MACHINERY|ironic foxes are final packages. requests about the furiousl +294|Customer#000000294|hSaNqI1P2IyEFHY0r0PsPkMqt|18|28-187-946-4260|-994.79|BUILDING|bold packages. regular, final asymptotes use quickly fluffily even waters. blithely express requests wake into th +295|Customer#000000295|mk649IH6njR14woTVZ1cxtlNs URxBHD5o5z2|0|10-340-773-4322|9497.89|HOUSEHOLD|play according to the quickly ironic instructions-- unusual, bol +296|Customer#000000296|4eyqk2zpg4m V JGEtgwNmCq3c|15|25-875-178-1959|8081.52|BUILDING|es need to affix furiously. ironic, final foxes are against the regular instructions: pinto beans haggle q +297|Customer#000000297|hzg,409pj0|15|25-915-518-8800|7096.32|HOUSEHOLD|de of the regular asymptotes detect slyly ironic theod +298|Customer#000000298|jFKF3w 8aegECg7mP,qtuR9IsTSYQlEXq|21|31-542-157-4074|3812.84|BUILDING|sleep slyly. stealthy, bold pinto beans sleep blit +299|Customer#000000299|3F3Q0fTkjIv1UfJbcN7|4|14-948-474-7353|5380.50|HOUSEHOLD|tes sleep fluffily. furiously regular requests boost fluffily evenly even asympt +300|Customer#000000300|I0fJfo60DRqQ|7|17-165-193-5964|8084.92|AUTOMOBILE|p fluffily among the slyly express grouches. furiously express instruct +301|Customer#000000301|FtFq9Cgg5UAzUL|7|17-265-345-9265|9305.05|HOUSEHOLD|ular, regular notornis sleep along the furiously pending foxes +302|Customer#000000302|cJ3cHoAjAiaxTU2t87EJM|4|14-152-594-2967|1107.42|MACHINERY|dolphins haggle fluffily across the final requests. regularly unusual sentiments detect fluffily requests. regular +303|Customer#000000303|5pSw0OIoNRcpyTEEI1gZ6zRMyJ0UGhJdD|3|13-184-254-6407|9339.57|AUTOMOBILE|mise ironically against the unusual foxes. deposits cajole asymptotes. ironic ideas shall have to sleep +304|Customer#000000304|Cilvb3k8ghDX4|0|10-321-698-7663|9217.55|MACHINERY|s integrate at the carefully ironic instructions. fin +305|Customer#000000305|x8kcl,R4Wk|11|21-250-654-3339|4356.59|FURNITURE|nts. even, regular courts nag. dugouts use blithely a +306|Customer#000000306|ADoOEIr5aQcLIoGJM6nCvPEP 91|10|20-109-305-9629|3268.01|AUTOMOBILE|ill have to are. final, express deposits hag +307|Customer#000000307|xvkJ13gs7GH|13|23-836-934-5394|346.59|FURNITURE| ironic platelets nag against the bold pinto +308|Customer#000000308|c9WuNBiEYmGxeBmZaELg WWb|9|19-992-128-2013|4150.76|HOUSEHOLD|ilent accounts haggle carefully unusual dolphins. carefully regular requests wake along the +309|Customer#000000309|6Jg4ECVS2u7i,E|21|31-231-377-9535|8824.78|FURNITURE|lyly. furiously enticing instructions haggle. carefull +310|Customer#000000310|QZnc5mkLIPh6JGrzcHmRzCiL0AmdE92vyM|1|11-838-647-9285|3186.57|FURNITURE|mise fluffily blithely ironic courts +311|Customer#000000311|dvpNARle3mR19GD4s2gpEbkL2mZV3uvV6P|23|33-919-292-8822|6589.50|AUTOMOBILE|essly even escapades. blithely regular Tiresias cajole blithely furiously close packages. furiously ironic pi +312|Customer#000000312|cH6XucXV0V|6|16-316-482-2555|-178.84|AUTOMOBILE|e slyly. furiously regular pinto beans wake slyly according to the fluffily even excuses. ca +313|Customer#000000313|Ay52vCrTXsSmp7TmQ1kujvuItfLGx|0|10-401-786-6040|6115.81|HOUSEHOLD|g to the even dependencies. accoun +314|Customer#000000314|8,tdTVYGYoYRaAKwG 6aDJna4Cfjt,F9DDCC2|13|23-366-243-4713|2394.92|MACHINERY|ets alongside of the slyly pending pinto bean +315|Customer#000000315|pXaKKTCTyc UI3tglBaWRimosymG6ZyOCyb6Vb3M|7|17-442-286-3594|348.58|FURNITURE|s. slyly regular sentiments are carefully. slyly ironic asymptot +316|Customer#000000316|zE dN3aqjaG|8|18-171-394-5011|4571.78|MACHINERY|egular ideas cajole around the ironic, pending deposits. furiously pending dolphins serve blithely regular +317|Customer#000000317|uOeuL8DG1j|19|29-615-537-8871|956.88|HOUSEHOLD|ages. hockey players are. dependencie +318|Customer#000000318|PtJQn0IjYtShb1f2uYTYBnnmUeGNiwcALU|0|10-229-548-7118|9149.98|HOUSEHOLD|nding requests. special, bold instruction +319|Customer#000000319| UQ5mF3sdoZT2|6|16-734-928-1642|1834.36|FURNITURE| packages use slyly always ironic deposits. unusual, even notornis above +320|Customer#000000320|pO8rWSwK j|12|22-358-857-3698|6082.74|MACHINERY|ing requests. furiously regular accounts hinder slyly. final, regular theodolites against the slyly quiet requests +321|Customer#000000321|g3,8g XHACSvjZtJuiNk5BYiyPFnIxg|20|30-114-675-9153|7718.77|FURNITURE|special requests! express dugouts can affix furiously blithely regular platelets. fu +322|Customer#000000322|bWRyCyjH5OfGX|20|30-660-202-7517|4489.98|HOUSEHOLD|usual sauternes are among the slyly even instructions! thinly regular +323|Customer#000000323|ZLnVZ CXRi2,QDrlo|18|28-347-223-6024|1137.67|AUTOMOBILE|ely special foxes. express, final excuses across the packages are quickly amon +324|Customer#000000324|fiW1n6dLSVRkXj7kU1768UI2w1vMxEde5a |2|12-722-560-7023|806.59|FURNITURE|, regular requests kindle slyly furio +325|Customer#000000325|Z I43vl3ta3iYmjXNaSM d6Pe24ibjhdvPSi|15|25-823-702-9630|2377.34|HOUSEHOLD|nal foxes alongside of the always bold +326|Customer#000000326|nWDOTh6X019pfBtV3ikACYZiMjGykLrFnuyAo2|2|12-447-614-7494|1906.52|HOUSEHOLD|ckey players. carefully ironic a +327|Customer#000000327|UyKulwfNnX4l4ba1vQtwCWw8WNP50U8DCU|8|18-606-718-3062|8762.16|MACHINERY| unusual braids. daringly final ideas are quickly c +328|Customer#000000328|9pu j2HoEf1uhiY3jxE9l9fCRfjoVU|5|15-817-180-1487|6709.90|BUILDING|y about the daring accounts. furiously thin escapades integrate furiously against the furiously ironi +329|Customer#000000329|67r6XnIxUVgAc3pRX8tmGOw|11|21-106-357-8302|-651.91|BUILDING|ans. fluffily unusual instructions haggle about the slyly ironic platelets. never regular pinto beans sleep fl +330|Customer#000000330|UfNb7T9CTCnsfN3b|20|30-476-852-2371|8244.73|MACHINERY|en pinto beans. quickly final excuses haggle furiously. slyly pendin +331|Customer#000000331|Ug e2IBbl,LJuqjNz5XeQV|5|15-411-430-7917|170.27|AUTOMOBILE|r the silent ideas. carefully ironic deposits was carefully above the furiously even excuses. evenly regu +332|Customer#000000332|Jfosq,G6ziag7M04IvCx7SMRafyYvSI,Do|22|32-767-972-2596|-267.09|HOUSEHOLD| around the pinto beans. final theodolites haggle +333|Customer#000000333|heiloGYs Yey7NKhEFoiNhUBb,QFbjtn5wt|11|21-908-534-7709|8018.89|AUTOMOBILE|uriously close theodolites! slyly express foxes cajole-- final pinto beans boost blithely along the ironic +334|Customer#000000334|OPN1N7t4aQ23TnCpc|4|14-947-291-5002|-405.91|BUILDING|fully busily special ideas. carefully final excuses lose slyly carefully express accounts. even, ironic platelets ar +335|Customer#000000335|d2JCYLr2F9tC1AZMIvbIYPDQA|21|31-772-165-3138|6837.46|HOUSEHOLD| requests haggle carefully about the quickly special escapades. regular a +336|Customer#000000336|yC zy1i6AGrnykrV McJyjg|2|12-345-190-9898|9241.49|AUTOMOBILE|es. dependencies lose carefully blithely regular deposits. t +337|Customer#000000337|EluRTlO4pE7u0XSKKyvKvVyt4sADWFRLZuiyn|0|10-337-165-1106|-270.59|MACHINERY|ld requests sleep quickly. carefully express tithes wake carefully ac +338|Customer#000000338| aiYAeWgI0okGSJv7OgvKqMvPLhxF3blT8josX|23|33-302-620-7535|4092.49|FURNITURE|ckages nag blithely regular requests: carefully final packages between the slyly regular instructions sleep +339|Customer#000000339|jUs1Im28boIduGhp5vbKK50gM5ov7xH9G|24|34-992-529-2023|8438.07|HOUSEHOLD|ix. ironic, special tithes detect dog +340|Customer#000000340|WRnPrKQmAmoMQgHQERoVOhyTklcHMajJlc|2|12-730-681-4571|4667.12|BUILDING|es sleep according to the even, unusual Tiresias. carefully bold packages haggle. furiously pending s +341|Customer#000000341|4,zQfld2YV9TSeNgCSOvqlxhJvVW8WD|9|19-870-813-8585|8247.11|FURNITURE|low, special platelets alongside of the even, bold theodolites are carefully +342|Customer#000000342|SpDDdUfraEAfCULAuGLE|18|28-690-119-9571|7186.74|AUTOMOBILE|luffily final ideas. finally unusual requests boost slyly above the furio +343|Customer#000000343|ejvvSNHIkJVm8I1zpQINNn5yyJbA|3|13-877-910-5134|5521.36|HOUSEHOLD| unusual requests cajole blithely about the carefully express ideas. blithely even excuses above the pint +344|Customer#000000344|Zasc8,E0VVY|2|12-810-788-6699|-544.95|FURNITURE|le according to the regular instruction +345|Customer#000000345|dGFK ICPKxnsAzlX4UYOUf,n200yyEWhIeG|9|19-209-576-4513|1936.77|AUTOMOBILE|en pinto beans nag along the slyly regular deposits. slyly ir +346|Customer#000000346|K61SvIue3Emcwfel,7f9tO5WyJ58MbT7k3iS|2|12-100-890-4659|238.14|FURNITURE|ickly even pinto beans affix across the bravel +347|Customer#000000347|qRT7WRrnykLDfTc5Ei|1|11-519-832-9913|7348.92|BUILDING|ts use blithely blithely regular theodolites. even requests after the +348|Customer#000000348|ciP7BWkhOe1IbbVGlqJePBI6ZwqENkS|13|23-986-141-5327|3310.49|HOUSEHOLD|al foxes are on the carefully final excuses. careful dependen +349|Customer#000000349|vjJBjxjW9uoRZP02nS p6XY5wU6Ic,6xHpxUKA|23|33-818-229-3473|-565.35|BUILDING|y. bold, ironic instructions after the theodolites sleep blithely ironic packages. ideas c +350|Customer#000000350|G vBMGVmIOHl7tc4HeNMiMkKY|15|25-960-809-3690|19.31|BUILDING|tions. quietly unusual accounts sleep blithely afte +351|Customer#000000351|De35Hx1QiyS0uy|7|17-873-420-4342|3419.54|AUTOMOBILE|telets haggle blithely against the ironic +352|Customer#000000352|HqhIE5GRTK0dFtWpJUQENU4aa1bwdsUBEWtzUw|9|19-906-158-8420|6257.88|HOUSEHOLD|ts are. blithely special requests wake. furiously bold packages among the blithely eve +353|Customer#000000353|eftGCmL4b5rAKdvUe9biJXzAH|10|20-733-644-2244|3199.03|BUILDING|nal theodolites nag carefully. requests wake. slyly ironic ideas according to the blithely pe +354|Customer#000000354|sV3WgvJA06WngO4|2|12-545-101-2447|7095.95|BUILDING|. regular, final requests cajole fluffily. express attainments wake slyly until the even acco +355|Customer#000000355|205r3Xg9ZWjPZNX1z|14|24-656-787-6091|8727.90|FURNITURE|ly bold requests detect furiously. unusual instructions sleep aft +356|Customer#000000356|9RfNXUJivKTonL2bp1eG5IT|10|20-415-457-4421|2934.06|FURNITURE|al packages haggle always. daringly bold inst +357|Customer#000000357|l2C0Xkdib4t4 qKFUcRDOhRQMK7U0|18|28-452-965-8560|8747.36|AUTOMOBILE|ress platelets cajole fluffily final accounts: slyly ironic foxes s +358|Customer#000000358|F z jplpUKWz1Hn7p3ez2qTsiIh|5|15-457-255-3822|-44.66|MACHINERY|e furiously pending requests. slyly bold requests wake deposits. furiously express +359|Customer#000000359|z4lUH9ssc3K2w0UjRIuNRrdqw|14|24-608-547-4751|6375.23|FURNITURE|ifts wake fluffily ironic ideas. slyly ironic deposits above the +360|Customer#000000360|S,6ajyDFO3WUQ0Qr|17|27-604-646-1645|6542.83|FURNITURE|engage. quickly final platelets about the fluffily unusual accounts wake +361|Customer#000000361|l0F8jMJVe63cb|20|30-164-267-4590|7451.84|BUILDING|fully busy ideas. regular foxes cajole +362|Customer#000000362|UscV00TNrNTDddxF7BTk|17|27-651-653-4122|6149.01|AUTOMOBILE|ut the fluffily ironic platelets. ironi +363|Customer#000000363|2Koh mYARhsVcFn0U2Abt35qIyedAr1TxP|17|27-460-529-3937|-573.86|HOUSEHOLD|s. carefully unusual deposits are foxes. furiously even foxes nag carefully according to the furiously express +364|Customer#000000364|SQ3b5Q5OtrmmZjJ87tq,o1TiXKVJQ0M7ZOuud|23|33-492-647-4972|32.24|HOUSEHOLD| dependencies? pending requests use carefull +365|Customer#000000365|QiZRz y1xU|24|34-708-696-5226|737.03|HOUSEHOLD|counts. unusual packages are blithely foxes. unusual dinos +366|Customer#000000366|pPQektSfn55AC7s9SRFkj07I2yXqakvCa|3|13-915-531-6826|-729.74|MACHINERY|nos wake quickly. regular, regula +367|Customer#000000367|yZaDoEZCqt2VMTVKoZUkf6gJ4yj|13|23-939-319-4691|9108.65|HOUSEHOLD|eodolites under the ironic, stealthy requests affix furiously among the unusual tit +368|Customer#000000368|9p ReFA4fseKWYUaUHi|22|32-552-596-4994|84.72|MACHINERY|ic asymptotes. quickly special packages along the bravely bold depos +369|Customer#000000369|ge1XhgI3ADIkvLr5GPMqpup,hzlTVv|8|18-333-644-9832|2881.06|FURNITURE| theodolites? quickly quick foxes are fluffily slyly regular instructions. fluffily +370|Customer#000000370|oyAPndV IN|12|22-524-280-8721|8982.79|FURNITURE|ges. final packages haggle quickly. slyly bold +371|Customer#000000371|dnxjCYwhuSHx 9KX38nV0R16fG|22|32-119-346-2028|7789.14|AUTOMOBILE|equests shall boost furiously special pinto beans. express, ironic ideas sleep across the ironi +372|Customer#000000372|aKPMNZfbgV0neVIBo|19|29-226-339-6392|-921.91|MACHINERY|. furiously even foxes sleep at the forges. bold accounts sleep after the ironic theodolites. ironi +373|Customer#000000373|2hrQ wHkbaNlJCzY,mVkugMIE 8ryNlaA3JHDTjJ|20|30-883-170-4010|2354.06|MACHINERY|requests wake blithely even packages. slyly ironic deposits haggle blithely +374|Customer#000000374|fg4eklU1,UaFOan|22|32-282-723-3627|6718.78|AUTOMOBILE|ges are carefully. slyly ironic deposits about the fin +375|Customer#000000375|e53JADEeGvM1ikhN7aa|15|25-575-273-9756|5562.22|HOUSEHOLD|st the pending accounts. final courts above the pending pinto beans use furiously ironic requests. dolphins +376|Customer#000000376|4NwsvFQU T4mSgzvU1Rx2ZtHOGyaNyhe|16|26-437-952-8986|4231.45|AUTOMOBILE|gs cajole quickly. bold asymptotes wake regularly along the quickly +377|Customer#000000377|PA4levhyD,Rvr0JHQ4QNOqJ9gW YXE|23|33-260-610-4079|1043.72|MACHINERY|. slyly regular ideas cajole blithely. slyly ironic foxes are carefully after the thinly special accou +378|Customer#000000378|133stqM9 LT,a2BSlbm49 nXreFggaZgW6P6J|22|32-147-793-4825|5718.05|BUILDING|ackages haggle fluffily ironic packages. +379|Customer#000000379|t3QzCf,q1NbshmjOIUY|7|17-228-550-9246|5348.11|AUTOMOBILE|l deposits cajole blithely blithely final deposits. express, even foxes grow carefully about the sile +380|Customer#000000380|n2w3Jd1bipwICbOVgrELzcNRexmWSklo|21|31-538-493-4229|2755.46|BUILDING|riously special accounts. slyly final accounts sleep; blithely special requests integrate carefully slyly en +381|Customer#000000381|w3zVseYDbjBbzLld|5|15-860-208-7093|9931.71|BUILDING|t regular, bold accounts. carefully quick packages haggle. care +382|Customer#000000382|UdgAMamK5JnSykA,ZPfR5W5zRFatDUye|8|18-942-650-6657|6269.42|AUTOMOBILE|. blithely express notornis according to the blithely even requests are never fina +383|Customer#000000383|iBIHYgXvVDpu6qq7FlqXVcAIDAzv4qs|2|12-868-920-9034|-849.44|MACHINERY|slyly express ideas haggle blithely unusual dugouts. ironic pinto beans are ironic ideas. +384|Customer#000000384|kDDMb3ML nUSu2Sn7CUHyZVedAFUx9|9|19-271-453-8361|-614.30|HOUSEHOLD|olites. express, unusual dolphins cajole carefully about the +385|Customer#000000385|zJvPI24TSPpiFzYfu3RvTKQ9|3|13-741-675-6890|2457.09|AUTOMOBILE|rs. blithely ironic deposits nag furiously across the furiously ironic accounts. bold deposits sleep express +386|Customer#000000386|DeQxsCxixT8RQ7JV6mddRYGDGQ2WM94|24|34-193-143-1425|232.01|BUILDING|counts. blithely permanent deposits wake slyly! unusual, even theodolites u +387|Customer#000000387|Yj 9g1mNu00rKRkc1ovOmptsPI|18|28-694-363-3673|3404.23|HOUSEHOLD|oach. blithely regular instructions sublate across the quickly regular ideas. qui +388|Customer#000000388|dV4lqEufXkF8R|7|17-856-814-6352|1938.05|HOUSEHOLD| carefully bold deposits: final pinto beans sleep slyly idl +389|Customer#000000389|ij8KNM0,HRvIvnvY w8jQK4zvr1EOO9YM|9|19-264-943-1253|-307.61|AUTOMOBILE|o beans affix fluffily. slyly ironic notornis wake +390|Customer#000000390|Nsc3VZZnVsw0mLAnqqzVz,|4|14-812-253-6693|8862.18|HOUSEHOLD| final packages promise quickly. pending theodolites haggle quickly above the doggedly ironic +391|Customer#000000391|q10SV05KB1038lzUR8P|11|21-604-451-4462|4801.30|HOUSEHOLD|le blithely final forges. furiously even deposits cajole fluffily even patterns. furious +392|Customer#000000392|H7M6JObndO|17|27-601-793-2507|8492.33|BUILDING|efully bold ideas. bold requests sleep carefully blithe instructions. carefully final accounts are blithely quickly +393|Customer#000000393|RSELskV44I3LFA9VLGY2Qe|20|30-749-949-5915|3593.57|FURNITURE|ake furiously express notornis. pending accounts hang slyly slyly blithe theod +394|Customer#000000394|nxW1jt,MQvImdr z72gAt1bslnfEipCh,bKZN|23|33-422-600-6936|5200.96|MACHINERY| instructions. carefully special ideas after the fluffily unusual r +395|Customer#000000395|b06rg6Cl5W|15|25-804-388-6600|4582.28|HOUSEHOLD|s mold blithely regular platelets. slyly silent instructions use slowly slyly specia +396|Customer#000000396|miE7JrCdGpQkF4zYJ27tBdSu IYhQ HXx0 |22|32-902-936-4845|1433.50|BUILDING|xcuses. regular pains wake slyly across the ruthlessly ironic dependencies. e +397|Customer#000000397|EzR2BKJ85SmBDS|7|17-103-357-8777|709.46|FURNITURE|al theodolites. regular accounts are regular, silent foxes. unusual asymptotes above t +398|Customer#000000398|cq9NmtIT4b6JB8L79iLzljlHs4 3|15|25-110-215-3747|8865.61|HOUSEHOLD|l deposits breach slyly ironic asymptotes. carefully pend +399|Customer#000000399|ZBvzMa6N1wdCGaPmG13xVusIxdjSiA94jTXN|8|18-882-664-5454|7358.53|BUILDING|yly even excuses. ironic theodolites wake furiously. blithely regular pinto beans cajole. fin +400|Customer#000000400|U23zy17EPxqmJn7neVc|14|24-522-746-1247|-98.46|BUILDING|fully bold accounts cajole bravel +401|Customer#000000401|aKALIG526OK4veQfUh2KmKcE,oRyg|19|29-667-766-5291|4146.43|BUILDING|l instructions wake. slyly express deposits us +402|Customer#000000402|8Cw4p1m1gKYVUgomkAq,es1ZtrnmHaO|6|16-950-729-1638|2106.67|AUTOMOBILE|dolites. furiously regular theodolites integrate furiously. bravely bold requests are. furiously +403|Customer#000000403|9,BVYegfkFLsEMDkeVW|14|24-753-433-1769|6693.36|HOUSEHOLD|al hockey players; ironic dependencies after t +404|Customer#000000404|2orgvLJ05jOvM292mhkS7iJmHG0jk|22|32-840-785-1776|7408.73|BUILDING|uickly brave requests haggle furiously carefully special idea +405|Customer#000000405|mCQNH1rJtqjjQ9Piauc2bZr4pRFydscZtbD9d|10|20-509-301-7901|7519.14|MACHINERY|nts. pending, express foxes sleep? ironic, pending instructions haggle. ironic, pending theodolites detect slyly. bl +406|Customer#000000406|j1fOG9WsIr2JI6Yi9jgJ M|9|19-426-693-4043|4286.94|FURNITURE|nal foxes. unusual pinto beans wake. special excuses cajole ironic +407|Customer#000000407|cfCP9bE3HnI|1|11-975-454-8499|9537.08|MACHINERY|ect among the carefully regular theodolites. regular dep +408|Customer#000000408|TBjb3m,3aea4JtP833HD4VDk7STz2Y9FB|10|20-177-807-5661|6825.37|BUILDING|unts. furiously ironic depths among the instructions wake carefully along the blithely ironi +409|Customer#000000409|mtrMiDvQxNsy1Cj0cU4ITEW5wGKLPQ2IPHNE9r4|11|21-466-412-4731|3969.86|FURNITURE|fily pending courts. express, regular packages are furiously along the quickly regular packages. +410|Customer#000000410|nYak2u Q9,gYUiLfh1N|7|17-576-345-5940|4349.27|BUILDING| sublate across the pending, express asymptotes. quickly +411|Customer#000000411|V3e,FX5x50scsQDzt5,ESxfOQBt4OzjHRoTZxF|18|28-483-924-1955|1209.32|HOUSEHOLD|refully. slyly even packages above the evenly regular asymptotes are blithely ironic dependencies. deposi +412|Customer#000000412|5IN2Y,QrhDJ2YBVGKiDbMpzi2hk1fmozIy2zQ|22|32-940-318-3191|6044.02|BUILDING|ithely silent notornis haggle. regular requests haggle according to the ironic deposits. blithely final dep +413|Customer#000000413|,4Jm5N0ruhJCB7cBR6Kw|6|16-158-285-7336|5817.90|FURNITURE|ular packages integrate furiously fluffily final accounts. carefully regular +414|Customer#000000414|i49DWI61AFb 45vb1RMH|19|29-552-380-2475|527.78|AUTOMOBILE|sily silent, even accounts. careful, final ideas boost fluffily. slyly final pinto be +415|Customer#000000415|334jCRiUb,gx3|23|33-346-876-2972|2317.93|FURNITURE|egular deposits. blithely ironic inst +416|Customer#000000416|fm7H7k6sYhKfXttOT|12|22-651-146-4780|4365.28|MACHINERY|p the pending pinto beans. furiously express reques +417|Customer#000000417|X3LMSpIn4FgjgJxldHVUlUvKzyX|11|21-794-364-5100|6187.73|BUILDING|lent multipliers. quickly express theodolites kindle blithely. ironic re +418|Customer#000000418|,e0q82drO rgVHXHrJRQ0GDrRoUOl|5|15-826-508-1218|1211.39|FURNITURE|d foxes against the furiously special packages snooze blithely quickly +419|Customer#000000419|gvbZNJ4UVBAo5yOZ2UOWcvV9TeTj|16|26-338-447-2399|7786.69|BUILDING|ideas affix alongside of the final accounts. quickly ironic deposits abo +420|Customer#000000420|HV0YB82MWw93 9K|20|30-776-366-5869|1999.35|BUILDING|ideas wake. fluffily ironic packages hang furiously above the regular, even platelets; packages haggle slyly +421|Customer#000000421|it3mUlkZAe9J8gmy|13|23-918-228-2560|7073.17|FURNITURE|lithely final deposits haggle furiously above the +422|Customer#000000422|AyNzZBvmIDo42JtjP9xzaK3pnvkh Qc0o08ssnvq|9|19-299-247-2444|-272.14|HOUSEHOLD|eposits; furiously ironic packages accordi +423|Customer#000000423|Y2B EbOg39GpFLS0n|13|23-201-501-7824|95.79|BUILDING|ts cajole after the silent, pending instructions. ironic, even asymptotes use carefully. furi +424|Customer#000000424|i4cf3kmRE9IJr,cu,1|19|29-891-311-6778|1866.42|HOUSEHOLD|bove the express, final deposits wake furiously furiou +425|Customer#000000425|lp3aCRBK11qFY|16|26-756-407-4828|5824.88|HOUSEHOLD|ajole even, pending accounts. carefully brave accounts +426|Customer#000000426|GjFjM4zjbyhNrV6XlE|19|29-768-330-6311|7818.25|HOUSEHOLD|ar instructions are against the ironic platelets. slyly final acc +427|Customer#000000427|LHzXa71U2AGqfbqj1yYYqw2MEXq99dWmY|2|12-124-309-3821|4376.80|MACHINERY|y even multipliers according to the regu +428|Customer#000000428|TCVjlzbX7x,kWcHN33LRdEjO38mAGmPR|21|31-587-557-8211|1952.36|BUILDING|furiously quick accounts. slyly bold dependencies cajole carefully. quickly even requests int +429|Customer#000000429|kZBtY,LQAFu4iaSagjfIk8Q8dzgmT|15|25-989-936-1954|9247.21|FURNITURE|ly regular requests haggle enticing excuses. carefully ironic requests on th +430|Customer#000000430|s2yfPEGGOqHfgkVSs5Rs6 qh,SuVmR|3|13-406-611-4228|7905.17|BUILDING|ly slyly ironic attainments. slyly special instructions until the deposits nag quickly whithout the bo +431|Customer#000000431|RNfSXbUJkgUlBBPn|6|16-326-904-6643|2273.50|HOUSEHOLD|e quickly. final, even excuses against the even accounts sleep agai +432|Customer#000000432|FDConiq g20GI9dH QTM ZNX4OB9KU|23|33-307-912-9016|5715.64|BUILDING|wake carefully close, special deposits. regu +433|Customer#000000433|7XFuE4 euQR0w|20|30-659-445-3595|8746.23|FURNITURE|sual ideas affix carefully always regular accou +434|Customer#000000434|6LGAf2hv4MB5MJhfvNsg|3|13-325-443-1474|2940.46|MACHINERY|lly final Tiresias. blithely regular ideas nag stealthily about the furiously +435|Customer#000000435|diwjNQSb3wLYLy WfCDATo5rc1I3 s|2|12-741-309-6377|6217.46|MACHINERY|quickly excuses. blithely express theodolites poach slyly along the theodolites. slyly reg +436|Customer#000000436|4DCNzAT842cVYTcaUS94kR0QXHSRM5oco0D6Z|19|29-927-687-6390|5896.87|FURNITURE|olites engage carefully. slyly ironic asymptotes about the ironi +437|Customer#000000437|0PM1xuHd0q2ElcJp 77F2MykOVBSQnZR8u3jkn|4|14-364-492-8498|7760.52|AUTOMOBILE| foxes sleep across the slyly unusual pack +438|Customer#000000438|eqo9A9oaE2CA7 7,L|23|33-394-388-4375|2131.13|MACHINERY|al deposits mold alongside of the fluffily brave requests. +439|Customer#000000439|3deBblz2syRv8yMf0yAVKkE4mDH20uDRj4tJVHUm|14|24-873-368-6801|-61.29|BUILDING|ions may impress thinly for the deposits? even packages towa +440|Customer#000000440|w4fKMgiBuGmV,nLn7NgJl1DoUWwNQMV8z 5,R|3|13-244-480-5751|1809.04|MACHINERY| even theodolites: fluffily final requests cajole about the quickly regular +441|Customer#000000441|gjYpcBx6MP8GvDa6|23|33-438-355-3491|9451.84|HOUSEHOLD|r requests wake theodolites. quickly final ideas haggle fluffily. blithely f +442|Customer#000000442|rvgayfJFLO2cjzMA|1|11-240-523-8711|4157.00|FURNITURE|lets would affix fluffily. regular, regular ideas ought to haggle carefully blit +443|Customer#000000443|UdyNGZ6GSz5aNpMO5N2|3|13-241-131-1632|3726.22|FURNITURE|t the special, final platelets. bold req +444|Customer#000000444|D8l4G8i9aZ7KRbqp6ajvR8h1wjr|1|11-402-300-1949|1505.27|HOUSEHOLD| express accounts along the pending deposits lose carefully above the furiously regular requests. pen +445|Customer#000000445|MX1UA0KUJzIGyWM p2hbLg5dCpVLws8KNcwEsP|20|30-849-846-6070|8018.81|FURNITURE|e ironic, special accounts. quickly regular packages integrate fluffily slyly +446|Customer#000000446|mJOJwYfch izLCuw70,qhlJSmH|24|34-321-168-5681|9225.60|FURNITURE|ending instructions. boldly ironic foxes across the regularly ironic pains sleep along the carefully final deposits. +447|Customer#000000447|hVZBzP8Pii|3|13-438-344-7007|7665.98|HOUSEHOLD|telets around the furiously unusual foxes detect carefully against the +448|Customer#000000448|BH4vtnDpabk0NgoGNJWu4OUXnidfJ|24|34-985-422-6009|8117.27|BUILDING|unts. final pinto beans boost carefully. furiously even foxes according to the express, regular pa +449|Customer#000000449|DiUXazp8EYcJFsX2a7nciEpo9W5BRB4iqdb9HWL|4|14-893-381-6454|3001.94|MACHINERY|posits boost slyly carefully regular requests. final, bold fo +450|Customer#000000450|KVpuYa4dDW8lZZVBttyK614C2qdS|9|19-782-397-9006|5544.42|HOUSEHOLD|gular decoys nod slyly express requests. slyly bold theodolites are along the regular +451|Customer#000000451|ZJKTC1Ck,B01fYZ xdN2|20|30-939-275-3248|2110.59|HOUSEHOLD|quests grow furiously final deposits. ironic, even pi +452|Customer#000000452|,TI7FdTc gCXUMi09qD|6|16-335-974-9174|6633.70|BUILDING|aggle quickly. unusual instructions i +453|Customer#000000453|PZ4mmWL7R,El0MtLWMfLXp120lo0,itmO|8|18-209-381-8571|5678.18|HOUSEHOLD|sts. slyly even dolphins across the bold, regular foxes haggle blithely +454|Customer#000000454|d9oQCm3onNsFlIoteVjFcQDv|7|17-818-915-9400|6134.40|AUTOMOBILE|ions print slyly platelets. carefully regular packages according to the fluffy, even foxes wake carefu +455|Customer#000000455|sssuscPJ,ZYQ8viO|6|16-863-225-9454|6860.34|BUILDING|l wake. blithely final instructions integrate furiously above the final, regular req +456|Customer#000000456|IgUSuulguDJ5|0|10-784-971-7777|8815.78|FURNITURE|ly even warhorses. quickly even requests wake slyly. +457|Customer#000000457|eaAWe Vqr0x17Uwj1uzQRb wQpXxZVDWS3Wg|20|30-543-684-2857|5867.61|FURNITURE|the foxes. carefully pending instructions integrate fluffily blithely pending packages. careful +458|Customer#000000458|iIKwI3HrgNlD9|4|14-651-706-4016|-38.42|BUILDING|ng. final, express requests are furious +459|Customer#000000459|CkGH34iK 9vAHXeY7 wAQIzJa1cmA8DAEA7m|6|16-927-662-8584|1207.97|MACHINERY|ronic, regular dependencies use above the ironic deposits. carefully express packages use car +460|Customer#000000460|Gbx5Hnw,ctlI7|11|21-643-955-6555|5222.83|FURNITURE|old dependencies mold slyly above the foxes. dogged, express ins +461|Customer#000000461|5vxNLzSASzkbrUr8CRf5|21|31-533-226-4307|9177.63|AUTOMOBILE|sits breach blithely. slyly regular ideas haggle fluffily; special ideas cajole q +462|Customer#000000462|MSqsCvNEkowp7FnscRXP6OUWm|21|31-157-561-4106|4522.60|HOUSEHOLD|ly special accounts? ideas engage regular dependencies. fluffily even pinto beans x-ray blith +463|Customer#000000463|LV7MN7Tkm2NSo4Q3lwvjxGQyRJjRZRf,M|8|18-167-214-5805|-654.50|HOUSEHOLD| quickly along the final ideas. slyly regular accounts are iro +464|Customer#000000464|kAALP9gEt3,G9XtxCXjv38HjKBEP|9|19-269-971-9738|8730.85|AUTOMOBILE|efully express accounts play. special requests use carefully. regular courts sle +465|Customer#000000465|gngnTNn7azjgQlQJnakTZto|2|12-137-838-1346|8432.74|FURNITURE|es. quick asymptotes integrate carefully alongside of the ideas. even requests believe slyly even ac +466|Customer#000000466|ZI1c8,ZanegEu5CEQxNf5,bkuYPwn7H7JIK7|12|22-280-738-3240|3168.41|MACHINERY|foxes. express, ironic accounts boost? carefully silent deposits engage. accou +467|Customer#000000467|amwRkh0nDQ6r6MU|11|21-449-581-5158|9398.51|MACHINERY|manently special warthogs. final ideas a +468|Customer#000000468|IcbihAtOVWcnswfyE|10|20-489-960-5023|9834.19|FURNITURE| accounts cajole quickly above the blithely final packages. even, express package +469|Customer#000000469|JWOULMa5Qtt|12|22-406-988-6460|6343.64|BUILDING|cajole carefully slyly regular packages. +470|Customer#000000470|v9 gWSuP4WrOjNJRgyJtjbNCChQME|20|30-507-458-4433|3597.53|HOUSEHOLD|ilent excuses. never ironic requests sleep furiously. daringly f +471|Customer#000000471|tGr0DtrK 91IgzfeZrSPpPIia3|4|14-574-118-1005|5716.90|FURNITURE|es. unusual accounts try to solve ca +472|Customer#000000472|hWgfnsmTAEOx9Mqp87YwztGrgLLqNkjMPh4|12|22-940-478-1933|7929.90|MACHINERY|deas sleep slyly blithely final foxes. slyly final e +473|Customer#000000473|zO3W9pYj PvlsQGe|9|19-209-647-5704|-202.22|HOUSEHOLD|ter the quickly pending requests sleep above the carefully iron +474|Customer#000000474|mvEKw,6zT0V8Yb2yTG hu990UX|21|31-247-536-6143|9165.47|MACHINERY|ns integrate against the quickly special courts. slyly +475|Customer#000000475|JJMbj6myLUzMlbUmg63hNtFv4pWL8nq|14|24-485-422-9361|9043.55|BUILDING|egular requests. ironic requests detect furiously; deposits ha +476|Customer#000000476|68r87HCBbQkVYaVfes8mgKs|2|12-996-628-9902|5973.10|BUILDING|sly. carefully quick instructions sleep carefully deposits. final, pending pinto beans use closely fluffily final in +477|Customer#000000477|5aW5WHphNgFdIS1Qdp2cIJXG8ER8|23|33-845-877-6997|1836.61|AUTOMOBILE|totes are blithely among the furiously final foxes. slyly +478|Customer#000000478|clyq458DIkXXt4qLyHlbe,n JueoniF|1|11-655-291-2694|-210.40|BUILDING|o the foxes. ironic requests sleep. c +479|Customer#000000479|RdIiG8NbwYtamReRwhR|18|28-336-406-1631|3653.64|AUTOMOBILE|ages. bravely even foxes detect careful +480|Customer#000000480|XyQSPswCeO WPD37K3 mYZ4hnCMJO5p|7|17-231-147-5851|2750.71|FURNITURE|posits. slyly ironic theodolites nag carefully about the quickly final accounts. s +481|Customer#000000481|o4xa7J20NqHM8E0ykH,NKe1gPz04OqIn|21|31-363-392-6461|7157.21|FURNITURE|s can nag slyly instructions. regular, regular asymptotes haggle sly +482|Customer#000000482|389RgNCsmVUKiRskmrQQm90xx JiIxOM0|13|23-732-448-1610|4333.37|HOUSEHOLD|carefully bold instructions. carefully final instructions wake carefully accounts. accounts cajole slyly ironic acc +483|Customer#000000483|Yv1QV 1JsV 9sVbNufRvdnprt0grx52|11|21-799-189-1135|8877.20|MACHINERY|pecial ideas. furiously final i +484|Customer#000000484|ismzlUzrqRMRGWmCEUUjkBsi|20|30-777-953-8902|4245.00|BUILDING|y against the express, even packages. blithely pending pearls haggle furiously above the fur +485|Customer#000000485|XeFbvXCQ,J|19|29-434-961-1623|8695.45|MACHINERY|ecial pinto beans. instructions ought to cajole even +486|Customer#000000486|2cXXa6MSx9CGU|21|31-787-534-8723|7487.40|AUTOMOBILE|nstructions. unusual, special pinto beans sleep about the slyly pending requests. fu +487|Customer#000000487|oTc,l9dAf8O0qOOMP4P0WFTuGS|2|12-111-401-4259|9749.37|AUTOMOBILE|as. excuses use carefully carefully pending i +488|Customer#000000488|bBcMjFPTysSTaTdHcoO|3|13-513-778-1881|-275.58|AUTOMOBILE|thely above the carefully ironic accounts. excuse +489|Customer#000000489|GIdW4IVgeqWMBXnNFZGHS8kmhw|4|14-916-241-6195|8255.83|AUTOMOBILE|lar accounts. finally pending dependencies solve fluffily +490|Customer#000000490| 66fG3Fyb946cVQsH9Z3VMNzR,yfHMKIEB|22|32-268-147-7824|-213.85|FURNITURE|ash carefully never bold instructions. regular, bold asymptotes cajole regularly. quickly bold foxes wak +491|Customer#000000491|r3zPOuenxHl0oqInxWlEyLP1ZH|0|10-856-259-7548|785.37|AUTOMOBILE| slyly special requests hang dogged, express epitaphs. +492|Customer#000000492|JexAgMLuUHoElYFaKx,hJcAP1b1GknYoYHQLyx|8|18-686-244-1077|8635.18|AUTOMOBILE|gle furiously furiously final packages. carefully bold pinto beans promise quickly alongside of the close +493|Customer#000000493|G dRBjxmBBug1 xRSa6VwRchFDtU5b|16|26-514-558-7246|6582.04|MACHINERY|er the furiously express excuses use above the regular accounts. regular instructions after the +494|Customer#000000494|GKgTjHFlQrDZWcketSqhZCopBhmChknI|10|20-330-453-6579|6295.47|FURNITURE|al courts. regular, ironic requests serve furiously. pending +495|Customer#000000495|QhFbEv6KbQIwfZs 1krt1eACKI31v3iyM|7|17-400-405-6060|7997.81|BUILDING| dependencies. silent accounts cajole quickly furiously pendin +496|Customer#000000496|Y8oYLlHme6Z4fEzkTu|12|22-173-644-7922|8174.82|MACHINERY| quickly bold packages. decoys among the blithely pending accounts lose according to the deposits. +497|Customer#000000497|0 qRRXAxUbo1J KDwDMjFde5fXDwn |23|33-937-724-3506|2191.59|BUILDING|fluffy ideas detect carefully +498|Customer#000000498|1Wnja9i7KAC3HxS5yATK,In8Q6AHcEUr0f5Tp|19|29-210-810-1479|3945.64|BUILDING|yly pending requests according to the slyly special asymptotes sleep carefully against the slyly even pack +499|Customer#000000499|m1hO3VXQVbwTbJ99Hw|14|24-387-817-9149|4293.76|HOUSEHOLD|old sentiments cajole carefully among the blithely unusual requests. final packages nag careful +500|Customer#000000500|fy7qx5fHLhcbFL93duj9|4|14-194-736-4233|3300.82|AUTOMOBILE|s boost furiously. slyly special deposits sleep quickly above the furiously i +501|Customer#000000501|lzkYA5C6wa,wX|13|23-867-672-1331|1909.35|FURNITURE|ual deposits wake. quickly ironic platelets along the careful deposits haggle +502|Customer#000000502|nouAF6kednGsWEhQYyVpSnnPt|11|21-405-590-9919|1378.67|HOUSEHOLD|even asymptotes haggle. final, unusual theodolites haggle. carefully bo +503|Customer#000000503|7xCLYGLCpFU,toJBIPIrJbLIuLok81h IxK ae5Z|20|30-441-755-3094|3213.66|MACHINERY| even deposits haggle. packages i +504|Customer#000000504|2GuRx4pOLEQWU7fJOa, DYiK8IuMsXRLO5D 0|10|20-916-264-7594|0.51|FURNITURE|slyly final theodolites are across the carefully +505|Customer#000000505|MAUkwAyEvg61RlCMomspMs0WzYa,Ns|2|12-530-647-8313|6557.51|HOUSEHOLD|mptotes haggle around the theodolites. furiously bold accounts detect quickly packages. special pinto beans +506|Customer#000000506|dT kFaJww1B|13|23-895-781-8227|1179.85|HOUSEHOLD| idle instructions impress blithely along the carefully unusual notornis. furiously even packages +507|Customer#000000507|QlA0Fc 6e,r67ugESzq|14|24-158-185-4455|5727.00|MACHINERY|nst the furiously even deposits cajole slyly among the furiously ironic requests. blithely unusual depo +508|Customer#000000508|q9Vq9 nTrUvx|18|28-344-250-3166|1685.90|BUILDING|uses dazzle since the carefully regular accounts. patterns around the furiously even accounts wake blithely abov +509|Customer#000000509|LHLR0IKQJHVF1 0UvBNPLq0|4|14-115-338-1002|7885.50|FURNITURE|ily! requests cajole fluffily. slyly regular waters na +510|Customer#000000510|r6f34uxtNID YBuAXpO94BKyqjkM0qmT5n0Rmd9L|5|15-846-260-5139|1572.48|HOUSEHOLD|symptotes. furiously careful re +511|Customer#000000511|lQC9KfW W77IYtJjAgSZguNzxjY rYk3t6lcxfSh|13|23-247-728-9743|4571.31|FURNITURE|he slyly close deposits. special, ironic ideas detect furiously carefull +512|Customer#000000512|e5 kymvjf6Vja7tNsL 3dfiK|2|12-144-416-6035|3937.58|BUILDING|packages are slyly after the slyly express packages. bold d +513|Customer#000000513|sbWV6FIPas6C0puqgnKUI|1|11-861-303-6887|955.37|HOUSEHOLD|press along the quickly regular instructions. regular requests against the carefully ironic s +514|Customer#000000514|0qD6Nwp3tG3QqCq9qvRAzT6N8L|23|33-194-775-6756|5840.97|BUILDING|carefully final ideas. quickly final packages are. requests haggle slyly. blithely pending sauternes lose bl +515|Customer#000000515|oXxHtgXP5pXYTh|15|25-204-592-4731|3225.07|BUILDING|ackages cajole furiously special, ironic deposits. carefully even Tiresias according to +516|Customer#000000516|EJwOQMTQnFwvd8r Y7f9i5POy6ZlNkIYxCL hg8t|6|16-947-309-2690|4768.96|MACHINERY|final requests after the furiously +517|Customer#000000517|mSo5eI8F4E6Kgl63nWtU84vfyQjOBg4y|10|20-475-741-4234|3959.71|FURNITURE|al, ironic foxes. packages wake according to the pending +518|Customer#000000518|EsCrt4chk,3IRIzwMHTu 6VQWrfh|17|27-651-256-7682|9871.66|BUILDING|as. quickly regular requests are carefully above th +519|Customer#000000519|Z6ke6Y9J2pYuPBp7jE|5|15-452-860-5592|9074.45|BUILDING|es. fluffily regular accounts should have to sleep quickly against the carefully ironic foxes. furiously daring +520|Customer#000000520|yaOGc9Ve92Bi4F6e0GcheU2MmEOXJE0zqyDT sEA|3|13-612-111-7765|8315.09|HOUSEHOLD| haggle across the even, bold instructions. final, even ideas might wake blithely against the +521|Customer#000000521|MUEAEA1ZuvRofNY453Ckr4Apqk1GlOe|2|12-539-480-8897|5830.69|MACHINERY|ackages. stealthily even attainments sleep carefull +522|Customer#000000522|gPz4FuAGpjvaU4YB9J,fGSnLBr9scEovGO1KkTx|12|22-771-454-9561|6358.46|BUILDING|instructions. doggedly express requests doze blithely. regular theodolites hagg +523|Customer#000000523|sHeOSgsSnJi6pwYSr0v5ugiGhgnx7ZB|10|20-638-320-5977|-275.73|BUILDING| fluffily deposits. slyly regular instructions sleep e +524|Customer#000000524|bpsO77xiAmjwOxqIgAszRu4Y|9|19-844-888-9800|5706.19|HOUSEHOLD|ending pinto beans unwind slyly. slyly final theodolites above the quickly ironic pinto beans haggle ev +525|Customer#000000525|w0pOG5FhH45aYg7mKtHQhAWQKe|19|29-365-641-8287|3931.68|AUTOMOBILE| blithely bold accounts about the quietl +526|Customer#000000526|0oAVPhh1I4JdrDafVG2Z8|1|11-170-679-3115|705.93|HOUSEHOLD|ctions cajole after the furiously unusual ideas. ironic packages among the instructions are carefully carefully iro +527|Customer#000000527|giJAUjnTtxX,HXIy0adwwvg,uu5Y3RVP|13|23-139-567-9286|4429.81|HOUSEHOLD|ending, ironic instructions. blithely regular deposits about the deposits wake pinto beans. closely silent +528|Customer#000000528|SRYjG5Wgp8ZG8GyDFhRIR5ep8yNs3nrCmYa|15|25-985-381-5453|1802.50|AUTOMOBILE| the slyly even instructions. carefully idle packages sleep about the platelets. bol +529|Customer#000000529|oGKgweC odpyORKPJ9oxTqzzdlYyFOwXm2F97C|15|25-383-240-7326|9647.58|FURNITURE| deposits after the fluffily special foxes integrate carefully blithely dogged dolphins. enticingly bold d +530|Customer#000000530|wG6AC7G6Y0DRuzJiroWCByzbrkqeySQDvRXzH|13|23-614-884-1055|4990.92|BUILDING|uctions cajole blithely across the ironic packages. slyly regular deposits wa +531|Customer#000000531|ceI1iHfAaZ4DVVcm6GU370dAuIEmUW1wxG|19|29-151-567-1296|5342.82|HOUSEHOLD|e the brave, pending accounts. pending pinto beans above the +532|Customer#000000532|xwWO3lWjgVJTZwhnltyH6zj5ddkzgH8RbF|15|25-875-978-2232|1725.68|MACHINERY|usly regular deposits kindle. quickly even depos +533|Customer#000000533|mSt8Gj4JqXXeDScn2CB PIrlnhvqxY,w6Ohku|15|25-525-957-4486|5432.77|HOUSEHOLD|even dolphins boost furiously among the theodo +534|Customer#000000534|3PI4ZATXq8yaHFt,sZOQccGl Fc1TA3Y 2|1|11-137-389-2888|6520.97|AUTOMOBILE|deas. blithely regular foxes use carefully bold accounts-- ruth +535|Customer#000000535|,2Y kklprPasEp6DcthUibs|2|12-787-866-1808|2912.80|BUILDING|even dinos breach. fluffily ironic +536|Customer#000000536|jf8PSOQDvqQj4uF8|12|22-521-348-9030|3342.75|MACHINERY|tes? blithely enticing theodolites wake. braids sleep. sly +537|Customer#000000537|wyXvxD,4jc|10|20-337-488-6765|2614.79|FURNITURE|e carefully blithely pending platelets. furiously final packages dazzle. ironic foxes wake f +538|Customer#000000538|u9jYEMPoKwrH5wXivkSebbxAx1PU|19|29-632-471-2852|-303.95|MACHINERY|uffily special requests nag around the quickly stealthy +539|Customer#000000539|FoGcDu9llpFiB LELF3rdjaiw RQe1S|6|16-166-785-8571|4390.33|HOUSEHOLD|ent instructions. pending patter +540|Customer#000000540|YkaXu3o1X8|16|26-933-117-7482|9195.77|MACHINERY| enticingly express excuses. quickly regular notornis cajole near th +541|Customer#000000541|,Cris88wkHw4Q0XlCLLYVOAJfkxw|0|10-362-308-9442|1295.54|FURNITURE|according to the final platelets. final, busy requests wake blithely across th +542|Customer#000000542|XU2ffxnW3TQasrfF0u2KwKWmMarPyY4q7Q|16|26-674-545-2517|3109.96|BUILDING|r forges! requests alongside of the bold, final deposits +543|Customer#000000543|JvbSKX7RG3xuqiKQ93C|17|27-972-408-3265|6089.13|AUTOMOBILE|l, even theodolites. carefully bold accounts sleep about the sly +544|Customer#000000544|Jv7vcm,oE,HEyxekXKia1V5H1up23|5|15-572-651-1323|4974.68|AUTOMOBILE|bout the packages integrate above the regular instructions. regular ideas hinder s +545|Customer#000000545|AsYw6k,nDUQcMOpEws|10|20-849-123-8918|7505.33|AUTOMOBILE| carefully final deposits. slyly unusual pinto beans may wake bold requests. unusual courts alongside +546|Customer#000000546|GZtBXX3OaqFLbC9JNi1hmF1JFLbmRs9|19|29-936-444-8248|3116.50|MACHINERY|ly fluffy braids. blithely special theodolites use express deposits-- slyly regular attainments +547|Customer#000000547|4h SK3dVkE1tQ0NCh|22|32-696-724-2981|6058.08|BUILDING|y express deposits. slyly ironic deposits nod slyly slyly ironic instructions. carefully quick idea +548|Customer#000000548|98nP31ToAGK tCCkYm7HqBZt0dLjy0JzlMMRCmkj|4|14-787-370-8722|90.45|BUILDING|c pinto beans. quickly even requests haggle against the blithel +549|Customer#000000549|v5uqfeHLiL1IELejUDnagWqP5pKWa9LtoemziGV|24|34-825-998-8579|91.53|BUILDING|n asymptotes grow blithely. blithely fluffy deposits boost furiously. busily fu +550|Customer#000000550|q5 gKwc7PBQOyd,H|17|27-938-997-6262|7270.82|FURNITURE|ully regular deposits. slyly ironic requests wake along the depos +551|Customer#000000551|holp1DkjYzznatSwjG|15|25-209-544-4006|-334.89|MACHINERY|y special ideas. slyly ironic foxes wake. regular packages alongside of the deposit +552|Customer#000000552|EbjtaRaiok7eqbQ5VJi7q|2|12-669-784-2191|1353.24|FURNITURE|ickly final accounts cajole fluffily according to the bold, regular accounts. +553|Customer#000000553|8tTlavJ sT|4|14-454-146-3094|4804.57|BUILDING|ully regular requests are blithely about the express, bold platelets. slyly permanent deposits across the +554|Customer#000000554|RluaguNRAJhYXmn,CWxcOC,Ly7|2|12-938-503-7317|8395.57|HOUSEHOLD|jole along the blithely bold +555|Customer#000000555|chm8jY6TfQ8CEnsvpuL6azNZzkqGcZcO8|15|25-548-367-9974|5486.52|BUILDING|lites are blithely ironic ideas. blithely special pinto beans dazzl +556|Customer#000000556|UMHllVkuyQUQ3aLXCVRxrXatsyd0AL6Xw|1|11-934-412-5846|7944.22|MACHINERY|nt excuses! carefully final requests solve quick +557|Customer#000000557|Nt6FUuDR7v|15|25-390-153-6699|9559.04|BUILDING|furiously pending dolphins use. carefully unusual ideas must have to are carefully. express instructions a +558|Customer#000000558|PB1ZV4kQnRHiC|17|27-866-273-7672|1912.23|HOUSEHOLD|ly final requests. regular requests hag +559|Customer#000000559|A3ACFoVbP,gPe xknVJMWC,wmRxb Nmg fWFS,UP|7|17-395-429-6655|5872.94|AUTOMOBILE|al accounts cajole carefully across the accounts. furiously pending pinto beans across the +560|Customer#000000560|gU5FQf0WM0sxTYQ|19|29-618-467-8489|1469.59|BUILDING|sly pending packages boost slyly-- fluffily ironic ideas bel +561|Customer#000000561|Z1kPCTbeTqGfdly2Ab9KEdE,jIKW|18|28-286-185-3047|2323.45|FURNITURE|across the furiously ironic theodolites. final requests cajole. slowly unusual foxes haggle carefully +562|Customer#000000562|04xjB,zuffnhVyEY0 PeiJPtdjh 0ji|15|25-271-465-6971|9234.50|BUILDING|accounts. ideas cajole. quick +563|Customer#000000563|2RSC1g7cVd,j23HusdkhdCGmiiE|12|22-544-152-1215|3231.71|FURNITURE| pinto beans believe fluffily. excuses wake blithely silent requests. b +564|Customer#000000564|qPQOo94iVl|4|14-865-332-8571|6307.59|MACHINERY|onic patterns about the furiously pending +565|Customer#000000565|HCBXAou,1eP6Z3IynHFI7XmEBgu27Sx|4|14-798-211-2891|2688.88|FURNITURE|e. carefully bold deposits sleep regu +566|Customer#000000566|5NmdMIwTpF8tj7O92363ycA6EL5Yh,vW|24|34-443-780-3708|1928.10|FURNITURE|ke express, ironic requests. regularly even sauternes detect de +567|Customer#000000567|KNE6mpW69IgTjVN|21|31-389-883-3371|8475.17|BUILDING|blithe, even ideas. fluffily special requests wake. c +568|Customer#000000568|ZddVCnzeABTTBgV3GvkvNtw9,KOHHpME2GELhz|13|23-603-795-8611|1317.56|BUILDING|gular decoys haggle slyly. blithely special packages slee +569|Customer#000000569|Kk20Q5HiysjcPpMlL6pNUZXXuE|2|12-648-567-6776|-795.23|MACHINERY|sh. blithely special excuses sleep. blithely ironic accounts slee +570|Customer#000000570|0Zo0P6m,sie 1,VXacPX2ccDIyWFolj6R|15|25-264-442-3057|8480.87|AUTOMOBILE|gular instructions unwind bold escapades. special asymptotes snooze according to the +571|Customer#000000571|hCrDDrMzGhsa6,5K4rGXQ|2|12-115-414-4819|8993.23|HOUSEHOLD|le fluffily. ironic, pending accounts poach quickly iron +572|Customer#000000572|Nf4Yqb49BqGkzmmtf6|11|21-425-209-5033|7252.65|AUTOMOBILE|leep. pending requests affix blithely. ironic theodol +573|Customer#000000573|BEluH7it7jUcWqb tNLbMIKjU9hrnL7K|4|14-354-826-9743|2333.96|HOUSEHOLD|as. furiously even packages sleep quickly final excu +574|Customer#000000574|ratVLdmp070|8|18-676-218-1058|9787.56|FURNITURE|al pinto beans. carefully ironic foxes cajole idly finally express theodolites. fluff +575|Customer#000000575|4K6h0pYH,bg2FS5cYL,qqejhvp7EfTlBjRjeVPkq|1|11-980-134-7627|3652.29|BUILDING| final requests cajole after the ironic, bold instructio +576|Customer#000000576|JI7ZI3BRrkt40uuUmg oyZC3pQ2lS65SnSGL|1|11-777-499-8213|2091.63|HOUSEHOLD|sual platelets. furiously final theodolit +577|Customer#000000577|a73SSq2cip7C8nSzdmmscpZyLCZ7KL|14|24-662-826-1317|7059.15|FURNITURE|int furiously. slyly express pin +578|Customer#000000578|nxUZ BCBO1 HAymUcopl2NtyWMuWVnE3bqPVDB|14|24-278-860-9263|6181.23|FURNITURE|ly. carefully pending packages cajole among the carefu +579|Customer#000000579|9ST2x,snyY3s|0|10-374-175-6181|1924.96|MACHINERY|ndencies detect slyly fluffil +580|Customer#000000580|wpvPbaPtx5QN|11|21-444-589-3830|-181.63|BUILDING|dependencies. final asymptotes haggle among the bold packages. slyly silent +581|Customer#000000581|s9SoN9XeVuCri|24|34-415-978-2518|3242.10|MACHINERY|ns. quickly regular pinto beans must sleep fluffily +582|Customer#000000582|KqH6uOztVK55zDxLA9kvdtny i5OYXt|3|13-484-591-9280|4879.55|MACHINERY|carefully against the quickly s +583|Customer#000000583|V3i6Gu9,LZtvdnNppXnI2eKQFx0b36WvL,F |13|23-234-625-4041|3686.07|HOUSEHOLD| haggle. regular, regular accounts hinder carefully i +584|Customer#000000584|jebKvptmHtS9,YE1qOjl2AOw38P,8skngJZh|15|25-352-778-1041|8825.71|MACHINERY|ages boost regular deposits. blithely stealthy depo +585|Customer#000000585|OAnZOqr6A,,77WC001ck8BAqvJTW6,dRGoRdX|16|26-397-693-4170|7820.26|MACHINERY|ickly ironic requests sleep regularly pending requ +586|Customer#000000586|vGaA9XBtn,hlswFhSjLIXGlLEDD2flE8UXwj|11|21-239-369-7791|5134.35|AUTOMOBILE|above the blithely express ideas. slyly r +587|Customer#000000587|J2UwoJEQzAOTtuBrxGVag9iWSUPTp|6|16-585-233-5906|7077.79|AUTOMOBILE|ve the final asymptotes. carefully final deposits wake fu +588|Customer#000000588|ex9SkK7K uM,ki1dsO7PgZLlIuQFKJUQZpD2oS|17|27-988-546-2598|483.89|FURNITURE|ic requests haggle quickly across the deposits. regular, express ideas along the +589|Customer#000000589|TvdYNogIzDfr 1UyJE4b9RTENPmffmIoH|19|29-479-316-3576|1647.05|FURNITURE|s; blithely ironic theodolites sleep-- accounts haggle around the furiously silent ideas. silent, final packages in +590|Customer#000000590|4sHhhAZWHYRxJVz0KRgjW9IlKu,55IuT|8|18-734-215-6394|3993.54|MACHINERY|es. regular dependencies cajole furiously blithely regular ideas. regular dependencies cajole carefully a +591|Customer#000000591|wGE7AnEtiX7cmCkYA|20|30-584-309-7885|6344.66|MACHINERY| regular requests after the deposits cajole blithely ironic pinto beans. platelets about the regular, sp +592|Customer#000000592|srNO5Hu10z1Ru4rRPU,QpXzFwY8759wqZ|24|34-832-574-7217|9712.75|BUILDING|lithely final requests use slyly. special theodolites nag carefully-- carefully pending deposits cajol +593|Customer#000000593|SYyEL2nytJXBbFemMseCiivA32USVEDbvGzZS|9|19-621-217-1535|233.51|AUTOMOBILE|ve the regular, ironic deposits. requests along the special, regular theodolites lose furi +594|Customer#000000594|sbcKWltfCAnXrc Z27ZYDzsH1ztd,ZhgaD9xIMsh|9|19-286-925-8440|6518.42|HOUSEHOLD|. fluffily final instructions are slyly toward the slyly +595|Customer#000000595|7Q17BacxM,liY2AwhnHGR0Pjf1180sMz1U|19|29-554-215-7805|4177.17|HOUSEHOLD|gular accounts x-ray carefully against the slyl +596|Customer#000000596|hoByQV2JchlIWfzPFW8I0nCI|5|15-484-811-5482|1722.88|MACHINERY|ecial deposits after the slyly regular packages dazzle furiously across the courts. accounts wake. reg +597|Customer#000000597|Dbv,XVGzl4X|15|25-687-952-9485|2443.52|AUTOMOBILE|es across the slyly brave packages maintain quickly quickly dogged excuses +598|Customer#000000598|9ICLFWFZa6|9|19-113-384-3847|3244.78|FURNITURE|es. furiously pending packages haggle fluffily carefully silent foxes. carefully unusual dependencies boost fu +599|Customer#000000599|fIvpza0tlXAVjOAPkWN5,DiU0DO4e5NkfgOlXpDI|4|14-916-825-6916|6004.52|HOUSEHOLD|thely even requests wake carefully regular theodolites. instructions haggle alongside of the f +600|Customer#000000600|LOtVjPC,Eu,0I2BRCqWf,K|12|22-675-907-7888|2003.44|HOUSEHOLD|nstructions sleep among the final, even pinto beans. fluffily pending theodolites according to the +601|Customer#000000601|P3 Dv,6yllTNmL9yt6NUZZPZjvM2coWJd|1|11-104-635-9839|9768.21|BUILDING|ly according to the unusual foxes. carefully ironic accounts haggle accounts-- regular dolphins will integ +602|Customer#000000602|NCryKIpG3W,FDV2|13|23-434-900-7213|8404.90|BUILDING|nstructions. asymptotes above the forges are against the carefully +603|Customer#000000603|DFAIWiyqZ0GzuF6AWCZX3DcDxyICb3EWxEw|19|29-629-573-6194|8161.13|AUTOMOBILE|n packages wake carefully. special requests haggle slyly carefully bold deposits. furiously regular pinto b +604|Customer#000000604|qCQsFELZ3W hlmi,zOHBcZGo0PZl3jbFu1jsijqE|21|31-757-951-9827|3195.96|HOUSEHOLD|le furiously express instructions. ideas hag +605|Customer#000000605|QAxZ0IXgCzUfNjseQCLfh95HEi|23|33-269-948-8039|-549.73|HOUSEHOLD|ly regular foxes are quickly +606|Customer#000000606|vBIUd7LjRJ5rZXSzITHIvpZwBCClyt4Hjr Tlnf,|1|11-284-540-8460|9676.98|AUTOMOBILE|, bold packages. regular, final theodolites haggle slyly carefully final accounts. silently specia +607|Customer#000000607|m61hvYPASIGmNJx7Tu|24|34-601-151-4029|4038.45|FURNITURE|ymptotes. blithely bold requests shall are about the furiously final platelets. +608|Customer#000000608|luMI1JpfrrILCEeTgz8k98z|16|26-767-193-8671|2256.36|BUILDING|ld packages. special requests along the accounts are after the carefully unusual deposits. blithely quiet excuses c +609|Customer#000000609|dSpUFl8IR8Gh|21|31-869-580-1707|3651.06|FURNITURE|pending, express platelets poach furiously after th +610|Customer#000000610|Fo8RfPq1kgzD 0|11|21-782-663-7023|3374.92|BUILDING|uriously final deposits against the deposits detect alongsi +611|Customer#000000611|E1dtWGHE7NrLfnSKLPFU|19|29-924-242-5243|4272.43|HOUSEHOLD|inst the slyly final accounts. final packages wake after the even pinto beans. carefully +612|Customer#000000612|oNFqorGhq3a3woEp5q8xVDX|14|24-818-339-9984|7669.16|HOUSEHOLD|ns wake quickly quickly ironic accounts. regular accounts toward the +613|Customer#000000613|AJT,26RbanTdEHOBgTWg|4|14-275-416-1669|6679.75|AUTOMOBILE|ironic, pending deposits: quickl +614|Customer#000000614|YKweqHJfVok|18|28-698-510-6194|9630.24|FURNITURE|y even multipliers. pinto beans nag busily after the busily ironic reques +615|Customer#000000615|6aITapYMqM1fJQKuJD05Yb,6FhjrW|2|12-639-391-3956|-482.48|BUILDING|yly. blithely even accounts sleep blithely unusual in +616|Customer#000000616|yvUE7Qy3Ub6uGhPkuEJeOI|1|11-275-121-4443|6898.65|FURNITURE|ts. blithely bold packages sleep +617|Customer#000000617|Ifjxbt3Y4mGu|14|24-527-532-7752|3625.93|HOUSEHOLD|deas sleep slyly? final, even gifts about the furiously regular +618|Customer#000000618|9O4fhgteQdyFvCkrFm|0|10-675-573-1877|-932.38|HOUSEHOLD|uickly even ideas sleep slyly pending foxes. final, pending foxes nag slyly. permanent instructio +619|Customer#000000619|6bxrNxQA oes7cMa23R 5lDmIOIRThvd|24|34-245-618-6317|2336.99|FURNITURE|ts breach slyly after the slyly regu +620|Customer#000000620|3ztw9KQqKGNsiMM,I1 6g2f,u2Pm5LhlSEe8ZK1k|8|18-466-916-8135|5795.15|AUTOMOBILE|ructions boost furiously among the slyly final dolphins. regular, regular ideas w +621|Customer#000000621|IpFo6e22CRink74PUEPthY9DJJnSeORmQJ4|17|27-667-987-3718|3164.28|HOUSEHOLD|nstructions! final dependencies s +622|Customer#000000622|qdRHTTnVf9O2iFMG1sDm2GSnlM24tKWK|13|23-925-151-9771|5974.11|FURNITURE| asymptotes. slyly ironic excus +623|Customer#000000623|HXiFb9oWlgqZXrJPUCEJ6zZIPxAM4m6|9|19-113-202-7085|7887.60|BUILDING| requests. dolphins above the busily regular dependencies cajole after +624|Customer#000000624|L1hGsNrx4BiN5DIZGk7WMsB90T4ag|4|14-558-935-8773|3907.11|MACHINERY|le carefully. sly asymptotes sleep fluffily unusual packages. final deposi +625|Customer#000000625|uvgDE6eQ2bJp4BkHyVdpYYC8|13|23-789-801-2873|5744.89|FURNITURE|, pending deposits. sly theodolites along the carefully unusual +626|Customer#000000626|PDeE61VY2Q96efuewIZ|5|15-540-121-5663|5447.12|FURNITURE|t brave foxes. slyly pending packages wake furiously along the deposits. carefully pendin +627|Customer#000000627|uOFz ,iMYi02Ksr13Q2nBCETCpSp|15|25-811-790-3533|5826.68|FURNITURE|ages. regular ideas sleep. bold foxes affix. regular instructions haggle. bravely unusual requests haggl +628|Customer#000000628|Vzraru5KbgcC3V|17|27-367-742-4090|4954.25|FURNITURE|l dependencies. pending warhorses haggle. fluffily final accounts slee +629|Customer#000000629|LeXGhXX1mFQ0Cq,7taW ruvRHTpG3q,KkW|12|22-260-205-9116|5100.77|AUTOMOBILE|ic attainments. stealthily pending pinto beans affix carefully ironic theodolites. fluffily final deposits sleep da +630|Customer#000000630|XAw3WrAa mt0DnOuycb16LG9zbUv04DXsS|24|34-396-743-8684|3649.05|HOUSEHOLD|ely across the blithely stealthy ac +631|Customer#000000631|By LIK3TbJ67sJLlpaoOCXZheuX|19|29-864-813-2575|2603.00|MACHINERY|bold platelets haggle. slyly even pearls can solve slyly among the final foxes. slyly unusual r +632|Customer#000000632|sUlni97rSK6DIL|3|13-310-645-6928|-487.92|MACHINERY|ld dependencies sleep slyly along the special requests. furiously regular asymptotes use furiously accounts. +633|Customer#000000633|0pgCxndi1coDLkAV,UJJDMV0wtVVahCQaQap 0M|2|12-450-116-1239|3385.52|HOUSEHOLD|ully. even, final requests use slyly. blithely special packages wake carefully furiously busy +634|Customer#000000634|O09TejHJ6UszNfmqTR cmal8zcs|20|30-997-704-1110|6397.58|FURNITURE|e above the regular deposits. slyly even requests integrate slyly blithely express forges. regular platele +635|Customer#000000635|Ftqi0UYvzz56Ov,J6,ySp5WE4vJ2rtY|2|12-399-186-7550|8216.79|AUTOMOBILE|efully bold deposits doubt above the clos +636|Customer#000000636|7urmO1zY77WBPOWn7pXA OqCm3upL9gOtL4V|7|17-420-712-5063|3660.47|FURNITURE|ions boost furiously at the final dolphins. blithe +637|Customer#000000637|Ey7g4q2oH Q1vs|7|17-983-923-8985|7511.17|HOUSEHOLD|ly furiously even accounts: final, unusual Tiresias do snooze theodolites. slyly regular dependenci +638|Customer#000000638|yyRRorZ HHzU1yJwNJwF72dvUVJ nMlzpKAXEb|24|34-102-347-8343|2258.40|HOUSEHOLD|nts x-ray fluffily across the theodolites. carefully final pearls cajole ruthl +639|Customer#000000639|8OiPHefIPoalRjUoCIwbXz|15|25-221-133-2233|4899.15|MACHINERY|ly bold asymptotes. ironic, even d +640|Customer#000000640|j3vjr0 n,pJFG4gIOtC|2|12-702-315-6637|3025.84|HOUSEHOLD|lly. furiously quick deposits haggle quickly regular packages. pinto +641|Customer#000000641|gbIvFlCygHjj5NG7U|24|34-761-987-7777|339.49|AUTOMOBILE|uriously final requests boost regular, final ideas. fluffily busy packages promise? requests along the bold, s +642|Customer#000000642|6Y1gEH0gMLh0yzlipNR|22|32-925-597-9911|5684.01|AUTOMOBILE| requests cajole blithely quick +643|Customer#000000643|9T 2avhfyF PQ|0|10-978-597-2747|5184.70|FURNITURE|fily along the quickly ironic ideas. final, final +644|Customer#000000644|bfZrdZE0QHtMc,ksudO|18|28-489-845-4801|6183.15|HOUSEHOLD|ke slyly alongside of the silent, even req +645|Customer#000000645|I,Kso,IZ,AL2rK4HhIB1wRWWrx3 yoaZlFs|11|21-242-974-5799|1146.49|BUILDING|. special packages haggle ruthles +646|Customer#000000646|gogI8kweD 2H6U,01lbIp0UWUwljSue,KRcC|2|12-177-329-4316|6074.42|HOUSEHOLD|ptotes. silent requests cajole fluffily along the slyly permanent ideas. pending instr +647|Customer#000000647|2Bx7,7i87h5cagC,ZBz49lyiziLqQoD|1|11-873-931-2886|-132.97|BUILDING|. excuses use alongside of the furiously final deposits. blithely express foxes wake furiously. blithely +648|Customer#000000648|pYCT1OLD5Y7rBjjAKnf0Lqd 41RC,0n,nT3oNWz9|7|17-473-731-8352|7029.24|FURNITURE| wake carefully outside the ironic, bold packages. blithely special dependencies boost slyly even ideas. careful +649|Customer#000000649|EntXL7MF4lU|11|21-656-678-1337|9442.55|BUILDING|unusual deposits engage along the carefully pen +650|Customer#000000650|1hqwYdlDhaqnkRrovbulo0rrDhJZgUz|5|15-842-586-1263|2086.91|AUTOMOBILE|g to the final deposits. quickly regular requests dazzle along the slyly express courts. +651|Customer#000000651|K7rCTwTb3UX9wAO6ihvYxwBOuJNx51|9|19-610-541-4787|4716.31|HOUSEHOLD| fluffily quick dependencies cajole slyly along the blithely final dependencies. carefully pen +652|Customer#000000652|0WlNKsoRqdjU9,5 Qz,bgm5swI,i0Kg|20|30-254-389-5987|-919.65|AUTOMOBILE|p carefully blithely bold platelets. furiously unusual deposits wake. sl +653|Customer#000000653|la,ROBPJ4I2YNzQw,RpbB0sTOjyv3F ZBeWRiQ|11|21-715-573-6928|7307.55|BUILDING|aggle bravely deposits. even du +654|Customer#000000654|Ip,OhnmOeHu9PezZBvw7AHJcBDOWVoVUJKsJyA|16|26-416-434-3449|1067.04|AUTOMOBILE| nag slyly. final deposits sleep along the ironic, bold i +655|Customer#000000655|SceikyyffYL5OUI8rFnAgrT5E|14|24-916-820-5158|1724.68|FURNITURE|e accounts. unusual, pending platelets are quickly. req +656|Customer#000000656|DeZPec2K1U1fCBR2Ul9mnBNjKuXPcRcm|5|15-379-993-4446|-390.09|AUTOMOBILE|uests cajole quickly. final, pending pinto beans wake furiously among the requests. ironic foxes with the forg +657|Customer#000000657|BpXQ3sbx8bCU0|19|29-952-164-8914|8729.97|FURNITURE|ies boost slyly bravely express instructions. fluffily even theodolites integrate s +658|Customer#000000658|9SboxGtXimmJg49IyT3Zt|1|11-675-750-9832|4716.68|HOUSEHOLD|r ideas about the slyly ironic theodolites integrate according to +659|Customer#000000659|ThR9miOedPuwVEZyz 3MMjHPwB|0|10-834-287-1466|5297.68|HOUSEHOLD|s cajole final, regular dependencies. final accounts sleep! furiously regular requests wake slyly silent +660|Customer#000000660|ZD4fphyxb5pyE|0|10-987-901-3986|2110.30|MACHINERY|ding excuses haggle furiously regular foxes. finally +661|Customer#000000661|1MqWuuRVM5y5NlT1kakwke|4|14-983-203-6472|1735.44|HOUSEHOLD| regular theodolites. brave platelets +662|Customer#000000662|ss AgOrB5VFubLk bsmTgbw2ddJD|0|10-728-355-4532|4517.33|BUILDING|ckages haggle: quickly regular ideas are after the furi +663|Customer#000000663| fqLQWxHWWC40GUOgVvb4idYDbE1Gxc6|9|19-613-882-5677|9698.21|AUTOMOBILE|r the slyly final packages. slyly bold attainments detect blithely acco +664|Customer#000000664|viRe1P6HiyL4LXpU7HPwu|15|25-329-655-5068|8878.22|BUILDING|yly ironic requests cajole pending pla +665|Customer#000000665|Fo9QgQsDOP28D3zR|22|32-759-858-2984|-616.79|BUILDING|y along the special requests. blithely regular waters thrash abou +666|Customer#000000666|dD32Q8kL6KW|2|12-594-508-9621|4538.54|AUTOMOBILE| special packages boost across the even accounts. ironic accounts serv +667|Customer#000000667|oQqeEC,OD9XC1JXyOsHqcpv0fPUdP9ek5KKb70tQ|6|16-917-453-2490|3288.76|AUTOMOBILE|lithely about the furiously sil +668|Customer#000000668|PCmw0r6KkLjXZsljablJ|15|25-582-501-2346|8184.21|FURNITURE|uffy excuses are carefully regular, ironic pinto +669|Customer#000000669|axdO3iaVyYXSxnqnwC0p2Dx6Mn3lDDMp|10|20-471-280-4789|6019.20|MACHINERY|ronic decoys. blithely ironic accoun +670|Customer#000000670|RJtcLv6Tjpx|2|12-839-426-4266|6738.93|BUILDING|y unusual deposits are carefully regular foxes. packages dazzle carefully. furiously unusual d +671|Customer#000000671|ic6qGrt0giB,HDEiBK,,FYGHXQpc|21|31-593-213-9388|3227.87|FURNITURE|bold ideas above the ironic packages affix blithely about the furiou +672|Customer#000000672|Rsq8zHIbqRRB8VlgldFlU56j,0SN |18|28-774-971-2700|7778.95|BUILDING|ake. regular requests about the idle asymptotes haggle slyly final, silent packages. carefully special +673|Customer#000000673|Q2S9DoW6mQN5iQ0A8DxD6UxNmPZky|4|14-769-230-8609|3942.58|MACHINERY|ons will cajole blithely. always even packages dazzle blithely across the regular, unusual +674|Customer#000000674|GLZCUQrtiNTrPKdK 0O86ZF|5|15-543-819-4391|7889.64|BUILDING|ites cajole ironic accounts. regular, ironic gifts nag furiously against the blithely express deposits; unusual, +675|Customer#000000675|canew8kOzr8RDTmenqJOn|20|30-299-640-9565|5295.26|HOUSEHOLD|riously even requests boost slowly. ex +676|Customer#000000676|JzJnD kA3KTjTYl|24|34-710-820-8362|5527.61|HOUSEHOLD|es. slyly even theodolites across the slyly ironic accounts nag from the slyly even accounts. accounts are. +677|Customer#000000677|,wTtWOOr wqX2sL,h79myT6nxG1EgY|3|13-398-309-9122|5582.63|AUTOMOBILE|ly brave ideas haggle slyly blithe acc +678|Customer#000000678|BiQyhSp oiDp,,MFVxyrOwMT810qiQlISEPye|9|19-508-735-4910|6302.93|AUTOMOBILE|gainst the carefully pending requests-- furiously special requests haggle? not +679|Customer#000000679|IJf1FlZL9I9m,rvofcoKy5pRUOjUQV|10|20-146-696-9508|1394.44|AUTOMOBILE|ely pending frays boost carefully +680|Customer#000000680|TuONtFVII8TR2QtJyl1lS5f0iagaWWsBm1IQo|12|22-593-663-2200|4366.23|AUTOMOBILE|kages: final deposits believe unusual deposits: b +681|Customer#000000681|x85ncT W41KEcUQCtxE,LD iMNO6j4Hh4x|20|30-809-878-5822|235.53|MACHINERY|ate carefully. accounts hang carefully along the blithely final theodolites. bravely sile +682|Customer#000000682|y5J0HJVI6Mb k4rXTAPbxE9aw|15|25-233-924-7389|7420.60|AUTOMOBILE|he bold, even accounts breach +683|Customer#000000683|G0, q8c6vBykpiLvcuSJLYvqE|6|16-566-251-5446|9120.93|MACHINERY| somas use-- slyly express foxes wake quickly blithely iro +684|Customer#000000684|5kSJ3qMS,7YKdfmwBFzQN4y8EgPiH,8ln19|15|25-456-286-6398|8545.90|HOUSEHOLD| of the bold requests. blithely regular accounts nag alongside of the carefully silent dolphins. carefully +685|Customer#000000685|eRvmYOdl5v|17|27-269-224-9902|2039.84|MACHINERY|nusual ideas. pending packages use carefully. slyly special sentiments cajole after the blithely even accounts. blit +686|Customer#000000686|1j C80VWHe ITCVCV|6|16-682-293-3599|5503.36|HOUSEHOLD| even deposits print quickly. foxes wake. furiously ironic asymptotes across the bold foxes +687|Customer#000000687|UJTC3 WtzvoD39r1GuoCP|21|31-149-119-1456|4999.31|FURNITURE|special packages haggle carefully slyly ironic pinto beans. sl +688|Customer#000000688|2QBxK8WIryWMZTsDM JS7GxWCB6Y71Swa,f1EUxk|8|18-210-546-2836|3354.47|HOUSEHOLD| use alongside of the ironic, pending foxes. final packages use. ironic, unusual dependencies haggle +689|Customer#000000689|Gcie9Q,Wc6J0QvKcefqflajjOtOVchnxqBn9|24|34-325-146-3591|1481.24|MACHINERY|ions. furiously unusual platelets cajole blithely. caref +690|Customer#000000690|xH61m,Si5X4REvi|3|13-489-760-5455|103.45|HOUSEHOLD|nt deposits. final, unusual requests use blithely. slyly unusual packages against the carefully bol +691|Customer#000000691|0RkDX6OLU1hISYCLmdLD C|16|26-741-688-4189|9566.15|MACHINERY|p. ironic, regular foxes against the ironic, special theodolites nod carefully quietly unusu +692|Customer#000000692|d6XE9sg, wINvIz8aZS b8n XuhAQU5|19|29-804-421-1703|276.71|AUTOMOBILE|cuses. slyly even asymptotes doubt quickly. fluffily thin theodolites boost. ca +693|Customer#000000693|r5gn5SUW0tsfkOw42x84|1|11-391-870-8153|6577.21|AUTOMOBILE|onic packages. carefully final sauternes across the even, express deposits h +694|Customer#000000694|3ToF2HqyF9mEcP1QgW NMN,6,KsFq6x4u14MS|10|20-646-375-1939|2222.65|BUILDING|efully final requests detect blithely. furiously ironic p +695|Customer#000000695|fbT9dQCc,su7JboB5FWI6|8|18-131-151-7466|9126.54|FURNITURE|ly express deposits according to the fina +696|Customer#000000696|dYyj4azN0EE GqeZxv|22|32-923-916-5643|3778.97|HOUSEHOLD| ironic ideas among the carefully bold foxes na +697|Customer#000000697|LFwdGCTUYDenZGoA9|4|14-613-651-2263|8121.84|AUTOMOBILE|he regular pinto beans. courts cajole carefully according to the blithely even theodolites. quickly +698|Customer#000000698|FLZ2NG5pKHpPtAh|23|33-282-178-6799|2894.22|BUILDING| sauternes. gifts cajole. slyly pending platelets cajole at the iron +699|Customer#000000699|4R6pspbuk5Sp,036VraUEKPBzs|4|14-865-140-8680|-809.22|HOUSEHOLD|. finally even ideas wake slyly pending dolphins. slyly even instructions wake whithout the p +700|Customer#000000700|zyWvi,SGc,tXTls|0|10-351-119-7514|4367.53|MACHINERY| bold excuses. furiously even asymptotes across the carefully regular dugouts cajole fur +701|Customer#000000701|yQU8LcjocNHkk1hse30M0U1f46MrU6dB|2|12-323-784-5793|148.98|FURNITURE|c packages. blithely final instructions according to the regular pinto beans +702|Customer#000000702|BDKtDAva8rBuCWXT6jXb2JJY7YoRS|3|13-549-296-5659|4782.05|FURNITURE| silent accounts. regular, regul +703|Customer#000000703|ge1GEYt4ewGUiSeqBA4rNB5JhyQ92uKF|6|16-741-513-6919|3998.42|AUTOMOBILE|arefully final accounts cajole quickly blith +704|Customer#000000704|41s9yU0ossOKgBvjPPSTZqhfciy|9|19-998-886-1551|441.44|AUTOMOBILE|ously ironic instructions believe about the pending, regular deposits; final accounts cajole alongside of t +705|Customer#000000705|YKdZRFEGcclF6rmdoiNCY8|18|28-991-405-7914|3199.00|BUILDING|s pinto beans sleep busily. ironic, bold theo +706|Customer#000000706|ycxysGDuWHN98FS4lZ2obT9ZPNRWjJTsHbQXvi|19|29-468-275-6045|6496.08|AUTOMOBILE|ses cajole furiously after the ironic requests. pinto beans sleep busi +707|Customer#000000707|DT0nzkijELHyI|21|31-796-903-4461|2619.52|FURNITURE| the deposits. fluffily ironic pinto beans wake quickly. slyly even foxes sleep slyly quickly final deposits. ev +708|Customer#000000708|9iJJ868sXAdFgZyo0V8cfPRTRaUc3d|17|27-796-490-6026|2297.33|BUILDING|p along the carefully ironic pinto beans. even pinto beans are fluffily against the furiously quick dolphins. s +709|Customer#000000709|drDnC6YXTJgcdfJkpbhrQ7z7XmCsoym2t22jwg|18|28-117-812-5493|-867.94|BUILDING|g the blithely ironic multipliers sleep a +710|Customer#000000710|OCLSZuXw1AEK NLvlofMkuK,YNe,bJD40a|22|32-459-427-9559|7412.12|FURNITURE|ges integrate express, even ideas +711|Customer#000000711|EmACeG3r2Y9bxf7KLLgX,ZdQlATjGaafINO|15|25-306-725-3622|9591.51|MACHINERY|ackages promise. theodolites haggle along the express dolphins. special, special deposits affix slyly final pac +712|Customer#000000712| 8w2pIiA4wWAhtjAdXR|6|16-843-486-5087|8667.09|BUILDING| express dependencies use fluffily final platelets. furiously regular accounts wake furiously. carefully careful cou +713|Customer#000000713|ov fZJgESFHP P|10|20-595-832-3185|3829.03|MACHINERY|lites sleep slyly furiously express requests. even, even notornis affix furious, ironic p +714|Customer#000000714|2,ARep1aMyhgNZqrkc,toQ3XY6FOiCZqNW|9|19-209-782-4244|2438.10|BUILDING|cross the bold pains. bold instructions haggle. even accounts wake slowly. carefully busy ideas need to x-ray sly +715|Customer#000000715|9qLvF42uxUarKl4I 2pEKOMNJmo8Ro5EK|19|29-500-408-6392|85.05|AUTOMOBILE|hins boost quickly. quickly regular epitaphs haggle fluffily quickly bold pinto beans. regular +716|Customer#000000716|jbXpMEcV9j,6ciftBXEMXDjE|12|22-501-849-6084|8364.99|AUTOMOBILE|as. even accounts about the slyly pending excuses lose bl +717|Customer#000000717|TqWi1c aNhdExPcDD7KQ18W|12|22-660-518-8009|8510.94|MACHINERY|ns poach slyly. carefully express pinto beans ab +718|Customer#000000718|w,GXCSSI4NEHAFPKG|20|30-605-635-8197|8438.40|HOUSEHOLD| regular packages-- pinto beans detect ironically. furiously even accounts detect unusual, pendin +719|Customer#000000719|wry Gj3xd8QX ylUCulG|15|25-498-699-7824|-774.47|HOUSEHOLD|gly express pinto beans sleep furiously around the quick foxes. +720|Customer#000000720|8shFEL7J9sq1NJXR8dixBqaTO,kbSx|22|32-575-838-4260|5357.32|HOUSEHOLD|furiously above the furiously ironic c +721|Customer#000000721|N6hr4gV9EkPBuE3Ayu |21|31-174-552-2949|3420.64|AUTOMOBILE|ar instructions. packages haggle stealthily ironic deposits. even platelets detect quickly. even sheaves along +722|Customer#000000722|aymiuXFyrALTRIzfbLDvtaj37ydq|20|30-633-109-9587|2724.80|BUILDING|leep sometimes express accounts. regular theodolites wake quickly ab +723|Customer#000000723|5tKvCvmVB0yxyAF|21|31-542-178-2520|738.57|BUILDING|e quickly against the blithely final requests. regular pinto beans nag fluffily fur +724|Customer#000000724|dF80enl1y5MfccEMqYz0JSY|5|15-316-638-4703|3035.29|AUTOMOBILE|s. bold accounts about the carefully final packages detect slyly pending platele +725|Customer#000000725|fm8t3X05Wm,PQxPSPHZy,rHI,wUBLTFO5S |16|26-923-317-3870|5030.24|FURNITURE|ts. accounts after the even pinto beans boost across the ironic, silent accounts. reques +726|Customer#000000726|4w7DOLtN9Hy,xzZMR|3|13-168-233-7513|6253.81|BUILDING|wake after the regular, final instructions. final epitaphs mold fluffily blithely ironic id +727|Customer#000000727|wLIX8hKnk0qjUAAGqm|18|28-815-316-3525|807.37|FURNITURE| requests-- quickly regular pinto beans need to detect +728|Customer#000000728|uACufK5vIMlsq,v9d4U5ZWi,|24|34-195-384-1105|4349.73|BUILDING|re stealthily furiously bold requests. carefully final pinto beans lose slyly +729|Customer#000000729|YZxBLBAqBmW53g2ia6s4u,MlJ4WhW|20|30-900-572-2883|8947.26|MACHINERY| packages about the furiously even foxes sleep furiously furiously pending ideas. slyly ironic epitaphs +730|Customer#000000730|ORP6ofUwyD1|2|12-513-973-2702|4718.23|AUTOMOBILE|foxes would cajole furiously slyly special forges; slyly regular pinto beans inste +731|Customer#000000731|D0ceqTVRO3EctrC|7|17-731-915-9753|9311.17|MACHINERY|lar dolphins are carefully slyly final theodolites. unusual accounts integrate across the regular, final deposit +732|Customer#000000732|tQ,r4voHok7oeKw9msDh4ORGje|16|26-154-285-2634|4830.51|BUILDING|structions are after the even deposits +733|Customer#000000733|Ks7Ed2g7zDP905tLGdGcFtomDNchNdaPK2cd|13|23-110-948-6754|4351.09|HOUSEHOLD| furiously. pending, quiet packages nag slyly. stealthy pinto beans haggle +734|Customer#000000734|xULRxhbfzPT5nBh|18|28-880-175-5173|9750.71|AUTOMOBILE|tions against the ideas haggle furiously quickly regular forges. carefully final requests solve even, +735|Customer#000000735|8Gn WOTY4cgGaoHwezrZ,JN,Px8e sr|5|15-959-576-4327|293.88|BUILDING|ites. furiously unusual frets boost among the slyly ironic theodolites. packages cajole +736|Customer#000000736|zQNs5e2aFcVY8MigFQEBtoCaQ9e|1|11-617-726-2039|9114.68|MACHINERY| the deposits. blithely regular asymptotes boost q +737|Customer#000000737|NdjG1k243iCLSoy1lYqMIrpvuH1Uf75|18|28-658-938-1102|2501.74|AUTOMOBILE|ding to the final platelets. regular packages against the carefully final ideas hag +738|Customer#000000738|iecb89zRRNeN3KywZSaPXEWMjz|10|20-722-370-5220|2734.95|MACHINERY| carefully slow instructions. furiously express dependencies alongside of the ca +739|Customer#000000739|pAROUfTi3wCEHi1PXu|14|24-309-302-6776|6344.18|HOUSEHOLD|ly regular accounts. blithely final theodolites sleep blithely. furiously regular decoys cajole blithely. bold de +740|Customer#000000740|FCerGpsfsWAsBrQTyqdzMxUQnbQembHKGg|10|20-215-156-3727|1733.76|BUILDING|ets. final, blithe theodolites abou +741|Customer#000000741|jiPAOQuJ5gIauMfvcbE8lKUVPMp|12|22-560-854-2068|9195.41|HOUSEHOLD|ve the fluffily regular accounts wake carefully ironic grouches. slyly bold theodo +742|Customer#000000742|2qRObRkFktME6SsNV0Pa3L8txbA0AFtXuWsKrkW|12|22-610-582-8610|6381.24|HOUSEHOLD|eodolites alongside of the daringly ironic deposi +743|Customer#000000743|WJ lVLsFSgZJCHHLqwRmvCjWvYlCs0c2TvO|20|30-743-559-7934|8450.37|HOUSEHOLD|ptotes. furiously even accounts haggle slyly. ironic foxes sl +744|Customer#000000744| nYSoGuQkf|7|17-121-555-4268|2458.81|HOUSEHOLD|n packages. furiously silent foxes sleep regular, regular accounts. slyly ironic patterns cajole fluffily +745|Customer#000000745|vjuHvDKdaomsivy l|18|28-913-438-9403|7115.14|FURNITURE|o beans. bold, regular theodolites haggle carefully about the quickl +746|Customer#000000746|JOKj8N2QKUm8Gi,F4qX0fLVy|20|30-154-354-9928|1164.46|MACHINERY| final theodolites. final pinto beans haggle-- furiously +747|Customer#000000747|uuichgTY7NjlZaaRZ6S7KzvapZWvAiCUWAQr|8|18-793-504-2931|67.95|FURNITURE|eodolites. blithely regular pinto bea +748|Customer#000000748|1 nkl3GMSnweulTNAMPeB8Sa5aSIk|23|33-403-226-2580|6959.09|AUTOMOBILE|nts. special excuses thrash blithe +749|Customer#000000749|U1Dvu0r793a|24|34-158-697-9591|7491.42|MACHINERY|accounts was. final, final requests wake. theodolites was slyly. blithely even foxes wake carefully ac +750|Customer#000000750|5OyNRajjgjjbaXtI rkxvB2lX4c6u|8|18-235-587-1274|269.90|BUILDING|s. regular, regular deposits sleep carefully blithely bol +751|Customer#000000751|e OSrreG6sx7l1t3wAg8u11DWk D 9|0|10-658-550-2257|2130.98|FURNITURE|ges sleep furiously bold deposits. furiously regular requests cajole slyly. unusual accounts nag unusual ide +752|Customer#000000752|KtdEacPUecPdPLt99kwZrnH9oIxUxpw|8|18-924-993-6038|8363.66|MACHINERY|mong the ironic, final waters. regular deposits above the fluffily ironic instructions +753|Customer#000000753|9k2PLlDRbMq4oSvW5Hh7Ak5iRDH|17|27-817-126-3646|8114.44|HOUSEHOLD|cies. deposits snooze. final, regular excuses wake furiously about the furiously final foxes. dependencies +754|Customer#000000754|8r5wwhhlL9MkAxOhRK|0|10-646-595-5871|-566.86|BUILDING|er regular accounts against the furiously unusual somas sleep carefull +755|Customer#000000755|F2YYbRT2EV|16|26-395-247-2207|7631.94|HOUSEHOLD|xpress instructions breach; pending request +756|Customer#000000756|Lv7cG by4Wyd8Hzmumwp8hSIZg9|14|24-267-298-7503|8116.99|AUTOMOBILE|ly unusual deposits. fluffily express deposits nag blithely above the silent, even instructions. expr +757|Customer#000000757|VFnouow3LhLvEDy|3|13-704-408-2991|9334.82|AUTOMOBILE|riously furiously unusual asymptotes. slyly +758|Customer#000000758|8fJLXfS5Zup0GQ3xBKL3eAC Q|17|27-175-799-9168|6352.14|HOUSEHOLD|eposits. blithely unusual deposits affix care +759|Customer#000000759|IX1uj4NFhOmu0V xDtiYzHVzWfi8bl,5EHtJ|1|11-731-806-1019|3477.59|FURNITURE|above the quickly pending requests nag final, ex +760|Customer#000000760|jp8DYJ7GPQSDQC|2|12-176-116-3113|2883.24|BUILDING|uriously alongside of the ironic deposits. slyly thin pinto beans a +761|Customer#000000761|oObRVLlulGS5xikRk8La|19|29-835-631-4258|1525.96|BUILDING|ress Tiresias haggle across the never ironic ideas. blithely pending theodolites cajole ironically +762|Customer#000000762|n5QsjD,gTSrdNRoRpvWqS|11|21-757-455-7898|3764.90|FURNITURE| sublate carefully carefully regular deposits. bold foxes along the gifts nag +763|Customer#000000763|ACMrkbcf3a2J3aobVEmU5hGnHuc|1|11-232-719-3610|2650.27|BUILDING| ironic asymptotes are. slyly bold realms alongside of the fluffily specia +764|Customer#000000764|F8WBznjtO2bX2knXl4ghnsp ixWylkf|16|26-714-322-4800|2061.45|MACHINERY|tructions. quick theodolites kindle +765|Customer#000000765|b7w2edOUZNe0QX 3Ab3y5RFlMZX|20|30-544-657-7473|5683.33|AUTOMOBILE|ter the blithely regular foxes. slyly bold packages use bl +766|Customer#000000766|zGTH6uWKoQxIE|16|26-283-847-8946|4677.55|BUILDING|ly special deposits boost blithely above the slyly ruthless ideas. carefully bold asymptotes unwind about the e +767|Customer#000000767|9f3 XsYXdvP0E39ZBi7r7oRCns3PTx,H|17|27-526-143-3959|7647.09|BUILDING|ngly express dolphins boost carefu +768|Customer#000000768| ,cIZ,06Kg|18|28-851-493-8588|9618.84|BUILDING|to cajole blithely express asymptotes. foxes use quickly. carefully special ideas could have to are bravely bl +769|Customer#000000769|0eGzsjpDFsN0|5|15-102-635-4835|5950.86|HOUSEHOLD|ggle slyly pinto beans. furiously even excuses above the +770|Customer#000000770|IjwJR6TjBJZbKIeouH2d|8|18-856-112-5677|2066.79|AUTOMOBILE|dolites haggle express, express requests. furiou +771|Customer#000000771|J9UMiYJznHVHZDuCG,ErV0iiMStETS|23|33-761-371-4753|7461.74|AUTOMOBILE|arefully unusual accounts shall boost unusual pinto beans. ironic, final ideas boost. slyly i +772|Customer#000000772|TBxlR0AAHeSYl0vyK 8joF|20|30-405-614-4887|7555.16|MACHINERY|ular requests. final ideas sleep. regular, even platelets could haggle blithely bol +773|Customer#000000773|NyRSeog kIkD7YOb0EuSfSGxfptN5nkX26Mk6|8|18-456-377-3723|4578.24|FURNITURE|hely silent ideas could doubt carefully al +774|Customer#000000774|95 O8gd08tdtmJwM0ebHUnDc|11|21-463-652-6686|-506.37|HOUSEHOLD|nd the bold platelets affix furiously doggedly express accounts. carefully unusual deposits serve furiousl +775|Customer#000000775|Cg3M4gTXeIY7llMN2puop7D2|17|27-903-936-7924|1376.67|BUILDING|ts. blithely regular requests upon the ironic, final courts haggle sly, regular deposits. final requests +776|Customer#000000776|rzhIStRHsiWoc6K,7yv3YMqVdrz|15|25-941-650-8313|2669.01|AUTOMOBILE| express accounts. furiously ironic theodolites serve blithely. blithely thin packages are among the eve +777|Customer#000000777|27adTXaVp7araW|20|30-765-163-9750|9097.52|AUTOMOBILE|pinto beans; furiously special platelets haggle quickly against the slyly unusual foxes. +778|Customer#000000778|tCuRA2W9y5iiGrcT7a4TzK|23|33-702-179-3134|52.43|MACHINERY|hely ironic instructions. regular, ironic requests affix along the carefully +779|Customer#000000779|2cTZiS4ulZ74edT,RmDnh4ZaCrphMMh Ff2|5|15-940-483-5702|-902.48|HOUSEHOLD|old dependencies. pains haggle fluffily carefull +780|Customer#000000780|CMxcdzgEUkCWP1|8|18-844-576-7345|9874.12|FURNITURE|, final packages use slyly regular deposits. slyly ironic instructions nag careful +781|Customer#000000781|FQCAkyfV0 kL3,FNA1OlBjABak|18|28-478-388-5881|6403.62|MACHINERY|ake blithely blithely final foxes. blithely silent pinto beans haggle furiously. fluffily bold acco +782|Customer#000000782|HFuyemzqz0g QhkL|19|29-850-576-7450|-326.32|AUTOMOBILE|usly bold deposits-- furiously ironic accoun +783|Customer#000000783|01bR7OOM6zPqo29DpAq|1|11-920-256-8525|2436.32|FURNITURE| slyly carefully pending packages; doggedly bold theodolites boost slyly slyly dogged excuses: slyly expr +784|Customer#000000784|evcGXqbosO6,qhx|14|24-975-574-2063|3170.47|BUILDING|cajole quickly. ironic dependencies wake quickly. silent ideas use furiously +785|Customer#000000785|gEkI8kSq8RYgO6tiTA0AB7urZX8s2w03JGwtMi9|18|28-808-670-2983|108.14|BUILDING|nal theodolites. dogged, ironic deposits wake carefully. slyly regular requests after the furiously ironic +786|Customer#000000786|viZtkiJ gbMcPrINM3Ez,33vOJW|13|23-413-365-2022|400.03|MACHINERY|ccording to the regular deposits. carefully final packages run. slyly final deposits h +787|Customer#000000787|wwPe2vMZZ1n1Mm2z0qzDfS43FPj2Ndn|10|20-210-617-3870|212.16|AUTOMOBILE|e. ironic theodolites serve regular foxes. pending requests haggle slyly busy instruct +788|Customer#000000788|LbFHoDpNUSu3AyDS7KLgjoQBJV|16|26-388-689-9272|-330.69|FURNITURE|. unusual packages against the +789|Customer#000000789|DW0NMV Ci5V2bnsX0Al98plG1J0QZqNwcjEVW|9|19-176-517-4263|6038.60|BUILDING|as. quickly special courts integrate slowly final accounts. ironic packages are slyly about th +790|Customer#000000790|CR bzmYYVP|0|10-368-832-9671|2724.98|BUILDING|riously final requests haggle to the blithely special requests. blithely pending gifts after the carefully silent id +791|Customer#000000791|3ZWQ5xexnnLDEmxpmbg|13|23-575-775-4059|3694.81|HOUSEHOLD|posits cajole carefully along the slyly final packages +792|Customer#000000792|icVt7HjGs,p3YL3nr1MHgaQIY5Gmzej57nB,b|7|17-392-500-4370|1672.46|AUTOMOBILE|latelets along the carefully even packages cajole blithely packages-- even pinto beans haggle +793|Customer#000000793| SltK1IMp2Xvwb,A0x3Co1uhcwr|0|10-404-953-9048|2072.99|BUILDING|uickly silent foxes use after the +794|Customer#000000794|RMY8 LyGnJ67NGc5cxPYiIDSF|23|33-633-470-5945|1709.50|FURNITURE|gular patterns cajole slyly blithely final ideas? furiously unusual courts wake among +795|Customer#000000795|droXvSIcNEElsEYS|14|24-973-990-6608|8443.18|HOUSEHOLD|packages cajole furiously since the slyly +796|Customer#000000796|79bj5Rk3jJj9ked7M|3|13-554-411-6773|2584.23|HOUSEHOLD|re slyly even deposits. pending pac +797|Customer#000000797|bdGkzA5duas6LZ1ywB96K6Av3x 99q95h|0|10-994-609-7082|3063.11|HOUSEHOLD|iously regular packages mold fluffily. express, idle accounts nag furiously across the carefully ironic req +798|Customer#000000798|wW2OgnHj6dBz tO9OXFqCLm|4|14-670-423-7529|-391.13|HOUSEHOLD|sleep slyly ironic, express ideas. slyly special packag +799|Customer#000000799|LVk8ljWeIYTQQFMKCmxEeRpWQT|12|22-909-693-7833|2263.25|MACHINERY|ets haggle. busily final packages nag carefully after the bo +800|Customer#000000800|mpI6pkdnWLZsBbQi4,uUC5Y3TcM9vmRIgZelrQ|14|24-555-630-2261|9443.39|AUTOMOBILE|ly alongside of the carefully ironic deposits. blithely ironic packages are blithely agains +801|Customer#000000801|UQ67hfDJlxgX68hiFPmDuHav12Vx|16|26-439-495-8236|5207.32|FURNITURE|sits wake blithely according to the slyly un +802|Customer#000000802|ZDk4Suvi8gMp2LLAOW6nFA 3u|0|10-606-236-5778|1377.52|BUILDING|the carefully even pinto beans. carefully unusual pinto beans against the asymptotes cajol +803|Customer#000000803|zm7Xs6RJJJfZ|18|28-855-429-9109|6003.09|BUILDING|. blithely special instructions +804|Customer#000000804|u6xYwCLD,Vd4ODt8|24|34-861-760-4796|3.43|AUTOMOBILE|usly. final accounts integrate slyly above the furiously sly pinto beans. furiously unusual ideas +805|Customer#000000805|wCKx5zcHvwpSffyc9qfi9dvqcm9LT,cLAG|10|20-732-989-5653|511.69|BUILDING|busy sentiments. pending packages haggle among the express requests-- slyly regular excuses above the slyl +806|Customer#000000806|FTM62Dujm2BoblKFY w|12|22-888-883-2475|6859.28|FURNITURE|the carefully regular accounts breach above +807|Customer#000000807|zKjtrn5FGIs|17|27-333-779-5333|1929.89|MACHINERY|y final patterns? carefully pendi +808|Customer#000000808|S2WkSKCGtnbhcFOp6MWcuB3rzFlFemVNrg |19|29-531-319-7726|5561.93|BUILDING| unusual deposits. furiously even packages against the furiously even ac +809|Customer#000000809|eApaa5hW3Mqp11ZuOP|16|26-776-223-5427|-594.23|HOUSEHOLD|ackages. quickly unusual dugouts c +810|Customer#000000810|3J1wwVhwzVT7XM1v3Rzx90a8c4|9|19-997-929-2765|9632.77|FURNITURE|ep pending deposits. quickly bold accounts are carefully instructions. ruth +811|Customer#000000811|Rau3ADOLCNXM42D6fjQTFuueQce2BHw9r|15|25-575-731-2159|9010.02|BUILDING|kly pending foxes dazzle fluffily after the furiously bold packages. fluffy +812|Customer#000000812|u9uI3BE68quHja6k0,UXRYFgvLHl3jKhn|17|27-714-618-2239|3428.67|BUILDING|ar packages. packages thrash amo +813|Customer#000000813|VBNrCYm67O|9|19-585-173-1514|5673.47|HOUSEHOLD|ts cajole silently bold pinto be +814|Customer#000000814|KmMC1nd5iOXTRlhzMu13Wtx|15|25-342-269-3824|4011.18|BUILDING|yly at the blithely regular excuses. carefully thin pinto beans boost slyly furiously regu +815|Customer#000000815|TmpTFwt3b0 WQUmljE1LKbg50dtQszn67qEog|12|22-941-606-7227|5841.33|HOUSEHOLD|unusual accounts. slyly ironic pinto beans nag against the regular, regular requests. slyly p +816|Customer#000000816|k2dnnQZowe|24|34-457-910-7430|9239.32|BUILDING|accounts cajole slyly quickly express platelets. carefully silent theodolites wake carefully. pe +817|Customer#000000817|jDJt0Wfk0,Wcx5HOI5itS XqUJmMpjzJ|0|10-566-341-4382|7297.64|MACHINERY|y against the carefully special patterns. unusual accounts sleep quickly final instructions. +818|Customer#000000818|CvQvKClYoh9lPjMngrjbCoxqqnp2QFiTe8eF|20|30-943-141-5174|-574.39|BUILDING|yly. blithely final platelets haggle regular, regular ideas: furiously r +819|Customer#000000819|cug3zDy qHUaZMQNEtYlWK3R,mGrid4Of|12|22-424-990-1743|2152.05|MACHINERY|y final accounts sleep slyly express ideas. carefully express foxes sleep. carefully stealthy pin +820|Customer#000000820|xsYy3Nu7RhNYyBqL8dD0fONh|4|14-993-368-5047|-614.28|AUTOMOBILE|g, final ideas. slyly ironic packages dazz +821|Customer#000000821|PVdTfF7cfPueJS0MBncE5v4bKfPV64Zg|5|15-901-460-2033|2691.42|FURNITURE|wake carefully. slyly express deposits wake furiously among the fluffily final deposits. pa +822|Customer#000000822|ZoRr18ZiDTtkRduo6PO60gNRg,b46zOe QdS8B|13|23-410-801-1644|736.47|BUILDING|ding dependencies hang alongs +823|Customer#000000823|HuoOuJLxx7S8YDQhexfmIX|0|10-109-430-5638|738.79|AUTOMOBILE|l requests are against the slyly ironic pinto beans. blithely unusual packages wake alongsid +824|Customer#000000824|qHxq5m g6Ug,SDq7R17|18|28-454-124-5859|6840.29|AUTOMOBILE|ffily unusual packages. furiously final ideas +825|Customer#000000825|L8P98o,xq9E78kmuadw,Z7Rwy|10|20-492-863-1129|1809.01|HOUSEHOLD| busy deposits. careful, bold foxes eat furiously according to the final as +826|Customer#000000826|f5Y UZoE nR|13|23-762-328-7631|8938.14|BUILDING|usly final dinos. final depths wake slyly across the final, bold requests. bl +827|Customer#000000827|fmmKD8aBlF9bFndkYf402cHVrUj8FhGZtHeL|14|24-196-343-6537|5411.20|HOUSEHOLD|om the carefully even requests are slowly along the regular +828|Customer#000000828|0PkG ELwBIgU4AsNcjDc5Q,9Gj|23|33-108-680-4317|7059.68|BUILDING|cial instructions. accounts nod special accounts. slowly even deposits belie +829|Customer#000000829|4oht3f64ZWA1,ACbBP9DNxjjG1CbIqOCK|8|18-404-707-6095|4086.56|MACHINERY|deposits cajole slyly ironic, express packages. asymptotes cajole ruthlessly +830|Customer#000000830|4fNmWCmfys1jUI|23|33-408-548-6806|7775.65|AUTOMOBILE|ironic packages integrate alo +831|Customer#000000831|1DyQwHuUncB7BSnQUiW8ksexb|20|30-495-591-5384|3401.49|AUTOMOBILE|c instructions. fluffily bold requests are furiously quickly ironic deposits. carefully +832|Customer#000000832|eNIy9PatAWlh0|19|29-264-864-8387|-201.49|HOUSEHOLD|the special ideas. finally ironic accounts doubt. slyly regular ideas +833|Customer#000000833|t3qDCo,Yh MZcJFV6PibeY,MUunz|6|16-624-307-4875|-526.14|FURNITURE|uickly final orbits across the blithely express accounts integrate furiously among the final sheaves. blithe +834|Customer#000000834|y4mA, TY6DW4gAY|14|24-637-803-7812|-976.25|MACHINERY|regular dolphins. furiously careful ideas eat beyond the bravely regular packages. slyly unusual deposi +835|Customer#000000835|Sjqs42jh111|21|31-700-242-6347|2106.81|BUILDING|gside of the furiously final packages wake quiet, permanent accounts. unusual packages into the unusual, ironic req +836|Customer#000000836|rayz3tXswDbL4hyIr5SMrEIOTqvmok48e|12|22-181-313-6281|9184.72|FURNITURE|press deposits-- fluffily express accounts cajole carefully according to the daringly even deposits-- furi +837|Customer#000000837|mMNC8wjT5aC655e3|9|19-572-730-8324|2701.29|BUILDING|he bold, pending theodolites. special, bold accounts haggle. blithely regular ideas nag fluffily regular packages +838|Customer#000000838|BxDlz44b56kXjsTpl|5|15-919-192-7197|1605.76|AUTOMOBILE|elets. never express accounts haggle slyly. depths along the requests haggle bl +839|Customer#000000839|Ch8 wZk5UKK45BSq1uZLJL0Z A8UUoms|22|32-435-825-7973|2924.78|HOUSEHOLD| close accounts. unusual pinto beans sleep quickly slyly bold instructions. blithely unusu +840|Customer#000000840|9wA4l70okCEW3GnYQvlIAXetDgD50l|22|32-802-156-1748|6799.00|AUTOMOBILE|usly according to the slyly regular pinto beans. blithely regula +841|Customer#000000841|pSISKRxFIgVasW71fLyaEuODHZQLBfd6E c7jo|9|19-556-695-9964|884.20|FURNITURE|ly. slyly special instructions wake. carefully even accounts sleep quickly slyly silent deposits. s +842|Customer#000000842|stRBRwdFCkdN|0|10-272-126-1413|8635.49|FURNITURE| silent pinto beans. bold, pending platelets sleep furiously express theodolites. fluffily express reque +843|Customer#000000843|OEJ7AElvHgEtDpjcrXgLK|14|24-979-584-7928|675.73|HOUSEHOLD|ronic somas. accounts was among the carefully unusual requests. unusual pinto beans are blithely regular depths. s +844|Customer#000000844|1nUzjsH9HS1sPAGLwDIom9IESivLeEh1BvyynjU|11|21-285-410-4046|2954.90|BUILDING|ymptotes. ironic, unusual notornis wake after the ironic, special deposits. blithely fina +845|Customer#000000845|fIq5p0GpDtw6FIsPMdbqNYgfSw3gL9ep|13|23-125-871-9246|6898.89|AUTOMOBILE|deposits above the deposits wake bold instructions. special accounts cajole. ideas along the regu +846|Customer#000000846|EWQcGkx0CU5ZGUNcTV9bBCQ4qnuKsHC|18|28-766-714-9136|7650.73|MACHINERY|s. quickly thin requests against the ironic, bold requests haggle above the final foxe +847|Customer#000000847|oR9VbMI LkR2GUv4MRmylhb|23|33-645-447-3944|4822.08|HOUSEHOLD|haggle carefully. pending, bold foxes play carefully ironic frets: slyly unusual ins +848|Customer#000000848|a nIm5Bk7 RMqMZ6|15|25-655-714-7125|5685.59|BUILDING|st furiously blithely pending packages. deposits across the +849|Customer#000000849|kqRGW2JQtTM,a6 DzJMgcU9U|24|34-718-798-7751|9670.64|MACHINERY|ly silent ideas. fluffily even packages boost carefully fur +850|Customer#000000850|GdhPVh9rkPqSt v17ZuxIlx8c1N8G|22|32-546-203-4000|7576.55|FURNITURE|ly ironic accounts whithout the regular waters are blithely abo +851|Customer#000000851|H9HRTaOz4yI9elrUUiS|9|19-678-843-9850|1144.23|FURNITURE|cross the final packages. blithely ironic excuses serve slyly about the final accounts. fluffily +852|Customer#000000852|fR1Cq8d6m,zJwS3FFrOBV7u|5|15-252-941-6247|1098.98|AUTOMOBILE|unts thrash quickly through the express, regular theodolites. +853|Customer#000000853|U0 9PrwAgWK8AE0GHmnCGtH9BTexWWv87k|2|12-869-161-3468|-444.73|MACHINERY|yly special deposits wake alongside of +854|Customer#000000854|flSR,SlEXwxrDcm3uedfK1Oiq,c9mZI|0|10-544-967-2382|3393.86|AUTOMOBILE|t slyly after the furiously even escapades. carefully regular pa +855|Customer#000000855|i8mS 0Plk2tI8HG1Mnzj8v5RIl5JqmwTSW2Wq|1|11-379-392-2701|3550.49|BUILDING|s. carefully final deposits detect furiously slyly even packages. final, special accounts eat along +856|Customer#000000856|X4U7LH4YtDzephie|15|25-336-316-9641|6988.55|FURNITURE|y bold pinto beans according to the pending foxes +857|Customer#000000857|TFCCMlSEyrItYvEZy068NhrUxJz|5|15-856-649-3113|7537.16|AUTOMOBILE|g to the deposits cajole furiously final deposits. furiously silent dependencies agains +858|Customer#000000858|8qSqHq,Fc378KIPPbTNmaL 0bpAwO|8|18-509-453-8977|-829.37|BUILDING|, special accounts. ironic, pending requests might cajole flu +859|Customer#000000859|yp6dlWnpbzQboP5Xj8W|17|27-379-135-4463|6737.18|BUILDING|uffy foxes boost about the eve +860|Customer#000000860|t0GtEsh39KvInVMH7CDn0xi|12|22-895-319-1388|6836.89|BUILDING| deposits above the blithe requests maintain furiously slyly even packages. slyly regular requests boost. blith +861|Customer#000000861|GvlCZ4fJYbHTOTYczE1iH2k6K9edUyNxWZsl6x|14|24-939-734-5650|-336.80|BUILDING|arefully regular requests unwind slyly +862|Customer#000000862|zkaZ,iOp8t9MBK9T,JIPGL5hmBmK,xjkjHEP|2|12-479-479-6941|2338.92|MACHINERY|yly regular foxes sleep. quickly ironic foxes use furiously express deposits! carefully regular +863|Customer#000000863| oaBBxuQLKPawG1yqOc7cyVhOezCy|3|13-801-392-5922|5274.52|AUTOMOBILE|d accounts detect. bold pinto beans against the slyly ironic +864|Customer#000000864|lKcUKtfu0myNF5msATCFVHHXfMg3,cdb|12|22-897-966-6672|8932.76|AUTOMOBILE| instructions detect slyly. never pending dependencies use slyly enticing accounts. slowl +865|Customer#000000865|UIv4t5cbA7j1ftOSatj2EKah3p|9|19-245-153-1471|3016.38|BUILDING|nic deposits print blithely slyly final accounts. special, express accounts are fluffily a +866|Customer#000000866|u,b0GdP7dZg|20|30-436-285-7224|6265.88|FURNITURE|ts. bravely express pinto beans after the blithely bold requests x-ray busy orbits. furiously pending +867|Customer#000000867|KmET9DxfPVs15pIUUWQ|14|24-522-194-4543|5680.23|FURNITURE|t according to the careful packages. regular +868|Customer#000000868|cFG8Fa5h1e uvHJ9pgZAO|22|32-850-421-3334|7616.48|FURNITURE|the requests. regular dinos at the even requests use furiously around the sheaves. slyly final theodolites bo +869|Customer#000000869|PDGU7BXDNXAo0vmo7QtDm,yCMVcD|2|12-379-344-7132|1228.06|HOUSEHOLD|. final packages wake slyly? blithely even deposits haggle carefully regular packages. unusual requests +870|Customer#000000870|6wGPZX1SbXLGtweqx8jK|2|12-953-532-5903|1970.76|BUILDING|es cajole slyly. furiously even asymptotes are furiously regular packages. special, final ideas s +871|Customer#000000871|KcLmBKitbx7NvU7bpu9clIyccxWG|20|30-933-714-8982|-395.89|HOUSEHOLD|ts. blithely silent courts doze. regular atta +872|Customer#000000872|vLP7iNZBK4B,HANFTKabVI3AO Y9O8H|17|27-357-139-7164|-858.61|BUILDING| detect. packages wake slyly express foxes. even deposits ru +873|Customer#000000873|XFnr9C2bANXL|6|16-375-385-5712|-797.38|AUTOMOBILE|lithely ironic, silent forges. furious +874|Customer#000000874|rdo knkGhtvpH6dbLkQon8QsrK1z4LFUpaVDTOn2|0|10-886-494-4217|5391.74|AUTOMOBILE|st the deposits. furiously even requests cajole slyly. bol +875|Customer#000000875|8pQ4YUYox0d|3|13-146-810-5423|-949.28|FURNITURE|ar theodolites snooze slyly. furiously express packages cajole blithely around the carefully r +876|Customer#000000876|NMzgtdV zCuRIMK0vV,DP9ynDd6Z9X3T|20|30-320-481-3076|4367.63|MACHINERY|ronic requests haggle blithely. slowly ironic ideas against the fluffily +877|Customer#000000877|uYO2BKogrHcOcHEgzjlmZAa1QYyR45i8|16|26-400-912-7812|1755.33|MACHINERY|packages cajole carefully. slyly regular pinto beans bo +878|Customer#000000878|hUCH2juGwk4OtThyY8p35Hi0,IfOGA|15|25-465-180-9022|8781.53|FURNITURE|the quickly pending deposits cajole care +879|Customer#000000879|EJcG18hFrS0SPT0yvl1b|2|12-878-466-6505|2235.20|HOUSEHOLD|ntegrate by the carefully special requests. dolphins sleep e +880|Customer#000000880|ogwHmUUFa1QB69pAoYAAoB0rjbdsVpAQ552e5Q,|8|18-763-990-8618|-77.63|FURNITURE|regular requests. regular deposits ar +881|Customer#000000881|XJ94RTR2oXI omeh|4|14-127-261-7876|2141.71|FURNITURE|pinto beans. asymptotes about the slowly even theodolites are pending requests +882|Customer#000000882|hsKaXwHCLD|2|12-437-842-6799|1650.12|HOUSEHOLD|ts. quickly regular packages alongside of the furiously silent theodolites nag slyly after +883|Customer#000000883|qVQ8rWNU5KZYDcS|3|13-526-239-6950|479.96|FURNITURE|uctions are carefully across the regular, regular asymptote +884|Customer#000000884|5KyisO0Tv9ZtlJhzyI7vAe88|21|31-483-489-6172|1601.60|FURNITURE| among the quickly express theodolites. accounts sleep furiously along the special, pending depende +885|Customer#000000885|nNUbC73nPBCKLg0|5|15-874-471-4903|-959.94|HOUSEHOLD|sits impress regular deposits. slyly silent excuses grow +886|Customer#000000886|QOTGbGPJjNPD7IrfAILA1da|12|22-771-691-7229|1194.33|AUTOMOBILE|slyly even foxes according to the pending, special accounts use carefully against the courts. regular, +887|Customer#000000887|CoInl1fmf5MjYn15AdA|1|11-136-651-8293|7009.42|MACHINERY|ording to the fluffily regular foxes nag fluffily instructions. thinly careful accounts around the furio +888|Customer#000000888|3vlJp0W8cniEXV|12|22-855-455-1154|6358.04|HOUSEHOLD|sleep carefully quick pinto beans. packages hinder beneath the instructions? ironic, unusual theodoli +889|Customer#000000889|pLvfd7drswfAcH8oh2seEct|13|23-625-369-6714|3635.35|FURNITURE|inal ideas. slowly pending frays are. fluff +890|Customer#000000890|rvsLCrRX9z,IPaaF9kqwvLLxueobbPiH4pz|4|14-938-708-4678|3329.21|BUILDING|ironic accounts cajole ruthlessly above the carefully pending accounts. quickly regular theodolites cajole. iro +891|Customer#000000891|AW0m6YSpe,BNPHvBj|11|21-439-958-7518|6032.18|FURNITURE|sits. final foxes run. quickly pendin +892|Customer#000000892|N KwiRAwIk6KL9WJ6vt0G|9|19-589-784-1249|4799.98|FURNITURE|ses are carefully. quickly regular theodolites cajole. carefully express accounts wake sly +893|Customer#000000893|W6m7LofOZoik72ku|13|23-827-724-6816|8250.87|BUILDING|ets. ironic instructions nag even, regular courts. slyly iro +894|Customer#000000894|5y7m8Ts4kDf|16|26-844-679-1540|4483.42|AUTOMOBILE|carefully regular accounts sleep carefully slyly ironic dependencies. blithely ironic accounts wa +895|Customer#000000895|MDaJr8ekGTS79bS7CH8f1WgWPU|0|10-933-819-2037|904.43|AUTOMOBILE|ggle final packages. slyly regular instructions affix fur +896|Customer#000000896|Tu1ZBNgiSEL9Ns|0|10-425-565-3199|7659.72|AUTOMOBILE|affix carefully unusual requests. furiously fin +897|Customer#000000897|nW1X1Hl9uWycuBEu3F3|6|16-988-776-4568|1999.42|MACHINERY|riously regular ideas sleep into the final, unusual +898|Customer#000000898|JrvrIEzAre,VJzJCi3SEmib1T2,YVXVvOGxaVZwR|3|13-265-738-4361|8137.24|AUTOMOBILE|s haggle around the special dependencies. slyly regular requests are according to the idly sly ideas! fluffily final +899|Customer#000000899|Th5XO5ImeCe9nHFQfQMCkNcmf5WHSeYQaR5TJ|2|12-594-534-9654|8605.53|FURNITURE|rding to the furiously unusual accounts. express, express accounts nag furiously. ide +900|Customer#000000900|kEhE1Y,OoZTDv,Auh d5G ALINN0rND|1|11-422-328-1612|3195.39|BUILDING| packages sleep slyly around the quickly special packages. final accounts are furiously. bol +901|Customer#000000901|QUyXt94YM6Ou6rDqK|12|22-202-667-4372|938.35|HOUSEHOLD| foxes maintain. theodolites sleep above the regular deposits. slyly bold excuses boost careful +902|Customer#000000902|A1hnMyYPSkXf7QgOPD2H|4|14-209-883-5797|5858.48|AUTOMOBILE| sometimes regular epitaphs. furiously regular gifts against +903|Customer#000000903|URTiQupkhObWG39,kZ3CfU|7|17-706-779-2078|509.23|FURNITURE|kly doggedly even instructions. regular, regular accounts along the even, bold packa +904|Customer#000000904|YdJEbNygDU6DrgWXQY6orasq|5|15-940-929-4572|9562.82|BUILDING|nic dolphins alongside of the slyly final ideas run +905|Customer#000000905|f iyVEgCU2lZZPCebx5bGp5|3|13-803-156-2231|-600.73|BUILDING|slyly closely ironic dolphins. blithely ironic asymptotes haggle carefully ironic theodolites. furiously +906|Customer#000000906|1Uavkms1A5z|6|16-594-569-6627|-613.45|HOUSEHOLD| accounts. furiously silent ins +907|Customer#000000907|UeVLwnnpccsG1pbQmN7pzD|10|20-501-816-7673|5751.31|HOUSEHOLD|sits haggle quickly above the excuses. slyly ironic packages print furiously. carefully pending reques +908|Customer#000000908|Fa5bchMKUMsaNKOXAiu9pX ME|12|22-814-669-9320|3215.96|AUTOMOBILE|quickly express packages. blithely fina +909|Customer#000000909|b 2X284A5AGpt8skuYwMvTyK68srMKikPst6X|24|34-717-350-9722|5565.58|MACHINERY|se carefully around the special, regular requests. ironic theodolites cajole quickly theodolites. regular, ev +910|Customer#000000910|Qg8TJTCT1mJ9H|9|19-899-463-4292|5794.69|BUILDING|uctions. silent requests after the regular theodolites haggle furiously across the ca +911|Customer#000000911|VS0fia,lJ RvUf68 l4Unv,Vx|13|23-121-746-7339|6364.60|BUILDING|gular foxes! permanently regular packages wake. quickly regular deposits detect blithely. carefully express +912|Customer#000000912|dQA12NEPQK1A5mvD|14|24-348-437-3105|3861.36|FURNITURE|sits use slyly carefully final dependen +913|Customer#000000913|aohNRUjsMbBNE1Ax|14|24-500-946-3315|6935.16|FURNITURE|y blithely final dugouts. accounts wake accounts. asymptotes above the even +914|Customer#000000914| LErnJFeOuDeMgvVzPKHS|5|15-915-758-7313|1230.79|MACHINERY|accounts. slyly final attainments boost slyly express, pen +915|Customer#000000915|mtGezp1BRzcfPVl,1,G8Wl|0|10-452-398-2445|3776.53|AUTOMOBILE|r ideas. final dependencies haggle fluffily. express ideas behin +916|Customer#000000916|9Zo7nkmzJla4Q4PE5mbw|23|33-511-587-8754|130.59|MACHINERY|sual ideas cajole carefully ironic excuses. final platelets use slyly. quickly special instructions nag. bold escapa +917|Customer#000000917|KZ TS0omSFmUQkIOmzlXhwQS,OcF3wzz5|1|11-100-917-5264|3679.65|HOUSEHOLD|arefully fluffy pinto beans. enticingly silent requests affix furiously busily regular ide +918|Customer#000000918|WSptkDdGQQyJ6|19|29-992-318-6425|-155.06|MACHINERY|s boost furiously slyly final dependencies! fluffily regular sheaves nag fluffily. slyly even courts sleep sl +919|Customer#000000919|cHGtsqVvXRiK|9|19-537-180-2200|9774.97|MACHINERY|lar instructions. blithely final deposits haggle furiously bold pinto bean +920|Customer#000000920|oDBFWKIP6M6OlYRPmqCBkVpVSj6uFa|2|12-905-464-3299|990.58|HOUSEHOLD|. ironic, pending frets haggle carefully. ironic, +921|Customer#000000921|XYBVDdDifSYrW gUeDPhITqMjpjtbnc|8|18-765-936-2316|3651.09|HOUSEHOLD|g the furiously unusual theodolites are carefully accounts. slyl +922|Customer#000000922|Az9RFaut7NkPnc5zSD2PwHgVwr4jRzq|7|17-945-916-9648|3869.25|BUILDING|luffily fluffy deposits. packages c +923|Customer#000000923|ckBLWkfYtn2VZXWWqUGbDgbP|11|21-476-142-5086|7462.20|HOUSEHOLD|s. furiously express depths boost. regular requests boost furiously. even, unusual deposits cajole blithely. expre +924|Customer#000000924|yKEtokQYXiuSSh8ZP5|15|25-518-232-9865|4212.53|BUILDING|ake slyly furiously even deposits. express pinto beans are carefully quic +925|Customer#000000925|jn Razhw70hWtHN4iRBWsf1UmrFUPn36Ni562ex|10|20-753-609-6699|1939.39|AUTOMOBILE|ironic accounts cajole carefully. even, expre +926|Customer#000000926| 3b8K2YhfbGDJOpSAUrvq82MnkhHBdwL|16|26-783-803-1329|274.50|AUTOMOBILE|ly quickly unusual foxes. fluffily regular ideas among the regular plat +927|Customer#000000927|Uy7xvOwo4Ndha1tSxDKrQ gXUTdS ,YDqwE2YSO|17|27-332-891-1391|2417.65|MACHINERY|es affix quickly carefully regular platelets. slyly special theodolites would sleep furiously after the special, +928|Customer#000000928|A9 UduEb48ffOe27FxMXF|21|31-508-509-6393|8330.70|HOUSEHOLD| instructions cajole fluffily alongside of the blithely regular re +929|Customer#000000929|c dPfaAmmoLjR3m|23|33-487-459-1026|4079.18|MACHINERY|ously silent foxes cajole slyly pe +930|Customer#000000930|84jHYR8u2XvhyT|19|29-562-904-5451|4787.20|FURNITURE|sual ideas according to the furiously regul +931|Customer#000000931|M,lWVafqdRIO, WnAyLLt|0|10-349-498-1720|2409.69|BUILDING|s the carefully regular packages: pending +932|Customer#000000932|HN9Ap0NsJG7Mb8O|13|23-300-708-7927|6553.37|BUILDING|packages boost slyly along the furiously express foxes. ev +933|Customer#000000933|V0SPv2VbrNo7Pj|14|24-623-803-8018|8541.16|MACHINERY| accounts haggle quickly against the blithely even accounts. deposits sleep blithely quickly p +934|Customer#000000934|UMAFCPYfCxn LhawyoEYoU9GZC7TORCX|12|22-119-576-7222|-592.69|AUTOMOBILE|fluffily requests. carefully even ideas snooze above the accounts. blithely bold platelets cajole +935|Customer#000000935|XkVT4jvetY4JV76IAkd91sSp9CqsICE|0|10-724-445-8323|2531.25|MACHINERY| furiously pending ideas. daringly +936|Customer#000000936|hwJIFpxofea6CLEbWZFsWUxNrGFLANp|11|21-100-538-9635|3650.90|MACHINERY| furiously enticingly final foxes. pending requests wake quickly according to the slyly regu +937|Customer#000000937|usrG6ohdPROyd98c9|23|33-869-990-3946|668.51|AUTOMOBILE|ickly alongside of the express, express ideas. sly +938|Customer#000000938|wrq9S3rEW8zXUVCXpa7uKi|12|22-157-321-7590|2584.52|BUILDING| the quickly special accounts are regular patt +939|Customer#000000939|jYaDdfxAlL1aVKPfN|19|29-627-844-1293|8059.51|FURNITURE|ages integrate carefully. sometimes even sheaves wake sometimes unusual ac +940|Customer#000000940|T7ROXBXdajS,vkwy3VuC8wNvA|19|29-958-573-1004|253.59|AUTOMOBILE|ent accounts. slyly even accounts breach across the dolphins. quickly regular pains dazzle carefully. sl +941|Customer#000000941|297w97UgOfpV3pv2QniJUWBKq0BRpcawOfpj|19|29-745-875-1061|2990.18|FURNITURE|e furiously along the slyly bold pains. ironic, ironic foxes affix quickly even deposits. packages caj +942|Customer#000000942|y0OKxFyfXeYuklJDY9RwujlNIC2ETXo9HxZCVhg1|18|28-560-449-7675|5898.17|HOUSEHOLD|lar depths! carefully regular pinto beans after the deposits wake about the packages. final, final instruc +943|Customer#000000943|74dBRGOKLFEQEqCgH2x8WGL9tubtgJAbHu|5|15-483-251-8603|7541.05|FURNITURE| quickly along the silent, express braids. quickly pending packages boost fluffily furiously regular foxes? a +944|Customer#000000944|8lO9F4WK6PKWXiocyE,ojIfPNfVY8|4|14-485-139-5142|9454.78|BUILDING|ilent pinto beans are according to the regular, final somas. idle, bold foxes was. som +945|Customer#000000945|300zKNJ9lg|15|25-542-662-1673|9615.39|BUILDING|. ironic deposits haggle among the carefully regular excuse +946|Customer#000000946|ufHQOmRhQoLSiyfQ|21|31-152-357-9762|2990.73|FURNITURE|ly after the furiously regular asymptotes. foxes play quickly ironic packages. dinos along the silently expre +947|Customer#000000947|JnzDRxqCwjRPyeq70wrxzKWLXI|22|32-838-393-6825|4092.24|BUILDING| blithely final instructions grow furiously ironic requests. furiously special theodolites sleep after +948|Customer#000000948|yxBr7nLGxxwECEk|17|27-125-968-3750|4346.90|AUTOMOBILE|he final, even deposits. furiously special pl +949|Customer#000000949|tOBbBIfhWM lNI3YxTYH8Or8Ki|2|12-391-316-1861|5340.67|AUTOMOBILE|pecial, pending dolphins. slyly final ideas boost quickly. carefull +950|Customer#000000950|mi3o6cp47mo8Miqh9d R1XWStjxatcQqHQZW|15|25-849-760-2017|9609.77|FURNITURE|s wake quickly after the carefully brave multipliers. regular excuses wake care +951|Customer#000000951|PnC4Xlds,v|0|10-813-916-8297|7499.47|FURNITURE|ts. permanently special accounts mold quickly. requests boost slyly bo +952|Customer#000000952|jg0YsHARdoULvVtP2vGHLVoAfWKFNz6QdTeAi|24|34-527-524-9172|3710.14|AUTOMOBILE|slyly regular ideas. even theodolite +953|Customer#000000953|5HJQ8UzSSl1PJv28MpZqWvNwUm|22|32-829-961-2870|6292.06|BUILDING| according to the carefully bold dependencies use boldly slyly express deposits. car +954|Customer#000000954|rr0Gz2iuYNuLgrIcLCdi5Zr2SnY8,wpzD9A|19|29-639-437-3775|5740.00|FURNITURE| haggle furiously. furiously ironic +955|Customer#000000955|FIis0dJhR5DwVCLy|0|10-918-863-8880|138.31|AUTOMOBILE|ts cajole quickly according to the pending, unusual dolphins. special, ironic c +956|Customer#000000956|aI12bsLSd1Y4dIx2Me5BLbGDCZPn |20|30-627-947-8311|1587.14|HOUSEHOLD|eans. regular, regular foxes wake furiously carefully even pinto beans. furiously r +957|Customer#000000957|9F8p,XsLLxyiZ3b8NN|19|29-941-553-8245|9076.68|FURNITURE|al excuses boost to the ideas. unusual requests are across the slyly +958|Customer#000000958|OrOUBBV7NlzVFXtuSOECmQFOkw8r|5|15-455-954-2914|1791.65|FURNITURE|s deposits. blithely even packages sleep carefully ironic deposits. quickly ironic accou +959|Customer#000000959|O FdrkZxCx PK|4|14-546-329-6898|3266.14|FURNITURE|press accounts wake busily after the furiously final theodolites: fluffily final deposits above the carefully iro +960|Customer#000000960|meekxaMlz5c1uE3wV7a,u h WcU,1OJz|4|14-664-604-8633|1932.59|HOUSEHOLD|s are carefully after the permanent foxes. fluffily +961|Customer#000000961|5,81YDLFuRR47KKzv8GXdmi3zyP37PlPn|12|22-989-463-6089|6963.68|MACHINERY|e final requests: busily final accounts believe a +962|Customer#000000962|lDp572JGdrL34kB YOQuC|4|14-792-232-1645|7557.00|BUILDING|. carefully brave foxes wake furiously final orbits. furiously pending theodolites along the bold the +963|Customer#000000963|40EdWkddaWhQyiQ6FfUo8VOZwgb MetJ2jV,QPL|13|23-921-332-7635|2557.49|HOUSEHOLD|ns snooze slyly daringly pending instructions. regular requests above the regular, even requests sleep blithely fin +964|Customer#000000964|ZnBNwMqvW7y3FSn6025pwkzgTDfsG2A|12|22-974-772-2802|4756.58|FURNITURE|al accounts haggle blithely! regular platelets haggle blit +965|Customer#000000965|UigBc,9d1iLtQAVatnWACSDc9mNx0mYl|2|12-893-735-6415|4768.80|MACHINERY|lly enticing pinto beans haggle requests. evenly express grouch +966|Customer#000000966|V9c8SR8WK7wEd|8|18-539-933-5176|1283.26|MACHINERY|ts. regular accounts cajole about the ideas. slyly unusual idea +967|Customer#000000967|xKdAl6HSWvAmptzHgQHX3cMmxZDhfyrMqx|23|33-687-917-3598|5710.41|BUILDING|iously quickly silent ideas. blithely pending pinto beans except t +968|Customer#000000968|eu 5FA1WHs9jq0pcdlVVA|0|10-470-740-2657|8921.97|BUILDING|ic foxes haggle slyly according to the dependencies. even, regular acc +969|Customer#000000969|N9NSGc0Bj6FlSw3d9k GI7VAd1jW|8|18-148-790-2039|8601.63|BUILDING|lithely according to the fluffily silent patterns. furiously fin +970|Customer#000000970|DXEgz7JHSFW401|14|24-266-486-1615|3623.60|MACHINERY|ronic requests sleep slyly at the slyl +971|Customer#000000971|z29DUY Utsi6mWKI|1|11-256-718-6928|3914.88|AUTOMOBILE|ular theodolites haggle carefully: f +972|Customer#000000972|ImKvHrrNc3rfWejksbCPyIQ|4|14-405-229-6174|4453.46|MACHINERY|deposits: slyly regular deposits among the furiously bold asymptotes are furiously along the slyly even +973|Customer#000000973|FT4jTOdVCpmYW|0|10-749-928-5415|3229.18|FURNITURE|sly special requests integrate carefully along the special foxes. regular, silent +974|Customer#000000974|7RcY6fOjTMbbOnVaFV,,6Dk5FIiHGrCpwXJNI|20|30-473-948-7149|7826.10|HOUSEHOLD|uickly. regular, ironic waters sleep blithely. blithely regular foxes are blithel +975|Customer#000000975|qPFceGMB0xDjY6BhTGdIxe2Z F4MVuKIXHqQ1|16|26-428-220-2070|4364.06|FURNITURE|furiously express packages. even, bold sheaves haggle fluffily. slyly ironic accounts wake slyly across the quickl +976|Customer#000000976|I78UJ2ks3sbcd0c2NQ7aH|19|29-436-660-4732|7772.85|BUILDING|special requests wake carefully regular somas. special theodolites wake regular, unusual pinto beans. furi +977|Customer#000000977|JcKxPwHPM7akg5IiCs,ZVAfO73KE3|2|12-602-807-5055|311.00|FURNITURE|lly against the busily unusual requests! busily even requests haggle blit +978|Customer#000000978|zpvQ6LYE89Inl40Yz,7NJ|24|34-261-243-2624|-50.51|BUILDING|ely unusual packages nag fluffily above the quickly regular requests. regular accounts run. blithely +979|Customer#000000979|DvzUxD35ohKtUnalLGO9kDsCzZxtfcjO|18|28-113-574-4962|7055.13|MACHINERY|. accounts wake carefully special accounts. de +980|Customer#000000980|UsrigSqZBnmbXhXNR6ibloq60qHBUj42kwX|1|11-572-281-8212|4586.33|AUTOMOBILE|st have to integrate above the regularly regular accounts. regular, final waters breach blithely +981|Customer#000000981|pM4DXkl6Y,7S6a6jlJf8dZogp9QOdv|18|28-202-962-8429|3383.26|MACHINERY|ts doze quickly. platelets are quickly agains +982|Customer#000000982|EN9aD5Xgh2q|23|33-460-986-9418|1437.55|FURNITURE|lithely express requests along the carefully pendi +983|Customer#000000983|9jgCxRufEbwbGwW0PmG1RDIOwCUYlHs8z|7|17-283-610-6143|2902.95|BUILDING|mas cajole furiously across the fluffily special deposits. pending foxes sleep regular, silent packages. ironic pla +984|Customer#000000984|fgAELFO9RS 6q9|11|21-247-588-5181|2811.97|AUTOMOBILE|t daringly against the even foxes. furiously silent forges sleep furiously busily ruthless requests. exp +985|Customer#000000985|0uAMe1ICB,wts4STD4eLL|23|33-408-194-5161|2701.21|HOUSEHOLD|gular deposits among the thin instructions haggle since the furiously final packages. ideas use. regular i +986|Customer#000000986|Cei2QidV0GC3OQWfJTNHLYPd|1|11-537-225-3800|178.73|BUILDING|cies impress blithely furiously final package +987|Customer#000000987|SO 0UTuH26eduKI|8|18-887-394-2506|9850.64|AUTOMOBILE|eposits. even packages cajole boldly bold ideas. even, regular accounts haggle. packages among +988|Customer#000000988|3BNYKEUyMbzfb40SEr 8OTb|3|13-862-722-3298|7746.97|FURNITURE|he courts. carefully silent courts impress. carefully close ideas run slyly pinto beans. even, ironic accounts are a +989|Customer#000000989|pKuixWbH6XZFJY0uZjGi0oRaH1Xl|10|20-646-819-6827|5453.74|AUTOMOBILE| accounts. fluffily regular requests use carefully after the furiously special instructions! slyly +990|Customer#000000990|uF idg4bq8Ij7ghxJ5KuTnU8w|0|10-403-137-1064|6988.49|BUILDING|dolites for the fluffily bold +991|Customer#000000991|dK1Gzw1glT|21|31-977-971-6175|6533.53|AUTOMOBILE|n somas. slyly ironic instructions solve quickly at the final dolphins. requests cajole carefully +992|Customer#000000992|Vbi1NGfPeKw,XU|5|15-262-535-3924|5027.75|MACHINERY| across the regular, pending requests. slyly ironic accounts wake furiously about the pending, regular +993|Customer#000000993|56K JjC bMcgbXlJA4KI Icu uggsRoviMQm,F|7|17-494-757-5759|8421.87|FURNITURE| according to the slyly bold accounts. +994|Customer#000000994|sZjdeW4LT9EKopmlv3M Xbnbe3gXQ9JkoxPv |16|26-638-159-5836|7461.27|HOUSEHOLD|ake furiously across the quickly idl +995|Customer#000000995|5tCSAsm4qL5OvHdRZsiwSlVTdqPZws3f|13|23-272-700-1002|-341.79|BUILDING|wake slyly fluffily unusual requests. stealthily regular pinto beans are along the slyly final dugouts. slyly +996|Customer#000000996|yjrSjcG z0Rm5PYrVMFTrU pFRMw|22|32-902-625-1946|6450.78|AUTOMOBILE|hely against the final, brave asymptotes. final ideas haggle slyly bold pinto beans. slyly unusu +997|Customer#000000997|85KMCT2D2RIGayG99ozpk85ppHE6i9gJE|17|27-218-645-5219|367.03|FURNITURE|ven asymptotes. carefully regular packages are blithely. special requests according to the care +998|Customer#000000998|fHRMFCGphazw9KvR1,EmNOUBG|17|27-951-935-6514|6679.20|MACHINERY|ular courts nag quickly unusual, sly pinto beans. special foxes thrash blithely up the foxes. +999|Customer#000000999|r2SFEmfqrRu3M7ouE4zvI2ApOAtD|16|26-876-956-1302|403.89|BUILDING|riously special instructions ac +1000|Customer#000001000|hzM1shTwWlLuk|22|32-730-275-2976|-881.70|BUILDING| closely against the slyly special deposits. regular, ironic p diff --git a/src/test/regress/data/customer.2.data b/src/test/regress/data/customer.2.data new file mode 100644 index 000000000..d23c5e9e3 --- /dev/null +++ b/src/test/regress/data/customer.2.data @@ -0,0 +1,1000 @@ +6001|Customer#000006001|e,jhgkgWnN|3|13-247-356-9056|9139.66|FURNITURE|eans haggle blithely. requests hinder furiously alongside of the slyly final foxes. carefully even instructions wake +6002|Customer#000006002|ZnHuM0Y9nONIKR5TFrHGuJnmxq9GLULVLitL8|20|30-330-985-9161|4400.25|HOUSEHOLD|final instructions. quickly regular epitaphs are according to the sl +6003|Customer#000006003|TD5JS9ULaDBUHIy5J7FfT|16|26-402-596-3552|-30.04|MACHINERY|yly furiously regular instructions. requests sleep about the carefully special accounts. +6004|Customer#000006004|Oo0mrAFH,KrRuF0eCxbklLZC|4|14-523-907-2485|-987.86|FURNITURE|the regular theodolites. carefully silent deposits hagg +6005|Customer#000006005|Qhudh0ioaEafuJ Rfr6DAUqtKkZ33nby|0|10-930-477-2232|4911.63|MACHINERY|p fluffily fluffily pending notornis. requests ser +6006|Customer#000006006|5VfR3EWqbrt0zdkyy8 |8|18-760-236-6029|3751.22|FURNITURE| instructions wake about the slyly ironic deposits! regular excuses wake. furiously pendin +6007|Customer#000006007|eFTUQxFkePYCDkt2YiTlP1oUNww1lUPA|16|26-238-936-7519|3752.79|MACHINERY|quickly special pinto beans serve carefully. blithely ironic requests cajole +6008|Customer#000006008|S1yv Nmjxkhb2yQU7sEX ,poB5f0ijkeRWsY|2|12-448-135-5947|8049.94|FURNITURE|uses boost carefully throughout the blithely express theodolites. furiously i +6009|Customer#000006009|tJ3M102q9VHZ0jX|15|25-821-240-1667|4357.29|AUTOMOBILE|endencies. carefully silent attainments cajole according to the ironic multipliers. final dependencies integr +6010|Customer#000006010|Oyw3CVbhnakZby zVlRd9jZPUygik65nK6UCg|23|33-702-784-8705|3887.84|HOUSEHOLD|uickly final pinto beans kindle instructions. slyly regular instructions sleep carefully. slyly ironic +6011|Customer#000006011|wP2fviXCIC9E6kZ2StshJetAa9x0vNMBZ0I|5|15-600-545-9353|895.26|HOUSEHOLD|en requests wake against the fur +6012|Customer#000006012|mSI9TkywG,fJgIV,mr24o,JupCD36mw0|14|24-197-638-5900|7639.44|FURNITURE|ourts against the slyly final ideas sleep quickly pint +6013|Customer#000006013|NOTH5 kyVefl4bJA|20|30-137-646-6576|2051.61|MACHINERY|nal packages are quickly regular, even instructions. even, ironic deposits sleep; slyly +6014|Customer#000006014|ZB9wS3fmWrQi8cZil6mzcKYo0PQLXrKw2ZM Rv5|24|34-570-696-6422|5302.25|BUILDING|y blithely express accounts. furiousl +6015|Customer#000006015|AAc,PFYt20otDa85nT6wDwOVJ|21|31-376-506-1388|1950.33|FURNITURE|riously theodolites; fluffily enticing +6016|Customer#000006016|Of93IVKgMknchAkEf16|22|32-695-578-4478|8103.98|BUILDING|requests cajole packages: quickly express accoun +6017|Customer#000006017|013MNSbWeJML ohf|23|33-579-732-1955|-402.46|FURNITURE|iously. furiously bold theodolites cajole blithely regular +6018|Customer#000006018|XNLYh8cfpNGERz1O|0|10-261-311-5038|9806.55|AUTOMOBILE|ng the blithely pending platelets detect s +6019|Customer#000006019|5,lbJvlCV l8V|18|28-475-771-1730|3695.26|MACHINERY|carefully. furiously pending p +6020|Customer#000006020|SIdmPkG3HQKTwU4p5hGrJttj,km|16|26-990-181-4165|9256.73|BUILDING|cial deposits x-ray after the blithely regular requests. final requests +6021|Customer#000006021|r5k7syDoG41,Uhtpoii9Hp,oxJKKME9|21|31-358-419-1438|3002.73|AUTOMOBILE|ly pending accounts about the blithely ironic package +6022|Customer#000006022|z9Gbi2AkLS0s6HNIDyerHNGE7V98G|10|20-331-281-6929|7892.25|BUILDING|tructions detect among the bold, regular accounts. ironic ideas inte +6023|Customer#000006023|uz9mw3nZBoJ0j2zkMueLynANFVN|21|31-825-465-7964|5150.58|AUTOMOBILE| must have to sleep furiously at the pending, regular accounts. fluffily unusual deposits nag along the carefull +6024|Customer#000006024|LZ80EMXjRz7JULb75V5n3qg|3|13-664-584-4042|4732.68|AUTOMOBILE|cajole blithely about the furiously pending theodolit +6025|Customer#000006025|cawvuhdgRy KaqlhXcWab y31A37F8IPT|14|24-233-488-3262|-815.07|BUILDING| final packages boost slyly above the blithely regular requests. slyly ir +6026|Customer#000006026|ius6eByivZ4BVYaESvB9p0bWsZ|12|22-822-409-2653|4993.97|AUTOMOBILE|xpress requests. carefully unusual accounts cajole blithely even ideas. carefully regular deposits are quickly iro +6027|Customer#000006027|hST46enQLI8TzdOmvA8J|7|17-178-716-9690|1657.83|HOUSEHOLD|deposits sleep slyly regular deposits. furiously ironic accounts boost carefully according to the carefully regular +6028|Customer#000006028|mL,IJFVI1MA9|0|10-424-273-2141|9173.51|MACHINERY|ckly ironic theodolites cajole after the quickly regular ide +6029|Customer#000006029|Bhz6SV,wpp|2|12-230-673-1285|1247.91|FURNITURE|ites wake blithely final, unusual accounts? quietly final foxes hinder. furiously express theodoli +6030|Customer#000006030|thigRH2AJJ5ay1akT2MoIWgGS3iH|0|10-385-880-2306|5585.25|BUILDING|uickly final deposits: even packages after the deposits wake regularly under the blithely ironic theodolites. furio +6031|Customer#000006031|ovto GrnDjTqwxdA0L|24|34-257-441-6562|6268.52|BUILDING|oss the carefully even deposits. furiously ironic deposits haggle furiously furio +6032|Customer#000006032|U9Y1LGOIyhU1r|24|34-124-269-1297|6098.48|AUTOMOBILE|its. pending excuses detect among the carefully ironic packages. carefully final gifts are. ironic in +6033|Customer#000006033|CY9eVCYfqrI1WlamyV,2h2fAuwRof4Vi|20|30-194-447-2847|8203.11|HOUSEHOLD| regular deposits wake carefully final accounts. regular, thin +6034|Customer#000006034|9C1trxxcizUyNm,rADOUt5UB|15|25-369-506-8757|4765.57|HOUSEHOLD|ding, even gifts about the regular, final requests sleep fluffily by the carefully silent dolphins. even, s +6035|Customer#000006035|pzz5CQ3wWzqmawu811Zfm|2|12-929-596-2859|1907.14|FURNITURE|es sleep fluffily besides the furiously qui +6036|Customer#000006036|oArQJruOuhJxRvLWjeDX3 h6CspeJwV7U6by|0|10-960-488-8572|8282.11|HOUSEHOLD| after the carefully even theodolites. furiously unusual pinto beans among the ironic theodolites k +6037|Customer#000006037|SnqQMacIw1UlhWOZib7iEU|6|16-600-315-6012|1463.98|AUTOMOBILE|encies cajole carefully according to the final, pending packages. regular, ironic packages b +6038|Customer#000006038| bIKiOVO1JVZiEtTF4T7HxjimXgL5|9|19-485-680-7672|7087.20|AUTOMOBILE|quests are furiously besides the blithely ironic requests. slow asymptotes cajole about the furiously +6039|Customer#000006039|a5rSHRtBDeEFAd8f,suDA8ve|5|15-453-414-1942|4616.61|HOUSEHOLD| pending instructions must have to sleep carefully +6040|Customer#000006040|al9P9X5hZsq4GVzXaf45nmYGre S|18|28-602-749-7354|6309.48|BUILDING|nstructions along the blithely final foxes solve according to t +6041|Customer#000006041|BFIr9VI8QcoMd4mjXtXH|22|32-422-646-4800|1445.52|BUILDING|ests boost furiously blithely ironic pinto beans. daringly ironic pac +6042|Customer#000006042|5HJbh0QShvTfZretlUSjRk|0|10-526-919-1776|4839.54|FURNITURE| express requests boost carefully. deposits boost blithely quickly ironic deposits. ironic accounts x +6043|Customer#000006043|04Ln0amBet|9|19-335-750-5425|2143.97|AUTOMOBILE| asymptotes haggle above the final gifts. ironic accounts sleep. pending, regu +6044|Customer#000006044|DOpmBtl1j5gVB36A57vtsI6Z|10|20-311-967-3855|6649.41|HOUSEHOLD|thely special packages. express pinto beans sleep about the final, unu +6045|Customer#000006045|FH8AwQ54fTohmWWZEFluKjNP|0|10-579-571-4767|5587.35|HOUSEHOLD| instructions. special accounts hinder quickly unusual depend +6046|Customer#000006046|3pqu0wwA NYnUQAx|1|11-901-156-9794|8566.39|FURNITURE|telets sleep around the accounts. busily special theodolites along the fluffily silent deposits use fu +6047|Customer#000006047|WJIOtP1XJSsFYl7yCfPo2|4|14-601-562-8081|5439.08|FURNITURE|y express, ironic deposits. final deposits nag slyly slyly bold excuses; blithely regular accounts affix slyly. ir +6048|Customer#000006048|DNtLkGdov3MnFfAGa40Pi6c6Y1r5j NF|24|34-996-904-3634|2634.46|AUTOMOBILE| sleep blithely across the regular deposits. accounts wake. slyly ironic gifts above th +6049|Customer#000006049|b1Wlcr2IYgYvlZWW3V,JNkpDg,Msiwmm9|23|33-822-276-9791|357.21|AUTOMOBILE| instructions. instructions boost fu +6050|Customer#000006050|orhXeGjD4RRH5QU|0|10-472-892-7595|6612.70|AUTOMOBILE|ts cajole quickly furiously express packages. evenly final theodolites use quickly +6051|Customer#000006051|k7txuddD z|4|14-674-349-1580|4706.51|MACHINERY|platelets. slyly bold packages sleep permanently along the c +6052|Customer#000006052|5R8 L5TJey,G7Ta7YGFnezUXaI4eIZu|21|31-792-184-4320|-624.49|FURNITURE|gular, final dolphins. sauternes against the slyly final dependencies cajol +6053|Customer#000006053|Yzq6dtXjEfbY PEVyUkJ|15|25-363-543-1931|7102.91|MACHINERY|r, ironic foxes. packages wake +6054|Customer#000006054|bXUQWTwB29ox1ganSx,QcxemZ|6|16-472-362-3917|4601.79|HOUSEHOLD|uriously after the silent deposits. blithely express instructions integrate carefully alongsi +6055|Customer#000006055|FnwMVA8yGuU SgVGARNz22st,8|9|19-663-939-5531|-631.98|FURNITURE|g to the final, regular requests haggle furiously quick foxes. regular requests p +6056|Customer#000006056|nyg076hIRk|2|12-687-122-1788|2218.75|AUTOMOBILE|se accounts. ironic pearls are +6057|Customer#000006057|R4Bt0gWYUrIshQjPi7UaKDrFs|20|30-448-516-3117|9526.94|FURNITURE|ly regular ideas haggle furiously enticingly final packages. regular, bold dolphins cajole slyly +6058|Customer#000006058|noUsJ1sGwBlm9KfvZ|21|31-818-798-9205|1401.74|MACHINERY|y ironic requests. silent deposits grow fluffily. regular, ironic pearls among the dolphins integrate even senti +6059|Customer#000006059|hbYI6RCnsefLu,WWFcArgxqy5xQdygs8tv9|15|25-133-925-3453|6051.11|BUILDING|s detect slyly. even pinto beans across the quickly ironic forges use furiously slyly regular courts. furiou +6060|Customer#000006060|G ziIQMNWzroTjGIHiWM 0pG|15|25-174-729-5653|4030.26|BUILDING|express, regular multipliers haggle after the fluffily final requests. regular excuses ar +6061|Customer#000006061|FRN1 emJhjvn9yjnKN9HjoNG,X aW3kdDmBA|15|25-551-122-4107|7532.06|MACHINERY|during the blithely express requests. quickly ironic frays across the blithe +6062|Customer#000006062|UtdDwozzDvfMtgj3W|3|13-756-700-4918|1370.35|FURNITURE|ourts-- regular packages hang furious +6063|Customer#000006063|P8McFZy0XZk2tO0fd6e|13|23-185-189-2252|6385.75|BUILDING|, special foxes. regular asymptotes sleep slyly +6064|Customer#000006064|,izgs4ldAZyamftqvB|20|30-205-718-3890|7335.40|AUTOMOBILE|theodolites. carefully pending packages sleep fluffily blithe +6065|Customer#000006065|Gb72LtD9HVv9slwDCWiufPxBYW6qVgnfe|16|26-150-752-2624|7191.82|HOUSEHOLD| alongside of the furiously unusual instr +6066|Customer#000006066|s,Txrg7qYwMSykuMvxhA26sOs1KNm8t|6|16-166-390-9922|2967.12|BUILDING|arefully blithely regular courts. furiously express request +6067|Customer#000006067|wktXPx5LSL5ZSP0shdmYDauSiNMRiAHaaKVJ|4|14-386-119-4898|3407.75|AUTOMOBILE|inal dependencies nag blithely car +6068|Customer#000006068|RCTOrn8 qmIVd6qGMMLmjWCvz7|4|14-138-821-9164|6028.37|FURNITURE|arefully even instructions sleep slyly regular, silent pinto b +6069|Customer#000006069|lP56RbvJxUsPWR7AJ3nGdcXjPYhDzw|8|18-520-115-6373|6775.83|FURNITURE|le furiously carefully brave ideas. f +6070|Customer#000006070|0Pycomq4a6KgwcZYyaH5g6t5hdLgsKF|14|24-195-934-6766|7430.40|AUTOMOBILE|even asymptotes wake about the furiously express accounts. special platelets between +6071|Customer#000006071|bSImC9SNAZBpJfS|3|13-976-555-2947|8764.04|AUTOMOBILE|after the dependencies eat carefully against the blithely regular pinto beans. +6072|Customer#000006072|dJTs qvHOtIuFDNIsyGkzkuz|16|26-754-599-4979|5312.01|MACHINERY|theodolites nag evenly among the bold excuses. ironic accounts sleep along +6073|Customer#000006073|pfb,24MPwsE8,0LUyO|9|19-689-677-5011|1045.91|HOUSEHOLD|. furiously regular ideas are regularly ironic theodolites. slyly even packages sleep slyly fluffily express p +6074|Customer#000006074|nrcHwNPzOQ x|8|18-837-412-1792|9486.43|AUTOMOBILE|olve furiously about the furiously bold deposits. slyl +6075|Customer#000006075|DOsAAUjRKdmOtvgEMibSALCKR M5Nj|1|11-593-566-6284|2455.27|FURNITURE|s the furiously ironic requests a +6076|Customer#000006076|At1D9HHVnICLHSzLkebTdUFubbpiizOsfsnT1|7|17-850-828-6128|2626.39|FURNITURE| pending deposits solve. slowly bold ideas haggle fluffily packages. blithely +6077|Customer#000006077|uhQEW4hX BiYzeK vM4p5nmxPwa|9|19-473-215-4783|7755.29|MACHINERY|e the pinto beans. final somas affix slyly: fluffily special instructions are careful +6078|Customer#000006078|SBe5gejYZc lZ|9|19-127-604-4037|2143.99|MACHINERY|o beans. quickly ironic accounts +6079|Customer#000006079|JrsyZ3aOo7pyfy1Nfcu7wv2y9MssX9Fl2j|24|34-956-792-4754|7035.43|AUTOMOBILE|pinto beans cajole carefully special pinto beans. bold packages was across the carefully ironic ideas. even, regular +6080|Customer#000006080|TO8wL2kHE7DAZOlyh7U4aW|2|12-853-465-2990|3557.21|FURNITURE|as sleep carefully along the ironic deposits. furiously dogged deposits among the fluffily regular frets sleep blit +6081|Customer#000006081|g9sWPKJZrAa2yRmoTwz|14|24-898-630-6492|-956.69|MACHINERY| courts affix around the furiously stealthy deposits. packages wake evenly +6082|Customer#000006082|A VQviGoD71daDZOZv|11|21-155-663-3196|898.19|BUILDING|usual pinto beans after the carefully pending fox +6083|Customer#000006083|Zk4jDSMrlCCH,MIpgre hsHn8XZJn62|11|21-852-430-5106|1845.68|AUTOMOBILE|ial accounts wake slyly. furiously unusual depths cajole blithely furiously +6084|Customer#000006084|E0NXucb5MGwfV5BnCW1qPSpeMoqf|15|25-403-768-3899|9300.11|AUTOMOBILE|s are carefully. doggedly pending foxes boost carefully pending, ironic accounts. closely bold +6085|Customer#000006085|N280OwVf0BbPajbB89YmFrHEihif|12|22-247-826-9697|6041.35|MACHINERY|slyly permanent courts was blithely packages. furiously b +6086|Customer#000006086|kBBqMZHke10dGuoDBvzv|20|30-613-894-3303|5029.81|MACHINERY|ays? dugouts sleep carefully around the slyly regular attainments. iron +6087|Customer#000006087|HZvlNvQ41HBORsewqAXWc1i5z,V|17|27-176-985-1293|9991.42|FURNITURE|fluffily. furiously final deposits believe about the furiously final excuses. slyly ironic accoun +6088|Customer#000006088|yxbYU1ogtMNgiSUAFNsA5 aYG|24|34-944-696-5888|8895.30|MACHINERY|thely. packages at the final packages use carefully around the regular, even deposits. +6089|Customer#000006089|1xUlqn0cOHlIKlRHeBz8Mfn|18|28-312-896-5088|458.27|HOUSEHOLD|es. accounts cajole slyly ironic c +6090|Customer#000006090|NqM,WhTKaDb4uzuNsmHPiSvWFsEGHJA|8|18-417-809-3338|61.15|HOUSEHOLD| special sheaves. quickly final requests are. quickly fina +6091|Customer#000006091|xqRatn5FncOIxHo9oZ9lBbPrJQ0e aoISrI|1|11-922-360-2419|2753.48|MACHINERY|quests. furiously ironic requests are above the carefully special packages. +6092|Customer#000006092|Z,XTnww1rI6aWDjmfk7w0p8kxLcqCIfD7h8|5|15-941-440-2662|9761.72|FURNITURE| foxes are above the ironic excuses. special instructions dazzle blithely about the regular asymptotes. fur +6093|Customer#000006093|BOuFVeQZ,E|8|18-806-815-4057|9343.42|AUTOMOBILE|gedly regular pinto beans. express pinto beans nag slyly. regular ideas wake thi +6094|Customer#000006094|X7kFGROKaQpglhpv20A|12|22-421-694-6690|7983.44|FURNITURE|to beans boost. carefully special pinto beans wake alongside of the slyly regular accounts. furiously regular pinto +6095|Customer#000006095|qP9OXihxntW60ybk|17|27-151-511-8515|8802.47|BUILDING|thely. furiously ironic request +6096|Customer#000006096|wy UjJzsFOKGCMfqtaHK5NI|1|11-517-930-3964|2237.40|HOUSEHOLD|silent excuses detect slyly silent accounts. slyly final instructions nag furiously. fur +6097|Customer#000006097|KCW2zgHZRm36j90QVmQ9b5Ml|2|12-742-944-8759|3963.90|MACHINERY|ding to the carefully silent accounts. special excuses wake. furiously final foxes about t +6098|Customer#000006098|c Bp7dnCuklVVNOM7Gc11k2gCRv|3|13-223-820-6932|3312.28|HOUSEHOLD|ts! carefully final foxes haggle slyly: slyly express tithes wake furiously about the final, final deposits. +6099|Customer#000006099|Zw,1lluCeZSlbwLKZo2i37|23|33-797-420-9100|7413.61|HOUSEHOLD| deposits are slyly pinto beans. carefully express packages wake furiously. even deposits +6100|Customer#000006100|BFnRAdDK0EMZAr2zS3js6,Jsh|14|24-425-432-3048|1569.09|AUTOMOBILE|olphins after the requests wake furiously silent requests. quickly ironic dependencies are furiously around the reg +6101|Customer#000006101|KI6M7iuiqLHAb|1|11-152-108-8875|2651.06|AUTOMOBILE|efully even requests. ironic, unusual deposits wake furiously. blithely pending req +6102|Customer#000006102|s5ViRaDEjv2nKox7c6Y|3|13-533-564-6439|4257.41|HOUSEHOLD|cial asymptotes are slyly regular sauternes-- slyly ironic deposits integrate regular, final theodolites-- furi +6103|Customer#000006103|YYS9 3AI8tkKqUqMtWssXA44M|4|14-405-808-5807|8364.07|HOUSEHOLD| pinto beans sleep. carefully regular sentiments sleep blithely. final packages cajole +6104|Customer#000006104|jcKuAbr5WFuVxd2xt,4KqyvQ7kz|15|25-250-924-1873|4010.86|MACHINERY| final packages sleep above the slyly bold +6105|Customer#000006105|EfQPHmIraBqSvNY15deoIPsc|4|14-506-543-9059|506.68|BUILDING|he unusual deposits. furiously even a +6106|Customer#000006106|nfroWgkspby66r6BkrvQCMX,f,i4Myrykv3k pa|7|17-151-647-7940|-337.05|FURNITURE| special excuses cajole. carefully bold req +6107|Customer#000006107|,4I3WYJQN9ZAWX5I5J54dJna|19|29-717-849-8757|9064.29|FURNITURE|long the excuses. slyly special instructions unwind slyly beyond the regular, final pinto beans. requests use blit +6108|Customer#000006108|0SPg7CHlEjunN0dHuKF932w|10|20-564-384-5926|2570.78|BUILDING|asymptotes sleep carefully. fluffily regular pinto +6109|Customer#000006109|gpgBDs5krmN|7|17-896-737-8894|8151.07|HOUSEHOLD|uriously pending asymptotes. fluffily bold pinto beans are above the +6110|Customer#000006110|FAxMqfHBG36oB|8|18-793-720-8574|-888.62|BUILDING|iously final ideas. furiously regular packages nag. quickly regular pinto beans above the regular theo +6111|Customer#000006111|CLSQ2jkX5hmEPyKFJkKxemAH|18|28-252-831-5956|857.85|HOUSEHOLD|ly final deposits. slyly special accounts against the furious +6112|Customer#000006112|wPzFnLHJ Eg3EzH |24|34-654-913-4569|5894.96|HOUSEHOLD| final, dogged packages wake furiously slyly regular platelets. fluffily silent pinto bea +6113|Customer#000006113|YV9LsSwnYEjuQENdPBp8Sfl|18|28-599-409-3070|8646.86|MACHINERY| blithely at the blithely ironic deposits. carefully final ideas cajole fluffily. unusual pa +6114|Customer#000006114|87W0S9L9zjjL,lPnNxpXEJKSjaOY|12|22-957-665-4649|4860.40|HOUSEHOLD|haggle slyly above the slyly express deposits. slyly even ideas sleep fluffily above the slyly ironic accoun +6115|Customer#000006115|r3MSiTaTNNKpIXe1x,RDRqPx1s|21|31-465-527-1774|821.94|MACHINERY|er the slyly express platelets affix carefully above the careful requests. pending +6116|Customer#000006116|Q1HHnkKguo6sSYNWgNEk2tTeEe6db3s6osO|4|14-743-932-4071|7234.12|BUILDING|he blithely express requests haggle furiously regular, final excuses; carefully regular pinto beans unwind ca +6117|Customer#000006117|4CHkWzZ3fT|24|34-380-887-8865|9826.19|FURNITURE|ly final packages. fluffily bold escapades sleep fluffily after the carefully express +6118|Customer#000006118|GZJ6Dctbr0USrtx|11|21-581-376-6339|3810.27|HOUSEHOLD|e fluffily special packages integrate quickly final dependencies. regular +6119|Customer#000006119|p8I8iRWN3HIQZPoMD5y1qogRuycR7VnAiEyOZff9|1|11-137-505-5251|6246.11|FURNITURE|wake blithely fluffily ironic theodolites. bold deposits cajole about the blithely fin +6120|Customer#000006120|ZTjNH4Si5g9pTrul2fRGaHEB|6|16-141-186-1813|3351.67|HOUSEHOLD| excuses nag fluffily ironic requests. slyly +6121|Customer#000006121|uAXqrguis17T1SGF9Od0sJ|13|23-689-704-1607|9531.41|FURNITURE|ss packages are furiously final depths-- final, ev +6122|Customer#000006122|48JzmrY5BZiS2C5Ts,wgJkRR7z5SOkJhg7|18|28-417-497-5317|-485.36|BUILDING|yly express accounts. slyly regular f +6123|Customer#000006123|rriyD1ssl4dg,ur1WRPBG|19|29-912-115-6013|2397.49|BUILDING|ogged deposits breach blithely. blithely express theodolites use. packages about the fina +6124|Customer#000006124|1FAv28GTpQRD2Nw ULiQG3qCi6PTGFXC|7|17-962-756-6916|-383.24|MACHINERY|final courts. furiously ironic deposits run blithely furiously express instructions. slyly special deposits slee +6125|Customer#000006125|q4dT2taZKQmIDI8,V|11|21-143-295-8049|2811.99|MACHINERY| ideas. slyly even packages are fluffily instead of t +6126|Customer#000006126|7NRolRPvqN3QIrcKU|23|33-988-127-6540|3047.89|BUILDING|hely. quickly even braids haggle slyly. quickly even theodolites +6127|Customer#000006127|4xg9rQlpgsZ7NJl4k9IL47ODv3E26jIRCvnlgd|23|33-236-693-8622|7908.12|BUILDING|le carefully. even requests grow carefully carefully bold theodolites. furiously regul +6128|Customer#000006128|c88JZp1so3TfKB6o5|16|26-586-949-7031|7899.60|FURNITURE|efully enticing braids according to the furiously ironic accounts detect furiously around the fluffi +6129|Customer#000006129|MVydnT2OcBdbSLF|22|32-368-121-9588|7571.87|HOUSEHOLD|ously after the regularly pending excuses. accounts boost slyly final ideas. special account +6130|Customer#000006130|uzgA6cyeuysYLVKMv|6|16-405-646-2657|-555.94|BUILDING|efully regular deposits about the regular packages believe blithely alongside of the ideas. bl +6131|Customer#000006131|EwoT1zKxHYj8|13|23-237-602-7871|4223.57|BUILDING|e doggedly permanent platelets slee +6132|Customer#000006132|LMFK0bKFaBIX8tW74Yoxb8,bw9XS|1|11-890-884-8734|468.90|HOUSEHOLD|ly close courts among the express, even packages believe doggedly among the fluffily regular ins +6133|Customer#000006133|FwwrG68tR4k|13|23-849-670-9143|2698.12|HOUSEHOLD|final ideas detect furiously permanent accounts. slyly regular courts boost final instructions. theodolite +6134|Customer#000006134| DMIOsEg5VDDKmWzjjShHILJhBrFVea|8|18-349-804-2162|3214.77|FURNITURE|kages sleep. furiously thin requests affix ac +6135|Customer#000006135|IED4rGsufuEnT4NrO7KvhQfFfcwGzvMHgQiUnoP|1|11-117-608-4110|7552.48|MACHINERY| deposits. deposits along the final packages haggle furiously ironi +6136|Customer#000006136|pDoECZ7k3AwOSp9wDO|19|29-974-254-4381|3649.73|BUILDING|ely ironic tithes sleep finally after the +6137|Customer#000006137|Uv1p49Ppo7lO9zpW05z|5|15-958-508-2113|3037.82|BUILDING|riously express, regular hockey players. quickly final pinto beans use packages. carefully e +6138|Customer#000006138|Dm6,p6hst9ub9FiYivgUm3FapKRiEYPG|15|25-872-607-4602|3638.97|FURNITURE|snooze slyly quickly ironic packages. furiously final deposits sleep quickly specia +6139|Customer#000006139|3r3Uc,7NMqKxby7w641xEV3su|17|27-704-480-4139|9119.98|AUTOMOBILE|s cajole blithely regular packages. furiously ironic deposits are final, regular fo +6140|Customer#000006140|QPlaw,8zEWbcabsVf,wRBMC1hvedP0|11|21-263-388-7344|3593.93|AUTOMOBILE|ke furiously slyly bold warhors +6141|Customer#000006141|4QBCP6mT5dep|10|20-961-227-7319|247.76|BUILDING| alongside of the patterns. pending ideas doze +6142|Customer#000006142|6rJlz 6aiuufZqN8Ldf9|7|17-856-660-5846|4045.08|BUILDING|the carefully bold deposits-- requests haggle slyly +6143|Customer#000006143|zuh77l1EZ6xUn6H,sZIYq|1|11-253-915-7383|3706.32|FURNITURE| nag slyly. final, pending dependencies haggle slyly about the furiously ironic o +6144|Customer#000006144|zPKzjSPczgTN9Yb3ybnDmhplv6ymvG|1|11-306-913-9602|8057.08|FURNITURE|equests cajole carefully pending, even packages. regular platelets +6145|Customer#000006145|CybtvIEF1DXOFCddFGr|21|31-879-282-9414|3423.05|HOUSEHOLD|sits are slyly even requests. regular packages across t +6146|Customer#000006146|RNKo8PgfKqgW6hGWTJMp|19|29-723-257-4271|-832.84|FURNITURE|ld requests alongside of the regular packages wake fluff +6147|Customer#000006147|fr6iYAVpls5Zy8UF1qn|21|31-729-268-4470|3418.83|FURNITURE|accounts. silent, ironic orbits believe furiously escapades. slyly regular packag +6148|Customer#000006148|OiRtO4N,szTYNMjqyl,|14|24-345-723-7631|5246.25|AUTOMOBILE|s poach carefully after the furiously ironic packages. even pinto beans are fluffily. blithely unusual pinto beans +6149|Customer#000006149|Dv0FCsfLC8tg I,NGqcnL3uO|9|19-981-118-5032|6737.15|BUILDING|mong the blithely final requests sleep according to the b +6150|Customer#000006150|aX47rrqgyvzy74tFd0o Wn1wr5XK|2|12-895-769-4268|6249.24|BUILDING|o beans cajole doggedly above the slyly unusual deposits. enticingly regular theodolites snooze c +6151|Customer#000006151|ojCmk5FfGZm4Oset4R|1|11-178-162-9290|1016.84|BUILDING|inos should have to use furiously among the quickly express somas. ironic requests cajole furiously after the slyly +6152|Customer#000006152|Bqxwa70bCy,M8Vs6cWn|19|29-492-966-5351|4957.70|MACHINERY|y final foxes. express packages wake across the ruthlessly regular instructions. express +6153|Customer#000006153|,oEYlRJs0L76hU5MtnT17H5qULk|6|16-303-738-6232|8070.72|MACHINERY|ctions use slyly above the blithely express deposits. +6154|Customer#000006154|FI1U42PTLrAG n3a5JxzHabcH|10|20-372-167-3439|1571.98|AUTOMOBILE|tithes nag regular, final theodolites. deposits sleep along the ironic theodolites. carefully +6155|Customer#000006155|03gJRZx3TGwScCd8d1 MhitTEHY i|20|30-511-190-6866|7246.91|HOUSEHOLD|ess accounts. carefully even theodolites are silent requests. slyly unusual packages +6156|Customer#000006156|cVhwUHk5,b74V|12|22-119-245-3413|4873.83|HOUSEHOLD|ly daring, express deposits. special, regular packages haggle furiously ironic package +6157|Customer#000006157|3hTpojm17PUW3OvoLxeqQtz2|11|21-578-529-7649|6444.10|HOUSEHOLD|are slyly sometimes final deposits. special, final dependencies cajole quickly. slyly e +6158|Customer#000006158|GmqBG39QiPPqq1YA|10|20-393-733-8825|8966.55|FURNITURE| even asymptotes. fluffily pending requests against the quickly silent platelets cajo +6159|Customer#000006159|naaCoV9ztjZ2YVP4hmQAtTnFsb,DAWFoAJp5|6|16-192-111-5212|9877.27|FURNITURE|g the silent, ironic theodolite +6160|Customer#000006160|NrxXWav6LihuuSlWGszrc|13|23-830-408-5650|4333.77|FURNITURE|pending orbits sleep quickly. slyly unusual requests cajole. furiously regular requests +6161|Customer#000006161|pbRxOFTDqY0lPBucGOSzCy|18|28-703-556-9515|4706.39|FURNITURE|ing deposits? furiously regular accounts alongside of the fluffily even requests are blithely above the +6162|Customer#000006162|wFK59S80D3m iXYc96LznPltGTpDcB|3|13-525-195-7035|8277.40|HOUSEHOLD|ackages. requests use blithely according to the final, regular requests. even, special accounts +6163|Customer#000006163|tmxBpVae0jKAe9vXikmLaCRGPAoyiDVGz|21|31-674-263-4416|-678.87|AUTOMOBILE|requests sleep. quickly final depths affix quickly unusual excuses-- final packages af +6164|Customer#000006164|PSgfAO1LnbP8 5aNt2lWBD|14|24-782-729-4216|6171.41|FURNITURE| ironic courts solve closely according to the carefully ironic requests; special, +6165|Customer#000006165|31aZoMFnTFf|12|22-414-194-1058|1982.00|AUTOMOBILE| the even, unusual excuses. slyly special foxes nag quickly special, expres +6166|Customer#000006166|df2AQz9BJgmAj XoIOiyoUd|14|24-891-533-8945|1444.98|HOUSEHOLD|ng packages affix even, final pi +6167|Customer#000006167|oPGRaBt5IuSxtQhwgztJyv1miL|7|17-798-361-3738|6729.32|FURNITURE|ly final requests grow alongside of t +6168|Customer#000006168|TfeEEZ9Ds8x3eQljQUYaNzpu6tE1ap,JGRn2gZm|24|34-877-467-2443|6633.98|MACHINERY|ily. special platelets about the slyly +6169|Customer#000006169|UDeLABnhksFK7tfInLsDPRtynoWxesfiJ|7|17-656-209-2093|-681.05|HOUSEHOLD|y final pinto beans. slyly even dependencies boost +6170|Customer#000006170|PLJi9aPgRlkkIUsc8LGRVLOGrz1IBd|19|29-558-582-4733|2570.49|BUILDING|t requests cajole slyly. slyly ironic courts ca +6171|Customer#000006171|SNyHcZsmA5EydGjLu0MT7Y|19|29-222-112-6966|3125.83|MACHINERY|ts nag fluffily even instructions. furiously even pint +6172|Customer#000006172|uafeB6k3L MWgR6k8Wokrv0gtSwTLmWRW8,UVhv|5|15-750-174-4232|8749.91|BUILDING|ound the slyly regular theodolites wake slyly across the platelets. carefu +6173|Customer#000006173|jd3so7 leJO5Y0SF1YFrMJ|20|30-743-439-3998|9725.31|MACHINERY|es boost above the carefully regular +6174|Customer#000006174|UOkeiQv5WK1OBw5CjtHQDh84JAV|11|21-570-543-7869|2314.46|FURNITURE|ly bold foxes-- final ideas x-ray among the regular theodo +6175|Customer#000006175|4fRoxmxFa4n|23|33-387-822-4617|1065.86|MACHINERY|ress pinto beans. fluffily final ideas dazzle closely slyly ironic packages. furiousl +6176|Customer#000006176|kXM67uOjA5sj|24|34-919-259-2224|3918.54|FURNITURE|nts wake after the even packages. ironic requests alongside of the slyly regular excuses boost slyly regular reque +6177|Customer#000006177|pZZ8D,yKhfsFatXwk|24|34-161-190-1931|-149.78|MACHINERY|are across the slyly ironic requests; carefully dogged accounts run blithely bli +6178|Customer#000006178|ejgXNsz sI0Dl3F,FVziTAF4mPWXczkmXlu|9|19-567-173-3123|-369.66|FURNITURE| furiously alongside of the pending, ironic theodolites. ideas among the silent pinto beans dazzle silently alongsi +6179|Customer#000006179|0MU9 AVKw SeY6kbL5VJm|6|16-699-827-5744|38.38|AUTOMOBILE|l accounts lose furiously slyly final tithes. quickly stealthy attainm +6180|Customer#000006180|4csqeJ8yw1y r 6Bzi49uv|11|21-527-929-7958|4979.33|AUTOMOBILE|ymptotes solve beside the ironic packages. carefully special deposits ar +6181|Customer#000006181|cZ9B3p5D4poouVdTvh0Sol7ODKuWa|2|12-716-858-1804|8630.17|MACHINERY|es. unusual instructions among the slyly regular deposits affix carefully after the furiously ironic platelets. +6182|Customer#000006182|8U367QGaD8IUUdHyHtwSj3pmJoeLcVrMccGMZ5J|6|16-291-418-8009|-745.50|AUTOMOBILE|es serve blithely alongside of the regular instructions: unusual deposits cajole ruthlessly alo +6183|Customer#000006183|iDx,aeynoLw|20|30-808-423-5478|8330.40|MACHINERY|gular, express accounts. requests use. furiously pending instructions detect within the quickly +6184|Customer#000006184|dkynJLYBPBCkx 1paCFtwxmixcoPoqaFVyGQ|19|29-373-987-6278|-960.96|MACHINERY|hely blithely special deposits. furiously pending requests boost carefully instructions. excuses nag +6185|Customer#000006185|4qtODzt Kxhkagjgtc5U 6l|24|34-493-651-6114|6109.32|HOUSEHOLD|ests are final ideas-- ironic, pe +6186|Customer#000006186|0dwkPKvOkPIniv3,Fahd1rq9nwc|16|26-982-329-6333|3360.22|AUTOMOBILE|sly bold grouches. ironic pinto beans sleep furiously furiously regular depths. platelets breach t +6187|Customer#000006187|LJJpyf,OZivsv6IQBJG3gEisgc7d QC7oKRuXOBj|15|25-545-311-4634|-838.33|AUTOMOBILE| requests. slyly regular requests after the accounts hagg +6188|Customer#000006188|Z85HZ6fRUEl3|15|25-648-100-5980|-895.88|AUTOMOBILE|gle carefully. bold theodolites x-ray fluffily. bold gifts alongside of the sent +6189|Customer#000006189|X6edGVb,Osa emoLHSaQKn|14|24-556-862-5258|-213.89|AUTOMOBILE|ly regular deposits across the regular theodolites serve blithely express +6190|Customer#000006190|mV9CzSEQr,nE3CC, xJ1EsQOw|2|12-212-128-8305|33.63|MACHINERY| finally regular theodolites wa +6191|Customer#000006191|7XGJ0ugPk dVdCm1nJQ|22|32-229-609-5050|2167.56|BUILDING|s dugouts. carefully bold pinto beans +6192|Customer#000006192|oI8CXoK1w9PnZDUEbvj|0|10-276-595-2077|7179.63|BUILDING|ly bold decoys are slyly. slyly even epitaphs around the regular requests cajole at the blit +6193|Customer#000006193|RnHj1jACEqFgLpCQfzgsZtgoZu1Jck|16|26-200-646-6714|7033.00|MACHINERY|dependencies. furiously special foxes cajole +6194|Customer#000006194|9GsTKrC4NgB2bqd4ui9kuijhjxDlw IU1|9|19-886-790-6122|6639.12|AUTOMOBILE|ts boost after the carefully ex +6195|Customer#000006195|eVLaPYm6NRhqQzuMx3vk|0|10-891-840-4980|8707.05|FURNITURE|y. quickly pending accounts against the blithely thin ins +6196|Customer#000006196|KNWdwsj7hGyO0lrvqr6G1o|15|25-200-325-2383|4462.11|BUILDING|c courts. final instructions a +6197|Customer#000006197|Ce9LTBhp7GkCqZy|11|21-395-292-5975|5631.85|FURNITURE| unusual instructions wake always above the regular excuses +6198|Customer#000006198|OglD6pbHC9ovv2mfZ rDO iay cVjX5SRng2|23|33-381-544-1422|8515.39|FURNITURE|y unusual platelets are slyly across the carefully final pack +6199|Customer#000006199|3LH72AxUTOqvuazpB6dk5i80YVo3,H2YZiyir|22|32-514-462-3884|6178.78|MACHINERY|ideas wake fluffily. pending, pending p +6200|Customer#000006200|oGCR8cSGI,rHCpRMi2|3|13-609-502-2266|4767.80|FURNITURE|l dolphins. sometimes unusual instructi +6201|Customer#000006201|oK3Q7pkcEZaGXxOeNB4okAaAxNDbZB8K1y|0|10-385-198-4441|6397.29|HOUSEHOLD|ly. regular, slow packages along the carefully express foxes doze to the blithely even foxes-- furiou +6202|Customer#000006202|E73qW mbEQINh gPymXB,ed4O nKl|15|25-477-944-7482|3330.24|FURNITURE|l excuses. fluffily ironic packages use. quickly final Tiresias a +6203|Customer#000006203|xVMuglbV53zSLL4wb7Mxb,pkD8MrP6 R,CO ehMc|19|29-735-432-9939|1280.15|BUILDING| ideas atop the even, unusual excuses sleep against the furiously careful pearls. closely express +6204|Customer#000006204|6MBV7BG qK9BOmGQny|16|26-983-171-4809|8460.54|FURNITURE|eful requests. quickly ironic instructions use b +6205|Customer#000006205|Bd2A0KLWCYN1WZ1XJc,N |18|28-920-423-1966|8416.88|FURNITURE|osits over the pending instructions wa +6206|Customer#000006206|EZ6yws0GmtHJXSHiV|4|14-448-256-3507|486.36|HOUSEHOLD|nding platelets are after the pending foxes. unusual, regula +6207|Customer#000006207|Ba2gZAYGD 74QLT8T7,uRQwIi0rqbJ9|7|17-896-188-3890|-740.28|FURNITURE|foxes. blithely pending platelets haggle quickly bold, silent asymptotes +6208|Customer#000006208|m,PxS2pByk43RfabxsV6in7n|18|28-322-291-1770|8045.41|FURNITURE|deposits wake slyly. slyly even ideas use blithely. furiously iro +6209|Customer#000006209|C1Ls6INP7D9jHTugpjUUWD9kS9cpKclB|2|12-685-144-7597|5241.88|BUILDING|ges. final accounts breach slyly. furiously regular deposits according to the express instructions wake after +6210|Customer#000006210|d5fRx4ruNET9kj6LqGhVxCYwT|17|27-245-729-5781|-791.51|AUTOMOBILE|special pinto beans poach quickly careful theodolites. fluffily pending instructions cajo +6211|Customer#000006211|,bXG5MlIamKtG8mMbce|2|12-200-723-4029|5045.01|BUILDING| furiously special requests. carefully final deposits wake even requests. carefully final accounts are alongside o +6212|Customer#000006212|ArifsT45MN,N2HR,CoiDLwG0|5|15-251-873-7969|1570.87|AUTOMOBILE|n foxes. ironic, final foxes boost blithely bold instructions. furiously dogged deposi +6213|Customer#000006213|jpXKO9LktOMMIPpfE xyGA7uurVPqSzOn|5|15-600-409-7048|-445.21|AUTOMOBILE|nts use carefully above the b +6214|Customer#000006214| ,MAKZxDGF3QKwDERiLKFCaCOcIOlN|22|32-811-917-7230|6202.90|HOUSEHOLD|. carefully express theodolites sleep furiously even requests. quickly express instructions lose slyly silent idea +6215|Customer#000006215|fAfdqCTURbOu,|5|15-792-734-1509|3206.02|BUILDING|deposits. furiously even hockey players sleep carefully. quickly bold requests across the slyly spe +6216|Customer#000006216|bGTXGAHg72BEDM09QZEFI|0|10-585-359-5566|3548.03|MACHINERY|ickly. slyly final theodolites integrate fluffily quickly ironic asymptotes. +6217|Customer#000006217|k9NiqQlFJVv6|9|19-612-407-3150|9647.49|MACHINERY|tions wake quickly slyly regular pinto beans. ironic, final asymptotes affix blithely around the hockey players. +6218|Customer#000006218|4,z5xJL2IWWO5LMrF36cZISGaq77Q6 7DvAh5|16|26-501-652-8685|3504.23|HOUSEHOLD|slyly final instructions. final e +6219|Customer#000006219|lM 6tdVkyERY,wQ6n7ZHD11,G|8|18-384-857-8254|-443.88|FURNITURE|lyly regular theodolites doze furiously bold ac +6220|Customer#000006220|je,Ssek0XNsaWRGsiKF 0,hDjGVOaSNsN7TkZz|7|17-755-898-9664|6694.27|BUILDING|ffily express deposits. carefully ironic packages haggle furiously final excuses. pending dolphins af +6221|Customer#000006221|J2Zx,5YWGMpbyd9yupa1PMuDhhHCFtDqmtzx0CE|6|16-641-636-3853|712.36|HOUSEHOLD| the furiously even braids. instructions use blithely +6222|Customer#000006222|8p2FbclgqcvoFR29P,OwwCkWR|8|18-981-975-1436|2589.32|FURNITURE|usual pinto beans. slyly special deposits breach about the slyly i +6223|Customer#000006223|kOimz7buzOsZP8DPRQfB pa8a7bWyA0Axx|7|17-805-445-2530|644.72|BUILDING|each slyly quickly even requests. quickly regular instructions cajole blithely. deposits wake along +6224|Customer#000006224|LFoSAlF,JOEn4gVU0qGhIpu|5|15-952-723-9945|9794.49|FURNITURE|ly blithe dependencies use across the slow requests. +6225|Customer#000006225|cqOhtNVujJSTrsZlLLvt1k|21|31-221-435-4954|-847.96|BUILDING|; slyly unusual deposits cajole pinto beans. fluffily regular accounts above the accounts lose slyly +6226|Customer#000006226|8gPu8,NPGkfyQQ0hcIYUGPIBWc,ybP5g,|23|33-657-701-3391|2230.09|BUILDING|ending platelets along the express deposits cajole carefully final +6227|Customer#000006227|hQpDSUJLnjcvDZ4WbiVrWDSYBjCou1kJ|11|21-159-594-1232|2062.51|FURNITURE|uffily stealthy deposits haggle quickly carefully final request +6228|Customer#000006228|Zb2Vj1EhkIivE CSYkb936,JYTQaWYT0a|5|15-417-317-1397|1524.63|FURNITURE|ts. furiously regular requests wake carefully regular packages. furiously regular packages about +6229|Customer#000006229|6jBRlUNs3Q,XQZsgUuaWybaSY|17|27-996-380-7890|3480.92|HOUSEHOLD| packages. even asymptotes nag ironic excuses. slyly ironic deposits cajole. express requests +6230|Customer#000006230|MGXvPZQ6UMzc4PbZcSUl8kGfew|18|28-226-342-3356|3763.78|MACHINERY|ously pending platelets; busily special theodolites sleep carefully! express platelets sleep slyly acros +6231|Customer#000006231|DssbpsUtrcZVi81wG|11|21-183-229-4023|5805.58|HOUSEHOLD|ding accounts thrash carefully alongside of the even, regular ex +6232|Customer#000006232|T0JFOylApn8YQr,|18|28-847-729-1271|2455.95|HOUSEHOLD|ly pending packages are. regularly express accounts past the fluffily regular p +6233|Customer#000006233|4ZbcmGRlrqQ5|22|32-482-650-3134|3186.31|FURNITURE| instructions along the regular packages maintain above th +6234|Customer#000006234|lQaP7fCR8lVTQY7pkMi1BLv|23|33-658-619-9537|2250.65|BUILDING|dle packages boost slyly. quickly special theodolites wake furiou +6235|Customer#000006235|YpIuvasSAUFQ027rL|11|21-845-791-5239|6718.32|AUTOMOBILE|e the ironic, final instructions. carefully unusual somas haggle quickly quickly ironic requests. quickly eve +6236|Customer#000006236|zQjCvBPfacwUT0nrJ2uF,4FtSAC0ldB|17|27-557-761-6785|8836.84|MACHINERY|uriously bold accounts boost blithely ironic theodolites. quickly even packages mold along the +6237|Customer#000006237|jgXVEi0rAQCxBmRGM1vE1|0|10-312-679-5009|7806.93|AUTOMOBILE|oze slyly. thin, unusual depths integrate quickly alo +6238|Customer#000006238|AckKNmINwCbVw kC5bZ0u3Hh7C3,7Rdva0|15|25-749-568-5891|1052.60|HOUSEHOLD|hely special deposits. regular requests solve un +6239|Customer#000006239|PklZCqNbiyA9|22|32-305-456-4164|1007.44|AUTOMOBILE|ular packages. final, even ideas print slowly along the pending acco +6240|Customer#000006240|kxWW41iCbmQJFT3GxGtmHakhcHZ07nW0diOTG|8|18-432-692-3478|939.14|BUILDING| even dependencies. pending, regular packages wake carefully above the deposits. +6241|Customer#000006241|ucocla,JAAW amojIyO Ow |7|17-623-128-3126|8018.46|FURNITURE|tructions wake fluffily. enticingly regular requests sleep furiously silent packages. slyly special +6242|Customer#000006242|1J2Yz5f1lOLcsSkMTme|14|24-293-990-7292|3379.23|FURNITURE|uickly ironic packages sleep. fluffily regular accounts wake qui +6243|Customer#000006243|JotibBD2zs87K8|19|29-356-403-8790|-377.14|AUTOMOBILE|ly even accounts. final instructions haggle. silent, silent platelets are around the carefully even accounts. caref +6244|Customer#000006244|5XQ1QzJOWRsj2dkV0WnG2lFantHSML9hToTT2tw|21|31-123-516-6719|6385.54|FURNITURE| furiously even requests sleep quickly under the pinto beans. ironic warthogs thrash sp +6245|Customer#000006245|okJFjGfCET8m41TwZdswM4nqi2,wx8qP6tpM8GE|19|29-589-374-8352|3766.89|BUILDING|ounts cajole. deposits are. quickly final ideas across the carefully ironic notor +6246|Customer#000006246|5l,sIIFQVnUUtzs1|10|20-124-894-8392|3090.40|FURNITURE|ckly regular theodolites use. furiously regular instructions against the regular dolphins are sl +6247|Customer#000006247|22fOQj6uLxyE6L,ev4yMzPv8FuBvstp9JJAmez|3|13-961-966-3385|7408.81|HOUSEHOLD|s should have to haggle furiously even requests. furiously bold d +6248|Customer#000006248|F3NgALjt9qjhFKEDz|10|20-237-638-2221|8834.94|AUTOMOBILE|ckly according to the theodolites. foxes along the ironic, bold accou +6249|Customer#000006249|I3e rogGC4PkngfpXmtiw|15|25-311-257-8481|8946.03|MACHINERY|efully across the fluffily bold tithes. fluffily regular frays nag blithely along the sometimes eve +6250|Customer#000006250|swZXFAFQ2O|17|27-861-967-3557|5926.27|FURNITURE|after the furiously ironic asymptotes. pinto beans nag. fluffily regular ideas pro +6251|Customer#000006251|GWig6svLrx4Lcr0I tMBGMgd7HuyLGjbDJnFkGTl|8|18-245-505-4627|6920.15|AUTOMOBILE| unusual dependencies wake furiously even foxes. regular pinto beans mold furiously spe +6252|Customer#000006252|iGu23V6R50fBd4,WCMeGmcF9QaffCWOZiiY|22|32-311-215-9551|1928.88|AUTOMOBILE|packages cajole. carefully ironic packages nod along the even excuses. foxes wake against the packages. +6253|Customer#000006253|dHtDAyg0dAsmNZUJ6yonI6|9|19-583-938-5958|-356.48|BUILDING|ffix blithely. special, special packages believe. slyly regular platel +6254|Customer#000006254|XpXxuBjXYzFBXCvTp8sO4 0zwCiWD9ggiF|12|22-251-775-8243|1538.38|FURNITURE|. blithely final courts are quickly across the ironic deposit +6255|Customer#000006255|l6XtT3yvhZ,VzKzrXl2vQiIgwcrFB3qL7fuARSYk|5|15-472-424-3063|3495.68|BUILDING|even excuses. fluffily regular pa +6256|Customer#000006256|,fpJxiGODuy,EqJmiD9qM1DN|23|33-628-309-9349|9846.83|FURNITURE|lithely ironic, bold deposits. blithely bold +6257|Customer#000006257|etreRcLjc7uC|17|27-604-361-9761|9836.21|AUTOMOBILE| asymptotes wake slyly. bold excuses are furiously carefully furious accounts. slyly even packa +6258|Customer#000006258|CzJGapE7fxQx3x9eN A7O|18|28-429-156-3365|7221.20|FURNITURE| foxes haggle slyly slyly final asymptotes. slyly even packages wake furiously along the +6259|Customer#000006259|fpEAMihvplhOKyor ZRcf2bEUOwQgGz6SkilLk|16|26-449-972-6429|1723.42|AUTOMOBILE|instructions are evenly unusual ideas. furiously regular pinto beans among the furiously bold deposits wake +6260|Customer#000006260|oJLJxevvYZqj,n6Dq,L5V6C|4|14-214-869-6336|405.59|FURNITURE| haggle above the slyly regular platelets. pending theodolites wake carefully even +6261|Customer#000006261|rbTkXWn,HeQxxR8SLRuBS3m,LK|12|22-636-489-9192|5612.90|AUTOMOBILE|ructions. final, unusual pinto beans are furiously specia +6262|Customer#000006262|HlUg CpG1hqLgHf|14|24-761-458-3272|8970.62|FURNITURE| ironic requests believe quickly after the furious dependencies. express, fin +6263|Customer#000006263|nTwk5ECJ6elmDX8zLW7Fta9u9PlmTaqqRNja7|14|24-936-988-1040|1314.66|FURNITURE|ckages use furiously slyly final accounts. bravely bold dependencies about the carefully ironic asymptotes are +6264|Customer#000006264|pV82CJ4rNyOcMzCXNmdy|17|27-583-887-6592|5392.22|AUTOMOBILE|al, careful instructions affix blithely. ironic +6265|Customer#000006265|,8NdehNjF5ojMMEKikadmc2ng|23|33-192-952-7496|6977.71|BUILDING|y after the quickly pending requests. unusual +6266|Customer#000006266|9OKHx1,rXIAV0pq6Vj,uERU44LaT|22|32-443-596-1740|1468.66|BUILDING|g blithely. ironic foxes cajole blithely around the packages. +6267|Customer#000006267|Hxi,BwRbqRQUkum7Ts3R ugk4w58Ozmpp|20|30-657-865-4960|8650.75|HOUSEHOLD|l platelets sleep blithely. quickly pe +6268|Customer#000006268|cG,c4luyALcY|5|15-764-581-5523|4236.85|BUILDING|special hockey players wake fluffily express, bold pinto bean +6269|Customer#000006269|t3tcDR3QxuXh1Q5eHbzBls8jxxc4eCZSKKu Rh|16|26-790-547-6046|3793.75|FURNITURE|ccording to the furiously ironic deposits. final decoys wake along the patterns. blithely even +6270|Customer#000006270|PGn,pJmM gsA1tDtDbbuiiGra57c4FL|18|28-717-120-2144|3485.91|AUTOMOBILE|deposits. pending braids cajole fluffily pinto beans. carefully ir +6271|Customer#000006271|C61IFNXGXjOgzUAf8drHHKFksk,dASWbIXele|15|25-214-187-2123|-342.40|AUTOMOBILE|ptotes haggle slyly regular accounts-- regular pinto beans use carefully against the blithely reg +6272|Customer#000006272|HnzXtYtwH8Jco2wa,L|2|12-494-911-3342|7209.51|FURNITURE|ajole slyly. furiously final packages affix silent, final theodolites. even asymptotes x-ray bravely. reg +6273|Customer#000006273|ZD7bJedn3FdCd3p1SLGq4rZGqBCMlic|0|10-717-770-2411|3278.98|AUTOMOBILE|uffily among the fluffily regular accounts. even asymptotes haggle finally +6274|Customer#000006274|SgRPgKV3mB1oPuGe1ccFvjhDBRYiopGwIsWTNuOL|24|34-845-579-7944|8778.79|AUTOMOBILE|uriously regular requests. slyly regular instructions haggle. in +6275|Customer#000006275|vFGTLUjxiQu4HEiY16P1jSBrn380WinK,|0|10-194-385-3660|187.26|AUTOMOBILE| poach above the furiously unusual sauternes. accounts poach slyly. blithe +6276|Customer#000006276|qrFgLgA0RCdrQioauSbVb8g|11|21-790-836-6047|-777.89|AUTOMOBILE|uriously regular deposits. even deposits alongside of the slyly +6277|Customer#000006277|0EKQ4D5RMYQ6,NHCtnq14Es7OIWwNDPRtBEswyFP|0|10-237-523-6848|2907.96|BUILDING|s boost furiously final, special r +6278|Customer#000006278|F kMurdAhFU0C2KEiojmsS5gWlgxPZ5Q49iZl|5|15-299-327-8860|9996.76|AUTOMOBILE|detect slyly unusual hockey players. regular requests after the final +6279|Customer#000006279|Ft4nZfY7lsZ ws|5|15-206-922-2248|-319.90|FURNITURE|ial, unusual accounts. final asymptot +6280|Customer#000006280|eA0MCPdIfSK06GY JDS,GKrDGrr3e7ZqkB|19|29-971-689-4133|407.63|AUTOMOBILE|cuses. ironic deposits wake above the permanently ironic deposits. final ideas are slyly ca +6281|Customer#000006281|yORAuTtjrCJF9lOKTJtS9|4|14-318-809-5732|7055.03|BUILDING|refully even frays cajole during the carefully even acc +6282|Customer#000006282|fCqZiNSOZ46KUCaRvVFPG60DMq|16|26-750-142-4294|2969.47|AUTOMOBILE| furiously regular deposits. slyly ironic packages +6283|Customer#000006283|tmVqD0BrhOBHlA|14|24-539-196-5846|9860.06|HOUSEHOLD|regular, silent requests. blithely ironic theodolites sleep. blithely even deposits nag r +6284|Customer#000006284|zEh7eHXMGoSNP9h7Bk7G8axMfEkBVkj,NADgz9|13|23-583-198-6369|1178.44|BUILDING|fily alongside of the fluffily speci +6285|Customer#000006285|nf 4a5KU8QuLSMPZWmEkyVq6UAD065pgsgI|3|13-353-741-3596|3913.54|MACHINERY|rmanent deposits print furiously among the slyly e +6286|Customer#000006286|WbndcI8V39JL1oxVYtRHMvESj1|16|26-227-468-4312|3895.62|AUTOMOBILE|le blithely ironic packages. furiously bold instructions wake blithely ruthless, ironic pinto beans. even +6287|Customer#000006287|b1WalykIgCZUEIk,KPnxg7ytSfEtEHsVRCX98H5|20|30-755-248-6558|-296.05|BUILDING| beans wake slowly according to the regular, ironic deposits. furiously regular requests cajole. express +6288|Customer#000006288|iN4rgnOJ5RH8M5r6fvF75YNLBiT4loi|11|21-622-156-3974|5184.42|HOUSEHOLD|unts sleep carefully quickly even foxes. fluffily bold requests about the silent theodolites breach quickly above +6289|Customer#000006289|MuOF83xgQwBnj42OUkVScHj7RKGR3U7NkdzVdLc|17|27-437-457-4918|1509.92|MACHINERY|efully furiously pending pinto beans. pinto beans after the blithely express pinto beans haggle carefully packa +6290|Customer#000006290|Vi6,QwAcedleabbr0SEv6LeHEU9SluHi57,|3|13-927-921-7780|9223.20|HOUSEHOLD|ual, express deposits wake carefully final instructions. slow, ironic requests across the furiously regular package +6291|Customer#000006291|JwSPtW9LtBALXgfhtQ3H|15|25-657-320-9686|313.68|HOUSEHOLD|ess instructions wake slyly by the +6292|Customer#000006292|xR0ShtQF06IrULp,|20|30-313-386-9424|910.80|FURNITURE|ely regular requests cajole blithely regular, unusual accounts. ironic, ironic packages about the slyl +6293|Customer#000006293|40Q UY9xqRxuXTIF3Kh58iCsPTn6g6FXAU|3|13-828-651-7919|4785.81|BUILDING|uickly final excuses was slyly silent, express requests. carefully regular requests g +6294|Customer#000006294|TEYcUTvYiWvxYjLqLx1a7dI7nqlcLDSG6S732 |10|20-377-548-8347|1065.94|AUTOMOBILE|uriously. furiously bold platelets detect theodolites. quickly final accounts can cajole according to the bli +6295|Customer#000006295|YEDvY2dxIZA5AFzrYqM2R,Qu0BWeRzqZ|11|21-326-272-7171|5134.99|BUILDING|sts boost final, final packages. unusual pinto beans against the carefully final re +6296|Customer#000006296|igCv4BEwY9,779Tix1Jw|21|31-763-742-7377|6768.63|BUILDING|could sleep blithely inside the regular accounts. furiously ironic accounts slee +6297|Customer#000006297|DX,A9MX7Xpum|22|32-968-252-6956|7365.56|BUILDING|ctions haggle furiously carefully final pinto beans. pending deposits dazzle regular, regul +6298|Customer#000006298|v5JDDFsvutMitkNO|10|20-805-968-6774|8028.38|FURNITURE| furiously fluffily pending packages. silent pinto beans across the final foxes nag perm +6299|Customer#000006299|,4uQAq3HIX7qNb2tA yA|4|14-120-953-8397|4991.04|HOUSEHOLD|refully regular ideas wake carefully dependencies. slyly regular excuses serve. fur +6300|Customer#000006300|iFuTBsELWUD|14|24-935-162-6227|7456.50|AUTOMOBILE|bold ideas. depths hang ideas. slyly final requests boost fluffily above the quickly bold escapades +6301|Customer#000006301|JdPIarVVF5vd0laNpjFh|18|28-940-337-3490|7399.19|AUTOMOBILE|nal instructions eat slyly. pendin +6302|Customer#000006302|Pmy5pzuh1YeOHkpciY0bCwMtDvMEPy2816MEBz|11|21-127-281-7462|1273.35|AUTOMOBILE|o beans. bold requests promise carefully slyly regular pains-- boldly ironic accounts are blithely pending +6303|Customer#000006303|YlPFtsXInnJ9pylCP3WVnzHDGX,RbchWeoZ|21|31-241-146-4709|4079.40|HOUSEHOLD|ans run quickly slyly special deposits. carefully +6304|Customer#000006304|Zg6sBmlhMs9XVZeDS3D|13|23-243-641-3155|8426.13|FURNITURE|ccording to the furiously express instructions. asymptotes affix slyly carefully even do +6305|Customer#000006305|26EjrYGIc38wIM,rkf nwGVNIaWPfmsEpjmyyfP|0|10-141-833-6715|2088.12|FURNITURE|dencies. blithely final packages integrate furiously. pending platelets use across the quickly bold de +6306|Customer#000006306|Bp0L3gbYTOCVi9N3Tq6CtAMW6jFuqWTmOEB|7|17-595-455-5504|3048.38|BUILDING|luffily across the special requests. quickly special packages among +6307|Customer#000006307|FJlRZXhd4LA,uWwwa78AoylhQkOOJrNZ|19|29-453-201-8768|5047.86|AUTOMOBILE|eat. quickly pending courts lose furiously against the slyly special platelets. carefully special +6308|Customer#000006308|FmSPcC6tPeT6M6|10|20-499-286-6565|5329.24|BUILDING|s. stealthy, silent packages print. deposits are slyly even, pending accounts. blithely even +6309|Customer#000006309|pHdznY21xwitGpZp|7|17-525-121-8608|4575.56|AUTOMOBILE|deas. quickly quiet instructions can are. express accounts use after the +6310|Customer#000006310|n2yStHsmbyEE6P|6|16-432-150-5510|9468.61|AUTOMOBILE|e final packages haggle blithely above the qui +6311|Customer#000006311|wSwN,5PelFjtbAIv,SzZXy05,GTmiXBsXSTfI|17|27-553-115-9891|-71.60|HOUSEHOLD|inal, ironic accounts above the excuses use evenly among the bold pinto beans. carefully silent foxes above the r +6312|Customer#000006312|QMhVQC0PiraO8oEHoMJ14b8Gxf9gK4h5ATkCn|4|14-870-343-5163|4562.08|AUTOMOBILE|ily silent foxes above the ironically unusual packages cajole quickl +6313|Customer#000006313|g66sNXSi5LC9tvZ|6|16-911-713-4691|2933.72|FURNITURE|beans. boldly final deposits wake blithely. slyly ironic packag +6314|Customer#000006314|lqbO7daGUg0T0QppRJTLXXan2PJ4YiZUtA|24|34-155-178-2373|2996.03|HOUSEHOLD|uickly regular packages alongside of the slow, special requests wake slyly against the furiously regular accounts. +6315|Customer#000006315|H3lTGfGTxl|6|16-965-207-3063|5307.12|BUILDING|packages. packages cajole notornis. closely express accounts according to the id +6316|Customer#000006316|jbMHTjobBPcepRl|14|24-427-805-3364|6714.53|HOUSEHOLD|l, bold requests. fluffily unusual accounts s +6317|Customer#000006317|1i8b72gMGW4MBizzmt2G2j9FiUhxKUV2xcJ|20|30-302-599-4639|154.99|MACHINERY| with the silent accounts? theodolites affix. ironic asymptotes across the idle, express requests h +6318|Customer#000006318|iYPP2u47,ZVs pK,|21|31-463-681-6877|6923.15|BUILDING|quick packages wake slyly unusual +6319|Customer#000006319|j1p9Rogz9sN1u9g0cyHBNsV5Uj0sT,mYh2Z5|14|24-464-821-9726|8487.59|BUILDING|ic deposits integrate slyly across the quickly ironic pinto beans. furiously re +6320|Customer#000006320|utTqGM30xwZPpmVURyoh7jWE4emjju6JHYuUAWFs|3|13-381-184-9600|937.20|MACHINERY|ly ironic requests detect blithely inside the sentiments +6321|Customer#000006321|QQ3MOdoHCo9I6SvghQ10xY|19|29-754-952-3500|8433.20|AUTOMOBILE|odolites. even, final requests through +6322|Customer#000006322|NK2pKqhhwp LJnExfiTmLeCZm6bhLkXWRIfxBPQj|9|19-998-647-9970|-95.54|FURNITURE|counts wake quickly pending packages. silent instructions above the even, r +6323|Customer#000006323|CSFI2KxIkCJ7O,KVsI9rtPZZi1cYypJbtN|23|33-716-180-9533|9240.58|MACHINERY|to cajole about the slyly ironic foxes. i +6324|Customer#000006324|o7FUm0oOy,5Cz|24|34-225-267-1395|6470.97|HOUSEHOLD|furiously idle accounts wake among the closely bold foxes. requests grow fluffily abo +6325|Customer#000006325|eI IZBMs2Neixixf|14|24-113-347-2651|9653.04|MACHINERY|he quickly regular sentiments. ironic, ironic theodolites doze. final deposits run blithely ironi +6326|Customer#000006326|Vvne n,VXT ykC6eBZ202wy4ev360a7jWQugfmC|9|19-653-669-5014|8701.02|MACHINERY|yly. furiously express foxes sublate slyly. pinto beans grow. slyly final deposits cajole quickly f +6327|Customer#000006327|zfiwjLhIm3ykcc0PExS1enEBsWkf|16|26-366-282-8221|2114.22|BUILDING|gle. accounts might nag silent deposits. pending packages use fl +6328|Customer#000006328|wibapP1Bq,wY|23|33-499-740-7766|1651.24|FURNITURE|eposits wake carefully regular, final accounts. pending pinto beans after the unusu +6329|Customer#000006329|GgzjDBrJgBnzfhNzdcbe7XSOs5a9CVHoO|22|32-532-430-2910|8415.80|AUTOMOBILE|ully regular accounts. carefully unusual grouches are. slyly even requests boost b +6330|Customer#000006330|6c1MemjbKFOa41b5CGI4rox|16|26-223-365-1109|4490.78|HOUSEHOLD|counts haggle alongside of the careful requests. fluffily regular deposits are. ideas grow: slow braids sleep +6331|Customer#000006331|7,qAyD7LhheRuOcwIJEzmPI|9|19-824-332-5078|3583.47|MACHINERY| between the pinto beans cajole quickly among the slyly special foxes. furio +6332|Customer#000006332|s7FTXH37X2fnlxS|6|16-913-396-4738|436.62|MACHINERY|yly ironic theodolites cajole fu +6333|Customer#000006333|IExKkHfdJck,eoVnei8NhqREtBsDfpFKG6otE|4|14-571-939-5220|-856.26|HOUSEHOLD|hinder carefully. deposits cajole +6334|Customer#000006334|RwSGFTlf,AMKTl2|24|34-336-748-8274|5795.61|HOUSEHOLD|to haggle. furiously final packages haggle. fluffily final pinto beans a +6335|Customer#000006335|4V2jDP,swx9N|18|28-547-289-9779|-197.98|AUTOMOBILE|xes across the ideas wake above the requests. carefully unusual theodolites according to the slyly fina +6336|Customer#000006336|IZ8GS3783y5 K6zMxFP,wa9cvcmzVIe4noGXa|14|24-979-385-1940|3438.49|MACHINERY| foxes sleep alongside of the ironic, express gifts. de +6337|Customer#000006337|PiZCe6IVnzD4lUtquLcVYM0eH|22|32-187-888-4292|5610.32|BUILDING|s. carefully final requests use bli +6338|Customer#000006338|PUuGLhCv0G0OYIeBs|21|31-679-556-1647|9653.55|FURNITURE|ully regular accounts haggle. furiously ironic sheaves affix. furio +6339|Customer#000006339|tk70NFG92XanAXo,NySdfkSiQcpyXHW|12|22-301-127-4981|6226.35|BUILDING| pending packages. slyly ironic accounts wake across the furiously even instructions. pinto beans +6340|Customer#000006340|oxxavhy2E4A No|2|12-958-657-2432|1279.15|HOUSEHOLD|inal dinos use. ironic, regular theodolites sleep quickly theodolites. even pinto beans wake accord +6341|Customer#000006341|JPBISK7sJEEmLqyjH8gwtLCqIgByZEh|16|26-657-318-9584|2573.55|AUTOMOBILE|ites. special ideas are across the reg +6342|Customer#000006342|70kmTAuDuG9pOnUUXeUp en555nKm3lyh|11|21-100-162-4466|-326.28|BUILDING|n, regular ideas haggle blithely. bold, regular packages will boost blithely. car +6343|Customer#000006343|RxSzYVBobmzOfG7NTC3JnFIvUoIcgSo|20|30-972-622-2287|3104.63|HOUSEHOLD|ngside of the close accounts are final, e +6344|Customer#000006344|ad,0JVklm5JfxVGyc LkIojMtdbWpZnXT2a1aKSX|7|17-693-904-1827|4576.81|AUTOMOBILE|uffily special dependencies boost bl +6345|Customer#000006345|es2go,e,Lr4TRItOoUAQKzu1OJIS,8cq50Yb|19|29-627-959-8977|8513.41|BUILDING|he carefully final excuses. final pinto beans sleep +6346|Customer#000006346|50RfbxMaJICGgfSOXGA|6|16-291-905-7678|5910.74|FURNITURE| requests. ideas nag fluffily alongside of the slyly pending dependencies. quickly +6347|Customer#000006347|70IEncoPD8K5Vin9BRkBxdndJkIraSM|23|33-977-252-8569|9804.85|MACHINERY|egular requests sleep furiously fluffily thin somas. special instructions after th +6348|Customer#000006348|1W8CqVR0os|22|32-400-947-4328|8251.10|AUTOMOBILE|sits after the unusual, even pinto beans are sl +6349|Customer#000006349|mb,ZNqwU0WkZFYDX6hw|8|18-762-580-1517|8319.51|MACHINERY|mong the ironic dependencies. fluffily special excuses solve blithely. regul +6350|Customer#000006350|9PHlaqUJG84BxDkb8fe|9|19-525-320-9404|3019.75|FURNITURE|efully according to the quickly final requests. regular packages wake furiously after the quickly furious f +6351|Customer#000006351|mXVsAYZWVd8rduL2Ndnd20a bFxcZ39umb|22|32-148-461-6773|7852.79|BUILDING|uickly regular accounts cajole slyly around the fluffily ironic courts. unusual theodolites a +6352|Customer#000006352|RoiheUBTOtjUEm L2kUWHswZBOmhW|23|33-416-643-4777|1902.93|MACHINERY|beans detect ironic, express requests. furiously final asymptotes boost furiously. express acc +6353|Customer#000006353|TiJAQNquw5b57kjKHrf6RLX|19|29-104-330-1710|3465.89|AUTOMOBILE|equests. asymptotes are along +6354|Customer#000006354|NUj4uSOE6ZlEKd5dhc|1|11-652-847-7151|4231.75|HOUSEHOLD|ons wake quickly above the busily ironic deposit +6355|Customer#000006355|0gR84cQxuKr0m6V3z6YnGms2Kqj5 FT FHE5YRwg|3|13-206-334-2025|6066.98|HOUSEHOLD|ven, final deposits are carefully carefully regular excuses. quickly unusual excuses +6356|Customer#000006356|6xjYndpkg 0HArUyB56Xqv7EyDD7JrEi|4|14-568-481-2395|6800.46|AUTOMOBILE|ronic ideas integrate furiously careful platelets. blithely regular packages sleep carefully. +6357|Customer#000006357|,HVhNgTVe,T|22|32-202-348-8130|3312.51|HOUSEHOLD|e carefully final deposits. carefully regular deposits run +6358|Customer#000006358|aynGZ5F8MJIzxoEJc kCqh7J9vj|16|26-600-100-6775|297.48|AUTOMOBILE|ages sleep slyly decoys. sometimes bold accounts nag quickly despite the +6359|Customer#000006359|fhA9rzJfqM686ozX RLctv|22|32-890-744-3388|3722.61|MACHINERY|oost carefully. quickly ironic deposits eat carefully. ironic requests boost furiou +6360|Customer#000006360|WYPts48L0tn7iuLS58Cw8JUY2GUY0enx|13|23-508-750-7646|6814.61|AUTOMOBILE|boost slyly blithely bold accounts. careful +6361|Customer#000006361|VzLr6guzIzrZpZfDZjndwix,|23|33-598-626-9499|-780.01|AUTOMOBILE|ggle furiously regular requests. regular, special requests use. fluffily express asymptotes are slyly alon +6362|Customer#000006362|0H7VGv7MTGlMxF8igvaoXhElF8S bqj|15|25-667-257-1612|236.71|HOUSEHOLD|riously regular theodolites-- quickly unusual packages are fluffily after the quickly silent packages: +6363|Customer#000006363|M,pjP 1RfkcWiPc0wMlUmiaV4cmlz57JMV1BI,|15|25-466-653-4756|5382.91|AUTOMOBILE|carefully ironic requests cajole carefully across the carefully regular asymptotes. quickly pending packages slee +6364|Customer#000006364|P7n15pH0vDHA|3|13-693-752-4345|4585.65|AUTOMOBILE|according to the carefully final accounts maintain carefully among the even packages. ironic, i +6365|Customer#000006365|q9FqvI49NhkzJH6lwSPbM,8sD|23|33-576-256-7432|2994.15|HOUSEHOLD| use blithely pending courts. even, ironic deposits about the quickly special dep +6366|Customer#000006366|EAiyyzQp,q7GUp0wQzThB4OasmaTEnE4z|12|22-771-559-9705|6622.87|FURNITURE|s are according to the fluffily ironic instructions. quickly ironic packages haggle slyly among the furiously +6367|Customer#000006367|hGP9UlKdD2BN3LePLnOJ|2|12-744-594-5061|-340.83|MACHINERY|y final foxes believe ironically. carefully pending theodolites haggle. carefully final pinto beans haggle care +6368|Customer#000006368|9wlLx9qDuskAA5Lg3CgbgK2,RYX3|7|17-527-847-1825|591.04|HOUSEHOLD|arefully regular ideas use furiously after the special, special waters: accounts alongside of t +6369|Customer#000006369|2GoiGrH9dEHSKHX3Y8fbA|3|13-817-557-7983|9563.67|HOUSEHOLD|e carefully final accounts. quickly final d +6370|Customer#000006370|mpRkYWqUoJQncfc7Q3VEEgI3eyoGyKFzPJ|3|13-586-788-3167|2734.72|HOUSEHOLD|wake furiously carefully regular theodolites. unusual foxes haggle slyly among the regular depos +6371|Customer#000006371|sqDry7KOh6ztkEJrGoX Y7NPIBW3|16|26-326-418-1698|2443.10|MACHINERY|onic packages dazzle furiously. ironic, final foxes wake slyly. re +6372|Customer#000006372|cN5aX8yXPYruA4rITmdh8e1QaOEyjEeub|7|17-585-758-4417|7197.10|MACHINERY|ithely special requests are alongside of the quickly final requests? furiously regular instructions lose furi +6373|Customer#000006373|Ap2nqlR9SntNoWkk5DFSON84r|22|32-608-822-4087|3700.15|MACHINERY|he packages. unusual asymptotes haggle alongside of the final, +6374|Customer#000006374|6U,tnx3EQ6ymmLLtrRYD8FwwaQEiwvEqA2pL|20|30-879-852-8442|3388.38|AUTOMOBILE|s at the ironic, final pinto beans nag quickly after the packages. slyly even instructions wake furiously +6375|Customer#000006375|,f00Mk7z1TQ4lHuZQA|17|27-709-238-4692|-510.18|HOUSEHOLD|nal excuses. quickly bold packages across the express requests sleep slyly about the slyly final foxes. ironic de +6376|Customer#000006376|9xX7j8zvAb3rY,y2N6rakYVhkcNShJZ|6|16-888-795-8432|3376.54|AUTOMOBILE|lent foxes affix against the even deposits. fin +6377|Customer#000006377|fb5rLUH6Hn|18|28-929-173-8781|9538.01|HOUSEHOLD|lly. instructions are. regular realms after the deposits integra +6378|Customer#000006378|jk4,Yt5J6YsUnLKs3Fj8PWF8y|21|31-227-241-6464|330.88|BUILDING|. express pinto beans doubt quickly. silently bold platelets haggle. furiously regular packages sleep alongside +6379|Customer#000006379|fJOnWmoLfEKa8FDt9T6foVT2njtBKSEnnsQlV0|1|11-989-205-6094|4057.27|MACHINERY|lyly regular deposits. foxes cajole blithely regular, ironic accounts. reg +6380|Customer#000006380|A3CZEoXr2U3M9TJq|14|24-601-213-9207|-453.65|AUTOMOBILE|its nag quickly. furiously unusual platelets x-ray. car +6381|Customer#000006381|qgLG,UnydWWKKYvXEe6g,|7|17-877-502-9214|7346.88|HOUSEHOLD|onic instructions wake furiously according to the carefully express instructions; pending theodolites +6382|Customer#000006382|iT3z1RZJfuFhTVQWn gUQQ30J59FLhUtNa1y|5|15-884-325-7498|2101.57|MACHINERY|ely pending requests haggle s +6383|Customer#000006383|pZMLOQVPjfqg3JvDp|8|18-910-470-6748|9130.34|MACHINERY|its. blithely express asymptote +6384|Customer#000006384|eRUjfmK9XOnuIxULs,H3g2jasWFLc|23|33-767-423-3297|1756.89|FURNITURE|sleep alongside of the slyly idle packages. slyly si +6385|Customer#000006385|feb0lDE33xT7COEBl4CL|15|25-446-991-1683|1948.61|AUTOMOBILE|eposits haggle blithely regular, pending requests. carefully even +6386|Customer#000006386| ,6di,DsCLRoei7glq03Dv03xA|24|34-991-678-6036|1252.97|HOUSEHOLD|sts sleep carefully blithely bold packages-- the +6387|Customer#000006387|YU5Ai0APMax|10|20-581-220-3948|2536.86|MACHINERY|ckages use slyly regular, regular deposits. special, regular deposits +6388|Customer#000006388|p8xZE4LxJw,BhxqdqhnokSPs7TIAZyieKyyzse|14|24-525-264-8052|9925.28|HOUSEHOLD| according to the regular requests cajole carefully above the even depend +6389|Customer#000006389|h1DyF2DxWF0|10|20-749-986-1120|8270.04|BUILDING|slyly express packages affix. carefully ironic requests use among the bold foxes? blithely regular hockey p +6390|Customer#000006390|bn2EoZThG0 s3CAOW0V|17|27-231-144-4566|7571.48|AUTOMOBILE| bold asymptotes use fluffily special packages! slyly final theodolites unwind slyly about th +6391|Customer#000006391|tJFRcLobeDbMdgzr1EfSw7PtH8Uqx97Pd|10|20-447-685-8271|3923.68|HOUSEHOLD|yly thin braids haggle quickly unusual, pending deposits. ca +6392|Customer#000006392| Nn14Ugte47JXBLpdJj4NAXbnsmyk2ykL8v0B|6|16-236-622-1653|9277.66|FURNITURE|s use. bold accounts affix about the ironic theodolites. ironic, ironic packages according to the special pack +6393|Customer#000006393|LrSfeTLkBD8iJmD4,mkCP0awj6UnAxhohA|10|20-600-941-3910|2762.42|BUILDING|ial sentiments cajole quickly. slyly unusual accounts boost blithely regular +6394|Customer#000006394|Qsb,p1hXnullljxxWg7svdXJSXRT58Tjxm2|2|12-653-895-4516|5972.35|HOUSEHOLD|rs doubt even requests. slyly express requests haggle ironic packages. pending accounts nag fluffily after +6395|Customer#000006395|g qNyxByuAIIKgSdK8ye9mw B1ujFXueIu9|17|27-165-881-6729|379.03|MACHINERY|are furiously. carefully silent accounts snooze quickly along the bold, final depos +6396|Customer#000006396|OkUGWXg2r42,|21|31-720-445-5419|-695.45|HOUSEHOLD| even theodolites nag furiously. busy instructions affix slyly after the careful accounts. doggedl +6397|Customer#000006397|OupmJTZAYWzow1H3zbv,v|3|13-204-711-1078|2415.67|AUTOMOBILE|ly against the furiously express notorn +6398|Customer#000006398|nE3eEiDxvFRyoT|5|15-144-311-5947|8155.12|AUTOMOBILE|ly special requests. bold, ironic accounts nag furiously sly +6399|Customer#000006399|dQbyCKR,g2,MXLYPiFE1NlLxzL|20|30-783-132-6452|1103.67|MACHINERY|tes. pending dolphins nag blith +6400|Customer#000006400|B7M0M7FZy06iyPxs VmGJaRJeYgSiL|13|23-177-650-5024|1362.29|AUTOMOBILE|ctions are above the permanently ironic packages. +6401|Customer#000006401|yveLKpTUIx7K6WtnhXAcz5|23|33-945-761-8571|2891.62|HOUSEHOLD|yly final foxes integrate across the carefully expres +6402|Customer#000006402|GLZyBHPsfH,y|9|19-260-224-4337|-594.88|HOUSEHOLD|uctions cajole slyly according to the f +6403|Customer#000006403|9eX1E4GyIXptoHrL5db b7wqVYaUB55u|24|34-376-305-4671|9717.24|FURNITURE|ly unusual accounts cajole slyly even platelets. carefully even package +6404|Customer#000006404|s,kUf5HrSnq,g8un,UAcz7HvRQ MV|19|29-917-546-1913|9678.44|FURNITURE| furiously bold deposits eat ironic ideas. slyly regular theodolites across the even i +6405|Customer#000006405|I0BmHPY,nxSz0vA8a|24|34-382-195-4386|6618.54|AUTOMOBILE|sly pending braids. slyly even platelets sleep fluffily final packages. express patterns integrate finally pen +6406|Customer#000006406|lL3dzJv7lVqtqz,DiuUHcvH1EcpM9X8jba|21|31-342-422-4630|3830.68|AUTOMOBILE|es would haggle after the final pinto beans. slyly ironic deposits sleep quickly. asymptotes h +6407|Customer#000006407|BtK4gy01cd|6|16-862-127-3910|8151.95|MACHINERY| ironic platelets. carefully bold excuses mold slyly above the pending pinto beans. asympt +6408|Customer#000006408|oa9bZUw3jwpkK,Gd|9|19-912-624-3972|2836.65|AUTOMOBILE|boost against the quickly final requests. daring +6409|Customer#000006409|T0HCEe4pnQrvw|17|27-890-763-2774|-451.44|BUILDING|its about the accounts nag even foxes! slyly i +6410|Customer#000006410|GGGN,NDpImMdzCHOjMg6D,35uOrTr3yJ71fW|9|19-197-885-8569|530.65|FURNITURE|side of the special pinto beans. dependencies are. regular, ironic foxes cajole +6411|Customer#000006411|z3ej9PD1gmKm1uaQySQhjFndp0kz062lnUVt|0|10-759-591-4295|6576.83|FURNITURE|y bold foxes. foxes haggle slyly about the silent, special ideas. slyly regular requests haggle across the pendi +6412|Customer#000006412|wJVfQt,87Ckyca4rS4yh8PPGbzQyVxCXqil9ex|24|34-744-473-7572|6753.76|AUTOMOBILE| furious accounts after the furiously regular dependenci +6413|Customer#000006413|okFK1CC8ibk3ml7X4ZhRl|10|20-949-158-4934|-563.78|AUTOMOBILE|ades. frays wake slyly. carefully final realms sleep. qui +6414|Customer#000006414|3mdeAURniRPufSi6dz2|24|34-799-456-8937|4444.30|AUTOMOBILE| final pinto beans. furiously bold pinto beans nag. blithely fina +6415|Customer#000006415|0SOe8iGHkEtlpwV7 e|10|20-971-763-1702|3396.66|HOUSEHOLD|ependencies. quickly ironic pack +6416|Customer#000006416|WGVJj9TyQ5ac3qL7RHW8jSOYQH6XZV|2|12-415-551-2448|6601.37|FURNITURE|lar theodolites. accounts use sometimes fluffily ironic packages +6417|Customer#000006417|06dHuGAxyFTfEygMp6ZU|23|33-360-140-2353|1256.36|MACHINERY|c sauternes. carefully final fox +6418|Customer#000006418| ydC4OuGkly|1|11-186-687-6620|4592.96|AUTOMOBILE|sts. unusual deposits haggle against the regular, +6419|Customer#000006419|JisGDcZRiDHg4yLNKSc2HPy32KfTIL,|12|22-243-778-7315|4838.38|FURNITURE|ound the fluffily furious accounts. courts haggle furiously about the quickly final packages. carefully eve +6420|Customer#000006420|ROdVxbHD0,GVCY,9NwYfDO|22|32-469-891-2051|4658.51|BUILDING|sts cajole according to the dependencies. final requests cajole carefully. final courts are fluffily express, slow +6421|Customer#000006421|fv4AI3OzYxdrM3I4cuDUoxMfOubOlO1m6Oxmv|3|13-450-314-2988|6650.59|FURNITURE| according to the slyly bold accounts are fu +6422|Customer#000006422|ZltvyXcMiO|2|12-501-888-2104|3415.78|HOUSEHOLD|nto beans. fluffily unusual deposits boost slyly. quickly +6423|Customer#000006423|7nudsRA5wmNNjs4,FThBletUyOIq|19|29-421-996-4033|9077.24|FURNITURE|inal, special accounts. furiously final pinto beans a +6424|Customer#000006424|ieZS lxnQBTqJO8BOfz7mcPbUsnlS|6|16-525-665-8732|258.29|MACHINERY|lly even accounts sleep slyly alongside of the blithely final asymptotes. bl +6425|Customer#000006425|y4kyZJUM4AOCGcaIjuj8as6XMgEb,tZyXaWTY2yS|9|19-638-440-4991|5006.99|AUTOMOBILE|fully even requests integrate quickly final pinto beans. carefully silent ideas cajole +6426|Customer#000006426|MBbafnBIIVTjNxVB8,yZcLEMlp5FbyMCFozSR|16|26-200-900-4409|529.42|MACHINERY| bold requests wake slyly. even instructions are. slyly express accounts nag blithely +6427|Customer#000006427|Xa17u3du45DiLnp8SEaIgKaS8l|5|15-852-433-6135|7907.55|HOUSEHOLD|s integrate even, regular foxes. blith +6428|Customer#000006428|jiZdycWOv3UcTXmeQYadg7xOV6LRX|20|30-758-610-5037|9217.56|HOUSEHOLD|kages boost slyly carefully pending packages. b +6429|Customer#000006429|723rhJstUlnqt siNCyOV67ZVvTEXcJ0PqJ1uE|14|24-314-971-8033|4648.01|AUTOMOBILE|thely pending theodolites haggle furiously express requests. fluffily even requests are furiously pending requests. +6430|Customer#000006430|xXFJR6GUfqeCyN5PiAvrw7HV2U|11|21-549-125-1175|6077.54|BUILDING|quickly among the special accounts: even, special packages according to the quickly sp +6431|Customer#000006431|alr2AvVdnwHuR6MYiNcZvdfHfN seFOpZMS|4|14-847-121-5795|8310.76|MACHINERY|inal orbits about the final deposits wake furiously blithe instruc +6432|Customer#000006432|4PGhIJsN8,hNjTsk6|22|32-173-374-5893|9988.42|HOUSEHOLD|encies. special requests after the regular, regular packages use +6433|Customer#000006433|a3pPw8Sauu6hhR4k5uL7wg1H95kiZ64Tk|19|29-909-421-8085|2412.87|FURNITURE|ickly final deposits use carefully. blithely +6434|Customer#000006434|XEo,6jjEzKR0aOUcozaEu8 gisw|2|12-500-275-2120|5131.87|BUILDING|e slyly bold pinto beans. final decoys use against the special ideas. furiously ironic courts against t +6435|Customer#000006435|Bg7iFjWjLVQKT0AEclRbHPBTDpvlrEXKAD9K2|21|31-382-296-1618|9295.79|AUTOMOBILE| bold deposits cajole furiously theodolit +6436|Customer#000006436|yfj8DtQgQrb52|13|23-860-371-1102|-651.11|AUTOMOBILE|ular dependencies cajole evenly final the +6437|Customer#000006437|pZ639dzBsf14zfwauL0jOSYTGQ870YRctiD|23|33-994-170-5321|-282.52|AUTOMOBILE| about the final accounts. slyly bold instructions are iro +6438|Customer#000006438|RyVaFQyhkoASdbPjYYBI|3|13-147-903-2434|1684.90|BUILDING|lithely unusual instructions nag according to the slyly special theodolites. express, r +6439|Customer#000006439|JoIRrAaO8XlKsPF35eCO8Vcy0o5L|13|23-346-902-8254|2048.44|MACHINERY|cuses. final, special ideas boost furiously. furiously close dependencies above the daring deposits wake according +6440|Customer#000006440|EhPeQVf4268eEE81yT7L3kHeBFC1nsvYjF|22|32-963-990-1859|7040.39|MACHINERY|aggle quickly excuses. regular packages nag ruthlessly regular, idle sentiments. bold account +6441|Customer#000006441|XG8rZ2j868y,WH1VUBZ|19|29-490-926-8692|9951.53|BUILDING|es affix carefully. slyly regul +6442|Customer#000006442|KHfAHw,EYDgYxunkuoCi5UZb 0nZL6i868CET|19|29-922-394-2085|9442.52|AUTOMOBILE|osits haggle quickly slowly final requests. even, fina +6443|Customer#000006443|pHv34YqZSMUDlEyxk Mlvf6Ub,|6|16-852-419-2587|1478.34|BUILDING|nic courts haggle slyly blithely regular theodolites-- special excuses use slyly. ironic dolphins are slyly f +6444|Customer#000006444|7wOibQuMiSsum0zAfieMfvToucnh|15|25-268-268-9763|6469.44|HOUSEHOLD|sits use among the fluffily even foxes. furiously regular dependenc +6445|Customer#000006445|J8HlYAyAUaCQpMoj4cTlS,TDmGK8gcKnrDxmUPG,|5|15-192-490-3051|5966.09|BUILDING|, regular theodolites according to the quickly even pa +6446|Customer#000006446|V0Dd,KY57jzAlKGMwRdstqlBUgAj12janY O8|2|12-139-856-4622|5131.95|FURNITURE|bove the regular, even instruc +6447|Customer#000006447|2iQk,R9iPSQKkb3e7oQi |23|33-450-821-7164|-380.57|MACHINERY|after the ironic requests thrash slyly carefully special +6448|Customer#000006448|13Wg2FUg2Ffki TBsY517Ztb4fytGvRe8peQtJ0|0|10-486-606-3968|3677.31|MACHINERY|ing requests. ironic, ironic deposits cajole above the carefully bold deposits. pending i +6449|Customer#000006449|pE4YcxWffV,7kwV8BX4XyOY4S7|1|11-503-687-8564|4467.60|MACHINERY|ptotes sleep against the slyly regular deposits. express requests wake ironically across the blithely r +6450|Customer#000006450|Gc,ojHknX6MUSgmXpv8EmEhKPkU|24|34-272-661-2143|9888.45|FURNITURE|riously slyly silent courts. ironic, final excuses sleep after the regula +6451|Customer#000006451|E,ekihaEI,uN4kGRUwQ csQjx3hVRvUDh,|12|22-457-204-2046|5307.46|AUTOMOBILE|ts integrate carefully carefully pending theodolites. quic +6452|Customer#000006452|Qrin8a98Frzmr0kMzVeX9h6|18|28-426-597-9924|1512.79|HOUSEHOLD|ironic theodolites. requests detect carefully silent courts. slyly +6453|Customer#000006453|pZ0jI IY sh07aKPdmQ7uv3ta8eU,jCXFbL1|22|32-372-439-2517|2372.25|BUILDING|into beans sleep at the blithely brave accounts. unusual deposits wake +6454|Customer#000006454|ypyPdN8tQvcYERecN,3Oufizu|1|11-276-495-7172|4437.76|FURNITURE|ly special packages cajole ruthlessly around t +6455|Customer#000006455|unZZGWq2HBJ4EKR3UlbpcORxMlO|2|12-239-754-9487|3482.98|MACHINERY|c pinto beans sleep blithely carefully express accounts +6456|Customer#000006456|XF8NeBd23gN|23|33-589-473-6210|5405.47|FURNITURE|dependencies. final accounts are furiously. bold instructions use quickly. express, br +6457|Customer#000006457|RWwZBhG0WF8ixJJ9csB|2|12-292-531-2808|9754.94|MACHINERY|olites cajole blithely. blithely bold foxes wake blithely. regular deposits sleep blit +6458|Customer#000006458|9hveScYbQY iKmqJuNs9PetcC|9|19-701-840-4110|5425.87|MACHINERY|pending asymptotes are alongside of the ironic, pending dependencies. blithe +6459|Customer#000006459|zd0TdwWz,IhDrPeawC3G9SHV2Tr0r|16|26-264-700-6190|633.59|AUTOMOBILE|carefully regular requests are furiously about the packages. furiously special accou +6460|Customer#000006460|Pr5bp2A90JjbrjE1XN5HM1|12|22-504-912-3129|9685.49|BUILDING|ending ideas. regular platelets use quickly final theodolites. foxes affix above the regular epi +6461|Customer#000006461|vgpOxXZRI,,Y92 1NO7N98jKwnOY7|5|15-362-557-8104|4166.62|AUTOMOBILE| blithe packages boost slyly. blit +6462|Customer#000006462|3njV5Ft7NhNxW50neyjlryC0Ylq0fI0n,P|18|28-848-982-8505|433.66|AUTOMOBILE|l requests play carefully across the instructions. blithely +6463|Customer#000006463|M9Oy,Xx9CbN GSl3L6khL0LTRgCi8MgX0gTzVbCQ|23|33-939-251-7239|4447.04|HOUSEHOLD|final foxes. accounts should nod against the unusual, even instructions. blithely regular theodolites hag +6464|Customer#000006464|eF9E6ScHCw9,z8nF0py9 ySlB0 iHTIEEZRWl6H|1|11-870-572-9943|5468.53|FURNITURE|telets could are quickly regular packages. fluffily iro +6465|Customer#000006465|hh2iSvQ3ixAtfId4QsSzJOMORcy4t|24|34-206-617-3619|2544.19|FURNITURE|express packages. ironic requests wake carefully +6466|Customer#000006466|nxPwv4px0 1LW05BtXaT7m,b2a63Dq8s25b09|20|30-314-197-3871|1131.19|MACHINERY|believe furiously. unusual, pending deposits wake. quickly pen +6467|Customer#000006467|VKsGXyxDaRzjYny fn 1zOOjPmkA9ZDp1C6lu|11|21-298-482-2423|1798.41|BUILDING| slyly special instructions boost carefully. final packages +6468|Customer#000006468|NTWZxBhUwmLUSwoXnrTwKdFs2|8|18-741-953-3789|6840.45|MACHINERY|y ironic deposits are along the furiously ironic requests. theodolites can are. accounts use after the f +6469|Customer#000006469|kDCpN,X8RAKe6EHXL6zsygq57|7|17-884-283-2518|4429.67|MACHINERY|osits hinder slowly along the regular accounts. even, unusual foxes wi +6470|Customer#000006470|BHgwAOTI0WReuiU9Ub1y|24|34-790-284-2739|-501.95|HOUSEHOLD|c platelets. carefully regular platelets sleep carefully. blithely unusual dependencies haggle. packages use furio +6471|Customer#000006471|z64U8Zsf 1ItZlk|1|11-284-691-1178|9608.94|AUTOMOBILE|bove the slyly even requests haggle even ideas. slyly r +6472|Customer#000006472|sLyBV0ZtMvAH1QSOnxg6koHGsKzzjm7RWuEMRWQV|20|30-220-128-1332|4515.01|HOUSEHOLD|onic pinto beans. furiously final platelets promise never. fluffily ironic instructions p +6473|Customer#000006473|Ee0nC9W1Y9j6e4V|9|19-156-916-4569|3728.77|AUTOMOBILE|al theodolites boost across the even dependencies. express theodolites sleep enticingly fluffily ironic i +6474|Customer#000006474|AqmYPBgr9r vxl8sMzecS5ak3JJ4ByqN5 |9|19-500-356-4558|478.16|BUILDING|e blithely pending dolphins. packages +6475|Customer#000006475|itSIjP3CZMWKp3MjgSuPFim0l6T|8|18-427-310-9935|4338.27|FURNITURE|pades. blithe attainments impress quickly ab +6476|Customer#000006476|NbYct5LvnQfrajINpQm34t3yxD32UQED5bk5dNPG|16|26-531-511-8701|3327.81|AUTOMOBILE|side of the deposits are slyly around the ideas. quickly final accounts wake furiously. bol +6477|Customer#000006477|qylnoy8Yoou7au1IjGNmAR,amKok|1|11-336-397-1897|4554.64|MACHINERY|ly permanently final warhorses. deposits ca +6478|Customer#000006478|E1ZXZROw4YBwc4HhN2M|6|16-483-594-1126|9874.64|MACHINERY|lar accounts are quickly fluffily pending packages. special pinto beans above the slyly bold excuses hag +6479|Customer#000006479|r,YZ8Bqo9gHbHFfnEITjeU4riKFay4mvovDTmc|11|21-143-392-9914|4160.96|FURNITURE| quickly express accounts. slyly furio +6480|Customer#000006480|jZCx1qKm8AJtV|14|24-732-299-9650|4276.33|BUILDING|ending realms cajole at the caref +6481|Customer#000006481|QM0JCcwqe 2OSh5LpTjoQVL0dIbCJ3unJO5V|9|19-708-287-2759|7278.40|BUILDING|pecial packages are busily according to the ironic escapades. slyly +6482|Customer#000006482|dOVykuZo,txNWSMQncRnWc4Goi9sslnW5zv|2|12-270-253-5013|6111.54|MACHINERY|ncies. slyly unusual platelets haggle slyly above the even, express deposi +6483|Customer#000006483|ZT8TwDuABR77|11|21-679-759-6880|7606.73|FURNITURE| are. carefully bold instructions by the foxes are along the slyly express theodolites. eve +6484|Customer#000006484|VbH7IC5F ZR1CDcyyjxX|3|13-467-401-7503|2438.45|MACHINERY|ress whithout the blithely regular deposit +6485|Customer#000006485|sCWkSZkKOpsnFhyNUIccdfvFvipe|1|11-541-386-1396|5926.60|HOUSEHOLD|ly express foxes integrate after +6486|Customer#000006486|huOvXcWg648ez69Yyebn8|11|21-909-289-7137|1380.84|MACHINERY|l theodolites. slyly regular ideas sleep carefully slyly idle asymptotes. fluffily unusual ideas +6487|Customer#000006487|1JfLyCcXKGeHiEV|12|22-967-924-9865|6789.80|HOUSEHOLD|uests across the packages could have to nod furiously silent dependencies. final or +6488|Customer#000006488|fEUg4BCUhNIcaNVKNdkadz2N2lIDWybFm,quvpnO|8|18-915-822-5617|144.97|MACHINERY|final deposits serve carefully about the slyly ironic or +6489|Customer#000006489|z6IrxkffxNyMYDRx4qR,PQnTDYSMXG3bsdBD8mx|8|18-713-226-2794|3494.92|HOUSEHOLD|s haggle around the carefully unusual deposits. carefully even theodolites are enticingly ironic dep +6490|Customer#000006490|VjpZnXeSD2oIK0U,CNLNfRxZF1NDFadS W|1|11-122-897-9952|8180.23|FURNITURE|n instructions lose carefully alongside of the fu +6491|Customer#000006491|J3,jSVfCkxq91fHjycRrqx1mQ,sGEFBT7iCtgu|6|16-977-273-4547|5239.92|AUTOMOBILE|al foxes sleep fluffily along the +6492|Customer#000006492|nPlHrfRAlpx|0|10-440-853-6387|-723.71|FURNITURE|ruthlessly regular packages. pending platelets near the slyly ironic packages haggle quickly against the blith +6493|Customer#000006493|ZT2dynxWMfOTM|19|29-295-246-8539|500.11|MACHINERY|ending decoys. furiously thin ideas cajole according to the f +6494|Customer#000006494|Vu5i1odOtPFZVNY53su76yFnal |12|22-121-359-7339|-795.34|HOUSEHOLD|ts across the final packages are slyly ideas. blithely unusual ac +6495|Customer#000006495|Hs,w9KO2RR At|18|28-465-937-3117|6679.86|AUTOMOBILE|deposits. theodolites hang blithely after the carefully ironic +6496|Customer#000006496|tdAcewkJ,9IL7tYdP6xFSlR4sxhzqYx|14|24-755-676-4374|517.43|BUILDING|cies wake slyly according to the blithely ironic accounts. slyly even packages across the slyly ironic a +6497|Customer#000006497|0m1WM8YSt2E1jhOAohr3Zs9NJuVlgORZFF85yp|21|31-417-915-1172|4355.91|MACHINERY|refully pending packages. even pinto beans haggle across the pinto beans. final instructions after the foxes +6498|Customer#000006498|M,,F70BZbI7wFy Eij7bct0rFLaJkqFN5DS8vS8|3|13-779-226-9489|2765.60|MACHINERY|side of the pinto beans. slyly express theodolites sleep regular, special platelets. slyly bold depos +6499|Customer#000006499|zXN1H4vSEbL VEvBO5lT8IICF|22|32-496-645-5422|4390.89|FURNITURE|tegrate alongside of the final, final theodolite +6500|Customer#000006500|SQLIuXRcQ3Q7G38eUgMXV4ybIKPQxKS0|21|31-954-475-8701|7764.33|HOUSEHOLD|ggle against the silent excuses. frays doubt quickly. carefully pending deposits sleep quickly final +6501|Customer#000006501|9v8gAkVB KcQoBRKbQ2rykps4fKqYX|24|34-433-352-7689|184.55|FURNITURE|pliers. platelets eat slyly against the even accounts. fluffily express requests are furiously unusua +6502|Customer#000006502|mbRY4j5rudW|11|21-562-896-1594|8710.50|BUILDING|eep among the fluffily ironic req +6503|Customer#000006503|4p3W4XHBSKbswkOpK3jehDgW|11|21-476-545-9987|7492.32|FURNITURE|st the quickly careful instructions wake quickly according to +6504|Customer#000006504|,XoJJFtPqo6Hk7GxI4agFf9r5|8|18-223-523-7723|4395.75|HOUSEHOLD|al requests. carefully unusual ideas en +6505|Customer#000006505|,35tS 0nsQ,|10|20-116-997-7935|1320.29|MACHINERY|al theodolites: carefully bold dependencies haggle pending accou +6506|Customer#000006506|Mol5UoqoOCHvOfBHz3s07NcF7HoU2rIWZGlkcI|7|17-831-994-7711|1146.56|HOUSEHOLD|wake blithely after the idle, even packages. final pains c +6507|Customer#000006507|ewNKMjvFSXSHZRYQnPbMCYqB|21|31-762-523-7126|7134.11|FURNITURE|ar foxes around the carefully even deposits haggle quickly quickly final i +6508|Customer#000006508|Swm,c vbMg36c1z5,4fdBedBNG1OrfhsTPco|18|28-986-386-9035|952.00|FURNITURE|ters are above the express, ironic dependencies. express deposits according to the furiously furious packages pri +6509|Customer#000006509|70iy4ZLmA6,OjYW7tTtxlnxkJf N5|24|34-658-604-7430|4234.26|FURNITURE|ly final theodolites affix fl +6510|Customer#000006510|mHOy9Hl0Qj|0|10-992-585-3630|4211.77|MACHINERY|express accounts according to the quickly specia +6511|Customer#000006511|Hqpb ssH,HNi|0|10-987-779-8094|238.09|FURNITURE|ost slyly carefully even packages. slyly final theo +6512|Customer#000006512| 33vAzHrrXIgd68KBr4mD|7|17-511-867-8977|6571.18|BUILDING| after the final requests. carefully ironic packages nag slyly. fluffily eve +6513|Customer#000006513|0yWTa31spHkfkccVy,mRh|4|14-344-180-9079|-125.66|MACHINERY|ites doubt fluffily. furiously regular deposits +6514|Customer#000006514|F8eUA3o2KlPxQoOP42h,cNYShHe|10|20-816-198-3141|8911.35|AUTOMOBILE| sly deposits alongside of the requests are carefully carefully unusual a +6515|Customer#000006515|knMzD7lwT9|16|26-565-114-8675|6121.09|AUTOMOBILE|t ideas. excuses across the furiously fluffy accounts use quickly about the express, +6516|Customer#000006516|zL3M2qRYhxxz|4|14-657-773-6508|3208.09|HOUSEHOLD|ole furiously among the slyly express requests. foxes sleep blithely blithely bold ide +6517|Customer#000006517|tjhz2CB9lXX0TcmPRX|17|27-923-897-4118|5407.70|FURNITURE|the furiously ironic packages haggle blithely pending req +6518|Customer#000006518|1gxNOhqNUnOgcA8pfdSuYB1ROX|13|23-117-625-2924|3187.34|HOUSEHOLD|inal requests above the furiously final asymptotes are bold, +6519|Customer#000006519|NomK60Y3wXy06J7YEMGp 3,XRpg0j9IxcDtVEAM|21|31-885-482-7206|8593.58|MACHINERY|pinto beans. furiously unusual platelets integrate. furiously special packages are. fluffily express fox +6520|Customer#000006520|GgmUKbGO4YqccuU|2|12-135-446-1603|326.88|FURNITURE|p slyly about the silent requests. qui +6521|Customer#000006521|ocqjyIQB3nrDvcPfNK6YdWLJRV,aNNfYjBl|3|13-856-838-6626|2762.22|AUTOMOBILE|ironic braids above the regular r +6522|Customer#000006522|9lIS6iU8xfx2UB77M,cRbhUYe7WaawYE|2|12-106-450-9122|2611.92|MACHINERY|ress notornis integrate blithely inside the slyly thin deposits; ironic, regular platelets hinder +6523|Customer#000006523|ppBY8l3kJDLcOjqD0mF5H|21|31-855-623-3767|6472.78|BUILDING|counts wake blithely. carefully pending requests haggle carefully. slyly ruthless asymptotes wake furiou +6524|Customer#000006524|3NMnX6Cbi83z3Cul C|14|24-198-901-2901|7024.93|BUILDING|rges. even packages sleep across the furiously +6525|Customer#000006525|9TeyC0eRLeHUiJYR9EA8fimqlu6biVgxdxVx|18|28-268-185-9919|2973.93|MACHINERY|s promise furiously across the final grouches. furiously final accounts according to the ironically final re +6526|Customer#000006526|j2e,TUUVZxaFSuiJauFDS2eo|5|15-609-391-3715|7755.32|BUILDING| courts cajole blithely above the fluffily bol +6527|Customer#000006527|R0sIPtavn8fgJTfsLCVTfSuuFHkTVFh0ZscC6Rub|13|23-215-568-8678|2722.00|FURNITURE|furiously: furiously unusual packages cajole. pinto beans are furiously across the unusual accou +6528|Customer#000006528|5F4Zd7t2UCw COOvRxsTqSFYbNuT3LNWqAbE|15|25-123-454-7331|8627.24|FURNITURE|l requests boost carefully across the furiously regular dependencies +6529|Customer#000006529|z MsqjmOtVW8ynDudk6XiUsAurx57YfL9|6|16-605-167-6202|5032.68|BUILDING| orbits are? unusual, ironic accounts are slyly. unusual requests sleep after the ironic, ironic ex +6530|Customer#000006530|MV,sirXvlYHdNS|17|27-993-759-6289|3190.15|FURNITURE|e requests; quickly regular excuses nag +6531|Customer#000006531|mS8cUs YGyXTFQ6,raiT IVNEprioVqOkf02J|2|12-613-384-6941|889.74|MACHINERY|ng warthogs print furiously i +6532|Customer#000006532|TvhgzSH6z6mBFPH4PVuV8WYBdwaL|1|11-390-945-2159|2857.43|AUTOMOBILE|xes. quickly bold accounts detect accordi +6533|Customer#000006533|nlQQZE8X8Gcs0DTc4FbikdL|0|10-292-966-8076|7733.20|AUTOMOBILE|ions. requests wake slyly alongside of the even, even depths. always regular accounts after the blithely exp +6534|Customer#000006534|VxsPQuMbLvQ|14|24-272-292-9916|4916.15|HOUSEHOLD|ly alongside of the furiously unusual packages. special, ironic orbits +6535|Customer#000006535|x nBq56OShrH,akf9CsjKBDGZXYjPPD0JClsM|22|32-183-174-5882|2786.57|HOUSEHOLD|e blithely express requests. packages breach along the packages +6536|Customer#000006536|LCjRJ4bGqSQQ|7|17-209-711-6334|4800.56|HOUSEHOLD|ate slyly slyly regular accounts. furiously speci +6537|Customer#000006537|crEEScryYpiugrKGzY2vjFvO22Bq,wCnTwIzpYN|10|20-987-261-6336|7057.74|BUILDING|ymptotes. fluffily final packages above the packages cajole carefully blithely regular excuses. packag +6538|Customer#000006538|zKfgcSybmZ8|19|29-312-894-5415|4435.01|FURNITURE|nal, regular packages. furiou +6539|Customer#000006539|7Il6KjzRIE xHg8B2wsoIP5y 5t|19|29-262-259-8994|1175.83|AUTOMOBILE| with the carefully even requests. even, bo +6540|Customer#000006540|I8kQ2XzSVZ3sXkl|16|26-663-746-1303|4042.13|HOUSEHOLD|instructions integrate carefully. final requests sleep. quickly special de +6541|Customer#000006541|3ua8FZTnQ5aC|18|28-614-720-7659|9117.32|HOUSEHOLD|al dependencies. carefully final instructions cajole account +6542|Customer#000006542|0r NUZcHVeN5ZImNTuc2Gjf3st|4|14-681-824-2073|2821.51|FURNITURE|r packages. carefully even accounts cajole carefully along the regular, ironi +6543|Customer#000006543|vv4vWlUAksCLLGzokFhUypa0d67QFAE2pxiH,|18|28-439-480-5859|9050.06|FURNITURE|express requests wake slyly even dependencies. close requests around the car +6544|Customer#000006544|blMRmjCIk9qZDmu|8|18-430-406-1141|5344.32|BUILDING|totes sleep fluffily. ruthless, special accounts alongside of the carefully +6545|Customer#000006545|EVlv0HyoPBatXo6VRaH0uSmnfd0YQZggZBaeHrB0|3|13-174-449-5530|5016.87|BUILDING| thin pinto beans boost furiously ironic instructi +6546|Customer#000006546|zYQtqlAP5jGhQOtMELGmOF QYmKwL,|22|32-365-893-3285|1530.52|AUTOMOBILE|e carefully against the pending requ +6547|Customer#000006547|3zLebAX1KgiP7|7|17-710-138-4406|3321.43|HOUSEHOLD|ide of the slyly unusual requests. blithely ironic packages haggle. quickly silent pinto bea +6548|Customer#000006548|32TjRFavvtwh M|1|11-397-769-2069|7325.51|HOUSEHOLD| have to are always pending deposits. slyly silent requests wake carefully regular accoun +6549|Customer#000006549|qAhHr41OY7bbo|7|17-522-198-9893|5850.07|FURNITURE|encies are blithely. special theodolites above the slyly regular realms cajole fluffily foxes. unusual requests sl +6550|Customer#000006550|3bUibIk2 e0g9upYw7f|21|31-679-244-3796|2107.94|BUILDING|ending, bold dependencies boost. regular, silent foxes haggle. deposits h +6551|Customer#000006551|CFd12CDJGcvLDzKaWj SOIjHwSGuIjnqclcJwqJh|11|21-528-245-9647|6066.94|MACHINERY|ans? furiously ironic foxes hinder blithely pending, pending deposits. blith +6552|Customer#000006552|Nf6QCAunWDenuiZJmxzANjkcjzjl|20|30-889-967-1134|6162.01|AUTOMOBILE|. furiously express foxes according to the slyly idle accounts mold ruthlessly slyly slow packages. special, p +6553|Customer#000006553| ocLpu754,ol|16|26-166-724-4677|8985.90|HOUSEHOLD|refully regular courts. requests sleep: special, final accounts sle +6554|Customer#000006554|A9l1P,V5p9431yso381EbxGEBIrjzbQqe4 Hn|8|18-845-570-6654|5037.71|AUTOMOBILE|e along the warhorses. fluffily fina +6555|Customer#000006555|UMegOBlfpGA0IaM|21|31-923-419-2629|-120.55|AUTOMOBILE|alongside of the furiously special +6556|Customer#000006556|p8DBE,GLPulEItM,G,YMkdQ|10|20-224-737-2850|6794.45|AUTOMOBILE|lites. blithely special accounts use furiously deposits. blithely regular accounts use evenly pending accounts. +6557|Customer#000006557|wUknF8m7MjQL,,6nUI1gB LWN|0|10-666-886-5603|1405.40|MACHINERY|even attainments are carefully pending asymptotes. special deposits could have +6558|Customer#000006558|Kzbfegyh P0YRTxW9aCqgoNrx3jYa8j6j|13|23-111-200-2537|1525.10|MACHINERY|ages after the slyly regular r +6559|Customer#000006559|j4vrCbCwWy4ZdMUF, bHX58wklRdI0|0|10-180-831-4219|314.77|FURNITURE|ts. carefully bold packages cajole permanently besides the quickly final foxes. bol +6560|Customer#000006560|nicoCxzD22IH|3|13-393-157-4401|8302.04|AUTOMOBILE|silent deposits sleep quickly. platelets sleep furiously furiously bold ideas. carefully unusua +6561|Customer#000006561|U B1notuUA|24|34-800-483-7728|6486.47|BUILDING|nstructions. regular packages haggle against the bold packages. deposits cajole. blithely unusual pinto beans +6562|Customer#000006562|6XINODN,YblT3W5FrWSo2voo7MeU5kv8hTni|14|24-485-841-2292|6057.40|BUILDING|s accounts. regular, ironic theodolites haggle +6563|Customer#000006563|ckpsWGe2Xt2QnI05rzcbreoFdTEK,OwotWDbccxm|11|21-535-565-6266|-250.80|BUILDING|bold deposits after the ironic, regular asymptotes are regular dolphins. quickly regular requests are bra +6564|Customer#000006564|pqkVXBhs6SV,fGXfelR1l29,yit1uOZ|13|23-518-531-7793|6761.96|MACHINERY|can cajole blithely even foxes. dogged instructions wake after the bold requests. furiously regular pin +6565|Customer#000006565|hqYF09xT hXv3RHhuSgCCfHnZr7Sz, 2Zuy5XfRN|22|32-398-565-3295|5309.19|AUTOMOBILE|furiously express deposits. furiously even asymptotes cajole quickly. final dependencies sleep slyly. +6566|Customer#000006566|i9Aw4WrBV7UKH3JXXjsdz5 W5UKD1t,pSOo0v7r|11|21-404-346-3746|8548.38|FURNITURE|ages haggle furiously regular p +6567|Customer#000006567|R8iEyHwfq7JefvXy7woKlcnqbVN 0TYcPZu|5|15-714-627-6738|-379.87|FURNITURE|l ideas nag furiously bold hockey players. furiously unusual requests brea +6568|Customer#000006568|7KgPG F0nEcyBKpQJqL|22|32-338-335-4860|4514.95|FURNITURE|ly. regular, silent dependencies affix about the idly special excuses. co +6569|Customer#000006569|67iACh32SK|1|11-178-911-3792|2712.91|MACHINERY|al dependencies wake blithely against the ironic pinto beans. final +6570|Customer#000006570|Xvm7kfDpAmTyhISPbrqibCUopcCq1qqNCOE1pzlO|0|10-475-471-1307|9873.25|AUTOMOBILE|wake bravely against the blithely express theodolites. furiously silent deposits a +6571|Customer#000006571|fj4IX5Zk4vvfUuEIC|14|24-892-309-1142|2767.45|FURNITURE| pending accounts sleep above the blithely regul +6572|Customer#000006572|ar ADMGk0y2|19|29-771-561-9164|2540.69|MACHINERY|telets use blithely accounts. pending platelets integrate fur +6573|Customer#000006573|N58H8Hoy0XD216MOSnWysRXUlIsVqAUR6GZ1LTlF|18|28-312-121-4734|8367.22|FURNITURE|lyly slyly pending foxes. blithely final requests cajole slyly after the even, pending deposits. slyly i +6574|Customer#000006574|nzW785SZCqoQLHUqxecq,xzU0EyIxa,bwZ|17|27-392-453-6805|1972.26|AUTOMOBILE|ts above the carefully ironic packages cajole alongside of the sile +6575|Customer#000006575|GARTfwst7rRbB5|22|32-486-660-6159|2769.78|MACHINERY|uriously ironic accounts haggle blithely. ironic pinto beans use carefully furiously final multipliers. fl +6576|Customer#000006576|cWpLaNr2DIuZanI3i|12|22-167-100-5796|8636.08|HOUSEHOLD|ual packages. ironic, special deposits thrash slyl +6577|Customer#000006577|uEQPgw rPzHldPtHfUqU1r4K5|20|30-983-783-3040|-395.07|HOUSEHOLD|egular packages. furiously ironic fo +6578|Customer#000006578| 5L06W67,Mw8G|2|12-946-562-5905|1973.65|AUTOMOBILE| silent accounts haggle blithely blithe ideas. carefully special request +6579|Customer#000006579|tpu9XN6JdsLCO6nnqauXv3|21|31-593-816-5830|4037.08|FURNITURE|about the blithely silent foxes need to sleep ironic, fin +6580|Customer#000006580|AaTSoiFwZUkdYNegqMCCs|6|16-285-854-7551|1193.35|HOUSEHOLD| sleep requests. slyly even asymptotes sleep; sentiments affix according to the waters! final, final fra +6581|Customer#000006581|m7AxxAwDpU173tVX8AryB4bRTv|0|10-473-250-2099|1624.68|FURNITURE|l, special requests after the quickly regular requests are fluffily pending id +6582|Customer#000006582|roC81vpXtYqj6w2ofenW|3|13-543-506-5912|1920.90|BUILDING|st the slyly regular foxes. even +6583|Customer#000006583|xm9DySSRKsU04Oru|15|25-719-747-8483|8469.57|HOUSEHOLD|thely dependencies: quickly ironic tithes wake fluffily special, special requests. regular, spec +6584|Customer#000006584|KVHnlcQNk3RAGL9llr|7|17-892-368-3465|6059.87|MACHINERY|lyly special theodolites cajole fluffily even requests. even pinto beans among the iro +6585|Customer#000006585|FSuVskGB021iRHHJpNyQiBYx2S2eS R1g9|24|34-421-647-5744|8304.87|HOUSEHOLD|ronic packages haggle blithely packages. unusual excuses sleep busily. slyly careful dep +6586|Customer#000006586|rmyIMRGGnIp84hB9APjbpN3l2J4 lDcogPRb|13|23-442-685-1204|9955.66|HOUSEHOLD|oss the slyly regular requests. furiously even requests believe. quickly ex +6587|Customer#000006587|U2vx2k5HvCCh MNEYbIRD3BwkR|17|27-495-708-8832|1888.45|MACHINERY|the ironic, unusual accounts +6588|Customer#000006588|q4ECgmz0iqJlZeKE0U|1|11-899-895-2340|2153.86|FURNITURE|ans. even instructions wake at the slyly even packag +6589|Customer#000006589|OPaay XGwsQ5FPbgRupMO5|2|12-462-422-9223|7820.61|HOUSEHOLD|e ironic pinto beans should boost ironically furiously ironic asymptotes. blithely regular accounts despite the furi +6590|Customer#000006590|aMW6NjpCUVPZxoLFEQ3V75cZ5eVfmeGc|14|24-797-771-6036|106.60|BUILDING|y final requests are. foxes mold carefully regular depos +6591|Customer#000006591|5f8amVgHTYIC9LNg,oJ2358|10|20-937-427-5966|7511.62|FURNITURE|lly ironic deposits integrate regular ideas. packages are quickly. fu +6592|Customer#000006592|ICcURs4cxBOwwDlSm1N0Q3o2gBIhX|21|31-112-360-4445|9860.40|FURNITURE|cuses. furiously bold requests wake above the furiously unusual dinos. ironi +6593|Customer#000006593|bXigSMqStoMDk4bZGp7sSpBFr,KfbgZzZkU6x|19|29-550-277-9067|6893.52|MACHINERY|ake among the fluffily ironic foxes. dependencies sleep orbits +6594|Customer#000006594|2cDc15tGdriYteAK75|18|28-438-658-3673|5410.27|HOUSEHOLD|fully ruthless accounts sleep across the slow instructio +6595|Customer#000006595|uVa27rCZ,a|19|29-292-466-2278|2348.08|FURNITURE|s among the unusual forges integr +6596|Customer#000006596|v05Csj41kqY8c Z|3|13-153-530-7399|5083.03|AUTOMOBILE|ronic decoys. slyly special packages above the slyly regular deposits cajole past the regular, final platelets. +6597|Customer#000006597|xan0fBW83D27pugrU|2|12-820-261-1596|2468.03|BUILDING|y unusual packages. blithely express deposits run slyly. si +6598|Customer#000006598|gbSYPPXD xhYTY|13|23-340-258-3248|8171.34|HOUSEHOLD| blithely final braids; furiously express ideas cajole c +6599|Customer#000006599|zZJjOj,Fl38qicLtaaRFZmXBPrsOPu6K|0|10-297-776-2902|9848.52|HOUSEHOLD|sly ironic ideas sleep fluffily regular instructions. special, pending pinto b +6600|Customer#000006600|m3pLs7ZW2DQGLirHs2KrrsVG|3|13-922-914-9708|5090.20|HOUSEHOLD|ut the furiously ironic realms hang furiously final packages. slyly unusual instructions nod furiously furiously i +6601|Customer#000006601|8CksnofGDe3,eOr yd G1NJvNV8g|3|13-158-904-5841|1921.72|HOUSEHOLD|y against the slyly bold deposits. carefully regular sauternes above the furiously silent deposits +6602|Customer#000006602|xYS0xzAVCHivnaBFSkuHzezVfozYTop|3|13-468-842-3174|252.68|BUILDING|structions. instructions sleep blith +6603|Customer#000006603|G0VkNa06eg5whaAH6XUH|17|27-100-185-6322|9705.48|MACHINERY|ronic, idle foxes. bold, pending warhorses are: dependencies use boldly ironic requests. quickl +6604|Customer#000006604|kmwPS7a1rYHG3d2KI12OKOegpaHNwQitCvRbb|5|15-116-310-7342|-850.55|HOUSEHOLD| use above the final asymptotes. ironic, ironic instructio +6605|Customer#000006605|bJpsYu5HBIgwd3bPpcfTMme|5|15-797-674-4556|2748.15|BUILDING|o beans are after the packages. even pinto beans boost according to the final excuses. fluffil +6606|Customer#000006606|veGv5 O g1eNuMCQ8lbO0X0|18|28-322-896-9125|8130.69|FURNITURE|y special asymptotes. even, even requests above the enticing +6607|Customer#000006607|pm9R99glhFCWZzIEllz428 TqMQQmX|17|27-924-798-8911|8585.44|BUILDING|regular deposits. foxes are blithely carefull +6608|Customer#000006608|WZYAo7ClTq8j|1|11-275-467-1847|6611.72|FURNITURE|s pinto beans. furiously regular platelets according to the furiously regular hockey players slee +6609|Customer#000006609|9XLzC3FZ8xeSgZX2PiZ2JTpZP7uW,KsvvqY|15|25-264-475-4079|-773.01|HOUSEHOLD|theodolites nag quickly idly ironic accounts. ironically even foxes are. blithely ironic platelets c +6610|Customer#000006610| QFFI2olnw1MmJfAqwsm0iw4oNDjU6kITjOa53h|8|18-120-297-4174|7884.20|HOUSEHOLD|ently even packages sleep furiously. carefully even theodolites haggle quickly exc +6611|Customer#000006611|aQKv,MgJ9FK3NjvADMZ3rhl|3|13-452-843-5081|1801.07|HOUSEHOLD|carefully thin, express requests. carefully re +6612|Customer#000006612|gnqac7Ybh2kSoqKa3ASVAHvypm|17|27-106-926-4405|7620.71|AUTOMOBILE|ld asymptotes. carefully final requests haggle fluffily regular, regular platelets +6613|Customer#000006613|zPS5aK 66ca8nD|4|14-453-488-2934|6296.69|AUTOMOBILE|unts. ironic, even instructions cajole blithely a +6614|Customer#000006614|ICoJpB8v3 QU8AfZ|11|21-180-351-9946|6559.73|MACHINERY|eep blithely slyly pending platelets. ironic, express ideas cajole according to the regular ideas. slyly r +6615|Customer#000006615|GkKngc3qcaXlUc0oUGBVh,Ah|22|32-821-576-6664|5407.17|HOUSEHOLD|kindle. always regular accounts thrash furiously ab +6616|Customer#000006616|8ssRl7vqBcxVrQWh xQdt5U1zX34R5ga Txw,|11|21-804-310-8614|5341.58|HOUSEHOLD| silent packages ought to use +6617|Customer#000006617|gkz18C,mxfkSot1U zHcc8E|18|28-955-200-3871|3008.53|MACHINERY|ainst the blithely regular deposits boost carefully carefully unusual ideas. quickly u +6618|Customer#000006618|jUw3FhXzO0qfzz zXxWOhKwfmI3r|11|21-610-354-6624|6411.46|HOUSEHOLD|nal requests affix quickly pending packages. close pint +6619|Customer#000006619|clyImCIDigUVv1edDwAG34tr7MWfI|20|30-409-954-6902|-549.38|AUTOMOBILE|hely final instructions nag; carefully bold accounts maintain after the even requests. carefully unusual saut +6620|Customer#000006620|,paCQ5qIt,Ylr,iREwAefW8ys5k|13|23-766-421-3496|4441.83|FURNITURE| ironic accounts doze carefully according to the blithely regular deposits. slyly silent reques +6621|Customer#000006621|EuR3TpdBnWKm6OMxOW9yAuiT|8|18-801-593-9685|5852.43|MACHINERY|ymptotes sleep quickly regular platelets. furiously ironic fox +6622|Customer#000006622|fidCV6mKheF|16|26-334-959-1721|8847.45|MACHINERY|wake regularly final instructions. deposits are slyly. furiously pending pinto beans boost. care +6623|Customer#000006623|Xjw9Hy5h4Pgb3zcUEWm8|24|34-304-460-3284|-872.31|BUILDING|g the slyly final foxes. even, pending requests boost about the requests. r +6624|Customer#000006624|5VX6OjpQ Bro52jdZej8FlK0OFFtf7R3ESIJPK|1|11-660-742-2374|-7.37|BUILDING|inder blithely? regular platelets about the packages believe instructions. regular fox +6625|Customer#000006625|R3hdYck8WB F4No|0|10-367-922-8280|6076.36|HOUSEHOLD|ly regular requests cajole; blithely pending instructions haggle al +6626|Customer#000006626|ZdfCZEerdNphvEz5|8|18-208-761-1975|-595.84|HOUSEHOLD|have to doze permanent pinto beans. special requests sleep across the furio +6627|Customer#000006627| lMYWGolCqdPZwftuYfusc7pMOGgLUZdrI|6|16-598-408-8591|4678.15|FURNITURE|ckages. ironic pinto beans use carefully-- carefully eve +6628|Customer#000006628|xP MMDAoXhUc,s8N|9|19-364-386-8197|6607.71|HOUSEHOLD|s are. furiously express platelets boost. regular, regular accounts cajole. depo +6629|Customer#000006629|aLIf6koYS8OSSnvRGqhRFqIRnX|6|16-310-265-2013|8761.81|AUTOMOBILE|onic deposits hang slyly enticing packages: slyly regular courts was blithel +6630|Customer#000006630|mrADj6gHX6kvN8H9hV2TTZD|10|20-993-605-4157|844.42|FURNITURE|across the blithely special excuses. express accounts are about the packages. ironic re +6631|Customer#000006631|7iOXTPto,B5|12|22-688-971-9796|89.69|BUILDING|the ironic deposits serve slyly slow, regu +6632|Customer#000006632|WFDE,gGvSeFejvfMg|2|12-979-552-7277|9324.80|MACHINERY|onic theodolites haggle carefully carefully pending excuses! packages boost against the furiously ironic p +6633|Customer#000006633|MXIkYoyLJbpxhc|4|14-157-941-2531|2911.60|FURNITURE|deposits cajole even instructions! slyly final requests integrate enticingly furiously special +6634|Customer#000006634|v40njkdojYnRdVGwAW|5|15-916-327-8851|5261.30|BUILDING|lar instructions. accounts haggle permanently according to th +6635|Customer#000006635|dPKoh,uNPUKABQlR,WDK3pTzCp|24|34-785-680-5961|6618.78|AUTOMOBILE|packages sleep. slyly silent deposits x-ray furiously deposits: bold, e +6636|Customer#000006636|0yf ,8IEF6Ym5JFeZb1HfyYJG CDxU|24|34-625-369-8340|7912.37|BUILDING|ously ironic ideas integrate furiously ironic instructions. careful +6637|Customer#000006637|5RhMx2tf5k8u|13|23-455-236-7135|2317.68|BUILDING|e blithely. furiously even dependencies integrate slyly. car +6638|Customer#000006638|Mm2JAYCCHstTE|16|26-315-337-6748|191.55|FURNITURE|s packages sleep quickly. final ideas boost carefully +6639|Customer#000006639|auyhpm1qOcoflRfR4S35,7nPTFyM ZG04eGAMb,U|13|23-364-243-5030|5269.15|FURNITURE|urts cajole bold, even requests. furiously ironic exc +6640|Customer#000006640|LraQsOeV6d|7|17-233-212-8020|6693.51|AUTOMOBILE|ate after the special packages. carefully regular excuses are quickly quickly even decoys. ironic foxes detect bo +6641|Customer#000006641|gw3LD4q9DzXioZ37chuNxB2|8|18-212-860-9043|9799.19|BUILDING|e furiously according to the theodolites. carefully bold ideas wake fina +6642|Customer#000006642|LoE,WKpwd79h4TGVAJDgTYwzSwDmBfd|2|12-278-337-5916|1026.55|HOUSEHOLD|s. slyly bold excuses play above the furiously ironic requests. furiousl +6643|Customer#000006643|Iuv NTvS6dJ2io6Q76FiZeJI|23|33-173-903-7175|3109.73|HOUSEHOLD|are carefully blithe accounts. carefully unusual pi +6644|Customer#000006644|mf2MRu7b37tyk|21|31-369-661-7739|2257.43|AUTOMOBILE|bout the unusual requests. special, unusual epitaphs haggle furiously final deposits: even requests agains +6645|Customer#000006645|9wuMUJea1LYIsA0MDzoFxKARmIJvMpI|22|32-339-429-1573|-347.93|BUILDING|according to the permanently special packages. pen +6646|Customer#000006646|GioIRa7f673rsFRHt2e|9|19-556-383-9646|2206.85|MACHINERY| furiously special packages haggle busily. s +6647|Customer#000006647|gLBSZ8P6yXMpyGwCirn9HfN,|6|16-349-915-4350|7515.71|AUTOMOBILE|ncies are against the furiously express instructions. deposits above the bold theodolit +6648|Customer#000006648|0HJ,ghgxYfPYPC eCh6nDUgWLalajrwBRY4p|0|10-142-681-9531|1611.85|AUTOMOBILE|y unusual packages. express ideas sleep furiously along the final frets. furiousl +6649|Customer#000006649|q7et5s1SAXMlokVdGW3ZYueHV|20|30-484-404-2575|6300.33|BUILDING|nts. packages integrate blithely around t +6650|Customer#000006650|NxtKIJDfOaBn|16|26-568-235-1339|1611.97|FURNITURE|pite the ironic packages. silent requests across the regular theodolites solve care +6651|Customer#000006651|cAtLrZCfDjtH5vIpaqg,qBs6J|9|19-396-649-7221|8251.81|AUTOMOBILE|al, final pearls wake furiously regular grouches. packages wake bl +6652|Customer#000006652|4mz9d8cQw7Hh,KZYOWhHrH5NpLkhQL|14|24-741-346-4893|9296.36|FURNITURE| above the regular, unusual dependencies. final pinto beans dazzle fluffily. pending +6653|Customer#000006653|4Q4ARPm8n2f|10|20-532-650-2293|8927.69|MACHINERY|riously final packages integrate. ironic, thin accounts cajole among the carefully pending +6654|Customer#000006654|AHYF0lz1LiG,wC1WMH9L9pCe3PdUaO4Q|7|17-933-462-3572|5789.45|MACHINERY|s. blithely regular accounts engage slowly carefully final se +6655|Customer#000006655|FgGQl7KxO2rmmwE0rndJ|24|34-277-845-9539|6372.81|AUTOMOBILE|ermanently regular packages do are carefully express requests. pending accounts sleep. pac +6656|Customer#000006656|jgLvAdS6UQcyaUCSb|17|27-416-436-5518|9824.64|FURNITURE|eas serve furiously pending theodolites. f +6657|Customer#000006657|fDo1gqlFFrkkqjwSb9 9RD7DNbuPI59zt|3|13-538-227-3972|-146.22|BUILDING|ly. blithely stealthy asymptotes alongside of the fu +6658|Customer#000006658|qOYY,NL6MESHOBu1r8jx|21|31-302-918-2979|4384.07|MACHINERY|riously blithe accounts cajole slyly ideas +6659|Customer#000006659|WKPkuTEjDJc|10|20-393-281-4388|3053.98|BUILDING|around the blithely express dependencies. careful +6660|Customer#000006660|Mhf8lV21 BapxeXn9lz9k7b6tBd|23|33-164-539-3410|188.29|BUILDING|s. quickly close requests are quickly. asymptotes are against the carefully slow requests. pending foxes caj +6661|Customer#000006661|bB6EP7Tf3mVskZJ7tLHKQSGDifygpVm2|16|26-168-633-7265|5529.99|AUTOMOBILE|t requests nag. blithely regular courts wake quickly. thinly regular deposits according +6662|Customer#000006662|oZ6a dkzIqrldlL|10|20-378-737-1289|1621.83|AUTOMOBILE|tes use pending, ironic dependencies. even, ironic dependencies boost according to the deposits. regular +6663|Customer#000006663|tFHYxL YrhKpX|13|23-250-528-2581|9077.11|AUTOMOBILE|ckages after the pending, regular dolphins use quickly +6664|Customer#000006664|580X3yq552pkRg5sQwDbltI6XxFJb6c6rb|24|34-426-291-1081|9108.44|BUILDING|unusual dependencies sleep quickly accounts. ironic ideas sleep along the carefully bold accounts: furiousl +6665|Customer#000006665|,Y,EsUyItpokyz9XVi9jf3L7JuOwrQjNE3c1Mlij|0|10-163-117-8909|7628.89|FURNITURE|ickly regular theodolites use blithely among t +6666|Customer#000006666|9zJqKbGbRjPS|18|28-557-833-2670|792.26|AUTOMOBILE|lithely regular requests after t +6667|Customer#000006667|SXoMfAHkfO4b44Yr1Qz|19|29-738-728-6617|3385.51|MACHINERY|ual accounts. final excuses cajole car +6668|Customer#000006668|t,qsLMTcPSMSc I3,7LYW W0EwfqtOu,pmLc,|5|15-364-427-1235|6319.59|FURNITURE|unts boost. final deposits serve furiously according to the carefully regular accounts. b +6669|Customer#000006669|lT6gKsLMZJaBBXCtnGWroOoUkdbqwFyjMU Q|9|19-723-887-5480|6311.20|AUTOMOBILE|carefully even instructions haggle furiously. c +6670|Customer#000006670|naiDNB2uULTBT,321CFY9HYG0jFelpYg|16|26-694-136-5425|8297.83|HOUSEHOLD|gular pinto beans solve quickly carefully bold accounts. express pinto beans promise slyly acr +6671|Customer#000006671|WaqMrlZBfcDiT3n5KvOWt14jgw1m5ZARzqI85fY|18|28-145-184-9679|1603.96|MACHINERY|ans run fluffily blithely unusual dependencies. bold, ironic packages above the quickly pending foxes believe caref +6672|Customer#000006672|TAk1jzQy60fSpBRSLShvpTZae1797Bdve|10|20-897-841-4188|5700.11|AUTOMOBILE|unusual sheaves haggle quickly according to the carefully final som +6673|Customer#000006673|heXKQ2V3L0uxVhdWxCvr42|23|33-166-738-4873|751.90|MACHINERY|packages sleep fluffily final grouches? fur +6674|Customer#000006674|WfEiHyBjekCdDYT2Gbb0infBTvADc27M9R3 BWZ|9|19-629-336-3947|7179.20|BUILDING|y even deposits. accounts cajole furiously about th +6675|Customer#000006675|HAnz4SbD7 1s,9fqBkN8A4L,m8UZ|5|15-317-619-9609|-226.28|MACHINERY|ess accounts. even packages above the quickly regular requests mold a +6676|Customer#000006676|VtWsbzZD4qe8Z T02uSPbSuKiz|10|20-569-115-2865|816.03|FURNITURE|he ironic, bold courts are ac +6677|Customer#000006677|Wh55,5rAIfHnBZbN|0|10-283-641-1486|7035.29|BUILDING|ns cajole furiously beneath the carefully ironic waters. regular requests are according to the furi +6678|Customer#000006678|QDpY,eRLnl5,HsjFuCEmufwZadvV4|3|13-605-424-6382|1201.45|MACHINERY|warthogs. blithely ironic asymptotes +6679|Customer#000006679|VqLS2XSCc0GFgWN5 Ol|19|29-169-326-9045|5642.93|MACHINERY|, even deposits use fluffily regular pi +6680|Customer#000006680|8TEDCB7fdAUhgYRUU7ZfV1Ld3mB00gDQhtNB,oS|17|27-962-923-6320|7673.78|BUILDING|s cajole. fluffily express ideas wake furiously about the ironic +6681|Customer#000006681|th39LRNpVorKObh7TB|6|16-926-344-3556|7321.37|AUTOMOBILE|egrate furiously. slyly ironi +6682|Customer#000006682|47B7Wsx8E7991Y2|19|29-904-610-3132|2230.59|AUTOMOBILE|bout the boldly final requests. slyly special ideas h +6683|Customer#000006683|snrDJsmCFVQ4O3dveQpw5JIDvmtsZXdRtzNmP4O,|10|20-812-694-7415|-549.56|HOUSEHOLD|gular accounts. fluffily express +6684|Customer#000006684|qdqKwrzOb2|5|15-109-442-3321|1412.15|HOUSEHOLD|ily express excuses wake blithely. carefully bold packages sleep above the even, regular pinto beans. +6685|Customer#000006685|BkWlHQusdN1kzNDHvqnOV1SJ9|17|27-406-584-3296|4996.19|BUILDING|ly regular foxes boost blithely bold foxes. e +6686|Customer#000006686|DvvWufVBbpdB3nSVazM7|4|14-799-782-6111|5959.97|HOUSEHOLD|y unusual deposits play final requests. ironi +6687|Customer#000006687|Q0K48 G0mj|17|27-869-237-1381|1157.82|FURNITURE|ress asymptotes. quickly regular deposits haggle. final, close packages snooze fluffily according +6688|Customer#000006688|h61o1Amg8a2wnZYMAqd5gJM16PPB|15|25-369-725-3205|9401.81|AUTOMOBILE|fully regular platelets. ironic ideas hagg +6689|Customer#000006689|x5j,b7K9Irw9KnJmeCur|23|33-787-189-8082|-652.17|MACHINERY|blithely regular packages across the packages poach across the bold platelets. even accounts nag furiously against t +6690|Customer#000006690|B1nB5mFxDsSJQvm5lxn3nkyMl|16|26-671-890-1848|3868.69|FURNITURE|eas try to are fluffily. pending, t +6691|Customer#000006691|NvkXKfvzF9oErd6MzanMySOlVPNUCQ7tcV|5|15-503-903-6718|8999.87|FURNITURE|luffily. unusual dinos doubt slyly. accounts sleep fluffily after +6692|Customer#000006692|HkPGTwsyUV|9|19-145-218-4626|8817.45|AUTOMOBILE|boost permanently final, regular deposits. blithe, ironic requests sleep furiously express dep +6693|Customer#000006693|Bd7U3RV0lbRer WQY|24|34-882-944-4437|925.49|HOUSEHOLD|silent deposits. special foxes nag sometimes permanent, bold deposits. carefully special pinto beans sleep fluffily +6694|Customer#000006694|XyOYqBJqGspMZSdqQq5DvaX9CD|4|14-959-393-1619|9588.19|HOUSEHOLD| against the slyly ironic deposits cajole blithely even pinto beans. final +6695|Customer#000006695|XGxqrdbm4jLBmrqTRmd5dLwIR|18|28-628-769-5605|7779.06|BUILDING|y even dolphins. requests wake. fluffily express asymptotes sleep. slyly final acc +6696|Customer#000006696|xhoBDOYsLR89|21|31-975-638-1125|5667.73|MACHINERY|es. slyly regular accounts integrate! fluffily ruthless accounts wake furiously! quiet accounts +6697|Customer#000006697|0NTbi10hHKSxo|24|34-307-871-2967|6632.75|HOUSEHOLD|re carefully quickly final asymptotes. blithely pending packages cajole quickly along th +6698|Customer#000006698|0QyCW1acGdoAo59FdWV 3pZ|19|29-862-853-4688|620.84|MACHINERY|ges wake blithely. quickly pending braids sleep furiously: carefully regular pinto beans mold after th +6699|Customer#000006699|jGDulmO0cw9lFBN1jlR64OLiBqCJc|2|12-708-798-7379|4317.54|BUILDING|unts-- carefully regular instructions maintain s +6700|Customer#000006700|KUpYErT7tXcOM04gpSlDW4566SCbvBT dA6l|8|18-304-498-5307|6932.01|FURNITURE|structions. blithely final ideas affix. blithely unusual requests haggle slyly fluffily even instructions +6701|Customer#000006701|CVKLM V7ST0Nx,jr0e0gHcduEj5|9|19-659-528-9243|3257.42|AUTOMOBILE|lly final foxes. ironic requests boost carefully du +6702|Customer#000006702|Wi DrmUzjVKPCSBNG6Wok7io9QxVX7kN7Jd|7|17-216-230-3435|9392.14|AUTOMOBILE|t slyly according to the furiously fluffy theodolites. carefully regular requests are carefully int +6703|Customer#000006703|03PTXkGYGGxCThBmmgGy|21|31-804-154-5053|1836.91|BUILDING|. unusual asymptotes cajole carefully against the ironic packages. +6704|Customer#000006704|B1B1Ms3HDpnvU8cDBoMP3T4PkW,mHSWd|19|29-206-376-9599|4862.96|MACHINERY|rmanently even ideas haggle carefully. carefully unusual courts according to the c +6705|Customer#000006705|aDX0WTflMQRyU2JMFFlW|3|13-434-897-7312|-159.03|BUILDING| foxes. furiously silent pinto beans integrate slyly across the grouches. slyly special pinto beans in +6706|Customer#000006706|TBcc48ZL2vZv7afiGoSEhjbM|3|13-134-428-9567|9100.37|AUTOMOBILE| special, even requests are fluffily-- regular accounts a +6707|Customer#000006707|o6Nm3V8 Zj2tt4j3sMiTJ4|6|16-466-364-3185|3977.38|FURNITURE|uriously against the regular, ironic requests. regular packages wake never. quietly pending instructions believe. +6708|Customer#000006708|mUhDV6NCOCJghkAjEX0Jo|12|22-281-780-5651|9900.11|BUILDING|ly. ironic accounts wake carefully at the final pinto beans. slyly regular requests slee +6709|Customer#000006709|BXNfIHT5cfG6DtLlBKePFXUQbBeB4|8|18-207-447-8319|3199.11|BUILDING|ronic, even requests. slyly unusual realms sleep carefully. ironic asymptote +6710|Customer#000006710|CeyxEnNCzAuXmAId1vHI4kN5YuwNvV0rH8NhYz99|12|22-412-672-8270|8494.05|HOUSEHOLD|usly even requests. accounts boost after the bold deposits. slyl +6711|Customer#000006711|z9trQmIO3Y5z60O5ozSv877GQILvo|13|23-886-250-5460|-361.61|AUTOMOBILE|ounts! thinly even theodolites cajole furiousl +6712|Customer#000006712|T QGDjZA2gcd92poV ,1rQrRu9ZB7EzZ|17|27-884-283-7355|3268.82|FURNITURE|ke blithely bold deposits. final requests sleep furiously? blithely specia +6713|Customer#000006713|ynNA7HFYdk0KjYuVxo9R9NK8qw8lXJxDFhA|9|19-945-198-9475|3006.93|FURNITURE|gular asymptotes nag. sometimes final accounts integrate blithely blithely ironic ideas. caref +6714|Customer#000006714|m8zfcfvyi7w PulZPp,g|21|31-407-424-6606|1494.63|MACHINERY| blithely over the furiously regular +6715|Customer#000006715|wEEcGy ed7V nIyY|8|18-303-744-7177|5244.28|BUILDING|ep slyly-- fluffily regular pinto beans use silent accounts: sometimes regular foxes are along the regular, regular +6716|Customer#000006716|qBJ6Dx1ASZOZLrQ7FTreiGRWX|4|14-339-999-9145|6593.08|MACHINERY|ons. blithely bold instructions instead of the blithely even dependencies haggle according t +6717|Customer#000006717|A3TpI60MfBQNedRV 3DcYhf3GUWL|23|33-731-150-6538|4844.87|HOUSEHOLD|ependencies wake except the reques +6718|Customer#000006718|8m61NcNrEZzFo,NmKaBzQXjeX Va|12|22-820-610-1027|3658.95|BUILDING|ely. notornis try to nag. blithely pending package +6719|Customer#000006719|,SJoHSlIYiQZ3ebJw SpwZ8lg|7|17-221-621-5826|3965.07|BUILDING|ronic warthogs after the fluff +6720|Customer#000006720|luGQxDrBGnnftUVgjF|6|16-457-628-5807|843.36|FURNITURE|odolites cajole. ironic packages haggle regular instructions. slyly special +6721|Customer#000006721|OkHnnK98UeBILbX2bjAPwvOdKMBidiW|4|14-701-354-8135|4277.74|AUTOMOBILE|l requests are. furiously quick dependencies cajole. deposits cajole blithely after th +6722|Customer#000006722|1jnPUXu2iBwB7|1|11-451-400-5785|8919.68|MACHINERY|ronic asymptotes use. furiously pending packages boost furiously-- slyly regular deposits wake +6723|Customer#000006723|gAfgW13,GB|20|30-582-567-3761|3070.48|FURNITURE|sts. tithes wake quickly. carefully regular theodolites integrate. carefully final asymptotes +6724|Customer#000006724|bcpvOK,8gUO1|12|22-598-908-4189|2471.21|AUTOMOBILE|s. slyly final pains wake carefully. express, ironic deposits among the furiously final dinos ar +6725|Customer#000006725|if8lplIxBWNs6u2fgJKJLKDrRlfhEjwQcJVooOH|7|17-685-688-6979|6523.60|FURNITURE|n accounts poach silently after the regular +6726|Customer#000006726|hssVbd6,2x8YN7nJDem092|6|16-514-909-5495|3108.77|MACHINERY|es against the carefully regular courts are quickly furiously even th +6727|Customer#000006727|APG0BfGWOYnDkXgbcKdhJXzzJgLtQXYKCoXMPxJA|23|33-373-151-6436|7993.12|BUILDING|riously close foxes. fluffily final accounts haggle quickly across the accounts. bold theodolites engage furiously a +6728|Customer#000006728|v9cVptqbc0tKb9ZT q|8|18-216-645-1385|6449.93|MACHINERY|about the bravely even ideas are carefully ironic accounts. thinly even dependencies haggle +6729|Customer#000006729| NrrDioTuXtkJCh|13|23-575-217-4725|8051.37|AUTOMOBILE| furiously. quickly regular packages above the reg +6730|Customer#000006730|EmtyBtMxazeTZFx1zqBuNju5VmzsqOi930BE|11|21-223-976-8367|6413.26|MACHINERY| carefully final accounts. closely final deposits integrate carefully according to the dogged, regular ideas; platel +6731|Customer#000006731|HpEXXgDmsqIPyVb FXeWbadti|2|12-283-284-3677|7639.55|MACHINERY| foxes. carefully final asymptotes print excuses. furiously ironic waters engage. c +6732|Customer#000006732|sHH4w G8QMTtCVTjbkiEHTvL8bRr5Tu|16|26-779-843-5056|4018.93|FURNITURE|ions haggle quickly against the slyly regular accounts-- bli +6733|Customer#000006733|Kik6R2t1WP|11|21-569-230-8251|4219.13|AUTOMOBILE| boldly across the carefully ironic dugouts; slyly bold pinto beans haggle. +6734|Customer#000006734|yRF8my1jIZM1QuEGXxSuXT0P83w ljVko |14|24-157-448-3086|2971.38|FURNITURE|ly final deposits. excuses along the carefully special packages promise regular theodolites. ca +6735|Customer#000006735|eG5Pt6wlZpFUt0140cHxYox3roKuQU,V|9|19-117-148-6129|8904.94|HOUSEHOLD|onic, express packages wake carefully final asy +6736|Customer#000006736|TwL2M9L6iblvaG,93Efw2HP Glnm8jsH4EQP|17|27-421-117-6858|8363.54|AUTOMOBILE|inal dependencies nag. regular theodolites sleep. blithely unusual foxes boost slyly. final packages nag slyl +6737|Customer#000006737|TnIV3SSmxJFDBYUexZHw2w2m3vIAFgv38lwDY7Rb|4|14-372-941-6618|6015.13|FURNITURE|iously ironic theodolites nag slyly according to the even requests! slow, regular platelets doubt. +6738|Customer#000006738|eAylAy5pHWBnUK6q3v2cXNODweF4|3|13-699-399-9154|4394.53|BUILDING|ending accounts. slyly special pin +6739|Customer#000006739|3lsA2Q8pNR|5|15-493-613-7300|2838.35|BUILDING|uests nag furiously according to the quickly even dinos. ironic, bold requests +6740|Customer#000006740|VZIi3wMuEDjnmgAq4YwDGnf5BK e7Fs2|11|21-751-155-2705|6098.86|MACHINERY|lphins affix quickly alongside of the deposits. slyly pending pearls wake regular, regu +6741|Customer#000006741|ogMwwJa0CY9MZsdv7nCQi5HCOAwuE|7|17-567-242-2914|3514.90|BUILDING| are over the foxes. furiously even requests after the closely r +6742|Customer#000006742|u5lVPzNeS1z2TcfehzgZFHXtHyxNJHU|1|11-643-477-4053|2834.80|BUILDING|bold deposits wake. special deposits about the regular excuses boost furiously furiously final packages. slyly r +6743|Customer#000006743|uXzHSYlqjnoKSFFTrUjwPa4g9oIMRp4D,S,cNM|20|30-195-288-9509|1464.96|FURNITURE| unusual accounts wake slyly about the carefully regular packages: carefully pending dol +6744|Customer#000006744|PGmBpCi8fCF9caRqw|9|19-551-917-8841|1605.91|MACHINERY|ly. quickly special accounts dazzle around the ideas. blithely regular requests sleep quickly carefully regular +6745|Customer#000006745|F4AQlOnBqEtwLi85Fm0RzN3ZmaMdl3|18|28-602-954-3388|5454.54|FURNITURE| final pinto beans sleep pending, ironic deposits. busi +6746|Customer#000006746|M0 KJuw4qc9UBliw9 oD42VXakTKG0,6|18|28-204-291-9356|9415.95|MACHINERY|ges. slyly ironic patterns haggle slowly carefully regular requests. quickly regular t +6747|Customer#000006747|3ntn2pmdvucSKFlb|3|13-243-582-8819|5970.51|AUTOMOBILE|round the slyly bold deposits. slyly unusual dolphins boost bli +6748|Customer#000006748|a8b2paF9T94UrLTiSzHSE38ZmxHL|17|27-580-967-4556|2410.88|AUTOMOBILE| furiously ironic deposits haggle across the slyly silent instructions. quietly ironic +6749|Customer#000006749|sU3,BsMtoVz xNJJX1emkZJxZbOIRc|0|10-774-652-4046|4693.71|AUTOMOBILE|ts. unusual accounts are slyly furiously final accounts! ironic, even pains cajole furiously. +6750|Customer#000006750|V7UkwofaAeXZ7 0rXuHekMbN3mXZLK7koxDO66Tl|4|14-457-948-4761|4227.49|HOUSEHOLD|ding dependencies. carefully regular accounts cajole carefully about the ironic deposits. package +6751|Customer#000006751|Tdxt4GKZYz|7|17-895-936-3672|365.42|FURNITURE|ly for the fluffily silent foxes? slow deposits are. packages doze carefully. quickl +6752|Customer#000006752|80HtfjhjeYU|17|27-487-194-4578|1487.49|AUTOMOBILE|regular accounts. pinto beans sleep express foxes. special instructions wake. quickl +6753|Customer#000006753|yNkYKPtxuhgzqBBm7s6|8|18-860-208-5739|6195.82|HOUSEHOLD|s. bold, ironic packages wake c +6754|Customer#000006754|B6i9QUe1MogaHVLxdQy4QnH3nkb UaY0|7|17-897-648-1827|5143.81|BUILDING|ar ideas doze furiously final +6755|Customer#000006755|aJU5CHd5UZzrd80j1|6|16-237-199-3241|964.67|AUTOMOBILE|nic asymptotes. blithely ironic foxes are. blithely ev +6756|Customer#000006756|sRflkvpvQnc6q8wXS|7|17-105-972-5722|8127.58|HOUSEHOLD|ing accounts. unusual theodolites hag +6757|Customer#000006757|Ot2eNxssE43x0Ivhlzy 2|13|23-725-154-2356|227.89|BUILDING|breach blithely; furiously regular deposits according to the quickly regular packages nag slyly fluffily regular p +6758|Customer#000006758|YhRgjpezuIfxnPM3docKnH9Dr6Zs9dlMPmI r5X|18|28-730-164-7975|15.13|HOUSEHOLD|dolites hang carefully. slyly special accounts nod slyly express theodolites. pending depths according to the regula +6759|Customer#000006759|CyomHt7D6FLzXgN5Rff0fo0a |19|29-276-479-4436|-773.12|FURNITURE|ut the slowly final accounts sleep blithely slyly special foxes. quickly final ac +6760|Customer#000006760|ZXjHellHGmKAh|18|28-609-664-1095|6035.85|FURNITURE|. furiously unusual packages sleep quickly. accounts nod sly +6761|Customer#000006761|v1sTMXm97sEpzFo|1|11-894-413-9156|521.65|BUILDING|tructions cajole carefully against the ironic deposits. blithely final asymptotes wake furiously ironic ac +6762|Customer#000006762|Vha,VM8y w5TD0q7|18|28-388-163-7393|9311.76|BUILDING|against the final requests. p +6763|Customer#000006763|laxf,Ybtd4d2FGE9RCG|18|28-654-592-3290|3895.04|AUTOMOBILE|ts. busy pinto beans cajole carefully since the slow accounts. final pinto beans cajo +6764|Customer#000006764|Ehu6TNlFTGdkY|16|26-720-544-9325|921.28|AUTOMOBILE| forges snooze. carefully pending warhorses cajole carefully upon the carefully regular packages. thinly unusu +6765|Customer#000006765|K8S00oGkfyhG7,A08NTyZTfOItXThIZ|14|24-562-459-8122|4816.14|AUTOMOBILE| regular instructions haggle slyly accor +6766|Customer#000006766|KbP0 fFP7iJCWl4E|4|14-369-503-4420|4814.57|FURNITURE|express, final accounts. furiously u +6767|Customer#000006767|yEB,5rAwZ1Vi,u|21|31-217-839-6340|528.35|BUILDING| ironic requests cajole quickly slyly even foxes. fluffily pending accounts are according to the regul +6768|Customer#000006768|h Kgr0xrW9MkORlqUgwFsGgQZG3,Jks|9|19-647-976-4923|979.30|AUTOMOBILE|furiously idle packages are slyly fluffily quiet dinos. quickly even instructions about the regular reque +6769|Customer#000006769|v5TrRZTAAiD4i1eyVTLNA|20|30-186-784-8328|1029.38|AUTOMOBILE| slyly regular packages nag carefully. furiously bold theodolites along the +6770|Customer#000006770|fhS8YZLcFyBIeZSp2|12|22-300-803-6439|6756.19|BUILDING| express ideas sleep slyly ironic dolphins. u +6771|Customer#000006771|MMWc6i48BJhKrgu9ko Io|24|34-589-527-3110|7287.84|BUILDING|iously alongside of the theodolites! even realms above the furiously special orbits are slyly final ideas. car +6772|Customer#000006772|ggL8d6JSSQUkE9zg6F3|10|20-387-573-8593|-238.33|MACHINERY|eas: carefully regular packages about the furiously silent pains +6773|Customer#000006773|WO 4bouYuu |7|17-627-272-8854|7232.34|BUILDING|tes. furiously bold pains wake care +6774|Customer#000006774|tufe2Xi42Fdq6R4hf7drAFRCg3Rz4i|2|12-800-430-6064|1958.28|HOUSEHOLD|ounts. slyly even theodolites sleep slyly accounts. ironic foxes sleep carefully. blithely pend +6775|Customer#000006775|bzDrDnIGQLCgiExwO6VwqlW|15|25-386-188-6886|9781.70|BUILDING|old, ironic pinto beans wake fluffily. even, regu +6776|Customer#000006776|JXoJqh4JpcdvugREShRwNHCee4ltrxrb3OM1,E7l|18|28-994-492-7101|4054.12|BUILDING|hely among the ideas. slyly unu +6777|Customer#000006777|uT2JCbpTRH9Inj0wgbRuv,|16|26-447-185-5798|1597.51|AUTOMOBILE|cajole. slyly express asymptotes sleep above the final, bold realms. slyly special realms boost on the quickly re +6778|Customer#000006778|ACpbkEbCPYy|4|14-172-893-4202|7333.47|MACHINERY|r platelets affix. carefully ironic accounts arou +6779|Customer#000006779|UeGNbDKhSDW1MkcE,GnxRAiyjHHe0itTSj|18|28-974-892-3856|7630.58|MACHINERY|xcuses might sleep slyly silent, final deposits. regular pinto beans integra +6780|Customer#000006780|R20cDLZCvC,XeXxr3JVgS63kH9IYW41ql9|4|14-601-747-4629|7181.83|MACHINERY|blithely even escapades. even deposits are carefully pending accou +6781|Customer#000006781|hjgOEQCNYiCKQTwECBEJ6pMsKqhNJH1oRj|21|31-556-362-4055|-21.79|AUTOMOBILE|packages nag along the quickly express packages. ironic deposits are along the +6782|Customer#000006782|QfjRd7YtTJRio2K70XUp7w,WY3a9xlo,|18|28-152-315-2630|5711.06|MACHINERY|ss realms. blithely even ideas haggle furiously afte +6783|Customer#000006783|VcFpiOQxpgr2Q5w0,d|4|14-418-290-9278|8724.64|MACHINERY|. blithely regular ideas haggle fluffily against the ironic requests. final deposits sleep. even, regu +6784|Customer#000006784|t7bVQGTfY,PwEmIshCKmrWiNMj|10|20-926-379-4893|3026.77|FURNITURE|ful pinto beans nag final, even accounts. requests +6785|Customer#000006785|Zeb0QWx561VbdmAnNJwFX|5|15-334-822-1897|4849.38|FURNITURE|equests. blithely ironic dependencies about the slyly ironic accounts wake furiously iron +6786|Customer#000006786|y JAZymUDAm19ImpwXrDBhrJ2tkCXImzEU84NXe|14|24-639-124-4027|2564.13|MACHINERY| forges: fluffily bold packages boost about the sometimes final excuses. ironic deposit +6787|Customer#000006787|x3R8xwciGpAldSQtfrfQjKPVA5MK|4|14-221-614-7132|6276.35|BUILDING|ularly silent ideas along the regular, even asymptotes boost fluffily bold theodolites. blithely express packages +6788|Customer#000006788|tkzbRySfDjHBZuJU8xa9XXx4EeZ6L EmX|12|22-769-485-6232|5623.43|MACHINERY|ackages. carefully express platelets haggle blithely +6789|Customer#000006789|wQUHbVSc8YanGHPCDbK0,njoByEX7ThcX7|13|23-254-104-3764|-913.53|MACHINERY|yly: carefully ironic asymptotes are furiously; pending do +6790|Customer#000006790|DCD1tDMXhoUIaKhQPnCUVUKxiLdcGsNK|18|28-476-389-8594|222.98|AUTOMOBILE|rave deposits. regular, even instructions us +6791|Customer#000006791|w7qvbNTA3AUnviiYrUHQ3rrvxg|24|34-796-717-7454|5488.16|BUILDING|g the blithely express packages. u +6792|Customer#000006792|1eyzmigbKdS,uPvd,gTfV82Q0s|7|17-399-754-8075|2503.03|AUTOMOBILE|thely ironic pinto beans. accoun +6793|Customer#000006793|6iyy1xAWokEzS7vzwKebMn8uc9rnD|14|24-645-815-1178|2415.53|AUTOMOBILE|ies sleep slyly along the blithely bold deposits. sly +6794|Customer#000006794|eW4D8D nAkkGhhx|21|31-846-103-1877|5798.75|MACHINERY| integrate about the quickly dogged requests. furiously ironic pinto beans haggle above the never final +6795|Customer#000006795|uHQSwrVKQCUmmUjgTjuUo oR65yPIOzNuZ5j|11|21-520-971-6013|8574.87|MACHINERY|counts. pending packages haggle quickly alongside of the pending requests. ironic fo +6796|Customer#000006796|ry4xotfFJkV|21|31-204-934-2930|4956.27|FURNITURE|beans! furiously even deposits doubt fluffily carefully express pinto beans. furiously pending +6797|Customer#000006797|CbAgm9paksZYcQNM|2|12-443-241-4031|6051.25|FURNITURE|s ideas are carefully across the fur +6798|Customer#000006798|DRAvKxwGdh8qBsv6DlFfvsilS7,QuSOQfO4D|21|31-784-264-5102|6312.50|MACHINERY|kly ironic pinto beans. fluffily final escapades beyond the reg +6799|Customer#000006799|OmuxHQ,MFaA6IKDRJpI7rOq0 2|19|29-861-675-1912|8266.46|MACHINERY|tes. slyly permanent foxes sleep against the carefully regular deposits. ironic, ev +6800|Customer#000006800|dyQqJ sBw9RZiggYPODCddm2|24|34-746-736-6270|2438.35|HOUSEHOLD|al accounts sleep carefully accord +6801|Customer#000006801|h4zMf8BMKsgOf964TpkBtFenTIiHb|7|17-563-914-8922|4350.72|AUTOMOBILE| the furiously express accounts. even foxes sleep fluffily ironic ideas? +6802|Customer#000006802|XwZM0 CSn4C Pe|24|34-621-826-1804|3589.51|MACHINERY|nstructions wake quickly along the bold accounts. ironically ironic tithes sleep blithely unusual +6803|Customer#000006803|6xmvFf,9ifUkUXDtls|6|16-508-741-8182|2880.15|MACHINERY|ully slow asymptotes. special pinto beans use after the final ideas. furiously even ideas hinder. qui +6804|Customer#000006804|y3KkEdC7h4oc6BGM8r xsYpi V7ivtz9|16|26-988-381-6875|4647.66|MACHINERY|ccounts sleep slyly among the regular packages. quickly final ideas sleep furiousl +6805|Customer#000006805|kTi3eJA0j3wmK,PDjWGed8tzM|24|34-956-659-4290|147.84|MACHINERY|eep quickly carefully even courts. +6806|Customer#000006806|63GYGgLROgXoSKxwRPVwKdjdTFx|3|13-535-116-9961|7653.27|HOUSEHOLD|press theodolites. blithely pending accounts according to the quickly regular accounts nag alongside of the unusua +6807|Customer#000006807|zfbTyBPugePY1ea3MbBFWuXrhsT|0|10-318-291-1534|3571.22|BUILDING| blithely ironic deposits wake slyly about the fluffily pending dependencies-- bold, unusual theodolites above the +6808|Customer#000006808|roBxgLQjBCcu7 Yls8BnCT3Oum241ON43b|7|17-840-939-1028|3471.22|MACHINERY|gle idly. ironic instructions sleep carefully accounts. bold, even sentiments haggle. furiously +6809|Customer#000006809|D2OPM0RO7wjQB,y5lQJIhGKRAK|19|29-455-199-9534|5772.30|MACHINERY|efully according to the fluffily silent packages. carefully silent packages use furiously above the carefully even +6810|Customer#000006810|Vav VVRBQ3WYqKNtNTi39x7,kXBcfblF3|13|23-459-864-2903|4116.60|AUTOMOBILE|instructions cajole permanently furiously bold grouc +6811|Customer#000006811|OcI9j59VXpHJy8akRgo9QazL2FBJzr|2|12-527-163-1718|6619.05|FURNITURE|ans besides the carefully ironic pinto beans sleep slyly fluffily pending +6812|Customer#000006812|AhoTwIbKJQn1FD4f59Og02|12|22-522-190-4711|1433.83|HOUSEHOLD| slyly ironic instructions! pending +6813|Customer#000006813|7sU37tY2xghEmgmrmGFw|6|16-378-417-2821|6328.64|FURNITURE|ges. pinto beans are fluffily. blithely +6814|Customer#000006814|xKxM4j61kF6WrHJSYTo|0|10-143-621-7307|4498.28|AUTOMOBILE|ructions. carefully bold Tiresias haggle furiousl +6815|Customer#000006815|SwpQn8U2,7FIzgYG|23|33-553-747-6097|8623.37|BUILDING|dolites sleep. regular theodolites after the express ideas are a +6816|Customer#000006816|l9iMew1ckL2nrx5YiUnd0Bs7Z96,A|23|33-435-484-3984|5981.91|HOUSEHOLD|to beans are alongside of the final +6817|Customer#000006817|0GuFB2pIst2i5ku761SGYJF0YKbemV3oGBxuY|11|21-463-437-2941|6900.32|BUILDING| beans. carefully final theodolites haggle furiously unusual foxes. pin +6818|Customer#000006818|NsWBjqO16kujv3WRtKhhLH28|18|28-865-256-2071|9642.22|HOUSEHOLD|pecial packages sleep carefully furiously regular deposits. even, regular pinto beans cajole slyly about the blith +6819|Customer#000006819|BxmHawhcf5E|19|29-909-925-3216|2833.96|HOUSEHOLD|ts above the regular theodolites cajole at the pending, bold requests! slyly pending asymptotes would haggle. ir +6820|Customer#000006820|i1RJGpP9HqI4s6151jR1z8ZWpXdOU|10|20-589-342-9128|9377.01|AUTOMOBILE|ironic requests against the regular warthogs nag across the fluffily regular deposits: +6821|Customer#000006821|GpFN4sJSskru0JEsjNZLg,dcTKNsIgDO|14|24-956-317-4494|431.91|FURNITURE|l platelets. fluffily regular accounts across the silent pinto beans p +6822|Customer#000006822|bo tbD14X1LH254lRO|18|28-422-199-2677|8027.05|FURNITURE|sly regular ideas wake. fluffily do +6823|Customer#000006823|NxR5mcTtNqZad4WGlWudh PLP1itX0Y,xI4f|5|15-158-466-1756|4742.19|MACHINERY|onic deposits. carefully brave decoys along the blithely ironic asymptotes detect c +6824|Customer#000006824|ots Xj,zI6Lt,5CSMqtm0aoz7UeBs|14|24-918-571-1016|4911.60|HOUSEHOLD|encies cajole at the fluffily even pinto beans. express ep +6825|Customer#000006825|iCyuTflSjsWcDC|12|22-228-819-1874|3300.02|AUTOMOBILE|accounts. furiously unusual ideas are daringly alongside of the carefully unusu +6826|Customer#000006826|i6Gp3F X4bJxVZ,IOFWyvKHBzEWDK7Ao4B|16|26-414-821-5076|-532.24|BUILDING| slyly pending asymptotes! pending foxes nag. slyl +6827|Customer#000006827|pkyUJaeoz7jLGIrQ,kYUVF5loZj|5|15-181-335-1276|6647.51|AUTOMOBILE|press packages cajole carefully blithely bold pinto be +6828|Customer#000006828|i07aofApQ6Sg,gMjYzl ycOlqa sSi|11|21-232-607-3504|6718.53|FURNITURE|ickly fluffily permanent asymptotes. fluffily regular deposits use slyly carefu +6829|Customer#000006829|hLxbhkw8dFbPqPuELUIn39hrnisrNUfJv4F|20|30-413-747-6182|1323.84|BUILDING| the packages. regular dolphins s +6830|Customer#000006830|eVnzLRiUrpOj2zHTaq|6|16-527-593-5356|5679.21|AUTOMOBILE|endencies are slyly against the final, r +6831|Customer#000006831|s ZzU g4nFiJrvNg pE7cN1UGL7z3THVaXiuuY|16|26-690-485-7073|1470.27|MACHINERY|around the accounts integrate slyly according to the special accounts. blithely express deposits wak +6832|Customer#000006832|AggcVEoM1Dw2WfE|10|20-653-330-2367|2821.81|BUILDING|o beans use slyly ironic theodolites. ironic platelets boost carefully into the fina +6833|Customer#000006833|xpXLjnef5qfH2xlHXF9oMMzIjIsuex,F0uw|13|23-153-556-1341|3185.16|FURNITURE| quickly bold instructions. even somas wake blithely. blithely furious theodo +6834|Customer#000006834|2 OGzQbTM4PhDp6|12|22-607-237-9927|4970.18|FURNITURE|y after the notornis. fluffily regu +6835|Customer#000006835| 1Vwc1DHAl|18|28-336-747-3054|8825.71|FURNITURE|ss asymptotes about the bold ideas +6836|Customer#000006836|IPAnUQ7OdyUJ9HlXzSKYEp|9|19-944-807-7519|7724.27|HOUSEHOLD|e regular requests sublate regular platelets. ironic dolphins integrate carefully. slyly even +6837|Customer#000006837|kcS0yon,tgPVfGO7hrxyv5C,Su,gM|4|14-101-991-2132|8823.38|BUILDING|s. pending, express pinto beans w +6838|Customer#000006838|BITaY3dbOQVUe3i5g7,ewHd|23|33-156-718-4716|1578.52|FURNITURE| courts are after the fluffily express requests; c +6839|Customer#000006839|oYnqEjWQ9dZezLjJtHPNIXI8HoxtqANG Z7z zj1|19|29-332-980-9867|7140.01|HOUSEHOLD|tes sleep slyly furiously special requests. carefully even dolphins nod blith +6840|Customer#000006840|8enbm51YZ1P8 9WL56McRjcRLxC|18|28-421-550-7131|1256.89|HOUSEHOLD|ly blithely bold ideas. blithely regular excuses nag slyly even requests. slyly regular forges are packages. pendin +6841|Customer#000006841|g NzADDwQKOQedcgxkP3 vDTJ0OThsh0sqI,vb|9|19-631-468-3008|2459.12|MACHINERY| busily final packages across +6842|Customer#000006842|1xXUXh723lgE0wfY1d9vuOTXELqhEPFo5t|9|19-676-771-4155|1342.45|MACHINERY| above the regular theodolites wake ironically against the bold, regular foxes. unusual requ +6843|Customer#000006843|M5z1DoiXAJCQVVIHKjMbntcT1A3Lfc4XSkXVRY|19|29-764-509-2918|-563.00|FURNITURE|ove the carefully regular instructions. carefully r +6844|Customer#000006844|hgGc5KCVN3QDk0Lci|6|16-763-561-5338|6663.09|AUTOMOBILE|ng to the silently unusual deposits. slyly ironic excuses use around the slyly regular escapades. regul +6845|Customer#000006845|VzpxA2uz,A BwWkAvIJnXqZHGDlhXK8n3IX8|19|29-371-479-7196|4510.06|MACHINERY|g the slyly pending packages wake along the carefully final accounts. regular pin +6846|Customer#000006846|ggBnTO6OZXBMWuflbpz4yVEDFUa9n|20|30-223-579-2199|8524.19|AUTOMOBILE| carefully ironic requests. slyly ironic deposits sleep along the carefully special dep +6847|Customer#000006847|FgCB,v15gQzq6|16|26-489-731-4993|81.08|AUTOMOBILE|across the quickly final theodolites. slyly ironic d +6848|Customer#000006848|XETSPsMa,,KHVAAu|8|18-993-692-5687|7653.55|MACHINERY|. theodolites run carefully quietly even packages. furiously even pinto +6849|Customer#000006849|zwnB9JnyCV0B2O Ue6Jn78KBarQRx2m|19|29-921-924-3641|8217.84|HOUSEHOLD|requests. ironic instructions use blithely blithely special ideas. bold theodolites haggle a +6850|Customer#000006850|A0qvm6saCh|4|14-519-545-3578|-702.43|BUILDING| special ideas. final, regular platelets affix regularly according to the slyly bol +6851|Customer#000006851|hvFJsItQnymk8pxkrjnenWCJ9GAjSNh |12|22-860-161-7304|6230.56|FURNITURE| foxes. blithely enticing accounts above the furiously re +6852|Customer#000006852|C hC7N6xSqjDVmEQzEZ01NYj4SBl5nhu|24|34-681-524-9480|6121.02|HOUSEHOLD|ily silent pinto beans. even, ironic dependenc +6853|Customer#000006853|AbpZYqtK6c5EfpZtpF|10|20-422-853-4017|1986.65|HOUSEHOLD|bout the requests. pending deposits cajole carefully above the regular deposits. requ +6854|Customer#000006854|Ka5iBA43bmKVAjKqFya2HfFkurzVx3pbFn,|5|15-430-821-6024|2568.18|FURNITURE|ts cajole carefully across the regular deposits. furi +6855|Customer#000006855|7yJhlD4Ziy9 IFz4VFzAURNoVWzFj5zyYdKBKT|6|16-876-384-6010|8375.91|BUILDING|s across the slyly unusual requests cajole alongside of +6856|Customer#000006856|CQMnbODOwhI9toZ75vf|23|33-529-574-6366|4984.79|AUTOMOBILE|. blithely ruthless warthogs against the slyly final deposits wake along the furiously fi +6857|Customer#000006857|qnTjfF57SI5LrBzO|23|33-446-990-4978|1409.67|BUILDING|. slyly final packages poach bli +6858|Customer#000006858|pd6Motczl51ondujEyQ7367tYCT4NC6|0|10-799-377-4331|7239.92|BUILDING|olites cajole carefully requests. special, blithe gifts pr +6859|Customer#000006859|1zy,R99p9Dg|17|27-368-450-7892|8452.75|MACHINERY|ular requests. blithely regular requests nag! quickly unusual instructions cajole. carefully ironic ac +6860|Customer#000006860|j0c5d8lwjd X7fYicMKeDycv|4|14-580-483-9140|9414.14|AUTOMOBILE|ithely unusual pinto beans unwind special packages: quickly pending deposits cajo +6861|Customer#000006861|um,8dEPxPOIu4uCO5oF9C os|19|29-269-205-4055|8593.46|BUILDING|ole fluffily against the carefully unusual excuses. special, final accounts +6862|Customer#000006862|WHjtQl UwzncNIkejao3a5W|14|24-682-159-5973|9323.04|FURNITURE|heodolites wake idly against the packages. ironic theodolites c +6863|Customer#000006863|C7xp7Euj8Zatj|1|11-147-882-1449|6353.09|AUTOMOBILE|luffily above the ironic, express requests. sly, careful foxes are about the pending, fl +6864|Customer#000006864|sdyPu0LQ3RkTdoFy|23|33-998-134-8314|8447.64|HOUSEHOLD|ickly even theodolites cajole slyly blithely special pinto beans? slyly unusual depos +6865|Customer#000006865|5JPh7HJJGpVizXF|24|34-198-293-9623|527.61|AUTOMOBILE|l courts. slyly ironic foxes b +6866|Customer#000006866|P7lfQDiROc4qhR3Khflxr|6|16-366-687-4124|-567.46|MACHINERY|ly. slyly regular ideas integrate instructions: dependencies haggle furiously regular, regular dolp +6867|Customer#000006867|t1gpHaWFZqRKhV,raEaxdUJ,MU|14|24-146-780-7698|8539.69|MACHINERY|es doze furiously express accounts. slyly silent requests sleep fluffily fluf +6868|Customer#000006868|R13,6EjlPmdsl|23|33-647-349-2675|7639.96|MACHINERY|al packages. ideas boost slyly above the final requests. regular deposits haggle fur +6869|Customer#000006869|6ZYHNoZX5,Me|14|24-606-630-9319|-84.65|MACHINERY| pinto beans. carefully ironic accounts haggle caref +6870|Customer#000006870|i3GhNxcD0,NDHWYXq778CcKI4Rok57Rk4I50R|16|26-714-569-7040|5292.68|AUTOMOBILE|boost furiously. furiously unusual ideas nag along the ideas. requests cajole carefully among the sly +6871|Customer#000006871|4Aawh3u9VlvfLcp,2|4|14-497-499-6031|6002.37|AUTOMOBILE| regular requests. even, close deposits are. permanen +6872|Customer#000006872|seuInq8wsBrKZU6lBlb ro1lt1gMtWkI L6LEQS|14|24-644-733-1264|9852.24|AUTOMOBILE|y ironic packages after the quickly final accounts haggle foxes. ironic e +6873|Customer#000006873|KXt6OTXQyCYz46Kw5Ynz|0|10-948-162-7136|1599.50|BUILDING|ts boost requests. slyly quiet requests are slyly across th +6874|Customer#000006874|VbQ7fM46whu0cr31adJ|19|29-695-872-3712|7814.06|FURNITURE|en requests mold furiously express, final multipliers. car +6875|Customer#000006875|TjO3DIyAnZ5kX3 KOWj7m7d,3jC1dbZZNy9MoNVg|10|20-934-535-5633|28.31|AUTOMOBILE|lly regular instructions haggle fluffily accounts. carefully regular dependencies wake furiously. +6876|Customer#000006876|AzTnyu945JeYf4PLbjV7cSL3v|21|31-326-600-5503|812.97|MACHINERY|ccounts should nag until the ironic, express packages. ironic forges +6877|Customer#000006877|QR2VDDA94zJHPMmac86RN1Lg3SPxPzIt,u|16|26-767-249-9337|-532.13|BUILDING|rding to the quickly bold instructions? careful ideas cajole furiously against the final packages-- fluffily busy a +6878|Customer#000006878|OyrOaYhd68cPx9maycfwDGq R22|14|24-648-517-8694|8396.86|HOUSEHOLD|ic packages boost around the blithely final deposits. permanent, +6879|Customer#000006879|qGAxDp5CIcJWPNt zGFerq4kFZWQiX|12|22-942-165-1099|5044.93|FURNITURE| to the special foxes? fluffily special theodolites +6880|Customer#000006880|t3um3YPoJ17XQUXC8V3VBIFnoz1D|24|34-961-846-5811|225.45|BUILDING|ts print. unusual, special deposits against the blithely regular accounts serve fluffily after the deposits. even +6881|Customer#000006881|6VfVWZMuCYB8i4b 6dRhgUPFMnWADADr407sLL|18|28-406-320-1387|3156.70|AUTOMOBILE|ets across the ironic pinto beans should boost ironically furiously ironic asymptotes. blithely regular accounts des +6882|Customer#000006882|3lBEzGcwg1vKtSkqtvzMVQwqvwfGBGn|2|12-151-684-6027|-396.82|HOUSEHOLD|he unusual pinto beans. slyly regular accounts haggle furiously express excuses? slyly pending warh +6883|Customer#000006883|,OGuJ9Zt3XpAEONbIpIpal Ux3|11|21-873-538-3754|5579.14|FURNITURE|s frets nod blithely alongside of the deposits. quickly even theodol +6884|Customer#000006884|yRIvbIG72RGuz|11|21-789-993-5944|2597.78|BUILDING|uickly. quickly express deposits sleep slyly? q +6885|Customer#000006885|zgFxaDEtwdOvsa8eku1KI5f0Hq|17|27-266-722-7657|-188.30|AUTOMOBILE|sits wake carefully. ideas are carefully. final, furious packages impress slyly unusual requests. slyly re +6886|Customer#000006886|e1kh m79wZ2sAUFXAzmTAsYsG6bpc2SlJ|5|15-103-327-5461|1158.35|FURNITURE|lly. fluffily regular foxes alo +6887|Customer#000006887|Ts6FP r64sVYHPT|0|10-744-644-3355|7280.37|MACHINERY|lly even accounts. unusual, final foxes cajole express waters. carefully special +6888|Customer#000006888| O40aa4,Ip frcWNEh6XbZL5kktj,QFqRe|5|15-967-617-5600|6207.74|AUTOMOBILE|to beans. regular packages accor +6889|Customer#000006889|SvUWryqsTeYMUI8MoGwe23MxCJcgnk|15|25-961-943-9801|7526.00|FURNITURE|according to the accounts. foxes cajole carefully. ironic packages haggle blithely +6890|Customer#000006890|9h9 InEMYJ5P|7|17-911-310-5010|9514.17|MACHINERY|en packages. express, even inst +6891|Customer#000006891|6KWm7ap8xnKV2zYC7ejZifLwE|12|22-373-997-5030|6815.03|BUILDING| use carefully regular packages. blithely +6892|Customer#000006892|mNuuOriPB9 YdILhmvINOGd38jGBZ|13|23-151-643-6412|6203.78|BUILDING|s sleep carefully foxes. slyly pending requests sleep requests. requests nag furiously carefully +6893|Customer#000006893|IQKKtRNXWAsdbqynSPQ7P5Pd8X uF|3|13-947-844-8526|6929.65|AUTOMOBILE|y special foxes are quickly carefully final requests. unusual packages affix express, regular requests. quickly +6894|Customer#000006894|qP,e3crppnJlKzejVH b2D,|12|22-247-482-7189|7747.33|AUTOMOBILE|al accounts according to the pinto beans doubt among the final braids. blithely fina +6895|Customer#000006895|eYt JN3SRFOg,PHtmhhfqN|20|30-525-577-9213|361.67|BUILDING|kly even theodolites. packages integrate across the slyly pending accou +6896|Customer#000006896|MvVnnxEF29nDVdr WvzbHWkm|24|34-850-657-1872|4576.31|AUTOMOBILE| final, regular waters. final platelets wake furiously silent deposits. regular +6897|Customer#000006897|2y42Nhr2PYA54EHyciLjYpnVHJStojcN|0|10-920-317-5942|101.13|BUILDING| the express dependencies. boldly ironic foxes nag slyly express requests. final +6898|Customer#000006898|Iu VC1aV16HlqfvkfNd8snf4|20|30-234-165-4904|3546.09|MACHINERY|. carefully regular ideas cajole carefully brave, final asymptotes. regular, regular +6899|Customer#000006899|fI2lc9kOUESmGia2kXSJNNI, 5MMioi3cbGg1M97|0|10-535-357-3310|-909.78|BUILDING|e carefully regular ideas. pending warhorses use quickly according to the blithely even accounts. blithely regular +6900|Customer#000006900|XxzSLyP jdrxrFf,iyxf|5|15-836-566-6221|8277.05|HOUSEHOLD|ully final requests sleep carefully enticing, even theodolites. excuses cajole! f +6901|Customer#000006901|MF1Yh6821MDYo|17|27-691-188-7577|4462.87|AUTOMOBILE|sleep quickly even theodolites. furi +6902|Customer#000006902|bDR25t GnLkoK|6|16-378-380-3108|7453.93|HOUSEHOLD|e fluffily above the blithely even dept +6903|Customer#000006903|AtYnMz1ydb2y2yeKlQ6df1txYM1Ibs5u|9|19-471-505-9852|8241.38|MACHINERY|gouts cajole instructions? quickly unusual ideas caj +6904|Customer#000006904|Pm8 tKCreWStvS|22|32-451-759-6848|9979.02|AUTOMOBILE|lyly ironic asymptotes: fluffily ironic accounts cajole blithely pending +6905|Customer#000006905|R,hn e5kStdmzVDhYooDC7Z1tJ7|11|21-390-139-1440|9534.63|MACHINERY|ng requests. carefully silent theodolites +6906|Customer#000006906|NtpZ4oXphusYXOHppCd,DNX g65hon1kdIAGs233|6|16-847-442-4850|9552.15|AUTOMOBILE|inal theodolites wake slyly carefully dogged packages. reque +6907|Customer#000006907|xVxf5 SbjMNLGhAFzmW6|6|16-105-262-6169|7106.46|HOUSEHOLD|ccounts integrate against the even packages; blithely even pac +6908|Customer#000006908|PSFN752zobO,NnrXueh68DsNliR|18|28-352-804-7306|9321.69|HOUSEHOLD|y packages; carefully even theodolites boost carefully after the furiously ironic gifts. foxes kindle slyly. sly +6909|Customer#000006909|wTMW41vDDJ,rDvLBtcP2lAGPortmxNP18h|10|20-480-370-7421|5745.76|AUTOMOBILE|s about the ironic deposits detect blithely bravely ironic orbits. pending packages above the blithely iron +6910|Customer#000006910|wHUTQtKiSMGbGqKcC526p9Pfebuc7r|5|15-722-787-9962|8945.89|FURNITURE|the express, regular escapades. carefully unusual theodolites do wake quickly. quickly +6911|Customer#000006911|lx95MUKc7,CsN WHXRWUoVV|6|16-440-937-2210|3682.25|FURNITURE|riously pending accounts? carefully unusual accounts according to the quickly unusual re +6912|Customer#000006912|eZArhHGNgAZTIIs6m8JEFgvhhsybD77LXI8ScXH|8|18-789-906-8424|-383.69|AUTOMOBILE|quickly against the regular deposits. blithely regu +6913|Customer#000006913|jH27L,gZj9dws4sVD9pjQWjNM9Z3hjJhNEAHd|7|17-424-926-7617|6237.26|HOUSEHOLD|ses nag blithely slyly silent accounts. slyly ironic pinto beans alongside of the +6914|Customer#000006914|6ZnxYihMt7HmIQqiItpeVDq81omFb9S4mul|21|31-622-699-4865|8725.78|MACHINERY|. regular, ironic accounts among the furiously even pe +6915|Customer#000006915| VQo,H2BRkjoa0dYXLAA01mqwUytbBM|19|29-651-328-4337|319.47|BUILDING|lets after the carefully slow packages cajole blithely asy +6916|Customer#000006916|KGSD2t2VRVQ,n3EW4TiQH8i4L8VBRP1P|5|15-509-409-1957|-795.98|AUTOMOBILE|lites. regular pearls solve quickly. carefully regular sheaves against the always +6917|Customer#000006917|SwW3qHYL1ZuBlx17gCKpvcP|6|16-544-374-5520|6932.21|FURNITURE|d sleep. blithely special ideas haggle along the special pinto beans. regular, special warhorses are alongside o +6918|Customer#000006918|0HHnMHiko6CFQTroq5lGeFg0JDtZm6PUhIWU|3|13-658-888-3933|6671.40|HOUSEHOLD| fluffily carefully quick accounts: fluffily regular pinto beans cajole quickly according to the q +6919|Customer#000006919|hUBFeaV6cn41fFHMpvd7nuAMC1Q4|10|20-964-269-3393|1279.94|HOUSEHOLD|deas are carefully. regular, permanent instructions boost slyly. blithely unusual deposits caj +6920|Customer#000006920|DmTeHxRVLSe32KfxJp38lE|0|10-384-129-2868|4968.13|BUILDING|ounts are blithely above the furiously special sauternes-- quickly special +6921|Customer#000006921|nGFGmYctkA9IM0vxf2Y4GBPnT|12|22-642-260-2620|7388.91|HOUSEHOLD|ly unusual requests boost above the final pinto beans. careful +6922|Customer#000006922|3bCCt0S2wd6RQeq|4|14-163-216-8977|4434.20|HOUSEHOLD|kindle carefully. carefully unusual packages d +6923|Customer#000006923|v6BO5dXHqLFmOfPck0|7|17-733-662-9017|9600.79|FURNITURE|t about the pending requests. final, regular theodol +6924|Customer#000006924|z,OREBfNfUkRsj|16|26-289-764-7597|-408.30|BUILDING| the unusual packages. ironic, final requ +6925|Customer#000006925|2Gg4xMqjRAV0nAn|8|18-878-944-5385|-448.55|HOUSEHOLD|sits about the slyly regular accounts x-ray carefully over the unusual, final theodolites. blithel +6926|Customer#000006926|KOx lB nFGsdak3 Sc5zCjiRFoWq1mx5t|22|32-894-701-8844|5160.08|HOUSEHOLD|its haggle quickly. fluffily even packages sleep slyly along the theodolites. express, pending deposits above +6927|Customer#000006927|Ra0BshyuR,4uTcWjvs1PIqswCbIC6U l7A|6|16-135-283-6467|-509.64|FURNITURE|efully even depths. requests should have to w +6928|Customer#000006928|SOf,2mOUgK5PpW,C9US8oH61eNDG4|2|12-944-721-3451|1380.62|AUTOMOBILE|fully after the slyly dogged depos +6929|Customer#000006929|sQEFEgufg0ZT|12|22-151-910-6027|3000.98|HOUSEHOLD|lites haggle final platelets. express, special theodolites wake slyl +6930|Customer#000006930|RpPHMhjHQLhRR|11|21-832-212-8391|386.35|AUTOMOBILE|e blithely even accounts. ironic, even accounts about the furiously final +6931|Customer#000006931|DJcGXg0BrP1ibpV7UCxEaK5OXy yCckOACzF|24|34-282-643-3571|1402.40|HOUSEHOLD|nusual pinto beans across the ironic deposits are blithely alongside of the carefully brave foxes. quic +6932|Customer#000006932|XjlmI08 R3CXJ8JPYGwSihQUDir|19|29-930-104-7406|6064.87|AUTOMOBILE| courts cajole ironic, final ideas. ironic multipliers cajole carefully iron +6933|Customer#000006933|w0D2wXhqohW3rtxjXxIQvcxH75Fh1XAWZ3O|20|30-564-778-5516|4292.61|FURNITURE| accounts above the quickly final warhorses print blithely +6934|Customer#000006934|oVWWov tNz1fn|14|24-121-895-8013|5944.59|MACHINERY|efully express ideas cajole furiously slyly brave packages. closely bold requests haggle +6935|Customer#000006935|eqVuF6zTXrqK4BhmNUBAZQghbjY8uy0co|3|13-497-759-6170|6730.94|FURNITURE|ronic, regular requests after the ca +6936|Customer#000006936|XgPD s4bQqx5|9|19-923-718-1041|1006.58|HOUSEHOLD|he ironically even packages. regular dolphins are slyly by the pending excuses. slyly final requests haggle careful +6937|Customer#000006937|BlUCF0,i2jMXs70wxl3AWvd9frn|24|34-883-594-7672|8496.83|HOUSEHOLD|lly slyly ironic deposits. quickly special excus +6938|Customer#000006938|2ud1eHT7TvCAPub2UZ3bkcKT2Pq8M11eSpd|15|25-974-463-8064|2339.57|HOUSEHOLD|realms are busily carefully express requests. furiously pending foxes try to cajole blithe +6939|Customer#000006939|e2UhEWWPopLOyQ6G|10|20-425-357-4024|5165.17|BUILDING|ut the ironic ideas. regular courts according to the final instructions detect blithely theodolites. even packages +6940|Customer#000006940|37YCc8T1xgurTO|11|21-485-600-2482|8105.71|HOUSEHOLD|y along the carefully regular gifts. final accounts cajole. quickly ironic deposits kindle carefully f +6941|Customer#000006941|63Z3Qe6urA|4|14-210-435-4058|6757.19|MACHINERY|ular instructions cajole above the bold, ironic accounts. ironic ideas about the blithely even re +6942|Customer#000006942|N31XA0a7VOdIiIxuKpbYwE0l|10|20-899-337-6472|2059.91|HOUSEHOLD|ep blithely about the quickly regular dependencies. ironic +6943|Customer#000006943|qjFXg1Ia9FuM|24|34-704-691-5442|1872.41|HOUSEHOLD| carefully regular excuses. ruthlessly unusual instructions was ironic theodolites. pinto beans cajole carefully +6944|Customer#000006944|PlOgCXn qIsC96sqwi7jMKVcv|8|18-677-417-1382|7549.91|AUTOMOBILE|nding accounts. bold dolphins detect bold packages. reques +6945|Customer#000006945|X6nI1uOqfKBA,7V7iEb9PWg6hbM794B1ZmSsgk|10|20-763-130-4896|4363.99|BUILDING|nt accounts sleep quickly. theodol +6946|Customer#000006946|O142a46LKzb75,ggUsnA7yY MHZ7rxNi|24|34-108-937-2099|6626.82|HOUSEHOLD| final packages boost above the carefully bold pinto beans. pending sheaves sleep beneath the sp +6947|Customer#000006947|2q61zt4rUQY6JOVeKxh FcRNRqj|24|34-935-489-1820|-30.39|AUTOMOBILE| packages. furiously close deposits sublate across the final packages. regular, bold requests breach. car +6948|Customer#000006948|GWfdOFWXism9l,PQp8azQJO UPfcdMm2cb,rqU5|3|13-636-530-5983|4150.95|HOUSEHOLD| blithely unusual forges run quickly furiously final accounts. blithely regular accoun +6949|Customer#000006949|88E o,rjHZJVp|0|10-920-156-2564|999.02|AUTOMOBILE| even instructions. asymptotes use. blithe theodolites +6950|Customer#000006950|D7PZ9 FXDeoG9jzsIqiVm8i V|16|26-567-707-8729|2414.22|BUILDING|g to the express platelets. even account +6951|Customer#000006951|dswooF8dKb|21|31-661-344-4562|5751.69|MACHINERY|regular requests. carefully silent theodolites promise quickly regular accounts. platelets sleep among the fina +6952|Customer#000006952|tedolX6bU7a07kS,HSV1Kh2VartW|1|11-964-186-1638|9600.30|HOUSEHOLD|ckages play pending ideas. pending dependencies wake blithely along the unusual accounts. eve +6953|Customer#000006953|T6GNNKYnmp3KhK2a,n|4|14-200-221-1070|2384.73|HOUSEHOLD|ar dependencies boost across the regular, bold +6954|Customer#000006954|rGHTeIqYsbkLG4yOmrZWyvY17zxvWjCgvj|19|29-846-280-8291|5080.67|BUILDING|ross the ironic pinto beans affix after the packages. ironic, express theodolites after the furious +6955|Customer#000006955|7Pl77 AAMou0F56ufvqSGYm2dFZrsBSf|23|33-734-299-2759|6751.07|HOUSEHOLD|is against the carefully bold theodoli +6956|Customer#000006956|k 4M1dYnBY0s9tDIjnpZQ7QSRAsqv,dP4qip CBY|19|29-765-731-1061|9202.51|HOUSEHOLD|ial requests detect carefully express instruct +6957|Customer#000006957|sAt10Pog00qXxf3|1|11-448-447-2941|4672.45|HOUSEHOLD|idly pending pinto beans. carefully pending deposits cajole quickly across the unu +6958|Customer#000006958|pyyjzooPiwi2FUIz|5|15-554-805-5336|9829.41|AUTOMOBILE|ly final pinto beans. carefully express ideas about the furiously unusual pinto beans ha +6959|Customer#000006959|rorENMWClttRXEp|13|23-233-789-3757|2990.45|HOUSEHOLD|gular packages are slyly across the asymptotes? escapades boost blit +6960|Customer#000006960|OUKTB cNG030,aFLzyB|19|29-674-628-3972|-505.65|BUILDING|blithely final waters detect according to the even pinto beans. express +6961|Customer#000006961|T6oeN XNst4bY6QOIxFQAj,WN|16|26-346-690-5410|2474.82|MACHINERY|its use carefully blithely even pinto beans. carefully even acco +6962|Customer#000006962|4G9HL28bwq|5|15-357-936-1344|1281.15|MACHINERY|equests. regular deposits nag. foxes sleep quickly-- carefully regular requests across the deposits wake quick +6963|Customer#000006963|CW0iwpVyNqVJiJf0roU5OAoX|16|26-430-431-1058|3161.07|AUTOMOBILE|le quickly ironic excuses. slyly close ideas wake quickly wit +6964|Customer#000006964|IWYQGMU6rEz4GMdjsQAKCsnQT5|13|23-185-648-1303|7140.70|HOUSEHOLD|lly bold requests use carefully carefully bold +6965|Customer#000006965|d6gerbM9AWmOdDpp|15|25-939-405-4493|1815.68|AUTOMOBILE|ular accounts. carefully close accounts doze. final requests solve furiously furiously ironic requests. special asym +6966|Customer#000006966|Q3yAE1yoj,TKafWnhyfcR4WL322ME Pv9bkNR,FW|22|32-842-357-9534|144.58|FURNITURE|theodolites use. finally special excuses hagg +6967|Customer#000006967|uMPce8nER9v3PCIcsZmNlSrCKcau6tJd4qe|13|23-816-949-8373|7865.21|MACHINERY|r pinto beans. regular multipliers detect carefully. carefully final instructions affix quickly. packages boost af +6968|Customer#000006968|Ez1Rhj5Qi2,10Nug38BsPiacwskhzpT|5|15-858-442-4792|1651.44|AUTOMOBILE|deposits are blithely unusual foxes-- even requests do are to the blit +6969|Customer#000006969|HKsXzhiJwn0oWqic7outvp6ek5|24|34-608-122-1503|727.09|HOUSEHOLD|s. even foxes wake. requests haggle slyly carefully final deposits. even f +6970|Customer#000006970|PEtGiJUdTje1Iag6unPFdev|7|17-244-333-8174|8208.18|MACHINERY| regular accounts grow carefully +6971|Customer#000006971|OMyW3Rc1F9r9ixU|15|25-797-318-1684|1906.06|MACHINERY|ts. carefully even excuses mold blithely carefully final foxes. furiously unusual accounts sleep carefully above +6972|Customer#000006972|MjqRGeXURtvVOEY5u30KbgffSKBvJ2X2OI,Hm6Tj|10|20-340-512-1672|1096.88|FURNITURE|ges wake up the fluffily pending deposits: slow deposits cajole before the slyly regular frets. regular theodolites +6973|Customer#000006973|2kXQXsfJMUjQn|21|31-948-302-3253|8232.51|MACHINERY| the regular, final asymptotes ca +6974|Customer#000006974|TVPV8QjdvgxuewOviKUj8IrMvta yJ|23|33-695-299-2927|3894.63|FURNITURE|ounts above the blithely bold requests sleep furiously across the regular instructions. quickly +6975|Customer#000006975|bSjO03DW yuKgBg2ewRK6e47ixGfAYRuFT,GR9|23|33-652-640-1772|5049.82|BUILDING|ld accounts above the furiously +6976|Customer#000006976|Oj Pipp9GFv8FLDelp82C|9|19-115-502-9616|5348.14|HOUSEHOLD|structions wake carefully. furiously even requests detect blithely. fi +6977|Customer#000006977|IAhFYl42MDQOWl FBdXT8M o|8|18-423-650-1806|3164.56|FURNITURE|usly alongside of the bold accounts. packages haggle after the blithely ironic accounts. ironic pinto beans dete +6978|Customer#000006978| TOk2qS85CJpdrRpGsszF|12|22-707-108-2535|-325.02|MACHINERY|xpress patterns engage fluffily after the deposits. blithely final theodolites nag abo +6979|Customer#000006979|K1aueKP9rhN,OLMh6NB9MF9JC|3|13-179-679-2432|2270.82|BUILDING|ously regular pinto beans wake: ironic requests wak +6980|Customer#000006980|IzbhQ7AaNNSNkTjIGPsH1bZe53WXDupcQm|11|21-352-950-4327|4710.25|HOUSEHOLD|ing instructions: furiously bold dolphins about the furiously ironic instructions haggle furi +6981|Customer#000006981|BDM83,inyQX8VjjAAY8hrSlA8uu9h6zusf|22|32-465-600-2595|7194.73|MACHINERY|le quickly express deposits. final theodolites haggle quickly permanently even pac +6982|Customer#000006982|dTif54yxBO1KSK90YnlVp,j53YYC4D|8|18-481-928-6409|7891.67|BUILDING| alongside of the furiously regular accounts. quick +6983|Customer#000006983|E0AqrX3aIw4ZcINSIWDXD,7qxDykEj5odh8|22|32-796-697-5842|6348.19|BUILDING|ackages. special instructions wake alo +6984|Customer#000006984|ESRBQnnbjKMRydlNyoXn,|2|12-423-137-1791|3020.71|AUTOMOBILE|ckages at the blithely regular ideas wake blithely amon +6985|Customer#000006985|J9qvTE,Ic0Oxv2cbFwAynNxzDW5KY96qVpOQ3q|13|23-652-721-2985|2119.77|BUILDING|efully carefully final deposits: quickly pending dependencies wake al +6986|Customer#000006986|EBY0Sg3HMtzo8CzNhzaUtjiR1bAL|23|33-582-389-4321|6959.44|AUTOMOBILE|nts sleep slyly above the regular packages. slyly unusual packages na +6987|Customer#000006987|lGJOaGFNBmiIy3AIqwf5Az0aGvrXnhfakZBOQawR|17|27-320-420-9595|2282.79|AUTOMOBILE|latelets haggle quickly slyly regular ac +6988|Customer#000006988|PuokzRJ2EY5|3|13-830-329-5880|7733.90|BUILDING|inal platelets affix furiously. blithely regular deposits promise special, unusual requests. fluf +6989|Customer#000006989|VAdDFdOq9BAyUsOP8CaFBvTG8G2K0|23|33-283-282-3404|5712.90|AUTOMOBILE|ular asymptotes use even, regu +6990|Customer#000006990|z3zQwqsS8eg61oVV4e8UgdFDt|7|17-437-544-6391|6746.93|MACHINERY|ackages. express, unusual accounts cajole furiously toward the fluffily final acc +6991|Customer#000006991|xMyl,tcSuNEP L6z5VlZXB69GuDoBz1 FeQxHnb|0|10-948-457-2049|5747.55|AUTOMOBILE|s around the slyly bold deposits wake carefully among the bravely pending asymptotes. quick +6992|Customer#000006992|HvnRKHV1kJ|23|33-830-883-1031|6070.79|MACHINERY|ithely quick foxes cajole fluffily. even accounts +6993|Customer#000006993|VgyZ4hR3o2DDrqX2p9f1ao8GLn7Y el0|11|21-996-879-2346|4754.10|FURNITURE|l pinto beans boost silent pinto beans. carefully even accounts integrate evenly. d +6994|Customer#000006994|rV05MzBGNrLz|0|10-962-702-6979|7109.05|BUILDING|ctions unwind. bold foxes cajole quickly above the regular, i +6995|Customer#000006995|h1Is0,kANMXbCDqVHJav|16|26-594-133-2656|8768.51|HOUSEHOLD|slyly ironic, even accounts. furiou +6996|Customer#000006996|FFH0V1HOhdgfDs,kJV|20|30-658-795-5594|3335.98|MACHINERY|egular asymptotes cajole quickly regular requests. unusual courts use quietly unusual, pending packages. package +6997|Customer#000006997|twNLY6rDvngJvLOEiF|18|28-278-657-2446|9728.39|BUILDING|ep furiously along the grouches. regular, slow accounts use blithely regular, bold foxes. slyly slo +6998|Customer#000006998|R4GseYn1PbPAQkah9p5Bdqfe|15|25-779-557-3473|-870.34|AUTOMOBILE|after the blithely bold deposits impress quickly idle instructions. slyly silent instructions among the bra +6999|Customer#000006999|1T9GzwkkJp,giqi KBNPEXhslG|9|19-345-535-4019|93.74|BUILDING| are above the slowly pending platelets. +7000|Customer#000007000|GabU4EArz2WOSxBImz79QitlufnV,kWbFSrQD|16|26-901-104-2112|469.82|MACHINERY|after the carefully ironic accounts boost slyly regular accounts. express, regular a diff --git a/src/test/regress/data/customer.3.data b/src/test/regress/data/customer.3.data new file mode 100644 index 000000000..66ec3f4d1 --- /dev/null +++ b/src/test/regress/data/customer.3.data @@ -0,0 +1,1000 @@ +1001|Customer#000001001|KbWTzGB3ZUymu nNCIuG5eCueaqu|21|31-389-986-4741|7140.81|MACHINERY|ever. fluffily special requests are. slyly final asymptotes are carefully quickly reg +1002|Customer#000001002|98bKmyr3jZWRLEY9WBtyUWOodVd|10|20-973-622-6579|3699.76|MACHINERY|ns. deposits along the ironic, regular packages wake furiously according to the carefully even excuses. slyly qui +1003|Customer#000001003|lE07lPMzVzMhG9CUC54uPwGw3BWO|21|31-716-397-1854|7894.00|AUTOMOBILE|quests sublate blithely blithely special dependencies. excuses use busily express pinto bea +1004|Customer#000001004|mBaNGEJoY2tgXD60V2DEO ajjoM3Zd,Jp|8|18-676-152-4849|1512.46|MACHINERY|ainst the ideas nag fluffily according to +1005|Customer#000001005|cTWPLcTvotjgrrcN3j|13|23-149-373-9093|7790.94|AUTOMOBILE|. furiously ironic accounts affix careful +1006|Customer#000001006|Q46palcsa4KwAMhPS|12|22-364-780-5932|7447.99|BUILDING|equests. regular pinto beans sleep furiously express, ironic accounts. special, +1007|Customer#000001007|PfH0lw8GzD7o|9|19-790-843-5283|7347.90|MACHINERY| theodolites. ironic requests wake. thinly silent +1008|Customer#000001008|AfP6tFNz1Eu4buoUd,HrZAld340 xz2wbQ2|2|12-115-571-7897|8191.74|HOUSEHOLD|press orbits affix furiously pending packages. courts alongsi +1009|Customer#000001009|cWONXs2Vx30bkgYoCkx7LrJH,E|12|22-132-906-1117|594.50|BUILDING|ng to the stealthy, final courts cajole carefully alongside of the gifts? regular ideas above the furiously express +1010|Customer#000001010|uasIK CZZ5|5|15-221-463-3776|1652.78|AUTOMOBILE|ing ideas doze carefully accounts. slyly regular theodolites poach. carefully pending de +1011|Customer#000001011|6m8KP FxT4nnHgoc4CN70TVLW1X5Q|5|15-736-809-3168|1188.94|BUILDING|uriously express asymptotes. u +1012|Customer#000001012|5Zsp rqM6oCmgqqFe|4|14-535-551-6255|4422.45|AUTOMOBILE|s above the carefully express r +1013|Customer#000001013|k5rfeOtchP1 w|15|25-725-599-1183|-951.53|BUILDING|idle packages cajole regular asymptotes. carefully express forg +1014|Customer#000001014|ZsiaboMOOV,aGwWUpfE|11|21-553-425-9152|-392.84|AUTOMOBILE|telets. ironic platelets cajole carefully; bold, special instructions unwind blithely regular somas. carefully +1015|Customer#000001015|RDJWEmcAk4GC8OT8WCsXB|10|20-134-926-5391|6392.00|HOUSEHOLD|g courts nag daringly brave pains. blithely special deposits use blithely carefully c +1016|Customer#000001016|8tzkhPXMFHKgmz|11|21-683-368-2994|2357.54|AUTOMOBILE|ular deposits. special foxes solve quickly idly special ideas. never final asymptotes nag. furiously even deposi +1017|Customer#000001017|OoVPZGR5hUp8oo|16|26-593-941-5690|-913.70|MACHINERY|integrate furiously furiously even pinto beans. ironically pending packages cajole quickly furiously special +1018|Customer#000001018|yldxLZOgQwzrXh3t4yktykZZV8v,vK2c6pVr|18|28-450-764-4871|8341.71|FURNITURE|e quickly around the quick, regular pinto beans. regular, regul +1019|Customer#000001019|VMFs38VlBt01g30PzPyliiAoGHazC4HG74JJ|21|31-502-683-3413|2114.53|FURNITURE|quickly special ideas about the courts use of the pending instructions. furiously final accounts c +1020|Customer#000001020|DHom,LSHKfYSwLSZv39AooYQHlvbaeztefjwR|3|13-692-286-8158|6914.87|MACHINERY|es. blithely unusual asymptotes sleep ironic accounts. fluffily express sheaves haggle fl +1021|Customer#000001021|m h2wQbujQnQOrcf109reW0 o|6|16-469-554-5196|1286.76|MACHINERY|courts could hang quickly express epitaphs. foxes haggle above the carefully unusual requ +1022|Customer#000001022|lP,9H6e6mQwLsWYYr2Y|8|18-733-553-2195|9605.83|AUTOMOBILE|ending packages. dependencies along the slyly pending dependencies wake carefu +1023|Customer#000001023|w8 oxHcOTUiF8dOr,ktZ05pO7qcHZ8ZeH7|17|27-960-306-5136|7188.35|AUTOMOBILE| express requests. slyly ironic asymptotes throughout the ironic, final packages nag careful +1024|Customer#000001024|9wLrRS78uOPy7CHW|11|21-508-779-7822|-425.09|FURNITURE| carefully regular instructions. furiously final deposits across the carefully special ideas cajole furi +1025|Customer#000001025|3T2A1uo8mCqTeO LTW8atjLBLO12nh6lyl|8|18-588-456-4616|3363.46|AUTOMOBILE|to beans sleep according to the fluffily regular instructions. +1026|Customer#000001026|ktKcS9tV2OC8T42KVqMem NjkNO 4pkXmu|17|27-169-221-8173|9699.28|MACHINERY|totes against the stealthy deposits haggle fluffily after the regular, regular deposi +1027|Customer#000001027|GNaw4RXXMr|2|12-278-154-5262|4946.21|BUILDING| final requests haggle. final, even sheaves maintain carefully above the even ac +1028|Customer#000001028|NxmOhIN,w45aogQ1hZSvqoz0 8nrbdkaiZOe|10|20-582-119-3249|1915.53|AUTOMOBILE|ly unusual, even packages. fluffily special foxes across the furiously final asymptotes main +1029|Customer#000001029|D3TLK5s,gc|15|25-602-810-8723|6252.18|BUILDING|arefully furiously final pinto beans. daringly express deposits +1030|Customer#000001030|Xpt1BiB5h9o|8|18-759-877-1870|6359.27|HOUSEHOLD|ding to the slyly unusual accounts. even requests among the evenly +1031|Customer#000001031|dwCYOftUgV5,EwGJc|21|31-946-641-1853|2226.80|AUTOMOBILE| theodolites. even theodolites sleep slyly. special, express excuses cajole among th +1032|Customer#000001032|6yoIzDrw5zLBO|18|28-449-227-3528|1853.64|FURNITURE| sleep quickly even somas. permanently regular grouches cajole blithely furiously ironic ide +1033|Customer#000001033|WOozPuOF8UdYMwjF5|8|18-470-380-2978|81.06|BUILDING| to the quickly final packages. carefully slow accounts use blithely slowly permanent requests. un +1034|Customer#000001034|Fn5qqb64TSKuJWz4f8GpPkF,c3WY3yqjsV,GgHu|5|15-370-179-6631|7349.82|HOUSEHOLD|bout the ironic requests-- packages wake. requests haggle silent, +1035|Customer#000001035|7yTbQ665G3Bi,6BK0EmQPw,Gc7bZOPk4ncXpo|10|20-376-345-3729|7499.36|AUTOMOBILE|ound the fluffily enticing foxes detect slyly at the furiously final deposits. quickly final instru +1036|Customer#000001036|fxujgj8DOFO6oKrH|8|18-791-577-7691|1766.23|BUILDING|ins sleep. slyly express platelets cajol +1037|Customer#000001037|dwgDZPKR5ZuU3HO2sDOS7Ym0oeC8c6Xm|23|33-855-960-2989|4936.25|BUILDING|lly final pinto beans. pending instructions boost careful +1038|Customer#000001038|yQCza56pNgcF9sxDR HCed22GeEq|17|27-511-101-1611|-509.92|AUTOMOBILE|uriously express accounts. even pinto beans wake. slyly regular requests according t +1039|Customer#000001039|F602TgKjElSWrZ|10|20-871-886-9220|7618.54|FURNITURE|nding packages use. blithely regular sheaves doze blithely. fluffi +1040|Customer#000001040|vbJmdHe6U9Pl|11|21-756-109-1482|2860.71|BUILDING|old requests wake slyly! slyly special deposits cajole above the unusua +1041|Customer#000001041|189f n2lA4|11|21-314-290-3052|7993.98|MACHINERY|uctions are busily along the furiously ironic instructions. blithely thin waters cajole slyly. +1042|Customer#000001042|S1sh9gyFn21m4zkb4J95GD5|5|15-215-652-3459|9849.87|FURNITURE|ly bold dugouts! pending asymptotes are blithel +1043|Customer#000001043|HJMn12xn4bl vWC7iVuTRsErYEzlyCO|7|17-266-334-8613|5847.76|HOUSEHOLD|iously ironic deposits cajole slyly busily final account +1044|Customer#000001044|Eh2e8gLyStrLE7A|0|10-451-459-9620|7291.30|BUILDING|ly across the slyly ironic accounts. even requests +1045|Customer#000001045|clvGUnQPLbzX 23hemPp24WS1MEtS4z|20|30-120-992-2121|2942.19|HOUSEHOLD|r deposits cajole blithely along the quickly silent pattern +1046|Customer#000001046|umgqzlyUW3AYz2C39YMhIgf|10|20-890-161-8958|2311.00|BUILDING| accounts. carefully regular theodolites run fluffily carefully e +1047|Customer#000001047|h5iBRMsym,y6LLSQU2DzNftiET qZ|9|19-146-399-4251|8918.99|BUILDING|lar packages haggle theodolites. thinly express deposits +1048|Customer#000001048|Mk0ebiw9SaFBTwoib|19|29-757-642-3735|2583.91|BUILDING|s are slyly regular foxes. slyly final pinto beans wake quickly among the regular, spe +1049|Customer#000001049|bZ1OcFhHaIZ5gMiH|9|19-499-258-2851|8747.99|MACHINERY|uriously according to the furiously silent packages +1050|Customer#000001050|KgVnjN7Y4HCN5f97HEUp7kYNNTrE3 O|11|21-448-313-4374|-517.65|FURNITURE|ely ironic packages. blithely regular foxes sublate furiously. special requests boost furiously agains +1051|Customer#000001051|iHS,UFudVOOe|2|12-869-221-1428|9776.39|HOUSEHOLD|cuses boost furiously silent deposits. quickly silent requests integrate quickly bold asymptotes; slyly regular ide +1052|Customer#000001052|OcXtKS,1Hvf2D0 rPvhw4qXViYOudQ3|13|23-496-475-9040|2837.96|BUILDING|s accounts haggle against the furiously final asymptotes. ironically regular accounts boost. furiously fina +1053|Customer#000001053|wDJTteyausmZswQAFQot|16|26-400-312-6496|-473.85|MACHINERY|efully enticing pinto beans. final pack +1054|Customer#000001054|Xgj6QVy2I9FVoSiIbgLf9LIE8XpWI2RtmbGUx|21|31-915-292-9727|8844.27|HOUSEHOLD|y pending ideas. dogged dependenci +1055|Customer#000001055|Z3AggyEMPME2hqqTfbMC76O0z|7|17-802-131-7180|639.93|HOUSEHOLD|dolphins: furiously ironic pinto beans above the carefully regular foxes nag slyly across th +1056|Customer#000001056|8u1rnDOcvU109|5|15-325-285-5215|6287.12|HOUSEHOLD|leep except the foxes. packages eat enticingly along the requests. even +1057|Customer#000001057|xyV8 FbW4xS,JhkxC0dY527tzcMKxM|24|34-750-735-1314|-377.11|AUTOMOBILE|s. furiously ironic deposits against the carefully bold accounts wake carefully even deposits. fluffily even +1058|Customer#000001058|R0NIEcSVDQ4rNUcCevDrap|19|29-818-620-9637|6807.55|MACHINERY|uctions. slyly express pinto beans are furiously. bold theodolites according to the fur +1059|Customer#000001059|OHwYMiDjmgeIQXhLlNW,8LIwIEr|23|33-683-418-9460|1547.50|HOUSEHOLD| wake carefully. carefully quick excuses cajole ruthlessly among the ideas. bold, ironic braids are +1060|Customer#000001060|aWJkU6JJJOvgaKPOAJJc|8|18-290-794-6133|2840.59|HOUSEHOLD|ter the bold, regular ideas! deposits eat. daringly unusual theodolites sleep alongside of the regular, fina +1061|Customer#000001061|CqLhg io1CpQKhrVHHDhWg1Omrx1hLcpKB6h|4|14-909-417-8324|-258.77|BUILDING|ticing packages maintain doggedly carefully regular instructio +1062|Customer#000001062|3OYrGEJC1YUa9DP|22|32-207-600-8684|4709.92|HOUSEHOLD|ag. carefully regular asymptotes a +1063|Customer#000001063|yHVWD7y1Oe1P|21|31-277-349-9036|1663.28|MACHINERY|ress attainments. furiously regular excu +1064|Customer#000001064|VmFhpV9 aIqPysMHRIWZl|15|25-391-998-4106|1666.07|MACHINERY|gular accounts. thin platelets promise fluffily. carefully express accounts haggle quickly qu +1065|Customer#000001065|qGBa7X0dOMsKLuYBpShpJVwGyU9rh|22|32-605-226-2449|4663.41|HOUSEHOLD|nts. quickly quick dolphins run +1066|Customer#000001066|2Ge 0Nk29FlBs1GuBiY84sLvn38mEkAKnM|0|10-333-463-4472|949.68|MACHINERY|requests. slyly final instructions sleep. fluffily even packages cajole pending, final +1067|Customer#000001067|g25CH,fhra|23|33-764-123-9568|9153.84|FURNITURE|ackages are furiously carefully even dependencies. idly final +1068|Customer#000001068|ElWdGnnKpmo0sA1Au teWwomSVgG,me|18|28-485-984-7299|737.40|AUTOMOBILE|nto beans. dinos sleep fluffily carefully regular sentiments. final, special packages wake blithely. ironic +1069|Customer#000001069|PdWrPGSArhnqWQ km65e|21|31-927-711-6278|5465.29|BUILDING|. ironic excuses after the special hockey pl +1070|Customer#000001070|m0sYmeYs5wLydSS qw542Et32|15|25-894-843-9171|3160.23|FURNITURE| carefully across the express foxes. carefully special accounts ca +1071|Customer#000001071|PgCAYL2LEwE7v7Pk4dYpRe Nn7MN8wVzYbA2qtj|16|26-350-231-6183|4033.56|MACHINERY|ar accounts. quickly regular packages sleep bold ideas. slyly pending asymptotes a +1072|Customer#000001072|HpCr1tM88WoELSld708ByJ|4|14-432-882-6163|7979.48|HOUSEHOLD|ic pinto beans are blithely across the grouches. furiously pending platelets sleep pe +1073|Customer#000001073|KEyFI2gYMZrSVbMMMIf|10|20-774-197-6595|8217.23|BUILDING|fter the blithely regular pinto beans. express asymptotes sleep special pa +1074|Customer#000001074|nG,eR,gjPr|10|20-176-839-1649|122.67|BUILDING|ly final courts haggle quickly boldly express excuses. dependencies eat. slyly even requests boost blithely +1075|Customer#000001075|hTIc2AUg pqhYh2W0yMUTQtrZV1KUutysIb6,nxb|21|31-724-234-4181|2714.50|BUILDING|regular patterns. unusual platelets try to are unusual theod +1076|Customer#000001076|C1gf0FyiU H88P0cpv4UOcdgaPRpVA|10|20-405-710-1902|3509.35|AUTOMOBILE|ainst the silent, silent ideas. sly theodolites use carefully express accounts. regular foxes boost carefully agai +1077|Customer#000001077|sjk1DTHWVMX53kG8AbTtTh1EcMvWeDO8gFDdpQOK|21|31-367-294-4048|8581.78|AUTOMOBILE|lithely regular deposits. carefully pending deposits sleep. quickl +1078|Customer#000001078|ZjRzAz8QbEeIkJxrUI,b|19|29-729-692-6790|70.93|MACHINERY|onic requests wake slyly furiously final attainments. ironic, even accounts cajo +1079|Customer#000001079|cOyd7wsHIQq2LNN|19|29-699-930-2250|2135.91|AUTOMOBILE|ter the express foxes nod slyly excuses. slyly speci +1080|Customer#000001080|Yux,gs14NpneiZEy9Rz|12|22-806-885-5347|3267.19|MACHINERY|ng dolphins cajole across the carefu +1081|Customer#000001081|eGGRjZex7YANvD1jfnPMcBK2JbM|12|22-866-942-1021|8647.42|MACHINERY|pendencies haggle after the quickly special instructions. furio +1082|Customer#000001082|vMX52A1zqDbGNzjfSzgsxSVU0GU6iFmrgiUE|5|15-646-384-2302|3247.92|BUILDING|ly. blithely final packages wake silent ideas. express, special theodo +1083|Customer#000001083|tnrpYmWGxwyaFmJy2Oq0Z|7|17-159-499-3318|3847.29|FURNITURE|luffily. slyly unusual accounts cajole furiously against the ironic asymptotes. slyly reg +1084|Customer#000001084|E091r836A8TPqn5|2|12-378-899-7136|1416.75|FURNITURE|nstructions. fluffily pending pinto beans affix slyly; carefully pending requ +1085|Customer#000001085|pZgtHRGIkUVwiEJLWZXs3KUNi6wLnQzJU1|21|31-831-702-3157|5275.88|BUILDING|he carefully regular courts use special excuses. ironic deposits along the blithely even sauternes nag slyly +1086|Customer#000001086|ECMZrONto2nI2TBv,k|8|18-399-482-6815|9726.83|FURNITURE|ymptotes cajole enticingly furiously silent ideas. furiously pending packages are al +1087|Customer#000001087|ETOH68urIxK839xmKEmfkjc|21|31-334-391-6403|5878.21|MACHINERY|s haggle above the slyly express requests. quickly regular packages after the quickly silent accoun +1088|Customer#000001088|YjXQtOJoM0nhClEy0,WFdNxvJ1g6xpn kL2ommEv|22|32-324-225-2635|2098.62|BUILDING|ly special ideas. slyly unusual requests haggle +1089|Customer#000001089|OO77 pLjaOe7bam1WnH9gtcZNCUlUPI|18|28-164-765-7462|3429.95|BUILDING|o beans affix carefully regular accounts. quickly even ideas sleep. pinto beans haggle fluffy courts. slyly regu +1090|Customer#000001090|P2JDHFVxjU|15|25-711-934-6343|5212.43|AUTOMOBILE|ffily even packages wake quickly +1091|Customer#000001091|4ye7wJ3gU92RZCpwTtDi8Ws,|17|27-336-955-4882|-710.53|BUILDING|y. carefully ironic excuses sleep quickly fluffily even requests. fi +1092|Customer#000001092|,oAq2L60hjb8|15|25-766-175-4580|2004.15|HOUSEHOLD|carefully silent somas can wake carefully aft +1093|Customer#000001093|LO,9qCPIjSXriBqQsAOXLrQKedQ8UO6gb|24|34-931-911-6156|-273.96|HOUSEHOLD|p furiously carefully bold packages. regular escapades breach. blithely unusual ideas integrate across t +1094|Customer#000001094|OFz0eedTmPmXk2 3XM9v9Mcp13NVC0PK|2|12-234-721-9871|2544.49|MACHINERY|tes serve blithely quickly pending foxes. express, quick accounts +1095|Customer#000001095|JtyQvLlCI ZPYQ6ygv,5q|9|19-881-259-2391|6221.26|MACHINERY|foxes. ironic, daring requests sleep regularly across the blithely +1096|Customer#000001096|ldbo6AfnCRjFW8rZnvG6UxbX6o7ISAJRDD7|4|14-368-827-9896|3687.37|FURNITURE|lyly even asymptotes cajole furiously. regular, ironic theodolite +1097|Customer#000001097|a wMc0lQutcHs6cRomoMCGjvM0MwEk4uyrxKI3|6|16-604-758-5574|8651.87|MACHINERY|p carefully. carefully special excuses haggle carefully about th +1098|Customer#000001098|XVJb1HxQeLu9x|22|32-206-732-5183|1009.22|FURNITURE|evenly unusual deposits. slyly even ideas according +1099|Customer#000001099|2ZiU64au LN0 GUxY8|1|11-128-186-5241|8990.07|AUTOMOBILE|ckages: blithely ironic theodolites cajole furiously. f +1100|Customer#000001100|PGXj,,vjAfMNLzd|12|22-880-206-7392|9189.75|BUILDING|ideas. furiously final sheaves integrate. pinto beans haggle slyly according to the furiously ironi +1101|Customer#000001101|h,UOEyoi1ZG4|3|13-528-469-6051|-842.72|MACHINERY|o beans; quickly express accounts slee +1102|Customer#000001102|F9fxZhJJhaR0P4Rgd7SE2PA58x|24|34-103-353-4822|2369.01|HOUSEHOLD|elets. regular requests sleep quickly. express ideas haggle. bold, regular ideas haggle. quickly regular accoun +1103|Customer#000001103|kbYrf d uR|16|26-307-423-8860|4878.10|AUTOMOBILE|n accounts cajole across the even pinto beans. quickly express pat +1104|Customer#000001104|,t,d8FlnmiECPa|8|18-644-507-8095|1230.47|AUTOMOBILE|ages haggle. slyly ironic foxes are idly among the furiously final pearls. slyly unusual reques +1105|Customer#000001105|cZhhOUzv6,Vbaa2bFT|22|32-885-298-6750|9491.46|FURNITURE|y final packages. furiously ironic packages was. fluffily ironic instructions integrate +1106|Customer#000001106|WZEExIU9g2smcowcinj|21|31-214-739-2409|9977.62|HOUSEHOLD|requests nag. fluffily regular packages haggle q +1107|Customer#000001107|yQBP1SLK2uzN4dzgaQ|1|11-720-869-9052|7961.62|AUTOMOBILE| along the final deposits. carefully express ideas wake? quickly regular instructions are furious +1108|Customer#000001108|9sPt6a66R0eCRVYh9QrF8zjxNWFFk8KU|7|17-408-450-8891|4997.35|BUILDING|rding to the final instructions. carefully final accounts wake along the carefully careful pinto beans. re +1109|Customer#000001109|BJCfTYEV9eCDraeyO3v|22|32-194-697-1794|3387.22|FURNITURE|r accounts. bold, final pinto beans wake carefully even Tiresias. quickly busy frays above the blithely ironic de +1110|Customer#000001110|BRnTy8RZ,1oHOg9ly8SsJLIyiuvhv|10|20-777-225-9349|2041.65|HOUSEHOLD|usual platelets along the quickly regul +1111|Customer#000001111|gavpg6eW5lEML|6|16-824-312-3537|2892.21|MACHINERY|s are slyly quiet requests. darin +1112|Customer#000001112|wFf 0nSvdJyk2GqRsqJrcr9 UPr0C3OT5zT|20|30-401-424-6458|9314.59|MACHINERY|fily quickly unusual theodolite +1113|Customer#000001113|jLtKZ0bRJyYL1k|12|22-412-216-1933|7392.30|HOUSEHOLD|ages among the furiously pending packages detect across the blithely unusual accounts. furiously ironic requests sh +1114|Customer#000001114|f7 he8eByBFy6z7vcOajC1gaUKqmRN|14|24-630-988-3843|6446.83|BUILDING|ularly ironic platelets. pinto beans along the slyly express packages wake unusual packa +1115|Customer#000001115|Elvb2a3FinAzxw |5|15-356-145-6356|-178.52|BUILDING|ending instructions thrash blithel +1116|Customer#000001116|aWuLgbu,8HZMbkI|14|24-116-214-4051|592.60|AUTOMOBILE|tes-- final, regular excuses sleep. sly +1117|Customer#000001117|80NfzBRWj5tUUaRdnsFE7Eg|23|33-461-439-5684|2829.07|FURNITURE| ironic deposits need to haggle furiously. furiously bold deposits use among the carefully ironic +1118|Customer#000001118|QHg,DNvEVXaYoCdrywazjAJ|11|21-583-715-8627|4130.18|HOUSEHOLD|y regular requests above the blithely ironic accounts use slyly bold packages: regular pinto beans eat carefully spe +1119|Customer#000001119|ER5vABifV766q5f0FN7l2eN7MIg2lO|20|30-789-716-6850|3971.65|AUTOMOBILE| pinto beans maintain slyly even instructions. regular acc +1120|Customer#000001120|UAG90slCmJS7JOP AhlV12tYD3yUiyB1p2hxZ|2|12-938-579-7156|1543.64|AUTOMOBILE|r theodolites boost. slyly final pinto beans sleep blithely unusual accounts. fluffily even multipliers +1121|Customer#000001121|o2uc3AHYz,m 3vYg8YxBwI0XuG|20|30-197-936-4724|3942.11|MACHINERY|usly? final theodolites are carefully +1122|Customer#000001122|9lxNEW0Rei4DFaT4vX,T551AwBzrZoOXsRNOm|0|10-257-957-3327|45.21|BUILDING|egular, regular instructions are slyly regular requests. deposits despite the regular, pendi +1123|Customer#000001123|pO80QGjK7S0Kmoh46dViD K4OSEVDyiJ53CN|16|26-983-192-5480|9786.36|MACHINERY|s carefully ironic packages. accounts boost boldly fluffily even gifts. slyly final fo +1124|Customer#000001124|EQNw9dNy63,|1|11-709-582-2006|5512.73|BUILDING|ctions wake. packages haggle furiously. express +1125|Customer#000001125|DrHkeaX6wshtuZOI2nLrME|3|13-807-542-3923|8427.55|MACHINERY|counts according to the carefully silent grouches haggl +1126|Customer#000001126|8J bzLWboPqySAWPgHrl4IK4roBvb|8|18-898-994-6389|3905.97|AUTOMOBILE|se carefully asymptotes. unusual accounts use slyly deposits; slyly regular pi +1127|Customer#000001127|nq1w3VhKie4I3ZquEIZuz1 5CWn|10|20-830-875-6204|8631.35|AUTOMOBILE|endencies. express instructions wake about th +1128|Customer#000001128|72XUL0qb4,NLmfyrtzyJlR0eP|0|10-392-200-8982|8123.99|BUILDING|odolites according to the regular courts detect quickly furiously pending foxes? unusual theodolites use p +1129|Customer#000001129|OMEqYv,hhyBAObDjIkoPL03BvuSRw02AuDPVoe|8|18-313-585-9420|6020.02|HOUSEHOLD|pades affix realms. pending courts haggle slowly fluffily final requests. quickly silent deposits are. iro +1130|Customer#000001130|60zzrBpFXjvHzyv0WObH3h8LhYbOaRID58e|22|32-503-721-8203|9519.36|HOUSEHOLD|s requests nag silently carefully special warhorses. special accounts hinder slyly. fluffily enticing +1131|Customer#000001131|KVAvB1lwuN qHWDDPNckenmRGULDFduxYRSBXv|20|30-644-540-9044|6019.10|MACHINERY|er the carefully dogged courts m +1132|Customer#000001132|6dcMOh60XVGcGYyEP|22|32-953-419-6880|4962.12|AUTOMOBILE|ges. final, special requests nag carefully carefully bold deposits. ironic requests boost slyly through th +1133|Customer#000001133|FfA0o cMP02Ylzxtmbq8DCOq|14|24-858-762-2348|5335.36|MACHINERY|g to the pending, ironic pinto beans. furiously blithe packages are fina +1134|Customer#000001134|79TYt94ty a|9|19-832-924-7391|8458.26|HOUSEHOLD|riously across the bold instructions. quickly +1135|Customer#000001135|cONv9cxslXOefPzhUQbGnMeRNKL1x,m2zlVOj|11|21-517-852-3282|3061.78|FURNITURE|regular frays about the bold, regular requests use quickly even pin +1136|Customer#000001136|GHCEiSK0TKsOncuJT3,2zSvlZW4Pz|24|34-440-798-1100|-723.49|FURNITURE|ular pinto beans. slyly special deposits according to the slyly ironic requests maintain quickly +1137|Customer#000001137|LJ3J3i0BlPLrhKi6VabXxNrtpLAGH|16|26-598-565-1269|4210.15|AUTOMOBILE|usly quickly unusual attainments. stealthily unusual requests cajole ironic reques +1138|Customer#000001138|8 9P,dIGWnrrDiVs0S|22|32-236-817-2959|6035.44|BUILDING| instructions cajole thinly ironic requests. regular packages affix. ironic, final pinto beans ac +1139|Customer#000001139|UDGG69rYgUGayNk 9vFytd5q3nZdeRZQNSfL6|22|32-182-662-9475|4604.83|BUILDING|y pending pinto beans haggle blit +1140|Customer#000001140|leG5nToZpjmWNeaOsVv|20|30-331-754-7359|6319.21|AUTOMOBILE| pinto beans. blithely regular packages sleep carefully blithely ironic requests. requests eat blithely aga +1141|Customer#000001141|A6uzuXpgRPp19ek8K8zd5O|22|32-330-618-9020|0.97|MACHINERY| accounts. furiously pending deposits cajole. c +1142|Customer#000001142|b7ytiiX7E9|16|26-191-682-8920|3273.08|AUTOMOBILE|doze slyly. furiously pending deposits cajole fluffily carefully pending packages. boldly regular +1143|Customer#000001143|9tfTGdYHyZXtXbbeboPIXwCT|4|14-568-471-9747|8655.98|AUTOMOBILE|e carefully final packages integrate against the furiously express platelets. ironic ideas wake above the e +1144|Customer#000001144|DGLUWG9evYLNbYhOXVzqZ LdfIMVfBjDf|1|11-336-453-4489|4189.04|BUILDING| ideas. even, regular excuses after the ironic requests cajole blithe +1145|Customer#000001145|6R rPD6SDQPpFuYxxwh,Dv1PeusmP,C6cNcI|2|12-270-756-2968|3249.25|HOUSEHOLD|e. asymptotes sleep fluffily quiet requests. even theodolites among the fluffily regular pinto +1146|Customer#000001146|DRBYvF0iBGsDC3iPNFsPHq3FkU,jCK8LJPX4W|12|22-720-237-1751|4204.36|FURNITURE|final, pending asymptotes. regular requests was +1147|Customer#000001147|AVjlczwVwL CT jO3sgWn|15|25-754-809-7107|7734.64|HOUSEHOLD|eposits. quickly express accounts are idly. slyly final platelets wak +1148|Customer#000001148|7PslyqtS1K2Pabjht 4qgaZ1BbSNFfz6QiK4K|19|29-393-445-2761|7129.84|AUTOMOBILE|c, even deposits. accounts do use. regular accounts haggle blithely special, express courts. blithely +1149|Customer#000001149|5JOAwCy8MD70TUZJDyxgEBMe|3|13-254-242-3889|6287.79|MACHINERY|ress requests haggle carefully across the fluffily regula +1150|Customer#000001150|fUJqzdkQg1|21|31-236-665-8430|-117.31|MACHINERY|usly final dolphins. fluffily bold platelets sleep. slyly unusual attainments lo +1151|Customer#000001151|ratQBQ4rYv TfhWfHe|7|17-948-135-2667|6354.89|BUILDING|l requests. furiously bold orbits after the furiously ironic excuses sleep +1152|Customer#000001152|QRmFl9ZkoBDQ7|12|22-471-341-5516|5680.15|HOUSEHOLD|oost along the quiet, bold foxes. ironic dinos nag fluffily final pinto beans. blithely regular deposit +1153|Customer#000001153|SYG3KMj1fMh7GwvIZ,pY7mGLR1NT6EmNjE|3|13-319-420-5160|6244.03|HOUSEHOLD|s. even packages use fluffily always express packages. regular, even asymptotes about the furiou +1154|Customer#000001154|7RqtNwcSPbaUKaC|19|29-797-132-6916|1498.46|BUILDING|thely. furiously regular accounts above the ironic platelets wake slyly blithely bold pint +1155|Customer#000001155|kEDBn1IQWyHyYjgGGs6FiXfm3|8|18-864-953-3058|3510.25|MACHINERY|ages? fluffily even accounts shall have to boost furiously alongside of the furiously pendin +1156|Customer#000001156|3ShFbt9dTbLOG4lUBvc1AZp0Tam0BNjYS qwTZ|14|24-637-724-1410|1799.67|HOUSEHOLD|ns. carefully regular foxes are quickly. furiously careful accounts accord +1157|Customer#000001157|3rchTZwilGpffMz1MfpnkFfWBtOIdgmvvS1E7sJj|20|30-741-794-9826|6013.09|HOUSEHOLD|equests. deposits cajole quickly slyly spe +1158|Customer#000001158|btAl2dQdvNV9cEzTwVRloTb08sLYKDopV2cK,p|10|20-487-747-8857|3081.79|MACHINERY| theodolites use stealthy asymptotes. frets integrate even instructions. car +1159|Customer#000001159|IAnWq4YFKs7|2|12-269-807-3861|5553.75|HOUSEHOLD|ages sleep fluffily. packages after the carefully express packages nag slyl +1160|Customer#000001160|v65g1aRCGA76ZHySoOBffL31n4vJ0nm,tK,UEA|24|34-103-942-4634|4976.24|AUTOMOBILE| pending, special packages against the blithely unusual packages eat quic +1161|Customer#000001161| QD7s2P6QpCC6g9t2aVzKg7y|19|29-213-663-3342|591.31|MACHINERY|ly alongside of the quickly blithe ideas. quickly ironic accounts haggle regul +1162|Customer#000001162|b5N12h9D6yJemoVx6OQf0uL|2|12-887-115-9986|3139.71|AUTOMOBILE|refully furious packages. furiously ironic ideas against the carefull +1163|Customer#000001163|54fBdElRYOjEH8S|2|12-204-803-1483|90.22|BUILDING|inments. carefully regular instructions haggle carefully slow packages. slyly even packages kindle blithely special +1164|Customer#000001164|XWfNRnO2S5KAW0VodNwaBDixCEtv nKzt2LVFiwm|0|10-828-178-5049|7341.35|HOUSEHOLD| ideas use. unusual packages sleep +1165|Customer#000001165|h7KTXGSqsn0|9|19-766-409-6769|8177.33|MACHINERY|jole slyly beside the quickly final accounts. silent, even requests are stealthily ironic, re +1166|Customer#000001166|W4FAGNPKcJFebzldtNp8SehhH3|17|27-869-223-7506|507.26|MACHINERY| before the platelets! carefully bold ideas lose carefully +1167|Customer#000001167|gNYGOcGkJu3ooSmsCh|19|29-721-479-1548|9510.87|FURNITURE|lly regular ideas grow furiously regular accounts. regular, special requests sleep blithely. slyly bold pla +1168|Customer#000001168|gmAnpwPPg0LX4|17|27-608-883-2632|6194.65|FURNITURE|ses run according to the regular instructions. slyly regular foxes around the furiously ironic theodolites use fl +1169|Customer#000001169|04YQNIYyRRFxUnJsTP36da|4|14-975-169-9356|7503.30|MACHINERY|into beans doubt about the slyly ironic multipliers. carefully regular requests breach theodolites. special packages +1170|Customer#000001170|BNhssVcV36vshEHUAc aPFJ|8|18-670-628-8499|2070.73|HOUSEHOLD|ronic instructions. express pinto beans poach blithely. quickly ironic accounts n +1171|Customer#000001171|GatOC LsLU9MkgyaNMYH|8|18-457-394-2863|7658.97|HOUSEHOLD|c dolphins. accounts are slyl +1172|Customer#000001172|r dreL8m8cRaiIz IqZ83oMo,AVxe2PbsHQzK|14|24-249-588-1969|420.97|FURNITURE|express asymptotes haggle furiously. fluffily special deposits haggle quietly even, special tithes. ironic foxes alo +1173|Customer#000001173|6Abj72jR5Z0GYQMZKBmiQxW|18|28-409-365-6392|182.59|FURNITURE| ironic accounts above the ironic excuses haggle fluffily furiously regular packages-- slyly regular gi +1174|Customer#000001174| b9zecNS,J97qi7Qk5|4|14-131-930-7154|8798.96|AUTOMOBILE| ironic packages. furiously regular excuses sleep about the fluffily unusual pinto beans? regular foxes kind +1175|Customer#000001175|olj7nLYgBZ526MNBg9CV7w LYo6F1uD,Hm54|4|14-756-259-6379|9207.16|FURNITURE| haggle pending requests. carefully regular ideas nag. ruthlessly final packages a +1176|Customer#000001176|V0xc0tXNMmObuUJ0rGARp6YIw4fo84CD|10|20-141-903-5936|5827.59|BUILDING|ven accounts boost after the accounts. slyly silent accounts use fluffily amon +1177|Customer#000001177|hZPNQ8a9QRM ,SYdTdoW9hw|14|24-200-701-8606|9281.72|FURNITURE|ng the quickly bold theodolites cajole carefully around the deposits. furi +1178|Customer#000001178|W,03Nl2iWQ94xYyCo3R8CTMNFhu|9|19-717-739-3103|4966.58|HOUSEHOLD| even requests cajole furiously after the quickly ironic accounts. even re +1179|Customer#000001179|JLtS3n1xDqnNFS5MZc5uZHOjDctAJEl|19|29-311-833-9211|3336.25|AUTOMOBILE|ress, special accounts sleep slyly about the carefully express packages. f +1180|Customer#000001180|jI4QtviiCs0,LOgUPH4aONMnoNt|13|23-188-767-6645|3367.36|BUILDING|uests poach carefully carefully final deposits: ironic, regular deposits are slyly busy excuses. regular +1181|Customer#000001181|ZFFYipzTg0vSjOhPbcBUgPK9se|10|20-330-305-8843|9180.50|AUTOMOBILE|gle about the busily special theodolites. furiously ironic deposits haggle beside the furiously special accounts. +1182|Customer#000001182|pLrF7F1,uoyGaU|6|16-229-473-7194|8814.39|AUTOMOBILE|jole carefully. furiously final pinto beans detect. f +1183|Customer#000001183|qdIqRUfpmvtWo0NGsyi4qyjkwzlImP9,NrSC|1|11-968-244-9275|4455.76|BUILDING|arefully regular dependencies. quick +1184|Customer#000001184|M0dd3R30k0YjIr4GVeo|11|21-661-875-1923|9032.89|BUILDING| excuses nag carefully even accounts. unusual platelets detect carefully bold acco +1185|Customer#000001185|z,dN83fETWpkJkoR|14|24-860-751-6688|2913.52|BUILDING|ndencies against the carefully even accounts cajole carefully quickly regular packages. even fox +1186|Customer#000001186|cj5EeLbJJ6MPdynzposq,Apbj9 2Jm|23|33-500-965-3385|4466.30|BUILDING|ding realms cajole after the even foxes +1187|Customer#000001187|W1GdUKr3vQMVAZIU|10|20-543-260-5157|-932.96|AUTOMOBILE| blithely unusual theodolites detect doggedly. bold dolphins was blithely. pinto beans use carefully at the furiou +1188|Customer#000001188|PtwoF3jNQ9r6 GbPIelt GvbNBuDH|15|25-108-989-8154|3698.86|MACHINERY|ts. quickly unusual ideas affix aft +1189|Customer#000001189|rbnZCbJSTE3qWLl|10|20-746-804-1553|3798.28|HOUSEHOLD|enticingly express platelets wake. regular requests boost even, regular instructions. express dependencies a +1190|Customer#000001190|JwzW9OtxFRXDnVo5hXl8 2A5VxH12|15|25-538-604-9042|2743.63|MACHINERY| regular deposits according to the pending packages wake blithely among the silent inst +1191|Customer#000001191|K9J7dhIXDB2kgubtIVdRC6RP0aF,GQXin|19|29-587-244-2901|9088.54|AUTOMOBILE|ts wake. waters detect fluffily carefully regu +1192|Customer#000001192|8DbtM3KloBZ4OO1dRrF99|20|30-904-936-4914|3231.33|BUILDING|efully final packages use. slyly pend +1193|Customer#000001193|gdKqrIp,yaMaQSFerrGGzc6Kpy|8|18-524-487-2547|-17.10|AUTOMOBILE|accounts sleep carefully. regular accounts wake slyly. carefully regular requests along the quickly pend +1194|Customer#000001194|NzWKbiPK1oFd7PNz|21|31-155-275-3981|7582.29|FURNITURE|lve quickly according to the carefully regu +1195|Customer#000001195|71mmXvaWKf|4|14-355-801-7486|9621.49|FURNITURE|l, regular gifts should have to x-ray blithely fluffily ironic +1196|Customer#000001196|S3sw3q SDWVuUoEFvwv9M|20|30-615-967-7758|6378.67|BUILDING| carefully alongside of the blithely even theodolites. carefully ironic instructions wake after the spec +1197|Customer#000001197|9A1LTDf0KbR|0|10-254-891-7835|9261.05|FURNITURE|ording to the slyly ironic accounts. carefully final instructions haggle. special, unusual foxes haggle enticing +1198|Customer#000001198|r0liwpMwaIBQ9 zQjojGylXkJuKUL|18|28-278-515-1034|9593.35|AUTOMOBILE|intain fluffily ironic instructions. regular requests nag fluffily carefully unu +1199|Customer#000001199|sQJZJRAgYrZY0gPo9fJp6KAbY|16|26-367-212-1737|6503.35|AUTOMOBILE|es. quickly slow foxes boost +1200|Customer#000001200|2PFysvL4pk80l|22|32-890-210-4199|3765.05|HOUSEHOLD|nent frets. blithely bold pearls thrash across the r +1201|Customer#000001201|LfCSVKWozyWOGDW02g9UX,XgH5YU2o5ql1zBrN|10|20-825-400-1187|5165.39|BUILDING|lyly pending packages. special requests sleep-- platelets use blithely after the instructions. sometimes even id +1202|Customer#000001202|xThQDiKdG,0sU IduCCPAgHJfx1PDJwtUQvfU|0|10-788-256-6117|702.73|BUILDING|accounts. fluffily regular requests are. packages among the final deposits haggle carefully arou +1203|Customer#000001203|9pTq4gggfKoSqQetn0yJR|16|26-370-660-6154|5787.69|MACHINERY|osits nag furiously final accounts. silent pack +1204|Customer#000001204|QxpCVhq2x0PwW,zgZ AEuFkgb50ryGM|20|30-117-472-8751|9777.19|HOUSEHOLD|ily final instructions. pending foxes detect doggedly accor +1205|Customer#000001205|1ALD7GN4Iw0Vl5toeM|8|18-185-307-2678|5390.34|HOUSEHOLD|ptotes. silent deposits above the bold warhorses boost +1206|Customer#000001206|dxzjW0gykcG2kJ gN8hZV02q6U5T6uVNfP|20|30-716-117-6066|8437.76|HOUSEHOLD|ng the ironic accounts. regular requests across the quickly bold deposits wake carefully across the +1207|Customer#000001207|tDZe2FlIxGjrf9x,n6N1tu0DbWyUkSSu|3|13-572-474-7362|-556.05|AUTOMOBILE|uriously by the slyly regular packages. fluffily final deposits across the quickly express epitaphs us +1208|Customer#000001208|M uLSFG6IrQkKQxrH5vCbPjglIpB3JC|5|15-789-973-6601|2426.52|BUILDING| blithely bold dependencies detect slyly. carefully silent platelets haggle along the pinto beans +1209|Customer#000001209|PW00geNpQOiug6dftXfBkpwdAfsmRYsve,b44uR8|4|14-664-771-9006|3551.21|HOUSEHOLD|unts. regular dolphins integrate slyly. regular, pending accounts sleep b +1210|Customer#000001210|bUTLW1KIHzzQkuOEwUMwEGCQfTQM7aBmUM0|16|26-202-315-9048|8137.66|AUTOMOBILE|luffily ironic accounts haggle about the regular theod +1211|Customer#000001211|HCACb3Al89h6NqHUJ8qIjhfGFyA4S0c2|18|28-280-785-7324|4723.37|HOUSEHOLD|posits. packages affix carefully after the carefully +1212|Customer#000001212|kjiVLfadsq6sU3A6MYwySu XZnWzgkiWSa9v3K 6|22|32-462-274-7707|7736.03|HOUSEHOLD|e quickly unusual pinto beans. packages need to sleep furiously. regular asymptotes are furiously. final packages +1213|Customer#000001213|4ATLYSTcqLfgAJLxL7U|7|17-548-151-7684|8555.12|HOUSEHOLD|ong the deposits. quickly express deposit +1214|Customer#000001214|EATpN6m rGunAAkWFNSpsqy|4|14-281-851-2904|2935.31|BUILDING|carefully across the carefully ironic asympto +1215|Customer#000001215|oAvLu8VcRg9FNS9sNmoqU9|16|26-405-743-5405|7795.87|MACHINERY|special packages against the slyly final pinto beans wake slyly furiously final +1216|Customer#000001216|CSf1BbFhJhucmvftOwYLQACMEqgXj|3|13-673-633-4561|2155.06|AUTOMOBILE|eposits. slyly ironic dependencies haggle quickly. slyly close orbits above +1217|Customer#000001217|ddk4YC7lmTM,Z3LbX|12|22-191-580-2887|6019.32|FURNITURE|ar instructions. furiously pending +1218|Customer#000001218|JYNvUpFG0dDy7aJNhl2zLyIxUGqZZ35ncUe|22|32-299-871-1751|8801.73|AUTOMOBILE|packages hang against the unusual, unusual accounts +1219|Customer#000001219|kP1xK5be a8tW5JRSq0nwJWgKbO|4|14-364-661-8744|774.23|FURNITURE| the quickly even packages wake fur +1220|Customer#000001220|tbyect2HMX47TzsKy5 ho5|18|28-379-869-1009|8429.33|FURNITURE|sual multipliers. furiously unusual theodolites are. +1221|Customer#000001221|4mmeiymVdRmz|22|32-185-876-3586|816.50|FURNITURE|express, bold pinto beans. packages would detect alongside of the quickly bold +1222|Customer#000001222|hn6SzlP4Dq8F89iOXH0tjIgsz0uBCiBM|11|21-709-519-4959|3883.18|AUTOMOBILE|riously special theodolites nag slyly. slyly special ideas sublate quickly across the slyly un +1223|Customer#000001223|,I0bRfCGE5ssaX4V3|11|21-659-745-8411|-413.03|BUILDING|oxes. bold foxes detect always furiously special platelets. fluffily bold depende +1224|Customer#000001224|PWOwgZKsBoFJQ7py4HJpdJoSO2,|8|18-794-312-9970|8124.15|HOUSEHOLD| furiously regular accounts. slyly regular +1225|Customer#000001225|CgaNokxe s|11|21-839-103-4411|8634.92|MACHINERY|elets. bold packages use blithely special foxes. quick +1226|Customer#000001226|HKR1zog fXW|0|10-251-221-9440|2135.92|FURNITURE|ns. furiously pending packages hinder special accounts. sl +1227|Customer#000001227|GiT5IrOJ1zJTZErbFt1Jy6Gj|23|33-468-642-3107|3335.72|FURNITURE|fily atop the bold, unusual theo +1228|Customer#000001228|fV,ZM6pj1nivvbnfseVaWRkB0UYwKgvv|12|22-778-955-6105|5392.30|AUTOMOBILE|s according to the carefully final ideas ha +1229|Customer#000001229|csvrfGKxtX|9|19-313-452-6076|8328.12|FURNITURE| instructions sleep. carefully regular accounts use furiously. ironic, even foxes wake: busily even deposits caj +1230|Customer#000001230|Pr7yxcRne6NiloD1oR,d28rwVFRnOoTWeYq9|23|33-786-129-3407|4787.85|MACHINERY|ackages cajole furiously quickly pending packages. ironic foxes +1231|Customer#000001231|qJWtxdKmKWcR5XgMDn|9|19-316-348-3289|2326.68|AUTOMOBILE|uickly regular foxes are after t +1232|Customer#000001232|yYXdTto04oLlk04SM|18|28-518-320-7417|8482.51|MACHINERY|. even deposits lose above the even, regular +1233|Customer#000001233|KdmXav1IIIo|15|25-522-912-6255|3649.49|MACHINERY|ymptotes according to the ironic deposits use around the reg +1234|Customer#000001234|B3OhbH0MRJE,F0Lc7Jq0Ttv3|1|11-742-434-6436|-982.32|FURNITURE|y ironic instructions are quickly about the slyly silent pinto beans. quickly final dependenci +1235|Customer#000001235|q 1E JKZqhvUzj48|24|34-549-333-8551|-982.05|BUILDING|ckly. furiously quick dependencie +1236|Customer#000001236|pTEEPYlnQBzi558CN7LJ5UTdvO|11|21-699-526-9355|3600.95|MACHINERY|, pending excuses wake slyly pending accounts. asymptotes wake fluffily against the ironic, bold pack +1237|Customer#000001237| CQEeqR ,cVU7Bby|20|30-415-666-7691|8156.62|BUILDING|the bold accounts wake blithely across the deposits +1238|Customer#000001238|HGCJI27,RIIQcS20,DcJbMQuUmN3Vhzdm|6|16-302-171-7578|4299.22|BUILDING|ly special requests. unusual, special asymptotes according to the blithely express pinto beans wake en +1239|Customer#000001239|,K7wNII9jhC ,|20|30-786-518-4678|6936.72|FURNITURE| are alongside of the requests. s +1240|Customer#000001240|XbvhyAXRkuujtESRmxeD9eQpYSkiCa|4|14-650-555-5310|5439.44|FURNITURE|ans above the slyly regular ideas cajole furiously across the regular, regular decoys. furiously final asymptotes s +1241|Customer#000001241|74mW8ipfvoVPR3PS|3|13-902-876-1609|8654.56|HOUSEHOLD|ructions affix against the evenly ironic packages. slyly regular accounts run carefully. accounts accor +1242|Customer#000001242|mA8bUqB6WqNEe2nsQXlaHqMqaACj|2|12-521-364-1211|2276.15|BUILDING| regular ideas cajole! blithely express excuses b +1243|Customer#000001243|g,qSvyYkgjDcCL cxx5qy8hAwhomRq9cYJRvXZ6|14|24-445-165-9851|6271.38|MACHINERY|s, regular packages through the carefully ruthless theodolites promise quickly blithely final pinto be +1244|Customer#000001244|I3DrbiKwP3dxs1jF0iDwXh|5|15-881-433-2257|-942.80|BUILDING|old deposits alongside of the packages are +1245|Customer#000001245| xLnSgzY70qTKPF753|4|14-500-764-3702|3196.66|FURNITURE|haggle slyly at the carefully pending excuses. slyly pending theodolites use re +1246|Customer#000001246|acguUq5BISzqjHB7Bt|4|14-882-141-9354|260.71|BUILDING|haggle furiously. blithely regular patterns sleep quickly slyly even +1247|Customer#000001247|q5,Og3ezW3jSUtbwK 6qLJPqPwCwdL|0|10-386-173-3167|1696.95|MACHINERY|s against the quickly unusual ideas are blithely packages. accounts sleep quickly. regular +1248|Customer#000001248|f0X68bItSl|8|18-692-669-1536|6539.15|AUTOMOBILE|theodolites for the unusual deposits cajole fluffily final patterns. caref +1249|Customer#000001249|x9ukZnNiUM5pBPXyE3epagewVQBPZzxGYD6sMH|7|17-866-269-1165|448.49|BUILDING| the ironic packages sleep carefully express theodolites. even, final deposits across the even deposits nag after t +1250|Customer#000001250|LBPszo9EVA88sbbdYl7E,MVm7UvoBjmjr|9|19-509-608-4350|780.05|AUTOMOBILE|und the fluffily bold requests. silent, final theodolites solve furiou +1251|Customer#000001251|4AjU4c4D4AMLwQx,lAJGwBIgmT7oSZwYUv0es3J|24|34-741-256-6399|7267.76|MACHINERY|ckly regular accounts affix slyly carefully unusual +1252|Customer#000001252|u2OUDBxaayX4WhrftcM,|12|22-604-782-7617|3279.84|MACHINERY|eans might impress about the bold requests. bl +1253|Customer#000001253|2rEfA2LR6LkUXjoMxIsv58YSHPMjlqr1YXhHSX|1|11-900-587-2067|1222.21|BUILDING|efully regular deposits. bravely ironi +1254|Customer#000001254|wdGz5Cm DrSdF|18|28-832-851-4673|2676.06|HOUSEHOLD|wind fluffily blithely regular pac +1255|Customer#000001255|UC6I32JjBU62t4WgDe e2pDYbuM3VAt4MPM|14|24-359-633-2713|6487.71|FURNITURE|s deposits sleep. blithely ironic dependencies wake. blithely even theodolites sleep. blithely +1256|Customer#000001256|sNx4HcJ35paZik,IN02G7p|15|25-306-342-4782|5012.07|MACHINERY|integrate carefully. blithely e +1257|Customer#000001257|kX6yufw5dfKrgwQPVwWE7|2|12-824-451-8526|8810.83|HOUSEHOLD|hins. furiously unusual foxes about the regular foxes wake blithel +1258|Customer#000001258|zK3TKgKVuFCBdjt|3|13-727-588-7092|-301.75|AUTOMOBILE|ove the carefully ironic asymptotes. quickly final Tiresias wake regular packages. s +1259|Customer#000001259| YQc2RRQJV7kl1zxWg4OiUVU 5GlpB|20|30-930-620-7210|8353.00|HOUSEHOLD|ages sleep blithely regular, final +1260|Customer#000001260|npdrgr5Yqp0znvQt,Cw07j4BS22RNIANcb3t|2|12-742-408-2980|4991.59|MACHINERY|kly express theodolites sleep blithely across the doggedly regular packages. final, unusual instruc +1261|Customer#000001261|mWs6m9QwmTOZ|20|30-372-895-4261|5579.81|BUILDING|uffily final pinto beans. ironic deposits according to th +1262|Customer#000001262|u39WRGDI6AKU|3|13-444-583-3984|2840.36|MACHINERY| final accounts sleep slyly Tiresias. packages are furiously idle platelets. slyly silent requests are acr +1263|Customer#000001263|MXA4v0xQ9Kt |9|19-690-614-5736|6975.90|MACHINERY|ress dependencies are carefully theodolites. blithely ironic foxes among the slyly bold packages sleep blith +1264|Customer#000001264|vC1Yg5q O9 Tt5SM7OF|16|26-617-707-6647|3959.28|MACHINERY|y, regular requests above the fluffily special deposits engage around the furiously +1265|Customer#000001265|CTbTIB ZTYyKUSY42Ksz F33fxKsSG|24|34-945-256-3226|2653.53|MACHINERY|yly pending deposits about the regular accounts pri +1266|Customer#000001266|LW7shrnoCLUjJKQI8EF7SIFofvvIUmiJzpdS|3|13-832-768-3873|1877.05|MACHINERY|egular ideas. blithely regular requests above the deposits unwind on the slyly dogged pinto +1267|Customer#000001267|o3dtauyIeWwFRok2whWam0MLjmOdlG1H|24|34-329-328-2500|8616.12|BUILDING| accounts nag fluffily blithely ironic pinto beans. carefully pending deposits dazzle along +1268|Customer#000001268|SHn6HpO2VXBw3RJFPxjQFGanrsndRwRR2LWdm|24|34-973-735-5374|5152.42|BUILDING|y pending accounts! blithely unusual ideas wake alongside of the regular, f +1269|Customer#000001269|j2hwJHCMprK8HQdK7DpeUx5SG8j4dfuNR|10|20-818-485-8060|2659.68|BUILDING|promise slyly against the carefully ironic deposits. fluffily unusual foxes cajole carefully +1270|Customer#000001270|HPcuKCEtUzP3np7 oDR|13|23-473-283-1422|6170.06|MACHINERY|oost along the unusual, permanent pinto beans. even packages integrate slyly according to the pendin +1271|Customer#000001271|S7fmHdkot3JAv|14|24-698-342-2768|1209.37|HOUSEHOLD|efully after the slyly regular accounts. carefully ironic theo +1272|Customer#000001272|hzMO9cmypW|21|31-659-617-1632|6865.14|FURNITURE|symptotes. carefully regular requests after the pending ideas affix fu +1273|Customer#000001273|6RglRQdIV9mF8Tn6ABFmSQl|12|22-594-567-9307|1499.56|AUTOMOBILE|t final packages. furiously unus +1274|Customer#000001274|eHJnE7ytBm|24|34-152-721-6307|126.97|AUTOMOBILE|nts are enticingly above the furiously +1275|Customer#000001275|KUtV3oFy2Kyuzs4zT DB,S|20|30-410-174-2034|8972.46|MACHINERY|uternes. blithely express accounts detect around the fluffily even theodolites. even, spe +1276|Customer#000001276|c5UAVe71MPvmerPafNlpvTBWCewT|16|26-809-582-2064|-761.70|AUTOMOBILE| the blithely regular packages boost blithely regular excuses. final dep +1277|Customer#000001277|2ETOoQWtvxqp|14|24-502-746-4128|-52.35|BUILDING|oss the packages. packages doze car +1278|Customer#000001278|OB JBXz5fghXsYEaClW8PZpDmxMVZct|5|15-253-270-5149|9038.43|HOUSEHOLD|foxes. even, special theodolites boost. furiously silent packages haggle? furiously +1279|Customer#000001279|fkrzLacsqCnwUwgjjttKmY|14|24-742-587-6985|7915.06|BUILDING|tes are. ideas above the carefully ironic d +1280|Customer#000001280|3AmBFWaqOYt7F|16|26-725-573-7255|3419.66|HOUSEHOLD|eodolites sleep according to the theodolites. slyly pending dolphins among the pending, express platel +1281|Customer#000001281|pekyJqzeIQKGO8TeLvXgH8HR|11|21-124-963-7614|8182.42|AUTOMOBILE|the furiously quick deposits. slyly regul +1282|Customer#000001282|qeYHABkf21,5C5OC5it6q|14|24-750-627-7414|8998.82|FURNITURE| even deposits sleep quickly regular +1283|Customer#000001283|6JeLWEtDERPB,0KzWB,I6Xs8rJXAC8ryFulW5NPC|0|10-203-771-2219|2222.71|AUTOMOBILE| blithely daringly final theodolites. foxes ha +1284|Customer#000001284|sdj PCsILD6mOJfEuIIbrN52hOHTYWwUUPT|18|28-750-346-1442|-911.40|BUILDING|pending packages cajole carefully! furiously final packages wake. special requests sleep along the caref +1285|Customer#000001285|5Hy,ajDzJPtZFeJedRSeLN7XGOJtyUy2FI93|19|29-424-835-1463|3061.58|HOUSEHOLD|ly bold ideas affix blithely about the slyly even pinto beans. slyly regular multip +1286|Customer#000001286|FP3aFvhRMSKfCz3l0h|12|22-374-932-9860|6906.08|MACHINERY|quests. quickly even packages wak +1287|Customer#000001287|8CaksGsCJOK3oUm1kUsQ|15|25-493-734-3918|7461.69|MACHINERY|e quickly silent courts. furiously even packages among the ironic ideas integrate slyl +1288|Customer#000001288|wQDTTCkSGxic2d66|3|13-533-256-9320|6603.43|HOUSEHOLD|equests detect atop the ironic deposits. final requests according to the blithely sp +1289|Customer#000001289|OGb4YMkool8QMr|24|34-409-591-4324|2925.52|MACHINERY|deas haggle carefully alongside of the always even ideas. never unusual as +1290|Customer#000001290|0Q9URl0Y3rJWt9GYZF|24|34-837-161-2672|8108.42|MACHINERY|s use across the express requests-- carefully bold foxes cajole slyly slyly express pinto beans. ironic request +1291|Customer#000001291|dg3hkdHiI9zqk7l3242Q28OLLFy,1vZ,|7|17-693-294-2656|8227.37|BUILDING|, final requests-- furiously careful ideas wake busily ironic, even a +1292|Customer#000001292|QVr2XTDOMzWcLKHtNgrLK|21|31-966-407-1575|5509.11|BUILDING|haggle. special foxes sleep blithely +1293|Customer#000001293|E79dBMCNl5xXBwtnSsjuBLa16VgrLsKz|12|22-517-223-6566|2565.67|HOUSEHOLD|heodolites boost blithely ironic packages. special, even ideas above the asymptotes wake quickly accordin +1294|Customer#000001294|EZVIKislr4L0PrBP8LShL|23|33-506-204-7796|-808.13|AUTOMOBILE|deas boost bravely final ideas. slyly even pearls are furiously +1295|Customer#000001295|kded3b,5e5|24|34-259-484-2624|753.62|BUILDING|slyly final accounts detect blithely regular, bold requests-- blithely final foxes wake blithel +1296|Customer#000001296|cLAyTJcfD3T4hKW52lIU9yk|5|15-130-485-4234|3034.69|MACHINERY|e slyly ironic requests. final requests +1297|Customer#000001297|4QnYEe0KXOP3yridKldXROs7jQdMu9tE|21|31-579-682-9907|6074.01|HOUSEHOLD| pinto beans! furiously regular courts ea +1298|Customer#000001298|ujAPYPBrLW,oIxGpuWmxoTDscSXFOP Tjk|15|25-765-244-1549|3903.54|AUTOMOBILE|er furiously despite the ironic, even ideas. slyly silent ideas boost +1299|Customer#000001299|vm2THnXrMKrn5xvPL88EMT9QntU|11|21-150-179-4763|808.39|HOUSEHOLD|sheaves promise furiously alongside of the slyly pending platelets. pending dolphins at the furi +1300|Customer#000001300|VmW1dNLVaQY0ud6Csa5WHWuV8|23|33-581-399-6027|-370.44|BUILDING| x-ray furiously regular deposits. final, silent theodolites are slyly pending ideas. final dependencies +1301|Customer#000001301|oR0kHfL6GWhF VPD,mM1Jxsd9l3nZEkfDn|10|20-339-347-9046|8966.63|MACHINERY|egular asymptotes along the even, express packages sleep express realms; carefully final packages haggle quickly +1302|Customer#000001302|vyImQ4AVgv,Rn|9|19-316-212-9313|197.90|MACHINERY| platelets engage carefully! furiously express ideas shall have to use. regular +1303|Customer#000001303|MarfB1lCCs2MZ8CWdWqCfb|5|15-658-234-7985|2020.15|MACHINERY|express deposits haggle slyly after the carefully unusual packages-- silently si +1304|Customer#000001304|1sXtodRtFvBd449a2aJ|11|21-638-815-3982|4548.46|AUTOMOBILE|orses boost blithely platelets. fur +1305|Customer#000001305|xHgwqc1p0eLf5F8JkE7zvYXPHhIOP5IgLRJgR|23|33-396-634-9150|4900.66|MACHINERY|efully. furiously ironic packages cajole slyly bold requests. quickly ruthless requests alongside of the iro +1306|Customer#000001306|0YRFIqAc5imIKGi9cEYtn6L|12|22-923-551-9639|6464.77|MACHINERY|le. quickly pending accounts detect furiously. packages +1307|Customer#000001307|L OAVSFQauP87kLdHouM8|3|13-970-299-8199|4344.52|MACHINERY|ts. brave, express packages boost. even, pending instructions nag blithely regular theodolite +1308|Customer#000001308|Ndovi7D9gJ u1gjQwYOkIARup6VzhQFCHHmSMw|18|28-560-833-2066|9290.53|MACHINERY|uickly even dependencies. unus +1309|Customer#000001309|xaOhk73bjekYrVc5zZ36c,GuZUxsMHjo7WH9WVe|10|20-821-905-5952|-922.69|AUTOMOBILE|nusual excuses. ironic deposits are furiously ironic frays. blithely ironic platelets are evenly regular package +1310|Customer#000001310|bN, XpseFnbjZRh3fryWogaudZB|17|27-538-338-3378|204.84|HOUSEHOLD|unts. silently bold ideas against the blithely regular deposits use furiously ironic fo +1311|Customer#000001311|rcff2L75vK5EOUaPK DiDz6atB|13|23-647-279-5735|8713.24|FURNITURE|nd the regularly unusual foxes. regular asympto +1312|Customer#000001312|f5zgMB4MHLMSHaX0tDduHAmVd4|3|13-153-492-9898|9459.50|BUILDING|odolites wake always packages. slyly slow orbits lose. regular depo +1313|Customer#000001313|Ax4TI4jbHvaYUaaFuEUQTiMWQvrjez G|23|33-623-834-3089|889.11|MACHINERY|ely. carefully pending foxes was furiously special, special +1314|Customer#000001314|auN4t99aykk1AlmJl|1|11-290-301-2722|3218.33|HOUSEHOLD|e special theodolites haggle furiously along the even deposits. final accounts haggle. furious +1315|Customer#000001315|5J941XxxkE|10|20-941-614-6433|1447.84|AUTOMOBILE|refully bold packages. final, regular pa +1316|Customer#000001316|nmbpR1rqOdlUDvT6C HXUhm2|5|15-642-801-1329|-158.39|BUILDING| might wake. sometimes unusual requests cajole carefully about the excuses. stealthily final requests wake quick +1317|Customer#000001317|a6M1wdC44LW|14|24-518-294-8197|8925.08|AUTOMOBILE|s haggle furiously slyly final accounts. slyly bold pac +1318|Customer#000001318|yrASJAqw67PQxFYVAVsGU|14|24-524-279-4270|5812.93|BUILDING|lyly blithely final depths. regularly even accounts haggle across the carefu +1319|Customer#000001319|c5M1KcH60UZPYsa|9|19-573-345-3305|4910.48|MACHINERY|se across the dependencies. express, +1320|Customer#000001320|8gman6hzpuKUsX7mKU9katXpP1ia|15|25-116-108-3791|6407.13|MACHINERY|lent, final accounts cajole fluffily special requests. deposits around the fluffily even packages +1321|Customer#000001321|dWd3MhPQY3|10|20-571-787-3958|3589.49|FURNITURE|express foxes are quickly blithely bold +1322|Customer#000001322|35jI39rgIHCI4Pwvpy1beKgL0|13|23-207-256-7245|2621.71|FURNITURE|tes cajole. blithely express request +1323|Customer#000001323|r9R6okXwQID,|23|33-476-768-7390|6006.81|HOUSEHOLD|uffily even packages. dependencies are. excuses cajole furiously regular foxes. special dep +1324|Customer#000001324|6qS1ZDpAYr9aED9Yh ggf8ACJcPi7sp|7|17-415-957-9976|7548.88|AUTOMOBILE|t the busy courts sleep quietly above the ideas. final accounts after the regular, ironic pl +1325|Customer#000001325|Agu uZvi6Xv77 nE7W8|7|17-687-303-1074|9108.61|HOUSEHOLD|n foxes integrate furiously ironic requests. furiously even theodolites use daringly pending deposits; even pl +1326|Customer#000001326|naLuK8XKUP72msE0e|21|31-373-307-4091|-468.49|HOUSEHOLD| pending accounts impress. regular, express accounts cajole ironically express deposits. slyly regular accoun +1327|Customer#000001327|LBVMBxjllZpTQd|12|22-920-576-6295|0.97|MACHINERY| are furiously according to the multipliers. pinto beans are thinly. special deposits haggle quickly express Ti +1328|Customer#000001328|fjKlKFyxTQRJjLeT1Md|10|20-305-428-9878|3264.99|AUTOMOBILE| deposits haggle ironic, bold packages. quickly unusual packages print furiously care +1329|Customer#000001329|Q3 pefFAcrEYPQ6J AC|17|27-945-826-8003|4645.91|BUILDING|quickly silent requests affix blithely slyly bold instructions. furiously even packages dazzle whith +1330|Customer#000001330|MGY4P7QIy3|1|11-353-524-1234|3893.14|BUILDING|to beans doze along the furiously final pinto beans. req +1331|Customer#000001331|mjaArHGsPWg|8|18-140-389-1328|2005.02|BUILDING|ic excuses. requests would promise according to the furiously ironic accounts. slyly final deposi +1332|Customer#000001332|1JMz4nbClfcxmzPyWyJK|18|28-560-351-6594|3323.04|FURNITURE|ing forges. foxes haggle fluffily. express, final excuses sleep slyly blithely express dependencies. +1333|Customer#000001333|o9o6lky2KYgFZ2cSx5lyFQYufM1i1d|2|12-154-975-6824|1330.85|AUTOMOBILE|beans integrate fluffily. carefully final pinto beans wake furiously even pint +1334|Customer#000001334|gZkxQY2Aa3o D6f1O 7nsPdg6BJ3|5|15-493-800-1041|2485.71|BUILDING| unusual dependencies cajole regular, r +1335|Customer#000001335|VeQAJlVqZgl0adTxSpZ6P2ZVIC0kWokJ|10|20-744-779-7057|8341.67|BUILDING|t slyly accounts. slyly express pinto beans nag. +1336|Customer#000001336|E4MeTLnSTIOlWkLDwmG7QPf 9Dq|16|26-350-110-5043|1490.21|AUTOMOBILE|ts after the deposits are quickly deposits! blithely regular theodolites integrate above the slyly pending +1337|Customer#000001337|ACAMJe2Xdw2BCgHrGMd0BX|22|32-528-594-1931|7882.44|MACHINERY|n, express gifts. express, fluffy pinto beans sleep. regula +1338|Customer#000001338|8Nx5v3cKF MK3ejHdMUgcY,FNZZs1|20|30-763-866-5779|5139.00|BUILDING|te quickly above the regular packages. thinly re +1339|Customer#000001339|QGiiQ1iMDmLKLAHsZa L68gZFyPXX18a38IS|4|14-904-963-2452|8167.50|MACHINERY|neath the carefully unusual plat +1340|Customer#000001340|dYRQ2tz0OdH|21|31-872-435-1900|280.29|HOUSEHOLD|against the final theodolites. slyly regular dependencies after the bo +1341|Customer#000001341|n5dnBrBUHnNEnaglCr9jNvONhG tMPb|18|28-701-221-9569|762.69|MACHINERY|nt requests. ironic, even excuse +1342|Customer#000001342|FD6UNqfsYMKkf3ZFZdI4EaYMZ|16|26-340-733-2096|1520.34|MACHINERY|y around the final, special foxes. +1343|Customer#000001343|WtCLJBdycxFOsHyv|18|28-393-594-5247|8303.09|AUTOMOBILE|accounts. blithely pending foxes wake among the carefully express forges. quickly ironic realms wake bl +1344|Customer#000001344|95XSwEZD22AZln3RB|5|15-307-682-9911|2113.32|AUTOMOBILE|after the furiously ironic foxes cajole slyly unusual, pending reques +1345|Customer#000001345|31zcobEB,6Li4YDZbnNX|9|19-913-651-7783|8593.83|BUILDING|of the express, express packages. final requests detect to the regular accou +1346|Customer#000001346|cuwz2Yvj VKYEXjZzfL|10|20-502-685-6183|4524.45|FURNITURE|heodolites after the quickly bold deposits wake according to the regular platelets. ca +1347|Customer#000001347|7oXery7shMx|24|34-956-232-6103|8476.43|HOUSEHOLD|ular accounts. furiously final t +1348|Customer#000001348|CgtcDDYMnvsgI1uozRj|23|33-360-732-3579|459.22|MACHINERY|s cajole furiously among the ironic deposits. carefully bold pinto beans wake carefully against the carefully +1349|Customer#000001349|HvlnFsKOdm39Ge4VPgzE,UN|18|28-950-527-8728|4967.24|AUTOMOBILE|ges. final ideas nag furiously against the fluffily express accounts. +1350|Customer#000001350|fc,TCo2zqB9T3C5IbaGkfV3,hLqLr|3|13-486-903-2349|3339.51|AUTOMOBILE| regular, ironic ideas are carefully against the silent packages. careful, +1351|Customer#000001351|NYMFfkNlCGoTeaDrNO9nn|1|11-916-210-6616|3106.00|FURNITURE| accounts after the final deposits sleep fluffily ironic accoun +1352|Customer#000001352|XW4X8ComPo5mlyrgLn|20|30-631-606-4317|5570.69|FURNITURE|en escapades after the furiously special accounts use slyly regular grouches. fluffily final pinto bean +1353|Customer#000001353|CzscM6Q8vW6|1|11-109-274-1421|3666.51|MACHINERY| quickly ironic packages. regular, bold asymptotes about the foxes haggle carefully regular pa +1354|Customer#000001354|rvGErAt5suIqpuxwtL QPAgN7n7Tyv|13|23-969-619-1363|-897.04|MACHINERY| blithely blithely pending packages. furiously pending accounts use slyly. bl +1355|Customer#000001355|c1r6G98ixzLQkvUV2KphsFwhYvpDo18oToGB|20|30-918-883-1662|2351.10|AUTOMOBILE|anent dependencies are blithely above the quickly silent escapades. requests sleep. final foxes sleep slyl +1356|Customer#000001356|3SLzAiW4PihnFUE243 AHKkwtL1PCj|5|15-656-712-5740|927.39|HOUSEHOLD|fully pending deposits. carefully unusual accounts +1357|Customer#000001357|S1bDHNFkDEi,Gbsc3|15|25-242-146-4223|8627.90|BUILDING|osits boost pending packages. slyly pending deposits along the requ +1358|Customer#000001358|t23gsl4TdVXqTZha DioEHIq5w7y|3|13-264-253-1258|5149.23|BUILDING|sy excuses. slyly express requests detect slyly quic +1359|Customer#000001359|F5XtTR5KeZ,wAL|11|21-124-833-5784|4069.82|FURNITURE|eposits sleep quickly. enticing packages sleep ironic, ironic accounts. daring, regular t +1360|Customer#000001360|xeaT6W6D569UKCKU86iK9b6aUanlra|19|29-574-552-4018|1422.57|MACHINERY|nt packages affix quickly furiously regular foxes; quickly +1361|Customer#000001361|OAHRbO5RS8,yFt16e7glYM4oVEZpf8BefK5DA,7|13|23-104-975-7608|4128.86|HOUSEHOLD| need to promise furiously quickly bold packages. finally express pinto beans alongside of the +1362|Customer#000001362|FKywgbtf4ib|7|17-801-385-5904|3718.92|MACHINERY|gouts. quickly silent foxes affix after the ironic, special accounts. carefully bold d +1363|Customer#000001363|mYa,yAtLmW2mCglfc7cZ8LrPuP0|13|23-964-365-7781|-112.46|HOUSEHOLD|silent packages. blithely regular instructions haggle carefully slyly ironic forges? thin, br +1364|Customer#000001364|INrMv02tUJWFSRMEbBl0oUTtCjry8qUcI8T|19|29-992-959-9626|-181.69|BUILDING|e furiously according to the slyly final ideas. blithely silent excuses cajole s +1365|Customer#000001365|DOifjgJKjlSgnpPJ3cHLl2yi EseDZbg3|17|27-358-301-5393|2207.81|MACHINERY|ironic requests use blithely according to the slyly ironic patterns. carefully regular excuses about the c +1366|Customer#000001366|v3YAa1hq4Qc7FdpLg4Jh0b7xo0soyvq1w,Yrb|20|30-193-707-6924|1634.70|HOUSEHOLD|the furiously final foxes. furiously bold depos +1367|Customer#000001367|gN803k703pZ1YizV5fp6S8|22|32-462-328-6604|5420.32|HOUSEHOLD|riously theodolites. slyly bold excuses thrash slyly final pinto beans. instructions use +1368|Customer#000001368|4PxJqZUIML EhegD7RXkLY8|15|25-801-622-7438|6376.18|BUILDING|iously regular packages wake according to the slyly final deposits. carefully even packages cajole. carefully +1369|Customer#000001369|rXTwOzU0a2ak4Nj5L5b1aLij|10|20-232-617-7418|498.77|AUTOMOBILE|ong the ironic ideas haggle slyly above the courts. packages engage blithely. pend +1370|Customer#000001370|WN7onCgcC,,Lt4dC4C f7SCgnHWSjeTUp|18|28-575-379-5893|9802.04|BUILDING|y across the regular dependencies. fur +1371|Customer#000001371|H,U3MSp1OTLGIQuW2|7|17-492-673-8157|4943.58|BUILDING|es are after the carefully ironic deposits. silent requests alongside of the furiously even dependencies +1372|Customer#000001372|WiWQk7DyBtI,hfP0CIZ|23|33-563-510-6488|1796.09|HOUSEHOLD|l theodolites. regular ideas are around the furiously iron +1373|Customer#000001373|fAfmAacTlPc|13|23-959-476-7310|909.84|FURNITURE|ckages cajole slyly even requests. express +1374|Customer#000001374|vRPteZtcyV|19|29-869-316-1166|-411.43|AUTOMOBILE|ckly permanent accounts wake fluffily regular packages. quickly express foxes cajole. carefully ironic packa +1375|Customer#000001375|lpKhW7g QK7Y13sxKlRvRYI7SItbTbcBxae|14|24-620-497-1489|2011.11|BUILDING|requests! even excuses are furiously express deposits: fluffily ironic +1376|Customer#000001376|VushDntQeYmYLT22vW09rlg5j06B|12|22-972-150-2900|6761.52|HOUSEHOLD|iously unusual ideas. ironic ideas use carefully about the foxes. slyly unusual pinto be +1377|Customer#000001377|P7aUKm47hbe14nVZSrwZ|17|27-398-963-9520|8839.15|MACHINERY|s sublate carefully alongside of the slyly express theodolites. furiously special instructions haggle +1378|Customer#000001378|zDULZOX6KrHF6aL1AMsIg0Ivv4Crz|17|27-806-173-2824|2675.73|HOUSEHOLD|ges haggle slyly alongside of the furiously final excuses. carefully regular foxes boost across the regular, ex +1379|Customer#000001379|rqYSBCMywMKnfcp2DwotVqI|6|16-695-982-9623|1008.26|MACHINERY|sly ironic requests cajole fluffi +1380|Customer#000001380|a,q fKSYFADxRtRQWSppP8YKp|17|27-641-565-1036|3723.53|HOUSEHOLD|lar instructions boost quickly. blithely regular +1381|Customer#000001381|HqKfFUD6Ib9yoFM5cIgMxjXaqdJAyKSN5w Od|22|32-418-900-6494|367.82|BUILDING|foxes thrash slyly express foxes. even th +1382|Customer#000001382|uiTMgqzTPqAPoKQwbnv|10|20-962-576-3853|8898.67|AUTOMOBILE| wake furiously through the pending platelets. furiously pending deposit +1383|Customer#000001383|bSLtrtrAaAky9GZuKhlQqp8BB|15|25-267-778-1591|2092.61|AUTOMOBILE|s. fluffily unusual accounts against the special theodolites print around the special the +1384|Customer#000001384|bQI5haTy6PHM8MyRtKSlvU4ixAUg|8|18-788-299-9227|1534.38|HOUSEHOLD|tes. regularly pending theodolites cajole even sheaves. stealthy, ironic ideas are furiously above the even p +1385|Customer#000001385|4jAtwsWIITPzhTIx7jblhjp9aAzejEGnu|3|13-693-138-5884|2326.75|BUILDING|ithely daring ideas? regular requests wake slyly ag +1386|Customer#000001386|uByG5EoybI5dNNLzU5uD4Ba|11|21-450-191-9064|9643.87|BUILDING|ages above the busily final packages grow blithely alongside of the blithely even f +1387|Customer#000001387|GQhAzCMyKiDoel3|19|29-444-890-8990|8541.87|BUILDING|foxes haggle furiously according to the stealthy ideas: slyly special accounts about the requests use caref +1388|Customer#000001388|WaKdgWEru70hsL8nyLeEkneHyM59Lboo5zfWv|13|23-185-747-9502|291.44|FURNITURE|longside of the ruthlessly regular dugouts. slyly ironic pinto beans wake. dogged de +1389|Customer#000001389|ORf,IQyXsXJ1svlQ,5U|19|29-865-304-6982|1111.02|FURNITURE|posits. accounts are carefully. carefully express deposits cajole-- slyly bold dugouts wake according to +1390|Customer#000001390|fQm,RnwO4Tt PMQIB|11|21-978-977-8988|3931.31|HOUSEHOLD|ress platelets poach carefully above the slyl +1391|Customer#000001391|7MqN5yFijW6Yua7LVU6i7QMjjiyJ2KTZEaQ|23|33-558-545-3053|5510.28|FURNITURE|ges haggle slyly across the carefully pending accounts. slyly regular accounts should sleep. slyly express packages +1392|Customer#000001392|iXmNoe7IBgjc|22|32-561-640-4912|249.82|HOUSEHOLD| sleep fluffily across the final, pendi +1393|Customer#000001393|zVp5Hbhro,9rTwCYys1HUk|24|34-953-819-7858|5672.05|FURNITURE|escapades. fluffily ironic packages nag among the slyly regular dolphins. special asymptot +1394|Customer#000001394|eE8wv lYYKLXB|3|13-580-581-6470|2233.10|MACHINERY|regular accounts cajole never above the even, final instructions. furiously regular foxes wake unusual requests. ca +1395|Customer#000001395|XJoxiYIaBYgEE|23|33-291-909-3901|8733.39|MACHINERY|tions sleep carefully. furiously final requests about the regular excuses a +1396|Customer#000001396|M4dHuyrttFfeBr|3|13-523-516-9742|7149.43|BUILDING| the even theodolites integrate fluffily regular dolphins. blithely +1397|Customer#000001397|1bk KBemIEsKhD3VyXa6IRLx 4GH u|8|18-294-992-6523|5466.83|AUTOMOBILE|onic packages across the bold, regular dolphins boost furiously furious multipliers; furiously specia +1398|Customer#000001398|K1rQq6exc3WcVCcgIjA4SaeqxtK2,HG1|8|18-377-181-4654|7004.90|HOUSEHOLD|the blithely silent dinos. even, special hockey pla +1399|Customer#000001399|FOuY,endAFj|0|10-775-919-7154|7352.14|AUTOMOBILE|foxes across the silent platelets haggle fluffily special requests. unusu +1400|Customer#000001400|BuouRkR7J f|0|10-217-180-5310|2432.73|BUILDING|etect fluffily final courts. carefully special instructions +1401|Customer#000001401|C4vlB8ENikVmaMizX3nH3zgds6|9|19-339-404-7859|8908.63|BUILDING|accounts use furiously unusual pinto bean +1402|Customer#000001402|F7 m0JwiCABmbJLPQpCJ2|6|16-713-144-2780|4396.25|AUTOMOBILE|g the carefully express dolphins: special, pending packages affix after the packa +1403|Customer#000001403|,ql804gtMc3uxTfP,lt4yRBWQ|12|22-458-624-2509|9782.34|HOUSEHOLD|tes are blithely carefully bold pac +1404|Customer#000001404|pIO5i3yjeODChGMHoVvrX,Ctpdj|12|22-320-701-5582|3828.46|MACHINERY|ven platelets use quickly pending requests. busily busy asymptotes sleep slyly across the +1405|Customer#000001405|i9khsGcg17kWI4q5LKTcc8U3aFojf403|16|26-285-488-6682|3987.39|BUILDING|haggle slyly; regular, final excuses are blithe +1406|Customer#000001406|g1xS4snd0fzl4R,JmPHfEzRD|5|15-767-155-6419|2023.59|HOUSEHOLD|uests are furiously carefully express packages. slyly permanen +1407|Customer#000001407|zZsTZ3nI1rG5X|14|24-529-300-1554|7424.99|BUILDING|nding, ironic instructions promise across the quickly regular r +1408|Customer#000001408|NMIb3p1DyU,Z4XOFUS0B,|11|21-901-381-6344|5920.09|HOUSEHOLD|express requests believe. pending, brave deposits sleep furiously. carefully regular deposit +1409|Customer#000001409|jzfaCksWUNlI|11|21-667-401-3780|1959.17|MACHINERY|ously ironic ideas are. unusual packages kindle along the dugouts. unus +1410|Customer#000001410|yEUlreh6mkGmg8SIwKZooUOJ42kuZwAptaR4HAJ|22|32-358-270-1819|2716.95|HOUSEHOLD|lar, express packages cajole bravely permanently final packages. blithely even dolphins nag finally special theo +1411|Customer#000001411|4iLVKtSmtJpU|21|31-898-640-7625|772.14|AUTOMOBILE|sly final ideas. carefully bold pinto beans wake: slyly regular packages must sleep. final platelets inte +1412|Customer#000001412|gfsI6WU i7kYypv09gGIqUFrUod9uhb|10|20-715-510-2804|6368.38|BUILDING|fully regular accounts print ironic, regular platelets. deposits promise slyly. express, ironic ideas +1413|Customer#000001413|9Yh cGpbCbrXZytNfH,dAEwX|15|25-624-816-9010|1387.83|AUTOMOBILE|onic foxes. quickly final dolphins are fluffily. quickly unusual ideas wake carefully. furiously +1414|Customer#000001414|2 HBoqTD0qCyMKtcBPVHbNna|20|30-323-797-7514|3136.15|BUILDING|ackages. blithely unusual accounts a +1415|Customer#000001415|x,hzUUAZ9w7ndksLyH0,fEpMfU|21|31-295-601-1598|6252.12|BUILDING|heodolites. furiously pending requests are above th +1416|Customer#000001416|ovOZcFGL31uxmA2ifIYudX6OuwNDz,B|7|17-306-898-9363|5348.40|MACHINERY|unts wake slyly excuses. bravely even pinto beans across the furiously final de +1417|Customer#000001417|1BDU8AvljnLmkM|1|11-242-612-1339|7543.01|FURNITURE|ag slyly-- furiously final accounts are ironic instruct +1418|Customer#000001418|S5uBtE hDxHcHunowPDXKSxP3csMFnhYt|17|27-773-818-3164|9359.01|AUTOMOBILE|ggle quickly blithely thin excuses. final, even accounts integrate slyly. carefully pending account +1419|Customer#000001419|JM4NV2pq4Ps0xJNRtUtlmQ8uuDvKx|4|14-533-796-5446|5912.72|FURNITURE|. idly express pinto beans sleep above the deposits. excuses use: furiously bold accounts cajole slyly across the ca +1420|Customer#000001420|mjkRUOEzdCWpNdpp5PKOObMmhpufeNGnO1VFdbpK|9|19-433-305-7356|-932.09|AUTOMOBILE|the instructions cajole carefully. slyly final requests nag carefully ac +1421|Customer#000001421|Qx9tZ9yiMo|12|22-139-990-1907|7292.93|MACHINERY|kly even ideas cajole carefully quickly ironic +1422|Customer#000001422|mzXw44ExYC8DAdeKBakiWy0II|17|27-270-833-4320|8389.50|MACHINERY|mong the evenly express asymptotes integrate slyly brave +1423|Customer#000001423|9BcCj8CLsqylKxRj0,lm|21|31-624-875-9135|2411.69|FURNITURE|he carefully express courts. regular instructions haggle. special, express accounts believe? packages cajole slyly. +1424|Customer#000001424| 3QsPgbVLZ|22|32-542-134-6212|7207.70|FURNITURE| instructions against the furiously express accounts doze fluffily unusual d +1425|Customer#000001425|I2UBZAPPdnA9oFKKJTGxaSQZb5QzNzTR4vN6d P|1|11-697-824-4418|5814.72|FURNITURE|uests boost carefully even foxes. accounts along the slyly ironic requests cajole express, final deposits. sl +1426|Customer#000001426|d1Tyzg,0ArKPuBln8CDH, 1Xsukm2nXVl|15|25-629-292-9022|1965.38|HOUSEHOLD|s are slyly according to the express, spe +1427|Customer#000001427|dDsmiig0T4oFKaf9ttFeh1etLvSIc9aV1xF2H|11|21-941-208-2485|8136.53|AUTOMOBILE|es detect accounts. slyly bold theodolites wake ironic, special accounts. instructions cajo +1428|Customer#000001428|3SdWi3lKPXk00UYT,hL|15|25-859-663-3690|7703.84|FURNITURE|iously final platelets sleep slyly ironic instructions. furious +1429|Customer#000001429|K5sID 6zGPrYdfoADUq4kidlPgF3|3|13-119-903-3814|6444.82|AUTOMOBILE|even requests among the blithely regular pinto beans use across the ironic accounts. slyly ironic +1430|Customer#000001430|mv 9MEDwd8yPeQj7N|0|10-209-317-6929|-920.40|BUILDING|nic deposits. bold, even accounts cajole blithely +1431|Customer#000001431|l3LM2d2T1n c7yI4sOfpEbbd540qO66A4MARk|13|23-640-395-7009|5805.81|AUTOMOBILE|eposits up the carefully bold requests mo +1432|Customer#000001432|,pbQM2fi642oAuel|21|31-831-635-9758|6314.25|MACHINERY|ts sleep. regular frets sleep carefully ironically special dolphins. carefully bold pinto beans +1433|Customer#000001433|gK7D76v78U iRA2YI2kxeKLlm4LZMH13,|17|27-558-375-8169|4605.87|BUILDING|ly bold deposits. furiously silent braids alongside +1434|Customer#000001434|V15TQAhSLp7YC3KdjuMwSV3cwg0lp|18|28-749-743-6583|1851.63|MACHINERY|lieve carefully ironic hockey players. special ide +1435|Customer#000001435|s0fqxkVVqLWR IaqibwwOf|20|30-309-437-9265|-729.09|AUTOMOBILE|usly final orbits are? unusual, ironic accounts are slyly. unusual requests sleep after the ironic, +1436|Customer#000001436|kV5m0jkgFEto,|10|20-918-593-1860|9158.91|MACHINERY|theodolites. final Tiresias after the quickly final packages dazzle carefully blithely bold +1437|Customer#000001437|DjHgTwtlzCmcQo|17|27-805-486-5768|8839.32|BUILDING|y. bold pinto beans affix carefully unusual pinto beans. carefully bold Tiresias mold +1438|Customer#000001438|Gz Aey8gzHxIIxtpJaG0lAqd82T|17|27-688-787-7928|5436.81|FURNITURE|odolites cajole slyly. furiously unusual requests boost furiously along the fluffily pending in +1439|Customer#000001439|IGGK4SXvT5ioAeT2fbVYDemsTTqqhsQu6|21|31-433-694-1822|8487.60|AUTOMOBILE|ely after the carefully bold accounts. carefully ironic packages are silent packages. blithely ironic pinto beans ar +1440|Customer#000001440|k3LXBO5QJrG94TBG77adB1HjqQkleDyUf2c|7|17-619-730-9883|1236.36|BUILDING|xpress, even accounts integrate. ironic, special requests doze. carefully express instructions doze furio +1441|Customer#000001441|u0YYZb46w,pwKo5H9vz d6B9zK4BOHhG jx|23|33-681-334-4499|9465.15|BUILDING|nts haggle quietly quickly final accounts. slyly regular accounts among the sl +1442|Customer#000001442|2fTQpX7N2kp31U|16|26-677-746-7145|7917.90|MACHINERY|ess theodolites. furiously express pinto beans alongside of the +1443|Customer#000001443|qtBPSM2NvmJXNePBT Ap3M6UqIZTvaF|10|20-959-383-4792|7141.87|HOUSEHOLD|ickly about the sly foxes. furiously bold patterns sleep regularly across +1444|Customer#000001444|8WcsyfQU5svH9miWvYbSTH9|7|17-107-228-8125|-501.37|HOUSEHOLD|inal platelets. quickly ironic requests do are carefully carefu +1445|Customer#000001445|5y7gtM75FOfTSBKx9gs9c9MkqJt|21|31-151-251-1931|8367.94|HOUSEHOLD|carefully regular accounts after the b +1446|Customer#000001446|p94EVXQW,Q3bhXDyhG1Gp96b5zbaW|23|33-873-120-5388|2981.48|BUILDING|gle ruthlessly. furiously express dolp +1447|Customer#000001447|pHkyNkViDja,dZVNg4bEEbicpoHIVDZvtQi8RPl|17|27-452-251-2941|2718.02|BUILDING|ously around the accounts. packages haggle blithely ironic, idle ac +1448|Customer#000001448|a45QD J55bo35zA4qR3v|24|34-969-612-1458|7756.35|AUTOMOBILE|y ironic instructions? slyly pending platelets hang quickly slyly ironic ideas. blithely ironic instructions a +1449|Customer#000001449|lNFczqF3TjlSO9BuO3jqXY,b|22|32-827-813-3340|9051.75|BUILDING|ructions wake slyly ironic notornis? slyly express courts wake along the slowly +1450|Customer#000001450|z7Pl iXBEstivMNf|3|13-443-688-6724|857.70|MACHINERY|ains; daringly dogged deposits across the furiously regular instructions breach furiously foxes. carefully unusual a +1451|Customer#000001451|Yt69m0Aw1LWZhisHJxL4iGEEzx6y,ehspkes|2|12-590-121-9328|3274.30|FURNITURE|ously regular packages. furiously final deposits boost. slyl +1452|Customer#000001452|51mhHAvPHZACedHYXVU5HXoDIQtBK9,pxuOIlJ|7|17-581-575-4538|7086.97|FURNITURE|silent theodolites. fluffily special +1453|Customer#000001453|FTfWkW1 8jVgOIIR9sMm2HpohiuR1v2278|0|10-852-397-3642|662.67|BUILDING| to wake above the blithely regular foxes. d +1454|Customer#000001454| wwPhUG35PiIVasu88,RvDA|24|34-478-555-5955|3366.61|FURNITURE|ss the blithely ironic deposits. regular deposits after t +1455|Customer#000001455|MrDN0cvhoLZ ioRLZCR hPcY4WvILz2|3|13-839-360-1866|7591.90|MACHINERY|ironic instructions: ironic pinto beans acros +1456|Customer#000001456|zKDB5elqlAQoUQp|13|23-171-834-8997|6123.69|AUTOMOBILE|unusual accounts wake. even, ironic packages wake carefully. regular p +1457|Customer#000001457|qmpteVs7H9WjRow7FDut9a77oFKRDOXxq0JmG|23|33-660-953-7656|2873.49|BUILDING|onic accounts nag blithely among the regular, regular pinto beans. carefully regular +1458|Customer#000001458|vsGifZH3fNgJjlgF6jJbmkSqGc|3|13-392-503-9207|2716.80|AUTOMOBILE|ests sleep bravely ironic accounts. quickly regular accounts cajole +1459|Customer#000001459|2sPwjFNEFf9dN4az|11|21-424-586-6295|9270.88|AUTOMOBILE|ounts use blithely. blithely pending packages use ironic deposits. final accounts boost slyly. care +1460|Customer#000001460|AEgBZGLmuMqe7Gqh1|20|30-151-388-7118|9680.51|BUILDING|accounts. ironic packages cajole furiously; quickly pending requests lose quickly carefully bold deposits. +1461|Customer#000001461|MMmT5l0zAilFCb2ZMqsUm3TXlRH|3|13-393-444-1533|8460.48|AUTOMOBILE|ress, unusual packages affix carefully carefully final ideas. blithely special instructions nag even deposits? f +1462|Customer#000001462|b9Ed,6BCKn5v37q1|17|27-153-195-4457|7305.88|FURNITURE|ously slyly express requests. spec +1463|Customer#000001463|WD3OuRpJ0NVj2qslrTkUPmeJqVx5|7|17-980-394-5868|6039.64|MACHINERY|s. blithely even courts wake quickly: quickly silent pains doubt slyly. slyl +1464|Customer#000001464|5kOAfK9s6goOZabgSzNLgD,CILowRxqC2OLnV|14|24-133-117-1577|9306.20|AUTOMOBILE|iously furiously regular tithes. boldly final requests use carefully at the f +1465|Customer#000001465|tDRaTC7UgFbBX7VF6cVXYQA0|8|18-807-487-1074|9365.93|FURNITURE|s lose blithely ironic, regular packages. regular, final foxes haggle c +1466|Customer#000001466|Fdm3uYarZ0Tnnh9R|17|27-360-496-5041|1268.69|FURNITURE|nts along the blithely bold instructions boost carefully after the unusual depos +1467|Customer#000001467|GE,jQi5oLlkzh4jIUct7r 3C5G|24|34-941-824-8063|2857.19|FURNITURE|. final, bold deposits sleep furiously. unusual instructions are final requests. quickly final sentiments +1468|Customer#000001468|APEd1ssFxDC9fhwosxxeQUul5EhwBczX|12|22-901-280-1023|3826.52|BUILDING|s. slyly regular theodolites aft +1469|Customer#000001469|yLW8qLv25wuMsibRd,1qJe9|7|17-961-583-4658|4329.98|FURNITURE|y even dependencies wake against the regular, final excuses. packages haggle slyly a +1470|Customer#000001470|8ufZxZ5IgwGrUM2CWfxYoRHuBi Vj8rY|17|27-350-836-5521|7033.49|HOUSEHOLD| excuses are slyly after the carefully bold accounts. unusual pinto beans boost. final accounts wak +1471|Customer#000001471|lbRP,tSo,eQT6rDDNNIBx|5|15-230-827-4758|3872.86|AUTOMOBILE|thely according to the carefully ironic foxes; packages according to the quickly special deposits wake fur +1472|Customer#000001472| Eayx9GAqjJEwrGy1Er5 ffNtLL|5|15-464-411-8342|2168.61|MACHINERY| haggle against the carefully bold theodolites. quietly regular ideas haggle. pending pinto beans engage sl +1473|Customer#000001473|UPkONG9dy4VYyGNJGHG|0|10-891-555-7734|2796.93|MACHINERY|uriously. quickly pending multipliers maintain slyly silent excuses. regular requests cajole qui +1474|Customer#000001474|KB83CaaM8DRjvAmEMg1fw|16|26-609-226-4269|2961.79|HOUSEHOLD|kages above the requests sleep furiously packages-- deposits detect fluffily. pending th +1475|Customer#000001475|4tUf4SaYTFV2H7ji|0|10-932-794-2009|1820.28|BUILDING|uctions sleep blithely bold packages. pending, silent deposits after the fluffily final pinto beans ar +1476|Customer#000001476|nsPnedR1dhWK,|16|26-621-638-1459|409.72|BUILDING|across the fluffily final requests. regular forges haggle furiously r +1477|Customer#000001477|nUT6kGEr7tmgpJaPgfFtXY|6|16-407-756-8079|9103.33|MACHINERY|ites nag blithely alongside of the ironic accounts. accounts use. carefully silent deposits +1478|Customer#000001478|x7HDvJDDpR3MqZ5vg2CanfQ1hF0j4|7|17-420-484-5959|9701.54|AUTOMOBILE|ng the furiously bold foxes. even notornis above the unusual +1479|Customer#000001479|KDZMMuMVSWQPkGpoTUE0G 1vXHd3mS4c,A,kFR|16|26-203-849-3685|9793.29|BUILDING|arefully final ideas. unusual accounts sleep. final packages wake. fluffily bold dependencies hang slyly. bl +1480|Customer#000001480|Hzjh65ZXBFSzflrjQgECkrp35gDha,2|7|17-573-775-8796|876.02|HOUSEHOLD|uriously pending courts are. deposits serve quickly blithely final excuses. slyly reg +1481|Customer#000001481|Vp7Um1Vy7MNVJvP 5cqUrz8scGtcaLJB3f5bZDW|12|22-674-694-9039|3204.67|AUTOMOBILE|lithely. idly ruthless packages wake above the bold, quick pinto beans. regular ex +1482|Customer#000001482|kTcr5JgkjFeLKIRcmtnCvOFr1feN59chP7|19|29-452-962-5934|2930.53|FURNITURE|are. slyly regular deposits mold carefully above the blithely regular ideas. carefully r +1483|Customer#000001483|ZjY1C b6cOnY3|7|17-202-113-4814|4409.70|BUILDING|nts sleep around the carefully express theodolites. requests nag +1484|Customer#000001484|WcOint654aJStnQWSgAAtI|18|28-987-505-1842|4883.17|FURNITURE|s against the furiously special packag +1485|Customer#000001485|oR6sZslMa7bPLxtHFhqdJt|24|34-329-123-7678|9412.02|BUILDING|pliers. ironic requests boost slyly carefully express ideas. blithely ironic foxes af +1486|Customer#000001486|7A2MhrNtsA|24|34-559-605-2237|5859.97|BUILDING|lithely ironic dependencies haggle quickly b +1487|Customer#000001487|AJXUi2qFVKfypmmpTEbkmjmz0gPKQ2|17|27-197-562-5547|3589.16|FURNITURE|y final instructions. regular, regular packages boost alongside of the b +1488|Customer#000001488|DtF2uJI8td2wqrumD|4|14-892-461-5341|7929.51|HOUSEHOLD|sits boost quickly fluffily even pinto beans. slyly e +1489|Customer#000001489|yM8biIU5IFKHODCGTCwdkUf|9|19-906-669-4354|4389.66|MACHINERY|ckages play carefully? permanently regular pinto beans +1490|Customer#000001490|vBUkY7eCyWP|20|30-326-598-2437|8997.60|MACHINERY| bold orbits boost slyly according to the carefully ironic accounts. slyly special packages whithout the +1491|Customer#000001491|GjZIP4Fv5lqDt|4|14-931-281-5631|3739.82|HOUSEHOLD|efully silent tithes. even deposits according to the unusual, even platelets haggle furiously a +1492|Customer#000001492|2QNz4Zy0UjjI|1|11-527-949-4092|-875.17|HOUSEHOLD| blithely even accounts. furiously final instructions across the decoys cajo +1493|Customer#000001493|FbV 8Ug9GkSfMde5b|24|34-947-154-7032|7014.12|MACHINERY|carefully quiet requests lose slyly. quickly final pinto beans haggle bli +1494|Customer#000001494|4V71P ku3jrqBfQp|11|21-248-166-9549|8292.21|MACHINERY|arefully furiously special ideas. pending deposits above the blithely regular excuses wake slyly car +1495|Customer#000001495|78w5H7VJSo0Ps,jqeoCWS4Kay17ygM4RtIH|10|20-416-910-7075|6227.55|FURNITURE|osely blithe, ironic foxes. regular dependencies use blithely about +1496|Customer#000001496|ZOyMxutVHpJy|3|13-802-978-9538|-496.49|AUTOMOBILE|counts wake slyly above the instructi +1497|Customer#000001497| D8e2U3gYd57H4grcOr,02|14|24-506-574-8552|2449.57|AUTOMOBILE|gular packages boost foxes. blithely bold escapades wake slyly special pack +1498|Customer#000001498|x XToT5oFi7oIsRG2mgIL3ncvYJoWBsufsQ7N,z|19|29-676-227-6356|5810.56|AUTOMOBILE|ackages are slyly unusual req +1499|Customer#000001499|4,6jWOEqfnuXkwhB7gs0M9TcWJlaJNv4bt|3|13-273-527-9609|9128.69|AUTOMOBILE|ole blithely permanent instructions. carefully even packages +1500|Customer#000001500|4zaoUzuWUTNFiNPbmu43|5|15-200-872-4790|6910.79|MACHINERY|s boost blithely above the fluffily ironic dolphins! ironic accounts +1501|Customer#000001501|tLJmtj5OgXCQM|10|20-489-284-9686|9734.53|BUILDING|longside of the furiously ruthless deposits slee +1502|Customer#000001502|FIsFVFApqxzRHQrRjAlODHWTDZc35,BD0c7CuyVy|13|23-873-733-3833|3361.88|FURNITURE| carefully express requests. quickly even in +1503|Customer#000001503|9fFMPuIIatxmXEDe4XCu4PRea9|2|12-957-226-3187|5164.52|FURNITURE|odolites. express notornis detect blithely unusual, regular d +1504|Customer#000001504|suueZs7bAberaafllLS|0|10-462-929-6039|8151.61|MACHINERY|ess theodolites. blithely speci +1505|Customer#000001505|SFczFxAak1xX,CmWAE|21|31-344-990-8260|8207.39|AUTOMOBILE|yly above the accounts. even deposi +1506|Customer#000001506|RUScjIPOHpz3it|1|11-381-308-9658|-373.24|MACHINERY|s. furiously unusual excuses sleep slyly. blithely unusual packages about the slyly regular accounts are accou +1507|Customer#000001507|KtVNuytlncvuV44YzpoB|10|20-694-294-7077|5801.76|BUILDING|symptotes around the blithely ironic requests may boost blithely during the bold, final ideas. ironic pinto beans sl +1508|Customer#000001508|E7fRkt7uXJHIR8akfmor42eTm5kZH|4|14-740-990-2746|4213.74|AUTOMOBILE| fluffily pending asymptotes. blithely even foxes nag slyly slyly pending platelets. carefully regular req +1509|Customer#000001509|LQY2i,MHY8czRV2Ize|9|19-226-262-5083|328.44|BUILDING|tipliers serve quickly furiously express excuses. furiously unusual deposits slee +1510|Customer#000001510|BVNRoS0TPt7yBxD|1|11-138-490-8934|7100.18|MACHINERY|ng the quickly bold deposits. regular, even deposits use silently. special, regular packages mold slyly regula +1511|Customer#000001511|Lh9VKgOjqeJ5P5veH6NKZG3We|4|14-230-666-6671|2757.29|MACHINERY|xes. ironic, special dolphins against the regular accounts haggle carefully across the f +1512|Customer#000001512| FhwT 40,zugIGQPtYUDkjvXct070xNX4Lze|16|26-502-737-9941|7729.48|HOUSEHOLD|l accounts. final deposits use carefully slyly regular deposit +1513|Customer#000001513|CkEgq3Yvj9kGkHvVeUELT1UP9HBnHwiEIFzRWNTA|10|20-670-367-4252|8434.13|FURNITURE|y regular accounts cajole blithely +1514|Customer#000001514|2dVI195Lf,EUjr1CY37GWxCxb0uUjEa|8|18-602-992-7324|4566.48|FURNITURE|ngage slyly alongside of the f +1515|Customer#000001515|QS USHJ02MP2yd7TIcCNGMyXjyQug0EIShDlUM|12|22-852-688-4287|-179.31|MACHINERY|ily: regular packages cajole furiously at the carefully dogged foxes. final grouches must are. silently daring de +1516|Customer#000001516|VFbEMU7LSQZPCZ3m73dNP2WH0ywr5loATV4r|14|24-797-943-8908|9263.27|FURNITURE|tructions integrate above the regular, regular somas. blithely ironic asymptote +1517|Customer#000001517|hJBcIv8Yc9ukY9Erz96RRKNR8upJ8IBJxgePjf9|23|33-993-734-9681|2875.95|FURNITURE|tes. carefully final packages against the p +1518|Customer#000001518|ulllJKhRl VkFwAIhlb |8|18-242-415-7477|37.80|MACHINERY|l, pending packages boost ironic, final theodolites. fluffy requests are carefully. ironic, regular theodoli +1519|Customer#000001519|ersLKVkITqd,b7yCM1td5h9Y1tQv|14|24-663-396-2927|6172.47|BUILDING|ost from the close accounts. r +1520|Customer#000001520|WuEf6uxQmSgTA1efbl24QhQ60WJoh2166RzzOiV|24|34-364-590-2076|8678.58|HOUSEHOLD|ges after the requests integrate slyly according to the ironic requ +1521|Customer#000001521| UAwhhVG066cebuZN6Wk7s|13|23-168-973-9213|9983.09|AUTOMOBILE|special deposits use quickly according to the furiously express packages. slyly unu +1522|Customer#000001522|aMbkFCcpuqN8YFzn8ctAhm skIIfd|4|14-712-410-2710|948.00|AUTOMOBILE|packages hang slyly alongside of the slyly silent foxes. closely express accounts alongside of the even Tir +1523|Customer#000001523| udI60hnJb0IMvB67xQFfkgamLpP2Bwynf5P|7|17-405-744-1455|2921.13|MACHINERY|oxes. slyly bold ideas snooze blithely. accounts sleep slyly agains +1524|Customer#000001524|nW8RCuzryVNcYMCvE ZKJC7apmhen|22|32-834-498-4224|425.06|BUILDING|ses are regular packages. even asymptotes believe. furiously regular platelets sleep carefully according to t +1525|Customer#000001525|NtS KugGxV4GMBxNAwZdR6wwq02 fd y5,M|0|10-178-851-9228|2915.69|AUTOMOBILE|cial dependencies. ironic accounts integrate regularly across the permanent accounts. quickly +1526|Customer#000001526|pAC6Yj2c5lyOIr5 IQpM0|8|18-679-265-7392|8012.73|MACHINERY|ructions. furiously ironic packages after the evenly express pinto beans +1527|Customer#000001527|486JIEEHa |24|34-219-462-2180|6025.59|FURNITURE|old excuses sleep furiously ironic packages-- final pinto beans cajol +1528|Customer#000001528|fa,9WdvoEW06FtLQ6bpXBYGORjOWt,w|21|31-594-709-9605|4114.07|AUTOMOBILE| bold deposits sleep slyly about the blithely express accounts. final accounts haggle furiously at the +1529|Customer#000001529|NYQrlaZMT2rOQadTbfSpAdPPTQwpWQEEWD|2|12-170-370-8690|8221.42|HOUSEHOLD|each blithely. ironic, even packages sleep slyly alongside of the furiousl +1530|Customer#000001530|KVYYmaQ7fGwFnhgBnot1zTnFa|2|12-845-483-5866|4404.87|MACHINERY|ckly furious deposits. furiously special instructions sleep furiously according to the regula +1531|Customer#000001531|OomxCS69ZBbyC99b6YHXYGvw1Fs|21|31-735-863-6916|728.83|AUTOMOBILE|. deposits use furiously. ironic accounts affix +1532|Customer#000001532|VHjtEO1OwfCkrTIj|1|11-301-550-1539|4311.62|BUILDING|ependencies. fluffily even instruction +1533|Customer#000001533|jVCPod3Ysz|7|17-511-289-3953|6323.48|HOUSEHOLD|cross the ironic, regular ideas. even, regular deposits haggle according to the blithely regular dep +1534|Customer#000001534|EJ1gh5MYQ7R xKH6RfqPU96So94cMHKHgnEVTgy|17|27-975-211-1327|5760.99|FURNITURE|ly final requests; blithely regular pinto beans haggle slyly along the quickly bold notornis. sentiments cajole c +1535|Customer#000001535|2l8xLuwaicTTg5RNA7mwyHhz|23|33-371-530-1740|1041.79|FURNITURE|g the blithely final accounts haggle carefully above the sly, express platelets. excuses eat slyly across the c +1536|Customer#000001536|HRUhB3D7LC6V ydQigaOZ10Y9Be1jN31|13|23-357-877-4041|6388.82|HOUSEHOLD|uriously against the slyly regular ideas. blithely ironic dependencies solve nev +1537|Customer#000001537|Fx1vbSLG90yTE3KF2VGDMOeny|15|25-482-334-6480|4000.55|HOUSEHOLD| courts. quickly regular instructions are blithely silent excuses. slyly special theodolites use finally +1538|Customer#000001538|ohSUJgfMxt2Hq9f0tv,MZaRsombSl,MU1d6,|2|12-766-442-8988|3245.69|FURNITURE| blithely carefully even instructions. blithe +1539|Customer#000001539|EFgodQ9F0u SUYZQcJCNzjDlte5 br0klLU|17|27-544-403-7594|-702.43|MACHINERY|e blithely express pinto beans. carefully regular pack +1540|Customer#000001540|c1kVCV43v2RpUwCoZJ2LBHWYt2BT7|17|27-352-357-7209|6102.98|HOUSEHOLD|ious foxes against the slyly regular deposits boost ideas. regular waters sleep slyly: unusual deposits +1541|Customer#000001541|3HbD4JaolktsAYU,OgPrar2|15|25-786-474-5957|6792.00|AUTOMOBILE|blithely. packages wake final accounts. carefully enticing asymptotes run quietly despite the slyl +1542|Customer#000001542|4whsFeeVSBH7Eq WSu gF5JCsJc|14|24-754-425-8980|4108.68|BUILDING|sual, regular deposits haggle blithely alongside of the quickly ironic foxes. slyly bold pinto beans det +1543|Customer#000001543|IKgaPQRsONfY1vAsPP|18|28-327-662-8527|5653.73|MACHINERY|ckages haggle. idly even deposits according to the regularly even ideas haggle blithely re +1544|Customer#000001544|R,hoHFlkusJ,1Kts,0QEixg|23|33-132-882-2925|2204.41|AUTOMOBILE|ular deposits. final, regular accounts nag carefully quickly regular pinto beans. unusual, unusual theodol +1545|Customer#000001545|08TtvYMUYuq6Hgi1T4IsV2fr1G90cnb D|1|11-287-870-3637|-487.86|BUILDING|ial requests wake. sometimes regular sentiments are. pinto beans use car +1546|Customer#000001546|kFu hXaTK2Vk|20|30-788-120-7833|4488.33|AUTOMOBILE|sts haggle furiously. even, regular packages sleep. idly idle somas affix furiousl +1547|Customer#000001547|RgRcB,v0ZS|4|14-683-809-4484|6387.31|AUTOMOBILE|ts after the accounts are above the fina +1548|Customer#000001548|0uaAwzhbw,1VFL|23|33-610-656-3668|562.75|AUTOMOBILE|eep slyly regular, final instructions. final dependencies engage a +1549|Customer#000001549|Bm8PVyaAYfS0IFPhkXiVGL|24|34-263-284-6757|7050.56|FURNITURE|sts about the quickly unusual dolphins integrate quickly slyly silent platelets. quickly final instructions +1550|Customer#000001550|NgbaaI8wjR|20|30-722-982-9755|4742.59|BUILDING|sits. regular requests cajole boldly after the slyly special ideas. quick t +1551|Customer#000001551|GSs9E1btXLKkSgkCAyLohk1bOLuJ6|14|24-667-589-4141|797.35|BUILDING|ely ironic dependencies. quickly iro +1552|Customer#000001552|eR6My q7YdhYeBH jVxHHC mYpeNFNBDuG10|21|31-902-185-9642|956.02|AUTOMOBILE|regular accounts eat furiously slyly slow ideas. carefully final accounts mold furiously after +1553|Customer#000001553|zS2t71h5ssFkRFiB4EvNtWPqjexC1FaO1MeNutf|1|11-879-323-7032|5853.10|AUTOMOBILE|he slyly unusual packages cajole slyly ab +1554|Customer#000001554|axGq6Zieq8sy|7|17-462-295-6567|8996.02|AUTOMOBILE|latelets cajole furiously final, regular packages. furiously even accounts cajole according to the even +1555|Customer#000001555|7V1UD h0 oKL04nnKVzu7UCmFSL56|5|15-722-660-7220|-740.02|BUILDING|ng deposits alongside of the express, bold deposits cajole blithely deposits. even packa +1556|Customer#000001556|0KThJm1X9rQH3Me,EI2QW8HzrUKnsU,gvw9BwzN|11|21-170-549-6376|1462.44|BUILDING|coys wake slyly along the ironic pinto beans. evenly ironic requests use quickly. final packages are slyly. dolph +1557|Customer#000001557|cbF7Kpmtk4w1vCoqB,3Ev3XNnr|19|29-927-226-6896|3144.14|BUILDING| according to the final, pending account +1558|Customer#000001558|hHKBdZXfRUbMjnlX i8sGWu6|9|19-532-314-9903|8473.41|AUTOMOBILE| thin packages against the even ideas sleep slyly according to the pending instructions: +1559|Customer#000001559|0rOzDCEPki4zpeqXx5nW3ajIGdLN15XHeS|0|10-700-486-1040|4630.52|FURNITURE|ronic sentiments doubt carefully slyly even deposits. e +1560|Customer#000001560|yNFoAP4UcMlluwL1uNYvUmCgrn7GfDiTo3H3mzV|15|25-187-156-3225|9146.01|MACHINERY|furiously ironic requests alongside of the deposits impre +1561|Customer#000001561|11hKNqixtqQsCgZKu3DYu0VEx28g04|13|23-445-875-1233|1083.49|AUTOMOBILE|slyly about the quickly expres +1562|Customer#000001562|Rj0aTQUqnb1u4qOvWzb3|13|23-883-927-3910|3102.27|FURNITURE|eposits cajole. final instructions alongsid +1563|Customer#000001563|cb7 vuR7o4Z5KQqgd5yllan5Evum5|4|14-146-791-5866|8838.33|MACHINERY|ourts-- slyly regular packages sleep car +1564|Customer#000001564| kQ06G,BN4KWou6DYH|5|15-898-126-9264|-184.33|BUILDING|ual foxes wake: theodolites sleep bravely after the furiously +1565|Customer#000001565|EWQO5Ck,nMuHVQimqL8dLrixRP6QKveXcz9QgorW|2|12-402-178-2007|1820.03|AUTOMOBILE|ously regular accounts wake slyly ironic idea +1566|Customer#000001566|NfBldfDRJyOWXbZ47UJP2hGn6HF1zOZGJaOa|23|33-480-441-5244|7256.21|FURNITURE| final frets are carefully against th +1567|Customer#000001567|D XMRaJOpRqLttO8yiMZ4tYU1L2nUr|24|34-146-945-2364|7209.94|BUILDING|thely ironic ideas. ruthlessly pending sauternes are furiously enticingly regular pinto +1568|Customer#000001568|uOMsOfJ0raeSGqW9PMPs1sL5D pcO,fUaYsY6|22|32-780-340-3819|-576.58|HOUSEHOLD|ts sublate carefully ironic orbits. final, even accounts sleep toward +1569|Customer#000001569|4vO9w7ixKJ 5od18LqLvr,|6|16-108-793-2841|9416.38|HOUSEHOLD| the unusual packages. even excuses against the fluffily regular idea +1570|Customer#000001570|RMBVeVOCt002J1|13|23-319-685-6601|2106.52|FURNITURE|unusual deposits unwind among the courts. silent packages +1571|Customer#000001571|akbtXy3o6igP3n8C|6|16-661-716-6605|4250.73|BUILDING|silent deposits sleep. silent foxes acro +1572|Customer#000001572|wS4p6kZ8dz8WyKfAbhXeBUO3QJj|5|15-262-124-6233|6070.44|FURNITURE|instructions affix furiously slyly regular foxe +1573|Customer#000001573|pcC2rrIA2bwtSXkcBy8X5eoQBrfoGb7gT|10|20-170-955-7287|9831.27|AUTOMOBILE|ests use of the brave accounts. excuses are +1574|Customer#000001574|hgovcHRlq4 y|8|18-753-101-5745|1204.82|HOUSEHOLD|e regular courts affix after the thinly ironic reque +1575|Customer#000001575|Ntyf,WOVz9hrnESfXT6gBxej1eZjbwgdSEVvmRw|0|10-455-580-7646|7283.99|AUTOMOBILE|dugouts. slyly even deposits about the quickly reg +1576|Customer#000001576|ec9dOjmCD0iicQEc4iIff88zX4kFGHPZUPYX1sBg|22|32-430-540-7796|1006.44|MACHINERY|y bold requests about the ironic, regular theodolites haggle slyly instructions: ironic courts wake carefully. +1577|Customer#000001577|eaMmfsWJ7 USPFwMH|22|32-267-732-1345|6204.00|MACHINERY|dolites boost slyly even deposits. furiously ironic asymptotes ha +1578|Customer#000001578|KGMw1t3in68W4|17|27-348-227-6667|-365.45|AUTOMOBILE|elets. special, express excuses after the accounts promise carefully requests. care +1579|Customer#000001579|TI4GCerFzw2UgqQdzJ94|3|13-255-948-9257|4763.17|AUTOMOBILE|efully across the quickly express deposits. slyly regular deposits sleep above the blithely ironic theodoli +1580|Customer#000001580|Uc5lBMkU8F1zW56P Bo,8fbVlyCKs|13|23-651-166-3240|5587.12|BUILDING|ts before the ironic packages sleep furiously regular, bold dependencies: dolphins +1581|Customer#000001581|fCDyGbFmnkclr,031ny|14|24-603-456-1171|4669.01|AUTOMOBILE|lithely final deposits. quickly express platelets unwind +1582|Customer#000001582|Tw 9wNgPjMmsy1brAYW0|11|21-998-418-6615|7119.80|BUILDING|even accounts. quickly brave deposits haggle. +1583|Customer#000001583|og6OTS,QKN2BidNDSZd0yB,Tn8ls6TGnKUz |13|23-136-310-3804|2540.51|BUILDING|bout the pinto beans. bold, e +1584|Customer#000001584|BWzLMEnPG7tsF54M8kdGVd7zQCxiXniOP|21|31-675-590-3473|5305.86|HOUSEHOLD|. quickly busy deposits haggle carefully under the even, unusual foxes. carefully blithe foxes snooze fluffily? qui +1585|Customer#000001585|kMDzNCvICH1j7sLp8g0CFB8cO12tCS70VTp5wM7|22|32-232-514-3624|7651.05|AUTOMOBILE| carefully regular packages are about the carefully silent foxes. fluffily regular Tiresias wake furiously across th +1586|Customer#000001586|I76G9G7dkkigm162L|2|12-221-668-7869|-808.05|FURNITURE|rs cajole silently. ideas doze furiously! spec +1587|Customer#000001587|ztyGKSLXBi6r,uNDAxxDeWuWWUdfR1WL4maTC|17|27-437-149-3006|2050.48|HOUSEHOLD|closely alongside of the furiously pending foxes. furiously final requests wake about the ironic, ironic depend +1588|Customer#000001588|TOCHdXfBa1nhv26OP|1|11-700-437-5542|8372.34|HOUSEHOLD|onic asymptotes sleep carefully-- furiously regular accounts against the quickly pending pinto beans mold boldl +1589|Customer#000001589|As9UC67KvgdnJcZWfdz,|13|23-189-857-8090|-101.68|HOUSEHOLD|s boost final excuses. slyly ironic deposits wake quickly blithely silent requests. car +1590|Customer#000001590|c9ykZTFqi2xpKpNedlJ5,v03aqCbT|19|29-736-744-4365|5065.00|AUTOMOBILE|nusual instructions sleep fluffily furiously bold realms. regular, quick platelets wake slyly. final asymptote +1591|Customer#000001591|ZLJNTInWmiv9a1|9|19-142-875-7741|7470.70|FURNITURE|yly final foxes should have to use carefully. even, bol +1592|Customer#000001592|Bf Y0y,RTCY4z|9|19-565-127-5247|4042.57|HOUSEHOLD|n foxes. foxes cajole daringly silent deposits. sentiments sleep flu +1593|Customer#000001593|IAhXngV2KlKAbAQh4y6S7Vd|7|17-767-583-7374|5447.72|AUTOMOBILE|he special pinto beans. silent accounts sleep furiously final packages; +1594|Customer#000001594|8No1IYGij7|13|23-416-484-3099|4796.94|FURNITURE| final packages wake idly. quickly regular pack +1595|Customer#000001595|bJ6tl8L3gexrf9rdD,Nn9ojzg92|3|13-153-638-7545|1151.78|MACHINERY|hely final ideas. regularly daring requests sleep. silent excuses s +1596|Customer#000001596|fpSMWvE3a |20|30-259-884-2046|6900.08|AUTOMOBILE|foxes integrate thinly. furious, special packages sleep furiously about the asymptotes. final accounts s +1597|Customer#000001597|6pS2oH twoOdcRPVMT13YQQA YIFu|22|32-621-493-2342|5728.91|HOUSEHOLD|s foxes eat furiously final foxes. slyly unusual packages are never against the deposits +1598|Customer#000001598|bz91jr1NNiJ|9|19-439-414-8308|835.29|AUTOMOBILE|onic packages about the ironic, bold ideas are packages. care +1599|Customer#000001599|DbZoJYdsMvL8hELLlgjAvUZ|11|21-556-967-2607|626.23|MACHINERY|ly unusual gifts. even, regular foxes use slyly along the ironic, regular dependencies. +1600|Customer#000001600|GFgAlTCNWGZU4Gyk9glu8uX2vZ|20|30-563-390-7858|7027.54|BUILDING| sleep blithely along the slyly ironic deposits. blithely permanent accounts nag. fluffily ironic accounts +1601|Customer#000001601|jiy,cXiM41u9yIb1Vy|9|19-152-934-8225|2884.08|MACHINERY|ly ironic, even accounts. special dependencies detect. c +1602|Customer#000001602|Lum76wozwPDwPGgk7yFzLnG|19|29-236-186-6698|4645.67|BUILDING|. blithely even requests use slyly. unusual platelets snooze carefully r +1603|Customer#000001603|JHju hD17jZDMXprwVfC|11|21-880-121-2298|-149.21|HOUSEHOLD|tect slyly quickly regular accounts. daringly bold deposits are blithely blithe +1604|Customer#000001604|DXn5Lr8KjjMebZznHhSsX3n7T6J8UkWdYw|6|16-960-140-9357|9079.75|HOUSEHOLD|odolites. final frets need to grow according to +1605|Customer#000001605|PLOEPrgnofqWl3|15|25-483-103-9669|9396.10|MACHINERY|sly unusual requests. furiously final theodolites are boldly unusual instructions. ironic, permanent acc +1606|Customer#000001606|rIhuh0JIXA caaG|19|29-275-181-3687|2244.46|FURNITURE|y slyly unusual accounts. even foxes print furiously daringly even waters. blithely unusual deposits boo +1607|Customer#000001607|JrtvTEYpFdqK68WSabydH6dz9Opj6X5orhrIYeHY|23|33-529-928-4089|1543.75|FURNITURE|ites sleep furiously quickly pending somas. fluffily special +1608|Customer#000001608|jGjdmzMbF05pXU5STryOYpL9orgJ6F|6|16-897-134-9884|5827.14|BUILDING|oys haggle never. regular ideas solve. express dependencies cajole furiously bold ac +1609|Customer#000001609|YuJ96cGZd lzZ5jo0HI6OAi,7b12GYDC,|20|30-784-105-5546|1710.71|HOUSEHOLD|unts alongside of the regular packages haggle carefull +1610|Customer#000001610|8T,m b4Gwjs9j|18|28-219-755-5479|6861.85|FURNITURE|ainst the slyly ironic instructions. blithely final deposits +1611|Customer#000001611|QX3yB3eqWVsGuy7WetBKk6U6s CXl|18|28-997-908-7044|1148.91|BUILDING|ests. furiously express instructions wake slyly! fluffily express frets haggle. quickly even instructions do +1612|Customer#000001612|oRmhlGYt71UyFdgI4KvPxF|16|26-493-547-6969|2613.29|AUTOMOBILE|oost blithely about the blithely express packages. reg +1613|Customer#000001613|grC4vU,xdQCWgrPJzj|19|29-636-508-4398|7539.75|HOUSEHOLD|onic excuses. regularly unusual deposits sleep. slyly ironic accounts nag carefully. furiousl +1614|Customer#000001614|7BofGHd,3lr2wda7i|1|11-986-549-9647|9609.43|HOUSEHOLD|to beans use blithely. unusual, regular waters along the slyly bold pinto beans wake sly +1615|Customer#000001615|AWqpPsmhK,yirQmha|18|28-449-655-8989|1764.25|MACHINERY|egular packages. carefully express ideas wake fluffily fluffily idle deposits. furiously final dinos n +1616|Customer#000001616|hZ7KvTsImg5hRUWmHXpkZGvhFe|20|30-752-506-2492|4635.15|FURNITURE| pending tithes. furiously blithe instructions boost. thinly pending ideas use careful +1617|Customer#000001617|SfX,PYtDB3h2gdmDD1JMN,gKIIVqo|2|12-677-936-3084|9911.51|AUTOMOBILE|y ironic requests above the regular requests haggle silent asymptotes. daringly special instructions detec +1618|Customer#000001618|efEU9gOnX05FfeJAyNMup|12|22-326-603-9101|7795.47|AUTOMOBILE|refully pending accounts haggle furiously dependencies. +1619|Customer#000001619|qM0OslnGfoXRS4YhYUDaUd6cXDDCPc5Ppke8CU|13|23-371-869-2433|6511.83|BUILDING|bout the slyly silent accounts. fluffily ironic deposits integrate carefully against the ironic, express pinto bea +1620|Customer#000001620|p2BIMDiWvXUWlb FXxIukQZI|5|15-151-404-4005|3324.77|FURNITURE|regular courts. carefully brave deposits +1621|Customer#000001621|5I2xwuWad5n73M5zM,Dj|16|26-615-141-1919|8358.51|AUTOMOBILE|efully silent deposits shall nag blithely a +1622|Customer#000001622|HEfEM41ad6Tar1EH526Q9cxe3Pi|5|15-120-999-7103|9617.34|HOUSEHOLD|e requests-- carefully bold packages are. +1623|Customer#000001623|azlsfbL,uqLb2T1wCn5yQ33YK5KvJ8Fo|23|33-467-523-3238|2746.27|HOUSEHOLD|ress carefully quickly special depend +1624|Customer#000001624|A8VfM,awG8VPydormLPcaw|17|27-822-330-4723|9566.20|AUTOMOBILE|accounts among the brave packages haggle finally careful +1625|Customer#000001625|qQ53P2z9Mnocb2HG9u|9|19-868-381-8072|1189.78|HOUSEHOLD|nts use furiously regular pinto beans. unusual, regular dependencies detect blithely +1626|Customer#000001626|Qqvd9BwVQQ133oxNXb8N1i6V3l9z7eu3A|22|32-751-259-8740|7564.80|FURNITURE|ar accounts haggle never. quietly regular instructions are carefu +1627|Customer#000001627|RV5yXOOv0tjeqxIoRtIw9lKU3UK|10|20-566-949-4093|1673.17|AUTOMOBILE|fully after the blithely regular warhorses-- quickly even +1628|Customer#000001628|xOOuECIqRpweZwxZRgQpb2guNYVE|18|28-241-420-5429|3002.83|MACHINERY|s use fluffily. slyly silent foxes +1629|Customer#000001629|eGVew4ADiILjquTPiTeVS9|18|28-413-295-5895|9601.48|HOUSEHOLD|sly express dependencies abou +1630|Customer#000001630|mFqtTXCA4QaCqP7yXsTlk|24|34-375-163-1478|214.28|FURNITURE|furiously final excuses. accounts cajole blithely ironic pinto +1631|Customer#000001631|TEZnHT8B6dqZw9,OoyNrOJs PlT2QfZKk|13|23-875-411-6115|2401.42|BUILDING|y ironic packages. fluffily express deposits sleep by the slyly ironic requests. regular depos +1632|Customer#000001632|9SoJbgMR23pwWXyE|24|34-183-653-4603|-378.16|AUTOMOBILE|p across the ironic foxes. furiously close dependencies det +1633|Customer#000001633|kO5Tq2Y W,NklARS,|11|21-575-247-9010|162.02|MACHINERY| ruthless pains alongside of the even platele +1634|Customer#000001634|mTRMQ9143TTe5kHsD2FdNE7proZ|24|34-186-980-9064|4030.37|FURNITURE|s are thinly fluffily ironic requests. pinto beans cajole blithely before the regular +1635|Customer#000001635|HjISwY7cr50HVcC81T7MnYJ7byRMXrMgB7RjsV|23|33-974-490-5943|9435.42|HOUSEHOLD| the blithely final dependencies. slyly ironic instructions are furiou +1636|Customer#000001636|t1VhiA5gssjGA4,o5b2e8WJHsaBAmCfm4G|20|30-559-573-5410|3228.88|FURNITURE|to beans are quickly carefully regular dolphins. regular, ironic dolphins de +1637|Customer#000001637|dqGWqAXF4JuL7FcYH7r9dnH3MiT0S08VS7KgD|15|25-177-814-7863|2844.51|HOUSEHOLD|the quickly ironic instructions. packages poach blithely express instructions. even packages haggle sl +1638|Customer#000001638|Gxgb1kyTwOAoVu0fqaRQk4KCyWzkULGTy6tkpdOx|17|27-548-377-6273|-411.15|FURNITURE|lly regular accounts! express attainments maintain carefully. furiously pending pi +1639|Customer#000001639|QWbeop69wQqRFQbySM7WqPGTSd7fW6QMFYIjL|1|11-304-833-1391|6651.19|AUTOMOBILE|nt deposits cajole slyly blithe pinto bea +1640|Customer#000001640|lGeZbMEg03r24lUuK|8|18-270-772-6060|2622.28|BUILDING| regular packages are slyly among th +1641|Customer#000001641|XT5DXFdGy4kjb|12|22-791-967-1788|4611.37|HOUSEHOLD|unts through the slyly pending platelets integrate carefully dependencies? blithely ironic +1642|Customer#000001642|UgLWC4Pw,XZX52b8hcEixGxk,J|9|19-134-303-4344|6248.64|FURNITURE|uick requests. furiously ironi +1643|Customer#000001643|,vdC1qp8aweR4z4 sTdnhujyZn,|13|23-553-752-7340|1982.44|BUILDING|ites. slyly pending accounts across the dogged excuses can are according to the bold packag +1644|Customer#000001644|la3oZuddBtIVanskRXO8|8|18-235-782-9940|8808.00|MACHINERY|thely final dependencies above the deposits boost fluffily above the ironic, express theodolites. ironic theodol +1645|Customer#000001645|2gNNcbkeFHKEgl4WSW7G8XpXL0VW,6MtTc0G|16|26-174-526-8279|7085.79|MACHINERY|ic theodolites. furiously regular theodolites nag furiously carefully pending pinto beans. blithely unusual de +1646|Customer#000001646|RQ,TryFh5loGPxszvCgRncdO5kM daRcgON|24|34-268-537-8282|2854.29|MACHINERY|re according to the ironic, ironic requests. ironic packages wake after the special requests. +1647|Customer#000001647|aLfdvxbHzfKz2CAdiOgKiJ|16|26-784-323-3431|9987.11|HOUSEHOLD| final deposits nag. sometimes final dependencies d +1648|Customer#000001648|e3oTXQ7OOTzwcRFXr|23|33-718-723-5373|2389.14|AUTOMOBILE|d sentiments eat carefully unusual instructions. unusual war +1649|Customer#000001649|7n8CvxEE4tthklLyRNZIMQds5rruRPiQLLdV|4|14-308-532-5953|2271.45|BUILDING|te across the blithely ironic packages. blithely final accounts among the quietl +1650|Customer#000001650|6mpXm8FQzetQ7wA1pzEmuYVcVp5 fnDk|24|34-295-469-8581|4183.71|FURNITURE|express ideas along the regular requests sleep furiously alongside of the fluffily ironic courts. idly final +1651|Customer#000001651|whCw6gMwEuls sCrsaB,DQI0,|3|13-593-198-5028|1614.35|AUTOMOBILE|eans. blithely final requests according to +1652|Customer#000001652|uDJ6cxL10W sEd4,O7,rdoxst2Sp1Ij72Jb1|7|17-670-200-2924|4335.18|MACHINERY|ainst the close pinto beans. furiously final asymptotes across the even deposits +1653|Customer#000001653|PQFMr5tmEgBCF7rww29Vc yMrHY9HJk|8|18-150-322-1853|6338.28|BUILDING|ic packages. platelets along the slyly pending dependencies sleep slyly alongside of the slyly +1654|Customer#000001654|igHSnmh 6yMC3vF|5|15-299-167-7023|1522.54|AUTOMOBILE|thely unusual requests boost slyly special, final requests. quickly exp +1655|Customer#000001655|DjCE7uReh1B,,ikdShz9W3PCfqkJow|5|15-306-607-3769|1214.81|BUILDING|s. special, bold requests haggle fluffily. carefull +1656|Customer#000001656|m3BvBNeQ1O eV1Bnn3y,MkEx7Io8GkfQ|19|29-904-708-2645|-664.93|AUTOMOBILE|furiously pending packages cajole regularly requests. fluffily even foxes wake blithely. furiously bold +1657|Customer#000001657|MSSbpflkYXCciBa|12|22-113-887-8875|9376.24|FURNITURE|ckages nag according to the regular +1658|Customer#000001658|5ZAXRv0hnyOcjObHR1ScVOZ77ncI,0|21|31-949-978-6932|9525.19|BUILDING|press instructions. carefully express requests are against the blithely final +1659|Customer#000001659|6,g4PcDD8cCUdAKNbhAmwyG3lqEKuUbq|11|21-545-972-9730|4982.96|MACHINERY|ake. regular, unusual instructions sleep quickly carefully even foxes. regular sauternes acco +1660|Customer#000001660|ClPcSJym47fEQW78Kt4|21|31-870-788-5315|3581.59|AUTOMOBILE| accounts breach slyly. permanent deposits are furi +1661|Customer#000001661|IRXXgB,YgRc078y2i1C,87 1wZ|0|10-582-676-4365|1760.90|HOUSEHOLD|s. ideas play slyly slyly bold theodolites. furiously ironic packages na +1662|Customer#000001662|fImm0 WZ JU39aNmhsh5WKcnCqXW|13|23-691-593-1242|3333.02|MACHINERY|nic accounts sleep carefully across the fluffily unusual pinto b +1663|Customer#000001663|7PGRXPj1HXVQUbcL S2|16|26-507-387-2886|4085.85|HOUSEHOLD| slyly ironic deposits. daringly regular requests haggle slyly. ironic dependencies cajole furiously +1664|Customer#000001664|LWrtr,G ifu9pwmSc2HknzWQS,o0FOMGucsq7Rdh|12|22-597-130-8584|6912.53|MACHINERY|thely ironic requests haggle slyly. quickly ruthless dolphins are slyly ironic requests. carefully special +1665|Customer#000001665|26NoCK4dbtU7jmEhrXSuq9rtQWM042UYODGFm,|9|19-542-708-2762|5869.13|HOUSEHOLD| wake furiously carefully even id +1666|Customer#000001666|AFCMGLIrCORZavTw7YX1dAVlJIk,aYlH|22|32-587-573-6083|3562.78|MACHINERY|fluffily regular ideas nag furiously. even accounts haggle carefully among the furiously final +1667|Customer#000001667|aEGS4v41BVwqZylqNvPj|16|26-528-257-9769|4649.03|AUTOMOBILE|nments; unusual deposits wake according to the regularly unusual deposits-- fluffily express requests sl +1668|Customer#000001668|CS067JF7eX,ax,vrx8wx|23|33-184-926-5421|1305.72|MACHINERY| ironic platelets must wake fur +1669|Customer#000001669|i38,,EDjrqVpk1UKXsl9cCdAwS,HpcFqPS|6|16-172-628-3560|9180.72|HOUSEHOLD|quickly unusual packages are. furiously express ins +1670|Customer#000001670|YP A2c1cFpn|18|28-571-377-3401|1472.96|AUTOMOBILE|ge silently. packages haggle quickly final packages! ruthless dependencies cajole ruthlessly q +1671|Customer#000001671|6yWHFFBO5YDpHN,YmYEpxulL|2|12-269-842-9419|4030.97|HOUSEHOLD|otes run slyly ironic deposits. carefully silent requests use slyly carefully ironic epita +1672|Customer#000001672|ZqEat15B3nCQI4MaRoxdfhN3WIH96vWpUs80z4|23|33-169-930-6985|8586.04|FURNITURE|sts. thinly final accounts are about the blithely regular foxes. blithely even dolphins promise blithely speci +1673|Customer#000001673|uQi2r9akwS4LNd7XQEa|3|13-713-161-3704|5714.73|HOUSEHOLD| slyly. dolphins wake carefully even deposits. quickly even dolphins grow slyly. express, regular deposits +1674|Customer#000001674|VDSnyhnkkFA1CKYDjdMx4Hpt1QaZ4g,1cy9Fnr|3|13-396-137-7834|4568.47|BUILDING|equests use furiously at the carefully ironic requests. unusual deposits boost slyly carefully even fox +1675|Customer#000001675|YvuT73pnh06wLlgAyTO1ZyZ4w,2e5Wk MGnbFO|24|34-888-827-2907|261.00|AUTOMOBILE|eep carefully. even deposits cajole furiously around the boldly final deposits. dep +1676|Customer#000001676|WgQKmlxIcGQz86n5sQMbWUu8cg7UG7W3r|5|15-612-997-6342|6504.47|AUTOMOBILE|s. even asymptotes boost blithely +1677|Customer#000001677|7PgxZfn 6hX3gSjJzRq|5|15-121-397-5027|650.89|MACHINERY|inal asymptotes haggle carefully packages. slyly ironic req +1678|Customer#000001678|xq R0 eIkV019MjY8yRdj r,Gfd|4|14-624-973-2343|3396.57|MACHINERY|sits. fluffily even instructions are again +1679|Customer#000001679|EBr12ymXS5u3,9Bh6Cd8VCsmJ9cOR8nuS|18|28-730-907-3502|5172.53|HOUSEHOLD|eep quickly. furiously express excuses haggl +1680|Customer#000001680|jYhr0a6R8XTw8RR3XJQ1kToU5H|18|28-465-621-9214|-203.01|HOUSEHOLD|ithely unusual patterns above the unusual ideas cajole blithely according to the fluffily expre +1681|Customer#000001681|QxfVn4jW30|16|26-375-137-8121|6996.10|HOUSEHOLD|tions among the ironically final accounts haggle according to the carefully unusual instructions. fluffi +1682|Customer#000001682|8TtqhjtXrYlzMxQ17N|17|27-438-398-2565|2459.75|MACHINERY|. blithely bold courts sleep carefully except the furiously unusual platelet +1683|Customer#000001683|ecOqgCbaUID9JwYZuvSrFxXH9dIDaV|22|32-209-661-3831|942.28|AUTOMOBILE| carefully unusual foxes doze according to the platelets. bo +1684|Customer#000001684|7t,Vo69PIG3t,ncWkzoLCJ8A,V28nMkK|6|16-197-588-1571|5928.82|AUTOMOBILE|d cajole about the ironic theodolites. fluffily special deposits about the enticingly blithe +1685|Customer#000001685|3Mg0g4AXNPa|8|18-694-638-1767|5621.33|MACHINERY| sheaves. regular packages nag slyly afte +1686|Customer#000001686|EYR2WxcOKG 4rIlcO9wbkAtID7PJOVkcPaC|12|22-241-190-8777|7782.48|HOUSEHOLD|osits sleep furiously about the closely ironic pac +1687|Customer#000001687|lNxhAZMB,t1bbxFz7UXI0gFWhw|23|33-345-542-8289|8151.36|AUTOMOBILE| boost blithely at the furiously special requests. ironic, unusual requests +1688|Customer#000001688|KE2TYjMt08|3|13-420-827-4701|3929.06|BUILDING|ckages use slyly. pinto beans haggle regular instructions. blithely even theodolites cajo +1689|Customer#000001689|oYgoEWSydzBD81VB3q20DEx8TgSUX6qio,zpL83p|23|33-974-102-7427|705.64|MACHINERY|y silent requests according to the slyly final deposits poach ac +1690|Customer#000001690|v2dVbJH3RxbBj5Wk5btJdzv9K35jXAoxhRYVthO|1|11-869-223-3212|-381.24|MACHINERY|riously throughout the slyly express accounts. slyl +1691|Customer#000001691|BvajZGLJDqzvJfZKsuVjdwaixCO|12|22-649-185-6921|3367.22|AUTOMOBILE|side of the ironic packages. fluffily special asymptotes among the slyly unusual foxes haggle slyly b +1692|Customer#000001692|C3n33KUNrCXK|7|17-625-330-9211|6921.50|BUILDING|. quickly unusual courts use furiously carefully ironic grouches. blithely unusual accounts sleep carefu +1693|Customer#000001693|k9j7wuuKPs8gE|12|22-402-777-3279|2747.22|MACHINERY|carefully special packages cajole. blithely bold +1694|Customer#000001694|jCLu0ZDrLdq7wFEJb|4|14-609-696-9902|3535.57|AUTOMOBILE|the pending, special Tiresias. fluffily even deposits wake carefully theo +1695|Customer#000001695|ihGFlPO39VGgr7xRcR7AM1BFKn9pDq3C|16|26-263-151-5237|9258.82|AUTOMOBILE|press, express packages nag. slyly special asymptotes sublate. regular, even +1696|Customer#000001696|HIJoLNtvjJbh5H0PturTaOBtSAQ3T,j7GSqq|16|26-115-967-9585|4978.11|BUILDING|eans across the even attainments haggle carefully above the furiously express req +1697|Customer#000001697|TQj18iiC1gziLOnTileoy|24|34-288-313-5272|-913.24|FURNITURE|nding dependencies wake alongside of the sly +1698|Customer#000001698|Xzkyij4D5OOWYsaWsucYV0|22|32-926-560-9683|5109.01|HOUSEHOLD|uriously ironic packages cajole slyly! regular deposits alon +1699|Customer#000001699|lGzEu5g4oOROn4QvjK8fEd Z,Y9Vn7IV7EnlE5|1|11-655-675-5843|-813.01|HOUSEHOLD|ngage ruthlessly alongside of the carefully +1700|Customer#000001700|DK3nJU9doE2BtBjQTFApwnLxOCSD |21|31-868-665-9539|6683.70|MACHINERY|ound the furiously final hockey pla +1701|Customer#000001701|IbyUBDvH,eRszYTbnEDHGu16B4UsJSbQaA7F |3|13-397-730-2856|9986.13|FURNITURE|gular ideas. deposits about the busily unusual deposits are furiously ironic theodolites. quickly e +1702|Customer#000001702|ZUf5SwR,j3HdY TBel7Mk|19|29-110-823-3729|8048.90|HOUSEHOLD|e quickly pending accounts-- carefully special deposi +1703|Customer#000001703|7qJL pH9GSS4BZ Nc31|19|29-687-882-9664|8889.69|BUILDING|the ironic, final accounts. qui +1704|Customer#000001704|G4lZ0VRWfLKldLDFR3,bA|16|26-425-543-6950|5145.40|HOUSEHOLD|fully express requests about the carefully regular deposits use carefully +1705|Customer#000001705|lvZ9qSNhUMiE0LTOzmU7,NgjBo6VvcGrs|11|21-470-157-6516|5688.31|AUTOMOBILE|s sleep carefully. fluffily regular accounts haggle furious +1706|Customer#000001706|FBx04exFTAFFRA3G,UR9Q2XSM1c8Uopaal2rEFv|2|12-442-364-1024|455.15|HOUSEHOLD| beans after the ironically pending accounts affix furiously quick pla +1707|Customer#000001707|MjHpj4aS20ftMyK5EMEk87p|11|21-859-412-6010|2714.86|AUTOMOBILE|. carefully even requests nag fluffily after the sometimes regular instructions. quickly bold foxes among the idly +1708|Customer#000001708|BdT2freRSXKa31JLnSBliCXmhi8J|2|12-857-766-2851|9702.83|AUTOMOBILE| always. requests are furiously packages. slyly regular tithes c +1709|Customer#000001709|x0 eZbj1iyKLgjF8qImD|11|21-877-394-8667|9588.88|AUTOMOBILE| deposits. blithely regular frets +1710|Customer#000001710|6kwF3TSVbf,JAh3PAjc0NSHHvdEGWjxVf2us|10|20-393-759-9313|8409.91|HOUSEHOLD|gular asymptotes. furiously silent excuses sleep never-- blith +1711|Customer#000001711|Mhg8c9IAFb8G|15|25-302-946-6337|4421.61|MACHINERY|gle carefully. final, even deposi +1712|Customer#000001712|Qdv0r7aA5tmEZw JkozgH|18|28-959-477-6941|7013.72|FURNITURE|le blithely. regular, regular dependencies integrate slowly a +1713|Customer#000001713|saqFezmCXyr2f2sGR3WexM8MSf03S|15|25-566-819-3545|1627.04|AUTOMOBILE|cial deposits. requests alongside of the +1714|Customer#000001714|6xIlLyed lGGxdneig8xdrvHZYHuLldIGeJu|23|33-251-747-7039|8569.50|BUILDING|ar packages. carefully final accounts wake carefully. slyly even ideas above the closely special reque +1715|Customer#000001715|TNwfsu3dIIti|12|22-283-174-5611|2587.36|BUILDING|slyly regular accounts. quickly furious accounts sleep blithely alongside of the carefully special packages. ironic +1716|Customer#000001716|FmPtChYDv7s7KX5Zi8Ug9SGMajKrQYRuv|20|30-299-232-8737|779.07|BUILDING|. final accounts use. furiously ironic asymptotes d +1717|Customer#000001717|HufIAAW0Xbs3qoYpAVxk4KKvm,F|3|13-450-115-4347|1715.40|MACHINERY|s doubt. blithely silent accounts try to haggle: blithely ironic pinto beans boost furiously. carefully unusual a +1718|Customer#000001718|z2SLViCW5QBh8FDiy3|24|34-842-694-7686|8697.88|FURNITURE|s sleep furiously about the carefully pending asymptotes. +1719|Customer#000001719|eOix0jv6gCP34oQBO2i2z1UugzE1hwWx28n7Uog0|9|19-261-141-3893|4257.24|BUILDING|ully furiously ironic courts. even asymptotes sleep! regular, ironic dependencies are. carefully silent theodolit +1720|Customer#000001720|CIRvBtD2pSJ2b2hoqOxhj|7|17-681-485-3576|5496.84|BUILDING|sly even accounts sleep carefully-- pending excuses sublate slyly. slyly unusual foxes al +1721|Customer#000001721|qRNwOW8G9E5fOvG,,W7HDgv|9|19-288-344-3668|5484.48|FURNITURE| furiously. foxes cajole. instructions after the bold instructions +1722|Customer#000001722|XqgWxT4hlg2EjS0HaV6XQwclVGN09kfwUJa iX|1|11-252-319-1249|6718.86|BUILDING|posits. furiously regular requests are fluffily ac +1723|Customer#000001723|riRitYAsJ0nPLmAnd5JX,8QpE2F9iZIKXAg|22|32-609-708-8185|6893.86|AUTOMOBILE|e the carefully unusual theodolites. bold, even deposits alongside of the pending packages s +1724|Customer#000001724|oCZhgKIkixlfOYiqSXqzeiUAV9ctBQSRsW55G6n|11|21-327-332-4432|123.03|AUTOMOBILE|ven packages. fluffily final deposits nag. carefully ironic dependencies unwind b +1725|Customer#000001725|deDnuDKB3fZczOWTxwxutP|6|16-227-800-7867|8778.07|FURNITURE|he furiously stealthy deposits. deposits haggle quickly among the final packages. carefully expres +1726|Customer#000001726|Gi5q77BDziKnHUbMcbOrja22sv|13|23-199-630-2326|-879.29|BUILDING|lithely final foxes around the ev +1727|Customer#000001727|g7iJ1HSEmxE1sd4lWLV XcE64HA2JHYqPEJBA|23|33-952-217-5029|3628.03|AUTOMOBILE|e regular excuses detect carefully spe +1728|Customer#000001728|ZbokjPCGrcUuysUjYtzQRK9gQSSNK CkFo3rh8i1|16|26-560-950-6812|1223.09|AUTOMOBILE|regular pinto beans; bold packages sleep. blithely ironic requests boost carefully furiously fin +1729|Customer#000001729|qc3FBSbJHHDIEkku69mWsz,KO|5|15-361-394-6195|6479.07|AUTOMOBILE|y even depths sleep silent accounts. evenly final epita +1730|Customer#000001730|p8wSGXOVmXO6rJBW3jgEjcFYRKW0jVY|1|11-216-159-3328|2743.27|HOUSEHOLD|efully final somas hang slyly. dependencies over the blithely regular requests haggle carefull +1731|Customer#000001731|YOLyjZXp0eenovcSOSR4cShVAvSLDG84VTtB7|2|12-671-588-4662|3075.42|MACHINERY|sual gifts above the blithely bold packages haggle slyly pending attainmen +1732|Customer#000001732|2ZHJonGizgo0QYzPxNF1PubW|2|12-505-455-1597|8512.55|BUILDING|arefully even deposits would cajole about the sometimes final requests. slyly silent ideas accordi +1733|Customer#000001733|RO7fzBGXbovRqHEQln,fPJza9UAmIOe,Q|21|31-150-385-3780|2568.57|BUILDING| pinto beans nag! furiously pending deposits grow blithely even tithes? pending, ironic requests impress. regular do +1734|Customer#000001734|Hj4hmdNc2sRBgG5YO4mz5q 9|8|18-264-978-2762|3888.89|AUTOMOBILE|inal asymptotes along the final platelets nag above the quickly regular requests. slyly final request +1735|Customer#000001735|59,bPx BNSZ1YJ9thet9N|10|20-343-415-9202|7495.94|HOUSEHOLD|efully along the special realms. ruthlessly brave courts cajole carefully carefully silent reques +1736|Customer#000001736|t3 1Dv36zNjBXauc2HKcSLJk,QRu4t|7|17-572-741-5408|-686.49|HOUSEHOLD|s! slyly sly requests above the expr +1737|Customer#000001737|Mdj2vXS04lbiu1hlBPSpA6XliT0yq,XL|5|15-973-473-2767|-917.33|MACHINERY|wake furiously even deposits. busy, bold grouches integrate q +1738|Customer#000001738|dKNfooI8lr6G0yb19Oug|8|18-263-208-3553|2290.69|AUTOMOBILE|mptotes. courts about the ideas nag requests. quickly unusual multipliers print after the pen +1739|Customer#000001739|lhga8XGNRXPfJTotgUTn5qc4ush|12|22-216-512-8595|8526.70|FURNITURE|ut the fluffily regular foxes. regular accounts haggle. special deposits affix carefully. even, final +1740|Customer#000001740|7SEO3ug3RMgpphEQ6Ozn2N22VGruDJA|19|29-148-722-9708|9323.31|FURNITURE|ronic foxes sleep carefully forges. regular, ironic pinto beans promise carefully across t +1741|Customer#000001741|W9G SogT0038gQBdoLtFsexbHqNl|20|30-605-828-6050|-0.28|FURNITURE|sits wake carefully final Tiresias. carefully unusual requests sleep +1742|Customer#000001742|t3PI5OUN02V0BSuoWRvpEcxhY6qX 3IxBOq|20|30-777-207-9522|4273.99|AUTOMOBILE| regular theodolites. carefully ironic packages are. even, express foxes h +1743|Customer#000001743|F 5AwQdqqG4K q Ra2AZ0DIsKLNwhtIgHVxIr|16|26-867-792-6806|985.87|HOUSEHOLD|riously regular attainments. furiously unusual pinto beans cajole slyly daringly r +1744|Customer#000001744|cUBf1 YMJEgbt2XDeQWD4WinTu4iFIF|17|27-864-312-2867|1436.96|FURNITURE|egularly bold, ironic packages. even theodolites nag. unusual theodolites would sleep furiously express +1745|Customer#000001745|pAo6p8Q,xr4Y|22|32-624-467-3275|3907.29|BUILDING|final instructions affix fluffily alongside of the blithely unusual pinto be +1746|Customer#000001746|f8Ku1TqpFJ 4wU,s6clle8G|17|27-110-285-2511|8774.31|HOUSEHOLD|ions cajole ironic theodolites. slyly even requests wake carefully. blithely regular frets integrate furiously agai +1747|Customer#000001747|xSJopUGOWIGwa2QJA9mbIzcLAA8OM|15|25-493-381-4100|1962.62|MACHINERY|furiously furiously ironic theodolites. stealthily reg +1748|Customer#000001748|4MaVm9Yox5xeu|13|23-496-856-9633|5779.19|AUTOMOBILE|y pending ideas. furiously regular instructions are. quickly ironic depo +1749|Customer#000001749|lgY9SnA8QnkA7x2LAje7MGsVYB|4|14-247-462-3766|9788.66|AUTOMOBILE| carefully ironic packages. d +1750|Customer#000001750|PBWOGiTcFiFucs8kN2h ,ACNS NC|16|26-538-454-1606|110.26|HOUSEHOLD|packages are stealthily final frets. regu +1751|Customer#000001751|8KIBa2IJPXquMkWYLAccUT|7|17-460-999-8173|3151.94|HOUSEHOLD|ithely regular, even accounts. unusual packages lose furiously; asymptotes nag si +1752|Customer#000001752|CZzZOOncqNdRX|5|15-542-683-9661|7585.99|MACHINERY|uriously unusual accounts. carefully unusual dependencies shall have to play sly +1753|Customer#000001753|XlL3uXUfcHDfQ 4unoq pbTPbUzO|11|21-214-570-7769|5787.81|MACHINERY| carefully regular asymptotes a +1754|Customer#000001754|wXsAA1ZgkeofaPGeZaIe|0|10-154-971-3056|759.00|BUILDING|requests. stealthily pending requ +1755|Customer#000001755|emfcQnwjix1Ul0eKbHP|3|13-333-888-8618|5389.05|MACHINERY|detect blithely about the fluffily regular foxes. slyly regular requests wake quickly about the final foxes +1756|Customer#000001756|q8WlGuUrrao7fWFp4pZE|19|29-962-368-3523|8817.44|MACHINERY|press pinto beans. accounts could are blithely carefully express dolphins. blithely bold deposits detect. eve +1757|Customer#000001757|jY0jJh ww3hLh8eLmmJvKhIL47ka2j1uAys|6|16-868-947-1151|830.36|HOUSEHOLD|, bold instructions integrate slyly final accounts! carefully final accounts caj +1758|Customer#000001758|xvGuRiXuKNuXABjdfERW8jl7b5FdFNo|16|26-263-427-8796|5746.38|FURNITURE|old bravely. ironic dugouts are slyly. carefull +1759|Customer#000001759|2hzwTzhbdHJlHbT0jWD6lKTGA|20|30-176-851-5565|8396.37|MACHINERY|tect furiously. permanently even requests ac +1760|Customer#000001760|HcnL7r33sIo1SAwc5|9|19-539-811-6674|7775.38|BUILDING|ts are after the regular theodolites. dar +1761|Customer#000001761|ypll07IxByF9atO nGkJo7R8Tds8Wq |21|31-376-476-3692|9846.97|BUILDING|en requests. accounts sleep quickly around the carefully e +1762|Customer#000001762|LD,Y0Xj io6wJYOZJI|15|25-319-745-1408|1171.92|AUTOMOBILE|ng accounts. thinly regular packages across the furiously ironic accounts wake fluffily accounts +1763|Customer#000001763|Co2ATzqcl61Cd|1|11-738-302-2342|4490.23|AUTOMOBILE|manent accounts use slyly regular requests. carefully special packages after the pending +1764|Customer#000001764|rlpLd5W4dwxpO7aAVKa7YlZHnwOQCziuByOrK|13|23-308-606-7773|5331.37|HOUSEHOLD|sits sleep slyly. even, ironic instructions breach permanently regular foxes. furiously silent platelets abo +1765|Customer#000001765|YYXRIFQJ4V9paDLFCd13|9|19-538-728-6104|7409.60|AUTOMOBILE|final, special deposits sleep carefully furiously special deposits. evenly ironic p +1766|Customer#000001766|n4uulup7FP1ZLXvSRHveY,TXBOTxs0pj67|15|25-155-396-7616|200.00|BUILDING|lly express foxes. blithely final deposits cajole doggedly regular theodol +1767|Customer#000001767|ddqHp2,Ylt8vN8Pf|12|22-421-403-9852|4369.15|AUTOMOBILE|e carefully atop the even theodolites. pending, ironic accounts hinder among the carefully regular foxes. c +1768|Customer#000001768|kId4M 0RG9dW9Po|17|27-746-769-7890|5356.96|AUTOMOBILE|s. carefully even requests are. spe +1769|Customer#000001769|mrche55tm5KGuJb6lGWqCeKKIlZ rj4|10|20-708-644-8998|8457.18|AUTOMOBILE|furiously silent packages. bold, bold theodolites sleep quickly against the quickly ironic theodolites. slyl +1770|Customer#000001770|IonoL5JlAeGYQFKq2k1sKH0QscvwaAYdrpFSxHV|18|28-976-259-9388|6876.37|BUILDING|ole. furiously regular pinto beans affix blithely inside +1771|Customer#000001771|evmQypmt DbfynZ4bXvm0KUNtyvynyDp3zjcXX|11|21-345-763-5234|3151.21|BUILDING|tes wake carefully according to the unusual accounts. fluffily regular theodolites na +1772|Customer#000001772|AQla93nCHVF6jkq,J|13|23-887-525-9315|6394.26|MACHINERY|e slyly ironic requests. furiously bold courts thrash blithely bold foxes. slyly express foxes +1773|Customer#000001773|StUAItIdmWQdpF6Gz|19|29-729-630-8987|7378.35|HOUSEHOLD|are furiously after the carefully unusual dependencies. ideas sleep furiously. slyly bold packages +1774|Customer#000001774|5pstbh4XaxP91 ,wNQFbR|8|18-753-365-9994|2922.61|AUTOMOBILE|furiously theodolites. blithely unusual ideas main +1775|Customer#000001775|RUY1tS8uCKV1DrB|2|12-544-332-4550|3221.15|MACHINERY| the furiously silent packages. pending, final accounts breach. instructions according to the quick +1776|Customer#000001776|,iyGlh4 Wrn2|22|32-425-716-3547|4801.42|BUILDING|l packages. slyly regular requests wake ruthlessly above the blithely bold dependencies. unusual, ironic in +1777|Customer#000001777|54GpDEcWWIDVMRjP3|24|34-469-776-4539|-535.08|MACHINERY|ar packages? blithely regular instructions along the fluffily ironic theodolites believe ironically aro +1778|Customer#000001778|XxR5jsS8OA1xjtocU,KS6F0Pte4Go5|4|14-504-368-5987|2772.31|BUILDING|eans. regular, pending packages haggle blithely regular p +1779|Customer#000001779|3iow2GjE85s8GnxfNO,fnr9T|23|33-986-427-8764|7233.18|AUTOMOBILE|ly pending instructions: carefully regular excuse +1780|Customer#000001780|ZIeOfVh8umRYig|17|27-213-387-3335|5137.48|FURNITURE|patterns use carefully about the slyly even foxes. furiously regular excuses about the furiously careful packages af +1781|Customer#000001781|JYtJY4OTZQUaEQlfDEeVkK4mtO|8|18-350-885-2317|4686.31|AUTOMOBILE|s cajole fluffily. platelets believe quickly. furiously even accounts wa +1782|Customer#000001782|ehV3 VRXVZ9SR3|21|31-246-927-6074|839.66|AUTOMOBILE|beans. requests was about the blithely regular foxes. unusual, final platelets sublate accounts. +1783|Customer#000001783|ey2RVFXAj5c1qisLEFJA43S2|3|13-239-528-2710|8131.81|BUILDING|dolites. ironic excuses shall wake blithely slyly even theodolites. quickly ironic asympt +1784|Customer#000001784|Zs8QpbcHZfcVJ6oujM8g69J|15|25-605-903-3007|5458.37|BUILDING|n frays. blithely ironic theodolites haggle carefully. blithel +1785|Customer#000001785|nnCUQ01AgIgYBDsdHteH4u0na6WiXvBv|23|33-475-488-7723|7805.55|FURNITURE|r packages was. permanent requests are special deposit +1786|Customer#000001786|pZAHd2LxDUbgcS1WQBN4vvoR5BeNpckOkl7DhG9|6|16-436-900-4501|-51.99|AUTOMOBILE|nts sleep among the quickly regular excuses. slyly even +1787|Customer#000001787|l9Rin,i89mx8LxSK0cC0BPi3OBcM3BXp|20|30-258-449-6408|4120.78|HOUSEHOLD|ts above the quickly regular instructions cajole about the attainments. carefully +1788|Customer#000001788|4,Lldd8YNe,DOiCq2dSW4JL0uqjdVpI2yW4fZMDI|24|34-826-793-6480|-45.96|BUILDING|tes promise. carefully final requests use above the blithely express packages. carefully even theodolites na +1789|Customer#000001789|lfHQVe9IPEKad|0|10-582-797-3122|6407.46|FURNITURE|he slyly express requests. silently daring packages sleep express courts! blithely pending foxes w +1790|Customer#000001790|z IQ1wwki0OLw7biMFHxPKNjp1JBOs7|5|15-805-568-6053|9177.60|MACHINERY| sleep along the special, bold requests. even accounts against the dogge +1791|Customer#000001791|nEuCQJ1,wiJUq7k05FED7j6EjZP0QdzriHsUWZ|8|18-937-127-3890|3917.82|HOUSEHOLD|he furiously final instructions sleep regular deposits. blithely ironic accounts boost among the ac +1792|Customer#000001792|IPqTE3D5cvxDmpveKD6WwW7Pb9ymeAgKs,rT|1|11-561-103-5122|9762.91|BUILDING|to the final instructions will wake quickly carefully special +1793|Customer#000001793|B13zlM7kKBKt|19|29-393-128-9130|7329.58|HOUSEHOLD|ringly furiously bold requests. +1794|Customer#000001794|col5dSe1MO8MyVdQ1f09bhAFsVjYwNH8R4I|7|17-670-112-5044|8243.80|HOUSEHOLD| instructions around the furious +1795|Customer#000001795|EaQbFX VR89kRgd6svC3NK8MSivUK8DZ3y|21|31-853-266-7057|6580.13|MACHINERY|; requests wake slyly after the furiously pending pa +1796|Customer#000001796|HGRGXJA8AwhfBNSyDNn8j3JMvbIwPUKjPTcvKBLs|10|20-905-459-3952|7327.39|BUILDING|ironic, regular accounts haggle care +1797|Customer#000001797|5v4QJxOVHNQ3J6NORJE2edRftfg8 HiGu|19|29-805-690-1846|4461.48|FURNITURE|long the accounts are furiously courts. quickly regular exc +1798|Customer#000001798|fOQAhX8wjDFg8tpeOa L ZdgFlOC69bvmZE|7|17-422-203-8428|6072.64|HOUSEHOLD|hely about the carefully bold deposits. quickly ruthless warthogs w +1799|Customer#000001799|07tCCGrmdFwcXYnolQabgAZW9yq|20|30-643-275-8135|2967.77|BUILDING|requests of the slyly ironic instructions believe slyly regular +1800|Customer#000001800|Cc 1QYWD8JeDlRuyLOEffaanH|16|26-566-785-6289|3323.37|FURNITURE|regular pearls. quickly even escapades alon +1801|Customer#000001801|8ZC3HFVDQGf23cjelZL0wa|3|13-994-265-8339|6806.86|MACHINERY|es sleep carefully along the quickly regular accounts. furiously unusual packages must are permanent accou +1802|Customer#000001802|fGUhRVo61nZfOPxAxzZLrp4z|23|33-720-109-4385|897.62|MACHINERY|c requests. slyly final deposits cajole bold packages. ironic deposits wake quickly around the ironic, special i +1803|Customer#000001803|D7E PteFioyOXeI 422,yZZIsEk|0|10-993-780-6774|3318.35|FURNITURE|its eat quickly around the slyly +1804|Customer#000001804|,TDgHBX9y5eC5ycEwVKbO3gJjXChWmj|15|25-332-547-7897|-516.28|HOUSEHOLD|quests cajole fluffily after the pending, special pinto beans. packages try to haggle. braids haggle fina +1805|Customer#000001805|ZERs4Cu5lQTYD|9|19-679-706-1096|-274.75|AUTOMOBILE|ding tithes. slyly ironic packages boost. final, stealthy requests wake. final, re +1806|Customer#000001806|BB6Vr7W,rSIpWKp|9|19-872-322-3433|254.17|MACHINERY|usly blithely regular instructions. slyly regular dugouts sleep carefully. +1807|Customer#000001807|jlGhIS6zaYIfu9tWFHAyDKVQpOvIluJ1RunV3X|6|16-707-959-9348|1720.94|MACHINERY| slyly final pinto beans sleep furious +1808|Customer#000001808|Z Losr9UXEWwm3RgetdFLr6Q|22|32-507-149-7712|2776.30|HOUSEHOLD|oost carefully ironic requests. fluffily regular foxes boost blithely blithely express ideas. car +1809|Customer#000001809|GqhON8SNyRv|20|30-390-140-3365|8306.29|MACHINERY|ld theodolites eat carefully special pinto +1810|Customer#000001810|RI0cwmW3gNVJiSnIGooUzA|0|10-274-496-6960|923.32|MACHINERY| the slyly special ideas. regular platelet +1811|Customer#000001811|GAuB2XYNF6YxAJgUQO1VcXal|14|24-892-235-8707|6104.69|MACHINERY|dazzle blithely. ironic asymptotes breach; carefully iron +1812|Customer#000001812|UqextI Ph0pve58|0|10-876-771-7164|2515.86|BUILDING| final orbits promise fluffily even waters. blithely +1813|Customer#000001813|xEoR4tsV2Bse527UyeFO8aFhmZ|3|13-604-485-5526|9074.92|FURNITURE|luffily ironic requests doze carefully after the express packages. slyly regular excuses sleep slyly carefu +1814|Customer#000001814|wrzLhEh9DAAHPrh19AGxqCxBWQjO52j4qA1fmqw6|13|23-588-705-2608|5215.32|AUTOMOBILE|ully special packages on the bold accounts sleep among the furiously ironic requests. final requests detect quickl +1815|Customer#000001815|wXx75IZkzX3hsqx5H,PBqxf1CB,cjS|13|23-954-607-5326|3940.94|BUILDING|, bold requests. ironically regular accounts sleep blithely carefully +1816|Customer#000001816|WemZ1IDB0sBS9yyqszdSxqRm8YtGGDme6 BW|4|14-307-306-8692|2328.09|BUILDING|e deposits maintain about the furiously thin theodolites. carefully iron +1817|Customer#000001817|,pNXvEI4pkygH 4wjAy,hPxNikXwej29WH8|7|17-246-120-5754|-862.51|FURNITURE|egular packages. carefully even Tiresias haggle. asymptotes haggle furiously across the quickly pending reque +1818|Customer#000001818|wSYuvOMT8YVZqRDS1YCGrALb|22|32-897-843-2620|-331.97|BUILDING|about the blithely regular requests. ironic requests sleep. blithely pending accounts are according to th +1819|Customer#000001819|pfaH03EbQcSE64yOEnKz7mwHHn|18|28-832-601-3029|6435.85|AUTOMOBILE|y even gifts haggle since the slyly bold warthogs. +1820|Customer#000001820|RsTONzasImDok,RBqc2J09pa29w8gSf6JDIuCBx|6|16-496-603-4437|2282.18|BUILDING|ymptotes affix fluffily doggedly express packages. ex +1821|Customer#000001821|QlxYI,DDZRUAyyVfdaF4q nurCpm,3FltjM|11|21-278-374-9593|8593.01|FURNITURE|tegrate slyly carefully final requests. ironic, regular package +1822|Customer#000001822|H79GEJ2,C0JTus4zVXNjEyMqEFe,7RmzxIGvU5|14|24-524-173-1344|1728.52|AUTOMOBILE|regular forges. ironic packages sleep furiously. slyly fina +1823|Customer#000001823|ci7lCqnRGp|19|29-787-260-1556|9240.38|FURNITURE| furiously. blithely final foxes integrate alongside of the instructions. quickly regular +1824|Customer#000001824|aN7aUMe22hd2LnIqVf7TnJLzSI8uggv,YpldbC|10|20-684-209-1084|3177.51|AUTOMOBILE|luffily regular, pending instructions. slyly pending foxes +1825|Customer#000001825|,E8l78G7k,u0eGXu,sGU1fta2Lg|8|18-969-538-4715|8447.18|FURNITURE|ing to the slyly silent deposits. +1826|Customer#000001826|tbWBFvYUZjBY,BH5r5CQsA71GJIQJNx|3|13-389-673-9030|3891.76|BUILDING|e. bold deposits among the slyly regular depths detect slyly a +1827|Customer#000001827|icXm8xlUo0Ca,T9MoUjkWej3|24|34-815-928-1369|800.31|BUILDING|se carefully alongside of the quickly special packages. regular requests run. pinto bean +1828|Customer#000001828|djbEIhlvmo1i8ZUgTNLFT2f1P|13|23-937-592-5811|6673.46|AUTOMOBILE|into beans alongside of the unusual foxes breach blithely above the quickly dog +1829|Customer#000001829|9TWqvF0jyqs5eJ O0OPAprl0chk8WGTf,|0|10-582-390-6176|2886.86|BUILDING|ccounts. boldly bold foxes use slyly even requests. never regular dolphins at th +1830|Customer#000001830|d6ZvjlxbHL6Kq5y,|17|27-148-316-6372|7363.56|AUTOMOBILE|around the fluffily regular notornis integrate above the final deposits. pending requests nag carefully packages +1831|Customer#000001831|DcW02etJU0N2SmSs3UgkmkPRvao7A|13|23-215-897-5399|7448.78|FURNITURE| thin ideas. furiously quiet pinto beans w +1832|Customer#000001832|VffJ90poBdj 9fq7Hpp0NvcEeeuHg |10|20-337-677-6483|9640.29|BUILDING|. furiously express ideas wake furiously. unusual, bold requests nag quickly. slyly regular +1833|Customer#000001833|KluDIF0rSvGj8mjBA vo7db1bA|3|13-425-435-3864|3418.04|BUILDING|y quickly slow requests? ironic, final pinto beans eat furiously. slyly regular deposits sleep +1834|Customer#000001834| oWU4qpGp8v5pjfHDGwIAh7z|24|34-976-916-8306|2985.37|HOUSEHOLD|slyly unusual packages play. unusual, ironic ideas integrate always according to the thin requests. ste +1835|Customer#000001835|XwMDWDz0zgJT7CpiEZ7Mak8kB6m|7|17-285-512-9067|2081.99|AUTOMOBILE|s. carefully unusual packages along the carefully idle pinto beans haggle carefull +1836|Customer#000001836|0oV7OBdPNyXRqIesxfDU0Ol4So|7|17-927-450-7081|9925.39|FURNITURE|ate slyly idle depths. silent, even theodolites are furiously ironic +1837|Customer#000001837|sWO0VNEY4GzuBq L0vJ5p2|14|24-908-704-5003|-886.94|AUTOMOBILE|unts after the bold, regular dependencies breach a +1838|Customer#000001838|4nF9mi2bj3s82Sv8KPgIsS|21|31-194-756-6301|7142.14|AUTOMOBILE| deposits. regular requests nag slyly-- regular accounts are furiously acr +1839|Customer#000001839|QKjHd6wOQJaxJCOqH2E5P n2tZb3Y|5|15-944-305-1436|3909.79|AUTOMOBILE|haggle furiously after the regular packages. ironic, regular foxes haggle +1840|Customer#000001840|cMNMPjKib0Ez0Bl,cesLvkOl39p4oiUH |3|13-833-461-5939|6879.93|BUILDING|the courts sleep blithely according to the slyly permanent ideas. +1841|Customer#000001841|xJLMIrO4OB|10|20-566-527-9390|8053.62|BUILDING|ts snooze furiously final waters. furiousl +1842|Customer#000001842|SYMcJ0iGluYT2pe6NR5jyErQBODPK|10|20-148-955-7830|233.23|BUILDING|y regular theodolites. packages sleep blithely according to the busy, final instructi +1843|Customer#000001843|5Op16OGLtq5hXrYvKBKPPu,B1pB|1|11-977-879-2346|1821.61|HOUSEHOLD| requests after the never bold ideas hang carefully bold sheaves. carefully pending deposits +1844|Customer#000001844|1BOo5no2lQ8Fa CLDWFaRC8j|18|28-705-205-8653|798.99|HOUSEHOLD| about the slyly final foxes. furiously pending asymptotes acco +1845|Customer#000001845|xHga IhnB2a,|10|20-777-704-2095|6567.69|MACHINERY| furiously requests. even instructions haggle. instructions haggle fluffily. requests along the carefu +1846|Customer#000001846|v0hJC6rlPBHdWAUGg7xm7SEUhpI3wWIO2|16|26-860-238-2408|7115.80|BUILDING|riously regular deposits wake regularly above the slyly unusual requests: unusual packages are furiously furiousl +1847|Customer#000001847|g12l6sqk5YNADO,NEnDg, prphdZp|16|26-677-971-4905|1240.90|MACHINERY|. furiously express packages wake quickly. sl +1848|Customer#000001848|g xIZPvP9AkmbUQa6e|4|14-161-419-6384|8684.90|HOUSEHOLD|as. final, regular asymptotes haggle in place of the slyly ironi +1849|Customer#000001849|vRc6mWLRoRf2ElUvz9byqx2Vt|22|32-730-179-7629|6259.04|BUILDING|ckages. bold epitaphs maintain slyly alongside of the carefully exp +1850|Customer#000001850|yY0Ihs9rn4Jt9qzowqGCKcGYUYVqrOpfKVArQK|10|20-451-644-7838|722.28|BUILDING|lly regular accounts. carefully regula +1851|Customer#000001851|n873H6Cz5A9uHamGSt iIs3|3|13-311-225-1271|4290.76|BUILDING|e slyly regular pains wake slyly final requests. quickly +1852|Customer#000001852|LCTu83UaCBLeatTuc|14|24-811-458-3601|7717.57|AUTOMOBILE|ar, final accounts. fluffily bold deposits cajole. ironic deposits above t +1853|Customer#000001853| z1i M6vmUfw|5|15-442-128-2785|6244.70|FURNITURE|ly pending instructions. blithely special pinto beans sleep carefully quickly final packages +1854|Customer#000001854|CYDzQ3P8qyP,o0ZCHt oAxFNfmlkY18|14|24-654-947-6633|1661.15|BUILDING| the fluffily silent deposits. quickly +1855|Customer#000001855|REHQRPduxffKW5vE8Laf|13|23-239-487-1955|9936.71|MACHINERY|nto beans cajole. pending packages nag quickly according to the packages. s +1856|Customer#000001856|FuvHERUFZy4lUPSGX9WzC6rM3dLy4DRPv21scFOR|21|31-242-270-7219|2381.48|AUTOMOBILE|ic requests. furiously silent requests wake slyly according to the never pending packages. slyly iro +1857|Customer#000001857|4BOgUDmgtH,RyMRb4jUc TDYqFB|12|22-974-598-1668|5485.71|HOUSEHOLD|sits doze among the ironic packages. carefully express requests wake blithely alongside of the theodolites. ca +1858|Customer#000001858|jtVS,lDzoPG7|18|28-940-298-3762|5263.13|MACHINERY| unusual theodolites affix according to the silent instructions. furiously darin +1859|Customer#000001859|MV0YXkg6XVwBzeXMljCiLp|1|11-147-516-2776|4508.50|AUTOMOBILE|t ideas. bold deposits across the quickly slow excuses haggle slyly unusual packages. furiously final ideas caj +1860|Customer#000001860|4,u2YoI2nnY|15|25-432-186-2226|4383.03|HOUSEHOLD|ackages wake on the pending sheaves. bold foxes nag slyly slyl +1861|Customer#000001861|E XEUZYUxRnh0Z1MKcU19Ff2kj7|15|25-966-583-8374|7584.92|HOUSEHOLD|blithely regular instructions detect fluffily abou +1862|Customer#000001862|jDYsot4wXtwiJ9W 7XqR,C|7|17-972-634-9470|9848.27|MACHINERY|s are after the blithely even instructions. slyly regular +1863|Customer#000001863|kfPxNgJute862KvopjfTItHJVC9Hu|16|26-777-313-6429|1024.85|FURNITURE|fily final accounts cajole furiously furiously pending accounts. slyly final requests acco +1864|Customer#000001864|ZTAtP8aj97X246rzbsglEXqogjhEcYybWE3W|22|32-582-138-8697|7669.96|FURNITURE|uriously. final packages detect slyly blithely r +1865|Customer#000001865|0wViSaeE08WI09xFxqr58|14|24-208-401-3922|9112.90|BUILDING|luffily regular dolphins. quickly regul +1866|Customer#000001866|bdPJelrGfDMOilIhvlZNmb3|6|16-520-541-7567|5563.66|HOUSEHOLD|ent accounts about the blithely unusual dolphins are carefully along the special deposits! final excuses u +1867|Customer#000001867|72gC1ZTlzFNQy9CvFosWzE|1|11-951-119-6203|6470.11|MACHINERY|final instructions are according to the carefully final accounts. caref +1868|Customer#000001868|kD u32wkAhHa FvvBM,y6oJVpfZQDcuDBQ|2|12-347-925-5872|6150.48|MACHINERY|onic, final ideas haggle blithely excuses. slyly regular ideas across the carefully bold dolphins cajole sly +1869|Customer#000001869|hOzuX9JGbYqPv677zUdWtUN3,LHdGYcEwqva|6|16-750-945-2045|2181.16|BUILDING|nts. special, unusual pinto beans haggle slyly +1870|Customer#000001870|iAG9OC,akOL06jR|1|11-950-597-6395|4739.19|BUILDING| epitaphs according to the slyly regular foxe +1871|Customer#000001871|,B2hG X848Trk9SZ|15|25-329-168-1291|9528.08|AUTOMOBILE|y express excuses. furiously regular warthogs integrate quickly after the regular packag +1872|Customer#000001872|CTHfC,m5kcnglbJawTVx5x1cJx3lynOTa7|22|32-985-585-5168|9479.72|FURNITURE|kages wake carefully after the ironic, special requests: regular foxes from the special asymptote +1873|Customer#000001873|fvkv57 kYzsIjzXH9,csoT7smnh pObla4,|3|13-581-396-9191|-201.93|BUILDING|yly. fluffily unusual theodolites among the ironic ac +1874|Customer#000001874|DVHIWiilJuI|17|27-133-279-5869|3121.93|FURNITURE|s. carefully final requests unwind furiously among the +1875|Customer#000001875|CiwSrmNO0dw3Bvf, v2NL,|10|20-222-437-7307|9319.39|MACHINERY|equests cajole above the slyly final requests. blithely special excuses nag blithely bold dependencies. blithely exp +1876|Customer#000001876|pUsteCJxfoVJ|7|17-965-399-4552|90.46|FURNITURE|s. ironic theodolites around the specia +1877|Customer#000001877|a1Rycy,Cni7sr7VUyLR|23|33-986-738-5501|341.10|MACHINERY|ss instructions. fluffily ironic packages boost alongside of the blithely final patterns. s +1878|Customer#000001878|EJqsZwacKoF5mzgYOzYM5Tt7tcuJ|6|16-201-771-9025|-120.65|MACHINERY|xes. furiously bold platelets sleep quickly among the slyly bold theodolites. special deposi +1879|Customer#000001879|DsH91sbfSoNl3Ohor9NQGBO94rGJeGRkc4|17|27-652-714-8086|5163.22|HOUSEHOLD|theodolites could cajole quickly about the ironically final requests. blithely even asymptotes use theodolit +1880|Customer#000001880|LRh,W2K0FBWZWB|16|26-331-549-2024|8247.29|HOUSEHOLD|aves are ironic, final accounts. regular asymptotes promise pending epitaphs-- ideas +1881|Customer#000001881|eo82SRJdBgn25wzgDGaYETk70Wj Y3NKEat|18|28-135-437-2467|-780.99|HOUSEHOLD|to beans haggle even, unusual packages. fluffily regular de +1882|Customer#000001882|U3c UftfresD4TjzRl8F|3|13-454-520-9987|5785.07|HOUSEHOLD|uickly regular, final accounts. furiously special theodolites cajole +1883|Customer#000001883|vyFP6B54fLxqmV3RkbkgNbb|18|28-359-399-4989|9692.28|MACHINERY|kly express packages haggle slyly according to the furiously even orbits. +1884|Customer#000001884|TFjb8jysqh0cMWSt36NLtlP|0|10-570-500-9765|8261.18|HOUSEHOLD|s over the ironic requests sleep fluffily carefully bold dependencies. +1885|Customer#000001885|WceTHrKwpwDq4AbQiFFO03R88q2|8|18-986-991-1839|1642.14|MACHINERY|. pinto beans wake along the theodolites. caref +1886|Customer#000001886|rEn7jolYiPkRQDuLU8lSbn|13|23-315-177-8462|9333.99|FURNITURE|ar pinto beans sleep even deposits. slyly special requests are. express platelets snooze blithely +1887|Customer#000001887|F9k42yQM7WJEwLS|10|20-704-266-2935|3370.69|AUTOMOBILE|s wake carefully against the carefully ironic deposits. finally regular attainments +1888|Customer#000001888|3psgNE6QfX,Iw2xTWauq9yL9EkSiD1fAUMXfXu8k|5|15-757-359-6861|-861.72|AUTOMOBILE|ntain ironic foxes. unusual accounts sleep quickly. quickly regular accounts are blithely. fin +1889|Customer#000001889|am4T 9xjY,|24|34-941-762-4541|1977.38|FURNITURE| ideas detect blithely. accounts haggle fluffily against the ironic, ironic accounts. slyly p +1890|Customer#000001890|QvxzOMYHMQUUfnfY3Fhydb|9|19-980-717-9488|704.54|BUILDING|nic sauternes. even pinto beans are carefully express requests. carefully express packages across the blithe +1891|Customer#000001891|xdhHnr2OrFVgZSEY190|9|19-323-409-2180|3069.79|HOUSEHOLD|ording to the blithely final requests. requests sleep quickly according to the ironic, even deposits. blithely ir +1892|Customer#000001892|Mm4BlT6Q10AlsxwZBAoJE,rXVDtArlKo3b,Ysk|14|24-677-485-8489|1917.06|AUTOMOBILE|luffily around the slyly ironic platelets. express deposits hang furiously among the r +1893|Customer#000001893|iFCRrPifE A|1|11-796-419-9244|9971.58|HOUSEHOLD|ccounts among the fluffily bold pinto beans +1894|Customer#000001894|X,KINka,nciwGbK|12|22-832-993-2803|5415.55|BUILDING| final deposits. regular frays was blithely carefully regular platelets. even dolphins run among the +1895|Customer#000001895|PAv4VeG04NXcldWKmT|12|22-350-120-2910|3216.87|HOUSEHOLD|onic pinto beans sleep quietly regular Tiresias: slyly regular excuses ha +1896|Customer#000001896|4QX6hX9fgTooTWKoy6jmMOEpNZHoNJ|16|26-210-412-7721|9849.67|MACHINERY|re among the slyly express packages. dolphins affix furiously across t +1897|Customer#000001897|bizbUJTTu896QHClLsGIeQmcIF5K,7pyN|8|18-397-783-2293|2415.01|BUILDING| fluffily final theodolites. blithely regular requests +1898|Customer#000001898|yK530x63pGQpzYZbGjsmt0INzw2f9oKfocxs0b|16|26-214-695-2065|7975.89|MACHINERY|ar requests. slyly pending accounts haggle blithely. busy account +1899|Customer#000001899|XuQb0moba ,XyN|10|20-243-672-4974|2869.40|MACHINERY| even, idle deposits about the busily final foxes +1900|Customer#000001900|lf78mUY8AHVrPld7M8Ysotn9WoXwKoN|21|31-565-138-3230|-57.96|MACHINERY|kly regular accounts. requests use furiously alongside of the carefu +1901|Customer#000001901|TJVv IWFTUUp ihC 7mzH,ru5s0J9Xb|24|34-736-824-5989|2749.93|FURNITURE|s use. express platelets beside +1902|Customer#000001902|03 VVAFfgEADO1Ert upreETF9E9i1QUgy53i|3|13-815-127-1409|5019.36|BUILDING|after the blithely regular packages. carefully regular gi +1903|Customer#000001903|oNu,vFSWInYzj5wIB5khmgObNMx61UfUap|15|25-489-905-9207|-679.30|FURNITURE|slyly regular requests sleep. blithely ironic packages c +1904|Customer#000001904|qtgYwanpIR3LfvbOPexVyJ8XHDWNn p95|24|34-565-694-9621|9913.42|BUILDING|. furiously special requests haggle finally carefully +1905|Customer#000001905|P xPYefatHsYxGtFYbzin3GqmqPWvR31YlXlOt|19|29-697-760-7269|6862.64|BUILDING|ajole about the pending, bold requests. furiously regular platelets above the q +1906|Customer#000001906|pByvzLPeSKa8Zlh5ncJwAuYK2U|5|15-956-730-8661|3448.10|MACHINERY| the fluffily special foxes. carefully pending deposits by the special, final accounts wake care +1907|Customer#000001907|Wjpx2yEVYfTUHPc9TgXzD64PBqW x|24|34-755-117-7537|2145.93|HOUSEHOLD|carefully silent platelets wake fluffily express deposits. forges against the ironic platelets are silent requests. +1908|Customer#000001908|eT6lmLbi11KA|17|27-275-292-5975|6551.65|HOUSEHOLD|ly unusual requests engage carefully blithely express depos +1909|Customer#000001909|wrQOWC 6kE|19|29-108-892-4321|1605.61|HOUSEHOLD| the regular, unusual accounts. fluffily final theodolites d +1910|Customer#000001910|LQ9x01e0v2qFuNr|5|15-112-377-2843|475.44|FURNITURE|. quickly even deposits sleep f +1911|Customer#000001911|F9kOxmOLLFyC|1|11-369-744-8780|2601.29|HOUSEHOLD|y idle requests poach across the quickly final theodolites. slyly ironic re +1912|Customer#000001912|1AHyJO5HDpo5AiczS 8zP9P9x7PUuoU5wwrTLEb|20|30-784-527-9935|3886.95|FURNITURE|uriously above the ironic requests. blithely careful packages use daringly furiously regular tithes. +1913|Customer#000001913|3Ya7Xzjzd,JayN,jN|8|18-831-659-1744|8031.55|BUILDING|y express platelets. quickly ironic requests hinder quickly against the carefully bold deposits. acc +1914|Customer#000001914|JqCaLg2nQOwrdP1DIHNQ9b,Wk|6|16-458-421-7729|3308.34|FURNITURE|ss pinto beans. quickly unusual packages doze carefully furiously final +1915|Customer#000001915|FMtQbAxpu5v3,0NVxEJwU24sV2TgF|16|26-683-446-1665|7268.98|AUTOMOBILE|s. furiously ironic ideas boost furiously among the ironic pinto beans. accounts thrash slyly about the +1916|Customer#000001916|jFGCdeXJVKzv7YDL|5|15-662-459-4512|1768.76|HOUSEHOLD|into beans. even deposits among the fluffily even platelets cajole ab +1917|Customer#000001917|gZW6epQmK,ISulI9 Qt IWytnY|7|17-940-989-5599|3470.08|AUTOMOBILE|silent packages boost quickly. regular, regular instructions nod. idle dependencies are slyly among the slyly i +1918|Customer#000001918|CRBet8MbYBwTgtdPOzX,ipUvTiOrp0vUQjnr|9|19-987-388-4413|8539.61|MACHINERY| ideas alongside of the blithely regular +1919|Customer#000001919|lnfRcSyQXSI|18|28-664-832-4585|6262.18|HOUSEHOLD|as outside the furiously expre +1920|Customer#000001920|FvwmRwSmKgzj7u4disg0ahJOtEfo|8|18-810-300-8541|9476.97|MACHINERY|uctions believe. furiously ironic accounts use fluffily. regula +1921|Customer#000001921|9AE6JuRlhkABh1m8ABQD4AsBk6x5rXlCQ5I|18|28-644-770-2274|8509.33|BUILDING|lar platelets was furiously above the slyly exp +1922|Customer#000001922|qMXL1bzgCtSj1GLMI3AMi1CNV,f, 0iCXt|9|19-532-924-9245|3398.55|MACHINERY|ake carefully even packages. ironic requests against the express, even asymptotes affi +1923|Customer#000001923|m6AVOkvy swPbt,pZ7b9MBfr8zo9vFUvappyyWjv|23|33-781-817-1440|5376.70|HOUSEHOLD|waters detect fluffily carefully regular pinto +1924|Customer#000001924|inc0YxJOJYunXhf|4|14-472-427-4447|-851.49|AUTOMOBILE|gular instructions boost among the blithely s +1925|Customer#000001925|qZ8m0grVeRJN9h6Bn|0|10-814-492-1424|8891.65|HOUSEHOLD|its sleep among the regular packages. fluffily final depende +1926|Customer#000001926|EMRuUDTA2m0|7|17-203-685-7821|4968.09|AUTOMOBILE|ve the even packages. blithely +1927|Customer#000001927|V4zstahq,OaYcbh2IeSkJfiRO7wtMPXOoV|1|11-876-774-5282|6756.49|AUTOMOBILE|side of the furiously final ideas are at the bold patterns. quickly pending requests thrash fluffily +1928|Customer#000001928|Ce02vQsU97|12|22-812-639-3782|1391.69|MACHINERY|t the carefully final instructions wake fluffily f +1929|Customer#000001929|imHqCzuePilpP5h UA2fwTIJMWVdj|20|30-949-561-2278|2157.13|AUTOMOBILE|osits are slyly across the even requests! busily special platelets cajole carefully +1930|Customer#000001930|kJD6LiynLuutDPKOcgIBUIdUQIWb14oGE jb|18|28-793-928-3242|7909.13|HOUSEHOLD|ular packages snooze blithely carefully express packages. quickly regular dolphins sleep about the slyl +1931|Customer#000001931|DUbNQry9jewVHI6GLNIbX0aIBGoWwsqWabbuXPy|19|29-893-435-8218|2762.06|BUILDING|heodolites. final ideas detect slyly furiously regular dugouts. even pinto beans haggle. slyly express foxes na +1932|Customer#000001932|VhBhkEXBrpSzYgxu1jmIJ3 tVomaDEr|15|25-252-625-7296|-55.92|FURNITURE|fully regular theodolites. quickly express requests may sleep carefully among the furio +1933|Customer#000001933|JGeZTkGT1uwbQa1C,sj|0|10-484-847-9516|4003.10|HOUSEHOLD|es the accounts. close, ironic dolphins wake quickly furiously ir +1934|Customer#000001934|REnXv9yHCBrQTv2i7j645dr5iSY5|10|20-656-890-6862|2038.31|HOUSEHOLD|ons. bold foxes haggle furiously blithely ironic ideas. blithely ironic deposits integrat +1935|Customer#000001935|2SwVYEBhbhWTTWCBsGow0Wu|9|19-674-562-9631|1775.61|HOUSEHOLD|ilent epitaphs wake slyly according to the slyly furious deposits. silent, special instructions past t +1936|Customer#000001936|PGu2Wen188BC|0|10-714-881-1338|8592.20|HOUSEHOLD|y regular packages. blithely even accounts are blithely. carefully regular accounts cajole blithely. quickly bol +1937|Customer#000001937|mXJvkSoAwpg1wVW45|3|13-166-456-2309|-866.47|FURNITURE|equests. final, ironic packages haggle: carefully regular packages mold fluffily accord +1938|Customer#000001938|IqaZSFbDxA,8a,xxnV,gHVOT|10|20-789-331-1347|-894.49|AUTOMOBILE|osits affix slow accounts. carefully final ideas according +1939|Customer#000001939|SBEYKDkrUBAt2RNh1z0dtG|0|10-417-450-5341|1306.86|HOUSEHOLD|usly unusual theodolites haggle slyly around the fluffily ironic asymptotes. express instructions cajo +1940|Customer#000001940|DIL GvUsP25WSgsshTdjULCPxy7l|24|34-475-738-8227|6310.63|BUILDING|e the furiously bold dependencies. slyly silent accounts grow carefully according to the +1941|Customer#000001941|,51rsqq9XV|0|10-365-133-1400|9710.06|FURNITURE|fluffily carefully regular foxes. fin +1942|Customer#000001942|5 eTPX2yTp49JPctgc1EeYMUSWm|3|13-500-263-4736|-947.24|MACHINERY| sauternes. quickly express accounts cajole carefully above the regular accounts. pinto beans +1943|Customer#000001943|sH4nc83Lh,6A2xe9ApH6WD|3|13-737-218-4651|5599.71|AUTOMOBILE|ckages above the final, final pinto beans haggle against t +1944|Customer#000001944|LbrsZ4CFBqJZ|14|24-492-922-6990|7279.93|HOUSEHOLD|s play boldly about the slyly iro +1945|Customer#000001945|ghlnLGw i,LV,MAuts8Ii7XE4WaoExoa|10|20-470-267-5365|9880.10|BUILDING|iously bold pinto beans cajole slyly warthogs. silent, special accounts detect evenly across the ironic pl +1946|Customer#000001946|Z3ceD0uA1BJsDmFl4botusq2SBPCJqIqzr9bHQM|20|30-764-188-4293|7851.87|FURNITURE| requests boost fluffily. ideas detect finally. quickly final deposits nag carefully. quick +1947|Customer#000001947|s 1fCYZ4AqqTJ,ZvJsLi5N|20|30-174-661-7603|8385.53|MACHINERY| ought to are furiously alongside of the blithel +1948|Customer#000001948|4aCCe9W1s4,VdYswJWigEOJ2sW6Thh|5|15-227-107-9153|1704.12|HOUSEHOLD|s about the blithely regular deposits cajole blithely +1949|Customer#000001949|fwIfk5BDREkV uapHbKzYrOCWUz|19|29-227-849-7731|6025.80|FURNITURE|nal platelets cajole whithout the silently regular ideas. furiously bold asympto +1950|Customer#000001950|sRX9I79UagRC3 sV9hO0H|6|16-524-582-1728|7698.52|HOUSEHOLD|nal requests. slyly pending pains according +1951|Customer#000001951|NOXYVa52HyF5lmpj9,WR0|0|10-334-921-5346|5002.24|MACHINERY|thely unusual accounts. furiously unusual deposits sleep along the blithely final packages-- f +1952|Customer#000001952|sZvM,CF54wYyQGhSuFVe|18|28-102-243-6615|8620.01|MACHINERY|y express pinto beans sleep carefully carefully regular pinto beans. fluffily final accounts +1953|Customer#000001953|vd2GjYHxhaYoyE0dU46shW|8|18-155-378-1656|4654.64|MACHINERY|ly slow foxes x-ray quickly even pinto beans. slyly permanent packages nag furiously. carefully +1954|Customer#000001954|ec2Cv6JlL3MFSnbBVWrE vljCiPiM6gFr4WE5PW8|22|32-872-341-1949|7575.28|BUILDING|ep furiously about the fluffily regular accounts. +1955|Customer#000001955|INxAk4G6dbQSijuSR,0t|7|17-649-408-5594|1754.99|BUILDING|usly. final packages doze carefully excuses. packages wake slyly according to the slyly ironic pi +1956|Customer#000001956|sOgO,FYO1KNY3Q45sj asSLH33rFk|21|31-426-823-2422|3007.04|HOUSEHOLD|ess platelets. express pinto beans wake furiously according to +1957|Customer#000001957|Hl2JPoWaDAeyGd|21|31-861-837-2140|3366.66|HOUSEHOLD|al platelets. sometimes final accounts +1958|Customer#000001958|P8lsQKRVNyrMTYEgXU7W|4|14-218-444-2269|8425.51|HOUSEHOLD|quests across the accounts need to haggle carefully regular deposits. careful accounts boost carefully fin +1959|Customer#000001959|NMDtn0GA,CLrZYGaMDmwb|7|17-992-958-9639|2608.12|AUTOMOBILE|ronic deposits: quickly bold packages along the fluffily regular depths sleep furiously thinly regular deposits +1960|Customer#000001960|DFG0YX 4bZQ40vdnfLc8zJfgdWY4iARmum|1|11-645-941-2149|8663.17|BUILDING|arefully carefully regular pains. carefully unusual ideas at the furio +1961|Customer#000001961|j7 XCftSKhgKscMoPW|23|33-428-682-4988|3918.30|MACHINERY|ut the fluffily regular theodolites. dependencies among the +1962|Customer#000001962|VxLrW,XnARNIdQgq1J |4|14-913-275-9532|6907.64|FURNITURE|os shall have to eat bold theodolites. regular dependencies sublate blithely alongside of the express, +1963|Customer#000001963|WFokQKiIqXjIiH|2|12-406-701-6501|680.33|BUILDING|ously fluffily express theodolites. ironic, final dolphins snooze regular ac +1964|Customer#000001964|xEoAWLcXGm|11|21-651-389-8060|3323.69|HOUSEHOLD|osits. furiously express ideas integrate +1965|Customer#000001965|Zf89ewXnl,RNe36J86yVxppUfr6VXEeKGYUa|15|25-361-492-1713|1223.48|BUILDING|ronic, even waters use along the final ideas. ruthlessly +1966|Customer#000001966|jPv1 UHra5JLALR5Isci5u0636RoAu7t vH|0|10-973-269-8886|1937.72|BUILDING|the blithely even accounts. final deposits cajole around the blithely final packages. +1967|Customer#000001967|F1wAzk2iYcb|14|24-936-670-3499|5250.63|BUILDING|ut the slyly ironic pearls. re +1968|Customer#000001968|dUAE71eduW|24|34-192-617-7717|3322.72|HOUSEHOLD|uriously regular deposits use car +1969|Customer#000001969|F7fcrNnwmFLr2fXyi58|11|21-978-965-1419|6864.72|FURNITURE|ckages sleep carefully. never bold instructions are even, final ideas. fluffily even id +1970|Customer#000001970|V9aSisZGbj8fo|14|24-949-639-9364|5469.10|MACHINERY|grate furiously ironic orbits? final, pending deposits affix carefully express ideas. special, express pack +1971|Customer#000001971|DZsft5O035OEx6ql2BKC3CHI3R5ZtlFgKsMs XZM|12|22-293-654-8027|1205.73|AUTOMOBILE|arefully. express packages are above the slyl +1972|Customer#000001972|0XaaQuagZ1K9E63qlSw5SBk|7|17-991-532-5136|689.12|AUTOMOBILE|ckly. regular, pending pinto beans solve around the blithely exp +1973|Customer#000001973|J8,WbeY81R4j4nAv5CEczBfn3XPh2dIcxnhLtdf|4|14-828-797-8149|7990.18|HOUSEHOLD|dolites affix bold, final requests. blithely special accounts integrate. bold, iron +1974|Customer#000001974|e4NzvGNJLIOkXfof8RF21qDH1O|24|34-740-820-4310|1007.21|AUTOMOBILE| sleep against the quickly ironic sentiments; ironic packages affix above the carefully final +1975|Customer#000001975|XzyjsmoapfpiWPo fn|5|15-174-926-1370|8125.51|MACHINERY|re slyly against the unusual dependencies. slyly +1976|Customer#000001976|M2WWTo3je0NgpIFOe55SvtJwnyxY8jp8Ikms4|15|25-703-881-1012|9548.13|MACHINERY| slyly regular deposits. fluffily fina +1977|Customer#000001977|TMAohw9bEg3eDJH|2|12-534-854-9706|5529.03|BUILDING| carefully bold requests up the final, speci +1978|Customer#000001978|e4sYh5qmltXfpKhnO fQF3E9dZuWXu,C0E|13|23-513-770-1875|7503.87|MACHINERY|ully regular dolphins. blithely express requests are furiously slyly regular accounts-- caref +1979|Customer#000001979|HSGMB5gHS1ieJ58hBBImFA9OxE|14|24-690-108-2317|631.63|MACHINERY|ns alongside of the bold, silent requests x-ray after the blithely silent p +1980|Customer#000001980|rhVLwo9PmcGj8oWJSAIYmcbPf 2lCekjg6V6|6|16-721-559-9819|9772.49|AUTOMOBILE|ckly regular packages. ironic packages after the special instructions breach fluffil +1981|Customer#000001981|wctyYavWwznYKAs4|13|23-867-283-2614|3283.90|FURNITURE|ding to the blithely bold deposits. ironic packages detect blithely deposits. regular, specia +1982|Customer#000001982|mpS3z3Av8c89RsaJyiet|12|22-891-773-1026|3567.30|HOUSEHOLD|e blithely courts. even, express re +1983|Customer#000001983|KFNKCUFOyS|0|10-305-434-9284|3640.90|FURNITURE|es sleep blithely regular instructions. regular instructions cajole carefully. slyly regular accounts +1984|Customer#000001984|MAqwYLxOBbMoyAWwvjEZK9QYgRMbhtFkdHbiR|13|23-768-636-1831|8661.08|HOUSEHOLD|y unusual requests. furiously ironic deposits haggle quickly a +1985|Customer#000001985|Cy7CMgihIn6lemMjU2d3SKiOmHXi0TrRZK|0|10-248-352-6397|1800.96|HOUSEHOLD| theodolites wake slyly fluffily regular pinto beans. furiously ironic packages according to t +1986|Customer#000001986|3ugRcAUZuXms2oHREuEsprYLg2u|0|10-971-309-8075|5749.20|FURNITURE|fter the slyly even deposits cajole pending accounts. +1987|Customer#000001987|lWwjammTGaKVKq9npAtfs3|19|29-745-306-2348|796.96|BUILDING|s. blithely even pinto beans boost always about the doggedly bold requests. regular requests use. +1988|Customer#000001988|MdIopEKT9C1|9|19-927-922-5628|5414.64|AUTOMOBILE|ve to are furiously bold theodolites. qu +1989|Customer#000001989|,WMIpzbXk5YrV7ZlH23grs5TeGhEtF|10|20-648-105-6440|9859.77|MACHINERY| unusual foxes wake slyly fluffily pending gifts. bold packages across the slyly +1990|Customer#000001990|M9VbFPNnktfGtPgnf3t1ptNYOzS3eCwlKpte|14|24-543-274-3227|7244.87|HOUSEHOLD|usual asymptotes around the packages haggle +1991|Customer#000001991|REzgRDc,2RF4ayaV3b3gZhIdMti9J6b8b90p|9|19-351-767-3188|3517.27|FURNITURE|nag blithely slyly special deposits? express accounts about the dolphins woul +1992|Customer#000001992|FNQZbT88wzGKhU9|1|11-760-815-8444|9679.43|BUILDING|e fluffily regular ideas haggle past the even requests. regular pinto beans nod acc +1993|Customer#000001993|Yi8QRnZDlVqZfW8SHbw,drKwsPBd6qXjavl|0|10-928-142-7350|1209.74|FURNITURE|regular pinto beans. furiously ironic epitaphs after the +1994|Customer#000001994|TRsalXgbwGxicJe1Ogt4th3BwgmrADqgILXd|1|11-384-723-1000|1971.60|HOUSEHOLD|taphs along the furiously regular dependencies must have to run blithely idle dependencies. slyly fi +1995|Customer#000001995|aIGN3hurONjCDOvfE JLx,5pmtqCPnXvgqV7VNy|2|12-339-453-3201|2674.92|BUILDING|ilent instructions sleep quickly quickly bold gifts-- final deposits grow after the final asymptotes. care +1996|Customer#000001996|SkYj5PWHdXD9|17|27-626-208-5273|9379.16|BUILDING|lyly final accounts are blithely final courts! even +1997|Customer#000001997|D7SUlJ,KUdYu|24|34-724-701-3880|3610.05|FURNITURE|accounts wake furiously. silently quick epitaphs are carefully slyly final pinto bea +1998|Customer#000001998|RpAD0CJxRxC2kjR|14|24-529-154-9925|7080.37|FURNITURE|p slyly alongside of the pains. +1999|Customer#000001999|y8mRnn6pJ0V|2|12-967-439-5391|-117.85|AUTOMOBILE|heodolites. furiously ironic excuses boost along the carefully f +2000|Customer#000002000|NabVtyaWao1l9Ss|13|23-122-829-3487|8176.83|AUTOMOBILE|s shall have to sleep quickly diff --git a/src/test/regress/data/large_records.data b/src/test/regress/data/large_records.data new file mode 100644 index 000000000..3b431196d --- /dev/null +++ b/src/test/regress/data/large_records.data @@ -0,0 +1,2 @@ +1|aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +2|a diff --git a/src/test/regress/data/lineitem.1.data b/src/test/regress/data/lineitem.1.data new file mode 100644 index 000000000..9ebd61c1a --- /dev/null +++ b/src/test/regress/data/lineitem.1.data @@ -0,0 +1,6000 @@ +1|155190|7706|1|17|21168.23|0.04|0.02|N|O|1996-03-13|1996-02-12|1996-03-22|DELIVER IN PERSON|TRUCK|egular courts above the +1|67310|7311|2|36|45983.16|0.09|0.06|N|O|1996-04-12|1996-02-28|1996-04-20|TAKE BACK RETURN|MAIL|ly final dependencies: slyly bold +1|63700|3701|3|8|13309.60|0.10|0.02|N|O|1996-01-29|1996-03-05|1996-01-31|TAKE BACK RETURN|REG AIR|riously. regular, express dep +1|2132|4633|4|28|28955.64|0.09|0.06|N|O|1996-04-21|1996-03-30|1996-05-16|NONE|AIR|lites. fluffily even de +1|24027|1534|5|24|22824.48|0.10|0.04|N|O|1996-03-30|1996-03-14|1996-04-01|NONE|FOB| pending foxes. slyly re +1|15635|638|6|32|49620.16|0.07|0.02|N|O|1996-01-30|1996-02-07|1996-02-03|DELIVER IN PERSON|MAIL|arefully slyly ex +2|106170|1191|1|38|44694.46|0.00|0.05|N|O|1997-01-28|1997-01-14|1997-02-02|TAKE BACK RETURN|RAIL|ven requests. deposits breach a +3|4297|1798|1|45|54058.05|0.06|0.00|R|F|1994-02-02|1994-01-04|1994-02-23|NONE|AIR|ongside of the furiously brave acco +3|19036|6540|2|49|46796.47|0.10|0.00|R|F|1993-11-09|1993-12-20|1993-11-24|TAKE BACK RETURN|RAIL| unusual accounts. eve +3|128449|3474|3|27|39890.88|0.06|0.07|A|F|1994-01-16|1993-11-22|1994-01-23|DELIVER IN PERSON|SHIP|nal foxes wake. +3|29380|1883|4|2|2618.76|0.01|0.06|A|F|1993-12-04|1994-01-07|1994-01-01|NONE|TRUCK|y. fluffily pending d +3|183095|650|5|28|32986.52|0.04|0.00|R|F|1993-12-14|1994-01-10|1994-01-01|TAKE BACK RETURN|FOB|ages nag slyly pending +3|62143|9662|6|26|28733.64|0.10|0.02|A|F|1993-10-29|1993-12-18|1993-11-04|TAKE BACK RETURN|RAIL|ges sleep after the caref +4|88035|5560|1|30|30690.90|0.03|0.08|N|O|1996-01-10|1995-12-14|1996-01-18|DELIVER IN PERSON|REG AIR|- quickly regular packages sleep. idly +5|108570|8571|1|15|23678.55|0.02|0.04|R|F|1994-10-31|1994-08-31|1994-11-20|NONE|AIR|ts wake furiously +5|123927|3928|2|26|50723.92|0.07|0.08|R|F|1994-10-16|1994-09-25|1994-10-19|NONE|FOB|sts use slyly quickly special instruc +5|37531|35|3|50|73426.50|0.08|0.03|A|F|1994-08-08|1994-10-13|1994-08-26|DELIVER IN PERSON|AIR|eodolites. fluffily unusual +6|139636|2150|1|37|61998.31|0.08|0.03|A|F|1992-04-27|1992-05-15|1992-05-02|TAKE BACK RETURN|TRUCK|p furiously special foxes +7|182052|9607|1|12|13608.60|0.07|0.03|N|O|1996-05-07|1996-03-13|1996-06-03|TAKE BACK RETURN|FOB|ss pinto beans wake against th +7|145243|7758|2|9|11594.16|0.08|0.08|N|O|1996-02-01|1996-03-02|1996-02-19|TAKE BACK RETURN|SHIP|es. instructions +7|94780|9799|3|46|81639.88|0.10|0.07|N|O|1996-01-15|1996-03-27|1996-02-03|COLLECT COD|MAIL| unusual reques +7|163073|3074|4|28|31809.96|0.03|0.04|N|O|1996-03-21|1996-04-08|1996-04-20|NONE|FOB|. slyly special requests haggl +7|151894|9440|5|38|73943.82|0.08|0.01|N|O|1996-02-11|1996-02-24|1996-02-18|DELIVER IN PERSON|TRUCK|ns haggle carefully ironic deposits. bl +7|79251|1759|6|35|43058.75|0.06|0.03|N|O|1996-01-16|1996-02-23|1996-01-22|TAKE BACK RETURN|FOB|jole. excuses wake carefully alongside of +7|157238|2269|7|5|6476.15|0.04|0.02|N|O|1996-02-10|1996-03-26|1996-02-13|NONE|FOB|ithely regula +32|82704|7721|1|28|47227.60|0.05|0.08|N|O|1995-10-23|1995-08-27|1995-10-26|TAKE BACK RETURN|TRUCK|sleep quickly. req +32|197921|441|2|32|64605.44|0.02|0.00|N|O|1995-08-14|1995-10-07|1995-08-27|COLLECT COD|AIR|lithely regular deposits. fluffily +32|44161|6666|3|2|2210.32|0.09|0.02|N|O|1995-08-07|1995-10-07|1995-08-23|DELIVER IN PERSON|AIR| express accounts wake according to the +32|2743|7744|4|4|6582.96|0.09|0.03|N|O|1995-08-04|1995-10-01|1995-09-03|NONE|REG AIR|e slyly final pac +32|85811|8320|5|44|79059.64|0.05|0.06|N|O|1995-08-28|1995-08-20|1995-09-14|DELIVER IN PERSON|AIR|symptotes nag according to the ironic depo +32|11615|4117|6|6|9159.66|0.04|0.03|N|O|1995-07-21|1995-09-23|1995-07-25|COLLECT COD|RAIL| gifts cajole carefully. +33|61336|8855|1|31|40217.23|0.09|0.04|A|F|1993-10-29|1993-12-19|1993-11-08|COLLECT COD|TRUCK|ng to the furiously ironic package +33|60519|5532|2|32|47344.32|0.02|0.05|A|F|1993-12-09|1994-01-04|1993-12-28|COLLECT COD|MAIL|gular theodolites +33|137469|9983|3|5|7532.30|0.05|0.03|A|F|1993-12-09|1993-12-25|1993-12-23|TAKE BACK RETURN|AIR|. stealthily bold exc +33|33918|3919|4|41|75928.31|0.09|0.00|R|F|1993-11-09|1994-01-24|1993-11-11|TAKE BACK RETURN|MAIL|unusual packages doubt caref +34|88362|871|1|13|17554.68|0.00|0.07|N|O|1998-10-23|1998-09-14|1998-11-06|NONE|REG AIR|nic accounts. deposits are alon +34|89414|1923|2|22|30875.02|0.08|0.06|N|O|1998-10-09|1998-10-16|1998-10-12|NONE|FOB|thely slyly p +34|169544|4577|3|6|9681.24|0.02|0.06|N|O|1998-10-30|1998-09-20|1998-11-05|NONE|FOB|ar foxes sleep +35|450|2951|1|24|32410.80|0.02|0.00|N|O|1996-02-21|1996-01-03|1996-03-18|TAKE BACK RETURN|FOB|, regular tithe +35|161940|4457|2|34|68065.96|0.06|0.08|N|O|1996-01-22|1996-01-06|1996-01-27|DELIVER IN PERSON|RAIL|s are carefully against the f +35|120896|8433|3|7|13418.23|0.06|0.04|N|O|1996-01-19|1995-12-22|1996-01-29|NONE|MAIL| the carefully regular +35|85175|7684|4|25|29004.25|0.06|0.05|N|O|1995-11-26|1995-12-25|1995-12-21|DELIVER IN PERSON|SHIP| quickly unti +35|119917|4940|5|34|65854.94|0.08|0.06|N|O|1995-11-08|1996-01-15|1995-11-26|COLLECT COD|MAIL|. silent, unusual deposits boost +35|30762|3266|6|28|47397.28|0.03|0.02|N|O|1996-02-01|1995-12-24|1996-02-28|COLLECT COD|RAIL|ly alongside of +36|119767|9768|1|42|75043.92|0.09|0.00|N|O|1996-02-03|1996-01-21|1996-02-23|COLLECT COD|SHIP| careful courts. special +37|22630|5133|1|40|62105.20|0.09|0.03|A|F|1992-07-21|1992-08-01|1992-08-15|NONE|REG AIR|luffily regular requests. slyly final acco +37|126782|1807|2|39|70542.42|0.05|0.02|A|F|1992-07-02|1992-08-18|1992-07-28|TAKE BACK RETURN|RAIL|the final requests. ca +37|12903|5405|3|43|78083.70|0.05|0.08|A|F|1992-07-10|1992-07-06|1992-08-02|DELIVER IN PERSON|TRUCK|iously ste +38|175839|874|1|44|84252.52|0.04|0.02|N|O|1996-09-29|1996-11-17|1996-09-30|COLLECT COD|MAIL|s. blithely unusual theodolites am +39|2320|9821|1|44|53782.08|0.09|0.06|N|O|1996-11-14|1996-12-15|1996-12-12|COLLECT COD|RAIL|eodolites. careful +39|186582|4137|2|26|43383.08|0.08|0.04|N|O|1996-11-04|1996-10-20|1996-11-20|NONE|FOB|ckages across the slyly silent +39|67831|5350|3|46|82746.18|0.06|0.08|N|O|1996-09-26|1996-12-19|1996-10-26|DELIVER IN PERSON|AIR|he carefully e +39|20590|3093|4|32|48338.88|0.07|0.05|N|O|1996-10-02|1996-12-19|1996-10-14|COLLECT COD|MAIL|heodolites sleep silently pending foxes. ac +39|54519|9530|5|43|63360.93|0.01|0.01|N|O|1996-10-17|1996-11-14|1996-10-26|COLLECT COD|MAIL|yly regular i +39|94368|6878|6|40|54494.40|0.06|0.05|N|O|1996-12-08|1996-10-22|1997-01-01|COLLECT COD|AIR|quickly ironic fox +64|85951|5952|1|21|40675.95|0.05|0.02|R|F|1994-09-30|1994-09-18|1994-10-26|DELIVER IN PERSON|REG AIR|ch slyly final, thin platelets. +65|59694|4705|1|26|42995.94|0.03|0.03|A|F|1995-04-20|1995-04-25|1995-05-13|NONE|TRUCK|pending deposits nag even packages. ca +65|73815|8830|2|22|39353.82|0.00|0.05|N|O|1995-07-17|1995-06-04|1995-07-19|COLLECT COD|FOB| ideas. special, r +65|1388|3889|3|21|27076.98|0.09|0.07|N|O|1995-07-06|1995-05-14|1995-07-31|DELIVER IN PERSON|RAIL|bove the even packages. accounts nag carefu +66|115118|7630|1|31|35126.41|0.00|0.08|R|F|1994-02-19|1994-03-11|1994-02-20|TAKE BACK RETURN|RAIL|ut the unusual accounts sleep at the bo +66|173489|3490|2|41|64061.68|0.04|0.07|A|F|1994-02-21|1994-03-01|1994-03-18|COLLECT COD|AIR| regular de +67|21636|9143|1|4|6230.52|0.09|0.04|N|O|1997-04-17|1997-01-31|1997-04-20|NONE|SHIP| cajole thinly expres +67|20193|5198|2|12|13358.28|0.09|0.05|N|O|1997-01-27|1997-02-21|1997-02-22|NONE|REG AIR| even packages cajole +67|173600|6118|3|5|8368.00|0.03|0.07|N|O|1997-02-20|1997-02-12|1997-02-21|DELIVER IN PERSON|TRUCK|y unusual packages thrash pinto +67|87514|7515|4|44|66066.44|0.08|0.06|N|O|1997-03-18|1997-01-29|1997-04-13|DELIVER IN PERSON|RAIL|se quickly above the even, express reques +67|40613|8126|5|23|35733.03|0.05|0.07|N|O|1997-04-19|1997-02-14|1997-05-06|DELIVER IN PERSON|REG AIR|ly regular deposit +67|178306|824|6|29|40144.70|0.02|0.05|N|O|1997-01-25|1997-01-27|1997-01-27|DELIVER IN PERSON|FOB|ultipliers +68|7068|9569|1|3|2925.18|0.05|0.02|N|O|1998-07-04|1998-06-05|1998-07-21|NONE|RAIL|fully special instructions cajole. furious +68|175180|2732|2|46|57738.28|0.02|0.05|N|O|1998-06-26|1998-06-07|1998-07-05|NONE|MAIL| requests are unusual, regular pinto +68|34980|7484|3|46|88089.08|0.04|0.05|N|O|1998-08-13|1998-07-08|1998-08-29|NONE|RAIL|egular dependencies affix ironically along +68|94728|2256|4|20|34454.40|0.07|0.01|N|O|1998-06-27|1998-05-23|1998-07-02|NONE|REG AIR| excuses integrate fluffily +68|82758|5267|5|27|47000.25|0.03|0.06|N|O|1998-06-19|1998-06-25|1998-06-29|DELIVER IN PERSON|SHIP|ccounts. deposits use. furiously +68|102561|5072|6|30|46906.80|0.05|0.06|N|O|1998-08-11|1998-07-11|1998-08-14|NONE|RAIL|oxes are slyly blithely fin +68|139247|1761|7|41|52735.84|0.09|0.08|N|O|1998-06-24|1998-06-27|1998-07-06|NONE|SHIP|eposits nag special ideas. furiousl +69|115209|7721|1|48|58761.60|0.01|0.07|A|F|1994-08-17|1994-08-11|1994-09-08|NONE|TRUCK|regular epitaphs. carefully even ideas hag +69|104180|9201|2|32|37893.76|0.08|0.06|A|F|1994-08-24|1994-08-17|1994-08-31|NONE|REG AIR|s sleep carefully bold, +69|137267|4807|3|17|22172.42|0.09|0.00|A|F|1994-07-02|1994-07-07|1994-07-03|TAKE BACK RETURN|AIR|final, pending instr +69|37502|2509|4|3|4318.50|0.09|0.04|R|F|1994-06-06|1994-07-27|1994-06-15|NONE|MAIL| blithely final d +69|92070|7089|5|42|44606.94|0.07|0.04|R|F|1994-07-31|1994-07-26|1994-08-28|DELIVER IN PERSON|REG AIR|tect regular, speci +69|18504|1006|6|23|32717.50|0.05|0.00|A|F|1994-10-03|1994-08-06|1994-10-24|NONE|SHIP|nding accounts ca +70|64128|9141|1|8|8736.96|0.03|0.08|R|F|1994-01-12|1994-02-27|1994-01-14|TAKE BACK RETURN|FOB|ggle. carefully pending dependenc +70|196156|1195|2|13|16277.95|0.06|0.06|A|F|1994-03-03|1994-02-13|1994-03-26|COLLECT COD|AIR|lyly special packag +70|179809|7361|3|1|1888.80|0.03|0.05|R|F|1994-01-26|1994-03-05|1994-01-28|TAKE BACK RETURN|RAIL|quickly. fluffily unusual theodolites c +70|45734|743|4|11|18477.03|0.01|0.05|A|F|1994-03-17|1994-03-17|1994-03-27|NONE|MAIL|alongside of the deposits. fur +70|37131|2138|5|37|39520.81|0.09|0.04|R|F|1994-02-13|1994-03-16|1994-02-21|COLLECT COD|MAIL|n accounts are. q +70|55655|3171|6|19|30602.35|0.06|0.03|A|F|1994-01-26|1994-02-17|1994-02-06|TAKE BACK RETURN|SHIP| packages wake pending accounts. +71|61931|1932|1|25|47323.25|0.09|0.07|N|O|1998-04-10|1998-04-22|1998-04-11|COLLECT COD|FOB|ckly. slyly +71|65916|3435|2|3|5645.73|0.09|0.07|N|O|1998-05-23|1998-04-03|1998-06-02|COLLECT COD|SHIP|y. pinto beans haggle after the +71|34432|1942|3|45|61489.35|0.00|0.07|N|O|1998-02-23|1998-03-20|1998-03-24|DELIVER IN PERSON|SHIP| ironic packages believe blithely a +71|96645|9155|4|33|54174.12|0.00|0.01|N|O|1998-04-12|1998-03-20|1998-04-15|NONE|FOB| serve quickly fluffily bold deposi +71|103255|5766|5|39|49071.75|0.08|0.06|N|O|1998-01-29|1998-04-07|1998-02-18|DELIVER IN PERSON|RAIL|l accounts sleep across the pack +71|195635|674|6|34|58841.42|0.04|0.01|N|O|1998-03-05|1998-04-22|1998-03-30|DELIVER IN PERSON|TRUCK|s cajole. +96|123076|613|1|23|25278.61|0.10|0.06|A|F|1994-07-19|1994-06-29|1994-07-25|DELIVER IN PERSON|TRUCK|ep-- carefully reg +96|135390|5391|2|30|42761.70|0.01|0.06|R|F|1994-06-03|1994-05-29|1994-06-22|DELIVER IN PERSON|TRUCK|e quickly even ideas. furiou +97|119477|1989|1|13|19454.11|0.00|0.02|R|F|1993-04-01|1993-04-04|1993-04-08|NONE|TRUCK|ayers cajole against the furiously +97|49568|2073|2|37|56149.72|0.02|0.06|A|F|1993-04-13|1993-03-30|1993-04-14|DELIVER IN PERSON|SHIP|ic requests boost carefully quic +97|77699|5221|3|19|31857.11|0.06|0.08|R|F|1993-05-14|1993-03-05|1993-05-25|TAKE BACK RETURN|RAIL|gifts. furiously ironic packages cajole. +98|40216|217|1|28|32373.88|0.06|0.07|A|F|1994-12-24|1994-10-25|1995-01-16|COLLECT COD|REG AIR| pending, regular accounts s +98|109743|7274|2|1|1752.74|0.00|0.00|A|F|1994-12-01|1994-12-12|1994-12-15|DELIVER IN PERSON|TRUCK|. unusual instructions against +98|44706|4707|3|14|23109.80|0.05|0.02|A|F|1994-12-30|1994-11-22|1995-01-27|COLLECT COD|AIR| cajole furiously. blithely ironic ideas +98|167180|7181|4|10|12471.80|0.03|0.03|A|F|1994-10-23|1994-11-08|1994-11-09|COLLECT COD|RAIL| carefully. quickly ironic ideas +99|87114|4639|1|10|11011.10|0.02|0.01|A|F|1994-05-18|1994-06-03|1994-05-23|COLLECT COD|RAIL|kages. requ +99|123766|3767|2|5|8948.80|0.02|0.07|R|F|1994-05-06|1994-05-28|1994-05-20|TAKE BACK RETURN|RAIL|ests cajole fluffily waters. blithe +99|134082|1622|3|42|46875.36|0.02|0.02|A|F|1994-04-19|1994-05-18|1994-04-20|NONE|RAIL|kages are fluffily furiously ir +99|108338|849|4|36|48467.88|0.09|0.02|A|F|1994-07-04|1994-04-17|1994-07-30|DELIVER IN PERSON|AIR|slyly. slyly e +100|62029|2030|1|28|27748.56|0.04|0.05|N|O|1998-05-08|1998-05-13|1998-06-07|COLLECT COD|TRUCK|sts haggle. slowl +100|115979|8491|2|22|43889.34|0.00|0.07|N|O|1998-06-24|1998-04-12|1998-06-29|DELIVER IN PERSON|SHIP|nto beans alongside of the fi +100|46150|8655|3|46|50422.90|0.03|0.04|N|O|1998-05-02|1998-04-10|1998-05-22|TAKE BACK RETURN|SHIP|ular accounts. even +100|38024|3031|4|14|13468.28|0.06|0.03|N|O|1998-05-22|1998-05-01|1998-06-03|COLLECT COD|MAIL|y. furiously ironic ideas gr +100|53439|955|5|37|51519.91|0.05|0.00|N|O|1998-03-06|1998-04-16|1998-03-31|TAKE BACK RETURN|TRUCK|nd the quickly s +101|118282|5816|1|49|63713.72|0.10|0.00|N|O|1996-06-21|1996-05-27|1996-06-29|DELIVER IN PERSON|REG AIR|ts-- final packages sleep furiousl +101|163334|883|2|36|50303.88|0.00|0.01|N|O|1996-05-19|1996-05-01|1996-06-04|DELIVER IN PERSON|AIR|tes. blithely pending dolphins x-ray f +101|138418|5958|3|12|17476.92|0.06|0.02|N|O|1996-03-29|1996-04-20|1996-04-12|COLLECT COD|MAIL|. quickly regular +102|88914|3931|1|37|70407.67|0.06|0.00|N|O|1997-07-24|1997-08-02|1997-08-07|TAKE BACK RETURN|SHIP|ully across the ideas. final deposit +102|169238|6787|2|34|44445.82|0.03|0.08|N|O|1997-08-09|1997-07-28|1997-08-26|TAKE BACK RETURN|SHIP|eposits cajole across +102|182321|4840|3|25|35083.00|0.01|0.01|N|O|1997-07-31|1997-07-24|1997-08-17|NONE|RAIL|bits. ironic accoun +102|61158|8677|4|15|16787.25|0.07|0.07|N|O|1997-06-02|1997-07-13|1997-06-04|DELIVER IN PERSON|SHIP|final packages. carefully even excu +103|194658|2216|1|6|10515.90|0.03|0.05|N|O|1996-10-11|1996-07-25|1996-10-28|NONE|FOB|cajole. carefully ex +103|10426|2928|2|37|49447.54|0.02|0.07|N|O|1996-09-17|1996-07-27|1996-09-20|TAKE BACK RETURN|MAIL|ies. quickly ironic requests use blithely +103|28431|8432|3|23|31266.89|0.01|0.04|N|O|1996-09-11|1996-09-18|1996-09-26|NONE|FOB|ironic accou +103|29022|4027|4|32|30432.64|0.01|0.07|N|O|1996-07-30|1996-08-06|1996-08-04|NONE|RAIL|kages doze. special, regular deposit +128|106828|9339|1|38|69723.16|0.06|0.01|A|F|1992-09-01|1992-08-27|1992-10-01|TAKE BACK RETURN|FOB| cajole careful +129|2867|5368|1|46|81413.56|0.08|0.02|R|F|1993-02-15|1993-01-24|1993-03-05|COLLECT COD|TRUCK|uietly bold theodolites. fluffil +129|185164|5165|2|36|44969.76|0.01|0.02|A|F|1992-11-25|1992-12-25|1992-12-09|TAKE BACK RETURN|REG AIR|packages are care +129|39444|1948|3|33|45653.52|0.04|0.06|A|F|1993-01-08|1993-02-14|1993-01-29|COLLECT COD|SHIP|sts nag bravely. fluffily +129|135137|164|4|34|39852.42|0.00|0.01|R|F|1993-01-29|1993-02-14|1993-02-10|COLLECT COD|MAIL|quests. express ideas +129|31373|8883|5|24|31304.88|0.06|0.00|A|F|1992-12-07|1993-01-02|1992-12-11|TAKE BACK RETURN|FOB|uests. foxes cajole slyly after the ca +129|77050|4572|6|22|22595.10|0.06|0.01|R|F|1993-02-15|1993-01-31|1993-02-24|COLLECT COD|SHIP|e. fluffily regular +129|168569|3602|7|1|1637.56|0.05|0.04|R|F|1993-01-26|1993-01-08|1993-02-24|DELIVER IN PERSON|FOB|e carefully blithely bold dolp +130|128816|8817|1|14|25827.34|0.08|0.05|A|F|1992-08-15|1992-07-25|1992-09-13|COLLECT COD|RAIL| requests. final instruction +130|1739|4240|2|48|78755.04|0.03|0.02|R|F|1992-07-01|1992-07-12|1992-07-24|NONE|AIR|lithely alongside of the regu +130|11860|1861|3|18|31893.48|0.04|0.08|A|F|1992-07-04|1992-06-14|1992-07-29|DELIVER IN PERSON|MAIL| slyly ironic decoys abou +130|115635|3169|4|13|21458.19|0.09|0.02|R|F|1992-06-26|1992-07-29|1992-07-05|NONE|FOB| pending dolphins sleep furious +130|69130|4143|5|31|34073.03|0.06|0.05|R|F|1992-09-01|1992-07-18|1992-09-02|TAKE BACK RETURN|RAIL|thily about the ruth +131|167505|22|1|45|70762.50|0.10|0.02|R|F|1994-09-14|1994-09-02|1994-10-04|NONE|FOB|ironic, bold accounts. careful +131|44255|9264|2|50|59962.50|0.02|0.04|A|F|1994-09-17|1994-08-10|1994-09-21|NONE|SHIP|ending requests. final, ironic pearls slee +131|189021|1540|3|4|4440.08|0.04|0.03|A|F|1994-09-20|1994-08-30|1994-09-23|COLLECT COD|REG AIR| are carefully slyly i +132|140449|2964|1|18|26809.92|0.00|0.08|R|F|1993-07-10|1993-08-05|1993-07-13|NONE|TRUCK|ges. platelets wake furio +132|119053|9054|2|43|46098.15|0.01|0.08|R|F|1993-09-01|1993-08-16|1993-09-22|NONE|TRUCK|y pending theodolites +132|114419|4420|3|32|45869.12|0.04|0.04|A|F|1993-07-12|1993-08-05|1993-08-05|COLLECT COD|TRUCK|d instructions hagg +132|28082|5589|4|23|23231.84|0.10|0.00|A|F|1993-06-16|1993-08-27|1993-06-23|DELIVER IN PERSON|AIR|refully blithely bold acco +133|103432|5943|1|27|38756.61|0.00|0.02|N|O|1997-12-21|1998-02-23|1997-12-27|TAKE BACK RETURN|MAIL|yly even gifts after the sl +133|176279|3831|2|12|16263.24|0.02|0.06|N|O|1997-12-02|1998-01-15|1997-12-29|DELIVER IN PERSON|REG AIR|ts cajole fluffily quickly i +133|117350|4884|3|29|39653.15|0.09|0.08|N|O|1998-02-28|1998-01-30|1998-03-09|DELIVER IN PERSON|RAIL| the carefully regular theodoli +133|89855|7380|4|11|20293.35|0.06|0.01|N|O|1998-03-21|1998-01-15|1998-04-04|DELIVER IN PERSON|REG AIR|e quickly across the dolphins +134|641|642|1|21|32374.44|0.00|0.03|A|F|1992-07-17|1992-07-08|1992-07-26|COLLECT COD|SHIP|s. quickly regular +134|164645|9678|2|35|59837.40|0.06|0.07|A|F|1992-08-23|1992-06-01|1992-08-24|NONE|MAIL|ajole furiously. instructio +134|188252|3289|3|26|34846.50|0.09|0.06|A|F|1992-06-20|1992-07-12|1992-07-16|NONE|RAIL| among the pending depos +134|144002|4003|4|47|49162.00|0.05|0.00|A|F|1992-08-16|1992-07-06|1992-08-28|NONE|REG AIR|s! carefully unusual requests boost careful +134|35172|5173|5|12|13286.04|0.05|0.02|A|F|1992-07-03|1992-06-01|1992-07-11|COLLECT COD|TRUCK|nts are quic +134|133103|5617|6|12|13633.20|0.00|0.00|A|F|1992-08-08|1992-07-07|1992-08-20|TAKE BACK RETURN|FOB|lyly regular pac +135|108205|8206|1|47|57020.40|0.06|0.08|N|O|1996-02-18|1996-01-01|1996-02-25|COLLECT COD|RAIL|ctions wake slyly abo +135|198344|5902|2|21|30289.14|0.00|0.07|N|O|1996-02-11|1996-01-12|1996-02-13|DELIVER IN PERSON|SHIP| deposits believe. furiously regular p +135|157510|5056|3|33|51727.83|0.02|0.00|N|O|1996-01-03|1995-11-21|1996-02-01|TAKE BACK RETURN|MAIL|ptotes boost slowly care +135|67005|9512|4|34|33048.00|0.02|0.03|N|O|1996-01-12|1996-01-19|1996-02-05|NONE|TRUCK|counts doze against the blithely ironi +135|136248|1275|5|20|25684.80|0.01|0.04|N|O|1996-01-25|1995-11-20|1996-02-09|NONE|MAIL|theodolites. quickly p +135|115000|2534|6|13|13195.00|0.04|0.02|N|O|1995-11-12|1995-12-22|1995-11-17|NONE|FOB|nal ideas. final instr +160|14785|9788|1|36|61192.08|0.07|0.01|N|O|1997-03-11|1997-03-11|1997-03-20|COLLECT COD|MAIL|old, ironic deposits are quickly abov +160|86382|8891|2|22|30104.36|0.00|0.04|N|O|1997-02-18|1997-03-05|1997-03-05|COLLECT COD|RAIL|ncies about the request +160|20080|5085|3|34|34002.72|0.01|0.05|N|O|1997-01-31|1997-03-13|1997-02-14|NONE|FOB|st sleep even gifts. dependencies along +161|102810|341|1|19|34443.39|0.01|0.01|A|F|1994-12-13|1994-11-19|1994-12-26|DELIVER IN PERSON|TRUCK|, regular sheaves sleep along +162|189288|4325|1|2|2754.56|0.02|0.01|N|O|1995-09-02|1995-06-17|1995-09-08|COLLECT COD|FOB|es! final somas integrate +163|167545|5094|1|43|69339.22|0.01|0.00|N|O|1997-09-19|1997-11-19|1997-10-03|COLLECT COD|REG AIR|al, bold dependencies wake. iron +163|120702|703|2|13|22395.10|0.01|0.04|N|O|1997-11-11|1997-10-18|1997-12-07|DELIVER IN PERSON|TRUCK|inal requests. even pinto beans hag +163|36818|9322|3|27|47379.87|0.04|0.08|N|O|1997-12-26|1997-11-28|1998-01-05|COLLECT COD|REG AIR|ously express dependen +163|192642|5162|4|5|8673.20|0.02|0.00|N|O|1997-11-17|1997-10-09|1997-12-05|DELIVER IN PERSON|TRUCK| must belie +163|126090|8603|5|12|13393.08|0.10|0.00|N|O|1997-12-18|1997-10-26|1997-12-22|COLLECT COD|TRUCK|ly blithe accounts cajole +163|190825|5864|6|20|38316.40|0.00|0.07|N|O|1997-09-27|1997-11-15|1997-10-07|TAKE BACK RETURN|FOB|tructions integrate b +164|91309|3819|1|26|33807.80|0.09|0.04|A|F|1993-01-04|1992-11-21|1993-01-07|NONE|RAIL|s. blithely special courts are blithel +164|18488|3491|2|24|33755.52|0.05|0.05|R|F|1992-12-22|1992-11-27|1993-01-06|NONE|AIR|side of the slyly unusual theodolites. f +164|125509|3046|3|38|58311.00|0.03|0.06|R|F|1992-12-04|1992-11-23|1993-01-02|TAKE BACK RETURN|AIR|counts cajole fluffily regular packages. b +164|17526|28|4|32|46192.64|0.05|0.01|R|F|1992-12-21|1992-12-23|1992-12-28|COLLECT COD|RAIL|ts wake again +164|147505|2534|5|43|66757.50|0.06|0.01|R|F|1992-11-26|1993-01-03|1992-12-08|COLLECT COD|RAIL|y carefully regular dep +164|108896|8897|6|27|51432.03|0.10|0.04|R|F|1992-12-23|1993-01-16|1993-01-10|DELIVER IN PERSON|AIR|ayers wake carefully a +164|3037|5538|7|23|21620.69|0.09|0.04|A|F|1992-11-03|1992-12-02|1992-11-12|NONE|REG AIR|ress packages haggle ideas. blithely spec +165|33175|8182|1|3|3324.51|0.01|0.08|R|F|1993-03-29|1993-03-06|1993-04-12|DELIVER IN PERSON|REG AIR|riously requests. depos +165|161627|9176|2|43|72610.66|0.08|0.05|R|F|1993-02-27|1993-04-19|1993-03-03|DELIVER IN PERSON|TRUCK|jole slyly according +165|58520|6036|3|15|22177.80|0.00|0.05|R|F|1993-04-10|1993-03-29|1993-05-01|COLLECT COD|SHIP| bold packages mainta +165|139190|4217|4|49|60230.31|0.07|0.06|A|F|1993-02-20|1993-04-02|1993-03-10|COLLECT COD|REG AIR|uses sleep slyly ruthlessly regular a +165|155084|7600|5|27|30755.16|0.01|0.04|R|F|1993-04-27|1993-03-04|1993-05-13|NONE|MAIL|around the ironic, even orb +166|64888|9901|1|37|68556.56|0.09|0.03|N|O|1995-11-16|1995-10-17|1995-12-13|NONE|MAIL|lar frays wake blithely a +166|166366|6367|2|13|18620.68|0.09|0.05|N|O|1995-11-09|1995-11-18|1995-11-14|COLLECT COD|SHIP|fully above the blithely fina +166|99652|2162|3|41|67717.65|0.07|0.03|N|O|1995-11-13|1995-11-07|1995-12-08|COLLECT COD|FOB|hily along the blithely pending fo +166|45027|7532|4|8|7776.16|0.05|0.02|N|O|1995-12-30|1995-11-29|1996-01-29|DELIVER IN PERSON|RAIL|e carefully bold +167|101171|1172|1|28|32820.76|0.06|0.01|R|F|1993-02-19|1993-02-16|1993-03-03|DELIVER IN PERSON|TRUCK|sly during the u +167|171555|4073|2|27|43916.85|0.09|0.00|R|F|1993-05-01|1993-03-31|1993-05-31|TAKE BACK RETURN|FOB|eans affix furiously-- packages +192|97017|2036|1|23|23322.23|0.00|0.00|N|O|1998-02-05|1998-02-06|1998-03-07|TAKE BACK RETURN|AIR|ly pending theodolites haggle quickly fluf +192|161368|8917|2|20|28587.20|0.07|0.01|N|O|1998-03-13|1998-02-02|1998-03-31|TAKE BACK RETURN|REG AIR|tes. carefu +192|110252|5275|3|15|18933.75|0.09|0.01|N|O|1998-01-30|1998-02-10|1998-02-23|TAKE BACK RETURN|TRUCK|he ironic requests haggle about +192|196400|3958|4|2|2992.80|0.06|0.02|N|O|1998-03-06|1998-02-03|1998-03-24|COLLECT COD|SHIP|s. dependencies nag furiously alongside +192|82915|7932|5|25|47447.75|0.02|0.03|N|O|1998-02-15|1998-01-11|1998-03-17|COLLECT COD|TRUCK|. carefully regular +192|141003|3518|6|45|46980.00|0.00|0.05|N|O|1998-03-11|1998-01-09|1998-04-03|NONE|MAIL|equests. ideas sleep idea +193|92638|5148|1|9|14675.67|0.06|0.06|A|F|1993-09-17|1993-10-08|1993-09-30|COLLECT COD|TRUCK|against the fluffily regular d +193|153954|1500|2|15|30119.25|0.02|0.07|R|F|1993-11-22|1993-10-09|1993-12-05|TAKE BACK RETURN|SHIP|ffily. regular packages d +193|93878|6388|3|23|43053.01|0.06|0.05|A|F|1993-08-21|1993-10-11|1993-09-02|DELIVER IN PERSON|TRUCK|ly even accounts wake blithely bold +194|2594|5095|1|17|25442.03|0.05|0.04|R|F|1992-05-24|1992-05-22|1992-05-30|COLLECT COD|AIR| regular deposi +194|183523|6042|2|1|1606.52|0.04|0.06|R|F|1992-04-30|1992-05-18|1992-05-23|NONE|REG AIR| regular theodolites. regular, iron +194|65994|3513|3|13|25479.87|0.08|0.08|A|F|1992-05-07|1992-06-18|1992-05-10|NONE|AIR|about the blit +194|145146|5147|4|36|42881.04|0.00|0.05|R|F|1992-05-21|1992-05-18|1992-05-27|TAKE BACK RETURN|RAIL|pecial packages wake after the slyly r +194|56176|1187|5|8|9057.36|0.04|0.00|R|F|1992-07-06|1992-06-25|1992-07-11|COLLECT COD|FOB|uriously unusual excuses +194|148984|1499|6|16|32527.68|0.06|0.03|A|F|1992-05-14|1992-06-14|1992-05-21|TAKE BACK RETURN|TRUCK|y regular requests. furious +194|167828|345|7|21|39812.22|0.02|0.01|R|F|1992-05-06|1992-05-20|1992-05-07|COLLECT COD|REG AIR|accounts detect quickly dogged +195|84590|9607|1|6|9447.54|0.04|0.02|A|F|1994-01-09|1994-03-27|1994-01-28|COLLECT COD|REG AIR|y, even deposits haggle carefully. bli +195|93847|1375|2|41|75474.44|0.05|0.07|A|F|1994-02-24|1994-02-11|1994-03-20|NONE|TRUCK|rts detect in place of t +195|85446|7955|3|34|48668.96|0.08|0.08|R|F|1994-01-31|1994-02-11|1994-02-12|NONE|TRUCK| cajole furiously bold i +195|85442|7951|4|41|58525.04|0.06|0.04|R|F|1994-03-14|1994-03-13|1994-04-09|COLLECT COD|RAIL|ggle fluffily foxes. fluffily ironic ex +196|135052|79|1|19|20653.95|0.03|0.02|R|F|1993-04-17|1993-05-27|1993-04-30|NONE|SHIP|sts maintain foxes. furiously regular p +196|9852|2353|2|15|26427.75|0.03|0.04|A|F|1993-07-05|1993-05-08|1993-07-06|TAKE BACK RETURN|SHIP|s accounts. furio +197|98494|1004|1|39|58207.11|0.02|0.04|N|O|1995-07-21|1995-07-01|1995-08-14|TAKE BACK RETURN|AIR|press accounts. daringly sp +197|177103|9621|2|8|9440.80|0.09|0.02|A|F|1995-04-17|1995-07-01|1995-04-27|DELIVER IN PERSON|SHIP|y blithely even deposits. blithely fina +197|155829|8345|3|17|32041.94|0.06|0.02|N|O|1995-08-02|1995-06-23|1995-08-03|COLLECT COD|REG AIR|ts. careful +197|17936|2939|4|25|46348.25|0.04|0.01|N|F|1995-06-13|1995-05-23|1995-06-24|TAKE BACK RETURN|FOB|s-- quickly final accounts +197|41466|3971|5|14|19704.44|0.09|0.01|R|F|1995-05-08|1995-05-24|1995-05-12|TAKE BACK RETURN|RAIL|use slyly slyly silent depo +197|105880|901|6|1|1885.88|0.07|0.05|N|O|1995-07-15|1995-06-21|1995-08-11|COLLECT COD|RAIL| even, thin dependencies sno +198|56061|6062|1|33|33562.98|0.07|0.02|N|O|1998-01-05|1998-03-20|1998-01-10|TAKE BACK RETURN|TRUCK|carefully caref +198|15229|7731|2|20|22884.40|0.03|0.00|N|O|1998-01-15|1998-03-31|1998-01-25|DELIVER IN PERSON|FOB|carefully final escapades a +198|148058|3087|3|15|16590.75|0.04|0.02|N|O|1998-04-12|1998-02-26|1998-04-15|COLLECT COD|MAIL|es. quickly pending deposits s +198|10371|2873|4|35|44847.95|0.08|0.02|N|O|1998-02-27|1998-03-23|1998-03-14|TAKE BACK RETURN|RAIL|ests nod quickly furiously sly pinto be +198|101952|1953|5|33|64480.35|0.02|0.01|N|O|1998-03-22|1998-03-12|1998-04-14|DELIVER IN PERSON|SHIP|ending foxes acr +199|132072|9612|1|50|55203.50|0.02|0.00|N|O|1996-06-12|1996-06-03|1996-07-04|DELIVER IN PERSON|MAIL|essly regular ideas boost sly +199|133998|3999|2|30|60959.70|0.08|0.05|N|O|1996-03-27|1996-05-29|1996-04-14|NONE|TRUCK|ilent packages doze quickly. thinly +224|150111|112|1|16|18577.76|0.04|0.00|A|F|1994-08-01|1994-07-30|1994-08-27|DELIVER IN PERSON|MAIL|y unusual foxes +224|108609|1120|2|34|54998.40|0.04|0.08|R|F|1994-07-13|1994-08-25|1994-07-31|COLLECT COD|TRUCK| carefully. final platelets +224|189967|7522|3|41|84335.36|0.07|0.04|A|F|1994-09-01|1994-09-15|1994-09-02|TAKE BACK RETURN|SHIP|after the furiou +224|166377|1410|4|12|17320.44|0.08|0.06|R|F|1994-10-12|1994-08-29|1994-10-20|DELIVER IN PERSON|MAIL|uriously regular packages. slyly fina +224|93857|8876|5|45|83288.25|0.07|0.07|R|F|1994-08-14|1994-09-02|1994-08-27|COLLECT COD|AIR|leep furiously regular requests. furiousl +224|50010|7526|6|4|3840.04|0.02|0.00|R|F|1994-09-08|1994-08-24|1994-10-04|DELIVER IN PERSON|FOB|tructions +225|171925|1926|1|4|7987.68|0.09|0.07|N|O|1995-08-05|1995-08-19|1995-09-03|TAKE BACK RETURN|SHIP|ng the ironic packages. asymptotes among +225|130565|8105|2|3|4786.68|0.00|0.08|N|O|1995-07-25|1995-07-08|1995-08-17|DELIVER IN PERSON|REG AIR| fluffily about the carefully bold a +225|198212|3251|3|45|58959.45|0.06|0.01|N|O|1995-08-17|1995-08-20|1995-08-30|TAKE BACK RETURN|FOB|the slyly even platelets use aro +225|146071|8586|4|24|26809.68|0.00|0.06|N|O|1995-09-23|1995-08-05|1995-10-16|COLLECT COD|MAIL|ironic accounts are final account +225|7589|5090|5|31|46393.98|0.04|0.06|N|O|1995-06-21|1995-07-24|1995-07-04|TAKE BACK RETURN|FOB|special platelets. quickly r +225|131835|9375|6|12|22401.96|0.00|0.00|A|F|1995-06-04|1995-07-15|1995-06-08|COLLECT COD|MAIL| unusual requests. bus +225|141233|8776|7|44|56066.12|0.10|0.06|N|O|1995-09-22|1995-08-16|1995-10-22|NONE|REG AIR|leep slyly +226|96909|9419|1|4|7623.60|0.00|0.00|R|F|1993-03-31|1993-04-30|1993-04-10|NONE|TRUCK|c foxes integrate carefully against th +226|137802|5342|2|46|84630.80|0.06|0.01|A|F|1993-07-06|1993-04-24|1993-07-13|COLLECT COD|FOB|s. carefully bold accounts cajol +226|37309|4819|3|35|43620.50|0.09|0.03|A|F|1993-03-31|1993-05-18|1993-04-01|NONE|RAIL|osits cajole. final, even foxes a +226|40633|8146|4|45|70813.35|0.10|0.02|R|F|1993-04-17|1993-05-27|1993-05-11|DELIVER IN PERSON|AIR| carefully pending pi +226|117956|5490|5|2|3947.90|0.07|0.02|R|F|1993-03-26|1993-04-13|1993-04-20|TAKE BACK RETURN|SHIP|al platelets. express somas +226|82937|7954|6|48|92156.64|0.02|0.00|A|F|1993-06-11|1993-05-15|1993-06-19|NONE|REG AIR|efully silent packages. final deposit +226|117961|5495|7|14|27705.44|0.09|0.00|R|F|1993-05-20|1993-06-05|1993-05-27|COLLECT COD|MAIL|ep carefully regular accounts. ironic +227|165335|2884|1|19|26606.27|0.05|0.06|N|O|1995-12-10|1996-01-30|1995-12-26|NONE|RAIL|s cajole furiously a +227|174102|1654|2|24|28226.40|0.07|0.07|N|O|1996-02-03|1995-12-24|1996-02-12|COLLECT COD|SHIP|uses across the blithe dependencies cajol +228|4039|6540|1|3|2829.09|0.10|0.08|A|F|1993-05-20|1993-04-08|1993-05-26|DELIVER IN PERSON|SHIP|ckages. sly +229|83580|8597|1|20|31271.60|0.02|0.03|R|F|1994-01-11|1994-01-31|1994-01-26|DELIVER IN PERSON|REG AIR|le. instructions use across the quickly fin +229|128904|8905|2|29|56054.10|0.07|0.00|A|F|1994-03-15|1994-03-02|1994-03-26|COLLECT COD|SHIP|s, final request +229|78526|8527|3|28|42126.56|0.02|0.02|R|F|1994-02-10|1994-02-02|1994-03-10|DELIVER IN PERSON|FOB| final, regular requests. platel +229|176948|1983|4|3|6074.82|0.02|0.08|R|F|1994-03-22|1994-03-24|1994-04-04|DELIVER IN PERSON|REG AIR|posits. furiously regular theodol +229|155180|211|5|33|40760.94|0.03|0.06|R|F|1994-03-25|1994-02-11|1994-04-13|NONE|FOB| deposits; bold, ruthless theodolites +229|105393|7904|6|29|40553.31|0.04|0.00|R|F|1994-01-14|1994-02-16|1994-01-22|NONE|FOB|uriously pending +230|185863|900|1|46|89647.56|0.09|0.00|R|F|1994-02-03|1994-01-15|1994-02-23|TAKE BACK RETURN|SHIP|old packages ha +230|194908|7428|2|6|12017.40|0.03|0.08|A|F|1994-01-26|1994-01-25|1994-02-13|NONE|REG AIR| sleep furiously about the p +230|7367|4868|3|1|1274.36|0.07|0.06|R|F|1994-01-22|1994-01-03|1994-02-05|TAKE BACK RETURN|RAIL|blithely unusual dolphins. bold, ex +230|9164|1665|4|44|47219.04|0.08|0.06|R|F|1994-02-09|1994-01-18|1994-03-11|NONE|MAIL|deposits integrate slyly sile +230|18923|6427|5|8|14735.36|0.09|0.06|R|F|1993-11-03|1994-01-20|1993-11-11|TAKE BACK RETURN|TRUCK|g the instructions. fluffil +230|33927|1437|6|8|14887.36|0.00|0.05|R|F|1993-11-21|1994-01-05|1993-12-19|TAKE BACK RETURN|FOB|nal ideas. silent, reg +231|158356|8357|1|16|22629.60|0.04|0.08|R|F|1994-11-20|1994-10-29|1994-12-17|TAKE BACK RETURN|AIR|e furiously ironic pinto beans. +231|83359|884|2|46|61748.10|0.04|0.05|R|F|1994-12-13|1994-12-02|1994-12-14|DELIVER IN PERSON|SHIP|affix blithely. bold requests among the f +231|198124|644|3|50|61106.00|0.09|0.01|A|F|1994-12-11|1994-12-14|1994-12-13|NONE|RAIL|onic packages haggle fluffily a +231|56760|6761|4|31|53219.56|0.08|0.02|A|F|1994-11-05|1994-12-27|1994-11-30|TAKE BACK RETURN|SHIP|iously special decoys wake q +256|88233|742|1|22|26867.06|0.09|0.02|R|F|1994-01-12|1993-12-28|1994-01-26|COLLECT COD|FOB|ke quickly ironic, ironic deposits. reg +256|118399|3422|2|40|56695.60|0.10|0.01|A|F|1993-11-30|1993-12-13|1993-12-02|NONE|FOB|nal theodolites. deposits cajole s +256|129111|4136|3|45|51304.95|0.02|0.08|R|F|1994-01-14|1994-01-17|1994-02-10|COLLECT COD|SHIP| grouches. ideas wake quickly ar +257|146229|6230|1|7|8926.54|0.05|0.02|N|O|1998-06-18|1998-05-15|1998-06-27|COLLECT COD|FOB|ackages sleep bold realms. f +258|106194|3725|1|8|9601.52|0.00|0.07|R|F|1994-01-20|1994-03-21|1994-02-09|NONE|REG AIR|ully about the fluffily silent dependencies +258|196119|3677|2|40|48604.40|0.10|0.01|A|F|1994-03-13|1994-02-23|1994-04-05|DELIVER IN PERSON|FOB|silent frets nod daringly busy, bold +258|161762|1763|3|45|82069.20|0.07|0.07|R|F|1994-03-04|1994-02-13|1994-03-30|DELIVER IN PERSON|TRUCK|regular excuses-- fluffily ruthl +258|132912|5426|4|31|60292.21|0.02|0.05|A|F|1994-04-20|1994-03-20|1994-04-28|COLLECT COD|REG AIR| slyly blithely special mul +258|35959|8463|5|25|47373.75|0.08|0.02|A|F|1994-04-13|1994-02-26|1994-04-29|TAKE BACK RETURN|TRUCK|leep pending packages. +258|146467|8982|6|36|54484.56|0.09|0.04|A|F|1994-01-11|1994-03-04|1994-01-18|DELIVER IN PERSON|AIR|nic asymptotes. slyly silent r +259|98779|8780|1|14|24888.78|0.00|0.08|A|F|1993-12-17|1993-12-09|1993-12-31|COLLECT COD|SHIP|ons against the express acco +259|161982|4499|2|14|28615.72|0.03|0.05|R|F|1993-11-10|1993-11-20|1993-11-17|DELIVER IN PERSON|FOB|ully even, regul +259|23514|3515|3|42|60375.42|0.09|0.00|R|F|1993-10-20|1993-11-18|1993-11-12|NONE|TRUCK|the slyly ironic pinto beans. fi +259|195335|2893|4|3|4290.99|0.08|0.06|R|F|1993-10-04|1993-11-07|1993-10-14|TAKE BACK RETURN|SHIP|ng slyly at the accounts. +259|192201|7240|5|6|7759.20|0.00|0.05|R|F|1993-12-05|1993-12-22|1993-12-21|COLLECT COD|TRUCK| requests sleep +260|155887|5888|1|50|97144.00|0.07|0.08|N|O|1997-03-24|1997-02-09|1997-04-20|TAKE BACK RETURN|REG AIR|c deposits +260|182736|2737|2|26|47286.98|0.02|0.07|N|O|1996-12-12|1997-02-06|1996-12-15|NONE|TRUCK|ld theodolites boost fl +260|41222|8735|3|27|31406.94|0.05|0.08|N|O|1997-03-23|1997-02-15|1997-04-22|TAKE BACK RETURN|RAIL|ions according to the +260|5337|338|4|29|36027.57|0.10|0.06|N|O|1997-03-15|1997-01-14|1997-04-13|NONE|MAIL|fluffily even asymptotes. express wa +260|95286|305|5|44|56376.32|0.01|0.05|N|O|1997-03-26|1997-02-03|1997-04-19|DELIVER IN PERSON|MAIL|above the blithely ironic instr +261|1349|6350|1|34|42511.56|0.05|0.08|R|F|1993-08-18|1993-09-24|1993-08-20|COLLECT COD|REG AIR|c packages. asymptotes da +261|65662|5663|2|20|32553.20|0.00|0.06|R|F|1993-10-21|1993-08-02|1993-11-04|DELIVER IN PERSON|RAIL|ites hinder +261|173959|8994|3|28|56922.60|0.08|0.03|R|F|1993-07-24|1993-08-20|1993-08-05|COLLECT COD|AIR|ironic packages nag slyly. carefully fin +261|118455|967|4|49|72199.05|0.04|0.05|R|F|1993-09-12|1993-08-31|1993-10-07|COLLECT COD|SHIP|ions. bold accounts +261|60469|7988|5|49|70043.54|0.01|0.08|A|F|1993-09-29|1993-09-08|1993-10-01|COLLECT COD|SHIP| pinto beans haggle slyly furiously pending +261|96989|9499|6|20|39719.60|0.06|0.06|A|F|1993-10-15|1993-09-05|1993-11-07|NONE|AIR|ing to the special, ironic deposi +262|191186|1187|1|39|49810.02|0.01|0.05|N|O|1996-01-15|1996-02-18|1996-01-28|COLLECT COD|RAIL|usual, regular requests +262|60074|7593|2|33|34124.31|0.09|0.03|N|O|1996-03-10|1996-01-31|1996-03-27|TAKE BACK RETURN|AIR|atelets sleep furiously. requests cajole. b +262|58695|6211|3|35|57879.15|0.05|0.08|N|O|1996-03-12|1996-02-14|1996-04-11|COLLECT COD|MAIL|lites cajole along the pending packag +263|23960|6463|1|22|41447.12|0.06|0.08|R|F|1994-08-24|1994-06-20|1994-09-09|NONE|FOB|efully express fo +263|84557|9574|2|9|13873.95|0.08|0.00|A|F|1994-07-21|1994-07-16|1994-08-08|TAKE BACK RETURN|TRUCK|lms wake bl +263|142891|434|3|50|96694.50|0.06|0.04|R|F|1994-08-18|1994-07-31|1994-08-22|NONE|TRUCK|re the packages. special +288|50641|8157|1|31|49340.84|0.00|0.03|N|O|1997-03-17|1997-04-28|1997-04-06|TAKE BACK RETURN|AIR|instructions wa +288|116386|8898|2|49|68716.62|0.08|0.05|N|O|1997-04-19|1997-05-19|1997-05-18|TAKE BACK RETURN|TRUCK|ic excuses sleep always spe +288|98833|8834|3|36|65945.88|0.02|0.02|N|O|1997-02-22|1997-05-07|1997-03-07|TAKE BACK RETURN|TRUCK|yly pending excu +288|78406|8407|4|19|26303.60|0.07|0.07|N|O|1997-03-14|1997-04-04|1997-03-26|NONE|MAIL|deposits. blithely quick courts ar +288|161894|6927|5|31|60632.59|0.10|0.04|N|O|1997-05-29|1997-04-24|1997-06-20|TAKE BACK RETURN|RAIL|ns. fluffily +289|173280|832|1|25|33832.00|0.07|0.05|N|O|1997-03-18|1997-05-05|1997-04-15|DELIVER IN PERSON|FOB|out the quickly bold theodol +289|111800|9334|2|6|10870.80|0.06|0.05|N|O|1997-02-18|1997-05-08|1997-03-19|DELIVER IN PERSON|SHIP|d packages use fluffily furiously +289|16996|1999|3|44|84171.56|0.10|0.08|N|O|1997-06-05|1997-04-20|1997-07-02|COLLECT COD|MAIL|ly ironic foxes. asymptotes +289|39439|1943|4|48|66164.64|0.01|0.08|N|O|1997-03-14|1997-03-30|1997-03-24|DELIVER IN PERSON|RAIL|sits cajole. bold pinto beans x-ray fl +289|46285|8790|5|13|16006.64|0.10|0.03|N|O|1997-06-08|1997-04-06|1997-06-18|TAKE BACK RETURN|REG AIR|ts. quickly bold deposits alongside +290|5351|352|1|35|43972.25|0.01|0.02|R|F|1994-04-01|1994-02-05|1994-04-27|NONE|MAIL|ove the final foxes detect slyly fluffily +290|128923|1436|2|2|3903.84|0.05|0.04|A|F|1994-01-30|1994-02-13|1994-02-21|TAKE BACK RETURN|TRUCK|. permanently furious reques +290|1888|4389|3|5|8949.40|0.03|0.05|A|F|1994-01-19|1994-02-24|1994-01-27|NONE|MAIL|ans integrate. requests sleep. fur +290|123741|6254|4|23|40589.02|0.05|0.08|R|F|1994-03-14|1994-02-21|1994-04-09|NONE|AIR|refully unusual packages. +291|122565|102|1|21|33338.76|0.05|0.07|A|F|1994-05-26|1994-05-10|1994-06-23|COLLECT COD|TRUCK|y quickly regular theodolites. final t +291|137316|7317|2|19|25712.89|0.08|0.02|R|F|1994-06-14|1994-04-25|1994-06-19|NONE|REG AIR|e. ruthlessly final accounts after the +291|60874|5887|3|30|55046.10|0.10|0.02|R|F|1994-03-22|1994-04-30|1994-03-24|DELIVER IN PERSON|FOB| fluffily regular deposits. quickl +292|153561|3562|1|8|12916.48|0.10|0.03|R|F|1992-02-18|1992-03-30|1992-03-18|DELIVER IN PERSON|RAIL|sily bold deposits alongside of the ex +292|99249|9250|2|24|29957.76|0.08|0.04|R|F|1992-03-24|1992-03-06|1992-04-20|COLLECT COD|TRUCK| bold, pending theodolites u +293|8960|6461|1|14|26165.44|0.02|0.05|R|F|1992-10-19|1992-12-23|1992-11-10|DELIVER IN PERSON|SHIP|es. packages above the +293|186406|6407|2|11|16416.40|0.10|0.04|R|F|1992-12-24|1992-12-01|1993-01-12|COLLECT COD|MAIL| affix carefully quickly special idea +293|117267|4801|3|13|16695.38|0.04|0.02|A|F|1992-12-17|1992-12-26|1992-12-22|COLLECT COD|RAIL| wake after the quickly even deposits. bli +294|59620|7136|1|31|48968.22|0.00|0.01|R|F|1993-08-06|1993-08-19|1993-08-13|TAKE BACK RETURN|AIR|le fluffily along the quick +295|197507|27|1|29|46530.50|0.02|0.07|A|F|1994-11-09|1994-12-08|1994-12-07|COLLECT COD|MAIL|inst the carefully ironic pinto beans. blit +295|91344|8872|2|26|34718.84|0.04|0.03|R|F|1994-12-13|1994-11-30|1995-01-06|DELIVER IN PERSON|AIR|ts above the slyly regular requests x-ray q +295|15283|7785|3|8|9586.24|0.10|0.07|R|F|1995-01-13|1994-11-17|1995-01-25|NONE|TRUCK| final instructions h +295|60621|3128|4|26|41122.12|0.10|0.04|A|F|1995-01-12|1994-11-22|1995-01-22|DELIVER IN PERSON|MAIL| carefully iron +320|4415|1916|1|30|39582.30|0.05|0.01|N|O|1997-12-04|1998-01-21|1997-12-13|NONE|RAIL| ironic, final accounts wake quick de +320|192158|4678|2|13|16251.95|0.03|0.00|N|O|1997-12-16|1997-12-26|1997-12-17|TAKE BACK RETURN|AIR|he furiously regular pinto beans. car +321|318|7819|1|21|25584.51|0.01|0.08|A|F|1993-07-18|1993-04-24|1993-08-13|TAKE BACK RETURN|REG AIR|hockey players sleep slyly sl +321|140433|5462|2|41|60410.63|0.08|0.07|R|F|1993-06-21|1993-06-07|1993-07-09|NONE|REG AIR|special packages shall have to doze blit +322|152499|7530|1|12|18617.88|0.08|0.07|A|F|1992-06-29|1992-05-30|1992-07-11|NONE|AIR|ular theodolites promise qu +322|43662|3663|2|48|77071.68|0.02|0.07|A|F|1992-06-11|1992-06-16|1992-06-26|COLLECT COD|RAIL|dolites detect qu +322|12673|177|3|20|31713.40|0.04|0.01|R|F|1992-04-26|1992-05-04|1992-05-22|DELIVER IN PERSON|MAIL|ckly toward +322|183246|5765|4|10|13292.40|0.06|0.03|R|F|1992-04-12|1992-05-13|1992-04-14|DELIVER IN PERSON|AIR| deposits grow slyly according to th +322|11605|9109|5|35|53081.00|0.07|0.06|A|F|1992-07-17|1992-05-03|1992-08-14|TAKE BACK RETURN|RAIL|egular accounts cajole carefully. even d +322|33310|8317|6|3|3729.93|0.08|0.05|A|F|1992-07-03|1992-05-10|1992-07-28|NONE|AIR|ending, ironic deposits along the blith +322|37435|4945|7|5|6862.15|0.01|0.02|A|F|1992-04-15|1992-05-12|1992-04-26|COLLECT COD|REG AIR| special grouches sleep quickly instructio +323|163628|1177|1|50|84581.00|0.05|0.04|A|F|1994-04-20|1994-04-25|1994-05-12|DELIVER IN PERSON|REG AIR|cial requests +323|95136|7646|2|18|20360.34|0.06|0.07|R|F|1994-04-13|1994-06-02|1994-05-10|DELIVER IN PERSON|TRUCK|posits cajole furiously pinto beans. +323|142725|2726|3|9|15909.48|0.07|0.04|A|F|1994-06-26|1994-06-10|1994-07-13|COLLECT COD|TRUCK|nic accounts. regular, regular pack +324|199475|4514|1|26|40936.22|0.07|0.01|R|F|1992-04-19|1992-05-28|1992-05-12|DELIVER IN PERSON|RAIL|ross the slyly regular s +325|158791|6337|1|34|62892.86|0.09|0.04|A|F|1993-10-28|1993-12-13|1993-11-17|TAKE BACK RETURN|MAIL|ly bold deposits. always iron +325|185139|7658|2|5|6120.65|0.07|0.08|A|F|1994-01-02|1994-01-05|1994-01-04|TAKE BACK RETURN|MAIL| theodolites. +325|18788|1290|3|35|59737.30|0.07|0.07|A|F|1993-12-06|1994-01-03|1993-12-26|DELIVER IN PERSON|REG AIR|packages wa +326|179094|4129|1|41|48096.69|0.06|0.03|N|O|1995-08-30|1995-07-09|1995-09-12|DELIVER IN PERSON|TRUCK|ily quickly bold ideas. +326|19480|1982|2|38|53180.24|0.02|0.08|N|O|1995-09-12|1995-08-23|1995-09-14|COLLECT COD|RAIL|es sleep slyly. carefully regular inst +326|183739|8776|3|25|45568.25|0.03|0.04|N|O|1995-08-03|1995-07-27|1995-08-16|NONE|AIR|ily furiously unusual accounts. +326|84836|9853|4|5|9104.15|0.03|0.08|N|O|1995-07-29|1995-07-13|1995-08-12|NONE|REG AIR|deas sleep according to the sometimes spe +326|34543|9550|5|31|45803.74|0.04|0.08|N|O|1995-09-27|1995-07-06|1995-10-22|NONE|TRUCK|cies sleep quick +326|156712|4258|6|41|72517.11|0.02|0.00|N|O|1995-07-05|1995-07-23|1995-07-20|TAKE BACK RETURN|REG AIR|to beans wake before the furiously re +326|42134|4639|7|47|50578.11|0.04|0.04|N|O|1995-09-16|1995-07-04|1995-10-04|NONE|REG AIR| special accounts sleep +327|143503|1046|1|16|24744.00|0.03|0.01|N|O|1995-07-05|1995-06-07|1995-07-09|TAKE BACK RETURN|TRUCK|cial ideas sleep af +327|41715|4220|2|9|14910.39|0.09|0.05|A|F|1995-05-24|1995-07-11|1995-06-05|NONE|AIR| asymptotes are fu +352|63762|3763|1|17|29337.92|0.07|0.05|R|F|1994-06-02|1994-05-31|1994-06-29|NONE|FOB|pending deposits sleep furiously +353|119305|4328|1|41|54296.30|0.00|0.06|A|F|1994-03-25|1994-03-31|1994-03-30|DELIVER IN PERSON|AIR|refully final theodoli +353|147542|7543|2|29|46096.66|0.09|0.00|A|F|1994-01-11|1994-03-19|1994-02-09|COLLECT COD|FOB|ctions impr +353|134318|1858|3|12|16227.72|0.06|0.01|R|F|1994-01-02|1994-03-26|1994-01-19|DELIVER IN PERSON|RAIL|g deposits cajole +353|77071|2086|4|46|48211.22|0.00|0.04|A|F|1994-04-14|1994-01-31|1994-05-05|DELIVER IN PERSON|FOB| ironic dolphins +353|116803|1826|5|9|16378.20|0.02|0.02|A|F|1994-03-15|1994-03-20|1994-03-18|TAKE BACK RETURN|RAIL|ual accounts! carefu +353|102699|2700|6|39|66365.91|0.02|0.05|A|F|1994-01-15|1994-03-30|1994-02-01|NONE|MAIL|losely quickly even accounts. c +354|49480|1985|1|14|20012.72|0.08|0.04|N|O|1996-04-12|1996-06-03|1996-05-08|NONE|SHIP|quickly regular grouches will eat. careful +354|193864|1422|2|24|46988.64|0.01|0.01|N|O|1996-05-08|1996-05-17|1996-06-07|DELIVER IN PERSON|AIR|y silent requests. regular, even accounts +354|58125|8126|3|50|54156.00|0.08|0.05|N|O|1996-03-21|1996-05-20|1996-04-04|COLLECT COD|TRUCK|to beans s +354|106672|4203|4|7|11750.69|0.06|0.01|N|O|1996-05-07|1996-04-18|1996-05-24|NONE|MAIL|ously idly ironic accounts-- quickl +354|30527|528|5|18|26235.36|0.04|0.08|N|O|1996-03-31|1996-05-13|1996-04-27|DELIVER IN PERSON|RAIL| about the carefully unusual +354|61082|3589|6|36|37550.88|0.03|0.02|N|O|1996-03-19|1996-05-29|1996-03-30|NONE|AIR|onic requests thrash bold g +354|4660|9661|7|14|21905.24|0.01|0.07|N|O|1996-07-06|1996-06-08|1996-07-10|TAKE BACK RETURN|MAIL|t thinly above the ironic, +355|113959|8982|1|31|61161.45|0.09|0.07|A|F|1994-07-13|1994-08-18|1994-07-18|DELIVER IN PERSON|FOB|y unusual, ironic +355|96030|3558|2|41|42067.23|0.05|0.00|A|F|1994-08-15|1994-07-19|1994-09-06|DELIVER IN PERSON|TRUCK| deposits. carefully r +356|45214|5215|1|4|4636.84|0.10|0.01|A|F|1994-07-28|1994-08-01|1994-08-04|DELIVER IN PERSON|REG AIR| the dependencies nod unusual, final ac +356|107463|2484|2|48|70582.08|0.02|0.03|R|F|1994-08-12|1994-07-31|1994-08-26|NONE|FOB|unusual packages. furiously +356|118002|514|3|35|35700.00|0.08|0.07|R|F|1994-10-14|1994-07-31|1994-10-23|COLLECT COD|TRUCK|s. unusual, final +356|55342|353|4|41|53190.94|0.07|0.05|A|F|1994-09-28|1994-09-20|1994-10-07|COLLECT COD|SHIP| according to the express foxes will +356|124271|1808|5|37|47924.99|0.05|0.03|A|F|1994-07-15|1994-08-24|1994-08-09|DELIVER IN PERSON|FOB|ndencies are since the packag +357|113143|3144|1|26|30059.64|0.06|0.03|N|O|1996-12-28|1996-11-26|1997-01-13|NONE|FOB| carefully pending accounts use a +357|185814|8333|2|36|68393.16|0.07|0.06|N|O|1996-12-28|1996-11-13|1997-01-24|DELIVER IN PERSON|AIR|d the carefully even requests. +357|164807|9840|3|32|59897.60|0.05|0.07|N|O|1997-01-28|1996-12-29|1997-02-14|NONE|MAIL|y above the carefully final accounts +358|190028|2548|1|41|45838.82|0.06|0.01|A|F|1993-11-18|1993-11-14|1993-11-28|NONE|TRUCK|ely frets. furious deposits sleep +358|189955|7510|2|32|65438.40|0.05|0.08|A|F|1993-10-18|1993-12-12|1993-10-31|NONE|TRUCK|y final foxes sleep blithely sl +358|168710|3743|3|40|71148.40|0.09|0.01|A|F|1993-12-05|1993-11-04|1994-01-01|COLLECT COD|MAIL|ng the ironic theo +358|96557|1576|4|15|23303.25|0.08|0.08|A|F|1993-10-04|1993-12-17|1993-10-23|TAKE BACK RETURN|MAIL|out the blithely ironic deposits slee +358|28629|6136|5|18|28037.16|0.01|0.02|R|F|1993-10-07|1993-11-01|1993-10-26|COLLECT COD|SHIP|olphins haggle ironic accounts. f +358|161283|1284|6|32|43016.96|0.03|0.05|R|F|1993-12-21|1993-11-06|1994-01-17|DELIVER IN PERSON|RAIL|lyly express deposits +358|82916|7933|7|45|85450.95|0.05|0.02|A|F|1993-12-08|1993-10-29|1993-12-30|NONE|REG AIR|to beans. regular, unusual deposits sl +359|165980|5981|1|30|61379.40|0.00|0.08|A|F|1995-01-06|1995-02-20|1995-01-20|TAKE BACK RETURN|AIR|uses detect spec +359|11158|6161|2|18|19244.70|0.00|0.03|A|F|1995-01-27|1995-03-18|1995-01-31|DELIVER IN PERSON|RAIL|unusual warthogs. ironically sp +359|131463|3977|3|17|25405.82|0.07|0.06|A|F|1995-01-31|1995-03-18|1995-02-10|COLLECT COD|SHIP|sts according to the blithely +359|89985|2494|4|38|75049.24|0.10|0.08|R|F|1995-03-30|1995-01-20|1995-04-25|DELIVER IN PERSON|RAIL|g furiously. regular, sile +359|167239|2272|5|11|14368.53|0.01|0.03|A|F|1995-02-15|1995-01-27|1995-02-18|NONE|FOB|rets wake blithely. slyly final dep +359|182663|218|6|23|40150.18|0.04|0.07|R|F|1995-01-31|1995-03-11|1995-02-16|DELIVER IN PERSON|REG AIR|ic courts snooze quickly furiously final fo +384|178442|3477|1|38|57776.72|0.07|0.01|R|F|1992-06-02|1992-04-18|1992-06-10|DELIVER IN PERSON|TRUCK|totes cajole blithely against the even +384|63342|5849|2|49|63961.66|0.09|0.07|A|F|1992-04-01|1992-04-25|1992-04-18|COLLECT COD|AIR|refully carefully ironic instructions. bl +384|181502|6539|3|11|17418.50|0.02|0.08|A|F|1992-04-02|1992-04-21|1992-04-15|COLLECT COD|MAIL|ash carefully +384|92053|7072|4|11|11495.55|0.00|0.06|R|F|1992-06-24|1992-05-29|1992-07-22|COLLECT COD|TRUCK|nic excuses are furiously above the blith +384|131403|8943|5|14|20081.60|0.08|0.06|R|F|1992-06-14|1992-05-29|1992-07-05|DELIVER IN PERSON|TRUCK|ckages are slyly after the slyly specia +385|166446|8963|1|7|10587.08|0.05|0.06|N|O|1996-05-23|1996-05-09|1996-06-06|DELIVER IN PERSON|REG AIR| special asymptote +385|53025|8036|2|46|44988.92|0.08|0.07|N|O|1996-03-29|1996-05-17|1996-04-18|NONE|REG AIR|lthily ironic f +386|152405|9951|1|39|56838.60|0.10|0.07|A|F|1995-05-10|1995-02-28|1995-05-25|NONE|SHIP|hely. carefully regular accounts hag +386|68123|5642|2|16|17457.92|0.06|0.01|A|F|1995-04-12|1995-04-18|1995-05-11|DELIVER IN PERSON|MAIL|lithely fluffi +386|130081|82|3|37|41109.96|0.09|0.04|A|F|1995-05-23|1995-03-01|1995-05-25|TAKE BACK RETURN|MAIL|ending pearls breach fluffily. slyly pen +387|136667|1694|1|1|1703.66|0.08|0.03|N|O|1997-05-06|1997-04-23|1997-05-10|NONE|SHIP| pinto beans wake furiously carefu +387|152800|2801|2|42|77817.60|0.07|0.05|N|O|1997-05-25|1997-02-25|1997-05-29|DELIVER IN PERSON|RAIL|lithely final theodolites. +387|96392|1411|3|40|55535.60|0.09|0.02|N|O|1997-03-08|1997-04-18|1997-03-31|COLLECT COD|TRUCK| quickly ironic platelets are slyly. fluff +387|55927|5928|4|19|35775.48|0.08|0.00|N|O|1997-03-14|1997-04-21|1997-04-04|NONE|REG AIR|gular dependencies +387|148313|828|5|32|43561.92|0.08|0.06|N|O|1997-05-02|1997-04-11|1997-05-11|DELIVER IN PERSON|TRUCK|gle. silent, fur +388|32590|100|1|42|63948.78|0.05|0.06|R|F|1993-02-21|1993-02-26|1993-03-15|COLLECT COD|FOB|accounts sleep furiously +388|127808|7809|2|46|84446.80|0.07|0.01|A|F|1993-03-22|1993-01-26|1993-03-24|COLLECT COD|FOB|to beans nag about the careful reque +388|64486|9499|3|40|58019.20|0.06|0.01|A|F|1992-12-24|1993-01-28|1993-01-19|TAKE BACK RETURN|REG AIR|quests against the carefully unusual epi +389|189295|1814|1|2|2768.58|0.09|0.00|R|F|1994-04-13|1994-04-10|1994-04-25|TAKE BACK RETURN|RAIL|fts. courts eat blithely even dependenc +390|106523|9034|1|10|15295.20|0.02|0.05|N|O|1998-05-26|1998-07-06|1998-06-23|TAKE BACK RETURN|SHIP| requests. final accounts x-ray beside the +390|123353|890|2|17|23397.95|0.09|0.06|N|O|1998-06-07|1998-06-14|1998-07-07|COLLECT COD|SHIP|ending, pending pinto beans wake slyl +390|183266|8303|3|46|62065.96|0.07|0.04|N|O|1998-06-06|1998-05-20|1998-06-14|DELIVER IN PERSON|SHIP|cial excuses. bold, pending packages +390|141937|1938|4|42|83115.06|0.01|0.05|N|O|1998-06-06|1998-06-22|1998-07-05|COLLECT COD|SHIP|counts nag across the sly, sil +390|127657|170|5|13|21900.45|0.02|0.06|N|O|1998-07-08|1998-05-10|1998-07-18|DELIVER IN PERSON|SHIP|sleep carefully idle packages. blithely +390|124632|9657|6|11|18222.93|0.09|0.06|N|O|1998-05-05|1998-05-15|1998-06-01|DELIVER IN PERSON|SHIP|according to the foxes are furiously +390|84937|2462|7|24|46126.32|0.05|0.02|N|O|1998-04-18|1998-05-19|1998-04-28|TAKE BACK RETURN|AIR|y. enticingly final depos +391|121586|6611|1|14|22506.12|0.09|0.02|R|F|1995-02-11|1995-02-03|1995-02-13|TAKE BACK RETURN|TRUCK| escapades sleep furiously about +416|93563|6073|1|25|38914.00|0.00|0.05|A|F|1993-10-11|1993-11-26|1993-10-21|DELIVER IN PERSON|TRUCK|y final theodolites about +416|110869|8403|2|22|41356.92|0.10|0.00|R|F|1993-12-27|1993-12-17|1994-01-09|COLLECT COD|RAIL|rint blithely above the pending sentim +416|174101|6619|3|25|29377.50|0.07|0.01|R|F|1993-10-16|1993-12-03|1993-10-29|NONE|AIR|ses boost after the bold requests. +417|39560|9561|1|39|58482.84|0.01|0.02|A|F|1994-05-31|1994-05-02|1994-06-06|NONE|SHIP|y regular requests wake along +417|69212|4225|2|18|21261.78|0.00|0.01|R|F|1994-03-29|1994-04-10|1994-04-26|TAKE BACK RETURN|FOB|- final requests sle +417|44192|6697|3|41|46583.79|0.10|0.01|R|F|1994-04-11|1994-03-08|1994-05-06|COLLECT COD|RAIL|tes. regular requests across the +417|131087|1088|4|2|2236.16|0.01|0.03|R|F|1994-02-13|1994-04-19|1994-03-15|DELIVER IN PERSON|SHIP|uriously bol +418|18552|1054|1|31|45587.05|0.00|0.03|N|F|1995-06-05|1995-06-18|1995-06-26|COLLECT COD|FOB|final theodolites. fluffil +418|1062|3563|2|1|963.06|0.04|0.07|N|O|1995-06-23|1995-06-16|1995-07-23|DELIVER IN PERSON|AIR|regular, silent pinto +418|34829|7333|3|3|5291.46|0.04|0.06|N|O|1995-06-29|1995-07-12|1995-07-01|COLLECT COD|AIR|ly furiously regular w +419|152691|7722|1|33|57541.77|0.05|0.02|N|O|1996-11-06|1996-12-25|1996-11-20|TAKE BACK RETURN|TRUCK|y above the bli +419|64192|9205|2|32|36998.08|0.01|0.06|N|O|1996-12-04|1996-12-04|1996-12-24|COLLECT COD|SHIP|blithely regular requests. special pinto +419|70495|3003|3|15|21982.35|0.07|0.04|N|O|1996-12-17|1996-11-28|1996-12-19|TAKE BACK RETURN|REG AIR| sleep final, regular theodolites. fluffi +419|8756|6257|4|15|24971.25|0.01|0.02|N|O|1997-01-09|1996-12-22|1997-01-25|COLLECT COD|FOB|of the careful, thin theodolites. quickly s +419|148401|3430|5|17|24639.80|0.01|0.00|N|O|1997-01-13|1996-12-20|1997-02-01|COLLECT COD|REG AIR|lar dependencies: carefully regu +420|100885|5906|1|5|9429.40|0.04|0.03|N|O|1995-11-04|1996-01-02|1995-11-30|NONE|REG AIR|cajole blit +420|161079|8628|2|22|25081.54|0.05|0.04|N|O|1996-01-25|1995-12-16|1996-02-03|TAKE BACK RETURN|AIR|ly against the blithely re +420|47557|2566|3|45|67704.75|0.09|0.08|N|O|1996-01-14|1996-01-01|1996-01-26|COLLECT COD|FOB| final accounts. furiously express forges +420|74795|4796|4|12|21237.48|0.08|0.08|N|O|1996-02-05|1996-01-03|1996-02-12|TAKE BACK RETURN|REG AIR|c instructions are +420|72918|7933|5|37|69963.67|0.02|0.00|N|O|1995-11-16|1995-12-13|1995-11-19|DELIVER IN PERSON|SHIP|rbits. bold requests along the quickl +420|123736|1273|6|40|70389.20|0.01|0.05|N|O|1995-11-26|1995-12-26|1995-12-20|TAKE BACK RETURN|FOB| after the special +420|15978|5979|7|39|73864.83|0.00|0.08|N|O|1995-12-09|1995-12-16|1995-12-31|DELIVER IN PERSON|REG AIR|s. ironic waters about the car +421|133070|3071|1|1|1103.07|0.02|0.07|R|F|1992-05-29|1992-04-27|1992-06-09|NONE|TRUCK|oldly busy deposit +422|151816|4332|1|25|46695.25|0.10|0.07|N|O|1997-07-01|1997-08-17|1997-07-09|DELIVER IN PERSON|SHIP|carefully bold theodolit +422|170666|3184|2|10|17366.60|0.02|0.03|N|O|1997-06-15|1997-08-04|1997-07-08|TAKE BACK RETURN|AIR|he furiously ironic theodolite +422|175984|3536|3|46|94759.08|0.09|0.00|N|O|1997-06-21|1997-07-14|1997-06-27|DELIVER IN PERSON|RAIL| ideas. qu +422|161622|9171|4|25|42090.50|0.10|0.04|N|O|1997-08-24|1997-07-09|1997-09-22|NONE|FOB|ep along the furiousl +423|131890|6917|1|27|51891.03|0.06|0.03|N|O|1996-08-20|1996-08-01|1996-08-23|TAKE BACK RETURN|SHIP|ccounts. blithely regular pack +448|125197|5198|1|4|4888.76|0.00|0.04|N|O|1995-11-25|1995-10-20|1995-11-26|TAKE BACK RETURN|MAIL|nts thrash quickly among the b +448|172359|9911|2|46|65842.10|0.05|0.00|N|O|1995-08-31|1995-09-30|1995-09-09|COLLECT COD|SHIP| to the fluffily ironic packages. +448|26809|1814|3|35|60753.00|0.10|0.08|N|O|1995-09-27|1995-11-19|1995-10-20|COLLECT COD|REG AIR|ses nag quickly quickly ir +448|169045|9046|4|8|8912.32|0.10|0.00|N|O|1995-11-02|1995-10-16|1995-11-15|COLLECT COD|TRUCK|ounts wake blithely. furiously pending +448|137283|7284|5|23|30366.44|0.02|0.05|N|O|1995-09-26|1995-11-02|1995-10-17|NONE|SHIP|ious, final gifts +449|151908|6939|1|12|23518.80|0.02|0.08|N|O|1995-11-06|1995-08-25|1995-11-18|TAKE BACK RETURN|SHIP|ly. blithely ironic +449|108408|5939|2|4|5665.60|0.10|0.06|N|O|1995-10-27|1995-09-14|1995-11-21|DELIVER IN PERSON|FOB|are fluffily. requests are furiously +449|9982|9983|3|3|5675.94|0.07|0.08|N|O|1995-07-28|1995-09-11|1995-08-01|NONE|RAIL| bold deposits. express theodolites haggle +449|157659|2690|4|22|37766.30|0.07|0.00|N|O|1995-08-17|1995-09-04|1995-09-10|COLLECT COD|FOB|furiously final theodolites eat careful +450|161582|9131|1|42|69030.36|0.03|0.00|N|F|1995-06-07|1995-05-29|1995-06-23|TAKE BACK RETURN|SHIP|y asymptotes. regular depen +450|106298|6299|2|5|6521.45|0.03|0.02|A|F|1995-04-02|1995-05-06|1995-04-13|TAKE BACK RETURN|TRUCK|the pinto bea +450|142528|7557|3|32|50256.64|0.06|0.03|N|O|1995-07-02|1995-04-25|1995-07-30|TAKE BACK RETURN|SHIP| accounts nod fluffily even, pending +450|56267|3783|4|40|48930.40|0.05|0.03|R|F|1995-03-20|1995-05-25|1995-04-14|NONE|RAIL|ve. asymptote +450|78048|8049|5|2|2052.08|0.09|0.00|A|F|1995-03-11|1995-05-21|1995-03-16|COLLECT COD|AIR|y even pinto beans; qui +450|152726|5242|6|33|58697.76|0.08|0.05|R|F|1995-05-18|1995-05-22|1995-05-23|TAKE BACK RETURN|REG AIR|ily carefully final depo +451|129532|4557|1|36|56215.08|0.02|0.06|N|O|1998-06-18|1998-08-14|1998-06-20|TAKE BACK RETURN|AIR|rges can haggle carefully ironic, dogged +451|32028|7035|2|42|40320.84|0.05|0.01|N|O|1998-08-01|1998-08-05|1998-08-30|DELIVER IN PERSON|TRUCK|express excuses. blithely ironic pin +451|86136|6137|3|1|1122.13|0.07|0.05|N|O|1998-07-13|1998-07-03|1998-08-04|DELIVER IN PERSON|AIR| carefully ironic packages solve furiously +451|76558|4080|4|28|42967.40|0.04|0.05|N|O|1998-06-16|1998-07-09|1998-06-17|DELIVER IN PERSON|SHIP| theodolites. even cou +452|114639|4640|1|2|3307.26|0.04|0.03|N|O|1997-12-26|1998-01-03|1998-01-12|COLLECT COD|FOB|y express instru +453|197917|2956|1|45|90670.95|0.01|0.00|N|O|1997-06-30|1997-08-20|1997-07-19|COLLECT COD|REG AIR|ifts wake carefully. +453|175131|2683|2|38|45832.94|0.08|0.04|N|O|1997-06-30|1997-07-08|1997-07-16|DELIVER IN PERSON|REG AIR| furiously f +453|13144|8147|3|38|40171.32|0.10|0.01|N|O|1997-08-10|1997-07-24|1997-09-07|NONE|SHIP|sts cajole. furiously un +453|95748|5749|4|45|78468.30|0.10|0.01|N|O|1997-09-18|1997-06-29|1997-10-14|TAKE BACK RETURN|AIR|ironic foxes. slyly pending depos +453|25722|8225|5|32|52727.04|0.04|0.01|N|O|1997-07-15|1997-06-27|1997-07-18|NONE|REG AIR|s. fluffily bold packages cajole. unu +453|94318|6828|6|28|36744.68|0.07|0.07|N|O|1997-08-16|1997-08-12|1997-08-27|NONE|MAIL|final dependencies. slyly special pl +454|117595|5129|1|24|38702.16|0.06|0.01|N|O|1996-04-26|1996-03-23|1996-05-20|NONE|TRUCK|le. deposits after the ideas nag unusual pa +455|156485|4031|1|42|64742.16|0.10|0.02|N|O|1997-01-26|1997-01-10|1997-02-22|DELIVER IN PERSON|REG AIR|around the quickly blit +455|27230|7231|2|44|50918.12|0.05|0.08|N|O|1997-01-17|1997-02-22|1997-02-12|TAKE BACK RETURN|TRUCK| accounts sleep slyly ironic asymptote +455|48360|3369|3|45|58876.20|0.04|0.06|N|O|1996-12-20|1997-01-31|1997-01-07|TAKE BACK RETURN|SHIP|thrash ironically regular packages. qui +455|170012|7564|4|11|11902.11|0.01|0.02|N|O|1997-03-15|1997-02-14|1997-03-26|DELIVER IN PERSON|MAIL|g deposits against the slyly idle foxes u +480|52148|2149|1|22|24203.08|0.04|0.02|A|F|1993-06-16|1993-07-28|1993-07-09|NONE|MAIL|into beans cajole furiously. accounts s +481|18649|6153|1|17|26649.88|0.07|0.05|A|F|1992-10-21|1992-12-09|1992-11-19|DELIVER IN PERSON|MAIL|. quickly final accounts among the +481|20646|647|2|19|29766.16|0.08|0.01|R|F|1993-01-09|1992-11-27|1993-01-14|TAKE BACK RETURN|AIR|p blithely after t +481|185785|5786|3|42|78572.76|0.08|0.08|A|F|1992-11-27|1992-11-11|1992-12-08|COLLECT COD|RAIL|mptotes are furiously among the iron +481|81009|6026|4|11|10890.00|0.05|0.06|A|F|1993-01-12|1992-11-17|1993-02-05|NONE|FOB|eful attai +481|111956|6979|5|31|61006.45|0.05|0.01|A|F|1993-01-15|1992-12-31|1993-01-21|DELIVER IN PERSON|AIR|usly final packages believe. quick +482|137343|7344|1|32|44170.88|0.00|0.02|N|O|1996-05-22|1996-05-14|1996-05-29|NONE|SHIP|usual deposits affix against +482|121382|8919|2|1|1403.38|0.05|0.08|N|O|1996-05-29|1996-05-20|1996-05-31|COLLECT COD|AIR|es. quickly ironic escapades sleep furious +482|61141|6154|3|31|34166.34|0.04|0.03|N|O|1996-06-01|1996-05-06|1996-06-17|NONE|MAIL| blithe pin +482|195826|5827|4|8|15374.56|0.02|0.05|N|O|1996-04-19|1996-05-05|1996-04-21|NONE|TRUCK|tructions near the final, regular ideas de +482|38215|3222|5|46|53047.66|0.01|0.06|N|O|1996-07-19|1996-06-05|1996-08-10|NONE|MAIL|furiously thin realms. final, fina +482|78696|8697|6|19|31819.11|0.04|0.00|N|O|1996-03-27|1996-04-25|1996-04-15|NONE|FOB|ts hinder carefully silent requests +483|32694|5198|1|8|13013.52|0.00|0.08|N|O|1995-08-22|1995-08-23|1995-09-18|COLLECT COD|RAIL|osits. carefully fin +483|79758|9759|2|23|39968.25|0.04|0.06|N|O|1995-07-20|1995-08-11|1995-08-04|DELIVER IN PERSON|MAIL|requests was quickly against th +483|87745|254|3|9|15594.66|0.04|0.03|N|O|1995-09-10|1995-09-02|1995-09-13|NONE|AIR| carefully express ins +484|30133|5140|1|49|52093.37|0.10|0.02|N|O|1997-03-06|1997-02-28|1997-03-23|COLLECT COD|TRUCK|ven accounts +484|31950|9460|2|45|84687.75|0.06|0.07|N|O|1997-04-09|1997-03-20|1997-04-19|DELIVER IN PERSON|TRUCK|usly final excuses boost slyly blithe +484|183351|5870|3|50|71717.50|0.06|0.05|N|O|1997-01-24|1997-03-27|1997-02-22|DELIVER IN PERSON|MAIL|uctions wake. final, silent requests haggle +484|164805|4806|4|22|41135.60|0.07|0.03|N|O|1997-04-29|1997-03-26|1997-05-17|TAKE BACK RETURN|SHIP|es are pending instructions. furiously unu +484|76308|1323|5|48|61646.40|0.00|0.05|N|O|1997-03-05|1997-02-08|1997-03-22|TAKE BACK RETURN|MAIL|l, bold packages? even mult +484|96871|9381|6|10|18678.70|0.01|0.08|N|O|1997-04-06|1997-02-14|1997-04-16|COLLECT COD|FOB|x fluffily carefully regular +485|149523|9524|1|50|78626.00|0.01|0.00|N|O|1997-03-28|1997-05-26|1997-04-18|TAKE BACK RETURN|MAIL|iously quick excuses. carefully final f +485|27973|2978|2|40|76038.80|0.08|0.01|N|O|1997-04-29|1997-05-08|1997-04-30|TAKE BACK RETURN|TRUCK|al escapades +485|136884|4424|3|22|42259.36|0.00|0.05|N|O|1997-04-06|1997-04-27|1997-05-01|DELIVER IN PERSON|TRUCK|refully final notornis haggle according +486|75437|5438|1|36|50847.48|0.00|0.01|N|O|1996-06-25|1996-05-06|1996-07-07|COLLECT COD|AIR|deposits around the quickly regular packa +486|67040|7041|2|40|40281.60|0.03|0.08|N|O|1996-05-21|1996-06-06|1996-06-07|COLLECT COD|SHIP|ts nag quickly among the slyl +486|135912|8426|3|26|50645.66|0.04|0.03|N|O|1996-03-16|1996-05-25|1996-03-31|NONE|RAIL|forges along the +486|71865|6880|4|38|69800.68|0.08|0.05|N|O|1996-05-07|1996-04-26|1996-05-26|TAKE BACK RETURN|TRUCK| blithely final pinto +486|28099|5606|5|3|3081.27|0.07|0.05|N|O|1996-07-07|1996-04-20|1996-07-23|DELIVER IN PERSON|RAIL|ccounts ha +486|46543|9048|6|46|68518.84|0.00|0.03|N|O|1996-04-18|1996-05-02|1996-04-20|COLLECT COD|AIR|theodolites eat carefully furious +487|91896|1897|1|47|88730.83|0.06|0.06|R|F|1992-09-30|1992-10-08|1992-10-24|NONE|TRUCK|tions. blithely reg +487|82099|2100|2|2|2162.18|0.02|0.06|R|F|1992-10-19|1992-11-04|1992-11-11|COLLECT COD|TRUCK|oss the unusual pinto beans. reg +512|188804|1323|1|19|35963.20|0.08|0.05|N|O|1995-07-12|1995-07-11|1995-08-04|COLLECT COD|MAIL| sleep. requests alongside of the fluff +512|22847|7852|2|37|65484.08|0.01|0.04|N|O|1995-06-20|1995-07-05|1995-07-16|NONE|RAIL|nic depths cajole? blithely b +512|179419|9420|3|40|59936.40|0.05|0.02|N|O|1995-07-06|1995-07-08|1995-07-08|COLLECT COD|TRUCK|quests are da +512|82470|7487|4|10|14524.70|0.09|0.02|N|O|1995-09-16|1995-07-29|1995-10-07|NONE|AIR|xes. pinto beans cajole carefully; +512|64154|4155|5|6|6708.90|0.03|0.05|R|F|1995-06-10|1995-06-21|1995-06-16|DELIVER IN PERSON|FOB|en ideas haggle +512|32014|4518|6|12|11352.12|0.04|0.00|R|F|1995-05-21|1995-08-03|1995-06-09|COLLECT COD|FOB|old furiously express deposits. specia +512|50769|3275|7|2|3439.52|0.09|0.08|N|O|1995-06-19|1995-08-13|1995-06-24|NONE|TRUCK|e slyly silent accounts serve with +513|61732|9251|1|20|33874.60|0.09|0.07|N|O|1995-07-12|1995-05-31|1995-07-31|NONE|AIR|efully ironic ideas doze slyl +513|121628|9165|2|44|72583.28|0.01|0.01|N|O|1995-07-14|1995-07-14|1995-08-12|NONE|MAIL|kages sleep boldly ironic theodolites. acco +514|78713|1221|1|21|35525.91|0.06|0.02|N|O|1996-06-09|1996-05-15|1996-07-07|DELIVER IN PERSON|RAIL|s sleep quickly blithely +514|117452|9964|2|34|49961.30|0.08|0.02|N|O|1996-04-14|1996-06-03|1996-04-23|COLLECT COD|REG AIR|ily even patterns. bold, silent instruc +514|12812|5314|3|6|10348.86|0.06|0.01|N|O|1996-05-30|1996-06-04|1996-06-28|COLLECT COD|SHIP|as haggle blithely; quickly s +514|115362|5363|4|43|59226.48|0.00|0.08|N|O|1996-06-07|1996-05-14|1996-07-01|TAKE BACK RETURN|FOB|thely regular +515|104014|6525|1|10|10180.10|0.03|0.02|A|F|1993-10-04|1993-11-03|1993-10-08|NONE|FOB|ar deposits th +515|147605|2634|2|38|62798.80|0.10|0.07|A|F|1993-09-19|1993-11-12|1993-10-03|DELIVER IN PERSON|SHIP|ays. furiously express requests haggle furi +515|182145|9700|3|11|13498.54|0.00|0.02|R|F|1993-09-04|1993-10-02|1993-09-05|DELIVER IN PERSON|FOB|ly pending accounts haggle blithel +515|108606|8607|4|34|54896.40|0.09|0.03|R|F|1993-10-03|1993-10-26|1993-10-15|DELIVER IN PERSON|REG AIR|ic dependencie +515|130881|3395|5|32|61180.16|0.01|0.07|R|F|1993-10-10|1993-10-08|1993-11-02|TAKE BACK RETURN|FOB|r sauternes boost. final theodolites wake a +515|108692|3713|6|25|42517.25|0.04|0.08|R|F|1993-11-14|1993-11-07|1993-12-03|DELIVER IN PERSON|MAIL|e packages engag +516|24974|9979|1|11|20888.67|0.01|0.06|N|O|1998-05-02|1998-05-23|1998-05-12|DELIVER IN PERSON|FOB|ongside of the blithely final reque +517|44551|4552|1|28|41875.40|0.03|0.02|N|O|1997-04-30|1997-05-18|1997-05-17|COLLECT COD|MAIL| requests. special, fi +517|155391|7907|2|15|21695.85|0.02|0.00|N|O|1997-04-09|1997-06-26|1997-05-01|NONE|TRUCK| slyly. express requests ar +517|40932|3437|3|9|16856.37|0.04|0.00|N|O|1997-05-03|1997-06-16|1997-05-24|COLLECT COD|SHIP| slyly stealthily express instructions. +517|132197|2198|4|11|13521.09|0.06|0.02|N|O|1997-06-20|1997-06-01|1997-06-27|NONE|REG AIR|ly throughout the fu +517|23349|8354|5|23|29263.82|0.00|0.01|N|O|1997-04-19|1997-05-07|1997-05-12|COLLECT COD|RAIL| kindle. furiously bold requests mus +518|164711|4712|1|30|53271.30|0.07|0.05|N|O|1998-02-18|1998-03-27|1998-03-16|COLLECT COD|TRUCK|slyly by the packages. carefull +518|83164|689|2|23|26384.68|0.05|0.07|N|O|1998-02-20|1998-05-05|1998-03-11|COLLECT COD|TRUCK| special requests. fluffily ironic re +518|133178|8205|3|12|14534.04|0.01|0.06|N|O|1998-03-08|1998-03-31|1998-04-06|NONE|AIR| packages thrash slyly +518|121990|1991|4|46|92551.54|0.07|0.02|N|O|1998-04-07|1998-04-17|1998-04-29|NONE|MAIL|. blithely even ideas cajole furiously. b +518|70019|20|5|16|15824.16|0.01|0.01|N|O|1998-03-15|1998-03-24|1998-04-08|NONE|MAIL|use quickly expre +518|196358|1397|6|39|56719.65|0.09|0.08|N|O|1998-02-26|1998-03-17|1998-03-21|DELIVER IN PERSON|FOB| the bold, special deposits are carefully +518|185956|8475|7|48|98013.60|0.03|0.07|N|O|1998-03-06|1998-04-22|1998-03-14|NONE|FOB| slyly final platelets; quickly even deposi +519|158970|4001|1|1|2028.97|0.07|0.07|N|O|1997-12-01|1998-01-26|1997-12-23|COLLECT COD|REG AIR|bold requests believe furiou +519|2946|2947|2|38|70259.72|0.05|0.08|N|O|1998-02-19|1997-12-15|1998-03-19|DELIVER IN PERSON|FOB|gular excuses detect quickly furiously +519|105900|921|3|19|36212.10|0.00|0.02|N|O|1998-01-09|1998-01-03|1998-02-06|COLLECT COD|AIR|asymptotes. p +519|46267|3780|4|27|32758.02|0.08|0.06|N|O|1997-11-20|1997-12-06|1997-12-16|DELIVER IN PERSON|REG AIR|le. even, final dependencies +519|9041|4042|5|13|12350.52|0.06|0.08|N|O|1998-02-06|1997-12-02|1998-03-03|TAKE BACK RETURN|TRUCK|c accounts wake along the ironic so +519|150926|5957|6|3|5930.76|0.04|0.00|N|O|1998-02-01|1998-01-25|1998-02-27|TAKE BACK RETURN|FOB|erve blithely blithely ironic asymp +544|138474|8475|1|47|71086.09|0.08|0.06|R|F|1993-03-14|1993-03-27|1993-03-27|COLLECT COD|SHIP|ecial pains. deposits grow foxes. +545|169547|9548|1|4|6466.16|0.02|0.00|N|O|1996-02-23|1995-12-16|1996-03-21|DELIVER IN PERSON|FOB|, ironic grouches cajole over +545|170188|5223|2|18|22647.24|0.00|0.00|N|O|1996-02-21|1996-01-17|1996-02-26|NONE|RAIL|al, final packages affix. even a +546|84585|2110|1|16|25113.28|0.08|0.02|N|O|1997-02-04|1996-12-30|1997-02-25|DELIVER IN PERSON|TRUCK|de of the orbits. sometimes regula +547|70789|5804|1|44|77430.32|0.08|0.08|N|O|1996-10-18|1996-08-17|1996-10-27|TAKE BACK RETURN|FOB|thely express dependencies. qu +547|136347|1374|2|48|66400.32|0.01|0.04|N|O|1996-10-21|1996-08-04|1996-11-20|COLLECT COD|SHIP|thely specia +547|181345|6382|3|3|4279.02|0.05|0.02|N|O|1996-09-04|1996-08-01|1996-09-21|COLLECT COD|SHIP|pinto beans. ironi +548|196550|6551|1|2|3293.10|0.06|0.05|A|F|1994-11-26|1994-11-06|1994-12-06|COLLECT COD|MAIL|ests haggle quickly eve +548|4641|4642|2|6|9273.84|0.00|0.08|A|F|1995-01-18|1994-12-08|1995-02-10|NONE|TRUCK|sits wake furiously regular +548|182|7683|3|21|22725.78|0.03|0.08|A|F|1995-01-13|1994-12-18|1995-01-25|NONE|AIR|ideas. special accounts above the furiou +548|56720|4236|4|21|35211.12|0.08|0.03|A|F|1994-10-27|1994-12-04|1994-11-21|DELIVER IN PERSON|AIR| engage quickly. regular theo +548|92995|523|5|19|37771.81|0.00|0.02|A|F|1994-09-24|1994-11-24|1994-10-01|DELIVER IN PERSON|MAIL|courts boost care +548|152753|7784|6|32|57784.00|0.06|0.04|A|F|1994-12-16|1994-11-20|1994-12-29|NONE|REG AIR|c instruction +549|195061|100|1|18|20809.08|0.07|0.04|R|F|1992-10-19|1992-08-12|1992-11-13|COLLECT COD|REG AIR|furiously according to the ironic, regular +549|188735|8736|2|38|69301.74|0.07|0.05|A|F|1992-08-17|1992-08-28|1992-09-05|COLLECT COD|RAIL|the regular, furious excuses. carefu +549|65213|5214|3|36|42415.56|0.08|0.04|R|F|1992-09-11|1992-10-11|1992-09-12|DELIVER IN PERSON|AIR|ts against the ironic, even theodolites eng +549|20101|7608|4|18|18379.80|0.09|0.01|A|F|1992-07-31|1992-09-11|1992-08-08|NONE|RAIL|ely regular accounts above the +549|23480|987|5|38|53332.24|0.06|0.02|R|F|1992-08-23|1992-08-12|1992-08-25|COLLECT COD|REG AIR|eposits. carefully regular depos +550|190307|2827|1|31|43316.30|0.04|0.02|N|O|1995-10-24|1995-09-27|1995-11-04|COLLECT COD|AIR|thely silent packages. unusual +551|23786|6289|1|8|13678.24|0.08|0.02|N|O|1995-07-29|1995-07-18|1995-08-02|NONE|REG AIR| wake quickly slyly pending platel +551|158813|3844|2|20|37436.20|0.00|0.07|N|O|1995-09-18|1995-08-25|1995-10-11|COLLECT COD|TRUCK|r ideas. final, even ideas hinder alongside +551|161089|6122|3|16|18401.28|0.07|0.06|N|O|1995-07-29|1995-08-19|1995-08-10|COLLECT COD|MAIL|y along the carefully ex +576|86490|1507|1|2|2952.98|0.07|0.01|N|O|1997-05-15|1997-06-30|1997-05-28|NONE|RAIL|ccounts along the ac +576|33096|8103|2|6|6174.54|0.06|0.05|N|O|1997-05-15|1997-07-26|1997-06-03|DELIVER IN PERSON|TRUCK|al deposits. slyly even sauternes a +576|36565|9069|3|6|9009.36|0.08|0.07|N|O|1997-08-28|1997-06-16|1997-09-25|DELIVER IN PERSON|FOB|ts. ironic multipliers +576|137608|2635|4|5|8228.00|0.03|0.07|N|O|1997-06-11|1997-06-17|1997-07-05|NONE|REG AIR|l foxes boost slyly. accounts af +577|25886|891|1|25|45297.00|0.06|0.01|A|F|1995-04-09|1995-02-20|1995-05-09|TAKE BACK RETURN|AIR|ve slyly of the frets. careful +577|63233|8246|2|14|16747.22|0.08|0.03|R|F|1995-03-19|1995-02-25|1995-04-09|DELIVER IN PERSON|RAIL|l accounts wake deposits. ironic packa +578|155542|5543|1|40|63901.60|0.02|0.08|N|O|1997-02-10|1997-03-18|1997-02-11|NONE|SHIP|usly even platel +578|187025|2062|2|23|25576.46|0.05|0.08|N|O|1997-03-06|1997-03-03|1997-03-20|TAKE BACK RETURN|FOB|nstructions. ironic deposits +579|150618|5649|1|9|15017.49|0.00|0.05|N|O|1998-06-20|1998-04-28|1998-07-19|DELIVER IN PERSON|RAIL|e ironic, express deposits are furiously +579|32145|7152|2|39|42008.46|0.02|0.01|N|O|1998-06-21|1998-06-03|1998-06-26|COLLECT COD|REG AIR|ncies. furiously final r +579|59048|4059|3|6|6042.24|0.03|0.00|N|O|1998-04-24|1998-05-03|1998-05-08|TAKE BACK RETURN|TRUCK|ickly final requests-- bold accou +579|6189|8690|4|41|44902.38|0.04|0.05|N|O|1998-05-28|1998-05-01|1998-06-04|COLLECT COD|REG AIR|bold, express requests sublate slyly. blith +579|12612|5114|5|28|42689.08|0.00|0.03|N|O|1998-07-10|1998-05-24|1998-07-19|NONE|RAIL|ic ideas until th +579|166717|9234|6|5|8918.55|0.05|0.08|N|O|1998-05-02|1998-04-25|1998-05-05|COLLECT COD|REG AIR|refully silent ideas cajole furious +580|84916|2441|1|33|62730.03|0.03|0.05|N|O|1997-10-11|1997-09-19|1997-10-16|TAKE BACK RETURN|FOB|y express theodolites cajole carefully +580|173320|3321|2|31|43192.92|0.04|0.08|N|O|1997-10-04|1997-09-08|1997-10-15|COLLECT COD|FOB|ose alongside of the sl +580|184444|6963|3|19|29040.36|0.04|0.04|N|O|1997-07-23|1997-09-21|1997-08-15|NONE|FOB|mong the special packag +581|63384|8397|1|41|55242.58|0.09|0.07|N|O|1997-05-26|1997-04-06|1997-06-10|TAKE BACK RETURN|MAIL|nts. quickly +581|92527|5037|2|14|21273.28|0.06|0.08|N|O|1997-05-17|1997-04-14|1997-06-08|NONE|MAIL|. deposits s +581|100106|5127|3|49|54198.90|0.10|0.02|N|O|1997-02-27|1997-04-24|1997-03-10|TAKE BACK RETURN|MAIL|. slyly regular pinto beans acr +581|74925|9940|4|30|56997.60|0.10|0.08|N|O|1997-06-19|1997-05-21|1997-06-22|TAKE BACK RETURN|TRUCK| regular ideas grow furio +582|56409|3925|1|7|9557.80|0.07|0.00|N|O|1997-11-16|1997-11-29|1997-12-10|TAKE BACK RETURN|FOB|ithely unusual t +582|50262|263|2|49|59400.74|0.05|0.03|N|O|1997-12-17|1998-01-12|1997-12-31|COLLECT COD|REG AIR|nts according to the furiously regular pin +582|140309|5338|3|42|56670.60|0.07|0.00|N|O|1997-11-15|1997-12-21|1997-12-03|COLLECT COD|SHIP|iously beside the silent de +582|167750|7751|4|36|65439.00|0.06|0.01|N|O|1997-12-09|1997-11-27|1997-12-26|TAKE BACK RETURN|SHIP|lar requests. quickly +583|144364|4365|1|1|1408.36|0.07|0.07|N|O|1997-06-17|1997-04-29|1997-06-28|NONE|TRUCK| regular, regular ideas. even, bra +583|119625|2137|2|47|77297.14|0.10|0.06|N|O|1997-07-14|1997-05-12|1997-08-11|DELIVER IN PERSON|AIR|nts are fluffily. furiously even re +583|129431|1944|3|34|49654.62|0.01|0.02|N|O|1997-05-11|1997-04-24|1997-06-03|DELIVER IN PERSON|MAIL|express req +583|141250|8793|4|33|42611.25|0.10|0.01|N|O|1997-05-28|1997-04-25|1997-06-24|NONE|AIR|kages cajole slyly across the +583|188537|6092|5|13|21131.89|0.04|0.06|N|O|1997-06-23|1997-05-29|1997-07-08|COLLECT COD|TRUCK|y sly theodolites. ironi +608|153579|1125|1|19|31018.83|0.08|0.06|N|O|1996-04-19|1996-05-02|1996-05-03|DELIVER IN PERSON|RAIL|ideas. the +608|197310|2349|2|40|56292.40|0.03|0.01|N|O|1996-05-21|1996-04-11|1996-06-02|NONE|AIR| alongside of the regular tithes. sly +609|65533|8040|1|21|31469.13|0.01|0.05|R|F|1994-08-24|1994-08-23|1994-08-27|DELIVER IN PERSON|FOB|de of the special warthogs. excu +610|110792|5815|1|49|88336.71|0.10|0.07|N|O|1995-08-29|1995-10-26|1995-09-12|TAKE BACK RETURN|SHIP|ular instruc +610|67896|5415|2|11|20502.79|0.07|0.08|N|O|1995-10-31|1995-10-25|1995-11-18|NONE|MAIL|blithely final +610|117617|7618|3|26|42499.86|0.09|0.04|N|O|1995-11-22|1995-09-09|1995-12-04|TAKE BACK RETURN|AIR|cross the furiously even theodolites sl +610|185206|7725|4|17|21950.40|0.03|0.03|N|O|1995-11-01|1995-10-30|1995-11-04|COLLECT COD|FOB|p quickly instead of the slyly pending foxe +610|145743|5744|5|39|69760.86|0.08|0.05|N|O|1995-10-30|1995-10-21|1995-11-11|TAKE BACK RETURN|REG AIR|counts. ironic warhorses are +610|94365|6875|6|5|6796.80|0.00|0.07|N|O|1995-08-11|1995-10-22|1995-08-26|TAKE BACK RETURN|FOB|n pinto beans. iro +610|189280|4317|7|27|36970.56|0.06|0.03|N|O|1995-09-02|1995-09-19|1995-09-15|NONE|REG AIR| ironic pinto beans haggle. blithe +611|16855|4359|1|39|69102.15|0.05|0.06|R|F|1993-05-06|1993-04-09|1993-05-22|TAKE BACK RETURN|SHIP|nto beans +611|80676|677|2|1|1656.67|0.08|0.07|R|F|1993-05-17|1993-02-26|1993-06-15|DELIVER IN PERSON|MAIL|ts. pending platelets aff +611|119545|2057|3|39|61017.06|0.09|0.02|A|F|1993-03-10|1993-03-10|1993-03-17|TAKE BACK RETURN|TRUCK|the evenly bold requests. furious +612|184959|9996|1|5|10219.75|0.07|0.00|R|F|1992-11-08|1992-11-20|1992-12-03|TAKE BACK RETURN|RAIL|structions. q +612|194864|7384|2|28|54848.08|0.07|0.06|R|F|1993-01-02|1992-12-11|1993-01-30|DELIVER IN PERSON|TRUCK|regular instructions affix bl +612|66130|1143|3|49|53710.37|0.00|0.08|A|F|1993-01-08|1992-11-25|1993-01-17|TAKE BACK RETURN|REG AIR|theodolite +612|38942|1446|4|28|52666.32|0.05|0.00|A|F|1992-11-12|1992-12-05|1992-12-02|TAKE BACK RETURN|REG AIR|lyly regular asym +612|87737|246|5|1|1724.73|0.08|0.04|R|F|1992-12-18|1992-12-13|1992-12-20|TAKE BACK RETURN|FOB| requests. +612|188203|5758|6|33|42609.60|0.10|0.03|R|F|1992-11-30|1992-12-01|1992-12-12|COLLECT COD|MAIL|bove the blithely even ideas. careful +613|90027|7555|1|17|17289.34|0.06|0.06|N|O|1995-09-23|1995-08-04|1995-10-15|NONE|SHIP|ar dependencie +613|78348|5870|2|6|7958.04|0.05|0.05|N|O|1995-08-05|1995-08-09|1995-08-08|TAKE BACK RETURN|MAIL|y ironic deposits eat +613|185016|7535|3|3|3303.03|0.03|0.01|N|O|1995-09-27|1995-09-11|1995-10-05|NONE|TRUCK|ccounts cajole. +613|158304|8305|4|7|9536.10|0.02|0.04|N|O|1995-09-07|1995-08-02|1995-09-16|DELIVER IN PERSON|MAIL|ously blithely final pinto beans. regula +614|194109|9148|1|21|25265.10|0.00|0.03|R|F|1993-03-29|1993-01-06|1993-04-16|TAKE BACK RETURN|TRUCK|arefully. slyly express packag +614|186897|9416|2|48|95226.72|0.07|0.07|A|F|1993-03-09|1993-01-19|1993-03-19|DELIVER IN PERSON|SHIP|riously special excuses haggle along the +614|166963|4512|3|43|87288.28|0.05|0.00|A|F|1993-03-07|1993-02-22|1993-03-18|DELIVER IN PERSON|SHIP| express accounts wake. slyly ironic ins +614|146951|4494|4|14|27971.30|0.04|0.06|A|F|1992-12-03|1993-02-14|1992-12-27|DELIVER IN PERSON|SHIP|ular packages haggle about the pack +614|195308|7828|5|30|42099.00|0.08|0.07|R|F|1993-01-16|1993-02-08|1993-02-12|TAKE BACK RETURN|FOB|tructions are f +614|136241|1268|6|48|61307.52|0.04|0.08|A|F|1992-12-14|1993-01-22|1993-01-11|NONE|TRUCK| regular platelets cajole quickly eve +615|104545|4546|1|36|55783.44|0.10|0.01|A|F|1992-06-01|1992-07-14|1992-06-27|NONE|FOB| packages. carefully final pinto bea +640|92997|525|1|49|97509.51|0.09|0.02|R|F|1993-03-27|1993-04-17|1993-04-15|NONE|RAIL|s haggle slyly +640|416|2917|2|40|52656.40|0.09|0.05|A|F|1993-05-11|1993-04-11|1993-05-15|COLLECT COD|TRUCK|oach according to the bol +640|179475|7027|3|22|34198.34|0.05|0.07|A|F|1993-05-07|1993-04-14|1993-05-21|TAKE BACK RETURN|TRUCK|osits across the slyly regular theodo +640|31474|1475|4|45|63246.15|0.07|0.07|R|F|1993-04-15|1993-04-23|1993-04-21|DELIVER IN PERSON|REG AIR|ong the qui +641|125192|2729|1|18|21909.42|0.01|0.08|R|F|1993-10-17|1993-10-11|1993-10-29|DELIVER IN PERSON|AIR|p blithely bold packages. quick +641|99477|1987|2|1|1476.47|0.09|0.02|R|F|1993-12-03|1993-10-28|1993-12-26|TAKE BACK RETURN|RAIL| nag across the regular foxes. +641|94311|6821|3|40|52212.40|0.05|0.06|R|F|1993-11-22|1993-10-20|1993-12-11|DELIVER IN PERSON|REG AIR|lets. furiously regular requests cajo +641|70043|5058|4|25|25326.00|0.03|0.02|A|F|1993-12-04|1993-11-18|1993-12-18|TAKE BACK RETURN|FOB|d, regular d +641|3794|8795|5|41|69609.39|0.07|0.04|R|F|1993-11-29|1993-10-27|1993-12-04|TAKE BACK RETURN|FOB| asymptotes are quickly. bol +642|53624|3625|1|26|41018.12|0.10|0.03|A|F|1994-04-16|1994-02-01|1994-04-27|COLLECT COD|REG AIR|quests according to the unu +643|12260|9764|1|28|32823.28|0.00|0.08|A|F|1995-04-13|1995-05-12|1995-04-14|TAKE BACK RETURN|TRUCK|ly regular requests nag sly +643|50168|169|2|48|53671.68|0.01|0.02|N|O|1995-07-10|1995-06-07|1995-08-01|NONE|FOB|ly ironic accounts +643|162447|4964|3|23|34717.12|0.05|0.03|N|O|1995-07-09|1995-05-18|1995-07-31|COLLECT COD|RAIL|sits are carefully according to the e +643|44743|2256|4|39|65821.86|0.08|0.04|A|F|1995-06-08|1995-06-16|1995-06-13|COLLECT COD|RAIL| the pains. carefully s +643|189459|4496|5|47|72777.15|0.10|0.03|R|F|1995-04-05|1995-06-14|1995-04-26|DELIVER IN PERSON|RAIL|y against +644|133143|5657|1|46|54102.44|0.02|0.01|A|F|1992-05-20|1992-06-14|1992-06-14|DELIVER IN PERSON|RAIL| special requests was sometimes expre +644|129821|7358|2|11|20359.02|0.05|0.02|A|F|1992-08-20|1992-07-21|1992-09-11|TAKE BACK RETURN|TRUCK|ealthy pinto beans use carefu +644|100047|5068|3|44|46069.76|0.04|0.04|R|F|1992-08-17|1992-07-26|1992-08-20|COLLECT COD|REG AIR|iously ironic pinto beans. bold packa +644|79744|7266|4|7|12066.18|0.01|0.02|A|F|1992-05-18|1992-07-01|1992-06-07|COLLECT COD|RAIL| regular requests are blithely. slyly +644|49295|9296|5|23|28618.67|0.02|0.04|R|F|1992-07-31|1992-07-28|1992-08-13|DELIVER IN PERSON|TRUCK|uctions nag quickly alongside of t +644|84932|2457|6|33|63258.69|0.00|0.07|R|F|1992-08-26|1992-07-27|1992-08-28|NONE|AIR|ages sleep. bold, bo +644|50239|2745|7|38|45190.74|0.08|0.06|R|F|1992-05-17|1992-07-10|1992-06-06|TAKE BACK RETURN|MAIL| packages. blithely slow accounts nag quic +645|159694|2210|1|33|57871.77|0.01|0.02|A|F|1994-12-09|1995-02-21|1995-01-03|NONE|TRUCK|heodolites b +645|169422|9423|2|47|70096.74|0.07|0.05|R|F|1995-02-16|1995-02-15|1995-02-25|COLLECT COD|TRUCK|hely regular instructions alon +645|69227|4240|3|46|55026.12|0.10|0.01|A|F|1995-01-04|1995-02-21|1995-01-21|COLLECT COD|REG AIR| regular dependencies across the speci +645|95402|421|4|49|68472.60|0.05|0.03|R|F|1995-01-24|1995-01-06|1995-02-17|NONE|TRUCK|y. slyly iron +645|4703|7204|5|43|69131.10|0.06|0.02|A|F|1995-02-12|1995-02-27|1995-03-06|TAKE BACK RETURN|REG AIR| furiously accounts. slyly +645|33631|8638|6|18|28163.34|0.10|0.08|A|F|1995-03-02|1995-02-08|1995-03-03|COLLECT COD|RAIL|ep. slyly even +645|27031|7032|7|9|8622.27|0.03|0.03|A|F|1994-12-25|1995-01-04|1995-01-15|COLLECT COD|REG AIR|special deposits. regular, final th +646|108975|6506|1|31|61503.07|0.00|0.05|R|F|1994-12-17|1995-02-16|1995-01-04|COLLECT COD|MAIL|ag furiousl +646|126723|6724|2|1|1749.72|0.07|0.01|A|F|1994-12-05|1995-01-07|1994-12-31|TAKE BACK RETURN|MAIL|t blithely regular deposits. quic +646|29744|4749|3|24|40169.76|0.06|0.02|A|F|1995-02-20|1994-12-30|1995-03-16|TAKE BACK RETURN|TRUCK|regular accounts haggle dog +646|98738|3757|4|34|59048.82|0.01|0.00|R|F|1994-12-28|1994-12-27|1994-12-31|COLLECT COD|SHIP|slow accounts. fluffily idle instructions +646|89173|4190|5|17|19756.89|0.04|0.01|A|F|1994-12-31|1994-12-26|1995-01-01|DELIVER IN PERSON|REG AIR|inal packages haggle carefully +646|114481|9504|6|40|59819.20|0.10|0.01|R|F|1995-01-01|1995-01-13|1995-01-11|COLLECT COD|TRUCK|ronic packages sleep across th +647|16310|8812|1|41|50278.71|0.08|0.08|N|O|1997-11-19|1997-09-24|1997-12-15|COLLECT COD|REG AIR|r instructions. quickly unusu +647|112177|7200|2|5|5945.85|0.10|0.00|N|O|1997-09-25|1997-09-22|1997-10-25|TAKE BACK RETURN|AIR|ly express packages haggle caref +647|152882|7913|3|15|29023.20|0.08|0.00|N|O|1997-09-23|1997-10-09|1997-10-21|NONE|MAIL|ve the even, bold foxes sleep +672|172190|2191|1|41|51749.79|0.06|0.06|R|F|1994-06-20|1994-07-03|1994-06-22|COLLECT COD|REG AIR| dependencies in +672|189656|9657|2|9|15710.85|0.03|0.04|R|F|1994-06-25|1994-06-06|1994-07-19|TAKE BACK RETURN|TRUCK|haggle carefully carefully reg +672|142390|9933|3|35|50133.65|0.02|0.01|R|F|1994-07-13|1994-06-04|1994-07-14|COLLECT COD|RAIL| dependencies haggle quickly. theo +673|70495|5510|1|22|32240.78|0.03|0.02|R|F|1994-03-15|1994-04-27|1994-03-29|TAKE BACK RETURN|TRUCK| the regular, even requests. carefully fin +674|101366|3877|1|23|31449.28|0.06|0.07|A|F|1992-10-25|1992-10-15|1992-11-03|COLLECT COD|SHIP|ve the quickly even deposits. blithe +674|58285|3296|2|4|4973.12|0.02|0.07|R|F|1992-10-05|1992-11-22|1992-10-22|NONE|RAIL|ly express pinto beans sleep car +675|156455|4001|1|1|1511.45|0.04|0.08|N|O|1997-11-27|1997-09-30|1997-12-12|DELIVER IN PERSON|REG AIR|ide of the slyly regular packages. unus +675|136633|4173|2|35|58437.05|0.08|0.07|N|O|1997-08-19|1997-10-16|1997-09-17|DELIVER IN PERSON|REG AIR|s. furiously expre +675|175802|8320|3|34|63845.20|0.10|0.04|N|O|1997-11-17|1997-10-07|1997-11-27|NONE|FOB|y final accounts unwind around the +675|99269|6797|4|15|19023.90|0.09|0.05|N|O|1997-10-18|1997-09-28|1997-11-13|COLLECT COD|TRUCK|posits after the furio +675|4669|7170|5|46|72388.36|0.09|0.05|N|O|1997-09-18|1997-10-14|1997-10-01|DELIVER IN PERSON|AIR| deposits along the express foxes +676|50972|8488|1|9|17306.73|0.09|0.02|N|O|1997-04-03|1997-02-02|1997-04-08|COLLECT COD|REG AIR|aintain sl +676|77668|5190|2|20|32913.20|0.07|0.07|N|O|1997-02-02|1997-02-01|1997-02-11|NONE|REG AIR|riously around the blithely +676|162330|2331|3|35|48731.55|0.05|0.01|N|O|1996-12-30|1997-01-13|1997-01-19|DELIVER IN PERSON|RAIL|into beans. blithe +676|72825|347|4|24|43147.68|0.01|0.06|N|O|1997-02-05|1997-01-16|1997-03-07|TAKE BACK RETURN|TRUCK|ress, regular dep +676|165127|2676|5|31|36955.72|0.01|0.06|N|O|1997-02-06|1997-02-28|1997-03-08|COLLECT COD|TRUCK|ial deposits cajo +676|75930|5931|6|33|62895.69|0.09|0.05|N|O|1997-03-02|1997-02-22|1997-03-19|TAKE BACK RETURN|TRUCK|as wake slyly furiously close pinto b +676|142123|7152|7|11|12816.32|0.07|0.02|N|O|1997-03-09|1997-03-06|1997-03-31|TAKE BACK RETURN|MAIL|he final acco +677|58986|1492|1|32|62239.36|0.04|0.08|R|F|1994-01-06|1994-01-31|1994-02-02|NONE|RAIL|slyly final +677|167361|7362|2|39|55706.04|0.00|0.07|R|F|1993-12-19|1994-02-11|1994-01-05|TAKE BACK RETURN|SHIP|ges. furiously regular packages use +677|23226|3227|3|46|52864.12|0.01|0.02|R|F|1993-12-02|1994-02-12|1993-12-06|COLLECT COD|RAIL|ng theodolites. furiously unusual theodo +677|147638|5181|4|1|1685.63|0.06|0.05|R|F|1993-12-01|1994-01-14|1993-12-26|DELIVER IN PERSON|MAIL|ly. regular +677|149613|7156|5|25|41565.25|0.00|0.05|A|F|1994-03-12|1994-02-02|1994-03-28|DELIVER IN PERSON|AIR| packages integrate blithely +678|145537|5538|1|20|31650.60|0.05|0.08|R|F|1993-06-21|1993-04-07|1993-07-10|TAKE BACK RETURN|MAIL|furiously express excuses. foxes eat fu +678|36553|4063|2|22|32770.10|0.01|0.02|A|F|1993-05-10|1993-04-29|1993-06-08|NONE|REG AIR|de of the carefully even requests. bl +678|142489|5004|3|16|24503.68|0.06|0.02|R|F|1993-03-20|1993-04-13|1993-04-16|DELIVER IN PERSON|REG AIR|equests cajole around the carefully regular +678|198067|8068|4|48|55922.88|0.08|0.08|R|F|1993-02-28|1993-04-04|1993-03-24|NONE|REG AIR|ithely. slyly express foxes +678|97451|7452|5|16|23175.20|0.06|0.04|R|F|1993-03-09|1993-04-18|1993-04-07|NONE|AIR| about the +678|42888|2889|6|11|20139.68|0.09|0.00|R|F|1993-04-28|1993-05-16|1993-05-11|COLLECT COD|TRUCK|ess deposits dazzle f +679|191759|1760|1|9|16656.75|0.09|0.00|N|O|1995-12-20|1996-01-27|1996-01-07|COLLECT COD|REG AIR|leep slyly. entici +704|189981|9982|1|40|82839.20|0.05|0.05|N|O|1997-01-30|1997-01-10|1997-02-20|COLLECT COD|AIR|ggle quickly. r +704|3839|3840|2|14|24399.62|0.07|0.08|N|O|1997-02-02|1996-12-26|1997-02-19|DELIVER IN PERSON|REG AIR|ve the quickly final forges. furiously p +705|188322|841|1|46|64874.72|0.05|0.06|N|O|1997-04-18|1997-05-06|1997-05-05|DELIVER IN PERSON|SHIP|ss deposits. ironic packa +705|116218|3752|2|35|43197.35|0.10|0.04|N|O|1997-03-25|1997-03-20|1997-04-23|TAKE BACK RETURN|FOB|carefully ironic accounts +706|196629|9149|1|23|39689.26|0.05|0.00|N|O|1995-12-06|1995-12-02|1995-12-16|COLLECT COD|SHIP|ckey players. requests above the +707|154736|4737|1|34|60884.82|0.01|0.02|R|F|1994-12-08|1995-01-15|1995-01-02|NONE|RAIL| dependencies +707|42642|5147|2|22|34862.08|0.00|0.06|A|F|1995-01-12|1994-12-28|1995-01-16|DELIVER IN PERSON|REG AIR| kindle ironically +708|123805|1342|1|3|5486.40|0.05|0.02|N|O|1998-10-09|1998-09-22|1998-11-07|COLLECT COD|FOB|e slyly pending foxes. +708|179124|9125|2|19|22859.28|0.06|0.00|N|O|1998-10-28|1998-09-23|1998-11-25|COLLECT COD|SHIP| requests. even, thin ideas +708|121298|8835|3|33|43536.57|0.09|0.06|N|O|1998-09-10|1998-09-20|1998-09-22|COLLECT COD|RAIL|s boost carefully ruthless theodolites. f +708|55176|5177|4|5|5655.85|0.07|0.07|N|O|1998-07-22|1998-08-15|1998-07-28|TAKE BACK RETURN|REG AIR|c pinto beans nag after the account +708|142490|33|5|36|55169.64|0.08|0.01|N|O|1998-07-16|1998-09-04|1998-08-11|NONE|SHIP|ests. even, regular hockey p +708|22352|9859|6|7|8920.45|0.10|0.03|N|O|1998-08-16|1998-08-15|1998-09-10|COLLECT COD|REG AIR|lly express ac +709|86203|1220|1|7|8324.40|0.00|0.00|N|O|1998-06-14|1998-06-08|1998-06-18|TAKE BACK RETURN|RAIL| special orbits cajole +709|197250|9770|2|15|20208.75|0.08|0.00|N|O|1998-07-10|1998-06-26|1998-08-09|NONE|RAIL|ily regular deposits. sauternes was accor +709|168496|1013|3|10|15644.90|0.01|0.02|N|O|1998-06-04|1998-06-30|1998-06-11|NONE|REG AIR|ts cajole boldly +709|107229|7230|4|40|49448.80|0.10|0.08|N|O|1998-08-12|1998-06-20|1998-08-20|DELIVER IN PERSON|RAIL|ggle fluffily carefully ironic +710|162111|9660|1|47|55136.17|0.06|0.08|A|F|1993-01-18|1993-03-24|1993-01-24|TAKE BACK RETURN|MAIL|usual ideas into th +710|192916|2917|2|38|76338.58|0.07|0.02|R|F|1993-04-18|1993-03-12|1993-05-15|COLLECT COD|FOB|sts boost fluffily aft +710|138984|6524|3|7|14160.86|0.04|0.06|R|F|1993-01-20|1993-03-28|1993-02-15|TAKE BACK RETURN|REG AIR|xpress, special ideas. bl +710|89308|9309|4|25|32432.50|0.00|0.05|R|F|1993-03-31|1993-02-05|1993-04-22|COLLECT COD|FOB|eas detect do +710|185454|491|5|12|18473.40|0.01|0.02|A|F|1993-02-18|1993-02-27|1993-03-07|DELIVER IN PERSON|MAIL|ions. slyly express theodolites al +710|113665|1199|6|21|35251.86|0.04|0.06|R|F|1993-03-22|1993-03-05|1993-03-27|DELIVER IN PERSON|SHIP|es. furiously p +710|159288|6834|7|46|61974.88|0.03|0.07|R|F|1993-04-16|1993-03-27|1993-05-05|COLLECT COD|MAIL|ges use; blithely pending excuses inte +711|145767|8282|1|2|3625.52|0.10|0.04|R|F|1993-12-01|1993-12-09|1993-12-16|DELIVER IN PERSON|REG AIR|ely across t +711|102501|7522|2|27|40594.50|0.00|0.08|A|F|1993-10-02|1993-10-26|1993-10-08|DELIVER IN PERSON|MAIL|slyly. ironic asy +711|127086|2111|3|46|51201.68|0.10|0.00|R|F|1993-12-26|1993-11-19|1994-01-21|TAKE BACK RETURN|MAIL|deposits. permanen +711|127682|7683|4|20|34193.60|0.09|0.00|A|F|1994-01-17|1993-11-10|1994-01-31|DELIVER IN PERSON|TRUCK|kly regular acco +736|157380|7381|1|46|66119.48|0.05|0.01|N|O|1998-07-16|1998-09-01|1998-08-09|NONE|AIR|uctions cajole +736|79423|9424|2|23|32255.66|0.02|0.05|N|O|1998-10-08|1998-08-27|1998-10-19|TAKE BACK RETURN|AIR|k accounts are carefully +736|56626|4142|3|13|20574.06|0.00|0.03|N|O|1998-08-16|1998-07-26|1998-08-19|DELIVER IN PERSON|FOB|st furiously among the +736|97851|5379|4|14|25883.90|0.06|0.04|N|O|1998-10-04|1998-08-14|1998-10-16|COLLECT COD|REG AIR|nstructions. +736|168002|3035|5|32|34240.00|0.04|0.03|N|O|1998-07-30|1998-08-22|1998-08-12|DELIVER IN PERSON|RAIL|iously final accoun +737|181815|9370|1|12|22761.72|0.01|0.01|R|F|1992-04-28|1992-06-30|1992-05-08|COLLECT COD|RAIL|posits after the slyly bold du +738|197203|2242|1|34|44206.80|0.00|0.06|R|F|1993-06-09|1993-04-15|1993-07-09|TAKE BACK RETURN|TRUCK|s against the ironic exc +738|187016|7017|2|4|4412.04|0.00|0.03|A|F|1993-06-20|1993-04-08|1993-07-09|NONE|AIR|ar packages. fluffily bo +738|169700|9701|3|23|40703.10|0.04|0.08|A|F|1993-03-17|1993-04-02|1993-04-05|TAKE BACK RETURN|SHIP|nic, final excuses promise quickly regula +738|140786|8329|4|12|21921.36|0.04|0.08|A|F|1993-06-16|1993-05-05|1993-06-22|NONE|SHIP|ove the slyly regular p +738|174837|9872|5|30|57354.90|0.02|0.00|A|F|1993-06-12|1993-05-29|1993-06-25|NONE|AIR|ecial instructions haggle blithely regula +739|84489|6998|1|28|41257.44|0.00|0.03|N|O|1998-06-03|1998-08-04|1998-06-29|TAKE BACK RETURN|RAIL|elets about the pe +739|3502|6003|2|50|70275.00|0.07|0.06|N|O|1998-08-26|1998-07-16|1998-09-02|COLLECT COD|MAIL|ndencies. blith +739|48733|3742|3|12|20180.76|0.05|0.00|N|O|1998-08-20|1998-07-24|1998-08-22|NONE|MAIL|le slyly along the close i +739|43470|983|4|47|66433.09|0.09|0.07|N|O|1998-08-12|1998-07-09|1998-08-28|NONE|REG AIR|deas according to the theodolites sn +739|187523|5078|5|30|48315.60|0.07|0.06|N|O|1998-06-19|1998-08-26|1998-07-02|DELIVER IN PERSON|REG AIR|above the even deposits. ironic requests +740|1206|8707|1|22|24358.40|0.10|0.02|N|O|1995-07-24|1995-09-11|1995-08-11|TAKE BACK RETURN|FOB|odolites cajole ironic, pending instruc +740|65211|2730|2|35|41167.35|0.00|0.00|N|O|1995-09-06|1995-08-22|1995-10-02|NONE|TRUCK|p quickly. fu +740|198037|8038|3|29|32915.87|0.06|0.05|N|O|1995-10-26|1995-09-17|1995-10-29|DELIVER IN PERSON|FOB|ntly bold pinto beans sleep quickl +741|186404|1441|1|25|37260.00|0.03|0.06|N|O|1998-07-15|1998-08-27|1998-08-12|DELIVER IN PERSON|MAIL|accounts. blithely bold pa +741|90396|5415|2|22|30500.58|0.09|0.01|N|O|1998-09-07|1998-09-28|1998-09-12|COLLECT COD|AIR|ven deposits about the regular, ironi +742|101309|1310|1|46|60273.80|0.04|0.08|A|F|1995-03-12|1995-03-20|1995-03-16|TAKE BACK RETURN|SHIP|e slyly bold deposits cajole according to +742|95395|7905|2|15|20855.85|0.08|0.05|A|F|1995-02-26|1995-03-20|1995-03-03|NONE|SHIP|blithely unusual pinto +742|101553|4064|3|24|37309.20|0.08|0.08|A|F|1995-02-12|1995-03-12|1995-02-14|DELIVER IN PERSON|SHIP|affix slyly. furiously i +742|191891|4411|4|16|31726.24|0.01|0.05|A|F|1995-01-15|1995-02-25|1995-01-24|COLLECT COD|AIR|eodolites haggle carefully regul +742|100006|2517|5|48|48288.00|0.09|0.08|R|F|1995-03-24|1995-01-23|1995-04-08|TAKE BACK RETURN|TRUCK| platelets +742|191966|9524|6|49|100840.04|0.02|0.07|A|F|1995-01-13|1995-02-13|1995-01-26|TAKE BACK RETURN|RAIL| carefully bold foxes sle +743|191460|6499|1|21|32580.66|0.01|0.04|N|O|1996-10-26|1996-11-05|1996-11-11|COLLECT COD|MAIL|d requests. packages afte +768|195813|5814|1|39|74443.59|0.06|0.08|N|O|1996-09-25|1996-10-27|1996-10-20|NONE|SHIP|out the ironic +768|17862|7863|2|2|3559.72|0.00|0.04|N|O|1996-11-13|1996-10-03|1996-11-25|DELIVER IN PERSON|SHIP|ular courts. slyly dogged accou +768|5964|965|3|30|56098.80|0.06|0.05|N|O|1996-09-22|1996-11-03|1996-10-13|NONE|MAIL| furiously fluffy pinto beans haggle along +768|24493|2000|4|37|52447.13|0.10|0.00|N|O|1996-10-02|1996-09-23|1996-10-14|TAKE BACK RETURN|REG AIR|ending requests across the quickly +768|46500|1509|5|47|67985.50|0.06|0.05|N|O|1996-11-28|1996-10-30|1996-12-12|NONE|TRUCK|foxes. slyly ironic deposits a +768|111635|6658|6|43|70805.09|0.10|0.06|N|O|1996-09-22|1996-11-03|1996-10-22|TAKE BACK RETURN|AIR|sual ideas wake quickly +768|48062|8063|7|33|33331.98|0.01|0.04|N|O|1996-09-06|1996-09-29|1996-10-01|COLLECT COD|RAIL|sly ironic instructions. excuses can hagg +769|175068|7586|1|36|41150.16|0.02|0.02|A|F|1993-10-01|1993-08-07|1993-10-15|NONE|AIR|es. furiously iro +769|159077|1593|2|4|4544.28|0.01|0.04|R|F|1993-06-25|1993-08-12|1993-07-15|DELIVER IN PERSON|FOB| ideas. even +770|180119|2638|1|39|46765.29|0.09|0.06|N|O|1998-07-19|1998-08-09|1998-08-04|NONE|REG AIR|osits. foxes cajole +770|53281|5787|2|25|30857.00|0.03|0.02|N|O|1998-05-26|1998-07-23|1998-06-04|TAKE BACK RETURN|AIR| deposits dazzle fluffily alongside of +771|6983|4484|1|12|22679.76|0.10|0.08|N|O|1995-07-18|1995-08-02|1995-08-07|COLLECT COD|TRUCK|carefully. pending in +771|160505|3022|2|38|59489.00|0.03|0.08|N|O|1995-07-22|1995-09-10|1995-07-29|TAKE BACK RETURN|REG AIR| quickly final requests are final packages. +771|6393|6394|3|14|18191.46|0.02|0.05|N|O|1995-07-31|1995-08-13|1995-08-07|DELIVER IN PERSON|AIR|r, final packages are slyly iro +771|41262|1263|4|7|8422.82|0.06|0.02|N|O|1995-06-18|1995-08-31|1995-06-20|NONE|REG AIR|theodolites after the fluffily express +771|77402|4924|5|13|17932.20|0.09|0.01|N|O|1995-08-10|1995-08-21|1995-08-30|NONE|FOB|packages affix slyly about the quickly +771|81921|9446|6|23|43767.16|0.08|0.03|N|O|1995-06-19|1995-09-07|1995-07-09|COLLECT COD|FOB|cajole besides the quickly ironic pin +772|52698|214|1|35|57774.15|0.10|0.06|R|F|1993-07-05|1993-06-05|1993-08-02|NONE|SHIP|kly thin packages wake slowly +772|83007|8024|2|10|9900.00|0.05|0.01|R|F|1993-05-20|1993-05-19|1993-06-15|DELIVER IN PERSON|MAIL| deposits cajole carefully instructions. t +772|85119|5120|3|35|38643.85|0.03|0.04|R|F|1993-04-18|1993-06-13|1993-05-01|COLLECT COD|MAIL|ng ideas. special packages haggle alon +772|179834|7386|4|10|19138.30|0.08|0.02|A|F|1993-05-17|1993-06-09|1993-05-29|COLLECT COD|AIR|o the furiously final deposits. furi +772|53649|3650|5|42|67310.88|0.02|0.07|A|F|1993-06-09|1993-07-16|1993-06-12|DELIVER IN PERSON|MAIL| express foxes abo +773|99317|9318|1|5|6581.55|0.06|0.04|A|F|1993-11-21|1993-12-19|1993-12-21|COLLECT COD|MAIL|ar requests. regular, thin packages u +773|10005|2507|2|31|28365.00|0.02|0.06|A|F|1993-12-30|1993-11-02|1994-01-01|TAKE BACK RETURN|MAIL|e slyly unusual deposit +773|150082|7628|3|39|44151.12|0.06|0.05|A|F|1994-01-04|1993-12-23|1994-01-26|DELIVER IN PERSON|FOB|quickly eve +773|28056|3061|4|28|27553.40|0.10|0.06|R|F|1994-01-19|1993-11-05|1994-01-23|NONE|TRUCK|he furiously slow deposits. +773|133007|3008|5|9|9360.00|0.09|0.02|R|F|1993-10-09|1993-12-25|1993-11-04|TAKE BACK RETURN|FOB|ent orbits haggle fluffily after the +773|39505|9506|6|43|62113.50|0.07|0.03|A|F|1993-11-06|1993-11-20|1993-11-08|TAKE BACK RETURN|SHIP|furiously bold dependencies. blithel +774|182652|2653|1|49|84997.85|0.08|0.03|N|O|1995-12-06|1996-01-07|1995-12-14|DELIVER IN PERSON|SHIP|ess accounts are carefully +774|16038|1041|2|3|2862.09|0.10|0.06|N|O|1996-02-13|1996-01-14|1996-03-04|COLLECT COD|FOB| slyly even courts nag blith +774|147809|5352|3|34|63131.20|0.02|0.07|N|O|1996-03-16|1996-01-03|1996-03-22|COLLECT COD|FOB|lar excuses are furiously final instr +774|14993|4994|4|8|15263.92|0.00|0.02|N|O|1996-01-24|1996-01-15|1996-02-13|COLLECT COD|RAIL|ully ironic requests c +774|176160|3712|5|44|54391.04|0.09|0.07|N|O|1996-02-29|1996-01-16|1996-03-06|NONE|REG AIR|s according to the deposits unwind ca +774|119813|9814|6|2|3665.62|0.07|0.03|N|O|1995-12-11|1996-02-10|1995-12-14|TAKE BACK RETURN|SHIP|accounts; slyly regular +775|31640|6647|1|16|25146.24|0.10|0.06|N|F|1995-05-23|1995-05-07|1995-06-19|NONE|TRUCK|un quickly slyly +775|173244|796|2|21|27662.04|0.01|0.06|R|F|1995-05-01|1995-06-02|1995-05-13|DELIVER IN PERSON|FOB| quickly sile +775|107093|4624|3|20|22001.80|0.01|0.08|N|F|1995-06-17|1995-05-22|1995-07-13|COLLECT COD|AIR|en dependencies nag slowly +800|71833|6848|1|38|68583.54|0.00|0.05|N|O|1998-07-21|1998-09-25|1998-08-07|TAKE BACK RETURN|TRUCK|according to the bold, final dependencies +800|84262|6771|2|21|26171.46|0.04|0.05|N|O|1998-07-23|1998-10-01|1998-08-20|TAKE BACK RETURN|RAIL|ckly even requests after the carefully r +800|175028|63|3|26|28678.52|0.01|0.02|N|O|1998-07-23|1998-10-08|1998-07-25|DELIVER IN PERSON|FOB|bove the pending requests. +801|5111|2612|1|13|13209.43|0.10|0.02|R|F|1992-04-25|1992-04-24|1992-05-16|COLLECT COD|RAIL|s are fluffily stealthily expres +801|94616|9635|2|21|33822.81|0.05|0.02|A|F|1992-03-14|1992-04-01|1992-04-05|COLLECT COD|AIR|wake silently furiously idle deposits. +801|2700|2701|3|21|33656.70|0.05|0.03|A|F|1992-04-25|1992-03-20|1992-05-04|COLLECT COD|REG AIR|cial, special packages. +801|163556|1105|4|12|19434.60|0.08|0.04|A|F|1992-06-06|1992-04-14|1992-06-12|TAKE BACK RETURN|RAIL|s. ironic pinto b +801|73144|666|5|45|50271.30|0.01|0.06|R|F|1992-03-22|1992-03-22|1992-03-25|COLLECT COD|REG AIR| even asymptotes +801|121868|4381|6|10|18898.60|0.08|0.01|A|F|1992-06-05|1992-05-15|1992-06-21|DELIVER IN PERSON|MAIL|al accounts. carefully regular foxes wake +801|25641|646|7|11|17233.04|0.01|0.03|A|F|1992-05-09|1992-04-19|1992-05-15|DELIVER IN PERSON|REG AIR|y special pinto beans cajole +802|142568|7597|1|40|64422.40|0.08|0.08|A|F|1995-01-07|1995-04-03|1995-01-23|DELIVER IN PERSON|RAIL|y bold accou +802|132751|2752|2|34|60647.50|0.08|0.06|A|F|1995-03-01|1995-03-15|1995-03-12|COLLECT COD|AIR|instructions cajole carefully. quietl +802|130920|921|3|44|85840.48|0.07|0.04|R|F|1995-01-09|1995-02-04|1995-01-18|TAKE BACK RETURN|SHIP|rmanently idly special requ +802|156598|1629|4|18|29782.62|0.09|0.02|R|F|1995-03-06|1995-02-07|1995-03-19|TAKE BACK RETURN|RAIL|y regular requests engage furiously final d +802|131708|1709|5|19|33054.30|0.08|0.06|A|F|1995-04-01|1995-02-20|1995-04-23|DELIVER IN PERSON|REG AIR|old, furious +803|53401|8412|1|8|10835.20|0.07|0.01|N|O|1997-08-04|1997-06-19|1997-08-12|NONE|SHIP|ronic theodo +803|98771|8772|2|21|37165.17|0.08|0.06|N|O|1997-08-25|1997-06-30|1997-09-10|TAKE BACK RETURN|AIR|ironic packages cajole slyly. un +804|125293|5294|1|30|39548.70|0.08|0.04|A|F|1993-03-29|1993-05-07|1993-04-14|COLLECT COD|REG AIR|ehind the quietly regular pac +804|198375|5933|2|2|2946.74|0.02|0.00|A|F|1993-06-23|1993-04-30|1993-06-25|NONE|TRUCK|slyly silent +804|75519|534|3|44|65758.44|0.04|0.05|R|F|1993-07-06|1993-04-13|1993-07-28|DELIVER IN PERSON|TRUCK|ly final deposits? special +804|37511|2518|4|21|30418.71|0.01|0.00|A|F|1993-04-12|1993-06-06|1993-04-20|DELIVER IN PERSON|RAIL|ular, ironic foxes. quickly even accounts +805|197826|346|1|25|48095.50|0.07|0.06|N|O|1995-08-05|1995-09-30|1995-08-06|NONE|AIR|ide of the pending, sly requests. quickly f +805|56623|9129|2|29|45808.98|0.07|0.01|N|O|1995-08-24|1995-08-15|1995-09-16|TAKE BACK RETURN|AIR|dolites according to the slyly f +805|46414|6415|3|12|16324.92|0.01|0.06|N|O|1995-07-13|1995-09-27|1995-08-02|TAKE BACK RETURN|REG AIR| regular foxes. furio +805|75351|7859|4|26|34485.10|0.08|0.07|N|O|1995-08-28|1995-09-24|1995-09-11|TAKE BACK RETURN|RAIL|. ironic deposits sleep across +806|104752|2283|1|1|1756.75|0.04|0.07|N|O|1996-07-14|1996-09-12|1996-07-25|COLLECT COD|RAIL|ar accounts? pending, pending foxes a +806|159749|4780|2|22|39792.28|0.08|0.02|N|O|1996-10-03|1996-08-11|1996-10-20|DELIVER IN PERSON|REG AIR|fily pending +806|90335|2845|3|4|5301.32|0.04|0.03|N|O|1996-08-09|1996-09-18|1996-08-13|COLLECT COD|TRUCK|eans. quickly ironic ideas +807|116568|4102|1|49|77643.44|0.00|0.00|R|F|1993-12-05|1994-01-13|1993-12-25|COLLECT COD|REG AIR| furiously according to the un +807|154875|9906|2|49|94563.63|0.01|0.06|A|F|1994-01-17|1994-01-24|1994-01-22|COLLECT COD|TRUCK|y regular requests haggle. +807|180228|7783|3|48|62794.56|0.07|0.07|A|F|1994-01-08|1994-02-02|1994-01-15|DELIVER IN PERSON|SHIP|kly across the f +807|79226|9227|4|10|12052.20|0.09|0.00|R|F|1994-01-19|1994-02-12|1994-01-28|NONE|TRUCK|furiously final depths sleep a +807|142418|7447|5|30|43812.30|0.02|0.01|R|F|1994-01-19|1994-01-09|1994-01-27|NONE|RAIL|cial accoun +807|11627|9131|6|11|16924.82|0.02|0.04|R|F|1994-03-25|1994-01-26|1994-04-14|NONE|FOB|unts above the slyly final ex +807|149|5150|7|19|19933.66|0.08|0.05|A|F|1994-02-10|1994-02-20|1994-03-06|NONE|SHIP|ns haggle quickly across the furi +832|102949|5460|1|45|87837.30|0.01|0.02|A|F|1992-05-08|1992-06-06|1992-06-04|COLLECT COD|MAIL|foxes engage slyly alon +832|47411|2420|2|24|32601.84|0.05|0.06|A|F|1992-06-15|1992-07-14|1992-06-17|NONE|TRUCK|ully. carefully speci +833|53556|3557|1|1|1509.55|0.04|0.04|R|F|1994-04-26|1994-04-05|1994-04-29|COLLECT COD|MAIL|ffily ironic theodolites +833|111833|4345|2|38|70103.54|0.05|0.05|A|F|1994-04-05|1994-04-21|1994-05-01|COLLECT COD|TRUCK| platelets promise furiously. +833|161174|8723|3|9|11116.53|0.05|0.07|A|F|1994-02-28|1994-04-26|1994-03-20|TAKE BACK RETURN|FOB|ecial, even requests. even, bold instructi +834|144119|6634|1|36|41871.96|0.06|0.04|R|F|1994-06-28|1994-07-25|1994-07-07|TAKE BACK RETURN|SHIP|ccounts haggle after the furiously +834|6951|1952|2|11|20437.45|0.03|0.00|A|F|1994-09-18|1994-08-03|1994-10-02|DELIVER IN PERSON|TRUCK|inst the regular packa +835|106431|1452|1|33|47435.19|0.09|0.06|N|O|1995-11-01|1995-12-02|1995-11-24|DELIVER IN PERSON|RAIL|onic instructions among the carefully iro +835|184562|9599|2|28|46103.68|0.02|0.02|N|O|1995-12-27|1995-12-11|1996-01-21|NONE|SHIP| fluffily furious pinto beans +836|187915|5470|1|6|12017.46|0.09|0.03|N|O|1996-12-09|1997-01-31|1996-12-29|COLLECT COD|TRUCK|fully bold theodolites are daringly across +836|83534|1059|2|18|27315.54|0.03|0.05|N|O|1997-02-27|1997-02-11|1997-03-22|NONE|REG AIR|y pending packages use alon +836|140671|3186|3|46|78736.82|0.05|0.07|N|O|1997-03-21|1997-02-06|1997-04-05|NONE|REG AIR|boldly final pinto beans haggle furiously +837|56565|9071|1|39|59340.84|0.03|0.08|A|F|1994-07-22|1994-08-10|1994-08-11|NONE|RAIL|ecial pinto bea +837|87341|4866|2|24|31880.16|0.08|0.00|R|F|1994-06-27|1994-09-02|1994-07-27|DELIVER IN PERSON|FOB|p carefully. theodolites use. bold courts a +838|133708|6222|1|20|34834.00|0.10|0.07|N|O|1998-04-11|1998-03-25|1998-04-19|COLLECT COD|TRUCK| furiously final ideas. slow, bold +838|28244|8245|2|27|31650.48|0.05|0.07|N|O|1998-02-15|1998-04-03|1998-02-20|DELIVER IN PERSON|SHIP| pending pinto beans haggle about t +838|94785|7295|3|23|40934.94|0.10|0.07|N|O|1998-03-26|1998-04-17|1998-04-02|COLLECT COD|AIR|ets haggle furiously furiously regular r +838|43152|3153|4|18|19712.70|0.09|0.00|N|O|1998-03-28|1998-04-06|1998-03-31|TAKE BACK RETURN|AIR|hely unusual foxes. furio +839|157077|4623|1|23|26083.61|0.07|0.02|N|O|1995-10-17|1995-11-03|1995-11-04|COLLECT COD|AIR|ng ideas haggle accord +839|188315|8316|2|47|65955.57|0.08|0.00|N|O|1995-10-17|1995-11-06|1995-11-10|NONE|AIR|refully final excuses about +864|129655|2168|1|34|57278.10|0.03|0.04|N|O|1997-12-16|1997-10-23|1998-01-12|TAKE BACK RETURN|SHIP|gside of the furiously special +864|97941|2960|2|7|13572.58|0.01|0.02|N|O|1997-11-13|1997-10-07|1997-12-13|TAKE BACK RETURN|MAIL|ven requests should sleep along +864|79304|1812|3|34|43632.20|0.03|0.00|N|O|1997-09-14|1997-11-04|1997-09-21|TAKE BACK RETURN|REG AIR|to the furiously ironic platelets! +865|197300|9820|1|16|22356.80|0.07|0.03|R|F|1993-08-24|1993-06-26|1993-08-28|TAKE BACK RETURN|TRUCK|y even accounts. quickly bold decoys +865|19188|4191|2|3|3321.54|0.02|0.05|A|F|1993-07-17|1993-07-14|1993-08-01|NONE|MAIL|fully regular the +865|86034|1051|3|15|15300.45|0.00|0.06|R|F|1993-07-05|1993-06-25|1993-07-26|NONE|SHIP| deposits sleep quickl +865|168398|5947|4|34|49857.26|0.09|0.06|A|F|1993-05-09|1993-07-28|1993-05-18|DELIVER IN PERSON|REG AIR|furiously fluffily unusual account +866|135703|5704|1|5|8693.50|0.08|0.00|R|F|1993-01-22|1993-01-14|1993-02-07|TAKE BACK RETURN|AIR|tegrate fluffily. carefully f +867|138798|8799|1|7|12857.53|0.04|0.07|A|F|1994-02-19|1993-12-25|1994-02-25|DELIVER IN PERSON|TRUCK|pendencies-- slyly unusual packages hagg +868|167908|7909|1|8|15807.20|0.06|0.03|R|F|1992-10-07|1992-08-01|1992-10-16|NONE|MAIL|l deposits. blithely regular pint +868|28659|3664|2|13|20639.45|0.05|0.07|R|F|1992-07-25|1992-08-26|1992-08-04|NONE|AIR|gged instructi +868|67432|2445|3|19|26589.17|0.09|0.06|R|F|1992-06-22|1992-08-27|1992-07-04|COLLECT COD|SHIP|lyly ironic platelets wake. rut +868|121059|6084|4|43|46442.15|0.02|0.04|A|F|1992-07-02|1992-07-22|1992-07-21|COLLECT COD|SHIP|kly silent deposits wake dar +868|24498|2005|5|27|38407.23|0.04|0.01|R|F|1992-08-01|1992-08-25|1992-08-12|TAKE BACK RETURN|RAIL|oss the fluffily unusual pinto +868|124220|4221|6|19|23640.18|0.02|0.05|R|F|1992-09-20|1992-07-18|1992-10-04|NONE|FOB|ely even deposits lose blithe +869|62275|4782|1|27|33406.29|0.07|0.07|N|O|1997-01-30|1997-02-17|1997-02-26|TAKE BACK RETURN|TRUCK|uffily even excuses? slyly even deposits +869|46068|8573|2|36|36506.16|0.04|0.01|N|O|1997-05-03|1997-03-17|1997-05-24|NONE|RAIL|ong the furiously bold instructi +870|49110|6623|1|36|38127.96|0.04|0.07|A|F|1993-10-18|1993-09-16|1993-11-15|COLLECT COD|MAIL|fily. furiously final accounts are +870|185850|5851|2|5|9679.25|0.06|0.05|A|F|1993-08-13|1993-09-11|1993-08-24|COLLECT COD|FOB|e slyly excuses. ironi +871|96392|6393|1|48|66642.72|0.10|0.03|N|O|1996-02-25|1996-02-09|1996-03-18|NONE|AIR|coys dazzle slyly slow notornis. f +871|54591|9602|2|47|72642.73|0.07|0.03|N|O|1995-12-25|1996-02-01|1996-01-24|TAKE BACK RETURN|RAIL|ss, final dep +871|107967|5498|3|13|25674.48|0.09|0.01|N|O|1996-01-25|1996-01-24|1996-02-03|NONE|REG AIR| haggle furiou +871|189917|9918|4|29|58200.39|0.06|0.07|N|O|1995-11-16|1996-01-27|1995-12-16|DELIVER IN PERSON|RAIL|ests are carefu +871|127480|2505|5|8|12059.84|0.00|0.01|N|O|1995-11-25|1996-01-12|1995-12-12|DELIVER IN PERSON|AIR|lar ideas-- slyly even accou +871|142499|42|6|26|40078.74|0.00|0.06|N|O|1996-02-07|1996-01-05|1996-02-25|COLLECT COD|AIR|symptotes use quickly near the +871|173371|8406|7|4|5777.48|0.00|0.07|N|O|1996-03-09|1996-01-20|1996-03-26|COLLECT COD|FOB|l, regular dependencies w +896|38675|8676|1|47|75842.49|0.07|0.08|R|F|1993-05-28|1993-05-15|1993-06-15|DELIVER IN PERSON|TRUCK|ly even pinto beans integrate. b +896|197621|5179|2|10|17186.20|0.03|0.07|A|F|1993-07-07|1993-06-03|1993-07-24|COLLECT COD|SHIP| quickly even theodolites. carefully regu +896|1925|9426|3|7|12788.44|0.09|0.02|A|F|1993-05-02|1993-05-24|1993-05-31|DELIVER IN PERSON|MAIL| requests +896|151663|1664|4|11|18861.26|0.08|0.04|A|F|1993-05-19|1993-05-22|1993-06-08|COLLECT COD|MAIL|the multipliers sleep +896|187481|5036|5|34|53328.32|0.00|0.05|R|F|1993-05-21|1993-06-01|1993-05-23|NONE|TRUCK|ular, close requests cajo +896|176862|1897|6|44|85309.84|0.09|0.08|R|F|1993-05-19|1993-04-14|1993-06-02|DELIVER IN PERSON|FOB|lar, pending packages. deposits are q +896|108889|1400|7|11|20876.68|0.01|0.07|A|F|1993-05-01|1993-04-09|1993-05-06|TAKE BACK RETURN|FOB|rding to the pinto beans wa +897|90450|5469|1|15|21606.75|0.07|0.04|R|F|1995-05-25|1995-05-09|1995-06-07|COLLECT COD|REG AIR|r ideas. slyly spec +897|183170|725|2|26|32582.42|0.05|0.08|N|O|1995-07-01|1995-06-10|1995-07-14|COLLECT COD|MAIL|tions sleep according to the special +897|125704|8217|3|13|22486.10|0.07|0.00|A|F|1995-03-30|1995-05-17|1995-04-21|TAKE BACK RETURN|MAIL|bold accounts mold carefully! braids +897|101182|6203|4|2|2366.36|0.08|0.08|R|F|1995-05-22|1995-05-07|1995-06-16|COLLECT COD|RAIL|into beans. slyly special fox +898|160159|160|1|9|10972.35|0.07|0.08|A|F|1993-07-04|1993-07-09|1993-07-25|NONE|AIR|e slyly across the blithe +898|178512|6064|2|37|58848.87|0.03|0.05|A|F|1993-08-17|1993-08-04|1993-09-01|DELIVER IN PERSON|REG AIR|packages sleep furiously +898|48242|5755|3|11|13092.64|0.01|0.00|A|F|1993-09-13|1993-08-31|1993-09-25|TAKE BACK RETURN|MAIL|etly bold accounts +898|192166|7205|4|36|45293.76|0.04|0.07|R|F|1993-08-04|1993-07-25|1993-08-23|DELIVER IN PERSON|REG AIR| after the carefully +899|60085|2592|1|18|18811.44|0.04|0.05|N|O|1998-08-06|1998-05-09|1998-09-05|DELIVER IN PERSON|AIR|re daring, pending deposits. blit +899|46070|8575|2|25|25401.75|0.00|0.07|N|O|1998-07-21|1998-05-12|1998-08-16|NONE|REG AIR|rly final sentiments. bold pinto beans +899|84976|2501|3|4|7843.88|0.09|0.05|N|O|1998-06-02|1998-06-28|1998-06-14|TAKE BACK RETURN|REG AIR|ter the carefully regular deposits are agai +899|179704|4739|4|14|24971.80|0.05|0.03|N|O|1998-05-21|1998-05-28|1998-06-03|TAKE BACK RETURN|FOB|ades impress carefully +899|70776|5791|5|4|6987.08|0.06|0.02|N|O|1998-04-11|1998-05-14|1998-04-27|NONE|TRUCK|ges. blithe, ironic waters cajole care +899|119083|1595|6|47|51797.76|0.00|0.04|N|O|1998-04-14|1998-05-30|1998-05-13|DELIVER IN PERSON|TRUCK|furiously final foxes after the s +899|13423|8426|7|11|14700.62|0.02|0.08|N|O|1998-06-03|1998-06-15|1998-06-20|COLLECT COD|REG AIR|t the ironic +900|198532|1052|1|44|71743.32|0.01|0.06|R|F|1994-12-15|1994-12-03|1994-12-27|COLLECT COD|MAIL| detect quick +900|114624|4625|2|48|78653.76|0.08|0.04|A|F|1994-12-22|1994-11-08|1995-01-19|COLLECT COD|TRUCK|cial pinto beans nag +900|74130|4131|3|24|26499.12|0.03|0.00|R|F|1994-10-21|1994-12-25|1994-10-22|TAKE BACK RETURN|SHIP|-ray furiously un +901|21113|3616|1|36|37227.96|0.01|0.01|N|O|1998-08-11|1998-10-09|1998-08-27|DELIVER IN PERSON|REG AIR|. accounts are care +901|45222|5223|2|2|2334.44|0.09|0.02|N|O|1998-10-25|1998-09-27|1998-11-01|DELIVER IN PERSON|AIR|d foxes use slyly +901|42615|5120|3|37|57631.57|0.04|0.08|N|O|1998-11-01|1998-09-13|1998-11-05|NONE|AIR|ickly final deposits +901|17758|7759|4|11|18433.25|0.00|0.06|N|O|1998-11-13|1998-10-19|1998-11-14|TAKE BACK RETURN|TRUCK|ourts among the quickly expre +902|110509|510|1|3|4558.50|0.06|0.00|R|F|1994-10-01|1994-10-25|1994-10-28|COLLECT COD|MAIL|into beans thrash blithely about the flu +902|117211|9723|2|8|9825.68|0.06|0.07|R|F|1994-10-25|1994-09-20|1994-11-07|COLLECT COD|RAIL| orbits al +902|164836|9869|3|24|45619.92|0.02|0.05|R|F|1994-11-08|1994-10-12|1994-11-26|NONE|FOB|. blithely even accounts poach furiously i +903|64367|1886|1|27|35946.72|0.04|0.03|N|O|1995-09-18|1995-09-20|1995-10-02|TAKE BACK RETURN|SHIP|lly pending foxes. furiously +903|8890|1391|2|35|62961.15|0.06|0.05|N|O|1995-09-18|1995-08-21|1995-10-12|TAKE BACK RETURN|TRUCK|rets wake fin +903|8238|739|3|33|37825.59|0.02|0.03|N|O|1995-09-24|1995-09-01|1995-10-12|COLLECT COD|MAIL|ely ironic packages wake blithely +903|55408|419|4|9|12270.60|0.09|0.00|N|O|1995-10-06|1995-09-14|1995-10-24|NONE|TRUCK|he slyly ev +903|41041|1042|5|1|982.04|0.04|0.00|N|O|1995-10-22|1995-09-13|1995-11-03|NONE|AIR|y final platelets sublate among the +903|167067|7068|6|13|14742.78|0.07|0.02|N|O|1995-09-11|1995-10-04|1995-10-03|COLLECT COD|SHIP|sleep along the final +928|168148|8149|1|29|35268.06|0.07|0.02|R|F|1995-05-17|1995-05-12|1995-05-21|NONE|REG AIR|ly alongside of the s +928|47775|5288|2|24|41346.48|0.05|0.08|A|F|1995-04-06|1995-05-08|1995-04-24|DELIVER IN PERSON|AIR|s the furiously regular warthogs im +928|151774|4290|3|46|83985.42|0.08|0.00|A|F|1995-05-09|1995-04-09|1995-06-01|DELIVER IN PERSON|REG AIR| beans sleep against the carefully ir +928|51313|8829|4|43|54365.33|0.10|0.05|A|F|1995-04-14|1995-04-21|1995-05-09|NONE|REG AIR|blithely. express, silent requests doze at +928|11725|1726|5|38|62195.36|0.02|0.08|N|F|1995-06-08|1995-04-15|1995-06-30|TAKE BACK RETURN|SHIP|xpress grouc +928|54038|4039|6|50|49601.50|0.05|0.00|N|F|1995-06-07|1995-04-15|1995-07-01|DELIVER IN PERSON|TRUCK| slyly slyly special request +928|10337|2839|7|11|13720.63|0.00|0.01|A|F|1995-04-29|1995-04-16|1995-04-30|NONE|AIR|longside of +929|128672|3697|1|45|76530.15|0.09|0.01|R|F|1993-01-24|1992-12-06|1993-02-16|DELIVER IN PERSON|REG AIR|ges haggle careful +929|174218|6736|2|44|56857.24|0.02|0.00|A|F|1992-10-09|1992-11-20|1992-10-22|DELIVER IN PERSON|SHIP|s. excuses cajole. carefully regu +929|73036|3037|3|14|14126.42|0.06|0.07|A|F|1992-10-21|1992-11-17|1992-11-15|NONE|FOB|gainst the +929|101639|4150|4|7|11484.41|0.06|0.01|A|F|1992-12-24|1992-12-19|1993-01-08|TAKE BACK RETURN|TRUCK|ithely. slyly c +930|44804|2317|1|36|62956.80|0.10|0.04|R|F|1994-12-21|1995-02-20|1994-12-24|COLLECT COD|RAIL|quickly regular pinto beans sle +930|17295|4799|2|47|56977.63|0.08|0.00|A|F|1995-03-20|1995-02-04|1995-04-04|DELIVER IN PERSON|AIR|ackages. fluffily e +930|64230|1749|3|10|11942.30|0.07|0.08|A|F|1994-12-18|1995-01-27|1995-01-16|COLLECT COD|AIR|ckly regular requests: regular instructions +930|99635|2145|4|21|34327.23|0.06|0.02|A|F|1995-02-16|1995-03-03|1995-03-13|DELIVER IN PERSON|SHIP|foxes. regular deposits integrate carefu +930|163239|788|5|50|65111.50|0.03|0.06|A|F|1995-04-03|1995-01-29|1995-04-22|COLLECT COD|MAIL| excuses among the furiously express ideas +930|144557|2100|6|10|16015.50|0.00|0.04|A|F|1995-02-09|1995-02-17|1995-02-16|NONE|SHIP|blithely bold i +930|166196|1229|7|30|37865.70|0.07|0.08|R|F|1995-01-20|1995-02-28|1995-02-04|TAKE BACK RETURN|RAIL|g accounts sleep along the platelets. +931|39783|9784|1|18|31010.04|0.00|0.05|A|F|1993-04-04|1993-01-11|1993-04-13|NONE|RAIL|slyly ironic re +931|16788|4292|2|10|17047.80|0.05|0.07|A|F|1993-03-01|1993-01-09|1993-03-07|TAKE BACK RETURN|SHIP|ajole quickly. slyly sil +931|146052|3595|3|48|52706.40|0.01|0.08|A|F|1993-02-03|1993-03-02|1993-02-09|TAKE BACK RETURN|FOB|ep alongside of the fluffy +931|81324|6341|4|38|49602.16|0.08|0.08|A|F|1993-03-06|1993-02-24|1993-03-27|DELIVER IN PERSON|RAIL|usly final packages integrate carefully +932|43763|6268|1|41|69977.16|0.01|0.05|N|O|1997-06-05|1997-07-22|1997-06-26|COLLECT COD|RAIL|foxes. ironic pl +933|48267|5780|1|23|27950.98|0.02|0.04|R|F|1992-08-13|1992-09-18|1992-08-25|DELIVER IN PERSON|MAIL| the furiously bold dinos. sly +933|12132|2133|2|27|28191.51|0.02|0.01|R|F|1992-10-03|1992-10-02|1992-10-26|DELIVER IN PERSON|RAIL|ests. express +933|99192|1702|3|26|30970.94|0.05|0.00|A|F|1992-11-09|1992-11-03|1992-11-16|DELIVER IN PERSON|AIR| the deposits affix slyly after t +934|117900|2923|1|18|34522.20|0.07|0.01|N|O|1996-09-10|1996-09-20|1996-09-25|COLLECT COD|RAIL|y unusual requests dazzle above t +935|27410|9913|1|23|30760.43|0.05|0.00|N|O|1997-11-11|1997-11-22|1997-11-29|COLLECT COD|REG AIR|ular accounts about +935|64553|2072|2|23|34903.65|0.02|0.01|N|O|1998-01-11|1997-11-25|1998-02-05|COLLECT COD|TRUCK|hes haggle furiously dolphins. qu +935|134031|6545|3|36|38341.08|0.06|0.00|N|O|1997-11-05|1997-12-05|1997-11-25|TAKE BACK RETURN|AIR|leep about the exp +935|57192|2203|4|13|14939.47|0.08|0.04|N|O|1998-01-13|1997-11-30|1998-02-08|DELIVER IN PERSON|TRUCK|ld platelet +935|12130|4632|5|8|8337.04|0.02|0.05|N|O|1998-01-12|1997-11-02|1998-02-05|NONE|TRUCK|cept the quickly regular p +935|58299|5815|6|1|1257.29|0.01|0.08|N|O|1997-12-14|1997-11-22|1998-01-08|DELIVER IN PERSON|TRUCK| instructions. ironic acc +960|106999|9510|1|1|2005.99|0.07|0.00|A|F|1994-12-24|1994-10-26|1995-01-20|DELIVER IN PERSON|AIR|y ironic packages. quickly even +960|116212|3746|2|25|30705.25|0.06|0.08|R|F|1994-12-01|1994-10-29|1994-12-27|DELIVER IN PERSON|RAIL|ts. fluffily regular requests +960|174776|2328|3|32|59224.64|0.01|0.08|R|F|1995-01-19|1994-12-17|1995-02-04|DELIVER IN PERSON|FOB|around the blithe, even pl +961|117921|2944|1|7|13572.44|0.10|0.00|N|O|1995-07-23|1995-07-20|1995-08-11|TAKE BACK RETURN|RAIL|usual dolphins. ironic pearls sleep blit +961|90469|470|2|18|26270.28|0.09|0.05|N|O|1995-07-01|1995-08-14|1995-07-04|DELIVER IN PERSON|AIR|rmanent foxes haggle speci +961|96938|6939|3|42|81267.06|0.06|0.01|N|O|1995-08-24|1995-08-21|1995-09-10|TAKE BACK RETURN|SHIP|ests do cajole blithely. furiously bo +961|33476|5980|4|29|40874.63|0.00|0.07|N|F|1995-06-10|1995-08-20|1995-06-26|TAKE BACK RETURN|TRUCK|l accounts use blithely against the +961|25276|5277|5|38|45648.26|0.03|0.05|N|O|1995-08-21|1995-07-19|1995-08-27|NONE|RAIL|he blithely special requests. furiousl +961|196988|6989|6|30|62549.40|0.09|0.03|N|O|1995-07-06|1995-07-20|1995-07-26|DELIVER IN PERSON|MAIL|warhorses slee +962|56598|6599|1|36|55965.24|0.01|0.03|R|F|1994-08-09|1994-07-10|1994-09-02|COLLECT COD|TRUCK|al foxes. iron +962|35276|7780|2|27|32704.29|0.09|0.02|A|F|1994-05-11|1994-07-10|1994-06-03|TAKE BACK RETURN|SHIP|y slyly express deposits. final i +962|79649|9650|3|3|4885.92|0.07|0.08|A|F|1994-05-08|1994-07-06|1994-06-02|DELIVER IN PERSON|FOB|ag furiously. even pa +962|56308|8814|4|20|25286.00|0.04|0.02|R|F|1994-08-26|1994-06-27|1994-09-11|DELIVER IN PERSON|SHIP| deposits use fluffily according to +962|151996|7027|5|12|24575.88|0.02|0.00|A|F|1994-06-09|1994-06-07|1994-06-11|COLLECT COD|TRUCK|across the furiously regular escapades daz +962|187354|2391|6|5|7206.75|0.02|0.05|A|F|1994-08-29|1994-07-15|1994-09-19|COLLECT COD|TRUCK|efully bold packages run slyly caref +963|193152|710|1|7|8716.05|0.01|0.00|R|F|1994-09-12|1994-07-18|1994-09-17|DELIVER IN PERSON|REG AIR|s. slyly regular depe +963|97483|9993|2|48|71063.04|0.10|0.06|R|F|1994-08-25|1994-08-12|1994-09-21|DELIVER IN PERSON|RAIL|ages. quickly express deposits cajole pe +964|198936|8937|1|39|79362.27|0.04|0.01|N|O|1995-06-21|1995-07-24|1995-06-24|NONE|AIR|se furiously regular instructions. blith +964|112231|2232|2|1|1243.23|0.02|0.05|N|O|1995-08-20|1995-07-29|1995-09-10|DELIVER IN PERSON|REG AIR|unts. quickly even platelets s +964|56790|9296|3|49|85592.71|0.01|0.03|N|O|1995-09-06|1995-08-10|1995-10-05|NONE|MAIL|ounts. blithely regular packag +964|54514|7020|4|44|64614.44|0.05|0.02|N|O|1995-09-18|1995-08-02|1995-10-17|TAKE BACK RETURN|TRUCK|ronic deposit +965|107207|9718|1|20|24284.00|0.04|0.05|N|F|1995-06-16|1995-07-20|1995-07-06|COLLECT COD|MAIL|kly. carefully pending requ +965|17015|2018|2|23|21436.23|0.06|0.08|N|O|1995-07-12|1995-07-08|1995-08-11|COLLECT COD|MAIL|ld kindle carefully across th +966|179337|6889|1|19|26910.27|0.07|0.01|N|O|1998-05-26|1998-07-15|1998-05-29|COLLECT COD|FOB|efully final pinto beans. quickly +966|116560|1583|2|42|66215.52|0.02|0.06|N|O|1998-06-28|1998-06-20|1998-07-05|NONE|TRUCK|tions boost furiously car +966|21218|6223|3|42|47846.82|0.06|0.08|N|O|1998-06-15|1998-06-08|1998-07-05|NONE|RAIL|sly ironic asymptotes hagg +966|4189|1690|4|20|21863.60|0.04|0.01|N|O|1998-07-19|1998-07-15|1998-07-27|NONE|TRUCK|pecial ins +967|58957|3968|1|41|78553.95|0.05|0.05|R|F|1992-09-21|1992-08-15|1992-10-21|NONE|MAIL|ld foxes wake closely special +967|84402|1927|2|4|5545.60|0.01|0.02|A|F|1992-07-15|1992-07-27|1992-07-18|DELIVER IN PERSON|REG AIR|platelets hang carefully along +967|131550|4064|3|10|15815.50|0.00|0.02|A|F|1992-09-18|1992-08-06|1992-09-19|DELIVER IN PERSON|MAIL|old pinto beans alongside of the exp +967|147690|5233|4|49|85146.81|0.01|0.04|A|F|1992-09-28|1992-09-15|1992-10-14|NONE|SHIP|the slyly even ideas. carefully even +967|16893|9395|5|41|74205.49|0.08|0.04|A|F|1992-07-23|1992-08-07|1992-08-13|TAKE BACK RETURN|FOB|efully special ide +967|105311|7822|6|17|22377.27|0.05|0.06|A|F|1992-10-02|1992-08-19|1992-10-25|NONE|MAIL|y ironic foxes caj +967|160878|5911|7|18|34899.66|0.00|0.02|A|F|1992-10-06|1992-08-05|1992-10-15|DELIVER IN PERSON|RAIL|ngage blith +992|59906|7422|1|14|26122.60|0.10|0.03|N|O|1998-01-29|1997-12-29|1998-02-18|TAKE BACK RETURN|MAIL|the unusual, even dependencies affix fluff +992|37967|7968|2|34|64768.64|0.02|0.00|N|O|1997-11-29|1998-01-21|1997-11-30|NONE|RAIL|s use silently. blithely regular ideas b +992|104722|4723|3|30|51801.60|0.10|0.00|N|O|1997-12-15|1998-02-02|1998-01-12|NONE|SHIP|nic instructions n +992|47212|9717|4|21|24343.41|0.06|0.06|N|O|1997-11-13|1997-12-28|1997-12-10|NONE|TRUCK|fily. quickly special deposit +992|91050|3560|5|7|7287.35|0.09|0.05|N|O|1997-11-30|1997-12-24|1997-12-16|DELIVER IN PERSON|TRUCK|ideas haggle. special theodolit +992|74101|1623|6|41|44079.10|0.10|0.01|N|O|1997-11-14|1998-02-04|1997-11-23|TAKE BACK RETURN|AIR|eodolites cajole across the accounts. +993|174476|6994|1|33|51165.51|0.01|0.05|N|O|1996-01-03|1995-11-28|1996-01-23|DELIVER IN PERSON|AIR| the deposits affix agains +993|2145|4646|2|28|29319.92|0.06|0.08|N|O|1995-10-24|1995-11-20|1995-11-06|DELIVER IN PERSON|RAIL|lites. even theodolite +993|39924|4931|3|10|18639.20|0.03|0.08|N|O|1995-12-17|1995-11-13|1995-12-20|NONE|RAIL|encies wake fur +993|190751|5790|4|40|73670.00|0.01|0.01|N|O|1995-11-16|1995-11-01|1995-12-05|TAKE BACK RETURN|RAIL|gle above the furiously +993|145484|5485|5|33|50472.84|0.09|0.08|N|O|1995-09-28|1995-10-24|1995-10-03|COLLECT COD|RAIL|fluffily. quiet excuses sleep furiously sly +993|136979|4519|6|35|70558.95|0.04|0.02|N|O|1995-10-26|1995-10-20|1995-11-05|DELIVER IN PERSON|FOB|es. ironic, ironic requests +993|4967|2468|7|15|28079.40|0.09|0.03|N|O|1995-09-27|1995-10-21|1995-10-17|DELIVER IN PERSON|MAIL|sits. pending pinto beans haggle? ca +994|64486|4487|1|4|5801.92|0.07|0.03|R|F|1994-07-05|1994-05-21|1994-07-20|COLLECT COD|SHIP|aggle carefully acc +994|9177|1678|2|11|11947.87|0.01|0.00|R|F|1994-05-03|1994-06-10|1994-05-22|NONE|AIR|ular accounts sleep +994|30745|8255|3|5|8378.70|0.08|0.08|A|F|1994-06-24|1994-06-14|1994-06-26|NONE|MAIL|ainst the pending requests. packages sl +994|130471|8011|4|25|37536.75|0.10|0.00|A|F|1994-06-03|1994-06-02|1994-06-06|COLLECT COD|RAIL|usual pinto beans. +995|172294|9846|1|15|20494.35|0.08|0.05|N|O|1995-06-30|1995-08-04|1995-07-27|NONE|REG AIR|uses. fluffily fina +995|128707|1220|2|28|48599.60|0.08|0.03|N|F|1995-06-12|1995-07-20|1995-06-19|DELIVER IN PERSON|SHIP|pades. quick, final frays use flu +995|165067|100|3|45|50942.70|0.00|0.05|N|O|1995-08-02|1995-07-21|1995-08-03|DELIVER IN PERSON|SHIP|lar packages detect blithely above t +995|65736|749|4|25|42543.25|0.01|0.08|N|O|1995-09-08|1995-08-05|1995-09-28|NONE|TRUCK|lyly even +995|23196|3197|5|18|20145.42|0.06|0.03|N|O|1995-07-03|1995-07-29|1995-07-22|TAKE BACK RETURN|AIR| even accounts unwind c +996|172396|7431|1|43|63140.77|0.03|0.06|N|O|1998-03-27|1998-03-25|1998-04-06|COLLECT COD|SHIP| the blithely ironic foxes. slyly silent d +997|162614|2615|1|11|18442.71|0.00|0.02|N|O|1997-06-16|1997-07-21|1997-07-14|DELIVER IN PERSON|TRUCK|p furiously according to t +997|47438|7439|2|17|23552.31|0.03|0.00|N|O|1997-07-28|1997-07-26|1997-08-20|DELIVER IN PERSON|SHIP|aggle quickly furiously +998|9924|7425|1|22|40346.24|0.04|0.05|A|F|1994-12-03|1995-02-17|1994-12-19|TAKE BACK RETURN|RAIL|lites. qui +998|180410|5447|2|7|10432.87|0.10|0.05|R|F|1995-03-24|1995-01-18|1995-04-03|NONE|MAIL|nic deposits. even asym +998|141752|4267|3|30|53812.50|0.05|0.07|A|F|1994-12-02|1995-01-23|1994-12-23|NONE|SHIP|lyly idle Tir +998|10143|5146|4|6|6318.84|0.09|0.05|R|F|1995-03-20|1994-12-27|1995-04-13|DELIVER IN PERSON|MAIL|refully accounts. carefully express ac +998|72407|7422|5|1|1379.40|0.04|0.00|R|F|1995-01-05|1995-01-06|1995-01-13|NONE|SHIP|es sleep. regular dependencies use bl +999|60071|7590|1|34|35056.38|0.00|0.08|R|F|1993-10-30|1993-10-17|1993-10-31|TAKE BACK RETURN|SHIP|its. daringly final instruc +999|198758|1278|2|41|76126.75|0.08|0.01|A|F|1993-10-16|1993-12-04|1993-11-03|DELIVER IN PERSON|REG AIR|us depths. carefully ironic instruc +999|117178|2201|3|15|17927.55|0.07|0.06|A|F|1993-12-12|1993-10-18|1994-01-08|COLLECT COD|REG AIR|y ironic requests. carefully regu +999|2643|2644|4|10|15456.40|0.05|0.02|A|F|1993-11-23|1993-12-02|1993-11-29|NONE|MAIL|efully pending +999|18337|8338|5|3|3765.99|0.03|0.00|R|F|1993-09-17|1993-10-22|1993-10-13|NONE|FOB|nic, pending ideas. bl +999|180934|8489|6|37|74552.41|0.00|0.04|R|F|1994-01-03|1993-10-28|1994-01-12|DELIVER IN PERSON|TRUCK|ckly slyly unusual packages: packages hagg +1024|198068|3107|1|49|57136.94|0.03|0.05|N|O|1998-03-06|1998-01-26|1998-03-29|TAKE BACK RETURN|FOB|ts. asymptotes nag fur +1024|125344|369|2|34|46557.56|0.00|0.01|N|O|1998-01-06|1998-02-05|1998-01-26|COLLECT COD|SHIP|des the slyly even +1024|43565|1078|3|28|42239.68|0.04|0.01|N|O|1998-03-04|1998-03-12|1998-03-15|TAKE BACK RETURN|TRUCK|e blithely regular pi +1024|183259|5778|4|13|17449.25|0.02|0.04|N|O|1998-04-11|1998-02-26|1998-04-18|NONE|FOB|e slyly around the slyly special instructi +1024|20829|8336|5|49|85741.18|0.02|0.04|N|O|1998-02-27|1998-03-10|1998-03-27|COLLECT COD|FOB| carefully bold +1025|149335|9336|1|36|49835.88|0.03|0.04|A|F|1995-05-15|1995-07-05|1995-06-10|COLLECT COD|FOB|e unusual, regular instr +1025|68247|8248|2|23|27950.52|0.08|0.03|N|F|1995-06-02|1995-07-29|1995-06-23|COLLECT COD|RAIL| regular platelets nag carefu +1025|22445|7450|3|25|34186.00|0.06|0.05|R|F|1995-05-29|1995-06-21|1995-06-13|DELIVER IN PERSON|REG AIR|xpress foxes. furiousl +1026|37213|4723|1|36|41407.56|0.10|0.02|N|O|1997-06-14|1997-07-20|1997-06-23|NONE|SHIP|st the ide +1026|36855|1862|2|6|10751.10|0.10|0.08|N|O|1997-07-07|1997-08-16|1997-07-14|TAKE BACK RETURN|TRUCK|to beans. special, regular packages hagg +1027|155942|973|1|43|85911.42|0.07|0.08|R|F|1992-06-17|1992-08-28|1992-07-10|DELIVER IN PERSON|MAIL|oxes. carefully regular deposits +1027|112414|7437|2|20|28528.20|0.01|0.02|A|F|1992-06-08|1992-08-29|1992-06-14|NONE|TRUCK|ar excuses eat f +1027|125692|3229|3|2|3435.38|0.01|0.02|R|F|1992-08-28|1992-07-09|1992-09-10|NONE|FOB|s. quickly unusual waters inside +1027|99229|6757|4|13|15966.86|0.08|0.01|R|F|1992-08-22|1992-07-10|1992-09-12|DELIVER IN PERSON|RAIL|ily ironic ideas use +1027|135427|7941|5|22|32173.24|0.02|0.00|A|F|1992-09-03|1992-08-14|1992-10-01|DELIVER IN PERSON|FOB|the furiously express ex +1027|104958|7469|6|10|19629.50|0.06|0.08|R|F|1992-08-28|1992-08-06|1992-09-03|COLLECT COD|REG AIR|ilent, express foxes near the blithely sp +1028|127811|324|1|2|3677.62|0.09|0.03|A|F|1994-01-10|1994-03-22|1994-01-26|COLLECT COD|FOB|s alongside of the regular asymptotes sleep +1028|111876|6899|2|39|73626.93|0.06|0.05|R|F|1994-02-18|1994-03-22|1994-03-06|TAKE BACK RETURN|MAIL| final dependencies affix a +1028|99556|4575|3|8|12444.40|0.03|0.07|A|F|1994-02-14|1994-03-28|1994-02-22|NONE|AIR|e carefully final packages. furiously fi +1028|31239|3743|4|26|30425.98|0.07|0.02|A|F|1994-03-18|1994-02-08|1994-03-19|TAKE BACK RETURN|RAIL|ronic platelets. carefully f +1028|28550|6057|5|27|39920.85|0.00|0.04|A|F|1994-04-03|1994-02-07|1994-04-26|NONE|REG AIR|ial accounts nag. slyly +1028|25111|7614|6|39|40408.29|0.03|0.02|A|F|1994-02-27|1994-02-16|1994-03-02|DELIVER IN PERSON|AIR|c theodoli +1028|30960|5967|7|22|41601.12|0.03|0.00|R|F|1994-04-24|1994-02-27|1994-05-08|NONE|REG AIR| Tiresias alongside of the carefully spec +1029|136137|8651|1|45|52790.85|0.05|0.07|R|F|1994-07-21|1994-08-30|1994-07-29|TAKE BACK RETURN|FOB|sits boost blithely +1030|64397|1916|1|17|23143.63|0.06|0.06|R|F|1994-10-13|1994-08-01|1994-11-10|DELIVER IN PERSON|RAIL|ly. carefully even packages dazz +1031|45551|5552|1|15|22448.25|0.10|0.08|A|F|1994-11-07|1994-10-29|1994-11-09|TAKE BACK RETURN|FOB|about the carefully bold a +1031|164788|7305|2|28|51877.84|0.05|0.01|A|F|1994-12-10|1994-10-29|1994-12-18|COLLECT COD|FOB|ly ironic accounts across the q +1031|186928|4483|3|27|54402.84|0.07|0.02|R|F|1994-09-20|1994-10-18|1994-10-10|DELIVER IN PERSON|SHIP|gular deposits cajole. blithely unus +1031|87154|2171|4|7|7988.05|0.03|0.03|R|F|1994-12-07|1994-11-11|1994-12-30|COLLECT COD|FOB|r instructions. car +1031|190193|7751|5|44|56460.36|0.01|0.07|R|F|1994-11-20|1994-11-24|1994-12-11|NONE|AIR|re slyly above the furio +1056|120970|3483|1|37|73665.89|0.04|0.06|R|F|1995-02-18|1995-04-01|1995-03-20|NONE|TRUCK| special packages. qui +1057|192240|4760|1|29|38634.96|0.10|0.01|A|F|1992-05-05|1992-05-05|1992-06-03|TAKE BACK RETURN|SHIP|es wake according to the q +1057|168078|595|2|11|12606.77|0.00|0.02|R|F|1992-03-31|1992-04-18|1992-04-18|COLLECT COD|AIR|yly final theodolites. furi +1057|84143|9160|3|21|23669.94|0.03|0.04|A|F|1992-02-28|1992-05-01|1992-03-10|NONE|REG AIR|ar orbits boost bli +1057|181895|6932|4|20|39537.80|0.06|0.03|R|F|1992-03-02|1992-05-19|1992-03-13|DELIVER IN PERSON|TRUCK|s wake bol +1057|96404|3932|5|7|9802.80|0.06|0.05|R|F|1992-06-05|1992-04-30|1992-06-20|NONE|TRUCK|y slyly express theodolites. slyly bo +1057|51461|6472|6|19|26836.74|0.04|0.07|A|F|1992-05-31|1992-05-09|1992-06-02|DELIVER IN PERSON|FOB|r-- packages haggle alon +1058|139555|7095|1|24|38269.20|0.08|0.04|A|F|1993-07-09|1993-05-28|1993-07-22|DELIVER IN PERSON|TRUCK|fully ironic accounts. express accou +1058|88088|5613|2|5|5380.40|0.04|0.07|R|F|1993-05-11|1993-05-29|1993-05-27|COLLECT COD|TRUCK|refully even requests boost along +1058|89249|9250|3|44|54482.56|0.10|0.01|R|F|1993-06-26|1993-06-21|1993-07-20|COLLECT COD|TRUCK|uriously f +1058|4119|1620|4|25|25577.75|0.09|0.01|A|F|1993-05-27|1993-06-10|1993-06-20|TAKE BACK RETURN|MAIL| the final requests believe carefully +1059|177583|7584|1|16|26569.28|0.07|0.02|A|F|1994-04-24|1994-03-31|1994-04-28|DELIVER IN PERSON|SHIP|y ironic pinto +1059|28839|6346|2|7|12374.81|0.07|0.06|R|F|1994-03-30|1994-04-01|1994-04-24|DELIVER IN PERSON|MAIL|the furiously silent excuses are e +1059|87935|444|3|45|86531.85|0.00|0.02|R|F|1994-06-10|1994-05-08|1994-06-21|COLLECT COD|RAIL|riously even theodolites. slyly regula +1059|109784|7315|4|26|46638.28|0.09|0.01|A|F|1994-03-17|1994-04-18|1994-03-26|DELIVER IN PERSON|TRUCK|ar pinto beans at the furiously +1059|138061|575|5|37|40665.22|0.09|0.04|R|F|1994-03-31|1994-05-08|1994-04-06|COLLECT COD|RAIL| packages lose in place of the slyly unusu +1059|189215|1734|6|50|65210.50|0.00|0.03|A|F|1994-06-15|1994-05-11|1994-06-29|NONE|MAIL|s impress furiously about +1059|122187|2188|7|13|15719.34|0.01|0.03|R|F|1994-06-12|1994-05-11|1994-07-02|COLLECT COD|TRUCK|usly regular theodo +1060|195479|3037|1|8|12595.76|0.07|0.04|R|F|1993-05-21|1993-05-06|1993-06-10|DELIVER IN PERSON|FOB|iously. furiously regular in +1060|7614|5115|2|26|39561.86|0.06|0.08|R|F|1993-04-12|1993-04-01|1993-04-20|DELIVER IN PERSON|TRUCK|counts; even deposits are carefull +1060|163141|5658|3|11|13245.54|0.01|0.07|A|F|1993-05-13|1993-05-08|1993-05-17|TAKE BACK RETURN|MAIL|e regular deposits: re +1060|109815|7346|4|16|29196.96|0.03|0.06|A|F|1993-06-15|1993-04-18|1993-07-05|COLLECT COD|SHIP|ccounts. foxes maintain care +1060|52852|7863|5|1|1804.85|0.04|0.06|A|F|1993-06-19|1993-05-10|1993-06-21|COLLECT COD|RAIL|posits detect carefully abo +1060|71383|3891|6|26|35213.88|0.01|0.03|A|F|1993-02-28|1993-04-01|1993-03-09|TAKE BACK RETURN|FOB|quickly abo +1060|120102|5127|7|36|40395.60|0.09|0.01|R|F|1993-03-14|1993-03-24|1993-04-02|TAKE BACK RETURN|FOB|r the quickly +1061|150016|5047|1|7|7462.07|0.04|0.04|N|O|1998-08-09|1998-08-12|1998-08-16|COLLECT COD|FOB|es are slyly expr +1061|118529|1041|2|2|3095.04|0.06|0.02|N|O|1998-08-15|1998-08-05|1998-08-24|COLLECT COD|MAIL|. regular accounts impre +1061|110165|5188|3|26|30554.16|0.08|0.02|N|O|1998-06-18|1998-07-25|1998-06-24|TAKE BACK RETURN|AIR|ave to slee +1061|135309|5310|4|41|55116.30|0.00|0.05|N|O|1998-06-29|1998-07-02|1998-07-27|NONE|MAIL|s are. ironic theodolites cajole. dep +1061|130014|15|5|50|52200.50|0.04|0.08|N|O|1998-05-25|1998-07-22|1998-06-22|COLLECT COD|AIR|nding excuses are around the e +1061|143492|6007|6|35|53742.15|0.09|0.05|N|O|1998-07-05|1998-07-07|1998-07-30|TAKE BACK RETURN|MAIL|ending requests nag careful +1062|136066|6067|1|38|41878.28|0.00|0.01|N|O|1997-01-27|1997-03-07|1997-02-16|DELIVER IN PERSON|TRUCK|deas. pending acc +1063|95042|61|1|42|43555.68|0.03|0.02|A|F|1994-07-10|1994-05-25|1994-07-26|NONE|RAIL|tructions about the blithely ex +1088|106899|6900|1|30|57176.70|0.07|0.03|A|F|1992-05-22|1992-06-25|1992-06-11|TAKE BACK RETURN|SHIP|long the packages snooze careful +1088|36841|4351|2|11|19556.24|0.06|0.00|A|F|1992-08-30|1992-07-25|1992-09-10|TAKE BACK RETURN|AIR|inal requests. fluffily express theod +1088|180349|2868|3|5|7146.70|0.03|0.07|A|F|1992-07-01|1992-07-25|1992-07-02|NONE|AIR|refully ironic packages. r +1088|123962|3963|4|3|5957.88|0.09|0.03|A|F|1992-06-15|1992-08-02|1992-06-18|DELIVER IN PERSON|MAIL|pecial theodolites +1089|150036|7582|1|47|51043.41|0.05|0.06|N|O|1996-06-26|1996-06-25|1996-07-11|NONE|TRUCK|aggle furiously among the bravely eve +1089|49934|2439|2|35|65937.55|0.03|0.00|N|O|1996-08-14|1996-07-10|1996-08-26|NONE|TRUCK|ly express deposits haggle +1089|25189|5190|3|23|25626.14|0.10|0.05|N|O|1996-06-24|1996-07-25|1996-07-20|DELIVER IN PERSON|AIR|g dolphins. deposits integrate. s +1089|140435|7978|4|1|1475.43|0.01|0.03|N|O|1996-07-08|1996-07-07|1996-07-17|COLLECT COD|RAIL|n courts among the caref +1090|21522|1523|1|5|7217.60|0.02|0.05|N|O|1998-02-19|1997-12-25|1998-02-24|DELIVER IN PERSON|AIR|s above the +1090|112475|7498|2|28|41649.16|0.08|0.08|N|O|1998-02-20|1998-01-03|1998-03-19|NONE|FOB|s cajole above the regular +1091|37233|7234|1|40|46809.20|0.10|0.06|N|O|1996-12-17|1996-10-14|1996-12-24|TAKE BACK RETURN|REG AIR|platelets. regular packag +1092|183493|3494|1|48|75671.52|0.04|0.04|N|O|1995-06-25|1995-04-06|1995-07-18|DELIVER IN PERSON|AIR|unusual accounts. fluffi +1092|152637|183|2|1|1689.63|0.01|0.06|A|F|1995-03-10|1995-04-21|1995-04-06|COLLECT COD|RAIL|lent, pending requests-- requests nag accor +1092|160701|5734|3|28|49327.60|0.05|0.08|R|F|1995-04-08|1995-05-01|1995-05-02|DELIVER IN PERSON|FOB|affix carefully. u +1092|85157|5158|4|2|2284.30|0.05|0.07|R|F|1995-04-09|1995-05-12|1995-05-03|TAKE BACK RETURN|TRUCK|ans. slyly eve +1093|86927|1944|1|7|13397.44|0.04|0.02|N|O|1997-11-24|1997-09-23|1997-11-25|TAKE BACK RETURN|SHIP|bold deposits. blithely ironic depos +1093|176300|3852|2|37|50923.10|0.08|0.04|N|O|1997-11-06|1997-10-08|1997-11-22|COLLECT COD|FOB|le furiously across the carefully sp +1093|60434|435|3|34|47410.62|0.01|0.06|N|O|1997-11-07|1997-09-06|1997-11-28|TAKE BACK RETURN|REG AIR|sits. express accounts play carefully. bol +1094|114492|4493|1|9|13558.41|0.07|0.06|N|O|1997-12-28|1998-03-16|1998-01-18|DELIVER IN PERSON|AIR|as. slyly pe +1095|136083|8597|1|33|36929.64|0.01|0.02|N|O|1995-10-03|1995-09-22|1995-10-13|NONE|MAIL|slyly around the iron +1095|135953|3493|2|24|47734.80|0.04|0.06|N|O|1995-08-24|1995-10-20|1995-09-09|COLLECT COD|TRUCK|packages nod furiously above the carefully +1095|155206|7722|3|13|16395.60|0.06|0.01|N|O|1995-08-24|1995-10-19|1995-09-02|TAKE BACK RETURN|REG AIR|ously even accounts. slyly bold a +1095|134380|1920|4|28|39602.64|0.08|0.03|N|O|1995-09-20|1995-11-18|1995-10-02|DELIVER IN PERSON|SHIP| regular pac +1095|111798|9332|5|40|72391.60|0.09|0.03|N|O|1995-10-18|1995-11-14|1995-11-09|NONE|MAIL| bold accounts haggle slyly furiously even +1095|180389|2908|6|37|54367.06|0.07|0.08|N|O|1995-10-04|1995-11-13|1995-10-12|NONE|SHIP|. quickly even dolphins sle +1120|177951|469|1|10|20289.50|0.08|0.05|N|O|1997-12-17|1998-01-21|1997-12-23|DELIVER IN PERSON|MAIL|dependencies. blithel +1120|19045|9046|2|49|47237.96|0.01|0.07|N|O|1998-01-03|1998-02-02|1998-01-09|TAKE BACK RETURN|RAIL|heodolites. quick re +1120|75472|7980|3|21|30396.87|0.06|0.01|N|O|1998-01-11|1998-02-04|1998-01-19|COLLECT COD|REG AIR|s: fluffily even packages c +1120|45653|662|4|22|35170.30|0.09|0.08|N|O|1997-11-15|1998-01-25|1997-12-07|TAKE BACK RETURN|REG AIR|ons. slyly silent requests sleep silent +1120|82435|2436|5|10|14174.30|0.07|0.08|N|O|1997-11-10|1998-02-01|1997-11-28|TAKE BACK RETURN|AIR|ages haggle furiously +1121|167726|5275|1|42|75336.24|0.04|0.05|N|O|1997-03-05|1997-03-18|1997-03-14|DELIVER IN PERSON|SHIP|nts are slyly special packages. f +1121|160276|2793|2|27|36079.29|0.08|0.00|N|O|1997-05-08|1997-03-28|1997-05-14|NONE|MAIL|ly ironic accounts cajole slyly abou +1121|156826|9342|3|10|18828.20|0.00|0.04|N|O|1997-04-17|1997-03-18|1997-05-02|TAKE BACK RETURN|RAIL|dencies. quickly regular theodolites n +1121|165255|2804|4|29|38287.25|0.02|0.01|N|O|1997-03-07|1997-04-02|1997-04-01|DELIVER IN PERSON|REG AIR| use furiously. quickly silent package +1121|29726|4731|5|47|77818.84|0.09|0.03|N|O|1997-04-27|1997-03-28|1997-05-14|COLLECT COD|FOB|ly idle, i +1121|199422|9423|6|50|76071.00|0.06|0.03|N|O|1997-04-21|1997-02-16|1997-04-25|NONE|TRUCK|odolites. slyly even accounts +1121|79080|6602|7|37|39185.96|0.06|0.01|N|O|1997-02-27|1997-03-04|1997-03-02|COLLECT COD|RAIL|special packages. fluffily final requests s +1122|91176|8704|1|8|9337.36|0.10|0.06|N|O|1997-02-02|1997-04-03|1997-02-22|TAKE BACK RETURN|RAIL|c foxes are along the slyly r +1122|181767|6804|2|29|53614.04|0.05|0.04|N|O|1997-05-07|1997-04-07|1997-05-15|COLLECT COD|SHIP|ptotes. quickl +1122|146422|3965|3|25|36710.50|0.09|0.01|N|O|1997-03-21|1997-03-03|1997-04-07|TAKE BACK RETURN|RAIL|d furiously. pinto +1122|105680|8191|4|40|67427.20|0.08|0.08|N|O|1997-02-07|1997-03-25|1997-02-25|NONE|REG AIR|packages sleep after the asym +1122|150352|353|5|15|21035.25|0.05|0.03|N|O|1997-04-15|1997-03-15|1997-05-07|COLLECT COD|SHIP|olve blithely regular, +1122|161814|9363|6|24|45019.44|0.04|0.01|N|O|1997-03-08|1997-02-20|1997-04-05|NONE|RAIL|blithely requests. slyly pending r +1122|299|5300|7|38|45573.02|0.00|0.08|N|O|1997-01-23|1997-04-02|1997-02-16|NONE|TRUCK|t theodolites sleep. even, ironic +1123|11173|8677|1|10|10841.70|0.05|0.08|N|O|1996-11-12|1996-10-04|1996-11-30|NONE|MAIL|ckages are above the depths. slyly ir +1123|177599|117|2|39|65387.01|0.03|0.08|N|O|1996-08-25|1996-10-21|1996-09-04|DELIVER IN PERSON|REG AIR|rding to the furiously ironic requests: r +1123|100807|3318|3|38|68696.40|0.03|0.08|N|O|1996-09-23|1996-10-04|1996-09-27|DELIVER IN PERSON|FOB| blithely carefully unusual reques +1124|197704|5262|1|1|1801.70|0.09|0.08|N|O|1998-10-06|1998-10-02|1998-10-30|NONE|REG AIR| instructions cajole qu +1124|5301|302|2|13|15681.90|0.05|0.04|N|O|1998-09-05|1998-10-03|1998-09-30|DELIVER IN PERSON|SHIP|t the slyly +1124|92298|4808|3|35|45160.15|0.10|0.05|N|O|1998-11-25|1998-10-08|1998-12-25|TAKE BACK RETURN|AIR|ut the slyly bold pinto beans; fi +1124|49104|9105|4|25|26327.50|0.08|0.05|N|O|1998-08-05|1998-10-14|1998-08-11|NONE|MAIL|ggle slyly according +1124|74888|7396|5|33|61475.04|0.05|0.04|N|O|1998-10-19|1998-09-17|1998-10-26|TAKE BACK RETURN|SHIP|eposits sleep slyly. stealthily f +1124|26745|1750|6|43|71884.82|0.01|0.03|N|O|1998-09-19|1998-10-28|1998-10-10|COLLECT COD|MAIL|across the +1124|94195|4196|7|1|1189.19|0.09|0.01|N|O|1998-10-07|1998-08-31|1998-10-12|NONE|TRUCK|ly bold accou +1125|132073|7100|1|4|4420.28|0.08|0.02|A|F|1994-12-10|1994-12-28|1994-12-30|NONE|MAIL| quickly express packages a +1125|137772|7773|2|24|43434.48|0.10|0.03|R|F|1995-01-31|1994-12-02|1995-02-20|COLLECT COD|AIR|es about the slyly s +1125|121039|3552|3|26|27560.78|0.05|0.04|A|F|1995-02-24|1995-01-18|1995-03-05|COLLECT COD|TRUCK|l instruction +1125|97823|2842|4|29|52803.78|0.06|0.00|A|F|1994-11-29|1994-12-20|1994-12-10|DELIVER IN PERSON|RAIL| platelets wake against the carefully i +1126|35025|2535|1|44|42240.88|0.08|0.03|N|O|1998-05-07|1998-04-02|1998-05-29|NONE|TRUCK|es. carefully special +1126|57176|2187|2|7|7932.19|0.06|0.01|N|O|1998-05-02|1998-03-22|1998-05-21|COLLECT COD|MAIL|ons. final, unusual +1126|146694|1723|3|14|24369.66|0.07|0.07|N|O|1998-04-17|1998-04-15|1998-05-12|DELIVER IN PERSON|TRUCK|nstructions. blithe +1127|42596|5101|1|35|53850.65|0.02|0.03|N|O|1995-11-25|1995-11-03|1995-12-17|NONE|TRUCK|l instructions boost blithely according +1127|109765|4786|2|38|67440.88|0.09|0.05|N|O|1995-11-07|1995-11-11|1995-11-26|DELIVER IN PERSON|RAIL|. never final packages boost acro +1127|19646|9647|3|29|45403.56|0.09|0.07|N|O|1995-09-20|1995-11-21|1995-10-11|DELIVER IN PERSON|REG AIR|y. blithely r +1127|174304|4305|4|7|9648.10|0.07|0.05|N|O|1995-11-05|1995-11-02|1995-11-11|DELIVER IN PERSON|FOB| idly pending pains +1152|8646|8647|1|23|35756.72|0.06|0.04|A|F|1994-10-14|1994-10-22|1994-10-21|DELIVER IN PERSON|MAIL|equests alongside of the unusual +1152|99604|2114|2|25|40090.00|0.04|0.08|R|F|1994-10-20|1994-09-18|1994-10-28|DELIVER IN PERSON|REG AIR|efully ironic accounts. sly instructions wa +1152|41846|4351|3|6|10727.04|0.07|0.03|A|F|1994-12-07|1994-11-05|1994-12-25|DELIVER IN PERSON|FOB|p furiously; packages above th +1153|85058|2583|1|15|15645.75|0.00|0.08|N|O|1996-04-24|1996-07-17|1996-04-29|TAKE BACK RETURN|SHIP|uctions boost fluffily according to +1153|168992|1509|2|50|103049.50|0.00|0.07|N|O|1996-06-27|1996-07-13|1996-07-05|COLLECT COD|REG AIR|ronic asymptotes nag slyly. +1153|43393|3394|3|25|33409.75|0.00|0.05|N|O|1996-06-18|1996-06-28|1996-07-09|NONE|TRUCK| theodolites +1153|91126|1127|4|43|48036.16|0.01|0.00|N|O|1996-06-09|1996-06-01|1996-07-04|DELIVER IN PERSON|MAIL|special instructions are. unusual, final du +1153|141212|6241|5|45|56394.45|0.00|0.02|N|O|1996-06-18|1996-06-20|1996-07-03|TAKE BACK RETURN|AIR|oss the ex +1153|135360|5361|6|26|36279.36|0.02|0.03|N|O|1996-08-16|1996-07-12|1996-09-08|NONE|MAIL|kages haggle carefully. f +1153|191834|4354|7|5|9629.15|0.02|0.03|N|O|1996-05-03|1996-06-12|1996-05-28|TAKE BACK RETURN|FOB|special excuses promi +1154|142724|5239|1|31|54768.32|0.06|0.06|A|F|1992-04-17|1992-04-26|1992-05-17|COLLECT COD|AIR|ithely. final, blithe +1154|147409|4952|2|50|72820.00|0.07|0.06|A|F|1992-04-22|1992-04-21|1992-05-01|NONE|TRUCK|ove the furiously bold Tires +1154|96103|3631|3|5|5495.50|0.09|0.04|A|F|1992-06-07|1992-05-07|1992-07-05|DELIVER IN PERSON|MAIL|the furiously +1154|574|575|4|35|51609.95|0.00|0.07|A|F|1992-03-30|1992-04-02|1992-04-21|DELIVER IN PERSON|TRUCK|the carefully regular pinto beans boost +1154|35462|7966|5|18|25154.28|0.02|0.03|A|F|1992-02-26|1992-03-24|1992-03-20|TAKE BACK RETURN|REG AIR|y regular excuses cajole blithely. fi +1154|195101|7621|6|50|59805.00|0.06|0.03|A|F|1992-03-04|1992-04-01|1992-04-01|TAKE BACK RETURN|TRUCK| even, special +1155|69329|9330|1|4|5193.28|0.09|0.05|N|O|1997-10-19|1997-12-09|1997-11-02|DELIVER IN PERSON|SHIP|ic foxes according to the carefully final +1155|195749|788|2|39|71944.86|0.08|0.05|N|O|1998-01-29|1998-01-03|1998-02-01|COLLECT COD|TRUCK|ckly final pinto beans was. +1155|146710|9225|3|23|40404.33|0.08|0.03|N|O|1997-11-24|1997-11-28|1997-12-06|DELIVER IN PERSON|FOB|ly unusual packages. iro +1155|139205|9206|4|12|14930.40|0.01|0.06|N|O|1997-11-01|1998-01-03|1997-11-19|DELIVER IN PERSON|RAIL|packages do +1155|4313|1814|5|49|59648.19|0.04|0.08|N|O|1997-12-07|1997-12-30|1997-12-08|NONE|AIR|ccounts are alongside of t +1156|86609|1626|1|15|23934.00|0.07|0.06|N|O|1996-12-21|1997-01-03|1997-01-10|TAKE BACK RETURN|AIR|the furiously pen +1156|32488|2489|2|21|29830.08|0.02|0.08|N|O|1996-11-07|1997-01-14|1996-12-03|NONE|AIR|dolphins. fluffily ironic packages sleep re +1156|11149|8653|3|29|30744.06|0.09|0.06|N|O|1997-01-24|1996-12-26|1997-02-04|DELIVER IN PERSON|TRUCK|ts sleep sly +1156|171422|1423|4|42|62723.64|0.02|0.00|N|O|1997-01-18|1997-01-12|1997-02-13|NONE|REG AIR|s. quickly bold pains are +1156|73755|6263|5|49|84708.75|0.04|0.01|N|O|1996-11-16|1996-12-02|1996-12-05|COLLECT COD|AIR|ithely unusual in +1156|194006|1564|6|42|46200.00|0.02|0.06|N|O|1997-01-27|1997-01-09|1997-01-28|DELIVER IN PERSON|MAIL|even requests boost ironic deposits. pe +1156|46115|3628|7|20|21222.20|0.08|0.07|N|O|1997-01-01|1997-01-06|1997-01-16|COLLECT COD|MAIL|deposits sleep bravel +1157|48128|3137|1|16|17217.92|0.06|0.00|N|O|1998-04-12|1998-03-09|1998-04-23|DELIVER IN PERSON|MAIL|tions hang +1157|82041|7058|2|4|4092.16|0.10|0.05|N|O|1998-02-24|1998-03-30|1998-03-24|DELIVER IN PERSON|SHIP|ounts. ironic deposits +1157|47985|5498|3|8|15463.84|0.02|0.00|N|O|1998-03-25|1998-03-16|1998-03-29|NONE|REG AIR|blithely even pa +1157|76907|6908|4|46|86659.40|0.07|0.08|N|O|1998-04-19|1998-03-13|1998-04-23|NONE|FOB|slyly regular excuses. accounts +1157|159850|4881|5|14|26737.90|0.03|0.03|N|O|1998-04-17|1998-03-03|1998-05-01|NONE|FOB|theodolites. fluffily re +1158|44218|6723|1|5|5811.05|0.02|0.04|N|O|1996-10-20|1996-07-30|1996-11-14|COLLECT COD|AIR|symptotes along the care +1158|156084|3630|2|23|26221.84|0.00|0.08|N|O|1996-10-21|1996-08-19|1996-10-31|COLLECT COD|MAIL|ularly ironic requests use care +1159|108033|8034|1|39|40600.17|0.01|0.00|A|F|1992-11-20|1992-10-28|1992-12-18|TAKE BACK RETURN|FOB| blithely express reques +1159|95490|509|2|7|10398.43|0.08|0.00|A|F|1992-11-25|1992-10-27|1992-12-20|NONE|AIR|olve somet +1159|97431|9941|3|11|15712.73|0.10|0.03|R|F|1992-12-09|1992-12-07|1992-12-18|DELIVER IN PERSON|MAIL|h furiousl +1184|46728|9233|1|27|45217.44|0.01|0.00|N|O|1998-01-10|1997-12-02|1998-02-06|TAKE BACK RETURN|REG AIR|s wake fluffily. fl +1184|146616|1645|2|4|6650.44|0.04|0.03|N|O|1997-12-25|1998-01-24|1998-01-18|DELIVER IN PERSON|RAIL| express packages. slyly expres +1184|163940|3941|3|7|14027.58|0.05|0.00|N|O|1998-02-14|1998-01-06|1998-03-11|COLLECT COD|TRUCK|ckly warthogs. blithely bold foxes hag +1184|125544|3081|4|3|4708.62|0.02|0.05|N|O|1998-01-15|1997-12-19|1998-02-02|NONE|REG AIR|ar packages. final packages cajol +1185|71925|6940|1|8|15175.36|0.01|0.06|A|F|1992-12-05|1992-10-05|1992-12-28|DELIVER IN PERSON|MAIL|ely according to the furiously regular r +1185|30749|750|2|28|47032.72|0.07|0.06|A|F|1992-09-24|1992-10-07|1992-10-10|DELIVER IN PERSON|REG AIR|ke. slyly regular t +1185|189350|1869|3|12|17272.20|0.05|0.06|R|F|1992-10-12|1992-09-26|1992-11-11|NONE|REG AIR|instructions. daringly pend +1186|2457|2458|1|28|38064.60|0.08|0.07|N|O|1996-12-08|1996-10-17|1996-12-15|TAKE BACK RETURN|TRUCK|ffily spec +1186|91123|6142|2|11|12255.32|0.07|0.05|N|O|1996-10-03|1996-10-21|1996-10-17|DELIVER IN PERSON|AIR|s haggle furiously; slyl +1186|100774|775|3|20|35495.40|0.07|0.07|N|O|1996-08-20|1996-10-23|1996-09-05|COLLECT COD|FOB|ely alongside of the blithel +1186|105917|5918|4|27|51918.57|0.06|0.04|N|O|1996-10-08|1996-11-06|1996-10-09|TAKE BACK RETURN|SHIP|accounts. express, e +1187|177779|5331|1|29|53846.33|0.01|0.04|R|F|1992-12-10|1993-02-09|1992-12-29|TAKE BACK RETURN|RAIL|riously express ac +1187|130451|2965|2|15|22221.75|0.03|0.04|A|F|1992-12-22|1993-01-13|1993-01-01|NONE|TRUCK|ests. foxes wake. carefu +1187|77243|9751|3|40|48809.60|0.08|0.06|R|F|1993-03-05|1992-12-31|1993-03-12|NONE|TRUCK|ar, brave deposits nag blithe +1188|114959|7471|1|2|3947.90|0.00|0.04|N|O|1996-05-22|1996-05-23|1996-06-06|COLLECT COD|RAIL|its breach blit +1188|112024|2025|2|9|9324.18|0.01|0.08|N|O|1996-08-04|1996-06-04|1996-08-19|NONE|REG AIR|ow carefully ironic d +1188|178737|8738|3|41|74444.93|0.07|0.04|N|O|1996-06-29|1996-05-21|1996-07-21|TAKE BACK RETURN|TRUCK|althy packages. fluffily unusual ideas h +1189|50676|677|1|23|37413.41|0.06|0.00|R|F|1994-07-25|1994-06-07|1994-08-02|COLLECT COD|FOB|s. fluffy Tiresias run quickly. bra +1189|104889|2420|2|32|60604.16|0.09|0.02|R|F|1994-05-06|1994-07-03|1994-05-15|TAKE BACK RETURN|FOB|e regular deposits. quickly quiet deposi +1189|56505|9011|3|22|32153.00|0.05|0.03|R|F|1994-06-09|1994-06-29|1994-06-23|DELIVER IN PERSON|TRUCK|quickly unusual platelets lose forges. ca +1190|83788|1313|1|32|56696.96|0.07|0.06|N|O|1997-05-08|1997-04-17|1997-06-01|COLLECT COD|FOB|y final packages? slyly even +1191|48288|793|1|29|35852.12|0.00|0.04|N|O|1996-01-24|1996-01-28|1996-02-17|COLLECT COD|AIR| regular pin +1216|96917|4445|1|8|15311.28|0.03|0.04|R|F|1993-02-01|1993-03-06|1993-02-08|TAKE BACK RETURN|TRUCK| of the carefully express +1216|74067|1589|2|48|49970.88|0.10|0.01|R|F|1993-01-17|1993-02-01|1993-02-13|COLLECT COD|SHIP|symptotes use against th +1216|41738|1739|3|18|30235.14|0.00|0.03|A|F|1993-01-20|1993-01-28|1993-02-02|COLLECT COD|MAIL|y final packages nod +1217|59148|4159|1|45|49821.30|0.07|0.02|A|F|1992-07-01|1992-06-23|1992-07-06|COLLECT COD|AIR|riously close ideas +1218|139055|1569|1|16|17504.80|0.04|0.07|A|F|1994-06-26|1994-08-07|1994-06-30|TAKE BACK RETURN|FOB|ven realms be +1218|93393|5903|2|41|56841.99|0.06|0.06|R|F|1994-08-04|1994-08-05|1994-08-11|TAKE BACK RETURN|SHIP|dolphins. theodolites beyond th +1218|47852|5365|3|44|79193.40|0.07|0.06|A|F|1994-10-05|1994-09-03|1994-10-30|COLLECT COD|TRUCK|thely ironic accounts wake slyly +1218|41364|3869|4|1|1305.36|0.01|0.08|R|F|1994-09-15|1994-09-07|1994-10-03|COLLECT COD|TRUCK|press furio +1219|131882|6909|1|6|11483.28|0.08|0.04|N|O|1995-11-13|1995-12-24|1995-11-18|NONE|MAIL|pecial, ironic requ +1219|128599|1112|2|4|6510.36|0.01|0.04|N|O|1995-11-24|1995-11-22|1995-12-07|TAKE BACK RETURN|SHIP|lly quick requests. blithely even h +1220|168916|6465|1|25|49622.75|0.10|0.03|N|O|1996-10-15|1996-11-07|1996-11-06|COLLECT COD|REG AIR| regular orbi +1220|159710|4741|2|36|63709.56|0.01|0.02|N|O|1996-12-10|1996-11-14|1997-01-07|COLLECT COD|SHIP|ar packages. blithely final acc +1220|36807|6808|3|3|5231.40|0.08|0.06|N|O|1996-09-06|1996-11-03|1996-09-10|COLLECT COD|REG AIR| final theodolites. blithely silent +1220|5144|145|4|36|37769.04|0.07|0.03|N|O|1996-12-12|1996-10-03|1996-12-15|TAKE BACK RETURN|TRUCK|unusual, silent pinto beans aga +1220|48992|4001|5|25|48524.75|0.03|0.08|N|O|1996-09-11|1996-10-09|1996-09-25|DELIVER IN PERSON|RAIL|packages affi +1221|80049|2558|1|43|44248.72|0.05|0.05|R|F|1992-06-22|1992-07-15|1992-07-20|DELIVER IN PERSON|FOB|y slyly above the slyly unusual ideas +1221|169470|9471|2|12|18473.64|0.00|0.08|R|F|1992-08-07|1992-06-24|1992-08-13|COLLECT COD|AIR|yly ironic +1221|68229|3242|3|3|3591.66|0.10|0.08|R|F|1992-07-01|1992-06-04|1992-07-27|COLLECT COD|TRUCK|ing to the fluffily +1221|119731|7265|4|41|71779.93|0.06|0.02|A|F|1992-04-28|1992-07-02|1992-05-19|NONE|RAIL|ns. bold deposit +1221|107651|162|5|13|21562.45|0.10|0.00|R|F|1992-08-01|1992-06-29|1992-08-27|TAKE BACK RETURN|AIR|ajole furiously. blithely expres +1221|84249|4250|6|7|8632.68|0.08|0.06|A|F|1992-06-27|1992-06-16|1992-07-23|TAKE BACK RETURN|RAIL|xpress accounts +1222|71266|8788|1|12|14847.12|0.09|0.02|A|F|1993-02-12|1993-03-14|1993-03-12|TAKE BACK RETURN|RAIL|s print permanently unusual packages. +1222|158637|1153|2|12|20347.56|0.08|0.01|A|F|1993-05-05|1993-03-27|1993-05-18|TAKE BACK RETURN|REG AIR| furiously bold instructions +1222|7554|55|3|26|38000.30|0.02|0.08|R|F|1993-02-13|1993-03-20|1993-02-22|TAKE BACK RETURN|MAIL|, even accounts are ironic +1223|99460|9461|1|28|40864.88|0.10|0.06|N|O|1996-08-07|1996-07-24|1996-08-13|TAKE BACK RETURN|MAIL| quickly ironic requests. furious +1248|163061|3062|1|45|50582.70|0.00|0.08|A|F|1992-04-17|1992-03-31|1992-05-13|NONE|RAIL|ter the pending pl +1248|150275|2791|2|37|49034.99|0.06|0.06|R|F|1992-01-26|1992-02-05|1992-02-13|COLLECT COD|TRUCK|. final requests integrate quickly. blit +1248|55368|2884|3|26|34407.36|0.09|0.06|A|F|1992-01-16|1992-03-01|1992-02-06|TAKE BACK RETURN|AIR| ironic dependen +1248|155169|5170|4|49|59983.84|0.02|0.01|A|F|1992-04-24|1992-02-18|1992-05-03|TAKE BACK RETURN|AIR|beans run quickly according to the carefu +1248|121465|3978|5|20|29729.20|0.08|0.00|A|F|1992-03-12|1992-03-23|1992-04-07|TAKE BACK RETURN|AIR|nal foxes cajole carefully slyl +1248|61457|6470|6|30|42553.50|0.10|0.01|R|F|1992-02-01|1992-03-24|1992-02-08|TAKE BACK RETURN|MAIL|fily special foxes kindle am +1249|58157|3168|1|49|54642.35|0.07|0.05|A|F|1994-03-03|1994-02-28|1994-03-08|NONE|RAIL|ffily express theodo +1250|1035|1036|1|15|14040.45|0.10|0.06|A|F|1992-11-05|1992-12-17|1992-12-03|TAKE BACK RETURN|SHIP| regular, i +1251|3325|3326|1|37|45447.84|0.08|0.08|N|O|1997-12-21|1998-01-12|1997-12-26|COLLECT COD|AIR|. furiously +1251|77902|7903|2|36|67676.40|0.07|0.04|N|O|1997-11-29|1998-01-07|1997-12-03|TAKE BACK RETURN|RAIL|y ironic Tiresias are slyly furio +1251|98778|6306|3|37|65740.49|0.09|0.02|N|O|1998-01-11|1997-12-01|1998-01-23|DELIVER IN PERSON|RAIL|finally bold requests +1251|149818|7361|4|7|13074.67|0.07|0.00|N|O|1998-01-08|1997-12-27|1998-01-18|COLLECT COD|MAIL|riously pe +1251|187484|2521|5|1|1571.48|0.02|0.03|N|O|1997-12-08|1998-01-06|1998-01-01|DELIVER IN PERSON|REG AIR| use quickly final packages. iron +1252|86435|8944|1|13|18478.59|0.10|0.01|N|O|1997-09-07|1997-09-12|1997-10-01|COLLECT COD|REG AIR|sts dazzle +1252|110885|5908|2|27|51188.76|0.00|0.08|N|O|1997-10-22|1997-10-10|1997-11-10|TAKE BACK RETURN|REG AIR|packages hag +1252|39144|9145|3|19|20579.66|0.07|0.02|N|O|1997-10-13|1997-10-23|1997-10-18|NONE|AIR|ts wake carefully-- packages sleep. quick +1252|91193|3703|4|11|13026.09|0.10|0.01|N|O|1997-10-16|1997-09-22|1997-10-28|COLLECT COD|AIR|s are. slyly final requests among the +1252|78748|8749|5|26|44895.24|0.05|0.05|N|O|1997-08-05|1997-10-24|1997-08-07|DELIVER IN PERSON|SHIP|onic pinto beans haggle furiously +1253|179988|7540|1|14|28951.72|0.00|0.06|R|F|1993-04-03|1993-04-16|1993-04-27|TAKE BACK RETURN|MAIL|lar foxes sleep furiously final, final pack +1253|53958|8969|2|13|24855.35|0.01|0.06|A|F|1993-03-05|1993-04-26|1993-03-08|DELIVER IN PERSON|FOB|al packages +1253|69375|9376|3|22|29576.14|0.05|0.06|A|F|1993-02-23|1993-04-06|1993-03-07|TAKE BACK RETURN|SHIP|telets cajole alongside of the final reques +1253|175589|624|4|23|38285.34|0.09|0.02|R|F|1993-04-18|1993-04-18|1993-05-07|COLLECT COD|FOB| the slyly silent re +1253|113918|6430|5|19|36706.29|0.05|0.05|A|F|1993-04-01|1993-04-22|1993-04-14|TAKE BACK RETURN|AIR|al pinto bea +1254|192385|4905|1|6|8864.28|0.08|0.01|N|O|1996-02-02|1996-03-21|1996-02-29|NONE|REG AIR|lithely even deposits eat! +1254|199414|4453|2|47|71130.27|0.05|0.06|N|O|1996-03-07|1996-02-20|1996-04-05|COLLECT COD|MAIL| platelets cajol +1254|134485|4486|3|35|53181.80|0.05|0.06|N|O|1996-04-08|1996-02-29|1996-04-18|DELIVER IN PERSON|FOB|ckages boost. furious warhorses cajole +1255|191801|4321|1|12|22713.60|0.00|0.02|A|F|1994-08-17|1994-06-29|1994-09-04|TAKE BACK RETURN|REG AIR| regular, express accounts are +1255|193712|1270|2|46|83062.66|0.07|0.05|R|F|1994-07-06|1994-07-14|1994-08-05|NONE|MAIL|ons nag qui +1280|128696|3721|1|17|29319.73|0.01|0.01|A|F|1993-02-04|1993-04-10|1993-02-07|NONE|FOB|ructions integrate across the th +1280|188305|5860|2|6|8359.80|0.05|0.06|R|F|1993-03-30|1993-02-16|1993-04-18|DELIVER IN PERSON|AIR|gular deposits +1280|32176|7183|3|13|14406.21|0.03|0.02|R|F|1993-03-06|1993-03-11|1993-03-18|DELIVER IN PERSON|TRUCK|blithely final accounts use evenly +1280|174752|2304|4|5|9133.75|0.06|0.03|R|F|1993-02-03|1993-02-11|1993-02-23|DELIVER IN PERSON|AIR|beans haggle. quickly bold instructions h +1280|51971|4477|5|24|46151.28|0.07|0.02|R|F|1993-03-20|1993-03-01|1993-04-09|COLLECT COD|RAIL|y pending orbits boost after the slyly +1280|65229|242|6|9|10747.98|0.00|0.05|R|F|1993-04-18|1993-03-28|1993-05-04|DELIVER IN PERSON|FOB|usual accou +1280|91590|9118|7|19|30050.21|0.02|0.06|A|F|1993-02-07|1993-02-28|1993-02-12|NONE|TRUCK|lyly along the furiously regular +1281|137813|327|1|33|61076.73|0.07|0.08|R|F|1995-02-01|1995-01-18|1995-03-03|NONE|REG AIR|dencies. thinly final pinto beans wake +1281|6372|1373|2|37|47299.69|0.08|0.03|A|F|1995-03-19|1995-02-02|1995-03-27|NONE|AIR|ounts detect +1281|93625|8644|3|2|3237.24|0.05|0.06|A|F|1994-12-27|1995-01-26|1995-01-21|TAKE BACK RETURN|FOB|ly unusual requests. final reques +1281|153005|5521|4|38|40204.00|0.04|0.06|R|F|1995-03-28|1995-01-11|1995-04-14|TAKE BACK RETURN|MAIL| ideas-- blithely regular +1281|151357|3873|5|13|18308.55|0.03|0.07|A|F|1995-02-06|1995-02-13|1995-02-18|DELIVER IN PERSON|TRUCK|fully final platelets wa +1281|49270|6783|6|4|4877.08|0.07|0.04|R|F|1995-03-15|1995-02-21|1995-03-20|NONE|SHIP|ggle against the even requests. requests +1281|77886|5408|7|43|80146.84|0.10|0.02|R|F|1995-01-28|1995-02-08|1995-02-10|DELIVER IN PERSON|AIR|final accounts. final packages slee +1282|22493|2494|1|14|19816.86|0.04|0.02|R|F|1992-06-29|1992-04-05|1992-07-21|TAKE BACK RETURN|REG AIR|ecial deposit +1282|29129|4134|2|10|10581.20|0.09|0.06|R|F|1992-04-10|1992-04-16|1992-05-01|DELIVER IN PERSON|SHIP|r theodolite +1282|159521|9522|3|19|30029.88|0.01|0.03|R|F|1992-05-07|1992-04-07|1992-05-13|NONE|RAIL|ts x-ray across the furi +1282|58316|8317|4|19|24211.89|0.00|0.05|A|F|1992-06-20|1992-04-17|1992-07-05|DELIVER IN PERSON|REG AIR|nto beans. carefully close theodo +1283|92682|210|1|47|78709.96|0.05|0.03|N|O|1996-10-21|1996-10-29|1996-11-12|DELIVER IN PERSON|TRUCK|even instructions boost slyly blithely +1283|105334|355|2|1|1339.33|0.00|0.08|N|O|1996-10-07|1996-10-12|1996-10-08|NONE|RAIL|d the sauternes. slyly ev +1283|137074|4614|3|18|19999.26|0.02|0.01|N|O|1996-10-14|1996-11-07|1996-10-22|DELIVER IN PERSON|AIR|equests use along the fluff +1283|191999|4519|4|40|83639.60|0.07|0.03|N|O|1996-11-09|1996-11-23|1996-11-28|NONE|MAIL|riously. even, ironic instructions after +1283|123473|5986|5|43|64348.21|0.01|0.04|N|O|1996-09-29|1996-11-19|1996-10-26|TAKE BACK RETURN|RAIL|requests sleep slyly about the +1283|7533|5034|6|30|43215.90|0.06|0.07|N|O|1996-11-22|1996-11-22|1996-12-15|COLLECT COD|TRUCK|t the fluffily +1283|196227|6228|7|21|27787.62|0.04|0.03|N|O|1996-09-12|1996-10-02|1996-10-12|NONE|REG AIR|fully regular +1284|177427|2462|1|49|73716.58|0.00|0.06|N|O|1996-04-11|1996-03-04|1996-04-16|NONE|MAIL|lar packages. special packages ac +1284|5304|5305|2|4|4837.20|0.07|0.06|N|O|1996-02-29|1996-02-11|1996-03-01|TAKE BACK RETURN|TRUCK| regular asymptotes. +1284|132592|2593|3|39|63359.01|0.08|0.00|N|O|1996-01-11|1996-02-07|1996-02-05|COLLECT COD|MAIL|even accoun +1284|58252|8253|4|1|1210.25|0.01|0.07|N|O|1996-04-28|1996-04-02|1996-05-08|DELIVER IN PERSON|SHIP|al packages use carefully express de +1284|33328|3329|5|9|11351.88|0.05|0.06|N|O|1996-03-03|1996-03-19|1996-04-01|DELIVER IN PERSON|REG AIR|after the pending +1285|21548|1549|1|12|17634.48|0.00|0.06|A|F|1992-06-21|1992-08-16|1992-07-12|COLLECT COD|MAIL|ss foxes. blithe theodolites cajole slyly +1285|142274|4789|2|45|59232.15|0.01|0.02|R|F|1992-09-05|1992-08-08|1992-10-02|COLLECT COD|REG AIR| special requests haggle blithely. +1285|188148|5703|3|4|4944.56|0.09|0.06|A|F|1992-07-20|1992-08-17|1992-07-26|DELIVER IN PERSON|FOB|l packages sleep slyly quiet i +1285|187439|9958|4|39|59530.77|0.05|0.01|A|F|1992-09-15|1992-08-05|1992-10-05|DELIVER IN PERSON|TRUCK|uctions. car +1285|83541|8558|5|33|50309.82|0.00|0.08|R|F|1992-09-08|1992-08-25|1992-09-16|NONE|SHIP|ites affix +1286|177013|7014|1|49|53410.49|0.08|0.01|R|F|1993-06-24|1993-08-12|1993-06-26|DELIVER IN PERSON|SHIP|gged accoun +1286|48230|735|2|48|56555.04|0.01|0.04|A|F|1993-07-11|1993-07-11|1993-08-01|COLLECT COD|TRUCK|unts alongs +1286|188576|3613|3|11|18310.27|0.03|0.04|R|F|1993-08-08|1993-07-30|1993-09-05|DELIVER IN PERSON|FOB| slyly even packages. requ +1286|183767|3768|4|37|68478.12|0.00|0.02|R|F|1993-05-27|1993-07-11|1993-06-01|COLLECT COD|SHIP|lyly ironic pinto beans cajole furiously s +1286|164048|1597|5|14|15568.56|0.00|0.01|R|F|1993-05-23|1993-08-09|1993-06-01|NONE|REG AIR|blithely bo +1286|145926|3469|6|41|80848.72|0.04|0.05|R|F|1993-08-02|1993-08-06|1993-08-07|TAKE BACK RETURN|FOB| the furiously expre +1287|173172|8207|1|35|43580.95|0.09|0.06|A|F|1994-09-07|1994-09-12|1994-09-30|TAKE BACK RETURN|FOB|s wake unusual grou +1287|94556|9575|2|10|15505.50|0.08|0.03|R|F|1994-07-08|1994-08-28|1994-07-10|TAKE BACK RETURN|RAIL|thely alongside of the unusual, ironic pa +1287|278|279|3|30|35348.10|0.00|0.07|R|F|1994-07-12|1994-09-23|1994-08-07|NONE|RAIL|ar packages. even, even +1287|61652|9171|4|10|16136.50|0.01|0.05|A|F|1994-09-03|1994-08-12|1994-09-16|TAKE BACK RETURN|REG AIR|ding, regular accounts +1287|178903|3938|5|21|41619.90|0.06|0.02|A|F|1994-10-06|1994-09-25|1994-10-16|TAKE BACK RETURN|TRUCK|y quickly bold theodoli +1287|20481|5486|6|26|36438.48|0.03|0.08|R|F|1994-10-03|1994-09-27|1994-10-30|DELIVER IN PERSON|RAIL|egular foxes. theodolites nag along t +1312|80689|5706|1|9|15027.12|0.04|0.08|R|F|1994-07-19|1994-06-29|1994-07-24|TAKE BACK RETURN|MAIL|. furiously +1312|135990|5991|2|28|56727.72|0.06|0.06|A|F|1994-09-09|1994-08-01|1994-10-02|TAKE BACK RETURN|FOB|uriously final frays should use quick +1312|172935|487|3|18|36142.74|0.03|0.07|A|F|1994-09-13|1994-07-08|1994-09-22|TAKE BACK RETURN|MAIL|. slyly ironic +1313|51361|8877|1|48|62993.28|0.01|0.03|A|F|1994-12-20|1994-10-29|1995-01-07|COLLECT COD|MAIL|s are quick +1314|197722|242|1|5|9098.60|0.03|0.01|A|F|1994-05-26|1994-08-06|1994-05-31|TAKE BACK RETURN|AIR|equests nag across the furious +1314|109303|4324|2|39|51179.70|0.01|0.03|R|F|1994-08-09|1994-06-14|1994-08-31|TAKE BACK RETURN|TRUCK| unusual accounts slee +1314|40911|912|3|11|20371.01|0.01|0.04|A|F|1994-05-16|1994-07-30|1994-05-31|COLLECT COD|REG AIR|tegrate furious +1315|95509|8019|1|27|40621.50|0.01|0.03|N|O|1998-07-04|1998-06-13|1998-07-28|NONE|SHIP|latelets. fluffily ironic account +1315|15742|3246|2|15|24866.10|0.05|0.01|N|O|1998-07-12|1998-06-10|1998-08-07|COLLECT COD|AIR|. foxes integrate carefully special +1315|167190|4739|3|25|31429.75|0.01|0.08|N|O|1998-06-26|1998-06-10|1998-07-06|TAKE BACK RETURN|FOB|lites. unusual foxes affi +1315|160919|8468|4|19|37618.29|0.02|0.05|N|O|1998-07-05|1998-05-23|1998-08-04|TAKE BACK RETURN|SHIP|nal, regular warhorses about the fu +1315|158532|1048|5|32|50896.96|0.10|0.05|N|O|1998-03-30|1998-06-12|1998-04-25|NONE|SHIP|neath the final p +1316|126429|1454|1|46|66949.32|0.05|0.04|A|F|1994-01-13|1994-01-24|1994-02-03|COLLECT COD|TRUCK|ges haggle of the +1316|78158|666|2|15|17042.25|0.02|0.01|R|F|1994-03-12|1994-03-02|1994-03-14|COLLECT COD|FOB|se. furiously final depo +1316|197244|7245|3|33|44260.92|0.10|0.06|R|F|1994-03-31|1994-01-23|1994-04-20|TAKE BACK RETURN|AIR|manently; blithely special deposits +1316|65047|60|4|15|15180.60|0.00|0.06|R|F|1993-12-17|1994-02-04|1993-12-20|NONE|RAIL|fully express dugouts. furiously silent ide +1316|40746|747|5|40|67469.60|0.01|0.03|R|F|1994-02-04|1994-02-09|1994-02-27|NONE|REG AIR|l dugouts. co +1316|3390|5891|6|7|9053.73|0.05|0.04|A|F|1993-12-09|1994-01-12|1993-12-30|TAKE BACK RETURN|MAIL|. furiously even accounts a +1316|162096|9645|7|8|9264.72|0.10|0.04|A|F|1994-03-26|1994-02-08|1994-04-19|NONE|SHIP|packages against the express requests wa +1317|133799|3800|1|34|62314.86|0.08|0.04|N|O|1995-08-13|1995-08-08|1995-09-10|COLLECT COD|RAIL|deposits boost thinly blithely final id +1317|159586|7132|2|7|11519.06|0.05|0.01|A|F|1995-06-08|1995-08-03|1995-06-16|TAKE BACK RETURN|SHIP| pinto beans according to the final, pend +1317|157179|7180|3|26|32140.42|0.01|0.02|N|O|1995-07-13|1995-06-26|1995-08-06|COLLECT COD|RAIL|leep along th +1317|105156|2687|4|35|40640.25|0.05|0.02|N|O|1995-07-16|1995-07-07|1995-07-22|TAKE BACK RETURN|FOB|r packages impress blithely car +1317|149415|6958|5|36|52718.76|0.02|0.00|N|O|1995-09-03|1995-07-06|1995-09-04|DELIVER IN PERSON|AIR| deposits. quic +1318|113682|1216|1|24|40696.32|0.08|0.06|N|O|1998-09-27|1998-09-15|1998-10-12|TAKE BACK RETURN|AIR|ual, unusual packages. fluffy, iro +1318|45822|8327|2|26|45963.32|0.01|0.03|N|O|1998-09-26|1998-08-09|1998-10-07|DELIVER IN PERSON|FOB|ly. regular, u +1318|128344|857|3|31|42542.54|0.01|0.04|N|O|1998-08-25|1998-07-31|1998-08-31|COLLECT COD|AIR|ve the carefully expr +1319|60918|5931|1|21|39457.11|0.03|0.04|N|O|1996-10-05|1996-12-02|1996-10-28|COLLECT COD|FOB|s: carefully express +1319|36685|1692|2|12|19460.16|0.09|0.05|N|O|1996-11-05|1996-12-12|1996-11-29|DELIVER IN PERSON|TRUCK|packages integrate furiously. expres +1344|140001|5030|1|15|15615.00|0.10|0.07|A|F|1992-06-22|1992-06-24|1992-06-23|TAKE BACK RETURN|MAIL|rding to the blithely ironic theodolite +1344|189888|4925|2|29|57358.52|0.09|0.00|A|F|1992-07-17|1992-06-07|1992-07-21|NONE|REG AIR|ffily quiet foxes wake blithely. slyly +1345|197110|7111|1|49|59148.39|0.08|0.00|A|F|1992-12-27|1993-01-23|1993-01-06|NONE|FOB|sly. furiously final accounts are blithely +1345|11261|6264|2|37|43373.62|0.10|0.07|A|F|1992-11-27|1992-12-11|1992-12-07|COLLECT COD|FOB|e slyly express requests. ironic accounts c +1345|56666|6667|3|31|50302.46|0.08|0.07|R|F|1992-12-02|1992-12-29|1992-12-14|COLLECT COD|REG AIR|. slyly silent accounts sublat +1346|159096|1612|1|29|33497.61|0.07|0.05|A|F|1992-08-18|1992-09-15|1992-09-17|TAKE BACK RETURN|REG AIR|the pinto +1346|124499|4500|2|48|73127.52|0.06|0.03|A|F|1992-09-28|1992-07-22|1992-10-13|TAKE BACK RETURN|REG AIR| along the carefully spec +1346|53819|3820|3|13|23046.53|0.10|0.04|A|F|1992-07-22|1992-08-10|1992-08-06|NONE|SHIP|arefully brave deposits into the slyly iro +1346|123555|3556|4|6|9471.30|0.02|0.02|R|F|1992-09-13|1992-07-21|1992-09-27|TAKE BACK RETURN|AIR|inst the furiously final theodolites. caref +1346|186043|6044|5|30|33871.20|0.01|0.07|R|F|1992-10-01|1992-07-22|1992-10-24|NONE|SHIP| nag blithely. unusual, ru +1346|15002|2506|6|45|41265.00|0.02|0.04|A|F|1992-09-11|1992-08-06|1992-09-12|COLLECT COD|FOB|press deposits. +1347|80130|7655|1|45|49955.85|0.02|0.05|N|O|1997-08-24|1997-09-03|1997-09-08|COLLECT COD|AIR|ages wake around t +1347|142381|7410|2|34|48394.92|0.07|0.04|N|O|1997-06-25|1997-09-08|1997-07-24|COLLECT COD|FOB|r packages. f +1347|184871|4872|3|23|44985.01|0.03|0.04|N|O|1997-07-31|1997-08-25|1997-08-21|COLLECT COD|SHIP|ronic pinto beans. express reques +1347|112077|4589|4|28|30493.96|0.01|0.00|N|O|1997-07-30|1997-07-22|1997-08-18|TAKE BACK RETURN|FOB|foxes after the blithely special i +1347|64173|4174|5|9|10234.53|0.01|0.03|N|O|1997-08-28|1997-09-16|1997-09-26|DELIVER IN PERSON|AIR| detect blithely above the fina +1347|152357|7388|6|21|29596.35|0.06|0.04|N|O|1997-10-10|1997-08-16|1997-11-02|NONE|FOB|g pinto beans affix car +1347|50283|7799|7|10|12332.80|0.02|0.07|N|O|1997-07-04|1997-07-23|1997-07-05|DELIVER IN PERSON|SHIP|y ironic pin +1348|94296|6806|1|13|16773.77|0.01|0.01|N|O|1998-04-28|1998-06-05|1998-05-12|TAKE BACK RETURN|SHIP| blithely r +1348|21908|9415|2|41|75025.90|0.07|0.03|N|O|1998-05-02|1998-05-26|1998-05-09|COLLECT COD|RAIL|kages. platelets about the ca +1348|198221|8222|3|40|52768.80|0.07|0.05|N|O|1998-08-14|1998-07-10|1998-08-27|COLLECT COD|AIR|fter the regu +1348|97544|2563|4|2|3083.08|0.01|0.04|N|O|1998-05-30|1998-06-20|1998-06-05|COLLECT COD|MAIL|lly final packages use fluffily express ac +1349|180575|3094|1|1|1655.57|0.06|0.03|N|O|1998-01-07|1998-01-14|1998-02-03|COLLECT COD|REG AIR| express inst +1349|117686|198|2|45|76665.60|0.03|0.02|N|O|1997-12-24|1998-01-17|1997-12-28|NONE|AIR| ironic, unusual deposits wake carefu +1350|53683|8694|1|21|34370.28|0.04|0.04|A|F|1993-12-17|1993-10-17|1993-12-25|COLLECT COD|REG AIR|lyly above the evenly +1350|43604|3605|2|32|49523.20|0.03|0.00|R|F|1993-11-18|1993-09-30|1993-12-16|COLLECT COD|MAIL|ic, final +1351|107227|7228|1|25|30855.50|0.06|0.04|N|O|1998-06-02|1998-05-25|1998-06-22|COLLECT COD|SHIP|iously regul +1376|168528|1045|1|22|35123.44|0.01|0.03|N|O|1997-08-05|1997-07-08|1997-09-03|NONE|REG AIR|inst the final, pending +1377|153593|1139|1|5|8232.95|0.06|0.05|N|O|1998-05-06|1998-07-08|1998-06-01|TAKE BACK RETURN|FOB| final, final grouches. accoun +1377|32599|5103|2|3|4594.77|0.10|0.04|N|O|1998-04-30|1998-07-02|1998-05-14|DELIVER IN PERSON|REG AIR|yly enticing requ +1377|83378|8395|3|26|35395.62|0.07|0.07|N|O|1998-05-28|1998-06-11|1998-06-25|COLLECT COD|SHIP|egular deposits. quickly regular acco +1377|120024|7561|4|39|40716.78|0.00|0.03|N|O|1998-07-27|1998-07-18|1998-08-13|DELIVER IN PERSON|SHIP|e ironic, regular requests. carefully +1377|32294|4798|5|19|23299.51|0.10|0.00|N|O|1998-06-20|1998-06-27|1998-07-20|NONE|AIR|ught to are bold foxes +1377|153755|1301|6|17|30748.75|0.03|0.04|N|O|1998-06-19|1998-07-20|1998-07-14|NONE|REG AIR|s must have to mold b +1378|196057|1096|1|34|39203.70|0.09|0.07|N|O|1996-07-08|1996-04-23|1996-07-09|COLLECT COD|RAIL|le furiously slyly final accounts. careful +1378|123358|5871|2|18|24864.30|0.05|0.02|N|O|1996-06-19|1996-05-16|1996-06-21|DELIVER IN PERSON|RAIL| theodolites. i +1378|72873|2874|3|11|20304.57|0.10|0.03|N|O|1996-06-07|1996-05-09|1996-07-05|COLLECT COD|TRUCK| blithely express hoc +1378|170689|690|4|12|21116.16|0.02|0.06|N|O|1996-06-16|1996-05-23|1996-07-09|COLLECT COD|SHIP|notornis. b +1378|155233|5234|5|9|11594.07|0.06|0.05|N|O|1996-04-20|1996-04-13|1996-05-09|COLLECT COD|REG AIR|e carefully. carefully iron +1378|193453|5973|6|29|44847.05|0.05|0.05|N|O|1996-04-15|1996-04-23|1996-05-14|NONE|REG AIR|ual packages are furiously blith +1379|72894|5402|1|13|24269.57|0.04|0.01|N|O|1998-06-08|1998-07-13|1998-06-16|NONE|AIR|ully across the furiously iron +1379|117107|9619|2|50|56205.00|0.07|0.08|N|O|1998-08-31|1998-07-13|1998-09-02|TAKE BACK RETURN|FOB|olphins. ca +1379|12350|4852|3|24|30296.40|0.05|0.02|N|O|1998-07-06|1998-07-09|1998-07-29|DELIVER IN PERSON|MAIL|ages cajole carefully idly express re +1380|148197|3226|1|6|7471.14|0.00|0.04|N|O|1996-08-06|1996-10-01|1996-08-14|NONE|RAIL|e foxes. slyly specia +1380|140792|5821|2|40|73311.60|0.02|0.02|N|O|1996-10-01|1996-08-14|1996-10-20|COLLECT COD|RAIL|ly final frets. ironic, +1380|77746|7747|3|15|25856.10|0.05|0.02|N|O|1996-07-14|1996-08-12|1996-08-03|NONE|FOB|riously ironic foxes aff +1380|60776|3283|4|33|57313.41|0.04|0.07|N|O|1996-08-23|1996-10-01|1996-09-18|TAKE BACK RETURN|SHIP|e ironic, even excuses haggle +1381|143074|5589|1|47|52502.29|0.08|0.04|N|O|1998-09-22|1998-08-12|1998-10-12|DELIVER IN PERSON|AIR|ly ironic deposits +1381|33128|5632|2|12|12733.44|0.07|0.08|N|O|1998-08-13|1998-08-12|1998-08-28|TAKE BACK RETURN|AIR| furiously regular package +1382|161373|1374|1|18|25818.66|0.08|0.03|R|F|1993-08-30|1993-10-19|1993-09-03|DELIVER IN PERSON|AIR|hely regular deposits. fluffy s +1382|180829|830|2|29|55384.78|0.08|0.04|A|F|1993-10-08|1993-11-11|1993-10-10|COLLECT COD|FOB| haggle: closely even asymptot +1382|177866|2901|3|43|83585.98|0.10|0.04|A|F|1993-09-02|1993-10-06|1993-09-15|DELIVER IN PERSON|AIR|ress deposits. slyly ironic foxes are blit +1382|180589|8144|4|11|18365.38|0.04|0.04|R|F|1993-09-17|1993-09-29|1993-09-21|NONE|SHIP|furiously unusual packages play quickly +1382|156162|6163|5|31|37762.96|0.07|0.03|R|F|1993-10-26|1993-10-15|1993-11-09|TAKE BACK RETURN|FOB|hely regular dependencies. f +1382|9855|4856|6|38|67064.30|0.07|0.07|R|F|1993-11-17|1993-09-28|1993-11-20|COLLECT COD|SHIP|ake pending pinto beans. s +1382|22788|2789|7|5|8553.90|0.07|0.01|R|F|1993-10-02|1993-09-29|1993-10-12|DELIVER IN PERSON|REG AIR|ter the carefully final excuses. blit +1383|192894|452|1|14|27816.46|0.07|0.06|A|F|1993-08-25|1993-07-09|1993-09-12|DELIVER IN PERSON|RAIL|ole carefully silent requests. car +1383|160122|2639|2|19|22460.28|0.06|0.04|R|F|1993-05-24|1993-07-07|1993-06-14|NONE|AIR|lyly unusual accounts sle +1408|147902|5445|1|29|56547.10|0.03|0.04|N|O|1998-03-12|1998-02-14|1998-03-17|COLLECT COD|MAIL|en accounts grow furiousl +1408|172326|7361|2|7|9788.24|0.05|0.06|N|O|1998-01-14|1998-03-21|1998-01-29|COLLECT COD|AIR|fully final instructions. theodolites ca +1408|75549|8057|3|11|16769.94|0.00|0.03|N|O|1998-04-04|1998-01-29|1998-04-18|NONE|REG AIR|y even accounts thrash care +1408|147092|9607|4|20|22781.80|0.06|0.00|N|O|1998-04-21|1998-01-25|1998-05-12|DELIVER IN PERSON|TRUCK| blithely fluffi +1408|169688|9689|5|41|72064.88|0.02|0.06|N|O|1998-02-25|1998-02-03|1998-03-13|COLLECT COD|REG AIR|ep along the fina +1408|133484|1024|6|42|63734.16|0.05|0.08|N|O|1998-01-30|1998-02-07|1998-02-18|TAKE BACK RETURN|REG AIR|even packages. even accounts cajole +1408|54519|4520|7|26|38311.26|0.00|0.00|N|O|1998-03-19|1998-03-14|1998-04-01|COLLECT COD|RAIL|ic foxes ca +1409|98868|1378|1|23|42937.78|0.01|0.03|A|F|1993-04-18|1993-02-25|1993-05-06|DELIVER IN PERSON|FOB|ions. slyly ironic packages wake quick +1409|64412|9425|2|36|49550.76|0.09|0.02|A|F|1993-01-27|1993-01-31|1993-02-07|COLLECT COD|FOB|ncies sleep carefully r +1409|159012|9013|3|17|18207.17|0.07|0.00|R|F|1993-04-15|1993-03-01|1993-04-29|NONE|REG AIR|pending accounts poach. care +1410|120271|5296|1|15|19369.05|0.06|0.05|N|O|1997-05-25|1997-07-08|1997-06-15|NONE|SHIP| bold packages are fluf +1410|178206|724|2|18|23115.60|0.03|0.00|N|O|1997-06-03|1997-05-17|1997-06-07|TAKE BACK RETURN|RAIL|gle furiously fluffily regular requests +1410|108109|3130|3|37|41332.70|0.02|0.01|N|O|1997-04-17|1997-06-18|1997-04-19|COLLECT COD|TRUCK|to beans b +1410|187510|5065|4|22|35145.22|0.10|0.00|N|O|1997-07-31|1997-05-17|1997-08-19|TAKE BACK RETURN|RAIL|gular account +1410|65802|3321|5|25|44195.00|0.09|0.02|N|O|1997-05-07|1997-07-10|1997-05-16|NONE|REG AIR|unts haggle against the furiously fina +1411|16321|3825|1|9|11135.88|0.06|0.04|A|F|1995-03-08|1995-03-04|1995-03-11|DELIVER IN PERSON|AIR|accounts. furiou +1411|106434|6435|2|26|37451.18|0.02|0.02|A|F|1995-04-12|1995-01-24|1995-05-03|TAKE BACK RETURN|TRUCK|c packages. +1411|26013|1018|3|37|34743.37|0.00|0.06|A|F|1995-02-27|1995-03-02|1995-03-24|NONE|MAIL|d excuses. furiously final pear +1411|199946|4985|4|20|40918.80|0.01|0.03|R|F|1995-04-06|1995-03-16|1995-04-17|COLLECT COD|FOB|s against the +1411|82816|7833|5|46|82745.26|0.08|0.05|A|F|1995-04-03|1995-01-20|1995-04-05|DELIVER IN PERSON|REG AIR|ly daring instructions +1411|76148|1163|6|30|33724.20|0.09|0.04|A|F|1995-01-12|1995-02-01|1995-01-23|DELIVER IN PERSON|MAIL|ious foxes wake courts. caref +1412|57200|2211|1|37|42816.40|0.06|0.01|A|F|1993-04-10|1993-04-19|1993-04-12|DELIVER IN PERSON|RAIL|hely express excuses are +1412|155021|52|2|20|21520.40|0.10|0.05|A|F|1993-07-04|1993-05-18|1993-07-22|DELIVER IN PERSON|REG AIR|odolites sleep ironically +1412|22620|7625|3|2|3085.24|0.10|0.07|R|F|1993-04-01|1993-05-03|1993-04-12|DELIVER IN PERSON|REG AIR|s among the requests are a +1412|166155|6156|4|11|13432.65|0.05|0.07|R|F|1993-05-27|1993-05-30|1993-06-07|DELIVER IN PERSON|MAIL|en packages. regular packages dete +1412|157647|163|5|11|18751.04|0.08|0.06|A|F|1993-03-30|1993-05-25|1993-04-21|NONE|FOB|se slyly. special, unusual accounts nag bl +1413|177936|7937|1|18|36250.74|0.08|0.05|N|O|1997-10-11|1997-08-17|1997-10-25|NONE|FOB|yly bold packages haggle quickly acr +1413|164292|1841|2|49|66458.21|0.07|0.06|N|O|1997-08-28|1997-08-23|1997-09-12|DELIVER IN PERSON|MAIL|nstructions br +1413|41545|4050|3|6|8919.24|0.04|0.02|N|O|1997-09-07|1997-07-30|1997-09-21|TAKE BACK RETURN|MAIL|lithely excuses. f +1414|37241|4751|1|39|45951.36|0.10|0.03|N|O|1995-09-22|1995-09-30|1995-10-07|NONE|MAIL|quickly aro +1414|106423|6424|2|4|5717.68|0.02|0.05|N|O|1995-09-16|1995-11-01|1995-10-02|COLLECT COD|AIR| haggle quickly +1415|148235|8236|1|25|32080.75|0.06|0.00|A|F|1994-09-03|1994-07-12|1994-09-13|DELIVER IN PERSON|RAIL|ect never fluff +1440|192213|7252|1|3|3915.63|0.06|0.01|N|O|1995-10-30|1995-10-17|1995-11-08|COLLECT COD|SHIP|instructions boost. fluffily regul +1440|113748|1282|2|46|81040.04|0.02|0.03|N|O|1995-09-21|1995-10-19|1995-10-19|NONE|RAIL|blithely even instructions. +1441|143130|8159|1|5|5865.65|0.04|0.01|N|O|1997-05-17|1997-05-11|1997-05-30|COLLECT COD|MAIL|egular courts. fluffily even grouches +1441|176636|9154|2|5|8563.15|0.02|0.05|N|O|1997-04-25|1997-04-16|1997-05-23|COLLECT COD|FOB|he quickly enticing pac +1441|117735|2758|3|14|24538.22|0.01|0.03|N|O|1997-06-30|1997-04-29|1997-07-24|DELIVER IN PERSON|REG AIR|special requests ha +1441|159879|2395|4|37|71738.19|0.01|0.00|N|O|1997-04-26|1997-04-27|1997-04-29|NONE|REG AIR|accounts. slyly special dolphins b +1441|71377|8899|5|34|45844.58|0.09|0.00|N|O|1997-06-12|1997-05-11|1997-06-29|TAKE BACK RETURN|RAIL|e carefully. blithely ironic dep +1441|24329|9334|6|15|18799.80|0.09|0.08|N|O|1997-05-21|1997-05-06|1997-06-04|NONE|REG AIR| dependencies-- cour +1441|95795|3323|7|50|89539.50|0.03|0.01|N|O|1997-06-07|1997-05-12|1997-06-08|NONE|SHIP| requests. blithely e +1442|25080|85|1|8|8040.64|0.05|0.01|A|F|1994-10-31|1994-09-04|1994-11-25|COLLECT COD|AIR|c deposits haggle after the even +1443|33679|6183|1|47|75795.49|0.04|0.06|N|O|1997-02-05|1997-02-02|1997-03-03|NONE|RAIL|carefully ironic requests sl +1444|169552|7101|1|42|68105.10|0.01|0.02|R|F|1994-12-22|1995-03-03|1994-12-31|NONE|SHIP|ly bold packages boost regular ideas. spe +1444|56665|1676|2|34|55136.44|0.04|0.08|A|F|1995-02-22|1995-02-15|1995-03-19|TAKE BACK RETURN|AIR|y. doggedly pend +1444|154729|7245|3|34|60646.48|0.02|0.07|R|F|1994-12-17|1995-01-12|1995-01-03|COLLECT COD|AIR|ular accounts +1444|118714|3737|4|6|10396.26|0.06|0.03|A|F|1995-01-07|1995-03-05|1995-01-17|COLLECT COD|RAIL|al accounts. br +1444|19173|9174|5|35|38225.95|0.02|0.05|A|F|1995-02-25|1995-03-05|1995-03-24|DELIVER IN PERSON|SHIP|aggle furiou +1444|32266|7273|6|42|50326.92|0.00|0.02|A|F|1994-12-16|1995-02-18|1994-12-22|DELIVER IN PERSON|RAIL|ss requests. ironic ideas wake above +1444|81925|1926|7|12|22883.04|0.00|0.03|R|F|1994-12-23|1995-01-15|1995-01-13|COLLECT COD|TRUCK|ly among the bol +1445|99368|9369|1|24|32816.64|0.01|0.00|A|F|1995-02-21|1995-02-22|1995-03-18|DELIVER IN PERSON|SHIP|al accounts use furiously a +1445|66877|6878|2|48|88505.76|0.10|0.02|A|F|1995-02-28|1995-03-16|1995-03-12|COLLECT COD|MAIL|. final ideas are carefully dar +1445|191125|3645|3|7|8512.84|0.10|0.04|A|F|1995-04-25|1995-02-25|1995-05-10|NONE|SHIP|structions: slyly regular re +1445|27878|5385|4|17|30699.79|0.04|0.07|A|F|1995-04-02|1995-04-04|1995-05-01|COLLECT COD|FOB|ges. furiously regular pint +1445|134431|6945|5|24|35170.32|0.10|0.06|R|F|1995-04-23|1995-02-16|1995-05-18|NONE|REG AIR|rate after the carefully reg +1445|167046|7047|6|39|43408.56|0.03|0.02|A|F|1995-02-05|1995-02-20|1995-02-06|NONE|MAIL|ully unusual reques +1446|71867|1868|1|31|57004.66|0.10|0.02|N|O|1998-05-01|1998-05-17|1998-05-30|NONE|REG AIR|. slyly reg +1447|166076|1109|1|19|21699.33|0.06|0.04|A|F|1993-01-31|1992-12-07|1993-02-04|COLLECT COD|MAIL|. quickly ironic +1447|31049|6056|2|6|5880.24|0.01|0.05|A|F|1992-10-24|1992-12-10|1992-11-05|DELIVER IN PERSON|AIR|as! regular packages poach above the +1447|38700|6210|3|9|14748.30|0.04|0.00|R|F|1992-11-15|1993-01-07|1992-11-29|DELIVER IN PERSON|MAIL|counts wake s +1447|21725|9232|4|8|13173.76|0.09|0.08|R|F|1992-11-20|1993-01-12|1992-12-14|COLLECT COD|FOB|ost carefully +1447|129435|9436|5|23|33681.89|0.02|0.07|A|F|1992-12-07|1992-12-25|1993-01-06|TAKE BACK RETURN|AIR| dazzle quickly deposits. f +1447|199588|4627|6|41|69190.78|0.08|0.02|R|F|1993-01-06|1993-01-05|1993-01-13|TAKE BACK RETURN|MAIL|rts boost s +1472|7243|4744|1|36|41408.64|0.04|0.05|N|O|1996-11-06|1996-11-13|1996-11-12|COLLECT COD|SHIP|riously silent deposits to the pending d +1472|132029|7056|2|26|27586.52|0.03|0.05|N|O|1996-11-08|1996-11-13|1996-12-02|DELIVER IN PERSON|FOB|ic packages w +1472|567|8068|3|6|8805.36|0.08|0.01|N|O|1996-10-24|1996-11-19|1996-11-23|COLLECT COD|FOB|onic theodolites hinder slyly slyly r +1473|53482|8493|1|50|71774.00|0.04|0.03|N|O|1997-05-05|1997-05-20|1997-05-09|NONE|TRUCK|requests wake express deposits. special, ir +1473|67401|4920|2|32|43788.80|0.00|0.08|N|O|1997-04-18|1997-05-12|1997-05-10|DELIVER IN PERSON|REG AIR|out the packages lose furiously ab +1474|14918|2422|1|5|9164.55|0.05|0.04|A|F|1995-04-22|1995-02-20|1995-05-06|COLLECT COD|SHIP|ully final a +1474|122645|5158|2|30|50029.20|0.04|0.02|A|F|1995-03-23|1995-02-11|1995-04-17|DELIVER IN PERSON|TRUCK|usly. evenly express +1474|91052|6071|3|18|18774.90|0.06|0.02|A|F|1995-01-23|1995-03-28|1995-02-03|NONE|RAIL|after the special +1475|167997|5546|1|15|30974.85|0.08|0.06|N|O|1998-02-12|1997-12-17|1998-03-02|TAKE BACK RETURN|SHIP|xpress requests haggle after the final, fi +1475|117282|7283|2|18|23387.04|0.07|0.00|N|O|1998-03-08|1998-01-18|1998-03-10|TAKE BACK RETURN|AIR|al deposits use. ironic packages along the +1475|143964|6479|3|30|60238.80|0.03|0.02|N|O|1998-03-11|1997-12-30|1998-03-15|COLLECT COD|REG AIR| regular theodolites mold across th +1475|186972|6973|4|50|102948.50|0.03|0.05|N|O|1997-12-14|1997-12-13|1997-12-21|COLLECT COD|AIR|. slyly bold re +1475|31490|6497|5|33|46909.17|0.01|0.06|N|O|1998-01-02|1998-01-27|1998-01-11|NONE|FOB|quickly fluffy +1475|49379|1884|6|12|15940.44|0.04|0.04|N|O|1998-01-09|1997-12-30|1998-01-23|NONE|TRUCK|arefully-- excuses sublate +1475|111789|1790|7|23|41417.94|0.02|0.00|N|O|1998-02-13|1998-02-05|1998-03-08|NONE|TRUCK|hely regular hocke +1476|30547|3051|1|20|29550.80|0.02|0.03|N|O|1996-08-11|1996-09-18|1996-08-26|TAKE BACK RETURN|AIR|. bold deposits are carefully amo +1477|71965|6980|1|31|60045.76|0.00|0.06|N|O|1997-12-16|1997-09-30|1997-12-17|COLLECT COD|RAIL| requests. fluffily final +1477|109605|7136|2|8|12916.80|0.09|0.05|N|O|1997-10-25|1997-10-18|1997-11-16|COLLECT COD|MAIL|ironic realms wake unusual, even ac +1477|124479|4480|3|42|63145.74|0.06|0.00|N|O|1997-11-02|1997-11-02|1997-11-20|DELIVER IN PERSON|SHIP|lithely after the ir +1477|106201|6202|4|32|38630.40|0.05|0.08|N|O|1997-09-12|1997-10-26|1997-10-12|TAKE BACK RETURN|AIR|; quickly regula +1477|114850|4851|5|41|76458.85|0.04|0.06|N|O|1997-12-16|1997-10-31|1998-01-12|DELIVER IN PERSON|REG AIR|y. final pearls kindle. accounts +1477|68931|3944|6|49|93096.57|0.06|0.00|N|O|1997-11-18|1997-11-06|1997-11-27|COLLECT COD|FOB|ise according to the sly, bold p +1477|119012|1524|7|33|34023.33|0.06|0.00|N|O|1997-11-12|1997-11-06|1997-11-24|DELIVER IN PERSON|TRUCK|yly regular p +1478|33650|3651|1|21|33256.65|0.00|0.06|N|O|1997-09-20|1997-10-25|1997-10-06|TAKE BACK RETURN|MAIL| fluffily pending acc +1479|148818|1333|1|33|61604.73|0.10|0.01|N|O|1996-03-12|1996-02-28|1996-03-31|DELIVER IN PERSON|FOB| carefully special courts affix. fluff +1504|81389|3898|1|42|57555.96|0.02|0.03|R|F|1992-10-18|1992-10-14|1992-11-10|TAKE BACK RETURN|FOB|ep. carefully ironic excuses haggle quickl +1504|102385|9916|2|22|30522.36|0.04|0.03|A|F|1992-09-09|1992-10-29|1992-09-10|NONE|REG AIR| accounts sleep. furiou +1504|177148|9666|3|9|11026.26|0.07|0.02|R|F|1992-11-02|1992-10-12|1992-11-15|TAKE BACK RETURN|RAIL|y slyly regular courts. +1504|114073|9096|4|10|10870.70|0.04|0.07|A|F|1992-09-22|1992-10-22|1992-10-13|TAKE BACK RETURN|TRUCK|final theodolites. furiously e +1504|19772|7276|5|7|11842.39|0.02|0.00|R|F|1992-11-20|1992-11-23|1992-12-13|COLLECT COD|MAIL|y final packa +1505|119898|4921|1|4|7671.56|0.09|0.00|A|F|1992-12-14|1992-11-11|1993-01-02|COLLECT COD|SHIP|side of the s +1505|122702|5215|2|50|86235.00|0.00|0.02|R|F|1992-11-22|1992-09-24|1992-11-26|TAKE BACK RETURN|FOB|lyly special platelets. requests ar +1506|132024|2025|1|46|48576.92|0.04|0.05|R|F|1993-01-18|1992-11-11|1993-02-09|COLLECT COD|REG AIR|sits whithout the blithely ironic packages +1506|113893|1427|2|30|57206.70|0.07|0.02|A|F|1992-11-22|1992-10-25|1992-12-04|DELIVER IN PERSON|FOB|deposits cajole +1506|190697|3217|3|28|50055.32|0.10|0.06|A|F|1992-09-22|1992-11-19|1992-10-09|TAKE BACK RETURN|AIR| unwind carefully: theodolit +1506|27798|2803|4|37|63854.23|0.00|0.03|R|F|1992-11-04|1992-12-01|1992-11-23|TAKE BACK RETURN|TRUCK|carefully bold dolphins. accounts su +1506|194708|9747|5|15|27040.50|0.05|0.00|R|F|1992-09-24|1992-11-11|1992-10-05|NONE|REG AIR| carefully fluffy packages-- caref +1506|49549|4558|6|38|56944.52|0.05|0.02|R|F|1992-12-02|1992-12-19|1992-12-29|NONE|REG AIR|xpress, regular excuse +1506|168077|3110|7|4|4580.28|0.07|0.00|R|F|1993-01-03|1992-12-06|1993-01-05|COLLECT COD|REG AIR|posits. furiou +1507|67094|2107|1|25|26527.25|0.01|0.08|R|F|1994-01-07|1994-01-06|1994-01-11|NONE|RAIL|xes. slyly busy de +1507|39977|2481|2|33|63260.01|0.04|0.02|A|F|1993-10-29|1993-12-23|1993-11-14|DELIVER IN PERSON|REG AIR| asymptotes nag furiously above t +1507|85770|8279|3|39|68475.03|0.03|0.07|R|F|1993-11-04|1993-12-16|1993-12-03|TAKE BACK RETURN|REG AIR|ly even instructions. +1508|50350|7866|1|16|20805.60|0.02|0.06|N|O|1998-06-21|1998-05-30|1998-07-11|COLLECT COD|MAIL|riously across the ironic, unusua +1508|24829|9834|2|20|35076.40|0.06|0.01|N|O|1998-04-17|1998-06-11|1998-05-17|DELIVER IN PERSON|MAIL|nic platelets. carefully final fra +1508|92173|9701|3|43|50102.31|0.01|0.02|N|O|1998-06-01|1998-06-24|1998-06-03|TAKE BACK RETURN|TRUCK|ndencies h +1508|147102|4645|4|1|1149.10|0.02|0.02|N|O|1998-07-13|1998-06-03|1998-07-17|TAKE BACK RETURN|AIR|s the blithely bold instruction +1508|134671|9698|5|29|49464.43|0.02|0.00|N|O|1998-08-03|1998-07-08|1998-08-22|COLLECT COD|RAIL|r instructions. carefully +1508|2673|174|6|5|7878.35|0.06|0.08|N|O|1998-05-22|1998-07-06|1998-06-04|COLLECT COD|REG AIR|cording to the furiously ironic depe +1508|116953|6954|7|38|74858.10|0.03|0.06|N|O|1998-04-30|1998-06-23|1998-05-18|DELIVER IN PERSON|RAIL|tes wake furiously regular w +1509|27109|2114|1|14|14505.40|0.04|0.01|A|F|1993-10-04|1993-09-25|1993-10-21|NONE|TRUCK|nal realms +1509|10883|884|2|46|82518.48|0.08|0.02|A|F|1993-10-15|1993-10-04|1993-11-01|TAKE BACK RETURN|FOB|uriously regula +1509|106243|6244|3|17|21237.08|0.06|0.05|A|F|1993-07-25|1993-08-28|1993-08-19|DELIVER IN PERSON|AIR| furiously. blithely regular ideas haggle c +1509|19486|1988|4|11|15460.28|0.03|0.08|R|F|1993-11-04|1993-10-03|1993-11-14|TAKE BACK RETURN|FOB|ily ironic packages nod carefully. +1509|89534|7059|5|37|56370.61|0.01|0.08|A|F|1993-08-31|1993-09-10|1993-09-24|NONE|FOB|he slyly even deposits wake a +1509|186349|3904|6|31|44495.54|0.04|0.03|A|F|1993-07-14|1993-08-21|1993-08-06|COLLECT COD|SHIP|ic deposits cajole carefully. quickly bold +1509|156167|1198|7|27|33025.32|0.01|0.01|A|F|1993-09-29|1993-09-08|1993-10-04|TAKE BACK RETURN|FOB|lithely after the +1510|97465|4993|1|11|16087.06|0.09|0.04|N|O|1996-09-23|1996-12-03|1996-10-01|DELIVER IN PERSON|RAIL|e of the unusual accounts. stealthy deposit +1510|83096|621|2|24|25898.16|0.05|0.04|N|O|1996-10-07|1996-10-22|1996-11-03|DELIVER IN PERSON|REG AIR|yly brave theod +1510|189992|2511|3|36|74951.64|0.07|0.02|N|O|1996-10-02|1996-11-23|1996-10-05|NONE|SHIP|old deposits along the carefully +1510|181428|8983|4|8|12075.36|0.01|0.08|N|O|1996-10-26|1996-11-07|1996-10-30|TAKE BACK RETURN|RAIL|blithely express +1510|58453|8454|5|27|38109.15|0.08|0.06|N|O|1996-10-20|1996-12-05|1996-11-02|NONE|MAIL|he blithely regular req +1510|13698|3699|6|3|4835.07|0.05|0.02|N|O|1996-10-31|1996-12-03|1996-11-13|COLLECT COD|RAIL|along the slyly regular pin +1510|21462|6467|7|50|69173.00|0.04|0.05|N|O|1996-11-01|1996-10-17|1996-11-28|NONE|MAIL|even packages. carefully regular fo +1511|97166|4694|1|29|33731.64|0.01|0.04|N|O|1997-03-17|1997-02-11|1997-03-27|DELIVER IN PERSON|AIR|s cajole furiously against +1511|61718|6731|2|32|53750.72|0.04|0.01|N|O|1997-01-06|1997-03-21|1997-01-26|TAKE BACK RETURN|REG AIR| deposits. carefully ironi +1536|193719|3720|1|5|9063.55|0.08|0.03|N|O|1997-02-08|1997-03-11|1997-03-02|COLLECT COD|MAIL|requests sleep pe +1537|17492|9994|1|17|23961.33|0.01|0.03|A|F|1992-04-12|1992-04-19|1992-04-13|NONE|TRUCK|he regular pack +1537|178379|3414|2|50|72868.50|0.08|0.00|R|F|1992-05-30|1992-05-14|1992-06-23|TAKE BACK RETURN|MAIL|special packages haggle slyly at the silent +1537|12480|2481|3|44|61269.12|0.05|0.04|R|F|1992-04-01|1992-03-31|1992-04-21|NONE|TRUCK|lar courts. +1537|139612|2126|4|3|4954.83|0.08|0.07|R|F|1992-03-20|1992-04-14|1992-03-21|TAKE BACK RETURN|SHIP|s, final ideas detect sl +1538|101743|4254|1|32|55831.68|0.05|0.05|N|O|1995-07-08|1995-07-29|1995-08-01|TAKE BACK RETURN|RAIL|uses maintain blithely. fluffily +1538|191738|1739|2|27|49402.71|0.05|0.01|N|O|1995-09-19|1995-08-03|1995-09-24|DELIVER IN PERSON|TRUCK|ngly even packag +1538|129762|7299|3|36|64503.36|0.08|0.04|N|O|1995-07-11|1995-09-10|1995-07-26|DELIVER IN PERSON|MAIL|al deposits mo +1538|103730|1261|4|28|48544.44|0.10|0.04|N|O|1995-09-19|1995-08-27|1995-10-10|COLLECT COD|RAIL|bout the fluffily unusual +1538|177315|2350|5|13|18100.03|0.01|0.05|N|O|1995-06-26|1995-07-30|1995-07-25|NONE|SHIP|ly. packages sleep f +1538|127205|9718|6|42|51752.40|0.08|0.08|N|O|1995-10-10|1995-09-12|1995-11-08|DELIVER IN PERSON|TRUCK|equests cajole blithely +1539|195722|761|1|21|38172.12|0.08|0.02|R|F|1995-04-19|1995-05-10|1995-04-27|COLLECT COD|TRUCK|ounts haggle. busy +1539|85981|998|2|11|21636.78|0.01|0.08|A|F|1995-05-27|1995-04-13|1995-06-10|TAKE BACK RETURN|TRUCK|ly express requests. furiously +1539|67462|2475|3|7|10006.22|0.09|0.04|R|F|1995-05-14|1995-04-16|1995-05-30|DELIVER IN PERSON|AIR|. fluffily reg +1540|172385|9937|1|38|55380.44|0.03|0.01|R|F|1992-09-30|1992-10-27|1992-10-12|TAKE BACK RETURN|SHIP| final grouches bo +1540|59905|7421|2|35|65271.50|0.02|0.07|R|F|1992-10-31|1992-09-04|1992-11-05|TAKE BACK RETURN|SHIP|e blithely a +1540|7166|2167|3|25|26829.00|0.08|0.04|R|F|1992-11-15|1992-10-24|1992-12-14|DELIVER IN PERSON|SHIP|ironic deposits amo +1540|24603|2110|4|6|9165.60|0.09|0.03|R|F|1992-08-28|1992-09-17|1992-09-14|COLLECT COD|MAIL|ing to the slyly express asymptote +1540|86906|9415|5|27|51108.30|0.10|0.08|R|F|1992-12-02|1992-10-18|1992-12-31|NONE|SHIP|carefully final packages; b +1541|63380|5887|1|44|59108.72|0.10|0.05|N|O|1995-08-24|1995-07-13|1995-08-26|TAKE BACK RETURN|MAIL|o beans boost fluffily abou +1541|25684|5685|2|8|12877.44|0.10|0.08|N|F|1995-06-05|1995-08-07|1995-06-21|TAKE BACK RETURN|TRUCK|y pending packages. blithely fi +1542|57750|7751|1|37|63186.75|0.07|0.06|A|F|1993-12-15|1993-10-17|1994-01-07|TAKE BACK RETURN|REG AIR|e blithely unusual accounts. quic +1542|2488|4989|2|12|16685.76|0.09|0.06|R|F|1993-10-29|1993-11-02|1993-11-09|TAKE BACK RETURN|RAIL|carefully +1542|5566|5567|3|18|26488.08|0.05|0.05|R|F|1993-10-17|1993-11-15|1993-10-26|TAKE BACK RETURN|FOB|pending instr +1542|142665|5180|4|21|35860.86|0.01|0.05|R|F|1993-10-13|1993-12-13|1993-11-12|NONE|RAIL|y pending foxes nag blithely +1542|154955|2501|5|46|92457.70|0.00|0.00|R|F|1993-09-28|1993-11-03|1993-10-15|COLLECT COD|FOB|ial instructions. ironically +1543|70883|5898|1|34|63031.92|0.02|0.08|N|O|1997-05-25|1997-03-30|1997-06-04|NONE|AIR|ic requests are ac +1543|114492|7004|2|6|9038.94|0.09|0.01|N|O|1997-04-16|1997-05-20|1997-05-16|DELIVER IN PERSON|MAIL| among the carefully bold or +1543|66020|6021|3|42|41412.84|0.06|0.01|N|O|1997-05-26|1997-03-30|1997-06-12|DELIVER IN PERSON|FOB|its sleep until the fur +1543|188591|3628|4|42|70542.78|0.05|0.06|N|O|1997-04-11|1997-04-11|1997-04-23|TAKE BACK RETURN|MAIL|xpress instructions. regular acc +1543|39868|9869|5|9|16270.74|0.08|0.06|N|O|1997-03-14|1997-05-19|1997-03-26|DELIVER IN PERSON|FOB|ravely special requests +1543|48782|6295|6|3|5192.34|0.10|0.04|N|O|1997-03-29|1997-05-10|1997-04-22|COLLECT COD|MAIL|sleep along the furiou +1543|67763|270|7|3|5192.28|0.00|0.02|N|O|1997-03-22|1997-04-06|1997-03-30|NONE|AIR|quickly. final accounts haggle slyl +1568|89369|1878|1|36|48900.96|0.02|0.03|N|O|1997-05-31|1997-04-22|1997-06-21|TAKE BACK RETURN|RAIL|platelets-- furiously sly excu +1568|8928|1429|2|46|84498.32|0.04|0.00|N|O|1997-04-06|1997-04-08|1997-04-23|TAKE BACK RETURN|MAIL|g the blithely even acco +1569|74460|1982|1|5|7172.30|0.07|0.00|N|O|1998-04-16|1998-06-21|1998-04-18|COLLECT COD|REG AIR| packages. ironic, even excuses a +1569|38749|8750|2|16|27003.84|0.01|0.08|N|O|1998-04-26|1998-06-16|1998-05-26|COLLECT COD|MAIL|deposits. blithely final asymptotes ac +1569|48818|8819|3|43|75972.83|0.10|0.03|N|O|1998-06-05|1998-05-31|1998-06-28|DELIVER IN PERSON|FOB| instructions. +1569|69193|9194|4|30|34865.70|0.02|0.03|N|O|1998-07-19|1998-06-04|1998-08-10|NONE|SHIP|packages. excuses lose evenly carefully reg +1570|182632|5151|1|25|42865.75|0.00|0.06|N|O|1998-05-03|1998-06-02|1998-06-02|DELIVER IN PERSON|REG AIR|its. slyly regular sentiments +1570|85017|34|2|7|7014.07|0.05|0.05|N|O|1998-07-10|1998-06-01|1998-07-23|TAKE BACK RETURN|MAIL|requests boost quickly re +1571|51371|1372|1|47|62151.39|0.00|0.05|R|F|1992-12-07|1993-02-24|1993-01-01|TAKE BACK RETURN|REG AIR|ng to the fluffily unusual +1571|182725|280|2|6|10846.32|0.03|0.00|A|F|1993-01-08|1993-02-13|1993-02-07|COLLECT COD|SHIP| special, ironic depo +1571|58030|536|3|18|17784.54|0.05|0.08|A|F|1993-01-09|1993-01-12|1993-01-31|COLLECT COD|AIR| pending grouches +1571|100330|2841|4|48|63855.84|0.05|0.05|A|F|1992-12-28|1993-01-04|1993-01-04|DELIVER IN PERSON|RAIL|slyly pending p +1571|41509|6518|5|10|14505.00|0.03|0.06|R|F|1992-12-12|1993-02-13|1992-12-29|DELIVER IN PERSON|AIR|lets. carefully regular ideas wake +1571|33276|786|6|24|29022.48|0.05|0.07|A|F|1993-03-22|1993-01-31|1993-04-09|NONE|TRUCK|warthogs wake carefully acro +1572|23675|3676|1|41|65545.47|0.02|0.00|N|O|1996-05-16|1996-04-09|1996-05-28|TAKE BACK RETURN|REG AIR|. pinto beans alongside +1572|92330|9858|2|10|13223.30|0.04|0.06|N|O|1996-05-17|1996-03-26|1996-05-19|NONE|AIR| accounts affix slyly. +1573|185330|5331|1|5|7076.65|0.05|0.01|A|F|1993-04-24|1993-03-13|1993-05-17|TAKE BACK RETURN|MAIL|ymptotes could u +1573|30683|684|2|17|27432.56|0.00|0.06|R|F|1993-02-24|1993-02-16|1993-03-08|TAKE BACK RETURN|TRUCK|carefully regular deposits. +1573|82204|2205|3|16|18979.20|0.04|0.03|A|F|1993-03-15|1993-03-16|1993-03-31|COLLECT COD|AIR|ely. furiously final requests wake slyl +1573|193749|8788|4|11|20270.14|0.09|0.01|R|F|1993-03-23|1993-03-24|1993-04-12|TAKE BACK RETURN|RAIL|nently pending +1573|136810|1837|5|7|12927.67|0.00|0.01|R|F|1993-01-30|1993-03-14|1993-02-27|DELIVER IN PERSON|SHIP|eodolites sleep slyly. slyly f +1573|153063|609|6|30|33481.80|0.03|0.01|A|F|1992-12-29|1993-03-06|1993-01-02|DELIVER IN PERSON|TRUCK|. blithely even theodolites boos +1574|47706|5219|1|41|67801.70|0.06|0.02|N|O|1997-03-08|1997-02-09|1997-04-01|COLLECT COD|AIR|s. slyly regular depen +1574|190353|7911|2|50|72167.50|0.00|0.05|N|O|1996-12-14|1997-02-14|1996-12-16|TAKE BACK RETURN|FOB|le regular, regular foxes. blithely e +1574|54013|6519|3|25|24175.25|0.06|0.02|N|O|1997-01-16|1997-02-14|1997-02-12|DELIVER IN PERSON|TRUCK|ly silent accounts. +1574|190880|5919|4|6|11825.28|0.03|0.05|N|O|1997-02-24|1997-02-03|1997-03-01|NONE|AIR|e silent, final packages. speci +1574|108301|3322|5|6|7855.80|0.05|0.05|N|O|1997-02-09|1997-03-02|1997-02-14|COLLECT COD|MAIL|nic, final ideas snooze. +1574|4733|2234|6|42|68784.66|0.07|0.01|N|O|1996-12-19|1997-01-13|1996-12-28|NONE|FOB|o beans according t +1574|135755|782|7|14|25070.50|0.04|0.01|N|O|1996-12-30|1997-01-19|1997-01-20|NONE|AIR|ily bold a +1575|28443|8444|1|42|57600.48|0.05|0.08|N|O|1995-10-21|1995-11-25|1995-10-24|DELIVER IN PERSON|RAIL|ly pending pinto beans. +1575|35236|243|2|39|45677.97|0.00|0.06|N|O|1995-10-30|1995-10-15|1995-11-10|COLLECT COD|TRUCK| ironic requests snooze ironic, regular acc +1575|1887|4388|3|12|21466.56|0.01|0.05|N|O|1995-12-27|1995-11-11|1996-01-23|TAKE BACK RETURN|AIR| bold accounts. furi +1575|110162|7696|4|39|45714.24|0.07|0.00|N|O|1995-09-23|1995-11-05|1995-09-25|TAKE BACK RETURN|TRUCK| after the unusual asym +1575|82215|4724|5|10|11972.10|0.09|0.00|N|O|1996-01-10|1995-11-20|1996-01-13|DELIVER IN PERSON|RAIL|k excuses. pinto beans wake a +1575|177660|5212|6|14|24327.24|0.08|0.06|N|O|1995-10-31|1995-12-06|1995-11-30|NONE|AIR|beans breach among the furiously specia +1575|116986|9498|7|48|96143.04|0.08|0.04|N|O|1995-11-19|1995-10-25|1995-12-07|DELIVER IN PERSON|TRUCK|cies. regu +1600|171408|8960|1|20|29588.00|0.02|0.01|R|F|1993-06-16|1993-04-23|1993-07-02|COLLECT COD|FOB|pths sleep blithely about the +1600|43128|641|2|48|51413.76|0.07|0.02|R|F|1993-04-17|1993-04-14|1993-05-03|DELIVER IN PERSON|FOB|furiously silent foxes could wake. car +1600|38465|3472|3|8|11227.68|0.04|0.07|R|F|1993-03-07|1993-04-22|1993-03-26|TAKE BACK RETURN|FOB|cajole furiously fluf +1600|68481|988|4|25|36237.00|0.00|0.06|A|F|1993-05-25|1993-04-07|1993-06-05|TAKE BACK RETURN|REG AIR|press packages. ironic excuses bo +1600|146041|6042|5|30|32611.20|0.03|0.08|R|F|1993-06-03|1993-05-03|1993-06-07|DELIVER IN PERSON|RAIL|al escapades alongside of the depo +1601|166156|6157|1|6|7332.90|0.00|0.00|A|F|1994-10-19|1994-09-28|1994-10-23|COLLECT COD|SHIP| bold sheaves. furiously per +1601|174374|1926|2|50|72418.50|0.03|0.02|R|F|1994-12-24|1994-10-23|1995-01-11|COLLECT COD|FOB|ideas doubt +1601|89887|2396|3|14|26276.32|0.04|0.08|R|F|1994-09-17|1994-11-22|1994-10-03|DELIVER IN PERSON|RAIL|he special, fin +1602|182806|2807|1|4|7555.20|0.08|0.06|R|F|1993-10-31|1993-09-05|1993-11-21|NONE|RAIL|y. even excuses +1603|38191|5701|1|1|1129.19|0.08|0.00|R|F|1993-08-17|1993-09-04|1993-08-22|TAKE BACK RETURN|REG AIR|d accounts. special warthogs use fur +1603|65209|7716|2|29|34051.80|0.06|0.08|A|F|1993-09-28|1993-09-20|1993-10-28|NONE|SHIP|ses wake furiously. theodolite +1604|41563|1564|1|15|22568.40|0.09|0.08|R|F|1993-09-22|1993-09-03|1993-09-29|TAKE BACK RETURN|MAIL| instructions haggle +1604|140413|5442|2|37|53776.17|0.06|0.06|A|F|1993-08-22|1993-09-21|1993-09-10|COLLECT COD|SHIP|requests. blithely ironic somas s +1604|113214|5726|3|19|23316.99|0.09|0.07|A|F|1993-10-15|1993-10-04|1993-11-09|COLLECT COD|RAIL| ideas. bol +1604|174239|9274|4|15|19698.45|0.03|0.00|R|F|1993-09-10|1993-08-31|1993-09-30|TAKE BACK RETURN|RAIL|ending realms along the special, p +1604|20091|7598|5|23|23255.07|0.08|0.05|A|F|1993-10-11|1993-08-30|1993-10-18|DELIVER IN PERSON|RAIL|en requests. blithely fin +1605|141821|9364|1|47|87552.54|0.00|0.01|N|O|1998-04-29|1998-06-12|1998-05-20|DELIVER IN PERSON|AIR|. carefully r +1605|179691|7243|2|18|31872.42|0.10|0.00|N|O|1998-05-13|1998-06-17|1998-06-03|COLLECT COD|REG AIR|ly regular foxes wake carefully. bol +1605|58546|8547|3|39|58677.06|0.02|0.03|N|O|1998-07-12|1998-06-05|1998-08-09|DELIVER IN PERSON|MAIL|nal dependencies-- quickly final frets acc +1605|182574|129|4|25|41414.25|0.06|0.02|N|O|1998-05-26|1998-06-14|1998-06-05|COLLECT COD|AIR|ole carefully car +1606|114082|4083|1|21|23017.68|0.04|0.00|N|O|1997-06-02|1997-07-02|1997-06-27|DELIVER IN PERSON|RAIL| pending theodolites prom +1606|173565|8600|2|35|57349.60|0.00|0.02|N|O|1997-06-20|1997-06-19|1997-06-22|COLLECT COD|TRUCK|carefully sil +1606|99477|7005|3|23|33958.81|0.00|0.06|N|O|1997-04-19|1997-06-26|1997-04-30|NONE|MAIL|ously final requests. slowly ironic ex +1606|96286|8796|4|20|25645.60|0.02|0.04|N|O|1997-05-01|1997-05-26|1997-05-28|TAKE BACK RETURN|TRUCK|fily carefu +1606|70181|5196|5|14|16116.52|0.10|0.01|N|O|1997-05-19|1997-07-05|1997-06-10|COLLECT COD|FOB|structions haggle f +1607|189131|6686|1|2|2440.26|0.02|0.00|N|O|1996-01-11|1996-02-15|1996-01-19|DELIVER IN PERSON|MAIL|packages haggle. regular requests boost s +1607|118923|1435|2|37|71851.04|0.05|0.02|N|O|1996-02-27|1996-02-18|1996-03-16|NONE|AIR|alongside +1607|122680|2681|3|39|66404.52|0.00|0.00|N|O|1996-02-01|1996-02-12|1996-02-16|NONE|FOB|uches cajole. accounts ar +1607|75587|8095|4|34|53127.72|0.05|0.06|N|O|1996-01-06|1996-02-24|1996-01-10|DELIVER IN PERSON|SHIP| quickly above the +1607|177948|466|5|48|97245.12|0.00|0.05|N|O|1996-02-22|1996-02-13|1996-03-09|TAKE BACK RETURN|MAIL|ular forges. deposits a +1632|190513|8071|1|47|75364.97|0.08|0.00|N|O|1997-01-25|1997-02-09|1997-02-19|TAKE BACK RETURN|RAIL|g to the closely special no +1632|147914|5457|2|14|27466.74|0.08|0.05|N|O|1997-01-15|1997-02-25|1997-01-28|NONE|RAIL|oxes. deposits nag slyly along the slyly +1632|176169|1204|3|47|58522.52|0.03|0.04|N|O|1997-01-29|1997-03-03|1997-02-21|NONE|MAIL|sts. blithely regular +1632|56164|3680|4|33|36965.28|0.09|0.02|N|O|1997-04-01|1997-02-24|1997-04-29|TAKE BACK RETURN|REG AIR|ructions! slyly +1632|141072|8615|5|43|47862.01|0.10|0.03|N|O|1997-02-24|1997-02-19|1997-03-25|DELIVER IN PERSON|FOB|ts. blithe, bold ideas cajo +1633|177903|2938|1|35|69331.50|0.01|0.02|N|O|1996-01-09|1995-12-02|1996-01-21|COLLECT COD|REG AIR|ly against the dolph +1633|4124|4125|2|15|15421.80|0.00|0.05|N|O|1995-12-13|1995-11-13|1996-01-04|TAKE BACK RETURN|FOB|ges wake fluffil +1634|47063|7064|1|21|21211.26|0.00|0.00|N|O|1996-10-04|1996-10-22|1996-11-01|NONE|MAIL|counts alo +1634|171632|1633|2|44|74959.72|0.05|0.01|N|O|1996-09-17|1996-11-09|1996-10-03|COLLECT COD|SHIP|requests affix slyly. quickly even pack +1634|18568|8569|3|21|31217.76|0.06|0.07|N|O|1996-11-16|1996-10-21|1996-11-27|NONE|TRUCK|y along the excuses. +1634|67465|4984|4|17|24351.82|0.08|0.07|N|O|1996-10-29|1996-10-15|1996-11-02|TAKE BACK RETURN|SHIP|cial, bold platelets alongside of the f +1634|75908|5909|5|2|3767.80|0.07|0.04|N|O|1996-11-22|1996-10-28|1996-12-17|NONE|SHIP|ly. carefully regular asymptotes wake +1634|169681|2198|6|11|19257.48|0.01|0.08|N|O|1996-10-04|1996-12-06|1996-10-14|DELIVER IN PERSON|SHIP|final requests +1634|12416|4918|7|35|46494.35|0.06|0.02|N|O|1996-11-25|1996-11-25|1996-12-12|TAKE BACK RETURN|RAIL|cies. regular, special de +1635|70167|2675|1|3|3411.48|0.06|0.08|N|O|1997-03-13|1997-03-25|1997-03-27|COLLECT COD|FOB| quickly ironic r +1635|89018|9019|2|8|8056.08|0.04|0.05|N|O|1997-04-30|1997-04-21|1997-05-09|DELIVER IN PERSON|AIR|ravely carefully express +1635|113791|3792|3|20|36095.80|0.07|0.01|N|O|1997-05-19|1997-04-01|1997-06-17|TAKE BACK RETURN|FOB|oost according to the carefully even accou +1635|76063|3585|4|40|41562.40|0.01|0.04|N|O|1997-02-25|1997-03-20|1997-03-12|TAKE BACK RETURN|RAIL|uriously up the ironic deposits. slyly i +1636|84083|1608|1|2|2134.16|0.09|0.03|N|O|1997-09-26|1997-08-22|1997-10-05|NONE|TRUCK|nal foxes cajole above the blithely reg +1636|168925|8926|2|45|89726.40|0.03|0.01|N|O|1997-07-14|1997-08-08|1997-07-27|COLLECT COD|RAIL|ely express reque +1636|107869|380|3|24|45044.64|0.07|0.08|N|O|1997-10-07|1997-08-12|1997-11-04|TAKE BACK RETURN|MAIL|e carefully unusual ideas are f +1636|152367|4883|4|43|61032.48|0.06|0.00|N|O|1997-08-23|1997-08-10|1997-09-17|NONE|REG AIR|blithely special r +1636|18378|3381|5|22|28520.14|0.05|0.02|N|O|1997-07-22|1997-08-18|1997-08-03|COLLECT COD|AIR|ular, regu +1636|62910|5417|6|34|63678.94|0.10|0.01|N|O|1997-08-11|1997-09-09|1997-08-23|NONE|TRUCK|ular depos +1636|113018|8041|7|7|7217.07|0.04|0.00|N|O|1997-07-28|1997-09-10|1997-07-31|NONE|MAIL|ronic instructions. final +1637|85755|5756|1|49|85296.75|0.02|0.03|N|F|1995-06-08|1995-04-19|1995-07-01|COLLECT COD|REG AIR|. blithely i +1637|72269|7284|2|1|1241.26|0.10|0.02|A|F|1995-02-14|1995-03-26|1995-03-09|TAKE BACK RETURN|AIR|ly final pinto beans. furiously +1637|21652|6657|3|10|15736.50|0.02|0.05|R|F|1995-02-21|1995-03-17|1995-03-11|NONE|AIR|uriously? blithely even sauternes wake. +1637|92629|5139|4|42|68108.04|0.06|0.01|A|F|1995-03-18|1995-04-24|1995-03-31|COLLECT COD|SHIP|blithely a +1637|4005|6506|5|25|22725.00|0.05|0.00|R|F|1995-06-07|1995-03-26|1995-06-08|COLLECT COD|RAIL| haggle carefully silent accou +1637|108780|3801|6|38|67973.64|0.02|0.08|R|F|1995-03-20|1995-05-05|1995-04-14|DELIVER IN PERSON|SHIP|even, pending foxes nod regular +1637|51705|4211|7|21|34790.70|0.07|0.08|A|F|1995-04-30|1995-04-30|1995-05-05|COLLECT COD|SHIP|ly ironic theodolites use b +1638|5840|5841|1|46|80308.64|0.03|0.02|N|O|1997-10-16|1997-10-28|1997-11-09|COLLECT COD|MAIL|otes haggle before the slyly bold instructi +1638|148976|8977|2|30|60749.10|0.00|0.04|N|O|1997-12-05|1997-09-17|1997-12-06|NONE|REG AIR|s cajole boldly bold requests. closely +1638|30158|2662|3|5|5440.75|0.08|0.07|N|O|1997-10-15|1997-11-01|1997-11-08|DELIVER IN PERSON|FOB|xcuses sleep furiou +1638|55974|3490|4|19|36669.43|0.00|0.08|N|O|1997-10-15|1997-10-27|1997-11-03|DELIVER IN PERSON|MAIL| quickly expres +1638|142867|7896|5|25|47746.50|0.05|0.03|N|O|1997-10-06|1997-09-30|1997-11-02|DELIVER IN PERSON|REG AIR|gle final, ironic pinto beans. +1638|154436|9467|6|46|68559.78|0.07|0.08|N|O|1997-08-20|1997-10-10|1997-09-09|COLLECT COD|AIR|ckages are carefully even instru +1639|186473|6474|1|24|37427.28|0.07|0.00|N|O|1995-08-24|1995-10-06|1995-08-31|COLLECT COD|REG AIR| the regular packages. courts dou +1639|42945|7954|2|38|71741.72|0.01|0.04|N|O|1995-08-23|1995-11-09|1995-08-29|TAKE BACK RETURN|FOB|y regular packages. b +1639|170376|5411|3|41|59301.17|0.04|0.02|N|O|1995-12-19|1995-11-11|1996-01-12|DELIVER IN PERSON|FOB|structions w +1664|117307|2330|1|48|63566.40|0.04|0.02|N|O|1996-06-21|1996-05-01|1996-07-19|TAKE BACK RETURN|RAIL| use. ironic deposits integrate. slyly unu +1664|172152|7187|2|30|36724.50|0.06|0.05|N|O|1996-04-04|1996-05-04|1996-05-03|COLLECT COD|FOB|ess multip +1664|150899|900|3|10|19498.90|0.00|0.06|N|O|1996-04-10|1996-05-13|1996-05-07|TAKE BACK RETURN|RAIL|instructions up the acc +1664|154273|6789|4|35|46454.45|0.00|0.04|N|O|1996-03-06|1996-05-16|1996-03-09|DELIVER IN PERSON|REG AIR|y regular ide +1664|56747|6748|5|9|15333.66|0.07|0.04|N|O|1996-04-15|1996-05-14|1996-05-11|DELIVER IN PERSON|TRUCK|ges. fluffil +1664|140115|2630|6|40|46204.40|0.09|0.07|N|O|1996-04-02|1996-04-22|1996-04-17|COLLECT COD|REG AIR|se blithely unusual pains. carefully +1665|46402|3915|1|4|5393.60|0.02|0.03|A|F|1994-09-01|1994-06-07|1994-09-12|DELIVER IN PERSON|TRUCK|ely final requests. requests +1665|77098|4620|2|1|1075.09|0.03|0.05|R|F|1994-05-22|1994-07-06|1994-05-24|TAKE BACK RETURN|TRUCK|sly final p +1666|184344|1899|1|30|42850.20|0.04|0.03|N|O|1995-10-28|1995-11-30|1995-11-18|TAKE BACK RETURN|AIR| breach evenly final accounts. r +1666|63994|9007|2|20|39159.80|0.01|0.00|N|O|1996-01-27|1995-12-12|1996-01-31|NONE|REG AIR|uietly regular foxes wake quick +1666|133479|1019|3|31|46886.57|0.05|0.07|N|O|1996-02-11|1996-01-11|1996-02-28|COLLECT COD|RAIL|ding to the express, bold accounts. fu +1666|168802|1319|4|41|76702.80|0.06|0.08|N|O|1995-11-29|1996-01-04|1995-12-24|NONE|TRUCK|ly regular excuses; regular ac +1667|20267|7774|1|6|7123.56|0.04|0.02|N|O|1997-12-07|1997-11-16|1998-01-02|COLLECT COD|FOB|riously busy requests. blithely final a +1667|21164|6169|2|29|31469.64|0.06|0.07|N|O|1997-10-15|1997-11-09|1997-11-11|TAKE BACK RETURN|MAIL|l accounts. furiously final courts h +1667|94941|9960|3|48|92925.12|0.05|0.01|N|O|1998-01-27|1998-01-06|1998-02-09|TAKE BACK RETURN|SHIP|tes sleep furiously. carefully eve +1667|58119|5635|4|24|25850.64|0.04|0.01|N|O|1997-10-14|1997-12-01|1997-11-09|TAKE BACK RETURN|MAIL|hrash final requests. care +1667|194315|1873|5|2|2818.62|0.07|0.00|N|O|1997-12-17|1997-11-22|1998-01-16|NONE|SHIP|pecial requests hag +1667|47733|5246|6|6|10084.38|0.01|0.03|N|O|1998-01-21|1997-12-19|1998-01-28|NONE|TRUCK| nag quickly above th +1667|39956|2460|7|19|36023.05|0.09|0.03|N|O|1998-01-23|1997-11-24|1998-01-26|DELIVER IN PERSON|SHIP|around the pinto beans. express, special +1668|131636|4150|1|8|13341.04|0.06|0.01|N|O|1997-07-23|1997-10-09|1997-08-06|DELIVER IN PERSON|FOB|arefully regular tithes! slyl +1668|945|8446|2|25|46148.50|0.01|0.06|N|O|1997-08-08|1997-09-28|1997-09-01|NONE|TRUCK|y ironic requests. bold, final ideas a +1668|74160|6668|3|42|47634.72|0.08|0.01|N|O|1997-08-09|1997-09-08|1997-08-31|NONE|FOB|ole carefully excuses. final +1668|190774|8332|4|9|16782.93|0.05|0.03|N|O|1997-10-17|1997-09-05|1997-11-01|COLLECT COD|RAIL|wake furiously even instructions. sil +1668|127924|7925|5|25|48798.00|0.01|0.02|N|O|1997-10-08|1997-09-20|1997-10-11|DELIVER IN PERSON|REG AIR|even platelets across the silent +1668|9920|2421|6|38|69536.96|0.07|0.01|N|O|1997-08-26|1997-09-17|1997-09-05|DELIVER IN PERSON|TRUCK|ep slyly across the furi +1669|78373|8374|1|24|32432.88|0.04|0.08|N|O|1997-09-04|1997-07-30|1997-09-20|DELIVER IN PERSON|RAIL| regular, final deposits use quick +1670|31411|6418|1|41|55038.81|0.07|0.01|N|O|1997-07-19|1997-08-20|1997-07-23|DELIVER IN PERSON|TRUCK|thely according to the sly +1670|121378|1379|2|10|13993.70|0.07|0.03|N|O|1997-09-14|1997-08-16|1997-09-23|NONE|SHIP|fily special ideas +1670|185284|321|3|41|56140.48|0.07|0.07|N|O|1997-07-19|1997-08-05|1997-07-26|COLLECT COD|SHIP|al gifts. speci +1671|148885|3914|1|21|40611.48|0.02|0.07|N|O|1996-07-28|1996-09-28|1996-08-08|TAKE BACK RETURN|AIR|s accounts slee +1671|95111|2639|2|4|4424.44|0.05|0.00|N|O|1996-08-30|1996-09-19|1996-09-23|DELIVER IN PERSON|TRUCK|lyly regular ac +1671|123591|8616|3|11|17760.49|0.06|0.08|N|O|1996-09-16|1996-10-21|1996-09-18|NONE|SHIP|tes sleep blithely +1671|177303|2338|4|5|6901.50|0.00|0.00|N|O|1996-11-14|1996-10-20|1996-11-25|TAKE BACK RETURN|FOB|luffily regular deposits +1671|126590|6591|5|12|19399.08|0.07|0.04|N|O|1996-11-17|1996-09-02|1996-12-17|COLLECT COD|RAIL|special, ironic +1671|196217|8737|6|46|60407.66|0.08|0.05|N|O|1996-09-13|1996-10-14|1996-09-28|TAKE BACK RETURN|REG AIR|. slyly bold instructions boost. furiousl +1696|15419|422|1|8|10675.28|0.04|0.02|N|O|1998-04-28|1998-02-07|1998-05-10|NONE|TRUCK|the blithely +1696|138312|826|2|13|17554.03|0.08|0.06|N|O|1998-03-01|1998-03-25|1998-03-24|TAKE BACK RETURN|TRUCK|tructions play slyly q +1696|1107|3608|3|19|19153.90|0.08|0.05|N|O|1998-05-03|1998-03-13|1998-05-28|TAKE BACK RETURN|REG AIR|its maintain alongside of the f +1696|192712|2713|4|21|37898.91|0.05|0.00|N|O|1998-05-04|1998-02-18|1998-05-07|NONE|MAIL|y players sleep along the final, pending +1696|93788|8807|5|43|76616.54|0.03|0.06|N|O|1998-02-14|1998-03-29|1998-02-20|COLLECT COD|FOB|arefully regular dep +1697|74452|6960|1|6|8558.70|0.05|0.00|N|O|1997-01-28|1996-11-27|1997-01-31|NONE|FOB|accounts breach slyly even de +1697|103417|5928|2|24|34089.84|0.00|0.08|N|O|1996-12-29|1996-12-19|1997-01-10|NONE|SHIP|ts cajole carefully above the carefully +1697|123693|6206|3|27|46350.63|0.06|0.00|N|O|1997-01-20|1996-12-02|1997-02-05|COLLECT COD|MAIL|ly regular packages across the silent, b +1697|93083|3084|4|49|52727.92|0.08|0.04|N|O|1996-12-07|1997-01-02|1996-12-31|COLLECT COD|TRUCK|lar foxes. fluffily furious ideas doubt qu +1697|34808|7312|5|19|33113.20|0.03|0.07|N|O|1997-01-08|1996-11-12|1997-01-11|DELIVER IN PERSON|FOB|ons? special, special accounts after +1698|96537|6538|1|44|67475.32|0.05|0.05|N|O|1997-05-16|1997-07-05|1997-05-27|NONE|RAIL|ts wake slyly after t +1698|92106|4616|2|6|6588.60|0.08|0.00|N|O|1997-08-21|1997-06-08|1997-09-03|DELIVER IN PERSON|RAIL| pending packages affix ne +1698|20546|3049|3|22|32263.88|0.03|0.04|N|O|1997-08-07|1997-05-28|1997-08-24|DELIVER IN PERSON|TRUCK|oward the furiously iro +1698|111909|4421|4|19|36497.10|0.00|0.07|N|O|1997-07-04|1997-06-21|1997-08-01|NONE|RAIL| fluffily e +1698|52417|2418|5|37|50668.17|0.00|0.03|N|O|1997-05-16|1997-05-29|1997-05-27|NONE|AIR|ly regular ideas. deposit +1698|165824|5825|6|15|28347.30|0.10|0.01|N|O|1997-07-20|1997-06-07|1997-07-21|TAKE BACK RETURN|RAIL|final ideas. even, ironic +1699|37350|2357|1|50|64367.50|0.00|0.06|A|F|1994-03-26|1994-03-23|1994-04-20|NONE|FOB|to the final requests are carefully silent +1699|134825|4826|2|17|31616.94|0.07|0.02|R|F|1994-01-12|1994-03-12|1994-02-08|NONE|AIR|haggle blithely slyly +1700|139702|4729|1|38|66184.60|0.04|0.04|N|O|1996-10-03|1996-07-27|1996-10-22|NONE|RAIL|ular dependencies engage slyly +1700|155943|5944|2|49|97948.06|0.04|0.00|N|O|1996-09-26|1996-07-28|1996-10-16|NONE|TRUCK|kly even dependencies haggle fluffi +1701|149418|6961|1|47|68968.27|0.08|0.05|R|F|1992-05-25|1992-06-29|1992-06-15|NONE|RAIL|slyly final requests cajole requests. f +1701|53004|3005|2|2|1914.00|0.01|0.04|R|F|1992-06-24|1992-07-12|1992-06-29|COLLECT COD|SHIP|ween the pending, final accounts. +1701|34683|7187|3|26|42059.68|0.10|0.06|R|F|1992-06-04|1992-07-11|1992-07-04|DELIVER IN PERSON|FOB| accounts. blithely pending pinto be +1702|66974|4493|1|19|36878.43|0.02|0.01|N|F|1995-06-02|1995-06-30|1995-06-29|NONE|REG AIR|ies haggle blith +1702|29762|2265|2|38|64286.88|0.00|0.00|N|O|1995-09-01|1995-06-10|1995-09-10|DELIVER IN PERSON|REG AIR|as believe blithely. bo +1702|194425|4426|3|46|69893.32|0.00|0.08|N|O|1995-07-14|1995-06-30|1995-07-20|NONE|FOB|y even foxes. carefully final dependencies +1702|92039|2040|4|28|28868.84|0.07|0.05|R|F|1995-06-10|1995-07-26|1995-06-16|TAKE BACK RETURN|AIR|nts haggle along the packa +1702|88038|8039|5|34|34885.02|0.01|0.06|N|O|1995-07-04|1995-06-08|1995-07-28|DELIVER IN PERSON|AIR|y careful packages; dogged acco +1702|41506|4011|6|28|40530.00|0.10|0.00|N|O|1995-08-14|1995-07-31|1995-09-08|COLLECT COD|RAIL|ackages sleep. furiously even excuses snooz +1703|165404|7921|1|36|52898.40|0.09|0.01|R|F|1993-04-22|1993-03-05|1993-04-24|DELIVER IN PERSON|SHIP|riously express +1703|136118|1145|2|35|40393.85|0.01|0.08|R|F|1993-04-14|1993-03-31|1993-04-27|NONE|RAIL|he carefully +1703|123460|3461|3|48|71206.08|0.06|0.02|R|F|1993-02-07|1993-04-20|1993-02-24|TAKE BACK RETURN|AIR|ggle slyly furiously regular theodol +1728|125205|230|1|1|1230.20|0.07|0.04|N|O|1996-09-16|1996-08-19|1996-09-18|COLLECT COD|FOB|lly. carefully ex +1728|104383|6894|2|23|31909.74|0.05|0.02|N|O|1996-09-08|1996-07-24|1996-09-20|NONE|FOB|ns. pending, final ac +1728|164065|1614|3|44|49678.64|0.08|0.07|N|O|1996-07-31|1996-06-22|1996-08-06|COLLECT COD|FOB|ide of the slyly blithe +1728|26347|6348|4|34|43293.56|0.08|0.05|N|O|1996-08-28|1996-07-20|1996-09-12|DELIVER IN PERSON|MAIL|special req +1728|198088|3127|5|31|36768.48|0.09|0.02|N|O|1996-07-26|1996-06-28|1996-08-14|NONE|REG AIR|kly sly theodolites. +1729|156948|6949|1|12|24059.28|0.08|0.04|A|F|1992-08-11|1992-07-24|1992-08-16|COLLECT COD|RAIL|y pending packages detect. carefully re +1730|165429|7946|1|41|61271.22|0.01|0.03|N|O|1998-08-11|1998-08-29|1998-09-02|TAKE BACK RETURN|TRUCK| instructions. unusual, even Tiresi +1730|161312|1313|2|15|20599.65|0.07|0.04|N|O|1998-09-07|1998-09-12|1998-09-30|TAKE BACK RETURN|AIR|pinto beans cajole. bravely bold +1730|161029|3546|3|9|9810.18|0.10|0.00|N|O|1998-09-18|1998-09-15|1998-09-21|DELIVER IN PERSON|FOB|gular dependencies wake. blithely final e +1730|9457|6958|4|40|54658.00|0.02|0.03|N|O|1998-10-02|1998-10-06|1998-10-03|NONE|SHIP|ven dinos slee +1730|140291|5320|5|43|57245.47|0.04|0.06|N|O|1998-10-26|1998-10-22|1998-11-02|DELIVER IN PERSON|TRUCK|ng deposits cajo +1731|183932|3933|1|36|72573.48|0.10|0.00|N|O|1996-04-18|1996-04-03|1996-04-29|TAKE BACK RETURN|MAIL|ngside of the even instruct +1731|138267|3294|2|7|9136.82|0.04|0.07|N|O|1996-04-11|1996-02-13|1996-04-30|DELIVER IN PERSON|REG AIR|fily quick asymptotes +1731|50920|3426|3|50|93546.00|0.05|0.04|N|O|1996-01-14|1996-03-13|1996-01-29|COLLECT COD|RAIL|ly slyly speci +1731|195874|3432|4|23|45307.01|0.10|0.04|N|O|1996-04-22|1996-02-25|1996-05-16|TAKE BACK RETURN|RAIL|rays? bold, express pac +1731|52355|2356|5|37|48371.95|0.10|0.05|N|O|1996-04-30|1996-03-17|1996-05-27|TAKE BACK RETURN|RAIL| beans use furiously slyly b +1731|123416|953|6|41|59015.81|0.03|0.08|N|O|1996-04-05|1996-02-28|1996-05-01|TAKE BACK RETURN|RAIL|haggle across the blithely ironi +1732|4397|4398|1|50|65069.50|0.02|0.01|R|F|1993-12-05|1994-01-23|1993-12-20|TAKE BACK RETURN|FOB|fily final asymptotes according +1732|98183|8184|2|36|42522.48|0.01|0.03|A|F|1994-03-15|1994-02-09|1994-04-02|DELIVER IN PERSON|TRUCK|ve the accounts. slowly ironic multip +1732|160895|5928|3|41|80191.49|0.00|0.04|R|F|1994-02-20|1994-01-07|1994-02-27|TAKE BACK RETURN|AIR|quests sublate against the silent +1732|151257|1258|4|9|11774.25|0.04|0.04|A|F|1994-02-25|1994-01-29|1994-03-16|TAKE BACK RETURN|FOB|ular platelets. deposits wak +1732|168899|1416|5|25|49197.25|0.02|0.05|A|F|1994-02-15|1994-01-07|1994-02-21|COLLECT COD|REG AIR|nag slyly. even, special de +1732|72930|452|6|16|30446.88|0.01|0.05|R|F|1994-01-07|1994-01-02|1994-01-25|COLLECT COD|SHIP|ix carefully at the furiously regular pac +1733|110444|2956|1|41|59632.04|0.08|0.01|N|O|1996-06-13|1996-07-08|1996-07-07|TAKE BACK RETURN|AIR|ess notornis. fur +1733|23938|1445|2|16|29790.88|0.00|0.04|N|O|1996-08-28|1996-07-25|1996-09-27|COLLECT COD|MAIL|slyly express deposits sleep abo +1733|119673|7207|3|29|49087.43|0.10|0.06|N|O|1996-07-16|1996-08-08|1996-07-28|NONE|TRUCK|ns detect among the special accounts. qu +1733|135517|544|4|38|58995.38|0.01|0.03|N|O|1996-08-26|1996-07-23|1996-08-28|NONE|FOB| deposits +1733|33586|8593|5|22|33430.76|0.06|0.07|N|O|1996-07-16|1996-07-24|1996-07-30|COLLECT COD|AIR|gainst the final deposits. carefully final +1733|65422|5423|6|9|12486.78|0.06|0.08|N|O|1996-05-25|1996-07-23|1996-06-10|COLLECT COD|TRUCK|ven foxes was according to t +1733|145889|918|7|13|25153.44|0.02|0.03|N|O|1996-08-03|1996-08-02|1996-08-18|NONE|MAIL|olites sleep furious +1734|154883|7399|1|38|73639.44|0.03|0.03|R|F|1994-08-09|1994-09-07|1994-08-12|COLLECT COD|FOB|ts doubt b +1734|117726|238|2|4|6974.88|0.06|0.03|A|F|1994-08-20|1994-07-17|1994-08-25|DELIVER IN PERSON|AIR|final warhorses. +1735|155456|5457|1|43|64992.35|0.02|0.06|A|F|1993-01-14|1993-03-25|1993-02-02|DELIVER IN PERSON|FOB|iously after the +1735|138514|1028|2|49|76072.99|0.03|0.04|A|F|1992-12-31|1993-02-03|1993-01-25|TAKE BACK RETURN|TRUCK|y express accounts above the exp +1760|95414|433|1|38|53557.58|0.09|0.03|N|O|1996-06-15|1996-06-29|1996-07-11|NONE|MAIL|tions. blithely regular orbits against the +1760|7256|7257|2|3|3489.75|0.00|0.06|N|O|1996-07-18|1996-07-01|1996-08-01|NONE|RAIL|lyly bold dolphins haggle carefully. sl +1760|136818|1845|3|44|81611.64|0.05|0.01|N|O|1996-06-11|1996-06-16|1996-07-02|COLLECT COD|REG AIR|instructions poach slyly ironic theodolites +1761|51042|8558|1|33|32770.32|0.09|0.03|R|F|1994-01-03|1994-01-23|1994-01-31|NONE|FOB|s. excuses a +1761|51137|1138|2|37|40260.81|0.02|0.07|R|F|1994-02-17|1994-03-08|1994-03-16|NONE|RAIL| integrate. quickly unusual +1761|48901|1406|3|37|68446.30|0.06|0.04|R|F|1994-01-02|1994-03-12|1994-01-25|DELIVER IN PERSON|TRUCK|regular packages wake after +1761|72503|25|4|49|72299.50|0.06|0.07|R|F|1994-01-08|1994-03-03|1994-02-05|TAKE BACK RETURN|FOB|y even packages promise +1761|156877|9393|5|37|71553.19|0.03|0.04|R|F|1994-04-24|1994-03-14|1994-04-29|TAKE BACK RETURN|MAIL|express requests print blithely around the +1761|23419|926|6|12|16108.92|0.01|0.05|A|F|1994-04-16|1994-03-08|1994-04-21|DELIVER IN PERSON|AIR| sleep furiously. deposits are acco +1761|811|5812|7|13|22253.53|0.03|0.08|R|F|1994-03-06|1994-03-18|1994-03-22|DELIVER IN PERSON|TRUCK|ons boost fu +1762|25243|248|1|15|17523.60|0.04|0.08|A|F|1994-12-18|1994-10-29|1995-01-17|TAKE BACK RETURN|REG AIR|old packages thrash. care +1762|49506|4515|2|39|56764.50|0.10|0.02|A|F|1994-09-12|1994-11-09|1994-10-08|DELIVER IN PERSON|MAIL| ironic platelets sleep along t +1762|31865|4369|3|7|12578.02|0.05|0.01|R|F|1994-09-03|1994-10-02|1994-09-10|NONE|REG AIR|uickly express packages wake slyly-- regul +1762|144131|6646|4|24|28203.12|0.03|0.03|A|F|1994-11-30|1994-11-02|1994-12-20|NONE|REG AIR|accounts solve alongside of the fluffily +1762|7408|7409|5|49|64454.60|0.08|0.05|A|F|1994-10-20|1994-11-02|1994-11-10|TAKE BACK RETURN|SHIP| packages sleep fluffily pen +1762|93430|8449|6|35|49820.05|0.05|0.05|A|F|1994-11-25|1994-10-21|1994-11-28|COLLECT COD|AIR|ind quickly. accounts ca +1762|72971|5479|7|47|91366.59|0.03|0.01|A|F|1994-11-02|1994-10-07|1994-11-08|NONE|SHIP| blithely brave +1763|11731|6734|1|22|36140.06|0.09|0.06|N|O|1997-01-17|1997-01-15|1997-02-03|TAKE BACK RETURN|SHIP|ld. fluffily final ideas boos +1763|156496|9012|2|43|66757.07|0.04|0.04|N|O|1996-11-04|1996-12-09|1996-11-28|DELIVER IN PERSON|FOB|r deposits integrate blithely pending, quic +1763|24137|6640|3|16|16978.08|0.06|0.02|N|O|1996-12-12|1996-12-04|1996-12-25|DELIVER IN PERSON|RAIL|ously pending asymptotes a +1763|60187|7706|4|44|50475.92|0.04|0.05|N|O|1996-12-04|1997-01-06|1996-12-25|DELIVER IN PERSON|REG AIR| instructions need to integrate deposits. +1763|146555|9070|5|13|20820.15|0.03|0.05|N|O|1996-11-23|1997-01-24|1996-12-05|TAKE BACK RETURN|SHIP|s sleep carefully. fluffily unusua +1763|142048|2049|6|3|3270.12|0.05|0.03|N|O|1996-12-10|1996-12-06|1997-01-04|TAKE BACK RETURN|FOB|ut the slyly pending deposi +1763|183931|1486|7|2|4029.86|0.05|0.07|N|O|1997-02-27|1996-12-04|1997-03-27|COLLECT COD|FOB|even pinto beans snooze fluffi +1764|120300|301|1|20|26406.00|0.09|0.02|A|F|1992-06-09|1992-05-22|1992-07-06|COLLECT COD|MAIL|y quickly regular packages. car +1764|66465|1478|2|3|4294.38|0.07|0.07|R|F|1992-05-13|1992-06-07|1992-05-26|COLLECT COD|RAIL|es wake slowly. +1764|77176|4698|3|27|31135.59|0.07|0.04|A|F|1992-05-06|1992-05-11|1992-05-23|COLLECT COD|TRUCK|ly final foxes wake blithely even requests +1765|160566|567|1|36|58556.16|0.08|0.04|N|O|1996-03-02|1996-02-17|1996-03-14|DELIVER IN PERSON|SHIP|he blithely pending accou +1766|86716|6717|1|32|54486.72|0.08|0.01|N|O|1997-01-08|1996-11-11|1997-01-31|TAKE BACK RETURN|AIR|ess accounts. stealthily ironic accou +1766|33969|6473|2|12|22835.52|0.05|0.01|N|O|1996-10-28|1996-12-18|1996-11-15|DELIVER IN PERSON|AIR|heodolites above the final, regular acc +1766|110761|8295|3|1|1771.76|0.10|0.02|N|O|1997-01-21|1997-01-07|1997-02-19|NONE|TRUCK|ly blithely pending accounts. reg +1767|24933|9938|1|32|59453.76|0.08|0.04|A|F|1995-05-22|1995-05-14|1995-05-23|COLLECT COD|SHIP|to the bravely ironic requests i +1767|41434|8947|2|1|1375.43|0.09|0.05|N|O|1995-06-23|1995-05-25|1995-07-03|TAKE BACK RETURN|RAIL|ing to the slyly fin +1767|173977|3978|3|24|49223.28|0.06|0.03|R|F|1995-03-16|1995-04-29|1995-04-11|DELIVER IN PERSON|RAIL|luffy theodolites need to detect furi +1767|22387|4890|4|50|65469.00|0.01|0.02|R|F|1995-05-29|1995-04-14|1995-06-15|NONE|REG AIR|y unusual foxe +1767|51549|4055|5|40|60021.60|0.06|0.00|R|F|1995-04-16|1995-05-06|1995-04-21|TAKE BACK RETURN|AIR|ep. accounts nag blithely fu +1792|87191|2208|1|9|10603.71|0.09|0.04|R|F|1994-02-28|1993-12-11|1994-03-12|TAKE BACK RETURN|AIR|final packages s +1792|8700|6201|2|5|8043.50|0.04|0.02|R|F|1994-02-13|1994-01-03|1994-02-28|DELIVER IN PERSON|TRUCK|ely regular accounts are slyly. pending, bo +1792|8139|640|3|8|8377.04|0.01|0.04|A|F|1994-02-21|1994-01-26|1994-02-27|DELIVER IN PERSON|RAIL|nts. fluffily special instructions integr +1792|190135|2655|4|45|55130.85|0.00|0.01|A|F|1994-02-27|1993-12-24|1994-03-07|DELIVER IN PERSON|MAIL|ests are. ironic, regular asy +1792|198786|3825|5|35|65967.30|0.06|0.05|R|F|1994-01-31|1994-01-20|1994-02-17|NONE|FOB|e against the quic +1793|47119|9624|1|29|30917.19|0.01|0.06|R|F|1992-10-24|1992-09-20|1992-11-23|NONE|MAIL|ar excuses. +1793|125194|2731|2|4|4876.76|0.07|0.05|A|F|1992-07-28|1992-08-26|1992-08-21|COLLECT COD|RAIL|nic foxes along the even +1793|130060|2574|3|6|6540.36|0.01|0.05|R|F|1992-09-21|1992-09-05|1992-10-01|DELIVER IN PERSON|REG AIR|uctions; depo +1793|117679|5213|4|4|6786.68|0.00|0.08|R|F|1992-09-27|1992-09-21|1992-10-07|DELIVER IN PERSON|AIR|equests nod ac +1793|24521|4522|5|42|60711.84|0.03|0.03|A|F|1992-10-13|1992-10-02|1992-11-06|NONE|RAIL|uctions sleep carefully special, fl +1794|167389|7390|1|36|52429.68|0.09|0.08|N|O|1997-11-07|1997-11-01|1997-11-18|TAKE BACK RETURN|FOB|ely fluffily ironi +1794|94575|9594|2|3|4708.71|0.02|0.03|N|O|1997-11-15|1997-12-16|1997-11-20|DELIVER IN PERSON|FOB| sentiments according to the q +1794|116160|6161|3|23|27051.68|0.08|0.04|N|O|1997-10-13|1997-11-30|1997-10-28|TAKE BACK RETURN|AIR|usly unusual theodolites doze about +1794|84627|9644|4|34|54795.08|0.06|0.08|N|O|1997-09-29|1997-11-13|1997-10-07|TAKE BACK RETURN|SHIP|rs above the accoun +1794|116434|1457|5|47|68170.21|0.10|0.06|N|O|1998-01-15|1997-11-30|1998-02-14|DELIVER IN PERSON|TRUCK| haggle slyly. furiously express orbit +1794|90185|2695|6|37|43481.66|0.01|0.01|N|O|1998-01-12|1997-12-21|1998-01-17|DELIVER IN PERSON|MAIL|ackages. pinto +1795|136200|6201|1|44|54392.80|0.08|0.08|A|F|1994-04-28|1994-05-24|1994-05-27|NONE|AIR|ites sleep carefully slyly p +1795|113154|3155|2|34|39683.10|0.08|0.00|A|F|1994-04-24|1994-06-01|1994-05-08|DELIVER IN PERSON|SHIP|closely regular instructions wake. +1795|167545|5094|3|25|40313.50|0.07|0.01|A|F|1994-05-18|1994-05-22|1994-05-20|TAKE BACK RETURN|RAIL|he always express accounts ca +1795|124863|2400|4|32|60411.52|0.03|0.06|R|F|1994-05-10|1994-04-21|1994-05-17|DELIVER IN PERSON|SHIP| asymptotes across the bold, +1795|162306|9855|5|11|15051.30|0.08|0.02|R|F|1994-06-19|1994-04-24|1994-07-02|TAKE BACK RETURN|TRUCK|slyly. special pa +1796|9888|9889|1|28|50340.64|0.08|0.04|A|F|1992-12-01|1993-01-01|1992-12-24|DELIVER IN PERSON|FOB|y quickly ironic accounts. +1796|184834|9871|2|8|15350.64|0.00|0.08|R|F|1993-01-07|1993-01-04|1993-01-10|NONE|SHIP|slyly bold accounts are furiously agains +1797|30639|3143|1|17|26683.71|0.01|0.02|N|O|1996-08-06|1996-07-11|1996-08-29|NONE|TRUCK| cajole carefully. unusual Tiresias e +1797|144215|6730|2|16|20147.36|0.01|0.00|N|O|1996-06-03|1996-07-21|1996-06-07|NONE|FOB|o beans wake regular accounts. blit +1797|11709|6712|3|21|34034.70|0.02|0.01|N|O|1996-08-05|1996-08-05|1996-08-06|DELIVER IN PERSON|AIR|ns. regular, regular deposit +1798|108858|8859|1|43|80274.55|0.01|0.08|N|O|1997-08-27|1997-10-23|1997-09-09|DELIVER IN PERSON|MAIL|ld packages sleep furiously. depend +1799|51159|3665|1|8|8881.20|0.04|0.08|R|F|1994-06-14|1994-05-27|1994-06-27|TAKE BACK RETURN|MAIL|ealms upon the special, ironic waters +1799|26318|3825|2|42|52261.02|0.02|0.02|R|F|1994-04-05|1994-04-28|1994-04-09|DELIVER IN PERSON|FOB|es pending +1824|119669|7203|1|45|75989.70|0.03|0.02|R|F|1994-08-21|1994-06-21|1994-09-19|NONE|RAIL|ent Tiresias. quickly express +1824|68198|5717|2|40|46647.60|0.10|0.03|A|F|1994-05-08|1994-07-24|1994-06-06|NONE|FOB|es mold furiously final instructions. s +1825|155040|71|1|43|47086.72|0.05|0.05|A|F|1994-02-18|1994-02-19|1994-03-02|TAKE BACK RETURN|RAIL| accounts breach fluffily spe +1825|147333|9848|2|39|53832.87|0.00|0.00|R|F|1994-04-01|1994-01-12|1994-04-21|DELIVER IN PERSON|REG AIR|ual, bold ideas haggle above the quickly ir +1825|16370|1373|3|7|9004.59|0.04|0.03|A|F|1994-01-02|1994-01-30|1994-01-30|TAKE BACK RETURN|REG AIR|fully ironic requests. requests cajole ex +1825|120223|5248|4|23|28594.06|0.05|0.01|R|F|1994-01-08|1994-02-08|1994-01-19|NONE|MAIL| wake express, even r +1825|177840|7841|5|33|63288.72|0.04|0.04|A|F|1993-12-07|1994-03-01|1993-12-16|TAKE BACK RETURN|RAIL|about the ne +1826|26601|4108|1|4|6110.40|0.06|0.00|R|F|1992-07-05|1992-06-12|1992-08-04|DELIVER IN PERSON|MAIL|alongside of the quickly unusual re +1826|67102|4621|2|9|9621.90|0.07|0.07|R|F|1992-07-12|1992-07-11|1992-07-15|DELIVER IN PERSON|TRUCK| blithely special +1826|175212|2764|3|14|18020.94|0.05|0.01|A|F|1992-04-28|1992-05-31|1992-05-25|COLLECT COD|TRUCK|uriously bold pinto beans are carefully ag +1826|179826|4861|4|6|11434.92|0.05|0.04|R|F|1992-06-30|1992-05-17|1992-07-30|DELIVER IN PERSON|RAIL|kages. blithely silent +1826|134617|2157|5|46|75974.06|0.05|0.06|R|F|1992-05-02|1992-06-25|1992-05-26|TAKE BACK RETURN|FOB|ously? quickly pe +1826|107352|2373|6|43|58452.05|0.02|0.03|A|F|1992-07-28|1992-06-14|1992-08-03|NONE|MAIL|ss tithes use even ideas. fluffily final t +1827|89460|6985|1|47|68124.62|0.00|0.01|N|O|1996-08-01|1996-08-07|1996-08-23|TAKE BACK RETURN|RAIL|. pending courts about the even e +1827|153091|8122|2|48|54916.32|0.03|0.05|N|O|1996-08-28|1996-09-15|1996-09-01|COLLECT COD|RAIL|oxes. special, final asymptote +1827|199818|9819|3|37|70958.97|0.01|0.07|N|O|1996-07-20|1996-08-18|1996-08-08|DELIVER IN PERSON|REG AIR|ously ironic theodolites serve quickly af +1827|126488|4025|4|4|6057.92|0.04|0.04|N|O|1996-07-22|1996-09-10|1996-08-11|DELIVER IN PERSON|RAIL|special requests. blithely +1827|79528|2036|5|24|36180.48|0.00|0.08|N|O|1996-08-07|1996-09-01|1996-09-04|DELIVER IN PERSON|SHIP|al gifts! re +1827|20469|470|6|7|9726.22|0.10|0.02|N|O|1996-08-28|1996-08-07|1996-08-31|DELIVER IN PERSON|AIR|egular foxes +1827|5933|5934|7|38|69879.34|0.05|0.01|N|O|1996-10-17|1996-08-29|1996-11-07|TAKE BACK RETURN|SHIP| blithely. express, bo +1828|99555|7083|1|33|51300.15|0.05|0.04|R|F|1994-06-27|1994-06-10|1994-07-24|COLLECT COD|FOB|s boost carefully. pending d +1828|12436|9940|2|40|53937.20|0.08|0.07|R|F|1994-05-05|1994-07-02|1994-05-19|COLLECT COD|REG AIR|s use above the quietly fin +1828|195860|5861|3|11|21514.46|0.07|0.08|R|F|1994-07-21|1994-05-28|1994-08-13|DELIVER IN PERSON|FOB| wake blithely +1828|7764|2765|4|45|75229.20|0.02|0.05|R|F|1994-05-15|1994-05-29|1994-05-28|COLLECT COD|RAIL| accounts run slyly +1828|78153|5675|5|14|15836.10|0.01|0.08|A|F|1994-05-20|1994-06-02|1994-05-25|TAKE BACK RETURN|SHIP|. final packages along the carefully bold +1829|149926|2441|1|12|23711.04|0.05|0.06|A|F|1994-08-23|1994-07-13|1994-09-04|DELIVER IN PERSON|FOB|ges wake furiously express pinto +1829|4612|4613|2|11|16682.71|0.04|0.05|A|F|1994-05-18|1994-06-13|1994-06-07|COLLECT COD|MAIL|ding orbits +1829|103502|8523|3|49|73769.50|0.09|0.08|A|F|1994-08-26|1994-08-01|1994-09-16|NONE|TRUCK|ound the quickly +1829|152994|2995|4|14|28657.86|0.03|0.06|A|F|1994-08-15|1994-06-08|1994-08-30|TAKE BACK RETURN|AIR|regular deposits alongside of the flu +1829|165795|8312|5|6|11164.74|0.02|0.07|A|F|1994-08-09|1994-08-05|1994-09-05|DELIVER IN PERSON|MAIL|s haggle! slyl +1829|114621|2155|6|36|58882.32|0.09|0.04|R|F|1994-06-10|1994-06-23|1994-06-22|NONE|FOB|ackages-- express requests sleep; pen +1830|119595|2107|1|38|61354.42|0.00|0.07|R|F|1995-04-20|1995-05-22|1995-04-24|TAKE BACK RETURN|TRUCK|ely even a +1830|24483|6986|2|9|12667.32|0.05|0.07|R|F|1995-03-09|1995-05-24|1995-03-14|NONE|SHIP|st furiously among +1830|81005|3514|3|36|35496.00|0.07|0.07|R|F|1995-04-21|1995-04-14|1995-05-10|DELIVER IN PERSON|SHIP| slowly unusual orbits. carefull +1831|135126|7640|1|9|10450.08|0.02|0.03|A|F|1993-12-17|1994-01-27|1993-12-26|NONE|TRUCK|mptotes. furiously regular dolphins al +1831|47035|7036|2|9|8838.27|0.07|0.06|R|F|1994-03-22|1994-01-07|1994-04-06|COLLECT COD|MAIL|ent deposits. regular saute +1831|114911|2445|3|17|32740.47|0.02|0.08|R|F|1994-01-18|1994-02-12|1994-01-30|TAKE BACK RETURN|MAIL|s boost ironic foxe +1831|94173|9192|4|23|26844.91|0.06|0.02|R|F|1993-12-21|1994-02-08|1994-01-04|NONE|SHIP|ests. express pinto beans abou +1856|54971|9982|1|10|19259.70|0.05|0.07|R|F|1992-05-11|1992-05-20|1992-06-02|TAKE BACK RETURN|FOB|he furiously even theodolites. account +1856|96908|1927|2|47|89530.30|0.07|0.07|R|F|1992-03-22|1992-06-09|1992-04-17|DELIVER IN PERSON|FOB|ingly blithe theodolites. slyly pending +1856|116508|4042|3|20|30490.00|0.04|0.06|R|F|1992-05-04|1992-05-06|1992-05-11|DELIVER IN PERSON|MAIL|ost carefully. slyly bold accounts +1856|149295|9296|4|22|29574.38|0.08|0.02|A|F|1992-05-02|1992-05-26|1992-05-20|TAKE BACK RETURN|REG AIR|platelets detect slyly regular packages. ca +1856|189673|9674|5|14|24677.38|0.01|0.01|A|F|1992-04-14|1992-05-02|1992-05-11|COLLECT COD|SHIP|ans are even requests. deposits caj +1856|22677|184|6|36|57588.12|0.03|0.05|A|F|1992-06-19|1992-05-12|1992-06-28|TAKE BACK RETURN|TRUCK|ly even foxes kindle blithely even realm +1856|129838|7375|7|42|78448.86|0.04|0.00|R|F|1992-05-23|1992-06-06|1992-06-19|COLLECT COD|RAIL|usly final deposits +1857|173807|3808|1|15|28212.00|0.10|0.03|R|F|1993-04-05|1993-02-28|1993-04-13|COLLECT COD|RAIL|egular, regular inst +1857|166343|8860|2|40|56373.60|0.10|0.00|R|F|1993-02-15|1993-03-08|1993-02-21|NONE|AIR|slyly close d +1857|118981|1493|3|8|15999.84|0.01|0.07|R|F|1993-01-27|1993-04-04|1993-02-20|TAKE BACK RETURN|AIR|slyly about the fluffily silent req +1857|99627|4646|4|41|66691.42|0.07|0.07|A|F|1993-04-16|1993-02-16|1993-04-18|NONE|REG AIR| the slyly +1858|13932|6434|1|33|60915.69|0.01|0.02|N|O|1997-12-28|1998-02-03|1998-01-13|NONE|RAIL|tect along the slyly final +1859|74969|4970|1|18|34991.28|0.10|0.00|N|O|1997-08-08|1997-06-30|1997-08-26|TAKE BACK RETURN|SHIP|e carefully a +1859|187741|5296|2|36|65834.64|0.02|0.01|N|O|1997-05-05|1997-07-08|1997-05-25|TAKE BACK RETURN|REG AIR|regular requests. carefully unusual theo +1859|157708|5254|3|5|8828.50|0.06|0.03|N|O|1997-06-20|1997-05-20|1997-07-19|TAKE BACK RETURN|AIR|across the p +1859|190876|877|4|21|41304.27|0.00|0.03|N|O|1997-08-06|1997-05-29|1997-08-26|TAKE BACK RETURN|REG AIR|lar packages wake quickly exp +1859|45333|7838|5|11|14061.63|0.06|0.06|N|O|1997-07-15|1997-06-05|1997-07-29|TAKE BACK RETURN|SHIP|ffily ironic pac +1859|104305|6816|6|12|15711.60|0.08|0.03|N|O|1997-05-22|1997-06-08|1997-06-07|COLLECT COD|TRUCK|es. unusual, silent request +1860|112942|2943|1|9|17594.46|0.04|0.04|N|O|1996-08-03|1996-05-31|1996-08-04|DELIVER IN PERSON|TRUCK|c realms print carefully car +1861|67093|2106|1|7|7420.63|0.08|0.05|A|F|1994-01-14|1994-04-03|1994-01-16|COLLECT COD|RAIL|s foxes. slyly +1861|26765|6766|2|31|52444.56|0.10|0.05|R|F|1994-01-29|1994-03-07|1994-02-15|TAKE BACK RETURN|RAIL|arefully unusual +1861|23676|6179|3|23|36792.41|0.00|0.08|A|F|1994-04-09|1994-03-04|1994-04-11|DELIVER IN PERSON|MAIL|in packages sleep silent dolphins; sly +1861|115108|2642|4|38|42677.80|0.10|0.05|R|F|1994-02-26|1994-02-05|1994-03-01|NONE|RAIL|pending deposits cajole quic +1861|15110|113|5|2|2050.22|0.03|0.08|R|F|1994-04-26|1994-03-15|1994-05-15|TAKE BACK RETURN|MAIL|e final, regular requests. carefully +1862|29629|2132|1|41|63903.42|0.10|0.00|N|O|1998-06-05|1998-05-17|1998-07-04|COLLECT COD|FOB| carefully along +1862|165414|5415|2|37|54738.17|0.06|0.02|N|O|1998-04-15|1998-05-15|1998-05-14|TAKE BACK RETURN|MAIL|l deposits. carefully even dep +1862|103981|1512|3|26|51609.48|0.02|0.01|N|O|1998-03-25|1998-05-17|1998-04-17|TAKE BACK RETURN|TRUCK|g carefully: thinly ironic deposits af +1863|62472|4979|1|48|68854.56|0.09|0.04|A|F|1993-10-10|1993-12-09|1993-10-19|NONE|FOB|ans hinder furiou +1863|156951|1982|2|48|96381.60|0.04|0.08|A|F|1993-11-08|1993-11-05|1993-12-08|COLLECT COD|AIR|onic theodolites alongside of the pending a +1888|97643|153|1|27|44297.28|0.03|0.06|R|F|1994-02-13|1994-01-16|1994-02-25|NONE|REG AIR|. carefully special dolphins sle +1888|73403|3404|2|38|52303.20|0.03|0.03|R|F|1993-11-29|1994-01-16|1993-12-08|TAKE BACK RETURN|TRUCK|dazzle carefull +1888|79623|9624|3|49|78528.38|0.07|0.05|A|F|1994-02-27|1994-01-14|1994-03-28|DELIVER IN PERSON|FOB|lar accounts haggle carefu +1888|18538|8539|4|9|13108.77|0.01|0.04|A|F|1994-02-09|1994-01-22|1994-02-19|NONE|AIR| packages are blithely. carefu +1888|159509|9510|5|4|6274.00|0.03|0.06|R|F|1993-12-28|1993-12-19|1994-01-11|COLLECT COD|FOB|lphins. ironically special theodolit +1888|52536|7547|6|48|71449.44|0.08|0.08|R|F|1994-02-28|1993-12-16|1994-03-15|COLLECT COD|TRUCK|ar ideas cajole. regular p +1888|166333|8850|7|50|69966.50|0.04|0.07|R|F|1993-12-22|1994-01-10|1994-01-06|DELIVER IN PERSON|FOB|ependencies affix blithely regular warhors +1889|151174|8720|1|41|50231.97|0.10|0.02|N|O|1997-06-15|1997-05-10|1997-07-08|NONE|AIR|s! furiously pending r +1889|171604|1605|2|13|21782.80|0.05|0.00|N|O|1997-06-12|1997-04-28|1997-06-23|NONE|REG AIR|to the regular accounts. carefully express +1889|137156|2183|3|36|42953.40|0.05|0.07|N|O|1997-05-19|1997-06-14|1997-05-23|NONE|SHIP|l pinto beans kindle +1889|167656|2689|4|5|8618.25|0.02|0.07|N|O|1997-06-26|1997-06-09|1997-07-21|COLLECT COD|AIR|ording to the blithely silent r +1890|140281|2796|1|26|34353.28|0.03|0.07|N|O|1997-04-02|1997-03-13|1997-04-22|DELIVER IN PERSON|FOB|ngage. slyly ironic +1890|99403|9404|2|43|60303.20|0.07|0.03|N|O|1996-12-30|1997-01-31|1997-01-19|DELIVER IN PERSON|FOB|p ironic, express accounts. fu +1890|58873|6389|3|24|43964.88|0.06|0.04|N|O|1997-02-09|1997-02-10|1997-02-12|COLLECT COD|MAIL|is wake carefully above the even id +1890|67265|7266|4|43|52987.18|0.09|0.04|N|O|1997-04-08|1997-02-19|1997-04-30|TAKE BACK RETURN|FOB|lyly. instructions across the furiously +1890|121175|1176|5|45|53827.65|0.08|0.05|N|O|1997-04-15|1997-03-16|1997-04-19|COLLECT COD|FOB|he carefully regular sauternes. ironic fret +1890|180789|3308|6|16|29916.48|0.08|0.02|N|O|1997-02-13|1997-02-18|1997-03-12|TAKE BACK RETURN|TRUCK|ged pinto beans. regular, regular id +1890|120205|7742|7|10|12252.00|0.01|0.04|N|O|1996-12-24|1997-02-19|1997-01-01|DELIVER IN PERSON|AIR|. even, unusual inst +1891|76099|6100|1|45|48379.05|0.07|0.04|A|F|1994-12-20|1995-01-16|1995-01-05|NONE|RAIL|ests along +1891|183091|5610|2|18|21133.62|0.06|0.00|A|F|1995-01-24|1995-01-29|1995-02-14|NONE|RAIL| foxes above the carefu +1891|197159|7160|3|15|18842.25|0.03|0.00|R|F|1995-03-11|1995-03-05|1995-03-18|TAKE BACK RETURN|MAIL| accounts are furiou +1892|112777|5289|1|48|85908.96|0.02|0.01|A|F|1994-06-16|1994-06-16|1994-06-28|NONE|RAIL|tornis detect regul +1892|42003|9516|2|35|33075.00|0.04|0.08|R|F|1994-04-05|1994-05-09|1994-05-03|NONE|MAIL|hes nod furiously around the instruc +1892|133278|8305|3|37|48516.99|0.10|0.03|R|F|1994-04-11|1994-06-04|1994-04-24|TAKE BACK RETURN|SHIP|nts. slyly regular asymptot +1892|196964|9484|4|14|28853.44|0.06|0.07|R|F|1994-04-08|1994-06-12|1994-04-27|DELIVER IN PERSON|FOB|furiously about the furiously +1893|98266|776|1|43|54363.18|0.10|0.00|N|O|1998-01-25|1998-01-06|1998-02-14|COLLECT COD|SHIP|he carefully regular +1893|147335|7336|2|49|67734.17|0.03|0.05|N|O|1998-01-19|1998-01-28|1998-02-02|TAKE BACK RETURN|FOB|y final foxes bo +1893|44119|4120|3|3|3189.33|0.03|0.02|N|O|1998-02-10|1998-01-18|1998-02-25|DELIVER IN PERSON|MAIL|gular, even ideas. fluffily bol +1893|100605|5626|4|18|28900.80|0.07|0.06|N|O|1998-01-24|1998-01-12|1998-02-13|TAKE BACK RETURN|RAIL|g packages. fluffily final reques +1893|52070|2071|5|6|6132.42|0.10|0.02|N|O|1998-01-23|1997-12-22|1998-02-09|DELIVER IN PERSON|TRUCK|ar accounts use. daringly ironic packag +1894|168292|8293|1|40|54411.60|0.03|0.07|R|F|1992-06-07|1992-05-11|1992-07-01|DELIVER IN PERSON|FOB|ily furiously bold packages. flu +1895|160192|7741|1|43|53844.17|0.09|0.07|R|F|1994-07-26|1994-07-19|1994-08-11|NONE|AIR| carefully eve +1920|95392|5393|1|24|33297.36|0.04|0.05|N|O|1998-09-27|1998-08-23|1998-10-15|DELIVER IN PERSON|AIR|thely. bold, pend +1920|50707|5718|2|31|51388.70|0.05|0.06|N|O|1998-08-01|1998-08-30|1998-08-17|COLLECT COD|SHIP|lly. ideas wa +1920|17189|9691|3|6|6637.08|0.01|0.05|N|O|1998-10-01|1998-08-20|1998-10-24|COLLECT COD|SHIP|l ideas boost slyly pl +1920|83349|3350|4|50|66617.00|0.09|0.06|N|O|1998-10-03|1998-08-04|1998-10-29|DELIVER IN PERSON|MAIL|e blithely unusual foxes. brave packages +1920|33789|1299|5|14|24118.92|0.08|0.05|N|O|1998-10-22|1998-08-10|1998-10-27|DELIVER IN PERSON|AIR|ickly ironic d +1921|20643|5648|1|9|14072.76|0.08|0.00|R|F|1994-02-01|1994-03-20|1994-03-01|DELIVER IN PERSON|FOB|to beans. even excuses integrate specia +1921|139685|2199|2|21|36218.28|0.02|0.06|R|F|1994-02-08|1994-03-28|1994-02-15|COLLECT COD|FOB|ckly regula +1921|70822|823|3|27|48406.14|0.00|0.04|A|F|1994-04-26|1994-04-07|1994-04-30|TAKE BACK RETURN|FOB|ing pinto beans above the pend +1922|9775|4776|1|13|21902.01|0.05|0.03|N|O|1996-10-24|1996-09-21|1996-11-15|NONE|SHIP|quests. furiously +1923|36198|6199|1|9|10207.71|0.01|0.08|N|O|1997-08-29|1997-09-13|1997-09-07|NONE|FOB|lites. ironic instructions integrate bravel +1923|177330|9848|2|23|32368.59|0.07|0.05|N|O|1997-09-08|1997-08-11|1997-09-14|TAKE BACK RETURN|MAIL|aggle carefully. furiously permanent +1923|179628|9629|3|11|18783.82|0.03|0.03|N|O|1997-07-12|1997-09-04|1997-08-01|TAKE BACK RETURN|REG AIR|ages wake slyly about the furiously regular +1923|192622|5142|4|49|84016.38|0.06|0.05|N|O|1997-07-21|1997-08-08|1997-07-26|NONE|AIR|de of the carefully expre +1923|183057|8094|5|25|28501.25|0.10|0.08|N|O|1997-08-18|1997-08-20|1997-09-12|DELIVER IN PERSON|TRUCK|the ideas: slyly pendin +1923|36955|9459|6|50|94597.50|0.03|0.03|N|O|1997-11-04|1997-08-08|1997-11-25|NONE|TRUCK|uickly along the bold courts. bold the +1924|72567|89|1|7|10776.92|0.06|0.07|N|O|1997-01-01|1996-12-02|1997-01-08|COLLECT COD|SHIP|osits. even accounts nag furious +1924|17366|4870|2|47|60317.92|0.02|0.06|N|O|1996-11-24|1996-10-18|1996-12-13|COLLECT COD|REG AIR|silent requests cajole blithely final pack +1924|56788|6789|3|40|69791.20|0.04|0.08|N|O|1996-10-31|1996-11-30|1996-11-21|NONE|REG AIR|ains sleep carefully +1924|33179|8186|4|31|34477.27|0.03|0.03|N|O|1996-09-20|1996-10-19|1996-10-19|DELIVER IN PERSON|SHIP| the slyly regular foxes. ruthle +1924|35419|426|5|17|23024.97|0.04|0.05|N|O|1996-12-31|1996-11-12|1997-01-25|COLLECT COD|TRUCK|e carefully theodolites. ironically ironic +1924|75709|3231|6|15|25270.50|0.02|0.04|N|O|1997-01-04|1996-11-13|1997-01-27|NONE|SHIP|he package +1924|39531|9532|7|21|30881.13|0.09|0.03|N|O|1996-09-21|1996-11-12|1996-10-02|TAKE BACK RETURN|AIR| blithely reg +1925|183718|8755|1|50|90085.50|0.01|0.02|R|F|1992-04-12|1992-04-23|1992-05-08|TAKE BACK RETURN|TRUCK|usual pinto +1925|134273|1813|2|35|45754.45|0.06|0.06|R|F|1992-05-11|1992-04-10|1992-05-14|TAKE BACK RETURN|AIR|counts. carefully ironic packages boost ab +1925|115014|7526|3|40|41160.40|0.08|0.08|A|F|1992-05-17|1992-05-20|1992-06-08|TAKE BACK RETURN|AIR|e carefully regul +1925|29757|2260|4|17|28674.75|0.06|0.02|R|F|1992-05-18|1992-04-06|1992-06-16|TAKE BACK RETURN|MAIL|instructions sleep. pinto bea +1926|50307|2813|1|24|30175.20|0.06|0.05|N|O|1996-05-04|1996-03-14|1996-06-01|DELIVER IN PERSON|RAIL|e theodolites. +1926|105027|7538|2|29|29928.58|0.09|0.08|N|O|1996-02-26|1996-03-14|1996-03-14|TAKE BACK RETURN|TRUCK|es. dependencies according to the fl +1926|177645|5197|3|10|17226.40|0.02|0.03|N|O|1996-05-23|1996-03-02|1996-06-04|NONE|AIR|usly bold accounts. express accounts +1926|67772|7773|4|13|22617.01|0.04|0.02|N|O|1996-04-26|1996-04-13|1996-05-08|DELIVER IN PERSON|MAIL|eans wake bli +1926|39928|4935|5|29|54169.68|0.06|0.00|N|O|1996-02-29|1996-03-13|1996-03-24|DELIVER IN PERSON|MAIL|hily unusual packages are fluffily am +1927|67893|2906|1|3|5582.67|0.00|0.05|N|O|1995-10-06|1995-12-08|1995-11-05|COLLECT COD|FOB|ccounts affi +1927|72462|7477|2|15|21516.90|0.08|0.08|N|O|1995-12-25|1995-12-26|1995-12-31|COLLECT COD|RAIL| carefully regular requests sleep car +1927|64783|2302|3|6|10486.68|0.05|0.05|N|O|1995-11-29|1995-11-20|1995-12-08|TAKE BACK RETURN|TRUCK|furiously even wat +1952|52059|7070|1|7|7077.35|0.04|0.05|A|F|1994-05-06|1994-06-11|1994-05-12|NONE|RAIL|about the express, even requ +1952|141675|6704|2|6|10300.02|0.06|0.05|A|F|1994-05-09|1994-05-21|1994-05-26|DELIVER IN PERSON|AIR|packages haggle. +1953|127615|5152|1|25|41065.25|0.07|0.06|A|F|1994-01-07|1994-01-28|1994-01-29|TAKE BACK RETURN|RAIL|ular, regular i +1953|13880|3881|2|35|62785.80|0.06|0.06|R|F|1994-02-03|1994-02-25|1994-02-14|DELIVER IN PERSON|FOB|among the fur +1954|151270|6301|1|31|40959.37|0.06|0.06|N|O|1997-08-18|1997-07-07|1997-09-03|DELIVER IN PERSON|RAIL|against the packages. bold, ironic e +1954|181175|6212|2|1|1256.17|0.03|0.01|N|O|1997-09-16|1997-07-08|1997-10-07|COLLECT COD|MAIL|te. furiously final deposits hag +1954|198665|3704|3|11|19400.26|0.07|0.07|N|O|1997-08-07|1997-07-23|1997-08-25|DELIVER IN PERSON|TRUCK|y carefully ironi +1954|158218|3249|4|12|15314.52|0.02|0.08|N|O|1997-07-19|1997-07-04|1997-08-06|COLLECT COD|AIR|ongside of the slyly unusual requests. reg +1954|169702|4735|5|29|51379.30|0.08|0.08|N|O|1997-08-25|1997-07-15|1997-09-02|DELIVER IN PERSON|RAIL|use thinly furiously regular asy +1954|176272|6273|6|13|17527.51|0.00|0.07|N|O|1997-06-15|1997-08-22|1997-06-20|TAKE BACK RETURN|MAIL|y ironic instructions cajole +1954|193476|3477|7|49|76904.03|0.05|0.06|N|O|1997-06-04|1997-08-29|1997-06-14|COLLECT COD|TRUCK|eans. final pinto beans sleep furiousl +1955|136052|8566|1|32|34817.60|0.02|0.02|A|F|1992-07-05|1992-06-29|1992-08-03|TAKE BACK RETURN|TRUCK|g to the carefully sile +1955|17074|4578|2|2|1982.14|0.03|0.01|R|F|1992-07-06|1992-07-06|1992-08-01|COLLECT COD|TRUCK|ickly aroun +1955|157697|213|3|41|71942.29|0.08|0.06|A|F|1992-08-01|1992-06-04|1992-08-07|COLLECT COD|AIR| carefully against the furiously reg +1955|8245|3246|4|16|18451.84|0.03|0.07|A|F|1992-04-30|1992-06-23|1992-05-23|TAKE BACK RETURN|FOB|odolites eat s +1955|158432|8433|5|11|16394.73|0.09|0.01|A|F|1992-06-03|1992-07-04|1992-06-07|NONE|REG AIR|ously quickly pendi +1956|176350|6351|1|8|11410.80|0.02|0.04|A|F|1992-12-25|1992-11-24|1993-01-12|TAKE BACK RETURN|AIR|efully about the ironic, ironic de +1956|102954|5465|2|16|31311.20|0.00|0.05|R|F|1992-11-11|1992-11-11|1992-11-30|NONE|FOB|es cajole blithely. pen +1956|138920|1434|3|39|76397.88|0.08|0.02|A|F|1992-09-24|1992-11-26|1992-10-15|DELIVER IN PERSON|REG AIR|r theodolites sleep above the b +1956|28284|8285|4|11|13335.08|0.10|0.00|A|F|1992-12-19|1992-10-29|1993-01-07|TAKE BACK RETURN|AIR| the braids slee +1956|154900|9931|5|16|31278.40|0.08|0.02|R|F|1992-09-28|1992-10-21|1992-09-30|TAKE BACK RETURN|FOB| wake after the +1957|78284|792|1|50|63114.00|0.09|0.05|N|O|1998-08-08|1998-09-28|1998-08-27|COLLECT COD|FOB|gainst the re +1957|118027|539|2|31|32395.62|0.10|0.08|N|O|1998-08-13|1998-08-31|1998-08-16|NONE|REG AIR|express packages maintain fluffi +1958|72052|7067|1|9|9216.45|0.01|0.05|N|O|1995-12-08|1995-12-17|1995-12-18|DELIVER IN PERSON|REG AIR|ickly. slyly bold +1958|175065|5066|2|29|33061.74|0.05|0.06|N|O|1996-01-19|1995-12-05|1996-02-14|COLLECT COD|SHIP|d pinto beans +1958|101773|1774|3|4|7099.08|0.04|0.02|N|O|1995-10-24|1995-12-09|1995-10-28|DELIVER IN PERSON|AIR|he slyly even dependencies +1958|82603|7620|4|38|60252.80|0.09|0.07|N|O|1995-10-09|1995-11-26|1995-11-05|COLLECT COD|TRUCK|yly. slyly regular courts use silentl +1958|100912|8443|5|31|59300.21|0.08|0.01|N|O|1995-10-31|1995-11-12|1995-11-07|TAKE BACK RETURN|TRUCK|r deposits c +1958|16175|1178|6|44|48011.48|0.08|0.04|N|O|1995-12-17|1995-11-30|1996-01-15|TAKE BACK RETURN|RAIL|c theodolites after the unusual deposit +1958|38399|5909|7|29|38784.31|0.02|0.05|N|O|1995-10-14|1995-11-06|1995-11-01|NONE|REG AIR|final requests nag according to the +1959|168675|8676|1|46|80208.82|0.04|0.00|N|O|1997-05-05|1997-03-03|1997-05-24|TAKE BACK RETURN|AIR| furiously ex +1959|119439|4462|2|15|21876.45|0.08|0.07|N|O|1997-01-20|1997-02-18|1997-02-08|DELIVER IN PERSON|MAIL| quickly sp +1984|52054|9570|1|45|45272.25|0.03|0.04|N|O|1998-04-09|1998-06-11|1998-05-01|COLLECT COD|AIR|p. quickly final ideas sle +1984|69990|5003|2|35|68599.65|0.01|0.07|N|O|1998-05-18|1998-05-04|1998-06-01|COLLECT COD|RAIL|tes. quickly pending packages haggle boldl +1985|27157|4664|1|33|35776.95|0.10|0.03|R|F|1994-12-04|1994-11-01|1994-12-05|DELIVER IN PERSON|FOB|s are express packages. pendin +1985|20393|2896|2|50|65669.50|0.04|0.02|R|F|1994-09-30|1994-10-18|1994-10-12|COLLECT COD|AIR|ate carefully. carefully +1985|133207|5721|3|20|24804.00|0.07|0.03|R|F|1994-10-29|1994-11-12|1994-11-27|NONE|TRUCK|regular requests. furiously express +1985|198140|8141|4|30|37144.20|0.05|0.07|R|F|1994-09-06|1994-10-10|1994-09-26|NONE|RAIL|uickly. instr +1985|123819|6332|5|42|77398.02|0.05|0.05|R|F|1994-10-25|1994-11-03|1994-11-19|DELIVER IN PERSON|SHIP| patterns? final requests after the sp +1985|19676|4679|6|2|3191.34|0.02|0.00|A|F|1994-11-25|1994-10-09|1994-12-25|TAKE BACK RETURN|FOB| silent inst +1986|91481|1482|1|12|17669.76|0.06|0.05|A|F|1994-08-17|1994-06-28|1994-09-02|COLLECT COD|RAIL|sleep furiously fluffily final +1986|104675|7186|2|10|16796.70|0.10|0.03|R|F|1994-05-14|1994-06-21|1994-06-02|COLLECT COD|REG AIR|yly into the carefully even +1986|62714|5221|3|14|23473.94|0.04|0.02|R|F|1994-07-14|1994-06-19|1994-08-08|NONE|SHIP|the packages. pending, unusual +1987|15018|2522|1|7|6531.07|0.03|0.03|A|F|1994-07-30|1994-07-06|1994-08-29|NONE|REG AIR| regular a +1988|71007|6022|1|36|35208.00|0.09|0.04|N|O|1996-01-21|1995-11-24|1996-01-27|NONE|RAIL|gular theodolites. +1988|198445|6003|2|19|29325.36|0.08|0.08|N|O|1996-02-03|1995-12-10|1996-02-14|COLLECT COD|FOB|lly about the slyly thin instructions. f +1988|53790|1306|3|8|13950.32|0.06|0.01|N|O|1995-10-20|1995-11-11|1995-11-18|DELIVER IN PERSON|AIR|le quickly ac +1988|35669|8173|4|27|43325.82|0.08|0.00|N|O|1996-01-27|1995-12-24|1996-02-24|TAKE BACK RETURN|TRUCK|uests. regular requests are according to t +1988|78175|3190|5|26|29982.42|0.08|0.04|N|O|1996-01-25|1995-12-15|1996-01-26|COLLECT COD|SHIP| ironic dolphins haggl +1988|85943|3468|6|9|17360.46|0.08|0.03|N|O|1995-12-26|1996-01-02|1996-01-25|DELIVER IN PERSON|MAIL|lar platelets. slyly ironic packa +1989|9871|7372|1|47|83700.89|0.10|0.02|R|F|1994-06-21|1994-05-27|1994-06-22|TAKE BACK RETURN|REG AIR|final deposits s +1990|100961|962|1|46|90250.16|0.01|0.07|R|F|1994-12-29|1995-03-14|1995-01-13|NONE|TRUCK|ar sentiments. +1991|109006|1517|1|39|39585.00|0.06|0.02|A|F|1993-01-01|1992-11-29|1993-01-10|TAKE BACK RETURN|TRUCK|ckages? carefully bold depos +1991|52810|5316|2|49|86377.69|0.08|0.06|R|F|1992-10-19|1992-11-29|1992-10-25|NONE|SHIP|nd the ideas affi +1991|173555|3556|3|6|9771.30|0.02|0.01|A|F|1992-11-02|1992-10-08|1992-11-14|TAKE BACK RETURN|REG AIR|hes nag slyly +1991|137375|2402|4|6|8474.22|0.10|0.06|A|F|1992-11-21|1992-11-03|1992-11-27|NONE|RAIL|uickly blithely final de +1991|59310|1816|5|49|62196.19|0.06|0.00|R|F|1992-09-10|1992-11-30|1992-10-07|NONE|AIR|quests cajole blithely +2016|146003|8518|1|2|2098.00|0.02|0.07|N|O|1996-10-12|1996-11-09|1996-10-31|DELIVER IN PERSON|TRUCK|carefully according to the +2016|62672|191|2|15|24520.05|0.04|0.05|N|O|1996-09-24|1996-10-05|1996-10-21|TAKE BACK RETURN|MAIL|uests haggle carefully furiously regul +2016|121423|3936|3|8|11555.36|0.09|0.02|N|O|1996-09-19|1996-10-21|1996-10-13|TAKE BACK RETURN|SHIP|mptotes haggle ideas. packages wake flu +2017|102545|2546|1|49|75829.46|0.10|0.06|N|O|1998-05-26|1998-07-01|1998-06-06|COLLECT COD|TRUCK| after the unusual instructions. sly +2017|70072|73|2|14|14588.98|0.07|0.04|N|O|1998-06-28|1998-06-15|1998-07-11|NONE|TRUCK|ily final w +2017|83446|8463|3|11|15723.84|0.05|0.02|N|O|1998-05-22|1998-07-13|1998-05-26|TAKE BACK RETURN|TRUCK|gside of the slyly dogged dolp +2018|194201|4202|1|2|2590.40|0.02|0.07|N|O|1995-06-25|1995-06-20|1995-07-04|NONE|TRUCK|ly ironic accounts against the slyly sly +2018|128111|8112|2|23|26199.53|0.05|0.01|R|F|1995-05-05|1995-05-12|1995-05-22|TAKE BACK RETURN|RAIL|ingly even theodolites s +2019|3228|8229|1|31|35067.82|0.07|0.03|R|F|1992-11-18|1992-12-26|1992-11-24|DELIVER IN PERSON|FOB|l ideas across the slowl +2019|51852|6863|2|18|32469.30|0.04|0.03|R|F|1993-01-24|1992-12-22|1993-02-02|NONE|MAIL|are carefully furiously regular requ +2020|33521|1031|1|50|72726.00|0.06|0.01|R|F|1993-07-12|1993-08-28|1993-08-02|COLLECT COD|TRUCK|ts against the pending ideas serve along +2020|175666|3218|2|40|69666.40|0.09|0.00|A|F|1993-10-17|1993-09-14|1993-10-29|TAKE BACK RETURN|RAIL|ently across the +2020|13808|1312|3|30|51654.00|0.07|0.04|A|F|1993-09-08|1993-08-11|1993-09-29|TAKE BACK RETURN|AIR|ly about the blithely ironic foxes. bold +2020|60852|5865|4|27|48946.95|0.05|0.06|A|F|1993-07-14|1993-09-02|1993-08-03|NONE|FOB|e of the bold foxes haggle +2021|84701|2226|1|7|11799.90|0.08|0.04|N|O|1995-10-17|1995-09-29|1995-10-20|NONE|MAIL| accounts boost blithely. blithely reg +2021|165276|309|2|19|25484.13|0.04|0.05|N|O|1995-08-14|1995-09-05|1995-08-23|NONE|RAIL| above the slyly fl +2022|168410|927|1|38|56179.58|0.00|0.08|R|F|1992-07-05|1992-04-20|1992-07-13|TAKE BACK RETURN|REG AIR| against the express accounts wake ca +2022|54766|7272|2|38|65388.88|0.05|0.04|R|F|1992-06-17|1992-05-15|1992-06-28|COLLECT COD|SHIP|instructions dazzle carefull +2022|48896|8897|3|48|88554.72|0.10|0.02|A|F|1992-06-14|1992-06-04|1992-07-12|DELIVER IN PERSON|SHIP|counts. slyly enticing accounts are during +2022|181336|1337|4|16|22677.28|0.05|0.03|R|F|1992-06-23|1992-05-22|1992-07-07|NONE|TRUCK|ages wake slyly care +2022|99490|9491|5|36|53621.64|0.05|0.02|R|F|1992-03-24|1992-05-07|1992-04-13|NONE|MAIL|ly after the foxes. regular, final inst +2022|128142|5679|6|20|23402.80|0.08|0.08|A|F|1992-03-31|1992-04-17|1992-04-02|NONE|SHIP|r deposits kindle +2022|77154|7155|7|13|14704.95|0.06|0.08|R|F|1992-04-04|1992-05-30|1992-04-21|NONE|FOB| orbits haggle fluffily fl +2023|126248|3785|1|9|11468.16|0.05|0.04|R|F|1992-06-04|1992-06-30|1992-06-10|NONE|AIR|ly regular pinto beans poa +2023|37736|5246|2|2|3347.46|0.01|0.00|R|F|1992-08-27|1992-07-16|1992-08-29|DELIVER IN PERSON|RAIL|ing packages. fluffily silen +2023|18539|3542|3|25|36438.25|0.10|0.03|A|F|1992-07-19|1992-07-07|1992-08-15|NONE|REG AIR| wake furiously among the slyly final +2023|184818|9855|4|9|17125.29|0.02|0.00|A|F|1992-07-23|1992-07-04|1992-08-20|TAKE BACK RETURN|AIR|nts maintain blithely alongside of the +2023|19435|6939|5|22|29797.46|0.04|0.06|A|F|1992-06-15|1992-07-13|1992-06-21|TAKE BACK RETURN|SHIP|ronic attainments. +2023|42824|337|6|29|51237.78|0.02|0.06|A|F|1992-08-29|1992-07-28|1992-09-18|COLLECT COD|RAIL|usual instructions. bli +2023|133971|6485|7|50|100248.50|0.00|0.03|R|F|1992-06-20|1992-07-04|1992-06-23|DELIVER IN PERSON|FOB|its! carefully ex +2048|34296|6800|1|7|8612.03|0.06|0.01|R|F|1993-12-07|1994-01-31|1994-01-05|TAKE BACK RETURN|REG AIR|lent platelets boost deposits. carefully sp +2048|7372|4873|2|5|6396.85|0.04|0.04|A|F|1994-01-18|1994-02-01|1994-01-29|TAKE BACK RETURN|TRUCK|affix carefully against +2048|100536|537|3|12|18438.36|0.01|0.05|R|F|1994-01-28|1994-01-19|1994-02-08|NONE|AIR| even theodoli +2048|96292|3820|4|11|14171.19|0.10|0.03|R|F|1993-12-20|1994-01-19|1994-01-04|TAKE BACK RETURN|MAIL|totes. idly ironic packages nag +2049|188067|8068|1|25|28876.50|0.08|0.00|N|O|1996-03-31|1996-02-29|1996-04-15|DELIVER IN PERSON|MAIL| excuses above the +2049|34609|7113|2|31|47851.60|0.10|0.05|N|O|1995-12-25|1996-02-25|1995-12-29|TAKE BACK RETURN|MAIL| packages are slyly alongside +2049|66556|9063|3|18|27405.90|0.05|0.05|N|O|1996-01-09|1996-01-22|1996-01-25|TAKE BACK RETURN|AIR| sleep fluffily. dependencies use never +2049|5410|5411|4|39|51300.99|0.02|0.05|N|O|1996-01-17|1996-01-21|1996-02-03|TAKE BACK RETURN|MAIL|the even pinto beans +2049|125275|7788|5|30|39008.10|0.04|0.06|N|O|1995-12-16|1996-02-04|1995-12-22|NONE|TRUCK|ial accounts are among the furiously perma +2049|83083|8100|6|17|18123.36|0.07|0.00|N|O|1996-02-04|1996-03-01|1996-02-24|NONE|FOB|al, regular foxes. pending, +2050|72622|7637|1|47|74947.14|0.05|0.03|A|F|1994-08-25|1994-07-18|1994-09-15|DELIVER IN PERSON|TRUCK|tside the blithely pending packages eat f +2050|151587|1588|2|48|78651.84|0.05|0.01|A|F|1994-09-30|1994-08-23|1994-10-29|COLLECT COD|AIR| final packages. pinto +2050|112099|2100|3|41|45554.69|0.10|0.04|A|F|1994-06-08|1994-08-27|1994-06-23|NONE|AIR| final theodolites. depende +2050|31521|9031|4|11|15977.72|0.02|0.01|A|F|1994-07-27|1994-08-18|1994-08-02|DELIVER IN PERSON|REG AIR|ns. bold, final ideas cajole among the fi +2050|167826|7827|5|16|30301.12|0.07|0.01|R|F|1994-08-17|1994-07-28|1994-09-05|DELIVER IN PERSON|REG AIR|al accounts. closely even +2050|48412|3421|6|29|39451.89|0.00|0.05|A|F|1994-09-23|1994-08-01|1994-10-23|TAKE BACK RETURN|MAIL|oxes alongsid +2050|47268|9773|7|25|30381.50|0.10|0.00|R|F|1994-08-18|1994-07-04|1994-09-04|TAKE BACK RETURN|RAIL|y according to +2051|24284|4285|1|43|51956.04|0.08|0.04|N|O|1996-04-22|1996-06-16|1996-04-28|COLLECT COD|RAIL|ounts sleep fluffily even requ +2051|129342|9343|2|48|65824.32|0.01|0.02|N|O|1996-05-04|1996-06-14|1996-05-19|NONE|TRUCK|unts. pending platelets believe about +2052|67826|333|1|50|89691.00|0.09|0.08|R|F|1992-06-22|1992-06-03|1992-07-19|DELIVER IN PERSON|AIR|wake after the decoy +2052|134863|7377|2|35|66425.10|0.09|0.05|A|F|1992-05-29|1992-05-24|1992-06-11|NONE|TRUCK|ts according t +2052|42203|9716|3|16|18323.20|0.01|0.08|A|F|1992-06-30|1992-07-09|1992-07-12|NONE|SHIP|y final deposits cajole according +2052|95911|5912|4|47|89624.77|0.08|0.01|A|F|1992-06-18|1992-05-16|1992-07-02|TAKE BACK RETURN|REG AIR|final requests. stealt +2053|100687|3198|1|20|33753.60|0.09|0.00|A|F|1995-04-25|1995-04-12|1995-05-13|NONE|TRUCK|ly ironic foxes haggle slyly speci +2053|32300|2301|2|34|41898.20|0.07|0.00|A|F|1995-03-15|1995-03-20|1995-04-09|TAKE BACK RETURN|TRUCK|ions. unusual dependencies +2053|64279|9292|3|46|57190.42|0.01|0.03|R|F|1995-04-01|1995-04-02|1995-04-18|NONE|RAIL|tions. furiously even requests hagg +2053|120953|3466|4|31|61192.45|0.06|0.08|R|F|1995-03-23|1995-03-13|1995-04-16|DELIVER IN PERSON|SHIP|ts. fluffily final mul +2054|112318|2319|1|11|14633.41|0.03|0.05|R|F|1992-08-13|1992-08-26|1992-08-22|NONE|AIR|ular accou +2054|119303|4326|2|31|40991.30|0.05|0.08|A|F|1992-08-18|1992-09-04|1992-08-24|NONE|FOB|se bold, regular accounts. unusual depos +2054|120984|985|3|32|64159.36|0.06|0.00|A|F|1992-06-23|1992-07-08|1992-07-22|NONE|FOB| packages thrash. carefully final +2054|173988|9023|4|14|28867.72|0.10|0.05|R|F|1992-06-25|1992-09-05|1992-07-14|DELIVER IN PERSON|SHIP|uickly final +2054|5970|971|5|40|75038.80|0.08|0.06|R|F|1992-06-23|1992-08-09|1992-07-04|TAKE BACK RETURN|RAIL|n pinto beans. ironic courts are iro +2054|133446|5960|6|17|25150.48|0.08|0.01|A|F|1992-06-09|1992-08-28|1992-06-16|NONE|AIR|ges nag acc +2054|10356|7860|7|4|5065.40|0.00|0.08|R|F|1992-08-12|1992-08-31|1992-08-15|DELIVER IN PERSON|AIR|lyly careful requests wake fl +2055|44447|4448|1|15|20871.60|0.04|0.06|A|F|1993-09-15|1993-10-06|1993-10-07|NONE|REG AIR|furiously bold +2055|8279|8280|2|15|17809.05|0.06|0.05|R|F|1993-10-30|1993-11-21|1993-11-22|COLLECT COD|RAIL|gular foxes. b +2055|134333|6847|3|12|16407.96|0.00|0.02|A|F|1993-10-26|1993-11-23|1993-11-22|COLLECT COD|TRUCK|al pains. acco +2055|133702|6216|4|16|27771.20|0.02|0.02|A|F|1993-11-16|1993-11-12|1993-11-28|NONE|TRUCK|arefully daringly regular accounts. +2080|6855|4356|1|5|8809.25|0.08|0.05|R|F|1993-08-26|1993-08-07|1993-09-02|DELIVER IN PERSON|TRUCK|refully unusual theo +2080|196959|9479|2|39|80182.05|0.07|0.04|A|F|1993-08-22|1993-09-09|1993-08-23|COLLECT COD|FOB|ic deposits haggle slyly carefully eve +2081|88449|5974|1|26|37373.44|0.03|0.08|N|O|1997-10-21|1997-10-03|1997-11-10|NONE|FOB|among the slyly express accounts. silen +2081|148309|3338|2|13|17644.90|0.07|0.05|N|O|1997-08-23|1997-08-22|1997-09-09|TAKE BACK RETURN|MAIL|fter the even deposi +2081|12941|7944|3|32|59326.08|0.09|0.07|N|O|1997-09-05|1997-09-26|1997-10-03|TAKE BACK RETURN|SHIP|e. final, regular dependencies sleep slyly! +2081|84662|4663|4|23|37873.18|0.03|0.08|N|O|1997-07-06|1997-09-11|1997-07-21|TAKE BACK RETURN|MAIL|ual requests wake blithely above the +2081|112141|4653|5|19|21909.66|0.02|0.06|N|O|1997-10-01|1997-08-12|1997-10-18|COLLECT COD|SHIP|s affix sometimes express requests. quickly +2081|141545|4060|6|31|49182.74|0.03|0.06|N|O|1997-09-19|1997-09-13|1997-09-27|NONE|AIR| silent, spe +2082|74452|1974|1|36|51352.20|0.00|0.00|R|F|1995-01-20|1995-03-18|1995-01-31|COLLECT COD|MAIL|haggle furiously silent pinto beans +2082|104536|9557|2|12|18486.36|0.08|0.05|A|F|1995-01-27|1995-02-11|1995-02-07|NONE|FOB| ironic instructions. carefull +2083|23917|8922|1|37|68113.67|0.07|0.00|R|F|1993-09-07|1993-09-30|1993-09-18|TAKE BACK RETURN|MAIL|ng the special foxes wake packages. f +2084|181162|8717|1|42|52212.72|0.03|0.05|A|F|1993-03-29|1993-05-05|1993-04-22|COLLECT COD|REG AIR|y fluffily even foxes. +2084|179838|2356|2|23|44110.09|0.09|0.08|A|F|1993-06-05|1993-05-26|1993-06-06|DELIVER IN PERSON|AIR|es against +2084|135354|2894|3|37|51405.95|0.07|0.05|A|F|1993-07-16|1993-04-20|1993-08-06|NONE|AIR|y careful courts. +2084|93773|1301|4|9|15900.93|0.02|0.02|A|F|1993-03-18|1993-06-08|1993-03-30|NONE|TRUCK|heaves boost slyly after the pla +2084|26853|4360|5|28|49835.80|0.07|0.02|R|F|1993-05-04|1993-05-14|1993-05-31|COLLECT COD|TRUCK|cajole quickly carefu +2084|114964|7476|6|15|29684.40|0.09|0.04|A|F|1993-06-23|1993-04-25|1993-07-23|COLLECT COD|SHIP|tithes. bravely pendi +2084|193410|5930|7|34|51115.94|0.09|0.02|R|F|1993-06-20|1993-05-28|1993-06-25|DELIVER IN PERSON|RAIL| carefully ironic requests. fluffil +2085|40196|2701|1|45|51128.55|0.00|0.07|R|F|1994-02-27|1994-01-11|1994-03-29|TAKE BACK RETURN|MAIL|. carefully e +2086|59829|9830|1|22|39354.04|0.03|0.07|R|F|1994-12-04|1994-12-16|1994-12-20|DELIVER IN PERSON|RAIL|idly busy acc +2086|140912|8455|2|32|62493.12|0.04|0.06|A|F|1994-11-15|1995-01-05|1994-12-09|TAKE BACK RETURN|TRUCK|e carefully along th +2086|104938|4939|3|44|85488.92|0.02|0.01|A|F|1994-12-04|1994-11-30|1994-12-21|DELIVER IN PERSON|FOB|latelets s +2086|83891|8908|4|27|50622.03|0.02|0.00|A|F|1994-11-04|1995-01-14|1994-11-25|COLLECT COD|REG AIR|theodolites haggle blithely blithe p +2086|155067|98|5|33|37027.98|0.04|0.00|A|F|1995-02-06|1994-11-25|1995-02-15|NONE|SHIP| slyly regular foxes. un +2086|199165|4204|6|20|25283.20|0.01|0.03|R|F|1994-11-30|1994-12-28|1994-12-07|COLLECT COD|FOB|lithely ironic acc +2086|155955|3501|7|7|14076.65|0.04|0.05|R|F|1994-12-27|1994-12-10|1995-01-05|COLLECT COD|RAIL| beans haggle car +2087|126684|6685|1|1|1710.68|0.05|0.04|N|O|1998-03-27|1998-03-24|1998-04-18|DELIVER IN PERSON|REG AIR|the quickly idle acco +2087|167256|4805|2|46|60869.50|0.10|0.03|N|O|1998-02-24|1998-04-02|1998-03-04|DELIVER IN PERSON|AIR|ter the dolphins. +2087|61740|1741|3|1|1701.74|0.02|0.05|N|O|1998-05-27|1998-04-11|1998-06-12|COLLECT COD|REG AIR|hely final acc +2087|58738|6254|4|6|10180.38|0.03|0.08|N|O|1998-04-23|1998-03-27|1998-05-18|DELIVER IN PERSON|REG AIR|dazzle after the slyly si +2112|70095|96|1|18|19171.62|0.02|0.05|N|O|1997-05-02|1997-03-16|1997-05-25|TAKE BACK RETURN|TRUCK|lphins solve ideas. even, special reque +2113|122730|5243|1|40|70109.20|0.04|0.06|N|O|1998-01-16|1997-12-11|1998-02-06|TAKE BACK RETURN|TRUCK|bout the quickly ironic t +2113|111214|8748|2|24|29405.04|0.03|0.02|N|O|1998-02-19|1998-01-08|1998-03-16|COLLECT COD|MAIL|kly regular accounts hinder about the +2114|167477|7478|1|50|77223.50|0.05|0.05|A|F|1995-02-05|1995-03-18|1995-02-13|COLLECT COD|RAIL|pecial pinto bean +2114|185076|113|2|26|30187.82|0.02|0.02|A|F|1995-04-30|1995-04-16|1995-05-28|NONE|SHIP|ar asymptotes sleep +2114|161760|4277|3|25|45544.00|0.07|0.01|A|F|1995-02-15|1995-03-13|1995-02-22|COLLECT COD|AIR|unts. regular, express accounts wake. b +2115|195180|7700|1|27|34429.86|0.06|0.03|N|O|1998-09-01|1998-07-29|1998-09-04|NONE|AIR|de of the carefully bold accounts +2115|183023|578|2|43|47558.86|0.06|0.02|N|O|1998-07-14|1998-07-25|1998-07-24|COLLECT COD|FOB| carefully pending requests alongs +2115|50851|8367|3|3|5405.55|0.03|0.04|N|O|1998-07-23|1998-07-30|1998-08-14|DELIVER IN PERSON|FOB|quickly ironic dolphin +2115|48123|8124|4|47|50342.64|0.06|0.07|N|O|1998-08-29|1998-07-30|1998-09-05|TAKE BACK RETURN|REG AIR|regular accounts integrate brav +2115|198956|6514|5|13|26714.35|0.04|0.00|N|O|1998-08-07|1998-08-06|1998-08-13|DELIVER IN PERSON|REG AIR|into beans. even accounts abou +2116|130050|51|1|2|2160.10|0.00|0.02|R|F|1994-10-16|1994-11-24|1994-11-09|DELIVER IN PERSON|TRUCK|r theodolites use blithely about the ir +2116|139382|9383|2|47|66804.86|0.10|0.06|R|F|1994-09-01|1994-11-18|1994-09-25|COLLECT COD|MAIL|iously ironic dependencies around the iro +2116|183247|5766|3|11|14632.64|0.03|0.05|R|F|1994-09-15|1994-10-21|1994-09-21|NONE|FOB| pinto beans. final, final sauternes play +2117|164531|9564|1|36|57439.08|0.10|0.01|N|O|1997-08-06|1997-07-15|1997-08-07|DELIVER IN PERSON|SHIP|ronic accounts wake +2117|60193|7712|2|19|21910.61|0.04|0.00|N|O|1997-07-30|1997-06-18|1997-08-13|DELIVER IN PERSON|REG AIR|s between the slyly regula +2117|57434|2445|3|43|59831.49|0.04|0.03|N|O|1997-06-27|1997-06-12|1997-07-22|DELIVER IN PERSON|SHIP| foxes sleep furiously +2117|90507|5526|4|24|35940.00|0.00|0.07|N|O|1997-06-15|1997-05-27|1997-06-18|COLLECT COD|SHIP|thely slyly pending platelets. ironic, +2117|146773|6774|5|3|5459.31|0.02|0.05|N|O|1997-05-05|1997-07-20|1997-05-26|TAKE BACK RETURN|TRUCK|tes cajole +2117|179|2680|6|27|29137.59|0.09|0.08|N|O|1997-06-30|1997-06-27|1997-07-11|TAKE BACK RETURN|REG AIR| the carefully ironic ideas +2118|159552|9553|1|24|38677.20|0.10|0.03|N|O|1997-01-06|1996-12-14|1997-01-14|TAKE BACK RETURN|RAIL|about the slyly bold depende +2118|183278|3279|2|4|5445.08|0.08|0.01|N|O|1996-10-25|1996-11-10|1996-11-22|COLLECT COD|AIR|theodolites affix according +2118|144382|1925|3|11|15690.18|0.05|0.04|N|O|1996-12-23|1996-12-20|1997-01-01|COLLECT COD|RAIL|y ironic accounts sleep upon the packages. +2119|101751|6772|1|36|63099.00|0.04|0.00|N|O|1996-11-10|1996-10-25|1996-12-03|TAKE BACK RETURN|RAIL|ly bold foxes. ironic accoun +2144|91477|9005|1|33|48459.51|0.00|0.07|R|F|1994-04-04|1994-06-20|1994-04-23|NONE|AIR| ironic excuses haggle final dependencies. +2144|50884|3390|2|46|84404.48|0.03|0.08|R|F|1994-04-08|1994-04-29|1994-05-07|COLLECT COD|SHIP| foxes haggle blithel +2144|3496|8497|3|29|40585.21|0.00|0.07|R|F|1994-05-03|1994-05-16|1994-06-01|DELIVER IN PERSON|FOB|ns wake carefully carefully ironic +2144|157171|7172|4|10|12281.70|0.00|0.04|R|F|1994-06-16|1994-05-03|1994-07-05|COLLECT COD|AIR| furiously unusual ideas. carefull +2145|77370|9878|1|13|17515.81|0.04|0.05|A|F|1992-11-12|1992-12-13|1992-12-07|TAKE BACK RETURN|MAIL|alongside of the slyly final +2145|153894|1440|2|6|11687.34|0.05|0.01|A|F|1992-10-10|1992-11-29|1992-10-14|NONE|AIR|s. fluffily express accounts sleep. slyl +2146|56891|9397|1|42|77611.38|0.10|0.01|A|F|1992-09-21|1992-11-02|1992-09-23|NONE|AIR|ns according to the doggedly +2146|156627|9143|2|6|10101.72|0.07|0.05|A|F|1993-01-03|1992-10-24|1993-01-24|DELIVER IN PERSON|RAIL|ing to the requests. dependencies boost +2146|24361|1868|3|14|17995.04|0.03|0.01|R|F|1992-09-16|1992-10-16|1992-09-20|COLLECT COD|SHIP|ecial, express a +2146|25952|3459|4|31|58216.45|0.02|0.00|A|F|1993-01-04|1992-10-24|1993-01-15|DELIVER IN PERSON|TRUCK|lly even deposit +2146|168542|6091|5|28|45095.12|0.02|0.05|R|F|1993-01-03|1992-10-17|1993-01-08|COLLECT COD|MAIL|r accounts sleep furio +2146|70175|7697|6|32|36645.44|0.07|0.03|R|F|1993-01-10|1992-10-19|1993-02-05|COLLECT COD|TRUCK|y regular foxes wake among the final +2146|24278|4279|7|39|46888.53|0.07|0.06|R|F|1993-01-05|1992-11-06|1993-01-14|DELIVER IN PERSON|TRUCK|uickly regular excuses detect. regular c +2147|28768|3773|1|50|84838.00|0.04|0.06|R|F|1992-11-18|1992-11-30|1992-11-30|NONE|RAIL|al accounts. even, even foxes wake +2147|100604|605|2|4|6418.40|0.01|0.04|A|F|1992-09-27|1992-11-15|1992-10-22|NONE|AIR|mong the blithely special +2147|43483|8492|3|34|48500.32|0.10|0.04|R|F|1992-11-29|1992-11-08|1992-12-22|TAKE BACK RETURN|REG AIR|egular deposits hang car +2147|10236|5239|4|11|12608.53|0.06|0.07|A|F|1992-09-27|1992-11-16|1992-10-16|NONE|AIR| the fluffily +2148|115933|3467|1|21|40927.53|0.09|0.01|R|F|1995-05-28|1995-05-26|1995-06-15|NONE|FOB|deposits ag +2149|18213|5717|1|12|13574.52|0.05|0.07|R|F|1993-06-01|1993-05-06|1993-06-11|TAKE BACK RETURN|TRUCK|riously bl +2149|98974|8975|2|10|19729.70|0.06|0.01|R|F|1993-06-09|1993-04-17|1993-06-16|DELIVER IN PERSON|TRUCK|eposits sleep above +2149|48678|3687|3|47|76453.49|0.00|0.04|R|F|1993-06-27|1993-05-12|1993-07-11|COLLECT COD|AIR|hely final depo +2149|128105|3130|4|18|20395.80|0.06|0.00|A|F|1993-04-05|1993-05-11|1993-04-23|DELIVER IN PERSON|REG AIR|uriously final pac +2149|59360|4371|5|22|29025.92|0.06|0.04|R|F|1993-05-24|1993-04-23|1993-06-20|TAKE BACK RETURN|SHIP|ptotes sleep along the blithely ir +2150|77886|2901|1|26|48460.88|0.00|0.03|A|F|1994-06-21|1994-08-05|1994-06-23|NONE|TRUCK|. always unusual packages +2150|17738|5242|2|29|48016.17|0.04|0.03|A|F|1994-09-02|1994-08-04|1994-10-02|TAKE BACK RETURN|RAIL|y ironic theodolites. foxes ca +2150|106769|1790|3|29|51497.04|0.04|0.08|R|F|1994-06-10|1994-07-31|1994-06-26|COLLECT COD|RAIL|arefully final att +2150|53727|1243|4|39|65548.08|0.05|0.02|R|F|1994-07-31|1994-08-17|1994-08-11|TAKE BACK RETURN|TRUCK|ess accounts nag. unusual asymptotes haggl +2150|182496|2497|5|35|55247.15|0.01|0.01|A|F|1994-09-27|1994-08-17|1994-10-13|COLLECT COD|RAIL|refully pending dependen +2150|6331|8832|6|12|14847.96|0.09|0.03|A|F|1994-08-27|1994-08-22|1994-09-18|COLLECT COD|AIR|press platelets haggle until the slyly fi +2151|166944|4493|1|23|46251.62|0.06|0.02|N|O|1996-11-20|1996-12-17|1996-11-30|DELIVER IN PERSON|AIR| silent dependencies about the slyl +2151|14480|6982|2|29|40439.92|0.00|0.02|N|O|1997-03-04|1996-12-27|1997-03-21|TAKE BACK RETURN|SHIP| bold packages acro +2151|164838|9871|3|49|93238.67|0.07|0.01|N|O|1997-01-20|1997-02-09|1997-02-18|NONE|FOB| packages. f +2151|17670|2673|4|28|44454.76|0.10|0.08|N|O|1996-12-11|1996-12-26|1996-12-12|DELIVER IN PERSON|AIR|y special packages. carefully ironic instru +2176|190213|5252|1|38|49521.98|0.02|0.08|R|F|1992-11-29|1993-01-14|1992-12-22|DELIVER IN PERSON|REG AIR|lithely ironic pinto beans. furious +2176|94137|9156|2|14|15835.82|0.00|0.06|A|F|1992-11-17|1993-01-07|1992-12-03|DELIVER IN PERSON|SHIP|ely ironic platelets +2176|159466|9467|3|25|38136.50|0.02|0.02|R|F|1993-02-23|1993-01-05|1993-03-07|COLLECT COD|RAIL| ruthless deposits according to the ent +2176|142226|7255|4|2|2536.44|0.05|0.06|A|F|1993-02-26|1993-01-08|1993-03-23|DELIVER IN PERSON|AIR|s pinto beans +2177|128562|8563|1|45|71575.20|0.02|0.01|N|O|1997-02-11|1997-02-27|1997-02-17|NONE|SHIP|. theodolites haggle carefu +2177|138448|962|2|27|40133.88|0.04|0.08|N|O|1997-01-29|1997-03-20|1997-02-04|DELIVER IN PERSON|SHIP|even, regula +2177|80066|2575|3|23|24059.38|0.07|0.05|N|O|1997-01-28|1997-03-02|1997-02-13|DELIVER IN PERSON|AIR|he silent foxes. iro +2177|54933|7439|4|34|64189.62|0.05|0.07|N|O|1997-02-03|1997-04-10|1997-02-21|COLLECT COD|REG AIR|tes are doggedly quickly +2177|56437|3953|5|46|64097.78|0.09|0.05|N|O|1997-05-10|1997-02-23|1997-05-28|COLLECT COD|RAIL|ending asymptotes. +2177|121616|4129|6|11|18013.71|0.02|0.04|N|O|1997-03-20|1997-03-07|1997-04-09|DELIVER IN PERSON|MAIL|gainst the ca +2178|156127|1158|1|15|17746.80|0.10|0.01|N|O|1997-03-27|1997-03-10|1997-04-18|NONE|REG AIR|l accounts. quickly expr +2178|15804|8306|2|27|46434.60|0.01|0.02|N|O|1997-02-26|1997-02-19|1997-03-25|NONE|MAIL| across the ironic reques +2178|4825|2326|3|40|69192.80|0.00|0.03|N|O|1997-03-17|1997-02-09|1997-04-15|COLLECT COD|RAIL|foxes are slowly regularly specia +2178|77639|5161|4|3|4849.89|0.07|0.07|N|O|1997-04-07|1997-01-23|1997-04-18|COLLECT COD|MAIL| permanentl +2179|129479|4504|1|22|33186.34|0.05|0.08|N|O|1996-11-16|1996-11-03|1996-11-25|DELIVER IN PERSON|FOB|lphins cajole acr +2179|138056|570|2|20|21881.00|0.03|0.01|N|O|1996-09-30|1996-11-10|1996-10-30|NONE|REG AIR|ncies. fin +2179|103363|8384|3|5|6831.80|0.03|0.02|N|O|1996-11-09|1996-10-08|1996-11-11|DELIVER IN PERSON|REG AIR|ts haggle blithely. ironic, careful theodol +2179|5267|2768|4|24|28134.24|0.04|0.04|N|O|1996-10-26|1996-11-05|1996-11-16|COLLECT COD|RAIL| cajole carefully. +2179|107337|4868|5|7|9410.31|0.00|0.02|N|O|1996-10-24|1996-11-14|1996-11-21|TAKE BACK RETURN|RAIL|gular dependencies. ironic packages haggle +2180|15125|128|1|31|32243.72|0.06|0.04|N|O|1996-10-20|1996-11-21|1996-11-06|COLLECT COD|REG AIR|n requests are furiously at the quickly +2180|192230|9788|2|39|51566.97|0.01|0.00|N|O|1997-01-03|1996-10-29|1997-01-25|NONE|RAIL|ep furiously furiously final request +2180|196985|9505|3|24|49967.52|0.03|0.00|N|O|1997-01-03|1996-10-24|1997-01-19|NONE|SHIP|uriously f +2180|110249|2761|4|47|59184.28|0.07|0.02|N|O|1996-09-23|1996-12-08|1996-10-12|NONE|FOB|pending, regular ideas. iron +2180|142825|368|5|23|42959.86|0.02|0.06|N|O|1996-11-08|1996-10-25|1996-11-28|NONE|TRUCK|ggle alongside of the fluffily speci +2180|54140|4141|6|48|52518.72|0.09|0.03|N|O|1996-12-30|1996-11-22|1997-01-16|DELIVER IN PERSON|RAIL|nic instructions haggle careful +2181|177848|7849|1|4|7703.36|0.05|0.04|N|O|1995-09-25|1995-11-12|1995-09-28|COLLECT COD|FOB|tes. slyly silent packages use along th +2181|87791|2808|2|46|81824.34|0.00|0.02|N|O|1995-11-28|1995-10-17|1995-12-26|COLLECT COD|AIR|osits. final packages sleep +2181|90740|741|3|15|25961.10|0.08|0.05|N|O|1995-10-05|1995-10-27|1995-11-03|DELIVER IN PERSON|FOB|e above the fluffily regul +2181|54662|9673|4|28|45266.48|0.04|0.05|N|O|1995-12-21|1995-10-23|1996-01-04|TAKE BACK RETURN|AIR|s excuses sleep car +2181|95783|5784|5|9|16009.02|0.06|0.07|N|O|1996-01-05|1995-12-05|1996-01-08|COLLECT COD|TRUCK|ward the quietly even requests. ir +2182|131671|9211|1|27|45972.09|0.02|0.07|R|F|1994-05-10|1994-07-04|1994-06-04|DELIVER IN PERSON|SHIP|en platele +2182|189760|7315|2|3|5549.28|0.05|0.03|R|F|1994-04-20|1994-07-04|1994-04-24|TAKE BACK RETURN|SHIP|y bold theodolites wi +2182|93343|5853|3|34|45435.56|0.02|0.03|R|F|1994-05-28|1994-06-02|1994-06-10|COLLECT COD|MAIL| slow tithes. ironi +2182|6068|3569|4|12|11688.72|0.04|0.07|A|F|1994-05-08|1994-06-02|1994-05-09|COLLECT COD|REG AIR|ments are fu +2182|178869|1387|5|37|72070.82|0.06|0.02|A|F|1994-04-08|1994-06-29|1994-04-18|TAKE BACK RETURN|TRUCK|ges. blithely ironic +2183|70665|3173|1|29|47434.14|0.05|0.01|N|O|1996-07-21|1996-08-24|1996-08-15|TAKE BACK RETURN|RAIL|ly unusual deposits sleep carefully +2183|51094|1095|2|25|26127.25|0.06|0.02|N|O|1996-07-06|1996-08-21|1996-08-05|NONE|RAIL|he quickly f +2208|57232|2243|1|48|57083.04|0.08|0.07|A|F|1995-05-13|1995-06-30|1995-05-20|COLLECT COD|MAIL|sits. idly permanent request +2208|96798|4326|2|11|19742.69|0.08|0.01|A|F|1995-05-06|1995-07-19|1995-05-22|COLLECT COD|TRUCK|ding waters lose. furiously regu +2208|73389|5897|3|41|55857.58|0.08|0.02|N|O|1995-08-18|1995-06-19|1995-09-05|COLLECT COD|RAIL|nd the furious, express dependencies. +2208|42342|9855|4|50|64217.00|0.07|0.07|N|F|1995-06-11|1995-05-31|1995-06-29|TAKE BACK RETURN|FOB|al foxes will hav +2208|29570|2073|5|43|64481.51|0.03|0.06|A|F|1995-05-10|1995-06-02|1995-06-09|TAKE BACK RETURN|MAIL|es. accounts cajole. fi +2208|166229|3778|6|18|23313.96|0.02|0.08|R|F|1995-06-06|1995-06-10|1995-06-11|TAKE BACK RETURN|TRUCK|packages are quickly bold de +2208|6106|1107|7|45|45544.50|0.00|0.08|A|F|1995-05-05|1995-06-10|1995-05-11|NONE|SHIP|e fluffily regular theodolites caj +2209|22676|7681|1|40|63946.80|0.05|0.01|R|F|1992-11-01|1992-09-25|1992-11-08|DELIVER IN PERSON|SHIP|ully special sheaves serve +2209|102771|2772|2|10|17737.70|0.00|0.02|R|F|1992-09-02|1992-09-24|1992-09-21|DELIVER IN PERSON|AIR|players. carefully reg +2209|63521|8534|3|11|16329.72|0.01|0.01|A|F|1992-07-12|1992-08-24|1992-08-10|DELIVER IN PERSON|REG AIR|express, regular pinto be +2209|180897|3416|4|39|77137.71|0.08|0.07|R|F|1992-11-04|1992-09-02|1992-11-11|TAKE BACK RETURN|MAIL|ly around the final packages. deposits ca +2209|123364|901|5|24|33296.64|0.08|0.06|R|F|1992-08-09|1992-08-18|1992-08-25|COLLECT COD|AIR| along the bol +2209|177413|2448|6|7|10432.87|0.09|0.07|A|F|1992-08-18|1992-09-09|1992-09-12|DELIVER IN PERSON|AIR| quickly regular pack +2210|77764|2779|1|36|62703.36|0.10|0.00|A|F|1992-03-04|1992-03-24|1992-03-21|DELIVER IN PERSON|AIR| requests wake enticingly final +2211|47822|2831|1|25|44245.50|0.04|0.01|A|F|1994-10-09|1994-08-04|1994-11-03|TAKE BACK RETURN|RAIL|deas. carefully special theodolites along +2211|139773|2287|2|40|72510.80|0.09|0.06|A|F|1994-09-30|1994-09-10|1994-10-26|NONE|MAIL|posits among the express dolphins +2211|159820|7366|3|25|46995.50|0.00|0.07|A|F|1994-08-13|1994-08-17|1994-08-16|NONE|AIR|ly regular, express +2211|84711|9728|4|23|39001.33|0.03|0.02|R|F|1994-10-05|1994-09-13|1994-10-17|DELIVER IN PERSON|AIR|ependencies +2211|134301|6815|5|3|4005.90|0.02|0.04|A|F|1994-08-28|1994-09-10|1994-09-06|TAKE BACK RETURN|SHIP|pendencies after the regular f +2211|186189|6190|6|18|22953.24|0.05|0.08|A|F|1994-08-31|1994-09-07|1994-09-22|NONE|TRUCK|c grouches. slyly express pinto +2211|78139|647|7|3|3351.39|0.06|0.05|R|F|1994-09-21|1994-08-10|1994-10-19|TAKE BACK RETURN|RAIL|y slyly final +2212|70810|5825|1|18|32054.58|0.07|0.06|R|F|1994-06-22|1994-06-18|1994-06-25|TAKE BACK RETURN|FOB| cajole. final, pending ideas should are bl +2213|117158|4692|1|20|23503.00|0.01|0.00|A|F|1993-01-21|1993-04-14|1993-01-29|COLLECT COD|REG AIR|iously express accounts; +2213|59646|9647|2|4|6422.56|0.09|0.05|R|F|1993-04-15|1993-04-15|1993-05-05|COLLECT COD|SHIP| affix carefully furiously +2213|69541|7060|3|1|1510.54|0.05|0.05|A|F|1993-04-25|1993-04-06|1993-04-28|TAKE BACK RETURN|AIR|s along the ironic reques +2213|173204|8239|4|39|49810.80|0.09|0.05|A|F|1993-05-12|1993-04-07|1993-05-23|TAKE BACK RETURN|SHIP|the blithely +2213|37976|2983|5|43|82300.71|0.04|0.03|A|F|1993-04-18|1993-03-11|1993-05-11|TAKE BACK RETURN|RAIL|r packages are along the carefully bol +2213|47675|180|6|41|66529.47|0.01|0.00|R|F|1993-01-31|1993-03-31|1993-02-28|COLLECT COD|FOB| carefully pend +2213|63836|1355|7|3|5399.49|0.02|0.04|A|F|1993-03-09|1993-03-17|1993-04-07|TAKE BACK RETURN|AIR|o wake. ironic platel +2214|75623|638|1|27|43162.74|0.04|0.04|N|O|1998-05-31|1998-06-07|1998-06-19|DELIVER IN PERSON|REG AIR|x fluffily along the even packages-- +2214|193950|3951|2|50|102197.50|0.00|0.02|N|O|1998-07-06|1998-06-16|1998-07-16|TAKE BACK RETURN|MAIL|accounts. blith +2214|112406|4918|3|42|59572.80|0.04|0.08|N|O|1998-05-26|1998-07-13|1998-06-22|COLLECT COD|FOB|ons. deposi +2214|195389|428|4|22|32656.36|0.01|0.01|N|O|1998-05-30|1998-07-02|1998-06-09|DELIVER IN PERSON|RAIL|t the blithely +2215|72044|9566|1|33|33529.32|0.00|0.00|N|O|1996-07-19|1996-08-10|1996-07-30|COLLECT COD|RAIL|dolites cajole b +2215|32526|5030|2|30|43755.60|0.01|0.00|N|O|1996-08-15|1996-09-10|1996-08-25|NONE|FOB|ckages caj +2215|56652|9158|3|30|48259.50|0.07|0.03|N|O|1996-09-09|1996-07-20|1996-09-28|COLLECT COD|TRUCK|against the carefu +2215|145112|7627|4|20|23142.20|0.02|0.02|N|O|1996-09-09|1996-08-10|1996-09-19|NONE|MAIL| unusual deposits haggle carefully. ide +2240|163898|6415|1|6|11771.34|0.01|0.00|A|F|1992-06-23|1992-05-17|1992-07-20|COLLECT COD|AIR|ymptotes boost. furiously bold p +2240|27897|5404|2|37|67520.93|0.03|0.07|R|F|1992-03-16|1992-05-31|1992-04-05|COLLECT COD|FOB| quickly after the packages? blithely si +2240|52103|9619|3|39|41148.90|0.08|0.06|A|F|1992-05-22|1992-05-10|1992-06-08|NONE|FOB|y orbits. final depos +2240|85867|884|4|10|18528.60|0.09|0.00|A|F|1992-05-25|1992-04-14|1992-06-23|DELIVER IN PERSON|REG AIR|are across the ironic packages. +2240|160522|3039|5|29|45893.08|0.02|0.06|A|F|1992-03-29|1992-05-08|1992-04-09|COLLECT COD|MAIL|lyly even ideas w +2240|80721|722|6|32|54455.04|0.06|0.06|R|F|1992-04-11|1992-04-18|1992-04-22|NONE|MAIL|ss thinly deposits. blithely bold package +2240|77504|2519|7|24|35556.00|0.04|0.05|R|F|1992-05-13|1992-04-09|1992-05-14|DELIVER IN PERSON|FOB|ng the silent accounts. slyly ironic t +2241|4034|4035|1|25|23450.75|0.00|0.08|R|F|1993-08-11|1993-07-23|1993-09-01|DELIVER IN PERSON|MAIL| final deposits use fluffily. even f +2241|194616|9655|2|38|65003.18|0.04|0.06|A|F|1993-08-04|1993-07-31|1993-08-06|TAKE BACK RETURN|TRUCK| silent, unusual d +2241|96673|1692|3|48|80144.16|0.08|0.04|A|F|1993-05-14|1993-07-30|1993-05-26|TAKE BACK RETURN|RAIL|ss accounts engage furiously. slyly even re +2241|166305|1338|4|19|26054.70|0.10|0.00|A|F|1993-06-01|1993-08-05|1993-06-07|TAKE BACK RETURN|TRUCK| are furiously quickl +2241|81485|1486|5|2|2932.96|0.04|0.03|A|F|1993-08-16|1993-08-02|1993-08-24|NONE|REG AIR|, express deposits. pear +2241|115401|424|6|22|31160.80|0.02|0.08|R|F|1993-08-13|1993-06-15|1993-08-16|DELIVER IN PERSON|TRUCK|, ironic depen +2241|141592|1593|7|9|14702.31|0.09|0.03|A|F|1993-05-14|1993-07-12|1993-05-29|NONE|AIR|lyly final +2242|122099|2100|1|15|16816.35|0.09|0.08|N|O|1997-08-04|1997-09-21|1997-08-11|COLLECT COD|FOB|its. carefully express packages cajole. bli +2243|126988|6989|1|10|20149.80|0.04|0.06|N|O|1995-07-26|1995-07-18|1995-08-03|NONE|RAIL|express, daring foxes affix fur +2244|50086|5097|1|3|3108.24|0.02|0.02|A|F|1993-04-30|1993-03-15|1993-05-19|TAKE BACK RETURN|FOB| beans for the regular platel +2244|192426|7465|2|16|24294.72|0.01|0.06|R|F|1993-02-12|1993-03-09|1993-02-28|COLLECT COD|FOB|rate around the reques +2245|75664|5665|1|44|72145.04|0.03|0.03|A|F|1993-06-12|1993-06-10|1993-06-16|NONE|TRUCK|refully even sheaves +2245|73630|8645|2|28|44901.64|0.05|0.03|R|F|1993-08-19|1993-07-27|1993-09-04|COLLECT COD|TRUCK|e requests sleep furiou +2245|85310|7819|3|33|42745.23|0.03|0.01|R|F|1993-06-26|1993-06-11|1993-07-17|TAKE BACK RETURN|AIR|ing to the carefully ruthless accounts +2245|188474|8475|4|14|21874.58|0.02|0.04|R|F|1993-05-06|1993-07-21|1993-05-19|DELIVER IN PERSON|RAIL|nts. always unusual dep +2245|79264|6786|5|33|41027.58|0.03|0.07|R|F|1993-06-16|1993-06-05|1993-07-07|NONE|MAIL| across the express reques +2246|52330|2331|1|22|28211.26|0.02|0.01|N|O|1996-07-25|1996-08-03|1996-08-24|DELIVER IN PERSON|SHIP|ructions wake carefully fina +2246|103090|3091|2|43|47002.87|0.07|0.06|N|O|1996-08-25|1996-08-23|1996-09-19|DELIVER IN PERSON|AIR|ainst the ironic theodolites haggle fi +2246|17158|4662|3|11|11826.65|0.10|0.00|N|O|1996-06-21|1996-07-24|1996-07-18|TAKE BACK RETURN|TRUCK|quests alongside o +2246|162721|270|4|13|23188.36|0.08|0.05|N|O|1996-09-15|1996-07-21|1996-10-08|DELIVER IN PERSON|AIR|equests. fluffily special epitaphs use +2247|171922|4440|1|12|23927.04|0.02|0.07|A|F|1992-09-06|1992-09-18|1992-09-26|NONE|MAIL|final accounts. requests across the furiou +2272|89989|9990|1|18|35621.64|0.04|0.00|R|F|1993-08-01|1993-07-06|1993-08-25|NONE|MAIL|ons along the blithely e +2272|33466|976|2|40|55978.40|0.07|0.00|A|F|1993-04-25|1993-07-12|1993-05-15|DELIVER IN PERSON|FOB|lithely ir +2272|55426|7932|3|36|49731.12|0.03|0.02|A|F|1993-05-25|1993-05-23|1993-06-09|TAKE BACK RETURN|RAIL|about the ironic packages; quickly iron +2272|137602|116|4|30|49188.00|0.09|0.07|A|F|1993-07-27|1993-05-15|1993-08-13|NONE|RAIL|quests at the foxes haggle evenly pack +2272|75858|3380|5|12|22006.20|0.03|0.03|A|F|1993-04-19|1993-05-14|1993-04-23|NONE|RAIL| accounts cajole. quickly b +2273|183596|8633|1|34|57106.06|0.02|0.03|N|O|1997-01-08|1997-02-02|1997-01-23|COLLECT COD|MAIL| furiously carefully bold de +2273|84638|9655|2|35|56792.05|0.00|0.05|N|O|1997-01-02|1997-01-19|1997-01-14|NONE|REG AIR|arefully f +2273|94138|9157|3|8|9057.04|0.00|0.04|N|O|1996-12-15|1997-02-27|1997-01-10|NONE|FOB|dependencies. slyly ir +2273|160895|8444|4|20|39117.80|0.06|0.04|N|O|1997-03-05|1997-02-25|1997-04-01|NONE|RAIL|cuses. quickly enticing requests wake +2273|161026|8575|5|18|19566.36|0.07|0.00|N|O|1996-12-16|1997-01-21|1997-01-03|COLLECT COD|TRUCK| beans. doggedly final packages wake +2273|154366|1912|6|16|22725.76|0.10|0.03|N|O|1997-01-10|1997-02-03|1997-02-01|TAKE BACK RETURN|RAIL|furiously above the ironic requests. +2273|19493|9494|7|7|9887.43|0.05|0.05|N|O|1997-02-19|1997-01-22|1997-02-21|TAKE BACK RETURN|TRUCK|ts. furiou +2274|11038|3540|1|18|17082.54|0.04|0.03|R|F|1993-09-06|1993-12-03|1993-09-22|COLLECT COD|SHIP|usly final re +2274|110510|5533|2|23|34971.73|0.04|0.03|R|F|1993-10-28|1993-11-03|1993-11-05|NONE|MAIL|kly special warhorse +2274|128795|8796|3|18|32828.22|0.03|0.06|R|F|1993-09-28|1993-11-22|1993-10-12|DELIVER IN PERSON|SHIP| express packages. even accounts hagg +2275|33183|8190|1|30|33485.40|0.08|0.05|R|F|1993-01-10|1992-11-21|1993-01-22|NONE|REG AIR|re slyly slyly special idea +2275|90399|5418|2|11|15283.29|0.08|0.03|A|F|1993-01-16|1992-12-10|1993-01-25|COLLECT COD|REG AIR|ost across the never express instruction +2276|118185|5719|1|5|6015.90|0.07|0.08|N|O|1996-05-09|1996-06-18|1996-05-13|DELIVER IN PERSON|FOB|ias instea +2276|134871|2411|2|13|24776.31|0.08|0.04|N|O|1996-07-24|1996-06-18|1996-08-16|COLLECT COD|RAIL|arefully ironic foxes cajole q +2276|170995|996|3|27|55781.73|0.07|0.08|N|O|1996-07-30|1996-06-10|1996-07-31|DELIVER IN PERSON|RAIL|the carefully unusual accoun +2276|108060|5591|4|38|40586.28|0.06|0.03|N|O|1996-07-07|1996-06-28|1996-07-17|COLLECT COD|RAIL|ans. pinto beans boost c +2276|152402|9948|5|50|72720.00|0.03|0.05|N|O|1996-07-13|1996-06-25|1996-07-22|DELIVER IN PERSON|REG AIR| accounts dete +2276|5041|7542|6|4|3784.16|0.10|0.03|N|O|1996-07-05|1996-06-30|1996-08-04|COLLECT COD|FOB|s. deposits +2277|136849|6850|1|38|71661.92|0.03|0.07|R|F|1995-04-23|1995-03-25|1995-05-20|TAKE BACK RETURN|TRUCK|fully bold +2277|7914|415|2|2|3643.82|0.10|0.08|A|F|1995-02-01|1995-02-04|1995-03-02|TAKE BACK RETURN|AIR|endencies sleep idly pending p +2277|197832|352|3|4|7719.32|0.05|0.06|R|F|1995-04-27|1995-03-16|1995-04-29|TAKE BACK RETURN|SHIP|. quickly unusual deposi +2277|158467|3498|4|31|47289.26|0.02|0.00|R|F|1995-03-07|1995-03-19|1995-03-26|TAKE BACK RETURN|MAIL|ic instructions detect ru +2278|44247|6752|1|36|42884.64|0.04|0.05|N|O|1998-06-04|1998-06-06|1998-06-30|NONE|TRUCK|y ironic pinto beans br +2278|44868|7373|2|50|90643.00|0.02|0.00|N|O|1998-08-09|1998-07-08|1998-09-05|DELIVER IN PERSON|RAIL|into beans. blit +2278|96343|8853|3|22|29465.48|0.03|0.00|N|O|1998-05-15|1998-07-14|1998-06-04|TAKE BACK RETURN|REG AIR|ep regular accounts. blithely even +2279|13676|3677|1|12|19076.04|0.07|0.08|A|F|1993-05-10|1993-03-25|1993-06-02|COLLECT COD|REG AIR|lets across the excuses nag quickl +2279|40972|973|2|38|72692.86|0.08|0.07|R|F|1993-06-09|1993-04-06|1993-06-26|COLLECT COD|TRUCK|s above the furiously express dep +2279|3443|5944|3|3|4039.32|0.09|0.04|A|F|1993-05-31|1993-05-07|1993-06-05|COLLECT COD|REG AIR|ing foxes above the even accounts use slyly +2279|51132|8648|4|42|45491.46|0.02|0.00|R|F|1993-02-28|1993-04-25|1993-03-02|TAKE BACK RETURN|REG AIR| above the furiously ironic deposits. +2279|168844|1361|5|9|17215.56|0.05|0.04|R|F|1993-05-21|1993-03-29|1993-06-17|DELIVER IN PERSON|MAIL|ns cajole after the final platelets. s +2279|146161|1190|6|12|14485.92|0.02|0.00|R|F|1993-05-04|1993-04-26|1993-05-28|DELIVER IN PERSON|FOB|ccounts. slyl +2279|118915|6449|7|32|61885.12|0.05|0.05|A|F|1993-04-20|1993-05-22|1993-05-18|DELIVER IN PERSON|RAIL|re quickly. furiously ironic ide +2304|199490|2010|1|42|66758.58|0.00|0.01|A|F|1994-01-20|1994-03-04|1994-02-05|COLLECT COD|RAIL|quests are blithely alongside of +2304|18186|5690|2|48|53000.64|0.00|0.00|R|F|1994-02-12|1994-02-16|1994-03-10|COLLECT COD|REG AIR| deposits cajole blithely e +2304|47934|7935|3|3|5645.79|0.00|0.05|R|F|1994-03-19|1994-03-04|1994-03-20|DELIVER IN PERSON|AIR|l excuses after the ev +2305|173979|6497|1|3|6158.91|0.00|0.01|A|F|1993-03-24|1993-04-05|1993-03-29|NONE|AIR|kages haggle quickly across the blithely +2305|59018|1524|2|39|38103.39|0.07|0.00|R|F|1993-04-16|1993-04-17|1993-04-22|COLLECT COD|MAIL|ms after the foxes +2305|101013|1014|3|32|32448.32|0.03|0.06|A|F|1993-04-02|1993-03-18|1993-04-03|NONE|AIR| haggle caref +2305|111463|1464|4|17|25065.82|0.00|0.05|A|F|1993-02-21|1993-03-30|1993-03-19|TAKE BACK RETURN|MAIL| carefully alongside of +2305|154380|1926|5|26|37293.88|0.06|0.07|A|F|1993-05-14|1993-02-28|1993-06-04|NONE|SHIP|arefully final theodo +2305|50969|8485|6|7|13439.72|0.06|0.00|R|F|1993-05-15|1993-04-25|1993-06-09|DELIVER IN PERSON|RAIL|gular deposits boost about the foxe +2306|195761|800|1|50|92838.00|0.09|0.01|N|O|1995-07-27|1995-09-26|1995-08-06|DELIVER IN PERSON|FOB|y quickly +2306|148556|3585|2|39|62577.45|0.04|0.00|N|O|1995-09-07|1995-09-13|1995-10-03|COLLECT COD|SHIP|f the slyly unusual accounts. furiousl +2306|177684|5236|3|35|61658.80|0.01|0.07|N|O|1995-08-18|1995-08-30|1995-08-20|TAKE BACK RETURN|RAIL|raids along the furiously unusual asympto +2306|118936|1448|4|21|41053.53|0.06|0.01|N|O|1995-10-07|1995-09-18|1995-10-17|COLLECT COD|MAIL| ironic pinto +2306|141746|4261|5|42|75085.08|0.04|0.07|N|O|1995-09-05|1995-08-25|1995-09-28|COLLECT COD|MAIL|furiously final acco +2306|123507|3508|6|29|44384.50|0.00|0.03|N|O|1995-11-01|1995-09-01|1995-11-22|DELIVER IN PERSON|REG AIR|uld have to mold. s +2306|175400|2952|7|19|28032.60|0.07|0.01|N|O|1995-11-17|1995-09-06|1995-11-30|DELIVER IN PERSON|AIR|tainments nag furiously carefull +2307|141367|3882|1|24|33800.64|0.10|0.05|R|F|1993-10-07|1993-08-05|1993-10-20|COLLECT COD|AIR|stealthily special packages nag a +2307|139516|2030|2|2|3111.02|0.01|0.00|A|F|1993-09-21|1993-08-22|1993-10-03|COLLECT COD|SHIP|ously. furiously furious requ +2307|33306|5810|3|7|8675.10|0.07|0.04|R|F|1993-08-03|1993-09-04|1993-08-28|DELIVER IN PERSON|AIR|ven instructions wake fluffily +2307|164357|4358|4|19|27005.65|0.08|0.06|R|F|1993-10-23|1993-09-09|1993-11-09|TAKE BACK RETURN|TRUCK|olites haggle furiously around the +2307|142685|2686|5|7|12093.76|0.01|0.06|R|F|1993-09-01|1993-08-08|1993-09-29|NONE|AIR| packages cajo +2308|117514|7515|1|24|36756.24|0.06|0.04|R|F|1993-02-23|1992-12-24|1993-03-10|NONE|MAIL|ts sleep. busy excuses along the s +2308|55630|641|2|36|57082.68|0.05|0.06|A|F|1992-11-11|1992-11-27|1992-11-23|NONE|MAIL|ong the pending hockey players. blithe +2309|169856|4889|1|14|26961.90|0.10|0.03|N|O|1996-01-01|1995-10-22|1996-01-23|NONE|AIR|asymptotes. furiously pending acco +2309|168253|770|2|1|1321.25|0.01|0.05|N|O|1995-12-08|1995-11-03|1995-12-31|COLLECT COD|RAIL|eposits alongside of the final re +2309|14764|9767|3|5|8393.80|0.01|0.00|N|O|1995-12-10|1995-10-29|1996-01-06|TAKE BACK RETURN|SHIP|s. requests wake blithely specia +2309|138046|3073|4|46|49865.84|0.08|0.04|N|O|1995-10-02|1995-10-30|1995-10-30|NONE|REG AIR|sly according to the carefully +2309|136205|3745|5|9|11170.80|0.00|0.07|N|O|1995-12-21|1995-10-10|1996-01-20|COLLECT COD|AIR|ding, unusual instructions. dep +2309|194880|9919|6|21|41472.48|0.09|0.00|N|O|1995-11-05|1995-11-07|1995-11-22|NONE|AIR|unts around the dolphins ar +2309|137744|258|7|48|85523.52|0.03|0.05|N|O|1995-10-21|1995-11-21|1995-11-09|NONE|MAIL|ccounts. id +2310|57879|385|1|36|66127.32|0.03|0.03|N|O|1996-10-09|1996-10-28|1996-10-29|TAKE BACK RETURN|RAIL|iously against the slyly special accounts +2310|170444|445|2|6|9086.64|0.07|0.01|N|O|1996-11-08|1996-12-09|1996-12-07|COLLECT COD|REG AIR|e slyly about the quickly ironic theodo +2310|41031|8544|3|48|46657.44|0.08|0.02|N|O|1996-10-04|1996-11-20|1996-10-25|TAKE BACK RETURN|FOB|ep slyly alongside of the +2311|140068|2583|1|18|19945.08|0.01|0.01|N|F|1995-06-11|1995-06-18|1995-07-02|NONE|FOB| fluffily even patterns haggle blithely. re +2311|121572|6597|2|49|78084.93|0.09|0.02|R|F|1995-05-14|1995-07-11|1995-05-20|COLLECT COD|FOB|ideas sleep +2311|53793|3794|3|15|26201.85|0.08|0.04|N|O|1995-06-23|1995-06-06|1995-07-09|COLLECT COD|AIR|ve the blithely pending accounts. furio +2311|89740|4757|4|42|72649.08|0.01|0.06|R|F|1995-06-03|1995-06-27|1995-06-11|DELIVER IN PERSON|MAIL|gle furiously. bold +2311|46446|1455|5|1|1392.44|0.05|0.02|A|F|1995-06-07|1995-06-20|1995-06-10|NONE|AIR|ptotes. furiously regular theodolite +2311|11993|6996|6|32|60959.68|0.01|0.03|N|O|1995-07-19|1995-06-26|1995-07-26|NONE|RAIL|sts along the slyly +2336|192161|4681|1|20|25063.20|0.01|0.03|N|O|1996-03-12|1996-02-25|1996-03-18|NONE|REG AIR|across the fi +2337|44792|7297|1|49|85102.71|0.06|0.05|N|O|1997-08-08|1997-08-15|1997-08-31|TAKE BACK RETURN|FOB| along the packages. furiously p +2338|51054|6065|1|30|30151.50|0.07|0.06|N|O|1997-12-10|1997-10-15|1997-12-11|TAKE BACK RETURN|REG AIR|ould have to nag quickly +2339|191542|1543|1|22|35937.88|0.03|0.03|A|F|1994-01-06|1994-03-06|1994-01-10|NONE|FOB| furiously above +2339|29709|2212|2|28|45883.60|0.00|0.00|R|F|1994-01-25|1994-01-22|1994-01-28|DELIVER IN PERSON|RAIL|e bold, even packag +2339|116749|1772|3|13|22954.62|0.06|0.08|R|F|1994-03-10|1994-02-18|1994-03-20|TAKE BACK RETURN|REG AIR|ges. blithely special depend +2340|137788|5328|1|9|16432.02|0.08|0.02|N|O|1996-05-01|1996-02-24|1996-05-16|COLLECT COD|RAIL|. carefully ironic +2340|192904|5424|2|21|41934.90|0.06|0.02|N|O|1996-01-17|1996-03-04|1996-01-29|DELIVER IN PERSON|SHIP| asymptotes. unusual theo +2341|46009|1018|1|12|11460.00|0.08|0.03|R|F|1993-06-06|1993-07-08|1993-06-17|DELIVER IN PERSON|FOB|. quickly final deposits sl +2341|70364|5379|2|37|49371.32|0.07|0.08|A|F|1993-09-23|1993-07-25|1993-10-14|DELIVER IN PERSON|RAIL|was blithel +2341|194541|9580|3|8|13084.32|0.03|0.07|R|F|1993-06-08|1993-07-09|1993-06-10|COLLECT COD|FOB|ns affix above the iron +2342|41169|8682|1|12|13321.92|0.00|0.08|N|O|1996-07-31|1996-07-26|1996-08-14|NONE|TRUCK|print blithely even deposits. carefull +2342|116462|8974|2|24|35483.04|0.10|0.06|N|O|1996-09-30|1996-07-22|1996-10-28|TAKE BACK RETURN|AIR|nstructions c +2342|169920|9921|3|50|99496.00|0.10|0.01|N|O|1996-08-28|1996-07-18|1996-09-22|COLLECT COD|RAIL|cial asymptotes pr +2342|35809|5810|4|1|1744.80|0.04|0.06|N|O|1996-08-31|1996-08-09|1996-09-07|DELIVER IN PERSON|REG AIR|ffily. unusual pinto beans wake c +2342|26756|9259|5|22|37020.50|0.08|0.01|N|O|1996-08-10|1996-08-02|1996-08-31|DELIVER IN PERSON|AIR|s. ironic +2343|109899|9900|1|27|51540.03|0.00|0.00|N|O|1995-11-10|1995-11-17|1995-12-10|TAKE BACK RETURN|SHIP|old theodolites. +2343|65555|3074|2|35|53219.25|0.03|0.06|N|O|1995-10-24|1995-11-09|1995-10-26|COLLECT COD|TRUCK|ges haggle furiously carefully regular req +2343|178754|6306|3|21|38487.75|0.00|0.03|N|O|1995-09-07|1995-10-26|1995-10-07|TAKE BACK RETURN|RAIL|osits. unusual theodolites boost furio +2368|151986|1987|1|16|32607.68|0.04|0.03|R|F|1993-10-31|1993-10-22|1993-11-06|NONE|REG AIR|telets wake carefully iro +2368|13052|3053|2|32|30881.60|0.03|0.00|R|F|1993-09-23|1993-10-07|1993-09-27|COLLECT COD|TRUCK|gular courts use blithely around the +2368|148805|1320|3|39|72298.20|0.08|0.03|R|F|1993-09-03|1993-09-20|1993-09-28|COLLECT COD|RAIL|ng the doggedly ironic requests are blithe +2368|155900|3446|4|17|33250.30|0.10|0.08|A|F|1993-10-03|1993-09-27|1993-10-05|NONE|FOB|fily. slyly final ideas alongside o +2369|23834|1341|1|30|52734.90|0.05|0.04|N|O|1997-04-23|1997-02-12|1997-05-21|COLLECT COD|REG AIR|pecial deposits sleep. blithely unusual w +2369|168416|8417|2|47|69767.27|0.10|0.02|N|O|1997-01-02|1997-02-18|1997-01-13|COLLECT COD|RAIL| to the regular dep +2370|45041|7546|1|3|2958.12|0.03|0.07|R|F|1994-03-24|1994-03-26|1994-04-15|COLLECT COD|SHIP|ly regular Tiresia +2370|1051|3552|2|24|22849.20|0.00|0.05|A|F|1994-05-15|1994-04-09|1994-06-12|NONE|REG AIR|final depen +2370|60844|845|3|32|57754.88|0.05|0.02|A|F|1994-04-24|1994-03-03|1994-05-15|DELIVER IN PERSON|MAIL|ies since the final deposits +2370|5044|2545|4|21|19929.84|0.04|0.01|R|F|1994-02-01|1994-02-19|1994-02-09|TAKE BACK RETURN|MAIL|ecial dependencies must have to +2371|158603|3634|1|37|61479.20|0.05|0.05|N|O|1998-02-11|1998-03-24|1998-02-27|DELIVER IN PERSON|TRUCK|s boost fluffil +2371|34147|6651|2|21|22703.94|0.00|0.05|N|O|1998-04-14|1998-02-14|1998-04-18|COLLECT COD|AIR|gle furiously regu +2371|100521|3032|3|11|16736.72|0.05|0.02|N|O|1998-02-25|1998-04-06|1998-03-23|TAKE BACK RETURN|TRUCK|requests. regular pinto beans wake. car +2371|42076|7085|4|33|33596.31|0.05|0.08|N|O|1998-03-30|1998-02-06|1998-04-05|DELIVER IN PERSON|AIR|deas are. express r +2371|164508|9541|5|22|34595.00|0.02|0.05|N|O|1998-03-26|1998-03-19|1998-04-16|DELIVER IN PERSON|REG AIR|y daring accounts. regular ins +2371|85027|5028|6|39|39468.78|0.05|0.03|N|O|1998-04-01|1998-03-13|1998-04-27|NONE|REG AIR|tructions. regular, stealthy packages wak +2371|35714|8218|7|32|52790.72|0.07|0.07|N|O|1998-02-15|1998-04-03|1998-02-23|NONE|REG AIR|the ruthless accounts. +2372|42661|2662|1|42|67353.72|0.08|0.02|N|O|1998-01-04|1998-01-02|1998-02-02|COLLECT COD|REG AIR|lar packages. regular +2372|2319|9820|2|17|20762.27|0.07|0.01|N|O|1997-12-17|1998-01-17|1997-12-25|NONE|RAIL|xcuses. slyly ironic theod +2372|163333|8366|3|12|16755.96|0.04|0.04|N|O|1998-03-21|1997-12-21|1998-04-12|DELIVER IN PERSON|SHIP|lyly according to +2372|121677|6702|4|4|6794.68|0.00|0.07|N|O|1997-12-14|1997-12-28|1997-12-16|TAKE BACK RETURN|REG AIR|e carefully blithely even epitaphs. r +2372|19420|4423|5|5|6697.10|0.02|0.04|N|O|1998-02-08|1998-01-18|1998-03-02|TAKE BACK RETURN|RAIL|ets against the +2372|188437|5992|6|11|16779.73|0.02|0.06|N|O|1998-02-14|1998-01-18|1998-03-10|TAKE BACK RETURN|FOB| silent, pending de +2372|56012|6013|7|19|18392.19|0.01|0.06|N|O|1997-12-26|1998-02-19|1998-01-02|COLLECT COD|SHIP| beans haggle sometimes +2373|190025|7583|1|17|18955.34|0.02|0.01|R|F|1994-03-29|1994-05-19|1994-04-20|COLLECT COD|AIR|auternes. blithely even pinto bea +2373|135214|2754|2|3|3747.63|0.08|0.08|R|F|1994-05-15|1994-06-10|1994-06-04|COLLECT COD|TRUCK|dependencies wake ironical +2373|140804|3319|3|29|53499.20|0.05|0.02|A|F|1994-06-01|1994-05-14|1994-06-17|NONE|TRUCK|yly silent ideas affix furiousl +2373|90692|8220|4|5|8413.45|0.10|0.01|R|F|1994-06-02|1994-05-03|1994-06-21|NONE|REG AIR|uffily blithely ironic requests +2374|117116|9628|1|41|46457.51|0.07|0.00|A|F|1994-01-27|1993-12-11|1994-02-12|TAKE BACK RETURN|RAIL|heodolites. requests +2374|159783|7329|2|24|44226.72|0.07|0.08|A|F|1994-02-02|1994-01-12|1994-02-04|DELIVER IN PERSON|TRUCK|. requests are above t +2374|60682|5695|3|2|3285.36|0.06|0.02|R|F|1993-12-30|1994-01-24|1994-01-02|COLLECT COD|FOB|, unusual ideas. deposits cajole quietl +2374|73993|3994|4|28|55075.72|0.04|0.08|R|F|1994-02-19|1993-12-16|1994-03-15|COLLECT COD|MAIL|ets cajole fu +2374|309|310|5|25|30232.50|0.08|0.00|A|F|1993-11-26|1993-12-15|1993-12-10|COLLECT COD|RAIL|refully pending d +2375|167272|7273|1|3|4017.81|0.02|0.08|N|O|1997-02-14|1996-12-25|1997-02-22|COLLECT COD|RAIL|slyly across the furiously e +2375|131282|3796|2|9|11819.52|0.09|0.02|N|O|1997-02-17|1996-12-27|1997-02-27|DELIVER IN PERSON|MAIL|ly against the packages. bold pinto bean +2375|46470|8975|3|26|36828.22|0.02|0.06|N|O|1997-03-18|1997-02-02|1997-03-29|TAKE BACK RETURN|TRUCK|rate across the +2375|4801|7302|4|5|8529.00|0.01|0.00|N|O|1997-01-31|1997-01-25|1997-02-22|COLLECT COD|REG AIR|final packages cajole according to the furi +2375|87210|4735|5|42|50282.82|0.01|0.08|N|O|1997-01-24|1997-02-15|1997-02-07|DELIVER IN PERSON|FOB|apades. idea +2375|125524|5525|6|20|30990.40|0.09|0.08|N|O|1996-12-01|1996-12-26|1996-12-19|TAKE BACK RETURN|SHIP|ckages! blithely enticing deposi +2400|102546|5057|1|48|74329.92|0.01|0.02|N|O|1998-10-07|1998-08-30|1998-11-03|DELIVER IN PERSON|MAIL|fore the car +2400|89966|2475|2|1|1955.96|0.04|0.07|N|O|1998-08-18|1998-09-12|1998-09-11|NONE|MAIL|silent deposits serve furious +2400|52503|19|3|23|33476.50|0.02|0.08|N|O|1998-08-05|1998-08-28|1998-08-30|NONE|SHIP|tions. fluffily ironic platelets cajole c +2400|16820|4324|4|23|39946.86|0.09|0.04|N|O|1998-10-04|1998-10-04|1998-10-31|NONE|RAIL|ages lose carefully around the regula +2401|181615|4134|1|39|66167.79|0.00|0.03|N|O|1997-09-29|1997-10-21|1997-10-17|DELIVER IN PERSON|FOB|ould affix +2401|2221|7222|2|49|55037.78|0.05|0.07|N|O|1997-09-02|1997-09-11|1997-09-13|TAKE BACK RETURN|AIR|lites cajole carefully +2402|85533|8042|1|43|65296.79|0.03|0.08|N|O|1996-09-17|1996-11-20|1996-09-22|DELIVER IN PERSON|RAIL|slyly slyly blithe sheaves +2402|151328|8874|2|24|33103.68|0.02|0.05|N|O|1996-11-21|1996-10-19|1996-11-29|DELIVER IN PERSON|SHIP|as; blithely ironic requ +2403|82868|393|1|34|62929.24|0.04|0.07|N|O|1998-05-30|1998-06-19|1998-06-05|NONE|REG AIR| slyly bold re +2403|151901|9447|2|19|37105.10|0.08|0.07|N|O|1998-04-20|1998-07-02|1998-05-13|DELIVER IN PERSON|FOB|sits. ironic in +2403|192434|2435|3|27|41213.61|0.05|0.03|N|O|1998-07-27|1998-07-08|1998-08-03|NONE|SHIP|deposits sleep slyly special theodolit +2403|30422|423|4|30|40572.60|0.05|0.06|N|O|1998-08-08|1998-06-17|1998-08-20|NONE|TRUCK|ackages sleep furiously pendin +2404|146703|1732|1|36|62989.20|0.07|0.00|N|O|1997-03-27|1997-05-16|1997-04-06|COLLECT COD|REG AIR|s nag furi +2404|35641|8145|2|1|1576.64|0.02|0.04|N|O|1997-05-22|1997-06-06|1997-05-28|DELIVER IN PERSON|MAIL|from the final orbits? even pinto beans hag +2404|17378|2381|3|41|53110.17|0.02|0.06|N|O|1997-06-12|1997-05-03|1997-07-12|NONE|AIR| dolphins are +2404|56668|6669|4|19|30868.54|0.09|0.03|N|O|1997-05-07|1997-05-24|1997-05-24|TAKE BACK RETURN|SHIP|cuses. quickly even in +2404|3058|8059|5|18|17298.90|0.00|0.04|N|O|1997-06-25|1997-05-06|1997-07-02|NONE|RAIL|packages. even requests according to +2405|88560|3577|1|18|27874.08|0.09|0.07|N|O|1997-01-23|1997-03-10|1997-02-03|COLLECT COD|REG AIR|carefully ironic accounts. slyly +2405|26169|3676|2|30|32854.80|0.10|0.08|N|O|1997-03-24|1997-03-10|1997-04-14|TAKE BACK RETURN|AIR|y final deposits are slyly caref +2405|16135|6136|3|49|51505.37|0.00|0.06|N|O|1996-12-24|1997-03-23|1997-01-01|TAKE BACK RETURN|FOB|cial requests. ironic, regu +2405|176791|9309|4|23|42959.17|0.08|0.05|N|O|1996-12-28|1997-01-29|1997-01-07|NONE|AIR|t wake blithely blithely regular idea +2406|169075|6624|1|18|20593.26|0.07|0.05|N|O|1997-02-17|1996-12-25|1997-02-19|COLLECT COD|MAIL|azzle furiously careful +2406|40475|2980|2|40|56618.80|0.02|0.07|N|O|1997-01-09|1996-12-02|1997-01-16|NONE|SHIP|gular accounts caj +2406|49072|9073|3|16|16337.12|0.07|0.03|N|O|1996-10-31|1996-11-28|1996-11-08|TAKE BACK RETURN|SHIP| special accou +2406|145035|64|4|34|36721.02|0.07|0.06|N|O|1996-12-01|1996-12-07|1996-12-16|NONE|AIR|hinly even accounts are slyly q +2406|186950|9469|5|25|50923.75|0.08|0.02|N|O|1996-12-03|1996-12-14|1996-12-26|COLLECT COD|MAIL|al, regular in +2406|58277|3288|6|22|27175.94|0.05|0.02|N|O|1996-11-22|1997-01-17|1996-12-15|NONE|TRUCK|hely even foxes unwind furiously aga +2406|59491|7007|7|30|43514.70|0.07|0.07|N|O|1997-01-17|1997-01-12|1997-01-22|TAKE BACK RETURN|TRUCK| final pinto beans han +2407|63032|5539|1|14|13930.42|0.04|0.02|N|O|1998-10-10|1998-08-25|1998-10-27|NONE|FOB|l dependencies s +2407|165166|5167|2|9|11080.44|0.07|0.05|N|O|1998-08-06|1998-08-11|1998-08-20|TAKE BACK RETURN|TRUCK|ts. special deposits are closely. +2407|130261|262|3|39|50359.14|0.02|0.02|N|O|1998-08-20|1998-09-12|1998-08-22|DELIVER IN PERSON|MAIL|iously final deposits solv +2407|90439|5458|4|10|14294.30|0.01|0.07|N|O|1998-08-14|1998-09-10|1998-08-29|COLLECT COD|FOB| pending instructions. theodolites x- +2407|197553|2592|5|14|23107.70|0.04|0.05|N|O|1998-09-24|1998-08-18|1998-10-06|DELIVER IN PERSON|FOB|tructions wake stealt +2407|70290|7812|6|18|22685.22|0.04|0.01|N|O|1998-10-03|1998-08-30|1998-10-19|TAKE BACK RETURN|MAIL| wake carefully. fluffily +2407|160877|5910|7|7|13565.09|0.07|0.03|N|O|1998-09-11|1998-08-15|1998-09-30|TAKE BACK RETURN|MAIL|totes are carefully accordin +2432|49371|4380|1|30|39611.10|0.03|0.02|N|O|1996-09-05|1996-10-10|1996-10-05|TAKE BACK RETURN|TRUCK| requests wake alongside of +2432|161797|1798|2|8|14870.32|0.07|0.01|N|O|1996-10-16|1996-10-01|1996-11-13|COLLECT COD|RAIL|s about the bold, close deposit +2432|108837|1348|3|13|23995.79|0.07|0.06|N|O|1996-09-03|1996-10-10|1996-10-03|NONE|RAIL|arefully about the caref +2432|12405|2406|4|14|18443.60|0.00|0.06|N|O|1996-08-18|1996-09-04|1996-08-27|TAKE BACK RETURN|RAIL|riously regular packages. p +2433|86794|6795|1|39|69450.81|0.01|0.04|R|F|1994-11-20|1994-09-23|1994-12-10|DELIVER IN PERSON|SHIP|ly final asy +2433|133323|8350|2|20|27126.40|0.05|0.06|A|F|1994-12-09|1994-10-20|1994-12-15|COLLECT COD|REG AIR|lithely blithely final ide +2433|156347|1378|3|38|53326.92|0.08|0.03|A|F|1994-10-15|1994-10-23|1994-11-06|DELIVER IN PERSON|SHIP|. slyly regular requests sle +2433|120254|2767|4|43|54792.75|0.01|0.05|A|F|1994-10-16|1994-10-23|1994-11-08|DELIVER IN PERSON|RAIL|ular requests. slyly even pa +2433|107164|9675|5|3|3513.48|0.06|0.02|A|F|1994-11-08|1994-09-24|1994-11-17|COLLECT COD|AIR|usly pending depos +2434|94433|4434|1|1|1427.43|0.01|0.06|N|O|1997-08-02|1997-05-28|1997-08-19|TAKE BACK RETURN|MAIL| furiously express packages. ironic, pend +2434|126777|4314|2|39|70347.03|0.09|0.05|N|O|1997-06-10|1997-06-08|1997-07-03|COLLECT COD|RAIL|r deposits sleep furiou +2434|129445|6982|3|28|41284.32|0.02|0.05|N|O|1997-06-28|1997-06-26|1997-07-15|COLLECT COD|RAIL|ven theodolites around the slyly +2434|167173|7174|4|49|60768.33|0.00|0.05|N|O|1997-08-08|1997-07-23|1997-08-27|DELIVER IN PERSON|FOB| after the requests haggle bold, fina +2435|38868|8869|1|8|14454.88|0.08|0.03|A|F|1993-06-08|1993-04-04|1993-06-29|COLLECT COD|SHIP|e fluffily quickly final accounts. care +2435|48350|3359|2|43|55829.05|0.03|0.08|A|F|1993-03-27|1993-05-20|1993-04-18|DELIVER IN PERSON|TRUCK|alongside of the s +2435|11457|6460|3|24|32842.80|0.07|0.08|R|F|1993-03-14|1993-05-20|1993-03-26|DELIVER IN PERSON|SHIP|s. carefully regular d +2435|155868|8384|4|22|42324.92|0.02|0.05|R|F|1993-05-23|1993-04-14|1993-06-04|NONE|SHIP|e final, final deposits. carefully regular +2435|71676|4184|5|3|4943.01|0.07|0.07|R|F|1993-06-01|1993-03-25|1993-06-27|DELIVER IN PERSON|FOB| final accounts ar +2435|45524|533|6|17|24981.84|0.02|0.02|A|F|1993-06-05|1993-05-05|1993-06-14|NONE|TRUCK|cajole aft +2435|120686|5711|7|8|13653.44|0.07|0.02|R|F|1993-05-03|1993-04-02|1993-05-17|COLLECT COD|SHIP|ng the fluffily special foxes nag +2436|154062|4063|1|48|53570.88|0.04|0.02|N|O|1995-10-22|1995-10-22|1995-11-16|DELIVER IN PERSON|FOB|he furiously +2436|116509|4043|2|18|27459.00|0.05|0.03|N|O|1995-10-14|1995-11-21|1995-11-12|TAKE BACK RETURN|TRUCK|y ironic accounts. furiously even packa +2436|163647|6164|3|6|10263.84|0.06|0.08|N|O|1995-10-25|1995-11-30|1995-11-24|DELIVER IN PERSON|RAIL|odolites. ep +2437|93699|6209|1|46|77863.74|0.07|0.04|A|F|1993-08-12|1993-06-16|1993-08-29|NONE|RAIL|e of the bold, dogged requests +2437|189398|1917|2|26|38672.14|0.00|0.04|A|F|1993-06-25|1993-05-22|1993-07-07|DELIVER IN PERSON|REG AIR|lyly regular accounts. +2437|1745|6746|3|23|37875.02|0.01|0.00|A|F|1993-08-15|1993-06-28|1993-08-23|TAKE BACK RETURN|SHIP|s deposits. pendi +2437|115739|8251|4|12|21056.76|0.03|0.08|A|F|1993-04-27|1993-07-01|1993-05-18|TAKE BACK RETURN|FOB|thely regular deposits. ironic fray +2437|16697|4201|5|29|46797.01|0.02|0.06|A|F|1993-05-12|1993-06-10|1993-05-25|NONE|FOB|ress dolphins. furiously fin +2437|18571|1073|6|10|14895.70|0.10|0.06|A|F|1993-05-20|1993-06-23|1993-05-22|TAKE BACK RETURN|MAIL|unts. even, ironic pl +2438|164492|9525|1|45|70042.05|0.01|0.00|A|F|1993-10-27|1993-09-24|1993-11-02|COLLECT COD|REG AIR|en theodolites w +2438|12785|2786|2|31|52631.18|0.08|0.01|R|F|1993-10-16|1993-08-31|1993-11-10|COLLECT COD|REG AIR|t. slyly ironic sh +2438|67446|9953|3|10|14134.40|0.10|0.00|R|F|1993-08-18|1993-08-28|1993-09-08|NONE|SHIP|engage car +2438|160408|5441|4|27|39646.80|0.01|0.02|R|F|1993-07-27|1993-10-01|1993-08-06|TAKE BACK RETURN|FOB|inal accounts. slyly final reques +2438|165750|783|5|28|50841.00|0.07|0.06|R|F|1993-11-05|1993-08-22|1993-11-22|TAKE BACK RETURN|TRUCK|ctions. bli +2438|148426|941|6|23|33911.66|0.09|0.02|R|F|1993-10-06|1993-08-17|1993-10-16|DELIVER IN PERSON|MAIL|ely; blithely special pinto beans breach +2438|182589|7626|7|46|76892.68|0.02|0.05|R|F|1993-10-27|1993-08-30|1993-11-14|COLLECT COD|SHIP| ironic requests cajole f +2439|163036|8069|1|2|2198.06|0.09|0.03|N|O|1997-04-14|1997-06-11|1997-05-09|COLLECT COD|MAIL|courts boos +2439|143488|3489|2|5|7657.40|0.07|0.01|N|O|1997-04-23|1997-04-26|1997-04-28|DELIVER IN PERSON|FOB|ites. furiously +2439|194676|7196|3|33|58432.11|0.08|0.05|N|O|1997-06-01|1997-05-15|1997-06-07|TAKE BACK RETURN|FOB|asymptotes wake packages-- furiously +2464|48367|5880|1|10|13153.60|0.05|0.03|N|O|1998-02-04|1997-12-29|1998-02-16|TAKE BACK RETURN|RAIL|slyly final pinto bean +2464|100451|5472|2|20|29029.00|0.01|0.07|N|O|1997-12-26|1998-01-02|1998-01-24|DELIVER IN PERSON|FOB|sts. slyly close ideas shall h +2465|67190|2203|1|27|31244.13|0.05|0.02|N|O|1995-09-05|1995-09-07|1995-09-17|DELIVER IN PERSON|FOB|posits boost carefully unusual instructio +2465|50636|8152|2|34|53945.42|0.02|0.05|N|O|1995-10-02|1995-08-04|1995-10-09|COLLECT COD|RAIL|posits wake. regular package +2465|31032|6039|3|8|7704.24|0.10|0.00|N|O|1995-10-16|1995-08-26|1995-11-07|TAKE BACK RETURN|FOB|s across the express deposits wak +2465|147716|5259|4|45|79366.95|0.03|0.01|N|O|1995-09-27|1995-08-25|1995-10-06|NONE|TRUCK|y silent foxes. final pinto beans above +2465|46762|9267|5|50|85438.00|0.01|0.04|N|O|1995-09-01|1995-09-06|1995-09-18|TAKE BACK RETURN|TRUCK|the pending th +2465|123555|3556|6|20|31571.00|0.03|0.03|N|O|1995-08-16|1995-08-13|1995-09-02|COLLECT COD|FOB|uriously? furiously ironic excu +2466|185322|2877|1|16|22517.12|0.00|0.02|R|F|1994-04-20|1994-04-20|1994-05-09|COLLECT COD|FOB|to beans sl +2466|104696|7207|2|10|17006.90|0.00|0.00|A|F|1994-05-08|1994-04-06|1994-06-05|DELIVER IN PERSON|AIR|sly regular deposits. regular, regula +2466|13198|8201|3|29|32224.51|0.10|0.07|A|F|1994-06-11|1994-04-27|1994-07-10|DELIVER IN PERSON|FOB|ckages. bold requests nag carefully. +2466|10394|5397|4|29|37827.31|0.04|0.04|A|F|1994-04-01|1994-04-20|1994-04-23|DELIVER IN PERSON|MAIL|es boost fluffily ab +2466|78716|8717|5|30|50841.30|0.02|0.01|A|F|1994-04-11|1994-05-02|1994-05-02|DELIVER IN PERSON|REG AIR|. fluffily even pinto beans are idly. f +2466|172628|7663|6|19|32311.78|0.10|0.07|R|F|1994-06-12|1994-04-18|1994-07-12|NONE|MAIL|ccounts cajole a +2466|154218|1764|7|35|44527.35|0.10|0.00|A|F|1994-06-01|1994-05-27|1994-06-21|COLLECT COD|AIR| packages detect carefully: ironically sl +2467|132883|423|1|7|13411.16|0.00|0.00|N|O|1995-07-28|1995-10-04|1995-08-27|NONE|REG AIR|gular packages cajole +2468|93522|8541|1|46|69713.92|0.00|0.04|N|O|1997-07-16|1997-08-09|1997-08-07|COLLECT COD|SHIP|unusual theodolites su +2468|20527|5532|2|43|62243.36|0.00|0.04|N|O|1997-08-17|1997-08-21|1997-08-30|DELIVER IN PERSON|FOB|uriously eve +2468|194115|4116|3|44|53200.84|0.00|0.03|N|O|1997-10-01|1997-08-02|1997-10-09|TAKE BACK RETURN|RAIL|egular, silent sheave +2468|81607|1608|4|5|7943.00|0.08|0.00|N|O|1997-06-28|1997-08-02|1997-07-22|NONE|MAIL| sleep fluffily acc +2468|158353|869|5|18|25404.30|0.07|0.00|N|O|1997-07-25|1997-08-26|1997-08-14|DELIVER IN PERSON|REG AIR|cies. fluffily r +2469|165688|3237|1|11|19290.48|0.00|0.04|N|O|1997-02-09|1997-01-26|1997-02-16|NONE|TRUCK|ies wake carefully b +2469|113359|8382|2|16|21957.60|0.07|0.06|N|O|1997-02-19|1997-02-04|1997-03-18|NONE|MAIL|ing asymptotes +2469|10263|2765|3|48|56316.48|0.05|0.06|N|O|1997-01-11|1997-01-03|1997-01-15|TAKE BACK RETURN|AIR|riously even theodolites u +2469|87876|5401|4|35|65235.45|0.06|0.06|N|O|1997-02-04|1997-02-02|1997-02-17|DELIVER IN PERSON|RAIL|ld packages haggle regular frets. fluffily +2469|120671|8208|5|30|50750.10|0.09|0.01|N|O|1996-12-21|1997-01-29|1997-01-02|COLLECT COD|SHIP| accounts. regular theodolites affix fu +2469|103013|3014|6|49|49784.49|0.02|0.02|N|O|1997-03-03|1996-12-26|1997-03-13|NONE|AIR| requests are car +2469|126264|3801|7|8|10322.08|0.02|0.00|N|O|1997-03-15|1997-01-20|1997-04-13|NONE|TRUCK|s. regular +2470|109485|4506|1|12|17933.76|0.06|0.06|N|O|1997-07-12|1997-05-24|1997-07-17|TAKE BACK RETURN|FOB|l accounts. deposits nag daringly. express, +2470|99927|7455|2|50|96346.00|0.03|0.03|N|O|1997-06-02|1997-06-01|1997-06-09|COLLECT COD|AIR| packages +2470|63936|6443|3|10|18999.30|0.05|0.08|N|O|1997-06-20|1997-06-19|1997-06-24|TAKE BACK RETURN|FOB| ironic requests a +2470|161046|1047|4|30|33211.20|0.04|0.08|N|O|1997-08-04|1997-07-13|1997-08-14|DELIVER IN PERSON|AIR|s across the furiously fina +2471|83845|3846|1|37|67667.08|0.05|0.01|N|O|1998-05-28|1998-04-17|1998-06-08|COLLECT COD|TRUCK|ounts mold blithely carefully express depo +2496|140193|2708|1|38|46861.22|0.02|0.07|R|F|1994-03-26|1994-04-06|1994-04-23|COLLECT COD|RAIL| bold accounts. furi +2496|22609|2610|2|39|59732.40|0.03|0.00|R|F|1994-03-23|1994-02-18|1994-04-10|TAKE BACK RETURN|FOB|arefully special dependencies abo +2496|188554|3591|3|36|59131.80|0.09|0.04|R|F|1994-03-27|1994-03-15|1994-04-17|TAKE BACK RETURN|SHIP|ully ironic f +2496|23236|5739|4|30|34776.90|0.04|0.01|A|F|1994-01-27|1994-03-11|1994-01-31|DELIVER IN PERSON|RAIL|ake. ironic foxes cajole quickly. fu +2497|11060|8564|1|34|33016.04|0.02|0.03|R|F|1992-09-02|1992-10-19|1992-09-12|COLLECT COD|AIR|ronic accounts. p +2497|76887|9395|2|15|27958.20|0.09|0.02|A|F|1992-12-23|1992-11-20|1993-01-18|DELIVER IN PERSON|SHIP|sly against the +2497|33578|8585|3|28|42323.96|0.02|0.08|A|F|1992-12-02|1992-11-21|1992-12-04|DELIVER IN PERSON|REG AIR|ouches. special, regular requests +2497|143832|3833|4|48|90039.84|0.06|0.05|A|F|1992-09-29|1992-11-13|1992-10-19|TAKE BACK RETURN|AIR| even, regular requests across +2497|174813|7331|5|28|52858.68|0.04|0.05|A|F|1992-11-10|1992-09-30|1992-11-18|DELIVER IN PERSON|MAIL|hely bold ideas. unusual instructions ac +2497|70598|599|6|19|29803.21|0.05|0.08|A|F|1992-11-10|1992-11-20|1992-12-05|TAKE BACK RETURN|TRUCK| instructions? carefully daring accounts +2498|142210|9753|1|48|60106.08|0.10|0.01|R|F|1993-11-25|1994-01-09|1993-12-24|DELIVER IN PERSON|RAIL|onic requests wake +2499|149310|4339|1|15|20389.65|0.04|0.06|N|O|1995-12-21|1995-12-06|1996-01-19|DELIVER IN PERSON|FOB| slyly across the slyly +2499|45085|7590|2|48|49443.84|0.09|0.03|N|O|1995-10-14|1995-12-12|1995-11-11|DELIVER IN PERSON|AIR|ronic ideas cajole quickly requests. caref +2499|132086|4600|3|31|34660.48|0.09|0.05|N|O|1995-12-09|1995-10-28|1996-01-05|COLLECT COD|AIR|to beans across the carefully ironic theodo +2499|158406|922|4|39|57111.60|0.06|0.02|N|O|1995-10-26|1995-10-27|1995-11-07|TAKE BACK RETURN|SHIP|otes sublat +2499|129132|4157|5|6|6966.78|0.02|0.01|N|O|1995-11-19|1995-12-14|1995-12-08|NONE|SHIP|cording to the +2499|118583|1095|6|12|19218.96|0.04|0.05|N|O|1995-11-18|1995-12-13|1995-11-23|COLLECT COD|REG AIR|le furiously along the r +2500|191268|1269|1|40|54370.40|0.00|0.02|A|F|1992-09-02|1992-09-30|1992-09-06|DELIVER IN PERSON|SHIP|efully unusual dolphins s +2500|36252|6253|2|34|40400.50|0.06|0.02|R|F|1992-10-03|1992-11-11|1992-10-29|DELIVER IN PERSON|TRUCK| stealthy a +2500|79210|1718|3|41|48757.61|0.02|0.00|R|F|1992-09-02|1992-11-11|1992-09-06|DELIVER IN PERSON|RAIL|s could have to integrate after the +2500|68182|689|4|17|19553.06|0.01|0.02|A|F|1992-09-30|1992-10-16|1992-10-05|DELIVER IN PERSON|REG AIR|encies-- ironic, even packages +2501|83413|938|1|4|5585.64|0.10|0.06|N|O|1997-07-17|1997-07-27|1997-07-22|COLLECT COD|RAIL|quests. furiously final +2501|105961|982|2|33|64909.68|0.01|0.04|N|O|1997-07-14|1997-08-09|1997-07-26|NONE|MAIL|leep furiously packages. even sauternes +2501|71879|4387|3|20|37017.40|0.10|0.06|N|O|1997-09-23|1997-07-01|1997-10-03|DELIVER IN PERSON|RAIL|equests. furiou +2501|57411|4927|4|26|35578.66|0.09|0.01|N|O|1997-07-15|1997-08-15|1997-07-28|DELIVER IN PERSON|SHIP|c accounts. express, iron +2502|162155|2156|1|33|40165.95|0.10|0.06|R|F|1993-08-12|1993-07-22|1993-09-04|COLLECT COD|REG AIR|have to print +2503|122548|7573|1|33|51827.82|0.06|0.01|R|F|1993-07-06|1993-08-14|1993-08-02|NONE|SHIP|nal courts integrate according to the +2503|64060|1579|2|28|28673.68|0.06|0.01|R|F|1993-08-08|1993-08-31|1993-08-10|NONE|SHIP|s wake quickly slyly +2503|45308|5309|3|50|62665.00|0.09|0.01|A|F|1993-09-22|1993-08-17|1993-09-29|DELIVER IN PERSON|TRUCK|s around the slyly +2503|90061|7589|4|27|28378.62|0.09|0.00|A|F|1993-07-12|1993-07-24|1993-07-22|DELIVER IN PERSON|TRUCK|lly even p +2503|47679|184|5|3|4880.01|0.04|0.02|A|F|1993-07-10|1993-09-17|1993-07-19|TAKE BACK RETURN|TRUCK|s cajole. slyly close courts nod f +2503|127722|2747|6|39|68239.08|0.05|0.05|R|F|1993-10-11|1993-09-09|1993-10-16|NONE|MAIL|d carefully fluffily +2503|18588|3591|7|17|25611.86|0.09|0.08|R|F|1993-09-04|1993-07-31|1993-09-23|DELIVER IN PERSON|SHIP|c accounts haggle blithel +2528|195|196|1|10|10951.90|0.02|0.03|R|F|1994-12-12|1994-12-29|1994-12-28|COLLECT COD|REG AIR|ely. fluffily even re +2528|73433|8448|2|13|18283.59|0.00|0.03|A|F|1994-11-27|1995-01-20|1994-12-03|TAKE BACK RETURN|REG AIR|ggle furiously. slyly final asympt +2528|174348|4349|3|35|49781.90|0.10|0.00|R|F|1994-12-19|1995-02-04|1995-01-15|NONE|MAIL|, even excuses. even, +2528|64125|6632|4|37|40297.44|0.00|0.01|A|F|1994-12-25|1995-02-02|1994-12-31|COLLECT COD|AIR|ng the pending excuses haggle after the bl +2529|130636|8176|1|4|6666.52|0.07|0.07|N|O|1996-10-19|1996-11-18|1996-10-24|DELIVER IN PERSON|SHIP|al dependencies haggle slyly alongsi +2530|20319|320|1|9|11153.79|0.09|0.03|R|F|1994-05-10|1994-04-30|1994-05-24|TAKE BACK RETURN|REG AIR|lyly ironic +2530|92397|9925|2|42|58354.38|0.04|0.08|R|F|1994-03-27|1994-05-20|1994-03-29|NONE|RAIL|ng platelets wake s +2530|107824|335|3|8|14654.56|0.10|0.08|A|F|1994-05-02|1994-05-08|1994-05-24|DELIVER IN PERSON|MAIL|ial asymptotes snooze slyly regular +2531|147722|5265|1|9|15927.48|0.03|0.07|N|O|1996-07-27|1996-07-03|1996-08-01|DELIVER IN PERSON|AIR|t the dogged, un +2531|157000|2031|2|3|3171.00|0.07|0.06|N|O|1996-07-20|1996-06-20|1996-08-10|NONE|MAIL|he quickly ev +2531|85917|934|3|20|38058.20|0.06|0.04|N|O|1996-07-18|1996-06-25|1996-07-29|TAKE BACK RETURN|TRUCK|into beans. furious +2531|190889|8447|4|36|71275.68|0.08|0.01|N|O|1996-06-11|1996-07-26|1996-06-27|NONE|MAIL|y ironic, bold packages. blithely e +2531|55891|8397|5|28|51712.92|0.03|0.07|N|O|1996-07-06|1996-07-31|1996-07-19|TAKE BACK RETURN|REG AIR|its. busily +2531|144342|1885|6|46|63771.64|0.10|0.08|N|O|1996-07-03|1996-06-27|1996-07-12|TAKE BACK RETURN|REG AIR|e final, bold pains. ir +2532|52631|2632|1|3|4750.89|0.06|0.07|N|O|1995-12-14|1995-11-28|1995-12-15|COLLECT COD|FOB|unusual sentiments. even pinto +2532|159799|7345|2|33|61340.07|0.06|0.05|N|O|1995-11-23|1996-01-04|1995-12-16|DELIVER IN PERSON|TRUCK|rve carefully slyly ironic accounts! fluf +2532|134223|1763|3|1|1257.22|0.00|0.06|N|O|1996-01-27|1995-11-23|1996-01-29|DELIVER IN PERSON|REG AIR|ely final ideas cajole despite the ca +2532|77534|42|4|50|75576.50|0.02|0.02|N|O|1995-11-13|1996-01-01|1995-11-26|NONE|TRUCK|yly after the fluffily regul +2532|113046|8069|5|9|9531.36|0.09|0.04|N|O|1995-11-30|1995-11-23|1995-12-12|DELIVER IN PERSON|TRUCK|cial ideas haggle slyly pending request +2532|149281|9282|6|20|26605.60|0.09|0.05|N|O|1995-12-02|1995-11-26|1995-12-08|TAKE BACK RETURN|AIR|er the slyly pending +2533|53585|8596|1|36|55388.88|0.06|0.04|N|O|1997-06-10|1997-04-28|1997-07-01|NONE|REG AIR|ss requests sleep neve +2533|197072|9592|2|5|5845.35|0.10|0.04|N|O|1997-05-26|1997-06-02|1997-06-24|NONE|FOB|ccounts. ironic, special accounts boo +2533|182962|517|3|37|75663.52|0.00|0.08|N|O|1997-05-10|1997-04-26|1997-05-28|COLLECT COD|SHIP| haggle carefully +2533|29341|1844|4|17|21595.78|0.06|0.02|N|O|1997-05-23|1997-05-10|1997-06-18|NONE|FOB|ackages. blith +2533|125554|8067|5|38|60022.90|0.09|0.00|N|O|1997-05-10|1997-06-02|1997-05-28|TAKE BACK RETURN|REG AIR|of the regular accounts. even packages caj +2533|183334|3335|6|20|28346.60|0.05|0.08|N|O|1997-07-04|1997-04-30|1997-07-05|COLLECT COD|FOB|thless excuses are b +2533|93767|8786|7|14|24650.64|0.06|0.04|N|O|1997-07-06|1997-05-08|1997-08-03|COLLECT COD|FOB|ut the pending, special depos +2534|138552|6092|1|29|46125.95|0.07|0.07|N|O|1996-08-09|1996-09-29|1996-08-11|COLLECT COD|TRUCK|ugouts haggle slyly. final +2534|26716|1721|2|49|80492.79|0.08|0.08|N|O|1996-09-01|1996-08-20|1996-09-06|NONE|SHIP|sometimes regular requests. blithely unus +2534|802|3303|3|50|85140.00|0.10|0.06|N|O|1996-09-25|1996-10-07|1996-10-09|TAKE BACK RETURN|AIR|ideas. deposits use. slyly regular pa +2534|74217|1739|4|43|51222.03|0.09|0.02|N|O|1996-10-25|1996-09-30|1996-11-05|TAKE BACK RETURN|REG AIR|ngly final depos +2534|164808|9841|5|14|26219.20|0.05|0.02|N|O|1996-08-12|1996-09-26|1996-08-28|COLLECT COD|MAIL|eposits doze quickly final +2534|115962|8474|6|12|23735.52|0.02|0.02|N|O|1996-07-29|1996-10-12|1996-08-14|TAKE BACK RETURN|AIR|sual depos +2534|172536|5054|7|17|27345.01|0.02|0.07|N|O|1996-07-22|1996-09-15|1996-08-03|NONE|SHIP|riously regular +2535|198027|3066|1|5|5625.10|0.06|0.01|A|F|1993-09-07|1993-07-25|1993-09-29|DELIVER IN PERSON|REG AIR|, unusual reque +2535|38012|516|2|12|11400.12|0.08|0.05|A|F|1993-07-17|1993-08-17|1993-07-31|TAKE BACK RETURN|FOB|uses sleep among the packages. excuses +2535|53012|3013|3|5|4825.05|0.09|0.06|R|F|1993-07-28|1993-08-14|1993-08-11|DELIVER IN PERSON|SHIP| across the express requests. silent, eve +2535|159290|4321|4|19|25636.51|0.01|0.02|A|F|1993-06-01|1993-08-01|1993-06-19|DELIVER IN PERSON|FOB|ructions. final requests +2535|173753|8788|5|25|45668.75|0.07|0.04|A|F|1993-07-19|1993-08-07|1993-07-27|NONE|REG AIR|ions believe ab +2560|168823|8824|1|41|77564.62|0.07|0.01|R|F|1992-10-23|1992-11-11|1992-11-22|NONE|SHIP| after the accounts. regular foxes are be +2560|3764|8765|2|27|45029.52|0.00|0.01|R|F|1992-12-03|1992-11-16|1992-12-30|NONE|MAIL| against the carefully +2560|45914|3427|3|31|57657.21|0.01|0.05|A|F|1992-11-14|1992-10-14|1992-12-11|DELIVER IN PERSON|AIR|to beans. blithely regular Tiresias int +2560|71128|6143|4|36|39568.32|0.01|0.02|A|F|1992-10-18|1992-10-30|1992-11-05|TAKE BACK RETURN|MAIL|accounts alongside of the excuses are +2560|41835|9348|5|9|15991.47|0.04|0.02|A|F|1992-10-23|1992-10-29|1992-11-02|COLLECT COD|REG AIR| deposits affix quickly. unusual, eve +2560|107511|7512|6|13|19740.63|0.03|0.06|A|F|1992-09-07|1992-10-21|1992-09-24|COLLECT COD|FOB|slyly final accoun +2561|24579|9584|1|32|48114.24|0.02|0.01|N|O|1998-01-05|1997-12-28|1998-01-26|DELIVER IN PERSON|REG AIR|bold packages wake slyly. slyly +2561|97066|2085|2|5|5315.30|0.07|0.04|N|O|1997-12-27|1998-01-23|1998-01-13|TAKE BACK RETURN|AIR|p ironic, regular pinto beans. +2561|172518|2519|3|47|74753.97|0.04|0.02|N|O|1997-11-19|1998-01-21|1997-12-03|DELIVER IN PERSON|REG AIR|larly pending t +2561|107536|7537|4|39|60197.67|0.08|0.06|N|O|1998-01-20|1997-12-16|1998-02-05|TAKE BACK RETURN|MAIL|equests are furiously against the +2561|149929|4958|5|2|3957.84|0.04|0.08|N|O|1998-03-14|1998-01-21|1998-03-27|DELIVER IN PERSON|TRUCK|s are. silently silent foxes sleep about +2561|50268|5279|6|14|17055.64|0.02|0.03|N|O|1998-03-07|1998-02-04|1998-03-21|COLLECT COD|RAIL|ep unusual, ironic accounts +2562|52202|9718|1|28|32317.60|0.04|0.03|R|F|1992-10-04|1992-09-24|1992-10-09|COLLECT COD|MAIL|ans haggle special, special packages. +2562|147205|7206|2|1|1252.20|0.01|0.06|R|F|1992-10-16|1992-09-18|1992-10-17|NONE|TRUCK| slyly final ideas haggle car +2562|65577|5578|3|25|38564.25|0.05|0.03|A|F|1992-11-23|1992-10-08|1992-12-19|DELIVER IN PERSON|REG AIR| accounts-- silent, unusual ideas a +2562|147127|2156|4|37|43442.44|0.08|0.03|R|F|1992-10-29|1992-10-06|1992-11-09|COLLECT COD|FOB|. slyly regular ideas according to the fl +2562|159068|1584|5|29|32684.74|0.05|0.08|A|F|1992-11-01|1992-09-29|1992-11-13|TAKE BACK RETURN|MAIL|eep against the furiously r +2562|49696|2201|6|17|27976.73|0.01|0.06|A|F|1992-10-15|1992-10-08|1992-10-26|DELIVER IN PERSON|TRUCK|lar pinto beans. blithely ev +2563|64353|6860|1|10|13173.50|0.07|0.04|A|F|1994-01-26|1993-12-19|1994-01-28|DELIVER IN PERSON|AIR|tealthily abo +2563|166759|1792|2|28|51121.00|0.04|0.03|R|F|1994-03-17|1994-02-04|1994-04-13|TAKE BACK RETURN|RAIL|hely regular depe +2563|118456|5990|3|39|57503.55|0.07|0.00|R|F|1994-02-10|1993-12-31|1994-02-19|COLLECT COD|FOB|lent requests should integrate; carefully e +2563|89071|6596|4|50|53003.50|0.01|0.01|A|F|1994-01-26|1994-01-03|1994-02-09|DELIVER IN PERSON|SHIP|ly regular, regular excuses. bold plate +2563|14990|4991|5|42|80009.58|0.06|0.08|R|F|1994-02-21|1994-02-14|1994-03-04|DELIVER IN PERSON|AIR|ymptotes nag furiously slyly even inst +2563|120830|831|6|5|9254.15|0.10|0.00|R|F|1993-12-27|1993-12-19|1994-01-02|DELIVER IN PERSON|REG AIR| the quickly final theodolite +2564|111220|1221|1|4|4924.88|0.02|0.00|R|F|1994-11-12|1994-10-29|1994-12-04|NONE|MAIL|y express requests sleep furi +2565|143630|3631|1|42|70292.46|0.04|0.08|N|O|1998-04-07|1998-04-02|1998-05-04|NONE|AIR|ngly silent +2565|188845|8846|2|26|50279.84|0.05|0.08|N|O|1998-05-07|1998-04-09|1998-05-15|DELIVER IN PERSON|TRUCK| pinto beans about the slyly regula +2565|114394|1928|3|34|47885.26|0.06|0.06|N|O|1998-03-19|1998-04-12|1998-04-17|DELIVER IN PERSON|SHIP|nstructions was carefu +2565|16224|3728|4|25|28505.50|0.10|0.08|N|O|1998-06-27|1998-05-20|1998-07-13|DELIVER IN PERSON|RAIL|, express accounts. final id +2565|75465|5466|5|26|37451.96|0.08|0.03|N|O|1998-03-05|1998-04-11|1998-03-11|TAKE BACK RETURN|AIR|ites wake. ironic acco +2565|140191|5220|6|48|59097.12|0.08|0.07|N|O|1998-06-18|1998-05-06|1998-07-13|DELIVER IN PERSON|TRUCK|r instructions sleep qui +2566|147224|9739|1|19|24153.18|0.06|0.07|R|F|1992-12-21|1992-11-24|1992-12-22|DELIVER IN PERSON|MAIL|ests. silent +2566|180474|8029|2|42|65287.74|0.08|0.02|R|F|1992-12-20|1992-12-22|1992-12-29|COLLECT COD|MAIL|ously ironic accounts +2566|22648|5151|3|18|28271.52|0.09|0.02|A|F|1992-11-16|1992-12-24|1992-12-16|COLLECT COD|FOB| braids according t +2566|41449|3954|4|3|4171.32|0.05|0.02|A|F|1992-11-04|1992-12-30|1992-12-04|TAKE BACK RETURN|FOB|ckages are ironic Tiresias. furious +2566|21214|1215|5|9|10216.89|0.04|0.03|R|F|1992-12-14|1992-12-28|1992-12-16|NONE|FOB|blithely bold accounts? quickl +2566|127422|9935|6|1|1449.42|0.07|0.03|A|F|1992-10-28|1992-11-20|1992-11-22|TAKE BACK RETURN|AIR|theodolites wake pending +2567|25711|3218|1|39|63831.69|0.03|0.04|N|O|1998-05-10|1998-05-10|1998-05-21|NONE|SHIP|ns. furiously final dependencies cajo +2567|111886|1887|2|50|94894.00|0.06|0.05|N|O|1998-05-05|1998-04-18|1998-05-09|DELIVER IN PERSON|TRUCK|. carefully pending foxes are furi +2567|51679|4185|3|6|9784.02|0.03|0.06|N|O|1998-04-21|1998-04-14|1998-05-11|NONE|RAIL|s cajole regular, final acco +2567|157535|51|4|50|79626.50|0.05|0.03|N|O|1998-03-27|1998-05-25|1998-04-23|DELIVER IN PERSON|FOB|pinto beans? r +2567|80318|7843|5|46|59722.26|0.07|0.02|N|O|1998-06-02|1998-04-30|1998-06-13|COLLECT COD|AIR|efully pending epitaphs. carefully reg +2567|99455|4474|6|32|46542.40|0.01|0.07|N|O|1998-05-24|1998-04-30|1998-06-14|NONE|RAIL| the even, iro +2567|134307|9334|7|43|57675.90|0.06|0.02|N|O|1998-05-11|1998-04-15|1998-05-29|NONE|RAIL|requests. final courts cajole +2592|89634|9635|1|7|11365.41|0.10|0.04|R|F|1993-03-13|1993-04-25|1993-04-01|NONE|REG AIR| carefully special theodolites integrate +2592|65700|3219|2|2|3331.40|0.10|0.00|A|F|1993-03-24|1993-04-05|1993-04-16|DELIVER IN PERSON|RAIL|side of the b +2593|104022|1553|1|37|37962.74|0.08|0.06|R|F|1993-12-14|1993-10-08|1994-01-04|NONE|SHIP|s wake bravel +2593|89185|6710|2|28|32877.04|0.08|0.03|A|F|1993-10-30|1993-10-18|1993-11-06|DELIVER IN PERSON|SHIP|y even escapades shall +2593|127040|9553|3|6|6402.24|0.04|0.05|A|F|1993-11-28|1993-10-04|1993-12-28|TAKE BACK RETURN|REG AIR|ular packages. re +2593|160005|2522|4|44|46860.00|0.02|0.08|A|F|1993-09-05|1993-10-23|1993-09-29|NONE|RAIL|ents impress furiously; unusual theodoli +2593|3498|3499|5|3|4204.47|0.03|0.00|A|F|1993-12-16|1993-11-01|1993-12-29|COLLECT COD|SHIP|the furiously +2593|174570|4571|6|1|1644.57|0.08|0.08|A|F|1993-11-23|1993-10-25|1993-12-04|DELIVER IN PERSON|RAIL| accounts wake slyly +2593|191389|6428|7|11|16284.18|0.00|0.07|R|F|1993-11-01|1993-11-19|1993-11-28|TAKE BACK RETURN|RAIL|express packages sleep bold re +2594|71490|1491|1|7|10230.43|0.06|0.02|R|F|1993-03-26|1993-03-05|1993-04-24|DELIVER IN PERSON|FOB|arls cajole +2594|123171|5684|2|13|15524.21|0.10|0.05|R|F|1993-02-06|1993-03-01|1993-02-23|TAKE BACK RETURN|TRUCK|fully special accounts use courts +2594|125492|8005|3|24|36419.76|0.03|0.00|A|F|1993-01-31|1993-03-10|1993-02-04|COLLECT COD|REG AIR|lar accounts sleep fur +2594|143957|8986|4|46|92043.70|0.00|0.08|R|F|1993-04-17|1993-03-06|1993-04-21|TAKE BACK RETURN|SHIP|beans. instructions across t +2595|60945|946|1|42|80049.48|0.08|0.02|N|O|1996-03-24|1996-01-28|1996-04-10|DELIVER IN PERSON|MAIL|ggle furiou +2595|87061|9570|2|30|31441.80|0.05|0.01|N|O|1996-03-05|1996-02-23|1996-03-19|NONE|AIR|ctions. regula +2595|23369|8374|3|19|24554.84|0.01|0.05|N|O|1995-12-23|1996-03-02|1996-01-17|COLLECT COD|MAIL|ns are neve +2595|158785|6331|4|29|53469.62|0.07|0.05|N|O|1996-01-01|1996-02-13|1996-01-18|TAKE BACK RETURN|RAIL|ronic accounts haggle carefully fin +2595|85077|94|5|30|31862.10|0.09|0.07|N|O|1996-03-16|1996-01-31|1996-04-05|TAKE BACK RETURN|FOB|. final orbits cajole +2595|81859|9384|6|31|57066.35|0.06|0.04|N|O|1996-02-07|1996-02-10|1996-03-05|DELIVER IN PERSON|AIR|tipliers w +2596|169486|7035|1|6|9332.88|0.05|0.01|N|O|1996-12-15|1996-11-02|1996-12-29|TAKE BACK RETURN|TRUCK|ily special re +2596|138885|3912|2|43|82726.84|0.07|0.03|N|O|1996-09-03|1996-10-26|1996-09-15|NONE|FOB|ial packages haggl +2596|38443|947|3|19|26247.36|0.10|0.00|N|O|1996-09-02|1996-11-03|1996-09-06|COLLECT COD|AIR|ias mold! sp +2596|104266|4267|4|10|12702.60|0.06|0.05|N|O|1996-08-25|1996-11-05|1996-09-13|DELIVER IN PERSON|REG AIR| instructions shall have +2597|83782|8799|1|24|42378.72|0.07|0.00|A|F|1993-05-15|1993-03-06|1993-05-25|TAKE BACK RETURN|FOB|pending packages. enticingly fi +2598|6983|4484|1|12|22679.76|0.00|0.01|N|O|1996-06-17|1996-04-12|1996-06-24|COLLECT COD|TRUCK|express packages nag sly +2598|147005|4548|2|40|42080.00|0.07|0.02|N|O|1996-05-11|1996-05-19|1996-06-08|TAKE BACK RETURN|AIR|the enticing +2598|103709|8730|3|4|6850.80|0.03|0.03|N|O|1996-05-23|1996-05-13|1996-05-25|COLLECT COD|AIR| across the furiously fi +2598|22081|7086|4|19|19058.52|0.02|0.00|N|O|1996-04-09|1996-05-30|1996-04-17|TAKE BACK RETURN|RAIL|nic packages. even accounts +2598|105924|3455|5|12|23159.04|0.01|0.08|N|O|1996-04-14|1996-04-24|1996-04-21|TAKE BACK RETURN|REG AIR|eposits cajol +2599|100735|3246|1|11|19093.03|0.08|0.08|N|O|1997-02-01|1996-12-14|1997-02-27|TAKE BACK RETURN|FOB| express accoun +2599|41370|6379|2|26|34095.62|0.03|0.04|N|O|1996-11-08|1996-12-21|1996-11-24|TAKE BACK RETURN|AIR|nag carefully +2599|98819|8820|3|29|52716.49|0.09|0.03|N|O|1997-01-10|1996-12-10|1997-02-02|COLLECT COD|RAIL|ly express dolphins. special, +2624|62426|7439|1|15|20826.30|0.03|0.07|N|O|1997-02-28|1997-02-19|1997-03-21|DELIVER IN PERSON|AIR|le. quickly pending requests +2624|188685|8686|2|12|21284.16|0.07|0.00|N|O|1997-02-24|1997-02-22|1997-02-27|DELIVER IN PERSON|SHIP|er the quickly unu +2625|19346|9347|1|42|53144.28|0.02|0.04|R|F|1992-10-18|1992-11-17|1992-10-23|DELIVER IN PERSON|AIR| even accounts haggle furiously +2626|21431|8938|1|45|60859.35|0.09|0.04|N|O|1995-11-22|1995-11-01|1995-11-23|NONE|AIR|deposits wake blithely according to +2626|174354|1906|2|2|2856.70|0.05|0.07|N|O|1995-10-19|1995-11-09|1995-10-24|TAKE BACK RETURN|FOB|uffy accounts haggle furiously above +2626|153317|5833|3|40|54812.40|0.05|0.07|N|O|1995-09-28|1995-12-03|1995-10-10|NONE|REG AIR|eans. ironic deposits haggle. depo +2627|130582|8122|1|28|45152.24|0.09|0.02|R|F|1992-05-14|1992-05-09|1992-05-31|COLLECT COD|SHIP|ggedly final excuses nag packages. f +2628|105867|8378|1|44|82405.84|0.07|0.03|R|F|1994-01-11|1994-01-14|1994-01-13|DELIVER IN PERSON|SHIP|lyly final, pending ide +2628|105425|7936|2|14|20025.88|0.01|0.03|A|F|1994-01-28|1993-11-30|1994-02-20|TAKE BACK RETURN|SHIP|g the furiously unusual pi +2628|63884|1403|3|42|77610.96|0.00|0.00|A|F|1993-11-20|1994-01-04|1993-12-19|DELIVER IN PERSON|TRUCK|ld notornis alongside +2628|94014|6524|4|23|23184.23|0.08|0.04|A|F|1993-10-27|1994-01-08|1993-11-12|DELIVER IN PERSON|TRUCK|usual packages sleep about the fina +2628|89996|2505|5|50|99299.50|0.07|0.01|A|F|1994-01-13|1993-12-11|1994-01-14|NONE|AIR|posits serve carefully toward +2629|117875|7876|1|6|11357.22|0.06|0.05|N|O|1998-06-10|1998-05-29|1998-06-13|DELIVER IN PERSON|SHIP|dolites hinder bli +2629|123076|613|2|31|34071.17|0.08|0.03|N|O|1998-05-24|1998-05-26|1998-06-10|COLLECT COD|AIR|ate blithely bold, regular deposits. bold +2629|127428|7429|3|29|42207.18|0.08|0.07|N|O|1998-07-09|1998-06-17|1998-07-12|TAKE BACK RETURN|AIR|eposits serve unusual, express i +2629|69303|6822|4|33|41985.90|0.06|0.03|N|O|1998-05-29|1998-05-14|1998-05-30|NONE|TRUCK|es. slowly express accounts are along the +2630|28480|3485|1|46|64790.08|0.05|0.03|R|F|1992-11-05|1992-12-17|1992-12-05|TAKE BACK RETURN|MAIL|uests cajole. e +2630|56285|1296|2|8|9930.24|0.09|0.07|A|F|1992-11-16|1993-01-01|1992-12-07|DELIVER IN PERSON|TRUCK|indle fluffily silent, ironic pi +2630|172605|7640|3|45|75492.00|0.08|0.07|A|F|1993-01-04|1993-01-11|1993-01-09|NONE|FOB|edly express ideas. carefully final +2630|161536|6569|4|29|46328.37|0.08|0.07|A|F|1992-12-03|1993-01-04|1992-12-12|DELIVER IN PERSON|SHIP|efully unusual dependencies. even i +2631|121656|4169|1|42|70461.30|0.00|0.03|A|F|1994-01-04|1993-12-01|1994-01-16|TAKE BACK RETURN|SHIP|ect carefully at the furiously final the +2631|66551|1564|2|4|6070.20|0.07|0.06|R|F|1993-11-03|1993-12-17|1993-11-05|COLLECT COD|AIR|special theodolites. a +2631|117876|5410|3|15|28408.05|0.06|0.05|A|F|1993-09-30|1993-11-06|1993-10-13|DELIVER IN PERSON|SHIP|y. furiously even pinto be +2656|180671|3190|1|10|17516.70|0.02|0.06|R|F|1993-06-28|1993-07-04|1993-07-12|TAKE BACK RETURN|TRUCK|s nag regularly about the deposits. slyly +2656|136884|6885|2|38|72993.44|0.07|0.02|A|F|1993-06-25|1993-06-04|1993-07-24|NONE|RAIL|structions wake along the furio +2656|1209|3710|3|19|21093.80|0.03|0.02|R|F|1993-08-03|1993-07-25|1993-08-20|TAKE BACK RETURN|MAIL|ts serve deposi +2656|109246|1757|4|40|50209.60|0.05|0.04|R|F|1993-06-09|1993-07-24|1993-06-21|DELIVER IN PERSON|RAIL|refully final pearls. final ideas wake. qu +2657|114332|6844|1|22|29619.26|0.02|0.03|N|O|1995-12-08|1995-12-28|1995-12-21|TAKE BACK RETURN|MAIL|r ideas. furiously special dolphins +2657|164877|9910|2|15|29128.05|0.08|0.05|N|O|1995-12-09|1995-12-16|1995-12-18|NONE|RAIL|ole carefully above the ironic ideas. b +2657|78233|741|3|25|30280.75|0.02|0.04|N|O|1995-10-21|1995-12-12|1995-11-09|COLLECT COD|FOB|lly pinto beans. final +2657|54839|2355|4|11|19732.13|0.04|0.08|N|O|1995-11-19|1995-12-11|1995-11-24|COLLECT COD|TRUCK|ckly enticing requests. fur +2657|77611|7612|5|42|66721.62|0.06|0.03|N|O|1996-01-23|1995-11-22|1996-01-25|COLLECT COD|RAIL|ckly slyly even accounts. platelets x-ray +2657|193153|8192|6|31|38630.65|0.01|0.03|N|O|1995-11-10|1995-11-27|1995-12-06|COLLECT COD|RAIL|re blithely +2658|131174|1175|1|41|49411.97|0.05|0.04|N|O|1995-11-07|1995-11-04|1995-12-04|NONE|MAIL|eposits. furiously final theodolite +2658|28573|1076|2|22|33034.54|0.08|0.05|N|O|1995-11-12|1995-11-18|1995-11-14|DELIVER IN PERSON|TRUCK|ts cajole. pending packages affix +2658|17832|2835|3|13|22747.79|0.07|0.06|N|O|1995-10-24|1995-12-12|1995-11-14|COLLECT COD|FOB|s kindle blithely regular accounts. +2658|91939|6958|4|22|42480.46|0.04|0.04|N|O|1995-12-02|1995-11-03|1995-12-26|DELIVER IN PERSON|SHIP| dependencies. blithely pending foxes abou +2658|6721|6722|5|45|73247.40|0.03|0.01|N|O|1995-11-02|1995-11-08|1995-11-29|DELIVER IN PERSON|MAIL|e special requests. quickly ex +2658|146785|9300|6|27|49458.06|0.05|0.07|N|O|1995-09-26|1995-12-08|1995-09-30|NONE|AIR|ecial packages use abov +2659|41783|9296|1|28|48293.84|0.08|0.05|A|F|1994-03-17|1994-01-24|1994-03-19|NONE|FOB|idle tithes +2659|42253|9766|2|21|25100.25|0.00|0.00|A|F|1993-12-23|1994-02-10|1994-01-17|DELIVER IN PERSON|RAIL|y beyond the furiously even co +2659|134547|2087|3|24|37956.96|0.04|0.03|R|F|1994-03-28|1994-02-20|1994-04-05|DELIVER IN PERSON|REG AIR| haggle carefully +2659|118095|3118|4|2|2226.18|0.00|0.08|R|F|1994-02-19|1994-03-12|1994-02-21|NONE|MAIL|sts above the fluffily express fo +2659|6161|3662|5|9|9604.44|0.08|0.03|A|F|1994-02-07|1994-03-17|1994-03-04|DELIVER IN PERSON|AIR|ly final packages sleep ac +2660|47703|5216|1|17|28061.90|0.00|0.05|N|O|1995-08-18|1995-09-13|1995-09-17|NONE|SHIP|al pinto beans wake after the furious +2661|177159|7160|1|31|38320.65|0.03|0.02|N|O|1997-04-07|1997-03-10|1997-04-23|TAKE BACK RETURN|AIR|e ironicall +2661|102402|7423|2|22|30896.80|0.08|0.02|N|O|1997-03-14|1997-03-17|1997-04-08|COLLECT COD|REG AIR| foxes affix quickly ironic request +2661|66183|8690|3|11|12640.98|0.00|0.08|N|O|1997-04-14|1997-02-11|1997-05-05|TAKE BACK RETURN|FOB|equests are a +2661|136127|1154|4|41|47687.92|0.06|0.02|N|O|1997-03-06|1997-03-27|1997-03-15|DELIVER IN PERSON|AIR|iously ironically ironic requests. +2662|101609|4120|1|43|69255.80|0.09|0.07|N|O|1996-11-24|1996-11-04|1996-12-08|NONE|RAIL|. slyly specia +2662|127424|7425|2|8|11611.36|0.02|0.07|N|O|1996-09-10|1996-10-09|1996-09-21|TAKE BACK RETURN|REG AIR|ajole carefully. sp +2662|1049|3550|3|6|5700.24|0.02|0.00|N|O|1996-11-30|1996-09-20|1996-12-03|DELIVER IN PERSON|REG AIR|olites cajole quickly along the b +2662|29760|9761|4|34|57451.84|0.06|0.07|N|O|1996-10-04|1996-11-05|1996-10-19|NONE|SHIP|ding theodolites use carefully. p +2663|113221|755|1|35|43197.70|0.02|0.01|N|O|1995-12-11|1995-10-16|1996-01-07|TAKE BACK RETURN|REG AIR|tect. slyly fina +2688|17768|2771|1|45|75859.20|0.08|0.08|R|F|1992-05-21|1992-04-14|1992-05-28|NONE|FOB|sits run carefully +2688|14500|4501|2|46|65067.00|0.01|0.01|R|F|1992-05-24|1992-04-01|1992-05-26|COLLECT COD|TRUCK|elets. regular reque +2688|88810|1319|3|30|53964.30|0.05|0.04|A|F|1992-04-18|1992-03-18|1992-05-18|TAKE BACK RETURN|RAIL|ithely final +2688|24410|6913|4|3|4003.23|0.00|0.03|R|F|1992-02-04|1992-03-18|1992-02-24|DELIVER IN PERSON|RAIL|e fluffily +2688|58449|8450|5|22|30963.68|0.02|0.05|R|F|1992-02-09|1992-04-09|1992-02-11|DELIVER IN PERSON|RAIL|press, ironic excuses wake carefully id +2688|148297|8298|6|42|56502.18|0.01|0.01|R|F|1992-04-29|1992-04-04|1992-05-17|TAKE BACK RETURN|FOB|lly even account +2689|5731|732|1|45|73652.85|0.02|0.04|R|F|1992-04-29|1992-06-22|1992-04-30|COLLECT COD|SHIP|e quickly. carefully silent +2690|139065|4092|1|44|48578.64|0.05|0.06|N|O|1996-05-30|1996-05-19|1996-06-26|NONE|REG AIR|ly alongside of th +2690|50963|964|2|50|95698.00|0.03|0.03|N|O|1996-06-13|1996-05-22|1996-06-14|DELIVER IN PERSON|MAIL| doubt careful +2690|124448|4449|3|45|66259.80|0.02|0.07|N|O|1996-05-23|1996-06-02|1996-05-29|DELIVER IN PERSON|MAIL|ounts. slyly regular dependencies wa +2690|194436|4437|4|12|18365.16|0.04|0.07|N|O|1996-07-18|1996-06-03|1996-07-25|NONE|AIR|nal, regular atta +2690|85190|2715|5|30|35255.70|0.01|0.08|N|O|1996-05-20|1996-06-01|1996-06-04|TAKE BACK RETURN|SHIP|d accounts above the express req +2690|188034|5589|6|3|3366.09|0.07|0.01|N|O|1996-07-04|1996-05-28|1996-07-06|TAKE BACK RETURN|RAIL|. final reques +2690|78616|6138|7|35|55811.35|0.05|0.06|N|O|1996-07-25|1996-05-14|1996-08-03|COLLECT COD|FOB|y silent pinto be +2691|90549|3059|1|11|16934.94|0.04|0.07|R|F|1992-06-21|1992-06-08|1992-07-09|COLLECT COD|FOB|leep alongside of the accounts. slyly ironi +2691|47716|5229|2|2|3327.42|0.00|0.07|R|F|1992-05-10|1992-06-04|1992-05-11|TAKE BACK RETURN|TRUCK|s cajole at the blithely ironic warthog +2691|161253|1254|3|16|21028.00|0.09|0.03|R|F|1992-06-11|1992-07-29|1992-06-29|NONE|RAIL|bove the even foxes. unusual theodoli +2691|165770|803|4|1|1835.77|0.08|0.00|A|F|1992-08-11|1992-06-07|1992-08-16|NONE|SHIP|egular instructions b +2692|16131|8633|1|3|3141.39|0.10|0.04|N|O|1998-02-25|1998-01-29|1998-03-27|TAKE BACK RETURN|MAIL|equests. bold, even foxes haggle slyl +2692|113501|8524|2|21|31804.50|0.03|0.05|N|O|1998-03-11|1998-02-11|1998-03-19|NONE|SHIP|posits. final, express requests nag furi +2693|8670|8671|1|26|41045.42|0.04|0.00|N|O|1996-09-14|1996-10-07|1996-10-03|COLLECT COD|MAIL|cajole alo +2693|101842|1843|2|43|79285.12|0.03|0.04|N|O|1996-10-24|1996-10-24|1996-11-03|TAKE BACK RETURN|TRUCK|as are according to th +2694|152518|5034|1|30|47115.30|0.02|0.06|N|O|1996-06-20|1996-06-01|1996-07-15|NONE|TRUCK|oxes. never iro +2694|156889|1920|2|35|68105.80|0.07|0.03|N|O|1996-05-24|1996-06-01|1996-05-25|NONE|RAIL|atelets past the furiously final deposits +2694|18030|532|3|15|14220.45|0.08|0.02|N|O|1996-06-30|1996-05-01|1996-07-25|TAKE BACK RETURN|REG AIR|e blithely even platelets. special wa +2694|19451|6955|4|12|16445.40|0.00|0.05|N|O|1996-04-24|1996-04-22|1996-05-14|DELIVER IN PERSON|RAIL|foxes atop the hockey pla +2694|107185|7186|5|10|11921.80|0.08|0.08|N|O|1996-06-23|1996-05-28|1996-06-27|COLLECT COD|REG AIR|fluffily fluffy accounts. even packages hi +2695|183259|8296|1|21|28187.25|0.07|0.00|N|O|1996-10-04|1996-11-02|1996-10-21|NONE|MAIL|y regular pinto beans. evenly regular packa +2695|18835|6339|2|44|77168.52|0.09|0.07|N|O|1996-10-05|1996-10-10|1996-11-01|NONE|MAIL|ts. busy platelets boost +2695|143480|8509|3|21|31993.08|0.02|0.07|N|O|1996-09-13|1996-09-25|1996-10-13|NONE|TRUCK|s. furiously ironic platelets ar +2695|57398|9904|4|16|21686.24|0.08|0.08|N|O|1996-11-16|1996-10-05|1996-11-22|NONE|TRUCK|its. theodolites sleep slyly +2695|85282|2807|5|40|50691.20|0.02|0.03|N|O|1996-11-02|1996-10-26|1996-11-14|NONE|FOB|ructions. pending +2720|44483|4484|1|5|7137.40|0.10|0.06|A|F|1993-06-24|1993-08-08|1993-07-08|NONE|FOB|ously ironic foxes thrash +2720|16655|6656|2|42|66009.30|0.09|0.03|R|F|1993-07-25|1993-07-23|1993-08-23|COLLECT COD|REG AIR|fter the inst +2720|119065|9066|3|50|54203.00|0.10|0.02|A|F|1993-08-10|1993-07-29|1993-09-06|NONE|SHIP|l requests. deposits nag furiously +2720|108938|1449|4|49|95399.57|0.06|0.02|A|F|1993-07-09|1993-07-14|1993-07-13|NONE|REG AIR| accounts. fluffily bold pack +2720|120884|3397|5|27|51431.76|0.04|0.00|R|F|1993-06-29|1993-08-06|1993-07-28|NONE|TRUCK|eas. carefully regular +2721|182460|4979|1|49|75580.54|0.00|0.08|N|O|1996-02-14|1996-04-26|1996-03-02|DELIVER IN PERSON|AIR|ounts poach carefu +2721|2633|2634|2|2|3071.26|0.02|0.05|N|O|1996-02-13|1996-03-14|1996-02-28|TAKE BACK RETURN|TRUCK| slyly final requests against +2722|123803|1340|1|21|38362.80|0.09|0.01|A|F|1994-07-29|1994-06-26|1994-08-09|NONE|RAIL|e carefully around the furiously ironic pac +2722|145739|5740|2|15|26770.95|0.05|0.03|R|F|1994-07-02|1994-06-01|1994-07-13|COLLECT COD|AIR|refully final asympt +2722|33709|6213|3|16|26283.20|0.04|0.06|R|F|1994-05-25|1994-06-09|1994-05-26|NONE|MAIL|ts besides the fluffy, +2723|12688|5190|1|47|75231.96|0.09|0.07|N|O|1995-12-05|1995-11-19|1995-12-11|TAKE BACK RETURN|AIR|furiously r +2723|31913|6920|2|10|18449.10|0.06|0.08|N|O|1995-11-27|1995-11-29|1995-12-12|DELIVER IN PERSON|MAIL|al, special r +2723|161747|4264|3|2|3617.48|0.10|0.01|N|O|1995-11-09|1995-11-10|1995-11-14|TAKE BACK RETURN|FOB| courts boost quickly about th +2723|81212|6229|4|12|14318.52|0.01|0.05|N|O|1995-12-24|1995-11-15|1996-01-17|DELIVER IN PERSON|RAIL|bold foxes are bold packages. regular, fin +2723|128077|8078|5|40|44202.80|0.09|0.05|N|O|1995-11-17|1995-11-22|1995-11-18|TAKE BACK RETURN|MAIL|unwind fluffily carefully regular realms. +2724|91316|3826|1|47|61443.57|0.09|0.01|A|F|1994-11-23|1994-11-13|1994-12-03|COLLECT COD|TRUCK|unusual patterns nag. special p +2724|146966|6967|2|21|42272.16|0.09|0.02|A|F|1994-11-25|1994-10-15|1994-12-07|COLLECT COD|RAIL|as. carefully regular dependencies wak +2724|49839|4848|3|22|39354.26|0.04|0.06|A|F|1994-09-19|1994-11-18|1994-10-17|TAKE BACK RETURN|TRUCK|express fo +2724|34495|9502|4|1|1429.49|0.07|0.03|A|F|1994-12-26|1994-11-27|1995-01-07|NONE|MAIL|lyly carefully blithe theodolites-- pl +2724|148071|3100|5|29|32453.03|0.05|0.06|A|F|1995-01-10|1994-11-17|1995-02-04|COLLECT COD|MAIL|l requests hagg +2725|117595|107|1|23|37089.57|0.10|0.08|R|F|1994-08-25|1994-06-22|1994-08-28|TAKE BACK RETURN|REG AIR|y regular deposits. brave foxes +2725|4819|7320|2|41|70676.21|0.01|0.00|R|F|1994-07-05|1994-06-29|1994-08-02|DELIVER IN PERSON|TRUCK|ns sleep furiously c +2725|188318|5873|3|15|21094.65|0.07|0.03|R|F|1994-08-06|1994-08-09|1994-08-15|TAKE BACK RETURN|AIR|? furiously regular a +2726|655|5656|1|50|77782.50|0.00|0.06|R|F|1993-03-04|1993-01-29|1993-03-28|COLLECT COD|TRUCK| furiously bold theodolites +2727|150928|5959|1|3|5936.76|0.03|0.01|N|O|1998-06-18|1998-06-06|1998-06-23|NONE|RAIL| the carefully regular foxes u +2752|30702|5709|1|41|66940.70|0.02|0.05|A|F|1994-03-02|1994-01-31|1994-03-06|DELIVER IN PERSON|AIR|tructions hag +2752|6810|1811|2|29|49787.49|0.02|0.04|R|F|1994-01-22|1994-01-08|1994-01-28|COLLECT COD|TRUCK|gly blithely re +2752|55050|5051|3|4|4020.20|0.08|0.00|A|F|1993-12-14|1994-02-13|1994-01-05|DELIVER IN PERSON|TRUCK|telets haggle. regular, final +2752|23153|660|4|40|43046.00|0.09|0.06|A|F|1994-01-24|1994-01-18|1994-02-22|DELIVER IN PERSON|MAIL|into beans are after the sly +2752|125934|959|5|22|43118.46|0.03|0.04|A|F|1994-03-20|1994-02-08|1994-04-01|TAKE BACK RETURN|TRUCK|equests nag. regular dependencies are furio +2752|169347|6896|6|21|29743.14|0.09|0.05|R|F|1994-01-01|1994-01-24|1994-01-24|COLLECT COD|SHIP| along the quickly +2752|198918|8919|7|38|76642.58|0.08|0.00|R|F|1994-02-23|1993-12-23|1994-03-24|DELIVER IN PERSON|SHIP|es boost. slyly silent ideas +2753|12855|359|1|6|10607.10|0.10|0.04|A|F|1993-12-30|1994-01-28|1994-01-29|COLLECT COD|TRUCK|s accounts +2753|47010|4523|2|40|38280.40|0.03|0.05|A|F|1994-01-06|1994-02-13|1994-02-03|DELIVER IN PERSON|SHIP|latelets kindle slyly final depos +2753|88608|3625|3|30|47898.00|0.00|0.07|A|F|1994-01-26|1994-01-29|1994-02-02|NONE|RAIL|ans wake fluffily blithely iro +2753|30853|3357|4|7|12486.95|0.07|0.03|R|F|1994-02-11|1994-01-22|1994-03-10|DELIVER IN PERSON|AIR|xpress ideas detect b +2753|136899|6900|5|36|69692.04|0.04|0.08|R|F|1994-03-15|1994-01-03|1994-04-03|DELIVER IN PERSON|SHIP|gle slyly final c +2753|49203|9204|6|17|19587.40|0.01|0.08|A|F|1994-03-08|1994-01-17|1994-03-11|TAKE BACK RETURN|REG AIR| carefully bold deposits sublate s +2753|147138|7139|7|20|23702.60|0.01|0.06|R|F|1994-02-24|1994-02-04|1994-03-23|DELIVER IN PERSON|FOB| express pack +2754|148092|607|1|4|4560.36|0.05|0.08|A|F|1994-07-13|1994-05-15|1994-08-02|NONE|REG AIR|blithely silent requests. regular depo +2754|176662|4214|2|19|33034.54|0.01|0.07|A|F|1994-06-27|1994-05-06|1994-06-28|NONE|FOB|latelets hag +2755|91404|3914|1|19|26512.60|0.10|0.00|R|F|1992-02-11|1992-03-15|1992-02-14|TAKE BACK RETURN|MAIL|furiously special deposits +2755|23483|8488|2|11|15471.28|0.03|0.08|A|F|1992-04-12|1992-05-07|1992-04-21|COLLECT COD|RAIL|egular excuses sleep carefully. +2755|63720|6227|3|21|35358.12|0.08|0.04|R|F|1992-02-13|1992-04-20|1992-03-02|NONE|AIR|furious re +2755|130096|7636|4|5|5630.45|0.01|0.00|A|F|1992-02-27|1992-04-07|1992-03-09|TAKE BACK RETURN|AIR|e the furi +2755|115039|5040|5|48|50593.44|0.05|0.06|R|F|1992-03-22|1992-03-10|1992-04-14|DELIVER IN PERSON|MAIL|yly even epitaphs for the +2756|117254|7255|1|35|44493.75|0.03|0.02|R|F|1994-06-08|1994-06-01|1994-06-21|TAKE BACK RETURN|AIR| deposits grow bold sheaves; iro +2756|79212|4227|2|47|55986.87|0.06|0.01|R|F|1994-05-10|1994-05-25|1994-05-13|NONE|AIR|e final, f +2756|104806|7317|3|31|56134.80|0.01|0.07|A|F|1994-07-27|1994-07-06|1994-08-22|TAKE BACK RETURN|TRUCK|en instructions use quickly. +2756|71763|4271|4|30|52042.80|0.00|0.04|A|F|1994-06-05|1994-06-30|1994-06-14|DELIVER IN PERSON|TRUCK|ular packages. regular deposi +2757|147369|9884|1|26|36825.36|0.07|0.00|N|O|1995-08-19|1995-10-02|1995-09-06|DELIVER IN PERSON|MAIL|around the blithely +2757|21865|4368|2|12|21442.32|0.07|0.08|N|O|1995-08-01|1995-09-04|1995-08-08|TAKE BACK RETURN|SHIP| regular, eve +2757|72740|5248|3|17|29116.58|0.10|0.04|N|O|1995-09-06|1995-09-27|1995-09-22|DELIVER IN PERSON|AIR|er the furiously silent +2757|139197|4224|4|25|30904.75|0.08|0.01|N|O|1995-11-09|1995-09-12|1995-11-23|NONE|AIR|uickly regular +2757|69696|4709|5|14|23319.66|0.04|0.05|N|O|1995-09-01|1995-08-24|1995-09-03|TAKE BACK RETURN|SHIP|special deposits u +2758|120880|5905|1|20|38017.60|0.02|0.04|N|O|1998-07-27|1998-09-10|1998-08-21|TAKE BACK RETURN|AIR|ptotes sleep furiously +2758|22897|5400|2|17|30938.13|0.10|0.06|N|O|1998-09-25|1998-10-03|1998-10-25|NONE|MAIL| accounts! qui +2758|25560|565|3|1|1485.56|0.06|0.02|N|O|1998-10-09|1998-09-15|1998-10-16|NONE|TRUCK|ake furious +2759|58995|6511|1|10|19539.90|0.10|0.03|R|F|1993-12-14|1994-01-08|1994-01-01|COLLECT COD|FOB|s. busily ironic theodo +2759|112674|7697|2|37|62406.79|0.00|0.06|R|F|1994-03-05|1994-02-22|1994-03-18|DELIVER IN PERSON|REG AIR|lar Tiresias affix ironically carefully sp +2759|111646|6669|3|11|18234.04|0.03|0.08|A|F|1994-01-24|1994-01-16|1994-02-21|DELIVER IN PERSON|TRUCK|hely regular +2759|22777|7782|4|31|52692.87|0.02|0.05|A|F|1994-01-11|1994-01-15|1994-01-23|NONE|SHIP|ithely aft +2784|32335|7342|1|45|57029.85|0.03|0.01|N|O|1998-02-15|1998-04-07|1998-02-26|COLLECT COD|AIR|yly along the asymptotes. reque +2784|53524|3525|2|23|33982.96|0.03|0.05|N|O|1998-03-28|1998-02-07|1998-04-17|DELIVER IN PERSON|AIR|uests lose after +2784|174715|9750|3|40|71588.40|0.07|0.01|N|O|1998-04-28|1998-03-19|1998-05-03|DELIVER IN PERSON|TRUCK|deas nag furiously never unusual +2784|28004|8005|4|3|2796.00|0.04|0.03|N|O|1998-01-19|1998-04-05|1998-02-05|TAKE BACK RETURN|AIR|n packages. foxes haggle quickly sile +2785|99049|4068|1|34|35633.36|0.08|0.06|N|O|1995-08-07|1995-09-09|1995-09-05|NONE|RAIL|ly final packages haggl +2785|109744|7275|2|37|64888.38|0.08|0.04|N|O|1995-07-25|1995-09-12|1995-08-06|DELIVER IN PERSON|TRUCK|tructions. furiously +2785|64524|2043|3|33|49121.16|0.08|0.06|N|O|1995-10-16|1995-08-24|1995-11-02|DELIVER IN PERSON|MAIL|fter the furiously final p +2785|47167|2176|4|34|37881.44|0.00|0.02|N|O|1995-09-16|1995-09-09|1995-10-11|COLLECT COD|SHIP|kages wake carefully silent +2786|135566|3106|1|15|24023.40|0.03|0.04|A|F|1992-05-19|1992-05-08|1992-05-28|COLLECT COD|TRUCK|low deposits are ironic +2786|50144|7660|2|42|45953.88|0.10|0.04|R|F|1992-05-15|1992-04-22|1992-05-30|DELIVER IN PERSON|AIR|unts are against the furious +2786|155318|349|3|41|56305.71|0.04|0.05|R|F|1992-07-01|1992-06-04|1992-07-13|COLLECT COD|RAIL|ix requests. bold requests a +2786|22696|2697|4|24|38848.56|0.05|0.02|A|F|1992-04-04|1992-06-09|1992-05-02|DELIVER IN PERSON|MAIL|ans. slyly unusual platelets detect. unus +2786|49478|4487|5|43|61381.21|0.06|0.03|R|F|1992-04-22|1992-05-13|1992-04-29|NONE|RAIL|ons. theodolites after +2786|161228|3745|6|21|27073.62|0.08|0.00|A|F|1992-05-03|1992-05-01|1992-05-14|COLLECT COD|AIR|slow instructi +2787|32479|9989|1|4|5645.88|0.04|0.04|N|O|1996-01-26|1995-11-26|1996-02-20|TAKE BACK RETURN|SHIP|ts. instructions nag furiously according +2788|176196|6197|1|16|20355.04|0.06|0.06|A|F|1994-10-04|1994-11-25|1994-10-18|DELIVER IN PERSON|AIR| requests wake carefully. carefully si +2789|162410|9959|1|16|23558.56|0.03|0.02|N|O|1998-04-18|1998-05-25|1998-05-12|DELIVER IN PERSON|REG AIR|o beans use carefully +2789|22835|2836|2|41|72071.03|0.02|0.05|N|O|1998-03-20|1998-05-15|1998-03-21|COLLECT COD|MAIL|d packages-- fluffily specia +2789|175892|927|3|33|64940.37|0.06|0.02|N|O|1998-04-21|1998-05-02|1998-04-30|COLLECT COD|TRUCK|deposits. ironic +2789|15982|985|4|47|89205.06|0.02|0.04|N|O|1998-03-29|1998-05-05|1998-04-07|NONE|RAIL|usly busy packages wake against the unusual +2789|196629|4187|5|23|39689.26|0.02|0.07|N|O|1998-03-25|1998-05-10|1998-04-24|COLLECT COD|RAIL|cording to the careful de +2789|143603|3604|6|16|26345.60|0.07|0.03|N|O|1998-05-11|1998-05-08|1998-05-24|TAKE BACK RETURN|RAIL|d the carefully iron +2789|132206|7233|7|42|52004.40|0.01|0.00|N|O|1998-04-28|1998-05-17|1998-05-24|TAKE BACK RETURN|AIR|ending packages shoul +2790|184300|4301|1|27|37376.10|0.06|0.08|R|F|1994-09-04|1994-09-27|1994-09-16|TAKE BACK RETURN|MAIL|ilent packages cajole. quickly ironic requ +2790|116975|9487|2|50|99598.50|0.00|0.06|A|F|1994-12-08|1994-11-17|1994-12-19|NONE|RAIL|fter the regular ideas. f +2790|183138|8175|3|19|23201.47|0.06|0.00|R|F|1994-10-23|1994-10-03|1994-10-26|TAKE BACK RETURN|RAIL|uffily even excuses. furiously thin +2790|196404|6405|4|24|36009.60|0.07|0.01|A|F|1994-12-04|1994-10-10|1994-12-25|NONE|MAIL|ments. slyly f +2790|147955|7956|5|11|22032.45|0.08|0.03|A|F|1994-09-28|1994-11-14|1994-10-04|TAKE BACK RETURN|AIR|lar requests poach slyly foxes +2790|72637|5145|6|13|20925.19|0.08|0.00|R|F|1994-09-20|1994-10-10|1994-10-20|COLLECT COD|SHIP|n deposits according to the regul +2790|3931|1432|7|32|58717.76|0.08|0.02|A|F|1994-09-25|1994-10-26|1994-10-01|NONE|SHIP|ully pending +2791|58694|8695|1|49|80981.81|0.10|0.04|A|F|1995-01-11|1994-11-10|1995-02-08|COLLECT COD|MAIL| accounts sleep at the bold, regular pinto +2791|62804|2805|2|4|7067.20|0.10|0.08|A|F|1995-01-02|1994-12-28|1995-01-29|NONE|SHIP|slyly bold packages boost. slyly +2791|132300|4814|3|44|58621.20|0.08|0.06|R|F|1994-11-17|1994-11-12|1994-12-14|NONE|FOB|heodolites use furio +2791|155894|3440|4|24|46797.36|0.04|0.02|R|F|1995-01-30|1994-11-20|1995-02-08|DELIVER IN PERSON|TRUCK|ilent forges. quickly special pinto beans +2791|104521|2052|5|8|12204.16|0.02|0.04|R|F|1995-01-30|1994-11-24|1995-02-13|NONE|FOB|se. close ideas alongs +2791|74435|1957|6|9|12684.87|0.08|0.02|R|F|1994-11-19|1994-12-14|1994-12-10|TAKE BACK RETURN|AIR|pendencies. blithely bold patterns acr +2791|28635|6142|7|26|40654.38|0.06|0.03|R|F|1995-02-06|1994-12-07|1995-02-23|DELIVER IN PERSON|AIR|uriously special instructio +2816|58258|8259|1|33|40136.25|0.00|0.07|R|F|1994-10-19|1994-11-10|1994-11-09|NONE|REG AIR|s; slyly even theodo +2816|141342|1343|2|4|5533.36|0.05|0.04|R|F|1994-12-11|1994-12-07|1995-01-03|NONE|FOB|. blithely pending id +2816|120406|2919|3|4|5705.60|0.02|0.06|R|F|1994-12-12|1994-12-05|1994-12-30|NONE|RAIL| requests print above the final deposits +2817|59597|2103|1|25|38914.75|0.07|0.01|R|F|1994-04-21|1994-06-20|1994-05-07|DELIVER IN PERSON|FOB|doze blithely. +2817|31271|3775|2|5|6011.35|0.03|0.04|A|F|1994-05-07|1994-05-31|1994-05-12|TAKE BACK RETURN|AIR|furiously unusual theodolites use furiou +2817|171177|8729|3|35|43685.95|0.01|0.07|A|F|1994-05-20|1994-06-03|1994-05-22|COLLECT COD|FOB|gular foxes +2817|160884|885|4|4|7779.52|0.00|0.05|R|F|1994-06-04|1994-06-11|1994-06-10|NONE|TRUCK|n accounts wake across the fluf +2818|120379|7916|1|12|16792.44|0.10|0.03|A|F|1995-02-01|1995-03-10|1995-02-16|NONE|AIR|lms. quickly bold asymp +2818|198766|3805|2|22|41024.72|0.06|0.07|R|F|1995-02-28|1995-03-10|1995-03-06|TAKE BACK RETURN|RAIL|egrate toward the carefully iron +2818|44234|4235|3|11|12960.53|0.01|0.06|R|F|1995-02-18|1995-02-11|1995-03-19|TAKE BACK RETURN|TRUCK|ggle across the carefully blithe +2818|39711|7221|4|32|52822.72|0.08|0.08|R|F|1995-02-04|1995-03-05|1995-02-18|COLLECT COD|REG AIR|arefully! ac +2818|17380|4884|5|42|54489.96|0.08|0.04|A|F|1995-02-12|1995-02-19|1995-03-13|COLLECT COD|MAIL|ar accounts wake carefully a +2818|90636|8164|6|7|11386.41|0.06|0.03|R|F|1995-03-24|1995-03-09|1995-04-06|TAKE BACK RETURN|TRUCK|ly according to the r +2819|69083|9084|1|17|17885.36|0.08|0.08|A|F|1994-07-16|1994-07-15|1994-07-17|TAKE BACK RETURN|RAIL|en deposits above the f +2819|66461|3980|2|12|17129.52|0.03|0.08|R|F|1994-07-18|1994-06-24|1994-07-28|NONE|MAIL| regular, regular a +2819|4924|2425|3|28|51209.76|0.03|0.08|R|F|1994-05-09|1994-07-02|1994-05-15|NONE|RAIL|ckages sublate carefully closely regular +2819|152830|2831|4|5|9414.15|0.00|0.02|R|F|1994-05-29|1994-06-12|1994-06-28|NONE|TRUCK| fluffily unusual foxes sleep caref +2819|199179|4218|5|6|7669.02|0.03|0.01|A|F|1994-07-22|1994-08-02|1994-07-29|NONE|REG AIR|eas after the carefully express pack +2820|173150|702|1|23|28132.45|0.04|0.08|R|F|1994-07-10|1994-08-08|1994-07-21|NONE|MAIL| was furiously. deposits among the ironic +2820|125718|3255|2|33|57542.43|0.08|0.06|A|F|1994-07-07|1994-08-17|1994-08-02|DELIVER IN PERSON|AIR|carefully even pinto beans. +2820|140013|7556|3|38|40014.38|0.03|0.08|A|F|1994-09-10|1994-08-07|1994-10-07|TAKE BACK RETURN|MAIL|ests despite the carefully unusual a +2820|196270|8790|4|40|54650.80|0.06|0.06|A|F|1994-08-08|1994-07-30|1994-08-21|TAKE BACK RETURN|REG AIR|g multipliers. final c +2821|180834|8389|1|4|7659.32|0.00|0.00|A|F|1993-09-15|1993-10-02|1993-09-17|TAKE BACK RETURN|TRUCK|nding foxes. +2821|71159|6174|2|4|4520.60|0.09|0.00|A|F|1993-11-19|1993-09-20|1993-11-27|TAKE BACK RETURN|TRUCK|ual multipliers. final deposits cajol +2821|163639|8672|3|27|45971.01|0.01|0.01|A|F|1993-11-27|1993-10-11|1993-12-08|COLLECT COD|TRUCK|requests. blit +2822|150765|3281|1|39|70814.64|0.04|0.02|R|F|1993-09-11|1993-08-29|1993-09-18|NONE|MAIL|kly about the sly +2823|85712|8221|1|45|76396.95|0.03|0.04|N|O|1995-12-28|1995-11-27|1996-01-02|DELIVER IN PERSON|SHIP|furiously special idea +2823|159624|4655|2|18|30305.16|0.00|0.03|N|O|1995-11-11|1995-10-30|1995-12-08|TAKE BACK RETURN|TRUCK| final deposits. furiously regular foxes u +2823|185277|7796|3|11|14984.97|0.07|0.02|N|O|1995-12-10|1995-11-24|1995-12-21|DELIVER IN PERSON|SHIP|bold requests nag blithely s +2823|138806|3833|4|48|88550.40|0.09|0.03|N|O|1995-11-21|1995-10-30|1995-11-27|NONE|SHIP|ously busily slow excus +2823|98943|3962|5|18|34954.92|0.04|0.06|N|O|1995-11-09|1995-10-30|1995-11-19|NONE|AIR|eas. decoys cajole deposi +2823|122443|7468|6|20|29308.80|0.07|0.00|N|O|1995-11-13|1995-12-06|1995-12-07|NONE|MAIL|its sleep between the unusual, ironic pac +2823|85076|2601|7|12|12732.84|0.02|0.04|N|O|1995-12-22|1995-11-20|1996-01-13|NONE|REG AIR|the slyly ironic dolphins; fin +2848|64222|6729|1|44|52193.68|0.01|0.05|R|F|1992-04-14|1992-05-09|1992-04-19|DELIVER IN PERSON|MAIL|ions. slyly express instructions n +2848|164452|4453|2|8|12131.60|0.07|0.01|A|F|1992-03-21|1992-05-18|1992-04-07|DELIVER IN PERSON|TRUCK|. silent, final ideas sublate packages. ir +2848|137332|9846|3|8|10954.64|0.07|0.08|A|F|1992-06-20|1992-04-12|1992-07-09|NONE|SHIP|sly regular foxes. +2848|124948|4949|4|34|67079.96|0.02|0.08|A|F|1992-03-15|1992-04-24|1992-04-12|TAKE BACK RETURN|RAIL|ts along the blithely regu +2848|194197|6717|5|18|23241.42|0.07|0.03|R|F|1992-04-10|1992-06-01|1992-05-05|DELIVER IN PERSON|TRUCK|osits haggle. stealthily ironic packa +2849|153805|6321|1|16|29740.80|0.09|0.08|N|O|1996-05-20|1996-07-23|1996-06-18|NONE|TRUCK|. furiously regular requ +2849|186843|1880|2|39|75263.76|0.10|0.03|N|O|1996-05-22|1996-07-18|1996-06-05|TAKE BACK RETURN|SHIP|s sleep furiously silently regul +2849|59872|9873|3|24|43964.88|0.01|0.05|N|O|1996-06-12|1996-07-10|1996-06-27|TAKE BACK RETURN|AIR|e slyly even asymptotes. slo +2849|54230|1746|4|48|56843.04|0.05|0.02|N|O|1996-05-03|1996-06-05|1996-05-28|NONE|AIR|mong the carefully regular theodol +2849|27255|2260|5|30|35467.50|0.10|0.06|N|O|1996-08-24|1996-07-08|1996-09-03|TAKE BACK RETURN|SHIP|ly. carefully silent +2849|68651|6170|6|30|48589.50|0.06|0.07|N|O|1996-06-20|1996-07-23|1996-07-06|NONE|FOB|yly furiously even id +2850|96931|4459|1|43|82900.99|0.02|0.05|N|O|1997-01-11|1996-11-03|1997-02-01|COLLECT COD|REG AIR|unusual accounts +2850|109283|6814|2|30|38768.40|0.09|0.01|N|O|1996-12-14|1996-11-29|1997-01-03|COLLECT COD|AIR|even ideas. busy pinto beans sleep above t +2850|104731|4732|3|49|85050.77|0.09|0.04|N|O|1996-10-07|1996-12-12|1996-10-12|TAKE BACK RETURN|MAIL| slyly unusual req +2850|198372|5930|4|4|5881.48|0.04|0.04|N|O|1996-10-28|1996-12-26|1996-11-07|COLLECT COD|RAIL|al deposits cajole carefully quickly +2851|147452|9967|1|8|11995.60|0.09|0.03|N|O|1997-11-12|1997-11-22|1997-12-11|NONE|REG AIR|y special theodolites. carefully +2852|176179|1214|1|6|7531.02|0.01|0.01|R|F|1993-03-02|1993-04-11|1993-03-11|TAKE BACK RETURN|RAIL| accounts above the furiously un +2852|40065|7578|2|24|24121.44|0.05|0.07|R|F|1993-01-18|1993-03-13|1993-02-14|DELIVER IN PERSON|MAIL| the blithe +2852|163403|952|3|29|42525.60|0.09|0.05|R|F|1993-04-21|1993-03-22|1993-05-02|COLLECT COD|SHIP|lyly ironi +2852|99183|4202|4|12|14186.16|0.08|0.02|A|F|1993-02-25|1993-03-24|1993-03-07|TAKE BACK RETURN|TRUCK|le. request +2852|153182|5698|5|28|34585.04|0.05|0.03|R|F|1993-02-08|1993-03-30|1993-02-11|NONE|MAIL|e accounts. caref +2853|138855|1369|1|14|26513.90|0.07|0.05|R|F|1994-05-16|1994-07-01|1994-05-27|NONE|TRUCK|oach slyly along t +2853|133051|591|2|26|28185.30|0.06|0.01|R|F|1994-06-26|1994-06-05|1994-07-02|TAKE BACK RETURN|MAIL|dolphins wake slyly. blith +2853|172674|5192|3|40|69866.80|0.06|0.04|A|F|1994-08-06|1994-06-24|1994-08-29|NONE|RAIL|lyly. pearls cajole. final accounts ca +2853|131257|8797|4|20|25765.00|0.02|0.04|A|F|1994-08-30|1994-06-16|1994-09-06|TAKE BACK RETURN|TRUCK|e slyly silent foxes. express deposits sno +2853|35872|879|5|1|1807.87|0.08|0.05|R|F|1994-09-01|1994-06-27|1994-09-12|TAKE BACK RETURN|FOB|refully slyly quick packages. final c +2854|180193|7748|1|46|58566.74|0.00|0.04|A|F|1994-09-22|1994-08-02|1994-09-30|COLLECT COD|AIR|. furiously regular deposits across th +2854|87581|7582|2|29|45488.82|0.09|0.07|R|F|1994-07-06|1994-08-26|1994-07-09|COLLECT COD|SHIP|y slyly ironic accounts. foxes haggle slyl +2854|159170|1686|3|20|24583.40|0.08|0.01|R|F|1994-09-18|1994-08-03|1994-10-12|COLLECT COD|AIR|rs impress after the deposits. +2854|169448|9449|4|34|51592.96|0.06|0.03|A|F|1994-09-06|1994-08-07|1994-09-22|NONE|REG AIR|age carefully +2854|101316|1317|5|7|9221.17|0.03|0.06|A|F|1994-09-23|1994-08-14|1994-10-10|DELIVER IN PERSON|REG AIR| the pending +2854|17762|264|6|13|21836.88|0.04|0.03|R|F|1994-09-15|1994-08-18|1994-09-19|DELIVER IN PERSON|SHIP| excuses wak +2855|32224|7231|1|50|57811.00|0.03|0.07|A|F|1993-05-20|1993-06-28|1993-06-16|TAKE BACK RETURN|TRUCK|beans. deposits +2880|34078|9085|1|40|40482.80|0.09|0.00|A|F|1992-05-26|1992-06-01|1992-05-31|COLLECT COD|TRUCK|even requests. quick +2880|138854|6394|2|26|49214.10|0.07|0.07|R|F|1992-04-12|1992-04-15|1992-04-28|NONE|RAIL|ully among the regular warthogs +2880|114490|7002|3|42|63188.58|0.01|0.01|R|F|1992-06-17|1992-05-29|1992-07-11|NONE|REG AIR|ions. carefully final accounts are unusual, +2880|17656|158|4|46|72387.90|0.02|0.02|A|F|1992-04-21|1992-06-05|1992-05-16|COLLECT COD|RAIL|eep quickly according to t +2881|179343|1861|1|16|22757.44|0.02|0.06|A|F|1992-06-21|1992-06-27|1992-07-03|TAKE BACK RETURN|TRUCK|usly bold +2881|9181|9182|2|1|1090.18|0.09|0.03|A|F|1992-05-13|1992-07-21|1992-05-18|COLLECT COD|MAIL|final theodolites. quickly +2881|92018|7037|3|21|21210.21|0.07|0.03|A|F|1992-05-28|1992-07-03|1992-06-02|TAKE BACK RETURN|SHIP|hely express Tiresias. final dependencies +2881|139814|7354|4|7|12976.67|0.06|0.01|R|F|1992-08-03|1992-07-10|1992-08-27|NONE|REG AIR|ironic packages are carefully final ac +2882|3763|6264|1|14|23334.64|0.09|0.02|N|O|1995-09-28|1995-11-11|1995-10-18|TAKE BACK RETURN|MAIL|kly. even requests w +2882|41007|8520|2|30|28440.00|0.00|0.00|N|O|1995-10-15|1995-10-13|1995-10-25|NONE|REG AIR|among the furiously even theodolites. regu +2882|196935|9455|3|29|58925.97|0.10|0.08|N|O|1995-09-10|1995-11-01|1995-10-02|NONE|TRUCK|kages. furiously ironic +2882|77298|4820|4|27|34432.83|0.06|0.02|N|O|1995-09-04|1995-11-11|1995-09-12|DELIVER IN PERSON|MAIL|rding to the regu +2882|133878|3879|5|32|61179.84|0.07|0.03|N|O|1995-10-21|1995-11-10|1995-11-01|COLLECT COD|RAIL|sts. quickly regular e +2882|86425|6426|6|47|66336.74|0.06|0.03|N|O|1995-09-13|1995-09-21|1995-09-14|NONE|REG AIR|l, special +2883|91|2592|1|33|32705.97|0.08|0.07|R|F|1995-02-26|1995-03-04|1995-03-01|NONE|RAIL|s. final i +2883|124341|4342|2|27|36864.18|0.00|0.02|A|F|1995-03-12|1995-03-10|1995-04-04|TAKE BACK RETURN|REG AIR|s. brave pinto beans nag furiously +2883|188690|6245|3|47|83598.43|0.05|0.04|R|F|1995-01-29|1995-04-19|1995-02-05|DELIVER IN PERSON|SHIP|ep carefully ironic +2883|97483|5011|4|23|34051.04|0.00|0.02|R|F|1995-02-03|1995-03-17|1995-02-19|TAKE BACK RETURN|AIR| even requests cajole. special, regular +2883|194465|9504|5|36|56140.56|0.07|0.06|A|F|1995-05-02|1995-03-14|1995-05-30|COLLECT COD|MAIL|ests detect slyly special packages +2884|70492|493|1|41|59962.09|0.03|0.00|N|O|1998-01-02|1997-12-17|1998-01-20|DELIVER IN PERSON|TRUCK|ep. slyly even accounts a +2884|145132|2675|2|25|29428.25|0.09|0.08|N|O|1998-01-18|1997-12-06|1998-02-16|TAKE BACK RETURN|MAIL|onic theodolites with the instructi +2884|25106|5107|3|8|8248.80|0.08|0.08|N|O|1997-11-30|1997-11-28|1997-12-14|COLLECT COD|TRUCK|pending accounts about +2885|3054|8055|1|6|5742.30|0.10|0.01|A|F|1993-01-05|1992-12-12|1993-01-19|COLLECT COD|FOB|ctions solve. slyly regular requests n +2885|111966|1967|2|4|7911.84|0.07|0.00|A|F|1992-10-09|1992-12-17|1992-11-04|TAKE BACK RETURN|SHIP| pending packages wake. +2885|716|5717|3|45|72751.95|0.10|0.04|A|F|1992-12-24|1992-10-30|1993-01-04|NONE|SHIP|ess ideas. regular, silen +2885|31307|6314|4|15|18574.50|0.03|0.04|R|F|1992-10-31|1992-11-24|1992-11-21|DELIVER IN PERSON|MAIL|odolites. boldly pending packages han +2885|174189|6707|5|43|54316.74|0.06|0.00|R|F|1992-11-17|1992-10-30|1992-12-04|DELIVER IN PERSON|SHIP|cial deposits use bold +2885|189615|7170|6|5|8523.05|0.01|0.02|R|F|1993-01-06|1992-11-13|1993-02-05|TAKE BACK RETURN|TRUCK|s. slyly express th +2885|49234|6747|7|40|47329.20|0.05|0.03|A|F|1992-09-23|1992-11-15|1992-10-07|TAKE BACK RETURN|AIR| express depos +2886|59748|9749|1|1|1707.74|0.09|0.05|A|F|1995-02-01|1994-12-18|1995-02-28|COLLECT COD|REG AIR|eposits fr +2886|183832|3833|2|38|72801.54|0.02|0.04|A|F|1995-01-21|1995-01-08|1995-01-30|NONE|SHIP|old requests along the fur +2886|62934|453|3|2|3793.86|0.04|0.07|A|F|1994-11-18|1995-01-31|1994-12-05|COLLECT COD|REG AIR|ar theodolites. e +2886|129991|7528|4|46|92965.54|0.03|0.08|A|F|1995-02-02|1995-01-26|1995-02-15|TAKE BACK RETURN|SHIP|ously final packages sleep blithely regular +2887|65504|517|1|11|16164.50|0.06|0.00|N|O|1997-07-08|1997-07-17|1997-07-15|COLLECT COD|SHIP|ackages. unusual, speci +2887|111534|4046|2|17|26274.01|0.00|0.08|N|O|1997-08-31|1997-07-04|1997-09-17|DELIVER IN PERSON|SHIP|fily final packages. regula +2912|121445|6470|1|8|11731.52|0.06|0.04|A|F|1992-04-09|1992-04-19|1992-04-26|NONE|RAIL|hs cajole over the slyl +2912|114577|7089|2|18|28648.26|0.00|0.08|R|F|1992-03-13|1992-04-19|1992-03-30|TAKE BACK RETURN|RAIL|unts cajole reg +2913|122736|273|1|39|68590.47|0.06|0.04|N|O|1997-08-28|1997-09-27|1997-09-02|TAKE BACK RETURN|AIR|. final packages a +2913|21727|9234|2|22|36271.84|0.10|0.07|N|O|1997-09-18|1997-08-11|1997-10-02|COLLECT COD|MAIL|riously pending realms. blithely even pac +2913|165309|2858|3|17|23363.10|0.07|0.04|N|O|1997-10-21|1997-09-25|1997-11-20|NONE|FOB|requests doze quickly. furious +2913|142502|2503|4|5|7722.50|0.10|0.07|N|O|1997-10-07|1997-08-25|1997-10-09|TAKE BACK RETURN|RAIL|haggle. even, bold instructi +2913|14885|7387|5|13|23398.44|0.03|0.01|N|O|1997-10-02|1997-08-20|1997-10-26|COLLECT COD|MAIL|inos are carefully alongside of the bol +2913|167718|2751|6|35|62499.85|0.06|0.08|N|O|1997-08-30|1997-08-21|1997-09-03|COLLECT COD|MAIL|es. quickly even braids against +2914|65685|5686|1|22|36314.96|0.05|0.06|R|F|1993-05-11|1993-04-09|1993-05-22|DELIVER IN PERSON|FOB| carefully about the fluffily ironic gifts +2914|162197|7230|2|25|31479.75|0.03|0.04|A|F|1993-05-14|1993-04-04|1993-05-22|NONE|SHIP|cross the carefully even accounts. +2914|34588|7092|3|4|6090.32|0.00|0.05|R|F|1993-06-11|1993-04-09|1993-06-14|TAKE BACK RETURN|SHIP|s integrate. bold deposits sleep req +2914|120324|325|4|9|12098.88|0.06|0.01|R|F|1993-06-17|1993-05-26|1993-06-19|NONE|REG AIR|s. carefully final foxes ar +2915|174124|6642|1|28|33547.36|0.10|0.02|R|F|1994-04-17|1994-06-09|1994-05-10|NONE|MAIL|yly special +2915|93386|8405|2|12|16552.56|0.00|0.03|A|F|1994-07-18|1994-06-11|1994-07-27|TAKE BACK RETURN|RAIL|accounts. slyly final +2915|135401|7915|3|15|21546.00|0.07|0.00|A|F|1994-05-01|1994-06-12|1994-05-15|DELIVER IN PERSON|TRUCK|al requests haggle furiousl +2915|80116|2625|4|43|47132.73|0.06|0.05|R|F|1994-06-02|1994-05-24|1994-06-06|DELIVER IN PERSON|SHIP|into beans dazzle alongside of +2916|82501|5010|1|21|31153.50|0.06|0.04|N|O|1996-03-11|1996-02-21|1996-03-30|NONE|REG AIR|uickly express ideas over the slyly even +2917|92630|2631|1|36|58414.68|0.10|0.01|N|O|1998-04-07|1998-02-23|1998-05-01|DELIVER IN PERSON|RAIL|usly ironic d +2917|20711|712|2|20|32634.20|0.06|0.03|N|O|1997-12-31|1998-01-22|1998-01-12|NONE|MAIL|slyly even ideas wa +2917|89342|6867|3|4|5325.36|0.02|0.07|N|O|1998-01-10|1998-01-18|1998-02-08|TAKE BACK RETURN|REG AIR|s. unusual instruct +2917|166826|4375|4|5|9464.10|0.05|0.01|N|O|1997-12-16|1998-01-26|1998-01-07|NONE|RAIL|bove the furiously silent packages. pend +2917|40412|7925|5|37|50039.17|0.04|0.01|N|O|1997-12-12|1998-02-03|1997-12-23|COLLECT COD|RAIL|dependencies. express +2917|193921|1479|6|7|14104.44|0.05|0.01|N|O|1998-03-21|1998-03-03|1998-03-25|NONE|REG AIR|ly about the regular accounts. carefully pe +2918|77412|2427|1|24|33345.84|0.10|0.03|N|O|1996-12-20|1996-10-28|1996-12-26|DELIVER IN PERSON|FOB| quickly. express requests haggle careful +2919|101323|3834|1|2|2648.64|0.03|0.05|R|F|1993-12-28|1994-02-23|1994-01-18|COLLECT COD|TRUCK|re slyly. regular ideas detect furiousl +2919|120203|7740|2|49|59936.80|0.07|0.02|R|F|1993-12-16|1994-02-28|1993-12-19|COLLECT COD|FOB|hely final inst +2919|45595|3108|3|44|67785.96|0.07|0.07|A|F|1994-04-01|1994-01-12|1994-04-07|TAKE BACK RETURN|TRUCK|final ideas haggle carefully fluff +2919|101408|3919|4|44|62013.60|0.00|0.05|R|F|1994-02-04|1994-02-03|1994-03-02|TAKE BACK RETURN|AIR|es doze around the furiously +2944|119834|9835|1|44|81568.52|0.08|0.05|N|O|1997-12-25|1997-10-28|1998-01-21|COLLECT COD|AIR|ickly special theodolit +2944|41779|4284|2|44|75713.88|0.06|0.02|N|O|1997-10-28|1997-11-22|1997-11-10|NONE|SHIP|ickly. regular requests haggle. idea +2944|169657|7206|3|2|3453.30|0.06|0.07|N|O|1997-12-13|1997-12-01|1998-01-08|DELIVER IN PERSON|REG AIR|luffily expr +2944|16331|3835|4|23|28688.59|0.02|0.03|N|O|1998-01-12|1997-12-03|1998-01-17|TAKE BACK RETURN|MAIL| excuses? regular platelets e +2944|74247|9262|5|18|21982.32|0.10|0.01|N|O|1998-01-07|1997-10-26|1998-01-27|TAKE BACK RETURN|FOB| furiously slyl +2944|59267|6783|6|17|20846.42|0.00|0.03|N|O|1997-10-18|1997-11-27|1997-10-29|TAKE BACK RETURN|SHIP|slyly final dolphins sleep silent the +2944|89264|1773|7|7|8772.82|0.01|0.06|N|O|1997-10-30|1997-11-03|1997-11-03|DELIVER IN PERSON|FOB|fluffily blithely express pea +2945|58944|8945|1|37|70408.78|0.00|0.02|N|O|1996-02-10|1996-03-20|1996-02-12|COLLECT COD|SHIP|l instructions. regular, regular +2945|71252|3760|2|30|36697.50|0.05|0.01|N|O|1996-01-19|1996-02-11|1996-01-26|NONE|TRUCK|ular instructions +2945|126197|6198|3|28|34249.32|0.06|0.02|N|O|1996-03-17|1996-03-13|1996-04-15|COLLECT COD|FOB|le slyly along the eve +2945|187861|7862|4|34|66261.24|0.08|0.06|N|O|1996-02-03|1996-03-17|1996-02-29|COLLECT COD|REG AIR|at the unusual theodolite +2945|172280|9832|5|10|13522.80|0.09|0.05|N|O|1996-03-13|1996-03-10|1996-04-06|COLLECT COD|FOB|thely. final courts could hang qu +2945|96154|8664|6|45|51756.75|0.07|0.00|N|O|1996-03-01|1996-03-25|1996-03-08|TAKE BACK RETURN|MAIL|ainst the final packages +2945|51230|3736|7|47|55517.81|0.07|0.05|N|O|1996-01-05|1996-02-11|1996-01-12|DELIVER IN PERSON|MAIL|quests use +2946|9193|4194|1|25|27554.75|0.05|0.02|N|O|1996-05-06|1996-04-23|1996-05-16|DELIVER IN PERSON|SHIP|ic deposits. furiously +2946|93176|3177|2|48|56120.16|0.03|0.07|N|O|1996-06-02|1996-03-31|1996-06-16|COLLECT COD|TRUCK|oss the platelets. furi +2946|2968|5469|3|35|65483.60|0.03|0.00|N|O|1996-03-15|1996-04-02|1996-03-26|NONE|REG AIR| sublate along the fluffily iron +2947|9960|9961|1|37|69188.52|0.09|0.07|N|O|1995-08-09|1995-07-05|1995-08-20|DELIVER IN PERSON|RAIL|e accounts: expres +2947|185207|7726|2|10|12922.00|0.09|0.07|A|F|1995-06-07|1995-06-26|1995-06-08|NONE|MAIL|lly special +2948|117469|7470|1|48|71350.08|0.00|0.04|R|F|1994-08-29|1994-10-23|1994-09-23|NONE|TRUCK|unusual excuses use about the +2948|91710|1711|2|49|83383.79|0.04|0.07|R|F|1994-12-16|1994-11-08|1995-01-07|DELIVER IN PERSON|MAIL|ress requests. furiously blithe foxes +2949|20139|2642|1|4|4236.52|0.06|0.06|A|F|1994-06-07|1994-06-17|1994-07-04|TAKE BACK RETURN|REG AIR|gular pinto beans wake alongside of the reg +2949|69423|6942|2|50|69621.00|0.05|0.04|A|F|1994-08-04|1994-06-23|1994-08-17|TAKE BACK RETURN|FOB|gular courts cajole across t +2949|179465|4500|3|38|58689.48|0.02|0.06|R|F|1994-05-22|1994-05-25|1994-05-27|COLLECT COD|REG AIR|se slyly requests. carefull +2950|129486|9487|1|32|48495.36|0.01|0.05|N|O|1997-09-21|1997-08-25|1997-10-08|DELIVER IN PERSON|REG AIR|its wake carefully slyly final ideas. +2950|65786|5787|2|18|31532.04|0.10|0.01|N|O|1997-07-19|1997-08-29|1997-08-17|COLLECT COD|TRUCK|uests cajole furio +2950|52680|2681|3|14|22857.52|0.01|0.02|N|O|1997-07-29|1997-08-05|1997-07-31|TAKE BACK RETURN|MAIL|ccounts haggle carefully according +2950|186367|6368|4|45|65401.20|0.08|0.00|N|O|1997-09-05|1997-09-23|1997-09-11|NONE|FOB|ides the b +2950|60950|951|5|46|87903.70|0.02|0.05|N|O|1997-07-15|1997-09-30|1997-07-25|COLLECT COD|RAIL|to the regular accounts are slyly carefu +2950|173548|3549|6|27|43781.58|0.01|0.03|N|O|1997-10-01|1997-09-13|1997-10-08|NONE|TRUCK|are alongside of the carefully silent +2951|2079|7080|1|5|4905.35|0.03|0.03|N|O|1996-03-27|1996-04-16|1996-03-30|NONE|REG AIR|to beans wake ac +2951|135955|8469|2|24|47782.80|0.07|0.03|N|O|1996-03-24|1996-04-16|1996-04-08|NONE|SHIP| ironic multipliers. express, regular +2951|186046|3601|3|40|45281.60|0.02|0.07|N|O|1996-05-03|1996-04-20|1996-05-22|COLLECT COD|REG AIR|ial deposits wake fluffily about th +2951|72188|4696|4|21|24363.78|0.06|0.08|N|O|1996-04-12|1996-04-27|1996-04-14|DELIVER IN PERSON|REG AIR|nt instructions toward the f +2951|50131|5142|5|15|16216.95|0.07|0.00|N|O|1996-03-25|1996-04-23|1996-03-27|COLLECT COD|REG AIR|inal account +2951|137099|4639|6|18|20449.62|0.06|0.00|N|O|1996-04-04|1996-04-27|1996-04-06|COLLECT COD|FOB|ep about the final, even package +2976|8521|3522|1|32|45744.64|0.06|0.00|A|F|1994-01-26|1994-02-13|1994-02-10|NONE|MAIL|nding, ironic deposits sleep f +2976|3059|3060|2|24|23089.20|0.00|0.03|A|F|1994-03-19|1994-01-26|1994-04-18|COLLECT COD|TRUCK|ronic pinto beans. slyly bol +2976|9775|4776|3|35|58966.95|0.10|0.07|R|F|1993-12-19|1994-02-14|1994-01-11|NONE|RAIL|boost slyly about the regular, regular re +2976|81070|6087|4|22|23123.54|0.00|0.04|A|F|1994-02-08|1994-03-03|1994-02-12|TAKE BACK RETURN|FOB|ncies kindle furiously. carefull +2976|133261|8288|5|13|16825.38|0.00|0.06|A|F|1994-02-06|1994-02-02|1994-02-19|NONE|FOB| furiously final courts boost +2976|108348|859|6|30|40690.20|0.08|0.03|R|F|1994-03-27|1994-02-01|1994-04-26|TAKE BACK RETURN|RAIL|c ideas! unusual +2977|69769|7288|1|25|43469.00|0.03|0.07|N|O|1996-09-21|1996-10-06|1996-10-13|TAKE BACK RETURN|RAIL|furiously pe +2978|89697|9698|1|29|48914.01|0.00|0.08|A|F|1995-06-03|1995-07-25|1995-06-06|NONE|SHIP|ecial ideas promise slyly +2978|126998|9511|2|42|85049.58|0.01|0.06|N|O|1995-08-19|1995-07-18|1995-09-07|DELIVER IN PERSON|MAIL|ial requests nag blithely alongside of th +2978|42972|485|3|26|49789.22|0.07|0.05|N|O|1995-07-29|1995-07-22|1995-08-20|COLLECT COD|REG AIR|as haggle against the carefully express dep +2978|27039|4546|4|7|6762.21|0.00|0.00|N|O|1995-07-18|1995-07-03|1995-07-23|NONE|FOB|. final ideas are blithe +2978|28403|5910|5|33|43936.20|0.09|0.03|R|F|1995-05-06|1995-07-23|1995-05-16|COLLECT COD|FOB|s. blithely unusual pack +2978|167063|9580|6|4|4520.24|0.08|0.04|N|O|1995-07-06|1995-07-31|1995-07-19|COLLECT COD|AIR|ffily unusual +2979|8022|5523|1|8|7440.16|0.00|0.08|N|O|1996-06-18|1996-05-21|1996-07-06|COLLECT COD|REG AIR|st blithely; blithely regular gifts dazz +2979|10662|663|2|47|73915.02|0.05|0.00|N|O|1996-03-25|1996-05-13|1996-04-04|TAKE BACK RETURN|SHIP|iously unusual dependencies wake across +2979|187872|5427|3|35|68595.45|0.04|0.03|N|O|1996-05-25|1996-06-11|1996-06-24|DELIVER IN PERSON|MAIL|old ideas beneath the blit +2979|164037|6554|4|28|30828.84|0.05|0.08|N|O|1996-06-04|1996-04-23|1996-06-24|DELIVER IN PERSON|FOB|ing, regular pinto beans. blithel +2980|36367|8871|1|2|2606.72|0.09|0.03|N|O|1996-11-18|1996-10-22|1996-11-27|TAKE BACK RETURN|SHIP|enly across the special, pending packag +2980|9576|7077|2|48|71307.36|0.04|0.05|N|O|1996-09-25|1996-12-09|1996-10-12|NONE|REG AIR|totes. regular pinto +2980|132090|4604|3|27|30296.43|0.08|0.08|N|O|1996-12-08|1996-12-03|1996-12-14|NONE|REG AIR| theodolites cajole blithely sl +2980|24644|7147|4|49|76863.36|0.03|0.02|N|O|1996-10-04|1996-12-04|1996-10-06|NONE|RAIL|hy packages sleep quic +2980|186048|6049|5|24|27216.96|0.05|0.04|N|O|1997-01-12|1996-10-27|1997-01-14|NONE|MAIL|elets. fluffily regular in +2980|108666|3687|6|43|72010.38|0.01|0.01|N|O|1996-12-07|1996-11-10|1997-01-02|COLLECT COD|AIR|sts. slyly regu +2981|13505|1009|1|17|24114.50|0.03|0.05|N|O|1998-10-17|1998-10-02|1998-10-21|DELIVER IN PERSON|RAIL|, unusual packages x-ray. furious +2981|175430|2982|2|8|12043.44|0.06|0.03|N|O|1998-08-21|1998-09-28|1998-09-05|DELIVER IN PERSON|MAIL|ng to the f +2981|36615|4125|3|14|21722.54|0.03|0.07|N|O|1998-08-30|1998-10-04|1998-09-04|DELIVER IN PERSON|MAIL|kages detect furiously express requests. +2982|111936|4448|1|21|40906.53|0.00|0.01|A|F|1995-04-03|1995-06-08|1995-04-18|DELIVER IN PERSON|AIR|ironic deposits. furiously ex +2982|98071|3090|2|13|13897.91|0.02|0.08|R|F|1995-03-31|1995-05-07|1995-04-18|TAKE BACK RETURN|RAIL|regular deposits unwind alongside +2982|69479|6998|3|21|30417.87|0.01|0.01|R|F|1995-04-19|1995-06-03|1995-04-28|COLLECT COD|SHIP|egular ideas use furiously? bl +2983|162174|2175|1|44|54391.48|0.03|0.06|R|F|1992-02-09|1992-03-07|1992-03-09|TAKE BACK RETURN|AIR|ly regular instruct +2983|48039|5552|2|11|10857.33|0.09|0.06|A|F|1992-04-29|1992-02-27|1992-05-26|NONE|MAIL|aids integrate s +3008|131565|6592|1|8|12772.48|0.10|0.04|N|O|1995-12-06|1996-01-12|1995-12-22|TAKE BACK RETURN|FOB|yly ironic foxes. regular requests h +3008|199716|4755|2|31|56287.01|0.05|0.06|N|O|1995-12-14|1995-12-11|1995-12-31|TAKE BACK RETURN|AIR| bold packages. quic +3008|23054|3055|3|40|39082.00|0.01|0.03|N|O|1995-12-18|1996-01-06|1996-01-11|COLLECT COD|AIR|esias. theodolites detect blithely +3008|59018|9019|4|48|46896.48|0.07|0.06|N|O|1996-01-23|1996-01-07|1996-02-09|COLLECT COD|SHIP|ld theodolites. fluffily bold theodolit +3008|104156|9177|5|31|35964.65|0.03|0.02|N|O|1995-12-01|1996-01-20|1995-12-28|COLLECT COD|RAIL|nts use thinly around the carefully iro +3009|44862|9871|1|48|86729.28|0.10|0.02|N|O|1997-03-19|1997-05-13|1997-04-11|TAKE BACK RETURN|TRUCK| dependencies sleep quickly a +3009|184598|7117|2|38|63938.42|0.00|0.01|N|O|1997-05-01|1997-04-10|1997-05-17|TAKE BACK RETURN|AIR|nal packages should haggle slyly. quickl +3009|129770|7307|3|26|46794.02|0.08|0.02|N|O|1997-05-15|1997-05-10|1997-06-13|TAKE BACK RETURN|SHIP|uriously specia +3010|137941|455|1|23|45515.62|0.04|0.00|N|O|1996-03-08|1996-02-29|1996-03-27|NONE|TRUCK|ounts. pendin +3010|173015|5533|2|22|23936.22|0.09|0.06|N|O|1996-03-06|1996-04-06|1996-03-18|COLLECT COD|REG AIR| final deposit +3010|57050|9556|3|24|24169.20|0.04|0.07|N|O|1996-05-09|1996-03-14|1996-05-15|DELIVER IN PERSON|RAIL|ar, even reques +3010|23675|1182|4|28|44762.76|0.09|0.06|N|O|1996-03-05|1996-03-28|1996-04-03|DELIVER IN PERSON|FOB|ake carefully carefully even request +3010|103499|3500|5|9|13522.41|0.02|0.02|N|O|1996-04-28|1996-03-17|1996-05-18|NONE|SHIP|inal packages. quickly even pinto +3010|91955|1956|6|38|73984.10|0.05|0.07|N|O|1996-04-15|1996-03-16|1996-04-21|DELIVER IN PERSON|RAIL|accounts ar +3011|197592|112|1|5|8447.95|0.02|0.04|R|F|1992-04-21|1992-02-23|1992-05-15|NONE|TRUCK|nusual sentiments. carefully bold idea +3011|122709|2710|2|42|72731.40|0.05|0.00|A|F|1992-02-01|1992-03-18|1992-02-29|NONE|TRUCK|osits haggle quickly pending, +3012|194274|6794|1|49|67045.23|0.00|0.00|A|F|1993-08-07|1993-07-01|1993-08-08|NONE|MAIL| quickly furious packages. silently unusua +3012|160226|227|2|37|47590.14|0.06|0.03|A|F|1993-08-16|1993-06-07|1993-08-24|TAKE BACK RETURN|REG AIR|uickly permanent packages sleep caref +3013|93613|6123|1|31|49804.91|0.08|0.08|N|O|1997-05-03|1997-04-05|1997-05-25|NONE|AIR|y furious depen +3013|138866|6406|2|30|57145.80|0.05|0.06|N|O|1997-05-02|1997-03-09|1997-05-12|TAKE BACK RETURN|MAIL|ronic packages. slyly even +3013|119628|7162|3|35|57666.70|0.00|0.03|N|O|1997-04-02|1997-05-04|1997-04-16|COLLECT COD|MAIL|ely accord +3013|180929|3448|4|17|34168.64|0.01|0.07|N|O|1997-02-26|1997-05-02|1997-03-27|DELIVER IN PERSON|SHIP|fully unusual account +3013|59896|4907|5|20|37117.80|0.00|0.04|N|O|1997-05-06|1997-03-18|1997-05-12|COLLECT COD|RAIL|unts boost regular ideas. slyly pe +3013|71557|4065|6|19|29042.45|0.08|0.07|N|O|1997-05-11|1997-04-18|1997-05-15|COLLECT COD|REG AIR|fluffily pending packages nag furiously al +3014|162368|2369|1|36|51492.96|0.05|0.03|A|F|1992-11-16|1993-01-20|1992-11-28|TAKE BACK RETURN|FOB|ding accounts boost fu +3014|105025|46|2|36|37080.72|0.00|0.08|R|F|1992-12-28|1992-12-29|1993-01-24|COLLECT COD|MAIL|iously ironic r +3014|150885|3401|3|48|92922.24|0.06|0.02|A|F|1992-12-19|1993-01-08|1992-12-25|DELIVER IN PERSON|REG AIR|y pending theodolites wake. reg +3014|113767|8790|4|14|24930.64|0.10|0.02|R|F|1992-11-19|1993-01-01|1992-12-17|DELIVER IN PERSON|SHIP|. slyly brave platelets nag. careful, +3014|74210|6718|5|28|33157.88|0.02|0.08|R|F|1993-01-09|1992-12-18|1993-01-10|TAKE BACK RETURN|FOB|es are. final braids nag slyly. fluff +3014|37443|9947|6|30|41413.20|0.04|0.01|R|F|1993-02-28|1993-01-02|1993-03-20|TAKE BACK RETURN|AIR| final foxes. +3015|2643|7644|1|5|7728.20|0.09|0.00|A|F|1993-01-10|1992-12-02|1993-01-19|TAKE BACK RETURN|RAIL| the furiously pendi +3015|17510|12|2|17|24267.67|0.03|0.01|R|F|1992-10-16|1992-11-20|1992-10-28|COLLECT COD|AIR|s above the fluffily final t +3015|90543|5562|3|23|35271.42|0.03|0.05|A|F|1992-12-03|1992-11-19|1992-12-23|DELIVER IN PERSON|FOB|s are slyly carefully special pinto bea +3015|155005|5006|4|7|7420.00|0.10|0.03|A|F|1992-12-07|1992-12-17|1992-12-30|DELIVER IN PERSON|REG AIR| after the evenly special packages ca +3015|164614|7131|5|42|70501.62|0.04|0.02|R|F|1993-01-21|1992-11-07|1993-02-11|DELIVER IN PERSON|AIR|encies haggle furious +3015|65123|5124|6|18|19586.16|0.02|0.03|R|F|1992-10-10|1992-11-19|1992-10-18|TAKE BACK RETURN|MAIL|equests wake fluffil +3040|15347|2851|1|18|22722.12|0.08|0.04|R|F|1993-06-25|1993-07-06|1993-07-19|TAKE BACK RETURN|SHIP|ly thin accou +3040|132715|255|2|9|15729.39|0.00|0.01|A|F|1993-06-12|1993-05-16|1993-06-14|NONE|RAIL|ges. pending packages wake. requests +3040|125608|633|3|30|49008.00|0.01|0.01|A|F|1993-08-06|1993-05-18|1993-08-19|NONE|MAIL|x furiously bold packages. expres +3040|82065|7082|4|14|14658.84|0.05|0.04|A|F|1993-05-13|1993-05-18|1993-05-19|TAKE BACK RETURN|REG AIR| haggle carefully. express hocke +3040|51516|1517|5|43|63102.93|0.04|0.04|R|F|1993-05-21|1993-05-25|1993-05-26|NONE|MAIL|sts nag slyly alongside of the depos +3040|17878|2881|6|10|17958.70|0.08|0.04|R|F|1993-05-16|1993-06-24|1993-06-11|DELIVER IN PERSON|MAIL|ely regular foxes haggle dari +3041|180636|8191|1|5|8583.15|0.07|0.04|N|O|1997-07-20|1997-07-15|1997-08-17|COLLECT COD|FOB|posits dazzle special p +3041|145837|866|2|9|16945.47|0.03|0.03|N|O|1997-06-29|1997-08-14|1997-07-19|COLLECT COD|AIR|iously across the silent pinto beans. furi +3041|67448|2461|3|9|12738.96|0.09|0.06|N|O|1997-08-28|1997-07-23|1997-09-16|TAKE BACK RETURN|FOB|scapades after the special +3042|104915|2446|1|30|57597.30|0.08|0.06|A|F|1995-01-12|1995-02-15|1995-01-24|DELIVER IN PERSON|SHIP|the requests detect fu +3042|101459|1460|2|28|40892.60|0.05|0.03|A|F|1994-11-24|1995-01-02|1994-12-06|TAKE BACK RETURN|MAIL|ng the furiously r +3042|13664|6166|3|34|53640.44|0.04|0.00|R|F|1994-12-11|1995-02-03|1994-12-21|TAKE BACK RETURN|TRUCK|can wake after the enticingly stealthy i +3042|47338|2347|4|19|24421.27|0.02|0.01|A|F|1995-03-05|1995-01-24|1995-03-17|COLLECT COD|TRUCK|e carefully. regul +3043|45387|396|1|23|30644.74|0.07|0.04|R|F|1992-05-08|1992-07-22|1992-05-18|COLLECT COD|TRUCK|uickly above the pending, +3043|5894|3395|2|15|26998.35|0.03|0.05|A|F|1992-05-27|1992-06-03|1992-06-09|COLLECT COD|FOB|usly furiously +3043|59231|9232|3|42|49989.66|0.10|0.07|R|F|1992-07-15|1992-06-19|1992-07-23|NONE|MAIL|ide of the un +3043|90453|454|4|5|7217.25|0.10|0.01|A|F|1992-05-22|1992-07-02|1992-06-20|TAKE BACK RETURN|TRUCK|ake blithely re +3044|100992|993|1|10|19929.90|0.07|0.08|N|O|1996-07-13|1996-05-06|1996-07-21|TAKE BACK RETURN|REG AIR| slyly ironic requests. s +3044|167015|9532|2|3|3246.03|0.06|0.02|N|O|1996-07-27|1996-05-26|1996-08-15|TAKE BACK RETURN|AIR|ecoys haggle furiously pending requests. +3044|18478|980|3|47|65634.09|0.09|0.00|N|O|1996-05-24|1996-06-22|1996-05-30|NONE|REG AIR|ly around the car +3045|87670|7671|1|41|67964.47|0.05|0.01|N|O|1995-09-30|1995-11-24|1995-10-03|TAKE BACK RETURN|MAIL|ely final foxes. carefully ironic pinto b +3045|68109|3122|2|48|51700.80|0.02|0.03|N|O|1995-10-01|1995-12-16|1995-10-10|TAKE BACK RETURN|MAIL|ole quickly outside th +3046|73235|3236|1|44|53162.12|0.03|0.03|N|O|1996-03-03|1996-02-25|1996-04-01|NONE|AIR| are quickly. blithe +3046|53645|3646|2|46|73537.44|0.03|0.08|N|O|1996-03-22|1996-02-28|1996-04-07|TAKE BACK RETURN|AIR|sits sleep furious +3046|1537|9038|3|31|44594.43|0.03|0.07|N|O|1996-03-24|1996-01-30|1996-03-26|NONE|RAIL|y pending somas alongside of the slyly iro +3047|103994|3995|1|17|33965.83|0.08|0.02|N|O|1997-06-14|1997-04-20|1997-06-23|COLLECT COD|FOB|onic instruction +3047|13957|8960|2|23|43031.85|0.00|0.04|N|O|1997-05-20|1997-06-14|1997-05-28|TAKE BACK RETURN|REG AIR| slyly ironi +3072|56531|4047|1|6|8925.18|0.09|0.05|R|F|1994-02-09|1994-03-24|1994-02-28|DELIVER IN PERSON|REG AIR|gular requests abov +3072|107152|2173|2|36|41729.40|0.07|0.02|R|F|1994-04-14|1994-04-22|1994-05-06|COLLECT COD|AIR| theodolites. blithely e +3072|96715|6716|3|7|11981.97|0.04|0.07|R|F|1994-05-09|1994-03-31|1994-05-19|COLLECT COD|TRUCK|uests. ironic, ironic depos +3072|82745|5254|4|39|67381.86|0.05|0.08|A|F|1994-05-27|1994-04-20|1994-06-14|COLLECT COD|MAIL|es; slyly spe +3072|87380|7381|5|1|1367.38|0.01|0.08|R|F|1994-02-26|1994-03-14|1994-03-19|NONE|AIR| slyly ironic attainments. car +3073|193992|9031|1|16|33375.84|0.07|0.01|R|F|1994-03-02|1994-03-23|1994-03-31|DELIVER IN PERSON|AIR|n requests. ironi +3073|21735|9242|2|47|77866.31|0.09|0.00|R|F|1994-03-26|1994-02-12|1994-04-21|NONE|REG AIR|eposits. fluffily +3073|86050|8559|3|10|10360.50|0.03|0.00|R|F|1994-02-11|1994-03-24|1994-02-26|COLLECT COD|FOB| furiously caref +3073|28574|1077|4|14|21035.98|0.09|0.07|R|F|1994-03-24|1994-04-01|1994-04-07|NONE|RAIL|ilently quiet epitaphs. +3073|40433|7946|5|25|34335.75|0.00|0.07|R|F|1994-04-14|1994-03-07|1994-04-22|NONE|TRUCK|nag asymptotes. pinto beans sleep +3073|146763|6764|6|39|70580.64|0.09|0.02|R|F|1994-05-01|1994-02-16|1994-05-12|DELIVER IN PERSON|AIR|lar excuses across the furiously even +3073|43770|3771|7|11|18851.47|0.08|0.07|A|F|1994-05-01|1994-03-06|1994-05-08|COLLECT COD|SHIP|instructions sleep according to the +3074|36636|1643|1|50|78631.50|0.08|0.08|A|F|1993-01-31|1992-12-15|1993-02-20|NONE|AIR|furiously pending requests haggle s +3074|138309|5849|2|39|52544.70|0.03|0.00|R|F|1992-12-08|1993-01-28|1992-12-09|DELIVER IN PERSON|TRUCK|iously throu +3075|8905|6406|1|39|70742.10|0.02|0.03|A|F|1994-06-10|1994-06-21|1994-06-20|NONE|FOB|ing deposits nag +3075|51164|3670|2|2|2230.32|0.07|0.08|R|F|1994-06-14|1994-06-10|1994-06-25|TAKE BACK RETURN|AIR|. unusual, unusual accounts haggle furious +3076|84436|4437|1|44|62498.92|0.00|0.05|A|F|1993-09-14|1993-10-04|1993-09-17|TAKE BACK RETURN|FOB| instructions h +3076|105266|287|2|22|27967.72|0.08|0.00|A|F|1993-09-05|1993-09-10|1993-09-27|NONE|REG AIR|packages wake furiou +3076|4172|6673|3|31|33361.27|0.06|0.06|A|F|1993-08-10|1993-09-17|1993-08-17|TAKE BACK RETURN|SHIP|regular depos +3077|71785|4293|1|25|43919.50|0.06|0.01|N|O|1997-09-14|1997-10-16|1997-10-06|NONE|TRUCK|lent account +3077|90110|2620|2|40|44004.40|0.05|0.06|N|O|1997-10-22|1997-09-19|1997-11-19|DELIVER IN PERSON|AIR|to the enticing packag +3077|77820|2835|3|13|23371.66|0.03|0.07|N|O|1997-09-09|1997-10-15|1997-09-19|NONE|TRUCK|luffily close depende +3077|114603|2137|4|23|37204.80|0.03|0.02|N|O|1997-11-05|1997-09-16|1997-11-20|NONE|MAIL|lly. fluffily pending dinos across +3078|131450|1451|1|25|37036.25|0.01|0.03|A|F|1993-04-22|1993-05-01|1993-04-28|TAKE BACK RETURN|AIR|express dinos. carefully ironic +3078|77158|9666|2|21|23838.15|0.09|0.07|A|F|1993-03-20|1993-03-21|1993-04-01|COLLECT COD|AIR|e fluffily. +3079|69026|6545|1|20|19900.40|0.05|0.00|N|O|1997-10-18|1997-10-26|1997-11-14|NONE|RAIL|ets are according to the quickly dari +3079|116489|9001|2|38|57208.24|0.08|0.07|N|O|1997-11-07|1997-11-25|1997-12-06|NONE|RAIL|e carefully regular realms +3079|16662|6663|3|40|63146.40|0.02|0.08|N|O|1997-09-26|1997-12-11|1997-10-09|NONE|RAIL|ide of the pending, special deposi +3079|23216|3217|4|2|2278.42|0.00|0.08|N|O|1998-01-05|1997-11-17|1998-01-28|NONE|FOB|ly busy requests believ +3079|187516|35|5|2|3207.02|0.10|0.00|N|O|1997-12-27|1997-10-25|1998-01-08|COLLECT COD|SHIP|y regular asymptotes doz +3079|165391|2940|6|46|66993.94|0.00|0.00|N|O|1997-11-19|1997-11-04|1997-11-25|DELIVER IN PERSON|REG AIR|es. final, regula +3104|50589|5600|1|20|30791.60|0.01|0.08|A|F|1993-12-31|1993-11-24|1994-01-12|DELIVER IN PERSON|REG AIR|s are. furiously s +3104|47520|2529|2|47|68973.44|0.02|0.05|A|F|1993-12-25|1993-11-02|1994-01-12|COLLECT COD|RAIL|ily daring acc +3104|62977|2978|3|11|21339.67|0.02|0.03|A|F|1993-10-05|1993-11-30|1993-10-27|NONE|TRUCK| special deposits u +3104|37868|7869|4|26|46952.36|0.02|0.08|R|F|1994-01-02|1993-12-05|1994-01-31|TAKE BACK RETURN|TRUCK|es boost carefully. slyly +3105|183486|8523|1|11|17264.28|0.01|0.06|N|O|1997-02-07|1997-02-09|1997-03-01|NONE|FOB|kly bold depths caj +3105|44436|4437|2|9|12423.87|0.08|0.08|N|O|1996-12-25|1997-02-04|1997-01-09|COLLECT COD|SHIP|es wake among t +3105|24472|9477|3|48|67030.56|0.02|0.05|N|O|1997-02-28|1997-01-31|1997-03-18|DELIVER IN PERSON|REG AIR|ending platelets wake carefully ironic inst +3105|90456|7984|4|23|33268.35|0.04|0.07|N|O|1997-03-08|1996-12-14|1997-03-18|COLLECT COD|REG AIR| detect slyly. blithely unusual requests ar +3105|89347|4364|5|8|10690.72|0.07|0.07|N|O|1996-12-28|1996-12-28|1997-01-25|NONE|FOB|s. blithely unusual ideas was after +3105|46261|3774|6|30|36217.80|0.08|0.05|N|O|1997-03-03|1997-02-03|1997-03-05|NONE|FOB|ess accounts boost among t +3106|85699|8208|1|22|37063.18|0.03|0.02|N|O|1997-02-28|1997-02-12|1997-03-03|DELIVER IN PERSON|FOB|structions atop the blithely +3106|135816|3356|2|49|90738.69|0.06|0.06|N|O|1997-02-27|1997-03-11|1997-03-12|NONE|TRUCK|lets. quietly regular courts +3106|51764|6775|3|42|72061.92|0.09|0.07|N|O|1997-04-05|1997-03-17|1997-04-22|COLLECT COD|REG AIR|nstructions wake. furiously +3106|195649|3207|4|6|10467.84|0.10|0.07|N|O|1997-02-02|1997-04-11|1997-02-27|COLLECT COD|REG AIR|symptotes. slyly bold platelets cajol +3106|64580|9593|5|16|24713.28|0.09|0.08|N|O|1997-02-25|1997-04-10|1997-03-16|NONE|AIR|sits wake slyl +3107|148150|665|1|16|19170.40|0.05|0.04|N|O|1997-08-30|1997-10-20|1997-09-20|TAKE BACK RETURN|REG AIR|regular pinto beans. ironic ideas haggle +3107|141690|1691|2|35|60609.15|0.05|0.06|N|O|1997-08-27|1997-11-19|1997-09-14|COLLECT COD|TRUCK|ets doubt furiously final ideas. final +3107|169733|2250|3|23|41462.79|0.03|0.06|N|O|1997-12-10|1997-11-11|1997-12-14|TAKE BACK RETURN|SHIP|atelets must ha +3107|86080|8589|4|27|28784.16|0.00|0.08|N|O|1997-11-15|1997-10-31|1997-11-28|DELIVER IN PERSON|FOB|furiously final +3108|108989|1500|1|37|73925.26|0.06|0.04|A|F|1993-10-16|1993-10-01|1993-11-09|DELIVER IN PERSON|RAIL| final requests. +3108|165850|3399|2|26|49812.10|0.08|0.05|A|F|1993-11-12|1993-10-05|1993-12-09|COLLECT COD|TRUCK| slyly slow foxes wake furious +3109|17514|16|1|32|45808.32|0.08|0.03|A|F|1993-09-05|1993-10-06|1993-09-18|DELIVER IN PERSON|FOB|ecial orbits are furiou +3109|144736|2279|2|49|87255.77|0.08|0.06|R|F|1993-10-24|1993-09-30|1993-11-21|TAKE BACK RETURN|AIR| even pearls. furiously pending +3109|175265|2817|3|43|57631.18|0.04|0.07|R|F|1993-09-29|1993-09-06|1993-10-13|COLLECT COD|MAIL|ding to the foxes. +3109|78107|8108|4|26|28212.60|0.01|0.05|R|F|1993-11-16|1993-10-18|1993-12-06|TAKE BACK RETURN|TRUCK| sleep slyly according to t +3109|142097|9640|5|50|56954.50|0.01|0.08|A|F|1993-09-17|1993-10-16|1993-10-11|NONE|FOB| regular packages boost blithely even, re +3109|14933|7435|6|10|18479.30|0.10|0.04|A|F|1993-10-26|1993-10-03|1993-11-09|NONE|TRUCK|sits haggle carefully. regular, unusual ac +3110|88455|3472|1|1|1443.45|0.02|0.07|A|F|1995-01-15|1995-01-20|1995-01-30|DELIVER IN PERSON|REG AIR|c theodolites a +3110|56453|1464|2|31|43692.95|0.01|0.06|R|F|1995-03-31|1995-03-07|1995-04-21|TAKE BACK RETURN|REG AIR|en deposits. ironic +3110|2097|9598|3|34|33969.06|0.02|0.02|A|F|1995-02-23|1995-01-27|1995-03-09|TAKE BACK RETURN|FOB|ly pending requests ha +3110|39004|9005|4|16|15088.00|0.04|0.04|A|F|1995-01-10|1995-02-06|1995-01-26|NONE|MAIL|across the regular acco +3110|139664|7204|5|39|66442.74|0.09|0.01|A|F|1995-02-09|1995-01-21|1995-02-21|NONE|MAIL|side of the blithely unusual courts. slyly +3111|136959|1986|1|22|43910.90|0.06|0.05|N|O|1995-09-21|1995-11-09|1995-10-17|COLLECT COD|REG AIR|quests. regular dolphins against the +3111|57194|4710|2|30|34535.70|0.06|0.05|N|O|1995-10-05|1995-11-15|1995-11-01|TAKE BACK RETURN|TRUCK|eas are furiously slyly special deposits. +3111|51332|1333|3|10|12833.30|0.02|0.02|N|O|1995-11-10|1995-11-02|1995-12-04|NONE|FOB|ng the slyly ironic inst +3111|131080|6107|4|31|34443.48|0.00|0.08|N|O|1995-10-26|1995-09-26|1995-11-02|TAKE BACK RETURN|MAIL|kages detect express attainments +3111|53483|999|5|14|20110.72|0.05|0.04|N|O|1995-10-17|1995-10-19|1995-10-19|TAKE BACK RETURN|SHIP|re. pinto +3111|85509|8018|6|5|7472.50|0.03|0.08|N|O|1995-08-30|1995-10-16|1995-09-04|DELIVER IN PERSON|TRUCK|. carefully even ideas +3111|147305|7306|7|41|55444.30|0.09|0.05|N|O|1995-11-22|1995-11-01|1995-12-01|TAKE BACK RETURN|FOB|fily slow ideas. +3136|141341|6370|1|30|41470.20|0.02|0.08|R|F|1994-08-13|1994-10-02|1994-09-02|TAKE BACK RETURN|RAIL|leep blithel +3136|102634|2635|2|7|11456.41|0.05|0.07|A|F|1994-10-08|1994-09-14|1994-10-11|TAKE BACK RETURN|SHIP|ic pinto beans are slyly. f +3136|157204|2235|3|43|54231.60|0.00|0.07|A|F|1994-09-05|1994-09-25|1994-09-11|NONE|RAIL|. special theodolites ha +3136|115183|2717|4|26|31152.68|0.04|0.05|A|F|1994-10-13|1994-11-07|1994-11-05|TAKE BACK RETURN|AIR|eep fluffily. daringly silent attainments d +3136|66751|6752|5|2|3435.50|0.08|0.07|R|F|1994-11-21|1994-11-03|1994-11-26|DELIVER IN PERSON|TRUCK|? special, silent +3136|79827|9828|6|29|52397.78|0.08|0.07|A|F|1994-11-16|1994-10-03|1994-12-14|NONE|FOB|latelets. final +3137|2357|2358|1|6|7556.10|0.02|0.02|N|O|1995-09-19|1995-10-23|1995-10-16|NONE|SHIP|ly express as +3137|5178|2679|2|4|4332.68|0.06|0.04|N|O|1995-10-01|1995-09-11|1995-10-30|COLLECT COD|RAIL|posits wake. silent excuses boost about +3138|92417|4927|1|7|9865.87|0.05|0.05|R|F|1994-03-04|1994-03-14|1994-03-20|NONE|AIR|lithely quickly even packages. packages +3138|43554|3555|2|27|40433.85|0.09|0.01|R|F|1994-03-24|1994-03-23|1994-04-18|DELIVER IN PERSON|FOB|counts cajole fluffily carefully special i +3138|196512|6513|3|32|51472.32|0.00|0.01|R|F|1994-02-24|1994-05-07|1994-02-28|TAKE BACK RETURN|MAIL|inal foxes affix slyly. fluffily regul +3138|171358|1359|4|38|54315.30|0.07|0.04|R|F|1994-02-21|1994-03-21|1994-03-13|COLLECT COD|FOB|lithely fluffily un +3138|9594|9595|5|12|18043.08|0.09|0.02|A|F|1994-03-04|1994-04-11|1994-03-21|COLLECT COD|FOB|. bold pinto beans haggl +3138|43107|8116|6|25|26252.50|0.05|0.08|A|F|1994-05-19|1994-04-07|1994-06-17|TAKE BACK RETURN|AIR|dolites around the carefully busy the +3139|39310|1814|1|46|57468.26|0.08|0.03|R|F|1992-04-28|1992-03-04|1992-05-19|TAKE BACK RETURN|FOB|of the unusual, unusual re +3140|6539|4040|1|21|30356.13|0.08|0.02|R|F|1992-04-12|1992-05-31|1992-04-21|NONE|REG AIR| furiously sly excuses according to the +3140|88674|1183|2|10|16626.70|0.07|0.01|A|F|1992-05-30|1992-05-09|1992-06-09|COLLECT COD|RAIL|accounts. expres +3140|132668|2669|3|28|47618.48|0.06|0.00|R|F|1992-06-08|1992-07-07|1992-07-08|TAKE BACK RETURN|SHIP|lar ideas. slyly ironic d +3141|176416|1451|1|32|47757.12|0.06|0.00|N|O|1995-11-21|1995-12-18|1995-11-26|DELIVER IN PERSON|FOB|oxes are quickly about t +3141|9358|6859|2|37|46891.95|0.10|0.05|N|O|1996-01-24|1995-12-16|1996-01-27|DELIVER IN PERSON|AIR|press pinto beans. bold accounts boost b +3141|78185|5707|3|9|10468.62|0.09|0.02|N|O|1995-11-11|1995-12-10|1995-12-02|DELIVER IN PERSON|MAIL|uickly ironic, pendi +3141|45956|965|4|47|89391.65|0.03|0.01|N|O|1995-11-29|1996-01-13|1995-12-10|TAKE BACK RETURN|TRUCK| are slyly pi +3142|119225|4248|1|15|18663.30|0.03|0.08|R|F|1992-08-15|1992-08-18|1992-08-22|DELIVER IN PERSON|AIR|instructions are. ironic packages doz +3143|89831|7356|1|22|40058.26|0.02|0.00|A|F|1993-05-11|1993-03-26|1993-05-20|TAKE BACK RETURN|MAIL|l, special instructions nag +3143|182257|9812|2|40|53570.00|0.03|0.08|A|F|1993-05-07|1993-03-29|1993-05-17|COLLECT COD|FOB|sly unusual theodolites. slyly ev +3143|182464|4983|3|22|34022.12|0.05|0.03|A|F|1993-03-18|1993-05-09|1993-04-14|DELIVER IN PERSON|MAIL|beans. fluf +3143|65651|5652|4|46|74365.90|0.05|0.08|R|F|1993-04-19|1993-03-21|1993-05-05|COLLECT COD|REG AIR|low forges haggle. even packages use bli +3168|59901|2407|1|46|85601.40|0.08|0.08|R|F|1992-02-14|1992-03-02|1992-03-02|TAKE BACK RETURN|SHIP|y across the express accounts. fluff +3168|153658|3659|2|1|1711.65|0.06|0.08|A|F|1992-05-27|1992-03-12|1992-06-09|TAKE BACK RETURN|SHIP|pinto beans. slyly regular courts haggle +3168|127053|9566|3|13|14040.65|0.09|0.02|A|F|1992-03-05|1992-04-29|1992-03-15|NONE|SHIP|ironic somas haggle quick +3168|164440|1989|4|11|16548.84|0.02|0.05|R|F|1992-04-12|1992-03-17|1992-05-12|COLLECT COD|SHIP|ously furious dependenc +3169|191052|3572|1|12|13716.60|0.01|0.04|R|F|1994-01-05|1994-03-18|1994-01-21|COLLECT COD|REG AIR| regular d +3169|199869|4908|2|17|33470.62|0.05|0.04|R|F|1994-03-02|1994-01-21|1994-03-03|DELIVER IN PERSON|TRUCK|usly regular packages. ironi +3169|187322|7323|3|12|16911.84|0.08|0.07|A|F|1994-04-18|1994-03-12|1994-05-08|TAKE BACK RETURN|FOB|atelets. pac +3169|104999|5000|4|26|52103.74|0.10|0.04|R|F|1994-04-08|1994-03-21|1994-04-29|NONE|TRUCK|ter the regular ideas. slyly iro +3169|107704|7705|5|6|10270.20|0.09|0.01|A|F|1994-03-24|1994-02-22|1994-04-04|TAKE BACK RETURN|AIR|ular instructions. ca +3169|176053|6054|6|46|51936.30|0.02|0.07|A|F|1994-02-01|1994-01-22|1994-02-24|DELIVER IN PERSON|RAIL|thely bold theodolites are fl +3170|39883|7393|1|12|21874.56|0.03|0.03|N|O|1998-02-12|1998-01-17|1998-02-24|NONE|TRUCK|ing accounts along the speci +3170|99060|1570|2|21|22240.26|0.01|0.00|N|O|1997-12-09|1998-01-31|1997-12-21|DELIVER IN PERSON|MAIL|o beans. carefully final requests dou +3170|88383|3400|3|27|37027.26|0.00|0.05|N|O|1998-02-25|1998-01-29|1998-02-27|COLLECT COD|AIR|efully bold foxes. regular, ev +3170|40846|847|4|34|60752.56|0.05|0.04|N|O|1998-02-01|1998-01-11|1998-02-20|TAKE BACK RETURN|TRUCK|s about the fluffily final de +3170|89767|9768|5|32|56216.32|0.02|0.04|N|O|1997-11-24|1997-12-12|1997-12-15|COLLECT COD|SHIP|ggle about the furiously r +3170|109150|4171|6|43|49843.45|0.08|0.05|N|O|1998-01-05|1998-01-04|1998-01-14|NONE|REG AIR|. express dolphins use sly +3170|83873|3874|7|26|48278.62|0.10|0.05|N|O|1998-02-12|1997-12-22|1998-02-28|COLLECT COD|TRUCK|s engage furiously. +3171|46382|8887|1|34|45164.92|0.04|0.00|A|F|1993-05-30|1993-05-27|1993-06-06|DELIVER IN PERSON|REG AIR|r the final, even packages. quickly +3171|138340|8341|2|50|68917.00|0.01|0.04|A|F|1993-07-19|1993-05-15|1993-07-31|TAKE BACK RETURN|REG AIR|riously final foxes about the ca +3172|95767|786|1|4|7051.04|0.06|0.07|A|F|1992-09-26|1992-08-15|1992-10-20|DELIVER IN PERSON|TRUCK|s are slyly thin package +3172|147816|5359|2|43|80143.83|0.05|0.07|R|F|1992-08-22|1992-07-07|1992-08-26|COLLECT COD|MAIL| final packages. +3172|131989|7016|3|13|26272.74|0.03|0.01|R|F|1992-07-06|1992-08-06|1992-08-05|DELIVER IN PERSON|MAIL|inal deposits haggle along the +3172|134555|9582|4|28|44507.40|0.08|0.04|R|F|1992-07-09|1992-07-14|1992-07-16|NONE|MAIL|regular ideas. packages are furi +3172|63775|3776|5|31|53901.87|0.05|0.08|A|F|1992-09-01|1992-08-27|1992-09-23|NONE|SHIP|. slyly regular dependencies haggle quiet +3173|194121|4122|1|35|42529.20|0.01|0.08|N|O|1996-09-09|1996-10-15|1996-10-04|TAKE BACK RETURN|RAIL| across the slyly even requests. +3173|177060|2095|2|5|5685.30|0.09|0.07|N|O|1996-12-06|1996-09-17|1996-12-07|DELIVER IN PERSON|REG AIR|express depo +3173|45832|841|3|16|28445.28|0.06|0.01|N|O|1996-08-12|1996-09-21|1996-08-22|NONE|SHIP|e special, +3173|93949|3950|4|2|3885.88|0.00|0.00|N|O|1996-10-15|1996-11-06|1996-10-18|COLLECT COD|MAIL|ular pearls +3173|184484|4485|5|2|3136.96|0.00|0.06|N|O|1996-08-18|1996-09-21|1996-09-07|DELIVER IN PERSON|MAIL|fluffily above t +3174|185221|7740|1|6|7837.32|0.04|0.08|N|O|1996-03-13|1996-02-09|1996-03-22|DELIVER IN PERSON|AIR| furiously ironic +3174|193509|8548|2|4|6410.00|0.01|0.05|N|O|1995-11-17|1996-01-08|1995-11-27|DELIVER IN PERSON|RAIL|deas sleep thi +3174|91355|3865|3|21|28273.35|0.08|0.05|N|O|1996-02-20|1995-12-28|1996-03-17|NONE|MAIL|iously. idly bold theodolites a +3174|191449|9007|4|13|20025.72|0.08|0.06|N|O|1996-01-11|1996-01-26|1996-02-01|DELIVER IN PERSON|SHIP|leep quickly? slyly special platelets +3174|71002|3510|5|39|37947.00|0.02|0.06|N|O|1995-12-02|1996-02-08|1995-12-12|TAKE BACK RETURN|TRUCK| wake slyly foxes. bold requests p +3174|119325|4348|6|8|10754.56|0.07|0.08|N|O|1995-12-07|1996-01-08|1995-12-29|DELIVER IN PERSON|TRUCK|nic deposits among t +3175|119225|6759|1|28|34838.16|0.10|0.01|R|F|1994-09-27|1994-10-05|1994-10-04|NONE|FOB|ore the even, silent foxes. b +3175|532|3033|2|38|54436.14|0.01|0.07|R|F|1994-10-10|1994-08-25|1994-10-28|NONE|MAIL|the quickly even dolph +3175|128833|1346|3|12|22341.96|0.09|0.07|R|F|1994-10-16|1994-09-15|1994-10-18|NONE|AIR|ter the pending deposits. slyly e +3175|84978|2503|4|14|27481.58|0.02|0.05|R|F|1994-10-21|1994-09-05|1994-11-15|NONE|MAIL|nt dependencies are quietly even +3175|17028|4532|5|47|44415.94|0.08|0.03|R|F|1994-08-08|1994-09-10|1994-08-21|COLLECT COD|REG AIR| final requests x-r +3175|174487|4488|6|44|68705.12|0.01|0.00|R|F|1994-09-26|1994-08-30|1994-10-24|TAKE BACK RETURN|MAIL|are carefully furiously ironic accounts. e +3175|864|3365|7|32|56475.52|0.01|0.02|R|F|1994-09-29|1994-09-20|1994-10-10|TAKE BACK RETURN|SHIP|lites sleep +3200|115903|3437|1|17|32621.30|0.10|0.00|N|O|1996-06-06|1996-04-21|1996-06-14|DELIVER IN PERSON|AIR|side of the furiously pendin +3200|165487|3036|2|27|41916.96|0.03|0.00|N|O|1996-05-07|1996-05-01|1996-05-09|TAKE BACK RETURN|REG AIR|as haggle furiously against the fluff +3200|130983|6010|3|36|72503.28|0.01|0.01|N|O|1996-03-22|1996-03-19|1996-03-30|DELIVER IN PERSON|FOB|f the carefu +3200|29905|4910|4|11|20183.90|0.10|0.02|N|O|1996-03-18|1996-03-21|1996-04-14|COLLECT COD|RAIL|osits sleep fur +3200|197667|7668|5|16|28234.56|0.05|0.00|N|O|1996-02-28|1996-03-13|1996-03-11|NONE|RAIL|ly against the quiet packages. blith +3200|174336|1888|6|25|35258.25|0.10|0.01|N|O|1996-02-08|1996-04-11|1996-03-06|COLLECT COD|FOB| slyly regular hockey players! pinto beans +3201|45786|5787|1|11|19049.58|0.10|0.06|A|F|1993-09-27|1993-08-29|1993-10-18|NONE|TRUCK|ing to the furiously expr +3201|117792|2815|2|27|48864.33|0.08|0.02|R|F|1993-08-31|1993-08-24|1993-09-08|TAKE BACK RETURN|FOB|deposits are slyly along +3201|118958|3981|3|50|98847.50|0.00|0.08|R|F|1993-10-27|1993-09-30|1993-11-16|COLLECT COD|TRUCK| deposits. express, ir +3202|182676|7713|1|30|52760.10|0.09|0.02|A|F|1993-03-18|1993-03-10|1993-03-23|COLLECT COD|SHIP|ven platelets. furiously final +3202|19748|2250|2|22|36690.28|0.01|0.02|R|F|1993-02-16|1993-02-16|1993-03-16|TAKE BACK RETURN|MAIL|the express packages. fu +3203|143488|3489|1|23|35224.04|0.01|0.07|N|O|1998-01-04|1998-01-12|1998-01-24|COLLECT COD|SHIP|uses. fluffily ironic pinto bea +3203|187707|2744|2|22|39483.40|0.03|0.03|N|O|1998-02-12|1998-01-01|1998-02-18|TAKE BACK RETURN|REG AIR|e the blithely regular accounts boost f +3204|11924|9428|1|10|18359.20|0.10|0.07|R|F|1993-01-27|1993-03-08|1993-01-29|COLLECT COD|SHIP|counts. bold +3204|6474|8975|2|39|53838.33|0.10|0.03|R|F|1993-02-11|1993-03-19|1993-02-28|TAKE BACK RETURN|MAIL|sits sleep theodolites. slyly bo +3205|67629|2642|1|7|11176.34|0.09|0.00|R|F|1992-07-05|1992-06-17|1992-07-07|NONE|SHIP|ly alongsi +3205|28792|8793|2|32|55065.28|0.08|0.03|A|F|1992-06-01|1992-07-10|1992-06-06|TAKE BACK RETURN|RAIL|lar accoun +3205|102663|5174|3|38|63295.08|0.10|0.08|A|F|1992-07-31|1992-06-03|1992-08-20|DELIVER IN PERSON|AIR|usly quiet accounts. slyly pending pinto +3205|55351|5352|4|10|13063.50|0.01|0.07|A|F|1992-06-18|1992-07-04|1992-07-16|COLLECT COD|RAIL| deposits cajole careful +3205|69090|1597|5|18|19063.62|0.03|0.03|A|F|1992-07-04|1992-06-14|1992-08-03|TAKE BACK RETURN|RAIL|symptotes. slyly even deposits ar +3205|194388|9427|6|19|28165.22|0.07|0.08|R|F|1992-05-28|1992-05-30|1992-06-05|COLLECT COD|AIR|yly pending packages snooz +3205|68994|1501|7|36|70667.64|0.06|0.03|A|F|1992-05-31|1992-06-19|1992-06-03|TAKE BACK RETURN|SHIP|s. ironic platelets above the s +3206|175184|2736|1|1|1259.18|0.07|0.05|N|O|1996-11-22|1996-10-16|1996-12-07|TAKE BACK RETURN|FOB|y unusual foxes cajole ab +3206|110775|3287|2|37|66073.49|0.07|0.01|N|O|1996-09-06|1996-10-31|1996-09-25|COLLECT COD|SHIP| quick theodolites hagg +3206|185591|5592|3|24|40238.16|0.00|0.08|N|O|1996-08-25|1996-10-01|1996-09-04|COLLECT COD|TRUCK|encies sleep deposits-- +3207|112470|4|1|2|2964.94|0.10|0.03|N|O|1998-06-15|1998-04-20|1998-06-21|COLLECT COD|MAIL|among the ironic, even packages +3207|70504|8026|2|42|61929.00|0.00|0.00|N|O|1998-05-02|1998-05-10|1998-06-01|NONE|SHIP|to the quickly special accounts? ironically +3207|151474|6505|3|17|25932.99|0.03|0.04|N|O|1998-03-27|1998-04-06|1998-03-28|COLLECT COD|RAIL|eep against the instructions. gifts hag +3207|18890|3893|4|32|57884.48|0.00|0.03|N|O|1998-06-17|1998-04-26|1998-07-07|TAKE BACK RETURN|SHIP|y across the slyly express foxes. bl +3207|82724|5233|5|8|13653.76|0.00|0.06|N|O|1998-06-13|1998-04-26|1998-07-11|COLLECT COD|SHIP|y. final pint +3207|133661|8688|6|32|54229.12|0.03|0.05|N|O|1998-04-19|1998-05-01|1998-05-08|COLLECT COD|FOB|l deposits wake beyond the carefully +3232|13217|3218|1|22|24864.62|0.10|0.01|A|F|1992-11-30|1992-12-09|1992-12-04|NONE|RAIL|thely. furio +3232|134360|6874|2|34|47408.24|0.07|0.04|R|F|1993-01-09|1992-11-14|1993-02-03|NONE|SHIP|old packages integrate quickly +3232|180226|7781|3|3|3918.66|0.04|0.06|R|F|1992-12-14|1992-12-11|1992-12-29|DELIVER IN PERSON|FOB|ily blithely ironic acco +3233|50584|585|1|23|35295.34|0.04|0.05|A|F|1994-12-07|1995-01-11|1994-12-26|NONE|AIR|pending instructions use after the carefu +3233|153443|989|2|6|8978.64|0.02|0.08|A|F|1994-12-06|1994-12-05|1994-12-07|TAKE BACK RETURN|REG AIR|requests are quickly above the slyly p +3233|99840|7368|3|2|3679.68|0.04|0.06|R|F|1995-01-03|1995-01-02|1995-01-21|TAKE BACK RETURN|AIR| across the bold packages +3233|8532|1033|4|25|36013.25|0.04|0.07|A|F|1994-11-24|1995-01-07|1994-12-11|NONE|RAIL|oss the pl +3234|78973|8974|1|45|87838.65|0.01|0.04|N|O|1996-05-15|1996-05-09|1996-06-02|DELIVER IN PERSON|TRUCK| express packages are carefully. f +3234|83220|745|2|23|27674.06|0.03|0.00|N|O|1996-05-29|1996-05-15|1996-06-17|DELIVER IN PERSON|AIR|d-- fluffily special packag +3234|74096|9111|3|16|17121.44|0.06|0.05|N|O|1996-06-10|1996-05-30|1996-06-18|COLLECT COD|RAIL|ithely ironic accounts wake along t +3234|121031|6056|4|50|52601.50|0.09|0.05|N|O|1996-06-11|1996-05-19|1996-06-18|NONE|MAIL|ly regular ideas according to the regula +3234|164274|9307|5|14|18735.78|0.01|0.07|N|O|1996-04-06|1996-05-30|1996-04-13|NONE|REG AIR|lithely regular f +3235|108187|698|1|9|10756.62|0.07|0.00|N|O|1995-11-17|1995-12-24|1995-11-30|COLLECT COD|AIR|l courts sleep quickly slyly +3235|94886|4887|2|43|80877.84|0.10|0.07|N|O|1995-12-25|1996-01-23|1996-01-09|COLLECT COD|MAIL|ckly final instru +3235|137620|7621|3|29|48070.98|0.06|0.06|N|O|1996-01-28|1995-12-26|1996-02-12|DELIVER IN PERSON|RAIL|e fluffy pinto bea +3235|177363|7364|4|23|33128.28|0.00|0.01|N|O|1996-02-16|1996-01-05|1996-03-07|DELIVER IN PERSON|SHIP|ldly ironic pinto beans +3236|116245|1268|1|10|12612.40|0.06|0.05|N|O|1996-11-15|1996-12-14|1996-11-29|TAKE BACK RETURN|AIR|arefully. fluffily reg +3236|121623|4136|2|21|34537.02|0.01|0.07|N|O|1996-12-23|1996-12-12|1997-01-21|NONE|AIR| final pinto +3236|117099|9611|3|7|7812.63|0.07|0.01|N|O|1996-12-27|1996-12-18|1997-01-24|DELIVER IN PERSON|SHIP|dolites. slyly unus +3237|10711|3213|1|11|17838.81|0.02|0.07|A|F|1992-08-03|1992-07-31|1992-08-13|TAKE BACK RETURN|AIR|es. permanently express platelets besid +3238|71612|1613|1|12|19003.32|0.06|0.01|R|F|1993-03-06|1993-05-08|1993-04-01|DELIVER IN PERSON|AIR|ackages affix furiously. furiously bol +3238|172398|7433|2|26|38230.14|0.01|0.06|A|F|1993-02-25|1993-04-04|1993-03-20|TAKE BACK RETURN|REG AIR|g accounts sleep furiously ironic attai +3238|80096|2605|3|1|1076.09|0.00|0.04|R|F|1993-05-17|1993-04-18|1993-05-27|NONE|SHIP|wake alongs +3239|44485|9494|1|50|71474.00|0.05|0.01|N|O|1998-02-09|1998-04-02|1998-02-22|NONE|FOB|d blithely stea +3239|44840|9849|2|43|76748.12|0.01|0.06|N|O|1998-01-15|1998-03-12|1998-01-29|COLLECT COD|REG AIR|y. bold pinto beans use +3239|12947|5449|3|13|24179.22|0.01|0.05|N|O|1998-02-10|1998-02-19|1998-02-25|DELIVER IN PERSON|MAIL|r deposits solve fluf +3239|194825|4826|4|26|49915.32|0.03|0.05|N|O|1998-01-21|1998-03-21|1998-02-08|DELIVER IN PERSON|SHIP|ngly pending platelets are fluff +3239|11739|6742|5|31|51172.63|0.10|0.08|N|O|1998-04-14|1998-03-24|1998-04-17|DELIVER IN PERSON|FOB|foxes. pendin +3264|199532|9533|1|39|63629.67|0.06|0.06|N|O|1996-11-07|1996-12-12|1996-11-20|TAKE BACK RETURN|REG AIR|sleep carefully after the slyly final +3264|130251|252|2|34|43562.50|0.00|0.01|N|O|1997-01-03|1997-01-06|1997-01-29|TAKE BACK RETURN|REG AIR|rns haggle carefully. blit +3264|124205|1742|3|11|13521.20|0.09|0.03|N|O|1996-12-11|1996-12-19|1996-12-15|DELIVER IN PERSON|SHIP|regular packages +3264|108626|8627|4|24|39230.88|0.09|0.07|N|O|1997-01-07|1996-12-13|1997-01-11|TAKE BACK RETURN|RAIL|ctions. quick +3264|62126|2127|5|6|6528.72|0.04|0.03|N|O|1996-11-10|1996-12-05|1996-11-22|TAKE BACK RETURN|SHIP|press packages. ironical +3264|140345|346|6|43|59569.62|0.06|0.06|N|O|1997-01-17|1997-01-24|1997-02-01|TAKE BACK RETURN|TRUCK|leep at the blithely bold +3265|24887|9892|1|8|14495.04|0.06|0.02|A|F|1992-09-01|1992-09-12|1992-09-27|DELIVER IN PERSON|TRUCK|thely ironic requests sleep slyly-- i +3265|71780|4288|2|7|12262.46|0.09|0.00|R|F|1992-09-16|1992-09-04|1992-10-14|DELIVER IN PERSON|MAIL|he forges. fluffily regular asym +3265|190046|5085|3|28|31809.12|0.09|0.08|A|F|1992-10-22|1992-08-23|1992-10-25|NONE|RAIL|n requests. quickly final dinos +3266|63179|8192|1|31|35407.27|0.09|0.02|N|O|1995-06-19|1995-05-04|1995-07-06|COLLECT COD|MAIL|grate among the quickly express deposits +3266|37805|309|2|43|74940.40|0.06|0.07|R|F|1995-05-04|1995-05-30|1995-05-11|COLLECT COD|AIR|ular asymptotes use careful +3267|184283|1838|1|33|45120.24|0.06|0.01|N|O|1997-03-30|1997-03-25|1997-04-23|TAKE BACK RETURN|AIR|es boost. +3268|95677|5678|1|1|1672.67|0.06|0.08|A|F|1994-09-12|1994-08-31|1994-09-16|NONE|TRUCK|. ironic, bold requests use carefull +3268|41914|4419|2|40|74236.40|0.08|0.01|R|F|1994-06-30|1994-08-22|1994-07-25|COLLECT COD|FOB|ly. bold, eve +3269|160745|3262|1|40|72229.60|0.02|0.07|N|O|1996-06-11|1996-05-06|1996-06-15|DELIVER IN PERSON|TRUCK|es. pending d +3269|37202|4712|2|46|52403.20|0.00|0.02|N|O|1996-04-21|1996-04-12|1996-05-10|DELIVER IN PERSON|MAIL|final asymptotes nag +3269|43059|572|3|39|39079.95|0.02|0.03|N|O|1996-03-13|1996-05-26|1996-03-19|COLLECT COD|MAIL|he express packages? +3269|82008|7025|4|37|36630.00|0.07|0.05|N|O|1996-06-14|1996-04-27|1996-07-07|NONE|MAIL|egular requests. carefully un +3269|92446|9974|5|42|60414.48|0.09|0.05|N|O|1996-03-19|1996-04-24|1996-04-18|COLLECT COD|TRUCK| the special packages. +3269|130091|7631|6|16|17937.44|0.01|0.08|N|O|1996-03-03|1996-04-06|1996-03-06|NONE|RAIL|s cajole. silent deposits are f +3270|34060|6564|1|11|10934.66|0.07|0.06|N|O|1997-07-29|1997-08-11|1997-08-05|TAKE BACK RETURN|AIR| solve at the regular deposits. +3270|37156|4666|2|44|48098.60|0.10|0.05|N|O|1997-07-20|1997-08-15|1997-08-04|DELIVER IN PERSON|SHIP| accounts. carefully even +3270|64294|6801|3|20|25165.80|0.01|0.02|N|O|1997-08-26|1997-07-31|1997-08-30|DELIVER IN PERSON|FOB|en accounts among the c +3270|188091|5646|4|29|34193.61|0.06|0.05|N|O|1997-07-01|1997-07-23|1997-07-10|TAKE BACK RETURN|MAIL|sly regular asymptotes. slyly dog +3270|33740|1250|5|32|53559.68|0.03|0.00|N|O|1997-09-23|1997-08-17|1997-09-27|NONE|REG AIR|promise carefully. +3270|56984|9490|6|29|56288.42|0.01|0.04|N|O|1997-08-22|1997-08-17|1997-09-06|COLLECT COD|RAIL|ptotes nag above the quickly bold deposits +3270|116753|9265|7|9|15927.75|0.06|0.08|N|O|1997-08-14|1997-08-11|1997-09-09|DELIVER IN PERSON|SHIP|ual packages +3271|56433|3949|1|30|41682.90|0.01|0.04|A|F|1992-01-16|1992-03-20|1992-01-17|DELIVER IN PERSON|AIR|r the unusual Tiresia +3271|53210|3211|2|18|20937.78|0.09|0.06|R|F|1992-05-01|1992-03-28|1992-05-29|DELIVER IN PERSON|FOB| packages eat around the furiously regul +3271|94870|4871|3|14|26108.18|0.05|0.01|A|F|1992-02-24|1992-02-14|1992-03-23|NONE|AIR|ending, even packa +3271|63369|8382|4|29|38638.44|0.07|0.04|A|F|1992-03-10|1992-02-05|1992-03-14|COLLECT COD|MAIL|lar instructions. carefully regular +3296|83475|1000|1|12|17501.64|0.06|0.07|R|F|1994-12-08|1994-12-14|1994-12-24|COLLECT COD|AIR|y about the slyly bold pinto bea +3296|148438|5981|2|31|46079.33|0.08|0.00|R|F|1995-01-26|1994-12-25|1995-02-16|NONE|REG AIR|ainst the furi +3296|184182|4183|3|29|36719.22|0.02|0.04|A|F|1995-01-12|1994-11-26|1995-02-06|DELIVER IN PERSON|SHIP|ss ideas are reg +3296|139691|4718|4|47|81342.43|0.06|0.00|A|F|1994-11-08|1994-12-20|1994-11-30|NONE|FOB|egular deposits. quic +3296|176498|1533|5|16|25191.84|0.06|0.02|R|F|1995-01-11|1994-12-27|1995-01-12|DELIVER IN PERSON|SHIP|kages cajole carefully +3296|196504|4062|6|40|64020.00|0.00|0.04|A|F|1994-12-28|1994-12-08|1995-01-13|COLLECT COD|REG AIR|ronic ideas across the +3296|35755|3265|7|6|10144.50|0.02|0.01|R|F|1995-01-03|1994-12-23|1995-01-27|TAKE BACK RETURN|AIR|carefully fur +3297|133262|5776|1|10|12952.60|0.10|0.04|A|F|1992-12-14|1993-01-21|1992-12-26|NONE|SHIP|ironic idea +3298|148414|929|1|9|13161.69|0.01|0.06|N|O|1996-08-15|1996-05-24|1996-09-12|COLLECT COD|REG AIR|ly final accou +3298|185925|5926|2|27|54294.84|0.06|0.06|N|O|1996-07-10|1996-05-21|1996-07-15|DELIVER IN PERSON|FOB|lar packages. regular deposit +3298|28881|6388|3|25|45247.00|0.10|0.08|N|O|1996-06-30|1996-05-31|1996-07-23|COLLECT COD|SHIP|ly express f +3298|190710|8268|4|1|1800.71|0.10|0.03|N|O|1996-07-31|1996-05-23|1996-08-24|TAKE BACK RETURN|FOB|refully regular requ +3299|182485|40|1|40|62699.20|0.03|0.02|A|F|1994-03-21|1994-03-23|1994-04-12|COLLECT COD|AIR|lyly even request +3300|128765|1278|1|3|5381.28|0.07|0.02|N|O|1995-11-01|1995-10-02|1995-11-20|NONE|REG AIR|g according to the dugouts. caref +3300|148043|8044|2|23|25093.92|0.02|0.02|N|O|1995-08-17|1995-09-03|1995-09-04|COLLECT COD|TRUCK|he fluffily final a +3301|168995|1512|1|45|92879.55|0.04|0.05|A|F|1994-11-19|1994-10-27|1994-11-24|TAKE BACK RETURN|FOB|nusual, final excuses after the entici +3302|35376|7880|1|45|59011.65|0.09|0.00|N|O|1996-01-24|1995-12-16|1996-02-13|COLLECT COD|FOB|counts use quickl +3303|183830|3831|1|25|47845.75|0.06|0.01|N|O|1998-03-25|1998-01-31|1998-04-12|NONE|SHIP|lly regular pi +3303|20879|880|2|15|26998.05|0.04|0.06|N|O|1998-01-29|1998-01-22|1998-02-21|COLLECT COD|SHIP| detect sly +3303|98533|8534|3|37|56666.61|0.05|0.02|N|O|1998-02-16|1998-03-07|1998-02-18|TAKE BACK RETURN|TRUCK| carefully ironic asympt +3303|35272|2782|4|26|31389.02|0.09|0.00|N|O|1998-01-18|1998-03-11|1998-02-11|DELIVER IN PERSON|REG AIR|ickly permanent requests w +3328|112585|5097|1|6|9585.48|0.03|0.08|A|F|1993-03-07|1993-01-25|1993-03-29|COLLECT COD|TRUCK|ffily even instructions detect b +3328|4400|1901|2|23|30001.20|0.01|0.06|R|F|1993-01-12|1993-02-07|1993-01-30|TAKE BACK RETURN|MAIL|y. careful +3328|138924|8925|3|44|86368.48|0.05|0.00|R|F|1992-12-03|1992-12-19|1992-12-09|TAKE BACK RETURN|FOB|dly quickly final foxes? re +3328|94005|1533|4|42|41958.00|0.01|0.05|R|F|1992-11-24|1992-12-20|1992-12-06|DELIVER IN PERSON|AIR|ronic requests +3328|130322|7862|5|25|33808.00|0.05|0.00|R|F|1993-01-28|1993-01-04|1993-01-31|NONE|RAIL|e unusual, r +3329|137884|398|1|36|69187.68|0.09|0.08|N|O|1995-08-06|1995-08-03|1995-08-14|DELIVER IN PERSON|TRUCK|ts at the re +3329|5898|3399|2|9|16235.01|0.00|0.02|N|O|1995-07-24|1995-08-02|1995-08-01|COLLECT COD|MAIL|lly final depo +3329|122108|2109|3|1|1130.10|0.04|0.08|N|O|1995-08-22|1995-09-28|1995-09-09|COLLECT COD|REG AIR|regular packages are carefull +3330|19095|4098|1|49|49690.41|0.05|0.01|R|F|1995-03-02|1995-03-03|1995-03-16|DELIVER IN PERSON|TRUCK|haggle carefully alongside of the bold r +3331|63261|780|1|9|11018.34|0.08|0.07|A|F|1993-07-18|1993-07-03|1993-08-16|TAKE BACK RETURN|AIR|odolites. bold accounts +3331|20445|446|2|38|51886.72|0.06|0.04|R|F|1993-07-24|1993-06-22|1993-08-23|NONE|AIR|ymptotes haggle across the ca +3331|2546|47|3|26|37662.04|0.09|0.05|A|F|1993-08-05|1993-07-17|1993-08-29|DELIVER IN PERSON|MAIL|p asymptotes. carefully unusual in +3332|83771|3772|1|28|49133.56|0.10|0.02|R|F|1994-12-30|1995-01-16|1995-01-16|COLLECT COD|FOB|s against the carefully special multipl +3332|135964|3504|2|21|41999.16|0.08|0.04|R|F|1995-02-04|1995-01-08|1995-02-06|COLLECT COD|MAIL| quick packages sle +3332|133508|8535|3|27|41620.50|0.03|0.02|A|F|1994-12-10|1995-01-14|1994-12-11|TAKE BACK RETURN|FOB|ording to the slyly regula +3333|149926|7469|1|27|53349.84|0.06|0.08|A|F|1992-12-06|1992-10-26|1992-12-07|COLLECT COD|SHIP|s dazzle fluffil +3333|198900|6458|2|36|71960.40|0.08|0.07|R|F|1992-11-20|1992-11-06|1992-12-16|TAKE BACK RETURN|FOB|foxes sleep neve +3333|107224|9735|3|38|46786.36|0.05|0.05|A|F|1992-10-30|1992-11-03|1992-11-04|NONE|MAIL|ccounts promise bl +3333|112230|2231|4|49|60869.27|0.07|0.07|R|F|1992-10-02|1992-11-30|1992-10-12|DELIVER IN PERSON|MAIL|riously ironic r +3333|42929|442|5|45|84236.40|0.07|0.08|A|F|1992-10-04|1992-11-08|1992-10-27|COLLECT COD|SHIP|dolites. quickly r +3334|186434|1471|1|20|30408.60|0.04|0.03|N|O|1996-05-21|1996-04-08|1996-05-26|TAKE BACK RETURN|AIR|uses nag furiously. instructions are ca +3334|189013|4050|2|7|7714.07|0.09|0.07|N|O|1996-04-28|1996-04-08|1996-05-25|NONE|SHIP|nts sublate slyly express pack +3335|104399|9420|1|13|18244.07|0.06|0.07|N|O|1996-01-20|1995-12-20|1996-02-09|COLLECT COD|REG AIR|out the special asymptotes +3335|30734|735|2|44|73248.12|0.07|0.02|N|O|1996-01-05|1995-12-25|1996-01-18|DELIVER IN PERSON|SHIP|r packages cajole ac +3335|139710|2224|3|16|27995.36|0.01|0.06|N|O|1995-10-18|1995-12-08|1995-11-03|DELIVER IN PERSON|SHIP|g packages. carefully regular reque +3335|89353|6878|4|47|63090.45|0.10|0.03|N|O|1995-12-02|1995-11-19|1995-12-27|NONE|MAIL| quickly special ideas. +3360|173707|6225|1|31|55201.70|0.08|0.04|N|O|1998-04-24|1998-04-12|1998-05-23|COLLECT COD|REG AIR|quests. carefully even deposits wake acros +3360|90182|2692|2|29|33993.22|0.00|0.06|N|O|1998-04-15|1998-02-25|1998-05-13|TAKE BACK RETURN|FOB|press asymptotes. furiously final +3360|81355|1356|3|39|52117.65|0.08|0.03|N|O|1998-04-09|1998-04-20|1998-05-05|DELIVER IN PERSON|REG AIR|s. blithely express pinto bean +3360|116741|4275|4|29|50974.46|0.10|0.01|N|O|1998-05-19|1998-03-03|1998-06-09|TAKE BACK RETURN|FOB|hely gifts. spe +3360|57076|9582|5|4|4132.28|0.08|0.07|N|O|1998-02-27|1998-03-23|1998-03-28|COLLECT COD|SHIP|ly busy inst +3360|70055|2563|6|42|43052.10|0.04|0.01|N|O|1998-05-07|1998-04-18|1998-06-04|DELIVER IN PERSON|FOB|ages cajole. pending, +3361|143748|3749|1|6|10750.44|0.02|0.02|R|F|1992-10-02|1992-10-25|1992-10-05|DELIVER IN PERSON|FOB| packages sleep. furiously unus +3361|170012|5047|2|33|35706.33|0.01|0.02|R|F|1992-11-09|1992-10-15|1992-11-11|TAKE BACK RETURN|MAIL|uriously ironic accounts. ironic, ir +3361|190085|7643|3|31|36427.48|0.06|0.04|R|F|1992-08-29|1992-10-13|1992-09-08|NONE|FOB|ts. pending, regular accounts sleep fur +3362|21372|8879|1|14|18107.18|0.06|0.05|N|O|1995-08-01|1995-09-06|1995-08-22|NONE|FOB|even Tires +3362|194902|4903|2|41|81872.90|0.05|0.03|N|O|1995-10-31|1995-09-04|1995-11-17|COLLECT COD|REG AIR|ake alongside of the +3362|114822|7334|3|40|73472.80|0.05|0.06|N|O|1995-08-19|1995-10-17|1995-09-05|TAKE BACK RETURN|FOB|packages haggle furi +3362|1127|6128|4|3|3084.36|0.03|0.01|N|O|1995-08-26|1995-09-02|1995-09-17|NONE|SHIP|its cajole blithely excuses. de +3362|137109|7110|5|36|41259.60|0.06|0.00|N|O|1995-10-05|1995-08-28|1995-11-03|TAKE BACK RETURN|RAIL|es against the quickly permanent pint +3362|187847|7848|6|46|89002.64|0.09|0.05|N|O|1995-08-02|1995-10-12|1995-08-28|COLLECT COD|REG AIR|ly bold packages. regular deposits cajol +3363|9770|2271|1|42|70550.34|0.00|0.08|N|O|1995-11-09|1995-11-25|1995-11-15|TAKE BACK RETURN|RAIL| blithely final ideas nag after +3363|190181|5220|2|21|26694.78|0.08|0.08|N|O|1995-12-10|1995-10-28|1995-12-28|COLLECT COD|RAIL|he regular, brave deposits. f +3363|158620|1136|3|2|3357.24|0.01|0.07|N|O|1996-01-22|1995-12-01|1996-02-18|TAKE BACK RETURN|SHIP|uickly bold ide +3363|112620|154|4|20|32652.40|0.07|0.06|N|O|1995-12-11|1995-11-15|1995-12-21|COLLECT COD|MAIL|carefully quiet excuses wake. sl +3363|199176|6734|5|4|5100.68|0.00|0.08|N|O|1995-10-30|1995-11-17|1995-11-22|COLLECT COD|FOB| ironic dependencie +3364|89208|6733|1|49|58662.80|0.03|0.05|N|O|1997-09-17|1997-08-23|1997-10-06|NONE|SHIP|d accounts? caref +3364|110107|108|2|38|42449.80|0.02|0.02|N|O|1997-08-30|1997-09-12|1997-09-27|COLLECT COD|REG AIR| slyly express +3364|155969|8485|3|10|20249.60|0.00|0.01|N|O|1997-08-10|1997-08-24|1997-08-15|TAKE BACK RETURN|SHIP|g the accounts. final, busy accounts wi +3364|159356|4387|4|7|9907.45|0.10|0.05|N|O|1997-07-09|1997-08-01|1997-07-16|NONE|TRUCK|furiously regular ideas haggle furiously b +3364|80467|5484|5|3|4342.38|0.01|0.00|N|O|1997-10-19|1997-08-15|1997-10-28|TAKE BACK RETURN|TRUCK|c theodolites. blithely ir +3365|150138|5169|1|37|43960.81|0.02|0.08|R|F|1994-12-22|1995-02-07|1995-01-20|TAKE BACK RETURN|SHIP|requests. quickly pending instructions a +3365|166378|3927|2|37|53441.69|0.07|0.08|A|F|1994-11-24|1995-01-09|1994-11-27|NONE|REG AIR|oze blithely. furiously ironic theodolit +3365|114118|4119|3|13|14717.43|0.09|0.02|R|F|1995-02-25|1995-01-31|1995-03-16|NONE|RAIL|pths wake r +3365|175036|2588|4|49|54440.47|0.02|0.07|R|F|1995-01-03|1995-01-01|1995-01-18|COLLECT COD|MAIL|lyly unusual asymptotes. final +3365|15264|267|5|2|2358.52|0.00|0.03|R|F|1995-02-04|1994-12-30|1995-03-06|TAKE BACK RETURN|FOB|es cajole fluffily pe +3365|125386|411|6|24|33873.12|0.01|0.00|R|F|1995-02-27|1995-01-09|1995-03-27|DELIVER IN PERSON|REG AIR|into beans? carefully regula +3366|39754|9755|1|4|6775.00|0.07|0.01|N|O|1997-05-20|1997-06-25|1997-06-03|DELIVER IN PERSON|AIR| carefully about +3366|135173|7687|2|9|10873.53|0.00|0.08|N|O|1997-06-02|1997-07-05|1997-06-26|COLLECT COD|REG AIR|ackages sleep carefully across the bli +3367|40397|7910|1|27|36109.53|0.01|0.03|A|F|1993-04-13|1993-03-16|1993-04-26|NONE|RAIL|kly even instructions caj +3367|140913|8456|2|34|66432.94|0.04|0.08|A|F|1993-03-30|1993-02-23|1993-04-11|COLLECT COD|MAIL| accounts wake slyly +3367|119437|4460|3|38|55344.34|0.03|0.03|R|F|1993-03-13|1993-02-12|1993-03-31|NONE|RAIL|even packages sleep blithely slyly expr +3392|170472|5507|1|40|61698.80|0.01|0.01|N|O|1996-02-18|1995-12-16|1996-02-26|COLLECT COD|MAIL|ress instructions affix carefully. fur +3392|122112|7137|2|13|14743.43|0.09|0.02|N|O|1995-11-26|1996-01-17|1995-12-01|NONE|MAIL|across the fluffily bold deposits. +3392|126515|4052|3|34|52411.34|0.10|0.08|N|O|1996-01-20|1996-01-21|1996-01-24|DELIVER IN PERSON|MAIL|e carefully even braids. +3392|123260|8285|4|7|8982.82|0.08|0.05|N|O|1995-12-07|1996-01-09|1995-12-29|TAKE BACK RETURN|RAIL|as. express, final accounts dou +3393|116495|4029|1|16|24183.84|0.01|0.00|N|O|1995-07-17|1995-08-19|1995-08-04|COLLECT COD|TRUCK|uses. instructions after the blithely +3393|124847|9872|2|44|82360.96|0.08|0.04|N|O|1995-10-16|1995-08-05|1995-11-01|NONE|AIR|ld requests hag +3393|96369|3897|3|25|34134.00|0.07|0.02|N|O|1995-10-17|1995-08-12|1995-11-11|DELIVER IN PERSON|MAIL|ng excuses +3393|71005|3513|4|48|46848.00|0.06|0.06|N|O|1995-07-12|1995-09-15|1995-08-02|NONE|FOB| blithely final reques +3393|177894|2929|5|37|72959.93|0.07|0.02|N|O|1995-10-16|1995-08-19|1995-10-19|COLLECT COD|AIR|ss the slyly ironic pinto beans. ironic, +3393|61866|9385|6|17|31073.62|0.04|0.01|N|O|1995-08-15|1995-09-07|1995-09-10|COLLECT COD|MAIL|kly ironic deposits could +3394|154659|4660|1|33|56550.45|0.07|0.08|N|O|1996-08-07|1996-07-17|1996-09-02|TAKE BACK RETURN|SHIP|ideas alongside of th +3394|145731|8246|2|43|76399.39|0.08|0.03|N|O|1996-08-23|1996-07-20|1996-08-25|COLLECT COD|RAIL|hockey players. slyly regular requests afte +3394|87945|454|3|26|50256.44|0.01|0.00|N|O|1996-08-08|1996-06-12|1996-09-05|TAKE BACK RETURN|RAIL|its use furiously. even, even account +3394|80118|119|4|14|15373.54|0.08|0.00|N|O|1996-06-02|1996-07-02|1996-06-19|COLLECT COD|MAIL|e furiously final theodolites. furio +3394|126483|6484|5|30|45284.40|0.04|0.06|N|O|1996-05-12|1996-07-24|1996-05-19|COLLECT COD|REG AIR|t ideas according to the fluffily iro +3394|183447|8484|6|14|21426.16|0.05|0.05|N|O|1996-06-18|1996-06-24|1996-07-17|NONE|REG AIR|arefully regular do +3395|141634|1635|1|21|35188.23|0.03|0.06|R|F|1994-12-19|1995-01-13|1994-12-25|TAKE BACK RETURN|SHIP| careful dep +3395|35345|2855|2|38|48652.92|0.01|0.07|R|F|1995-01-13|1995-01-13|1995-01-25|COLLECT COD|SHIP| silent accounts are blithely +3395|42169|2170|3|43|47779.88|0.06|0.07|A|F|1994-12-13|1995-01-07|1994-12-14|COLLECT COD|AIR|ckages above the furiously regu +3395|121513|6538|4|39|59845.89|0.05|0.07|R|F|1994-12-03|1995-01-17|1994-12-10|NONE|AIR|riously unusual theodolites. fur +3396|127938|2963|1|34|66841.62|0.00|0.06|A|F|1994-05-30|1994-08-16|1994-06-11|NONE|AIR|. slyly unusual packages wak +3396|48322|827|2|43|54623.76|0.03|0.08|A|F|1994-07-03|1994-08-09|1994-07-14|TAKE BACK RETURN|MAIL|cial packages cajole blithely around the +3396|137579|93|3|9|14549.13|0.01|0.06|R|F|1994-07-01|1994-08-18|1994-07-21|DELIVER IN PERSON|AIR|usly special foxes. accounts wake careful +3396|74334|1856|4|32|41866.56|0.06|0.02|R|F|1994-08-07|1994-08-10|1994-09-05|COLLECT COD|TRUCK|osits are slyly. final, bold foxes s +3396|125022|47|5|27|28269.54|0.02|0.01|A|F|1994-09-14|1994-07-26|1994-09-28|DELIVER IN PERSON|FOB| theodolites +3396|38687|8688|6|18|29262.24|0.10|0.00|A|F|1994-07-27|1994-06-26|1994-08-25|TAKE BACK RETURN|REG AIR|l requests haggle furiously along the fur +3396|197228|4786|7|31|41081.82|0.05|0.06|A|F|1994-06-07|1994-06-23|1994-06-19|TAKE BACK RETURN|REG AIR|l, express pinto beans. quic +3397|194289|9328|1|8|11066.24|0.07|0.01|A|F|1994-08-05|1994-08-11|1994-08-08|DELIVER IN PERSON|RAIL|y final foxes +3397|12042|9546|2|11|10494.44|0.00|0.07|A|F|1994-07-29|1994-09-18|1994-08-12|DELIVER IN PERSON|REG AIR|iously careful packages. s +3397|183905|6424|3|1|1988.90|0.07|0.05|R|F|1994-08-03|1994-07-30|1994-08-28|NONE|RAIL| regular packag +3397|85592|5593|4|33|52060.47|0.05|0.01|R|F|1994-09-04|1994-08-06|1994-09-22|COLLECT COD|RAIL|gular accounts. blithely re +3397|131561|1562|5|28|44591.68|0.05|0.05|R|F|1994-07-13|1994-08-26|1994-07-17|NONE|TRUCK|counts around the final reques +3398|172957|2958|1|1|2029.95|0.01|0.08|N|O|1996-11-22|1996-11-16|1996-12-09|COLLECT COD|MAIL| blithely final deposits. +3399|133853|8880|1|28|52831.80|0.09|0.05|N|O|1995-06-29|1995-05-19|1995-07-12|COLLECT COD|AIR|oggedly final theodolites grow. fi +3399|54517|4518|2|8|11772.08|0.01|0.05|A|F|1995-05-15|1995-04-19|1995-06-05|COLLECT COD|TRUCK|s use carefully carefully ir +3399|66486|1499|3|3|4357.44|0.03|0.00|N|F|1995-06-16|1995-04-04|1995-06-23|NONE|SHIP|hely pending dugouts +3399|13659|3660|4|21|33025.65|0.09|0.06|A|F|1995-03-12|1995-05-18|1995-03-28|TAKE BACK RETURN|MAIL|se final courts. exc +3424|180866|8421|1|39|75927.54|0.06|0.07|N|O|1996-11-03|1996-11-08|1996-11-23|DELIVER IN PERSON|MAIL|bits boost closely slyly p +3425|119527|9528|1|11|17011.72|0.03|0.08|N|O|1996-04-24|1996-05-29|1996-05-23|DELIVER IN PERSON|FOB|ckly final deposits use quickly? +3425|78421|5943|2|37|51778.54|0.06|0.03|N|O|1996-06-04|1996-05-09|1996-06-12|NONE|SHIP|as sleep carefully into the caref +3425|13460|964|3|8|10987.68|0.06|0.08|N|O|1996-07-22|1996-06-07|1996-07-26|TAKE BACK RETURN|AIR|iously regular theodolites wake. s +3425|18914|8915|4|37|67817.67|0.04|0.01|N|O|1996-07-10|1996-05-10|1996-08-02|NONE|SHIP|ngside of the furiously thin dol +3425|78322|830|5|48|62415.36|0.08|0.04|N|O|1996-04-14|1996-05-25|1996-04-23|TAKE BACK RETURN|AIR|uctions wake fluffily. care +3425|147931|7932|6|24|47494.32|0.05|0.04|N|O|1996-04-22|1996-06-24|1996-04-25|TAKE BACK RETURN|AIR|ajole blithely sl +3426|109706|4727|1|20|34314.00|0.05|0.04|N|O|1996-11-10|1996-12-24|1996-12-01|COLLECT COD|FOB|sits cajole blit +3426|13356|860|2|19|24117.65|0.10|0.08|N|O|1996-11-02|1997-01-13|1996-11-15|DELIVER IN PERSON|RAIL|slyly special packages oug +3426|66426|8933|3|19|26455.98|0.08|0.05|N|O|1996-12-07|1996-12-15|1996-12-14|DELIVER IN PERSON|FOB|c accounts cajole carefu +3426|5263|5264|4|9|10514.34|0.09|0.05|N|O|1996-12-24|1997-01-14|1997-01-13|NONE|FOB|pecial theodolites haggle fluf +3426|48579|1084|5|31|47354.67|0.07|0.08|N|O|1996-11-11|1996-12-10|1996-12-10|DELIVER IN PERSON|SHIP| even sentiment +3427|53394|3395|1|41|55242.99|0.10|0.01|N|O|1997-09-11|1997-07-03|1997-10-04|COLLECT COD|RAIL|s the carefully +3427|188918|3955|2|24|48165.84|0.02|0.04|N|O|1997-07-01|1997-07-28|1997-07-30|NONE|SHIP|y bold, sly deposits. pendi +3427|138997|1511|3|40|81439.60|0.06|0.05|N|O|1997-06-12|1997-08-19|1997-06-23|COLLECT COD|MAIL|patterns cajole ca +3427|118088|3111|4|31|34288.48|0.08|0.04|N|O|1997-08-12|1997-07-26|1997-08-25|COLLECT COD|RAIL|s are carefull +3428|197651|7652|1|4|6994.60|0.00|0.03|N|O|1996-05-09|1996-06-13|1996-06-02|NONE|REG AIR|sly pending requests int +3428|117436|7437|2|35|50870.05|0.02|0.03|N|O|1996-05-01|1996-06-07|1996-05-20|COLLECT COD|TRUCK|ly regular pinto beans sleep +3428|135307|5308|3|47|63088.10|0.07|0.05|N|O|1996-04-16|1996-06-08|1996-05-05|NONE|REG AIR|y final pinto +3429|136768|1795|1|48|86628.48|0.06|0.02|N|O|1997-04-08|1997-03-09|1997-04-25|TAKE BACK RETURN|SHIP| haggle furiously ir +3429|58421|927|2|15|20691.30|0.03|0.04|N|O|1997-02-04|1997-03-09|1997-03-01|TAKE BACK RETURN|TRUCK|beans are fu +3429|68561|6080|3|10|15295.60|0.05|0.07|N|O|1997-01-19|1997-02-22|1997-01-25|TAKE BACK RETURN|REG AIR|ackages. quickly e +3429|88366|875|4|28|37922.08|0.10|0.07|N|O|1997-01-30|1997-03-18|1997-02-17|TAKE BACK RETURN|AIR|nstructions boost. thin +3429|164054|4055|5|45|50312.25|0.10|0.00|N|O|1997-04-21|1997-03-08|1997-05-05|COLLECT COD|REG AIR|ites poach a +3430|188117|3154|1|2|2410.22|0.07|0.06|R|F|1995-03-07|1995-01-28|1995-03-30|TAKE BACK RETURN|MAIL|sh furiously according to the evenly e +3430|80604|5621|2|32|50707.20|0.08|0.00|R|F|1995-01-17|1995-01-28|1995-02-06|NONE|TRUCK|egular instruction +3430|96381|6382|3|41|56472.58|0.06|0.04|R|F|1995-02-18|1995-02-21|1995-03-11|TAKE BACK RETURN|AIR|cuses. silent excuses h +3430|64955|9968|4|50|95997.50|0.01|0.00|R|F|1994-12-15|1995-03-03|1994-12-24|COLLECT COD|REG AIR|ironic theodolites. carefully regular pac +3430|94745|2273|5|5|8698.70|0.05|0.05|A|F|1995-04-02|1995-02-12|1995-04-08|DELIVER IN PERSON|FOB|even accounts haggle slyly bol +3430|170718|5753|6|15|26830.65|0.08|0.07|A|F|1995-02-01|1995-03-12|1995-02-04|COLLECT COD|SHIP|cajole around the accounts. qui +3430|51323|6334|7|23|29309.36|0.09|0.08|A|F|1995-03-06|1995-03-01|1995-03-10|COLLECT COD|MAIL|eas according to the +3431|179230|6782|1|41|53678.43|0.03|0.06|A|F|1993-09-26|1993-10-13|1993-10-22|NONE|AIR| sleep carefully ironically special +3456|110400|5423|1|34|47953.60|0.10|0.06|A|F|1993-08-29|1993-08-26|1993-09-07|TAKE BACK RETURN|SHIP|usy pinto beans b +3457|181229|6266|1|29|37996.38|0.03|0.02|R|F|1995-05-12|1995-07-13|1995-06-05|NONE|TRUCK|refully final excuses wake +3457|105915|5916|2|22|42260.02|0.06|0.01|N|O|1995-06-23|1995-06-16|1995-06-29|NONE|SHIP|packages nag furiously against +3457|108003|514|3|7|7077.00|0.07|0.08|N|O|1995-08-14|1995-07-06|1995-08-18|COLLECT COD|SHIP| pending accounts along the +3457|983|984|4|24|45215.52|0.07|0.07|N|O|1995-08-03|1995-05-30|1995-08-14|TAKE BACK RETURN|REG AIR|tructions haggle alongsid +3457|108595|3616|5|42|67350.78|0.05|0.01|A|F|1995-06-12|1995-06-14|1995-06-14|COLLECT COD|MAIL|riously final instruc +3457|143724|6239|6|45|79547.40|0.08|0.01|N|O|1995-08-12|1995-07-18|1995-08-23|TAKE BACK RETURN|SHIP| packages. care +3457|166641|1674|7|9|15368.76|0.04|0.00|R|F|1995-05-29|1995-06-30|1995-06-12|DELIVER IN PERSON|FOB|quests. foxes sleep quickly +3458|132484|7511|1|48|72791.04|0.06|0.04|R|F|1995-03-17|1995-01-25|1995-03-28|TAKE BACK RETURN|AIR|iously pending dep +3458|49179|4188|2|46|51895.82|0.06|0.06|R|F|1995-03-08|1995-01-21|1995-03-10|TAKE BACK RETURN|SHIP|nod across the boldly even instruct +3458|142061|2062|3|36|39710.16|0.01|0.06|R|F|1995-04-20|1995-02-14|1995-05-09|TAKE BACK RETURN|REG AIR|s lose. blithely ironic requests boost +3458|15253|7755|4|16|18692.00|0.09|0.03|R|F|1995-03-01|1995-02-25|1995-03-06|TAKE BACK RETURN|AIR|s grow carefully. express, final grouc +3458|156396|8912|5|2|2904.78|0.09|0.03|A|F|1995-02-05|1995-02-01|1995-03-07|COLLECT COD|FOB|ironic packages haggle past the furiously +3458|141853|9396|6|6|11369.10|0.09|0.04|A|F|1995-03-10|1995-02-02|1995-03-23|TAKE BACK RETURN|AIR|dolites; regular theodolites cajole +3459|178065|5617|1|31|35434.86|0.06|0.01|A|F|1994-09-05|1994-10-20|1994-10-03|NONE|REG AIR|y regular pain +3459|129270|4295|2|30|38978.10|0.04|0.08|R|F|1994-11-22|1994-09-12|1994-12-11|NONE|REG AIR|nic theodolites; evenly i +3459|40035|2540|3|45|43876.35|0.04|0.05|A|F|1994-07-31|1994-09-09|1994-08-02|TAKE BACK RETURN|REG AIR|ntly speci +3459|68031|8032|4|10|9990.30|0.05|0.06|A|F|1994-10-06|1994-09-16|1994-11-03|TAKE BACK RETURN|REG AIR| furiously silent dolphi +3459|188574|6129|5|10|16625.70|0.02|0.02|R|F|1994-08-01|1994-10-17|1994-08-11|TAKE BACK RETURN|FOB|. blithely ironic pinto beans above +3460|10655|8159|1|40|62626.00|0.10|0.06|N|O|1995-12-28|1995-12-14|1996-01-02|NONE|REG AIR|odolites are slyly bold deposits +3460|73365|5873|2|3|4015.08|0.06|0.00|N|O|1996-01-19|1995-12-28|1996-01-31|COLLECT COD|AIR|er quickly +3460|34658|7162|3|40|63706.00|0.08|0.07|N|O|1995-10-29|1995-11-10|1995-11-24|TAKE BACK RETURN|REG AIR|o the even deposits +3460|94647|9666|4|50|82082.00|0.02|0.07|N|O|1996-01-30|1995-12-10|1996-02-06|DELIVER IN PERSON|SHIP|e slyly about the sly +3460|129391|9392|5|47|66758.33|0.08|0.05|N|O|1995-12-09|1995-11-12|1995-12-22|TAKE BACK RETURN|SHIP|es haggle slyly regular accounts. fi +3460|62084|7097|6|46|48119.68|0.03|0.07|N|O|1996-01-27|1996-01-01|1996-02-01|NONE|TRUCK|uses run among the carefully even deposits +3460|44512|7017|7|28|40782.28|0.00|0.01|N|O|1995-10-28|1995-11-13|1995-11-17|COLLECT COD|SHIP|inal, ironic instructions. carefully +3461|99796|7324|1|49|87993.71|0.06|0.06|A|F|1993-03-09|1993-04-16|1993-03-13|DELIVER IN PERSON|RAIL|ual request +3461|62417|2418|2|27|37244.07|0.06|0.06|A|F|1993-02-10|1993-03-02|1993-03-04|COLLECT COD|SHIP|ely unusual deposits. quickly ir +3461|38930|1434|3|44|82232.92|0.09|0.06|A|F|1993-05-20|1993-04-03|1993-05-27|COLLECT COD|RAIL| haggle quickly even ideas. fin +3461|94288|6798|4|41|52573.48|0.09|0.02|R|F|1993-02-19|1993-04-20|1993-02-21|NONE|TRUCK|heodolites. blithely ironi +3461|89771|4788|5|16|28172.32|0.08|0.06|A|F|1993-05-09|1993-04-29|1993-05-26|TAKE BACK RETURN|TRUCK| pending deposi +3461|166821|4370|6|24|45307.68|0.10|0.00|A|F|1993-06-01|1993-03-12|1993-06-20|TAKE BACK RETURN|MAIL|thely. carefully re +3462|150880|8426|1|4|7723.52|0.09|0.04|N|O|1997-06-12|1997-07-31|1997-06-16|COLLECT COD|RAIL|ackages. fu +3462|39432|4439|2|43|58971.49|0.08|0.03|N|O|1997-08-01|1997-07-18|1997-08-29|NONE|RAIL| carefully. final, final ideas sleep slyly +3462|128298|811|3|6|7957.74|0.05|0.04|N|O|1997-06-02|1997-08-09|1997-06-30|NONE|RAIL|iously regular fo +3462|98093|5621|4|2|2182.18|0.09|0.07|N|O|1997-09-10|1997-08-08|1997-09-19|NONE|AIR|nic packages. even accounts alongside +3462|37353|4863|5|14|18064.90|0.01|0.02|N|O|1997-05-31|1997-07-05|1997-06-24|COLLECT COD|MAIL|yly. blithely bold theodolites wa +3463|60779|3286|1|45|78289.65|0.02|0.02|A|F|1993-10-30|1993-11-04|1993-11-08|DELIVER IN PERSON|FOB|nts are slyly +3463|97924|2943|2|43|82642.56|0.04|0.02|A|F|1993-10-28|1993-09-24|1993-11-03|DELIVER IN PERSON|FOB| across the +3488|159702|4733|1|1|1761.70|0.04|0.01|A|F|1995-03-06|1995-02-16|1995-03-23|DELIVER IN PERSON|FOB| final excuses. carefully even waters hagg +3488|103455|8476|2|48|70005.60|0.00|0.03|A|F|1995-03-29|1995-03-26|1995-04-28|COLLECT COD|SHIP|sly? final requests +3488|159080|9081|3|11|12529.88|0.03|0.08|R|F|1995-03-25|1995-02-08|1995-04-16|COLLECT COD|TRUCK|unusual re +3488|41028|3533|4|12|11628.24|0.05|0.07|R|F|1995-04-27|1995-02-16|1995-05-09|DELIVER IN PERSON|RAIL|e slyly; furiously final packages wak +3488|155132|163|5|18|21368.34|0.09|0.06|A|F|1995-03-18|1995-03-19|1995-03-29|DELIVER IN PERSON|FOB|s the carefully r +3489|185663|8182|1|19|33224.54|0.09|0.05|A|F|1993-07-31|1993-10-26|1993-08-15|NONE|SHIP|c deposits alongside of the pending, fu +3489|28091|594|2|46|46878.14|0.00|0.00|A|F|1993-08-02|1993-10-09|1993-08-10|TAKE BACK RETURN|TRUCK|xcuses? quickly stealthy dependenci +3490|91360|8888|1|43|58108.48|0.05|0.05|N|O|1997-08-04|1997-08-06|1997-08-14|TAKE BACK RETURN|SHIP|. even requests cajol +3490|85447|2972|2|50|71622.00|0.05|0.07|N|O|1997-06-27|1997-08-15|1997-06-28|NONE|RAIL| haggle carefu +3490|92453|9981|3|8|11563.60|0.10|0.04|N|O|1997-08-11|1997-07-25|1997-08-28|COLLECT COD|MAIL|inal deposits use furiousl +3491|153491|6007|1|28|43245.72|0.04|0.03|N|O|1998-09-29|1998-09-08|1998-10-23|COLLECT COD|FOB|ccounts. sly +3491|121773|1774|2|22|39484.94|0.08|0.02|N|O|1998-08-19|1998-08-22|1998-09-03|TAKE BACK RETURN|REG AIR| grow against the boldly pending pinto bea +3492|155860|5861|1|3|5747.58|0.02|0.08|R|F|1994-11-26|1994-12-28|1994-12-19|COLLECT COD|REG AIR|the deposits. carefully +3492|125526|3063|2|7|10860.64|0.04|0.00|R|F|1995-03-10|1995-01-03|1995-03-16|COLLECT COD|FOB|thely regular dolphi +3492|108869|8870|3|34|63847.24|0.05|0.06|A|F|1994-12-07|1994-12-29|1994-12-24|COLLECT COD|AIR| unusual requests. ir +3492|146899|4442|4|30|58376.70|0.02|0.06|A|F|1995-01-29|1995-01-02|1995-02-13|DELIVER IN PERSON|MAIL| detect furiously permanent, unusual accou +3492|121499|6524|5|47|71463.03|0.09|0.07|R|F|1995-03-24|1994-12-28|1995-03-29|NONE|REG AIR|deposits. quickly express +3492|21118|3621|6|47|48838.17|0.04|0.07|R|F|1994-12-12|1995-01-18|1994-12-26|COLLECT COD|RAIL|ronic instructions u +3493|92506|7525|1|31|46453.50|0.06|0.07|R|F|1993-10-22|1993-10-12|1993-11-07|DELIVER IN PERSON|REG AIR|ructions. slyly regular accounts across the +3493|131994|1995|2|10|20259.90|0.02|0.06|R|F|1993-08-27|1993-10-07|1993-09-23|COLLECT COD|TRUCK|hall have to integ +3494|116147|8659|1|40|46525.60|0.05|0.04|R|F|1993-07-10|1993-06-01|1993-07-25|TAKE BACK RETURN|TRUCK|lites haggle furiously about the fin +3494|74124|4125|2|23|25256.76|0.10|0.01|A|F|1993-06-19|1993-06-04|1993-07-14|NONE|FOB|osits nag +3494|197161|4719|3|40|50326.40|0.02|0.08|A|F|1993-05-30|1993-07-02|1993-06-20|TAKE BACK RETURN|MAIL|uests cajole blithely +3494|76076|6077|4|30|31562.10|0.04|0.03|R|F|1993-07-01|1993-06-08|1993-07-15|TAKE BACK RETURN|TRUCK|ns are quickly regular, +3495|27321|9824|1|20|24966.40|0.10|0.03|N|O|1996-04-24|1996-05-18|1996-05-01|TAKE BACK RETURN|RAIL|posits are carefully; forges cajole qui +3495|172119|9671|2|24|28586.64|0.05|0.02|N|O|1996-03-22|1996-04-10|1996-04-07|DELIVER IN PERSON|RAIL|ic, final pains along the even request +3495|198597|8598|3|16|27129.44|0.08|0.02|N|O|1996-03-30|1996-04-02|1996-04-12|TAKE BACK RETURN|AIR|y bold dependencies; blithely idle sautern +3520|27999|5506|1|30|57809.70|0.04|0.02|N|O|1997-11-11|1997-10-02|1997-12-06|COLLECT COD|SHIP|deas should solve blithely among the ironi +3520|166759|1792|2|38|69378.50|0.00|0.04|N|O|1997-08-14|1997-10-26|1997-09-09|NONE|RAIL|yly final packages according to the quickl +3520|105258|7769|3|5|6316.25|0.01|0.02|N|O|1997-11-13|1997-09-22|1997-12-09|NONE|MAIL|ly even ideas haggle +3520|63745|3746|4|41|70058.34|0.01|0.01|N|O|1997-08-06|1997-09-20|1997-08-20|TAKE BACK RETURN|AIR| carefully pendi +3520|162174|7207|5|35|43265.95|0.02|0.02|N|O|1997-09-16|1997-09-03|1997-09-24|DELIVER IN PERSON|FOB|s nag carefully. sometimes unusual account +3521|58448|3459|1|48|67509.12|0.09|0.03|A|F|1993-01-03|1992-12-31|1993-01-22|NONE|AIR|ses use. furiously express ideas wake f +3521|130897|898|2|2|3855.78|0.05|0.06|R|F|1993-01-29|1992-12-20|1993-02-23|NONE|MAIL|refully duri +3521|177971|489|3|38|77860.86|0.00|0.08|A|F|1993-02-15|1992-12-10|1993-03-10|COLLECT COD|FOB|ges hang q +3521|143978|9007|4|26|52571.22|0.02|0.08|R|F|1993-01-04|1993-01-20|1993-01-17|DELIVER IN PERSON|AIR|onic dependencies haggle. fur +3521|35052|59|5|28|27637.40|0.10|0.01|A|F|1993-01-06|1993-01-22|1993-02-02|TAKE BACK RETURN|FOB|e slyly above the slyly final +3522|3671|8672|1|6|9448.02|0.08|0.03|A|F|1995-01-21|1994-12-09|1995-01-23|NONE|SHIP|tes snooze +3522|86438|8947|2|48|68372.64|0.00|0.03|R|F|1994-12-05|1994-10-30|1994-12-26|TAKE BACK RETURN|SHIP|ve the quickly special packages +3522|156693|1724|3|46|80485.74|0.09|0.02|A|F|1994-11-12|1994-11-30|1994-11-20|NONE|AIR|d the express, silent foxes. blit +3522|129818|4843|4|7|12934.67|0.10|0.02|A|F|1994-10-31|1994-11-19|1994-11-28|NONE|TRUCK|e stealthil +3522|49144|6657|5|27|29514.78|0.02|0.05|R|F|1994-11-29|1994-12-15|1994-12-08|COLLECT COD|REG AIR|ic tithes. car +3522|157970|5516|6|18|36503.46|0.01|0.03|A|F|1994-11-16|1994-10-29|1994-11-29|COLLECT COD|RAIL|sits wake carefully pen +3523|24474|4475|1|15|20977.05|0.06|0.02|N|O|1998-06-26|1998-05-22|1998-07-24|COLLECT COD|REG AIR|se slyly pending, sp +3523|132127|9667|2|4|4636.48|0.03|0.06|N|O|1998-05-08|1998-05-18|1998-05-25|TAKE BACK RETURN|MAIL|ts. final accounts detect furiously along +3523|49146|1651|3|24|26283.36|0.07|0.04|N|O|1998-08-02|1998-06-22|1998-08-27|COLLECT COD|FOB|ke according to the doggedly re +3523|191238|3758|4|36|47852.28|0.06|0.08|N|O|1998-05-26|1998-06-04|1998-06-25|DELIVER IN PERSON|SHIP|accounts. fluffily regu +3523|133109|3110|5|48|54820.80|0.00|0.01|N|O|1998-07-22|1998-06-25|1998-08-19|DELIVER IN PERSON|AIR| regular requests +3524|136119|6120|1|5|5775.55|0.01|0.04|R|F|1992-05-23|1992-07-25|1992-06-19|DELIVER IN PERSON|RAIL|ts whithout the bold depende +3524|142948|7977|2|17|33845.98|0.09|0.08|A|F|1992-09-01|1992-07-17|1992-09-05|DELIVER IN PERSON|FOB|g, final epitaphs about the pinto +3525|45478|5479|1|12|17081.64|0.01|0.03|N|O|1996-03-08|1996-03-18|1996-03-16|NONE|TRUCK|lar excuses wake carefull +3525|137210|2237|2|27|33674.67|0.03|0.03|N|O|1995-12-30|1996-01-23|1996-01-02|DELIVER IN PERSON|SHIP|y slyly special asymptotes +3525|74397|6905|3|31|42513.09|0.00|0.03|N|O|1996-03-08|1996-02-27|1996-03-13|COLLECT COD|TRUCK|he careful +3525|183399|954|4|28|41506.92|0.03|0.02|N|O|1996-01-22|1996-02-08|1996-01-27|COLLECT COD|FOB| nag according +3526|97645|7646|1|11|18069.04|0.02|0.03|R|F|1995-05-23|1995-05-28|1995-05-24|NONE|TRUCK|ges. furiously regular d +3526|116383|3917|2|23|32185.74|0.03|0.04|A|F|1995-05-01|1995-05-31|1995-05-25|DELIVER IN PERSON|FOB|special, regular packages cajole. +3526|32541|51|3|20|29470.80|0.05|0.08|N|F|1995-06-16|1995-04-26|1995-06-22|DELIVER IN PERSON|REG AIR|kages. bold, special requests detect sl +3527|101388|6409|1|47|65300.86|0.07|0.02|N|O|1997-07-14|1997-07-29|1997-07-21|DELIVER IN PERSON|RAIL|unts. express re +3527|25083|2590|2|33|33266.64|0.01|0.02|N|O|1997-09-25|1997-09-17|1997-10-12|NONE|FOB|kly alongside of +3527|161298|8847|3|50|67964.50|0.09|0.07|N|O|1997-07-17|1997-08-03|1997-07-29|DELIVER IN PERSON|SHIP|e even accounts was about th +3527|127163|9676|4|17|20232.72|0.02|0.05|N|O|1997-07-30|1997-09-01|1997-08-17|COLLECT COD|MAIL|ular instruction +3552|196483|6484|1|18|28430.64|0.01|0.07|N|O|1997-08-11|1997-07-14|1997-08-15|DELIVER IN PERSON|TRUCK|s deposits against the blithely unusual pin +3552|89318|1827|2|44|57521.64|0.01|0.00|N|O|1997-08-08|1997-06-15|1997-08-29|COLLECT COD|FOB|ns after the blithely reg +3552|160455|8004|3|36|54556.20|0.04|0.08|N|O|1997-06-29|1997-06-24|1997-07-21|COLLECT COD|TRUCK|ly regular theodolites. fin +3553|142076|4591|1|4|4472.28|0.05|0.01|R|F|1994-06-13|1994-07-10|1994-07-03|COLLECT COD|RAIL|olites boost bli +3553|64118|6625|2|26|28134.86|0.05|0.08|A|F|1994-08-06|1994-07-30|1994-08-23|DELIVER IN PERSON|MAIL|fily special p +3553|21291|8798|3|18|21821.22|0.04|0.03|A|F|1994-07-03|1994-06-30|1994-07-07|COLLECT COD|RAIL|. quickly ironic +3553|31009|3513|4|40|37600.00|0.06|0.00|A|F|1994-09-14|1994-06-26|1994-09-25|NONE|RAIL| slyly pending asymptotes against the furi +3553|156020|1051|5|36|38736.72|0.06|0.08|R|F|1994-08-12|1994-06-25|1994-09-06|DELIVER IN PERSON|TRUCK| realms. pending, bold theodolites +3554|174151|6669|1|32|39204.80|0.01|0.05|N|O|1995-09-28|1995-09-01|1995-10-07|NONE|RAIL|. blithely ironic t +3554|144071|4072|2|18|20071.26|0.03|0.00|N|O|1995-09-11|1995-08-12|1995-10-04|DELIVER IN PERSON|REG AIR| haggle. furiously fluffy requests ac +3554|191547|1548|3|41|67180.14|0.02|0.01|N|O|1995-07-13|1995-08-28|1995-07-27|DELIVER IN PERSON|MAIL|ent dependencies. sly +3555|165543|576|1|11|17693.94|0.05|0.02|N|O|1996-09-25|1996-10-01|1996-10-03|NONE|FOB|oost caref +3555|78411|8412|2|15|20841.15|0.03|0.08|N|O|1996-07-13|1996-09-01|1996-08-02|TAKE BACK RETURN|RAIL|y across the pending a +3555|42078|9591|3|25|25501.75|0.09|0.07|N|O|1996-10-01|1996-08-23|1996-10-24|TAKE BACK RETURN|MAIL|sual packages. quickly +3555|4429|4430|4|19|25334.98|0.00|0.05|N|O|1996-09-08|1996-09-14|1996-10-01|COLLECT COD|REG AIR|leep special theodolit +3555|32976|7983|5|29|55360.13|0.07|0.04|N|O|1996-08-02|1996-09-04|1996-08-08|DELIVER IN PERSON|TRUCK|deas. carefully s +3555|27342|9845|6|33|41888.22|0.04|0.08|N|O|1996-09-20|1996-09-23|1996-10-05|TAKE BACK RETURN|AIR|fluffily regular a +3555|125254|279|7|9|11513.25|0.07|0.02|N|O|1996-10-13|1996-10-02|1996-10-22|NONE|SHIP|are. slyly final foxes acro +3556|141443|3958|1|45|66799.80|0.05|0.06|A|F|1992-10-14|1992-12-21|1992-10-16|NONE|TRUCK|ckages boost quickl +3556|30350|5357|2|43|55055.05|0.02|0.06|R|F|1993-01-18|1992-11-09|1993-02-04|NONE|FOB|wake carefull +3556|86856|6857|3|28|51599.80|0.10|0.04|A|F|1993-01-06|1992-11-27|1993-01-16|NONE|MAIL|refully final instructions? ironic packa +3557|174245|1797|1|41|54088.84|0.01|0.07|R|F|1993-01-30|1992-12-31|1993-02-18|COLLECT COD|FOB|ideas breach c +3557|128842|8843|2|37|69221.08|0.03|0.05|R|F|1993-02-16|1993-01-05|1993-03-15|DELIVER IN PERSON|RAIL|gside of the ca +3558|86334|6335|1|8|10562.64|0.01|0.03|N|O|1996-05-31|1996-05-26|1996-06-25|COLLECT COD|AIR|? even requests sle +3558|9567|7068|2|28|41343.68|0.02|0.08|N|O|1996-06-02|1996-04-18|1996-06-24|COLLECT COD|TRUCK|l deposits +3558|186452|1489|3|3|4615.35|0.03|0.06|N|O|1996-05-19|1996-04-28|1996-05-26|DELIVER IN PERSON|RAIL|l, final deposits haggle. fina +3558|90560|8088|4|22|34112.32|0.06|0.03|N|O|1996-04-27|1996-04-19|1996-04-30|DELIVER IN PERSON|SHIP|refully ironic theodolites are fu +3558|28850|3855|5|38|67596.30|0.03|0.08|N|O|1996-05-29|1996-05-02|1996-06-09|COLLECT COD|RAIL|refully permanently iron +3558|71821|6836|6|17|30477.94|0.07|0.07|N|O|1996-03-14|1996-05-04|1996-04-05|NONE|RAIL|ithely unusual packa +3559|89591|9592|1|29|45837.11|0.00|0.07|R|F|1992-12-10|1992-12-03|1992-12-20|COLLECT COD|REG AIR|l, regular accounts wake flu +3584|10196|5199|1|4|4424.76|0.04|0.08|N|O|1997-08-16|1997-10-31|1997-08-28|DELIVER IN PERSON|TRUCK|nal packag +3584|159495|2011|2|23|35753.27|0.00|0.03|N|O|1997-09-10|1997-10-15|1997-09-30|COLLECT COD|TRUCK|l platelets until the asymptotes +3584|23297|3298|3|6|7321.74|0.03|0.06|N|O|1997-10-28|1997-11-09|1997-11-24|TAKE BACK RETURN|MAIL|deposits across the +3584|145596|3139|4|11|18057.49|0.06|0.02|N|O|1997-11-27|1997-10-15|1997-12-08|NONE|REG AIR|lithely slyly +3584|17924|2927|5|39|71834.88|0.09|0.07|N|O|1997-09-20|1997-10-31|1997-10-06|COLLECT COD|AIR|eposits. carefu +3585|121713|6738|1|21|36428.91|0.05|0.04|A|F|1994-12-04|1994-12-25|1995-01-01|TAKE BACK RETURN|TRUCK|ounts use. express, final platelets us +3585|18535|8536|2|40|58141.20|0.03|0.00|R|F|1995-01-22|1995-01-17|1995-02-07|TAKE BACK RETURN|RAIL|elets affix. even asymptotes play care +3585|111350|8884|3|11|14974.85|0.01|0.04|R|F|1995-01-04|1995-02-14|1995-01-15|NONE|MAIL|even packages +3585|47911|2920|4|33|61344.03|0.08|0.08|A|F|1994-12-14|1995-01-19|1994-12-22|NONE|RAIL|ironic dependencies serve furi +3585|24543|2050|5|13|19078.02|0.06|0.07|R|F|1995-03-15|1995-01-22|1995-03-17|DELIVER IN PERSON|AIR|ccording to the foxes. slyly iro +3585|93452|8471|6|7|10118.15|0.10|0.02|A|F|1994-12-13|1995-01-20|1995-01-05|TAKE BACK RETURN|TRUCK|dependencies sleep un +3585|41685|9198|7|45|73200.60|0.03|0.00|A|F|1995-01-20|1995-02-19|1995-02-11|DELIVER IN PERSON|MAIL|are blithely c +3586|193699|8738|1|2|3585.38|0.03|0.08|R|F|1994-02-10|1994-01-07|1994-03-03|DELIVER IN PERSON|RAIL|he even, unusual decoy +3586|83314|3315|2|29|37621.99|0.04|0.07|R|F|1994-03-06|1994-03-02|1994-03-13|DELIVER IN PERSON|RAIL| slyly unusual i +3586|57422|2433|3|2|2758.84|0.03|0.06|R|F|1994-03-22|1994-02-20|1994-04-08|NONE|REG AIR|unts. slyly final ideas agai +3586|83722|3723|4|33|56288.76|0.06|0.01|R|F|1994-01-24|1994-02-09|1994-02-07|NONE|TRUCK|refully across the fur +3586|107949|460|5|8|15655.52|0.06|0.02|A|F|1994-03-29|1994-02-26|1994-04-02|NONE|FOB|theodolites hagg +3586|98598|1108|6|8|12772.72|0.09|0.01|A|F|1994-03-18|1994-01-17|1994-04-06|DELIVER IN PERSON|RAIL| ironic pinto beans cajole carefully theo +3586|122699|2700|7|33|56815.77|0.05|0.04|A|F|1994-02-11|1994-01-15|1994-03-03|NONE|REG AIR|iously regular pinto beans integrate +3587|196712|1751|1|5|9043.55|0.09|0.07|N|O|1996-09-03|1996-07-05|1996-09-11|DELIVER IN PERSON|SHIP|ithely regular decoys above the +3587|131240|8780|2|48|61019.52|0.00|0.03|N|O|1996-08-02|1996-07-02|1996-08-05|TAKE BACK RETURN|MAIL|beans. blithely final depe +3587|150350|7896|3|36|50412.60|0.05|0.05|N|O|1996-07-26|1996-06-16|1996-08-23|TAKE BACK RETURN|MAIL|ully regular excuse +3587|123620|6133|4|31|50952.22|0.03|0.01|N|O|1996-07-21|1996-07-01|1996-07-23|COLLECT COD|SHIP|press fluffily regul +3587|69585|4598|5|12|18654.96|0.06|0.03|N|O|1996-08-30|1996-07-04|1996-09-22|DELIVER IN PERSON|RAIL|g the even pinto beans. special, +3587|106080|1101|6|16|17377.28|0.01|0.03|N|O|1996-05-11|1996-06-19|1996-06-04|COLLECT COD|FOB|y ruthless dolphins to +3587|73225|747|7|23|27559.06|0.07|0.05|N|O|1996-08-30|1996-07-01|1996-09-10|COLLECT COD|FOB|l multipliers sleep theodolites-- slyly +3588|90135|7663|1|28|31503.64|0.04|0.08|R|F|1995-05-03|1995-05-03|1995-05-14|DELIVER IN PERSON|TRUCK|special pinto beans cajole slyly. slyly +3588|87759|268|2|6|10480.50|0.06|0.08|A|F|1995-04-09|1995-05-30|1995-04-10|TAKE BACK RETURN|MAIL|s. fluffily fluf +3588|158716|8717|3|45|79861.95|0.04|0.02|R|F|1995-05-07|1995-05-04|1995-05-28|TAKE BACK RETURN|TRUCK|ecial pains integrate blithely. reques +3588|126284|3821|4|22|28826.16|0.05|0.00|A|F|1995-04-08|1995-05-06|1995-04-27|NONE|RAIL|inal accounts. pending, bo +3588|54948|7454|5|28|53282.32|0.03|0.03|A|F|1995-04-23|1995-05-25|1995-04-28|DELIVER IN PERSON|TRUCK| express sheaves. unusual theodo +3588|109433|1944|6|37|53369.91|0.08|0.04|N|F|1995-06-17|1995-05-25|1995-06-24|TAKE BACK RETURN|RAIL|xcuses sleep quickly along th +3588|38463|967|7|46|64467.16|0.08|0.07|A|F|1995-06-06|1995-05-08|1995-06-08|NONE|AIR| slyly ironic deposits sublate ab +3589|36519|4029|1|42|61131.42|0.08|0.08|R|F|1994-08-11|1994-07-17|1994-08-23|DELIVER IN PERSON|AIR|he blithely unusual pac +3590|175980|8498|1|10|20559.80|0.08|0.00|N|O|1995-07-17|1995-06-26|1995-08-12|TAKE BACK RETURN|SHIP|t the quickly ironic +3590|94336|4337|2|19|25276.27|0.03|0.03|N|O|1995-08-02|1995-06-20|1995-08-08|NONE|SHIP|special pinto beans. blithely reg +3590|95583|602|3|43|67878.94|0.07|0.06|N|O|1995-07-12|1995-07-25|1995-07-16|DELIVER IN PERSON|SHIP|s could have to use +3590|55334|2850|4|26|33522.58|0.01|0.03|N|O|1995-07-08|1995-06-17|1995-08-02|DELIVER IN PERSON|SHIP|arefully along th +3590|190226|227|5|37|48700.14|0.00|0.08|N|O|1995-09-01|1995-06-29|1995-09-10|NONE|SHIP|ccounts above the silent waters thrash f +3590|118843|8844|6|31|57717.04|0.03|0.01|N|O|1995-06-24|1995-07-12|1995-06-25|DELIVER IN PERSON|REG AIR|ve furiously final instructions. slyly regu +3590|193517|8556|7|44|70862.44|0.05|0.04|N|F|1995-06-07|1995-06-15|1995-06-27|NONE|MAIL|s sleep after the regular platelets. blit +3591|28873|3878|1|21|37839.27|0.03|0.03|A|F|1994-02-25|1994-02-02|1994-03-05|DELIVER IN PERSON|TRUCK|structions against +3591|68232|3245|2|24|28805.52|0.04|0.04|R|F|1993-12-26|1994-01-07|1994-01-25|COLLECT COD|FOB|ages. slyly regular dependencies cajo +3591|163239|788|3|4|5208.92|0.01|0.03|A|F|1994-04-04|1994-02-19|1994-05-02|DELIVER IN PERSON|RAIL|he final packages. deposits serve quick +3591|152523|2524|4|49|77200.48|0.01|0.00|A|F|1994-03-21|1994-01-26|1994-03-28|COLLECT COD|AIR| mold slyly. bl +3616|196546|9066|1|30|49276.20|0.01|0.00|A|F|1994-05-05|1994-04-24|1994-05-12|TAKE BACK RETURN|FOB|ly ironic accounts unwind b +3616|137984|7985|2|28|56615.44|0.08|0.06|R|F|1994-02-20|1994-04-18|1994-03-05|DELIVER IN PERSON|REG AIR|ironic packages. furiously ev +3617|116065|6066|1|46|49728.76|0.03|0.02|N|O|1996-05-19|1996-05-14|1996-06-11|NONE|RAIL|ar theodolites. regu +3617|97942|7943|2|16|31039.04|0.05|0.02|N|O|1996-05-08|1996-06-03|1996-05-19|COLLECT COD|RAIL| slyly on th +3617|97724|5252|3|32|55095.04|0.00|0.06|N|O|1996-04-20|1996-06-07|1996-05-19|DELIVER IN PERSON|MAIL|uriously against the express accounts. ex +3617|40706|8219|4|22|36227.40|0.10|0.05|N|O|1996-07-11|1996-05-02|1996-07-25|NONE|REG AIR|uffily even accounts. packages sleep blithe +3617|136286|1313|5|11|14545.08|0.08|0.05|N|O|1996-07-16|1996-04-23|1996-07-28|COLLECT COD|MAIL|ly quickly even requests. final +3618|139641|4668|1|38|63864.32|0.08|0.00|N|O|1997-12-22|1998-02-23|1998-01-03|TAKE BACK RETURN|TRUCK|nts haggle fluffily above the regular +3618|143397|3398|2|48|69138.72|0.04|0.00|N|O|1998-03-12|1998-02-13|1998-03-29|DELIVER IN PERSON|TRUCK|tructions atop the ironi +3618|62032|4539|3|24|23856.72|0.01|0.04|N|O|1998-01-26|1998-01-15|1998-02-17|TAKE BACK RETURN|AIR|xpress acc +3618|160418|419|4|26|38438.66|0.01|0.05|N|O|1998-03-23|1998-01-24|1998-04-15|DELIVER IN PERSON|AIR|iously regular deposits cajole ruthless +3619|95741|5742|1|49|85100.26|0.01|0.08|N|O|1997-01-22|1996-12-21|1997-02-17|TAKE BACK RETURN|MAIL| waters. furiously even deposits +3619|115622|8134|2|27|44215.74|0.08|0.04|N|O|1996-12-12|1997-01-18|1996-12-18|TAKE BACK RETURN|SHIP|pecial accounts haggle care +3619|47022|4535|3|46|44574.92|0.08|0.03|N|O|1997-01-31|1997-01-27|1997-02-11|NONE|SHIP|press, expres +3619|92969|7988|4|18|35315.28|0.04|0.02|N|O|1997-03-18|1996-12-24|1997-03-21|COLLECT COD|AIR|eodolites +3619|119269|6803|5|38|48953.88|0.05|0.08|N|O|1996-12-08|1997-02-03|1997-01-07|NONE|RAIL|theodolites detect abo +3619|151951|1952|6|43|86126.85|0.01|0.01|N|O|1997-01-25|1997-01-06|1997-02-07|COLLECT COD|RAIL| bold, even +3620|58688|1194|1|41|67513.88|0.03|0.08|N|O|1997-03-21|1997-04-20|1997-03-30|COLLECT COD|FOB|t attainments cajole qui +3620|166574|1607|2|16|26249.12|0.00|0.06|N|O|1997-05-17|1997-05-08|1997-06-03|COLLECT COD|SHIP|s. even, pending in +3621|16475|6476|1|29|40352.63|0.02|0.06|A|F|1993-08-03|1993-07-08|1993-08-10|DELIVER IN PERSON|FOB|al requests. fl +3621|92329|4839|2|13|17177.16|0.09|0.04|R|F|1993-08-30|1993-06-30|1993-09-01|NONE|REG AIR|r the unusual packages. brave theodoli +3621|163518|1067|3|45|71167.95|0.07|0.07|R|F|1993-08-09|1993-06-18|1993-09-05|DELIVER IN PERSON|AIR| doubt about the bold deposits. carefully +3621|43242|755|4|20|23704.80|0.05|0.04|R|F|1993-05-27|1993-07-04|1993-06-22|TAKE BACK RETURN|SHIP|gular accounts use carefully with +3622|174754|4755|1|47|85951.25|0.09|0.00|N|O|1996-02-24|1996-02-22|1996-03-12|TAKE BACK RETURN|TRUCK|are careful +3622|88392|901|2|4|5521.56|0.04|0.04|N|O|1996-02-03|1996-02-19|1996-02-16|TAKE BACK RETURN|TRUCK|lithely brave foxes. furi +3622|189480|9481|3|46|72196.08|0.07|0.07|N|O|1995-12-18|1996-01-23|1996-01-12|TAKE BACK RETURN|AIR|sits wake. blithe +3622|176517|6518|4|9|14341.59|0.08|0.05|N|O|1995-12-12|1996-02-09|1995-12-13|TAKE BACK RETURN|SHIP|arefully. furiously regular ideas n +3623|79831|2339|1|32|57946.56|0.05|0.00|N|O|1997-04-18|1997-03-15|1997-05-09|COLLECT COD|SHIP| courts. furiously regular ideas b +3623|116203|1226|2|33|40233.60|0.08|0.01|N|O|1997-03-17|1997-02-13|1997-04-02|TAKE BACK RETURN|TRUCK|odolites. blithely spe +3623|23025|532|3|21|19908.42|0.02|0.02|N|O|1997-01-19|1997-03-18|1997-01-24|NONE|FOB|ress ideas are furio +3623|164747|9780|4|42|76093.08|0.05|0.06|N|O|1997-01-11|1997-03-24|1997-01-21|COLLECT COD|RAIL|g to the slyly regular packa +3623|87761|5286|5|30|52462.80|0.10|0.04|N|O|1997-04-04|1997-03-03|1997-05-01|NONE|RAIL| ironic somas sleep fluffily +3623|185158|195|6|7|8702.05|0.01|0.02|N|O|1997-01-05|1997-03-26|1997-01-26|NONE|TRUCK|aves. slyly special packages cajole. fu +3623|139856|2370|7|13|24646.05|0.03|0.08|N|O|1997-01-02|1997-02-26|1997-01-26|DELIVER IN PERSON|SHIP|deas. furiously expres +3648|143090|3091|1|16|18129.44|0.02|0.06|A|F|1993-08-14|1993-08-14|1993-08-15|COLLECT COD|FOB|s nag packages. +3648|104769|2300|2|30|53212.80|0.00|0.01|R|F|1993-08-31|1993-09-06|1993-09-06|DELIVER IN PERSON|FOB| above the somas boost furious +3648|45851|5852|3|34|61092.90|0.10|0.00|A|F|1993-08-21|1993-07-25|1993-09-15|DELIVER IN PERSON|FOB| deposits are furiously. careful, +3648|12026|7029|4|16|15008.32|0.06|0.03|R|F|1993-07-27|1993-08-26|1993-08-24|DELIVER IN PERSON|FOB|uriously stealthy deposits haggle furi +3648|116962|4496|5|25|49474.00|0.06|0.03|R|F|1993-08-15|1993-08-25|1993-09-09|TAKE BACK RETURN|TRUCK|s requests. silent asymp +3648|168406|8407|6|14|20641.60|0.08|0.06|R|F|1993-10-02|1993-08-26|1993-10-09|COLLECT COD|AIR|sly pending excuses. carefully i +3648|194110|4111|7|49|59001.39|0.09|0.03|R|F|1993-06-27|1993-07-27|1993-07-24|TAKE BACK RETURN|FOB|egular instructions. slyly regular pinto +3649|4730|4731|1|25|40868.25|0.10|0.04|A|F|1994-10-27|1994-08-23|1994-11-05|TAKE BACK RETURN|TRUCK|special re +3649|88968|3985|2|23|45010.08|0.08|0.00|R|F|1994-09-26|1994-10-01|1994-09-28|NONE|REG AIR|rs promise blithe +3649|69238|4251|3|14|16901.22|0.02|0.04|A|F|1994-09-19|1994-08-17|1994-10-12|DELIVER IN PERSON|TRUCK|ithely bold accounts wake +3649|75499|3021|4|40|58979.60|0.00|0.08|R|F|1994-07-20|1994-08-30|1994-08-14|TAKE BACK RETURN|RAIL|luffy somas sleep quickly-- ironic de +3649|99669|9670|5|24|40047.84|0.05|0.03|A|F|1994-07-07|1994-08-20|1994-07-27|TAKE BACK RETURN|FOB|c accounts. quickly final theodo +3649|121063|1064|6|3|3252.18|0.10|0.04|A|F|1994-07-17|1994-08-10|1994-08-03|NONE|FOB|lly bold requests nag; +3650|135535|8049|1|30|47115.90|0.10|0.00|A|F|1992-08-26|1992-07-05|1992-09-01|DELIVER IN PERSON|SHIP|ckly special platelets. furiously sil +3650|127935|7936|2|43|84405.99|0.05|0.05|A|F|1992-09-07|1992-08-12|1992-09-10|COLLECT COD|TRUCK|gside of the quick +3650|1634|9135|3|1|1535.63|0.04|0.06|A|F|1992-06-23|1992-07-18|1992-07-08|NONE|REG AIR|re about the pinto +3650|62057|4564|4|31|31590.55|0.10|0.08|R|F|1992-06-15|1992-07-01|1992-07-15|DELIVER IN PERSON|RAIL| against the ironic accounts cajol +3650|186345|6346|5|19|27195.46|0.05|0.04|R|F|1992-08-29|1992-08-09|1992-09-21|DELIVER IN PERSON|AIR|y even forges. fluffily furious accounts +3650|93525|1053|6|27|41000.04|0.07|0.08|A|F|1992-07-03|1992-07-23|1992-07-13|COLLECT COD|MAIL|ular requests snooze fluffily regular pi +3650|69009|4022|7|43|42054.00|0.10|0.07|A|F|1992-06-25|1992-07-09|1992-07-22|DELIVER IN PERSON|RAIL|structions use caref +3651|18097|5601|1|20|20301.80|0.01|0.04|N|O|1998-06-10|1998-06-06|1998-06-23|NONE|SHIP|tect quickly among the r +3651|154336|1882|2|24|33367.92|0.09|0.04|N|O|1998-06-22|1998-07-17|1998-07-10|DELIVER IN PERSON|RAIL|excuses haggle according to th +3651|112460|7483|3|41|60370.86|0.00|0.05|N|O|1998-05-10|1998-07-09|1998-05-13|NONE|RAIL|blithely. furiously +3651|109126|4147|4|27|30648.24|0.05|0.03|N|O|1998-05-03|1998-06-30|1998-05-05|DELIVER IN PERSON|RAIL| sleep blithely furiously do +3652|179779|7331|1|24|44610.48|0.05|0.03|N|O|1997-06-07|1997-04-07|1997-06-12|COLLECT COD|MAIL|the final p +3652|136489|6490|2|37|56442.76|0.02|0.05|N|O|1997-05-11|1997-04-06|1997-06-05|COLLECT COD|MAIL|osits haggle carefu +3652|162640|189|3|39|66402.96|0.01|0.02|N|O|1997-03-10|1997-04-03|1997-03-21|NONE|REG AIR|y express instructions. un +3652|79671|4686|4|1|1650.67|0.01|0.04|N|O|1997-04-20|1997-05-03|1997-05-18|DELIVER IN PERSON|SHIP| bold dependencies sublate. r +3653|144753|2296|1|38|68314.50|0.08|0.05|A|F|1994-06-26|1994-05-13|1994-07-13|NONE|REG AIR|ainst the +3653|63021|8034|2|29|28536.58|0.07|0.01|A|F|1994-04-11|1994-06-11|1994-04-29|COLLECT COD|RAIL|ording to the special, final +3653|180579|3098|3|17|28212.69|0.09|0.03|R|F|1994-06-24|1994-06-02|1994-07-17|DELIVER IN PERSON|RAIL|gle slyly regular +3653|185220|257|4|9|11746.98|0.10|0.07|R|F|1994-04-03|1994-05-19|1994-04-10|COLLECT COD|FOB|slyly silent account +3653|187794|313|5|41|77153.39|0.08|0.01|A|F|1994-06-18|1994-05-18|1994-06-20|COLLECT COD|RAIL|onic packages affix sly +3653|42462|2463|6|9|12640.14|0.05|0.03|A|F|1994-07-21|1994-05-31|1994-08-17|NONE|MAIL|tes: blithely bo +3653|48442|947|7|2|2780.88|0.06|0.03|R|F|1994-06-02|1994-05-31|1994-06-29|NONE|FOB|n accounts. fina +3654|164675|9708|1|46|80024.82|0.08|0.05|A|F|1992-06-05|1992-08-19|1992-06-06|DELIVER IN PERSON|FOB|usly regular foxes. furio +3654|92688|2689|2|29|48739.72|0.07|0.06|A|F|1992-09-11|1992-07-20|1992-10-04|DELIVER IN PERSON|FOB|odolites detect. quickly r +3654|1676|6677|3|37|58373.79|0.07|0.05|A|F|1992-09-22|1992-07-20|1992-10-19|TAKE BACK RETURN|RAIL|unts doze bravely ab +3654|167246|7247|4|11|14445.64|0.08|0.00|A|F|1992-07-20|1992-07-30|1992-07-23|TAKE BACK RETURN|SHIP|quickly along the express, ironic req +3654|93515|3516|5|34|51289.34|0.04|0.00|R|F|1992-07-26|1992-08-26|1992-08-12|TAKE BACK RETURN|REG AIR| the quick +3654|106597|4128|6|20|32071.80|0.03|0.02|A|F|1992-07-30|1992-07-05|1992-08-05|COLLECT COD|SHIP|s sleep about the slyly +3654|172225|9777|7|45|58374.90|0.01|0.07|A|F|1992-09-15|1992-07-04|1992-09-20|DELIVER IN PERSON|FOB|sly ironic notornis nag slyly +3655|183811|1366|1|5|9474.05|0.03|0.04|R|F|1993-01-17|1992-12-31|1993-01-23|DELIVER IN PERSON|TRUCK|riously bold pinto be +3655|96652|1671|2|1|1648.65|0.10|0.06|R|F|1992-10-24|1992-12-18|1992-11-07|DELIVER IN PERSON|AIR|arefully slow pinto beans are +3655|29968|2471|3|35|66428.60|0.01|0.04|R|F|1992-12-20|1992-11-16|1993-01-15|TAKE BACK RETURN|MAIL|blithely even accounts! furiously regular +3655|71347|1348|4|35|46141.90|0.04|0.07|R|F|1992-10-17|1992-12-23|1992-10-28|COLLECT COD|MAIL|ng foxes cajole fluffily slyly final fo +3680|176451|1486|1|48|73317.60|0.00|0.06|R|F|1993-01-16|1993-01-23|1993-01-19|COLLECT COD|FOB|packages. quickly fluff +3680|4228|6729|2|41|46421.02|0.00|0.04|A|F|1993-01-06|1993-03-02|1993-01-08|NONE|FOB|iously ironic platelets in +3680|55001|7507|3|33|31548.00|0.09|0.08|R|F|1993-03-16|1993-02-19|1993-04-05|NONE|FOB|ts. ironic, fina +3681|105232|7743|1|35|43303.05|0.03|0.08|R|F|1992-07-31|1992-05-18|1992-08-07|COLLECT COD|FOB|lyly special pinto +3682|60637|3144|1|6|9585.78|0.07|0.02|N|O|1997-05-06|1997-04-04|1997-05-11|NONE|AIR|ronic deposits wake slyly. ca +3682|115598|5599|2|18|29044.62|0.06|0.06|N|O|1997-04-30|1997-03-21|1997-05-10|NONE|FOB|regular dependencies +3682|46639|1648|3|17|26955.71|0.03|0.05|N|O|1997-02-12|1997-04-04|1997-02-22|COLLECT COD|FOB|, ironic packages wake a +3682|56495|9001|4|30|43544.70|0.09|0.05|N|O|1997-04-16|1997-04-16|1997-04-29|NONE|MAIL|he requests cajole quickly pending package +3683|100842|3353|1|35|64499.40|0.05|0.03|A|F|1993-05-31|1993-04-17|1993-06-14|NONE|SHIP| the furiously expr +3683|48689|6202|2|41|67144.88|0.01|0.06|A|F|1993-03-26|1993-05-06|1993-04-09|NONE|TRUCK|ress instructions. slyly express a +3683|99314|4333|3|23|30206.13|0.00|0.08|R|F|1993-07-02|1993-05-16|1993-07-30|NONE|TRUCK|xpress accounts sleep slyly re +3684|125106|5107|1|48|54292.80|0.04|0.06|A|F|1993-08-20|1993-09-02|1993-09-10|DELIVER IN PERSON|REG AIR|its boost alongside +3684|45384|5385|2|6|7976.28|0.06|0.08|R|F|1993-08-09|1993-10-05|1993-09-06|DELIVER IN PERSON|FOB|he silent requests. packages sleep fu +3684|162500|49|3|19|29687.50|0.04|0.02|A|F|1993-10-19|1993-08-25|1993-11-02|COLLECT COD|FOB|e slyly carefully pending foxes. d +3684|134811|2351|4|13|23995.53|0.02|0.05|A|F|1993-07-23|1993-09-16|1993-08-06|NONE|TRUCK|ing, unusual pinto beans! thinly p +3685|46199|8704|1|37|42372.03|0.02|0.03|R|F|1992-03-11|1992-04-09|1992-04-05|DELIVER IN PERSON|TRUCK|ress attai +3685|57413|9919|2|7|9592.87|0.05|0.00|R|F|1992-05-16|1992-02-23|1992-05-17|DELIVER IN PERSON|FOB|sits. special asymptotes about the r +3685|133706|3707|3|38|66108.60|0.08|0.03|A|F|1992-05-17|1992-03-16|1992-06-06|TAKE BACK RETURN|TRUCK|thely unusual pack +3685|191626|6665|4|39|66987.18|0.10|0.05|R|F|1992-02-19|1992-04-06|1992-03-02|COLLECT COD|FOB|ic courts nag carefully after the +3685|55782|5783|5|37|64297.86|0.00|0.01|A|F|1992-03-02|1992-04-10|1992-03-04|NONE|FOB|. carefully sly requests are regular, regu +3686|121557|9094|1|7|11049.85|0.02|0.04|N|O|1998-07-15|1998-08-22|1998-07-30|DELIVER IN PERSON|TRUCK| furiously unusual accou +3686|199146|1666|2|38|47315.32|0.06|0.03|N|O|1998-09-04|1998-08-11|1998-09-19|DELIVER IN PERSON|AIR|y silent foxes! carefully ruthless cour +3686|44727|4728|3|31|51823.32|0.10|0.06|N|O|1998-09-09|1998-08-28|1998-10-09|COLLECT COD|MAIL|gle across the courts. furiously regu +3686|116078|8590|4|7|7658.49|0.10|0.01|N|O|1998-07-16|1998-09-02|1998-07-22|NONE|FOB|ake carefully carefully q +3687|144005|1548|1|32|33568.00|0.03|0.06|R|F|1993-05-07|1993-04-05|1993-05-25|DELIVER IN PERSON|AIR|deas cajole fo +3687|80501|3010|2|2|2963.00|0.00|0.08|R|F|1993-02-23|1993-03-25|1993-03-11|NONE|TRUCK| express requests. slyly regular depend +3687|173664|6182|3|10|17376.60|0.01|0.02|A|F|1993-02-11|1993-03-22|1993-03-09|NONE|FOB|ing pinto beans +3687|161643|6676|4|19|32388.16|0.02|0.05|A|F|1993-05-14|1993-04-24|1993-06-01|DELIVER IN PERSON|MAIL|ly final asymptotes according to t +3687|118039|5573|5|31|32767.93|0.07|0.08|A|F|1993-05-28|1993-03-20|1993-06-05|DELIVER IN PERSON|FOB|foxes cajole quickly about the furiously f +3712|140013|5042|1|27|28431.27|0.01|0.05|R|F|1992-02-01|1992-02-26|1992-03-02|TAKE BACK RETURN|SHIP|ctions. even accounts haggle alongside +3712|184915|2470|2|13|25998.83|0.03|0.03|R|F|1992-04-30|1992-02-11|1992-05-30|DELIVER IN PERSON|FOB|s around the furiously ironic account +3712|63923|8936|3|44|83024.48|0.01|0.01|A|F|1992-03-26|1992-02-19|1992-04-18|TAKE BACK RETURN|FOB|ously permanently regular req +3712|147022|4565|4|38|40622.76|0.01|0.06|A|F|1992-01-15|1992-03-24|1992-01-27|COLLECT COD|RAIL|s nag carefully-- even, reg +3713|111310|3822|1|41|54173.71|0.07|0.08|N|O|1998-05-11|1998-07-17|1998-05-22|COLLECT COD|RAIL|eposits wake blithely fina +3713|176914|9432|2|19|37827.29|0.04|0.04|N|O|1998-06-25|1998-07-24|1998-07-08|DELIVER IN PERSON|AIR|tructions serve blithely around the furi +3713|179662|9663|3|19|33091.54|0.03|0.02|N|O|1998-05-19|1998-07-06|1998-06-09|DELIVER IN PERSON|REG AIR|quests cajole careful +3713|168912|8913|4|45|89140.95|0.06|0.04|N|O|1998-06-15|1998-07-30|1998-07-14|DELIVER IN PERSON|MAIL|al pinto beans affix after the slyly +3713|89165|4182|5|46|53091.36|0.10|0.04|N|O|1998-08-22|1998-06-27|1998-08-31|NONE|MAIL|totes. carefully special theodolites s +3713|181492|4011|6|29|45631.21|0.09|0.03|N|O|1998-08-04|1998-06-13|1998-08-21|NONE|RAIL|the regular dugouts wake furiously sil +3713|129891|9892|7|14|26892.46|0.04|0.00|N|O|1998-07-19|1998-07-02|1998-07-28|DELIVER IN PERSON|SHIP|eposits impress according +3714|68433|3446|1|13|18218.59|0.07|0.03|N|O|1998-06-26|1998-06-17|1998-07-07|TAKE BACK RETURN|REG AIR| the furiously final +3714|145675|8190|2|14|24089.38|0.02|0.05|N|O|1998-05-30|1998-06-30|1998-05-31|DELIVER IN PERSON|RAIL|ending ideas. thinly unusual theodo +3714|158877|8878|3|16|30973.92|0.00|0.02|N|O|1998-05-25|1998-07-07|1998-06-17|TAKE BACK RETURN|AIR|ccounts cajole fu +3714|29287|4292|4|44|53516.32|0.04|0.02|N|O|1998-07-18|1998-07-10|1998-07-22|DELIVER IN PERSON|AIR|s. quickly ironic dugouts sublat +3715|96625|4153|1|13|21081.06|0.00|0.03|N|O|1996-05-11|1996-04-25|1996-06-09|TAKE BACK RETURN|SHIP|e quickly ironic +3715|168955|3988|2|16|32383.20|0.01|0.06|N|O|1996-06-28|1996-04-22|1996-06-30|TAKE BACK RETURN|AIR|usly regular pearls haggle final packages +3715|11629|1630|3|37|57002.94|0.05|0.02|N|O|1996-05-03|1996-04-30|1996-05-17|NONE|SHIP|ut the carefully expr +3716|31701|4205|1|10|16327.00|0.09|0.04|N|O|1997-12-02|1997-11-09|1997-12-14|TAKE BACK RETURN|SHIP|ts. quickly sly ideas slee +3716|193081|3082|2|39|45789.12|0.02|0.08|N|O|1997-11-27|1997-10-23|1997-12-24|COLLECT COD|REG AIR|even deposits. +3716|106882|6883|3|42|79332.96|0.02|0.08|N|O|1997-12-03|1997-10-12|1997-12-15|NONE|TRUCK| of the pend +3716|164383|1932|4|19|27500.22|0.05|0.08|N|O|1997-09-25|1997-10-18|1997-10-12|NONE|TRUCK|arefully unusual accounts. flu +3716|181638|4157|5|25|42990.75|0.06|0.05|N|O|1997-11-23|1997-10-24|1997-11-24|COLLECT COD|REG AIR|fully unusual accounts. carefu +3717|152273|7304|1|45|59637.15|0.07|0.04|N|O|1998-08-09|1998-08-18|1998-08-14|TAKE BACK RETURN|TRUCK|ests wake whithout the blithely final pl +3717|52014|9530|2|3|2898.03|0.01|0.07|N|O|1998-06-09|1998-07-31|1998-06-14|NONE|REG AIR|nside the regular packages sleep +3717|195221|5222|3|45|59229.90|0.05|0.08|N|O|1998-09-19|1998-07-22|1998-09-28|DELIVER IN PERSON|MAIL|s the blithely unu +3717|68318|3331|4|5|6431.55|0.06|0.03|N|O|1998-09-02|1998-08-20|1998-09-26|TAKE BACK RETURN|AIR|quickly among +3717|15272|5273|5|7|8310.89|0.09|0.02|N|O|1998-09-08|1998-07-18|1998-09-10|DELIVER IN PERSON|RAIL| after the packa +3717|63587|8600|6|38|58922.04|0.01|0.07|N|O|1998-07-10|1998-07-08|1998-07-29|COLLECT COD|RAIL|ly about the car +3717|105267|5268|7|28|35623.28|0.03|0.01|N|O|1998-07-25|1998-08-12|1998-08-16|COLLECT COD|RAIL|ts sleep q +3718|20775|5780|1|40|67830.80|0.01|0.04|N|O|1996-11-20|1996-12-17|1996-12-03|DELIVER IN PERSON|MAIL|out the express deposits +3718|162663|212|2|16|27610.56|0.02|0.06|N|O|1996-11-11|1996-12-25|1996-11-12|COLLECT COD|TRUCK|slyly even accounts. blithely special acco +3718|69553|7072|3|8|12180.40|0.05|0.03|N|O|1996-12-06|1996-12-06|1996-12-15|TAKE BACK RETURN|AIR| the even deposits sleep carefully b +3719|21430|8937|1|35|47300.05|0.06|0.08|N|O|1997-06-11|1997-04-03|1997-06-15|TAKE BACK RETURN|TRUCK|ly foxes. pending braids haggle furio +3719|173998|6516|2|2|4143.98|0.02|0.08|N|O|1997-02-17|1997-04-25|1997-03-03|NONE|REG AIR|ccounts boost carefu +3719|181502|6539|3|12|19002.00|0.05|0.06|N|O|1997-06-10|1997-05-04|1997-07-09|TAKE BACK RETURN|REG AIR|grate according to the +3719|89266|6791|4|13|16318.38|0.02|0.00|N|O|1997-05-03|1997-04-16|1997-05-27|TAKE BACK RETURN|SHIP|iously. regular dep +3719|77643|151|5|19|30792.16|0.06|0.08|N|O|1997-05-22|1997-03-20|1997-06-12|COLLECT COD|TRUCK|he regular ideas integrate acros +3719|141336|6365|6|43|59225.19|0.03|0.08|N|O|1997-05-08|1997-04-15|1997-06-06|COLLECT COD|RAIL|the furiously special pinto bean +3719|18433|8434|7|16|21622.88|0.10|0.01|N|O|1997-03-02|1997-03-18|1997-03-28|TAKE BACK RETURN|RAIL| express asymptotes. ir +3744|194756|9795|1|30|55522.50|0.05|0.06|A|F|1992-05-07|1992-02-12|1992-05-17|TAKE BACK RETURN|FOB|nts among +3745|136294|1321|1|18|23945.22|0.01|0.05|A|F|1993-10-17|1993-11-16|1993-11-13|DELIVER IN PERSON|SHIP| slyly bold pinto beans according to +3746|164012|4013|1|37|39812.37|0.07|0.00|A|F|1994-12-29|1994-10-25|1995-01-03|COLLECT COD|FOB|e of the careful +3746|143595|8624|2|28|45880.52|0.06|0.08|R|F|1994-09-20|1994-10-21|1994-09-27|DELIVER IN PERSON|FOB|s after the even, special requests +3746|187888|7889|3|3|5927.64|0.10|0.01|R|F|1994-11-03|1994-12-10|1994-11-12|NONE|MAIL| the silent ideas cajole carefully +3746|27486|2491|4|11|15548.28|0.00|0.05|R|F|1994-10-02|1994-11-19|1994-10-10|COLLECT COD|SHIP| ironic theodolites are among th +3747|140559|8102|1|42|67181.10|0.05|0.05|N|O|1996-11-10|1996-10-19|1996-11-19|TAKE BACK RETURN|REG AIR|y. blithely fina +3747|169914|9915|2|33|65469.03|0.01|0.03|N|O|1996-10-14|1996-11-12|1996-11-11|NONE|REG AIR| regular p +3747|138552|8553|3|30|47716.50|0.00|0.07|N|O|1996-12-16|1996-11-15|1996-12-17|NONE|RAIL|! furiously f +3747|32970|480|4|21|39962.37|0.00|0.06|N|O|1996-11-18|1996-09-23|1996-11-26|TAKE BACK RETURN|AIR|ithely bold orbits mold furiously blit +3747|125802|827|5|32|58489.60|0.08|0.05|N|O|1996-09-10|1996-11-04|1996-10-10|DELIVER IN PERSON|MAIL|quests shall h +3747|153991|3992|6|14|28629.86|0.08|0.07|N|O|1996-11-03|1996-10-29|1996-11-06|TAKE BACK RETURN|AIR|packages cajole carefu +3747|117993|505|7|23|46252.77|0.00|0.04|N|O|1996-11-08|1996-11-10|1996-12-03|NONE|REG AIR|kages are ironic +3748|103539|6050|1|12|18510.36|0.06|0.01|N|O|1998-04-17|1998-04-15|1998-05-12|NONE|AIR|old reques +3748|164717|7234|2|24|42761.04|0.08|0.04|N|O|1998-06-07|1998-05-02|1998-06-21|DELIVER IN PERSON|TRUCK|al deposits. blithely +3748|196085|3643|3|19|22440.52|0.05|0.01|N|O|1998-04-23|1998-05-17|1998-05-23|COLLECT COD|RAIL|pinto beans run carefully quic +3748|186693|1730|4|5|8898.45|0.00|0.07|N|O|1998-06-29|1998-05-06|1998-07-12|DELIVER IN PERSON|MAIL| regular accounts sleep quickly-- furious +3748|146699|9214|5|21|36659.49|0.07|0.08|N|O|1998-03-30|1998-04-07|1998-04-05|TAKE BACK RETURN|MAIL|fix carefully furiously express ideas. furi +3749|172888|5406|1|11|21569.68|0.07|0.05|N|O|1995-06-25|1995-05-23|1995-07-10|TAKE BACK RETURN|RAIL|egular requests along the +3749|128102|3127|2|9|10170.90|0.08|0.05|A|F|1995-04-23|1995-04-18|1995-04-26|NONE|REG AIR|uses cajole blithely pla +3749|198854|3893|3|31|60538.35|0.00|0.05|N|F|1995-06-11|1995-05-20|1995-06-27|COLLECT COD|REG AIR|s. foxes sleep slyly unusual grouc +3749|130302|5329|4|7|9326.10|0.07|0.06|A|F|1995-03-31|1995-04-05|1995-04-11|NONE|TRUCK|he slyly ironic packages +3749|182309|4828|5|14|19478.20|0.02|0.00|N|F|1995-06-11|1995-05-19|1995-07-11|DELIVER IN PERSON|SHIP|press instruc +3749|53716|1232|6|10|16697.10|0.10|0.03|N|O|1995-06-24|1995-05-24|1995-07-18|COLLECT COD|SHIP|essly. regular pi +3750|133299|5813|1|37|49294.73|0.04|0.03|N|O|1995-07-08|1995-07-28|1995-07-28|DELIVER IN PERSON|REG AIR|usly busy account +3750|151799|1800|2|33|61076.07|0.05|0.03|N|O|1995-06-27|1995-06-20|1995-07-03|TAKE BACK RETURN|REG AIR|theodolites haggle. slyly pendin +3750|79370|1878|3|20|26987.40|0.09|0.05|N|F|1995-06-17|1995-06-06|1995-06-28|TAKE BACK RETURN|REG AIR|ss, ironic requests! fur +3750|165817|3366|4|33|62132.73|0.04|0.03|N|F|1995-06-15|1995-06-04|1995-06-29|COLLECT COD|RAIL|ep blithely according to the flu +3750|82651|5160|5|1|1633.65|0.05|0.01|N|O|1995-07-24|1995-06-25|1995-08-21|DELIVER IN PERSON|REG AIR|l dolphins against the slyly +3750|112383|4895|6|47|65582.86|0.01|0.08|R|F|1995-05-11|1995-06-13|1995-06-02|TAKE BACK RETURN|FOB|slowly regular accounts. blithely ev +3751|171747|4265|1|37|67293.38|0.00|0.04|R|F|1994-04-30|1994-05-30|1994-05-30|NONE|REG AIR|ly express courts +3751|140684|3199|2|32|55189.76|0.03|0.05|R|F|1994-05-05|1994-07-02|1994-06-02|COLLECT COD|MAIL|rthogs could have to slee +3751|64236|9249|3|45|54010.35|0.08|0.06|R|F|1994-05-27|1994-06-19|1994-06-14|NONE|RAIL|according to +3751|13891|1395|4|39|70390.71|0.07|0.01|A|F|1994-08-16|1994-07-11|1994-09-12|COLLECT COD|TRUCK|refully according to the iro +3751|57100|2111|5|12|12685.20|0.02|0.03|A|F|1994-08-09|1994-06-30|1994-08-12|TAKE BACK RETURN|TRUCK|accounts wake furious +3751|75535|550|6|39|58910.67|0.02|0.08|R|F|1994-08-01|1994-06-01|1994-08-26|COLLECT COD|SHIP|to beans. pending, express packages c +3776|2128|9629|1|39|40174.68|0.05|0.01|R|F|1993-01-03|1993-02-05|1993-01-08|COLLECT COD|FOB|yly blithely pending packages +3776|158157|3188|2|14|17012.10|0.06|0.08|R|F|1992-12-30|1993-02-12|1993-01-27|DELIVER IN PERSON|RAIL|y special ideas. express packages pr +3776|140995|3510|3|49|99763.51|0.01|0.08|R|F|1992-12-03|1993-02-16|1992-12-28|TAKE BACK RETURN|RAIL|equests. final, thin grouches +3776|91553|9081|4|49|75682.95|0.08|0.05|A|F|1993-02-11|1993-01-06|1993-02-27|COLLECT COD|MAIL|es: careful warthogs haggle fluffi +3777|99495|7023|1|11|16439.39|0.02|0.03|A|F|1994-04-09|1994-06-05|1994-04-14|NONE|FOB|ld ideas. even theodolites +3777|7436|4937|2|10|13434.30|0.03|0.01|R|F|1994-05-22|1994-05-29|1994-06-13|COLLECT COD|RAIL|le. ironic depths a +3777|165409|5410|3|18|26539.20|0.10|0.06|R|F|1994-05-04|1994-05-23|1994-05-22|COLLECT COD|REG AIR|eful packages use slyly: even deposits +3777|17130|7131|4|35|36649.55|0.10|0.04|A|F|1994-05-25|1994-05-26|1994-06-13|COLLECT COD|AIR|s. carefully express asymptotes accordi +3777|97412|9922|5|14|19731.74|0.04|0.05|R|F|1994-05-06|1994-06-24|1994-05-31|NONE|TRUCK|ording to the iro +3778|56669|1680|1|21|34138.86|0.01|0.06|R|F|1993-05-27|1993-07-10|1993-06-03|COLLECT COD|REG AIR|ts. blithely special theodoli +3778|28589|8590|2|32|48562.56|0.09|0.00|A|F|1993-06-22|1993-08-18|1993-07-03|TAKE BACK RETURN|MAIL|tes affix carefully above the +3778|93436|5946|3|41|58606.63|0.05|0.00|R|F|1993-06-21|1993-07-27|1993-07-15|COLLECT COD|FOB|e the furiously ironi +3778|168841|6390|4|28|53475.52|0.03|0.05|R|F|1993-08-18|1993-07-10|1993-09-06|TAKE BACK RETURN|REG AIR|y silent orbits print carefully against +3778|97021|4549|5|28|28504.56|0.01|0.06|R|F|1993-09-02|1993-08-08|1993-10-02|DELIVER IN PERSON|FOB|r deposits. theodol +3778|19451|4454|6|26|35631.70|0.00|0.01|A|F|1993-09-24|1993-07-06|1993-10-22|NONE|TRUCK| against the fluffily +3778|104793|4794|7|49|88091.71|0.02|0.04|A|F|1993-06-13|1993-08-08|1993-07-04|DELIVER IN PERSON|MAIL|ans. furiously +3779|45738|3251|1|28|47144.44|0.04|0.05|N|O|1997-05-06|1997-04-01|1997-05-18|TAKE BACK RETURN|AIR|s. close requests sleep +3779|109004|1515|2|5|5065.00|0.07|0.03|N|O|1997-01-07|1997-03-26|1997-02-05|DELIVER IN PERSON|AIR|heodolites. slyly regular a +3780|126173|6174|1|25|29979.25|0.08|0.04|N|O|1996-06-27|1996-07-02|1996-07-22|NONE|AIR|l, unusual +3780|189496|7051|2|40|63419.60|0.10|0.04|N|O|1996-06-06|1996-05-29|1996-07-01|COLLECT COD|SHIP|gular deposits-- furiously regular +3781|13185|3186|1|48|52712.64|0.02|0.06|N|O|1996-08-22|1996-08-13|1996-09-15|NONE|REG AIR|equests may cajole careful +3781|187496|7497|2|39|61756.11|0.10|0.00|N|O|1996-08-20|1996-08-16|1996-09-01|DELIVER IN PERSON|REG AIR|unts are carefully. ir +3781|29895|9896|3|17|31023.13|0.01|0.03|N|O|1996-06-23|1996-09-04|1996-07-19|TAKE BACK RETURN|REG AIR|. theodolite +3781|30810|5817|4|15|26112.15|0.05|0.00|N|O|1996-08-23|1996-08-08|1996-09-06|TAKE BACK RETURN|AIR| carefully blithe +3781|15001|2505|5|23|21068.00|0.09|0.08|N|O|1996-09-05|1996-08-18|1996-09-27|DELIVER IN PERSON|SHIP|pendencies are b +3782|26844|4351|1|29|51354.36|0.01|0.07|N|O|1996-09-17|1996-10-03|1996-10-07|DELIVER IN PERSON|REG AIR|quickly unusual pinto beans. carefully fina +3782|152897|5413|2|10|19498.90|0.03|0.05|N|O|1996-09-07|1996-11-19|1996-10-04|COLLECT COD|FOB|ven pinto b +3782|135201|5202|3|30|37086.00|0.06|0.06|N|O|1996-12-19|1996-10-31|1997-01-14|TAKE BACK RETURN|MAIL|slyly even pinto beans hag +3782|116305|3839|4|34|44924.20|0.02|0.06|N|O|1996-11-07|1996-10-22|1996-11-19|DELIVER IN PERSON|MAIL|gage after the even +3782|129239|6776|5|40|50729.20|0.09|0.04|N|O|1996-12-16|1996-11-22|1997-01-01|COLLECT COD|AIR|s instructions. regular accou +3783|166578|1611|1|36|59204.52|0.04|0.08|R|F|1993-12-17|1994-02-26|1994-01-03|DELIVER IN PERSON|SHIP|ites haggle among the carefully unusu +3783|72856|5364|2|36|65838.60|0.02|0.02|R|F|1994-03-02|1994-02-09|1994-03-15|COLLECT COD|TRUCK|egular accounts +3783|84967|7476|3|50|97598.00|0.04|0.01|R|F|1994-03-14|1994-01-09|1994-04-10|DELIVER IN PERSON|FOB|he furiously regular deposits. +3783|26279|1284|4|37|44594.99|0.10|0.05|R|F|1993-12-09|1994-02-17|1993-12-30|COLLECT COD|REG AIR|ing to the ideas. regular accounts de +3808|42716|5221|1|28|46443.88|0.02|0.01|R|F|1994-05-27|1994-06-18|1994-06-22|TAKE BACK RETURN|FOB|lly final accounts alo +3808|126319|1344|2|47|63229.57|0.04|0.08|R|F|1994-06-12|1994-06-03|1994-07-02|COLLECT COD|TRUCK|fully for the quickly final deposits: flu +3808|30291|292|3|45|54958.05|0.00|0.03|R|F|1994-07-03|1994-05-29|1994-07-14|TAKE BACK RETURN|REG AIR| carefully special +3808|99468|9469|4|34|49893.64|0.07|0.04|R|F|1994-08-13|1994-07-22|1994-08-31|DELIVER IN PERSON|FOB| pearls will have to +3808|154755|2301|5|29|52482.75|0.08|0.03|A|F|1994-06-22|1994-05-26|1994-07-06|TAKE BACK RETURN|TRUCK| deposits across the pac +3808|167127|2160|6|44|52541.28|0.06|0.06|A|F|1994-06-07|1994-06-04|1994-06-25|NONE|REG AIR|the blithely regular foxes. even, final +3809|190322|2842|1|17|24009.44|0.10|0.04|N|O|1996-08-14|1996-07-05|1996-09-04|DELIVER IN PERSON|FOB|es detect furiously sil +3809|132963|2964|2|32|63870.72|0.01|0.02|N|O|1996-07-03|1996-06-01|1996-07-25|COLLECT COD|SHIP|xcuses would boost against the fluffily eve +3809|104789|4790|3|46|82513.88|0.10|0.06|N|O|1996-08-20|1996-06-01|1996-08-24|TAKE BACK RETURN|TRUCK|l asymptotes. special +3809|177249|7250|4|43|57028.32|0.00|0.04|N|O|1996-05-06|1996-06-22|1996-06-05|TAKE BACK RETURN|TRUCK|yly ironic decoys; regular, iron +3810|183458|1013|1|49|75531.05|0.05|0.01|R|F|1992-11-27|1992-10-30|1992-12-16|COLLECT COD|AIR|cajole. fur +3810|168724|1241|2|18|32268.96|0.01|0.04|A|F|1992-11-28|1992-11-15|1992-12-27|DELIVER IN PERSON|SHIP|s. furiously careful deposi +3810|136788|9302|3|41|74815.98|0.08|0.08|A|F|1992-10-26|1992-10-27|1992-11-05|COLLECT COD|SHIP|l requests boost slyly along the slyl +3810|181036|3555|4|11|12287.33|0.06|0.04|A|F|1992-12-18|1992-12-11|1993-01-15|DELIVER IN PERSON|MAIL| the pending pinto beans. expr +3811|163383|5900|1|24|34713.12|0.04|0.02|N|O|1998-07-13|1998-05-16|1998-08-12|TAKE BACK RETURN|TRUCK|deposits. slyly regular accounts cajo +3811|165958|8475|2|2|4047.90|0.01|0.08|N|O|1998-06-16|1998-06-16|1998-06-23|NONE|MAIL|slyly fluff +3811|42469|7478|3|19|26817.74|0.02|0.06|N|O|1998-07-20|1998-06-14|1998-07-29|NONE|MAIL|s boost blithely furiou +3811|170416|2934|4|50|74320.50|0.08|0.03|N|O|1998-07-28|1998-07-06|1998-08-16|COLLECT COD|FOB|ts are slyly fluffy ideas. furiou +3811|181104|3623|5|23|27257.30|0.00|0.04|N|O|1998-08-13|1998-07-09|1998-08-29|COLLECT COD|AIR|nstructions sleep quickly. slyly final +3811|1635|6636|6|35|53782.05|0.04|0.07|N|O|1998-04-17|1998-06-30|1998-04-25|NONE|REG AIR|yly final dolphins? quickly ironic frets +3812|144641|2184|1|33|55626.12|0.00|0.05|N|O|1996-10-10|1996-10-05|1996-10-15|TAKE BACK RETURN|MAIL|posits engage. ironic, regular p +3812|172434|7469|2|33|49712.19|0.06|0.03|N|O|1996-10-05|1996-10-13|1996-10-22|TAKE BACK RETURN|MAIL|inal excuses d +3813|175506|5507|1|37|58515.50|0.05|0.04|N|O|1998-10-13|1998-09-19|1998-10-28|NONE|REG AIR|ravely special packages haggle p +3813|122720|7745|2|39|67966.08|0.05|0.00|N|O|1998-08-30|1998-08-12|1998-09-29|COLLECT COD|FOB|y ideas. final ideas about the sp +3814|130445|7985|1|7|10328.08|0.02|0.02|R|F|1995-05-01|1995-05-09|1995-05-28|DELIVER IN PERSON|REG AIR|es sleep furiou +3814|172629|5147|2|14|23822.68|0.01|0.00|R|F|1995-03-17|1995-05-10|1995-04-16|DELIVER IN PERSON|AIR|sits along the final, ironic deposit +3814|167125|9642|3|36|42916.32|0.06|0.02|N|O|1995-06-19|1995-04-18|1995-06-28|COLLECT COD|SHIP|beans cajole quickly sl +3814|65004|5005|4|20|19380.00|0.04|0.07|R|F|1995-02-23|1995-03-26|1995-03-04|DELIVER IN PERSON|SHIP|. doggedly ironic deposits will have to wa +3814|106211|1232|5|15|18258.15|0.03|0.04|N|O|1995-06-23|1995-03-25|1995-07-09|COLLECT COD|SHIP| carefully final deposits haggle slyly +3814|82129|7146|6|47|52222.64|0.09|0.05|A|F|1995-04-16|1995-04-03|1995-05-14|DELIVER IN PERSON|AIR|nusual requests. bli +3814|131307|3821|7|12|16059.60|0.10|0.01|R|F|1995-03-18|1995-04-16|1995-03-20|TAKE BACK RETURN|REG AIR|ages cajole. packages haggle. final +3815|76048|8556|1|3|3072.12|0.07|0.00|N|O|1997-11-16|1997-11-15|1997-11-30|NONE|FOB|egular, express ideas. ironic, final dep +3815|129840|2353|2|11|20568.24|0.02|0.04|N|O|1997-11-01|1997-11-05|1997-11-27|COLLECT COD|TRUCK|sleep blithe +3840|186402|8921|1|45|66978.00|0.02|0.08|N|O|1998-10-31|1998-09-19|1998-11-30|DELIVER IN PERSON|TRUCK|o beans are. carefully final courts x +3840|45522|531|2|12|17610.24|0.04|0.07|N|O|1998-10-02|1998-08-19|1998-10-20|TAKE BACK RETURN|RAIL|xpress pinto beans. accounts a +3840|72943|2944|3|45|86217.30|0.02|0.05|N|O|1998-10-12|1998-10-12|1998-10-28|TAKE BACK RETURN|FOB|onic, even packages are. pe +3840|147247|7248|4|41|53063.84|0.07|0.02|N|O|1998-07-21|1998-10-08|1998-08-01|TAKE BACK RETURN|MAIL| nag slyly? slyly pending accounts +3840|172923|5441|5|7|13971.44|0.09|0.08|N|O|1998-09-17|1998-09-20|1998-10-14|DELIVER IN PERSON|MAIL|. furiously final gifts sleep carefully pin +3840|106112|6113|6|33|36897.63|0.10|0.02|N|O|1998-07-29|1998-10-06|1998-08-04|DELIVER IN PERSON|SHIP|hely silent deposits w +3841|156889|9405|1|1|1945.88|0.06|0.03|A|F|1994-10-10|1994-11-12|1994-10-21|DELIVER IN PERSON|AIR| boost even re +3841|20882|5887|2|31|55889.28|0.09|0.03|A|F|1995-01-24|1994-11-25|1995-02-20|TAKE BACK RETURN|SHIP|n theodolites shall promise carefully. qui +3841|151821|4337|3|40|74912.80|0.06|0.02|A|F|1995-02-02|1994-11-30|1995-02-14|TAKE BACK RETURN|MAIL|its. quickly regular ideas nag carefully +3841|49764|9765|4|9|15423.84|0.10|0.07|A|F|1994-11-21|1994-12-26|1994-11-26|NONE|FOB|s according to the courts shall nag s +3841|175794|5795|5|3|5609.37|0.04|0.02|R|F|1994-10-24|1994-12-07|1994-11-09|COLLECT COD|FOB|foxes integrate +3841|162372|9921|6|48|68849.76|0.03|0.00|R|F|1994-11-23|1994-11-22|1994-12-01|DELIVER IN PERSON|FOB| according to the regular, +3842|161893|9442|1|28|54736.92|0.05|0.07|A|F|1992-06-17|1992-06-03|1992-06-24|DELIVER IN PERSON|TRUCK|s excuses thrash carefully. +3842|121783|6808|2|21|37900.38|0.07|0.05|R|F|1992-07-15|1992-06-02|1992-07-21|NONE|RAIL|r pinto be +3842|193009|8048|3|28|30856.00|0.00|0.00|A|F|1992-06-20|1992-05-22|1992-07-13|DELIVER IN PERSON|MAIL|lly alongside of the +3842|87373|4898|4|15|20405.55|0.07|0.01|A|F|1992-06-26|1992-06-23|1992-07-09|COLLECT COD|MAIL|ave packages are slyl +3842|67312|4831|5|13|16631.03|0.09|0.02|R|F|1992-04-13|1992-06-22|1992-05-11|COLLECT COD|RAIL|t blithely. busily regular accounts alon +3842|106971|4502|6|24|47471.28|0.08|0.08|R|F|1992-08-05|1992-06-29|1992-08-16|TAKE BACK RETURN|MAIL|phins are quickly +3843|14732|4733|1|7|11527.11|0.10|0.03|N|O|1997-02-13|1997-02-21|1997-02-20|TAKE BACK RETURN|SHIP|slyly even instructions. furiously eve +3843|484|2985|2|30|41534.40|0.01|0.05|N|O|1997-02-14|1997-03-25|1997-03-13|DELIVER IN PERSON|AIR| wake. slyly even packages boost +3844|134522|7036|1|2|3113.04|0.03|0.07|R|F|1995-02-24|1995-02-03|1995-03-18|TAKE BACK RETURN|AIR|es haggle final acco +3844|101965|6986|2|5|9834.80|0.10|0.03|R|F|1995-04-29|1995-02-24|1995-05-05|TAKE BACK RETURN|RAIL| unwind quickly about the pending, i +3845|33809|3810|1|44|76683.20|0.01|0.08|A|F|1992-07-20|1992-07-15|1992-07-24|DELIVER IN PERSON|REG AIR|s haggle among the fluffily regula +3845|23875|1382|2|16|28781.92|0.09|0.05|A|F|1992-08-08|1992-06-08|1992-08-26|DELIVER IN PERSON|SHIP|ely bold ideas use. ex +3845|58967|6483|3|17|32741.32|0.08|0.01|A|F|1992-06-12|1992-07-05|1992-06-26|TAKE BACK RETURN|RAIL|counts haggle. reg +3845|45398|407|4|1|1343.39|0.04|0.05|R|F|1992-05-21|1992-06-07|1992-06-17|COLLECT COD|REG AIR| blithely ironic t +3845|195390|5391|5|27|40105.53|0.00|0.05|R|F|1992-08-20|1992-07-17|1992-09-02|COLLECT COD|REG AIR|kages. care +3845|104773|7284|6|30|53333.10|0.09|0.06|R|F|1992-08-21|1992-07-07|1992-08-25|COLLECT COD|FOB|counts do wake blithely. ironic requests +3846|60152|2659|1|15|16682.25|0.06|0.03|N|O|1998-02-17|1998-04-27|1998-02-21|NONE|REG AIR|uternes. carefully even +3846|170299|300|2|30|41078.70|0.08|0.07|N|O|1998-05-01|1998-03-12|1998-05-20|TAKE BACK RETURN|FOB|deposits according to the fur +3846|14707|2211|3|49|79463.30|0.08|0.07|N|O|1998-02-14|1998-03-22|1998-02-17|DELIVER IN PERSON|RAIL|efully even packages against the blithe +3846|164058|1607|4|33|37027.65|0.05|0.00|N|O|1998-05-12|1998-03-14|1998-05-14|DELIVER IN PERSON|TRUCK|s instructions are. fu +3847|188290|8291|1|7|9648.03|0.08|0.00|A|F|1993-05-06|1993-06-06|1993-05-22|COLLECT COD|MAIL| about the blithely daring Tiresias. fl +3872|180331|5368|1|28|39517.24|0.10|0.04|N|O|1996-11-05|1996-11-10|1996-11-24|DELIVER IN PERSON|REG AIR|t after the carefully ironic excuses. f +3872|16635|1638|2|38|58961.94|0.04|0.05|N|O|1996-10-18|1996-12-03|1996-11-15|TAKE BACK RETURN|AIR|iously against the ironic, unusual a +3872|168467|6016|3|18|27638.28|0.07|0.07|N|O|1996-12-25|1996-10-24|1997-01-08|TAKE BACK RETURN|SHIP|s. regular, brave accounts sleep blith +3872|10643|644|4|41|63699.24|0.07|0.03|N|O|1996-11-23|1996-11-12|1996-12-03|COLLECT COD|REG AIR|ly regular epitaphs boost +3872|69266|4279|5|42|51880.92|0.03|0.00|N|O|1997-01-03|1996-10-12|1997-01-16|COLLECT COD|MAIL|s the furio +3872|139604|7144|6|40|65744.00|0.07|0.05|N|O|1997-01-02|1996-10-29|1997-01-14|NONE|REG AIR|nts? regularly ironic ex +3873|67790|5309|1|19|33398.01|0.04|0.04|N|O|1998-05-15|1998-05-10|1998-05-17|NONE|FOB|y final ac +3873|144960|9989|2|44|88218.24|0.05|0.05|N|O|1998-07-23|1998-05-22|1998-08-14|COLLECT COD|AIR|yly even platelets wake. +3873|139267|1781|3|29|37881.54|0.01|0.04|N|O|1998-06-22|1998-05-20|1998-07-05|COLLECT COD|REG AIR|olphins af +3874|169193|4226|1|21|26505.99|0.09|0.08|R|F|1993-06-19|1993-07-20|1993-07-08|DELIVER IN PERSON|SHIP| requests cajole fluff +3874|18904|3907|2|48|87499.20|0.06|0.07|R|F|1993-06-13|1993-07-20|1993-06-20|NONE|RAIL| ideas throughout +3875|80973|8498|1|24|46895.28|0.02|0.08|N|O|1997-10-15|1997-11-27|1997-11-09|COLLECT COD|AIR|ecial packages. +3875|112716|5228|2|49|84706.79|0.04|0.04|N|O|1997-10-18|1997-10-13|1997-10-19|NONE|MAIL|sleep furiously about the deposits. quickl +3876|140105|2620|1|12|13741.20|0.06|0.07|N|O|1996-09-16|1996-10-23|1996-10-05|TAKE BACK RETURN|REG AIR|y above the pending tithes. blithely ironi +3876|139212|1726|2|37|46294.77|0.00|0.03|N|O|1996-11-30|1996-10-18|1996-12-18|DELIVER IN PERSON|AIR|t dependencies. blithely final packages u +3876|126650|6651|3|41|68742.65|0.02|0.04|N|O|1996-10-15|1996-10-17|1996-10-19|NONE|AIR| quickly blit +3877|49774|2279|1|12|20685.24|0.06|0.01|R|F|1993-05-30|1993-08-09|1993-06-24|TAKE BACK RETURN|FOB|nal requests. even requests are. pac +3877|144635|2178|2|47|78942.61|0.05|0.00|A|F|1993-08-01|1993-08-16|1993-08-04|NONE|FOB|furiously quick requests nag along the theo +3877|79690|7212|3|44|73466.36|0.09|0.00|A|F|1993-06-07|1993-07-15|1993-07-06|DELIVER IN PERSON|REG AIR|elets. quickly regular accounts caj +3877|147844|7845|4|36|68106.24|0.06|0.01|A|F|1993-07-27|1993-07-13|1993-08-11|DELIVER IN PERSON|AIR|lithely about the dogged ideas. ac +3877|4649|4650|5|41|63699.24|0.03|0.07|A|F|1993-06-30|1993-07-20|1993-07-01|DELIVER IN PERSON|FOB|integrate against the expres +3877|122502|2503|6|7|10671.50|0.04|0.08|R|F|1993-06-14|1993-07-09|1993-06-28|NONE|TRUCK|lar dolphins cajole silently +3878|199696|9697|1|6|10774.14|0.07|0.04|N|O|1997-06-21|1997-05-22|1997-07-01|COLLECT COD|FOB|s. regular instru +3878|87395|7396|2|13|17971.07|0.01|0.06|N|O|1997-06-08|1997-06-03|1997-06-25|TAKE BACK RETURN|TRUCK|leep ruthlessly about the carefu +3878|40052|2557|3|20|19841.00|0.08|0.03|N|O|1997-06-20|1997-05-24|1997-07-20|TAKE BACK RETURN|MAIL|the furiously careful ideas cajole slyly sl +3878|151976|1977|4|20|40559.40|0.01|0.07|N|O|1997-07-13|1997-05-22|1997-07-20|NONE|FOB|about the carefully ironic pa +3879|125689|714|1|45|77160.60|0.10|0.08|N|O|1996-03-18|1996-01-03|1996-04-03|COLLECT COD|RAIL|ly according to the expr +3879|44020|1533|2|35|33740.70|0.00|0.07|N|O|1995-12-08|1996-01-23|1995-12-28|TAKE BACK RETURN|MAIL|o beans. accounts cajole furiously. re +3904|37424|4934|1|22|29951.24|0.04|0.03|N|O|1998-02-02|1998-02-09|1998-02-10|TAKE BACK RETURN|REG AIR|structions cajole carefully. carefully f +3904|183753|1308|2|19|34898.25|0.09|0.01|N|O|1998-02-10|1998-02-13|1998-02-20|TAKE BACK RETURN|AIR| excuses sleep slyly according to th +3905|100739|8270|1|43|74808.39|0.07|0.08|A|F|1994-03-30|1994-02-18|1994-04-09|DELIVER IN PERSON|REG AIR|uses are care +3905|115915|8427|2|7|13516.37|0.03|0.00|R|F|1994-03-01|1994-02-19|1994-03-11|DELIVER IN PERSON|AIR|ully furiously furious packag +3905|169943|4976|3|6|12077.64|0.07|0.02|R|F|1994-04-07|1994-03-07|1994-04-21|DELIVER IN PERSON|RAIL|ow furiously. deposits wake ironic +3906|152987|5503|1|42|85679.16|0.00|0.04|R|F|1992-09-03|1992-07-22|1992-09-04|COLLECT COD|RAIL|jole blithely after the furiously regular +3906|39340|4347|2|50|63967.00|0.01|0.07|R|F|1992-09-24|1992-08-24|1992-09-29|NONE|MAIL|ke slyly. stealt +3906|179655|4690|3|15|26019.75|0.06|0.02|R|F|1992-07-30|1992-08-26|1992-08-02|TAKE BACK RETURN|FOB|dependencies at the +3906|58264|8265|4|36|44001.36|0.08|0.08|A|F|1992-08-07|1992-08-08|1992-08-24|NONE|SHIP|y. ironic deposits haggle sl +3907|111784|4296|1|41|73626.98|0.06|0.02|A|F|1992-09-13|1992-10-23|1992-09-29|COLLECT COD|MAIL|ackages wake along the carefully regul +3907|144491|2034|2|41|62955.09|0.03|0.00|A|F|1992-10-25|1992-10-17|1992-11-01|TAKE BACK RETURN|RAIL|s above the unusual ideas sleep furiousl +3907|51501|9017|3|45|65362.50|0.02|0.07|R|F|1992-09-21|1992-09-19|1992-10-18|COLLECT COD|REG AIR| about the regular pac +3907|175693|728|4|48|84897.12|0.05|0.07|A|F|1992-09-24|1992-10-16|1992-10-06|DELIVER IN PERSON|TRUCK|nt asymptotes lose across th +3907|61958|1959|5|22|42238.90|0.09|0.01|R|F|1992-09-20|1992-10-30|1992-09-29|TAKE BACK RETURN|TRUCK|ly. furiously unusual deposits use afte +3907|125062|2599|6|34|36960.04|0.02|0.02|R|F|1992-09-06|1992-10-08|1992-09-12|COLLECT COD|FOB| requests according to the slyly pending +3907|109234|4255|7|8|9945.84|0.10|0.01|A|F|1992-09-18|1992-10-29|1992-09-27|NONE|REG AIR|furiously final packages. +3908|91840|4350|1|50|91592.00|0.05|0.04|R|F|1993-06-19|1993-04-27|1993-07-05|DELIVER IN PERSON|MAIL| even accounts wake +3908|147084|7085|2|8|9048.64|0.06|0.03|A|F|1993-03-12|1993-04-13|1993-03-22|DELIVER IN PERSON|SHIP|r instructions was requests. ironically +3909|177914|5466|1|30|59757.30|0.03|0.07|N|O|1998-10-17|1998-10-14|1998-10-28|COLLECT COD|TRUCK|ly even deposits across the ironic notorni +3909|190896|5935|2|46|91396.94|0.03|0.01|N|O|1998-10-08|1998-10-15|1998-10-24|NONE|FOB|the blithely unusual ideas +3910|138602|3629|1|10|16406.00|0.00|0.08|N|O|1996-10-18|1996-10-31|1996-11-14|DELIVER IN PERSON|FOB|tions boost furiously unusual e +3910|70782|5797|2|31|54336.18|0.05|0.03|N|O|1996-12-22|1996-11-14|1997-01-01|TAKE BACK RETURN|SHIP|ess instructions. +3910|19716|4719|3|6|9814.26|0.04|0.04|N|O|1996-12-08|1996-10-30|1996-12-31|DELIVER IN PERSON|MAIL|ly sly platelets are fluffily slyly si +3910|152611|5127|4|1|1663.61|0.03|0.06|N|O|1996-09-12|1996-10-21|1996-09-19|DELIVER IN PERSON|FOB|s sleep neve +3911|112842|5354|1|10|18548.40|0.07|0.06|N|O|1995-06-22|1995-05-30|1995-06-28|COLLECT COD|FOB|ss theodolites are blithely along t +3911|118861|6395|2|14|26318.04|0.08|0.05|R|F|1995-04-28|1995-05-03|1995-05-22|NONE|RAIL|e blithely brave depo +3911|91085|6104|3|12|12912.96|0.10|0.05|R|F|1995-04-04|1995-04-16|1995-04-10|COLLECT COD|FOB|uctions. blithely regula +3936|136372|6373|1|25|35209.25|0.06|0.03|N|O|1996-12-03|1996-12-27|1997-01-01|DELIVER IN PERSON|RAIL|gular requests nag quic +3936|187641|160|2|24|41487.36|0.10|0.07|N|O|1996-11-22|1997-01-01|1996-12-08|NONE|AIR|ns. accounts mold fl +3936|82065|7082|3|42|43976.52|0.00|0.07|N|O|1997-01-03|1997-01-29|1997-01-14|COLLECT COD|AIR|elets wake amo +3936|61051|8570|4|12|12144.60|0.06|0.05|N|O|1996-11-25|1997-01-09|1996-12-06|DELIVER IN PERSON|SHIP|ithely across the carefully brave req +3936|83519|3520|5|35|52587.85|0.02|0.08|N|O|1996-12-04|1997-01-06|1996-12-22|NONE|SHIP|lly ironic requ +3936|102029|4540|6|26|26806.52|0.01|0.02|N|O|1997-02-27|1997-01-16|1997-03-22|NONE|RAIL|quickly pen +3937|69439|4452|1|48|67604.64|0.10|0.02|N|O|1998-03-15|1998-02-22|1998-03-30|DELIVER IN PERSON|FOB|gainst the thinl +3937|47321|2330|2|30|38049.60|0.01|0.07|N|O|1998-01-17|1998-01-03|1998-02-08|COLLECT COD|TRUCK|al packages slee +3937|114474|2008|3|27|40188.69|0.03|0.00|N|O|1998-02-06|1998-01-12|1998-02-20|NONE|MAIL|ven ideas. slyly expr +3937|153056|5572|4|50|55452.50|0.01|0.02|N|O|1998-01-15|1998-01-09|1998-02-04|DELIVER IN PERSON|AIR|ong the carefully exp +3937|2904|405|5|29|52400.10|0.03|0.07|N|O|1998-03-06|1998-02-22|1998-03-14|NONE|TRUCK|nt pinto beans above the pending instr +3937|192002|7041|6|6|6564.00|0.00|0.00|N|O|1998-01-24|1998-02-13|1998-01-27|DELIVER IN PERSON|FOB|into beans. slyly silent orbits alongside o +3937|163846|1395|7|1|1909.84|0.02|0.05|N|O|1998-03-29|1998-01-08|1998-04-27|TAKE BACK RETURN|TRUCK|refully agains +3938|158367|3398|1|46|65566.56|0.10|0.07|R|F|1993-05-20|1993-05-04|1993-06-12|DELIVER IN PERSON|FOB|ly even foxes are slyly fu +3939|159523|2039|1|8|12660.16|0.03|0.06|N|O|1996-01-29|1996-04-05|1996-02-26|COLLECT COD|REG AIR|e packages. express, pen +3940|177038|2073|1|33|36795.99|0.10|0.07|N|O|1996-05-19|1996-04-19|1996-05-23|TAKE BACK RETURN|RAIL|ly ironic packages about the pending accou +3940|68501|6020|2|40|58780.00|0.08|0.02|N|O|1996-02-29|1996-03-22|1996-03-04|NONE|MAIL|ts. regular fox +3940|88876|8877|3|8|14918.96|0.07|0.08|N|O|1996-04-04|1996-04-12|1996-04-18|DELIVER IN PERSON|RAIL|ions cajole furiously regular pinto beans. +3940|136206|8720|4|11|13664.20|0.09|0.05|N|O|1996-03-09|1996-05-13|1996-03-17|COLLECT COD|REG AIR|e of the special packages. furiously +3940|942|5943|5|41|75560.54|0.00|0.07|N|O|1996-05-08|1996-05-03|1996-06-03|COLLECT COD|MAIL|thily. deposits cajole. +3941|40836|837|1|47|83511.01|0.05|0.07|N|O|1996-11-24|1996-10-09|1996-12-22|DELIVER IN PERSON|RAIL| carefully pending +3941|122533|70|2|19|29555.07|0.05|0.00|N|O|1996-11-10|1996-10-26|1996-12-05|COLLECT COD|RAIL|eposits haggle furiously even +3941|9693|2194|3|2|3205.38|0.01|0.03|N|O|1996-12-04|1996-10-01|1996-12-25|NONE|REG AIR|es wake after the +3941|109348|6879|4|29|39362.86|0.00|0.03|N|O|1996-09-14|1996-10-04|1996-09-19|NONE|MAIL|g the blithely +3942|182281|7318|1|6|8179.68|0.05|0.05|A|F|1993-07-01|1993-09-14|1993-07-23|DELIVER IN PERSON|SHIP|ep ruthlessly carefully final accounts: s +3942|193715|8754|2|5|9043.55|0.06|0.02|R|F|1993-09-27|1993-09-24|1993-10-07|DELIVER IN PERSON|MAIL|. fluffily pending deposits above the flu +3942|155497|8013|3|25|38812.25|0.04|0.06|R|F|1993-09-13|1993-08-01|1993-09-29|COLLECT COD|RAIL|d the quick packages +3943|197698|5256|1|15|26935.35|0.03|0.01|N|O|1997-01-13|1996-12-17|1997-02-02|COLLECT COD|REG AIR| grow fluffily according to the +3943|95557|5558|2|9|13972.95|0.00|0.06|N|O|1996-11-27|1997-01-03|1996-12-17|COLLECT COD|RAIL|refully ironic +3943|16818|1821|3|32|55513.92|0.00|0.02|N|O|1996-10-22|1996-12-17|1996-11-04|TAKE BACK RETURN|TRUCK| unusual ideas into the furiously even pack +3943|49034|9035|4|5|4915.15|0.04|0.04|N|O|1997-01-09|1996-11-10|1997-02-06|COLLECT COD|RAIL|arefully regular deposits accord +3968|53646|6152|1|27|43190.28|0.04|0.05|N|O|1997-04-25|1997-04-17|1997-05-11|TAKE BACK RETURN|MAIL|t silently. +3968|25166|2673|2|45|49102.20|0.00|0.07|N|O|1997-06-18|1997-04-24|1997-06-25|DELIVER IN PERSON|FOB|ully slyly fi +3968|155118|5119|3|43|50443.73|0.07|0.06|N|O|1997-04-30|1997-05-14|1997-05-18|TAKE BACK RETURN|SHIP|ly regular accounts +3968|60159|5172|4|7|7834.05|0.07|0.02|N|O|1997-03-30|1997-05-01|1997-04-12|DELIVER IN PERSON|SHIP|efully bold instructions. express +3969|51062|8578|1|39|39509.34|0.04|0.04|N|O|1997-06-12|1997-06-13|1997-07-05|NONE|MAIL|ly bold ideas s +3969|196745|4303|2|26|47885.24|0.05|0.03|N|O|1997-07-08|1997-07-30|1997-07-10|TAKE BACK RETURN|AIR|fluffily; braids detect. +3969|78703|3718|3|46|77358.20|0.04|0.02|N|O|1997-05-29|1997-06-15|1997-06-10|TAKE BACK RETURN|SHIP|fully final requests sleep stealthily. care +3969|150168|2684|4|21|25581.36|0.07|0.04|N|O|1997-08-31|1997-07-16|1997-09-02|TAKE BACK RETURN|MAIL|unts doze quickly final reque +3969|71513|1514|5|40|59380.40|0.09|0.00|N|O|1997-05-19|1997-08-02|1997-06-05|COLLECT COD|TRUCK|lar requests cajole furiously blithely regu +3969|104963|7474|6|4|7871.84|0.02|0.01|N|O|1997-06-04|1997-07-31|1997-06-13|COLLECT COD|REG AIR|dencies wake blithely? quickly even theodo +3970|87268|7269|1|2|2510.52|0.01|0.07|R|F|1992-04-24|1992-06-03|1992-05-16|TAKE BACK RETURN|RAIL|carefully pending foxes wake blithely +3970|108084|5615|2|18|19657.44|0.03|0.08|A|F|1992-06-06|1992-06-18|1992-07-05|DELIVER IN PERSON|TRUCK| maintain slyly. ir +3970|153569|1115|3|10|16225.60|0.10|0.04|A|F|1992-07-01|1992-05-31|1992-07-02|NONE|AIR| special packages wake after the final br +3970|21600|9107|4|34|51734.40|0.05|0.00|A|F|1992-06-25|1992-05-23|1992-07-12|COLLECT COD|SHIP|y final gifts are. carefully pe +3970|29048|6555|5|23|22471.92|0.05|0.04|A|F|1992-06-04|1992-06-14|1992-06-13|COLLECT COD|TRUCK| above the final braids. regular +3970|8771|6272|6|46|77269.42|0.07|0.04|R|F|1992-04-29|1992-05-14|1992-05-24|NONE|FOB|yly ironic +3970|4076|6577|7|46|45083.22|0.08|0.08|R|F|1992-05-02|1992-05-12|1992-05-10|COLLECT COD|MAIL|ix slyly. quickly silen +3971|95389|7899|1|47|65065.86|0.06|0.04|N|O|1996-07-07|1996-08-08|1996-08-01|TAKE BACK RETURN|RAIL|e slyly final dependencies x-ray +3971|190223|7781|2|2|2626.44|0.04|0.03|N|O|1996-07-15|1996-08-12|1996-07-26|NONE|SHIP|haggle abou +3972|50440|7956|1|2|2780.88|0.05|0.03|A|F|1994-07-24|1994-06-30|1994-08-13|TAKE BACK RETURN|SHIP|y final theodolite +3973|29590|4595|1|21|31911.39|0.02|0.06|R|F|1992-06-18|1992-06-03|1992-07-02|COLLECT COD|REG AIR|equests. furiously +3973|114205|9228|2|37|45110.40|0.07|0.00|A|F|1992-05-29|1992-05-04|1992-06-23|TAKE BACK RETURN|SHIP|inos wake fluffily. pending requests nag +3973|39243|1747|3|40|47289.60|0.08|0.05|R|F|1992-05-03|1992-06-09|1992-05-21|COLLECT COD|RAIL|g the carefully blithe f +3974|21091|6096|1|47|47568.23|0.10|0.03|N|O|1996-06-03|1996-05-08|1996-06-28|NONE|TRUCK|dencies above the re +3974|60454|5467|2|17|24045.65|0.05|0.07|N|O|1996-04-05|1996-05-21|1996-04-28|COLLECT COD|TRUCK|ions eat slyly after the blithely +3975|56042|3558|1|38|37925.52|0.01|0.05|N|O|1995-08-02|1995-06-18|1995-08-19|COLLECT COD|TRUCK|es are furiously: furi +4000|195697|5698|1|41|73500.29|0.06|0.01|A|F|1992-03-02|1992-03-14|1992-03-27|COLLECT COD|FOB|ve the even, fi +4000|74526|7034|2|44|66022.88|0.09|0.06|A|F|1992-03-27|1992-02-18|1992-03-31|COLLECT COD|AIR|equests use blithely blithely bold d +4001|105185|206|1|26|30944.68|0.00|0.01|N|O|1997-07-26|1997-06-18|1997-08-08|DELIVER IN PERSON|RAIL|tegrate blithely +4001|40918|8431|2|19|35319.29|0.03|0.02|N|O|1997-08-23|1997-06-15|1997-09-18|COLLECT COD|SHIP|ackages. carefully ironi +4001|93081|3082|3|18|19333.44|0.07|0.00|N|O|1997-06-04|1997-06-22|1997-06-13|DELIVER IN PERSON|MAIL|lithely ironic d +4001|1923|9424|4|39|71171.88|0.00|0.00|N|O|1997-06-13|1997-06-17|1997-06-25|NONE|SHIP| dogged excuses. blithe +4002|110728|3240|1|35|60855.20|0.01|0.08|N|O|1997-05-16|1997-06-15|1997-06-02|DELIVER IN PERSON|TRUCK|eep. quickly +4002|197837|7838|2|20|38696.60|0.00|0.03|N|O|1997-06-15|1997-05-20|1997-07-11|NONE|MAIL|lly even ins +4002|39841|4848|3|6|10685.04|0.08|0.07|N|O|1997-05-02|1997-07-07|1997-05-16|TAKE BACK RETURN|RAIL| furiously furiously special theodoli +4002|198650|6208|4|6|10491.90|0.06|0.06|N|O|1997-07-01|1997-05-15|1997-07-31|NONE|MAIL|he slyly iro +4002|98186|696|5|4|4736.72|0.08|0.07|N|O|1997-05-06|1997-06-15|1997-05-24|NONE|REG AIR|ccording to the careful +4003|51112|8628|1|18|19135.98|0.04|0.07|R|F|1993-02-02|1993-04-15|1993-02-28|TAKE BACK RETURN|AIR|ar grouches s +4004|120061|62|1|23|24864.38|0.07|0.02|A|F|1993-08-12|1993-07-13|1993-08-16|TAKE BACK RETURN|TRUCK| bold theodolites? special packages accordi +4004|63505|3506|2|47|69019.50|0.07|0.04|R|F|1993-06-25|1993-08-03|1993-07-12|NONE|SHIP|thely instead of the even, unu +4004|113136|3137|3|39|44816.07|0.10|0.05|R|F|1993-07-12|1993-07-27|1993-07-18|NONE|MAIL|ccounts sleep furious +4004|73634|6142|4|46|73950.98|0.10|0.04|R|F|1993-09-04|1993-07-13|1993-09-28|COLLECT COD|FOB|ncies. slyly pending dolphins sleep furio +4004|154767|7283|5|9|16395.84|0.04|0.06|A|F|1993-08-25|1993-06-10|1993-09-24|COLLECT COD|MAIL|ly ironic requests. quickly pending ide +4004|160037|2554|6|44|48269.32|0.07|0.05|R|F|1993-07-25|1993-07-23|1993-08-16|TAKE BACK RETURN|REG AIR|ut the sauternes. bold, ironi +4004|125377|2914|7|20|28047.40|0.07|0.05|A|F|1993-06-19|1993-06-14|1993-07-04|COLLECT COD|REG AIR|. ironic deposits cajole blithely? +4005|3667|1168|1|26|40837.16|0.09|0.05|N|O|1996-12-01|1997-02-03|1996-12-15|NONE|REG AIR| to the quic +4005|16605|6606|2|28|42604.80|0.02|0.06|N|O|1996-12-11|1997-01-24|1996-12-17|DELIVER IN PERSON|REG AIR|ly carefully ironic deposits. slyly +4005|71317|8839|3|28|36072.68|0.03|0.01|N|O|1996-12-08|1997-01-14|1996-12-30|TAKE BACK RETURN|MAIL|y pending dependenc +4005|14650|7152|4|49|76667.85|0.09|0.00|N|O|1997-01-31|1996-12-24|1997-03-02|NONE|RAIL|tions sleep across the silent d +4005|5747|5748|5|14|23138.36|0.09|0.08|N|O|1996-11-27|1997-01-09|1996-12-25|NONE|TRUCK|ld requests. slyly final instructi +4006|54773|2289|1|11|19005.47|0.05|0.08|A|F|1995-04-29|1995-02-21|1995-05-20|TAKE BACK RETURN|RAIL|ress foxes cajole quick +4006|158031|3062|2|18|19602.54|0.05|0.03|A|F|1995-01-29|1995-03-08|1995-02-02|TAKE BACK RETURN|MAIL|gouts! slyly iron +4006|23176|3177|3|15|16487.55|0.01|0.02|R|F|1995-02-23|1995-04-02|1995-02-25|TAKE BACK RETURN|RAIL|n deposits cajole slyl +4006|113466|3467|4|25|36986.50|0.00|0.07|A|F|1995-02-23|1995-02-09|1995-02-24|DELIVER IN PERSON|SHIP| requests use depos +4007|56091|1102|1|32|33506.88|0.00|0.03|R|F|1993-09-30|1993-08-16|1993-10-03|DELIVER IN PERSON|RAIL|nal accounts across t +4007|115470|7982|2|41|60904.27|0.04|0.06|A|F|1993-10-11|1993-08-30|1993-11-04|DELIVER IN PERSON|TRUCK|eposits. regular epitaphs boost blithely. +4007|101478|9009|3|5|7397.35|0.09|0.06|A|F|1993-09-17|1993-08-29|1993-10-12|TAKE BACK RETURN|FOB|y unusual packa +4007|137992|5532|4|15|30449.85|0.05|0.02|A|F|1993-09-01|1993-07-19|1993-09-03|DELIVER IN PERSON|FOB|le furiously quickly +4007|25894|5895|5|23|41857.47|0.02|0.07|A|F|1993-10-08|1993-09-09|1993-10-23|COLLECT COD|MAIL|ter the accounts. expr +4032|101625|1626|1|8|13012.96|0.06|0.00|N|O|1998-06-04|1998-05-17|1998-07-03|TAKE BACK RETURN|RAIL|ometimes even cou +4032|1652|9153|2|27|41948.55|0.09|0.00|N|O|1998-05-31|1998-04-19|1998-06-24|COLLECT COD|REG AIR|le furiously according to +4032|153608|6124|3|23|38216.80|0.09|0.06|N|O|1998-06-12|1998-05-11|1998-06-24|COLLECT COD|MAIL|ording to the +4032|84644|7153|4|10|16286.40|0.09|0.05|N|O|1998-03-31|1998-04-22|1998-04-07|NONE|REG AIR| carefully bol +4033|109529|9530|1|27|41540.04|0.01|0.04|R|F|1993-08-08|1993-08-14|1993-08-09|NONE|AIR|pinto beans +4033|37321|9825|2|34|42782.88|0.07|0.00|R|F|1993-07-19|1993-08-05|1993-07-26|NONE|RAIL|t the blithely dogg +4034|189949|4986|1|48|97869.12|0.03|0.03|A|F|1994-03-01|1994-01-16|1994-03-16|NONE|RAIL| blithely regular requests play carefull +4034|56730|9236|2|47|79276.31|0.07|0.05|A|F|1994-01-27|1993-12-26|1994-02-04|NONE|TRUCK|eodolites was slyly ironic ideas. de +4034|53884|3885|3|43|79028.84|0.10|0.03|A|F|1993-11-29|1994-01-08|1993-12-10|DELIVER IN PERSON|FOB|posits wake carefully af +4034|27679|7680|4|46|73906.82|0.06|0.00|A|F|1994-02-22|1994-01-09|1994-03-04|DELIVER IN PERSON|AIR|uests. furiously unusual instructions wake +4034|195196|2754|5|7|9038.33|0.07|0.06|R|F|1994-03-04|1994-01-22|1994-04-01|NONE|AIR|y even theodolites. slyly regular instru +4034|49283|6796|6|5|6161.40|0.01|0.06|A|F|1994-02-12|1994-01-24|1994-02-13|COLLECT COD|AIR|fully around the furiously ironic re +4035|96790|6791|1|4|7147.16|0.08|0.03|R|F|1992-04-21|1992-04-23|1992-04-25|COLLECT COD|AIR|ilent, even pear +4035|135094|5095|2|4|4516.36|0.07|0.00|A|F|1992-05-21|1992-04-24|1992-05-24|DELIVER IN PERSON|FOB|en instructions sleep blith +4035|117010|4544|3|1|1027.01|0.03|0.01|R|F|1992-06-18|1992-05-19|1992-07-02|COLLECT COD|FOB| requests. quickly +4035|181284|8839|4|13|17748.64|0.00|0.01|R|F|1992-06-10|1992-05-16|1992-07-10|NONE|SHIP|s. furiously even courts wake slyly +4036|5585|586|1|46|68566.68|0.09|0.00|N|O|1997-06-21|1997-05-29|1997-07-18|NONE|REG AIR|usly across the even th +4036|52428|4934|2|21|28988.82|0.09|0.07|N|O|1997-08-08|1997-06-28|1997-08-09|COLLECT COD|MAIL|e carefully. qui +4036|141687|1688|3|6|10372.08|0.07|0.01|N|O|1997-06-19|1997-06-16|1997-07-01|DELIVER IN PERSON|SHIP|equests wake about the bold id +4036|126016|3553|4|20|20840.20|0.08|0.02|N|O|1997-08-11|1997-07-11|1997-09-03|NONE|TRUCK|slyly bold deposits cajole pending, blithe +4037|63703|1222|1|32|53334.40|0.00|0.06|A|F|1993-05-06|1993-06-08|1993-05-31|DELIVER IN PERSON|AIR|e of the pending, iron +4037|46766|6767|2|4|6851.04|0.09|0.07|A|F|1993-07-05|1993-06-12|1993-08-03|DELIVER IN PERSON|RAIL|s around the blithely ironic ac +4038|195610|3168|1|40|68224.40|0.05|0.01|N|O|1996-01-15|1996-03-13|1996-01-25|COLLECT COD|TRUCK|t. slyly silent pinto beans amo +4038|11283|6286|2|37|44188.36|0.04|0.03|N|O|1996-03-17|1996-03-19|1996-04-07|DELIVER IN PERSON|REG AIR| packages +4038|31841|1842|3|24|42548.16|0.10|0.04|N|O|1996-04-06|1996-02-15|1996-04-18|TAKE BACK RETURN|RAIL|the furiously regu +4038|149264|9265|4|29|38084.54|0.07|0.06|N|O|1996-01-07|1996-03-08|1996-01-13|NONE|FOB|ffix. quietly ironic packages a +4038|78767|6289|5|24|41898.24|0.07|0.06|N|O|1996-04-01|1996-04-05|1996-04-28|DELIVER IN PERSON|TRUCK|ake quickly after the final, ironic ac +4038|35867|8371|6|6|10817.16|0.07|0.05|N|O|1996-02-09|1996-03-05|1996-03-10|COLLECT COD|SHIP| special instructions. packa +4039|93195|3196|1|38|45151.22|0.03|0.06|N|O|1998-03-09|1997-12-31|1998-03-21|DELIVER IN PERSON|REG AIR|sual asymptotes. ironic deposits nag aft +4039|121085|8622|2|17|18803.36|0.10|0.04|N|O|1998-01-15|1998-01-20|1998-01-28|TAKE BACK RETURN|MAIL| regular foxes haggle carefully bo +4039|63297|8310|3|9|11342.61|0.10|0.01|N|O|1998-03-08|1998-02-05|1998-04-05|TAKE BACK RETURN|FOB|t? pinto beans cajole across the thinly r +4039|27080|9583|4|43|43304.44|0.01|0.02|N|O|1998-01-02|1997-12-22|1998-01-15|NONE|FOB|beans believe bene +4039|133273|3274|5|43|56169.61|0.09|0.00|N|O|1998-01-20|1998-01-11|1998-02-05|COLLECT COD|SHIP|sts along the regular in +4064|198313|833|1|3|4233.93|0.10|0.04|N|O|1997-01-04|1997-01-01|1997-01-23|NONE|SHIP|its! quickly sp +4064|39472|1976|2|15|21172.05|0.02|0.02|N|O|1996-11-09|1996-12-04|1996-11-18|DELIVER IN PERSON|MAIL|braids affix across the regular sheave +4064|196654|1693|3|32|56020.80|0.04|0.07|N|O|1997-01-14|1997-01-01|1997-01-21|COLLECT COD|REG AIR|es boost. careful +4064|162125|9674|4|24|28490.88|0.02|0.02|N|O|1997-01-01|1996-12-31|1997-01-23|DELIVER IN PERSON|SHIP|ly regular ideas. +4064|20658|659|5|12|18943.80|0.08|0.08|N|O|1997-02-08|1996-12-18|1997-03-06|TAKE BACK RETURN|RAIL|ding to the requests +4064|183388|943|6|46|67683.48|0.03|0.00|N|O|1996-10-13|1997-01-05|1996-11-06|DELIVER IN PERSON|REG AIR|alongside of the f +4064|199699|2219|7|9|16188.21|0.01|0.06|N|O|1996-12-17|1996-12-13|1997-01-12|NONE|AIR|furiously f +4065|137373|7374|1|14|19745.18|0.04|0.02|A|F|1994-08-22|1994-07-29|1994-09-19|DELIVER IN PERSON|TRUCK|e furiously outside +4065|14060|4061|2|46|44806.76|0.03|0.05|A|F|1994-06-29|1994-08-01|1994-07-03|TAKE BACK RETURN|SHIP|, regular requests may mold above the +4065|96443|1462|3|33|47501.52|0.00|0.03|A|F|1994-09-03|1994-08-16|1994-09-13|DELIVER IN PERSON|AIR|ain blithely +4065|106463|1484|4|8|11755.68|0.00|0.01|R|F|1994-10-04|1994-08-05|1994-10-25|TAKE BACK RETURN|SHIP|ages haggle carefully +4065|122670|2671|5|29|49087.43|0.02|0.07|A|F|1994-06-29|1994-08-19|1994-07-17|NONE|RAIL|equests. packages sleep slyl +4065|109059|4080|6|16|17088.80|0.05|0.00|R|F|1994-08-25|1994-08-06|1994-09-09|COLLECT COD|TRUCK|ncies use furiously. quickly un +4065|143199|8228|7|11|13664.09|0.10|0.04|A|F|1994-07-25|1994-08-02|1994-07-30|NONE|RAIL|hang silently about +4066|138329|5869|1|9|12305.88|0.01|0.05|N|O|1997-05-06|1997-03-25|1997-05-27|COLLECT COD|FOB|nal, ironic accounts. blithel +4066|92550|5060|2|19|29308.45|0.05|0.00|N|O|1997-05-13|1997-04-17|1997-06-08|NONE|TRUCK|quests. slyly regu +4066|75789|804|3|8|14118.24|0.03|0.03|N|O|1997-04-24|1997-03-11|1997-05-20|NONE|REG AIR|accounts. special pinto beans +4066|178139|657|4|49|59639.37|0.01|0.01|N|O|1997-02-17|1997-03-24|1997-02-19|NONE|TRUCK|ial braids. furiously final deposits sl +4066|170234|235|5|43|56081.89|0.05|0.02|N|O|1997-02-16|1997-04-14|1997-02-18|DELIVER IN PERSON|MAIL|r instructions. slyly special +4066|108491|1002|6|44|65977.56|0.01|0.00|N|O|1997-03-01|1997-04-27|1997-03-29|DELIVER IN PERSON|MAIL|express accounts nag bli +4067|179063|9064|1|18|20557.08|0.03|0.08|A|F|1993-01-24|1992-12-23|1993-02-20|TAKE BACK RETURN|FOB|e the slyly final packages d +4067|95338|2866|2|14|18666.62|0.00|0.00|R|F|1993-02-03|1992-12-02|1993-02-07|TAKE BACK RETURN|TRUCK|ructions. quickly ironic accounts detect +4067|140221|7764|3|17|21440.74|0.03|0.05|A|F|1993-01-26|1992-11-23|1993-01-27|NONE|REG AIR|ts haggle slyly unusual, final +4067|89682|2191|4|40|66867.20|0.07|0.08|R|F|1993-01-09|1992-11-21|1993-01-16|DELIVER IN PERSON|TRUCK|lar theodolites nag blithely above the +4067|84828|9845|5|17|30817.94|0.08|0.03|A|F|1993-01-20|1992-12-29|1993-02-03|DELIVER IN PERSON|REG AIR|r accounts. slyly special pa +4067|95501|8011|6|12|17958.00|0.04|0.03|A|F|1992-12-12|1992-11-28|1992-12-15|DELIVER IN PERSON|AIR|lly slyly even theodol +4067|82675|5184|7|17|28180.39|0.01|0.01|R|F|1992-12-12|1992-12-23|1992-12-30|NONE|AIR|ts affix. regular, regular requests s +4068|109101|9102|1|43|47734.30|0.05|0.06|N|O|1996-11-28|1996-11-16|1996-12-22|NONE|AIR|ructions. regular, special packag +4068|56989|9495|2|31|60325.38|0.08|0.03|N|O|1996-12-11|1996-12-07|1996-12-30|NONE|SHIP|ds wake carefully amon +4069|128033|5570|1|39|41380.17|0.09|0.02|R|F|1992-09-06|1992-07-22|1992-09-25|COLLECT COD|SHIP|ven theodolites nag quickly. fluffi +4069|42553|2554|2|32|47857.60|0.10|0.08|A|F|1992-06-18|1992-07-20|1992-07-07|TAKE BACK RETURN|TRUCK|unts. deposit +4069|185023|7542|3|3|3324.06|0.06|0.01|R|F|1992-07-26|1992-07-07|1992-08-04|COLLECT COD|FOB|l packages. even, +4069|78465|3480|4|22|31756.12|0.10|0.05|A|F|1992-08-05|1992-08-04|1992-08-25|COLLECT COD|SHIP|ts. slyly special instruction +4069|156895|9411|5|50|97594.50|0.09|0.06|A|F|1992-07-26|1992-06-30|1992-08-01|TAKE BACK RETURN|REG AIR|even foxes among the express wate +4069|124947|2484|6|3|5915.82|0.02|0.01|A|F|1992-05-24|1992-06-18|1992-06-12|COLLECT COD|MAIL|y final deposits wake furiously! slyl +4069|183483|6002|7|50|78324.00|0.00|0.01|R|F|1992-09-03|1992-06-14|1992-10-01|NONE|REG AIR|ages. carefully regular +4070|182612|7649|1|2|3389.22|0.09|0.08|N|O|1995-08-03|1995-09-10|1995-08-17|TAKE BACK RETURN|REG AIR|ptotes affix +4070|154868|7384|2|40|76914.40|0.07|0.07|N|O|1995-07-13|1995-07-23|1995-08-06|COLLECT COD|MAIL|about the sentiments. quick +4070|61774|1775|3|11|19093.47|0.00|0.08|N|O|1995-08-23|1995-08-15|1995-08-31|TAKE BACK RETURN|MAIL| carefully final pack +4070|28495|998|4|46|65480.54|0.02|0.02|N|O|1995-06-22|1995-07-14|1995-07-11|DELIVER IN PERSON|REG AIR|nticing ideas. boldly +4071|111872|9406|1|22|41445.14|0.02|0.07|N|O|1996-10-31|1996-12-14|1996-11-05|NONE|REG AIR|sits cajole carefully final instructio +4071|17736|5240|2|47|77725.31|0.00|0.03|N|O|1996-11-04|1996-12-09|1996-11-16|NONE|TRUCK|ts cajole furiously along the +4096|26850|4357|1|31|55082.35|0.10|0.02|A|F|1992-07-14|1992-09-03|1992-07-31|COLLECT COD|TRUCK|y final, even platelets. boldly +4096|56025|3541|2|17|16677.34|0.07|0.03|R|F|1992-09-30|1992-08-11|1992-10-11|TAKE BACK RETURN|REG AIR|platelets alongside of the +4096|8635|8636|3|21|32416.23|0.08|0.00|A|F|1992-08-24|1992-09-04|1992-09-11|DELIVER IN PERSON|MAIL|tes mold flu +4096|127636|149|4|20|33272.60|0.02|0.07|R|F|1992-08-24|1992-09-13|1992-08-28|DELIVER IN PERSON|TRUCK|sual requests. furiously bold packages wake +4097|73486|3487|1|50|72974.00|0.04|0.04|N|O|1996-08-31|1996-08-14|1996-09-27|DELIVER IN PERSON|MAIL|egular deposits. blithely pending +4097|73230|5738|2|46|55348.58|0.10|0.01|N|O|1996-07-29|1996-08-19|1996-08-25|COLLECT COD|AIR| even depend +4097|173706|1258|3|42|74747.40|0.06|0.06|N|O|1996-08-11|1996-07-30|1996-08-15|NONE|FOB|carefully silent foxes are against the +4098|199417|9418|1|46|69754.86|0.07|0.03|N|O|1997-01-26|1997-01-27|1997-02-13|TAKE BACK RETURN|SHIP|e slyly blithely silent deposits. fluff +4099|3007|5508|1|29|26390.00|0.09|0.07|R|F|1992-11-21|1992-11-04|1992-11-30|NONE|FOB| slowly final warthogs sleep blithely. q +4099|136994|4534|2|3|6092.97|0.04|0.06|A|F|1992-09-12|1992-10-18|1992-10-01|NONE|RAIL|. special packages sleep +4099|50012|7528|3|36|34632.36|0.06|0.06|R|F|1992-11-06|1992-09-28|1992-12-02|NONE|FOB|beans cajole slyly quickly ironic +4099|138940|6480|4|7|13852.58|0.05|0.02|A|F|1992-09-12|1992-11-13|1992-09-14|TAKE BACK RETURN|AIR|onic foxes. quickly final fox +4099|162936|7969|5|48|95948.64|0.00|0.02|R|F|1992-10-18|1992-10-14|1992-11-01|NONE|REG AIR|ts haggle according to the slyly f +4099|58106|8107|6|39|41499.90|0.07|0.02|R|F|1992-12-13|1992-11-13|1992-12-26|DELIVER IN PERSON|REG AIR|fluffy accounts impress pending, iro +4099|179228|6780|7|46|60132.12|0.06|0.07|R|F|1992-10-29|1992-11-03|1992-11-10|DELIVER IN PERSON|REG AIR|ages nag requests. +4100|73624|3625|1|4|6390.48|0.03|0.03|N|O|1996-06-20|1996-04-29|1996-06-21|TAKE BACK RETURN|FOB|lyly regular, bold requ +4101|114376|9399|1|22|30588.14|0.05|0.02|R|F|1994-02-02|1994-02-19|1994-02-12|COLLECT COD|AIR|ly express instructions. careful +4102|9762|2263|1|17|28419.92|0.02|0.02|N|O|1996-06-03|1996-05-06|1996-07-02|COLLECT COD|AIR|ly silent theodolites sleep unusual exc +4102|68535|1042|2|5|7517.65|0.08|0.02|N|O|1996-05-11|1996-05-11|1996-05-16|COLLECT COD|AIR| the furiously even +4102|66779|1792|3|39|68085.03|0.08|0.01|N|O|1996-04-14|1996-05-18|1996-04-20|DELIVER IN PERSON|AIR|ffix blithely slyly special +4102|139097|1611|4|39|44307.51|0.02|0.00|N|O|1996-06-15|1996-06-06|1996-06-30|DELIVER IN PERSON|SHIP|y among the furiously special +4102|175|5176|5|32|34405.44|0.08|0.01|N|O|1996-05-14|1996-04-29|1996-05-29|NONE|RAIL| the even requests; regular pinto +4102|136116|1143|6|7|8064.77|0.02|0.01|N|O|1996-06-19|1996-05-21|1996-07-15|NONE|REG AIR|bove the carefully pending the +4103|74738|9753|1|40|68509.20|0.05|0.03|R|F|1992-09-19|1992-08-14|1992-09-21|COLLECT COD|RAIL|usly across the slyly busy accounts! fin +4128|195824|8344|1|5|9599.10|0.04|0.04|N|O|1995-10-18|1995-11-28|1995-10-28|TAKE BACK RETURN|FOB|ake permanently +4129|55253|2769|1|32|38664.00|0.03|0.04|A|F|1993-09-16|1993-08-25|1993-09-25|TAKE BACK RETURN|MAIL|ckages haggl +4129|26905|1910|2|39|71444.10|0.06|0.07|R|F|1993-10-21|1993-08-04|1993-10-29|COLLECT COD|MAIL|y regular foxes. slyly ironic deposits +4130|177966|5518|1|44|89934.24|0.07|0.04|N|O|1996-05-14|1996-04-15|1996-05-15|COLLECT COD|TRUCK|eaves haggle qui +4130|62910|7923|2|2|3745.82|0.05|0.06|N|O|1996-05-19|1996-04-24|1996-06-17|TAKE BACK RETURN|RAIL|uriously regular instructions around th +4131|49740|2245|1|6|10138.44|0.05|0.01|N|O|1998-04-27|1998-04-18|1998-04-29|TAKE BACK RETURN|MAIL|ns cajole slyly. even, iro +4131|177535|53|2|32|51600.96|0.08|0.01|N|O|1998-03-02|1998-03-21|1998-03-07|TAKE BACK RETURN|TRUCK| furiously regular asymptotes nod sly +4131|25254|2761|3|25|29481.25|0.02|0.07|N|O|1998-02-24|1998-03-01|1998-02-27|TAKE BACK RETURN|FOB|uickly exp +4131|35077|84|4|8|8096.56|0.04|0.01|N|O|1998-03-03|1998-03-15|1998-03-26|COLLECT COD|FOB| after the furiously ironic d +4131|124360|4361|5|30|41530.80|0.01|0.01|N|O|1998-04-01|1998-04-13|1998-04-08|TAKE BACK RETURN|FOB|he fluffily express depen +4131|101926|6947|6|47|90612.24|0.02|0.00|N|O|1998-03-09|1998-04-05|1998-03-13|TAKE BACK RETURN|RAIL|ges. ironic pinto be +4132|137396|9910|1|28|40134.92|0.07|0.03|N|O|1995-08-16|1995-08-01|1995-08-29|TAKE BACK RETURN|SHIP|pths wake against the stealthily special pi +4132|14238|1742|2|23|26501.29|0.07|0.07|N|O|1995-06-27|1995-07-27|1995-07-13|TAKE BACK RETURN|FOB|d deposits. fluffily even requests haggle b +4132|86626|1643|3|18|29027.16|0.09|0.04|A|F|1995-06-01|1995-08-01|1995-06-02|TAKE BACK RETURN|RAIL|y final de +4133|23646|3647|1|35|54937.40|0.02|0.00|A|F|1992-11-25|1992-09-15|1992-12-25|NONE|AIR|g above the quickly bold packages. ev +4134|120218|7755|1|34|42099.14|0.02|0.05|R|F|1995-04-29|1995-03-13|1995-05-11|DELIVER IN PERSON|FOB|e furiously regular sheaves sleep +4134|95661|3189|2|34|56326.44|0.01|0.03|A|F|1995-05-06|1995-03-28|1995-05-13|DELIVER IN PERSON|SHIP|ual asymptotes wake carefully alo +4134|170507|8059|3|12|18930.00|0.05|0.04|A|F|1995-03-19|1995-03-27|1995-04-14|COLLECT COD|TRUCK|kly above the quickly regular +4134|99989|7517|4|45|89504.10|0.08|0.02|A|F|1995-04-11|1995-03-27|1995-04-17|TAKE BACK RETURN|MAIL|ironic pin +4135|1947|1948|1|23|42525.62|0.06|0.01|N|O|1997-04-09|1997-05-12|1997-04-16|TAKE BACK RETURN|FOB|posits cajole furiously carefully +4135|119317|9318|2|32|42761.92|0.07|0.00|N|O|1997-03-14|1997-04-23|1997-04-12|TAKE BACK RETURN|TRUCK| ideas. requests use. furiously +4135|159231|4262|3|33|42577.59|0.05|0.05|N|O|1997-05-01|1997-05-23|1997-05-23|DELIVER IN PERSON|AIR|he fluffil +4135|194719|4720|4|13|23578.23|0.04|0.07|N|O|1997-03-16|1997-05-19|1997-04-03|COLLECT COD|RAIL|efully special account +4160|112413|7436|1|25|35635.25|0.10|0.04|N|O|1996-09-22|1996-10-17|1996-09-24|NONE|SHIP|ar accounts sleep blithe +4160|121668|4181|2|12|20275.92|0.00|0.03|N|O|1996-11-22|1996-09-25|1996-12-10|DELIVER IN PERSON|REG AIR|y bold package +4160|62498|2499|3|48|70103.52|0.04|0.04|N|O|1996-09-19|1996-11-02|1996-09-24|COLLECT COD|FOB| unusual dolphins +4161|121535|4048|1|12|18678.36|0.08|0.02|R|F|1993-08-25|1993-10-04|1993-09-22|COLLECT COD|RAIL|onic dolphins. in +4161|27319|9822|2|47|58576.57|0.05|0.00|A|F|1993-12-20|1993-10-29|1994-01-19|TAKE BACK RETURN|RAIL|r requests about the final, even foxes hag +4161|137027|9541|3|42|44688.84|0.03|0.04|R|F|1993-11-12|1993-10-04|1993-11-27|COLLECT COD|MAIL|thely across the even attainments. express +4161|9463|4464|4|45|61760.70|0.02|0.06|A|F|1993-10-22|1993-10-17|1993-10-30|COLLECT COD|REG AIR|about the ironic packages cajole blithe +4161|28343|8344|5|46|58481.64|0.05|0.01|A|F|1993-11-09|1993-11-17|1993-11-17|TAKE BACK RETURN|TRUCK|he stealthily ironic foxes. ideas haggl +4161|147061|7062|6|19|21053.14|0.07|0.00|R|F|1993-08-22|1993-11-11|1993-09-01|TAKE BACK RETURN|REG AIR|beans breach s +4162|73106|8121|1|45|48559.50|0.10|0.07|A|F|1992-03-21|1992-05-02|1992-03-29|DELIVER IN PERSON|AIR|elets. slyly regular i +4162|89349|9350|2|29|38811.86|0.00|0.05|R|F|1992-02-25|1992-04-25|1992-03-17|NONE|REG AIR|nding pinto beans haggle blithe +4163|32870|2871|1|13|23437.31|0.08|0.03|A|F|1993-02-17|1993-03-13|1993-03-15|DELIVER IN PERSON|REG AIR|phins wake. pending requests inte +4164|119658|4681|1|9|15098.85|0.07|0.02|N|O|1998-08-25|1998-08-13|1998-09-19|DELIVER IN PERSON|SHIP|re fluffily slyly bold requests. +4165|40102|103|1|12|12505.20|0.00|0.01|N|O|1997-09-20|1997-10-20|1997-10-12|TAKE BACK RETURN|REG AIR|nwind slow theodolites. carefully pending +4166|140721|8264|1|8|14093.76|0.00|0.08|A|F|1993-06-05|1993-04-10|1993-07-05|COLLECT COD|MAIL|uickly. blithely pending de +4166|92165|4675|2|8|9257.28|0.06|0.04|A|F|1993-06-07|1993-04-17|1993-06-16|DELIVER IN PERSON|REG AIR|es along the furiously regular acc +4166|6324|8825|3|17|20915.44|0.02|0.06|R|F|1993-06-29|1993-05-15|1993-07-24|DELIVER IN PERSON|SHIP|ackages. re +4166|85553|3078|4|36|55387.80|0.06|0.05|R|F|1993-03-01|1993-05-25|1993-03-05|COLLECT COD|MAIL|unts. furiously express accounts w +4166|76379|1394|5|5|6776.85|0.08|0.01|A|F|1993-06-19|1993-04-24|1993-06-27|NONE|REG AIR|hely unusual packages are above the f +4166|101840|4351|6|6|11051.04|0.04|0.08|R|F|1993-04-30|1993-04-17|1993-05-08|DELIVER IN PERSON|MAIL|ily ironic deposits print furiously. iron +4166|23149|3150|7|26|27875.64|0.09|0.01|R|F|1993-03-17|1993-05-09|1993-03-25|NONE|MAIL|lar dependencies. s +4167|60623|5636|1|47|74430.14|0.04|0.02|N|O|1998-08-02|1998-08-24|1998-08-28|DELIVER IN PERSON|REG AIR| carefully final asymptotes. slyly bo +4167|86504|6505|2|17|25338.50|0.06|0.07|N|O|1998-09-18|1998-09-06|1998-10-07|COLLECT COD|REG AIR|ly around the even instr +4167|72505|5013|3|1|1477.50|0.03|0.06|N|O|1998-10-11|1998-08-14|1998-10-13|COLLECT COD|TRUCK|xpress platelets. blithely +4192|10837|8341|1|36|62921.88|0.06|0.08|N|O|1998-04-25|1998-05-26|1998-05-03|COLLECT COD|TRUCK|eodolites sleep +4192|120696|3209|2|15|25750.35|0.04|0.08|N|O|1998-06-26|1998-05-26|1998-07-16|COLLECT COD|AIR|e slyly special grouches. express pinto b +4192|134922|9949|3|7|13698.44|0.06|0.03|N|O|1998-05-19|1998-07-08|1998-05-31|COLLECT COD|FOB|y; excuses use. ironic, close instru +4192|23256|8261|4|32|37736.00|0.09|0.04|N|O|1998-06-23|1998-06-25|1998-07-17|NONE|FOB|ounts are fluffily slyly bold req +4192|47037|4550|5|48|47233.44|0.08|0.01|N|O|1998-08-17|1998-07-11|1998-09-03|NONE|AIR|ests. quickly bol +4192|149567|2082|6|44|71128.64|0.10|0.02|N|O|1998-08-06|1998-07-09|1998-08-20|NONE|FOB|structions mai +4192|169807|7356|7|27|50673.60|0.02|0.00|N|O|1998-07-03|1998-06-26|1998-07-13|TAKE BACK RETURN|AIR| carefully even escapades. care +4193|130286|7826|1|37|48702.36|0.09|0.06|A|F|1994-04-25|1994-02-24|1994-05-08|NONE|AIR|er the quickly regular dependencies wake +4193|116403|3937|2|3|4258.20|0.09|0.05|R|F|1994-04-29|1994-03-20|1994-05-29|TAKE BACK RETURN|REG AIR|osits above the depo +4193|178441|8442|3|10|15194.40|0.06|0.03|A|F|1994-02-10|1994-03-22|1994-03-09|COLLECT COD|RAIL|uffily spe +4193|50040|2546|4|29|28711.16|0.09|0.05|A|F|1994-02-11|1994-03-11|1994-03-13|TAKE BACK RETURN|RAIL|ly. final packages use blit +4193|19877|4880|5|50|89843.50|0.01|0.01|R|F|1994-04-28|1994-03-23|1994-05-09|NONE|FOB| beans. regular accounts cajole. de +4193|65248|2767|6|21|25478.04|0.02|0.04|R|F|1994-04-26|1994-03-22|1994-05-23|DELIVER IN PERSON|TRUCK|accounts cajole b +4194|196755|4313|1|43|79625.25|0.08|0.06|A|F|1994-11-06|1994-12-09|1994-11-16|NONE|TRUCK|olites are after the exp +4194|46577|1586|2|18|27424.26|0.07|0.07|A|F|1995-02-14|1994-12-04|1995-03-11|TAKE BACK RETURN|TRUCK|ld packages. quickly eve +4195|5693|8194|1|14|22381.66|0.09|0.04|R|F|1993-09-06|1993-07-21|1993-09-18|DELIVER IN PERSON|REG AIR|ironic packages. carefully express +4195|65973|3492|2|22|42657.34|0.10|0.08|R|F|1993-07-01|1993-07-23|1993-07-28|COLLECT COD|RAIL|lly express pinto bea +4195|193646|1204|3|19|33053.16|0.01|0.06|R|F|1993-09-06|1993-08-13|1993-09-15|TAKE BACK RETURN|REG AIR|telets sleep even requests. final, even i +4196|155079|7595|1|30|34022.10|0.02|0.06|N|O|1998-08-09|1998-06-30|1998-09-05|COLLECT COD|SHIP|egular foxes us +4196|8234|5735|2|31|35409.13|0.09|0.08|N|O|1998-06-12|1998-07-28|1998-07-11|NONE|MAIL|ut the blithely ironic inst +4196|177505|7506|3|46|72795.00|0.05|0.00|N|O|1998-09-05|1998-06-28|1998-09-10|TAKE BACK RETURN|MAIL|according to t +4196|113898|6410|4|42|80299.38|0.04|0.06|N|O|1998-08-13|1998-07-18|1998-09-07|TAKE BACK RETURN|AIR| instructions. courts cajole slyly ev +4196|71690|4198|5|3|4985.07|0.01|0.03|N|O|1998-05-17|1998-07-21|1998-05-18|DELIVER IN PERSON|TRUCK| accounts. fu +4196|86060|8569|6|43|44980.58|0.01|0.06|N|O|1998-08-12|1998-07-12|1998-08-22|DELIVER IN PERSON|FOB|es. slyly even +4196|3066|567|7|3|2907.18|0.00|0.06|N|O|1998-08-05|1998-07-28|1998-08-15|DELIVER IN PERSON|REG AIR|y regular packages haggle furiously alongs +4197|128035|3060|1|50|53151.50|0.06|0.03|N|O|1996-11-15|1996-11-01|1996-11-20|NONE|FOB|. carefully bold asymptotes nag blithe +4197|69664|2171|2|39|63712.74|0.02|0.08|N|O|1996-10-07|1996-10-11|1996-10-18|DELIVER IN PERSON|RAIL|ronic requests. quickly bold packages in +4197|31921|4425|3|28|51881.76|0.06|0.02|N|O|1996-10-05|1996-10-24|1996-10-22|TAKE BACK RETURN|AIR|regular pin +4197|95301|5302|4|23|29814.90|0.00|0.03|N|O|1996-09-10|1996-10-10|1996-09-25|NONE|AIR|l instructions print slyly past the reg +4197|120952|3465|5|37|72999.15|0.03|0.04|N|O|1996-10-20|1996-10-10|1996-11-10|COLLECT COD|TRUCK|carefully enticing decoys boo +4197|30658|3162|6|48|76255.20|0.08|0.00|N|O|1996-10-07|1996-10-25|1996-10-23|COLLECT COD|REG AIR| final instructions. blithe, spe +4198|145163|192|1|48|57991.68|0.09|0.05|N|O|1997-09-03|1997-07-18|1997-09-11|NONE|REG AIR|cajole carefully final, ironic ide +4198|142247|7276|2|46|59305.04|0.09|0.01|N|O|1997-08-17|1997-09-08|1997-09-11|COLLECT COD|TRUCK|posits among th +4198|144524|2067|3|13|20390.76|0.03|0.04|N|O|1997-07-18|1997-07-24|1997-08-10|NONE|REG AIR| furious excuses. bli +4199|69662|7181|1|16|26106.56|0.10|0.00|A|F|1992-06-11|1992-04-10|1992-07-10|COLLECT COD|TRUCK|ncies. furiously special accounts +4199|8840|8841|2|18|31479.12|0.00|0.01|A|F|1992-06-01|1992-03-30|1992-06-28|DELIVER IN PERSON|RAIL|pending, regular accounts. carefully +4224|198265|8266|1|27|36808.02|0.05|0.03|N|O|1997-09-05|1997-08-19|1997-09-30|NONE|SHIP|ly special deposits sleep qui +4224|36701|4211|2|20|32754.00|0.07|0.05|N|O|1997-11-09|1997-08-23|1997-11-14|NONE|FOB|unts promise across the requests. blith +4224|23726|1233|3|4|6598.88|0.08|0.05|N|O|1997-09-07|1997-09-05|1997-09-25|TAKE BACK RETURN|FOB| even dinos. carefull +4224|159653|7199|4|50|85632.50|0.10|0.06|N|O|1997-07-30|1997-09-10|1997-08-19|COLLECT COD|RAIL|side of the carefully silent dep +4224|84136|6645|5|48|53766.24|0.00|0.04|N|O|1997-10-03|1997-08-31|1997-10-10|NONE|RAIL| final, regular asymptotes use alway +4225|48772|6285|1|25|43019.25|0.08|0.04|N|O|1997-07-10|1997-08-08|1997-07-31|TAKE BACK RETURN|TRUCK|se fluffily. busily ironic requests are; +4225|95002|7512|2|23|22931.00|0.02|0.04|N|O|1997-09-18|1997-08-31|1997-10-11|TAKE BACK RETURN|RAIL|. quickly b +4225|97926|436|3|28|53869.76|0.08|0.03|N|O|1997-07-11|1997-09-01|1997-08-03|DELIVER IN PERSON|FOB|ts are requests. even, bold depos +4226|187065|9584|1|27|31105.62|0.06|0.08|A|F|1993-05-03|1993-04-12|1993-05-16|COLLECT COD|AIR|sly alongside of the slyly ironic pac +4227|157199|9715|1|19|23867.61|0.01|0.08|A|F|1995-05-05|1995-05-03|1995-05-22|COLLECT COD|REG AIR|ns sleep along the blithely even theodolit +4227|32622|2623|2|8|12436.96|0.09|0.00|N|F|1995-06-11|1995-04-30|1995-06-28|COLLECT COD|REG AIR| packages since the bold, u +4227|74624|4625|3|11|17584.82|0.10|0.04|A|F|1995-03-30|1995-05-02|1995-04-26|DELIVER IN PERSON|SHIP|l requests-- bold requests cajole dogg +4227|199283|6841|4|2|2764.56|0.02|0.05|R|F|1995-04-24|1995-05-09|1995-05-21|DELIVER IN PERSON|AIR|ep. specia +4227|146835|4378|5|49|92209.67|0.05|0.06|R|F|1995-05-19|1995-04-12|1995-06-12|TAKE BACK RETURN|REG AIR|ts sleep blithely carefully unusual ideas. +4228|140949|8492|1|20|39798.80|0.00|0.06|N|O|1997-04-24|1997-05-29|1997-05-17|NONE|RAIL|f the slyly fluffy pinto beans are +4229|95318|337|1|44|57785.64|0.02|0.05|N|O|1998-05-29|1998-05-12|1998-06-16|DELIVER IN PERSON|AIR|s. carefully e +4229|4570|7071|2|34|50135.38|0.07|0.05|N|O|1998-05-26|1998-04-13|1998-06-08|DELIVER IN PERSON|MAIL|thely final accounts use even packa +4230|45124|2637|1|38|40626.56|0.10|0.03|A|F|1992-04-28|1992-04-21|1992-05-28|TAKE BACK RETURN|FOB|ly regular packages. regular ideas boost +4230|198644|6202|2|43|74933.52|0.02|0.08|R|F|1992-03-14|1992-05-13|1992-03-28|NONE|FOB|ses lose blithely slyly final e +4230|195055|94|3|10|11500.50|0.06|0.02|A|F|1992-06-11|1992-04-11|1992-07-02|TAKE BACK RETURN|MAIL|ar packages are +4230|74334|4335|4|28|36633.24|0.01|0.03|R|F|1992-05-12|1992-05-10|1992-06-01|TAKE BACK RETURN|MAIL|nt instruct +4230|124748|7261|5|50|88637.00|0.00|0.01|A|F|1992-03-29|1992-05-19|1992-04-20|TAKE BACK RETURN|SHIP|ts. final instructions in +4230|34864|9871|6|30|53965.80|0.05|0.07|A|F|1992-03-11|1992-04-29|1992-03-30|NONE|AIR|s. final excuses across the +4230|151041|1042|7|18|19656.72|0.10|0.04|R|F|1992-06-23|1992-05-10|1992-07-04|COLLECT COD|SHIP| the final acco +4231|141535|1536|1|47|74096.91|0.09|0.03|N|O|1997-11-27|1998-01-26|1997-12-17|NONE|REG AIR|hely along the silent at +4231|165189|222|2|4|5016.72|0.06|0.02|N|O|1997-11-28|1998-01-26|1997-12-12|TAKE BACK RETURN|MAIL|lithely even packages. +4231|120334|335|3|31|41984.23|0.07|0.08|N|O|1998-02-14|1997-12-27|1998-03-01|DELIVER IN PERSON|FOB|ublate. theodoli +4231|39030|4037|4|35|33916.05|0.10|0.00|N|O|1998-02-21|1998-01-24|1998-03-18|DELIVER IN PERSON|FOB|le quickly regular, unus +4256|150384|2900|1|22|31556.36|0.05|0.05|R|F|1992-07-30|1992-05-14|1992-08-14|NONE|TRUCK|, final platelets are slyly final pint +4257|64416|1935|1|3|4141.23|0.10|0.03|N|O|1995-06-18|1995-05-01|1995-07-12|DELIVER IN PERSON|MAIL|thin the theodolites use after the bl +4257|34970|9977|2|5|9524.85|0.01|0.04|R|F|1995-04-29|1995-06-05|1995-05-13|TAKE BACK RETURN|TRUCK|n deposits. furiously e +4257|127007|7008|3|33|34122.00|0.03|0.04|A|F|1995-05-23|1995-05-03|1995-05-31|COLLECT COD|AIR|uffily regular accounts ar +4258|165025|5026|1|36|39240.72|0.02|0.06|N|O|1997-02-23|1997-01-25|1997-02-27|TAKE BACK RETURN|SHIP|ns use alongs +4258|161733|4250|2|19|34099.87|0.03|0.02|N|O|1997-01-14|1996-12-12|1997-01-20|TAKE BACK RETURN|AIR|ly busily ironic foxes. f +4258|30847|8357|3|46|81780.64|0.04|0.07|N|O|1997-01-02|1996-12-26|1997-01-12|DELIVER IN PERSON|AIR| furiously pend +4258|34234|4235|4|22|25701.06|0.04|0.04|N|O|1996-12-12|1996-12-06|1996-12-20|TAKE BACK RETURN|AIR|e regular, even asym +4258|162806|7839|5|9|16819.20|0.04|0.03|N|O|1996-12-04|1996-12-08|1996-12-20|DELIVER IN PERSON|TRUCK|counts wake permanently after the bravely +4259|42595|7604|1|14|21526.26|0.05|0.03|N|O|1998-01-09|1997-11-21|1998-01-29|TAKE BACK RETURN|RAIL| furiously pending excuses. ideas hagg +4260|23397|904|1|21|27728.19|0.08|0.04|R|F|1992-08-06|1992-06-18|1992-08-22|NONE|AIR|al, pending accounts must +4261|109388|9389|1|12|16768.56|0.05|0.01|A|F|1992-11-01|1993-01-01|1992-11-12|NONE|FOB|into beans +4261|81703|9228|2|4|6738.80|0.02|0.07|R|F|1992-12-11|1992-12-18|1992-12-24|DELIVER IN PERSON|FOB|ackages unwind furiously fluff +4261|174248|6766|3|3|3966.72|0.07|0.02|R|F|1992-11-10|1992-12-14|1992-11-17|COLLECT COD|RAIL|ly even deposits eat blithely alo +4261|173239|8274|4|36|47240.28|0.04|0.06|R|F|1992-12-02|1992-12-18|1992-12-25|NONE|REG AIR| slyly pendi +4261|23678|1185|5|28|44846.76|0.07|0.06|A|F|1992-10-08|1992-12-23|1992-10-11|TAKE BACK RETURN|MAIL|packages. fluffily i +4262|75546|5547|1|30|45646.20|0.01|0.03|N|O|1996-08-11|1996-10-11|1996-09-09|TAKE BACK RETURN|RAIL|tes after the carefully +4262|95696|5697|2|5|8458.45|0.02|0.05|N|O|1996-09-27|1996-09-05|1996-10-25|COLLECT COD|SHIP|blithely final asymptotes integrate +4262|161033|3550|3|5|5470.15|0.08|0.00|N|O|1996-10-02|1996-10-16|1996-10-05|NONE|REG AIR|ironic accounts are unusu +4262|73333|855|4|45|58784.85|0.02|0.01|N|O|1996-11-09|1996-09-09|1996-11-12|DELIVER IN PERSON|SHIP|ackages boost. pending, even instruction +4262|99103|4122|5|28|30858.80|0.06|0.02|N|O|1996-10-22|1996-09-06|1996-11-13|DELIVER IN PERSON|FOB|ironic, regular depend +4262|16420|3924|6|26|34746.92|0.03|0.02|N|O|1996-08-29|1996-09-25|1996-08-31|NONE|RAIL|s boost slyly along the bold, iro +4262|159435|4466|7|41|61271.63|0.03|0.01|N|O|1996-08-28|1996-09-14|1996-09-20|COLLECT COD|RAIL|cuses unwind ac +4263|17017|7018|1|9|8406.09|0.08|0.07|N|O|1998-04-04|1998-04-29|1998-05-04|COLLECT COD|AIR|structions cajole quic +4263|195562|3120|2|28|46411.68|0.05|0.03|N|O|1998-06-24|1998-06-08|1998-07-14|NONE|MAIL|ideas for the carefully re +4263|10259|7763|3|38|44431.50|0.01|0.01|N|O|1998-07-10|1998-05-08|1998-07-17|NONE|TRUCK|rding to the dep +4263|18148|650|4|20|21322.80|0.02|0.07|N|O|1998-04-09|1998-04-30|1998-05-04|NONE|RAIL|uietly regular deposits. sly deposits w +4263|197901|5459|5|14|27984.60|0.09|0.06|N|O|1998-05-06|1998-04-17|1998-05-11|DELIVER IN PERSON|TRUCK|d accounts. daringly regular accounts hagg +4263|112955|7978|6|47|92493.65|0.08|0.06|N|O|1998-06-28|1998-05-09|1998-07-02|DELIVER IN PERSON|TRUCK|y. theodolites wake idly ironic do +4263|28779|1282|7|6|10246.62|0.04|0.04|N|O|1998-05-01|1998-06-02|1998-05-14|TAKE BACK RETURN|REG AIR|g the final, regular instructions: +4288|73060|3061|1|32|33057.92|0.10|0.07|R|F|1993-03-19|1993-01-26|1993-04-18|TAKE BACK RETURN|AIR|e blithely even instructions. speci +4288|104952|4953|2|39|76321.05|0.05|0.02|R|F|1993-03-25|1993-02-06|1993-03-28|DELIVER IN PERSON|AIR|uffy theodolites run +4288|124632|2169|3|7|11596.41|0.03|0.01|A|F|1993-01-15|1993-02-05|1993-01-26|NONE|TRUCK|ngside of the special platelet +4289|195619|5620|1|19|32577.59|0.06|0.06|R|F|1993-12-31|1993-11-06|1994-01-23|DELIVER IN PERSON|TRUCK|e carefully regular ideas. sl +4290|136795|9309|1|23|42131.17|0.06|0.04|R|F|1995-04-04|1995-02-16|1995-04-07|TAKE BACK RETURN|REG AIR|uests cajole carefully. +4290|98378|3397|2|3|4129.11|0.09|0.03|A|F|1995-03-25|1995-03-07|1995-04-11|NONE|RAIL|lar platelets cajole +4291|191809|9367|1|3|5702.40|0.08|0.08|A|F|1994-03-17|1994-02-21|1994-03-27|COLLECT COD|SHIP|tes sleep slyly above the quickly sl +4291|124889|2426|2|43|82296.84|0.01|0.06|A|F|1994-02-01|1994-02-27|1994-02-06|DELIVER IN PERSON|REG AIR|s. quietly regular +4291|7976|477|3|25|47099.25|0.09|0.08|R|F|1994-02-14|1994-02-08|1994-03-15|COLLECT COD|AIR|uctions. furiously regular ins +4292|43509|1022|1|22|31955.00|0.08|0.03|R|F|1992-02-14|1992-02-16|1992-03-01|NONE|FOB|refully expres +4292|39824|7334|2|1|1763.82|0.03|0.01|A|F|1992-02-07|1992-03-16|1992-02-10|DELIVER IN PERSON|FOB| the furiously ev +4292|119234|6768|3|35|43863.05|0.03|0.06|A|F|1992-03-23|1992-04-04|1992-04-02|COLLECT COD|TRUCK|dugouts use. furiously bold packag +4292|162381|7414|4|40|57735.20|0.05|0.04|A|F|1992-04-27|1992-03-07|1992-05-04|COLLECT COD|REG AIR|ounts according to the furiously +4292|130292|7832|5|6|7933.74|0.07|0.08|R|F|1992-03-03|1992-02-24|1992-03-25|COLLECT COD|FOB|bove the silently regula +4292|3041|542|6|47|44369.88|0.05|0.00|R|F|1992-05-02|1992-03-21|1992-05-27|TAKE BACK RETURN|FOB|y packages; even ideas boost +4293|957|5958|1|34|63170.30|0.03|0.08|N|O|1996-11-05|1996-10-12|1996-12-04|NONE|FOB|ions sleep blithely on +4293|76837|4359|2|50|90691.50|0.01|0.05|N|O|1996-11-27|1996-10-30|1996-12-22|COLLECT COD|MAIL| special deposits. furiousl +4293|198566|1086|3|47|78234.32|0.08|0.02|N|O|1996-09-07|1996-10-24|1996-09-15|NONE|RAIL|ithely pending deposits af +4293|87832|5357|4|25|45495.75|0.04|0.04|N|O|1996-09-11|1996-11-14|1996-09-22|DELIVER IN PERSON|FOB|inal asympt +4293|180656|3175|5|1|1736.65|0.06|0.05|N|O|1996-11-15|1996-10-09|1996-11-26|COLLECT COD|AIR|eposits should boost along the +4293|78993|6515|6|45|88739.55|0.10|0.04|N|O|1996-11-04|1996-11-06|1996-11-23|NONE|MAIL|lar ideas use carefully +4294|104911|7422|1|19|36402.29|0.03|0.04|A|F|1992-10-16|1992-11-13|1992-10-26|DELIVER IN PERSON|AIR|nt dependencies. furiously regular ideas d +4294|26561|9064|2|16|23800.96|0.01|0.02|R|F|1992-08-17|1992-09-24|1992-09-04|TAKE BACK RETURN|REG AIR|lithely pint +4294|197032|2071|3|30|33870.90|0.01|0.00|A|F|1992-09-12|1992-11-06|1992-09-25|NONE|MAIL|olites. bold foxes affix ironic theodolite +4294|104405|1936|4|34|47919.60|0.02|0.01|R|F|1992-09-09|1992-11-06|1992-10-04|TAKE BACK RETURN|REG AIR|pendencies! +4294|118956|1468|5|37|73073.15|0.05|0.01|R|F|1992-09-07|1992-10-13|1992-09-08|NONE|REG AIR|cial packages nag f +4294|86273|8782|6|42|52889.34|0.02|0.03|A|F|1992-09-30|1992-11-13|1992-10-15|DELIVER IN PERSON|FOB| carefully; furiously ex +4294|174787|2339|7|47|87503.66|0.02|0.08|R|F|1992-11-09|1992-11-03|1992-12-05|TAKE BACK RETURN|SHIP|es. blithely r +4295|28410|5917|1|49|65582.09|0.09|0.01|N|O|1996-05-25|1996-03-17|1996-06-19|TAKE BACK RETURN|REG AIR|refully silent requests. f +4295|70554|8076|2|4|6098.20|0.09|0.07|N|O|1996-06-05|1996-04-26|1996-06-13|DELIVER IN PERSON|TRUCK|arefully according to the pending ac +4295|192627|2628|3|3|5158.86|0.04|0.00|N|O|1996-06-04|1996-04-24|1996-06-24|DELIVER IN PERSON|AIR|telets cajole bravely +4295|79439|4454|4|30|42552.90|0.07|0.06|N|O|1996-03-22|1996-04-23|1996-04-20|NONE|SHIP|yly ironic frets. pending foxes after +4320|45894|3407|1|28|51516.92|0.02|0.06|N|O|1997-01-28|1997-02-07|1997-02-07|COLLECT COD|FOB|nts. even, ironic excuses hagg +4320|139168|1682|2|6|7242.96|0.08|0.08|N|O|1997-01-11|1997-01-26|1997-01-22|DELIVER IN PERSON|SHIP|against the carefully careful asym +4320|187628|2665|3|33|56615.46|0.09|0.02|N|O|1996-12-11|1997-02-27|1997-01-08|TAKE BACK RETURN|SHIP|ess asymptotes so +4321|146895|4438|1|33|64082.37|0.09|0.02|A|F|1994-09-01|1994-08-17|1994-09-05|DELIVER IN PERSON|TRUCK|yly special excuses. fluffily +4321|53251|5757|2|45|54191.25|0.00|0.08|R|F|1994-11-13|1994-09-15|1994-11-18|DELIVER IN PERSON|SHIP| haggle ironically bold theodolites. quick +4321|185298|5299|3|23|31815.67|0.01|0.05|A|F|1994-11-03|1994-10-08|1994-11-06|DELIVER IN PERSON|SHIP|ly even orbits slee +4321|90271|272|4|4|5045.08|0.02|0.00|R|F|1994-09-10|1994-10-06|1994-09-11|NONE|FOB|ironic deposi +4321|171625|4143|5|10|16966.20|0.04|0.03|A|F|1994-09-07|1994-08-23|1994-09-17|TAKE BACK RETURN|SHIP|wake carefully alongside of +4322|68766|6285|1|39|67655.64|0.04|0.02|N|O|1998-04-27|1998-06-03|1998-05-04|TAKE BACK RETURN|MAIL|its integrate fluffily +4322|139800|9801|2|9|16558.20|0.05|0.08|N|O|1998-05-18|1998-04-27|1998-05-28|COLLECT COD|AIR|ual instructio +4322|7548|7549|3|12|17466.48|0.09|0.05|N|O|1998-03-29|1998-06-05|1998-04-16|DELIVER IN PERSON|TRUCK|e blithely against the slyly unusu +4322|45880|5881|4|17|31039.96|0.09|0.08|N|O|1998-05-31|1998-05-31|1998-06-10|TAKE BACK RETURN|FOB|ructions boost +4322|101331|6352|5|10|13323.30|0.00|0.05|N|O|1998-05-31|1998-04-27|1998-06-25|TAKE BACK RETURN|REG AIR| regular ideas engage carefully quick +4322|59477|1983|6|39|56022.33|0.09|0.08|N|O|1998-03-16|1998-05-21|1998-04-11|COLLECT COD|AIR|ccounts. dogged pin +4322|13150|654|7|34|36147.10|0.05|0.00|N|O|1998-05-27|1998-04-12|1998-06-16|NONE|REG AIR|ounts haggle fluffily ideas. pend +4323|358|359|1|33|41525.55|0.09|0.02|A|F|1994-05-04|1994-03-06|1994-05-23|COLLECT COD|TRUCK|the slyly bold deposits slee +4324|50292|293|1|44|54660.76|0.05|0.04|N|O|1995-10-15|1995-09-07|1995-11-07|DELIVER IN PERSON|AIR|ainst the u +4324|47117|4630|2|12|12769.32|0.04|0.02|N|O|1995-10-05|1995-09-07|1995-10-18|NONE|REG AIR|c packages. furiously express sauternes +4324|81374|8899|3|14|18975.18|0.07|0.06|N|O|1995-11-12|1995-08-26|1995-11-21|COLLECT COD|AIR| packages nag express excuses. qui +4324|49985|2490|4|14|27089.72|0.02|0.04|N|O|1995-09-20|1995-10-08|1995-10-06|COLLECT COD|RAIL| express ideas. blithely blit +4324|83480|5989|5|22|32196.56|0.07|0.03|N|O|1995-09-13|1995-10-04|1995-09-23|DELIVER IN PERSON|SHIP|ke express, special ideas. +4324|42432|9945|6|31|42607.33|0.08|0.04|N|O|1995-10-23|1995-09-14|1995-11-09|COLLECT COD|RAIL|efully flu +4324|153018|564|7|46|49266.46|0.00|0.03|N|O|1995-11-03|1995-09-28|1995-11-22|NONE|SHIP|ular, final theodo +4325|159610|7156|1|18|30052.98|0.01|0.07|N|O|1996-10-07|1996-09-28|1996-10-31|DELIVER IN PERSON|RAIL|. blithely +4326|162728|2729|1|11|19697.92|0.01|0.01|N|O|1997-02-02|1996-12-10|1997-02-20|DELIVER IN PERSON|TRUCK|press reque +4326|166954|9471|2|27|54565.65|0.06|0.01|N|O|1996-11-29|1997-01-20|1996-12-23|COLLECT COD|AIR|inal packages. final asymptotes about t +4327|94813|9832|1|18|32540.58|0.08|0.00|N|F|1995-06-16|1995-04-20|1995-07-12|COLLECT COD|RAIL|y final excuses. ironic, special requests a +4327|105917|8428|2|40|76916.40|0.07|0.01|N|F|1995-05-26|1995-04-17|1995-06-18|NONE|AIR|quests. packages are after th +4327|144418|6933|3|11|16086.51|0.10|0.07|R|F|1995-04-24|1995-05-27|1995-05-24|TAKE BACK RETURN|FOB| ironic dolphins +4327|20003|5008|4|8|7384.00|0.04|0.08|N|F|1995-05-26|1995-05-28|1995-06-19|DELIVER IN PERSON|AIR|eodolites cajole; unusual Tiresias +4327|189038|9039|5|39|43954.17|0.01|0.00|N|O|1995-06-23|1995-04-18|1995-07-13|TAKE BACK RETURN|FOB|kages against the blit +4327|151058|8604|6|10|11090.50|0.00|0.06|A|F|1995-04-28|1995-06-11|1995-05-07|TAKE BACK RETURN|TRUCK|arefully sile +4352|105786|8297|1|18|32252.04|0.00|0.03|N|O|1998-02-27|1998-02-02|1998-03-01|DELIVER IN PERSON|RAIL|ding to th +4353|93627|1155|1|22|35653.64|0.05|0.05|N|O|1998-01-19|1998-01-23|1998-02-10|COLLECT COD|FOB|ent packages. accounts are slyly. +4354|14218|6720|1|30|33966.30|0.08|0.07|R|F|1995-01-27|1994-11-24|1995-02-25|TAKE BACK RETURN|REG AIR|around the ir +4354|152107|7138|2|23|26659.30|0.01|0.08|R|F|1994-11-20|1994-12-23|1994-11-27|TAKE BACK RETURN|AIR|kly along the ironic, ent +4354|50734|5745|3|2|3369.46|0.10|0.04|A|F|1995-01-09|1994-12-15|1995-01-24|TAKE BACK RETURN|REG AIR|s nag quickly +4354|85171|2696|4|36|41622.12|0.05|0.05|A|F|1994-11-20|1994-12-06|1994-12-06|DELIVER IN PERSON|AIR| wake slyly eve +4354|64313|1832|5|37|47260.47|0.06|0.02|R|F|1995-01-13|1994-12-29|1995-01-31|DELIVER IN PERSON|FOB|deas use blithely! special foxes print af +4354|107393|2414|6|36|50414.04|0.03|0.04|R|F|1994-12-03|1994-12-05|1995-01-02|TAKE BACK RETURN|TRUCK|efully special packages use fluffily +4354|138728|1242|7|18|31800.96|0.03|0.04|A|F|1994-12-07|1994-12-11|1994-12-11|TAKE BACK RETURN|SHIP|ross the furiously +4355|194040|6560|1|32|36289.28|0.10|0.02|N|O|1996-12-29|1997-02-08|1997-01-24|DELIVER IN PERSON|REG AIR|y silent deposits. b +4355|16565|9067|2|4|5926.24|0.05|0.02|N|O|1997-02-25|1997-01-29|1997-03-17|TAKE BACK RETURN|TRUCK|slyly blithely regular packag +4355|738|739|3|13|21303.49|0.07|0.05|N|O|1997-01-21|1996-12-22|1997-02-14|COLLECT COD|TRUCK| ought to mold. blithely pending ideas +4355|193886|6406|4|14|27718.32|0.04|0.02|N|O|1997-03-08|1997-01-22|1997-03-26|NONE|RAIL|he furiously ironic accounts. quickly iro +4355|30531|8041|5|50|73076.50|0.10|0.00|N|O|1996-11-25|1997-01-01|1996-12-06|DELIVER IN PERSON|REG AIR| regular accounts boost along the +4355|121860|4373|6|35|65865.10|0.00|0.08|N|O|1997-01-28|1997-01-28|1997-02-20|NONE|FOB|ess accounts affix ironic +4355|100815|3326|7|47|85343.07|0.09|0.02|N|O|1996-12-28|1996-12-29|1997-01-09|NONE|RAIL|e. realms integrate +4356|193770|3771|1|35|65231.95|0.00|0.04|R|F|1994-05-30|1994-06-14|1994-06-08|COLLECT COD|MAIL|arefully ironic +4357|83306|831|1|50|64465.00|0.04|0.07|N|O|1997-11-25|1997-12-03|1997-12-17|DELIVER IN PERSON|RAIL|s. final, e +4357|107896|7897|2|17|32366.13|0.10|0.07|N|O|1998-02-01|1997-12-08|1998-02-09|DELIVER IN PERSON|MAIL|e carefully furiou +4358|125030|55|1|47|49586.41|0.04|0.00|N|O|1997-10-15|1997-10-14|1997-11-04|DELIVER IN PERSON|SHIP|refully busy dep +4359|173759|8794|1|41|75142.75|0.03|0.07|A|F|1993-04-06|1993-05-06|1993-04-14|COLLECT COD|RAIL|s affix sly +4359|152794|7825|2|8|14774.32|0.03|0.08|R|F|1993-06-27|1993-05-16|1993-07-04|DELIVER IN PERSON|MAIL|packages affix. fluffily regular f +4359|192211|7250|3|32|41702.72|0.10|0.03|R|F|1993-06-18|1993-04-04|1993-07-18|COLLECT COD|MAIL|olites nag quietly caref +4359|77506|14|4|1|1483.50|0.05|0.03|R|F|1993-04-27|1993-05-09|1993-05-08|NONE|MAIL| fluffily ironic, bold pac +4359|32507|7514|5|22|31669.00|0.04|0.01|A|F|1993-03-28|1993-06-01|1993-04-13|NONE|REG AIR|accounts wake ironic deposits. ironic +4384|135485|5486|1|5|7602.40|0.09|0.01|A|F|1992-08-22|1992-08-24|1992-09-20|DELIVER IN PERSON|MAIL|instructions sleep. blithely express pa +4384|88695|6220|2|38|63980.22|0.07|0.06|A|F|1992-10-18|1992-09-24|1992-11-04|NONE|FOB|ly final requests. regu +4384|88921|6446|3|11|21009.12|0.05|0.04|R|F|1992-08-31|1992-10-04|1992-09-28|TAKE BACK RETURN|FOB|deposits promise carefully even, regular e +4385|110994|6017|1|38|76189.62|0.00|0.02|N|O|1996-11-22|1996-10-30|1996-12-21|DELIVER IN PERSON|TRUCK|inal frays. final, bold exc +4386|129394|6931|1|10|14233.90|0.05|0.07|N|O|1998-06-03|1998-04-16|1998-06-28|TAKE BACK RETURN|MAIL|gainst the quickly expre +4386|117055|9567|2|28|30017.40|0.03|0.06|N|O|1998-03-19|1998-05-01|1998-03-27|NONE|FOB|. quick packages play slyly +4386|139628|4655|3|4|6670.48|0.07|0.05|N|O|1998-04-07|1998-03-25|1998-04-19|COLLECT COD|FOB|ns wake carefully carefully iron +4386|120458|459|4|21|31047.45|0.09|0.00|N|O|1998-05-05|1998-03-19|1998-05-13|NONE|RAIL|e pending, sp +4386|129214|6751|5|39|48485.19|0.09|0.06|N|O|1998-03-05|1998-03-15|1998-03-16|NONE|RAIL|structions cajole quickly express +4386|89453|9454|6|18|25964.10|0.02|0.05|N|O|1998-04-12|1998-04-09|1998-05-12|TAKE BACK RETURN|SHIP| deposits use according to the pending, +4386|19821|2323|7|16|27853.12|0.07|0.02|N|O|1998-05-05|1998-03-17|1998-06-03|COLLECT COD|AIR|e furiously final pint +4387|121746|9283|1|3|5303.22|0.02|0.01|N|O|1996-01-17|1996-01-14|1996-01-28|COLLECT COD|AIR| boost slyly ironic instructions. furiou +4387|176820|4372|2|48|91047.36|0.06|0.05|N|O|1995-10-29|1995-12-11|1995-11-01|NONE|REG AIR|sleep slyly. blithely sl +4387|1622|4123|3|15|22854.30|0.00|0.03|N|O|1996-01-11|1996-01-14|1996-01-30|TAKE BACK RETURN|REG AIR|s hinder quietly across the pla +4387|46843|6844|4|9|16108.56|0.00|0.03|N|O|1996-01-04|1995-12-26|1996-01-12|DELIVER IN PERSON|REG AIR|c ideas. slyly regular packages sol +4387|81324|6341|5|3|3915.96|0.05|0.08|N|O|1995-11-17|1995-12-28|1995-11-25|COLLECT COD|SHIP| pinto beans +4387|5012|2513|6|40|36680.40|0.02|0.04|N|O|1995-11-29|1995-12-10|1995-12-20|NONE|REG AIR|deas according to the blithely regular fox +4388|64943|2462|1|30|57238.20|0.02|0.07|N|O|1996-06-07|1996-05-07|1996-06-22|DELIVER IN PERSON|FOB|s cajole fluffil +4388|83255|8272|2|28|34671.00|0.05|0.04|N|O|1996-05-08|1996-06-20|1996-05-12|TAKE BACK RETURN|RAIL|ove the ide +4388|51377|8893|3|13|17268.81|0.07|0.05|N|O|1996-06-28|1996-05-23|1996-07-04|DELIVER IN PERSON|REG AIR|ly even, expre +4389|156730|1761|1|20|35734.60|0.08|0.00|A|F|1994-06-06|1994-06-17|1994-06-17|DELIVER IN PERSON|SHIP|ng the carefully express d +4389|152822|368|2|13|24372.66|0.00|0.00|A|F|1994-08-18|1994-06-06|1994-08-20|NONE|RAIL|nal, regula +4389|78001|509|3|39|38181.00|0.04|0.07|A|F|1994-06-08|1994-06-04|1994-06-10|TAKE BACK RETURN|TRUCK| unusual, final excuses cajole carefully +4389|159554|7100|4|5|8067.75|0.09|0.00|A|F|1994-09-03|1994-06-23|1994-09-16|NONE|FOB| ironic request +4389|10461|2963|5|22|30172.12|0.08|0.00|R|F|1994-07-05|1994-06-12|1994-07-12|NONE|TRUCK|lly silent de +4389|1428|1429|6|22|29247.24|0.01|0.04|R|F|1994-06-07|1994-06-29|1994-06-19|COLLECT COD|TRUCK|at the final excuses hinder carefully a +4389|184028|4029|7|4|4448.08|0.09|0.08|R|F|1994-06-14|1994-06-30|1994-07-06|NONE|REG AIR| blithely even d +4390|151140|3656|1|35|41689.90|0.07|0.04|R|F|1995-05-30|1995-07-02|1995-06-15|DELIVER IN PERSON|TRUCK|ongside of the slyly regular ideas +4390|195068|7588|2|28|32565.68|0.03|0.00|N|O|1995-09-07|1995-06-22|1995-10-05|COLLECT COD|SHIP|ld braids haggle atop the for +4390|100762|8293|3|42|74035.92|0.05|0.08|A|F|1995-06-12|1995-07-16|1995-06-17|NONE|AIR|arefully even accoun +4390|97112|4640|4|32|35491.52|0.07|0.08|N|O|1995-09-15|1995-08-12|1995-10-05|TAKE BACK RETURN|TRUCK|ctions across +4391|160992|3509|1|1|2052.99|0.09|0.00|R|F|1992-06-18|1992-04-27|1992-06-20|COLLECT COD|TRUCK|ong the silent deposits +4391|186943|4498|2|45|91347.30|0.07|0.04|R|F|1992-04-01|1992-05-01|1992-04-13|TAKE BACK RETURN|TRUCK|ep quickly after +4416|93919|8938|1|37|70777.67|0.08|0.03|A|F|1992-10-23|1992-08-23|1992-11-16|COLLECT COD|RAIL|fluffily ironic +4416|88976|8977|2|3|5894.91|0.06|0.03|R|F|1992-10-22|1992-08-06|1992-11-13|DELIVER IN PERSON|SHIP| requests sleep along the +4416|8657|6158|3|45|70454.25|0.09|0.03|A|F|1992-10-16|1992-09-09|1992-10-28|COLLECT COD|AIR|the final pinto beans. special frets +4417|74480|6988|1|28|40725.44|0.08|0.02|N|O|1998-09-04|1998-10-04|1998-09-19|TAKE BACK RETURN|REG AIR|ies across the furious +4417|180729|5766|2|1|1809.72|0.06|0.08|N|O|1998-10-23|1998-08-22|1998-10-24|NONE|REG AIR|press deposits promise stealthily amo +4417|97701|5229|3|35|59454.50|0.06|0.04|N|O|1998-08-08|1998-09-23|1998-09-02|DELIVER IN PERSON|FOB|slyly regular, silent courts. even packag +4418|34773|7277|1|32|54648.64|0.02|0.06|A|F|1993-05-28|1993-06-02|1993-05-30|TAKE BACK RETURN|RAIL|ly. bold pinto b +4418|21913|9420|2|14|25688.74|0.03|0.04|A|F|1993-05-20|1993-06-18|1993-06-05|TAKE BACK RETURN|SHIP| blithely regular requests. blith +4418|78027|5549|3|3|3015.06|0.00|0.02|R|F|1993-04-08|1993-06-04|1993-05-02|NONE|SHIP|luffily across the unusual ideas. reque +4419|107398|7399|1|45|63242.55|0.01|0.05|N|O|1996-07-20|1996-09-07|1996-08-18|DELIVER IN PERSON|TRUCK|s doze sometimes fluffily regular a +4419|31638|4142|2|42|65924.46|0.00|0.03|N|O|1996-09-18|1996-07-25|1996-09-21|COLLECT COD|RAIL|sts. furious +4419|131738|6765|3|6|10618.38|0.02|0.08|N|O|1996-06-25|1996-09-04|1996-07-20|DELIVER IN PERSON|AIR|ts wake slyly final dugou +4420|7317|4818|1|7|8570.17|0.07|0.03|R|F|1994-08-30|1994-09-03|1994-09-25|NONE|FOB| regular instructions sleep around +4421|97523|5051|1|37|56259.24|0.09|0.08|N|O|1997-07-22|1997-06-27|1997-07-25|DELIVER IN PERSON|SHIP|l accounts. ironic request +4421|55380|391|2|46|61427.48|0.04|0.04|N|O|1997-04-21|1997-05-13|1997-05-15|DELIVER IN PERSON|FOB|reful packages. bold, +4421|166181|8698|3|46|57370.28|0.00|0.06|N|O|1997-05-25|1997-05-21|1997-06-23|COLLECT COD|TRUCK|g dependenci +4421|190694|5733|4|32|57110.08|0.06|0.04|N|O|1997-07-09|1997-06-03|1997-07-25|NONE|SHIP|ar ideas eat among the furiousl +4421|189912|9913|5|32|64061.12|0.06|0.04|N|O|1997-07-28|1997-06-14|1997-08-13|NONE|REG AIR|uickly final pinto beans impress. bold +4421|46583|4096|6|44|67301.52|0.09|0.06|N|O|1997-06-17|1997-06-20|1997-06-29|NONE|TRUCK|le carefully. bl +4421|115306|329|7|18|23783.40|0.01|0.00|N|O|1997-06-07|1997-05-13|1997-06-10|DELIVER IN PERSON|FOB|. regular, s +4422|134519|2059|1|5|7767.55|0.09|0.07|N|O|1995-07-17|1995-08-13|1995-07-25|NONE|SHIP|e furiously about t +4422|47451|9956|2|41|57336.45|0.08|0.05|N|F|1995-06-12|1995-07-09|1995-06-20|COLLECT COD|TRUCK| theodolites shal +4422|102348|9879|3|39|52663.26|0.00|0.05|N|O|1995-09-02|1995-06-24|1995-09-14|NONE|TRUCK|en hockey players engage +4422|152192|2193|4|4|4976.76|0.02|0.05|N|O|1995-09-18|1995-08-12|1995-10-18|COLLECT COD|FOB|cies along the bo +4422|79692|4707|5|20|33433.80|0.07|0.05|N|O|1995-08-17|1995-07-16|1995-09-13|DELIVER IN PERSON|RAIL|ructions wake slyly al +4423|149239|6782|1|3|3864.69|0.03|0.00|A|F|1995-03-22|1995-04-06|1995-04-19|NONE|TRUCK| final theodolites nag after the bli +4423|59576|4587|2|2|3071.14|0.07|0.04|A|F|1995-03-04|1995-04-04|1995-03-08|TAKE BACK RETURN|REG AIR|old sheaves sleep +4448|51574|6585|1|24|36613.68|0.10|0.07|N|O|1998-09-09|1998-07-06|1998-09-27|DELIVER IN PERSON|SHIP|nal packages along the ironic instructi +4448|188627|1146|2|13|22303.06|0.00|0.01|N|O|1998-07-26|1998-07-03|1998-08-14|COLLECT COD|MAIL|fluffily express accounts integrate furiou +4448|40980|5989|3|35|67234.30|0.10|0.06|N|O|1998-09-18|1998-07-27|1998-10-08|NONE|REG AIR|aggle carefully alongside of the q +4448|140138|139|4|3|3534.39|0.01|0.01|N|O|1998-07-20|1998-07-10|1998-08-07|DELIVER IN PERSON|TRUCK|ronic theod +4448|90140|141|5|41|46335.74|0.00|0.08|N|O|1998-07-30|1998-08-09|1998-08-03|NONE|AIR|pon the permanently even excuses nag +4448|171401|1402|6|12|17668.80|0.06|0.03|N|O|1998-08-21|1998-06-30|1998-09-09|COLLECT COD|RAIL|sits about the ironic, bu +4449|31484|6491|1|42|59450.16|0.10|0.07|N|O|1998-03-22|1998-05-09|1998-04-03|NONE|FOB| packages. blithely final +4449|140638|3153|2|10|16786.30|0.02|0.03|N|O|1998-05-09|1998-05-04|1998-05-15|NONE|SHIP|ccounts alongside of the platelets integr +4450|173191|3192|1|44|55624.36|0.10|0.00|N|O|1997-10-12|1997-10-13|1997-10-29|DELIVER IN PERSON|RAIL| the slyly eve +4450|14714|4715|2|9|14658.39|0.03|0.03|N|O|1997-08-13|1997-08-16|1997-08-15|NONE|FOB|gular requests cajole carefully. regular c +4450|95500|8010|3|45|67297.50|0.08|0.01|N|O|1997-09-01|1997-10-06|1997-09-19|NONE|TRUCK|express ideas are furiously regular +4450|61930|6943|4|13|24595.09|0.00|0.00|N|O|1997-08-26|1997-09-18|1997-09-20|COLLECT COD|MAIL| brave foxes. slyly unusual +4450|55040|5041|5|6|5970.24|0.09|0.01|N|O|1997-09-02|1997-09-30|1997-09-09|NONE|FOB|eposits. foxes cajole unusual fox +4451|163032|3033|1|40|43801.20|0.03|0.03|A|F|1994-11-18|1994-12-25|1994-11-26|DELIVER IN PERSON|RAIL|y. slyly special deposits are sly +4451|62282|2283|2|34|42305.52|0.10|0.02|A|F|1994-11-30|1994-12-04|1994-12-13|COLLECT COD|SHIP| regular ideas. +4451|158586|8587|3|19|31247.02|0.05|0.06|R|F|1994-10-09|1994-11-26|1994-10-23|COLLECT COD|FOB|ly after the fluffi +4452|113429|5941|1|21|30290.82|0.07|0.03|R|F|1994-10-06|1994-08-23|1994-10-15|COLLECT COD|TRUCK|multipliers x-ray carefully in place of +4452|149|7650|2|47|49309.58|0.01|0.06|A|F|1994-10-08|1994-08-09|1994-10-09|TAKE BACK RETURN|TRUCK|ts. slyly regular cour +4453|146971|2000|1|41|82736.77|0.00|0.08|N|O|1997-07-17|1997-05-15|1997-07-31|NONE|REG AIR|anent theodolites are slyly except t +4453|132711|2712|2|16|27899.36|0.03|0.00|N|O|1997-07-22|1997-05-05|1997-08-03|COLLECT COD|FOB|ar excuses nag quickly even accounts. b +4453|61826|9345|3|48|85815.36|0.02|0.07|N|O|1997-05-29|1997-06-24|1997-06-03|NONE|SHIP|eep. fluffily express accounts at the furi +4453|101706|4217|4|26|44400.20|0.06|0.07|N|O|1997-05-07|1997-06-07|1997-05-22|NONE|TRUCK|express packages are +4454|150851|3367|1|20|38037.00|0.10|0.08|R|F|1994-05-06|1994-03-17|1994-05-20|COLLECT COD|SHIP|lar theodolites. even instructio +4454|151032|3548|2|22|23826.66|0.06|0.02|A|F|1994-02-06|1994-04-11|1994-03-06|DELIVER IN PERSON|RAIL|ully. carefully final accounts accordi +4454|191552|1553|3|45|73959.75|0.07|0.04|A|F|1994-03-29|1994-03-26|1994-04-04|TAKE BACK RETURN|RAIL|ests promise. packages print fur +4454|1324|1325|4|1|1225.32|0.09|0.05|A|F|1994-02-05|1994-04-19|1994-02-12|COLLECT COD|RAIL|equests run. +4454|51060|8576|5|48|48530.88|0.00|0.07|R|F|1994-04-23|1994-04-03|1994-04-26|COLLECT COD|FOB|to beans wake across th +4454|159632|2148|6|20|33832.60|0.10|0.03|A|F|1994-04-08|1994-03-06|1994-04-26|DELIVER IN PERSON|TRUCK|quickly regular requests. furiously +4455|69731|7250|1|20|34014.60|0.01|0.05|A|F|1994-01-31|1993-11-21|1994-03-02|DELIVER IN PERSON|MAIL| express packages. packages boost quickly +4455|152587|2588|2|47|77060.26|0.09|0.01|R|F|1994-01-01|1993-12-25|1994-01-05|COLLECT COD|FOB| requests. even, even accou +4455|122723|7748|3|34|59354.48|0.00|0.06|A|F|1993-10-24|1993-11-27|1993-11-04|TAKE BACK RETURN|AIR| slyly ironic requests. quickly even d +4480|107888|5419|1|30|56876.40|0.08|0.03|R|F|1994-07-29|1994-06-22|1994-08-01|NONE|FOB|ven braids us +4481|23918|6421|1|50|92095.50|0.02|0.06|N|O|1996-07-22|1996-05-13|1996-08-14|DELIVER IN PERSON|RAIL|ar packages. regula +4481|189040|1559|2|27|30484.08|0.02|0.03|N|O|1996-04-06|1996-05-17|1996-04-12|TAKE BACK RETURN|AIR|ackages haggle even, +4482|70869|870|1|32|58875.52|0.06|0.03|A|F|1995-05-16|1995-07-22|1995-06-07|NONE|RAIL| quickly pendin +4482|95182|201|2|32|37669.76|0.01|0.06|N|O|1995-08-16|1995-06-26|1995-09-10|DELIVER IN PERSON|AIR|eans wake according +4483|5133|5134|1|32|33220.16|0.07|0.07|R|F|1992-04-05|1992-05-25|1992-04-08|DELIVER IN PERSON|MAIL|ests haggle. slyl +4483|61832|4339|2|50|89691.50|0.01|0.06|A|F|1992-06-19|1992-05-12|1992-07-08|DELIVER IN PERSON|TRUCK|ag blithely even +4483|8334|3335|3|50|62116.50|0.00|0.04|R|F|1992-06-10|1992-04-18|1992-06-17|DELIVER IN PERSON|MAIL|ackages. furiously ironi +4484|94779|2307|1|4|7095.08|0.06|0.03|N|O|1997-04-09|1997-02-11|1997-04-12|TAKE BACK RETURN|TRUCK|packages de +4484|136812|6813|2|39|72103.59|0.05|0.02|N|O|1997-04-01|1997-01-26|1997-04-21|NONE|RAIL|onic accounts wake blithel +4484|190000|1|3|38|41420.00|0.06|0.07|N|O|1997-03-07|1997-01-31|1997-04-01|COLLECT COD|REG AIR|. even requests un +4484|121153|8690|4|41|48140.15|0.06|0.03|N|O|1997-01-25|1997-02-15|1997-01-29|TAKE BACK RETURN|REG AIR|ress accounts. ironic deposits unwind fur +4484|2585|2586|5|42|62478.36|0.03|0.07|N|O|1997-03-25|1997-02-21|1997-04-05|DELIVER IN PERSON|REG AIR|ding, pending requests wake. fluffily +4484|35516|5517|6|29|42093.79|0.09|0.06|N|O|1996-12-27|1997-03-10|1997-01-13|NONE|FOB| wake blithely ironic +4484|102267|7288|7|50|63463.00|0.07|0.01|N|O|1997-03-17|1997-03-16|1997-03-21|COLLECT COD|FOB|the ironic, final theodo +4485|190656|8214|1|1|1746.65|0.03|0.05|R|F|1994-12-04|1995-02-07|1994-12-09|NONE|AIR|play according to the ironic, ironic +4485|140072|7615|2|46|51155.22|0.04|0.06|R|F|1995-03-09|1994-12-14|1995-03-23|DELIVER IN PERSON|AIR|. ironic foxes haggle. regular war +4485|174651|4652|3|43|74202.95|0.01|0.05|R|F|1995-01-17|1995-02-11|1995-02-07|DELIVER IN PERSON|TRUCK|al accounts according to the slyly r +4485|143072|3073|4|43|47948.01|0.08|0.06|R|F|1995-01-28|1995-01-26|1995-02-07|DELIVER IN PERSON|AIR|. blithely +4485|5035|5036|5|47|44181.41|0.08|0.04|R|F|1995-03-11|1995-01-11|1995-03-21|TAKE BACK RETURN|RAIL|luffily pending acc +4486|134209|6723|1|46|57187.20|0.08|0.00|N|O|1998-05-02|1998-04-05|1998-05-08|COLLECT COD|MAIL|ackages. specia +4486|48748|3757|2|19|32238.06|0.10|0.01|N|O|1998-06-07|1998-05-28|1998-07-02|NONE|MAIL|pending foxes after +4486|95192|5193|3|47|55797.93|0.02|0.07|N|O|1998-04-09|1998-05-24|1998-05-07|DELIVER IN PERSON|MAIL|ts around the quiet packages ar +4486|90018|5037|4|28|28224.28|0.07|0.02|N|O|1998-04-21|1998-04-19|1998-04-26|TAKE BACK RETURN|AIR|to the furious, regular foxes play abov +4487|137105|9619|1|37|42257.70|0.03|0.07|R|F|1993-02-28|1993-04-18|1993-03-17|TAKE BACK RETURN|MAIL|bove the fu +4487|112846|7869|2|49|91083.16|0.10|0.00|R|F|1993-06-13|1993-05-08|1993-07-10|COLLECT COD|FOB|sual packages should ha +4487|189582|2101|3|1|1671.58|0.02|0.07|A|F|1993-05-11|1993-05-23|1993-05-17|TAKE BACK RETURN|FOB|ithely final asym +4487|92846|2847|4|25|45971.00|0.07|0.03|A|F|1993-03-09|1993-04-27|1993-03-30|COLLECT COD|RAIL|g the final instructions. slyly c +4512|161210|3727|1|30|38136.30|0.07|0.07|N|O|1996-01-28|1995-12-22|1996-02-22|TAKE BACK RETURN|TRUCK|ly unusual package +4512|40933|5942|2|24|44974.32|0.04|0.06|N|O|1995-12-16|1996-01-16|1995-12-25|NONE|SHIP|ly regular pinto beans. carefully bold depo +4512|144996|25|3|21|42860.79|0.00|0.00|N|O|1995-10-31|1995-12-30|1995-11-15|NONE|REG AIR|lly unusual pinto b +4512|140248|249|4|32|41223.68|0.10|0.01|N|O|1995-11-25|1995-12-28|1995-12-06|NONE|FOB|counts are against the quickly regular +4512|132998|8025|5|43|87332.57|0.06|0.00|N|O|1995-12-20|1995-11-28|1996-01-14|NONE|AIR|are carefully. theodolites wake +4513|169018|9019|1|29|31523.29|0.03|0.01|N|O|1996-05-18|1996-05-23|1996-06-08|NONE|REG AIR|cajole. regular packages boost. s +4513|69944|2451|2|39|74643.66|0.01|0.04|N|O|1996-06-25|1996-05-14|1996-07-24|NONE|MAIL|slyly furiously unusual deposits. blit +4513|137348|4888|3|34|47101.56|0.00|0.03|N|O|1996-03-27|1996-06-12|1996-04-06|DELIVER IN PERSON|SHIP|sits. quickly even instructions +4513|191361|8919|4|13|18880.68|0.08|0.08|N|O|1996-04-12|1996-05-19|1996-04-25|DELIVER IN PERSON|AIR|l, final excuses detect furi +4514|163673|1222|1|27|46890.09|0.06|0.06|R|F|1994-07-01|1994-07-13|1994-07-26|COLLECT COD|AIR| even, silent foxes be +4514|45129|7634|2|15|16111.80|0.10|0.04|R|F|1994-08-24|1994-07-11|1994-09-14|DELIVER IN PERSON|RAIL|! unusual, special deposits afte +4514|77425|9933|3|10|14024.20|0.09|0.05|A|F|1994-06-19|1994-06-25|1994-07-01|COLLECT COD|SHIP|ake furiously. carefully regular requests +4514|80738|3247|4|9|15468.57|0.10|0.03|A|F|1994-08-04|1994-07-01|1994-09-01|DELIVER IN PERSON|REG AIR|wly. quick +4514|148628|6171|5|12|20119.44|0.02|0.03|R|F|1994-08-20|1994-06-09|1994-09-15|TAKE BACK RETURN|FOB| carefully ironic foxes nag caref +4514|188706|8707|6|38|68198.60|0.03|0.05|A|F|1994-07-28|1994-07-06|1994-08-25|NONE|AIR|ending excuses. sl +4514|176429|6430|7|27|40646.34|0.04|0.06|A|F|1994-06-24|1994-07-14|1994-06-30|TAKE BACK RETURN|TRUCK|. slyly sile +4515|38003|8004|1|15|14115.00|0.06|0.01|R|F|1992-05-26|1992-05-25|1992-06-03|NONE|SHIP|posits wake +4515|102050|9581|2|50|52602.50|0.06|0.03|A|F|1992-03-28|1992-05-16|1992-04-20|NONE|AIR|ding instructions again +4515|153202|748|3|27|33890.40|0.09|0.01|A|F|1992-06-06|1992-06-08|1992-06-07|DELIVER IN PERSON|REG AIR| against the even re +4515|53814|3815|4|32|56569.92|0.06|0.03|R|F|1992-04-07|1992-05-11|1992-04-09|COLLECT COD|MAIL|carefully express depo +4515|44659|9668|5|22|35280.30|0.09|0.07|A|F|1992-07-16|1992-05-07|1992-07-23|NONE|SHIP|le quickly above the even, bold ideas. +4515|179908|7460|6|23|45721.70|0.04|0.00|R|F|1992-05-23|1992-06-15|1992-06-20|TAKE BACK RETURN|FOB|ns. bold r +4516|169570|2087|1|34|55745.38|0.05|0.04|A|F|1994-05-16|1994-06-23|1994-06-12|NONE|SHIP|even pinto beans wake qui +4517|42540|2541|1|50|74127.00|0.01|0.02|N|O|1998-06-08|1998-04-18|1998-06-20|DELIVER IN PERSON|MAIL|refully pending acco +4518|143741|8770|1|9|16062.66|0.09|0.04|N|O|1997-06-26|1997-07-07|1997-07-10|NONE|RAIL| pending deposits. slyly re +4518|44083|4084|2|19|19514.52|0.10|0.05|N|O|1997-08-09|1997-06-06|1997-08-27|COLLECT COD|RAIL|ter the slyly bo +4519|54680|7186|1|30|49040.40|0.09|0.07|R|F|1993-04-11|1993-06-05|1993-04-22|DELIVER IN PERSON|REG AIR|totes. slyly bold somas after the +4519|190062|2582|2|37|42626.22|0.06|0.08|R|F|1993-07-22|1993-06-16|1993-08-19|COLLECT COD|AIR|ly slyly furious depth +4544|130682|3196|1|40|68507.20|0.07|0.01|N|O|1997-08-15|1997-10-16|1997-08-20|DELIVER IN PERSON|RAIL| detect slyly. evenly pending instru +4544|171088|3606|2|19|22022.52|0.08|0.01|N|O|1997-08-14|1997-09-08|1997-08-25|NONE|SHIP|regular ideas are furiously about +4544|70629|8151|3|20|31992.40|0.02|0.07|N|O|1997-10-12|1997-10-11|1997-10-13|COLLECT COD|REG AIR| waters about the +4544|50571|5582|4|39|59341.23|0.07|0.05|N|O|1997-08-20|1997-09-07|1997-08-27|COLLECT COD|REG AIR|ular packages. s +4544|132280|7307|5|31|40680.68|0.09|0.03|N|O|1997-08-09|1997-09-29|1997-08-17|COLLECT COD|TRUCK|dolites detect quickly reg +4544|26100|6101|6|8|8208.80|0.10|0.03|N|O|1997-10-13|1997-10-06|1997-10-25|COLLECT COD|AIR|olites. fi +4545|172885|437|1|38|74399.44|0.06|0.06|R|F|1993-01-27|1993-03-01|1993-02-04|NONE|TRUCK|nts serve according to th +4545|62456|2457|2|27|38298.15|0.01|0.06|R|F|1993-02-07|1993-02-18|1993-02-18|NONE|FOB|ously bold asymptotes! blithely pen +4545|86195|3720|3|9|10630.71|0.10|0.06|R|F|1993-03-20|1993-02-23|1993-04-11|TAKE BACK RETURN|AIR|xpress accounts +4545|63981|1500|4|2|3889.96|0.10|0.00|R|F|1993-04-16|1993-04-17|1993-05-03|NONE|REG AIR|ages use. slyly even i +4545|116732|9244|5|27|47215.71|0.08|0.05|A|F|1993-03-18|1993-02-22|1993-03-23|NONE|RAIL|ccounts haggle carefully. deposits +4545|108682|1193|6|8|13525.44|0.03|0.02|A|F|1993-05-01|1993-03-12|1993-05-15|NONE|FOB| boost slyly. slyly +4545|8362|863|7|36|45732.96|0.10|0.04|R|F|1993-01-28|1993-03-30|1993-02-04|DELIVER IN PERSON|SHIP|sublate slyly. furiously ironic accounts b +4546|132467|7494|1|10|14994.60|0.09|0.02|N|O|1995-09-23|1995-10-10|1995-10-23|COLLECT COD|TRUCK|osits alongside of the +4546|170327|5362|2|15|20959.80|0.04|0.07|N|O|1995-07-31|1995-10-17|1995-08-06|NONE|REG AIR|ught to cajole furiously. qu +4546|76977|6978|3|4|7815.88|0.06|0.08|N|O|1995-08-14|1995-10-07|1995-08-16|COLLECT COD|MAIL|kly pending dependencies along the furio +4546|148745|1260|4|10|17937.40|0.08|0.02|N|O|1995-09-02|1995-09-16|1995-09-10|DELIVER IN PERSON|FOB|above the enticingly ironic dependencies +4547|187798|317|1|15|28286.85|0.10|0.04|A|F|1993-12-08|1993-11-15|1993-12-22|NONE|REG AIR|ets haggle. regular dinos affix fu +4547|115181|7693|2|7|8373.26|0.10|0.02|A|F|1993-09-04|1993-09-29|1993-09-20|COLLECT COD|RAIL|slyly express a +4547|44955|7460|3|15|28499.25|0.00|0.00|R|F|1993-11-18|1993-10-06|1993-12-13|NONE|TRUCK|e carefully across the unus +4547|147087|4630|4|15|17011.20|0.05|0.08|R|F|1993-11-29|1993-10-12|1993-12-29|COLLECT COD|REG AIR|ironic gifts integrate +4548|13272|5774|1|21|24890.67|0.10|0.05|N|O|1996-07-11|1996-09-04|1996-07-30|COLLECT COD|REG AIR|pecial theodoli +4548|46001|1010|2|17|16099.00|0.00|0.08|N|O|1996-07-23|1996-09-21|1996-07-26|DELIVER IN PERSON|REG AIR|y ironic requests above the fluffily d +4548|122710|7735|3|47|81437.37|0.05|0.04|N|O|1996-07-24|1996-09-12|1996-08-08|NONE|MAIL|ts. excuses use slyly spec +4548|176323|1358|4|22|30785.04|0.07|0.01|N|O|1996-07-06|1996-08-23|1996-07-15|DELIVER IN PERSON|RAIL|s. furiously ironic theodolites c +4548|44556|2069|5|36|54019.80|0.04|0.06|N|O|1996-08-19|1996-09-12|1996-09-08|COLLECT COD|FOB|tions integrat +4549|158023|5569|1|44|47564.88|0.08|0.00|N|O|1998-03-13|1998-04-15|1998-03-27|TAKE BACK RETURN|TRUCK|ding to the regular, silent requests +4549|88030|539|2|1|1018.03|0.05|0.08|N|O|1998-05-04|1998-04-11|1998-05-14|TAKE BACK RETURN|AIR| requests wake. furiously even +4550|149038|1553|1|9|9783.27|0.05|0.06|R|F|1995-04-19|1995-02-07|1995-04-24|COLLECT COD|SHIP|l dependencies boost slyly after th +4550|65547|8054|2|19|28738.26|0.06|0.04|A|F|1995-01-01|1995-02-13|1995-01-20|NONE|AIR|quests. express +4551|10447|7951|1|6|8144.64|0.08|0.08|N|O|1996-05-18|1996-04-23|1996-06-13|DELIVER IN PERSON|TRUCK|fily silent fo +4551|178094|3129|2|26|30474.34|0.02|0.04|N|O|1996-04-14|1996-04-26|1996-04-17|TAKE BACK RETURN|RAIL|le. carefully dogged accounts use furiousl +4551|21706|6711|3|22|35809.40|0.08|0.01|N|O|1996-05-12|1996-03-17|1996-05-29|TAKE BACK RETURN|REG AIR|ly ironic reques +4551|197665|185|4|27|47591.82|0.00|0.01|N|O|1996-04-28|1996-03-22|1996-05-22|TAKE BACK RETURN|RAIL|y along the slyly even +4576|89514|9515|1|5|7517.55|0.09|0.03|N|O|1996-08-23|1996-11-08|1996-09-20|TAKE BACK RETURN|AIR|ly express, special asymptote +4576|57907|7908|2|43|80190.70|0.08|0.06|N|O|1996-10-24|1996-09-23|1996-11-10|NONE|SHIP|ly final deposits. never +4576|41350|8863|3|14|18078.90|0.09|0.01|N|O|1996-09-12|1996-09-30|1996-09-24|COLLECT COD|MAIL|detect slyly. +4577|184089|6608|1|43|50442.44|0.01|0.03|N|O|1998-06-16|1998-07-09|1998-06-17|TAKE BACK RETURN|AIR|packages. +4577|176990|2025|2|43|88880.57|0.05|0.03|N|O|1998-08-24|1998-06-02|1998-09-14|TAKE BACK RETURN|RAIL|ly accounts. carefully +4577|68494|3507|3|12|17549.88|0.07|0.05|N|O|1998-07-29|1998-06-17|1998-08-04|DELIVER IN PERSON|TRUCK|equests alongsi +4578|73111|633|1|10|10841.10|0.09|0.06|R|F|1993-01-01|1992-11-19|1993-01-28|TAKE BACK RETURN|REG AIR|uests. blithely unus +4578|168393|8394|2|42|61378.38|0.06|0.00|R|F|1993-01-05|1992-11-06|1993-01-13|DELIVER IN PERSON|FOB|s are caref +4578|178494|3529|3|15|23587.35|0.01|0.01|R|F|1992-10-23|1992-11-22|1992-11-09|DELIVER IN PERSON|REG AIR|gular theodo +4578|138667|3694|4|7|11939.62|0.09|0.08|A|F|1992-12-07|1992-11-27|1993-01-05|TAKE BACK RETURN|SHIP|odolites. carefully unusual ideas accor +4578|162341|4858|5|20|28066.80|0.04|0.02|A|F|1993-01-11|1992-11-09|1993-01-23|TAKE BACK RETURN|RAIL|iously pending theodolites-- +4579|174085|9120|1|14|16227.12|0.02|0.02|N|O|1996-02-01|1996-01-08|1996-02-08|TAKE BACK RETURN|MAIL|nding theodolites. fluffil +4579|41886|1887|2|28|51180.64|0.02|0.05|N|O|1996-01-22|1996-02-13|1996-02-03|DELIVER IN PERSON|RAIL|slyly across the +4579|177457|7458|3|34|52171.30|0.05|0.02|N|O|1996-02-26|1996-02-22|1996-03-16|COLLECT COD|MAIL|hely. carefully blithe dependen +4579|119554|9555|4|8|12588.40|0.05|0.06|N|O|1995-12-16|1996-01-15|1995-12-18|TAKE BACK RETURN|AIR|posits. carefully perman +4580|91060|6079|1|22|23123.32|0.01|0.05|A|F|1994-01-16|1994-01-26|1994-02-05|COLLECT COD|AIR|nticingly final packag +4580|31880|6887|2|10|18118.80|0.05|0.04|R|F|1993-12-20|1993-12-30|1994-01-17|COLLECT COD|RAIL|gular, pending deposits. fina +4580|963|8464|3|41|76422.36|0.00|0.07|R|F|1993-12-13|1994-01-31|1994-01-06|NONE|SHIP|requests. quickly silent asymptotes sle +4580|177771|289|4|5|9243.85|0.07|0.00|A|F|1994-01-28|1993-12-17|1994-02-22|NONE|TRUCK|o beans. f +4580|188804|1323|5|39|73819.20|0.03|0.02|R|F|1993-12-28|1993-12-26|1994-01-23|NONE|RAIL|. fluffily final dolphins use furiously al +4581|164947|7464|1|37|74441.78|0.01|0.04|A|F|1992-10-17|1992-11-05|1992-11-04|DELIVER IN PERSON|MAIL|e the blithely bold pearls ha +4581|49672|4681|2|7|11351.69|0.01|0.02|A|F|1992-10-09|1992-10-20|1992-10-21|TAKE BACK RETURN|MAIL|express accounts d +4581|20508|5513|3|46|65711.00|0.04|0.04|A|F|1992-09-09|1992-11-27|1992-09-26|NONE|REG AIR|nag toward the carefully final accounts. +4582|191457|6496|1|17|26323.65|0.09|0.08|N|O|1996-08-17|1996-08-26|1996-08-20|COLLECT COD|REG AIR|ng packages. depo +4583|140441|442|1|17|25184.48|0.01|0.05|A|F|1994-11-08|1994-11-03|1994-11-29|COLLECT COD|MAIL|romise. reques +4583|186542|6543|2|43|70027.22|0.04|0.04|A|F|1994-10-30|1994-12-17|1994-11-16|COLLECT COD|RAIL|fully after the speci +4583|195513|3071|3|28|45038.28|0.00|0.07|A|F|1994-10-29|1994-11-21|1994-11-28|NONE|SHIP|to beans haggle sly +4583|172130|2131|4|27|32457.51|0.08|0.03|R|F|1995-01-11|1994-12-24|1995-02-10|DELIVER IN PERSON|TRUCK| detect silent requests. furiously speci +4583|183800|8837|5|36|67816.80|0.09|0.06|A|F|1995-01-06|1994-11-25|1995-01-29|DELIVER IN PERSON|RAIL|ar requests haggle after the furiously +4583|121705|4218|6|14|24173.80|0.09|0.01|R|F|1994-11-17|1994-11-08|1994-11-21|DELIVER IN PERSON|AIR|detect. doggedly regular pi +4583|86867|1884|7|32|59323.52|0.04|0.00|A|F|1995-01-13|1994-10-29|1995-02-08|TAKE BACK RETURN|RAIL|across the pinto beans-- quickly +4608|172217|9769|1|30|38676.30|0.08|0.05|R|F|1994-10-08|1994-07-18|1994-10-25|DELIVER IN PERSON|SHIP|s cajole. slyly +4608|46212|6213|2|50|57910.50|0.06|0.01|A|F|1994-07-25|1994-09-01|1994-08-10|NONE|FOB| theodolites +4608|78184|692|3|50|58109.00|0.03|0.01|A|F|1994-08-04|1994-09-10|1994-08-13|COLLECT COD|TRUCK| wake closely. even decoys haggle above +4608|30557|558|4|36|53551.80|0.05|0.06|R|F|1994-10-04|1994-08-02|1994-10-21|COLLECT COD|FOB|ages wake quickly slyly iron +4609|46409|3922|1|28|37951.20|0.10|0.05|N|O|1997-02-02|1997-02-17|1997-03-02|DELIVER IN PERSON|REG AIR|ously. quickly final requests cajole fl +4609|184318|6837|2|3|4206.93|0.09|0.03|N|O|1996-12-28|1997-02-06|1997-01-20|NONE|FOB|nstructions. furious instructions +4609|22399|2400|3|46|60783.94|0.05|0.05|N|O|1997-02-11|1997-01-16|1997-03-07|NONE|FOB|r foxes. fluffily ironic ideas ha +4610|86177|1194|1|21|24426.57|0.07|0.07|R|F|1993-08-10|1993-08-05|1993-08-27|NONE|REG AIR|ly special theodolites. even, +4610|174842|7360|2|14|26835.76|0.00|0.07|R|F|1993-07-28|1993-07-25|1993-07-31|TAKE BACK RETURN|SHIP| ironic frays. dependencies detect blithel +4610|158379|5925|3|44|63244.28|0.05|0.03|A|F|1993-08-05|1993-07-20|1993-08-19|COLLECT COD|TRUCK| final theodolites +4610|74538|2060|4|26|39325.78|0.06|0.03|R|F|1993-07-01|1993-07-19|1993-07-19|NONE|MAIL| to the fluffily ironic requests h +4610|146158|6159|5|29|34920.35|0.08|0.04|R|F|1993-08-09|1993-07-27|1993-08-16|DELIVER IN PERSON|AIR| foxes. special, express package +4611|51267|6278|1|47|57258.22|0.09|0.06|A|F|1993-03-05|1993-03-01|1993-03-17|COLLECT COD|TRUCK|iously. furiously regular +4611|34872|4873|2|31|56012.97|0.04|0.02|A|F|1993-01-28|1993-02-14|1993-01-29|TAKE BACK RETURN|AIR| final pinto beans. permanent, sp +4611|81649|1650|3|50|81532.00|0.08|0.01|R|F|1993-01-22|1993-03-30|1993-02-16|TAKE BACK RETURN|AIR|l platelets. +4611|70451|7973|4|48|68229.60|0.02|0.08|R|F|1993-02-28|1993-02-12|1993-03-01|COLLECT COD|AIR|ular accounts +4612|5989|8490|1|20|37899.60|0.02|0.03|R|F|1993-09-24|1993-12-18|1993-10-22|NONE|AIR|beans sleep blithely iro +4612|49750|2255|2|17|28895.75|0.10|0.06|A|F|1994-01-09|1993-11-08|1994-02-06|TAKE BACK RETURN|REG AIR|equests haggle carefully silent excus +4612|136371|1398|3|40|56294.80|0.08|0.01|R|F|1993-10-08|1993-11-23|1993-10-24|DELIVER IN PERSON|RAIL|special platelets. +4612|184664|7183|4|10|17486.60|0.10|0.06|A|F|1993-11-11|1993-11-19|1993-11-13|TAKE BACK RETURN|SHIP|unusual theodol +4613|37372|7373|1|17|22259.29|0.09|0.07|N|O|1998-06-07|1998-05-11|1998-06-29|DELIVER IN PERSON|SHIP|liers cajole a +4613|107883|394|2|25|47272.00|0.05|0.04|N|O|1998-05-22|1998-04-11|1998-05-27|TAKE BACK RETURN|SHIP|y pending platelets x-ray ironically! pend +4613|173667|8702|3|15|26109.90|0.10|0.02|N|O|1998-05-31|1998-04-16|1998-06-25|DELIVER IN PERSON|MAIL|against the quickly r +4613|7183|9684|4|36|39246.48|0.04|0.01|N|O|1998-04-22|1998-05-05|1998-05-04|DELIVER IN PERSON|AIR|gainst the furiously ironic +4613|110121|5144|5|35|39589.20|0.04|0.06|N|O|1998-06-04|1998-04-17|1998-06-20|COLLECT COD|MAIL|e blithely against the even, bold pi +4613|195878|8398|6|47|92771.89|0.04|0.04|N|O|1998-07-03|1998-05-26|1998-07-09|NONE|FOB|uriously special requests wak +4613|118713|1225|7|39|67536.69|0.09|0.05|N|O|1998-06-12|1998-06-01|1998-07-06|DELIVER IN PERSON|REG AIR|ously express +4614|6014|1015|1|19|17480.19|0.09|0.08|N|O|1996-05-17|1996-06-21|1996-06-08|TAKE BACK RETURN|AIR|ix. carefully regular +4614|64629|4630|2|3|4780.86|0.08|0.01|N|O|1996-07-22|1996-07-21|1996-08-07|NONE|MAIL|ions engage final, ironic +4614|7136|9637|3|36|37552.68|0.10|0.04|N|O|1996-07-05|1996-06-26|1996-07-07|NONE|REG AIR|onic foxes affix furi +4614|125036|2573|4|6|6366.18|0.09|0.01|N|O|1996-06-11|1996-05-30|1996-07-03|COLLECT COD|REG AIR|ake quickly quickly regular epitap +4614|72044|4552|5|24|24384.96|0.07|0.06|N|O|1996-07-01|1996-06-24|1996-07-08|COLLECT COD|REG AIR|regular, even +4614|33149|3150|6|32|34628.48|0.10|0.05|N|O|1996-08-21|1996-05-28|1996-09-16|NONE|REG AIR|ickly furio +4614|127060|4597|7|41|44569.46|0.01|0.07|N|O|1996-07-31|1996-07-12|1996-08-16|COLLECT COD|REG AIR|ackages haggle carefully about the even, b +4615|91296|3806|1|10|12872.90|0.02|0.08|A|F|1993-11-20|1993-10-05|1993-12-08|DELIVER IN PERSON|AIR|sits. slyly express deposits are +4640|87422|4947|1|5|7047.10|0.03|0.08|N|O|1996-02-05|1996-02-14|1996-02-15|TAKE BACK RETURN|RAIL| warthogs against the regular +4640|87287|4812|2|9|11468.52|0.03|0.05|N|O|1996-02-12|1996-02-14|1996-02-29|DELIVER IN PERSON|AIR| accounts. unu +4640|26265|3772|3|18|21442.68|0.02|0.07|N|O|1996-02-28|1996-03-06|1996-03-28|DELIVER IN PERSON|RAIL|boost furiously accord +4640|22346|7351|4|36|45660.24|0.06|0.08|N|O|1996-01-03|1996-03-09|1996-01-11|DELIVER IN PERSON|RAIL|iously furious accounts boost. carefully +4640|155974|1005|5|15|30449.55|0.03|0.02|N|O|1996-03-19|1996-02-09|1996-04-11|TAKE BACK RETURN|FOB|y regular instructions doze furiously. reg +4641|189796|7351|1|45|84860.55|0.07|0.03|R|F|1993-05-11|1993-04-19|1993-05-21|DELIVER IN PERSON|MAIL| about the close +4641|94261|6771|2|39|48955.14|0.06|0.00|R|F|1993-02-10|1993-03-06|1993-02-15|TAKE BACK RETURN|REG AIR| the bold reque +4641|35287|5288|3|15|18334.20|0.01|0.08|R|F|1993-01-25|1993-04-09|1993-02-05|TAKE BACK RETURN|AIR|s. carefully even exc +4642|193181|8220|1|11|14015.98|0.04|0.07|A|F|1995-05-23|1995-04-26|1995-06-04|COLLECT COD|TRUCK|lithely express asympt +4642|179594|2112|2|34|56902.06|0.04|0.07|R|F|1995-04-01|1995-05-11|1995-04-23|COLLECT COD|SHIP|theodolites detect among the ironically sp +4642|20152|153|3|10|10721.50|0.04|0.02|R|F|1995-04-16|1995-04-28|1995-04-24|COLLECT COD|RAIL|urts. even deposits nag beneath +4642|93698|8717|4|18|30450.42|0.00|0.04|N|F|1995-06-16|1995-04-16|1995-06-21|NONE|TRUCK|ily pending accounts hag +4642|178937|8938|5|41|82653.13|0.10|0.00|R|F|1995-04-08|1995-04-13|1995-05-01|DELIVER IN PERSON|MAIL|s are blithely. requests wake above the fur +4643|184931|2486|1|50|100796.50|0.08|0.05|N|O|1995-09-11|1995-08-13|1995-09-30|DELIVER IN PERSON|SHIP|. ironic deposits cajo +4644|176873|9391|1|4|7799.48|0.06|0.03|N|O|1998-05-06|1998-03-19|1998-05-28|NONE|MAIL|gular requests? pendi +4644|96503|6504|2|16|23992.00|0.03|0.04|N|O|1998-03-13|1998-02-21|1998-04-03|COLLECT COD|SHIP|lar excuses across the +4644|114307|6819|3|10|13213.00|0.02|0.02|N|O|1998-02-21|1998-02-28|1998-03-19|COLLECT COD|REG AIR|osits according to the +4644|153953|6469|4|45|90312.75|0.10|0.07|N|O|1998-02-02|1998-04-08|1998-02-15|COLLECT COD|SHIP| carefully a +4644|86667|4192|5|10|16536.60|0.08|0.08|N|O|1998-03-12|1998-03-11|1998-03-19|TAKE BACK RETURN|REG AIR| the slow, final fo +4645|49353|1858|1|45|58605.75|0.09|0.05|A|F|1994-12-27|1994-11-02|1994-12-31|DELIVER IN PERSON|AIR|ular ideas. slyly +4645|65060|5061|2|32|32801.92|0.10|0.08|A|F|1994-11-17|1994-10-30|1994-11-18|COLLECT COD|REG AIR| final accounts alongside +4645|53599|3600|3|25|38814.75|0.03|0.00|R|F|1994-10-25|1994-12-11|1994-11-14|NONE|REG AIR|braids. ironic dependencies main +4645|36614|1621|4|42|65125.62|0.10|0.02|R|F|1994-12-02|1994-12-18|1994-12-16|COLLECT COD|TRUCK|regular pinto beans amon +4645|160043|2560|5|35|38606.40|0.03|0.07|A|F|1994-12-08|1994-11-25|1994-12-09|TAKE BACK RETURN|FOB|sias believe bl +4645|41437|3942|6|27|37217.61|0.09|0.08|R|F|1994-11-26|1994-10-25|1994-12-04|NONE|SHIP|ously express pinto beans. ironic depos +4645|30142|143|7|42|45029.88|0.10|0.06|A|F|1994-12-31|1994-10-22|1995-01-28|DELIVER IN PERSON|AIR|e slyly regular pinto beans. thin +4646|190170|2690|1|24|30244.08|0.02|0.05|N|O|1996-09-18|1996-08-09|1996-09-21|TAKE BACK RETURN|RAIL|ic platelets lose carefully. blithely unu +4646|177583|5135|2|26|43175.08|0.07|0.00|N|O|1996-10-02|1996-08-25|1996-10-27|DELIVER IN PERSON|MAIL|ix according to the slyly spe +4646|33120|630|3|18|18956.16|0.01|0.00|N|O|1996-06-30|1996-08-10|1996-07-12|TAKE BACK RETURN|TRUCK|beans sleep car +4646|39105|9106|4|38|39675.80|0.08|0.01|N|O|1996-09-01|1996-08-23|1996-09-27|COLLECT COD|SHIP|al platelets cajole. slyly final dol +4646|25896|8399|5|22|40081.58|0.01|0.08|N|O|1996-07-14|1996-08-06|1996-07-29|DELIVER IN PERSON|MAIL|cies are blithely after the slyly reg +4647|92862|7881|1|16|29677.76|0.09|0.07|R|F|1994-09-07|1994-07-15|1994-10-06|COLLECT COD|RAIL|o beans about the fluffily special the +4647|128884|6421|2|34|65037.92|0.01|0.02|R|F|1994-05-20|1994-06-20|1994-05-29|COLLECT COD|TRUCK|ly sly accounts +4647|146614|6615|3|27|44836.47|0.03|0.08|R|F|1994-05-20|1994-06-26|1994-05-30|NONE|FOB|ully even ti +4647|138275|8276|4|2|2626.54|0.04|0.07|R|F|1994-07-03|1994-07-22|1994-07-22|TAKE BACK RETURN|RAIL|dolites wake furiously special pinto be +4647|186829|6830|5|2|3831.64|0.07|0.06|A|F|1994-05-27|1994-08-05|1994-06-10|TAKE BACK RETURN|FOB| pinto beans believe furiously slyly silent +4647|28488|991|6|28|39661.44|0.02|0.03|A|F|1994-08-25|1994-08-06|1994-09-18|DELIVER IN PERSON|FOB| are above the fluffily fin +4672|58147|653|1|22|24313.08|0.01|0.07|N|O|1995-12-03|1995-12-08|1995-12-17|COLLECT COD|AIR|l instructions. blithely ironic packages +4672|60961|3468|2|41|78800.36|0.00|0.00|N|O|1995-12-01|1995-12-15|1995-12-12|COLLECT COD|RAIL| slyly quie +4672|162043|7076|3|24|26520.96|0.04|0.03|N|O|1995-11-11|1995-12-28|1995-12-04|NONE|REG AIR|y fluffily stealt +4672|56171|1182|4|13|14653.21|0.10|0.03|N|O|1996-02-02|1995-12-13|1996-03-02|DELIVER IN PERSON|RAIL|ar requests? pending accounts against +4672|54022|9033|5|45|43920.90|0.08|0.07|N|O|1996-02-07|1996-01-16|1996-02-14|DELIVER IN PERSON|MAIL| platelets use amon +4672|140922|3437|6|20|39258.40|0.02|0.07|N|O|1995-12-08|1996-01-25|1995-12-19|COLLECT COD|REG AIR|s boost at the ca +4672|71853|9375|7|38|69344.30|0.01|0.01|N|O|1995-11-28|1995-12-08|1995-12-13|COLLECT COD|SHIP|ests. idle, regular ex +4673|16607|6608|1|8|12188.80|0.08|0.01|N|O|1996-10-12|1996-10-05|1996-11-04|TAKE BACK RETURN|FOB|lithely final re +4673|100894|895|2|44|83375.16|0.06|0.01|N|O|1996-12-11|1996-10-31|1997-01-08|DELIVER IN PERSON|RAIL| gifts cajole dari +4673|122258|7283|3|9|11522.25|0.04|0.07|N|O|1996-10-15|1996-09-30|1996-10-30|DELIVER IN PERSON|MAIL|ages nag across +4674|149045|1560|1|50|54702.00|0.07|0.08|A|F|1994-05-13|1994-06-15|1994-06-05|COLLECT COD|RAIL|haggle about the blithel +4674|188714|1233|2|35|63094.85|0.02|0.05|A|F|1994-08-02|1994-06-04|1994-08-21|COLLECT COD|FOB|le quickly after the express sent +4674|110443|2955|3|3|4360.32|0.01|0.05|A|F|1994-07-19|1994-05-28|1994-07-23|TAKE BACK RETURN|RAIL| regular requests na +4674|12164|4666|4|21|22599.36|0.02|0.08|R|F|1994-05-08|1994-07-02|1994-06-04|COLLECT COD|RAIL|ent accounts sublate deposits. instruc +4675|170390|391|1|6|8762.34|0.00|0.05|R|F|1994-01-22|1994-01-06|1994-02-12|TAKE BACK RETURN|TRUCK| unusual ideas thrash bl +4675|143689|8718|2|12|20792.16|0.00|0.04|A|F|1993-12-22|1994-01-12|1993-12-23|TAKE BACK RETURN|AIR|posits affix carefully +4675|180963|964|3|5|10219.80|0.05|0.05|A|F|1994-01-16|1994-01-05|1994-01-18|DELIVER IN PERSON|RAIL|lent pinto beans +4675|33646|1156|4|26|41070.64|0.03|0.01|A|F|1993-12-16|1993-12-29|1993-12-23|DELIVER IN PERSON|SHIP|nts. express requests are quickly +4675|80498|499|5|18|26612.82|0.01|0.08|R|F|1994-02-23|1994-01-18|1994-03-05|TAKE BACK RETURN|FOB|cajole unusual dep +4675|118089|8090|6|1|1107.08|0.10|0.06|R|F|1994-03-18|1994-02-14|1994-04-17|NONE|SHIP|unts. caref +4676|164646|9679|1|47|80400.08|0.03|0.06|N|O|1995-12-20|1995-10-04|1996-01-09|NONE|AIR|lithely about the carefully special requ +4676|5043|44|2|33|31285.32|0.08|0.05|N|O|1995-12-29|1995-10-01|1996-01-18|TAKE BACK RETURN|FOB|yly express +4676|145173|7688|3|4|4872.68|0.10|0.06|N|O|1995-12-12|1995-10-22|1995-12-13|TAKE BACK RETURN|TRUCK|detect above the ironic platelets. fluffily +4676|110831|832|4|50|92091.50|0.07|0.01|N|O|1995-09-20|1995-11-20|1995-10-18|TAKE BACK RETURN|AIR|r deposits boost boldly quickly quick asymp +4676|121096|3609|5|29|32395.61|0.01|0.02|N|O|1995-12-29|1995-11-12|1996-01-06|TAKE BACK RETURN|RAIL|ly regular theodolites sleep. +4676|45569|5570|6|8|12116.48|0.08|0.08|N|O|1995-12-05|1995-10-18|1996-01-02|COLLECT COD|AIR|cuses boost above +4676|63244|8257|7|13|15694.12|0.05|0.07|N|O|1995-11-18|1995-11-07|1995-12-10|TAKE BACK RETURN|TRUCK| at the slyly bold attainments. silently e +4677|127864|377|1|25|47296.50|0.04|0.04|N|O|1998-04-11|1998-05-11|1998-04-18|TAKE BACK RETURN|REG AIR|unts doubt furiousl +4678|57388|9894|1|35|47088.30|0.04|0.08|N|O|1998-11-27|1998-10-02|1998-12-17|TAKE BACK RETURN|AIR|he accounts. fluffily bold sheaves b +4678|116672|9184|2|18|30396.06|0.03|0.06|N|O|1998-10-30|1998-09-22|1998-11-25|TAKE BACK RETURN|SHIP|usly ironic +4678|95355|374|3|13|17554.55|0.10|0.07|N|O|1998-11-03|1998-10-17|1998-11-06|TAKE BACK RETURN|SHIP|its. carefully final fr +4678|21704|6709|4|23|37391.10|0.06|0.05|N|O|1998-09-03|1998-09-20|1998-09-04|DELIVER IN PERSON|SHIP|ily sly deposi +4678|177771|7772|5|40|73950.80|0.03|0.07|N|O|1998-11-11|1998-10-27|1998-11-24|TAKE BACK RETURN|AIR|. final, unusual requests sleep thinl +4679|189136|4173|1|7|8575.91|0.10|0.05|R|F|1993-05-11|1993-04-11|1993-05-16|NONE|TRUCK|kages. bold, regular packa +4704|77934|5456|1|14|26767.02|0.04|0.04|N|O|1996-10-27|1996-11-02|1996-11-07|DELIVER IN PERSON|TRUCK| above the slyly final requests. quickly +4704|27671|174|2|7|11190.69|0.03|0.04|N|O|1996-12-04|1996-10-30|1996-12-23|DELIVER IN PERSON|SHIP|ers wake car +4704|63081|3082|3|44|45939.52|0.02|0.05|N|O|1996-09-02|1996-10-07|1996-09-17|DELIVER IN PERSON|REG AIR|out the care +4705|110778|5801|1|22|39352.94|0.04|0.04|R|F|1992-07-05|1992-05-11|1992-07-29|DELIVER IN PERSON|SHIP| fluffily pending accounts ca +4705|30527|3031|2|14|20405.28|0.00|0.08|R|F|1992-07-14|1992-05-23|1992-07-25|DELIVER IN PERSON|TRUCK|ain carefully amon +4705|55426|437|3|16|22102.72|0.07|0.08|R|F|1992-07-02|1992-06-06|1992-07-06|DELIVER IN PERSON|RAIL|special ideas nag sl +4705|129147|6684|4|31|36460.34|0.03|0.03|R|F|1992-04-03|1992-05-30|1992-04-05|COLLECT COD|TRUCK|furiously final accou +4705|162432|7465|5|28|41844.04|0.10|0.01|A|F|1992-06-03|1992-06-07|1992-06-22|DELIVER IN PERSON|MAIL|tes wake according to the unusual plate +4705|183715|6234|6|23|41370.33|0.06|0.03|R|F|1992-06-22|1992-06-11|1992-07-18|DELIVER IN PERSON|MAIL| above the furiously ev +4705|88534|3551|7|40|60901.20|0.08|0.06|A|F|1992-04-19|1992-04-28|1992-05-07|COLLECT COD|TRUCK|blithely. sly +4706|181872|4391|1|37|72293.19|0.02|0.06|A|F|1993-02-20|1993-03-05|1993-03-03|DELIVER IN PERSON|TRUCK|kly final deposits c +4706|121133|1134|2|23|26544.99|0.03|0.01|A|F|1993-04-01|1993-03-13|1993-05-01|COLLECT COD|FOB|deas across t +4706|67134|2147|3|6|6606.78|0.01|0.04|R|F|1993-01-20|1993-03-18|1993-01-26|NONE|MAIL|efully eve +4706|115455|7967|4|5|7352.25|0.06|0.06|R|F|1993-02-14|1993-01-31|1993-02-26|NONE|REG AIR|ptotes haggle ca +4706|49189|1694|5|27|30730.86|0.06|0.08|A|F|1993-04-04|1993-03-11|1993-04-09|COLLECT COD|REG AIR|into beans. finally special instruct +4707|33590|8597|1|7|10665.13|0.02|0.05|R|F|1995-05-14|1995-04-06|1995-06-06|COLLECT COD|SHIP|ecial sheaves boost blithely accor +4707|135550|577|2|49|77691.95|0.00|0.07|N|F|1995-06-17|1995-05-16|1995-06-25|COLLECT COD|FOB| alongside of the slyly ironic instructio +4708|190913|5952|1|18|36070.38|0.02|0.04|A|F|1994-11-11|1994-11-15|1994-11-26|NONE|REG AIR|special, eve +4708|74046|1568|2|5|5100.20|0.05|0.05|A|F|1994-10-15|1994-12-02|1994-11-12|COLLECT COD|MAIL|ely. carefully sp +4708|76824|9332|3|32|57626.24|0.04|0.07|A|F|1994-11-12|1994-11-14|1994-11-23|TAKE BACK RETURN|MAIL|the accounts. e +4709|24334|4335|1|25|31458.25|0.03|0.05|N|O|1996-02-21|1996-02-11|1996-03-17|DELIVER IN PERSON|AIR|deposits grow. fluffily unusual accounts +4709|176003|3555|2|25|26975.00|0.05|0.03|N|O|1996-01-22|1996-03-03|1996-02-21|DELIVER IN PERSON|REG AIR|inst the ironic, regul +4710|182634|189|1|40|68665.20|0.10|0.08|A|F|1995-03-09|1995-02-25|1995-03-29|TAKE BACK RETURN|AIR|cross the blithely bold packages. silen +4710|127253|9766|2|47|60171.75|0.04|0.01|R|F|1995-02-22|1995-01-12|1995-02-28|NONE|RAIL|blithely express packages. even, ironic re +4711|132347|2348|1|7|9655.38|0.03|0.01|N|O|1998-05-12|1998-06-24|1998-05-24|COLLECT COD|MAIL|ly. bold accounts use fluff +4711|144056|4057|2|15|16500.75|0.08|0.07|N|O|1998-06-09|1998-07-30|1998-06-18|COLLECT COD|SHIP| beans wake. deposits could bo +4711|149014|9015|3|22|23386.22|0.02|0.03|N|O|1998-06-21|1998-06-18|1998-07-19|TAKE BACK RETURN|REG AIR|along the quickly careful packages. bli +4711|64012|1531|4|8|7808.08|0.07|0.00|N|O|1998-06-17|1998-06-13|1998-06-27|TAKE BACK RETURN|SHIP|g to the carefully ironic deposits. specia +4711|48820|3829|5|15|26532.30|0.05|0.01|N|O|1998-09-03|1998-07-15|1998-09-13|TAKE BACK RETURN|SHIP|ld requests: furiously final inst +4711|115669|5670|6|45|75809.70|0.05|0.06|N|O|1998-05-19|1998-07-14|1998-05-21|COLLECT COD|SHIP| ironic theodolites +4711|45160|2673|7|18|19892.88|0.05|0.04|N|O|1998-07-03|1998-07-31|1998-07-23|DELIVER IN PERSON|RAIL| blithely. bold asymptote +4736|195526|3084|1|26|42159.52|0.03|0.03|N|O|1996-02-02|1996-01-18|1996-02-09|DELIVER IN PERSON|AIR|efully speci +4736|3390|891|2|43|55615.77|0.06|0.07|N|O|1996-02-05|1995-12-21|1996-02-06|COLLECT COD|MAIL|quests. carefully +4737|190140|7698|1|37|45515.18|0.03|0.04|R|F|1993-05-17|1993-04-10|1993-05-30|DELIVER IN PERSON|TRUCK|s. fluffily regular +4737|68303|810|2|22|27968.60|0.04|0.04|A|F|1993-03-29|1993-05-22|1993-04-16|TAKE BACK RETURN|RAIL| hang fluffily around t +4738|186778|4333|1|9|16782.93|0.04|0.04|A|F|1992-06-01|1992-06-26|1992-06-02|COLLECT COD|TRUCK|posits serve slyly. unusual pint +4738|172482|5000|2|16|24871.68|0.07|0.08|A|F|1992-06-17|1992-06-20|1992-06-21|NONE|MAIL|nic deposits are slyly! carefu +4738|99175|1685|3|50|58708.50|0.04|0.02|A|F|1992-06-18|1992-07-04|1992-07-07|TAKE BACK RETURN|TRUCK|the blithely ironic braids sleep slyly +4738|28274|777|4|22|26449.94|0.02|0.08|A|F|1992-05-25|1992-05-19|1992-06-12|COLLECT COD|SHIP|ld, even packages. furio +4738|186242|6243|5|13|17267.12|0.04|0.05|R|F|1992-05-30|1992-06-11|1992-06-26|COLLECT COD|AIR| wake. unusual platelets for the +4738|158558|6104|6|10|16165.50|0.10|0.01|R|F|1992-07-10|1992-06-16|1992-07-25|TAKE BACK RETURN|SHIP|hins above the +4738|82750|275|7|28|48517.00|0.05|0.07|A|F|1992-06-09|1992-07-05|1992-06-25|NONE|AIR|e furiously ironic excuses. care +4739|167941|7942|1|8|16071.52|0.07|0.07|R|F|1993-06-22|1993-05-10|1993-07-11|TAKE BACK RETURN|SHIP|cording to the +4739|184061|6580|2|31|35496.86|0.09|0.06|R|F|1993-06-20|1993-05-18|1993-06-26|COLLECT COD|SHIP|blithely special pin +4739|99183|6711|3|30|35465.40|0.09|0.00|A|F|1993-05-29|1993-04-12|1993-06-18|NONE|TRUCK|ly even packages use across th +4740|2282|2283|1|22|26054.16|0.06|0.01|N|O|1996-10-04|1996-08-17|1996-10-05|TAKE BACK RETURN|RAIL|final dependencies nag +4740|152247|9793|2|24|31181.76|0.08|0.02|N|O|1996-09-10|1996-09-27|1996-10-07|TAKE BACK RETURN|TRUCK|hely regular deposits +4741|72763|7778|1|24|41658.24|0.00|0.01|A|F|1992-09-16|1992-09-19|1992-09-20|DELIVER IN PERSON|RAIL|deas boost furiously slyly regular id +4741|112165|2166|2|16|18834.56|0.01|0.07|R|F|1992-08-25|1992-08-10|1992-08-29|TAKE BACK RETURN|FOB|final foxes haggle r +4741|155605|3151|3|24|39854.40|0.05|0.08|A|F|1992-11-04|1992-08-14|1992-11-06|TAKE BACK RETURN|MAIL|even requests. +4741|50954|8470|4|39|74293.05|0.09|0.06|R|F|1992-10-28|1992-10-03|1992-11-11|COLLECT COD|SHIP|t, regular requests +4741|178507|8508|5|40|63420.00|0.09|0.03|R|F|1992-09-20|1992-09-23|1992-10-09|TAKE BACK RETURN|REG AIR| fluffily slow deposits. fluffily regu +4741|156686|9202|6|34|59251.12|0.02|0.07|R|F|1992-08-25|1992-08-18|1992-09-20|DELIVER IN PERSON|RAIL|sly special packages after the furiously +4742|155564|8080|1|32|51825.92|0.10|0.08|R|F|1995-04-04|1995-06-12|1995-04-19|COLLECT COD|RAIL|eposits boost blithely. carefully regular a +4742|154833|2379|2|29|54747.07|0.02|0.03|N|F|1995-06-15|1995-05-05|1995-06-24|COLLECT COD|REG AIR|integrate closely among t +4742|71018|8540|3|15|14835.15|0.06|0.04|N|O|1995-07-20|1995-05-26|1995-08-11|NONE|SHIP|terns are sl +4742|187940|5495|4|31|62866.14|0.05|0.08|N|F|1995-06-13|1995-05-08|1995-06-24|COLLECT COD|REG AIR|ke slyly among the furiousl +4742|99331|9332|5|45|59864.85|0.05|0.00|R|F|1995-05-12|1995-05-14|1995-06-07|TAKE BACK RETURN|RAIL|ke carefully. do +4743|59402|4413|1|19|25866.60|0.04|0.07|A|F|1993-06-23|1993-05-03|1993-07-20|COLLECT COD|AIR|hely even accounts +4743|158379|3410|2|3|4312.11|0.01|0.03|R|F|1993-04-14|1993-06-08|1993-05-09|NONE|TRUCK|al requests. express idea +4743|72936|7951|3|21|40087.53|0.08|0.03|A|F|1993-07-02|1993-06-15|1993-07-26|DELIVER IN PERSON|RAIL|ake blithely against the packages. reg +4743|33527|3528|4|27|39434.04|0.08|0.05|R|F|1993-07-26|1993-05-27|1993-08-24|DELIVER IN PERSON|AIR|aids use. express deposits +4768|35822|829|1|5|8789.10|0.00|0.03|R|F|1993-12-27|1994-02-09|1994-01-11|NONE|MAIL|egular accounts. bravely final fra +4769|34240|1750|1|16|18787.84|0.08|0.05|N|O|1995-07-16|1995-07-05|1995-07-22|TAKE BACK RETURN|FOB| deposits. slyly even asymptote +4769|62918|437|2|34|63950.94|0.06|0.07|N|O|1995-07-26|1995-05-18|1995-08-03|COLLECT COD|REG AIR|ven instructions. ca +4769|46414|1423|3|36|48974.76|0.10|0.03|N|O|1995-07-22|1995-06-16|1995-08-11|NONE|RAIL|. slyly even deposit +4769|68431|8432|4|45|62974.35|0.08|0.06|R|F|1995-06-01|1995-07-13|1995-06-04|TAKE BACK RETURN|RAIL|accounts are. even accounts sleep +4769|111623|4135|5|15|24519.30|0.07|0.08|N|F|1995-06-12|1995-07-07|1995-07-04|NONE|SHIP|egular platelets can cajole across the +4770|31961|9471|1|41|77611.36|0.00|0.08|N|O|1995-09-04|1995-08-08|1995-09-10|COLLECT COD|FOB|ithely even packages sleep caref +4770|156036|8552|2|30|32760.90|0.09|0.07|N|O|1995-08-25|1995-08-27|1995-09-07|COLLECT COD|SHIP|ffily carefully ironic ideas. ironic d +4771|48612|8613|1|9|14045.49|0.01|0.00|R|F|1993-02-28|1993-02-19|1993-03-25|NONE|FOB|riously after the packages. fina +4771|15316|5317|2|21|25857.51|0.09|0.01|R|F|1993-01-19|1993-02-10|1993-02-01|NONE|FOB|fluffily pendi +4771|11568|1569|3|5|7397.80|0.06|0.08|R|F|1993-01-07|1993-01-19|1993-01-26|NONE|RAIL|ar, quiet accounts nag furiously express id +4771|8448|3449|4|21|28485.24|0.05|0.04|A|F|1992-12-20|1993-01-22|1992-12-26|TAKE BACK RETURN|SHIP| carefully re +4772|86830|6831|1|1|1816.83|0.10|0.00|R|F|1994-11-13|1994-10-25|1994-11-15|DELIVER IN PERSON|AIR|ans. slyly even acc +4772|145505|534|2|16|24808.00|0.07|0.06|R|F|1994-10-27|1994-12-07|1994-10-29|TAKE BACK RETURN|MAIL|egular accounts wake s +4772|94751|4752|3|31|54118.25|0.02|0.04|A|F|1994-10-02|1994-10-21|1994-10-13|TAKE BACK RETURN|FOB|ests are thinly. furiously unusua +4772|70799|5814|4|15|26546.85|0.02|0.07|R|F|1994-09-19|1994-10-22|1994-09-26|COLLECT COD|TRUCK| requests. express, regular th +4773|143131|3132|1|23|27004.99|0.00|0.08|N|O|1996-01-01|1996-03-19|1996-01-04|NONE|FOB|ly express grouches wak +4773|196476|8996|2|36|56608.92|0.09|0.04|N|O|1996-04-08|1996-03-03|1996-05-01|COLLECT COD|REG AIR| dependencies. quickly +4773|166028|6029|3|49|53606.98|0.05|0.02|N|O|1996-01-26|1996-02-29|1996-01-27|TAKE BACK RETURN|FOB|y final reque +4773|19370|6874|4|49|63179.13|0.09|0.04|N|O|1996-01-12|1996-02-17|1996-02-05|TAKE BACK RETURN|TRUCK|ly pending theodolites cajole caref +4773|149461|4490|5|20|30209.20|0.02|0.07|N|O|1995-12-28|1996-02-17|1996-01-15|COLLECT COD|TRUCK| blithely final deposits nag after t +4773|189276|1795|6|11|15017.97|0.10|0.06|N|O|1996-01-02|1996-01-29|1996-01-24|DELIVER IN PERSON|REG AIR|en accounts. slyly b +4773|157333|2364|7|6|8341.98|0.07|0.01|N|O|1996-03-09|1996-03-18|1996-03-27|NONE|AIR|latelets haggle s +4774|83182|5691|1|45|52433.10|0.10|0.00|R|F|1993-07-07|1993-06-08|1993-07-31|COLLECT COD|TRUCK| haggle busily afte +4774|38828|1332|2|4|7067.28|0.02|0.03|A|F|1993-08-03|1993-05-30|1993-08-19|COLLECT COD|FOB|xes according to the foxes wake above the f +4774|172460|2461|3|47|72025.62|0.10|0.08|R|F|1993-06-13|1993-07-04|1993-07-09|TAKE BACK RETURN|FOB|regular dolphins above the furi +4774|129151|6688|4|30|35404.50|0.05|0.08|A|F|1993-08-18|1993-06-08|1993-08-21|DELIVER IN PERSON|REG AIR|tions against the blithely final theodolit +4775|73979|6487|1|1|1952.97|0.10|0.02|N|O|1995-09-06|1995-09-28|1995-09-29|DELIVER IN PERSON|MAIL|furiously ironic theodolite +4775|152779|5295|2|37|67775.49|0.02|0.01|N|O|1995-09-06|1995-09-28|1995-09-28|COLLECT COD|TRUCK|ts. pinto beans use according to th +4775|152242|9788|3|34|44004.16|0.09|0.06|N|O|1995-09-14|1995-10-15|1995-09-21|DELIVER IN PERSON|MAIL|onic epitaphs. f +4775|118461|5995|4|39|57698.94|0.07|0.04|N|O|1995-08-30|1995-10-12|1995-09-20|NONE|AIR|eep never with the slyly regular acc +4800|96498|1517|1|11|16439.39|0.03|0.03|R|F|1992-01-27|1992-03-16|1992-02-19|TAKE BACK RETURN|RAIL|ic dependenc +4800|25491|496|2|1|1416.49|0.06|0.06|A|F|1992-02-23|1992-03-16|1992-03-20|TAKE BACK RETURN|MAIL|nal accounts are blithely deposits. bol +4800|10518|5521|3|21|29998.71|0.09|0.05|A|F|1992-02-14|1992-03-15|1992-02-26|NONE|SHIP|ithely according to +4800|175228|5229|4|38|49522.36|0.10|0.08|R|F|1992-02-01|1992-02-28|1992-02-21|NONE|TRUCK|s sleep fluffily. furiou +4800|52240|2241|5|24|28613.76|0.08|0.04|R|F|1992-01-14|1992-02-23|1992-01-25|NONE|TRUCK|ully carefully r +4801|183937|1492|1|37|74774.41|0.10|0.02|N|O|1996-03-09|1996-02-29|1996-03-25|TAKE BACK RETURN|FOB|uests hinder blithely against the instr +4801|25246|7749|2|34|39822.16|0.03|0.02|N|O|1996-02-05|1996-04-16|1996-02-23|NONE|SHIP|y final requests +4801|109282|9283|3|4|5165.12|0.04|0.04|N|O|1996-03-23|1996-04-04|1996-03-25|COLLECT COD|RAIL|pitaphs. regular, reg +4801|91183|1184|4|39|45793.02|0.07|0.01|N|O|1996-03-19|1996-03-21|1996-04-17|TAKE BACK RETURN|REG AIR|warhorses wake never for the care +4802|39444|9445|1|6|8300.64|0.00|0.06|N|O|1997-04-16|1997-03-25|1997-04-21|TAKE BACK RETURN|SHIP|unusual accounts wake blithely. b +4803|131052|6079|1|2|2166.10|0.08|0.03|N|O|1996-04-16|1996-03-20|1996-05-15|NONE|REG AIR|gular reque +4803|175165|2717|2|47|58287.52|0.10|0.00|N|O|1996-03-14|1996-03-30|1996-03-15|DELIVER IN PERSON|FOB|ly final excuses. slyly express requ +4803|195742|8262|3|42|77185.08|0.04|0.08|N|O|1996-04-27|1996-05-05|1996-05-17|NONE|TRUCK| accounts affix quickly ar +4803|21312|6317|4|24|29599.44|0.10|0.04|N|O|1996-02-24|1996-04-02|1996-02-28|NONE|MAIL|t blithely slyly special decoys. +4803|188148|5703|5|21|25958.94|0.03|0.06|N|O|1996-05-25|1996-03-15|1996-06-09|COLLECT COD|FOB| silent packages use. b +4803|193599|3600|6|19|32159.21|0.07|0.00|N|O|1996-04-20|1996-03-25|1996-04-27|TAKE BACK RETURN|RAIL|sts. enticing, even +4804|127009|4546|1|44|45584.00|0.06|0.08|A|F|1992-05-02|1992-03-24|1992-05-28|TAKE BACK RETURN|AIR|aggle quickly among the slyly fi +4804|34942|9949|2|41|76954.54|0.10|0.02|R|F|1992-04-06|1992-04-12|1992-05-03|COLLECT COD|MAIL|. deposits haggle express tithes? +4804|64829|9842|3|33|59196.06|0.09|0.05|A|F|1992-03-02|1992-04-14|1992-03-13|DELIVER IN PERSON|AIR|, thin excuses. +4805|149235|9236|1|7|8989.61|0.09|0.03|A|F|1992-05-01|1992-07-09|1992-05-09|NONE|FOB| requests. regular deposit +4805|188967|1486|2|45|92518.20|0.02|0.03|R|F|1992-06-16|1992-06-08|1992-07-03|NONE|TRUCK|the furiously sly t +4805|153857|1403|3|44|84077.40|0.01|0.02|R|F|1992-05-14|1992-06-23|1992-05-25|DELIVER IN PERSON|SHIP|eposits sleep furiously qui +4805|64284|9297|4|13|16227.64|0.04|0.04|R|F|1992-07-16|1992-06-07|1992-08-10|COLLECT COD|AIR|its serve about the accounts. slyly regu +4805|8529|8530|5|42|60375.84|0.03|0.03|R|F|1992-08-17|1992-07-03|1992-09-14|NONE|REG AIR|the regular, fina +4805|135959|986|6|18|35909.10|0.06|0.04|A|F|1992-06-07|1992-07-10|1992-06-12|COLLECT COD|TRUCK|o use pending, unusu +4806|15046|5047|1|26|24987.04|0.10|0.05|R|F|1993-05-28|1993-06-07|1993-05-29|DELIVER IN PERSON|SHIP| bold pearls sublate blithely. quickly pe +4806|71151|8673|2|6|6732.90|0.01|0.06|A|F|1993-05-17|1993-07-19|1993-05-29|TAKE BACK RETURN|SHIP|even theodolites. packages sl +4806|28806|1309|3|8|13878.40|0.09|0.00|A|F|1993-05-08|1993-07-16|1993-05-28|NONE|TRUCK|requests boost blithely. qui +4807|121903|6928|1|9|17324.10|0.04|0.08|N|O|1997-04-23|1997-03-01|1997-05-15|TAKE BACK RETURN|TRUCK|may are blithely. carefully even pinto b +4807|9767|9768|2|41|68747.16|0.07|0.08|N|O|1997-05-02|1997-03-31|1997-05-15|TAKE BACK RETURN|AIR| fluffily re +4807|144309|4310|3|34|46012.20|0.06|0.02|N|O|1997-01-31|1997-03-13|1997-02-01|NONE|SHIP|ecial ideas. deposits according to the fin +4807|189336|4373|4|32|45610.56|0.05|0.00|N|O|1997-04-04|1997-03-21|1997-04-16|NONE|RAIL|efully even dolphins slee +4807|158706|6252|5|2|3529.40|0.02|0.05|N|O|1997-05-09|1997-04-03|1997-06-05|TAKE BACK RETURN|RAIL|deas wake bli +4807|159022|9023|6|22|23782.44|0.09|0.06|N|O|1997-03-13|1997-02-23|1997-04-01|NONE|FOB|es use final excuses. furiously final +4832|14730|4731|1|23|37828.79|0.03|0.01|N|O|1997-12-05|1998-01-05|1997-12-10|NONE|RAIL|y express depo +4832|151303|8849|2|10|13543.00|0.00|0.06|N|O|1998-01-08|1998-02-01|1998-01-11|DELIVER IN PERSON|MAIL|ly. blithely bold pinto beans should have +4832|148228|743|3|4|5104.88|0.04|0.01|N|O|1998-01-16|1998-02-12|1998-02-08|TAKE BACK RETURN|AIR|ages. slyly express deposits cajole car +4832|63875|3876|4|6|11033.22|0.02|0.01|N|O|1997-12-08|1998-02-03|1997-12-10|COLLECT COD|TRUCK|ages cajole after the bold requests. furi +4832|137354|4894|5|43|59828.05|0.10|0.08|N|O|1997-12-31|1998-02-20|1998-01-26|COLLECT COD|RAIL|oze according to the accou +4833|106154|8665|1|31|35964.65|0.08|0.04|N|O|1996-06-24|1996-07-15|1996-07-02|NONE|SHIP|ven instructions cajole against the caref +4833|116084|3618|2|11|12100.88|0.03|0.01|N|O|1996-08-24|1996-07-26|1996-09-19|NONE|REG AIR|s nag above the busily sile +4833|17043|7044|3|26|24961.04|0.08|0.04|N|O|1996-05-13|1996-07-12|1996-05-31|NONE|SHIP|s packages. even gif +4833|35345|352|4|19|24326.46|0.07|0.07|N|O|1996-08-21|1996-07-09|1996-09-10|TAKE BACK RETURN|AIR|y quick theodolit +4833|34266|1776|5|4|4801.04|0.10|0.02|N|O|1996-08-16|1996-06-29|1996-08-22|NONE|AIR|y pending packages sleep blithely regular r +4834|182667|222|1|27|47240.82|0.06|0.02|N|O|1997-01-09|1996-10-27|1997-01-27|DELIVER IN PERSON|RAIL|es nag blithe +4834|70960|3468|2|26|50204.96|0.01|0.00|N|O|1996-10-04|1996-10-21|1996-10-10|DELIVER IN PERSON|TRUCK|ages dazzle carefully. slyly daring foxes +4834|22952|7957|3|34|63748.30|0.03|0.01|N|O|1996-12-09|1996-11-26|1996-12-10|NONE|MAIL|ounts haggle bo +4834|142668|5183|4|38|65005.08|0.03|0.06|N|O|1997-01-10|1996-12-06|1997-01-22|COLLECT COD|FOB|alongside of the carefully even plate +4835|178289|8290|1|18|24611.04|0.00|0.03|R|F|1995-02-17|1994-12-14|1995-03-17|DELIVER IN PERSON|MAIL|eat furiously against the slyly +4835|90575|3085|2|3|4696.71|0.09|0.06|R|F|1995-01-24|1995-01-12|1995-02-16|COLLECT COD|AIR|etimes final pac +4835|85483|5484|3|27|39648.96|0.05|0.00|A|F|1994-12-10|1994-12-13|1995-01-02|DELIVER IN PERSON|REG AIR| accounts after the car +4835|101125|6146|4|23|25900.76|0.08|0.07|A|F|1995-02-05|1995-01-04|1995-02-28|NONE|SHIP|e carefully regular foxes. deposits are sly +4836|161531|4048|1|22|35035.66|0.01|0.03|N|O|1997-03-03|1997-02-23|1997-03-04|NONE|SHIP|al pinto beans. care +4836|47331|9836|2|16|20453.28|0.07|0.08|N|O|1997-01-14|1997-03-05|1997-01-30|COLLECT COD|MAIL|gular packages against the express reque +4836|75666|3188|3|14|22983.24|0.03|0.08|N|O|1997-02-21|1997-02-06|1997-03-08|COLLECT COD|MAIL|lites. unusual, bold dolphins ar +4836|105341|362|4|15|20195.10|0.10|0.00|N|O|1997-03-08|1997-03-14|1997-03-30|TAKE BACK RETURN|TRUCK|eep slyly. even requests cajole +4836|50120|5131|5|12|12841.44|0.01|0.04|N|O|1997-02-02|1997-02-10|1997-02-03|COLLECT COD|TRUCK|sly ironic accoun +4837|41768|9281|1|16|27356.16|0.09|0.04|N|O|1998-08-12|1998-06-06|1998-08-26|COLLECT COD|FOB|ing requests are blithely regular instructi +4837|192758|5278|2|16|29612.00|0.01|0.02|N|O|1998-08-19|1998-06-18|1998-08-26|NONE|RAIL|counts cajole slyly furiou +4837|67706|2719|3|42|70295.40|0.10|0.00|N|O|1998-06-19|1998-07-06|1998-06-23|COLLECT COD|MAIL|o the furiously final theodolites boost +4838|121792|1793|1|35|63482.65|0.01|0.00|R|F|1992-10-30|1992-10-23|1992-11-21|TAKE BACK RETURN|RAIL|ly blithely unusual foxes. even package +4838|147002|9517|2|2|2098.00|0.03|0.08|R|F|1992-08-11|1992-09-16|1992-08-26|COLLECT COD|MAIL|hely final notornis are furiously blithe +4838|51200|1201|3|26|29931.20|0.06|0.04|R|F|1992-09-03|1992-10-25|1992-09-11|TAKE BACK RETURN|FOB|ular requests boost about the packages. r +4839|59762|7278|1|5|8608.80|0.10|0.07|A|F|1994-09-07|1994-07-15|1994-10-05|DELIVER IN PERSON|FOB|ses integrate. regular deposits are about +4839|9631|9632|2|25|38515.75|0.02|0.02|R|F|1994-05-20|1994-07-08|1994-05-30|NONE|REG AIR|regular packages ab +4839|59660|9661|3|18|29153.88|0.06|0.01|R|F|1994-05-18|1994-06-13|1994-06-09|TAKE BACK RETURN|FOB|blithely ironic theodolites use along +4839|99142|9143|4|19|21681.66|0.07|0.08|R|F|1994-05-20|1994-07-14|1994-05-30|NONE|REG AIR| deposits sublate furiously ir +4839|70988|6003|5|9|17630.82|0.05|0.01|R|F|1994-06-17|1994-06-18|1994-07-10|NONE|SHIP|ounts haggle carefully above +4864|149726|7269|1|28|49720.16|0.06|0.08|A|F|1993-02-06|1992-12-15|1993-02-10|COLLECT COD|REG AIR|thely around the bli +4864|37481|9985|2|38|53902.24|0.10|0.02|R|F|1992-12-20|1993-01-07|1993-01-06|TAKE BACK RETURN|SHIP|ording to the ironic, ir +4864|132447|7474|3|45|66574.80|0.02|0.01|A|F|1992-11-17|1993-01-02|1992-11-26|COLLECT COD|SHIP|round the furiously careful pa +4864|30832|5839|4|46|81090.18|0.07|0.03|A|F|1993-02-24|1993-01-02|1993-03-17|TAKE BACK RETURN|RAIL|sts use carefully across the carefull +4865|161406|8955|1|16|23478.40|0.07|0.05|N|O|1997-10-02|1997-08-20|1997-10-04|COLLECT COD|TRUCK|osits haggle. fur +4865|136210|6211|2|4|4984.84|0.07|0.01|N|O|1997-07-24|1997-07-25|1997-08-07|TAKE BACK RETURN|FOB|sts. blithely special instruction +4865|67618|5137|3|44|69766.84|0.10|0.08|N|O|1997-07-25|1997-08-20|1997-08-22|COLLECT COD|FOB|even deposits sleep against the quickly r +4865|49947|4956|4|21|39835.74|0.04|0.02|N|O|1997-07-17|1997-08-10|1997-07-21|NONE|RAIL|eposits detect sly +4865|53744|8755|5|33|56025.42|0.00|0.05|N|O|1997-07-17|1997-08-16|1997-07-30|TAKE BACK RETURN|FOB|y pending notornis ab +4865|64770|9783|6|47|81534.19|0.00|0.05|N|O|1997-08-26|1997-08-07|1997-08-31|NONE|RAIL|y unusual packages. packages +4866|10585|5588|1|9|13460.22|0.01|0.05|N|O|1997-08-30|1997-09-18|1997-09-24|TAKE BACK RETURN|MAIL|ven dependencies x-ray. quic +4866|101252|1253|2|1|1253.25|0.06|0.00|N|O|1997-10-15|1997-10-01|1997-11-14|TAKE BACK RETURN|AIR|latelets nag. q +4866|130432|2946|3|17|24861.31|0.07|0.00|N|O|1997-11-26|1997-10-11|1997-12-12|COLLECT COD|TRUCK|ess packages doubt. even somas wake f +4867|81666|1667|1|7|11533.62|0.09|0.03|A|F|1992-07-17|1992-08-17|1992-07-22|COLLECT COD|FOB|e carefully even packages. slyly ironic i +4867|159641|2157|2|3|5101.92|0.04|0.08|R|F|1992-07-04|1992-07-15|1992-07-21|NONE|AIR|yly silent deposits +4868|72576|5084|1|47|72782.79|0.03|0.03|N|O|1997-04-29|1997-04-27|1997-05-11|DELIVER IN PERSON|SHIP|gle unusual, fluffy packages. foxes cajol +4868|179044|9045|2|8|8984.32|0.10|0.08|N|O|1997-03-26|1997-05-09|1997-04-16|NONE|RAIL|ly special th +4868|190723|724|3|49|88872.28|0.09|0.03|N|O|1997-04-23|1997-05-07|1997-04-26|NONE|SHIP|ys engage. th +4868|79046|9047|4|34|34851.36|0.04|0.02|N|O|1997-05-19|1997-04-27|1997-06-15|NONE|RAIL|en instructions about th +4868|121574|1575|5|22|35102.54|0.07|0.06|N|O|1997-04-26|1997-05-16|1997-05-01|DELIVER IN PERSON|FOB|osits. final foxes boost regular, +4869|40808|3313|1|31|54212.80|0.10|0.01|A|F|1995-01-17|1994-11-30|1995-02-02|NONE|SHIP|ins. always unusual ideas across the ir +4869|57367|2378|2|24|31784.64|0.09|0.06|A|F|1994-11-17|1994-11-07|1994-11-27|COLLECT COD|MAIL|olites cajole after the ideas. special t +4869|156025|6026|3|25|27025.50|0.00|0.05|R|F|1994-11-25|1994-11-14|1994-12-19|DELIVER IN PERSON|AIR|e according t +4869|102539|7560|4|24|36996.72|0.10|0.07|R|F|1994-11-23|1994-11-18|1994-12-11|DELIVER IN PERSON|MAIL|se deposits above the sly, q +4869|172852|7887|5|42|80843.70|0.07|0.04|R|F|1994-10-16|1994-12-10|1994-11-07|TAKE BACK RETURN|REG AIR| slyly even instructions. +4869|121042|8579|6|30|31891.20|0.00|0.05|A|F|1995-01-09|1994-11-20|1995-02-02|COLLECT COD|RAIL|gedly even requests. s +4870|47881|386|1|49|89615.12|0.05|0.05|R|F|1994-11-14|1994-10-24|1994-12-12|TAKE BACK RETURN|SHIP| regular packages +4870|126176|3713|2|6|7213.02|0.06|0.08|A|F|1994-09-09|1994-10-16|1994-09-21|DELIVER IN PERSON|TRUCK|ress requests. bold, silent pinto bea +4870|30179|5186|3|5|5545.85|0.05|0.00|R|F|1994-10-11|1994-10-07|1994-10-24|NONE|AIR|s haggle furiously. slyly ironic dinos +4870|5978|8479|4|4|7535.88|0.03|0.08|A|F|1994-10-23|1994-09-16|1994-11-04|COLLECT COD|RAIL|its wake quickly. slyly quick +4870|70598|3106|5|36|56469.24|0.09|0.06|A|F|1994-09-06|1994-09-17|1994-10-01|COLLECT COD|REG AIR| instructions. carefully pending pac +4871|176651|4203|1|14|24187.10|0.07|0.03|N|O|1995-09-30|1995-07-29|1995-10-18|TAKE BACK RETURN|REG AIR|inst the never ironic +4871|160509|8058|2|17|26681.50|0.07|0.03|N|O|1995-09-09|1995-09-01|1995-10-02|DELIVER IN PERSON|AIR|es. carefully ev +4871|62067|2068|3|3|3087.18|0.03|0.06|N|O|1995-10-03|1995-08-10|1995-10-06|DELIVER IN PERSON|TRUCK|y special packages wak +4871|148471|6014|4|35|53181.45|0.08|0.07|N|O|1995-08-11|1995-07-18|1995-08-29|DELIVER IN PERSON|TRUCK|ackages sle +4871|151422|1423|5|10|14734.20|0.09|0.02|N|O|1995-09-12|1995-09-02|1995-10-05|TAKE BACK RETURN|AIR|s integrate after the a +4871|135500|3040|6|36|55278.00|0.02|0.08|N|O|1995-09-18|1995-08-29|1995-10-05|TAKE BACK RETURN|AIR|ely according +4871|139040|6580|7|10|10790.40|0.10|0.02|N|O|1995-07-13|1995-08-19|1995-07-29|NONE|REG AIR|p ironic theodolites. slyly even platel +4896|40766|767|1|19|32428.44|0.09|0.05|A|F|1992-12-13|1992-11-13|1993-01-09|NONE|AIR|nusual requ +4896|139589|4616|2|44|71657.52|0.04|0.03|A|F|1992-11-24|1992-11-15|1992-12-18|COLLECT COD|MAIL|e after the slowly f +4896|57169|4685|3|6|6756.96|0.04|0.04|A|F|1992-10-30|1992-11-12|1992-11-28|DELIVER IN PERSON|TRUCK|usly regular deposits +4896|22746|2747|4|5|8343.70|0.08|0.02|R|F|1992-12-02|1992-11-11|1992-12-19|COLLECT COD|SHIP|eposits hang carefully. sly +4896|85033|2558|5|21|21378.63|0.07|0.08|R|F|1992-11-18|1992-11-18|1992-11-29|DELIVER IN PERSON|TRUCK|ly express deposits. carefully pending depo +4897|54403|4404|1|26|35292.40|0.01|0.01|R|F|1992-12-22|1992-10-25|1992-12-27|DELIVER IN PERSON|TRUCK|. carefully ironic dep +4897|142171|7200|2|34|41247.78|0.02|0.00|R|F|1992-12-31|1992-11-11|1993-01-30|COLLECT COD|AIR|ts. special dependencies use fluffily +4897|54770|2286|3|42|72440.34|0.09|0.03|A|F|1992-09-23|1992-10-28|1992-10-02|DELIVER IN PERSON|FOB|sts. blithely regular deposits will have +4897|103352|3353|4|19|25751.65|0.03|0.00|A|F|1992-11-08|1992-12-14|1992-12-03|DELIVER IN PERSON|FOB|! ironic, pending dependencies doze furiou +4898|71592|6607|1|44|68797.96|0.07|0.02|A|F|1994-09-13|1994-08-18|1994-09-16|NONE|FOB|y regular grouches about +4899|33087|597|1|14|14281.12|0.06|0.00|R|F|1993-11-10|1994-01-10|1993-11-20|NONE|REG AIR| foxes eat +4900|115397|420|1|40|56495.60|0.10|0.03|A|F|1992-09-02|1992-09-25|1992-09-21|COLLECT COD|TRUCK|heodolites. request +4900|76356|6357|2|33|43967.55|0.06|0.06|R|F|1992-08-18|1992-09-20|1992-08-19|COLLECT COD|MAIL|nto beans nag slyly reg +4900|102019|7040|3|48|49008.48|0.02|0.00|R|F|1992-09-18|1992-08-14|1992-09-28|TAKE BACK RETURN|MAIL|uickly ironic ideas kindle s +4900|31089|1090|4|20|20401.60|0.05|0.00|R|F|1992-09-22|1992-09-23|1992-09-27|TAKE BACK RETURN|MAIL|yers. accounts affix somet +4900|104891|7402|5|40|75835.60|0.03|0.02|R|F|1992-07-14|1992-09-05|1992-07-20|NONE|REG AIR|luffily final dol +4900|102405|4916|6|46|64740.40|0.06|0.08|R|F|1992-07-11|1992-09-19|1992-07-16|TAKE BACK RETURN|SHIP|ly final acco +4901|140928|8471|1|37|72850.04|0.00|0.04|N|O|1998-01-26|1998-02-20|1998-01-31|DELIVER IN PERSON|TRUCK| furiously ev +4901|164332|6849|2|12|16755.96|0.00|0.04|N|O|1998-01-12|1998-02-06|1998-02-03|COLLECT COD|REG AIR|y unusual deposits prom +4901|119727|2239|3|16|27947.52|0.05|0.08|N|O|1998-04-19|1998-03-18|1998-04-21|NONE|AIR|deposits. blithely fin +4901|35623|5624|4|41|63903.42|0.03|0.00|N|O|1998-03-18|1998-02-18|1998-04-14|TAKE BACK RETURN|AIR|efully bold packages affix carefully eve +4901|115677|5678|5|40|67706.80|0.06|0.02|N|O|1998-01-08|1998-01-30|1998-01-15|DELIVER IN PERSON|MAIL|ect across the furiou +4902|195198|2756|1|22|28450.18|0.00|0.04|N|O|1998-10-17|1998-08-10|1998-10-21|COLLECT COD|RAIL|r the furiously final fox +4902|82370|7387|2|1|1352.37|0.09|0.04|N|O|1998-10-12|1998-08-20|1998-11-08|NONE|RAIL|daring foxes? even, bold requests wake f +4903|120758|759|1|1|1778.75|0.06|0.03|R|F|1992-04-23|1992-06-13|1992-05-03|NONE|SHIP|nusual requests +4903|164392|4393|2|6|8738.34|0.09|0.07|R|F|1992-04-01|1992-05-16|1992-04-11|DELIVER IN PERSON|SHIP|azzle quickly along the blithely final pla +4903|119755|7289|3|27|47918.25|0.07|0.06|A|F|1992-06-29|1992-06-09|1992-07-08|COLLECT COD|RAIL|pinto beans are; +4928|99357|9358|1|4|5425.40|0.04|0.02|R|F|1993-10-25|1993-12-24|1993-11-16|TAKE BACK RETURN|REG AIR|bout the slyly final accounts. carefull +4928|92887|2888|2|20|37597.60|0.03|0.08|A|F|1994-01-19|1993-11-29|1994-02-13|DELIVER IN PERSON|SHIP|quiet theodolites ca +4928|148249|5792|3|34|44106.16|0.06|0.05|A|F|1993-10-12|1993-12-31|1993-10-14|DELIVER IN PERSON|AIR|, regular depos +4929|13595|8598|1|20|30171.80|0.00|0.04|N|O|1996-03-12|1996-05-23|1996-03-20|COLLECT COD|REG AIR| final pinto beans detect. final, +4929|78044|5566|2|40|40881.60|0.08|0.03|N|O|1996-05-30|1996-04-13|1996-06-22|TAKE BACK RETURN|AIR|unts against +4929|76404|8912|3|32|44172.80|0.08|0.02|N|O|1996-04-28|1996-05-23|1996-04-30|COLLECT COD|TRUCK|usly at the blithely pending pl +4929|108935|3956|4|26|50542.18|0.00|0.05|N|O|1996-06-10|1996-05-29|1996-06-26|DELIVER IN PERSON|RAIL| slyly. fl +4929|66430|6431|5|24|33514.32|0.09|0.05|N|O|1996-04-15|1996-04-30|1996-05-09|NONE|MAIL| accounts boost +4930|186572|6573|1|35|58049.95|0.03|0.01|A|F|1994-07-09|1994-07-30|1994-07-15|NONE|RAIL|lose slyly regular dependencies. fur +4930|114748|2282|2|20|35254.80|0.02|0.04|A|F|1994-08-21|1994-06-17|1994-08-24|COLLECT COD|FOB|he carefully +4930|167762|279|3|28|51233.28|0.00|0.08|R|F|1994-08-27|1994-06-27|1994-09-18|COLLECT COD|TRUCK|e ironic, unusual courts. regula +4930|165538|5539|4|42|67348.26|0.00|0.00|A|F|1994-06-18|1994-06-22|1994-07-10|COLLECT COD|AIR|ions haggle. furiously regular ideas use +4930|189517|7072|5|38|61047.38|0.02|0.03|A|F|1994-06-06|1994-06-18|1994-07-03|TAKE BACK RETURN|AIR|bold requests sleep never +4931|193048|8087|1|1|1141.04|0.08|0.06|A|F|1995-01-24|1994-12-19|1995-02-07|DELIVER IN PERSON|SHIP| furiously +4931|150506|8052|2|8|12452.00|0.06|0.02|R|F|1994-12-15|1995-01-14|1995-01-06|NONE|SHIP|ts boost. packages wake sly +4931|143024|3025|3|20|21340.40|0.09|0.00|A|F|1995-01-25|1994-12-21|1995-02-06|DELIVER IN PERSON|MAIL|the furious +4931|199283|6841|4|50|69114.00|0.04|0.01|A|F|1994-12-15|1994-12-18|1994-12-23|COLLECT COD|REG AIR|s haggle al +4931|149123|1638|5|25|29303.00|0.05|0.05|R|F|1994-12-19|1995-01-05|1994-12-21|COLLECT COD|FOB|aggle bravely according to the quic +4931|102419|4930|6|8|11371.28|0.02|0.03|A|F|1995-02-16|1994-12-30|1995-03-15|DELIVER IN PERSON|SHIP|dependencies are slyly +4932|50248|7764|1|13|15577.12|0.04|0.03|A|F|1993-09-13|1993-10-16|1993-09-20|DELIVER IN PERSON|SHIP|slyly according to the furiously fin +4932|102499|30|2|15|22522.35|0.01|0.02|R|F|1993-11-15|1993-10-25|1993-11-29|NONE|REG AIR|yly. unusu +4932|86827|9336|3|5|9069.10|0.06|0.06|A|F|1993-10-01|1993-09-13|1993-10-04|NONE|MAIL| haggle furiously. slyly ironic packages sl +4932|97299|2318|4|11|14259.19|0.09|0.06|A|F|1993-09-21|1993-09-30|1993-09-23|COLLECT COD|SHIP|as. special depende +4933|31326|8836|1|48|60351.36|0.08|0.00|N|O|1995-10-10|1995-10-03|1995-11-04|COLLECT COD|SHIP|ideas. sly +4933|81917|6934|2|2|3797.82|0.09|0.00|N|O|1995-10-01|1995-09-29|1995-10-19|DELIVER IN PERSON|MAIL|ctions nag final instructions. accou +4934|96074|1093|1|48|51363.36|0.00|0.01|N|O|1997-05-20|1997-04-22|1997-06-02|TAKE BACK RETURN|SHIP| ideas cajol +4934|109380|9381|2|41|56964.58|0.06|0.06|N|O|1997-06-04|1997-04-11|1997-06-25|TAKE BACK RETURN|FOB|wake final, ironic f +4934|139725|9726|3|8|14117.76|0.03|0.06|N|O|1997-05-20|1997-04-30|1997-05-27|TAKE BACK RETURN|MAIL|arefully express pains cajo +4934|147233|9748|4|9|11522.07|0.06|0.08|N|O|1997-06-10|1997-04-09|1997-06-12|TAKE BACK RETURN|REG AIR| haggle alongside of the +4934|137089|7090|5|29|32656.32|0.09|0.03|N|O|1997-04-10|1997-05-05|1997-05-04|DELIVER IN PERSON|AIR|aggle furiously among the busily final re +4934|51634|1635|6|42|66596.46|0.00|0.07|N|O|1997-03-19|1997-05-05|1997-03-25|NONE|MAIL|ven, ironic ideas +4934|10672|3174|7|2|3165.34|0.10|0.06|N|O|1997-06-05|1997-03-26|1997-06-09|COLLECT COD|MAIL|ongside of the brave, regula +4935|160733|734|1|13|23318.49|0.09|0.01|A|F|1993-06-20|1993-08-13|1993-06-27|COLLECT COD|REG AIR|ly requests. final deposits might +4935|39163|6673|2|37|40779.92|0.01|0.05|R|F|1993-08-30|1993-07-23|1993-09-07|TAKE BACK RETURN|RAIL|y even dependencies nag a +4935|10868|5871|3|24|42692.64|0.06|0.04|A|F|1993-05-29|1993-08-17|1993-06-22|NONE|RAIL|ly quickly s +4935|44935|4936|4|49|92116.57|0.06|0.01|A|F|1993-09-16|1993-08-21|1993-10-12|COLLECT COD|TRUCK|ffily after the furiou +4935|9508|9509|5|14|19845.00|0.08|0.08|A|F|1993-05-30|1993-07-25|1993-05-31|COLLECT COD|FOB|slowly. blith +4935|187915|2952|6|36|72104.76|0.10|0.00|R|F|1993-07-11|1993-07-04|1993-08-01|DELIVER IN PERSON|RAIL|requests across the quick +4960|17091|2094|1|36|36291.24|0.01|0.05|R|F|1995-03-06|1995-05-04|1995-04-05|TAKE BACK RETURN|RAIL|c, unusual accou +4960|44360|9369|2|6|7826.16|0.03|0.08|R|F|1995-03-21|1995-05-13|1995-04-14|TAKE BACK RETURN|SHIP|ual package +4960|148041|5584|3|9|9801.36|0.01|0.03|A|F|1995-03-20|1995-05-05|1995-04-17|COLLECT COD|RAIL|e blithely carefully fina +4960|119052|4075|4|14|14994.70|0.00|0.06|A|F|1995-04-03|1995-04-17|1995-04-07|NONE|RAIL|accounts. warhorses are. grouches +4960|97171|2190|5|8|9345.36|0.07|0.04|R|F|1995-03-14|1995-04-18|1995-04-09|NONE|FOB|as. busily regular packages nag. +4960|145105|5106|6|37|42553.70|0.10|0.04|R|F|1995-05-23|1995-04-12|1995-06-01|DELIVER IN PERSON|MAIL|ending theodolites w +4960|169635|9636|7|42|71594.46|0.08|0.07|A|F|1995-04-19|1995-04-11|1995-05-08|NONE|SHIP|s requests cajole. +4961|43748|8757|1|38|64286.12|0.10|0.07|N|O|1998-07-09|1998-06-03|1998-07-11|TAKE BACK RETURN|FOB|e on the blithely bold accounts. unu +4961|59997|5008|2|1|1956.99|0.08|0.08|N|O|1998-07-08|1998-05-25|1998-07-12|DELIVER IN PERSON|MAIL|s affix carefully silent dependen +4961|161177|1178|3|41|50764.97|0.02|0.02|N|O|1998-07-15|1998-06-15|1998-08-05|TAKE BACK RETURN|REG AIR|ily against the n +4961|99354|4373|4|10|13533.50|0.02|0.04|N|O|1998-04-15|1998-07-03|1998-04-18|DELIVER IN PERSON|MAIL|quests. regular, ironic ideas at the ironi +4962|18377|3380|1|46|59587.02|0.01|0.07|R|F|1993-08-23|1993-09-04|1993-08-27|COLLECT COD|REG AIR| pinto beans grow about the sl +4963|167840|2873|1|38|72497.92|0.08|0.02|N|O|1996-12-25|1996-12-12|1997-01-02|COLLECT COD|AIR|tegrate daringly accou +4963|75326|2848|2|16|20821.12|0.00|0.03|N|O|1996-11-20|1997-01-13|1996-12-06|COLLECT COD|MAIL| carefully slyly u +4964|132406|4920|1|29|41713.60|0.04|0.01|N|O|1997-10-18|1997-08-30|1997-11-01|NONE|AIR|k accounts nag carefully-- ironic, fin +4964|147067|9582|2|46|51246.76|0.06|0.06|N|O|1997-10-05|1997-09-12|1997-10-11|NONE|TRUCK|althy deposits +4964|142559|2560|3|18|28827.90|0.00|0.06|N|O|1997-10-13|1997-09-01|1997-11-10|DELIVER IN PERSON|AIR| platelets. furio +4964|179773|2291|4|12|22233.24|0.08|0.01|N|O|1997-09-03|1997-10-25|1997-09-15|NONE|TRUCK|ully silent instructions ca +4964|40697|8210|5|42|68782.98|0.06|0.04|N|O|1997-09-04|1997-08-28|1997-10-02|TAKE BACK RETURN|AIR| hinder. idly even +4964|192728|286|6|22|40055.84|0.04|0.08|N|O|1997-09-11|1997-10-06|1997-09-29|NONE|AIR|equests doubt quickly. caref +4964|172770|2771|7|28|51597.56|0.00|0.05|N|O|1997-08-30|1997-09-15|1997-09-18|COLLECT COD|RAIL|among the carefully regula +4965|130042|5069|1|28|30017.12|0.05|0.03|A|F|1994-01-02|1993-11-20|1994-01-04|TAKE BACK RETURN|REG AIR| deposits. requests sublate quickly +4965|12001|7004|2|25|22825.00|0.10|0.02|R|F|1994-02-05|1993-12-15|1994-02-24|TAKE BACK RETURN|MAIL|wake at the carefully speci +4965|100514|8045|3|27|40891.77|0.05|0.06|R|F|1993-11-06|1993-12-24|1993-11-30|TAKE BACK RETURN|SHIP|efully final foxes +4965|137469|2496|4|33|49713.18|0.04|0.04|A|F|1993-12-31|1993-11-29|1994-01-27|DELIVER IN PERSON|REG AIR|iously slyly +4966|75766|8274|1|10|17417.60|0.06|0.03|N|O|1996-09-23|1996-11-02|1996-10-07|TAKE BACK RETURN|SHIP| requests. carefully pending requests +4966|193834|6354|2|6|11566.98|0.02|0.01|N|O|1996-12-09|1996-11-29|1996-12-30|NONE|AIR|d deposits are sly excuses. slyly iro +4966|164992|4993|3|7|14398.93|0.00|0.01|N|O|1996-12-08|1996-10-09|1997-01-06|COLLECT COD|MAIL|ckly ironic tithe +4966|15871|3375|4|26|46458.62|0.08|0.03|N|O|1996-11-14|1996-11-29|1996-12-05|COLLECT COD|REG AIR|nt pearls haggle carefully slyly even +4966|143660|6175|5|12|20443.92|0.02|0.07|N|O|1996-12-07|1996-11-23|1996-12-20|DELIVER IN PERSON|RAIL|eodolites. ironic requests across the exp +4967|70796|3304|1|50|88339.50|0.07|0.01|N|O|1997-05-27|1997-05-13|1997-06-12|NONE|REG AIR|kages. final, unusual accounts c +4967|52398|9914|2|43|58066.77|0.00|0.07|N|O|1997-05-28|1997-04-10|1997-06-09|NONE|TRUCK|ons. slyly ironic requests +4967|49975|9976|3|15|28874.55|0.08|0.02|N|O|1997-04-16|1997-04-12|1997-05-08|TAKE BACK RETURN|MAIL|y. blithel +4967|122478|7503|4|1|1500.47|0.10|0.07|N|O|1997-06-04|1997-03-29|1997-06-23|NONE|FOB|osits. unusual frets thrash furiously +4992|183528|3529|1|42|67683.84|0.07|0.01|R|F|1992-07-19|1992-06-16|1992-08-17|TAKE BACK RETURN|RAIL|foxes about the quickly final platele +4992|146436|8951|2|47|69674.21|0.10|0.08|A|F|1992-09-04|1992-08-05|1992-09-21|COLLECT COD|MAIL|atterns use fluffily. +4992|143147|8176|3|17|20232.38|0.03|0.03|A|F|1992-07-05|1992-07-19|1992-07-30|TAKE BACK RETURN|FOB|s along the perma +4992|69920|4933|4|25|47248.00|0.04|0.06|R|F|1992-08-06|1992-07-11|1992-08-20|NONE|SHIP|ly about the never ironic requests. pe +4992|138500|6040|5|23|35385.50|0.01|0.08|R|F|1992-06-28|1992-07-15|1992-07-12|DELIVER IN PERSON|MAIL|uickly regul +4992|162601|150|6|44|73198.40|0.05|0.02|A|F|1992-06-01|1992-07-22|1992-06-03|NONE|RAIL|rmanent, sly packages print slyly. regula +4993|37231|4741|1|34|39719.82|0.05|0.00|R|F|1994-09-21|1994-10-31|1994-09-24|TAKE BACK RETURN|REG AIR|ular, pending packages at the even packa +4993|128552|1065|2|39|61641.45|0.03|0.08|R|F|1994-09-10|1994-09-04|1994-09-26|COLLECT COD|SHIP|pending, regular requests solve caref +4993|165619|3168|3|42|70753.62|0.06|0.00|A|F|1994-08-27|1994-09-24|1994-09-05|NONE|MAIL| final packages at the q +4993|157398|9914|4|31|45117.09|0.10|0.06|A|F|1994-10-02|1994-10-29|1994-10-15|NONE|AIR|nwind thinly platelets. a +4994|155833|3379|1|36|67997.88|0.00|0.06|N|O|1996-09-29|1996-07-30|1996-10-03|TAKE BACK RETURN|TRUCK|ess ideas. blithely silent brai +4994|79276|4291|2|47|58997.69|0.04|0.05|N|O|1996-09-20|1996-08-04|1996-10-15|COLLECT COD|TRUCK|sts. blithely close ideas sleep quic +4994|182034|4553|3|29|32364.87|0.08|0.01|N|O|1996-08-26|1996-09-27|1996-09-25|DELIVER IN PERSON|RAIL|ptotes boost carefully +4994|38154|8155|4|40|43686.00|0.01|0.06|N|O|1996-08-25|1996-08-16|1996-09-07|TAKE BACK RETURN|REG AIR|eposits. regula +4994|41357|3862|5|24|31160.40|0.01|0.07|N|O|1996-08-19|1996-09-24|1996-08-25|TAKE BACK RETURN|FOB|s. slyly ironic deposits cajole f +4994|72561|2562|6|6|9201.36|0.01|0.02|N|O|1996-09-05|1996-08-04|1996-09-30|TAKE BACK RETURN|FOB|grate carefully around th +4994|129748|9749|7|31|55109.94|0.07|0.04|N|O|1996-10-14|1996-09-23|1996-11-08|TAKE BACK RETURN|RAIL|lar decoys cajole fluffil +4995|64943|7450|1|16|30527.04|0.02|0.05|N|O|1996-02-27|1996-04-03|1996-02-29|DELIVER IN PERSON|MAIL|egular, bold packages. accou +4995|80476|8001|2|43|62628.21|0.00|0.06|N|O|1996-02-24|1996-02-20|1996-03-07|NONE|AIR|ts. blithely silent ideas after t +4995|155462|5463|3|22|33384.12|0.03|0.06|N|O|1996-03-17|1996-03-12|1996-04-01|DELIVER IN PERSON|MAIL|s wake furious, express dependencies. +4995|39933|4940|4|9|16856.37|0.07|0.07|N|O|1996-03-07|1996-03-17|1996-03-11|DELIVER IN PERSON|FOB| ironic packages cajole across t +4995|147648|5191|5|48|81390.72|0.08|0.07|N|O|1996-03-22|1996-04-01|1996-04-07|NONE|SHIP|t blithely. requests affix blithely. +4995|109830|4851|6|48|88311.84|0.09|0.07|N|O|1996-04-14|1996-04-04|1996-05-07|DELIVER IN PERSON|RAIL|nstructions. carefully final depos +4996|55891|902|1|35|64641.15|0.07|0.01|A|F|1992-10-30|1992-10-27|1992-11-05|TAKE BACK RETURN|SHIP|s. unusual, regular dolphins integrate care +4996|155848|5849|2|39|74249.76|0.02|0.07|A|F|1992-09-19|1992-10-19|1992-10-06|COLLECT COD|FOB|equests are carefully final +4996|127777|2802|3|12|21657.24|0.04|0.06|R|F|1993-01-09|1992-11-22|1993-02-04|DELIVER IN PERSON|SHIP|usly bold requests sleep dogge +4996|143576|1119|4|13|21054.41|0.00|0.00|A|F|1992-09-17|1992-12-02|1992-10-07|DELIVER IN PERSON|TRUCK|o beans use about the furious +4997|78040|5562|1|44|44793.76|0.02|0.05|N|O|1998-06-09|1998-06-12|1998-07-07|NONE|RAIL|r escapades ca +4997|16188|3692|2|5|5520.90|0.02|0.04|N|O|1998-05-16|1998-06-05|1998-06-07|COLLECT COD|REG AIR|cuses are furiously unusual asymptotes +4997|57193|7194|3|24|27604.56|0.04|0.06|N|O|1998-04-20|1998-04-23|1998-05-16|NONE|AIR|xpress, bo +4997|39081|1585|4|5|5100.40|0.10|0.03|N|O|1998-06-12|1998-04-24|1998-06-13|DELIVER IN PERSON|TRUCK|aggle slyly alongside of the slyly i +4997|21826|4329|5|46|80399.72|0.00|0.04|N|O|1998-04-28|1998-06-04|1998-05-08|TAKE BACK RETURN|SHIP|ecial courts are carefully +4997|28912|6419|6|2|3681.82|0.07|0.01|N|O|1998-07-09|1998-06-10|1998-07-21|TAKE BACK RETURN|REG AIR|counts. slyl +4998|153471|5987|1|12|18293.64|0.04|0.03|A|F|1992-02-20|1992-03-06|1992-03-01|TAKE BACK RETURN|RAIL| sleep slyly furiously final accounts. ins +4998|182630|7667|2|15|25689.45|0.06|0.00|R|F|1992-04-24|1992-03-21|1992-05-02|NONE|REG AIR|heodolites sleep quickly. +4998|58992|8993|3|27|52676.73|0.06|0.02|R|F|1992-03-17|1992-02-26|1992-04-05|DELIVER IN PERSON|MAIL|the blithely ironic +4998|62376|7389|4|47|62903.39|0.10|0.04|A|F|1992-02-07|1992-03-07|1992-02-19|DELIVER IN PERSON|TRUCK|mong the careful +4998|144589|2132|5|24|39205.92|0.01|0.04|R|F|1992-01-25|1992-03-16|1992-01-27|COLLECT COD|REG AIR| unwind about +4998|98492|1002|6|8|11923.92|0.03|0.07|A|F|1992-05-01|1992-03-03|1992-05-24|TAKE BACK RETURN|AIR|ions nag quickly according to the theodolit +4999|152687|7718|1|30|52190.40|0.00|0.02|A|F|1993-08-20|1993-08-15|1993-08-30|NONE|AIR|ades cajole carefully unusual ide +4999|9204|9205|2|44|48980.80|0.03|0.01|A|F|1993-08-01|1993-08-04|1993-08-17|COLLECT COD|REG AIR|ependencies. slowly regu +4999|85996|5997|3|30|59459.70|0.09|0.01|R|F|1993-07-21|1993-08-11|1993-08-20|DELIVER IN PERSON|RAIL|s cajole among the blithel +5024|165411|444|1|17|25098.97|0.10|0.02|N|O|1996-11-24|1997-01-10|1996-12-04|NONE|AIR| to the expre +5024|57578|84|2|41|62958.37|0.06|0.01|N|O|1996-11-09|1996-12-03|1996-12-01|COLLECT COD|REG AIR|osits hinder carefully +5024|111009|3521|3|18|18360.00|0.04|0.03|N|O|1996-12-02|1997-01-16|1996-12-05|NONE|MAIL|zle carefully sauternes. quickly +5024|122508|5021|4|42|64281.00|0.03|0.06|N|O|1996-12-02|1996-12-08|1996-12-04|DELIVER IN PERSON|RAIL|tegrate. busily spec +5025|29421|4426|1|11|14854.62|0.00|0.04|N|O|1997-02-21|1997-04-16|1997-03-14|COLLECT COD|SHIP|the carefully final esc +5025|77470|2485|2|10|14474.70|0.07|0.04|N|O|1997-06-04|1997-04-29|1997-06-28|COLLECT COD|RAIL|lly silent deposits boost busily again +5026|95360|7870|1|13|17619.68|0.02|0.04|N|O|1997-12-23|1997-11-02|1998-01-03|TAKE BACK RETURN|SHIP|endencies sleep carefully alongs +5027|97261|4789|1|6|7549.56|0.04|0.05|N|O|1997-09-28|1997-11-24|1997-10-25|NONE|FOB|ar, ironic deposi +5027|61744|1745|2|39|66523.86|0.06|0.01|N|O|1997-09-09|1997-11-13|1997-09-21|TAKE BACK RETURN|FOB|ess requests! quickly regular pac +5027|125140|165|3|32|37284.48|0.00|0.01|N|O|1997-11-13|1997-10-29|1997-11-18|TAKE BACK RETURN|RAIL|cording to +5027|25594|5595|4|37|56224.83|0.02|0.00|N|O|1997-10-05|1997-10-30|1997-10-26|NONE|REG AIR|ost slyly fluffily +5027|142732|2733|5|3|5324.19|0.03|0.06|N|O|1997-09-30|1997-11-26|1997-10-05|DELIVER IN PERSON|AIR|t the even mu +5027|86493|9002|6|25|36987.25|0.06|0.00|N|O|1997-09-16|1997-11-25|1997-10-08|TAKE BACK RETURN|RAIL|ic ideas. requests sleep fluffily am +5027|80444|2953|7|50|71222.00|0.07|0.02|N|O|1997-09-18|1997-11-07|1997-10-05|DELIVER IN PERSON|MAIL| beans dazzle according to the fluffi +5028|13876|8879|1|15|26848.05|0.07|0.07|R|F|1992-07-17|1992-07-16|1992-08-05|COLLECT COD|REG AIR|es are quickly final pains. furiously pend +5028|198686|8687|2|15|26770.20|0.03|0.07|R|F|1992-08-02|1992-07-09|1992-08-30|NONE|REG AIR|gular, bold pinto bea +5029|153597|3598|1|17|28060.03|0.02|0.01|A|F|1993-03-12|1992-12-18|1993-04-02|DELIVER IN PERSON|FOB|! packages boost blithely. furious +5029|96432|8942|2|2|2856.86|0.00|0.04|A|F|1992-11-25|1993-01-04|1992-12-20|DELIVER IN PERSON|MAIL|packages. furiously ironi +5030|101356|1357|1|22|29861.70|0.04|0.06|N|O|1998-09-01|1998-08-15|1998-09-30|TAKE BACK RETURN|TRUCK|. quickly regular foxes believe +5030|79762|4777|2|50|87088.00|0.05|0.06|N|O|1998-08-22|1998-07-25|1998-09-18|TAKE BACK RETURN|FOB|ss excuses serve bli +5031|49942|9943|1|15|28379.10|0.02|0.05|R|F|1995-04-01|1995-02-24|1995-04-12|DELIVER IN PERSON|AIR|yly pending theodolites. +5031|160895|8444|2|40|78235.60|0.10|0.04|A|F|1994-12-04|1995-01-27|1995-01-01|NONE|TRUCK|ns hang blithely across th +5031|153067|613|3|4|4480.24|0.01|0.07|R|F|1994-12-26|1995-02-24|1995-01-11|NONE|RAIL|after the even frays: ironic, unusual th +5031|180435|2954|4|31|46978.33|0.10|0.08|R|F|1995-01-15|1995-01-08|1995-02-09|COLLECT COD|MAIL|ts across the even requests doze furiously +5056|47302|4815|1|7|8745.10|0.09|0.01|N|O|1997-04-28|1997-04-07|1997-05-15|DELIVER IN PERSON|TRUCK|rouches after the pending instruc +5056|196388|3946|2|19|28203.22|0.04|0.00|N|O|1997-03-24|1997-05-05|1997-04-23|DELIVER IN PERSON|AIR|c theodolites. ironic a +5056|89040|4057|3|23|23667.92|0.02|0.05|N|O|1997-05-12|1997-04-28|1997-05-25|NONE|SHIP|ickly regular requests cajole. depos +5056|86915|1932|4|14|26626.74|0.08|0.00|N|O|1997-06-09|1997-04-13|1997-07-06|COLLECT COD|SHIP|sts haggle carefully along the slyl +5057|36914|4424|1|38|70334.58|0.02|0.03|N|O|1997-10-24|1997-09-07|1997-10-30|TAKE BACK RETURN|MAIL|packages. stealthily bold wa +5057|7083|9584|2|45|44553.60|0.08|0.07|N|O|1997-09-20|1997-10-02|1997-10-20|NONE|FOB| asymptotes wake slyl +5058|192440|4960|1|16|24519.04|0.09|0.07|N|O|1998-07-12|1998-06-09|1998-07-15|DELIVER IN PERSON|SHIP| the special foxes +5059|69538|7057|1|5|7537.65|0.03|0.08|R|F|1993-12-23|1994-01-12|1993-12-24|TAKE BACK RETURN|FOB|ts affix slyly accordi +5059|122882|7907|2|19|36192.72|0.06|0.04|R|F|1994-03-02|1993-12-26|1994-03-14|TAKE BACK RETURN|MAIL| special ideas poach blithely qu +5059|76305|8813|3|45|57658.50|0.02|0.00|A|F|1994-01-28|1994-01-08|1994-02-18|DELIVER IN PERSON|MAIL|enly. requests doze. express, close pa +5060|24932|2439|1|27|50137.11|0.10|0.07|R|F|1992-07-23|1992-09-05|1992-08-07|COLLECT COD|SHIP|s. ironic +5060|31033|3537|2|28|26992.84|0.04|0.04|R|F|1992-09-25|1992-08-11|1992-10-09|NONE|REG AIR|c requests +5060|160257|258|3|15|19758.75|0.06|0.01|A|F|1992-08-28|1992-08-20|1992-09-01|DELIVER IN PERSON|AIR|ular deposits sl +5061|164896|9929|1|18|35296.02|0.03|0.00|A|F|1993-10-20|1993-10-05|1993-10-28|TAKE BACK RETURN|SHIP|atelets among the ca +5061|197491|2530|2|8|12707.92|0.01|0.02|R|F|1993-09-07|1993-10-31|1993-10-04|DELIVER IN PERSON|REG AIR|regular foxes. ir +5061|23216|3217|3|26|29619.46|0.02|0.05|A|F|1993-11-07|1993-09-13|1993-11-13|NONE|REG AIR| cajole slyly. carefully spe +5062|100784|3295|1|9|16063.02|0.08|0.00|R|F|1993-01-02|1992-12-01|1993-01-20|TAKE BACK RETURN|MAIL| silent theodolites wake. c +5062|74681|4682|2|4|6622.72|0.02|0.02|R|F|1993-02-06|1992-12-14|1993-03-03|DELIVER IN PERSON|AIR|ke furiously express theodolites. +5062|158504|8505|3|50|78125.00|0.09|0.07|A|F|1992-12-25|1992-12-13|1992-12-29|TAKE BACK RETURN|MAIL| the regular, unusual pains. specia +5062|160148|2665|4|18|21746.52|0.03|0.07|R|F|1992-11-04|1992-12-25|1992-11-05|NONE|SHIP|furiously pending requests are ruthles +5062|193632|1190|5|25|43140.75|0.08|0.02|R|F|1992-12-15|1992-11-17|1993-01-01|NONE|TRUCK|uthless excuses ag +5063|128529|8530|1|31|48283.12|0.08|0.01|N|O|1997-06-02|1997-06-20|1997-06-27|NONE|RAIL|kages. ironic, ironic courts wake. carefu +5063|173640|1192|2|43|73686.52|0.04|0.08|N|O|1997-09-14|1997-07-05|1997-10-05|TAKE BACK RETURN|TRUCK|latelets might nod blithely regular requ +5063|166201|1234|3|2|2534.40|0.02|0.03|N|O|1997-06-17|1997-07-27|1997-06-24|COLLECT COD|SHIP|kly regular i +5063|134525|9552|4|18|28071.36|0.08|0.05|N|O|1997-06-02|1997-06-18|1997-06-06|TAKE BACK RETURN|RAIL|refully quiet reques +5063|160636|5669|5|1|1696.63|0.06|0.07|N|O|1997-09-03|1997-06-26|1997-10-03|NONE|FOB|ously special +5088|77900|5422|1|23|43191.70|0.06|0.06|R|F|1993-03-03|1993-03-07|1993-03-08|NONE|FOB|cording to the fluffily expr +5088|50009|7525|2|41|39319.00|0.09|0.00|R|F|1993-01-22|1993-03-07|1993-02-09|TAKE BACK RETURN|TRUCK|ing requests. +5088|85245|2770|3|36|44288.64|0.10|0.05|A|F|1993-04-16|1993-04-03|1993-05-14|NONE|TRUCK|the furiously final deposits. furiously re +5088|108479|6010|4|10|14874.70|0.04|0.05|R|F|1993-04-07|1993-02-06|1993-04-26|NONE|FOB|beans. special requests af +5089|157064|9580|1|4|4484.24|0.05|0.06|R|F|1992-09-18|1992-09-28|1992-10-13|DELIVER IN PERSON|TRUCK|nts sleep blithely +5089|161548|1549|2|20|32190.80|0.00|0.07|R|F|1992-10-10|1992-10-07|1992-11-06|COLLECT COD|RAIL| ironic accounts +5089|123570|1107|3|46|73304.22|0.03|0.04|A|F|1992-11-09|1992-10-13|1992-11-10|TAKE BACK RETURN|RAIL|above the express accounts. exc +5089|33436|5940|4|38|52038.34|0.05|0.03|R|F|1992-11-23|1992-09-11|1992-12-22|TAKE BACK RETURN|SHIP|regular instructions are +5090|21309|1310|1|22|27066.60|0.07|0.00|N|O|1997-05-10|1997-05-25|1997-05-24|TAKE BACK RETURN|TRUCK|ets integrate ironic, regul +5090|128542|8543|2|46|72244.84|0.05|0.00|N|O|1997-04-05|1997-04-14|1997-05-01|COLLECT COD|REG AIR|lose theodolites sleep blit +5090|1804|9305|3|22|37527.60|0.09|0.05|N|O|1997-07-03|1997-04-12|1997-07-26|NONE|REG AIR|ular requests su +5090|113646|6158|4|2|3319.28|0.03|0.06|N|O|1997-04-07|1997-04-23|1997-05-01|TAKE BACK RETURN|AIR|tes. slowly iro +5090|47604|7605|5|21|32583.60|0.10|0.02|N|O|1997-03-29|1997-04-24|1997-04-25|TAKE BACK RETURN|FOB|ly express accounts. slyly even r +5090|79662|4677|6|30|49249.80|0.02|0.03|N|O|1997-05-04|1997-04-14|1997-05-30|COLLECT COD|MAIL|osits nag slyly. fluffily ex +5091|77312|4834|1|50|64465.50|0.05|0.03|N|O|1998-07-21|1998-06-22|1998-07-26|COLLECT COD|REG AIR|al dependencies. r +5092|163090|8123|1|30|34592.70|0.06|0.00|N|O|1995-12-27|1995-12-08|1996-01-09|DELIVER IN PERSON|MAIL|ss, ironic deposits. furiously stea +5092|44716|2229|2|34|56464.14|0.04|0.02|N|O|1995-12-09|1995-12-26|1995-12-21|TAKE BACK RETURN|AIR|ckages nag +5092|139286|6826|3|13|17228.64|0.06|0.01|N|O|1995-11-21|1996-01-05|1995-12-19|TAKE BACK RETURN|SHIP|es detect sly +5092|179246|9247|4|14|18553.36|0.04|0.00|N|O|1996-02-20|1995-11-30|1996-03-20|DELIVER IN PERSON|REG AIR| deposits cajole furiously against the sly +5092|185660|8179|5|42|73317.72|0.01|0.02|N|O|1995-11-06|1996-01-01|1995-12-06|DELIVER IN PERSON|AIR|s use along t +5092|177555|5107|6|11|17958.05|0.03|0.03|N|O|1995-12-02|1995-12-27|1995-12-11|COLLECT COD|MAIL|ly against the slyly silen +5092|158325|8326|7|50|69166.00|0.10|0.03|N|O|1995-11-30|1996-01-14|1995-12-19|NONE|REG AIR|r platelets maintain car +5093|167649|7650|1|40|68665.60|0.05|0.01|R|F|1993-09-16|1993-11-04|1993-10-05|TAKE BACK RETURN|REG AIR|ing pinto beans. quickly bold dependenci +5093|73419|941|2|15|20886.15|0.01|0.04|A|F|1993-12-02|1993-11-18|1994-01-01|DELIVER IN PERSON|FOB|ly among the unusual foxe +5093|150780|3296|3|31|56754.18|0.00|0.02|R|F|1993-09-22|1993-11-14|1993-09-26|TAKE BACK RETURN|REG AIR| against the +5093|155669|700|4|37|63812.42|0.04|0.00|A|F|1993-10-26|1993-12-02|1993-10-27|NONE|TRUCK|courts. qui +5093|114865|9888|5|30|56395.80|0.06|0.05|A|F|1993-11-22|1993-11-27|1993-12-14|DELIVER IN PERSON|TRUCK|ithely ironic sheaves use fluff +5093|120197|2710|6|31|37732.89|0.01|0.08|A|F|1993-12-17|1993-11-14|1994-01-02|NONE|SHIP|he final foxes. fluffily ironic +5094|142519|5034|1|19|29668.69|0.03|0.03|R|F|1993-03-31|1993-06-12|1993-04-04|NONE|AIR|ronic foxes. furi +5094|107604|5135|2|23|37066.80|0.05|0.07|R|F|1993-06-13|1993-05-19|1993-07-06|NONE|MAIL|st furiously above the fluffily care +5094|91455|8983|3|11|15910.95|0.04|0.08|A|F|1993-06-25|1993-06-24|1993-07-18|TAKE BACK RETURN|MAIL|s cajole quickly against the furiously ex +5094|78510|8511|4|21|31258.71|0.09|0.08|R|F|1993-07-26|1993-05-03|1993-08-16|NONE|MAIL| blithely furiously final re +5095|64242|1761|1|46|55487.04|0.07|0.01|A|F|1992-06-26|1992-06-25|1992-07-05|COLLECT COD|RAIL|egular instruction +5095|105488|3019|2|2|2986.96|0.07|0.08|A|F|1992-07-09|1992-05-25|1992-07-21|DELIVER IN PERSON|REG AIR|detect car +5095|122758|5271|3|28|49861.00|0.01|0.04|A|F|1992-06-20|1992-06-27|1992-06-22|DELIVER IN PERSON|AIR| into the final courts. ca +5095|177984|3019|4|42|86603.16|0.08|0.08|R|F|1992-05-23|1992-06-01|1992-06-18|COLLECT COD|TRUCK|ccounts. packages could have t +5095|165425|5426|5|9|13413.78|0.10|0.07|R|F|1992-08-14|1992-06-23|1992-08-16|TAKE BACK RETURN|REG AIR|bold theodolites wake about the expr +5095|96768|6769|6|15|26471.40|0.01|0.06|A|F|1992-07-11|1992-07-12|1992-08-09|COLLECT COD|AIR| to the packages wake sly +5095|168890|8891|7|40|78355.60|0.05|0.02|A|F|1992-07-11|1992-06-07|1992-07-26|DELIVER IN PERSON|MAIL|carefully unusual plat +5120|132365|7392|1|28|39126.08|0.06|0.03|N|O|1996-07-20|1996-08-31|1996-08-06|NONE|RAIL| across the silent requests. caref +5121|183562|1117|1|23|37847.88|0.06|0.01|A|F|1992-05-18|1992-06-20|1992-06-02|TAKE BACK RETURN|REG AIR|even courts are blithely ironically +5121|110722|8256|2|45|77972.40|0.08|0.04|A|F|1992-08-13|1992-07-27|1992-09-12|NONE|TRUCK|pecial accounts cajole ca +5121|96595|1614|3|27|42972.93|0.08|0.07|R|F|1992-06-17|1992-06-11|1992-06-19|NONE|MAIL|ly silent theodolit +5121|67014|9521|4|10|9810.10|0.04|0.05|R|F|1992-06-08|1992-07-10|1992-07-02|TAKE BACK RETURN|FOB|e quickly according +5121|88202|8203|5|46|54749.20|0.03|0.02|R|F|1992-05-27|1992-07-19|1992-05-28|TAKE BACK RETURN|FOB|use express foxes. slyly +5121|79|7580|6|2|1958.14|0.04|0.07|R|F|1992-08-10|1992-06-28|1992-08-11|NONE|FOB| final, regular account +5122|182287|9842|1|28|38339.84|0.03|0.00|N|O|1996-04-20|1996-03-29|1996-04-29|DELIVER IN PERSON|FOB|g the busily ironic accounts boos +5122|81957|9482|2|43|83374.85|0.09|0.03|N|O|1996-05-31|1996-04-12|1996-06-13|NONE|MAIL|ut the carefully special foxes. idle, +5122|44058|4059|3|12|12024.60|0.07|0.03|N|O|1996-04-02|1996-04-27|1996-04-10|DELIVER IN PERSON|AIR|lar instructions +5123|25745|5746|1|13|21719.62|0.08|0.07|N|O|1998-05-17|1998-03-23|1998-06-02|COLLECT COD|MAIL|regular pearls +5124|54193|1709|1|43|49329.17|0.00|0.02|N|O|1997-07-10|1997-05-13|1997-07-31|COLLECT COD|AIR|onic package +5124|5101|2602|2|41|41250.10|0.02|0.06|N|O|1997-07-05|1997-06-29|1997-07-23|DELIVER IN PERSON|RAIL|wake across the +5124|124798|4799|3|44|80202.76|0.03|0.03|N|O|1997-07-13|1997-06-26|1997-08-01|DELIVER IN PERSON|RAIL|equests. carefully unusual d +5124|69465|1972|4|36|51640.56|0.10|0.07|N|O|1997-04-20|1997-07-03|1997-05-04|TAKE BACK RETURN|AIR|r deposits ab +5125|5424|7925|1|38|50517.96|0.09|0.05|N|O|1998-03-20|1998-04-14|1998-03-22|COLLECT COD|MAIL|ily even deposits w +5125|159077|9078|2|5|5680.35|0.08|0.06|N|O|1998-04-07|1998-04-14|1998-04-29|COLLECT COD|RAIL| thinly even pack +5126|23568|8573|1|33|49221.48|0.02|0.02|R|F|1993-02-04|1992-12-23|1993-02-14|NONE|RAIL|ipliers promise furiously whithout the +5126|100832|5853|2|43|78811.69|0.09|0.04|R|F|1993-01-07|1992-12-19|1993-01-16|COLLECT COD|MAIL|e silently. ironic, unusual accounts +5126|77521|29|3|23|34465.96|0.08|0.01|R|F|1993-01-02|1993-01-02|1993-01-05|COLLECT COD|TRUCK|egular, blithe packages. +5127|18637|1139|1|33|51335.79|0.08|0.04|N|O|1997-03-25|1997-03-02|1997-04-04|NONE|SHIP| bold deposits use carefully a +5127|31122|3626|2|20|21062.40|0.01|0.03|N|O|1997-05-11|1997-02-26|1997-05-12|TAKE BACK RETURN|SHIP|dolites about the final platelets w +5152|104917|2448|1|9|17297.19|0.04|0.03|N|O|1997-04-11|1997-02-11|1997-04-18|COLLECT COD|AIR| cajole furiously alongside of the bo +5152|133398|5912|2|50|71569.50|0.04|0.04|N|O|1997-03-10|1997-02-04|1997-03-15|COLLECT COD|FOB| the final deposits. slyly ironic warth +5153|34465|6969|1|42|58777.32|0.03|0.01|N|O|1995-10-03|1995-11-09|1995-10-11|COLLECT COD|RAIL|re thinly. ironic +5153|52804|320|2|14|24595.20|0.05|0.05|N|O|1995-11-29|1995-10-21|1995-12-08|TAKE BACK RETURN|TRUCK| slyly daring pinto beans lose blithely fi +5153|67863|370|3|30|54925.80|0.09|0.01|N|O|1995-11-10|1995-11-14|1995-11-16|DELIVER IN PERSON|AIR|beans sleep bl +5153|172162|7197|4|32|39493.12|0.10|0.08|N|O|1995-12-05|1995-09-25|1996-01-03|DELIVER IN PERSON|MAIL|egular deposits. ironi +5153|111676|9210|5|36|60756.12|0.01|0.03|N|O|1995-12-15|1995-11-08|1995-12-30|COLLECT COD|TRUCK| ironic instru +5153|135055|2595|6|42|45782.10|0.00|0.03|N|O|1995-10-19|1995-11-23|1995-11-06|TAKE BACK RETURN|RAIL|ickly even deposi +5154|189775|2294|1|11|20512.47|0.02|0.05|N|O|1997-08-06|1997-06-30|1997-09-04|NONE|RAIL|luffily bold foxes. final +5154|143948|3949|2|15|29879.10|0.07|0.08|N|O|1997-06-23|1997-07-11|1997-07-11|NONE|AIR|even packages. packages use +5155|47932|7933|1|1|1879.93|0.00|0.00|A|F|1994-07-03|1994-08-11|1994-07-29|COLLECT COD|FOB|oze slyly after the silent, regular idea +5155|187548|2585|2|5|8177.70|0.08|0.02|A|F|1994-06-30|1994-08-13|1994-07-15|TAKE BACK RETURN|AIR|ole blithely slyly ironic +5155|105449|2980|3|28|40724.32|0.05|0.02|R|F|1994-07-01|1994-07-19|1994-07-18|COLLECT COD|REG AIR|s cajole. accounts wake. thinly quiet pla +5155|78860|6382|4|39|71715.54|0.09|0.06|A|F|1994-08-25|1994-09-01|1994-09-18|COLLECT COD|TRUCK|l dolphins nag caref +5156|116520|1543|1|21|32266.92|0.06|0.03|N|O|1997-01-01|1997-01-30|1997-01-11|TAKE BACK RETURN|TRUCK|ts detect against the furiously reg +5156|147020|2049|2|36|38412.72|0.04|0.07|N|O|1997-02-12|1996-12-10|1997-03-13|TAKE BACK RETURN|REG AIR| slyly even orbi +5157|54165|1681|1|35|39170.60|0.06|0.08|N|O|1997-07-28|1997-09-30|1997-08-15|TAKE BACK RETURN|REG AIR|to the furiously sil +5157|137834|7835|2|18|33692.94|0.10|0.04|N|O|1997-09-06|1997-10-03|1997-09-19|COLLECT COD|MAIL|y bold deposits nag blithely. final reque +5157|166387|6388|3|15|21800.70|0.09|0.00|N|O|1997-07-27|1997-08-30|1997-08-08|DELIVER IN PERSON|RAIL|cajole. spec +5157|58188|694|4|25|28654.50|0.00|0.03|N|O|1997-08-24|1997-09-23|1997-08-28|COLLECT COD|REG AIR| packages detect. even requests against th +5157|148947|6490|5|40|79837.60|0.09|0.06|N|O|1997-08-11|1997-08-28|1997-09-01|TAKE BACK RETURN|FOB|ial packages according to +5157|149156|6699|6|26|31333.90|0.10|0.01|N|O|1997-07-28|1997-08-22|1997-08-22|NONE|FOB|nto beans cajole car +5157|48745|6258|7|12|20324.88|0.10|0.08|N|O|1997-10-19|1997-08-07|1997-10-26|NONE|FOB|es. busily +5158|44249|1762|1|43|51309.32|0.10|0.04|N|O|1997-04-10|1997-03-06|1997-04-15|DELIVER IN PERSON|AIR|nusual platelets. slyly even foxes cajole +5158|84248|4249|2|18|22180.32|0.04|0.04|N|O|1997-04-30|1997-03-28|1997-05-12|COLLECT COD|REG AIR|hely regular pa +5158|141878|4393|3|41|78714.67|0.05|0.05|N|O|1997-02-25|1997-03-19|1997-03-03|COLLECT COD|AIR|deposits. quickly special +5158|130049|7589|4|49|52872.96|0.05|0.01|N|O|1997-04-10|1997-03-21|1997-04-30|NONE|REG AIR|r requests sleep q +5158|118468|6002|5|20|29729.20|0.01|0.04|N|O|1997-02-03|1997-02-20|1997-02-08|TAKE BACK RETURN|AIR|latelets use accordin +5158|87969|478|6|39|76321.44|0.08|0.04|N|O|1997-05-15|1997-04-04|1997-06-02|DELIVER IN PERSON|FOB|lithely fina +5158|90030|7558|7|38|38761.14|0.10|0.05|N|O|1997-05-09|1997-03-03|1997-06-04|NONE|SHIP|uffily regular ac +5159|123367|904|1|39|54224.04|0.06|0.07|N|O|1996-12-17|1996-12-08|1997-01-10|COLLECT COD|MAIL|re furiously after the pending dolphin +5159|16681|9183|2|46|73493.28|0.01|0.01|N|O|1996-12-15|1996-12-07|1996-12-30|DELIVER IN PERSON|SHIP|s kindle slyly carefully regular +5159|151238|8784|3|22|28363.06|0.01|0.02|N|O|1996-11-06|1996-11-04|1996-11-15|TAKE BACK RETURN|SHIP|he furiously sile +5159|51907|1908|4|5|9294.50|0.10|0.00|N|O|1996-11-25|1996-12-19|1996-12-25|TAKE BACK RETURN|FOB|nal deposits. pending, ironic ideas grow +5159|197897|417|5|36|71816.04|0.06|0.01|N|O|1997-01-24|1996-11-07|1997-02-08|NONE|REG AIR|packages wake. +5184|152521|7552|1|33|51926.16|0.07|0.04|N|O|1998-08-17|1998-10-16|1998-08-24|TAKE BACK RETURN|AIR|posits. carefully express asympto +5184|15749|3253|2|47|78242.78|0.05|0.01|N|O|1998-11-02|1998-08-19|1998-11-07|COLLECT COD|TRUCK|se. carefully express pinto beans x +5184|87427|9936|3|39|55162.38|0.03|0.06|N|O|1998-10-27|1998-10-17|1998-11-19|DELIVER IN PERSON|FOB|es above the care +5184|175958|5959|4|26|52882.70|0.05|0.08|N|O|1998-11-11|1998-08-26|1998-12-01|TAKE BACK RETURN|TRUCK| packages are +5184|123097|5610|5|19|21281.71|0.06|0.03|N|O|1998-11-15|1998-10-12|1998-11-21|COLLECT COD|REG AIR|refully express platelets sleep carefull +5184|79525|4540|6|49|73721.48|0.02|0.00|N|O|1998-09-18|1998-08-28|1998-10-14|COLLECT COD|FOB|thlessly closely even reque +5185|196408|3966|1|37|55662.80|0.00|0.04|N|O|1997-08-08|1997-09-08|1997-08-14|COLLECT COD|SHIP|gainst the courts dazzle care +5185|24597|2104|2|32|48690.88|0.06|0.00|N|O|1997-08-17|1997-09-30|1997-08-24|TAKE BACK RETURN|REG AIR|ackages. slyly even requests +5185|195889|928|3|41|81380.08|0.00|0.05|N|O|1997-10-15|1997-10-11|1997-11-02|COLLECT COD|REG AIR|ly blithe deposits. furi +5185|95730|5731|4|30|51771.90|0.09|0.04|N|O|1997-10-17|1997-09-16|1997-10-23|TAKE BACK RETURN|SHIP|ress packages are furiously +5185|127706|7707|5|8|13869.60|0.04|0.00|N|O|1997-08-30|1997-09-02|1997-09-22|COLLECT COD|REG AIR|sts around the slyly perma +5185|145806|835|6|50|92590.00|0.03|0.04|N|O|1997-10-15|1997-10-19|1997-11-06|TAKE BACK RETURN|FOB|final platelets. ideas sleep careful +5186|54412|9423|1|38|51923.58|0.06|0.02|N|O|1996-11-23|1996-09-21|1996-12-11|DELIVER IN PERSON|MAIL|y ruthless foxes. fluffily +5186|90920|921|2|31|59238.52|0.09|0.03|N|O|1996-10-19|1996-09-26|1996-10-25|TAKE BACK RETURN|REG AIR| accounts use furiously slyly spe +5186|88279|3296|3|26|32949.02|0.03|0.02|N|O|1996-08-08|1996-10-05|1996-08-21|DELIVER IN PERSON|FOB|capades. accounts sublate. pinto +5186|89226|9227|4|8|9721.76|0.10|0.05|N|O|1996-09-23|1996-09-29|1996-09-30|COLLECT COD|RAIL|y regular notornis k +5186|17403|9905|5|28|36971.20|0.09|0.03|N|O|1996-10-05|1996-10-27|1996-10-19|TAKE BACK RETURN|RAIL|al decoys. blit +5186|81990|4499|6|35|69019.65|0.00|0.05|N|O|1996-10-20|1996-10-12|1996-11-12|TAKE BACK RETURN|RAIL|sly silent pack +5186|197847|367|7|44|85572.96|0.00|0.08|N|O|1996-09-23|1996-10-14|1996-10-01|NONE|TRUCK|old, final accounts cajole sl +5187|10977|8481|1|49|92510.53|0.04|0.06|N|O|1997-10-20|1997-10-12|1997-10-26|DELIVER IN PERSON|AIR|l, regular platelets instead of the foxes w +5187|82848|2849|2|1|1830.84|0.10|0.08|N|O|1997-08-08|1997-08-24|1997-08-22|DELIVER IN PERSON|REG AIR|aggle never bold +5188|117534|46|1|18|27927.54|0.04|0.03|N|O|1995-06-19|1995-05-19|1995-06-25|DELIVER IN PERSON|AIR|p according to the sometimes regu +5188|193702|1260|2|36|64645.20|0.04|0.02|A|F|1995-03-09|1995-05-16|1995-03-19|NONE|TRUCK|packages? blithely s +5188|147932|2961|3|9|17819.37|0.06|0.08|A|F|1995-05-09|1995-05-22|1995-05-19|TAKE BACK RETURN|REG AIR|r attainments are across the +5189|137325|2352|1|44|59942.08|0.02|0.06|A|F|1994-01-13|1994-02-07|1994-01-21|DELIVER IN PERSON|MAIL|y finally pendin +5189|15881|884|2|38|68281.44|0.06|0.00|A|F|1994-03-26|1994-01-28|1994-04-20|DELIVER IN PERSON|REG AIR|ideas. idle, final deposits de +5189|109889|4910|3|4|7595.52|0.09|0.02|A|F|1993-12-21|1994-02-23|1994-01-09|DELIVER IN PERSON|REG AIR|. blithely exp +5189|93195|8214|4|49|58221.31|0.05|0.01|R|F|1994-01-22|1994-01-19|1994-02-04|TAKE BACK RETURN|SHIP| requests +5189|122046|7071|5|14|14952.56|0.02|0.03|A|F|1994-01-23|1994-01-05|1994-02-12|DELIVER IN PERSON|REG AIR|unusual packag +5189|16138|6139|6|41|43219.33|0.02|0.06|R|F|1993-12-12|1994-02-05|1994-01-09|DELIVER IN PERSON|RAIL|ial theodolites cajole slyly. slyly unus +5190|55509|520|1|43|62973.50|0.09|0.06|A|F|1992-08-19|1992-06-10|1992-09-01|DELIVER IN PERSON|FOB|encies use fluffily unusual requests? hoc +5190|131308|6335|2|6|8035.80|0.10|0.08|A|F|1992-08-08|1992-07-14|1992-08-22|COLLECT COD|RAIL|furiously regular pinto beans. furiously i +5190|88403|3420|3|45|62613.00|0.04|0.03|A|F|1992-07-23|1992-06-16|1992-08-04|NONE|FOB|y carefully final ideas. f +5191|114713|4714|1|41|70836.11|0.00|0.08|A|F|1995-02-05|1995-02-27|1995-02-15|DELIVER IN PERSON|AIR|uests! ironic theodolites cajole care +5191|167719|236|2|40|71468.40|0.02|0.01|A|F|1995-03-31|1995-02-21|1995-04-02|NONE|AIR|nes haggle sometimes. requests eng +5191|42244|2245|3|27|32028.48|0.07|0.05|A|F|1994-12-26|1995-01-24|1995-01-14|DELIVER IN PERSON|RAIL|tructions nag bravely within the re +5191|182828|383|4|7|13375.74|0.01|0.04|A|F|1995-03-24|1995-01-30|1995-03-30|NONE|RAIL|eposits. express +5216|68007|8008|1|17|16575.00|0.04|0.06|N|O|1997-08-20|1997-11-07|1997-09-14|COLLECT COD|FOB|s according to the accounts bo +5217|79528|9529|1|50|75376.00|0.05|0.02|N|O|1995-12-26|1995-11-21|1996-01-24|DELIVER IN PERSON|MAIL|s. express, express accounts c +5217|15345|5346|2|23|28987.82|0.06|0.07|N|O|1996-01-18|1995-12-24|1996-02-10|COLLECT COD|RAIL|ven ideas. requests amo +5217|101296|6317|3|23|29837.67|0.03|0.02|N|O|1995-11-15|1995-12-17|1995-11-27|DELIVER IN PERSON|FOB|pending packages cajole ne +5217|80311|2820|4|47|60691.57|0.04|0.00|N|O|1995-11-24|1995-12-25|1995-11-25|COLLECT COD|AIR|ronic packages i +5218|82747|272|1|43|74378.82|0.05|0.04|A|F|1992-08-04|1992-09-12|1992-08-17|DELIVER IN PERSON|SHIP|k theodolites. express, even id +5218|124729|9754|2|33|57872.76|0.06|0.01|R|F|1992-09-16|1992-09-30|1992-09-27|NONE|TRUCK|ronic instructi +5219|134892|4893|1|2|3853.78|0.08|0.00|N|O|1997-06-26|1997-04-29|1997-07-08|TAKE BACK RETURN|FOB| blithely according to the stea +5219|118635|6169|2|20|33072.60|0.05|0.00|N|O|1997-04-20|1997-05-26|1997-05-13|COLLECT COD|FOB|e along the ironic, +5220|82721|7738|1|27|46000.44|0.10|0.04|R|F|1992-09-21|1992-08-29|1992-10-16|DELIVER IN PERSON|RAIL|s cajole blithely furiously iron +5221|103446|8467|1|24|34786.56|0.07|0.03|N|O|1995-10-04|1995-08-11|1995-10-30|COLLECT COD|REG AIR|s pinto beans sleep. sly +5221|8710|8711|2|34|55036.14|0.01|0.05|N|O|1995-09-11|1995-07-17|1995-10-10|COLLECT COD|SHIP|eans. furio +5221|179197|1715|3|16|20419.04|0.04|0.01|N|O|1995-08-29|1995-09-06|1995-09-12|TAKE BACK RETURN|TRUCK|ending request +5222|150471|8017|1|1|1521.47|0.00|0.00|A|F|1994-08-19|1994-07-16|1994-09-08|TAKE BACK RETURN|FOB|idle requests. carefully pending pinto bean +5223|44573|2086|1|24|36421.68|0.00|0.00|A|F|1994-10-03|1994-09-20|1994-10-11|TAKE BACK RETURN|TRUCK|refully bold courts besides the regular, +5223|123366|5879|2|25|34734.00|0.09|0.02|R|F|1994-07-12|1994-08-13|1994-08-01|NONE|FOB|y express ideas impress +5223|5732|3233|3|19|31116.87|0.04|0.01|R|F|1994-10-28|1994-08-26|1994-10-31|COLLECT COD|REG AIR|ntly. furiously even excuses a +5223|129873|4898|4|40|76114.80|0.01|0.04|R|F|1994-10-01|1994-09-18|1994-10-28|COLLECT COD|SHIP|kly pending +5248|80249|7774|1|39|47940.36|0.05|0.03|N|O|1995-08-10|1995-07-04|1995-09-09|TAKE BACK RETURN|MAIL|yly even accounts. spe +5248|137103|2130|2|45|51304.50|0.00|0.06|A|F|1995-05-09|1995-07-12|1995-05-27|DELIVER IN PERSON|FOB|. bold, pending foxes h +5249|49720|7233|1|31|51761.32|0.07|0.03|A|F|1994-11-21|1994-11-19|1994-12-08|NONE|REG AIR|f the excuses. furiously fin +5249|30026|2530|2|44|42064.88|0.05|0.00|A|F|1994-12-28|1994-11-29|1994-12-29|TAKE BACK RETURN|MAIL|ole furiousl +5249|31770|4274|3|13|22123.01|0.09|0.00|R|F|1994-09-27|1994-10-20|1994-10-05|DELIVER IN PERSON|SHIP|ites. finally exp +5249|145318|7833|4|29|39535.99|0.00|0.05|A|F|1994-09-16|1994-11-03|1994-10-06|NONE|TRUCK| players. f +5249|157742|258|5|12|21596.88|0.01|0.08|R|F|1994-12-28|1994-11-07|1995-01-15|COLLECT COD|MAIL|press depths could have to sleep carefu +5250|43529|1042|1|2|2945.04|0.08|0.04|N|O|1995-08-09|1995-10-10|1995-08-13|COLLECT COD|AIR|its. final pinto +5250|191534|9092|2|27|43889.31|0.10|0.05|N|O|1995-10-24|1995-09-03|1995-11-18|COLLECT COD|TRUCK|l forges are. furiously unusual pin +5251|138965|3992|1|36|72142.56|0.10|0.01|N|O|1995-07-16|1995-07-05|1995-07-28|DELIVER IN PERSON|FOB|slowly! bli +5252|140986|8529|1|13|26350.74|0.02|0.01|N|O|1996-03-02|1996-05-10|1996-03-11|NONE|FOB|boost fluffily across +5252|138978|1492|2|39|78661.83|0.06|0.05|N|O|1996-05-17|1996-04-23|1996-05-23|COLLECT COD|AIR|gular requests. +5252|194020|1578|3|9|10026.18|0.09|0.03|N|O|1996-05-30|1996-05-03|1996-06-26|TAKE BACK RETURN|RAIL|x. slyly special depos +5252|86576|1593|4|48|75003.36|0.01|0.06|N|O|1996-04-17|1996-03-19|1996-05-03|COLLECT COD|AIR|bold requests. furious +5252|67746|2759|5|24|41129.76|0.04|0.05|N|O|1996-05-11|1996-04-17|1996-05-12|COLLECT COD|REG AIR|posits after the fluffi +5252|2202|9703|6|41|45272.20|0.02|0.03|N|O|1996-03-16|1996-04-18|1996-03-17|NONE|TRUCK|ording to the blithely express somas sho +5253|30616|5623|1|35|54131.35|0.02|0.00|N|O|1995-07-23|1995-06-12|1995-08-03|DELIVER IN PERSON|AIR|ven deposits. careful +5253|149475|1990|2|38|57929.86|0.02|0.06|N|O|1995-08-03|1995-06-14|1995-08-27|DELIVER IN PERSON|REG AIR|onic dependencies are furiou +5253|13981|3982|3|9|17054.82|0.03|0.08|N|F|1995-06-08|1995-05-12|1995-06-23|DELIVER IN PERSON|REG AIR|lyly express deposits use furiou +5253|165076|2625|4|25|28526.75|0.04|0.03|A|F|1995-05-21|1995-06-13|1995-06-09|COLLECT COD|TRUCK|urts. even theodoli +5254|110141|142|1|35|40289.90|0.01|0.07|A|F|1992-07-28|1992-09-05|1992-08-07|COLLECT COD|REG AIR|ntegrate carefully among the pending +5254|134265|9292|2|10|12992.60|0.05|0.04|A|F|1992-11-19|1992-10-20|1992-12-15|COLLECT COD|SHIP| accounts. silent deposit +5254|191752|6791|3|32|59000.00|0.00|0.08|A|F|1992-08-10|1992-09-21|1992-08-16|NONE|RAIL|ts impress closely furi +5254|162208|4725|4|45|57159.00|0.05|0.06|A|F|1992-11-11|1992-09-01|1992-12-07|COLLECT COD|REG AIR| wake. blithely silent excuse +5254|28653|3658|5|23|36377.95|0.02|0.06|A|F|1992-08-16|1992-09-05|1992-09-15|COLLECT COD|RAIL|lyly regular accounts. furiously pendin +5254|157626|2657|6|34|57243.08|0.09|0.02|R|F|1992-08-29|1992-10-16|1992-09-20|TAKE BACK RETURN|RAIL| furiously above the furiously +5254|19583|4586|7|9|13523.22|0.09|0.03|R|F|1992-07-29|1992-10-15|1992-08-20|TAKE BACK RETURN|REG AIR| wake blithely fluff +5255|130706|8246|1|2|3473.40|0.04|0.08|N|O|1996-09-27|1996-10-04|1996-10-04|DELIVER IN PERSON|RAIL|ajole blithely fluf +5255|171139|8691|2|30|36303.90|0.04|0.08|N|O|1996-09-20|1996-08-18|1996-10-09|TAKE BACK RETURN|AIR| to the silent requests cajole b +5255|129900|7437|3|41|79125.90|0.09|0.03|N|O|1996-08-21|1996-09-24|1996-09-05|COLLECT COD|FOB|tect blithely against t +5280|96078|8588|1|16|17185.12|0.02|0.03|N|O|1998-03-29|1998-01-28|1998-04-03|TAKE BACK RETURN|SHIP| foxes are furiously. theodoli +5280|175550|585|2|46|74775.30|0.01|0.06|N|O|1998-01-04|1998-01-21|1998-02-03|TAKE BACK RETURN|FOB|efully carefully pen +5281|113555|8578|1|37|58036.35|0.05|0.02|N|O|1995-11-10|1996-01-31|1995-11-22|DELIVER IN PERSON|MAIL|ronic dependencies. fluffily final p +5281|104572|2103|2|38|59909.66|0.00|0.05|N|O|1996-02-17|1995-12-19|1996-02-29|NONE|RAIL|n asymptotes could wake about th +5281|126120|8633|3|23|26360.76|0.08|0.00|N|O|1995-12-30|1996-01-26|1996-01-23|COLLECT COD|REG AIR|. final theodolites cajole. ironic p +5281|86431|1448|4|48|68036.64|0.03|0.05|N|O|1996-01-31|1995-12-23|1996-02-08|TAKE BACK RETURN|REG AIR|ss the furiously +5281|42872|5377|5|33|59890.71|0.01|0.07|N|O|1996-03-01|1995-12-28|1996-03-05|COLLECT COD|RAIL|ly brave foxes. bold deposits above the +5282|117371|9883|1|36|49981.32|0.05|0.02|N|O|1998-05-20|1998-04-10|1998-06-14|DELIVER IN PERSON|TRUCK|re slyly accor +5282|51792|4298|2|32|55801.28|0.02|0.05|N|O|1998-03-01|1998-03-31|1998-03-03|NONE|FOB|onic deposits; furiou +5282|57236|4752|3|28|33410.44|0.03|0.06|N|O|1998-05-06|1998-04-24|1998-05-30|COLLECT COD|SHIP|fily final instruc +5283|4165|1666|1|20|21383.20|0.05|0.02|A|F|1994-09-16|1994-08-03|1994-10-15|TAKE BACK RETURN|TRUCK|al deposits? blithely even pinto beans +5283|185925|8444|2|1|2010.92|0.10|0.08|R|F|1994-06-20|1994-08-03|1994-07-01|COLLECT COD|FOB|deposits within the furio +5284|172419|9971|1|16|23862.56|0.04|0.02|N|O|1995-08-17|1995-08-23|1995-08-26|DELIVER IN PERSON|TRUCK|unts detect furiously even d +5284|43086|8095|2|24|24697.92|0.03|0.08|N|O|1995-10-21|1995-08-23|1995-10-27|COLLECT COD|AIR| haggle according +5285|192958|5478|1|31|63579.45|0.08|0.00|A|F|1994-04-17|1994-04-05|1994-05-09|NONE|RAIL|ubt. quickly blithe +5285|30061|5068|2|37|36669.22|0.09|0.02|R|F|1994-02-26|1994-02-18|1994-03-27|NONE|SHIP|uffily regu +5285|33846|1356|3|24|42716.16|0.02|0.04|A|F|1994-04-19|1994-04-03|1994-04-25|DELIVER IN PERSON|FOB|ess packages. quick, even deposits snooze b +5285|42130|9643|4|12|12865.56|0.05|0.06|A|F|1994-04-22|1994-04-07|1994-05-19|NONE|AIR| deposits-- quickly bold requests hag +5285|70694|695|5|1|1664.69|0.03|0.05|R|F|1994-03-14|1994-02-20|1994-04-10|COLLECT COD|TRUCK|e fluffily about the slyly special pa +5285|145672|5673|6|1|1717.67|0.06|0.01|R|F|1994-02-08|1994-04-02|1994-02-17|COLLECT COD|SHIP|ing deposits integra +5286|198566|1086|1|1|1664.56|0.01|0.07|N|O|1997-11-25|1997-11-07|1997-12-17|COLLECT COD|REG AIR|ly! furiously final pack +5286|96223|3751|2|7|8534.54|0.06|0.05|N|O|1997-10-23|1997-12-10|1997-11-20|TAKE BACK RETURN|RAIL|y express instructions sleep carefull +5286|15473|7975|3|3|4165.41|0.06|0.08|N|O|1997-12-04|1997-11-06|1997-12-09|COLLECT COD|MAIL|re fluffily +5286|39019|1523|4|6|5748.06|0.04|0.03|N|O|1997-10-15|1997-12-05|1997-11-12|COLLECT COD|RAIL|y special a +5286|185301|5302|5|38|52679.40|0.07|0.05|N|O|1997-11-29|1997-11-26|1997-12-15|TAKE BACK RETURN|SHIP|fluffily. special, ironic deposit +5286|137943|7944|6|24|47542.56|0.08|0.00|N|O|1997-09-27|1997-12-21|1997-09-30|COLLECT COD|TRUCK|s. express foxes of the +5287|38269|3276|1|32|38632.32|0.01|0.01|A|F|1994-01-29|1994-01-27|1994-02-08|NONE|RAIL|heodolites haggle caref +5312|60844|8363|1|27|48730.68|0.04|0.08|A|F|1995-04-20|1995-04-09|1995-04-25|COLLECT COD|SHIP|tructions cajol +5312|1004|3505|2|43|38915.00|0.05|0.08|A|F|1995-03-24|1995-05-07|1995-03-28|NONE|TRUCK|ly unusual +5313|16090|8592|1|34|34207.06|0.10|0.02|N|O|1997-08-07|1997-08-12|1997-08-24|DELIVER IN PERSON|FOB|ccording to the blithely final account +5313|12109|7112|2|17|17358.70|0.00|0.02|N|O|1997-09-02|1997-08-20|1997-09-07|NONE|SHIP|uests wake +5313|111704|6727|3|47|80637.90|0.06|0.08|N|O|1997-08-12|1997-08-18|1997-08-13|TAKE BACK RETURN|RAIL|pinto beans across the +5313|196554|4112|4|16|26408.80|0.08|0.00|N|O|1997-10-04|1997-08-02|1997-10-25|COLLECT COD|REG AIR|ckages wake carefully aga +5313|71942|6957|5|30|57418.20|0.06|0.08|N|O|1997-06-27|1997-07-18|1997-06-30|NONE|SHIP|nding packages use +5313|119930|4953|6|21|40948.53|0.05|0.05|N|O|1997-09-26|1997-09-02|1997-10-18|COLLECT COD|FOB|he blithely regular packages. quickly +5314|117209|7210|1|10|12262.00|0.07|0.05|N|O|1995-09-26|1995-07-24|1995-10-19|DELIVER IN PERSON|RAIL|latelets haggle final +5314|124781|4782|2|16|28892.48|0.00|0.04|N|O|1995-09-25|1995-07-08|1995-10-17|COLLECT COD|SHIP|hely unusual packages acc +5315|34544|2054|1|12|17742.48|0.08|0.06|R|F|1992-12-18|1993-01-16|1993-01-10|NONE|AIR|ccounts. furiously ironi +5315|178618|8619|2|39|66167.79|0.00|0.06|R|F|1992-11-09|1992-12-29|1992-12-07|NONE|SHIP|ly alongside of the ca +5316|107714|225|1|29|49929.59|0.10|0.05|R|F|1994-03-28|1994-04-29|1994-04-09|DELIVER IN PERSON|REG AIR|ckly unusual foxes bo +5316|135125|5126|2|31|35963.72|0.00|0.08|A|F|1994-04-01|1994-04-21|1994-04-12|DELIVER IN PERSON|MAIL|s. deposits cajole around t +5317|81001|8526|1|29|28478.00|0.02|0.06|A|F|1994-11-28|1994-11-27|1994-12-16|COLLECT COD|FOB|oss the carefull +5317|170294|295|2|18|24557.22|0.06|0.06|A|F|1995-01-02|1994-10-29|1995-01-16|NONE|RAIL|g to the blithely p +5317|119181|1693|3|37|44406.66|0.09|0.00|R|F|1994-09-15|1994-10-24|1994-09-23|NONE|TRUCK|totes nag theodolites. pend +5317|66431|8938|4|50|69871.50|0.09|0.01|A|F|1994-10-17|1994-10-25|1994-11-03|NONE|REG AIR|cajole furiously. accounts use quick +5317|94765|9784|5|19|33435.44|0.07|0.07|R|F|1994-12-15|1994-10-18|1994-12-27|NONE|MAIL|onic requests boost bli +5317|114725|7237|6|48|83506.56|0.01|0.03|A|F|1994-09-19|1994-11-25|1994-10-03|COLLECT COD|MAIL|ts about the packages cajole furio +5317|168493|6042|7|30|46844.70|0.07|0.07|A|F|1994-10-13|1994-10-31|1994-10-28|NONE|AIR|cross the attainments. slyly +5318|60046|7565|1|13|13078.52|0.10|0.04|R|F|1993-07-15|1993-06-25|1993-08-13|COLLECT COD|REG AIR|ly silent ideas. ideas haggle among the +5318|179521|9522|2|26|41613.52|0.00|0.04|R|F|1993-07-07|1993-05-23|1993-07-28|COLLECT COD|SHIP|al, express foxes. bold requests sleep alwa +5318|6173|8674|3|37|39929.29|0.07|0.05|A|F|1993-07-09|1993-06-22|1993-07-21|COLLECT COD|SHIP|ickly final deposi +5318|141228|6257|4|31|39345.82|0.01|0.04|R|F|1993-07-28|1993-05-06|1993-08-06|DELIVER IN PERSON|REG AIR|requests must sleep slyly quickly +5319|149703|7246|1|31|54333.70|0.04|0.07|N|O|1996-03-26|1996-03-07|1996-04-24|COLLECT COD|TRUCK|d carefully about the courts. fluffily spe +5319|43282|795|2|39|47785.92|0.09|0.05|N|O|1996-05-17|1996-03-14|1996-06-11|NONE|TRUCK|unts. furiously silent +5344|18176|678|1|6|6565.02|0.07|0.01|N|O|1998-08-04|1998-09-03|1998-08-11|TAKE BACK RETURN|REG AIR|ithely about the pending plate +5344|78150|658|2|37|41741.55|0.03|0.07|N|O|1998-10-09|1998-07-26|1998-11-08|NONE|TRUCK|thely express packages +5344|66249|6250|3|26|31596.24|0.02|0.06|N|O|1998-08-27|1998-08-22|1998-09-24|NONE|AIR|furiously pending, silent multipliers. +5344|38164|3171|4|21|23145.36|0.03|0.01|N|O|1998-08-31|1998-09-06|1998-09-02|NONE|MAIL|xes. furiously even pinto beans sleep f +5345|82522|5031|1|3|4513.56|0.05|0.01|N|O|1997-12-10|1997-10-03|1998-01-05|COLLECT COD|SHIP|ites wake carefully unusual +5345|145618|3161|2|2|3327.22|0.10|0.02|N|O|1997-11-18|1997-10-12|1997-12-08|NONE|MAIL|ut the slyly specia +5345|191094|6133|3|46|54514.14|0.06|0.04|N|O|1997-10-06|1997-09-27|1997-10-18|COLLECT COD|REG AIR|slyly special deposits. fin +5345|113634|1168|4|37|60962.31|0.01|0.01|N|O|1997-11-01|1997-10-09|1997-11-26|DELIVER IN PERSON|AIR| along the ironically fina +5345|33600|6104|5|22|33739.20|0.02|0.02|N|O|1997-08-27|1997-11-22|1997-09-10|TAKE BACK RETURN|MAIL|leep slyly regular fox +5346|148105|5648|1|21|24215.10|0.07|0.08|R|F|1994-03-11|1994-03-07|1994-04-04|DELIVER IN PERSON|RAIL|integrate blithely a +5346|191665|6704|2|13|22836.58|0.04|0.04|A|F|1994-02-03|1994-02-05|1994-02-09|COLLECT COD|TRUCK|y. fluffily bold accounts grow. furio +5346|108881|1392|3|7|13229.16|0.08|0.05|A|F|1994-01-30|1994-03-26|1994-01-31|DELIVER IN PERSON|SHIP|equests use carefully care +5346|161238|1239|4|35|45473.05|0.06|0.02|A|F|1994-02-09|1994-03-01|1994-02-14|TAKE BACK RETURN|FOB|nic excuses cajole entic +5346|120595|596|5|25|40389.75|0.05|0.06|R|F|1993-12-28|1994-03-19|1994-01-09|TAKE BACK RETURN|REG AIR|he ironic ideas are boldly slyly ironi +5346|32956|466|6|6|11333.70|0.08|0.04|R|F|1994-03-01|1994-02-04|1994-03-09|NONE|REG AIR|escapades sleep furiously beside the +5346|79234|4249|7|41|49742.43|0.05|0.04|R|F|1994-01-10|1994-02-15|1994-01-26|TAKE BACK RETURN|REG AIR|fully close instructi +5347|82283|7300|1|48|60733.44|0.04|0.08|A|F|1995-02-25|1995-04-26|1995-03-26|NONE|SHIP|equests are slyly. blithely regu +5347|123439|8464|2|47|68734.21|0.02|0.01|N|F|1995-06-05|1995-03-29|1995-06-28|COLLECT COD|AIR|across the slyly bol +5347|22862|7867|3|34|60685.24|0.06|0.00|A|F|1995-05-18|1995-04-04|1995-06-02|DELIVER IN PERSON|SHIP| pending deposits. fluffily regular senti +5347|39456|9457|4|4|5581.80|0.06|0.03|A|F|1995-03-24|1995-04-03|1995-04-01|NONE|SHIP|ldly pending asymptotes ki +5347|130711|5738|5|21|36575.91|0.08|0.04|R|F|1995-04-01|1995-04-16|1995-04-23|NONE|SHIP|sly slyly final requests. careful +5347|55468|479|6|6|8540.76|0.06|0.02|A|F|1995-04-11|1995-04-14|1995-05-02|NONE|TRUCK|lly unusual ideas. sl +5347|49567|2072|7|18|27298.08|0.01|0.01|N|F|1995-05-24|1995-05-07|1995-06-19|NONE|FOB|he ideas among the requests +5348|68446|5965|1|21|29703.24|0.10|0.04|N|O|1997-12-11|1997-12-24|1997-12-28|NONE|REG AIR| regular theodolites haggle car +5348|155865|896|2|31|59546.66|0.07|0.02|N|O|1998-01-04|1997-12-09|1998-01-17|COLLECT COD|RAIL|are finally +5348|16638|6639|3|16|24874.08|0.06|0.08|N|O|1998-02-28|1997-12-25|1998-03-12|DELIVER IN PERSON|AIR|uriously thin pinto beans +5348|19183|1685|4|7|7715.26|0.04|0.00|N|O|1998-01-29|1997-12-20|1998-02-10|DELIVER IN PERSON|RAIL|even foxes. epitap +5348|1818|4319|5|37|63632.97|0.06|0.07|N|O|1997-12-01|1998-02-02|1997-12-07|NONE|FOB|y according to the carefully pending acco +5348|142875|5390|6|14|26850.18|0.06|0.05|N|O|1997-12-16|1998-01-12|1997-12-24|COLLECT COD|FOB|en pinto beans. somas cajo +5349|155065|5066|1|19|21281.14|0.06|0.01|N|O|1996-09-11|1996-11-18|1996-09-22|TAKE BACK RETURN|FOB|endencies use whithout the special +5349|167110|4659|2|14|16479.54|0.06|0.00|N|O|1996-11-07|1996-11-17|1996-11-20|TAKE BACK RETURN|TRUCK|fully regular +5349|3482|3483|3|6|8312.88|0.10|0.01|N|O|1996-12-30|1996-10-08|1997-01-01|DELIVER IN PERSON|MAIL|inal deposits affix carefully +5350|121045|1046|1|19|20254.76|0.02|0.06|R|F|1993-10-20|1993-11-15|1993-11-17|DELIVER IN PERSON|RAIL|romise slyly alongsi +5350|190829|5868|2|44|84472.08|0.04|0.06|R|F|1993-10-30|1993-11-23|1993-11-25|DELIVER IN PERSON|AIR|p above the ironic, pending dep +5350|53095|8106|3|12|12577.08|0.10|0.04|A|F|1994-01-30|1993-11-21|1994-02-15|COLLECT COD|REG AIR| cajole. even instructions haggle. blithe +5350|154932|9963|4|7|13908.51|0.08|0.00|R|F|1993-10-19|1993-12-28|1993-11-04|NONE|SHIP|alongside of th +5350|128746|8747|5|27|47917.98|0.07|0.04|A|F|1993-11-25|1993-12-27|1993-12-08|COLLECT COD|TRUCK|es. blithe theodolites haggl +5351|6095|1096|1|36|36039.24|0.06|0.05|N|O|1998-07-27|1998-07-06|1998-08-25|NONE|MAIL|ss the ironic, regular asymptotes cajole +5351|32041|4545|2|47|45732.88|0.04|0.01|N|O|1998-05-30|1998-08-08|1998-06-23|DELIVER IN PERSON|REG AIR|s. grouches cajole. sile +5351|105327|2858|3|2|2664.64|0.00|0.02|N|O|1998-05-12|1998-07-15|1998-05-24|NONE|TRUCK|g accounts wake furiously slyly even dolph +5376|60778|8297|1|42|73028.34|0.10|0.04|A|F|1994-09-20|1994-08-30|1994-09-29|TAKE BACK RETURN|REG AIR|y even asymptotes. courts are unusual pa +5376|90990|6009|2|44|87163.56|0.05|0.02|R|F|1994-08-30|1994-08-05|1994-09-07|COLLECT COD|AIR|ithe packages detect final theodolites. f +5376|64871|4872|3|18|33045.66|0.02|0.08|A|F|1994-10-29|1994-09-13|1994-11-01|COLLECT COD|MAIL| accounts boo +5377|78172|3187|1|40|46006.80|0.00|0.04|N|O|1997-05-21|1997-06-15|1997-05-26|DELIVER IN PERSON|AIR|lithely ironic theodolites are care +5377|29316|6823|2|17|21170.27|0.09|0.00|N|O|1997-07-05|1997-05-25|1997-07-22|COLLECT COD|RAIL|dencies. carefully regular re +5377|102464|7485|3|23|33728.58|0.07|0.08|N|O|1997-06-26|1997-07-13|1997-07-08|COLLECT COD|RAIL| silent wa +5377|103123|5634|4|12|13513.44|0.05|0.07|N|O|1997-05-08|1997-06-15|1997-05-15|DELIVER IN PERSON|MAIL| ironic, final +5377|172292|4810|5|27|36835.83|0.08|0.02|N|O|1997-07-11|1997-06-12|1997-08-08|TAKE BACK RETURN|MAIL|press theodolites. e +5378|154773|7289|1|39|71283.03|0.07|0.04|R|F|1992-11-25|1992-12-22|1992-12-02|COLLECT COD|AIR|ts are quickly around the +5378|61083|6096|2|46|48027.68|0.01|0.04|A|F|1993-02-17|1993-01-20|1993-02-26|COLLECT COD|REG AIR|into beans sleep. fu +5378|9760|7261|3|18|30055.68|0.02|0.03|R|F|1992-11-25|1992-12-21|1992-12-10|COLLECT COD|FOB|onic accounts was bold, +5379|198787|1307|1|40|75431.20|0.01|0.08|N|O|1995-10-01|1995-10-19|1995-10-30|COLLECT COD|MAIL|carefully final accounts haggle blithely. +5380|181291|1292|1|14|19212.06|0.10|0.01|N|O|1997-12-18|1997-12-03|1998-01-06|NONE|RAIL|final platelets. +5380|146343|3886|2|10|13893.40|0.09|0.05|N|O|1997-11-24|1998-01-10|1997-12-21|COLLECT COD|AIR|refully pending deposits. special, even t +5380|183714|6233|3|40|71908.40|0.02|0.08|N|O|1997-12-30|1997-11-27|1998-01-09|DELIVER IN PERSON|SHIP|ar asymptotes. blithely r +5380|65789|802|4|6|10528.68|0.09|0.05|N|O|1997-11-15|1998-01-08|1997-12-11|COLLECT COD|MAIL|es. fluffily brave accounts across t +5380|106753|6754|5|48|84468.00|0.04|0.03|N|O|1997-12-01|1997-12-28|1997-12-05|DELIVER IN PERSON|FOB|encies haggle car +5381|187310|9829|1|37|51700.47|0.04|0.01|A|F|1993-04-08|1993-04-07|1993-04-12|DELIVER IN PERSON|SHIP|ly final deposits print carefully. unusua +5381|110002|5025|2|48|48576.00|0.04|0.03|R|F|1993-04-22|1993-04-17|1993-05-14|TAKE BACK RETURN|FOB|luffily spec +5381|191097|1098|3|13|15445.17|0.08|0.03|R|F|1993-05-09|1993-04-26|1993-05-25|NONE|FOB|s after the f +5381|167208|4757|4|17|21678.40|0.05|0.05|R|F|1993-05-25|1993-04-14|1993-06-17|NONE|MAIL|ckly final requests haggle qui +5381|62375|9894|5|49|65531.13|0.06|0.02|R|F|1993-05-08|1993-04-07|1993-06-03|NONE|FOB| accounts. regular, regula +5381|131056|6083|6|33|35872.65|0.10|0.00|A|F|1993-04-09|1993-04-03|1993-04-22|DELIVER IN PERSON|SHIP|ly special deposits +5381|43349|862|7|31|40062.54|0.04|0.05|A|F|1993-04-10|1993-03-22|1993-04-13|TAKE BACK RETURN|MAIL|the carefully expre +5382|152952|7983|1|34|68168.30|0.03|0.03|R|F|1992-02-22|1992-02-18|1992-03-02|DELIVER IN PERSON|FOB|gular accounts. even accounts integrate +5382|54879|7385|2|13|23840.31|0.09|0.06|A|F|1992-01-16|1992-03-12|1992-02-06|NONE|MAIL|eodolites. final foxes +5382|148097|8098|3|3|3435.27|0.10|0.06|A|F|1992-03-22|1992-03-06|1992-04-19|TAKE BACK RETURN|AIR|efully unusua +5382|61771|6784|4|20|34655.40|0.08|0.02|A|F|1992-03-26|1992-02-17|1992-04-15|DELIVER IN PERSON|FOB|carefully regular accounts. slyly ev +5382|176212|6213|5|14|18034.94|0.02|0.02|A|F|1992-04-05|1992-04-05|1992-05-04|TAKE BACK RETURN|FOB| brave platelets. ev +5382|179706|4741|6|6|10714.20|0.02|0.01|A|F|1992-03-07|1992-04-02|1992-03-18|TAKE BACK RETURN|FOB|y final foxes by the sl +5382|104356|1887|7|48|65296.80|0.05|0.05|A|F|1992-02-14|1992-03-19|1992-02-25|DELIVER IN PERSON|REG AIR|nts integrate quickly ca +5383|95116|5117|1|12|13333.32|0.04|0.00|N|O|1995-07-02|1995-08-16|1995-08-01|TAKE BACK RETURN|AIR|y regular instructi +5408|101941|6962|1|2|3885.88|0.07|0.04|R|F|1992-08-21|1992-10-03|1992-08-28|DELIVER IN PERSON|MAIL|cross the dolphins h +5408|117718|230|2|35|60749.85|0.04|0.05|R|F|1992-10-02|1992-10-17|1992-10-13|TAKE BACK RETURN|AIR|thely ironic requests alongside of the sl +5408|75127|7635|3|34|37472.08|0.10|0.02|A|F|1992-10-22|1992-08-25|1992-11-16|DELIVER IN PERSON|TRUCK|requests detect blithely a +5408|53108|5614|4|48|50932.80|0.04|0.05|R|F|1992-09-30|1992-08-27|1992-10-27|NONE|TRUCK|. furiously regular +5408|182529|7566|5|8|12892.16|0.03|0.07|A|F|1992-10-24|1992-09-06|1992-11-03|NONE|AIR|thely regular hocke +5409|193319|877|1|27|38132.37|0.01|0.02|A|F|1992-02-14|1992-03-18|1992-02-23|DELIVER IN PERSON|AIR|eodolites +5409|103573|3574|2|38|59909.66|0.01|0.02|A|F|1992-03-17|1992-03-29|1992-04-13|NONE|REG AIR|onic, regular accounts! blithely even +5409|140347|7890|3|17|23584.78|0.07|0.00|A|F|1992-01-13|1992-04-05|1992-01-20|DELIVER IN PERSON|AIR|cross the sil +5409|403|7904|4|9|11730.60|0.07|0.03|A|F|1992-02-15|1992-04-02|1992-02-28|DELIVER IN PERSON|AIR| unusual, unusual reques +5409|158141|8142|5|37|44368.18|0.06|0.04|R|F|1992-05-07|1992-02-10|1992-05-20|DELIVER IN PERSON|FOB|ously regular packages. packages +5409|63902|6409|6|14|26122.60|0.03|0.08|R|F|1992-02-14|1992-03-26|1992-02-29|DELIVER IN PERSON|AIR|osits cajole furiously +5410|116768|6769|1|48|85668.48|0.04|0.08|N|O|1998-09-27|1998-09-11|1998-10-01|TAKE BACK RETURN|AIR| about the slyly even courts. quickly regul +5410|104411|6922|2|41|58031.81|0.01|0.07|N|O|1998-08-25|1998-10-20|1998-09-01|DELIVER IN PERSON|REG AIR|sly. slyly ironic theodolites +5410|28027|530|3|40|38200.80|0.07|0.08|N|O|1998-11-17|1998-10-02|1998-11-27|COLLECT COD|TRUCK|iously special accounts are along th +5410|49503|2008|4|8|11620.00|0.05|0.04|N|O|1998-09-12|1998-10-22|1998-09-22|DELIVER IN PERSON|TRUCK|ly. fluffily ironic platelets alon +5411|95432|451|1|17|24266.31|0.05|0.01|N|O|1997-07-22|1997-07-14|1997-07-30|TAKE BACK RETURN|REG AIR| slyly slyly even deposits. carefully b +5411|112029|4541|2|10|10410.20|0.08|0.01|N|O|1997-07-19|1997-08-04|1997-07-26|TAKE BACK RETURN|MAIL|nding, special foxes unw +5411|55057|5058|3|5|5060.25|0.10|0.01|N|O|1997-09-12|1997-08-03|1997-09-23|DELIVER IN PERSON|FOB| bold, ironic theodo +5411|128590|3615|4|15|24278.85|0.08|0.05|N|O|1997-07-01|1997-07-15|1997-07-07|COLLECT COD|RAIL|attainments sleep slyly ironic +5411|3016|3017|5|19|17461.19|0.05|0.08|N|O|1997-05-25|1997-07-30|1997-06-19|COLLECT COD|RAIL|ial accounts according to the f +5412|53078|8089|1|2|2062.14|0.03|0.07|N|O|1998-04-14|1998-04-02|1998-04-19|TAKE BACK RETURN|REG AIR| sleep above the furiou +5412|65168|2687|2|48|54391.68|0.01|0.08|N|O|1998-02-22|1998-03-28|1998-03-18|TAKE BACK RETURN|TRUCK|s. slyly final packages cajole blithe +5412|73678|1200|3|31|51201.77|0.05|0.08|N|O|1998-03-23|1998-04-17|1998-04-10|NONE|SHIP|t the accounts detect slyly about the c +5412|96319|1338|4|26|34198.06|0.02|0.08|N|O|1998-01-22|1998-04-19|1998-02-17|NONE|AIR| the blithel +5413|125457|5458|1|48|71157.60|0.02|0.08|N|O|1998-01-25|1997-11-20|1998-02-22|COLLECT COD|SHIP| theodolites. furiously ironic instr +5413|141805|4320|2|37|68331.60|0.02|0.07|N|O|1997-12-08|1998-01-01|1997-12-13|COLLECT COD|TRUCK|usly bold instructions affix idly unusual, +5413|110854|5877|3|36|67134.60|0.02|0.07|N|O|1997-12-12|1997-11-28|1997-12-25|NONE|TRUCK|ular, regular ideas mold! final requests +5413|109216|1727|4|22|26954.62|0.02|0.08|N|O|1997-11-10|1997-11-24|1997-11-22|DELIVER IN PERSON|FOB|posits. quick +5413|188636|6191|5|5|8623.15|0.10|0.01|N|O|1997-11-28|1997-11-24|1997-12-05|NONE|RAIL|tes are al +5413|189019|9020|6|32|35456.32|0.02|0.03|N|O|1997-10-28|1998-01-03|1997-11-10|NONE|TRUCK|refully special package +5413|30016|2520|7|32|30272.32|0.06|0.07|N|O|1997-10-23|1997-12-09|1997-11-17|NONE|TRUCK|he quickly ironic ideas. slyly ironic ide +5414|67051|7052|1|40|40722.00|0.07|0.06|R|F|1993-04-07|1993-05-18|1993-04-23|COLLECT COD|AIR|ts are evenly across +5414|122106|4619|2|48|54148.80|0.06|0.07|R|F|1993-06-08|1993-05-14|1993-07-06|DELIVER IN PERSON|FOB| silent dolphins; fluffily regular tithe +5414|34768|2278|3|23|39163.48|0.10|0.00|A|F|1993-07-22|1993-05-26|1993-08-08|COLLECT COD|MAIL|e bold, express dolphins. spec +5414|132077|2078|4|15|16636.05|0.06|0.08|R|F|1993-05-18|1993-06-09|1993-05-27|DELIVER IN PERSON|REG AIR|e slyly about the carefully regula +5414|8372|873|5|19|24327.03|0.01|0.05|R|F|1993-04-06|1993-05-12|1993-05-02|DELIVER IN PERSON|RAIL|ffily silent theodolites na +5414|97119|2138|6|28|31251.08|0.10|0.05|A|F|1993-03-27|1993-06-04|1993-04-07|TAKE BACK RETURN|SHIP|ts sleep sl +5415|101746|4257|1|44|76900.56|0.00|0.06|A|F|1992-08-19|1992-10-26|1992-09-17|TAKE BACK RETURN|TRUCK| requests. unusual theodolites sleep agains +5415|30220|7730|2|16|18403.52|0.08|0.00|A|F|1992-09-29|1992-09-12|1992-10-10|NONE|AIR|pinto beans haggle furiously +5415|101066|6087|3|6|6402.36|0.10|0.03|A|F|1992-10-28|1992-09-09|1992-11-20|COLLECT COD|RAIL|ges around the fur +5415|15099|5100|4|43|43605.87|0.01|0.02|R|F|1992-11-17|1992-09-14|1992-12-14|DELIVER IN PERSON|SHIP|yly blithely stealthy deposits. carefu +5415|160014|7563|5|11|11814.11|0.00|0.01|R|F|1992-11-22|1992-10-19|1992-12-10|DELIVER IN PERSON|SHIP|gle among t +5415|143712|6227|6|46|80762.66|0.03|0.03|R|F|1992-08-25|1992-09-10|1992-09-22|DELIVER IN PERSON|REG AIR|ve the fluffily +5415|152967|2968|7|11|22219.56|0.08|0.06|A|F|1992-08-21|1992-09-04|1992-08-23|NONE|TRUCK|unts maintain carefully unusual +5440|114100|9123|1|3|3342.30|0.02|0.08|N|O|1997-02-18|1997-02-28|1997-03-15|NONE|SHIP|y. accounts haggle along the blit +5441|163452|8485|1|3|4546.35|0.00|0.02|R|F|1994-08-12|1994-10-14|1994-09-01|TAKE BACK RETURN|REG AIR|are. unusual, +5441|130764|765|2|49|87943.24|0.02|0.03|A|F|1994-09-23|1994-09-22|1994-10-22|NONE|FOB|ording to the furio +5441|143016|559|3|33|34947.33|0.09|0.02|R|F|1994-10-09|1994-10-06|1994-10-30|DELIVER IN PERSON|TRUCK|ges. final instruction +5441|66124|1137|4|47|51235.64|0.07|0.08|R|F|1994-11-19|1994-10-16|1994-12-16|TAKE BACK RETURN|FOB|ounts wake slyly about the express instr +5442|41917|6926|1|16|29742.56|0.00|0.00|N|O|1998-04-12|1998-03-03|1998-05-04|TAKE BACK RETURN|RAIL|r packages. accounts haggle dependencies. f +5442|87111|4636|2|45|49414.95|0.08|0.01|N|O|1998-03-30|1998-02-24|1998-04-18|TAKE BACK RETURN|AIR|old slyly after +5442|60318|5331|3|12|15339.72|0.01|0.08|N|O|1998-04-15|1998-03-18|1998-05-05|DELIVER IN PERSON|TRUCK|fully final +5442|157234|7235|4|21|27115.83|0.07|0.06|N|O|1998-03-13|1998-02-19|1998-04-06|COLLECT COD|MAIL|ffily furiously ironic theodolites. furio +5442|15990|5991|5|25|47649.75|0.04|0.00|N|O|1998-03-29|1998-02-13|1998-04-13|TAKE BACK RETURN|REG AIR|ake furiously. slyly express th +5442|143507|1050|6|26|40313.00|0.08|0.07|N|O|1998-03-21|1998-03-21|1998-03-25|TAKE BACK RETURN|AIR|have to sleep furiously bold ideas. blith +5443|177288|7289|1|14|19113.92|0.02|0.00|N|O|1996-10-27|1996-11-11|1996-11-21|DELIVER IN PERSON|RAIL|s after the regular, regular deposits hag +5443|71326|1327|2|39|50595.48|0.03|0.07|N|O|1996-11-01|1996-11-30|1996-11-19|NONE|RAIL|gage carefully across the furiously +5443|159719|4750|3|25|44467.75|0.05|0.00|N|O|1996-12-07|1997-01-08|1997-01-05|NONE|FOB|use carefully above the pinto bea +5443|190188|5227|4|6|7669.08|0.05|0.02|N|O|1996-11-17|1996-12-03|1996-11-30|TAKE BACK RETURN|AIR|p fluffily foxe +5443|82716|5225|5|40|67948.40|0.03|0.03|N|O|1997-01-28|1996-12-10|1997-02-13|NONE|FOB|n courts. special re +5444|185509|3064|1|21|33484.50|0.01|0.07|A|F|1995-04-11|1995-04-25|1995-04-21|DELIVER IN PERSON|RAIL|ar packages haggle above th +5444|42182|7191|2|40|44967.20|0.05|0.08|N|O|1995-07-09|1995-04-25|1995-07-19|COLLECT COD|TRUCK|ously bold ideas. instructions wake slyl +5444|149858|7401|3|40|76314.00|0.08|0.01|A|F|1995-04-06|1995-05-08|1995-05-06|DELIVER IN PERSON|AIR| even packages. +5444|58950|3961|4|33|62995.35|0.05|0.04|N|O|1995-06-24|1995-04-24|1995-07-13|DELIVER IN PERSON|SHIP|ut the courts cajole blithely excuses +5444|170692|8244|5|21|37016.49|0.04|0.00|R|F|1995-05-05|1995-05-25|1995-05-29|TAKE BACK RETURN|REG AIR|aves serve sly +5444|19026|4029|6|21|19845.42|0.07|0.01|A|F|1995-03-30|1995-05-01|1995-03-31|COLLECT COD|AIR|furiously even theodolites. +5445|89126|4143|1|33|36798.96|0.08|0.07|A|F|1993-10-21|1993-10-14|1993-10-28|DELIVER IN PERSON|REG AIR|ests. final instructions +5445|130119|120|2|12|13789.32|0.09|0.08|R|F|1993-11-02|1993-09-05|1993-11-26|COLLECT COD|FOB| slyly pending pinto beans was slyly al +5445|102859|7880|3|46|85645.10|0.04|0.07|A|F|1993-10-06|1993-09-15|1993-10-28|DELIVER IN PERSON|RAIL|old depend +5445|148677|8678|4|10|17256.70|0.08|0.06|A|F|1993-09-16|1993-10-05|1993-10-01|NONE|TRUCK|ncies abou +5445|12496|7499|5|14|19718.86|0.00|0.02|R|F|1993-11-19|1993-10-18|1993-12-07|NONE|RAIL| requests. bravely i +5446|189366|4403|1|27|39294.72|0.05|0.07|R|F|1994-07-21|1994-08-25|1994-08-17|TAKE BACK RETURN|RAIL|ously across the quic +5447|98536|1046|1|31|47570.43|0.09|0.03|N|O|1996-07-14|1996-05-07|1996-07-17|COLLECT COD|SHIP| foxes sleep. blithely unusual accounts det +5472|58956|8957|1|27|51703.65|0.09|0.06|A|F|1993-08-04|1993-07-07|1993-09-03|COLLECT COD|TRUCK|fily pending attainments. unus +5472|67697|5216|2|28|46611.32|0.00|0.03|A|F|1993-07-28|1993-05-28|1993-08-11|TAKE BACK RETURN|FOB|ffily pendin +5472|177295|2330|3|45|61753.05|0.06|0.02|R|F|1993-06-05|1993-05-14|1993-06-10|NONE|TRUCK| idle packages. furi +5472|183690|8727|4|37|65626.53|0.07|0.05|R|F|1993-06-15|1993-07-03|1993-07-09|DELIVER IN PERSON|RAIL|egrate carefully dependencies. +5472|74051|4052|5|40|41002.00|0.02|0.05|A|F|1993-04-13|1993-07-04|1993-05-04|NONE|REG AIR|e requests detect furiously. ruthlessly un +5472|166920|4469|6|39|77489.88|0.02|0.03|R|F|1993-04-18|1993-07-10|1993-05-12|TAKE BACK RETURN|MAIL|uriously carefully +5472|14390|1894|7|1|1304.39|0.03|0.02|A|F|1993-04-14|1993-06-28|1993-04-16|NONE|RAIL|s use furiou +5473|47878|383|1|9|16432.83|0.03|0.07|R|F|1992-06-03|1992-05-30|1992-06-09|TAKE BACK RETURN|AIR| excuses sleep blithely! regular dep +5473|69115|9116|2|27|29270.97|0.01|0.03|A|F|1992-04-06|1992-04-26|1992-04-29|TAKE BACK RETURN|MAIL|the deposits. warthogs wake fur +5473|14473|1977|3|33|45786.51|0.09|0.00|R|F|1992-05-18|1992-06-10|1992-06-13|TAKE BACK RETURN|MAIL|efully above the even, +5474|183763|3764|1|38|70176.88|0.01|0.08|A|F|1992-07-15|1992-07-16|1992-07-20|NONE|REG AIR| slyly beneath +5474|93631|1159|2|10|16246.30|0.06|0.00|R|F|1992-08-08|1992-08-10|1992-08-24|TAKE BACK RETURN|TRUCK|pinto bean +5474|47831|2840|3|31|55143.73|0.00|0.08|R|F|1992-08-02|1992-07-12|1992-08-04|NONE|TRUCK|the furiously express ideas. speci +5474|89506|4523|4|46|68793.00|0.03|0.04|A|F|1992-06-07|1992-07-11|1992-06-22|NONE|TRUCK|nstructions. furio +5475|182422|9977|1|10|15044.20|0.09|0.08|N|O|1996-07-19|1996-08-22|1996-07-23|COLLECT COD|AIR|ding to the deposits wake fina +5476|47660|2669|1|13|20899.58|0.01|0.04|N|O|1997-12-27|1997-12-08|1997-12-29|COLLECT COD|TRUCK|iously special ac +5476|19679|2181|2|17|27177.39|0.10|0.01|N|O|1998-02-02|1998-01-28|1998-02-14|COLLECT COD|FOB|ng dependencies until the f +5477|79222|6744|1|20|24024.40|0.03|0.01|N|O|1998-03-21|1998-02-09|1998-04-07|TAKE BACK RETURN|SHIP|platelets about the ironic +5477|76155|8663|2|21|23754.15|0.03|0.00|N|O|1998-01-28|1998-02-15|1998-02-24|TAKE BACK RETURN|SHIP|blate slyly. silent +5477|133790|3791|3|31|56537.49|0.04|0.01|N|O|1998-01-11|1998-01-30|1998-02-04|DELIVER IN PERSON|MAIL| special Tiresias cajole furiously. pending +5477|192129|7168|4|16|19537.92|0.00|0.01|N|O|1998-03-07|1998-03-12|1998-04-06|COLLECT COD|RAIL|regular, s +5477|95742|761|5|23|39968.02|0.00|0.06|N|O|1998-01-04|1998-02-23|1998-01-24|NONE|REG AIR|telets wake blithely ab +5477|120319|2832|6|19|25446.89|0.10|0.03|N|O|1998-02-03|1998-01-30|1998-03-04|TAKE BACK RETURN|MAIL|ost carefully packages. +5478|7283|7284|1|39|46420.92|0.09|0.06|N|O|1996-08-19|1996-06-25|1996-09-08|DELIVER IN PERSON|SHIP|s. furiously +5478|1079|3580|2|47|46063.29|0.10|0.01|N|O|1996-08-15|1996-07-12|1996-08-31|NONE|RAIL| instructions; slyly even accounts hagg +5478|118847|1359|3|25|46646.00|0.09|0.07|N|O|1996-06-08|1996-07-12|1996-07-07|NONE|TRUCK|unusual, pending requests haggle accoun +5479|137771|285|1|50|90438.50|0.02|0.02|A|F|1993-12-24|1994-02-14|1994-01-18|DELIVER IN PERSON|MAIL|ironic gifts. even dependencies sno +5479|103906|3907|2|19|36288.10|0.05|0.03|A|F|1994-01-22|1994-03-07|1994-02-11|DELIVER IN PERSON|SHIP|arefully bo +5504|67102|2115|1|4|4276.40|0.10|0.07|A|F|1993-04-30|1993-03-01|1993-05-22|DELIVER IN PERSON|AIR|into beans boost. +5504|176056|6057|2|7|7924.35|0.03|0.05|R|F|1993-04-25|1993-03-15|1993-05-06|NONE|TRUCK|packages detect furiously express reques +5504|159600|7146|3|29|48128.40|0.05|0.03|A|F|1993-01-28|1993-02-13|1993-02-27|NONE|SHIP|ajole carefully. care +5505|24501|2008|1|43|61296.50|0.07|0.01|N|O|1997-12-30|1997-11-28|1998-01-09|TAKE BACK RETURN|TRUCK|y alongside of the special requests. +5505|181434|8989|2|33|50009.19|0.05|0.08|N|O|1998-01-11|1997-11-11|1998-01-30|TAKE BACK RETURN|AIR|ithely unusual excuses integrat +5505|154641|9672|3|10|16956.40|0.06|0.01|N|O|1997-10-28|1997-11-27|1997-10-29|DELIVER IN PERSON|AIR| furiously special asym +5505|39422|4429|4|18|24505.56|0.04|0.04|N|O|1997-10-25|1997-12-12|1997-10-30|TAKE BACK RETURN|RAIL| to the quickly express pac +5505|161992|7025|5|46|94483.54|0.05|0.00|N|O|1998-01-06|1997-11-04|1998-02-04|TAKE BACK RETURN|SHIP|usly ironic dependencies haggle across +5506|139309|9310|1|2|2696.60|0.00|0.03|R|F|1994-02-04|1994-01-13|1994-02-17|COLLECT COD|MAIL|onic theodolites are fluffil +5506|159024|9025|2|6|6498.12|0.07|0.06|R|F|1994-02-21|1994-01-30|1994-02-27|DELIVER IN PERSON|MAIL|hely according to the furiously unusua +5507|9600|4601|1|23|34720.80|0.05|0.04|N|O|1998-09-04|1998-07-04|1998-09-18|TAKE BACK RETURN|AIR|ously slow packages poach whithout the +5507|137601|7602|2|48|78652.80|0.03|0.01|N|O|1998-08-03|1998-08-10|1998-08-24|DELIVER IN PERSON|AIR|yly idle deposits. final, final fox +5507|44676|7181|3|4|6482.68|0.04|0.06|N|O|1998-06-06|1998-07-02|1998-06-27|TAKE BACK RETURN|RAIL|into beans are +5507|66850|9357|4|22|39970.70|0.07|0.01|N|O|1998-07-08|1998-08-10|1998-07-22|DELIVER IN PERSON|TRUCK|gular ideas. carefully unu +5507|131412|1413|5|48|69283.68|0.06|0.01|N|O|1998-07-21|1998-07-15|1998-07-31|DELIVER IN PERSON|SHIP|uriously regular acc +5508|116947|4481|1|4|7855.76|0.10|0.04|N|O|1996-09-01|1996-08-02|1996-09-17|COLLECT COD|AIR|fluffily about the even +5509|196663|1702|1|3|5278.98|0.03|0.02|A|F|1994-06-14|1994-05-11|1994-06-17|NONE|SHIP| quickly fin +5509|98560|6088|2|17|26495.52|0.03|0.07|R|F|1994-07-01|1994-06-30|1994-07-31|COLLECT COD|AIR|ccounts wake ar +5509|92611|139|3|30|48108.30|0.04|0.04|A|F|1994-07-23|1994-06-01|1994-08-08|NONE|AIR|counts haggle pinto beans. furiously +5509|99849|4868|4|45|83197.80|0.00|0.07|A|F|1994-07-24|1994-05-28|1994-08-20|COLLECT COD|AIR|counts sleep. f +5509|155719|3265|5|35|62114.85|0.04|0.03|A|F|1994-04-17|1994-06-29|1994-04-24|COLLECT COD|RAIL|c accounts. ca +5510|15828|3332|1|8|13950.56|0.01|0.01|A|F|1993-03-16|1993-03-29|1993-03-24|DELIVER IN PERSON|FOB|n packages boost sly +5510|19300|6804|2|46|56087.80|0.02|0.07|A|F|1993-03-12|1993-02-09|1993-03-19|NONE|TRUCK|silent packages cajole doggedly regular +5510|161054|1055|3|47|52407.35|0.03|0.01|A|F|1993-01-20|1993-03-25|1993-02-15|DELIVER IN PERSON|SHIP|riously even requests. slyly bold accou +5510|23375|882|4|29|37652.73|0.09|0.08|A|F|1993-02-28|1993-03-28|1993-03-12|COLLECT COD|AIR|lithely fluffily ironic req +5511|164477|6994|1|16|24663.52|0.10|0.05|A|F|1995-02-02|1995-01-06|1995-02-19|TAKE BACK RETURN|RAIL|thely bold theodolites +5511|164130|1679|2|31|37018.03|0.09|0.01|A|F|1995-02-23|1995-01-21|1995-03-02|COLLECT COD|REG AIR|gular excuses. fluffily even pinto beans c +5511|127764|277|3|49|87796.24|0.05|0.05|R|F|1994-12-21|1995-01-27|1994-12-26|NONE|REG AIR|bout the requests. theodolites +5511|121474|3987|4|4|5981.88|0.08|0.02|R|F|1994-12-28|1995-01-16|1995-01-24|TAKE BACK RETURN|RAIL|lphins. carefully blithe de +5511|8948|1449|5|23|42709.62|0.10|0.07|A|F|1995-03-11|1995-01-21|1995-03-27|TAKE BACK RETURN|TRUCK|ing dugouts +5511|187419|2456|6|5|7532.05|0.08|0.05|R|F|1994-12-29|1995-01-16|1995-01-24|DELIVER IN PERSON|MAIL|al theodolites. blithely final de +5511|142696|239|7|23|39989.87|0.02|0.07|R|F|1995-02-03|1995-01-05|1995-02-18|COLLECT COD|REG AIR|ully deposits. warthogs hagg +5536|89717|7242|1|14|23893.94|0.08|0.06|N|O|1998-05-18|1998-05-08|1998-06-05|COLLECT COD|MAIL|instructions sleep +5536|61023|3530|2|20|19680.40|0.08|0.04|N|O|1998-05-08|1998-05-10|1998-05-31|DELIVER IN PERSON|REG AIR|equests mo +5536|196848|9368|3|35|68069.40|0.07|0.02|N|O|1998-05-19|1998-06-08|1998-06-05|NONE|MAIL|c, final theo +5536|8827|8828|4|30|52074.60|0.05|0.07|N|O|1998-04-15|1998-05-23|1998-05-03|NONE|FOB|arefully regular theodolites according +5536|140844|845|5|11|20733.24|0.02|0.08|N|O|1998-03-18|1998-05-12|1998-03-28|TAKE BACK RETURN|FOB| snooze furio +5537|44015|9024|1|10|9590.10|0.05|0.08|N|O|1997-01-13|1996-12-25|1997-01-28|TAKE BACK RETURN|AIR| sleep carefully slyly bold depos +5537|149459|7002|2|15|22626.75|0.07|0.04|N|O|1997-01-13|1996-12-25|1997-01-27|COLLECT COD|AIR|eposits. permanently pending packag +5537|150896|5927|3|39|75928.71|0.03|0.00|N|O|1996-12-17|1996-11-08|1997-01-15|COLLECT COD|REG AIR| slyly bold packages are. qu +5537|96020|3548|4|38|38608.76|0.01|0.00|N|O|1996-11-06|1996-11-23|1996-11-12|TAKE BACK RETURN|MAIL|s above the carefully ironic deposits +5538|153301|8332|1|42|56880.60|0.05|0.00|A|F|1994-04-08|1994-03-17|1994-05-05|DELIVER IN PERSON|REG AIR|vely ironic accounts. furiously unusual acc +5538|120083|84|2|4|4412.32|0.02|0.03|R|F|1994-03-21|1994-02-17|1994-04-11|TAKE BACK RETURN|REG AIR|ithely along the c +5538|18521|1023|3|38|54701.76|0.03|0.06|R|F|1994-03-17|1994-02-11|1994-04-10|TAKE BACK RETURN|FOB|ular pinto beans. silent ideas above +5538|77667|5189|4|9|14801.94|0.00|0.01|R|F|1993-12-26|1994-01-31|1994-01-03|TAKE BACK RETURN|REG AIR|encies across the blithely fina +5539|64404|1923|1|42|57472.80|0.10|0.08|A|F|1994-09-29|1994-09-17|1994-10-20|DELIVER IN PERSON|RAIL|ons across the carefully si +5540|180895|896|1|42|82987.38|0.02|0.08|N|O|1996-11-12|1996-12-18|1996-12-05|TAKE BACK RETURN|RAIL|ss dolphins haggle +5540|101022|1023|2|2|2046.04|0.06|0.02|N|O|1996-12-12|1997-01-09|1996-12-25|DELIVER IN PERSON|MAIL|nic asymptotes could hav +5540|63336|5843|3|19|24687.27|0.01|0.03|N|O|1997-02-06|1996-11-18|1997-02-20|DELIVER IN PERSON|SHIP| slyly slyl +5540|71466|8988|4|24|34499.04|0.10|0.05|N|O|1997-01-09|1996-12-02|1997-01-23|COLLECT COD|FOB|deposits! ironic depths may engage-- b +5541|95359|7869|1|39|52819.65|0.08|0.05|N|O|1997-11-17|1997-12-27|1997-12-11|TAKE BACK RETURN|RAIL|ding theodolites haggle against the slyly +5542|188250|8251|1|6|8029.50|0.03|0.01|N|O|1996-06-14|1996-05-28|1996-07-11|DELIVER IN PERSON|TRUCK| foxes doubt. theodolites ca +5543|142617|5132|1|14|23234.54|0.02|0.03|R|F|1993-10-09|1993-12-09|1993-10-21|NONE|SHIP|ecial reque +5543|161544|9093|2|22|35321.88|0.04|0.00|A|F|1993-11-06|1993-11-02|1993-12-02|DELIVER IN PERSON|SHIP|instructions. deposits use quickly. ir +5543|66993|9500|3|3|5879.97|0.08|0.05|R|F|1993-11-18|1993-11-05|1993-12-17|NONE|FOB|ress, even +5543|146766|1795|4|8|14502.08|0.05|0.01|R|F|1993-10-28|1993-11-18|1993-11-07|NONE|SHIP|totes? iron +5543|79919|9920|5|32|60765.12|0.03|0.03|R|F|1993-10-04|1993-11-14|1993-11-03|DELIVER IN PERSON|AIR|ully around the +5543|183372|927|6|1|1455.37|0.03|0.07|A|F|1993-10-29|1993-11-11|1993-11-23|TAKE BACK RETURN|FOB|uriously. slyly +5543|128171|3196|7|39|46767.63|0.06|0.00|R|F|1993-10-07|1993-11-15|1993-10-28|TAKE BACK RETURN|MAIL|l excuses are furiously. slyly unusual requ +5568|165351|7868|1|50|70817.50|0.05|0.05|N|O|1995-07-14|1995-09-04|1995-08-03|COLLECT COD|TRUCK|furious ide +5568|43012|3013|2|18|17190.18|0.01|0.08|N|O|1995-08-19|1995-08-18|1995-08-24|DELIVER IN PERSON|SHIP|structions haggle. carefully regular +5568|88766|8767|3|35|61416.60|0.08|0.07|N|O|1995-09-17|1995-09-04|1995-10-14|NONE|SHIP|lyly. blit +5569|28825|1328|1|25|43845.50|0.10|0.03|R|F|1993-06-29|1993-07-18|1993-07-05|TAKE BACK RETURN|TRUCK| deposits cajole above +5569|57218|4734|2|26|30555.46|0.09|0.06|A|F|1993-08-21|1993-07-22|1993-09-09|DELIVER IN PERSON|MAIL|pitaphs. ironic req +5569|54713|7219|3|48|80050.08|0.02|0.03|R|F|1993-06-16|1993-06-15|1993-07-09|COLLECT COD|SHIP|the fluffily +5569|146526|1555|4|19|29877.88|0.10|0.08|R|F|1993-07-30|1993-06-21|1993-08-13|TAKE BACK RETURN|FOB| detect ca +5569|58516|6032|5|15|22117.65|0.02|0.06|A|F|1993-06-29|1993-07-06|1993-07-05|DELIVER IN PERSON|MAIL|lithely bold requests boost fur +5570|160555|8104|1|37|59775.35|0.08|0.02|N|O|1996-08-29|1996-10-23|1996-09-11|NONE|RAIL|y ironic pin +5570|38607|3614|2|15|23184.00|0.09|0.02|N|O|1996-10-04|1996-10-05|1996-10-28|TAKE BACK RETURN|REG AIR|beans nag slyly special, regular pack +5570|59349|9350|3|29|37941.86|0.02|0.05|N|O|1996-10-12|1996-10-20|1996-11-08|TAKE BACK RETURN|SHIP|he silent, enticing requests. +5571|153454|5970|1|32|48238.40|0.05|0.01|R|F|1992-12-25|1993-03-01|1993-01-23|NONE|FOB| the blithely even packages nag q +5571|93241|769|2|31|38261.44|0.09|0.07|R|F|1993-01-05|1993-01-18|1993-02-04|DELIVER IN PERSON|SHIP|uffily even accounts. quickly re +5571|91430|8958|3|18|25585.74|0.10|0.05|R|F|1993-03-11|1993-02-28|1993-04-03|COLLECT COD|REG AIR|uests haggle furiously pending d +5572|21549|6554|1|24|35292.96|0.08|0.08|R|F|1994-10-30|1994-10-02|1994-11-27|TAKE BACK RETURN|MAIL|ests cajole. evenly ironic exc +5572|171660|9212|2|27|46754.82|0.03|0.04|A|F|1994-08-29|1994-09-10|1994-08-30|TAKE BACK RETURN|SHIP| accounts. carefully final accoun +5572|86234|6235|3|19|23184.37|0.10|0.00|A|F|1994-08-12|1994-10-07|1994-09-01|DELIVER IN PERSON|RAIL|es. final, final requests wake blithely ag +5572|134303|1843|4|46|61515.80|0.02|0.01|R|F|1994-09-08|1994-10-14|1994-10-01|NONE|REG AIR|ully regular platelet +5572|23056|8061|5|34|33287.70|0.10|0.08|R|F|1994-10-22|1994-08-16|1994-11-08|NONE|TRUCK|asymptotes integrate. s +5572|100044|45|6|14|14616.56|0.04|0.05|A|F|1994-11-02|1994-09-20|1994-11-03|COLLECT COD|RAIL|he fluffily express packages. fluffily fina +5572|25241|7744|7|24|27989.76|0.01|0.05|R|F|1994-09-26|1994-09-04|1994-10-22|DELIVER IN PERSON|FOB| beans. foxes sleep fluffily across th +5573|20138|2641|1|32|33860.16|0.05|0.07|N|O|1996-09-30|1996-10-25|1996-10-15|DELIVER IN PERSON|RAIL|egular depths haggl +5573|49469|4478|2|2|2836.92|0.01|0.07|N|O|1996-08-26|1996-09-29|1996-09-04|COLLECT COD|TRUCK| even foxes. specia +5573|10720|5723|3|46|75013.12|0.06|0.01|N|O|1996-11-04|1996-10-02|1996-11-15|DELIVER IN PERSON|MAIL|s haggle qu +5573|168653|6202|4|43|74030.95|0.10|0.03|N|O|1996-10-22|1996-11-03|1996-11-02|TAKE BACK RETURN|FOB| furiously pending packages against +5573|137649|7650|5|43|72525.52|0.05|0.04|N|O|1996-09-09|1996-09-24|1996-09-28|COLLECT COD|AIR| bold package +5574|184533|7052|1|46|74406.38|0.02|0.07|A|F|1992-06-20|1992-04-19|1992-07-11|NONE|FOB|arefully express requests wake furiousl +5574|32304|7311|2|21|25962.30|0.05|0.08|A|F|1992-03-22|1992-04-26|1992-04-16|TAKE BACK RETURN|TRUCK|fully final dugouts. express foxes nag +5574|118564|3587|3|27|42729.12|0.10|0.06|R|F|1992-05-08|1992-05-19|1992-06-05|TAKE BACK RETURN|REG AIR|ecial realms. furiously entici +5574|93359|5869|4|14|18932.90|0.09|0.01|R|F|1992-05-20|1992-04-09|1992-05-23|COLLECT COD|REG AIR| use slyly carefully special requests? slyl +5574|84053|9070|5|19|19703.95|0.05|0.03|A|F|1992-05-28|1992-04-24|1992-06-11|TAKE BACK RETURN|REG AIR|old deposits int +5575|57026|4542|1|7|6881.14|0.01|0.07|N|O|1995-10-01|1995-09-30|1995-10-06|NONE|FOB|s. slyly pending theodolites prin +5575|30170|7680|2|23|25303.91|0.04|0.02|N|O|1995-10-26|1995-10-09|1995-11-13|TAKE BACK RETURN|AIR|enticingly final requests. ironically +5575|62433|9952|3|16|22326.88|0.00|0.07|N|O|1995-08-17|1995-10-14|1995-08-30|NONE|RAIL|jole boldly beyond the final as +5575|109718|9719|4|7|12093.97|0.01|0.04|N|O|1995-10-15|1995-09-14|1995-10-18|DELIVER IN PERSON|RAIL|special requests. final, final +5600|186280|8799|1|34|46453.52|0.02|0.00|N|O|1997-03-22|1997-04-05|1997-04-09|TAKE BACK RETURN|MAIL|ly above the stealthy ideas. permane +5600|7352|4853|2|19|23927.65|0.00|0.01|N|O|1997-04-10|1997-03-24|1997-04-16|TAKE BACK RETURN|TRUCK|dencies. carefully p +5601|37982|5492|1|29|55679.42|0.09|0.04|A|F|1992-04-06|1992-02-24|1992-04-29|DELIVER IN PERSON|TRUCK| ironic ideas. final +5601|163175|8208|2|45|55717.65|0.10|0.07|A|F|1992-03-25|1992-04-03|1992-04-04|TAKE BACK RETURN|MAIL|ts-- blithely final accounts cajole. carefu +5601|72205|2206|3|38|44733.60|0.07|0.00|A|F|1992-01-08|1992-03-01|1992-01-09|TAKE BACK RETURN|REG AIR|ter the evenly final deposit +5601|147847|362|4|12|22738.08|0.03|0.01|A|F|1992-02-27|1992-03-16|1992-03-27|COLLECT COD|TRUCK|ep carefully a +5602|175324|2876|1|9|12593.88|0.08|0.03|N|O|1997-10-14|1997-09-14|1997-11-11|COLLECT COD|FOB|lar foxes; quickly ironic ac +5602|61015|8534|2|31|30256.31|0.04|0.08|N|O|1997-09-04|1997-10-24|1997-09-07|NONE|TRUCK|rate fluffily regular platelets. blithel +5602|67680|2693|3|30|49430.40|0.04|0.00|N|O|1997-09-20|1997-10-25|1997-10-12|DELIVER IN PERSON|FOB|e slyly even packages. careful +5603|97812|5340|1|50|90490.50|0.03|0.02|A|F|1992-10-06|1992-08-20|1992-10-08|COLLECT COD|SHIP|final theodolites accor +5603|115704|3238|2|49|84265.30|0.06|0.05|A|F|1992-06-24|1992-07-28|1992-07-01|DELIVER IN PERSON|FOB|fully silent requests. carefully fin +5603|31836|9346|3|49|86623.67|0.00|0.02|R|F|1992-10-07|1992-07-21|1992-10-10|DELIVER IN PERSON|TRUCK|nic, pending dependencies print +5604|135036|5037|1|44|47125.32|0.05|0.01|N|O|1998-08-06|1998-07-08|1998-09-04|NONE|RAIL|efully ironi +5604|135056|7570|2|49|53461.45|0.10|0.00|N|O|1998-05-02|1998-07-07|1998-05-20|NONE|FOB|ove the regula +5604|77004|9512|3|10|9810.00|0.07|0.05|N|O|1998-08-03|1998-06-23|1998-08-04|COLLECT COD|SHIP|ly final realms wake blit +5605|86747|1764|1|50|86687.00|0.08|0.05|N|O|1996-08-26|1996-10-15|1996-09-04|TAKE BACK RETURN|RAIL|instructions sleep carefully ironic req +5605|150710|711|2|7|12324.97|0.06|0.01|N|O|1996-12-13|1996-10-13|1996-12-15|TAKE BACK RETURN|FOB|lowly special courts nag among the furi +5605|172146|7181|3|3|3654.42|0.01|0.02|N|O|1996-09-01|1996-10-02|1996-09-20|TAKE BACK RETURN|AIR|posits. accounts boost. t +5605|54851|7357|4|45|81263.25|0.00|0.01|N|O|1996-09-05|1996-10-04|1996-09-13|COLLECT COD|FOB|ly unusual instructions. carefully ironic p +5605|69922|4935|5|39|73784.88|0.00|0.08|N|O|1996-12-13|1996-11-03|1996-12-24|DELIVER IN PERSON|REG AIR|cial deposits. theodolites w +5605|165991|5992|6|29|59652.71|0.08|0.08|N|O|1996-09-19|1996-10-22|1996-10-06|DELIVER IN PERSON|SHIP| quickly. quickly pending sen +5606|173945|3946|1|47|94890.18|0.10|0.04|N|O|1996-12-23|1997-01-31|1997-01-20|DELIVER IN PERSON|REG AIR|carefully final foxes. pending, final +5606|91684|1685|2|34|56973.12|0.09|0.06|N|O|1997-02-23|1997-02-08|1997-03-09|TAKE BACK RETURN|REG AIR|uses. slyly final +5606|126750|6751|3|46|81730.50|0.04|0.00|N|O|1997-03-11|1997-01-13|1997-03-23|DELIVER IN PERSON|REG AIR|ter the ironic accounts. even, ironic depos +5606|81657|1658|4|30|49159.50|0.08|0.04|N|O|1997-02-06|1997-01-26|1997-02-16|DELIVER IN PERSON|REG AIR| nag always. blithely express packages +5606|6317|1318|5|25|30582.75|0.06|0.00|N|O|1996-12-25|1997-01-12|1997-01-11|TAKE BACK RETURN|AIR|breach about the furiously bold +5606|153929|3930|6|3|5948.76|0.04|0.06|N|O|1997-01-11|1997-01-04|1997-02-08|COLLECT COD|AIR| sauternes. asympto +5606|73859|3860|7|46|84311.10|0.07|0.01|N|O|1997-02-01|1997-01-31|1997-02-15|DELIVER IN PERSON|TRUCK|ow requests wake around the regular accoun +5607|131532|4046|1|23|35961.19|0.02|0.06|R|F|1992-04-17|1992-02-12|1992-04-30|DELIVER IN PERSON|MAIL|the special, final patterns +5632|9074|1575|1|48|47187.36|0.06|0.06|N|O|1996-05-08|1996-03-24|1996-06-04|TAKE BACK RETURN|FOB|unts. decoys u +5632|105591|5592|2|21|33528.39|0.02|0.08|N|O|1996-03-22|1996-03-10|1996-04-10|NONE|AIR|refully regular pinto beans. ironic reques +5632|66291|3810|3|24|30174.96|0.04|0.06|N|O|1996-03-23|1996-04-02|1996-03-30|TAKE BACK RETURN|MAIL|beans detect. quickly final i +5633|159226|6772|1|28|35986.16|0.02|0.00|N|O|1998-08-14|1998-07-24|1998-08-26|TAKE BACK RETURN|SHIP|as boost quickly. unusual pinto +5633|101711|1712|2|10|17127.10|0.09|0.04|N|O|1998-07-15|1998-08-03|1998-08-03|COLLECT COD|AIR|its cajole fluffily fluffily special pinto +5633|45872|5873|3|27|49082.49|0.03|0.02|N|O|1998-09-28|1998-07-28|1998-10-12|DELIVER IN PERSON|AIR|ructions. even ideas haggle carefully r +5633|163653|3654|4|50|85832.50|0.02|0.05|N|O|1998-07-23|1998-07-09|1998-08-21|DELIVER IN PERSON|TRUCK|ts. slyly regular +5633|99323|1833|5|48|63471.36|0.01|0.05|N|O|1998-06-24|1998-07-22|1998-07-18|DELIVER IN PERSON|TRUCK|even courts haggle slyly at the requ +5633|106564|1585|6|1|1570.56|0.02|0.03|N|O|1998-09-29|1998-08-28|1998-10-19|NONE|RAIL|thely notornis: +5633|10697|3199|7|39|62699.91|0.02|0.08|N|O|1998-07-12|1998-07-03|1998-07-13|COLLECT COD|TRUCK|ding ideas cajole furiously after +5634|184279|1834|1|26|35445.02|0.10|0.08|N|O|1996-10-29|1996-09-15|1996-11-24|COLLECT COD|REG AIR|ptotes mold qu +5634|174875|2427|2|22|42897.14|0.02|0.05|N|O|1996-09-01|1996-08-31|1996-09-05|DELIVER IN PERSON|MAIL|silently unusual foxes above the blithely +5634|108573|6104|3|16|25305.12|0.08|0.02|N|O|1996-11-15|1996-09-14|1996-12-04|NONE|AIR|ess ideas are carefully pending, even re +5634|181044|6081|4|29|32626.16|0.00|0.01|N|O|1996-08-10|1996-10-29|1996-08-11|TAKE BACK RETURN|MAIL|ely final ideas. deposits sleep. reg +5634|309|310|5|1|1209.30|0.04|0.02|N|O|1996-10-02|1996-10-21|1996-10-27|COLLECT COD|MAIL|ctions haggle carefully. carefully clo +5635|82066|7083|1|43|45066.58|0.03|0.00|R|F|1992-10-12|1992-09-29|1992-11-01|TAKE BACK RETURN|TRUCK|cross the d +5635|71392|1393|2|5|6816.95|0.05|0.08|R|F|1992-10-02|1992-11-05|1992-10-26|TAKE BACK RETURN|REG AIR|yly along the ironic, fi +5635|71245|6260|3|12|14594.88|0.09|0.02|A|F|1992-10-18|1992-09-24|1992-11-17|NONE|REG AIR|ke slyly against the carefully final req +5635|7781|5282|4|40|67551.20|0.03|0.01|A|F|1992-09-25|1992-11-05|1992-10-11|NONE|FOB|pending foxes. regular packages +5635|168511|8512|5|38|60021.38|0.05|0.06|A|F|1992-10-09|1992-09-25|1992-10-18|NONE|MAIL|ckly pendin +5635|161513|6546|6|23|36213.73|0.05|0.04|A|F|1992-08-24|1992-11-10|1992-09-21|NONE|AIR|ily pending packages. bold, +5635|136198|8712|7|32|39494.08|0.03|0.08|R|F|1992-11-24|1992-09-20|1992-12-17|TAKE BACK RETURN|TRUCK|slyly even +5636|69821|2328|1|18|32234.76|0.05|0.03|R|F|1995-05-14|1995-05-17|1995-06-12|DELIVER IN PERSON|REG AIR|slyly express requests. furiously pen +5636|69120|6639|2|26|28317.12|0.03|0.06|A|F|1995-03-05|1995-05-16|1995-03-23|TAKE BACK RETURN|AIR| furiously final pinto beans o +5636|89315|9316|3|21|27390.51|0.03|0.03|A|F|1995-03-13|1995-05-11|1995-03-24|COLLECT COD|AIR| are furiously unusual +5636|108256|5787|4|15|18963.75|0.03|0.04|R|F|1995-04-21|1995-04-30|1995-05-05|DELIVER IN PERSON|REG AIR|efully special +5636|46791|9296|5|13|22591.27|0.10|0.03|A|F|1995-05-11|1995-04-27|1995-05-26|COLLECT COD|AIR|en, fluffy accounts amon +5636|11278|1279|6|33|39245.91|0.06|0.04|A|F|1995-03-09|1995-04-05|1995-03-23|DELIVER IN PERSON|MAIL|ding to the +5636|133257|5771|7|24|30966.00|0.10|0.05|R|F|1995-04-12|1995-03-27|1995-04-16|DELIVER IN PERSON|RAIL|counts sleep furiously b +5637|46670|9175|1|14|22633.38|0.03|0.05|N|O|1996-07-20|1996-07-26|1996-08-14|COLLECT COD|MAIL|y bold deposits wak +5637|171887|1888|2|35|68560.80|0.09|0.08|N|O|1996-08-01|1996-08-04|1996-08-20|NONE|AIR|s sleep blithely alongside of the ironic +5637|95346|2874|3|22|29509.48|0.01|0.07|N|O|1996-08-28|1996-07-30|1996-09-17|COLLECT COD|REG AIR|nding requests are ca +5637|65175|2694|4|16|18242.72|0.03|0.03|N|O|1996-09-08|1996-08-31|1996-09-29|TAKE BACK RETURN|TRUCK|d packages. express requests +5637|195700|5701|5|10|17957.00|0.01|0.00|N|O|1996-08-25|1996-08-11|1996-09-23|TAKE BACK RETURN|MAIL|ickly ironic gifts. blithely even cour +5637|128281|794|6|27|35350.56|0.01|0.05|N|O|1996-06-27|1996-08-09|1996-07-27|DELIVER IN PERSON|REG AIR|oss the carefully express warhorses +5638|137834|7835|1|45|84232.35|0.09|0.07|A|F|1994-05-17|1994-03-09|1994-06-15|NONE|TRUCK|ar foxes. fluffily pending accounts +5638|167678|5227|2|12|20948.04|0.02|0.05|A|F|1994-02-05|1994-04-01|1994-02-25|COLLECT COD|TRUCK|n, even requests. furiously ironic not +5638|161923|6956|3|21|41683.32|0.08|0.00|A|F|1994-03-13|1994-03-27|1994-03-17|DELIVER IN PERSON|TRUCK|press courts use f +5639|46609|1618|1|11|17111.60|0.09|0.02|R|F|1994-09-18|1994-07-10|1994-10-12|TAKE BACK RETURN|SHIP|g the unusual pinto beans caj +5664|121079|6104|1|25|27501.75|0.00|0.06|N|O|1998-10-29|1998-09-23|1998-11-25|COLLECT COD|FOB|eposits: furiously ironic grouch +5664|172408|7443|2|9|13323.60|0.07|0.05|N|O|1998-07-31|1998-08-26|1998-08-12|COLLECT COD|RAIL| ironic deposits haggle furiously. re +5664|52439|2440|3|31|43134.33|0.01|0.03|N|O|1998-11-10|1998-09-12|1998-12-07|TAKE BACK RETURN|FOB|ainst the never silent request +5664|137545|2572|4|33|52223.82|0.08|0.03|N|O|1998-08-29|1998-09-17|1998-09-25|DELIVER IN PERSON|RAIL|d the final +5664|111779|9313|5|44|78793.88|0.01|0.06|N|O|1998-09-24|1998-09-26|1998-10-23|NONE|TRUCK|ang thinly bold pa +5664|67733|2746|6|34|57824.82|0.09|0.01|N|O|1998-09-10|1998-10-05|1998-09-15|COLLECT COD|RAIL|st. fluffily pending foxes na +5664|181490|9045|7|9|14143.41|0.01|0.05|N|O|1998-11-04|1998-10-15|1998-11-20|TAKE BACK RETURN|REG AIR|yly. express ideas agai +5665|100935|936|1|32|61949.76|0.00|0.02|A|F|1993-08-11|1993-08-01|1993-09-07|NONE|AIR|f the slyly even requests! regular request +5665|4924|7425|2|14|25604.88|0.02|0.00|R|F|1993-06-29|1993-09-16|1993-07-16|DELIVER IN PERSON|AIR|- special pinto beans sleep quickly blithel +5665|157104|7105|3|41|47605.10|0.09|0.02|A|F|1993-08-23|1993-09-22|1993-09-11|COLLECT COD|REG AIR| idle ideas across +5665|45118|127|4|47|49966.17|0.01|0.01|A|F|1993-10-06|1993-09-19|1993-11-01|NONE|RAIL|s mold fluffily. final deposits along the +5666|121226|8763|1|7|8730.54|0.09|0.08|R|F|1994-05-10|1994-04-06|1994-05-21|NONE|FOB| ideas. regular packag +5666|35783|790|2|14|24062.92|0.08|0.01|A|F|1994-02-27|1994-04-11|1994-03-06|DELIVER IN PERSON|TRUCK|lar deposits nag against the slyly final d +5666|192178|7217|3|39|49536.63|0.00|0.01|A|F|1994-05-13|1994-04-02|1994-06-12|DELIVER IN PERSON|TRUCK|the even, final foxes. quickly iron +5666|130643|5670|4|24|40167.36|0.07|0.01|R|F|1994-02-14|1994-03-09|1994-03-06|DELIVER IN PERSON|FOB|on the carefully pending asympto +5666|108483|8484|5|36|53693.28|0.07|0.07|R|F|1994-03-15|1994-03-16|1994-03-18|COLLECT COD|TRUCK|accounts. furiousl +5667|144431|1974|1|37|54590.91|0.09|0.06|N|O|1995-09-24|1995-09-17|1995-10-03|NONE|REG AIR|s cajole blit +5668|3645|8646|1|15|23229.60|0.03|0.04|A|F|1995-04-06|1995-05-12|1995-04-17|COLLECT COD|FOB| the express, pending requests. bo +5669|190847|848|1|7|13564.88|0.06|0.06|N|O|1996-06-19|1996-07-07|1996-07-11|COLLECT COD|SHIP|yly regular requests lose blithely. careful +5669|155814|3360|2|2|3739.62|0.06|0.07|N|O|1996-08-04|1996-06-15|1996-08-20|NONE|SHIP| blithely excuses. slyly +5669|157654|7655|3|40|68466.00|0.00|0.02|N|O|1996-08-30|1996-06-15|1996-09-07|TAKE BACK RETURN|FOB|ar accounts alongside of the final, p +5669|89245|9246|4|31|38261.44|0.04|0.05|N|O|1996-08-05|1996-06-10|1996-08-29|COLLECT COD|AIR|to beans against the regular depo +5669|139680|7220|5|30|51590.40|0.07|0.01|N|O|1996-07-14|1996-07-28|1996-08-10|TAKE BACK RETURN|TRUCK|l accounts. care +5670|89569|9570|1|27|42081.12|0.10|0.06|R|F|1993-05-09|1993-05-30|1993-06-06|TAKE BACK RETURN|REG AIR| ideas promise bli +5670|185257|7776|2|43|57716.75|0.06|0.00|A|F|1993-07-09|1993-06-03|1993-07-14|DELIVER IN PERSON|FOB|ests in place of the carefully sly depos +5670|6482|6483|3|24|33323.52|0.09|0.04|A|F|1993-07-17|1993-07-01|1993-08-03|NONE|AIR|press, express requests haggle +5670|141383|3898|4|11|15668.18|0.06|0.06|R|F|1993-07-11|1993-06-26|1993-07-24|DELIVER IN PERSON|MAIL|etect furiously among the even pin +5671|119482|4505|1|25|37537.00|0.00|0.08|N|O|1998-04-17|1998-03-28|1998-05-06|DELIVER IN PERSON|AIR|cording to the quickly final requests-- +5671|128838|3863|2|46|85874.18|0.05|0.08|N|O|1998-03-28|1998-04-22|1998-04-19|TAKE BACK RETURN|MAIL|lar pinto beans detect care +5671|171340|8892|3|13|18347.42|0.10|0.06|N|O|1998-03-02|1998-04-03|1998-03-08|TAKE BACK RETURN|TRUCK|bold theodolites about +5671|110212|7746|4|42|51332.82|0.00|0.07|N|O|1998-02-17|1998-04-24|1998-03-17|TAKE BACK RETURN|SHIP|carefully slyly special deposit +5671|128097|610|5|13|14626.17|0.09|0.00|N|O|1998-04-24|1998-03-26|1998-04-27|NONE|REG AIR|ers according to the ironic, unusual excu +5671|113340|8363|6|30|40600.20|0.09|0.07|N|O|1998-06-06|1998-04-15|1998-07-01|DELIVER IN PERSON|TRUCK|fily ironi +5696|136316|3856|1|28|37864.68|0.03|0.06|N|O|1995-07-03|1995-06-14|1995-07-27|COLLECT COD|REG AIR| the fluffily brave pearls +5696|58914|6430|2|46|86153.86|0.01|0.00|N|O|1995-08-10|1995-07-08|1995-08-25|COLLECT COD|AIR|ter the instruct +5696|166282|3831|3|42|56627.76|0.04|0.01|N|F|1995-06-06|1995-06-11|1995-06-19|TAKE BACK RETURN|SHIP|te furious +5696|97646|156|4|20|32872.80|0.08|0.00|N|O|1995-06-25|1995-07-18|1995-07-16|NONE|TRUCK|silent, pending ideas sleep fluffil +5696|123505|6018|5|19|29041.50|0.07|0.05|N|O|1995-08-31|1995-06-13|1995-09-10|COLLECT COD|SHIP|unusual requests sleep furiously ru +5696|131928|9468|6|37|72517.04|0.04|0.05|N|O|1995-07-21|1995-06-23|1995-08-19|NONE|RAIL| carefully expres +5696|101569|9100|7|6|9423.36|0.07|0.05|N|O|1995-08-03|1995-07-15|1995-09-01|DELIVER IN PERSON|REG AIR|n patterns lose slyly fina +5697|54193|1709|1|24|27532.56|0.10|0.07|R|F|1992-10-27|1992-11-28|1992-11-20|NONE|RAIL|uffily iro +5697|15283|7785|2|43|51526.04|0.06|0.02|R|F|1992-12-08|1992-12-03|1992-12-17|TAKE BACK RETURN|FOB|blithely reg +5697|55460|2976|3|42|59449.32|0.03|0.01|A|F|1992-12-19|1992-12-08|1993-01-03|COLLECT COD|TRUCK|inal theodolites cajole after the bli +5698|10470|5473|1|30|41414.10|0.01|0.05|A|F|1994-05-26|1994-08-16|1994-06-19|COLLECT COD|AIR|its. quickly regular foxes aro +5698|162073|2074|2|25|28376.75|0.08|0.07|R|F|1994-08-06|1994-06-21|1994-08-25|NONE|SHIP| asymptotes sleep slyly above the +5698|154975|7491|3|45|91348.65|0.03|0.01|A|F|1994-06-23|1994-08-13|1994-07-02|NONE|FOB|ng excuses. slyly express asymptotes +5698|57104|9610|4|15|15916.50|0.07|0.08|R|F|1994-06-29|1994-07-03|1994-07-02|COLLECT COD|REG AIR|ly ironic frets haggle carefully +5698|139406|9407|5|37|53479.80|0.06|0.06|A|F|1994-06-30|1994-06-23|1994-07-22|TAKE BACK RETURN|SHIP|ts. even, ironic +5698|187630|149|6|1|1717.63|0.06|0.04|R|F|1994-05-31|1994-07-10|1994-06-03|DELIVER IN PERSON|MAIL|nts. slyly quiet pinto beans nag carefu +5699|1884|6885|1|24|42861.12|0.01|0.07|A|F|1992-10-21|1992-09-04|1992-11-04|COLLECT COD|AIR|kages. fin +5699|54419|9430|2|26|35708.66|0.06|0.06|R|F|1992-08-11|1992-09-21|1992-08-14|COLLECT COD|MAIL|y final deposits wake fluffily u +5699|17473|9975|3|48|66742.56|0.10|0.05|R|F|1992-11-23|1992-10-20|1992-11-29|DELIVER IN PERSON|TRUCK|s. carefully regul +5699|54313|6819|4|46|58296.26|0.08|0.02|A|F|1992-11-28|1992-09-23|1992-12-27|TAKE BACK RETURN|FOB|o the slyly +5699|27286|2291|5|21|25478.88|0.02|0.02|A|F|1992-10-13|1992-09-30|1992-10-19|NONE|MAIL|lyly final pla +5699|190036|7594|6|30|33780.90|0.08|0.05|R|F|1992-11-13|1992-10-01|1992-12-11|DELIVER IN PERSON|AIR| the carefully final +5699|128219|3244|7|45|56124.45|0.09|0.06|A|F|1992-09-23|1992-10-22|1992-10-04|DELIVER IN PERSON|SHIP|rmanent packages sleep across the f +5700|167890|2923|1|24|46989.36|0.09|0.00|N|O|1997-12-26|1998-01-28|1998-01-18|DELIVER IN PERSON|REG AIR|ix carefully +5700|122421|4934|2|30|43302.60|0.00|0.06|N|O|1998-04-19|1998-03-13|1998-04-27|COLLECT COD|MAIL|ly blithely final instructions. fl +5700|125320|345|3|23|30942.36|0.03|0.05|N|O|1998-01-30|1998-01-31|1998-01-31|NONE|REG AIR| wake quickly carefully fluffy hockey +5701|53487|5993|1|17|24488.16|0.02|0.05|N|O|1997-03-27|1997-04-08|1997-04-21|DELIVER IN PERSON|RAIL|tes. quickly final a +5702|76997|9505|1|44|86855.56|0.06|0.02|R|F|1994-01-04|1993-11-25|1994-01-22|NONE|RAIL|lites. carefully final requests doze b +5702|85532|5533|2|37|56148.61|0.10|0.05|R|F|1993-12-14|1993-10-21|1994-01-08|NONE|FOB|ix slyly. regular instructions slee +5702|130640|8180|3|44|73508.16|0.00|0.02|R|F|1993-11-28|1993-12-02|1993-12-22|NONE|TRUCK|ake according to th +5702|62204|9723|4|31|36152.20|0.00|0.04|A|F|1994-01-04|1993-10-22|1994-01-26|DELIVER IN PERSON|TRUCK|pinto beans. blithely +5703|87698|207|1|2|3371.38|0.09|0.01|R|F|1993-05-29|1993-07-26|1993-06-05|TAKE BACK RETURN|REG AIR|nts against the blithely sile +5728|43599|6104|1|47|72501.73|0.10|0.05|A|F|1994-12-13|1995-01-25|1994-12-25|TAKE BACK RETURN|MAIL|nd the bravely final deposits. final ideas +5728|158786|6332|2|40|73791.20|0.05|0.08|A|F|1995-03-28|1995-01-17|1995-04-14|TAKE BACK RETURN|SHIP|final deposits. theodolite +5729|142388|2389|1|5|7151.90|0.07|0.00|R|F|1994-11-27|1994-11-11|1994-12-23|TAKE BACK RETURN|MAIL|s. even sheaves nag courts. +5729|106136|8647|2|39|44543.07|0.10|0.00|A|F|1995-01-22|1994-11-21|1995-02-13|TAKE BACK RETURN|MAIL|. special pl +5729|11181|1182|3|50|54609.00|0.00|0.05|R|F|1994-12-09|1994-12-31|1994-12-24|TAKE BACK RETURN|AIR|ly special sentiments. car +5730|150009|10|1|2|2118.00|0.08|0.00|N|O|1998-02-24|1998-03-15|1998-03-11|COLLECT COD|SHIP|ely ironic foxes. carefu +5730|199690|9691|2|9|16107.21|0.10|0.01|N|O|1998-03-05|1998-02-02|1998-03-28|DELIVER IN PERSON|MAIL|s lose blithely. specia +5731|191796|9354|1|13|24541.27|0.02|0.04|N|O|1997-07-30|1997-06-23|1997-08-13|COLLECT COD|RAIL|ngside of the quickly regular depos +5731|104178|4179|2|11|13003.87|0.00|0.08|N|O|1997-06-06|1997-07-08|1997-06-25|NONE|MAIL| furiously final accounts wake. d +5731|110812|813|3|6|10936.86|0.01|0.04|N|O|1997-07-02|1997-07-01|1997-07-08|COLLECT COD|SHIP|sits integrate slyly close platelets. quick +5731|13471|8474|4|6|8306.82|0.03|0.06|N|O|1997-09-07|1997-06-20|1997-09-20|TAKE BACK RETURN|RAIL|rs. quickly regular theo +5731|194960|4961|5|19|39044.24|0.08|0.02|N|O|1997-06-29|1997-06-27|1997-07-15|NONE|REG AIR|ly unusual ideas above the +5732|138287|5827|1|26|34457.28|0.02|0.07|N|O|1997-08-18|1997-10-25|1997-09-12|TAKE BACK RETURN|TRUCK|totes cajole according to the theodolites. +5733|32868|2869|1|39|70233.54|0.01|0.07|A|F|1993-03-22|1993-05-24|1993-04-04|DELIVER IN PERSON|FOB|side of the +5734|182945|5464|1|29|58810.26|0.05|0.01|N|O|1997-12-01|1997-12-08|1997-12-23|NONE|RAIL|structions cajole final, express +5734|149299|4328|2|6|8089.74|0.07|0.00|N|O|1997-10-27|1997-12-19|1997-11-02|COLLECT COD|RAIL|s. regular platelets cajole furiously. regu +5734|66727|6728|3|10|16937.20|0.01|0.03|N|O|1997-12-28|1997-12-24|1998-01-24|DELIVER IN PERSON|TRUCK|equests; accounts above +5735|59754|9755|1|41|70263.75|0.01|0.01|R|F|1994-12-23|1995-02-10|1995-01-22|COLLECT COD|MAIL|lthily ruthless i +5760|667|8168|1|6|9405.96|0.09|0.03|R|F|1994-07-30|1994-07-31|1994-08-16|COLLECT COD|REG AIR|ng the acco +5760|5757|758|2|24|39906.00|0.04|0.05|A|F|1994-07-15|1994-07-04|1994-08-08|NONE|MAIL|s. bravely ironic accounts among +5760|147375|9890|3|8|11378.96|0.07|0.04|A|F|1994-09-06|1994-08-03|1994-10-06|NONE|AIR|l accounts among the carefully even de +5760|122293|2294|4|19|24990.51|0.10|0.01|R|F|1994-08-02|1994-08-02|1994-08-15|COLLECT COD|SHIP|sits nag. even, regular ideas cajole b +5760|165638|3187|5|6|10221.78|0.03|0.07|R|F|1994-06-09|1994-07-06|1994-06-16|DELIVER IN PERSON|MAIL| shall have to cajole along the +5761|46273|3786|1|41|49990.07|0.08|0.00|N|O|1998-07-31|1998-08-09|1998-08-08|TAKE BACK RETURN|TRUCK|pecial deposits. qu +5761|107289|7290|2|36|46666.08|0.00|0.07|N|O|1998-09-07|1998-09-21|1998-09-11|TAKE BACK RETURN|TRUCK| pinto beans thrash alongside of the pendi +5761|197395|4953|3|49|73127.11|0.04|0.08|N|O|1998-07-14|1998-08-20|1998-07-25|NONE|SHIP|ly bold accounts wake above the +5762|174993|4994|1|6|12407.94|0.05|0.02|N|O|1997-04-07|1997-03-25|1997-05-02|NONE|AIR|ironic dependencies doze carefu +5762|101749|9280|2|27|47269.98|0.02|0.08|N|O|1997-02-21|1997-05-08|1997-03-23|NONE|REG AIR|across the bold ideas. carefully sp +5762|88317|8318|3|40|52212.40|0.00|0.08|N|O|1997-04-30|1997-05-09|1997-05-08|COLLECT COD|SHIP|al instructions. furiousl +5762|132375|2376|4|47|66146.39|0.05|0.06|N|O|1997-03-02|1997-03-23|1997-03-19|NONE|RAIL|equests sleep after the furiously ironic pa +5762|24527|4528|5|28|40642.56|0.02|0.06|N|O|1997-02-22|1997-03-25|1997-02-24|TAKE BACK RETURN|SHIP|ic foxes among the blithely qui +5762|11673|4175|6|12|19016.04|0.00|0.06|N|O|1997-04-18|1997-04-27|1997-05-11|DELIVER IN PERSON|REG AIR|ages are abo +5763|130799|5826|1|32|58553.28|0.02|0.06|N|O|1998-07-16|1998-09-13|1998-08-02|DELIVER IN PERSON|FOB|ding instruct +5763|135695|8209|2|23|39805.87|0.09|0.04|N|O|1998-07-25|1998-09-21|1998-08-15|DELIVER IN PERSON|SHIP|re after the blithel +5763|12360|9864|3|25|31809.00|0.01|0.02|N|O|1998-10-04|1998-08-16|1998-10-09|DELIVER IN PERSON|REG AIR|inal theodolites. even re +5763|120969|3482|4|47|93528.12|0.09|0.00|N|O|1998-08-22|1998-09-22|1998-09-04|NONE|REG AIR|gle slyly. slyly final re +5763|122996|2997|5|8|16151.92|0.06|0.05|N|O|1998-09-23|1998-09-15|1998-09-27|DELIVER IN PERSON|TRUCK|foxes wake slyly. car +5763|189104|9105|6|9|10737.90|0.08|0.02|N|O|1998-09-24|1998-09-01|1998-10-02|NONE|AIR| deposits. instru +5764|100625|626|1|28|45517.36|0.04|0.04|A|F|1993-12-07|1993-12-20|1993-12-26|TAKE BACK RETURN|RAIL|sleep furi +5764|199143|4182|2|20|24842.80|0.10|0.05|A|F|1993-10-17|1993-12-24|1993-10-18|TAKE BACK RETURN|FOB|ng to the fluffily qu +5764|187173|4728|3|4|5040.68|0.03|0.05|A|F|1993-10-25|1993-12-23|1993-11-06|DELIVER IN PERSON|AIR|ily regular courts haggle +5765|161940|9489|1|31|62060.14|0.00|0.06|A|F|1995-01-11|1995-02-13|1995-01-23|TAKE BACK RETURN|AIR|r foxes. ev +5765|123802|6315|2|29|52948.20|0.07|0.08|A|F|1994-12-29|1995-02-01|1995-01-26|NONE|RAIL|nic requests. deposits wake quickly among +5765|138309|3336|3|31|41766.30|0.05|0.01|R|F|1995-03-01|1995-01-23|1995-03-31|TAKE BACK RETURN|REG AIR|the furiou +5765|151733|9279|4|46|82097.58|0.07|0.07|R|F|1995-03-13|1995-02-12|1995-03-20|DELIVER IN PERSON|MAIL|ccounts sleep about th +5765|173421|8456|5|48|71732.16|0.09|0.02|A|F|1995-03-30|1995-01-14|1995-04-09|DELIVER IN PERSON|SHIP|theodolites integrate furiously +5765|82052|7069|6|41|42396.05|0.04|0.00|A|F|1994-12-31|1995-02-11|1995-01-17|TAKE BACK RETURN|SHIP| furiously. slyly sile +5765|41209|6218|7|21|24154.20|0.05|0.04|R|F|1995-04-05|1995-02-12|1995-05-05|COLLECT COD|TRUCK|ole furiously. quick, special dependencies +5766|187050|9569|1|1|1137.05|0.10|0.01|R|F|1994-01-16|1993-11-16|1994-01-23|NONE|MAIL|blithely regular the +5766|148529|6072|2|39|61523.28|0.02|0.07|A|F|1993-10-24|1993-12-07|1993-11-08|DELIVER IN PERSON|SHIP| furiously unusual courts. slyly final pear +5766|117751|5285|3|4|7075.00|0.08|0.08|R|F|1993-11-10|1993-10-30|1993-12-01|COLLECT COD|TRUCK|ly even requests. furiou +5767|166864|6865|1|11|21239.46|0.08|0.01|A|F|1992-06-02|1992-05-30|1992-06-08|NONE|TRUCK|instructions. carefully final accou +5767|68555|1062|2|15|22853.25|0.07|0.05|R|F|1992-06-05|1992-07-28|1992-06-08|DELIVER IN PERSON|MAIL|warthogs. carefully unusual g +5767|190490|3010|3|42|66380.58|0.06|0.01|R|F|1992-07-31|1992-06-09|1992-08-09|COLLECT COD|TRUCK| blithe deposi +5767|152475|2476|4|34|51933.98|0.06|0.01|R|F|1992-06-02|1992-06-23|1992-06-17|NONE|FOB|sits among the +5767|45270|5271|5|36|43749.72|0.03|0.00|A|F|1992-07-17|1992-06-10|1992-07-19|COLLECT COD|AIR|ake carefully. packages +5792|177019|9537|1|34|37264.34|0.08|0.07|R|F|1993-05-23|1993-06-25|1993-06-12|NONE|RAIL|requests are against t +5792|156410|8926|2|47|68921.27|0.10|0.00|A|F|1993-06-08|1993-05-10|1993-06-26|COLLECT COD|AIR|regular, ironic excuses n +5792|182806|2807|3|32|60441.60|0.05|0.08|R|F|1993-06-26|1993-05-23|1993-07-07|COLLECT COD|RAIL|s are slyly against the ev +5792|13894|6396|4|14|25310.46|0.09|0.02|A|F|1993-07-28|1993-06-17|1993-08-27|DELIVER IN PERSON|RAIL|olites print carefully +5792|101362|8893|5|31|42264.16|0.02|0.01|A|F|1993-06-17|1993-05-05|1993-07-01|COLLECT COD|TRUCK|s? furiously even instructions +5793|52084|9600|1|20|20721.60|0.05|0.03|N|O|1997-10-05|1997-09-04|1997-10-30|COLLECT COD|AIR|e carefully ex +5793|169992|7541|2|41|84541.59|0.06|0.06|N|O|1997-08-04|1997-10-10|1997-08-12|DELIVER IN PERSON|TRUCK|snooze quick +5793|42777|2778|3|8|13758.16|0.07|0.03|N|O|1997-08-16|1997-09-08|1997-08-28|COLLECT COD|AIR|al foxes l +5793|147676|5219|4|48|82736.16|0.02|0.02|N|O|1997-09-27|1997-08-23|1997-10-27|DELIVER IN PERSON|REG AIR|quickly enticing excuses use slyly abov +5794|157144|7145|1|42|50447.88|0.06|0.05|R|F|1993-06-29|1993-05-30|1993-07-28|COLLECT COD|REG AIR|he careful +5794|114786|9809|2|14|25210.92|0.09|0.02|R|F|1993-04-19|1993-07-02|1993-05-18|COLLECT COD|SHIP|uriously carefully ironic reque +5794|6827|6828|3|15|26007.30|0.09|0.06|R|F|1993-06-25|1993-06-27|1993-07-09|NONE|MAIL|blithely regular ideas. final foxes haggle +5794|136244|8758|4|47|60171.28|0.00|0.08|A|F|1993-07-16|1993-06-21|1993-08-05|TAKE BACK RETURN|REG AIR|quests. blithely final excu +5795|192991|8030|1|34|70855.66|0.09|0.05|A|F|1992-08-21|1992-07-30|1992-08-27|COLLECT COD|REG AIR|al instructions must affix along the ironic +5796|57971|2982|1|27|52082.19|0.10|0.00|N|O|1996-04-06|1996-02-29|1996-04-20|DELIVER IN PERSON|RAIL|s wake quickly aro +5797|60967|8486|1|17|32775.32|0.09|0.03|N|O|1997-12-13|1998-01-12|1997-12-23|NONE|REG AIR|the ironic, even theodoli +5798|126015|6016|1|2|2082.02|0.09|0.00|N|O|1998-05-25|1998-06-22|1998-06-09|COLLECT COD|FOB|e furiously across +5798|123814|6327|2|14|25729.34|0.06|0.05|N|O|1998-04-01|1998-06-14|1998-04-27|NONE|RAIL|he special, bold packages. carefully iron +5798|133608|8635|3|22|36115.20|0.02|0.01|N|O|1998-06-24|1998-06-06|1998-07-20|COLLECT COD|TRUCK|sits poach carefully +5798|145699|8214|4|40|69787.60|0.08|0.06|N|O|1998-07-09|1998-06-24|1998-07-16|NONE|TRUCK| integrate carefu +5798|148631|6174|5|7|11757.41|0.06|0.07|N|O|1998-06-06|1998-05-10|1998-06-07|NONE|SHIP|ts against the blithely final p +5798|37444|4954|6|9|12432.96|0.06|0.02|N|O|1998-05-05|1998-05-25|1998-05-09|DELIVER IN PERSON|REG AIR|e blithely +5798|114851|7363|7|32|59707.20|0.08|0.01|N|O|1998-04-27|1998-05-03|1998-05-08|TAKE BACK RETURN|REG AIR|ubt blithely above the +5799|94586|4587|1|41|64803.78|0.04|0.02|N|O|1995-11-13|1995-10-31|1995-11-16|COLLECT COD|TRUCK|al accounts sleep ruthlessl +5799|99882|4901|2|30|56456.40|0.03|0.08|N|O|1995-09-12|1995-09-13|1995-09-19|NONE|RAIL| furiously s +5824|76111|8619|1|40|43484.40|0.06|0.06|N|O|1997-01-14|1997-01-17|1997-02-02|NONE|REG AIR|he final packag +5824|181001|6038|2|42|45444.00|0.09|0.00|N|O|1997-02-01|1997-02-20|1997-02-07|COLLECT COD|SHIP|ts sleep. carefully regular accounts h +5824|72131|9653|3|16|17650.08|0.03|0.02|N|O|1997-02-13|1997-01-07|1997-02-17|TAKE BACK RETURN|TRUCK|sly express Ti +5824|91100|6119|4|32|34915.20|0.03|0.02|N|O|1997-02-16|1997-01-24|1997-02-20|DELIVER IN PERSON|RAIL|ven requests. +5824|107000|7001|5|44|44308.00|0.08|0.03|N|O|1997-01-24|1997-01-31|1997-02-11|COLLECT COD|TRUCK|fily fluffily bold +5825|158214|730|1|23|29260.83|0.10|0.05|R|F|1995-05-10|1995-04-28|1995-05-13|DELIVER IN PERSON|TRUCK| special pinto beans. dependencies haggl +5826|143968|6483|1|4|8047.84|0.03|0.06|N|O|1998-07-31|1998-09-10|1998-08-27|NONE|AIR| packages across the fluffily spec +5826|63777|3778|2|18|31333.86|0.04|0.01|N|O|1998-07-17|1998-09-03|1998-07-22|NONE|SHIP|atelets use above t +5827|186619|6620|1|30|51168.30|0.03|0.05|N|O|1998-11-11|1998-09-27|1998-11-30|DELIVER IN PERSON|RAIL|ounts may c +5827|102134|4645|2|23|26130.99|0.09|0.05|N|O|1998-11-16|1998-09-14|1998-11-17|COLLECT COD|RAIL|ans. furiously special instruct +5827|163706|8739|3|3|5309.10|0.03|0.06|N|O|1998-10-17|1998-09-29|1998-10-28|DELIVER IN PERSON|MAIL|uses eat along the furiously +5827|199067|9068|4|26|30317.56|0.06|0.00|N|O|1998-07-29|1998-09-24|1998-07-30|DELIVER IN PERSON|SHIP|arefully special packages wake thin +5827|111610|6633|5|38|61621.18|0.03|0.06|N|O|1998-10-18|1998-08-27|1998-10-23|TAKE BACK RETURN|TRUCK|ly ruthless accounts +5827|16474|1477|6|14|19466.58|0.05|0.01|N|O|1998-08-31|1998-09-06|1998-09-13|TAKE BACK RETURN|RAIL|rges. fluffily pending +5828|1343|8844|1|28|34841.52|0.10|0.03|A|F|1994-05-15|1994-05-20|1994-06-08|DELIVER IN PERSON|MAIL| special ideas haggle slyly ac +5828|157303|2334|2|37|50331.10|0.01|0.00|R|F|1994-06-07|1994-05-30|1994-06-17|NONE|RAIL|e carefully spec +5829|39657|4664|1|4|6386.60|0.01|0.02|N|O|1997-03-01|1997-02-17|1997-03-22|NONE|TRUCK|ithely; accounts cajole ideas. regular foxe +5829|106523|9034|2|40|61180.80|0.04|0.01|N|O|1997-04-21|1997-02-12|1997-05-04|COLLECT COD|TRUCK| the carefully ironic accounts. a +5829|128238|3263|3|6|7597.38|0.05|0.06|N|O|1997-01-22|1997-03-12|1997-02-02|TAKE BACK RETURN|AIR|sts. slyly special fo +5829|89153|4170|4|42|47970.30|0.02|0.07|N|O|1997-03-26|1997-04-01|1997-03-30|COLLECT COD|REG AIR|pearls. slyly bold deposits solve final +5829|190779|8337|5|49|91618.73|0.05|0.01|N|O|1997-01-31|1997-03-13|1997-02-18|NONE|MAIL| ironic excuses use fluf +5829|17069|2072|6|17|16763.02|0.09|0.02|N|O|1997-04-10|1997-03-29|1997-04-22|COLLECT COD|AIR|after the furiously ironic ideas no +5829|77942|7943|7|27|51838.38|0.08|0.04|N|O|1997-02-25|1997-03-31|1997-03-03|DELIVER IN PERSON|AIR|ns about the excuses are c +5830|159261|6807|1|29|38287.54|0.10|0.02|R|F|1993-06-19|1993-05-10|1993-07-13|DELIVER IN PERSON|REG AIR|y bold excuses +5831|190330|331|1|2|2840.66|0.10|0.01|N|O|1997-02-09|1997-01-20|1997-03-07|TAKE BACK RETURN|TRUCK|quickly silent req +5831|73475|8490|2|33|47799.51|0.04|0.03|N|O|1996-11-20|1997-01-18|1996-12-18|TAKE BACK RETURN|MAIL| instructions wake. slyly sil +5831|81622|4131|3|6|9621.72|0.05|0.07|N|O|1997-01-29|1997-01-14|1997-02-09|NONE|MAIL|ly ironic accounts nag pendin +5831|12962|7965|4|46|86248.16|0.06|0.02|N|O|1997-02-24|1997-01-18|1997-03-02|COLLECT COD|MAIL|ly final pa +5831|42828|2829|5|37|65520.34|0.05|0.01|N|O|1997-01-17|1997-02-08|1997-02-01|NONE|FOB|uriously even requests +5856|3680|1181|1|1|1583.68|0.03|0.02|A|F|1994-12-29|1995-01-07|1995-01-10|TAKE BACK RETURN|MAIL|tly. special deposits wake blithely even +5856|34305|9312|2|35|43375.50|0.09|0.02|R|F|1994-11-24|1994-12-23|1994-11-30|COLLECT COD|AIR|excuses. finally ir +5856|152739|2740|3|39|69877.47|0.05|0.03|A|F|1995-01-18|1995-01-11|1995-01-19|DELIVER IN PERSON|TRUCK|uickly quickly fluffy in +5857|57226|7227|1|25|29580.50|0.03|0.02|N|O|1997-12-02|1997-12-17|1997-12-08|DELIVER IN PERSON|REG AIR|ding platelets. pending excu +5857|194769|2327|2|50|93188.00|0.06|0.07|N|O|1997-12-04|1997-12-16|1997-12-20|NONE|TRUCK|y regular d +5857|67860|5379|3|1|1827.86|0.03|0.01|N|O|1998-02-01|1997-12-09|1998-02-20|TAKE BACK RETURN|SHIP|instructions detect final reques +5857|117998|510|4|12|24191.88|0.03|0.08|N|O|1998-01-24|1997-12-27|1998-02-10|TAKE BACK RETURN|AIR|counts. express, final +5857|191260|3780|5|14|18917.64|0.07|0.07|N|O|1997-12-10|1998-01-06|1998-01-04|TAKE BACK RETURN|TRUCK|ffily pendin +5857|92862|5372|6|49|90888.14|0.00|0.04|N|O|1998-01-23|1997-12-12|1998-01-28|DELIVER IN PERSON|REG AIR|egular pinto beans +5858|120832|8369|1|20|37056.60|0.02|0.06|A|F|1992-07-23|1992-08-26|1992-07-24|COLLECT COD|SHIP|uffily unusual pinto beans sleep +5858|15003|5004|2|36|33048.00|0.00|0.05|A|F|1992-09-25|1992-08-16|1992-10-11|NONE|SHIP|osits wake quickly quickly sile +5858|147996|511|3|7|14307.93|0.08|0.02|A|F|1992-10-07|1992-08-16|1992-10-15|TAKE BACK RETURN|REG AIR|. doggedly regular packages use pendin +5858|163490|1039|4|46|71460.54|0.07|0.06|R|F|1992-09-07|1992-10-06|1992-10-06|DELIVER IN PERSON|MAIL|posits withi +5858|160181|5214|5|18|22341.24|0.00|0.07|A|F|1992-11-05|1992-10-08|1992-12-03|NONE|TRUCK|al excuses. bold +5858|153937|8968|6|7|13936.51|0.04|0.00|A|F|1992-09-14|1992-10-01|1992-10-01|TAKE BACK RETURN|RAIL|dly pending ac +5858|10709|3211|7|50|80985.00|0.06|0.00|R|F|1992-07-20|1992-10-07|1992-07-25|NONE|TRUCK|r the ironic ex +5859|174988|23|1|50|103149.00|0.07|0.01|N|O|1997-07-08|1997-06-20|1997-07-27|COLLECT COD|MAIL|ly regular deposits use. ironic +5859|8773|6274|2|17|28590.09|0.03|0.03|N|O|1997-05-15|1997-06-30|1997-05-26|DELIVER IN PERSON|AIR|ly ironic requests. quickly unusual pin +5859|45701|8206|3|33|54341.10|0.10|0.04|N|O|1997-07-08|1997-06-22|1997-07-18|TAKE BACK RETURN|TRUCK|eposits unwind furiously final pinto bea +5859|92269|2270|4|40|50450.40|0.09|0.02|N|O|1997-08-05|1997-06-17|1997-08-20|NONE|REG AIR|l dependenci +5859|152689|7720|5|35|60958.80|0.00|0.08|N|O|1997-05-28|1997-07-14|1997-06-15|COLLECT COD|TRUCK|egular acco +5859|43446|3447|6|9|12504.96|0.01|0.02|N|O|1997-06-15|1997-06-06|1997-06-20|NONE|RAIL|ges boost quickly. blithely r +5859|190127|7685|7|27|32862.24|0.05|0.08|N|O|1997-07-30|1997-07-08|1997-08-08|NONE|MAIL| across th +5860|50168|7684|1|10|11181.60|0.04|0.04|A|F|1992-03-11|1992-03-30|1992-03-31|NONE|MAIL|ual patterns try to eat carefully above +5861|190867|8425|1|32|62651.52|0.00|0.03|N|O|1997-05-27|1997-05-29|1997-05-28|TAKE BACK RETURN|MAIL|nt asymptotes. carefully express request +5861|85611|628|2|6|9579.66|0.10|0.03|N|O|1997-07-28|1997-05-18|1997-08-24|TAKE BACK RETURN|TRUCK|olites. slyly +5862|112061|4573|1|4|4292.24|0.09|0.06|N|O|1997-06-04|1997-04-26|1997-06-19|NONE|TRUCK|yly silent deposit +5862|1334|6335|2|29|35824.57|0.03|0.05|N|O|1997-04-02|1997-04-16|1997-04-04|NONE|FOB|e fluffily. furiously +5863|160562|3079|1|45|73015.20|0.07|0.06|A|F|1993-12-19|1994-01-25|1994-01-05|NONE|REG AIR| deposits are ab +5863|159369|1885|2|21|29995.56|0.09|0.03|R|F|1994-01-13|1994-01-09|1994-01-28|DELIVER IN PERSON|FOB|atelets nag blithely furi +5888|61291|8810|1|46|57605.34|0.02|0.00|N|O|1996-11-18|1996-11-05|1996-12-08|TAKE BACK RETURN|FOB|yly final accounts hag +5888|111595|1596|2|24|38558.16|0.03|0.01|N|O|1996-11-07|1996-11-30|1996-11-20|COLLECT COD|SHIP|ing to the spe +5889|76129|8637|1|17|18787.04|0.09|0.02|N|O|1995-07-01|1995-08-12|1995-07-25|NONE|AIR|blithely pending packages. flu +5890|112221|2222|1|38|46862.36|0.01|0.08|A|F|1993-02-14|1992-12-09|1993-02-27|COLLECT COD|FOB| accounts. carefully final asymptotes +5891|84905|4906|1|22|41577.80|0.00|0.06|R|F|1993-01-01|1993-02-18|1993-01-14|DELIVER IN PERSON|TRUCK|iresias cajole deposits. special, ir +5891|185580|8099|2|9|14990.22|0.03|0.07|R|F|1993-01-20|1993-02-27|1993-02-10|COLLECT COD|REG AIR|cajole carefully +5891|29674|4679|3|10|16036.70|0.08|0.01|A|F|1993-04-14|1993-02-07|1993-04-15|DELIVER IN PERSON|RAIL|nding requests. b +5892|147722|7723|1|7|12388.04|0.02|0.03|N|O|1995-06-26|1995-07-18|1995-07-25|COLLECT COD|AIR|e furiously. quickly even deposits da +5892|149926|7469|2|37|73109.04|0.09|0.06|N|O|1995-08-12|1995-06-11|1995-09-05|NONE|REG AIR|maintain. bold, expre +5892|2064|2065|3|28|27049.68|0.03|0.06|N|O|1995-08-16|1995-07-06|1995-08-22|DELIVER IN PERSON|MAIL|ithely unusual accounts will have to integ +5892|74798|4799|4|23|40774.17|0.08|0.04|R|F|1995-05-18|1995-07-06|1995-05-29|COLLECT COD|MAIL| foxes nag slyly about the qui +5893|133707|1247|1|43|74850.10|0.05|0.02|R|F|1992-11-02|1992-09-27|1992-11-21|TAKE BACK RETURN|RAIL|s. regular courts above the carefully silen +5893|1868|9369|2|2|3539.72|0.10|0.04|R|F|1992-07-18|1992-09-10|1992-08-12|NONE|RAIL|ckages wake sly +5894|7312|4813|1|23|28044.13|0.04|0.08|A|F|1994-09-05|1994-10-27|1994-09-13|NONE|TRUCK| furiously even deposits haggle alw +5894|78446|3461|2|48|68373.12|0.04|0.08|A|F|1994-09-04|1994-11-03|1994-09-17|NONE|TRUCK| asymptotes among the blithely silent +5895|14728|7230|1|38|62423.36|0.05|0.08|N|O|1997-04-05|1997-03-06|1997-05-03|DELIVER IN PERSON|RAIL|ts are furiously. regular, final excuses +5895|121538|1539|2|47|73297.91|0.04|0.06|N|O|1997-04-27|1997-03-17|1997-05-07|DELIVER IN PERSON|AIR|r packages wake carefull +5895|83712|1237|3|49|83089.79|0.03|0.07|N|O|1997-03-15|1997-02-17|1997-04-04|NONE|TRUCK|permanent foxes. packages +5895|145714|5715|4|31|54551.01|0.03|0.01|N|O|1997-03-03|1997-03-30|1997-03-08|TAKE BACK RETURN|TRUCK| final deposits nod slyly careful +5895|199172|9173|5|20|25423.40|0.07|0.00|N|O|1997-04-30|1997-02-07|1997-05-08|DELIVER IN PERSON|AIR|gular deposits wake blithely carefully fin +5895|77733|2748|6|15|25660.95|0.08|0.08|N|O|1997-04-19|1997-03-09|1997-05-13|TAKE BACK RETURN|RAIL|silent package +5920|186069|6070|1|50|57753.00|0.06|0.00|A|F|1995-03-13|1995-01-03|1995-03-31|TAKE BACK RETURN|RAIL|across the carefully pending platelets +5920|57793|7794|2|24|42018.96|0.01|0.05|A|F|1994-12-28|1995-01-21|1994-12-31|DELIVER IN PERSON|FOB|fully regular dolphins. furiousl +5920|116952|9464|3|2|3937.90|0.08|0.07|A|F|1995-02-18|1995-01-13|1995-03-04|NONE|SHIP| evenly spe +5920|11323|8827|4|28|34560.96|0.06|0.02|R|F|1994-12-17|1995-02-13|1994-12-31|NONE|SHIP|le slyly slyly even deposits. f +5920|99165|6693|5|42|48894.72|0.09|0.08|A|F|1994-12-18|1995-01-07|1995-01-14|COLLECT COD|AIR|lar, ironic dependencies sno +5921|98016|5544|1|44|44616.44|0.07|0.01|R|F|1994-07-14|1994-06-30|1994-07-15|NONE|TRUCK|ain about the special +5921|145670|699|2|25|42891.75|0.06|0.01|A|F|1994-05-19|1994-06-15|1994-06-17|COLLECT COD|TRUCK|nd the slyly regular deposits. quick +5921|67177|2190|3|17|19450.89|0.06|0.01|R|F|1994-05-20|1994-05-26|1994-05-23|NONE|FOB|final asymptotes. even packages boost +5921|27331|2336|4|26|32716.58|0.03|0.04|A|F|1994-05-03|1994-07-06|1994-05-06|NONE|AIR|hy dependenc +5921|142246|4761|5|41|52817.84|0.04|0.02|R|F|1994-04-13|1994-05-31|1994-04-26|DELIVER IN PERSON|AIR|nusual, regular theodol +5921|114421|4422|6|5|7177.10|0.02|0.00|R|F|1994-06-01|1994-05-07|1994-06-10|COLLECT COD|TRUCK|eas cajole across the final, fi +5922|195631|3189|1|9|15539.67|0.07|0.00|N|O|1996-12-04|1997-01-20|1996-12-08|DELIVER IN PERSON|RAIL|haggle slyly even packages. packages +5922|156595|1626|2|37|61108.83|0.01|0.04|N|O|1996-12-19|1996-12-16|1997-01-15|COLLECT COD|RAIL|s wake slyly. requests cajole furiously asy +5922|89515|4532|3|35|52657.85|0.08|0.00|N|O|1996-12-12|1997-01-21|1997-01-01|DELIVER IN PERSON|SHIP|accounts. regu +5922|65048|5049|4|13|13169.52|0.08|0.07|N|O|1997-03-08|1996-12-26|1997-04-03|DELIVER IN PERSON|FOB|sly special accounts wake ironically. +5922|56428|8934|5|39|53992.38|0.04|0.07|N|O|1997-03-04|1997-01-17|1997-03-25|TAKE BACK RETURN|SHIP|e of the instructions. quick +5922|178810|1328|6|10|18888.10|0.04|0.01|N|O|1997-02-23|1996-12-26|1997-03-04|NONE|REG AIR|sly regular deposits haggle quickly ins +5923|176934|6935|1|27|54295.11|0.08|0.03|N|O|1997-08-16|1997-06-27|1997-08-29|DELIVER IN PERSON|RAIL|arefully i +5923|118577|1089|2|42|67013.94|0.01|0.08|N|O|1997-09-16|1997-07-23|1997-09-27|COLLECT COD|REG AIR|y regular theodolites w +5923|107597|5128|3|2|3209.18|0.06|0.05|N|O|1997-06-19|1997-07-31|1997-06-28|TAKE BACK RETURN|TRUCK|express patterns. even deposits +5923|173158|5676|4|46|56632.90|0.05|0.04|N|O|1997-07-29|1997-07-23|1997-08-23|COLLECT COD|SHIP|nto beans cajole blithe +5923|58535|3546|5|35|52273.55|0.04|0.05|N|O|1997-07-21|1997-07-11|1997-08-01|DELIVER IN PERSON|AIR|sts affix unusual, final requests. request +5924|175145|180|1|38|46365.32|0.06|0.05|N|O|1995-12-17|1995-12-11|1996-01-06|TAKE BACK RETURN|AIR|ions cajole carefully along the +5924|52349|4855|2|49|63765.66|0.04|0.00|N|O|1995-10-25|1995-12-11|1995-11-08|NONE|MAIL|inly final excuses. blithely regular requ +5924|16705|6706|3|24|38920.80|0.09|0.08|N|O|1996-01-12|1995-12-13|1996-01-25|COLLECT COD|REG AIR| use carefully. special, e +5925|86543|9052|1|42|64240.68|0.05|0.02|N|O|1996-03-05|1996-01-13|1996-03-10|COLLECT COD|SHIP|to the furiously +5925|124966|9991|2|31|61719.76|0.03|0.03|N|O|1996-01-02|1995-12-14|1996-01-07|TAKE BACK RETURN|FOB|e slyly. furiously regular deposi +5925|88288|3305|3|50|63814.00|0.03|0.04|N|O|1996-02-14|1996-01-10|1996-02-15|NONE|TRUCK|es. stealthily express pains print bli +5925|53309|8320|4|30|37869.00|0.02|0.07|N|O|1996-02-21|1996-02-11|1996-03-10|NONE|TRUCK| the packa +5925|159746|9747|5|41|74035.34|0.00|0.06|N|O|1996-02-03|1995-12-24|1996-02-20|NONE|SHIP| across the pending deposits nag caref +5925|49812|7325|6|48|84566.88|0.02|0.00|N|O|1996-02-03|1996-01-19|1996-03-04|DELIVER IN PERSON|REG AIR| haggle after the fo +5926|89216|4233|1|8|9641.68|0.02|0.00|R|F|1994-07-17|1994-07-20|1994-08-11|COLLECT COD|MAIL|gle furiously express foxes. bo +5926|49773|7286|2|27|46514.79|0.09|0.05|A|F|1994-07-05|1994-08-11|1994-08-02|DELIVER IN PERSON|MAIL|ironic requests +5926|126721|6722|3|46|80395.12|0.01|0.03|R|F|1994-09-05|1994-08-12|1994-09-11|COLLECT COD|RAIL|ts integrate. courts haggl +5926|189693|7248|4|23|41001.87|0.01|0.02|A|F|1994-07-23|1994-08-10|1994-07-27|DELIVER IN PERSON|FOB|ickly special packages among +5927|89541|2050|1|44|67343.76|0.04|0.05|N|O|1997-11-29|1997-11-21|1997-12-13|DELIVER IN PERSON|TRUCK|rding to the special, final decoy +5927|114570|9593|2|8|12676.56|0.04|0.05|N|O|1997-09-24|1997-11-15|1997-10-22|TAKE BACK RETURN|SHIP|ilent dependencies nod c +5927|166058|8575|3|32|35969.60|0.10|0.07|N|O|1997-12-26|1997-10-27|1997-12-31|COLLECT COD|AIR|telets. carefully bold accounts was +5952|199810|2330|1|49|93580.69|0.10|0.02|N|O|1997-06-30|1997-07-10|1997-07-02|COLLECT COD|AIR|e furiously regular +5952|190128|7686|2|11|13399.32|0.10|0.05|N|O|1997-05-13|1997-06-04|1997-05-27|DELIVER IN PERSON|FOB|y nag blithely aga +5952|70338|339|3|43|56258.19|0.01|0.01|N|O|1997-06-29|1997-06-06|1997-07-15|COLLECT COD|MAIL|posits sleep furiously quickly final p +5952|157819|2850|4|23|43166.63|0.00|0.07|N|O|1997-05-13|1997-06-27|1997-05-20|NONE|TRUCK|e blithely packages. eve +5953|128103|8104|1|36|40719.60|0.03|0.00|R|F|1992-05-28|1992-06-24|1992-05-29|DELIVER IN PERSON|FOB| cajole furio +5953|12029|4531|2|34|31994.68|0.03|0.04|A|F|1992-05-04|1992-06-12|1992-06-02|NONE|RAIL|hockey players use furiously against th +5953|161015|6048|3|5|5380.05|0.07|0.06|A|F|1992-04-10|1992-04-27|1992-04-14|NONE|SHIP|s. blithely +5953|168308|825|4|23|31654.90|0.09|0.02|R|F|1992-06-05|1992-06-03|1992-06-29|TAKE BACK RETURN|FOB|he silent ideas. silent foxes po +5954|146706|4249|1|8|14021.60|0.03|0.00|A|F|1993-03-27|1993-01-22|1993-04-04|TAKE BACK RETURN|AIR|unusual th +5954|80235|2744|2|40|48609.20|0.02|0.01|A|F|1992-12-30|1993-01-16|1993-01-09|COLLECT COD|RAIL|iously ironic deposits after +5954|93387|915|3|20|27607.60|0.09|0.07|A|F|1992-12-25|1993-02-05|1992-12-31|COLLECT COD|REG AIR| accounts wake carefu +5954|144672|2215|4|20|34333.40|0.00|0.01|R|F|1993-02-27|1993-01-04|1993-03-08|NONE|TRUCK|ke furiously blithely special packa +5954|99780|7308|5|35|62292.30|0.04|0.06|A|F|1993-03-17|1993-02-06|1993-04-10|NONE|SHIP|tions maintain slyly. furious +5954|192029|4549|6|39|43719.78|0.04|0.08|A|F|1993-02-27|1993-02-25|1993-03-29|DELIVER IN PERSON|REG AIR| always regular dolphins. furiously p +5955|139375|4402|1|14|19801.18|0.08|0.08|N|O|1995-06-22|1995-05-23|1995-06-24|DELIVER IN PERSON|TRUCK| unusual, bold theodolit +5955|61553|9072|2|15|22718.25|0.08|0.07|R|F|1995-04-22|1995-05-28|1995-04-27|NONE|FOB|y final accounts above the regu +5955|111196|6219|3|40|48287.60|0.03|0.00|R|F|1995-04-01|1995-06-11|1995-04-27|NONE|FOB|oss the fluffily regular +5956|154047|6563|1|10|11010.40|0.04|0.05|N|O|1998-07-27|1998-07-04|1998-08-21|NONE|MAIL|ic packages am +5956|54179|1695|2|23|26062.91|0.08|0.03|N|O|1998-06-06|1998-07-10|1998-06-15|DELIVER IN PERSON|RAIL|ly slyly special +5956|174834|7352|3|47|89715.01|0.04|0.06|N|O|1998-09-06|1998-06-29|1998-09-18|TAKE BACK RETURN|MAIL|lyly express theodol +5956|19995|7499|4|40|76599.60|0.09|0.05|N|O|1998-06-11|1998-07-19|1998-06-21|NONE|MAIL|final theodolites sleep carefully ironic c +5957|14617|7119|1|37|56669.57|0.07|0.00|A|F|1994-04-18|1994-02-19|1994-05-11|NONE|AIR| ideas use ruthlessly. +5957|58726|3737|2|46|77497.12|0.04|0.08|A|F|1994-01-23|1994-01-30|1994-02-07|NONE|SHIP|platelets. furiously unusual requests +5957|1377|6378|3|17|21732.29|0.01|0.01|A|F|1994-01-24|1994-02-16|1994-02-08|TAKE BACK RETURN|SHIP|. final, pending packages +5957|131499|6526|4|29|44384.21|0.01|0.03|R|F|1994-02-24|1994-03-04|1994-03-08|COLLECT COD|REG AIR|sits. final, even asymptotes cajole quickly +5957|87262|4787|5|40|49970.40|0.04|0.04|R|F|1994-01-07|1994-02-05|1994-01-26|DELIVER IN PERSON|SHIP|ironic asymptotes sleep blithely again +5957|5079|80|6|41|40346.87|0.10|0.07|R|F|1994-03-25|1994-02-20|1994-03-31|DELIVER IN PERSON|MAIL|es across the regular requests maint +5957|158431|5977|7|32|47661.76|0.10|0.07|A|F|1994-03-05|1994-02-20|1994-03-09|NONE|TRUCK| boost carefully across the +5958|148834|6377|1|33|62133.39|0.02|0.04|N|O|1995-09-24|1995-12-12|1995-10-05|COLLECT COD|MAIL|lar, regular accounts wake furi +5958|42932|7941|2|23|43123.39|0.03|0.04|N|O|1995-09-26|1995-10-19|1995-09-27|COLLECT COD|SHIP|regular requests. bold, bold deposits unwin +5958|152606|7637|3|42|69661.20|0.10|0.00|N|O|1995-12-12|1995-10-19|1996-01-09|NONE|AIR|n accounts. final, ironic packages +5958|38433|8434|4|18|24685.74|0.04|0.05|N|O|1995-12-02|1995-10-17|1995-12-22|COLLECT COD|FOB|regular requests haggle +5958|131786|4300|5|32|58168.96|0.06|0.00|N|O|1995-09-20|1995-12-10|1995-10-14|COLLECT COD|REG AIR|e carefully special theodolites. carefully +5959|134156|6670|1|49|58317.35|0.07|0.03|R|F|1992-07-16|1992-08-09|1992-08-14|DELIVER IN PERSON|SHIP|usual packages haggle slyly pi +5959|146297|6298|2|17|22835.93|0.09|0.07|R|F|1992-06-10|1992-07-06|1992-06-23|COLLECT COD|MAIL|ackages. blithely ex +5959|4379|4380|3|4|5133.48|0.04|0.03|R|F|1992-06-14|1992-07-05|1992-07-01|NONE|MAIL|gular requests ar +5959|195921|5922|4|13|26219.96|0.03|0.00|A|F|1992-07-29|1992-07-13|1992-08-20|COLLECT COD|SHIP|ar forges. deposits det +5959|39979|7489|5|37|71001.89|0.04|0.01|R|F|1992-06-05|1992-07-18|1992-06-29|NONE|TRUCK|endencies. brai +5959|118109|621|6|35|39448.50|0.03|0.00|A|F|1992-05-27|1992-06-19|1992-06-23|NONE|TRUCK|ely silent deposits. +5959|42154|4659|7|47|51519.05|0.02|0.01|R|F|1992-08-28|1992-07-24|1992-09-09|TAKE BACK RETURN|RAIL|deposits. slyly special cou +5984|69454|6973|1|13|18504.85|0.06|0.07|R|F|1994-10-16|1994-09-06|1994-11-11|NONE|MAIL|lar platelets. f +5984|101208|1209|2|25|30230.00|0.05|0.08|R|F|1994-10-06|1994-07-21|1994-10-28|COLLECT COD|RAIL|gular accounts. even packages nag slyly +5984|321|2822|3|8|9770.56|0.10|0.00|R|F|1994-09-17|1994-08-28|1994-09-25|COLLECT COD|RAIL|its. express, +5984|189708|9709|4|35|62919.50|0.00|0.01|A|F|1994-08-25|1994-08-05|1994-08-31|DELIVER IN PERSON|SHIP|le fluffily regula +5985|85717|8226|1|4|6810.84|0.02|0.02|A|F|1995-05-04|1995-04-01|1995-05-17|DELIVER IN PERSON|MAIL|ole along the quickly slow d +5986|78789|6311|1|26|45962.28|0.00|0.00|R|F|1992-08-10|1992-05-23|1992-08-24|TAKE BACK RETURN|SHIP|e fluffily ironic ideas. silent +5986|195254|7774|2|25|33731.25|0.03|0.06|A|F|1992-06-16|1992-07-17|1992-06-29|TAKE BACK RETURN|MAIL| instructions. slyly regular de +5986|29636|2139|3|1|1565.63|0.07|0.06|A|F|1992-05-21|1992-06-21|1992-05-24|DELIVER IN PERSON|REG AIR|fix quickly quickly final deposits. fluffil +5986|89590|7115|4|31|48967.29|0.00|0.03|A|F|1992-08-21|1992-06-29|1992-09-14|NONE|AIR|structions! furiously pending instructi +5986|135143|5144|5|6|7068.84|0.05|0.02|A|F|1992-07-16|1992-06-10|1992-07-29|DELIVER IN PERSON|RAIL|al foxes within the slyly speci diff --git a/src/test/regress/data/lineitem.2.data b/src/test/regress/data/lineitem.2.data new file mode 100644 index 000000000..d1031583b --- /dev/null +++ b/src/test/regress/data/lineitem.2.data @@ -0,0 +1,6000 @@ +8997|19353|9354|2|25|31808.75|0.05|0.03|R|F|1994-08-05|1994-09-29|1994-08-15|TAKE BACK RETURN|AIR| blithely asymptotes. +8997|57771|7772|3|11|19016.47|0.04|0.00|R|F|1994-09-12|1994-09-10|1994-09-19|NONE|RAIL|nic sheaves are +8997|149605|4634|4|1|1654.60|0.07|0.01|A|F|1994-10-13|1994-09-05|1994-10-21|NONE|REG AIR|theodolite +8997|195853|5854|5|33|64312.05|0.05|0.04|A|F|1994-09-02|1994-09-25|1994-09-19|NONE|MAIL|requests wake furiously. foxes d +8997|101036|1037|6|23|23851.69|0.00|0.01|R|F|1994-08-20|1994-09-23|1994-09-18|DELIVER IN PERSON|TRUCK|quickly regular +8998|119794|2306|1|47|85248.13|0.01|0.07|A|F|1993-01-22|1993-02-21|1993-02-09|DELIVER IN PERSON|RAIL|about the sometimes ironic excuse +8998|166895|1928|2|37|72589.93|0.02|0.05|A|F|1993-02-21|1993-03-24|1993-03-23|COLLECT COD|AIR|ay fluffily final pinto beans! bli +8998|3110|5611|3|12|12157.32|0.04|0.02|R|F|1993-03-04|1993-02-08|1993-03-27|NONE|AIR| engage furiously blithely ironic +8998|58188|3199|4|15|17192.70|0.03|0.01|A|F|1993-01-19|1993-02-27|1993-01-23|DELIVER IN PERSON|RAIL|gular Tiresias kindle +8999|107599|7600|1|21|33738.39|0.10|0.06|A|F|1994-08-23|1994-08-12|1994-08-27|TAKE BACK RETURN|FOB|among the slyly +8999|8987|6488|2|48|91007.04|0.02|0.06|A|F|1994-10-04|1994-08-16|1994-10-24|TAKE BACK RETURN|FOB|nts sleep quickl +8999|38529|1033|3|26|38155.52|0.09|0.03|R|F|1994-09-03|1994-08-03|1994-10-03|DELIVER IN PERSON|FOB|r instructions. deposits use furiously aga +8999|150058|5089|4|9|9972.45|0.00|0.06|A|F|1994-08-24|1994-08-18|1994-08-31|TAKE BACK RETURN|AIR|ost blithely final, regu +9024|186958|6959|1|21|42943.95|0.05|0.06|A|F|1992-09-11|1992-08-30|1992-09-17|DELIVER IN PERSON|MAIL|the blithel +9024|189463|1982|2|12|18629.52|0.04|0.08|A|F|1992-09-21|1992-07-19|1992-10-08|DELIVER IN PERSON|AIR|ven deposits +9024|95896|5897|3|19|35945.91|0.10|0.08|A|F|1992-07-12|1992-08-14|1992-07-20|NONE|SHIP|deposits use ironic requests. final re +9024|119442|6976|4|46|67226.24|0.10|0.05|A|F|1992-06-27|1992-08-22|1992-07-15|TAKE BACK RETURN|RAIL|fluffy requests sleep +9024|58677|8678|5|31|50705.77|0.05|0.03|A|F|1992-09-28|1992-08-20|1992-10-19|NONE|TRUCK|xpress forges? final platelets +9024|174695|7213|6|37|65478.53|0.03|0.08|A|F|1992-08-25|1992-08-03|1992-09-17|COLLECT COD|TRUCK|posits cajole blithely alon +9024|84320|4321|7|27|35216.64|0.06|0.07|A|F|1992-09-27|1992-07-16|1992-10-14|COLLECT COD|SHIP|g asymptotes. +9025|159410|9411|1|18|26449.38|0.04|0.01|A|F|1994-06-14|1994-06-28|1994-06-19|TAKE BACK RETURN|TRUCK|ffily final excuses wake sl +9025|674|675|2|15|23620.05|0.00|0.08|R|F|1994-08-26|1994-07-06|1994-09-21|TAKE BACK RETURN|RAIL|deposits. slyly unusual d +9025|127232|7233|3|49|61702.27|0.08|0.07|A|F|1994-09-15|1994-06-20|1994-10-04|TAKE BACK RETURN|FOB|print across the fluffily silent account +9026|177512|2547|1|21|33379.71|0.04|0.03|N|O|1996-10-02|1996-09-06|1996-10-25|NONE|MAIL|ly unusual as +9026|35171|7675|2|1|1106.17|0.05|0.08|N|O|1996-10-22|1996-10-13|1996-11-07|NONE|AIR| pinto beans. ironi +9026|102332|4843|3|28|37361.24|0.03|0.08|N|O|1996-09-14|1996-09-21|1996-10-12|NONE|RAIL|te fluffily regul +9027|7068|4569|1|39|38027.34|0.00|0.03|N|O|1995-09-26|1995-12-02|1995-10-01|DELIVER IN PERSON|MAIL|sts. furiously r +9027|175635|3187|2|44|75267.72|0.02|0.03|N|O|1995-10-01|1995-11-29|1995-10-23|TAKE BACK RETURN|FOB|ve furiously. furiously +9027|90479|5498|3|24|35267.28|0.05|0.04|N|O|1995-11-26|1995-11-09|1995-12-15|NONE|RAIL|. slyly unus +9028|53205|721|1|45|52119.00|0.06|0.04|R|F|1994-04-01|1994-01-28|1994-04-09|COLLECT COD|SHIP|furiously furiously +9029|76225|8733|1|40|48048.80|0.03|0.05|R|F|1992-12-15|1993-01-13|1993-01-02|NONE|FOB|sly ironic pinto beans sl +9029|107623|7624|2|11|17936.82|0.06|0.08|A|F|1993-03-01|1992-12-28|1993-03-15|TAKE BACK RETURN|REG AIR|heodolites. fluffily e +9030|159615|9616|1|28|46889.08|0.09|0.08|N|O|1998-09-02|1998-08-16|1998-09-10|DELIVER IN PERSON|TRUCK|ace of the sl +9030|36087|6088|2|2|2046.16|0.09|0.03|N|O|1998-08-19|1998-09-14|1998-09-18|DELIVER IN PERSON|TRUCK|es wake among the slyly regular ideas +9030|112873|2874|3|43|81092.41|0.00|0.05|N|O|1998-08-27|1998-09-02|1998-08-31|COLLECT COD|MAIL|posits. qu +9030|48049|3058|4|5|4985.20|0.10|0.08|N|O|1998-07-20|1998-09-17|1998-07-28|COLLECT COD|RAIL|ove the pinto bean +9030|150168|169|5|47|57253.52|0.00|0.04|N|O|1998-09-29|1998-09-24|1998-10-13|COLLECT COD|AIR|fily unusual foxes! flu +9030|62890|409|6|38|70409.82|0.04|0.07|N|O|1998-09-03|1998-10-04|1998-10-02|TAKE BACK RETURN|MAIL|ct furiousl +9031|181160|1161|1|5|6205.80|0.02|0.07|R|F|1994-01-24|1994-02-11|1994-02-10|TAKE BACK RETURN|SHIP|furiously. furio +9031|146553|6554|2|48|76778.40|0.06|0.07|R|F|1994-04-05|1994-03-14|1994-04-18|DELIVER IN PERSON|REG AIR|accounts before the even pinto be +9031|105141|7652|3|19|21776.66|0.10|0.03|R|F|1994-03-18|1994-02-17|1994-04-10|TAKE BACK RETURN|RAIL|ong the doggedly special deposits. +9031|104337|1868|4|21|28167.93|0.09|0.08|R|F|1994-03-07|1994-02-24|1994-03-22|COLLECT COD|FOB|ackages cajole slyly +9031|187842|361|5|33|63684.72|0.01|0.03|A|F|1994-04-15|1994-03-12|1994-05-06|COLLECT COD|MAIL|ic deposits ca +9031|55903|3419|6|49|91086.10|0.10|0.00|A|F|1994-02-21|1994-03-20|1994-03-08|COLLECT COD|RAIL|lar packages. b +9031|159991|2507|7|24|49223.76|0.03|0.00|A|F|1993-12-31|1994-03-11|1994-01-29|DELIVER IN PERSON|SHIP|y final accounts detect. q +9056|159443|1959|1|34|51082.96|0.07|0.07|N|O|1996-09-20|1996-10-18|1996-09-30|DELIVER IN PERSON|REG AIR|nal accounts nag furiously +9056|152800|5316|2|43|79670.40|0.01|0.05|N|O|1996-10-24|1996-10-06|1996-11-19|TAKE BACK RETURN|AIR|anent theodolites! furiously sil +9056|97264|2283|3|19|23963.94|0.06|0.05|N|O|1996-09-09|1996-10-19|1996-09-20|NONE|MAIL| doubt abo +9056|109236|9237|4|5|6226.15|0.02|0.06|N|O|1996-10-23|1996-09-19|1996-11-08|NONE|REG AIR|uickly express packages haggle bl +9056|122746|7771|5|13|22993.62|0.03|0.07|N|O|1996-08-28|1996-09-24|1996-09-12|DELIVER IN PERSON|FOB|nic packages boost furiously unusua +9057|24643|4644|1|35|54867.40|0.07|0.05|R|F|1994-11-06|1995-01-15|1994-11-18|NONE|SHIP|attainments. slyly final requests cajo +9057|168578|3611|2|41|67509.37|0.09|0.03|A|F|1995-01-26|1995-01-24|1995-02-09|DELIVER IN PERSON|REG AIR|fter the slyly dogged excuses. ironic, b +9057|90016|7544|3|45|45270.45|0.02|0.01|A|F|1994-12-08|1995-01-10|1994-12-27|NONE|TRUCK|y even decoys sleep. slyly +9057|85561|3086|4|17|26291.52|0.06|0.00|A|F|1995-03-03|1994-12-29|1995-03-29|NONE|SHIP|ndencies use carefully along +9057|14681|2185|5|17|27126.56|0.05|0.06|R|F|1995-01-22|1995-01-16|1995-02-12|COLLECT COD|FOB|carefully regular frets. furiously even a +9057|132402|2403|6|9|12909.60|0.07|0.06|R|F|1994-12-30|1994-12-27|1995-01-07|DELIVER IN PERSON|REG AIR| after the slyly bold accounts a +9057|75919|8427|7|48|90955.68|0.01|0.05|R|F|1995-02-04|1994-12-31|1995-02-19|DELIVER IN PERSON|FOB| maintain slyly. ca +9058|158834|3865|1|41|77606.03|0.07|0.08|A|F|1993-09-11|1993-09-25|1993-09-17|COLLECT COD|SHIP|uffily even instruction +9058|122910|7935|2|2|3865.82|0.08|0.00|A|F|1993-09-02|1993-09-26|1993-10-01|TAKE BACK RETURN|AIR|ely. courts are? furiou +9059|152748|5264|1|50|90037.00|0.06|0.03|N|O|1996-08-11|1996-09-17|1996-09-02|NONE|FOB|e furiously close ideas. s +9059|31290|6297|2|20|24425.80|0.02|0.01|N|O|1996-11-22|1996-10-06|1996-11-23|TAKE BACK RETURN|MAIL|usly pending packages. platelets a +9059|89746|2255|3|29|50336.46|0.10|0.03|N|O|1996-09-06|1996-10-14|1996-09-10|NONE|TRUCK| the even requests. slyly +9059|153935|1481|4|24|47734.32|0.05|0.08|N|O|1996-09-23|1996-10-18|1996-10-03|TAKE BACK RETURN|AIR|thy packages. blithely final packages haggl +9059|178283|5835|5|6|8167.68|0.00|0.04|N|O|1996-11-25|1996-10-15|1996-12-06|TAKE BACK RETURN|SHIP|ironic requests haggle. furiously pending +9060|166475|8992|1|11|16956.17|0.10|0.02|N|O|1996-06-21|1996-07-23|1996-07-02|COLLECT COD|REG AIR|luffily regular packages wake furiously +9060|131051|1052|2|12|12984.60|0.06|0.02|N|O|1996-09-02|1996-07-11|1996-09-07|NONE|MAIL| special courts. furiously even packages sl +9060|160989|8538|3|10|20499.80|0.04|0.07|N|O|1996-08-21|1996-08-01|1996-09-01|NONE|FOB|es cajole slyly unusual requests. slyly bol +9061|181110|6147|1|23|27395.53|0.00|0.08|N|O|1996-03-31|1996-02-27|1996-04-25|NONE|TRUCK|y express requests. furiously si +9061|110391|7925|2|24|33633.36|0.04|0.02|N|O|1996-04-08|1996-03-15|1996-05-02|NONE|RAIL|ic theodolites. regular, ir +9062|159691|7237|1|34|59523.46|0.09|0.03|R|F|1995-03-28|1995-05-07|1995-04-25|DELIVER IN PERSON|SHIP| regular theod +9062|125314|5315|2|13|17411.03|0.06|0.07|N|F|1995-06-08|1995-05-26|1995-06-22|NONE|SHIP|ckages are quickly quickly specia +9062|148561|6104|3|9|14486.04|0.04|0.07|N|O|1995-07-06|1995-05-24|1995-07-21|COLLECT COD|FOB|counts haggle someti +9062|54927|4928|4|46|86568.32|0.04|0.04|A|F|1995-03-22|1995-04-22|1995-04-03|TAKE BACK RETURN|MAIL|heodolites d +9062|144289|1832|5|50|66664.00|0.08|0.01|R|F|1995-03-28|1995-05-18|1995-04-23|TAKE BACK RETURN|AIR|ly unusual deposits cajole +9062|64034|6541|6|5|4990.15|0.00|0.03|R|F|1995-04-02|1995-06-02|1995-04-20|NONE|RAIL|ave to wake bli +9063|174926|2478|1|31|62028.52|0.06|0.06|N|O|1997-06-05|1997-04-29|1997-06-27|COLLECT COD|FOB|furiously requests. fina +9088|174809|7327|1|49|92306.20|0.09|0.00|A|F|1994-09-14|1994-08-30|1994-10-03|TAKE BACK RETURN|RAIL|ess deposits sleep always. carefu +9088|13094|8097|2|42|42297.78|0.02|0.02|A|F|1994-10-14|1994-09-06|1994-11-01|COLLECT COD|SHIP|ts integrate carefully according +9088|68532|3545|3|31|46516.43|0.09|0.08|A|F|1994-10-18|1994-09-10|1994-10-25|TAKE BACK RETURN|FOB|o the theodolites. pending foxes +9088|7666|167|4|13|20457.58|0.02|0.08|R|F|1994-09-20|1994-08-17|1994-10-06|NONE|REG AIR|yers. furiously ironic instru +9088|34183|1693|5|39|43570.02|0.08|0.02|R|F|1994-08-10|1994-08-31|1994-08-17|COLLECT COD|TRUCK|after the final packag +9089|104735|9756|1|28|48712.44|0.06|0.02|R|F|1993-06-23|1993-08-05|1993-07-17|COLLECT COD|SHIP|s integrate +9089|76004|8512|2|8|7840.00|0.05|0.08|A|F|1993-06-14|1993-07-31|1993-07-05|DELIVER IN PERSON|TRUCK| blithely even theodoli +9090|114007|9030|1|10|10210.00|0.10|0.05|N|O|1997-03-15|1997-02-14|1997-03-25|NONE|REG AIR|grate final, regul +9091|91081|3591|1|4|4288.32|0.04|0.06|R|F|1993-12-06|1994-01-08|1993-12-24|TAKE BACK RETURN|FOB|are across the p +9091|195833|3391|2|48|92583.84|0.09|0.01|R|F|1993-12-22|1994-01-29|1994-01-14|COLLECT COD|REG AIR|nts. furiously regular accounts +9091|155340|5341|3|36|50232.24|0.01|0.03|A|F|1993-12-12|1993-12-24|1994-01-08|DELIVER IN PERSON|TRUCK|ajole slyly +9091|194311|4312|4|18|25295.58|0.10|0.02|R|F|1994-02-14|1994-01-26|1994-02-19|COLLECT COD|SHIP|t the quickly even +9091|179349|6901|5|25|35708.50|0.01|0.00|A|F|1994-03-01|1993-12-25|1994-03-23|DELIVER IN PERSON|TRUCK|ess ideas boost +9091|115378|401|6|26|36227.62|0.06|0.04|R|F|1993-12-05|1994-02-02|1993-12-10|NONE|TRUCK|c requests above +9092|99552|7080|1|19|29479.45|0.03|0.07|A|F|1994-08-10|1994-09-15|1994-08-15|COLLECT COD|RAIL| regular packages. +9092|167146|2179|2|19|23049.66|0.04|0.01|R|F|1994-11-10|1994-10-14|1994-11-24|NONE|RAIL|fily above the final acco +9092|12987|5489|3|33|62699.34|0.03|0.05|R|F|1994-10-22|1994-10-08|1994-11-10|DELIVER IN PERSON|MAIL|ly final pinto beans sleep fluffily +9092|70885|5900|4|14|25982.32|0.03|0.01|A|F|1994-09-29|1994-10-03|1994-10-29|TAKE BACK RETURN|FOB| even packages wake a +9092|161570|9119|5|11|17947.27|0.05|0.04|R|F|1994-10-10|1994-09-14|1994-10-30|TAKE BACK RETURN|AIR|g to the quickly ironic asympt +9092|92123|7142|6|15|16726.80|0.00|0.08|A|F|1994-09-19|1994-09-17|1994-09-30|TAKE BACK RETURN|RAIL|lar accounts wake above the carefully exp +9092|105725|746|7|37|64036.64|0.05|0.00|A|F|1994-08-01|1994-09-25|1994-08-05|COLLECT COD|AIR|quests engage blithely across the bold t +9093|112141|9675|1|19|21909.66|0.02|0.02|N|O|1996-03-25|1996-02-11|1996-04-20|TAKE BACK RETURN|SHIP|riously bold theodolites? dep +9094|57706|5222|1|32|53238.40|0.04|0.03|N|O|1998-07-09|1998-08-19|1998-07-30|TAKE BACK RETURN|MAIL|y even theodolites sleep +9095|27289|9792|1|43|52300.04|0.01|0.00|N|O|1995-09-05|1995-08-30|1995-09-16|COLLECT COD|MAIL| sleep furiously express de +9120|156720|1751|1|5|8883.60|0.00|0.07|A|F|1992-08-03|1992-07-26|1992-08-21|COLLECT COD|MAIL|onic dinos. final packages cajo +9120|191829|1830|2|4|7683.28|0.06|0.04|A|F|1992-09-09|1992-08-04|1992-10-02|TAKE BACK RETURN|TRUCK|ld foxes eat above the regular, eve +9120|66777|1790|3|24|41850.48|0.03|0.04|R|F|1992-08-05|1992-08-18|1992-08-08|COLLECT COD|AIR|according to the quickly bold orbits +9120|104713|2244|4|21|36071.91|0.07|0.02|A|F|1992-07-03|1992-08-14|1992-07-16|COLLECT COD|TRUCK|riously thin packa +9120|102057|7078|5|15|15885.75|0.02|0.07|A|F|1992-10-04|1992-09-12|1992-10-27|NONE|SHIP| sauternes integrate. unusual, ironic ac +9120|59694|4705|6|22|36381.18|0.02|0.04|A|F|1992-07-19|1992-08-29|1992-07-27|DELIVER IN PERSON|RAIL|iously regular foxes must have to de +9120|62190|7203|7|6|6913.14|0.04|0.00|A|F|1992-08-05|1992-09-04|1992-08-14|COLLECT COD|FOB|aringly even instructions +9121|15157|160|1|49|52535.35|0.03|0.07|N|O|1996-07-24|1996-08-04|1996-08-01|NONE|AIR|ly above the qu +9121|140523|5552|2|30|46905.60|0.02|0.07|N|O|1996-10-31|1996-08-15|1996-11-20|DELIVER IN PERSON|RAIL|ld foxes. blithely ironic wa +9122|191935|9493|1|40|81077.20|0.06|0.00|N|O|1997-01-30|1997-02-10|1997-02-09|DELIVER IN PERSON|SHIP|ven requests are furio +9122|49033|9034|2|42|41245.26|0.03|0.07|N|O|1997-04-01|1997-01-19|1997-04-28|DELIVER IN PERSON|SHIP|its. carefu +9122|94903|7413|3|16|30366.40|0.06|0.04|N|O|1997-03-06|1997-01-24|1997-03-25|TAKE BACK RETURN|SHIP|uctions integrate busily along +9122|21812|1813|4|29|50280.49|0.04|0.07|N|O|1997-02-23|1997-02-26|1997-03-07|NONE|SHIP|instructions. regular accou +9122|177526|2561|5|28|44898.56|0.09|0.01|N|O|1997-03-22|1997-02-09|1997-04-20|NONE|TRUCK|y silent accounts against the dependenc +9123|156933|4479|1|5|9949.65|0.05|0.01|R|F|1993-07-07|1993-08-16|1993-07-29|NONE|AIR|lar, bold accounts use. +9123|162219|4736|2|32|40998.72|0.02|0.00|A|F|1993-08-04|1993-09-01|1993-08-27|NONE|FOB|ess deposits cajole a +9123|5727|728|3|7|11429.04|0.00|0.06|R|F|1993-07-20|1993-09-05|1993-08-01|DELIVER IN PERSON|AIR|ronic, bold deposits. +9123|52698|7709|4|2|3301.38|0.10|0.01|A|F|1993-08-10|1993-09-17|1993-08-31|COLLECT COD|AIR|sits. slyly express theodolites sno +9124|169074|1591|1|16|18289.12|0.04|0.07|N|O|1995-12-24|1996-01-10|1996-01-07|COLLECT COD|AIR|side of the fluffily even asym +9124|24359|9364|2|3|3850.05|0.04|0.02|N|O|1995-10-28|1995-12-13|1995-10-31|COLLECT COD|MAIL|to haggle blithely. blithely careful pint +9124|186459|6460|3|46|71090.70|0.03|0.08|N|O|1995-12-28|1995-12-08|1996-01-15|TAKE BACK RETURN|MAIL|ully bold packages. +9124|2555|5056|4|2|2915.10|0.07|0.02|N|O|1995-12-10|1995-12-31|1995-12-12|TAKE BACK RETURN|FOB| blithe packag +9124|134598|9625|5|19|31019.21|0.09|0.03|N|O|1995-11-13|1995-11-28|1995-12-05|TAKE BACK RETURN|SHIP|totes. blithely even accoun +9124|183982|9019|6|21|43385.58|0.07|0.03|N|O|1995-12-27|1995-12-16|1996-01-03|DELIVER IN PERSON|TRUCK|s thrash. fluffily busy acco +9125|188758|1277|1|5|9233.75|0.07|0.05|N|O|1998-07-11|1998-07-31|1998-07-21|TAKE BACK RETURN|MAIL|unts. bold, regular accounts wake. package +9125|46941|1950|2|8|15103.52|0.06|0.06|N|O|1998-08-01|1998-07-28|1998-08-25|TAKE BACK RETURN|TRUCK|lithely regular packa +9125|123102|5615|3|14|15751.40|0.08|0.07|N|O|1998-06-05|1998-08-05|1998-06-11|TAKE BACK RETURN|AIR|s. furiously regular platelets after the fi +9125|170828|5863|4|42|79750.44|0.05|0.04|N|O|1998-09-07|1998-08-20|1998-09-11|TAKE BACK RETURN|SHIP|lent theod +9125|90075|2585|5|11|11715.77|0.03|0.02|N|O|1998-06-06|1998-08-27|1998-06-08|COLLECT COD|REG AIR|efully express ex +9125|88097|5622|6|25|27127.25|0.09|0.03|N|O|1998-09-11|1998-07-30|1998-09-29|TAKE BACK RETURN|MAIL|nto beans. blithely spe +9125|37036|9540|7|26|25298.78|0.05|0.02|N|O|1998-07-16|1998-08-10|1998-07-18|DELIVER IN PERSON|SHIP| packages doubt carefully. regular +9126|58481|3492|1|28|40305.44|0.05|0.03|R|F|1995-01-05|1995-02-03|1995-01-26|TAKE BACK RETURN|SHIP|accounts sleep carefully. carefully final r +9126|73598|6106|2|40|62863.60|0.02|0.02|A|F|1995-01-03|1995-02-14|1995-01-17|TAKE BACK RETURN|REG AIR|are blithel +9127|199675|9676|1|23|40817.41|0.05|0.00|N|O|1995-12-05|1995-11-17|1995-12-19|TAKE BACK RETURN|SHIP| cajole final t +9127|130954|5981|2|33|65503.35|0.08|0.02|N|O|1995-11-09|1995-12-08|1995-11-10|COLLECT COD|SHIP|ly alongside of the +9152|144506|7021|1|20|31010.00|0.03|0.00|A|F|1993-08-29|1993-10-18|1993-09-03|DELIVER IN PERSON|RAIL|uickly. blithely even de +9152|100901|3412|2|8|15215.20|0.00|0.06|R|F|1993-11-14|1993-11-02|1993-12-13|TAKE BACK RETURN|MAIL|nto beans according to the care +9152|37773|5283|3|32|54744.64|0.02|0.04|R|F|1993-09-03|1993-11-04|1993-09-18|TAKE BACK RETURN|REG AIR|old packages engage blithely. fur +9152|34519|9526|4|46|66861.46|0.07|0.01|A|F|1993-09-06|1993-10-02|1993-09-28|NONE|REG AIR| alongside of the express accounts a +9153|99051|4070|1|41|43052.05|0.02|0.04|N|O|1997-09-08|1997-10-05|1997-09-24|DELIVER IN PERSON|RAIL|furiously ironic asymptotes. idly +9153|148432|5975|2|29|42932.47|0.00|0.08|N|O|1997-07-27|1997-08-22|1997-08-03|DELIVER IN PERSON|TRUCK| requests: bold dep +9153|82118|7135|3|5|5500.55|0.07|0.00|N|O|1997-08-10|1997-09-17|1997-09-02|TAKE BACK RETURN|MAIL|t ideas after th +9153|155396|7912|4|40|58055.60|0.08|0.00|N|O|1997-10-13|1997-08-21|1997-10-15|NONE|MAIL| blithely re +9153|127491|7492|5|18|27332.82|0.08|0.01|N|O|1997-09-13|1997-10-11|1997-09-14|COLLECT COD|FOB|y above the carefully regu +9153|140134|135|6|5|5870.65|0.03|0.03|N|O|1997-08-14|1997-10-14|1997-09-02|COLLECT COD|SHIP|beans haggl +9154|86513|9022|1|45|67477.95|0.06|0.06|N|O|1997-09-24|1997-08-11|1997-10-14|NONE|FOB|nal, careful instructions wake carefully. b +9154|14212|1716|2|7|7883.47|0.09|0.05|N|O|1997-09-28|1997-09-21|1997-10-27|TAKE BACK RETURN|SHIP|nts cajole near +9154|53311|5817|3|46|58158.26|0.04|0.01|N|O|1997-07-18|1997-08-22|1997-07-31|NONE|MAIL|inal depths. blithely quick deposits n +9154|196620|4178|4|31|53215.22|0.00|0.00|N|O|1997-08-28|1997-07-29|1997-09-07|NONE|AIR|final warthogs. slyly pending request +9154|176947|9465|5|12|24287.28|0.00|0.00|N|O|1997-08-20|1997-07-26|1997-09-17|NONE|RAIL|es. requests print furiously instead of th +9154|140238|2753|6|40|51129.20|0.03|0.02|N|O|1997-06-24|1997-09-03|1997-07-24|COLLECT COD|TRUCK|t haggle bli +9154|173448|3449|7|47|71507.68|0.04|0.05|N|O|1997-07-07|1997-09-07|1997-07-25|DELIVER IN PERSON|SHIP|wake boldly above the furiousl +9155|129335|1848|1|10|13643.30|0.04|0.03|R|F|1992-11-01|1992-10-23|1992-11-23|DELIVER IN PERSON|AIR| carefully. final packages +9155|131031|1032|2|44|46729.32|0.02|0.02|A|F|1992-11-09|1992-11-20|1992-11-20|COLLECT COD|TRUCK|, fluffy platelets wake above the +9155|35698|8202|3|14|22871.66|0.01|0.04|A|F|1992-10-02|1992-10-21|1992-10-23|TAKE BACK RETURN|REG AIR|sits above the furiously even pack +9156|92865|7884|1|5|9289.30|0.06|0.01|A|F|1994-05-31|1994-03-20|1994-06-03|NONE|REG AIR|endencies. sl +9156|176190|1225|2|22|27856.18|0.03|0.00|R|F|1994-02-08|1994-04-01|1994-02-24|DELIVER IN PERSON|AIR|equests dete +9156|13621|6123|3|15|23019.30|0.05|0.00|A|F|1994-03-29|1994-05-01|1994-04-06|NONE|SHIP|nts. foxes cajole. ironic packages c +9156|119085|1597|4|35|38642.80|0.07|0.05|A|F|1994-05-31|1994-03-24|1994-06-20|TAKE BACK RETURN|FOB|e quickly. express, ev +9156|51687|1688|5|28|45883.04|0.03|0.01|A|F|1994-05-08|1994-04-04|1994-05-25|TAKE BACK RETURN|FOB|he carefully final deposits use slyly ca +9157|14625|4626|1|3|4618.86|0.10|0.00|A|F|1992-08-27|1992-07-26|1992-09-11|TAKE BACK RETURN|MAIL|lyly bold ideas cajole even packages. bol +9157|190856|3376|2|28|54511.80|0.09|0.08|A|F|1992-06-27|1992-08-24|1992-07-12|NONE|RAIL|ests haggle above the carefully s +9158|184272|4273|1|32|43400.64|0.06|0.05|N|F|1995-06-13|1995-06-19|1995-07-02|DELIVER IN PERSON|MAIL|g deposits. b +9158|44401|9410|2|1|1345.40|0.07|0.00|A|F|1995-05-10|1995-06-27|1995-05-24|DELIVER IN PERSON|AIR| fluffily bold deposits. blithely re +9158|42107|4612|3|33|34620.30|0.10|0.03|N|F|1995-06-02|1995-07-02|1995-06-20|TAKE BACK RETURN|SHIP|ular foxes nag even excuses. slyly regular +9159|1269|3770|1|34|39788.84|0.03|0.05|N|O|1995-08-22|1995-10-18|1995-09-04|DELIVER IN PERSON|MAIL| wake blithely +9159|117697|2720|2|8|13717.52|0.06|0.08|N|O|1995-08-16|1995-09-20|1995-09-09|DELIVER IN PERSON|AIR|accounts wake. regular accou +9159|120863|3376|3|49|92309.14|0.07|0.05|N|O|1995-09-06|1995-09-06|1995-09-28|TAKE BACK RETURN|MAIL| after the dependencies. special fray +9159|142513|2514|4|5|7777.55|0.09|0.01|N|O|1995-08-04|1995-09-19|1995-08-17|COLLECT COD|REG AIR|iously ironic theodolites; regular, re +9184|118166|3189|1|46|54471.36|0.01|0.04|N|O|1997-09-07|1997-09-30|1997-10-03|NONE|SHIP|ntegrate furiously final asy +9184|10202|5205|2|1|1112.20|0.05|0.02|N|O|1997-11-15|1997-09-08|1997-12-12|COLLECT COD|SHIP|nag carefully. sl +9184|57392|7393|3|3|4048.17|0.10|0.02|N|O|1997-08-26|1997-10-07|1997-09-08|TAKE BACK RETURN|REG AIR|ic accounts. excuses a +9185|137990|7991|1|32|64895.68|0.08|0.08|R|F|1994-07-12|1994-07-24|1994-07-20|DELIVER IN PERSON|AIR|accounts snooze +9185|183999|4000|2|14|29161.86|0.06|0.02|R|F|1994-08-19|1994-07-30|1994-09-15|TAKE BACK RETURN|REG AIR|ackages sleep blithely regular deposits +9186|54814|9825|1|48|84902.88|0.05|0.06|A|F|1992-05-10|1992-05-03|1992-05-19|TAKE BACK RETURN|SHIP|s haggle furiously b +9186|42400|4905|2|45|60408.00|0.07|0.06|R|F|1992-04-30|1992-05-10|1992-05-13|TAKE BACK RETURN|REG AIR|y regular requests. even dependencies +9186|13523|1027|3|5|7182.60|0.07|0.03|R|F|1992-07-01|1992-06-27|1992-07-03|TAKE BACK RETURN|REG AIR|yly final deposits use caref +9186|65260|5261|4|22|26955.72|0.03|0.03|R|F|1992-05-30|1992-06-01|1992-06-18|COLLECT COD|TRUCK|ts. dependencies along the even epitaphs +9187|25511|8014|1|45|64642.95|0.00|0.06|R|F|1994-11-21|1994-11-06|1994-12-17|TAKE BACK RETURN|FOB|ar excuses boost fur +9187|161772|9321|2|49|89854.73|0.05|0.02|R|F|1994-09-21|1994-11-04|1994-10-12|COLLECT COD|AIR|fully final +9187|96390|6391|3|24|33273.36|0.03|0.01|A|F|1994-10-30|1994-11-11|1994-11-24|TAKE BACK RETURN|MAIL|kly alongside of +9187|23585|1092|4|36|54308.88|0.00|0.01|R|F|1994-11-12|1994-09-27|1994-11-21|TAKE BACK RETURN|TRUCK|bold ideas cajole fur +9188|25258|263|1|38|44963.50|0.05|0.08|N|O|1998-01-28|1998-04-16|1998-02-12|TAKE BACK RETURN|TRUCK|ely final instructions about the +9188|100867|3378|2|13|24282.18|0.06|0.00|N|O|1998-05-24|1998-03-02|1998-06-12|NONE|AIR|r deposits haggle carefu +9188|57314|2325|3|23|29240.13|0.07|0.06|N|O|1998-04-01|1998-03-18|1998-04-21|COLLECT COD|SHIP|y express packages poach f +9188|71385|6400|4|38|51542.44|0.09|0.03|N|O|1998-03-27|1998-04-16|1998-03-31|NONE|REG AIR|tructions boost car +9188|165425|2974|5|50|74521.00|0.09|0.05|N|O|1998-02-23|1998-04-13|1998-03-23|NONE|MAIL|mptotes boost carefully q +9188|85348|365|6|2|2666.68|0.07|0.06|N|O|1998-03-10|1998-04-01|1998-04-04|TAKE BACK RETURN|MAIL|ual deposits affix around t +9189|153079|625|1|44|49811.08|0.09|0.00|N|O|1996-12-30|1997-01-12|1997-01-26|TAKE BACK RETURN|SHIP|ecial theodolit +9189|190381|382|2|27|39727.26|0.00|0.07|N|O|1997-03-16|1997-01-25|1997-03-27|DELIVER IN PERSON|SHIP|kages along the furiously pending e +9190|79688|7210|1|30|50030.40|0.02|0.07|N|O|1998-05-01|1998-05-14|1998-05-12|NONE|RAIL|fily expres +9190|104491|9512|2|27|40378.23|0.08|0.02|N|O|1998-04-12|1998-05-25|1998-04-28|DELIVER IN PERSON|MAIL|e across the car +9190|164225|6742|3|33|42544.26|0.09|0.04|N|O|1998-05-08|1998-05-20|1998-06-01|COLLECT COD|MAIL|egular foxes impress quickly slyly ir +9190|122380|4893|4|44|61704.72|0.01|0.05|N|O|1998-04-29|1998-05-19|1998-05-29|TAKE BACK RETURN|FOB| along the final, ironic ac +9190|40578|5587|5|40|60742.80|0.01|0.06|N|O|1998-03-11|1998-04-06|1998-04-10|COLLECT COD|RAIL|riously ironic package +9190|188861|3898|6|24|46796.64|0.05|0.00|N|O|1998-04-11|1998-04-16|1998-04-19|TAKE BACK RETURN|FOB|t blithely upon the carefu +9191|41105|6114|1|17|17783.70|0.06|0.01|N|O|1996-06-17|1996-06-15|1996-07-02|DELIVER IN PERSON|MAIL|ng accounts do wake quickly +9216|132812|2813|1|43|79326.83|0.00|0.04|N|O|1995-07-27|1995-05-17|1995-08-13|TAKE BACK RETURN|MAIL|oss the quickly bold foxes wa +9216|168513|1030|2|22|34793.22|0.06|0.03|N|O|1995-07-13|1995-05-23|1995-08-11|COLLECT COD|REG AIR|y bold accounts use slyly. bold courts abov +9216|189321|6876|3|31|43719.92|0.00|0.05|N|O|1995-07-12|1995-06-13|1995-07-19|COLLECT COD|SHIP|re slyly slyly unusual accounts. +9217|114037|6549|1|26|27326.78|0.09|0.08|N|O|1997-07-30|1997-08-16|1997-08-20|DELIVER IN PERSON|RAIL|s. ironic accounts cajole +9217|5722|5723|2|5|8138.60|0.06|0.02|N|O|1997-08-22|1997-08-24|1997-08-30|NONE|RAIL|sly upon the fluffily regul +9217|153390|3391|3|34|49075.26|0.04|0.05|N|O|1997-07-06|1997-08-14|1997-07-19|TAKE BACK RETURN|AIR|ackages. b +9217|9246|1747|4|37|42743.88|0.01|0.01|N|O|1997-06-21|1997-07-14|1997-07-21|DELIVER IN PERSON|TRUCK|ts. furiously even deposits hag +9218|51243|8759|1|14|16719.36|0.10|0.00|N|O|1997-12-22|1998-02-10|1997-12-26|COLLECT COD|MAIL|deas cajole care +9218|37324|2331|2|11|13874.52|0.03|0.00|N|O|1998-03-31|1998-02-20|1998-04-02|DELIVER IN PERSON|RAIL|y ironic asymptotes. slyly regular pack +9219|127664|7665|1|29|49058.14|0.00|0.06|R|F|1995-01-21|1994-11-10|1995-02-02|COLLECT COD|MAIL|ular excuses above +9219|37592|2599|2|26|39769.34|0.00|0.01|R|F|1995-01-25|1994-11-23|1995-02-10|DELIVER IN PERSON|AIR|y even acc +9219|196140|6141|3|37|45737.18|0.02|0.02|R|F|1994-10-08|1994-12-10|1994-10-12|DELIVER IN PERSON|MAIL|yly final orbits. regular theodo +9219|124322|9347|4|19|25580.08|0.01|0.07|A|F|1994-11-13|1994-12-07|1994-12-13|NONE|RAIL|ies. furiously regular de +9219|73562|8577|5|28|42995.68|0.10|0.06|R|F|1994-12-26|1994-12-18|1995-01-09|COLLECT COD|AIR|arefully final pinto beans cajole furio +9220|112446|4958|1|1|1458.44|0.07|0.04|N|O|1998-07-06|1998-07-06|1998-08-03|DELIVER IN PERSON|AIR|s haggle among the furio +9221|188455|974|1|43|66368.35|0.00|0.02|R|F|1995-03-30|1995-03-26|1995-04-15|NONE|REG AIR|carefully. furiously pending courts +9221|157932|5478|2|41|81587.13|0.09|0.06|R|F|1995-02-19|1995-02-27|1995-02-25|TAKE BACK RETURN|RAIL|cross the furiously regular sentiments. unu +9221|149585|2100|3|49|80094.42|0.08|0.04|R|F|1995-03-20|1995-02-11|1995-04-03|NONE|MAIL|riously alongside of +9221|72850|5358|4|43|78382.55|0.04|0.06|A|F|1995-04-16|1995-03-22|1995-04-29|TAKE BACK RETURN|MAIL| ironic braids wake furiously unusua +9222|23687|3688|1|38|61205.84|0.03|0.08|A|F|1994-04-24|1994-03-30|1994-05-03|TAKE BACK RETURN|AIR|nusual requests wake behind th +9222|94739|9758|2|49|84952.77|0.03|0.01|A|F|1994-03-07|1994-05-02|1994-03-25|NONE|TRUCK| ironic theodolites. +9222|70423|424|3|50|69671.00|0.08|0.01|A|F|1994-02-22|1994-03-24|1994-03-23|NONE|FOB|the carefully reg +9222|194568|2126|4|1|1662.56|0.05|0.02|A|F|1994-02-23|1994-03-17|1994-03-12|NONE|SHIP|ily regular ideas. fluffily ironic depo +9222|97026|9536|5|26|26598.52|0.06|0.05|A|F|1994-04-30|1994-03-31|1994-05-11|TAKE BACK RETURN|REG AIR|ar, final de +9223|72012|9534|1|5|4920.05|0.08|0.08|N|O|1997-10-24|1997-09-22|1997-11-06|NONE|TRUCK|al packages across +9223|101537|6558|2|37|56925.61|0.08|0.08|N|O|1997-11-10|1997-10-31|1997-11-28|DELIVER IN PERSON|TRUCK|stealthy ideas. blithely unusual +9223|117570|5104|3|43|68265.51|0.02|0.01|N|O|1997-11-02|1997-10-02|1997-11-26|TAKE BACK RETURN|SHIP|, unusual ideas haggle theodolites. sl +9223|195301|2859|4|36|50266.80|0.03|0.04|N|O|1997-09-27|1997-10-19|1997-10-16|DELIVER IN PERSON|AIR| haggle about the +9223|20939|8446|5|3|5579.79|0.03|0.02|N|O|1997-09-28|1997-09-22|1997-10-13|NONE|MAIL|ly dependencies +9223|107044|7045|6|16|16816.64|0.02|0.00|N|O|1997-09-27|1997-10-12|1997-10-04|TAKE BACK RETURN|TRUCK|as are quic +9223|73575|3576|7|26|40262.82|0.03|0.02|N|O|1997-10-08|1997-09-12|1997-10-24|NONE|RAIL|ly ironic packages wake after the s +9248|165458|7975|1|22|33515.90|0.07|0.00|R|F|1995-04-24|1995-02-08|1995-05-19|DELIVER IN PERSON|REG AIR|ly even theodolites? furiously pend +9248|36543|1550|2|8|11836.32|0.02|0.08|R|F|1995-01-08|1995-03-21|1995-01-14|NONE|AIR|telets use along the slyly re +9248|172293|2294|3|26|35497.54|0.08|0.08|A|F|1995-04-14|1995-01-29|1995-05-10|COLLECT COD|MAIL|iously. silent, express instructions dete +9248|124711|7224|4|24|41657.04|0.07|0.03|A|F|1995-01-27|1995-03-11|1995-02-12|COLLECT COD|RAIL|. furiously f +9249|17709|211|1|36|58561.20|0.02|0.04|A|F|1993-06-03|1993-06-28|1993-06-29|DELIVER IN PERSON|FOB|efully final accounts cajole p +9249|25832|3339|2|36|63281.88|0.09|0.08|R|F|1993-06-30|1993-07-29|1993-07-07|COLLECT COD|FOB|onic dolphins. dependencies us +9249|151415|6446|3|15|21996.15|0.02|0.01|R|F|1993-05-29|1993-07-16|1993-06-26|COLLECT COD|SHIP|ly ironic foxes are slyly. ca +9249|30963|3467|4|28|53030.88|0.00|0.01|A|F|1993-05-23|1993-06-22|1993-05-26|NONE|MAIL|ts wake requests. +9249|188804|1323|5|15|28392.00|0.07|0.04|R|F|1993-06-01|1993-06-29|1993-06-25|NONE|FOB|le unusual deposits. blithely regular pla +9250|85178|195|1|11|12794.87|0.02|0.08|R|F|1992-08-17|1992-09-14|1992-08-28|TAKE BACK RETURN|TRUCK|ically. slyly expr +9250|184894|7413|2|20|39577.80|0.09|0.05|A|F|1992-12-08|1992-09-18|1992-12-26|COLLECT COD|REG AIR|es cajole across +9250|110095|5118|3|15|16576.35|0.02|0.08|R|F|1992-09-17|1992-09-30|1992-10-05|NONE|TRUCK|ut the deposits. final, regular packages +9250|149927|7470|4|12|23723.04|0.07|0.01|A|F|1992-11-30|1992-10-31|1992-12-08|TAKE BACK RETURN|SHIP|bout the f +9251|10288|2790|1|29|34750.12|0.03|0.06|R|F|1993-12-19|1993-10-12|1994-01-04|TAKE BACK RETURN|RAIL|sts. final warhorses about the blithely s +9252|91328|8856|1|24|31663.68|0.08|0.03|N|O|1998-02-18|1998-02-07|1998-03-06|TAKE BACK RETURN|SHIP|side of the care +9252|147473|9988|2|9|13684.23|0.08|0.02|N|O|1998-03-17|1998-02-05|1998-04-16|DELIVER IN PERSON|FOB|usly. accounts are sl +9252|169048|4081|3|23|25691.92|0.01|0.02|N|O|1998-03-25|1998-02-14|1998-04-17|DELIVER IN PERSON|FOB|furiously +9253|172435|2436|1|34|51252.62|0.10|0.07|A|F|1992-03-03|1992-04-25|1992-03-09|COLLECT COD|RAIL|hely across the carefull +9253|111547|1548|2|44|68575.76|0.03|0.06|R|F|1992-04-22|1992-04-09|1992-05-09|COLLECT COD|AIR| regular packages sleep slyly; express de +9253|154658|7174|3|26|44528.90|0.09|0.06|A|F|1992-02-11|1992-03-28|1992-03-09|COLLECT COD|TRUCK|regular notornis. iro +9253|128948|6485|4|30|59308.20|0.03|0.01|R|F|1992-05-10|1992-03-09|1992-06-07|TAKE BACK RETURN|AIR|rate thinly quickly ironic +9253|18312|814|5|23|28297.13|0.00|0.02|A|F|1992-02-08|1992-03-27|1992-02-19|TAKE BACK RETURN|RAIL|deposits print +9253|160065|66|6|42|47252.52|0.08|0.03|A|F|1992-02-21|1992-04-14|1992-03-21|TAKE BACK RETURN|REG AIR| patterns play sometimes +9254|117383|7384|1|6|8402.28|0.05|0.03|R|F|1993-06-29|1993-07-11|1993-07-13|TAKE BACK RETURN|TRUCK|e carefully acc +9254|47579|2588|2|16|24425.12|0.05|0.01|A|F|1993-08-20|1993-07-11|1993-09-10|COLLECT COD|MAIL| the silently final instructi +9254|59159|6675|3|16|17890.40|0.03|0.03|R|F|1993-06-14|1993-07-02|1993-06-25|TAKE BACK RETURN|RAIL|ly above the instructions. +9254|77847|355|4|3|5474.52|0.07|0.08|R|F|1993-06-07|1993-07-03|1993-06-16|NONE|REG AIR|y fluffily spec +9255|91102|6121|1|8|8744.80|0.06|0.03|N|O|1996-02-29|1996-01-26|1996-03-19|DELIVER IN PERSON|FOB|tes. pending, ir +9255|137229|2256|2|49|62044.78|0.08|0.06|N|O|1996-03-26|1996-02-06|1996-04-10|DELIVER IN PERSON|MAIL|sts. packages integrate slyly. furiou +9255|191504|4024|3|36|57438.00|0.10|0.08|N|O|1995-12-15|1996-03-03|1995-12-27|COLLECT COD|SHIP|onic requests. slyly regul +9255|5192|5193|4|16|17555.04|0.08|0.04|N|O|1996-02-16|1996-02-28|1996-02-17|TAKE BACK RETURN|TRUCK| ironic accounts wake caref +9280|42165|4670|1|30|33214.80|0.03|0.05|N|O|1998-08-21|1998-07-31|1998-08-27|COLLECT COD|TRUCK|arefully carefully spe +9280|60733|734|2|21|35568.33|0.09|0.08|N|O|1998-09-19|1998-08-24|1998-09-22|NONE|MAIL|o beans. fluffily ironic packa +9280|137366|7367|3|7|9823.52|0.05|0.02|N|O|1998-08-17|1998-07-20|1998-09-12|DELIVER IN PERSON|FOB|nic ideas. unusual, regular pinto beans +9280|96638|9148|4|49|80096.87|0.10|0.01|N|O|1998-09-02|1998-09-10|1998-09-10|NONE|TRUCK|he dinos. regular ac +9280|182392|2393|5|36|53078.04|0.10|0.07|N|O|1998-09-07|1998-07-18|1998-09-14|COLLECT COD|REG AIR|ress ideas are theodolit +9280|57572|5088|6|14|21413.98|0.07|0.04|N|O|1998-09-21|1998-08-16|1998-10-15|DELIVER IN PERSON|AIR|l packages. carefully silent hockey player +9280|11281|8785|7|31|36960.68|0.03|0.05|N|O|1998-07-11|1998-08-02|1998-07-17|TAKE BACK RETURN|MAIL|ending, busy courts p +9281|189089|9090|1|4|4712.32|0.05|0.05|R|F|1992-04-24|1992-05-20|1992-05-16|TAKE BACK RETURN|RAIL|somas. quickly expr +9281|10943|5946|2|22|40786.68|0.01|0.07|A|F|1992-03-27|1992-04-22|1992-04-23|TAKE BACK RETURN|REG AIR|fix alongside +9281|109134|6665|3|26|29721.38|0.00|0.06|A|F|1992-04-08|1992-04-17|1992-04-15|COLLECT COD|MAIL| use above the sl +9281|13657|8660|4|48|75391.20|0.03|0.05|A|F|1992-06-18|1992-03-30|1992-06-21|TAKE BACK RETURN|FOB|ully unusual accounts detect +9281|120094|5119|5|26|28966.34|0.04|0.01|A|F|1992-05-09|1992-05-21|1992-06-01|NONE|TRUCK| slyly along the blithely express accou +9281|6744|6745|6|27|44569.98|0.04|0.00|R|F|1992-03-11|1992-04-13|1992-03-20|COLLECT COD|TRUCK|deposits nag abov +9281|135164|7678|7|10|11991.60|0.09|0.02|R|F|1992-02-28|1992-05-05|1992-03-21|NONE|FOB|c pinto beans. bold instruc +9282|96895|1914|1|19|35945.91|0.05|0.03|N|O|1996-02-12|1996-01-19|1996-02-23|COLLECT COD|REG AIR|telets. slyly e +9283|157127|2158|1|5|5920.60|0.02|0.08|R|F|1994-07-15|1994-07-10|1994-07-29|DELIVER IN PERSON|RAIL|s theodolites cajole. regular ideas wak +9284|131824|9364|1|49|90935.18|0.06|0.00|R|F|1994-08-20|1994-09-08|1994-09-07|TAKE BACK RETURN|AIR|ecial packages ag +9285|37702|7703|1|13|21316.10|0.04|0.02|A|F|1994-02-14|1994-03-19|1994-03-07|COLLECT COD|MAIL|carefully final pinto beans ca +9285|54398|4399|2|50|67619.50|0.06|0.07|A|F|1994-01-29|1994-02-15|1994-02-17|TAKE BACK RETURN|RAIL| quickly after the final theodolit +9285|51665|4171|3|21|33949.86|0.01|0.01|R|F|1994-03-01|1994-04-03|1994-03-10|TAKE BACK RETURN|TRUCK|heodolites. blithely regular requ +9286|127938|451|1|10|19659.30|0.01|0.07|R|F|1995-05-27|1995-06-22|1995-06-06|TAKE BACK RETURN|FOB|y against the brave ideas. carefully bold i +9286|38242|5752|2|8|9441.92|0.07|0.05|N|O|1995-07-11|1995-05-11|1995-07-15|COLLECT COD|FOB|e blithely ironic foxes +9286|116907|1930|3|11|21162.90|0.07|0.05|N|O|1995-06-27|1995-06-27|1995-07-17|NONE|AIR|ets. fluffily final accounts +9286|54679|4680|4|21|34307.07|0.07|0.03|N|F|1995-05-25|1995-05-27|1995-06-20|TAKE BACK RETURN|MAIL|ckages doubt above the +9286|183652|3653|5|11|19092.15|0.06|0.08|N|O|1995-07-22|1995-05-24|1995-08-07|COLLECT COD|RAIL|slyly slyly special foxes. fluffily bold a +9286|34485|4486|6|12|17033.76|0.07|0.05|N|O|1995-06-21|1995-06-22|1995-07-02|TAKE BACK RETURN|REG AIR| deposits. sl +9286|177796|5348|7|34|63708.86|0.04|0.07|R|F|1995-04-09|1995-06-01|1995-04-26|DELIVER IN PERSON|TRUCK|express requests wake slyly ruth +9287|824|825|1|16|27597.12|0.07|0.00|N|O|1998-03-25|1998-02-10|1998-04-16|DELIVER IN PERSON|FOB|ironic accounts sl +9312|44079|9088|1|9|9207.63|0.01|0.04|A|F|1992-07-21|1992-07-28|1992-08-04|NONE|SHIP|t instructions. blithely final do +9312|24092|6595|2|19|19305.71|0.05|0.01|A|F|1992-07-02|1992-07-09|1992-07-10|DELIVER IN PERSON|TRUCK|es. regular, +9312|99355|4374|3|49|66363.15|0.02|0.08|R|F|1992-07-06|1992-08-16|1992-07-17|TAKE BACK RETURN|AIR|efully even deco +9312|58326|3337|4|35|44951.20|0.07|0.03|R|F|1992-05-21|1992-07-24|1992-05-30|NONE|AIR|deposits. never spec +9312|77377|4899|5|28|37922.36|0.08|0.05|A|F|1992-06-08|1992-07-20|1992-06-16|TAKE BACK RETURN|SHIP|fily final realms are. fluf +9313|11918|9422|1|37|67706.67|0.09|0.03|N|O|1996-07-26|1996-06-10|1996-08-18|DELIVER IN PERSON|SHIP|ously regular +9313|91264|6283|2|49|61507.74|0.01|0.08|N|O|1996-06-14|1996-06-26|1996-06-20|TAKE BACK RETURN|REG AIR| ideas doze furiously. bravely ironic pa +9313|64570|4571|3|16|24553.12|0.10|0.04|N|O|1996-04-29|1996-06-12|1996-05-25|DELIVER IN PERSON|AIR|are bold deposits. special th +9313|11454|6457|4|22|30039.90|0.05|0.06|N|O|1996-04-25|1996-06-11|1996-04-26|NONE|REG AIR| even instructions +9313|103476|8497|5|29|42904.63|0.01|0.07|N|O|1996-06-24|1996-06-16|1996-07-13|COLLECT COD|FOB|cross the furiously regula +9313|105107|2638|6|18|20017.80|0.01|0.06|N|O|1996-06-28|1996-06-08|1996-07-14|NONE|RAIL|ep ironic platelets. dogge +9314|133242|782|1|12|15302.88|0.07|0.03|R|F|1995-03-26|1995-04-15|1995-04-10|TAKE BACK RETURN|SHIP|riously final accounts wake furiously ca +9315|46059|3572|1|11|11055.55|0.01|0.08|N|O|1998-04-21|1998-05-11|1998-05-19|NONE|REG AIR|ly according to the special, regular +9316|184937|4938|1|27|54592.11|0.06|0.06|N|O|1995-10-17|1995-12-03|1995-10-27|NONE|SHIP|y express pinto beans ar +9316|26760|9263|2|32|53976.32|0.05|0.06|N|O|1995-09-26|1995-12-04|1995-09-29|NONE|MAIL|heodolites wake exp +9316|144110|9139|3|25|28852.75|0.03|0.01|N|O|1995-12-12|1995-11-18|1995-12-24|DELIVER IN PERSON|TRUCK|to the blithely special deposits. blithely +9316|49339|6852|4|46|59263.18|0.05|0.05|N|O|1995-11-23|1995-12-12|1995-12-22|TAKE BACK RETURN|RAIL|cording to the furious +9316|29162|4167|5|36|39281.76|0.06|0.08|N|O|1995-12-09|1995-12-04|1996-01-08|DELIVER IN PERSON|RAIL|ss, special d +9317|2957|5458|1|8|14879.60|0.10|0.01|A|F|1994-05-08|1994-05-05|1994-05-12|TAKE BACK RETURN|REG AIR|y final deposits nag daringly ab +9317|91028|8556|2|39|39741.78|0.06|0.00|R|F|1994-04-04|1994-05-11|1994-04-11|NONE|MAIL|cial requests haggle blithely. i +9317|93723|3724|3|28|48068.16|0.00|0.07|R|F|1994-03-17|1994-06-08|1994-04-02|COLLECT COD|AIR|lar accounts are furi +9317|199575|4614|4|15|25118.55|0.00|0.00|A|F|1994-05-24|1994-05-30|1994-05-25|COLLECT COD|FOB|e thin waters. furiously regular dep +9318|136377|8891|1|10|14133.70|0.02|0.07|R|F|1992-11-18|1992-09-15|1992-11-20|DELIVER IN PERSON|RAIL|according to the +9318|83046|8063|2|44|45277.76|0.06|0.05|A|F|1992-08-18|1992-10-23|1992-08-22|NONE|FOB|s. stealthy theodolit +9318|154010|4011|3|15|15960.15|0.04|0.00|R|F|1992-07-29|1992-10-26|1992-08-10|NONE|TRUCK|ckly carefully special packages. carefull +9319|152719|5235|1|6|10630.26|0.05|0.02|A|F|1992-10-23|1992-12-05|1992-11-10|NONE|FOB| ironic asymptotes wake slyly carefully eve +9319|143992|3993|2|31|63115.69|0.01|0.02|A|F|1993-01-03|1992-11-13|1993-02-01|TAKE BACK RETURN|SHIP|the quickl +9319|73520|8535|3|20|29870.40|0.09|0.05|R|F|1992-10-05|1992-12-03|1992-10-23|DELIVER IN PERSON|REG AIR|nt excuses. expr +9319|46396|3909|4|17|22820.63|0.06|0.03|A|F|1992-12-24|1992-10-14|1993-01-12|DELIVER IN PERSON|REG AIR|lar platelets haggle furiously? express +9344|199309|4348|1|29|40840.70|0.00|0.04|N|O|1996-03-13|1996-02-27|1996-03-22|NONE|REG AIR|ng realms nag. fi +9344|169866|7415|2|2|3871.72|0.10|0.03|N|O|1996-02-08|1996-03-03|1996-02-15|TAKE BACK RETURN|MAIL|deposits. ironic packages abo +9344|121294|6319|3|40|52611.60|0.04|0.05|N|O|1996-02-25|1996-02-21|1996-03-16|NONE|RAIL|counts sleep slyly. care +9344|183596|3597|4|39|65504.01|0.06|0.07|N|O|1995-12-20|1996-02-23|1995-12-21|DELIVER IN PERSON|REG AIR|nusual, pending dolphins wa +9344|97880|2899|5|44|82626.72|0.04|0.04|N|O|1995-12-18|1996-02-23|1995-12-25|TAKE BACK RETURN|FOB|ermanent requests sleep along the furiou +9344|56075|3591|6|39|40211.73|0.03|0.03|N|O|1996-03-02|1996-03-06|1996-03-27|TAKE BACK RETURN|MAIL|rts. slyly regular theo +9344|45101|2614|7|27|28244.70|0.09|0.07|N|O|1996-01-16|1996-01-20|1996-02-11|NONE|RAIL|unusual asymp +9345|197049|2088|1|20|22920.80|0.06|0.01|N|O|1996-03-07|1996-03-13|1996-03-20|COLLECT COD|RAIL|ound the express deposits ha +9345|196532|6533|2|16|26056.48|0.03|0.06|N|O|1996-03-31|1996-03-30|1996-04-26|NONE|SHIP|ickly blithely even th +9345|98436|5964|3|17|24385.31|0.02|0.05|N|O|1996-03-06|1996-04-01|1996-03-07|TAKE BACK RETURN|AIR|ely final ideas across the quickly +9345|10529|530|4|43|61899.36|0.08|0.06|N|O|1996-04-22|1996-03-21|1996-05-08|NONE|SHIP| carefully id +9345|149611|9612|5|16|26569.76|0.01|0.00|N|O|1996-03-31|1996-04-03|1996-04-13|NONE|AIR|es. special, expr +9346|179972|7524|1|44|90286.68|0.10|0.04|N|O|1996-12-22|1996-11-08|1997-01-06|NONE|MAIL|lar requests. +9346|183861|1416|2|7|13614.02|0.08|0.04|N|O|1996-12-15|1996-11-20|1996-12-20|COLLECT COD|RAIL| theodolites affix slyly about the expr +9346|142461|4|3|24|36083.04|0.03|0.04|N|O|1997-01-01|1997-01-06|1997-01-05|DELIVER IN PERSON|RAIL| deposits must have to cajol +9346|129194|1707|4|14|17124.66|0.00|0.07|N|O|1997-01-06|1996-12-06|1997-01-25|COLLECT COD|REG AIR|ld, silent dolphins cajole bli +9346|147486|5029|5|33|50604.84|0.08|0.01|N|O|1996-10-12|1996-11-16|1996-11-06|DELIVER IN PERSON|REG AIR| unusual foxes wake furiously regular de +9347|26225|8728|1|40|46048.80|0.09|0.06|R|F|1992-11-10|1992-11-03|1992-12-09|DELIVER IN PERSON|MAIL|bold instr +9347|163397|3398|2|43|62796.77|0.02|0.08|A|F|1992-11-07|1992-10-28|1992-11-15|TAKE BACK RETURN|RAIL| carefully at the furiou +9347|364|2865|3|4|5057.44|0.08|0.05|R|F|1992-10-31|1992-09-19|1992-11-17|TAKE BACK RETURN|REG AIR|ly final d +9347|104454|4455|4|46|67088.70|0.05|0.08|R|F|1992-08-31|1992-11-03|1992-09-21|NONE|MAIL|fully special ideas caj +9348|66780|4299|1|8|13974.24|0.09|0.05|N|O|1996-08-09|1996-08-23|1996-09-06|DELIVER IN PERSON|AIR|the special pack +9348|168532|8533|2|1|1600.53|0.08|0.03|N|O|1996-06-16|1996-08-28|1996-06-24|COLLECT COD|MAIL|y regular pa +9348|113796|6308|3|22|39815.38|0.04|0.03|N|O|1996-07-24|1996-08-11|1996-08-11|NONE|TRUCK|unusual pinto beans haggle slyly slyly +9348|167733|250|4|34|61224.82|0.07|0.04|N|O|1996-09-27|1996-08-24|1996-10-07|COLLECT COD|MAIL|regular packages nag slyly silent +9348|78826|6348|5|6|10828.92|0.04|0.08|N|O|1996-07-22|1996-07-14|1996-08-12|TAKE BACK RETURN|RAIL|ronic epitaphs about the p +9348|12318|2319|6|22|27066.82|0.03|0.00|N|O|1996-09-01|1996-09-01|1996-09-06|TAKE BACK RETURN|TRUCK|nd the fin +9349|186734|9253|1|13|23669.49|0.09|0.07|N|O|1997-09-02|1997-10-08|1997-09-11|NONE|RAIL|into beans are +9349|37874|378|2|12|21742.44|0.01|0.06|N|O|1997-12-23|1997-11-09|1998-01-09|DELIVER IN PERSON|SHIP|sits sleep careful +9349|141459|9002|3|3|4501.35|0.06|0.04|N|O|1997-10-28|1997-10-27|1997-11-22|TAKE BACK RETURN|RAIL|uses. regular instructions wake. +9349|94795|2323|4|35|62642.65|0.06|0.04|N|O|1997-09-25|1997-10-28|1997-10-08|NONE|TRUCK|: carefully pending ideas are +9349|17179|2182|5|46|50423.82|0.07|0.02|N|O|1997-10-28|1997-09-29|1997-11-03|DELIVER IN PERSON|RAIL|ites affix quickly deposits. fu +9349|120800|5825|6|29|52803.20|0.03|0.05|N|O|1997-09-28|1997-10-01|1997-10-25|COLLECT COD|AIR|he slyly regular pinto beans. express cou +9349|72852|374|7|20|36497.00|0.04|0.02|N|O|1997-10-18|1997-10-16|1997-10-22|DELIVER IN PERSON|AIR|impress blithely slyly unusual d +9350|9721|4722|1|31|50552.32|0.03|0.07|R|F|1993-02-24|1993-01-19|1993-02-25|COLLECT COD|FOB|ns integrate slow +9350|169368|9369|2|8|11498.88|0.00|0.04|A|F|1992-11-15|1993-01-16|1992-11-27|DELIVER IN PERSON|TRUCK|the even requests. blithely bold depths ha +9350|164782|2331|3|39|72024.42|0.06|0.01|A|F|1993-01-03|1993-01-21|1993-01-07|COLLECT COD|SHIP|ully regular foxes. fina +9350|88760|6285|4|9|15738.84|0.04|0.00|A|F|1992-11-17|1992-12-30|1992-12-05|COLLECT COD|FOB|y regular packages sublate. final, ir +9350|182370|9925|5|50|72618.50|0.03|0.02|R|F|1993-01-10|1993-01-19|1993-01-14|TAKE BACK RETURN|MAIL|ely pending deposits. blithely even p +9350|81515|1516|6|30|44895.30|0.04|0.05|A|F|1992-11-09|1992-12-19|1992-12-04|COLLECT COD|TRUCK|requests mold slyly pe +9351|153358|5874|1|12|16936.20|0.08|0.01|N|O|1996-08-08|1996-07-22|1996-08-25|TAKE BACK RETURN|REG AIR|accounts wake since the bol +9351|72104|2105|2|39|41967.90|0.01|0.04|N|O|1996-07-02|1996-06-28|1996-07-21|DELIVER IN PERSON|TRUCK|ole blithely pinto beans. carefully i +9376|103245|776|1|33|41191.92|0.04|0.01|N|O|1997-11-07|1997-09-11|1997-11-24|NONE|FOB|ffily even instructions +9376|27711|7712|2|13|21303.23|0.08|0.01|N|O|1997-10-28|1997-09-12|1997-10-29|DELIVER IN PERSON|AIR|ges sleep slyly caref +9376|123182|8207|3|18|21693.24|0.00|0.01|N|O|1997-10-15|1997-09-15|1997-11-07|COLLECT COD|AIR|requests hang +9376|104162|9183|4|38|44314.08|0.04|0.06|N|O|1997-08-11|1997-08-27|1997-08-24|TAKE BACK RETURN|SHIP|lyly according to +9376|46430|3943|5|13|17893.59|0.02|0.06|N|O|1997-11-17|1997-09-21|1997-12-02|COLLECT COD|TRUCK| regular instr +9376|135450|2990|6|20|29709.00|0.04|0.06|N|O|1997-08-22|1997-08-24|1997-08-25|DELIVER IN PERSON|FOB|ide of the blithely regular fo +9377|29222|1725|1|8|9209.76|0.10|0.05|A|F|1993-07-17|1993-06-23|1993-08-08|COLLECT COD|MAIL|ole fluffily across the pending instru +9378|58253|5769|1|14|16957.50|0.05|0.01|N|O|1997-11-24|1997-12-22|1997-12-03|COLLECT COD|AIR|al deposits. special, ironic ideas boos +9378|43565|1078|2|17|25645.52|0.09|0.05|N|O|1997-12-26|1997-11-16|1998-01-01|TAKE BACK RETURN|TRUCK|carefully bold foxes cajole slyly slyly fin +9378|192511|7550|3|43|68950.93|0.10|0.05|N|O|1997-12-27|1997-12-01|1998-01-05|TAKE BACK RETURN|REG AIR|gle fluffily-- ir +9379|121797|1798|1|31|56382.49|0.01|0.06|A|F|1992-04-03|1992-02-19|1992-04-25|COLLECT COD|REG AIR| instructions boost quietly around t +9379|38591|6101|2|22|33650.98|0.09|0.08|A|F|1992-02-12|1992-03-27|1992-02-22|DELIVER IN PERSON|SHIP|re fluffily final sheaves. carefully +9379|185319|2874|3|38|53363.78|0.02|0.05|R|F|1992-03-22|1992-03-27|1992-03-27|DELIVER IN PERSON|REG AIR|fully regula +9379|55596|5597|4|13|20170.67|0.00|0.01|A|F|1992-01-09|1992-03-20|1992-01-12|COLLECT COD|TRUCK|. blithely unusual deposits boost reque +9380|4088|1589|1|35|34722.80|0.00|0.08|A|F|1994-12-18|1994-10-01|1994-12-28|NONE|REG AIR|eposits after the furiously even foxes +9380|91867|6886|2|38|70636.68|0.08|0.05|R|F|1994-11-12|1994-10-05|1994-11-24|COLLECT COD|SHIP|lithely final packages alongside +9380|193779|8818|3|36|67419.72|0.03|0.02|A|F|1994-11-07|1994-11-15|1994-11-08|TAKE BACK RETURN|AIR|osits are blithely. slyly +9381|133307|3308|1|17|22785.10|0.10|0.06|N|O|1996-01-02|1996-01-31|1996-01-29|TAKE BACK RETURN|RAIL|c requests. final, regular deposits +9381|77611|119|2|43|68310.23|0.02|0.05|N|O|1996-01-01|1996-02-11|1996-01-28|TAKE BACK RETURN|REG AIR| slyly regular instructions use. +9382|32770|7777|1|23|39163.71|0.09|0.06|N|O|1996-03-27|1996-04-16|1996-04-04|TAKE BACK RETURN|AIR|yly furiously bold deposits? furio +9382|162553|7586|2|45|72699.75|0.07|0.04|N|O|1996-05-31|1996-05-03|1996-06-10|DELIVER IN PERSON|TRUCK|rve across the pending +9382|25679|684|3|4|6418.68|0.07|0.00|N|O|1996-03-08|1996-04-27|1996-04-02|TAKE BACK RETURN|REG AIR|instructions. excuses haggle. fu +9382|176070|1105|4|30|34382.10|0.02|0.08|N|O|1996-03-27|1996-04-28|1996-04-21|DELIVER IN PERSON|SHIP|boost carefully. theodolites along the ir +9383|162634|2635|1|12|20359.56|0.03|0.02|R|F|1994-03-22|1994-05-16|1994-04-17|NONE|TRUCK| accounts impress fin +9383|175325|2877|2|27|37808.64|0.01|0.04|R|F|1994-07-09|1994-05-16|1994-07-25|TAKE BACK RETURN|AIR|al courts. express frays sh +9383|83483|8500|3|1|1466.48|0.04|0.03|A|F|1994-06-10|1994-04-16|1994-06-28|DELIVER IN PERSON|TRUCK|al asympto +9383|86362|8871|4|31|41799.16|0.09|0.01|A|F|1994-06-05|1994-04-21|1994-06-10|TAKE BACK RETURN|TRUCK|out the fluffily bol +9383|74623|2145|5|43|68697.66|0.10|0.01|A|F|1994-04-28|1994-06-10|1994-05-10|COLLECT COD|AIR|ly express foxes +9408|153529|8560|1|9|14242.68|0.09|0.01|A|F|1992-11-19|1992-11-29|1992-11-25|NONE|MAIL|he fluffily regular packages are +9409|65556|5557|1|14|21301.70|0.09|0.08|R|F|1992-08-27|1992-07-24|1992-09-09|TAKE BACK RETURN|AIR|furiously notornis. regular ideas s +9409|184651|2206|2|6|10413.90|0.03|0.05|A|F|1992-06-21|1992-06-30|1992-07-19|TAKE BACK RETURN|FOB|heodolites. sp +9409|12718|7721|3|22|35875.62|0.08|0.05|R|F|1992-06-15|1992-06-05|1992-06-30|NONE|FOB|thely express deposits +9409|140319|320|4|47|63887.57|0.04|0.03|A|F|1992-06-27|1992-06-19|1992-07-18|DELIVER IN PERSON|FOB| packages cajole slyly +9409|135388|5389|5|31|44124.78|0.00|0.05|R|F|1992-05-09|1992-07-25|1992-05-31|COLLECT COD|SHIP|lithely bold inst +9410|56465|8971|1|48|68230.08|0.03|0.06|N|O|1997-11-02|1997-09-19|1997-11-03|NONE|AIR|otes sleep. f +9410|5483|7984|2|6|8330.88|0.02|0.07|N|O|1997-07-21|1997-10-13|1997-08-06|DELIVER IN PERSON|SHIP|ly ironic dependencies serve s +9410|137813|7814|3|8|14806.48|0.07|0.04|N|O|1997-10-10|1997-10-04|1997-11-01|COLLECT COD|TRUCK|eposits. deposi +9411|15044|2548|1|25|23976.00|0.09|0.02|R|F|1995-04-04|1995-03-10|1995-04-17|TAKE BACK RETURN|AIR|c ideas boost quickly ironic acc +9411|44502|9511|2|23|33269.50|0.05|0.06|A|F|1995-03-15|1995-03-26|1995-03-16|DELIVER IN PERSON|MAIL|ctions haggle blithely a +9412|134984|7498|1|11|22208.78|0.09|0.03|N|O|1998-10-31|1998-09-04|1998-11-22|COLLECT COD|SHIP|ackages. pending, unusual deposits integra +9412|75406|2928|2|47|64925.80|0.08|0.06|N|O|1998-09-24|1998-09-30|1998-10-09|COLLECT COD|TRUCK|hely ironic packages. always final theodol +9412|140047|2562|3|50|54352.00|0.00|0.08|N|O|1998-10-08|1998-09-13|1998-10-25|TAKE BACK RETURN|AIR|y bold ideas. bold, bold +9412|160025|7574|4|40|43400.80|0.10|0.07|N|O|1998-10-20|1998-09-04|1998-11-01|COLLECT COD|SHIP|s nag quickly. quickly express depende +9412|134132|4133|5|24|27987.12|0.09|0.06|N|O|1998-08-11|1998-08-28|1998-08-22|TAKE BACK RETURN|RAIL|ithely final pinto beans. brave, final hoc +9413|96693|4221|1|33|55759.77|0.04|0.08|N|O|1995-09-19|1995-09-10|1995-10-02|COLLECT COD|AIR|ld packages. requests cajole s +9413|114436|4437|2|41|59467.63|0.01|0.03|N|O|1995-07-25|1995-09-06|1995-07-29|TAKE BACK RETURN|TRUCK|bold foxes nag carefully. ironic pin +9413|119070|6604|3|24|26137.68|0.08|0.06|N|O|1995-08-19|1995-09-06|1995-09-13|COLLECT COD|RAIL| quickly bold requests. blithely ironic fox +9413|222|7723|4|18|20199.96|0.03|0.08|N|O|1995-10-22|1995-08-23|1995-11-10|NONE|TRUCK|ven deposits haggle blithely alo +9414|166411|1444|1|3|4432.23|0.09|0.07|A|F|1993-11-23|1993-11-11|1993-11-25|COLLECT COD|SHIP|ng to the closely regu +9414|54999|5000|2|26|50803.74|0.07|0.03|R|F|1993-12-09|1993-10-15|1993-12-17|TAKE BACK RETURN|FOB|eep furiously from the pending depo +9414|151574|4090|3|39|63397.23|0.01|0.05|R|F|1993-11-20|1993-12-04|1993-12-05|COLLECT COD|MAIL|uriously ironi +9415|188600|8601|1|36|60789.60|0.04|0.01|A|F|1992-08-26|1992-10-27|1992-08-29|NONE|AIR|al deposit +9415|193150|8189|2|32|39780.80|0.06|0.07|R|F|1992-08-25|1992-10-04|1992-09-15|DELIVER IN PERSON|RAIL|long the special, silent re +9415|68978|3991|3|8|15575.76|0.10|0.05|R|F|1992-10-22|1992-11-01|1992-11-14|COLLECT COD|FOB|le according to t +9415|100241|5262|4|25|31031.00|0.10|0.04|R|F|1992-12-11|1992-10-15|1992-12-25|TAKE BACK RETURN|RAIL|rding to the furiously u +9415|135662|689|5|13|22069.58|0.07|0.03|R|F|1992-11-28|1992-11-12|1992-12-22|NONE|AIR|ly about the ironic packages. ironic p +9415|68380|5899|6|38|51238.44|0.00|0.06|R|F|1992-10-13|1992-10-29|1992-10-17|COLLECT COD|REG AIR| theodolites alongside of +9415|55467|7973|7|5|7112.30|0.00|0.01|A|F|1992-09-20|1992-11-01|1992-10-20|COLLECT COD|RAIL|leep alongside of +9440|19472|1974|1|4|5565.88|0.04|0.03|A|F|1994-07-29|1994-07-25|1994-07-30|TAKE BACK RETURN|TRUCK|iously idle +9441|177807|5359|1|2|3769.60|0.08|0.04|N|O|1997-08-25|1997-09-16|1997-09-03|TAKE BACK RETURN|TRUCK|, daring instruction +9442|64332|9345|1|49|63520.17|0.07|0.02|A|F|1993-04-29|1993-05-14|1993-05-03|TAKE BACK RETURN|MAIL|ts snooze carefully ironi +9442|11921|6924|2|21|38491.32|0.08|0.02|A|F|1993-06-17|1993-06-06|1993-07-13|DELIVER IN PERSON|REG AIR| boost furiously at th +9442|152987|8018|3|8|16319.84|0.03|0.01|A|F|1993-03-31|1993-04-11|1993-04-16|DELIVER IN PERSON|RAIL|ckages haggle against the quickly regul +9443|164774|9807|1|20|36775.40|0.10|0.00|N|O|1997-08-15|1997-06-25|1997-08-19|NONE|FOB|nts are blithely unu +9443|155313|344|2|11|15051.41|0.06|0.08|N|O|1997-05-18|1997-06-27|1997-06-15|DELIVER IN PERSON|AIR|ites? quickly unusua +9443|131544|4058|3|28|44115.12|0.02|0.08|N|O|1997-08-08|1997-06-16|1997-08-31|COLLECT COD|SHIP|ronic foxes. carefully f +9443|55167|2683|4|50|56108.00|0.04|0.01|N|O|1997-08-14|1997-06-07|1997-09-09|TAKE BACK RETURN|AIR|ct. fluffily pending foxes alongside of +9443|177161|4713|5|10|12381.60|0.09|0.07|N|O|1997-07-30|1997-07-14|1997-08-12|COLLECT COD|AIR| bold deposits cajole +9444|85626|5627|1|10|16116.20|0.09|0.06|N|O|1996-10-08|1996-10-14|1996-10-09|TAKE BACK RETURN|SHIP|ly furiously ironic excuses. slyly even p +9444|102466|9997|2|12|17621.52|0.01|0.06|N|O|1996-07-23|1996-08-23|1996-08-14|TAKE BACK RETURN|MAIL|ickly ironic ideas s +9444|143269|3270|3|6|7873.56|0.10|0.06|N|O|1996-11-12|1996-10-13|1996-11-25|NONE|MAIL|s sleep slyl +9445|34125|9132|1|22|23300.64|0.06|0.05|N|O|1998-03-06|1997-12-30|1998-03-12|DELIVER IN PERSON|TRUCK|ackages. regularly ironic deposits cajol +9445|129823|2336|2|40|74112.80|0.04|0.08|N|O|1998-01-30|1998-02-02|1998-02-12|NONE|SHIP|inder fluffily. quickly final deposits +9446|124663|2200|1|23|38816.18|0.03|0.00|N|O|1998-04-14|1998-02-06|1998-04-27|COLLECT COD|FOB|deas cajole special accounts. blithely eve +9446|245|246|2|36|41228.64|0.05|0.02|N|O|1998-02-03|1998-02-20|1998-02-28|TAKE BACK RETURN|FOB|. silent deposits sleep. express, +9446|111555|4067|3|49|76760.95|0.09|0.07|N|O|1998-03-05|1998-02-19|1998-03-21|DELIVER IN PERSON|FOB|tions use. carefully even platelets a +9446|103465|5976|4|16|23495.36|0.03|0.01|N|O|1998-04-28|1998-02-25|1998-05-02|NONE|RAIL|nic instructions slee +9446|135837|5838|5|44|82404.52|0.01|0.07|N|O|1998-04-06|1998-03-21|1998-05-04|TAKE BACK RETURN|REG AIR|ake busily regular requests. +9446|195666|8186|6|21|36994.86|0.09|0.05|N|O|1998-02-07|1998-02-11|1998-02-08|DELIVER IN PERSON|REG AIR|le fluffily blithely ironic id +9447|20285|286|1|32|38568.96|0.09|0.08|N|O|1995-07-10|1995-09-01|1995-08-08|DELIVER IN PERSON|FOB|latelets na +9447|119768|2280|2|43|76873.68|0.08|0.03|N|O|1995-10-14|1995-07-23|1995-11-04|DELIVER IN PERSON|FOB| express pinto bean +9472|53105|8116|1|12|12697.20|0.09|0.06|N|O|1995-08-20|1995-08-25|1995-08-23|COLLECT COD|MAIL|ly ironic accounts boost. +9472|133807|3808|2|24|44179.20|0.10|0.03|N|O|1995-07-10|1995-09-05|1995-07-23|TAKE BACK RETURN|REG AIR|s haggle across the slyly even instru +9473|128849|3874|1|36|67602.24|0.01|0.03|R|F|1993-02-02|1992-12-20|1993-02-22|DELIVER IN PERSON|FOB|eposits detect slyl +9473|153732|8763|2|4|7142.92|0.10|0.04|A|F|1992-10-16|1992-12-02|1992-10-29|COLLECT COD|AIR|hely unusual requ +9473|172057|2058|3|23|25968.15|0.07|0.00|R|F|1992-11-15|1992-11-11|1992-12-04|DELIVER IN PERSON|FOB|iously. quickly quiet +9473|159009|4040|4|33|35244.00|0.05|0.06|A|F|1992-11-29|1992-12-14|1992-12-21|COLLECT COD|SHIP|r the always ironi +9473|62934|2935|5|14|26557.02|0.04|0.00|A|F|1993-02-06|1992-12-09|1993-02-25|COLLECT COD|FOB|uses. final excuses haggle. fur +9473|129728|2241|6|50|87886.00|0.04|0.02|A|F|1992-11-03|1993-01-02|1992-11-27|DELIVER IN PERSON|MAIL|riously along the accou +9474|24286|1793|1|9|10892.52|0.09|0.00|N|F|1995-06-10|1995-06-21|1995-06-29|TAKE BACK RETURN|REG AIR| was after the fur +9474|172736|2737|2|44|79584.12|0.10|0.05|N|O|1995-08-28|1995-06-11|1995-09-10|NONE|TRUCK| the quickly pending platelets cajol +9474|164524|4525|3|44|69894.88|0.00|0.06|N|O|1995-08-23|1995-06-13|1995-08-28|NONE|AIR|. slyly express deposits a +9474|154506|9537|4|48|74904.00|0.07|0.00|N|O|1995-07-28|1995-07-17|1995-08-11|COLLECT COD|RAIL|en instructi +9474|171143|1144|5|21|25496.94|0.08|0.05|N|O|1995-08-02|1995-08-02|1995-08-10|COLLECT COD|RAIL|ckly final deposits. slyly final pac +9475|111405|1406|1|3|4249.20|0.00|0.07|N|O|1997-01-12|1997-01-08|1997-01-16|TAKE BACK RETURN|TRUCK|nts are carefully. quickly close +9475|168173|3206|2|50|62058.50|0.07|0.03|N|O|1997-01-02|1996-12-27|1997-01-14|DELIVER IN PERSON|REG AIR| final requests +9475|69055|4068|3|24|24577.20|0.00|0.03|N|O|1997-02-25|1997-02-17|1997-03-02|DELIVER IN PERSON|RAIL|e slyly furiously +9475|194141|9180|4|47|58051.58|0.06|0.08|N|O|1997-03-14|1997-02-17|1997-04-04|COLLECT COD|MAIL|al accounts. b +9476|189211|6766|1|24|31205.04|0.08|0.07|A|F|1994-06-16|1994-08-22|1994-06-22|COLLECT COD|SHIP|ructions mus +9476|55682|3198|2|1|1637.68|0.09|0.06|R|F|1994-08-31|1994-08-02|1994-09-05|NONE|TRUCK|counts. even dolph +9476|39971|4978|3|6|11465.82|0.09|0.07|A|F|1994-07-02|1994-08-08|1994-07-24|COLLECT COD|TRUCK|ly above the regular +9476|175828|3380|4|25|47595.50|0.03|0.00|R|F|1994-07-15|1994-08-09|1994-08-08|TAKE BACK RETURN|MAIL|ring requests. sile +9476|137780|5320|5|2|3635.56|0.02|0.06|R|F|1994-07-04|1994-07-25|1994-07-07|NONE|MAIL|: ironic accounts sleep across the f +9476|66938|6939|6|26|49528.18|0.00|0.00|R|F|1994-08-09|1994-08-22|1994-08-14|TAKE BACK RETURN|TRUCK|y. bold pinto +9476|25270|7773|7|36|43029.72|0.00|0.02|R|F|1994-06-27|1994-07-25|1994-07-26|TAKE BACK RETURN|REG AIR|ts sleep bravely even foxes! fluffil +9477|105052|73|1|3|3171.15|0.06|0.00|N|O|1998-04-07|1998-05-13|1998-04-30|NONE|SHIP|nstructions nag slyly after the flu +9477|199284|4323|2|17|23515.76|0.07|0.06|N|O|1998-05-13|1998-05-27|1998-06-08|TAKE BACK RETURN|AIR|eep at the care +9477|160878|3395|3|45|87249.15|0.07|0.02|N|O|1998-04-18|1998-05-29|1998-04-30|TAKE BACK RETURN|RAIL|ar pinto bea +9477|72177|9699|4|44|50563.48|0.08|0.00|N|O|1998-04-28|1998-05-15|1998-05-04|TAKE BACK RETURN|MAIL|ic foxes. slyly special dependencies tr +9477|62911|7924|5|28|52469.48|0.09|0.03|N|O|1998-04-01|1998-04-19|1998-04-16|COLLECT COD|REG AIR| theodolite +9477|142746|289|6|20|35774.80|0.08|0.02|N|O|1998-04-09|1998-05-10|1998-04-20|TAKE BACK RETURN|FOB|? quickly even instructions are +9477|118889|8890|7|34|64867.92|0.00|0.07|N|O|1998-04-10|1998-06-06|1998-05-03|NONE|SHIP|ully final ideas acco +9478|163525|3526|1|19|30181.88|0.09|0.05|A|F|1994-07-05|1994-06-21|1994-07-06|DELIVER IN PERSON|REG AIR|ously. carefully final reque +9478|158313|8314|2|44|60337.64|0.05|0.00|R|F|1994-05-01|1994-05-21|1994-05-09|COLLECT COD|TRUCK|iously bold packages ar +9478|155703|3249|3|15|26380.50|0.05|0.02|R|F|1994-07-12|1994-05-13|1994-07-16|COLLECT COD|TRUCK|y even requests haggle quickly i +9478|98579|6107|4|35|55214.95|0.10|0.04|R|F|1994-05-10|1994-05-24|1994-06-08|NONE|SHIP|le carefully +9479|86472|1489|1|42|61255.74|0.02|0.05|A|F|1994-10-23|1994-12-16|1994-11-05|DELIVER IN PERSON|RAIL|sits. slyly even excuses nag quic +9504|136766|9280|1|28|50477.28|0.08|0.03|A|F|1992-12-07|1993-01-08|1992-12-25|DELIVER IN PERSON|MAIL|e the furiously pending +9504|11167|6170|2|44|47439.04|0.05|0.03|R|F|1993-03-08|1993-02-11|1993-03-28|NONE|MAIL|e of the final, unusual accounts. f +9504|69703|2210|3|48|80289.60|0.08|0.05|A|F|1992-12-14|1993-02-21|1992-12-23|TAKE BACK RETURN|MAIL|s; closely ironic asymptotes accor +9504|94552|2080|4|11|17012.05|0.09|0.07|R|F|1993-01-24|1993-02-07|1993-02-09|COLLECT COD|MAIL|print blithely fl +9505|142134|2135|1|21|24698.73|0.06|0.02|A|F|1992-10-07|1992-08-23|1992-11-05|TAKE BACK RETURN|MAIL|ld instructions. blithely bold ideas use sl +9505|31216|3720|2|14|16060.94|0.07|0.04|R|F|1992-06-16|1992-08-23|1992-07-14|DELIVER IN PERSON|RAIL|gedly pending pinto beans. ironi +9505|40542|5551|3|32|47441.28|0.08|0.02|A|F|1992-06-13|1992-08-05|1992-06-19|TAKE BACK RETURN|MAIL|ckages. always final accounts play +9505|176188|8706|4|49|61944.82|0.00|0.06|R|F|1992-08-20|1992-07-13|1992-08-25|DELIVER IN PERSON|MAIL|quests. carefully ironic pla +9505|185902|3457|5|25|49697.50|0.05|0.04|R|F|1992-09-14|1992-07-12|1992-10-02|COLLECT COD|TRUCK|arefully final accounts are across the +9505|38547|6057|6|5|7427.70|0.04|0.08|R|F|1992-09-16|1992-07-25|1992-09-28|DELIVER IN PERSON|TRUCK|odolites. carefully express +9505|48756|3765|7|46|78418.50|0.05|0.07|A|F|1992-07-09|1992-08-28|1992-08-03|DELIVER IN PERSON|MAIL|ep slyly bli +9506|39741|2245|1|38|63868.12|0.07|0.04|A|F|1994-06-02|1994-04-10|1994-06-27|DELIVER IN PERSON|TRUCK|hlessly around +9507|13584|3585|1|33|49420.14|0.03|0.03|A|F|1995-01-28|1995-02-02|1995-02-19|DELIVER IN PERSON|FOB|hely carefully express fox +9508|149318|6861|1|4|5469.24|0.04|0.02|N|O|1996-08-18|1996-06-19|1996-09-08|NONE|TRUCK|aggle furiously among +9508|184998|7517|2|46|95817.54|0.06|0.01|N|O|1996-06-20|1996-06-10|1996-06-28|DELIVER IN PERSON|TRUCK| cajole carefull +9508|59432|9433|3|41|57048.63|0.04|0.02|N|O|1996-07-01|1996-07-16|1996-07-20|DELIVER IN PERSON|REG AIR|egular ideas solve permanently +9508|65872|3391|4|24|44108.88|0.01|0.01|N|O|1996-08-10|1996-05-29|1996-08-23|COLLECT COD|REG AIR|bold foxes haggle slyly. ironic, +9508|109271|6802|5|42|53771.34|0.02|0.00|N|O|1996-06-10|1996-07-20|1996-07-09|COLLECT COD|RAIL|ages. furi +9508|105039|2570|6|17|17748.51|0.09|0.01|N|O|1996-06-25|1996-06-03|1996-07-22|COLLECT COD|TRUCK| deposits nag. carefully silent theodolites +9509|17281|7282|1|45|53922.60|0.01|0.01|A|F|1993-01-31|1992-12-15|1993-02-08|NONE|TRUCK|nding pinto beans cajole blithely carefull +9509|36568|1575|2|41|61686.96|0.08|0.07|A|F|1992-12-16|1992-11-15|1992-12-23|DELIVER IN PERSON|MAIL|press packages +9509|196916|6917|3|22|44284.02|0.07|0.06|R|F|1993-01-02|1992-11-20|1993-01-24|DELIVER IN PERSON|REG AIR|lar deposits to the sl +9509|160021|5054|4|49|52969.98|0.10|0.05|R|F|1993-01-30|1992-12-27|1993-02-05|NONE|REG AIR|d patterns. quickly pending packag +9509|70870|5885|5|9|16567.83|0.03|0.05|R|F|1992-10-24|1992-11-22|1992-11-06|COLLECT COD|REG AIR| final courts sle +9510|135947|8461|1|3|5948.82|0.10|0.08|N|O|1997-02-08|1996-12-23|1997-02-21|DELIVER IN PERSON|FOB|e. quickly regular deposits in +9510|50303|5314|2|24|30079.20|0.10|0.01|N|O|1997-02-04|1997-02-12|1997-02-05|COLLECT COD|TRUCK|fully about the accounts. even excuses gr +9510|28175|5682|3|49|54055.33|0.02|0.05|N|O|1996-12-29|1997-01-06|1997-01-19|COLLECT COD|AIR|s against the pending pinto beans so +9511|42418|4923|1|45|61218.45|0.05|0.01|N|O|1996-10-29|1996-10-17|1996-11-20|DELIVER IN PERSON|REG AIR|ealthily regula +9511|108580|1091|2|39|61954.62|0.02|0.03|N|O|1996-11-24|1996-10-04|1996-12-15|DELIVER IN PERSON|TRUCK|ending theodolite +9536|162621|5138|1|23|38723.26|0.00|0.03|N|O|1997-09-14|1997-11-09|1997-09-20|TAKE BACK RETURN|TRUCK|ts. requests sleep carefully about the care +9536|167762|5311|2|29|53063.04|0.01|0.00|N|O|1997-11-20|1997-10-13|1997-11-22|NONE|REG AIR|final requests. slyly ironic foxes +9536|169803|9804|3|16|29964.80|0.06|0.00|N|O|1997-09-18|1997-10-03|1997-10-18|NONE|RAIL|efully pending deposits according +9537|83262|5771|1|39|48565.14|0.07|0.04|A|F|1995-02-25|1995-04-25|1995-03-10|TAKE BACK RETURN|REG AIR|hely regular pinto beans on th +9537|182340|4859|2|45|64005.30|0.08|0.00|R|F|1995-03-18|1995-04-16|1995-03-28|NONE|REG AIR|pitaphs cajole fu +9537|180554|8109|3|45|73554.75|0.05|0.02|A|F|1995-03-09|1995-05-11|1995-03-25|DELIVER IN PERSON|REG AIR|uthless packages haggle enticingly. re +9537|165664|3213|4|24|41511.84|0.04|0.06|R|F|1995-05-17|1995-05-12|1995-05-29|DELIVER IN PERSON|RAIL|its. slyly furious +9538|178612|1130|1|19|32121.59|0.02|0.03|A|F|1994-03-21|1994-05-15|1994-03-31|DELIVER IN PERSON|SHIP|h. quickly special requests wake. slyly reg +9539|110937|938|1|29|56489.97|0.09|0.00|N|O|1996-01-20|1995-12-19|1996-02-04|COLLECT COD|FOB| packages haggle furious +9540|30245|7755|1|36|42308.64|0.02|0.01|R|F|1994-09-07|1994-07-23|1994-09-15|TAKE BACK RETURN|MAIL| accounts bo +9540|125559|8072|2|47|74473.85|0.03|0.01|A|F|1994-06-28|1994-09-03|1994-06-29|DELIVER IN PERSON|AIR|out the regular sauternes. carefully +9541|107323|9834|1|43|57203.76|0.10|0.05|R|F|1992-07-14|1992-04-30|1992-08-08|COLLECT COD|FOB|nding depos +9541|175495|5496|2|40|62819.60|0.01|0.01|A|F|1992-06-25|1992-05-24|1992-06-27|DELIVER IN PERSON|SHIP| are fluffily final sauternes. express +9542|80553|8078|1|43|65942.65|0.04|0.06|N|O|1996-02-23|1996-02-12|1996-03-15|NONE|SHIP|eposits sleep slyly. thinly +9542|37947|451|2|37|69742.78|0.01|0.00|N|O|1996-04-15|1996-02-05|1996-05-09|COLLECT COD|RAIL|sits sleep finally ideas; final, final +9543|25382|7885|1|3|3922.14|0.10|0.06|A|F|1992-08-03|1992-08-03|1992-08-21|NONE|AIR|counts cajole careful +9543|188109|628|2|35|41898.50|0.08|0.00|A|F|1992-06-22|1992-07-31|1992-07-06|NONE|FOB|ously pending instructions after the +9543|143570|6085|3|37|59702.09|0.01|0.01|R|F|1992-05-25|1992-06-25|1992-06-10|TAKE BACK RETURN|SHIP|st after the slyly final request +9543|174941|2493|4|23|46366.62|0.10|0.03|A|F|1992-09-01|1992-06-27|1992-09-17|NONE|SHIP|nto beans. regular, ironic +9568|51138|3644|1|37|40297.81|0.08|0.07|A|F|1993-05-15|1993-05-23|1993-05-25|NONE|FOB|after the carefully +9568|65635|8142|2|19|30411.97|0.06|0.05|R|F|1993-04-25|1993-04-19|1993-05-03|TAKE BACK RETURN|FOB|e carefully +9569|40304|5313|1|44|54749.20|0.08|0.04|N|O|1997-11-30|1998-01-03|1997-12-19|TAKE BACK RETURN|AIR| silent packages doubt blithel +9569|180402|2921|2|25|37060.00|0.04|0.05|N|O|1998-01-19|1997-12-22|1998-02-08|NONE|TRUCK|heaves! carefully expr +9569|15706|8208|3|30|48651.00|0.07|0.00|N|O|1998-02-23|1997-12-08|1998-03-02|COLLECT COD|TRUCK|ckages are +9569|167758|275|4|40|73030.00|0.00|0.02|N|O|1997-11-15|1997-12-15|1997-11-26|NONE|RAIL|ial accounts cajole. furiously even depen +9569|97572|5100|5|10|15695.70|0.07|0.06|N|O|1998-01-09|1997-12-12|1998-01-13|COLLECT COD|REG AIR|ly unusual pinto beans. bold ideas a +9570|78583|8584|1|6|9369.48|0.02|0.06|N|O|1996-06-19|1996-07-15|1996-06-27|NONE|AIR|ounts detect +9570|135805|832|2|7|12885.60|0.02|0.05|N|O|1996-06-08|1996-07-16|1996-06-17|DELIVER IN PERSON|TRUCK|the unusual packages. pending +9570|65140|5141|3|20|22102.80|0.09|0.07|N|O|1996-09-06|1996-08-06|1996-09-17|COLLECT COD|RAIL|ges about the pe +9570|198168|688|4|6|7596.96|0.01|0.04|N|O|1996-07-12|1996-07-10|1996-07-19|DELIVER IN PERSON|REG AIR|c pinto beans caj +9570|2309|9810|5|19|23014.70|0.06|0.07|N|O|1996-06-18|1996-08-07|1996-06-22|DELIVER IN PERSON|AIR|excuses dazzle carefully accor +9571|134976|3|1|4|8043.88|0.07|0.04|N|O|1996-08-10|1996-06-01|1996-08-25|TAKE BACK RETURN|FOB|posits sleep. quickly +9571|134589|7103|2|45|73061.10|0.06|0.01|N|O|1996-06-21|1996-07-14|1996-07-20|TAKE BACK RETURN|SHIP|nal requests b +9572|41732|1733|1|33|55233.09|0.08|0.02|N|O|1998-06-13|1998-06-02|1998-06-30|COLLECT COD|TRUCK|lent packages sl +9572|173131|683|2|17|20470.21|0.10|0.00|N|O|1998-05-13|1998-05-30|1998-05-27|TAKE BACK RETURN|REG AIR|nic pinto beans haggl +9572|10558|5561|3|21|30839.55|0.07|0.01|N|O|1998-04-29|1998-04-27|1998-05-23|COLLECT COD|AIR| deposits cajole qui +9573|124255|4256|1|5|6396.25|0.01|0.00|R|F|1992-09-23|1992-08-02|1992-10-20|NONE|AIR|l, final packages detect blithely +9573|141184|6213|2|45|55133.10|0.04|0.00|R|F|1992-09-05|1992-07-19|1992-09-14|NONE|TRUCK|regular requests caj +9573|67876|2889|3|50|92193.50|0.08|0.07|A|F|1992-07-12|1992-07-16|1992-07-16|NONE|AIR|g the fluffily quiet asymptotes. unus +9574|130456|457|1|48|71349.60|0.04|0.03|N|O|1995-09-13|1995-09-02|1995-10-12|COLLECT COD|RAIL| final dependen +9574|166446|6447|2|24|36298.56|0.04|0.06|N|O|1995-08-01|1995-09-20|1995-08-18|COLLECT COD|FOB|refully express decoys boost furious +9574|47833|5346|3|38|67671.54|0.04|0.00|N|O|1995-11-16|1995-10-22|1995-11-23|NONE|MAIL| packages affix. +9575|117151|4685|1|2|2336.30|0.10|0.06|R|F|1992-07-01|1992-06-05|1992-07-19|TAKE BACK RETURN|REG AIR|nding packages wake quickly. furio +9575|143007|8036|2|19|19950.00|0.07|0.08|A|F|1992-04-15|1992-06-09|1992-05-09|DELIVER IN PERSON|RAIL|y express w +9600|150890|891|1|40|77635.60|0.03|0.00|A|F|1994-02-01|1994-01-13|1994-02-24|DELIVER IN PERSON|REG AIR|he express requests. bold pack +9600|1529|4030|2|3|4291.56|0.01|0.03|R|F|1993-12-19|1993-12-28|1994-01-15|DELIVER IN PERSON|MAIL| realms. even, regular frets sl +9600|86351|3876|3|24|32096.40|0.08|0.08|R|F|1993-12-11|1993-12-15|1993-12-20|TAKE BACK RETURN|TRUCK|ly blithely final ins +9601|30052|53|1|25|24551.25|0.00|0.06|N|O|1996-04-07|1996-04-24|1996-05-04|NONE|SHIP|uffily regular packages engage slyly st +9601|72394|2395|2|28|38258.92|0.10|0.05|N|O|1996-03-31|1996-04-21|1996-04-30|DELIVER IN PERSON|MAIL|g foxes wake among +9601|122791|2792|3|17|30834.43|0.04|0.05|N|O|1996-06-29|1996-05-18|1996-07-12|TAKE BACK RETURN|FOB|nto beans +9601|137381|2408|4|14|19857.32|0.02|0.08|N|O|1996-06-10|1996-06-10|1996-06-24|TAKE BACK RETURN|SHIP|ously special a +9601|160371|372|5|21|30058.77|0.10|0.07|N|O|1996-05-04|1996-05-05|1996-06-03|TAKE BACK RETURN|MAIL|-- furiously final accou +9602|3426|5927|1|24|31906.08|0.04|0.05|A|F|1993-01-21|1992-12-28|1993-02-19|NONE|AIR|ithes are after the sly +9602|179455|1973|2|44|67515.80|0.05|0.03|R|F|1993-01-09|1993-01-01|1993-01-25|DELIVER IN PERSON|RAIL|xpress excuses wak +9602|97604|2623|3|20|32032.00|0.09|0.02|A|F|1993-02-16|1993-01-29|1993-02-26|COLLECT COD|AIR|efully accounts. slyly +9602|18612|1114|4|28|42857.08|0.04|0.00|R|F|1992-11-15|1993-01-12|1992-11-21|COLLECT COD|SHIP|fluffily special accounts. c +9602|196886|1925|5|19|37674.72|0.06|0.02|A|F|1993-01-17|1993-02-07|1993-01-31|COLLECT COD|RAIL|the quickly final accounts. reg +9603|188171|3208|1|46|57921.82|0.08|0.02|N|O|1998-04-08|1998-02-13|1998-04-19|DELIVER IN PERSON|FOB|ifts nod. slyly regular accounts nag +9603|189801|4838|2|36|68068.80|0.05|0.03|N|O|1998-03-10|1998-03-15|1998-03-22|NONE|RAIL|sts. slyly silent hockey players s +9603|172767|319|3|11|20237.36|0.02|0.04|N|O|1998-04-22|1998-02-12|1998-05-11|NONE|TRUCK|ending depth +9603|90840|8368|4|26|47601.84|0.05|0.06|N|O|1998-04-25|1998-03-12|1998-04-27|TAKE BACK RETURN|MAIL|ake furiously around th +9603|139221|6761|5|45|56709.90|0.01|0.02|N|O|1998-01-14|1998-04-02|1998-01-20|DELIVER IN PERSON|TRUCK|raids sleep carefully. deposits +9603|73456|3457|6|33|47171.85|0.10|0.05|N|O|1998-04-25|1998-03-20|1998-05-15|NONE|MAIL|nly bold theodolites. unusual +9604|199340|6898|1|26|37422.84|0.04|0.03|N|O|1996-07-15|1996-08-13|1996-08-11|DELIVER IN PERSON|FOB|ly unusual requests. carefully express d +9605|187052|4607|1|22|25059.10|0.04|0.02|R|F|1993-03-24|1993-02-08|1993-04-01|TAKE BACK RETURN|MAIL| haggle fluffily. blithely final +9605|177771|289|2|48|88740.96|0.08|0.01|R|F|1993-02-10|1993-03-23|1993-02-25|DELIVER IN PERSON|FOB|. theodoli +9606|144368|1911|1|45|63556.20|0.00|0.04|A|F|1994-08-24|1994-09-17|1994-09-07|TAKE BACK RETURN|SHIP|heodolites. slyly bold theodolite +9606|178683|1201|2|18|31710.24|0.05|0.04|R|F|1994-08-11|1994-10-11|1994-08-13|DELIVER IN PERSON|RAIL| use slyly across the pending, +9606|113580|6092|3|7|11155.06|0.00|0.01|A|F|1994-08-07|1994-10-25|1994-08-24|TAKE BACK RETURN|AIR|ly pending packages +9606|139012|4039|4|23|24173.23|0.08|0.00|R|F|1994-10-25|1994-09-10|1994-11-21|TAKE BACK RETURN|AIR|ies boost slyly furiously express ide +9606|162432|9981|5|14|20922.02|0.04|0.08|R|F|1994-11-05|1994-09-23|1994-11-23|DELIVER IN PERSON|TRUCK|ss the carefully pendin +9607|152253|2254|1|33|43073.25|0.08|0.04|N|O|1996-01-07|1996-03-11|1996-01-24|DELIVER IN PERSON|SHIP|packages wake quickly. +9632|146679|6680|1|31|53495.77|0.08|0.01|R|F|1992-04-30|1992-04-07|1992-05-22|NONE|AIR|essly. carefully ironi +9632|27554|7555|2|9|13333.95|0.07|0.04|R|F|1992-02-28|1992-04-12|1992-03-02|TAKE BACK RETURN|TRUCK|he furiously +9632|95106|7616|3|46|50650.60|0.05|0.07|A|F|1992-02-26|1992-03-17|1992-03-03|DELIVER IN PERSON|SHIP|orges cajole furiously slyly un +9632|30594|8104|4|8|12196.72|0.01|0.02|A|F|1992-05-05|1992-04-12|1992-06-03|NONE|RAIL| the carefully ex +9633|59955|9956|1|36|68938.20|0.07|0.06|N|O|1995-12-12|1995-11-15|1996-01-05|COLLECT COD|SHIP|nto beans. slyly speci +9633|54783|7289|2|43|74724.54|0.09|0.04|N|O|1995-12-26|1995-11-09|1996-01-10|DELIVER IN PERSON|MAIL|s after the slyly final requests are fluffi +9633|135364|2904|3|42|58773.12|0.05|0.00|N|O|1995-09-15|1995-11-09|1995-10-15|NONE|FOB| unusual ideas are above the quickl +9633|58995|1501|4|12|23447.88|0.09|0.04|N|O|1995-11-12|1995-11-13|1995-11-18|COLLECT COD|AIR|t foxes. ironic ideas haggle c +9633|121099|8636|5|11|12320.99|0.09|0.06|N|O|1995-12-04|1995-11-20|1995-12-14|COLLECT COD|FOB|believe carefully furiously ev +9634|89345|6870|1|43|57376.62|0.06|0.04|N|O|1998-02-23|1998-03-01|1998-03-05|COLLECT COD|SHIP|platelets. expre +9634|11823|4325|2|25|43370.50|0.00|0.07|N|O|1998-04-21|1998-03-30|1998-04-27|NONE|TRUCK|fully regularly regular courts. depos +9634|103771|8792|3|19|33720.63|0.07|0.02|N|O|1998-04-17|1998-02-17|1998-05-05|DELIVER IN PERSON|MAIL|se slyly after the sly +9634|71160|3668|4|47|53164.52|0.09|0.05|N|O|1998-05-03|1998-02-12|1998-05-24|NONE|TRUCK|foxes thrash quickly bold +9634|183506|8543|5|27|42916.50|0.10|0.06|N|O|1998-03-26|1998-03-06|1998-04-14|DELIVER IN PERSON|MAIL|usual accounts. even requests nag bli +9634|169366|4399|6|48|68897.28|0.01|0.03|N|O|1998-04-03|1998-03-20|1998-04-12|TAKE BACK RETURN|FOB| furiously among the furiously express inst +9635|58860|3871|1|11|20007.46|0.07|0.08|A|F|1994-05-02|1994-06-08|1994-05-18|DELIVER IN PERSON|SHIP|gular packages nag +9635|50334|335|2|30|38529.90|0.05|0.07|R|F|1994-07-14|1994-06-25|1994-07-19|NONE|REG AIR|dolites sleep. busy, unusual requests +9635|156763|1794|3|19|34575.44|0.09|0.03|A|F|1994-08-08|1994-06-09|1994-08-26|NONE|FOB|final packages cajole f +9635|112469|3|4|12|17777.52|0.05|0.06|R|F|1994-07-09|1994-06-05|1994-07-31|TAKE BACK RETURN|MAIL|eposits haggl +9635|55848|5849|5|26|46899.84|0.03|0.02|A|F|1994-07-24|1994-05-29|1994-08-21|NONE|FOB|s detect furiously even accounts. quickly +9635|33812|8819|6|28|48882.68|0.06|0.01|R|F|1994-08-11|1994-06-14|1994-08-24|DELIVER IN PERSON|SHIP| quickly about the theodolites. un +9636|14487|9490|1|47|65869.56|0.02|0.02|N|O|1997-02-05|1997-03-31|1997-02-26|TAKE BACK RETURN|AIR| even deposits wake slyly a +9636|73732|8747|2|36|61406.28|0.08|0.02|N|O|1997-02-10|1997-04-14|1997-03-05|NONE|SHIP|ickly darin +9636|8147|648|3|5|5275.70|0.00|0.04|N|O|1997-05-25|1997-03-07|1997-06-16|TAKE BACK RETURN|SHIP|uctions are carefu +9637|63519|6026|1|45|66712.95|0.10|0.02|R|F|1994-03-24|1994-02-28|1994-03-30|COLLECT COD|SHIP|even foxes doubt slyly. quickly stealthy +9637|147364|4907|2|6|8468.16|0.05|0.02|A|F|1994-03-18|1994-04-04|1994-03-28|DELIVER IN PERSON|MAIL|s. instructions nag quickly. carefully +9637|136557|9071|3|33|52587.15|0.05|0.01|R|F|1994-02-27|1994-04-02|1994-03-26|NONE|FOB|y ironic deposits was blithely accord +9637|110850|5873|4|1|1860.85|0.02|0.02|A|F|1994-03-21|1994-03-19|1994-04-15|TAKE BACK RETURN|FOB|ccounts solve furiously blithely +9638|167879|396|1|48|93449.76|0.06|0.07|N|O|1996-09-26|1996-09-06|1996-10-15|NONE|FOB| around the pe +9638|134563|7077|2|4|6390.24|0.06|0.02|N|O|1996-07-03|1996-08-07|1996-07-28|COLLECT COD|FOB|fily special, regular deposits? sly +9638|197483|2522|3|6|9482.88|0.03|0.04|N|O|1996-07-24|1996-08-24|1996-08-02|TAKE BACK RETURN|FOB|ding accounts! furiously ironic deposits +9638|94737|4738|4|10|17317.30|0.00|0.06|N|O|1996-09-04|1996-09-04|1996-09-21|COLLECT COD|SHIP|e special, regular pinto beans int +9639|32155|7162|1|34|36963.10|0.06|0.05|R|F|1993-10-23|1993-11-24|1993-11-01|TAKE BACK RETURN|RAIL|fter the furiously final +9639|22990|497|2|42|80345.58|0.09|0.08|A|F|1993-09-24|1993-11-16|1993-09-27|NONE|MAIL|. carefully fi +9639|180852|3371|3|33|63784.05|0.01|0.03|A|F|1993-10-28|1993-11-22|1993-11-01|COLLECT COD|TRUCK|boost boldly across the furious +9639|179538|7090|4|2|3235.06|0.10|0.04|A|F|1993-11-22|1993-11-01|1993-12-21|NONE|TRUCK|each along the bold foxes. +9639|94490|9509|5|44|65317.56|0.02|0.07|A|F|1993-12-28|1993-10-18|1994-01-16|DELIVER IN PERSON|MAIL|uickly ironi +9639|88113|5638|6|3|3303.33|0.10|0.07|A|F|1993-11-13|1993-10-14|1993-12-13|TAKE BACK RETURN|RAIL|the regular, unusual requests. +9639|110576|3088|7|6|9519.42|0.01|0.03|A|F|1993-12-21|1993-11-26|1993-12-30|TAKE BACK RETURN|AIR|ar accounts integrate slyly alongside +9664|35714|8218|1|50|82485.50|0.09|0.07|A|F|1993-04-18|1993-05-28|1993-04-22|DELIVER IN PERSON|MAIL|packages nag furiously +9664|35214|221|2|1|1149.21|0.00|0.04|A|F|1993-06-01|1993-06-06|1993-06-19|TAKE BACK RETURN|AIR|es poach blithely. caref +9664|30960|5967|3|37|69965.52|0.08|0.03|R|F|1993-05-30|1993-05-27|1993-06-04|COLLECT COD|TRUCK|es sleep about the furiousl +9665|88355|5880|1|11|14776.85|0.06|0.00|R|F|1994-05-11|1994-06-28|1994-06-04|TAKE BACK RETURN|MAIL|y across the quickly even frays? fluffi +9665|182360|4879|2|5|7211.80|0.02|0.04|A|F|1994-06-27|1994-06-12|1994-07-21|NONE|RAIL|ly ironic tithes +9665|116755|4289|3|50|88587.50|0.02|0.04|R|F|1994-07-31|1994-07-12|1994-08-11|TAKE BACK RETURN|REG AIR| ironic deposits. final warhorses h +9666|95963|5964|1|32|62686.72|0.00|0.02|N|O|1996-06-27|1996-07-09|1996-07-01|DELIVER IN PERSON|RAIL|into beans. quickly unusual asymptotes h +9666|43024|5529|2|49|47383.98|0.07|0.08|N|O|1996-06-03|1996-07-08|1996-06-07|DELIVER IN PERSON|SHIP|fully regular requests +9666|97079|9589|3|2|2152.14|0.04|0.01|N|O|1996-05-19|1996-06-25|1996-05-20|DELIVER IN PERSON|SHIP|could have to sublate i +9666|194928|9967|4|46|93054.32|0.03|0.02|N|O|1996-06-12|1996-08-05|1996-06-13|COLLECT COD|AIR|regular accounts haggle f +9666|148399|3428|5|8|11579.12|0.09|0.07|N|O|1996-07-06|1996-07-24|1996-07-30|TAKE BACK RETURN|SHIP|slyly. account +9666|141975|7004|6|12|24203.64|0.03|0.02|N|O|1996-06-05|1996-07-02|1996-07-04|DELIVER IN PERSON|MAIL|uickly special accounts use abo +9667|21696|4199|1|16|25883.04|0.03|0.08|N|O|1996-04-11|1996-05-11|1996-05-11|DELIVER IN PERSON|RAIL|he regular request +9667|34359|4360|2|43|55614.05|0.04|0.04|N|O|1996-04-29|1996-04-04|1996-05-15|COLLECT COD|SHIP| silent instructions. quickly regular th +9667|61109|8628|3|38|40663.80|0.03|0.04|N|O|1996-06-19|1996-05-17|1996-07-07|NONE|FOB| regular accounts +9667|43101|614|4|8|8352.80|0.07|0.02|N|O|1996-04-01|1996-05-14|1996-04-16|DELIVER IN PERSON|RAIL| after the final requests sle +9667|192388|4908|5|25|37009.50|0.09|0.04|N|O|1996-03-28|1996-04-16|1996-04-06|DELIVER IN PERSON|TRUCK|heodolites detect +9667|61785|9304|6|7|12227.46|0.06|0.06|N|O|1996-03-01|1996-03-27|1996-03-16|DELIVER IN PERSON|REG AIR|gular realms cajole sl +9667|11734|4236|7|16|26331.68|0.09|0.00|N|O|1996-04-26|1996-04-30|1996-05-20|COLLECT COD|REG AIR|ccounts wake f +9668|198979|1499|1|41|85196.77|0.04|0.04|R|F|1994-10-06|1994-10-07|1994-11-02|NONE|AIR|es boost furiously. courts sleep blit +9669|79922|2430|1|49|93194.08|0.08|0.04|R|F|1994-06-19|1994-07-14|1994-06-25|TAKE BACK RETURN|TRUCK|mpress blithely pending +9670|32654|5158|1|44|69812.60|0.10|0.07|N|O|1998-02-14|1997-12-15|1998-03-09|DELIVER IN PERSON|AIR|boost against the +9670|1896|9397|2|34|61128.26|0.01|0.04|N|O|1998-01-20|1997-12-25|1998-02-14|TAKE BACK RETURN|TRUCK|thely sentiments. +9670|57916|422|3|27|50595.57|0.06|0.04|N|O|1997-11-27|1998-01-25|1997-12-27|COLLECT COD|FOB|g packages. quickly pending ideas c +9670|184117|1672|4|46|55251.06|0.06|0.03|N|O|1998-01-07|1998-02-05|1998-01-23|COLLECT COD|SHIP|bold, pending requests ki +9671|173606|8641|1|50|83980.00|0.07|0.07|N|O|1995-10-28|1995-11-15|1995-11-24|COLLECT COD|TRUCK|equests sleep blithely +9671|193774|8813|2|18|33619.86|0.10|0.07|N|O|1995-12-10|1995-12-01|1995-12-12|NONE|TRUCK|uffy asymptotes a +9671|155470|3016|3|32|48815.04|0.06|0.00|N|O|1995-10-07|1995-11-02|1995-10-14|NONE|TRUCK|o beans. carefully pending requ +9696|169143|6692|1|43|52122.02|0.07|0.07|A|F|1995-05-24|1995-03-31|1995-05-31|TAKE BACK RETURN|TRUCK|efully accounts. blith +9696|176762|6763|2|28|51485.28|0.03|0.03|A|F|1995-03-28|1995-05-06|1995-04-04|COLLECT COD|REG AIR|ing accounts are. ironic packages nag af +9696|25919|5920|3|49|90400.59|0.01|0.04|A|F|1995-04-08|1995-04-21|1995-04-20|NONE|AIR|s poach furiously pending, ironic instru +9696|14948|2452|4|37|68928.78|0.07|0.05|N|F|1995-06-08|1995-04-01|1995-06-20|DELIVER IN PERSON|TRUCK|usual pains! ironic, even acco +9697|129726|2239|1|8|14045.76|0.10|0.05|A|F|1995-02-26|1995-04-16|1995-03-25|COLLECT COD|RAIL|ns. even requests nod alon +9697|96814|6815|2|21|38027.01|0.08|0.03|R|F|1995-04-06|1995-03-10|1995-04-23|NONE|FOB|egular theodolites boost carefully +9697|137535|5075|3|6|9435.18|0.09|0.08|R|F|1995-02-05|1995-03-30|1995-02-07|NONE|RAIL|ily regular accounts doze furiously. i +9697|147922|2951|4|19|37428.48|0.04|0.04|A|F|1995-02-08|1995-04-05|1995-03-02|NONE|RAIL|le carefully foxes. enti +9697|113678|8701|5|34|57516.78|0.05|0.02|A|F|1995-04-16|1995-04-16|1995-05-10|NONE|AIR|requests de +9697|175102|5103|6|39|45906.90|0.07|0.01|A|F|1995-03-25|1995-03-31|1995-04-23|DELIVER IN PERSON|RAIL|ix fluffily accounts. qui +9698|70382|2890|1|5|6761.90|0.08|0.04|N|O|1995-09-15|1995-10-18|1995-10-11|COLLECT COD|AIR|e furiously +9699|22967|2968|1|10|18899.60|0.10|0.06|A|F|1995-03-29|1995-04-18|1995-04-21|DELIVER IN PERSON|TRUCK|o beans use slyly a +9700|26812|4319|1|47|81724.07|0.10|0.02|N|O|1995-11-12|1995-10-16|1995-12-03|NONE|REG AIR|are furiously pend +9700|25400|7903|2|42|55666.80|0.06|0.06|N|O|1995-11-15|1995-10-19|1995-12-10|TAKE BACK RETURN|AIR|ess foxes. slyly unusual deposits wake ca +9700|88280|5805|3|42|53267.76|0.04|0.04|N|O|1995-11-26|1995-09-20|1995-11-27|NONE|FOB|ts nag. furiousl +9700|117589|7590|4|44|70689.52|0.03|0.00|N|O|1995-08-30|1995-09-20|1995-09-28|NONE|FOB|s haggle. special accounts about +9700|110347|348|5|31|42077.54|0.08|0.03|N|O|1995-08-31|1995-10-25|1995-09-12|TAKE BACK RETURN|AIR|lly unusual requests. furiousl +9700|195678|3236|6|9|15963.03|0.01|0.06|N|O|1995-10-25|1995-09-30|1995-11-06|DELIVER IN PERSON|REG AIR|ly regular theodolit +9701|159445|6991|1|33|49646.52|0.03|0.07|A|F|1993-04-29|1993-05-09|1993-05-07|NONE|RAIL|g, even deposit +9701|190939|5978|2|32|64957.76|0.02|0.01|R|F|1993-03-20|1993-05-01|1993-03-26|TAKE BACK RETURN|MAIL| ironic accounts wake c +9701|107213|7214|3|17|20743.57|0.06|0.03|R|F|1993-05-28|1993-05-17|1993-06-24|NONE|SHIP|ironic pinto beans nag furiously expres +9701|125092|5093|4|36|40215.24|0.10|0.00|R|F|1993-04-20|1993-04-03|1993-05-12|DELIVER IN PERSON|MAIL|l asymptotes use +9701|16569|4073|5|38|56451.28|0.04|0.08|A|F|1993-05-07|1993-04-23|1993-05-12|DELIVER IN PERSON|SHIP|daring pinto beans cajole quickly accord +9701|71111|6126|6|43|46530.73|0.03|0.05|A|F|1993-06-26|1993-05-04|1993-07-01|TAKE BACK RETURN|TRUCK|pinto beans. ex +9701|155369|5370|7|2|2848.72|0.06|0.00|R|F|1993-06-19|1993-04-02|1993-07-11|TAKE BACK RETURN|RAIL|ld courts. bold, bold +9702|82467|7484|1|18|26090.28|0.09|0.05|N|O|1996-11-07|1996-10-15|1996-11-15|TAKE BACK RETURN|AIR|ed theodolites. ironic accounts hang bl +9702|12117|9621|2|14|14407.54|0.05|0.06|N|O|1996-10-10|1996-10-06|1996-10-14|DELIVER IN PERSON|AIR|. final packages ato +9702|37261|2268|3|5|5991.30|0.08|0.00|N|O|1996-09-02|1996-10-16|1996-09-24|COLLECT COD|RAIL|lithely special accounts shall kind +9702|30981|3485|4|37|70743.26|0.06|0.06|N|O|1996-10-08|1996-09-27|1996-10-25|DELIVER IN PERSON|FOB|ly unusual deposits haggle carefull +9702|97005|9515|5|28|28056.00|0.07|0.07|N|O|1996-11-25|1996-11-14|1996-12-03|TAKE BACK RETURN|TRUCK|heodolites sleep furiously special exc +9702|152267|7298|6|17|22427.42|0.04|0.06|N|O|1996-09-16|1996-11-04|1996-10-02|DELIVER IN PERSON|SHIP| special platelets. carefully bold account +9702|136243|6244|7|9|11513.16|0.09|0.06|N|O|1996-10-29|1996-11-02|1996-11-12|DELIVER IN PERSON|TRUCK| blithely even requests about th +9703|35644|3154|1|24|37911.36|0.05|0.01|R|F|1994-10-22|1994-12-24|1994-11-01|COLLECT COD|REG AIR|e slyly. regular forge +9728|45399|5400|1|32|43020.48|0.10|0.01|A|F|1993-07-04|1993-09-25|1993-07-08|COLLECT COD|SHIP|y final instructions cajole furiously regu +9729|44362|9371|1|39|50948.04|0.04|0.03|N|O|1996-07-30|1996-08-22|1996-08-17|COLLECT COD|MAIL|lar accounts a +9729|179117|6669|2|44|52628.84|0.08|0.08|N|O|1996-08-04|1996-08-23|1996-08-26|COLLECT COD|MAIL|regular deposits detec +9729|2994|7995|3|25|47424.75|0.05|0.05|N|O|1996-10-21|1996-09-12|1996-11-14|DELIVER IN PERSON|RAIL| blithely even deposits nod ironi +9729|103663|8684|4|15|24999.90|0.09|0.05|N|O|1996-08-22|1996-08-25|1996-09-15|DELIVER IN PERSON|RAIL|n packages cajole slyly slyly final requ +9730|55350|7856|1|24|31328.40|0.05|0.05|N|O|1997-04-22|1997-05-31|1997-05-22|NONE|FOB|ess asymptotes boo +9730|61422|3929|2|37|51186.54|0.06|0.06|N|O|1997-05-01|1997-05-12|1997-05-22|COLLECT COD|MAIL|e furiously even, express foxe +9730|113663|8686|3|29|48623.14|0.03|0.05|N|O|1997-03-24|1997-05-24|1997-03-26|COLLECT COD|AIR|f the furiously regula +9730|126899|4436|4|50|96294.50|0.10|0.02|N|O|1997-04-06|1997-06-02|1997-04-17|NONE|TRUCK|express dependencies are fluffily +9730|189785|9786|5|33|61867.74|0.01|0.08|N|O|1997-06-15|1997-05-04|1997-07-09|COLLECT COD|MAIL|packages are carefully dolphins. reques +9730|105436|457|6|41|59098.63|0.02|0.03|N|O|1997-06-16|1997-05-23|1997-07-04|NONE|FOB|sual theodolites dazzle slyl +9731|123746|1283|1|8|14157.92|0.08|0.06|A|F|1993-11-26|1994-01-09|1993-12-05|COLLECT COD|RAIL|always regular deposits. ironic +9731|193979|6499|2|7|14510.79|0.06|0.05|A|F|1994-01-03|1993-12-09|1994-01-12|COLLECT COD|REG AIR| theodolites dazzle ironic accounts. furio +9732|145137|7652|1|4|4728.52|0.09|0.06|N|O|1995-06-25|1995-05-26|1995-07-12|DELIVER IN PERSON|AIR|s. regular pac +9732|101014|8545|2|47|47705.47|0.10|0.08|A|F|1995-04-02|1995-04-20|1995-04-06|DELIVER IN PERSON|REG AIR|ole carefully furiou +9732|133412|5926|3|20|28908.20|0.08|0.00|A|F|1995-04-11|1995-05-09|1995-04-12|DELIVER IN PERSON|REG AIR|lly. regularly even excuses cajole furi +9733|197698|2737|1|23|41300.87|0.01|0.06|A|F|1994-04-28|1994-05-02|1994-05-19|TAKE BACK RETURN|FOB|theodolites about the +9733|109605|9606|2|10|16146.00|0.10|0.01|A|F|1994-06-04|1994-05-31|1994-06-18|COLLECT COD|SHIP|ajole according to the c +9733|127148|9661|3|17|19977.38|0.10|0.00|R|F|1994-06-24|1994-06-03|1994-07-02|TAKE BACK RETURN|AIR|refully above the flu +9734|98732|3751|1|48|83075.04|0.07|0.05|N|O|1997-02-24|1997-05-04|1997-02-27|TAKE BACK RETURN|SHIP|ptotes doubt about the +9734|187333|2370|2|21|29826.93|0.06|0.02|N|O|1997-05-22|1997-04-29|1997-06-02|DELIVER IN PERSON|FOB|usly speci +9735|108001|5532|1|1|1009.00|0.10|0.08|N|O|1997-10-24|1997-08-05|1997-11-19|NONE|AIR|. close, final reque +9735|160380|7929|2|13|18724.94|0.03|0.07|N|O|1997-08-15|1997-09-10|1997-09-14|COLLECT COD|FOB|ess pinto beans. regula +9735|90550|5569|3|10|15405.50|0.09|0.06|N|O|1997-07-09|1997-08-12|1997-07-30|COLLECT COD|MAIL|c instructio +9735|63313|5820|4|22|28078.82|0.06|0.03|N|O|1997-07-23|1997-08-29|1997-08-17|COLLECT COD|AIR|re thinly bold +9735|89757|4774|5|26|45415.50|0.08|0.02|N|O|1997-08-23|1997-08-27|1997-09-05|NONE|AIR|egular grouches cajole fluffil +9760|74592|2114|1|17|26632.03|0.02|0.05|N|O|1998-04-28|1998-06-20|1998-04-30|TAKE BACK RETURN|FOB| permanent attainments kindle carefully +9760|65102|7609|2|30|32013.00|0.03|0.07|N|O|1998-05-31|1998-05-24|1998-06-21|NONE|SHIP|y fluffily careful packages. fluffily bol +9760|166643|1676|3|14|23934.96|0.03|0.05|N|O|1998-05-25|1998-06-04|1998-06-22|TAKE BACK RETURN|REG AIR| instructions haggle. furio +9760|155108|139|4|40|46524.00|0.02|0.04|N|O|1998-07-05|1998-06-29|1998-08-01|COLLECT COD|FOB|bove the blithely pending requests +9761|79926|2434|1|27|51459.84|0.07|0.04|A|F|1992-02-12|1992-03-22|1992-02-16|NONE|FOB|uctions integrate unusual, +9761|109068|1579|2|26|28003.56|0.05|0.08|A|F|1992-04-08|1992-03-09|1992-04-23|COLLECT COD|MAIL|furiously regular packages. furiously +9762|117423|7424|1|17|24487.14|0.02|0.06|R|F|1994-04-24|1994-03-13|1994-05-17|TAKE BACK RETURN|AIR|instructions nag a +9762|117816|7817|2|30|55014.30|0.10|0.03|R|F|1994-02-02|1994-04-01|1994-02-25|DELIVER IN PERSON|TRUCK|ly special packages. blithely regular depos +9762|118568|6102|3|30|47596.80|0.06|0.08|A|F|1994-04-21|1994-03-16|1994-04-22|COLLECT COD|REG AIR|ions are above the blithel +9762|157550|66|4|33|53049.15|0.00|0.02|R|F|1994-04-18|1994-03-20|1994-05-15|DELIVER IN PERSON|RAIL|ackages. quickly ev +9762|130684|5711|5|12|20576.16|0.04|0.00|A|F|1994-04-21|1994-02-16|1994-05-17|COLLECT COD|RAIL|xpress requests; c +9762|193298|856|6|50|69564.50|0.06|0.08|A|F|1994-03-26|1994-03-14|1994-04-08|NONE|FOB|ly after the slyly regular foxes: ironic s +9763|107354|7355|1|50|68067.50|0.10|0.04|N|O|1995-11-21|1995-10-27|1995-11-28|COLLECT COD|REG AIR| the slyly iron +9763|89625|9626|2|2|3229.24|0.07|0.00|N|O|1995-10-09|1995-09-22|1995-11-05|DELIVER IN PERSON|RAIL|sts sleep fluffily accounts. slyly unusual +9763|112967|7990|3|1|1979.96|0.02|0.02|N|O|1995-11-11|1995-10-18|1995-12-01|NONE|RAIL| final, ironic deposits. hockey play +9763|22353|2354|4|14|17854.90|0.02|0.07|N|O|1995-09-27|1995-09-28|1995-10-22|COLLECT COD|SHIP|lar pinto beans are blit +9763|76096|3618|5|12|12865.08|0.09|0.02|N|O|1995-09-17|1995-10-06|1995-10-14|NONE|MAIL|gle blithely alongside +9763|144749|2292|6|14|25112.36|0.01|0.04|N|O|1995-09-14|1995-10-22|1995-09-20|COLLECT COD|MAIL|furiously special instructions caj +9763|193535|6055|7|15|24427.95|0.06|0.07|N|O|1995-10-23|1995-10-12|1995-10-28|COLLECT COD|REG AIR| furiously bold accounts. furiously speci +9764|135481|5482|1|23|34879.04|0.09|0.03|A|F|1993-02-25|1993-03-04|1993-03-15|DELIVER IN PERSON|AIR|regular, ironic requests wake across +9764|18928|1430|2|5|9234.60|0.00|0.06|R|F|1993-01-01|1993-03-27|1993-01-23|TAKE BACK RETURN|RAIL|cial packages. special requ +9764|108463|3484|3|26|38257.96|0.08|0.01|A|F|1993-02-17|1993-02-04|1993-02-28|NONE|RAIL|h-- quickly express foxes bo +9765|136467|6468|1|34|51117.64|0.01|0.06|A|F|1992-11-04|1992-12-16|1992-11-19|COLLECT COD|FOB|sits. slyly careful theodolites integrat +9766|139772|2286|1|46|83341.42|0.08|0.01|A|F|1992-11-18|1992-10-02|1992-12-04|TAKE BACK RETURN|FOB|beans. pinto beans use. final requests +9766|138656|8657|2|3|5083.95|0.04|0.04|R|F|1992-08-28|1992-10-22|1992-09-17|TAKE BACK RETURN|FOB|ending deposits cajole among the quickly +9766|180225|5262|3|25|32630.50|0.03|0.06|A|F|1992-11-21|1992-10-14|1992-12-11|COLLECT COD|TRUCK| the excuses. fluffily eve +9766|26389|6390|4|50|65769.00|0.00|0.07|R|F|1992-12-11|1992-10-12|1992-12-17|COLLECT COD|RAIL|s; even, final requests wake sl +9767|84775|9792|1|28|49273.56|0.08|0.04|A|F|1994-08-29|1994-08-17|1994-09-07|NONE|AIR| deposits alongside of the +9792|169745|9746|1|16|29035.84|0.07|0.03|N|O|1995-10-24|1995-10-03|1995-10-29|TAKE BACK RETURN|AIR| was. slyly even accoun +9792|98588|6116|2|25|39664.50|0.03|0.06|N|O|1995-09-25|1995-10-12|1995-10-25|COLLECT COD|TRUCK| regular packages ought to detect. furi +9792|157942|2973|3|41|81997.54|0.01|0.00|N|O|1995-08-05|1995-10-20|1995-08-25|COLLECT COD|FOB|ly bold acc +9792|115811|834|4|4|7307.24|0.06|0.02|N|O|1995-08-27|1995-08-26|1995-09-02|NONE|AIR|ar dolphins. carefully +9792|30240|5247|5|29|33936.96|0.06|0.05|N|O|1995-11-05|1995-08-25|1995-11-24|DELIVER IN PERSON|MAIL|uctions haggle furiously f +9793|28378|5885|1|7|9144.59|0.04|0.06|A|F|1992-06-22|1992-06-10|1992-07-07|TAKE BACK RETURN|MAIL|nst the closely s +9793|141637|4152|2|2|3357.26|0.01|0.06|R|F|1992-05-01|1992-05-05|1992-05-03|DELIVER IN PERSON|AIR|ding theodolites abov +9793|84752|7261|3|4|6947.00|0.09|0.04|R|F|1992-06-22|1992-06-14|1992-07-02|NONE|TRUCK|grate quickly. fluffily regular pack +9793|13918|1422|4|33|60453.03|0.01|0.05|A|F|1992-04-14|1992-05-06|1992-04-22|COLLECT COD|MAIL|the regular pinto beans. ex +9793|106791|9302|5|29|52135.91|0.06|0.03|R|F|1992-07-20|1992-06-25|1992-07-21|COLLECT COD|FOB|l packages. even pinto bean +9794|104868|2399|1|32|59931.52|0.09|0.01|R|F|1992-04-28|1992-05-15|1992-05-03|NONE|FOB| slyly along the dependenc +9794|111191|6214|2|3|3606.57|0.09|0.08|A|F|1992-07-12|1992-05-17|1992-07-28|NONE|REG AIR|ost according to the busily regular realm +9794|185507|8026|3|17|27072.50|0.06|0.06|A|F|1992-05-14|1992-04-24|1992-06-11|NONE|MAIL|egular asymptotes. carefully +9794|199929|9930|4|44|89272.48|0.08|0.07|R|F|1992-05-14|1992-05-14|1992-05-31|DELIVER IN PERSON|AIR|the furiou +9794|3648|3649|5|32|49652.48|0.06|0.08|R|F|1992-04-30|1992-05-13|1992-05-22|NONE|FOB|ending accounts. carefully regula +9794|96937|6938|6|40|77357.20|0.01|0.05|R|F|1992-05-03|1992-05-27|1992-05-24|TAKE BACK RETURN|AIR|e the fluffily regular pa +9794|10360|5363|7|8|10162.88|0.00|0.05|A|F|1992-07-01|1992-05-15|1992-07-25|DELIVER IN PERSON|AIR|ular asympto +9795|115264|2798|1|13|16630.38|0.08|0.01|N|O|1998-05-26|1998-03-16|1998-06-07|NONE|SHIP|es are slyly. unusual co +9795|41109|1110|2|26|27302.60|0.06|0.02|N|O|1998-04-22|1998-05-01|1998-05-06|TAKE BACK RETURN|FOB|ironic, silent theodolites wake accordi +9795|104652|9673|3|23|38102.95|0.06|0.06|N|O|1998-05-13|1998-04-05|1998-06-09|NONE|RAIL| engage iro +9795|75286|5287|4|47|59280.16|0.01|0.04|N|O|1998-03-10|1998-05-04|1998-03-21|TAKE BACK RETURN|AIR|ntegrate fluffily blithely +9795|117424|9936|5|27|38918.34|0.09|0.02|N|O|1998-02-09|1998-04-22|1998-02-26|DELIVER IN PERSON|RAIL|ing to the ironi +9795|128671|8672|6|34|57788.78|0.05|0.07|N|O|1998-02-25|1998-03-07|1998-03-07|TAKE BACK RETURN|SHIP|egrate slyly blithel +9796|182132|9687|1|36|43708.68|0.00|0.06|A|F|1993-10-15|1993-10-15|1993-11-01|COLLECT COD|RAIL|ng pinto beans integrate. requests +9796|78417|3432|2|25|34885.25|0.03|0.05|A|F|1993-10-10|1993-11-13|1993-10-31|TAKE BACK RETURN|AIR|gle slyly ironic pearls. requ +9796|141456|3971|3|18|26954.10|0.03|0.06|A|F|1993-09-28|1993-10-30|1993-10-02|TAKE BACK RETURN|SHIP|accounts. final ideas sle +9796|44955|2468|4|31|58898.45|0.03|0.06|R|F|1993-09-19|1993-12-01|1993-09-29|NONE|RAIL|haggle carefully furiously even asym +9796|158237|5783|5|39|50513.97|0.07|0.06|A|F|1993-09-28|1993-10-11|1993-10-23|COLLECT COD|REG AIR|ake. slyly final cou +9796|74987|2509|6|8|15695.84|0.03|0.07|R|F|1993-11-27|1993-11-01|1993-12-19|DELIVER IN PERSON|FOB|ironic pinto beans. even +9797|41400|1401|1|4|5365.60|0.10|0.05|R|F|1993-12-20|1993-11-21|1993-12-26|NONE|REG AIR| beans above the carefully bold hoc +9797|193478|5998|2|28|44001.16|0.10|0.01|R|F|1993-10-03|1993-11-03|1993-10-04|NONE|FOB|en instructions. quickly regular theodoli +9797|175257|5258|3|22|29309.50|0.00|0.04|A|F|1993-10-01|1993-11-07|1993-10-14|NONE|SHIP| final deposits at the even +9797|142470|7499|4|33|49911.51|0.02|0.01|A|F|1993-12-16|1993-11-03|1994-01-06|NONE|FOB|ackages boost fluffily. spec +9797|86998|2015|5|31|61534.69|0.09|0.02|R|F|1993-10-24|1993-12-12|1993-11-21|DELIVER IN PERSON|AIR| permanently final theodolites +9797|170215|7767|6|2|2570.42|0.00|0.06|A|F|1993-12-25|1993-11-04|1993-12-30|DELIVER IN PERSON|REG AIR|counts after the +9797|2631|2632|7|24|36807.12|0.04|0.03|R|F|1993-12-08|1993-12-01|1994-01-02|COLLECT COD|MAIL|usly thin packages among the theod +9798|6017|8518|1|2|1846.02|0.05|0.03|N|O|1996-06-11|1996-05-07|1996-07-08|NONE|MAIL|ending asymptot +9798|118587|6121|2|20|32111.60|0.03|0.03|N|O|1996-05-20|1996-05-27|1996-05-29|DELIVER IN PERSON|FOB|fully regular braids. +9799|35698|705|1|4|6534.76|0.06|0.03|N|O|1996-04-25|1996-06-29|1996-05-24|COLLECT COD|SHIP|eposits nag after the reg +9799|162974|2975|2|12|24443.64|0.02|0.05|N|O|1996-05-28|1996-05-26|1996-06-05|DELIVER IN PERSON|RAIL|fluffily final accounts. final ideas sleep. +9799|88999|6524|3|16|31807.84|0.04|0.05|N|O|1996-04-12|1996-06-15|1996-05-06|TAKE BACK RETURN|TRUCK|ffily regular d +9799|198175|5733|4|9|11458.53|0.06|0.07|N|O|1996-08-06|1996-06-19|1996-08-19|DELIVER IN PERSON|MAIL|s. final, ironic instructions affix +9799|125373|7886|5|49|68520.13|0.08|0.04|N|O|1996-07-18|1996-06-11|1996-08-15|COLLECT COD|REG AIR|ly special deposits. regular foxe +9799|129764|7301|6|23|41256.48|0.02|0.05|N|O|1996-07-10|1996-05-25|1996-08-08|TAKE BACK RETURN|REG AIR|deposits nag alongside of the even instru +9824|41380|8893|1|8|10571.04|0.05|0.07|N|F|1995-05-24|1995-04-21|1995-06-21|TAKE BACK RETURN|FOB| are. packages haggl +9824|73184|5692|2|1|1157.18|0.02|0.07|A|F|1995-01-26|1995-04-16|1995-02-11|COLLECT COD|TRUCK|dencies. final, +9824|191278|1279|3|38|52032.26|0.03|0.05|A|F|1995-03-11|1995-03-27|1995-03-15|COLLECT COD|REG AIR|gular, ironic package +9824|194659|7179|4|11|19290.15|0.07|0.01|R|F|1995-05-08|1995-04-17|1995-05-14|NONE|REG AIR| furious t +9824|30349|350|5|11|14072.74|0.09|0.00|A|F|1995-04-15|1995-04-14|1995-05-04|TAKE BACK RETURN|FOB|s use doggedly. pending, regular pac +9824|71024|1025|6|49|48755.98|0.04|0.01|R|F|1995-03-10|1995-04-07|1995-03-11|NONE|MAIL|ly ironic packages. +9824|97930|440|7|25|48198.25|0.00|0.07|A|F|1995-02-17|1995-03-12|1995-02-22|COLLECT COD|RAIL|inst the blithely final excuses. final +9825|105098|7609|1|22|24267.98|0.04|0.06|N|O|1996-04-21|1996-07-01|1996-05-19|NONE|MAIL|hely final sentimen +9825|180049|50|2|16|18064.64|0.07|0.07|N|O|1996-06-15|1996-07-08|1996-07-11|DELIVER IN PERSON|TRUCK|en asymptotes according to the r +9825|75854|869|3|4|7319.40|0.09|0.00|N|O|1996-06-29|1996-06-28|1996-07-15|NONE|TRUCK|l platelets boost car +9825|63603|1122|4|25|39165.00|0.02|0.04|N|O|1996-05-03|1996-07-06|1996-05-18|DELIVER IN PERSON|RAIL|d, ironic instructions. carefully spec +9826|172074|4592|1|34|38966.38|0.10|0.05|R|F|1992-07-18|1992-06-12|1992-07-30|DELIVER IN PERSON|AIR|old, ironic courts alongside of +9826|45559|8064|2|1|1504.55|0.02|0.04|A|F|1992-04-22|1992-05-06|1992-05-15|COLLECT COD|MAIL|uickly. blithely pending depths lose slyly +9826|108587|3608|3|50|79779.00|0.03|0.08|R|F|1992-05-07|1992-06-13|1992-05-21|COLLECT COD|FOB|ound the blithely spec +9827|27876|379|1|16|28861.92|0.09|0.08|N|O|1998-08-15|1998-09-13|1998-09-08|NONE|SHIP| blithely silent pa +9827|99930|9931|2|20|38598.60|0.08|0.08|N|O|1998-10-23|1998-09-07|1998-11-15|DELIVER IN PERSON|TRUCK|, bold accounts af +9828|71566|9088|1|39|59964.84|0.00|0.05|R|F|1992-04-29|1992-06-16|1992-05-23|COLLECT COD|RAIL|he furiousl +9828|6370|1371|2|17|21698.29|0.00|0.03|A|F|1992-05-31|1992-06-28|1992-06-23|DELIVER IN PERSON|FOB|final accounts according to +9828|50776|3282|3|21|36262.17|0.00|0.06|R|F|1992-06-05|1992-06-29|1992-07-02|COLLECT COD|AIR|nts. special +9828|183615|8652|4|32|54355.52|0.06|0.00|A|F|1992-08-16|1992-06-17|1992-08-17|DELIVER IN PERSON|SHIP|uickly even foxes across the special accou +9828|12218|9722|5|25|28255.25|0.01|0.01|R|F|1992-08-19|1992-06-12|1992-08-21|NONE|TRUCK| blithely fluffil +9828|139798|9799|6|41|75349.39|0.02|0.06|A|F|1992-07-25|1992-07-10|1992-08-03|TAKE BACK RETURN|RAIL|e furiously across the even requests. ir +9828|177261|9779|7|13|17397.38|0.00|0.01|R|F|1992-06-27|1992-07-15|1992-07-18|COLLECT COD|RAIL|ding, ironic packages promise blithel +9829|20948|8455|1|2|3737.88|0.08|0.08|N|O|1996-03-31|1996-01-25|1996-04-06|DELIVER IN PERSON|MAIL|ss the quickly bold de +9829|59855|4866|2|3|5444.55|0.03|0.01|N|O|1996-02-25|1996-03-01|1996-03-20|NONE|AIR|. unusual accounts affix carefully about +9830|157412|2443|1|26|38204.66|0.00|0.06|N|O|1997-12-01|1997-10-09|1997-12-22|DELIVER IN PERSON|TRUCK|ular dependencies. request +9830|23029|5532|2|34|32368.68|0.04|0.03|N|O|1997-10-06|1997-11-28|1997-11-03|NONE|SHIP| boldly pen +9830|34622|2132|3|17|26462.54|0.02|0.01|N|O|1997-12-04|1997-10-16|1997-12-20|NONE|MAIL|y pending ideas. furiously e +9830|83441|8458|4|19|27064.36|0.03|0.04|N|O|1997-11-16|1997-10-10|1997-11-21|COLLECT COD|AIR|y across the regular requests. quickly r +9830|180595|596|5|42|70374.78|0.10|0.08|N|O|1997-12-25|1997-11-07|1998-01-15|DELIVER IN PERSON|AIR|platelets: silent instructions c +9831|16176|8678|1|23|25119.91|0.06|0.04|N|O|1996-10-05|1996-08-13|1996-10-20|DELIVER IN PERSON|RAIL|pending theodolites. iro +9831|69594|2101|2|37|57852.83|0.02|0.08|N|O|1996-07-28|1996-08-05|1996-08-24|DELIVER IN PERSON|MAIL|l accounts. care +9856|113771|1305|1|31|55327.87|0.09|0.03|R|F|1993-06-07|1993-08-10|1993-06-30|COLLECT COD|AIR|posits. quick, final pinto b +9856|135955|3495|2|49|97556.55|0.08|0.06|R|F|1993-08-25|1993-07-24|1993-09-12|COLLECT COD|SHIP|ests engage furio +9856|191669|4189|3|48|84511.68|0.03|0.00|A|F|1993-06-24|1993-08-11|1993-07-18|DELIVER IN PERSON|MAIL|arefully quickly unusu +9856|168935|1452|4|37|74145.41|0.00|0.04|A|F|1993-06-14|1993-08-23|1993-06-27|NONE|TRUCK|refully furiously regular de +9857|108800|8801|1|6|10852.80|0.06|0.02|A|F|1993-05-15|1993-06-26|1993-05-19|TAKE BACK RETURN|FOB|ickly regular deposit +9857|199912|7470|2|42|84500.22|0.05|0.07|A|F|1993-07-22|1993-08-03|1993-07-27|TAKE BACK RETURN|MAIL|scapades are blithely abou +9857|106188|6189|3|6|7165.08|0.03|0.03|A|F|1993-06-01|1993-07-27|1993-06-18|TAKE BACK RETURN|MAIL|lites. ironic foxes wa +9857|87608|2625|4|40|63824.00|0.00|0.07|R|F|1993-07-18|1993-06-14|1993-08-11|TAKE BACK RETURN|RAIL|ording to the regular theodolites are ac +9857|16637|6638|5|10|15536.30|0.00|0.03|R|F|1993-08-08|1993-07-25|1993-08-20|COLLECT COD|REG AIR|cuses would af +9857|16240|1243|6|5|5781.20|0.09|0.00|A|F|1993-08-04|1993-06-27|1993-09-02|DELIVER IN PERSON|AIR|ongside of the fin +9857|143609|3610|7|13|21483.80|0.08|0.03|A|F|1993-08-31|1993-06-17|1993-09-02|DELIVER IN PERSON|SHIP|ions. furiously ironic +9858|35273|2783|1|18|21748.86|0.10|0.01|N|O|1997-12-15|1998-02-04|1998-01-09|NONE|RAIL| deposits was quickly. accounts i +9858|31739|9249|2|37|61817.01|0.04|0.03|N|O|1998-01-13|1998-02-19|1998-02-06|DELIVER IN PERSON|TRUCK|y carefully furiousl +9858|34584|2094|3|30|45557.40|0.02|0.06|N|O|1998-01-04|1998-01-10|1998-01-11|NONE|RAIL|ffily unusual requests ab +9859|109160|9161|1|20|23383.20|0.04|0.06|N|O|1996-09-03|1996-09-06|1996-10-02|DELIVER IN PERSON|AIR|es according to the quickly r +9859|48922|3931|2|50|93546.00|0.02|0.05|N|O|1996-11-09|1996-10-13|1996-11-18|TAKE BACK RETURN|AIR|its are slyly final accounts. pe +9859|20489|7996|3|30|42284.40|0.03|0.08|N|O|1996-10-26|1996-09-25|1996-11-25|TAKE BACK RETURN|TRUCK| fluffily regular deposits; slyly regular f +9859|147859|5402|4|37|70553.45|0.09|0.00|N|O|1996-08-20|1996-09-25|1996-09-15|DELIVER IN PERSON|TRUCK|he pending pinto beans +9859|53981|6487|5|49|94814.02|0.00|0.06|N|O|1996-08-27|1996-09-16|1996-09-17|COLLECT COD|REG AIR|ve theodolites will nag carefully aga +9860|75599|614|1|4|6298.36|0.06|0.07|A|F|1993-12-03|1993-12-27|1993-12-13|COLLECT COD|MAIL|posits thrash. en +9860|186045|1082|2|30|33931.20|0.03|0.00|A|F|1993-11-02|1993-11-10|1993-11-30|COLLECT COD|SHIP| the slyly bold foxes +9860|41810|4315|3|37|64816.97|0.03|0.05|A|F|1994-02-07|1994-01-03|1994-03-04|DELIVER IN PERSON|FOB|foxes cajole furiously slyly express +9860|99360|4379|4|4|5437.44|0.04|0.03|A|F|1993-10-18|1993-12-23|1993-11-03|TAKE BACK RETURN|RAIL|carefully special accoun +9860|130601|3115|5|15|24474.00|0.03|0.08|R|F|1994-01-12|1993-12-08|1994-01-30|TAKE BACK RETURN|REG AIR|. regular pearls u +9860|2543|44|6|19|27465.26|0.04|0.04|R|F|1993-10-28|1993-12-10|1993-11-15|TAKE BACK RETURN|REG AIR|ges. even packages cajole pending, ironi +9861|134874|7388|1|1|1908.87|0.08|0.03|R|F|1992-11-16|1992-11-30|1992-12-04|COLLECT COD|AIR|ular pinto beans wake fluffily aft +9861|10802|5805|2|7|11989.60|0.09|0.02|A|F|1992-11-28|1992-12-12|1992-12-23|DELIVER IN PERSON|RAIL|es sleep carefully speci +9861|135558|5559|3|21|33464.55|0.03|0.08|R|F|1993-01-28|1993-01-10|1993-01-31|DELIVER IN PERSON|REG AIR|ly express pinto b +9861|112191|9725|4|6|7219.14|0.10|0.05|A|F|1992-12-26|1992-12-04|1993-01-21|COLLECT COD|SHIP|e furiously express req +9861|191342|1343|5|13|18633.42|0.02|0.08|R|F|1992-12-31|1993-01-15|1993-01-30|COLLECT COD|MAIL| carefully +9862|86241|8750|1|26|31908.24|0.05|0.06|N|O|1998-01-15|1997-11-19|1998-01-25|NONE|FOB|p blithely +9862|39555|9556|2|11|16440.05|0.06|0.06|N|O|1997-12-18|1998-01-03|1998-01-12|TAKE BACK RETURN|AIR|s haggle quietl +9862|195846|3404|3|37|71848.08|0.05|0.07|N|O|1997-11-20|1997-12-27|1997-12-15|DELIVER IN PERSON|SHIP| according t +9862|182659|214|4|4|6966.60|0.10|0.01|N|O|1997-12-12|1997-12-06|1998-01-04|TAKE BACK RETURN|SHIP|each slyly after the furiously unusual req +9862|135675|5676|5|45|76980.15|0.07|0.07|N|O|1997-12-15|1997-11-21|1997-12-30|NONE|RAIL|nal theodolites sleep quickly th +9863|85537|8046|1|48|73081.44|0.06|0.08|N|O|1995-12-11|1995-10-11|1996-01-04|NONE|SHIP|arefully at the blithely unusual excuses. +9863|12911|2912|2|47|85723.77|0.06|0.04|N|O|1995-11-17|1995-10-14|1995-12-14|TAKE BACK RETURN|AIR|ts. asymptotes +9863|187433|2470|3|27|41051.61|0.07|0.05|N|O|1995-11-13|1995-11-22|1995-11-29|NONE|RAIL|boost bold requests. pending, pe +9863|174462|4463|4|36|55312.56|0.04|0.04|N|O|1995-11-17|1995-10-12|1995-11-27|COLLECT COD|AIR|ts haggle. regular accounts haggle q +9863|170852|8404|5|18|34611.30|0.01|0.06|N|O|1995-12-12|1995-11-22|1995-12-14|TAKE BACK RETURN|AIR|press packa +9863|103671|1202|6|43|72010.81|0.03|0.06|N|O|1995-10-21|1995-10-06|1995-10-22|COLLECT COD|FOB|ly unusual foxes a +9863|186664|4219|7|29|50769.14|0.07|0.08|N|O|1995-11-06|1995-11-19|1995-11-12|COLLECT COD|TRUCK|uests cajole slyly aro +9888|58135|641|1|34|37166.42|0.04|0.06|A|F|1994-11-25|1994-12-09|1994-12-13|TAKE BACK RETURN|FOB| slyly daring accounts. regular dependen +9888|66812|4331|2|12|21345.72|0.10|0.03|A|F|1994-11-11|1994-11-25|1994-11-12|TAKE BACK RETURN|REG AIR|ach blithely along the evenly f +9888|104133|4134|3|6|6822.78|0.07|0.04|A|F|1994-11-25|1994-12-06|1994-12-12|NONE|TRUCK|se requests sleep slyly above t +9889|180812|5849|1|11|20820.91|0.02|0.00|A|F|1994-12-26|1994-11-30|1995-01-06|DELIVER IN PERSON|MAIL|deposits detect care +9889|103863|3864|2|20|37337.20|0.10|0.00|A|F|1994-11-10|1994-12-01|1994-11-14|NONE|RAIL|are quickly furiou +9890|118699|3722|1|26|44659.94|0.00|0.01|R|F|1995-03-15|1995-03-27|1995-03-23|COLLECT COD|MAIL|lly ironic deposits. +9890|165934|967|2|41|81997.13|0.09|0.01|N|O|1995-06-22|1995-04-14|1995-06-25|DELIVER IN PERSON|AIR|ully final packages. quickl +9891|195822|861|1|5|9589.10|0.02|0.05|N|O|1995-09-16|1995-07-23|1995-09-18|TAKE BACK RETURN|RAIL| dolphins. boldly final ac +9891|173014|5532|2|32|34784.32|0.03|0.02|N|F|1995-06-13|1995-07-09|1995-06-23|COLLECT COD|AIR|s sleep. carefully special theodolites was +9892|196949|1988|1|5|10229.70|0.09|0.08|R|F|1992-09-11|1992-10-06|1992-09-16|NONE|MAIL| bold instruction +9892|108997|8998|2|4|8023.96|0.05|0.02|A|F|1992-09-22|1992-08-24|1992-10-04|DELIVER IN PERSON|RAIL|y unusual asymptotes: bli +9892|110096|97|3|3|3318.27|0.02|0.04|R|F|1992-09-21|1992-10-06|1992-10-17|NONE|TRUCK|even warthogs. accounts affix +9893|144553|7068|1|31|49524.05|0.03|0.05|R|F|1994-11-22|1994-10-21|1994-11-29|NONE|REG AIR|deas sleep carefully carefully st +9893|87426|2443|2|13|18374.46|0.02|0.07|R|F|1994-08-31|1994-09-17|1994-09-12|DELIVER IN PERSON|TRUCK|quests. sometimes unusual i +9893|164560|2109|3|25|40614.00|0.04|0.04|A|F|1994-09-08|1994-11-02|1994-10-01|DELIVER IN PERSON|MAIL|. blithely pendi +9894|132438|9978|1|23|33819.89|0.01|0.00|A|F|1994-05-06|1994-04-26|1994-06-03|DELIVER IN PERSON|SHIP|ages sleep according to th +9894|80110|111|2|6|6540.66|0.00|0.07|R|F|1994-05-15|1994-06-09|1994-06-05|NONE|AIR|ckages engage +9894|197156|2195|3|33|41353.95|0.06|0.06|R|F|1994-05-18|1994-04-26|1994-06-07|DELIVER IN PERSON|MAIL| carefully even accounts mol +9895|72990|5498|1|50|98149.50|0.00|0.01|R|F|1993-05-07|1993-07-17|1993-05-14|DELIVER IN PERSON|RAIL|he enticingly final co +9895|137457|9971|2|24|35866.80|0.05|0.05|A|F|1993-04-23|1993-06-30|1993-04-29|COLLECT COD|REG AIR|ding ideas detec +9895|27701|7702|3|46|74920.20|0.02|0.04|A|F|1993-05-23|1993-07-18|1993-06-04|DELIVER IN PERSON|TRUCK| carefully silent packages. +9895|162041|9590|4|48|52945.92|0.02|0.08|A|F|1993-05-24|1993-07-06|1993-06-18|DELIVER IN PERSON|REG AIR|ecial dugouts. silent excuses detect furiou +9920|133813|8840|1|1|1846.81|0.06|0.02|N|O|1996-08-05|1996-07-12|1996-08-31|TAKE BACK RETURN|FOB|ently special warhorses. b +9920|190951|3471|2|28|57174.60|0.08|0.03|N|O|1996-09-25|1996-08-30|1996-10-01|DELIVER IN PERSON|FOB|es detect. fluffily +9920|103580|6091|3|29|45923.82|0.08|0.03|N|O|1996-08-31|1996-07-13|1996-09-19|TAKE BACK RETURN|TRUCK|uctions haggle among the express deposits. +9921|56036|8542|1|9|8928.27|0.07|0.05|N|O|1995-07-10|1995-08-07|1995-07-14|COLLECT COD|FOB|ackages. furiously bold req +9921|180355|7910|2|48|68896.80|0.00|0.04|N|F|1995-05-31|1995-07-02|1995-06-20|TAKE BACK RETURN|TRUCK|thely. slyly unusual asymptot +9921|24553|7056|3|7|10342.85|0.03|0.04|N|O|1995-08-24|1995-06-29|1995-08-30|NONE|RAIL|usly regular in +9921|49522|9523|4|28|41202.56|0.05|0.01|N|O|1995-06-19|1995-06-22|1995-06-25|COLLECT COD|MAIL|lar, regular pinto bean +9922|88564|6089|1|20|31051.20|0.01|0.02|R|F|1995-05-09|1995-07-03|1995-05-17|NONE|FOB|bove the ironic depths haggle blithely spec +9922|80232|7757|2|1|1212.23|0.09|0.00|N|F|1995-06-16|1995-06-17|1995-06-27|DELIVER IN PERSON|SHIP| final accou +9922|52868|384|3|21|38238.06|0.03|0.04|R|F|1995-04-21|1995-06-09|1995-04-29|DELIVER IN PERSON|MAIL|indle slyly ideas. requests nag quietly ab +9922|147236|4779|4|31|39780.13|0.09|0.04|R|F|1995-05-27|1995-06-04|1995-06-10|DELIVER IN PERSON|MAIL|s integrate. packages hinder silent, re +9922|179906|2424|5|16|31774.40|0.06|0.05|A|F|1995-05-24|1995-06-09|1995-06-05|DELIVER IN PERSON|MAIL|iously special depos +9922|68566|3579|6|32|49105.92|0.09|0.04|N|F|1995-06-13|1995-05-17|1995-06-21|NONE|TRUCK|usly regular pac +9922|176269|6270|7|2|2690.52|0.09|0.02|N|O|1995-08-01|1995-06-15|1995-08-10|NONE|REG AIR|ironic pint +9923|143875|1418|1|11|21107.57|0.09|0.05|R|F|1995-01-26|1994-11-15|1995-02-22|TAKE BACK RETURN|SHIP|y final deposits sleep. furi +9923|102166|7187|2|45|52567.20|0.02|0.00|R|F|1994-12-05|1994-11-11|1994-12-12|COLLECT COD|RAIL|urts. bold courts above the furiou +9923|92784|312|3|33|58633.74|0.04|0.03|A|F|1994-12-30|1994-11-29|1995-01-21|TAKE BACK RETURN|MAIL|fully fluffily even d +9923|16621|1624|4|6|9225.72|0.07|0.02|R|F|1994-10-23|1994-12-09|1994-11-02|DELIVER IN PERSON|FOB|unts wake sl +9923|142601|5116|5|26|42733.60|0.05|0.01|R|F|1995-01-21|1994-11-29|1995-01-22|COLLECT COD|RAIL|usly. ironic platel +9923|82692|217|6|41|68662.29|0.02|0.01|A|F|1995-01-02|1995-01-01|1995-02-01|COLLECT COD|REG AIR|ronic accounts cajole. unusual account +9924|80257|7782|1|2|2474.50|0.04|0.01|N|O|1997-09-05|1997-06-15|1997-09-18|COLLECT COD|TRUCK|ilent theodolites. bli +9924|67448|4967|2|31|43878.64|0.09|0.06|N|O|1997-08-25|1997-06-24|1997-09-06|NONE|MAIL|, ironic packages. deposits se +9924|193257|815|3|27|36456.75|0.01|0.05|N|O|1997-05-13|1997-07-21|1997-05-20|TAKE BACK RETURN|RAIL|regular pinto beans. slyly f +9924|56154|8660|4|27|29974.05|0.00|0.00|N|O|1997-06-17|1997-06-19|1997-07-16|COLLECT COD|AIR|e after the even, express dependencies. re +9924|175084|2636|5|34|39408.72|0.09|0.00|N|O|1997-08-23|1997-08-06|1997-08-29|COLLECT COD|MAIL|eas boost careful +9925|158985|1501|1|40|81759.20|0.08|0.01|R|F|1992-03-18|1992-04-09|1992-03-27|COLLECT COD|AIR|s use quickly. regular pinto beans use +9925|50339|2845|2|46|59309.18|0.09|0.04|R|F|1992-02-02|1992-03-26|1992-02-06|DELIVER IN PERSON|FOB|ns. pending, special deposits +9925|41690|9203|3|48|78321.12|0.07|0.00|A|F|1992-05-25|1992-04-11|1992-06-10|DELIVER IN PERSON|RAIL|kages nag above +9925|81623|6640|4|38|60975.56|0.07|0.08|A|F|1992-05-16|1992-04-30|1992-06-03|TAKE BACK RETURN|SHIP|t the courts boost carefully +9925|31442|8952|5|6|8240.64|0.10|0.03|A|F|1992-05-18|1992-04-14|1992-06-07|DELIVER IN PERSON|RAIL|s boost. carefully final requests wake qui +9925|29854|9855|6|40|71354.00|0.03|0.04|A|F|1992-02-29|1992-04-22|1992-03-10|NONE|TRUCK|le regularly final asymptotes +9926|28201|3206|1|42|47426.40|0.04|0.02|A|F|1995-01-21|1994-11-21|1995-02-06|COLLECT COD|AIR|lowly? carefully final accounts wake. +9926|173681|8716|2|4|7018.72|0.08|0.07|A|F|1994-11-26|1994-11-23|1994-12-09|TAKE BACK RETURN|TRUCK|he pending tithes wake acco +9926|40736|8249|3|33|55332.09|0.10|0.05|A|F|1994-11-28|1995-01-10|1994-12-25|COLLECT COD|AIR|r the blithely ironic platelets. +9926|34487|6991|4|34|48330.32|0.09|0.00|R|F|1995-01-02|1994-12-09|1995-01-22|NONE|TRUCK|s. fluffily +9926|18782|6286|5|32|54424.96|0.10|0.05|A|F|1995-01-30|1994-11-19|1995-02-22|DELIVER IN PERSON|TRUCK|lar, even t +9926|64220|1739|6|39|46184.58|0.07|0.03|R|F|1995-01-24|1994-12-12|1995-02-05|NONE|AIR|ackages about +9927|875|3376|1|43|76362.41|0.01|0.05|N|O|1995-12-16|1995-09-16|1995-12-28|COLLECT COD|TRUCK|regular in +9927|103164|3165|2|9|10504.44|0.07|0.04|N|O|1995-10-12|1995-09-25|1995-10-28|COLLECT COD|MAIL|efully fin +9927|70144|7666|3|46|51250.44|0.09|0.06|N|O|1995-10-25|1995-10-24|1995-11-09|COLLECT COD|AIR|arefully according to the express request +9927|99528|2038|4|32|48880.64|0.07|0.00|N|O|1995-11-03|1995-09-18|1995-11-15|DELIVER IN PERSON|SHIP|all have to are above the furiously even r +9927|151611|1612|5|37|61516.57|0.01|0.03|N|O|1995-11-15|1995-09-23|1995-12-15|TAKE BACK RETURN|RAIL|he quickly regular packages. ca +9927|119356|4379|6|8|11002.80|0.07|0.08|N|O|1995-10-21|1995-10-31|1995-11-11|DELIVER IN PERSON|MAIL|ously above the quickly regular depo +9952|99735|2245|1|23|39898.79|0.05|0.04|R|F|1992-08-24|1992-07-22|1992-08-27|NONE|REG AIR|cies about the furiously express +9952|41867|9380|2|20|36177.20|0.03|0.00|A|F|1992-05-21|1992-06-07|1992-06-01|NONE|AIR|requests. regularly +9952|42894|7903|3|15|27553.35|0.10|0.04|R|F|1992-05-07|1992-06-24|1992-05-19|COLLECT COD|SHIP|e ironic, special accounts. car +9953|179971|5006|1|2|4101.94|0.09|0.06|A|F|1995-04-05|1995-04-28|1995-05-03|DELIVER IN PERSON|MAIL|usly regular accou +9953|159217|4248|2|10|12762.10|0.06|0.05|R|F|1995-03-09|1995-05-23|1995-04-06|COLLECT COD|MAIL|ckly regular +9954|92138|2139|1|30|33903.90|0.00|0.07|R|F|1994-07-26|1994-09-01|1994-08-24|DELIVER IN PERSON|RAIL|requests are blithely after the ironic d +9954|154176|1722|2|3|3690.51|0.01|0.06|A|F|1994-09-10|1994-09-02|1994-10-04|DELIVER IN PERSON|REG AIR|s haggle evenly. dogged +9954|31841|4345|3|28|49639.52|0.04|0.02|A|F|1994-09-08|1994-07-24|1994-09-28|TAKE BACK RETURN|TRUCK|nding, bol +9954|143464|3465|4|37|55776.02|0.05|0.02|R|F|1994-08-08|1994-07-21|1994-09-01|DELIVER IN PERSON|FOB| express requests sleep +9954|182959|5478|5|20|40839.00|0.05|0.06|R|F|1994-07-14|1994-09-08|1994-07-20|NONE|REG AIR|ntly pending dolphins. quickly ironic pa +9954|181203|8758|6|18|23115.60|0.09|0.02|A|F|1994-06-21|1994-08-26|1994-06-29|TAKE BACK RETURN|TRUCK|refully fin +9955|6119|1120|1|36|36903.96|0.09|0.00|N|O|1995-12-17|1995-10-24|1995-12-23|NONE|AIR|es. carefully p +9955|28536|3541|2|15|21967.95|0.00|0.03|N|O|1995-11-12|1995-11-19|1995-11-26|NONE|RAIL|deas. regular, express +9955|193828|1386|3|42|80716.44|0.01|0.08|N|O|1995-10-11|1995-10-16|1995-10-14|TAKE BACK RETURN|AIR|ecial, special deposit +9955|52552|5058|4|9|13540.95|0.01|0.07|N|O|1995-10-24|1995-12-02|1995-11-14|COLLECT COD|SHIP|de of the pending +9955|38777|6287|5|23|39462.71|0.05|0.00|N|O|1995-12-23|1995-11-06|1996-01-13|NONE|REG AIR|ages. express inst +9955|113117|3118|6|14|15821.54|0.05|0.04|N|O|1995-10-30|1995-10-25|1995-11-25|NONE|TRUCK|ending packages sleep fluffily +9956|6898|9399|1|40|72195.60|0.02|0.02|R|F|1993-05-13|1993-05-30|1993-06-01|COLLECT COD|MAIL|n ideas detect blithely package +9957|149692|7235|1|23|40058.87|0.03|0.03|A|F|1994-03-30|1994-02-05|1994-04-13|DELIVER IN PERSON|SHIP| according to the special accounts doubt at +9957|70593|8115|2|21|32835.39|0.09|0.06|R|F|1994-03-08|1994-01-21|1994-04-04|TAKE BACK RETURN|AIR|ages. blithely +9958|178719|6271|1|37|66515.27|0.09|0.04|A|F|1994-01-25|1994-01-27|1994-02-03|DELIVER IN PERSON|AIR|ter the carefully final plate +9958|128173|3198|2|38|45644.46|0.03|0.05|R|F|1994-03-24|1993-12-27|1994-04-12|DELIVER IN PERSON|FOB|instructions. regular pinto beans boost +9958|191054|3574|3|23|26336.15|0.08|0.00|A|F|1993-12-21|1994-01-21|1993-12-23|DELIVER IN PERSON|REG AIR|cuses detect. flu +9958|39415|9416|4|38|51467.58|0.05|0.06|R|F|1994-01-11|1994-01-22|1994-01-30|NONE|AIR|refully reg +9959|48904|1409|1|6|11117.40|0.00|0.03|N|O|1995-11-13|1995-12-13|1995-11-16|COLLECT COD|RAIL| unusual pin +9959|114641|9664|2|10|16556.40|0.07|0.07|N|O|1995-11-07|1995-11-17|1995-11-28|TAKE BACK RETURN|SHIP|bove the pendi +9984|120079|80|1|18|19783.26|0.01|0.04|N|O|1998-09-26|1998-08-27|1998-10-13|NONE|REG AIR|nusual excuses; fluffily ironic pack +9984|151767|1768|2|49|89119.24|0.01|0.03|N|O|1998-08-02|1998-09-13|1998-08-08|TAKE BACK RETURN|FOB|er the special sheaves. unusual +9984|139257|9258|3|33|42776.25|0.03|0.00|N|O|1998-09-03|1998-09-15|1998-09-16|COLLECT COD|REG AIR| theodolites. carefully re +9984|79982|7504|4|27|52973.46|0.04|0.05|N|O|1998-07-14|1998-08-21|1998-07-15|TAKE BACK RETURN|AIR|lly. furiously express +9984|48156|8157|5|41|45270.15|0.07|0.02|N|O|1998-10-18|1998-08-20|1998-10-31|TAKE BACK RETURN|TRUCK|ructions. doggedly special requests de +9985|160380|5413|1|38|54734.44|0.06|0.08|A|F|1993-08-21|1993-10-23|1993-09-06|NONE|MAIL|fully ironic hockey players use q +9985|97630|7631|2|1|1627.63|0.03|0.00|A|F|1993-10-08|1993-11-06|1993-10-24|COLLECT COD|RAIL|bove the ac +9985|52396|4902|3|17|22922.63|0.08|0.01|R|F|1993-10-17|1993-10-03|1993-11-10|NONE|TRUCK|rding to the regular +9986|21662|1663|1|40|63346.40|0.04|0.07|N|O|1998-01-20|1997-11-03|1998-01-31|DELIVER IN PERSON|RAIL| the regular asymptotes. fl +9986|67666|2679|2|47|76782.02|0.02|0.02|N|O|1997-10-02|1997-12-19|1997-10-13|TAKE BACK RETURN|REG AIR|ular platelets. quickly final asymptotes a +9986|46637|1646|3|22|34839.86|0.00|0.01|N|O|1997-12-10|1997-12-17|1997-12-16|TAKE BACK RETURN|REG AIR|ing to the slyly ironic r +9987|183000|3001|1|11|11913.00|0.06|0.07|N|O|1995-12-28|1996-02-16|1996-01-10|TAKE BACK RETURN|SHIP|accounts are furio +9987|65367|5368|2|41|54626.76|0.10|0.08|N|O|1996-02-23|1996-01-22|1996-03-22|DELIVER IN PERSON|TRUCK|unts toward the blithely unusual ide +9987|6983|1984|3|20|37799.60|0.09|0.06|N|O|1996-01-15|1996-02-10|1996-01-22|NONE|AIR|slyly final requ +9987|161053|1054|4|41|45676.05|0.06|0.07|N|O|1996-03-03|1996-01-30|1996-03-25|TAKE BACK RETURN|MAIL|ctions haggle furiously furiousl +9987|14038|6540|5|38|36177.14|0.02|0.01|N|O|1996-01-10|1996-02-13|1996-02-06|COLLECT COD|SHIP|s. express, dogged instr +9987|133634|3635|6|33|55031.79|0.06|0.05|N|O|1996-01-22|1996-02-02|1996-01-25|DELIVER IN PERSON|RAIL|ent, silent pinto beans about th +9988|175628|8146|1|37|63033.94|0.07|0.05|N|O|1998-02-01|1998-02-05|1998-02-22|TAKE BACK RETURN|TRUCK|es wake fluffily bold multipliers. slyly +9988|173163|5681|2|50|61808.00|0.04|0.01|N|O|1997-12-19|1998-02-02|1997-12-31|COLLECT COD|MAIL| unusual accounts. carefully +9989|24718|9723|1|8|13141.68|0.06|0.08|A|F|1993-08-17|1993-09-16|1993-09-14|COLLECT COD|TRUCK|ly ironic packages. f +9989|25985|5986|2|4|7643.92|0.00|0.02|R|F|1993-09-02|1993-08-16|1993-09-21|TAKE BACK RETURN|MAIL|inal instructions impress according +9989|119365|4388|3|28|38762.08|0.08|0.02|A|F|1993-08-21|1993-07-22|1993-09-13|NONE|SHIP|packages. i +9989|152320|2321|4|50|68616.00|0.05|0.04|A|F|1993-09-11|1993-09-12|1993-09-13|NONE|TRUCK|lithely fi +9990|78600|8601|1|48|75772.80|0.06|0.06|R|F|1992-03-29|1992-06-08|1992-04-14|COLLECT COD|AIR|ly ironic theodolites-- bold deposit +9991|4827|7328|1|37|64077.34|0.01|0.00|N|O|1996-07-07|1996-07-22|1996-07-16|COLLECT COD|AIR|ng asymptotes across the blithely r +9991|127269|4806|2|47|60924.22|0.02|0.00|N|O|1996-06-21|1996-08-16|1996-07-11|COLLECT COD|AIR|ular accounts? furiousl +10016|32092|9602|1|23|23554.07|0.02|0.06|R|F|1993-05-10|1993-04-02|1993-06-03|TAKE BACK RETURN|FOB|ons. requests haggle furiously aft +10017|32566|5070|1|50|74928.00|0.01|0.01|N|O|1998-06-07|1998-05-25|1998-06-10|NONE|SHIP|have to wake. packages inte +10017|131861|6888|2|31|58678.66|0.04|0.07|N|O|1998-07-27|1998-05-12|1998-08-23|TAKE BACK RETURN|SHIP|about the ironically ironic +10018|136298|1325|1|1|1334.29|0.08|0.03|A|F|1993-07-16|1993-08-04|1993-08-02|COLLECT COD|SHIP|ter the fluffily pending asymp +10018|155140|7656|2|35|41829.90|0.10|0.02|R|F|1993-07-13|1993-08-30|1993-07-28|DELIVER IN PERSON|MAIL|ls. carefully pending pinto beans dazzle +10018|32266|4770|3|31|37146.06|0.06|0.05|A|F|1993-07-12|1993-08-02|1993-08-07|COLLECT COD|FOB|after the furiously regular theodolites: +10019|55050|7556|1|50|50252.50|0.02|0.04|R|F|1994-10-08|1994-10-09|1994-10-20|COLLECT COD|RAIL|ts are even, special grouches. slyly regula +10019|24390|6893|2|32|42060.48|0.01|0.07|R|F|1994-08-10|1994-08-20|1994-08-30|COLLECT COD|FOB|uickly. blithely final dependencies +10019|108905|8906|3|42|80383.80|0.05|0.03|A|F|1994-08-31|1994-09-07|1994-09-28|TAKE BACK RETURN|REG AIR| serve carefully carefully even ideas. +10019|154987|18|4|11|22461.78|0.03|0.04|R|F|1994-10-06|1994-09-22|1994-10-18|TAKE BACK RETURN|REG AIR|n furiously regular deposits. sly +10020|121658|6683|1|23|38631.95|0.02|0.00|N|O|1998-05-24|1998-06-21|1998-06-01|NONE|REG AIR|ackages use accounts. unusual, final packa +10020|91478|6497|2|40|58778.80|0.03|0.05|N|O|1998-07-31|1998-06-27|1998-08-13|NONE|REG AIR|ously express requests integrate fu +10021|17774|2777|1|18|30451.86|0.02|0.00|R|F|1992-09-09|1992-10-16|1992-09-28|COLLECT COD|SHIP|ounts use. silent foxe +10021|121007|8544|2|28|28784.00|0.04|0.06|A|F|1992-10-02|1992-10-16|1992-10-21|COLLECT COD|RAIL|s. regular, ironic deposits sleep +10022|26504|9007|1|40|57220.00|0.05|0.08|R|F|1994-04-17|1994-05-04|1994-04-27|COLLECT COD|REG AIR|leep furiously. furiously +10022|40185|7698|2|18|20253.24|0.03|0.02|A|F|1994-07-04|1994-04-26|1994-07-30|DELIVER IN PERSON|FOB|. carefully final asymptotes above th +10023|24002|6505|1|40|37040.00|0.03|0.03|N|O|1996-12-17|1997-02-18|1996-12-30|DELIVER IN PERSON|MAIL|special excuses cajole fluffily blit +10023|199662|9663|2|7|12331.62|0.02|0.02|N|O|1997-01-04|1997-01-17|1997-01-12|NONE|SHIP|ages solve blithely regular, fina +10023|108439|8440|3|31|44870.33|0.05|0.04|N|O|1997-03-31|1997-01-01|1997-04-16|NONE|REG AIR|efully. fluffily bold dolphins haggle +10023|132174|7201|4|15|18092.55|0.03|0.06|N|O|1997-02-27|1997-01-18|1997-03-06|COLLECT COD|MAIL| integrate furiously even package +10048|173678|1230|1|19|33281.73|0.01|0.04|A|F|1994-08-31|1994-06-29|1994-09-22|TAKE BACK RETURN|AIR|sits. unusual pinto b +10048|204|7705|2|34|37542.80|0.03|0.05|A|F|1994-06-07|1994-08-10|1994-06-11|DELIVER IN PERSON|RAIL|usual requests shoul +10049|68506|8507|1|39|57505.50|0.00|0.06|N|O|1997-10-09|1997-09-25|1997-10-12|NONE|RAIL|final courts. furiousl +10049|165548|581|2|34|54860.36|0.04|0.07|N|O|1997-08-27|1997-10-05|1997-09-07|DELIVER IN PERSON|AIR|eodolites. final, even deposits +10049|159301|6847|3|4|5441.20|0.00|0.00|N|O|1997-11-13|1997-09-26|1997-12-11|NONE|FOB|e. bold packages nod qu +10049|164042|6559|4|30|33181.20|0.09|0.04|N|O|1997-08-26|1997-09-18|1997-09-07|DELIVER IN PERSON|MAIL|ses sleep along the furiously unusual shea +10050|199821|7379|1|33|63387.06|0.08|0.05|N|O|1996-11-12|1996-11-09|1996-11-25|NONE|TRUCK|ests haggl +10050|175779|814|2|35|64916.95|0.06|0.00|N|O|1997-01-02|1996-11-14|1997-01-19|COLLECT COD|FOB| bold, regular foxe +10050|104518|7029|3|5|7612.55|0.08|0.08|N|O|1996-09-15|1996-10-24|1996-09-28|COLLECT COD|RAIL|he ideas detect slyly dur +10050|22788|295|4|29|49612.62|0.06|0.04|N|O|1996-11-15|1996-11-14|1996-11-27|COLLECT COD|MAIL|st furiously final requ +10051|82853|378|1|31|56911.35|0.08|0.04|N|O|1996-06-20|1996-07-17|1996-07-18|DELIVER IN PERSON|SHIP|nal packages sleep along the r +10051|97751|2770|2|28|48965.00|0.06|0.08|N|O|1996-06-04|1996-06-24|1996-06-08|TAKE BACK RETURN|TRUCK| final ideas sle +10051|86917|6918|3|14|26654.74|0.08|0.00|N|O|1996-08-23|1996-08-18|1996-09-10|TAKE BACK RETURN|REG AIR|ully even requests are fi +10051|5431|5432|4|46|61475.78|0.08|0.02|N|O|1996-07-11|1996-08-21|1996-07-29|COLLECT COD|TRUCK|eaves are after the blithely ev +10052|38654|8655|1|30|47779.50|0.07|0.06|A|F|1994-12-18|1994-12-02|1994-12-29|NONE|SHIP|ove the blithely final a +10052|54372|1888|2|39|51728.43|0.09|0.07|A|F|1994-12-22|1994-10-10|1995-01-06|TAKE BACK RETURN|AIR| express packages. even packages are care +10052|17613|7614|3|29|44387.69|0.01|0.04|A|F|1994-12-09|1994-11-26|1995-01-04|NONE|TRUCK| the unusual accounts. furiousl +10052|13442|3443|4|25|33886.00|0.06|0.05|R|F|1995-01-02|1994-11-11|1995-01-07|DELIVER IN PERSON|MAIL|lar deposits! f +10052|109995|2506|5|29|58144.71|0.05|0.04|A|F|1994-09-10|1994-12-06|1994-09-16|NONE|MAIL|refully bold ins +10052|71363|3871|6|10|13343.60|0.01|0.01|R|F|1994-10-19|1994-11-06|1994-11-02|DELIVER IN PERSON|MAIL|ross the regular platel +10053|7672|5173|1|15|23695.05|0.08|0.00|R|F|1992-01-12|1992-03-08|1992-02-08|TAKE BACK RETURN|TRUCK|ously unusual requests wake against t +10053|134417|4418|2|24|34833.84|0.01|0.01|R|F|1992-04-16|1992-02-18|1992-05-13|NONE|TRUCK|ar, ironic +10053|143937|3938|3|21|41599.53|0.02|0.07|R|F|1992-03-20|1992-02-10|1992-03-25|COLLECT COD|TRUCK|ts boost furiously ironic fo +10053|140152|7695|4|24|28611.60|0.07|0.06|R|F|1992-01-14|1992-03-05|1992-01-18|TAKE BACK RETURN|TRUCK|es. even warthogs are sly +10053|128705|3730|5|43|74549.10|0.09|0.05|A|F|1992-04-08|1992-02-22|1992-04-11|TAKE BACK RETURN|REG AIR|the express asympto +10054|96535|1554|1|34|52072.02|0.00|0.01|N|O|1995-08-11|1995-07-21|1995-09-10|TAKE BACK RETURN|MAIL|press accounts detect slyly. quickly speci +10054|58123|629|2|31|33514.72|0.02|0.06|N|O|1995-07-17|1995-07-08|1995-07-25|DELIVER IN PERSON|AIR|nto beans are. even foxes use idle +10055|160218|219|1|43|54963.03|0.00|0.04|N|O|1996-04-23|1996-05-26|1996-04-29|COLLECT COD|REG AIR|slyly final package +10055|168451|6000|2|2|3038.90|0.04|0.01|N|O|1996-05-14|1996-04-02|1996-05-18|DELIVER IN PERSON|REG AIR|ove the slyly even accounts. ir +10055|147373|7374|3|11|15624.07|0.00|0.00|N|O|1996-03-10|1996-05-07|1996-03-31|DELIVER IN PERSON|RAIL|old pinto bea +10055|95918|8428|4|13|24880.83|0.04|0.01|N|O|1996-04-18|1996-05-17|1996-05-13|DELIVER IN PERSON|RAIL|s sleep among th +10080|20683|684|1|44|70561.92|0.03|0.05|R|F|1993-05-21|1993-04-23|1993-05-26|COLLECT COD|FOB|fluffily unusual sentiments run. +10080|14831|9834|2|24|41899.92|0.05|0.01|R|F|1993-04-20|1993-03-26|1993-04-30|TAKE BACK RETURN|SHIP| slyly quick dolphins. +10080|57039|7040|3|49|48805.47|0.04|0.03|R|F|1993-06-06|1993-05-12|1993-06-09|NONE|SHIP|beans against the +10080|40848|8361|4|32|57242.88|0.04|0.04|R|F|1993-04-11|1993-05-01|1993-05-04|TAKE BACK RETURN|TRUCK|final ideas integra +10080|128152|665|5|10|11801.50|0.05|0.01|A|F|1993-03-18|1993-04-13|1993-04-06|NONE|REG AIR|riously about +10080|49386|6899|6|14|18695.32|0.07|0.06|R|F|1993-05-17|1993-03-17|1993-05-27|DELIVER IN PERSON|FOB|ely unusual requests boost +10080|25736|741|7|2|3323.46|0.07|0.07|A|F|1993-05-11|1993-03-19|1993-05-12|TAKE BACK RETURN|REG AIR|ress theodolites sleep bravely. final, eve +10081|141819|6848|1|28|52102.68|0.02|0.07|A|F|1993-10-18|1993-09-28|1993-11-15|NONE|TRUCK|nic requests are slyly. packages ca +10081|148533|1048|2|41|64842.73|0.04|0.02|A|F|1993-10-22|1993-10-08|1993-10-28|DELIVER IN PERSON|FOB|e packages. bol +10081|180304|5341|3|37|51219.10|0.07|0.06|A|F|1993-10-31|1993-09-30|1993-11-28|COLLECT COD|TRUCK|iously thin accounts? regular, unu +10081|166665|1698|4|38|65803.08|0.02|0.06|R|F|1993-11-23|1993-10-03|1993-11-25|TAKE BACK RETURN|REG AIR|e final courts. quickly express accou +10081|134875|2415|5|1|1909.87|0.04|0.08|R|F|1993-09-19|1993-10-17|1993-10-19|COLLECT COD|SHIP|unusual deposi +10081|38249|8250|6|39|46302.36|0.06|0.02|A|F|1993-12-06|1993-09-28|1993-12-20|NONE|REG AIR|nic ideas haggle quickly ar +10082|20056|7563|1|48|46850.40|0.05|0.00|R|F|1994-12-13|1994-11-10|1994-12-25|TAKE BACK RETURN|FOB|telets. ironic requests hagg +10082|77354|4876|2|10|13313.50|0.06|0.08|R|F|1994-12-17|1994-10-19|1994-12-20|NONE|AIR| alongside of the deposits +10082|84626|2151|3|25|40265.50|0.10|0.04|R|F|1994-09-04|1994-11-18|1994-09-07|TAKE BACK RETURN|TRUCK|sits. blithely regul +10082|96929|9439|4|23|44296.16|0.10|0.03|A|F|1994-09-15|1994-10-10|1994-09-27|TAKE BACK RETURN|AIR|esias nag ca +10082|71710|6725|5|20|33634.20|0.07|0.04|R|F|1994-10-11|1994-11-12|1994-10-29|DELIVER IN PERSON|SHIP|slyly final accoun +10082|18117|8118|6|35|36228.85|0.05|0.02|A|F|1994-10-12|1994-09-30|1994-11-06|TAKE BACK RETURN|SHIP|equests are quickly ironic requests. b +10083|150645|8191|1|40|67825.60|0.04|0.02|N|O|1995-10-12|1995-12-05|1995-10-22|NONE|SHIP|unusual instructions a +10084|95352|2880|1|3|4042.05|0.09|0.05|N|O|1997-09-07|1997-09-18|1997-09-22|NONE|AIR|gainst the slyly +10085|195730|5731|1|35|63900.55|0.08|0.06|N|O|1996-07-12|1996-06-15|1996-07-19|NONE|MAIL| about the blithely daring deposi +10085|27484|7485|2|34|47990.32|0.05|0.04|N|O|1996-04-06|1996-06-22|1996-04-20|TAKE BACK RETURN|MAIL|rate quickly stealthily clos +10085|123287|3288|3|14|18343.92|0.01|0.00|N|O|1996-05-19|1996-06-04|1996-05-20|DELIVER IN PERSON|TRUCK|ans. doggedly pending excuses +10085|72189|4697|4|33|38318.94|0.07|0.06|N|O|1996-06-04|1996-05-08|1996-06-26|NONE|MAIL| foxes alongside of the careful +10085|74613|4614|5|33|52391.13|0.06|0.04|N|O|1996-06-13|1996-05-03|1996-06-16|COLLECT COD|REG AIR|arefully after the requests. iron +10086|157864|2895|1|35|67265.10|0.08|0.07|N|O|1995-06-29|1995-08-01|1995-07-21|TAKE BACK RETURN|MAIL| deposits haggle blithely. even packages a +10087|140968|8511|1|48|96430.08|0.09|0.06|N|O|1997-05-08|1997-06-05|1997-05-13|NONE|MAIL|c patterns alongs +10087|33430|5934|2|14|19088.02|0.00|0.00|N|O|1997-05-11|1997-06-07|1997-05-13|DELIVER IN PERSON|RAIL|usly above +10112|171163|8715|1|21|25917.36|0.00|0.04|A|F|1994-03-03|1994-03-04|1994-03-30|DELIVER IN PERSON|TRUCK|ully special theodolites about the stealthi +10113|187288|9807|1|35|48134.80|0.03|0.02|R|F|1994-07-20|1994-07-18|1994-07-25|COLLECT COD|REG AIR|grate carefull +10113|149264|6807|2|20|26265.20|0.08|0.02|A|F|1994-08-12|1994-09-04|1994-08-22|NONE|SHIP|uickly express packages wake fluffily. s +10113|72444|4952|3|28|39660.32|0.05|0.05|R|F|1994-10-04|1994-07-13|1994-10-24|COLLECT COD|FOB|ccounts sleep. blithely dog +10113|153335|8366|4|40|55533.20|0.01|0.07|R|F|1994-07-02|1994-07-23|1994-07-04|COLLECT COD|REG AIR|haggle quickly platelets. furiously +10114|144275|9304|1|34|44855.18|0.05|0.08|R|F|1993-04-11|1993-03-13|1993-04-30|TAKE BACK RETURN|MAIL|ly final packages. specia +10115|176655|6656|1|16|27706.40|0.00|0.00|N|O|1998-10-01|1998-08-10|1998-10-26|NONE|FOB|n foxes haggle carefully according +10115|27859|7860|2|40|71474.00|0.07|0.06|N|O|1998-09-05|1998-08-31|1998-09-19|COLLECT COD|RAIL|oss the expres +10115|23656|3657|3|28|44230.20|0.06|0.01|N|O|1998-09-15|1998-09-11|1998-09-22|TAKE BACK RETURN|MAIL|blithely after t +10115|185632|5633|4|23|39505.49|0.04|0.07|N|O|1998-10-25|1998-08-06|1998-11-05|TAKE BACK RETURN|RAIL|ourts among the blithely spe +10116|87915|7916|1|36|68504.76|0.00|0.03|N|O|1997-04-26|1997-04-26|1997-05-17|DELIVER IN PERSON|FOB|nts. blithely bo +10116|177796|7797|2|9|16864.11|0.06|0.07|N|O|1997-07-20|1997-06-12|1997-08-17|TAKE BACK RETURN|FOB|s. fluffily unusual instructions run abov +10116|10319|2821|3|48|59006.88|0.09|0.05|N|O|1997-04-21|1997-06-21|1997-05-20|COLLECT COD|FOB|e blithely special theodolites. s +10116|15931|8433|4|31|57254.83|0.02|0.07|N|O|1997-06-09|1997-04-29|1997-06-17|TAKE BACK RETURN|TRUCK|pending instructions use slyly. unusual +10116|150511|512|5|43|67144.93|0.04|0.05|N|O|1997-04-17|1997-05-08|1997-05-11|DELIVER IN PERSON|REG AIR|equests. slyly +10117|168157|5706|1|47|57582.05|0.08|0.00|R|F|1993-12-22|1993-12-18|1994-01-08|DELIVER IN PERSON|FOB|use according to t +10117|11617|9121|2|12|18343.32|0.03|0.08|R|F|1994-02-15|1993-12-28|1994-03-03|DELIVER IN PERSON|FOB|ular excuses. +10117|42753|266|3|38|64438.50|0.03|0.00|A|F|1994-02-26|1994-02-13|1994-02-27|NONE|TRUCK|-- requests about +10118|188894|1413|1|14|27760.46|0.03|0.01|R|F|1994-06-12|1994-05-12|1994-06-18|COLLECT COD|MAIL|ely quick pinto beans. slyly express the +10119|198109|629|1|27|32591.70|0.04|0.06|N|O|1996-07-12|1996-09-21|1996-08-05|NONE|TRUCK|en excuses grow evenly furiously +10144|141663|1664|1|17|28979.22|0.06|0.08|A|F|1995-04-05|1995-03-21|1995-04-26|TAKE BACK RETURN|AIR|s. furiously even deposits acros +10144|128812|8813|2|19|34975.39|0.07|0.05|A|F|1995-03-30|1995-02-21|1995-04-12|DELIVER IN PERSON|FOB|s serve blithely permanent package +10144|136479|4019|3|41|62134.27|0.07|0.06|A|F|1995-02-19|1995-03-27|1995-03-01|DELIVER IN PERSON|MAIL|osits nag carefully express +10144|197167|4725|4|40|50566.40|0.07|0.00|R|F|1995-02-07|1995-03-15|1995-03-02|NONE|RAIL|uses. even requests play +10144|176216|3768|5|42|54272.82|0.06|0.06|R|F|1995-02-19|1995-03-30|1995-03-02|NONE|REG AIR|eas sleep furiously. pending +10145|175671|3223|1|30|52400.10|0.01|0.02|N|O|1995-07-31|1995-07-15|1995-08-02|NONE|FOB|ironic warthogs bo +10145|90677|3187|2|16|26682.72|0.01|0.03|N|O|1995-07-11|1995-08-10|1995-07-28|NONE|AIR|refully special +10145|198700|8701|3|19|34175.30|0.00|0.06|N|O|1995-08-11|1995-07-24|1995-08-17|TAKE BACK RETURN|TRUCK|y behind the furiously regular reque +10145|143870|6385|4|47|89951.89|0.00|0.07|R|F|1995-05-27|1995-07-02|1995-06-14|TAKE BACK RETURN|FOB|regular pinto bea +10145|21312|8819|5|37|45632.47|0.10|0.03|N|O|1995-06-19|1995-06-29|1995-07-12|DELIVER IN PERSON|REG AIR|iously bold req +10145|175895|930|6|46|90660.94|0.02|0.05|N|F|1995-05-31|1995-07-21|1995-06-30|COLLECT COD|TRUCK|ial platelets above the furiously i +10146|28088|3093|1|32|32514.56|0.01|0.04|A|F|1994-05-29|1994-06-18|1994-06-09|COLLECT COD|FOB| ironic ideas. depo +10146|64363|4364|2|33|43802.88|0.07|0.05|A|F|1994-06-19|1994-07-21|1994-07-01|NONE|REG AIR|mptotes sleep furiously. slyl +10146|134555|7069|3|13|20664.15|0.03|0.06|R|F|1994-05-10|1994-06-15|1994-06-04|COLLECT COD|REG AIR|ts. packages wake slyly against +10146|62327|4834|4|11|14182.52|0.05|0.07|R|F|1994-05-25|1994-07-31|1994-06-08|COLLECT COD|AIR|ously regular packages affix along the unus +10146|116058|3592|5|31|33295.55|0.04|0.07|R|F|1994-07-27|1994-07-29|1994-08-03|DELIVER IN PERSON|MAIL|nic accounts. ideas sleep slyly +10146|182088|7125|6|30|35102.40|0.03|0.08|A|F|1994-06-26|1994-07-18|1994-07-25|COLLECT COD|FOB|old ideas. slyly regular +10146|143846|3847|7|20|37796.80|0.00|0.01|R|F|1994-05-16|1994-07-20|1994-06-05|NONE|FOB| blithely ironic notornis. furiously bo +10147|15121|124|1|40|41444.80|0.08|0.07|A|F|1993-12-23|1993-11-14|1994-01-05|NONE|MAIL|fluffily bold pinto beans. ironic, +10147|138383|5923|2|1|1421.38|0.06|0.08|A|F|1993-12-30|1993-11-14|1994-01-23|NONE|AIR| furiously even orbits. furious +10147|190695|5734|3|10|17856.90|0.00|0.07|A|F|1993-11-13|1994-01-01|1993-12-13|DELIVER IN PERSON|SHIP|lar deposits. furiously +10147|194511|4512|4|44|70642.44|0.10|0.07|A|F|1993-12-25|1993-12-18|1994-01-03|TAKE BACK RETURN|AIR|furiously regular packages. +10147|138188|3215|5|47|57630.46|0.02|0.07|A|F|1993-10-15|1993-12-18|1993-10-22|TAKE BACK RETURN|AIR|lar packages. ironic depo +10148|101480|9011|1|10|14814.80|0.00|0.01|R|F|1994-04-25|1994-05-15|1994-05-10|NONE|MAIL|g, regular hockey players cajole si +10148|162766|7799|2|16|29260.16|0.02|0.02|R|F|1994-05-19|1994-06-02|1994-06-15|COLLECT COD|REG AIR| accounts. carefully final foxes among the +10148|195608|8128|3|28|47700.80|0.07|0.08|A|F|1994-05-21|1994-06-24|1994-05-28|DELIVER IN PERSON|FOB|al accounts sleep finally carefu +10148|180599|600|4|33|55426.47|0.05|0.02|R|F|1994-05-20|1994-04-29|1994-06-01|TAKE BACK RETURN|FOB|equests slee +10149|68636|3649|1|32|51348.16|0.08|0.02|A|F|1994-10-03|1994-11-07|1994-11-02|COLLECT COD|RAIL|lithely? slyly final theo +10149|163019|8052|2|46|49772.46|0.10|0.02|R|F|1994-11-04|1994-11-05|1994-12-03|TAKE BACK RETURN|TRUCK|l, regular instructions boost +10149|50073|74|3|13|13299.91|0.10|0.06|R|F|1994-12-27|1994-11-19|1995-01-05|TAKE BACK RETURN|SHIP|tly stealthy requests are fluffily alongsid +10149|164076|9109|4|8|9120.56|0.02|0.03|A|F|1994-12-19|1994-11-25|1995-01-06|DELIVER IN PERSON|MAIL| the regul +10149|13808|3809|5|23|39601.40|0.00|0.06|A|F|1995-01-15|1994-11-13|1995-01-21|COLLECT COD|RAIL|sly packages. slyly unusual package +10149|70113|2621|6|1|1083.11|0.07|0.04|A|F|1994-11-08|1994-10-28|1994-11-19|NONE|RAIL|nusual, express packages wak +10150|83663|8680|1|49|80686.34|0.02|0.03|A|F|1992-07-18|1992-07-21|1992-08-09|TAKE BACK RETURN|REG AIR|ess dolphins. blithely regular f +10150|117479|2502|2|27|40404.69|0.00|0.00|R|F|1992-06-16|1992-06-03|1992-06-25|NONE|FOB|ackages. silent foxe +10150|54897|7403|3|41|75927.49|0.08|0.04|R|F|1992-05-12|1992-06-19|1992-06-05|NONE|MAIL|counts. excuses agains +10150|37786|5296|4|13|22409.14|0.10|0.01|A|F|1992-06-14|1992-06-01|1992-07-03|NONE|SHIP|ickly special accounts integrate quickly f +10150|54076|1592|5|28|28841.96|0.04|0.00|A|F|1992-06-10|1992-06-28|1992-06-17|DELIVER IN PERSON|TRUCK|efully even i +10150|53849|8860|6|44|79324.96|0.03|0.07|A|F|1992-08-29|1992-06-30|1992-09-19|NONE|REG AIR|e ironic ide +10151|163988|9021|1|7|14363.86|0.10|0.06|R|F|1992-04-13|1992-03-07|1992-04-15|NONE|MAIL|nusual packages. furiously final instru +10176|32093|2094|1|46|47154.14|0.08|0.03|N|O|1996-09-01|1996-11-18|1996-09-20|TAKE BACK RETURN|TRUCK| never final, pending ac +10176|185648|685|2|29|50275.56|0.06|0.03|N|O|1996-11-14|1996-10-24|1996-12-13|TAKE BACK RETURN|TRUCK| slyly among the +10177|135285|312|1|43|56772.04|0.05|0.03|N|O|1996-09-20|1996-08-05|1996-10-13|COLLECT COD|FOB|realms. spe +10177|118635|6169|2|32|52916.16|0.07|0.03|N|O|1996-07-14|1996-08-19|1996-08-02|DELIVER IN PERSON|TRUCK|inal packages sleep furiously entici +10177|96426|1445|3|41|58319.22|0.02|0.02|N|O|1996-07-12|1996-09-02|1996-07-23|NONE|SHIP|about the blithely regular packages. excus +10177|20231|7738|4|41|47200.43|0.03|0.04|N|O|1996-10-22|1996-08-21|1996-11-17|COLLECT COD|TRUCK|e ideas. slyly regular packages a +10177|17452|4956|5|1|1369.45|0.10|0.01|N|O|1996-08-19|1996-08-11|1996-08-22|TAKE BACK RETURN|TRUCK|er the carefully even +10178|148709|3738|1|33|58004.10|0.00|0.01|A|F|1994-01-29|1994-02-27|1994-02-06|COLLECT COD|RAIL|oss the carefully s +10179|67970|2983|1|34|65890.98|0.09|0.03|N|O|1996-08-23|1996-06-27|1996-08-29|COLLECT COD|SHIP|ithely regu +10179|165928|8445|2|31|61811.52|0.10|0.06|N|O|1996-07-26|1996-07-09|1996-08-10|COLLECT COD|AIR|courts. furiously ironi +10179|141337|3852|3|44|60646.52|0.08|0.07|N|O|1996-06-02|1996-06-15|1996-06-16|DELIVER IN PERSON|REG AIR|the final instructions wake about the +10180|125189|7702|1|9|10927.62|0.00|0.05|N|O|1997-04-23|1997-05-20|1997-04-28|COLLECT COD|SHIP|ly alongside of the +10180|49205|9206|2|29|33471.80|0.10|0.05|N|O|1997-04-28|1997-04-24|1997-05-02|NONE|FOB|cuses within the ironic, final pinto be +10180|174482|4483|3|17|26460.16|0.04|0.01|N|O|1997-04-20|1997-05-23|1997-05-02|NONE|SHIP|counts are carefully bli +10181|67236|4755|1|12|14438.76|0.00|0.02|N|O|1996-03-25|1996-04-30|1996-03-29|DELIVER IN PERSON|FOB|nts sleep ca +10181|28997|1500|2|23|44297.77|0.07|0.06|N|O|1996-02-22|1996-04-09|1996-03-21|NONE|SHIP|ular, final excuses. furiou +10182|141766|4281|1|44|79541.44|0.05|0.04|R|F|1994-06-24|1994-07-04|1994-07-20|DELIVER IN PERSON|SHIP|hins. furiou +10182|44701|7206|2|24|39496.80|0.04|0.08|A|F|1994-09-23|1994-08-16|1994-10-22|DELIVER IN PERSON|TRUCK|r dependencies wake. quickly special +10182|86226|6227|3|3|3636.66|0.03|0.07|A|F|1994-08-08|1994-07-25|1994-08-19|NONE|MAIL|ake furiously packages. pen +10182|183789|1344|4|46|86147.88|0.05|0.08|A|F|1994-06-15|1994-07-28|1994-07-10|TAKE BACK RETURN|RAIL|ely across the deposits. slyly s +10182|140930|8473|5|16|31534.88|0.05|0.05|R|F|1994-09-10|1994-08-21|1994-10-10|DELIVER IN PERSON|RAIL|e slyly regular +10183|53735|1251|1|33|55728.09|0.02|0.03|A|F|1995-03-02|1995-01-26|1995-03-17|NONE|SHIP|ckages hinder carefully. furiously +10183|113981|9004|2|2|3989.96|0.03|0.00|R|F|1995-02-24|1995-01-03|1995-03-19|DELIVER IN PERSON|FOB|lent packages against the furiously final t +10183|67479|2492|3|1|1446.47|0.00|0.06|A|F|1994-12-23|1995-01-29|1995-01-09|DELIVER IN PERSON|FOB|. carefully final requests could wake among +10183|113964|1498|4|19|37581.24|0.05|0.03|R|F|1995-02-09|1995-01-19|1995-02-25|TAKE BACK RETURN|MAIL|y unusual sheaves +10183|180890|5927|5|15|29563.35|0.02|0.07|A|F|1995-03-25|1995-01-23|1995-04-02|DELIVER IN PERSON|MAIL|sual packages. quiet, special excuses at +10183|10622|3124|6|13|19924.06|0.08|0.05|A|F|1994-11-26|1995-02-11|1994-12-08|TAKE BACK RETURN|FOB|ests alongside of the furiously ironic +10208|176632|1667|1|31|52967.53|0.08|0.05|N|O|1996-11-16|1996-11-18|1996-12-05|NONE|RAIL|al requests; ironic, ironi +10208|39153|9154|2|44|48054.60|0.00|0.03|N|O|1996-09-29|1996-09-28|1996-10-08|NONE|REG AIR| above the final packages. fluffily regular +10208|41563|4068|3|38|57173.28|0.01|0.04|N|O|1996-10-20|1996-10-06|1996-10-25|TAKE BACK RETURN|FOB|ent instructions haggle around the slyly sp +10208|140579|580|4|22|35630.54|0.06|0.02|N|O|1996-09-24|1996-09-26|1996-10-24|TAKE BACK RETURN|FOB|nusual accounts. r +10208|101815|6836|5|2|3633.62|0.08|0.03|N|O|1996-10-24|1996-11-13|1996-11-06|DELIVER IN PERSON|MAIL|rding to the brave, bold asympto +10208|193071|5591|6|26|30265.82|0.07|0.08|N|O|1996-11-19|1996-10-03|1996-11-28|TAKE BACK RETURN|TRUCK|the idle, unusual instructions. fluffily fi +10208|143474|1017|7|41|62216.27|0.10|0.00|N|O|1996-10-30|1996-10-27|1996-11-20|TAKE BACK RETURN|TRUCK|ly bold packag +10209|160597|3114|1|44|72933.96|0.04|0.07|A|F|1994-02-20|1994-01-17|1994-03-04|COLLECT COD|REG AIR|iously along the bold foxes: furiously fina +10209|146995|2024|2|18|36755.82|0.05|0.06|A|F|1994-02-07|1993-12-31|1994-02-08|TAKE BACK RETURN|FOB|of the blit +10209|139167|1681|3|46|55483.36|0.02|0.07|R|F|1994-03-07|1994-01-11|1994-03-31|DELIVER IN PERSON|MAIL| alongside of the blithely regular pa +10209|171623|9175|4|27|45754.74|0.10|0.08|R|F|1993-12-14|1994-02-21|1994-01-02|COLLECT COD|MAIL|egular pinto bean +10209|59630|7146|5|47|74712.61|0.00|0.05|A|F|1994-01-22|1994-01-05|1994-02-07|DELIVER IN PERSON|REG AIR| even ideas +10209|198063|3102|6|31|35992.86|0.03|0.01|A|F|1993-12-03|1994-02-28|1993-12-12|COLLECT COD|TRUCK|e. quickly even th +10209|43024|3025|7|50|48351.00|0.00|0.07|A|F|1994-01-20|1994-02-17|1994-02-16|NONE|TRUCK|tes are according to the regular asymptote +10210|102801|5312|1|8|14430.40|0.02|0.02|N|O|1995-10-11|1995-09-22|1995-11-08|NONE|AIR|uick orbits. slyl +10210|175359|5360|2|11|15777.85|0.10|0.04|N|O|1995-08-08|1995-08-31|1995-08-10|DELIVER IN PERSON|FOB|y express dependencies wake furiously +10210|47011|9516|3|36|34488.36|0.02|0.03|N|O|1995-10-20|1995-09-19|1995-11-10|TAKE BACK RETURN|RAIL|across the w +10210|106952|1973|4|11|21548.45|0.03|0.05|N|O|1995-09-06|1995-09-14|1995-09-11|COLLECT COD|REG AIR|es wake blit +10210|129121|4146|5|42|48305.04|0.06|0.01|N|O|1995-10-13|1995-08-26|1995-10-18|NONE|AIR|tegrate bl +10210|124653|4654|6|4|6710.60|0.04|0.03|N|O|1995-07-11|1995-08-21|1995-07-12|NONE|MAIL|nding patterns sleep excuses. regular +10210|33382|5886|7|10|13153.80|0.09|0.00|N|O|1995-07-02|1995-07-27|1995-08-01|COLLECT COD|TRUCK| even accounts ar +10211|46990|9495|1|44|85227.56|0.09|0.06|N|O|1997-10-07|1997-09-11|1997-10-22|DELIVER IN PERSON|TRUCK|ng the carefully unusual deposits +10211|144633|7148|2|21|35230.23|0.04|0.07|N|O|1997-10-24|1997-09-24|1997-11-07|NONE|MAIL| are throughout the carefully +10211|39834|7344|3|15|26607.45|0.03|0.03|N|O|1997-11-26|1997-08-30|1997-12-20|NONE|RAIL|furiously fi +10211|78504|3519|4|28|41510.00|0.08|0.07|N|O|1997-10-12|1997-10-19|1997-11-09|TAKE BACK RETURN|SHIP|cuses. carefully brave req +10211|8985|6486|5|42|79547.16|0.08|0.02|N|O|1997-10-30|1997-10-02|1997-11-08|DELIVER IN PERSON|AIR|ithely express theodolites. bli +10212|128144|657|1|23|26959.22|0.09|0.03|A|F|1993-08-09|1993-08-10|1993-08-19|TAKE BACK RETURN|MAIL| haggle blithely. final, bold +10212|107983|3004|2|40|79639.20|0.01|0.00|A|F|1993-08-17|1993-08-18|1993-08-18|COLLECT COD|AIR|slowly final pack +10212|53595|8606|3|46|71235.14|0.06|0.00|A|F|1993-07-06|1993-07-06|1993-07-12|NONE|MAIL|counts sleep. final asymptotes are sl +10213|151567|4083|1|4|6474.24|0.00|0.02|A|F|1995-03-15|1995-03-24|1995-04-12|DELIVER IN PERSON|MAIL|tes. unusual requests cajole care +10213|182090|9645|2|9|10548.81|0.10|0.08|N|F|1995-06-14|1995-04-24|1995-07-01|NONE|REG AIR|uctions boost slyly about the flu +10213|182839|394|3|13|24983.79|0.03|0.01|N|F|1995-05-28|1995-03-22|1995-06-22|TAKE BACK RETURN|MAIL|into beans. blithe deposits wake carefully +10214|36646|9150|1|22|34818.08|0.02|0.02|N|O|1996-03-08|1996-04-09|1996-04-03|DELIVER IN PERSON|REG AIR|ove the frets cajo +10214|94680|9699|2|5|8373.40|0.01|0.03|N|O|1996-03-20|1996-04-15|1996-04-09|TAKE BACK RETURN|RAIL| regular, express sheaves cajole fluf +10214|77129|2144|3|40|44244.80|0.01|0.06|N|O|1996-04-16|1996-04-17|1996-04-22|NONE|REG AIR|xpress accounts cajo +10214|92033|2034|4|20|20500.60|0.04|0.08|N|O|1996-03-15|1996-03-04|1996-04-10|TAKE BACK RETURN|RAIL|ructions. carefully close +10215|160337|338|1|1|1397.33|0.00|0.05|N|O|1996-11-18|1996-11-07|1996-11-29|COLLECT COD|SHIP|c accounts boost carefu +10215|168207|5756|2|30|38256.00|0.05|0.02|N|O|1996-10-13|1996-11-15|1996-10-27|TAKE BACK RETURN|FOB|are. stealthily r +10215|51618|1619|3|17|26683.37|0.10|0.00|N|O|1996-08-31|1996-10-10|1996-09-26|DELIVER IN PERSON|MAIL|ly special foxes among the +10215|140940|3455|4|9|17828.46|0.02|0.02|N|O|1996-11-27|1996-09-19|1996-12-05|COLLECT COD|AIR|furiously among the slyl +10215|163480|8513|5|47|72543.56|0.04|0.08|N|O|1996-11-21|1996-10-07|1996-12-11|NONE|SHIP|sly unusual requests boost +10240|35204|211|1|33|37593.60|0.02|0.02|A|F|1994-08-01|1994-06-19|1994-08-06|COLLECT COD|FOB|express asymptote +10241|41555|9068|1|27|40406.85|0.06|0.02|N|O|1997-12-01|1997-12-06|1997-12-22|DELIVER IN PERSON|TRUCK|ckly unusual foxes ha +10241|8903|6404|2|20|36238.00|0.02|0.05|N|O|1997-10-21|1997-10-30|1997-11-11|TAKE BACK RETURN|TRUCK| the ironic +10242|32317|7324|1|44|54969.64|0.00|0.03|R|F|1994-02-01|1994-02-02|1994-02-02|COLLECT COD|RAIL| dependencies boost furiously among +10242|144308|4309|2|8|10818.40|0.10|0.00|R|F|1994-03-02|1994-03-11|1994-03-14|TAKE BACK RETURN|RAIL|ronic instructions. instructions on the fin +10242|169321|9322|3|3|4170.96|0.05|0.05|A|F|1994-04-03|1994-03-10|1994-04-27|TAKE BACK RETURN|SHIP|e stealthily i +10242|163966|8999|4|30|60898.80|0.01|0.01|R|F|1993-12-16|1994-02-18|1994-01-08|TAKE BACK RETURN|FOB|ve slyly. blithely even +10242|173971|6489|5|9|18404.73|0.03|0.07|A|F|1994-03-23|1994-03-04|1994-04-05|TAKE BACK RETURN|AIR|tructions h +10242|130108|7648|6|23|26176.30|0.07|0.05|A|F|1994-01-26|1994-02-02|1994-02-19|DELIVER IN PERSON|REG AIR|lites nag blithely. iron +10242|115797|3331|7|32|58009.28|0.02|0.06|A|F|1994-03-29|1994-01-25|1994-04-03|COLLECT COD|SHIP|ithely. blithel +10243|185080|117|1|40|46603.20|0.01|0.04|N|O|1996-04-21|1996-02-01|1996-04-25|DELIVER IN PERSON|RAIL| accounts integrate carefully ca +10244|5308|309|1|19|23052.70|0.10|0.02|N|O|1996-04-22|1996-06-11|1996-05-11|COLLECT COD|AIR|e carefully special dependencies. depos +10244|2328|9829|2|48|59055.36|0.07|0.05|N|O|1996-07-22|1996-05-09|1996-07-24|TAKE BACK RETURN|SHIP| regular deposits +10244|112559|7582|3|21|33002.55|0.05|0.01|N|O|1996-07-29|1996-06-03|1996-08-16|DELIVER IN PERSON|FOB|across the slyly special acc +10244|178991|6543|4|28|57959.72|0.01|0.04|N|O|1996-08-02|1996-05-26|1996-08-09|TAKE BACK RETURN|REG AIR|s alongside of the ir +10245|128622|8623|1|49|80880.38|0.08|0.02|R|F|1995-03-18|1995-03-21|1995-04-17|TAKE BACK RETURN|SHIP|ag furiously. fur +10245|144321|9350|2|5|6826.60|0.06|0.01|A|F|1995-05-06|1995-05-07|1995-05-14|TAKE BACK RETURN|FOB|ins. final packages sublate never +10245|190134|135|3|2|2448.26|0.02|0.05|R|F|1995-04-17|1995-04-09|1995-05-10|DELIVER IN PERSON|REG AIR|riously dar +10245|171121|3639|4|50|59606.00|0.06|0.03|R|F|1995-04-08|1995-04-25|1995-04-21|TAKE BACK RETURN|AIR|ding to the blithely regula +10245|22532|39|5|39|56726.67|0.04|0.01|R|F|1995-03-08|1995-04-12|1995-03-19|NONE|SHIP|s final accounts sleep blithely regular ins +10245|84930|4931|6|48|91916.64|0.06|0.00|A|F|1995-03-22|1995-04-06|1995-04-10|DELIVER IN PERSON|TRUCK|t the stea +10245|10633|8137|7|4|6174.52|0.01|0.01|R|F|1995-03-23|1995-03-19|1995-04-02|NONE|SHIP|posits. idly unu +10246|99563|7091|1|50|78128.00|0.07|0.02|N|O|1997-10-04|1997-09-07|1997-10-15|COLLECT COD|SHIP|eodolites. blithel +10246|153129|3130|2|13|15367.56|0.10|0.06|N|O|1997-08-24|1997-07-21|1997-09-03|NONE|AIR| haggle blithely pending pinto b +10246|24370|1877|3|11|14238.07|0.09|0.04|N|O|1997-09-11|1997-09-01|1997-10-03|NONE|REG AIR|y stealthy tithes. special, regular in +10246|173520|6038|4|42|66927.84|0.06|0.06|N|O|1997-08-08|1997-08-10|1997-08-21|COLLECT COD|REG AIR|iously special dependencies kindle? fur +10247|61583|6596|1|13|20079.54|0.01|0.01|A|F|1993-01-25|1993-03-28|1993-02-23|COLLECT COD|REG AIR|instructions. pinto beans hagg +10247|19854|9855|2|42|74501.70|0.09|0.08|A|F|1993-02-12|1993-03-13|1993-03-02|COLLECT COD|SHIP|t deposits grow slyly along the fi +10247|79131|1639|3|45|49955.85|0.08|0.04|R|F|1993-02-06|1993-03-12|1993-02-12|DELIVER IN PERSON|MAIL|ges maintain furiously even pinto bea +10247|140246|247|4|2|2572.48|0.06|0.07|A|F|1993-03-07|1993-04-03|1993-03-27|DELIVER IN PERSON|SHIP|press pinto beans print furiously +10247|105942|8453|5|42|81813.48|0.04|0.04|A|F|1993-03-31|1993-04-11|1993-04-21|TAKE BACK RETURN|TRUCK|y pending pinto beans: +10247|158858|6404|6|5|9584.25|0.06|0.01|A|F|1993-02-22|1993-02-25|1993-02-27|DELIVER IN PERSON|FOB|ilent foxe +10272|15512|5513|1|34|48535.34|0.03|0.04|R|F|1994-03-12|1994-04-07|1994-03-27|NONE|TRUCK|lent requests. packages boost agai +10272|93604|3605|2|46|73489.60|0.03|0.06|R|F|1994-02-02|1994-04-16|1994-02-22|DELIVER IN PERSON|TRUCK|ly bold excus +10272|195440|5441|3|14|21496.16|0.06|0.04|A|F|1994-03-01|1994-02-20|1994-03-27|COLLECT COD|SHIP|s boost slyly even theodolites. carefully f +10272|158123|639|4|16|18897.92|0.00|0.07|R|F|1994-02-08|1994-04-10|1994-03-09|NONE|REG AIR|ic asymptotes cajole among the +10272|157794|2825|5|35|64812.65|0.05|0.07|R|F|1994-02-13|1994-02-22|1994-02-14|NONE|RAIL|luffily final inst +10272|37579|2586|6|18|27298.26|0.04|0.07|A|F|1994-04-27|1994-03-08|1994-05-01|TAKE BACK RETURN|FOB|l foxes nag +10272|179164|6716|7|32|39781.12|0.02|0.01|A|F|1994-05-11|1994-04-12|1994-05-23|DELIVER IN PERSON|RAIL| across th +10273|196991|9511|1|21|43847.79|0.06|0.06|N|O|1998-06-29|1998-07-15|1998-07-07|COLLECT COD|REG AIR|y unusual platelets are quickly final pint +10273|22731|2732|2|50|82686.50|0.05|0.03|N|O|1998-07-08|1998-07-03|1998-07-27|COLLECT COD|SHIP|. carefully stealthy ideas a +10273|30224|7734|3|47|54248.34|0.03|0.00|N|O|1998-07-09|1998-07-11|1998-07-21|COLLECT COD|FOB|pecial packages among th +10273|164952|2501|4|23|46389.85|0.02|0.01|N|O|1998-05-30|1998-06-09|1998-06-06|TAKE BACK RETURN|FOB|along the regular, unusual requests. fl +10273|131756|6783|5|33|58995.75|0.02|0.06|N|O|1998-07-09|1998-06-10|1998-07-29|DELIVER IN PERSON|FOB|ole bold, bold th +10273|15138|141|6|49|51603.37|0.10|0.00|N|O|1998-06-18|1998-06-11|1998-07-17|DELIVER IN PERSON|TRUCK|es. furiously final dolphins wake furiousl +10274|25373|7876|1|26|33757.62|0.04|0.03|R|F|1993-12-17|1994-01-09|1994-01-01|TAKE BACK RETURN|MAIL|dencies haggle. furiously even packa +10274|34146|9153|2|17|18362.38|0.03|0.03|R|F|1994-03-27|1994-02-03|1994-04-15|TAKE BACK RETURN|SHIP| furiously p +10275|170630|631|1|12|20407.56|0.00|0.01|N|O|1997-08-31|1997-08-14|1997-09-17|DELIVER IN PERSON|AIR|ts use alongside of the g +10275|167379|2412|2|36|52069.32|0.02|0.06|N|O|1997-07-12|1997-08-08|1997-07-24|TAKE BACK RETURN|TRUCK|he slyly regular depo +10276|123917|1454|1|39|75695.49|0.09|0.03|N|O|1996-06-24|1996-04-15|1996-07-14|DELIVER IN PERSON|SHIP|s cajole. regula +10276|61733|4240|2|45|76262.85|0.03|0.08|N|O|1996-06-21|1996-04-16|1996-07-17|COLLECT COD|SHIP| even requests haggle. even, +10276|141623|6652|3|29|48273.98|0.06|0.03|N|O|1996-05-25|1996-05-07|1996-05-27|NONE|TRUCK|ses breach. final ideas are carefully +10276|48615|3624|4|43|67235.23|0.09|0.06|N|O|1996-05-31|1996-04-22|1996-06-18|COLLECT COD|RAIL|y express depths mold slyly regular +10276|55774|785|5|40|69190.80|0.09|0.07|N|O|1996-04-13|1996-04-01|1996-05-10|DELIVER IN PERSON|SHIP| bold platelets. stealthy r +10277|127499|2524|1|12|18317.88|0.07|0.07|A|F|1994-07-27|1994-05-22|1994-08-11|NONE|RAIL| according to the furiously silent th +10277|68298|8299|2|8|10130.32|0.04|0.07|R|F|1994-04-25|1994-06-14|1994-05-11|COLLECT COD|SHIP|ing asymptotes unwind s +10277|81031|1032|3|45|45541.35|0.10|0.05|A|F|1994-06-25|1994-06-26|1994-07-01|NONE|AIR|ual deposits. deposits nag to the blith +10277|79269|6791|4|21|26213.46|0.00|0.06|R|F|1994-08-07|1994-06-20|1994-08-18|NONE|FOB|cajole. blithely careful ideas dete +10277|68772|3785|5|1|1740.77|0.05|0.08|R|F|1994-07-21|1994-06-04|1994-08-05|COLLECT COD|RAIL| ironic instructions. q +10278|179582|9583|1|34|56493.72|0.07|0.01|N|O|1995-11-02|1995-12-10|1995-11-06|DELIVER IN PERSON|AIR|kly even packages above the furiou +10278|28842|8843|2|28|49583.52|0.04|0.06|N|O|1995-12-01|1995-12-06|1995-12-15|COLLECT COD|AIR|e the special instruction +10278|131390|6417|3|21|29849.19|0.05|0.02|N|O|1995-10-19|1995-10-14|1995-11-12|TAKE BACK RETURN|TRUCK|requests. regular +10278|60199|2706|4|36|41730.84|0.10|0.01|N|O|1995-09-24|1995-11-21|1995-10-06|NONE|FOB|nts against t +10279|144465|4466|1|29|43774.34|0.07|0.00|N|O|1996-10-22|1996-12-13|1996-11-17|COLLECT COD|FOB|r the blith +10279|18141|643|2|29|30715.06|0.01|0.00|N|O|1996-11-18|1996-10-22|1996-11-22|TAKE BACK RETURN|MAIL|ronic accounts. carefully regular +10279|91595|4105|3|47|74569.73|0.00|0.01|N|O|1996-11-16|1996-11-19|1996-12-10|COLLECT COD|FOB|dolites cajole carefu +10279|35179|2689|4|15|16712.55|0.01|0.05|N|O|1997-01-02|1996-11-05|1997-01-11|COLLECT COD|MAIL|ully carefully special reques +10279|41687|1688|5|42|68404.56|0.06|0.05|N|O|1997-01-18|1996-11-14|1997-02-07|DELIVER IN PERSON|FOB|ithely close +10304|2004|7005|1|20|18120.00|0.07|0.05|N|O|1996-02-13|1996-01-28|1996-03-07|COLLECT COD|SHIP|ges across th +10304|76716|1731|2|35|59244.85|0.05|0.02|N|O|1996-01-18|1996-01-19|1996-02-02|COLLECT COD|SHIP|ep furiously above the pending de +10304|150547|3063|3|40|63901.60|0.09|0.04|N|O|1995-11-17|1995-12-23|1995-12-06|NONE|SHIP|ding to the pending pack +10304|42662|5167|4|3|4813.98|0.04|0.08|N|O|1996-01-14|1996-01-23|1996-02-10|NONE|REG AIR|express sauternes +10304|19855|2357|5|36|63894.60|0.05|0.08|N|O|1995-11-30|1996-01-14|1995-12-16|NONE|AIR|fter the quickly +10304|86901|6902|6|43|81179.70|0.01|0.03|N|O|1996-01-29|1995-12-27|1996-02-26|COLLECT COD|REG AIR| quickly blithely regul +10304|130962|963|7|43|85697.28|0.06|0.07|N|O|1996-02-20|1996-02-06|1996-03-13|DELIVER IN PERSON|SHIP| to the caref +10305|70906|907|1|36|67568.40|0.01|0.08|R|F|1994-08-13|1994-09-09|1994-08-29|TAKE BACK RETURN|TRUCK|s detect blithely final packages +10305|106709|1730|2|1|1715.70|0.08|0.06|A|F|1994-10-14|1994-09-18|1994-10-30|TAKE BACK RETURN|RAIL|g to the slyly unusual deposits. furio +10305|55965|8471|3|40|76838.40|0.09|0.07|A|F|1994-09-18|1994-09-26|1994-09-23|DELIVER IN PERSON|AIR|never special +10305|198192|8193|4|17|21933.23|0.02|0.02|A|F|1994-08-11|1994-09-17|1994-09-07|NONE|FOB|en deposits boost. pinto beans pr +10305|199499|9500|5|1|1598.49|0.08|0.05|A|F|1994-08-05|1994-09-23|1994-09-02|DELIVER IN PERSON|RAIL|to the slyly final de +10306|120901|902|1|8|15375.20|0.04|0.02|A|F|1993-07-26|1993-09-21|1993-08-12|TAKE BACK RETURN|TRUCK|es use slyly slyly ironic accounts. qui +10306|178441|3476|2|18|27349.92|0.03|0.05|R|F|1993-10-22|1993-08-27|1993-10-29|TAKE BACK RETURN|AIR|uests cajole fluffily-- re +10306|55738|3254|3|36|60974.28|0.05|0.04|A|F|1993-10-21|1993-08-24|1993-10-27|COLLECT COD|FOB|final theodolites wake blithel +10307|48865|3874|1|40|72554.40|0.02|0.00|N|O|1998-05-26|1998-04-28|1998-06-10|DELIVER IN PERSON|TRUCK|ully express +10307|57897|7898|2|50|92744.50|0.03|0.05|N|O|1998-02-18|1998-03-21|1998-02-27|DELIVER IN PERSON|MAIL|e furiously p +10307|68067|3080|3|30|31051.80|0.00|0.05|N|O|1998-04-22|1998-04-01|1998-04-24|DELIVER IN PERSON|REG AIR| regular deposits are a +10307|186346|8865|4|29|41537.86|0.08|0.06|N|O|1998-03-10|1998-04-28|1998-04-02|COLLECT COD|SHIP|oze. furiously express the +10307|114221|9244|5|1|1235.22|0.02|0.08|N|O|1998-04-26|1998-03-23|1998-05-10|NONE|TRUCK| beans haggl +10308|8745|6246|1|49|81033.26|0.06|0.07|A|F|1995-05-09|1995-06-27|1995-05-30|TAKE BACK RETURN|REG AIR|arly regular requests. even, pendi +10308|162143|2144|2|27|32538.78|0.06|0.02|N|O|1995-06-27|1995-06-30|1995-07-05|DELIVER IN PERSON|RAIL|ronic instructions above the blithe +10308|124798|9823|3|4|7291.16|0.04|0.08|R|F|1995-05-08|1995-06-04|1995-05-29|COLLECT COD|SHIP|iously regular pinto beans detect quickly +10308|73373|3374|4|41|55201.17|0.04|0.05|N|O|1995-07-25|1995-07-15|1995-08-03|DELIVER IN PERSON|FOB|ing to the final, even packages. e +10308|178125|5677|5|42|50531.04|0.08|0.05|N|O|1995-08-04|1995-06-30|1995-08-13|NONE|AIR|ests haggle carefully pen +10308|140149|5178|6|39|46376.46|0.04|0.02|R|F|1995-05-07|1995-07-20|1995-05-16|NONE|MAIL|ents. forges nag slyly. furiousl +10309|69383|6902|1|20|27047.60|0.10|0.00|R|F|1995-01-18|1995-02-08|1995-01-27|COLLECT COD|MAIL|ges cajole alongside of the furiously +10309|107294|2315|2|30|39038.70|0.01|0.01|A|F|1995-02-22|1995-01-19|1995-03-19|COLLECT COD|AIR|regular foxes. p +10309|84432|1957|3|19|26912.17|0.01|0.03|A|F|1995-01-23|1994-12-22|1995-02-03|NONE|FOB|the slyly final excuse +10309|46686|6687|4|12|19592.16|0.06|0.04|R|F|1995-01-11|1995-01-20|1995-01-19|NONE|SHIP|uffily special requests. +10309|43828|1341|5|47|83275.54|0.04|0.05|R|F|1994-12-30|1995-01-19|1995-01-15|NONE|TRUCK|nal pinto beans nag among the quick +10309|12563|7566|6|44|64924.64|0.04|0.03|A|F|1994-12-06|1994-12-26|1994-12-14|DELIVER IN PERSON|REG AIR|lly regular ideas against the blithely p +10310|20104|105|1|36|36867.60|0.08|0.07|A|F|1994-03-09|1994-04-08|1994-03-21|DELIVER IN PERSON|AIR|telets. sly +10310|84926|9943|2|33|63060.36|0.09|0.07|R|F|1994-03-24|1994-03-14|1994-03-29|COLLECT COD|TRUCK|fully special deposits run +10310|142833|376|3|7|13130.81|0.08|0.02|R|F|1994-04-03|1994-03-31|1994-04-06|DELIVER IN PERSON|MAIL|lyly final ideas. +10310|187705|2742|4|50|89635.00|0.01|0.08|R|F|1994-02-19|1994-05-07|1994-03-21|TAKE BACK RETURN|REG AIR|e furiously regular deposits. regular, +10310|144222|9251|5|12|15194.64|0.10|0.01|R|F|1994-06-04|1994-03-29|1994-07-04|NONE|AIR|thely. even packag +10311|96413|8923|1|3|4228.23|0.09|0.02|R|F|1992-11-12|1992-09-18|1992-11-27|TAKE BACK RETURN|TRUCK|even requests haggle +10336|53149|5655|1|16|17634.24|0.10|0.05|N|O|1997-07-09|1997-08-11|1997-07-18|NONE|RAIL|sleep blithely. deposits detect +10336|60665|666|2|24|39015.84|0.08|0.08|N|O|1997-06-16|1997-09-04|1997-07-08|DELIVER IN PERSON|REG AIR|ly furiously unusual deposi +10337|103491|3492|1|7|10461.43|0.06|0.08|N|O|1996-04-22|1996-05-13|1996-05-18|DELIVER IN PERSON|FOB|carefully specia +10337|156582|1613|2|9|14747.22|0.04|0.02|N|O|1996-07-02|1996-06-03|1996-07-20|NONE|REG AIR|ully bold packages! carefully slow +10337|67157|9664|3|4|4496.60|0.01|0.07|N|O|1996-05-24|1996-06-05|1996-05-30|NONE|MAIL|ly unusual depe +10337|92334|4844|4|20|26526.60|0.03|0.04|N|O|1996-05-09|1996-06-06|1996-05-28|DELIVER IN PERSON|AIR|s are across the fluffily regular deposi +10338|39907|9908|1|2|3693.80|0.05|0.06|N|O|1995-08-01|1995-09-02|1995-08-07|DELIVER IN PERSON|AIR| deposits integrate slyly slyly unusual i +10338|115167|2701|2|6|7092.96|0.08|0.08|N|O|1995-08-12|1995-09-08|1995-08-13|TAKE BACK RETURN|REG AIR|dle pinto beans. slyly even pinto beans +10338|10580|8084|3|38|56642.04|0.01|0.07|N|O|1995-09-09|1995-09-01|1995-09-12|COLLECT COD|AIR|. enticing ideas lose about t +10338|11253|1254|4|4|4657.00|0.07|0.06|N|O|1995-09-01|1995-08-20|1995-09-27|NONE|MAIL|its. dependencies hinder. +10338|124791|2328|5|2|3631.58|0.09|0.07|N|O|1995-09-09|1995-08-27|1995-09-21|NONE|MAIL| blithely regu +10338|157969|3000|6|30|60808.80|0.06|0.07|N|O|1995-11-01|1995-08-14|1995-11-13|NONE|RAIL| requests +10339|86310|8819|1|20|25926.20|0.06|0.00|N|O|1996-02-05|1995-12-19|1996-03-01|TAKE BACK RETURN|TRUCK|ages are blithely around the asym +10339|10288|5291|2|48|57517.44|0.07|0.05|N|O|1996-01-24|1995-12-02|1996-02-04|NONE|FOB|ular theodolites haggle. furiousl +10339|96807|9317|3|19|34272.20|0.00|0.01|N|O|1995-12-25|1996-01-10|1996-01-24|DELIVER IN PERSON|MAIL|odolites. slyly ir +10340|4996|7497|1|47|89346.53|0.06|0.05|N|O|1995-09-08|1995-08-11|1995-09-24|COLLECT COD|TRUCK|riously even platelets hagg +10340|163951|6468|2|37|74553.15|0.00|0.05|N|O|1995-07-15|1995-08-07|1995-08-10|DELIVER IN PERSON|SHIP|aggle carefully regular ideas. slyly +10340|114048|6560|3|12|12744.48|0.09|0.04|N|O|1995-08-05|1995-09-16|1995-08-20|DELIVER IN PERSON|SHIP|accounts boost against the caref +10340|2318|2319|4|19|23185.89|0.01|0.01|N|O|1995-08-08|1995-08-11|1995-08-18|NONE|AIR|blithely ironic +10340|156320|1351|5|27|37160.64|0.01|0.01|N|O|1995-07-04|1995-07-30|1995-07-14|DELIVER IN PERSON|MAIL|cajole against the +10340|63819|8832|6|43|76660.83|0.01|0.08|N|O|1995-09-16|1995-08-30|1995-09-23|NONE|RAIL|! carefully special pint +10341|37919|2926|1|8|14855.28|0.09|0.07|R|F|1993-03-22|1993-01-30|1993-04-20|TAKE BACK RETURN|AIR|l dependencie +10341|96568|6569|2|41|64146.96|0.09|0.00|R|F|1993-03-02|1993-02-17|1993-03-11|COLLECT COD|FOB|posits. carefully regular deposits cajole f +10341|2594|5095|3|47|70339.73|0.06|0.04|A|F|1993-01-31|1993-01-31|1993-02-16|NONE|FOB|ix boldly instructions. daringl +10341|183238|5757|4|43|56812.89|0.00|0.04|R|F|1993-01-13|1993-02-17|1993-02-09|COLLECT COD|SHIP|press packages believe above the +10341|78018|8019|5|21|20916.21|0.00|0.05|R|F|1993-01-19|1993-01-21|1993-01-27|COLLECT COD|FOB|fully quickly unusual accounts. furiously +10341|41112|6121|6|11|11584.21|0.08|0.06|A|F|1993-02-02|1993-03-16|1993-02-16|DELIVER IN PERSON|RAIL| dependencies are stealthily ab +10342|156257|8773|1|19|24951.75|0.02|0.04|N|O|1996-01-05|1996-01-10|1996-01-14|NONE|TRUCK|ag slyly. packages across th +10342|197714|5272|2|50|90585.50|0.06|0.05|N|O|1995-12-12|1996-02-10|1995-12-27|TAKE BACK RETURN|TRUCK| pending ideas alo +10342|172166|9718|3|8|9905.28|0.10|0.00|N|O|1996-01-14|1995-12-25|1996-01-27|COLLECT COD|AIR|gular foxes past the +10342|183172|8209|4|41|51461.97|0.04|0.06|N|O|1996-02-03|1996-02-09|1996-02-10|TAKE BACK RETURN|TRUCK|en deposit +10342|159057|9058|5|42|46874.10|0.00|0.02|N|O|1996-01-15|1996-01-04|1996-02-05|TAKE BACK RETURN|AIR|close packages slee +10342|62620|5127|6|3|4747.86|0.08|0.00|N|O|1996-02-20|1996-01-16|1996-03-19|COLLECT COD|MAIL|n instructions are furiously caref +10343|79215|1723|1|27|32243.67|0.08|0.05|A|F|1992-03-31|1992-05-20|1992-04-06|NONE|AIR|es. carefully stealthy requests +10368|159990|5021|1|43|88149.57|0.04|0.04|N|O|1996-07-24|1996-08-11|1996-08-02|COLLECT COD|SHIP| special grouches wake furiously along th +10369|125673|8186|1|43|73042.81|0.01|0.04|N|O|1996-03-06|1996-01-15|1996-03-26|DELIVER IN PERSON|TRUCK|sts nag carefully. carefully even pear +10369|177561|2596|2|45|73735.20|0.08|0.00|N|O|1995-11-17|1995-12-16|1995-11-24|DELIVER IN PERSON|REG AIR|about the special, unusual multipli +10370|137603|2630|1|35|57421.00|0.07|0.01|A|F|1994-07-26|1994-06-16|1994-08-06|DELIVER IN PERSON|REG AIR|eans haggle slyly slyly regular i +10370|84057|9074|2|41|42683.05|0.05|0.04|A|F|1994-08-17|1994-06-02|1994-09-14|NONE|REG AIR|ual accounts. quickly special pinto beans b +10371|44835|4836|1|24|42715.92|0.09|0.00|A|F|1994-11-21|1994-12-06|1994-12-08|NONE|REG AIR| quickly bold pinto beans. regular platelet +10371|139703|2217|2|43|74936.10|0.08|0.05|A|F|1994-09-21|1994-10-17|1994-10-01|DELIVER IN PERSON|AIR|eposits pr +10371|185281|7800|3|50|68314.00|0.00|0.02|A|F|1994-12-05|1994-12-04|1994-12-11|DELIVER IN PERSON|MAIL|gular deposits. +10371|3771|3772|4|35|58616.95|0.09|0.06|A|F|1994-10-19|1994-11-15|1994-10-30|DELIVER IN PERSON|SHIP|ly bold ideas haggle. blithe +10372|58506|1012|1|50|73225.00|0.03|0.04|N|O|1995-07-11|1995-09-24|1995-07-21|DELIVER IN PERSON|REG AIR|gular foxes. express +10372|100866|8397|2|30|56005.80|0.03|0.02|N|O|1995-10-23|1995-08-04|1995-10-24|NONE|SHIP|sits. blithely regular asymptotes boost bl +10373|125226|251|1|45|56304.90|0.01|0.06|A|F|1993-08-10|1993-08-10|1993-09-01|NONE|FOB|ironic packages sleep +10373|63988|3989|2|45|87839.10|0.04|0.06|R|F|1993-09-04|1993-09-19|1993-09-12|TAKE BACK RETURN|AIR| slyly near the pending packages-- ironic +10373|36047|6048|3|12|11796.48|0.09|0.05|A|F|1993-10-16|1993-07-31|1993-11-03|NONE|RAIL|d hockey p +10373|28570|8571|4|3|4495.71|0.00|0.08|A|F|1993-10-18|1993-08-19|1993-11-02|TAKE BACK RETURN|MAIL|final requests. regular, regular theo +10373|162620|7653|5|48|80765.76|0.01|0.05|A|F|1993-10-16|1993-09-22|1993-10-22|NONE|SHIP|s requests. furiously final reque +10373|145459|3002|6|25|37611.25|0.02|0.06|R|F|1993-08-14|1993-09-02|1993-08-20|NONE|SHIP|uriously about t +10374|153565|8596|1|19|30752.64|0.00|0.04|A|F|1993-11-09|1993-09-24|1993-11-16|DELIVER IN PERSON|RAIL|. even requ +10375|77849|357|1|7|12787.88|0.00|0.03|N|O|1997-04-10|1997-03-10|1997-04-18|TAKE BACK RETURN|TRUCK|nding pinto beans wake. deposits above +10375|5827|3328|2|23|39854.86|0.06|0.05|N|O|1997-02-08|1997-03-20|1997-02-20|TAKE BACK RETURN|TRUCK|ly regular deposits sleep care +10375|119573|7107|3|21|33443.97|0.05|0.01|N|O|1997-03-16|1997-03-10|1997-04-09|TAKE BACK RETURN|AIR| requests. dep +10400|145989|8504|1|50|101749.00|0.07|0.04|N|O|1996-11-07|1996-11-27|1996-11-19|NONE|REG AIR|al platelets play carefully even +10400|33500|8507|2|27|38704.50|0.00|0.03|N|O|1996-12-23|1997-01-17|1997-01-13|NONE|REG AIR|ial packages boost furiou +10400|31910|9420|3|3|5525.73|0.03|0.04|N|O|1997-01-08|1997-01-16|1997-02-02|NONE|MAIL|oxes. slyly bold accounts use. carefull +10400|105847|868|4|48|88936.32|0.03|0.08|N|O|1997-02-01|1996-12-12|1997-02-15|DELIVER IN PERSON|RAIL|ow fluffily quickly ironic i +10400|159407|6953|5|20|29328.00|0.07|0.04|N|O|1996-11-08|1996-12-19|1996-11-18|DELIVER IN PERSON|TRUCK|ironic deposits along the blithely fina +10400|141502|1503|6|27|41674.50|0.08|0.03|N|O|1996-11-26|1997-01-22|1996-12-09|TAKE BACK RETURN|AIR|ounts. blithely bold packages detect bli +10401|142093|2094|1|1|1135.09|0.08|0.04|N|O|1998-08-30|1998-09-14|1998-09-23|NONE|SHIP|ar deposits. bold, express excuses are alo +10401|153432|5948|2|10|14854.30|0.07|0.04|N|O|1998-09-04|1998-10-08|1998-09-28|TAKE BACK RETURN|REG AIR|ve the final, +10402|53661|1177|1|38|61357.08|0.07|0.07|N|O|1998-04-04|1998-02-09|1998-04-19|COLLECT COD|TRUCK|l, regular requests integrate. dog +10402|64514|7021|2|10|14785.10|0.01|0.02|N|O|1997-12-21|1998-01-20|1997-12-27|COLLECT COD|MAIL|efully final packages. slyly e +10403|178924|6476|1|29|58084.68|0.10|0.02|N|O|1996-08-10|1996-07-30|1996-09-03|NONE|FOB|ake fluffily. requ +10403|173289|3290|2|47|64027.16|0.02|0.08|N|O|1996-06-06|1996-06-29|1996-06-08|COLLECT COD|AIR|ideas thrash aga +10403|57245|7246|3|26|31258.24|0.10|0.07|N|O|1996-09-11|1996-07-22|1996-09-15|TAKE BACK RETURN|FOB|fully among the carefully even depe +10403|115251|7763|4|24|30390.00|0.07|0.02|N|O|1996-09-03|1996-08-19|1996-09-22|TAKE BACK RETURN|TRUCK|y unusual f +10403|8747|6248|5|29|48016.46|0.07|0.05|N|O|1996-06-27|1996-06-23|1996-07-12|COLLECT COD|RAIL|g slyly pending deposits. fu +10403|337|5338|6|21|25983.93|0.07|0.02|N|O|1996-07-12|1996-07-18|1996-07-16|COLLECT COD|FOB|usly across t +10403|55512|523|7|29|42557.79|0.09|0.04|N|O|1996-06-28|1996-07-31|1996-07-20|COLLECT COD|REG AIR|onic deposits cajole carefu +10404|178467|985|1|35|54091.10|0.08|0.01|N|O|1998-06-12|1998-05-14|1998-06-15|NONE|MAIL|efully express deposits sl +10404|82499|2500|2|9|13333.41|0.03|0.08|N|O|1998-04-13|1998-05-05|1998-04-21|NONE|TRUCK|ial deposits. asymptotes detect. quick +10404|150821|822|3|49|91719.18|0.02|0.02|N|O|1998-04-20|1998-05-13|1998-04-22|DELIVER IN PERSON|SHIP|thely unusual acc +10404|46294|8799|4|6|7441.74|0.07|0.04|N|O|1998-06-27|1998-06-13|1998-07-02|COLLECT COD|AIR|he carefully regular theodolit +10405|134957|9984|1|25|49798.75|0.08|0.07|N|O|1998-01-31|1998-03-02|1998-02-25|DELIVER IN PERSON|MAIL|deposits. platel +10405|10667|668|2|14|22087.24|0.01|0.02|N|O|1998-05-01|1998-03-17|1998-05-10|NONE|REG AIR|thely ironic d +10405|68342|5861|3|37|48482.58|0.06|0.00|N|O|1998-02-28|1998-02-25|1998-03-27|TAKE BACK RETURN|REG AIR|ges according to the regular depos +10405|9267|4268|4|22|25877.72|0.08|0.05|N|O|1998-04-01|1998-03-13|1998-04-28|TAKE BACK RETURN|TRUCK|thely even +10405|138918|6458|5|27|52836.57|0.07|0.08|N|O|1998-04-19|1998-03-08|1998-05-07|NONE|MAIL|taphs haggle quick +10406|130929|8469|1|23|45078.16|0.01|0.06|N|O|1996-06-12|1996-05-23|1996-07-11|NONE|RAIL|uests cajole fluffily +10406|112911|2912|2|41|78880.31|0.09|0.05|N|O|1996-04-25|1996-05-20|1996-04-26|NONE|AIR|ual account +10406|83336|3337|3|41|54092.53|0.10|0.00|N|O|1996-04-27|1996-04-27|1996-05-20|COLLECT COD|MAIL| beans. ev +10406|14430|4431|4|10|13444.30|0.06|0.00|N|O|1996-05-04|1996-04-16|1996-05-15|DELIVER IN PERSON|SHIP| packages nag enticingly +10407|33001|5505|1|9|8406.00|0.10|0.04|N|O|1996-05-30|1996-04-25|1996-06-05|DELIVER IN PERSON|TRUCK| ideas kindle slyly abo +10407|38956|6466|2|10|18949.50|0.01|0.03|N|O|1996-07-18|1996-05-25|1996-07-27|COLLECT COD|AIR|ess deposits +10407|118454|5988|3|20|29449.00|0.00|0.00|N|O|1996-05-13|1996-05-05|1996-06-05|DELIVER IN PERSON|TRUCK|ously ironic foxes. carefully +10407|43275|5780|4|12|14619.24|0.06|0.00|N|O|1996-04-06|1996-05-09|1996-05-04|NONE|REG AIR|g the final, even accounts. regular acc +10407|108468|3489|5|10|14764.60|0.06|0.08|N|O|1996-06-08|1996-05-21|1996-06-10|NONE|RAIL|arefully even +10407|20726|3229|6|2|3293.44|0.04|0.02|N|O|1996-04-19|1996-05-18|1996-05-19|TAKE BACK RETURN|REG AIR|nding requests. carefully ironic +10432|170454|5489|1|40|60978.00|0.06|0.05|R|F|1992-03-04|1992-02-10|1992-03-18|COLLECT COD|REG AIR|ly even requ +10432|5363|7864|2|46|58344.56|0.00|0.02|A|F|1992-04-29|1992-03-19|1992-05-03|COLLECT COD|SHIP|efully express requests wake blithe +10432|129153|9154|3|26|30735.90|0.05|0.07|A|F|1992-04-23|1992-03-08|1992-04-26|NONE|REG AIR|after the ironic, unusual ideas cajo +10432|64660|2179|4|18|29243.88|0.06|0.07|A|F|1992-01-27|1992-03-19|1992-02-06|NONE|FOB| ironic ideas. +10433|126788|1813|1|16|29036.48|0.05|0.08|A|F|1993-05-09|1993-04-10|1993-05-29|COLLECT COD|REG AIR|he unusual theodolites. furiously iro +10434|152202|2203|1|6|7525.20|0.02|0.07|R|F|1995-02-11|1995-03-17|1995-03-12|DELIVER IN PERSON|SHIP|uests. packages integrate +10434|46437|6438|2|42|58104.06|0.09|0.04|R|F|1995-03-27|1995-02-24|1995-04-25|DELIVER IN PERSON|TRUCK|es the unusual platelets are furiou +10435|49276|9277|1|39|47785.53|0.08|0.03|R|F|1993-08-23|1993-11-04|1993-08-27|DELIVER IN PERSON|AIR|usly pending requests +10435|170131|132|2|9|10810.17|0.10|0.06|R|F|1993-12-05|1993-09-19|1993-12-10|TAKE BACK RETURN|SHIP|ily regular pack +10435|179479|4514|3|4|6233.88|0.05|0.05|R|F|1993-08-25|1993-09-14|1993-08-26|TAKE BACK RETURN|TRUCK|osits affix furiously +10435|95698|717|4|25|42342.25|0.04|0.01|A|F|1993-10-29|1993-10-23|1993-10-31|NONE|MAIL|, unusual deposits. ruthless +10435|193436|994|5|19|29059.17|0.00|0.05|A|F|1993-08-27|1993-10-30|1993-09-25|DELIVER IN PERSON|MAIL|regular theodolites mold along the asymp +10435|66083|6084|6|20|20981.60|0.03|0.06|A|F|1993-09-23|1993-10-07|1993-10-15|TAKE BACK RETURN|AIR|s. carefully regular +10436|119696|2208|1|31|53186.39|0.09|0.05|A|F|1995-04-26|1995-03-11|1995-05-07|TAKE BACK RETURN|MAIL|thely ironic packages. silent account +10437|88256|5781|1|13|16175.25|0.09|0.01|A|F|1994-08-24|1994-09-20|1994-09-17|NONE|TRUCK|. busy requests sleep carefully en +10437|116442|6443|2|27|39377.88|0.02|0.03|A|F|1994-11-04|1994-11-07|1994-11-25|DELIVER IN PERSON|TRUCK|telets thrash carefull +10437|35786|8290|3|11|18939.58|0.03|0.05|A|F|1994-10-08|1994-11-16|1994-10-27|DELIVER IN PERSON|REG AIR|e ideas believe slyly after the fluffil +10438|197774|5332|1|46|86101.42|0.09|0.03|A|F|1993-02-05|1993-03-01|1993-02-06|DELIVER IN PERSON|RAIL|n dependencies grow along the furiously e +10438|170937|938|2|34|68269.62|0.03|0.04|A|F|1992-12-12|1993-02-17|1992-12-26|TAKE BACK RETURN|MAIL|nal, even deposits wake +10438|135851|3391|3|15|28302.75|0.02|0.00|A|F|1993-02-12|1993-03-02|1993-02-27|TAKE BACK RETURN|AIR|ular requests boos +10438|38975|8976|4|27|51677.19|0.06|0.07|R|F|1993-01-27|1993-01-15|1993-02-15|DELIVER IN PERSON|AIR|packages affix blithely along +10439|16078|3582|1|32|31810.24|0.08|0.04|R|F|1992-05-20|1992-06-23|1992-06-13|DELIVER IN PERSON|FOB|cajole furiously after the slyly un +10439|12108|9612|2|27|27542.70|0.05|0.03|R|F|1992-06-29|1992-05-06|1992-07-10|NONE|MAIL|rding to the +10439|89835|7360|3|49|89416.67|0.00|0.00|A|F|1992-04-13|1992-06-03|1992-04-16|COLLECT COD|FOB|nal accounts +10439|53666|3667|4|15|24294.90|0.09|0.03|A|F|1992-04-06|1992-06-13|1992-05-04|COLLECT COD|FOB|ly across the reg +10439|159551|9552|5|30|48316.50|0.05|0.04|R|F|1992-06-05|1992-06-01|1992-06-13|NONE|REG AIR|ly final acco +10439|159732|7278|6|33|59127.09|0.00|0.03|R|F|1992-06-06|1992-05-08|1992-06-20|DELIVER IN PERSON|FOB|n dependenci +10439|199792|4831|7|20|37835.80|0.04|0.01|R|F|1992-06-02|1992-04-29|1992-06-27|NONE|AIR|e express, ironic accou +10464|101451|6472|1|47|68265.15|0.06|0.03|R|F|1994-08-21|1994-10-19|1994-09-01|TAKE BACK RETURN|AIR|luffily unusual requests along the caref +10465|151174|1175|1|16|19602.72|0.00|0.05|N|O|1997-04-20|1997-05-20|1997-05-15|COLLECT COD|REG AIR|ourts. pending +10465|177226|2261|2|21|27367.62|0.06|0.02|N|O|1997-05-06|1997-05-23|1997-05-23|TAKE BACK RETURN|FOB|regular foxes mold sl +10465|33903|8910|3|1|1836.90|0.00|0.03|N|O|1997-04-23|1997-05-13|1997-05-08|TAKE BACK RETURN|RAIL|eep furiously after the fur +10465|194519|9558|4|47|75834.97|0.07|0.03|N|O|1997-08-02|1997-06-16|1997-08-14|NONE|SHIP|ly unusual accounts. iro +10465|77826|5348|5|49|88387.18|0.10|0.03|N|O|1997-07-07|1997-05-21|1997-07-09|COLLECT COD|MAIL|e blithely about the furiously unusual +10465|6209|6210|6|49|54644.80|0.06|0.08|N|O|1997-07-22|1997-05-29|1997-08-03|TAKE BACK RETURN|MAIL|c pinto beans. slyly unusual +10465|147495|2524|7|17|26222.33|0.04|0.04|N|O|1997-05-30|1997-07-09|1997-06-13|COLLECT COD|TRUCK|out the flu +10466|137134|7135|1|44|51529.72|0.08|0.02|R|F|1993-03-13|1993-02-25|1993-04-07|COLLECT COD|SHIP|es. brave accounts wake furiou +10466|195816|8336|2|15|28677.15|0.00|0.08|A|F|1993-01-18|1993-02-17|1993-02-02|NONE|REG AIR|rate furiously steal +10466|65411|2930|3|42|57809.22|0.06|0.06|A|F|1993-02-25|1993-03-01|1993-03-21|TAKE BACK RETURN|AIR|even foxes nag slyly according to the +10467|112703|2704|1|36|61765.20|0.00|0.05|N|O|1997-06-30|1997-05-17|1997-07-07|COLLECT COD|MAIL|ly regular ideas. carefull +10467|189929|2448|2|16|32302.72|0.03|0.01|N|O|1997-07-04|1997-05-07|1997-07-31|TAKE BACK RETURN|RAIL| carefully. blithely even excuses haggle. +10467|133778|1318|3|26|47106.02|0.08|0.05|N|O|1997-05-13|1997-05-15|1997-05-19|NONE|AIR|s use. ideas above +10467|199672|4711|4|28|49606.76|0.01|0.02|N|O|1997-03-28|1997-05-08|1997-04-22|COLLECT COD|RAIL|al accounts +10467|76301|3823|5|3|3831.90|0.07|0.03|N|O|1997-06-04|1997-04-22|1997-06-08|NONE|REG AIR|t foxes. package +10467|180962|5999|6|20|40859.20|0.10|0.02|N|O|1997-05-07|1997-05-09|1997-05-18|DELIVER IN PERSON|RAIL|usly slyly re +10467|22338|9845|7|11|13863.63|0.07|0.05|N|O|1997-04-26|1997-05-20|1997-05-16|NONE|RAIL|jole blithely ironic instructions. blith +10468|34701|7205|1|6|9814.20|0.02|0.00|A|F|1995-02-28|1995-03-05|1995-03-02|DELIVER IN PERSON|FOB|, ironic pack +10468|19519|9520|2|39|56101.89|0.00|0.02|R|F|1994-12-26|1995-03-06|1994-12-31|COLLECT COD|REG AIR|against the fluffily pending foxe +10469|73648|8663|1|26|42162.64|0.08|0.00|N|O|1996-12-20|1996-10-21|1996-12-27|DELIVER IN PERSON|FOB|ronic ideas arou +10469|1273|6274|2|1|1174.27|0.02|0.06|N|O|1996-09-18|1996-10-05|1996-09-27|TAKE BACK RETURN|SHIP|ronic, final accounts use car +10469|179442|9443|3|28|42600.32|0.01|0.06|N|O|1996-10-10|1996-11-03|1996-10-21|TAKE BACK RETURN|RAIL|accounts. furiously +10470|169517|7066|1|48|76152.48|0.07|0.04|R|F|1992-08-01|1992-07-05|1992-08-02|DELIVER IN PERSON|SHIP|ven accounts. regular, reg +10470|71961|4469|2|46|88916.16|0.08|0.03|R|F|1992-08-16|1992-06-11|1992-08-23|DELIVER IN PERSON|MAIL| deposits. pending, final inst +10470|45499|5500|3|50|72224.50|0.05|0.08|R|F|1992-07-18|1992-06-06|1992-07-28|NONE|RAIL|heodolites. blithely regular accounts a +10470|98456|8457|4|41|59632.45|0.00|0.01|R|F|1992-06-19|1992-06-16|1992-07-12|TAKE BACK RETURN|SHIP| integrate carefully slyly +10470|143007|5522|5|21|22050.00|0.05|0.07|R|F|1992-06-11|1992-07-12|1992-06-23|DELIVER IN PERSON|REG AIR|regular theodolites sleep? furiously re +10470|111619|1620|6|1|1630.61|0.06|0.05|R|F|1992-07-18|1992-06-28|1992-08-01|TAKE BACK RETURN|MAIL|e above the stealthy, final instru +10471|24317|4318|1|46|57100.26|0.08|0.01|R|F|1993-01-21|1992-12-24|1993-02-17|TAKE BACK RETURN|MAIL|ages. slyly bold platelet +10471|91198|3708|2|35|41621.65|0.02|0.05|A|F|1992-10-11|1992-12-09|1992-11-08|DELIVER IN PERSON|TRUCK|deas sleep furio +10471|164223|4224|3|8|10297.76|0.06|0.01|A|F|1992-12-10|1992-12-23|1992-12-26|DELIVER IN PERSON|REG AIR| packages impress slyly about the carefully +10471|82438|7455|4|35|49715.05|0.09|0.00|R|F|1992-10-17|1993-01-03|1992-11-07|COLLECT COD|SHIP|lent deposits. carefully final pa +10471|124323|1860|5|39|52545.48|0.04|0.05|R|F|1992-12-05|1992-11-11|1992-12-25|COLLECT COD|FOB|packages. quickly s +10471|81539|4048|6|48|72985.44|0.03|0.05|A|F|1992-11-28|1992-12-13|1992-12-16|DELIVER IN PERSON|SHIP|hely special deposits. package +10496|10232|5235|1|8|9137.84|0.08|0.01|N|O|1997-03-26|1997-04-11|1997-04-22|NONE|REG AIR|the express, final requests. furiously ex +10496|168660|1177|2|37|63960.42|0.00|0.01|N|O|1997-05-06|1997-05-01|1997-05-30|TAKE BACK RETURN|RAIL|fter the final courts. final, pend +10497|39416|6926|1|10|13554.10|0.08|0.06|N|O|1996-09-11|1996-09-14|1996-09-13|NONE|AIR|y regular packages along the fluf +10497|53773|6279|2|29|50076.33|0.05|0.03|N|O|1996-08-01|1996-09-19|1996-08-25|TAKE BACK RETURN|FOB|even deposits boost slyly about the bold, +10497|147098|9613|3|36|41223.24|0.07|0.08|N|O|1996-09-13|1996-08-12|1996-09-27|COLLECT COD|MAIL|ges. furiousl +10498|113921|3922|1|3|5804.76|0.00|0.07|A|F|1993-11-01|1993-12-23|1993-11-10|DELIVER IN PERSON|REG AIR|ronic accounts wake quickly +10498|69678|7197|2|34|56020.78|0.03|0.00|A|F|1994-02-16|1993-12-09|1994-02-19|COLLECT COD|REG AIR|ously bold +10498|71970|6985|3|31|60201.07|0.08|0.05|A|F|1994-01-21|1993-11-30|1994-02-07|NONE|REG AIR|tegrate never fin +10498|196032|8552|4|25|28200.75|0.09|0.00|A|F|1994-01-07|1993-11-27|1994-01-08|DELIVER IN PERSON|FOB|leep blithely after the regul +10499|17534|36|1|12|17418.36|0.00|0.08|R|F|1994-03-08|1994-02-02|1994-04-04|TAKE BACK RETURN|SHIP|t pinto beans. quic +10499|85307|7816|2|32|41353.60|0.05|0.07|R|F|1993-12-20|1994-01-22|1994-01-17|NONE|RAIL|r packages alongside of the regular +10499|147347|7348|3|30|41830.20|0.09|0.04|R|F|1994-01-27|1994-02-14|1994-02-11|NONE|RAIL|le fluffily among the blithely +10499|48187|8188|4|39|44272.02|0.09|0.06|R|F|1994-02-28|1994-02-11|1994-03-26|NONE|REG AIR|eans. quickly ironic +10499|69508|9509|5|2|2955.00|0.03|0.00|R|F|1994-03-14|1994-01-04|1994-04-09|DELIVER IN PERSON|FOB|ke blithely regular ideas. accoun +10499|7483|9984|6|21|29200.08|0.01|0.04|R|F|1994-02-19|1993-12-28|1994-03-07|COLLECT COD|SHIP|brave requests. blithely unusual +10500|72565|87|1|16|24600.96|0.00|0.03|R|F|1994-04-14|1994-03-10|1994-04-19|COLLECT COD|REG AIR|y. frets according to the +10501|170006|7558|1|12|12912.00|0.02|0.04|N|O|1998-09-28|1998-09-24|1998-10-08|NONE|RAIL|ckages. slyly even theodolites are bold i +10501|83012|8029|2|40|39800.40|0.04|0.03|N|O|1998-07-24|1998-08-06|1998-08-01|NONE|FOB|ular requests cajole. ironic ideas +10501|179005|6557|3|43|46612.00|0.01|0.03|N|O|1998-07-27|1998-09-26|1998-08-23|NONE|REG AIR|lyly bold theodolites sleep carefully f +10501|133448|988|4|22|32591.68|0.00|0.04|N|O|1998-09-25|1998-08-20|1998-10-10|COLLECT COD|FOB|gged package +10501|46215|8720|5|11|12773.31|0.06|0.02|N|O|1998-10-28|1998-09-06|1998-11-21|TAKE BACK RETURN|AIR|lly even dependencies. busy deposits hagg +10501|124284|4285|6|21|27473.88|0.09|0.03|N|O|1998-09-18|1998-08-22|1998-10-01|COLLECT COD|REG AIR|refully ironic platelets hag +10502|177508|5060|1|50|79275.00|0.01|0.00|A|F|1993-05-20|1993-06-25|1993-05-22|COLLECT COD|FOB|ents could have to +10502|166630|9147|2|48|81438.24|0.09|0.01|A|F|1993-06-11|1993-08-01|1993-06-12|TAKE BACK RETURN|MAIL|egular requests. bold +10502|146999|7000|3|8|16367.92|0.10|0.04|R|F|1993-08-30|1993-06-23|1993-09-19|TAKE BACK RETURN|REG AIR|dolphins. b +10502|3600|6101|4|17|25561.20|0.09|0.04|R|F|1993-09-02|1993-06-16|1993-09-26|DELIVER IN PERSON|MAIL|ecial orbits boost +10503|9137|9138|1|28|29291.64|0.07|0.06|N|O|1996-09-15|1996-08-07|1996-09-26|TAKE BACK RETURN|AIR|packages wake never packages. quickly ir +10503|149991|5020|2|12|24491.88|0.04|0.01|N|O|1996-09-07|1996-07-15|1996-09-18|DELIVER IN PERSON|RAIL|fully slow pinto beans. slyly slow theodol +10503|84275|1800|3|45|56667.15|0.03|0.04|N|O|1996-08-08|1996-07-15|1996-08-29|NONE|TRUCK|y final packa +10503|4452|1953|4|28|37980.60|0.01|0.07|N|O|1996-06-23|1996-07-25|1996-07-17|DELIVER IN PERSON|RAIL|haggle final dependencies? fluffily regular +10528|84490|6999|1|45|66352.05|0.09|0.02|A|F|1995-01-07|1994-10-20|1995-01-22|NONE|FOB|y. quickly sly accounts wake after the bo +10528|18491|8492|2|4|5637.96|0.02|0.08|A|F|1994-10-20|1994-12-07|1994-11-12|NONE|MAIL|ly final accou +10528|169905|9906|3|18|35548.20|0.06|0.03|R|F|1994-10-02|1994-10-28|1994-10-06|TAKE BACK RETURN|SHIP|ily. pending, unusual requests +10528|178783|6335|4|13|24203.14|0.08|0.07|R|F|1994-10-11|1994-11-18|1994-10-28|NONE|AIR|onic accounts. blithely even accounts are f +10529|101055|8586|1|37|39073.85|0.01|0.08|N|O|1997-10-28|1998-01-16|1997-11-12|COLLECT COD|SHIP|e furiously express accounts. slowl +10529|26917|4424|2|41|75600.31|0.01|0.04|N|O|1998-01-10|1997-12-29|1998-01-21|TAKE BACK RETURN|MAIL|onic forges +10529|186513|6514|3|31|49584.81|0.05|0.08|N|O|1998-01-15|1997-12-13|1998-02-05|DELIVER IN PERSON|AIR|uriously even depo +10530|198910|6468|1|20|40178.20|0.06|0.00|A|F|1994-03-03|1994-03-20|1994-03-06|NONE|TRUCK|lly regular deposits wake al +10530|80120|2629|2|28|30803.36|0.05|0.04|R|F|1994-04-30|1994-03-16|1994-05-14|COLLECT COD|RAIL|press requests. un +10530|166123|6124|3|25|29728.00|0.07|0.04|R|F|1994-04-10|1994-03-24|1994-04-29|DELIVER IN PERSON|REG AIR|blithely a +10531|70447|2955|1|24|34018.56|0.08|0.00|R|F|1992-03-21|1992-05-29|1992-04-10|COLLECT COD|RAIL| lose fluffily slyly express asymptotes +10531|2494|2495|2|14|19550.86|0.09|0.07|A|F|1992-03-27|1992-04-19|1992-04-10|DELIVER IN PERSON|RAIL|al instructions +10531|109619|9620|3|40|65144.40|0.08|0.07|R|F|1992-04-20|1992-04-29|1992-04-26|COLLECT COD|REG AIR| quickly ironic requests. regular pac +10531|163865|8898|4|25|48221.50|0.09|0.05|A|F|1992-07-16|1992-05-18|1992-08-10|COLLECT COD|REG AIR|nently. sheaves +10531|78835|3850|5|2|3627.66|0.00|0.02|A|F|1992-04-14|1992-04-26|1992-04-23|NONE|RAIL|eodolites above the carefully +10531|165961|3510|6|2|4053.92|0.00|0.00|A|F|1992-05-25|1992-05-16|1992-06-06|DELIVER IN PERSON|SHIP|. carefully sly ideas use furiously pe +10531|92246|9774|7|24|29717.76|0.00|0.04|R|F|1992-04-02|1992-05-30|1992-04-09|NONE|TRUCK|regular asymptotes. blithely +10532|177057|9575|1|25|28351.25|0.00|0.01|N|O|1997-12-30|1998-01-26|1998-01-13|DELIVER IN PERSON|SHIP|g deposits are furiously: carefully +10532|182074|7111|2|15|17341.05|0.00|0.07|N|O|1998-03-26|1997-12-30|1998-04-25|NONE|SHIP| special deposits +10532|108204|3225|3|26|31517.20|0.02|0.02|N|O|1998-01-05|1998-02-02|1998-01-23|DELIVER IN PERSON|AIR|xpress deposits. forges are regularly a +10532|170166|2684|4|44|54391.04|0.03|0.07|N|O|1998-03-14|1998-01-08|1998-03-29|NONE|REG AIR|blithely idle account +10532|168858|1375|5|23|44317.55|0.10|0.05|N|O|1998-01-25|1998-01-13|1998-01-30|DELIVER IN PERSON|REG AIR|cajole. always final de +10532|185602|8121|6|50|84380.00|0.05|0.00|N|O|1998-01-08|1998-01-04|1998-01-26|COLLECT COD|SHIP|endencies cajole. slow asymptot +10532|12313|2314|7|30|36759.30|0.05|0.07|N|O|1997-12-24|1998-02-19|1998-01-14|COLLECT COD|REG AIR|e slyly bold packages. furiously u +10533|139838|2352|1|16|30045.28|0.04|0.06|N|O|1998-08-02|1998-07-16|1998-08-21|TAKE BACK RETURN|MAIL|quests haggle quickly. carefully express +10533|52052|2053|2|16|16064.80|0.00|0.06|N|O|1998-07-07|1998-06-29|1998-07-09|NONE|FOB| across the carefully silent a +10533|35349|7853|3|46|59079.64|0.02|0.07|N|O|1998-08-10|1998-06-15|1998-08-31|COLLECT COD|FOB|thely regular +10533|101856|1857|4|42|78029.70|0.05|0.04|N|O|1998-07-13|1998-07-14|1998-07-31|COLLECT COD|FOB|encies maintain careful +10533|81300|8825|5|27|34595.10|0.09|0.00|N|O|1998-07-18|1998-06-29|1998-08-11|DELIVER IN PERSON|MAIL|tly regular +10534|155376|407|1|3|4294.11|0.05|0.07|R|F|1993-07-13|1993-07-16|1993-08-06|COLLECT COD|MAIL|counts are regular +10535|74247|4248|1|2|2442.48|0.00|0.04|N|O|1995-06-29|1995-08-08|1995-07-21|NONE|REG AIR|unusual in +10535|68405|8406|2|30|41202.00|0.01|0.07|N|O|1995-07-29|1995-07-15|1995-08-03|DELIVER IN PERSON|REG AIR|usly final excuses nod. blithely +10535|72786|308|3|33|58039.74|0.09|0.01|N|O|1995-07-29|1995-07-30|1995-08-18|TAKE BACK RETURN|REG AIR|carefully even excuses against t +10535|103719|3720|4|22|37899.62|0.02|0.03|N|O|1995-09-22|1995-07-01|1995-09-27|NONE|FOB|e carefully final ideas kindle +10535|191146|8704|5|40|49485.60|0.00|0.03|N|O|1995-09-04|1995-08-14|1995-09-11|TAKE BACK RETURN|RAIL|y ironic asymptotes should sleep after +10535|185224|5225|6|20|26184.40|0.01|0.04|N|O|1995-09-02|1995-08-15|1995-09-15|DELIVER IN PERSON|MAIL|d packages haggle f +10535|44607|9616|7|11|17067.60|0.01|0.01|N|O|1995-07-09|1995-07-27|1995-07-20|COLLECT COD|RAIL|even asymptotes bo +10560|101574|9105|1|8|12604.56|0.08|0.00|N|O|1997-10-08|1997-10-19|1997-10-31|DELIVER IN PERSON|MAIL| slyly final ideas sleep +10560|138597|3624|2|49|80143.91|0.07|0.06|N|O|1997-11-27|1997-09-07|1997-12-25|DELIVER IN PERSON|AIR|ously bold sauternes boost among the fin +10560|197713|7714|3|8|14485.68|0.04|0.07|N|O|1997-08-08|1997-10-24|1997-09-04|NONE|MAIL|ss the blithely unusual foxes snooze +10560|156618|9134|4|18|30142.98|0.10|0.06|N|O|1997-08-07|1997-10-17|1997-08-15|TAKE BACK RETURN|RAIL|nding asymptotes boost fluffily alo +10560|70202|7724|5|6|7033.20|0.01|0.07|N|O|1997-10-08|1997-10-02|1997-10-09|TAKE BACK RETURN|REG AIR|. carefully even +10560|73524|8539|6|38|56905.76|0.03|0.01|N|O|1997-10-05|1997-08-29|1997-11-02|DELIVER IN PERSON|SHIP|hinly final instruct +10560|108268|3289|7|5|6381.30|0.10|0.04|N|O|1997-10-03|1997-09-07|1997-10-12|NONE|MAIL|s requests are carefully final re +10561|55067|5068|1|30|30661.80|0.02|0.08|N|O|1997-06-18|1997-07-08|1997-06-22|COLLECT COD|SHIP|es. blithely pe +10561|94896|7406|2|25|47272.25|0.09|0.00|N|O|1997-07-24|1997-06-18|1997-07-29|TAKE BACK RETURN|FOB|riously. express, final theodolites +10561|102092|9623|3|44|48139.96|0.08|0.05|N|O|1997-05-16|1997-06-26|1997-06-12|COLLECT COD|RAIL| above the ironic asymptotes. +10561|43981|1494|4|30|57749.40|0.01|0.04|N|O|1997-07-28|1997-07-26|1997-08-18|NONE|AIR|y against the deposits. carefully fin +10561|173609|1161|5|31|52160.60|0.08|0.08|N|O|1997-06-06|1997-06-13|1997-06-30|NONE|TRUCK|se slyly. s +10562|143546|3547|1|37|58812.98|0.06|0.07|R|F|1994-12-21|1995-01-08|1995-01-12|COLLECT COD|FOB|ickly final packages cajole +10562|164233|9266|2|37|47997.51|0.05|0.04|R|F|1994-12-12|1995-01-07|1994-12-24|NONE|RAIL|regular pinto beans +10562|59124|9125|3|25|27078.00|0.09|0.02|R|F|1995-03-05|1995-01-18|1995-03-07|COLLECT COD|REG AIR| ironic instruction +10562|95120|139|4|13|14496.56|0.06|0.04|R|F|1995-02-05|1995-01-23|1995-02-26|TAKE BACK RETURN|SHIP|es boost across th +10562|76172|8680|5|46|52815.82|0.03|0.02|R|F|1995-03-06|1994-12-22|1995-03-17|TAKE BACK RETURN|TRUCK|es haggle ruthlessly. ca +10562|11713|6716|6|8|12997.68|0.10|0.00|A|F|1995-01-17|1995-01-10|1995-02-09|DELIVER IN PERSON|TRUCK|bold deposits. +10562|56831|1842|7|34|60786.22|0.02|0.02|A|F|1995-02-19|1995-01-30|1995-02-20|NONE|SHIP|carefully careful packages wake fluffily a +10563|147459|5002|1|12|18077.40|0.06|0.01|R|F|1994-01-04|1993-11-14|1994-02-01|DELIVER IN PERSON|SHIP|ithely unusual packages cajole blithe +10563|136884|6885|2|35|67230.80|0.10|0.06|R|F|1993-11-15|1993-12-21|1993-12-09|COLLECT COD|RAIL|equests inte +10563|199924|7482|3|46|93100.32|0.05|0.00|A|F|1993-11-11|1993-11-05|1993-11-18|COLLECT COD|MAIL|quests. bli +10563|110741|742|4|46|80580.04|0.07|0.07|R|F|1994-01-10|1993-11-02|1994-01-17|DELIVER IN PERSON|RAIL|quickly ironic asymptotes wake according +10564|161233|3750|1|13|16824.99|0.06|0.06|N|O|1996-03-31|1996-04-20|1996-04-19|TAKE BACK RETURN|AIR| regular deposits +10564|40151|2656|2|23|25096.45|0.04|0.03|N|O|1996-05-03|1996-05-15|1996-05-09|DELIVER IN PERSON|TRUCK|egular accounts use +10564|8647|3648|3|25|38891.00|0.00|0.06|N|O|1996-06-19|1996-05-26|1996-07-02|NONE|MAIL|raids-- carefully f +10564|114370|9393|4|2|2768.74|0.02|0.05|N|O|1996-03-19|1996-04-27|1996-03-31|COLLECT COD|AIR|ents wake furi +10565|86664|6665|1|11|18157.26|0.03|0.03|N|O|1997-08-26|1997-10-21|1997-09-21|NONE|MAIL|uests lose about the quickly bold +10565|151832|9378|2|15|28257.45|0.07|0.04|N|O|1997-10-07|1997-11-04|1997-10-14|COLLECT COD|AIR|y pending accounts. packag +10565|39431|4438|3|31|42483.33|0.01|0.05|N|O|1997-10-30|1997-10-17|1997-11-13|DELIVER IN PERSON|AIR|to the caref +10565|115167|5168|4|27|31918.32|0.01|0.06|N|O|1997-11-21|1997-11-07|1997-12-18|COLLECT COD|MAIL|s run idly carefully +10565|3992|3993|5|27|51191.73|0.01|0.06|N|O|1997-09-23|1997-10-05|1997-10-08|DELIVER IN PERSON|REG AIR|ites are car +10566|66288|8795|1|44|55188.32|0.01|0.04|N|O|1995-10-25|1995-11-18|1995-11-14|TAKE BACK RETURN|MAIL|en instructions doubt past t +10566|91056|3566|2|1|1047.05|0.01|0.03|N|O|1995-10-03|1995-11-04|1995-10-31|NONE|RAIL|sual theodolites. slyly regula +10566|166467|4016|3|18|27602.28|0.10|0.00|N|O|1995-10-13|1995-09-30|1995-11-11|COLLECT COD|RAIL|ic dependencies. furiousl +10566|8130|631|4|36|37372.68|0.01|0.02|N|O|1995-10-18|1995-10-13|1995-11-11|NONE|SHIP| slyly pending depths impress slyly ab +10566|28488|3493|5|9|12748.32|0.00|0.04|N|O|1995-09-22|1995-10-21|1995-10-16|NONE|RAIL|deposits wake +10566|191002|3522|6|41|44813.00|0.06|0.08|N|O|1995-11-10|1995-09-29|1995-11-23|COLLECT COD|RAIL| carefully even deposits s +10567|147068|2097|1|37|41257.22|0.05|0.01|A|F|1992-05-05|1992-06-07|1992-05-06|NONE|REG AIR|e furiously regular warthogs: special +10567|166044|6045|2|9|9990.36|0.02|0.07|A|F|1992-05-01|1992-06-07|1992-05-29|COLLECT COD|TRUCK|out the qui +10567|98368|878|3|22|30059.92|0.05|0.05|A|F|1992-04-10|1992-05-16|1992-04-26|TAKE BACK RETURN|MAIL|e fluffily e +10592|183486|8523|1|41|64348.68|0.10|0.07|N|O|1996-01-08|1995-12-14|1996-02-06|TAKE BACK RETURN|AIR|ronic, final accounts. fl +10592|37757|261|2|12|20337.00|0.03|0.08|N|O|1995-12-02|1996-02-02|1995-12-19|NONE|TRUCK|e fluffily bold accounts. blithely eve +10593|137824|5364|1|10|18618.20|0.03|0.02|R|F|1992-05-24|1992-03-23|1992-06-12|DELIVER IN PERSON|SHIP|are bravely quickly bold depos +10593|192667|2668|2|7|12317.62|0.08|0.05|R|F|1992-05-10|1992-04-24|1992-05-22|COLLECT COD|AIR|p the slyl +10593|140212|2727|3|36|45079.56|0.08|0.08|A|F|1992-03-03|1992-03-22|1992-03-15|COLLECT COD|SHIP|endencies can +10593|128732|3757|4|36|63386.28|0.01|0.01|R|F|1992-05-13|1992-03-20|1992-06-01|DELIVER IN PERSON|AIR|refully. carefully final accounts run car +10593|183907|8944|5|23|45790.70|0.05|0.08|A|F|1992-04-09|1992-04-18|1992-04-17|DELIVER IN PERSON|SHIP|sts are bold, i +10593|120929|5954|6|5|9749.60|0.09|0.00|A|F|1992-05-14|1992-04-20|1992-05-20|TAKE BACK RETURN|MAIL|er the furiously ironic a +10594|44310|1823|1|5|6271.55|0.03|0.02|N|O|1996-05-03|1996-05-18|1996-05-10|NONE|TRUCK|al foxes. final ideas among the slyly s +10595|26458|3965|1|19|26304.55|0.01|0.06|N|O|1998-03-17|1998-01-30|1998-03-19|TAKE BACK RETURN|SHIP|wake carefully at t +10596|163071|5588|1|42|47630.94|0.10|0.03|N|O|1997-05-31|1997-06-04|1997-06-06|TAKE BACK RETURN|TRUCK| the packages. ev +10596|130885|8425|2|19|36401.72|0.09|0.00|N|O|1997-06-22|1997-05-04|1997-06-25|DELIVER IN PERSON|MAIL|ins boost above the fina +10596|179212|1730|3|15|19368.15|0.03|0.04|N|O|1997-05-02|1997-06-25|1997-05-20|TAKE BACK RETURN|SHIP|gle accord +10597|116175|6176|1|23|27396.91|0.07|0.08|N|O|1996-12-24|1996-10-28|1997-01-19|NONE|FOB|ly regular ideas ought to dazzle +10597|141365|1366|2|27|37971.72|0.01|0.07|N|O|1996-12-01|1996-10-22|1996-12-19|COLLECT COD|TRUCK|y carefully u +10597|108343|8344|3|6|8108.04|0.06|0.03|N|O|1996-09-24|1996-10-30|1996-10-03|DELIVER IN PERSON|AIR|iously final depths boost bold requests. d +10598|28544|3549|1|16|23560.64|0.03|0.05|R|F|1992-06-02|1992-04-07|1992-07-02|NONE|AIR|ructions. fluffily bold requests abo +10599|10655|8159|1|42|65757.30|0.02|0.07|N|O|1997-08-11|1997-08-26|1997-08-31|TAKE BACK RETURN|TRUCK|l packages near the pending, even re +10599|69140|9141|2|16|17746.24|0.00|0.04|N|O|1997-08-27|1997-09-19|1997-08-31|DELIVER IN PERSON|RAIL|blithely ironic theodolites use against the +10599|30560|5567|3|24|35773.44|0.00|0.06|N|O|1997-10-24|1997-09-22|1997-10-25|NONE|RAIL|s. quickly special dep +10599|18894|3897|4|40|72515.60|0.09|0.04|N|O|1997-07-30|1997-09-21|1997-08-13|COLLECT COD|SHIP| slyly regular packages. regular fra +10624|105112|133|1|23|25693.53|0.06|0.04|R|F|1995-02-09|1995-02-23|1995-03-09|COLLECT COD|AIR|thely regular requests nag furi +10624|11243|8747|2|46|53095.04|0.03|0.05|A|F|1995-03-13|1995-02-07|1995-03-20|COLLECT COD|AIR|inal packages after +10624|154730|7246|3|22|39264.06|0.02|0.05|A|F|1995-01-19|1995-03-08|1995-01-23|COLLECT COD|REG AIR|yly regular foxes boost d +10624|147063|7064|4|24|26641.44|0.10|0.07|A|F|1995-04-16|1995-02-19|1995-05-01|NONE|RAIL|e the ideas. carefully ironic p +10624|75349|2871|5|30|39730.20|0.09|0.05|A|F|1995-02-18|1995-03-07|1995-03-18|COLLECT COD|REG AIR|slyly alongside of the slyly +10624|185864|5865|6|7|13649.02|0.10|0.02|A|F|1994-12-24|1995-03-04|1995-01-07|TAKE BACK RETURN|TRUCK|beans. pending, regular +10625|88855|8856|1|20|36877.00|0.09|0.01|N|O|1996-02-14|1996-03-20|1996-03-06|TAKE BACK RETURN|AIR|o beans above the even, even ideas c +10625|180842|843|2|13|24996.92|0.03|0.00|N|O|1996-02-07|1996-03-24|1996-03-08|DELIVER IN PERSON|REG AIR| fluffily bold packages. fluf +10625|196134|8654|3|46|56585.98|0.03|0.01|N|O|1996-03-01|1996-03-27|1996-03-14|COLLECT COD|MAIL|s integrate furiousl +10625|11655|1656|4|7|10966.55|0.07|0.02|N|O|1996-02-15|1996-04-20|1996-03-12|COLLECT COD|MAIL|ly bold ideas wake fi +10625|81872|4381|5|12|22246.44|0.03|0.08|N|O|1996-02-02|1996-03-06|1996-02-19|COLLECT COD|MAIL|luffy packages. furiously bold +10625|11654|4156|6|12|18787.80|0.10|0.04|N|O|1996-02-15|1996-03-22|1996-02-28|TAKE BACK RETURN|SHIP|p along the +10625|61719|9238|7|35|58824.85|0.04|0.08|N|O|1996-03-20|1996-03-22|1996-04-11|NONE|AIR| above the furiously final deposits. de +10626|101850|1851|1|21|38888.85|0.04|0.03|N|O|1995-12-26|1996-01-28|1996-01-11|DELIVER IN PERSON|TRUCK|o the furious +10627|174246|1798|1|24|31685.76|0.01|0.03|R|F|1993-02-26|1993-04-30|1993-03-20|DELIVER IN PERSON|TRUCK|quickly bold forges. e +10627|147002|4545|2|27|28323.00|0.08|0.02|A|F|1993-03-16|1993-05-19|1993-03-29|DELIVER IN PERSON|MAIL|at the cou +10627|56397|1408|3|41|55488.99|0.06|0.02|R|F|1993-03-11|1993-05-18|1993-04-07|COLLECT COD|RAIL|sits unwind +10627|49844|4853|4|28|50227.52|0.01|0.08|A|F|1993-04-06|1993-04-10|1993-04-20|TAKE BACK RETURN|SHIP|e even pinto b +10627|120630|8167|5|35|57772.05|0.09|0.02|R|F|1993-04-08|1993-03-30|1993-05-06|DELIVER IN PERSON|RAIL|ily final theodolites sle +10628|48662|6175|1|4|6442.64|0.01|0.04|N|O|1998-08-16|1998-08-08|1998-09-08|COLLECT COD|REG AIR|regularly b +10629|110716|5739|1|24|41441.04|0.04|0.08|R|F|1994-11-03|1994-10-23|1994-11-16|TAKE BACK RETURN|SHIP|dogged requests. ir +10629|193362|3363|2|16|23285.76|0.00|0.02|A|F|1994-12-03|1994-11-23|1994-12-24|COLLECT COD|MAIL|ounts haggle bl +10630|144651|9680|1|29|49173.85|0.10|0.01|R|F|1993-04-23|1993-04-10|1993-05-11|NONE|AIR|deposits boo +10630|146897|6898|2|15|29158.35|0.10|0.00|R|F|1993-04-03|1993-04-23|1993-04-20|NONE|RAIL|y. slyly furious foxes ought to are bli +10630|84699|7208|3|37|62296.53|0.06|0.08|A|F|1993-03-04|1993-04-09|1993-03-26|NONE|TRUCK|l, special instruc +10630|130438|5465|4|20|29368.60|0.08|0.05|R|F|1993-05-16|1993-04-01|1993-06-02|DELIVER IN PERSON|FOB|ld platelets wake blithely after the +10631|75273|5274|1|45|56172.15|0.08|0.03|A|F|1993-07-24|1993-07-15|1993-08-08|NONE|MAIL| regular ideas s +10631|103443|8464|2|10|14464.40|0.05|0.02|A|F|1993-07-07|1993-07-29|1993-07-09|COLLECT COD|REG AIR|pliers boos +10631|154005|4006|3|36|38124.00|0.08|0.00|R|F|1993-08-16|1993-07-19|1993-09-14|NONE|AIR|ve the Tiresias integrate against the +10631|156366|8882|4|23|32714.28|0.09|0.01|R|F|1993-08-11|1993-07-25|1993-09-10|COLLECT COD|REG AIR|kly? fluffily final foxes wake b +10631|28875|8876|5|24|43292.88|0.08|0.01|A|F|1993-06-20|1993-08-09|1993-07-17|TAKE BACK RETURN|SHIP|ns use sly +10631|89379|4396|6|41|56103.17|0.02|0.02|A|F|1993-08-02|1993-07-07|1993-08-13|TAKE BACK RETURN|MAIL|ding, special theod +10656|198104|5662|1|47|56498.70|0.05|0.00|N|O|1995-11-06|1996-01-23|1995-11-16|NONE|TRUCK|o beans. furiously regular foxes +10656|118013|5547|2|11|11341.11|0.08|0.03|N|O|1995-12-02|1995-12-30|1995-12-10|TAKE BACK RETURN|SHIP|arefully regular deposits. even co +10656|31955|6962|3|1|1886.95|0.00|0.05|N|O|1995-12-27|1995-12-03|1996-01-07|DELIVER IN PERSON|RAIL|ck, unusual accounts. iron +10657|106396|3927|1|20|28047.80|0.03|0.04|A|F|1993-11-16|1993-12-09|1993-11-30|TAKE BACK RETURN|TRUCK|s. carefully silent courts arou +10657|192434|9992|2|29|44266.47|0.01|0.06|A|F|1993-11-12|1993-11-14|1993-12-06|NONE|AIR|gular accounts. ironic package +10657|37229|4739|3|13|15160.86|0.06|0.03|R|F|1993-12-01|1993-12-05|1993-12-07|TAKE BACK RETURN|TRUCK|lithely quickly brave request +10658|86342|1359|1|19|25238.46|0.09|0.00|R|F|1994-10-15|1994-10-05|1994-10-24|NONE|SHIP|osits cajole slyly around the bold dec +10658|136785|4325|2|2|3643.56|0.00|0.04|R|F|1994-12-01|1994-11-04|1994-12-30|NONE|FOB|totes sleep quickly over the carefu +10658|133198|3199|3|6|7387.14|0.01|0.08|R|F|1994-09-28|1994-10-19|1994-10-12|COLLECT COD|SHIP| sleep according to the fluffily ironic a +10658|55072|2588|4|2|2054.14|0.06|0.00|A|F|1994-12-02|1994-10-17|1994-12-14|COLLECT COD|TRUCK|de of the deposits. blithely busy asymptote +10658|186744|1781|5|3|5492.22|0.05|0.01|A|F|1994-11-17|1994-11-02|1994-11-22|TAKE BACK RETURN|TRUCK| requests use pending, final fr +10658|3266|3267|6|37|43262.62|0.06|0.08|A|F|1994-09-21|1994-09-30|1994-09-27|NONE|FOB| deposits. quickly reg +10658|76921|1936|7|21|39856.32|0.07|0.04|R|F|1994-12-06|1994-11-08|1994-12-15|COLLECT COD|AIR|theodolites us +10659|199827|7385|1|6|11560.92|0.08|0.06|R|F|1994-08-28|1994-07-12|1994-09-24|DELIVER IN PERSON|SHIP|slyly even re +10659|86957|1974|2|41|79701.95|0.10|0.00|R|F|1994-07-01|1994-06-16|1994-07-15|TAKE BACK RETURN|TRUCK| slyly final asymptotes +10659|77721|2736|3|26|44166.72|0.03|0.05|R|F|1994-05-19|1994-06-17|1994-06-01|TAKE BACK RETURN|MAIL| slyly. final, special accounts det +10659|49753|7266|4|15|25541.25|0.09|0.01|R|F|1994-08-14|1994-07-17|1994-08-23|DELIVER IN PERSON|SHIP|kages solve c +10659|184777|9814|5|41|76332.57|0.00|0.07|A|F|1994-08-21|1994-07-16|1994-09-19|NONE|AIR|rays across t +10659|145884|8399|6|49|94564.12|0.04|0.00|R|F|1994-08-10|1994-08-02|1994-09-08|COLLECT COD|MAIL|es believe alongside of the furi +10659|64008|4009|7|6|5832.00|0.00|0.06|R|F|1994-08-07|1994-07-09|1994-08-11|DELIVER IN PERSON|SHIP|s cajole. fluffily bold theodolites along +10660|179853|9854|1|49|94709.65|0.09|0.04|N|O|1998-08-22|1998-06-27|1998-09-07|TAKE BACK RETURN|SHIP|g furiously. carefully pending depo +10660|178373|5925|2|10|14513.70|0.05|0.03|N|O|1998-07-02|1998-07-14|1998-07-18|COLLECT COD|REG AIR|efully ruthles +10660|99940|7468|3|48|93117.12|0.10|0.02|N|O|1998-07-24|1998-06-28|1998-08-13|TAKE BACK RETURN|AIR|ilent requests. fu +10661|156228|6229|1|33|42379.26|0.09|0.01|R|F|1994-05-03|1994-03-08|1994-05-06|TAKE BACK RETURN|FOB|ly above the ne +10661|108975|1486|2|16|31743.52|0.00|0.08|R|F|1994-02-16|1994-03-17|1994-02-20|DELIVER IN PERSON|RAIL| regular packages. even, quiet +10661|126679|9192|3|27|46053.09|0.09|0.00|A|F|1994-01-27|1994-03-23|1994-02-08|COLLECT COD|REG AIR|ns. ironically fin +10662|46431|8936|1|4|5509.72|0.10|0.01|N|O|1995-07-15|1995-07-14|1995-07-24|TAKE BACK RETURN|AIR| accounts boost above the depos +10662|152860|5376|2|41|78427.26|0.03|0.04|N|O|1995-07-15|1995-06-26|1995-08-13|NONE|RAIL| regular pinto beans nag express the +10662|110535|3047|3|39|60275.67|0.01|0.02|A|F|1995-05-26|1995-07-07|1995-06-09|NONE|TRUCK|ackages. final packages do +10662|148822|8823|4|39|72961.98|0.07|0.06|R|F|1995-05-26|1995-06-26|1995-05-28|DELIVER IN PERSON|AIR|ss the blithely s +10663|7746|5247|1|27|44650.98|0.09|0.03|R|F|1994-06-09|1994-08-16|1994-07-08|DELIVER IN PERSON|AIR|se besides the regular pinto beans. slyly +10663|178586|6138|2|35|58260.30|0.07|0.01|R|F|1994-07-20|1994-07-21|1994-08-01|TAKE BACK RETURN|MAIL|ounts cajole stealthily agains +10663|90271|272|3|25|31531.75|0.10|0.00|A|F|1994-05-29|1994-07-05|1994-06-27|NONE|AIR|ajole furiously express asymptotes. care +10663|176069|1104|4|19|21756.14|0.00|0.04|A|F|1994-07-13|1994-07-29|1994-08-06|DELIVER IN PERSON|MAIL|c requests around the carefully +10688|45037|7542|1|16|15712.48|0.05|0.01|A|F|1992-06-19|1992-07-31|1992-07-06|TAKE BACK RETURN|AIR|ing instructions nag according t +10688|132574|2575|2|19|30524.83|0.09|0.07|R|F|1992-06-16|1992-06-27|1992-07-05|TAKE BACK RETURN|MAIL|to beans solve blithely quickly permane +10689|137029|2056|1|26|27716.52|0.08|0.08|N|O|1996-09-09|1996-08-25|1996-09-21|COLLECT COD|FOB|y. regular, busy requests us +10689|39420|4427|2|11|14953.62|0.09|0.07|N|O|1996-07-25|1996-10-17|1996-08-20|TAKE BACK RETURN|RAIL| furiously. pending depen +10689|128688|8689|3|47|80683.96|0.06|0.00|N|O|1996-08-15|1996-09-21|1996-09-02|TAKE BACK RETURN|REG AIR|uctions are. blithely speci +10690|150523|3039|1|14|22029.28|0.05|0.07|N|O|1997-12-19|1998-01-22|1997-12-31|NONE|REG AIR| fluffily regular deposits are +10690|34397|9404|2|27|35947.53|0.08|0.06|N|O|1998-01-06|1998-01-26|1998-01-23|DELIVER IN PERSON|MAIL|lent foxes wake busily. blith +10690|98521|1031|3|1|1519.52|0.00|0.05|N|O|1998-03-22|1998-02-21|1998-04-04|TAKE BACK RETURN|REG AIR|al accounts! fl +10691|154742|9773|1|10|17967.40|0.04|0.00|R|F|1995-04-11|1995-05-16|1995-05-10|DELIVER IN PERSON|MAIL|pecial deposits cajole +10691|148690|8691|2|18|31296.42|0.05|0.08|A|F|1995-05-14|1995-05-05|1995-06-06|TAKE BACK RETURN|MAIL|nal deposits sleep ir +10691|30770|5777|3|43|73133.11|0.10|0.02|R|F|1995-06-02|1995-05-16|1995-06-17|DELIVER IN PERSON|SHIP|c deposits. furiously expre +10692|187763|5318|1|1|1850.76|0.09|0.03|A|F|1994-08-27|1994-09-13|1994-09-13|NONE|REG AIR|kages. quickly ironic packages n +10692|131810|4324|2|3|5525.43|0.07|0.06|R|F|1994-10-04|1994-09-19|1994-10-09|DELIVER IN PERSON|AIR|he fluffy, unusual accounts. blithel +10692|123457|994|3|49|72542.05|0.03|0.06|A|F|1994-08-14|1994-09-08|1994-08-19|TAKE BACK RETURN|REG AIR|thely brave deposits sleep b +10692|130855|856|4|7|13200.95|0.07|0.01|A|F|1994-08-27|1994-10-13|1994-09-22|COLLECT COD|REG AIR|sits. carefully unusual requests coul +10692|72340|4848|5|28|36745.52|0.02|0.00|A|F|1994-08-06|1994-09-25|1994-08-30|DELIVER IN PERSON|TRUCK|ng ideas use +10692|18077|579|6|40|39802.80|0.05|0.05|A|F|1994-07-29|1994-08-30|1994-08-11|DELIVER IN PERSON|SHIP|yly careful pinto beans +10693|145215|244|1|35|44107.35|0.10|0.02|N|F|1995-06-15|1995-07-14|1995-07-10|COLLECT COD|FOB|ng the special accounts nag f +10694|180562|8117|1|19|31208.64|0.05|0.03|N|O|1998-01-22|1998-02-10|1998-01-28|TAKE BACK RETURN|TRUCK|e regular, express instruction +10694|100524|525|2|11|16769.72|0.08|0.03|N|O|1998-03-07|1998-02-26|1998-03-23|TAKE BACK RETURN|AIR|ully ironic notornis are ironic, special f +10694|90290|2800|3|32|40969.28|0.08|0.04|N|O|1997-12-24|1998-01-17|1998-01-19|COLLECT COD|AIR| blithely i +10694|89899|2408|4|15|28333.35|0.07|0.03|N|O|1997-12-25|1998-02-24|1998-01-06|TAKE BACK RETURN|REG AIR| detect bl +10694|116054|3588|5|38|40661.90|0.00|0.05|N|O|1998-01-03|1998-01-19|1998-01-30|COLLECT COD|REG AIR|ely regular accounts. care +10694|103987|9008|6|8|15927.84|0.03|0.08|N|O|1998-03-08|1998-01-17|1998-03-25|NONE|FOB|cording to the blithel +10694|101951|4462|7|12|23435.40|0.07|0.03|N|O|1998-01-05|1998-02-06|1998-01-12|DELIVER IN PERSON|FOB|furiously even deposits sleep among t +10695|78490|998|1|5|7342.45|0.09|0.02|N|O|1995-07-05|1995-07-07|1995-07-28|COLLECT COD|AIR|lar pinto beans. final +10695|176986|2021|2|39|80456.22|0.06|0.01|N|F|1995-06-02|1995-06-20|1995-06-23|TAKE BACK RETURN|MAIL|ect. slyly ironic foxes according to the f +10695|199879|2399|3|9|17809.83|0.05|0.01|R|F|1995-05-28|1995-07-14|1995-06-16|NONE|REG AIR|sly. ironic sauternes across the +10695|156999|9515|4|5|10279.95|0.02|0.03|N|O|1995-07-31|1995-07-29|1995-08-02|TAKE BACK RETURN|MAIL|lent asymptotes cajole carefully accordin +10720|14133|9136|1|9|9424.17|0.03|0.06|N|O|1998-04-19|1998-06-07|1998-04-21|TAKE BACK RETURN|MAIL|haggle furiously around t +10720|118834|8835|2|32|59290.56|0.05|0.03|N|O|1998-07-29|1998-06-24|1998-08-05|TAKE BACK RETURN|SHIP|ependencies. carefully final theodo +10720|35748|8252|3|7|11786.18|0.01|0.03|N|O|1998-04-25|1998-06-10|1998-04-29|DELIVER IN PERSON|SHIP|iously bold dolphins. regular, regular +10720|11217|8721|4|20|22564.20|0.09|0.07|N|O|1998-06-28|1998-05-25|1998-07-23|DELIVER IN PERSON|RAIL|omise furiously express instr +10720|122784|5297|5|15|27101.70|0.06|0.06|N|O|1998-05-05|1998-06-11|1998-05-22|NONE|AIR|quests sleep. ironic theodo +10721|134703|9730|1|25|43442.50|0.02|0.08|N|O|1996-04-18|1996-05-09|1996-04-28|DELIVER IN PERSON|AIR|nto beans. careful +10721|141279|3794|2|11|14522.97|0.05|0.00|N|O|1996-05-22|1996-04-18|1996-06-01|NONE|RAIL|riously regular theodolites. slyl +10721|68611|6130|3|39|61604.79|0.05|0.03|N|O|1996-06-22|1996-04-26|1996-07-09|DELIVER IN PERSON|RAIL|lets. slyly regular +10722|71795|9317|1|27|47703.33|0.00|0.08|R|F|1995-04-26|1995-02-23|1995-05-13|NONE|REG AIR|s are. carefully special excuses +10722|48845|3854|2|30|53815.20|0.08|0.05|A|F|1995-02-26|1995-03-29|1995-03-24|COLLECT COD|TRUCK|atelets: ironic, pe +10722|127239|7240|3|48|60779.04|0.04|0.00|R|F|1995-03-04|1995-03-23|1995-03-17|NONE|TRUCK| quickly. platelets promise furiously at +10722|101748|6769|4|7|12248.18|0.06|0.03|R|F|1995-05-10|1995-04-13|1995-05-16|COLLECT COD|FOB|urts wake. blith +10722|65968|5969|5|43|83160.28|0.04|0.01|R|F|1995-02-25|1995-03-01|1995-03-04|DELIVER IN PERSON|AIR|he dependencies. furiously eve +10722|113068|5580|6|6|6486.36|0.09|0.03|R|F|1995-02-12|1995-04-02|1995-02-21|NONE|FOB|eas. carefully special deposits after the +10723|90356|5375|1|23|30966.05|0.06|0.05|N|O|1998-07-25|1998-06-30|1998-08-11|TAKE BACK RETURN|REG AIR|counts sleep blithely silent re +10723|11345|6348|2|27|33921.18|0.03|0.06|N|O|1998-07-07|1998-08-08|1998-07-13|TAKE BACK RETURN|TRUCK|jole carefully. deposits wake slyly. unusua +10724|60572|573|1|38|58237.66|0.02|0.08|A|F|1994-10-30|1994-11-06|1994-11-12|NONE|FOB|l, bold packages are sl +10724|25371|376|2|14|18149.18|0.00|0.08|A|F|1994-09-21|1994-11-24|1994-10-05|COLLECT COD|SHIP|he depths detect s +10724|195983|1022|3|47|97712.06|0.10|0.08|A|F|1995-01-04|1994-11-02|1995-01-14|COLLECT COD|MAIL|. furiously final asymptotes afte +10724|75024|5025|4|32|31968.64|0.01|0.01|R|F|1994-11-28|1994-10-17|1994-12-28|DELIVER IN PERSON|MAIL|al dolphins cajole busily. regular asympto +10725|101123|8654|1|28|31475.36|0.01|0.07|N|O|1998-05-14|1998-06-10|1998-06-05|NONE|MAIL|nstructions. always regular requ +10725|171672|4190|2|28|48822.76|0.09|0.00|N|O|1998-05-19|1998-06-29|1998-06-09|COLLECT COD|SHIP| furiously final notornis wake carefully +10725|87247|7248|3|5|6171.20|0.01|0.01|N|O|1998-07-07|1998-05-22|1998-07-09|NONE|FOB|accounts affix +10726|167880|7881|1|17|33113.96|0.01|0.04|A|F|1993-06-25|1993-07-02|1993-07-14|DELIVER IN PERSON|REG AIR|unts integrate fluffily alongs +10726|143391|3392|2|10|14343.90|0.01|0.01|A|F|1993-05-14|1993-06-11|1993-05-16|COLLECT COD|SHIP|. ironic, ironic a +10726|172108|4626|3|26|30682.60|0.08|0.06|A|F|1993-05-17|1993-06-10|1993-06-05|DELIVER IN PERSON|RAIL|ely final i +10726|17540|5044|4|48|69961.92|0.09|0.02|R|F|1993-06-24|1993-06-12|1993-07-21|DELIVER IN PERSON|AIR| across the quickly +10726|189988|7543|5|13|27013.74|0.02|0.05|A|F|1993-06-20|1993-07-15|1993-07-07|NONE|REG AIR|ze slyly against the fu +10726|117878|390|6|48|91001.76|0.05|0.08|A|F|1993-06-13|1993-06-12|1993-07-10|DELIVER IN PERSON|SHIP|ironic accounts. si +10726|171613|6648|7|5|8423.05|0.05|0.03|R|F|1993-05-31|1993-07-07|1993-06-10|COLLECT COD|FOB|jole above the regular packages. ent +10727|98482|3501|1|34|50336.32|0.08|0.07|A|F|1992-10-10|1992-10-23|1992-11-07|TAKE BACK RETURN|MAIL|ake requests. +10727|182390|9945|2|38|55950.82|0.07|0.02|R|F|1992-11-22|1992-10-03|1992-11-29|DELIVER IN PERSON|RAIL|nts haggle slyly theodolites. quickly fina +10727|27198|7199|3|17|19128.23|0.02|0.07|R|F|1992-08-13|1992-10-28|1992-08-14|COLLECT COD|REG AIR|y furiously at the blithely pending as +10727|113125|659|4|22|25038.64|0.10|0.07|R|F|1992-08-29|1992-09-21|1992-09-01|TAKE BACK RETURN|REG AIR|unusual platelets. fluffi +10727|84834|4835|5|48|87303.84|0.09|0.00|A|F|1992-08-06|1992-09-26|1992-09-03|TAKE BACK RETURN|RAIL|ct carefully. silent +10727|189781|2300|6|20|37415.60|0.07|0.00|R|F|1992-10-13|1992-09-04|1992-11-07|COLLECT COD|MAIL| quickly. carefully final accounts wake fur +10727|39486|6996|7|27|38487.96|0.07|0.03|A|F|1992-11-08|1992-09-08|1992-11-16|DELIVER IN PERSON|MAIL|usual packages. furiously +10752|33055|3056|1|39|38533.95|0.03|0.02|N|O|1995-09-27|1995-12-09|1995-10-15|COLLECT COD|MAIL|y alongside of the even fo +10752|139938|4965|2|49|96918.57|0.08|0.02|N|O|1995-10-20|1995-11-02|1995-11-18|COLLECT COD|SHIP|sly special deposits af +10752|132778|318|3|27|48890.79|0.09|0.01|N|O|1995-09-25|1995-11-28|1995-09-26|NONE|AIR|ular requests. +10752|185813|850|4|50|94940.50|0.06|0.04|N|O|1995-11-08|1995-11-30|1995-12-01|DELIVER IN PERSON|SHIP|aids at the quickly final foxes maintai +10753|12535|7538|1|22|31845.66|0.08|0.00|A|F|1994-08-14|1994-07-29|1994-08-19|COLLECT COD|TRUCK|ccounts. instructi +10754|116553|1576|1|46|72199.30|0.10|0.03|R|F|1993-06-16|1993-04-25|1993-06-29|DELIVER IN PERSON|AIR|kly across the +10754|90299|5318|2|34|43835.86|0.03|0.05|R|F|1993-07-11|1993-06-09|1993-08-09|DELIVER IN PERSON|REG AIR|e carefully against +10754|40069|7582|3|14|14126.84|0.03|0.03|A|F|1993-04-18|1993-05-13|1993-05-01|COLLECT COD|MAIL|y ironic ideas. bold packages n +10754|36825|1832|4|34|59901.88|0.03|0.06|R|F|1993-03-31|1993-05-01|1993-04-22|NONE|FOB|gular accounts. regular courts above the c +10754|107788|5319|5|27|48486.06|0.08|0.01|A|F|1993-06-09|1993-05-18|1993-06-11|DELIVER IN PERSON|FOB| the blithely regular requests +10754|188952|3989|6|21|42859.95|0.10|0.03|A|F|1993-06-30|1993-04-22|1993-07-30|COLLECT COD|TRUCK|furiously ironic +10755|122062|7087|1|48|52034.88|0.04|0.04|R|F|1993-08-22|1993-09-22|1993-09-13|DELIVER IN PERSON|RAIL|ress dependencies engage slyly ab +10755|82566|91|2|6|9291.36|0.08|0.08|A|F|1993-08-18|1993-09-05|1993-09-09|COLLECT COD|SHIP|ng foxes cajole carefu +10755|77413|4935|3|9|12513.69|0.06|0.05|A|F|1993-10-06|1993-09-25|1993-10-18|NONE|SHIP|sits. silent packages wake furiously +10755|74129|1651|4|34|37506.08|0.07|0.04|A|F|1993-07-17|1993-09-12|1993-08-09|NONE|SHIP|iously spe +10756|115702|8214|1|39|66990.30|0.06|0.05|A|F|1992-06-23|1992-07-14|1992-06-27|TAKE BACK RETURN|SHIP|slowly regular or +10757|96764|4292|1|39|68669.64|0.04|0.07|N|O|1998-09-04|1998-07-18|1998-09-16|NONE|REG AIR|sits cajole sile +10757|105991|1012|2|19|37942.81|0.07|0.05|N|O|1998-07-21|1998-08-26|1998-08-18|TAKE BACK RETURN|RAIL|packages use instructions. pi +10758|52776|2777|1|34|58778.18|0.05|0.08|N|O|1997-01-26|1997-01-28|1997-02-24|COLLECT COD|FOB|counts again +10758|193504|1062|2|17|27157.50|0.01|0.00|N|O|1997-02-19|1996-12-17|1997-03-02|DELIVER IN PERSON|RAIL|ly asymptotes. furiously regular pearls +10758|14207|4208|3|2|2242.40|0.06|0.07|N|O|1997-01-29|1997-01-18|1997-01-30|DELIVER IN PERSON|FOB|s. pinto beans u +10758|170856|3374|4|33|63586.05|0.03|0.04|N|O|1997-01-24|1996-12-28|1997-01-29|NONE|AIR|y against the furiously ironic ac +10759|150941|3457|1|10|19919.40|0.05|0.07|N|O|1996-10-18|1996-11-16|1996-11-02|DELIVER IN PERSON|TRUCK|ts thrash blithely among th +10759|62932|7945|2|26|49268.18|0.01|0.02|N|O|1996-10-06|1996-12-16|1996-10-25|TAKE BACK RETURN|RAIL|requests. s +10784|158100|8101|1|31|35901.10|0.03|0.01|A|F|1993-10-30|1993-09-13|1993-11-28|DELIVER IN PERSON|AIR| deposits nag slyl +10784|174365|6883|2|9|12954.24|0.00|0.06|R|F|1993-09-08|1993-09-11|1993-09-30|COLLECT COD|RAIL|nto beans cajole blithely ironic, si +10784|138262|5802|3|20|26005.20|0.03|0.04|A|F|1993-10-28|1993-09-27|1993-11-05|NONE|SHIP|azzle across the blithely spe +10784|163219|3220|4|42|53852.82|0.09|0.00|A|F|1993-10-15|1993-08-13|1993-11-14|COLLECT COD|FOB|lyly even requests boost quick +10784|9728|4729|5|8|13101.76|0.08|0.03|A|F|1993-09-04|1993-09-29|1993-09-30|COLLECT COD|FOB|sly special deposits wake fu +10784|90236|237|6|18|22072.14|0.05|0.03|A|F|1993-07-20|1993-09-21|1993-07-21|NONE|REG AIR|y. fluffily sp +10785|155114|5115|1|1|1169.11|0.03|0.07|R|F|1992-09-08|1992-08-14|1992-09-16|TAKE BACK RETURN|MAIL| instructions. regular, sile +10786|47961|2970|1|36|68722.56|0.08|0.03|N|O|1995-10-30|1995-09-26|1995-11-14|COLLECT COD|MAIL|y even, final requests. regular, ironi +10786|78969|1477|2|14|27271.44|0.08|0.05|N|O|1995-10-07|1995-09-16|1995-10-19|TAKE BACK RETURN|SHIP|xcuses boost +10786|15782|8284|3|1|1697.78|0.08|0.03|N|O|1995-10-08|1995-11-02|1995-10-10|NONE|SHIP|t. foxes along the furiously spec +10787|66790|6791|1|29|50946.91|0.00|0.04|N|O|1997-05-01|1997-04-01|1997-05-08|NONE|TRUCK|e carefully according +10787|134138|6652|2|42|49229.46|0.06|0.02|N|O|1997-02-15|1997-05-05|1997-03-14|COLLECT COD|AIR|ts are quickly. eve +10787|53394|910|3|47|63327.33|0.01|0.07|N|O|1997-04-22|1997-03-19|1997-05-01|TAKE BACK RETURN|REG AIR|ffily bold waters wake express deposits; sp +10787|176351|8869|4|36|51384.60|0.10|0.07|N|O|1997-04-01|1997-04-11|1997-04-23|COLLECT COD|RAIL|st are. blithely even gifts along t +10787|115617|8129|5|47|76732.67|0.04|0.00|N|O|1997-06-06|1997-04-25|1997-06-17|COLLECT COD|FOB|eas. instructions wake blith +10787|167062|9579|6|30|33871.80|0.07|0.05|N|O|1997-05-16|1997-04-03|1997-06-07|DELIVER IN PERSON|MAIL|usual requests wake slyl +10787|197695|2734|7|28|50195.32|0.02|0.02|N|O|1997-04-30|1997-04-15|1997-05-06|NONE|AIR|ular pinto beans. carefu +10788|50814|8330|1|22|38825.82|0.00|0.06|N|O|1997-04-18|1997-03-18|1997-05-01|NONE|AIR|y final instructio +10788|15283|2787|2|27|32353.56|0.01|0.04|N|O|1997-03-06|1997-03-17|1997-03-28|NONE|REG AIR|pinto beans. ironic theo +10788|53407|923|3|26|35370.40|0.03|0.01|N|O|1997-03-06|1997-04-13|1997-03-28|NONE|AIR|dolphins. carefully enticing requests +10788|196473|6474|4|28|43945.16|0.08|0.02|N|O|1997-05-13|1997-04-10|1997-06-05|TAKE BACK RETURN|SHIP|ake carefully silently bold pa +10789|155580|3126|1|7|11449.06|0.08|0.00|R|F|1993-09-23|1993-10-24|1993-10-11|NONE|SHIP|y unusual theodolit +10789|17566|5070|2|36|53408.16|0.08|0.00|R|F|1993-08-25|1993-10-23|1993-09-11|TAKE BACK RETURN|MAIL|alongside of the furiously +10789|20873|8380|3|25|44846.75|0.09|0.06|A|F|1993-09-06|1993-10-31|1993-09-12|COLLECT COD|SHIP|tructions nag quickly. slyly silent forge +10789|9727|9728|4|9|14730.48|0.00|0.08|R|F|1993-12-11|1993-10-11|1993-12-16|NONE|TRUCK|endencies-- blithely f +10789|75990|5991|5|7|13761.93|0.00|0.07|A|F|1993-08-26|1993-11-11|1993-09-02|COLLECT COD|TRUCK|ncies above the final courts hag +10790|156577|6578|1|27|44106.39|0.09|0.00|A|F|1994-12-17|1995-01-23|1995-01-15|TAKE BACK RETURN|TRUCK|as. requests +10790|182698|2699|2|24|42736.56|0.03|0.03|R|F|1995-01-30|1995-01-29|1995-02-15|TAKE BACK RETURN|FOB|thely. bus +10791|28487|8488|1|35|49541.80|0.03|0.08|N|O|1995-09-21|1995-10-26|1995-10-04|DELIVER IN PERSON|SHIP|slyly unusual foxes wake entic +10791|174102|1654|2|24|28226.40|0.07|0.03|N|O|1995-10-08|1995-10-09|1995-10-24|COLLECT COD|AIR|furiously pending dependencies. pinto beans +10791|116160|3694|3|40|47046.40|0.06|0.03|N|O|1995-08-22|1995-11-02|1995-09-21|NONE|FOB|sly ironic packages. thin deposits ab +10791|92935|2936|4|23|44342.39|0.09|0.06|N|O|1995-10-29|1995-11-10|1995-11-02|NONE|TRUCK|efully above the ironic, re +10791|156949|6950|5|8|16047.52|0.10|0.02|N|O|1995-10-06|1995-11-12|1995-10-21|TAKE BACK RETURN|FOB|es about the quickly even +10816|121900|4413|1|22|42281.80|0.01|0.06|N|O|1996-02-17|1996-02-27|1996-03-10|NONE|MAIL|osits are slyly even packag +10816|160226|7775|2|14|18007.08|0.08|0.02|N|O|1996-04-25|1996-02-22|1996-05-17|NONE|FOB|ach furiously above the regular sentiments. +10817|22309|9816|1|4|4925.20|0.06|0.05|N|O|1997-02-26|1997-02-13|1997-03-06|TAKE BACK RETURN|FOB|lithely pending p +10817|137646|5186|2|39|65661.96|0.00|0.07|N|O|1997-02-23|1997-01-17|1997-02-28|TAKE BACK RETURN|FOB|re fluffily according to the +10817|1979|9480|3|43|80881.71|0.05|0.05|N|O|1997-04-06|1997-03-04|1997-04-25|DELIVER IN PERSON|REG AIR|ar accounts. express frets affix +10817|57844|5360|4|33|59460.72|0.03|0.04|N|O|1997-03-04|1997-02-19|1997-03-24|COLLECT COD|FOB|gular requests wake +10817|169203|4236|5|44|55976.80|0.07|0.03|N|O|1996-12-27|1997-01-08|1997-01-21|TAKE BACK RETURN|REG AIR|de of the fluffily final reque +10818|64694|2213|1|9|14928.21|0.03|0.08|N|O|1998-06-06|1998-07-22|1998-06-26|DELIVER IN PERSON|SHIP|es-- bravely regular platelets haggle care +10818|103934|1465|2|45|87206.85|0.08|0.08|N|O|1998-07-26|1998-07-28|1998-08-09|TAKE BACK RETURN|MAIL|heodolites sleep quic +10818|14819|2323|3|15|26007.15|0.02|0.08|N|O|1998-06-07|1998-06-26|1998-06-19|NONE|MAIL| furiously express a +10818|59744|9745|4|33|56223.42|0.06|0.03|N|O|1998-08-11|1998-07-30|1998-08-25|TAKE BACK RETURN|AIR|s across the regular pinto beans +10818|104747|7258|5|38|66566.12|0.06|0.05|N|O|1998-07-03|1998-06-20|1998-07-26|TAKE BACK RETURN|FOB|ven requests. bold, dogged senti +10818|73585|1107|6|50|77929.00|0.07|0.04|N|O|1998-06-05|1998-07-11|1998-07-03|NONE|RAIL|deas are slyly. even deposits +10818|138211|5751|7|8|9993.68|0.10|0.02|N|O|1998-08-23|1998-07-29|1998-09-13|COLLECT COD|MAIL|st furiously final instructions! +10819|96448|8958|1|12|17333.28|0.03|0.08|R|F|1993-11-02|1993-11-09|1993-11-04|TAKE BACK RETURN|RAIL|tithes. ironic, special ideas about the +10819|199691|4730|2|32|57302.08|0.07|0.00|A|F|1993-08-31|1993-10-30|1993-09-26|DELIVER IN PERSON|FOB|ecial theodolites. i +10820|71257|6272|1|28|34391.00|0.10|0.03|N|O|1996-04-14|1996-01-27|1996-05-01|TAKE BACK RETURN|TRUCK| carefully ironic instructions +10820|14646|4647|2|37|57743.68|0.09|0.03|N|O|1995-12-29|1996-02-08|1996-01-11|COLLECT COD|REG AIR|s. blithe dep +10820|149020|4049|3|24|25656.48|0.02|0.07|N|O|1996-03-17|1996-03-09|1996-04-09|NONE|TRUCK|rets. requests affix f +10820|170268|5303|4|26|34794.76|0.01|0.02|N|O|1996-03-15|1996-02-17|1996-03-26|DELIVER IN PERSON|FOB|l requests wake-- +10820|84755|4756|5|21|36534.75|0.01|0.04|N|O|1996-01-28|1996-02-28|1996-02-08|DELIVER IN PERSON|REG AIR|ly final theodol +10820|66887|4406|6|16|29662.08|0.05|0.01|N|O|1996-04-04|1996-03-16|1996-04-25|NONE|RAIL|st the fluffily even accoun +10820|154541|4542|7|2|3191.08|0.06|0.08|N|O|1996-03-20|1996-03-17|1996-04-15|COLLECT COD|RAIL|t to use furious +10821|163202|8235|1|46|58199.20|0.09|0.07|N|O|1996-07-18|1996-06-19|1996-07-23|COLLECT COD|MAIL|hely according to the sl +10821|124679|7192|2|47|80072.49|0.01|0.07|N|O|1996-07-31|1996-07-28|1996-08-28|DELIVER IN PERSON|MAIL| bold ideas. fluffily +10821|73531|6039|3|33|49649.49|0.05|0.05|N|O|1996-08-02|1996-07-11|1996-08-26|TAKE BACK RETURN|REG AIR|posits. final instructions about th +10822|98457|8458|1|10|14554.50|0.03|0.05|A|F|1994-02-23|1994-02-08|1994-03-09|TAKE BACK RETURN|RAIL|ully regular requests. theodolites amon +10823|67702|7703|1|32|53430.40|0.06|0.04|A|F|1992-07-03|1992-08-24|1992-07-17|TAKE BACK RETURN|AIR|s grow about the ideas. s +10823|62804|2805|2|40|70672.00|0.01|0.00|R|F|1992-09-01|1992-09-07|1992-09-21|NONE|SHIP|gular, regular +10848|69183|4196|1|41|47239.38|0.01|0.04|N|O|1997-01-31|1996-12-28|1997-02-12|TAKE BACK RETURN|TRUCK|usual excuses. +10849|21596|6601|1|33|50080.47|0.01|0.06|N|O|1997-05-08|1997-03-03|1997-05-20|COLLECT COD|TRUCK|refully expr +10849|158963|1479|2|38|76834.48|0.10|0.03|N|O|1997-05-26|1997-03-26|1997-06-03|COLLECT COD|MAIL|foxes. express fo +10849|87878|2895|3|2|3731.74|0.03|0.00|N|O|1997-04-16|1997-04-08|1997-05-16|COLLECT COD|RAIL|osits affix idly pending instructions +10849|158416|3447|4|50|73720.50|0.06|0.06|N|O|1997-02-01|1997-03-20|1997-02-24|NONE|AIR| unusual, thin sentiments. fu +10849|83457|982|5|50|72022.50|0.04|0.00|N|O|1997-05-13|1997-04-15|1997-05-17|TAKE BACK RETURN|MAIL| final pinto beans u +10849|59612|7128|6|39|61292.79|0.02|0.00|N|O|1997-04-09|1997-04-30|1997-04-16|DELIVER IN PERSON|REG AIR|requests are about t +10850|129760|7297|1|9|16107.84|0.06|0.02|N|O|1996-11-25|1996-12-19|1996-12-04|COLLECT COD|FOB|ular deposits. packages am +10850|60300|7819|2|1|1260.30|0.07|0.05|N|O|1996-12-11|1996-11-20|1997-01-09|DELIVER IN PERSON|REG AIR|ironic packages sleep +10850|47821|7822|3|15|26532.30|0.06|0.04|N|O|1996-11-23|1996-10-25|1996-12-02|TAKE BACK RETURN|SHIP|equests boost platelets. i +10850|122151|2152|4|41|48099.15|0.03|0.00|N|O|1996-11-29|1996-10-29|1996-12-12|NONE|MAIL| slyly silent excuses affix slyly accordin +10850|189336|9337|5|1|1425.33|0.04|0.02|N|O|1996-09-27|1996-11-24|1996-10-02|DELIVER IN PERSON|FOB|unts. quickly regular warthogs thras +10851|7478|9979|1|4|5541.88|0.06|0.04|R|F|1994-06-27|1994-06-12|1994-07-19|NONE|FOB|gular tithes. unusual deposits h +10851|69635|4648|2|33|52952.79|0.07|0.05|R|F|1994-06-16|1994-07-01|1994-07-08|DELIVER IN PERSON|AIR|tions should have to sleep fluffil +10851|145153|7668|3|18|21566.70|0.00|0.04|R|F|1994-05-01|1994-06-15|1994-05-09|TAKE BACK RETURN|TRUCK|uffily unusual platelets slee +10851|171030|3548|4|29|31929.87|0.01|0.02|A|F|1994-05-18|1994-06-26|1994-05-21|NONE|MAIL|le. ironic dependencie +10851|92333|4843|5|27|35783.91|0.05|0.04|R|F|1994-04-12|1994-06-14|1994-04-18|DELIVER IN PERSON|MAIL|furiously instructions. deposits a +10851|27053|7054|6|18|17640.90|0.04|0.05|R|F|1994-07-06|1994-07-01|1994-07-31|NONE|AIR|pendencies. slyly regular +10851|67006|4525|7|35|34055.00|0.00|0.07|R|F|1994-06-27|1994-06-04|1994-07-22|COLLECT COD|REG AIR|sly unusual dep +10852|159610|2126|1|31|51757.91|0.03|0.07|A|F|1994-01-15|1994-01-14|1994-02-09|TAKE BACK RETURN|MAIL| accounts haggle quickly. carefully br +10852|155297|2843|2|11|14875.19|0.10|0.00|R|F|1994-01-24|1993-12-01|1994-02-07|DELIVER IN PERSON|MAIL|packages wake +10852|74594|2116|3|39|61175.01|0.02|0.06|A|F|1993-12-03|1994-01-12|1993-12-07|DELIVER IN PERSON|MAIL|ly final request +10852|85429|2954|4|35|49504.70|0.07|0.00|A|F|1993-12-17|1993-11-26|1994-01-03|TAKE BACK RETURN|MAIL| according to the requests. careful +10852|196586|9106|5|43|72350.94|0.01|0.02|A|F|1993-12-10|1993-12-27|1993-12-26|TAKE BACK RETURN|RAIL|r courts? p +10852|13251|755|6|23|26777.75|0.03|0.01|A|F|1993-12-11|1993-12-29|1994-01-02|COLLECT COD|TRUCK|nts are. ev +10853|148996|1511|1|14|28629.86|0.02|0.04|R|F|1994-01-27|1994-03-28|1994-02-07|NONE|SHIP|regular packages. slyly bold asympt +10853|161854|4371|2|21|40232.85|0.03|0.02|A|F|1994-01-31|1994-04-01|1994-02-21|DELIVER IN PERSON|SHIP|ithely fluffi +10853|64203|4204|3|12|14006.40|0.10|0.04|A|F|1994-02-10|1994-03-19|1994-03-11|NONE|RAIL|eful platelets. even, final deposits cajo +10854|78461|5983|1|3|4318.38|0.08|0.05|N|O|1998-08-11|1998-07-30|1998-08-17|DELIVER IN PERSON|AIR|ing to the ironic, final foxes. special ac +10855|426|2927|1|38|50403.96|0.10|0.06|N|O|1997-07-23|1997-09-17|1997-08-22|COLLECT COD|RAIL|ross the slyly regular packages. even +10855|151223|1224|2|36|45871.92|0.08|0.00|N|O|1997-10-07|1997-08-17|1997-10-27|DELIVER IN PERSON|RAIL|old packages. idle depende +10855|1927|9428|3|46|84130.32|0.02|0.03|N|O|1997-10-15|1997-09-27|1997-10-18|COLLECT COD|RAIL|y silent packages cajole at the sly +10855|175713|748|4|11|19675.81|0.00|0.00|N|O|1997-09-24|1997-09-10|1997-10-01|COLLECT COD|REG AIR|ias. furiously bold instru +10855|3103|5604|5|27|27164.70|0.09|0.05|N|O|1997-09-17|1997-09-22|1997-09-23|TAKE BACK RETURN|REG AIR|ctions. quick +10855|152017|2018|6|8|8552.08|0.07|0.05|N|O|1997-08-09|1997-09-17|1997-08-26|TAKE BACK RETURN|TRUCK| hinder blithely. furiously special a +10855|140744|3259|7|41|73174.34|0.09|0.05|N|O|1997-09-21|1997-09-19|1997-10-04|COLLECT COD|AIR|lly regular request +10880|84170|6679|1|25|28854.25|0.09|0.01|R|F|1992-06-22|1992-07-31|1992-07-02|COLLECT COD|REG AIR|arefully alongside of the caref +10881|126670|1695|1|15|25450.05|0.00|0.08|R|F|1994-06-01|1994-03-29|1994-06-14|TAKE BACK RETURN|SHIP|en platelets haggle after th +10881|135021|2561|2|15|15840.30|0.09|0.00|A|F|1994-04-08|1994-04-27|1994-04-22|DELIVER IN PERSON|AIR|dugouts boost against the +10881|88337|8338|3|11|14578.63|0.06|0.07|A|F|1994-03-01|1994-04-11|1994-03-02|DELIVER IN PERSON|FOB|ending pinto +10881|79771|2279|4|19|33264.63|0.01|0.01|A|F|1994-02-24|1994-04-26|1994-03-08|TAKE BACK RETURN|REG AIR|es haggle slyly. carefully final exc +10881|97559|7560|5|32|49809.60|0.01|0.08|A|F|1994-05-19|1994-04-01|1994-05-29|COLLECT COD|FOB|beans print sl +10881|69594|4607|6|46|71925.14|0.02|0.01|R|F|1994-03-20|1994-04-02|1994-03-26|NONE|SHIP|sits wake quick +10881|51794|9310|7|7|12220.53|0.00|0.05|A|F|1994-06-09|1994-03-29|1994-06-25|COLLECT COD|AIR|ctions haggle slyly ironic platelets. bli +10882|96380|6381|1|37|50926.06|0.05|0.02|N|O|1998-07-18|1998-07-23|1998-08-11|COLLECT COD|AIR| unusual requests affi +10882|52266|7277|2|1|1218.26|0.08|0.00|N|O|1998-07-06|1998-07-14|1998-07-10|TAKE BACK RETURN|REG AIR|ole carefully permanently eve +10882|19375|1877|3|1|1294.37|0.06|0.02|N|O|1998-06-21|1998-08-10|1998-07-07|TAKE BACK RETURN|FOB|te alongside of the even accounts. excuses +10882|32249|2250|4|3|3543.72|0.02|0.05|N|O|1998-08-09|1998-08-05|1998-08-28|NONE|FOB|inal, unusual depos +10882|195999|1038|5|16|33519.84|0.00|0.04|N|O|1998-08-25|1998-08-18|1998-09-22|TAKE BACK RETURN|REG AIR|, special somas s +10883|50665|666|1|47|75936.02|0.06|0.04|N|O|1998-05-17|1998-04-04|1998-06-01|DELIVER IN PERSON|SHIP|ven requests. flu +10883|122733|270|2|19|33358.87|0.06|0.05|N|O|1998-04-22|1998-04-07|1998-05-01|DELIVER IN PERSON|TRUCK| accounts sleep carefully-- furiously un +10883|167101|4650|3|9|10512.90|0.10|0.05|N|O|1998-03-04|1998-03-08|1998-04-02|DELIVER IN PERSON|MAIL|ickly. pending, final th +10883|57855|7856|4|14|25379.90|0.07|0.01|N|O|1998-03-02|1998-04-18|1998-03-08|DELIVER IN PERSON|RAIL|nic packages maintain. r +10884|139163|4190|1|17|20436.72|0.01|0.07|A|F|1995-02-02|1995-02-02|1995-02-27|COLLECT COD|FOB|counts cajole q +10884|103673|8694|2|32|53653.44|0.06|0.07|A|F|1994-12-30|1995-01-03|1995-01-09|DELIVER IN PERSON|REG AIR|ost quickly +10884|22246|9753|3|21|24533.04|0.03|0.06|R|F|1995-01-13|1995-01-16|1995-02-03|DELIVER IN PERSON|MAIL|deposits against +10884|81535|9060|4|1|1516.53|0.05|0.00|R|F|1995-01-08|1995-01-29|1995-01-24|COLLECT COD|FOB|y final requests. fi +10884|150849|8395|5|8|15198.72|0.01|0.00|R|F|1995-01-19|1995-01-12|1995-02-13|DELIVER IN PERSON|FOB|erns along the blithely express instru +10884|111093|8627|6|50|55204.50|0.00|0.03|R|F|1995-01-15|1994-12-27|1995-01-18|NONE|MAIL|uses integrate slyly fur +10884|127911|424|7|46|89189.86|0.09|0.03|A|F|1994-12-14|1995-01-16|1994-12-23|COLLECT COD|FOB|ssly furiously ironic dep +10885|196244|8764|1|22|29485.28|0.01|0.05|N|O|1998-05-29|1998-07-13|1998-06-04|NONE|AIR|tegrate fluffily ironic accounts. quickl +10885|67707|2720|2|36|60289.20|0.01|0.01|N|O|1998-05-09|1998-06-21|1998-06-02|NONE|MAIL|thely even asymptotes nag furio +10885|141866|9409|3|9|17170.74|0.04|0.00|N|O|1998-05-27|1998-05-22|1998-06-04|DELIVER IN PERSON|REG AIR|nding accounts; slyl +10885|133992|1532|4|45|91169.55|0.09|0.05|N|O|1998-04-22|1998-05-25|1998-05-07|NONE|MAIL|cial, even theodolit +10885|191645|6684|5|47|81622.08|0.00|0.04|N|O|1998-05-01|1998-07-16|1998-05-28|TAKE BACK RETURN|REG AIR| the pending packages haggle asymptot +10886|77856|7857|1|50|91692.50|0.03|0.02|A|F|1994-12-16|1994-11-18|1995-01-10|COLLECT COD|FOB|elets serve slyly about the accounts +10886|113896|1430|2|42|80215.38|0.05|0.00|R|F|1994-11-18|1994-11-02|1994-12-03|COLLECT COD|AIR|dependencies haggle quickly along t +10886|45966|3479|3|36|68830.56|0.02|0.06|R|F|1994-10-21|1994-10-16|1994-10-24|DELIVER IN PERSON|AIR|nts sleep blithely. id +10886|147658|5201|4|12|20467.80|0.07|0.08|A|F|1994-10-27|1994-10-29|1994-10-30|NONE|TRUCK|ackages. fi +10886|79493|2001|5|21|30922.29|0.03|0.03|R|F|1994-10-27|1994-11-13|1994-11-14|DELIVER IN PERSON|FOB| across th +10886|36781|4291|6|21|36073.38|0.06|0.08|R|F|1994-09-03|1994-09-26|1994-09-11|COLLECT COD|SHIP|ternes along the ironic r +10886|170308|5343|7|13|17917.90|0.06|0.05|R|F|1994-10-11|1994-11-04|1994-11-08|COLLECT COD|TRUCK|l sauternes. ideas wake +10887|156868|4414|1|36|69294.96|0.05|0.00|N|O|1995-08-17|1995-07-09|1995-09-07|DELIVER IN PERSON|SHIP|blithely ironic packages cajole caref +10912|127624|5161|1|26|42942.12|0.02|0.08|N|O|1996-12-30|1997-03-06|1997-01-24|NONE|MAIL|nts. regular packages promise care +10912|173074|5592|2|12|13764.84|0.07|0.00|N|O|1997-03-15|1997-02-06|1997-03-20|DELIVER IN PERSON|RAIL|lyly about the furiously ev +10912|38240|8241|3|37|43594.88|0.02|0.08|N|O|1997-03-05|1997-03-23|1997-03-30|COLLECT COD|AIR|e after the express accounts. +10912|89867|7392|4|48|89129.28|0.03|0.02|N|O|1997-04-06|1997-02-03|1997-05-01|TAKE BACK RETURN|REG AIR|r accounts detect slyly +10912|191621|4141|5|31|53091.22|0.10|0.00|N|O|1997-03-30|1997-02-25|1997-04-05|NONE|FOB|ar, regular requests w +10912|167264|7265|6|4|5325.04|0.07|0.06|N|O|1997-03-03|1997-02-15|1997-03-18|COLLECT COD|SHIP|. regular deposits engage over +10913|66990|4509|1|27|52838.73|0.10|0.02|A|F|1993-03-23|1993-04-26|1993-04-10|TAKE BACK RETURN|AIR|blithely special, ironic +10913|96835|9345|2|18|32972.94|0.08|0.03|R|F|1993-02-26|1993-04-30|1993-03-24|TAKE BACK RETURN|TRUCK|fully carefully pending acco +10913|95138|157|3|30|33993.90|0.09|0.08|R|F|1993-02-19|1993-04-25|1993-02-27|DELIVER IN PERSON|RAIL|requests nag carefully. ruthle +10914|153523|6039|1|19|29953.88|0.09|0.03|R|F|1995-02-26|1995-04-01|1995-03-07|COLLECT COD|REG AIR|l packages. pinto beans eat. f +10914|58808|1314|2|28|49470.40|0.07|0.04|R|F|1995-03-24|1995-03-06|1995-04-08|TAKE BACK RETURN|AIR|cajole quickly. bli +10914|177450|5002|3|13|19856.85|0.05|0.02|R|F|1995-04-24|1995-03-28|1995-05-20|NONE|TRUCK|ever. ironic, bold ideas boost +10914|189406|4443|4|32|47852.80|0.03|0.07|R|F|1995-02-28|1995-02-27|1995-03-07|DELIVER IN PERSON|TRUCK| blithely exp +10914|144158|9187|5|24|28851.60|0.05|0.06|A|F|1995-04-28|1995-03-27|1995-05-11|DELIVER IN PERSON|TRUCK|riously express pack +10914|56255|1266|6|24|29070.00|0.04|0.01|A|F|1995-04-21|1995-04-03|1995-04-26|NONE|REG AIR|ans sleep slyly along +10915|91562|9090|1|2|3107.12|0.00|0.05|R|F|1993-12-30|1994-01-28|1994-01-02|COLLECT COD|AIR| ruthless p +10915|71987|4495|2|6|11753.88|0.09|0.05|R|F|1993-11-30|1994-01-14|1993-12-05|TAKE BACK RETURN|SHIP| print carefully unusual +10915|77222|9730|3|30|35976.60|0.04|0.02|A|F|1994-01-07|1994-01-19|1994-01-23|NONE|AIR|refully express pinto beans-- ironi +10915|64848|4849|4|22|39882.48|0.07|0.01|A|F|1994-02-20|1993-12-28|1994-02-25|DELIVER IN PERSON|SHIP|ites use ab +10915|97153|4681|5|44|50606.60|0.00|0.02|A|F|1994-02-22|1993-12-21|1994-03-10|COLLECT COD|MAIL|the carefully regular mu +10916|182329|9884|1|39|55041.48|0.00|0.08|N|O|1995-07-02|1995-05-17|1995-07-13|COLLECT COD|MAIL|quickly bold packages +10916|194545|9584|2|33|54104.82|0.09|0.02|R|F|1995-04-17|1995-05-04|1995-04-25|DELIVER IN PERSON|AIR|t the even frets. final instructions caj +10916|107053|4584|3|32|33921.60|0.08|0.07|N|F|1995-06-13|1995-05-28|1995-07-02|NONE|TRUCK|ometimes blithe +10916|38354|5864|4|30|38770.50|0.01|0.02|R|F|1995-05-15|1995-04-26|1995-06-06|COLLECT COD|RAIL| blithely regular requests! closely blith +10916|14664|9667|5|34|53674.44|0.05|0.05|N|F|1995-06-10|1995-05-27|1995-07-07|NONE|SHIP|platelets along the special +10916|53239|3240|6|2|2384.46|0.01|0.00|A|F|1995-05-21|1995-04-14|1995-05-25|DELIVER IN PERSON|SHIP|wake according +10916|175631|5632|7|10|17066.30|0.09|0.05|N|O|1995-06-21|1995-05-28|1995-07-06|NONE|MAIL|cally final ac +10917|19234|9235|1|15|17298.45|0.01|0.01|R|F|1992-03-23|1992-03-31|1992-04-12|DELIVER IN PERSON|AIR|pite the slyly final p +10917|56165|3681|2|1|1121.16|0.05|0.02|A|F|1992-06-09|1992-04-30|1992-06-10|COLLECT COD|MAIL|usly regular dolphins. packages +10917|149827|9828|3|18|33782.76|0.09|0.08|A|F|1992-03-12|1992-04-18|1992-04-08|DELIVER IN PERSON|AIR| doubt furiously carefully regula +10917|125734|3271|4|45|79187.85|0.07|0.02|A|F|1992-04-10|1992-04-07|1992-04-14|TAKE BACK RETURN|REG AIR|deposits solve furiously. blithely final +10917|195956|3514|5|19|38987.05|0.05|0.04|A|F|1992-04-17|1992-04-14|1992-04-29|DELIVER IN PERSON|SHIP|iously final deposits are after the qu +10918|31027|3531|1|8|7664.16|0.09|0.06|N|O|1996-02-13|1995-11-29|1996-03-03|NONE|AIR|the furious +10918|65587|8094|2|46|71418.68|0.05|0.04|N|O|1995-11-30|1995-12-27|1995-12-19|COLLECT COD|SHIP|s. regular accounts throughout the p +10919|136404|8918|1|45|64818.00|0.05|0.04|A|F|1993-07-04|1993-05-29|1993-07-15|COLLECT COD|SHIP|telets across the +10944|83518|8535|1|11|16516.61|0.05|0.05|N|O|1996-01-14|1995-12-28|1996-02-05|NONE|SHIP|ourts. deposits nag blithely at the accou +10944|75874|889|2|41|75844.67|0.07|0.07|N|O|1995-12-03|1996-02-03|1995-12-14|DELIVER IN PERSON|FOB|egularly bold deposits +10944|669|3170|3|34|53368.44|0.01|0.06|N|O|1995-12-02|1995-12-20|1995-12-03|COLLECT COD|RAIL|ording to the blithely silent accounts. sly +10944|36452|1459|4|9|12496.05|0.05|0.00|N|O|1996-02-21|1996-01-29|1996-02-27|COLLECT COD|RAIL|ly regular packages! carefu +10945|179796|9797|1|28|52522.12|0.06|0.07|A|F|1992-02-13|1992-03-30|1992-02-25|TAKE BACK RETURN|REG AIR|egular packages haggle. slyly i +10945|26118|6119|2|35|36543.85|0.06|0.06|A|F|1992-02-19|1992-03-13|1992-03-14|COLLECT COD|AIR| carefully even theodolites. +10945|155258|5259|3|17|22325.25|0.09|0.01|A|F|1992-01-28|1992-02-13|1992-02-22|NONE|FOB|telets use slyly according to the furi +10945|14709|7211|4|49|79561.30|0.08|0.01|R|F|1992-02-18|1992-03-06|1992-03-07|DELIVER IN PERSON|RAIL|fully furiously even theodolites. quickly +10945|197899|419|5|5|9984.45|0.04|0.06|R|F|1992-03-19|1992-02-24|1992-04-12|NONE|TRUCK|iously unusual ideas haggle slyly. ironi +10946|115457|480|1|43|63315.35|0.08|0.05|N|O|1997-05-11|1997-06-09|1997-05-19|NONE|SHIP|ole furiously. bold packages slee +10946|73825|3826|2|30|53964.60|0.04|0.02|N|O|1997-06-26|1997-05-10|1997-07-18|COLLECT COD|RAIL|es. carefully pending instru +10946|166811|4360|3|20|37556.20|0.10|0.06|N|O|1997-03-30|1997-05-23|1997-04-01|NONE|RAIL|uthless ideas wak +10946|178282|5834|4|39|53050.92|0.01|0.07|N|O|1997-05-29|1997-05-25|1997-06-03|DELIVER IN PERSON|AIR|ns. slyly special pint +10946|172475|7510|5|48|74278.56|0.06|0.03|N|O|1997-05-10|1997-05-20|1997-06-04|TAKE BACK RETURN|TRUCK|riously fi +10946|180260|5297|6|39|52270.14|0.04|0.02|N|O|1997-05-30|1997-06-01|1997-06-09|COLLECT COD|FOB|nusual inst +10947|167855|372|1|21|40379.85|0.07|0.04|N|O|1996-01-14|1996-03-28|1996-01-25|TAKE BACK RETURN|MAIL|dogged requests. slyly even plate +10947|136724|1751|2|1|1760.72|0.05|0.03|N|O|1996-02-20|1996-03-24|1996-02-23|DELIVER IN PERSON|TRUCK|the carefully final requests +10947|110791|5814|3|42|75675.18|0.05|0.02|N|O|1996-05-06|1996-02-07|1996-05-16|TAKE BACK RETURN|SHIP|pinto beans sleep fluffily against the p +10947|58273|5789|4|43|52944.61|0.09|0.05|N|O|1996-04-07|1996-04-02|1996-04-23|TAKE BACK RETURN|REG AIR|y. carefully final accounts sleep fluff +10948|3770|3771|1|44|73645.88|0.09|0.01|A|F|1992-10-24|1992-10-16|1992-11-01|TAKE BACK RETURN|SHIP|leep blithely deposits. foxes n +10948|157064|7065|2|49|54931.94|0.05|0.06|A|F|1992-11-25|1992-09-16|1992-12-14|DELIVER IN PERSON|FOB|y along the quickly bold a +10948|170795|8347|3|43|80228.97|0.01|0.08|R|F|1992-10-27|1992-11-09|1992-11-19|DELIVER IN PERSON|TRUCK| special requests +10948|148621|3650|4|27|45079.74|0.01|0.06|A|F|1992-10-09|1992-10-31|1992-10-24|NONE|AIR|ver the slyly regular dependencies nag b +10949|24705|9710|1|24|39112.80|0.10|0.07|A|F|1994-05-13|1994-06-06|1994-06-12|TAKE BACK RETURN|SHIP|yly unusual theodolites? deposits sleep fl +10949|9227|9228|2|19|21588.18|0.01|0.07|R|F|1994-07-13|1994-06-10|1994-07-16|NONE|AIR|deposits. blithely special requests sle +10949|75092|7600|3|39|41616.51|0.02|0.05|R|F|1994-05-26|1994-06-01|1994-06-23|DELIVER IN PERSON|MAIL|owly about the regular, regu +10950|140319|2834|1|29|39419.99|0.00|0.00|N|O|1997-08-01|1997-08-25|1997-08-14|NONE|REG AIR|ts haggle ruthlessly depos +10951|102569|7590|1|26|40860.56|0.02|0.08|R|F|1993-02-10|1993-01-31|1993-02-12|TAKE BACK RETURN|SHIP|ctions promise blithely ironic packages. +10951|64517|4518|2|22|32593.22|0.10|0.05|R|F|1992-12-09|1993-01-14|1992-12-24|DELIVER IN PERSON|MAIL|ages. silent accounts cajole ruthlessly. +10951|135353|380|3|26|36097.10|0.08|0.01|R|F|1992-12-27|1993-01-19|1993-01-13|DELIVER IN PERSON|MAIL|ns. requests wake fluffily. +10951|74088|9103|4|31|32924.48|0.03|0.05|R|F|1992-12-04|1993-01-27|1992-12-29|COLLECT COD|FOB|final pinto +10951|183009|3010|5|21|22932.00|0.10|0.08|R|F|1992-12-10|1992-12-18|1993-01-02|NONE|MAIL|silent packages? blit +10976|24040|1547|1|11|10604.44|0.02|0.04|A|F|1992-12-21|1992-11-13|1993-01-13|TAKE BACK RETURN|SHIP|lyly pending pinto beans +10976|38295|3302|2|26|32065.54|0.04|0.03|A|F|1993-01-05|1992-11-14|1993-01-20|TAKE BACK RETURN|FOB|ssly against the cour +10976|18259|3262|3|19|22367.75|0.05|0.03|R|F|1992-11-28|1992-12-25|1992-12-16|TAKE BACK RETURN|REG AIR|even, regular dependencies haggle +10976|77587|5109|4|13|20339.54|0.08|0.06|R|F|1992-10-26|1992-11-15|1992-11-09|DELIVER IN PERSON|REG AIR|y ironic ideas unwind in +10976|190762|5801|5|28|51877.28|0.03|0.08|A|F|1992-12-08|1992-12-07|1992-12-16|TAKE BACK RETURN|TRUCK|its use sly +10976|128068|8069|6|27|29593.62|0.10|0.06|R|F|1992-10-21|1992-12-25|1992-10-27|COLLECT COD|SHIP|al ideas above the quickly +10976|34654|2164|7|13|20652.45|0.10|0.08|A|F|1992-11-13|1992-12-05|1992-11-21|NONE|RAIL|ake slyly. attainme +10977|23770|1277|1|41|69444.57|0.01|0.08|N|O|1998-06-19|1998-07-24|1998-07-14|DELIVER IN PERSON|SHIP|even packages. stealt +10977|96874|9384|2|6|11225.22|0.10|0.01|N|O|1998-09-01|1998-08-14|1998-09-19|TAKE BACK RETURN|RAIL|nal asymptotes +10977|149166|4195|3|3|3645.48|0.03|0.04|N|O|1998-06-27|1998-08-08|1998-06-30|DELIVER IN PERSON|MAIL|y slow accounts according to the som +10977|17187|9689|4|31|34229.58|0.00|0.05|N|O|1998-09-21|1998-08-17|1998-10-11|NONE|TRUCK|osits play! fluffily unusual instructions i +10978|159639|2155|1|40|67945.20|0.00|0.04|A|F|1994-05-31|1994-05-06|1994-06-13|DELIVER IN PERSON|TRUCK|ole slyly even, pendi +10978|45660|669|2|13|20873.58|0.07|0.03|R|F|1994-06-11|1994-06-13|1994-07-07|DELIVER IN PERSON|MAIL|y express hockey players except the care +10978|1017|6018|3|32|29376.32|0.10|0.05|R|F|1994-05-03|1994-05-13|1994-05-15|COLLECT COD|REG AIR|e slyly about the daringly pending p +10979|138834|8835|1|28|52439.24|0.09|0.02|N|O|1995-11-09|1995-11-06|1995-12-05|DELIVER IN PERSON|TRUCK|ng the slyly bold theodolites. fi +10979|166462|8979|2|5|7642.30|0.04|0.03|N|O|1996-01-30|1995-11-18|1996-01-31|NONE|FOB| will have to are pack +10979|116370|3904|3|25|34659.25|0.10|0.06|N|O|1995-12-18|1995-12-31|1995-12-29|NONE|TRUCK|blithely even foxes wake +10979|26845|1850|4|11|19490.24|0.00|0.07|N|O|1995-10-29|1995-12-04|1995-11-17|TAKE BACK RETURN|TRUCK|nal decoys. carefully even p +10979|171962|9514|5|23|46781.08|0.02|0.03|N|O|1995-10-28|1995-11-07|1995-11-09|NONE|RAIL|quests wake slyly about the blithely silent +10979|161253|1254|6|27|35484.75|0.06|0.05|N|O|1995-11-05|1995-11-13|1995-11-20|COLLECT COD|AIR|e slyly sp +10979|170870|5905|7|5|9704.35|0.09|0.05|N|O|1995-10-25|1995-12-15|1995-11-10|TAKE BACK RETURN|SHIP|pitaphs cajole +10980|960|961|1|28|52106.88|0.09|0.07|N|O|1996-11-13|1996-10-12|1996-12-02|TAKE BACK RETURN|SHIP|es. carefully even platelets na +10980|128470|6007|2|43|64434.21|0.04|0.01|N|O|1996-10-08|1996-09-09|1996-11-02|TAKE BACK RETURN|MAIL|ackages wake according to the asymp +10980|179662|2180|3|1|1741.66|0.03|0.02|N|O|1996-08-10|1996-09-24|1996-09-06|TAKE BACK RETURN|AIR|e carefully +10981|67653|160|1|26|42136.90|0.04|0.07|A|F|1993-08-16|1993-07-10|1993-09-13|NONE|FOB|ingly regular theodolites hinder blithely +10981|32871|2872|2|20|36077.40|0.01|0.06|R|F|1993-08-04|1993-07-04|1993-08-25|COLLECT COD|TRUCK| slyly regular +10981|51280|3786|3|25|30782.00|0.10|0.00|R|F|1993-07-04|1993-08-11|1993-07-06|TAKE BACK RETURN|MAIL|ecial asymptotes. final fox +10981|60378|2885|4|16|21413.92|0.07|0.01|R|F|1993-06-03|1993-07-25|1993-06-20|DELIVER IN PERSON|SHIP|y regular foxes are quickly care +10981|158862|1378|5|19|36496.34|0.08|0.02|R|F|1993-08-25|1993-07-01|1993-08-28|TAKE BACK RETURN|SHIP|nag slyly-- c +10981|179962|9963|6|30|61258.80|0.01|0.08|R|F|1993-06-09|1993-07-15|1993-06-12|DELIVER IN PERSON|AIR|heodolites above the +10981|19368|6872|7|30|38620.80|0.02|0.00|A|F|1993-07-10|1993-08-12|1993-07-26|DELIVER IN PERSON|TRUCK|egular packages wake above the +10982|107537|5068|1|6|9267.18|0.07|0.01|A|F|1993-02-25|1993-01-22|1993-03-01|NONE|REG AIR| fluffily speci +10982|167653|2686|2|18|30971.70|0.07|0.06|A|F|1993-01-31|1993-01-14|1993-02-09|TAKE BACK RETURN|AIR|instructions are foxes. de +10982|130743|3257|3|39|69175.86|0.05|0.06|A|F|1993-01-31|1993-01-26|1993-02-08|DELIVER IN PERSON|SHIP|pinto beans after the blithely +10982|186156|1193|4|35|43475.25|0.09|0.05|R|F|1993-01-06|1993-01-13|1993-01-22|DELIVER IN PERSON|SHIP|lithely pen +10982|111291|1292|5|4|5209.16|0.06|0.01|A|F|1993-02-16|1993-02-09|1993-03-03|NONE|REG AIR|refully special ideas: quick +10982|51891|1892|6|25|46072.25|0.08|0.07|R|F|1993-01-09|1993-01-13|1993-01-26|COLLECT COD|AIR|refully accordin +10982|120551|5576|7|18|28287.90|0.01|0.04|R|F|1992-12-21|1993-03-11|1993-01-17|TAKE BACK RETURN|SHIP| pending, final requests nag regular +10983|84365|6874|1|36|48576.96|0.07|0.04|N|O|1997-03-15|1997-03-12|1997-04-01|COLLECT COD|AIR| to the regular ideas. slyly even re +10983|116106|6107|2|43|48250.30|0.06|0.07|N|O|1997-04-15|1997-03-18|1997-05-11|DELIVER IN PERSON|MAIL|y regular accounts. gifts sleep ab +11008|181073|3592|1|30|34622.10|0.10|0.06|A|F|1994-03-05|1994-04-04|1994-03-22|TAKE BACK RETURN|RAIL| blithely slow pinto beans. fluff +11008|84208|4209|2|39|46495.80|0.00|0.03|R|F|1994-06-10|1994-04-18|1994-06-11|TAKE BACK RETURN|SHIP|atelets. fluffily +11008|79887|2395|3|16|29870.08|0.08|0.01|A|F|1994-05-07|1994-04-02|1994-05-31|NONE|MAIL|ely final foxes. bold, final depe +11008|58854|3865|4|15|27192.75|0.05|0.03|R|F|1994-05-04|1994-03-31|1994-06-02|DELIVER IN PERSON|TRUCK|lyly along the blithely bold wa +11008|144533|9562|5|42|66256.26|0.01|0.00|R|F|1994-03-23|1994-05-24|1994-04-18|DELIVER IN PERSON|RAIL|rash furiously blithely silent +11009|148175|5718|1|41|50149.97|0.07|0.05|N|O|1997-03-09|1997-05-17|1997-04-03|TAKE BACK RETURN|MAIL| accounts. furiously regular cou +11009|166636|6637|2|6|10215.78|0.00|0.08|N|O|1997-04-06|1997-04-21|1997-04-24|TAKE BACK RETURN|TRUCK|lly bold a +11010|81106|8631|1|23|25003.30|0.08|0.07|N|O|1997-04-03|1997-06-20|1997-04-18|COLLECT COD|AIR|uests. ironic, pend +11010|147609|124|2|23|38101.80|0.01|0.03|N|O|1997-06-07|1997-05-04|1997-06-26|DELIVER IN PERSON|FOB|ter the furiou +11010|56411|3927|3|8|10939.28|0.03|0.08|N|O|1997-04-13|1997-04-27|1997-05-10|DELIVER IN PERSON|FOB|er the express, express sheaves w +11010|96985|2004|4|22|43603.56|0.09|0.00|N|O|1997-04-17|1997-05-20|1997-04-21|DELIVER IN PERSON|SHIP|s about the enticingly final ideas wa +11010|20904|5909|5|39|71171.10|0.07|0.06|N|O|1997-04-28|1997-05-30|1997-05-03|TAKE BACK RETURN|MAIL|regular requests. slyly special inst +11011|172485|5003|1|16|24919.68|0.05|0.08|R|F|1992-05-27|1992-08-01|1992-05-29|NONE|FOB|xpress, quiet deposit +11011|140442|7985|2|50|74122.00|0.07|0.02|R|F|1992-08-18|1992-08-11|1992-09-02|COLLECT COD|MAIL|nd the furiously ironic +11011|723|5724|3|36|58453.92|0.06|0.05|R|F|1992-08-02|1992-06-28|1992-08-15|TAKE BACK RETURN|TRUCK|unusual, pending foxes cajole unusual, un +11011|141985|4500|4|29|58782.42|0.00|0.02|R|F|1992-05-27|1992-07-06|1992-06-26|COLLECT COD|RAIL|ts above th +11011|128974|3999|5|14|28041.58|0.03|0.08|A|F|1992-08-30|1992-08-03|1992-09-08|NONE|SHIP|dolites. express, regular orbits agai +11011|57839|7840|6|12|21561.96|0.08|0.06|A|F|1992-05-22|1992-08-01|1992-06-02|DELIVER IN PERSON|FOB|ully ironic theodolites about th +11011|95939|3467|7|31|59982.83|0.08|0.01|R|F|1992-06-18|1992-06-19|1992-06-23|TAKE BACK RETURN|FOB| instructions. final r +11012|40913|8426|1|47|87133.77|0.06|0.06|N|O|1998-07-25|1998-05-23|1998-08-01|NONE|AIR| about the ironi +11012|17062|7063|2|49|47973.94|0.07|0.08|N|O|1998-07-14|1998-06-14|1998-08-08|COLLECT COD|REG AIR| final dependencies. special pack +11013|44071|6576|1|2|2030.14|0.08|0.05|R|F|1994-07-24|1994-06-09|1994-08-02|DELIVER IN PERSON|AIR|ges nag slyly even +11014|32212|2213|1|43|49201.03|0.04|0.02|A|F|1993-12-16|1993-11-15|1993-12-27|COLLECT COD|RAIL|kages haggle +11014|170763|8315|2|9|16503.84|0.10|0.05|A|F|1993-12-12|1993-10-09|1994-01-06|NONE|TRUCK|l asymptotes. slyly ev +11014|6997|9498|3|20|38079.80|0.02|0.00|A|F|1993-09-24|1993-12-03|1993-09-28|DELIVER IN PERSON|RAIL|y final warhorses after the special +11014|184056|6575|4|36|41041.80|0.04|0.01|R|F|1993-11-10|1993-11-05|1993-12-09|TAKE BACK RETURN|REG AIR| carefully final d +11014|25466|5467|5|5|6957.30|0.08|0.07|A|F|1993-09-18|1993-10-13|1993-09-19|NONE|REG AIR|y around the blit +11015|138737|8738|1|16|28411.68|0.04|0.05|N|O|1997-12-03|1997-11-30|1997-12-26|DELIVER IN PERSON|SHIP|lyly final accounts are blithel +11015|152427|9973|2|16|23670.72|0.05|0.07|N|O|1997-10-06|1997-10-19|1997-10-28|NONE|SHIP|carefully +11015|25706|8209|3|15|24475.50|0.10|0.02|N|O|1998-01-06|1997-11-15|1998-01-18|COLLECT COD|SHIP|s. depths na +11015|39006|6516|4|43|40635.00|0.08|0.03|N|O|1997-09-22|1997-12-11|1997-09-24|COLLECT COD|REG AIR|thely. slyly bold theodolite +11015|171796|1797|5|13|24281.27|0.08|0.04|N|O|1997-10-02|1997-11-25|1997-10-31|TAKE BACK RETURN|MAIL|he always final foxes? silent deposits +11040|170940|8492|1|48|96525.12|0.03|0.02|N|O|1995-11-13|1996-01-14|1995-12-09|TAKE BACK RETURN|SHIP|sly ironic requ +11040|186364|1401|2|19|27556.84|0.07|0.08|N|O|1996-02-11|1995-12-03|1996-02-27|NONE|RAIL|inal deposits. carefully bold asymptot +11040|10168|5171|3|21|22641.36|0.03|0.06|N|O|1996-01-15|1995-12-12|1996-02-06|TAKE BACK RETURN|MAIL|ly pending accounts. furiously slow reques +11040|77456|7457|4|49|70239.05|0.04|0.01|N|O|1996-02-14|1996-01-18|1996-02-27|COLLECT COD|MAIL|deposits detect fluffily e +11041|47470|7471|1|40|56698.80|0.03|0.01|N|O|1997-06-29|1997-05-29|1997-07-27|NONE|SHIP| blithely fluffily +11041|18491|8492|2|10|14094.90|0.10|0.06|N|O|1997-05-30|1997-05-29|1997-06-27|COLLECT COD|TRUCK| ironic accounts alongsid +11041|168529|8530|3|9|14377.68|0.04|0.02|N|O|1997-07-05|1997-06-02|1997-07-19|DELIVER IN PERSON|FOB|egrate furio +11041|54440|9451|4|24|33466.56|0.06|0.03|N|O|1997-04-17|1997-05-13|1997-04-18|COLLECT COD|MAIL|its wake. blithely fin +11041|158840|3871|5|12|22786.08|0.08|0.03|N|O|1997-05-18|1997-05-06|1997-06-10|TAKE BACK RETURN|SHIP|was fluffily pending +11042|8030|531|1|6|5628.18|0.04|0.08|N|O|1998-06-03|1998-07-22|1998-06-05|TAKE BACK RETURN|SHIP|ep furiously re +11042|156474|1505|2|49|74993.03|0.03|0.04|N|O|1998-07-04|1998-07-24|1998-07-14|NONE|SHIP| orbits. fluffily +11042|42096|7105|3|49|50866.41|0.04|0.07|N|O|1998-05-30|1998-06-30|1998-06-19|DELIVER IN PERSON|SHIP|ng, final asymptotes. regular, ex +11042|95673|692|4|41|68415.47|0.02|0.05|N|O|1998-07-29|1998-07-14|1998-08-01|COLLECT COD|RAIL|o beans are s +11043|115203|7715|1|23|28018.60|0.03|0.06|R|F|1995-03-17|1995-04-30|1995-03-29|DELIVER IN PERSON|SHIP|the bold ideas sleep against the fur +11043|2343|9844|2|24|29888.16|0.07|0.04|R|F|1995-02-24|1995-05-11|1995-02-25|NONE|FOB|he regular, unusual packages a +11043|167568|5117|3|23|37617.88|0.04|0.03|R|F|1995-05-30|1995-05-19|1995-06-08|DELIVER IN PERSON|TRUCK|nooze furiously pen +11043|101050|8581|4|21|22072.05|0.01|0.05|R|F|1995-04-26|1995-04-29|1995-05-20|DELIVER IN PERSON|RAIL|ments. final requests sleep into the even +11044|119582|4605|1|37|59258.46|0.07|0.01|R|F|1992-08-31|1992-08-08|1992-09-03|DELIVER IN PERSON|FOB|s along the fur +11044|8460|8461|2|6|8210.76|0.03|0.00|R|F|1992-08-22|1992-07-30|1992-09-21|TAKE BACK RETURN|MAIL|ntly ironic attainments +11044|174977|7495|3|15|30779.55|0.01|0.02|A|F|1992-09-07|1992-08-12|1992-10-02|NONE|FOB|y final platelets are blithely caref +11045|9629|7130|1|36|55390.32|0.03|0.00|A|F|1992-05-09|1992-05-14|1992-05-29|COLLECT COD|TRUCK|after the pack +11045|23120|5623|2|16|16689.92|0.04|0.02|A|F|1992-07-23|1992-05-04|1992-08-06|DELIVER IN PERSON|RAIL|eposits detect quick +11045|175517|5518|3|22|35035.22|0.03|0.00|A|F|1992-05-16|1992-05-04|1992-06-10|NONE|MAIL|s play carefully. theodolites +11045|100859|5880|4|5|9299.25|0.00|0.03|R|F|1992-06-11|1992-05-12|1992-07-05|NONE|MAIL|refully final deposits boost ar +11045|134456|9483|5|46|68560.70|0.06|0.06|R|F|1992-04-15|1992-05-06|1992-04-30|COLLECT COD|RAIL|requests among the furiously final excuse +11045|191187|1188|6|18|23007.24|0.03|0.07|R|F|1992-04-09|1992-05-17|1992-04-12|NONE|SHIP|olites integrate slyly express, speci +11045|73077|5585|7|27|28351.89|0.06|0.04|R|F|1992-06-26|1992-05-24|1992-07-18|NONE|RAIL|asymptotes. blithely even excuses are qui +11046|195577|5578|1|46|76938.22|0.06|0.03|N|O|1997-08-01|1997-08-24|1997-08-11|NONE|RAIL|gular, bold accounts grow evenl +11046|48857|1362|2|33|59593.05|0.07|0.05|N|O|1997-10-06|1997-08-23|1997-10-22|TAKE BACK RETURN|TRUCK|ronic foxes. regul +11046|131772|4286|3|45|81169.65|0.02|0.02|N|O|1997-08-03|1997-07-21|1997-08-21|TAKE BACK RETURN|TRUCK|haggle. asymptotes use fluffily according +11046|83996|1521|4|24|47519.76|0.02|0.04|N|O|1997-09-21|1997-08-02|1997-10-14|TAKE BACK RETURN|MAIL|ckly regular asymptotes breach furi +11046|104337|1868|5|4|5365.32|0.04|0.02|N|O|1997-09-08|1997-09-09|1997-10-06|NONE|AIR|furious deposits. evenly f +11046|183885|6404|6|48|94506.24|0.02|0.04|N|O|1997-08-14|1997-08-22|1997-08-21|TAKE BACK RETURN|RAIL|ever. quickly regular pinto beans +11046|150398|399|7|18|26071.02|0.08|0.02|N|O|1997-10-08|1997-09-09|1997-10-12|COLLECT COD|AIR|ly quickly +11047|125940|5941|1|34|66841.96|0.05|0.08|A|F|1994-03-29|1994-02-04|1994-04-27|NONE|FOB|boost against the regula +11047|65936|949|2|15|28528.95|0.06|0.06|R|F|1994-02-08|1994-01-20|1994-03-09|TAKE BACK RETURN|SHIP|dencies. regular accou +11047|185685|8204|3|4|7082.72|0.09|0.02|R|F|1994-01-14|1994-02-01|1994-01-30|COLLECT COD|AIR|never special asymptotes. p +11072|142734|7763|1|37|65739.01|0.04|0.02|N|O|1996-09-26|1996-09-29|1996-10-13|NONE|RAIL|ely after the quickly final instructions. c +11072|125993|8506|2|34|68645.66|0.00|0.04|N|O|1996-07-21|1996-08-31|1996-08-03|DELIVER IN PERSON|AIR| use carefully unusual p +11072|151661|6692|3|29|49667.14|0.01|0.04|N|O|1996-08-10|1996-08-13|1996-08-26|TAKE BACK RETURN|SHIP|ss the carefully special instructions +11072|153937|8968|4|21|41809.53|0.06|0.06|N|O|1996-11-08|1996-09-14|1996-11-09|TAKE BACK RETURN|REG AIR|ending platelets nag furiously enticing +11072|5902|3403|5|48|86779.20|0.03|0.02|N|O|1996-08-12|1996-10-03|1996-08-21|NONE|SHIP|l packages wake ideas. furiou +11073|142790|7819|1|40|73311.60|0.04|0.00|R|F|1995-01-09|1995-01-08|1995-01-16|NONE|TRUCK|ages against the even ideas sleep quiet +11073|66632|9139|2|5|7993.15|0.07|0.04|A|F|1995-03-24|1995-01-08|1995-04-17|NONE|TRUCK|egular pinto beans are carefully against t +11073|67957|464|3|43|82772.85|0.05|0.04|A|F|1995-03-15|1995-02-26|1995-03-17|NONE|MAIL|ges are furiousl +11073|148643|1158|4|37|62590.68|0.03|0.04|R|F|1994-12-16|1995-01-03|1995-01-14|DELIVER IN PERSON|SHIP|ounts. blithely thin pa +11074|159942|9943|1|46|92089.24|0.06|0.01|N|O|1995-06-23|1995-07-20|1995-07-19|COLLECT COD|MAIL|y above the caref +11074|130768|3282|2|18|32377.68|0.04|0.02|N|O|1995-08-15|1995-08-11|1995-08-24|TAKE BACK RETURN|MAIL|ave to integrat +11074|16100|1103|3|44|44708.40|0.08|0.01|N|O|1995-08-11|1995-07-11|1995-08-24|NONE|RAIL|leep carefully acro +11074|192297|2298|4|44|61128.76|0.10|0.06|N|O|1995-07-13|1995-08-28|1995-07-30|NONE|REG AIR|haggle stealthily slyly express requests. +11074|132508|2509|5|24|36972.00|0.08|0.07|N|O|1995-08-10|1995-08-03|1995-08-20|NONE|MAIL|cross the even reque +11074|49008|6521|6|48|45936.00|0.02|0.02|N|O|1995-10-04|1995-08-25|1995-10-24|DELIVER IN PERSON|RAIL|ckages. evenly daring platelets according +11075|126591|4128|1|40|64703.60|0.01|0.04|N|O|1996-04-25|1996-05-15|1996-05-23|COLLECT COD|RAIL|ding requests nod +11075|199146|1666|2|29|36109.06|0.03|0.05|N|O|1996-04-12|1996-05-05|1996-04-23|TAKE BACK RETURN|MAIL|ts are carefully among the furiously ironi +11075|34817|7321|3|37|64816.97|0.10|0.07|N|O|1996-05-19|1996-05-04|1996-05-29|COLLECT COD|SHIP|le furiously around the even d +11075|162931|2932|4|45|89726.85|0.09|0.06|N|O|1996-03-20|1996-04-28|1996-04-03|COLLECT COD|RAIL|le furiousl +11076|97883|393|1|26|48902.88|0.10|0.05|R|F|1994-09-28|1994-11-02|1994-10-22|TAKE BACK RETURN|SHIP|eep among the hockey p +11076|112608|7631|2|8|12964.80|0.00|0.01|A|F|1994-08-22|1994-11-01|1994-09-05|DELIVER IN PERSON|MAIL|s haggle slyly ironic deposits. slyl +11077|171691|9243|1|45|79321.05|0.00|0.05|R|F|1994-07-03|1994-04-22|1994-07-10|NONE|FOB| ironic de +11078|75669|5670|1|28|46050.48|0.06|0.04|A|F|1992-08-06|1992-08-12|1992-08-07|TAKE BACK RETURN|RAIL|xcuses. ironic Tire +11078|156173|1204|2|40|49166.80|0.02|0.02|A|F|1992-08-22|1992-08-20|1992-09-11|COLLECT COD|REG AIR|arefully. quickly ex +11079|22488|2489|1|3|4231.44|0.01|0.03|N|O|1997-11-26|1997-10-22|1997-12-08|DELIVER IN PERSON|SHIP|never even pinto beans. quickly express a +11079|153485|3486|2|35|53846.80|0.06|0.05|N|O|1997-12-06|1997-10-08|1997-12-18|NONE|FOB|the foxes eat carefully +11079|20491|492|3|42|59282.58|0.05|0.02|N|O|1997-11-30|1997-10-26|1997-12-21|COLLECT COD|FOB| furiously. pending ideas cajole slyl +11104|197058|9578|1|26|30031.30|0.00|0.05|N|O|1998-09-08|1998-09-06|1998-09-16|TAKE BACK RETURN|FOB|kages. blithely cl +11105|31064|6071|1|17|16916.02|0.03|0.04|N|O|1996-03-26|1996-02-07|1996-04-25|COLLECT COD|MAIL|ngside of the stealthily final +11106|136107|8621|1|10|11431.00|0.05|0.00|N|O|1995-06-27|1995-06-07|1995-07-21|COLLECT COD|SHIP|kages. slyly regular platelets ar +11106|146654|4197|2|35|59522.75|0.03|0.02|R|F|1995-04-16|1995-06-19|1995-05-08|TAKE BACK RETURN|SHIP|ole slyly. slyly specia +11107|119459|1971|1|27|39918.15|0.01|0.06|N|O|1995-11-19|1996-01-20|1995-12-16|DELIVER IN PERSON|REG AIR|posits. reque +11107|131246|3760|2|2|2554.48|0.05|0.05|N|O|1995-11-04|1995-12-26|1995-11-14|NONE|REG AIR|s shall have to sleep slyly before the +11107|41242|8755|3|23|27214.52|0.05|0.07|N|O|1995-11-27|1995-12-03|1995-12-25|NONE|AIR|arefully ironic foxes gro +11108|194541|9580|1|37|60514.98|0.06|0.04|R|F|1992-08-26|1992-10-08|1992-09-07|COLLECT COD|MAIL|he instructions haggle about the carefull +11108|45114|123|2|39|41305.29|0.03|0.06|A|F|1992-10-26|1992-11-05|1992-11-12|DELIVER IN PERSON|TRUCK|ckages. quickly ironic asymptotes wak +11108|21992|9499|3|15|28709.85|0.08|0.07|R|F|1992-12-06|1992-11-12|1992-12-10|NONE|SHIP|thely blithely express packages. slyly f +11108|3023|8024|4|4|3704.08|0.08|0.03|R|F|1992-11-27|1992-10-28|1992-12-08|TAKE BACK RETURN|AIR|accounts: +11108|4365|4366|5|41|52043.76|0.06|0.08|A|F|1992-10-25|1992-09-23|1992-11-21|NONE|TRUCK|e. furiously ironic accounts are. furi +11108|149161|6704|6|19|22993.04|0.00|0.00|R|F|1992-10-05|1992-10-05|1992-10-19|TAKE BACK RETURN|TRUCK|al theodolites nag fluffily bold depo +11108|132441|9981|7|24|35362.56|0.00|0.06|R|F|1992-11-24|1992-10-03|1992-12-06|NONE|RAIL|. bold excuses are ruthlessly express, pend +11109|135663|5664|1|3|5095.98|0.09|0.07|R|F|1995-03-24|1995-05-09|1995-04-03|NONE|AIR|eas-- evenly even excuses mold caref +11109|78684|8685|2|1|1662.68|0.06|0.05|R|F|1995-03-21|1995-05-31|1995-04-13|NONE|SHIP|nts wake slyly pending instructions. foxes +11110|54990|4991|1|2|3889.98|0.10|0.03|N|O|1996-09-25|1996-08-08|1996-10-18|NONE|AIR|ns! bold courts besid +11110|9449|1950|2|33|44828.52|0.09|0.07|N|O|1996-09-01|1996-07-26|1996-09-21|COLLECT COD|RAIL|s about the quickly express deposits gro +11110|199155|6713|3|21|26337.15|0.03|0.06|N|O|1996-10-07|1996-08-02|1996-10-30|NONE|TRUCK|beans are among the thin de +11110|194473|4474|4|6|9404.82|0.03|0.03|N|O|1996-10-07|1996-07-27|1996-10-14|COLLECT COD|REG AIR|lithely regular ideas. dependencies sub +11110|107501|5032|5|41|61848.50|0.05|0.04|N|O|1996-07-15|1996-09-13|1996-07-22|TAKE BACK RETURN|REG AIR|ay accordin +11110|162643|192|6|18|30701.52|0.01|0.01|N|O|1996-07-21|1996-08-18|1996-07-30|COLLECT COD|MAIL| among the blithely +11111|72329|7344|1|39|50751.48|0.06|0.07|A|F|1995-02-03|1995-04-12|1995-02-24|NONE|FOB|ress instructions are according to the car +11111|21492|6497|2|25|35337.25|0.00|0.03|A|F|1995-03-24|1995-04-08|1995-03-31|DELIVER IN PERSON|MAIL|ring the pinto beans are careful +11111|13370|8373|3|1|1283.37|0.01|0.06|A|F|1995-02-19|1995-03-13|1995-03-03|TAKE BACK RETURN|MAIL|uses among the deposits ca +11111|99611|9612|4|16|25769.76|0.10|0.04|A|F|1995-05-10|1995-04-17|1995-05-15|NONE|MAIL|arefully even excuses wake. blithel +11136|30422|2926|1|50|67621.00|0.07|0.08|R|F|1994-01-23|1994-02-02|1994-02-20|COLLECT COD|FOB|y express packages ab +11137|126867|6868|1|3|5681.58|0.08|0.08|R|F|1992-12-07|1993-02-17|1993-01-04|COLLECT COD|RAIL|s haggle furiously. f +11137|43946|1459|2|2|3779.88|0.00|0.06|A|F|1993-01-06|1993-01-01|1993-01-22|COLLECT COD|AIR|heodolites cajole about the pendi +11137|186555|9074|3|19|31189.45|0.07|0.04|R|F|1992-12-16|1993-01-13|1993-01-06|COLLECT COD|SHIP|tructions wake carefully among the reg +11137|14031|6533|4|28|26460.84|0.02|0.04|R|F|1993-02-25|1993-01-20|1993-03-21|COLLECT COD|AIR|fter the regular accounts. car +11137|12405|7408|5|47|61917.80|0.04|0.04|A|F|1993-02-03|1993-01-07|1993-03-01|NONE|SHIP|unts wake furiously. slyly pending pin +11137|88880|1389|6|32|59804.16|0.04|0.08|A|F|1993-03-05|1993-01-20|1993-03-23|TAKE BACK RETURN|TRUCK|carefully about the instructio +11137|308|309|7|31|37457.30|0.04|0.05|A|F|1993-01-06|1993-01-04|1993-01-13|DELIVER IN PERSON|RAIL|es promise blithely +11138|174350|1902|1|40|56974.00|0.06|0.06|R|F|1995-05-12|1995-04-13|1995-05-21|NONE|TRUCK|ut the carefully even orbits wake caref +11138|87867|7868|2|48|89033.28|0.07|0.05|N|F|1995-06-07|1995-05-05|1995-07-05|NONE|FOB|ions detect. unusual foxes nag daringly +11138|169532|4565|3|9|14413.77|0.05|0.00|R|F|1995-05-04|1995-05-19|1995-05-10|DELIVER IN PERSON|FOB|ickly carefully +11139|55505|5506|1|15|21907.50|0.05|0.08|N|O|1998-08-03|1998-07-07|1998-08-16|NONE|TRUCK| unusual p +11139|63645|1164|2|39|62736.96|0.08|0.03|N|O|1998-09-09|1998-08-15|1998-10-02|TAKE BACK RETURN|SHIP|gular ideas engage flu +11139|65302|2821|3|13|16474.90|0.10|0.06|N|O|1998-07-01|1998-07-06|1998-07-19|TAKE BACK RETURN|SHIP|s packages. carefully specia +11139|114018|1552|4|17|17544.17|0.10|0.05|N|O|1998-09-15|1998-08-07|1998-10-03|TAKE BACK RETURN|TRUCK|unusual pinto beans integrate +11140|185779|5780|1|25|46619.25|0.06|0.02|N|O|1997-10-25|1997-09-30|1997-10-28|TAKE BACK RETURN|TRUCK|atelets. blithely regular exc +11140|174923|4924|2|16|31966.72|0.07|0.06|N|O|1997-08-23|1997-10-04|1997-09-11|TAKE BACK RETURN|SHIP|fully even sentiments. slyly even foxes +11140|117237|4771|3|9|11288.07|0.08|0.03|N|O|1997-10-07|1997-08-28|1997-10-14|DELIVER IN PERSON|TRUCK|ix slyly pending deposits. fluffily u +11140|1927|4428|4|9|16460.28|0.07|0.01|N|O|1997-08-19|1997-09-06|1997-09-17|NONE|AIR|ic decoys alongside of the ironic, +11140|173588|8623|5|33|54832.14|0.02|0.00|N|O|1997-08-15|1997-09-28|1997-09-10|TAKE BACK RETURN|AIR|d foxes wake blithely +11140|77440|2455|6|13|18426.72|0.10|0.01|N|O|1997-10-30|1997-10-09|1997-11-13|DELIVER IN PERSON|TRUCK|packages. furiously +11140|129611|4636|7|31|50858.91|0.10|0.08|N|O|1997-08-27|1997-09-23|1997-09-18|TAKE BACK RETURN|SHIP|oss the blithe, regular hockey player +11141|171369|1370|1|33|47531.88|0.07|0.02|N|O|1998-04-27|1998-03-03|1998-05-06|TAKE BACK RETURN|FOB|requests a +11141|184589|4590|2|11|18409.38|0.06|0.05|N|O|1998-04-20|1998-02-19|1998-05-14|COLLECT COD|RAIL|riously ironic courts? c +11141|175434|2986|3|2|3018.86|0.03|0.01|N|O|1998-05-16|1998-04-08|1998-05-27|NONE|FOB|ully ruthless accounts sleep slyl +11142|62787|5294|1|48|83989.44|0.05|0.07|N|O|1997-12-06|1997-12-05|1997-12-14|TAKE BACK RETURN|SHIP|jole furiously against the express a +11142|53183|3184|2|49|55672.82|0.08|0.07|N|O|1997-11-11|1997-12-24|1997-12-01|NONE|RAIL| sauternes. carefully +11142|44833|2346|3|9|16000.47|0.02|0.01|N|O|1997-11-29|1997-12-23|1997-12-20|TAKE BACK RETURN|MAIL| sleep along +11142|98552|3571|4|29|44965.95|0.01|0.06|N|O|1997-10-16|1997-11-04|1997-10-30|TAKE BACK RETURN|AIR|ons haggle attainments. +11142|159591|9592|5|44|72625.96|0.06|0.02|N|O|1997-11-17|1997-11-28|1997-11-21|TAKE BACK RETURN|SHIP|ter the final r +11142|30987|988|6|37|70965.26|0.06|0.04|N|O|1997-10-19|1997-11-19|1997-11-11|TAKE BACK RETURN|SHIP|xpress courts along the re +11142|185421|7940|7|44|66282.48|0.04|0.01|N|O|1997-11-17|1997-12-06|1997-11-29|TAKE BACK RETURN|TRUCK|ithely even packages alongsid +11143|160967|6000|1|40|81118.40|0.09|0.00|R|F|1993-03-26|1993-01-26|1993-04-24|COLLECT COD|FOB|re. final packages haggle furiously. pinto +11143|160689|8238|2|38|66487.84|0.10|0.04|A|F|1992-12-22|1993-02-10|1993-01-16|DELIVER IN PERSON|SHIP|ronic deposits haggle. packages boost sl +11143|97914|424|3|34|65004.94|0.04|0.02|A|F|1993-02-05|1993-02-17|1993-02-14|TAKE BACK RETURN|MAIL|e silent dependencies. quietly special th +11143|30185|186|4|1|1115.18|0.05|0.08|R|F|1992-12-16|1993-01-07|1993-01-08|NONE|AIR|uriously regular +11168|65350|5351|1|8|10522.80|0.04|0.05|R|F|1993-01-21|1992-12-13|1993-01-22|NONE|AIR|ely furious instructions. furiously expr +11168|136809|9323|2|47|86752.60|0.01|0.05|R|F|1993-01-20|1992-12-07|1993-02-05|DELIVER IN PERSON|REG AIR|al courts cajole af +11169|145967|3510|1|35|70453.60|0.05|0.06|R|F|1993-08-14|1993-07-23|1993-08-19|NONE|REG AIR| blithely. carefully expres +11169|56930|1941|2|1|1886.93|0.00|0.06|R|F|1993-09-11|1993-08-20|1993-09-20|DELIVER IN PERSON|SHIP| deposits haggle. fluffily even p +11169|12311|7314|3|39|47709.09|0.10|0.04|A|F|1993-08-13|1993-06-22|1993-09-09|NONE|FOB| instructions. +11169|102406|4917|4|41|57744.40|0.10|0.02|R|F|1993-06-05|1993-07-05|1993-06-13|TAKE BACK RETURN|TRUCK|cuses. regular excuse +11170|162157|2158|1|40|48766.00|0.03|0.07|N|O|1997-09-07|1997-09-15|1997-09-08|NONE|FOB|ests. slyly exp +11170|170261|262|2|25|33281.50|0.08|0.01|N|O|1997-11-03|1997-10-01|1997-11-27|DELIVER IN PERSON|REG AIR|refully daring pearls wake quickly acco +11170|171946|4464|3|4|8071.76|0.00|0.03|N|O|1997-09-29|1997-09-17|1997-10-24|COLLECT COD|AIR|the regular packages. fluffily +11170|81208|3717|4|28|33297.60|0.10|0.06|N|O|1997-08-10|1997-09-12|1997-08-21|TAKE BACK RETURN|MAIL|leep instead of the furiously ir +11171|195819|3377|1|36|68933.16|0.08|0.08|N|O|1995-09-11|1995-09-28|1995-09-16|NONE|MAIL|ccording to the +11171|125866|5867|2|35|66215.10|0.08|0.02|N|O|1995-09-21|1995-09-15|1995-10-15|NONE|AIR| notornis could nag about the ironic dep +11172|190772|8330|1|22|40980.94|0.09|0.01|N|O|1998-03-09|1998-02-09|1998-04-06|NONE|REG AIR|carefully +11172|92170|7189|2|23|26729.91|0.10|0.07|N|O|1998-02-06|1998-02-02|1998-02-15|NONE|FOB|d foxes will ha +11172|92688|2689|3|35|58823.80|0.08|0.02|N|O|1998-02-02|1998-03-28|1998-03-02|TAKE BACK RETURN|FOB|ackages among the blithely +11172|5045|7546|4|32|30401.28|0.03|0.01|N|O|1998-03-06|1998-02-13|1998-04-01|COLLECT COD|MAIL|always enticing requests after +11173|75244|5245|1|6|7315.44|0.10|0.06|R|F|1992-04-07|1992-06-29|1992-04-09|NONE|MAIL|cies. blithely ironic sentiments +11173|23844|6347|2|26|45963.84|0.08|0.05|A|F|1992-05-28|1992-05-07|1992-06-25|TAKE BACK RETURN|AIR|ng pinto bean +11173|144655|7170|3|32|54388.80|0.04|0.04|A|F|1992-07-02|1992-05-12|1992-07-31|TAKE BACK RETURN|RAIL|unusual packages haggle furious +11173|13343|8346|4|16|20101.44|0.05|0.03|R|F|1992-05-30|1992-06-10|1992-06-09|COLLECT COD|AIR| instructions. regular packages sleep +11173|40520|8033|5|9|13144.68|0.05|0.06|R|F|1992-04-01|1992-05-11|1992-04-17|DELIVER IN PERSON|SHIP|iously unusu +11173|19623|7127|6|39|60162.18|0.06|0.04|R|F|1992-05-24|1992-05-05|1992-06-22|TAKE BACK RETURN|MAIL|ons. pending deposits wake a +11173|3196|3197|7|29|31876.51|0.04|0.08|R|F|1992-07-23|1992-05-25|1992-08-07|TAKE BACK RETURN|MAIL|fully express foxes. regular +11174|113431|965|1|22|31777.46|0.01|0.06|A|F|1994-04-24|1994-05-19|1994-05-10|TAKE BACK RETURN|REG AIR|fter the waters. regular +11174|23936|8941|2|2|3719.86|0.04|0.05|R|F|1994-05-30|1994-05-19|1994-06-27|COLLECT COD|MAIL| the deposit +11174|84065|1590|3|18|18883.08|0.02|0.04|A|F|1994-05-31|1994-05-12|1994-06-14|NONE|RAIL|carefully bold dependencies use packages. r +11174|64889|9902|4|8|14831.04|0.01|0.00|R|F|1994-04-22|1994-07-04|1994-05-07|NONE|TRUCK|sits. accounts boost quickly ab +11174|180491|5528|5|31|48716.19|0.01|0.00|R|F|1994-06-23|1994-05-16|1994-07-16|TAKE BACK RETURN|AIR|t the ironic deposits cajole slyly across +11174|99052|6580|6|14|14714.70|0.07|0.08|A|F|1994-08-08|1994-05-11|1994-08-12|NONE|RAIL|. slyly daring requests +11175|134377|4378|1|6|8468.22|0.04|0.02|N|O|1998-03-08|1998-05-13|1998-03-31|COLLECT COD|TRUCK|mong the slyl +11175|74131|6639|2|6|6630.78|0.05|0.00|N|O|1998-04-23|1998-05-25|1998-05-19|TAKE BACK RETURN|REG AIR|ms wake quickly. furiously +11175|115322|2856|3|26|34770.32|0.00|0.00|N|O|1998-05-27|1998-05-05|1998-05-31|TAKE BACK RETURN|TRUCK|tegrate along the ironi +11200|29324|1827|1|36|45119.52|0.10|0.01|N|O|1997-04-14|1997-04-04|1997-04-18|COLLECT COD|TRUCK| theodolites wake. carefull +11200|42326|4831|2|3|3804.96|0.02|0.00|N|O|1997-03-14|1997-04-28|1997-04-03|COLLECT COD|SHIP|ies. fluffily regular dependencies are fina +11200|162319|4836|3|47|64921.57|0.05|0.04|N|O|1997-04-28|1997-05-01|1997-05-26|NONE|SHIP|posits. pending deposits sleep ironic +11201|176601|6602|1|2|3355.20|0.05|0.04|N|O|1996-12-21|1997-02-21|1996-12-27|DELIVER IN PERSON|AIR|ns. regular i +11202|29182|6689|1|39|43336.02|0.04|0.06|R|F|1992-04-29|1992-06-11|1992-05-13|NONE|MAIL| ideas wake fluffily around the +11202|50642|5653|2|44|70076.16|0.01|0.05|R|F|1992-06-22|1992-05-09|1992-07-16|DELIVER IN PERSON|SHIP|equests wake blithely +11202|135027|7541|3|38|40356.76|0.04|0.01|R|F|1992-06-23|1992-04-27|1992-07-12|COLLECT COD|SHIP|y ironic theodolites detect car +11203|71198|8720|1|39|45598.41|0.05|0.06|N|O|1996-09-06|1996-07-31|1996-09-29|NONE|SHIP|egular ideas sleep according to the fur +11203|24147|4148|2|19|20351.66|0.04|0.03|N|O|1996-07-26|1996-09-11|1996-08-09|COLLECT COD|REG AIR|g accounts cajole furiously +11204|34209|1719|1|22|25150.40|0.07|0.06|N|O|1998-11-19|1998-08-25|1998-12-18|TAKE BACK RETURN|REG AIR| deposits. carefully pending acc +11204|149204|6747|2|2|2506.40|0.09|0.04|N|O|1998-09-12|1998-09-30|1998-10-01|DELIVER IN PERSON|TRUCK| haggle furiously pending +11205|79806|2314|1|9|16072.20|0.03|0.08|N|O|1996-11-01|1996-11-05|1996-11-05|TAKE BACK RETURN|RAIL|he foxes at the even asymptotes haggle +11205|90659|660|2|9|14846.85|0.07|0.05|N|O|1996-10-20|1996-10-16|1996-11-10|COLLECT COD|AIR| ideas. fluffil +11205|92562|5072|3|34|52855.04|0.04|0.03|N|O|1996-11-20|1996-10-28|1996-12-16|COLLECT COD|TRUCK|ular forges affix boldly after the silent a +11206|176764|1799|1|33|60745.08|0.04|0.01|R|F|1995-04-20|1995-03-28|1995-05-11|TAKE BACK RETURN|REG AIR| accounts use slyly final, even pin +11206|57746|2757|2|22|37482.28|0.02|0.02|A|F|1995-02-16|1995-02-28|1995-03-06|DELIVER IN PERSON|RAIL|eposits. carefully special pinto b +11206|126517|4054|3|23|35500.73|0.03|0.05|A|F|1995-04-02|1995-01-29|1995-04-17|NONE|TRUCK|dolites-- carefully un +11206|168257|8258|4|27|35781.75|0.04|0.03|A|F|1995-01-07|1995-02-06|1995-01-14|TAKE BACK RETURN|MAIL| ironic deposits? dolph +11206|81802|4311|5|33|58865.40|0.08|0.03|A|F|1995-02-18|1995-03-16|1995-03-08|DELIVER IN PERSON|SHIP|beans. blithely iron +11207|8450|5951|1|40|54338.00|0.02|0.00|N|O|1996-07-23|1996-06-04|1996-08-13|DELIVER IN PERSON|RAIL|usy theodolites cajole against the regula +11207|8793|1294|2|15|25526.85|0.02|0.02|N|O|1996-04-19|1996-05-07|1996-05-14|NONE|FOB|uests cajole blithely express s +11207|174686|4687|3|19|33452.92|0.02|0.00|N|O|1996-07-21|1996-06-20|1996-08-15|NONE|REG AIR|yly regular accounts. excuses use. +11232|87149|2166|1|10|11361.40|0.00|0.04|N|O|1996-04-14|1996-03-30|1996-05-01|DELIVER IN PERSON|RAIL|sly about the furiously silent ide +11232|97892|5420|2|4|7559.56|0.02|0.05|N|O|1996-05-15|1996-03-22|1996-06-05|DELIVER IN PERSON|RAIL|ng. slyly regular theo +11232|56837|6838|3|29|52021.07|0.07|0.04|N|O|1996-05-21|1996-04-05|1996-06-03|TAKE BACK RETURN|REG AIR|. blithely regula +11232|52442|2443|4|7|9761.08|0.04|0.06|N|O|1996-05-15|1996-04-18|1996-05-29|TAKE BACK RETURN|RAIL|onic requests according to the sheaves wake +11233|151577|1578|1|17|27685.69|0.02|0.00|N|O|1995-09-12|1995-10-23|1995-09-19|DELIVER IN PERSON|FOB|usual reques +11233|138106|620|2|25|28602.50|0.05|0.03|N|O|1995-11-28|1995-10-30|1995-12-12|COLLECT COD|RAIL|, regular decoys. ruthlessly +11233|136030|1057|3|36|38377.08|0.10|0.02|N|O|1995-10-14|1995-10-26|1995-10-24|COLLECT COD|AIR|ar theodolites. +11234|52252|7263|1|36|43353.00|0.07|0.07|A|F|1993-04-12|1993-04-03|1993-05-01|DELIVER IN PERSON|REG AIR|nstructions. car +11234|191265|1266|2|9|12206.34|0.03|0.07|A|F|1993-05-17|1993-05-01|1993-05-26|NONE|AIR|y about the quickly regular attai +11234|179260|1778|3|29|38838.54|0.01|0.01|R|F|1993-05-16|1993-04-18|1993-05-26|TAKE BACK RETURN|AIR|usly pending theodolites +11235|141531|9074|1|15|23587.95|0.08|0.04|N|O|1996-05-27|1996-06-10|1996-06-03|NONE|REG AIR| packages +11235|104517|7028|2|28|42602.28|0.01|0.07|N|O|1996-05-23|1996-06-27|1996-06-13|NONE|SHIP|d dependencies. caref +11235|13092|8095|3|50|50254.50|0.10|0.01|N|O|1996-05-23|1996-06-01|1996-06-14|NONE|TRUCK|pinto beans hinder quickly even, iro +11235|35451|5452|4|9|12478.05|0.08|0.03|N|O|1996-05-29|1996-06-17|1996-06-06|DELIVER IN PERSON|SHIP|inal theodolites sleep furi +11235|23743|3744|5|48|80003.52|0.01|0.01|N|O|1996-05-16|1996-06-30|1996-06-01|TAKE BACK RETURN|MAIL|ly regular packages. slyl +11235|41608|6617|6|43|66632.80|0.00|0.06|N|O|1996-04-15|1996-06-01|1996-04-27|COLLECT COD|REG AIR|tegrate furiously accounts. c +11235|90799|8327|7|34|60852.86|0.05|0.01|N|O|1996-07-26|1996-06-23|1996-08-15|DELIVER IN PERSON|FOB|quests sleep furiously carefully fu +11236|51111|1112|1|17|18055.87|0.02|0.08|A|F|1993-11-23|1994-01-21|1993-11-29|NONE|MAIL|even instructions against the f +11236|8046|5547|2|19|18126.76|0.02|0.00|A|F|1993-12-29|1994-01-28|1994-01-20|COLLECT COD|MAIL|refully even dinos nod care +11236|27820|7821|3|46|80399.72|0.00|0.04|R|F|1993-11-05|1993-12-14|1993-11-30|TAKE BACK RETURN|SHIP|s according +11236|162441|7474|4|23|34579.12|0.07|0.08|R|F|1993-12-02|1994-01-08|1993-12-08|COLLECT COD|FOB|ding to the furiousl +11236|136678|9192|5|26|44581.42|0.06|0.00|R|F|1994-02-10|1993-12-17|1994-02-18|TAKE BACK RETURN|SHIP|st carefully regular deposits. qu +11236|141988|9531|6|34|69019.32|0.07|0.06|R|F|1993-11-13|1993-12-01|1993-11-15|TAKE BACK RETURN|MAIL| carefully regular foxes +11237|54501|9512|1|43|62586.50|0.05|0.06|N|O|1996-10-06|1996-08-01|1996-11-01|NONE|REG AIR|sly pending accounts use. furiously +11237|189682|9683|2|32|56693.76|0.05|0.03|N|O|1996-09-20|1996-07-21|1996-10-18|TAKE BACK RETURN|REG AIR| the fluffily p +11237|185168|5169|3|15|18797.40|0.01|0.06|N|O|1996-07-09|1996-08-14|1996-07-16|COLLECT COD|FOB|s. furiously ir +11237|117395|9907|4|8|11299.12|0.04|0.04|N|O|1996-06-29|1996-08-11|1996-06-30|TAKE BACK RETURN|TRUCK|according to the fluffily final +11238|130254|255|1|35|44948.75|0.01|0.05|N|O|1996-10-09|1996-10-16|1996-10-30|DELIVER IN PERSON|TRUCK|tect carefully again +11238|162312|2313|2|7|9620.17|0.04|0.01|N|O|1996-07-27|1996-09-19|1996-07-31|COLLECT COD|AIR|ly blithely unusual asymptot +11238|166116|8633|3|5|5910.55|0.09|0.05|N|O|1996-09-10|1996-08-28|1996-09-16|COLLECT COD|AIR|unts thrash. blithely final requ +11238|104440|4441|4|50|72222.00|0.09|0.07|N|O|1996-09-12|1996-09-05|1996-09-25|DELIVER IN PERSON|FOB|t instructions sublate fluffily fl +11238|107837|7838|5|2|3689.66|0.00|0.04|N|O|1996-10-17|1996-09-14|1996-10-18|TAKE BACK RETURN|SHIP|ely even id +11238|10373|374|6|17|21817.29|0.05|0.05|N|O|1996-11-01|1996-09-14|1996-11-06|COLLECT COD|REG AIR|ic sauternes haggle across t +11239|132016|4530|1|41|42968.41|0.04|0.05|R|F|1992-05-15|1992-04-14|1992-05-27|COLLECT COD|RAIL|y ironic pa +11239|182352|7389|2|39|55939.65|0.06|0.05|A|F|1992-04-08|1992-04-26|1992-05-04|DELIVER IN PERSON|RAIL| of the carefully final reque +11239|182476|4995|3|10|15584.70|0.08|0.04|A|F|1992-02-26|1992-04-03|1992-02-28|DELIVER IN PERSON|SHIP|cial somas. pinto beans may wak +11239|66906|6907|4|34|63678.60|0.00|0.05|R|F|1992-05-25|1992-04-11|1992-05-28|COLLECT COD|REG AIR|ly final deposits; f +11239|78481|8482|5|39|56919.72|0.08|0.03|R|F|1992-06-10|1992-04-02|1992-06-27|DELIVER IN PERSON|FOB|ithely. slyly regul +11239|17483|7484|6|5|7002.40|0.10|0.04|R|F|1992-05-13|1992-03-15|1992-05-24|NONE|REG AIR|he carefully regular requests. f +11239|33449|3450|7|40|55297.60|0.00|0.08|A|F|1992-05-05|1992-03-21|1992-05-29|NONE|AIR| foxes wake. slyly +11264|169411|9412|1|22|32569.02|0.08|0.07|N|O|1996-12-13|1996-10-03|1996-12-17|TAKE BACK RETURN|FOB|inst the quickly final reque +11264|89135|6660|2|11|12365.43|0.01|0.05|N|O|1996-10-04|1996-11-25|1996-10-25|TAKE BACK RETURN|TRUCK|nal, ironic requests wake a +11264|79359|6881|3|20|26767.00|0.00|0.02|N|O|1996-12-26|1996-11-18|1997-01-10|TAKE BACK RETURN|REG AIR|luffy patterns use careful +11264|170634|3152|4|26|44320.38|0.03|0.03|N|O|1996-11-11|1996-11-13|1996-11-30|TAKE BACK RETURN|REG AIR|nts haggle carefully across the u +11264|35445|7949|5|16|22087.04|0.03|0.08|N|O|1996-11-12|1996-11-13|1996-12-03|DELIVER IN PERSON|AIR| express theodolites. even accounts hag +11265|183060|3061|1|24|27433.44|0.07|0.02|N|O|1997-07-09|1997-08-03|1997-07-20|TAKE BACK RETURN|AIR|to the final +11265|73744|1266|2|29|49814.46|0.04|0.00|N|O|1997-07-18|1997-07-25|1997-07-19|NONE|MAIL|ke dependencies? slyly quick foxe +11265|9144|9145|3|4|4212.56|0.03|0.02|N|O|1997-07-21|1997-06-26|1997-08-15|DELIVER IN PERSON|FOB|ly ironic dolphi +11266|173342|3343|1|8|11322.72|0.00|0.04|N|O|1997-10-16|1997-10-24|1997-11-07|COLLECT COD|FOB|onic asymptotes sleep slyly furiousl +11267|19898|2400|1|3|5453.67|0.00|0.01|R|F|1992-05-28|1992-04-11|1992-06-23|NONE|REG AIR|ly express requ +11267|15506|3010|2|40|56860.00|0.01|0.01|A|F|1992-03-01|1992-03-28|1992-03-29|NONE|TRUCK|symptotes haggle furiously. careful +11268|74499|9514|1|12|17681.88|0.00|0.03|N|O|1998-10-13|1998-09-05|1998-10-15|TAKE BACK RETURN|TRUCK|carefully. deposits boost across th +11268|97786|5314|2|7|12486.46|0.01|0.01|N|O|1998-09-15|1998-08-10|1998-10-11|NONE|FOB|ully according to the blit +11268|77651|7652|3|48|78175.20|0.09|0.07|N|O|1998-10-06|1998-07-30|1998-11-02|COLLECT COD|REG AIR|ut the even excuses. final reque +11268|77680|7681|4|49|81226.32|0.10|0.05|N|O|1998-09-25|1998-09-03|1998-10-21|TAKE BACK RETURN|RAIL|ns are fluffily according to th +11269|78038|3053|1|31|31496.93|0.02|0.00|A|F|1992-08-06|1992-08-23|1992-08-12|TAKE BACK RETURN|TRUCK|ual theodolites are q +11269|182004|2005|2|33|35838.00|0.01|0.04|R|F|1992-07-26|1992-08-11|1992-07-30|NONE|FOB|lly. silent theodolite +11269|126442|6443|3|6|8810.64|0.01|0.06|R|F|1992-08-16|1992-08-23|1992-08-30|DELIVER IN PERSON|SHIP|r ideas wake furio +11269|106154|8665|4|41|47566.15|0.09|0.08|A|F|1992-09-18|1992-07-05|1992-09-19|DELIVER IN PERSON|RAIL|theodolites. care +11269|129780|2293|5|49|88679.22|0.07|0.03|A|F|1992-08-03|1992-08-20|1992-08-15|DELIVER IN PERSON|REG AIR|d, dogged pains are blithely. car +11269|8172|8173|6|34|36725.78|0.07|0.02|R|F|1992-08-30|1992-07-27|1992-09-12|TAKE BACK RETURN|FOB|lly regular deposits haggle carefully +11269|144659|7174|7|9|15332.85|0.01|0.03|R|F|1992-09-25|1992-06-26|1992-10-14|DELIVER IN PERSON|SHIP|ar foxes boost +11270|71997|9519|1|6|11813.94|0.03|0.01|N|O|1995-09-05|1995-09-23|1995-09-09|TAKE BACK RETURN|SHIP|deas. sly accounts integrate bl +11270|37320|9824|2|29|36462.28|0.09|0.06|N|O|1995-08-10|1995-09-06|1995-08-19|TAKE BACK RETURN|REG AIR|requests sleep quic +11270|28150|8151|3|39|42047.85|0.02|0.06|N|O|1995-10-04|1995-08-25|1995-10-07|TAKE BACK RETURN|SHIP| even pint +11270|110745|746|4|49|86031.26|0.10|0.02|N|O|1995-09-20|1995-08-21|1995-09-21|TAKE BACK RETURN|SHIP|he blithely even packages +11270|84215|6724|5|28|33577.88|0.02|0.03|N|O|1995-10-16|1995-09-25|1995-11-03|COLLECT COD|AIR|pending foxes use fluffily fluffily +11270|191662|1663|6|6|10521.96|0.09|0.01|N|O|1995-08-01|1995-08-19|1995-08-25|NONE|MAIL| haggle under the furiously express pack +11271|148623|6166|1|23|38447.26|0.00|0.04|N|O|1995-12-06|1995-12-19|1995-12-10|NONE|SHIP|refully above th +11271|99475|9476|2|17|25065.99|0.08|0.06|N|O|1995-12-15|1995-11-18|1995-12-30|DELIVER IN PERSON|REG AIR|c pinto beans. quickly regular depend +11271|61492|9011|3|45|65407.05|0.04|0.04|N|O|1996-01-22|1995-11-19|1996-02-09|DELIVER IN PERSON|TRUCK|y regular dependencies cajole furio +11271|79482|1990|4|41|59920.68|0.09|0.06|N|O|1996-01-15|1996-01-15|1996-01-18|COLLECT COD|TRUCK|ely even platelets. fluffily permanent idea +11271|48436|941|5|21|29073.03|0.04|0.02|N|O|1996-01-19|1995-12-13|1996-02-12|COLLECT COD|MAIL|xpress deposi +11271|60821|5834|6|2|3563.64|0.00|0.07|N|O|1996-01-21|1995-12-12|1996-02-15|TAKE BACK RETURN|MAIL|pendencies. careful +11271|12547|2548|7|25|36488.50|0.09|0.02|N|O|1995-12-11|1996-01-16|1995-12-12|NONE|REG AIR|dazzle ironically fu +11296|70172|5187|1|29|33122.93|0.03|0.02|R|F|1992-03-08|1992-02-11|1992-04-05|DELIVER IN PERSON|TRUCK|riously silent deposits han +11296|171725|1726|2|36|64681.92|0.02|0.06|A|F|1992-03-06|1992-03-29|1992-03-09|COLLECT COD|MAIL|, stealthy p +11296|178828|6380|3|35|66738.70|0.08|0.00|R|F|1992-02-17|1992-03-08|1992-02-26|NONE|FOB|counts. waters doze blithely instruct +11296|161987|1988|4|50|102449.00|0.00|0.07|A|F|1992-02-14|1992-03-21|1992-02-25|NONE|SHIP| packages wake quickly. furiou +11296|99577|2087|5|35|55179.95|0.07|0.03|A|F|1992-03-24|1992-03-19|1992-04-13|NONE|MAIL|yly above the ruthl +11296|184791|2346|6|41|76907.39|0.06|0.07|A|F|1992-03-09|1992-02-12|1992-04-07|NONE|FOB|egular asymptotes are carefully special req +11297|42178|4683|1|32|35845.44|0.08|0.04|R|F|1993-04-07|1993-03-20|1993-04-30|COLLECT COD|RAIL|ding, expres +11297|75480|7988|2|45|65496.60|0.08|0.01|R|F|1993-03-15|1993-03-11|1993-04-01|NONE|AIR|ndencies haggle caref +11298|36904|4414|1|34|62590.60|0.04|0.00|N|O|1998-03-09|1998-03-07|1998-03-26|DELIVER IN PERSON|AIR|ously even i +11298|44136|4137|2|17|18362.21|0.00|0.08|N|O|1998-02-08|1998-03-21|1998-02-26|COLLECT COD|AIR|. regular, +11298|187355|9874|3|32|46155.20|0.09|0.01|N|O|1998-01-29|1998-03-26|1998-02-02|NONE|RAIL|quests cajole quickly furiously careful +11298|65090|7597|4|43|45368.87|0.01|0.06|N|O|1998-01-18|1998-04-03|1998-02-08|COLLECT COD|MAIL|ffily even packages. quick +11298|156898|4444|5|15|29323.35|0.07|0.03|N|O|1998-03-05|1998-03-03|1998-03-30|DELIVER IN PERSON|SHIP|r dolphins play furi +11298|168694|1211|6|12|21152.28|0.06|0.07|N|O|1998-01-20|1998-03-21|1998-02-15|DELIVER IN PERSON|AIR|refully regular ideas +11299|114121|4122|1|42|47675.04|0.06|0.03|R|F|1993-12-02|1994-01-07|1993-12-04|COLLECT COD|FOB|l requests +11299|25646|3153|2|15|23574.60|0.07|0.07|R|F|1993-12-21|1993-12-13|1994-01-14|DELIVER IN PERSON|AIR|yly at the carefully ironic theodo +11299|17524|5028|3|45|64868.40|0.10|0.00|A|F|1993-12-03|1993-12-14|1993-12-13|COLLECT COD|REG AIR|y regular accounts. +11299|122763|5276|4|17|30357.92|0.05|0.05|A|F|1993-12-29|1994-02-03|1994-01-03|DELIVER IN PERSON|REG AIR| packages wake +11299|65332|345|5|38|49298.54|0.09|0.02|R|F|1994-03-09|1993-12-13|1994-03-13|TAKE BACK RETURN|MAIL|riously pending ex +11299|32371|7378|6|47|61258.39|0.01|0.07|A|F|1994-01-02|1994-02-01|1994-02-01|TAKE BACK RETURN|FOB|y final packages sleep express foxes. ironi +11299|56648|1659|7|10|16046.40|0.06|0.08|A|F|1994-01-12|1994-01-19|1994-02-10|DELIVER IN PERSON|RAIL|thely even theodolites! accounts h +11300|71283|8805|1|47|58951.16|0.03|0.05|N|O|1996-09-07|1996-08-31|1996-09-11|NONE|AIR|ic instructions! even, final +11301|83447|5956|1|24|34330.56|0.04|0.07|R|F|1992-07-05|1992-06-16|1992-07-06|NONE|MAIL|uctions are carefully about the fu +11301|85807|824|2|20|35856.00|0.02|0.00|R|F|1992-06-20|1992-06-15|1992-07-14|NONE|SHIP|egular excuses n +11301|148757|3786|3|22|39726.50|0.06|0.01|R|F|1992-03-28|1992-06-07|1992-04-13|NONE|TRUCK|s boost fluffily quickly bold dugouts. +11301|149006|9007|4|2|2110.00|0.05|0.08|A|F|1992-06-19|1992-05-10|1992-06-22|TAKE BACK RETURN|MAIL|deas use slyly accoun +11301|141630|6659|5|23|38447.49|0.01|0.00|A|F|1992-04-24|1992-05-13|1992-04-26|COLLECT COD|RAIL|lar foxes poach blithel +11301|166120|6121|6|33|39141.96|0.02|0.03|A|F|1992-06-23|1992-04-26|1992-06-28|DELIVER IN PERSON|FOB|ges. furiously pending theodolites wake +11302|41317|1318|1|39|49074.09|0.10|0.07|R|F|1994-04-23|1994-04-04|1994-05-04|DELIVER IN PERSON|AIR| express packages wake careful +11302|7682|183|2|16|25434.88|0.00|0.08|A|F|1994-04-11|1994-04-29|1994-05-07|NONE|AIR|lyly regular cou +11302|94802|9821|3|50|89840.00|0.08|0.01|A|F|1994-05-10|1994-04-01|1994-05-18|NONE|MAIL|posits wake according to th +11302|121522|4035|4|32|49392.64|0.10|0.06|A|F|1994-03-27|1994-05-24|1994-03-31|TAKE BACK RETURN|REG AIR|fily special sauternes. furiously fina +11302|8899|6400|5|27|48813.03|0.01|0.07|R|F|1994-06-30|1994-04-21|1994-07-06|DELIVER IN PERSON|MAIL|r the carefully p +11302|154128|1674|6|21|24824.52|0.03|0.00|A|F|1994-06-19|1994-05-13|1994-06-21|TAKE BACK RETURN|RAIL|lar asymptotes integrate carefully bli +11303|128731|8732|1|25|43993.25|0.06|0.05|R|F|1992-06-28|1992-06-24|1992-07-19|DELIVER IN PERSON|SHIP|packages: even requests doubt quietly aft +11303|172446|7481|2|23|34924.12|0.10|0.04|A|F|1992-07-14|1992-06-16|1992-07-19|TAKE BACK RETURN|SHIP|ts integrate slyly enticingly unusual as +11303|96992|2011|3|16|31823.84|0.09|0.05|R|F|1992-04-11|1992-05-08|1992-04-12|COLLECT COD|SHIP|l foxes cajole carefully atop th +11328|35060|2570|1|15|14925.90|0.06|0.06|R|F|1992-07-08|1992-05-04|1992-08-02|TAKE BACK RETURN|MAIL|silent deposits about the carefully bold +11329|1850|6851|1|27|47299.95|0.02|0.03|N|O|1995-10-27|1995-10-17|1995-11-07|TAKE BACK RETURN|FOB|special, regular dolphins +11329|77261|7262|2|38|47053.88|0.06|0.01|N|O|1995-11-04|1995-11-02|1995-11-07|NONE|RAIL|sly unusual accounts cajole slyly i +11329|110671|8205|3|42|70630.14|0.03|0.02|N|O|1995-10-01|1995-10-03|1995-10-11|DELIVER IN PERSON|AIR| quickly carefully regular deposits! fi +11329|37585|2592|4|32|48722.56|0.02|0.06|N|O|1995-08-19|1995-10-10|1995-09-04|COLLECT COD|RAIL|ress pinto be +11329|89847|7372|5|20|36736.80|0.04|0.02|N|O|1995-09-08|1995-09-17|1995-09-26|COLLECT COD|RAIL|c patterns. furi +11329|57006|9512|6|44|42372.00|0.01|0.05|N|O|1995-10-10|1995-10-08|1995-11-05|NONE|RAIL|tes boost against the quickly pending re +11330|43850|3851|1|3|5381.55|0.05|0.00|R|F|1992-07-15|1992-05-28|1992-07-28|DELIVER IN PERSON|REG AIR|ly final instructions. pe +11331|119367|1879|1|18|24954.48|0.09|0.01|N|O|1996-03-11|1996-03-15|1996-03-12|COLLECT COD|AIR|ly. carefully even multipliers after the +11332|6817|6818|1|42|72400.02|0.00|0.03|R|F|1994-11-18|1995-01-26|1994-12-02|DELIVER IN PERSON|AIR|nic asymptotes b +11332|157150|2181|2|8|9657.20|0.08|0.00|A|F|1994-12-26|1995-01-28|1995-01-12|TAKE BACK RETURN|REG AIR|y quick requests boost slyly. +11332|12522|5024|3|15|21517.80|0.05|0.06|R|F|1995-03-08|1994-12-28|1995-03-24|TAKE BACK RETURN|MAIL|eans haggle furiously +11332|50726|3232|4|5|8383.60|0.08|0.00|A|F|1995-03-05|1994-12-24|1995-03-11|DELIVER IN PERSON|SHIP|regular pinto bean +11332|135508|8022|5|3|4630.50|0.01|0.01|R|F|1995-01-22|1994-12-25|1995-02-21|COLLECT COD|FOB|ackages according to the finally f +11332|67191|7192|6|45|52118.55|0.00|0.07|R|F|1994-12-02|1994-12-22|1994-12-28|NONE|MAIL|iously brave accounts boost slyly. furiousl +11332|66816|6817|7|38|67746.78|0.04|0.04|R|F|1994-11-24|1995-01-11|1994-12-03|DELIVER IN PERSON|SHIP|oost blithely acco +11333|172255|7290|1|10|13272.50|0.06|0.03|A|F|1994-10-05|1994-08-14|1994-10-10|COLLECT COD|AIR|ily regular instruction +11334|190587|3107|1|43|72135.94|0.01|0.01|N|O|1997-09-23|1997-10-22|1997-10-03|COLLECT COD|FOB|ular ideas wake furiously above +11334|194487|2045|2|35|55351.80|0.09|0.05|N|O|1997-10-08|1997-10-10|1997-10-14|NONE|AIR|er the caref +11334|130911|8451|3|4|7767.64|0.08|0.04|N|O|1997-11-03|1997-09-07|1997-11-11|COLLECT COD|SHIP|eodolites +11334|14036|1540|4|38|36101.14|0.03|0.06|N|O|1997-10-07|1997-09-10|1997-11-04|NONE|TRUCK|dazzle furiously above th +11334|91975|6994|5|33|64910.01|0.10|0.08|N|O|1997-09-18|1997-09-20|1997-10-18|NONE|AIR|as are acro +11334|7265|9766|6|25|29306.50|0.08|0.00|N|O|1997-11-25|1997-09-28|1997-11-30|TAKE BACK RETURN|FOB|shall sleep. blithely careful +11334|88498|3515|7|43|63919.07|0.06|0.08|N|O|1997-11-02|1997-10-17|1997-11-17|TAKE BACK RETURN|RAIL| packages. express, unusual accoun +11335|178511|1029|1|4|6358.04|0.01|0.08|R|F|1994-12-16|1994-12-10|1994-12-19|NONE|FOB|ven pinto beans sleep car +11335|25816|8319|2|46|80123.26|0.00|0.02|R|F|1995-01-05|1994-12-26|1995-01-23|COLLECT COD|REG AIR|nal theodoli +11335|83788|1313|3|7|12402.46|0.08|0.05|A|F|1995-01-25|1994-12-19|1995-02-22|NONE|MAIL|ly ironic, regular accou +11335|17375|2378|4|17|21970.29|0.03|0.05|R|F|1995-02-08|1994-12-11|1995-02-23|COLLECT COD|SHIP|ong the special, express fox +11335|11448|1449|5|41|55737.04|0.03|0.03|R|F|1994-12-24|1995-01-15|1995-01-06|COLLECT COD|FOB|pending request +11360|44426|9435|1|3|4111.26|0.01|0.05|N|O|1997-11-09|1997-10-30|1997-12-08|NONE|FOB|the quickly unusu +11360|66016|6017|2|41|40262.41|0.07|0.06|N|O|1997-11-25|1997-11-16|1997-12-13|COLLECT COD|FOB| pending asymptotes. car +11361|51698|1699|1|49|80834.81|0.04|0.01|R|F|1994-10-02|1994-11-23|1994-11-01|TAKE BACK RETURN|RAIL|y ironic deposi +11361|85161|2686|2|33|37823.28|0.02|0.03|R|F|1994-09-29|1994-11-01|1994-10-22|DELIVER IN PERSON|FOB|ts. ironic +11361|88898|1407|3|1|1886.89|0.04|0.03|R|F|1994-11-07|1994-12-17|1994-12-07|COLLECT COD|REG AIR|tes. carefully express platelets pl +11361|98332|8333|4|48|63855.84|0.08|0.03|A|F|1995-01-16|1994-12-06|1995-01-22|TAKE BACK RETURN|MAIL|tions. pending, regular request +11361|54400|4401|5|22|29796.80|0.02|0.00|R|F|1995-01-09|1994-11-07|1995-02-08|NONE|FOB|counts are blithely accordin +11361|85173|190|6|4|4632.68|0.02|0.05|R|F|1994-11-29|1994-11-10|1994-12-15|NONE|MAIL|s sleep asymptotes. caref +11362|180911|912|1|32|63741.12|0.09|0.07|R|F|1992-10-24|1992-11-12|1992-11-04|NONE|REG AIR|eposits cajole carefully according to the +11362|164085|6602|2|10|11490.80|0.02|0.05|R|F|1992-12-19|1992-12-09|1993-01-10|NONE|SHIP|affix. quietly daring packages s +11362|164086|4087|3|45|51753.60|0.09|0.07|R|F|1993-01-03|1992-10-22|1993-01-30|COLLECT COD|MAIL|blithely after the fi +11362|179798|2316|4|50|93889.50|0.00|0.03|A|F|1992-10-23|1992-11-22|1992-11-14|DELIVER IN PERSON|TRUCK|ons after the carefully regular a +11362|55061|72|5|18|18289.08|0.08|0.07|A|F|1992-11-05|1992-12-05|1992-11-16|NONE|RAIL|uickly express +11363|177817|5369|1|44|83371.64|0.03|0.03|N|O|1998-06-07|1998-05-07|1998-06-08|COLLECT COD|FOB|od careful +11363|160279|280|2|9|12053.43|0.03|0.04|N|O|1998-03-12|1998-04-15|1998-03-20|TAKE BACK RETURN|REG AIR|foxes affix slyly special, bol +11363|7051|4552|3|20|19161.00|0.03|0.03|N|O|1998-03-15|1998-04-23|1998-03-21|TAKE BACK RETURN|AIR|ents alongside of th +11363|95856|875|4|29|53703.65|0.02|0.07|N|O|1998-03-22|1998-03-20|1998-04-12|COLLECT COD|FOB|nal, even theodolite +11364|39858|4865|1|24|43148.40|0.08|0.08|N|O|1997-04-22|1997-05-25|1997-05-20|NONE|FOB|s above the furiously +11364|85887|3412|2|44|82406.72|0.04|0.03|N|O|1997-06-12|1997-05-16|1997-06-27|NONE|SHIP|kly ironic deposits a +11365|48185|690|1|31|35128.58|0.00|0.04|N|O|1997-12-28|1997-11-03|1998-01-13|COLLECT COD|MAIL|ven depende +11365|40661|8174|2|31|49651.46|0.00|0.00|N|O|1997-10-21|1997-10-27|1997-11-08|TAKE BACK RETURN|REG AIR|ss packages? sp +11365|185504|8023|3|27|42916.50|0.06|0.07|N|O|1997-11-24|1997-10-22|1997-12-14|NONE|MAIL| are. dolp +11365|150401|7947|4|17|24673.80|0.09|0.06|N|O|1997-10-30|1997-11-13|1997-11-20|COLLECT COD|AIR| have to cajole blithely? blithely unu +11365|179909|4944|5|32|63644.80|0.02|0.05|N|O|1997-12-28|1997-10-09|1998-01-22|DELIVER IN PERSON|AIR| accounts mold blithely about th +11366|151079|3595|1|9|10170.63|0.01|0.01|R|F|1992-08-08|1992-07-22|1992-08-30|DELIVER IN PERSON|FOB|counts across the +11367|107563|7564|1|19|29840.64|0.06|0.04|A|F|1995-04-13|1995-01-24|1995-04-19|TAKE BACK RETURN|RAIL|ges wake around the ev +11392|33795|8802|1|46|79524.34|0.00|0.03|R|F|1994-12-02|1994-11-09|1994-12-24|TAKE BACK RETURN|SHIP|y ironic re +11392|189062|6617|2|46|52948.76|0.09|0.02|A|F|1994-12-11|1994-10-15|1994-12-25|TAKE BACK RETURN|SHIP|ggle slyly after the ironic packages. final +11393|189941|7496|1|49|99516.06|0.08|0.01|A|F|1992-05-08|1992-05-26|1992-05-26|NONE|TRUCK|tions wake courts. carefully even +11393|127972|485|2|48|95998.56|0.06|0.06|A|F|1992-04-12|1992-06-13|1992-05-02|NONE|AIR|cording to the blithely bold +11394|128173|3198|1|35|42040.95|0.04|0.06|N|O|1998-04-13|1998-04-28|1998-04-28|DELIVER IN PERSON|FOB|ly regular fo +11394|188545|1064|2|8|13068.32|0.09|0.01|N|O|1998-04-16|1998-04-17|1998-05-12|NONE|TRUCK|e regular, special foxes. +11394|68401|5920|3|32|43820.80|0.02|0.01|N|O|1998-06-06|1998-04-20|1998-06-25|TAKE BACK RETURN|RAIL|heodolites. blithely +11394|699|8200|4|50|79984.50|0.06|0.06|N|O|1998-04-05|1998-04-06|1998-05-04|COLLECT COD|FOB|encies. express accounts sleep blithely; sl +11394|135460|7974|5|25|37386.50|0.01|0.00|N|O|1998-06-14|1998-04-20|1998-06-27|COLLECT COD|REG AIR|ld foxes nag. quickly ironic +11395|32137|2138|1|24|25659.12|0.02|0.03|N|O|1997-10-28|1997-10-16|1997-10-31|DELIVER IN PERSON|AIR| regular, enticing accounts breach ab +11395|112300|9834|2|7|9186.10|0.04|0.08|N|O|1997-09-25|1997-10-26|1997-10-23|TAKE BACK RETURN|AIR|lar deposit +11395|20046|2549|3|9|8694.36|0.06|0.05|N|O|1997-09-13|1997-10-01|1997-10-13|COLLECT COD|TRUCK|egular packages. packages accordi +11396|67948|5467|1|15|28739.10|0.09|0.03|R|F|1992-09-16|1992-10-05|1992-09-19|COLLECT COD|REG AIR|lly even instructions sleep daringl +11396|199457|9458|2|15|23346.75|0.03|0.02|A|F|1992-09-14|1992-08-25|1992-09-17|DELIVER IN PERSON|TRUCK|according to the slyly even pa +11396|58100|8101|3|38|40207.80|0.05|0.07|A|F|1992-10-21|1992-09-26|1992-10-23|DELIVER IN PERSON|REG AIR|odolites believe quickly. bli +11397|51626|9142|1|41|64682.42|0.09|0.05|N|O|1996-11-19|1996-12-24|1996-12-06|NONE|AIR| ironic pa +11398|21246|1247|1|18|21010.32|0.06|0.08|A|F|1992-09-21|1992-10-04|1992-10-05|DELIVER IN PERSON|RAIL|en dolphins. slyly fina +11398|77243|4765|2|17|20744.08|0.09|0.07|R|F|1992-09-30|1992-11-05|1992-10-08|COLLECT COD|FOB| accounts haggle f +11398|20106|7613|3|46|47200.60|0.10|0.05|R|F|1992-08-14|1992-10-12|1992-09-08|COLLECT COD|AIR|thily regular plat +11398|113048|3049|4|35|37136.40|0.07|0.01|R|F|1992-08-30|1992-10-30|1992-09-13|TAKE BACK RETURN|RAIL|aggle quickly alongside of the +11398|184413|6932|5|39|58398.99|0.01|0.07|A|F|1992-09-06|1992-10-24|1992-09-12|TAKE BACK RETURN|RAIL|ts doubt furiously special pa +11398|28748|8749|6|49|82160.26|0.10|0.07|A|F|1992-09-12|1992-11-03|1992-10-05|NONE|RAIL|packages use furiously clos +11399|77514|5036|1|23|34304.73|0.03|0.06|R|F|1994-07-11|1994-06-02|1994-07-16|TAKE BACK RETURN|SHIP|ses kindle quickly. slyly pe +11424|167541|2574|1|37|59515.98|0.03|0.04|A|F|1993-06-30|1993-05-03|1993-07-12|NONE|FOB|ar instructions boost slyly abo +11425|195170|5171|1|15|18977.55|0.08|0.05|N|O|1995-09-14|1995-09-09|1995-10-11|DELIVER IN PERSON|SHIP|slyly ironic instructions. careful +11425|5868|5869|2|4|7095.44|0.05|0.06|N|O|1995-09-19|1995-07-31|1995-10-10|COLLECT COD|REG AIR|e carefully silent foxes. quickly final +11425|14094|4095|3|44|44355.96|0.02|0.07|N|O|1995-08-04|1995-07-31|1995-08-31|NONE|SHIP|gle. slyly pe +11425|68292|8293|4|8|10082.32|0.02|0.07|N|O|1995-09-18|1995-08-08|1995-09-21|TAKE BACK RETURN|REG AIR|ily even foxes about the +11425|178030|5582|5|5|5540.15|0.04|0.01|N|O|1995-09-01|1995-08-30|1995-09-27|NONE|TRUCK|y. theodolites +11425|136747|1774|6|44|78484.56|0.00|0.00|N|O|1995-07-01|1995-08-26|1995-07-29|DELIVER IN PERSON|AIR| courts cajole blithely according +11426|46935|9440|1|8|15055.44|0.03|0.05|A|F|1994-06-18|1994-07-24|1994-06-28|DELIVER IN PERSON|FOB|y after the special packages. furious +11426|29197|1700|2|32|36038.08|0.03|0.00|R|F|1994-05-22|1994-07-08|1994-06-19|DELIVER IN PERSON|REG AIR|ly final packages. quickly final asymptote +11426|101523|1524|3|20|30490.40|0.06|0.03|A|F|1994-07-19|1994-07-27|1994-08-02|NONE|TRUCK|ents wake accordin +11426|84056|6565|4|13|13520.65|0.10|0.08|A|F|1994-05-24|1994-07-02|1994-06-10|COLLECT COD|TRUCK|usly. blithely re +11426|128624|1137|5|6|9915.72|0.07|0.00|R|F|1994-08-04|1994-07-22|1994-08-29|NONE|RAIL|slyly requests. pendi +11427|4066|9067|1|24|23281.44|0.05|0.03|R|F|1994-03-03|1994-01-27|1994-03-24|DELIVER IN PERSON|AIR|e furiously. final, regular sauternes +11427|124007|6520|2|14|14434.00|0.08|0.04|R|F|1994-03-08|1994-02-13|1994-03-22|TAKE BACK RETURN|MAIL|gside of th +11427|175738|3290|3|34|61666.82|0.01|0.07|A|F|1994-03-05|1994-02-08|1994-03-17|TAKE BACK RETURN|REG AIR| the blithely silent ideas. c +11427|21509|4012|4|50|71525.00|0.09|0.04|A|F|1994-01-18|1993-12-25|1994-02-02|NONE|TRUCK|nts through the slyly unusual pinto +11427|93709|8728|5|20|34054.00|0.05|0.07|R|F|1994-03-06|1994-02-19|1994-03-29|NONE|MAIL| ironic packages. carefull +11427|156874|4420|6|42|81096.54|0.01|0.03|R|F|1994-03-13|1994-02-07|1994-03-25|COLLECT COD|RAIL|y. carefully unusual +11427|178873|3908|7|35|68315.45|0.09|0.05|A|F|1993-12-14|1994-01-23|1994-01-11|NONE|REG AIR|usual packages +11428|114029|9052|1|7|7301.14|0.08|0.05|R|F|1992-04-06|1992-04-19|1992-04-28|COLLECT COD|SHIP|e quickly even packages. furious +11429|53688|6194|1|30|49250.40|0.10|0.05|A|F|1993-04-10|1993-04-20|1993-04-14|COLLECT COD|AIR|. blithely speci +11429|126706|9219|2|28|48515.60|0.06|0.01|R|F|1993-04-06|1993-05-11|1993-04-26|COLLECT COD|REG AIR|gular dependencies above +11429|139372|6912|3|32|45163.84|0.02|0.05|R|F|1993-05-04|1993-06-02|1993-05-07|DELIVER IN PERSON|AIR|even instructions. regular deposits ca +11429|10030|2532|4|33|31020.99|0.06|0.00|R|F|1993-03-21|1993-05-06|1993-03-29|NONE|MAIL|packages boost furious +11430|36371|8875|1|3|3922.11|0.04|0.00|N|O|1998-02-04|1998-03-21|1998-02-05|TAKE BACK RETURN|AIR|y slyly bold asymp +11431|62112|2113|1|11|11815.21|0.04|0.03|R|F|1992-08-08|1992-10-18|1992-08-30|COLLECT COD|RAIL|ins cajole furiously pending ide +11431|102126|2127|2|28|31587.36|0.06|0.08|R|F|1992-09-24|1992-10-07|1992-10-20|TAKE BACK RETURN|REG AIR|furiously slyly final p +11431|19499|9500|3|44|62413.56|0.01|0.08|R|F|1992-09-16|1992-10-14|1992-10-05|TAKE BACK RETURN|SHIP|le furiously above the +11431|110090|2602|4|16|17601.44|0.05|0.04|R|F|1992-08-19|1992-10-14|1992-08-21|NONE|FOB|riously. bold asympt +11431|79064|6586|5|22|22947.32|0.06|0.02|R|F|1992-08-13|1992-10-14|1992-08-26|COLLECT COD|TRUCK|s sleep bravely ca +11431|20873|5878|6|50|89693.50|0.05|0.07|R|F|1992-08-12|1992-09-16|1992-08-15|TAKE BACK RETURN|TRUCK|accounts are fl +11431|8563|3564|7|28|41203.68|0.05|0.07|R|F|1992-09-28|1992-09-02|1992-09-30|NONE|SHIP|e carefully above the bo +11456|103167|3168|1|24|28083.84|0.04|0.07|A|F|1993-06-13|1993-06-28|1993-06-28|DELIVER IN PERSON|MAIL| haggle blithely around the bravely regular +11456|122613|2614|2|6|9813.66|0.04|0.03|A|F|1993-06-20|1993-07-12|1993-06-21|DELIVER IN PERSON|AIR|ly even packages grow. furiou +11456|155167|198|3|5|6110.80|0.03|0.08|A|F|1993-06-20|1993-07-12|1993-06-26|NONE|AIR|oss the regular deposits cajole slyly o +11456|80812|5829|4|10|17928.10|0.10|0.05|R|F|1993-06-13|1993-05-23|1993-06-18|DELIVER IN PERSON|REG AIR| after the carefu +11457|38383|3390|1|22|29070.36|0.07|0.04|N|O|1996-02-17|1996-02-11|1996-03-14|TAKE BACK RETURN|FOB|ole quickly. bold, ironic pinto beans wake +11457|87729|238|2|12|20600.64|0.01|0.05|N|O|1996-03-21|1996-03-12|1996-04-20|COLLECT COD|TRUCK|ckly even i +11457|54843|2359|3|34|61126.56|0.08|0.04|N|O|1996-02-07|1996-02-23|1996-02-25|COLLECT COD|AIR|ly. even deposits are final acc +11457|139331|9332|4|14|19184.62|0.10|0.08|N|O|1996-02-26|1996-01-14|1996-03-25|NONE|TRUCK|unts boost blithely sly accou +11457|126458|8971|5|37|54924.65|0.06|0.03|N|O|1995-12-17|1996-01-24|1996-01-03|COLLECT COD|MAIL|ongside of the +11457|171830|9382|6|50|95091.50|0.10|0.05|N|O|1996-01-13|1996-02-04|1996-02-04|DELIVER IN PERSON|SHIP|thely regular courts sleep furiou +11458|137561|5101|1|8|12788.48|0.08|0.07|N|O|1998-05-04|1998-06-10|1998-05-25|NONE|MAIL|ake after the carefully silent pinto b +11458|173767|6285|2|38|69948.88|0.08|0.04|N|O|1998-05-29|1998-05-05|1998-06-20|TAKE BACK RETURN|RAIL| instructions. platelets de +11458|95191|7701|3|22|26096.18|0.09|0.03|N|O|1998-07-11|1998-05-18|1998-07-13|TAKE BACK RETURN|FOB| ideas. care +11458|69651|4664|4|36|58343.40|0.02|0.05|N|O|1998-04-11|1998-06-26|1998-04-21|NONE|AIR|ic deposits. blithely thin platelets +11458|14101|9104|5|30|30453.00|0.08|0.06|N|O|1998-05-31|1998-06-02|1998-06-11|COLLECT COD|SHIP| accounts integrate slyly about +11458|188197|5752|6|2|2570.38|0.05|0.04|N|O|1998-07-13|1998-06-05|1998-08-05|TAKE BACK RETURN|AIR|kages! sil +11459|63646|3647|1|9|14486.76|0.10|0.00|N|O|1996-09-10|1996-10-05|1996-10-10|COLLECT COD|AIR|dependencies affix furiously +11459|93459|5969|2|46|66812.70|0.01|0.04|N|O|1996-10-17|1996-08-29|1996-11-06|TAKE BACK RETURN|REG AIR| carefully above the blithely regular pin +11459|160673|5706|3|16|27738.72|0.01|0.00|N|O|1996-10-08|1996-09-12|1996-10-26|TAKE BACK RETURN|SHIP|ly final pinto beans +11459|15307|2811|4|34|41558.20|0.06|0.04|N|O|1996-07-25|1996-08-18|1996-07-29|TAKE BACK RETURN|MAIL|bout the flu +11459|53270|8281|5|39|47707.53|0.05|0.07|N|O|1996-09-07|1996-09-25|1996-09-18|COLLECT COD|FOB|s. slyly f +11459|98838|6366|6|5|9184.15|0.09|0.02|N|O|1996-11-04|1996-10-09|1996-11-23|DELIVER IN PERSON|REG AIR|tithes. silent deposits boost along +11459|157139|7140|7|5|5980.65|0.08|0.03|N|O|1996-10-12|1996-09-29|1996-11-02|COLLECT COD|REG AIR|egular pinto beans. regular theodolites sn +11460|32043|7050|1|6|5850.24|0.07|0.06|A|F|1993-11-14|1993-10-31|1993-11-25|DELIVER IN PERSON|AIR|packages. blithely pending ideas i +11460|136716|9230|2|32|56086.72|0.10|0.08|A|F|1993-09-21|1993-10-23|1993-09-28|COLLECT COD|SHIP|s the even, regular accounts. +11460|174536|9571|3|3|4831.59|0.04|0.01|A|F|1993-12-24|1993-11-03|1993-12-25|NONE|AIR|ing foxes are. bold foxes eat carefull +11461|168128|645|1|16|19137.92|0.05|0.08|N|O|1996-06-29|1996-07-13|1996-07-16|TAKE BACK RETURN|TRUCK|nding packages according to the f +11461|119705|9706|2|23|39668.10|0.10|0.03|N|O|1996-05-16|1996-07-19|1996-05-28|COLLECT COD|RAIL|he carefully silent +11461|71848|9370|3|19|34576.96|0.01|0.01|N|O|1996-08-08|1996-06-09|1996-08-25|TAKE BACK RETURN|FOB|integrate blithely final, eve +11462|84222|6731|1|8|9649.76|0.03|0.02|N|O|1996-09-07|1996-10-28|1996-09-14|NONE|REG AIR|structions was stealthily. furiously quick +11462|115697|3231|2|14|23977.66|0.05|0.07|N|O|1996-09-23|1996-11-16|1996-10-22|NONE|AIR|es sleep furiously acros +11462|118718|8719|3|44|76415.24|0.04|0.08|N|O|1996-11-17|1996-11-23|1996-12-09|TAKE BACK RETURN|MAIL| requests acco +11462|84011|6520|4|5|4975.05|0.04|0.05|N|O|1996-11-26|1996-09-28|1996-12-24|NONE|TRUCK|oxes. furious +11462|170225|2743|5|9|11656.98|0.00|0.02|N|O|1996-12-01|1996-11-01|1996-12-28|COLLECT COD|RAIL|ounts-- blithely ironic depos +11462|169777|9778|6|39|72024.03|0.05|0.05|N|O|1996-09-03|1996-11-10|1996-09-27|DELIVER IN PERSON|REG AIR|riously. regular ideas after the slyly +11463|30332|333|1|17|21459.61|0.03|0.03|N|O|1998-04-02|1998-03-13|1998-04-29|COLLECT COD|MAIL|nts. blithely +11463|180400|2919|2|42|62176.80|0.03|0.00|N|O|1998-04-19|1998-03-08|1998-05-13|NONE|RAIL|l deposits! carefully ironic foxes +11463|173705|3706|3|48|85377.60|0.07|0.03|N|O|1998-03-15|1998-02-09|1998-04-13|TAKE BACK RETURN|AIR|ages sleep against the blith +11463|57064|7065|4|8|8168.48|0.06|0.03|N|O|1998-03-20|1998-03-12|1998-04-03|NONE|TRUCK|s. finally special ideas are blithely. +11463|66050|6051|5|5|5080.25|0.04|0.06|N|O|1998-03-21|1998-02-11|1998-04-13|COLLECT COD|MAIL|inal, unusual ideas cajole furiously regu +11463|97260|4788|6|25|31431.50|0.02|0.08|N|O|1998-04-16|1998-01-30|1998-04-23|DELIVER IN PERSON|AIR|t requests. final instructions hang acc +11463|33178|5682|7|19|21112.23|0.00|0.04|N|O|1998-04-14|1998-02-14|1998-05-08|NONE|REG AIR|- even pinto beans cajole after the blithel +11488|12214|2215|1|28|31533.88|0.09|0.06|R|F|1993-11-10|1993-10-16|1993-11-24|TAKE BACK RETURN|AIR|ccounts. ruthlessly even g +11488|66168|6169|2|45|51037.20|0.09|0.02|R|F|1993-09-27|1993-11-21|1993-10-22|TAKE BACK RETURN|REG AIR|ffily bold deposits. fluffily thin p +11489|76350|8858|1|49|64991.15|0.03|0.07|N|O|1996-12-05|1996-12-10|1996-12-26|NONE|REG AIR|gular dependencies detect dolphins. slyly +11489|199901|7459|2|19|38017.10|0.06|0.01|N|O|1996-12-24|1996-12-09|1997-01-15|DELIVER IN PERSON|RAIL|usual theodolites. unu +11490|126180|1205|1|42|50659.56|0.05|0.01|N|O|1996-11-02|1996-11-28|1996-11-23|NONE|SHIP|roughout the dependencies. furiously +11490|92901|429|2|10|18939.00|0.02|0.08|N|O|1996-12-10|1996-12-01|1996-12-25|DELIVER IN PERSON|REG AIR|s above the grouc +11491|185472|5473|1|10|15574.70|0.04|0.01|A|F|1993-10-30|1993-11-07|1993-10-31|DELIVER IN PERSON|FOB| accounts n +11491|19681|7185|2|45|72030.60|0.10|0.05|R|F|1993-12-03|1993-09-29|1993-12-19|COLLECT COD|TRUCK| somas-- pending, regular instruct +11491|165727|760|3|29|51988.88|0.09|0.05|R|F|1993-10-28|1993-09-30|1993-11-19|DELIVER IN PERSON|RAIL|regular excuses. furiousl +11491|167228|4777|4|48|62170.56|0.05|0.03|R|F|1993-09-26|1993-10-31|1993-10-26|TAKE BACK RETURN|RAIL|y pending warthogs! blit +11491|197849|369|5|16|31149.44|0.00|0.04|A|F|1993-11-25|1993-10-08|1993-12-25|COLLECT COD|SHIP|ely even dependencies use +11491|45729|5730|6|18|30144.96|0.02|0.08|R|F|1993-12-10|1993-10-12|1994-01-03|TAKE BACK RETURN|FOB|the pinto bea +11491|163242|5759|7|3|3915.72|0.02|0.03|R|F|1993-09-13|1993-10-31|1993-09-23|NONE|REG AIR|uriously regular packages. accoun +11492|7397|9898|1|20|26087.80|0.02|0.06|N|O|1997-05-30|1997-05-22|1997-05-31|DELIVER IN PERSON|REG AIR|accounts haggle. c +11492|109404|6935|2|46|65016.40|0.00|0.00|N|O|1997-06-13|1997-05-05|1997-07-05|NONE|AIR|ackages eat blithely +11492|146036|1065|3|48|51937.44|0.08|0.02|N|O|1997-04-15|1997-04-15|1997-05-08|DELIVER IN PERSON|TRUCK| the ironic sauternes wake requests. acco +11492|10427|428|4|14|18723.88|0.05|0.03|N|O|1997-04-05|1997-05-02|1997-04-27|NONE|RAIL|y blithe realms +11493|158267|783|1|9|11927.34|0.09|0.02|N|O|1995-12-02|1996-01-04|1995-12-08|COLLECT COD|AIR|lly special theodolite +11493|188641|8642|2|28|48429.92|0.04|0.07|N|O|1995-10-26|1995-12-29|1995-11-14|DELIVER IN PERSON|RAIL|final deposits. regular, pending inst +11494|81614|1615|1|13|20742.93|0.05|0.00|N|O|1997-10-03|1997-10-15|1997-10-17|COLLECT COD|RAIL|the bold requests-- ironic deposit +11494|76221|3743|2|2|2394.44|0.07|0.02|N|O|1997-08-07|1997-10-17|1997-08-25|TAKE BACK RETURN|TRUCK|ake furiously sp +11494|40901|8414|3|15|27628.50|0.00|0.03|N|O|1997-08-08|1997-09-05|1997-08-15|TAKE BACK RETURN|RAIL|ng platelets. even pac +11494|22409|7414|4|40|53256.00|0.01|0.03|N|O|1997-10-09|1997-09-11|1997-10-23|TAKE BACK RETURN|MAIL| carefully regular deposits haggle blithel +11495|198614|8615|1|15|25689.15|0.05|0.08|N|O|1995-09-26|1995-09-23|1995-10-26|TAKE BACK RETURN|TRUCK|ronic accounts integrate. furiously regular +11495|94853|9872|2|8|14782.80|0.06|0.07|N|O|1995-08-19|1995-09-21|1995-09-02|TAKE BACK RETURN|RAIL|ously regular deposits. furiously bold in +11520|30859|3363|1|45|80543.25|0.10|0.00|A|F|1994-12-11|1994-11-03|1995-01-08|NONE|MAIL|aggle. ruthlessly ironic pac +11520|47003|4516|2|47|44650.00|0.07|0.05|A|F|1995-01-01|1994-10-30|1995-01-23|COLLECT COD|AIR|express ideas are quickly. bold, bold p +11521|116548|6549|1|8|12516.32|0.03|0.05|N|O|1996-09-13|1996-10-26|1996-09-26|COLLECT COD|SHIP|gular foxes +11521|8014|3015|2|12|11064.12|0.09|0.03|N|O|1997-01-03|1996-11-04|1997-01-11|TAKE BACK RETURN|FOB| among the slyly regula +11522|104376|4377|1|16|22085.92|0.03|0.05|A|F|1993-10-02|1993-11-02|1993-10-14|COLLECT COD|RAIL|onic courts. bold dolphins sle +11522|34706|7210|2|5|8203.50|0.03|0.00|A|F|1993-10-10|1993-11-13|1993-10-19|DELIVER IN PERSON|AIR| foxes. express packages +11523|31447|1448|1|31|42731.64|0.08|0.02|N|O|1998-11-22|1998-09-13|1998-12-11|TAKE BACK RETURN|AIR|deposits haggle about t +11523|113552|6064|2|21|32876.55|0.03|0.06|N|O|1998-08-06|1998-09-09|1998-08-13|DELIVER IN PERSON|AIR| pinto beans +11523|60486|8005|3|15|21697.20|0.03|0.03|N|O|1998-09-20|1998-08-30|1998-10-14|TAKE BACK RETURN|MAIL| regular platelets. furiously ironic fox +11523|173759|1311|4|48|87972.00|0.08|0.05|N|O|1998-08-18|1998-10-11|1998-09-09|NONE|SHIP|ecial instructions poach permanently across +11523|161651|4168|5|19|32540.35|0.07|0.00|N|O|1998-11-17|1998-09-01|1998-11-27|COLLECT COD|SHIP|the enticingly regular +11523|66679|4198|6|17|27976.39|0.04|0.05|N|O|1998-07-28|1998-10-08|1998-08-08|DELIVER IN PERSON|MAIL|affix slyly among the reg +11524|132726|2727|1|6|10552.32|0.02|0.03|N|O|1996-02-23|1996-03-06|1996-03-16|TAKE BACK RETURN|SHIP|kly after the final ideas. fluffily reg +11525|79590|7112|1|33|51796.47|0.08|0.07|N|O|1997-03-21|1997-05-15|1997-03-24|TAKE BACK RETURN|MAIL|. finally express excuses around the q +11525|59466|6982|2|32|45614.72|0.00|0.02|N|O|1997-06-16|1997-05-19|1997-07-03|DELIVER IN PERSON|TRUCK|are furiously ironic accounts. fluffily exp +11525|36535|9039|3|5|7357.65|0.03|0.07|N|O|1997-07-12|1997-05-23|1997-08-07|NONE|TRUCK|tions. quickly final p +11525|39708|4715|4|46|75794.20|0.03|0.01|N|O|1997-05-10|1997-06-18|1997-05-23|TAKE BACK RETURN|SHIP|es haggle car +11526|133223|8250|1|12|15074.64|0.08|0.08|N|O|1998-05-26|1998-04-30|1998-06-12|DELIVER IN PERSON|REG AIR|le final, final +11526|73925|3926|2|30|56967.60|0.01|0.08|N|O|1998-06-12|1998-05-03|1998-06-26|DELIVER IN PERSON|SHIP|uriously pending pearls are slyl +11526|52398|2399|3|39|52665.21|0.00|0.02|N|O|1998-05-29|1998-05-05|1998-06-11|DELIVER IN PERSON|RAIL| above the ironically spec +11527|20901|8408|1|47|85629.30|0.10|0.00|A|F|1994-10-24|1994-09-03|1994-11-16|NONE|TRUCK|sual packages haggle. b +11552|137065|4605|1|28|30857.68|0.08|0.06|R|F|1993-03-08|1993-03-03|1993-03-31|COLLECT COD|MAIL| are furiously according to the quickly iro +11553|24558|7061|1|49|72644.95|0.00|0.01|A|F|1994-08-03|1994-06-16|1994-08-23|COLLECT COD|TRUCK|lphins integrate across the ironic +11553|132507|5021|2|21|32329.50|0.02|0.07|R|F|1994-07-09|1994-06-14|1994-07-16|COLLECT COD|FOB|inal theodolites. furiously ironic +11553|37116|9620|3|49|51602.39|0.10|0.02|R|F|1994-04-24|1994-06-21|1994-05-18|NONE|FOB|lly according to the fur +11553|7144|4645|4|41|43096.74|0.02|0.03|R|F|1994-07-09|1994-05-28|1994-08-06|NONE|REG AIR|bold theodoli +11553|59864|4875|5|18|32829.48|0.05|0.03|R|F|1994-06-18|1994-06-09|1994-06-26|NONE|SHIP|ing packages. slyly regular dinos wake quic +11554|76343|6344|1|49|64647.66|0.03|0.03|N|O|1998-07-24|1998-07-14|1998-08-11|COLLECT COD|TRUCK| platelets use blithely +11554|85601|3126|2|27|42838.20|0.06|0.01|N|O|1998-07-13|1998-07-09|1998-07-20|TAKE BACK RETURN|RAIL|gainst the furiously regular accounts. si +11554|95556|8066|3|1|1551.55|0.01|0.04|N|O|1998-07-26|1998-08-06|1998-08-13|DELIVER IN PERSON|TRUCK|. ideas sublate slyly f +11554|4280|6781|4|50|59214.00|0.06|0.07|N|O|1998-07-08|1998-07-20|1998-07-10|DELIVER IN PERSON|SHIP|nic, quiet requests may boost! +11554|125497|522|5|27|41107.23|0.02|0.07|N|O|1998-09-24|1998-07-11|1998-10-23|NONE|REG AIR|alongside of the slyly +11554|19552|7056|6|40|58862.00|0.09|0.08|N|O|1998-08-20|1998-08-01|1998-09-13|NONE|TRUCK|efully. ironic +11554|193924|8963|7|10|20179.20|0.02|0.00|N|O|1998-09-15|1998-07-12|1998-10-08|TAKE BACK RETURN|AIR|quests doubt along the permane +11555|67787|7788|1|42|73700.76|0.01|0.05|N|O|1996-07-06|1996-07-20|1996-07-12|COLLECT COD|MAIL|kages use carefully; bold i +11555|81030|3539|2|34|34375.02|0.04|0.03|N|O|1996-07-10|1996-07-10|1996-07-13|DELIVER IN PERSON|REG AIR|ing to the slyly final pains. blith +11555|59691|7207|3|16|26411.04|0.04|0.01|N|O|1996-06-10|1996-08-22|1996-06-24|TAKE BACK RETURN|SHIP|l packages according to t +11555|13842|3843|4|47|82524.48|0.09|0.03|N|O|1996-09-05|1996-08-13|1996-10-01|NONE|SHIP|aggle. unusual requests about the +11555|27317|4824|5|40|49772.40|0.03|0.03|N|O|1996-09-08|1996-06-27|1996-09-15|COLLECT COD|TRUCK|ual excuses. quickly regula +11556|80541|5558|1|34|51732.36|0.09|0.06|N|O|1996-03-06|1996-04-07|1996-03-23|DELIVER IN PERSON|FOB| even accounts. regular accounts hagg +11556|44578|2091|2|32|48722.24|0.05|0.04|N|O|1996-04-16|1996-05-16|1996-04-17|NONE|SHIP|nos. slow waters wake blithely +11556|12224|7227|3|21|23860.62|0.05|0.03|N|O|1996-04-07|1996-04-21|1996-04-27|TAKE BACK RETURN|MAIL|y blithely special dependencies. f +11556|33163|3164|4|13|14250.08|0.09|0.02|N|O|1996-05-22|1996-05-26|1996-06-13|DELIVER IN PERSON|AIR| pinto beans wake furiousl +11556|170459|5494|5|15|22941.75|0.04|0.06|N|O|1996-07-02|1996-05-08|1996-07-25|COLLECT COD|TRUCK|uses sleep blithely. furiously ir +11556|90199|200|6|39|46378.41|0.04|0.00|N|O|1996-06-30|1996-04-05|1996-07-22|TAKE BACK RETURN|AIR| ironic, bold accounts snooze carefully. +11556|172469|4987|7|7|10790.22|0.03|0.03|N|O|1996-04-26|1996-05-08|1996-05-14|TAKE BACK RETURN|MAIL| bold account +11557|75231|5232|1|2|2412.46|0.09|0.02|N|O|1997-06-15|1997-05-24|1997-07-04|NONE|MAIL|otes across the carefully regular instruct +11557|6004|3505|2|35|31850.00|0.04|0.07|N|O|1997-07-28|1997-05-22|1997-08-04|DELIVER IN PERSON|REG AIR|. furiously special +11557|95553|5554|3|1|1548.55|0.08|0.05|N|O|1997-08-05|1997-05-22|1997-08-19|NONE|RAIL|. asymptotes +11558|64174|1693|1|9|10243.53|0.04|0.05|A|F|1994-05-02|1994-06-09|1994-05-31|DELIVER IN PERSON|TRUCK|arefully even foxes cajole furiously ac +11558|167634|2667|2|21|35734.23|0.03|0.04|A|F|1994-05-05|1994-05-04|1994-05-24|DELIVER IN PERSON|REG AIR|ts. regular re +11559|47339|4852|1|42|54025.86|0.08|0.02|N|O|1996-01-12|1995-12-03|1996-01-14|DELIVER IN PERSON|FOB|y daring asymptotes. regular +11584|41214|1215|1|39|45053.19|0.01|0.01|A|F|1994-12-22|1994-12-24|1994-12-29|COLLECT COD|FOB|g the slyly pendin +11584|73295|3296|2|46|58341.34|0.01|0.08|R|F|1994-12-07|1995-01-04|1995-01-01|COLLECT COD|AIR|ully above the +11584|68647|1154|3|25|40391.00|0.01|0.06|A|F|1995-01-19|1995-01-09|1995-01-20|TAKE BACK RETURN|SHIP|y express packages haggle. final, iron +11584|137281|9795|4|32|42184.96|0.09|0.02|A|F|1995-02-18|1994-12-25|1995-03-07|COLLECT COD|SHIP|hins cajole unusual asymptotes. blithely +11584|70464|7986|5|22|31558.12|0.03|0.07|R|F|1995-01-13|1995-01-15|1995-02-08|NONE|TRUCK| even deposits? final requests belie +11584|72180|7195|6|45|51848.10|0.10|0.03|A|F|1994-12-23|1994-12-24|1995-01-05|DELIVER IN PERSON|REG AIR|e carefully regular deposits. fluffily +11584|117646|158|7|32|53236.48|0.00|0.01|R|F|1994-12-21|1995-01-14|1994-12-31|NONE|SHIP|unts. carefully bold pains impress. s +11585|65421|7928|1|28|38819.76|0.02|0.02|R|F|1994-05-20|1994-04-17|1994-06-16|DELIVER IN PERSON|MAIL|thely at the blithely ironic packages. +11585|120271|7808|2|1|1291.27|0.08|0.05|R|F|1994-04-04|1994-05-30|1994-04-18|DELIVER IN PERSON|REG AIR|e. carefully regular +11585|179088|1606|3|9|10503.72|0.04|0.03|R|F|1994-06-13|1994-05-29|1994-06-17|DELIVER IN PERSON|FOB|lly regular requests. carefully expre +11586|178790|3825|1|12|22425.48|0.06|0.07|R|F|1993-12-29|1994-01-23|1994-01-24|NONE|FOB|are regular, final deposits. slyly bold re +11586|113545|1079|2|4|6234.16|0.04|0.00|A|F|1993-11-27|1994-01-30|1993-12-24|COLLECT COD|REG AIR|sits cajole slyly. quickly +11587|170022|7574|1|22|24024.44|0.10|0.06|N|O|1998-06-16|1998-05-31|1998-07-09|NONE|SHIP|lyly unusual foxes above the slyly +11587|150020|5051|2|33|35310.66|0.09|0.00|N|O|1998-06-03|1998-04-12|1998-06-09|COLLECT COD|SHIP|ly ironic accounts. slyly regular instr +11587|174801|2353|3|44|82535.20|0.03|0.05|N|O|1998-05-05|1998-05-27|1998-05-06|COLLECT COD|RAIL|the carefully express pinto bea +11588|170453|8005|1|33|50273.85|0.00|0.05|N|O|1998-01-14|1997-12-06|1998-01-28|COLLECT COD|SHIP|r packages are above the blithely s +11588|186857|6858|2|18|34989.30|0.06|0.05|N|O|1998-01-16|1997-12-10|1998-01-24|NONE|AIR|regular foxes cajole +11588|94899|9918|3|9|17045.01|0.06|0.04|N|O|1997-11-15|1997-12-22|1997-12-04|COLLECT COD|FOB|r deposits snooze blithely. sl +11588|160315|5348|4|35|48135.85|0.08|0.08|N|O|1998-02-14|1997-12-16|1998-03-14|NONE|MAIL|sly final dol +11588|6202|8703|5|35|38787.00|0.09|0.04|N|O|1998-01-26|1998-01-16|1998-02-18|TAKE BACK RETURN|TRUCK|posits are; carefully final ideas nag even +11589|85088|7597|1|21|22534.68|0.07|0.04|A|F|1992-06-03|1992-07-02|1992-07-01|TAKE BACK RETURN|TRUCK|nusual instructions. reg +11589|68516|1023|2|45|66802.95|0.02|0.02|A|F|1992-06-09|1992-07-08|1992-06-21|COLLECT COD|AIR|es. final, regul +11590|2989|2990|1|43|81355.14|0.01|0.00|N|O|1996-06-23|1996-06-18|1996-07-07|COLLECT COD|FOB|s cajole packages. +11590|31055|3559|2|47|46344.35|0.03|0.06|N|O|1996-07-26|1996-06-12|1996-08-25|NONE|TRUCK| ideas wake regular, regular theodoli +11590|132643|7670|3|41|68701.24|0.01|0.06|N|O|1996-07-08|1996-05-31|1996-07-15|NONE|SHIP|mptotes run. +11590|122412|9949|4|49|70286.09|0.01|0.08|N|O|1996-04-27|1996-05-29|1996-05-15|DELIVER IN PERSON|AIR|es. blithely pending foxes alongside of th +11590|162359|7392|5|27|38376.45|0.06|0.07|N|O|1996-05-01|1996-05-26|1996-05-04|COLLECT COD|REG AIR|odolites boost blithel +11591|61941|6954|1|42|79923.48|0.07|0.01|R|F|1993-02-01|1993-04-02|1993-02-24|COLLECT COD|SHIP| carefully unusual sentiments. b +11591|27375|7376|2|42|54699.54|0.05|0.04|A|F|1993-02-06|1993-02-22|1993-02-12|COLLECT COD|TRUCK|its nag according to the furiously exp +11616|62918|7931|1|6|11285.46|0.06|0.00|N|O|1996-10-28|1996-10-10|1996-11-11|TAKE BACK RETURN|RAIL|ideas haggle blithely even theo +11616|50272|5283|2|42|51335.34|0.00|0.06|N|O|1996-11-08|1996-09-07|1996-11-12|COLLECT COD|REG AIR|nic ideas nag +11616|116561|4095|3|27|42594.12|0.02|0.07|N|O|1996-08-10|1996-09-24|1996-09-09|TAKE BACK RETURN|TRUCK|efully final sauternes sleep carefully +11616|25047|52|4|42|40825.68|0.08|0.01|N|O|1996-09-13|1996-09-09|1996-09-21|TAKE BACK RETURN|REG AIR|nal packages wake slyly amon +11616|152475|2476|5|37|56516.39|0.10|0.02|N|O|1996-08-03|1996-10-29|1996-08-07|COLLECT COD|AIR|counts sleep bl +11616|44778|4779|6|6|10336.62|0.10|0.07|N|O|1996-09-18|1996-09-28|1996-10-13|COLLECT COD|FOB|nticing excuses. +11616|178840|6392|7|34|65240.56|0.03|0.05|N|O|1996-09-13|1996-09-12|1996-09-30|TAKE BACK RETURN|REG AIR|usly even packages. slyly brave s +11617|149032|9033|1|8|8648.24|0.05|0.02|R|F|1994-12-29|1995-01-29|1995-01-25|TAKE BACK RETURN|FOB|usly final ideas affix +11617|173791|3792|2|46|85780.34|0.02|0.04|A|F|1995-04-03|1995-01-14|1995-04-23|DELIVER IN PERSON|FOB|s sleep blithely ironic pl +11617|98628|1138|3|33|53678.46|0.08|0.02|A|F|1995-03-20|1995-02-27|1995-03-30|DELIVER IN PERSON|SHIP|slyly express packa +11617|32169|7176|4|2|2202.32|0.00|0.03|A|F|1995-03-02|1995-02-14|1995-03-10|NONE|AIR|s. slyly bold f +11617|59492|9493|5|16|23223.84|0.04|0.04|R|F|1995-03-07|1995-02-17|1995-04-04|DELIVER IN PERSON|SHIP|leep carefully. quickly pending +11617|68657|6176|6|9|14630.85|0.03|0.01|A|F|1995-01-06|1995-03-05|1995-01-13|TAKE BACK RETURN|MAIL|c theodolites. bold excuses boost slyly ne +11618|59367|4378|1|27|35811.72|0.01|0.02|N|O|1998-05-17|1998-04-01|1998-05-25|COLLECT COD|SHIP|e of the asymptotes are quickly pinto +11618|168154|671|2|4|4888.60|0.00|0.03|N|O|1998-02-23|1998-04-23|1998-03-18|DELIVER IN PERSON|MAIL|t have to sleep carefully in place of the i +11618|150644|8190|3|22|37282.08|0.08|0.06|N|O|1998-03-02|1998-03-19|1998-03-28|NONE|AIR|. express platelets breach quickly along +11618|58153|3164|4|6|6666.90|0.07|0.00|N|O|1998-03-20|1998-04-04|1998-03-23|COLLECT COD|SHIP|ages: busily r +11618|176547|1582|5|25|40588.50|0.07|0.06|N|O|1998-06-04|1998-04-26|1998-07-02|DELIVER IN PERSON|RAIL|d packages? furiousl +11619|166090|8607|1|8|9248.72|0.02|0.00|N|O|1998-10-15|1998-08-12|1998-11-05|DELIVER IN PERSON|MAIL|bold accounts. daring, unu +11619|73698|6206|2|10|16716.90|0.08|0.04|N|O|1998-08-05|1998-10-09|1998-09-02|NONE|SHIP|ptotes use quickly furiously regular p +11619|36284|8788|3|13|15863.64|0.09|0.00|N|O|1998-10-27|1998-08-26|1998-11-07|DELIVER IN PERSON|MAIL|ding dependencies boost fluffily even, +11620|178525|1043|1|7|11224.64|0.09|0.04|N|O|1997-07-28|1997-10-07|1997-08-22|COLLECT COD|RAIL| quickly. fluffily ironic +11620|53711|6217|2|5|8323.55|0.00|0.08|N|O|1997-09-23|1997-10-16|1997-09-26|NONE|REG AIR|uriously express orbits. furiou +11620|106333|8844|3|23|30804.59|0.09|0.05|N|O|1997-08-18|1997-09-15|1997-09-11|COLLECT COD|RAIL|into beans. final accounts above the regul +11620|137631|5171|4|26|43384.38|0.08|0.06|N|O|1997-07-29|1997-09-13|1997-08-19|NONE|FOB|riously regular warhorses use slyly am +11620|152910|5426|5|31|60850.21|0.07|0.03|N|O|1997-09-26|1997-10-18|1997-10-14|COLLECT COD|RAIL|quests. bold requests alongside o +11621|127197|4734|1|8|9793.52|0.03|0.08|N|O|1996-01-20|1996-01-26|1996-02-12|COLLECT COD|AIR|usual requests +11621|191934|9492|2|47|95218.71|0.03|0.03|N|O|1996-02-12|1995-12-25|1996-03-10|NONE|AIR|ironic ideas impress quickly enti +11621|19965|7469|3|12|22619.52|0.01|0.05|N|O|1995-12-01|1996-02-07|1995-12-30|COLLECT COD|RAIL|regular excuses; deposits affix fu +11621|137250|9764|4|10|12872.50|0.02|0.03|N|O|1996-01-14|1995-12-13|1996-01-28|COLLECT COD|RAIL|pinto beans. carefully final +11621|152524|70|5|35|55178.20|0.01|0.05|N|O|1996-01-08|1996-01-01|1996-01-14|TAKE BACK RETURN|SHIP|o the blithely regular accounts. idly +11621|59206|6722|6|42|48938.40|0.09|0.05|N|O|1995-12-07|1996-01-10|1995-12-17|TAKE BACK RETURN|MAIL|instructions are according to the care +11622|150070|2586|1|22|24641.54|0.02|0.07|N|O|1996-06-01|1996-07-25|1996-06-04|DELIVER IN PERSON|MAIL|cial foxes. slyly thin platelets around +11622|23819|3820|2|20|34856.20|0.07|0.00|N|O|1996-05-22|1996-06-18|1996-06-19|NONE|REG AIR|old dependencies. slyly regular dolphi +11622|122888|7913|3|40|76435.20|0.03|0.03|N|O|1996-08-02|1996-06-20|1996-08-20|TAKE BACK RETURN|SHIP| ironic instructions n +11622|163017|566|4|20|21600.20|0.06|0.07|N|O|1996-07-31|1996-07-22|1996-08-25|COLLECT COD|SHIP|nding realms integrate slyly careful +11622|16344|8846|5|40|50413.60|0.09|0.03|N|O|1996-06-19|1996-05-27|1996-06-23|NONE|SHIP|lly bold ideas cajole slyly across the +11623|71504|4012|1|45|66397.50|0.03|0.01|N|O|1996-01-15|1996-03-06|1996-01-19|COLLECT COD|AIR|c deposits. pending f +11623|161341|3858|2|48|67312.32|0.05|0.01|N|O|1996-03-27|1996-03-03|1996-04-13|NONE|AIR|ely regular requests. ideas beyond the bli +11623|57154|7155|3|35|38890.25|0.07|0.04|N|O|1996-02-16|1996-01-21|1996-03-07|DELIVER IN PERSON|TRUCK|ons are. fluffi +11623|174001|1553|4|19|20425.00|0.04|0.03|N|O|1996-03-25|1996-01-18|1996-04-13|DELIVER IN PERSON|MAIL|cording to the pending +11623|19513|9514|5|15|21487.65|0.10|0.05|N|O|1995-12-18|1996-02-24|1995-12-31|TAKE BACK RETURN|SHIP|. dolphins cajole blithely. quickly expres +11623|141995|1996|6|46|93701.54|0.06|0.00|N|O|1996-04-05|1996-03-05|1996-04-30|DELIVER IN PERSON|SHIP|tructions. fluffily final warhorses engag +11623|101572|4083|7|46|72384.22|0.09|0.08|N|O|1995-12-28|1996-03-14|1996-01-24|NONE|SHIP|ts. furiou +11648|113296|830|1|38|49753.02|0.02|0.00|R|F|1995-05-18|1995-06-21|1995-05-21|NONE|REG AIR|eodolites +11648|162352|2353|2|39|55159.65|0.01|0.00|N|O|1995-08-07|1995-06-17|1995-08-15|COLLECT COD|FOB|egular braids run furiousl +11648|35732|5733|3|5|8338.65|0.04|0.08|A|F|1995-04-26|1995-06-20|1995-05-01|NONE|SHIP|ter the carefully iron +11648|146055|1084|4|2|2202.10|0.05|0.08|R|F|1995-05-08|1995-07-01|1995-05-26|NONE|REG AIR|riously carefully +11648|143599|8628|5|38|62418.42|0.10|0.06|N|O|1995-06-24|1995-07-04|1995-07-24|COLLECT COD|RAIL|ly express requests. regular as +11648|57011|9517|6|22|21296.22|0.03|0.00|A|F|1995-05-01|1995-06-20|1995-05-12|DELIVER IN PERSON|REG AIR| haggle bravely t +11648|169231|9232|7|24|31205.52|0.07|0.05|N|O|1995-08-06|1995-06-09|1995-09-03|COLLECT COD|MAIL|. sometimes even deposits +11649|61039|3546|1|3|3000.09|0.08|0.00|N|O|1996-08-07|1996-09-08|1996-08-22|COLLECT COD|REG AIR|sits. carefully regular pac +11649|72671|2672|2|35|57528.45|0.06|0.01|N|O|1996-10-16|1996-09-08|1996-11-11|COLLECT COD|TRUCK|y final th +11649|168787|1304|3|45|83510.10|0.03|0.03|N|O|1996-07-20|1996-07-30|1996-07-30|COLLECT COD|REG AIR|nic packages. quickly express dolphins aff +11649|188093|3130|4|44|51967.96|0.10|0.04|N|O|1996-09-21|1996-09-19|1996-10-16|COLLECT COD|TRUCK|osits wake blithely. special dependencies w +11649|67965|7966|5|40|77318.40|0.04|0.04|N|O|1996-08-01|1996-08-24|1996-08-22|COLLECT COD|FOB|ely ironic requests cajole thinly slyly exp +11649|71731|1732|6|16|27243.68|0.06|0.03|N|O|1996-07-21|1996-08-13|1996-08-04|COLLECT COD|FOB|le. slyly regular ideas sleep ironically qu +11649|178827|3862|7|26|49551.32|0.01|0.04|N|O|1996-08-19|1996-08-28|1996-08-22|COLLECT COD|SHIP|ilently regular accounts cajole +11650|133459|5973|1|48|71637.60|0.06|0.01|A|F|1992-11-23|1992-12-02|1992-12-23|DELIVER IN PERSON|MAIL|fily final ideas. +11650|44339|1852|2|50|64166.50|0.03|0.07|R|F|1993-01-06|1992-12-12|1993-01-16|DELIVER IN PERSON|TRUCK|lly special theodo +11650|3391|8392|3|30|38831.70|0.04|0.00|R|F|1992-11-09|1992-12-18|1992-11-25|DELIVER IN PERSON|FOB|urts. somet +11651|138059|5599|1|41|44979.05|0.00|0.06|A|F|1995-05-26|1995-04-19|1995-06-16|DELIVER IN PERSON|RAIL|ould have to are. slyly expre +11651|156233|1264|2|8|10313.84|0.08|0.03|N|F|1995-06-03|1995-04-08|1995-06-18|TAKE BACK RETURN|RAIL|ic accounts detect +11652|197430|2469|1|39|59569.77|0.07|0.04|N|O|1995-12-22|1996-01-28|1996-01-04|TAKE BACK RETURN|TRUCK|nic sentiments bo +11652|199693|9694|2|11|19719.59|0.06|0.06|N|O|1996-02-13|1996-01-16|1996-03-01|COLLECT COD|AIR|ges. silent, silent waters cajole +11652|29189|9190|3|28|31309.04|0.08|0.08|N|O|1996-02-11|1996-01-04|1996-02-28|DELIVER IN PERSON|FOB| final requests doubt furiously +11652|167214|4763|4|24|30749.04|0.02|0.02|N|O|1996-02-28|1996-01-30|1996-03-07|COLLECT COD|AIR|y about the s +11652|164074|1623|5|10|11380.70|0.07|0.08|N|O|1996-01-26|1996-01-13|1996-02-20|TAKE BACK RETURN|REG AIR|blithely express as +11652|185690|8209|6|8|14205.52|0.10|0.00|N|O|1996-03-01|1996-01-30|1996-03-13|COLLECT COD|MAIL|an sleep furiously silent Tiresias; bold, s +11652|81147|8672|7|21|23690.94|0.03|0.07|N|O|1996-02-26|1996-01-22|1996-03-18|DELIVER IN PERSON|SHIP|quickly regular packages haggle. frays h +11653|36226|8730|1|18|20919.96|0.01|0.01|N|O|1997-09-30|1997-08-24|1997-10-05|DELIVER IN PERSON|FOB|. carefully pending +11653|45469|2982|2|25|35361.50|0.07|0.01|N|O|1997-09-27|1997-09-25|1997-10-26|TAKE BACK RETURN|TRUCK| even packages. reg +11653|191348|3868|3|27|38862.18|0.01|0.04|N|O|1997-10-26|1997-08-18|1997-11-17|TAKE BACK RETURN|AIR|regular packages. pending pa +11653|178332|850|4|42|59233.86|0.10|0.01|N|O|1997-07-30|1997-09-18|1997-08-20|DELIVER IN PERSON|MAIL|ar, regular ideas integrate quickly +11653|15888|5889|5|22|39685.36|0.07|0.00|N|O|1997-09-01|1997-08-31|1997-09-18|COLLECT COD|AIR|pendencies. blithely even pa +11654|74512|2034|1|47|69865.97|0.06|0.02|R|F|1993-11-29|1993-12-23|1993-12-15|COLLECT COD|MAIL|sleep blithely against the furiously ironi +11654|117724|5258|2|39|67927.08|0.03|0.00|A|F|1993-11-29|1993-12-01|1993-12-22|NONE|FOB|ts integrate blithely. even, enticing inst +11655|135252|7766|1|32|41192.00|0.04|0.04|N|O|1998-08-11|1998-09-25|1998-09-02|TAKE BACK RETURN|SHIP|g to the slyly ironic requests. +11655|174050|1602|2|49|55078.45|0.06|0.07|N|O|1998-07-04|1998-09-20|1998-07-06|COLLECT COD|SHIP|nal courts. s +11655|49898|7411|3|46|85002.94|0.01|0.00|N|O|1998-10-10|1998-09-01|1998-10-21|DELIVER IN PERSON|MAIL|ges. blithely even accounts sleep furiou +11680|24361|1868|1|27|34704.72|0.00|0.01|A|F|1994-11-10|1994-11-05|1994-11-12|TAKE BACK RETURN|SHIP|ounts haggle blithely +11680|26880|1885|2|35|63240.80|0.09|0.01|R|F|1994-09-17|1994-11-29|1994-09-25|NONE|MAIL|ly pending gifts sleep carefully +11680|168923|6472|3|43|85652.56|0.06|0.01|R|F|1994-11-05|1994-11-16|1994-11-25|COLLECT COD|MAIL|integrate furiously. special instruct +11680|84966|7475|4|49|95597.04|0.02|0.08|R|F|1994-11-05|1994-11-05|1994-11-20|TAKE BACK RETURN|REG AIR| carefully express, spec +11680|20183|2686|5|24|26476.32|0.01|0.00|R|F|1994-09-08|1994-11-11|1994-09-09|NONE|TRUCK|silent depo +11680|14963|7465|6|26|48826.96|0.10|0.01|R|F|1994-10-22|1994-11-02|1994-11-02|NONE|MAIL|uickly above the slyly pending +11680|69164|1671|7|9|10198.44|0.09|0.02|R|F|1994-12-20|1994-11-29|1995-01-19|DELIVER IN PERSON|AIR|ently ironic grouches after the +11681|22974|7979|1|28|53115.16|0.07|0.02|A|F|1993-02-15|1992-12-11|1993-03-04|TAKE BACK RETURN|REG AIR| carefully carefully ruth +11681|123592|8617|2|37|59776.83|0.06|0.06|A|F|1992-12-29|1992-12-11|1993-01-27|TAKE BACK RETURN|RAIL|y ironic ideas. slyly ironic re +11681|904|905|3|31|55951.90|0.09|0.01|A|F|1993-01-26|1992-12-18|1993-02-07|NONE|AIR|uffily. ideas kin +11681|191944|1945|4|30|61078.20|0.02|0.06|A|F|1993-01-12|1992-11-24|1993-02-09|NONE|RAIL|. theodolites across the even packages are +11681|199627|7185|5|47|81151.14|0.02|0.05|A|F|1993-01-27|1992-12-13|1993-01-29|COLLECT COD|TRUCK|ly even depths. furious +11682|31634|4138|1|13|20353.19|0.06|0.06|R|F|1993-10-04|1993-08-06|1993-10-11|NONE|REG AIR|lyly among the pending platelets. +11682|68851|1358|2|35|63694.75|0.05|0.08|R|F|1993-11-01|1993-09-07|1993-11-04|TAKE BACK RETURN|RAIL|ly even foxes +11682|177152|9670|3|46|56540.90|0.02|0.07|R|F|1993-08-06|1993-10-03|1993-08-28|COLLECT COD|AIR|arefully unusual or +11683|162515|64|1|31|48902.81|0.00|0.01|R|F|1992-05-04|1992-04-01|1992-06-03|NONE|MAIL|y regular requests. foxes eat fu +11683|179349|4384|2|18|25710.12|0.08|0.04|A|F|1992-03-15|1992-03-28|1992-03-19|NONE|TRUCK|nstructions. blithely even accounts cajole +11683|111989|1990|3|38|76037.24|0.04|0.07|A|F|1992-05-29|1992-03-17|1992-06-19|NONE|MAIL|totes use slyly carefully bold pa +11683|198711|8712|4|1|1809.71|0.08|0.05|R|F|1992-03-17|1992-03-31|1992-03-29|DELIVER IN PERSON|FOB|beans are furiously blithe platele +11683|122448|7473|5|7|10293.08|0.09|0.02|A|F|1992-06-01|1992-03-26|1992-06-25|NONE|AIR| requests. slyly u +11683|171639|9191|6|8|13685.04|0.03|0.03|R|F|1992-05-27|1992-03-20|1992-06-12|NONE|SHIP|l dolphins: quickly even packa +11683|124774|4775|7|40|71950.80|0.08|0.05|A|F|1992-03-02|1992-03-11|1992-04-01|COLLECT COD|MAIL|ooze alongsi +11684|61558|4065|1|48|72938.40|0.03|0.02|A|F|1992-11-15|1992-10-05|1992-11-25|COLLECT COD|TRUCK|ld pinto beans. carefully d +11684|191251|3771|2|30|40267.50|0.07|0.03|R|F|1992-10-10|1992-09-09|1992-10-19|TAKE BACK RETURN|TRUCK|ckly. blithe +11684|143701|8730|3|27|47106.90|0.02|0.04|R|F|1992-09-03|1992-09-15|1992-10-02|DELIVER IN PERSON|MAIL|ironic pinto beans-- sly depos +11684|170381|5416|4|49|71117.62|0.08|0.05|R|F|1992-08-24|1992-09-08|1992-09-02|NONE|FOB|yly across the furiously pending +11684|190117|2637|5|25|30177.75|0.01|0.01|A|F|1992-10-20|1992-10-19|1992-11-09|DELIVER IN PERSON|AIR|e theodolites. foxes solve carefu +11685|64149|4150|1|19|21149.66|0.08|0.04|N|O|1997-04-02|1997-04-22|1997-05-01|NONE|AIR|ly bold platele +11685|146250|3793|2|16|20740.00|0.04|0.02|N|O|1997-06-24|1997-05-28|1997-06-28|TAKE BACK RETURN|RAIL|sits haggle +11685|7071|4572|3|7|6846.49|0.06|0.07|N|O|1997-04-01|1997-04-30|1997-04-05|NONE|FOB| to the flu +11685|36369|3879|4|19|24801.84|0.01|0.07|N|O|1997-06-13|1997-04-23|1997-07-04|COLLECT COD|FOB|ests. carefully regular requests among +11685|50022|7538|5|36|34992.72|0.01|0.00|N|O|1997-07-10|1997-05-26|1997-08-07|DELIVER IN PERSON|FOB|regular platelets. asymp +11685|119379|9380|6|30|41951.10|0.03|0.06|N|O|1997-04-05|1997-06-13|1997-04-12|DELIVER IN PERSON|AIR|ily ironic theod +11685|192949|2950|7|50|102097.00|0.06|0.04|N|O|1997-04-23|1997-06-05|1997-05-20|DELIVER IN PERSON|REG AIR|nts. furiously final d +11686|89930|7455|1|36|69117.48|0.10|0.01|A|F|1994-03-28|1994-04-04|1994-04-02|COLLECT COD|FOB|ts cajole. carefully +11686|49749|2254|2|5|8493.70|0.01|0.04|R|F|1994-04-18|1994-04-05|1994-05-12|TAKE BACK RETURN|SHIP|nding pinto beans h +11686|128836|8837|3|50|93241.50|0.04|0.01|A|F|1994-02-06|1994-03-12|1994-02-14|DELIVER IN PERSON|RAIL|he final theodolite +11686|140082|83|4|37|41516.96|0.07|0.01|R|F|1994-03-09|1994-04-18|1994-04-07|DELIVER IN PERSON|MAIL|ully along +11687|23468|975|1|23|32003.58|0.07|0.00|N|O|1996-02-22|1996-02-04|1996-02-28|NONE|FOB| are slyly bold ideas. +11687|13326|3327|2|18|22307.76|0.10|0.07|N|O|1996-04-04|1996-02-29|1996-05-03|NONE|REG AIR|he slyly regular accounts. final requests +11687|162717|266|3|23|40933.33|0.02|0.08|N|O|1996-02-28|1996-02-06|1996-03-22|DELIVER IN PERSON|RAIL|al instructions +11687|180603|604|4|32|53875.20|0.08|0.01|N|O|1996-01-09|1996-03-08|1996-01-20|NONE|AIR|uses detect slyly. slyly even accou +11687|187801|5356|5|28|52886.40|0.00|0.05|N|O|1996-01-05|1996-02-21|1996-01-10|TAKE BACK RETURN|TRUCK|nts cajole +11712|152579|2580|1|19|30999.83|0.10|0.04|A|F|1994-06-23|1994-07-24|1994-07-01|NONE|MAIL|y final reque +11712|178601|1119|2|36|60465.60|0.07|0.05|R|F|1994-05-14|1994-07-09|1994-05-15|COLLECT COD|TRUCK|dolites. furiously +11712|134274|6788|3|26|34015.02|0.03|0.04|R|F|1994-08-23|1994-06-26|1994-09-22|NONE|AIR|ounts are. slyly quick theodolites ough +11713|135589|8103|1|17|27617.86|0.10|0.08|R|F|1994-03-11|1994-02-07|1994-03-28|COLLECT COD|MAIL|kages. carefully ironic reques +11713|42573|2574|2|33|50013.81|0.04|0.03|A|F|1994-03-11|1994-02-09|1994-03-21|NONE|TRUCK|gle fluffily quickly c +11713|123091|3092|3|46|51248.14|0.09|0.06|A|F|1994-04-07|1994-03-08|1994-04-08|DELIVER IN PERSON|TRUCK|ly final foxes sleep fl +11713|184762|7281|4|6|11080.56|0.10|0.07|A|F|1994-03-19|1994-02-20|1994-04-05|COLLECT COD|REG AIR|mong the even instructions wake f +11714|143625|6140|1|24|40046.88|0.09|0.02|A|F|1994-10-20|1994-10-27|1994-11-14|DELIVER IN PERSON|FOB|ily blithely unusual deposits. quietly reg +11714|94110|6620|2|20|22082.20|0.01|0.05|A|F|1994-11-20|1994-10-29|1994-11-24|DELIVER IN PERSON|FOB|g after the pending reques +11714|102084|4595|3|46|49959.68|0.09|0.06|A|F|1994-08-29|1994-09-13|1994-09-04|TAKE BACK RETURN|TRUCK|ites wake sometim +11714|116041|6042|4|23|24311.92|0.07|0.08|A|F|1994-11-11|1994-10-29|1994-12-08|DELIVER IN PERSON|AIR|r ideas. furious pinto beans wake slyl +11714|99079|6607|5|17|18327.19|0.08|0.04|R|F|1994-11-05|1994-09-05|1994-11-11|TAKE BACK RETURN|RAIL| ideas should haggle furiously +11714|5889|890|6|6|10769.28|0.00|0.01|A|F|1994-11-01|1994-10-27|1994-11-14|DELIVER IN PERSON|SHIP|requests. ironic, even requests +11715|90962|963|1|7|13670.72|0.08|0.02|R|F|1994-10-02|1994-10-30|1994-10-22|COLLECT COD|RAIL|s. regular, exp +11715|194622|9661|2|25|42915.50|0.03|0.05|A|F|1994-10-18|1994-10-30|1994-10-26|TAKE BACK RETURN|TRUCK|etly slyly regular requests +11715|11374|8878|3|2|2570.74|0.05|0.01|A|F|1994-12-03|1994-11-13|1994-12-19|TAKE BACK RETURN|FOB|. slyly regular depths n +11715|157821|5367|4|4|7515.28|0.01|0.05|A|F|1995-01-04|1994-12-05|1995-01-18|DELIVER IN PERSON|REG AIR|ording to the dogged packages. ironic bra +11716|144142|6657|1|38|45073.32|0.02|0.03|A|F|1994-02-09|1993-11-28|1994-03-05|TAKE BACK RETURN|MAIL|osits promise closely. slyly b +11716|180178|2697|2|41|51584.97|0.09|0.03|R|F|1993-11-11|1993-12-31|1993-11-29|NONE|AIR|t theodolites among the unusu +11716|42719|5224|3|48|79762.08|0.08|0.05|A|F|1993-11-27|1993-12-09|1993-12-07|NONE|RAIL|ual accounts affix s +11717|188907|8908|1|12|23950.80|0.00|0.06|N|O|1998-06-21|1998-05-11|1998-06-25|NONE|AIR| packages play regular, ironic req +11717|156726|4272|2|41|73091.52|0.08|0.08|N|O|1998-04-19|1998-05-13|1998-04-30|NONE|AIR|haggle behind the pending, bol +11717|81925|4434|3|11|20976.12|0.04|0.00|N|O|1998-05-02|1998-06-16|1998-05-07|TAKE BACK RETURN|MAIL|gular ideas use furiously against the +11717|103486|1017|4|38|56600.24|0.04|0.04|N|O|1998-03-23|1998-05-11|1998-04-06|DELIVER IN PERSON|SHIP|deposits. quickly +11717|82061|7078|5|10|10430.60|0.07|0.06|N|O|1998-06-15|1998-05-21|1998-07-07|COLLECT COD|SHIP|egular accounts. furiously bu +11718|76551|1566|1|20|30551.00|0.00|0.06|A|F|1995-04-12|1995-03-11|1995-05-03|COLLECT COD|MAIL|across the regular in +11719|94710|4711|1|21|35798.91|0.03|0.01|A|F|1995-04-16|1995-05-07|1995-05-02|NONE|AIR|carefully against the +11719|179157|6709|2|44|54390.60|0.06|0.00|R|F|1995-03-27|1995-03-09|1995-04-06|DELIVER IN PERSON|TRUCK|sits are bli +11719|88684|8685|3|5|8363.40|0.10|0.06|R|F|1995-05-30|1995-03-19|1995-06-06|DELIVER IN PERSON|SHIP|deas detect past t +11719|97588|5116|4|17|26954.86|0.01|0.03|A|F|1995-02-20|1995-03-29|1995-03-19|COLLECT COD|SHIP| excuses integrate +11719|159291|4322|5|40|54011.60|0.02|0.00|A|F|1995-03-29|1995-03-09|1995-04-09|DELIVER IN PERSON|AIR|hs. carefully fluffy +11719|197506|5064|6|18|28863.00|0.05|0.02|R|F|1995-03-09|1995-04-11|1995-03-13|TAKE BACK RETURN|SHIP|nt accounts. fluffily sly +11744|82750|2751|1|28|48517.00|0.06|0.03|N|O|1996-09-12|1996-08-16|1996-09-23|NONE|FOB|eep ironically. slyl +11744|171974|1975|2|42|85930.74|0.01|0.02|N|O|1996-08-25|1996-09-01|1996-08-29|TAKE BACK RETURN|SHIP|requests use quickly; blithely express +11744|152329|7360|3|50|69066.00|0.07|0.03|N|O|1996-09-21|1996-08-25|1996-10-15|NONE|FOB| regular packages believe above the re +11745|124422|6935|1|34|49178.28|0.03|0.01|R|F|1992-08-03|1992-09-29|1992-08-28|NONE|AIR|s wake. regular platelets haggle ag +11745|153385|931|2|35|50343.30|0.02|0.03|R|F|1992-09-13|1992-09-23|1992-09-19|NONE|RAIL| even sheaves! slyly sile +11745|125755|5756|3|29|51641.75|0.02|0.00|A|F|1992-10-02|1992-10-14|1992-10-17|COLLECT COD|REG AIR|ns around the carefully final theo +11745|152344|7375|4|12|16756.08|0.07|0.08|A|F|1992-09-17|1992-08-28|1992-09-20|COLLECT COD|TRUCK| the ironic, reg +11745|33891|3892|5|7|12774.23|0.07|0.03|A|F|1992-11-16|1992-08-29|1992-11-26|COLLECT COD|TRUCK|mptotes. acc +11746|180724|725|1|22|39703.84|0.09|0.05|N|O|1998-05-09|1998-07-05|1998-05-12|DELIVER IN PERSON|RAIL|rbits according +11746|16197|1200|2|6|6679.14|0.04|0.06|N|O|1998-05-27|1998-06-12|1998-06-09|NONE|RAIL|deas. slowly regul +11746|13705|3706|3|25|40467.50|0.00|0.02|N|O|1998-08-27|1998-06-08|1998-09-01|COLLECT COD|REG AIR|en deposits de +11746|131768|9308|4|26|46793.76|0.00|0.02|N|O|1998-08-09|1998-06-30|1998-08-14|COLLECT COD|REG AIR|st across the ir +11746|17060|7061|5|13|12701.78|0.01|0.02|N|O|1998-06-16|1998-07-14|1998-07-01|DELIVER IN PERSON|RAIL|nusual excu +11746|114250|6762|6|36|45513.00|0.00|0.06|N|O|1998-08-16|1998-06-15|1998-08-26|COLLECT COD|REG AIR| the slyly ironic accounts. i +11746|193807|3808|7|12|22809.60|0.06|0.07|N|O|1998-07-22|1998-06-20|1998-07-23|DELIVER IN PERSON|RAIL|heodolites haggle slowly +11747|99279|6807|1|27|34513.29|0.10|0.01|A|F|1993-06-25|1993-04-13|1993-07-16|COLLECT COD|TRUCK|y express requests. regular de +11748|197679|7680|1|23|40863.41|0.00|0.00|A|F|1994-07-04|1994-07-30|1994-07-15|COLLECT COD|AIR|its against the +11749|76477|3999|1|7|10174.29|0.01|0.07|N|O|1998-04-11|1998-05-02|1998-04-15|COLLECT COD|SHIP|ully according to t +11749|142096|4611|2|48|54628.32|0.02|0.01|N|O|1998-05-24|1998-05-11|1998-06-20|NONE|TRUCK|packages. deposits slee +11750|143307|5822|1|23|31056.90|0.07|0.08|N|O|1997-04-21|1997-04-21|1997-04-25|COLLECT COD|TRUCK|ending excuses. packages hagg +11750|148878|6421|2|21|40464.27|0.06|0.06|N|O|1997-06-09|1997-05-18|1997-06-19|DELIVER IN PERSON|TRUCK|ronic dinos cajole +11750|191844|9402|3|31|60011.04|0.02|0.02|N|O|1997-06-27|1997-04-08|1997-07-09|TAKE BACK RETURN|AIR|ckages. caref +11750|108784|1295|4|1|1792.78|0.05|0.08|N|O|1997-04-02|1997-04-14|1997-04-13|DELIVER IN PERSON|SHIP| even dugouts; slyly special i +11751|90705|706|1|23|39001.10|0.05|0.00|N|O|1996-07-06|1996-08-19|1996-07-19|COLLECT COD|RAIL| the regular packages thrash ironic, ir +11751|71117|6132|2|45|48964.95|0.08|0.07|N|O|1996-09-05|1996-07-12|1996-09-07|DELIVER IN PERSON|SHIP|theodolites. carefully even r +11751|54146|4147|3|5|5500.70|0.06|0.08|N|O|1996-07-09|1996-08-10|1996-08-01|COLLECT COD|AIR|efully express foxes hagg +11751|20891|892|4|29|52544.81|0.01|0.01|N|O|1996-06-09|1996-08-19|1996-07-05|TAKE BACK RETURN|REG AIR|gular excuses wak +11776|180896|8451|1|50|98844.50|0.07|0.08|A|F|1992-05-26|1992-04-21|1992-05-31|NONE|AIR|kly regular accounts believe account +11776|102368|2369|2|5|6851.80|0.10|0.02|A|F|1992-06-05|1992-03-28|1992-06-12|COLLECT COD|MAIL|fully carefully pending +11777|187033|9552|1|31|34720.93|0.05|0.08|R|F|1995-03-13|1995-03-16|1995-03-30|NONE|SHIP|grate carefully according to t +11778|134653|4654|1|43|72568.95|0.04|0.05|N|O|1997-06-21|1997-05-07|1997-07-02|COLLECT COD|MAIL|tions according to the furiously +11778|107426|7427|2|5|7167.10|0.08|0.05|N|O|1997-07-01|1997-06-20|1997-07-15|TAKE BACK RETURN|SHIP|wake carefully regular sauternes. sl +11778|106511|9022|3|47|71322.97|0.05|0.02|N|O|1997-05-20|1997-06-05|1997-05-31|DELIVER IN PERSON|TRUCK|accounts. slyly even requests are be +11779|150205|7751|1|15|18828.00|0.05|0.08|R|F|1993-10-05|1993-08-06|1993-10-10|NONE|SHIP|about the quickly pend +11779|86451|3976|2|9|12937.05|0.00|0.03|A|F|1993-10-15|1993-09-27|1993-11-13|COLLECT COD|RAIL|ins are carefull +11779|170976|3494|3|27|55268.19|0.03|0.01|R|F|1993-10-25|1993-08-04|1993-11-13|COLLECT COD|RAIL|. fluffily eve +11779|181843|1844|4|7|13473.88|0.06|0.03|A|F|1993-10-24|1993-09-21|1993-11-08|NONE|MAIL|y bold excuses sleep sl +11779|20624|8131|5|50|77231.00|0.06|0.08|R|F|1993-09-30|1993-09-10|1993-10-20|TAKE BACK RETURN|TRUCK|thely bold packages nag carefully q +11779|15122|125|6|32|33187.84|0.02|0.06|R|F|1993-08-12|1993-09-23|1993-09-11|TAKE BACK RETURN|REG AIR|r deposits cajole sl +11780|39412|4419|1|41|55407.81|0.09|0.07|A|F|1993-10-21|1993-12-12|1993-10-30|TAKE BACK RETURN|SHIP| asymptotes. ironic, even ideas engage s +11780|194901|9940|2|36|71852.40|0.04|0.02|A|F|1993-12-24|1993-12-11|1994-01-09|DELIVER IN PERSON|RAIL|above the fluffily even a +11780|93548|3549|3|7|10790.78|0.09|0.05|R|F|1993-10-18|1993-11-28|1993-10-20|DELIVER IN PERSON|TRUCK|longside of the blithely +11781|34909|7413|1|37|68224.30|0.07|0.01|N|O|1996-06-14|1996-06-27|1996-06-20|TAKE BACK RETURN|MAIL|packages use alongside of +11781|113505|1039|2|42|63777.00|0.07|0.05|N|O|1996-04-24|1996-06-02|1996-04-28|NONE|SHIP| deposits wake. slyly regular dependenc +11781|68546|6065|3|42|63610.68|0.10|0.03|N|O|1996-07-08|1996-07-07|1996-07-17|NONE|TRUCK| express, +11782|159204|1720|1|27|34106.40|0.01|0.00|A|F|1992-08-10|1992-09-05|1992-08-20|DELIVER IN PERSON|AIR|above the quickly even pains. bold +11782|136196|3736|2|35|43126.65|0.09|0.08|A|F|1992-09-14|1992-09-06|1992-09-21|TAKE BACK RETURN|FOB|s eat slyly according to th +11782|36552|6553|3|50|74427.50|0.10|0.07|R|F|1992-10-25|1992-10-02|1992-11-07|COLLECT COD|MAIL|even accounts boost slyly de +11782|128290|8291|4|17|22410.93|0.07|0.04|R|F|1992-11-20|1992-09-20|1992-12-20|NONE|AIR|ess deposits cajole carefull +11783|59568|4579|1|3|4582.68|0.03|0.04|N|O|1998-06-12|1998-05-04|1998-06-21|DELIVER IN PERSON|MAIL|es nag. furiously ca +11783|156003|8519|2|13|13767.00|0.05|0.02|N|O|1998-07-20|1998-05-23|1998-07-26|DELIVER IN PERSON|SHIP|ly even theodolites are furiously. reg +11808|60788|789|1|12|20985.36|0.03|0.08|A|F|1992-11-15|1992-09-17|1992-11-27|TAKE BACK RETURN|RAIL|instructions affix closel +11808|52650|7661|2|30|48079.50|0.06|0.04|R|F|1992-09-03|1992-10-22|1992-09-20|TAKE BACK RETURN|SHIP|usual requests ha +11809|22356|7361|1|22|28123.70|0.07|0.07|N|O|1996-07-18|1996-07-18|1996-07-19|DELIVER IN PERSON|FOB|er the special platelets. request +11809|123135|5648|2|49|56748.37|0.03|0.03|N|O|1996-05-03|1996-06-15|1996-05-12|COLLECT COD|FOB|lar sauternes. slyly ironic packages ha +11809|113164|3165|3|18|21188.88|0.08|0.03|N|O|1996-07-21|1996-07-05|1996-08-10|TAKE BACK RETURN|AIR|ackages use thinly express +11809|132643|5157|4|29|48593.56|0.04|0.02|N|O|1996-06-04|1996-06-14|1996-06-18|NONE|MAIL|ely regular asymptotes lose caref +11809|114504|4505|5|3|4555.50|0.08|0.03|N|O|1996-08-04|1996-06-23|1996-08-22|TAKE BACK RETURN|SHIP|urts. deposits wake across the ideas. regul +11809|56578|4094|6|18|27622.26|0.02|0.01|N|O|1996-07-16|1996-06-10|1996-07-23|NONE|SHIP|ly even ideas integr +11810|69374|9375|1|47|63138.39|0.00|0.03|A|F|1992-08-02|1992-06-20|1992-08-22|NONE|RAIL|final foxes wake blithely regular idea +11811|105578|599|1|8|12668.56|0.09|0.06|A|F|1993-02-07|1992-11-28|1993-02-09|COLLECT COD|RAIL| quickly along the pendin +11812|592|5593|1|20|29851.80|0.05|0.00|A|F|1993-09-16|1993-08-23|1993-10-03|COLLECT COD|REG AIR|ounts doze regular +11813|147502|2531|1|49|75925.50|0.03|0.05|A|F|1994-05-24|1994-03-21|1994-05-26|COLLECT COD|MAIL|regular dependencies cajole carefu +11813|50530|8046|2|32|47376.96|0.02|0.04|A|F|1994-03-17|1994-04-27|1994-03-21|DELIVER IN PERSON|FOB|e alongside of the fu +11813|46828|1837|3|47|83416.54|0.02|0.07|R|F|1994-02-24|1994-04-13|1994-03-21|NONE|TRUCK|es impress quickly sly +11813|30924|3428|4|25|46373.00|0.02|0.00|R|F|1994-03-30|1994-05-07|1994-04-21|DELIVER IN PERSON|MAIL|side of the ironic, express pin +11814|115154|7666|1|9|10522.35|0.08|0.04|R|F|1993-04-25|1993-03-22|1993-04-29|TAKE BACK RETURN|RAIL|al accounts boost slyly alongsid +11814|183586|1141|2|46|76800.68|0.09|0.03|A|F|1993-04-09|1993-03-11|1993-04-19|COLLECT COD|RAIL|eposits wake. slyly regular pack +11814|115553|3087|3|39|61173.45|0.06|0.03|R|F|1993-05-12|1993-04-02|1993-06-01|NONE|TRUCK|ss pinto beans nod fl +11814|99147|6675|4|41|46991.74|0.04|0.00|A|F|1993-04-27|1993-03-06|1993-04-30|TAKE BACK RETURN|AIR|d the pinto b +11815|137648|162|1|38|64054.32|0.04|0.03|N|O|1995-10-31|1995-11-25|1995-11-06|COLLECT COD|REG AIR|e above the fluffily pending +11815|40332|333|2|28|35625.24|0.02|0.04|N|O|1995-10-22|1995-11-11|1995-10-29|TAKE BACK RETURN|AIR|ns doze ironically pendin +11815|45621|3134|3|37|57964.94|0.03|0.06|N|O|1995-10-29|1995-10-19|1995-11-05|DELIVER IN PERSON|SHIP|coys are. carefully ironic platelets hag +11815|137524|38|4|33|51530.16|0.02|0.06|N|O|1995-12-01|1995-10-22|1995-12-07|DELIVER IN PERSON|SHIP|uests are fluffily carefully sp +11815|161562|4079|5|12|19482.72|0.02|0.04|N|O|1995-11-21|1995-11-19|1995-12-18|DELIVER IN PERSON|REG AIR|silent deposit +11840|41372|1373|1|27|35460.99|0.01|0.08|A|F|1994-12-02|1994-10-03|1994-12-16|DELIVER IN PERSON|TRUCK|ymptotes. ironic accounts integra +11840|123478|1015|2|13|19519.11|0.10|0.05|R|F|1994-12-10|1994-10-27|1994-12-19|COLLECT COD|MAIL|lly regular packages. ruthlessly regu +11840|83851|6360|3|25|45871.25|0.10|0.01|A|F|1994-08-31|1994-10-08|1994-09-20|NONE|FOB|fluffily even accounts; quickly expr +11840|73814|6322|4|37|66148.97|0.00|0.06|R|F|1994-09-17|1994-10-15|1994-09-30|DELIVER IN PERSON|FOB|uests. pinto beans sleep regular pinto bea +11840|187166|9685|5|41|51379.56|0.06|0.01|R|F|1994-09-14|1994-10-16|1994-10-14|NONE|MAIL|even packages det +11840|86200|6201|6|33|39144.60|0.04|0.05|A|F|1994-10-23|1994-11-12|1994-11-19|COLLECT COD|RAIL| stealthy accounts wak +11841|16862|6863|1|22|39134.92|0.01|0.06|R|F|1993-07-28|1993-05-25|1993-08-21|COLLECT COD|MAIL|c pinto bea +11841|184199|4200|2|26|33362.94|0.06|0.05|R|F|1993-05-22|1993-06-21|1993-06-02|DELIVER IN PERSON|SHIP|ockey players. furiously even requ +11841|22484|4987|3|26|36568.48|0.09|0.05|A|F|1993-05-21|1993-06-21|1993-06-12|COLLECT COD|TRUCK|against the fi +11841|84012|4013|4|22|21912.22|0.06|0.07|A|F|1993-06-30|1993-06-06|1993-07-25|DELIVER IN PERSON|FOB|counts. furiously sp +11841|185853|8372|5|4|7755.40|0.03|0.01|A|F|1993-08-01|1993-07-08|1993-08-09|DELIVER IN PERSON|AIR|iously silent the +11841|24432|9437|6|14|18990.02|0.08|0.03|A|F|1993-05-10|1993-06-18|1993-06-06|COLLECT COD|MAIL|. special theodolites wake blithely +11842|62915|434|1|17|31924.47|0.08|0.00|N|O|1996-07-24|1996-06-12|1996-07-27|DELIVER IN PERSON|MAIL|ns sleep permanently blithely +11842|10020|5023|2|26|24180.52|0.02|0.06|N|O|1996-04-13|1996-05-25|1996-04-22|TAKE BACK RETURN|AIR|y silent excuses affix s +11842|191409|3929|3|21|31508.40|0.01|0.04|N|O|1996-04-14|1996-06-05|1996-04-27|NONE|AIR| according to the stealthily special ho +11843|189162|4199|1|37|46292.92|0.02|0.02|R|F|1994-11-10|1994-08-21|1994-11-22|NONE|AIR|e slyly final requests: fluffily pending +11843|36779|9283|2|32|54904.64|0.06|0.02|R|F|1994-07-26|1994-09-09|1994-08-12|NONE|FOB|es must hav +11843|141353|3868|3|50|69717.50|0.01|0.01|A|F|1994-07-25|1994-09-15|1994-08-02|NONE|SHIP| cajole above the ironic deposits. bl +11843|119667|9668|4|37|62406.42|0.04|0.05|R|F|1994-11-01|1994-10-04|1994-11-04|TAKE BACK RETURN|AIR|nal excuses. slyly special instruct +11844|48088|5601|1|5|5180.40|0.06|0.07|N|O|1997-04-06|1997-03-27|1997-04-24|NONE|AIR|odolites sl +11844|4272|9273|2|38|44698.26|0.09|0.08|N|O|1997-04-03|1997-02-27|1997-04-05|TAKE BACK RETURN|AIR|gainst the ide +11844|196609|9129|3|23|39228.80|0.06|0.08|N|O|1997-02-04|1997-03-19|1997-02-28|TAKE BACK RETURN|RAIL|y regular dependenc +11844|2641|2642|4|1|1543.64|0.03|0.08|N|O|1997-01-21|1997-03-13|1997-02-17|NONE|AIR|ending deposits wake theodolites. express +11845|152227|7258|1|5|6396.10|0.10|0.05|N|O|1997-05-29|1997-06-18|1997-06-03|NONE|MAIL|ding courts from the careful, +11845|64284|9297|2|30|37448.40|0.04|0.01|N|O|1997-07-18|1997-05-17|1997-08-07|COLLECT COD|REG AIR|ecial deposits. slyly final platele +11845|11614|1615|3|48|73229.28|0.05|0.08|N|O|1997-05-21|1997-06-25|1997-06-13|DELIVER IN PERSON|REG AIR|d packages sleep +11845|188155|674|4|13|16160.95|0.03|0.05|N|O|1997-06-14|1997-05-26|1997-07-05|TAKE BACK RETURN|TRUCK|efully across the quickly even theodolite +11846|142518|61|1|15|23407.65|0.04|0.03|A|F|1993-07-01|1993-07-06|1993-07-10|COLLECT COD|REG AIR| final instructions. sl +11846|85818|3343|2|17|30664.77|0.10|0.02|A|F|1993-07-22|1993-06-29|1993-08-08|TAKE BACK RETURN|SHIP|inal foxes run furiously. pi +11846|142868|7897|3|2|3821.72|0.04|0.00|R|F|1993-05-22|1993-07-16|1993-06-01|NONE|TRUCK|ecial accounts. +11846|175535|3087|4|1|1610.53|0.10|0.08|A|F|1993-07-01|1993-06-23|1993-07-06|COLLECT COD|RAIL|oach above the slyly regula +11847|110848|8382|1|19|35317.96|0.05|0.07|N|O|1997-11-10|1997-11-02|1997-12-06|COLLECT COD|FOB|lyly careful pinto beans are a +11847|17662|164|2|14|22115.24|0.02|0.00|N|O|1997-12-20|1997-12-02|1998-01-08|TAKE BACK RETURN|MAIL| ironic deposits. blithe +11847|33282|3283|3|10|12152.80|0.08|0.00|N|O|1997-10-31|1997-11-23|1997-11-30|TAKE BACK RETURN|FOB|final, ironic +11847|166839|9356|4|5|9529.15|0.04|0.05|N|O|1997-12-31|1997-12-25|1998-01-14|NONE|MAIL|fully among the express dependencies. +11847|49043|9044|5|4|3968.16|0.10|0.05|N|O|1997-10-14|1997-11-23|1997-11-04|NONE|MAIL|egular foxes. carefu +11847|49355|9356|6|26|33913.10|0.07|0.06|N|O|1997-12-15|1997-11-07|1997-12-23|TAKE BACK RETURN|AIR|efully regular deposits. carefully iron +11872|97438|2457|1|43|61723.49|0.07|0.01|A|F|1994-10-29|1994-10-07|1994-11-17|COLLECT COD|MAIL|pecial depo +11873|69603|4616|1|14|22016.40|0.07|0.01|N|O|1996-06-23|1996-07-05|1996-07-20|COLLECT COD|FOB|er. regular foxes above the platele +11874|133463|5977|1|50|74823.00|0.09|0.00|R|F|1992-12-02|1992-10-10|1992-12-15|COLLECT COD|REG AIR|mptotes. pending requests +11874|106147|8658|2|20|23062.80|0.03|0.05|A|F|1992-12-17|1992-10-29|1992-12-19|NONE|FOB|esias. slyly pending requests are accord +11874|9919|2420|3|29|53038.39|0.02|0.07|R|F|1992-11-11|1992-11-05|1992-11-17|COLLECT COD|TRUCK|eep blithely quickly special +11874|106947|9458|4|15|29309.10|0.05|0.08|R|F|1992-10-24|1992-10-22|1992-11-22|COLLECT COD|RAIL|ole ironic instructions +11874|49149|4158|5|44|48318.16|0.02|0.00|A|F|1992-12-19|1992-10-28|1993-01-01|DELIVER IN PERSON|TRUCK| slyly regular accounts. unusual pinto +11874|45226|5227|6|9|10540.98|0.10|0.03|A|F|1992-10-12|1992-12-02|1992-10-31|COLLECT COD|REG AIR|the pending, +11874|107079|4610|7|32|34754.24|0.08|0.01|R|F|1992-12-25|1992-12-07|1993-01-15|DELIVER IN PERSON|RAIL|he carefull +11875|68212|5731|1|40|47208.40|0.04|0.05|R|F|1992-11-11|1992-10-27|1992-12-03|COLLECT COD|MAIL|olphins sleep slyl +11875|22448|7453|2|30|41113.20|0.05|0.03|R|F|1992-09-08|1992-10-23|1992-10-08|TAKE BACK RETURN|RAIL|egular packages; +11875|71076|1077|3|1|1047.07|0.01|0.07|A|F|1992-10-06|1992-10-05|1992-10-09|COLLECT COD|RAIL|ve the idly express deposits. +11876|27216|4723|1|14|16004.94|0.05|0.06|N|O|1995-09-25|1995-08-10|1995-10-04|NONE|FOB|its sleep blithely regular requests. i +11876|7609|110|2|3|4549.80|0.00|0.06|N|O|1995-09-07|1995-08-06|1995-09-23|DELIVER IN PERSON|REG AIR|ainst the blithely final +11876|83496|1021|3|8|11835.92|0.01|0.04|N|O|1995-10-20|1995-09-23|1995-10-27|COLLECT COD|MAIL|ly ruthless accounts; blithely final mul +11876|102360|2361|4|34|46320.24|0.09|0.07|N|O|1995-10-29|1995-09-21|1995-11-17|NONE|FOB|r requests detect furiously +11876|159730|7276|5|2|3579.46|0.00|0.07|N|O|1995-10-12|1995-09-19|1995-11-04|DELIVER IN PERSON|AIR|heaves-- slyly fluffy deposits sleep +11876|172450|2|6|43|65465.35|0.10|0.00|N|O|1995-10-09|1995-08-04|1995-10-12|DELIVER IN PERSON|AIR|y ironic packages use slyly across t +11877|89961|2470|1|4|7803.84|0.10|0.01|R|F|1993-06-19|1993-07-08|1993-07-18|COLLECT COD|TRUCK|. special +11877|164288|9321|2|4|5409.12|0.00|0.03|R|F|1993-06-12|1993-08-11|1993-06-17|DELIVER IN PERSON|SHIP|ly unusual excuses. special packages boost +11877|175487|522|3|50|78124.00|0.07|0.07|R|F|1993-08-31|1993-07-01|1993-09-23|TAKE BACK RETURN|MAIL|ly final requests +11877|7505|7506|4|22|31075.00|0.03|0.00|A|F|1993-05-29|1993-07-24|1993-06-09|TAKE BACK RETURN|FOB|ress deposits use eve +11877|134290|4291|5|5|6621.45|0.04|0.04|R|F|1993-09-03|1993-08-01|1993-09-19|COLLECT COD|MAIL|to the ironic accounts. slyly pending pack +11878|134125|9152|1|50|57956.00|0.06|0.00|A|F|1993-05-26|1993-05-22|1993-06-14|TAKE BACK RETURN|AIR|ns among the ironi +11878|31045|8555|2|29|28305.16|0.08|0.04|R|F|1993-03-29|1993-03-31|1993-04-04|COLLECT COD|REG AIR|inal accounts boost furiously dep +11879|68327|5846|1|41|53108.12|0.04|0.07|A|F|1993-07-26|1993-09-10|1993-08-20|TAKE BACK RETURN|TRUCK|t the silent dolphins. carefully pendin +11879|171027|8579|2|14|15372.28|0.03|0.06|A|F|1993-10-05|1993-08-24|1993-10-29|COLLECT COD|AIR|quickly final requests. ironic packages +11879|49724|4733|3|31|51885.32|0.06|0.05|R|F|1993-07-13|1993-09-13|1993-08-03|COLLECT COD|MAIL| carefully slyly even pinto beans. even +11879|109027|4048|4|32|33152.64|0.02|0.03|R|F|1993-09-09|1993-09-02|1993-09-14|TAKE BACK RETURN|FOB|engage furiou +11879|511|3012|5|22|31053.22|0.02|0.04|R|F|1993-10-13|1993-09-15|1993-10-24|DELIVER IN PERSON|TRUCK|usly along the final, even acc +11904|16991|6992|1|45|85859.55|0.08|0.06|N|O|1998-01-29|1998-02-07|1998-02-06|DELIVER IN PERSON|MAIL|theodolites haggle busy accounts. +11904|165129|2678|2|27|32241.24|0.00|0.02|N|O|1997-12-09|1998-01-28|1998-01-08|DELIVER IN PERSON|FOB| special, even attainments cajole slyly fl +11904|121294|3807|3|3|3945.87|0.08|0.07|N|O|1998-03-21|1998-01-08|1998-04-09|COLLECT COD|SHIP|ly fluffily final excuses. always daring +11904|187759|2796|4|27|49862.25|0.06|0.03|N|O|1998-03-18|1998-02-17|1998-03-21|COLLECT COD|MAIL|uctions. furiou +11904|49675|4684|5|28|45490.76|0.02|0.07|N|O|1998-02-09|1998-01-02|1998-02-26|TAKE BACK RETURN|RAIL|t pains are above the ironic packages +11904|86985|9494|6|21|41411.58|0.07|0.02|N|O|1998-03-31|1998-02-01|1998-04-28|COLLECT COD|REG AIR| integrate carefully ac +11904|155241|7757|7|44|57034.56|0.08|0.08|N|O|1998-01-15|1998-02-11|1998-01-19|NONE|AIR|s use unusual instructions. furious +11905|122666|5179|1|27|45593.82|0.05|0.01|N|O|1997-08-19|1997-08-11|1997-09-17|NONE|TRUCK|uctions breach quickly acc +11905|39027|6537|2|18|17388.36|0.01|0.00|N|O|1997-08-30|1997-09-13|1997-09-08|TAKE BACK RETURN|MAIL|pending theodolites nag +11905|116763|9275|3|43|76529.68|0.05|0.08|N|O|1997-10-06|1997-08-04|1997-10-22|COLLECT COD|MAIL|sleep carefully. fluffily regular pla +11905|30785|8295|4|2|3431.56|0.04|0.03|N|O|1997-08-28|1997-09-05|1997-09-25|DELIVER IN PERSON|SHIP|lithely ironi +11906|5599|3100|1|41|61688.19|0.07|0.07|N|O|1997-01-08|1997-01-21|1997-01-17|DELIVER IN PERSON|SHIP| sentiments detect along the careful +11906|91232|6251|2|39|47705.97|0.03|0.03|N|O|1996-12-21|1997-02-28|1997-01-11|TAKE BACK RETURN|REG AIR|ly ironic pinto beans nag q +11906|127909|2934|3|35|67791.50|0.09|0.00|N|O|1997-01-14|1997-02-08|1997-01-24|TAKE BACK RETURN|TRUCK| carefully final asympt +11906|160091|5124|4|45|51799.05|0.10|0.00|N|O|1997-02-14|1997-02-21|1997-02-21|DELIVER IN PERSON|MAIL|. furiously unusual acc +11906|42048|2049|5|33|32671.32|0.01|0.02|N|O|1997-03-10|1997-02-12|1997-04-09|COLLECT COD|MAIL|efully according t +11906|98641|3660|6|39|63945.96|0.04|0.03|N|O|1997-01-07|1997-02-09|1997-01-12|NONE|RAIL|y across the +11907|126669|9182|1|26|44087.16|0.02|0.07|A|F|1993-12-11|1993-11-09|1993-12-28|DELIVER IN PERSON|TRUCK|s. furious dolphins could +11907|110099|5122|2|35|38818.15|0.10|0.01|R|F|1993-10-23|1993-10-01|1993-11-01|COLLECT COD|MAIL|he carefully iron +11907|19405|4408|3|32|42380.80|0.03|0.08|R|F|1993-12-18|1993-10-16|1993-12-19|COLLECT COD|REG AIR|sleep quickly around the quickly final ac +11907|130183|5210|4|24|29116.32|0.08|0.03|A|F|1993-09-03|1993-11-02|1993-09-05|DELIVER IN PERSON|REG AIR|oost. furiously ironic gifts prin +11908|87504|13|1|29|43253.50|0.03|0.05|R|F|1993-07-02|1993-08-12|1993-07-27|NONE|REG AIR|arefully blithely special asymptot +11908|75461|2983|2|13|18673.98|0.08|0.02|A|F|1993-08-31|1993-08-19|1993-09-19|NONE|FOB|ajole along the carefully ironic requests. +11908|67901|2914|3|30|56067.00|0.02|0.00|A|F|1993-06-19|1993-07-18|1993-06-26|TAKE BACK RETURN|REG AIR|ructions cajole furiously blith +11908|196191|3749|4|3|3861.57|0.06|0.07|R|F|1993-06-10|1993-08-13|1993-06-18|NONE|REG AIR|e thinly at the ideas. slyly unusual th +11908|171984|1985|5|12|24671.76|0.10|0.08|R|F|1993-07-22|1993-07-01|1993-08-21|NONE|MAIL| requests ar +11908|120936|8473|6|35|68492.55|0.08|0.02|A|F|1993-08-22|1993-07-15|1993-09-17|DELIVER IN PERSON|TRUCK| quickly unusual +11909|159237|6783|1|8|10369.84|0.07|0.00|R|F|1995-03-01|1995-01-15|1995-03-16|DELIVER IN PERSON|SHIP|bout the slyly final platelets. blithel +11909|79502|2010|2|20|29630.00|0.07|0.05|A|F|1995-02-10|1995-01-17|1995-02-21|COLLECT COD|FOB|s the furiously ironic re +11909|189805|2324|3|4|7579.20|0.01|0.03|R|F|1994-12-08|1995-02-12|1994-12-12|NONE|AIR|nstructions. closely iro +11910|96826|1845|1|16|29165.12|0.10|0.06|N|O|1995-08-07|1995-09-05|1995-08-27|NONE|AIR|le according to the ironic hockey play +11910|144648|9677|2|11|18619.04|0.05|0.05|N|O|1995-07-20|1995-08-09|1995-07-28|NONE|TRUCK|. slyly express platelets det +11910|85025|7534|3|28|28280.56|0.06|0.08|N|O|1995-09-19|1995-08-25|1995-10-16|NONE|FOB| special instruction +11910|199561|4600|4|5|8302.80|0.05|0.02|N|O|1995-08-14|1995-08-23|1995-08-24|DELIVER IN PERSON|TRUCK|lites along the accounts wake blithely +11911|56701|9207|1|33|54704.10|0.02|0.02|R|F|1994-03-11|1994-02-04|1994-04-01|DELIVER IN PERSON|TRUCK|rets-- slyly final packages boost fluffil +11911|159355|1871|2|47|66474.45|0.05|0.05|R|F|1994-02-19|1994-01-04|1994-03-12|NONE|SHIP|asymptotes sle +11911|70537|538|3|16|24120.48|0.05|0.08|A|F|1994-01-03|1994-01-27|1994-01-07|NONE|REG AIR|ts hang bli +11911|108339|3360|4|43|57935.19|0.06|0.06|A|F|1994-01-03|1994-01-25|1994-01-18|DELIVER IN PERSON|AIR|about the express, bold pinto be +11911|48207|3216|5|25|28880.00|0.07|0.00|R|F|1993-11-21|1993-12-13|1993-12-04|NONE|TRUCK|deas cajole ironic, final acco +11936|98703|3722|1|13|22122.10|0.10|0.03|N|O|1995-11-10|1995-11-04|1995-12-06|COLLECT COD|TRUCK|uriously even +11936|84827|4828|2|5|9059.10|0.08|0.06|N|O|1996-01-05|1995-10-25|1996-01-22|DELIVER IN PERSON|AIR|the ironic instructions. quickly i +11936|71711|6726|3|21|35336.91|0.03|0.07|N|O|1995-10-16|1995-10-31|1995-11-08|COLLECT COD|REG AIR|pending, even asymptot +11936|34107|9114|4|5|5205.50|0.05|0.04|N|O|1995-10-22|1995-11-22|1995-11-17|DELIVER IN PERSON|MAIL|nusual dependencies. +11936|20043|5048|5|33|31780.32|0.10|0.01|N|O|1995-10-05|1995-12-01|1995-10-16|COLLECT COD|REG AIR|iously quickly express +11936|52318|2319|6|42|53353.02|0.02|0.06|N|O|1995-11-28|1995-11-19|1995-12-16|COLLECT COD|RAIL|e. careful +11937|123736|3737|1|6|10558.38|0.07|0.00|N|O|1998-10-24|1998-09-19|1998-11-08|COLLECT COD|TRUCK|neath the ironic excuses. slyly +11937|29277|9278|2|21|25331.67|0.03|0.04|N|O|1998-08-26|1998-09-17|1998-09-21|NONE|FOB|lyly. fluffily final foxes play to the care +11937|42080|4585|3|10|10220.80|0.05|0.04|N|O|1998-10-07|1998-08-06|1998-11-06|COLLECT COD|AIR|re fluffily sp +11937|23482|5985|4|32|44975.36|0.09|0.07|N|O|1998-08-18|1998-09-06|1998-08-30|DELIVER IN PERSON|AIR|quietly bold depe +11937|48568|8569|5|19|28814.64|0.10|0.03|N|O|1998-08-04|1998-09-22|1998-08-08|DELIVER IN PERSON|RAIL|lites wake. fina +11937|72938|2939|6|18|34396.74|0.00|0.00|N|O|1998-07-26|1998-09-06|1998-07-30|NONE|FOB|al deposits. final attainments affi +11937|63136|655|7|18|19784.34|0.08|0.01|N|O|1998-09-22|1998-08-30|1998-10-15|NONE|REG AIR|e slyly carefully fi +11938|110006|5029|1|40|40640.00|0.01|0.05|N|O|1998-08-22|1998-10-18|1998-08-28|COLLECT COD|TRUCK|lay after the silent, ironic ideas. unus +11938|64593|7100|2|48|74764.32|0.09|0.07|N|O|1998-08-25|1998-10-23|1998-09-02|TAKE BACK RETURN|AIR|hely until the sl +11938|12269|2270|3|19|22443.94|0.06|0.03|N|O|1998-10-29|1998-08-29|1998-11-14|NONE|MAIL| accounts. +11938|835|836|4|33|57282.39|0.08|0.03|N|O|1998-11-14|1998-09-22|1998-11-20|COLLECT COD|REG AIR|quickly even accounts affix fur +11939|41461|6470|1|46|64513.16|0.03|0.01|N|O|1996-12-12|1996-11-14|1996-12-14|TAKE BACK RETURN|FOB| boost alongside of the carefu +11939|30880|8390|2|22|39839.36|0.07|0.03|N|O|1996-12-11|1996-12-23|1996-12-30|DELIVER IN PERSON|REG AIR|dazzle. furiously +11940|73394|916|1|9|12306.51|0.01|0.08|N|O|1998-07-16|1998-08-04|1998-08-12|COLLECT COD|TRUCK| cajole furio +11940|130310|5337|2|11|14743.41|0.09|0.00|N|O|1998-08-29|1998-08-14|1998-09-27|NONE|SHIP|uickly carefully even +11940|114308|9331|3|42|55536.60|0.00|0.00|N|O|1998-07-14|1998-07-04|1998-07-26|TAKE BACK RETURN|FOB|uriously against the regular, unusual ideas +11940|170051|7603|4|7|7847.35|0.02|0.03|N|O|1998-09-15|1998-08-19|1998-10-10|NONE|TRUCK| accounts cajole blithel +11940|33589|8596|5|20|30451.60|0.04|0.04|N|O|1998-06-10|1998-08-25|1998-06-21|NONE|TRUCK|s sleep qu +11940|126424|1449|6|36|52215.12|0.00|0.00|N|O|1998-08-30|1998-07-06|1998-09-09|TAKE BACK RETURN|REG AIR|lar, final +11941|45007|7512|1|11|10472.00|0.00|0.05|A|F|1993-07-16|1993-08-01|1993-07-19|NONE|SHIP|al deposits poach. quickly express +11941|20314|2817|2|33|40732.23|0.07|0.07|A|F|1993-10-21|1993-08-09|1993-10-26|DELIVER IN PERSON|SHIP|y even realms engage carefully. +11941|14966|4967|3|34|63952.64|0.08|0.02|A|F|1993-09-23|1993-08-06|1993-09-26|TAKE BACK RETURN|RAIL|unusual dependencies sleep carefully a +11941|125563|588|4|36|57188.16|0.02|0.03|A|F|1993-07-03|1993-07-31|1993-07-21|TAKE BACK RETURN|TRUCK|thely final +11941|136891|6892|5|20|38557.80|0.05|0.00|A|F|1993-08-15|1993-08-04|1993-08-18|NONE|AIR|venly regular frets. bold pinto bean +11941|117786|7787|6|5|9018.90|0.00|0.08|A|F|1993-08-29|1993-09-08|1993-09-06|NONE|SHIP|. blithely +11942|125764|5765|1|36|64431.36|0.01|0.06|A|F|1994-07-04|1994-07-23|1994-07-25|COLLECT COD|REG AIR|s integrate carefully bold, bold ideas. +11943|102173|7194|1|46|54057.82|0.07|0.00|R|F|1993-06-08|1993-06-01|1993-06-15|COLLECT COD|SHIP|ly even pinto beans. slyly regul +11943|9998|9999|2|40|76319.60|0.10|0.04|A|F|1993-04-15|1993-06-18|1993-04-30|NONE|FOB| deposits are pending excuses. furious +11943|31767|1768|3|50|84938.00|0.00|0.02|R|F|1993-07-23|1993-06-27|1993-07-24|NONE|RAIL|sual asymptotes wake slyly according +11943|92390|9918|4|33|45618.87|0.09|0.04|A|F|1993-06-24|1993-05-21|1993-07-01|TAKE BACK RETURN|AIR|into beans sleep blit +11943|193988|3989|5|9|18737.82|0.04|0.02|R|F|1993-08-06|1993-06-25|1993-08-15|TAKE BACK RETURN|REG AIR|atelets across the careful +11943|150271|5302|6|17|22461.59|0.03|0.01|R|F|1993-07-23|1993-06-22|1993-08-13|TAKE BACK RETURN|AIR|ar courts. carefull +11968|45256|265|1|15|18018.75|0.06|0.02|A|F|1995-05-19|1995-05-02|1995-06-16|TAKE BACK RETURN|RAIL|ag against the even account +11968|14348|4349|2|25|31558.50|0.10|0.02|N|F|1995-05-26|1995-06-13|1995-06-22|COLLECT COD|SHIP|sts wake carefully about the close +11969|29924|7431|1|10|18539.20|0.10|0.04|R|F|1992-01-30|1992-03-01|1992-02-01|COLLECT COD|TRUCK|eans above +11969|125906|8419|2|38|73412.20|0.09|0.05|A|F|1992-01-29|1992-03-26|1992-02-10|DELIVER IN PERSON|AIR|yly final hockey players al +11969|95479|7989|3|37|54555.39|0.04|0.05|R|F|1992-04-24|1992-03-24|1992-04-29|COLLECT COD|FOB|ts. furiously final req +11969|101537|9068|4|4|6154.12|0.04|0.05|A|F|1992-02-15|1992-03-27|1992-02-16|COLLECT COD|REG AIR|t the permanently even theodolites sle +11969|124049|4050|5|43|46140.72|0.02|0.04|R|F|1992-02-12|1992-04-16|1992-02-21|TAKE BACK RETURN|AIR|he slyly ironic foxe +11969|82282|7299|6|30|37928.40|0.06|0.07|R|F|1992-04-23|1992-02-19|1992-05-14|COLLECT COD|REG AIR|accounts are after the blithe +11969|111024|6047|7|44|45540.88|0.08|0.04|A|F|1992-04-21|1992-03-14|1992-04-24|DELIVER IN PERSON|REG AIR| beans above the carefully express requests +11970|177623|7624|1|18|30611.16|0.06|0.00|N|O|1998-06-03|1998-08-20|1998-06-15|DELIVER IN PERSON|SHIP|t the busily regular accounts thrash p +11970|98294|3313|2|28|36184.12|0.09|0.04|N|O|1998-08-20|1998-07-30|1998-09-08|TAKE BACK RETURN|MAIL|eposits. blithely pending a +11970|19872|7376|3|17|30461.79|0.02|0.07|N|O|1998-09-05|1998-07-11|1998-09-22|COLLECT COD|MAIL|uickly. carefully unusual asymptotes sle +11970|180076|77|4|21|24277.47|0.01|0.00|N|O|1998-06-12|1998-07-06|1998-06-15|TAKE BACK RETURN|AIR|ake furiously. slyly regula +11970|136506|4046|5|48|74040.00|0.00|0.05|N|O|1998-07-28|1998-07-21|1998-08-18|COLLECT COD|REG AIR|e accounts are busily above the +11970|46275|1284|6|41|50072.07|0.03|0.08|N|O|1998-06-04|1998-07-13|1998-06-08|TAKE BACK RETURN|FOB|y along th +11971|116679|6680|1|5|8478.35|0.03|0.08|N|O|1997-04-12|1997-05-15|1997-05-05|NONE|MAIL|ic requests. slyly unusual i +11971|9312|1813|2|5|6106.55|0.08|0.05|N|O|1997-04-01|1997-06-04|1997-04-23|COLLECT COD|FOB|y furiously ironi +11971|90822|3332|3|36|65261.52|0.05|0.00|N|O|1997-05-05|1997-06-10|1997-05-27|DELIVER IN PERSON|FOB|yly across the slyly daring foxes-- slyly +11971|44625|4626|4|34|53367.08|0.00|0.03|N|O|1997-04-03|1997-05-16|1997-05-01|TAKE BACK RETURN|MAIL|out the quickly special accounts ca +11972|193036|3037|1|10|11290.30|0.02|0.03|R|F|1994-03-13|1994-02-22|1994-04-08|DELIVER IN PERSON|REG AIR|refully bold instru +11972|141252|1253|2|38|49143.50|0.02|0.02|R|F|1994-03-24|1994-02-23|1994-04-19|DELIVER IN PERSON|RAIL|gular sentiments boost. quic +11972|17183|9685|3|38|41806.84|0.02|0.00|A|F|1994-03-26|1994-02-07|1994-04-05|COLLECT COD|REG AIR| accounts det +11972|179784|7336|4|20|37275.60|0.02|0.01|A|F|1994-02-10|1994-02-03|1994-03-04|DELIVER IN PERSON|FOB|sts cajole idly regular reques +11972|20546|547|5|5|7332.70|0.01|0.03|A|F|1994-03-15|1994-03-19|1994-04-11|DELIVER IN PERSON|REG AIR|ash across the ca +11973|18344|8345|1|2|2524.68|0.10|0.07|R|F|1994-04-05|1994-04-21|1994-05-04|NONE|FOB|y requests. regular, express theo +11973|96564|4092|2|45|70225.20|0.05|0.02|R|F|1994-06-16|1994-05-28|1994-06-26|TAKE BACK RETURN|REG AIR|endencies try +11973|138824|6364|3|15|27942.30|0.08|0.07|A|F|1994-03-05|1994-04-06|1994-03-07|NONE|TRUCK|arefully after the +11973|13341|8344|4|11|13797.74|0.09|0.06|A|F|1994-04-23|1994-04-04|1994-05-20|DELIVER IN PERSON|SHIP| silent deposit +11973|5853|3354|5|1|1758.85|0.05|0.01|R|F|1994-03-31|1994-04-08|1994-04-11|NONE|RAIL|unts. carefully regular acco +11973|159837|2353|6|30|56904.90|0.08|0.07|R|F|1994-04-27|1994-04-04|1994-05-16|COLLECT COD|SHIP|ess, final dept +11974|76806|4328|1|42|74877.60|0.07|0.06|R|F|1992-10-24|1992-12-28|1992-11-08|DELIVER IN PERSON|RAIL|eas cajole; silent +11974|78181|8182|2|12|13910.16|0.10|0.05|R|F|1992-10-18|1993-01-02|1992-10-28|DELIVER IN PERSON|MAIL|s beyond th +11975|173575|1127|1|23|37917.11|0.07|0.05|N|O|1995-06-18|1995-07-03|1995-06-30|COLLECT COD|TRUCK|s detect above the b +11975|67370|7371|2|19|25410.03|0.10|0.01|N|O|1995-07-01|1995-06-17|1995-07-17|NONE|FOB|regular requests nag qui +11975|71225|1226|3|40|47848.80|0.02|0.00|N|O|1995-07-23|1995-06-15|1995-08-02|NONE|SHIP|uffily furiously bo +11975|66673|9180|4|34|55748.78|0.06|0.03|N|O|1995-06-22|1995-05-24|1995-06-26|NONE|MAIL|ate furiously quickly ironic re +11975|172938|5456|5|32|64349.76|0.04|0.03|N|O|1995-08-09|1995-05-25|1995-08-11|NONE|FOB|eposits cajole across the fur +12000|129438|4463|1|33|48425.19|0.03|0.03|R|F|1994-09-10|1994-08-01|1994-10-04|DELIVER IN PERSON|MAIL|lyly even gifts. f +12000|64359|6866|2|6|7940.10|0.09|0.01|A|F|1994-06-15|1994-06-17|1994-07-12|COLLECT COD|MAIL|counts. carefu +12000|77944|452|3|9|17297.46|0.03|0.05|R|F|1994-09-05|1994-07-22|1994-09-26|TAKE BACK RETURN|AIR|quests play blithel +12000|196890|4448|4|13|25829.57|0.00|0.06|R|F|1994-06-09|1994-08-08|1994-06-13|COLLECT COD|RAIL|l ideas haggle across the e +12001|195743|8263|1|8|14709.92|0.01|0.01|R|F|1994-07-18|1994-09-30|1994-08-03|TAKE BACK RETURN|SHIP|ickly final packages cajole bli +12001|45856|865|2|23|41442.55|0.04|0.05|R|F|1994-08-11|1994-10-05|1994-08-30|NONE|FOB| fluffily final ideas haggle above t +12001|90652|8180|3|11|18069.15|0.05|0.04|R|F|1994-07-17|1994-09-25|1994-08-12|TAKE BACK RETURN|TRUCK|totes sleep qu +12001|171889|1890|4|46|90200.48|0.09|0.07|R|F|1994-09-19|1994-08-10|1994-10-12|NONE|SHIP|eep quietly. regula +12002|196745|1784|1|44|81036.56|0.07|0.04|R|F|1994-03-28|1994-02-10|1994-03-30|COLLECT COD|REG AIR|lly pending ideas promise theodolites! r +12003|171996|1997|1|10|20679.90|0.06|0.07|N|O|1998-07-06|1998-08-10|1998-07-27|COLLECT COD|REG AIR|nstruction +12004|64822|7329|1|47|83980.54|0.04|0.07|R|F|1995-02-10|1995-01-30|1995-02-11|COLLECT COD|SHIP|s. dugouts use. slyly regula +12005|34175|4176|1|13|14419.21|0.03|0.02|R|F|1992-07-09|1992-07-31|1992-08-05|TAKE BACK RETURN|AIR|thely around the quickly express de +12005|163319|8352|2|26|35940.06|0.10|0.01|R|F|1992-08-03|1992-08-10|1992-08-29|TAKE BACK RETURN|MAIL| the blithely reg +12005|92410|7429|3|25|35060.25|0.06|0.07|R|F|1992-09-21|1992-08-17|1992-10-01|NONE|REG AIR|blithely final accounts. even requests ab +12005|125147|5148|4|2|2344.28|0.09|0.00|A|F|1992-08-18|1992-08-05|1992-09-10|TAKE BACK RETURN|AIR|refully ironic accounts. fu +12005|135008|35|5|41|42763.00|0.06|0.01|R|F|1992-07-19|1992-08-20|1992-08-14|NONE|FOB|deposits. requests haggle carefu +12005|67318|9825|6|40|51412.40|0.09|0.07|R|F|1992-07-29|1992-09-22|1992-08-20|COLLECT COD|AIR|s. slyly ironic requests haggle blith +12005|18|7519|7|46|42228.46|0.05|0.03|R|F|1992-07-01|1992-08-15|1992-07-18|TAKE BACK RETURN|AIR| furiously express grouches sleep reg +12006|101018|8549|1|37|37703.37|0.01|0.04|N|O|1997-06-20|1997-08-31|1997-07-05|TAKE BACK RETURN|AIR|ly thin exc +12006|6408|6409|2|32|42060.80|0.00|0.05|N|O|1997-09-21|1997-07-05|1997-10-17|NONE|FOB|bout the slyly regular foxes. fur +12006|91903|9431|3|18|34108.20|0.04|0.02|N|O|1997-09-02|1997-07-25|1997-09-03|COLLECT COD|REG AIR| asymptotes haggle blithely. pe +12006|1375|1376|4|19|24251.03|0.02|0.05|N|O|1997-08-08|1997-07-24|1997-09-06|COLLECT COD|REG AIR|ial deposits sleep blithely furiously pend +12006|93486|1014|5|7|10356.36|0.08|0.01|N|O|1997-08-04|1997-08-06|1997-08-10|TAKE BACK RETURN|REG AIR|requests according t +12007|94741|2269|1|45|78108.30|0.06|0.05|R|F|1994-12-18|1994-12-22|1994-12-30|TAKE BACK RETURN|FOB|s integrate slyly. ideas use. blith +12007|98362|3381|2|11|14963.96|0.10|0.03|R|F|1994-10-10|1994-10-30|1994-11-04|TAKE BACK RETURN|REG AIR|es sleep blithely a +12007|158164|680|3|41|50108.56|0.08|0.03|R|F|1995-01-27|1994-11-19|1995-02-17|DELIVER IN PERSON|RAIL| about the s +12007|56905|1916|4|8|14895.20|0.02|0.08|R|F|1994-11-05|1994-12-18|1994-11-21|NONE|SHIP|t the pinto beans. bold, u +12007|192503|7542|5|40|63820.00|0.07|0.00|A|F|1994-10-20|1994-12-07|1994-11-05|COLLECT COD|AIR|. dogged w +12032|41408|1409|1|28|37783.20|0.05|0.03|N|O|1997-10-19|1997-10-13|1997-11-16|TAKE BACK RETURN|AIR|equests are +12032|128837|6374|2|39|72767.37|0.01|0.06|N|O|1997-11-27|1997-10-22|1997-11-29|DELIVER IN PERSON|MAIL|sits are carefull +12032|147611|126|3|1|1658.61|0.04|0.07|N|O|1997-11-18|1997-10-18|1997-11-27|DELIVER IN PERSON|TRUCK|ickly care +12032|87639|148|4|10|16266.30|0.09|0.00|N|O|1997-08-25|1997-11-08|1997-09-10|TAKE BACK RETURN|TRUCK|ainments wake blithely accor +12033|52063|9579|1|33|33496.98|0.06|0.03|A|F|1992-11-03|1992-11-27|1992-11-23|DELIVER IN PERSON|SHIP|yly express excuses boost slyly fu +12033|19638|7142|2|30|46728.90|0.07|0.00|R|F|1992-10-19|1992-10-22|1992-11-09|COLLECT COD|AIR|ily express +12033|48461|966|3|22|31008.12|0.02|0.07|R|F|1992-12-22|1992-11-08|1993-01-18|NONE|MAIL|egular courts. ironic, bold deposits a +12033|70943|5958|4|35|66987.90|0.10|0.08|R|F|1992-11-07|1992-11-03|1992-12-05|TAKE BACK RETURN|RAIL| fluffily even theodolites. pac +12033|134644|7158|5|39|65466.96|0.01|0.07|R|F|1993-01-07|1992-10-21|1993-01-13|NONE|AIR|efully ideas. platelets +12034|167264|2297|1|33|43931.58|0.03|0.00|N|O|1997-01-22|1997-01-17|1997-02-12|DELIVER IN PERSON|AIR|ffily final foxes. furiously +12034|192644|202|2|21|36469.44|0.06|0.06|N|O|1997-01-29|1997-02-11|1997-02-26|DELIVER IN PERSON|SHIP|le slyly across the blithely final courts +12035|144806|7321|1|35|64778.00|0.08|0.04|N|O|1996-12-11|1996-12-30|1996-12-26|DELIVER IN PERSON|RAIL|ly deposits wake. fluffily regul +12035|144599|9628|2|41|67387.19|0.00|0.06|N|O|1996-11-15|1997-02-06|1996-11-26|DELIVER IN PERSON|RAIL|accounts. final requests +12035|60111|112|3|7|7497.77|0.04|0.05|N|O|1996-12-31|1997-01-17|1997-01-03|NONE|TRUCK| unusual foxes. even, spe +12035|79923|2431|4|39|74213.88|0.04|0.01|N|O|1997-02-16|1997-02-05|1997-03-05|COLLECT COD|REG AIR|gular dependencies with +12035|55954|5955|5|1|1909.95|0.08|0.00|N|O|1997-01-20|1997-01-28|1997-01-26|TAKE BACK RETURN|FOB|permanently. slyl +12035|9618|4619|6|34|51938.74|0.06|0.00|N|O|1996-12-01|1996-12-19|1996-12-27|TAKE BACK RETURN|RAIL|e slyly regula +12035|49109|9110|7|25|26452.50|0.04|0.02|N|O|1997-03-01|1996-12-15|1997-03-22|TAKE BACK RETURN|SHIP|ions shall have to ca +12036|164335|9368|1|38|53174.54|0.04|0.02|N|O|1998-03-23|1998-03-30|1998-04-05|TAKE BACK RETURN|FOB|ounts. pac +12036|172126|2127|2|33|39537.96|0.01|0.08|N|O|1998-03-28|1998-02-15|1998-04-19|TAKE BACK RETURN|MAIL| final ideas. slyl +12036|107423|7424|3|29|41482.18|0.09|0.00|N|O|1998-03-02|1998-04-07|1998-03-05|TAKE BACK RETURN|SHIP|sts. carefully final r +12036|44430|4431|4|19|26114.17|0.02|0.07|N|O|1998-04-02|1998-03-12|1998-04-20|DELIVER IN PERSON|TRUCK| are furiously. un +12036|134528|2068|5|7|10937.64|0.03|0.05|N|O|1998-01-23|1998-03-03|1998-02-21|COLLECT COD|TRUCK|ntegrate slyly alongside of the c +12036|5580|581|6|35|51995.30|0.00|0.04|N|O|1998-02-08|1998-04-16|1998-02-28|TAKE BACK RETURN|REG AIR| carefully always pend +12036|170742|5777|7|20|36254.80|0.09|0.03|N|O|1998-05-09|1998-03-02|1998-06-06|TAKE BACK RETURN|FOB| theodolite +12037|55485|5486|1|3|4321.44|0.02|0.05|N|O|1995-08-20|1995-08-23|1995-09-01|DELIVER IN PERSON|MAIL| platelets above the unusual deposit +12037|122147|2148|2|20|23382.80|0.03|0.05|N|O|1995-07-20|1995-08-26|1995-08-07|NONE|FOB|ly express theodolites. special ideas a +12037|119146|6680|3|12|13981.68|0.05|0.03|N|O|1995-08-19|1995-09-29|1995-08-26|DELIVER IN PERSON|RAIL| packages u +12037|80269|5286|4|10|12492.60|0.00|0.01|N|O|1995-09-23|1995-09-19|1995-10-11|NONE|RAIL|aggle slyly. final pint +12037|66892|1905|5|5|9294.45|0.09|0.06|N|O|1995-10-16|1995-08-14|1995-10-26|NONE|SHIP|ar dugouts kindle quickly regular id +12037|49635|4644|6|46|72892.98|0.09|0.07|N|O|1995-08-29|1995-08-16|1995-09-04|NONE|FOB|bold instructions. quickly regular r +12037|199943|7501|7|13|26558.22|0.04|0.08|N|O|1995-07-03|1995-08-21|1995-07-26|NONE|AIR|ly quickly ironic theodolites. ironic i +12038|31586|9096|1|15|22763.70|0.04|0.06|N|O|1995-12-14|1996-01-07|1996-01-04|TAKE BACK RETURN|RAIL|dencies. blithely special plate +12038|56094|3610|2|28|29402.52|0.04|0.04|N|O|1996-02-29|1996-01-26|1996-03-16|COLLECT COD|REG AIR|silent dolphins sleep carefully pend +12039|44983|7488|1|49|94471.02|0.03|0.06|A|F|1993-08-09|1993-07-29|1993-08-22|TAKE BACK RETURN|RAIL|ly furious +12039|28913|8914|2|43|79202.13|0.06|0.07|R|F|1993-07-24|1993-08-14|1993-08-21|DELIVER IN PERSON|TRUCK|side of the ironic, final platelets +12039|131258|3772|3|44|56727.00|0.10|0.03|R|F|1993-09-25|1993-08-14|1993-10-14|TAKE BACK RETURN|AIR|. quickly re +12039|50037|7553|4|7|6909.21|0.01|0.04|A|F|1993-08-05|1993-08-10|1993-09-01|NONE|RAIL|le furiously. asymptot +12039|168603|8604|5|46|76893.60|0.09|0.01|A|F|1993-07-17|1993-08-08|1993-08-02|DELIVER IN PERSON|TRUCK|earls. slyly +12039|108582|3603|6|46|73166.68|0.06|0.05|R|F|1993-08-12|1993-07-17|1993-08-16|COLLECT COD|FOB|hy accounts: final theod +12039|136931|6932|7|10|19679.30|0.10|0.07|R|F|1993-08-05|1993-08-31|1993-08-07|DELIVER IN PERSON|AIR|instructions +12064|196280|8800|1|9|12386.52|0.04|0.06|R|F|1993-01-01|1992-11-14|1993-01-26|NONE|MAIL|d, bold deposits wake quickly regular +12064|75298|7806|2|13|16552.77|0.04|0.04|A|F|1992-11-08|1992-11-26|1992-11-25|TAKE BACK RETURN|AIR|ts. ironic deposits alongside of the ironic +12064|120203|7740|3|3|3669.60|0.09|0.08|R|F|1992-12-27|1992-12-06|1992-12-31|NONE|FOB|boost slyly pending deposits. care +12064|46454|8959|4|24|33610.80|0.03|0.04|R|F|1992-12-08|1992-12-03|1993-01-06|DELIVER IN PERSON|AIR|ly. carefully silent a +12064|144257|4258|5|24|31230.00|0.08|0.04|A|F|1992-11-17|1992-11-23|1992-12-17|NONE|MAIL|e blithely unusual theodo +12064|115320|5321|6|27|36053.64|0.05|0.01|A|F|1992-09-26|1992-10-24|1992-10-05|NONE|RAIL|into beans. fl +12065|130182|7722|1|48|58184.64|0.00|0.04|N|O|1997-02-04|1997-03-12|1997-02-17|COLLECT COD|FOB| since the slyl +12066|121182|1183|1|12|14438.16|0.09|0.03|A|F|1995-05-15|1995-04-09|1995-06-07|COLLECT COD|TRUCK|ts above the slowly regular pinto beans w +12066|98939|6467|2|21|40696.53|0.03|0.01|A|F|1995-04-05|1995-03-22|1995-04-12|TAKE BACK RETURN|SHIP|sleep after the quic +12066|67270|2283|3|23|28457.21|0.03|0.01|R|F|1995-04-22|1995-04-07|1995-05-08|TAKE BACK RETURN|AIR|uests. speci +12066|196285|8805|4|35|48344.80|0.08|0.05|R|F|1995-05-27|1995-03-31|1995-06-10|TAKE BACK RETURN|SHIP|ss accounts. even accounts sleep darin +12066|148942|8943|5|27|53755.38|0.07|0.07|N|F|1995-06-03|1995-04-18|1995-06-22|COLLECT COD|REG AIR|nusual pinto beans. careful theodo +12067|150268|269|1|23|30319.98|0.06|0.04|R|F|1993-03-16|1993-04-24|1993-04-10|COLLECT COD|FOB|pinto beans cajole +12067|148470|8471|2|32|48591.04|0.10|0.00|A|F|1993-04-14|1993-04-04|1993-04-25|NONE|RAIL|eas. blithely ironic d +12067|133136|8163|3|22|25720.86|0.04|0.05|A|F|1993-05-09|1993-04-08|1993-06-03|COLLECT COD|TRUCK|the even realms. +12067|10612|8116|4|30|45678.30|0.08|0.00|R|F|1993-04-06|1993-05-06|1993-04-12|NONE|AIR|es sleep fluffily furi +12067|142765|5280|5|1|1807.76|0.02|0.04|A|F|1993-03-09|1993-04-09|1993-03-21|COLLECT COD|TRUCK|nto beans; regular courts are +12067|50597|3103|6|50|77379.50|0.07|0.07|A|F|1993-02-10|1993-05-06|1993-02-24|NONE|MAIL|es. bold instructions use after the re +12067|182215|9770|7|18|23349.78|0.06|0.01|A|F|1993-05-09|1993-05-01|1993-05-11|TAKE BACK RETURN|TRUCK| blithely bold excuses. requests beneath +12068|80926|3435|1|8|15255.36|0.09|0.03|N|O|1996-08-19|1996-08-03|1996-08-24|NONE|RAIL|ly. unusual, bold theodolites use carefully +12068|107705|5236|2|8|13701.60|0.04|0.00|N|O|1996-06-07|1996-08-06|1996-06-15|TAKE BACK RETURN|FOB|der carefully. furiously unusual deposits +12069|187335|4890|1|35|49781.55|0.03|0.01|N|O|1995-12-12|1995-12-12|1995-12-22|COLLECT COD|MAIL|ely final acco +12069|129073|4098|2|28|30857.96|0.01|0.05|N|O|1995-12-14|1995-12-10|1995-12-22|NONE|REG AIR| carefully regular accounts are slyly: ex +12069|113501|6013|3|8|12116.00|0.08|0.08|N|O|1995-11-20|1995-12-29|1995-12-03|DELIVER IN PERSON|MAIL|ans. bold, silent dolphins snooze blithel +12069|9791|4792|4|35|59527.65|0.05|0.03|N|O|1995-12-28|1996-01-25|1995-12-29|COLLECT COD|REG AIR|uses are! dol +12069|142339|7368|5|21|29007.93|0.08|0.07|N|O|1995-12-15|1996-01-29|1996-01-09|DELIVER IN PERSON|REG AIR| bold ideas are furiously accord +12069|85550|3075|6|41|62957.55|0.08|0.06|N|O|1995-12-04|1996-01-13|1995-12-16|NONE|SHIP|y across the carefull +12070|3972|8973|1|4|7503.88|0.10|0.03|N|O|1998-08-08|1998-06-23|1998-09-06|TAKE BACK RETURN|TRUCK|slyly ironi +12070|145009|2552|2|50|52700.00|0.00|0.04|N|O|1998-06-18|1998-08-15|1998-07-06|TAKE BACK RETURN|TRUCK|sias cajole slyly. furiously dogged ins +12070|153444|5960|3|19|28451.36|0.02|0.01|N|O|1998-06-16|1998-07-29|1998-06-19|DELIVER IN PERSON|REG AIR|luffy instructions integrate furious +12070|127577|7578|4|48|77019.36|0.02|0.07|N|O|1998-05-28|1998-08-19|1998-06-07|NONE|RAIL|lent theodolites. pi +12070|178453|6005|5|14|21440.30|0.09|0.03|N|O|1998-07-22|1998-08-10|1998-07-27|NONE|TRUCK| accounts. quickly silent +12070|48764|6277|6|40|68510.40|0.00|0.07|N|O|1998-06-19|1998-08-13|1998-06-22|DELIVER IN PERSON|REG AIR|kly final instr +12070|174778|4779|7|9|16674.93|0.01|0.03|N|O|1998-05-26|1998-08-16|1998-05-31|DELIVER IN PERSON|FOB|ular packages must wak +12071|93347|875|1|27|36189.18|0.02|0.00|N|O|1998-08-17|1998-08-24|1998-09-10|NONE|SHIP|refully carefully final deposits. f +12071|70329|2837|2|23|29884.36|0.05|0.06|N|O|1998-10-07|1998-08-15|1998-10-28|DELIVER IN PERSON|SHIP|. slyly special attainments poach blit +12071|9340|1841|3|15|18740.10|0.08|0.06|N|O|1998-08-18|1998-08-13|1998-08-27|DELIVER IN PERSON|RAIL|; careful, unusual requests haggle c +12096|5930|3431|1|21|38554.53|0.10|0.03|A|F|1992-12-10|1992-11-08|1992-12-13|DELIVER IN PERSON|SHIP|kly after the slyly bold tithes? deposi +12096|49374|6887|2|48|63521.76|0.00|0.05|A|F|1992-10-08|1992-10-23|1992-10-27|TAKE BACK RETURN|TRUCK|quickly across the slyly +12096|18446|948|3|13|17737.72|0.10|0.00|A|F|1992-11-07|1992-11-29|1992-11-25|COLLECT COD|TRUCK|ss deposits hinder caref +12096|5655|8156|4|29|45258.85|0.04|0.07|A|F|1993-01-15|1992-11-03|1993-01-28|DELIVER IN PERSON|REG AIR|final foxes accord +12096|34848|2358|5|24|42788.16|0.00|0.04|R|F|1992-12-03|1992-11-20|1992-12-18|TAKE BACK RETURN|TRUCK|aringly ironic ideas h +12096|81180|1181|6|40|46447.20|0.05|0.03|A|F|1992-11-09|1992-11-12|1992-11-29|DELIVER IN PERSON|SHIP| furiously +12096|187062|7063|7|17|19534.02|0.08|0.04|R|F|1992-11-14|1992-11-11|1992-12-02|NONE|TRUCK|dolites affix? slyly even realms integ +12097|138074|3101|1|50|55603.50|0.03|0.02|R|F|1994-01-19|1994-01-23|1994-02-14|DELIVER IN PERSON|REG AIR| after the carefull +12097|5135|5136|2|17|17682.21|0.08|0.06|A|F|1993-12-30|1994-01-17|1994-01-12|NONE|AIR|osits about the depths integ +12097|91917|6936|3|33|62994.03|0.06|0.01|R|F|1994-03-01|1993-12-16|1994-03-12|TAKE BACK RETURN|RAIL|hins alongside of the blithely i +12097|39592|4599|4|15|22973.85|0.03|0.08|A|F|1994-02-20|1994-01-10|1994-03-19|TAKE BACK RETURN|TRUCK|lyly silent platele +12098|157360|2391|1|25|35434.00|0.08|0.03|A|F|1993-06-24|1993-07-19|1993-07-02|NONE|TRUCK|lithely ironic deposits solve slyly. regula +12099|133057|8084|1|22|23981.10|0.10|0.07|A|F|1994-09-23|1994-10-29|1994-10-14|TAKE BACK RETURN|TRUCK|ld deposits boost until the regular plat +12099|85848|5849|2|19|34842.96|0.01|0.04|R|F|1994-10-10|1994-10-27|1994-10-22|COLLECT COD|AIR|n, special packages sleep across the bl +12099|46597|4110|3|41|63287.19|0.05|0.08|R|F|1994-12-18|1994-12-11|1994-12-26|NONE|FOB|eath the carefully +12099|142194|9737|4|37|45739.03|0.01|0.03|A|F|1994-11-08|1994-12-09|1994-11-15|NONE|SHIP|the carefully careful ideas cajole aga +12099|41305|8818|5|17|21187.10|0.10|0.03|A|F|1994-12-28|1994-11-25|1995-01-25|NONE|MAIL|nal pinto beans abov +12099|196863|9383|6|22|43116.92|0.02|0.03|R|F|1994-09-14|1994-10-25|1994-10-13|TAKE BACK RETURN|FOB|ng courts boost furiously +12100|180958|8513|1|36|73402.20|0.00|0.02|N|O|1996-06-10|1996-06-11|1996-06-20|TAKE BACK RETURN|SHIP|regular deposits run carefully final p +12101|120010|7547|1|28|28840.28|0.08|0.01|A|F|1995-02-13|1995-02-27|1995-03-14|DELIVER IN PERSON|TRUCK|es haggle express excuses. +12101|1596|1597|2|25|37439.75|0.04|0.04|A|F|1995-02-13|1995-03-02|1995-02-14|COLLECT COD|REG AIR|al, final foxes about the ir +12101|14373|1877|3|48|61793.76|0.03|0.06|R|F|1995-03-07|1995-02-06|1995-04-02|NONE|TRUCK|gular platelets. care +12102|36536|4046|1|22|32395.66|0.07|0.04|N|O|1996-02-09|1995-12-20|1996-03-02|COLLECT COD|MAIL|pending escapade +12102|59974|4985|2|20|38679.40|0.01|0.05|N|O|1996-01-21|1996-01-18|1996-02-15|COLLECT COD|RAIL|- furiously express warhorses ca +12102|173298|8333|3|32|43881.28|0.07|0.06|N|O|1996-01-24|1995-12-28|1996-02-23|TAKE BACK RETURN|RAIL|ccounts cajole around the even ideas. quick +12102|7651|7652|4|34|52994.10|0.05|0.05|N|O|1996-01-04|1996-01-20|1996-01-25|TAKE BACK RETURN|MAIL|ts nag bold, special deposits. even req +12102|182156|7193|5|38|47049.70|0.06|0.07|N|O|1995-11-20|1996-01-10|1995-12-04|TAKE BACK RETURN|REG AIR| platelets; furiously +12103|69727|9728|1|24|40721.28|0.09|0.01|N|O|1997-02-17|1997-02-23|1997-03-08|COLLECT COD|REG AIR|he finally regular r +12103|92318|2319|2|33|43240.23|0.02|0.03|N|O|1996-12-23|1996-12-27|1997-01-21|COLLECT COD|RAIL|gular deposits. slyly regular request +12103|176524|6525|3|5|8002.60|0.05|0.08|N|O|1997-01-23|1996-12-29|1997-02-05|TAKE BACK RETURN|RAIL|lyly above the quickly unusu +12103|37177|2184|4|35|38995.95|0.06|0.01|N|O|1996-12-26|1997-01-16|1997-01-22|TAKE BACK RETURN|RAIL| according to the slyly pendin +12103|28762|1265|5|19|32124.44|0.01|0.00|N|O|1997-01-22|1997-02-17|1997-01-27|DELIVER IN PERSON|SHIP|es. unusual foxes wake foxes. quick +12128|26707|4214|1|22|35941.40|0.10|0.04|N|O|1997-08-30|1997-09-04|1997-09-01|DELIVER IN PERSON|AIR| accounts are slyl +12128|60785|8304|2|16|27932.48|0.07|0.03|N|O|1997-07-13|1997-08-19|1997-08-10|COLLECT COD|AIR|he fluffily regular asymptotes thrash aga +12128|10572|8076|3|31|45959.67|0.01|0.08|N|O|1997-07-06|1997-08-14|1997-07-22|NONE|SHIP| theodolites cajole fluf +12128|83352|877|4|47|62761.45|0.06|0.08|N|O|1997-10-20|1997-08-14|1997-11-07|DELIVER IN PERSON|REG AIR|, regular pinto +12129|191010|8568|1|8|8808.08|0.00|0.00|A|F|1993-02-06|1993-02-21|1993-03-05|NONE|RAIL|regular requests haggle furious +12129|91681|4191|2|11|18399.48|0.02|0.06|R|F|1993-01-09|1993-03-15|1993-01-16|TAKE BACK RETURN|SHIP|carefully final theodol +12129|74871|9886|3|45|83064.15|0.00|0.00|R|F|1993-03-19|1993-02-24|1993-03-21|COLLECT COD|AIR|t the quic +12129|143967|3968|4|2|4021.92|0.07|0.01|A|F|1993-01-31|1993-02-16|1993-03-01|NONE|MAIL| above the c +12129|49757|2262|5|4|6827.00|0.05|0.04|A|F|1993-01-15|1993-02-25|1993-01-30|NONE|RAIL|fix silent asym +12130|94877|4878|1|35|65515.45|0.07|0.03|N|O|1996-02-04|1996-03-06|1996-03-05|COLLECT COD|SHIP|. regular, express requests befor +12130|195879|5880|2|11|21723.57|0.05|0.05|N|O|1995-12-18|1996-02-19|1996-01-03|NONE|MAIL|l tithes about the blithel +12130|122789|2790|3|47|85153.66|0.01|0.02|N|O|1996-01-17|1996-02-05|1996-02-08|NONE|TRUCK|yly ironic packages. bold pa +12130|110894|895|4|10|19048.90|0.09|0.04|N|O|1995-12-13|1996-01-20|1995-12-22|COLLECT COD|RAIL|iresias. special packages wak +12130|183881|1436|5|7|13754.16|0.05|0.00|N|O|1996-03-01|1996-02-24|1996-03-21|COLLECT COD|FOB|deposits. express, +12131|105988|1009|1|26|51843.48|0.03|0.01|N|O|1998-09-20|1998-08-06|1998-10-02|COLLECT COD|SHIP|courts. blithely r +12131|133985|9012|2|9|18170.82|0.06|0.06|N|O|1998-06-30|1998-08-12|1998-07-21|DELIVER IN PERSON|FOB|ular requests. unusual pinto +12131|79805|7327|3|21|37480.80|0.07|0.07|N|O|1998-10-06|1998-07-31|1998-10-13|COLLECT COD|FOB|posits. ideas across the requests kindl +12131|68864|6383|4|40|73314.40|0.08|0.00|N|O|1998-07-05|1998-08-27|1998-07-07|NONE|AIR|ests haggle +12131|186130|8649|5|21|25538.73|0.06|0.04|N|O|1998-07-22|1998-08-07|1998-07-26|TAKE BACK RETURN|SHIP|nstructions are bli +12131|75741|5742|6|43|73819.82|0.03|0.08|N|O|1998-09-12|1998-07-31|1998-09-25|COLLECT COD|MAIL|pendencies nag slyly. fluffil +12131|163520|3521|7|28|44338.56|0.01|0.06|N|O|1998-07-08|1998-09-14|1998-07-23|COLLECT COD|MAIL|usual deposits. furiously regular packa +12132|75402|7910|1|32|44076.80|0.04|0.05|N|O|1997-01-03|1996-11-05|1997-01-20|TAKE BACK RETURN|SHIP| according to the quickly even theod +12132|70683|5698|2|48|79376.64|0.01|0.08|N|O|1996-09-09|1996-11-27|1996-09-11|DELIVER IN PERSON|AIR|al ideas! carefully unusual deposits n +12132|166916|9433|3|7|13880.37|0.07|0.05|N|O|1996-09-23|1996-10-08|1996-10-19|NONE|REG AIR|nic, express ideas. furiously regul +12132|155282|5283|4|31|41455.68|0.04|0.00|N|O|1996-10-02|1996-10-11|1996-10-20|NONE|RAIL|heodolites use along the even packages: +12132|21886|1887|5|11|19886.68|0.03|0.00|N|O|1996-09-28|1996-11-01|1996-10-15|DELIVER IN PERSON|REG AIR|. busily unusual pinto bean +12132|35480|2990|6|44|62281.12|0.03|0.08|N|O|1996-10-05|1996-11-17|1996-10-24|COLLECT COD|MAIL|onic, pending deposits +12132|105217|2748|7|13|15888.73|0.08|0.07|N|O|1996-10-14|1996-11-03|1996-10-21|TAKE BACK RETURN|RAIL|y. furiously regular theodolites cajole fur +12133|167412|7413|1|35|51779.35|0.09|0.04|R|F|1992-08-09|1992-05-16|1992-09-08|COLLECT COD|FOB|en accounts are fluffily +12134|49297|6810|1|23|28664.67|0.08|0.00|N|O|1996-06-05|1996-07-21|1996-06-26|DELIVER IN PERSON|FOB|sleep fluffil +12134|131795|9335|2|22|40189.38|0.03|0.04|N|O|1996-07-22|1996-08-09|1996-08-13|NONE|REG AIR|of the furiously +12135|98456|8457|1|26|37815.70|0.02|0.08|N|O|1996-01-16|1995-12-18|1996-02-08|DELIVER IN PERSON|SHIP|e pending foxes. unusual packa +12135|139783|7323|2|49|89316.22|0.04|0.02|N|O|1995-10-21|1995-11-20|1995-11-08|TAKE BACK RETURN|REG AIR|nto beans sleep closely about the slowl +12135|118050|8051|3|36|38449.80|0.10|0.08|N|O|1995-12-23|1995-12-31|1996-01-21|DELIVER IN PERSON|TRUCK|lar theodolites haggle +12135|63097|5604|4|5|5300.45|0.07|0.06|N|O|1995-10-14|1995-12-13|1995-11-06|DELIVER IN PERSON|MAIL|kages. express gifts affix +12135|60463|5476|5|12|17081.52|0.04|0.06|N|O|1995-12-02|1995-11-15|1995-12-26|NONE|RAIL|slyly unusual packages. slyly pending +12135|191097|6136|6|46|54652.14|0.08|0.08|N|O|1995-11-27|1995-11-09|1995-11-30|NONE|RAIL|was above the +12135|153038|3039|7|5|5455.15|0.05|0.06|N|O|1996-01-21|1995-11-28|1996-01-22|TAKE BACK RETURN|FOB|ts. bravely ironic packages wake blithel +12160|100056|5077|1|3|3168.15|0.10|0.07|R|F|1994-02-15|1994-02-27|1994-02-27|DELIVER IN PERSON|SHIP|leep quickly along the theodolites. +12160|32059|9569|2|9|8919.45|0.01|0.01|R|F|1994-01-29|1994-02-18|1994-02-23|TAKE BACK RETURN|TRUCK|ites among the +12160|11420|6423|3|44|58582.48|0.00|0.01|R|F|1993-12-29|1994-03-09|1994-01-15|NONE|FOB|ets sleep furiously ironic req +12160|124592|9617|4|8|12932.72|0.03|0.04|A|F|1994-01-06|1994-01-28|1994-01-12|NONE|FOB|sits wake furious +12161|42139|2140|1|31|33515.03|0.06|0.05|N|O|1997-04-03|1997-06-10|1997-04-22|COLLECT COD|REG AIR|leep above +12161|24748|4749|2|5|8363.70|0.02|0.01|N|O|1997-06-28|1997-05-08|1997-07-01|TAKE BACK RETURN|MAIL|y pending ideas. slyly special package +12161|135494|521|3|42|64238.58|0.09|0.02|N|O|1997-03-26|1997-04-28|1997-04-09|COLLECT COD|AIR|uctions about the ev +12161|39833|9834|4|9|15955.47|0.00|0.07|N|O|1997-05-10|1997-05-10|1997-06-02|DELIVER IN PERSON|FOB|eep carefully +12161|67763|5282|5|42|72691.92|0.10|0.01|N|O|1997-03-24|1997-05-27|1997-04-11|DELIVER IN PERSON|TRUCK|ly bold ins +12161|86524|1541|6|14|21147.28|0.05|0.08|N|O|1997-05-08|1997-05-14|1997-05-16|NONE|FOB|grate. slyly regular deposits mold accor +12161|8096|8097|7|22|22089.98|0.02|0.03|N|O|1997-04-01|1997-05-08|1997-04-29|NONE|FOB|xpress requests sleep fluffi +12162|65245|2764|1|31|37517.44|0.06|0.06|N|O|1997-03-21|1997-05-09|1997-04-07|DELIVER IN PERSON|FOB|efully express platelets. carefully r +12163|181419|3938|1|38|57015.58|0.09|0.07|N|O|1997-08-21|1997-09-28|1997-09-07|TAKE BACK RETURN|FOB|cial packages use acc +12163|104538|9559|2|39|60158.67|0.08|0.00|N|O|1997-09-28|1997-09-23|1997-10-04|TAKE BACK RETURN|TRUCK|es. express, si +12163|165249|5250|3|32|42055.68|0.01|0.07|N|O|1997-08-10|1997-08-26|1997-08-18|TAKE BACK RETURN|AIR| pending dolphins use furiously ir +12163|136074|6075|4|48|53283.36|0.10|0.02|N|O|1997-07-23|1997-09-29|1997-08-09|COLLECT COD|FOB|eans across the furiously final theodolit +12164|182450|5|1|27|41376.15|0.06|0.07|R|F|1994-01-31|1993-11-30|1994-02-26|NONE|SHIP|tead of the blithely r +12164|37007|7008|2|19|17936.00|0.09|0.04|A|F|1993-12-22|1993-12-16|1994-01-02|COLLECT COD|RAIL|riously ab +12164|160393|394|3|22|31974.58|0.01|0.06|R|F|1993-10-28|1993-12-07|1993-11-18|DELIVER IN PERSON|REG AIR|lithely regular accounts sleep slyly alo +12164|119377|6911|4|28|39098.36|0.02|0.02|R|F|1994-01-28|1993-12-30|1994-02-06|COLLECT COD|SHIP|ckly unusual foxes. final deposits a +12164|165163|7680|5|5|6140.80|0.04|0.08|R|F|1993-11-06|1993-11-24|1993-12-01|TAKE BACK RETURN|AIR|s affix about +12164|78167|8168|6|22|25193.52|0.04|0.06|R|F|1993-12-16|1993-11-29|1994-01-07|DELIVER IN PERSON|REG AIR|wake. pendi +12165|137408|9922|1|12|17344.80|0.02|0.07|R|F|1994-07-14|1994-06-28|1994-07-25|DELIVER IN PERSON|FOB|tructions. ironic, even foxes +12165|3282|8283|2|42|49781.76|0.01|0.00|A|F|1994-08-05|1994-07-09|1994-08-13|NONE|SHIP|lly even foxes along the f +12165|155591|3137|3|30|49397.70|0.00|0.05|A|F|1994-06-15|1994-05-17|1994-06-30|NONE|MAIL|foxes affix above the +12165|13234|5736|4|47|53919.81|0.07|0.07|R|F|1994-06-09|1994-05-17|1994-06-30|DELIVER IN PERSON|RAIL|use quickly bold ideas. slyly express braid +12165|23422|5925|5|4|5381.68|0.01|0.06|A|F|1994-05-13|1994-05-29|1994-05-29|NONE|RAIL|ounts ought to da +12166|176941|1976|1|11|22197.34|0.04|0.02|A|F|1995-05-08|1995-05-08|1995-05-21|DELIVER IN PERSON|RAIL| accounts are after the carefully special +12167|2633|5134|1|22|33783.86|0.00|0.05|N|O|1998-08-10|1998-07-01|1998-09-08|NONE|REG AIR|above the f +12167|50763|3269|2|26|44557.76|0.02|0.08|N|O|1998-06-25|1998-07-09|1998-07-13|COLLECT COD|SHIP| of the quickly s +12192|92163|7182|1|15|17327.40|0.07|0.07|R|F|1995-02-10|1995-01-14|1995-03-04|DELIVER IN PERSON|RAIL|dinos. final, silent accounts p +12193|194164|4165|1|35|44035.60|0.04|0.06|N|O|1996-10-16|1996-09-18|1996-11-02|DELIVER IN PERSON|TRUCK| quickly slyly regular requests. furiously +12193|102933|7954|2|9|17423.37|0.02|0.02|N|O|1996-09-25|1996-09-19|1996-10-08|NONE|SHIP|ly special d +12193|181069|6106|3|38|43702.28|0.08|0.03|N|O|1996-10-06|1996-10-09|1996-10-19|TAKE BACK RETURN|AIR|even asymptotes sleep ironic accounts +12193|20766|5771|4|21|35421.96|0.05|0.07|N|O|1996-10-28|1996-10-09|1996-11-02|DELIVER IN PERSON|RAIL|e blithely. pin +12194|32241|2242|1|32|37543.68|0.02|0.01|A|F|1995-04-11|1995-05-14|1995-04-18|TAKE BACK RETURN|FOB| ironic instructi +12194|59404|1910|2|14|19087.60|0.06|0.07|A|F|1995-04-10|1995-05-24|1995-04-17|DELIVER IN PERSON|AIR|deas impress at the quickly unusual the +12195|178760|3795|1|40|73550.40|0.04|0.00|N|O|1997-07-16|1997-06-09|1997-07-28|NONE|AIR|eas wake never. fluffily final foxe +12195|6797|6798|2|46|78374.34|0.03|0.02|N|O|1997-07-17|1997-05-30|1997-08-10|COLLECT COD|REG AIR|ular requests are quickly +12196|87576|5101|1|1|1563.57|0.09|0.07|A|F|1993-06-15|1993-08-12|1993-06-30|COLLECT COD|SHIP|ounts. blithel +12196|74240|4241|2|4|4856.96|0.02|0.07|R|F|1993-09-20|1993-08-09|1993-10-02|DELIVER IN PERSON|MAIL|ly regular requests +12196|147678|193|3|6|10354.02|0.04|0.01|A|F|1993-06-18|1993-08-05|1993-06-25|NONE|MAIL|even packages above the instructions are +12196|23481|988|4|30|42134.40|0.01|0.00|A|F|1993-07-26|1993-09-01|1993-08-01|DELIVER IN PERSON|FOB|es wake slyly. regular +12196|38261|5771|5|19|22785.94|0.07|0.08|R|F|1993-09-19|1993-08-01|1993-09-21|COLLECT COD|TRUCK| final Tir +12196|37671|7672|6|7|11260.69|0.03|0.05|A|F|1993-08-10|1993-07-16|1993-08-16|DELIVER IN PERSON|RAIL|. slyly even +12197|67782|289|1|48|83989.44|0.08|0.05|N|O|1997-08-23|1997-09-23|1997-08-29|TAKE BACK RETURN|AIR|usly special instructions according t +12197|10142|143|2|44|46294.16|0.01|0.02|N|O|1997-07-26|1997-09-25|1997-08-13|DELIVER IN PERSON|MAIL| to the evenly final ideas. bra +12197|43021|3022|3|20|19280.40|0.03|0.06|N|O|1997-09-27|1997-08-20|1997-10-01|TAKE BACK RETURN|SHIP|ent theodolites sleep f +12197|43075|5580|4|41|41740.87|0.01|0.03|N|O|1997-07-29|1997-08-27|1997-08-01|TAKE BACK RETURN|AIR| after the dep +12197|157882|2913|5|4|7759.52|0.09|0.03|N|O|1997-10-01|1997-09-08|1997-10-06|COLLECT COD|RAIL|ual instructions affix furiousl +12198|169225|4258|1|37|47886.14|0.05|0.07|A|F|1993-06-04|1993-05-15|1993-06-05|TAKE BACK RETURN|REG AIR|ses. pending, final instructions cajo +12199|134883|2423|1|3|5753.64|0.03|0.03|N|O|1996-03-04|1996-03-06|1996-03-25|DELIVER IN PERSON|TRUCK|ly silent pinto beans +12199|171898|6933|2|2|3939.78|0.08|0.02|N|O|1996-02-23|1996-01-16|1996-03-04|COLLECT COD|FOB|ully about the fur +12199|83081|3082|3|38|40435.04|0.05|0.08|N|O|1996-02-10|1996-03-08|1996-02-14|COLLECT COD|TRUCK|haggle busily among the blithely spec +12199|141022|3537|4|22|23386.44|0.06|0.07|N|O|1995-12-17|1996-02-04|1996-01-09|DELIVER IN PERSON|MAIL|eposits affix blithely even +12224|43212|725|1|11|12707.31|0.03|0.00|R|F|1995-04-12|1995-02-06|1995-04-13|NONE|SHIP| integrate bl +12224|55114|5115|2|46|49179.06|0.00|0.03|A|F|1995-03-12|1995-02-15|1995-04-10|COLLECT COD|MAIL|asymptotes. special requests eat +12224|97205|2224|3|47|56503.40|0.09|0.05|R|F|1995-03-14|1995-02-09|1995-04-11|DELIVER IN PERSON|AIR|the slyly i +12224|114290|1824|4|42|54780.18|0.04|0.08|A|F|1995-01-03|1995-01-23|1995-01-21|DELIVER IN PERSON|RAIL|otes are above the final +12225|110946|8480|1|2|3913.88|0.02|0.04|N|O|1997-03-27|1997-03-30|1997-03-31|TAKE BACK RETURN|MAIL|nt requests w +12225|56514|9020|2|29|42644.79|0.08|0.05|N|O|1997-03-14|1997-03-06|1997-03-19|NONE|TRUCK|cajole fluffily furiously regular a +12225|30272|2776|3|48|57708.96|0.04|0.04|N|O|1997-04-14|1997-03-11|1997-05-05|DELIVER IN PERSON|MAIL|e, regular excuses boo +12225|179154|1672|4|13|16030.95|0.05|0.00|N|O|1997-02-14|1997-04-12|1997-03-04|COLLECT COD|FOB|ide of the carefully silent f +12225|28777|8778|5|36|61407.72|0.10|0.04|N|O|1997-03-06|1997-03-02|1997-03-19|TAKE BACK RETURN|TRUCK|e blithely. +12225|54743|7249|6|19|32257.06|0.09|0.05|N|O|1997-05-25|1997-03-21|1997-06-08|COLLECT COD|RAIL|lthily among the quietly ironic asymptotes. +12226|105936|3467|1|33|64083.69|0.06|0.07|N|O|1998-04-06|1998-05-12|1998-05-02|TAKE BACK RETURN|REG AIR|ans nag. bold, expr +12226|58969|3980|2|39|75190.44|0.02|0.07|N|O|1998-04-02|1998-06-12|1998-04-05|COLLECT COD|REG AIR|s. fluffily regular ins +12226|81554|4063|3|16|24568.80|0.04|0.06|N|O|1998-07-11|1998-06-17|1998-07-20|DELIVER IN PERSON|MAIL|s nag along the ca +12227|117948|2971|1|3|5897.82|0.08|0.03|N|O|1998-08-11|1998-08-13|1998-08-29|DELIVER IN PERSON|RAIL|, ironic tithes. furiously even +12227|151425|6456|2|44|64962.48|0.00|0.02|N|O|1998-10-09|1998-09-09|1998-11-05|DELIVER IN PERSON|TRUCK|ular accounts. furiously regula +12227|183277|832|3|11|14962.97|0.01|0.07|N|O|1998-08-13|1998-07-28|1998-08-29|COLLECT COD|MAIL|odolites haggle. pint +12227|124622|9647|4|34|55985.08|0.10|0.01|N|O|1998-10-06|1998-08-04|1998-10-27|TAKE BACK RETURN|REG AIR|ronic excuses nag fur +12227|109016|4037|5|40|41000.40|0.00|0.01|N|O|1998-07-25|1998-07-31|1998-08-22|NONE|TRUCK|as nag around the carefully specia +12227|15184|187|6|23|25281.14|0.00|0.03|N|O|1998-09-08|1998-09-12|1998-09-19|COLLECT COD|REG AIR| the furiously pending escapades. +12227|188046|565|7|13|14742.52|0.09|0.08|N|O|1998-08-15|1998-09-22|1998-08-31|DELIVER IN PERSON|AIR| platelets. final, ironic pin +12228|80995|8520|1|17|33591.83|0.06|0.00|A|F|1994-08-20|1994-08-22|1994-09-18|DELIVER IN PERSON|SHIP|blithely ironic depths +12228|73597|3598|2|50|78529.50|0.06|0.04|A|F|1994-10-14|1994-08-25|1994-11-01|TAKE BACK RETURN|MAIL| theodolites hagg +12228|143501|8530|3|18|27801.00|0.08|0.00|A|F|1994-08-21|1994-08-13|1994-08-27|COLLECT COD|FOB|equests. quickly pendi +12228|11554|6557|4|9|13189.95|0.10|0.01|R|F|1994-08-07|1994-09-09|1994-09-04|COLLECT COD|TRUCK|jole silently. even deposits hagg +12228|180656|5693|5|30|52099.50|0.01|0.00|A|F|1994-08-10|1994-09-04|1994-08-14|COLLECT COD|MAIL|ites cajole. regu +12228|68953|6472|6|47|90331.65|0.02|0.05|R|F|1994-08-10|1994-09-02|1994-08-21|NONE|AIR|accounts? slyly unusua +12228|83954|8971|7|6|11627.70|0.02|0.04|A|F|1994-10-01|1994-08-13|1994-10-19|DELIVER IN PERSON|TRUCK|g to the regular warhorses. slyly blithe co +12229|14403|1907|1|12|15808.80|0.09|0.06|N|O|1996-08-28|1996-09-09|1996-09-11|TAKE BACK RETURN|AIR|ag across the unusual theodolites. a +12229|70171|172|2|21|23964.57|0.06|0.06|N|O|1996-09-27|1996-10-14|1996-10-19|TAKE BACK RETURN|AIR|about the bold deposits +12229|163220|769|3|38|48762.36|0.03|0.07|N|O|1996-07-27|1996-08-26|1996-08-03|NONE|SHIP|en deposits: special foxes nag above +12230|4363|6864|1|19|24079.84|0.03|0.06|N|O|1998-05-03|1998-05-12|1998-05-05|COLLECT COD|TRUCK|e slyly against the +12230|114089|4090|2|30|33092.40|0.03|0.03|N|O|1998-06-07|1998-05-10|1998-07-06|TAKE BACK RETURN|TRUCK|ackages. furiously final exc +12230|85305|2830|3|12|15483.60|0.07|0.00|N|O|1998-06-03|1998-06-20|1998-07-03|COLLECT COD|AIR|le furiousl +12230|117093|9605|4|25|27752.25|0.07|0.08|N|O|1998-07-09|1998-06-20|1998-08-07|DELIVER IN PERSON|RAIL|es cajole. quickly regu +12230|175713|8231|5|40|71548.40|0.07|0.06|N|O|1998-07-05|1998-06-10|1998-07-10|TAKE BACK RETURN|MAIL|ct unusual requests? carefully ironic foxe +12231|95465|2993|1|9|13144.14|0.09|0.06|N|O|1997-10-17|1997-09-10|1997-11-16|COLLECT COD|SHIP|ound the fur +12231|63935|6442|2|17|32281.81|0.07|0.01|N|O|1997-11-22|1997-10-27|1997-12-22|DELIVER IN PERSON|TRUCK|ts cajole. permanently bold attainments ag +12231|142031|4546|3|16|17168.48|0.09|0.04|N|O|1997-09-25|1997-09-07|1997-10-02|TAKE BACK RETURN|TRUCK|rts. special pac +12231|109185|1696|4|35|41796.30|0.05|0.07|N|O|1997-11-16|1997-08-29|1997-12-12|TAKE BACK RETURN|TRUCK| the pending accoun +12231|59939|9940|5|44|83552.92|0.02|0.08|N|O|1997-11-17|1997-10-04|1997-12-16|DELIVER IN PERSON|SHIP|ourts. silent, bold T +12231|190509|510|6|43|68778.50|0.01|0.01|N|O|1997-08-29|1997-09-03|1997-09-04|COLLECT COD|SHIP|, bold deposits are never express platelet +12256|182959|514|1|17|34713.15|0.03|0.04|A|F|1993-02-12|1993-03-09|1993-02-24|TAKE BACK RETURN|FOB|ges. unusual multiplier +12256|190364|7922|2|11|15997.96|0.02|0.04|R|F|1993-03-21|1993-02-11|1993-04-20|COLLECT COD|TRUCK|xpress deposits thrash blithely about the +12256|41062|3567|3|20|20061.20|0.09|0.04|R|F|1993-04-12|1993-02-15|1993-05-10|NONE|RAIL|r ideas wake +12256|117709|7710|4|19|32807.30|0.08|0.06|R|F|1993-01-16|1993-03-09|1993-02-03|NONE|TRUCK|regular deposits. regular, regular pinto +12256|124380|9405|5|44|61792.72|0.01|0.04|R|F|1992-12-24|1993-02-11|1992-12-28|COLLECT COD|TRUCK|ess packages use fluffily inside the +12257|109205|6736|1|21|25498.20|0.04|0.05|N|O|1996-07-28|1996-05-29|1996-08-17|TAKE BACK RETURN|REG AIR|nusual asymptotes. quickly even a +12257|192155|7194|2|27|33673.05|0.00|0.03|N|O|1996-08-14|1996-07-10|1996-08-20|DELIVER IN PERSON|FOB|gular tithes haggle slyly +12257|132847|7874|3|46|86472.64|0.04|0.04|N|O|1996-05-27|1996-05-28|1996-06-07|DELIVER IN PERSON|REG AIR| fluffily final foxes. ca +12258|76987|4509|1|31|60883.38|0.07|0.03|A|F|1995-02-11|1995-01-22|1995-03-09|TAKE BACK RETURN|FOB|s use. sil +12258|109655|2166|2|27|44945.55|0.03|0.05|A|F|1994-12-05|1995-02-25|1995-01-01|DELIVER IN PERSON|MAIL|e slyly stealthy packages. slyly busy id +12258|160850|3367|3|25|47771.25|0.05|0.02|R|F|1995-02-28|1995-01-11|1995-03-02|NONE|AIR|ounts are acros +12258|197161|2200|4|36|45293.76|0.07|0.05|A|F|1994-12-23|1995-02-07|1995-01-07|TAKE BACK RETURN|TRUCK|iously. care +12258|82090|2091|5|20|21441.80|0.01|0.00|A|F|1994-12-19|1995-02-06|1994-12-24|DELIVER IN PERSON|REG AIR|elets. bli +12258|82199|7216|6|39|46066.41|0.07|0.06|R|F|1995-01-20|1995-01-26|1995-02-08|NONE|RAIL|refully. blithely bold deposits ab +12258|116052|6053|7|20|21361.00|0.05|0.00|R|F|1994-12-15|1995-01-30|1995-01-03|TAKE BACK RETURN|SHIP|s. quickly express excuses eat: never r +12259|82264|4773|1|1|1246.26|0.02|0.03|R|F|1993-05-15|1993-05-14|1993-05-31|TAKE BACK RETURN|RAIL| fluffily blithe foxes are ca +12259|5666|3167|2|34|53436.44|0.06|0.02|R|F|1993-05-15|1993-05-11|1993-05-24|COLLECT COD|SHIP|y even dugouts. final instructions along th +12259|20358|5363|3|13|16618.55|0.09|0.05|R|F|1993-05-17|1993-04-22|1993-06-14|TAKE BACK RETURN|TRUCK|ets boost. quickly unu +12259|147680|2709|4|32|55285.76|0.08|0.05|R|F|1993-04-18|1993-04-16|1993-04-29|DELIVER IN PERSON|TRUCK| ironic attainments. carefully ironic du +12259|51135|3641|5|34|36928.42|0.10|0.00|A|F|1993-04-07|1993-03-21|1993-04-14|COLLECT COD|SHIP|t have to are +12259|13881|8884|6|16|28718.08|0.01|0.06|R|F|1993-05-17|1993-03-20|1993-05-28|DELIVER IN PERSON|RAIL|gular accounts haggl +12259|93517|1045|7|14|21147.14|0.07|0.00|R|F|1993-03-11|1993-04-12|1993-03-29|DELIVER IN PERSON|AIR|ecial sheaves. final accounts cajole +12260|125302|7815|1|26|34509.80|0.03|0.02|R|F|1993-01-29|1993-02-15|1993-02-21|COLLECT COD|MAIL|quests. regular pinto beans against the +12260|147539|5082|2|11|17451.83|0.09|0.06|A|F|1993-03-26|1993-01-17|1993-04-17|NONE|REG AIR|y. regular packag +12260|80531|532|3|36|54415.08|0.07|0.03|A|F|1993-03-05|1993-02-20|1993-03-16|DELIVER IN PERSON|RAIL|ffily even theo +12260|70468|5483|4|13|18699.98|0.06|0.00|A|F|1993-03-11|1992-12-31|1993-03-19|DELIVER IN PERSON|FOB|ironic courts. fu +12260|143666|3667|5|38|64967.08|0.09|0.07|R|F|1993-01-31|1993-01-11|1993-02-24|COLLECT COD|SHIP|sly even theodolites cajole. final requ +12261|30576|3080|1|28|42183.96|0.09|0.00|A|F|1994-02-13|1994-01-22|1994-03-14|COLLECT COD|SHIP|s cajole carefully. pending Tiresias +12261|75034|7542|2|30|30270.90|0.08|0.00|R|F|1993-12-30|1993-12-18|1994-01-28|COLLECT COD|AIR|ual, special +12261|92472|4982|3|41|60043.27|0.05|0.01|R|F|1994-02-03|1993-12-03|1994-02-26|DELIVER IN PERSON|MAIL|o beans sleep across the doggedly reg +12261|174193|1745|4|37|46886.03|0.10|0.06|R|F|1993-11-24|1993-12-18|1993-12-21|NONE|REG AIR|after the quickly ironic id +12261|60130|7649|5|39|42515.07|0.05|0.08|A|F|1994-02-03|1993-12-08|1994-02-26|DELIVER IN PERSON|MAIL|ly quietly ir +12261|4705|4706|6|49|78875.30|0.05|0.06|R|F|1993-10-29|1994-01-07|1993-11-28|TAKE BACK RETURN|TRUCK|ublate slyly beside th +12261|63701|3702|7|32|53270.40|0.04|0.04|R|F|1994-01-21|1994-01-15|1994-01-26|NONE|MAIL|as nag carefully a +12262|21521|1522|1|17|24522.84|0.02|0.07|N|O|1996-01-29|1996-01-25|1996-02-11|DELIVER IN PERSON|AIR|onic packages. ex +12262|95743|762|2|33|57378.42|0.05|0.04|N|O|1996-01-12|1996-01-21|1996-02-07|DELIVER IN PERSON|MAIL|ven packages sleep slyly +12262|152260|9806|3|9|11810.34|0.08|0.08|N|O|1996-03-04|1996-03-09|1996-03-18|COLLECT COD|FOB|ly silent accounts ha +12262|28024|8025|4|43|40936.86|0.09|0.00|N|O|1995-12-24|1996-02-18|1996-01-02|DELIVER IN PERSON|RAIL|bold deposit +12263|65253|5254|1|35|42638.75|0.08|0.02|N|O|1995-08-24|1995-08-29|1995-09-11|TAKE BACK RETURN|SHIP|ccounts sleep slyly blithely express de +12263|93355|3356|2|33|44495.55|0.05|0.00|N|O|1995-09-14|1995-09-02|1995-10-07|TAKE BACK RETURN|REG AIR|ans use blithely +12263|3859|6360|3|13|22917.05|0.03|0.00|N|O|1995-08-21|1995-09-16|1995-08-23|COLLECT COD|TRUCK|y. special accounts a +12263|54466|6972|4|29|41193.34|0.08|0.06|N|O|1995-09-19|1995-09-02|1995-10-19|NONE|RAIL|usly. carefully ironic +12288|75235|5236|1|21|25414.83|0.05|0.00|N|O|1996-12-29|1996-12-15|1997-01-15|TAKE BACK RETURN|REG AIR|blithely even foxes h +12288|62354|7367|2|13|17112.55|0.04|0.04|N|O|1996-12-26|1996-12-06|1997-01-09|TAKE BACK RETURN|TRUCK|ackages are blithely. +12288|167627|144|3|17|28808.54|0.05|0.03|N|O|1997-01-19|1997-01-13|1997-01-24|NONE|SHIP|uests detect furiously. qu +12288|102003|2004|4|48|48240.00|0.02|0.07|N|O|1997-02-15|1996-12-13|1997-03-01|DELIVER IN PERSON|MAIL|ies about the carefully ir +12289|185411|448|1|39|58359.99|0.02|0.07|N|O|1996-04-16|1996-02-12|1996-05-13|NONE|RAIL|ely. final, even foxes according to +12289|193595|6115|2|29|48969.11|0.01|0.08|N|O|1996-03-11|1996-03-21|1996-04-06|COLLECT COD|AIR|ess requests eat thinly blithely unus +12290|166534|9051|1|49|78425.97|0.07|0.04|N|O|1995-09-30|1995-08-11|1995-10-14|TAKE BACK RETURN|MAIL|, pending deposits sleep iron +12290|136061|3601|2|23|25232.38|0.03|0.02|N|O|1995-10-09|1995-09-01|1995-10-10|NONE|FOB|usual packa +12291|140230|7773|1|14|17783.22|0.02|0.08|N|O|1998-05-03|1998-06-12|1998-05-17|TAKE BACK RETURN|RAIL|jole quickly final foxes. unusu +12292|81949|6966|1|45|86892.30|0.07|0.08|A|F|1992-08-07|1992-07-14|1992-08-09|COLLECT COD|REG AIR|tes? carefully bold packages above th +12292|115640|663|2|25|41391.00|0.10|0.01|A|F|1992-07-20|1992-07-06|1992-07-24|TAKE BACK RETURN|AIR| bold theodolites +12292|151368|8914|3|42|59613.12|0.05|0.00|R|F|1992-06-12|1992-07-05|1992-07-07|DELIVER IN PERSON|SHIP| even deposits. qu +12292|29244|6751|4|15|17598.60|0.02|0.03|R|F|1992-08-26|1992-07-20|1992-09-11|COLLECT COD|RAIL|ely ironic asymptotes. final, +12293|168359|8360|1|28|39965.80|0.04|0.07|N|O|1995-10-02|1995-08-26|1995-10-14|COLLECT COD|AIR| slyly slyly +12293|199973|7531|2|37|76699.89|0.10|0.02|N|O|1995-09-11|1995-09-07|1995-09-25|DELIVER IN PERSON|REG AIR|lites. carefully final +12293|144290|4291|3|20|26685.80|0.03|0.00|N|O|1995-10-16|1995-07-26|1995-10-31|DELIVER IN PERSON|SHIP|warthogs. carefully quiet acc +12294|132083|2084|1|15|16726.20|0.06|0.04|N|O|1995-08-31|1995-08-25|1995-09-20|COLLECT COD|AIR|thely special accounts wake slyly +12294|104905|4906|2|39|74486.10|0.10|0.00|N|O|1995-11-02|1995-10-03|1995-11-26|DELIVER IN PERSON|AIR|t the slyly bold theodoli +12294|136813|4353|3|16|29596.96|0.00|0.08|N|O|1995-07-25|1995-09-13|1995-08-01|COLLECT COD|RAIL|ructions. packages across the ironi +12294|600|8101|4|39|58523.40|0.06|0.01|N|O|1995-09-09|1995-08-07|1995-09-22|COLLECT COD|TRUCK|special, regular deposi +12294|75933|3455|5|48|91628.64|0.05|0.00|N|O|1995-08-02|1995-09-11|1995-08-31|TAKE BACK RETURN|AIR|e of the blithely bold asympto +12295|82213|9738|1|45|53784.45|0.06|0.00|A|F|1993-12-02|1994-01-17|1993-12-13|COLLECT COD|FOB|ccounts affix f +12295|148978|1493|2|8|16215.76|0.06|0.08|A|F|1994-03-01|1994-01-01|1994-03-12|NONE|TRUCK|iously pending ide +12320|136931|4471|1|43|84620.99|0.02|0.07|N|O|1996-02-29|1996-02-29|1996-03-28|NONE|REG AIR|ts. special packages above the packages caj +12320|193674|3675|2|33|58333.11|0.05|0.06|N|O|1996-02-18|1996-03-09|1996-02-29|COLLECT COD|TRUCK| excuses are carefully abov +12321|105127|2658|1|13|14717.56|0.01|0.02|A|F|1994-05-16|1994-05-14|1994-05-31|NONE|AIR|nag. express deposits are blithely fu +12322|55282|7788|1|11|13610.08|0.00|0.06|N|F|1995-06-10|1995-06-12|1995-06-21|COLLECT COD|MAIL|ily furiou +12322|118458|970|2|20|29529.00|0.00|0.04|N|O|1995-07-20|1995-06-24|1995-08-04|TAKE BACK RETURN|REG AIR| carefully iron +12322|108775|1286|3|3|5351.31|0.07|0.06|R|F|1995-05-24|1995-08-05|1995-06-16|NONE|AIR|o the fluffily ironic deposits +12323|118585|1097|1|1|1603.58|0.04|0.00|N|O|1995-06-26|1995-06-13|1995-07-13|NONE|MAIL|es sleep slyly. fu +12323|54955|4956|2|4|7639.80|0.02|0.05|N|O|1995-06-20|1995-06-04|1995-07-06|TAKE BACK RETURN|MAIL|c packages +12323|19248|4251|3|34|39686.16|0.00|0.08|N|O|1995-07-28|1995-05-26|1995-08-05|COLLECT COD|RAIL|ctions. carefully regular req +12323|97783|5311|4|35|62327.30|0.09|0.08|N|O|1995-06-28|1995-06-19|1995-07-05|COLLECT COD|TRUCK|efully after the +12323|37037|9541|5|6|5844.18|0.03|0.05|R|F|1995-04-19|1995-06-16|1995-05-02|NONE|AIR| ideas. fluffily bold dep +12323|75483|5484|6|12|17501.76|0.00|0.02|N|O|1995-07-20|1995-06-01|1995-08-19|TAKE BACK RETURN|FOB|nts. blithely final platelets are c +12324|27201|2206|1|11|12410.20|0.07|0.06|N|O|1998-10-08|1998-10-01|1998-11-04|DELIVER IN PERSON|REG AIR| final foxes. slyly sp +12324|153140|8171|2|42|50111.88|0.00|0.03|N|O|1998-11-09|1998-09-27|1998-12-08|DELIVER IN PERSON|TRUCK| the furiously pending deposits. i +12324|11237|3739|3|35|40188.05|0.02|0.08|N|O|1998-09-25|1998-10-22|1998-09-27|DELIVER IN PERSON|MAIL|r, ironic deposits sleep. unus +12324|48672|1177|4|13|21068.71|0.04|0.03|N|O|1998-11-07|1998-10-14|1998-11-10|NONE|AIR|g to the fluffily even packages cajole +12324|25881|8384|5|16|28910.08|0.07|0.00|N|O|1998-09-21|1998-10-21|1998-10-02|COLLECT COD|REG AIR|old accounts cajole carefully requests +12324|165386|2935|6|34|49346.92|0.03|0.07|N|O|1998-09-12|1998-10-16|1998-09-20|NONE|TRUCK|eans. requests are furiou +12325|62491|4998|1|49|71221.01|0.08|0.02|R|F|1995-03-07|1995-04-04|1995-03-17|DELIVER IN PERSON|RAIL| furiously final deposits. orbits are qui +12326|42694|7703|1|12|19640.28|0.06|0.03|R|F|1995-04-17|1995-04-12|1995-05-02|TAKE BACK RETURN|MAIL|ironic, final accounts above the furious +12326|158058|3089|2|29|32365.45|0.05|0.03|R|F|1995-03-11|1995-05-04|1995-04-06|NONE|REG AIR|pecial instructions. carefully fin +12326|77516|2531|3|43|64220.93|0.02|0.00|A|F|1995-05-07|1995-04-09|1995-05-10|DELIVER IN PERSON|TRUCK|eep slyly pending req +12326|197759|7760|4|30|55702.50|0.09|0.04|R|F|1995-05-02|1995-03-19|1995-05-08|COLLECT COD|SHIP| bold asymptotes detect regular +12327|162360|9909|1|9|12801.24|0.07|0.04|N|O|1998-05-31|1998-05-30|1998-06-11|NONE|SHIP| foxes. express frets at the regular +12327|168349|8350|2|10|14173.40|0.05|0.02|N|O|1998-06-27|1998-06-24|1998-07-04|TAKE BACK RETURN|FOB|foxes are regular acco +12327|27568|71|3|9|13460.04|0.04|0.03|N|O|1998-07-12|1998-06-19|1998-08-02|COLLECT COD|SHIP|ithely spe +12352|34284|6788|1|31|37766.68|0.08|0.03|R|F|1992-06-15|1992-05-26|1992-07-15|NONE|FOB|ring, silent d +12352|195641|8161|2|44|76412.16|0.09|0.01|A|F|1992-07-23|1992-05-04|1992-08-19|NONE|TRUCK|riously blithely reg +12352|129830|7367|3|39|72533.37|0.05|0.08|A|F|1992-04-01|1992-05-27|1992-04-19|TAKE BACK RETURN|AIR|he furiously ironic requests. slyly re +12352|52148|9664|4|30|33004.20|0.10|0.07|A|F|1992-05-15|1992-05-15|1992-05-23|COLLECT COD|TRUCK|ts wake quietly alon +12352|37734|5244|5|20|33434.60|0.03|0.03|R|F|1992-06-13|1992-05-04|1992-06-30|COLLECT COD|FOB|t blithely. regular requests +12352|185368|405|6|18|26160.48|0.04|0.00|R|F|1992-04-12|1992-05-27|1992-04-30|DELIVER IN PERSON|SHIP|p ruthlessly despite the slyl +12352|75056|7564|7|48|49490.40|0.09|0.04|A|F|1992-06-12|1992-05-22|1992-06-29|DELIVER IN PERSON|REG AIR|ularly above the ironic requests. +12353|61838|9357|1|28|50395.24|0.02|0.04|N|O|1996-05-24|1996-06-10|1996-06-22|TAKE BACK RETURN|MAIL|uests use. fluffily regular foxes +12353|100105|2616|2|43|47519.30|0.04|0.03|N|O|1996-08-05|1996-06-20|1996-08-28|NONE|TRUCK|y special accounts are: expres +12353|53311|3312|3|33|41722.23|0.10|0.01|N|O|1996-06-27|1996-05-25|1996-07-02|TAKE BACK RETURN|SHIP|slyly ironic epitaphs. +12353|197681|5239|4|26|46245.68|0.00|0.06|N|O|1996-07-25|1996-06-06|1996-08-02|TAKE BACK RETURN|REG AIR| of the unusual, special packages. eve +12353|13471|5973|5|43|59532.21|0.05|0.02|N|O|1996-05-07|1996-06-11|1996-05-25|DELIVER IN PERSON|REG AIR|al ideas sleep. +12354|172573|5091|1|18|29620.26|0.04|0.07|N|O|1997-02-07|1997-03-16|1997-03-05|TAKE BACK RETURN|TRUCK|ual foxes detect f +12354|21897|6902|2|15|27283.35|0.09|0.08|N|O|1997-04-27|1997-03-19|1997-05-14|TAKE BACK RETURN|SHIP|d about the regular, +12354|14948|7450|3|8|14903.52|0.05|0.05|N|O|1997-05-02|1997-03-10|1997-05-08|DELIVER IN PERSON|REG AIR| accounts wake acro +12355|125725|5726|1|31|54272.32|0.01|0.02|N|O|1995-09-08|1995-08-19|1995-09-19|NONE|SHIP|ns. blithely reg +12355|55091|7597|2|36|37659.24|0.09|0.06|N|O|1995-08-11|1995-07-14|1995-08-17|COLLECT COD|TRUCK|egular accounts. fluff +12355|101599|1600|3|14|22408.26|0.08|0.02|N|F|1995-06-13|1995-06-28|1995-07-11|NONE|MAIL| express de +12355|168483|8484|4|47|72919.56|0.10|0.08|N|O|1995-06-30|1995-08-25|1995-07-03|NONE|TRUCK|thely even deposits haggle fluffily regu +12355|79033|1541|5|18|18216.54|0.09|0.04|N|F|1995-06-17|1995-08-20|1995-07-13|DELIVER IN PERSON|MAIL|slyly above the ac +12355|94634|9653|6|35|57002.05|0.05|0.06|N|O|1995-09-21|1995-07-25|1995-10-20|DELIVER IN PERSON|FOB|ackages use by the fur +12355|112918|2919|7|20|38618.20|0.01|0.02|N|O|1995-09-08|1995-07-10|1995-10-01|TAKE BACK RETURN|MAIL|ven excuses u +12356|5787|8288|1|50|84639.00|0.05|0.03|A|F|1993-02-13|1992-12-03|1993-02-17|TAKE BACK RETURN|MAIL|t the blithely slow packages. care +12356|54663|4664|2|26|42059.16|0.06|0.05|R|F|1992-11-25|1992-12-06|1992-12-24|DELIVER IN PERSON|TRUCK|ep quickly. slyly bo +12356|112337|2338|3|38|51274.54|0.07|0.04|A|F|1992-11-19|1992-12-26|1992-12-09|TAKE BACK RETURN|TRUCK|l, pending dependencies. blithely iron +12357|35814|8318|1|4|6999.24|0.09|0.04|N|O|1995-11-07|1995-11-16|1995-11-25|NONE|REG AIR| pinto beans. carefull +12357|114840|2374|2|18|33387.12|0.06|0.04|N|O|1995-09-16|1995-10-06|1995-09-18|TAKE BACK RETURN|TRUCK|detect furiously +12357|113518|3519|3|42|64323.42|0.03|0.08|N|O|1995-11-27|1995-10-06|1995-12-10|NONE|REG AIR|final reques +12357|94231|9250|4|12|14702.76|0.03|0.03|N|O|1995-11-29|1995-11-20|1995-11-30|TAKE BACK RETURN|TRUCK|ages against the unusual d +12358|189895|9896|1|19|37712.91|0.04|0.00|N|O|1997-01-15|1996-12-03|1997-02-10|DELIVER IN PERSON|AIR|. carefully even deposi +12358|153885|3886|2|27|52349.76|0.02|0.02|N|O|1996-11-17|1996-11-29|1996-12-14|TAKE BACK RETURN|RAIL|yly regular packages about the ir +12358|133567|3568|3|3|4801.68|0.04|0.00|N|O|1996-12-26|1996-12-09|1997-01-02|TAKE BACK RETURN|SHIP| regular requests above the de +12358|51074|6085|4|31|31777.17|0.05|0.05|N|O|1997-01-29|1996-11-28|1997-02-27|TAKE BACK RETURN|REG AIR|nts. fluffily permanent ins +12358|191167|8725|5|32|40261.12|0.08|0.01|N|O|1997-01-30|1996-11-10|1997-02-03|NONE|RAIL|ests sleep furiously ironic pa +12358|140436|7979|6|1|1476.43|0.06|0.04|N|O|1996-10-16|1996-11-19|1996-11-13|COLLECT COD|RAIL|r the carefully express theodolites. stealt +12358|97582|5110|7|30|47387.40|0.01|0.02|N|O|1997-01-24|1997-01-06|1997-01-28|COLLECT COD|FOB|the final, final deposits sleep exp +12359|58090|5606|1|33|34586.97|0.00|0.08|N|O|1997-07-23|1997-07-21|1997-08-08|DELIVER IN PERSON|FOB|nts haggle quickly aft +12359|108675|8676|2|42|70714.14|0.03|0.08|N|O|1997-06-16|1997-07-18|1997-06-17|TAKE BACK RETURN|RAIL|ely final theodolit +12359|91211|8739|3|27|32459.67|0.10|0.02|N|O|1997-08-05|1997-08-19|1997-08-25|NONE|REG AIR|final pinto beans are fluffily amo +12359|169624|9625|4|48|81293.76|0.03|0.00|N|O|1997-08-18|1997-08-17|1997-09-12|COLLECT COD|REG AIR|n dependencies above t +12384|187657|176|1|17|29659.05|0.03|0.00|N|O|1998-11-14|1998-09-05|1998-12-01|COLLECT COD|AIR|ove the fluffily regular asympt +12384|150286|287|2|47|62805.16|0.05|0.07|N|O|1998-09-01|1998-09-28|1998-10-01|NONE|MAIL|kly pending foxes cajole regular +12384|45204|2717|3|20|22984.00|0.09|0.06|N|O|1998-08-11|1998-10-23|1998-09-05|DELIVER IN PERSON|MAIL|arefully among th +12384|135758|3298|4|8|14350.00|0.09|0.01|N|O|1998-10-15|1998-10-09|1998-11-05|COLLECT COD|MAIL|eodolites-- always ev +12384|84161|1686|5|6|6870.96|0.04|0.00|N|O|1998-11-26|1998-10-04|1998-12-08|COLLECT COD|RAIL|ep blithely. blithely ironic r +12384|79057|4072|6|39|40405.95|0.04|0.01|N|O|1998-08-06|1998-10-11|1998-09-01|NONE|REG AIR|nstructions affix blithely according to +12384|107297|4828|7|8|10434.32|0.01|0.01|N|O|1998-09-22|1998-09-22|1998-10-18|TAKE BACK RETURN|RAIL|al requests sleep carefully +12385|132181|7208|1|6|7279.08|0.01|0.03|R|F|1993-03-20|1993-02-10|1993-03-26|COLLECT COD|RAIL|quickly unusual +12385|158731|6277|2|22|39374.06|0.01|0.04|R|F|1993-01-01|1993-02-12|1993-01-19|DELIVER IN PERSON|TRUCK|fily. ironic, ironic +12385|191899|1900|3|1|1990.89|0.00|0.08|R|F|1993-01-28|1993-01-05|1993-02-22|NONE|FOB|ns-- furiously unusual requests snooze a +12385|37018|9522|4|32|30560.32|0.01|0.02|A|F|1993-01-10|1993-01-01|1993-01-22|NONE|RAIL|quests wake blithely. regular +12385|145100|2643|5|6|6870.60|0.02|0.08|A|F|1993-02-19|1993-01-29|1993-03-09|NONE|RAIL|l accounts thrash +12386|96471|8981|1|49|71906.03|0.10|0.06|R|F|1992-06-29|1992-06-01|1992-07-24|COLLECT COD|REG AIR| the blithely +12386|175077|112|2|34|39170.38|0.07|0.02|R|F|1992-05-26|1992-05-18|1992-06-15|TAKE BACK RETURN|MAIL|ronic theodolites. regular, +12386|105581|602|3|32|50770.56|0.08|0.06|A|F|1992-05-29|1992-05-08|1992-06-08|TAKE BACK RETURN|TRUCK|ecial deposits. furiously steal +12386|84452|9469|4|43|61767.35|0.03|0.08|A|F|1992-06-19|1992-05-25|1992-07-10|TAKE BACK RETURN|MAIL|odolites. evenly even requ +12386|170228|2746|5|43|55823.46|0.07|0.02|A|F|1992-04-15|1992-05-17|1992-05-01|NONE|AIR|ons. furiously regular requ +12387|128638|6175|1|46|76664.98|0.10|0.07|N|O|1997-09-18|1997-08-30|1997-10-03|TAKE BACK RETURN|AIR|ic accounts sleep. foxes sleep along the +12388|186826|9345|1|47|89902.54|0.01|0.04|N|O|1997-12-07|1997-12-01|1997-12-08|COLLECT COD|SHIP|le after the slyly expres +12388|169235|9236|2|17|22171.91|0.09|0.07|N|O|1998-01-13|1997-12-17|1998-01-25|NONE|MAIL|tructions +12388|119544|7078|3|15|23453.10|0.04|0.08|N|O|1997-11-17|1998-01-12|1997-12-15|COLLECT COD|TRUCK|le carefully quickly regular acco +12388|170252|2770|4|31|40989.75|0.02|0.04|N|O|1997-12-28|1997-11-26|1998-01-07|TAKE BACK RETURN|REG AIR|nic escapades. furiousl +12388|20812|5817|5|40|69312.40|0.03|0.01|N|O|1997-12-19|1997-11-15|1998-01-12|DELIVER IN PERSON|RAIL|y final packag +12388|181289|6326|6|50|68514.00|0.10|0.00|N|O|1997-11-29|1997-12-10|1997-12-09|NONE|REG AIR|ding to the blit +12388|116171|8683|7|29|34427.93|0.08|0.08|N|O|1997-11-01|1998-01-07|1997-11-11|NONE|AIR|foxes. quickly i +12389|79233|4248|1|31|37579.13|0.06|0.06|R|F|1994-09-07|1994-09-30|1994-09-29|DELIVER IN PERSON|TRUCK|fily carefully even foxes. even de +12389|56151|1162|2|44|48714.60|0.02|0.03|A|F|1994-10-29|1994-10-22|1994-11-13|DELIVER IN PERSON|REG AIR|s? unusual, even instruction +12389|118764|8765|3|12|21393.12|0.07|0.04|R|F|1994-09-19|1994-10-18|1994-10-15|DELIVER IN PERSON|AIR|e special accounts. bl +12389|56692|6693|4|43|70893.67|0.10|0.03|A|F|1994-09-22|1994-09-20|1994-10-05|TAKE BACK RETURN|AIR|ts about the car +12389|6666|1667|5|20|31453.20|0.06|0.08|A|F|1994-10-04|1994-10-21|1994-10-06|NONE|TRUCK|s. special accounts wake blithely +12389|20906|5911|6|8|14615.20|0.01|0.02|R|F|1994-08-12|1994-10-06|1994-09-11|DELIVER IN PERSON|FOB|ic foxes. qui +12389|150745|746|7|19|34119.06|0.10|0.06|A|F|1994-10-14|1994-10-04|1994-10-15|TAKE BACK RETURN|MAIL|each carefully about the +12390|167594|2627|1|16|26585.44|0.03|0.02|N|O|1996-07-21|1996-08-04|1996-08-20|TAKE BACK RETURN|TRUCK|egular packages boost slyly slyly s +12390|139156|4183|2|8|9561.20|0.10|0.03|N|O|1996-07-20|1996-08-17|1996-08-17|DELIVER IN PERSON|REG AIR|sits. slyly ironic dependencies cajole furi +12390|185166|5167|3|9|11260.44|0.09|0.06|N|O|1996-06-30|1996-08-18|1996-07-17|TAKE BACK RETURN|FOB|ymptotes cajole slyly after the depo +12391|47912|5425|1|26|48357.66|0.05|0.05|N|O|1998-10-26|1998-09-23|1998-11-24|DELIVER IN PERSON|TRUCK|s doubt fluffily furiously ironic t +12391|46665|6666|2|45|72524.70|0.07|0.03|N|O|1998-08-15|1998-08-29|1998-08-22|NONE|SHIP|the final platelets +12416|60034|35|1|7|6958.21|0.10|0.05|R|F|1993-10-18|1993-09-01|1993-10-27|DELIVER IN PERSON|AIR|packages. slyly un +12417|45147|5148|1|25|27303.50|0.03|0.08|R|F|1993-11-23|1993-12-29|1993-12-11|NONE|AIR|unts haggl +12417|184243|9280|2|21|27872.04|0.02|0.01|A|F|1993-11-26|1994-01-11|1993-12-12|NONE|AIR|nal instructions use quick +12417|156646|1677|3|45|76618.80|0.08|0.00|R|F|1994-01-03|1994-01-07|1994-01-11|COLLECT COD|AIR|ts use carefully acc +12417|144074|4075|4|45|50313.15|0.01|0.06|A|F|1994-02-04|1993-11-25|1994-02-28|NONE|TRUCK|ly even reque +12417|49828|9829|5|24|42667.68|0.01|0.05|A|F|1993-11-03|1993-12-25|1993-11-18|NONE|REG AIR|ages. furiously iron +12418|192140|2141|1|7|8624.98|0.05|0.03|A|F|1992-05-20|1992-04-09|1992-06-09|COLLECT COD|RAIL|yly express idea +12418|86697|4222|2|5|8418.45|0.09|0.03|R|F|1992-04-14|1992-03-27|1992-05-07|COLLECT COD|RAIL|s affix quickly regular theodolite +12418|110812|3324|3|38|69266.78|0.05|0.04|A|F|1992-05-11|1992-03-28|1992-06-07|NONE|MAIL|lites above the daringl +12418|10259|260|4|34|39754.50|0.04|0.06|A|F|1992-06-05|1992-05-03|1992-06-19|DELIVER IN PERSON|MAIL|ecial requests run fluffily special de +12418|11852|4354|5|10|17638.50|0.10|0.05|A|F|1992-04-24|1992-05-03|1992-05-16|DELIVER IN PERSON|MAIL|dolites haggle carefully +12418|188904|8905|6|12|23914.80|0.08|0.08|A|F|1992-06-15|1992-05-12|1992-06-17|COLLECT COD|SHIP|ly bold pl +12419|90612|3122|1|26|41667.86|0.09|0.06|N|O|1995-11-28|1995-12-26|1995-12-01|COLLECT COD|REG AIR|quests. unusual request +12419|115094|5095|2|18|19963.62|0.02|0.07|N|O|1996-01-29|1995-12-20|1996-02-06|COLLECT COD|FOB|yly according +12419|174183|4184|3|44|55315.92|0.08|0.00|N|O|1995-10-31|1996-01-08|1995-11-02|NONE|TRUCK|regular accounts cajole +12419|81943|6960|4|42|80847.48|0.04|0.04|N|O|1996-02-09|1995-11-15|1996-02-19|TAKE BACK RETURN|REG AIR|oost evenly. slyly final accounts after +12419|4959|9960|5|24|44734.80|0.05|0.06|N|O|1996-01-25|1996-01-14|1996-02-05|COLLECT COD|RAIL| beans. final, regular accounts nag slyly +12419|143968|1511|6|19|38227.24|0.09|0.01|N|O|1995-11-30|1995-12-06|1995-12-20|COLLECT COD|FOB| instructions. care +12419|58777|1283|7|12|20829.24|0.00|0.04|N|O|1995-11-21|1995-11-18|1995-12-07|DELIVER IN PERSON|RAIL|gular courts. blithe +12420|64389|9402|1|39|52781.82|0.04|0.06|R|F|1994-04-06|1994-03-20|1994-04-25|NONE|AIR|pinto beans are sl +12420|177090|7091|2|22|25675.98|0.09|0.03|A|F|1994-03-31|1994-02-03|1994-04-05|NONE|SHIP|e furiously regular theodolites. fl +12420|135019|7533|3|5|5270.05|0.07|0.08|A|F|1994-01-16|1994-03-02|1994-02-01|NONE|REG AIR|excuses believe +12420|63396|8409|4|7|9515.73|0.10|0.08|A|F|1994-02-18|1994-02-09|1994-02-22|COLLECT COD|TRUCK|y. blithely even deposits haggl +12420|95147|7657|5|30|34264.20|0.02|0.03|R|F|1994-01-12|1994-02-26|1994-02-06|DELIVER IN PERSON|RAIL|ular deposits boost carefully. quickly +12420|134518|9545|6|9|13972.59|0.08|0.03|A|F|1994-02-12|1994-02-12|1994-02-18|DELIVER IN PERSON|FOB| express packages unwind quickly slyly unus +12421|29162|9163|1|37|40372.92|0.05|0.01|N|O|1996-02-26|1995-12-15|1996-03-22|COLLECT COD|REG AIR|ithely final dolphins sleep afte +12421|117245|4779|2|24|30293.76|0.00|0.03|N|O|1995-12-25|1995-12-20|1996-01-06|DELIVER IN PERSON|SHIP|ithely regular acc +12421|130483|8023|3|43|65079.64|0.04|0.08|N|O|1995-11-09|1996-01-26|1995-11-20|TAKE BACK RETURN|REG AIR| carefully expr +12421|13296|5798|4|6|7255.74|0.09|0.08|N|O|1995-12-04|1996-01-05|1995-12-20|DELIVER IN PERSON|MAIL|pending excuses. express ideas detect +12421|50463|2969|5|43|60778.78|0.07|0.00|N|O|1996-02-20|1996-01-08|1996-03-06|TAKE BACK RETURN|FOB|ages. blit +12421|116678|6679|6|27|45756.09|0.10|0.05|N|O|1996-01-13|1996-01-10|1996-01-18|NONE|TRUCK|s. quickly pend +12422|8183|3184|1|33|36008.94|0.08|0.05|N|O|1995-08-01|1995-08-11|1995-08-24|COLLECT COD|FOB|ts detect against the furiously brave sh +12422|130300|301|2|21|27936.30|0.05|0.08|N|O|1995-07-08|1995-07-24|1995-07-19|COLLECT COD|MAIL|ole. slyly regu +12422|148331|846|3|14|19310.62|0.02|0.00|N|F|1995-06-06|1995-08-09|1995-06-28|NONE|REG AIR|egular foxes. carefully regular +12422|195562|5563|4|46|76247.76|0.09|0.08|N|O|1995-09-20|1995-06-26|1995-10-07|TAKE BACK RETURN|REG AIR|ag blithely +12422|9279|9280|5|16|19012.32|0.02|0.03|N|O|1995-06-19|1995-07-01|1995-06-27|DELIVER IN PERSON|TRUCK|ding to the ideas could use blithely fluf +12422|149617|4646|6|29|48331.69|0.02|0.03|N|F|1995-06-16|1995-07-10|1995-06-24|DELIVER IN PERSON|FOB| bold sentimen +12423|89959|2468|1|2|3897.90|0.08|0.02|R|F|1992-09-05|1992-09-09|1992-09-14|COLLECT COD|RAIL|the fluffily daring pinto beans +12423|126320|3857|2|26|35004.32|0.04|0.05|R|F|1992-08-07|1992-10-01|1992-08-11|COLLECT COD|MAIL|uickly ironic theodolites affix. i +12423|59370|6886|3|38|50516.06|0.05|0.05|R|F|1992-10-09|1992-08-20|1992-10-29|COLLECT COD|SHIP|ggedly unusual theodolites. dogged +12448|111283|8817|1|16|20708.48|0.06|0.02|N|O|1996-03-01|1996-01-19|1996-03-06|DELIVER IN PERSON|TRUCK|ic requests; foxes detect s +12448|122530|2531|2|17|26393.01|0.05|0.05|N|O|1996-03-05|1995-12-31|1996-04-02|COLLECT COD|TRUCK|e carefully deposits. furiously idle +12448|158758|6304|3|42|76303.50|0.03|0.06|N|O|1996-01-24|1995-12-15|1996-02-10|NONE|FOB|ependencies? reg +12448|35116|123|4|24|25226.64|0.01|0.05|N|O|1996-02-12|1996-01-05|1996-02-26|COLLECT COD|SHIP|uests haggle s +12448|179805|9806|5|17|32041.60|0.07|0.05|N|O|1995-11-24|1996-01-30|1995-12-09|DELIVER IN PERSON|MAIL|foxes above the blithely sl +12449|152105|7136|1|45|52069.50|0.02|0.03|A|F|1993-04-08|1993-03-28|1993-04-10|TAKE BACK RETURN|REG AIR|furiously pending accounts +12449|17944|446|2|45|83787.30|0.09|0.02|A|F|1993-02-06|1993-04-26|1993-02-24|COLLECT COD|TRUCK|packages. carefully final deposits accor +12449|168146|3179|3|16|19426.24|0.06|0.00|A|F|1993-02-04|1993-04-27|1993-03-06|COLLECT COD|RAIL|carefully always final foxe +12450|109032|9033|1|40|41641.20|0.01|0.06|R|F|1994-03-31|1994-06-09|1994-04-07|TAKE BACK RETURN|SHIP|efully ironic p +12451|30996|8506|1|49|94422.51|0.07|0.06|R|F|1993-06-27|1993-07-05|1993-06-28|NONE|FOB|arefully even excuses wake fi +12451|142947|7976|2|29|57708.26|0.04|0.06|A|F|1993-06-24|1993-07-11|1993-07-17|NONE|MAIL|pending platelets wake furiously accordin +12451|100951|5972|3|19|37087.05|0.02|0.02|R|F|1993-06-04|1993-05-23|1993-06-15|NONE|MAIL|quests about +12451|82372|2373|4|49|66364.13|0.02|0.08|A|F|1993-05-08|1993-07-14|1993-05-26|COLLECT COD|REG AIR|wake carefull +12451|24309|1816|5|20|24666.00|0.09|0.05|R|F|1993-06-27|1993-05-29|1993-07-22|DELIVER IN PERSON|TRUCK|the furiously ironic packages? +12451|156032|3578|6|28|30464.84|0.00|0.00|A|F|1993-06-13|1993-07-13|1993-07-04|DELIVER IN PERSON|MAIL|fully even foxes wake. special, final acco +12451|27699|7700|7|26|42293.94|0.00|0.03|R|F|1993-07-01|1993-06-30|1993-07-27|DELIVER IN PERSON|RAIL|ions: ironic packages eat +12452|125160|185|1|14|16592.24|0.08|0.01|R|F|1994-03-29|1994-01-17|1994-04-10|NONE|MAIL|es. carefully regular r +12452|161354|1355|2|31|43875.85|0.10|0.07|R|F|1994-01-04|1994-01-15|1994-01-16|NONE|RAIL|g instructions. furious, bra +12452|71689|9211|3|31|51481.08|0.09|0.07|A|F|1994-01-14|1994-02-09|1994-01-31|NONE|MAIL|jole. special, +12452|61542|9061|4|44|66155.76|0.10|0.07|A|F|1994-03-29|1994-01-10|1994-04-14|DELIVER IN PERSON|TRUCK|osits. deposits sleep fluffi +12453|178720|8721|1|33|59357.76|0.03|0.06|R|F|1994-03-26|1994-03-08|1994-04-06|TAKE BACK RETURN|RAIL|y ironic deposits sleep furiously pen +12453|139962|2476|2|20|40039.20|0.00|0.03|R|F|1994-04-04|1994-03-08|1994-04-05|COLLECT COD|MAIL|r the ruthlessly regular +12453|139578|7118|3|26|42056.82|0.08|0.05|R|F|1994-01-20|1994-04-07|1994-01-22|DELIVER IN PERSON|TRUCK|ges kindle after the final, unusual pinto +12453|83273|3274|4|1|1256.27|0.10|0.05|R|F|1994-04-20|1994-04-07|1994-04-26|NONE|REG AIR|y above the fluffily special foxes. f +12453|158324|840|5|28|38704.96|0.07|0.01|R|F|1994-05-09|1994-02-19|1994-06-06|NONE|SHIP|oxes grow past the carefully regular pint +12453|139258|4285|6|17|22053.25|0.01|0.08|A|F|1994-02-12|1994-03-04|1994-03-07|DELIVER IN PERSON|MAIL|the carefully final pinto +12454|116913|9425|1|39|75266.49|0.05|0.07|N|O|1997-04-01|1997-05-23|1997-04-25|DELIVER IN PERSON|AIR|ts integrate carefully about +12455|199506|7064|1|37|59403.50|0.10|0.07|A|F|1992-12-14|1992-10-29|1992-12-28|TAKE BACK RETURN|MAIL|refully alo +12455|86374|1391|2|10|13603.70|0.09|0.01|A|F|1992-10-05|1992-11-26|1992-10-11|NONE|RAIL|s. ironic foxes are +12455|79628|7150|3|45|72342.90|0.05|0.06|R|F|1992-12-21|1992-11-06|1992-12-22|NONE|AIR|deposits. quickly even foxes wake quic +12455|99414|9415|4|29|40988.89|0.09|0.06|A|F|1992-11-23|1992-11-21|1992-11-24|DELIVER IN PERSON|AIR|l escapades. quickly ex +12455|44704|2217|5|2|3297.40|0.01|0.03|A|F|1992-09-30|1992-10-28|1992-10-05|DELIVER IN PERSON|REG AIR|xpress packages cajole. quickly +12480|61252|8771|1|30|36397.50|0.05|0.02|A|F|1994-09-11|1994-09-10|1994-09-17|COLLECT COD|RAIL| the quickly regular ideas. +12480|52044|9560|2|22|21912.88|0.06|0.08|R|F|1994-07-31|1994-08-26|1994-08-12|NONE|RAIL|posits. slyly fluffy dolphins are regular, +12480|86811|6812|3|26|46743.06|0.02|0.03|R|F|1994-11-05|1994-09-16|1994-11-06|COLLECT COD|TRUCK|ide the slyly +12481|85187|2712|1|14|16410.52|0.02|0.00|N|O|1995-11-05|1995-08-18|1995-11-20|TAKE BACK RETURN|AIR|ss packages cajole. ironic, regul +12481|129097|9098|2|23|25900.07|0.04|0.03|N|O|1995-09-22|1995-09-15|1995-09-27|NONE|TRUCK|ely against the foxes. +12481|120149|150|3|23|26890.22|0.09|0.04|N|O|1995-08-10|1995-08-15|1995-09-07|COLLECT COD|RAIL|s snooze. carefully express accounts ha +12481|129110|4135|4|9|10251.99|0.08|0.08|N|O|1995-07-31|1995-10-05|1995-08-17|DELIVER IN PERSON|TRUCK|jole furiously. slowly unusual ac +12482|16751|1754|1|10|16677.50|0.03|0.05|N|O|1996-02-19|1996-03-05|1996-03-09|DELIVER IN PERSON|RAIL|ckly silent notornis sleep sl +12482|117405|9917|2|40|56896.00|0.05|0.06|N|O|1996-04-10|1996-03-09|1996-04-22|NONE|TRUCK|ns. fluffily regular somas against the blit +12482|13722|3723|3|50|81786.00|0.10|0.02|N|O|1996-05-04|1996-03-04|1996-05-28|COLLECT COD|TRUCK|ayers wake quickly quickly +12482|17809|5313|4|8|13814.40|0.07|0.02|N|O|1996-03-18|1996-04-06|1996-04-16|COLLECT COD|MAIL|r pinto beans +12482|112756|2757|5|45|79593.75|0.10|0.04|N|O|1996-01-11|1996-02-10|1996-02-10|NONE|TRUCK|: special packages above the furiously +12483|89379|1888|1|22|30104.14|0.07|0.08|R|F|1993-10-31|1993-10-27|1993-11-02|NONE|TRUCK|blithely. epitaphs boost c +12483|188791|1310|2|28|52634.12|0.10|0.06|R|F|1993-11-19|1993-10-07|1993-11-23|DELIVER IN PERSON|REG AIR|. slyly even theodolites boost. carefull +12483|1051|8552|3|29|27609.45|0.07|0.00|R|F|1993-08-22|1993-09-22|1993-09-04|NONE|REG AIR|ng packages affix deposi +12483|51118|6129|4|28|29935.08|0.01|0.04|R|F|1993-10-28|1993-09-23|1993-11-10|COLLECT COD|RAIL|y bold requests ca +12483|129881|2394|5|1|1910.88|0.05|0.01|R|F|1993-08-12|1993-09-11|1993-08-27|TAKE BACK RETURN|MAIL|lyly regular packages. slyly r +12484|35012|7516|1|34|32198.34|0.06|0.02|N|O|1995-09-28|1995-11-06|1995-10-19|COLLECT COD|TRUCK|quickly even dependenci +12484|36126|3636|2|30|31863.60|0.10|0.00|N|O|1995-12-12|1995-10-13|1995-12-25|COLLECT COD|SHIP|ly unusual accounts boost furiously ac +12484|167098|2131|3|26|30292.34|0.01|0.01|N|O|1995-09-29|1995-10-09|1995-10-28|NONE|REG AIR|have to wake blithely: ironically ironic +12484|7451|2452|4|1|1358.45|0.04|0.07|N|O|1995-11-15|1995-11-16|1995-12-02|DELIVER IN PERSON|REG AIR|s mold blithely boldly express theodolit +12484|12503|7506|5|50|70775.00|0.01|0.00|N|O|1995-09-19|1995-10-16|1995-09-30|TAKE BACK RETURN|RAIL|after the pending deposits. ex +12484|128177|3202|6|14|16872.38|0.07|0.08|N|O|1995-12-07|1995-10-27|1995-12-21|TAKE BACK RETURN|AIR|r theodolites about the unusual foxes belie +12485|105047|5048|1|41|43133.64|0.03|0.07|R|F|1993-11-14|1993-10-15|1993-11-30|COLLECT COD|RAIL|egular packages. car +12485|118929|1441|2|32|62333.44|0.01|0.07|R|F|1993-11-26|1993-09-10|1993-12-05|DELIVER IN PERSON|FOB|furiously special theodolites sl +12485|36100|1107|3|8|8288.80|0.08|0.01|R|F|1993-10-05|1993-10-23|1993-10-27|TAKE BACK RETURN|RAIL|hely regular instructions. +12485|121213|1214|4|28|34557.88|0.07|0.04|A|F|1993-11-17|1993-11-03|1993-12-07|TAKE BACK RETURN|MAIL|ges. deposits against the regu +12485|10277|2779|5|29|34430.83|0.05|0.03|A|F|1993-08-31|1993-09-09|1993-09-22|TAKE BACK RETURN|FOB|eposits haggle furiously. regula +12485|114966|7478|6|19|37638.24|0.10|0.08|A|F|1993-08-17|1993-09-07|1993-09-07|COLLECT COD|MAIL| packages. s +12485|21131|3634|7|43|45241.59|0.08|0.01|R|F|1993-09-12|1993-10-16|1993-09-30|COLLECT COD|FOB|lphins. instructions among the slyly s +12486|147042|7043|1|26|28315.04|0.09|0.04|A|F|1995-04-30|1995-04-11|1995-05-14|NONE|SHIP| carefully re +12486|118492|3515|2|19|28699.31|0.08|0.04|A|F|1995-06-01|1995-04-10|1995-06-07|DELIVER IN PERSON|MAIL|xpress asymptotes u +12486|83645|8662|3|15|24429.60|0.07|0.04|N|F|1995-06-07|1995-04-09|1995-06-22|TAKE BACK RETURN|SHIP|y idle deposits. furiously +12486|19677|7181|4|19|30336.73|0.06|0.04|N|O|1995-06-20|1995-05-13|1995-07-19|NONE|RAIL|ts nag. slyly reg +12486|110520|521|5|20|30610.40|0.10|0.05|N|F|1995-06-16|1995-05-08|1995-06-28|TAKE BACK RETURN|MAIL|riously special foxes sleep quickly. f +12486|99671|2181|6|4|6682.68|0.08|0.05|R|F|1995-03-05|1995-04-03|1995-03-07|DELIVER IN PERSON|TRUCK| slyly ironic pinto beans wake +12486|157907|7908|7|38|74666.20|0.01|0.05|N|F|1995-06-15|1995-04-17|1995-06-29|NONE|SHIP|s. carefully regular braids haggle sly +12487|127699|7700|1|34|58707.46|0.02|0.05|R|F|1995-02-07|1995-02-28|1995-02-27|TAKE BACK RETURN|FOB|endencies. unusual ideas nod carefully +12512|124769|4770|1|25|44844.00|0.03|0.08|N|O|1996-05-02|1996-05-17|1996-05-18|NONE|MAIL|the final, ruthless requests affix +12512|178374|3409|2|28|40666.36|0.10|0.01|N|O|1996-07-04|1996-05-06|1996-07-22|DELIVER IN PERSON|AIR| packages. regular accounts haggle fur +12512|128716|3741|3|27|47107.17|0.03|0.06|N|O|1996-07-22|1996-05-11|1996-07-25|NONE|RAIL|even, express requests. furiously +12513|25364|7867|1|31|39970.16|0.07|0.02|N|O|1997-11-18|1997-10-14|1997-12-18|NONE|TRUCK|gside of the re +12513|82619|144|2|2|3203.22|0.01|0.04|N|O|1997-09-13|1997-11-28|1997-09-24|TAKE BACK RETURN|REG AIR|ing notornis +12513|176470|8988|3|16|24743.52|0.09|0.01|N|O|1997-10-10|1997-10-10|1997-10-15|TAKE BACK RETURN|FOB|foxes. ironic, ironic accounts will +12514|139815|9816|1|22|40805.82|0.04|0.06|A|F|1994-08-23|1994-05-28|1994-09-02|COLLECT COD|TRUCK|cial foxes are blithel +12514|67596|2609|2|6|9381.54|0.01|0.00|R|F|1994-05-27|1994-07-07|1994-06-23|TAKE BACK RETURN|AIR|ily regular accounts poach according to th +12515|173285|5803|1|37|50256.36|0.00|0.05|A|F|1993-06-07|1993-07-28|1993-07-01|TAKE BACK RETURN|FOB|ages hang above the final requests. +12515|191017|3537|2|29|32132.29|0.07|0.07|A|F|1993-07-03|1993-07-17|1993-07-28|COLLECT COD|MAIL|fily pending package +12515|16180|1183|3|11|12057.98|0.02|0.07|A|F|1993-06-11|1993-07-23|1993-06-25|COLLECT COD|REG AIR|beans. quickly regular +12516|181548|1549|1|35|57033.90|0.09|0.03|R|F|1994-08-04|1994-08-13|1994-08-23|TAKE BACK RETURN|MAIL|refully final depo +12516|61814|9333|2|28|49722.68|0.03|0.04|R|F|1994-05-26|1994-07-10|1994-06-24|COLLECT COD|SHIP| about the quickly expres +12516|104249|4250|3|14|17545.36|0.05|0.08|R|F|1994-09-23|1994-07-18|1994-10-22|DELIVER IN PERSON|SHIP|e the slyly f +12517|54553|2069|1|21|31658.55|0.07|0.07|N|O|1997-03-27|1997-03-24|1997-04-01|COLLECT COD|RAIL|l dependencies hagg +12517|65294|307|2|17|21407.93|0.08|0.08|N|O|1997-02-22|1997-03-24|1997-03-21|COLLECT COD|REG AIR|ully even reque +12517|180291|292|3|17|23311.93|0.05|0.01|N|O|1997-04-18|1997-03-24|1997-04-26|NONE|SHIP|mong the deposits. +12518|63098|617|1|11|11671.99|0.08|0.03|A|F|1993-10-25|1993-09-09|1993-10-31|TAKE BACK RETURN|TRUCK|l frays along the bold, bol +12518|75289|7797|2|19|24021.32|0.08|0.00|A|F|1993-11-03|1993-09-25|1993-11-16|COLLECT COD|MAIL| asymptotes cajole unusual req +12518|176283|3835|3|21|28544.88|0.09|0.07|A|F|1993-09-13|1993-10-12|1993-10-13|NONE|RAIL|t according to th +12518|171760|6795|4|7|12822.32|0.05|0.02|A|F|1993-09-16|1993-10-03|1993-09-17|DELIVER IN PERSON|TRUCK|st the even foxes. requests haggle blithe +12518|166866|9383|5|6|11597.16|0.05|0.00|A|F|1993-07-27|1993-10-21|1993-08-21|DELIVER IN PERSON|TRUCK|ular depos +12518|106314|1335|6|3|3960.93|0.03|0.00|R|F|1993-08-12|1993-10-19|1993-08-13|TAKE BACK RETURN|TRUCK|quiet, silent packages sleep quickly +12518|7702|7703|7|50|80485.00|0.00|0.07|A|F|1993-10-10|1993-08-22|1993-10-11|NONE|MAIL|ets wake slyly. theodolites cajole fluffi +12519|45913|8418|1|23|42754.93|0.08|0.02|R|F|1994-04-30|1994-03-15|1994-05-04|DELIVER IN PERSON|SHIP|ly. pending instr +12519|48696|6209|2|47|77300.43|0.05|0.02|A|F|1994-03-08|1994-03-01|1994-04-04|DELIVER IN PERSON|SHIP|e across the fluffily regular packages. +12519|28226|729|3|26|30009.72|0.08|0.00|R|F|1994-01-11|1994-02-28|1994-02-04|DELIVER IN PERSON|AIR|g the blithely special accou +12519|191537|4057|4|4|6514.12|0.07|0.04|A|F|1994-04-19|1994-03-21|1994-05-04|NONE|RAIL|wake slyly express requests. fur +12519|148475|6018|5|20|30469.40|0.03|0.02|A|F|1994-02-17|1994-02-02|1994-02-24|DELIVER IN PERSON|MAIL|sh regular, ironic +12519|7123|2124|6|36|37084.32|0.09|0.01|A|F|1994-02-25|1994-02-20|1994-03-20|NONE|MAIL|, quiet accounts are al +12544|133239|3240|1|25|31805.75|0.04|0.05|A|F|1994-05-22|1994-04-24|1994-06-01|NONE|FOB| ironic accounts +12544|145485|514|2|24|36731.52|0.04|0.02|R|F|1994-04-07|1994-05-09|1994-04-14|COLLECT COD|TRUCK|furiously according to the theodolites. +12545|174994|4995|1|4|8275.96|0.03|0.06|N|O|1996-07-19|1996-09-13|1996-08-01|DELIVER IN PERSON|RAIL|unusual ide +12545|115389|412|2|42|58983.96|0.07|0.04|N|O|1996-08-31|1996-08-09|1996-09-09|COLLECT COD|SHIP|as are carefully ironic pinto beans. qui +12545|132374|2375|3|20|28127.40|0.10|0.07|N|O|1996-07-08|1996-09-02|1996-07-21|COLLECT COD|SHIP| packages engage carefully according +12545|1331|6332|4|1|1232.33|0.00|0.08|N|O|1996-07-18|1996-09-16|1996-07-21|NONE|SHIP|carefully bol +12546|120156|2669|1|4|4704.60|0.00|0.03|N|O|1996-03-30|1996-04-19|1996-04-17|DELIVER IN PERSON|FOB|y unusual foxes h +12546|61123|6136|2|5|5420.60|0.06|0.07|N|O|1996-05-05|1996-03-30|1996-05-21|TAKE BACK RETURN|FOB|. furiously express Tiresias sleep +12546|90136|5155|3|28|31531.64|0.01|0.03|N|O|1996-03-13|1996-04-27|1996-03-29|COLLECT COD|TRUCK|eposits; carefully ironic requ +12546|103748|3749|4|25|43793.50|0.06|0.01|N|O|1996-02-23|1996-03-28|1996-02-24|NONE|TRUCK|ously ironic deposi +12546|90417|418|5|2|2814.82|0.06|0.01|N|O|1996-03-15|1996-03-18|1996-03-18|DELIVER IN PERSON|TRUCK|refully final ideas caj +12547|152899|2900|1|50|97594.50|0.07|0.05|N|O|1998-08-04|1998-06-23|1998-08-07|DELIVER IN PERSON|FOB|hely unusual deposits cajo +12547|172081|2082|2|46|53041.68|0.00|0.02|N|O|1998-06-04|1998-05-19|1998-06-20|NONE|AIR|ly regular requests +12547|148670|1185|3|1|1718.67|0.09|0.06|N|O|1998-04-16|1998-07-11|1998-04-22|TAKE BACK RETURN|RAIL|about the quickly regular fret +12547|92638|7657|4|32|52180.16|0.03|0.02|N|O|1998-07-08|1998-06-24|1998-08-03|DELIVER IN PERSON|SHIP|yly. furiously reg +12548|156497|4043|1|27|41944.23|0.03|0.08|N|O|1998-01-19|1998-01-29|1998-01-26|TAKE BACK RETURN|FOB|he furious +12548|31285|1286|2|31|37704.68|0.10|0.07|N|O|1997-12-13|1998-02-08|1997-12-25|COLLECT COD|TRUCK|ys dogged deposits. carefully ironic depen +12548|6802|1803|3|23|39302.40|0.03|0.01|N|O|1997-12-15|1998-02-16|1997-12-18|DELIVER IN PERSON|MAIL|nstructions are furiousl +12548|116456|6457|4|41|60370.45|0.03|0.05|N|O|1998-03-19|1997-12-31|1998-04-12|DELIVER IN PERSON|AIR|riously final instructions use qui +12548|73078|5586|5|40|42042.80|0.05|0.06|N|O|1997-12-29|1998-01-29|1998-01-01|TAKE BACK RETURN|TRUCK|nic platelets solv +12549|37018|9522|1|13|12415.13|0.05|0.03|N|O|1997-08-07|1997-07-12|1997-08-08|NONE|RAIL|. carefully ironic theodo +12549|152208|9754|2|33|41586.60|0.05|0.01|N|O|1997-07-05|1997-08-20|1997-07-22|NONE|AIR|requests. furiously even accounts n +12549|152719|7750|3|28|49607.88|0.04|0.02|N|O|1997-07-09|1997-07-06|1997-07-21|NONE|RAIL|oxes haggle against the qui +12550|10372|5375|1|3|3847.11|0.01|0.06|R|F|1993-03-17|1993-05-22|1993-04-03|DELIVER IN PERSON|RAIL|accounts. furiously bold ac +12550|115164|187|2|35|41270.60|0.08|0.07|R|F|1993-05-17|1993-05-23|1993-06-09|TAKE BACK RETURN|MAIL| accounts. furiously regular p +12551|165658|8175|1|30|51709.50|0.01|0.02|A|F|1992-07-31|1992-09-10|1992-08-20|DELIVER IN PERSON|RAIL|equests. carefu +12551|8957|6458|2|26|48514.70|0.04|0.08|R|F|1992-10-11|1992-07-15|1992-10-13|TAKE BACK RETURN|TRUCK|fully special accou +12551|131355|8895|3|25|34658.75|0.07|0.00|A|F|1992-08-26|1992-08-21|1992-09-05|DELIVER IN PERSON|MAIL|he blithely final acc +12551|80466|7991|4|47|67983.62|0.08|0.01|R|F|1992-07-13|1992-07-31|1992-07-30|NONE|TRUCK|kly unusual instructio +12576|131014|8554|1|28|29260.28|0.03|0.03|R|F|1993-04-02|1993-04-10|1993-04-17|DELIVER IN PERSON|RAIL|ll have to are sly +12577|145893|3436|1|8|15511.12|0.06|0.04|N|O|1998-06-09|1998-07-29|1998-06-28|TAKE BACK RETURN|SHIP|egular depo +12577|17282|2285|2|17|20387.76|0.05|0.07|N|O|1998-06-04|1998-08-06|1998-06-06|DELIVER IN PERSON|AIR|refully ironic requests. fin +12577|42203|4708|3|49|56114.80|0.00|0.06|N|O|1998-06-14|1998-06-30|1998-06-21|NONE|FOB|ickly silent waters cajole furiously a +12577|104124|9145|4|43|48509.16|0.10|0.01|N|O|1998-07-15|1998-07-09|1998-08-09|TAKE BACK RETURN|AIR|ily carefully unusual request +12578|186626|6627|1|32|54803.84|0.01|0.04|N|O|1996-12-16|1997-01-28|1996-12-27|TAKE BACK RETURN|AIR|lyly express pinto +12578|8071|3072|2|21|20560.47|0.05|0.03|N|O|1997-01-18|1997-02-03|1997-01-21|COLLECT COD|SHIP|ncies lose. requests after the furiously b +12578|32899|7906|3|49|89762.61|0.09|0.07|N|O|1997-02-03|1997-01-18|1997-02-28|DELIVER IN PERSON|MAIL|y express foxes +12578|121587|1588|4|11|17694.38|0.08|0.04|N|O|1996-12-07|1997-01-01|1997-01-04|TAKE BACK RETURN|FOB|le after th +12578|108065|8066|5|17|18242.02|0.01|0.06|N|O|1996-12-20|1997-01-18|1996-12-24|DELIVER IN PERSON|FOB|ronic accounts sublate. final requests wak +12578|47246|9751|6|17|20285.08|0.07|0.06|N|O|1997-03-16|1996-12-28|1997-04-01|DELIVER IN PERSON|FOB|ts. furiously permanent excuses +12578|58880|8881|7|47|86427.36|0.06|0.00|N|O|1997-03-05|1996-12-30|1997-03-25|TAKE BACK RETURN|FOB|ccounts boost quickly final, pending req +12579|187859|2896|1|26|50618.10|0.02|0.04|N|O|1995-07-08|1995-08-31|1995-07-26|NONE|TRUCK|at the carefully silent ideas. ironic, +12580|831|3332|1|32|55418.56|0.10|0.07|R|F|1993-04-05|1993-02-28|1993-05-05|COLLECT COD|REG AIR|s affix. carefully +12580|152523|7554|2|10|15755.20|0.03|0.00|A|F|1993-04-22|1993-03-29|1993-05-08|DELIVER IN PERSON|MAIL| haggle carefully quickly ironic d +12581|165914|947|1|37|73256.67|0.06|0.03|A|F|1994-11-11|1994-12-03|1994-12-06|NONE|SHIP|y regular foxes. special +12581|104915|2446|2|25|47997.75|0.04|0.07|A|F|1994-12-08|1994-12-06|1995-01-03|DELIVER IN PERSON|FOB|uriously express dep +12581|101877|6898|3|28|52608.36|0.01|0.02|R|F|1994-11-13|1994-12-23|1994-11-22|COLLECT COD|TRUCK|oss the quickly +12582|106620|1641|1|23|37412.26|0.06|0.08|A|F|1993-03-21|1993-04-08|1993-04-08|TAKE BACK RETURN|AIR|refully regular reque +12583|60853|8372|1|30|54415.50|0.09|0.04|N|O|1996-02-10|1996-03-27|1996-02-23|DELIVER IN PERSON|AIR|ial, regular plate +12608|61390|1391|1|4|5405.56|0.10|0.04|R|F|1993-06-16|1993-04-09|1993-07-08|NONE|TRUCK|ironic accounts sleep along the quickly +12608|181421|1422|2|7|10516.94|0.08|0.01|R|F|1993-06-22|1993-06-04|1993-07-02|TAKE BACK RETURN|AIR|side of the u +12608|141771|6800|3|36|65259.72|0.06|0.01|A|F|1993-05-04|1993-05-26|1993-05-30|COLLECT COD|MAIL|nic realms. sly +12609|68400|3413|1|31|42420.40|0.03|0.06|N|O|1996-02-08|1996-04-01|1996-02-24|DELIVER IN PERSON|MAIL|en pinto beans haggle furiously according +12609|192508|5028|2|15|24007.50|0.08|0.02|N|O|1996-04-29|1996-03-25|1996-05-24|COLLECT COD|TRUCK|ously unusual platelets. carefully +12609|68011|8012|3|24|23496.24|0.04|0.01|N|O|1996-05-15|1996-03-25|1996-06-13|COLLECT COD|MAIL|ructions. carefully bold asy +12609|45114|123|4|11|11650.21|0.01|0.02|N|O|1996-05-15|1996-03-21|1996-06-06|COLLECT COD|TRUCK|nal ideas along th +12610|183151|3152|1|6|7404.90|0.07|0.04|A|F|1993-09-26|1993-09-13|1993-10-16|NONE|TRUCK| final, bold platele +12611|74929|9944|1|26|49501.92|0.04|0.07|N|O|1995-11-08|1995-12-06|1995-11-17|TAKE BACK RETURN|RAIL|ieve carefully along t +12611|124716|9741|2|35|60924.85|0.05|0.04|N|O|1995-12-06|1995-12-24|1995-12-28|COLLECT COD|TRUCK|uses across the express, express accoun +12611|97217|7218|3|3|3642.63|0.00|0.02|N|O|1996-01-20|1995-12-14|1996-01-26|NONE|RAIL|lyly ironic accounts wake slyly special ins +12611|125917|8430|4|48|93259.68|0.06|0.03|N|O|1996-01-07|1995-12-26|1996-01-12|NONE|MAIL|al requests should +12611|73837|6345|5|25|45270.75|0.01|0.04|N|O|1995-11-22|1995-12-25|1995-11-27|COLLECT COD|TRUCK|l requests cajole stealthy asymptotes-- re +12612|43599|6104|1|25|38564.75|0.04|0.08|R|F|1994-02-17|1994-02-07|1994-03-11|COLLECT COD|FOB|e blithely silent platelets are quickly +12612|156705|9221|2|36|63421.20|0.06|0.08|A|F|1994-02-27|1994-01-24|1994-03-18|DELIVER IN PERSON|MAIL|riously regular requ +12612|126104|3641|3|45|50854.50|0.01|0.03|R|F|1994-03-14|1994-03-01|1994-04-04|COLLECT COD|AIR|arefully bold instructions caj +12612|16871|6872|4|15|26818.05|0.01|0.08|A|F|1994-01-18|1994-02-05|1994-02-09|NONE|FOB|ly among the furiously pending theodo +12612|139451|4478|5|4|5961.80|0.06|0.01|R|F|1994-04-11|1994-01-21|1994-04-12|COLLECT COD|SHIP|nal excuses boost fur +12612|137588|102|6|17|27634.86|0.06|0.06|A|F|1994-01-27|1994-02-06|1994-01-31|DELIVER IN PERSON|RAIL|slyly regular requests. special +12613|28520|6027|1|17|24624.84|0.10|0.04|A|F|1993-04-18|1993-06-04|1993-05-06|DELIVER IN PERSON|REG AIR|ic theodolites around the slyly even pac +12613|128121|5658|2|9|10342.08|0.03|0.07|A|F|1993-04-20|1993-05-26|1993-05-15|COLLECT COD|TRUCK|ajole blithely even p +12613|118337|8338|3|9|12197.97|0.06|0.02|R|F|1993-04-16|1993-07-03|1993-05-12|COLLECT COD|RAIL|s sleep careful +12613|86967|1984|4|35|68388.60|0.04|0.06|R|F|1993-04-24|1993-05-18|1993-04-27|NONE|TRUCK|osits wake blithely slyly u +12613|49408|1913|5|11|14931.40|0.10|0.01|R|F|1993-08-01|1993-07-07|1993-08-06|NONE|AIR|iously above the blithely iro +12614|153828|6344|1|25|47045.50|0.02|0.05|N|O|1996-05-16|1996-05-25|1996-06-03|NONE|FOB|s. ironic, even packages should h +12614|178895|8896|2|18|35530.02|0.08|0.07|N|O|1996-04-27|1996-04-12|1996-05-08|TAKE BACK RETURN|FOB|s by the idly ironic instru +12614|87523|5048|3|39|58910.28|0.10|0.06|N|O|1996-03-07|1996-04-20|1996-03-28|NONE|RAIL|ccounts across the blithely bol +12614|196119|3677|4|35|42528.85|0.01|0.01|N|O|1996-05-30|1996-05-27|1996-06-14|DELIVER IN PERSON|REG AIR| players haggle. special dinos sleep +12614|155234|7750|5|46|59304.58|0.03|0.00|N|O|1996-04-19|1996-04-25|1996-05-19|NONE|RAIL|out the furiously special re +12614|4089|6590|6|11|10923.88|0.09|0.04|N|O|1996-06-09|1996-04-15|1996-06-20|DELIVER IN PERSON|FOB|instructions. regular packages sleep ac +12615|140527|528|1|16|25080.32|0.05|0.05|A|F|1995-04-19|1995-05-18|1995-05-04|COLLECT COD|TRUCK|ously final packages d +12640|195843|882|1|21|40715.64|0.01|0.03|N|O|1998-07-31|1998-09-05|1998-08-05|NONE|TRUCK|uriously ironic deposit +12640|120115|116|2|33|37458.63|0.02|0.03|N|O|1998-09-26|1998-10-14|1998-10-24|NONE|RAIL|carefully quick platelets. +12641|35087|94|1|33|33728.64|0.03|0.05|A|F|1995-05-01|1995-05-14|1995-05-29|TAKE BACK RETURN|AIR|d instructions cajole sl +12641|94963|9982|2|7|13705.72|0.04|0.03|A|F|1995-04-30|1995-04-18|1995-05-24|COLLECT COD|MAIL|deposits haggle bold, +12641|41555|9068|3|24|35917.20|0.03|0.05|R|F|1995-04-01|1995-04-17|1995-04-04|DELIVER IN PERSON|FOB|luffily reg +12641|198862|1382|4|3|5882.58|0.07|0.03|R|F|1995-02-26|1995-05-06|1995-03-19|COLLECT COD|REG AIR|o the fluffil +12641|68162|3175|5|39|44076.24|0.04|0.03|A|F|1995-04-14|1995-03-28|1995-05-11|COLLECT COD|TRUCK|encies. reg +12641|194139|1697|6|46|56723.98|0.06|0.08|N|F|1995-06-17|1995-04-10|1995-07-11|TAKE BACK RETURN|SHIP| platelets. courts thras +12642|24569|7072|1|40|59742.40|0.04|0.01|R|F|1994-07-08|1994-07-03|1994-07-15|COLLECT COD|AIR|y. furiously quick pack +12642|121633|4146|2|13|21510.19|0.08|0.08|A|F|1994-08-23|1994-05-28|1994-09-20|TAKE BACK RETURN|SHIP| pending packages cajole slyly i +12642|74074|1596|3|1|1048.07|0.07|0.01|R|F|1994-06-01|1994-07-01|1994-06-11|COLLECT COD|RAIL|ts. regular, expr +12642|160876|877|4|37|71664.19|0.00|0.05|R|F|1994-07-07|1994-07-25|1994-07-19|DELIVER IN PERSON|RAIL|o beans boost furiously against the pint +12642|32032|9542|5|20|19280.60|0.01|0.04|R|F|1994-06-12|1994-05-29|1994-07-04|DELIVER IN PERSON|MAIL|. dependenci +12642|152981|8012|6|26|52883.48|0.03|0.07|A|F|1994-08-08|1994-07-13|1994-08-27|COLLECT COD|AIR|e the final pinto beans. packages hag +12642|140806|3321|7|50|92340.00|0.04|0.03|A|F|1994-06-09|1994-06-15|1994-06-17|COLLECT COD|RAIL|ckages. sile +12643|118903|8904|1|25|48047.50|0.03|0.00|A|F|1993-05-25|1993-06-13|1993-06-10|DELIVER IN PERSON|REG AIR|e carefully +12643|187258|4813|2|40|53810.00|0.09|0.06|R|F|1993-07-13|1993-05-04|1993-07-27|COLLECT COD|TRUCK|kages cajole blithely sly +12643|29063|4068|3|25|24801.50|0.07|0.06|R|F|1993-04-15|1993-04-26|1993-05-09|TAKE BACK RETURN|MAIL| requests. express p +12644|109752|7283|1|19|33473.25|0.09|0.04|A|F|1992-02-07|1992-03-31|1992-02-24|DELIVER IN PERSON|AIR|r furiously final packa +12644|192133|4653|2|39|47780.07|0.01|0.05|R|F|1992-04-21|1992-03-27|1992-04-30|COLLECT COD|FOB|t quickly after the ironic, final asymptote +12644|170803|8355|3|32|59961.60|0.06|0.05|A|F|1992-02-25|1992-04-07|1992-03-08|DELIVER IN PERSON|RAIL|osits detect against the quickly ironic +12644|72938|2939|4|5|9554.65|0.03|0.00|A|F|1992-04-23|1992-04-23|1992-04-25|COLLECT COD|FOB|ts boost at the ironic br +12645|112611|5123|1|17|27601.37|0.01|0.00|A|F|1994-08-25|1994-08-13|1994-09-20|COLLECT COD|RAIL|iet, bold requests wake. care +12645|44527|7032|2|34|50031.68|0.03|0.06|R|F|1994-09-07|1994-08-27|1994-09-12|DELIVER IN PERSON|RAIL|es dazzle carefully. quick, unusual p +12645|150594|8140|3|32|52626.88|0.10|0.02|A|F|1994-09-21|1994-08-06|1994-09-24|NONE|FOB|sly along the regular deposits. even, +12645|17146|2149|4|11|11694.54|0.01|0.06|A|F|1994-07-12|1994-09-20|1994-07-23|NONE|AIR|. blithely special theodolites according t +12645|162601|7634|5|50|83180.00|0.09|0.00|A|F|1994-11-01|1994-09-14|1994-11-16|DELIVER IN PERSON|MAIL|inal requests impress fluffily slyly ir +12645|29495|7002|6|8|11395.92|0.03|0.01|R|F|1994-10-08|1994-09-25|1994-10-27|TAKE BACK RETURN|AIR|bout the furiously regular depos +12645|122447|9984|7|32|47022.08|0.07|0.03|R|F|1994-10-20|1994-09-04|1994-11-19|TAKE BACK RETURN|AIR|theodolites slee +12646|157739|255|1|35|62885.55|0.07|0.06|A|F|1993-05-20|1993-04-08|1993-05-22|DELIVER IN PERSON|FOB|l requests. bold, bold instructions a +12646|113662|8685|2|29|48594.14|0.06|0.03|A|F|1993-03-02|1993-05-08|1993-03-15|COLLECT COD|TRUCK|nstructions. quickly express requ +12646|106505|6506|3|40|60460.00|0.05|0.00|R|F|1993-05-16|1993-04-07|1993-05-19|DELIVER IN PERSON|TRUCK|pinto beans sol +12647|30132|5139|1|32|33988.16|0.07|0.07|N|O|1997-06-02|1997-05-15|1997-06-10|NONE|RAIL|thely bold requests. ironic, even cour +12672|171515|6550|1|6|9519.06|0.01|0.05|R|F|1994-09-14|1994-08-30|1994-09-17|DELIVER IN PERSON|FOB|y ironic ideas. evenly special orbits int +12672|45406|2919|2|20|27028.00|0.02|0.02|A|F|1994-08-09|1994-08-16|1994-09-03|NONE|AIR|beans cajole blithel +12673|132103|4617|1|18|20431.80|0.07|0.07|R|F|1994-08-22|1994-08-31|1994-09-20|COLLECT COD|SHIP|ckages haggle c +12674|145220|7735|1|29|36691.38|0.08|0.00|A|F|1992-09-21|1992-08-31|1992-10-01|DELIVER IN PERSON|AIR|furiously unusu +12674|110135|7669|2|21|24047.73|0.08|0.06|R|F|1992-08-19|1992-09-06|1992-08-23|NONE|RAIL|c accounts are carefully +12674|22784|5287|3|21|35842.38|0.01|0.03|R|F|1992-10-09|1992-08-14|1992-10-20|TAKE BACK RETURN|RAIL| fluffy deposits. quickly bold excus +12674|114882|7394|4|9|17071.92|0.01|0.01|A|F|1992-08-19|1992-09-28|1992-09-13|TAKE BACK RETURN|MAIL|al accounts. furiously express pinto beans +12674|17757|5261|5|6|10048.50|0.00|0.03|R|F|1992-08-14|1992-10-01|1992-08-27|TAKE BACK RETURN|FOB|quickly special f +12675|77350|9858|1|17|22564.95|0.06|0.08|R|F|1994-02-03|1994-03-19|1994-02-12|NONE|FOB|ites. instructions use always accordin +12675|8375|5876|2|35|44917.95|0.08|0.01|A|F|1994-02-11|1994-03-08|1994-02-28|DELIVER IN PERSON|MAIL|de of the slyly bold accounts sleep ag +12675|150566|567|3|41|66278.96|0.05|0.07|A|F|1994-05-11|1994-03-06|1994-05-15|DELIVER IN PERSON|FOB|ly regular platelets haggle carefully reg +12675|160177|7726|4|26|32166.42|0.08|0.00|R|F|1994-05-10|1994-03-24|1994-06-06|TAKE BACK RETURN|AIR|ns. furiousl +12676|131174|1175|1|5|6025.85|0.03|0.00|A|F|1994-04-17|1994-03-10|1994-04-23|NONE|AIR|ly final theodolites. even instructi +12677|139233|1747|1|30|38166.90|0.10|0.03|N|O|1996-08-12|1996-08-12|1996-08-15|DELIVER IN PERSON|SHIP|onic platelets. carefully pending ideas abo +12677|76340|1355|2|13|17112.42|0.03|0.00|N|O|1996-08-17|1996-08-14|1996-08-22|TAKE BACK RETURN|FOB| carefully special requests detect. re +12677|39348|6858|3|21|27034.14|0.01|0.00|N|O|1996-06-28|1996-07-10|1996-07-15|TAKE BACK RETURN|AIR|bold pinto beans. ca +12677|107228|9739|4|40|49408.80|0.06|0.05|N|O|1996-09-07|1996-07-07|1996-09-08|NONE|MAIL|even asymptotes cajole. sly +12677|176826|9344|5|17|32347.94|0.05|0.03|N|O|1996-07-12|1996-08-07|1996-07-19|COLLECT COD|TRUCK|slyly ironic forges +12677|103217|748|6|41|50028.61|0.07|0.04|N|O|1996-07-07|1996-08-12|1996-07-19|COLLECT COD|MAIL|refully. slyly final instructions wake. fu +12678|145133|5134|1|10|11781.30|0.10|0.05|N|O|1998-05-13|1998-04-03|1998-06-10|TAKE BACK RETURN|FOB|ly bold multipliers. fluffil +12678|34105|1615|2|5|5195.50|0.10|0.03|N|O|1998-05-26|1998-04-22|1998-06-03|NONE|MAIL|ckages are slyly above the slyly bold i +12678|190553|5592|3|16|26296.80|0.03|0.03|N|O|1998-03-25|1998-04-26|1998-03-26|NONE|RAIL|ial deposits nag slyly af +12678|17932|5436|4|25|46248.25|0.00|0.06|N|O|1998-05-26|1998-04-18|1998-05-27|DELIVER IN PERSON|TRUCK|ackages could have to integr +12678|178827|6379|5|1|1905.82|0.01|0.05|N|O|1998-04-16|1998-03-25|1998-05-09|TAKE BACK RETURN|RAIL|ccounts maintain slyly about the q +12679|3866|1367|1|3|5309.58|0.10|0.06|N|O|1997-10-05|1997-08-24|1997-10-30|TAKE BACK RETURN|SHIP|ular, unusual ideas wake alongside of t +12679|159368|4399|2|50|71368.00|0.05|0.03|N|O|1997-07-04|1997-09-15|1997-07-20|DELIVER IN PERSON|SHIP|ccounts across +12704|134845|4846|1|21|39476.64|0.09|0.02|A|F|1993-02-20|1993-05-05|1993-03-09|COLLECT COD|RAIL|posits. regular deposits cajol +12704|133122|5636|2|30|34653.60|0.10|0.06|R|F|1993-04-18|1993-04-24|1993-05-08|TAKE BACK RETURN|SHIP| pending theo +12704|179274|9275|3|28|37891.56|0.07|0.03|A|F|1993-06-07|1993-03-21|1993-06-27|COLLECT COD|RAIL|riously ironic excuses. carefully ex +12704|43593|8602|4|11|16902.49|0.05|0.03|A|F|1993-02-14|1993-04-25|1993-02-19|NONE|MAIL|lly even pack +12704|64000|9013|5|16|15424.00|0.10|0.06|A|F|1993-04-29|1993-04-03|1993-05-08|TAKE BACK RETURN|RAIL| are slyly. carefully daring account +12705|136908|9422|1|40|77796.00|0.01|0.08|R|F|1995-01-05|1994-12-08|1995-01-30|TAKE BACK RETURN|SHIP| instructions. furiously unusual th +12705|3107|3108|2|24|24242.40|0.09|0.01|R|F|1994-10-15|1994-11-20|1994-10-22|TAKE BACK RETURN|FOB|- stealthily even requests +12706|190600|8158|1|32|54099.20|0.02|0.04|R|F|1995-01-04|1994-12-24|1995-01-16|NONE|RAIL|leep carefully. even +12706|3401|5902|2|41|53480.40|0.09|0.08|A|F|1995-02-24|1995-01-07|1995-03-16|NONE|MAIL|ss the final, even asympt +12706|148013|528|3|16|16976.16|0.02|0.02|A|F|1995-03-18|1994-12-27|1995-03-19|TAKE BACK RETURN|TRUCK|eposits around the express, special +12706|40264|7777|4|30|36127.80|0.06|0.05|A|F|1995-01-12|1995-01-16|1995-01-15|COLLECT COD|TRUCK|lly pending asymptote +12707|168678|6227|1|17|29693.39|0.09|0.06|R|F|1993-08-15|1993-07-21|1993-09-07|TAKE BACK RETURN|AIR|g carefully final theodolites. blit +12707|169022|9023|2|47|51277.94|0.07|0.02|A|F|1993-07-07|1993-07-25|1993-07-08|NONE|MAIL|requests. slyly ironic accounts about th +12707|150327|7873|3|11|15150.52|0.06|0.01|A|F|1993-07-31|1993-08-01|1993-08-21|COLLECT COD|REG AIR|roughout the dogg +12707|135662|689|4|35|59418.10|0.04|0.02|R|F|1993-08-04|1993-07-03|1993-08-29|COLLECT COD|RAIL|gle above the silent, bold dependenci +12707|62504|23|5|47|68925.50|0.04|0.06|A|F|1993-09-05|1993-08-01|1993-09-26|COLLECT COD|RAIL|efully regular platelets. fl +12707|96895|9405|6|13|24594.57|0.02|0.03|R|F|1993-08-08|1993-07-01|1993-08-10|COLLECT COD|REG AIR|ges. regular packages cajole furiously. c +12707|110996|6019|7|1|2006.99|0.07|0.06|A|F|1993-08-11|1993-07-31|1993-08-13|TAKE BACK RETURN|MAIL|y ironic accounts. blithely pending ideas i +12708|98516|6044|1|14|21203.14|0.02|0.05|R|F|1993-03-08|1993-02-24|1993-03-22|DELIVER IN PERSON|MAIL|iously pending deposits +12708|149517|9518|2|20|31330.20|0.04|0.05|A|F|1993-03-06|1993-03-03|1993-03-24|TAKE BACK RETURN|MAIL|ly unusual requests. quickly regular re +12708|128863|1376|3|49|92701.14|0.10|0.08|A|F|1993-01-10|1993-03-07|1993-01-26|DELIVER IN PERSON|MAIL|among the quickly r +12708|194950|4951|4|44|89977.80|0.04|0.08|A|F|1993-03-03|1993-03-07|1993-03-26|TAKE BACK RETURN|FOB| carefully ironic pin +12708|124533|2070|5|10|15575.30|0.06|0.06|R|F|1993-01-25|1993-03-21|1993-02-11|TAKE BACK RETURN|TRUCK|ly hockey players. slyly unusual dep +12708|21766|1767|6|7|11814.32|0.02|0.03|A|F|1993-02-03|1993-03-17|1993-02-15|TAKE BACK RETURN|TRUCK|sts. slyly even packages cajole closely. ca +12708|10380|381|7|50|64519.00|0.09|0.03|R|F|1993-03-11|1993-03-15|1993-04-03|TAKE BACK RETURN|RAIL|ages nag car +12709|55306|2822|1|17|21442.10|0.09|0.01|N|O|1996-08-01|1996-06-17|1996-08-21|COLLECT COD|REG AIR|daring instructions use. slyly unusual i +12709|121235|3748|2|49|61555.27|0.08|0.03|N|O|1996-07-06|1996-07-07|1996-07-18|DELIVER IN PERSON|FOB|s. slyly ironic de +12710|32123|7130|1|13|13716.56|0.04|0.06|A|F|1993-11-25|1993-10-07|1993-12-07|COLLECT COD|FOB| sleep blithely across the requests. even +12710|84517|2042|2|28|42042.28|0.03|0.04|R|F|1993-12-10|1993-11-07|1993-12-17|COLLECT COD|AIR| dependencies alongside of the f +12710|65338|7845|3|49|63863.17|0.10|0.03|R|F|1993-11-18|1993-11-06|1993-11-26|NONE|RAIL|to beans kindle blithel +12710|119919|7453|4|21|40717.11|0.09|0.03|A|F|1993-12-01|1993-11-14|1993-12-30|COLLECT COD|SHIP|accounts. furiously sp +12710|64654|7161|5|49|79313.85|0.06|0.04|A|F|1993-09-27|1993-09-24|1993-10-27|DELIVER IN PERSON|AIR|n accounts according to the ironic deposi +12710|23538|3539|6|41|59922.73|0.03|0.06|R|F|1993-12-16|1993-10-30|1994-01-13|TAKE BACK RETURN|REG AIR|ans nag carefully express +12710|193054|5574|7|14|16058.70|0.05|0.04|A|F|1993-12-06|1993-10-10|1994-01-01|TAKE BACK RETURN|SHIP|xcuses nag carefu +12711|53211|8222|1|9|10477.89|0.06|0.01|A|F|1992-06-20|1992-05-15|1992-06-22|COLLECT COD|AIR|ag slyly against the ironic +12711|113418|5930|2|48|68707.68|0.09|0.04|A|F|1992-06-11|1992-04-16|1992-06-27|TAKE BACK RETURN|RAIL|symptotes use across the +12711|7927|7928|3|17|31193.64|0.02|0.06|A|F|1992-06-01|1992-04-19|1992-06-11|DELIVER IN PERSON|SHIP|ges are furiously ironic ideas. furiously +12711|14804|2308|4|4|6875.20|0.09|0.07|A|F|1992-04-09|1992-03-27|1992-04-27|TAKE BACK RETURN|SHIP|ly unusual foxes use slyly across th +12736|44178|4179|1|26|29176.42|0.09|0.02|R|F|1993-04-28|1993-05-31|1993-05-06|NONE|MAIL|ke furiously furi +12736|93561|6071|2|33|51300.48|0.09|0.07|R|F|1993-05-31|1993-05-21|1993-06-22|NONE|AIR|nts solve fluffily about the caref +12736|72173|9695|3|18|20613.06|0.03|0.05|R|F|1993-04-20|1993-04-28|1993-04-26|DELIVER IN PERSON|REG AIR| wake. quickly st +12736|198662|3701|4|48|84511.68|0.10|0.07|A|F|1993-06-13|1993-04-15|1993-07-11|TAKE BACK RETURN|MAIL|s-- quickly special packages shall +12736|96428|6429|5|48|68372.16|0.10|0.06|R|F|1993-04-14|1993-04-10|1993-05-11|NONE|TRUCK|out the idle ideas. regular, even ideas ca +12736|52557|73|6|37|55853.35|0.01|0.00|R|F|1993-06-02|1993-05-28|1993-06-30|TAKE BACK RETURN|TRUCK|ly. carefully regular r +12737|58954|6470|1|3|5738.85|0.06|0.02|R|F|1994-05-12|1994-06-25|1994-05-18|NONE|MAIL|es are ironically carefu +12737|32159|4663|2|9|9820.35|0.02|0.07|R|F|1994-05-14|1994-07-03|1994-05-27|NONE|AIR|e quietly along the furi +12737|90506|5525|3|50|74825.00|0.08|0.07|A|F|1994-08-16|1994-07-16|1994-08-22|DELIVER IN PERSON|FOB|rash according to the slyly final instruc +12737|131043|3557|4|42|45109.68|0.03|0.04|R|F|1994-08-11|1994-07-27|1994-09-07|TAKE BACK RETURN|REG AIR|odolites. blithely regul +12737|35532|5533|5|50|73376.50|0.09|0.04|R|F|1994-06-09|1994-06-16|1994-06-21|COLLECT COD|RAIL|ts detect slyly slowly even +12737|177448|7449|6|22|33559.68|0.01|0.05|A|F|1994-08-08|1994-07-23|1994-08-12|TAKE BACK RETURN|FOB|into beans about the furiously eve +12737|164517|4518|7|45|71167.95|0.10|0.06|R|F|1994-05-26|1994-06-28|1994-06-07|TAKE BACK RETURN|REG AIR|nal pinto beans use along +12738|27684|187|1|11|17728.48|0.01|0.07|N|O|1998-07-12|1998-08-25|1998-08-08|TAKE BACK RETURN|RAIL|sual reque +12738|80209|7734|2|16|19027.20|0.02|0.03|N|O|1998-07-03|1998-08-03|1998-07-04|COLLECT COD|FOB|r platelets. final dependencies among th +12738|65353|5354|3|24|31640.40|0.03|0.06|N|O|1998-08-21|1998-08-31|1998-09-09|NONE|SHIP|de of the dep +12738|185193|2748|4|37|47293.03|0.10|0.06|N|O|1998-09-25|1998-07-31|1998-10-18|TAKE BACK RETURN|AIR|c foxes use according to t +12738|137983|497|5|32|64671.36|0.01|0.01|N|O|1998-09-04|1998-08-16|1998-10-02|COLLECT COD|FOB|s are quickly ent +12739|198723|6281|1|30|54651.60|0.08|0.08|A|F|1992-05-15|1992-05-10|1992-05-26|COLLECT COD|REG AIR| final requests serve blithely blithely +12740|62109|7122|1|41|43915.10|0.04|0.03|N|O|1997-08-19|1997-07-12|1997-09-09|DELIVER IN PERSON|RAIL| pending requests. regular depo +12741|132436|7463|1|41|60205.63|0.00|0.02|A|F|1992-10-17|1992-09-06|1992-11-11|TAKE BACK RETURN|MAIL|of the quickly regular foxes. +12741|49800|4809|2|27|47244.60|0.10|0.04|A|F|1992-09-10|1992-10-04|1992-10-06|DELIVER IN PERSON|AIR|usual accounts. e +12741|177611|5163|3|6|10131.66|0.06|0.06|A|F|1992-07-25|1992-09-16|1992-08-03|DELIVER IN PERSON|RAIL|wake even courts. f +12741|92129|9657|4|1|1121.12|0.05|0.07|A|F|1992-09-11|1992-08-24|1992-09-13|DELIVER IN PERSON|RAIL|ggle above the regular, ironic requests. as +12741|198842|3881|5|32|62106.88|0.01|0.07|R|F|1992-09-24|1992-08-20|1992-10-08|TAKE BACK RETURN|AIR| express theodolite +12742|78600|1108|1|22|34729.20|0.03|0.01|N|O|1997-08-15|1997-07-11|1997-08-20|TAKE BACK RETURN|AIR| integrate carefully pinto +12743|42944|5449|1|32|60382.08|0.05|0.00|A|F|1993-10-07|1993-09-06|1993-10-31|NONE|REG AIR|ies sleep carefully slyly special r +12743|144731|2274|2|11|19533.03|0.09|0.08|A|F|1993-07-24|1993-08-20|1993-08-04|COLLECT COD|AIR|aters are thinly pending +12743|80671|8196|3|22|36336.74|0.09|0.06|A|F|1993-08-23|1993-08-07|1993-09-22|TAKE BACK RETURN|SHIP|al theodolites. slyly even foxes atop +12743|33477|8484|4|9|12694.23|0.09|0.02|R|F|1993-08-07|1993-09-06|1993-08-11|COLLECT COD|AIR|kages boost slyly up the fin +12768|16354|6355|1|25|31758.75|0.06|0.06|R|F|1994-05-01|1994-06-01|1994-05-31|TAKE BACK RETURN|MAIL|ests cajole furiously pearls. carefully +12768|46995|2004|2|18|34955.82|0.03|0.08|R|F|1994-04-15|1994-06-09|1994-04-27|TAKE BACK RETURN|TRUCK|ccording to the unusual +12768|35810|817|3|17|29678.77|0.08|0.02|R|F|1994-05-26|1994-05-25|1994-06-05|NONE|RAIL|theodolites cajole b +12768|55066|77|4|21|21442.26|0.00|0.04|A|F|1994-07-15|1994-06-10|1994-08-02|COLLECT COD|FOB| of the regular pack +12768|80508|509|5|10|14885.00|0.06|0.07|R|F|1994-04-23|1994-05-10|1994-05-21|DELIVER IN PERSON|AIR|ly alongside o +12769|191206|1207|1|16|20755.20|0.07|0.08|R|F|1992-04-01|1992-03-24|1992-04-21|NONE|RAIL|ven Tiresias cajole qui +12770|45953|8458|1|3|5696.85|0.09|0.02|A|F|1993-07-22|1993-06-15|1993-08-04|NONE|RAIL|even pinto beans haggle regular, express a +12770|116655|4189|2|17|28418.05|0.02|0.08|R|F|1993-07-11|1993-07-11|1993-08-04|NONE|TRUCK|iously even instructions. furiously +12770|10139|5142|3|49|51407.37|0.05|0.04|A|F|1993-04-28|1993-05-20|1993-04-29|DELIVER IN PERSON|FOB|ly final pinto beans about +12770|190091|92|4|4|4724.36|0.01|0.02|A|F|1993-06-08|1993-05-18|1993-07-08|COLLECT COD|TRUCK| fluffily pend +12770|53014|8025|5|37|35779.37|0.10|0.06|A|F|1993-07-09|1993-07-04|1993-07-27|DELIVER IN PERSON|MAIL| even deposits wake bravely +12771|59508|2014|1|30|44025.00|0.08|0.06|R|F|1994-04-14|1994-03-03|1994-04-21|COLLECT COD|SHIP|s. furiously final requests use slyly blith +12771|148248|763|2|28|36294.72|0.09|0.06|A|F|1994-04-03|1994-03-09|1994-04-22|TAKE BACK RETURN|SHIP|ss pinto beans. slyly specia +12771|196779|9299|3|28|52521.56|0.01|0.07|R|F|1994-02-16|1994-03-31|1994-03-03|TAKE BACK RETURN|SHIP|ong the quickly furious instruct +12771|55018|2534|4|41|39893.41|0.06|0.03|A|F|1994-04-09|1994-02-21|1994-05-06|TAKE BACK RETURN|AIR|ole quickly. carefully final foxes use +12771|77197|2212|5|5|5870.95|0.02|0.08|A|F|1994-04-27|1994-04-06|1994-05-25|NONE|REG AIR|the blithely +12772|7826|2827|1|37|64151.34|0.09|0.02|R|F|1995-05-17|1995-07-03|1995-05-19|DELIVER IN PERSON|MAIL| furiously reg +12772|116247|6248|2|34|42950.16|0.07|0.00|N|O|1995-07-24|1995-08-07|1995-08-06|DELIVER IN PERSON|SHIP|ake slyly against the r +12772|160715|716|3|44|78131.24|0.02|0.03|N|O|1995-07-14|1995-08-06|1995-07-18|NONE|TRUCK|pendencies. even, enticing +12772|122044|9581|4|32|34113.28|0.01|0.04|R|F|1995-06-07|1995-06-16|1995-06-13|TAKE BACK RETURN|TRUCK|s. fluffily ironic pinto beans at +12772|178615|3650|5|30|50808.30|0.04|0.03|N|O|1995-07-15|1995-06-26|1995-07-21|NONE|SHIP|lly final packages engage carefully reg +12773|179116|9117|1|17|20316.87|0.06|0.08|R|F|1995-02-04|1995-04-02|1995-02-09|NONE|AIR| accounts nag sl +12773|189160|9161|2|39|48717.24|0.01|0.06|R|F|1995-02-25|1995-03-12|1995-03-27|COLLECT COD|TRUCK|. slyly bold requests +12773|197469|2508|3|38|59525.48|0.05|0.02|A|F|1995-03-18|1995-03-13|1995-03-24|NONE|TRUCK| requests. +12773|53351|867|4|16|20869.60|0.08|0.03|A|F|1995-03-09|1995-02-28|1995-03-13|TAKE BACK RETURN|RAIL|inly thin Tiresias. furiou +12773|65254|7761|5|41|49989.25|0.07|0.02|R|F|1995-03-31|1995-03-03|1995-04-18|NONE|SHIP|s; quickly ironic hockey players cajol +12773|123724|6237|6|23|40197.56|0.02|0.06|R|F|1995-04-01|1995-03-27|1995-04-11|TAKE BACK RETURN|REG AIR|kly furiously final theodolites. ironic d +12773|23092|3093|7|20|20301.80|0.03|0.07|R|F|1995-03-09|1995-03-26|1995-03-25|COLLECT COD|FOB|ckly regular packages. final +12774|105359|2890|1|16|21829.60|0.08|0.05|R|F|1993-01-09|1992-12-25|1993-01-19|DELIVER IN PERSON|FOB|refully boldly +12774|152390|2391|2|29|41829.31|0.04|0.04|A|F|1992-10-24|1992-11-27|1992-11-08|DELIVER IN PERSON|RAIL|ts are furiously: furiously even ac +12774|2572|73|3|5|7372.85|0.04|0.04|R|F|1993-02-07|1992-12-13|1993-02-28|DELIVER IN PERSON|TRUCK|ly bold deposits across t +12775|84317|4318|1|45|58558.95|0.02|0.00|N|O|1996-12-06|1996-12-07|1996-12-25|TAKE BACK RETURN|RAIL| integrate furiously along th +12775|103430|8451|2|9|12900.87|0.06|0.02|N|O|1996-10-24|1996-12-11|1996-10-31|DELIVER IN PERSON|AIR| express hockey players sleep fur +12775|137183|2210|3|33|40265.94|0.05|0.01|N|O|1996-11-09|1996-11-17|1996-11-25|COLLECT COD|TRUCK| unusual ideas. care +12775|33483|3484|4|2|2832.96|0.10|0.05|N|O|1996-10-16|1996-12-21|1996-10-28|NONE|TRUCK|lyly final excuses. carefully regular +12800|152806|7837|1|47|87363.60|0.01|0.06|R|F|1993-07-12|1993-07-23|1993-07-27|TAKE BACK RETURN|MAIL|equests. slyly regular accounts could +12800|193965|3966|2|43|88535.28|0.03|0.07|R|F|1993-09-19|1993-08-17|1993-10-01|DELIVER IN PERSON|TRUCK|s. blithely even foxes impress above +12800|163839|3840|3|27|51376.41|0.08|0.06|R|F|1993-06-12|1993-07-02|1993-06-19|DELIVER IN PERSON|REG AIR|icingly bold fo +12800|30986|987|4|24|46007.52|0.10|0.04|R|F|1993-07-20|1993-06-25|1993-08-07|COLLECT COD|FOB|itaphs. express, unusual instructions +12800|179110|9111|5|47|55888.17|0.02|0.05|A|F|1993-08-23|1993-08-02|1993-09-22|NONE|AIR|refully bold requests should +12801|42447|9960|1|42|58356.48|0.08|0.07|N|O|1997-08-30|1997-10-01|1997-09-03|COLLECT COD|AIR|old, final deposits +12801|6684|4185|2|1|1590.68|0.04|0.05|N|O|1997-09-10|1997-10-27|1997-10-01|COLLECT COD|SHIP|ve the express, final foxes. +12801|136092|1119|3|39|43995.51|0.03|0.03|N|O|1997-10-17|1997-11-15|1997-11-01|NONE|FOB|usly blithely final i +12801|93165|3166|4|45|52117.20|0.01|0.07|N|O|1997-09-13|1997-10-21|1997-09-18|DELIVER IN PERSON|RAIL|ong the final acc +12801|7371|4872|5|35|44742.95|0.02|0.01|N|O|1997-09-03|1997-10-03|1997-09-27|COLLECT COD|REG AIR|ously unus +12802|88993|4010|1|43|85225.57|0.02|0.02|N|O|1998-05-27|1998-05-17|1998-06-19|COLLECT COD|MAIL|s haggle furiously after th +12802|105348|369|2|28|37893.52|0.09|0.01|N|O|1998-03-29|1998-04-25|1998-04-03|TAKE BACK RETURN|REG AIR|he final ideas. blithely fi +12802|181975|9530|3|17|34968.49|0.04|0.04|N|O|1998-04-27|1998-04-06|1998-05-06|NONE|AIR|unts wake. even, final +12802|46158|6159|4|22|24291.30|0.02|0.04|N|O|1998-04-29|1998-05-26|1998-05-16|DELIVER IN PERSON|MAIL|. ironic deposits cajole fluffily +12802|174094|4095|5|44|51395.96|0.00|0.00|N|O|1998-06-29|1998-05-20|1998-07-16|DELIVER IN PERSON|SHIP|lyly bold deposits. +12803|4494|6995|1|16|22375.84|0.08|0.04|R|F|1993-03-30|1993-05-24|1993-04-18|TAKE BACK RETURN|AIR|leep across the furiously pending courts +12803|116025|1048|2|13|13533.26|0.10|0.04|A|F|1993-03-12|1993-05-24|1993-03-20|TAKE BACK RETURN|AIR|thogs cajole along the pe +12804|22965|472|1|50|94398.00|0.02|0.04|R|F|1992-09-17|1992-07-25|1992-10-13|TAKE BACK RETURN|MAIL|. express, special excuses doubt. carefully +12804|165842|875|2|24|45788.16|0.09|0.05|A|F|1992-07-08|1992-08-04|1992-07-15|NONE|AIR| ironic dolphins cajo +12804|98939|6467|3|40|77517.20|0.01|0.04|A|F|1992-08-19|1992-08-02|1992-09-04|TAKE BACK RETURN|SHIP|affix after the even, special account +12804|59949|4960|4|49|93538.06|0.04|0.06|A|F|1992-06-25|1992-08-12|1992-07-04|DELIVER IN PERSON|SHIP|thlessly acc +12804|155838|3384|5|19|35982.77|0.00|0.04|R|F|1992-08-13|1992-06-25|1992-09-01|NONE|MAIL|l asymptotes. final reques +12804|155724|755|6|46|81867.12|0.03|0.08|R|F|1992-07-22|1992-08-18|1992-08-01|DELIVER IN PERSON|RAIL|requests use around the even depo +12804|43149|8158|7|10|10921.40|0.06|0.02|R|F|1992-07-23|1992-07-09|1992-07-28|NONE|MAIL| foxes ought to ha +12805|190941|3461|1|9|18287.46|0.04|0.07|N|O|1997-02-13|1997-02-24|1997-02-15|COLLECT COD|FOB|nding, express courts +12805|135845|3385|2|24|45140.16|0.04|0.06|N|O|1997-02-16|1997-03-10|1997-02-22|NONE|REG AIR|e regular, regular packages. ex +12805|142936|5451|3|23|45515.39|0.09|0.03|N|O|1997-02-25|1997-02-13|1997-03-08|NONE|REG AIR|le quickly +12806|120141|7678|1|1|1161.14|0.00|0.06|N|O|1996-01-18|1996-02-21|1996-01-25|TAKE BACK RETURN|FOB|, special deposits nag after +12806|195941|8461|2|44|89625.36|0.07|0.07|N|O|1996-03-03|1996-01-25|1996-03-28|COLLECT COD|SHIP|kages. platelets dazzle c +12806|168953|6502|3|41|82899.95|0.04|0.03|N|O|1996-01-16|1996-03-19|1996-01-21|COLLECT COD|TRUCK| ironic platelets are +12806|177495|7496|4|14|22014.86|0.08|0.06|N|O|1995-12-30|1996-02-26|1996-01-06|TAKE BACK RETURN|TRUCK|ly regular requests. +12806|156267|6268|5|3|3969.78|0.00|0.03|N|O|1996-03-03|1996-02-02|1996-03-20|DELIVER IN PERSON|TRUCK|patterns cajole sly +12806|169099|6648|6|21|24529.89|0.01|0.03|N|O|1996-01-15|1996-02-19|1996-01-25|TAKE BACK RETURN|AIR|nusual ideas sleep furiously +12807|130759|8299|1|7|12528.25|0.10|0.01|N|O|1998-04-14|1998-03-20|1998-05-13|NONE|SHIP|s the deposits use of +12807|63106|3107|2|16|17105.60|0.00|0.08|N|O|1998-03-19|1998-04-07|1998-04-01|COLLECT COD|REG AIR|rate carefully regular theodolites. +12832|142761|2762|1|49|88384.24|0.02|0.04|A|F|1995-03-13|1995-03-04|1995-03-18|NONE|RAIL|ag. carefully final +12833|76248|6249|1|11|13466.64|0.02|0.01|N|O|1998-08-10|1998-08-01|1998-09-08|TAKE BACK RETURN|FOB|ges affix furiously final courts. +12833|95041|60|2|47|48693.88|0.07|0.04|N|O|1998-09-27|1998-08-12|1998-10-22|NONE|RAIL|about the +12834|143389|5904|1|28|40106.64|0.06|0.03|N|O|1996-12-26|1996-12-03|1997-01-03|TAKE BACK RETURN|SHIP|p carefully. care +12834|125756|781|2|41|73051.75|0.05|0.01|N|O|1997-01-30|1997-01-28|1997-02-27|NONE|FOB|s. foxes among +12834|171836|9388|3|37|70589.71|0.06|0.05|N|O|1996-11-15|1996-12-29|1996-12-11|TAKE BACK RETURN|RAIL|theodolites s +12834|41907|1908|4|18|33280.20|0.04|0.01|N|O|1996-12-12|1996-12-20|1996-12-19|TAKE BACK RETURN|MAIL|lar gifts. blithely even escapades acr +12834|116607|1630|5|16|25977.60|0.03|0.06|N|O|1997-02-21|1996-12-17|1997-03-17|DELIVER IN PERSON|SHIP|the blithely even reque +12834|4373|9374|6|34|43430.58|0.01|0.01|N|O|1996-12-06|1996-12-25|1996-12-17|TAKE BACK RETURN|REG AIR|sly unusual, regular packages. ide +12834|90805|3315|7|26|46690.80|0.01|0.07|N|O|1996-12-24|1996-12-26|1996-12-30|TAKE BACK RETURN|MAIL|. ironic deposits haggle quickly p +12835|155946|8462|1|1|2001.94|0.08|0.07|N|O|1997-01-27|1997-03-27|1997-01-30|DELIVER IN PERSON|SHIP|ole stealthily blit +12835|183026|3027|2|15|16635.30|0.04|0.00|N|O|1997-03-24|1997-03-05|1997-03-31|TAKE BACK RETURN|REG AIR| accounts use along the fluffy +12835|112232|7255|3|11|13686.53|0.03|0.03|N|O|1997-05-13|1997-04-20|1997-05-19|DELIVER IN PERSON|FOB|quickly ironic accounts. blithely si +12835|72688|7703|4|33|54802.44|0.08|0.06|N|O|1997-05-09|1997-03-25|1997-05-28|DELIVER IN PERSON|AIR|xes are furiously after the express acc +12835|60377|5390|5|5|6686.85|0.04|0.02|N|O|1997-02-24|1997-02-22|1997-03-25|TAKE BACK RETURN|MAIL|sits. carefully final pinto +12835|144081|1624|6|5|5625.40|0.00|0.03|N|O|1997-03-10|1997-04-06|1997-03-30|COLLECT COD|RAIL|ely regular asymptotes: regular, e +12835|157696|5242|7|28|49103.32|0.07|0.00|N|O|1997-05-20|1997-04-17|1997-06-01|DELIVER IN PERSON|TRUCK|s nag furiously. regular packag +12836|183156|711|1|1|1239.15|0.04|0.03|N|O|1996-05-14|1996-06-23|1996-05-20|TAKE BACK RETURN|AIR|hely pending asymptotes? +12836|100898|5919|2|48|91146.72|0.07|0.06|N|O|1996-06-13|1996-06-30|1996-06-28|COLLECT COD|SHIP| the ruthless requests. fina +12836|183448|1003|3|33|50537.52|0.03|0.00|N|O|1996-07-08|1996-05-21|1996-08-04|NONE|SHIP|e the foxes snooze carefu +12836|4424|9425|4|44|58450.48|0.06|0.01|N|O|1996-07-10|1996-05-18|1996-07-14|COLLECT COD|SHIP|dolphins haggle blithely sometimes +12836|137694|7695|5|19|32902.11|0.01|0.01|N|O|1996-04-21|1996-06-22|1996-05-08|COLLECT COD|RAIL| pinto beans alongsi +12836|7386|9887|6|21|27160.98|0.09|0.03|N|O|1996-07-08|1996-06-12|1996-07-11|NONE|REG AIR|ns. ironic accounts could h +12836|132699|2700|7|31|53682.39|0.04|0.07|N|O|1996-05-11|1996-05-27|1996-05-30|NONE|TRUCK|arefully even packages. bold, final pint +12837|59547|2053|1|14|21091.56|0.10|0.03|A|F|1993-01-09|1993-01-26|1993-01-15|DELIVER IN PERSON|RAIL|g the pending deposits are so +12837|2342|2343|2|38|47284.92|0.05|0.07|R|F|1993-01-11|1993-02-24|1993-01-16|TAKE BACK RETURN|MAIL| the never regular foxes haggle blithely +12837|146346|3889|3|8|11138.72|0.00|0.00|R|F|1993-01-22|1993-01-17|1993-02-17|NONE|REG AIR|ckly ironic deposits. +12837|23184|8189|4|44|48715.92|0.08|0.02|R|F|1993-02-08|1993-01-03|1993-02-13|TAKE BACK RETURN|FOB|gage. slyly bold pinto +12838|189852|7407|1|21|40778.85|0.10|0.07|N|O|1998-07-17|1998-08-28|1998-07-25|DELIVER IN PERSON|AIR|nes sleep furiously against the +12838|42278|9791|2|27|32947.29|0.10|0.05|N|O|1998-09-05|1998-09-18|1998-09-28|DELIVER IN PERSON|MAIL|ways even deposits. furio +12838|165410|443|3|24|35409.84|0.07|0.00|N|O|1998-10-21|1998-08-26|1998-11-10|TAKE BACK RETURN|RAIL|to the bold packages x-ray slyly near +12839|163996|6513|1|26|53559.74|0.05|0.01|N|O|1998-01-23|1998-03-12|1998-02-08|COLLECT COD|RAIL|gly bold accoun +12839|77385|4907|2|34|46320.92|0.02|0.02|N|O|1998-02-16|1998-03-11|1998-03-06|DELIVER IN PERSON|AIR|e furiously +12839|8947|1448|3|2|3711.88|0.01|0.08|N|O|1998-04-26|1998-03-31|1998-05-26|NONE|MAIL|ages are c +12839|165815|8332|4|21|39497.01|0.00|0.07|N|O|1998-02-12|1998-03-01|1998-02-22|DELIVER IN PERSON|TRUCK| fluffily above the final theodolit +12839|45786|5787|5|5|8658.90|0.10|0.04|N|O|1998-02-14|1998-02-19|1998-03-11|DELIVER IN PERSON|AIR|express accounts b +12839|116785|4319|6|37|66665.86|0.08|0.08|N|O|1998-03-14|1998-03-31|1998-04-09|NONE|SHIP|lar deposits cajole +12864|146165|6166|1|5|6055.80|0.03|0.02|R|F|1994-08-05|1994-06-23|1994-08-09|TAKE BACK RETURN|TRUCK|uctions. slyly special pearls wake +12864|193889|1447|2|43|85263.84|0.04|0.03|R|F|1994-07-12|1994-07-17|1994-08-04|COLLECT COD|MAIL|e carefully final pinto beans cajole +12864|78885|3900|3|34|63371.92|0.00|0.00|A|F|1994-06-07|1994-07-31|1994-06-28|TAKE BACK RETURN|REG AIR|asymptotes lose quickly +12865|153942|8973|1|33|65866.02|0.04|0.00|N|O|1997-06-28|1997-07-18|1997-07-27|COLLECT COD|FOB|ickly final pinto beans haggle furiously +12865|99278|4297|2|1|1277.27|0.01|0.01|N|O|1997-07-13|1997-08-18|1997-08-07|COLLECT COD|REG AIR|ly special instructions about the qu +12865|161828|4345|3|50|94491.00|0.04|0.00|N|O|1997-09-17|1997-07-02|1997-10-16|NONE|AIR|uriously express dolphins haggle bli +12865|43084|8093|4|21|21568.68|0.08|0.02|N|O|1997-06-11|1997-07-07|1997-07-06|NONE|SHIP|riously pending theodolites. quickly +12865|97514|5042|5|32|48368.32|0.00|0.05|N|O|1997-09-08|1997-08-04|1997-09-11|DELIVER IN PERSON|MAIL| regularly pending inst +12865|112541|7564|6|2|3107.08|0.10|0.02|N|O|1997-08-13|1997-07-05|1997-08-16|NONE|REG AIR|uests use car +12865|70009|2517|7|21|20559.00|0.08|0.06|N|O|1997-07-03|1997-08-05|1997-07-18|COLLECT COD|MAIL|hinder carefully special deposits. caref +12866|37959|463|1|6|11381.70|0.02|0.06|N|O|1997-02-06|1997-04-10|1997-02-07|COLLECT COD|MAIL|eposits. regular Tire +12866|166355|3904|2|32|45483.20|0.00|0.07|N|O|1997-05-11|1997-04-10|1997-06-05|COLLECT COD|MAIL|bove the furiousl +12866|111733|9267|3|35|61065.55|0.06|0.01|N|O|1997-04-27|1997-04-07|1997-05-26|DELIVER IN PERSON|FOB|y even accounts thr +12866|91196|1197|4|9|10684.71|0.01|0.02|N|O|1997-04-11|1997-02-20|1997-05-09|DELIVER IN PERSON|SHIP|olites. care +12866|123228|5741|5|17|21270.74|0.06|0.07|N|O|1997-02-05|1997-03-10|1997-02-25|DELIVER IN PERSON|FOB|y furiously ironic deposits. unusual +12866|87504|2521|6|8|11932.00|0.05|0.05|N|O|1997-04-04|1997-03-18|1997-05-04|TAKE BACK RETURN|AIR|t. blithely special ideas wake. slyly +12866|63645|6152|7|12|19303.68|0.00|0.08|N|O|1997-05-04|1997-03-02|1997-05-28|TAKE BACK RETURN|SHIP|sheaves wake fluffi +12867|72148|7163|1|14|15681.96|0.02|0.04|A|F|1995-04-20|1995-05-29|1995-05-09|DELIVER IN PERSON|AIR|ts. furiously regular instructio +12867|183275|830|2|45|61122.15|0.10|0.08|N|F|1995-06-10|1995-05-02|1995-07-04|TAKE BACK RETURN|SHIP|final tithes. s +12867|102014|4525|3|48|48768.48|0.00|0.06|A|F|1995-06-06|1995-06-08|1995-06-13|NONE|REG AIR|quickly brave +12867|148961|3990|4|20|40199.20|0.07|0.03|R|F|1995-04-15|1995-04-15|1995-04-29|DELIVER IN PERSON|SHIP|atelets wake fluffily after th +12867|173650|8685|5|15|25854.75|0.06|0.06|A|F|1995-05-17|1995-06-07|1995-06-10|TAKE BACK RETURN|RAIL|ccording to the furio +12868|188092|8093|1|10|11800.90|0.02|0.01|R|F|1995-03-12|1995-04-08|1995-03-29|NONE|MAIL|nal ideas. furiousl +12868|50423|5434|2|46|63177.32|0.00|0.03|A|F|1995-05-30|1995-05-17|1995-06-15|COLLECT COD|MAIL|cajole. carefully even packages integra +12868|42933|2934|3|32|60029.76|0.00|0.04|N|O|1995-06-21|1995-05-28|1995-07-04|COLLECT COD|RAIL| outside the furiously bold courts. packa +12868|165058|5059|4|45|50537.25|0.06|0.05|A|F|1995-04-08|1995-05-31|1995-04-12|DELIVER IN PERSON|MAIL|nal, ironic ideas use blith +12868|115054|7566|5|3|3207.15|0.07|0.04|N|F|1995-06-10|1995-04-30|1995-07-07|COLLECT COD|MAIL|efully about the car +12868|99853|2363|6|15|27792.75|0.02|0.04|R|F|1995-04-11|1995-04-26|1995-04-12|DELIVER IN PERSON|TRUCK|y final accounts lose regular +12869|143673|6188|1|35|60083.45|0.06|0.07|A|F|1994-05-23|1994-03-12|1994-06-12|TAKE BACK RETURN|FOB|e slyly. pending foxes along the carefull +12869|98221|3240|2|44|53645.68|0.05|0.07|R|F|1994-05-15|1994-04-08|1994-05-19|TAKE BACK RETURN|TRUCK|ckages according to the f +12870|33602|1112|1|39|59888.40|0.01|0.08|A|F|1993-10-22|1993-09-21|1993-11-02|NONE|AIR|ilent ideas. quickly special asympt +12871|14151|1655|1|33|35149.95|0.00|0.02|N|O|1995-11-29|1995-12-04|1995-12-28|COLLECT COD|FOB|posits. furiously daring foxes boost +12871|31717|6724|2|50|82435.50|0.09|0.02|N|O|1996-01-13|1995-12-22|1996-01-18|TAKE BACK RETURN|MAIL| snooze quic +12871|53443|3444|3|29|40496.76|0.08|0.04|N|O|1995-10-17|1995-12-12|1995-10-23|COLLECT COD|REG AIR|ajole alongside of the furiously regular +12871|788|789|4|15|25331.70|0.07|0.02|N|O|1995-11-29|1995-11-09|1995-12-18|TAKE BACK RETURN|MAIL|l packages. grouches use c +12871|37758|2765|5|25|42393.75|0.02|0.03|N|O|1995-11-29|1995-12-03|1995-12-07|COLLECT COD|RAIL|olites sleep carefully blithely +12871|187307|4862|6|10|13943.00|0.00|0.03|N|O|1996-01-26|1995-12-24|1996-02-02|COLLECT COD|MAIL|totes. slyly p +12896|84370|9387|1|47|63655.39|0.08|0.00|N|O|1997-04-18|1997-02-18|1997-04-30|DELIVER IN PERSON|REG AIR|eposits are quickly. eve +12896|194930|7450|2|16|32398.88|0.01|0.02|N|O|1997-01-01|1997-02-27|1997-01-16|NONE|RAIL|its sleep f +12896|180323|2842|3|42|58939.44|0.09|0.07|N|O|1996-12-26|1997-02-03|1997-01-04|COLLECT COD|TRUCK|r escapades alongs +12896|84613|2138|4|48|76685.28|0.01|0.00|N|O|1997-01-30|1997-03-13|1997-02-08|DELIVER IN PERSON|MAIL| final grouches boost +12896|83826|6335|5|10|18098.20|0.09|0.08|N|O|1997-04-14|1997-02-08|1997-04-27|COLLECT COD|AIR|xes nag carefully. theodolites are +12896|55584|3100|6|11|16935.38|0.03|0.03|N|O|1997-03-13|1997-02-13|1997-04-09|COLLECT COD|MAIL|against the deposits doze +12896|191920|4440|7|17|34202.64|0.06|0.04|N|O|1997-01-21|1997-02-03|1997-02-10|DELIVER IN PERSON|RAIL|th the doggedly regular foxes. iron +12897|195630|5631|1|32|55220.16|0.10|0.02|N|O|1995-08-08|1995-08-29|1995-08-22|NONE|RAIL|the furiously regular accoun +12897|138091|8092|2|27|30485.43|0.06|0.01|N|O|1995-11-04|1995-09-27|1995-11-27|TAKE BACK RETURN|FOB|g from the slyly silent accounts. packages +12897|81568|4077|3|19|29441.64|0.03|0.06|N|O|1995-08-02|1995-09-17|1995-08-15|TAKE BACK RETURN|FOB|nstructions wake. fu +12897|111824|1825|4|4|7343.28|0.02|0.00|N|O|1995-10-20|1995-08-29|1995-10-29|DELIVER IN PERSON|TRUCK|ully final packages h +12897|24056|4057|5|2|1960.10|0.00|0.03|N|O|1995-09-27|1995-09-07|1995-10-01|COLLECT COD|AIR|refully ironic theodolites. qui +12897|103953|8974|6|29|56751.55|0.08|0.03|N|O|1995-08-17|1995-10-13|1995-08-22|TAKE BACK RETURN|MAIL|lent instructions boost carefully sp +12898|144643|2186|1|32|54004.48|0.01|0.05|R|F|1994-11-05|1994-12-06|1994-11-27|COLLECT COD|MAIL|osits affix quickly fluffily regul +12899|32847|357|1|18|32037.12|0.10|0.01|N|O|1996-04-09|1996-06-22|1996-05-03|COLLECT COD|AIR|ffily even platelets sleep bl +12899|47659|5172|2|5|8033.25|0.04|0.07|N|O|1996-07-03|1996-05-28|1996-07-24|TAKE BACK RETURN|SHIP|ic platelets. requests integrate furi +12899|193568|3569|3|7|11630.92|0.03|0.07|N|O|1996-04-12|1996-06-30|1996-04-26|TAKE BACK RETURN|MAIL|press asymptotes sle +12900|182705|5224|1|11|19664.70|0.03|0.05|R|F|1993-05-20|1993-07-27|1993-05-28|NONE|REG AIR|iously regular accounts. express platel +12900|119564|9565|2|19|30087.64|0.00|0.05|R|F|1993-07-08|1993-06-19|1993-07-25|NONE|AIR| pinto beans cajole alongside of the quickl +12901|163222|771|1|33|42412.26|0.04|0.06|R|F|1994-07-09|1994-07-30|1994-07-30|DELIVER IN PERSON|SHIP|ect furiousl +12901|60894|8413|2|21|38952.69|0.09|0.08|A|F|1994-06-16|1994-07-27|1994-06-26|NONE|AIR|arefully bold accounts +12901|31679|6686|3|39|62816.13|0.07|0.05|A|F|1994-08-10|1994-07-25|1994-08-13|NONE|RAIL|ests. slyl +12901|27122|2127|4|46|48259.52|0.04|0.08|R|F|1994-06-30|1994-07-06|1994-07-06|NONE|FOB|st about the unusual +12901|26216|6217|5|42|47972.82|0.00|0.05|R|F|1994-06-27|1994-07-25|1994-07-21|NONE|RAIL|ructions caj +12901|10639|3141|6|43|66634.09|0.03|0.08|A|F|1994-09-03|1994-06-16|1994-09-19|TAKE BACK RETURN|TRUCK|according to the furiously ir +12901|193200|5720|7|12|15518.40|0.07|0.01|A|F|1994-08-06|1994-07-06|1994-08-08|COLLECT COD|RAIL|anent ideas use fu +12902|97534|7535|1|50|76576.50|0.09|0.04|R|F|1993-11-27|1993-12-26|1993-12-06|TAKE BACK RETURN|REG AIR|unts haggle furio +12902|37566|2573|2|15|22553.40|0.05|0.02|A|F|1994-01-28|1993-12-05|1994-02-17|COLLECT COD|AIR|s. even foxes boost carefull +12902|155428|5429|3|24|35602.08|0.05|0.04|A|F|1993-10-31|1993-12-14|1993-11-16|NONE|SHIP|after the quickl +12902|73626|3627|4|37|59185.94|0.04|0.00|R|F|1993-12-06|1993-12-05|1993-12-15|DELIVER IN PERSON|FOB|s. carefully regular requests b +12902|31143|1144|5|26|27927.64|0.10|0.05|A|F|1993-12-31|1993-12-18|1994-01-26|NONE|FOB|ly. never special +12902|15443|2947|6|40|54337.60|0.08|0.00|R|F|1993-11-15|1994-01-09|1993-11-26|COLLECT COD|AIR| across th +12902|134829|2369|7|44|82008.08|0.08|0.04|R|F|1993-12-14|1993-12-26|1994-01-02|COLLECT COD|MAIL|ites. special, regular ideas across the +12903|57913|419|1|20|37418.20|0.05|0.02|R|F|1994-11-04|1994-11-13|1994-11-19|DELIVER IN PERSON|REG AIR|ar, furious hockey play +12903|131876|9416|2|20|38157.40|0.05|0.02|R|F|1994-10-30|1994-11-24|1994-11-16|DELIVER IN PERSON|REG AIR|uffily. fluffily ironic packages nag. sly +12903|35801|3311|3|29|50367.20|0.03|0.01|R|F|1994-12-15|1994-11-30|1995-01-14|DELIVER IN PERSON|TRUCK| requests print furiously above th +12903|107301|2322|4|1|1308.30|0.09|0.08|R|F|1994-11-20|1994-11-06|1994-12-07|NONE|AIR| pending packages across the final, final +12928|132657|5171|1|28|47310.20|0.00|0.03|R|F|1994-04-05|1994-06-06|1994-04-21|NONE|SHIP|s the quickly furious ideas. ironic, ironic +12928|160901|3418|2|2|3923.80|0.04|0.08|A|F|1994-04-26|1994-05-01|1994-05-11|NONE|RAIL| ironic accoun +12928|60762|8281|3|48|82692.48|0.01|0.04|R|F|1994-06-06|1994-05-17|1994-06-10|NONE|MAIL|ctions sleep quickly along the as +12928|19323|9324|4|8|9938.56|0.00|0.04|R|F|1994-05-02|1994-06-09|1994-05-06|NONE|FOB|ns sleep regular accounts. fluffily regu +12928|151477|1478|5|33|50439.51|0.04|0.06|R|F|1994-07-20|1994-05-25|1994-08-14|COLLECT COD|TRUCK|leep fluffily slyly ironic requests. +12928|64859|7366|6|29|52891.65|0.02|0.02|A|F|1994-07-27|1994-06-04|1994-08-11|COLLECT COD|FOB|gular deposits. regular +12928|83076|8093|7|27|28594.89|0.10|0.03|A|F|1994-05-24|1994-05-09|1994-06-13|COLLECT COD|RAIL| around the final deposits. furi +12929|57081|7082|1|40|41523.20|0.02|0.02|A|F|1993-10-11|1993-11-22|1993-11-02|TAKE BACK RETURN|AIR|ages. regu +12929|158534|8535|2|7|11147.71|0.06|0.04|A|F|1993-10-04|1993-10-02|1993-10-11|COLLECT COD|AIR|gular deposits use deposits. b +12929|74863|9878|3|34|62487.24|0.04|0.04|A|F|1993-12-23|1993-10-23|1994-01-18|TAKE BACK RETURN|AIR|sly against the regular +12929|13037|5539|4|13|12350.39|0.03|0.04|A|F|1993-11-11|1993-10-09|1993-11-16|DELIVER IN PERSON|SHIP|ke regular, close ideas. +12930|18656|3659|1|10|15746.50|0.04|0.04|N|O|1995-12-27|1996-01-08|1996-01-18|NONE|AIR|ven packages are furiously orbits. ca +12931|181733|6770|1|4|7258.92|0.08|0.03|R|F|1992-06-11|1992-06-28|1992-06-23|NONE|TRUCK| epitaphs across the blithely even pin +12931|182324|9879|2|24|33751.68|0.04|0.06|A|F|1992-05-27|1992-07-17|1992-06-18|COLLECT COD|AIR| cajole blithely. pending, pendin +12931|109139|4160|3|24|27555.12|0.09|0.08|R|F|1992-05-22|1992-06-25|1992-06-19|DELIVER IN PERSON|MAIL|s eat express, ironic packages. blithely +12932|161614|6647|1|44|73726.84|0.05|0.07|N|O|1997-10-17|1997-11-19|1997-10-23|COLLECT COD|REG AIR|eodolites cajole pending, iro +12932|40155|2660|2|50|54757.50|0.07|0.06|N|O|1997-12-16|1997-11-20|1997-12-30|DELIVER IN PERSON|AIR| excuses. regular asymptotes +12932|77055|4577|3|5|5160.25|0.02|0.02|N|O|1997-09-07|1997-10-15|1997-09-26|NONE|TRUCK|olites. slyly special packages integrate +12932|59868|4879|4|7|12795.02|0.00|0.03|N|O|1997-09-08|1997-11-12|1997-10-01|COLLECT COD|FOB|ar ideas poach b +12933|165120|7637|1|3|3555.36|0.00|0.03|N|O|1998-06-07|1998-04-05|1998-06-11|DELIVER IN PERSON|TRUCK|s among the fur +12933|159414|6960|2|27|39782.07|0.07|0.06|N|O|1998-05-24|1998-03-26|1998-06-05|TAKE BACK RETURN|RAIL|furiously final foxes cajole +12933|60149|150|3|17|18855.38|0.04|0.03|N|O|1998-03-17|1998-05-09|1998-03-22|COLLECT COD|RAIL|lly unusual dependenc +12933|109191|9192|4|30|36005.70|0.00|0.05|N|O|1998-03-06|1998-04-13|1998-03-12|DELIVER IN PERSON|TRUCK| quickly ironic +12933|167657|2690|5|50|86232.50|0.07|0.01|N|O|1998-05-29|1998-05-16|1998-06-22|COLLECT COD|REG AIR|uffily. daringly pending packages c +12933|197702|7703|6|31|55790.70|0.09|0.06|N|O|1998-03-19|1998-05-07|1998-04-02|TAKE BACK RETURN|AIR|ronic dependencies. carefully regular hocke +12933|170856|5891|7|14|26975.90|0.04|0.00|N|O|1998-05-15|1998-05-07|1998-05-25|DELIVER IN PERSON|RAIL| accounts among the special deposits +12934|168185|8186|1|37|46367.66|0.10|0.02|A|F|1994-03-15|1994-05-31|1994-04-13|TAKE BACK RETURN|FOB|e stealthy, express epit +12934|78960|6482|2|34|65924.64|0.01|0.07|R|F|1994-07-04|1994-05-16|1994-07-26|DELIVER IN PERSON|REG AIR|uring the final theodolites. fur +12934|63927|3928|3|5|9454.60|0.03|0.01|R|F|1994-05-20|1994-05-28|1994-06-04|COLLECT COD|RAIL|ly unusual deposits alongside of the slyl +12934|11580|6583|4|7|10441.06|0.07|0.04|R|F|1994-06-20|1994-05-10|1994-07-13|TAKE BACK RETURN|SHIP|quickly unusu +12934|11024|1025|5|13|12155.26|0.02|0.07|A|F|1994-04-25|1994-05-06|1994-05-21|DELIVER IN PERSON|AIR| final requests cajole bold, silent reque +12934|79308|9309|6|50|64365.00|0.03|0.00|A|F|1994-06-16|1994-05-06|1994-06-23|TAKE BACK RETURN|MAIL|uthless deposits wake slyly. care +12934|118380|5914|7|47|65723.86|0.06|0.01|A|F|1994-04-22|1994-05-25|1994-05-16|NONE|SHIP|pecial instructions nag s +12935|1698|1699|1|9|14397.21|0.10|0.01|A|F|1994-08-10|1994-07-01|1994-08-20|TAKE BACK RETURN|MAIL|special asymptotes sleep furiously. c +12935|127450|2475|2|4|5909.80|0.01|0.00|A|F|1994-05-27|1994-08-05|1994-06-13|DELIVER IN PERSON|FOB|jole above the regular, regular gifts +12935|41292|6301|3|3|3699.87|0.00|0.02|R|F|1994-06-01|1994-07-15|1994-06-22|TAKE BACK RETURN|REG AIR|ons. blithely final instructions print furi +12935|188188|3225|4|31|39561.58|0.10|0.07|A|F|1994-08-23|1994-07-07|1994-08-29|NONE|SHIP|ts cajole blithely against +12960|30203|204|1|38|43061.60|0.02|0.04|A|F|1993-10-26|1994-01-08|1993-11-14|NONE|AIR|structions +12960|12622|2623|2|32|49107.84|0.06|0.07|A|F|1994-02-08|1993-12-19|1994-02-21|COLLECT COD|REG AIR|s detect blithely. slyly careful +12960|137302|2329|3|8|10714.40|0.01|0.02|R|F|1994-01-05|1993-11-27|1994-02-01|DELIVER IN PERSON|AIR|its cajole. special, bold requests +12960|23622|6125|4|38|58733.56|0.08|0.06|A|F|1993-12-04|1993-11-18|1993-12-21|TAKE BACK RETURN|SHIP| quiet requ +12961|15645|8147|1|43|67107.52|0.02|0.01|A|F|1995-04-08|1995-01-31|1995-05-01|COLLECT COD|REG AIR|ilent pinto beans cajole fluffily regul +12961|137203|7204|2|15|18603.00|0.04|0.01|A|F|1995-02-16|1995-01-30|1995-03-04|COLLECT COD|TRUCK| pending requests ab +12961|169935|9936|3|22|44108.46|0.04|0.02|R|F|1995-03-25|1995-02-06|1995-04-17|NONE|MAIL|blithely i +12961|95926|3454|4|20|38438.40|0.07|0.03|R|F|1995-01-10|1995-01-30|1995-01-29|NONE|AIR|ges alongside of the accounts +12962|161802|6835|1|25|46595.00|0.10|0.07|N|O|1995-10-30|1996-01-26|1995-11-03|NONE|RAIL|ut the blithely express braids. slyly fi +12962|193072|630|2|16|18641.12|0.07|0.04|N|O|1995-12-29|1995-11-30|1996-01-06|NONE|AIR|olites haggle. inst +12962|153619|1165|3|43|71922.23|0.00|0.06|N|O|1996-02-04|1996-01-16|1996-03-01|NONE|TRUCK|nts haggle a +12963|74528|4529|1|42|63105.84|0.00|0.05|N|O|1998-08-27|1998-08-23|1998-09-01|COLLECT COD|TRUCK|d packages affix quickly quickly u +12964|26402|1407|1|7|9298.80|0.05|0.04|N|O|1998-03-31|1998-03-30|1998-04-06|TAKE BACK RETURN|FOB|uriously even pinto beans +12964|137023|7024|2|11|11660.22|0.02|0.07|N|O|1998-05-08|1998-03-27|1998-06-07|NONE|TRUCK|y. regular deposits among the blithely cl +12964|130354|355|3|14|19380.90|0.03|0.00|N|O|1998-05-11|1998-02-26|1998-06-03|DELIVER IN PERSON|REG AIR|pinto beans after the blit +12964|44380|9389|4|33|43704.54|0.07|0.08|N|O|1998-01-30|1998-03-19|1998-02-12|TAKE BACK RETURN|MAIL|latelets. qui +12964|88465|974|5|32|46510.72|0.05|0.07|N|O|1998-03-14|1998-04-02|1998-03-24|DELIVER IN PERSON|AIR|r the furiousl +12964|18223|725|6|28|31954.16|0.02|0.07|N|O|1998-02-26|1998-02-22|1998-03-01|DELIVER IN PERSON|MAIL|gh the regular accounts. +12964|61871|6884|7|38|69649.06|0.10|0.05|N|O|1998-02-02|1998-03-11|1998-02-09|TAKE BACK RETURN|RAIL|riously final deposits; theodoli +12965|49893|9894|1|15|27643.35|0.00|0.08|A|F|1993-08-17|1993-08-30|1993-09-12|TAKE BACK RETURN|FOB|counts are furiously +12965|146161|3704|2|34|41043.44|0.03|0.08|R|F|1993-09-10|1993-09-07|1993-09-21|COLLECT COD|TRUCK| regular requests. bold, +12965|111475|3987|3|35|52026.45|0.02|0.03|R|F|1993-06-29|1993-09-19|1993-07-05|COLLECT COD|FOB|even requests haggle quietly spe +12966|46301|3814|1|35|43655.50|0.02|0.07|N|O|1997-12-15|1997-12-11|1997-12-21|COLLECT COD|AIR|ly furiously regular depo +12966|164725|7242|2|1|1789.72|0.05|0.04|N|O|1997-12-28|1997-12-21|1998-01-01|TAKE BACK RETURN|AIR|uickly furious +12967|38722|8723|1|8|13285.76|0.07|0.02|R|F|1993-10-01|1993-12-03|1993-10-02|TAKE BACK RETURN|FOB|the carefully regular accounts +12992|1515|4016|1|32|45328.32|0.01|0.02|N|O|1997-04-09|1997-04-13|1997-04-18|COLLECT COD|RAIL|ic deposits. quick +12992|61340|6353|2|6|7808.04|0.06|0.08|N|O|1997-04-04|1997-04-29|1997-04-17|DELIVER IN PERSON|RAIL|atelets about the slyly pendin +12992|129260|4285|3|32|41256.32|0.03|0.01|N|O|1997-05-01|1997-04-03|1997-05-19|NONE|RAIL|pecial ideas. blithely final accounts are b +12992|60170|2677|4|26|29384.42|0.01|0.02|N|O|1997-06-15|1997-03-29|1997-06-17|DELIVER IN PERSON|MAIL|tes haggle b +12992|66584|6585|5|44|68225.52|0.03|0.00|N|O|1997-03-14|1997-04-21|1997-03-31|NONE|REG AIR|oxes. carefully bold grouches +12992|67060|4579|6|10|10270.60|0.00|0.05|N|O|1997-05-31|1997-05-04|1997-06-22|NONE|MAIL|lyly express packages. bold, final foxe +12993|120860|5885|1|7|13166.02|0.08|0.06|N|O|1998-07-09|1998-07-21|1998-08-04|COLLECT COD|FOB|er the deposi +12993|90635|636|2|22|35763.86|0.05|0.04|N|O|1998-08-03|1998-07-14|1998-08-29|NONE|AIR|never. carefully ironic platelets +12994|17449|7450|1|48|65589.12|0.00|0.05|A|F|1995-03-12|1995-02-07|1995-03-21|NONE|AIR|long the pending, bold excuses. pending +12995|101041|6062|1|46|47933.84|0.03|0.00|N|O|1996-08-02|1996-09-14|1996-09-01|DELIVER IN PERSON|SHIP|fily along the ironic platelets. exc +12995|182578|5097|2|14|23247.98|0.01|0.08|N|O|1996-08-20|1996-09-04|1996-09-01|NONE|MAIL|nts haggle bli +12995|176767|1802|3|31|57156.56|0.01|0.02|N|O|1996-10-19|1996-10-17|1996-10-30|DELIVER IN PERSON|MAIL|blithely ironic asymptotes nag quickly +12995|117823|2846|4|33|60747.06|0.09|0.00|N|O|1996-10-20|1996-09-27|1996-11-18|NONE|FOB|s cajole. furiously ironic theodolites +12995|36887|1894|5|6|10943.28|0.10|0.08|N|O|1996-10-13|1996-09-01|1996-10-19|TAKE BACK RETURN|MAIL|snooze alongside of t +12995|145831|5832|6|30|56304.90|0.01|0.04|N|O|1996-09-23|1996-10-10|1996-09-30|COLLECT COD|SHIP| cajole fluffily express requests. bold, r +12996|65992|1005|1|8|15663.92|0.09|0.03|N|O|1996-02-19|1996-02-26|1996-03-19|TAKE BACK RETURN|TRUCK|express, ironic +12996|123659|1196|2|6|10095.90|0.08|0.01|N|O|1996-02-16|1996-02-03|1996-02-28|NONE|RAIL|y above the always ironic instructions. re +12996|132333|2334|3|49|66901.17|0.04|0.03|N|O|1995-12-25|1996-02-12|1996-01-08|NONE|SHIP| nod above the carefully final +12996|110133|7667|4|30|34293.90|0.02|0.02|N|O|1996-04-04|1996-01-14|1996-04-28|COLLECT COD|FOB|sts haggle slowly e +12997|129157|6694|1|6|7116.90|0.05|0.05|N|O|1996-06-06|1996-08-07|1996-06-30|NONE|RAIL|eposits. sly +12997|130248|249|2|7|8947.68|0.04|0.06|N|O|1996-07-07|1996-06-27|1996-07-08|NONE|REG AIR|eas cajole enticingly? even requests after +12997|69583|2090|3|5|7762.90|0.05|0.00|N|O|1996-08-18|1996-08-10|1996-09-12|NONE|AIR| accounts wake deposits. request +12998|64934|4935|1|2|3797.86|0.04|0.08|N|O|1997-01-25|1996-11-29|1997-02-04|COLLECT COD|AIR|cial packages boost. regula +12998|137994|7995|2|18|36575.82|0.07|0.06|N|O|1996-10-23|1996-11-23|1996-10-27|COLLECT COD|REG AIR|efully. slyly even platelets cajole +12999|189835|2354|1|45|86617.35|0.10|0.05|A|F|1993-07-09|1993-06-23|1993-08-04|TAKE BACK RETURN|TRUCK|y ironic ideas use furiously carefully regu +12999|152131|2132|2|31|36677.03|0.01|0.06|A|F|1993-05-09|1993-05-21|1993-05-14|DELIVER IN PERSON|TRUCK|jole silently. quickly final foxes d +12999|64990|7497|3|36|70379.64|0.00|0.03|A|F|1993-04-24|1993-05-19|1993-05-11|TAKE BACK RETURN|RAIL|unts maintain blithely furiously regular +12999|85528|5529|4|20|30270.40|0.01|0.04|A|F|1993-07-05|1993-06-24|1993-07-10|DELIVER IN PERSON|TRUCK|e carefully pending Tiresias? pa +13024|78939|8940|1|24|46030.32|0.04|0.04|R|F|1992-06-16|1992-05-26|1992-07-04|DELIVER IN PERSON|RAIL|ckages along +13024|125737|762|2|1|1762.73|0.10|0.02|R|F|1992-05-15|1992-06-11|1992-06-09|COLLECT COD|AIR|sleep? blithely slow requests +13024|53294|3295|3|12|14967.48|0.09|0.05|R|F|1992-04-17|1992-04-30|1992-04-24|DELIVER IN PERSON|MAIL|en instructions x-ra +13025|54312|6818|1|26|32924.06|0.10|0.01|N|O|1998-02-07|1998-03-22|1998-02-08|NONE|FOB|fully bold theodolites wake. ironic +13025|10693|5696|2|24|38488.56|0.00|0.03|N|O|1998-05-19|1998-03-21|1998-05-31|TAKE BACK RETURN|RAIL|mold blithely final accounts. even acc +13025|103618|8639|3|21|34053.81|0.08|0.02|N|O|1998-04-15|1998-02-27|1998-04-21|TAKE BACK RETURN|FOB|nag blithely +13025|93815|3816|4|32|57881.92|0.00|0.03|N|O|1998-03-15|1998-03-13|1998-04-03|DELIVER IN PERSON|REG AIR| blithely final requests boost +13026|96411|8921|1|44|61926.04|0.05|0.07|N|O|1997-06-08|1997-05-23|1997-06-18|DELIVER IN PERSON|RAIL|he slyly silent dugouts +13026|174513|7031|2|18|28575.18|0.04|0.01|N|O|1997-05-06|1997-06-23|1997-05-29|COLLECT COD|RAIL|ously. carefully regular reques +13026|30748|3252|3|11|18466.14|0.05|0.00|N|O|1997-07-30|1997-05-17|1997-08-23|TAKE BACK RETURN|AIR|nal foxes do maintain am +13026|170915|5950|4|26|51633.66|0.10|0.06|N|O|1997-05-21|1997-06-10|1997-06-20|COLLECT COD|REG AIR|uctions. express +13026|152382|9928|5|21|30121.98|0.06|0.07|N|O|1997-06-01|1997-05-07|1997-06-29|DELIVER IN PERSON|FOB|es are never. blithely re +13027|100270|271|1|30|38108.10|0.05|0.02|A|F|1992-01-17|1992-02-24|1992-02-04|DELIVER IN PERSON|TRUCK| accounts. unusual deposits are carefull +13027|22198|9705|2|33|36966.27|0.01|0.07|R|F|1992-03-24|1992-03-22|1992-04-04|TAKE BACK RETURN|MAIL|, regular package +13027|72825|7840|3|15|26967.30|0.08|0.04|A|F|1992-04-06|1992-04-04|1992-04-28|NONE|SHIP| final accounts a +13027|167047|9564|4|6|6684.24|0.09|0.01|A|F|1992-03-19|1992-04-04|1992-04-10|TAKE BACK RETURN|REG AIR|olites engage slyly carefully regular +13027|155303|334|5|45|61123.50|0.10|0.06|A|F|1992-03-07|1992-03-05|1992-03-18|COLLECT COD|MAIL|along the +13028|108441|952|1|35|50730.40|0.07|0.07|A|F|1994-04-13|1994-06-22|1994-05-09|DELIVER IN PERSON|RAIL|slyly special accoun +13028|155810|841|2|3|5597.43|0.06|0.00|A|F|1994-05-21|1994-07-03|1994-05-30|NONE|RAIL|ake slyly about the regular +13028|92387|9915|3|40|55175.20|0.10|0.01|A|F|1994-05-30|1994-06-25|1994-06-05|DELIVER IN PERSON|SHIP| blithely. regular, silent foxes cajole c +13028|143015|558|4|49|51842.49|0.03|0.06|A|F|1994-05-18|1994-06-13|1994-06-06|COLLECT COD|TRUCK|ts affix b +13028|44656|9665|5|43|68827.95|0.01|0.03|R|F|1994-08-05|1994-06-30|1994-08-31|DELIVER IN PERSON|TRUCK|ss the stealthily q +13029|101331|3842|1|4|5329.32|0.04|0.08|N|O|1997-11-13|1998-01-13|1997-12-09|DELIVER IN PERSON|MAIL|the ironic, final requests. +13029|61385|8904|2|14|18849.32|0.04|0.06|N|O|1998-03-03|1998-01-16|1998-03-26|TAKE BACK RETURN|RAIL| carefully regular ex +13029|82063|9588|3|39|40757.34|0.10|0.01|N|O|1997-12-04|1998-01-14|1997-12-26|NONE|TRUCK| even accounts. accounts cajole. b +13029|16936|6937|4|34|62999.62|0.00|0.01|N|O|1998-02-04|1998-01-24|1998-03-02|TAKE BACK RETURN|AIR|apades are furiously ab +13029|31315|3819|5|44|54837.64|0.03|0.04|N|O|1998-01-23|1997-12-21|1998-02-06|NONE|AIR| dependencies. deposits ab +13030|167075|9592|1|42|47966.94|0.03|0.00|A|F|1994-10-17|1994-09-24|1994-10-30|TAKE BACK RETURN|RAIL|ts sleep after the express deposits. blithe +13030|18179|5683|2|46|50469.82|0.08|0.07|A|F|1994-08-07|1994-09-16|1994-09-02|TAKE BACK RETURN|MAIL|refully ironic +13030|133381|8408|3|27|38188.26|0.05|0.07|R|F|1994-11-19|1994-09-26|1994-11-27|COLLECT COD|REG AIR|ual, final accounts. final, pe +13031|112161|4673|1|19|22290.04|0.01|0.07|R|F|1993-01-17|1993-02-26|1993-01-24|COLLECT COD|TRUCK|round the accounts +13031|76379|8887|2|39|52859.43|0.01|0.07|R|F|1993-01-07|1993-02-15|1993-01-31|DELIVER IN PERSON|TRUCK|ss packages. final theodolites sleep af +13031|93925|3926|3|17|32621.64|0.07|0.07|A|F|1993-03-08|1993-02-26|1993-03-27|TAKE BACK RETURN|REG AIR|e slyly sl +13031|185830|3385|4|12|22989.96|0.00|0.05|R|F|1993-01-28|1993-02-16|1993-02-07|TAKE BACK RETURN|AIR|ecial asymptotes doze bli +13031|41400|1401|5|44|59021.60|0.05|0.08|R|F|1993-04-03|1993-02-08|1993-04-04|TAKE BACK RETURN|SHIP|unusual packages. blithely regular fra +13031|7761|2762|6|38|63412.88|0.08|0.04|R|F|1993-03-08|1993-02-08|1993-03-18|COLLECT COD|MAIL|ly regular dugouts boost carefully careful +13056|122183|2184|1|29|34950.22|0.09|0.08|A|F|1994-05-27|1994-05-29|1994-05-31|NONE|FOB|ce of the furiously even the +13056|123489|3490|2|36|54449.28|0.03|0.02|R|F|1994-04-24|1994-06-30|1994-05-01|DELIVER IN PERSON|REG AIR|, special deposits haggle thinly accordi +13056|70424|5439|3|28|39043.76|0.07|0.03|R|F|1994-06-20|1994-07-18|1994-07-13|NONE|MAIL|efully fluffily unusual acc +13056|3146|3147|4|11|11540.54|0.02|0.01|R|F|1994-07-21|1994-05-28|1994-08-20|TAKE BACK RETURN|REG AIR|lly regular frays boost about +13056|62442|4949|5|21|29493.24|0.07|0.04|R|F|1994-07-14|1994-06-09|1994-07-30|NONE|SHIP|arefully regular requests are above +13056|46695|4208|6|28|45967.32|0.09|0.06|R|F|1994-07-06|1994-06-21|1994-08-03|COLLECT COD|SHIP| express deposi +13057|184904|9941|1|44|87511.60|0.02|0.02|N|O|1998-02-22|1998-02-12|1998-03-19|COLLECT COD|SHIP|x-ray above the slyly regular instructi +13057|80805|5822|2|16|28572.80|0.08|0.03|N|O|1998-01-14|1998-01-28|1998-02-07|TAKE BACK RETURN|AIR|ests detect +13058|45801|8306|1|9|15721.20|0.03|0.05|N|O|1997-05-19|1997-06-14|1997-05-24|COLLECT COD|SHIP|gular deposits. slyly e +13059|41262|1263|1|22|26471.72|0.01|0.01|N|O|1997-07-20|1997-06-30|1997-08-04|DELIVER IN PERSON|TRUCK|ecial, regul +13059|84924|7433|2|3|5726.76|0.00|0.05|N|O|1997-07-14|1997-08-20|1997-07-17|TAKE BACK RETURN|AIR| slyly bold theodolites-- quickly fin +13059|116043|1066|3|40|42361.60|0.03|0.00|N|O|1997-09-20|1997-07-27|1997-09-22|COLLECT COD|RAIL|elets cajole slyly after the furiou +13059|133856|8883|4|36|68034.60|0.08|0.08|N|O|1997-06-29|1997-08-08|1997-07-13|NONE|FOB| ironic packages try to haggle caref +13059|107205|4736|5|21|25456.20|0.09|0.05|N|O|1997-06-15|1997-08-06|1997-07-06|TAKE BACK RETURN|RAIL|ely ironic pinto beans. deposits haggle- +13059|178875|1393|6|35|68385.45|0.05|0.03|N|O|1997-09-24|1997-07-21|1997-10-14|DELIVER IN PERSON|AIR| instructions +13060|199119|4158|1|17|20707.87|0.01|0.08|N|O|1997-06-03|1997-04-24|1997-06-05|NONE|REG AIR|ely final instructi +13060|178415|3450|2|30|44802.30|0.05|0.00|N|O|1997-04-30|1997-04-05|1997-05-04|COLLECT COD|REG AIR|es sleep bold re +13060|5277|5278|3|7|8275.89|0.10|0.03|N|O|1997-02-10|1997-04-24|1997-02-14|COLLECT COD|REG AIR| pending platelets sleep blithely +13060|85222|7731|4|40|48288.80|0.10|0.07|N|O|1997-03-26|1997-04-14|1997-04-10|TAKE BACK RETURN|AIR|he blithely re +13060|121514|4027|5|36|55278.36|0.05|0.01|N|O|1997-04-19|1997-03-10|1997-04-26|COLLECT COD|TRUCK|the doggedly ironic asympt +13060|73022|5530|6|19|18905.38|0.06|0.04|N|O|1997-05-09|1997-05-02|1997-05-26|NONE|RAIL|he pending courts thrash slyl +13060|73973|8988|7|32|62303.04|0.10|0.00|N|O|1997-04-14|1997-03-28|1997-05-01|TAKE BACK RETURN|MAIL|encies. furiously unu +13061|58769|1275|1|1|1727.76|0.04|0.04|N|O|1997-10-17|1997-10-19|1997-11-03|TAKE BACK RETURN|MAIL|ly special deposits wake +13061|120331|7868|2|9|12161.97|0.04|0.08|N|O|1997-11-27|1997-12-10|1997-12-05|TAKE BACK RETURN|SHIP|equests are ironic, regular dep +13061|187331|7332|3|37|52478.21|0.06|0.04|N|O|1997-11-14|1997-10-28|1997-11-28|TAKE BACK RETURN|AIR|furiously regular sheaves doze a +13062|102511|42|1|39|59026.89|0.05|0.07|N|O|1996-08-08|1996-06-03|1996-08-14|DELIVER IN PERSON|RAIL|enticingly? +13062|102092|4603|2|27|29540.43|0.09|0.06|N|O|1996-07-19|1996-07-29|1996-07-25|NONE|FOB|ending braids haggle carefully final pi +13062|44162|6667|3|2|2212.32|0.10|0.02|N|O|1996-07-22|1996-07-19|1996-08-02|DELIVER IN PERSON|MAIL|he unusual, regular ide +13063|44086|9095|1|29|29872.32|0.08|0.00|N|O|1997-03-03|1997-03-29|1997-03-22|NONE|MAIL|tes. pending, even warhors +13063|150559|3075|2|24|38629.20|0.07|0.06|N|O|1997-02-22|1997-03-13|1997-03-20|COLLECT COD|SHIP|de of the fluffil +13063|44782|7287|3|27|46623.06|0.03|0.01|N|O|1997-02-25|1997-03-05|1997-03-09|COLLECT COD|REG AIR|to are. furiously regular r +13063|35848|8352|4|45|80272.80|0.05|0.03|N|O|1997-05-13|1997-03-06|1997-05-17|DELIVER IN PERSON|REG AIR|yly express, express fo +13063|96588|6589|5|5|7922.90|0.06|0.04|N|O|1997-04-28|1997-04-02|1997-05-11|DELIVER IN PERSON|MAIL|efully furiously r +13063|154079|9110|6|45|50988.15|0.04|0.03|N|O|1997-04-24|1997-03-10|1997-05-20|TAKE BACK RETURN|TRUCK|ymptotes integrate? final foxe +13063|197919|5477|7|45|90760.95|0.01|0.01|N|O|1997-03-19|1997-03-05|1997-04-08|TAKE BACK RETURN|FOB|s. carefully care +13088|15280|283|1|18|21515.04|0.01|0.00|R|F|1993-08-15|1993-05-27|1993-08-21|NONE|RAIL|tes. carefully bold dependencies are +13088|1997|9498|2|42|79757.58|0.10|0.07|R|F|1993-08-02|1993-07-08|1993-08-14|NONE|REG AIR|s wake slyly above the furiously regular +13088|151051|3567|3|35|38571.75|0.00|0.06|A|F|1993-05-08|1993-06-15|1993-05-21|COLLECT COD|AIR|quickly final pinto be +13088|100898|3409|4|15|28483.35|0.06|0.01|R|F|1993-07-31|1993-07-06|1993-08-02|COLLECT COD|FOB|ts-- carefu +13088|190246|2766|5|3|4008.72|0.01|0.06|A|F|1993-08-04|1993-06-09|1993-08-14|COLLECT COD|TRUCK|s cajole regularly furiously ironic acco +13088|58146|5662|6|48|52998.72|0.10|0.05|A|F|1993-06-01|1993-06-04|1993-06-23|DELIVER IN PERSON|SHIP|theodolites wak +13088|56476|8982|7|46|65893.62|0.04|0.04|A|F|1993-08-11|1993-05-29|1993-09-07|NONE|RAIL|y about the slyly final accou +13089|190891|892|1|28|55492.92|0.05|0.08|N|O|1996-04-07|1996-01-25|1996-04-22|DELIVER IN PERSON|AIR|theodolites boost blithely +13089|94321|9340|2|50|65766.00|0.03|0.08|N|O|1996-03-01|1996-02-01|1996-03-18|COLLECT COD|SHIP|nts detect carefully above th +13089|47497|7498|3|40|57779.60|0.06|0.08|N|O|1996-02-24|1996-01-29|1996-03-11|NONE|AIR|sts. carefull +13089|65295|5296|4|49|61754.21|0.07|0.03|N|O|1996-03-19|1996-03-01|1996-04-10|DELIVER IN PERSON|FOB|packages haggle blithel +13090|85418|5419|1|32|44909.12|0.10|0.00|R|F|1993-10-08|1993-08-31|1993-11-01|COLLECT COD|RAIL|ress instruction +13090|10351|7855|2|34|42885.90|0.09|0.03|R|F|1993-09-24|1993-09-19|1993-09-28|COLLECT COD|TRUCK|ly regular dinos a +13090|166352|3901|3|18|25530.30|0.10|0.08|R|F|1993-11-24|1993-08-28|1993-12-02|COLLECT COD|RAIL|unusual packag +13090|71614|4122|4|10|15856.10|0.01|0.07|A|F|1993-08-20|1993-09-29|1993-08-25|TAKE BACK RETURN|MAIL|ideas. regular waters +13090|2186|2187|5|20|21763.60|0.00|0.05|R|F|1993-11-01|1993-10-24|1993-11-16|COLLECT COD|RAIL| furiously regular a +13091|192233|9791|1|11|14577.53|0.00|0.00|R|F|1995-02-08|1994-12-28|1995-02-18|DELIVER IN PERSON|SHIP|st boldly after the furiously regular court +13091|43567|1080|2|11|16616.16|0.10|0.04|A|F|1994-11-22|1995-01-17|1994-12-08|TAKE BACK RETURN|MAIL|egular, pending braids across the +13091|23164|8169|3|23|25004.68|0.02|0.02|R|F|1995-02-22|1994-12-27|1995-02-23|NONE|AIR|pinto beans sleep. bold instructions aroun +13091|105703|5704|4|31|52969.70|0.07|0.06|A|F|1995-01-26|1995-01-21|1995-01-30|DELIVER IN PERSON|TRUCK|even theodolites snooze quickly special +13091|139725|4752|5|38|67059.36|0.08|0.04|R|F|1995-01-26|1995-02-10|1995-02-21|NONE|REG AIR|ly final pinto beans wake ideas. bli +13091|150927|5958|6|48|94940.16|0.06|0.01|A|F|1995-03-02|1995-01-23|1995-03-29|DELIVER IN PERSON|SHIP|fully. carefully pending accounts +13092|97346|4874|1|31|41643.54|0.00|0.02|N|O|1998-10-20|1998-08-27|1998-11-17|DELIVER IN PERSON|TRUCK|atelets alongside of the caref +13092|93535|6045|2|48|73369.44|0.09|0.04|N|O|1998-07-24|1998-09-10|1998-07-27|DELIVER IN PERSON|AIR|dencies. fluffily express dep +13093|162962|2963|1|31|62773.76|0.06|0.06|N|O|1996-07-24|1996-06-30|1996-08-11|COLLECT COD|FOB|ckages. regular sentiments use slyly sl +13093|96995|4523|2|39|77687.61|0.08|0.07|N|O|1996-07-02|1996-07-18|1996-07-20|COLLECT COD|MAIL| pinto beans u +13093|181619|4138|3|15|25509.15|0.03|0.03|N|O|1996-05-15|1996-06-18|1996-05-31|COLLECT COD|TRUCK|ages haggle: unusua +13094|127614|5151|1|41|67306.01|0.00|0.02|R|F|1993-09-15|1993-11-04|1993-09-19|COLLECT COD|TRUCK| about the regular packages. warthogs +13094|3179|5680|2|16|17314.72|0.00|0.01|R|F|1993-10-05|1993-09-30|1993-10-14|NONE|FOB|e slyly unusual requests. +13095|22461|9968|1|42|58105.32|0.10|0.02|N|O|1996-11-20|1996-09-24|1996-12-05|NONE|SHIP|e requests. bold +13095|101561|4072|2|49|76565.44|0.02|0.01|N|O|1996-10-18|1996-10-14|1996-11-10|COLLECT COD|FOB|eep packages. f +13095|128760|6297|3|46|82282.96|0.08|0.03|N|O|1996-08-29|1996-09-07|1996-09-21|COLLECT COD|SHIP| doggedly furiously ironic deposits. p +13095|59153|6669|4|34|37813.10|0.10|0.03|N|O|1996-08-25|1996-09-14|1996-09-02|TAKE BACK RETURN|TRUCK|ke against th +13095|168961|1478|5|29|58868.84|0.10|0.08|N|O|1996-07-28|1996-09-15|1996-08-24|TAKE BACK RETURN|RAIL|iously iron +13095|126325|6326|6|17|22972.44|0.07|0.06|N|O|1996-09-20|1996-09-18|1996-10-10|NONE|REG AIR|en ideas. deposits br +13095|131461|6488|7|27|40296.42|0.05|0.00|N|O|1996-10-07|1996-08-21|1996-10-24|TAKE BACK RETURN|RAIL|affix carefully after the carefully pendin +13120|62148|9667|1|44|48846.16|0.04|0.08|A|F|1994-12-21|1995-01-15|1995-01-03|COLLECT COD|MAIL|en pinto beans. fluffily special +13120|113634|1168|2|22|36247.86|0.06|0.00|R|F|1995-03-14|1995-02-11|1995-04-08|NONE|MAIL|. requests cajole slyly. +13121|106028|8539|1|50|51701.00|0.10|0.06|A|F|1993-03-26|1993-05-21|1993-03-31|DELIVER IN PERSON|TRUCK| blithely against the car +13121|9947|9948|2|17|31567.98|0.08|0.06|R|F|1993-03-14|1993-05-20|1993-03-17|TAKE BACK RETURN|REG AIR| the even pin +13121|172259|2260|3|1|1331.25|0.06|0.05|A|F|1993-06-17|1993-04-14|1993-06-28|NONE|AIR|ggedly. slyly ironic accou +13121|149421|9422|4|44|64698.48|0.00|0.04|A|F|1993-05-01|1993-06-02|1993-05-07|NONE|MAIL|jole. sometimes ironic account +13121|106294|6295|5|24|31206.96|0.01|0.07|R|F|1993-05-27|1993-04-12|1993-06-03|TAKE BACK RETURN|AIR|ts. express packages about the fur +13121|75482|5483|6|11|16032.28|0.05|0.03|A|F|1993-06-23|1993-04-25|1993-07-11|NONE|MAIL|pending idea +13121|24652|7155|7|18|28379.70|0.00|0.00|R|F|1993-07-01|1993-05-12|1993-07-10|COLLECT COD|MAIL|de of the unusual, regular packages ha +13122|109495|2006|1|42|63188.58|0.08|0.08|A|F|1994-10-15|1994-11-28|1994-11-06|DELIVER IN PERSON|AIR|s the final +13122|80506|8031|2|8|11892.00|0.09|0.02|A|F|1995-01-15|1994-11-23|1995-01-19|DELIVER IN PERSON|AIR|carefully +13122|61629|9148|3|34|54081.08|0.05|0.06|A|F|1994-12-16|1994-12-09|1995-01-08|COLLECT COD|FOB|usly silent accounts wake slyly. +13122|193766|1324|4|16|29756.16|0.00|0.08|A|F|1995-01-02|1994-12-15|1995-01-20|DELIVER IN PERSON|MAIL| ideas. blithely ironic +13122|19619|4622|5|23|35388.03|0.01|0.08|A|F|1994-10-31|1994-10-30|1994-11-08|TAKE BACK RETURN|AIR|lar courts +13123|153683|1229|1|11|19103.48|0.02|0.00|N|O|1998-10-05|1998-08-04|1998-10-27|DELIVER IN PERSON|REG AIR|ts sleep quickly blithe +13123|147584|2613|2|13|21210.54|0.06|0.01|N|O|1998-09-17|1998-08-17|1998-10-16|TAKE BACK RETURN|AIR|ously final forges use blithely a +13123|31795|1796|3|37|63891.23|0.09|0.03|N|O|1998-10-28|1998-09-04|1998-11-25|COLLECT COD|MAIL|al foxes affix furiously ironic accounts +13123|166905|9422|4|50|98595.00|0.04|0.07|N|O|1998-07-21|1998-08-30|1998-07-31|TAKE BACK RETURN|MAIL|ts nag according +13123|156391|1422|5|16|23158.24|0.03|0.08|N|O|1998-08-22|1998-08-13|1998-09-02|NONE|MAIL|to beans. quickly final accounts ar +13123|52076|2077|6|18|18505.26|0.09|0.03|N|O|1998-09-21|1998-08-15|1998-10-19|DELIVER IN PERSON|TRUCK|ns sleep furiously. furiously bold +13123|37427|7428|7|4|5457.68|0.08|0.01|N|O|1998-08-12|1998-09-09|1998-08-21|TAKE BACK RETURN|TRUCK|egular dependencies are carefully. slyly +13124|29414|6921|1|28|37615.48|0.03|0.07|A|F|1994-01-18|1994-01-27|1994-01-28|NONE|REG AIR|y express patterns +13124|153607|6123|2|12|19927.20|0.06|0.04|A|F|1994-02-23|1994-02-06|1994-03-24|TAKE BACK RETURN|SHIP|ld ideas. quickly regular +13124|67055|7056|3|4|4088.20|0.09|0.06|A|F|1994-04-04|1994-02-26|1994-04-09|NONE|AIR|into beans. daring theodolites cajole s +13125|148446|3475|1|16|23911.04|0.06|0.04|R|F|1994-03-07|1994-02-18|1994-03-27|DELIVER IN PERSON|RAIL|structions wake. exp +13125|121034|1035|2|2|2110.06|0.01|0.05|R|F|1994-04-10|1994-02-04|1994-04-18|NONE|REG AIR|ies wake blithely ironic d +13125|9454|1955|3|25|34086.25|0.05|0.05|A|F|1994-02-19|1994-03-03|1994-02-23|DELIVER IN PERSON|SHIP| the blithely bold pi +13125|91162|6181|4|41|47279.56|0.06|0.06|A|F|1994-01-18|1994-01-22|1994-02-03|DELIVER IN PERSON|FOB|ncies haggle alongsid +13125|152711|5227|5|27|47620.17|0.08|0.03|A|F|1994-02-03|1994-02-18|1994-02-06|NONE|TRUCK| dependencies. re +13125|3669|3670|6|27|42461.82|0.01|0.01|A|F|1994-04-05|1994-02-04|1994-04-17|TAKE BACK RETURN|SHIP|iously final courts. slyly special acc +13125|53594|8605|7|4|6190.36|0.08|0.00|A|F|1994-01-23|1994-02-16|1994-02-21|COLLECT COD|TRUCK|lithely carefull +13126|145211|7726|1|50|62810.50|0.10|0.08|N|O|1996-02-12|1995-12-22|1996-02-26|DELIVER IN PERSON|FOB|luffily furiously final a +13126|156523|1554|2|16|25272.32|0.08|0.02|N|O|1995-12-13|1996-01-02|1995-12-28|COLLECT COD|SHIP|r accounts about the +13126|78001|509|3|2|1958.00|0.02|0.00|N|O|1995-12-09|1995-12-09|1995-12-26|DELIVER IN PERSON|TRUCK|lar deposits cajole carefully carefu +13126|146981|6982|4|11|22307.78|0.10|0.04|N|O|1995-12-13|1996-01-12|1996-01-12|COLLECT COD|SHIP|es. slyly iron +13126|108158|8159|5|26|30319.90|0.02|0.04|N|O|1995-12-05|1996-01-16|1995-12-23|DELIVER IN PERSON|TRUCK|o beans haggle quickly +13127|113849|3850|1|40|74513.60|0.07|0.00|R|F|1993-09-06|1993-10-30|1993-09-25|COLLECT COD|FOB|tes. furiously special asympt +13152|170532|533|1|40|64101.20|0.00|0.01|R|F|1994-04-12|1994-04-27|1994-04-17|COLLECT COD|MAIL|ts. slyly special accounts sleep agai +13152|124211|4212|2|47|58054.87|0.08|0.06|R|F|1994-03-13|1994-05-16|1994-03-19|NONE|MAIL|ns wake carefull +13152|9061|4062|3|24|23281.44|0.05|0.06|A|F|1994-04-16|1994-04-01|1994-05-15|COLLECT COD|MAIL|ests along the regular accounts caj +13152|86561|4086|4|48|74282.88|0.01|0.06|A|F|1994-02-18|1994-04-25|1994-02-23|COLLECT COD|FOB|usual pinto beans +13152|23445|8450|5|47|64316.68|0.07|0.08|R|F|1994-05-07|1994-03-29|1994-05-25|NONE|RAIL| gifts cajole unusual +13153|175018|5019|1|23|25139.23|0.06|0.07|N|O|1997-01-26|1997-01-23|1997-02-06|DELIVER IN PERSON|RAIL|nts integrate carefully. +13153|113605|6117|2|7|11330.20|0.04|0.06|N|O|1996-12-03|1997-01-16|1997-01-01|NONE|FOB|eep quickly quickly daring foxes; slyly reg +13153|159188|9189|3|22|27437.96|0.04|0.00|N|O|1997-02-04|1997-01-10|1997-03-01|TAKE BACK RETURN|SHIP|er. furiously unusu +13153|57972|478|4|13|25089.61|0.01|0.05|N|O|1997-03-03|1997-01-08|1997-03-06|DELIVER IN PERSON|AIR|s thrash. regular acco +13153|120799|800|5|32|58233.28|0.03|0.04|N|O|1997-02-28|1997-01-14|1997-03-13|TAKE BACK RETURN|FOB|onic courts affix instruct +13153|61328|1329|6|21|27075.72|0.04|0.07|N|O|1997-03-07|1996-12-11|1997-04-01|COLLECT COD|SHIP|sely ironic requests sleep. furiously exp +13154|16092|3596|1|42|42339.78|0.09|0.05|N|O|1997-12-03|1998-01-02|1997-12-27|TAKE BACK RETURN|MAIL| careful pi +13154|48328|8329|2|31|39565.92|0.04|0.03|N|O|1997-11-02|1997-12-26|1997-11-25|TAKE BACK RETURN|SHIP|hely requests! quickly express asymptotes +13154|42280|7289|3|33|40335.24|0.04|0.05|N|O|1997-11-12|1997-11-21|1997-12-06|NONE|MAIL|t the carefully +13154|186864|4419|4|10|19508.60|0.03|0.05|N|O|1998-02-07|1997-12-09|1998-02-11|COLLECT COD|REG AIR|, ironic ideas haggle en +13154|13022|3023|5|45|42075.90|0.01|0.07|N|O|1998-02-09|1998-01-06|1998-02-26|COLLECT COD|RAIL|s among the furiously express +13154|60151|7670|6|34|37779.10|0.10|0.05|N|O|1997-12-12|1997-11-25|1997-12-30|NONE|AIR|ns sleep sometimes? regular, silent +13154|157330|2361|7|29|40232.57|0.07|0.05|N|O|1998-01-06|1997-11-26|1998-01-30|COLLECT COD|FOB|lets. caref +13155|30284|7794|1|5|6071.40|0.06|0.01|N|O|1996-07-15|1996-08-27|1996-07-22|DELIVER IN PERSON|AIR|haggle slyly final hockey pla +13155|174918|9953|2|16|31886.56|0.04|0.06|N|O|1996-07-18|1996-08-25|1996-07-27|DELIVER IN PERSON|FOB|ress instructions nag after the +13155|36087|1094|3|12|12276.96|0.10|0.02|N|O|1996-06-20|1996-08-05|1996-07-14|COLLECT COD|FOB|es cajole. regular foxes cajole care +13155|112909|2910|4|24|46125.60|0.05|0.01|N|O|1996-10-13|1996-08-15|1996-11-09|TAKE BACK RETURN|SHIP| packages affix carefully. +13155|53123|639|5|23|24750.76|0.08|0.08|N|O|1996-10-13|1996-09-04|1996-10-18|TAKE BACK RETURN|REG AIR|g deposits cajole +13155|25952|957|6|31|58216.45|0.08|0.07|N|O|1996-07-24|1996-07-30|1996-07-31|DELIVER IN PERSON|TRUCK|e the slyly unusual deposits. regular, +13155|172680|5198|7|35|61343.80|0.10|0.02|N|O|1996-07-18|1996-07-18|1996-07-27|COLLECT COD|RAIL|s. carefully even deposits afte +13156|27357|7358|1|4|5137.40|0.05|0.06|N|O|1996-01-02|1995-11-14|1996-01-31|NONE|SHIP|nag. furiously ironic depen +13156|188372|8373|2|22|32128.14|0.03|0.00|N|O|1995-12-03|1995-12-18|1995-12-07|TAKE BACK RETURN|AIR|the always regular platelets. stealth +13156|162958|507|3|48|97005.60|0.08|0.08|N|O|1996-01-16|1995-11-27|1996-02-15|NONE|REG AIR|lly quickl +13156|27919|7920|4|32|59101.12|0.10|0.06|N|O|1995-12-20|1995-11-12|1996-01-02|COLLECT COD|SHIP|ess, unusual req +13156|29101|1604|5|26|26782.60|0.09|0.02|N|O|1996-01-04|1995-12-15|1996-01-13|COLLECT COD|REG AIR|eposits along th +13157|149306|6849|1|29|39303.70|0.01|0.08|R|F|1992-03-20|1992-05-03|1992-04-19|COLLECT COD|FOB|ccording to the furiously thin packages. +13157|181884|1885|2|13|25556.44|0.09|0.07|R|F|1992-06-12|1992-03-19|1992-06-26|DELIVER IN PERSON|REG AIR|ages wake even accou +13157|111831|9365|3|34|62656.22|0.07|0.04|R|F|1992-03-17|1992-03-19|1992-03-28|COLLECT COD|REG AIR|ding pinto +13157|143188|731|4|47|57865.46|0.04|0.02|R|F|1992-03-09|1992-04-04|1992-03-14|NONE|FOB|n requests boost +13157|145857|886|5|33|62794.05|0.03|0.04|R|F|1992-04-05|1992-05-02|1992-04-11|COLLECT COD|RAIL|fluffily. fluffily ironic deposits are car +13157|10034|35|6|41|38705.23|0.04|0.07|A|F|1992-02-18|1992-04-13|1992-02-23|DELIVER IN PERSON|FOB|ackages. slyly even requests +13157|25221|7724|7|26|29801.72|0.08|0.08|A|F|1992-05-11|1992-04-14|1992-05-14|COLLECT COD|RAIL|kages nod furiously expr +13158|87174|9683|1|49|56897.33|0.10|0.07|A|F|1992-12-08|1993-01-10|1992-12-18|NONE|FOB|s. fluffily pending idea +13158|132117|9657|2|24|27578.64|0.06|0.04|R|F|1993-03-22|1993-01-28|1993-03-27|COLLECT COD|MAIL|furiously against the iron +13158|89014|6539|3|13|13039.13|0.08|0.08|R|F|1993-01-09|1993-02-08|1993-02-08|TAKE BACK RETURN|MAIL|equests affix +13158|49170|4179|4|2|2238.34|0.07|0.03|R|F|1992-12-14|1992-12-28|1992-12-26|DELIVER IN PERSON|REG AIR|uriously even account +13158|194854|2412|5|32|62363.20|0.06|0.08|R|F|1993-01-23|1993-01-21|1993-02-06|DELIVER IN PERSON|RAIL|y ironic asymptotes haggle pending, +13159|99791|4810|1|50|89539.50|0.02|0.05|N|O|1996-12-25|1997-02-14|1997-01-21|DELIVER IN PERSON|AIR|t, regular pinto beans nag +13159|181873|9428|2|26|50826.62|0.09|0.04|N|O|1996-12-20|1997-02-27|1997-01-13|TAKE BACK RETURN|FOB|ckly final somas. deposits af +13159|130937|8477|3|12|23615.16|0.10|0.01|N|O|1997-02-20|1997-01-29|1997-03-14|DELIVER IN PERSON|FOB| affix furiously. flu +13159|57675|7676|4|16|26122.72|0.07|0.02|N|O|1997-02-22|1997-01-14|1997-03-13|COLLECT COD|MAIL|etween the quickly sp +13184|195917|8437|1|12|24154.92|0.06|0.04|N|O|1998-05-01|1998-06-18|1998-05-14|TAKE BACK RETURN|MAIL|s wake ruthlessly. furiou +13185|65360|7867|1|26|34459.36|0.06|0.07|N|O|1997-11-12|1997-09-11|1997-11-18|DELIVER IN PERSON|RAIL|lites use furiously. furiously unusual es +13185|102854|385|2|30|55705.50|0.01|0.05|N|O|1997-09-14|1997-09-07|1997-10-02|NONE|AIR|old dugouts use fur +13185|50782|783|3|49|84906.22|0.08|0.00|N|O|1997-08-15|1997-09-17|1997-08-28|TAKE BACK RETURN|SHIP| deposits wake blithely +13185|85227|5228|4|44|53337.68|0.00|0.03|N|O|1997-09-24|1997-09-24|1997-09-27|NONE|REG AIR|gside of the reg +13185|193629|1187|5|6|10335.72|0.08|0.04|N|O|1997-11-11|1997-08-15|1997-11-13|NONE|FOB|ideas wake +13185|114817|4818|6|30|54954.30|0.01|0.06|N|O|1997-09-23|1997-10-08|1997-09-27|NONE|TRUCK|lithely pending instructions. even idea +13185|123654|8679|7|40|67106.00|0.08|0.05|N|O|1997-10-12|1997-08-21|1997-10-14|COLLECT COD|TRUCK|accounts haggle +13186|44544|7049|1|42|62518.68|0.01|0.05|N|O|1996-12-20|1996-11-20|1996-12-23|NONE|AIR|posits again +13186|50763|5774|2|21|35988.96|0.07|0.03|N|O|1996-10-22|1996-10-30|1996-11-19|NONE|MAIL|en requests cajole slyly ag +13186|164857|4858|3|18|34593.30|0.08|0.04|N|O|1996-11-11|1996-11-27|1996-11-28|DELIVER IN PERSON|REG AIR|dolphins could boost careful +13186|146887|1916|4|35|67685.80|0.04|0.06|N|O|1996-09-29|1996-11-30|1996-10-16|NONE|REG AIR|ecial requests. special, regular acc +13186|113195|8218|5|43|51952.17|0.06|0.04|N|O|1996-10-04|1996-11-22|1996-10-16|NONE|TRUCK|c packages wake blithely about the bold +13187|44054|9063|1|24|23953.20|0.08|0.07|R|F|1994-02-01|1994-02-18|1994-02-08|DELIVER IN PERSON|TRUCK|yly unusual +13187|12310|2311|2|38|46447.78|0.10|0.08|R|F|1994-01-01|1994-01-12|1994-01-12|COLLECT COD|TRUCK|sts. enticingly ironic requests about t +13187|91247|8775|3|5|6191.20|0.05|0.05|A|F|1994-01-28|1994-02-21|1994-01-29|TAKE BACK RETURN|AIR|efully iro +13188|178253|5805|1|26|34612.50|0.10|0.04|N|O|1998-08-27|1998-09-28|1998-09-18|COLLECT COD|MAIL|lly ironic instruc +13188|95732|3260|2|18|31099.14|0.08|0.03|N|O|1998-09-03|1998-09-10|1998-09-09|TAKE BACK RETURN|MAIL|ests. blithely final accounts ar +13188|155895|5896|3|16|31214.24|0.04|0.02|N|O|1998-10-03|1998-10-06|1998-10-17|TAKE BACK RETURN|RAIL|. carefully regular ac +13189|135476|5477|1|2|3022.94|0.06|0.00|A|F|1995-06-04|1995-07-02|1995-06-09|NONE|SHIP|heodolites affix evenly. final, iro +13190|188508|6063|1|14|22351.00|0.02|0.01|N|O|1998-07-21|1998-08-01|1998-07-31|DELIVER IN PERSON|RAIL|out the careful +13191|100303|304|1|21|27369.30|0.09|0.05|N|O|1998-03-09|1998-03-24|1998-03-27|DELIVER IN PERSON|REG AIR|ully ironic dugouts a +13191|186999|7000|2|41|85525.59|0.06|0.03|N|O|1998-01-01|1998-02-05|1998-01-29|DELIVER IN PERSON|SHIP|ly final theod +13191|81460|6477|3|33|47568.18|0.03|0.05|N|O|1998-04-09|1998-02-09|1998-04-14|NONE|SHIP|riously packa +13191|82971|5480|4|29|56665.13|0.07|0.03|N|O|1997-12-29|1998-03-21|1998-01-26|NONE|TRUCK| express deposits. ironic ideas solve a +13191|84183|6692|5|24|28012.32|0.03|0.02|N|O|1998-02-13|1998-02-02|1998-03-04|DELIVER IN PERSON|MAIL|ainst the packages haggle slyly quickly eve +13191|61231|8750|6|48|57227.04|0.09|0.02|N|O|1998-02-04|1998-03-21|1998-02-25|COLLECT COD|AIR|uffily silent exc +13191|107952|5483|7|28|54878.60|0.03|0.07|N|O|1998-01-12|1998-02-03|1998-01-30|TAKE BACK RETURN|MAIL|ix carefully along the bravely even packa +13216|149032|6575|1|27|29187.81|0.10|0.06|A|F|1992-05-31|1992-06-19|1992-06-05|COLLECT COD|FOB|ithely ironic +13216|178514|1032|2|37|58922.87|0.06|0.05|R|F|1992-05-29|1992-07-01|1992-06-01|DELIVER IN PERSON|RAIL|gle slyly pending, bold excuses. +13217|46088|8593|1|50|51704.00|0.07|0.06|N|O|1997-09-27|1997-11-11|1997-10-21|NONE|TRUCK|ular requests detect +13218|26902|9405|1|36|65840.40|0.07|0.01|A|F|1994-08-06|1994-08-14|1994-08-27|DELIVER IN PERSON|SHIP|slyly regular pi +13218|132449|7476|2|20|29628.80|0.00|0.08|A|F|1994-05-18|1994-06-20|1994-05-25|NONE|REG AIR|nic courts. blithely pend +13218|57380|2391|3|30|40121.40|0.07|0.04|R|F|1994-07-12|1994-07-07|1994-07-22|DELIVER IN PERSON|REG AIR|ular instructions +13218|180673|674|4|49|85929.83|0.06|0.00|A|F|1994-08-03|1994-07-05|1994-08-11|DELIVER IN PERSON|RAIL|fts sleep slyly +13218|163210|759|5|14|17824.94|0.09|0.01|R|F|1994-08-25|1994-07-26|1994-09-23|NONE|REG AIR|instructions. bold, fluffy pea +13218|68021|8022|6|2|1978.04|0.02|0.04|A|F|1994-08-03|1994-07-10|1994-09-01|DELIVER IN PERSON|RAIL|packages cajole carefully accordi +13219|89562|4579|1|21|32582.76|0.01|0.02|N|O|1998-01-30|1998-01-05|1998-02-05|TAKE BACK RETURN|FOB|lets boost fluffily. furiousl +13219|52365|7376|2|43|56646.48|0.04|0.04|N|O|1997-12-27|1997-12-09|1998-01-16|NONE|SHIP|ironic pinto beans are along the careful +13219|94840|4841|3|29|53210.36|0.00|0.06|N|O|1997-11-02|1997-12-08|1997-11-30|TAKE BACK RETURN|TRUCK|carefully blithely bold deposits +13219|163012|561|4|23|24725.23|0.10|0.07|N|O|1997-12-08|1997-11-29|1997-12-27|DELIVER IN PERSON|FOB|y. even, bol +13220|101899|9430|1|30|57026.70|0.01|0.06|N|O|1998-10-23|1998-10-23|1998-11-13|DELIVER IN PERSON|MAIL|odolites sleep. express instructions g +13220|5946|947|2|1|1851.94|0.01|0.03|N|O|1998-11-16|1998-08-30|1998-12-12|NONE|MAIL|ts. idle courts wake blithely. slyly u +13220|118369|5903|3|22|30521.92|0.02|0.06|N|O|1998-09-07|1998-08-30|1998-09-26|COLLECT COD|MAIL|y unusual packages. fur +13220|24839|4840|4|9|15874.47|0.05|0.01|N|O|1998-09-12|1998-10-10|1998-10-02|COLLECT COD|RAIL|ar deposits. even hockey pla +13220|62821|340|5|44|78488.08|0.01|0.05|N|O|1998-10-06|1998-09-14|1998-10-08|DELIVER IN PERSON|SHIP|lly atop the slyly special requests. caref +13221|101879|6900|1|20|37617.40|0.03|0.06|N|O|1995-11-09|1996-01-09|1995-11-13|TAKE BACK RETURN|AIR|excuses. car +13221|80351|7876|2|22|29289.70|0.10|0.07|N|O|1996-01-18|1995-12-18|1996-02-04|COLLECT COD|AIR| somas. quickly express decoys n +13221|56999|9505|3|34|66503.66|0.00|0.03|N|O|1995-12-24|1995-11-15|1996-01-22|DELIVER IN PERSON|TRUCK|cross the ironic +13222|142347|9890|1|20|27786.80|0.06|0.07|N|O|1997-07-29|1997-06-10|1997-08-24|COLLECT COD|TRUCK|c accounts. bold foxes use c +13222|14627|7129|2|10|15416.20|0.07|0.00|N|O|1997-06-17|1997-07-12|1997-07-14|TAKE BACK RETURN|TRUCK|fully bold packages. even, +13222|32065|4569|3|35|34897.10|0.03|0.07|N|O|1997-05-19|1997-07-08|1997-05-30|DELIVER IN PERSON|RAIL|nstructions boost furio +13222|100309|2820|4|14|18330.20|0.05|0.06|N|O|1997-06-02|1997-07-16|1997-06-07|NONE|FOB|along the packages was blithely e +13223|66490|4009|1|30|43694.70|0.06|0.04|N|O|1996-08-22|1996-10-14|1996-09-07|NONE|SHIP|slyly above the slyly bo +13248|131484|6511|1|10|15154.80|0.08|0.07|N|O|1997-05-12|1997-04-15|1997-05-13|TAKE BACK RETURN|AIR|et theodolites n +13248|37260|9764|2|18|21550.68|0.03|0.02|N|O|1997-05-09|1997-03-07|1997-05-24|TAKE BACK RETURN|FOB|elets. furiousl +13248|14590|9593|3|5|7522.95|0.08|0.07|N|O|1997-03-02|1997-04-03|1997-03-30|DELIVER IN PERSON|MAIL|slow deposits det +13249|64030|9043|1|38|37773.14|0.03|0.05|N|O|1997-09-06|1997-09-27|1997-09-25|TAKE BACK RETURN|RAIL|e sometimes +13249|148816|3845|2|24|44755.44|0.08|0.01|N|O|1997-08-14|1997-10-02|1997-08-18|COLLECT COD|TRUCK|inal packages above the final p +13249|143242|5757|3|14|17993.36|0.10|0.08|N|O|1997-09-19|1997-09-17|1997-10-07|DELIVER IN PERSON|REG AIR| lose slyly quickly eve +13249|55007|2523|4|26|25012.00|0.04|0.00|N|O|1997-10-20|1997-08-19|1997-10-21|COLLECT COD|TRUCK|lites. ironic, even d +13249|97193|2212|5|37|44037.03|0.10|0.08|N|O|1997-11-01|1997-09-24|1997-11-22|DELIVER IN PERSON|MAIL|sly pending warho +13249|117474|2497|6|6|8948.82|0.08|0.04|N|O|1997-08-02|1997-10-04|1997-08-13|TAKE BACK RETURN|FOB|hely unusua +13249|179749|2267|7|2|3657.48|0.04|0.05|N|O|1997-10-07|1997-09-26|1997-11-04|TAKE BACK RETURN|AIR|ously sile +13250|38251|755|1|33|39245.25|0.08|0.06|N|O|1997-09-26|1997-10-27|1997-10-19|TAKE BACK RETURN|RAIL|ts. unusual, silent accounts sleep. furiou +13250|82894|419|2|2|3753.78|0.09|0.05|N|O|1997-09-25|1997-11-16|1997-10-17|TAKE BACK RETURN|RAIL|longside of the fi +13250|187013|2050|3|37|40700.37|0.09|0.07|N|O|1997-09-12|1997-09-29|1997-09-24|NONE|TRUCK| above the furiou +13250|114689|2223|4|4|6814.72|0.03|0.05|N|O|1997-10-12|1997-10-22|1997-10-29|TAKE BACK RETURN|AIR|ckly theodol +13250|161673|1674|5|16|27754.72|0.05|0.06|N|O|1997-11-13|1997-09-30|1997-12-10|TAKE BACK RETURN|SHIP| cajole furiously after th +13250|25027|7530|6|4|3808.08|0.04|0.05|N|O|1997-10-07|1997-11-02|1997-10-09|TAKE BACK RETURN|RAIL|ainst the carefully pending pac +13251|184734|7253|1|33|60018.09|0.08|0.07|N|O|1997-07-18|1997-05-23|1997-08-02|TAKE BACK RETURN|SHIP|r packages use along +13251|20369|2872|2|14|18051.04|0.02|0.06|N|O|1997-05-20|1997-06-03|1997-05-21|DELIVER IN PERSON|TRUCK|old requests nag +13251|126895|9408|3|12|23062.68|0.03|0.04|N|O|1997-03-29|1997-05-01|1997-04-19|COLLECT COD|FOB|dolites across the p +13251|108638|6169|4|24|39519.12|0.01|0.03|N|O|1997-04-05|1997-04-29|1997-04-30|TAKE BACK RETURN|SHIP|nd furiously regular p +13251|69033|1540|5|8|8016.24|0.10|0.04|N|O|1997-07-18|1997-05-03|1997-08-16|COLLECT COD|MAIL|ke. blithely silent requests kindle car +13252|50155|5166|1|9|9946.35|0.10|0.04|R|F|1994-06-28|1994-05-18|1994-07-02|COLLECT COD|MAIL|! quickly regular the +13252|145788|5789|2|18|33008.04|0.04|0.03|R|F|1994-05-31|1994-05-06|1994-06-06|NONE|TRUCK| unusual ideas use. packag +13252|57846|2857|3|50|90192.00|0.10|0.05|A|F|1994-05-17|1994-06-21|1994-06-08|TAKE BACK RETURN|REG AIR|press pinto beans. platel +13252|16204|1207|4|32|35846.40|0.10|0.06|R|F|1994-05-15|1994-06-04|1994-06-06|DELIVER IN PERSON|FOB|ts wake. quickly special +13252|129488|9489|5|18|27314.64|0.03|0.08|A|F|1994-06-09|1994-04-23|1994-07-01|COLLECT COD|REG AIR|press foxes. sly +13252|101806|6827|6|3|5423.40|0.08|0.00|A|F|1994-06-28|1994-04-29|1994-07-24|NONE|RAIL| haggle furiously. even accounts affix slyl +13253|184302|9339|1|42|58224.60|0.07|0.06|N|O|1997-02-05|1996-12-13|1997-03-02|NONE|REG AIR|haggle. final, special epita +13253|152317|7348|2|28|38340.68|0.00|0.05|N|O|1997-01-28|1997-01-12|1997-02-02|COLLECT COD|SHIP|cies affix quickly deposits. bl +13253|181482|4001|3|16|25015.68|0.06|0.00|N|O|1996-11-05|1996-12-22|1996-11-17|NONE|AIR|cuses above the regular, +13253|158918|8919|4|18|35584.38|0.10|0.08|N|O|1996-11-17|1997-01-03|1996-12-01|NONE|FOB|requests sleep furiously. final +13253|120221|2734|5|50|62061.00|0.03|0.07|N|O|1996-12-17|1996-12-12|1996-12-19|COLLECT COD|SHIP|sleep around th +13253|142928|7957|6|4|7883.68|0.01|0.00|N|O|1996-12-28|1997-01-01|1997-01-04|NONE|REG AIR|ng the blithely regular id +13253|179825|7377|7|30|57144.60|0.10|0.06|N|O|1997-01-20|1996-12-05|1997-02-04|DELIVER IN PERSON|MAIL| furiously near the carefully iron +13254|102772|2773|1|49|86963.73|0.09|0.00|N|O|1998-04-08|1998-03-25|1998-05-03|COLLECT COD|SHIP|regular deposits are after the +13254|80092|2601|2|46|49316.14|0.10|0.03|N|O|1998-03-17|1998-04-25|1998-04-02|TAKE BACK RETURN|MAIL| bold plat +13254|99009|1519|3|37|37296.00|0.02|0.01|N|O|1998-03-11|1998-05-13|1998-04-10|TAKE BACK RETURN|SHIP|er the furiously ironic frays? +13254|42074|2075|4|12|12192.84|0.01|0.06|N|O|1998-05-19|1998-03-25|1998-06-12|NONE|AIR|ously. fluffily unusual de +13254|123202|3203|5|4|4900.80|0.08|0.04|N|O|1998-03-01|1998-04-08|1998-03-18|TAKE BACK RETURN|MAIL|usual, bold requests boost. furiou +13255|178995|4030|1|8|16591.92|0.09|0.08|A|F|1993-11-05|1993-09-06|1993-11-25|COLLECT COD|MAIL|hely ironic pinto beans haggle +13255|163393|8426|2|18|26215.02|0.10|0.03|R|F|1993-07-25|1993-09-10|1993-07-30|TAKE BACK RETURN|TRUCK|equests. blithely pending deposit +13255|140539|5568|3|8|12636.24|0.09|0.02|A|F|1993-09-30|1993-08-24|1993-10-22|COLLECT COD|TRUCK| slyly; furiously bold +13255|29602|4607|4|39|59732.40|0.07|0.00|A|F|1993-10-15|1993-09-09|1993-10-26|DELIVER IN PERSON|AIR|ly pending packages impress of the expr +13255|107218|7219|5|22|26954.62|0.02|0.04|A|F|1993-11-11|1993-10-03|1993-11-16|COLLECT COD|FOB|osits nag carefully after +13280|142760|2761|1|24|43266.24|0.08|0.02|A|F|1994-12-19|1994-11-18|1995-01-10|COLLECT COD|AIR|iously reg +13280|159486|9487|2|41|63364.68|0.05|0.08|R|F|1995-01-10|1994-12-04|1995-01-18|DELIVER IN PERSON|RAIL|es. fluffi +13280|71901|6916|3|45|84280.50|0.07|0.07|A|F|1994-10-05|1994-11-30|1994-10-13|TAKE BACK RETURN|RAIL|al deposits. asy +13280|26007|1012|4|1|933.00|0.04|0.02|R|F|1994-10-08|1994-10-22|1994-10-22|DELIVER IN PERSON|RAIL|s sleep slyly blith +13280|86329|8838|5|42|55243.44|0.07|0.02|R|F|1995-01-02|1994-11-09|1995-01-06|DELIVER IN PERSON|REG AIR|ously after the slyly regular +13281|87629|7630|1|27|43648.74|0.10|0.01|R|F|1992-08-01|1992-06-22|1992-08-16|DELIVER IN PERSON|TRUCK|lyly final deposits. slyly even ac +13281|168661|8662|2|50|86483.00|0.09|0.02|R|F|1992-06-04|1992-07-10|1992-06-30|DELIVER IN PERSON|REG AIR|usly against the carefully ir +13281|80721|722|3|27|45946.44|0.00|0.02|A|F|1992-05-09|1992-06-16|1992-05-13|DELIVER IN PERSON|RAIL|nic foxes wake fluffily regu +13282|67657|7658|1|17|27619.05|0.10|0.05|A|F|1992-09-01|1992-06-15|1992-09-15|TAKE BACK RETURN|TRUCK|ronic requests hag +13282|106580|9091|2|1|1586.58|0.08|0.03|R|F|1992-08-29|1992-08-03|1992-09-19|COLLECT COD|TRUCK|uriously silent deposits should integra +13282|74169|1691|3|34|38867.44|0.02|0.02|R|F|1992-07-04|1992-07-15|1992-07-30|TAKE BACK RETURN|RAIL|anent packages cajole packages. silentl +13282|151302|6333|4|7|9473.10|0.07|0.02|R|F|1992-09-06|1992-07-28|1992-09-07|NONE|TRUCK|fully bold asymptotes integrate +13282|125804|5805|5|8|14638.40|0.02|0.07|A|F|1992-05-14|1992-07-03|1992-06-04|COLLECT COD|FOB|ests. slyly ironic pinto beans after t +13282|181804|9359|6|28|52802.40|0.00|0.08|A|F|1992-09-04|1992-07-17|1992-09-22|DELIVER IN PERSON|REG AIR| regularly. blithely pending ideas affi +13283|173733|1285|1|37|66849.01|0.03|0.05|N|O|1998-04-07|1998-03-12|1998-04-26|COLLECT COD|FOB|en, regular excuses along the car +13283|115556|3090|2|12|18858.60|0.05|0.07|N|O|1998-02-18|1998-02-27|1998-02-25|TAKE BACK RETURN|SHIP| x-ray. final, e +13283|144293|6808|3|40|53491.60|0.03|0.06|N|O|1998-03-11|1998-03-02|1998-04-08|NONE|FOB|evenly. silen +13284|84502|2027|1|39|57973.50|0.00|0.03|R|F|1992-09-23|1992-10-10|1992-09-27|TAKE BACK RETURN|FOB|s courts wake regular accounts. carefully +13284|17785|5289|2|31|52786.18|0.01|0.05|A|F|1992-09-18|1992-10-29|1992-10-06|TAKE BACK RETURN|FOB| requests use fu +13284|100757|758|3|12|21093.00|0.01|0.00|R|F|1992-09-24|1992-11-04|1992-10-12|TAKE BACK RETURN|FOB|iously ironic ins +13284|14949|2453|4|20|37278.80|0.03|0.01|R|F|1992-11-21|1992-09-12|1992-12-18|DELIVER IN PERSON|TRUCK|lites wake. even requests +13285|63980|8993|1|5|9719.90|0.00|0.06|N|O|1995-07-26|1995-06-20|1995-08-12|DELIVER IN PERSON|TRUCK|lyly final reque +13286|156962|4508|1|1|2018.96|0.00|0.03|N|O|1995-10-28|1996-01-04|1995-11-25|NONE|FOB| the blithely bold deposits sleep speci +13286|48579|8580|2|5|7637.85|0.04|0.08|N|O|1996-01-11|1995-11-18|1996-01-28|DELIVER IN PERSON|REG AIR|efully express dependen +13286|63726|8739|3|46|77727.12|0.10|0.08|N|O|1996-01-18|1995-12-31|1996-01-21|DELIVER IN PERSON|REG AIR|c pinto beans. packages against the fur +13286|38720|3727|4|3|4976.16|0.09|0.06|N|O|1996-01-07|1995-12-22|1996-02-02|DELIVER IN PERSON|MAIL|eans. regular, exp +13287|100295|5316|1|3|3885.87|0.09|0.04|N|O|1997-07-06|1997-04-12|1997-07-15|DELIVER IN PERSON|FOB|gainst the regular asymptote +13287|57551|7552|2|34|51290.70|0.07|0.00|N|O|1997-05-26|1997-06-03|1997-06-08|NONE|REG AIR|pecial packages. packages sleep final ac +13287|46444|3957|3|13|18075.72|0.01|0.00|N|O|1997-03-23|1997-06-02|1997-04-20|NONE|RAIL|y ironic requests-- dependenc +13287|170942|943|4|16|32207.04|0.02|0.03|N|O|1997-03-17|1997-04-18|1997-03-19|TAKE BACK RETURN|REG AIR|s run quickly. qu +13287|11001|8505|5|41|37392.00|0.03|0.05|N|O|1997-06-16|1997-06-04|1997-07-11|DELIVER IN PERSON|FOB|ly fluffily enticing accounts. accounts +13287|91125|3635|6|8|8928.96|0.08|0.02|N|O|1997-06-15|1997-05-15|1997-07-12|DELIVER IN PERSON|SHIP| deposits sleep after the quic +13287|123011|5524|7|18|18612.18|0.05|0.01|N|O|1997-06-25|1997-05-14|1997-07-25|COLLECT COD|TRUCK|lly slyly regular escapades. pin +13312|31080|1081|1|12|12132.96|0.02|0.02|N|O|1997-01-27|1997-01-11|1997-02-23|TAKE BACK RETURN|FOB|ress requests wake. permanently final +13312|156097|1128|2|49|56501.41|0.10|0.03|N|O|1996-12-19|1997-01-15|1997-01-12|TAKE BACK RETURN|MAIL|ffix quickly p +13313|23380|887|1|36|46921.68|0.10|0.01|A|F|1994-10-19|1994-09-17|1994-11-13|NONE|REG AIR|uriously. slyly unusual +13313|139680|2194|2|19|32673.92|0.02|0.01|A|F|1994-10-04|1994-09-02|1994-11-01|NONE|MAIL|ily ironic ideas above the blithely unusua +13313|196897|4455|3|11|21932.79|0.00|0.08|R|F|1994-11-09|1994-09-13|1994-11-21|DELIVER IN PERSON|SHIP| carefully ironic deposits +13313|41034|6043|4|7|6825.21|0.05|0.01|A|F|1994-10-15|1994-08-17|1994-10-22|TAKE BACK RETURN|RAIL|unts. regular theodolit +13313|53701|6207|5|30|49641.00|0.00|0.02|R|F|1994-11-04|1994-09-03|1994-11-13|TAKE BACK RETURN|AIR|ular pinto beans +13313|138304|3331|6|47|63088.10|0.08|0.06|A|F|1994-10-06|1994-09-26|1994-10-09|DELIVER IN PERSON|RAIL|ously special theodolites nag quickly e +13313|73935|6443|7|37|70630.41|0.08|0.05|R|F|1994-11-05|1994-08-28|1994-11-27|DELIVER IN PERSON|MAIL|ent foxes thr +13314|8884|3885|1|41|73508.08|0.04|0.06|A|F|1994-06-05|1994-07-18|1994-06-07|TAKE BACK RETURN|RAIL|lithely regular accounts. even +13314|111786|6809|2|36|64720.08|0.05|0.08|A|F|1994-06-25|1994-08-02|1994-07-13|COLLECT COD|MAIL|after the fluffily express account +13314|183707|3708|3|12|21488.40|0.02|0.05|A|F|1994-06-24|1994-06-24|1994-07-18|TAKE BACK RETURN|AIR|tions sleep. unusual +13314|161050|8599|4|32|35553.60|0.03|0.07|A|F|1994-09-05|1994-07-23|1994-09-12|COLLECT COD|SHIP|al packages. blithely final packages +13314|162841|7874|5|1|1903.84|0.03|0.01|A|F|1994-07-25|1994-06-18|1994-08-20|NONE|RAIL| dolphins about +13314|66039|1052|6|46|46231.38|0.00|0.04|R|F|1994-08-20|1994-07-05|1994-09-12|TAKE BACK RETURN|RAIL|. dogged ideas x-ray slyly furiously +13315|69925|7444|1|22|41688.24|0.10|0.05|N|O|1996-12-27|1996-12-27|1997-01-14|DELIVER IN PERSON|SHIP|deposits use furiously across the +13315|23003|8008|2|27|25002.00|0.07|0.03|N|O|1997-01-03|1997-01-11|1997-01-20|TAKE BACK RETURN|REG AIR| the even foxes nag blit +13315|2408|7409|3|8|10483.20|0.00|0.05|N|O|1996-12-27|1997-01-01|1996-12-31|DELIVER IN PERSON|AIR|olites. careful +13315|56475|6476|4|43|61553.21|0.07|0.07|N|O|1996-12-10|1997-01-13|1997-01-02|COLLECT COD|RAIL|gle closely with the blithely bold req +13315|174435|4436|5|29|43773.47|0.03|0.06|N|O|1996-10-24|1996-11-15|1996-11-21|NONE|FOB|arefully final depo +13315|122968|5481|6|10|19909.60|0.07|0.03|N|O|1996-12-12|1996-12-20|1996-12-29|DELIVER IN PERSON|RAIL|equests. regular accoun +13316|107528|7529|1|1|1535.52|0.10|0.02|R|F|1993-01-26|1993-01-09|1993-02-22|NONE|AIR|gular foxes are fluffily around t +13316|11845|9349|2|43|75544.12|0.10|0.05|A|F|1993-01-25|1992-12-08|1993-02-08|DELIVER IN PERSON|TRUCK|ts detect furiously according to the exp +13317|120146|5171|1|22|25655.08|0.06|0.02|N|O|1996-04-25|1996-06-26|1996-05-16|COLLECT COD|MAIL|unts cajole bli +13317|77323|7324|2|13|16904.16|0.07|0.01|N|O|1996-07-08|1996-07-06|1996-07-17|TAKE BACK RETURN|SHIP|o the express, +13318|119497|2009|1|44|66725.56|0.06|0.02|N|O|1997-09-14|1997-08-03|1997-10-01|TAKE BACK RETURN|MAIL|ly among the +13318|169978|7527|2|50|102398.50|0.05|0.01|N|O|1997-06-16|1997-07-14|1997-07-03|TAKE BACK RETURN|RAIL| to the even, pending deposits +13318|8438|939|3|11|14810.73|0.02|0.05|N|O|1997-08-26|1997-08-19|1997-09-08|TAKE BACK RETURN|AIR| sometimes regular ex +13318|16915|1918|4|5|9159.55|0.03|0.07|N|O|1997-06-27|1997-07-21|1997-07-20|NONE|RAIL|ounts promise according to the blithe +13318|89041|4058|5|39|40171.56|0.01|0.02|N|O|1997-08-13|1997-07-16|1997-08-20|NONE|RAIL|epitaphs use sly +13318|111245|6268|6|16|20099.84|0.06|0.07|N|O|1997-07-15|1997-08-11|1997-07-19|DELIVER IN PERSON|TRUCK|y carefully express packages. r +13318|91096|8624|7|11|11957.99|0.00|0.06|N|O|1997-10-03|1997-08-11|1997-11-02|NONE|FOB|ess instruction +13319|37395|7396|1|8|10659.12|0.03|0.01|N|O|1996-04-25|1996-04-10|1996-05-16|COLLECT COD|SHIP|ld deposits nag. ironic i +13319|95479|7989|2|46|67825.62|0.06|0.00|N|O|1996-04-23|1996-04-17|1996-05-16|DELIVER IN PERSON|MAIL|lly excuses +13319|103702|1233|3|50|85285.00|0.04|0.07|N|O|1996-01-22|1996-04-12|1996-02-10|DELIVER IN PERSON|RAIL|losely final requests are sly +13344|62405|9924|1|17|23245.80|0.09|0.02|N|O|1997-04-07|1997-05-26|1997-04-19|NONE|REG AIR|the slyly regu +13344|32413|9923|2|5|6727.05|0.00|0.06|N|O|1997-04-05|1997-05-19|1997-04-17|DELIVER IN PERSON|TRUCK|ckages promise slyly fi +13344|154057|6573|3|30|33331.50|0.08|0.02|N|O|1997-07-17|1997-05-20|1997-08-15|DELIVER IN PERSON|AIR|sts. fluffily bold plate +13344|29892|4897|4|17|30972.13|0.04|0.01|N|O|1997-07-12|1997-05-21|1997-07-30|TAKE BACK RETURN|MAIL|counts wak +13345|54326|9337|1|16|20485.12|0.02|0.00|A|F|1992-10-25|1992-10-05|1992-10-26|NONE|AIR| final requests ca +13345|53468|8479|2|45|63965.70|0.04|0.06|R|F|1992-11-13|1992-11-29|1992-11-16|TAKE BACK RETURN|TRUCK|y final requests hag +13345|32113|9623|3|38|39714.18|0.04|0.08|R|F|1992-12-08|1992-10-11|1992-12-20|NONE|AIR|elets. carefully special requests sleep flu +13346|29815|4820|1|15|26172.15|0.05|0.04|A|F|1993-01-23|1993-01-17|1993-02-04|DELIVER IN PERSON|SHIP|ess accounts sleep s +13346|93803|8822|2|42|75465.60|0.00|0.01|R|F|1993-02-22|1993-01-29|1993-03-11|COLLECT COD|REG AIR|rbits about the e +13346|141116|1117|3|32|37027.52|0.05|0.08|A|F|1992-12-15|1993-01-28|1993-01-07|COLLECT COD|FOB|thely pending foxes haggle blithely. s +13346|131485|6512|4|26|39428.48|0.02|0.07|A|F|1993-01-05|1993-01-08|1993-02-02|COLLECT COD|RAIL|structions ab +13346|63527|3528|5|32|47696.64|0.08|0.06|R|F|1992-12-05|1993-01-17|1992-12-27|TAKE BACK RETURN|RAIL|ke regularly according to th +13346|81714|4223|6|8|13565.68|0.08|0.01|R|F|1993-01-13|1993-01-25|1993-01-19|NONE|RAIL|, special foxes nag carefu +13346|166844|4393|7|8|15286.72|0.04|0.00|A|F|1993-01-10|1992-12-20|1993-01-21|TAKE BACK RETURN|RAIL|ts; pending, p +13347|134053|1593|1|26|28263.30|0.07|0.05|A|F|1993-07-01|1993-07-13|1993-07-11|DELIVER IN PERSON|REG AIR|ronic deposits +13347|12809|7812|2|44|75759.20|0.09|0.06|R|F|1993-05-13|1993-06-07|1993-05-26|DELIVER IN PERSON|FOB| furiously +13347|78763|3778|3|30|52252.80|0.02|0.05|A|F|1993-06-13|1993-05-28|1993-07-07|DELIVER IN PERSON|RAIL|regular depo +13347|155171|7687|4|39|47820.63|0.10|0.07|A|F|1993-06-20|1993-06-06|1993-06-28|COLLECT COD|RAIL|ang slyly after the regular foxes. stealt +13347|154579|4580|5|34|55541.38|0.05|0.03|A|F|1993-08-10|1993-07-09|1993-08-15|DELIVER IN PERSON|RAIL| requests nag. sentiments sleep fluffily. +13347|197839|359|6|11|21305.13|0.10|0.07|R|F|1993-05-23|1993-06-24|1993-06-13|COLLECT COD|FOB|lar excuses. unusual requests use sly +13348|6866|4367|1|11|19501.46|0.10|0.06|R|F|1993-11-22|1994-01-24|1993-12-10|TAKE BACK RETURN|RAIL|lithely about the blithely even d +13348|182702|2703|2|19|33909.30|0.06|0.01|R|F|1993-11-26|1993-12-23|1993-12-03|NONE|REG AIR|l accounts. slyly regular ideas are b +13348|65644|657|3|1|1609.64|0.08|0.01|R|F|1993-12-02|1994-01-20|1993-12-12|NONE|TRUCK|instructions c +13348|69169|1676|4|15|17072.40|0.03|0.03|A|F|1993-12-19|1993-12-26|1994-01-06|COLLECT COD|RAIL|ffily. furiously bold instructions +13348|110833|8367|5|28|51627.24|0.08|0.06|R|F|1994-02-02|1994-01-15|1994-02-26|NONE|AIR|gle daring plate +13349|198325|5883|1|20|28466.40|0.06|0.08|A|F|1994-09-28|1994-11-02|1994-10-14|DELIVER IN PERSON|MAIL|usly. quickly pending d +13349|44634|7139|2|40|63145.20|0.04|0.02|A|F|1994-11-03|1994-11-30|1994-12-01|NONE|REG AIR|uests. even accounts p +13350|174351|9386|1|49|69842.15|0.05|0.08|N|O|1998-09-04|1998-07-09|1998-09-24|NONE|TRUCK| the fluffily final packages haggle bl +13350|109521|2032|2|31|47446.12|0.08|0.07|N|O|1998-06-29|1998-07-29|1998-07-24|NONE|FOB|al pinto beans haggle along the sile +13350|108285|3306|3|2|2586.56|0.09|0.02|N|O|1998-07-10|1998-06-08|1998-07-31|COLLECT COD|AIR|according +13350|132976|516|4|39|78349.83|0.08|0.07|N|O|1998-08-13|1998-08-01|1998-08-29|COLLECT COD|AIR| wake. ironic waters nag acr +13350|122830|5343|5|35|64849.05|0.08|0.01|N|O|1998-05-25|1998-06-29|1998-06-02|COLLECT COD|MAIL|ans instead of the slyly pending d +13350|193719|3720|6|24|43505.04|0.00|0.08|N|O|1998-08-19|1998-07-12|1998-09-12|TAKE BACK RETURN|MAIL|e requests. pending excus +13351|18549|6053|1|42|61636.68|0.02|0.07|R|F|1993-08-19|1993-07-19|1993-08-26|NONE|FOB|uickly even deposits doubt slyly +13351|146543|1572|2|31|49275.74|0.06|0.08|R|F|1993-05-16|1993-06-06|1993-06-12|DELIVER IN PERSON|AIR|. blithely p +13351|142597|5112|3|4|6558.36|0.10|0.01|A|F|1993-08-08|1993-07-14|1993-09-07|TAKE BACK RETURN|AIR|evenly ironic i +13351|22323|4826|4|29|36114.28|0.09|0.05|A|F|1993-08-30|1993-07-07|1993-09-02|DELIVER IN PERSON|REG AIR|fluffily after the quickly ironic reque +13351|172027|7062|5|42|46158.84|0.05|0.03|A|F|1993-07-02|1993-07-14|1993-07-27|DELIVER IN PERSON|RAIL|ly unusual packages are about the quick +13351|43044|5549|6|7|6909.28|0.02|0.08|R|F|1993-09-03|1993-06-16|1993-09-21|TAKE BACK RETURN|SHIP| accounts. furiously even dependencies ha +13376|39894|9895|1|43|78857.27|0.09|0.06|A|F|1992-10-20|1992-12-22|1992-10-22|NONE|SHIP|t the ironic deposits. blithe +13376|92575|5085|2|17|26648.69|0.02|0.08|A|F|1992-11-02|1992-11-19|1992-11-04|DELIVER IN PERSON|RAIL|egular theodoli +13376|91732|4242|3|27|46540.71|0.10|0.01|A|F|1992-12-28|1992-12-07|1993-01-23|NONE|MAIL|ns are carefully caref +13376|138043|5583|4|28|30269.12|0.08|0.07|A|F|1992-12-27|1993-01-03|1993-01-16|NONE|REG AIR|lithely furio +13376|72929|7944|5|25|47548.00|0.05|0.06|A|F|1993-01-06|1993-01-01|1993-01-21|DELIVER IN PERSON|TRUCK|al, unusual packages unw +13376|111863|6886|6|37|69369.82|0.00|0.00|A|F|1992-10-14|1992-11-17|1992-11-06|COLLECT COD|AIR|ckages. final requests wake +13377|71563|1564|1|35|53709.60|0.03|0.07|N|O|1995-11-15|1995-09-06|1995-11-28|COLLECT COD|TRUCK|press dolph +13377|147329|9844|2|1|1376.32|0.02|0.00|N|O|1995-11-17|1995-09-30|1995-12-07|DELIVER IN PERSON|AIR|lthy excuses. +13378|125772|797|1|37|66517.49|0.08|0.07|A|F|1994-09-30|1994-12-10|1994-10-25|TAKE BACK RETURN|AIR|haggle slyly. blithely bold instruct +13378|40204|5213|2|2|2288.40|0.04|0.01|A|F|1994-09-30|1994-12-09|1994-10-05|COLLECT COD|REG AIR|the thin packages. f +13378|98970|6498|3|50|98448.50|0.10|0.08|A|F|1994-10-18|1994-11-21|1994-11-09|TAKE BACK RETURN|FOB|kages sleep final, silent pack +13378|174226|9261|4|21|27304.62|0.03|0.01|R|F|1994-10-11|1994-11-07|1994-11-02|DELIVER IN PERSON|MAIL|blithely final foxes x-ray quick +13378|9127|1628|5|37|38336.44|0.06|0.07|A|F|1994-10-03|1994-11-11|1994-10-17|TAKE BACK RETURN|FOB| fluffy asymptotes sleep furiously +13379|152325|7356|1|40|55092.80|0.04|0.07|R|F|1994-02-01|1993-12-14|1994-03-03|DELIVER IN PERSON|RAIL|y regular packages. s +13379|119146|9147|2|8|9321.12|0.05|0.00|R|F|1993-12-05|1993-12-25|1993-12-26|DELIVER IN PERSON|RAIL|y bold deposits +13379|82304|4813|3|2|2572.60|0.04|0.02|R|F|1993-11-26|1994-01-26|1993-12-14|COLLECT COD|SHIP|l deposits. special realms sleep fluffil +13379|66717|1730|4|24|40409.04|0.04|0.03|A|F|1994-03-08|1994-01-11|1994-03-29|COLLECT COD|SHIP|ong the blithely silent packages. +13380|185482|8001|1|14|21944.72|0.09|0.00|R|F|1994-09-29|1994-09-11|1994-10-05|NONE|RAIL|ding to the requests. carefully ironi +13380|193606|6126|2|5|8498.00|0.02|0.06|A|F|1994-10-06|1994-09-30|1994-10-11|TAKE BACK RETURN|REG AIR|s after the carefu +13380|129993|7530|3|21|42482.79|0.09|0.05|A|F|1994-10-20|1994-08-24|1994-11-01|DELIVER IN PERSON|FOB| regular theodolites +13380|184303|6822|4|43|59653.90|0.08|0.07|R|F|1994-07-17|1994-08-29|1994-07-21|TAKE BACK RETURN|REG AIR|lets. even at +13381|79903|7425|1|32|60252.80|0.01|0.04|N|O|1995-10-14|1995-09-28|1995-11-13|TAKE BACK RETURN|MAIL|ly final requests dete +13381|120007|7544|2|29|29783.00|0.07|0.05|N|O|1995-08-28|1995-09-17|1995-09-16|COLLECT COD|MAIL|ilent orbits along the fluffily unusual +13381|150062|63|3|12|13344.72|0.10|0.03|N|O|1995-12-12|1995-10-14|1995-12-14|COLLECT COD|MAIL|y. carefully special requests ca +13382|54279|6785|1|27|33298.29|0.02|0.05|N|O|1996-02-16|1996-01-14|1996-02-24|TAKE BACK RETURN|RAIL|er blithely bl +13382|66557|9064|2|15|22853.25|0.03|0.02|N|O|1996-02-22|1995-12-02|1996-03-04|COLLECT COD|FOB|tions. even, pending foxes integrat +13382|7359|7360|3|1|1266.35|0.09|0.08|N|O|1996-01-05|1996-01-16|1996-01-18|DELIVER IN PERSON|AIR|s detect closely a +13383|72424|9946|1|36|50271.12|0.09|0.07|R|F|1992-10-03|1992-07-21|1992-10-15|NONE|TRUCK|hely idle foxes +13383|26208|1213|2|30|34026.00|0.00|0.06|R|F|1992-07-01|1992-08-12|1992-07-04|DELIVER IN PERSON|FOB|y. regular, even excuses aff +13383|68836|8837|3|44|79412.52|0.07|0.01|A|F|1992-08-16|1992-08-07|1992-08-18|DELIVER IN PERSON|MAIL|osits after the fluffily final packages +13383|112631|165|4|6|9861.78|0.03|0.03|A|F|1992-06-18|1992-07-31|1992-07-12|COLLECT COD|FOB|y slowly carefully i +13408|39713|9714|1|34|56192.14|0.05|0.04|R|F|1994-06-04|1994-04-24|1994-07-03|DELIVER IN PERSON|SHIP|. carefully pending accounts according +13408|48560|3569|2|32|48273.92|0.07|0.07|A|F|1994-04-27|1994-04-12|1994-05-18|TAKE BACK RETURN|MAIL|symptotes haggle around the ironic +13408|137184|9698|3|20|24423.60|0.06|0.01|R|F|1994-06-02|1994-05-10|1994-06-14|NONE|FOB|blithely un +13408|34970|4971|4|40|76198.80|0.01|0.07|A|F|1994-06-11|1994-05-13|1994-07-08|COLLECT COD|MAIL|l requests hang silently. sile +13408|131208|6235|5|40|49568.00|0.05|0.02|R|F|1994-05-04|1994-04-19|1994-05-22|COLLECT COD|REG AIR|ly special +13409|178581|3616|1|28|46468.24|0.06|0.05|R|F|1993-08-30|1993-09-27|1993-09-10|NONE|AIR|regular accounts-- final decoys pri +13410|131558|4072|1|4|6358.20|0.08|0.02|A|F|1993-09-10|1993-07-20|1993-09-17|COLLECT COD|TRUCK|st carefully across the unusual a +13410|90100|7628|2|12|13081.20|0.08|0.05|A|F|1993-09-18|1993-08-10|1993-09-25|COLLECT COD|RAIL|carefully ironic requests haggl +13410|104793|2324|3|1|1797.79|0.09|0.06|A|F|1993-08-24|1993-07-21|1993-09-15|DELIVER IN PERSON|REG AIR|deposits. ruthless, u +13410|50875|5886|4|32|58427.84|0.08|0.08|A|F|1993-09-13|1993-08-19|1993-09-22|COLLECT COD|MAIL|s nag furiously quickly final in +13411|137967|7968|1|21|42104.16|0.03|0.03|R|F|1994-07-22|1994-05-18|1994-07-26|COLLECT COD|AIR| packages hag +13411|5374|375|2|4|5117.48|0.06|0.01|R|F|1994-07-25|1994-06-16|1994-08-23|TAKE BACK RETURN|MAIL|ipliers. quietly ironic instructions +13411|104310|9331|3|22|28914.82|0.04|0.00|A|F|1994-06-29|1994-05-27|1994-07-07|COLLECT COD|TRUCK| special platelets. accounts ac +13411|132974|5488|4|26|52181.22|0.04|0.05|R|F|1994-07-17|1994-05-19|1994-08-13|NONE|MAIL|arefully special ideas. b +13411|79657|7179|5|29|47462.85|0.09|0.06|R|F|1994-08-05|1994-06-14|1994-08-12|TAKE BACK RETURN|TRUCK| ironic pl +13412|120961|3474|1|49|97116.04|0.09|0.03|N|O|1997-09-04|1997-09-12|1997-09-16|DELIVER IN PERSON|FOB|ges about the car +13412|189355|9356|2|39|56329.65|0.09|0.01|N|O|1997-09-26|1997-09-30|1997-10-24|TAKE BACK RETURN|SHIP|pending pinto beans cajole expr +13413|89034|9035|1|47|48082.41|0.05|0.01|A|F|1993-03-12|1993-03-28|1993-03-22|NONE|REG AIR|ccounts sleep carefully +13413|184100|6619|2|3|3552.30|0.06|0.02|R|F|1993-03-28|1993-03-29|1993-04-11|TAKE BACK RETURN|FOB|egular foxes belie +13413|154497|2043|3|44|68265.56|0.10|0.01|A|F|1993-02-21|1993-03-04|1993-03-11|DELIVER IN PERSON|FOB|g. slyly r +13413|24452|4453|4|46|63316.70|0.08|0.03|R|F|1993-05-08|1993-04-25|1993-05-09|TAKE BACK RETURN|REG AIR|lent theodolites haggle ca +13413|157166|2197|5|26|31802.16|0.06|0.06|R|F|1993-04-01|1993-03-13|1993-04-19|TAKE BACK RETURN|SHIP| boldly express dinos +13414|5288|289|1|10|11932.80|0.01|0.07|N|O|1995-07-28|1995-08-24|1995-08-10|TAKE BACK RETURN|FOB|otes use qu +13414|73234|8249|2|1|1207.23|0.04|0.02|N|O|1995-10-27|1995-08-21|1995-11-10|DELIVER IN PERSON|TRUCK|ets detect alo +13414|27491|4998|3|30|42554.70|0.07|0.07|N|O|1995-07-15|1995-08-25|1995-08-10|NONE|MAIL|cuses. blithely iro +13414|28556|8557|4|35|51959.25|0.02|0.01|N|O|1995-08-24|1995-08-07|1995-08-28|NONE|AIR|usual packages. even +13414|134362|6876|5|45|62836.20|0.05|0.04|N|O|1995-08-02|1995-08-08|1995-08-12|NONE|REG AIR|ions cajole blithely. car +13415|130737|8277|1|19|33586.87|0.02|0.01|N|O|1997-06-18|1997-08-05|1997-07-06|NONE|FOB| the packages. regular account +13415|90295|2805|2|16|20564.64|0.03|0.01|N|O|1997-07-30|1997-08-25|1997-08-14|DELIVER IN PERSON|REG AIR|osits sleep +13415|183846|8883|3|2|3859.68|0.01|0.00|N|O|1997-07-05|1997-08-07|1997-07-16|DELIVER IN PERSON|MAIL| final accounts +13415|95662|5663|4|31|51387.46|0.07|0.05|N|O|1997-09-26|1997-08-01|1997-10-06|DELIVER IN PERSON|MAIL|ccounts should have to w +13415|190275|5314|5|32|43688.64|0.04|0.04|N|O|1997-09-06|1997-08-28|1997-09-10|DELIVER IN PERSON|AIR|s. express ac +13415|138134|5674|6|44|51573.72|0.04|0.03|N|O|1997-06-27|1997-07-31|1997-07-16|TAKE BACK RETURN|MAIL|tructions. fluffily bold asy +13415|16408|3912|7|45|59598.00|0.01|0.00|N|O|1997-07-06|1997-08-09|1997-07-07|TAKE BACK RETURN|FOB|riously regular packages nag around the sl +13440|163059|5576|1|17|19074.85|0.08|0.02|R|F|1994-01-25|1993-11-15|1994-02-14|TAKE BACK RETURN|RAIL|e carefully. +13441|26849|1854|1|2|3551.68|0.06|0.07|N|O|1995-10-22|1995-10-03|1995-11-12|NONE|TRUCK|tions. requests at the car +13441|39363|6873|2|46|59908.56|0.05|0.02|N|O|1995-11-14|1995-11-29|1995-11-27|DELIVER IN PERSON|RAIL|cies. quickly regular asymptotes +13442|115498|8010|1|45|68107.05|0.10|0.04|N|O|1997-11-13|1997-09-25|1997-11-19|COLLECT COD|REG AIR| instruction +13442|170248|7800|2|3|3954.72|0.01|0.04|N|O|1997-11-24|1997-09-25|1997-12-18|NONE|REG AIR|ickly regular theodolites. fu +13442|151658|9204|3|46|78643.90|0.02|0.07|N|O|1997-11-20|1997-10-11|1997-11-24|NONE|FOB|ke carefully aft +13442|113393|5905|4|22|30940.58|0.09|0.01|N|O|1997-10-17|1997-09-28|1997-10-29|COLLECT COD|FOB|ironic dinos. stealthily even ideas ha +13443|195394|7914|1|14|20851.46|0.01|0.00|A|F|1994-01-23|1993-11-14|1994-01-27|COLLECT COD|AIR|ide of the final packages. slow +13443|170463|5498|2|36|55204.56|0.03|0.07|A|F|1993-11-19|1993-12-27|1993-11-28|TAKE BACK RETURN|MAIL|ublate along the furiously pending +13443|158027|3058|3|23|24955.46|0.07|0.06|R|F|1994-01-29|1993-11-15|1994-01-31|COLLECT COD|RAIL| across the eve +13443|157864|2895|4|21|40359.06|0.03|0.05|A|F|1994-01-24|1993-12-13|1994-02-18|NONE|SHIP|l ideas are sl +13443|4317|1818|5|20|24426.20|0.03|0.00|R|F|1993-10-29|1993-11-26|1993-11-19|DELIVER IN PERSON|SHIP|uests according to the slyly fi +13443|143237|780|6|13|16642.99|0.02|0.07|A|F|1993-10-22|1993-12-29|1993-10-25|NONE|REG AIR|unts. requests sleep f +13443|176092|6093|7|17|19857.53|0.04|0.06|R|F|1993-11-13|1993-12-18|1993-11-14|COLLECT COD|TRUCK|hlessly unusual asymptotes. quick +13444|175368|5369|1|22|31753.92|0.05|0.01|A|F|1992-04-09|1992-03-02|1992-04-18|COLLECT COD|TRUCK|ep slyly above the special +13444|197889|7890|2|48|95370.24|0.05|0.04|A|F|1992-04-29|1992-02-08|1992-05-20|COLLECT COD|AIR|ickly even accounts. +13444|118739|6273|3|12|21092.76|0.06|0.08|R|F|1992-03-21|1992-02-13|1992-04-03|DELIVER IN PERSON|MAIL|hely at the e +13444|39643|7153|4|5|7913.20|0.04|0.07|A|F|1992-01-15|1992-04-01|1992-01-17|NONE|REG AIR|quests. fluffily final packages +13444|73626|8641|5|38|60785.56|0.04|0.01|A|F|1992-01-24|1992-03-13|1992-02-18|DELIVER IN PERSON|REG AIR|foxes about the carefully pen +13444|26739|4246|6|36|59966.28|0.05|0.05|R|F|1992-04-25|1992-02-19|1992-05-13|COLLECT COD|TRUCK|ly, special packages. regular reque +13444|185975|5976|7|35|72133.95|0.09|0.03|A|F|1992-01-20|1992-04-04|1992-02-19|DELIVER IN PERSON|TRUCK|y. final asymptotes believe finally. +13445|80153|154|1|14|15864.10|0.09|0.00|N|O|1998-01-15|1998-03-10|1998-02-11|COLLECT COD|REG AIR|lly above the blithely +13446|196044|1083|1|13|14820.52|0.02|0.00|N|O|1996-06-28|1996-04-17|1996-07-21|DELIVER IN PERSON|AIR|ular deposits. blithely regular acco +13446|97688|198|2|17|28656.56|0.02|0.02|N|O|1996-06-03|1996-05-13|1996-06-29|COLLECT COD|FOB|ly along the fluf +13447|160203|7752|1|45|56844.00|0.01|0.08|A|F|1993-02-06|1993-02-09|1993-03-05|NONE|FOB|ckly about the furiously ironi +13472|75219|7727|1|30|35826.30|0.08|0.04|N|O|1995-11-17|1995-12-17|1995-12-02|TAKE BACK RETURN|RAIL|pinto bean +13472|195930|8450|2|3|6077.79|0.06|0.02|N|O|1996-02-19|1996-01-09|1996-03-15|DELIVER IN PERSON|AIR|slyly after the carefully +13472|184551|2106|3|9|14719.95|0.01|0.06|N|O|1995-11-22|1995-12-08|1995-12-11|DELIVER IN PERSON|REG AIR|riously pending packages +13473|101995|1996|1|2|3993.98|0.06|0.05|N|O|1996-03-27|1996-05-09|1996-04-12|DELIVER IN PERSON|TRUCK|according to the carefully even idea +13473|16677|6678|2|13|20717.71|0.08|0.05|N|O|1996-06-26|1996-06-08|1996-06-30|DELIVER IN PERSON|MAIL|gular sheave +13473|73779|8794|3|27|47324.79|0.05|0.06|N|O|1996-07-11|1996-05-17|1996-07-18|DELIVER IN PERSON|SHIP|luffy tithes hagg +13473|196111|8631|4|18|21727.98|0.08|0.05|N|O|1996-05-27|1996-05-23|1996-05-28|COLLECT COD|AIR|into beans. b +13473|20902|903|5|19|34635.10|0.06|0.00|N|O|1996-04-26|1996-05-15|1996-05-22|COLLECT COD|AIR| promise abo +13473|89493|9494|6|46|68194.54|0.06|0.04|N|O|1996-06-03|1996-05-08|1996-06-16|NONE|AIR|wake fluffily +13474|69662|9663|1|20|32633.20|0.04|0.04|N|O|1997-06-13|1997-07-09|1997-06-18|DELIVER IN PERSON|TRUCK|heodolites detect +13474|5774|5775|2|37|62151.49|0.05|0.04|N|O|1997-06-27|1997-08-13|1997-07-22|NONE|SHIP|al waters. blithely final pinto beans nag c +13474|27551|7552|3|30|44356.50|0.09|0.07|N|O|1997-07-11|1997-07-10|1997-07-24|NONE|TRUCK|nal, ironic instructions are bravely acc +13475|166185|6186|1|45|56303.10|0.04|0.04|A|F|1994-07-19|1994-07-29|1994-07-28|NONE|FOB|y ironic accounts integrate qu +13475|57505|2516|2|45|65812.50|0.07|0.05|A|F|1994-08-09|1994-07-13|1994-08-20|DELIVER IN PERSON|FOB|ly final warthogs along the car +13475|75395|2917|3|36|49334.04|0.02|0.03|R|F|1994-09-16|1994-08-07|1994-09-18|NONE|SHIP|ong the carefully even theodol +13475|146977|2006|4|22|44527.34|0.07|0.04|A|F|1994-06-25|1994-08-28|1994-07-02|TAKE BACK RETURN|RAIL|lar accounts. eve +13475|28022|8023|5|12|11400.24|0.09|0.01|A|F|1994-07-05|1994-08-01|1994-07-11|DELIVER IN PERSON|REG AIR|y. bold foxes sleep. slyly permanent pla +13475|155318|349|6|24|32959.44|0.03|0.03|A|F|1994-06-19|1994-08-02|1994-07-01|DELIVER IN PERSON|TRUCK| the thinly reg +13475|14441|6943|7|22|29819.68|0.03|0.04|A|F|1994-10-04|1994-08-26|1994-10-31|NONE|SHIP|ular theodolites. bli +13476|103419|3420|1|10|14224.10|0.05|0.05|A|F|1994-01-25|1993-12-07|1994-01-26|DELIVER IN PERSON|MAIL|ly even ideas. +13476|148734|1249|2|30|53481.90|0.09|0.06|R|F|1994-01-30|1993-12-04|1994-02-04|DELIVER IN PERSON|TRUCK| regular requests. caref +13476|161390|3907|3|38|55152.82|0.09|0.00|R|F|1994-02-08|1993-12-27|1994-02-09|NONE|AIR|blithely special ideas haggle fluffi +13476|69597|7116|4|29|45431.11|0.06|0.04|R|F|1993-12-21|1993-12-18|1994-01-05|NONE|MAIL|osits. slyly ironic asymptotes w +13476|101327|6348|5|40|53132.80|0.05|0.06|A|F|1993-12-20|1993-11-25|1994-01-07|DELIVER IN PERSON|RAIL|nto beans are carefully atop the +13476|199041|6599|6|41|46741.64|0.02|0.06|A|F|1994-01-01|1993-12-16|1994-01-11|DELIVER IN PERSON|SHIP|ecial accou +13477|16060|3564|1|14|13664.84|0.01|0.01|N|O|1998-03-22|1998-02-13|1998-04-06|NONE|MAIL|ic foxes wake slyly. final accounts haggl +13477|116094|8606|2|2|2220.18|0.03|0.04|N|O|1997-12-27|1998-01-14|1998-01-17|NONE|AIR|s. quickly special accounts are f +13477|188689|3726|3|23|40886.64|0.03|0.05|N|O|1998-02-05|1998-02-14|1998-02-16|DELIVER IN PERSON|REG AIR| are blithely. regular requests sleep abo +13477|95807|826|4|19|34253.20|0.07|0.06|N|O|1998-02-23|1998-01-27|1998-03-16|NONE|RAIL|requests boost slyly flu +13477|19071|1573|5|46|45543.22|0.00|0.00|N|O|1997-12-20|1998-01-03|1998-01-02|NONE|SHIP|gle slyly silent warhorses. +13478|151749|6780|1|28|50420.72|0.06|0.06|N|O|1998-01-16|1998-03-08|1998-02-09|COLLECT COD|MAIL|e carefully. slyly express +13478|44074|9083|2|50|50903.50|0.09|0.00|N|O|1998-03-20|1998-02-10|1998-04-01|NONE|AIR|n requests across th +13478|148149|8150|3|18|21548.52|0.10|0.08|N|O|1998-04-23|1998-03-06|1998-05-10|COLLECT COD|MAIL|es. slyly final requests ag +13478|135582|3122|4|22|35586.76|0.06|0.04|N|O|1998-04-21|1998-03-23|1998-04-25|NONE|TRUCK|lphins use. fi +13478|117643|5177|5|15|24909.60|0.08|0.03|N|O|1998-02-08|1998-03-26|1998-02-27|COLLECT COD|SHIP|uests. ironically express dolphins +13479|144067|1610|1|28|31109.68|0.06|0.08|R|F|1995-02-16|1995-01-19|1995-03-07|TAKE BACK RETURN|SHIP|al ideas. unu +13479|119189|4212|2|18|21747.24|0.06|0.03|A|F|1995-04-04|1995-02-10|1995-04-18|COLLECT COD|FOB|lly ironic pack +13479|195370|2928|3|22|32238.14|0.07|0.06|A|F|1995-02-20|1995-01-24|1995-03-17|COLLECT COD|MAIL|fully slyly final courts. carefull +13479|179825|9826|4|34|64763.88|0.08|0.06|A|F|1995-03-11|1995-02-02|1995-03-21|NONE|RAIL|he furiously express packa +13479|112408|4920|5|16|22726.40|0.08|0.08|R|F|1995-02-06|1995-01-06|1995-02-28|TAKE BACK RETURN|SHIP|regular requests. silent, final accounts a +13504|132116|7143|1|26|29850.86|0.02|0.04|N|O|1997-10-02|1997-08-17|1997-10-06|NONE|RAIL|nent deposits. slyly final dependencies ca +13504|66225|6226|2|5|5956.10|0.00|0.06|N|O|1997-08-02|1997-09-07|1997-08-27|TAKE BACK RETURN|AIR|inal, regular de +13504|37439|4949|3|41|56433.63|0.07|0.00|N|O|1997-06-19|1997-07-19|1997-06-25|NONE|RAIL|ect about the qui +13504|23276|8281|4|31|37177.37|0.02|0.08|N|O|1997-06-24|1997-08-28|1997-06-26|DELIVER IN PERSON|AIR|alongside of t +13505|197359|2398|1|6|8738.10|0.02|0.02|N|O|1997-06-09|1997-08-06|1997-06-19|TAKE BACK RETURN|FOB|nding, regular ideas ab +13505|12655|7658|2|22|34488.30|0.03|0.08|N|O|1997-08-14|1997-07-05|1997-08-31|DELIVER IN PERSON|TRUCK|foxes doubt furiously. ideas serve quickly +13505|82401|9926|3|32|44268.80|0.10|0.05|N|O|1997-08-13|1997-07-27|1997-09-09|NONE|AIR|unusual ideas +13505|99029|4048|4|40|41120.80|0.05|0.05|N|O|1997-07-23|1997-07-17|1997-08-08|COLLECT COD|AIR|ven theodolites about the q +13505|164725|7242|5|39|69799.08|0.08|0.02|N|O|1997-09-11|1997-08-03|1997-10-02|COLLECT COD|MAIL|heodolites integrate furiou +13506|104014|6525|1|12|12216.12|0.02|0.00|N|O|1995-10-03|1995-10-03|1995-10-04|TAKE BACK RETURN|RAIL|es. even, ironic packa +13506|147678|193|2|18|31062.06|0.06|0.01|N|O|1995-08-24|1995-08-30|1995-09-16|DELIVER IN PERSON|MAIL|ove the slyly stealthy instructions +13506|18601|6105|3|48|72940.80|0.02|0.01|N|O|1995-09-24|1995-09-21|1995-09-26|NONE|TRUCK| pending theodolites cajole furi +13506|11296|1297|4|25|30182.25|0.06|0.04|N|O|1995-10-18|1995-10-15|1995-11-12|DELIVER IN PERSON|TRUCK|ly final deposits na +13507|67193|4712|1|11|12762.09|0.07|0.07|A|F|1993-02-16|1993-02-04|1993-03-03|TAKE BACK RETURN|TRUCK| silent packages wake quickly a +13507|105998|3529|2|47|94187.53|0.10|0.08|A|F|1993-01-16|1993-02-05|1993-02-09|DELIVER IN PERSON|MAIL|ts. quickly regular depos +13507|103038|569|3|30|31230.90|0.04|0.03|A|F|1993-02-13|1993-01-30|1993-03-09|DELIVER IN PERSON|RAIL|nts hang slyly against the +13507|148644|3673|4|22|37238.08|0.09|0.03|R|F|1993-01-11|1993-02-24|1993-02-03|NONE|FOB|. fluffily ironic gifts wake quickly boldl +13508|169529|4562|1|2|3197.04|0.10|0.03|N|O|1997-07-18|1997-07-15|1997-07-24|TAKE BACK RETURN|TRUCK|ounts. furiou +13509|89079|9080|1|39|41654.73|0.03|0.01|N|O|1997-01-04|1996-12-30|1997-01-16|COLLECT COD|REG AIR|fully quic +13510|105808|8319|1|22|39903.60|0.06|0.02|N|O|1998-01-16|1997-12-03|1998-01-17|TAKE BACK RETURN|FOB|osits along the even +13510|113340|8363|2|29|39246.86|0.08|0.05|N|O|1998-01-15|1997-11-14|1998-01-24|TAKE BACK RETURN|RAIL|theodolites. furiously iron +13510|97091|7092|3|16|17409.44|0.01|0.05|N|O|1998-01-25|1997-11-18|1998-01-30|COLLECT COD|REG AIR|es use blithely after the cl +13511|57644|150|1|42|67268.88|0.00|0.01|N|O|1998-03-24|1998-02-28|1998-04-19|COLLECT COD|RAIL|c accounts nag carefully. slyly fin +13511|9609|4610|2|29|44039.40|0.05|0.04|N|O|1998-02-16|1998-03-24|1998-03-10|NONE|TRUCK| ironic requests are quickly fur +13511|92290|2291|3|4|5129.16|0.00|0.07|N|O|1998-03-21|1998-02-23|1998-03-30|TAKE BACK RETURN|REG AIR|wake according to the pinto beans. fina +13511|115367|5368|4|13|17970.68|0.10|0.02|N|O|1998-02-08|1998-03-01|1998-02-22|DELIVER IN PERSON|FOB| packages. carefull +13511|157164|2195|5|16|19538.56|0.02|0.00|N|O|1998-04-20|1998-03-30|1998-05-01|NONE|RAIL|s requests haggle furiously final asymptote +13536|5520|8021|1|19|27084.88|0.10|0.06|R|F|1994-10-04|1994-09-24|1994-10-24|NONE|MAIL|l tithes. furiously ironic accou +13536|163196|3197|2|25|31479.75|0.01|0.00|A|F|1994-11-23|1994-10-09|1994-12-07|COLLECT COD|AIR|ly even frets nag regular, +13536|22637|2638|3|36|56146.68|0.10|0.07|A|F|1994-11-09|1994-09-19|1994-11-12|NONE|REG AIR|elets. final theodolites alongside of the +13536|57542|48|4|37|55482.98|0.03|0.04|R|F|1994-09-24|1994-09-27|1994-09-28|DELIVER IN PERSON|REG AIR|accounts. slyly +13536|93653|3654|5|20|32933.00|0.06|0.01|A|F|1994-10-25|1994-10-12|1994-11-19|TAKE BACK RETURN|RAIL|y deposits pro +13536|11319|6322|6|8|9842.48|0.02|0.08|R|F|1994-10-21|1994-10-06|1994-10-24|DELIVER IN PERSON|MAIL| slyly carefully express acco +13537|48059|3068|1|20|20141.00|0.08|0.04|R|F|1993-07-29|1993-07-25|1993-08-22|TAKE BACK RETURN|MAIL|grate blithely about the ironic de +13538|35956|3466|1|49|92705.55|0.02|0.06|N|O|1997-05-23|1997-03-08|1997-06-05|DELIVER IN PERSON|SHIP|against the foxes haggle bli +13538|109611|9612|2|1|1620.61|0.07|0.07|N|O|1997-02-12|1997-03-12|1997-02-27|DELIVER IN PERSON|MAIL|ng about the regular, ir +13539|49694|9695|1|15|24655.35|0.10|0.00|N|O|1997-05-08|1997-03-29|1997-05-30|NONE|RAIL|y among the sly +13539|3551|8552|2|47|68363.85|0.09|0.01|N|O|1997-04-13|1997-04-28|1997-04-30|TAKE BACK RETURN|AIR|heodolites integ +13539|74618|7126|3|11|17518.71|0.01|0.04|N|O|1997-03-19|1997-05-12|1997-03-25|TAKE BACK RETURN|MAIL|egular, regular theodoli +13539|100101|5122|4|50|55055.00|0.06|0.04|N|O|1997-02-15|1997-04-27|1997-03-10|TAKE BACK RETURN|FOB|as use quic +13539|194753|9792|5|35|64671.25|0.01|0.01|N|O|1997-03-11|1997-04-01|1997-04-07|COLLECT COD|MAIL|omas sleep daringly. blithely regular exc +13539|5642|8143|6|4|6190.56|0.04|0.04|N|O|1997-02-24|1997-04-18|1997-03-12|COLLECT COD|FOB|ar, pending excuses around the careful +13540|88303|812|1|25|32282.50|0.10|0.02|R|F|1993-06-02|1993-08-02|1993-06-29|TAKE BACK RETURN|MAIL|ily final deposits cajo +13540|95382|5383|2|44|60604.72|0.06|0.08|R|F|1993-07-01|1993-07-19|1993-07-16|TAKE BACK RETURN|MAIL|ckages x-ray +13540|76149|6150|3|6|6750.84|0.01|0.01|R|F|1993-08-09|1993-06-26|1993-09-08|NONE|SHIP|lites nag about the slyly even instruc +13540|24670|2177|4|48|76544.16|0.08|0.02|A|F|1993-08-04|1993-08-04|1993-08-30|TAKE BACK RETURN|TRUCK|lyly. fluffily ironic requests +13540|13364|3365|5|26|33211.36|0.01|0.02|A|F|1993-07-18|1993-07-22|1993-08-04|COLLECT COD|AIR| pending requests wake +13540|192976|2977|6|17|35172.49|0.10|0.04|R|F|1993-09-04|1993-08-12|1993-09-19|TAKE BACK RETURN|AIR|nts. slyly fi +13540|144990|19|7|28|56979.72|0.09|0.05|R|F|1993-09-08|1993-08-13|1993-10-08|DELIVER IN PERSON|MAIL|sly unusual +13541|35518|8022|1|21|30523.71|0.07|0.02|N|O|1996-09-03|1996-09-02|1996-09-06|NONE|RAIL|ccounts-- final +13541|146932|1961|2|1|1978.93|0.04|0.07|N|O|1996-10-02|1996-09-24|1996-10-27|TAKE BACK RETURN|AIR|y even requests. slyly +13541|76813|9321|3|17|30426.77|0.07|0.04|N|O|1996-09-20|1996-10-02|1996-09-25|DELIVER IN PERSON|MAIL|busily against the slyly even foxe +13542|95266|7776|1|42|52972.92|0.04|0.03|R|F|1994-07-01|1994-05-21|1994-07-22|TAKE BACK RETURN|RAIL|ep blithely along the slyly regular a +13542|120336|337|2|46|62391.18|0.00|0.06|R|F|1994-06-02|1994-06-05|1994-06-27|TAKE BACK RETURN|SHIP|hely. regular, silent req +13542|78797|6319|3|46|81686.34|0.10|0.01|A|F|1994-06-21|1994-04-20|1994-07-02|DELIVER IN PERSON|AIR|sts haggle: +13542|141105|8648|4|45|51574.50|0.03|0.02|R|F|1994-04-16|1994-05-25|1994-05-06|DELIVER IN PERSON|SHIP|kages cajole quickly about +13542|141549|1550|5|34|54078.36|0.05|0.00|R|F|1994-03-24|1994-04-26|1994-03-26|TAKE BACK RETURN|RAIL|press tithes sleep after the pending +13543|78522|3537|1|11|16505.72|0.10|0.00|R|F|1992-10-05|1992-09-19|1992-10-25|DELIVER IN PERSON|RAIL|g the pending, ironic deposits. packages +13543|112521|7544|2|7|10734.64|0.02|0.05|A|F|1992-08-28|1992-10-15|1992-09-08|DELIVER IN PERSON|AIR|ously bold multipliers +13568|136086|1113|1|17|19075.36|0.03|0.02|R|F|1993-07-23|1993-07-20|1993-07-26|COLLECT COD|MAIL|riously even depo +13568|194815|9854|2|4|7639.24|0.01|0.07|A|F|1993-05-31|1993-07-25|1993-06-12|DELIVER IN PERSON|MAIL|s haggle furiously ironic, even d +13568|50910|8426|3|38|70714.58|0.06|0.04|A|F|1993-07-18|1993-06-15|1993-07-31|DELIVER IN PERSON|FOB|ver special dolphins sleep blithely ab +13569|510|5511|1|26|36673.26|0.05|0.08|R|F|1995-05-21|1995-05-21|1995-06-17|TAKE BACK RETURN|MAIL|kly unusual, even packages. blithely f +13569|160580|8129|2|38|62342.04|0.04|0.08|R|F|1995-04-29|1995-05-12|1995-05-26|COLLECT COD|SHIP|es are daringly after the unusual, final a +13569|63740|1259|3|15|25556.10|0.08|0.01|A|F|1995-05-11|1995-07-04|1995-05-30|COLLECT COD|MAIL|, regular requests believe alongsi +13569|70923|924|4|9|17045.28|0.02|0.04|N|O|1995-06-21|1995-06-28|1995-06-24|DELIVER IN PERSON|TRUCK|x carefully against the regular pack +13569|1560|1561|5|14|20461.84|0.03|0.06|N|O|1995-07-11|1995-05-30|1995-08-04|TAKE BACK RETURN|RAIL|ly. carefully final h +13569|10596|8100|6|33|49717.47|0.05|0.03|R|F|1995-05-10|1995-06-11|1995-05-22|NONE|SHIP|uests use quickly regular platelets. care +13569|73100|622|7|14|15023.40|0.06|0.01|N|O|1995-07-08|1995-05-31|1995-08-05|COLLECT COD|TRUCK|oxes play along the bold ins +13570|184569|2124|1|19|31417.64|0.05|0.03|A|F|1993-02-02|1993-02-26|1993-02-04|NONE|SHIP|thely ironic foxes. quickly final re +13570|45234|7739|2|17|20046.91|0.03|0.05|A|F|1993-02-28|1993-02-17|1993-03-19|COLLECT COD|FOB| packages doubt fluffily. +13570|31980|1981|3|44|84127.12|0.06|0.08|R|F|1992-12-27|1993-02-19|1993-01-12|TAKE BACK RETURN|SHIP|ainments use furiously spe +13570|79772|2280|4|33|57808.41|0.08|0.08|A|F|1993-01-23|1993-01-30|1993-01-29|TAKE BACK RETURN|REG AIR|s cajole. carefully regular pla +13570|127785|2810|5|50|90639.00|0.03|0.06|R|F|1993-01-25|1993-03-03|1993-02-16|DELIVER IN PERSON|FOB|ly quickly bold pin +13571|3190|8191|1|25|27329.75|0.02|0.01|N|O|1998-06-08|1998-08-01|1998-07-01|DELIVER IN PERSON|SHIP| the bold, regular platelets. sa +13571|199336|9337|2|32|45930.56|0.03|0.02|N|O|1998-09-29|1998-07-15|1998-10-18|TAKE BACK RETURN|AIR|uffily final ideas +13571|39753|4760|3|20|33855.00|0.01|0.04|N|O|1998-07-02|1998-08-21|1998-07-15|NONE|FOB|lar requests. fluffil +13571|118557|1069|4|31|48842.05|0.06|0.02|N|O|1998-10-01|1998-07-10|1998-10-03|NONE|SHIP|usual packages cajole. carefully +13572|135689|5690|1|7|12072.76|0.05|0.03|R|F|1992-05-28|1992-08-11|1992-06-02|NONE|AIR|sly bold deposit +13572|108762|3783|2|1|1770.76|0.08|0.07|A|F|1992-07-15|1992-07-05|1992-08-05|DELIVER IN PERSON|REG AIR|sual accounts. quickly r +13572|155268|5269|3|21|27788.46|0.03|0.07|R|F|1992-07-11|1992-06-28|1992-08-01|TAKE BACK RETURN|RAIL|r asymptotes? slyly ev +13572|175346|7864|4|8|11370.72|0.10|0.07|A|F|1992-06-18|1992-07-14|1992-06-25|TAKE BACK RETURN|TRUCK|yly ironic accounts; blithely regular attai +13572|37308|2315|5|42|52302.60|0.05|0.08|R|F|1992-06-26|1992-08-02|1992-07-05|DELIVER IN PERSON|FOB|beans shall snooze thinly re +13572|30841|3345|6|5|8859.20|0.04|0.07|R|F|1992-07-27|1992-06-25|1992-08-23|COLLECT COD|MAIL|use final requests. carefully express ac +13573|69558|7077|1|9|13747.95|0.01|0.04|N|O|1997-07-30|1997-06-10|1997-08-15|DELIVER IN PERSON|SHIP|osits among the slyly bol +13573|54916|9927|2|30|56127.30|0.06|0.01|N|O|1997-05-05|1997-07-08|1997-06-02|DELIVER IN PERSON|SHIP|. blithely ev +13573|166967|9484|3|7|14237.72|0.09|0.06|N|O|1997-06-24|1997-06-21|1997-06-27|COLLECT COD|TRUCK|y. quickly final dependencies are carefull +13573|12368|4870|4|12|15364.32|0.06|0.01|N|O|1997-06-28|1997-06-04|1997-07-26|NONE|REG AIR|t the fluffily special depen +13574|92775|5285|1|41|72478.57|0.10|0.08|N|O|1997-11-27|1997-12-25|1997-12-27|DELIVER IN PERSON|AIR|usual tithes. slyl +13575|86685|9194|1|29|48478.72|0.01|0.01|R|F|1992-11-22|1992-11-25|1992-12-08|COLLECT COD|AIR|s sleep fluffily fluffily express sent +13575|107358|4889|2|42|57344.70|0.05|0.05|R|F|1992-12-06|1992-10-23|1992-12-27|DELIVER IN PERSON|REG AIR| the deposits. even instr +13600|143251|3252|1|24|31062.00|0.02|0.05|A|F|1993-08-07|1993-08-10|1993-08-30|NONE|TRUCK|fully bold asymptotes. platelets sleep. +13600|7003|9504|2|7|6370.00|0.06|0.05|A|F|1993-08-16|1993-09-01|1993-08-24|DELIVER IN PERSON|AIR|ests. ironic instructions +13600|92577|7596|3|48|75339.36|0.06|0.03|A|F|1993-11-03|1993-09-19|1993-11-12|DELIVER IN PERSON|FOB|arefully even cour +13601|40504|5513|1|24|34668.00|0.02|0.07|R|F|1992-11-05|1992-10-28|1992-11-28|NONE|TRUCK| bold deposits. +13601|146355|6356|2|48|67264.80|0.04|0.07|R|F|1992-12-06|1992-10-16|1992-12-07|TAKE BACK RETURN|REG AIR|ly final accounts. slyly +13601|177170|7171|3|43|53628.31|0.05|0.07|A|F|1992-10-11|1992-10-17|1992-11-09|NONE|MAIL| packages can haggle furiously furio +13601|95759|3287|4|27|47378.25|0.03|0.02|A|F|1992-08-23|1992-09-29|1992-09-15|NONE|AIR| across the special theodolites affi +13601|12470|4972|5|32|44239.04|0.04|0.07|R|F|1992-08-28|1992-11-04|1992-09-25|DELIVER IN PERSON|RAIL|yly regular dependencies! blithely daring +13602|151853|1854|1|34|64764.90|0.03|0.00|A|F|1994-03-03|1994-03-04|1994-03-27|NONE|SHIP|st the quickly regular instructions. bold +13602|187052|4607|2|49|55813.45|0.04|0.07|A|F|1994-03-19|1994-03-24|1994-04-01|COLLECT COD|SHIP|sts thrash fu +13602|176488|6489|3|44|68837.12|0.09|0.02|A|F|1994-04-30|1994-03-03|1994-05-27|NONE|SHIP|yly regular excuses. furiously specia +13602|23346|3347|4|4|5077.36|0.01|0.08|R|F|1994-04-08|1994-03-14|1994-04-26|COLLECT COD|SHIP|luffily special dinos +13602|162193|2194|5|49|61504.31|0.01|0.02|R|F|1994-02-08|1994-03-03|1994-02-28|TAKE BACK RETURN|TRUCK|beans detect f +13603|52956|472|1|26|49632.70|0.10|0.03|N|O|1997-07-29|1997-09-05|1997-08-27|DELIVER IN PERSON|MAIL|press, even packages +13603|29051|4056|2|3|2940.15|0.10|0.00|N|O|1997-08-04|1997-07-26|1997-08-16|DELIVER IN PERSON|FOB| the furiously pend +13603|44869|7374|3|18|32649.48|0.09|0.05|N|O|1997-09-08|1997-08-28|1997-09-15|TAKE BACK RETURN|RAIL|lithely. requests again +13603|108970|1481|4|22|43537.34|0.03|0.08|N|O|1997-06-18|1997-07-10|1997-07-07|DELIVER IN PERSON|FOB|ickly even +13603|49377|1882|5|4|5305.48|0.10|0.08|N|O|1997-06-29|1997-07-29|1997-07-09|COLLECT COD|MAIL|he quickly final foxes are blithely r +13603|68091|5610|6|44|46599.96|0.03|0.04|N|O|1997-08-06|1997-08-05|1997-08-12|DELIVER IN PERSON|MAIL|ecial courts? final accounts haggle a +13603|2460|2461|7|39|53135.94|0.00|0.08|N|O|1997-09-27|1997-07-13|1997-10-07|TAKE BACK RETURN|MAIL| blithely even instruc +13604|141649|6678|1|15|25359.60|0.02|0.00|R|F|1994-05-22|1994-04-28|1994-06-01|TAKE BACK RETURN|FOB|sleep. furiously special requests u +13604|82427|2428|2|20|28188.40|0.01|0.05|A|F|1994-03-31|1994-04-23|1994-04-10|NONE|FOB|st have to wake among the silen +13604|142756|2757|3|17|30578.75|0.05|0.03|R|F|1994-04-26|1994-04-27|1994-05-01|NONE|TRUCK|ding to the ironic pinto bean +13604|83777|1302|4|30|52823.10|0.10|0.02|R|F|1994-06-03|1994-03-25|1994-06-13|TAKE BACK RETURN|FOB|deas. regular dependencies are +13604|27953|7954|5|35|65833.25|0.02|0.08|R|F|1994-03-12|1994-03-07|1994-04-05|TAKE BACK RETURN|RAIL|egular deposits. slyly regular ideas cajole +13604|2362|9863|6|40|50574.40|0.06|0.03|R|F|1994-04-29|1994-03-10|1994-05-16|COLLECT COD|RAIL|ctions. slyly carefu +13604|88413|3430|7|42|58859.22|0.01|0.02|A|F|1994-03-06|1994-03-27|1994-03-29|TAKE BACK RETURN|TRUCK| quickly deposits. regular pinto beans +13605|145290|5291|1|30|40058.70|0.08|0.01|N|O|1996-08-24|1996-09-02|1996-08-29|NONE|AIR|ep carefully above +13605|78979|6501|2|27|52865.19|0.08|0.01|N|O|1996-08-01|1996-09-01|1996-08-09|NONE|MAIL|ual accounts. fur +13605|196829|1868|3|7|13480.74|0.03|0.05|N|O|1996-10-03|1996-09-08|1996-10-09|COLLECT COD|MAIL|pecial requests alongside of the d +13605|102936|467|4|4|7755.72|0.09|0.08|N|O|1996-09-03|1996-09-03|1996-09-21|DELIVER IN PERSON|MAIL|lar packages sublate blithely final request +13605|39009|4016|5|40|37920.00|0.04|0.07|N|O|1996-07-05|1996-09-04|1996-07-15|TAKE BACK RETURN|RAIL|s use furio +13605|21319|8826|6|34|42170.54|0.00|0.05|N|O|1996-07-26|1996-09-01|1996-08-14|COLLECT COD|RAIL|inal packages sleep after +13605|105590|5591|7|12|19147.08|0.02|0.04|N|O|1996-06-16|1996-07-30|1996-07-12|DELIVER IN PERSON|REG AIR|luffily regular platelets integrate-- bli +13606|49648|9649|1|27|43136.28|0.09|0.04|R|F|1994-04-29|1994-07-22|1994-05-01|DELIVER IN PERSON|TRUCK|ic pinto beans sleep furiously after t +13606|17245|2248|2|13|15109.12|0.09|0.06|R|F|1994-06-23|1994-06-25|1994-07-03|COLLECT COD|REG AIR|kages nag furiously after +13606|30889|3393|3|27|49136.76|0.10|0.08|R|F|1994-04-28|1994-06-10|1994-05-22|NONE|REG AIR|the excuses. even br +13606|140107|7650|4|34|39001.40|0.07|0.07|A|F|1994-05-05|1994-05-28|1994-05-17|COLLECT COD|REG AIR|e blithely. special fox +13606|166379|1412|5|17|24571.29|0.02|0.01|R|F|1994-06-15|1994-06-27|1994-07-03|COLLECT COD|SHIP|en accounts +13606|120620|8157|6|45|73827.90|0.01|0.04|A|F|1994-07-31|1994-06-19|1994-08-02|DELIVER IN PERSON|TRUCK| packages nag ab +13606|56630|9136|7|5|7933.15|0.06|0.00|A|F|1994-06-29|1994-07-13|1994-07-22|DELIVER IN PERSON|MAIL|ronic instructions. pen +13607|172165|9717|1|42|51960.72|0.03|0.01|R|F|1994-02-20|1994-01-27|1994-03-19|COLLECT COD|FOB| requests; fluffily u +13607|171916|1917|2|44|87468.04|0.10|0.08|A|F|1994-01-01|1994-02-09|1994-01-24|COLLECT COD|FOB|ins wake brav +13607|181410|8965|3|6|8948.46|0.07|0.02|R|F|1994-02-17|1993-12-19|1994-03-03|COLLECT COD|FOB|e requests. regul +13607|151046|1047|4|7|7679.28|0.01|0.03|R|F|1994-02-16|1993-12-26|1994-02-18|COLLECT COD|RAIL|ect blithely regular dependencie +13607|19841|7345|5|22|38738.48|0.00|0.01|A|F|1993-11-29|1993-12-19|1993-12-20|NONE|RAIL|ans. unusual instructions above +13607|53374|5880|6|14|18583.18|0.07|0.04|R|F|1994-03-07|1993-12-25|1994-04-02|DELIVER IN PERSON|REG AIR|unts against the +13607|53824|1340|7|7|12444.74|0.02|0.03|A|F|1994-03-12|1994-02-09|1994-03-19|DELIVER IN PERSON|RAIL|yly express packages. enticingly eve +13632|17060|2063|1|45|43967.70|0.08|0.07|A|F|1994-04-23|1994-04-29|1994-05-19|TAKE BACK RETURN|SHIP| regular packages are +13632|120613|8150|2|1|1633.61|0.04|0.08|R|F|1994-03-20|1994-05-21|1994-04-13|DELIVER IN PERSON|AIR|ons. instructions are ca +13632|134028|1568|3|49|52038.98|0.10|0.04|R|F|1994-03-15|1994-06-05|1994-03-24|TAKE BACK RETURN|AIR|jole. pendi +13632|6406|6407|4|50|65620.00|0.00|0.00|A|F|1994-06-08|1994-05-24|1994-07-03|COLLECT COD|MAIL|ged, final realms. furiously bold accoun +13632|63423|8436|5|28|38819.76|0.05|0.04|A|F|1994-06-20|1994-05-05|1994-07-07|TAKE BACK RETURN|RAIL|e fluffily accor +13632|135363|2903|6|8|11186.88|0.10|0.08|A|F|1994-04-11|1994-05-28|1994-04-12|TAKE BACK RETURN|RAIL|structions after the even account +13632|45718|727|7|42|69875.82|0.00|0.03|R|F|1994-06-24|1994-05-31|1994-07-03|TAKE BACK RETURN|RAIL|! quickly final braids a +13633|180395|7950|1|13|19180.07|0.02|0.08|A|F|1992-06-30|1992-05-16|1992-07-20|COLLECT COD|REG AIR|ording to the +13633|90052|7580|2|11|11462.55|0.04|0.06|R|F|1992-07-07|1992-06-21|1992-07-15|TAKE BACK RETURN|AIR|onic accounts are slyly car +13633|102262|4773|3|20|25285.20|0.10|0.08|R|F|1992-05-25|1992-06-22|1992-06-02|DELIVER IN PERSON|FOB| carefully regular deposits af +13633|103003|8024|4|23|23138.00|0.02|0.01|A|F|1992-06-28|1992-06-14|1992-07-06|DELIVER IN PERSON|RAIL|olites. fluffily regu +13633|169459|1976|5|5|7642.25|0.09|0.04|R|F|1992-06-24|1992-06-26|1992-06-28|NONE|AIR|ost carefully. blithely bold d +13633|97284|7285|6|44|56376.32|0.05|0.06|R|F|1992-05-09|1992-06-28|1992-05-14|DELIVER IN PERSON|RAIL|s integrate. deposits haggle slyly +13634|25083|2590|1|21|21169.68|0.03|0.07|A|F|1995-05-14|1995-06-01|1995-06-07|NONE|REG AIR|odolites are along the final foxes. +13634|156338|8854|2|13|18126.29|0.07|0.02|N|O|1995-07-03|1995-07-07|1995-08-02|TAKE BACK RETURN|FOB|s. slyly dogged patterns nag furiously +13635|72440|7455|1|22|31073.68|0.02|0.05|A|F|1994-08-19|1994-06-28|1994-09-17|TAKE BACK RETURN|FOB|ourts play c +13635|95997|8507|2|46|91677.54|0.08|0.07|R|F|1994-06-22|1994-06-27|1994-06-28|DELIVER IN PERSON|AIR| nag blithely idly special ac +13636|152314|2315|1|1|1366.31|0.00|0.06|R|F|1994-05-11|1994-03-14|1994-05-31|NONE|TRUCK|ar pinto beans? slyly pendin +13636|137307|2334|2|27|36296.10|0.03|0.02|A|F|1994-04-03|1994-03-20|1994-04-08|COLLECT COD|RAIL|are furious +13636|107026|2047|3|48|49584.96|0.00|0.06|A|F|1994-05-11|1994-04-19|1994-05-18|DELIVER IN PERSON|REG AIR|lent requests. ironic excuses +13636|181540|9095|4|49|79455.46|0.05|0.08|A|F|1994-01-25|1994-03-20|1994-02-10|TAKE BACK RETURN|FOB|dolites. silently pendin +13637|141460|3975|1|47|70568.62|0.00|0.08|N|O|1996-02-27|1996-03-02|1996-03-22|COLLECT COD|FOB|he quickly ironic platelets boost b +13638|24573|4574|1|24|35941.68|0.02|0.07|N|O|1995-11-27|1995-11-07|1995-12-21|DELIVER IN PERSON|TRUCK|fluffily bold accounts affix at th +13638|181686|4205|2|43|76010.24|0.01|0.07|N|O|1996-01-06|1995-12-26|1996-01-17|COLLECT COD|TRUCK|special pai +13638|189830|7385|3|22|42236.26|0.02|0.04|N|O|1995-11-19|1995-11-28|1995-12-14|TAKE BACK RETURN|AIR|ve the final, sly requests wake f +13638|71634|4142|4|42|67436.46|0.00|0.02|N|O|1995-10-30|1995-11-18|1995-11-04|TAKE BACK RETURN|REG AIR|ding to the bold theodolites boost fin +13638|146224|8739|5|28|35566.16|0.02|0.06|N|O|1995-11-16|1995-11-29|1995-11-30|TAKE BACK RETURN|AIR|ymptotes are slyly +13638|182547|102|6|41|66811.14|0.04|0.05|N|O|1995-12-30|1995-12-11|1996-01-07|COLLECT COD|SHIP|s use. deposits are carefully according t +13639|101652|4163|1|34|56224.10|0.05|0.01|N|O|1997-09-25|1997-08-18|1997-10-05|DELIVER IN PERSON|TRUCK|nts. fluffily even reque +13639|52003|9519|2|46|43930.00|0.03|0.03|N|O|1997-09-18|1997-07-20|1997-10-12|DELIVER IN PERSON|FOB|en accounts eat slyly +13639|6244|1245|3|31|35657.44|0.01|0.06|N|O|1997-09-05|1997-08-23|1997-10-03|DELIVER IN PERSON|SHIP| even instructi +13664|188470|8471|1|19|29610.93|0.04|0.07|N|O|1996-03-23|1996-02-15|1996-04-03|NONE|AIR| print among the regular, regular deposits. +13664|13951|8954|2|40|74598.00|0.05|0.02|N|O|1996-04-01|1996-03-04|1996-04-15|DELIVER IN PERSON|AIR| poach ent +13664|66326|8833|3|48|62031.36|0.01|0.08|N|O|1995-12-31|1996-02-16|1996-01-26|NONE|REG AIR|ainst the final cour +13664|136392|1419|4|47|67134.33|0.00|0.02|N|O|1996-02-05|1996-02-22|1996-02-07|DELIVER IN PERSON|RAIL|lar accoun +13664|125249|274|5|12|15290.88|0.06|0.06|N|O|1995-12-18|1996-02-25|1996-01-06|NONE|TRUCK|dolites according to the carefully bold pl +13664|53940|1456|6|45|85227.30|0.06|0.02|N|O|1996-03-22|1996-02-23|1996-04-07|COLLECT COD|REG AIR|posits haggle. cou +13665|165990|8507|1|34|69903.66|0.09|0.08|N|O|1996-06-19|1996-06-27|1996-07-01|DELIVER IN PERSON|RAIL|ding asymptotes sl +13665|188903|8904|2|16|31870.40|0.02|0.06|N|O|1996-07-03|1996-06-20|1996-08-02|NONE|AIR|uffily final requests engage carefully upo +13665|86170|6171|3|20|23123.40|0.04|0.07|N|O|1996-04-10|1996-05-10|1996-04-28|DELIVER IN PERSON|MAIL|, ironic pack +13665|42457|7466|4|30|41983.50|0.01|0.06|N|O|1996-06-07|1996-06-03|1996-06-10|COLLECT COD|RAIL|r instructions boo +13665|170385|5420|5|4|5821.52|0.04|0.03|N|O|1996-08-01|1996-06-28|1996-08-29|COLLECT COD|RAIL|etect carefully. carefully ironic deposit +13665|59392|9393|6|10|13513.90|0.06|0.06|N|O|1996-05-17|1996-06-24|1996-06-03|TAKE BACK RETURN|REG AIR|ackages above the regular asymptote +13666|8721|8722|1|28|45632.16|0.07|0.05|R|F|1992-05-12|1992-05-31|1992-05-14|NONE|RAIL|ven packages haggle. carefully bold +13666|159927|4958|2|21|41725.32|0.00|0.02|R|F|1992-03-31|1992-04-20|1992-04-13|COLLECT COD|FOB| regular requests hang blithely according t +13667|133648|6162|1|5|8408.20|0.06|0.04|N|O|1997-01-18|1997-02-03|1997-02-04|TAKE BACK RETURN|RAIL|ul escapades! caref +13667|20219|7726|2|2|2278.42|0.05|0.08|N|O|1997-03-24|1997-01-03|1997-04-03|NONE|AIR|old theodolites. carefully final pa +13667|11825|6828|3|16|27789.12|0.05|0.03|N|O|1997-01-05|1997-02-04|1997-01-25|DELIVER IN PERSON|RAIL|ly careful deposits. p +13667|135501|528|4|31|47631.50|0.08|0.08|N|O|1997-01-05|1997-02-13|1997-01-22|COLLECT COD|AIR|. even instructions above th +13667|151661|6692|5|35|59943.10|0.03|0.08|N|O|1997-02-13|1997-01-20|1997-03-03|COLLECT COD|MAIL|along the special notornis. quickly spec +13667|158603|8604|6|38|63140.80|0.00|0.00|N|O|1996-12-23|1997-01-24|1996-12-28|TAKE BACK RETURN|MAIL|ress theodol +13667|28731|3736|7|34|56430.82|0.10|0.02|N|O|1997-02-09|1997-01-10|1997-02-19|DELIVER IN PERSON|SHIP|e daringly against the carefu +13668|76371|3893|1|49|66021.13|0.02|0.02|A|F|1992-04-18|1992-04-04|1992-05-08|NONE|TRUCK|as sleep. per +13668|163193|8226|2|6|7537.14|0.09|0.04|A|F|1992-06-04|1992-05-22|1992-06-20|DELIVER IN PERSON|TRUCK|uses. bold p +13668|178617|1135|3|50|84780.50|0.05|0.02|R|F|1992-06-09|1992-04-26|1992-06-13|TAKE BACK RETURN|FOB|rding to the furiously bold platelet +13668|10098|2600|4|44|44355.96|0.01|0.07|A|F|1992-03-24|1992-04-19|1992-03-25|COLLECT COD|REG AIR|s theodolites boost regu +13669|90220|221|1|29|35096.38|0.05|0.03|N|O|1996-10-21|1996-10-20|1996-11-18|NONE|REG AIR| special deposits. sile +13669|114193|1727|2|40|48287.60|0.03|0.03|N|O|1996-08-30|1996-11-08|1996-09-18|NONE|SHIP|ly unusual asymptotes boost caref +13669|35983|990|3|16|30703.68|0.06|0.00|N|O|1996-10-18|1996-11-09|1996-11-15|NONE|MAIL|luffily pending requests. slowly ironic +13669|152308|2309|4|7|9522.10|0.04|0.03|N|O|1996-12-09|1996-09-26|1997-01-01|NONE|AIR|instructions. accounts +13669|27993|2998|5|22|42261.78|0.07|0.08|N|O|1996-08-16|1996-09-27|1996-09-07|TAKE BACK RETURN|AIR|ironic, enticing pac +13669|66124|3643|6|10|10901.20|0.08|0.02|N|O|1996-09-29|1996-10-16|1996-10-08|NONE|REG AIR|. slowly even excuses nag after t +13669|139763|9764|7|13|23435.88|0.06|0.04|N|O|1996-10-15|1996-10-15|1996-11-14|NONE|FOB|o beans nag quickly about the even t +13670|188271|8272|1|38|51652.26|0.04|0.08|A|F|1992-06-29|1992-07-17|1992-07-17|TAKE BACK RETURN|MAIL|xpress pack +13670|55318|5319|2|21|26739.51|0.05|0.01|R|F|1992-06-03|1992-07-06|1992-06-21|NONE|SHIP| theodolites affix ru +13670|119002|4025|3|50|51050.00|0.05|0.03|A|F|1992-06-20|1992-07-21|1992-07-13|COLLECT COD|AIR|kly past the requests. qui +13671|88845|8846|1|14|25673.76|0.06|0.03|N|O|1996-11-11|1996-09-24|1996-12-06|DELIVER IN PERSON|RAIL|uests doubt slyly. quickly final packages w +13671|11939|1940|2|40|74037.20|0.07|0.05|N|O|1996-10-06|1996-09-24|1996-11-03|COLLECT COD|FOB|le above the ironically final reques +13671|52820|5326|3|20|35456.40|0.04|0.02|N|O|1996-08-12|1996-10-10|1996-08-24|TAKE BACK RETURN|AIR|g the carefully final dep +13671|142076|9619|4|12|13416.84|0.07|0.01|N|O|1996-08-17|1996-09-13|1996-08-27|NONE|MAIL|ost fluffily even deposits. even d +13671|61645|4152|5|41|65872.24|0.10|0.05|N|O|1996-08-31|1996-09-20|1996-09-05|NONE|RAIL|y pending deposits wake slyl +13671|55350|361|6|30|39160.50|0.10|0.06|N|O|1996-10-04|1996-08-26|1996-10-05|COLLECT COD|AIR|gle slyly quic +13671|59727|7243|7|8|13493.76|0.06|0.01|N|O|1996-08-31|1996-08-25|1996-09-03|TAKE BACK RETURN|REG AIR|ironic foxes wake furiously ironic depos +13696|22578|2579|1|30|45017.10|0.00|0.00|N|O|1997-12-01|1997-11-01|1997-12-31|COLLECT COD|TRUCK|odolites sleep along the fi +13696|62787|7800|2|8|13998.24|0.06|0.02|N|O|1997-09-12|1997-11-11|1997-09-20|NONE|REG AIR|ickly final requests. quickl +13696|46166|8671|3|7|7785.12|0.09|0.04|N|O|1997-11-24|1997-10-31|1997-11-25|NONE|SHIP|ions eat furiously. ironically ironic p +13696|108052|563|4|46|48762.30|0.09|0.02|N|O|1997-09-01|1997-10-17|1997-09-08|DELIVER IN PERSON|MAIL|sual accounts alongside of the +13696|22820|5323|5|1|1742.82|0.00|0.04|N|O|1997-09-02|1997-10-31|1997-09-24|TAKE BACK RETURN|MAIL|the special, +13696|133882|1422|6|18|34485.84|0.07|0.01|N|O|1997-11-15|1997-10-16|1997-12-03|NONE|MAIL|ajole blithely pending pinto b +13697|66614|6615|1|2|3161.22|0.07|0.08|N|O|1998-07-11|1998-07-01|1998-08-04|DELIVER IN PERSON|TRUCK|the bold pinto beans: expre +13697|180764|8319|2|30|55342.80|0.04|0.08|N|O|1998-07-19|1998-05-22|1998-08-18|NONE|SHIP|foxes. furiously pending f +13697|90584|5603|3|28|44088.24|0.08|0.02|N|O|1998-04-26|1998-06-21|1998-05-10|TAKE BACK RETURN|TRUCK|nly final requests. bo +13698|350|351|1|50|62517.50|0.03|0.03|A|F|1994-09-23|1994-11-01|1994-09-26|TAKE BACK RETURN|MAIL|ffily express accounts use after th +13698|67996|503|2|46|90343.54|0.08|0.03|R|F|1994-10-27|1994-10-21|1994-11-06|TAKE BACK RETURN|REG AIR|uses wake careful +13698|3107|608|3|34|34343.40|0.00|0.07|R|F|1994-08-19|1994-10-25|1994-09-03|NONE|FOB|y. platelets are quickly. enticingly +13698|15875|8377|4|7|12536.09|0.10|0.06|R|F|1994-10-13|1994-09-29|1994-11-01|TAKE BACK RETURN|REG AIR|egular courts. ironic instruct +13699|154807|7323|1|15|27927.00|0.00|0.05|N|O|1997-05-31|1997-06-07|1997-06-15|DELIVER IN PERSON|FOB| the blithe, pending dependencie +13700|14284|9287|1|19|22767.32|0.01|0.03|R|F|1992-06-11|1992-03-19|1992-07-06|DELIVER IN PERSON|FOB|, final requests. slyly +13701|61036|3543|1|47|46860.41|0.02|0.01|N|O|1998-08-01|1998-06-17|1998-08-12|TAKE BACK RETURN|RAIL|s. even depe +13701|24802|7305|2|5|8634.00|0.04|0.01|N|O|1998-07-14|1998-07-11|1998-08-07|TAKE BACK RETURN|FOB|inal platelets. quickly f +13701|31059|3563|3|25|24751.25|0.04|0.05|N|O|1998-06-26|1998-08-13|1998-07-13|COLLECT COD|TRUCK|after the furiously even dependenc +13701|3700|6201|4|3|4811.10|0.01|0.00|N|O|1998-07-25|1998-06-30|1998-08-12|DELIVER IN PERSON|TRUCK|ding epitaphs are. regular +13701|180298|7853|5|30|41348.70|0.01|0.08|N|O|1998-07-17|1998-08-05|1998-08-14|TAKE BACK RETURN|FOB|lyly regular theodolites. +13701|54200|9211|6|41|47322.20|0.02|0.01|N|O|1998-06-11|1998-06-28|1998-06-15|COLLECT COD|TRUCK| sleep slyly. slyly final deposits nag +13702|189769|7324|1|20|37175.20|0.10|0.00|N|O|1995-12-23|1995-10-28|1996-01-16|COLLECT COD|FOB|s platelets boost according t +13702|36185|1192|2|16|17938.88|0.05|0.02|N|O|1995-12-04|1995-11-21|1995-12-22|TAKE BACK RETURN|TRUCK|thely after the carefully bold accounts. +13703|81203|6220|1|13|15394.60|0.04|0.08|N|O|1997-04-22|1997-03-17|1997-05-14|NONE|REG AIR|kly above the idle deposits. +13703|163488|3489|2|20|31029.60|0.02|0.02|N|O|1997-03-14|1997-03-15|1997-04-09|DELIVER IN PERSON|TRUCK|ly silent deposits about the regular pint +13703|137378|7379|3|42|59445.54|0.03|0.05|N|O|1997-04-11|1997-03-13|1997-04-17|NONE|MAIL|refully ironic requests. bold do +13703|105437|2968|4|38|54812.34|0.02|0.06|N|O|1997-02-27|1997-03-07|1997-03-12|NONE|FOB|kly bold deposits. dependencies thrash som +13703|79042|9043|5|40|40841.60|0.00|0.08|N|O|1997-03-04|1997-02-18|1997-03-16|NONE|FOB|ructions haggle slyly carefully unusual +13728|86216|3741|1|36|43279.56|0.04|0.00|N|O|1996-01-22|1996-01-26|1996-02-19|NONE|SHIP|excuses x-ray slyly special ideas. +13728|23075|5578|2|20|19961.40|0.09|0.02|N|O|1996-01-28|1996-03-09|1996-02-11|NONE|RAIL|sual packages hinder abov +13728|12450|2451|3|40|54498.00|0.03|0.05|N|O|1996-01-30|1996-01-15|1996-01-31|TAKE BACK RETURN|REG AIR|deas wake furiously. +13729|6285|8786|1|14|16677.92|0.01|0.06|A|F|1994-04-27|1994-03-19|1994-05-04|COLLECT COD|RAIL|ully above the idly e +13729|27003|2008|2|18|16740.00|0.02|0.06|A|F|1994-01-19|1994-03-22|1994-01-28|TAKE BACK RETURN|SHIP| sleep. carefully expr +13729|29196|4201|3|44|49508.36|0.04|0.04|A|F|1994-02-11|1994-03-24|1994-02-26|DELIVER IN PERSON|TRUCK|quests believe alon +13730|103273|3274|1|42|53603.34|0.09|0.03|N|F|1995-06-06|1995-07-22|1995-06-28|NONE|RAIL|slyly according to the fu +13731|64682|9695|1|41|67513.88|0.05|0.02|A|F|1993-07-09|1993-07-07|1993-07-17|TAKE BACK RETURN|RAIL|oldly against t +13731|93975|6485|2|31|61038.07|0.07|0.00|R|F|1993-05-23|1993-06-29|1993-06-03|TAKE BACK RETURN|SHIP|lithely. sl +13731|24269|4270|3|30|35797.80|0.00|0.06|R|F|1993-08-23|1993-06-12|1993-08-27|NONE|AIR|oost furiously bold +13731|84644|2169|4|33|53745.12|0.01|0.02|R|F|1993-08-08|1993-06-21|1993-08-19|COLLECT COD|MAIL|kages sleep quickly. reque +13732|21120|6125|1|5|5205.60|0.09|0.07|R|F|1993-01-21|1993-02-08|1993-02-07|TAKE BACK RETURN|RAIL|slyly after +13732|160159|5192|2|15|18287.25|0.06|0.07|R|F|1993-03-11|1993-02-17|1993-04-06|COLLECT COD|SHIP|o beans. slyly sly dolphins nag. sly +13732|180264|265|3|40|53770.40|0.02|0.07|A|F|1993-03-23|1993-02-19|1993-04-04|NONE|MAIL|y even instruc +13732|86399|8908|4|38|52644.82|0.04|0.04|A|F|1993-02-04|1993-02-02|1993-02-08|TAKE BACK RETURN|AIR|ronic dolphins use across the foxes. +13733|198334|3373|1|50|71616.50|0.02|0.05|N|O|1998-01-15|1998-03-01|1998-02-06|DELIVER IN PERSON|AIR|refully special packages. +13733|188670|6225|2|8|14069.36|0.00|0.05|N|O|1998-01-11|1998-03-20|1998-01-14|DELIVER IN PERSON|MAIL|sual dolphins are carefully. furiously sp +13733|175993|5994|3|39|80690.61|0.01|0.02|N|O|1998-03-17|1998-03-28|1998-03-26|DELIVER IN PERSON|RAIL|ges: ironic ideas integrate +13733|111511|6534|4|3|4567.53|0.10|0.07|N|O|1998-03-12|1998-02-16|1998-03-31|DELIVER IN PERSON|AIR|ly express excuse +13733|163974|3975|5|41|83556.77|0.01|0.03|N|O|1998-03-26|1998-03-18|1998-04-23|NONE|RAIL|rding to the quickly regular accounts ca +13733|98541|8542|6|2|3079.08|0.02|0.05|N|O|1998-02-02|1998-03-23|1998-02-17|COLLECT COD|SHIP|r deposits. blithe +13733|164467|6984|7|49|75041.54|0.01|0.06|N|O|1998-03-18|1998-02-14|1998-03-19|NONE|FOB| regular platelets detect. iro +13734|183468|3469|1|31|48095.26|0.03|0.01|N|O|1996-11-02|1996-11-07|1996-11-22|TAKE BACK RETURN|REG AIR|lar pinto beans about +13734|135770|5771|2|34|61396.18|0.05|0.08|N|O|1996-10-29|1996-10-28|1996-11-04|TAKE BACK RETURN|FOB|ccounts haggle. qui +13734|79338|1846|3|37|48741.21|0.10|0.06|N|O|1996-09-04|1996-10-08|1996-09-13|NONE|RAIL|y ironic deposits boost slyly ironic ins +13735|83671|6180|1|25|41366.75|0.03|0.00|A|F|1994-07-11|1994-08-17|1994-08-07|COLLECT COD|RAIL| fluffily final requests wake +13735|54475|9486|2|23|32877.81|0.05|0.01|R|F|1994-05-30|1994-08-10|1994-06-26|DELIVER IN PERSON|SHIP|osits wake after the final, e +13735|144955|2498|3|40|79998.00|0.00|0.05|R|F|1994-06-10|1994-07-20|1994-07-06|COLLECT COD|REG AIR|ickly bold pack +13760|51768|4274|1|29|49873.04|0.03|0.07|N|O|1996-07-15|1996-07-06|1996-07-16|COLLECT COD|RAIL|t even grouches? blithely +13760|57573|5089|2|11|16836.27|0.05|0.05|N|O|1996-07-24|1996-08-07|1996-08-11|COLLECT COD|TRUCK|heodolites sleep carefully about the ironi +13760|17868|7869|3|23|41074.78|0.05|0.03|N|O|1996-08-02|1996-07-15|1996-08-04|NONE|FOB|haggle fluffily final excu +13760|91292|3802|4|3|3849.87|0.03|0.05|N|O|1996-08-12|1996-08-23|1996-08-28|TAKE BACK RETURN|TRUCK|its alongside o +13760|128382|3407|5|14|19745.32|0.08|0.02|N|O|1996-08-09|1996-07-10|1996-09-05|NONE|MAIL|en accounts. slyly +13760|109085|1596|6|21|22975.68|0.10|0.08|N|O|1996-07-30|1996-07-10|1996-08-11|NONE|RAIL|ously idle packages haggle furiously even a +13760|190564|5603|7|3|4963.68|0.00|0.07|N|O|1996-07-13|1996-07-27|1996-07-22|TAKE BACK RETURN|MAIL|nts are according to the ironi +13761|196145|8665|1|22|27305.08|0.03|0.02|R|F|1994-11-12|1994-12-05|1994-11-16|NONE|SHIP|unts use regular asymptotes. pending, fu +13761|199493|2013|2|39|62107.11|0.07|0.04|A|F|1994-11-15|1994-12-09|1994-12-09|COLLECT COD|FOB|even, thin foxes ab +13761|67710|2723|3|19|31876.49|0.03|0.01|A|F|1994-12-19|1994-12-07|1995-01-04|DELIVER IN PERSON|SHIP|boldly final +13761|192750|5270|4|1|1842.75|0.10|0.08|R|F|1995-02-09|1994-12-19|1995-02-18|DELIVER IN PERSON|TRUCK| the unusual, final foxes cajole fluffily +13761|140075|5104|5|24|26761.68|0.02|0.05|R|F|1995-02-13|1994-12-15|1995-02-18|DELIVER IN PERSON|FOB| carefully bold requests along the even p +13761|35208|5209|6|2|2286.40|0.10|0.02|R|F|1995-01-23|1995-01-01|1995-01-29|TAKE BACK RETURN|AIR| carefully ironic pi +13761|129862|9863|7|17|32161.62|0.00|0.06|A|F|1994-12-28|1994-12-28|1995-01-12|TAKE BACK RETURN|FOB| regular ideas. regular asymptotes s +13762|176776|4328|1|27|50024.79|0.09|0.08|A|F|1993-10-02|1993-07-27|1993-10-09|DELIVER IN PERSON|FOB|ording to the furiously blithe dug +13762|62902|7915|2|22|41027.80|0.09|0.00|A|F|1993-10-14|1993-08-05|1993-10-24|NONE|TRUCK|sts nag blithely af +13762|179173|6725|3|3|3756.51|0.04|0.01|R|F|1993-09-24|1993-08-02|1993-10-24|DELIVER IN PERSON|SHIP|sly pending, special pac +13762|152810|356|4|27|50295.87|0.04|0.01|A|F|1993-08-17|1993-08-28|1993-08-23|TAKE BACK RETURN|AIR| quickly ironic foxes slee +13762|61170|8689|5|25|28279.25|0.08|0.08|R|F|1993-08-15|1993-09-12|1993-08-22|DELIVER IN PERSON|TRUCK|lar, express excuses. ironic, +13762|78826|6348|6|30|54144.60|0.01|0.05|R|F|1993-08-21|1993-08-15|1993-09-06|COLLECT COD|FOB|. slowly bold requests run furiously across +13762|13888|1392|7|3|5405.64|0.04|0.05|R|F|1993-07-09|1993-08-20|1993-07-20|DELIVER IN PERSON|TRUCK|ven packages boost carefully bl +13763|7793|5294|1|25|42519.75|0.03|0.02|N|O|1997-07-28|1997-08-07|1997-08-02|COLLECT COD|RAIL|blithely quiet pinto +13763|161162|8711|2|48|58711.68|0.03|0.08|N|O|1997-10-19|1997-08-15|1997-11-18|COLLECT COD|TRUCK|ve to nag carefully. slyly bold accounts +13763|43091|8100|3|41|42397.69|0.03|0.01|N|O|1997-10-06|1997-08-15|1997-11-04|NONE|REG AIR|y final instructions. even cou +13763|14567|4568|4|10|14815.60|0.02|0.02|N|O|1997-10-24|1997-09-24|1997-11-14|COLLECT COD|SHIP|g to the quickly +13764|139711|4738|1|20|35014.20|0.03|0.03|N|O|1995-09-11|1995-09-14|1995-09-29|COLLECT COD|SHIP|s. quickly regular theodolites +13764|109116|1627|2|11|12376.21|0.02|0.03|N|O|1995-11-08|1995-10-08|1995-12-05|TAKE BACK RETURN|AIR|even platelets. carefully even tithes +13764|99885|2395|3|44|82934.72|0.04|0.06|N|O|1995-08-24|1995-10-05|1995-09-09|DELIVER IN PERSON|RAIL|he silent instruct +13765|78419|927|1|27|37730.07|0.02|0.03|A|F|1994-06-01|1994-06-28|1994-06-18|COLLECT COD|REG AIR|r, pending requests about +13765|185924|961|2|9|18089.28|0.03|0.03|R|F|1994-04-22|1994-06-20|1994-05-18|TAKE BACK RETURN|RAIL| regularly fluffily express de +13765|16360|8862|3|48|61265.28|0.02|0.01|R|F|1994-06-19|1994-05-24|1994-07-03|NONE|SHIP|dependencies integrate ironic wartho +13765|156556|9072|4|32|51601.60|0.10|0.05|A|F|1994-04-23|1994-05-20|1994-04-28|NONE|RAIL|uffily above the final requests. bold, expr +13766|91578|6597|1|26|40808.82|0.06|0.02|R|F|1993-01-09|1992-12-13|1993-01-19|TAKE BACK RETURN|REG AIR|carefully regular warhorses use bl +13767|150404|2920|1|17|24724.80|0.01|0.00|R|F|1993-09-15|1993-11-09|1993-10-03|TAKE BACK RETURN|FOB|affix caref +13767|39580|2084|2|43|65341.94|0.03|0.08|A|F|1993-09-30|1993-11-20|1993-10-04|DELIVER IN PERSON|RAIL|tes. somas t +13767|20928|8435|3|19|35129.48|0.02|0.08|A|F|1993-11-06|1993-11-13|1993-11-24|NONE|MAIL|ial, daring packages. quickly expr +13767|126084|6085|4|9|9990.72|0.03|0.01|R|F|1993-09-21|1993-10-12|1993-10-19|DELIVER IN PERSON|SHIP|l asymptotes. bold ideas cajole ca +13767|83145|670|5|13|14665.82|0.09|0.03|A|F|1993-11-27|1993-11-01|1993-11-28|COLLECT COD|SHIP|entiments-- ide +13767|10319|7823|6|44|54089.64|0.06|0.07|R|F|1993-12-23|1993-11-10|1994-01-21|DELIVER IN PERSON|RAIL|egular packages. furiously iro +13767|19923|7427|7|28|51601.76|0.06|0.08|A|F|1993-11-26|1993-10-09|1993-12-19|COLLECT COD|SHIP|regular packages gro +13792|34783|9790|1|42|72146.76|0.10|0.03|N|O|1996-06-01|1996-03-30|1996-06-26|TAKE BACK RETURN|REG AIR|riously ironic requests poach along +13793|109944|2455|1|17|33216.98|0.00|0.06|N|O|1995-10-30|1995-11-03|1995-11-14|DELIVER IN PERSON|TRUCK| asymptotes. final, unusual account +13794|50101|102|1|50|52555.00|0.10|0.03|R|F|1994-02-14|1994-04-04|1994-02-21|NONE|TRUCK|regular theodolites. quickly sile +13794|37080|7081|2|6|6102.48|0.03|0.05|R|F|1994-04-16|1994-03-01|1994-04-23|TAKE BACK RETURN|REG AIR|out the regularly ironic p +13794|189418|1937|3|24|36177.84|0.03|0.02|R|F|1994-03-08|1994-03-10|1994-03-20|NONE|TRUCK|ding accounts are carefully final, +13794|140091|2606|4|49|55423.41|0.01|0.04|A|F|1994-03-23|1994-02-13|1994-04-20|NONE|TRUCK|ccounts. blithely unusu +13794|104781|4782|5|35|62502.30|0.03|0.04|A|F|1994-03-05|1994-04-02|1994-03-22|COLLECT COD|SHIP|slyly. blithely final instructio +13794|43744|8753|6|2|3375.48|0.04|0.03|A|F|1994-04-18|1994-02-15|1994-04-27|COLLECT COD|FOB|sits sleep. thin theodolites thrash furiou +13794|197615|2654|7|9|15413.49|0.04|0.05|A|F|1994-01-14|1994-03-26|1994-01-28|COLLECT COD|FOB|sleep after the fluffily pendin +13795|99776|4795|1|4|7103.08|0.05|0.08|N|O|1995-07-01|1995-06-19|1995-07-24|TAKE BACK RETURN|RAIL|e slyly slyly enticing requests. quick +13795|120452|2965|2|10|14724.50|0.01|0.05|R|F|1995-06-06|1995-06-25|1995-06-14|NONE|REG AIR|uriously even requests +13795|26815|1820|3|9|15676.29|0.06|0.05|A|F|1995-04-14|1995-06-01|1995-04-17|NONE|REG AIR|e the permanent, special +13795|75340|5341|4|43|56559.62|0.06|0.03|R|F|1995-05-17|1995-05-13|1995-06-06|DELIVER IN PERSON|FOB|uriously express pin +13795|30906|8416|5|49|90008.10|0.06|0.07|N|O|1995-07-13|1995-06-30|1995-07-14|TAKE BACK RETURN|REG AIR|to the requests use carefully quickly eve +13795|35150|2660|6|50|54257.50|0.02|0.07|R|F|1995-05-03|1995-06-03|1995-05-16|TAKE BACK RETURN|REG AIR| the carefully bold packages. furiou +13795|156839|4385|7|7|13270.81|0.08|0.01|N|O|1995-07-19|1995-06-02|1995-07-21|COLLECT COD|TRUCK|ic, unusual requests nag sly +13796|183420|5939|1|47|70660.74|0.00|0.03|N|O|1997-08-14|1997-09-17|1997-09-02|DELIVER IN PERSON|MAIL| deposits serve slyly special a +13796|124493|9518|2|40|60699.60|0.00|0.04|N|O|1997-10-12|1997-09-04|1997-10-18|NONE|RAIL| blithely ironic de +13796|151141|1142|3|49|58414.86|0.09|0.03|N|O|1997-09-07|1997-08-14|1997-09-16|COLLECT COD|MAIL|ial hockey players after the instructions s +13796|26698|4205|4|42|68236.98|0.07|0.07|N|O|1997-06-27|1997-09-13|1997-07-02|COLLECT COD|SHIP|gular escapades. bl +13797|66981|4500|1|34|66231.32|0.02|0.02|N|O|1996-12-14|1996-11-02|1997-01-08|NONE|TRUCK|osits. final deposits use b +13797|145243|272|2|18|23188.32|0.03|0.08|N|O|1996-11-23|1996-11-03|1996-12-22|COLLECT COD|RAIL|gular theodolites. realms boo +13797|87104|7105|3|22|24004.20|0.08|0.04|N|O|1996-10-07|1996-10-05|1996-10-28|COLLECT COD|MAIL|y silent dependencies. blithely final depo +13797|150810|8356|4|35|65128.35|0.06|0.02|N|O|1996-09-09|1996-10-23|1996-09-30|NONE|TRUCK| carefully unusua +13797|54194|6700|5|36|41334.84|0.10|0.07|N|O|1996-10-31|1996-10-27|1996-11-13|NONE|SHIP|ckages are furiously around +13797|35201|208|6|11|12498.20|0.06|0.04|N|O|1996-11-28|1996-11-12|1996-12-17|TAKE BACK RETURN|FOB|en request +13798|127534|2559|1|30|46845.90|0.01|0.01|N|O|1996-03-31|1996-03-19|1996-04-07|COLLECT COD|REG AIR| final, express dolphins sl +13798|56561|1572|2|26|39456.56|0.08|0.06|N|O|1996-05-24|1996-04-28|1996-05-29|NONE|FOB|entiments. requests are accounts. s +13798|13647|8650|3|11|17167.04|0.01|0.02|N|O|1996-06-02|1996-04-10|1996-06-20|DELIVER IN PERSON|AIR|. ironic ide +13798|148828|8829|4|29|54427.78|0.02|0.01|N|O|1996-05-05|1996-04-22|1996-05-17|DELIVER IN PERSON|SHIP| ideas are. slyly express pinto be +13799|50524|3030|1|42|61929.84|0.09|0.03|R|F|1994-01-30|1994-01-09|1994-02-21|TAKE BACK RETURN|SHIP|tithes. slyly silent requests are carefull +13799|152193|2194|2|39|48562.41|0.07|0.02|R|F|1994-03-04|1994-03-01|1994-03-15|DELIVER IN PERSON|RAIL| slyly fin +13799|102297|2298|3|38|49373.02|0.07|0.06|A|F|1994-03-27|1994-01-29|1994-04-15|NONE|RAIL|nding instruction +13824|129495|9496|1|33|50308.17|0.01|0.07|R|F|1995-04-26|1995-03-08|1995-05-04|COLLECT COD|TRUCK|sly accord +13824|19170|6674|2|8|8713.36|0.04|0.03|A|F|1995-01-15|1995-02-25|1995-02-06|TAKE BACK RETURN|FOB|e. special requests nag fina +13824|182867|422|3|19|37047.34|0.08|0.01|A|F|1995-03-01|1995-02-24|1995-03-29|TAKE BACK RETURN|REG AIR|riously pending, idle r +13824|41713|6722|4|27|44677.17|0.09|0.05|A|F|1995-03-19|1995-03-18|1995-04-03|DELIVER IN PERSON|TRUCK|aringly silent requests boost slyly. +13825|1286|6287|1|34|40367.52|0.06|0.03|A|F|1994-04-14|1994-05-03|1994-04-15|TAKE BACK RETURN|MAIL|g to the regular epitaphs! ironic depos +13825|198222|5780|2|5|6601.10|0.04|0.06|R|F|1994-05-01|1994-04-29|1994-05-02|TAKE BACK RETURN|SHIP|e boldly reg +13825|108726|3747|3|19|32959.68|0.10|0.08|R|F|1994-05-21|1994-04-26|1994-06-01|COLLECT COD|FOB|onic deposits beneath the +13825|157439|4985|4|29|43396.47|0.09|0.06|R|F|1994-07-08|1994-04-29|1994-08-07|TAKE BACK RETURN|REG AIR| silent, express requests. furiou +13825|77246|9754|5|2|2446.48|0.04|0.07|A|F|1994-06-17|1994-06-11|1994-06-18|DELIVER IN PERSON|MAIL| asymptotes +13825|66925|9432|6|11|20811.12|0.03|0.01|A|F|1994-05-14|1994-05-22|1994-05-15|COLLECT COD|TRUCK|ously expr +13825|198404|924|7|29|43569.60|0.04|0.04|A|F|1994-07-03|1994-05-27|1994-07-05|NONE|FOB| blithely ironic +13826|166572|4121|1|3|4915.71|0.00|0.03|N|O|1997-06-02|1997-05-05|1997-06-04|COLLECT COD|AIR| express pinto beans after the silently reg +13826|165568|3117|2|10|16335.60|0.06|0.01|N|O|1997-03-21|1997-04-25|1997-04-08|NONE|MAIL|t the blithely express plate +13826|86044|3569|3|26|26781.04|0.09|0.04|N|O|1997-04-25|1997-05-20|1997-04-27|COLLECT COD|AIR|eas snooze +13826|135159|186|4|43|51348.45|0.09|0.07|N|O|1997-02-28|1997-04-16|1997-03-21|COLLECT COD|FOB|regular excuses. regular accounts are +13826|5394|7895|5|48|62370.72|0.06|0.04|N|O|1997-05-01|1997-04-17|1997-05-13|NONE|SHIP|unusual packages h +13827|126891|9404|1|38|72879.82|0.01|0.01|R|F|1993-08-08|1993-09-17|1993-08-11|NONE|RAIL|p furiously arou +13828|55088|99|1|31|32335.48|0.02|0.08|A|F|1994-08-06|1994-08-25|1994-08-18|NONE|MAIL|lly even excuses. furiously +13828|48793|1298|2|28|48770.12|0.07|0.05|A|F|1994-09-18|1994-09-04|1994-10-01|TAKE BACK RETURN|MAIL|y. even, unusual deposits sleep +13829|35228|5229|1|26|30243.72|0.00|0.01|N|O|1996-12-06|1996-11-18|1997-01-05|COLLECT COD|MAIL|s detect slyly final asymptote +13829|76319|8827|2|23|29792.13|0.07|0.00|N|O|1997-01-17|1996-11-30|1997-01-19|NONE|SHIP|ckly ironic ins +13829|91581|1582|3|12|18870.96|0.05|0.04|N|O|1996-09-29|1996-11-21|1996-10-20|DELIVER IN PERSON|AIR|ld ideas-- regular instructions +13829|199305|9306|4|50|70215.00|0.00|0.04|N|O|1996-11-18|1996-12-14|1996-11-25|DELIVER IN PERSON|SHIP|. platelet +13830|49896|7409|1|11|20304.79|0.03|0.05|R|F|1995-04-15|1995-02-18|1995-05-06|COLLECT COD|REG AIR|c excuses. +13830|197174|2213|2|30|38135.10|0.04|0.08|R|F|1995-03-03|1995-02-18|1995-04-01|TAKE BACK RETURN|TRUCK|ly furiously silent accounts: +13830|101086|8617|3|30|32612.40|0.07|0.00|R|F|1995-03-28|1995-01-23|1995-04-15|COLLECT COD|TRUCK|usual pinto beans. blithely regu +13830|146280|8795|4|49|64987.72|0.00|0.05|R|F|1995-04-05|1995-02-18|1995-04-23|COLLECT COD|SHIP|iously special dependenc +13831|92518|7537|1|46|69483.46|0.03|0.05|N|O|1996-05-28|1996-06-07|1996-06-05|DELIVER IN PERSON|RAIL|nd the regularly bold req +13831|140722|5751|2|38|66983.36|0.08|0.02|N|O|1996-07-03|1996-06-23|1996-07-17|DELIVER IN PERSON|AIR|kages. instructions according to the s +13831|107869|7870|3|20|37537.20|0.03|0.04|N|O|1996-07-16|1996-05-25|1996-07-30|DELIVER IN PERSON|MAIL|aggle furiously even ideas. bl +13831|150050|5081|4|30|33001.50|0.07|0.02|N|O|1996-07-31|1996-07-11|1996-08-12|NONE|RAIL|even instruc +13831|83192|717|5|12|14102.28|0.01|0.01|N|O|1996-06-09|1996-06-15|1996-06-28|COLLECT COD|REG AIR|ackages mold above the furiously exp +13831|3734|6235|6|24|39305.52|0.08|0.07|N|O|1996-06-07|1996-06-06|1996-07-03|COLLECT COD|RAIL|thely pending ide +13856|186653|9172|1|4|6958.60|0.06|0.00|N|O|1998-03-06|1998-02-26|1998-03-12|DELIVER IN PERSON|SHIP|fully ironic deposits; slyly fl +13856|60350|7869|2|8|10482.80|0.01|0.07|N|O|1997-12-09|1998-01-14|1997-12-23|COLLECT COD|TRUCK|ly final accounts boost. +13856|96445|1464|3|23|33153.12|0.06|0.07|N|O|1998-01-26|1998-01-09|1998-02-02|DELIVER IN PERSON|TRUCK|symptotes do +13856|148673|1188|4|30|51650.10|0.10|0.00|N|O|1998-01-16|1998-01-23|1998-01-18|NONE|MAIL|usly above the carefully final +13856|132269|4783|5|15|19518.90|0.02|0.01|N|O|1998-03-12|1998-01-24|1998-04-07|NONE|MAIL|ng instructions. carefully final account +13856|39682|2186|6|8|12973.44|0.10|0.03|N|O|1998-03-15|1998-01-24|1998-04-01|TAKE BACK RETURN|FOB|ers among the carefully pendin +13856|135091|5092|7|21|23647.89|0.02|0.02|N|O|1998-03-14|1998-01-09|1998-04-11|NONE|FOB|fluffily final packages about the instruct +13857|58594|8595|1|6|9315.54|0.02|0.06|N|O|1995-08-26|1995-10-11|1995-09-15|TAKE BACK RETURN|TRUCK| furiously pending hock +13858|95440|7950|1|24|34450.56|0.09|0.02|A|F|1994-07-14|1994-09-27|1994-07-15|TAKE BACK RETURN|REG AIR|nts. ironic accounts sleep slyly +13858|57643|7644|2|2|3201.28|0.09|0.05|A|F|1994-07-29|1994-08-19|1994-08-05|TAKE BACK RETURN|TRUCK|structions. quickly ironic i +13859|146389|1418|1|25|35884.50|0.02|0.07|N|O|1997-02-21|1997-03-05|1997-03-18|NONE|FOB|integrate. quickly ex +13859|150544|545|2|5|7972.70|0.00|0.03|N|O|1997-04-29|1997-03-25|1997-05-23|NONE|FOB|lay. carefully pending excuses h +13859|190886|3406|3|38|75121.44|0.06|0.03|N|O|1997-02-20|1997-03-20|1997-03-14|COLLECT COD|SHIP|sts detect +13859|18463|3466|4|10|13814.60|0.05|0.03|N|O|1997-03-16|1997-03-30|1997-03-24|TAKE BACK RETURN|REG AIR|arefully dolphins. slyly +13859|104331|4332|5|5|6676.65|0.04|0.03|N|O|1997-01-20|1997-03-15|1997-02-14|TAKE BACK RETURN|FOB|. carefully speci +13859|85149|2674|6|32|36292.48|0.02|0.00|N|O|1997-02-14|1997-03-02|1997-02-19|NONE|SHIP|fluffily thin accounts. busily regular requ +13859|95970|5971|7|27|53081.19|0.08|0.05|N|O|1997-02-13|1997-03-15|1997-02-15|TAKE BACK RETURN|RAIL|ests are quickly according to the +13860|160316|7865|1|42|57805.02|0.05|0.03|A|F|1994-11-06|1994-11-29|1994-11-19|TAKE BACK RETURN|SHIP|even, special foxes +13861|44098|1611|1|18|18757.62|0.06|0.03|A|F|1993-10-06|1993-09-23|1993-10-07|COLLECT COD|TRUCK|nts will have to wake s +13861|140484|5513|2|17|25916.16|0.03|0.08|A|F|1993-10-04|1993-10-08|1993-10-30|DELIVER IN PERSON|TRUCK|. pending orbits play +13861|98594|8595|3|29|46185.11|0.03|0.08|R|F|1993-09-21|1993-09-22|1993-10-13|TAKE BACK RETURN|FOB|ial requests +13861|61323|8842|4|31|39813.92|0.01|0.05|A|F|1993-11-20|1993-09-24|1993-12-02|DELIVER IN PERSON|REG AIR|nic excuses. final, ironic platelets inte +13861|51070|3576|5|22|22463.54|0.01|0.08|R|F|1993-11-18|1993-10-12|1993-12-03|COLLECT COD|REG AIR|ts. furiously speci +13861|123183|3184|6|25|30154.50|0.09|0.07|A|F|1993-09-28|1993-09-29|1993-10-21|TAKE BACK RETURN|MAIL| ironic instructions. final, even pinto b +13861|124285|4286|7|9|11783.52|0.05|0.05|A|F|1993-11-10|1993-09-24|1993-11-21|DELIVER IN PERSON|AIR|ual theodolites haggle furiously until th +13862|56391|3907|1|39|52548.21|0.08|0.08|N|O|1997-11-22|1997-10-28|1997-12-03|TAKE BACK RETURN|TRUCK|its use permanent +13862|147854|2883|2|34|64662.90|0.01|0.06|N|O|1997-12-22|1997-10-03|1998-01-13|COLLECT COD|RAIL|unusual depos +13862|172790|5308|3|15|27941.85|0.02|0.00|N|O|1997-10-19|1997-10-05|1997-10-28|TAKE BACK RETURN|FOB|wake alongside of the +13862|80343|5360|4|3|3970.02|0.04|0.07|N|O|1997-09-06|1997-10-14|1997-09-30|COLLECT COD|RAIL|endencies. slyly ironic accounts e +13862|111861|4373|5|34|63677.24|0.04|0.08|N|O|1997-10-06|1997-10-09|1997-11-01|NONE|MAIL|ithely special escapades. carefully bo +13862|39131|1635|6|50|53506.50|0.03|0.00|N|O|1997-10-17|1997-10-21|1997-10-18|TAKE BACK RETURN|SHIP|ar pains c +13863|159211|1727|1|19|24133.99|0.01|0.03|R|F|1992-09-14|1992-07-10|1992-10-01|COLLECT COD|FOB| sleep blithely regular reque +13863|58511|6027|2|15|22042.65|0.02|0.00|A|F|1992-09-23|1992-07-06|1992-09-27|TAKE BACK RETURN|SHIP|ly even requests use. unusual, bold ide +13863|188028|3065|3|48|53568.96|0.10|0.06|A|F|1992-06-09|1992-08-15|1992-06-22|NONE|AIR|quickly about the quickly final depen +13888|101057|3568|1|8|8464.40|0.10|0.01|R|F|1993-08-04|1993-07-04|1993-08-22|TAKE BACK RETURN|REG AIR|sly against the careful +13889|174474|2026|1|26|40260.22|0.02|0.00|N|O|1995-11-27|1995-11-24|1995-12-27|DELIVER IN PERSON|RAIL|y after the f +13889|183160|5679|2|19|23620.04|0.09|0.06|N|O|1995-12-31|1995-11-04|1996-01-06|TAKE BACK RETURN|FOB|nts wake slyly pending accounts. +13890|143656|3657|1|12|20395.80|0.04|0.01|N|O|1996-09-18|1996-06-24|1996-09-23|TAKE BACK RETURN|FOB|ar packages nag blithely carefully bold +13890|19147|1649|2|4|4264.56|0.05|0.06|N|O|1996-06-05|1996-07-04|1996-06-24|TAKE BACK RETURN|MAIL|ounts. blithely silent ideas i +13890|193524|3525|3|3|4852.56|0.04|0.02|N|O|1996-08-23|1996-08-04|1996-09-12|DELIVER IN PERSON|SHIP|ic accounts. fluffily regular accounts wak +13890|152444|2445|4|18|26935.92|0.06|0.04|N|O|1996-08-05|1996-07-27|1996-08-23|COLLECT COD|TRUCK|y express requests +13891|107268|9779|1|25|31881.50|0.08|0.00|N|O|1996-07-15|1996-08-22|1996-07-27|NONE|AIR|e special, ironic deposits. bold pinto bea +13891|41472|1473|2|17|24028.99|0.05|0.01|N|O|1996-07-24|1996-08-09|1996-08-07|TAKE BACK RETURN|SHIP|efully pending platelets +13891|18338|8339|3|5|6281.65|0.03|0.04|N|O|1996-07-09|1996-08-23|1996-07-14|TAKE BACK RETURN|MAIL|cajole in place of the slyly iron +13891|191561|6600|4|7|11567.92|0.01|0.04|N|O|1996-07-23|1996-09-09|1996-08-01|DELIVER IN PERSON|SHIP| even requests boost blithely daring +13892|34920|4921|1|49|90891.08|0.06|0.05|A|F|1992-08-09|1992-06-26|1992-09-04|NONE|AIR|ix fluffily around the quickly +13892|86042|8551|2|44|45233.76|0.06|0.08|R|F|1992-06-09|1992-06-02|1992-06-17|TAKE BACK RETURN|SHIP|aggle carefully along +13892|98009|519|3|38|38266.00|0.00|0.08|A|F|1992-07-14|1992-06-19|1992-08-05|NONE|FOB|out the quickly sly in +13893|85995|5996|1|47|93106.53|0.01|0.07|N|O|1998-06-19|1998-06-10|1998-07-11|NONE|REG AIR|ly regular excus +13893|116198|3732|2|31|37639.89|0.09|0.03|N|O|1998-05-03|1998-05-17|1998-05-06|COLLECT COD|REG AIR|structions. +13893|133397|8424|3|12|17164.68|0.04|0.00|N|O|1998-05-20|1998-06-30|1998-05-21|TAKE BACK RETURN|TRUCK|ly express theodolites. final packa +13894|22488|2489|1|22|31030.56|0.01|0.08|R|F|1992-04-19|1992-05-19|1992-05-16|DELIVER IN PERSON|RAIL|furiously silent dolphins. +13894|149824|7367|2|39|73078.98|0.01|0.02|A|F|1992-07-21|1992-05-13|1992-08-18|TAKE BACK RETURN|REG AIR|nic dependencies sleep fluffily ca +13894|87114|7115|3|8|8808.88|0.04|0.06|R|F|1992-08-06|1992-06-15|1992-08-27|TAKE BACK RETURN|TRUCK|ly ironic theodolites +13894|109587|9588|4|30|47897.40|0.09|0.08|R|F|1992-08-06|1992-06-11|1992-08-16|COLLECT COD|AIR|even accounts wake slyly unusual pac +13895|189586|2105|1|47|78752.26|0.09|0.02|R|F|1994-03-12|1994-01-27|1994-03-19|TAKE BACK RETURN|AIR|blithely slyly steal +13895|169158|1675|2|45|55221.75|0.05|0.03|R|F|1994-03-18|1994-01-21|1994-04-07|NONE|RAIL|final sauternes a +13895|26594|4101|3|9|13685.31|0.08|0.01|A|F|1994-03-17|1993-12-21|1994-04-10|COLLECT COD|REG AIR|fily even +13895|148885|6428|4|50|96694.00|0.10|0.08|A|F|1993-12-15|1994-01-13|1993-12-27|DELIVER IN PERSON|MAIL|pecial foxes. ironic accoun +13920|58231|737|1|37|44001.51|0.01|0.04|R|F|1995-01-14|1994-12-29|1995-02-02|DELIVER IN PERSON|SHIP|yly fluffily express theodolit +13920|78556|8557|2|39|59847.45|0.00|0.02|A|F|1995-01-30|1994-12-14|1995-02-17|TAKE BACK RETURN|REG AIR| haggle bold, regular +13920|80533|8058|3|19|28757.07|0.09|0.07|R|F|1995-01-17|1994-12-06|1995-01-23|NONE|REG AIR|gainst the always quiet +13921|36168|3678|1|4|4416.64|0.03|0.07|N|O|1997-09-09|1997-09-27|1997-10-05|COLLECT COD|FOB|ounts. fluffily even packag +13921|74379|6887|2|40|54134.80|0.01|0.04|N|O|1997-09-07|1997-10-29|1997-09-09|NONE|AIR|nic requests cajole furious theodoli +13921|87825|5350|3|14|25379.48|0.03|0.08|N|O|1997-10-16|1997-11-05|1997-11-04|DELIVER IN PERSON|SHIP|lites. furiously pending +13921|74438|4439|4|33|46610.19|0.03|0.01|N|O|1997-12-07|1997-10-12|1998-01-03|NONE|MAIL|ss the slyly exp +13922|16168|6169|1|14|15178.24|0.08|0.03|N|O|1995-10-13|1995-09-28|1995-11-06|COLLECT COD|FOB|eposits x-ray blithely over +13922|126747|4284|2|50|88687.00|0.03|0.00|N|O|1995-09-18|1995-10-11|1995-10-04|DELIVER IN PERSON|TRUCK|metimes. reg +13922|24282|6785|3|37|44632.36|0.01|0.05|N|O|1995-09-30|1995-10-17|1995-10-29|NONE|SHIP| courts sleep among the p +13922|102792|7813|4|45|80765.55|0.02|0.07|N|O|1995-11-20|1995-10-23|1995-11-24|COLLECT COD|MAIL| unusual requests. carefully blit +13922|11312|8816|5|20|24466.20|0.00|0.07|N|O|1995-10-11|1995-09-14|1995-10-26|TAKE BACK RETURN|SHIP|nic requests. furiously unusual foxes c +13922|109741|7272|6|41|71780.34|0.09|0.08|N|O|1995-11-01|1995-10-25|1995-11-16|TAKE BACK RETURN|MAIL|ounts sleep bli +13922|14914|7416|7|32|58525.12|0.09|0.06|N|O|1995-08-31|1995-09-28|1995-09-22|COLLECT COD|FOB|cajole carefully about the reg +13923|55436|5437|1|42|58440.06|0.02|0.00|R|F|1992-09-02|1992-09-20|1992-09-27|DELIVER IN PERSON|RAIL|ages. bold Tiresi +13923|97143|2162|2|13|14821.82|0.07|0.03|A|F|1992-10-19|1992-09-09|1992-11-01|TAKE BACK RETURN|RAIL|tealthily spe +13923|73669|1191|3|1|1642.66|0.00|0.03|R|F|1992-07-23|1992-09-24|1992-07-26|COLLECT COD|AIR|wake furiously accordi +13923|154198|6714|4|26|32556.94|0.06|0.01|R|F|1992-10-01|1992-09-08|1992-10-08|NONE|REG AIR| unusual, unusual excuses affix. ca +13923|197076|7077|5|2|2346.14|0.08|0.05|A|F|1992-08-15|1992-08-14|1992-08-27|NONE|REG AIR| excuses print carefully bli +13923|43730|8739|6|24|40169.52|0.05|0.04|A|F|1992-09-17|1992-08-20|1992-10-06|COLLECT COD|AIR|o beans against the f +13924|98639|1149|1|2|3275.26|0.05|0.02|A|F|1995-04-03|1995-01-28|1995-04-28|DELIVER IN PERSON|SHIP|l courts about the slyly regular frets nag +13925|81268|3777|1|16|19988.16|0.01|0.07|N|O|1997-04-29|1997-03-16|1997-05-24|TAKE BACK RETURN|FOB|y about the regular dolphins. blithel +13925|56193|6194|2|16|18387.04|0.00|0.03|N|O|1997-02-14|1997-02-07|1997-02-24|DELIVER IN PERSON|FOB|s print slyly final pa +13925|32898|408|3|1|1830.89|0.06|0.08|N|O|1997-04-06|1997-02-11|1997-05-04|NONE|REG AIR|furiously ironic sheaves. requests acro +13925|111554|4066|4|38|59490.90|0.06|0.08|N|O|1997-03-08|1997-03-17|1997-03-25|COLLECT COD|MAIL|e alongside of the furiously un +13925|76621|1636|5|43|68697.66|0.09|0.05|N|O|1997-01-19|1997-03-24|1997-02-04|NONE|AIR|p against the final accounts. pendin +13926|180260|5297|1|28|37527.28|0.10|0.05|N|O|1997-08-29|1997-08-17|1997-09-26|NONE|AIR|ke furiously at the quickly ironi +13926|28661|3666|2|1|1589.66|0.01|0.01|N|O|1997-09-14|1997-08-12|1997-09-26|NONE|AIR|the furiously silent sheaves. ironic, +13926|89759|2268|3|3|5246.25|0.00|0.08|N|O|1997-10-30|1997-09-19|1997-11-05|COLLECT COD|SHIP|even deposits cajole quickly +13927|109042|4063|1|17|17867.68|0.04|0.00|R|F|1994-11-13|1994-10-10|1994-12-07|TAKE BACK RETURN|FOB|ss accounts engage slyly instructions; pen +13927|54949|9960|2|9|17135.46|0.05|0.02|A|F|1994-11-27|1994-11-16|1994-12-07|DELIVER IN PERSON|SHIP|usly unusual ac +13927|122669|7694|3|21|35524.86|0.05|0.01|R|F|1994-09-08|1994-11-11|1994-09-13|COLLECT COD|SHIP| foxes sleep. ironic ideas +13927|95170|189|4|24|27964.08|0.01|0.06|A|F|1994-11-27|1994-10-29|1994-12-02|TAKE BACK RETURN|FOB|to beans. furiously final theodolite +13927|116240|6241|5|6|7537.44|0.00|0.02|A|F|1994-12-05|1994-10-10|1994-12-07|TAKE BACK RETURN|FOB|posits sleep slyly caref +13927|41125|3630|6|13|13859.56|0.00|0.00|R|F|1994-10-19|1994-11-25|1994-10-25|COLLECT COD|MAIL|g according to the ironic package +13952|27050|7051|1|31|30288.55|0.05|0.06|N|O|1997-06-06|1997-06-03|1997-06-18|DELIVER IN PERSON|REG AIR|press depe +13952|13167|8170|2|41|44286.56|0.09|0.02|N|O|1997-08-12|1997-07-24|1997-08-28|COLLECT COD|AIR|y ironic, regular courts. qui +13952|84858|2383|3|22|40542.70|0.03|0.05|N|O|1997-05-28|1997-06-28|1997-06-08|TAKE BACK RETURN|REG AIR|express excuses. carefully ru +13953|183927|1482|1|29|58316.68|0.02|0.02|N|O|1995-09-09|1995-08-22|1995-09-24|COLLECT COD|AIR|lar packages cajole blithely. car +13953|58579|6095|2|49|75340.93|0.05|0.06|N|O|1995-09-09|1995-08-03|1995-09-10|NONE|TRUCK| slyly about the r +13953|133161|701|3|48|57319.68|0.03|0.07|N|O|1995-08-11|1995-08-14|1995-09-02|COLLECT COD|REG AIR|uests haggle slyly. theodol +13953|22484|7489|4|47|66104.56|0.09|0.01|N|O|1995-08-15|1995-07-09|1995-08-28|NONE|TRUCK|ecial deposits. carefully regular dependen +13954|196115|8635|1|3|3633.33|0.05|0.06|N|O|1996-06-17|1996-06-13|1996-07-03|COLLECT COD|REG AIR|the ironically regular deposits. expr +13954|97636|2655|2|45|73513.35|0.08|0.08|N|O|1996-08-30|1996-06-08|1996-09-28|TAKE BACK RETURN|RAIL| deposits. quickly ironic +13954|164891|7408|3|20|39117.80|0.06|0.07|N|O|1996-06-06|1996-06-17|1996-06-25|DELIVER IN PERSON|REG AIR|luffy packages are never above the carefu +13954|108191|3212|4|13|15589.47|0.06|0.01|N|O|1996-07-03|1996-06-13|1996-07-12|COLLECT COD|RAIL| according to the final accounts use final +13955|97215|2234|1|28|33941.88|0.00|0.00|N|O|1998-07-18|1998-07-02|1998-08-09|DELIVER IN PERSON|REG AIR|accounts after the blithely regular t +13955|77570|78|2|8|12380.56|0.10|0.00|N|O|1998-05-20|1998-08-05|1998-06-03|DELIVER IN PERSON|FOB|nusual packages. +13955|112304|2305|3|16|21060.80|0.06|0.00|N|O|1998-07-31|1998-07-24|1998-08-10|TAKE BACK RETURN|MAIL|y even packages. +13955|92489|17|4|42|62222.16|0.01|0.08|N|O|1998-08-10|1998-07-14|1998-08-22|COLLECT COD|RAIL|rmanent excuses. even, bo +13956|112692|226|1|20|34093.80|0.03|0.03|A|F|1995-04-02|1995-04-27|1995-04-03|TAKE BACK RETURN|TRUCK|s instructions. slyly bold +13956|197969|5527|2|13|26870.48|0.05|0.04|R|F|1995-05-09|1995-05-02|1995-05-13|TAKE BACK RETURN|REG AIR|onic, regular packages boost slyly. pend +13956|53833|8844|3|4|7147.32|0.08|0.00|N|F|1995-06-12|1995-05-03|1995-06-20|COLLECT COD|TRUCK|deposits instead of the packa +13956|165692|5693|4|38|66792.22|0.10|0.07|N|O|1995-07-04|1995-04-17|1995-07-13|TAKE BACK RETURN|TRUCK|ajole slyly. carefully ironic pa +13957|152582|128|1|46|75190.68|0.05|0.00|N|O|1995-08-13|1995-10-12|1995-08-30|TAKE BACK RETURN|TRUCK| nag carefully even packages. fluffily e +13957|33063|5567|2|32|31873.92|0.07|0.06|N|O|1995-09-09|1995-09-12|1995-10-05|COLLECT COD|MAIL| accounts wake gifts. fluffily d +13957|79434|1942|3|48|67844.64|0.09|0.02|N|O|1995-09-19|1995-09-21|1995-09-30|NONE|RAIL|y under the slyly e +13958|109665|2176|1|7|11722.62|0.10|0.00|R|F|1993-03-15|1993-03-08|1993-03-31|TAKE BACK RETURN|MAIL|s instructions. pending ideas sleep +13958|126365|1390|2|29|40349.44|0.10|0.02|R|F|1993-04-23|1993-03-13|1993-05-04|TAKE BACK RETURN|TRUCK|egular theodolites wake agai +13958|10920|3422|3|16|29294.72|0.10|0.01|A|F|1993-04-25|1993-03-31|1993-05-20|DELIVER IN PERSON|TRUCK|eas after the quickly bold fo +13959|124028|9053|1|44|46288.88|0.03|0.04|R|F|1994-05-09|1994-05-25|1994-05-25|DELIVER IN PERSON|SHIP|fily final requ +13959|122936|2937|2|47|92069.71|0.10|0.01|R|F|1994-07-22|1994-05-11|1994-07-30|NONE|FOB|are around the dolphin +13984|92361|2362|1|39|52781.04|0.07|0.00|A|F|1992-11-30|1992-11-08|1992-12-21|TAKE BACK RETURN|AIR|l pinto beans. fin +13984|108573|3594|2|45|71170.65|0.07|0.08|R|F|1992-12-03|1992-11-25|1992-12-16|NONE|MAIL|y slyly even +13984|182037|7074|3|1|1119.03|0.00|0.04|A|F|1993-01-22|1992-11-12|1993-02-17|COLLECT COD|REG AIR| nag slyly ironic ideas. f +13984|79300|1808|4|48|61406.40|0.01|0.06|A|F|1992-12-19|1992-12-17|1992-12-22|DELIVER IN PERSON|FOB|ses. furiously even gifts wake furi +13985|35416|7920|1|7|9459.87|0.02|0.08|N|O|1998-10-09|1998-08-24|1998-11-02|NONE|SHIP|s haggle beyond the slyly bold dinos. regu +13985|36502|1509|2|7|10069.50|0.05|0.08|N|O|1998-08-22|1998-08-26|1998-09-08|NONE|RAIL|. furiously regular accounts use furiousl +13985|87827|5352|3|38|68963.16|0.06|0.03|N|O|1998-07-24|1998-07-15|1998-08-03|COLLECT COD|SHIP|es are! silent, regular a +13985|103296|3297|4|36|46774.44|0.09|0.04|N|O|1998-09-09|1998-07-24|1998-09-18|DELIVER IN PERSON|MAIL|inal pinto beans. always pending package +13985|80572|573|5|8|12420.56|0.04|0.06|N|O|1998-08-17|1998-07-15|1998-08-20|NONE|REG AIR|g deposits: f +13985|164261|6778|6|29|38432.54|0.01|0.02|N|O|1998-07-02|1998-08-07|1998-07-29|DELIVER IN PERSON|MAIL|platelets sleep carefully? even dependenci +13986|35526|533|1|9|13153.68|0.00|0.08|N|O|1995-11-07|1995-11-13|1995-11-20|DELIVER IN PERSON|TRUCK|old packages use. +13986|73059|581|2|24|24769.20|0.03|0.04|N|O|1995-11-07|1996-01-04|1995-11-16|DELIVER IN PERSON|TRUCK|he final accounts; pinto beans wak +13986|87191|2208|3|23|27098.37|0.10|0.05|N|O|1996-02-09|1996-01-02|1996-03-01|TAKE BACK RETURN|AIR| theodolites. slyly silent deposits are +13986|12776|7779|4|13|21954.01|0.07|0.08|N|O|1995-11-16|1996-01-05|1995-11-29|DELIVER IN PERSON|REG AIR|le blithely a +13987|47483|2492|1|25|35762.00|0.07|0.03|N|O|1998-07-28|1998-05-17|1998-08-12|TAKE BACK RETURN|RAIL|refully fina +13987|32567|7574|2|20|29991.20|0.04|0.05|N|O|1998-07-25|1998-05-17|1998-08-23|DELIVER IN PERSON|AIR|carefully brave foxes. carefully final p +13987|147955|7956|3|5|10014.75|0.09|0.07|N|O|1998-07-28|1998-07-01|1998-08-22|DELIVER IN PERSON|TRUCK|y even patter +13988|28827|3832|1|40|70232.80|0.03|0.08|A|F|1992-08-22|1992-09-15|1992-08-27|NONE|SHIP|slyly final instructions. evenly sile +13988|78847|3862|2|10|18258.40|0.07|0.06|A|F|1992-08-29|1992-10-30|1992-09-24|DELIVER IN PERSON|FOB|s. even deposits unwind +13988|172544|2545|3|28|45263.12|0.01|0.06|A|F|1992-12-01|1992-09-21|1992-12-27|COLLECT COD|AIR|ncies. regular, reg +13989|173056|8091|1|14|15806.70|0.03|0.01|N|O|1997-07-26|1997-09-18|1997-07-30|NONE|FOB|nto the the +13989|149139|1654|2|49|58218.37|0.06|0.05|N|O|1997-09-26|1997-08-27|1997-10-23|DELIVER IN PERSON|RAIL| warthogs +13989|162896|2897|3|33|64643.37|0.04|0.08|N|O|1997-08-13|1997-08-25|1997-08-20|COLLECT COD|REG AIR|tes mold furiously. blithely pending i +13989|184382|6901|4|7|10264.66|0.02|0.06|N|O|1997-10-11|1997-08-11|1997-11-08|COLLECT COD|MAIL|eep fluffily amon +13989|106581|6582|5|37|58740.46|0.05|0.02|N|O|1997-11-01|1997-08-18|1997-11-12|DELIVER IN PERSON|SHIP|. regular requests hang slyly even f +13990|96939|9449|1|11|21295.23|0.04|0.01|N|O|1998-05-10|1998-03-10|1998-06-04|TAKE BACK RETURN|AIR|ep blithely. +13990|39816|7326|2|13|22825.53|0.01|0.01|N|O|1998-05-13|1998-03-16|1998-05-15|TAKE BACK RETURN|FOB|past the furiou +13990|170884|3402|3|12|23458.56|0.06|0.02|N|O|1998-03-10|1998-04-18|1998-03-18|TAKE BACK RETURN|REG AIR|inal requests-- carefully +13990|37299|4809|4|5|6181.45|0.02|0.05|N|O|1998-03-14|1998-04-09|1998-03-30|TAKE BACK RETURN|RAIL|uickly after the regular, unusual +13990|80288|2797|5|37|46926.36|0.05|0.03|N|O|1998-05-30|1998-03-29|1998-06-20|DELIVER IN PERSON|TRUCK| the slyly final theodolites. blithel +13990|198060|5618|6|11|12738.66|0.07|0.03|N|O|1998-05-04|1998-04-05|1998-05-10|NONE|TRUCK|ke carefully sl +13991|185788|8307|1|17|31854.26|0.10|0.01|R|F|1992-06-04|1992-04-12|1992-06-26|NONE|SHIP|ests sleep slyly. sheaves sleep above t +13991|136728|4268|2|43|75882.96|0.02|0.02|A|F|1992-04-17|1992-04-14|1992-05-12|DELIVER IN PERSON|FOB| beans nag blithely above th +13991|182085|2086|3|32|37346.56|0.03|0.05|A|F|1992-03-21|1992-05-08|1992-04-18|TAKE BACK RETURN|SHIP|ironic asymptotes? blithely unusua +13991|88600|3617|4|43|68309.80|0.00|0.00|R|F|1992-03-18|1992-06-02|1992-03-21|COLLECT COD|FOB|lar packages slee +13991|89875|9876|5|26|48486.62|0.02|0.01|A|F|1992-03-28|1992-04-25|1992-04-02|DELIVER IN PERSON|SHIP|the ideas. accounts are c +14016|190582|5621|1|14|23416.12|0.00|0.00|A|F|1992-09-29|1992-08-12|1992-10-11|TAKE BACK RETURN|AIR|integrate Tiresias. furiously e +14016|105291|312|2|44|57036.76|0.08|0.02|A|F|1992-10-31|1992-08-25|1992-11-16|COLLECT COD|RAIL|ges affix carefully accord +14016|21047|8554|3|41|39689.64|0.07|0.01|R|F|1992-07-18|1992-09-21|1992-08-05|COLLECT COD|FOB|slyly silent foxes. final accounts na +14016|131300|6327|4|48|63902.40|0.03|0.06|A|F|1992-08-27|1992-08-14|1992-09-12|NONE|RAIL|riously even a +14016|148151|3180|5|2|2398.30|0.02|0.02|R|F|1992-10-31|1992-09-07|1992-11-11|DELIVER IN PERSON|RAIL| ironic accounts ar +14016|165613|8130|6|18|30214.98|0.10|0.08|R|F|1992-09-09|1992-09-20|1992-09-10|DELIVER IN PERSON|TRUCK|deposits. slyly even requ +14016|54443|1959|7|3|4192.32|0.10|0.00|A|F|1992-08-17|1992-09-30|1992-09-16|NONE|AIR|es. expres +14017|20429|7936|1|10|13494.20|0.08|0.05|A|F|1994-07-02|1994-05-13|1994-07-12|NONE|TRUCK|uests. special deposits x-ray. rut +14017|140411|412|2|22|31931.02|0.10|0.03|R|F|1994-05-06|1994-04-17|1994-05-18|NONE|RAIL|press foxes wak +14017|78510|1018|3|31|46143.81|0.05|0.06|R|F|1994-04-21|1994-05-12|1994-05-17|DELIVER IN PERSON|TRUCK|. carefully final d +14017|109378|9379|4|37|51332.69|0.06|0.03|R|F|1994-05-12|1994-06-05|1994-05-25|NONE|FOB|tes play slyly after the ironic, +14017|114972|4973|5|1|1986.97|0.00|0.08|R|F|1994-05-17|1994-05-29|1994-06-14|DELIVER IN PERSON|REG AIR|ts above the fin +14017|119517|7051|6|14|21511.14|0.02|0.06|R|F|1994-06-16|1994-04-29|1994-06-20|TAKE BACK RETURN|FOB|efully carefully bold dependencies. care +14018|32997|8004|1|11|21229.89|0.00|0.03|R|F|1993-08-05|1993-08-02|1993-08-25|COLLECT COD|AIR| blithely according +14018|174454|2006|2|16|24455.20|0.06|0.03|A|F|1993-07-28|1993-08-17|1993-08-03|NONE|FOB|its. blithely pending re +14018|36619|9123|3|21|32667.81|0.03|0.01|A|F|1993-06-20|1993-07-26|1993-07-18|DELIVER IN PERSON|TRUCK|cross the regular packages hinder pendin +14018|46451|1460|4|27|37731.15|0.07|0.04|A|F|1993-06-08|1993-08-13|1993-06-25|COLLECT COD|AIR|brave requests. iron +14019|47545|5058|1|6|8955.24|0.05|0.00|N|O|1997-12-17|1997-10-21|1998-01-12|COLLECT COD|MAIL|hins. fluffily even i +14019|73913|8928|2|30|56607.30|0.01|0.07|N|O|1997-11-23|1997-11-07|1997-12-07|COLLECT COD|RAIL|nic deposits: special instructi +14019|39895|9896|3|47|86239.83|0.05|0.04|N|O|1997-11-27|1997-12-05|1997-11-29|NONE|FOB| cajole quickly alongside of the special d +14019|99689|2199|4|19|32084.92|0.01|0.03|N|O|1997-10-16|1997-12-01|1997-11-13|DELIVER IN PERSON|AIR|s among the fluffily special requests boo +14019|59582|9583|5|39|60121.62|0.05|0.07|N|O|1997-10-14|1997-11-12|1997-10-30|TAKE BACK RETURN|MAIL|sits wake furiously blithely ironic acc +14020|197282|4840|1|24|33102.72|0.00|0.03|N|O|1998-04-02|1998-03-23|1998-04-10|COLLECT COD|TRUCK|unts. packages are carefully about the f +14020|102615|146|2|33|53381.13|0.06|0.01|N|O|1998-04-16|1998-04-16|1998-04-23|NONE|REG AIR|re evenly even, final theodolites. bli +14021|199795|7353|1|4|7579.16|0.10|0.00|A|F|1995-04-17|1995-05-13|1995-04-21|DELIVER IN PERSON|FOB|cally slowly +14021|140451|7994|2|34|50709.30|0.02|0.00|A|F|1995-04-08|1995-05-11|1995-04-14|COLLECT COD|RAIL|sts haggle slyly. final ideas ca +14021|151820|4336|3|20|37436.40|0.10|0.02|R|F|1995-03-12|1995-05-03|1995-03-31|DELIVER IN PERSON|REG AIR|he regular, ironic instructions. furiously +14021|36830|1837|4|40|70673.20|0.02|0.00|N|O|1995-06-27|1995-06-05|1995-07-01|TAKE BACK RETURN|REG AIR|l instructions out +14021|196445|8965|5|27|41618.88|0.10|0.05|A|F|1995-04-04|1995-04-17|1995-04-22|TAKE BACK RETURN|TRUCK|ual foxes. furiously ir +14021|49016|9017|6|15|14475.15|0.00|0.00|R|F|1995-05-09|1995-04-26|1995-05-18|NONE|RAIL|ly final packages. deposi +14021|6778|9279|7|12|20217.24|0.01|0.02|A|F|1995-06-03|1995-05-09|1995-06-09|DELIVER IN PERSON|SHIP|ly bold requests are fluffily according to +14022|110756|3268|1|4|7067.00|0.05|0.00|R|F|1995-05-16|1995-05-03|1995-06-14|TAKE BACK RETURN|AIR|ully ironic excuses doze quickly. ironic +14022|69831|4844|2|41|73834.03|0.03|0.06|N|F|1995-06-08|1995-04-01|1995-06-28|TAKE BACK RETURN|REG AIR|es use against the +14023|27236|9739|1|36|41876.28|0.06|0.08|R|F|1993-05-15|1993-05-04|1993-05-30|TAKE BACK RETURN|RAIL|al accounts are blithely according to the s +14023|147153|9668|2|3|3600.45|0.02|0.02|R|F|1993-04-17|1993-05-05|1993-05-07|COLLECT COD|TRUCK|lly express pack +14023|197819|7820|3|31|59421.11|0.06|0.07|R|F|1993-04-20|1993-04-13|1993-04-30|TAKE BACK RETURN|RAIL|ress, regular ac +14023|137022|4562|4|17|18003.34|0.04|0.05|A|F|1993-02-28|1993-04-10|1993-03-22|DELIVER IN PERSON|SHIP|nic deposits. c +14048|101818|1819|1|25|45495.25|0.02|0.07|R|F|1993-08-26|1993-06-27|1993-09-13|NONE|SHIP|; regular instructions print furiously. +14048|38483|3490|2|7|9950.36|0.01|0.08|A|F|1993-08-25|1993-07-27|1993-09-01|COLLECT COD|TRUCK|telets. regular epitaphs cajole caref +14048|178336|8337|3|30|42429.90|0.00|0.00|A|F|1993-06-07|1993-07-29|1993-06-21|COLLECT COD|FOB|s nag quickly. sly dolphins +14048|84919|9936|4|37|70444.67|0.08|0.06|R|F|1993-07-02|1993-06-24|1993-07-19|COLLECT COD|AIR|ongside of +14048|18521|3524|5|35|50383.20|0.02|0.08|A|F|1993-09-09|1993-08-01|1993-10-01|TAKE BACK RETURN|AIR|at the pending accounts boost fluffil +14048|67785|5304|6|2|3505.56|0.10|0.01|A|F|1993-06-13|1993-07-29|1993-07-06|TAKE BACK RETURN|RAIL|he silent packa +14048|60406|5419|7|21|28694.40|0.06|0.03|A|F|1993-06-04|1993-07-20|1993-06-20|NONE|SHIP|sts among the ironic packages maintain q +14049|31311|1312|1|39|48450.09|0.00|0.02|N|O|1996-05-14|1996-04-27|1996-05-24|DELIVER IN PERSON|MAIL| haggle according to the slyly da +14049|42697|5202|2|3|4919.07|0.06|0.00|N|O|1996-02-22|1996-03-22|1996-03-15|COLLECT COD|RAIL| regular asymptotes breach quickly bl +14049|192490|48|3|10|15824.90|0.07|0.07|N|O|1996-05-07|1996-03-31|1996-05-31|TAKE BACK RETURN|AIR|gside of the carefully r +14050|130335|336|1|7|9557.31|0.01|0.02|N|O|1997-10-27|1997-10-17|1997-11-21|COLLECT COD|FOB|egular platelets. regular, ironic request +14050|130444|5471|2|14|20642.16|0.08|0.08|N|O|1997-10-19|1997-09-26|1997-10-25|DELIVER IN PERSON|RAIL|inal foxes haggle. even asymptotes haggle +14050|165784|5785|3|32|59192.96|0.08|0.04|N|O|1997-09-07|1997-10-19|1997-09-28|COLLECT COD|SHIP|he fluffy packages. pa +14050|124176|1713|4|8|9601.36|0.00|0.08|N|O|1997-12-05|1997-11-17|1997-12-14|COLLECT COD|MAIL| regular platelets +14050|12589|7592|5|47|70574.26|0.07|0.04|N|O|1997-11-09|1997-09-26|1997-11-23|NONE|FOB|even dugouts. fluffily even account +14050|170806|8358|6|21|39412.80|0.06|0.01|N|O|1997-09-07|1997-10-06|1997-09-29|TAKE BACK RETURN|TRUCK|ons detect slyly +14051|29603|4608|1|19|29119.40|0.06|0.04|A|F|1993-10-12|1993-11-25|1993-11-10|TAKE BACK RETURN|FOB|cording to the furiousl +14052|140796|797|1|17|31225.43|0.04|0.08|R|F|1995-04-15|1995-04-17|1995-04-18|NONE|AIR|o the blit +14053|156746|4292|1|4|7210.96|0.10|0.08|R|F|1993-03-12|1993-03-22|1993-04-08|NONE|REG AIR|s sleep. even, special th +14053|23655|1162|2|19|29994.35|0.10|0.02|A|F|1993-04-26|1993-04-29|1993-04-30|NONE|REG AIR|theodolites abov +14054|139493|4520|1|46|70494.54|0.06|0.01|N|O|1996-04-10|1996-04-10|1996-04-11|NONE|FOB|slyly pending deposits along +14054|44368|4369|2|40|52494.40|0.09|0.07|N|O|1996-03-12|1996-02-15|1996-03-31|COLLECT COD|MAIL| carefully even deposits nag stealthily +14054|88745|6270|3|13|22538.62|0.05|0.05|N|O|1996-04-24|1996-04-03|1996-05-22|NONE|REG AIR|t deposits use fur +14054|131715|6742|4|20|34934.20|0.06|0.02|N|O|1996-04-12|1996-04-07|1996-04-30|DELIVER IN PERSON|AIR|ven packages. carefully ironic somas +14054|120775|776|5|17|30528.09|0.08|0.02|N|O|1996-01-26|1996-03-07|1996-02-13|DELIVER IN PERSON|RAIL|ackages. requests are furio +14054|48907|8908|6|32|59388.80|0.02|0.03|N|O|1996-03-08|1996-02-18|1996-03-19|COLLECT COD|SHIP|ns breach across the special accou +14054|165582|8099|7|45|74141.10|0.10|0.07|N|O|1996-01-25|1996-04-03|1996-02-17|NONE|RAIL|regular instructions haggle car +14055|135791|8305|1|46|84032.34|0.05|0.06|A|F|1994-12-08|1994-11-22|1994-12-14|COLLECT COD|RAIL|y special deposits use atop +14055|37516|20|2|1|1453.51|0.02|0.04|A|F|1994-12-12|1994-11-17|1994-12-17|DELIVER IN PERSON|SHIP|the carefull +14055|126830|4367|3|26|48277.58|0.06|0.07|A|F|1994-09-12|1994-11-19|1994-09-20|COLLECT COD|REG AIR| sleep furiously +14080|79562|2070|1|38|58579.28|0.04|0.01|N|O|1998-08-19|1998-07-11|1998-09-12|DELIVER IN PERSON|MAIL|against the +14081|70954|3462|1|45|86622.75|0.10|0.06|R|F|1993-10-14|1994-01-04|1993-10-29|TAKE BACK RETURN|REG AIR|ts. pending platele +14081|121672|6697|2|41|69440.47|0.08|0.07|A|F|1994-02-02|1993-11-24|1994-02-23|TAKE BACK RETURN|RAIL| bold foxes doubt bold excuses. furious +14082|95605|624|1|28|44816.80|0.10|0.03|N|O|1998-06-17|1998-06-10|1998-07-09|NONE|FOB|bold dependencies sleep alongs +14083|56563|1574|1|8|12156.48|0.00|0.00|A|F|1994-11-12|1994-10-17|1994-12-04|TAKE BACK RETURN|AIR|. express accounts h +14084|190259|7817|1|43|58017.75|0.07|0.02|N|O|1995-10-27|1995-10-31|1995-11-07|COLLECT COD|MAIL|ular pinto beans sl +14084|79390|1898|2|46|62991.94|0.05|0.00|N|O|1995-09-01|1995-09-08|1995-09-14|COLLECT COD|RAIL| foxes cajole blithel +14084|98209|719|3|31|37423.20|0.04|0.05|N|O|1995-10-23|1995-10-18|1995-10-29|TAKE BACK RETURN|TRUCK|s. ironic packag +14084|197744|5302|4|43|79194.82|0.00|0.08|N|O|1995-08-12|1995-10-09|1995-08-18|COLLECT COD|REG AIR|ut the idly pending id +14084|74901|9916|5|6|11255.40|0.02|0.02|N|O|1995-08-25|1995-10-12|1995-09-18|TAKE BACK RETURN|SHIP|. theodolites sleep-- packages cajole a +14085|112495|29|1|34|51254.66|0.09|0.03|R|F|1994-03-04|1994-04-17|1994-03-05|DELIVER IN PERSON|TRUCK|ding, final multipliers boo +14085|86723|9232|2|7|11968.04|0.07|0.01|A|F|1994-03-01|1994-03-11|1994-03-15|COLLECT COD|RAIL|instructions acro +14085|141508|4023|3|34|52683.00|0.09|0.03|R|F|1994-05-29|1994-04-03|1994-06-04|DELIVER IN PERSON|SHIP|ke even, bold accounts. quickly +14085|118893|8894|4|50|95594.50|0.10|0.02|R|F|1994-05-25|1994-04-11|1994-06-22|TAKE BACK RETURN|MAIL|unts wake carefully pinto +14086|121179|1180|1|7|8401.19|0.10|0.01|R|F|1993-12-26|1993-12-11|1994-01-10|NONE|RAIL|use regularly. carefully fina +14086|46187|6188|2|21|23796.78|0.04|0.04|A|F|1993-12-03|1993-12-03|1993-12-20|COLLECT COD|SHIP|as. slyly bold foxes nag carefully after t +14086|49963|7476|3|7|13390.72|0.04|0.00|A|F|1993-11-27|1994-01-09|1993-12-01|COLLECT COD|MAIL|aggle. even accounts along the p +14086|114171|9194|4|9|10666.53|0.09|0.07|R|F|1993-11-18|1993-12-15|1993-11-30|NONE|REG AIR|gular deposits haggle ag +14087|50737|3243|1|23|38817.79|0.00|0.06|N|O|1997-04-18|1997-04-06|1997-04-23|TAKE BACK RETURN|REG AIR|ly ironic pin +14087|128733|3758|2|35|61660.55|0.02|0.07|N|O|1997-05-17|1997-03-28|1997-06-04|TAKE BACK RETURN|AIR|fix across the final packages. fl +14087|3642|1143|3|50|77282.00|0.08|0.00|N|O|1997-06-02|1997-05-11|1997-06-08|NONE|TRUCK| express package +14087|6616|1617|4|37|56336.57|0.06|0.02|N|O|1997-04-29|1997-03-25|1997-05-04|COLLECT COD|REG AIR|ress courts poach quickly against +14087|185362|7881|5|30|43420.80|0.01|0.02|N|O|1997-05-14|1997-03-16|1997-06-05|NONE|AIR|arefully about the silent dolphins +14112|51072|3578|1|15|15346.05|0.03|0.01|R|F|1994-09-13|1994-10-14|1994-09-20|NONE|REG AIR|he accounts. pinto beans boost furious +14113|164873|4874|1|4|7751.48|0.02|0.03|N|O|1995-09-09|1995-10-21|1995-09-17|TAKE BACK RETURN|RAIL|ntegrate after +14113|6282|1283|2|21|24953.88|0.00|0.03|N|O|1995-10-28|1995-10-19|1995-11-10|COLLECT COD|TRUCK|fully fluffy foxes. dependencies +14114|128598|8599|1|31|50424.29|0.09|0.05|A|F|1994-05-19|1994-05-22|1994-06-17|NONE|AIR|ross the blithely express +14114|142944|487|2|35|69542.90|0.01|0.06|R|F|1994-06-02|1994-06-04|1994-06-24|TAKE BACK RETURN|AIR|the always even +14114|48361|8362|3|17|22259.12|0.05|0.04|R|F|1994-05-27|1994-05-19|1994-06-14|DELIVER IN PERSON|RAIL| beans around the even accou +14114|1051|6052|4|15|14280.75|0.03|0.03|R|F|1994-05-13|1994-05-21|1994-05-24|DELIVER IN PERSON|MAIL|tes detect fluffil +14114|58786|1292|5|9|15703.02|0.08|0.02|A|F|1994-07-26|1994-05-21|1994-08-17|TAKE BACK RETURN|REG AIR|ggle. regular, even instructio +14114|10606|3108|6|40|60664.00|0.09|0.03|A|F|1994-05-12|1994-06-12|1994-06-02|TAKE BACK RETURN|MAIL|sly pending packages. even d +14115|7012|7013|1|31|28489.31|0.08|0.06|A|F|1994-09-05|1994-10-07|1994-09-24|TAKE BACK RETURN|RAIL|even deposits. instructio +14115|40351|352|2|30|38740.50|0.00|0.00|A|F|1994-11-05|1994-11-03|1994-11-27|NONE|FOB|aggle quickly at the f +14116|23980|3981|1|9|17135.82|0.04|0.01|N|O|1995-10-12|1995-12-15|1995-10-22|DELIVER IN PERSON|RAIL|ole besides +14116|29208|1711|2|7|7960.40|0.04|0.06|N|O|1995-11-09|1995-12-01|1995-12-01|TAKE BACK RETURN|AIR|s unwind carefully blithely spe +14116|98775|6303|3|30|53213.10|0.05|0.06|N|O|1995-12-17|1995-11-21|1995-12-28|DELIVER IN PERSON|MAIL|aggle. carefully pending Tiresias +14116|109854|7385|4|36|67098.60|0.00|0.07|N|O|1995-12-25|1995-12-21|1996-01-19|DELIVER IN PERSON|REG AIR| accounts. furiously even dolphins are +14116|102923|7944|5|39|75110.88|0.09|0.03|N|O|1995-12-27|1995-12-07|1996-01-10|TAKE BACK RETURN|RAIL| print quickly. sl +14116|10526|3028|6|41|58897.32|0.00|0.07|N|O|1995-12-06|1995-11-29|1995-12-16|DELIVER IN PERSON|RAIL| slyly unusual p +14117|163814|3815|1|23|43189.63|0.03|0.06|A|F|1993-10-14|1993-10-31|1993-10-25|DELIVER IN PERSON|AIR|sly regular courts. ca +14117|17696|2699|2|43|69388.67|0.09|0.04|R|F|1993-12-03|1993-10-29|1994-01-01|NONE|SHIP|ts. platelets nag clos +14117|10516|5519|3|47|67045.97|0.03|0.02|R|F|1993-11-04|1993-10-12|1993-11-05|COLLECT COD|FOB|furiously bold platelets use. furiousl +14117|136403|6404|4|48|69091.20|0.06|0.07|A|F|1993-10-09|1993-11-07|1993-10-26|TAKE BACK RETURN|MAIL|hely final d +14117|119581|9582|5|32|51218.56|0.04|0.04|A|F|1993-10-29|1993-09-27|1993-11-09|DELIVER IN PERSON|RAIL|wake quickly ironic foxes. slyly sil +14117|189835|9836|6|5|9624.15|0.05|0.05|A|F|1993-09-08|1993-10-08|1993-09-28|NONE|FOB|oxes detect furiously. excuses +14117|141348|1349|7|39|54184.26|0.05|0.02|R|F|1993-11-02|1993-10-22|1993-11-07|NONE|MAIL|r, stealthy accounts use after the +14118|32226|4730|1|37|42854.14|0.10|0.01|A|F|1993-07-02|1993-08-16|1993-07-25|DELIVER IN PERSON|SHIP|y careful accounts are +14119|118706|6240|1|42|72437.40|0.04|0.01|A|F|1993-07-15|1993-07-28|1993-08-11|NONE|RAIL|ial accounts. blithely even excuses x-ray q +14119|76212|8720|2|30|35646.30|0.06|0.00|A|F|1993-07-12|1993-07-26|1993-07-19|TAKE BACK RETURN|FOB|furiously pending theodolites. +14119|84105|4106|3|6|6534.60|0.01|0.04|R|F|1993-07-21|1993-07-27|1993-07-23|TAKE BACK RETURN|AIR|e carefull +14119|141746|6775|4|26|46481.24|0.03|0.02|A|F|1993-08-01|1993-07-16|1993-08-16|NONE|MAIL|never express dependencies; quickly bo +14119|120868|8405|5|10|18888.60|0.05|0.05|A|F|1993-08-12|1993-08-06|1993-09-08|TAKE BACK RETURN|FOB|sly even pinto beans. carefully pendi +14119|20858|8365|6|48|85384.80|0.02|0.08|A|F|1993-07-31|1993-07-13|1993-08-21|COLLECT COD|MAIL|y unusual, bo +14144|82691|2692|1|29|48537.01|0.03|0.05|N|O|1997-08-18|1997-06-28|1997-08-21|DELIVER IN PERSON|SHIP|ed asymptotes cajole fluffil +14144|184193|4194|2|48|61305.12|0.04|0.06|N|O|1997-07-13|1997-07-06|1997-07-19|DELIVER IN PERSON|SHIP| the final dependencies. carefully r +14144|131320|3834|3|31|41890.92|0.05|0.06|N|O|1997-07-25|1997-07-12|1997-08-16|TAKE BACK RETURN|AIR|carefully ironic dependencies. bl +14144|79241|4256|4|22|26845.28|0.07|0.05|N|O|1997-08-20|1997-07-16|1997-09-11|DELIVER IN PERSON|REG AIR|y across the even +14144|192818|376|5|8|15286.48|0.05|0.01|N|O|1997-05-29|1997-07-22|1997-06-22|NONE|MAIL|ges wake furiou +14144|84236|9253|6|46|56130.58|0.00|0.04|N|O|1997-05-24|1997-07-18|1997-05-27|NONE|SHIP|lent request +14145|138729|1243|1|45|79547.40|0.02|0.05|N|O|1997-06-13|1997-06-19|1997-06-20|DELIVER IN PERSON|TRUCK|ely final accounts haggle slyly. +14145|15512|5513|2|43|61382.93|0.02|0.06|N|O|1997-04-25|1997-06-09|1997-04-28|NONE|MAIL|ctions. final, regular requ +14145|103641|1172|3|6|9867.84|0.02|0.08|N|O|1997-06-27|1997-07-07|1997-07-11|COLLECT COD|FOB|to are carefully +14145|79500|2008|4|40|59180.00|0.08|0.05|N|O|1997-07-26|1997-07-09|1997-08-22|COLLECT COD|MAIL|l accounts wake fluffily s +14145|146388|8903|5|27|38728.26|0.10|0.00|N|O|1997-05-06|1997-06-30|1997-05-12|TAKE BACK RETURN|RAIL|ly carefully regular foxes +14145|130723|3237|6|48|84178.56|0.00|0.02|N|O|1997-05-10|1997-07-09|1997-06-01|NONE|RAIL|ole blithely? ruth +14146|172424|9976|1|25|37410.50|0.08|0.06|N|O|1996-01-25|1996-03-17|1996-02-05|TAKE BACK RETURN|FOB| across the final courts. fur +14146|127007|7008|2|14|14476.00|0.01|0.03|N|O|1996-04-20|1996-03-31|1996-05-13|NONE|SHIP|aggle blithely ar +14146|198844|8845|3|20|38856.80|0.08|0.01|N|O|1996-01-14|1996-02-15|1996-01-29|TAKE BACK RETURN|REG AIR| packages try to hang furiously unusual a +14146|159935|7481|4|8|15959.44|0.03|0.05|N|O|1996-03-04|1996-02-04|1996-03-05|TAKE BACK RETURN|REG AIR|lar hockey +14146|15121|2625|5|4|4144.48|0.02|0.08|N|O|1996-04-11|1996-03-04|1996-04-19|NONE|TRUCK|usy, pending pac +14147|42968|481|1|4|7643.84|0.08|0.01|A|F|1993-05-20|1993-05-15|1993-05-27|TAKE BACK RETURN|SHIP|s after the ironic +14147|160647|8196|2|12|20491.68|0.05|0.01|A|F|1993-07-01|1993-04-30|1993-07-29|COLLECT COD|SHIP| accounts. final ideas haggle care +14147|193347|905|3|38|54732.92|0.05|0.03|R|F|1993-06-30|1993-05-09|1993-07-30|COLLECT COD|AIR|uctions. ideas unwind! ironic +14147|167115|7116|4|47|55559.17|0.07|0.06|R|F|1993-07-02|1993-05-24|1993-07-21|DELIVER IN PERSON|FOB|st the blithel +14147|86771|1788|5|31|54490.87|0.07|0.08|R|F|1993-03-26|1993-05-27|1993-04-16|TAKE BACK RETURN|FOB|usly even requests. carefully +14147|143547|3548|6|17|27039.18|0.06|0.05|R|F|1993-07-07|1993-06-06|1993-07-28|DELIVER IN PERSON|MAIL|eep around the pending pack +14147|179884|2402|7|12|23566.56|0.00|0.03|A|F|1993-06-03|1993-05-15|1993-06-25|TAKE BACK RETURN|SHIP| asymptotes along the ironic, regular +14148|108393|904|1|12|16816.68|0.02|0.08|N|O|1998-07-29|1998-06-26|1998-08-09|COLLECT COD|FOB| use fluffily a +14148|154643|9674|2|50|84882.00|0.07|0.00|N|O|1998-05-25|1998-06-10|1998-06-07|COLLECT COD|FOB|mptotes cajole among the sl +14148|84706|2231|3|14|23669.80|0.02|0.07|N|O|1998-08-10|1998-05-30|1998-08-17|DELIVER IN PERSON|FOB|ix. quickly final notornis mol +14148|39635|2139|4|21|33067.23|0.10|0.03|N|O|1998-05-27|1998-06-24|1998-06-03|NONE|MAIL|uffy, even deposits. blithely ironic pl +14149|56876|4392|1|5|9164.35|0.04|0.08|N|O|1998-02-17|1998-03-23|1998-03-03|DELIVER IN PERSON|RAIL|luffily ironic dependencies boos +14149|109594|9595|2|4|6414.36|0.01|0.08|N|O|1998-05-09|1998-03-18|1998-05-21|NONE|AIR|edly regular asympto +14149|139308|4335|3|15|20209.50|0.00|0.04|N|O|1998-05-06|1998-03-05|1998-05-24|TAKE BACK RETURN|REG AIR|iously bold courts! blithely final inst +14149|148441|5984|4|10|14894.40|0.05|0.08|N|O|1998-05-04|1998-03-28|1998-05-22|DELIVER IN PERSON|SHIP|ress platelets; slyl +14149|44048|9057|5|12|11904.48|0.02|0.02|N|O|1998-02-03|1998-04-12|1998-02-22|COLLECT COD|SHIP|nic requests. ca +14149|98540|3559|6|24|36924.96|0.06|0.08|N|O|1998-03-25|1998-03-16|1998-04-12|NONE|RAIL|onic deposits aft +14149|152729|275|7|35|62360.20|0.08|0.06|N|O|1998-03-27|1998-03-19|1998-04-18|NONE|FOB|instructions +14150|103093|5604|1|3|3288.27|0.09|0.03|A|F|1994-03-07|1994-04-27|1994-03-29|TAKE BACK RETURN|AIR|l pinto be +14150|78908|6430|2|38|71702.20|0.02|0.07|R|F|1994-02-12|1994-05-09|1994-03-03|DELIVER IN PERSON|MAIL|ronic packages integrate enticing +14150|195870|5871|3|33|64873.71|0.01|0.04|A|F|1994-02-17|1994-04-16|1994-03-05|TAKE BACK RETURN|SHIP| deposits haggl +14150|176730|4282|4|37|66849.01|0.02|0.04|R|F|1994-03-20|1994-04-09|1994-04-01|COLLECT COD|FOB|s. slyly pending pinto be +14151|74922|2444|1|37|70186.04|0.10|0.04|N|O|1997-08-19|1997-08-07|1997-08-25|TAKE BACK RETURN|RAIL|gular packages are carefully. pendi +14151|2069|2070|2|36|34958.16|0.01|0.04|N|O|1997-09-30|1997-08-26|1997-10-03|TAKE BACK RETURN|TRUCK|he quickly +14151|168539|3572|3|39|62693.67|0.01|0.01|N|O|1997-09-30|1997-07-23|1997-10-29|TAKE BACK RETURN|FOB|about the silently sp +14151|34913|7417|4|9|16631.19|0.09|0.00|N|O|1997-09-12|1997-07-21|1997-09-20|NONE|FOB| quickly unusual asymptotes haggle +14151|167620|7621|5|32|54003.84|0.08|0.04|N|O|1997-08-03|1997-08-18|1997-08-30|COLLECT COD|MAIL| among the quickly spec +14151|173429|5947|6|40|60096.80|0.09|0.00|N|O|1997-07-03|1997-08-22|1997-07-12|COLLECT COD|SHIP|d ideas wake carefully ironic idea +14151|6570|6571|7|16|23625.12|0.00|0.01|N|O|1997-10-04|1997-09-01|1997-10-20|TAKE BACK RETURN|MAIL|uld use quickly bold +14176|7418|2419|1|22|29159.02|0.04|0.06|R|F|1994-06-14|1994-04-12|1994-06-20|DELIVER IN PERSON|TRUCK|carefully final accounts cajole even, +14176|67727|5246|2|33|55925.76|0.09|0.07|A|F|1994-06-28|1994-05-04|1994-07-20|COLLECT COD|SHIP|egular theodolites +14176|72128|7143|3|24|26402.88|0.00|0.02|A|F|1994-05-15|1994-05-10|1994-05-29|TAKE BACK RETURN|AIR|gular theodolites wake-- furio +14176|44499|9508|4|20|28869.80|0.01|0.08|A|F|1994-06-11|1994-05-05|1994-06-23|COLLECT COD|SHIP|cording to the +14177|48976|3985|1|23|44274.31|0.03|0.07|R|F|1992-04-09|1992-06-03|1992-04-17|NONE|SHIP|wake furiously blithely final acco +14177|130838|839|2|16|29901.28|0.04|0.07|A|F|1992-04-29|1992-07-01|1992-05-29|TAKE BACK RETURN|TRUCK|ully. ideas sleep a +14177|186608|6609|3|34|57616.40|0.02|0.01|A|F|1992-07-10|1992-06-24|1992-08-04|NONE|SHIP|sublate care +14178|131122|8662|1|9|10378.08|0.02|0.05|R|F|1995-04-10|1995-03-21|1995-04-21|NONE|RAIL|s past the furio +14179|176468|8986|1|41|63322.86|0.02|0.07|N|O|1997-11-29|1997-11-07|1997-11-30|DELIVER IN PERSON|SHIP|osits instead of the slyly regular pin +14179|96715|1734|2|30|51351.30|0.00|0.08|N|O|1997-11-19|1997-12-02|1997-11-20|NONE|TRUCK|y unusual excuses abou +14179|85220|2745|3|43|51824.46|0.00|0.05|N|O|1997-09-23|1997-10-10|1997-10-15|TAKE BACK RETURN|REG AIR|into beans are blithely regular requ +14179|79629|4644|4|40|64344.80|0.01|0.05|N|O|1997-11-15|1997-10-20|1997-12-15|NONE|RAIL|carefully final +14179|109088|6619|5|46|50465.68|0.00|0.03|N|O|1997-10-15|1997-10-13|1997-10-29|TAKE BACK RETURN|TRUCK|requests wake +14179|25410|5411|6|46|61428.86|0.00|0.04|N|O|1997-10-04|1997-10-08|1997-10-25|DELIVER IN PERSON|TRUCK|sts boost furiously. quic +14180|56629|9135|1|24|38054.88|0.00|0.05|N|O|1997-09-08|1997-07-19|1997-09-23|NONE|TRUCK|t the unusual deposits. bold, pen +14180|161557|6590|2|46|74453.30|0.09|0.01|N|O|1997-07-07|1997-06-28|1997-07-26|COLLECT COD|AIR|sts unwind fluffily +14180|85598|615|3|32|50674.88|0.08|0.02|N|O|1997-06-13|1997-07-28|1997-07-10|TAKE BACK RETURN|AIR|sits lose slyly +14180|33956|6460|4|21|39688.95|0.00|0.00|N|O|1997-08-03|1997-06-27|1997-09-01|NONE|MAIL|ts use carefully across the quickly iron +14180|96657|1676|5|4|6614.60|0.05|0.04|N|O|1997-07-09|1997-08-20|1997-08-02|NONE|FOB|ccording to the quietly final ideas. re +14181|89552|2061|1|18|27747.90|0.06|0.03|N|O|1998-06-13|1998-03-15|1998-06-21|DELIVER IN PERSON|RAIL|l tithes are. carefully +14181|83823|8840|2|26|46977.32|0.07|0.08|N|O|1998-03-14|1998-03-15|1998-03-29|NONE|MAIL|furiously final depths. unusual foxes wake +14181|2265|9766|3|34|39686.84|0.05|0.08|N|O|1998-03-20|1998-03-21|1998-04-19|DELIVER IN PERSON|RAIL|yly pending deposits. final theo +14181|51277|3783|4|18|22108.86|0.00|0.07|N|O|1998-03-06|1998-03-22|1998-03-07|DELIVER IN PERSON|REG AIR|le slyly final, special pla +14181|7691|2692|5|3|4796.07|0.00|0.01|N|O|1998-05-04|1998-04-08|1998-05-20|DELIVER IN PERSON|AIR|ly regular ideas cajole fluffi +14181|46472|8977|6|37|52483.39|0.06|0.08|N|O|1998-05-19|1998-03-16|1998-06-08|DELIVER IN PERSON|MAIL|requests sleep carefully against the furi +14181|44933|4934|7|29|54459.97|0.07|0.00|N|O|1998-04-01|1998-05-11|1998-04-12|NONE|MAIL|t courts. carefully +14182|186680|9199|1|37|65367.16|0.09|0.05|A|F|1994-09-05|1994-07-30|1994-09-23|COLLECT COD|SHIP|quests. ironic, express pe +14182|118495|6029|2|5|7567.45|0.02|0.08|R|F|1994-10-21|1994-09-12|1994-10-26|TAKE BACK RETURN|TRUCK|lets are. pending, final packages use. care +14183|184565|4566|1|4|6598.24|0.09|0.01|N|O|1997-05-02|1997-05-18|1997-05-10|COLLECT COD|TRUCK|ffily pending instructions haggle bl +14183|173348|5866|2|50|71067.00|0.04|0.01|N|O|1997-03-18|1997-06-03|1997-03-21|COLLECT COD|FOB|luffily silent depos +14208|98390|900|1|33|45816.87|0.04|0.08|N|O|1995-08-26|1995-07-23|1995-09-10|DELIVER IN PERSON|MAIL| blithely unusual accounts boost car +14208|26912|6913|2|27|49650.57|0.06|0.04|N|O|1995-07-14|1995-06-06|1995-07-28|COLLECT COD|FOB| alongside o +14208|102265|7286|3|28|35483.28|0.04|0.04|N|O|1995-06-29|1995-06-17|1995-07-17|DELIVER IN PERSON|FOB|ar ideas. furiously unusual forges use flu +14209|190853|3373|1|26|50540.10|0.06|0.03|N|O|1996-12-16|1997-01-30|1996-12-30|TAKE BACK RETURN|RAIL| ironic deposits. ironic +14209|63644|3645|2|7|11253.48|0.09|0.04|N|O|1996-11-23|1996-12-24|1996-12-21|COLLECT COD|REG AIR|rding to the bold, silent patterns. blith +14209|58992|8993|3|35|68284.65|0.07|0.04|N|O|1997-01-22|1997-01-08|1997-02-19|NONE|MAIL|hely above the bold accounts? sly +14209|68254|8255|4|7|8555.75|0.06|0.07|N|O|1997-01-29|1997-01-11|1997-02-16|DELIVER IN PERSON|RAIL|y regular theodolites aff +14209|129468|1981|5|17|25456.82|0.04|0.03|N|O|1996-12-23|1996-12-16|1996-12-29|DELIVER IN PERSON|RAIL|e slyly quick accounts; carefully unusual +14210|60883|5896|1|15|27658.20|0.00|0.04|A|F|1992-09-13|1992-08-17|1992-10-12|COLLECT COD|MAIL| even depo +14211|47107|4620|1|11|11595.10|0.00|0.08|R|F|1994-02-28|1994-04-21|1994-03-05|TAKE BACK RETURN|REG AIR|ges nag ruthlessly ironic foxes. pinto bean +14211|112553|2554|2|14|21917.70|0.00|0.01|R|F|1994-03-07|1994-04-17|1994-03-13|NONE|SHIP|cross the furiously regular accounts. fl +14211|74664|7172|3|29|47521.14|0.08|0.02|A|F|1994-03-14|1994-05-08|1994-04-01|DELIVER IN PERSON|REG AIR|ar deposits besides the +14211|72196|2197|4|35|40886.65|0.06|0.04|R|F|1994-05-01|1994-03-15|1994-05-09|COLLECT COD|MAIL|sits integrate furiously quickly silent exc +14211|192167|7206|5|3|3777.48|0.05|0.03|A|F|1994-03-26|1994-05-07|1994-04-03|DELIVER IN PERSON|AIR|lar excuses boost. slyly pen +14211|137493|7|6|41|62750.09|0.00|0.01|R|F|1994-05-28|1994-04-16|1994-05-31|NONE|REG AIR|ctions cajole furious +14212|174575|2127|1|44|72581.08|0.08|0.01|A|F|1992-04-24|1992-04-18|1992-05-19|COLLECT COD|MAIL|carefully express r +14212|75991|5992|2|45|88514.55|0.04|0.07|R|F|1992-03-07|1992-04-28|1992-04-06|COLLECT COD|RAIL|r, special foxes cajole furious +14212|168672|3705|3|20|34813.40|0.09|0.03|R|F|1992-02-28|1992-04-14|1992-03-13|COLLECT COD|TRUCK|. dependencies accord +14212|65583|596|4|15|23228.70|0.09|0.06|R|F|1992-04-11|1992-03-26|1992-04-20|DELIVER IN PERSON|AIR|ilent platelets abo +14213|18872|3875|1|45|80589.15|0.01|0.05|R|F|1994-01-05|1994-03-18|1994-01-24|TAKE BACK RETURN|TRUCK|ironic requests are excuses. +14214|199460|7018|1|26|40545.96|0.00|0.05|N|O|1997-09-17|1997-10-12|1997-10-15|TAKE BACK RETURN|MAIL|lyly final accounts cajole slyly abov +14214|107594|5125|2|3|4804.77|0.09|0.06|N|O|1997-12-08|1997-09-23|1998-01-03|TAKE BACK RETURN|SHIP|ent dependencies. instructions haggle b +14214|122636|5149|3|29|48100.27|0.07|0.06|N|O|1997-11-23|1997-10-10|1997-12-06|NONE|TRUCK|pecial sheaves haggle slyly about t +14214|129497|4522|4|36|54953.64|0.09|0.07|N|O|1997-09-24|1997-09-20|1997-10-23|TAKE BACK RETURN|TRUCK|cuses. pending, fin +14215|183217|5736|1|4|5200.84|0.07|0.05|A|F|1992-09-10|1992-09-26|1992-10-09|DELIVER IN PERSON|SHIP|unts breach quickly +14215|124889|9914|2|11|21052.68|0.04|0.08|R|F|1992-08-09|1992-10-02|1992-08-22|TAKE BACK RETURN|TRUCK|y daring pinto +14215|3496|997|3|35|48982.15|0.09|0.03|R|F|1992-07-18|1992-08-16|1992-08-08|NONE|RAIL|ously regular courts hang. c +14240|111270|6293|1|47|60219.69|0.06|0.00|R|F|1992-06-06|1992-04-08|1992-07-04|COLLECT COD|AIR|eep carefully along the ironic, eve +14240|111486|9020|2|26|38934.48|0.00|0.02|R|F|1992-05-08|1992-04-19|1992-06-05|TAKE BACK RETURN|REG AIR|ely slyly regular dependencies: even reque +14240|137070|9584|3|14|15498.98|0.06|0.02|A|F|1992-05-24|1992-04-04|1992-06-07|DELIVER IN PERSON|TRUCK|y. thinly special accounts around the dep +14240|133118|5632|4|35|40288.85|0.03|0.02|A|F|1992-05-08|1992-05-15|1992-06-07|COLLECT COD|FOB|lites dazzle by the quickly silent account +14240|112078|7101|5|9|9810.63|0.05|0.01|A|F|1992-06-04|1992-03-21|1992-06-11|TAKE BACK RETURN|MAIL|express pi +14240|86452|1469|6|14|20138.30|0.09|0.04|R|F|1992-04-29|1992-04-21|1992-05-03|COLLECT COD|RAIL|ording to the carefu +14240|187824|2861|7|26|49707.32|0.00|0.00|R|F|1992-05-10|1992-04-15|1992-05-23|DELIVER IN PERSON|FOB|gular, ironic pinto beans n +14241|156393|3939|1|44|63773.16|0.05|0.08|A|F|1992-10-03|1992-09-12|1992-10-04|COLLECT COD|SHIP|ly bold foxes wake. ir +14241|87761|2778|2|47|82191.72|0.00|0.04|A|F|1992-09-04|1992-09-02|1992-09-22|DELIVER IN PERSON|RAIL|ed excuses above the carefully ironic +14242|44414|9423|1|17|23092.97|0.03|0.04|N|F|1995-06-17|1995-06-09|1995-06-25|DELIVER IN PERSON|AIR|posits. quickly even instructions are +14242|57589|5105|2|7|10826.06|0.04|0.05|R|F|1995-05-13|1995-07-04|1995-05-18|DELIVER IN PERSON|FOB|eans according to the slyly +14242|88331|5856|3|10|13193.30|0.02|0.07|N|O|1995-08-21|1995-07-29|1995-09-15|DELIVER IN PERSON|RAIL|e blithely over the blithely pen +14242|174174|6692|4|34|42437.78|0.08|0.08|N|O|1995-08-22|1995-07-23|1995-09-12|DELIVER IN PERSON|MAIL|te at the sil +14242|137106|9620|5|6|6858.60|0.09|0.08|N|O|1995-07-13|1995-06-29|1995-07-17|NONE|SHIP|eposits. fluffily express deposits inte +14243|187706|2743|1|33|59192.10|0.04|0.05|N|O|1997-03-24|1997-05-04|1997-03-30|TAKE BACK RETURN|REG AIR| silently. warthogs about the package +14243|167340|4889|2|3|4222.02|0.09|0.06|N|O|1997-02-28|1997-05-12|1997-03-14|COLLECT COD|RAIL|counts wake quickly against the +14244|77207|2222|1|14|16578.80|0.00|0.02|N|O|1998-03-25|1998-04-23|1998-03-27|NONE|MAIL|onic packages integrate fluffily +14244|5897|8398|2|3|5408.67|0.08|0.08|N|O|1998-05-19|1998-05-29|1998-06-06|COLLECT COD|RAIL|wake slyly ironic accounts. express +14244|106357|3888|3|27|36810.45|0.01|0.02|N|O|1998-05-19|1998-04-05|1998-06-04|COLLECT COD|FOB| warthogs nag blithely ironic reque +14245|141837|9380|1|3|5636.49|0.00|0.02|A|F|1993-03-11|1993-04-14|1993-04-03|DELIVER IN PERSON|FOB|endencies sleep carefu +14245|41467|8980|2|35|49296.10|0.09|0.07|R|F|1993-03-06|1993-04-13|1993-04-03|NONE|RAIL|d requests eat. quickl +14245|134484|4485|3|21|31888.08|0.06|0.01|A|F|1993-04-15|1993-04-11|1993-04-16|COLLECT COD|RAIL|nal, unusual ideas wake carefully. spe +14246|62405|2406|1|34|46491.60|0.03|0.07|N|O|1997-12-30|1998-01-02|1998-01-25|DELIVER IN PERSON|AIR|counts above the e +14246|40615|8128|2|20|31112.20|0.00|0.04|N|O|1998-01-07|1997-12-23|1998-01-26|COLLECT COD|AIR| nag. blithely pendi +14246|5659|660|3|37|57892.05|0.09|0.00|N|O|1997-11-16|1997-11-15|1997-12-14|NONE|REG AIR|affix among the carefully regul +14246|104269|1800|4|19|24191.94|0.08|0.04|N|O|1997-12-01|1997-11-21|1997-12-31|COLLECT COD|MAIL|sual deposits among the final +14246|47669|174|5|2|3233.32|0.01|0.05|N|O|1997-10-21|1997-11-12|1997-10-23|COLLECT COD|FOB|cuses. special requests caj +14247|157084|7085|1|19|21680.52|0.00|0.03|N|O|1995-11-24|1995-11-13|1995-12-19|COLLECT COD|TRUCK|d excuses caj +14247|103692|6203|2|21|35609.49|0.06|0.00|N|O|1995-09-27|1995-10-13|1995-10-14|DELIVER IN PERSON|MAIL|t carefully. furiously ironic mu +14247|134747|4748|3|21|37416.54|0.04|0.01|N|O|1995-11-06|1995-09-17|1995-11-21|COLLECT COD|MAIL|ross the slyly regular accounts! furiously +14247|80185|2694|4|33|38450.94|0.02|0.00|N|O|1995-08-18|1995-09-28|1995-09-02|DELIVER IN PERSON|TRUCK|onic court +14247|66880|4399|5|38|70181.44|0.02|0.00|N|O|1995-12-12|1995-11-14|1995-12-19|TAKE BACK RETURN|SHIP|eas are quick +14247|43940|3941|6|6|11303.64|0.03|0.00|N|O|1995-11-24|1995-10-29|1995-12-05|DELIVER IN PERSON|RAIL|kages. carefully even pinto bean +14247|97487|7488|7|13|19298.24|0.02|0.06|N|O|1995-12-06|1995-11-11|1996-01-02|DELIVER IN PERSON|MAIL|s believe slyly! ironic i +14272|61387|6400|1|28|37754.64|0.08|0.08|A|F|1992-03-02|1992-04-21|1992-03-20|TAKE BACK RETURN|TRUCK|iously unusu +14272|121597|4110|2|11|17804.49|0.09|0.07|A|F|1992-05-22|1992-05-08|1992-06-06|COLLECT COD|FOB| carefully among the ironic +14272|66919|6920|3|30|56577.30|0.09|0.02|R|F|1992-02-17|1992-04-01|1992-03-04|TAKE BACK RETURN|AIR|are along the slyly bold as +14273|59354|4365|1|21|27580.35|0.00|0.03|N|O|1996-03-26|1996-05-28|1996-04-12|NONE|RAIL|al accounts. carefully regular pint +14273|150612|5643|2|39|64841.79|0.00|0.06|N|O|1996-06-01|1996-06-03|1996-06-16|DELIVER IN PERSON|RAIL|even, final accounts. furiously +14274|113938|3939|1|44|85884.92|0.03|0.00|A|F|1994-05-05|1994-03-12|1994-06-03|NONE|TRUCK| regular decoys wake fluffily. theodoli +14274|150028|2544|2|34|36652.68|0.09|0.04|R|F|1994-04-12|1994-03-22|1994-04-30|TAKE BACK RETURN|TRUCK|tes. ironic, final package +14274|113387|5899|3|13|18204.94|0.03|0.03|R|F|1994-02-06|1994-04-04|1994-02-15|COLLECT COD|RAIL|o beans are above the package +14274|85399|5400|4|49|67835.11|0.10|0.03|A|F|1994-03-08|1994-03-05|1994-03-09|NONE|MAIL|haggle carefully abo +14274|94379|9398|5|4|5493.48|0.07|0.07|A|F|1994-03-06|1994-03-25|1994-03-11|COLLECT COD|TRUCK|nding patterns shall engage furiously final +14274|17539|7540|6|48|69913.44|0.01|0.07|R|F|1994-04-22|1994-02-27|1994-04-24|DELIVER IN PERSON|REG AIR|packages. accounts haggle fluffily after +14275|12140|7143|1|19|19990.66|0.01|0.07|R|F|1993-10-12|1993-08-13|1993-10-30|TAKE BACK RETURN|RAIL| deposits. frets sleep fluffily after th +14275|34103|1613|2|31|32150.10|0.01|0.05|A|F|1993-07-26|1993-08-07|1993-08-09|TAKE BACK RETURN|REG AIR|the special packa +14275|159759|4790|3|1|1818.75|0.03|0.04|A|F|1993-08-31|1993-09-01|1993-09-19|COLLECT COD|REG AIR|thely silent accounts. realms hagg +14275|69351|6870|4|6|7922.10|0.04|0.08|R|F|1993-07-01|1993-07-30|1993-07-23|TAKE BACK RETURN|MAIL|ckly silent multipliers a +14275|174126|4127|5|23|27602.76|0.08|0.08|R|F|1993-07-09|1993-09-12|1993-08-06|DELIVER IN PERSON|REG AIR|across the blithely re +14275|125230|2767|6|41|51464.43|0.09|0.07|R|F|1993-09-15|1993-07-26|1993-10-01|DELIVER IN PERSON|REG AIR|ions. special, final accounts wake +14275|136354|6355|7|11|15293.85|0.05|0.00|A|F|1993-07-18|1993-08-24|1993-08-15|COLLECT COD|RAIL|ic, even packages wake blithely. fin +14276|87051|7052|1|49|50864.45|0.09|0.01|R|F|1994-08-20|1994-08-24|1994-08-30|DELIVER IN PERSON|AIR| special accounts. blithely sly +14276|57621|2632|2|25|39465.50|0.06|0.01|R|F|1994-09-01|1994-08-13|1994-09-24|DELIVER IN PERSON|REG AIR| cajole slyly furiously ironic +14276|25200|2707|3|32|36006.40|0.01|0.05|R|F|1994-10-11|1994-07-28|1994-10-25|NONE|TRUCK|ests. silentl +14276|124443|6956|4|15|22011.60|0.10|0.00|A|F|1994-09-21|1994-09-16|1994-10-18|NONE|MAIL|haggle quickly regular deposits. car +14276|97635|5163|5|40|65305.20|0.10|0.07|R|F|1994-09-30|1994-08-25|1994-10-14|COLLECT COD|FOB| final theodolites +14277|18594|3597|1|35|52940.65|0.03|0.07|N|O|1998-04-24|1998-05-07|1998-04-29|NONE|MAIL|ges. carefully regular courts sleep agai +14277|105696|5697|2|3|5105.07|0.05|0.05|N|O|1998-05-14|1998-04-30|1998-06-04|TAKE BACK RETURN|REG AIR|cajole slyly +14277|29124|1627|3|41|43177.92|0.05|0.06|N|O|1998-05-12|1998-05-04|1998-05-23|NONE|REG AIR| pending requ +14277|85213|5214|4|16|19171.36|0.10|0.00|N|O|1998-03-16|1998-04-11|1998-04-03|NONE|FOB| furiously bold accounts boost along t +14278|139440|1954|1|30|44383.20|0.03|0.03|N|O|1998-06-14|1998-08-01|1998-06-28|COLLECT COD|MAIL|ic, special deposits. carefully regula +14278|162792|7825|2|46|85320.34|0.04|0.06|N|O|1998-07-30|1998-07-04|1998-08-17|COLLECT COD|FOB|en theodolites sleep furiously after th +14278|35521|528|3|23|33499.96|0.05|0.03|N|O|1998-09-10|1998-08-24|1998-10-04|DELIVER IN PERSON|REG AIR|o the carefully regular foxes. +14278|188133|8134|4|14|17095.82|0.03|0.01|N|O|1998-06-17|1998-08-19|1998-06-19|DELIVER IN PERSON|SHIP|sual pinto +14278|144344|4345|5|48|66640.32|0.02|0.03|N|O|1998-07-30|1998-07-17|1998-07-31|TAKE BACK RETURN|SHIP|y ironic dolphins +14278|188304|5859|6|6|8353.80|0.03|0.00|N|O|1998-07-16|1998-08-23|1998-08-01|NONE|AIR|ely ironic instr +14278|8708|8709|7|29|46884.30|0.09|0.06|N|O|1998-08-23|1998-07-28|1998-09-05|NONE|FOB|ithe theodolites across the fluff +14279|145541|570|1|4|6346.16|0.00|0.08|N|O|1998-04-15|1998-04-29|1998-05-11|DELIVER IN PERSON|REG AIR|. special, e +14279|93852|1380|2|47|86754.95|0.03|0.01|N|O|1998-06-02|1998-05-02|1998-06-19|NONE|TRUCK|old deposits use sl +14279|156943|1974|3|8|15999.52|0.09|0.05|N|O|1998-05-23|1998-04-08|1998-06-19|DELIVER IN PERSON|MAIL|theodolites nag blit +14279|135751|3291|4|42|75043.50|0.00|0.03|N|O|1998-03-14|1998-05-10|1998-03-19|COLLECT COD|AIR|ole blithely pending asympto +14279|166796|9313|5|1|1862.79|0.08|0.06|N|O|1998-04-24|1998-03-23|1998-05-10|TAKE BACK RETURN|SHIP|press orbits serve +14304|14803|9806|1|33|56687.40|0.09|0.03|N|O|1997-12-31|1998-01-01|1998-01-07|NONE|MAIL| unusual instructions grow fluffil +14304|181239|1240|2|9|11882.07|0.01|0.07|N|O|1997-11-16|1998-02-07|1997-12-06|COLLECT COD|MAIL|venly regular requests ha +14304|79941|9942|3|30|57628.20|0.06|0.00|N|O|1998-01-24|1998-01-19|1998-02-10|COLLECT COD|SHIP|efully even packages sleep slyl +14304|155953|3499|4|48|96429.60|0.09|0.06|N|O|1998-01-27|1997-12-24|1998-02-10|TAKE BACK RETURN|TRUCK| slyly pending accounts could h +14304|89806|4823|5|5|8979.00|0.10|0.02|N|O|1998-03-01|1997-12-15|1998-03-25|DELIVER IN PERSON|MAIL|gular instructions sleep fluffily +14304|161198|8747|6|30|37775.70|0.08|0.03|N|O|1998-01-07|1997-12-15|1998-01-28|TAKE BACK RETURN|MAIL| blithe accounts a +14305|99317|1827|1|44|57917.64|0.05|0.02|N|O|1996-08-27|1996-09-12|1996-09-07|TAKE BACK RETURN|SHIP|nto the slyly unusual accounts. furio +14306|86638|9147|1|15|24369.45|0.04|0.07|A|F|1993-11-15|1993-12-27|1993-11-23|COLLECT COD|FOB|s. permanently furious theodo +14307|68136|8137|1|16|17666.08|0.01|0.03|N|O|1997-06-30|1997-07-25|1997-07-24|COLLECT COD|AIR|se theodolites are fur +14307|145286|7801|2|47|62570.16|0.05|0.01|N|O|1997-07-11|1997-09-10|1997-07-24|COLLECT COD|MAIL|mong the carefully ironic accounts +14307|14042|1546|3|27|25813.08|0.08|0.05|N|O|1997-10-06|1997-08-01|1997-10-13|NONE|MAIL|he slyly final packages detect +14307|1494|8995|4|41|57215.09|0.07|0.07|N|O|1997-08-03|1997-08-19|1997-08-05|DELIVER IN PERSON|MAIL|es snooze furiously slyly sil +14307|94457|4458|5|15|21771.75|0.08|0.08|N|O|1997-08-19|1997-08-02|1997-08-20|NONE|REG AIR|. slyly regular +14308|157430|2461|1|20|29748.60|0.04|0.03|N|O|1997-11-11|1997-11-05|1997-11-30|DELIVER IN PERSON|REG AIR|courts. carefully final accounts acco +14308|111058|6081|2|46|49176.30|0.08|0.07|N|O|1997-10-17|1997-09-21|1997-11-11|DELIVER IN PERSON|RAIL|equests. slyly unusual instr +14308|140916|5945|3|45|88060.95|0.04|0.02|N|O|1997-12-09|1997-10-09|1998-01-07|DELIVER IN PERSON|RAIL|ully bold pinto beans. final, +14309|170960|5995|1|37|75145.52|0.08|0.04|R|F|1994-05-18|1994-03-02|1994-06-04|DELIVER IN PERSON|MAIL|ncies x-ray a +14309|120450|451|2|28|41172.60|0.08|0.03|R|F|1994-03-19|1994-03-09|1994-03-22|DELIVER IN PERSON|SHIP| instructions. furiously ironic foxes u +14309|190038|5077|3|10|11280.30|0.07|0.01|R|F|1994-05-06|1994-04-16|1994-06-01|DELIVER IN PERSON|AIR|detect fluffily along the +14310|50411|5422|1|42|57179.22|0.01|0.02|N|O|1997-09-24|1997-12-01|1997-10-08|NONE|SHIP|ly final theodolite +14311|194627|4628|1|26|44762.12|0.10|0.00|R|F|1994-11-07|1994-10-26|1994-11-15|COLLECT COD|SHIP|ptotes. carefully ironic foxes according +14311|83981|6490|2|2|3929.96|0.01|0.06|R|F|1994-09-15|1994-09-22|1994-10-03|TAKE BACK RETURN|TRUCK| careful id +14336|22492|4995|1|29|41020.21|0.03|0.08|R|F|1994-11-26|1994-12-25|1994-12-21|NONE|FOB|rding to the n +14336|6470|8971|2|6|8258.82|0.07|0.04|R|F|1995-02-06|1995-01-25|1995-02-10|COLLECT COD|REG AIR|usly at the slyly pending forges! ir +14336|131317|3831|3|23|31011.13|0.02|0.07|A|F|1994-12-14|1995-02-08|1995-01-04|DELIVER IN PERSON|REG AIR|lithely carefully fina +14336|29788|2291|4|44|75582.32|0.04|0.01|A|F|1994-11-25|1995-02-07|1994-12-23|TAKE BACK RETURN|FOB|e blithely acco +14336|31842|9352|5|45|79822.80|0.08|0.04|A|F|1994-12-02|1995-01-05|1994-12-06|TAKE BACK RETURN|SHIP|uests wake ironic courts. accounts use c +14337|89110|1619|1|25|27477.75|0.10|0.07|N|O|1997-10-17|1997-12-03|1997-11-12|COLLECT COD|SHIP|ven deposits a +14337|56206|8712|2|6|6973.20|0.04|0.01|N|O|1997-11-09|1997-12-08|1997-11-12|COLLECT COD|AIR|nd the furiously +14337|38120|5630|3|37|39150.44|0.04|0.03|N|O|1998-01-27|1997-12-11|1998-02-06|TAKE BACK RETURN|MAIL|osits. even ideas sleep blithely r +14337|69127|6646|4|50|54806.00|0.06|0.02|N|O|1998-01-07|1997-11-21|1998-01-08|COLLECT COD|RAIL|kly. ironic packages x-ray slyly agains +14337|8259|8260|5|18|21010.50|0.03|0.02|N|O|1997-11-20|1997-12-15|1997-12-15|NONE|REG AIR|equests. permanent packag +14337|193252|8291|6|25|33631.25|0.03|0.01|N|O|1998-01-26|1997-12-06|1998-02-23|COLLECT COD|AIR|ent accounts cajole carefull +14337|185357|7876|7|23|33174.05|0.01|0.07|N|O|1997-10-27|1997-12-28|1997-11-20|COLLECT COD|REG AIR|are blithely bold reque +14338|84252|1777|1|33|40796.25|0.00|0.03|R|F|1993-02-17|1993-05-01|1993-02-25|NONE|AIR|ounts among the bold, even instructions use +14338|23178|685|2|35|38540.95|0.04|0.00|A|F|1993-05-16|1993-03-18|1993-06-06|COLLECT COD|RAIL|final dolphins. +14339|116154|6155|1|34|39785.10|0.09|0.06|N|O|1997-08-05|1997-10-21|1997-08-24|TAKE BACK RETURN|REG AIR|kages. slyly express p +14339|197917|5475|2|28|56417.48|0.01|0.04|N|O|1997-10-24|1997-10-20|1997-11-18|COLLECT COD|MAIL| foxes haggle. fluffily ironic p +14339|182971|2972|3|28|57511.16|0.00|0.00|N|O|1997-07-28|1997-08-29|1997-08-01|TAKE BACK RETURN|SHIP|ng to the enticing, unusual p +14339|187700|219|4|14|25027.80|0.01|0.00|N|O|1997-08-15|1997-10-21|1997-09-02|TAKE BACK RETURN|MAIL|uriously ironic theodol +14339|61160|3667|5|34|38119.44|0.10|0.01|N|O|1997-10-28|1997-09-06|1997-11-12|NONE|REG AIR|he foxes. +14340|150833|8379|1|17|32025.11|0.06|0.00|N|O|1996-01-30|1995-12-08|1996-02-27|TAKE BACK RETURN|TRUCK|ronic pinto beans wake closely requests. +14340|46892|4405|2|29|53327.81|0.10|0.03|N|O|1996-01-29|1995-11-15|1996-02-01|DELIVER IN PERSON|FOB|ag. ironic packages across the furiou +14340|101567|9098|3|50|78428.00|0.06|0.08|N|O|1996-01-05|1995-12-05|1996-01-27|COLLECT COD|TRUCK|o beans. sly +14340|22899|406|4|18|32794.02|0.03|0.06|N|O|1996-01-08|1995-12-22|1996-02-01|COLLECT COD|AIR|out the even pi +14340|48283|788|5|23|28319.44|0.01|0.07|N|O|1995-10-30|1996-01-02|1995-11-21|TAKE BACK RETURN|MAIL|arefully under the slyly special theodol +14340|92019|2020|6|35|35385.35|0.04|0.01|N|O|1995-11-05|1995-12-21|1995-11-10|TAKE BACK RETURN|AIR|l requests could are about the +14341|68900|3913|1|48|89707.20|0.01|0.05|R|F|1993-09-18|1993-10-13|1993-10-14|COLLECT COD|RAIL|t the carefully eve +14341|190825|3345|2|7|13410.74|0.09|0.05|R|F|1993-10-14|1993-10-28|1993-10-25|COLLECT COD|AIR| along the furiously +14341|185096|5097|3|37|43700.33|0.00|0.02|A|F|1993-10-13|1993-10-19|1993-10-31|COLLECT COD|FOB|. final, ironi +14341|102013|9544|4|8|8120.08|0.04|0.01|A|F|1993-12-25|1993-11-18|1993-12-27|NONE|SHIP|nic sentiments are sly +14341|127465|7466|5|28|41788.88|0.01|0.00|A|F|1993-09-19|1993-11-05|1993-09-28|COLLECT COD|MAIL|oost furiously. ironic, final fox +14342|1101|6102|1|45|45094.50|0.00|0.06|A|F|1994-08-01|1994-06-09|1994-08-31|DELIVER IN PERSON|FOB|s. furiously even pinto beans accord +14342|89598|9599|2|33|52390.47|0.01|0.01|A|F|1994-06-16|1994-06-09|1994-06-22|TAKE BACK RETURN|SHIP|ecial deposi +14342|57121|2132|3|10|10781.20|0.03|0.03|R|F|1994-07-19|1994-07-27|1994-07-30|TAKE BACK RETURN|TRUCK|regular instru +14342|30190|2694|4|4|4480.76|0.01|0.08|A|F|1994-05-16|1994-05-28|1994-05-29|TAKE BACK RETURN|FOB|ckly pending accounts are. accounts nag +14342|195226|5227|5|8|10569.76|0.00|0.03|A|F|1994-08-03|1994-06-19|1994-08-05|NONE|FOB|ickly after the ironic accou +14343|101465|3976|1|13|19063.98|0.10|0.02|N|O|1996-04-25|1996-04-24|1996-05-19|TAKE BACK RETURN|MAIL|ly ironic packages breach unus +14343|114665|7177|2|44|73905.04|0.01|0.04|N|O|1996-04-23|1996-05-21|1996-05-15|COLLECT COD|SHIP|r accounts sublate about the carefully ir +14368|126076|6077|1|42|46286.94|0.09|0.02|N|O|1995-09-19|1995-11-14|1995-10-05|COLLECT COD|TRUCK|nal, ironic packages. fi +14368|144175|6690|2|6|7315.02|0.07|0.07|N|O|1995-11-17|1995-10-22|1995-12-14|NONE|RAIL|luffily according to the slowly ironic +14368|146430|3973|3|7|10335.01|0.01|0.07|N|O|1995-09-23|1995-11-19|1995-10-20|NONE|AIR|l foxes mold +14368|38459|3466|4|42|58692.90|0.01|0.00|N|O|1995-12-16|1995-11-24|1996-01-02|NONE|FOB|eas! blithely regular accounts ca +14368|167851|7852|5|3|5756.55|0.04|0.03|N|O|1995-11-30|1995-10-20|1995-12-30|TAKE BACK RETURN|SHIP|beneath the slyl +14369|127016|4553|1|45|46935.45|0.02|0.01|N|O|1996-12-04|1997-02-20|1996-12-09|NONE|MAIL|sly bold platelets are fluffily +14369|151571|4087|2|46|74638.22|0.09|0.05|N|O|1997-03-17|1997-01-01|1997-04-06|NONE|SHIP|refully even accounts cajole furious +14369|40948|949|3|34|64223.96|0.00|0.01|N|O|1997-01-20|1997-01-25|1997-01-28|COLLECT COD|REG AIR|eas. permanent instructio +14369|199621|9622|4|35|60221.70|0.09|0.05|N|O|1997-01-20|1997-02-06|1997-01-30|DELIVER IN PERSON|AIR|en ideas. regul +14369|16955|1958|5|33|61774.35|0.05|0.02|N|O|1997-03-17|1997-01-25|1997-04-05|NONE|MAIL|egular requests after the reque +14369|147671|186|6|11|18905.37|0.07|0.07|N|O|1996-12-05|1997-01-03|1996-12-14|TAKE BACK RETURN|SHIP|egrate abou +14370|8106|8107|1|44|44620.40|0.00|0.06|N|O|1997-07-30|1997-07-28|1997-08-19|DELIVER IN PERSON|MAIL|osits boost b +14370|30977|3481|2|38|72502.86|0.01|0.08|N|O|1997-07-06|1997-06-26|1997-07-17|COLLECT COD|FOB|phs after the express foxes use slyly bo +14370|28897|1400|3|42|76687.38|0.07|0.08|N|O|1997-07-01|1997-06-27|1997-07-08|DELIVER IN PERSON|AIR|the pending packages. blithely ironic in +14370|57819|5335|4|12|21321.72|0.00|0.01|N|O|1997-07-22|1997-06-03|1997-07-26|COLLECT COD|TRUCK|aring requests. foxes ha +14371|8637|1138|1|33|51005.79|0.08|0.05|A|F|1993-08-11|1993-09-08|1993-08-14|COLLECT COD|TRUCK|ording to the carefully special packages +14371|156437|1468|2|49|73178.07|0.08|0.03|R|F|1993-10-20|1993-08-26|1993-10-28|COLLECT COD|TRUCK|deas. pend +14371|21087|1088|3|16|16129.28|0.06|0.01|R|F|1993-09-13|1993-08-12|1993-09-22|TAKE BACK RETURN|RAIL| wake furiously q +14372|97894|2913|1|28|52972.92|0.09|0.02|R|F|1993-01-22|1992-12-23|1993-02-05|COLLECT COD|AIR|uickly iron +14372|96727|6728|2|2|3447.44|0.09|0.08|A|F|1993-02-06|1993-01-12|1993-03-05|NONE|REG AIR|d platelets. special instructions cajole sl +14372|74241|1763|3|31|37672.44|0.01|0.08|R|F|1992-12-13|1992-12-23|1992-12-29|TAKE BACK RETURN|RAIL|gside of the regular accou +14372|153980|6496|4|40|81359.20|0.02|0.06|A|F|1992-12-07|1992-12-30|1992-12-14|TAKE BACK RETURN|TRUCK|above the depos +14373|115106|5107|1|49|54933.90|0.01|0.04|A|F|1993-10-08|1993-10-21|1993-10-20|DELIVER IN PERSON|REG AIR|. slyly regular accounts acc +14374|198398|3437|1|39|58359.21|0.00|0.07|N|O|1995-08-30|1995-08-14|1995-09-18|COLLECT COD|AIR|. blithely final pinto beans haggl +14374|62522|7535|2|18|26721.36|0.06|0.07|N|O|1995-07-30|1995-07-04|1995-08-18|TAKE BACK RETURN|REG AIR|c escapades +14374|196982|2021|3|9|18710.82|0.10|0.01|N|O|1995-08-17|1995-06-17|1995-08-23|COLLECT COD|REG AIR|y final ideas. carefully final asymptote +14375|147032|4575|1|30|32370.90|0.10|0.07|A|F|1993-02-05|1993-04-27|1993-03-07|NONE|TRUCK|arefully at the ironic, regular packa +14375|156253|8769|2|5|6546.25|0.07|0.07|A|F|1993-04-15|1993-03-10|1993-05-09|NONE|RAIL|ccounts. carefully ru +14375|131605|6632|3|25|40915.00|0.06|0.03|R|F|1993-04-28|1993-03-13|1993-05-19|TAKE BACK RETURN|MAIL|usly after the carefully regular ins +14375|72469|7484|4|4|5765.84|0.04|0.03|A|F|1993-02-11|1993-03-30|1993-02-25|TAKE BACK RETURN|SHIP|warhorses wake among the qui +14375|185015|52|5|14|15400.14|0.00|0.03|R|F|1993-05-12|1993-03-09|1993-05-28|DELIVER IN PERSON|RAIL|e furiously. pinto beans believe fur +14375|141393|1394|6|9|12909.51|0.01|0.05|A|F|1993-02-16|1993-03-31|1993-02-25|DELIVER IN PERSON|REG AIR|deas. blithely even requests a +14375|177766|7767|7|12|22125.12|0.05|0.07|R|F|1993-05-05|1993-04-14|1993-05-26|TAKE BACK RETURN|FOB|nic dugouts. pen +14400|102213|2214|1|5|6076.05|0.02|0.05|A|F|1994-02-28|1994-03-21|1994-03-28|NONE|RAIL| after the +14400|93342|870|2|3|4006.02|0.05|0.05|A|F|1994-03-25|1994-03-16|1994-04-14|DELIVER IN PERSON|TRUCK|ructions nag +14400|190663|664|3|26|45595.16|0.00|0.01|R|F|1994-03-30|1994-04-15|1994-04-08|DELIVER IN PERSON|AIR|ans. special r +14400|59887|7403|4|23|42478.24|0.01|0.08|R|F|1994-02-09|1994-04-10|1994-02-25|NONE|AIR|posits. ir +14400|112957|491|5|40|78798.00|0.07|0.08|A|F|1994-02-23|1994-03-08|1994-03-25|DELIVER IN PERSON|FOB|long the special deposits. slyly ironic +14400|56071|6072|6|35|35947.45|0.05|0.02|A|F|1994-03-31|1994-04-02|1994-04-24|DELIVER IN PERSON|RAIL|ng to the slyly regular r +14400|171634|6669|7|48|81870.24|0.06|0.05|A|F|1994-05-27|1994-04-23|1994-06-26|COLLECT COD|SHIP|. requests nag instructio +14401|51832|9348|1|33|58866.39|0.04|0.03|N|O|1995-11-17|1995-09-14|1995-12-09|TAKE BACK RETURN|SHIP|osits haggle slyl +14401|129372|9373|2|24|33632.88|0.10|0.01|N|O|1995-10-24|1995-10-13|1995-10-27|COLLECT COD|MAIL|about the special pa +14401|149648|7191|3|15|25464.60|0.06|0.05|N|O|1995-09-24|1995-10-28|1995-10-03|NONE|FOB|en requests +14401|124471|4472|4|29|43368.63|0.06|0.00|N|O|1995-08-22|1995-10-31|1995-09-03|COLLECT COD|TRUCK|es! unusual multiplier +14401|179729|2247|5|20|36174.40|0.07|0.03|N|O|1995-10-07|1995-09-05|1995-10-14|COLLECT COD|MAIL|ns are furiousl +14402|24611|4612|1|33|50675.13|0.02|0.00|A|F|1993-11-11|1993-12-25|1993-11-25|DELIVER IN PERSON|FOB|cording to t +14402|21647|9154|2|41|64314.24|0.00|0.08|R|F|1994-02-01|1993-12-02|1994-02-20|DELIVER IN PERSON|MAIL|odolites! regular, regular depos +14402|8459|5960|3|25|34186.25|0.08|0.00|A|F|1994-01-27|1993-12-08|1994-02-21|TAKE BACK RETURN|TRUCK|ckages. bo +14403|130511|5538|1|48|73992.48|0.10|0.05|N|O|1998-03-25|1998-05-21|1998-04-04|COLLECT COD|SHIP|al pearls. blithely +14403|84128|9145|2|33|36699.96|0.05|0.05|N|O|1998-07-01|1998-05-09|1998-07-20|NONE|TRUCK|eas sleep carefully. theodolites impress. i +14403|137490|7491|3|7|10692.43|0.04|0.02|N|O|1998-06-25|1998-05-12|1998-07-18|DELIVER IN PERSON|AIR|lyly ironic asymptotes. fluffily regular +14404|143034|5549|1|39|42004.17|0.00|0.00|N|O|1996-12-25|1996-12-31|1997-01-11|DELIVER IN PERSON|SHIP|r pending pinto beans. +14404|161156|8705|2|32|38948.80|0.00|0.06|N|O|1997-02-14|1996-12-24|1997-03-11|DELIVER IN PERSON|RAIL|e to are f +14404|145195|7710|3|31|38445.89|0.03|0.05|N|O|1997-01-22|1996-12-15|1997-02-18|TAKE BACK RETURN|TRUCK|ronic, final deposit +14404|87298|2315|4|40|51411.60|0.02|0.03|N|O|1997-01-16|1997-01-18|1997-01-22|DELIVER IN PERSON|MAIL|odolites across the carefully regu +14404|4396|6897|5|41|53315.99|0.04|0.04|N|O|1996-11-18|1997-01-29|1996-11-22|TAKE BACK RETURN|REG AIR|ly blithely final packag +14404|75019|5020|6|33|32802.33|0.07|0.00|N|O|1997-02-16|1996-12-05|1997-02-23|COLLECT COD|MAIL|oss the requests boost slyly fu +14404|35349|7853|7|42|53942.28|0.10|0.01|N|O|1997-02-14|1997-01-20|1997-03-11|TAKE BACK RETURN|RAIL|s. slyly iro +14405|110624|625|1|36|58846.32|0.04|0.00|N|O|1996-06-26|1996-06-14|1996-06-29|COLLECT COD|SHIP|the silent requests. regular dep +14405|56238|3754|2|17|20301.91|0.04|0.04|N|O|1996-07-29|1996-06-30|1996-08-28|NONE|AIR|egular requests ar +14405|188461|3498|3|20|30989.20|0.10|0.08|N|O|1996-07-05|1996-06-26|1996-07-08|COLLECT COD|FOB|ag blithely. care +14406|31484|3988|1|12|16985.76|0.03|0.00|R|F|1993-07-05|1993-05-25|1993-07-25|DELIVER IN PERSON|MAIL|he blithely r +14406|144137|6652|2|9|10630.17|0.04|0.08|A|F|1993-06-04|1993-04-18|1993-06-27|NONE|FOB|grate slyly spe +14406|96844|1863|3|24|44180.16|0.04|0.01|A|F|1993-03-23|1993-04-18|1993-04-16|TAKE BACK RETURN|TRUCK|e accounts. pending, special instructi +14406|54658|4659|4|20|32253.00|0.02|0.02|R|F|1993-04-30|1993-05-07|1993-05-19|NONE|MAIL|lar ideas boost carefully instru +14406|28351|5858|5|12|15352.20|0.06|0.03|R|F|1993-05-21|1993-04-20|1993-06-03|DELIVER IN PERSON|TRUCK| deposits +14406|81979|6996|6|49|96087.53|0.09|0.07|R|F|1993-03-27|1993-05-28|1993-04-10|COLLECT COD|REG AIR|refully unusual requests haggle iron +14407|2135|7136|1|24|24891.12|0.04|0.03|A|F|1993-11-17|1994-01-22|1993-12-05|TAKE BACK RETURN|SHIP|bold pinto beans. ironic, re +14432|16765|9267|1|42|70633.92|0.07|0.06|N|O|1997-01-18|1997-01-20|1997-01-19|NONE|REG AIR|bout the slow +14433|129660|7197|1|46|77724.36|0.06|0.03|N|O|1996-05-20|1996-07-26|1996-06-08|DELIVER IN PERSON|SHIP| the blithe, regular foxes boost +14433|187551|7552|2|9|14746.95|0.02|0.08|N|O|1996-08-13|1996-08-06|1996-08-17|TAKE BACK RETURN|RAIL|carefully. packag +14433|160671|672|3|5|8658.35|0.03|0.02|N|O|1996-08-24|1996-07-31|1996-09-07|TAKE BACK RETURN|AIR|re. slyly re +14433|183186|3187|4|40|50767.20|0.09|0.04|N|O|1996-08-02|1996-07-10|1996-08-22|TAKE BACK RETURN|REG AIR|xes haggle +14433|195880|8400|5|5|9879.40|0.03|0.05|N|O|1996-07-28|1996-06-15|1996-08-02|COLLECT COD|FOB|c foxes slee +14433|143474|1017|6|40|60698.80|0.05|0.00|N|O|1996-07-10|1996-07-10|1996-08-02|COLLECT COD|SHIP|as. pending dolphins sleep after the +14434|48747|3756|1|7|11870.18|0.06|0.05|R|F|1995-05-28|1995-04-07|1995-06-17|NONE|REG AIR|ly even deposits. reg +14434|84423|1948|2|23|32370.66|0.05|0.02|R|F|1995-05-04|1995-04-02|1995-05-19|TAKE BACK RETURN|AIR|requests. ironic instruc +14434|94022|9041|3|35|35560.70|0.09|0.00|A|F|1995-04-06|1995-03-20|1995-04-15|NONE|TRUCK|cial requests. even, even courts x-ray +14434|15118|7620|4|2|2066.22|0.05|0.07|R|F|1995-03-25|1995-04-09|1995-04-18|TAKE BACK RETURN|TRUCK|accounts cajole quickly. pending som +14434|72906|7921|5|41|77034.90|0.08|0.01|A|F|1995-03-01|1995-04-14|1995-03-28|NONE|SHIP|ctions along the regula +14435|179454|7006|1|10|15334.50|0.10|0.08|A|F|1993-04-01|1993-02-11|1993-05-01|NONE|TRUCK|ress, ironic packages maintain +14435|71731|4239|2|25|42568.25|0.08|0.07|R|F|1992-12-23|1993-02-09|1992-12-25|DELIVER IN PERSON|MAIL| boost caref +14435|180992|6029|3|22|45605.78|0.01|0.06|A|F|1992-12-28|1993-02-15|1993-01-18|NONE|AIR|sleep slyly am +14435|116812|4346|4|32|58521.92|0.02|0.05|R|F|1993-01-22|1993-02-15|1993-01-24|DELIVER IN PERSON|AIR|ickly special packa +14435|44771|7276|5|8|13726.16|0.03|0.03|A|F|1993-02-22|1993-01-13|1993-03-12|TAKE BACK RETURN|REG AIR|ar foxes: slyly ironic Tiresias solve f +14435|66018|3537|6|17|16728.17|0.02|0.07|A|F|1993-01-23|1993-02-24|1993-01-29|TAKE BACK RETURN|FOB|thely about +14435|152893|439|7|14|27242.46|0.02|0.08|R|F|1992-12-31|1993-02-10|1993-01-27|TAKE BACK RETURN|RAIL|uses. furiously special notornis haggle flu +14436|69708|4721|1|33|55364.10|0.09|0.06|R|F|1994-05-05|1994-05-21|1994-05-25|NONE|SHIP| deposits. slyly unusual instr +14436|181786|6823|2|39|72843.42|0.03|0.03|A|F|1994-06-17|1994-05-19|1994-07-02|COLLECT COD|MAIL|counts haggle c +14436|72782|2783|3|9|15793.02|0.05|0.07|R|F|1994-06-07|1994-05-04|1994-07-02|TAKE BACK RETURN|AIR|o beans. regularly pending d +14436|31445|8955|4|11|15140.84|0.04|0.02|R|F|1994-03-27|1994-05-03|1994-04-14|COLLECT COD|FOB|rmanent deposits are +14436|92288|4798|5|50|64014.00|0.10|0.04|A|F|1994-05-12|1994-06-02|1994-05-15|TAKE BACK RETURN|AIR|. deposits are according to +14437|9243|1744|1|36|41480.64|0.09|0.03|R|F|1994-06-28|1994-07-13|1994-07-23|COLLECT COD|RAIL|ronically +14437|138095|5635|2|35|39658.15|0.01|0.05|R|F|1994-08-14|1994-07-06|1994-08-28|TAKE BACK RETURN|FOB| slyly pen +14437|159500|2016|3|19|29630.50|0.07|0.05|A|F|1994-05-22|1994-07-05|1994-06-20|TAKE BACK RETURN|FOB| instructions haggle carefully even, +14437|112504|38|4|27|40945.50|0.07|0.03|A|F|1994-07-25|1994-07-10|1994-08-15|DELIVER IN PERSON|SHIP|tes across the carefull +14437|39612|9613|5|30|46548.30|0.00|0.04|A|F|1994-06-07|1994-06-22|1994-06-23|NONE|SHIP|usly pending sentiments use blithely. +14437|158507|6053|6|42|65751.00|0.06|0.04|R|F|1994-06-24|1994-08-08|1994-07-13|TAKE BACK RETURN|AIR|ans according to the furiously fin +14437|19983|7487|7|45|85634.10|0.04|0.04|R|F|1994-07-21|1994-08-02|1994-08-19|DELIVER IN PERSON|FOB|ress foxes. furio +14438|52637|5143|1|37|58816.31|0.09|0.01|N|O|1995-10-27|1995-11-06|1995-11-08|COLLECT COD|TRUCK|fter the furiously regular sentiments sl +14438|62310|7323|2|11|13995.41|0.08|0.01|N|O|1995-08-29|1995-10-21|1995-09-16|COLLECT COD|FOB|ng the packages. furiou +14438|42480|2481|3|33|46941.84|0.06|0.05|N|O|1995-12-01|1995-10-16|1995-12-23|COLLECT COD|SHIP| carefully iron +14439|53377|5883|1|3|3991.11|0.09|0.03|R|F|1992-09-22|1992-10-22|1992-10-09|NONE|AIR| the carefully pending f +14464|170970|971|1|29|59188.13|0.07|0.01|N|O|1998-05-08|1998-04-19|1998-05-16|TAKE BACK RETURN|SHIP|as against the bold, +14465|112818|352|1|48|87878.88|0.00|0.07|R|F|1994-09-19|1994-09-05|1994-10-17|COLLECT COD|AIR|ding to the fluffily slow dependencie +14465|124353|4354|2|7|9641.45|0.01|0.03|R|F|1994-08-28|1994-07-28|1994-09-12|COLLECT COD|SHIP|its. furiously special gifts are regul +14465|186875|4430|3|17|33351.79|0.08|0.06|A|F|1994-09-25|1994-08-07|1994-10-02|NONE|TRUCK|r dependencies. quickly fi +14465|2585|86|4|12|17850.96|0.10|0.07|R|F|1994-06-26|1994-07-30|1994-07-25|COLLECT COD|REG AIR| are. ironic pinto +14465|36918|6919|5|6|11129.46|0.01|0.03|A|F|1994-08-24|1994-08-26|1994-09-13|DELIVER IN PERSON|FOB|ular deposits after the ruthless, bold +14466|130175|5202|1|17|20487.89|0.09|0.06|N|O|1996-08-21|1996-06-26|1996-09-15|COLLECT COD|RAIL|regular pin +14467|172320|2321|1|16|22277.12|0.00|0.08|N|O|1996-07-20|1996-07-10|1996-08-08|COLLECT COD|MAIL|g dependencies. reque +14467|174606|9641|2|44|73946.40|0.01|0.00|N|O|1996-08-17|1996-08-24|1996-08-20|COLLECT COD|SHIP|s. carefully regular packages affix acc +14467|199008|6566|3|24|26568.00|0.02|0.00|N|O|1996-09-13|1996-07-20|1996-10-07|COLLECT COD|REG AIR|ckages haggle slyly quickly iron +14467|123363|900|4|15|20795.40|0.05|0.01|N|O|1996-06-02|1996-08-13|1996-06-22|COLLECT COD|FOB| slyly careful +14468|92361|2362|1|10|13533.60|0.01|0.08|N|O|1998-07-27|1998-09-26|1998-08-18|DELIVER IN PERSON|TRUCK|inal theodolites. carefully express +14468|97666|176|2|23|38264.18|0.10|0.06|N|O|1998-07-22|1998-10-07|1998-08-14|DELIVER IN PERSON|RAIL|the blithely fi +14469|74039|6547|1|19|19247.57|0.08|0.07|N|O|1997-06-02|1997-04-23|1997-07-01|NONE|TRUCK|d pinto beans cajole fluffily fluffil +14469|170633|634|2|33|56219.79|0.02|0.00|N|O|1997-05-05|1997-04-09|1997-05-14|DELIVER IN PERSON|SHIP|deposits cajole doggedly sly, s +14470|55833|844|1|28|50087.24|0.10|0.06|R|F|1995-05-06|1995-03-26|1995-05-14|TAKE BACK RETURN|TRUCK|slyly express requests lose. bold pac +14470|168924|3957|2|38|75730.96|0.04|0.02|A|F|1995-02-22|1995-04-12|1995-03-22|COLLECT COD|RAIL| regular theodolites sleep slyly blit +14470|97002|7003|3|20|19980.00|0.00|0.07|R|F|1995-05-04|1995-03-11|1995-05-19|DELIVER IN PERSON|MAIL|arefully even ideas. fin +14470|98994|1504|4|1|1992.99|0.01|0.00|R|F|1995-04-20|1995-03-29|1995-05-05|DELIVER IN PERSON|RAIL|st the bli +14471|39029|6539|1|50|48401.00|0.06|0.05|N|O|1995-07-03|1995-07-25|1995-07-05|TAKE BACK RETURN|MAIL|kly regular theodolites +14471|146115|8630|2|13|15094.43|0.01|0.00|N|O|1995-08-11|1995-08-14|1995-08-30|TAKE BACK RETURN|RAIL|ructions hinder +14471|150106|2622|3|50|57805.00|0.01|0.07|N|O|1995-09-24|1995-07-20|1995-10-16|NONE|FOB|s. slyly even dolphins after the theodol +14471|21640|9147|4|19|29671.16|0.08|0.04|N|O|1995-06-30|1995-08-09|1995-07-30|TAKE BACK RETURN|SHIP|ing accounts use about the fluffily spe +14471|89450|4467|5|42|60456.90|0.05|0.04|N|F|1995-06-07|1995-08-23|1995-06-29|DELIVER IN PERSON|AIR| cajole quickly evenly special Tire +14471|177795|5347|6|35|65547.65|0.05|0.03|A|F|1995-06-07|1995-07-01|1995-06-08|TAKE BACK RETURN|SHIP|refully. furi +14471|190131|2651|7|9|10990.17|0.03|0.03|N|O|1995-09-13|1995-07-09|1995-09-15|NONE|AIR|pending theodolites integrat +14496|127361|9874|1|22|30543.92|0.03|0.07|N|O|1996-05-20|1996-06-25|1996-06-08|NONE|AIR|sits might +14496|142143|7172|2|27|31998.78|0.04|0.08|N|O|1996-07-14|1996-05-27|1996-08-03|DELIVER IN PERSON|AIR|g the blithely special t +14496|193332|8371|3|48|68415.84|0.07|0.03|N|O|1996-06-14|1996-05-22|1996-07-04|COLLECT COD|AIR|riously ironic pinto beans sleep ironica +14496|114285|9308|4|9|11693.52|0.07|0.05|N|O|1996-08-06|1996-06-30|1996-08-10|DELIVER IN PERSON|MAIL|lphins across the +14496|184832|4833|5|29|55588.07|0.06|0.02|N|O|1996-05-26|1996-06-27|1996-05-30|TAKE BACK RETURN|MAIL|es haggle quickly pending +14497|169342|9343|1|48|67744.32|0.02|0.07|R|F|1992-07-16|1992-07-26|1992-07-26|TAKE BACK RETURN|SHIP|losely ironic excuses across the carefully +14497|121921|9458|2|17|33029.64|0.07|0.03|A|F|1992-08-02|1992-07-20|1992-08-09|COLLECT COD|TRUCK|al deposits sleep among +14497|117788|7789|3|1|1805.78|0.08|0.07|A|F|1992-08-03|1992-08-14|1992-09-01|DELIVER IN PERSON|RAIL|s. regular, regular asympt +14497|50729|3235|4|22|36953.84|0.08|0.08|R|F|1992-08-13|1992-06-22|1992-08-26|TAKE BACK RETURN|REG AIR|ackages haggle permanently? qui +14498|14860|7362|1|5|8874.30|0.06|0.02|N|O|1996-11-17|1997-01-02|1996-12-04|DELIVER IN PERSON|SHIP|ges are. ideas haggle +14498|140281|7824|2|23|30389.44|0.08|0.08|N|O|1996-10-14|1996-11-21|1996-11-04|NONE|FOB|y even packages. bli +14498|94192|1720|3|10|11861.90|0.08|0.06|N|O|1996-10-28|1996-11-06|1996-11-12|DELIVER IN PERSON|FOB|c, final platelets. quickly special packag +14498|81013|6030|4|14|13916.14|0.10|0.08|N|O|1996-11-26|1996-12-24|1996-12-22|TAKE BACK RETURN|REG AIR|lthily express deposits. furious +14498|185242|279|5|7|9290.68|0.09|0.08|N|O|1996-10-31|1996-12-16|1996-11-03|COLLECT COD|AIR|to beans are slyly. c +14498|151917|4433|6|20|39378.20|0.08|0.03|N|O|1996-11-17|1996-12-19|1996-12-02|NONE|AIR|s. furiously fina +14498|64363|9376|7|40|53094.40|0.10|0.04|N|O|1996-12-24|1996-11-06|1997-01-01|NONE|FOB|iers. unusual +14499|137179|9693|1|46|55943.82|0.10|0.02|R|F|1993-12-24|1994-01-08|1994-01-02|NONE|FOB|eep blithely unusual de +14499|153793|1339|2|25|46169.75|0.02|0.01|R|F|1993-12-04|1994-02-07|1993-12-05|TAKE BACK RETURN|SHIP|e blithely final ideas! care +14499|194962|2520|3|41|84335.36|0.02|0.02|R|F|1994-01-01|1994-01-23|1994-01-29|TAKE BACK RETURN|TRUCK| foxes are across the +14499|121612|9149|4|41|66978.01|0.01|0.07|A|F|1994-02-05|1994-02-11|1994-02-18|TAKE BACK RETURN|RAIL| even excuses are silent foxes. +14499|127424|7425|5|42|60959.64|0.00|0.07|R|F|1994-02-10|1994-02-05|1994-03-12|NONE|AIR|tes detect along the carefull +14499|10241|2743|6|6|6907.44|0.04|0.04|A|F|1994-01-26|1994-01-07|1994-02-16|NONE|AIR| carefully ironic packages. even fox +14499|107738|5269|7|36|62846.28|0.04|0.01|A|F|1994-01-30|1994-01-12|1994-02-08|COLLECT COD|SHIP|ys special foxes. caref +14500|146148|8663|1|30|35824.20|0.07|0.03|N|O|1995-07-23|1995-07-29|1995-07-29|TAKE BACK RETURN|TRUCK|thely above the silent, pending pint +14500|94666|2194|2|33|54801.78|0.00|0.01|N|O|1995-09-21|1995-09-04|1995-10-09|NONE|TRUCK|g, stealthy packages about +14501|115948|8460|1|33|64810.02|0.01|0.08|N|O|1997-10-20|1997-10-10|1997-11-13|DELIVER IN PERSON|MAIL|lly after th +14501|136104|1131|2|36|41043.60|0.06|0.07|N|O|1997-12-04|1997-11-10|1997-12-17|NONE|AIR|fully slow asymptotes play furiously? pendi +14502|56286|1297|1|33|40995.24|0.05|0.00|N|O|1996-11-11|1996-10-05|1996-12-05|TAKE BACK RETURN|RAIL|xpress deposits +14502|189046|9047|2|26|29511.04|0.10|0.00|N|O|1996-09-09|1996-10-05|1996-09-14|NONE|MAIL| final foxes nag. furiously bold warh +14503|97881|391|1|11|20667.68|0.07|0.03|R|F|1995-03-26|1995-03-19|1995-04-04|NONE|RAIL|he quickly final depo +14503|76873|9381|2|30|55496.10|0.05|0.05|A|F|1995-03-22|1995-04-25|1995-04-04|DELIVER IN PERSON|REG AIR|lly according to the furiously express fo +14503|193619|1177|3|42|71929.62|0.06|0.02|A|F|1995-04-15|1995-03-24|1995-05-05|NONE|TRUCK|r the furiously pendin +14503|142632|2633|4|41|68659.83|0.06|0.06|A|F|1995-05-19|1995-04-21|1995-05-27|COLLECT COD|AIR|aggle furiously slyly ruthless excuses. +14528|165974|5975|1|48|97918.56|0.04|0.03|A|F|1994-08-18|1994-08-07|1994-09-02|TAKE BACK RETURN|MAIL|lites are fur +14528|113412|3413|2|36|51314.76|0.02|0.06|R|F|1994-07-16|1994-09-02|1994-07-29|DELIVER IN PERSON|AIR|ly even foxe +14528|103412|3413|3|21|29723.61|0.05|0.04|A|F|1994-08-27|1994-08-25|1994-08-30|COLLECT COD|REG AIR|ackages. even requests wake s +14528|32874|384|4|19|34330.53|0.01|0.00|R|F|1994-07-26|1994-09-01|1994-08-20|DELIVER IN PERSON|FOB|ix against the carefully spec +14529|19412|6916|1|43|57250.63|0.01|0.03|R|F|1993-11-15|1993-10-21|1993-12-08|NONE|FOB|re. quickly express instructions boo +14529|50347|348|2|26|33730.84|0.02|0.01|A|F|1994-01-09|1993-11-24|1994-02-06|TAKE BACK RETURN|TRUCK|ven requests boost carefully int +14529|176971|9489|3|22|45055.34|0.05|0.03|A|F|1994-01-08|1993-11-03|1994-01-10|COLLECT COD|RAIL|, silent a +14529|138599|6139|4|28|45852.52|0.06|0.04|R|F|1993-10-07|1993-12-05|1993-11-01|COLLECT COD|RAIL| blithely after the sl +14529|20557|558|5|22|32506.10|0.01|0.04|A|F|1993-11-16|1993-12-01|1993-12-04|NONE|REG AIR| special instruct +14529|89114|4131|6|7|7721.77|0.04|0.07|R|F|1994-01-15|1993-11-04|1994-02-12|NONE|SHIP|ts haggle across the ac +14530|181529|9084|1|48|77304.96|0.03|0.06|A|F|1994-06-09|1994-06-28|1994-06-18|COLLECT COD|AIR|inal asymptotes sleep alongsi +14530|149281|4310|2|35|46559.80|0.06|0.01|A|F|1994-07-28|1994-06-20|1994-08-22|DELIVER IN PERSON|FOB|t deposits! even platelets boost furiou +14530|153140|8171|3|16|19090.24|0.09|0.08|A|F|1994-07-04|1994-06-10|1994-07-18|DELIVER IN PERSON|MAIL|busy requests nag slyly doggedly regul +14530|8721|8722|4|45|73337.40|0.08|0.07|R|F|1994-08-06|1994-05-11|1994-09-04|NONE|FOB|totes sleep blithely ironic +14530|172427|4945|5|4|5997.68|0.02|0.07|R|F|1994-06-17|1994-06-05|1994-06-25|NONE|REG AIR|brave packages +14530|174330|9365|6|8|11234.64|0.10|0.06|R|F|1994-07-01|1994-06-18|1994-07-02|NONE|REG AIR|es. carefully express escapade +14530|155234|7750|7|16|20627.68|0.01|0.02|A|F|1994-06-17|1994-07-05|1994-07-10|COLLECT COD|REG AIR| foxes alongside of the quickly ironic depo +14531|3076|8077|1|47|46016.29|0.03|0.07|N|O|1997-07-17|1997-07-23|1997-07-18|COLLECT COD|MAIL|luffily regular package +14531|89009|6534|2|34|33932.00|0.04|0.00|N|O|1997-07-11|1997-07-11|1997-08-02|DELIVER IN PERSON|SHIP|oxes sleep quickly even, regular p +14531|165198|2747|3|45|56843.55|0.06|0.02|N|O|1997-08-22|1997-09-05|1997-09-13|TAKE BACK RETURN|MAIL|ng theodolites try to run +14531|73309|8324|4|34|43598.20|0.08|0.01|N|O|1997-10-05|1997-08-21|1997-10-27|TAKE BACK RETURN|RAIL|c foxes alo +14532|81179|3688|1|9|10441.53|0.06|0.04|N|O|1996-07-19|1996-06-21|1996-08-16|DELIVER IN PERSON|FOB|ely packages. carefully ironi +14533|11500|1501|1|19|26818.50|0.06|0.02|N|O|1996-08-27|1996-07-21|1996-08-29|NONE|SHIP|ic accounts. furiously b +14533|79264|1772|2|4|4973.04|0.01|0.01|N|O|1996-05-31|1996-06-20|1996-06-28|TAKE BACK RETURN|TRUCK|ggle across the ironic p +14533|188356|8357|3|36|51996.60|0.04|0.03|N|O|1996-06-21|1996-07-08|1996-07-04|NONE|FOB|into beans. even, +14533|98818|1328|4|8|14534.48|0.02|0.05|N|O|1996-06-06|1996-07-17|1996-06-19|COLLECT COD|RAIL|ly express somas under t +14533|27569|7570|5|17|25441.52|0.00|0.00|N|O|1996-06-30|1996-07-08|1996-07-05|NONE|FOB|kages across the fluffily +14533|149477|9478|6|27|41214.69|0.07|0.05|N|O|1996-07-21|1996-07-08|1996-08-13|NONE|REG AIR| quickly; unusual accounts +14534|125750|5751|1|46|81684.50|0.07|0.02|A|F|1993-09-02|1993-09-11|1993-09-24|COLLECT COD|FOB|. furiousl +14534|76768|1783|2|43|75024.68|0.05|0.08|R|F|1993-10-03|1993-08-28|1993-10-10|DELIVER IN PERSON|FOB|at furiously regular accounts. fluff +14534|26087|6088|3|14|14183.12|0.03|0.00|R|F|1993-08-15|1993-08-30|1993-08-16|TAKE BACK RETURN|RAIL|n instructions sleep carefully s +14534|27637|7638|4|19|29727.97|0.00|0.05|A|F|1993-08-04|1993-08-26|1993-08-07|DELIVER IN PERSON|MAIL|ts. unusual theodolites sleep against the f +14534|89491|7016|5|48|71063.52|0.03|0.02|R|F|1993-07-28|1993-09-08|1993-08-25|TAKE BACK RETURN|AIR|aggle slyly. furiously special foxes +14535|122664|7689|1|5|8433.30|0.00|0.01|A|F|1993-11-13|1993-12-12|1993-12-01|DELIVER IN PERSON|REG AIR|y special grouches. slyly regular packages +14535|6743|4244|2|27|44542.98|0.02|0.01|R|F|1994-01-19|1993-12-26|1994-02-16|TAKE BACK RETURN|AIR|yly express +14535|123387|924|3|27|38080.26|0.02|0.00|R|F|1993-12-03|1993-11-25|1993-12-08|TAKE BACK RETURN|TRUCK| beans cajole pa +14535|158831|3862|4|22|41576.26|0.02|0.06|R|F|1994-01-29|1993-11-03|1994-02-01|DELIVER IN PERSON|RAIL|hely expres +14560|146557|9072|1|24|38485.20|0.05|0.06|N|O|1998-01-29|1998-02-07|1998-02-16|COLLECT COD|AIR|refully fluffily express ideas. final p +14561|116713|4247|1|50|86485.50|0.03|0.07|N|O|1998-08-02|1998-08-15|1998-08-05|DELIVER IN PERSON|REG AIR|hins hinder ironi +14561|180854|3373|2|9|17413.65|0.02|0.02|N|O|1998-09-02|1998-09-09|1998-09-15|COLLECT COD|MAIL|thely after the express instr +14561|6107|1108|3|29|29379.90|0.04|0.08|N|O|1998-10-13|1998-08-09|1998-10-16|DELIVER IN PERSON|FOB|inal requests. furiously ironic packa +14561|38973|8974|4|48|91774.56|0.01|0.03|N|O|1998-08-11|1998-08-10|1998-08-13|NONE|FOB|ully. slyly unusual theodolites use; +14561|17061|2064|5|21|20539.26|0.00|0.02|N|O|1998-07-12|1998-08-29|1998-07-13|COLLECT COD|MAIL|uriously fluffily regular requests. asy +14561|136043|6044|6|36|38845.44|0.00|0.08|N|O|1998-07-29|1998-09-08|1998-08-04|TAKE BACK RETURN|SHIP|regular requests poach. always regular +14561|73931|6439|7|25|47623.25|0.09|0.06|N|O|1998-08-17|1998-08-24|1998-09-02|NONE|FOB|sleep blithely ironic depths. furiously f +14562|157860|7861|1|13|24932.18|0.01|0.03|N|O|1996-11-12|1996-10-11|1996-11-21|COLLECT COD|SHIP|out the quickly specia +14562|138023|8024|2|36|38196.72|0.07|0.03|N|O|1996-07-25|1996-09-27|1996-08-16|NONE|RAIL| slyly. blithely final +14562|139249|4276|3|17|21900.08|0.10|0.05|N|O|1996-08-19|1996-08-29|1996-09-17|NONE|RAIL|arefully regular requests. slyly special +14562|145650|679|4|50|84782.50|0.08|0.05|N|O|1996-11-06|1996-08-28|1996-12-03|DELIVER IN PERSON|REG AIR| after the furiously +14563|143517|1060|1|31|48375.81|0.08|0.05|N|O|1996-02-05|1996-01-04|1996-02-23|TAKE BACK RETURN|AIR|r packages haggle. ironic ideas ca +14563|82155|4664|2|44|50034.60|0.07|0.02|N|O|1996-02-06|1996-01-24|1996-03-05|NONE|SHIP|kly final instructions. furiously regular +14563|178603|1121|3|30|50448.00|0.01|0.00|N|O|1996-03-01|1996-01-26|1996-03-04|DELIVER IN PERSON|FOB| the final requests! regular +14563|176331|8849|4|32|45034.56|0.02|0.08|N|O|1996-02-05|1996-01-19|1996-02-21|NONE|TRUCK| slyly even warthogs haggle. +14563|187456|7457|5|10|15434.50|0.04|0.06|N|O|1996-03-11|1996-01-02|1996-04-05|TAKE BACK RETURN|FOB|fully special +14564|159052|4083|1|1|1111.05|0.09|0.00|A|F|1993-09-14|1993-07-15|1993-10-08|TAKE BACK RETURN|FOB|usual packages wake slyly bold, +14565|36770|4280|1|33|56323.41|0.01|0.00|N|O|1998-01-31|1998-02-05|1998-02-24|TAKE BACK RETURN|FOB|gular, regular dependencies doubt f +14565|185202|239|2|5|6436.00|0.05|0.03|N|O|1998-01-04|1998-02-05|1998-01-30|DELIVER IN PERSON|SHIP|ages nag regular requests +14566|170090|91|1|25|29002.25|0.02|0.01|N|O|1997-01-29|1997-01-18|1997-02-12|NONE|FOB|quickly pend +14566|87778|7779|2|22|38846.94|0.01|0.04|N|O|1996-12-17|1997-01-10|1996-12-29|DELIVER IN PERSON|TRUCK|dependencie +14566|80752|3261|3|14|24258.50|0.07|0.08|N|O|1996-12-25|1996-12-10|1997-01-15|DELIVER IN PERSON|REG AIR|yly carefull +14566|190576|5615|4|28|46663.96|0.07|0.04|N|O|1997-01-25|1997-01-06|1997-02-05|DELIVER IN PERSON|TRUCK|ters are. bravely ironi +14566|504|5505|5|40|56180.00|0.08|0.03|N|O|1997-02-01|1997-01-07|1997-02-10|DELIVER IN PERSON|FOB|egular theodol +14566|61602|6615|6|20|31272.00|0.00|0.01|N|O|1996-11-09|1997-01-06|1996-11-30|DELIVER IN PERSON|FOB|lites. fluffily express courts alongside o +14566|131641|1642|7|3|5017.92|0.07|0.00|N|O|1996-11-03|1996-12-01|1996-11-18|COLLECT COD|TRUCK|nder. furi +14567|81535|4044|1|19|28814.07|0.07|0.03|N|O|1996-11-03|1997-01-05|1996-11-30|NONE|AIR|e. even deposits haggle slyly quic +14567|145072|101|2|46|51385.22|0.03|0.04|N|O|1996-11-21|1997-01-05|1996-12-03|COLLECT COD|MAIL|? deposits cajole agai +14567|9898|7399|3|7|12655.23|0.09|0.02|N|O|1997-01-02|1996-11-18|1997-01-21|DELIVER IN PERSON|TRUCK|, even dugo +14567|140062|2577|4|6|6612.36|0.08|0.05|N|O|1996-12-31|1996-12-28|1997-01-25|DELIVER IN PERSON|SHIP|ly even accounts. evenly final platelet +14567|20717|718|5|31|50769.01|0.06|0.00|N|O|1996-10-29|1996-11-24|1996-11-20|NONE|MAIL|he slowly +14567|178932|3967|6|13|26142.09|0.08|0.02|N|O|1997-01-05|1997-01-13|1997-01-23|NONE|REG AIR|y regular platelets. +14567|106195|1216|7|16|19219.04|0.03|0.03|N|O|1996-11-17|1996-11-28|1996-11-22|COLLECT COD|TRUCK|platelets. blithel +14592|5656|5657|1|28|43726.20|0.00|0.04|N|O|1995-08-16|1995-09-28|1995-09-06|TAKE BACK RETURN|AIR|quickly across the slyly final accounts. +14592|53711|1227|2|21|34958.91|0.06|0.02|N|O|1995-07-22|1995-08-08|1995-08-16|NONE|SHIP| ideas haggle blit +14592|113557|1091|3|36|56539.80|0.08|0.07|N|O|1995-07-12|1995-09-15|1995-08-04|TAKE BACK RETURN|AIR|beans sleep according to the ironic, exp +14593|26526|4033|1|8|11620.16|0.08|0.00|N|O|1998-02-02|1998-04-05|1998-03-03|NONE|SHIP|ncies. pending packages ab +14593|14114|4115|2|6|6168.66|0.09|0.07|N|O|1998-03-20|1998-04-01|1998-04-12|COLLECT COD|MAIL|unusual pinto +14593|12098|9602|3|44|44443.96|0.01|0.06|N|O|1998-04-20|1998-04-01|1998-04-21|COLLECT COD|MAIL|s according to the regular, ironic +14594|131085|8625|1|15|16741.20|0.10|0.01|A|F|1993-10-13|1993-11-19|1993-11-10|COLLECT COD|SHIP|phs need to a +14595|166889|1922|1|20|39117.60|0.01|0.05|N|O|1998-01-11|1998-02-27|1998-02-10|TAKE BACK RETURN|FOB|osits nag sly +14596|196890|1929|1|28|55632.92|0.05|0.00|A|F|1994-01-30|1994-03-04|1994-02-15|TAKE BACK RETURN|TRUCK|ructions serve b +14596|129554|9555|2|37|58591.35|0.00|0.03|A|F|1994-03-09|1994-03-06|1994-03-23|NONE|SHIP|y across the r +14596|3139|5640|3|7|7294.91|0.06|0.03|R|F|1994-04-18|1994-03-29|1994-04-21|COLLECT COD|MAIL|al instructions. care +14596|144974|7489|4|31|62588.07|0.06|0.05|R|F|1994-02-06|1994-04-08|1994-02-21|DELIVER IN PERSON|FOB| pinto beans wake alo +14596|169725|4758|5|8|14357.76|0.01|0.02|A|F|1994-04-20|1994-03-23|1994-05-10|COLLECT COD|TRUCK|encies haggle after the final +14596|165801|3350|6|8|14934.40|0.09|0.04|R|F|1994-03-13|1994-04-02|1994-03-22|COLLECT COD|RAIL|uests doubt quickly. +14597|70785|3293|1|45|79010.10|0.09|0.06|A|F|1993-09-09|1993-10-21|1993-09-15|NONE|AIR|oost. always ironic platelets affix bli +14597|76250|3772|2|44|53955.00|0.00|0.05|R|F|1993-09-10|1993-10-29|1993-09-14|NONE|FOB|hely bold i +14597|128977|6514|3|10|20059.70|0.07|0.00|R|F|1993-10-10|1993-09-30|1993-10-13|NONE|FOB| accounts haggle carefully. even, bold p +14597|113491|1025|4|39|58675.11|0.04|0.01|R|F|1993-09-12|1993-11-26|1993-10-12|DELIVER IN PERSON|RAIL|jole after the even accoun +14597|34843|4844|5|48|85336.32|0.04|0.07|A|F|1993-11-24|1993-10-20|1993-12-16|COLLECT COD|AIR|yly packages. slyl +14597|199238|4277|6|18|24070.14|0.01|0.04|R|F|1993-11-11|1993-11-14|1993-12-06|DELIVER IN PERSON|SHIP|lithely regul +14598|150351|7897|1|43|60258.05|0.00|0.00|N|O|1998-05-30|1998-04-13|1998-06-19|NONE|TRUCK|en foxes sleep. furiousl +14598|138254|3281|2|35|45228.75|0.07|0.03|N|O|1998-05-23|1998-03-17|1998-06-19|TAKE BACK RETURN|RAIL|regular requests sleep slow +14598|18941|8942|3|40|74397.60|0.08|0.06|N|O|1998-03-05|1998-03-17|1998-03-17|TAKE BACK RETURN|MAIL| slyly bra +14598|136911|1938|4|13|25322.83|0.06|0.00|N|O|1998-03-30|1998-04-19|1998-04-08|COLLECT COD|REG AIR|ndencies cajole +14598|57242|4758|5|7|8394.68|0.06|0.02|N|O|1998-03-18|1998-04-28|1998-04-02|DELIVER IN PERSON|AIR|lithely even dependencie +14599|122739|2740|1|12|21140.76|0.02|0.04|A|F|1992-09-03|1992-07-14|1992-09-14|NONE|MAIL|sual deposits sleep furiously ex +14624|199006|6564|1|12|13260.00|0.03|0.08|N|O|1998-07-16|1998-06-28|1998-08-15|NONE|AIR| after the pending deposit +14624|85839|3364|2|35|63869.05|0.08|0.04|N|O|1998-06-18|1998-05-28|1998-06-25|DELIVER IN PERSON|RAIL|ly even deposits. fluffily unus +14624|84733|2258|3|21|36072.33|0.02|0.03|N|O|1998-06-23|1998-06-14|1998-06-25|DELIVER IN PERSON|FOB|ly special requests. fluffily reg +14624|103967|6478|4|36|70954.56|0.01|0.02|N|O|1998-08-12|1998-05-24|1998-09-01|TAKE BACK RETURN|TRUCK|ess packages. furiously special acco +14624|163152|701|5|24|29163.60|0.05|0.07|N|O|1998-07-12|1998-06-27|1998-07-29|DELIVER IN PERSON|REG AIR|phins. final, ironic multipliers +14624|86564|9073|6|5|7752.80|0.07|0.08|N|O|1998-07-05|1998-06-22|1998-07-12|TAKE BACK RETURN|REG AIR|ng dependencies against +14624|75952|8460|7|6|11567.70|0.04|0.04|N|O|1998-05-07|1998-07-06|1998-05-26|TAKE BACK RETURN|MAIL|onic requests maintain along +14625|110858|8392|1|2|3737.70|0.01|0.03|A|F|1992-03-10|1992-04-01|1992-04-01|DELIVER IN PERSON|REG AIR|ffily bold +14626|60915|8434|1|4|7503.64|0.01|0.03|N|O|1997-10-27|1997-09-26|1997-11-02|NONE|SHIP|requests. careful +14626|188120|8121|2|19|22954.28|0.00|0.00|N|O|1997-09-04|1997-09-14|1997-09-23|DELIVER IN PERSON|SHIP|blithely slyly ironic +14626|131530|1531|3|30|46845.90|0.02|0.07|N|O|1997-08-23|1997-10-06|1997-09-04|NONE|RAIL|gular excuses. slyly pendin +14626|12768|7771|4|41|68911.16|0.07|0.02|N|O|1997-08-14|1997-09-27|1997-08-18|COLLECT COD|TRUCK| packages wake slyly si +14627|18749|3752|1|40|66709.60|0.02|0.01|A|F|1994-04-23|1994-04-25|1994-04-24|NONE|REG AIR|nic instructions. ironic packages w +14627|98547|3566|2|1|1545.54|0.04|0.04|R|F|1994-03-29|1994-03-11|1994-04-04|NONE|SHIP|deas was slyly dogge +14627|77415|4937|3|33|45949.53|0.01|0.07|R|F|1994-02-15|1994-04-07|1994-03-04|DELIVER IN PERSON|MAIL|y silent foxes among the blithely r +14627|110519|3031|4|38|58121.38|0.08|0.01|A|F|1994-02-18|1994-03-27|1994-03-19|DELIVER IN PERSON|SHIP|ges. blithely brave dependencies +14627|80659|5676|5|27|44270.55|0.00|0.07|R|F|1994-04-04|1994-04-19|1994-04-16|TAKE BACK RETURN|FOB|fully unusua +14627|26312|6313|6|18|22289.58|0.00|0.04|A|F|1994-05-01|1994-03-19|1994-05-03|COLLECT COD|AIR|nag slyly quickly even the +14627|11250|3752|7|2|2322.50|0.01|0.06|A|F|1994-05-31|1994-04-29|1994-06-09|TAKE BACK RETURN|AIR|regular dinos. fluffily +14628|70249|250|1|50|60962.00|0.07|0.01|A|F|1993-08-08|1993-08-13|1993-08-18|TAKE BACK RETURN|MAIL|o integrate care +14629|175128|2680|1|50|60156.00|0.06|0.01|A|F|1993-02-13|1993-02-21|1993-02-19|DELIVER IN PERSON|MAIL|en asymptotes lose caref +14630|182185|2186|1|39|49420.02|0.02|0.04|A|F|1992-12-26|1992-11-20|1993-01-12|TAKE BACK RETURN|RAIL|ans sleep furiousl +14630|183172|727|2|40|50206.80|0.03|0.00|R|F|1992-11-27|1992-12-16|1992-12-17|DELIVER IN PERSON|TRUCK|ar pinto beans. regular platelets at +14630|156994|4540|3|14|28713.86|0.07|0.01|R|F|1993-01-29|1993-01-02|1993-02-15|DELIVER IN PERSON|TRUCK|osits. carefully f +14630|189259|1778|4|20|26965.00|0.08|0.03|R|F|1993-02-10|1993-01-10|1993-03-04|COLLECT COD|AIR|althy pinto beans wake. blithely +14631|158986|8987|1|14|28629.72|0.01|0.03|N|O|1997-06-01|1997-07-12|1997-06-22|COLLECT COD|FOB|arefully bold deposits are slyly acr +14631|62888|2889|2|9|16657.92|0.05|0.01|N|O|1997-05-01|1997-07-02|1997-05-19|TAKE BACK RETURN|FOB|ges around the furiously special requests +14656|59539|9540|1|21|31469.13|0.09|0.00|N|O|1998-01-23|1997-12-23|1998-02-15|DELIVER IN PERSON|AIR|lar deposits. fluffily regular accounts w +14657|33797|3798|1|49|84808.71|0.04|0.08|A|F|1994-03-23|1994-04-18|1994-03-29|COLLECT COD|SHIP| pinto beans boost fu +14657|23550|3551|2|50|73677.50|0.09|0.03|A|F|1994-05-07|1994-05-06|1994-05-28|TAKE BACK RETURN|REG AIR|lar platelet +14658|96747|6748|1|3|5231.22|0.04|0.00|R|F|1994-04-08|1994-06-25|1994-05-03|COLLECT COD|TRUCK|ravely regular pinto beans. b +14658|13234|3235|2|40|45889.20|0.03|0.07|A|F|1994-04-10|1994-05-21|1994-05-01|DELIVER IN PERSON|REG AIR|among the sl +14659|73635|8650|1|47|75605.61|0.08|0.08|N|O|1998-03-28|1998-04-22|1998-03-30|TAKE BACK RETURN|SHIP| ironic, unu +14659|172586|5104|2|18|29854.44|0.07|0.04|N|O|1998-06-08|1998-05-01|1998-06-20|TAKE BACK RETURN|FOB|ites. carefully +14659|45273|5274|3|16|19492.32|0.07|0.06|N|O|1998-05-06|1998-04-27|1998-05-22|COLLECT COD|TRUCK|s cajole carefully above the +14659|87575|2592|4|11|17188.27|0.03|0.02|N|O|1998-06-01|1998-05-04|1998-06-05|COLLECT COD|REG AIR|sleep finally fo +14660|125832|857|1|48|89175.84|0.10|0.04|N|O|1997-06-10|1997-07-02|1997-06-19|COLLECT COD|SHIP|accounts. slyly clos +14660|44934|9943|2|12|22547.16|0.04|0.07|N|O|1997-08-26|1997-08-09|1997-09-05|NONE|REG AIR|dolites are furiously. slyly ironic accou +14660|4521|9522|3|8|11404.16|0.06|0.07|N|O|1997-06-20|1997-08-10|1997-06-27|NONE|FOB|ymptotes haggl +14660|172037|9589|4|39|43252.17|0.08|0.08|N|O|1997-06-07|1997-08-20|1997-07-06|DELIVER IN PERSON|REG AIR|en requests. the +14661|27248|7249|1|32|37607.68|0.00|0.02|R|F|1993-03-30|1993-03-24|1993-04-18|DELIVER IN PERSON|FOB|symptotes use. +14662|70059|5074|1|17|17493.85|0.02|0.03|N|O|1996-01-08|1995-12-22|1996-01-21|TAKE BACK RETURN|TRUCK|across the c +14662|70005|7527|2|4|3900.00|0.09|0.04|N|O|1996-01-05|1996-01-01|1996-01-20|TAKE BACK RETURN|TRUCK|lent requests integr +14662|169533|2050|3|19|30448.07|0.03|0.05|N|O|1995-11-21|1996-02-01|1995-12-16|COLLECT COD|REG AIR|y final, ironic instructions. +14662|131473|1474|4|18|27080.46|0.00|0.01|N|O|1996-02-15|1995-12-31|1996-02-19|TAKE BACK RETURN|AIR|unts. express pinto beans c +14662|54401|4402|5|48|65059.20|0.01|0.04|N|O|1995-11-21|1996-01-21|1995-12-13|DELIVER IN PERSON|RAIL|lar packages nag about the ca +14662|113093|627|6|41|45349.69|0.07|0.07|N|O|1996-02-18|1996-01-13|1996-03-09|TAKE BACK RETURN|AIR|he fluffily regular Ti +14663|127337|2362|1|36|49115.88|0.06|0.03|A|F|1993-02-02|1992-12-23|1993-02-23|COLLECT COD|SHIP|elets. slyly +14663|152565|7596|2|1|1617.56|0.00|0.01|A|F|1993-02-02|1992-12-21|1993-03-01|DELIVER IN PERSON|MAIL|ges wake fluffily. +14688|1254|8755|1|11|12707.75|0.04|0.08|N|O|1997-06-19|1997-04-04|1997-07-09|COLLECT COD|FOB|ies are express packages. unusual +14688|65591|8098|2|20|31131.80|0.01|0.01|N|O|1997-02-19|1997-04-11|1997-03-08|DELIVER IN PERSON|SHIP|ages along the carefully idle requests wa +14688|173017|569|3|10|10900.10|0.02|0.08|N|O|1997-03-14|1997-04-22|1997-04-05|COLLECT COD|AIR|riously even packages sleep a +14688|81632|4141|4|40|64545.20|0.00|0.00|N|O|1997-04-08|1997-04-06|1997-05-07|DELIVER IN PERSON|SHIP|ruthless packages. furiously special instru +14689|98171|3190|1|29|33905.93|0.05|0.06|N|O|1998-08-22|1998-09-11|1998-09-09|NONE|TRUCK|ly bold theodolites. t +14689|148396|911|2|6|8666.34|0.01|0.06|N|O|1998-08-30|1998-10-19|1998-09-01|COLLECT COD|FOB|tes are quickly regular packages. bold dep +14689|89849|4866|3|3|5516.52|0.10|0.07|N|O|1998-09-17|1998-10-21|1998-09-27|DELIVER IN PERSON|SHIP|hy requests. unusual, special cou +14690|87337|4862|1|23|30459.59|0.02|0.03|N|O|1997-09-16|1997-07-31|1997-10-03|COLLECT COD|SHIP| pinto beans. ironic platele +14691|29610|2113|1|23|35411.03|0.09|0.01|N|O|1998-06-21|1998-05-28|1998-06-28|DELIVER IN PERSON|MAIL|gedly regular ac +14691|45081|5082|2|42|43095.36|0.08|0.07|N|O|1998-07-26|1998-07-07|1998-08-01|DELIVER IN PERSON|SHIP|hlessly final requests-- unusual t +14692|126330|1355|1|18|24413.94|0.01|0.00|N|O|1996-06-17|1996-05-15|1996-07-07|NONE|REG AIR|es alongside of the accounts nag according +14692|24090|9095|2|30|30422.70|0.06|0.02|N|O|1996-05-16|1996-03-29|1996-05-20|NONE|SHIP|arefully always even accounts. +14693|61159|6172|1|31|34724.65|0.01|0.03|A|F|1995-03-07|1995-02-10|1995-03-09|TAKE BACK RETURN|RAIL|packages are upon the packages. careful +14693|88681|8682|2|47|78474.96|0.06|0.04|A|F|1995-01-19|1995-02-22|1995-02-05|COLLECT COD|RAIL|ch slyly furio +14693|50710|3216|3|40|66428.40|0.10|0.03|A|F|1995-04-04|1995-02-25|1995-05-02|COLLECT COD|TRUCK|gainst the express, final accounts. fur +14693|74248|9263|4|16|19555.84|0.07|0.06|R|F|1995-01-24|1995-04-08|1995-02-13|NONE|FOB|e slyly; quickly f +14693|72747|7762|5|22|37834.28|0.01|0.07|A|F|1995-02-14|1995-04-07|1995-02-20|TAKE BACK RETURN|REG AIR|hall have to cajo +14694|50239|240|1|45|53515.35|0.07|0.05|N|O|1998-11-21|1998-10-22|1998-11-26|DELIVER IN PERSON|SHIP|r, express packages wake. furiously re +14694|164487|4488|2|17|26375.16|0.04|0.08|N|O|1998-11-01|1998-10-06|1998-11-04|DELIVER IN PERSON|TRUCK|slyly regular foxes. carefully regular +14694|123164|701|3|47|55796.52|0.05|0.02|N|O|1998-09-22|1998-10-13|1998-10-10|DELIVER IN PERSON|SHIP| the unusual +14694|1927|4428|4|33|60354.36|0.06|0.08|N|O|1998-08-11|1998-09-06|1998-09-10|DELIVER IN PERSON|AIR|rts. slyly even pinto +14694|172742|7777|5|22|39924.28|0.06|0.02|N|O|1998-09-23|1998-08-30|1998-10-13|COLLECT COD|REG AIR|arefully special excuses. blit +14694|71359|1360|6|40|53214.00|0.05|0.02|N|O|1998-10-06|1998-10-03|1998-10-14|COLLECT COD|FOB|venly special requ +14694|124237|6750|7|44|55494.12|0.06|0.07|N|O|1998-11-09|1998-10-25|1998-11-21|NONE|SHIP|the quickly express pinto beans. stealthi +14695|37154|7155|1|32|34916.80|0.08|0.01|A|F|1992-09-23|1992-10-16|1992-10-01|DELIVER IN PERSON|SHIP|g pinto beans are special theodolites. pend +14695|45727|3240|2|11|18399.92|0.01|0.00|R|F|1992-11-07|1992-11-20|1992-12-01|COLLECT COD|REG AIR|slyly final account +14695|127842|5379|3|32|59834.88|0.04|0.04|R|F|1992-10-04|1992-12-01|1992-10-19|COLLECT COD|RAIL|orses. regular theodolites alo +14695|35673|8177|4|43|69172.81|0.09|0.08|A|F|1992-09-28|1992-10-22|1992-10-24|NONE|AIR|ely regular packages s +14695|155411|2957|5|43|63055.63|0.06|0.05|A|F|1992-10-08|1992-12-02|1992-10-30|TAKE BACK RETURN|SHIP|lithely express asymptotes af +14720|44563|4564|1|23|34673.88|0.06|0.00|R|F|1993-10-06|1993-12-01|1993-10-23|TAKE BACK RETURN|RAIL|ges boost slyly sl +14720|156215|1246|2|4|5084.84|0.00|0.01|A|F|1993-09-11|1993-11-27|1993-09-26|DELIVER IN PERSON|AIR|ly silent requests wake fluf +14720|100576|3087|3|20|31531.40|0.08|0.06|R|F|1993-11-27|1993-11-09|1993-12-22|NONE|AIR|slyly unusual request +14720|164764|2313|4|23|42061.48|0.04|0.07|R|F|1993-10-03|1993-11-13|1993-10-29|DELIVER IN PERSON|MAIL|ly ironic foxes cajole furiously. even +14720|185734|5735|5|48|87347.04|0.10|0.08|A|F|1993-12-05|1993-11-24|1993-12-21|COLLECT COD|FOB|bout the ironic accounts sleep carefu +14721|129563|9564|1|39|62109.84|0.08|0.08|N|O|1997-07-31|1997-07-28|1997-08-18|TAKE BACK RETURN|REG AIR|ely alongside of the unusual deposits! +14721|151799|4315|2|37|68479.23|0.08|0.02|N|O|1997-07-06|1997-06-04|1997-07-28|TAKE BACK RETURN|RAIL|eodolites detect carefully ironic pinto +14721|78952|6474|3|21|40549.95|0.01|0.06|N|O|1997-06-03|1997-07-21|1997-06-16|NONE|AIR|e blithely sly accounts nag quickly abo +14721|141699|4214|4|23|40035.87|0.06|0.03|N|O|1997-05-31|1997-07-08|1997-06-16|COLLECT COD|AIR|ess pinto beans cajo +14721|133327|867|5|3|4080.96|0.00|0.02|N|O|1997-08-16|1997-07-30|1997-09-06|COLLECT COD|MAIL|lar accounts. blithely ironic +14722|79326|6848|1|49|63960.68|0.06|0.01|N|O|1997-07-18|1997-07-14|1997-07-31|DELIVER IN PERSON|REG AIR|ests. unusual requests dete +14722|28501|3506|2|35|50032.50|0.03|0.08|N|O|1997-06-14|1997-07-31|1997-07-14|NONE|REG AIR|thely according to the +14722|12861|2862|3|49|86919.14|0.05|0.03|N|O|1997-08-11|1997-08-01|1997-08-12|TAKE BACK RETURN|SHIP|low foxes. bold deposits against +14722|139463|1977|4|46|69113.16|0.02|0.03|N|O|1997-05-29|1997-07-28|1997-06-20|COLLECT COD|REG AIR|lyly ironic multi +14722|144500|7015|5|25|38612.50|0.08|0.06|N|O|1997-09-08|1997-08-11|1997-10-05|NONE|AIR|ar requests. even platelets thrash blithely +14723|28579|1082|1|34|51257.38|0.02|0.02|N|O|1997-01-16|1997-03-17|1997-02-10|COLLECT COD|TRUCK|ironic accoun +14724|130120|7660|1|36|41404.32|0.06|0.03|N|O|1996-02-06|1996-02-04|1996-02-11|COLLECT COD|MAIL| regular pinto +14725|145744|8259|1|15|26846.10|0.07|0.04|N|O|1995-06-27|1995-07-17|1995-07-24|TAKE BACK RETURN|REG AIR|yly regular packages. +14725|109317|6848|2|10|13263.10|0.03|0.02|N|O|1995-07-05|1995-07-29|1995-07-20|DELIVER IN PERSON|TRUCK|quickly ironic instruct +14725|79070|1578|3|14|14686.98|0.04|0.07|N|O|1995-07-08|1995-09-09|1995-07-20|COLLECT COD|RAIL|y ironic dependencies. sl +14725|125263|5264|4|48|61836.48|0.04|0.00|N|O|1995-09-06|1995-07-28|1995-10-04|DELIVER IN PERSON|SHIP|s cajole furiously permanen +14725|85888|5889|5|50|93694.00|0.05|0.08|N|O|1995-09-06|1995-08-21|1995-09-29|NONE|MAIL|xpress the +14725|118076|8077|6|22|24069.54|0.09|0.05|N|O|1995-08-11|1995-08-20|1995-09-09|TAKE BACK RETURN|SHIP| deposits. carefully sp +14725|89803|9804|7|23|41234.40|0.05|0.06|N|O|1995-06-24|1995-09-07|1995-07-03|COLLECT COD|TRUCK| furiously even theodolites believe bli +14726|111133|6156|1|30|34323.90|0.09|0.05|A|F|1992-02-16|1992-03-27|1992-02-29|NONE|TRUCK| above the caref +14726|2231|9732|2|12|13598.76|0.00|0.08|A|F|1992-03-18|1992-02-08|1992-04-16|DELIVER IN PERSON|TRUCK|ar foxes nag sly +14726|92071|2072|3|30|31892.10|0.08|0.05|R|F|1992-01-13|1992-02-11|1992-01-28|DELIVER IN PERSON|TRUCK|s cajole above the busily +14727|134297|6811|1|12|15975.48|0.10|0.05|R|F|1992-10-21|1992-09-01|1992-10-24|DELIVER IN PERSON|MAIL|ilent theodolites sleep sl +14727|121310|1311|2|11|14644.41|0.03|0.04|R|F|1992-08-03|1992-08-19|1992-08-24|DELIVER IN PERSON|TRUCK|al packages sleep before the flu +14727|56183|6184|3|16|18226.88|0.03|0.06|A|F|1992-07-31|1992-08-21|1992-08-20|DELIVER IN PERSON|RAIL|y quickly +14727|53811|6317|4|38|67062.78|0.08|0.03|R|F|1992-10-26|1992-09-22|1992-11-17|NONE|RAIL|ts haggle slyly asymptotes. i +14752|169824|7373|1|21|39770.22|0.08|0.02|R|F|1994-02-11|1994-03-19|1994-02-20|NONE|MAIL|y on the blithely regular dep +14753|42094|2095|1|23|23830.07|0.10|0.01|N|O|1997-01-13|1997-02-16|1997-01-23|DELIVER IN PERSON|SHIP|ptotes against the carefully pending pinto +14753|61413|3920|2|2|2748.82|0.08|0.06|N|O|1997-04-11|1997-03-31|1997-05-03|NONE|TRUCK|sleep quickly against the +14753|155173|2719|3|10|12281.70|0.03|0.05|N|O|1997-02-02|1997-03-19|1997-02-03|TAKE BACK RETURN|FOB|ccounts. ironic instructions are fluf +14754|25056|2563|1|18|17658.90|0.03|0.03|N|O|1996-07-17|1996-08-27|1996-08-10|DELIVER IN PERSON|SHIP|usly final depths wake +14754|102865|396|2|8|14942.88|0.07|0.07|N|O|1996-08-23|1996-08-28|1996-09-03|COLLECT COD|MAIL|sleep carefully according to the regular +14754|48608|6121|3|12|18679.20|0.02|0.04|N|O|1996-06-30|1996-09-07|1996-07-16|TAKE BACK RETURN|MAIL|ests cajole fina +14754|139590|9591|4|3|4888.77|0.06|0.07|N|O|1996-08-16|1996-08-17|1996-08-30|COLLECT COD|MAIL|as. quickly ir +14754|78237|3252|5|36|43748.28|0.10|0.08|N|O|1996-07-16|1996-08-05|1996-08-10|DELIVER IN PERSON|TRUCK|ncies sublate quickly against the final d +14754|122472|2473|6|4|5977.88|0.10|0.08|N|O|1996-07-26|1996-08-23|1996-08-03|DELIVER IN PERSON|FOB|lly thin accounts; carefully +14755|32105|2106|1|48|49780.80|0.05|0.06|A|F|1993-02-24|1993-03-13|1993-03-18|COLLECT COD|TRUCK|s. even theodolites a +14755|188118|5673|2|47|56687.17|0.01|0.05|R|F|1993-01-20|1993-03-13|1993-02-19|TAKE BACK RETURN|SHIP|y against the furiously brave ins +14755|92533|61|3|31|47291.43|0.04|0.07|R|F|1993-04-01|1993-03-23|1993-04-02|DELIVER IN PERSON|AIR|rate regular packages. ca +14755|186278|3833|4|14|19099.78|0.05|0.06|R|F|1993-01-22|1993-04-04|1993-02-11|NONE|MAIL|le blithely. bold, express deposits a +14755|158587|1103|5|29|47721.82|0.08|0.08|R|F|1993-04-03|1993-02-11|1993-04-20|COLLECT COD|FOB| sheaves are. furiously even requests +14755|169276|6825|6|36|48429.72|0.06|0.02|A|F|1993-04-26|1993-04-01|1993-05-17|TAKE BACK RETURN|RAIL|heodolites are. ironic, final theo +14755|14541|4542|7|30|43666.20|0.06|0.05|A|F|1993-02-19|1993-04-04|1993-03-20|COLLECT COD|AIR|y. ironic, ironic +14756|188915|8916|1|43|86168.13|0.01|0.02|R|F|1994-11-12|1994-11-06|1994-11-13|COLLECT COD|TRUCK|ldly even packages; blithely ev +14756|84634|4635|2|23|37228.49|0.05|0.00|A|F|1994-10-05|1994-11-17|1994-10-21|COLLECT COD|REG AIR|tions upon the s +14756|30304|5311|3|9|11108.70|0.10|0.04|R|F|1994-12-27|1994-10-03|1995-01-11|TAKE BACK RETURN|AIR| regular asymptotes wake furiousl +14756|112388|9922|4|6|8402.28|0.01|0.08|A|F|1994-10-09|1994-11-25|1994-10-14|NONE|AIR|he bold accounts boost slyly +14757|136123|1150|1|43|49842.16|0.00|0.03|N|O|1998-04-14|1998-03-21|1998-05-11|TAKE BACK RETURN|REG AIR|tes are fluffily a +14758|113627|8650|1|8|13124.96|0.09|0.07|R|F|1994-01-28|1994-01-04|1994-02-22|COLLECT COD|AIR|se alongside of the +14758|113351|885|2|9|12279.15|0.10|0.08|R|F|1994-02-06|1994-01-10|1994-02-12|DELIVER IN PERSON|AIR|al deposits wake blit +14758|84883|7392|3|6|11207.28|0.04|0.03|A|F|1994-02-21|1994-01-04|1994-03-20|COLLECT COD|TRUCK|efully furiously r +14758|26202|8705|4|2|2256.40|0.00|0.06|R|F|1993-12-13|1994-01-18|1994-01-02|DELIVER IN PERSON|MAIL|posits nag quic +14758|172288|7323|5|5|6801.40|0.10|0.07|R|F|1994-01-03|1993-12-24|1994-01-20|DELIVER IN PERSON|RAIL|ial, pending deposits haggl +14759|139528|9529|1|19|29782.88|0.01|0.03|N|O|1997-04-24|1997-03-22|1997-05-08|COLLECT COD|MAIL| furiously ironic pinto beans cajole expres +14759|35766|8270|2|13|22122.88|0.09|0.06|N|O|1997-02-19|1997-03-31|1997-03-05|DELIVER IN PERSON|RAIL| pinto beans. quickly express attainme +14784|52807|323|1|36|63352.80|0.05|0.03|R|F|1992-05-11|1992-04-23|1992-05-19|DELIVER IN PERSON|FOB|r special accounts. fu +14784|114073|9096|2|11|11957.77|0.05|0.01|R|F|1992-05-23|1992-05-31|1992-06-05|DELIVER IN PERSON|FOB|ously furiously special instructi +14784|23878|6381|3|21|37839.27|0.03|0.08|R|F|1992-04-10|1992-04-15|1992-04-27|COLLECT COD|AIR|ccounts haggle furiously beyond the regu +14784|107741|252|4|18|31477.32|0.03|0.02|R|F|1992-05-20|1992-05-21|1992-06-02|DELIVER IN PERSON|RAIL|lithely. blithely ironic dependencies bo +14784|188894|8895|5|24|47589.36|0.06|0.08|R|F|1992-07-03|1992-05-30|1992-08-01|TAKE BACK RETURN|RAIL|n packages. enticing dolphins sleep. ca +14784|127758|2783|6|37|66072.75|0.07|0.00|A|F|1992-06-29|1992-05-26|1992-07-01|COLLECT COD|SHIP|ic accounts. bold excuses integrate careful +14785|114180|6692|1|3|3582.54|0.03|0.07|A|F|1994-12-22|1994-12-03|1995-01-10|NONE|RAIL|thy platelets wake. +14785|13801|6303|2|2|3429.60|0.01|0.05|A|F|1994-10-18|1994-12-07|1994-11-15|DELIVER IN PERSON|MAIL|uriously silent inst +14785|152348|4864|3|3|4201.02|0.02|0.06|A|F|1995-01-05|1995-01-01|1995-01-24|TAKE BACK RETURN|MAIL|theodolites are care +14785|99622|7150|4|1|1621.62|0.01|0.08|R|F|1994-12-28|1994-12-31|1995-01-12|TAKE BACK RETURN|FOB|ages affix furiously excuses. +14785|139259|6799|5|21|27263.25|0.04|0.02|R|F|1994-11-05|1994-11-30|1994-12-01|TAKE BACK RETURN|RAIL|long the ironic requests are about +14785|117214|9726|6|5|6156.05|0.04|0.03|R|F|1994-10-14|1994-11-27|1994-11-12|COLLECT COD|AIR|he platelets can cajole +14785|199722|2242|7|34|61938.48|0.04|0.03|R|F|1994-10-28|1994-12-28|1994-11-04|COLLECT COD|REG AIR| the special, regular theodoli +14786|115117|2651|1|33|37359.63|0.02|0.00|N|O|1997-08-05|1997-05-29|1997-08-31|NONE|MAIL|its. pending, regular asymptotes doze qui +14787|151208|8754|1|6|7555.20|0.10|0.08|N|O|1998-07-24|1998-09-20|1998-07-28|DELIVER IN PERSON|SHIP|al theodolites ca +14787|141155|1156|2|50|59807.50|0.04|0.05|N|O|1998-10-23|1998-08-18|1998-11-08|TAKE BACK RETURN|SHIP|final asymptotes. pending, unusual patte +14787|189227|1746|3|32|42119.04|0.01|0.07|N|O|1998-07-29|1998-09-02|1998-08-01|TAKE BACK RETURN|AIR|efully regular instructions nod slyly. p +14788|136955|6956|1|41|81669.95|0.09|0.08|N|O|1997-11-05|1998-01-07|1997-11-27|DELIVER IN PERSON|SHIP|ording to the regular, pending foxes +14789|6127|8628|1|45|46490.40|0.07|0.06|A|F|1993-12-16|1994-02-05|1994-01-10|COLLECT COD|FOB|ut the final accounts. blith +14789|168042|8043|2|45|49951.80|0.02|0.05|A|F|1994-03-31|1994-02-20|1994-04-30|COLLECT COD|AIR| ideas. requests cajole furiously r +14789|81209|1210|3|49|58319.80|0.02|0.05|A|F|1994-02-13|1994-02-01|1994-02-24|COLLECT COD|TRUCK|ests. special packages sleep; +14789|68542|6061|4|8|12084.32|0.10|0.04|R|F|1994-03-30|1994-01-24|1994-04-06|NONE|TRUCK|equests. bold +14790|186591|4146|1|47|78846.73|0.02|0.06|N|O|1996-09-11|1996-10-09|1996-09-20|TAKE BACK RETURN|MAIL|e slowly with the stealthily regula +14790|27309|7310|2|30|37089.00|0.10|0.04|N|O|1996-09-14|1996-09-22|1996-10-04|TAKE BACK RETURN|SHIP|lyly ironic pinto be +14790|166099|1132|3|39|45438.51|0.06|0.07|N|O|1996-09-17|1996-10-12|1996-10-12|DELIVER IN PERSON|AIR|use across the quickly ironic +14790|24169|4170|4|4|4372.64|0.06|0.00|N|O|1996-09-23|1996-11-01|1996-09-28|DELIVER IN PERSON|AIR|fily ironic dinos c +14790|8106|8107|5|10|10141.00|0.06|0.04|N|O|1996-09-23|1996-09-23|1996-09-28|TAKE BACK RETURN|MAIL|lar sauternes +14790|28180|683|6|28|31029.04|0.00|0.02|N|O|1996-12-02|1996-09-27|1996-12-27|TAKE BACK RETURN|SHIP| accounts; careful accounts +14790|17291|9793|7|42|50748.18|0.07|0.00|N|O|1996-10-24|1996-10-18|1996-11-22|TAKE BACK RETURN|FOB|regular platele +14791|4477|4478|1|25|34536.75|0.06|0.05|R|F|1993-03-06|1993-04-10|1993-03-27|DELIVER IN PERSON|AIR|bold packages. furiously pending de +14791|34930|7434|2|50|93246.50|0.05|0.01|R|F|1993-06-05|1993-04-27|1993-06-14|DELIVER IN PERSON|AIR|the regular frays. fluffily ir +14791|67725|2738|3|2|3385.44|0.01|0.02|R|F|1993-04-06|1993-04-06|1993-04-30|COLLECT COD|RAIL|ts. orbits wake blithely furiously re +14816|149711|7254|1|47|82753.37|0.05|0.01|R|F|1993-08-07|1993-09-23|1993-08-13|NONE|FOB|ording to the acc +14816|189125|6680|2|15|18211.80|0.04|0.04|R|F|1993-08-26|1993-09-16|1993-09-08|DELIVER IN PERSON|MAIL|carefully ironic dugou +14817|85190|2715|1|27|31730.13|0.04|0.00|A|F|1992-08-29|1992-09-04|1992-09-18|COLLECT COD|FOB|press pinto beans. iro +14817|186376|3931|2|24|35096.88|0.10|0.04|R|F|1992-08-21|1992-09-14|1992-09-20|TAKE BACK RETURN|AIR|y even ideas wake slyly a +14817|18912|8913|3|5|9154.55|0.05|0.08|A|F|1992-08-15|1992-09-07|1992-08-26|TAKE BACK RETURN|SHIP|into beans sleep furiousl +14817|53342|8353|4|25|32383.50|0.10|0.04|A|F|1992-08-03|1992-10-17|1992-08-07|NONE|TRUCK|. deposits are carefully. slyly expre +14817|105618|8129|5|15|24354.15|0.08|0.08|R|F|1992-08-01|1992-09-28|1992-08-07|NONE|TRUCK| ironic, express gifts-- blith +14818|126888|6889|1|34|65105.92|0.00|0.04|N|O|1997-01-25|1997-02-05|1997-02-07|DELIVER IN PERSON|SHIP|the slyly regula +14818|192495|53|2|24|38099.76|0.10|0.08|N|O|1997-01-05|1997-02-09|1997-01-16|DELIVER IN PERSON|REG AIR|le slyly regular theodolites. furiously eve +14818|48257|3266|3|1|1205.25|0.08|0.05|N|O|1997-02-23|1997-01-06|1997-03-01|NONE|AIR|ilent theodolites print regular, unusu +14818|48176|8177|4|22|24731.74|0.08|0.03|N|O|1997-02-03|1997-02-13|1997-02-19|NONE|MAIL|uts detect regular, regular depo +14818|87761|2778|5|26|45467.76|0.05|0.03|N|O|1996-12-09|1997-01-16|1996-12-21|COLLECT COD|REG AIR|ts sleep carefully after th +14818|184352|9389|6|13|18672.55|0.06|0.06|N|O|1997-02-20|1997-02-09|1997-03-14|COLLECT COD|MAIL|unusual deposits haggle blithely quick +14819|115742|765|1|10|17577.40|0.01|0.04|A|F|1993-05-23|1993-03-16|1993-05-28|DELIVER IN PERSON|FOB|ording to the dogged pearls. quickly pen +14819|63806|1325|2|9|15928.20|0.07|0.04|R|F|1993-02-27|1993-03-23|1993-03-20|COLLECT COD|RAIL|long the accounts. furiously e +14819|170826|8378|3|49|92944.18|0.09|0.03|A|F|1993-05-13|1993-02-25|1993-05-17|COLLECT COD|FOB|kages wake blithely. +14819|59230|1736|4|28|33298.44|0.00|0.04|A|F|1993-04-17|1993-03-16|1993-05-04|TAKE BACK RETURN|SHIP|ular instructions. r +14820|131362|3876|1|9|12540.24|0.05|0.02|A|F|1992-03-04|1992-02-13|1992-03-31|COLLECT COD|SHIP| foxes sleep +14820|188254|5809|2|46|61743.50|0.01|0.08|R|F|1992-03-09|1992-03-28|1992-03-16|DELIVER IN PERSON|REG AIR|ges cajole carefully regular request +14820|169352|9353|3|38|54011.30|0.05|0.07|R|F|1992-02-21|1992-02-27|1992-03-17|DELIVER IN PERSON|SHIP|ep slyly after the f +14821|7148|7149|1|28|29543.92|0.00|0.00|N|O|1998-10-03|1998-07-31|1998-10-10|NONE|TRUCK|old packages. furious +14821|135022|5023|2|39|41223.78|0.00|0.04|N|O|1998-07-05|1998-09-09|1998-07-12|COLLECT COD|FOB|requests sleep carefully among the fu +14821|109822|7353|3|22|40300.04|0.09|0.07|N|O|1998-10-10|1998-09-10|1998-10-13|NONE|FOB|le careful +14821|177307|9825|4|27|37376.10|0.06|0.06|N|O|1998-06-13|1998-08-31|1998-07-09|DELIVER IN PERSON|SHIP|posits dazzle blithely quickly express acco +14821|185290|7809|5|45|61888.05|0.02|0.06|N|O|1998-10-07|1998-07-30|1998-11-05|TAKE BACK RETURN|MAIL|instructions. blithely bold deposit +14821|155936|3482|6|39|77685.27|0.08|0.03|N|O|1998-08-14|1998-08-11|1998-08-27|DELIVER IN PERSON|MAIL|ely across the idly spec +14821|4414|4415|7|43|56691.63|0.01|0.03|N|O|1998-09-27|1998-07-17|1998-10-26|COLLECT COD|AIR|fluffily final deposits eat. furiousl +14822|183138|693|1|23|28085.99|0.06|0.04|N|O|1996-07-22|1996-06-05|1996-08-13|DELIVER IN PERSON|AIR|ironic dep +14822|199146|6704|2|29|36109.06|0.08|0.04|N|O|1996-04-21|1996-06-17|1996-05-11|COLLECT COD|TRUCK| fluffily silent multiplier +14822|38796|3803|3|34|58982.86|0.02|0.02|N|O|1996-06-05|1996-05-29|1996-07-05|COLLECT COD|SHIP|old accounts nag quickly ironic, bold req +14822|36742|6743|4|38|63792.12|0.06|0.04|N|O|1996-06-22|1996-05-26|1996-07-16|NONE|MAIL|e about the +14823|16733|1736|1|29|47842.17|0.08|0.04|A|F|1994-03-06|1994-04-12|1994-03-22|TAKE BACK RETURN|FOB|ly final ideas affix daringly across the sl +14823|30091|7601|2|35|35738.15|0.01|0.00|R|F|1994-05-21|1994-04-06|1994-05-25|NONE|TRUCK|al accounts across the +14823|129982|2495|3|31|62371.38|0.01|0.02|A|F|1994-02-22|1994-04-10|1994-03-20|COLLECT COD|SHIP|y bold theodolites-- f +14823|190826|827|4|47|90090.54|0.10|0.06|A|F|1994-04-22|1994-03-27|1994-05-22|NONE|MAIL|uctions x-ray slyly quic +14848|34473|6977|1|4|5629.88|0.00|0.06|N|O|1996-12-06|1996-12-09|1996-12-27|COLLECT COD|MAIL|e. furiously pending req +14848|186170|6171|2|38|47734.46|0.02|0.07|N|O|1996-11-16|1996-12-15|1996-11-17|TAKE BACK RETURN|AIR|ts above t +14848|150696|8242|3|11|19213.59|0.05|0.05|N|O|1997-01-11|1997-01-14|1997-01-25|DELIVER IN PERSON|SHIP|gular packages. quickly regul +14848|140215|7758|4|5|6276.05|0.10|0.01|N|O|1996-10-26|1997-01-01|1996-11-08|COLLECT COD|AIR|on the special instructions wake slyly alon +14848|185114|7633|5|7|8393.77|0.08|0.05|N|O|1996-10-27|1997-01-03|1996-11-01|COLLECT COD|SHIP|ely regular tithes; regular +14848|8441|942|6|6|8096.64|0.01|0.06|N|O|1997-01-15|1996-11-30|1997-01-28|NONE|AIR|among the express pinto beans. fluffily +14849|58262|3273|1|3|3660.78|0.08|0.08|N|O|1997-03-03|1997-04-07|1997-03-11|NONE|AIR|bout the stea +14849|6042|8543|2|27|25597.08|0.07|0.07|N|O|1997-06-03|1997-05-02|1997-06-20|COLLECT COD|RAIL| shall boost? quickly special theo +14849|143300|3301|3|2|2686.60|0.07|0.00|N|O|1997-03-20|1997-04-27|1997-04-05|NONE|RAIL|s maintain bli +14849|42412|7421|4|25|33860.25|0.04|0.04|N|O|1997-04-17|1997-03-18|1997-05-10|DELIVER IN PERSON|REG AIR|pinto bean +14849|4389|6890|5|19|24574.22|0.10|0.04|N|O|1997-02-22|1997-05-04|1997-03-11|NONE|AIR|der blithely +14850|177439|7440|1|8|12131.44|0.06|0.07|N|O|1998-03-27|1998-01-08|1998-04-16|TAKE BACK RETURN|REG AIR| after the dolp +14850|5886|8387|2|41|73467.08|0.01|0.03|N|O|1998-02-18|1998-01-04|1998-03-10|COLLECT COD|TRUCK|lar, regular +14850|114564|7076|3|28|44199.68|0.01|0.03|N|O|1998-04-02|1998-02-01|1998-04-29|COLLECT COD|MAIL|s impress never about the slyly express +14850|67055|2068|4|15|15330.75|0.03|0.07|N|O|1998-02-19|1998-01-03|1998-02-27|DELIVER IN PERSON|REG AIR|osits use busily regular, regu +14850|177559|5111|5|47|76917.85|0.07|0.00|N|O|1998-03-22|1998-01-12|1998-04-17|NONE|AIR|requests are furiously above the furiou +14850|32612|122|6|40|61784.40|0.07|0.01|N|O|1997-12-07|1998-02-05|1998-01-06|NONE|FOB|he express instructions. furiously +14851|128017|530|1|23|24035.23|0.09|0.04|R|F|1992-06-06|1992-07-18|1992-06-07|DELIVER IN PERSON|TRUCK|he pending ideas. quickly final pi +14851|166102|6103|2|25|29202.50|0.06|0.03|R|F|1992-08-10|1992-06-27|1992-08-28|DELIVER IN PERSON|RAIL|eodolites unwind blithely according to th +14851|75733|5734|3|23|39300.79|0.08|0.02|R|F|1992-07-27|1992-06-25|1992-07-28|DELIVER IN PERSON|FOB| asymptotes wake. ironic accounts boost ir +14851|31669|4173|4|29|46419.14|0.04|0.05|R|F|1992-08-03|1992-07-12|1992-08-16|NONE|REG AIR|ajole furiously furiously regular acc +14851|58285|3296|5|9|11189.52|0.10|0.02|R|F|1992-08-05|1992-07-13|1992-08-29|DELIVER IN PERSON|SHIP|ously special foxe +14851|187820|2857|6|49|93483.18|0.09|0.04|A|F|1992-07-29|1992-07-26|1992-08-20|NONE|RAIL|cies lose blithely furiously regu +14852|25634|3141|1|22|34311.86|0.03|0.03|N|O|1996-03-26|1996-02-08|1996-04-25|DELIVER IN PERSON|FOB|al pinto beans according +14852|16474|8976|2|9|12514.23|0.05|0.01|N|O|1996-01-12|1996-02-16|1996-01-25|TAKE BACK RETURN|RAIL|hely final deposits a +14853|121211|1212|1|16|19715.36|0.07|0.00|N|O|1996-11-19|1996-12-02|1996-11-26|COLLECT COD|AIR|ld packages acros +14853|192401|7440|2|46|68696.40|0.03|0.08|N|O|1996-12-25|1996-11-02|1996-12-26|DELIVER IN PERSON|MAIL|among the slyly re +14853|82658|183|3|18|29531.70|0.00|0.00|N|O|1996-12-01|1996-11-20|1996-12-08|TAKE BACK RETURN|RAIL|nts. slyly blithe +14853|18576|8577|4|16|23913.12|0.02|0.01|N|O|1996-11-18|1996-10-10|1996-12-04|DELIVER IN PERSON|TRUCK|etly accounts. e +14854|169774|9775|1|20|36875.40|0.10|0.04|A|F|1993-04-30|1993-06-30|1993-05-08|DELIVER IN PERSON|REG AIR|. blithely final instructions ha +14854|183507|1062|2|3|4771.50|0.00|0.07|R|F|1993-08-27|1993-07-26|1993-09-09|DELIVER IN PERSON|AIR| ironic pinto beans use blithely around +14854|186680|4235|3|9|15900.12|0.00|0.00|R|F|1993-06-17|1993-06-21|1993-07-14|COLLECT COD|FOB|s dolphins. ironic +14854|119332|9333|4|23|31080.59|0.04|0.00|R|F|1993-05-24|1993-07-09|1993-06-14|DELIVER IN PERSON|TRUCK|is integrate quickly dep +14855|93981|1509|1|2|3949.96|0.09|0.06|A|F|1993-08-13|1993-06-16|1993-08-28|COLLECT COD|RAIL|he blithely fin +14855|127948|461|2|28|55326.32|0.04|0.01|R|F|1993-08-04|1993-06-11|1993-08-20|DELIVER IN PERSON|AIR|ronic packages. slyly +14855|18339|8340|3|49|61609.17|0.01|0.01|R|F|1993-06-30|1993-06-28|1993-07-06|DELIVER IN PERSON|TRUCK|ckages cajole furiously carefull +14855|11873|4375|4|43|76749.41|0.06|0.06|A|F|1993-05-16|1993-06-13|1993-06-03|NONE|SHIP|t the slyly +14855|142111|9654|5|7|8071.77|0.08|0.08|A|F|1993-08-02|1993-07-22|1993-08-14|DELIVER IN PERSON|REG AIR|uickly regular pinto be +14880|179008|9009|1|26|28262.00|0.02|0.03|N|O|1998-02-25|1998-02-18|1998-03-22|DELIVER IN PERSON|RAIL|nts detect. final pinto beans are. furio +14880|172714|2715|2|42|75041.82|0.04|0.03|N|O|1997-12-11|1998-01-14|1997-12-24|COLLECT COD|RAIL|bove the final, spec +14880|197606|126|3|23|39182.80|0.09|0.01|N|O|1998-01-10|1998-01-24|1998-02-08|TAKE BACK RETURN|MAIL|nag furiously. fu +14880|147307|9822|4|17|23023.10|0.06|0.01|N|O|1998-02-07|1998-01-04|1998-02-08|NONE|FOB|out the ideas. foxes cajole carefully +14880|180186|2705|5|13|16460.34|0.01|0.03|N|O|1998-01-25|1998-02-12|1998-02-01|NONE|REG AIR|dencies. bli +14880|177291|4843|6|8|10946.32|0.10|0.06|N|O|1998-01-17|1998-01-20|1998-02-12|NONE|REG AIR|-- final instructi +14881|179247|6799|1|35|46418.40|0.07|0.03|N|O|1996-10-30|1996-12-14|1996-11-25|NONE|AIR|regular accoun +14881|3657|1158|2|35|54622.75|0.04|0.00|N|O|1996-11-18|1997-01-08|1996-12-07|NONE|MAIL|nal deposits alongside of the +14881|61853|1854|3|23|41741.55|0.00|0.08|N|O|1996-11-20|1996-12-21|1996-12-03|TAKE BACK RETURN|REG AIR|cing excuses sleep slyly +14882|139468|7008|1|35|52761.10|0.08|0.01|N|O|1997-05-26|1997-03-22|1997-06-25|DELIVER IN PERSON|TRUCK|r accounts. the +14882|32167|7174|2|41|45065.56|0.08|0.03|N|O|1997-03-18|1997-04-05|1997-03-21|TAKE BACK RETURN|MAIL|s. account +14883|180536|3055|1|37|59811.61|0.02|0.03|N|O|1995-09-05|1995-06-07|1995-09-11|DELIVER IN PERSON|MAIL|into beans wake bl +14883|54835|7341|2|23|41166.09|0.00|0.07|A|F|1995-05-24|1995-07-16|1995-05-31|NONE|SHIP|ts cajole permanently +14883|7868|7869|3|9|15982.74|0.01|0.04|N|O|1995-06-20|1995-07-07|1995-07-17|COLLECT COD|FOB|ong the carefully regul +14883|33615|8622|4|9|13937.49|0.10|0.00|N|O|1995-07-16|1995-07-11|1995-08-06|COLLECT COD|AIR|ccounts. express, unusual foxes wa +14883|166991|6992|5|8|16463.92|0.04|0.04|N|O|1995-07-10|1995-07-31|1995-07-12|NONE|MAIL|g packages. furiously unusual packages s +14883|8118|8119|6|18|18469.98|0.02|0.03|N|O|1995-07-16|1995-06-16|1995-07-20|COLLECT COD|FOB|its. permanentl +14884|28731|1234|1|37|61410.01|0.10|0.00|N|O|1995-11-26|1995-12-03|1995-12-09|DELIVER IN PERSON|TRUCK| quickly slyly final theodolites. qu +14884|67955|462|2|18|34613.10|0.08|0.08|N|O|1995-10-05|1995-11-06|1995-10-17|COLLECT COD|REG AIR|y unusual accounts +14884|107456|2477|3|42|61464.90|0.03|0.01|N|O|1995-12-09|1995-12-24|1995-12-19|TAKE BACK RETURN|MAIL|regular epitaph +14884|654|655|4|17|26429.05|0.00|0.05|N|O|1995-11-26|1995-10-29|1995-12-19|NONE|TRUCK| cajole furiously regular, bol +14884|177747|7748|5|30|54742.20|0.08|0.08|N|O|1995-10-27|1995-12-13|1995-11-04|DELIVER IN PERSON|TRUCK|press dolphins. final excuses about +14884|178070|8071|6|34|39034.38|0.08|0.07|N|O|1995-11-19|1995-10-28|1995-11-29|TAKE BACK RETURN|MAIL|. slyly express account +14884|19078|4081|7|42|41876.94|0.01|0.05|N|O|1996-01-11|1995-12-26|1996-02-02|COLLECT COD|FOB|luffily pending dolphins-- fi +14885|36154|3664|1|15|16352.25|0.09|0.02|N|O|1997-11-04|1997-11-16|1997-11-10|TAKE BACK RETURN|RAIL| asymptotes across the +14885|39103|9104|2|28|29178.80|0.07|0.06|N|O|1998-01-15|1997-11-10|1998-02-09|TAKE BACK RETURN|FOB|above the carefully regular +14885|198838|3877|3|2|3873.66|0.00|0.08|N|O|1997-11-21|1997-10-27|1997-12-09|NONE|FOB|e furiously express ideas. furiou +14885|67242|9749|4|37|44741.88|0.09|0.08|N|O|1997-12-23|1997-11-16|1998-01-08|DELIVER IN PERSON|AIR|uests. fluffily pending accounts accord +14885|134174|6688|5|40|48326.80|0.05|0.06|N|O|1997-10-17|1997-12-11|1997-11-15|NONE|RAIL|e fluffily even packages use blithel +14885|47626|5139|6|30|47208.60|0.04|0.01|N|O|1997-12-04|1997-11-17|1997-12-09|COLLECT COD|SHIP| the requests hang slyly a +14885|45991|8496|7|42|81353.58|0.02|0.01|N|O|1997-10-19|1997-11-08|1997-11-14|TAKE BACK RETURN|AIR|ng to the regular, ironic pinto beans. bo +14886|160915|5948|1|50|98795.50|0.02|0.01|A|F|1994-08-08|1994-08-06|1994-08-20|COLLECT COD|AIR| to the packages. +14886|95628|647|2|5|8118.10|0.04|0.08|A|F|1994-07-04|1994-07-24|1994-07-07|COLLECT COD|TRUCK| requests. ironic instructio +14887|148649|1164|1|23|39045.72|0.05|0.04|N|O|1996-07-08|1996-06-05|1996-07-10|NONE|SHIP|unusual grouches. blithely ironic +14887|133470|8497|2|34|51117.98|0.08|0.06|N|O|1996-07-16|1996-05-11|1996-08-04|DELIVER IN PERSON|REG AIR|are quickly alongside of th +14887|26457|8960|3|14|19368.30|0.02|0.05|N|O|1996-07-16|1996-06-16|1996-08-09|COLLECT COD|RAIL|the quickly final excuses? fluffily even +14887|61414|3921|4|23|31634.43|0.06|0.08|N|O|1996-04-02|1996-05-22|1996-04-29|NONE|MAIL|unts above the +14912|35275|2785|1|14|16943.78|0.02|0.02|R|F|1993-11-16|1994-01-24|1993-12-09|COLLECT COD|AIR|the pinto beans-- express deposi +14912|56870|1881|2|7|12788.09|0.02|0.05|R|F|1993-12-20|1993-12-28|1993-12-22|DELIVER IN PERSON|MAIL| even ideas. unusual deposits sleep slyly +14913|169423|1940|1|27|40295.34|0.10|0.06|A|F|1994-03-14|1994-05-03|1994-04-09|NONE|FOB|pinto beans sleep carefull +14913|83528|8545|2|12|18138.24|0.05|0.01|R|F|1994-05-13|1994-04-20|1994-06-09|NONE|MAIL|ticingly regular courts boost. care +14913|41248|6257|3|10|11892.40|0.03|0.04|A|F|1994-04-23|1994-04-30|1994-05-22|NONE|SHIP| even, silent deposits. bold, iro +14913|46748|9253|4|44|74568.56|0.00|0.06|A|F|1994-03-31|1994-03-31|1994-04-05|TAKE BACK RETURN|AIR|cial instructions wake +14913|79152|9153|5|25|28278.75|0.10|0.05|A|F|1994-03-11|1994-03-28|1994-03-31|TAKE BACK RETURN|TRUCK| unusual, express ideas sleep slyly. +14914|86646|4171|1|20|32652.80|0.08|0.08|N|O|1998-05-26|1998-05-05|1998-06-02|NONE|SHIP|ests alongsid +14914|51355|1356|2|38|49641.30|0.04|0.02|N|O|1998-03-17|1998-04-26|1998-04-04|TAKE BACK RETURN|RAIL|even pinto beans against the quickly reg +14914|109131|4152|3|20|22802.60|0.07|0.05|N|O|1998-04-03|1998-04-24|1998-04-10|TAKE BACK RETURN|MAIL|oxes. fluffily e +14914|160032|7581|4|19|20748.57|0.06|0.05|N|O|1998-05-28|1998-03-25|1998-06-22|NONE|MAIL|es are always against the ir +14914|49477|6990|5|24|34235.28|0.10|0.02|N|O|1998-02-17|1998-05-09|1998-03-04|TAKE BACK RETURN|MAIL|y permanent foxes b +14914|150197|7743|6|20|24943.80|0.10|0.01|N|O|1998-02-19|1998-04-29|1998-03-21|TAKE BACK RETURN|TRUCK|nding depos +14915|82338|2339|1|1|1320.33|0.06|0.06|N|O|1996-11-22|1996-11-25|1996-12-11|NONE|FOB|ual sheaves sleep +14915|37981|5491|2|45|86354.10|0.00|0.01|N|O|1997-01-08|1996-10-27|1997-01-22|NONE|SHIP| carefully express instructions. carefu +14916|20029|30|1|25|23725.50|0.04|0.07|A|F|1994-05-07|1994-04-20|1994-06-03|TAKE BACK RETURN|FOB|cajole. silent accounts nod iron +14916|13490|3491|2|43|60350.07|0.04|0.03|A|F|1994-06-26|1994-04-18|1994-07-25|DELIVER IN PERSON|REG AIR|ests doubt furiously. bold +14917|44468|9477|1|26|36723.96|0.08|0.01|N|O|1998-04-25|1998-03-14|1998-05-07|COLLECT COD|SHIP|nic theodolites. theodolites +14917|173011|5529|2|29|31436.29|0.05|0.03|N|O|1998-03-24|1998-02-20|1998-03-28|NONE|FOB|nusual theodolit +14917|189874|4911|3|48|94265.76|0.08|0.07|N|O|1998-03-05|1998-04-11|1998-03-13|COLLECT COD|TRUCK|g theodolites affix slyly fina +14917|8532|1033|4|40|57621.20|0.04|0.06|N|O|1998-02-20|1998-03-13|1998-03-14|COLLECT COD|TRUCK|g bravely. fu +14917|191897|1898|5|21|41766.69|0.04|0.05|N|O|1998-02-18|1998-04-01|1998-03-02|DELIVER IN PERSON|AIR|as above the regular excuses ha +14917|6142|8643|6|43|45070.02|0.10|0.03|N|O|1998-05-11|1998-04-07|1998-05-12|DELIVER IN PERSON|AIR|e. final, pending pint +14918|27104|2109|1|33|34026.30|0.04|0.05|N|O|1997-09-04|1997-08-30|1997-09-11|TAKE BACK RETURN|FOB|he blithely +14918|129359|9360|2|24|33320.40|0.00|0.02|N|O|1997-06-20|1997-08-11|1997-07-10|COLLECT COD|FOB| the pending, e +14919|52516|32|1|24|35244.24|0.00|0.07|N|O|1996-09-29|1996-11-09|1996-10-16|COLLECT COD|AIR|jole quickly blith +14944|173320|3321|1|50|69666.00|0.01|0.05|N|O|1997-11-30|1997-12-08|1997-12-11|COLLECT COD|RAIL|ges. slyly special requ +14944|173250|8285|2|21|27788.25|0.05|0.06|N|O|1998-01-11|1997-12-01|1998-01-26|TAKE BACK RETURN|AIR|uriously express platelets +14945|9317|9318|1|28|34336.68|0.05|0.06|N|O|1996-07-04|1996-06-09|1996-07-23|COLLECT COD|MAIL|o the regular, regular asymptotes. c +14945|187788|307|2|24|45018.72|0.10|0.03|N|O|1996-05-27|1996-05-05|1996-06-01|NONE|REG AIR|to the carefully eve +14945|145205|5206|3|38|47507.60|0.01|0.05|N|O|1996-04-29|1996-04-30|1996-05-20|TAKE BACK RETURN|SHIP|eposits. fluff +14945|54657|2173|4|2|3223.30|0.09|0.07|N|O|1996-07-03|1996-05-13|1996-07-16|COLLECT COD|FOB|tween the expres +14945|8458|8459|5|44|60123.80|0.08|0.03|N|O|1996-06-20|1996-05-03|1996-07-14|DELIVER IN PERSON|RAIL|ly around the furiously regular +14945|139229|6769|6|37|46924.14|0.05|0.00|N|O|1996-07-02|1996-05-15|1996-07-31|NONE|FOB|ironic asymptotes. +14946|5229|7730|1|38|43100.36|0.00|0.04|N|O|1996-12-13|1997-02-04|1997-01-08|NONE|MAIL|pon the blithely final courts. bl +14946|79479|4494|2|37|53963.39|0.01|0.01|N|O|1996-11-27|1997-02-01|1996-11-29|COLLECT COD|AIR|sleep furiously after the furio +14947|31184|3688|1|14|15612.52|0.09|0.02|N|O|1995-11-05|1995-09-25|1995-11-27|TAKE BACK RETURN|RAIL|bout the even, iro +14947|107098|7099|2|29|32047.61|0.04|0.06|N|O|1995-11-08|1995-08-30|1995-12-03|TAKE BACK RETURN|FOB|inal sentiments t diff --git a/src/test/regress/data/nation.data b/src/test/regress/data/nation.data new file mode 100644 index 000000000..ee71b02ea --- /dev/null +++ b/src/test/regress/data/nation.data @@ -0,0 +1,25 @@ +0|ALGERIA|0| haggle. carefully final deposits detect slyly agai +1|ARGENTINA|1|al foxes promise slyly according to the regular accounts. bold requests alon +2|BRAZIL|1|y alongside of the pending deposits. carefully special packages are about the ironic forges. slyly special +3|CANADA|1|eas hang ironic, silent packages. slyly regular packages are furiously over the tithes. fluffily bold +4|EGYPT|4|y above the carefully unusual theodolites. final dugouts are quickly across the furiously regular d +5|ETHIOPIA|0|ven packages wake quickly. regu +6|FRANCE|3|refully final requests. regular, ironi +7|GERMANY|3|l platelets. regular accounts x-ray: unusual, regular acco +8|INDIA|2|ss excuses cajole slyly across the packages. deposits print aroun +9|INDONESIA|2| slyly express asymptotes. regular deposits haggle slyly. carefully ironic hockey players sleep blithely. carefull +10|IRAN|4|efully alongside of the slyly final dependencies. +11|IRAQ|4|nic deposits boost atop the quickly final requests? quickly regula +12|JAPAN|2|ously. final, express gifts cajole a +13|JORDAN|4|ic deposits are blithely about the carefully regular pa +14|KENYA|0| pending excuses haggle furiously deposits. pending, express pinto beans wake fluffily past t +15|MOROCCO|0|rns. blithely bold courts among the closely regular packages use furiously bold platelets? +16|MOZAMBIQUE|0|s. ironic, unusual asymptotes wake blithely r +17|PERU|1|platelets. blithely pending dependencies use fluffily across the even pinto beans. carefully silent accoun +18|CHINA|2|c dependencies. furiously express notornis sleep slyly regular accounts. ideas sleep. depos +19|ROMANIA|3|ular asymptotes are about the furious multipliers. express dependencies nag above the ironically ironic account +20|SAUDI ARABIA|4|ts. silent requests haggle. closely express packages sleep across the blithely +21|VIETNAM|2|hely enticingly express accounts. even, final +22|RUSSIA|3| requests against the platelets use never according to the quickly regular pint +23|UNITED KINGDOM|3|eans boost carefully special requests. accounts are. carefull +24|UNITED STATES|1|y final packages. slow foxes cajole quickly. quickly silent platelets breach ironic accounts. unusual pinto be diff --git a/src/test/regress/data/orders.1.data b/src/test/regress/data/orders.1.data new file mode 100644 index 000000000..990d08ce0 --- /dev/null +++ b/src/test/regress/data/orders.1.data @@ -0,0 +1,1498 @@ +1|370|O|172799.49|1996-01-02|5-LOW|Clerk#000000951|0|nstructions sleep furiously among +2|781|O|38426.09|1996-12-01|1-URGENT|Clerk#000000880|0| foxes. pending accounts at the pending, silent asymptot +3|1234|F|205654.30|1993-10-14|5-LOW|Clerk#000000955|0|sly final accounts boost. carefully regular ideas cajole carefully. depos +4|1369|O|56000.91|1995-10-11|5-LOW|Clerk#000000124|0|sits. slyly regular warthogs cajole. regular, regular theodolites acro +5|445|F|105367.67|1994-07-30|5-LOW|Clerk#000000925|0|quickly. bold deposits sleep slyly. packages use slyly +6|557|F|45523.10|1992-02-21|4-NOT SPECIFIED|Clerk#000000058|0|ggle. special, final requests are against the furiously specia +7|392|O|271885.66|1996-01-10|2-HIGH|Clerk#000000470|0|ly special requests +32|1301|O|198665.57|1995-07-16|2-HIGH|Clerk#000000616|0|ise blithely bold, regular requests. quickly unusual dep +33|670|F|146567.24|1993-10-27|3-MEDIUM|Clerk#000000409|0|uriously. furiously final request +34|611|O|73315.48|1998-07-21|3-MEDIUM|Clerk#000000223|0|ly final packages. fluffily final deposits wake blithely ideas. spe +35|1276|O|194641.93|1995-10-23|4-NOT SPECIFIED|Clerk#000000259|0|zzle. carefully enticing deposits nag furio +36|1153|O|42011.04|1995-11-03|1-URGENT|Clerk#000000358|0| quick packages are blithely. slyly silent accounts wake qu +37|862|F|131896.49|1992-06-03|3-MEDIUM|Clerk#000000456|0|kly regular pinto beans. carefully unusual waters cajole never +38|1249|O|71553.08|1996-08-21|4-NOT SPECIFIED|Clerk#000000604|0|haggle blithely. furiously express ideas haggle blithely furiously regular re +39|818|O|326565.37|1996-09-20|3-MEDIUM|Clerk#000000659|0|ole express, ironic requests: ir +64|322|F|35831.73|1994-07-16|3-MEDIUM|Clerk#000000661|0|wake fluffily. sometimes ironic pinto beans about the dolphin +65|163|P|95469.44|1995-03-18|1-URGENT|Clerk#000000632|0|ular requests are blithely pending orbits-- even requests against the deposit +66|1292|F|104190.66|1994-01-20|5-LOW|Clerk#000000743|0|y pending requests integrate +67|568|O|182481.16|1996-12-19|4-NOT SPECIFIED|Clerk#000000547|0|symptotes haggle slyly around the furiously iron +68|286|O|301968.79|1998-04-18|3-MEDIUM|Clerk#000000440|0| pinto beans sleep carefully. blithely ironic deposits haggle furiously acro +69|845|F|204110.73|1994-06-04|4-NOT SPECIFIED|Clerk#000000330|0| depths atop the slyly thin deposits detect among the furiously silent accou +70|644|F|125705.32|1993-12-18|5-LOW|Clerk#000000322|0| carefully ironic request +71|34|O|260603.38|1998-01-24|4-NOT SPECIFIED|Clerk#000000271|0| express deposits along the blithely regul +96|1078|F|64364.30|1994-04-17|2-HIGH|Clerk#000000395|0|oost furiously. pinto +97|211|F|100572.55|1993-01-29|3-MEDIUM|Clerk#000000547|0|hang blithely along the regular accounts. furiously even ideas after the +98|1045|F|71721.40|1994-09-25|1-URGENT|Clerk#000000448|0|c asymptotes. quickly regular packages should have to nag re +99|890|F|108594.87|1994-03-13|4-NOT SPECIFIED|Clerk#000000973|0|e carefully ironic packages. pending +100|1471|O|198978.27|1998-02-28|4-NOT SPECIFIED|Clerk#000000577|0|heodolites detect slyly alongside of the ent +101|280|O|118448.39|1996-03-17|3-MEDIUM|Clerk#000000419|0|ding accounts above the slyly final asymptote +102|8|O|184806.58|1997-05-09|2-HIGH|Clerk#000000596|0| slyly according to the asymptotes. carefully final packages integrate furious +103|292|O|118745.16|1996-06-20|4-NOT SPECIFIED|Clerk#000000090|0|ges. carefully unusual instructions haggle quickly regular f +128|740|F|34997.04|1992-06-15|1-URGENT|Clerk#000000385|0|ns integrate fluffily. ironic asymptotes after the regular excuses nag around +129|712|F|254281.41|1992-11-19|5-LOW|Clerk#000000859|0|ing tithes. carefully pending deposits boost about the silently express +130|370|F|140213.54|1992-05-08|2-HIGH|Clerk#000000036|0|le slyly unusual, regular packages? express deposits det +131|928|F|140726.47|1994-06-08|3-MEDIUM|Clerk#000000625|0|after the fluffily special foxes integrate s +132|265|F|133485.89|1993-06-11|3-MEDIUM|Clerk#000000488|0|sits are daringly accounts. carefully regular foxes sleep slyly about the +133|440|O|95971.06|1997-11-29|1-URGENT|Clerk#000000738|0|usly final asymptotes +134|62|F|208201.46|1992-05-01|4-NOT SPECIFIED|Clerk#000000711|0|lar theodolites boos +135|605|O|230472.84|1995-10-21|4-NOT SPECIFIED|Clerk#000000804|0|l platelets use according t +160|826|O|114742.32|1996-12-19|4-NOT SPECIFIED|Clerk#000000342|0|thely special sauternes wake slyly of t +161|167|F|17668.60|1994-08-31|2-HIGH|Clerk#000000322|0|carefully! special instructions sin +162|142|O|3553.15|1995-05-08|3-MEDIUM|Clerk#000000378|0|nts hinder fluffily ironic instructions. express, express excuses +163|878|O|177809.13|1997-09-05|3-MEDIUM|Clerk#000000379|0|y final packages. final foxes since the quickly even +164|8|F|250417.20|1992-10-21|5-LOW|Clerk#000000209|0|cajole ironic courts. slyly final ideas are slyly. blithely final Tiresias sub +165|274|F|193302.35|1993-01-30|4-NOT SPECIFIED|Clerk#000000292|0|across the blithely regular accounts. bold +166|1079|O|158207.39|1995-09-12|2-HIGH|Clerk#000000440|0|lets. ironic, bold asymptotes kindle +167|1195|F|64017.85|1993-01-04|4-NOT SPECIFIED|Clerk#000000731|0|s nag furiously bold excuses. fluffily iron +192|826|O|194637.57|1997-11-25|5-LOW|Clerk#000000483|0|y unusual platelets among the final instructions integrate rut +193|791|F|80834.26|1993-08-08|1-URGENT|Clerk#000000025|0|the furiously final pin +194|619|F|154284.73|1992-04-05|3-MEDIUM|Clerk#000000352|0|egular requests haggle slyly regular, regular pinto beans. asymptote +195|1355|F|216638.92|1993-12-28|3-MEDIUM|Clerk#000000216|0|old forges are furiously sheaves. slyly fi +196|649|F|38660.64|1993-03-17|2-HIGH|Clerk#000000988|0|beans boost at the foxes. silent foxes +197|326|P|155247.48|1995-04-07|2-HIGH|Clerk#000000969|0|solve quickly about the even braids. carefully express deposits affix care +198|1103|O|149551.63|1998-01-02|4-NOT SPECIFIED|Clerk#000000331|0|its. carefully ironic requests sleep. furiously express fox +199|530|O|95867.70|1996-03-07|2-HIGH|Clerk#000000489|0|g theodolites. special packag +224|25|F|234050.44|1994-06-18|4-NOT SPECIFIED|Clerk#000000642|0|r the quickly thin courts. carefully +225|331|P|226028.98|1995-05-25|1-URGENT|Clerk#000000177|0|s. blithely ironic accounts wake quickly fluffily special acc +226|1276|F|256459.40|1993-03-10|2-HIGH|Clerk#000000756|0|s are carefully at the blithely ironic acc +227|100|O|69020.68|1995-11-10|5-LOW|Clerk#000000919|0| express instructions. slyly regul +228|442|F|2744.06|1993-02-25|1-URGENT|Clerk#000000562|0|es was slyly among the regular foxes. blithely regular dependenci +229|1118|F|195619.74|1993-12-29|1-URGENT|Clerk#000000628|0|he fluffily even instructions. furiously i +230|1027|F|147711.01|1993-10-27|1-URGENT|Clerk#000000520|0|odolites. carefully quick requ +231|910|F|234383.86|1994-09-29|2-HIGH|Clerk#000000446|0| packages haggle slyly after the carefully ironic instruct +256|1249|F|132718.67|1993-10-19|4-NOT SPECIFIED|Clerk#000000834|0|he fluffily final ideas might are final accounts. carefully f +257|1228|O|9255.12|1998-03-28|3-MEDIUM|Clerk#000000680|0|ts against the sly warhorses cajole slyly accounts +258|419|F|259466.78|1993-12-29|1-URGENT|Clerk#000000167|0|dencies. blithely quick packages cajole. ruthlessly final accounts +259|433|F|110611.59|1993-09-29|4-NOT SPECIFIED|Clerk#000000601|0|ages doubt blithely against the final foxes. carefully express deposits dazzle +260|1048|O|268084.69|1996-12-10|3-MEDIUM|Clerk#000000960|0|lently regular pinto beans sleep after the slyly e +261|461|F|278279.30|1993-06-29|3-MEDIUM|Clerk#000000310|0|ully fluffily brave instructions. furiousl +262|304|O|173401.63|1995-11-25|4-NOT SPECIFIED|Clerk#000000551|0|l packages. blithely final pinto beans use carefu +263|1162|F|104961.32|1994-05-17|2-HIGH|Clerk#000000088|0| pending instructions. blithely un +288|71|O|239366.68|1997-02-21|1-URGENT|Clerk#000000109|0|uriously final requests. even, final ideas det +289|1039|O|174624.55|1997-02-10|3-MEDIUM|Clerk#000000103|0|sily. slyly special excuse +290|1180|F|67636.54|1994-01-01|4-NOT SPECIFIED|Clerk#000000735|0|efully dogged deposits. furiou +291|1411|F|88375.89|1994-03-13|1-URGENT|Clerk#000000923|0|dolites. carefully regular pinto beans cajol +292|223|F|54152.77|1992-01-13|2-HIGH|Clerk#000000193|0|g pinto beans will have to sleep f +293|301|F|46128.56|1992-10-02|2-HIGH|Clerk#000000629|0|re bold, ironic deposits. platelets c +294|505|F|46889.54|1993-07-16|3-MEDIUM|Clerk#000000499|0|kly according to the frays. final dolphins affix quickly +295|190|F|148569.49|1994-09-29|2-HIGH|Clerk#000000155|0| unusual pinto beans play. regular ideas haggle +320|4|O|50202.60|1997-11-21|2-HIGH|Clerk#000000573|0|ar foxes nag blithely +321|1226|F|73024.50|1993-03-21|3-MEDIUM|Clerk#000000289|0|equests run. blithely final dependencies after the deposits wake caref +322|1336|F|165992.05|1992-03-19|1-URGENT|Clerk#000000158|0|fully across the slyly bold packages. packages against the quickly regular i +323|392|F|121127.17|1994-03-26|1-URGENT|Clerk#000000959|0|arefully pending foxes sleep blithely. slyly express accoun +324|1052|F|46327.90|1992-03-20|1-URGENT|Clerk#000000352|0| about the ironic, regular deposits run blithely against the excuses +325|401|F|94638.59|1993-10-17|5-LOW|Clerk#000000844|0|ly sometimes pending pa +326|760|O|325448.68|1995-06-04|2-HIGH|Clerk#000000466|0| requests. furiously ironic asymptotes mold carefully alongside of the blit +327|1447|P|32302.12|1995-04-17|5-LOW|Clerk#000000992|0|ng the slyly final courts. slyly even escapades eat +352|1066|F|25542.02|1994-03-08|2-HIGH|Clerk#000000932|0|ke slyly bold pinto beans. blithely regular accounts against the spe +353|19|F|224983.69|1993-12-31|5-LOW|Clerk#000000449|0| quiet ideas sleep. even instructions cajole slyly. silently spe +354|1384|O|231311.22|1996-03-14|2-HIGH|Clerk#000000511|0|ly regular ideas wake across the slyly silent ideas. final deposits eat b +355|701|F|103949.82|1994-06-14|5-LOW|Clerk#000000532|0|s. sometimes regular requests cajole. regular, pending accounts a +356|1469|F|189160.02|1994-06-30|4-NOT SPECIFIED|Clerk#000000944|0|as wake along the bold accounts. even, +357|604|O|138936.83|1996-10-09|2-HIGH|Clerk#000000301|0|e blithely about the express, final accounts. quickl +358|23|F|362024.17|1993-09-20|2-HIGH|Clerk#000000392|0|l, silent instructions are slyly. silently even de +359|776|F|214770.97|1994-12-19|3-MEDIUM|Clerk#000000934|0|n dolphins. special courts above the carefully ironic requests use +384|1132|F|191275.12|1992-03-03|5-LOW|Clerk#000000206|0|, even accounts use furiously packages. slyly ironic pla +385|331|O|75866.47|1996-03-22|5-LOW|Clerk#000000600|0|hless accounts unwind bold pain +386|602|F|119718.02|1995-01-25|2-HIGH|Clerk#000000648|0| haggle quickly. stealthily bold asymptotes haggle among the furiously even re +387|34|O|197839.44|1997-01-26|4-NOT SPECIFIED|Clerk#000000768|0| are carefully among the quickly even deposits. furiously silent req +388|448|F|161560.04|1992-12-16|4-NOT SPECIFIED|Clerk#000000356|0|ar foxes above the furiously ironic deposits nag slyly final reque +389|1270|F|3266.69|1994-02-17|2-HIGH|Clerk#000000062|0|ing to the regular asymptotes. final, pending foxes about the blithely sil +390|1027|O|232256.36|1998-04-07|5-LOW|Clerk#000000404|0|xpress asymptotes use among the regular, final pinto b +391|1103|F|14517.91|1994-11-17|2-HIGH|Clerk#000000256|0|orges thrash fluffil +416|403|F|106818.50|1993-09-27|5-LOW|Clerk#000000294|0| the accounts. fluffily bold depo +417|547|F|132531.73|1994-02-06|3-MEDIUM|Clerk#000000468|0|ironic, even packages. thinly unusual accounts sleep along the slyly unusual +418|949|P|39431.46|1995-04-13|4-NOT SPECIFIED|Clerk#000000643|0|. furiously ironic instruc +419|1163|O|159079.22|1996-10-01|3-MEDIUM|Clerk#000000376|0|osits. blithely pending theodolites boost carefully +420|902|O|269064.47|1995-10-31|4-NOT SPECIFIED|Clerk#000000756|0|leep carefully final excuses. fluffily pending requests unwind carefully above +421|392|F|1292.21|1992-02-22|5-LOW|Clerk#000000405|0|egular, even packages according to the final, un +422|731|O|155533.71|1997-05-31|4-NOT SPECIFIED|Clerk#000000049|0|aggle carefully across the accounts. regular accounts eat fluffi +423|1034|O|31900.60|1996-06-01|1-URGENT|Clerk#000000674|0|quests. deposits cajole quickly. furiously bold accounts haggle q +448|1498|O|157247.56|1995-08-21|3-MEDIUM|Clerk#000000597|0| regular, express foxes use blithely. quic +449|958|O|55082.33|1995-07-20|2-HIGH|Clerk#000000841|0|. furiously regular theodolites affix blithely +450|475|P|213638.07|1995-03-05|4-NOT SPECIFIED|Clerk#000000293|0|d theodolites. boldly bold foxes since the pack +451|988|O|142756.81|1998-05-25|5-LOW|Clerk#000000048|0|nic pinto beans. theodolites poach carefully; +452|596|O|2072.79|1997-10-14|1-URGENT|Clerk#000000498|0|t, unusual instructions above the blithely bold pint +453|442|O|343004.49|1997-05-26|5-LOW|Clerk#000000504|0|ss foxes. furiously regular ideas sleep according to t +454|488|O|24543.95|1995-12-27|5-LOW|Clerk#000000890|0|dolites sleep carefully blithely regular deposits. quickly regul +455|121|O|190711.32|1996-12-04|1-URGENT|Clerk#000000796|0| about the final platelets. dependen +480|715|F|30644.49|1993-05-08|5-LOW|Clerk#000000004|0|ealthy pinto beans. fluffily regular requests along the special sheaves wake +481|304|F|160370.14|1992-10-08|2-HIGH|Clerk#000000230|0|ly final ideas. packages haggle fluffily +482|1252|O|197194.23|1996-03-26|1-URGENT|Clerk#000000295|0|ts. deposits wake: final acco +483|349|O|66194.38|1995-07-11|2-HIGH|Clerk#000000025|0|cross the carefully final e +484|544|O|331553.32|1997-01-03|3-MEDIUM|Clerk#000000545|0|grouches use. furiously bold accounts maintain. bold, regular deposits +485|1006|O|142389.70|1997-03-26|2-HIGH|Clerk#000000105|0| regular ideas nag thinly furiously s +486|509|O|286150.09|1996-03-11|4-NOT SPECIFIED|Clerk#000000803|0|riously dolphins. fluffily ironic requ +487|1079|F|88805.07|1992-08-18|1-URGENT|Clerk#000000086|0|ithely unusual courts eat accordi +512|631|P|183939.48|1995-05-20|5-LOW|Clerk#000000814|0|ding requests. carefully express theodolites was quickly. furious +513|607|O|78769.71|1995-05-01|2-HIGH|Clerk#000000522|0|regular packages. pinto beans cajole carefully against the even +514|749|O|123202.51|1996-04-04|2-HIGH|Clerk#000000094|0| cajole furiously. slyly final excuses cajole. slyly special instructions +515|1420|F|177231.12|1993-08-29|4-NOT SPECIFIED|Clerk#000000700|0|eposits are furiously furiously silent pinto beans. pending pack +516|440|O|13277.79|1998-04-21|2-HIGH|Clerk#000000305|0|lar, unusual platelets are carefully. even courts sleep bold, final pinto bea +517|94|O|109269.47|1997-04-07|5-LOW|Clerk#000000359|0|slyly pending deposits cajole quickly packages. furiou +518|1444|O|335285.37|1998-02-08|2-HIGH|Clerk#000000768|0| the carefully bold accounts. quickly regular excuses are +519|631|O|109395.60|1997-10-31|1-URGENT|Clerk#000000985|0|ains doze furiously against the f +544|934|F|58960.45|1993-02-17|2-HIGH|Clerk#000000145|0|the special, final accounts. dogged dolphins +545|632|O|35129.54|1995-11-07|2-HIGH|Clerk#000000537|0|as. blithely final hockey players about th +546|1433|O|26227.74|1996-11-01|2-HIGH|Clerk#000000041|0|osits sleep. slyly special dolphins about the q +547|983|O|137852.72|1996-06-22|3-MEDIUM|Clerk#000000976|0|ing accounts eat. carefully regular packa +548|1240|F|139094.89|1994-09-21|1-URGENT|Clerk#000000435|0|arefully express instru +549|1100|F|211787.30|1992-07-13|1-URGENT|Clerk#000000196|0|ideas alongside of +550|236|O|54818.45|1995-08-02|1-URGENT|Clerk#000000204|0|t requests. blithely +551|898|O|64301.40|1995-05-30|1-URGENT|Clerk#000000179|0|xpress accounts boost quic +576|296|O|24722.97|1997-05-13|3-MEDIUM|Clerk#000000955|0|l requests affix regular requests. final account +577|553|F|47860.53|1994-12-19|5-LOW|Clerk#000000154|0| deposits engage stealthil +578|926|O|103543.00|1997-01-10|5-LOW|Clerk#000000281|0|e blithely even packages. slyly pending platelets bes +579|671|O|146610.11|1998-03-11|2-HIGH|Clerk#000000862|0| regular instructions. blithely even p +580|593|O|144557.44|1997-07-05|2-HIGH|Clerk#000000314|0|tegrate fluffily regular accou +581|688|O|175985.28|1997-02-23|4-NOT SPECIFIED|Clerk#000000239|0| requests. even requests use slyly. blithely ironic +582|494|O|181813.20|1997-10-21|1-URGENT|Clerk#000000378|0|n pinto beans print a +583|472|O|154731.76|1997-03-19|3-MEDIUM|Clerk#000000792|0|efully express requests. a +608|260|O|100151.20|1996-02-28|3-MEDIUM|Clerk#000000995|0|nic waters wake slyly slyly expre +609|1252|F|33980.88|1994-06-01|3-MEDIUM|Clerk#000000348|0|- ironic gifts believe furiously ca +610|508|O|229411.94|1995-08-02|1-URGENT|Clerk#000000610|0|totes. ironic, unusual packag +611|1055|F|83388.31|1993-01-27|1-URGENT|Clerk#000000401|0|ounts detect furiously ac +612|815|F|232560.07|1992-10-21|3-MEDIUM|Clerk#000000759|0|boost quickly quickly final excuses. final foxes use bravely afte +613|1384|O|56355.92|1995-06-18|2-HIGH|Clerk#000000172|0|ts hinder among the deposits. fluffily ironic depos +614|1333|F|325942.94|1992-12-01|2-HIGH|Clerk#000000388|0| deposits! even, daring theodol +615|655|F|30990.93|1992-05-09|5-LOW|Clerk#000000388|0|t to promise asymptotes. packages haggle alongside of the fluffil +640|952|F|210229.36|1993-01-23|2-HIGH|Clerk#000000433|0|r, unusual accounts boost carefully final ideas. slyly silent theod +641|1330|F|175084.81|1993-08-30|5-LOW|Clerk#000000175|0|ents cajole furiously about the quickly silent pac +642|400|F|34647.34|1993-12-16|3-MEDIUM|Clerk#000000357|0| among the requests wake slyly alongside of th +643|578|P|261882.19|1995-03-25|2-HIGH|Clerk#000000354|0|g dependencies. regular accounts +644|74|F|267079.41|1992-05-01|1-URGENT|Clerk#000000550|0| blithely unusual platelets haggle ironic, special excuses. excuses unwi +645|1144|F|350110.21|1994-12-03|2-HIGH|Clerk#000000090|0|quickly daring theodolites across the regu +646|505|F|192105.59|1994-11-22|2-HIGH|Clerk#000000203|0|carefully even foxes. fina +647|1430|O|67696.52|1997-08-07|1-URGENT|Clerk#000000270|0|egular pearls. carefully express asymptotes are. even account +672|1081|F|128581.82|1994-04-14|5-LOW|Clerk#000000106|0|egular requests are furiously according to +673|793|F|34950.94|1994-03-10|1-URGENT|Clerk#000000448|0| special pinto beans use quickly furiously even depende +674|332|F|27390.00|1992-08-29|5-LOW|Clerk#000000448|0|ully special deposits. furiously final warhorses affix carefully. fluffily f +675|118|O|166843.13|1997-07-31|2-HIGH|Clerk#000000168|0|ffily between the careful +676|380|O|254171.66|1996-12-13|2-HIGH|Clerk#000000248|0|the final deposits. special, pending +677|1240|F|205917.22|1993-11-24|3-MEDIUM|Clerk#000000824|0|uriously special pinto beans cajole carefully. fi +678|1307|F|208791.37|1993-02-27|5-LOW|Clerk#000000530|0|. blithely final somas about the +679|485|O|14905.06|1995-12-15|2-HIGH|Clerk#000000853|0|tealthy, final pinto beans haggle slyly. pending platelets about the special, +704|844|O|85100.07|1996-11-21|3-MEDIUM|Clerk#000000682|0|blithely pending platelets wake alongside of the final, iron +705|428|O|117587.40|1997-02-13|4-NOT SPECIFIED|Clerk#000000294|0|ithely regular dependencies. express, even packages sleep slyly pending t +706|1474|O|40836.77|1995-09-09|1-URGENT|Clerk#000000448|0|g the packages. deposits caj +707|1162|F|80722.77|1994-11-20|3-MEDIUM|Clerk#000000199|0| ideas about the silent, bold deposits nag dolphins +708|316|O|127925.56|1998-07-03|3-MEDIUM|Clerk#000000101|0|lphins cajole about t +709|361|O|92115.73|1998-04-21|1-URGENT|Clerk#000000461|0|ons alongside of the carefully bold pinto bea +710|1312|F|309878.50|1993-01-02|5-LOW|Clerk#000000026|0| regular, regular requests boost. fluffily re +711|637|F|99553.27|1993-09-23|4-NOT SPECIFIED|Clerk#000000856|0|its. fluffily regular gifts are furi +736|464|O|200720.61|1998-06-21|5-LOW|Clerk#000000881|0|refully of the final pi +737|1198|F|20647.65|1992-04-26|5-LOW|Clerk#000000233|0|ake blithely express, ironic theodolites. blithely special accounts wa +738|208|F|177823.89|1993-03-02|4-NOT SPECIFIED|Clerk#000000669|0|ly even foxes. furiously regular accounts cajole ca +739|4|O|226008.80|1998-05-31|5-LOW|Clerk#000000900|0| against the slyly ironic packages nag slyly ironic +740|436|O|126713.42|1995-07-16|3-MEDIUM|Clerk#000000583|0|courts haggle furiously across the final, regul +741|1045|O|81912.56|1998-07-07|2-HIGH|Clerk#000000295|0|ic instructions. slyly express instructions solv +742|1030|F|258834.44|1994-12-23|5-LOW|Clerk#000000543|0|equests? slyly ironic dolphins boost carefully above the blithely +743|784|O|39284.49|1996-10-04|4-NOT SPECIFIED|Clerk#000000933|0|eans. furiously ironic deposits sleep carefully carefully qui +768|971|O|294534.22|1996-08-20|3-MEDIUM|Clerk#000000411|0|jole slyly ironic packages. slyly even idea +769|800|F|65622.27|1993-06-02|3-MEDIUM|Clerk#000000172|0|ggle furiously. ironic packages haggle slyly. bold platelets affix s +770|320|O|99554.29|1998-05-23|5-LOW|Clerk#000000572|0|heodolites. furiously special pinto beans cajole pac +771|446|O|151561.45|1995-06-17|1-URGENT|Clerk#000000105|0|s. furiously final instructions across the deposit +772|965|F|205442.15|1993-04-17|2-HIGH|Clerk#000000430|0|s boost blithely fluffily idle ideas? fluffily even pin +773|1319|F|190734.21|1993-09-26|3-MEDIUM|Clerk#000000307|0|tions are quickly accounts. accounts use bold, even pinto beans. gifts ag +774|796|O|214484.43|1995-12-04|1-URGENT|Clerk#000000883|0|tealthily even depths +775|1333|F|75392.93|1995-03-18|1-URGENT|Clerk#000000191|0|kly express requests. fluffily silent accounts poach furiously +800|560|O|144932.63|1998-07-14|2-HIGH|Clerk#000000213|0|y alongside of the pending packages? final platelets nag fluffily carefu +801|1178|F|186160.67|1992-02-18|1-URGENT|Clerk#000000186|0|iously from the furiously enticing reques +802|1367|F|192178.48|1995-01-05|1-URGENT|Clerk#000000516|0|posits. ironic, pending requests cajole. even theodol +803|145|O|49471.93|1997-04-29|5-LOW|Clerk#000000260|0|ic instructions. even deposits haggle furiously at the deposits-- regular de +804|500|F|136844.01|1993-03-12|3-MEDIUM|Clerk#000000931|0|s. blithely final foxes are about the packag +805|1261|O|145879.67|1995-07-05|4-NOT SPECIFIED|Clerk#000000856|0|y according to the fluffily +806|1309|O|39072.30|1996-06-20|2-HIGH|Clerk#000000240|0| the ironic packages wake carefully fina +807|1436|F|291066.38|1993-11-24|3-MEDIUM|Clerk#000000012|0|refully special tithes. blithely regular accoun +832|290|F|75549.27|1992-04-19|5-LOW|Clerk#000000495|0|xes. bravely regular packages sleep up the furiously bold accou +833|553|F|53948.73|1994-02-13|3-MEDIUM|Clerk#000000437|0|ts haggle quickly across the slyl +834|428|F|57631.12|1994-05-23|3-MEDIUM|Clerk#000000805|0| sleep. quickly even foxes are boldly. slyly express requests use slyly +835|649|O|79671.35|1995-10-08|4-NOT SPECIFIED|Clerk#000000416|0|s about the carefully special foxes haggle quickly about the +836|688|O|103041.70|1996-11-25|4-NOT SPECIFIED|Clerk#000000729|0|ely bold excuses sleep regular ideas. furiously unusual ideas wake furiou +837|1159|F|99107.47|1994-06-15|4-NOT SPECIFIED|Clerk#000000563|0|kages sleep slyly above the ironic, final orbits +838|164|O|119122.55|1998-01-29|5-LOW|Clerk#000000213|0| slyly around the slyly even +839|280|O|109349.68|1995-08-08|1-URGENT|Clerk#000000951|0|the carefully even platelets. furiously unusual fo +864|1378|O|110290.44|1997-08-17|1-URGENT|Clerk#000000036|0|ly after the slyly regular deposits. express, regular asymptotes nag ca +865|26|F|112126.26|1993-05-04|3-MEDIUM|Clerk#000000337|0|. special packages wake after the carefully final accounts. express pinto be +866|383|F|5793.01|1992-11-28|3-MEDIUM|Clerk#000000718|0|ins after the even, even accounts nod blithel +867|253|F|9271.15|1993-11-16|3-MEDIUM|Clerk#000000877|0|pades nag quickly final, +868|1036|F|157914.01|1992-06-09|4-NOT SPECIFIED|Clerk#000000782|0|onic theodolites print carefully. blithely dogge +869|1348|O|88458.72|1997-01-12|2-HIGH|Clerk#000000245|0|ar sheaves are slowly. slyly even attainments boost theodolites. furiously +870|322|F|60182.94|1993-06-20|4-NOT SPECIFIED|Clerk#000000123|0|blithely ironic ideas nod. sly, r +871|145|O|265450.06|1995-11-15|5-LOW|Clerk#000000882|0|oss the ironic theodolites. +896|17|F|248402.10|1993-03-09|1-URGENT|Clerk#000000187|0|inal packages eat blithely according to the warhorses. furiously quiet de +897|490|P|88281.28|1995-03-20|1-URGENT|Clerk#000000316|0| wake quickly against +898|536|F|159708.26|1993-06-03|2-HIGH|Clerk#000000611|0|. unusual pinto beans haggle quickly across +899|1085|O|165248.53|1998-04-08|5-LOW|Clerk#000000575|0|rts engage carefully final theodolites. +900|460|F|173555.09|1994-10-01|4-NOT SPECIFIED|Clerk#000000060|0| fluffily express deposits nag furiousl +901|113|O|106041.48|1998-07-21|4-NOT SPECIFIED|Clerk#000000929|0|lyly even foxes are furious, silent requests. requests about the quickly +902|86|F|49777.81|1994-07-27|4-NOT SPECIFIED|Clerk#000000811|0|yly final requests over the furiously regula +903|109|O|140726.26|1995-07-07|4-NOT SPECIFIED|Clerk#000000793|0|e slyly about the final pl +928|658|F|315638.02|1995-03-02|5-LOW|Clerk#000000450|0|ithely express pinto beans. +929|827|F|149145.44|1992-10-02|2-HIGH|Clerk#000000160|0|its. furiously even foxes affix carefully finally silent accounts. express req +930|1310|F|285619.42|1994-12-17|1-URGENT|Clerk#000000004|0| accounts nag slyly. ironic, ironic accounts wake blithel +931|1030|F|170066.75|1992-12-07|1-URGENT|Clerk#000000881|0|ss packages haggle furiously express, regular deposits. even, e +932|404|O|57043.21|1997-05-16|2-HIGH|Clerk#000000218|0|ly express instructions boost furiously reg +933|955|F|106503.56|1992-08-05|4-NOT SPECIFIED|Clerk#000000752|0|ial courts wake permanently against the furiously regular ideas. unusual +934|514|O|18262.86|1996-07-03|1-URGENT|Clerk#000000229|0|ts integrate carefully. sly, regular deposits af +935|493|O|131247.01|1997-09-24|5-LOW|Clerk#000000180|0|iously final deposits cajole. blithely even packages +960|347|F|84356.33|1994-09-21|3-MEDIUM|Clerk#000000120|0|regular accounts. requests +961|551|P|248080.06|1995-06-04|4-NOT SPECIFIED|Clerk#000000720|0|ons nag furiously among the quickl +962|353|F|144898.54|1994-05-06|5-LOW|Clerk#000000463|0|ments nag deposits. fluffily ironic a +963|253|F|98613.54|1994-05-26|3-MEDIUM|Clerk#000000497|0|uses haggle carefully. slyly even dependencies after the packages ha +964|752|O|207649.97|1995-05-20|3-MEDIUM|Clerk#000000657|0|print blithely ironic, careful theodolit +965|685|P|44648.62|1995-05-15|5-LOW|Clerk#000000218|0|iously special packages. slyly pending requests are carefully +966|134|O|142557.51|1998-04-30|2-HIGH|Clerk#000000239|0|special deposits. furious +967|1099|F|236000.05|1992-06-21|3-MEDIUM|Clerk#000000167|0|excuses engage quickly bold dep +992|538|O|189842.36|1997-11-11|3-MEDIUM|Clerk#000000875|0|ts. regular pinto beans thrash carefully sl +993|793|O|269632.17|1995-09-10|3-MEDIUM|Clerk#000000894|0|quickly express accounts among the furiously bol +994|13|F|49870.71|1994-04-20|5-LOW|Clerk#000000497|0|ole. slyly bold excuses nag caref +995|1160|P|189854.55|1995-05-31|3-MEDIUM|Clerk#000000439|0|deas. blithely final deposits play. express accounts wake blithely caref +996|710|O|71877.30|1997-12-29|1-URGENT|Clerk#000000497|0|arefully final packages into the slyly final requests affix blit +997|1087|O|39832.61|1997-05-19|2-HIGH|Clerk#000000651|0|ly express depths. furiously final requests haggle furiously. carefu +998|317|F|81009.81|1994-11-26|4-NOT SPECIFIED|Clerk#000000956|0|ronic dolphins. ironic, bold ideas haggle furiously furious +999|602|F|221018.87|1993-09-05|5-LOW|Clerk#000000464|0|pitaphs sleep. regular accounts use. f +1024|35|O|248306.79|1997-12-23|5-LOW|Clerk#000000903|0| blithely. even, express theodolites cajole slyly across +1025|1027|F|112960.50|1995-05-05|2-HIGH|Clerk#000000376|0|ross the slyly final pa +1026|712|O|49485.22|1997-06-04|5-LOW|Clerk#000000223|0|s wake blithely. special acco +1027|1280|F|145806.89|1992-06-03|3-MEDIUM|Clerk#000000241|0|equests cajole. slyly final pinto bean +1028|685|F|190755.43|1994-01-01|2-HIGH|Clerk#000000131|0|ts are. final, silent deposits are among the fl +1029|1288|F|57789.24|1994-06-21|2-HIGH|Clerk#000000700|0|quests sleep. slyly even foxes wake quickly final theodolites. clo +1030|1340|F|26164.34|1994-06-15|5-LOW|Clerk#000000422|0|ully ironic accounts sleep carefully. requests are carefully alongside of the +1031|37|F|203268.37|1994-09-01|3-MEDIUM|Clerk#000000448|0|s; ironic theodolites along the carefully ex +1056|275|F|41838.38|1995-02-11|1-URGENT|Clerk#000000125|0|t, even deposits hang about the slyly special i +1057|760|F|176625.96|1992-02-20|1-URGENT|Clerk#000000124|0|cuses dazzle carefully careful, ironic pinto beans. carefully even theod +1058|530|F|132338.09|1993-04-26|3-MEDIUM|Clerk#000000373|0|kly pending courts haggle. blithely regular sheaves integrate carefully fi +1059|1268|F|291519.65|1994-02-27|1-URGENT|Clerk#000000104|0|en accounts. carefully bold packages cajole daringly special depende +1060|1397|F|155247.64|1993-02-21|3-MEDIUM|Clerk#000000989|0|l platelets sleep quickly slyly special requests. furiously +1061|1027|O|197424.17|1998-05-15|5-LOW|Clerk#000000576|0|uests sleep at the packages. fur +1062|1051|O|48449.37|1997-01-15|1-URGENT|Clerk#000000152|0|eposits use blithely +1063|370|F|76957.40|1994-04-02|2-HIGH|Clerk#000000024|0|deposits nag quickly regular deposits. quickl +1088|1469|F|53063.07|1992-05-21|5-LOW|Clerk#000000347|0|counts are blithely. platelets print. carefully +1089|481|O|140302.14|1996-05-04|4-NOT SPECIFIED|Clerk#000000226|0|ns haggle ruthlessly. even requests are quickly abov +1090|172|O|34290.36|1997-11-15|2-HIGH|Clerk#000000300|0| furiously regular platelets haggle along the slyly unusual foxes! +1091|829|O|48591.79|1996-08-27|1-URGENT|Clerk#000000549|0| even pinto beans haggle quickly alongside of the eve +1092|1232|P|131664.83|1995-03-04|3-MEDIUM|Clerk#000000006|0|re quickly along the blithe +1093|1007|O|124792.59|1997-07-31|4-NOT SPECIFIED|Clerk#000000159|0| after the carefully ironic requests. carefully ironic packages wake fluffil +1094|1438|O|9281.56|1997-12-24|3-MEDIUM|Clerk#000000570|0|beans affix furiously about the pending, even deposits. finally pendi +1095|1433|O|225466.98|1995-08-22|3-MEDIUM|Clerk#000000709|0|sly bold requests cajole carefully according to +1120|1391|O|152580.64|1997-11-07|3-MEDIUM|Clerk#000000319|0|lly special requests. slyly pending platelets are quickly pending requ +1121|281|O|368220.47|1997-01-13|3-MEDIUM|Clerk#000000541|0|r escapades. deposits above the fluffily bold requests hag +1122|1196|O|225660.19|1997-01-10|1-URGENT|Clerk#000000083|0|uffily carefully final theodolites. furiously express packages affix +1123|715|O|115157.87|1996-08-03|3-MEDIUM|Clerk#000000929|0|uriously pending requests. slyly regular instruction +1124|796|O|214762.97|1998-07-30|5-LOW|Clerk#000000326|0|regular pinto beans along the fluffily silent packages +1125|242|F|112869.93|1994-10-27|2-HIGH|Clerk#000000510|0|ithely final requests. i +1126|1433|O|81025.22|1998-01-28|4-NOT SPECIFIED|Clerk#000000928|0|d slyly regular ideas: special ideas believe slyly. slyly ironic sheaves w +1127|575|O|125368.14|1995-09-19|4-NOT SPECIFIED|Clerk#000000397|0|usly silent, regular pinto beans. blithely express requests boos +1152|490|F|78973.34|1994-08-14|4-NOT SPECIFIED|Clerk#000000496|0|equests. deposits ab +1153|1196|O|328207.15|1996-04-18|5-LOW|Clerk#000000059|0| across the pending deposi +1154|352|F|264213.46|1992-02-15|1-URGENT|Clerk#000000268|0|old asymptotes are special requests. blithely even deposits sleep furiously +1155|1498|O|170273.99|1997-10-06|2-HIGH|Clerk#000000164|0|c deposits haggle among the ironic, even requests. carefully ironic sheaves n +1156|1318|O|333319.23|1996-10-19|1-URGENT|Clerk#000000200|0| blithely ironic dolphins. furiously pendi +1157|968|O|136306.85|1998-01-14|4-NOT SPECIFIED|Clerk#000000207|0|out the regular excuses boost carefully against the furio +1158|1414|O|43176.15|1996-06-30|2-HIGH|Clerk#000000549|0|integrate slyly furiously ironic deposit +1159|685|F|68999.67|1992-09-18|3-MEDIUM|Clerk#000000992|0|ts may sleep. requests according to the +1184|886|O|55815.77|1997-10-26|5-LOW|Clerk#000000777|0|iously even packages haggle fluffily care +1185|736|F|68659.75|1992-08-24|5-LOW|Clerk#000000344|0| even escapades are. package +1186|589|O|88428.13|1996-08-15|4-NOT SPECIFIED|Clerk#000000798|0|ingly regular pinto beans: instructi +1187|1337|F|133699.36|1992-11-20|3-MEDIUM|Clerk#000000047|0|s after the furiously final deposits boost slyly under the +1188|199|O|79030.59|1996-04-11|2-HIGH|Clerk#000000256|0|ully ironic deposits. slyl +1189|445|F|90219.24|1994-04-09|1-URGENT|Clerk#000000243|0|f the even accounts. courts print blithely ironic accounts. sile +1190|121|O|54852.43|1997-03-16|5-LOW|Clerk#000000575|0|ccounts above the foxes integrate carefully after the +1191|1103|O|41725.75|1995-11-07|3-MEDIUM|Clerk#000000011|0|uests nag furiously. carefully even requests +1216|1220|F|111175.17|1992-12-07|5-LOW|Clerk#000000918|0|nal foxes around the e +1217|64|F|63714.18|1992-04-26|4-NOT SPECIFIED|Clerk#000000538|0| foxes nag quickly. ironic excuses nod. blithely pending +1218|83|F|157442.11|1994-06-20|4-NOT SPECIFIED|Clerk#000000994|0|s cajole. special, silent deposits about the theo +1219|271|O|11895.23|1995-10-05|3-MEDIUM|Clerk#000000800|0|od carefully. slyly final dependencies across the even fray +1220|485|O|164363.11|1996-08-29|1-URGENT|Clerk#000000712|0|inal theodolites wake. fluffily ironic asymptotes cajol +1221|134|F|164863.12|1992-04-19|4-NOT SPECIFIED|Clerk#000000852|0| detect against the silent, even deposits. carefully ironic +1222|98|F|61432.27|1993-02-05|3-MEDIUM|Clerk#000000811|0|theodolites use quickly even accounts. carefully final asympto +1223|91|O|50645.67|1996-05-25|4-NOT SPECIFIED|Clerk#000000238|0|posits was blithely fr +1248|472|F|295111.15|1992-01-02|1-URGENT|Clerk#000000890|0|t the carefully regular dugouts. s +1249|1498|F|70939.22|1994-01-05|1-URGENT|Clerk#000000095|0|al ideas sleep above the pending pin +1250|359|F|13036.54|1992-09-29|4-NOT SPECIFIED|Clerk#000000652|0|ts after the fluffily pending instructions use slyly about the s +1251|379|O|168646.06|1997-10-30|1-URGENT|Clerk#000000276|0|, brave sauternes. deposits boost fluffily. +1252|1499|O|135540.70|1997-08-04|5-LOW|Clerk#000000348|0|ng the slyly regular excuses. special courts nag furiously blithely e +1253|1145|F|135358.41|1993-01-26|1-URGENT|Clerk#000000775|0| requests sleep furiously even foxes. ruthless packag +1254|698|O|143889.73|1995-12-22|1-URGENT|Clerk#000000607|0| pinto beans. carefully regular request +1255|1217|F|104935.74|1994-05-30|4-NOT SPECIFIED|Clerk#000000798|0|ct slyly regular accounts. quick +1280|956|F|137579.92|1993-01-11|5-LOW|Clerk#000000160|0|posits thrash quickly after the theodolites. furiously iro +1281|611|F|226132.40|1994-12-11|1-URGENT|Clerk#000000430|0|counts. carefully pending accounts eat +1282|1160|F|85558.32|1992-02-29|4-NOT SPECIFIED|Clerk#000000168|0|he quickly special packages. furiously final re +1283|1165|O|296055.80|1996-08-30|4-NOT SPECIFIED|Clerk#000000260|0| pinto beans boost slyly ac +1284|1340|O|147647.95|1996-01-07|2-HIGH|Clerk#000000492|0|s. blithely silent deposits s +1285|104|F|209656.04|1992-06-01|1-URGENT|Clerk#000000423|0|cial deposits cajole after the ironic requests. p +1286|1087|F|308115.46|1993-05-14|4-NOT SPECIFIED|Clerk#000000939|0| deposits use carefully from the excuses. slyly bold p +1287|173|F|181586.61|1994-07-05|2-HIGH|Clerk#000000288|0|ly ironic dolphins integrate furiously among the final packages. st +1312|1111|F|81611.04|1994-05-19|3-MEDIUM|Clerk#000000538|0|n, express accounts across the ironic +1313|1477|F|69234.03|1994-09-13|1-URGENT|Clerk#000000774|0|ld accounts. regular deposits cajole. ironically pending theodolites use car +1314|1424|F|63623.22|1994-05-13|3-MEDIUM|Clerk#000000485|0|ickly blithe packages nod ideas. furiously bold braids boost around the car +1315|215|O|182956.83|1998-03-22|5-LOW|Clerk#000000840|0|final theodolites alongside of the carefu +1316|160|F|232915.54|1993-12-03|1-URGENT|Clerk#000000857|0|ully bold theodolites? pending, bold pin +1317|991|P|170654.55|1995-05-19|2-HIGH|Clerk#000000373|0|sts. furiously special deposits lose fur +1318|1279|O|98170.50|1998-06-27|3-MEDIUM|Clerk#000000581|0|s hang bold requests. pending, re +1319|313|O|46533.50|1996-09-27|2-HIGH|Clerk#000000257|0|y across the ruthlessly ironic accounts. unusu +1344|170|F|66338.64|1992-04-16|5-LOW|Clerk#000000178|0|omise close, silent requests. pending theodolites boost pending +1345|943|F|165361.31|1992-10-28|5-LOW|Clerk#000000447|0| regular tithes. quickly fluffy de +1346|748|F|224106.48|1992-06-18|2-HIGH|Clerk#000000374|0|ges sleep quickly-- even pint +1347|403|O|249530.87|1997-06-20|5-LOW|Clerk#000000977|0|he furiously even foxes use carefully express req +1348|175|O|145456.56|1998-04-18|5-LOW|Clerk#000000206|0|tly. quickly even deposi +1349|637|O|49656.84|1997-10-26|1-URGENT|Clerk#000000543|0|yly! blithely special theodolites cajole. unusual, reg +1350|508|F|71653.64|1993-08-24|1-URGENT|Clerk#000000635|0|iously about the blithely special a +1351|1060|O|23806.26|1998-04-20|1-URGENT|Clerk#000000012|0| cajole. regular, special re +1376|461|O|35617.06|1997-05-04|4-NOT SPECIFIED|Clerk#000000730|0|der furiously final, final frets. carefull +1377|199|O|145303.74|1998-04-24|4-NOT SPECIFIED|Clerk#000000625|0|lly across the blithely express accounts. ironic excuses promise carefully de +1378|196|O|184205.63|1996-03-09|4-NOT SPECIFIED|Clerk#000000705|0| furiously even tithes cajole slyly among the quick +1379|643|O|98253.79|1998-05-25|5-LOW|Clerk#000000861|0|y deposits are caref +1380|1363|O|136526.77|1996-07-07|3-MEDIUM|Clerk#000000969|0|inal deposits wake slyly daringly even requests. bold, even foxe +1381|1264|O|74771.86|1998-05-25|3-MEDIUM|Clerk#000000107|0|even requests breach after the bold, ironic instructions. slyly even +1382|1324|F|246263.02|1993-08-17|5-LOW|Clerk#000000241|0|fully final packages sl +1383|1196|F|53197.34|1993-04-27|2-HIGH|Clerk#000000785|0|ts. express requests sleep blithel +1408|539|O|255424.00|1997-12-26|4-NOT SPECIFIED|Clerk#000000942|0|t the quickly final asymptotes. unusual +1409|1429|F|119571.58|1992-12-31|4-NOT SPECIFIED|Clerk#000000065|0|ructions. furiously unusual excuses are regular, unusual theodolites. fin +1410|1123|O|153160.36|1997-04-12|5-LOW|Clerk#000000123|0|iously along the bravely regular dolphins. pinto beans cajole furiously sp +1411|946|F|222485.73|1994-12-21|2-HIGH|Clerk#000000566|0|s. furiously special excuses across the pending pinto beans haggle sp +1412|529|F|114697.28|1993-03-13|4-NOT SPECIFIED|Clerk#000000083|0|uffily daring theodolit +1413|907|O|111589.54|1997-06-14|3-MEDIUM|Clerk#000000342|0|, ironic instructions. carefully even packages dazzle +1414|763|O|50012.42|1995-08-16|1-URGENT|Clerk#000000883|0|ccounts. ironic foxes haggle car +1415|787|F|32535.28|1994-05-29|4-NOT SPECIFIED|Clerk#000000601|0|rays. blithely final ideas affix quickl +1440|979|O|53447.02|1995-08-10|5-LOW|Clerk#000000956|0| pending requests. closely s +1441|1219|O|243310.98|1997-03-06|4-NOT SPECIFIED|Clerk#000000156|0|ter the excuses. ironic dependencies m +1442|1106|F|8836.99|1994-07-05|4-NOT SPECIFIED|Clerk#000000935|0|nal pinto beans. slyly ironic ideas cajol +1443|439|O|59178.01|1996-12-16|5-LOW|Clerk#000000185|0|x blithely against the carefully final somas. even asymptotes are. quickly spe +1444|1333|F|290512.20|1994-12-06|3-MEDIUM|Clerk#000000783|0|ove the bold accounts cajole fluffily about +1445|1136|F|235888.22|1995-01-10|3-MEDIUM|Clerk#000000211|0|even packages wake fluffily +1446|401|O|46093.69|1998-02-16|5-LOW|Clerk#000000274|0|lly regular notornis above the requests sleep final accounts! +1447|901|F|158371.04|1992-10-15|2-HIGH|Clerk#000000880|0|inly against the blithely pending excuses. regular, pe +1472|1499|O|72730.13|1996-10-06|5-LOW|Clerk#000000303|0|y special dolphins around the final dependencies wake quick +1473|923|O|125427.75|1997-03-17|3-MEDIUM|Clerk#000000960|0|furiously close accoun +1474|691|F|69600.97|1995-01-09|1-URGENT|Clerk#000000438|0|detect quickly above the carefully even +1475|49|O|252931.74|1997-11-12|2-HIGH|Clerk#000000972|0|cally final packages boost. blithely ironic packa +1476|1447|O|24352.78|1996-06-27|2-HIGH|Clerk#000000673|0|ding accounts hinder alongside of the quickly pending requests. fluf +1477|755|O|288752.23|1997-08-24|5-LOW|Clerk#000000612|0|ly bold foxes. final ideas would cajo +1478|499|O|27542.96|1997-08-03|2-HIGH|Clerk#000000827|0|lessly. carefully express +1479|146|O|41710.22|1995-12-16|4-NOT SPECIFIED|Clerk#000000697|0|he furiously even foxes. thinly bold deposits +1504|19|F|125349.58|1992-08-28|3-MEDIUM|Clerk#000000381|0|, brave deposits. bold de +1505|352|F|61594.91|1992-08-21|2-HIGH|Clerk#000000544|0|s. slyly ironic packages cajole. carefully regular packages haggle +1506|1462|F|263170.47|1992-09-21|3-MEDIUM|Clerk#000000620|0| dependencies. accounts affix blithely slowly unusual deposits. slyly regular +1507|1205|F|155226.23|1993-10-14|3-MEDIUM|Clerk#000000305|0|stealthy, ironic de +1508|1013|O|207727.99|1998-04-10|5-LOW|Clerk#000000117|0| after the furiously regular pinto beans hang slyly quickly ironi +1509|625|F|252994.90|1993-07-08|5-LOW|Clerk#000000770|0|the regular ideas. regul +1510|523|O|235151.19|1996-09-17|5-LOW|Clerk#000000128|0|ld carefully. furiously final asymptotes haggle furiously +1511|785|O|103042.07|1996-12-22|4-NOT SPECIFIED|Clerk#000000386|0|ts above the depend +1536|932|O|8717.58|1997-01-26|3-MEDIUM|Clerk#000000117|0|ges are! furiously final deposits cajole iron +1537|1076|F|144582.24|1992-02-15|4-NOT SPECIFIED|Clerk#000000862|0|g to the even deposits. ironic, final packages +1538|290|O|214050.85|1995-06-18|4-NOT SPECIFIED|Clerk#000000258|0| instructions. regular theod +1539|1118|F|67801.22|1995-03-10|5-LOW|Clerk#000000840|0|nstructions boost pa +1540|142|F|191775.25|1992-08-05|2-HIGH|Clerk#000000927|0|r ideas hinder blithe +1541|940|P|72808.67|1995-05-18|1-URGENT|Clerk#000000906|0|y. slyly ironic warhorses around the furiously regul +1542|1427|F|177573.43|1993-09-15|3-MEDIUM|Clerk#000000435|0|t the furiously close deposits do was f +1543|503|O|221716.54|1997-02-20|1-URGENT|Clerk#000000398|0|unts. furiously pend +1568|167|O|108945.79|1997-01-30|4-NOT SPECIFIED|Clerk#000000554|0|d notornis. carefully +1569|1036|O|133309.13|1998-04-02|5-LOW|Clerk#000000786|0|orbits. fluffily even decoys serve blithely. furiously furious realms nag acro +1570|1223|O|58046.02|1998-03-16|1-URGENT|Clerk#000000745|0|pinto beans haggle furiousl +1571|1027|F|194190.45|1992-12-05|2-HIGH|Clerk#000000565|0|ously furiously bold warthogs. slyly ironic instructions are quickly a +1572|104|O|64264.28|1996-02-24|2-HIGH|Clerk#000000994|0|fluffily ironic accounts haggle blithely final platelets! slyly regular foxes +1573|1480|F|127138.20|1992-12-28|2-HIGH|Clerk#000000940|0|ess, ironic deposits use along the carefu +1574|1334|O|255009.95|1996-12-12|3-MEDIUM|Clerk#000000809|0| ideas hinder after the carefully unusual +1575|1447|O|238537.34|1995-09-13|3-MEDIUM|Clerk#000000497|0|. furiously regular dep +1600|926|F|188076.26|1993-03-03|3-MEDIUM|Clerk#000000627|0|tions cajole quietly above the regular, silent requests. slyly fin +1601|524|F|116922.47|1994-08-27|5-LOW|Clerk#000000469|0|ent deposits are ca +1602|10|F|6751.57|1993-08-05|5-LOW|Clerk#000000660|0|deposits. busily silent instructions haggle furiously. fin +1603|13|F|46920.46|1993-07-31|4-NOT SPECIFIED|Clerk#000000869|0|s. slyly silent deposits boo +1604|1123|F|135098.39|1993-07-17|5-LOW|Clerk#000000512|0|lithely silent waters. blithely unusual packages alongside +1605|577|O|190137.68|1998-04-24|4-NOT SPECIFIED|Clerk#000000616|0|sleep furiously? ruthless, even pinto beans +1606|530|O|184091.64|1997-04-17|4-NOT SPECIFIED|Clerk#000000550|0|r requests. quickly even platelets breach before the ironically +1607|1493|O|228124.53|1995-12-16|2-HIGH|Clerk#000000498|0| bold, pending foxes haggle. slyly silent +1632|659|O|272854.60|1997-01-08|3-MEDIUM|Clerk#000000351|0|onic requests are accounts. bold a +1633|143|O|74276.27|1995-10-14|2-HIGH|Clerk#000000666|0|y silent accounts sl +1634|689|O|202866.17|1996-09-10|1-URGENT|Clerk#000000360|0|arefully blithely ironic requests. slyly unusual instructions alongside +1635|38|O|107289.95|1997-02-13|3-MEDIUM|Clerk#000000958|0|s. slyly ironic requests affix slyly +1636|787|O|232036.04|1997-06-17|3-MEDIUM|Clerk#000000457|0|ding requests. slyly ironic courts wake quickl +1637|728|F|264917.81|1995-02-08|4-NOT SPECIFIED|Clerk#000000189|0| final accounts. blithely silent ideas cajole bravely. carefully express +1638|1390|O|222330.55|1997-08-13|2-HIGH|Clerk#000000643|0|he fluffily regular asymp +1639|44|O|155953.46|1995-08-20|4-NOT SPECIFIED|Clerk#000000939|0|haggle furiously. final requests detect furious +1664|640|O|229693.92|1996-03-03|1-URGENT|Clerk#000000090|0|y quickly even asymptotes. furiously regular packages haggle quickly fin +1665|757|F|7215.86|1994-05-08|2-HIGH|Clerk#000000920|0|ly regular packages are fluffily even ideas. fluffily final +1666|941|O|187461.04|1995-10-18|1-URGENT|Clerk#000000849|0|ffily pending dependencies wake fluffily. pending, final accounts +1667|46|O|193695.84|1997-10-10|2-HIGH|Clerk#000000103|0|e accounts. slyly express accounts must are a +1668|1415|O|178694.86|1997-07-12|4-NOT SPECIFIED|Clerk#000000148|0|eodolites. carefully dogged dolphins haggle q +1669|19|O|41922.71|1997-06-09|3-MEDIUM|Clerk#000000663|0|er ironic requests detect furiously blithely sp +1670|245|O|129082.05|1997-05-24|2-HIGH|Clerk#000000320|0|unusual dependencies. furiously special platelets main +1671|343|O|155157.94|1996-07-27|4-NOT SPECIFIED|Clerk#000000275|0|ly. slyly pending requests was above the +1696|35|O|159110.93|1998-01-08|4-NOT SPECIFIED|Clerk#000000041|0|bravely bold accounts above the quickly bold +1697|758|O|173054.70|1996-10-07|1-URGENT|Clerk#000000815|0|o x-ray blithely. pl +1698|395|O|212919.29|1997-04-23|2-HIGH|Clerk#000000432|0|slyly. carefully express deposit +1699|835|F|87704.83|1993-12-30|1-URGENT|Clerk#000000125|0|jole blithely. furiously un +1700|649|O|118049.58|1996-06-15|3-MEDIUM|Clerk#000000328|0|ely final dolphins wake sometimes above the quietly regular deposits. fur +1701|1285|F|97290.23|1992-05-19|2-HIGH|Clerk#000000395|0|furiously. regular, close theodoli +1702|655|P|313394.52|1995-05-07|2-HIGH|Clerk#000000300|0|around the carefully final deposits cajole carefully according to the b +1703|1334|F|151075.27|1993-01-28|3-MEDIUM|Clerk#000000463|0| pinto beans poach. bold courts boost. regular, express deposits at +1728|631|O|181415.94|1996-05-22|2-HIGH|Clerk#000000711|0|beans. slyly regular instructions sleep! slyly final packages +1729|1312|F|16895.97|1992-05-19|2-HIGH|Clerk#000000158|0|pending foxes wake. accounts +1730|1234|O|196574.65|1998-07-24|5-LOW|Clerk#000000794|0| fluffily pending deposits serve. furiously even requests wake furiou +1731|1279|O|274023.72|1996-01-06|1-URGENT|Clerk#000000268|0|lithely regular, final instructions. ironic, express packages are above +1732|1459|F|261007.93|1993-11-29|5-LOW|Clerk#000000903|0|inal requests integrate dolph +1733|1475|O|195828.98|1996-05-12|2-HIGH|Clerk#000000789|0|e carefully according to the accounts. furiously pending instructions sleep +1734|64|F|59250.30|1994-06-11|2-HIGH|Clerk#000000722|0| final ideas haggle. blithely quick foxes sleep busily bold ideas. i +1735|206|F|128698.48|1992-12-27|1-URGENT|Clerk#000000458|0|ully idle requests wake qu +1760|1142|O|122830.52|1996-05-17|5-LOW|Clerk#000000917|0| deposits. busily regular deposits wake blithely along the furiously even re +1761|1049|F|310359.22|1993-12-24|2-HIGH|Clerk#000000817|0|efully slyly bold frets. packages boost b +1762|767|F|293674.75|1994-08-20|4-NOT SPECIFIED|Clerk#000000653|0|ly ironic packages. furi +1763|1205|O|194261.80|1996-10-29|2-HIGH|Clerk#000000321|0|es. bold dependencies haggle furiously along +1764|283|F|68855.70|1992-03-25|1-URGENT|Clerk#000000182|0|. slyly final packages integrate carefully acro +1765|727|O|51928.97|1995-12-03|4-NOT SPECIFIED|Clerk#000000490|0| regular excuses wake slyly +1766|1385|O|67803.59|1996-10-12|2-HIGH|Clerk#000000983|0|unusual deposits affix quickly beyond the carefully s +1767|247|P|184646.16|1995-03-14|2-HIGH|Clerk#000000327|0|eposits use carefully carefully regular platelets. quickly regular packages al +1792|472|F|175299.11|1993-11-09|5-LOW|Clerk#000000102|0|ructions haggle along the pending packages. carefully speci +1793|178|F|106527.58|1992-07-12|4-NOT SPECIFIED|Clerk#000000291|0|regular packages cajole. blithely special packages according to the final d +1794|1396|O|259572.58|1997-09-28|1-URGENT|Clerk#000000686|0|ally silent pinto beans. regular package +1795|928|F|178189.68|1994-03-19|2-HIGH|Clerk#000000815|0| quickly final packages! blithely dogged accounts c +1796|463|F|41893.26|1992-11-21|2-HIGH|Clerk#000000245|0|eans use furiously around th +1797|1243|O|63183.36|1996-05-07|3-MEDIUM|Clerk#000000508|0|quiet platelets haggle since the quickly ironic instructi +1798|517|O|45519.51|1997-07-28|1-URGENT|Clerk#000000741|0|al foxes are blithe +1799|601|F|60595.26|1994-03-07|4-NOT SPECIFIED|Clerk#000000339|0|ns sleep furiously final waters. blithely regular instructions h +1824|482|F|107580.47|1994-05-05|1-URGENT|Clerk#000000972|0|e blithely fluffily +1825|1465|F|203057.19|1993-12-05|3-MEDIUM|Clerk#000000345|0|ironic, final accou +1826|814|F|150931.79|1992-04-16|4-NOT SPECIFIED|Clerk#000000718|0|the even asymptotes dazzle fluffily slyly regular asymptotes. final, unu +1827|1051|O|320537.08|1996-06-22|4-NOT SPECIFIED|Clerk#000000369|0|luffily even requests haggle sly +1828|314|F|193253.78|1994-04-18|3-MEDIUM|Clerk#000000840|0|y quickly bold packag +1829|1114|F|138691.03|1994-05-08|2-HIGH|Clerk#000000537|0| accounts wake above the furiously unusual requests. pending package +1830|1315|F|116412.14|1995-02-23|1-URGENT|Clerk#000000045|0|according to the even, +1831|706|F|83108.48|1993-12-02|1-URGENT|Clerk#000000854|0| accounts. carefully even accounts boost furiously. regular ideas engage. +1856|1045|F|267665.56|1992-03-20|4-NOT SPECIFIED|Clerk#000000952|0|. special pinto beans run acr +1857|1321|F|165861.54|1993-01-13|2-HIGH|Clerk#000000083|0|hely final ideas slee +1858|1423|O|34660.99|1997-12-13|1-URGENT|Clerk#000000389|0|thely. slyly final deposits sleep +1859|598|O|162087.77|1997-04-11|4-NOT SPECIFIED|Clerk#000000949|0| the foxes. bravely special excuses nag carefully special r +1860|97|O|9265.31|1996-04-04|3-MEDIUM|Clerk#000000556|0|osits. quickly bold deposits according to +1861|685|F|113123.65|1994-01-03|3-MEDIUM|Clerk#000000847|0|r the fluffily close sauternes. furio +1862|325|O|123620.54|1998-02-24|5-LOW|Clerk#000000348|0|ts snooze ironically abou +1863|731|F|142539.37|1993-09-23|4-NOT SPECIFIED|Clerk#000000658|0|old sentiments. careful, +1888|1192|F|360144.81|1993-10-31|4-NOT SPECIFIED|Clerk#000000659|0|olites. pinto beans cajole. regular deposits affix. slyly regular +1889|244|O|128067.39|1997-03-16|1-URGENT|Clerk#000000854|0|p around the regular notornis. unusual deposits +1890|95|O|297716.58|1996-12-18|4-NOT SPECIFIED|Clerk#000000627|0|romise final, regular deposits. regular fox +1891|610|F|128912.17|1994-12-15|5-LOW|Clerk#000000495|0|unusual foxes sleep regular deposits. requests wake special pac +1892|235|F|165541.41|1994-03-26|5-LOW|Clerk#000000733|0|sts. slyly regular dependencies use slyly. ironic, spec +1893|1244|O|169481.16|1997-10-30|2-HIGH|Clerk#000000111|0|olites. silent, special deposits eat slyly quickly express packages; hockey p +1894|751|F|65789.57|1992-03-30|1-URGENT|Clerk#000000626|0|e furiously. furiously even accounts are slyly final accounts. closely speci +1895|67|F|62954.37|1994-05-30|3-MEDIUM|Clerk#000000878|0|ress accounts. bold accounts cajole. slyly final pinto beans poach regul +1920|1096|O|195949.19|1998-06-24|5-LOW|Clerk#000000018|0|hely; furiously regular excuses +1921|862|F|82692.09|1994-01-18|3-MEDIUM|Clerk#000000293|0|counts. slyly quiet requests along the ruthlessly regular accounts are +1922|556|O|12696.20|1996-07-13|3-MEDIUM|Clerk#000000984|0|side of the blithely final re +1923|1345|O|262475.36|1997-07-07|1-URGENT|Clerk#000000471|0| express dolphins. +1924|748|O|235357.72|1996-09-07|4-NOT SPECIFIED|Clerk#000000823|0| of the ironic accounts. instructions near the final instr +1925|167|F|192587.39|1992-03-05|1-URGENT|Clerk#000000986|0|e slyly regular deposits. furiously +1926|931|O|132894.56|1996-01-31|2-HIGH|Clerk#000000568|0|cajole. even warhorses sleep carefully. +1927|1399|O|38474.28|1995-09-30|3-MEDIUM|Clerk#000000616|0|riously special packages. permanent pearls wake furiously. even packages alo +1952|662|F|17837.86|1994-03-16|2-HIGH|Clerk#000000254|0| silent accounts boost +1953|1495|F|65277.06|1993-11-30|3-MEDIUM|Clerk#000000891|0| fluffily along the quickly even packages. +1954|559|O|244793.78|1997-05-31|4-NOT SPECIFIED|Clerk#000000104|0| unusual excuses cajole according to the blithely regular theodolites. +1955|121|F|132951.01|1992-04-20|1-URGENT|Clerk#000000792|0|ly special ideas. sometimes final +1956|1258|F|109978.44|1992-09-20|4-NOT SPECIFIED|Clerk#000000600|0|ironic ideas are silent ideas. furiously final deposits sleep slyly carefu +1957|302|O|113050.82|1998-07-21|2-HIGH|Clerk#000000639|0|nding excuses about the +1958|523|O|240252.23|1995-09-22|5-LOW|Clerk#000000343|0| haggle blithely. flu +1959|424|O|86342.43|1997-01-13|4-NOT SPECIFIED|Clerk#000000631|0| cajole about the blithely express requests. even excuses mold bl +1984|508|O|123878.05|1998-04-01|1-URGENT|Clerk#000000416|0| slyly special instructions. unusual foxes use packages. carefully regular req +1985|59|F|220942.19|1994-09-02|4-NOT SPECIFIED|Clerk#000000741|0|slyly slyly even pains. slyly reg +1986|1486|F|51251.50|1994-05-05|2-HIGH|Clerk#000000609|0|across the theodolites. quick +1987|982|F|7351.41|1994-04-30|2-HIGH|Clerk#000000652|0|gular platelets alongside +1988|1075|O|189572.71|1995-10-06|4-NOT SPECIFIED|Clerk#000000011|0|ly ironic dolphins serve quickly busy accounts. bu +1989|1162|F|43106.73|1994-03-16|4-NOT SPECIFIED|Clerk#000000747|0|ely bold pinto beans ha +1990|1181|F|44391.50|1994-12-16|2-HIGH|Clerk#000000114|0|e bold patterns. always regul +1991|187|F|191273.88|1992-09-07|4-NOT SPECIFIED|Clerk#000000854|0|ing accounts can haggle at the carefully final Tiresias-- pending, regular +2016|76|O|34243.46|1996-08-16|3-MEDIUM|Clerk#000000641|0|the carefully ironic foxes. requests nag bold, r +2017|1006|O|83524.96|1998-05-13|3-MEDIUM|Clerk#000000427|0|nusual requests. blit +2018|176|P|29982.40|1995-04-05|4-NOT SPECIFIED|Clerk#000000920|0|gular accounts wake fur +2019|1342|F|52971.22|1992-10-23|1-URGENT|Clerk#000000565|0| furiously bold packages. fluffily fi +2020|725|F|190262.97|1993-06-21|3-MEDIUM|Clerk#000000192|0|es. furiously regular packages above the furiously special theodolites are a +2021|700|O|41487.67|1995-07-15|1-URGENT|Clerk#000000155|0|ong the furiously regular requests. unusual deposits wake fluffily inside +2022|619|F|319320.43|1992-03-15|1-URGENT|Clerk#000000268|0| dependencies sleep fluffily even, ironic deposits. express, silen +2023|1180|F|181994.65|1992-05-06|5-LOW|Clerk#000000137|0|ular courts engage according to the +2048|169|F|43446.23|1993-11-15|1-URGENT|Clerk#000000934|0|s cajole after the blithely final accounts. f +2049|298|O|206620.70|1995-12-07|2-HIGH|Clerk#000000859|0|ly regular requests thrash blithely about the fluffily even theodolites. r +2050|274|F|289457.13|1994-06-02|4-NOT SPECIFIED|Clerk#000000821|0|d accounts against the furiously regular packages use bli +2051|382|O|104971.81|1996-03-18|4-NOT SPECIFIED|Clerk#000000333|0|ctions sleep blithely. blithely regu +2052|895|F|223352.03|1992-04-13|2-HIGH|Clerk#000000767|0| requests sleep around the even, even courts. ironic theodolites affix furious +2053|1406|F|162584.35|1995-02-07|1-URGENT|Clerk#000000717|0|ar requests: blithely sly accounts boost carefully across t +2054|401|F|162781.21|1992-06-08|4-NOT SPECIFIED|Clerk#000000103|0|l requests affix carefully about the furiously special +2055|970|F|70155.57|1993-09-04|1-URGENT|Clerk#000000067|0|. warhorses affix slyly blithely express instructions? fur +2080|946|F|75292.75|1993-06-18|5-LOW|Clerk#000000190|0|ironic, pending theodolites are carefully about the quickly regular theodolite +2081|1193|O|202626.98|1997-07-05|2-HIGH|Clerk#000000136|0|ong the regular theo +2082|487|F|70224.72|1995-01-10|2-HIGH|Clerk#000000354|0|cial accounts. ironic, express dolphins nod slyly sometimes final reques +2083|1009|F|39235.65|1993-07-14|3-MEDIUM|Clerk#000000361|0|al patterns. bold, final foxes nag bravely about the furiously express +2084|800|F|277607.01|1993-03-17|2-HIGH|Clerk#000000048|0|zle furiously final, careful packages. slyly ironic ideas amo +2085|488|F|62710.56|1993-11-21|3-MEDIUM|Clerk#000000818|0|ress, express ideas haggle +2086|1405|F|259355.86|1994-10-19|1-URGENT|Clerk#000000046|0| permanently regular +2087|493|O|79220.54|1998-01-31|2-HIGH|Clerk#000000626|0|e always regular packages nod against the furiously spec +2112|634|O|29666.67|1997-02-05|2-HIGH|Clerk#000000351|0|against the slyly even id +2113|319|O|70044.40|1997-11-08|2-HIGH|Clerk#000000527|0|slyly regular instruct +2114|787|F|159876.50|1995-01-16|5-LOW|Clerk#000000751|0|r, unusual accounts haggle across the busy platelets. carefully +2115|1042|O|213137.77|1998-05-23|4-NOT SPECIFIED|Clerk#000000101|0|odolites boost. carefully regular excuses cajole. quickly ironic pinto be +2116|223|F|79971.53|1994-08-26|1-URGENT|Clerk#000000197|0|efully after the asymptotes. furiously sp +2117|220|O|215355.06|1997-04-26|2-HIGH|Clerk#000000887|0|ely even dependencies. regular foxes use blithely. +2118|1333|O|54388.61|1996-10-09|1-URGENT|Clerk#000000196|0|ial requests wake carefully special packages. f +2119|622|O|31760.98|1996-08-20|2-HIGH|Clerk#000000434|0|uickly pending escapades. fluffily ir +2144|1348|F|176382.12|1994-03-29|3-MEDIUM|Clerk#000000546|0|t. carefully quick requests across the deposits wake regu +2145|1336|F|30239.30|1992-10-03|1-URGENT|Clerk#000000886|0|sts would snooze blithely alongside of th +2146|1177|F|254476.65|1992-09-14|4-NOT SPECIFIED|Clerk#000000476|0|ven packages. dependencies wake slyl +2147|988|F|117795.98|1992-09-06|4-NOT SPECIFIED|Clerk#000000424|0| haggle carefully furiously final foxes. pending escapades thrash. bold theod +2148|1283|F|20481.54|1995-04-19|4-NOT SPECIFIED|Clerk#000000517|0|ross the furiously unusual theodolites. always expre +2149|1007|F|151151.22|1993-03-13|5-LOW|Clerk#000000555|0|nusual accounts nag furiously special reques +2150|817|F|230677.37|1994-06-03|3-MEDIUM|Clerk#000000154|0|ect slyly against the even, final packages. quickly regular pinto beans wake c +2151|580|O|166259.86|1996-11-11|3-MEDIUM|Clerk#000000996|0|c requests. ironic platelets cajole across the quickly fluffy deposits. +2176|1036|F|140007.98|1992-11-10|1-URGENT|Clerk#000000195|0|s haggle regularly accor +2177|1351|O|254199.26|1997-01-20|3-MEDIUM|Clerk#000000161|0|ove the blithely unusual packages cajole carefully fluffily special request +2178|80|O|92942.00|1996-12-12|3-MEDIUM|Clerk#000000656|0|thely according to the instructions. furious +2179|410|O|86553.77|1996-09-07|2-HIGH|Clerk#000000935|0|ounts alongside of the furiously unusual braids cajol +2180|751|O|287379.99|1996-09-14|4-NOT SPECIFIED|Clerk#000000650|0|xpress, unusual pains. furiously ironic excu +2181|742|O|174000.86|1995-09-13|3-MEDIUM|Clerk#000000814|0|y against the ironic, even +2182|226|F|174578.47|1994-04-05|2-HIGH|Clerk#000000071|0|ccounts. quickly bold deposits across the excuses sl +2183|1121|O|78568.93|1996-06-22|1-URGENT|Clerk#000000287|0| among the express, ironic packages. slyly ironic platelets integrat +2208|676|P|346978.53|1995-05-01|4-NOT SPECIFIED|Clerk#000000900|0|symptotes wake slyly blithely unusual packages. +2209|892|F|173318.78|1992-07-10|2-HIGH|Clerk#000000056|0|er above the slyly silent requests. furiously reg +2210|319|F|54392.14|1992-01-16|2-HIGH|Clerk#000000941|0| believe carefully quickly express pinto beans. deposi +2211|920|F|204877.13|1994-06-30|2-HIGH|Clerk#000000464|0|ffily bold courts e +2212|1163|F|28563.15|1994-03-23|3-MEDIUM|Clerk#000000954|0|structions above the unusual requests use fur +2213|1213|F|204541.38|1993-01-15|4-NOT SPECIFIED|Clerk#000000598|0|osits are carefully reg +2214|1141|O|224136.38|1998-05-05|3-MEDIUM|Clerk#000000253|0|packages. fluffily even accounts haggle blithely. carefully ironic depen +2215|388|O|159169.89|1996-06-16|4-NOT SPECIFIED|Clerk#000000817|0|le final, final foxes. quickly regular gifts are carefully deposit +2240|554|F|265020.95|1992-03-06|4-NOT SPECIFIED|Clerk#000000622|0|accounts against the slyly express foxes are after the slyly regular +2241|1013|F|248564.48|1993-05-11|1-URGENT|Clerk#000000081|0|y about the silent excuses. furiously ironic instructions along the sil +2242|815|O|16543.76|1997-07-20|4-NOT SPECIFIED|Clerk#000000360|0| pending multipliers. carefully express asymptotes use quickl +2243|479|O|11918.84|1995-06-10|2-HIGH|Clerk#000000813|0|ously regular deposits integrate s +2244|1268|F|34877.52|1993-01-09|1-URGENT|Clerk#000001000|0|ckages. ironic, ironic accounts haggle blithely express excuses. +2245|565|F|257990.42|1993-04-28|3-MEDIUM|Clerk#000000528|0|ake carefully. braids haggle slyly quickly b +2246|1124|O|100351.39|1996-05-27|4-NOT SPECIFIED|Clerk#000000739|0| final gifts sleep +2247|947|F|20406.41|1992-08-02|4-NOT SPECIFIED|Clerk#000000947|0|furiously regular packages. final brai +2272|1384|F|186159.70|1993-04-13|2-HIGH|Clerk#000000449|0|s. bold, ironic pinto beans wake. silently specia +2273|1343|O|223151.74|1996-12-14|5-LOW|Clerk#000000155|0|uickly express foxes haggle quickly against +2274|1040|F|62910.69|1993-09-04|4-NOT SPECIFIED|Clerk#000000258|0|nstructions try to hag +2275|1484|F|54526.45|1992-10-22|4-NOT SPECIFIED|Clerk#000000206|0| furiously furious platelets. slyly final packa +2276|415|O|177003.87|1996-04-29|4-NOT SPECIFIED|Clerk#000000821|0|ecial requests. fox +2277|889|F|104747.35|1995-01-02|4-NOT SPECIFIED|Clerk#000000385|0|accounts cajole. even i +2278|1406|O|154671.54|1998-04-25|3-MEDIUM|Clerk#000000186|0|r pinto beans integrate after the carefully even deposits. blit +2279|794|F|187322.08|1993-02-23|3-MEDIUM|Clerk#000000898|0|de of the quickly unusual instructio +2304|451|F|136763.46|1994-01-07|4-NOT SPECIFIED|Clerk#000000415|0|onic platelets. ironic packages haggle. packages nag doggedly according to +2305|421|F|154302.46|1993-01-26|2-HIGH|Clerk#000000440|0|ove the furiously even acco +2306|268|O|341859.20|1995-07-26|2-HIGH|Clerk#000000975|0| wake furiously requests. permanent requests affix. final packages caj +2307|1042|F|79156.35|1993-06-29|5-LOW|Clerk#000000952|0|furiously even asymptotes? carefully regular accounts +2308|239|F|78112.08|1992-10-25|4-NOT SPECIFIED|Clerk#000000609|0|ts. slyly final depo +2309|997|O|194143.51|1995-09-04|5-LOW|Clerk#000000803|0|he carefully pending packages. fluffily stealthy foxes engage carefully +2310|304|O|121341.69|1996-09-20|5-LOW|Clerk#000000917|0|wake carefully. unusual instructions nag ironic, regular excuse +2311|718|P|208795.07|1995-05-02|2-HIGH|Clerk#000000761|0|ly pending asymptotes-- furiously bold excus +2336|1414|O|37197.01|1996-01-07|4-NOT SPECIFIED|Clerk#000000902|0|c, final excuses sleep furiously among the even theodolites. f +2337|1402|O|65214.59|1997-06-18|4-NOT SPECIFIED|Clerk#000000754|0| quickly. final accounts haggle. carefully final acco +2338|1394|O|41743.98|1997-09-15|2-HIGH|Clerk#000000951|0|riously final dugouts. final, ironic packages wake express, ironic id +2339|1084|F|87620.47|1993-12-15|5-LOW|Clerk#000000847|0| against the regular +2340|646|O|47690.57|1996-01-12|1-URGENT|Clerk#000000964|0|ter the deposits sleep according to the slyly regular packages. carefully +2341|817|F|90460.36|1993-05-30|5-LOW|Clerk#000000443|0|sts-- blithely bold dolphins through the deposits nag blithely carefully re +2342|365|O|139380.41|1996-06-09|1-URGENT|Clerk#000000615|0|oost carefully across the regular accounts. blithely final d +2343|712|O|119571.52|1995-08-21|3-MEDIUM|Clerk#000000170|0|fluffily over the slyly special deposits. quickl +2368|130|F|130017.09|1993-08-20|1-URGENT|Clerk#000000830|0|t the bold instructions. carefully unusual +2369|1097|O|102225.66|1996-12-24|2-HIGH|Clerk#000000752|0|iously even requests are dogged, express +2370|1405|F|93340.00|1994-01-17|1-URGENT|Clerk#000000231|0|lyly final packages. quickly final deposits haggl +2371|187|O|278700.24|1998-01-07|1-URGENT|Clerk#000000028|0|ckages haggle at th +2372|292|O|145396.99|1997-11-21|5-LOW|Clerk#000000342|0|s: deposits haggle along the final ideas. careful +2373|263|F|79116.08|1994-03-12|4-NOT SPECIFIED|Clerk#000000306|0| even, special courts grow quickly. pending, +2374|40|F|148382.76|1993-10-29|4-NOT SPECIFIED|Clerk#000000081|0| blithely regular packages. blithely unusua +2375|49|O|159126.15|1996-11-20|3-MEDIUM|Clerk#000000197|0|unusual, pending theodolites cajole carefully +2400|364|O|104781.57|1998-07-25|5-LOW|Clerk#000000782|0|nusual courts nag against the carefully unusual pinto b +2401|1477|O|115018.83|1997-07-29|4-NOT SPECIFIED|Clerk#000000531|0|ully unusual instructions boost carefully silently regular requests. +2402|658|O|114097.88|1996-09-06|4-NOT SPECIFIED|Clerk#000000162|0|slyly final sheaves sleep slyly. q +2403|544|O|171679.55|1998-04-11|3-MEDIUM|Clerk#000000820|0|furiously regular deposits use. furiously unusual accounts wake along the +2404|767|O|136444.96|1997-03-13|4-NOT SPECIFIED|Clerk#000000409|0|deposits breach furiously. ironic foxes haggle carefully bold packag +2405|713|O|157476.73|1996-12-23|3-MEDIUM|Clerk#000000535|0|ular, regular asympto +2406|67|O|267248.11|1996-10-28|5-LOW|Clerk#000000561|0|blithely regular accounts u +2407|536|O|165349.80|1998-06-19|2-HIGH|Clerk#000000068|0|uests affix slyly among the slyly regular depos +2432|1021|O|80711.22|1996-07-13|1-URGENT|Clerk#000000115|0|re. slyly even deposits wake bra +2433|299|F|200835.08|1994-08-22|4-NOT SPECIFIED|Clerk#000000324|0|ess patterns are slyly. packages haggle carefu +2434|238|O|160941.81|1997-04-27|3-MEDIUM|Clerk#000000190|0|s. quickly ironic dolphins impress final deposits. blithel +2435|715|F|165964.31|1993-02-21|5-LOW|Clerk#000000112|0|es are carefully along the carefully final instructions. pe +2436|1250|O|95969.65|1995-09-11|4-NOT SPECIFIED|Clerk#000000549|0|arefully. blithely bold deposits affix special accounts. final foxes nag. spe +2437|844|F|207060.97|1993-04-21|4-NOT SPECIFIED|Clerk#000000578|0|. theodolites wake slyly-- ironic, pending platelets above the carefully exp +2438|127|F|308209.95|1993-07-15|2-HIGH|Clerk#000000744|0|the final, regular warhorses. regularly +2439|541|O|68090.09|1997-03-15|2-HIGH|Clerk#000000819|0|lithely after the car +2464|1450|O|32741.64|1997-11-23|5-LOW|Clerk#000000633|0|le about the instructions. courts wake carefully even +2465|325|O|253098.40|1995-06-24|1-URGENT|Clerk#000000078|0|al pinto beans. final, bold packages wake quickly +2466|181|F|221482.78|1994-03-06|1-URGENT|Clerk#000000424|0|c pinto beans. express deposits wake quickly. even, final courts nag. package +2467|343|O|8612.24|1995-07-16|4-NOT SPECIFIED|Clerk#000000914|0|pades sleep furiously. sometimes regular packages again +2468|1109|O|253685.87|1997-06-09|4-NOT SPECIFIED|Clerk#000000260|0|ickly regular packages. slyly ruthless requests snooze quickly blithe +2469|1229|O|230050.24|1996-11-26|5-LOW|Clerk#000000730|0| sleep closely regular instructions. furiously ironic instructi +2470|563|O|119774.66|1997-04-19|3-MEDIUM|Clerk#000000452|0|to the furiously final packages? pa +2471|884|O|61766.57|1998-03-12|4-NOT SPECIFIED|Clerk#000000860|0|carefully blithely regular pac +2496|1342|F|188456.20|1994-01-09|2-HIGH|Clerk#000000142|0|slyly. pending instructions sleep. quic +2497|470|F|236003.51|1992-08-27|1-URGENT|Clerk#000000977|0|ily ironic pinto beans. furiously final platelets alongside of t +2498|959|F|57787.08|1993-11-08|5-LOW|Clerk#000000373|0|g the slyly special pinto beans. +2499|1210|O|194133.93|1995-09-24|1-URGENT|Clerk#000000277|0|r the quickly bold foxes. bold instructi +2500|1330|F|210458.54|1992-08-15|2-HIGH|Clerk#000000447|0|integrate slyly pending deposits. furiously ironic accounts across the s +2501|665|O|105442.80|1997-05-25|5-LOW|Clerk#000000144|0|ickly special theodolite +2502|694|F|47966.60|1993-05-28|4-NOT SPECIFIED|Clerk#000000914|0|lyly: carefully pending ideas affix again +2503|67|F|250884.59|1993-06-20|3-MEDIUM|Clerk#000000294|0|ly even packages was. ironic, regular deposits unwind furiously across the p +2528|550|F|140496.46|1994-11-20|1-URGENT|Clerk#000000789|0|ular dependencies? regular frays kindle according to the blith +2529|1349|O|4809.51|1996-08-20|2-HIGH|Clerk#000000511|0|posits across the silent instructions wake blithely across +2530|1271|F|96402.94|1994-03-21|3-MEDIUM|Clerk#000000291|0|ular instructions about the quic +2531|434|O|214816.43|1996-05-06|4-NOT SPECIFIED|Clerk#000000095|0|even accounts. furiously ironic excuses sleep fluffily. carefully silen +2532|937|O|173714.44|1995-10-11|2-HIGH|Clerk#000000498|0|the blithely pending accounts. regular, regular excuses boost aro +2533|496|O|248797.75|1997-03-24|1-URGENT|Clerk#000000594|0|ecial instructions. spec +2534|754|O|265775.52|1996-07-17|3-MEDIUM|Clerk#000000332|0|packages cajole ironic requests. furiously regular +2535|1202|F|99020.66|1993-05-25|5-LOW|Clerk#000000296|0|phins cajole beneath the fluffily express asymptotes. c +2560|1309|F|213993.64|1992-09-05|1-URGENT|Clerk#000000538|0|atelets; quickly sly requests +2561|572|O|180170.50|1997-11-14|1-URGENT|Clerk#000000861|0|ual requests. unusual deposits cajole furiously pending, regular platelets. +2562|82|F|196430.96|1992-08-01|1-URGENT|Clerk#000000467|0|elets. pending dolphins promise slyly. bo +2563|613|F|237151.86|1993-11-19|4-NOT SPECIFIED|Clerk#000000150|0|sly even packages after the furio +2564|761|F|3975.31|1994-09-09|2-HIGH|Clerk#000000718|0|usly regular pinto beans. orbits wake carefully. slyly e +2565|554|O|269678.73|1998-02-28|3-MEDIUM|Clerk#000000032|0|x-ray blithely along +2566|856|F|127226.57|1992-10-10|3-MEDIUM|Clerk#000000414|0|ructions boost bold ideas. idly ironic accounts use according to th +2567|694|O|366949.49|1998-02-27|2-HIGH|Clerk#000000031|0|detect. furiously ironic requests +2592|1006|F|14583.53|1993-03-05|4-NOT SPECIFIED|Clerk#000000524|0|ts nag fluffily. quickly stealthy theodolite +2593|913|F|184358.17|1993-09-04|2-HIGH|Clerk#000000468|0|r the carefully final +2594|776|F|118325.94|1992-12-17|1-URGENT|Clerk#000000550|0|ests. theodolites above the blithely even accounts detect furio +2595|737|O|278418.04|1995-12-14|4-NOT SPECIFIED|Clerk#000000222|0|arefully ironic requests nag carefully ideas. +2596|424|O|93640.14|1996-08-17|1-URGENT|Clerk#000000242|0|requests. ironic, bold theodolites wak +2597|1036|F|38810.68|1993-02-04|2-HIGH|Clerk#000000757|0|iously ruthless exc +2598|1120|O|100794.85|1996-03-05|3-MEDIUM|Clerk#000000391|0| ironic notornis according to the blithely final requests should +2599|1483|O|95783.25|1996-11-07|2-HIGH|Clerk#000000722|0|ts. slyly regular theodolites wake sil +2624|512|O|43715.51|1996-11-28|5-LOW|Clerk#000000930|0|ic, regular packages +2625|382|F|46838.33|1992-10-14|4-NOT SPECIFIED|Clerk#000000386|0| final deposits. blithely ironic ideas +2626|1372|O|109208.97|1995-09-08|4-NOT SPECIFIED|Clerk#000000289|0|gside of the carefully special packages are furiously after the slyly express +2627|1486|F|31377.24|1992-03-24|3-MEDIUM|Clerk#000000181|0|s. silent, ruthless requests +2628|553|F|243890.34|1993-10-22|5-LOW|Clerk#000000836|0|ajole across the blithely careful accounts. blithely silent deposits sl +2629|1372|O|124187.64|1998-04-06|5-LOW|Clerk#000000680|0|uches dazzle carefully even, express excuses. ac +2630|841|F|180224.30|1992-10-24|5-LOW|Clerk#000000712|0|inal theodolites. ironic instructions s +2631|352|F|70543.30|1993-09-24|5-LOW|Clerk#000000833|0| quickly unusual deposits doubt around +2656|766|F|119993.15|1993-05-04|1-URGENT|Clerk#000000307|0|elets. slyly final accou +2657|247|O|231309.69|1995-10-17|2-HIGH|Clerk#000000160|0| foxes-- slyly final dependencies around the slyly final theodo +2658|134|O|208449.54|1995-09-23|3-MEDIUM|Clerk#000000400|0|bout the slyly regular accounts. ironic, +2659|821|F|103595.36|1993-12-18|4-NOT SPECIFIED|Clerk#000000758|0|cross the pending requests maintain +2660|1264|O|24605.68|1995-08-05|5-LOW|Clerk#000000480|0|ly finally regular deposits. ironic theodolites cajole +2661|739|O|138682.43|1997-01-04|3-MEDIUM|Clerk#000000217|0|al, regular pinto beans. silently final deposits should have t +2662|370|O|94638.61|1996-08-21|3-MEDIUM|Clerk#000000589|0|bold pinto beans above the slyly final accounts affix furiously deposits. pac +2663|941|O|35825.35|1995-09-06|1-URGENT|Clerk#000000950|0|ar requests. furiously final dolphins along the fluffily spe +2688|974|F|244642.45|1992-01-24|2-HIGH|Clerk#000000720|0|have to nag according to the pending theodolites. sly +2689|1015|F|43940.00|1992-04-09|4-NOT SPECIFIED|Clerk#000000698|0|press pains wake. furiously express theodolites alongsid +2690|935|O|325313.14|1996-03-31|3-MEDIUM|Clerk#000000760|0|ravely even theodolites +2691|59|F|47515.61|1992-04-30|5-LOW|Clerk#000000439|0|es at the regular deposits sleep slyly by the fluffy requests. eve +2692|619|O|25165.18|1997-12-02|3-MEDIUM|Clerk#000000878|0|es. regular asymptotes cajole above t +2693|172|O|64546.06|1996-09-04|1-URGENT|Clerk#000000370|0|ndle never. blithely regular packages nag carefully enticing platelets. ca +2694|1192|O|132476.42|1996-03-14|5-LOW|Clerk#000000722|0| requests. bold deposits above the theodol +2695|563|O|204229.27|1996-08-20|1-URGENT|Clerk#000000697|0|ven deposits around the quickly regular packa +2720|301|F|173898.68|1993-06-08|1-URGENT|Clerk#000000948|0|quickly. special asymptotes are fluffily ironi +2721|773|O|93291.10|1996-01-27|2-HIGH|Clerk#000000401|0| ideas eat even, unusual ideas. theodolites are carefully +2722|347|F|62122.98|1994-04-09|5-LOW|Clerk#000000638|0|rding to the carefully quick deposits. bli +2723|592|O|128721.12|1995-10-06|5-LOW|Clerk#000000836|0|nts must have to cajo +2724|1369|F|178028.99|1994-09-14|2-HIGH|Clerk#000000217|0| sleep blithely. blithely idle +2725|884|F|88263.14|1994-05-21|4-NOT SPECIFIED|Clerk#000000835|0|ular deposits. spec +2726|58|F|48071.00|1992-11-27|5-LOW|Clerk#000000470|0| blithely even dinos sleep care +2727|739|O|4148.56|1998-04-19|4-NOT SPECIFIED|Clerk#000000879|0|sual theodolites cajole enticingly above the furiously fin +2752|581|F|252581.73|1993-11-19|2-HIGH|Clerk#000000648|0| carefully regular foxes are quickly quickl +2753|154|F|228723.78|1993-11-30|2-HIGH|Clerk#000000380|0|ending instructions. unusual deposits +2754|1438|F|39260.31|1994-04-03|2-HIGH|Clerk#000000960|0|cies detect slyly. +2755|1177|F|131857.47|1992-02-07|4-NOT SPECIFIED|Clerk#000000177|0|ously according to the sly foxes. blithely regular pinto bean +2756|1166|F|194478.82|1994-04-18|1-URGENT|Clerk#000000537|0|arefully special warho +2757|755|O|125256.68|1995-07-20|2-HIGH|Clerk#000000216|0| regular requests subl +2758|412|O|42052.59|1998-07-12|5-LOW|Clerk#000000863|0|s cajole according to the carefully special +2759|1159|F|101861.98|1993-11-25|4-NOT SPECIFIED|Clerk#000000071|0|ts. regular, pending pinto beans sleep ab +2784|943|O|153115.55|1998-01-07|1-URGENT|Clerk#000000540|0|g deposits alongside of the silent requests s +2785|1462|O|195472.29|1995-07-21|2-HIGH|Clerk#000000098|0|iously pending packages sleep according to the blithely unusual foxe +2786|788|F|247891.00|1992-03-22|2-HIGH|Clerk#000000976|0|al platelets cajole blithely ironic requests. ironic re +2787|1030|O|4893.42|1995-09-30|1-URGENT|Clerk#000000906|0|he ironic, regular +2788|1234|F|26524.32|1994-09-22|1-URGENT|Clerk#000000641|0|nts wake across the fluffily bold accoun +2789|361|O|291634.33|1998-03-14|2-HIGH|Clerk#000000972|0|gular patterns boost. carefully even re +2790|250|F|239747.97|1994-08-19|2-HIGH|Clerk#000000679|0| the carefully express deposits sleep slyly +2791|1207|F|212540.36|1994-10-10|2-HIGH|Clerk#000000662|0|as. slyly ironic accounts play furiously bl +2816|568|F|62180.16|1994-09-20|2-HIGH|Clerk#000000289|0|kages at the final deposits cajole furious foxes. quickly +2817|397|F|107437.21|1994-04-19|3-MEDIUM|Clerk#000000982|0|ic foxes haggle upon the daringly even pinto beans. slyly +2818|482|F|166324.37|1994-12-12|3-MEDIUM|Clerk#000000413|0|eep furiously special ideas. express +2819|1019|F|92864.28|1994-05-05|1-URGENT|Clerk#000000769|0|ngside of the blithely ironic dolphins. furio +2820|181|F|202441.88|1994-05-20|3-MEDIUM|Clerk#000000807|0|equests are furiously. carefu +2821|1166|F|54252.30|1993-08-09|3-MEDIUM|Clerk#000000323|0|ng requests. even instructions are quickly express, silent instructi +2822|788|F|53827.11|1993-07-26|2-HIGH|Clerk#000000510|0|furiously against the accounts. unusual accounts aft +2823|781|O|261004.83|1995-09-09|2-HIGH|Clerk#000000567|0|encies. carefully fluffy accounts m +2848|689|F|165694.90|1992-03-10|1-URGENT|Clerk#000000256|0|ly fluffy foxes sleep furiously across the slyly regu +2849|455|O|272713.22|1996-04-30|2-HIGH|Clerk#000000659|0|al packages are after the quickly bold requests. carefully special +2850|992|O|161737.06|1996-10-02|2-HIGH|Clerk#000000392|0|, regular deposits. furiously pending packages hinder carefully carefully u +2851|1445|O|10321.32|1997-09-07|5-LOW|Clerk#000000566|0|Tiresias wake quickly quickly even +2852|892|F|144902.15|1993-01-16|1-URGENT|Clerk#000000740|0|ruthless deposits against the final instructions use quickly al +2853|929|F|137718.56|1994-05-05|2-HIGH|Clerk#000000878|0|the carefully even packages. +2854|1384|F|232446.67|1994-06-27|1-URGENT|Clerk#000000010|0| furiously ironic tithes use furiously +2855|481|F|63484.19|1993-04-04|4-NOT SPECIFIED|Clerk#000000973|0| silent, regular packages sleep +2880|79|F|172033.71|1992-03-15|2-HIGH|Clerk#000000756|0|ves maintain doggedly spec +2881|986|F|74406.92|1992-05-10|5-LOW|Clerk#000000864|0|uriously. slyly express requests according to the silent dol +2882|1201|O|266004.51|1995-08-22|2-HIGH|Clerk#000000891|0|pending deposits. carefully eve +2883|1208|F|253433.41|1995-01-23|5-LOW|Clerk#000000180|0|uses. carefully ironic accounts lose fluffil +2884|914|O|106271.93|1997-10-12|3-MEDIUM|Clerk#000000780|0|efully express instructions sleep against +2885|61|F|195560.03|1992-09-19|4-NOT SPECIFIED|Clerk#000000280|0|ly sometimes special excuses. final requests are +2886|1075|F|129888.20|1994-11-13|4-NOT SPECIFIED|Clerk#000000619|0|uctions. ironic packages sle +2887|1075|O|34769.89|1997-05-26|5-LOW|Clerk#000000566|0|slyly even pinto beans. slyly bold epitaphs cajole blithely above t +2912|922|F|29086.04|1992-03-12|5-LOW|Clerk#000000186|0|jole blithely above the quickly regular packages. carefully regular pinto bean +2913|424|O|168204.36|1997-07-12|3-MEDIUM|Clerk#000000118|0|mptotes doubt furiously slyly regu +2914|1072|F|87611.96|1993-03-03|3-MEDIUM|Clerk#000000543|0|he slyly regular theodolites are furiously sile +2915|925|F|154725.01|1994-03-31|5-LOW|Clerk#000000410|0|ld packages. bold deposits boost blithely. ironic, unusual theodoli +2916|74|O|35450.91|1995-12-27|2-HIGH|Clerk#000000681|0|ithely blithe deposits sleep beyond the +2917|908|O|155542.57|1997-12-09|4-NOT SPECIFIED|Clerk#000000061|0| special dugouts among the special deposi +2918|1175|O|37282.52|1996-09-08|3-MEDIUM|Clerk#000000439|0|ular deposits across th +2919|526|F|154899.61|1993-12-10|2-HIGH|Clerk#000000209|0|es. pearls wake quietly slyly ironic instructions-- +2944|136|O|196529.29|1997-09-24|4-NOT SPECIFIED|Clerk#000000740|0|deas. permanently special foxes haggle carefully ab +2945|283|O|351345.57|1996-01-03|2-HIGH|Clerk#000000499|0|ons are carefully toward the permanent, bold pinto beans. regu +2946|1243|O|146922.98|1996-02-05|5-LOW|Clerk#000000329|0|g instructions about the regular accounts sleep carefully along the pen +2947|697|P|53117.45|1995-04-26|1-URGENT|Clerk#000000464|0|ronic accounts. accounts run furiously d +2948|439|F|145273.22|1994-08-23|5-LOW|Clerk#000000701|0| deposits according to the blithely pending +2949|1363|F|150199.75|1994-04-12|2-HIGH|Clerk#000000184|0|y ironic accounts use. quickly blithe accou +2950|1345|O|275176.74|1997-07-06|1-URGENT|Clerk#000000833|0| dolphins around the furiously +2951|737|O|183228.93|1996-02-06|2-HIGH|Clerk#000000680|0|gular deposits above the finally regular ideas integrate idly stealthil +2976|281|F|170496.06|1993-12-10|4-NOT SPECIFIED|Clerk#000000159|0|. furiously ironic asymptotes haggle ruthlessly silently regular r +2977|712|O|41482.00|1996-08-27|3-MEDIUM|Clerk#000000252|0|quickly special platelets are furio +2978|439|P|192591.22|1995-05-03|1-URGENT|Clerk#000000135|0|d. even platelets are. ironic dependencies cajole slow, e +2979|1330|O|159392.83|1996-03-23|3-MEDIUM|Clerk#000000820|0|even, ironic foxes sleep along +2980|38|O|223259.35|1996-09-14|3-MEDIUM|Clerk#000000661|0|y quick pinto beans wake. slyly re +2981|475|O|49188.07|1998-07-29|5-LOW|Clerk#000000299|0|hely among the express foxes. blithely stealthy requests cajole boldly. regu +2982|844|F|81058.61|1995-03-19|2-HIGH|Clerk#000000402|0|lyly. express theodolites affix slyly after the slyly speci +2983|613|F|83588.10|1992-01-07|1-URGENT|Clerk#000000278|0|r the even requests. accounts maintain. regular accounts +3008|394|O|214071.78|1995-11-08|3-MEDIUM|Clerk#000000701|0|ze quickly. blithely regular packages above the slyly bold foxes shall +3009|544|O|155804.55|1997-02-28|1-URGENT|Clerk#000000205|0|r ideas. carefully pe +3010|76|O|208692.43|1996-01-26|2-HIGH|Clerk#000000931|0| blithely final requests. special deposits are slyl +3011|898|F|54626.00|1992-01-14|5-LOW|Clerk#000000515|0|onic deposits kindle slyly. dependencies around the quickly iro +3012|314|F|144301.93|1993-05-05|1-URGENT|Clerk#000000414|0|ts after the regular pinto beans impress blithely s +3013|1423|O|227439.49|1997-02-05|5-LOW|Clerk#000000591|0|the furiously pendin +3014|289|F|254837.16|1992-10-30|4-NOT SPECIFIED|Clerk#000000476|0|ep blithely according to the blith +3015|1016|F|165794.93|1992-09-27|5-LOW|Clerk#000000013|0|ously regular deposits affix carefully. furiousl +3040|1108|F|159027.67|1993-04-12|3-MEDIUM|Clerk#000000544|0|carefully special packages. blithe +3041|1126|O|34175.78|1997-06-03|5-LOW|Clerk#000000092|0|s. unusual, pending deposits use carefully. thinly final +3042|199|F|112621.21|1994-11-21|3-MEDIUM|Clerk#000000573|0| the slyly ironic depo +3043|434|F|113399.95|1992-04-25|5-LOW|Clerk#000000137|0|cajole blithely furiously fina +3044|529|O|60086.93|1996-04-03|2-HIGH|Clerk#000000008|0|cajole final courts. ironic deposits about the quickly final re +3045|499|O|146623.24|1995-09-27|1-URGENT|Clerk#000000405|0| express courts sleep quickly special asymptotes. +3046|314|O|170565.91|1995-11-30|2-HIGH|Clerk#000000522|0|r deposits. platelets use furi +3047|247|O|39892.35|1997-03-21|1-URGENT|Clerk#000000962|0|as. slyly express deposits are dogged pearls. silent ide +3072|226|F|126150.96|1994-01-30|4-NOT SPECIFIED|Clerk#000000370|0|ely final deposits cajole carefully. ironic, re +3073|1354|F|207755.81|1994-01-08|3-MEDIUM|Clerk#000000404|0|kly slyly bold accounts. express courts near the regular ideas sleep bli +3074|658|F|111588.36|1992-11-01|5-LOW|Clerk#000000546|0|yly even asymptotes shall have to haggle fluffily. deposits are +3075|1252|F|41813.90|1994-05-07|3-MEDIUM|Clerk#000000433|0|ackages: carefully unusual reques +3076|914|F|129065.87|1993-07-23|2-HIGH|Clerk#000000099|0|busy foxes. deposits affix quickly ironic, pending pint +3077|1208|O|157557.18|1997-08-06|2-HIGH|Clerk#000000228|0|kly. fluffily ironic requests use qui +3078|473|F|65211.07|1993-02-12|2-HIGH|Clerk#000000110|0|ounts are alongside of the blith +3079|986|O|192511.27|1997-09-12|5-LOW|Clerk#000000505|0|lly ironic accounts +3104|689|F|148848.19|1993-09-16|3-MEDIUM|Clerk#000000871|0|ges boost-- regular accounts are furiousl +3105|1366|O|185113.31|1996-11-13|4-NOT SPECIFIED|Clerk#000000772|0|s. blithely final ins +3106|1445|O|192869.71|1997-01-12|3-MEDIUM|Clerk#000000729|0|its use slyly final theodolites; regular dolphins hang above t +3107|254|O|157543.64|1997-08-21|1-URGENT|Clerk#000000669|0|ously even deposits acr +3108|844|F|75046.18|1993-08-05|1-URGENT|Clerk#000000574|0|s packages haggle furiously am +3109|1222|F|296211.71|1993-07-24|5-LOW|Clerk#000000936|0|bold requests sleep quickly according to the slyly final +3110|874|F|148021.35|1994-12-17|2-HIGH|Clerk#000000564|0|round the fluffy instructions. carefully silent packages cajol +3111|1328|O|208880.19|1995-08-25|5-LOW|Clerk#000000922|0|slyly regular theodolites. furious deposits cajole deposits. ironic theodoli +3136|230|F|195429.40|1994-08-10|4-NOT SPECIFIED|Clerk#000000891|0|tructions sleep slyly. pending di +3137|1342|O|9264.77|1995-07-26|3-MEDIUM|Clerk#000000063|0|ymptotes wake carefully above t +3138|1390|F|210941.18|1994-02-09|4-NOT SPECIFIED|Clerk#000000650|0|e fluffily final theodolites. even dependencies wake along the quickly ir +3139|166|F|56421.93|1992-01-02|3-MEDIUM|Clerk#000000855|0|ounts against the ruthlessly unusual dolphins +3140|1450|F|68160.48|1992-04-09|1-URGENT|Clerk#000000670|0|carefully ironic deposits use furiously. blith +3141|253|O|161595.67|1995-11-10|1-URGENT|Clerk#000000475|0|es. furiously bold instructions after the carefully final p +3142|73|F|17194.09|1992-06-28|3-MEDIUM|Clerk#000000043|0|usual accounts about the carefully special requests sleep slyly quickly regul +3143|1069|F|221770.55|1993-02-17|1-URGENT|Clerk#000000519|0| are final, ironic accounts. ironic +3168|1358|F|101697.90|1992-01-30|5-LOW|Clerk#000000352|0|s sleep slyly? ironic, furious instructions detect. quickly final i +3169|181|F|184054.00|1993-12-21|3-MEDIUM|Clerk#000000252|0| even pinto beans are blithely special, special multip +3170|43|O|292168.10|1997-11-09|1-URGENT|Clerk#000000288|0|requests. furiously bold +3171|466|F|110707.33|1993-04-06|5-LOW|Clerk#000000940|0|ar deposits. idly r +3172|883|F|165727.78|1992-06-03|4-NOT SPECIFIED|Clerk#000000771|0|es. slyly ironic packages x-ra +3173|1462|O|105183.55|1996-08-10|5-LOW|Clerk#000000516|0|ial requests lose along t +3174|1264|O|152505.56|1995-11-15|5-LOW|Clerk#000000663|0|rts. silent, regular pinto beans are blithely regular packages. furiousl +3175|439|F|252261.28|1994-07-15|5-LOW|Clerk#000000629|0| across the slyly even realms use carefully ironic deposits: sl +3200|122|O|178687.59|1996-02-07|1-URGENT|Clerk#000000020|0| regular dependencies impress evenly even excuses. blithely +3201|952|F|100522.53|1993-07-02|4-NOT SPECIFIED|Clerk#000000738|0|. busy, express instruction +3202|868|F|72537.65|1992-12-24|5-LOW|Clerk#000000067|0|fluffily express requests affix carefully around th +3203|1259|O|71682.53|1997-11-05|2-HIGH|Clerk#000000493|0|e furiously silent warhorses. slyly silent deposits wake bli +3204|88|F|44713.55|1992-12-26|1-URGENT|Clerk#000000693|0|ess somas cajole slyly. pending accounts cajole +3205|1463|F|215063.16|1992-04-11|5-LOW|Clerk#000000803|0|e furiously. quickly regular dinos about the final pinto be +3206|1213|O|82248.70|1996-08-09|1-URGENT|Clerk#000000755|0|ntegrate furiously final, express +3207|205|O|184595.78|1998-02-16|1-URGENT|Clerk#000000695|0|uriously accounts. fluffily i +3232|809|F|66817.67|1992-10-09|1-URGENT|Clerk#000000314|0|yly final accounts. packages agains +3233|1397|F|70920.20|1994-10-24|5-LOW|Clerk#000000470|0|ly ironic epitaphs use stealthy, express deposits. quickly regular instruct +3234|139|O|218988.88|1996-04-05|4-NOT SPECIFIED|Clerk#000000367|0|ents according to the dependencies will sleep after the blithely even p +3235|448|O|160699.91|1995-11-15|5-LOW|Clerk#000000349|0| quickly pinto beans. ironi +3236|1405|O|42427.77|1996-11-06|4-NOT SPECIFIED|Clerk#000000553|0|ithely slyly pending req +3237|182|F|11628.02|1992-06-03|1-URGENT|Clerk#000000606|0|inal requests. slyly even foxes detect about the furiously exp +3238|610|F|64556.89|1993-02-21|5-LOW|Clerk#000000818|0|lly express deposits are. furiously unusual ideas wake carefully somas. instr +3239|343|O|219052.93|1998-01-12|4-NOT SPECIFIED|Clerk#000000619|0| cajole carefully along the furiously pending deposits. +3264|925|O|214961.96|1996-11-02|5-LOW|Clerk#000000244|0|carefully. express, bold +3265|523|F|68739.22|1992-06-27|1-URGENT|Clerk#000000265|0|re quickly quickly pe +3266|37|P|99432.16|1995-03-17|5-LOW|Clerk#000000545|0|refully ironic instructions. slyly final pi +3267|1120|O|54666.17|1997-01-07|5-LOW|Clerk#000000484|0| the packages. regular decoys about the bold dependencies grow fi +3268|1414|F|50963.54|1994-06-25|5-LOW|Clerk#000000746|0|y brave requests unwind furiously accordin +3269|169|O|331533.22|1996-03-01|3-MEDIUM|Clerk#000000378|0|ts. accounts wake carefully. carefully dogged accounts wake slyly slyly i +3270|379|O|240687.99|1997-05-28|1-URGENT|Clerk#000000375|0|uffily pending courts ca +3271|331|F|138053.06|1992-01-01|1-URGENT|Clerk#000000421|0|s. furiously regular requests +3296|1471|F|280148.00|1994-10-19|3-MEDIUM|Clerk#000000991|0|as! carefully final requests wake. furiously even +3297|1385|F|11553.32|1992-11-03|2-HIGH|Clerk#000000220|0| after the theodolites cajole carefully according to the finally +3298|1159|O|91070.97|1996-04-17|5-LOW|Clerk#000000241|0|even accounts boost +3299|892|F|68340.62|1993-12-26|3-MEDIUM|Clerk#000000853|0|bold deposits. special instructions sleep care +3300|1168|O|35168.76|1995-07-15|5-LOW|Clerk#000000198|0|ses. carefully unusual instructions must have to detect about the blithel +3301|1322|F|72199.05|1994-09-04|4-NOT SPECIFIED|Clerk#000000325|0|ular gifts impress enticingly carefully express deposits; instructions boo +3302|334|O|51365.63|1995-11-14|2-HIGH|Clerk#000000367|0|eep blithely ironic requests. quickly even courts haggle slyly +3303|1435|O|155557.55|1997-12-14|4-NOT SPECIFIED|Clerk#000000661|0|nto beans sleep furiously above the carefully ironic +3328|65|F|192264.80|1992-11-19|5-LOW|Clerk#000000384|0|ake among the express accounts? carefully ironic packages cajole never. +3329|34|O|55269.13|1995-07-03|2-HIGH|Clerk#000000236|0|old deposits. special accounts haggle furiousl +3330|65|F|51302.83|1994-12-19|1-URGENT|Clerk#000000124|0|kages use. carefully regular deposits cajole carefully about +3331|907|F|77649.29|1993-05-21|2-HIGH|Clerk#000000901|0|uffily carefully sly accounts. blithely unu +3332|1424|F|103092.90|1994-11-05|1-URGENT|Clerk#000000840|0|ans detect carefully furiously final deposits: regular accoun +3333|913|F|252419.80|1992-09-16|4-NOT SPECIFIED|Clerk#000000157|0|ctions boost slyly quickly even accounts. deposits along +3334|751|O|47161.56|1996-02-18|5-LOW|Clerk#000000532|0|ounts maintain carefully. furiously close request +3335|487|O|162808.07|1995-10-15|3-MEDIUM|Clerk#000000694|0| deposits poach. ironic ideas about the carefully ironi +3360|1030|O|266634.93|1998-01-23|5-LOW|Clerk#000000254|0| the deposits. fluffily bold requests cajole regula +3361|484|F|116078.71|1992-08-23|4-NOT SPECIFIED|Clerk#000000577|0|unts detect furiously instructions. slow deposi +3362|1399|O|256039.11|1995-07-29|5-LOW|Clerk#000000011|0|the quickly pending deposits. silent, ev +3363|512|O|114518.93|1995-09-23|2-HIGH|Clerk#000000615|0|posits. ironic, final deposits are furiously slyly pending +3364|448|O|157350.59|1997-06-21|1-URGENT|Clerk#000000280|0|y even foxes? blithely stea +3365|820|F|240272.44|1994-11-09|2-HIGH|Clerk#000000126|0|he slyly regular foxes nag about the accounts. fluffily +3366|508|O|17060.87|1997-05-18|1-URGENT|Clerk#000000160|0| pinto beans upon the quickly expres +3367|727|F|123759.09|1992-12-31|4-NOT SPECIFIED|Clerk#000000029|0|efully blithely ironic pinto beans. carefully close +3392|737|O|124060.27|1995-10-28|1-URGENT|Clerk#000000325|0|es thrash blithely depths. bold multipliers wake f +3393|973|O|270663.25|1995-07-04|2-HIGH|Clerk#000000076|0|even requests. excuses are carefully deposits. fluf +3394|1486|O|231035.67|1996-05-05|4-NOT SPECIFIED|Clerk#000000105|0| blithely among the attainments. carefully final accounts nag blit +3395|1496|F|180443.18|1994-10-30|4-NOT SPECIFIED|Clerk#000000682|0|ideas haggle beside the ev +3396|1492|F|277647.09|1994-05-21|3-MEDIUM|Clerk#000000868|0|uffily regular platelet +3397|1297|F|117210.56|1994-06-23|3-MEDIUM|Clerk#000000048|0|yly. final deposits wake f +3398|668|O|1744.64|1996-09-23|1-URGENT|Clerk#000000818|0|uthless, special courts atop the unusual accounts grow fur +3399|1220|P|70777.98|1995-02-28|4-NOT SPECIFIED|Clerk#000000575|0|the carefully sly accounts. regular, pending theodolites wa +3424|1013|O|67108.17|1996-08-21|1-URGENT|Clerk#000000190|0|ven requests are quickly pending accounts. blithely furious requests +3425|1150|O|230685.11|1996-03-31|4-NOT SPECIFIED|Clerk#000000188|0|ions. deposits nag blithely alongside of the carefully f +3426|521|O|118942.14|1996-10-16|3-MEDIUM|Clerk#000000283|0|alongside of the slyly +3427|28|O|180376.94|1997-05-29|4-NOT SPECIFIED|Clerk#000000404|0|y final pinto beans snooze fluffily bold asymptot +3428|85|O|103376.25|1996-04-07|5-LOW|Clerk#000000953|0|lar excuses. slyly pending ideas detect p +3429|1453|O|207631.78|1997-01-06|4-NOT SPECIFIED|Clerk#000000737|0|l deposits cajole furiously enticing deposits. blithe packages haggle careful +3430|1121|F|270267.01|1994-12-12|4-NOT SPECIFIED|Clerk#000000664|0| regular attainments are at the final foxes. final packages along the blithe +3431|463|F|71445.89|1993-08-22|1-URGENT|Clerk#000000439|0| sleep. slyly busy Tiresias a +3456|448|F|32601.42|1993-06-01|5-LOW|Clerk#000000924|0|es promise slyly. ironicall +3457|241|P|207252.29|1995-04-27|4-NOT SPECIFIED|Clerk#000000849|0|ely thin asymptotes. deposits kindle. pending +3458|946|F|197366.63|1994-12-22|2-HIGH|Clerk#000000392|0|rges snooze. slyly unusua +3459|1187|F|179504.40|1994-07-28|4-NOT SPECIFIED|Clerk#000000777|0|n instructions? carefully regular excuses are blithely. silent, ironi +3460|808|O|354036.76|1995-10-03|2-HIGH|Clerk#000000078|0|ans integrate carefu +3461|986|F|320694.21|1993-01-31|1-URGENT|Clerk#000000504|0|al, bold deposits cajole fluffily fluffily final foxes. pending ideas beli +3462|1328|O|86823.93|1997-05-17|3-MEDIUM|Clerk#000000657|0|uriously express asympto +3463|884|F|147059.62|1993-08-18|1-URGENT|Clerk#000000545|0|ding to the carefully ironic deposits +3488|1477|F|106165.56|1995-01-08|3-MEDIUM|Clerk#000000694|0|cording to the carefully regular deposits. re +3489|1072|F|86269.91|1993-07-29|3-MEDIUM|Clerk#000000307|0|s detect. carefully even platelets across the fur +3490|899|O|180759.57|1997-05-26|5-LOW|Clerk#000000703|0|gular ideas. furiously silent deposits across the unusual accounts boost i +3491|826|O|62878.19|1998-06-24|1-URGENT|Clerk#000000560|0|nic orbits believe carefully across the +3492|1019|F|193799.44|1994-11-24|5-LOW|Clerk#000000066|0|packages along the regular foxes lose final dependencie +3493|805|F|69650.05|1993-08-24|2-HIGH|Clerk#000000887|0|lyly special accounts use blithely across the furiously sil +3494|472|F|204991.65|1993-04-04|5-LOW|Clerk#000000559|0|r instructions haggle. accounts cajole. carefully final requests at the +3495|307|O|87879.06|1996-02-26|2-HIGH|Clerk#000000441|0|nticing excuses are carefully +3520|1250|O|217904.72|1997-08-04|1-URGENT|Clerk#000000023|0|hely. ideas nag; even, even fo +3521|68|F|207058.26|1992-10-26|5-LOW|Clerk#000000812|0|y even instructions cajole carefully above the bli +3522|256|F|228929.46|1994-09-26|5-LOW|Clerk#000000250|0|deposits-- slyly stealthy requests boost caref +3523|1499|O|179947.37|1998-04-07|2-HIGH|Clerk#000000688|0|are on the carefully even depe +3524|934|F|28748.76|1992-05-03|2-HIGH|Clerk#000000607|0|efully unusual tithes among the foxes use blithely daringly bold deposits. re +3525|1072|O|151567.42|1995-12-22|4-NOT SPECIFIED|Clerk#000000084|0|s nag among the blithely e +3526|559|F|70730.17|1995-03-16|5-LOW|Clerk#000000364|0|to the quickly special deposits print agai +3527|557|O|173421.31|1997-06-21|5-LOW|Clerk#000000874|0|regular ideas across the quickly bold theodo +3552|343|O|170016.99|1997-04-23|2-HIGH|Clerk#000000973|0| the ironic packages. furiously +3553|908|F|165037.95|1994-05-18|3-MEDIUM|Clerk#000000270|0|counts mold furiously. slyly i +3554|439|O|151890.41|1995-06-17|5-LOW|Clerk#000000931|0|hely ironic requests haggl +3555|455|O|178654.01|1996-07-07|5-LOW|Clerk#000000585|0|s nag carefully regular, even pinto be +3556|148|F|159831.74|1992-09-23|4-NOT SPECIFIED|Clerk#000000140|0|e. dependencies need to haggle alongs +3557|1192|F|116288.27|1992-11-09|2-HIGH|Clerk#000000291|0|ithely courts. furi +3558|265|O|162598.01|1996-02-29|1-URGENT|Clerk#000000841|0|around the furiously even requests. quickl +3559|1054|F|55757.49|1992-10-24|3-MEDIUM|Clerk#000000634|0|sly deposits. fluffily final ideas cajole careful +3584|118|O|101937.04|1997-08-11|1-URGENT|Clerk#000000760|0|fully bold packages. fluffily final braids haggle final, ironic dolphins. b +3585|1381|F|206416.27|1994-11-23|2-HIGH|Clerk#000000988|0|regular asymptotes. bold pains above the carefully pending asymptot +3586|1201|F|171227.96|1993-12-05|2-HIGH|Clerk#000000438|0|he quickly final courts. carefully regular requests nag unusua +3587|775|O|225119.62|1996-05-10|4-NOT SPECIFIED|Clerk#000000443|0|ular patterns detect +3588|1186|F|287191.29|1995-03-19|4-NOT SPECIFIED|Clerk#000000316|0|ong the pains. evenly unusual +3589|307|F|52846.72|1994-05-26|2-HIGH|Clerk#000000023|0|ithe deposits nag furiously. furiously pending packages sleep f +3590|1489|P|352720.59|1995-05-13|5-LOW|Clerk#000000986|0|lyly final deposits. +3591|1345|F|138408.31|1993-12-08|3-MEDIUM|Clerk#000000144|0|ual foxes haggle! unusual request +3616|1273|F|90467.25|1994-02-16|4-NOT SPECIFIED|Clerk#000000268|0|uickly about the quickly final requests. fluffily final packages wake evenly +3617|394|O|181875.51|1996-03-19|3-MEDIUM|Clerk#000000886|0|the carefully regular platelets ha +3618|98|O|185247.02|1997-12-13|3-MEDIUM|Clerk#000000894|0|. ideas run carefully. thin, pending +3619|1489|O|320560.24|1996-11-20|2-HIGH|Clerk#000000211|0|uests mold after the blithely ironic excuses. slyly pending pa +3620|440|O|90481.44|1997-03-07|5-LOW|Clerk#000000124|0|le quickly against the epitaphs. requests sleep slyly according to the +3621|1408|F|149743.36|1993-05-06|3-MEDIUM|Clerk#000000643|0|kly unusual deposits. qu +3622|901|O|174438.86|1995-11-27|5-LOW|Clerk#000000012|0|c deposits are fluffily about the blithely final theo +3623|29|O|253649.01|1996-12-26|1-URGENT|Clerk#000000184|0|- ironic excuses boost quickly in place +3648|1249|F|240597.67|1993-06-17|5-LOW|Clerk#000000717|0|foxes. unusual deposits boost quickly. slyly regular asymptotes across t +3649|388|F|202043.25|1994-07-06|5-LOW|Clerk#000000349|0|taphs boost above the final p +3650|445|F|280273.39|1992-05-28|4-NOT SPECIFIED|Clerk#000000454|0|kages sleep fluffily slyly +3651|986|O|125508.45|1998-04-27|1-URGENT|Clerk#000000222|0|ly unusual deposits thrash quickly after the ideas. +3652|1066|O|150080.43|1997-02-25|4-NOT SPECIFIED|Clerk#000000024|0|sly even requests after the +3653|383|F|215841.09|1994-03-27|1-URGENT|Clerk#000000402|0| pearls. bold accounts are along the ironic, +3654|56|F|326681.49|1992-06-03|5-LOW|Clerk#000000475|0|s cajole slyly carefully special theodolites. even deposits haggl +3655|487|F|111868.80|1992-10-06|1-URGENT|Clerk#000000815|0|er the carefully unusual deposits sleep quickly according to +3680|1267|F|172093.20|1992-12-10|4-NOT SPECIFIED|Clerk#000000793|0|ular platelets. carefully regular packages cajole blithely al +3681|517|F|34981.18|1992-04-04|1-URGENT|Clerk#000000566|0|. ironic deposits against the ironic, regular frets use pending plat +3682|317|O|93227.96|1997-01-22|2-HIGH|Clerk#000000001|0|es haggle carefully. decoys nag +3683|874|F|137933.64|1993-03-04|2-HIGH|Clerk#000000248|0|ze across the express foxes. carefully special acco +3684|229|F|109708.71|1993-07-20|2-HIGH|Clerk#000000835|0|bold accounts affix along the carefully ironic requ +3685|158|F|226866.11|1992-01-17|3-MEDIUM|Clerk#000000954|0| sleep fluffily special ide +3686|400|O|124290.79|1998-07-07|2-HIGH|Clerk#000000175|0|s. furiously final pinto beans poach carefully among +3687|422|F|127789.54|1993-02-03|1-URGENT|Clerk#000000585|0|gular accounts. slyly regular instructions can are final ide +3712|640|F|181818.96|1992-01-02|2-HIGH|Clerk#000000032|0| promise according +3713|1498|O|315464.25|1998-05-07|3-MEDIUM|Clerk#000000325|0|s haggle quickly. ironic, regular Tiresi +3714|392|O|115054.72|1998-05-01|3-MEDIUM|Clerk#000000595|0|nding accounts. ironic pinto beans wake slyly. furiously pendin +3715|644|O|88203.51|1996-03-18|1-URGENT|Clerk#000000463|0| always silent requests wake pinto beans. slyly pending foxes are aga +3716|415|O|202853.22|1997-08-19|4-NOT SPECIFIED|Clerk#000000748|0| pending ideas haggle. ironic, +3717|266|O|254701.10|1998-06-03|4-NOT SPECIFIED|Clerk#000000974|0|t the carefully even ideas use sp +3718|305|O|83545.86|1996-10-23|2-HIGH|Clerk#000000016|0|refully. furiously final packages use carefully slyly pending deposits! final, +3719|1180|O|194113.04|1997-02-16|2-HIGH|Clerk#000000034|0|, enticing accounts are blithely among the daringly final asymptotes. furious +3744|643|F|55886.68|1992-01-10|3-MEDIUM|Clerk#000000765|0|osits sublate about the regular requests. fluffily unusual accou +3745|1118|F|23657.43|1993-09-29|5-LOW|Clerk#000000181|0|ckages poach slyly against the foxes. slyly ironic instructi +3746|731|F|109530.26|1994-09-11|4-NOT SPECIFIED|Clerk#000000188|0|. express, special requests nag quic +3747|1492|O|258977.08|1996-08-20|1-URGENT|Clerk#000000226|0|refully across the final theodolites. carefully bold accounts cajol +3748|521|O|118550.25|1998-02-28|1-URGENT|Clerk#000000156|0|slyly special packages +3749|376|P|134685.89|1995-02-24|3-MEDIUM|Clerk#000000639|0|y regular instructions haggle blithel +3750|965|P|227479.98|1995-04-30|3-MEDIUM|Clerk#000000885|0|y. express, even packages wake after the ide +3751|91|F|296988.49|1994-04-27|4-NOT SPECIFIED|Clerk#000000925|0|sheaves. express, unusual t +3776|844|F|210295.67|1992-11-20|2-HIGH|Clerk#000000698|0|efully even platelets slee +3777|272|F|118933.43|1994-04-08|3-MEDIUM|Clerk#000000941|0| regular, special dolphins cajole enticingly ca +3778|1054|F|314918.09|1993-05-26|1-URGENT|Clerk#000000187|0| above the express requests. packages maintain fluffily according to +3779|733|O|43092.48|1997-01-05|4-NOT SPECIFIED|Clerk#000000670|0| against the deposits. quickly bold instructions x-ray. pending fox +3780|410|O|95100.73|1996-04-13|5-LOW|Clerk#000000967|0| around the brave, pendin +3781|1384|O|175615.29|1996-06-20|1-URGENT|Clerk#000000394|0|yly after the ruthless packages. pinto beans use slyly: never ironic dependenc +3782|650|O|170815.80|1996-08-24|1-URGENT|Clerk#000000121|0|counts are. pending, regular asym +3783|436|F|242713.60|1993-12-06|4-NOT SPECIFIED|Clerk#000000614|0| along the pinto beans. special packages use. regular theo +3808|778|F|320547.32|1994-04-24|1-URGENT|Clerk#000000717|0|odolites. blithely ironic cour +3809|1474|O|185067.55|1996-05-01|5-LOW|Clerk#000000646|0| regular excuses. even theodolites are fluffily according to t +3810|997|F|181248.66|1992-09-17|1-URGENT|Clerk#000000660|0|ters sleep across the carefully final +3811|799|O|215676.13|1998-04-16|3-MEDIUM|Clerk#000000290|0|sits wake slyly abo +3812|406|O|98698.11|1996-08-13|3-MEDIUM|Clerk#000000727|0|al, final requests cajole +3813|1459|O|102438.30|1998-06-29|1-URGENT|Clerk#000000531|0|g the furiously regular instructions +3814|1162|P|222423.89|1995-02-22|5-LOW|Clerk#000000669|0| the furiously pending theodo +3815|1039|O|18092.99|1997-08-26|1-URGENT|Clerk#000000249|0|es snooze carefully stealth +3840|985|O|270240.36|1998-07-17|4-NOT SPECIFIED|Clerk#000000713|0|yly slow theodolites. enticingly +3841|577|F|176161.65|1994-10-05|4-NOT SPECIFIED|Clerk#000000018|0| bold requests sleep quickly ironic packages. sometimes regular deposits nag +3842|269|F|184717.13|1992-04-09|5-LOW|Clerk#000000418|0|silent ideas. final deposits use furiously. blithely express excuses cajole fu +3843|85|O|35023.79|1997-01-04|4-NOT SPECIFIED|Clerk#000000693|0|eodolites; slyly unusual accounts nag boldly +3844|784|F|6858.13|1994-12-29|1-URGENT|Clerk#000000686|0|r dolphins. slyly ironic theodolites ag +3845|887|F|180711.26|1992-04-26|1-URGENT|Clerk#000000404|0|es among the pending, regular accounts sleep blithely blithely even de +3846|475|O|168131.67|1998-02-05|2-HIGH|Clerk#000000877|0|y alongside of the slyl +3847|337|F|11494.62|1993-03-12|5-LOW|Clerk#000000338|0|uriously even deposits. furiously pe +3872|1331|O|269197.14|1996-09-06|5-LOW|Clerk#000000943|0|counts boost slyly against the ironic platelets-- blithely p +3873|535|O|127910.27|1998-03-30|4-NOT SPECIFIED|Clerk#000000791|0|express deposits-- even ideas +3874|1186|F|85524.46|1993-06-09|3-MEDIUM|Clerk#000000208|0|ular asymptotes sleep blithely ironic ideas. blithel +3875|1177|O|93803.50|1997-09-10|1-URGENT|Clerk#000000587|0| solve among the fluffily even +3876|283|O|113879.01|1996-08-02|5-LOW|Clerk#000000708|0|into beans. blithely +3877|164|F|239783.44|1993-05-21|5-LOW|Clerk#000000652|0|foxes. thinly bold reques +3878|866|O|90013.77|1997-03-23|1-URGENT|Clerk#000000314|0|e carefully regular platelets. special, express dependencies slee +3879|1408|O|100898.76|1995-11-23|1-URGENT|Clerk#000000231|0|sts along the quickly ironic sentiments cajole carefully according to t +3904|1483|O|58126.35|1997-11-15|4-NOT SPECIFIED|Clerk#000000883|0|sits haggle furiously across the requests. theodolites ha +3905|211|F|55580.47|1993-12-21|4-NOT SPECIFIED|Clerk#000000573|0|usly even accounts lose quietly above the slyly express p +3906|443|F|208585.62|1992-05-28|3-MEDIUM|Clerk#000000867|0|ironic theodolites haggle blithely above the final re +3907|661|F|318521.56|1992-08-19|3-MEDIUM|Clerk#000000084|0|gular pinto beans sleep f +3908|412|F|100534.13|1993-03-09|3-MEDIUM|Clerk#000000490|0|ounts cajole. regularly +3909|206|O|133975.94|1998-07-27|1-URGENT|Clerk#000000980|0|nic, special theodolites sleep furiously! furiously +3910|629|O|70759.37|1996-08-26|3-MEDIUM|Clerk#000000270|0|ickly. furiously final packag +3911|89|P|45445.54|1995-03-17|4-NOT SPECIFIED|Clerk#000000818|0|he fluffily final forges haggle slyly according to the blithely +3936|314|O|255569.92|1996-11-07|2-HIGH|Clerk#000000200|0|iously express packages engage slyly fina +3937|935|O|254234.45|1997-11-30|4-NOT SPECIFIED|Clerk#000000189|0|ckages boost carefully blithely q +3938|298|F|65808.22|1993-03-03|1-URGENT|Clerk#000000199|0|. unusual, final foxes haggle +3939|682|O|12318.56|1996-01-11|5-LOW|Clerk#000000647|0|ly ruthlessly silent requests. blithely regular requests haggle blithely wh +3940|1495|O|180309.76|1996-02-14|5-LOW|Clerk#000000363|0|e above the ideas. quickly even dependencies along the blithely ir +3941|1354|O|114660.33|1996-08-29|2-HIGH|Clerk#000000503|0|gular theodolites integrate quickly +3942|754|F|56198.29|1993-06-28|4-NOT SPECIFIED|Clerk#000000608|0|eas cajole bold requests. idly silent instructions +3943|397|O|87171.39|1996-10-09|5-LOW|Clerk#000000482|0|se alongside of the final pinto beans. regular packages boost across the ca +3968|242|O|166197.28|1997-02-17|4-NOT SPECIFIED|Clerk#000000431|0| the slyly special accounts; +3969|512|O|269722.89|1997-05-14|2-HIGH|Clerk#000000731|0|uriously final dependencies slee +3970|751|F|185828.35|1992-03-27|3-MEDIUM|Clerk#000000190|0|luffily furiously regular deposits. blithely special requests cajole blithely +3971|1033|O|88799.11|1996-06-28|5-LOW|Clerk#000000287|0|alongside of the instructions ought to are +3972|1225|F|2750.56|1994-04-21|3-MEDIUM|Clerk#000000049|0|y regular requests haggle quickly. pending, express acco +3973|1018|F|112002.24|1992-03-24|4-NOT SPECIFIED|Clerk#000000114|0|somas according to the quickly even instructions wake fu +3974|931|O|74431.82|1996-03-05|4-NOT SPECIFIED|Clerk#000000938|0|deposits are furiously beneath the bl +3975|1175|O|57733.07|1995-04-11|3-MEDIUM|Clerk#000000016|0|ts. regular, regular Tiresias play furiously. ironi +4000|697|F|142251.94|1992-01-04|5-LOW|Clerk#000000339|0|le carefully closely even pinto beans. regular, ironic foxes against the +4001|1141|O|116208.23|1997-05-15|3-MEDIUM|Clerk#000000878|0|detect. asymptotes sleep furio +4002|1036|O|102892.70|1997-04-08|5-LOW|Clerk#000000097|0| regular braids are. furiously even patterns agains +4003|1102|F|26116.74|1993-01-27|1-URGENT|Clerk#000000177|0| blithe theodolites are slyly. slyly silent accounts toward +4004|683|F|302888.59|1993-05-07|3-MEDIUM|Clerk#000000273|0|accounts among the blithely regular sentiments +4005|1394|O|158486.49|1996-11-20|2-HIGH|Clerk#000000341|0|ily according to the slyly iron +4006|343|F|87327.23|1995-01-04|3-MEDIUM|Clerk#000000765|0|ly ironic packages integrate. regular requests alongside of +4007|80|F|143238.58|1993-06-18|2-HIGH|Clerk#000000623|0|ecial packages. slyly regular accounts integrate +4032|100|O|78049.89|1998-02-26|3-MEDIUM|Clerk#000000686|0|iresias sleep slyly regular ideas. quickly unusual +4033|830|F|68013.86|1993-06-02|5-LOW|Clerk#000000181|0|ously bold instructions haggle furiously above the fluf +4034|925|F|282204.87|1993-11-14|4-NOT SPECIFIED|Clerk#000000548|0|ts x-ray. express requests affix fluffily regular theodolites. pending, fina +4035|1165|F|35308.69|1992-02-19|5-LOW|Clerk#000000097|0|he ironic deposits sleep blith +4036|469|O|98412.41|1997-04-26|3-MEDIUM|Clerk#000000398|0|ly express deposits nag slyly. ironic, final asymptotes boost bra +4037|1210|F|57520.19|1993-03-24|2-HIGH|Clerk#000000384|0|t carefully above the unusual the +4038|937|O|223001.93|1996-01-06|1-URGENT|Clerk#000000272|0|re slyly. silent requests wake quickly. regular packages play quickly +4039|281|O|201017.09|1997-11-16|1-URGENT|Clerk#000000358|0|ly ironic deposits. ironic reques +4064|1288|O|231293.88|1996-10-10|4-NOT SPECIFIED|Clerk#000000598|0|ccounts. furiously unusual theodolites wake carefully about +4065|794|F|200609.19|1994-06-09|1-URGENT|Clerk#000000131|0|even foxes! slyly final deposits agai +4066|313|O|250572.93|1997-01-27|4-NOT SPECIFIED|Clerk#000000286|0|yly ironic dinos. quickly regular accounts haggle. requests wa +4067|145|F|232299.26|1992-10-07|2-HIGH|Clerk#000000027|0|tes boost furiously quick asymptotes. final deposits of the dolphins solv +4068|1250|O|86200.64|1996-09-18|3-MEDIUM|Clerk#000000203|0|lly even accounts wake furiously across the unusual platelets. unusu +4069|727|F|286148.59|1992-05-13|3-MEDIUM|Clerk#000000359|0|deposits: slyly bold ideas detect furiously. f +4070|284|O|133677.58|1995-06-12|2-HIGH|Clerk#000000713|0|xpress ideas poach ab +4071|1462|O|75727.31|1996-09-15|4-NOT SPECIFIED|Clerk#000000486|0|nal deposits. pending deposits d +4096|1378|F|100856.31|1992-07-03|4-NOT SPECIFIED|Clerk#000000706|0|sits. quickly thin deposits x-ray blith +4097|85|O|218589.15|1996-05-24|1-URGENT|Clerk#000000475|0|ickly under the even accounts. even packages after the furiously express +4098|221|O|83587.82|1996-11-05|4-NOT SPECIFIED|Clerk#000000491|0|otes. quickly final requests after the stealthily ironic pinto bean +4099|161|F|297452.57|1992-08-21|1-URGENT|Clerk#000000379|0|r platelets. slyly regular requests cajole carefully against the +4100|22|O|6545.02|1996-03-12|3-MEDIUM|Clerk#000000429|0|posits. carefully unusual packages use pending deposits. regular she +4101|1417|F|22280.28|1993-11-22|4-NOT SPECIFIED|Clerk#000000704|0|y around the express, careful epitaphs. accounts use fluffily. quickly p +4102|208|O|166220.63|1996-03-17|1-URGENT|Clerk#000000675|0|nding dependencies was slyly about the bl +4103|1048|F|64531.68|1992-07-03|5-LOW|Clerk#000000679|0|fully ironic dependencies. +4128|1390|O|9289.86|1995-10-07|4-NOT SPECIFIED|Clerk#000000635|0|ctions. dependencies from the slyly regular accounts nag slyly fu +4129|317|F|92828.14|1993-06-26|3-MEDIUM|Clerk#000000541|0|nwind. quickly final theodolites use packages. accounts +4130|1033|O|74653.84|1996-03-10|5-LOW|Clerk#000000609|0|omise alongside of the carefully final foxes. blithel +4131|436|O|174653.40|1998-01-30|1-URGENT|Clerk#000000612|0| above the foxes hang +4132|179|P|88197.43|1995-05-29|4-NOT SPECIFIED|Clerk#000000158|0|ld asymptotes solve alongside of the express, final packages. fluffily fi +4133|1001|F|39006.98|1992-08-07|4-NOT SPECIFIED|Clerk#000000268|0|al, express foxes. quickly pending deposits might cajole alongsi +4134|961|F|160154.58|1995-01-12|1-URGENT|Clerk#000000171|0|fully even deposits. regular de +4135|361|O|126584.08|1997-03-10|3-MEDIUM|Clerk#000000627|0|ly quietly even ideas. deposits haggle blithely +4160|542|O|110944.85|1996-08-20|5-LOW|Clerk#000000283|0|the carefully special accounts. furiously regular dugouts alongs +4161|1177|F|241960.17|1993-08-21|5-LOW|Clerk#000000047|0|nts. fluffily regular foxes above the quickly daring reques +4162|212|F|125408.74|1992-02-10|5-LOW|Clerk#000000179|0|r packages are slyly accounts. furiously special foxes detect carefully re +4163|628|F|15143.73|1992-12-21|2-HIGH|Clerk#000000268|0| integrate furiously slyly regular depende +4164|940|O|9375.68|1998-07-03|2-HIGH|Clerk#000000720|0| regularly busy theodolites boost furiously quickly bold packages. express, s +4165|29|O|15785.08|1997-07-25|3-MEDIUM|Clerk#000000621|0|special foxes affix never blithely ironic pinto beans; blithely +4166|413|F|145533.27|1993-02-28|5-LOW|Clerk#000000757|0|quickly sly forges impress. careful foxes across the blithely even a +4167|262|O|101266.76|1998-06-17|1-URGENT|Clerk#000000917|0|kly furiously even deposits. unu +4192|1453|O|256886.42|1998-04-19|1-URGENT|Clerk#000000369|0|equests above the slyly regular pinto beans unwi +4193|34|F|189411.15|1994-01-09|2-HIGH|Clerk#000000201|0|ng accounts haggle quickly. packages use fluffily ironic excu +4194|1058|F|102889.89|1994-10-16|3-MEDIUM|Clerk#000000385|0| instructions are quickly even pinto beans. courts boost furiously regular, ev +4195|1037|F|82719.34|1993-05-29|4-NOT SPECIFIED|Clerk#000000777|0| pinto beans cajole furiously theodolites-- slyly regular deposits doub +4196|1058|O|280403.32|1998-05-15|3-MEDIUM|Clerk#000000532|0|affix carefully. quickly final requests +4197|919|O|294678.85|1996-08-13|4-NOT SPECIFIED|Clerk#000000264|0| pinto beans according +4198|1429|O|135740.09|1997-06-16|3-MEDIUM|Clerk#000000583|0|g the special packages haggle pen +4199|41|F|40988.20|1992-02-13|1-URGENT|Clerk#000000309|0|e blithely. special deposits haggle slyly final foxes. carefully even +4224|689|O|237454.70|1997-07-14|1-URGENT|Clerk#000000034|0|jole quickly final dolphins. slyly pending foxes wake furiously bold pl +4225|1277|O|126532.76|1997-06-03|3-MEDIUM|Clerk#000000992|0|r the platelets nag among the special deposits. ironic, ironic re +4226|919|F|48595.07|1993-03-09|5-LOW|Clerk#000000203|0|phins wake slyly regular packages. deposits haggle slowl +4227|1318|F|127357.75|1995-02-24|1-URGENT|Clerk#000000063|0|ng the requests; ideas haggle fluffily. slyly unusual ideas c +4228|1100|O|27801.89|1997-03-28|5-LOW|Clerk#000000309|0|pecial requests aft +4229|133|O|115394.17|1998-03-03|1-URGENT|Clerk#000000301|0|p furiously: final excuses hagg +4230|1396|F|318270.36|1992-03-04|1-URGENT|Clerk#000000364|0|lly ironic deposits integrate carefully about the fu +4231|859|O|139085.25|1997-11-20|4-NOT SPECIFIED|Clerk#000000630|0|ly final accounts cajole furiously accounts. bravely ironic platelets am +4256|1178|F|30843.69|1992-04-05|4-NOT SPECIFIED|Clerk#000000043|0|y alongside of the fluffily iro +4257|163|P|49760.53|1995-03-25|3-MEDIUM|Clerk#000000682|0|r ideas cajole along the blithely regular gifts. +4258|916|O|184702.51|1996-10-27|4-NOT SPECIFIED|Clerk#000000364|0|efully final platelets around the blit +4259|1037|O|18170.62|1997-10-09|5-LOW|Clerk#000000781|0|es snooze slyly against the furiously unusual ideas. furious +4260|1418|F|22789.85|1992-05-16|4-NOT SPECIFIED|Clerk#000000919|0|e among the fluffily bold accounts. +4261|1174|F|114623.71|1992-10-03|1-URGENT|Clerk#000000662|0| about the even, pending packages. slyly bold deposits boost +4262|868|O|278346.38|1996-08-04|3-MEDIUM|Clerk#000000239|0| of the furious accounts. furiously regular accounts w +4263|25|O|200998.16|1998-03-16|1-URGENT|Clerk#000000265|0|sly ruthless deposits. final packages are instructions. fu +4288|340|F|94099.00|1992-12-04|4-NOT SPECIFIED|Clerk#000000823|0|usly carefully even theodolites: slyly express pac +4289|1246|F|35192.89|1993-10-07|3-MEDIUM|Clerk#000000912|0|e carefully close instructions. slyly special reques +4290|407|F|33841.66|1995-01-15|3-MEDIUM|Clerk#000000688|0| slyly quickly bold requests. final deposits haggle pending ideas! som +4291|881|F|81411.97|1993-11-29|3-MEDIUM|Clerk#000000655|0| sleep fluffily between the bold packages. bold +4292|244|F|177630.99|1992-01-09|3-MEDIUM|Clerk#000000794|0| ruthlessly. slyly bo +4293|1028|O|319796.01|1996-08-20|2-HIGH|Clerk#000000750|0|ly packages. regular packages nag according to t +4294|487|F|320119.78|1992-08-15|3-MEDIUM|Clerk#000000407|0|ng pinto beans breach. slyly express requests bo +4295|43|O|115056.47|1996-02-10|3-MEDIUM|Clerk#000000023|0|e boldly bold dependencies +4320|1144|O|101740.00|1996-12-08|4-NOT SPECIFIED|Clerk#000000223|0|ages haggle after the slowly bold se +4321|151|F|176680.44|1994-07-18|3-MEDIUM|Clerk#000000041|0|ending deposits are carefully carefully regular packa +4322|1412|O|206843.22|1998-03-13|3-MEDIUM|Clerk#000000433|0|totes nag across the fluffily special instructions. quickly silent hockey +4323|1036|F|27690.06|1994-01-23|2-HIGH|Clerk#000000282|0|lve after the slyly regular multipliers. even, regular excus +4324|713|O|264556.68|1995-07-17|1-URGENT|Clerk#000000800|0|ccounts. slyly stealthy requests shall have t +4325|1294|O|28574.21|1996-07-18|2-HIGH|Clerk#000000591|0|y around the always ev +4326|286|O|57111.99|1996-10-27|4-NOT SPECIFIED|Clerk#000000869|0|packages. carefully express deposit +4327|1456|P|174336.63|1995-03-16|2-HIGH|Clerk#000000571|0|yly pending braids. final requests abo +4352|136|O|17780.78|1997-11-26|2-HIGH|Clerk#000000620|0|ly final platelets integrate carefully even requ +4353|721|O|40333.36|1997-12-12|2-HIGH|Clerk#000000790|0|uickly even ideas cajole +4354|1436|F|245015.68|1994-09-30|4-NOT SPECIFIED|Clerk#000000046|0|pending notornis. requests serve +4355|28|O|231360.69|1996-11-16|1-URGENT|Clerk#000000362|0|ndencies use furiously across the regular +4356|961|F|66973.45|1994-04-11|5-LOW|Clerk#000000956|0| asymptotes sleep blithely. asymptotes sleep. blithely regul +4357|461|O|105145.58|1997-10-23|4-NOT SPECIFIED|Clerk#000000031|0|ages nag between the +4358|236|O|51989.52|1997-08-12|1-URGENT|Clerk#000000692|0|according to the fluffily special asymptotes +4359|142|F|163691.40|1993-03-03|1-URGENT|Clerk#000000393|0|sts. special, unusual deposits across the ironic theodo +4384|241|F|92211.63|1992-07-13|1-URGENT|Clerk#000000192|0|onic platelets. furiously regular asymptotes according to the special pac +4385|1217|O|39190.62|1996-08-06|2-HIGH|Clerk#000000597|0|ully final requests. ironic, even dolphins above the regular +4386|610|O|164103.41|1998-02-06|5-LOW|Clerk#000000070|0| dolphins. silent, idle pinto beans +4387|1091|O|153390.55|1995-10-23|1-URGENT|Clerk#000000025|0|ter the regular pinto beans. special, final gifts above the requests wi +4388|97|O|114701.49|1996-03-28|2-HIGH|Clerk#000000715|0|ts wake against the carefully final accounts. sly +4389|541|F|167744.85|1994-05-05|3-MEDIUM|Clerk#000000403|0|wly express excuses after the permanently even instructions are +4390|53|P|197545.62|1995-05-23|1-URGENT|Clerk#000000691|0|inal pinto beans. exp +4391|379|F|78494.42|1992-02-18|2-HIGH|Clerk#000000880|0|regular accounts. even depo +4416|1481|F|111380.89|1992-06-30|5-LOW|Clerk#000000391|0| deposits. ideas cajole express theodolites: +4417|670|O|109268.75|1998-07-09|1-URGENT|Clerk#000000365|0|ideas are alongside of the blithely final reque +4418|599|F|62464.13|1993-03-25|3-MEDIUM|Clerk#000000731|0|pecial pinto beans. close foxes affix iron +4419|1033|O|106015.25|1996-06-12|4-NOT SPECIFIED|Clerk#000000410|0|ages wake furiously slyly thin theodolit +4420|1090|F|6531.42|1994-06-18|1-URGENT|Clerk#000000706|0|lly bold deposits along the bold, pending foxes detect blithely after the acco +4421|85|O|401055.62|1997-04-04|3-MEDIUM|Clerk#000000246|0|t the pending warhorses. express waters a +4422|682|P|137446.09|1995-05-22|3-MEDIUM|Clerk#000000938|0|ly bold accounts sleep special, regular foxes. doggedly regular in +4423|635|F|6952.95|1995-02-17|5-LOW|Clerk#000000888|0|excuses are ruthless +4448|685|O|202506.72|1998-05-21|2-HIGH|Clerk#000000428|0|. deposits haggle around the silent packages; slyly unusual packages +4449|86|O|62361.39|1998-02-08|5-LOW|Clerk#000000035|0|ourts are carefully even deposits. pending +4450|1060|O|179497.92|1997-07-15|1-URGENT|Clerk#000000867|0|quests boost. furiously even realms are blithely bold requests. bl +4451|26|F|137267.09|1994-10-01|1-URGENT|Clerk#000000181|0|. carefully final foxes along the quickly express T +4452|122|F|65330.93|1994-06-21|5-LOW|Clerk#000000985|0|oxes are slyly. express, ironic pinto beans wake after the quickly pending re +4453|643|O|180326.79|1997-04-01|3-MEDIUM|Clerk#000000603|0|ages could have to nag slyly furiously even asymptotes! slowly regular +4454|1409|F|237490.06|1994-02-02|5-LOW|Clerk#000000411|0|uriously regular pint +4455|172|F|135599.42|1993-10-11|3-MEDIUM|Clerk#000000924|0|even requests. bravely regular foxes according to the carefully unusual +4480|832|F|27861.42|1994-03-31|4-NOT SPECIFIED|Clerk#000000534|0|press, bold deposits boost blit +4481|1468|O|108087.11|1996-03-30|5-LOW|Clerk#000000443|0|press sheaves cajole furio +4482|808|P|112095.89|1995-05-15|4-NOT SPECIFIED|Clerk#000000534|0|ravely bold accounts. furiously ironic instructions affix quickly. pend +4483|505|F|161222.40|1992-03-07|3-MEDIUM|Clerk#000000615|0|its. blithely idle accounts run; theodolites wake carefully around the fi +4484|1304|O|287136.09|1996-12-24|1-URGENT|Clerk#000000392|0|ct across the pinto beans. quickly pending excuses engage furiously. +4485|524|F|235145.28|1994-11-13|3-MEDIUM|Clerk#000000038|0|es wake slyly even packages. blithely brave requests nag above the regul +4486|367|O|215821.93|1998-03-03|2-HIGH|Clerk#000000656|0|ffily according to the carefully pending acc +4487|446|F|140035.87|1993-02-23|3-MEDIUM|Clerk#000000017|0|s up the never pending excuses wake furiously special pinto beans. furiously i +4512|683|O|193312.17|1995-10-25|5-LOW|Clerk#000000393|0|ending instructions maintain fu +4513|832|O|177644.71|1996-03-15|5-LOW|Clerk#000000154|0|ests. final, final ideas +4514|967|F|222536.94|1994-04-30|3-MEDIUM|Clerk#000000074|0|deposits according to the carefull +4515|1397|F|209521.83|1992-03-17|1-URGENT|Clerk#000000191|0|quests among the accounts sleep boldly about the regular f +4516|1294|F|53669.59|1994-03-29|3-MEDIUM|Clerk#000000739|0|ing packages sleep slyly regular attainments +4517|1129|O|66970.94|1998-03-07|4-NOT SPECIFIED|Clerk#000000231|0|uriously final deposits doze furiously furiously reg +4518|1246|O|35494.27|1997-05-01|3-MEDIUM|Clerk#000000187|0|luffily against the spec +4519|1343|F|110005.32|1993-03-30|4-NOT SPECIFIED|Clerk#000000938|0|ccording to the final +4544|1117|O|205337.52|1997-08-07|3-MEDIUM|Clerk#000000435|0|g dependencies dazzle slyly ironic somas. carefu +4545|586|F|191746.13|1993-01-17|4-NOT SPECIFIED|Clerk#000000303|0|ep. requests use sly +4546|418|O|55946.84|1995-07-29|5-LOW|Clerk#000000373|0|ns sleep. regular, regular instructions maintai +4547|1082|F|73135.94|1993-08-23|3-MEDIUM|Clerk#000000519|0|uctions thrash platelets. slyly final foxes wake slyly against th +4548|1265|O|181682.48|1996-06-28|5-LOW|Clerk#000000798|0| in place of the blithely express sentiments haggle slyly r +4549|638|O|61843.03|1998-03-05|4-NOT SPECIFIED|Clerk#000000965|0|ully even deposits dazzle. fluffily pending ideas against the requests +4550|1177|F|41533.95|1994-12-29|2-HIGH|Clerk#000000748|0|s haggle carefully acco +4551|1090|O|124682.71|1996-02-09|2-HIGH|Clerk#000000462|0|ts. slyly quick theodolite +4576|1381|O|87420.18|1996-08-14|5-LOW|Clerk#000000798|0|e pending deposits. +4577|785|O|165340.00|1998-05-02|5-LOW|Clerk#000000409|0|ly. unusual platelets are alw +4578|893|F|142392.37|1992-09-13|5-LOW|Clerk#000000121|0| to the furiously ironic instructions? furiou +4579|1042|O|125085.80|1995-12-01|2-HIGH|Clerk#000000951|0|its wake quickly blithely specia +4580|805|F|170320.34|1993-11-15|4-NOT SPECIFIED|Clerk#000000086|0|rs wake blithely regular requests. fluffily ev +4581|778|F|119792.47|1992-09-04|4-NOT SPECIFIED|Clerk#000000687|0|ges. carefully pending accounts use furiously abo +4582|184|O|30356.19|1996-07-04|1-URGENT|Clerk#000000638|0|g the furiously regular pac +4583|217|F|325377.79|1994-09-25|3-MEDIUM|Clerk#000000240|0|equests. slyly even platelets was qui +4608|796|F|237969.57|1994-06-17|1-URGENT|Clerk#000000259|0|y even instructions detect slyly asymptotes. blithely final packa +4609|1325|O|92624.01|1996-12-05|3-MEDIUM|Clerk#000000239|0|hang slyly slyly expre +4610|259|F|204812.77|1993-06-18|5-LOW|Clerk#000000616|0|e carefully express pinto +4611|286|F|263391.24|1993-01-10|2-HIGH|Clerk#000000152|0|. furiously regular instructions haggle dolphins. even instructions det +4612|604|F|105777.20|1993-09-20|3-MEDIUM|Clerk#000000397|0|bove the deposits. even deposits dazzle. slyly express packages haggle sl +4613|1315|O|265437.03|1998-03-05|3-MEDIUM|Clerk#000000541|0|furiously blithely pending dependen +4614|596|O|187916.73|1996-04-22|1-URGENT|Clerk#000000974|0| sauternes wake thinly special accounts. fur +4615|286|F|19198.41|1993-08-27|3-MEDIUM|Clerk#000000982|0|jole after the fluffily pending foxes. packages affix carefully acco +4640|955|O|110296.53|1996-01-01|5-LOW|Clerk#000000902|0|requests. deposits do detect above the blithely iron +4641|1334|F|165285.20|1993-01-20|4-NOT SPECIFIED|Clerk#000000755|0|ronic, final requests integrate slyly: specia +4642|1474|F|187642.74|1995-02-27|1-URGENT|Clerk#000000295|0|cial requests wake carefully around the regular, unusual ideas. furi +4643|667|O|84614.35|1995-06-30|2-HIGH|Clerk#000000292|0|ously regular packages. unusual, special platel +4644|935|O|127086.51|1998-01-17|5-LOW|Clerk#000000961|0|requests. fluffily even ideas bo +4645|434|F|329585.38|1994-09-20|1-URGENT|Clerk#000000764|0|fully even instructions. final gifts sublate quickly final requests. bl +4646|826|O|179979.78|1996-06-18|1-URGENT|Clerk#000000036|0|n place of the blithely qu +4647|265|F|147711.77|1994-05-14|3-MEDIUM|Clerk#000000626|0|out the deposits. slyly final pinto beans haggle idly. slyly s +4672|788|O|303147.86|1995-11-07|1-URGENT|Clerk#000000475|0|lyly final dependencies caj +4673|820|O|56339.98|1996-08-13|4-NOT SPECIFIED|Clerk#000000914|0|c deposits are slyly. bravely ironic deposits cajole carefully after the +4674|364|F|160248.90|1994-04-19|1-URGENT|Clerk#000000122|0|careful hockey players. carefully pending deposits caj +4675|860|F|100736.18|1993-11-25|4-NOT SPECIFIED|Clerk#000000741|0|al deposits haggle slyly final +4676|133|O|221378.75|1995-09-01|2-HIGH|Clerk#000000407|0|s. slyly bold accounts sleep furiously special +4677|382|O|29459.53|1998-02-21|3-MEDIUM|Clerk#000000245|0|ly pending deposits after the carefully regular foxes sleep blithely after t +4678|866|O|191622.17|1998-08-02|4-NOT SPECIFIED|Clerk#000000175|0|side of the bold platelets detect slyly blithely ironic e +4679|865|F|11866.57|1993-01-20|2-HIGH|Clerk#000000905|0|ely regular accounts affix slyly. final dolphins are. furiously final de +4704|13|O|101152.73|1996-08-16|4-NOT SPECIFIED|Clerk#000000256|0|lithely final requests about the fluffily regular +4705|979|F|248055.57|1992-03-22|4-NOT SPECIFIED|Clerk#000000522|0| special instructions poa +4706|238|F|144370.16|1992-12-29|4-NOT SPECIFIED|Clerk#000000722|0| packages above the never regular packages nag packages. deposits c +4707|893|F|74828.14|1995-02-27|2-HIGH|Clerk#000000943|0|ully enticing accounts behind the regular +4708|832|F|96314.41|1994-10-01|1-URGENT|Clerk#000000383|0|ly thinly even accounts. unusu +4709|256|O|69810.47|1996-01-08|3-MEDIUM|Clerk#000000785|0|he furiously even deposits! ironic theodolites haggle blithely. r +4710|985|F|120729.41|1994-12-08|4-NOT SPECIFIED|Clerk#000000734|0|the final, regular foxes. carefully ironic pattern +4711|1417|O|162618.22|1998-05-06|1-URGENT|Clerk#000000818|0|mptotes. unusual packages wake furiously qui +4736|1378|O|88659.44|1995-11-20|2-HIGH|Clerk#000000563|0|blithely regular courts affix into the carefully ironic deposits. slyly exp +4737|787|F|102138.81|1993-03-11|4-NOT SPECIFIED|Clerk#000000275|0|ents use slyly among the unusual, ironic pearls. furiously pending +4738|43|F|248132.99|1992-04-08|2-HIGH|Clerk#000000150|0|deposits. thin acco +4739|1472|F|116385.48|1993-02-21|5-LOW|Clerk#000000872|0|ing to the pending attainments: pending, express account +4740|677|O|51361.39|1996-07-05|2-HIGH|Clerk#000000420|0| dependencies haggle about the +4741|1270|F|261434.58|1992-07-07|4-NOT SPECIFIED|Clerk#000000983|0|ly bold deposits are slyly about the r +4742|637|P|249116.09|1995-03-23|3-MEDIUM|Clerk#000000058|0|n packages. quickly regular ideas cajole blithely +4743|967|F|98430.47|1993-03-31|5-LOW|Clerk#000000048|0|pinto beans above the bold, even idea +4768|1351|F|6485.65|1993-11-22|2-HIGH|Clerk#000000875|0|ctions snooze idly beneath the quick waters. fluffily u +4769|1205|P|202053.23|1995-04-14|4-NOT SPECIFIED|Clerk#000000116|0|pon the asymptotes. idle, final account +4770|589|O|96758.59|1995-06-20|2-HIGH|Clerk#000000461|0|cial instructions believe carefully. +4771|943|F|58304.87|1992-12-14|1-URGENT|Clerk#000000571|0|lly express deposits serve furiously along the f +4772|277|F|106724.51|1994-09-14|1-URGENT|Clerk#000000708|0|es sleep. regular requests haggle furiously slyly +4773|1213|O|278107.39|1995-12-23|1-URGENT|Clerk#000000327|0|ptotes was slyly along the +4774|508|F|186430.13|1993-04-20|3-MEDIUM|Clerk#000000299|0|eposits use blithely bold deposits. carefully regular gifts about the fin +4775|1273|O|141549.59|1995-08-13|4-NOT SPECIFIED|Clerk#000000609|0|s integrate slyly slyly final instructions. carefully bold pack +4800|352|F|135654.46|1992-01-06|5-LOW|Clerk#000000625|0|ggle furiously along the pending pinto beans. deposits use: final foxe +4801|874|O|168339.96|1996-01-25|1-URGENT|Clerk#000000553|0|r the final sentiments. pending theodolites sleep doggedly across t +4802|1288|O|8238.68|1997-01-23|3-MEDIUM|Clerk#000000400|0| ironic, thin packages wake furiously ironic, ironic deposits. the +4803|1234|O|249267.51|1996-02-08|5-LOW|Clerk#000000892|0|lly unusual courts are ironic +4804|358|F|148287.00|1992-01-28|2-HIGH|Clerk#000000614|0|ly final accounts. blithely unusual theodolite +4805|149|F|238156.01|1992-04-25|4-NOT SPECIFIED|Clerk#000000514|0|even accounts wake furiously slyly final accounts; blithel +4806|53|F|44638.95|1993-04-21|5-LOW|Clerk#000000625|0|ave accounts. furiously pending wa +4807|526|O|184759.45|1997-01-09|3-MEDIUM|Clerk#000000310|0|kly. slyly special accounts +4832|340|O|106440.70|1997-12-04|3-MEDIUM|Clerk#000000548|0|final accounts sleep among the blithe +4833|1319|O|94940.36|1996-05-12|3-MEDIUM|Clerk#000000256|0|r deposits against the slyly final excuses slee +4834|178|O|175765.87|1996-09-12|2-HIGH|Clerk#000000284|0|lar accounts. furiously ironic accounts haggle slyly +4835|1451|F|102173.80|1994-10-25|1-URGENT|Clerk#000000250|0|s integrate furiously blithely expr +4836|643|O|110667.95|1996-12-18|1-URGENT|Clerk#000000691|0|c packages cajole carefully through the accounts. careful +4837|1282|O|109203.24|1998-04-24|4-NOT SPECIFIED|Clerk#000000517|0|n accounts are regular, bold accounts. even instructions use request +4838|436|F|77558.81|1992-08-02|1-URGENT|Clerk#000000569|0|ffily bold sentiments. carefully close dolphins cajole across the +4839|244|F|107759.92|1994-05-10|1-URGENT|Clerk#000000925|0| even somas. slyly express ideas lose carefully. blithely unusu +4864|863|F|192178.70|1992-11-11|5-LOW|Clerk#000000423|0|ests nag within the quickly ironic asymptotes. ironic +4865|839|O|250988.92|1997-06-07|3-MEDIUM|Clerk#000000418|0|sits boost stealthily above the bl +4866|530|O|29343.32|1997-08-07|2-HIGH|Clerk#000000663|0|kages. unusual packages nag fluffily. qui +4867|82|F|15931.91|1992-05-21|1-URGENT|Clerk#000000891|0|ss the slyly regular dependencies. fluffily regular deposits within the car +4868|745|O|253228.69|1997-03-02|5-LOW|Clerk#000000729|0|regular asymptotes. regular packages sublate carefully al +4869|568|F|232130.29|1994-09-26|5-LOW|Clerk#000000802|0|boost! ironic packages un +4870|1016|F|140038.23|1994-08-06|3-MEDIUM|Clerk#000000911|0|nto beans about the blithely regular d +4871|448|O|172274.73|1995-06-12|1-URGENT|Clerk#000000531|0|ven, special instructions across t +4896|850|F|131264.74|1992-08-22|1-URGENT|Clerk#000000622|0|sly pending deposits. final accounts boost above the sly, even +4897|800|F|155933.30|1992-09-17|5-LOW|Clerk#000000184|0|s. bold pinto beans sleep. evenly final accounts daz +4898|137|F|67478.88|1994-07-11|4-NOT SPECIFIED|Clerk#000000841|0|final patterns. special theodolites haggle ruthlessly at the blithely spec +4899|601|F|16204.30|1993-10-18|4-NOT SPECIFIED|Clerk#000000348|0| instructions. furiously even packages are furiously speci +4900|1361|F|241094.13|1992-06-30|4-NOT SPECIFIED|Clerk#000000878|0|sleep quickly unusual +4901|790|O|178383.88|1997-12-31|4-NOT SPECIFIED|Clerk#000000980|0|inal dependencies cajole furiously. carefully express accounts na +4902|1372|O|44050.73|1998-07-04|3-MEDIUM|Clerk#000000874|0| the slyly express dolphins. +4903|920|F|39360.53|1992-03-22|4-NOT SPECIFIED|Clerk#000000907|0|yly. multipliers within the fo +4928|22|F|92223.13|1993-10-04|4-NOT SPECIFIED|Clerk#000000952|0|slyly brave instructions after the ironic excuses haggle ruthlessly about +4929|1492|O|198278.90|1996-02-29|3-MEDIUM|Clerk#000000109|0|uests. furiously special ideas poach. pending +4930|1483|F|264157.22|1994-05-06|5-LOW|Clerk#000000593|0| haggle slyly quietly final theodolites. packages are furious +4931|496|F|170930.79|1994-11-17|1-URGENT|Clerk#000000356|0|leep. slyly express dolphins nag slyly. furiously regular s +4932|1219|F|60768.93|1993-08-10|1-URGENT|Clerk#000000830|0|onic foxes. enticingly reg +4933|925|O|56755.81|1995-07-14|3-MEDIUM|Clerk#000000848|0|y special sauternes integr +4934|382|O|254375.72|1997-02-17|1-URGENT|Clerk#000000372|0|nes cajole; carefully special accounts haggle. special pinto beans nag +4935|400|F|225832.93|1993-05-25|4-NOT SPECIFIED|Clerk#000000601|0|c foxes. fluffily pendin +4960|1228|F|204893.89|1995-02-26|5-LOW|Clerk#000000229|0|uriously even excuses. fluffily regular instructions along the furiously ironi +4961|574|O|131816.39|1998-04-06|3-MEDIUM|Clerk#000000731|0| braids. furiously even theodolites +4962|1037|F|52829.69|1993-07-28|3-MEDIUM|Clerk#000000008|0| breach never ironic +4963|329|O|83635.70|1996-11-07|3-MEDIUM|Clerk#000000754|0|ully unusual epitaphs nod s +4964|1003|O|285003.26|1997-07-28|4-NOT SPECIFIED|Clerk#000000144|0|ithely final theodolites. blithely regu +4965|518|F|123088.54|1993-10-21|5-LOW|Clerk#000000638|0|dependencies poach packages. sometim +4966|688|O|80899.69|1996-09-07|2-HIGH|Clerk#000000243|0|accounts. blithely ironic courts wake boldly furiously express +4967|976|O|161892.72|1997-02-17|3-MEDIUM|Clerk#000000397|0|e theodolites; furiously b +4992|613|F|291161.83|1992-05-10|1-URGENT|Clerk#000000166|0|telets nag carefully am +4993|112|F|194811.83|1994-08-04|4-NOT SPECIFIED|Clerk#000000258|0|ing instructions nag furiously. un +4994|425|O|315464.22|1996-06-29|4-NOT SPECIFIED|Clerk#000000868|0|oxes wake above the asymptotes. bold requests sleep br +4995|388|O|259750.37|1996-01-06|4-NOT SPECIFIED|Clerk#000000748|0|s. even deposits boost along the express, even theodolites. stealthily ir +4996|1330|F|139500.09|1992-09-14|3-MEDIUM|Clerk#000000433|0|foxes. carefully special packages haggle quickly fluffi +4997|463|O|179285.35|1998-03-18|5-LOW|Clerk#000000040|0|egrate final pinto beans. fluffily special notornis use blith +4998|319|F|196035.93|1992-01-11|4-NOT SPECIFIED|Clerk#000000054|0|alongside of the quickly final requests hang always +4999|844|F|135073.82|1993-06-26|2-HIGH|Clerk#000000504|0| dolphins cajole blithely above the sly +5024|1222|O|148461.38|1996-10-25|3-MEDIUM|Clerk#000000659|0|r foxes. regular excuses are about the quickly regular theodolites. regular, +5025|1198|O|29882.15|1997-02-03|5-LOW|Clerk#000000805|0|ackages are slyly about the quickly +5026|271|O|24577.34|1997-09-06|1-URGENT|Clerk#000000955|0|y final requests us +5027|1463|O|273265.90|1997-08-30|2-HIGH|Clerk#000000751|0|e-- final, pending requests along t +5028|116|F|44919.14|1992-04-17|2-HIGH|Clerk#000000180|0|ickly blithely express deposits. b +5029|104|F|28069.92|1992-11-14|3-MEDIUM|Clerk#000000469|0|. regular accounts haggle slyly. regul +5030|1057|O|106018.58|1998-05-25|4-NOT SPECIFIED|Clerk#000000564|0| wake slyly furiously thin requests. ironic pinto beans ha +5031|1381|F|135672.76|1994-12-02|3-MEDIUM|Clerk#000000788|0|lar instructions haggle blithely pending foxes? sometimes final excuses h +5056|508|O|108095.49|1997-02-15|5-LOW|Clerk#000000828|0|lithely above the express ideas. blithely final deposits are fluffily spec +5057|640|O|91744.27|1997-08-03|1-URGENT|Clerk#000000955|0|r ironic requests of the carefully ironic dependencies wake slyly a +5058|1190|O|28461.94|1998-03-23|1-URGENT|Clerk#000000367|0| the pending packages wake after the quickly speci +5059|413|F|102772.50|1993-11-10|2-HIGH|Clerk#000000058|0|latelets. final, regular accounts cajole furiously ironic pinto beans? do +5060|1111|F|85197.05|1992-07-07|4-NOT SPECIFIED|Clerk#000000333|0|e according to the excuses. express theodo +5061|1006|F|72555.51|1993-08-14|1-URGENT|Clerk#000000009|0|e packages use fluffily according to the carefully ironic deposits. bol +5062|598|F|157769.50|1992-10-08|3-MEDIUM|Clerk#000000012|0|ithely. blithely bold theodolites affix. blithely final deposits haggle ac +5063|224|O|133623.15|1997-05-17|2-HIGH|Clerk#000000745|0|lyly after the pending foxes. express theodolites breach across t +5088|1294|F|160391.21|1993-01-06|5-LOW|Clerk#000000930|0|ole slyly since the quickly ironic br +5089|1295|F|137114.54|1992-07-29|1-URGENT|Clerk#000000677|0|cial platelets. quiet, final ideas cajole carefully. unusu +5090|881|O|174101.49|1997-03-09|1-URGENT|Clerk#000000953|0|ress accounts affix silently carefully quick accounts. carefully f +5091|1477|O|81938.11|1998-05-21|3-MEDIUM|Clerk#000000311|0|egular decoys mold carefully fluffily unus +5092|206|O|288758.19|1995-10-30|5-LOW|Clerk#000000194|0|are blithely along the pin +5093|776|F|249888.04|1993-09-03|3-MEDIUM|Clerk#000000802|0|ully ironic theodolites sleep above the furiously ruthless instructions. bli +5094|1051|F|103588.23|1993-03-29|4-NOT SPECIFIED|Clerk#000000406|0|uickly pending deposits haggle quickly ide +5095|952|F|275920.02|1992-04-22|2-HIGH|Clerk#000000964|0|accounts are carefully! slyly even packages wake slyly a +5120|155|O|33217.93|1996-06-05|1-URGENT|Clerk#000000332|0|against the slyly express requests. furiousl +5121|1328|F|229899.02|1992-05-11|4-NOT SPECIFIED|Clerk#000000736|0|gular requests. furiously final pearls against the permanent, thin courts s +5122|688|O|131621.44|1996-02-10|5-LOW|Clerk#000000780|0|blithely. slyly ironic deposits nag. excuses s +5123|97|O|14822.35|1998-02-10|1-URGENT|Clerk#000000776|0|ic requests. furiously ironic packages grow above the express, ironic inst +5124|238|O|209658.77|1997-04-04|4-NOT SPECIFIED|Clerk#000000749|0|kly even courts. bold packages solve. +5125|274|O|41954.76|1998-02-07|5-LOW|Clerk#000000834|0|ructions. dolphins wake slowly carefully unusual +5126|1120|F|110348.46|1992-10-12|4-NOT SPECIFIED|Clerk#000000270|0|s. unusual deposits +5127|722|O|59050.89|1997-01-15|5-LOW|Clerk#000000829|0|fully express pinto beans. slyly final accounts along the ironic dugouts use s +5152|433|O|70131.25|1997-01-04|3-MEDIUM|Clerk#000000963|0| for the blithely reg +5153|1124|O|256816.81|1995-08-26|1-URGENT|Clerk#000000954|0| the furiously ironic foxes. express packages shall cajole carefully across +5154|79|O|40583.07|1997-04-13|3-MEDIUM|Clerk#000000316|0|inal requests. slyly regular deposits nag. even deposits haggle agains +5155|763|F|99230.28|1994-06-12|2-HIGH|Clerk#000000108|0|y pending deposits are ag +5156|1249|O|72450.53|1996-11-04|5-LOW|Clerk#000000117|0|ngside of the multipliers solve slyly requests. regu +5157|1412|O|235193.85|1997-07-06|4-NOT SPECIFIED|Clerk#000000689|0|closely above the unusual deposits. furiously +5158|755|O|349464.54|1997-01-21|1-URGENT|Clerk#000000541|0| regular foxes. even foxes wake blithely +5159|1048|O|195720.25|1996-09-25|1-URGENT|Clerk#000000303|0|tegrate slyly around the slyly sly sauternes. final pa +5184|850|O|311131.08|1998-07-20|5-LOW|Clerk#000000250|0|nding accounts detect final, even +5185|1477|O|316890.58|1997-07-25|3-MEDIUM|Clerk#000000195|0| regular ideas about the even ex +5186|520|O|345577.74|1996-08-03|1-URGENT|Clerk#000000332|0|pecial platelets. slyly final ac +5187|538|O|52047.87|1997-07-16|3-MEDIUM|Clerk#000000682|0|ckly according to t +5188|1400|P|96653.92|1995-03-02|4-NOT SPECIFIED|Clerk#000000029|0|counts. finally ironic requests ab +5189|704|F|247112.62|1993-11-26|5-LOW|Clerk#000000940|0|e after the pending accounts. asymptotes boost. re +5190|580|F|146966.67|1992-04-26|5-LOW|Clerk#000000888|0|equests. slyly unusual +5191|770|F|156365.18|1994-12-11|4-NOT SPECIFIED|Clerk#000000318|0|ing, regular deposits alongside of the deposits boost fluffily quickly ev +5216|587|O|27361.79|1997-08-14|3-MEDIUM|Clerk#000000418|0|des boost across the platelets. slyly busy theodolit +5217|349|O|204315.50|1995-10-13|2-HIGH|Clerk#000000873|0|ons might wake quickly according to th +5218|802|F|109453.09|1992-07-30|4-NOT SPECIFIED|Clerk#000000683|0|y ruthless packages according to the bold, ironic package +5219|875|O|22976.04|1997-02-27|1-URGENT|Clerk#000000510|0|aggle always. foxes above the ironic deposits +5220|95|F|43690.73|1992-07-30|2-HIGH|Clerk#000000051|0| final packages. ideas detect slyly around +5221|125|O|82717.41|1995-06-09|4-NOT SPECIFIED|Clerk#000000324|0|lar accounts above the sl +5222|797|F|1406.50|1994-05-27|4-NOT SPECIFIED|Clerk#000000613|0|along the bold ideas. furiously final foxes snoo +5223|1486|F|125739.86|1994-06-30|1-URGENT|Clerk#000000745|0|e. theodolites serve blithely unusual, final foxes. carefully pending packag +5248|697|P|125759.30|1995-04-15|2-HIGH|Clerk#000000737|0|theodolites cajole according to the silent packages. quickly ironic packages a +5249|1019|F|166411.87|1994-09-06|3-MEDIUM|Clerk#000000019|0|refully bold accounts +5250|956|O|48941.36|1995-07-16|2-HIGH|Clerk#000000307|0|. carefully final instructions sleep among the finally regular dependen +5251|340|O|42259.44|1995-04-12|3-MEDIUM|Clerk#000000687|0| ironic dugouts detect. reque +5252|898|O|247519.93|1996-02-17|1-URGENT|Clerk#000000724|0| ironic accounts among the silent asym +5253|1480|P|144724.33|1995-04-11|2-HIGH|Clerk#000000275|0|egular requests! blithely regular deposits alongside of t +5254|1105|F|265744.68|1992-07-26|4-NOT SPECIFIED|Clerk#000000527|0|he express, even ideas cajole blithely special requests +5255|634|O|98826.70|1996-07-12|5-LOW|Clerk#000000591|0|ly slow forges. express foxes haggle. regular, even asymp +5280|329|O|110094.95|1997-12-03|3-MEDIUM|Clerk#000000604|0|riously ironic instructions. ironic ideas according to the accounts boost fur +5281|1240|O|232387.44|1995-11-02|2-HIGH|Clerk#000000158|0|ackages haggle slyly a +5282|499|O|126638.39|1998-01-30|1-URGENT|Clerk#000000030|0|rding to the unusual, bold accounts. regular instructions +5283|1309|F|19969.25|1994-06-04|3-MEDIUM|Clerk#000000579|0|ests. even, final ideas alongside of t +5284|608|O|58961.47|1995-07-09|4-NOT SPECIFIED|Clerk#000000155|0| careful dependencies use sly +5285|700|F|142725.60|1994-01-18|2-HIGH|Clerk#000000976|0|p across the furiously ironic deposits. +5286|1156|O|119200.31|1997-09-26|5-LOW|Clerk#000000606|0|structions are furiously quickly ironic asymptotes. quickly iro +5287|250|F|41064.04|1993-12-22|5-LOW|Clerk#000000406|0|regular packages. bold instructions sleep always. carefully final p +5312|649|F|82451.06|1995-02-24|2-HIGH|Clerk#000000690|0|ter the even, bold foxe +5313|130|O|199395.07|1997-06-17|4-NOT SPECIFIED|Clerk#000000896|0|le. final courts haggle furiously according to the +5314|331|O|29612.61|1995-06-02|2-HIGH|Clerk#000000617|0|ions across the quickly special d +5315|1387|F|84399.32|1992-10-29|4-NOT SPECIFIED|Clerk#000000035|0| furiously. quickly unusual packages use. sly +5316|997|F|68793.55|1994-01-31|1-URGENT|Clerk#000000734|0| requests haggle across the regular, pending deposits. furiously regular requ +5317|367|F|322782.46|1994-09-09|5-LOW|Clerk#000000687|0|jole quickly at the slyly pend +5318|590|F|140892.20|1993-04-04|2-HIGH|Clerk#000000663|0|efully regular dolphins. even ideas nag fluffily furiously even packa +5319|979|O|94253.83|1996-01-21|1-URGENT|Clerk#000000237|0|lent requests. quickly pe +5344|1072|O|139337.42|1998-06-21|3-MEDIUM|Clerk#000000569|0|s. ironic excuses cajole across the +5345|304|O|154585.90|1997-08-24|1-URGENT|Clerk#000000057|0|r the slyly silent packages. pending, even pinto b +5346|367|F|213859.93|1993-12-26|2-HIGH|Clerk#000000220|0|gly close packages against the even, regular escapades boost evenly accordi +5347|478|F|237559.02|1995-02-22|3-MEDIUM|Clerk#000000180|0|onic, regular deposits. packag +5348|524|O|151375.82|1997-11-08|5-LOW|Clerk#000000497|0|totes. accounts after the furiously +5349|670|O|52011.10|1996-09-01|1-URGENT|Clerk#000000960|0|le along the carefully bold dolphins. carefully special packa +5350|745|F|159518.11|1993-10-10|5-LOW|Clerk#000000604|0|ccounts after the carefully pending requests believe +5351|1213|O|91753.68|1998-05-11|1-URGENT|Clerk#000000443|0|to beans sleep furiously after the carefully even +5376|1486|F|166038.52|1994-07-04|5-LOW|Clerk#000000392|0|. quickly ironic deposits integrate along +5377|623|O|162417.75|1997-04-24|2-HIGH|Clerk#000000917|0|ons nag blithely furiously regula +5378|412|F|144404.53|1992-10-25|1-URGENT|Clerk#000000520|0|n ideas. regular accounts haggle. ironic ideas use along the bold ideas. blith +5379|884|O|80830.65|1995-08-08|2-HIGH|Clerk#000000503|0|he unusual accounts. carefully special instructi +5380|1462|O|163456.68|1997-10-12|1-URGENT|Clerk#000000481|0|le slyly about the slyly final dolphins. fu +5381|311|F|309639.39|1993-01-29|5-LOW|Clerk#000000531|0|arefully bold packages are slyly furiously ironic foxes. fluffil +5382|344|F|177903.56|1992-01-13|5-LOW|Clerk#000000809|0|lent deposits are according to the reg +5383|308|O|21345.98|1995-05-26|5-LOW|Clerk#000000409|0|ly bold requests hang furiously furiously unusual accounts. evenly unusu +5408|223|F|175098.30|1992-07-21|5-LOW|Clerk#000000735|0|egular requests according to the +5409|127|F|190710.92|1992-01-09|5-LOW|Clerk#000000171|0|eans. regular accounts are regul +5410|202|O|152792.92|1998-07-28|4-NOT SPECIFIED|Clerk#000000117|0|final deposits: pending excuses boost. ironic theodolites cajole furi +5411|598|O|81721.30|1997-05-16|3-MEDIUM|Clerk#000000800|0|equests cajole slyly furious +5412|1408|O|186066.37|1998-01-20|2-HIGH|Clerk#000000151|0|ets boost furiously regular accounts. regular foxes above th +5413|940|O|275955.54|1997-10-17|1-URGENT|Clerk#000000066|0|e even excuses. always final depen +5414|995|F|229650.28|1993-03-25|4-NOT SPECIFIED|Clerk#000000242|0|lent dependencies? carefully express requests sleep furiously ac +5415|221|F|204898.67|1992-08-05|3-MEDIUM|Clerk#000000998|0|ly even ideas nag blithely above the final instructions +5440|1291|O|3309.00|1997-01-12|1-URGENT|Clerk#000000154|0|posits boost regularly ironic packages. regular, ironic deposits wak +5441|401|F|179096.05|1994-07-21|4-NOT SPECIFIED|Clerk#000000257|0|after the furiously ironic +5442|413|O|204762.90|1998-01-13|4-NOT SPECIFIED|Clerk#000000954|0|ully. quickly express accounts against the +5443|1306|O|203531.90|1996-10-10|4-NOT SPECIFIED|Clerk#000000492|0|al foxes could detect. blithely stealthy asymptotes kind +5444|1288|P|247984.02|1995-03-18|1-URGENT|Clerk#000000677|0| asymptotes. asymptotes cajole quickly quickly bo +5445|1150|F|144557.32|1993-07-26|5-LOW|Clerk#000000623|0|s. even, special requests cajole furiously even, +5446|56|F|49289.08|1994-06-21|5-LOW|Clerk#000000304|0| furiously final pac +5447|130|O|54828.65|1996-03-16|3-MEDIUM|Clerk#000000597|0|uternes around the furiously bold accounts wake after +5472|686|F|349883.98|1993-04-11|5-LOW|Clerk#000000552|0|counts. deposits about the slyly dogged pinto beans cajole slyly +5473|641|F|88121.08|1992-03-25|4-NOT SPECIFIED|Clerk#000000306|0|te the quickly stealthy ideas. even, regular deposits above +5474|538|F|217534.09|1992-06-01|4-NOT SPECIFIED|Clerk#000000487|0|gle blithely enticing ideas. final, exp +5475|1372|O|16971.18|1996-07-07|5-LOW|Clerk#000000856|0|es shall boost slyly. furiously even deposits lose. instruc +5476|898|O|35392.02|1997-11-06|1-URGENT|Clerk#000000189|0|furiously final ideas. furiously bold dependencies sleep care +5477|1061|O|198571.43|1997-12-30|5-LOW|Clerk#000000689|0|ckages. ironic deposits caj +5478|1153|O|102065.07|1996-05-17|1-URGENT|Clerk#000000272|0|ckages. quickly pending deposits thrash furiously: bl +5479|697|F|81438.25|1993-12-22|3-MEDIUM|Clerk#000000335|0|ng asymptotes. pinto beans sleep care +5504|178|F|60408.91|1993-01-06|2-HIGH|Clerk#000000221|0|y pending packages. furiousl +5505|943|O|207951.17|1997-10-04|5-LOW|Clerk#000000719|0| final, regular packages according to the slyly ironic accounts nag ironica +5506|907|F|11496.86|1993-11-08|1-URGENT|Clerk#000000292|0|nusual theodolites. sly +5507|17|O|176100.92|1998-05-28|5-LOW|Clerk#000000692|0|the carefully ironic instructions are quickly iro +5508|557|O|4010.45|1996-06-21|1-URGENT|Clerk#000000128|0|y express packages cajole furiously. slyly unusual requests +5509|793|F|235588.34|1994-04-08|5-LOW|Clerk#000000164|0|usual deposits use packages. furiously final requests wake slyly about th +5510|361|F|163179.38|1993-01-08|3-MEDIUM|Clerk#000000819|0| nag slyly. carefully eve +5511|773|F|191746.63|1994-11-29|1-URGENT|Clerk#000000438|0|ng instructions integrate fluffily among the fluffily silent accounts. bli +5536|1151|O|161021.95|1998-03-16|4-NOT SPECIFIED|Clerk#000000076|0| carefully final dolphins. ironic, ironic deposits lose. bold, +5537|1178|O|157429.58|1996-10-03|3-MEDIUM|Clerk#000000742|0|ng to the daring, final +5538|1384|F|119417.57|1993-12-25|1-URGENT|Clerk#000000992|0|ttainments. slyly final ideas are about the furiously silent excuses. +5539|1189|F|63099.20|1994-07-31|5-LOW|Clerk#000000675|0|structions. slyly regular patterns solve above the carefully expres +5540|1285|O|144175.37|1996-10-12|4-NOT SPECIFIED|Clerk#000000120|0|y ironic packages cajole blithely +5541|1423|O|69883.38|1997-09-30|3-MEDIUM|Clerk#000000217|0|encies among the silent accounts sleep slyly quickly pending deposits +5542|481|O|10491.88|1996-04-20|4-NOT SPECIFIED|Clerk#000000100|0|riously among the regularly regular pac +5543|1150|F|165445.62|1993-09-25|3-MEDIUM|Clerk#000000644|0|ckly regular epitaphs. carefully bold accounts haggle furiously +5568|295|O|164846.25|1995-06-07|3-MEDIUM|Clerk#000000491|0| nag. fluffily pending de +5569|1088|F|183119.70|1993-04-30|4-NOT SPECIFIED|Clerk#000000759|0|e regular dependencies. furiously unusual ideas b +5570|1106|O|114869.30|1996-08-12|2-HIGH|Clerk#000000795|0|eans. ironic, even requests doze +5571|1021|F|130352.45|1992-12-19|4-NOT SPECIFIED|Clerk#000000184|0|ts cajole furiously carefully regular sheaves. un +5572|73|F|236455.84|1994-07-17|2-HIGH|Clerk#000000163|0|e fluffily express deposits cajole slyly across th +5573|358|O|200471.60|1996-08-15|3-MEDIUM|Clerk#000000055|0|lites. slyly final pinto beans about the carefully regul +5574|268|F|194685.04|1992-03-10|4-NOT SPECIFIED|Clerk#000000002|0|n deposits. special, regular t +5575|1012|O|71308.78|1995-07-24|5-LOW|Clerk#000000948|0|uriously express frays breach +5600|941|O|77497.53|1997-02-08|4-NOT SPECIFIED|Clerk#000000019|0|lly regular deposits. car +5601|110|F|175212.24|1992-01-06|2-HIGH|Clerk#000000827|0|gular deposits wake platelets? blithe +5602|1294|O|108142.13|1997-07-30|3-MEDIUM|Clerk#000000395|0|onic asymptotes haggl +5603|703|F|205166.88|1992-06-20|4-NOT SPECIFIED|Clerk#000000535|0| asymptotes. fluffily ironic instructions are. pending pinto bean +5604|443|O|124425.17|1998-04-14|4-NOT SPECIFIED|Clerk#000000123|0|ously across the blithely ironic pinto beans. sile +5605|346|O|278023.41|1996-08-22|2-HIGH|Clerk#000000538|0|sleep carefully final packages. dependencies wake slyly. theodol +5606|1486|O|330692.08|1996-11-12|5-LOW|Clerk#000000688|0|uriously express pinto beans. packages sh +5607|911|F|29084.44|1992-01-01|4-NOT SPECIFIED|Clerk#000000137|0|c requests promise quickly fluffily ironic deposits. caref +5632|784|O|106861.13|1996-02-05|1-URGENT|Clerk#000000508|0|ons. blithely pending pinto beans thrash. furiously busy theodoli +5633|775|O|302286.82|1998-05-31|3-MEDIUM|Clerk#000000841|0|cial deposits wake final, final +5634|677|O|147338.82|1996-07-31|3-MEDIUM|Clerk#000000915|0|out the accounts. carefully ironic ideas are slyly. sheaves could h +5635|686|F|273995.47|1992-08-16|3-MEDIUM|Clerk#000000734|0|nal platelets sleep daringly. idle, final accounts about +5636|1214|F|200472.48|1995-02-16|3-MEDIUM|Clerk#000000916|0|. boldly even Tiresias sleep. blithely ironic packages among the ca +5637|1030|O|194938.85|1996-06-17|3-MEDIUM|Clerk#000000183|0|nic dolphins are regular packages. ironic pinto beans hagg +5638|1078|F|104992.42|1994-01-17|1-URGENT|Clerk#000000355|0|enly bold deposits eat. special realms play against the regular, speci +5639|1450|F|13962.03|1994-06-02|3-MEDIUM|Clerk#000000005|0|ending packages use after the blithely regular accounts. regular package +5664|1186|O|241226.07|1998-07-23|2-HIGH|Clerk#000000789|0|the quickly ironic dolp +5665|994|F|162407.28|1993-06-28|4-NOT SPECIFIED|Clerk#000000513|0| carefully special instructions. ironic pinto beans nag slyly blithe +5666|139|F|158442.98|1994-02-02|2-HIGH|Clerk#000000396|0|mptotes. quickly final instructions are +5667|434|O|48054.70|1995-08-10|1-URGENT|Clerk#000000358|0|s print upon the quickly ironic packa +5668|1088|F|14179.13|1995-03-22|4-NOT SPECIFIED|Clerk#000000047|0|p slyly slyly express accoun +5669|736|O|168537.13|1996-05-06|1-URGENT|Clerk#000000336|0|ng packages nag fluffily furio +5670|64|F|153552.69|1993-04-21|5-LOW|Clerk#000000922|0|he carefully final packages. deposits are slyly among the requests. +5671|418|O|195159.38|1998-02-06|2-HIGH|Clerk#000000838|0|k dependencies. slyly +5696|1411|P|274605.94|1995-05-04|1-URGENT|Clerk#000000447|0|e quickly unusual pack +5697|541|F|136651.75|1992-10-05|1-URGENT|Clerk#000000112|0|pendencies impress furiously. bold, final requests solve ab +5698|943|F|204527.94|1994-05-21|3-MEDIUM|Clerk#000000455|0|he furiously silent accounts haggle blithely against the carefully unusual +5699|1414|F|300221.03|1992-07-30|5-LOW|Clerk#000000311|0|o beans. ironic asymptotes boost. blithe, final courts integrate +5700|1427|O|97397.92|1997-12-25|1-URGENT|Clerk#000000618|0|ly pending dolphins sleep carefully slyly pending i +5701|421|O|25111.71|1997-02-07|5-LOW|Clerk#000000798|0| blithely final pinto beans. blit +5702|967|F|235263.35|1993-09-07|4-NOT SPECIFIED|Clerk#000000743|0|ironic accounts. final accounts wake express deposits. final pac +5703|1196|F|3268.07|1993-05-16|3-MEDIUM|Clerk#000000647|0|ly special instructions. slyly even reque +5728|793|F|120489.88|1994-12-11|4-NOT SPECIFIED|Clerk#000000426|0|furiously express pin +5729|434|F|93102.37|1994-10-10|2-HIGH|Clerk#000000843|0|uffily sly accounts about +5730|110|O|18116.22|1997-12-18|1-URGENT|Clerk#000000181|0|l platelets. ironic pinto beans wake slyly. quickly b +5731|79|O|80961.79|1997-05-17|5-LOW|Clerk#000000841|0| silent excuses among the express accounts wake +5732|352|O|35016.82|1997-08-03|1-URGENT|Clerk#000000910|0|he quickly bold asymptotes: final platelets wake quickly. blithely final pinto +5733|1003|F|50786.52|1993-03-17|2-HIGH|Clerk#000000873|0|osits. pending accounts boost quickly. furiously permanent acco +5734|925|O|71965.89|1997-10-12|3-MEDIUM|Clerk#000000084|0|efully even braids detect blithely alo +5735|395|F|61436.03|1994-12-11|3-MEDIUM|Clerk#000000600|0| bold realms cajole slyly fu +5760|241|F|68043.47|1994-05-25|4-NOT SPECIFIED|Clerk#000000498|0|s among the blithely regular frays haggle ironically bold theodolites. al +5761|151|O|184256.14|1998-07-06|3-MEDIUM|Clerk#000000208|0|s asymptotes cajole boldly. regular, +5762|481|O|217243.20|1997-02-14|1-URGENT|Clerk#000000901|0|ly bold packages: slyly ironic deposits sleep quietly foxes. express a +5763|74|O|165052.79|1998-06-26|4-NOT SPECIFIED|Clerk#000000633|0|according to the furiously regular pinto beans. even accounts wake fu +5764|1306|F|68406.47|1993-10-03|4-NOT SPECIFIED|Clerk#000000363|0| furiously regular deposits haggle fluffily around th +5765|518|F|354366.71|1994-12-15|5-LOW|Clerk#000000959|0|longside of the quickly final packages. instructions so +5766|476|F|62642.11|1993-09-27|5-LOW|Clerk#000000753|0|. quickly final packages print slyly. fu +5767|1174|F|204654.62|1992-04-29|2-HIGH|Clerk#000000225|0|ts wake fluffily above the r +5792|256|F|216427.94|1993-04-04|2-HIGH|Clerk#000000731|0|packages. doggedly bold deposits integrate furiously across the +5793|362|O|169572.44|1997-07-13|2-HIGH|Clerk#000000294|0|thely. fluffily even instructi +5794|80|F|152918.94|1993-04-05|5-LOW|Clerk#000000855|0|t accounts kindle about the gifts. as +5795|368|F|59513.90|1992-05-05|2-HIGH|Clerk#000000581|0| even instructions x-ray ironic req +5796|1493|O|35978.09|1996-01-23|3-MEDIUM|Clerk#000000326|0|eodolites. slyly ironic pinto beans at the silent, special request +5797|1216|O|24070.20|1997-10-15|4-NOT SPECIFIED|Clerk#000000381|0|ng! packages against the blithely b +5798|1057|O|149833.20|1998-03-30|5-LOW|Clerk#000000343|0|lent accounts affix quickly! platelets run slyly slyly final packages. f +5799|260|O|133862.33|1995-08-03|1-URGENT|Clerk#000000238|0| unusual deposits sleep blithely along the carefully even requests. care +5824|556|O|255277.52|1996-12-03|2-HIGH|Clerk#000000171|0|unusual packages. even ideas along the even requests are along th +5825|607|F|32267.34|1995-02-21|5-LOW|Clerk#000000494|0|regular packages use bravely. +5826|217|O|32370.45|1998-06-13|1-URGENT|Clerk#000000087|0|even, regular dependenc +5827|305|O|179433.51|1998-07-23|3-MEDIUM|Clerk#000000660|0|hely furiously blithe dolphins. slyly +5828|1270|F|77774.16|1994-03-06|5-LOW|Clerk#000000377|0|ages boost never during the final packa +5829|1246|O|274279.62|1997-01-11|1-URGENT|Clerk#000000196|0|gular accounts. bold accounts are blithely furiously ironic r +5830|836|F|39788.96|1993-03-25|3-MEDIUM|Clerk#000000233|0|lites haggle. ironic, ironic instructions maintain blit +5831|1387|O|159764.61|1996-11-17|5-LOW|Clerk#000000585|0|s final, final pinto beans. unusual depos +5856|361|F|95904.56|1994-11-06|2-HIGH|Clerk#000000634|0|special excuses. slyly final theodolites cajole blithely furiou +5857|1231|O|263158.48|1997-11-06|4-NOT SPECIFIED|Clerk#000000267|0|gage blithely. quickly special ac +5858|625|F|227582.06|1992-07-14|4-NOT SPECIFIED|Clerk#000000580|0|lyly pending dugouts believe through the ironic deposits. silent s +5859|43|O|320141.27|1997-04-23|1-URGENT|Clerk#000000993|0|requests boost. asymptotes across the deposits solve slyly furiously pendin +5860|127|F|14002.56|1992-02-20|4-NOT SPECIFIED|Clerk#000000079|0| beans. bold, special foxes sleep about the ir +5861|1387|O|69464.42|1997-04-10|3-MEDIUM|Clerk#000000094|0|rthogs cajole slyly. express packages sleep blithely final +5862|628|O|30940.39|1997-02-20|1-URGENT|Clerk#000000039|0|leep beneath the quickly busy excuses. ironic theodolit +5863|641|F|96316.78|1993-11-22|3-MEDIUM|Clerk#000000774|0|ets about the slyly pending ideas sleep according to the blithely +5888|448|O|92148.63|1996-09-28|3-MEDIUM|Clerk#000000748|0|quickly against the furiously final requests. evenly fi +5889|209|O|26237.34|1995-05-23|5-LOW|Clerk#000000690|0|ites wake across the slyly ironic +5890|487|F|41609.58|1992-11-04|2-HIGH|Clerk#000000013|0|packages. final, final reques +5891|452|F|68375.28|1992-12-29|3-MEDIUM|Clerk#000000302|0|ounts haggle furiously abo +5892|1003|P|122565.47|1995-05-09|5-LOW|Clerk#000000639|0| pending instruction +5893|19|F|53359.53|1992-07-08|4-NOT SPECIFIED|Clerk#000000560|0|final sentiments. instructions boost above the never speci +5894|703|F|107123.24|1994-08-13|2-HIGH|Clerk#000000776|0|regular deposits wake +5895|622|O|284265.76|1997-01-01|4-NOT SPECIFIED|Clerk#000000747|0| ironic, unusual requests cajole blithely special, special deposits. s +5920|1189|F|227213.95|1994-11-20|2-HIGH|Clerk#000000081|0|ns: even ideas cajole slyly among the packages. never ironic patterns +5921|571|F|224503.60|1994-04-07|5-LOW|Clerk#000000125|0|kly special requests breach. +5922|1426|O|224288.29|1996-11-14|5-LOW|Clerk#000000625|0| ironic instructions haggle furiously blithely regular accounts: even platele +5923|1003|O|220218.91|1997-05-27|2-HIGH|Clerk#000000304|0|o beans haggle slyly above the regular, even dependencies +5924|305|O|154229.85|1995-10-10|3-MEDIUM|Clerk#000000433|0|arefully after the pains. blithely ironic pinto +5925|1453|O|373674.80|1995-11-13|5-LOW|Clerk#000000602|0|ourts. boldly regular foxes might sleep. slyly express tithes against +5926|748|F|146768.49|1994-05-20|5-LOW|Clerk#000000071|0| carefully after the furiously even re +5927|1153|O|136294.71|1997-08-28|4-NOT SPECIFIED|Clerk#000000972|0|endencies according to the slyly ironic foxes detect furiously about the furio +5952|1462|O|209693.87|1997-04-14|3-MEDIUM|Clerk#000000950|0| regular, final pla +5953|58|F|117651.40|1992-03-28|1-URGENT|Clerk#000000049|0|ages are furiously. slowly bold requests +5954|268|F|282400.28|1992-12-03|1-URGENT|Clerk#000000968|0|requests along the blith +5955|922|P|79722.29|1995-03-27|5-LOW|Clerk#000000340|0|deas integrate. fluffily regular pa +5956|208|O|166980.55|1998-05-18|1-URGENT|Clerk#000000587|0|le even, express platelets. +5957|883|F|312733.08|1993-12-27|2-HIGH|Clerk#000000020|0| dependencies are slyly. bold accounts according to the carefully regular r +5958|1141|O|191632.81|1995-09-16|3-MEDIUM|Clerk#000000787|0|e final requests detect alongside of the qu +5959|230|F|253103.52|1992-05-15|3-MEDIUM|Clerk#000000913|0|into beans use ironic, unusual foxes. carefully regular excuses boost caref +5984|688|F|114443.53|1994-06-18|5-LOW|Clerk#000000023|0|ickly final pains haggle along the furiously ironic pinto bea +5985|1430|F|7032.58|1995-01-12|3-MEDIUM|Clerk#000000417|0|as nag fluffily slyly permanent accounts. regular depo +5986|1147|F|157431.69|1992-04-22|2-HIGH|Clerk#000000674|0|iously unusual notornis are diff --git a/src/test/regress/data/orders.2.data b/src/test/regress/data/orders.2.data new file mode 100644 index 000000000..fb297e3a8 --- /dev/null +++ b/src/test/regress/data/orders.2.data @@ -0,0 +1,1486 @@ +8997|607|F|147614.36|1994-07-02|5-LOW|Clerk#000000404|0|lithely. express, ironic pearls nag permanently. +8998|80|F|147264.16|1993-01-04|5-LOW|Clerk#000000733|0| fluffily pending sauternes cajo +8999|1175|F|113671.53|1994-06-13|2-HIGH|Clerk#000000097|0|ly even foxes. slyly express a +9024|1469|F|298241.36|1992-06-03|3-MEDIUM|Clerk#000000901|0|ar the theodolites. fluffily stealthy requests among the quickly regular asy +9025|739|F|97454.69|1994-05-20|5-LOW|Clerk#000000379|0|ording to the quickly regular ideas integrate above the sly platelets. sly +9026|677|O|63256.87|1996-07-24|5-LOW|Clerk#000000320|0|ironic escapades would wake carefully +9027|514|O|155500.43|1995-09-03|5-LOW|Clerk#000000918|0| sleep carefully with th +9028|1475|F|63063.84|1993-12-22|5-LOW|Clerk#000000364|0| the regular packages. daringly even f +9029|1213|F|78703.86|1992-11-20|3-MEDIUM|Clerk#000000965|0| excuses nag quickly carefully unusual excuse +9030|535|O|225136.87|1998-07-14|3-MEDIUM|Clerk#000000872|0|foxes according to the furiously silent excuses could haggle unusual d +9031|1379|F|270589.18|1993-12-27|5-LOW|Clerk#000000890|0|r packages. slyly express ideas +9056|121|O|170074.18|1996-08-08|3-MEDIUM|Clerk#000000117|0|was carefully after the furiously bold dug +9057|71|F|320227.49|1994-11-05|1-URGENT|Clerk#000000539|0| fluffily quickly ironic packages. furiously ironic accounts a +9058|403|F|63464.13|1993-06-29|2-HIGH|Clerk#000000376|0|ealthily special deposits. quickly regular requests wake silently. fur +9059|926|O|187590.77|1996-08-01|2-HIGH|Clerk#000000725|0|ar pinto beans sleep special +9060|463|O|45295.71|1996-06-09|1-URGENT|Clerk#000000438|0|iously. slyly regular dol +9061|325|O|66191.69|1996-01-15|2-HIGH|Clerk#000000428|0|silent excuses! slyl +9062|1102|P|212710.32|1995-03-21|2-HIGH|Clerk#000000201|0|sts cajole slyly according to the carefully slow foxes. furio +9063|1399|O|51019.90|1997-02-12|2-HIGH|Clerk#000000323|0|ffily regular grouche +9088|610|F|224148.01|1994-06-23|1-URGENT|Clerk#000000975|0|ter the blithely final deposits. furiously +9089|370|F|39118.01|1993-05-24|1-URGENT|Clerk#000000538|0|d platelets are deposits. pinto beans cajole boldly. +9090|775|O|9848.22|1996-11-21|4-NOT SPECIFIED|Clerk#000000699|0|cial theodolites at the evenl +9091|679|F|242198.88|1993-11-12|2-HIGH|Clerk#000000426|0|final packages wake carefully. +9092|664|F|202836.36|1994-07-25|4-NOT SPECIFIED|Clerk#000000144|0| slyly final waters. special packages solve +9093|619|O|19431.49|1995-12-10|3-MEDIUM|Clerk#000000333|0|even accounts. special, +9094|1430|O|46784.32|1998-05-27|3-MEDIUM|Clerk#000000805|0|es boost slyly after the platelets. shea +9095|220|O|49946.10|1995-06-11|2-HIGH|Clerk#000000621|0|riously regular accounts wake slyly special theodolites. asymptotes use f +9120|1010|F|128719.48|1992-06-22|3-MEDIUM|Clerk#000000252|0|ly ironic realms. furio +9121|434|O|94637.46|1996-07-05|5-LOW|Clerk#000000930|0| final dependencies. carefully even excuses after the +9122|79|O|234630.52|1996-12-14|4-NOT SPECIFIED|Clerk#000000991|0|across the carefull +9123|367|F|64575.87|1993-06-27|1-URGENT|Clerk#000000988|0|wake carefully pendin +9124|559|O|173690.73|1995-10-17|5-LOW|Clerk#000000381|0|nstructions after the c +9125|151|O|195514.25|1998-05-30|2-HIGH|Clerk#000000591|0|kages around the fluffily bold f +9126|371|F|106144.91|1994-11-18|3-MEDIUM|Clerk#000000319|0|deposits boost carefully against the fluffily final instructions. i +9127|611|O|79003.80|1995-10-11|4-NOT SPECIFIED|Clerk#000000628|0|ress packages across the furio +9152|1210|F|129410.55|1993-08-21|4-NOT SPECIFIED|Clerk#000000612|0|nto beans! final instructions nag slyly. slyly ironic foxes nag blith +9153|1147|O|210245.80|1997-07-19|4-NOT SPECIFIED|Clerk#000000488|0|uffily express instructions haggle carefully. quickly fluffy th +9154|1|O|357345.46|1997-06-23|4-NOT SPECIFIED|Clerk#000000328|0|y ironic packages cajole. blithely final depende +9155|355|F|83263.25|1992-08-31|1-URGENT|Clerk#000000253|0|ickly regular requests sleep alongside of the car +9156|154|F|135183.22|1994-02-07|1-URGENT|Clerk#000000387|0|deposits. dependencies wake ca +9157|595|F|52660.33|1992-06-20|5-LOW|Clerk#000000736|0|requests detect furiously special, silent packages. carefu +9158|271|F|96814.40|1995-04-25|4-NOT SPECIFIED|Clerk#000000195|0|ecial, even packages. even foxes print. regu +9159|1135|O|99594.61|1995-07-26|1-URGENT|Clerk#000000892|0|xcuses. quickly ironic deposits wake alongside of the quickly pending p +9184|1156|O|56334.07|1997-07-19|1-URGENT|Clerk#000000086|0|blithely final packages haggle according to the slyly quick pack +9185|145|F|64122.78|1994-06-16|2-HIGH|Clerk#000000951|0|leep carefully blithely regular orbits. blithely regular foxes cajol +9186|457|F|167929.61|1992-03-30|5-LOW|Clerk#000000044|0|lar, silent asymptotes haggl +9187|769|F|212469.45|1994-08-22|2-HIGH|Clerk#000000985|0|lithely ironic theodolites. furiously ironic instructions print along +9188|619|O|224857.18|1998-01-25|1-URGENT|Clerk#000000765|0|aggle quickly above the accounts. excuses +9189|1069|O|109530.95|1996-12-02|3-MEDIUM|Clerk#000000501|0|r waters haggle furiously fluffily ironic id +9190|460|O|272754.44|1998-03-03|2-HIGH|Clerk#000000196|0|side of the permanently ironic courts unwind +9191|535|O|21182.03|1996-03-24|3-MEDIUM|Clerk#000000095|0|final packages wake carefully. +9216|643|O|147294.33|1995-04-15|3-MEDIUM|Clerk#000000320|0|its nag regular deposits. slyly even reques +9217|1489|O|117161.58|1997-05-26|1-URGENT|Clerk#000000051|0| above the blithely regular d +9218|241|O|31407.74|1997-12-10|4-NOT SPECIFIED|Clerk#000000795|0|hely regular foxes are alongside of the furiously regular deposit +9219|412|F|205446.61|1994-09-29|5-LOW|Clerk#000000382|0|nst the furiously regular dinos. regular asymptotes against the slyly fina +9220|482|O|992.46|1998-04-07|1-URGENT|Clerk#000000880|0|y bravely ironic deposits. furiously unusual sentiments about the fluffily ir +9221|85|F|273797.07|1995-01-04|5-LOW|Clerk#000000240|0|ess accounts sleep carefully. carefully final pinto beans sleep f +9222|211|F|258460.61|1994-02-11|2-HIGH|Clerk#000000148|0|ding to the instructions. regular requests nag f +9223|304|O|215658.19|1997-08-05|4-NOT SPECIFIED|Clerk#000000785|0|ully according to the blithely +9248|1163|F|110964.49|1994-12-24|4-NOT SPECIFIED|Clerk#000000259|0|ids cajole regular, regular dependencies. deposits along the dolphi +9249|1348|F|161815.08|1993-05-20|2-HIGH|Clerk#000000756|0|slyly pending accounts. packages wake c +9250|1345|F|85572.38|1992-08-14|1-URGENT|Clerk#000000535|0|y final packages; carefully pendi +9251|323|F|29910.23|1993-08-30|3-MEDIUM|Clerk#000000374|0|ld requests. deposits use blithely ruthlessly unusual packages. fluffil +9252|412|O|89891.37|1997-12-11|2-HIGH|Clerk#000000454|0|encies affix slyly perma +9253|818|F|255856.03|1992-01-31|1-URGENT|Clerk#000000307|0|es. sometimes regular grouches wa +9254|1276|F|56365.27|1993-05-15|3-MEDIUM|Clerk#000000761|0|r deposits. quickly bold requests use- +9255|472|O|153124.60|1995-12-08|4-NOT SPECIFIED|Clerk#000000476|0|y bold asymptotes-- carefully +9280|1223|O|275205.91|1998-06-12|5-LOW|Clerk#000000022|0|beans alongside of the fluffily express asymptotes integrate +9281|904|F|173278.28|1992-02-24|1-URGENT|Clerk#000000530|0|eep furiously according to the requests; ideas integrate +9282|79|O|34765.35|1995-11-26|4-NOT SPECIFIED|Clerk#000000824|0|ses? carefully express platelets sleep blithely against the blithely specia +9283|1255|F|7798.12|1994-06-03|3-MEDIUM|Clerk#000000859|0|ully even platelets. silent packages +9284|661|F|56207.47|1994-06-14|4-NOT SPECIFIED|Clerk#000000544|0| furiously across the final deposits. quickly ironic requests accordin +9285|1012|F|118683.77|1994-01-03|1-URGENT|Clerk#000000553|0|sts. express accounts snooze; furiously final +9286|505|P|155839.92|1995-04-04|1-URGENT|Clerk#000000557|0|ake. carefully bold packages promise with the +9287|790|O|13525.92|1998-01-02|4-NOT SPECIFIED|Clerk#000000636|0|ously unusual packages. regular foxes detect. blithely slow ideas sl +9312|920|F|226584.81|1992-05-19|4-NOT SPECIFIED|Clerk#000000897|0|ckly slyly regular packages. unusual packages are. regular +9313|1348|O|222818.15|1996-04-06|3-MEDIUM|Clerk#000000926|0|s wake slyly against the slyly express packages. ironic packages +9314|1313|F|14188.37|1995-02-15|4-NOT SPECIFIED|Clerk#000000907|0|eas. blithely regular asymptotes sleep carefully across the slyly even +9315|587|O|16012.39|1998-03-17|3-MEDIUM|Clerk#000000559|0|ackages are furiously alongside of the slyly regular theodolite +9316|1393|O|225240.88|1995-09-18|4-NOT SPECIFIED|Clerk#000000363|0|inal pinto beans haggle c +9317|100|F|156751.98|1994-03-15|4-NOT SPECIFIED|Clerk#000000347|0|aves across the unusual, regular sauternes wake +9318|1463|F|109251.02|1992-07-28|1-URGENT|Clerk#000000738|0|ss courts across the slyly silent foxes are regular, final pac +9319|880|F|104039.47|1992-09-11|1-URGENT|Clerk#000000155|0|. fluffily ironic instructions detect +9344|664|O|348335.72|1995-12-07|5-LOW|Clerk#000000961|0|ial deposits nag blithely alongside of the caref +9345|1376|O|163627.01|1996-01-22|4-NOT SPECIFIED|Clerk#000000126|0|out the daringly ironic packages affix furiously fluffi +9346|917|O|173943.50|1996-10-09|4-NOT SPECIFIED|Clerk#000000088|0|furiously final packages integrate stealthily expres +9347|673|F|162913.90|1992-08-10|5-LOW|Clerk#000000268|0|he gifts. slyly permanent requests +9348|658|O|120413.73|1996-06-07|5-LOW|Clerk#000000416|0|ackages. carefully ironic pinto beans about the close accoun +9349|1414|O|217101.05|1997-08-29|4-NOT SPECIFIED|Clerk#000000804|0|. fluffily final accounts haggle; furiously reg +9350|145|F|255516.01|1992-11-01|1-URGENT|Clerk#000000253|0|ackages doze evenly across the foxes. quickly ironic reques +9351|898|O|81166.06|1996-05-17|5-LOW|Clerk#000000430|0|ven dependencies. furiously ironic dependencies promise along the slyly +9376|835|O|145196.26|1997-07-24|2-HIGH|Clerk#000000348|0|ng the carefully pending ac +9377|340|F|9021.26|1993-04-22|2-HIGH|Clerk#000000466|0|ers above the carefull +9378|457|O|115914.73|1997-10-16|1-URGENT|Clerk#000000014|0|ultipliers wake furiously never special deposits! +9379|350|F|152004.78|1992-01-04|1-URGENT|Clerk#000000764|0|nusual deposits. furiously final packages wake evenly even tithes. qu +9380|887|F|167911.91|1994-08-26|1-URGENT|Clerk#000000962|0| deposits boost along the carefully ironic deposits. express requests use. +9381|1184|O|94270.85|1995-12-18|4-NOT SPECIFIED|Clerk#000000215|0|y final Tiresias are. requests +9382|337|O|150840.29|1996-02-19|1-URGENT|Clerk#000000308|0|l accounts. furiously ironic deposits use. +9383|140|F|180583.64|1994-03-17|4-NOT SPECIFIED|Clerk#000000237|0|uffily final pinto beans cajole ca +9408|184|F|11891.10|1992-10-21|3-MEDIUM|Clerk#000000664|0|xes cajole carefully furiously final pains. carefully express accou +9409|970|F|155483.25|1992-05-06|1-URGENT|Clerk#000000300|0|ly express platelets above the sl +9410|787|O|88246.41|1997-07-18|5-LOW|Clerk#000000985|0|theodolites solve fluffily. blithely iron +9411|661|F|55576.82|1995-02-07|2-HIGH|Clerk#000000594|0|rses. furiously regular requests haggl +9412|1216|O|245785.65|1998-07-14|2-HIGH|Clerk#000000016|0|requests. carefully regular packages play carefully pending dependencies. ca +9413|148|O|150237.99|1995-07-13|5-LOW|Clerk#000000202|0|latelets are blithely requests. ironic packages boost slyly across t +9414|1333|F|98169.43|1993-09-10|3-MEDIUM|Clerk#000000661|0|above the slyly ironic +9415|1049|F|241463.63|1992-08-24|1-URGENT|Clerk#000000311|0|ccounts boost blithely. final +9440|643|F|4331.68|1994-06-08|5-LOW|Clerk#000000711|0| requests. regular, final pinto beans are. furiously regular accounts det +9441|334|O|3216.31|1997-06-18|4-NOT SPECIFIED|Clerk#000000381|0|iously final deposits. express, regular waters haggle sl +9442|1267|F|103119.65|1993-03-11|4-NOT SPECIFIED|Clerk#000000948|0|hely special courts. furiously final foxes sleep quickly. quick, +9443|304|O|166940.25|1997-05-07|4-NOT SPECIFIED|Clerk#000000317|0|y along the carefully reg +9444|106|O|36255.65|1996-07-18|2-HIGH|Clerk#000000387|0| quickly. always silent platelets must sleep f +9445|928|O|76754.58|1997-11-14|4-NOT SPECIFIED|Clerk#000000394|0|as. slyly ironic deposits along +9446|1358|O|216362.20|1997-12-29|1-URGENT|Clerk#000000173|0|ake pinto beans. slyly f +9447|1162|O|79483.65|1995-06-19|2-HIGH|Clerk#000000115|0|theodolites haggle carefully instructio +9472|481|O|44176.66|1995-06-17|1-URGENT|Clerk#000000979|0|bove the quickly final deposits are carefully +9473|23|F|212682.92|1992-10-12|4-NOT SPECIFIED|Clerk#000000541|0|ts sleep above the accounts. slyly final deposits are regularly. r +9474|133|P|246662.69|1995-05-12|3-MEDIUM|Clerk#000000710|0|ely final requests: dependencies cajole slyly. slyly +9475|1442|O|206441.11|1996-11-22|2-HIGH|Clerk#000000233|0| notornis. ironically even instructions en +9476|1283|F|177524.44|1994-05-26|4-NOT SPECIFIED|Clerk#000000088|0|e slyly final requests might integrate carefully against the slyly express p +9477|170|O|269394.57|1998-03-19|3-MEDIUM|Clerk#000000812|0|lites along the even deposits use bold pinto beans. regular requests +9478|940|F|173044.15|1994-03-29|2-HIGH|Clerk#000000033|0|ound the blithely express instructions. furiously +9479|1373|F|76316.92|1994-09-22|3-MEDIUM|Clerk#000000047|0|ter the carefully ironic +9504|736|F|171165.10|1992-11-26|3-MEDIUM|Clerk#000000902|0|among the quickly bold deposits haggle exp +9505|316|F|283831.70|1992-06-08|2-HIGH|Clerk#000000873|0|hely ironic asymptot +9506|1232|F|47720.50|1994-02-11|4-NOT SPECIFIED|Clerk#000000441|0|carefully ironic accou +9507|517|F|34161.51|1994-11-30|5-LOW|Clerk#000000438|0|press pinto beans are slyly. final packages cajole. quickly regular excus +9508|448|O|235237.15|1996-04-22|5-LOW|Clerk#000000312|0|ss attainments slee +9509|37|F|224330.32|1992-10-08|4-NOT SPECIFIED|Clerk#000000350|0|iously final instructions sleep fu +9510|235|O|93930.42|1996-11-20|5-LOW|Clerk#000000302|0|packages sleep furiously. bold theodolites haggle slyly. ironic, +9511|1141|O|96086.28|1996-08-01|5-LOW|Clerk#000000555|0|out the packages may +9536|1138|O|105639.69|1997-08-20|4-NOT SPECIFIED|Clerk#000000224|0|. slyly even ideas doubt slyly. slowly regular orbits cajole. fur +9537|806|F|249384.96|1995-02-14|4-NOT SPECIFIED|Clerk#000000203|0| packages. final, regular foxes haggle bli +9538|1399|F|32388.43|1994-03-11|4-NOT SPECIFIED|Clerk#000000040|0|ly. slyly final accounts nag carefully regular ideas. blithely ironic theodo +9539|262|O|26683.19|1995-11-15|2-HIGH|Clerk#000000917|0|iously ironic deposits affix furiously alongside of the slyly even foxes. even +9540|784|F|96163.55|1994-06-11|1-URGENT|Clerk#000000048|0|t above the stealthily bold theodolites +9541|598|F|105885.33|1992-03-26|4-NOT SPECIFIED|Clerk#000000840|0|xcuses dazzle furiously regular the +9542|1147|O|121584.41|1995-12-16|2-HIGH|Clerk#000000349|0|theodolites. blithely pendin +9543|850|F|145441.29|1992-05-10|1-URGENT|Clerk#000000187|0| unusual warhorses cajole +9568|619|F|80658.16|1993-03-08|4-NOT SPECIFIED|Clerk#000000270|0|ng the quickly unusual pinto beans sublate blithely ca +9569|1264|O|210401.62|1997-11-01|2-HIGH|Clerk#000000856|0|pecial deposits after the final, pending packages wake carefully +9570|1435|O|79124.61|1996-06-04|2-HIGH|Clerk#000000397|0|ccounts. foxes nag special, special theodolites +9571|1366|O|58131.32|1996-04-30|4-NOT SPECIFIED|Clerk#000000263|0| furiously express requests. even requests are. carefully final a +9572|49|O|85669.13|1998-03-28|4-NOT SPECIFIED|Clerk#000000452|0|atelets. slyly regular requests nag quickly ev +9573|1361|F|140154.64|1992-06-14|3-MEDIUM|Clerk#000000250|0|ix carefully busily unusual deposits. thin excuses haggle quickly. quickly +9574|790|O|145838.53|1995-07-31|3-MEDIUM|Clerk#000000814|0|efully regular platelets. pending packages unwind carefully among the fur +9575|916|F|27475.15|1992-03-31|5-LOW|Clerk#000000133|0|nts haggle busily unusual, even packages. regular packages u +9600|536|F|99615.09|1993-11-08|4-NOT SPECIFIED|Clerk#000000467|0|he unusual, ironic requests nag furiously ironic accounts +9601|1435|O|143520.49|1996-03-20|1-URGENT|Clerk#000000677|0|ugh the slyly regular requests. furiously even pinto beans are blithely slyl +9602|1481|F|193843.49|1992-11-11|1-URGENT|Clerk#000000086|0| across the slyly ironic ideas. carefully unusual requests +9603|1204|O|315928.32|1998-01-09|5-LOW|Clerk#000000191|0|ng the quickly special requests caj +9604|620|O|48743.62|1996-06-25|2-HIGH|Clerk#000000414|0|usly ironic theodolites! blithely final ideas +9605|1220|F|113112.29|1992-12-26|4-NOT SPECIFIED|Clerk#000000777|0|yly bold pinto beans are furiously packages. slyly express courts play +9606|152|F|149838.50|1994-07-28|4-NOT SPECIFIED|Clerk#000000474|0| above the always regular pinto beans. special, unusual accounts grow. pending +9607|643|O|44978.35|1995-12-18|1-URGENT|Clerk#000000752|0| ironic requests are carefully. silent +9632|1429|F|146044.97|1992-01-17|5-LOW|Clerk#000000857|0|y ironic theodolites are silent foxes. blithely final plate +9633|1336|O|191021.09|1995-09-12|4-NOT SPECIFIED|Clerk#000000918|0|ns around the slyly ironic pinto beans cajole carefully ironic depths. careful +9634|958|O|314926.50|1998-01-13|2-HIGH|Clerk#000000166|0| carefully. slyly ironic courts mold. ironic +9635|847|F|168349.65|1994-04-14|1-URGENT|Clerk#000000127|0|the quickly ironic ideas sleep at the quickly +9636|304|O|109568.95|1997-01-30|1-URGENT|Clerk#000000263|0|lar foxes are requests. quickly even pinto be +9637|1411|F|112613.87|1994-01-04|5-LOW|Clerk#000000953|0|s. furiously final requests believe furiously against the brave +9638|1126|O|112055.66|1996-06-08|2-HIGH|Clerk#000000953|0|requests after the furiously unusual accounts integrate slyly u +9639|722|F|244899.69|1993-09-06|4-NOT SPECIFIED|Clerk#000000666|0|press, express pinto +9664|310|F|105001.15|1993-04-08|2-HIGH|Clerk#000000715|0|ccounts across the slyly ironic pinto be +9665|1067|F|81734.81|1994-04-24|5-LOW|Clerk#000000277|0|sleep furiously carefully ironic foxes. pinto beans wake. final deposits caj +9666|221|O|240666.92|1996-05-09|1-URGENT|Clerk#000000511|0|ss the fluffily express tithes. +9667|1102|O|208860.66|1996-02-24|3-MEDIUM|Clerk#000000142|0|nal instructions. special accounts along the regular +9668|847|F|77447.46|1994-09-07|5-LOW|Clerk#000000469|0|refully ironic accounts. furiously bold packages a +9669|619|F|79738.94|1994-04-23|3-MEDIUM|Clerk#000000297|0|deposits promise blithely ironic theodolites. fluffily bold requests +9670|1387|O|200921.16|1997-11-08|3-MEDIUM|Clerk#000000035|0|unts? furiously express deposits are blithely. regular, special forges sle +9671|136|O|157241.36|1995-09-13|2-HIGH|Clerk#000000417|0|ages boost slyly against the furiously +9696|575|F|211382.08|1995-02-20|4-NOT SPECIFIED|Clerk#000000971|0|xpress requests would are pinto beans. +9697|164|F|174800.10|1995-01-27|3-MEDIUM|Clerk#000000432|0|courts are. even platelets was alongside of +9698|1487|O|7676.88|1995-08-07|2-HIGH|Clerk#000000040|0| around the quickly bold packages sle +9699|875|F|10782.39|1995-03-12|3-MEDIUM|Clerk#000000853|0|kly regular platelets. slyly silent accounts alongside of the blithely r +9700|544|O|266611.98|1995-08-09|1-URGENT|Clerk#000000137|0|althy pinto beans wake blithely. qui +9701|112|F|277385.28|1993-02-28|5-LOW|Clerk#000000399|0|bold deposits cajole furiously bold requests. even excuses +9702|1201|O|182347.71|1996-08-22|3-MEDIUM|Clerk#000000852|0|tions haggle slyly among the ironic theodolites. blithel +9703|1126|F|28954.25|1994-10-07|5-LOW|Clerk#000000101|0|realms wake. express, ironic accou +9728|826|F|39398.24|1993-07-03|5-LOW|Clerk#000000647|0|ng requests. fluffily enticing re +9729|970|O|162532.59|1996-07-06|3-MEDIUM|Clerk#000000148|0|ndencies about the care +9730|143|O|278148.33|1997-03-04|5-LOW|Clerk#000000743|0| final dependencies doze furiously slyly silent ideas? furiousl +9731|283|F|21613.76|1993-10-21|5-LOW|Clerk#000000586|0| dolphins nag slyly even deposits-- blithely +9732|820|P|69634.87|1995-03-14|4-NOT SPECIFIED|Clerk#000000599|0|f the special, even instructions. carefully final requests use along the +9733|1000|F|72374.84|1994-03-18|4-NOT SPECIFIED|Clerk#000000997|0|n dolphins haggle. slyly express accounts wake carefully final asymptotes. qui +9734|835|O|124297.04|1997-02-03|1-URGENT|Clerk#000000086|0|equests affix quietly bold deposits. dependencies affix among the quietly +9735|337|O|115276.76|1997-06-28|4-NOT SPECIFIED|Clerk#000000454|0|nic foxes. accounts detect fur +9760|1181|O|158777.10|1998-04-14|5-LOW|Clerk#000000207|0|anent accounts. accounts sleep carefully slyl +9761|433|F|70880.34|1992-01-23|4-NOT SPECIFIED|Clerk#000000468|0| permanent requests. furious requests nag blithely about the q +9762|1492|F|238951.03|1994-01-04|2-HIGH|Clerk#000000861|0|ic requests cajole quickly unusual accounts. regular foxes are blithely. in +9763|1492|O|132201.56|1995-08-14|3-MEDIUM|Clerk#000000374|0| requests detect carefull +9764|1256|F|56685.16|1992-12-30|1-URGENT|Clerk#000000289|0|nts. platelets wake blithe +9765|1153|F|45183.21|1992-10-13|5-LOW|Clerk#000000364|0|ts. even pinto beans haggle alongside of the theodolites. +9766|235|F|165508.82|1992-08-15|1-URGENT|Clerk#000000265|0|s excuses cajole quickly. regul +9767|973|F|46852.11|1994-06-28|5-LOW|Clerk#000000546|0|asymptotes hinder blithely after the busily final fo +9792|1114|O|171667.54|1995-07-24|5-LOW|Clerk#000000929|0| the special accounts. carefully special ideas mainta +9793|1198|F|80712.82|1992-04-04|3-MEDIUM|Clerk#000000770|0| carefully ironic courts haggle evenly. carefully final requests ca +9794|505|F|216443.67|1992-03-25|4-NOT SPECIFIED|Clerk#000000852|0|dolites grow furiously fluffily final requests. blithely special +9795|370|O|215242.29|1998-02-04|3-MEDIUM|Clerk#000000481|0|ng the furiously iron +9796|1052|F|246896.17|1993-09-11|1-URGENT|Clerk#000000150|0|lyly regular packages. furio +9797|43|F|209264.66|1993-09-13|1-URGENT|Clerk#000000296|0|packages. blithe requests affix quickly carefully unusual ideas. blithe +9798|1135|O|23604.81|1996-03-09|1-URGENT|Clerk#000000485|0|ial deposits. accounts detect dependencies. silent accounts cajole flu +9799|461|O|152265.02|1996-04-07|4-NOT SPECIFIED|Clerk#000000526|0|ully final requests cajole carefully according to t +9824|472|F|240691.30|1995-01-23|1-URGENT|Clerk#000000653|0|furiously even theodolites impress even, special asymptotes. idle ideas dazzl +9825|28|O|93645.30|1996-04-09|1-URGENT|Clerk#000000990|0|rding to the pending +9826|698|F|105223.73|1992-03-23|3-MEDIUM|Clerk#000000777|0|deas haggle slyly final reques +9827|1289|O|36448.45|1998-07-04|4-NOT SPECIFIED|Clerk#000000085|0|e unusual dependencies. regular accounts alongside of the quickly regular f +9828|1306|F|269649.39|1992-04-25|3-MEDIUM|Clerk#000000355|0| deposits are carefully bold notornis. blith +9829|1379|O|6613.63|1995-12-09|1-URGENT|Clerk#000000004|0|ke across the requests. silently final foxes wake never amo +9830|493|O|202703.99|1997-09-08|2-HIGH|Clerk#000000191|0|final packages are furiously beside the quickly final e +9831|790|O|86410.08|1996-06-20|4-NOT SPECIFIED|Clerk#000000010|0|mas above the even instructions haggle ironical +9856|802|F|236403.75|1993-05-30|3-MEDIUM|Clerk#000000278|0|usual tithes against the express requests sleep across t +9857|172|F|158381.98|1993-05-12|2-HIGH|Clerk#000000627|0|ons haggle quickly above the blithely regular sauternes. slyly express instru +9858|1399|O|103920.84|1997-12-08|3-MEDIUM|Clerk#000000432|0|e of the fluffily final packa +9859|475|O|247788.34|1996-07-28|3-MEDIUM|Clerk#000000989|0|xes boost slyly. furiously regul +9860|623|F|151734.45|1993-10-11|1-URGENT|Clerk#000000345|0|carefully. ironic ideas haggle theodolites. quickly speci +9861|1477|F|66189.04|1992-10-29|5-LOW|Clerk#000000113|0|le after the unusual deposits. even acc +9862|10|O|193015.83|1997-10-10|2-HIGH|Clerk#000000168|0|among the instructions was after the slyly special packages. final, final hoc +9863|247|O|362398.22|1995-09-05|1-URGENT|Clerk#000000473|0|urts nag finally even, stealthy instructions. quickly final ideas +9888|1319|F|74228.41|1994-09-13|5-LOW|Clerk#000000434|0|g to the carefully final foxes. fur +9889|82|F|35362.96|1994-09-09|3-MEDIUM|Clerk#000000786|0|lly atop the foxes. doggedly final packages integrate thin +9890|731|P|87423.78|1995-02-22|2-HIGH|Clerk#000000168|0|uickly silent theodolites. pe +9891|1093|P|61268.10|1995-06-09|1-URGENT|Clerk#000000544|0|ut the theodolites. bold, even grouches across t +9892|691|F|16104.32|1992-07-17|3-MEDIUM|Clerk#000000387|0|ts. blithe deposits wake carefully carefully +9893|412|F|105380.78|1994-08-17|3-MEDIUM|Clerk#000000931|0|y special dependencies run +9894|851|F|100473.64|1994-03-19|2-HIGH|Clerk#000000424|0| asymptotes along the regular, bold instructions eat quickly again +9895|142|F|245503.17|1993-04-21|5-LOW|Clerk#000000965|0|lithely. furiously even pinto beans h +9920|1073|O|75014.21|1996-06-06|1-URGENT|Clerk#000000007|0|ites. special requests believe against the furiously regular requests. furiou +9921|1379|P|143610.80|1995-05-15|5-LOW|Clerk#000000936|0|r, blithe deposits. furiously bold +9922|802|P|186264.65|1995-04-04|4-NOT SPECIFIED|Clerk#000000131|0|ajole blithely across the unusual, unusual packages. car +9923|1217|F|223804.09|1994-10-06|2-HIGH|Clerk#000000818|0|instructions use slyl +9924|799|O|192545.87|1997-05-09|4-NOT SPECIFIED|Clerk#000000639|0|onic excuses wake slyly +9925|52|F|296109.93|1992-01-31|1-URGENT|Clerk#000000751|0|ve the always ironic pinto bean +9926|254|F|225023.94|1994-10-12|2-HIGH|Clerk#000000090|0|sits believe carefully ironic pinto beans. sl +9927|13|O|238640.42|1995-08-17|2-HIGH|Clerk#000000388|0|sts sleep regular, dogged packages. s +9952|521|F|87414.24|1992-05-02|2-HIGH|Clerk#000000549|0|ully about the daringly pending idea +9953|946|F|18034.69|1995-02-28|2-HIGH|Clerk#000000364|0|iresias. furiously bold deposits wake. furiously +9954|19|F|207935.24|1994-06-20|4-NOT SPECIFIED|Clerk#000000651|0| furiously express packages. slyly ironic packages nag sly +9955|1010|O|188555.97|1995-09-05|1-URGENT|Clerk#000000588|0|gainst the quickly regular deposits. carefully final accounts are furiously +9956|530|F|38746.89|1993-03-17|2-HIGH|Clerk#000000001|0|s? ironic foxes wake even, ironic de +9957|1465|F|64682.58|1993-12-01|4-NOT SPECIFIED|Clerk#000000874|0| unusual sauternes. fluffily e +9958|764|F|192897.71|1993-11-26|4-NOT SPECIFIED|Clerk#000000199|0| idle depths. quickly even pearls are express theodolites. final pint +9959|689|O|19023.25|1995-09-25|3-MEDIUM|Clerk#000000755|0|y special deposits. slyly final deposits against +9984|376|O|232843.69|1998-07-10|1-URGENT|Clerk#000000161|0|ronic packages-- final packages boost! even, express frets boo +9985|1207|F|82406.34|1993-08-08|5-LOW|Clerk#000000636|0|ing depths boost about the even depo +9986|289|O|150409.70|1997-09-22|3-MEDIUM|Clerk#000000913|0|the ruthlessly regular courts. ironic pack +9987|997|O|241701.18|1995-11-28|5-LOW|Clerk#000000308|0|ding to the regular foxes dazzle slyly f +9988|1372|O|139134.68|1997-12-05|4-NOT SPECIFIED|Clerk#000000015|0|d, final foxes. fluffily even sheaves w +9989|1210|F|113256.41|1993-06-22|3-MEDIUM|Clerk#000000298|0| bold orbits. pinto beans haggle carefully unusual accounts. furiously final +9990|391|F|80673.96|1992-03-28|2-HIGH|Clerk#000000466|0|y express foxes. blithely +9991|823|O|88850.20|1996-06-10|2-HIGH|Clerk#000000542|0|foxes nag fluffily packages. b +10016|1295|F|29180.26|1993-02-02|1-URGENT|Clerk#000000546|0|ptotes. platelets across the blithely regular accounts us +10017|811|O|100168.42|1998-04-09|4-NOT SPECIFIED|Clerk#000000617|0|ly accounts. carefully regular pinto beans wake according to th +10018|307|F|85330.56|1993-06-10|3-MEDIUM|Clerk#000000855|0|ld accounts above the bold, regular requests ha +10019|919|F|169596.33|1994-07-19|4-NOT SPECIFIED|Clerk#000000887|0|ests are carefully blithely ironic instructi +10020|469|O|99184.61|1998-04-08|3-MEDIUM|Clerk#000000162|0|yly against the final warth +10021|1282|F|50708.88|1992-08-01|4-NOT SPECIFIED|Clerk#000000321|0|ide of the slyly even Tiresias. carefully express fox +10022|929|F|71058.00|1994-03-05|5-LOW|Clerk#000000445|0|nto beans. furiously silent deposits nag. bold requests are ironic +10023|1204|O|107965.02|1996-12-02|1-URGENT|Clerk#000000596|0|onically even packages haggle among the slyly brave pin +10048|803|F|63327.47|1994-05-16|4-NOT SPECIFIED|Clerk#000000893|0|nt pinto beans are. ironi +10049|683|O|169774.94|1997-07-23|1-URGENT|Clerk#000000648|0|ly special forges. blithely bo +10050|1046|O|151895.89|1996-09-03|2-HIGH|Clerk#000000530|0|bove the permanently regular multipliers. special req +10051|661|O|168753.53|1996-05-25|2-HIGH|Clerk#000000804|0|ly. quickly unusual de +10052|763|F|195461.73|1994-09-08|4-NOT SPECIFIED|Clerk#000000488|0|carefully final packages. ironic foxes cajo +10053|1441|F|152632.75|1992-01-11|2-HIGH|Clerk#000000508|0|ual deposits haggle against the furiously final realms. b +10054|665|O|111854.62|1995-04-29|2-HIGH|Clerk#000000093|0|furiously regular platele +10055|1276|O|108949.78|1996-02-29|5-LOW|Clerk#000000508|0|e bravely bold notornis. carefully reg +10080|109|F|219815.04|1993-02-13|5-LOW|Clerk#000000362|0|carefully blithely express epitaph +10081|493|F|267898.00|1993-08-08|4-NOT SPECIFIED|Clerk#000000097|0|eans would sleep. carefully iro +10082|1264|F|216021.80|1994-08-31|4-NOT SPECIFIED|Clerk#000000049|0|ayers use special excuses. special req +10083|565|O|55168.12|1995-09-26|5-LOW|Clerk#000000949|0|t the brave decoys sleep regularly among the iron +10084|1424|O|5317.21|1997-07-08|1-URGENT|Clerk#000000088|0|grow blithely packages. slyly final requests cajole; accounts +10085|518|O|224630.63|1996-03-31|4-NOT SPECIFIED|Clerk#000000074|0|o beans wake against the blithely final accounts. fluffily silent f +10086|397|O|51011.55|1995-05-16|5-LOW|Clerk#000000728|0|its wake alongside of the f +10087|404|O|78013.94|1997-03-31|2-HIGH|Clerk#000000001|0|ounts integrate despite the regular ideas. furiously quiet idea +10112|223|F|35243.42|1993-12-21|5-LOW|Clerk#000000586|0| deposits. furiously even asymptotes alongside of the slyly regular +10113|56|F|193866.35|1994-06-13|1-URGENT|Clerk#000000094|0|e quickly. regular accounts boost bravely regular instructions. quickly fina +10114|1064|F|46899.44|1993-02-09|1-URGENT|Clerk#000000757|0|al requests. quickly express de +10115|799|O|144986.20|1998-07-07|2-HIGH|Clerk#000000530|0|even accounts. express ideas +10116|118|O|222761.53|1997-03-26|5-LOW|Clerk#000000991|0|mptotes. carefully express depo +10117|734|F|130230.17|1993-11-17|3-MEDIUM|Clerk#000000343|0|ilent theodolites sleep furiously +10118|742|F|24563.35|1994-04-11|1-URGENT|Clerk#000000431|0|ithely pending foxes integrate across the fin +10119|509|O|51762.72|1996-07-11|3-MEDIUM|Clerk#000000868|0|ar depths. slyly sly theodolites sleep slyly. furiously bold foxes integrate +10144|311|F|235400.84|1995-01-03|1-URGENT|Clerk#000000751|0|ironic accounts cajole blithely around the blithe deposits. ir +10145|646|P|302026.89|1995-05-25|5-LOW|Clerk#000000550|0|y unusual deposits sleep furiously i +10146|994|F|237459.34|1994-05-02|5-LOW|Clerk#000000653|0|hin gifts nag. furiously pending deposits after the sly frets sl +10147|1166|F|203640.84|1993-10-10|2-HIGH|Clerk#000000212|0|ilently ironic pinto beans. +10148|1462|F|140605.75|1994-03-26|5-LOW|Clerk#000000334|0|the bold ideas are carefully ruthlessly special pac +10149|26|F|169118.62|1994-09-24|2-HIGH|Clerk#000000681|0|final sentiments. slyly special bra +10150|1325|F|291469.33|1992-04-30|1-URGENT|Clerk#000000802|0|r the requests sleep s +10151|589|F|10295.06|1992-01-15|1-URGENT|Clerk#000000645|0|ideas. deposits haggle quickly accounts; f +10176|985|O|102621.47|1996-08-26|3-MEDIUM|Clerk#000000456|0|unts. bold accounts are carefully according to the quickly p +10177|568|O|209213.44|1996-06-29|3-MEDIUM|Clerk#000000221|0|nstructions; bold, regular attainments among th +10178|1148|F|46311.36|1993-12-15|4-NOT SPECIFIED|Clerk#000000756|0|ray across the ironic, final dependencies. +10179|1157|O|153533.06|1996-04-30|4-NOT SPECIFIED|Clerk#000000803|0|sly bold packages haggle about the the +10180|712|O|76230.32|1997-03-10|1-URGENT|Clerk#000000743|0|ke blithely carefully even packag +10181|874|O|46249.63|1996-02-13|3-MEDIUM|Clerk#000000866|0|, pending deposits. express +10182|268|F|199446.10|1994-05-25|5-LOW|Clerk#000000304|0|s. slyly final pinto beans wake a +10183|250|F|110520.40|1994-11-25|1-URGENT|Clerk#000000534|0| dependencies. blithely pending requests about the furiously regular pac +10208|1028|O|286549.53|1996-08-26|3-MEDIUM|Clerk#000000259|0| ideas. slow, ironic instructions doze furiou +10209|1210|F|400191.77|1993-11-30|3-MEDIUM|Clerk#000000153|0|ts wake. slyly blithe +10210|937|O|148557.25|1995-06-24|4-NOT SPECIFIED|Clerk#000000573|0|ts. furiously bold ideas about the furiously bold pac +10211|797|O|192242.04|1997-07-29|4-NOT SPECIFIED|Clerk#000000363|0| careful theodolites. special accounts caj +10212|1471|F|126475.34|1993-05-24|5-LOW|Clerk#000000011|0|uickly according to the pending pinto beans. instructions brea +10213|1288|F|42898.55|1995-02-18|2-HIGH|Clerk#000000845|0|ly ironic dependencies. final excuses acros +10214|913|O|145287.98|1996-01-30|2-HIGH|Clerk#000000991|0|encies after the deposits sleep furiously bold packages. even deposits +10215|1031|O|156012.73|1996-08-17|1-URGENT|Clerk#000000770|0|pecial instructions. fluffily regular packa +10240|691|F|41343.99|1994-05-16|4-NOT SPECIFIED|Clerk#000000109|0|al accounts are along the unusual packages. unusual, even platelets use slyl +10241|271|O|54454.72|1997-09-30|5-LOW|Clerk#000000366|0|y unusual asymptotes. regular dependencies wake fluffily about the +10242|101|F|193761.97|1993-12-13|3-MEDIUM|Clerk#000000234|0|s was slyly alongside of the deposits. +10243|385|O|72189.37|1995-12-25|2-HIGH|Clerk#000000844|0|nic requests. boldly regular deposits haggle blithely. orbits integrate +10244|298|O|129419.40|1996-04-04|3-MEDIUM|Clerk#000000459|0|lent pinto beans. furiously iro +10245|587|F|268471.58|1995-02-14|3-MEDIUM|Clerk#000000785|0| beans. foxes haggle around the car +10246|1231|O|188201.88|1997-06-19|1-URGENT|Clerk#000000571|0|s. blithely unusual packages affix according to the hockey players. regular +10247|866|F|187970.24|1993-01-11|3-MEDIUM|Clerk#000000646|0|fully after the carefully pending requests. even, pending ideas alongside +10272|730|F|303855.22|1994-01-18|3-MEDIUM|Clerk#000000680|0| blithely express accounts. slyly regular pinto beans use slyly. +10273|112|O|272748.60|1998-04-24|1-URGENT|Clerk#000000303|0|n, ironic packages. slyly close accounts sleep. blithe +10274|1369|F|50775.14|1993-12-10|1-URGENT|Clerk#000000939|0|sits. fluffily bold requests cajole accounts +10275|83|O|78422.44|1997-05-16|5-LOW|Clerk#000000202|0|fts at the furiously express accounts are whithout the slyly slow deposits. f +10276|1463|O|264683.22|1996-02-24|3-MEDIUM|Clerk#000000706|0|y even deposits. even accounts nag among the ironic asymptotes. req +10277|538|F|139188.55|1994-04-08|3-MEDIUM|Clerk#000000655|0|counts sleep around the special +10278|359|O|162008.27|1995-09-13|5-LOW|Clerk#000000697|0|le quickly. pending, bold theo +10279|1223|O|227770.72|1996-09-22|5-LOW|Clerk#000000051|0|nal deposits. fluffily silent ideas are across the +10304|814|O|302630.21|1995-11-11|3-MEDIUM|Clerk#000000230|0|l deposits nag pending, regular attainments. ironic ideas detect. unusu +10305|25|F|153676.38|1994-07-08|5-LOW|Clerk#000000429|0|phins use furiously about the quickly bold id +10306|152|F|91506.19|1993-07-22|5-LOW|Clerk#000000345|0| slyly never final requests. perm +10307|298|O|230682.65|1998-01-28|4-NOT SPECIFIED|Clerk#000000488|0|yly ironic foxes. quickly regular +10308|413|P|278555.38|1995-04-21|2-HIGH|Clerk#000001000|0|are above the furiously final deposits. special packages nag s +10309|1312|F|215890.35|1994-11-22|5-LOW|Clerk#000000622|0| above the carefully bold packages. carefully even pinto beans mai +10310|1027|F|213874.91|1994-02-06|5-LOW|Clerk#000000645|0| accounts kindle qu +10311|52|F|5195.95|1992-08-18|2-HIGH|Clerk#000000147|0|ntegrate carefully above the regular pinto beans. quick +10336|1358|O|57610.67|1997-06-15|4-NOT SPECIFIED|Clerk#000000519|0|. carefully special pinto beans are ironic accounts. foxes +10337|1360|O|63068.37|1996-03-19|3-MEDIUM|Clerk#000000499|0|ly silent instructions wake qui +10338|1213|O|100334.47|1995-07-15|4-NOT SPECIFIED|Clerk#000000964|0|gular packages. slyly even packages haggle furious +10339|154|O|116081.18|1995-10-12|5-LOW|Clerk#000000585|0|ts. always ironic deposits haggle thinly. +10340|1486|O|243706.09|1995-06-23|2-HIGH|Clerk#000000064|0|hely final warthogs detect blithely regular pa +10341|1276|F|250921.23|1992-12-22|2-HIGH|Clerk#000000964|0|efully final packages cajole f +10342|638|O|273325.12|1995-11-23|3-MEDIUM|Clerk#000000277|0|theodolites. carefully regul +10343|91|F|44177.42|1992-03-27|4-NOT SPECIFIED|Clerk#000000600|0|ackages. carefully pending idea +10368|508|O|64465.48|1996-06-25|3-MEDIUM|Clerk#000000722|0|carefully special theodolites doze. fluffily ironic pinto be +10369|1397|O|120738.63|1995-11-10|5-LOW|Clerk#000000636|0| deposits are quickly; regular requests nag carefully regular i +10370|839|F|112585.48|1994-04-28|4-NOT SPECIFIED|Clerk#000000084|0|thrash. accounts boost never quickly final ac +10371|1022|F|204611.98|1994-09-17|2-HIGH|Clerk#000000231|0|nding requests. ideas af +10372|1241|O|101993.71|1995-06-28|4-NOT SPECIFIED|Clerk#000000276|0|sleep after the carefully ironic platelets. regular, unusual deposits wake qui +10373|671|F|254861.41|1993-06-26|1-URGENT|Clerk#000000681|0|cajole blithely final foxes. carefully +10374|337|F|28405.59|1993-07-23|5-LOW|Clerk#000000885|0|ing courts? carefully unusual ideas +10375|814|O|55990.35|1997-01-08|2-HIGH|Clerk#000000384|0|ending deposits. special, regular tith +10400|230|O|214820.02|1996-10-24|2-HIGH|Clerk#000000375|0|cing accounts sleep slyly regu +10401|1405|O|15159.38|1998-07-20|4-NOT SPECIFIED|Clerk#000000351|0|ts x-ray? slyly unusual a +10402|7|O|69976.43|1997-12-20|1-URGENT|Clerk#000000487|0|ing pinto beans for the carefully regular +10403|820|O|273217.58|1996-05-21|5-LOW|Clerk#000000523|0|ounts. carefully special accounts grow +10404|1255|O|148128.43|1998-03-29|1-URGENT|Clerk#000000142|0|uffy foxes about the qui +10405|929|O|156274.53|1998-01-04|4-NOT SPECIFIED|Clerk#000000343|0|uriously final dolphins. sly +10406|46|O|143470.97|1996-02-29|4-NOT SPECIFIED|Clerk#000000923|0| the slyly express deposits. deposits +10407|442|O|72476.48|1996-03-26|4-NOT SPECIFIED|Clerk#000000011|0|onic foxes. asymptotes across the ironi +10432|1231|F|167753.06|1992-01-06|5-LOW|Clerk#000000429|0|thely bold pinto bea +10433|1295|F|19194.57|1993-02-20|2-HIGH|Clerk#000000566|0|ajole blithely. furiously re +10434|781|F|63237.89|1994-12-24|2-HIGH|Clerk#000000939|0| blithely regular ideas are deposits. requests nod slyly final r +10435|1195|F|185835.34|1993-08-11|3-MEDIUM|Clerk#000000660|0|te. slyly final theodolites are after th +10436|916|F|32528.92|1995-01-03|5-LOW|Clerk#000001000|0|lthily special asymptotes. blithely pending deposits after the unusual, e +10437|305|F|64469.14|1994-08-19|1-URGENT|Clerk#000000098|0|inal requests about the regular, +10438|715|F|189906.48|1992-12-03|5-LOW|Clerk#000000148|0|tect among the blithely +10439|940|F|300103.82|1992-03-29|4-NOT SPECIFIED|Clerk#000000626|0|nal, even requests h +10464|233|F|41683.39|1994-08-11|1-URGENT|Clerk#000000752|0|e slyly after the platelets; furiously even ac +10465|79|O|289512.24|1997-04-10|4-NOT SPECIFIED|Clerk#000000791|0|ic tithes sleep carefully across the furiously ironic ideas. sl +10466|616|F|147826.40|1992-12-26|2-HIGH|Clerk#000000899|0|thely even ideas cajole quickly across the carefu +10467|1088|O|200254.31|1997-03-12|4-NOT SPECIFIED|Clerk#000000125|0|ffily unusual deposits. carefully regular asymptotes use fur +10468|574|F|50946.66|1994-12-12|2-HIGH|Clerk#000000429|0|osits wake-- quickly pending foxes alongside of the slyly even +10469|622|O|89980.03|1996-09-03|2-HIGH|Clerk#000000913|0|hely unusual, unusual accounts. furiously fi +10470|184|F|321900.81|1992-05-05|5-LOW|Clerk#000000632|0|even, ironic accounts among the bold theodolites use across the ste +10471|262|F|309852.68|1992-10-10|2-HIGH|Clerk#000000590|0|lites wake doggedly accounts. blithely final deposits sleep evenly. +10496|400|O|66825.60|1997-02-20|2-HIGH|Clerk#000000907|0|iously regular requests. furiously slow hockey players are quickly even ac +10497|119|O|103079.38|1996-06-22|3-MEDIUM|Clerk#000000423|0|ar hockey players sleep furiously until the furious +10498|1081|F|146950.27|1993-10-24|5-LOW|Clerk#000000424|0|lithely bold packages. re +10499|872|F|186269.45|1993-11-17|4-NOT SPECIFIED|Clerk#000000065|0|es haggle slyly even instructions. ironica +10500|998|F|26808.34|1994-01-24|2-HIGH|Clerk#000000179|0| packages wake quickly pearls. slyly even deposits haggle blithe +10501|911|O|227512.69|1998-07-03|3-MEDIUM|Clerk#000000977|0|equests. packages nag slyly. quickly even accounts toward the ironic +10502|1462|F|177583.01|1993-05-15|4-NOT SPECIFIED|Clerk#000000530|0|tructions alongside of the blithely bold foxes could have to sleep slyly a +10503|853|O|150884.39|1996-06-09|5-LOW|Clerk#000000028|0|eodolites play against the pending accounts. special packages are slyly ab +10528|166|F|127054.41|1994-09-14|3-MEDIUM|Clerk#000000724|0|press pinto beans. express theodolites do cajole furiously. slyly f +10529|692|O|141709.31|1997-10-18|1-URGENT|Clerk#000000573|0|yly. doggedly final epitaphs haggle among the flu +10530|1276|F|120484.95|1994-01-28|3-MEDIUM|Clerk#000000879|0|ounts. blithely unus +10531|55|F|176261.61|1992-03-19|2-HIGH|Clerk#000000021|0|regular somas. fluffily special instructions doze blithely. quick +10532|1337|O|318050.97|1997-11-28|5-LOW|Clerk#000000805|0|ly slyly bold accounts. carefully express theodolites nag +10533|961|O|186070.73|1998-05-01|3-MEDIUM|Clerk#000000778|0| nag busily bold dependencies. special, ironic p +10534|1070|F|4438.69|1993-04-19|4-NOT SPECIFIED|Clerk#000000973|0|ly according to the slyly r +10535|1225|O|249751.99|1995-05-28|5-LOW|Clerk#000000967|0|lyly unusual frets nag alongsi +10560|91|O|185333.40|1997-07-29|1-URGENT|Clerk#000000157|0|lar requests among the blithely regular packages doze unusual requests; +10561|718|O|219244.25|1997-04-27|5-LOW|Clerk#000000435|0|r requests. even, even deposits b +10562|1246|F|297373.68|1994-11-12|4-NOT SPECIFIED|Clerk#000000034|0|ests across the courts print r +10563|2|F|143707.70|1993-09-30|1-URGENT|Clerk#000000889|0|etect after the pending requests. packa +10564|1019|O|77547.24|1996-03-14|4-NOT SPECIFIED|Clerk#000000362|0|ests. final, express foxes are slyly regular ideas. darin +10565|613|O|138255.60|1997-08-17|1-URGENT|Clerk#000000126|0| slyly unusual deposits after the carefully +10566|578|O|220319.71|1995-08-20|4-NOT SPECIFIED|Clerk#000000541|0|s sleep blithely permanently even ideas. bl +10567|328|F|104838.06|1992-03-30|2-HIGH|Clerk#000000046|0|y even pinto beans cajole bold instructions. carefully sly wate +10592|778|O|84645.88|1995-11-04|2-HIGH|Clerk#000000435|0|as-- ironic packages +10593|1123|F|160662.68|1992-02-13|2-HIGH|Clerk#000000573|0|excuses after the fina +10594|214|O|6650.94|1996-03-21|3-MEDIUM|Clerk#000000126|0|ly express asymptotes against th +10595|818|O|23233.65|1997-11-22|3-MEDIUM|Clerk#000000425|0|gular excuses. slowly ca +10596|308|O|106243.04|1997-03-31|5-LOW|Clerk#000000662|0|oss the furiously regular theodolit +10597|619|O|67904.94|1996-09-13|2-HIGH|Clerk#000000040|0|ch. bold ideas about the deposits wake fluffily +10598|461|F|19331.61|1992-03-08|4-NOT SPECIFIED|Clerk#000000682|0|e among the fluffily regular deposits. slyly final requests haggle furious +10599|194|O|142776.50|1997-07-21|4-NOT SPECIFIED|Clerk#000000559|0|ly regular requests wake regular instructions. pending, pending dolphins +10624|1288|F|192178.14|1994-12-21|1-URGENT|Clerk#000000666|0|re furiously along the slyly final ideas. carefu +10625|259|O|233381.66|1996-01-30|1-URGENT|Clerk#000000688|0|. pending deposits above the car +10626|997|O|19103.82|1995-12-14|3-MEDIUM|Clerk#000000656|0| regular deposits cajo +10627|127|F|210497.85|1993-02-25|5-LOW|Clerk#000000236|0|s. unusual instructions are. furiously express requests a +10628|1429|O|5714.19|1998-06-28|4-NOT SPECIFIED|Clerk#000000437|0|etimes quickly final packa +10629|650|F|55072.00|1994-09-12|1-URGENT|Clerk#000000229|0|endencies wake. accounts are carefully. a +10630|313|F|143006.19|1993-02-05|3-MEDIUM|Clerk#000000607|0|iously special instruct +10631|1243|F|258430.09|1993-05-27|1-URGENT|Clerk#000000844|0|affix blithely blithely regular dinos. furiously blithe instructions ar +10656|371|O|96681.23|1995-10-25|1-URGENT|Clerk#000000233|0| accounts use never blithely bold deposits. i +10657|734|F|91096.35|1993-09-26|3-MEDIUM|Clerk#000000502|0|ts wake. bold packages cajole fluffily according to the furi +10658|1199|F|117872.35|1994-08-28|5-LOW|Clerk#000000204|0|xes cajole thinly ironic requests. theodolites +10659|397|F|290769.79|1994-05-15|1-URGENT|Clerk#000000587|0| slyly across the bold request +10660|469|O|135068.75|1998-05-01|2-HIGH|Clerk#000000352|0|onic depths? furiously +10661|179|F|90250.70|1994-01-24|4-NOT SPECIFIED|Clerk#000000986|0| about the final foxes. eve +10662|1420|P|157252.72|1995-05-13|5-LOW|Clerk#000000241|0|tain blithely quickly regular pinto beans. furiously bold deposits +10663|317|F|153682.58|1994-05-24|2-HIGH|Clerk#000000137|0|s above the furiously final foxes nag idly requests. caref +10688|4|F|43453.24|1992-05-13|3-MEDIUM|Clerk#000000226|0|ly ironic instructions lose quickly alongside of the carefully +10689|203|O|99242.62|1996-07-23|5-LOW|Clerk#000000436|0|usly. furiously ironic instructions wak +10690|103|O|54775.41|1997-12-15|5-LOW|Clerk#000000041|0|ltipliers cajole slyly busy accounts. express theodolites af +10691|664|F|87254.45|1995-03-14|3-MEDIUM|Clerk#000000536|0|al decoys among the carefull +10692|187|F|158201.74|1994-07-27|5-LOW|Clerk#000000832|0|orbits. asymptotes cajole. furiously eve +10693|1030|F|43518.47|1995-04-17|4-NOT SPECIFIED|Clerk#000000797|0|s. slyly regular accounts are among the slyly regular sentiments. +10694|1423|O|183151.32|1997-12-05|2-HIGH|Clerk#000000812|0|olites. quickly bold package +10695|1456|P|93566.64|1995-05-03|2-HIGH|Clerk#000000039|0| asymptotes. quickly unus +10720|736|O|89368.05|1998-03-31|2-HIGH|Clerk#000000597|0|ccounts sleep bold, even theodol +10721|781|O|107381.35|1996-02-27|5-LOW|Clerk#000000599|0|haggle slyly blithely even instructions. quickly even dolphins wa +10722|79|F|218680.31|1995-01-20|4-NOT SPECIFIED|Clerk#000000743|0|ding instructions print. f +10723|1040|O|69126.13|1998-05-21|3-MEDIUM|Clerk#000000144|0| bold accounts. carefully busy platelets sleep fluffily. spe +10724|1492|F|215958.98|1994-09-14|2-HIGH|Clerk#000000165|0|furiously regular dolphins. regular foxes along the daringly express +10725|1444|O|77193.41|1998-04-09|5-LOW|Clerk#000000505|0| carefully unusual sauternes after the fluffily regular foxes use pending, +10726|164|F|215356.45|1993-04-25|4-NOT SPECIFIED|Clerk#000000210|0| regular dependencies. quickly spe +10727|496|F|311532.26|1992-08-05|5-LOW|Clerk#000000396|0|nusual pinto beans. special, pending requests breach slyly fina +10752|199|O|223930.05|1995-09-11|1-URGENT|Clerk#000000610|0|ic accounts. carefully ironic courts against the caref +10753|1430|F|20768.66|1994-05-02|1-URGENT|Clerk#000000218|0|ously ironic packag +10754|1061|F|229997.58|1993-03-18|5-LOW|Clerk#000000827|0|r pinto beans sleep even +10755|1435|F|132981.98|1993-07-15|1-URGENT|Clerk#000000257|0|se furiously excuses. always unusual packages above the furiously unusual de +10756|1087|F|40769.85|1992-04-15|2-HIGH|Clerk#000000994|0| even, express platelets nag above +10757|128|O|92703.05|1998-06-06|4-NOT SPECIFIED|Clerk#000001000|0|patterns haggle quickly across the bravely +10758|368|O|136484.05|1996-11-15|2-HIGH|Clerk#000000209|0|es. pinto beans sleep carefully final +10759|34|O|54534.36|1996-09-22|4-NOT SPECIFIED|Clerk#000000258|0| boost evenly final pinto beans. +10784|1396|F|184632.93|1993-07-06|4-NOT SPECIFIED|Clerk#000000982|0|en packages sleep. final foxes detec +10785|148|F|1508.63|1992-06-26|3-MEDIUM|Clerk#000000948|0|iously unusual packages use quickly furiously +10786|154|O|70962.05|1995-08-06|3-MEDIUM|Clerk#000000705|0| ironic, special theodolites caj +10787|1117|O|372954.40|1997-02-12|2-HIGH|Clerk#000000133|0|ckages could have to wake blithely above the final requests. furiously +10788|4|O|147767.08|1997-01-15|3-MEDIUM|Clerk#000000905|0|esides the slyly ironic dependencies. ironic foxes cajole fur +10789|1378|F|93918.24|1993-08-24|4-NOT SPECIFIED|Clerk#000000463|0|s unwind blithely agains +10790|113|F|77512.26|1994-12-15|5-LOW|Clerk#000000381|0|ly alongside of the express, regular foxes. req +10791|319|O|173850.27|1995-08-20|4-NOT SPECIFIED|Clerk#000000131|0|efully special pinto beans dazzle fluffily according to the express, silen +10816|1303|O|45628.88|1996-01-11|2-HIGH|Clerk#000000003|0|after the final, spe +10817|712|O|213714.56|1996-12-09|1-URGENT|Clerk#000000852|0|final ideas across the +10818|157|O|245383.91|1998-05-07|2-HIGH|Clerk#000000735|0|ids nag carefully against the final deposit +10819|571|F|79971.29|1993-08-25|1-URGENT|Clerk#000000144|0|ncies use furiously alongside of the fluffily final instructions. quickly re +10820|661|O|220224.56|1995-12-28|4-NOT SPECIFIED|Clerk#000000630|0|ecial ideas. silently unusual somas are blith +10821|590|O|179780.96|1996-05-13|2-HIGH|Clerk#000000856|0| the furiously final excuses. blithely final pack +10822|1186|F|19208.70|1993-12-01|5-LOW|Clerk#000000046|0|hely regular requests. carefully silent instructions use slyly f +10823|391|F|109958.79|1992-06-13|5-LOW|Clerk#000000869|0|blithely boldly pending deposits. silent hockey players acros +10848|841|O|67233.17|1996-10-26|3-MEDIUM|Clerk#000000131|0| according to the boldly final accounts. slyly bold asymptotes detect qui +10849|56|O|309269.38|1997-01-31|1-URGENT|Clerk#000000279|0|y even requests. blithely silent theodolites cajole carefully ev +10850|1052|O|78474.67|1996-09-23|2-HIGH|Clerk#000000055|0|its cajole quickly. permanently even pinto beans dazz +10851|1201|F|256653.25|1994-04-07|2-HIGH|Clerk#000000841|0|ffix blithely blithely even dugouts? quickly re +10852|559|F|290873.68|1993-10-27|2-HIGH|Clerk#000000623|0|oxes. carefully final pinto be +10853|275|F|68787.35|1994-01-06|4-NOT SPECIFIED|Clerk#000000276|0|ronic dugouts wake s +10854|917|O|4885.38|1998-06-20|2-HIGH|Clerk#000000219|0|old, ironic dependencies. fluffily bold excuses shall have to integrate amon +10855|608|O|227086.67|1997-07-16|1-URGENT|Clerk#000000149|0|fully unusual pinto beans sleep sl +10880|278|F|40046.10|1992-05-23|4-NOT SPECIFIED|Clerk#000000553|0|e furiously bold deposits. slyly spe +10881|1001|F|235385.68|1994-02-16|1-URGENT|Clerk#000000872|0|quickly final pinto beans engage quickly pending, final +10882|1462|O|103982.52|1998-06-02|5-LOW|Clerk#000000949|0|gouts sleep fluffily according to the dep +10883|226|O|118687.62|1998-02-03|5-LOW|Clerk#000000759|0|sly silent accounts. carefully express pinto bean +10884|749|F|193592.93|1994-11-26|5-LOW|Clerk#000000802|0| express, regular accounts nag furiously! platele +10885|991|O|253167.35|1998-04-18|5-LOW|Clerk#000000893|0|thely ironic accounts sleep carefully depo +10886|1312|F|275313.31|1994-08-24|1-URGENT|Clerk#000000422|0|along the final epitaphs dazzle carefull +10887|436|O|50293.15|1995-05-26|4-NOT SPECIFIED|Clerk#000000575|0|ag against the dependencies. furiously regular foxes sleep fu +10912|293|O|243339.25|1996-12-25|1-URGENT|Clerk#000000579|0|odolites wake sometimes on the unusual deposits. epitaphs cajole b +10913|514|F|125458.51|1993-02-07|5-LOW|Clerk#000000114|0|ches are blithely around t +10914|689|F|213268.60|1995-01-23|4-NOT SPECIFIED|Clerk#000000582|0| quickly regular packages above the furiously bold pl +10915|1357|F|178357.32|1993-11-11|5-LOW|Clerk#000000649|0|bold packages nag. furiously regular excu +10916|328|P|253026.49|1995-03-11|3-MEDIUM|Clerk#000000047|0|pinto beans cajole furiously according to the dependencies. fi +10917|251|F|127026.23|1992-02-11|1-URGENT|Clerk#000000078|0|beans across the regular theodolites affix silent instructions. even deposits +10918|1030|O|80094.04|1995-10-16|3-MEDIUM|Clerk#000000874|0|structions. ironic, express dep +10919|1339|F|56302.36|1993-03-28|2-HIGH|Clerk#000000180|0|press requests haggle blithely. blithely +10944|319|O|129953.86|1995-11-13|2-HIGH|Clerk#000000077|0|ily unusual requests. special instruct +10945|248|F|168422.71|1992-01-04|3-MEDIUM|Clerk#000000296|0|ages are. final, silent deposits haggle quickly! ironic +10946|1147|O|332313.82|1997-03-22|3-MEDIUM|Clerk#000000975|0|nal deposits detect among the quickly +10947|1070|O|135370.80|1996-01-07|2-HIGH|Clerk#000000347|0|ar excuses x-ray fluffily a +10948|670|F|223943.13|1992-08-14|3-MEDIUM|Clerk#000000489|0|nic grouches detect stealthily fluffily even de +10949|331|F|112812.10|1994-03-31|3-MEDIUM|Clerk#000000874|0|luffily even grouches. regular notornis against the sl +10950|767|O|37856.60|1997-06-11|3-MEDIUM|Clerk#000000015|0|y carefully pending packages. silent accounts nod careful +10951|1159|F|175198.95|1992-11-07|4-NOT SPECIFIED|Clerk#000000619|0|dependencies. sometimes pending foxes cajole. quickly +10976|685|F|186488.10|1992-10-02|4-NOT SPECIFIED|Clerk#000000282|0| deposits: brave, ironic packages maintain fluffily about the regular +10977|757|O|99211.94|1998-06-04|2-HIGH|Clerk#000000089|0|rious accounts about the regular excuses wake ironically special r +10978|1346|F|106794.18|1994-04-02|1-URGENT|Clerk#000000546|0|cial multipliers wake pending, pending theodolites: blithe +10979|1267|O|166156.36|1995-10-05|3-MEDIUM|Clerk#000000527|0|ans cajole carefully. regular pinto be +10980|754|O|75950.23|1996-07-29|4-NOT SPECIFIED|Clerk#000000818|0| ironic, stealthy patterns detect +10981|919|F|235684.93|1993-05-15|2-HIGH|Clerk#000000341|0|ly bold attainments nag! furiously special acco +10982|739|F|199304.65|1992-12-11|4-NOT SPECIFIED|Clerk#000000481|0|tithes use slyly silent, unusual a +10983|599|O|106734.94|1997-02-06|1-URGENT|Clerk#000000299|0|sts sleep of the regular foxes. permanent re +11008|523|F|222231.62|1994-02-25|1-URGENT|Clerk#000000927|0|ickly regular deposits detect fluffily: caref +11009|1303|O|65554.60|1997-03-05|3-MEDIUM|Clerk#000000515|0|deposits are blithely furio +11010|440|O|163532.15|1997-03-22|4-NOT SPECIFIED|Clerk#000000659|0|ithely-- express, final ideas sleep slyly to the blithely express reque +11011|14|F|248409.17|1992-05-14|2-HIGH|Clerk#000000948|0|luffily even warhors +11012|1420|O|114085.80|1998-04-07|1-URGENT|Clerk#000000771|0|ze fluffily quickly sly excuses. quickly pending frays haggle accordin +11013|395|F|2591.65|1994-04-18|2-HIGH|Clerk#000000759|0|ng deposits nag. special deposits sublate furio +11014|319|F|150733.48|1993-09-08|2-HIGH|Clerk#000000934|0|yly regular depths. re +11015|514|O|132711.70|1997-09-16|5-LOW|Clerk#000000216|0|its cajole against the unusual ideas? sly deposits boost fluffily. furiously +11040|82|O|211495.01|1995-10-24|4-NOT SPECIFIED|Clerk#000000003|0|arefully pending dolphins print brave +11041|1306|O|128785.82|1997-03-30|4-NOT SPECIFIED|Clerk#000000892|0|instructions. blithely pending packages solve of the furiously ironic requests +11042|857|O|223492.72|1998-05-07|4-NOT SPECIFIED|Clerk#000000677|0|ccounts. quickly unusual pinto beans nag enticingly a +11043|820|F|102166.94|1995-02-20|1-URGENT|Clerk#000000196|0|dolphins. accounts are f +11044|164|F|68884.04|1992-06-25|3-MEDIUM|Clerk#000000861|0|he deposits hinder above the furiously express excuses. silent depo +11045|556|F|226703.02|1992-03-26|3-MEDIUM|Clerk#000000216|0|uriously ironic asy +11046|1411|O|337558.78|1997-06-17|5-LOW|Clerk#000000454|0|lly special theodolites use furiously. carefully +11047|175|F|70365.24|1993-12-11|5-LOW|Clerk#000000223|0|. pending accounts alongside o +11072|265|O|207339.71|1996-07-14|2-HIGH|Clerk#000000804|0|osits: pending requests sleep quietly silently unusual deposits. special fo +11073|548|F|177610.35|1994-12-02|4-NOT SPECIFIED|Clerk#000000009|0|ing deposits-- slyly express dolphins detect fluffily ironic dep +11074|709|O|302642.18|1995-06-10|2-HIGH|Clerk#000000449|0|t the special asymptotes. furiously even dolphins sleep quickly ir +11075|1244|O|215012.92|1996-03-05|5-LOW|Clerk#000000379|0|efully furiously special pinto beans. fluffily unusual acc +11076|1012|F|54498.05|1994-08-18|1-URGENT|Clerk#000000361|0|lyly special notornis. bold requests haggle careful +11077|610|F|76484.04|1994-03-21|5-LOW|Clerk#000000024|0|gularly pending deposits. quick +11078|1301|F|103896.23|1992-05-28|2-HIGH|Clerk#000000227|0|ag. ironic, unusual accounts nag fluffily across the ironic, final ideas. car +11079|218|O|98046.49|1997-08-11|3-MEDIUM|Clerk#000000507|0|tainments affix doggedly slyly special asymptotes. +11104|1315|O|51132.08|1998-07-07|4-NOT SPECIFIED|Clerk#000000062|0|s cajole slyly alon +11105|1124|O|20773.48|1995-11-30|4-NOT SPECIFIED|Clerk#000000769|0|blithely about the closely silent foxes. blithely r +11106|1175|P|59390.31|1995-04-01|2-HIGH|Clerk#000000828|0|fter the quickly bold theodolites are blithely across +11107|445|O|64188.60|1995-10-24|5-LOW|Clerk#000000896|0|ymptotes. escapades use slyly? slyly b +11108|1186|F|238113.15|1992-08-17|4-NOT SPECIFIED|Clerk#000000137|0|ond the carefully unusual courts. regul +11109|664|F|5341.59|1995-03-16|3-MEDIUM|Clerk#000000578|0|. silent platelets haggle slyly. quickly ironic asymptotes +11110|757|O|153722.23|1996-06-23|4-NOT SPECIFIED|Clerk#000000243|0|es are quickly alongside of the spe +11111|631|F|121957.72|1995-01-18|3-MEDIUM|Clerk#000000301|0|nic deposits affix quickly regula +11136|1313|F|60530.16|1993-11-14|4-NOT SPECIFIED|Clerk#000000987|0|ular foxes haggle against the unusual frays. i +11137|668|F|204264.90|1992-11-30|2-HIGH|Clerk#000000515|0|bout the final accounts. regular ideas cajole slyly. blithely sly d +11138|181|F|162678.89|1995-02-27|4-NOT SPECIFIED|Clerk#000000983|0|d platelets. carefully ironic packages alongside of the carefully +11139|883|O|115264.28|1998-05-17|5-LOW|Clerk#000000891|0|the furiously silent i +11140|988|O|194048.42|1997-07-26|1-URGENT|Clerk#000000117|0|. fluffily busy sauternes cajole slyly above the quickly express excuses. exp +11141|1030|O|72800.37|1998-01-17|1-URGENT|Clerk#000000084|0|ckages. carefully regul +11142|1375|O|395039.05|1997-10-03|4-NOT SPECIFIED|Clerk#000000457|0| even accounts sublate carefully +11143|97|F|172537.11|1992-11-27|5-LOW|Clerk#000000613|0|unusual instructions. q +11168|1441|F|74602.03|1992-10-22|1-URGENT|Clerk#000000585|0|es. even patterns use fluff +11169|1222|F|121781.45|1993-05-22|3-MEDIUM|Clerk#000000536|0|eodolites wake. fluffily express packages +11170|736|O|152992.55|1997-07-30|1-URGENT|Clerk#000000832|0|eyond the furiously regular pinto beans. car +11171|730|O|104672.68|1995-07-17|1-URGENT|Clerk#000000792|0|l deposits promise according to the express deposits. fluffily final r +11172|1076|O|166824.37|1997-12-30|1-URGENT|Clerk#000000187|0|ructions. furiously pending dependencies wake. deposits +11173|319|F|179045.62|1992-03-31|1-URGENT|Clerk#000000815|0|e ironically silent deposits wake blithely across the regular instructions +11174|1315|F|149433.95|1994-04-10|3-MEDIUM|Clerk#000000321|0|se about the pending, special decoys-- fluffily express +11175|1421|O|44114.12|1998-02-26|2-HIGH|Clerk#000000812|0| slyly even deposits are blithely; packages integrate furiously. bravely ironi +11200|956|O|113819.40|1997-02-07|1-URGENT|Clerk#000000417|0|ajole. silent requests boost carefully blithely thin multiplier +11201|632|O|3297.46|1996-12-08|3-MEDIUM|Clerk#000000746|0|ns cajole after the pending pinto beans. carefully ironic requests wake r +11202|1168|F|157836.48|1992-03-18|3-MEDIUM|Clerk#000000614|0|wake daringly. carefully regular account +11203|1498|O|84795.43|1996-06-15|2-HIGH|Clerk#000000010|0|al instructions haggle slyly. fu +11204|1249|O|29604.53|1998-07-25|2-HIGH|Clerk#000000752|0| express requests. slyly special packages cajole fluffily; quickly ironi +11205|1294|O|93334.58|1996-09-15|1-URGENT|Clerk#000000800|0|ckages. furiously final packages ac +11206|379|F|209373.08|1994-12-29|5-LOW|Clerk#000000139|0|ending packages cajole busily. slyly +11207|1213|O|84129.92|1996-04-03|2-HIGH|Clerk#000000354|0|ress accounts haggle permanently about the furiously unusua +11232|661|O|77549.43|1996-02-01|1-URGENT|Clerk#000000676|0|fully regular accounts. final, unusual deposits sleep eve +11233|680|O|96728.84|1995-08-31|4-NOT SPECIFIED|Clerk#000000820|0|lphins. carefully ironic ideas use after the quickly unusual a +11234|1153|F|117092.84|1993-03-01|4-NOT SPECIFIED|Clerk#000000291|0|e slyly across the carefully even requests. slyly +11235|590|O|278256.83|1996-04-03|4-NOT SPECIFIED|Clerk#000000495|0|ackages solve carefully furiously final accounts. fluf +11236|223|F|210654.72|1993-10-31|2-HIGH|Clerk#000000792|0|ess pinto beans. foxes b +11237|1423|O|155158.38|1996-06-16|4-NOT SPECIFIED|Clerk#000000627|0|e the carefully special ideas inte +11238|535|O|126764.00|1996-07-23|1-URGENT|Clerk#000000809|0|gular foxes run after the even instructions. regular instructions wake. unu +11239|475|F|310241.51|1992-02-10|1-URGENT|Clerk#000000240|0|e regular, even excuses. +11264|676|O|152483.91|1996-09-02|4-NOT SPECIFIED|Clerk#000000227|0|usly silent deposits. carefully unusual asymptotes ha +11265|905|O|88998.81|1997-05-20|3-MEDIUM|Clerk#000000427|0|ias. carefully pending platel +11266|292|O|13609.27|1997-08-10|4-NOT SPECIFIED|Clerk#000000315|0|lets nag about the carefully special packages. ironic sheaves +11267|548|F|45572.31|1992-02-15|5-LOW|Clerk#000000096|0| wake slyly even deposits. c +11268|43|O|189596.87|1998-06-30|1-URGENT|Clerk#000000130|0|ptotes are blithely slyly silen +11269|199|F|256118.53|1992-05-27|5-LOW|Clerk#000000752|0|ath the decoys. final excuses must have to wake. ironic asymptotes wake q +11270|160|O|197781.66|1995-07-01|2-HIGH|Clerk#000000757|0|ily pending theodolites a +11271|745|O|255335.88|1995-10-19|2-HIGH|Clerk#000000144|0|sts. furiously ironic foxes wake ca +11296|832|F|378166.33|1992-01-10|1-URGENT|Clerk#000000966|0|s-- ironic, unusual requests haggle furiously. carefully special depend +11297|694|F|109722.85|1993-01-09|4-NOT SPECIFIED|Clerk#000000247|0|hely. express escapades kindle blithely. even requests wake +11298|805|O|228663.94|1998-01-03|2-HIGH|Clerk#000000160|0| blithely express ideas sleep slyly ruthl +11299|50|F|253114.92|1993-11-13|4-NOT SPECIFIED|Clerk#000000885|0|ns haggle bravely alongside of the fluffily express requests. +11300|346|O|77247.48|1996-07-10|5-LOW|Clerk#000000697|0|he final platelets. blithely even theodolites along the car +11301|1358|F|191271.29|1992-03-23|3-MEDIUM|Clerk#000000321|0|hes detect fluffily ironic requests. deposits br +11302|451|F|243997.09|1994-03-02|5-LOW|Clerk#000000492|0|. never ironic requests sleep furiousl +11303|388|F|92968.88|1992-03-30|5-LOW|Clerk#000000788|0|he slyly pending requests. final deposits +11328|466|F|18702.67|1992-03-21|1-URGENT|Clerk#000000101|0|theodolites. blithely pending accounts above the carefully +11329|1285|O|272307.07|1995-08-05|1-URGENT|Clerk#000000903|0|on the daringly express instructions. fluf +11330|281|F|3817.37|1992-03-28|5-LOW|Clerk#000000429|0|he slyly ironic ideas are q +11331|179|O|18118.60|1996-01-21|3-MEDIUM|Clerk#000000616|0|platelets wake carefully ruthless requests. silent deposits believe +11332|422|F|213792.99|1994-11-17|5-LOW|Clerk#000000572|0|o the unusual foxes-- ironic requests wake slyly enticingly re +11333|103|F|15730.53|1994-06-10|2-HIGH|Clerk#000000914|0|excuses cajole blithely against the slyly express r +11334|245|O|343561.63|1997-07-29|3-MEDIUM|Clerk#000000843|0|ronic deposits haggle fu +11335|871|F|133549.00|1994-10-22|2-HIGH|Clerk#000000669|0|ealms. theodolites maintain. regular, even instructions against t +11360|886|O|67314.59|1997-09-07|1-URGENT|Clerk#000000561|0|. slyly regular deposits lose +11361|442|F|251600.98|1994-09-28|1-URGENT|Clerk#000000345|0| final requests boost never pinto beans. special accounts are slyly unusual t +11362|1042|F|250063.55|1992-09-11|5-LOW|Clerk#000000922|0|ly blithe deposits cajole blithely slyly silent deposits. regular +11363|1358|O|163511.72|1998-02-09|5-LOW|Clerk#000000844|0| silent pinto beans haggle al +11364|163|O|107551.91|1997-03-11|1-URGENT|Clerk#000000582|0|sts wake fluffily about the slyly special accounts. qu +11365|1214|O|211938.69|1997-08-29|3-MEDIUM|Clerk#000000520|0|de of the blithely final requests. fluffily regular dolphin +11366|863|F|12711.31|1992-06-08|3-MEDIUM|Clerk#000000993|0|lites nag blithely un +11367|418|F|18148.48|1994-12-17|1-URGENT|Clerk#000000566|0| carefully regular deposits. bold theodolites haggle. enticingly final fo +11392|1340|F|135223.44|1994-09-06|5-LOW|Clerk#000000607|0|tect blithely across the express dependencies. instructions after the slyly re +11393|1150|F|138539.25|1992-03-19|5-LOW|Clerk#000000022|0|al packages. carefully speci +11394|1255|O|181795.18|1998-03-06|2-HIGH|Clerk#000000559|0| deposits! fluffily sp +11395|940|O|46826.01|1997-08-26|1-URGENT|Clerk#000000306|0|beans nag carefully even sentiments-- express platelets +11396|1273|F|107605.76|1992-07-22|1-URGENT|Clerk#000000265|0|ously regular accounts haggle +11397|757|O|55531.65|1996-10-29|5-LOW|Clerk#000000603|0|oss the regular pac +11398|587|F|258130.52|1992-08-07|2-HIGH|Clerk#000000407|0|f the theodolites are fu +11399|346|F|39653.25|1994-04-19|5-LOW|Clerk#000000460|0|ffily furiously even pa +11424|343|F|58887.47|1993-04-03|4-NOT SPECIFIED|Clerk#000000547|0|s. quickly final requests around the slyly unusual dependencies cajol +11425|1123|O|156058.42|1995-06-23|1-URGENT|Clerk#000000336|0|arefully special requests cajole bravely fluffy pinto beans. ironic +11426|1357|F|94572.71|1994-05-08|3-MEDIUM|Clerk#000000066|0|ilent notornis boost blithely quickly even pinto beans. carefully speci +11427|427|F|306906.43|1993-11-25|3-MEDIUM|Clerk#000000401|0|y slyly brave excuses. slow packages sleep quickl +11428|628|F|7046.94|1992-01-22|3-MEDIUM|Clerk#000000926|0|ep slyly even, unusual packages. spe +11429|1192|F|145545.35|1993-03-04|5-LOW|Clerk#000000765|0| bold courts sleep blithely. regular, even r +11430|1342|O|3641.35|1998-01-05|5-LOW|Clerk#000000817|0|tions breach. regular, express pinto beans wake across the carefully +11431|10|F|230289.60|1992-08-02|2-HIGH|Clerk#000000055|0|press ideas use slyly regular pinto beans. furiously +11456|271|F|53466.58|1993-04-13|5-LOW|Clerk#000000209|0|ar foxes against the quickly special th +11457|1430|O|232660.01|1995-12-14|1-URGENT|Clerk#000000294|0|the slyly quiet ideas. idly final deposits nag. carefully regu +11458|1468|O|201085.02|1998-04-02|5-LOW|Clerk#000000402|0|l pinto beans cajole carefully +11459|325|O|230925.13|1996-07-15|4-NOT SPECIFIED|Clerk#000000852|0|ular requests use blithely. quickly special packages boost furiously. deposits +11460|763|F|51498.95|1993-08-25|2-HIGH|Clerk#000000014|0| brave dependencies nag. blithely final foxe +11461|1049|O|80204.90|1996-05-01|1-URGENT|Clerk#000000630|0|ymptotes. packages haggle whithout the evenly final requests. req +11462|226|O|164290.80|1996-08-25|2-HIGH|Clerk#000000210|0|grouches. closely dogged deposits sleep. special, pending packages slee +11463|140|O|258622.38|1997-12-28|3-MEDIUM|Clerk#000000886|0|ular deposits. slyly final attainments detect careful +11488|751|F|92903.96|1993-08-23|4-NOT SPECIFIED|Clerk#000000119|0|ickly final requests. furiously even attainments sleep fluffily slyly regu +11489|929|O|100935.67|1996-09-19|4-NOT SPECIFIED|Clerk#000000155|0|ions. ironic foxes wake. regular platelets cajole slyly close +11490|745|O|66256.76|1996-09-27|1-URGENT|Clerk#000000489|0|quests affix according to the special p +11491|158|F|242695.19|1993-08-18|5-LOW|Clerk#000000329|0|cial foxes across the final packag +11492|478|O|141195.82|1997-03-06|2-HIGH|Clerk#000000708|0|ely regular instructions was fluffily among the fluffil +11493|1486|O|63852.92|1995-10-21|1-URGENT|Clerk#000000543|0|e blithely regular accounts +11494|1484|O|90512.73|1997-07-20|3-MEDIUM|Clerk#000000486|0|s. blithely unusual pi +11495|1048|O|43956.73|1995-07-05|2-HIGH|Clerk#000000684|0|y bold accounts cajo +11520|1217|F|111920.94|1994-09-28|3-MEDIUM|Clerk#000000106|0|courts. carefully final requests along the carefully final +11521|55|O|19730.00|1996-09-09|1-URGENT|Clerk#000000010|0| express platelets according to the iro +11522|47|F|21454.81|1993-09-16|5-LOW|Clerk#000000121|0|ual foxes x-ray carefully alo +11523|355|O|210039.66|1998-07-27|4-NOT SPECIFIED|Clerk#000000008|0|y: fluffily regular instructions sleep quickly enticing orbits. carefully un +11524|766|O|7445.25|1995-12-14|5-LOW|Clerk#000000943|0|encies. foxes detect around the final, even theodolites. special depos +11525|1495|O|169021.86|1997-03-20|1-URGENT|Clerk#000000159|0|ong the ironic accounts are slyly furiously pending dependencies. even exc +11526|466|O|124012.92|1998-02-23|5-LOW|Clerk#000000798|0|ickly regular packages use slyly ironic, +11527|1108|F|46961.88|1994-07-03|3-MEDIUM|Clerk#000000187|0|ously final packages was slyly above the bli +11552|1421|F|34742.82|1992-12-15|1-URGENT|Clerk#000000960|0|g, dogged notornis. carefully even instructions across the furiou +11553|196|F|207629.22|1994-04-19|3-MEDIUM|Clerk#000000467|0|s thrash blithely carefully ironic requests. quickl +11554|344|O|269777.97|1998-06-07|2-HIGH|Clerk#000000746|0| platelets are fluffily above the ironic theodolites. slyly pending +11555|1318|O|242411.22|1996-05-26|3-MEDIUM|Clerk#000000308|0|hinly bold deposits detect along the courts. express theodo +11556|707|O|237841.53|1996-03-03|5-LOW|Clerk#000000790|0|around the furiously ironic courts. blithely unusual deposits cajo +11557|1412|O|39415.83|1997-04-12|5-LOW|Clerk#000000522|0|ily. fluffily dogged asymptotes wake slyly regular grouches. a +11558|61|F|47438.62|1994-03-28|2-HIGH|Clerk#000000181|0| the slyly final excuses. +11559|931|O|54171.71|1995-09-26|1-URGENT|Clerk#000000582|0| pending excuses; carefully final dependencies +11584|643|F|350276.97|1994-11-23|3-MEDIUM|Clerk#000000150|0|l pinto beans haggle bold packages. fina +11585|895|F|59671.89|1994-03-16|3-MEDIUM|Clerk#000000105|0|g to the slyly unusual deposits. bold, final requests boost f +11586|1013|F|24377.52|1993-11-17|4-NOT SPECIFIED|Clerk#000000180|0|ously special packages solve carefully above th +11587|220|O|149730.78|1998-03-05|4-NOT SPECIFIED|Clerk#000000103|0| the slyly regular platelets. silently final packages may nag. foxes accordi +11588|1396|O|187668.87|1997-10-30|5-LOW|Clerk#000000492|0|ep. final, even excuses dazzle about the carefully special req +11589|1315|F|106954.20|1992-05-19|4-NOT SPECIFIED|Clerk#000000420|0|y express foxes shall have to cajole about the quickly unusu +11590|883|O|251411.55|1996-04-15|2-HIGH|Clerk#000000744|0|dolites sleep across the carefully regular depo +11591|269|F|108716.86|1993-01-21|2-HIGH|Clerk#000000691|0|pinto beans. bold deposits a +11616|403|O|261053.80|1996-08-02|2-HIGH|Clerk#000000003|0|cording to the express +11617|1459|F|186543.96|1994-12-11|4-NOT SPECIFIED|Clerk#000000519|0|etect blithely pending +11618|356|O|126867.40|1998-02-04|1-URGENT|Clerk#000000594|0|s kindle fluffily after +11619|55|O|42866.58|1998-07-12|2-HIGH|Clerk#000000245|0|ress instructions. ideas solve carefully special requests. patterns p +11620|353|O|115080.33|1997-07-22|4-NOT SPECIFIED|Clerk#000000961|0|ies nag slyly along +11621|964|O|233849.43|1995-11-11|5-LOW|Clerk#000000316|0|pinto beans. ruthless pinto beans haggle. slyly regular +11622|349|O|169440.18|1996-04-27|4-NOT SPECIFIED|Clerk#000000006|0| never instructions. express Tiresias boost. unusual, even pinto bean +11623|715|O|335923.49|1995-12-16|2-HIGH|Clerk#000000827|0|atelets cajole quietly final requests. slyly final courts are ironic, final +11648|949|P|223995.17|1995-04-10|5-LOW|Clerk#000000916|0| cajole carefully alon +11649|718|O|336620.13|1996-06-30|5-LOW|Clerk#000000666|0|kly even pinto beans cajole fu +11650|667|F|153010.80|1992-09-25|4-NOT SPECIFIED|Clerk#000000444|0|ccording to the ironic, regular excuses are +11651|689|F|66834.76|1995-02-23|3-MEDIUM|Clerk#000000982|0|sly furious sheaves. regular requests c +11652|1442|O|228052.10|1995-11-11|4-NOT SPECIFIED|Clerk#000000098|0|uriously bold foxes promise among the blithely ironic packages. fluffily regu +11653|314|O|191078.29|1997-07-05|2-HIGH|Clerk#000000533|0|kages doubt according to the final theodolites. furiously regular +11654|791|F|115033.02|1993-09-28|4-NOT SPECIFIED|Clerk#000000756|0|onic waters. carefully even packages haggle f +11655|910|O|184768.86|1998-06-27|1-URGENT|Clerk#000000614|0|slyly special asymptotes. final, unusual requests engage carefully pe +11680|1187|F|288910.60|1994-09-05|3-MEDIUM|Clerk#000000731|0|pecial asymptotes. final platelets cajole among the ironic pinto beans. pla +11681|857|F|246493.05|1992-10-17|1-URGENT|Clerk#000000485|0|final packages. carefully final accounts affi +11682|5|F|153588.74|1993-07-05|5-LOW|Clerk#000000852|0|s grow slyly. express, fin +11683|209|F|183381.18|1992-02-08|4-NOT SPECIFIED|Clerk#000000583|0|to beans cajole. furiously even frets detect. unusual pinto beans are +11684|323|F|282136.80|1992-07-28|2-HIGH|Clerk#000000986|0|instructions. final, even packages throughout the epi +11685|445|O|254981.92|1997-03-19|3-MEDIUM|Clerk#000000641|0|leep slyly unusual foxes. blithely even ideas through the t +11686|1039|F|169100.57|1994-01-28|4-NOT SPECIFIED|Clerk#000000169|0|ts wake furiously. accounts about the regular ideas are furiously +11687|1025|O|182611.71|1995-12-26|2-HIGH|Clerk#000000390|0|fluffily ideas. blithely pending packages lose blithely. slyly +11712|173|F|117391.91|1994-04-27|5-LOW|Clerk#000000376|0|special excuses. final accounts use. dependencies detect by the carefu +11713|1397|F|124407.44|1993-12-25|4-NOT SPECIFIED|Clerk#000000481|0|nic packages. unusual, unusual Ti +11714|1250|F|170165.48|1994-08-05|1-URGENT|Clerk#000000877|0|sts could have to wake ironic dependencies. furiously regul +11715|863|F|67076.38|1994-09-07|2-HIGH|Clerk#000000106|0|xpress foxes. pinto beans above the express deposits are final foxes. furio +11716|481|F|178602.59|1993-10-12|3-MEDIUM|Clerk#000000021|0|sly ironic packages haggle blithely around the unusual accounts. slyly re +11717|413|O|153316.94|1998-03-19|5-LOW|Clerk#000000185|0|furiously regular waters +11718|688|F|35335.31|1994-12-19|3-MEDIUM|Clerk#000000131|0|ly regular asymptotes. decoys integrate slyly among the bo +11719|1147|F|240503.39|1995-02-06|4-NOT SPECIFIED|Clerk#000000307|0|hely slyly special instr +11744|127|O|183922.62|1996-07-05|1-URGENT|Clerk#000000197|0|pecial packages above the furio +11745|25|F|147334.29|1992-07-20|2-HIGH|Clerk#000000549|0|lar ideas. slyly expre +11746|5|O|177360.54|1998-04-29|3-MEDIUM|Clerk#000000038|0|heodolites. final asymptotes was above the furiously final pin +11747|460|F|46484.18|1993-02-26|3-MEDIUM|Clerk#000000537|0|. requests use across +11748|733|F|43216.31|1994-06-04|4-NOT SPECIFIED|Clerk#000000147|0|uffily regular accounts cajole blithely alongside of the furiously pending p +11749|818|O|75180.45|1998-02-17|5-LOW|Clerk#000000819|0| excuses boost against the final pai +11750|823|O|117385.37|1997-03-05|2-HIGH|Clerk#000000801|0| furiously packages. carefully silent instruc +11751|1282|O|150450.18|1996-05-23|1-URGENT|Clerk#000000605|0|uickly express pinto beans. blithely bold foxes use above the dep +11776|386|F|90162.21|1992-02-25|5-LOW|Clerk#000000548|0|ck theodolites integrate furiously along the bold deposits. even, pending +11777|271|F|56387.90|1994-12-26|5-LOW|Clerk#000000292|0|g dependencies; quickly dogged courts wake quick +11778|217|O|102865.25|1997-03-28|5-LOW|Clerk#000000253|0|ss the final, unusual packages. quickly quick theodolites haggle. slyl +11779|1045|F|183456.75|1993-06-30|4-NOT SPECIFIED|Clerk#000000740|0|according to the care +11780|28|F|129283.92|1993-09-22|1-URGENT|Clerk#000000793|0|ove the regular theodolites are furiously regular notornis. +11781|1484|O|147766.37|1996-04-16|5-LOW|Clerk#000000619|0|s. final, final deposi +11782|427|F|163855.06|1992-07-29|5-LOW|Clerk#000000609|0|bold, unusual requests are slyly against the quickly bold dependencies. s +11783|1498|O|22953.13|1998-04-03|1-URGENT|Clerk#000000028|0|. regular theodolites snooze furiou +11808|874|F|60831.20|1992-08-01|4-NOT SPECIFIED|Clerk#000000710|0|could detect quickly unusu +11809|556|O|161697.76|1996-04-25|2-HIGH|Clerk#000000617|0|old realms alongside of the special dugouts use along the fluffily iro +11810|647|F|77198.94|1992-04-23|1-URGENT|Clerk#000000804|0| final requests boost among the furiously bold accounts. final +11811|527|F|7385.35|1992-10-28|2-HIGH|Clerk#000000940|0| packages haggle furiously pend +11812|940|F|17214.00|1993-06-03|3-MEDIUM|Clerk#000000844|0|y regular accounts. regular, pending requests print careful +11813|376|F|211762.16|1994-02-10|1-URGENT|Clerk#000000813|0|ly regular instructions. quickly ironi +11814|121|F|198422.64|1993-01-26|2-HIGH|Clerk#000000404|0|final ideas sleep sometimes deposits. final, final foxes boost fu +11815|1396|O|199250.12|1995-09-13|5-LOW|Clerk#000000342|0|counts use according to the bli +11840|596|F|283439.67|1994-08-15|1-URGENT|Clerk#000000466|0|ggle slowly across the sly +11841|727|F|158024.06|1993-04-21|3-MEDIUM|Clerk#000000521|0|s sleep carefully unusual ac +11842|1414|O|90262.04|1996-04-08|4-NOT SPECIFIED|Clerk#000000566|0|furiously unusual platelets. express requests +11843|730|F|211984.66|1994-07-18|3-MEDIUM|Clerk#000000747|0|g requests snooze care +11844|121|O|86777.18|1997-01-18|2-HIGH|Clerk#000000609|0|ular deposits haggle +11845|887|O|125342.31|1997-03-29|1-URGENT|Clerk#000000902|0|ts. final accounts detect furiously bold foxes. carefully regular packages h +11846|1046|F|51318.21|1993-04-21|5-LOW|Clerk#000000688|0|uriously ironic packages cajole furiously express, even ideas. ironic ideas +11847|1007|O|94551.77|1997-10-02|2-HIGH|Clerk#000000860|0|ely pending deposits haggle furiously across the pending +11872|145|F|75770.24|1994-07-25|5-LOW|Clerk#000000620|0| courts across the furiously +11873|863|O|21009.93|1996-04-06|4-NOT SPECIFIED|Clerk#000000322|0|press, final deposits da +11874|481|F|221467.60|1992-09-10|3-MEDIUM|Clerk#000000163|0|r the slyly bold deposits wake about the c +11875|698|F|98592.08|1992-08-21|3-MEDIUM|Clerk#000000300|0|. quickly special asymptotes after the slowly final pa +11876|611|O|130732.20|1995-07-04|2-HIGH|Clerk#000000325|0| to the quickly even pains: always +11877|268|F|122384.64|1993-05-24|4-NOT SPECIFIED|Clerk#000000312|0|ly above the unusua +11878|1349|F|92047.44|1993-02-25|4-NOT SPECIFIED|Clerk#000000041|0|ole blithely fluffy, unusua +11879|1057|F|185103.30|1993-06-20|2-HIGH|Clerk#000000371|0|to the special excuses detect carefully carefully express accounts. carefully +11904|415|O|279468.40|1997-12-02|4-NOT SPECIFIED|Clerk#000000924|0|accounts. platelets k +11905|343|O|101799.49|1997-07-04|5-LOW|Clerk#000000543|0|thely regular foxes. fluffily regular pinto beans i +11906|524|O|325004.58|1996-12-15|5-LOW|Clerk#000000929|0|deas cajole quickly? blithely final dolphins boost. blithely final deposits wa +11907|1327|F|127812.95|1993-08-24|5-LOW|Clerk#000000062|0|osits above the quickly ironic instructions are carefully after t +11908|1063|F|180189.92|1993-05-26|4-NOT SPECIFIED|Clerk#000000456|0|atelets across the express deposits kindle evenly unu +11909|868|F|51603.50|1994-11-25|4-NOT SPECIFIED|Clerk#000000012|0|lithely unusual accounts aga +11910|644|O|102331.93|1995-06-16|2-HIGH|Clerk#000000664|0|uriously final ideas cajole furi +11911|355|F|219307.51|1993-11-11|1-URGENT|Clerk#000000563|0| requests try to wake according to the carefully regular deposit +11936|749|O|167898.60|1995-09-16|1-URGENT|Clerk#000000869|0|ns wake blithely even, express theodolites; final +11937|1424|O|159471.41|1998-06-27|1-URGENT|Clerk#000000941|0|ic deposits sleep carefully special, regular foxes. special theo +11938|67|O|161199.79|1998-07-25|1-URGENT|Clerk#000000911|0|iously above the reg +11939|1333|O|84765.05|1996-10-01|2-HIGH|Clerk#000000610|0|iously regular dinos cajole furiously foxes. blithely regular foxes acr +11940|683|O|149688.34|1998-05-30|2-HIGH|Clerk#000000152|0|ular ideas cajole quickly +11941|659|F|157391.90|1993-06-25|1-URGENT|Clerk#000000392|0| instructions. carefully final theodolites wake quickly. carefully iro +11942|1324|F|43794.61|1994-05-09|1-URGENT|Clerk#000000317|0|ely bold accounts are carefully alongside of the unusual packages. slyly eve +11943|244|F|235683.21|1993-04-08|5-LOW|Clerk#000000724|0|requests haggle quickly about the carefully +11968|311|F|43428.32|1995-03-17|5-LOW|Clerk#000000526|0|g frets was above the fur +11969|449|F|270998.74|1992-01-20|4-NOT SPECIFIED|Clerk#000000641|0|efully. blithely pending deposits haggle regular, regular +11970|937|O|255762.04|1998-05-24|1-URGENT|Clerk#000000885|0|cial pinto beans. blithely expres +11971|1351|O|119482.38|1997-03-21|2-HIGH|Clerk#000000026|0|slyly regular requests lose quickly: depen +11972|1396|F|147645.78|1994-01-04|4-NOT SPECIFIED|Clerk#000000751|0|riously silent gifts affix slyl +11973|631|F|158758.99|1994-03-04|4-NOT SPECIFIED|Clerk#000000545|0| regular theodolites use carefully pen +11974|1366|F|88216.78|1992-10-09|4-NOT SPECIFIED|Clerk#000000595|0|slyly unusual accounts according to the blithely ironic ideas boost furio +11975|322|O|230472.15|1995-04-14|1-URGENT|Clerk#000000551|0|on the bold ideas cajole across the f +12000|1150|F|89148.77|1994-05-13|4-NOT SPECIFIED|Clerk#000000683|0|s against the furiously ironic grouches sleep according to the e +12001|739|F|138635.75|1994-07-07|2-HIGH|Clerk#000000863|0|old, even theodolites. regular, special theodolites use furio +12002|826|F|79579.51|1993-11-30|3-MEDIUM|Clerk#000000431|0| regular packages wake qui +12003|1205|O|16311.25|1998-05-24|1-URGENT|Clerk#000000708|0|s along the quickly regular instructions haggle carefully furiously u +12004|656|F|74814.13|1994-12-05|3-MEDIUM|Clerk#000000633|0|nis against the slyly specia +12005|1102|F|250917.29|1992-06-25|4-NOT SPECIFIED|Clerk#000000904|0| after the ironic, unusua +12006|944|O|129075.40|1997-06-02|4-NOT SPECIFIED|Clerk#000000501|0|n packages. carefully ironic accounts are after the pending platele +12007|613|F|239431.45|1994-09-28|4-NOT SPECIFIED|Clerk#000000363|0|even requests wake carefully unusual packages. quickly +12032|902|O|102348.27|1997-08-10|4-NOT SPECIFIED|Clerk#000000349|0| after the even, regular instructions. blithe tithes use furiously. b +12033|334|F|214360.53|1992-09-12|2-HIGH|Clerk#000000274|0| bold pearls haggle. carefully ironic pinto beans cajole. blit +12034|121|O|88674.23|1996-12-08|2-HIGH|Clerk#000000363|0|ges. deposits sleep slyly. ideas sleep +12035|1010|O|245999.17|1996-11-09|5-LOW|Clerk#000000963|0|furiously special instructions. pending deposits nod. blithely unusual pint +12036|838|O|241236.07|1998-01-16|5-LOW|Clerk#000000041|0|ic requests. unusual pinto beans sleep fluffily about the furiously regular +12037|1462|O|139739.68|1995-07-01|5-LOW|Clerk#000000375|0|pending foxes shall cajol +12038|164|O|59423.94|1995-11-10|2-HIGH|Clerk#000000587|0|ironic asymptotes mainta +12039|1252|F|303373.40|1993-06-17|2-HIGH|Clerk#000000765|0|packages integrate c +12064|38|F|133067.27|1992-09-16|5-LOW|Clerk#000000994|0| blithely quickly pending t +12065|557|O|60068.73|1997-01-30|4-NOT SPECIFIED|Clerk#000000064|0|the final deposits boost pending deposits. pending +12066|1066|F|187325.65|1995-02-07|3-MEDIUM|Clerk#000000084|0|heodolites cajole a +12067|257|F|227467.91|1993-02-05|1-URGENT|Clerk#000000019|0|requests. quickly regular packages run f +12068|1231|O|20347.58|1996-05-08|2-HIGH|Clerk#000000402|0|ctions. furiously even accounts +12069|1381|O|235666.55|1995-11-08|2-HIGH|Clerk#000000460|0|ong the pinto beans. deposits among the excuses cajole +12070|746|O|256785.35|1998-05-23|5-LOW|Clerk#000000287|0|bold pinto beans hagg +12071|956|O|100260.23|1998-06-26|1-URGENT|Clerk#000000205|0|ly bold multipliers cajole quickly re +12096|1004|F|257237.41|1992-09-20|3-MEDIUM|Clerk#000000156|0|hely final requests kindle among the regular foxes. orb +12097|118|F|156644.02|1993-11-10|1-URGENT|Clerk#000000239|0|out the slyly regular theodolites. regularly reg +12098|1325|F|34956.25|1993-05-01|2-HIGH|Clerk#000000214|0| carefully ironic, express deposits. ideas are slyly a +12099|112|F|230209.47|1994-09-12|1-URGENT|Clerk#000000042|0|furiously regular accounts haggle quic +12100|1298|O|62857.66|1996-03-15|2-HIGH|Clerk#000000518|0|ress frays use blithely pending requests-- quickly regular somas acros +12101|754|F|103072.24|1995-01-07|1-URGENT|Clerk#000000853|0|fily regular packages w +12102|1264|O|208734.50|1995-11-18|3-MEDIUM|Clerk#000000981|0|eposits are blithely along +12103|229|O|169239.68|1996-11-25|3-MEDIUM|Clerk#000000605|0|ironic foxes. quickly brave pinto beans +12128|1192|O|163301.92|1997-06-27|4-NOT SPECIFIED|Clerk#000000102|0|yly across the furiously ironic accounts. carefully special real +12129|418|F|117561.31|1992-12-26|3-MEDIUM|Clerk#000000119|0|dencies cajole furiously about the +12130|1261|O|157170.80|1995-12-10|4-NOT SPECIFIED|Clerk#000000894|0|according to the even, regular packages. furiously unusual pinto beans wake +12131|1172|O|285746.20|1998-06-29|3-MEDIUM|Clerk#000000074|0|ironic ideas. blithely unus +12132|1277|O|271963.86|1996-09-06|1-URGENT|Clerk#000000831|0|ptotes boost permanently. carefully unusual instr +12133|361|F|52225.60|1992-04-15|1-URGENT|Clerk#000000634|0|st after the furiously special +12134|355|O|56547.11|1996-05-31|3-MEDIUM|Clerk#000000868|0|blithely blithely regular theodolites. slyly even packages nag slyly slyly e +12135|1420|O|268120.03|1995-10-10|5-LOW|Clerk#000000246|0|ual excuses alongside of th +12160|1423|F|67966.80|1993-12-13|5-LOW|Clerk#000000707|0|ully about the furiously ironic braids-- carefully en +12161|1307|O|215072.11|1997-03-15|4-NOT SPECIFIED|Clerk#000000382|0|le blithely across the blithely slow fox +12162|1222|O|47989.76|1997-03-18|3-MEDIUM|Clerk#000000066|0| players according to the fluffily ironic dolphins cajole slyly spe +12163|88|O|205826.29|1997-07-20|5-LOW|Clerk#000000951|0|se furiously carefully special pinto beans. blithely special +12164|1313|F|180895.16|1993-10-17|1-URGENT|Clerk#000000148|0|ests. instructions haggle blithely express dependencies. furiously bold war +12165|1489|F|153853.42|1994-04-11|5-LOW|Clerk#000000091|0|nic pinto beans boost carefully +12166|62|F|18006.96|1995-03-15|4-NOT SPECIFIED|Clerk#000000469|0|of the slyly even pinto bean +12167|91|O|60173.82|1998-05-31|1-URGENT|Clerk#000000618|0|counts. bravely special pac +12192|277|F|27209.81|1994-10-19|1-URGENT|Clerk#000000387|0| bold ideas boost slyly slyly final frays. carefully unusual pinto b +12193|802|O|159382.08|1996-07-28|3-MEDIUM|Clerk#000000559|0|y. blithely final pinto beans according to the theodolites haggle care +12194|271|F|59806.63|1995-03-02|1-URGENT|Clerk#000000922|0|atelets haggle among the regular accounts. furiously even plate +12195|73|O|108946.27|1997-04-27|4-NOT SPECIFIED|Clerk#000000947|0|iously silent foxes eat carefull +12196|1261|F|83958.83|1993-06-03|4-NOT SPECIFIED|Clerk#000000284|0|e furiously ironic ideas affix fluffily above the quickly +12197|577|O|206318.73|1997-06-27|2-HIGH|Clerk#000000976|0|ular packages affix upon the slyly +12198|1300|F|59977.08|1993-02-28|3-MEDIUM|Clerk#000000917|0| ironic deposits. furiously express escapades detect +12199|520|O|103350.42|1995-12-15|5-LOW|Clerk#000000478|0|he ironic accounts. ideas detect. slyly final packa +12224|646|F|212674.36|1994-12-13|2-HIGH|Clerk#000000672|0|. slyly final accounts boost. blithely express deposits haggle sl +12225|656|O|188067.32|1997-01-29|2-HIGH|Clerk#000000903|0|ons. blithely bold requests are carefu +12226|1348|O|120809.59|1998-04-01|5-LOW|Clerk#000000415|0| across the final instructi +12227|1282|O|210133.42|1998-06-27|3-MEDIUM|Clerk#000000980|0| packages. quickly ironic accounts affix quickly. ironic, even packages +12228|226|F|276130.19|1994-06-26|4-NOT SPECIFIED|Clerk#000000474|0|fully regular excuses? ironic foxes are across the dogge +12229|1250|O|106159.32|1996-07-24|1-URGENT|Clerk#000000293|0|ptotes boost slyly even accounts. +12230|712|O|161632.17|1998-04-05|2-HIGH|Clerk#000000383|0|s. regular foxes breach regularly pending theodo +12231|1021|O|243683.82|1997-07-30|4-NOT SPECIFIED|Clerk#000000012|0|sual sauternes use across the bold theodolites. req +12256|532|F|146646.67|1992-12-19|3-MEDIUM|Clerk#000000238|0|iously alongside of the +12257|149|O|128270.26|1996-04-17|2-HIGH|Clerk#000000278|0|y above the unusual foxes. slyly even accounts haggl +12258|1408|F|300041.05|1994-12-01|5-LOW|Clerk#000000878|0|ing foxes boost. stealthy +12259|250|F|173853.14|1993-02-15|2-HIGH|Clerk#000000282|0| boost about the carefully ironic ideas. fluffily iron +12260|496|F|172336.18|1992-11-26|3-MEDIUM|Clerk#000000484|0|s along the slyly ruthless pinto beans haggle about the +12261|1126|F|362237.85|1993-10-24|5-LOW|Clerk#000000279|0|ccounts use quickly about the furiously bold foxes. furiously final +12262|1441|O|139469.07|1995-12-11|5-LOW|Clerk#000000886|0|efully. slyly final theodolit +12263|550|O|161275.31|1995-07-07|2-HIGH|Clerk#000000566|0|ts sleep across the carefully bold instruc +12288|1153|O|125448.87|1996-11-06|1-URGENT|Clerk#000000183|0|slyly regular deposits above the foxes are at the packages- +12289|421|O|128835.39|1995-12-25|5-LOW|Clerk#000000269|0| even deposits. ironic, regular deposits haggle blith +12290|1304|O|103022.30|1995-07-10|3-MEDIUM|Clerk#000000947|0|ully pending instructions boost slyly furiously +12291|740|O|19328.06|1998-03-23|1-URGENT|Clerk#000000074|0|al deposits. warhorses inte +12292|739|F|176370.50|1992-06-03|4-NOT SPECIFIED|Clerk#000000375|0|sometimes final foxes after the qui +12293|329|O|102326.14|1995-06-19|2-HIGH|Clerk#000000103|0| quietly ironic instructions sleep carefully furiously iro +12294|784|O|182534.50|1995-07-06|5-LOW|Clerk#000000583|0|ns run about the qui +12295|883|F|84218.70|1993-11-10|5-LOW|Clerk#000000955|0|ost around the slowly iron +12320|298|O|118435.28|1995-12-21|1-URGENT|Clerk#000000356|0|o beans wake carefully theodolites. final gifts haggle quickly +12321|79|F|12511.06|1994-04-04|3-MEDIUM|Clerk#000000705|0|uriously ironic deposits cajole furiously doggedly ironic depend +12322|856|P|42466.03|1995-05-12|1-URGENT|Clerk#000000760|0| the special instructions detect fluffily ac +12323|926|P|139824.58|1995-04-03|4-NOT SPECIFIED|Clerk#000000019|0|ts detect above the even dep +12324|1033|O|202248.40|1998-08-02|3-MEDIUM|Clerk#000000746|0|ending theodolites try to thrash. regular deposits about the fluffily pending +12325|973|F|70150.43|1995-01-05|1-URGENT|Clerk#000000440|0|packages are final p +12326|506|F|181528.08|1995-02-03|1-URGENT|Clerk#000000765|0|ccounts are fluffily carefu +12327|166|O|39113.28|1998-04-23|4-NOT SPECIFIED|Clerk#000000969|0|tions haggle carefully slyly +12352|1466|F|331745.34|1992-03-24|3-MEDIUM|Clerk#000000997|0|eas. regular instructions need to boost slyly re +12353|595|O|219706.88|1996-04-13|4-NOT SPECIFIED|Clerk#000000312|0|ependencies. special dependencies nag quickly even packages. slyly final de +12354|1243|O|54975.46|1997-01-21|5-LOW|Clerk#000000859|0|g to the carefully pending excuses cajole +12355|178|P|286003.34|1995-05-29|4-NOT SPECIFIED|Clerk#000000081|0|arhorses. close, final foxes are slyly +12356|656|F|121696.19|1992-10-19|1-URGENT|Clerk#000000540|0|ges haggle quickly! blithely careful courts impress alongside of the bold fox +12357|154|O|90986.72|1995-08-23|2-HIGH|Clerk#000000169|0|instructions poach furiously final requests. quickly express depo +12358|880|O|231011.45|1996-10-10|2-HIGH|Clerk#000000335|0| blithely pending ideas. quickly ironic pinto b +12359|1400|O|215672.79|1997-05-29|4-NOT SPECIFIED|Clerk#000000382|0| express packages grow above the blithely even foxes: +12384|1168|O|213609.26|1998-08-02|3-MEDIUM|Clerk#000000311|0|gle. furiously unus +12385|821|F|92862.99|1992-11-24|5-LOW|Clerk#000000324|0|sts use furiously. ironi +12386|424|F|314497.24|1992-03-21|3-MEDIUM|Clerk#000000709|0|e fluffily ironic dolphins. quick +12387|638|O|52638.42|1997-07-03|2-HIGH|Clerk#000000051|0|o the quickly regular requests use slyly unusual theodolites. +12388|952|O|331123.13|1997-10-16|4-NOT SPECIFIED|Clerk#000000611|0|boost furiously furiously final accounts. slyly regular deposits are am +12389|653|F|242568.31|1994-08-05|3-MEDIUM|Clerk#000000139|0|s boost according to the slyly even dolphins. final depend +12390|1285|O|49792.77|1996-06-24|3-MEDIUM|Clerk#000000421|0|posits doze blithely. fluffily ironic d +12391|1000|O|94747.78|1998-07-01|5-LOW|Clerk#000000433|0|cies are blithely. furious +12416|1150|F|9933.08|1993-06-26|1-URGENT|Clerk#000000400|0|ow ideas cajole furiou +12417|1081|F|230795.43|1993-10-25|1-URGENT|Clerk#000000152|0|requests. furiously express instructions haggle. e +12418|1300|F|124402.47|1992-02-19|4-NOT SPECIFIED|Clerk#000000547|0|tructions. foxes nag furiously abo +12419|982|O|268861.58|1995-10-16|1-URGENT|Clerk#000000104|0|y. furiously final sauternes sleep slyly above the pending +12420|1489|F|179274.43|1993-12-27|3-MEDIUM|Clerk#000000798|0|ackages cajole permanently. blithely quick packages alongs +12421|673|O|212213.47|1995-11-02|1-URGENT|Clerk#000000203|0|pending theodolites wake: ironic, express platelets cajole furiously. +12422|575|P|217235.25|1995-05-22|3-MEDIUM|Clerk#000000349|0|ssly pending requests cajole quietly final i +12423|986|F|90571.46|1992-07-18|1-URGENT|Clerk#000000742|0|nic courts haggle carefully finally regular requests. depo +12448|511|O|158476.25|1995-11-09|1-URGENT|Clerk#000000711|0|he quickly pending accounts. ironic +12449|461|F|133597.11|1993-02-01|3-MEDIUM|Clerk#000000312|0|s hinder carefully across the iro +12450|1321|F|41643.96|1994-03-13|4-NOT SPECIFIED|Clerk#000000550|0|kages use quickly final accounts. carefully regular packages integrate blithe +12451|1150|F|298853.62|1993-04-20|5-LOW|Clerk#000000319|0|uriously even ideas hagg +12452|364|F|173339.75|1993-12-08|3-MEDIUM|Clerk#000000867|0|indle furiously near the quickly regular accounts: silent, +12453|1213|F|180966.45|1994-01-14|5-LOW|Clerk#000000085|0|ic ideas promise. slyly ironic pinto beans above the dinos wake quickly bold +12454|217|O|42464.91|1997-03-21|1-URGENT|Clerk#000000910|0|ic, regular deposits are against the carefully unusual accounts. e +12455|292|F|216570.72|1992-09-04|4-NOT SPECIFIED|Clerk#000000594|0|nusual asymptotes. regular ideas haggle blithely across the ironic ideas. +12480|320|F|122198.33|1994-07-08|3-MEDIUM|Clerk#000000055|0|ructions wake fluffily fluffily final gifts! furiou +12481|271|O|85849.06|1995-07-11|1-URGENT|Clerk#000000785|0|uests sleep furiously bold deposits. blithely express acc +12482|998|O|153413.61|1996-01-08|5-LOW|Clerk#000000311|0|y express dependencies along the f +12483|124|F|153915.13|1993-08-05|1-URGENT|Clerk#000000652|0|cial ideas sleep furiously against the final, regular re +12484|1027|O|184195.36|1995-08-22|3-MEDIUM|Clerk#000000268|0|olphins. blithely ironic platelets s +12485|188|F|209369.25|1993-08-08|1-URGENT|Clerk#000000994|0|tions along the ideas +12486|1286|P|184001.37|1995-02-21|2-HIGH|Clerk#000000206|0| deposits; quickly ironic packages use stealthily about the qui +12487|401|F|41222.94|1994-11-30|2-HIGH|Clerk#000000575|0|xes. requests sleep carefully +12512|1402|O|106021.12|1996-04-02|2-HIGH|Clerk#000000813|0|nal foxes are fluffily. foxes snooze about the ironi +12513|419|O|62011.18|1997-09-03|5-LOW|Clerk#000000422|0| wake final, special requests. express instructions cajole after the furi +12514|1495|F|38477.49|1994-04-25|2-HIGH|Clerk#000000120|0|c courts doubt express, bo +12515|1459|F|128077.61|1993-05-14|3-MEDIUM|Clerk#000000624|0|kly special accounts. blithely regular packages boost slyly packages. pl +12516|1373|F|112837.28|1994-05-25|5-LOW|Clerk#000000087|0|y after the quickly unusual gifts. fluffily exp +12517|1303|O|84279.32|1997-02-01|5-LOW|Clerk#000000162|0|packages. express packages impress furiously even, bold theodolite +12518|1082|F|153987.45|1993-07-23|5-LOW|Clerk#000000194|0|ultipliers serve furiously a +12519|913|F|187489.35|1994-01-01|2-HIGH|Clerk#000000387|0|ependencies. carefully unusual deposits use finally ironic deposits. e +12544|440|F|62982.76|1994-03-04|5-LOW|Clerk#000000600|0|thely above the even +12545|175|O|74242.81|1996-07-01|1-URGENT|Clerk#000000472|0|ly. carefully silent excuses use carefully around the reg +12546|217|O|89344.66|1996-02-08|4-NOT SPECIFIED|Clerk#000000547|0|ounts mold. blithely stealthy depths haggle blithely blithe +12547|1141|O|205195.87|1998-04-14|2-HIGH|Clerk#000000729|0|odolites? blithely ir +12548|145|O|209786.08|1997-11-20|4-NOT SPECIFIED|Clerk#000000517|0|s excuses x-ray against +12549|28|O|100471.72|1997-06-03|1-URGENT|Clerk#000000845|0|he furiously regular pint +12550|878|F|39446.33|1993-03-09|4-NOT SPECIFIED|Clerk#000000282|0|as. blithely ironic pinto beans wake. slyly bold deposits detect blithely alon +12551|790|F|176659.70|1992-06-12|5-LOW|Clerk#000000090|0| slyly alongside of the special waters. asymptotes outside the pend +12576|1057|F|33914.11|1993-01-26|4-NOT SPECIFIED|Clerk#000000762|0|n decoys behind the carefully final requests +12577|616|O|134783.72|1998-05-18|4-NOT SPECIFIED|Clerk#000000586|0|special instruction +12578|1207|O|255196.69|1996-11-15|2-HIGH|Clerk#000000150|0|p slyly furious foxes. slyly pending a +12579|193|O|47191.62|1995-06-17|4-NOT SPECIFIED|Clerk#000000536|0|y silent pinto beans-- ironic deposits affix. furiously fina +12580|589|F|41858.68|1993-01-14|5-LOW|Clerk#000000373|0|y bold theodolites above the carefully regular +12581|823|F|106379.64|1994-10-21|2-HIGH|Clerk#000000582|0| final requests after the final patterns wake blithel +12582|538|F|22603.80|1993-01-22|4-NOT SPECIFIED|Clerk#000000671|0| ironic packages against the requests slee +12583|943|O|42860.56|1996-01-18|5-LOW|Clerk#000000676|0|yly fluffily even accounts. quickly careful asymptotes boost. ironic, bo +12608|301|F|61932.81|1993-03-08|1-URGENT|Clerk#000000087|0| have to nag quietly among the carefully bold pinto beans. expres +12609|805|O|128069.23|1996-01-17|3-MEDIUM|Clerk#000000207|0|l requests haggle furiously +12610|85|F|10061.76|1993-07-17|5-LOW|Clerk#000000952|0| bold theodolites engage blithely against th +12611|41|O|185736.53|1995-10-16|3-MEDIUM|Clerk#000000579|0|ckly carefully regular deposits +12612|1444|F|185433.93|1993-12-22|5-LOW|Clerk#000000381|0| accounts. furiously ironic requests along the final, ruthless accounts cajol +12613|328|F|116318.24|1993-04-11|3-MEDIUM|Clerk#000000550|0|lithely express ins +12614|670|O|273057.78|1996-02-28|3-MEDIUM|Clerk#000000387|0|wake. quickly stealthy foxes affix slyly ironic requests. +12615|118|F|20866.10|1995-03-06|4-NOT SPECIFIED|Clerk#000000993|0|old packages. accounts use slyly after the foxes. +12640|413|O|76597.62|1998-07-20|2-HIGH|Clerk#000000081|0|ites. slyly express deposits integrate fluffily. ironic courts abo +12641|1097|F|239626.14|1995-02-23|5-LOW|Clerk#000000617|0|its wake according to the slyly unusual excuses. even patterns are carefully +12642|1243|F|247694.31|1994-04-28|1-URGENT|Clerk#000000015|0|symptotes thrash blithely above the furiously regular accounts. q +12643|322|F|124302.25|1993-03-20|5-LOW|Clerk#000000486|0| slyly silent requests. qui +12644|1159|F|150689.23|1992-02-01|2-HIGH|Clerk#000000394|0| the final instructions. blithely ironic asymptotes boost carefully regular +12645|250|F|231538.56|1994-07-07|5-LOW|Clerk#000000705|0|de of the blithely regular accounts use slyly final accounts. fluff +12646|1334|F|116946.28|1993-02-18|1-URGENT|Clerk#000000155|0|regular ideas. slyly ironic re +12647|1198|O|38285.07|1997-02-27|4-NOT SPECIFIED|Clerk#000000190|0|. regular theodolites sleep after the care +12672|257|F|37187.79|1994-07-07|4-NOT SPECIFIED|Clerk#000000963|0|es are carefully blithely unusual dugouts. regular, i +12673|62|F|21911.85|1994-06-12|1-URGENT|Clerk#000000435|0|ffily. express accounts sleep slyly regular deposit +12674|586|F|96952.15|1992-07-05|5-LOW|Clerk#000000811|0|xcuses. express deposits wake quickl +12675|679|F|155533.85|1994-01-28|3-MEDIUM|Clerk#000000921|0|r theodolites. furiously pending gifts alongside +12676|839|F|5884.55|1994-01-16|2-HIGH|Clerk#000000960|0|ake slyly special deposits. slyly un +12677|190|O|187187.63|1996-05-25|5-LOW|Clerk#000000500|0|ely above the furiously silent accounts; carefully regular depend +12678|844|O|77831.02|1998-01-26|5-LOW|Clerk#000000395|0|around the blithely slow packages nag quickly express packages. carefully +12679|1117|O|75859.23|1997-06-22|2-HIGH|Clerk#000000326|0|s. furiously pending deposits sleep furiously a +12704|439|F|143027.03|1993-02-10|5-LOW|Clerk#000000553|0|ackages sleep. pinto beans haggle furiously. quickly final dolphins use blit +12705|295|F|74933.03|1994-09-16|5-LOW|Clerk#000000983|0|grow above the fluffily final packages. slyly pending ideas nag furiou +12706|458|F|157344.88|1994-11-21|1-URGENT|Clerk#000000997|0|ing instructions. deposits cajole. slyly sp +12707|1219|F|253413.30|1993-05-30|2-HIGH|Clerk#000000820|0|ffix furiously according to the final, ironic dolphin +12708|172|F|262921.58|1993-01-08|5-LOW|Clerk#000000882|0|ly ironic deposits. quickly final sentiments cajole car +12709|268|O|74462.32|1996-05-11|5-LOW|Clerk#000000991|0|hely alongside of the a +12710|1169|F|305191.71|1993-08-18|1-URGENT|Clerk#000000329|0|es wake furiously ironic accounts. fluffily ironic pinto bea +12711|85|F|80711.39|1992-02-20|1-URGENT|Clerk#000000326|0|usual instructions. pending, final deposits use. +12736|751|F|346186.75|1993-03-09|5-LOW|Clerk#000000385|0|ithely express deposits. pinto beans n +12737|1187|F|320360.43|1994-05-04|1-URGENT|Clerk#000000047|0|ly regular dinos affix slyly. ironic, quick packages boost carefully. specia +12738|1334|O|182506.16|1998-06-12|2-HIGH|Clerk#000000613|0|sts boost: carefully even decoys integrate against the furiously reg +12739|772|F|56336.51|1992-03-02|4-NOT SPECIFIED|Clerk#000000078|0|side the bold, express depend +12740|439|O|61728.22|1997-06-05|2-HIGH|Clerk#000000643|0| the special deposits ca +12741|1348|F|162616.34|1992-07-20|4-NOT SPECIFIED|Clerk#000000800|0| of the instructions. furiou +12742|748|O|36355.83|1997-06-07|5-LOW|Clerk#000000591|0|always final sauternes. carefully regula +12743|695|F|101594.83|1993-06-24|2-HIGH|Clerk#000000015|0|inal foxes cajole quickly. bli +12768|1202|F|121309.88|1994-04-09|1-URGENT|Clerk#000000642|0|sly even accounts haggle slyly. blithely pending epitaphs boost. carefully f +12769|1057|F|29166.32|1992-01-08|4-NOT SPECIFIED|Clerk#000000590|0|blithely across the furiously express foxes; slyly silent pa +12770|1415|F|129333.56|1993-04-18|4-NOT SPECIFIED|Clerk#000000243|0|bove the special, regular ideas. final pinto beans grow? iro +12771|451|F|203114.43|1994-01-18|1-URGENT|Clerk#000000548|0|counts. furiously final dependencies sleep. fluffi +12772|1451|P|221390.02|1995-05-12|4-NOT SPECIFIED|Clerk#000000248|0|ual requests wake quickly even pinto +12773|817|F|304639.93|1995-01-12|5-LOW|Clerk#000000670|0|s, pending ideas. fluffily ironic deposits cajole blithely furiously unusual +12774|1108|F|60657.84|1992-10-10|1-URGENT|Clerk#000000067|0|ounts. quickly final requests +12775|979|O|127678.72|1996-10-15|5-LOW|Clerk#000000553|0|s the quickly unusual +12800|11|F|302431.56|1993-05-23|5-LOW|Clerk#000000898|0|. slyly final accounts cajole i +12801|1412|O|226079.43|1997-08-28|3-MEDIUM|Clerk#000000582|0|bove the fluffily express asymptot +12802|1481|O|233609.74|1998-03-02|1-URGENT|Clerk#000000774|0|ounts. special, pending ideas cajole pe +12803|392|F|27391.77|1993-02-26|4-NOT SPECIFIED|Clerk#000000876|0|sly final accounts use slyly final accounts. blithe +12804|734|F|358058.27|1992-05-26|3-MEDIUM|Clerk#000000544|0|l packages boost quickly ironic, +12805|478|O|76234.32|1996-12-11|3-MEDIUM|Clerk#000000035|0| to the quickly special platelets? +12806|526|O|208746.01|1995-12-25|4-NOT SPECIFIED|Clerk#000000181|0|s about the slyly regular pinto beans nag +12807|391|O|34178.61|1998-01-16|5-LOW|Clerk#000000393|0|uffily final accounts wake fur +12832|362|F|66392.28|1994-12-11|3-MEDIUM|Clerk#000000566|0|unts are after the regular packages. furiously pending +12833|1285|O|102301.35|1998-06-14|5-LOW|Clerk#000000773|0|nts. even, pending foxes are +12834|757|O|263553.51|1996-11-03|4-NOT SPECIFIED|Clerk#000000370|0|ns. unusual ideas are. somas b +12835|370|O|142811.34|1997-01-20|4-NOT SPECIFIED|Clerk#000000894|0|ges. slyly final id +12836|1057|O|222420.89|1996-04-18|3-MEDIUM|Clerk#000000728|0|es sleep furiously against the quickly even inst +12837|590|F|112787.85|1992-12-03|3-MEDIUM|Clerk#000000431|0|ter the slowly unusual foxes. blithely express pinto beans haggle. furiou +12838|112|O|104930.86|1998-07-01|1-URGENT|Clerk#000000424|0|fully ironic foxes. quickly pending accounts about the fin +12839|1424|O|178226.93|1998-01-08|3-MEDIUM|Clerk#000001000|0|ng pinto beans. unusual theodolites engag +12864|647|F|142470.94|1994-05-17|2-HIGH|Clerk#000000620|0| the ironic, silent foxes. special +12865|1271|O|244542.24|1997-05-23|5-LOW|Clerk#000000362|0|requests boost slyly carefully even instructions. carefully regular packages c +12866|1433|O|165429.43|1997-01-17|3-MEDIUM|Clerk#000000996|0|y regular requests play carefully against the always final +12867|59|F|197098.68|1995-03-12|4-NOT SPECIFIED|Clerk#000000638|0|lar platelets. blithely unusual deposits cajole carefully s +12868|1042|P|229577.12|1995-03-02|1-URGENT|Clerk#000000993|0|ns sleep above the carefully ex +12869|1396|F|131379.62|1994-01-26|4-NOT SPECIFIED|Clerk#000000871|0|s the pending foxes: fluffily regular requests wake slyly against the slyl +12870|1366|F|51595.17|1993-07-28|1-URGENT|Clerk#000000157|0| furiously dogged theodolites. regular requests among the blithely +12871|1174|O|194923.17|1995-10-05|4-NOT SPECIFIED|Clerk#000000646|0|ally ironic packages. blithely regular asymptotes are a +12896|370|O|321570.67|1996-12-22|1-URGENT|Clerk#000000337|0|nic theodolites. slyly even pinto beans use quickly. care +12897|1169|O|153229.93|1995-07-19|4-NOT SPECIFIED|Clerk#000000854|0|ost carefully regular packages. blithely +12898|1045|F|44854.49|1994-09-17|3-MEDIUM|Clerk#000000873|0|packages maintain carefully after +12899|868|O|40541.89|1996-04-07|4-NOT SPECIFIED|Clerk#000000006|0|efully pending ideas cajole fluf +12900|220|F|41268.96|1993-05-04|2-HIGH|Clerk#000000285|0|s. even requests sleep carefully blithely unusual ac +12901|1283|F|302296.36|1994-05-06|2-HIGH|Clerk#000000994|0|ely final requests. fu +12902|640|F|321334.39|1993-10-30|4-NOT SPECIFIED|Clerk#000000254|0|y regular deposits. regular instructions sleep +12903|301|F|89081.29|1994-09-26|1-URGENT|Clerk#000000914|0|wake furiously fluffily bold dolphins. blithely regular pinto beans sle +12928|634|F|258054.14|1994-03-28|2-HIGH|Clerk#000000465|0|ng slyly after the final requests. furiously special +12929|917|F|138543.10|1993-08-31|1-URGENT|Clerk#000000397|0|g the blithely bold asymptotes. pending dependencies +12930|1072|O|10854.39|1995-11-25|2-HIGH|Clerk#000000162|0|es cajole alongside of the fluffily pending dependencies. regular +12931|775|F|72091.62|1992-04-25|3-MEDIUM|Clerk#000000196|0|final foxes boost across the slyly pending dependencies. even, +12932|238|O|151284.17|1997-08-27|3-MEDIUM|Clerk#000000787|0|ackages. foxes cajole blithely regular +12933|173|O|253181.34|1998-02-17|3-MEDIUM|Clerk#000000224|0|haggle according to +12934|623|F|273516.60|1994-03-06|4-NOT SPECIFIED|Clerk#000000441|0|sual, pending dependencies among +12935|509|F|69433.26|1994-05-10|3-MEDIUM|Clerk#000000549|0|gouts at the even packages cajole slyly final packages. slyly enticin +12960|1243|F|132107.73|1993-10-10|2-HIGH|Clerk#000000340|0|ng theodolites haggle after the final id +12961|1144|F|133684.91|1994-12-13|2-HIGH|Clerk#000000913|0|rding to the enticing, final foxes use blithely furiou +12962|1111|O|130541.81|1995-10-29|1-URGENT|Clerk#000000488|0|. accounts breach carefully blithely ironic deposits. +12963|1232|O|72621.23|1998-07-08|3-MEDIUM|Clerk#000000546|0|uriously regular deposits wake slowly along t +12964|556|O|228128.18|1998-01-13|2-HIGH|Clerk#000000980|0|ronic instructions. quickly regular a +12965|964|F|107134.13|1993-06-26|3-MEDIUM|Clerk#000000650|0|ate slyly against the carefully final packages. furiously final requests alo +12966|224|O|51608.06|1997-10-11|5-LOW|Clerk#000000252|0|ly furiously final packages. carefully regular packages integrate quic +12967|1147|F|9777.25|1993-09-22|2-HIGH|Clerk#000000650|0|gly final deposits are slyly carefully ironic cour +12992|139|O|199084.84|1997-02-25|5-LOW|Clerk#000000099|0|xpress theodolites use across the un +12993|1348|O|46875.17|1998-05-14|5-LOW|Clerk#000000435|0| across the depths. idle, final accounts lose furiously regular, +12994|1451|F|54188.56|1994-11-18|5-LOW|Clerk#000000557|0|ily among the slyly unusual deposits. quickly pending acco +12995|1162|O|200689.05|1996-07-29|3-MEDIUM|Clerk#000000027|0|ts except the quickly express request +12996|967|O|107497.47|1995-12-05|4-NOT SPECIFIED|Clerk#000000531|0|ccounts. blithely ironic pinto beans cajol +12997|520|O|23304.56|1996-05-27|1-URGENT|Clerk#000000085|0|accounts boost. final asymptotes affix blithely fluff +12998|799|O|25952.72|1996-10-03|2-HIGH|Clerk#000000213|0|instructions sleep. express, final patterns detect furiously. furi +12999|940|F|216567.07|1993-04-04|2-HIGH|Clerk#000000745|0|nusual foxes. express accounts sublate q +13024|664|F|58015.05|1992-03-14|3-MEDIUM|Clerk#000000700|0| bold requests nag quickly. d +13025|158|O|138165.03|1998-01-28|2-HIGH|Clerk#000000785|0|lly regular instructions serve. special deposits against the careful +13026|1126|O|194927.69|1997-04-01|2-HIGH|Clerk#000000050|0| bold ideas! express ideas across the furiously dogged theodolites use bold, +13027|955|F|160057.71|1992-01-16|1-URGENT|Clerk#000000236|0|ongside of the ideas wak +13028|685|F|231028.06|1994-04-09|1-URGENT|Clerk#000000687|0|regular platelets a +13029|340|O|177062.13|1997-11-11|3-MEDIUM|Clerk#000000699|0|riously above the blithely f +13030|1459|F|146978.50|1994-07-23|3-MEDIUM|Clerk#000000878|0|hely ironic packages are slyly regular ideas. quickly final pack +13031|7|F|237595.83|1992-12-05|5-LOW|Clerk#000000325|0|s are furiously. busy requests haggle furiously pinto beans. asymptotes are. +13056|437|F|193618.95|1994-04-23|4-NOT SPECIFIED|Clerk#000000174|0|ounts. quickly regular packages above the furiously unusual sauternes ha +13057|67|O|102973.85|1997-12-16|1-URGENT|Clerk#000000125|0|y. final requests breach furiously. regular deposits engage. +13058|1156|O|12461.38|1997-03-26|1-URGENT|Clerk#000000685|0|ly! special instructions sleep furiously throughout the deposits. +13059|136|O|197435.35|1997-05-31|5-LOW|Clerk#000000463|0| requests. blithely special +13060|1345|O|272394.13|1997-02-06|4-NOT SPECIFIED|Clerk#000000724|0|ously above the pending, special theodolites. dolphins ar +13061|821|O|76034.36|1997-09-17|1-URGENT|Clerk#000000937|0|regular deposits. s +13062|1291|O|63228.29|1996-05-03|2-HIGH|Clerk#000000216|0|s asymptotes cajole carefully regular depen +13063|1412|O|318204.60|1997-01-15|5-LOW|Clerk#000000506|0|packages are slyly fluffil +13088|1460|F|261581.56|1993-04-23|4-NOT SPECIFIED|Clerk#000000089|0|s. even, final packages on the carefully regular platelets cajole quick +13089|1403|O|277440.38|1995-12-15|4-NOT SPECIFIED|Clerk#000000502|0|e slyly ironic pinto beans. blithely express accounts boost. pen +13090|130|F|146458.92|1993-07-27|4-NOT SPECIFIED|Clerk#000000717|0|packages impress quickly across the fluffily regul +13091|856|F|200741.15|1994-11-16|3-MEDIUM|Clerk#000000786|0|ironic requests nag furiously stealthy pinto beans. slyly even pains +13092|1430|O|142733.13|1998-06-24|1-URGENT|Clerk#000000241|0|eans haggle furiously about the slyly daring deposi +13093|1132|O|144898.05|1996-05-05|2-HIGH|Clerk#000000244|0| slyly even sheaves haggl +13094|1129|F|64336.85|1993-08-19|4-NOT SPECIFIED|Clerk#000000376|0|theodolites serve around the slyly special accounts. instruc +13095|1454|O|282335.80|1996-07-22|1-URGENT|Clerk#000000837|0|ve theodolites detect according to the slyly special grouches. un +13120|1039|F|90929.21|1994-12-15|5-LOW|Clerk#000000149|0| to the quickly express requests nag carefully stealthily regular requ +13121|878|F|190958.73|1993-03-08|2-HIGH|Clerk#000000148|0|cross the blithely ironic the +13122|242|F|164977.59|1994-09-24|2-HIGH|Clerk#000000229|0|t blithely furiously special accounts. carefully regular +13123|841|O|208768.85|1998-07-03|2-HIGH|Clerk#000000231|0|fter the slyly speci +13124|10|F|57676.34|1993-12-18|3-MEDIUM|Clerk#000000862|0|ggle quickly according to the carefully even pac +13125|355|F|190034.02|1993-12-14|4-NOT SPECIFIED|Clerk#000000302|0|ly quickly final ideas. carefully bold ideas slee +13126|956|O|131328.54|1995-10-20|4-NOT SPECIFIED|Clerk#000000919|0|ithely bold foxes wake. accounts according to the quickly ev +13127|1165|F|38692.83|1993-08-01|3-MEDIUM|Clerk#000000178|0|cording to the ironic asymptotes sleep care +13152|850|F|283938.70|1994-02-15|2-HIGH|Clerk#000000367|0|ts. blithely final instructions sleep quickly final requ +13153|1144|O|165659.63|1996-11-06|1-URGENT|Clerk#000000666|0|refully across the carefully careful notornis. qu +13154|520|O|286298.87|1997-10-22|5-LOW|Clerk#000000557|0|foxes? quickly blithe ideas nag slyly. blithely regular packages cajole. fluff +13155|1079|O|190720.20|1996-06-18|1-URGENT|Clerk#000000727|0|ns play. express requests cajole quickly theodolites. carefully furious dino +13156|1283|O|180693.69|1995-10-06|5-LOW|Clerk#000000482|0| about the carefully regular a +13157|656|F|277209.62|1992-02-12|3-MEDIUM|Clerk#000000655|0|regular requests wake. never special ac +13158|134|F|198301.99|1992-11-21|1-URGENT|Clerk#000000638|0|ns promise slyly even requests. carefully ironic packages haggle +13159|784|O|175684.88|1996-12-02|1-URGENT|Clerk#000000262|0|efully among the blithely regular instructions. carefu +13184|472|O|21843.01|1998-03-28|4-NOT SPECIFIED|Clerk#000000845|0|ilent deposits haggle furiously about the silent deposits. +13185|805|O|300236.26|1997-07-15|5-LOW|Clerk#000000862|0|ly even tithes sleep daringly. unusual, ironic accou +13186|556|O|206062.94|1996-09-18|2-HIGH|Clerk#000000427|0|ckly pending accounts. quick +13187|923|F|78566.07|1993-12-09|2-HIGH|Clerk#000000421|0|ns haggle slyly. slyly pending instructions at the carefully final +13188|1436|O|95591.25|1998-07-20|3-MEDIUM|Clerk#000000061|0|ckey players. accounts haggle fluffily against the foxes. unusual, expre +13189|94|F|2361.93|1995-04-05|1-URGENT|Clerk#000000002|0|l deposits above the pending pinto beans are +13190|136|O|24775.00|1998-05-04|4-NOT SPECIFIED|Clerk#000000173|0|furiously express accounts. carefully i +13191|214|O|331578.75|1997-12-24|5-LOW|Clerk#000000080|0|regular accounts at the blithely even sh +13216|1075|F|97503.77|1992-04-14|3-MEDIUM|Clerk#000000901|0|e furiously express pinto beans. unusual deposits are. even instructio +13217|946|O|67106.36|1997-09-25|5-LOW|Clerk#000000659|0|se dependencies nag blithely after the blithely regular ideas. +13218|1438|F|210525.16|1994-05-17|2-HIGH|Clerk#000000715|0|ccounts. slyly pending instru +13219|535|O|190074.19|1997-10-15|2-HIGH|Clerk#000000251|0|s. regular, special platelets wake. unusual, even +13220|1480|O|134628.97|1998-07-31|1-URGENT|Clerk#000000586|0|refully final platelets: accounts of the busily special +13221|946|O|106536.33|1995-10-15|4-NOT SPECIFIED|Clerk#000000459|0|lthy accounts around the +13222|1363|O|93525.50|1997-05-04|4-NOT SPECIFIED|Clerk#000000435|0|quests. furiously silent packages +13223|352|O|45917.67|1996-08-08|4-NOT SPECIFIED|Clerk#000000713|0| slyly blithely regular requests. furiously regular multipliers wake +13248|892|O|39800.14|1997-02-02|3-MEDIUM|Clerk#000000920|0|eans use. even packages eat after the ca +13249|569|O|222028.79|1997-07-18|5-LOW|Clerk#000000660|0|nstructions nag blithely quick +13250|1325|O|141857.68|1997-08-18|3-MEDIUM|Clerk#000000150|0|sts about the final requests a +13251|982|O|123168.81|1997-03-28|1-URGENT|Clerk#000000928|0|cording to the blithely silent deposit +13252|1309|F|163473.91|1994-03-23|4-NOT SPECIFIED|Clerk#000000026|0|n ideas must boost blithely. expre +13253|790|O|277363.52|1996-10-28|2-HIGH|Clerk#000000767|0|refully even packages print. blithely bold deposits boost fluffily +13254|1066|O|204264.00|1998-02-23|3-MEDIUM|Clerk#000000890|0|blithely silent packages. fin +13255|1115|F|113899.92|1993-07-18|3-MEDIUM|Clerk#000000993|0|metimes across the even deposits. pending accounts affix blithely furi +13280|314|F|236922.45|1994-09-12|2-HIGH|Clerk#000000073|0|pinto beans promise carefully final requests. r +13281|1480|F|164425.24|1992-04-23|1-URGENT|Clerk#000000327|0|slyly. regularly ironic deposits haggle bli +13282|817|F|153262.10|1992-05-10|5-LOW|Clerk#000000436|0|luffily express foxes +13283|946|O|129981.62|1997-12-29|4-NOT SPECIFIED|Clerk#000000842|0|dependencies? quickly quick deposits cajol +13284|851|F|136289.59|1992-08-13|2-HIGH|Clerk#000000186|0|equests. slyly final de +13285|406|O|8165.39|1995-05-17|4-NOT SPECIFIED|Clerk#000000312|0|r packages. silent, even +13286|1114|O|81226.73|1995-10-12|2-HIGH|Clerk#000000186|0|osits. slyly express requests promise quickly. bold, final asymptote +13287|895|O|168246.03|1997-03-10|3-MEDIUM|Clerk#000000335|0|e theodolites. blithely even deposits dazzle care +13312|1324|O|80963.75|1996-11-04|1-URGENT|Clerk#000000904|0|final accounts wake slyl +13313|1438|F|254146.32|1994-07-17|4-NOT SPECIFIED|Clerk#000000036|0|d platelets. slyly express requests print carefully across the quickl +13314|412|F|226838.60|1994-05-14|2-HIGH|Clerk#000000842|0|ajole stealthily even deposits. furiously express foxes was evenly r +13315|449|O|192954.51|1996-10-16|2-HIGH|Clerk#000000759|0|thinly ironic accoun +13316|1316|F|42308.46|1992-10-23|5-LOW|Clerk#000000555|0|tain even, pending instructions. quickly pending pinto beans sleep against the +13317|865|O|43720.88|1996-04-12|3-MEDIUM|Clerk#000000096|0|ggedly unusual packages along the carefully final +13318|325|O|247805.76|1997-06-11|4-NOT SPECIFIED|Clerk#000000381|0|ounts. sometimes ironic packages sleep stealthily. slyly regular accounts are +13319|425|O|138467.85|1996-01-19|1-URGENT|Clerk#000000158|0|ecial excuses boost. carefully regular asymptotes was acco +13344|367|O|90946.06|1997-03-27|4-NOT SPECIFIED|Clerk#000000924|0|de the quickly regular excuses. blithely express packages nod fur +13345|1339|F|136543.60|1992-09-03|4-NOT SPECIFIED|Clerk#000000876|0|thely special dolphins. slyly regular foxes sleep carefull +13346|1012|F|244898.42|1992-11-16|5-LOW|Clerk#000000594|0|thely bold foxes sleep final reque +13347|560|F|250026.98|1993-04-24|4-NOT SPECIFIED|Clerk#000000933|0|uriously against the carefully final foxes. carefully +13348|1267|F|94270.40|1993-11-08|3-MEDIUM|Clerk#000000878|0|ns doubt fluffily across the requests. even theodolites around the fluffi +13349|1454|F|91069.45|1994-09-20|2-HIGH|Clerk#000000916|0|usual courts haggle ruthlessly. final deposi +13350|1307|O|246713.06|1998-05-06|2-HIGH|Clerk#000000152|0|gular requests cajole quickl +13351|709|F|203403.50|1993-05-07|3-MEDIUM|Clerk#000000892|0|eposits haggle slowly alongside of +13376|1456|F|245552.88|1992-10-10|3-MEDIUM|Clerk#000000807|0| deposits. furiously regular packages unwind slyly bl +13377|394|O|60077.37|1995-07-19|2-HIGH|Clerk#000000094|0|ily along the bold deposits. carefully unusual accounts use quickl +13378|1151|F|207411.39|1994-09-22|5-LOW|Clerk#000000729|0|nis integrate; deposits wake bravely special frets. furiously expre +13379|286|F|107484.04|1993-11-08|5-LOW|Clerk#000000398|0|hely special dependencies. carefully unusual deposits are regularly. b +13380|934|F|129938.34|1994-07-16|1-URGENT|Clerk#000000683|0|ffy deposits haggle blithely. bold deposits amon +13381|1109|O|102850.64|1995-08-18|3-MEDIUM|Clerk#000000835|0|s platelets nod carefully. final, unusual deposits nag blith +13382|1207|O|64313.96|1995-11-02|4-NOT SPECIFIED|Clerk#000000427|0|kages. regular packages boost slyly alongside +13383|1346|F|165841.68|1992-06-16|4-NOT SPECIFIED|Clerk#000000258|0|pecial ideas boost stealthily about the regular, express pinto bean +13408|1370|F|211990.67|1994-02-15|5-LOW|Clerk#000000772|0| since the pinto beans. furiously pending accounts ru +13409|1279|F|46643.47|1993-07-14|4-NOT SPECIFIED|Clerk#000000002|0|n dependencies detect furi +13410|592|F|71187.66|1993-06-07|4-NOT SPECIFIED|Clerk#000000922|0|lly ironic braids are. quickly final gifts haggle si +13411|1376|F|130230.72|1994-04-13|2-HIGH|Clerk#000000179|0|l foxes. silent theodolit +13412|1240|O|115408.80|1997-07-12|1-URGENT|Clerk#000000124|0|lithely slow packages. packages past the ru +13413|473|F|231772.27|1993-01-30|1-URGENT|Clerk#000000565|0|ironic instructions. special instructions boost quick +13414|1333|O|143244.82|1995-07-07|3-MEDIUM|Clerk#000000693|0|across the blithely regular +13415|1222|O|271662.08|1997-05-31|2-HIGH|Clerk#000000851|0|ully. packages haggle slyly around the +13440|865|F|24449.73|1993-10-14|4-NOT SPECIFIED|Clerk#000000189|0|fily ironic accounts. quietly regular deposits among th +13441|1282|O|60048.20|1995-08-31|1-URGENT|Clerk#000000983|0|tes. blithely regular packages wake enticingly. quickly da +13442|238|O|138794.82|1997-08-06|4-NOT SPECIFIED|Clerk#000000830|0|p quickly fluffily +13443|545|F|216308.57|1993-10-07|3-MEDIUM|Clerk#000000379|0|uriously silent packages nag. ideas cajole quickly carefully regula +13444|176|F|304179.27|1992-01-06|2-HIGH|Clerk#000000199|0|. forges are carefully. furiously final packages are blithely ironic the +13445|682|O|21693.67|1997-12-24|4-NOT SPECIFIED|Clerk#000000599|0|quickly. excuses cajole. idly express packages cajole blithely pending pinto b +13446|484|O|55646.82|1996-02-29|1-URGENT|Clerk#000000050|0|lly regular requests. blithely express excuses integra +13447|244|F|72392.32|1993-01-09|2-HIGH|Clerk#000000925|0|ts. blithely ironic ideas accord +13472|814|O|69332.61|1995-10-27|1-URGENT|Clerk#000000454|0|uests. regular asymptotes haggle quickly aro +13473|655|O|192774.21|1996-03-22|5-LOW|Clerk#000000655|0|usual pinto beans haggle blithely at the carefully regular p +13474|1069|O|101285.14|1997-06-09|3-MEDIUM|Clerk#000000912|0|out the bold instructions. requests a +13475|1403|F|295575.64|1994-06-06|1-URGENT|Clerk#000000426|0|ake among the quickly express depo +13476|1459|F|264702.77|1993-10-17|4-NOT SPECIFIED|Clerk#000000203|0|r, permanent accounts. ironic, ironic packages dazzle at the +13477|1276|O|143935.11|1997-11-23|3-MEDIUM|Clerk#000000242|0|express instructions. regular ideas +13478|325|O|167211.22|1998-01-04|2-HIGH|Clerk#000000849|0|ajole ironic, stealthy theodolites. d +13479|1217|F|170168.00|1994-12-05|2-HIGH|Clerk#000000469|0|s the furiously regular accounts. blithely +13504|1495|O|126515.95|1997-06-18|2-HIGH|Clerk#000000486|0|ngly after the pending accounts. final instr +13505|286|O|219315.83|1997-06-03|3-MEDIUM|Clerk#000000880|0|sly against the furiously regular packages. care +13506|1099|O|111048.07|1995-07-22|5-LOW|Clerk#000000974|0|. slyly ironic requests among the +13507|923|F|117398.65|1992-12-30|3-MEDIUM|Clerk#000000127|0|. bold deposits affix furiously. furiously ironi +13508|802|O|2962.11|1997-04-17|4-NOT SPECIFIED|Clerk#000000951|0|accounts. blithely eve +13509|946|O|68465.06|1996-10-07|2-HIGH|Clerk#000000562|0|p. dolphins are. regular reques +13510|710|O|80383.62|1997-10-15|3-MEDIUM|Clerk#000000723|0|tions. slyly ironic in +13511|467|O|134751.21|1998-01-03|4-NOT SPECIFIED|Clerk#000000611|0|ly regular foxes are slyly furiously bold deposits. furiously fin +13536|316|F|192964.26|1994-08-19|3-MEDIUM|Clerk#000000262|0|posits. blithely final i +13537|430|F|26435.99|1993-05-31|5-LOW|Clerk#000000623|0|telets haggle carefully. quickly regular frays are! slyly regular pla +13538|782|O|65147.01|1997-02-01|2-HIGH|Clerk#000000598|0|lly alongside of the pending, unusual reque +13539|1231|O|190664.21|1997-02-13|3-MEDIUM|Clerk#000000022|0|ding dolphins use. final pinto beans +13540|460|F|277929.48|1993-05-24|2-HIGH|Clerk#000000994|0|. blithely even asymptotes poach blithely alongside of the doggedly un +13541|634|O|53890.86|1996-07-29|4-NOT SPECIFIED|Clerk#000000094|0| the furiously quick accounts. final packages nag +13542|1016|F|302527.26|1994-03-09|5-LOW|Clerk#000000170|0|ts are until the furiously +13543|790|F|24097.46|1992-08-09|3-MEDIUM|Clerk#000000636|0|l dependencies nag against the packages. expr +13568|31|F|81474.17|1993-05-07|5-LOW|Clerk#000000024|0|sts. carefully bold dolphins cajole across the even requ +13569|839|P|187147.11|1995-04-11|1-URGENT|Clerk#000000973|0|s? regular platelets cajole above the furiousl +13570|1468|F|226767.02|1992-12-03|4-NOT SPECIFIED|Clerk#000000602|0|e of the theodolites. slyly pending deposits between the regula +13571|1231|O|142142.08|1998-06-04|5-LOW|Clerk#000000452|0|ites? carefully regular +13572|1498|F|115177.91|1992-05-18|1-URGENT|Clerk#000000144|0|inal requests are regularly against th +13573|898|O|78389.93|1997-04-23|5-LOW|Clerk#000000144|0| slyly final packages. carefully e +13574|151|O|72886.11|1997-11-14|1-URGENT|Clerk#000000472|0|y above the fluffily final instructions. express +13575|349|F|92113.36|1992-08-30|1-URGENT|Clerk#000000008|0|! express, express instruct +13600|1129|F|124567.73|1993-07-11|4-NOT SPECIFIED|Clerk#000000910|0|lites boost furiously after the quickly ironic packages. carefully fina +13601|8|F|256717.52|1992-08-17|5-LOW|Clerk#000000608|0| ironic, special foxes- +13602|1348|F|284393.60|1994-01-14|5-LOW|Clerk#000000312|0|nusual packages cajole stealthily regular accounts. regular, +13603|496|O|198335.91|1997-06-09|4-NOT SPECIFIED|Clerk#000000777|0|nic deposits? blithely ironic packages do nag +13604|1141|F|280511.75|1994-02-03|4-NOT SPECIFIED|Clerk#000000798|0|p stealthily. requests thrash carefully. accounts wake furiously afte +13605|1388|O|201717.90|1996-06-14|3-MEDIUM|Clerk#000000099|0| regular depths use furiou +13606|160|F|209589.77|1994-04-27|4-NOT SPECIFIED|Clerk#000000310|0|eas. unusual courts haggle slyly ruthless realms. even, unusua +13607|358|F|210043.39|1993-11-19|1-URGENT|Clerk#000000366|0|es mold. blithely express packages integrate after the bold pinto beans. b +13632|1084|F|264841.12|1994-03-11|3-MEDIUM|Clerk#000000635|0|quickly special ideas use bravely bold, bold packag +13633|1373|F|173408.51|1992-04-04|4-NOT SPECIFIED|Clerk#000000419|0|ifts cajole quickly +13634|869|P|43165.51|1995-04-19|2-HIGH|Clerk#000000538|0|ain carefully according to t +13635|269|F|121071.76|1994-05-02|1-URGENT|Clerk#000000172|0|uctions thrash quickly. furiously regular requests about the n +13636|107|F|171401.11|1994-01-23|5-LOW|Clerk#000000855|0|gular ideas wake among th +13637|188|O|66820.97|1995-12-11|1-URGENT|Clerk#000000074|0| quickly ironic requests. care +13638|1361|O|327915.84|1995-10-01|2-HIGH|Clerk#000000261|0| ironic requests haggle quickly ironic packages. final +13639|1009|O|126608.97|1997-06-13|2-HIGH|Clerk#000000848|0|s cajole slyly doggedly ironic asymptotes. ca +13664|814|O|292106.85|1995-12-16|3-MEDIUM|Clerk#000000542|0|ely bold theodolites nag. pinto beans above the p +13665|1039|O|181151.79|1996-04-08|1-URGENT|Clerk#000000591|0|as wake even, pending requests +13666|445|F|59180.35|1992-03-03|4-NOT SPECIFIED|Clerk#000000031|0| the packages. ironi +13667|1216|O|208665.97|1996-12-04|2-HIGH|Clerk#000000893|0| ruthless ideas poach ironically-- unusual +13668|878|F|218731.00|1992-02-25|1-URGENT|Clerk#000000198|0|press ideas. blithely unusual instructions are blithely. carefully final pac +13669|454|O|178957.15|1996-08-15|3-MEDIUM|Clerk#000000955|0| instructions could have to cajol +13670|226|F|153065.25|1992-05-24|1-URGENT|Clerk#000000988|0|s haggle at the even platelets. even +13671|1291|O|218819.92|1996-07-14|1-URGENT|Clerk#000000321|0| blithely regular requests. furiously special idea +13696|722|O|118614.92|1997-08-28|5-LOW|Clerk#000000882|0|ag fluffily carefully even theodolite +13697|1457|O|103807.36|1998-04-06|4-NOT SPECIFIED|Clerk#000000473|0|st the blithely unusual foxes cajole fluf +13698|1483|F|155040.76|1994-08-05|4-NOT SPECIFIED|Clerk#000000640|0|iously bold deposits are carefully blithely unusual +13699|577|O|22846.00|1997-04-08|4-NOT SPECIFIED|Clerk#000000746|0|. ironically ironic foxes among the f +13700|1063|F|20210.10|1992-02-14|1-URGENT|Clerk#000000801|0|heodolites cajole blithely. blithely unusual de +13701|1270|O|222424.50|1998-05-18|2-HIGH|Clerk#000000270|0|final accounts wake furiously among the regular foxes. slyly bold t +13702|1132|O|51969.64|1995-09-11|5-LOW|Clerk#000000834|0|round the fluffily silen +13703|236|O|219200.99|1996-12-29|5-LOW|Clerk#000000778|0| quickly furiously regular accou +13728|4|O|123722.52|1995-12-11|2-HIGH|Clerk#000000094|0|theodolites. ironic deposits boost among the slyly regular instru +13729|79|F|88426.57|1994-01-02|4-NOT SPECIFIED|Clerk#000000866|0|y regular platelets +13730|952|F|36769.57|1995-05-10|2-HIGH|Clerk#000000826|0|- quickly even pinto beans boost fluffily ironic, even requests. ironic, u +13731|1475|F|209159.47|1993-05-10|4-NOT SPECIFIED|Clerk#000000549|0|beans detect boldly. sheaves after the eve +13732|605|F|166563.09|1992-11-28|1-URGENT|Clerk#000000599|0|uriously regular courts +13733|100|O|328307.40|1998-01-03|5-LOW|Clerk#000000431|0|e quickly express foxes. blithely ironic instructio +13734|124|O|156502.58|1996-08-14|2-HIGH|Clerk#000000344|0|n deposits should have to thrash fluffily quickly regu +13735|58|F|130804.16|1994-05-22|3-MEDIUM|Clerk#000000589|0|ccounts are slyly blithely final accounts. furiously final accounts w +13760|964|O|130352.76|1996-06-03|5-LOW|Clerk#000000053|0|s wake. blithely bold dependencies +13761|169|F|199387.32|1994-10-18|5-LOW|Clerk#000000226|0|ainst the quickly regular accounts. quickly en +13762|1337|F|210739.37|1993-06-22|3-MEDIUM|Clerk#000000053|0|re blithely ideas. blithely regular ideas haggle above the foxe +13763|1142|O|164241.80|1997-06-27|3-MEDIUM|Clerk#000000027|0|as affix carefully express ideas. carefully ironic asymptotes unwin +13764|598|O|122061.97|1995-07-14|3-MEDIUM|Clerk#000000236|0|ronic deposits? furiously re +13765|715|F|156724.02|1994-04-06|4-NOT SPECIFIED|Clerk#000000969|0|ronic theodolites will have to haggle except the slyl +13766|1387|F|45293.38|1992-10-19|1-URGENT|Clerk#000000274|0|boost unusual accounts. regular reques +13767|923|F|211468.27|1993-08-27|2-HIGH|Clerk#000000679|0|. thinly express dolphins sleep; slyly final instr +13792|1366|O|48602.86|1996-02-04|4-NOT SPECIFIED|Clerk#000000980|0|y slyly final foxes. slyly even ideas affix furiously dependencies. caref +13793|904|O|18039.82|1995-09-18|2-HIGH|Clerk#000000222|0|e blithely above the slyly pending ideas. furiously furious pl +13794|587|F|234351.58|1994-01-05|1-URGENT|Clerk#000000119|0|ages cajole furiously alongside of the slyly express ideas- +13795|1406|P|233445.40|1995-04-11|4-NOT SPECIFIED|Clerk#000000673|0|ld dolphins cajole quickly unusual instructions. +13796|1004|O|245467.47|1997-06-22|4-NOT SPECIFIED|Clerk#000000344|0|special deposits wake +13797|272|O|227061.71|1996-08-26|1-URGENT|Clerk#000000379|0|usly silent theodolites wake slyly across +13798|1298|O|123932.29|1996-02-12|1-URGENT|Clerk#000000778|0|fluffily special, bol +13799|994|F|142646.96|1993-12-02|1-URGENT|Clerk#000000945|0|g according to the regularly even requests. carefully bold accoun +13824|1096|F|115028.49|1994-12-28|5-LOW|Clerk#000000604|0|equests. slow, sly ideas cajole fu +13825|56|F|174217.02|1994-03-22|2-HIGH|Clerk#000000038|0|ests. slyly express pin +13826|232|O|160230.62|1997-02-22|3-MEDIUM|Clerk#000000053|0|ost packages. slyly pending requests are c +13827|479|F|44465.43|1993-06-21|5-LOW|Clerk#000000455|0|busily close requests. ironic, even pinto beans use furiously requests. c +13828|985|F|85589.73|1994-07-13|1-URGENT|Clerk#000000682|0| unusual instructions sleep quickly. packages +13829|1075|O|188654.94|1996-09-22|3-MEDIUM|Clerk#000000010|0|raids alongside of the quick +13830|598|F|169613.65|1994-12-22|2-HIGH|Clerk#000000693|0|impress. even, special requests alongside of the instructions cajole fu +13831|740|O|234924.78|1996-04-17|1-URGENT|Clerk#000000204|0|efully unusual theodolites s +13856|1156|O|154144.16|1997-11-28|4-NOT SPECIFIED|Clerk#000000601|0| special theodolites cajole fluffi +13857|275|O|9265.55|1995-08-15|1-URGENT|Clerk#000000012|0|uses boost furiously even +13858|1105|F|44168.23|1994-07-13|2-HIGH|Clerk#000000003|0| fluffily even, regular accounts. furiously permanent dependencies are. slyl +13859|221|O|228467.72|1997-01-09|4-NOT SPECIFIED|Clerk#000000630|0|; enticingly ironic deposits detect along the blithely bold +13860|454|F|61875.64|1994-09-25|3-MEDIUM|Clerk#000000878|0|ccounts nod carefully. express requests whithout the slyly regular in +13861|1249|F|223838.87|1993-08-12|2-HIGH|Clerk#000000153|0|ng requests. quickly ironic packages around th +13862|1240|O|233858.28|1997-09-03|3-MEDIUM|Clerk#000000838|0|odolites integrate carefully unusual requests. sly ideas are +13863|1399|F|132450.97|1992-05-31|2-HIGH|Clerk#000000471|0|y special deposits boost ca +13888|733|F|6632.13|1993-05-04|3-MEDIUM|Clerk#000000635|0|ly regular pinto beans boost about the sheav +13889|848|O|73735.52|1995-09-05|3-MEDIUM|Clerk#000000379|0|ng the silent foxes. even, quiet patterns about th +13890|34|O|50473.48|1996-05-25|5-LOW|Clerk#000000263|0|eposits along the fluffily final accounts wake final, pending foxe +13891|508|O|62430.54|1996-07-05|4-NOT SPECIFIED|Clerk#000000147|0|es are slyly. special packages use slyly against the theodolites. pa +13892|1013|F|216407.28|1992-04-28|2-HIGH|Clerk#000000365|0|ithely ironic packages sleep after the ruthless instructions. quickly dogged t +13893|289|O|132790.59|1998-04-12|2-HIGH|Clerk#000000931|0| blithely regular, unusual dep +13894|1246|F|125452.99|1992-04-11|3-MEDIUM|Clerk#000000524|0|y pending hockey players cajole fluffily special sentiments. closely ironic +13895|671|F|225938.31|1993-11-21|2-HIGH|Clerk#000000381|0|across the fluffily even accounts. carefully silent ideas wake. blithe +13920|37|F|155193.67|1994-10-10|1-URGENT|Clerk#000000060|0| unusual deposits sleep blithely +13921|49|O|152288.97|1997-08-19|4-NOT SPECIFIED|Clerk#000000358|0|elets doubt against the slyly final +13922|241|O|252983.77|1995-08-03|2-HIGH|Clerk#000000301|0|requests use ironic de +13923|1000|F|155909.13|1992-07-09|2-HIGH|Clerk#000000189|0|s. regular packages +13924|328|F|3658.90|1994-12-20|2-HIGH|Clerk#000000251|0|haggle quickly ironic platelets. even tithes wake blit +13925|73|O|162158.06|1997-01-06|1-URGENT|Clerk#000000303|0|uriously ironic accounts around the never regular packages +13926|49|O|52124.55|1997-07-13|4-NOT SPECIFIED|Clerk#000000881|0|ages haggle furiously bold, final accounts. special foxes +13927|562|F|121815.82|1994-08-27|5-LOW|Clerk#000000534|0|lar, silent packages wake quickly +13952|571|O|115051.12|1997-04-25|4-NOT SPECIFIED|Clerk#000000896|0|ly ironic pinto beans. furiously even accounts haggle carefully accordi +13953|388|O|233895.85|1995-06-01|1-URGENT|Clerk#000000337|0|riously deposits. blithely +13954|775|O|132924.82|1996-05-02|5-LOW|Clerk#000000809|0|t furiously above the final requ +13955|1409|O|161957.19|1998-05-12|2-HIGH|Clerk#000000359|0|ar foxes. packages nag blithely fina +13956|716|P|107050.72|1995-03-13|1-URGENT|Clerk#000000062|0|e final deposits are according to the regula +13957|475|O|176779.20|1995-07-22|4-NOT SPECIFIED|Clerk#000000019|0|mpress carefully slyly even requests. blithely pending t +13958|616|F|52000.53|1993-01-24|5-LOW|Clerk#000000863|0|ly. carefully special accounts among the slyly express requests sleep afte +13959|451|F|99030.36|1994-04-05|3-MEDIUM|Clerk#000000952|0|efully bold requests above the busy, express deposits use express p +13984|401|F|197913.83|1992-09-25|5-LOW|Clerk#000000750|0|final, special foxes. carefully express theodolites boost ne +13985|397|O|174830.89|1998-06-14|2-HIGH|Clerk#000000876|0|old accounts wake instructions. furiously ironic requests use quickly. quickl +13986|1333|O|103675.53|1995-10-12|2-HIGH|Clerk#000000793|0|riously final foxes. fur +13987|643|O|64387.39|1998-04-14|4-NOT SPECIFIED|Clerk#000000268|0|es. furiously even +13988|53|F|114321.03|1992-08-02|4-NOT SPECIFIED|Clerk#000000556|0|le daring packages. final, final escapades cajole expre +13989|1480|O|189523.80|1997-07-06|5-LOW|Clerk#000000996|0|ate about the bold, express packages. closely brave accou +13990|751|O|143454.90|1998-02-07|1-URGENT|Clerk#000000683|0| slyly according to the furiously spe +13991|1204|F|261061.37|1992-03-07|2-HIGH|Clerk#000000245|0|nic, special accounts. quickly pending accounts wake +14016|1145|F|201366.56|1992-07-12|5-LOW|Clerk#000000150|0|ymptotes: packages around the +14017|1033|F|142714.54|1994-03-08|2-HIGH|Clerk#000000238|0|unusual deposits sleep furiously +14018|367|F|101182.03|1993-06-07|2-HIGH|Clerk#000000376|0|uctions. pending instructions cajole about th +14019|184|O|216427.67|1997-09-08|1-URGENT|Clerk#000000961|0|tect fluffily final pac +14020|841|O|75424.30|1998-01-29|2-HIGH|Clerk#000000275|0|aggle quickly along the blithely bold ins +14021|62|P|206447.05|1995-03-08|2-HIGH|Clerk#000000467|0|sly. carefully regular +14022|685|F|71271.43|1995-02-14|2-HIGH|Clerk#000000732|0|es. quickly express deposits nag across the iron +14023|787|F|127450.06|1993-02-21|4-NOT SPECIFIED|Clerk#000000349|0|ironic, regular dugouts +14048|1016|F|221205.20|1993-05-18|4-NOT SPECIFIED|Clerk#000000548|0|s. blithely even asy +14049|952|O|70228.24|1996-01-29|5-LOW|Clerk#000000189|0|yly express epitaphs are slyly express depo +14050|88|O|161689.12|1997-08-22|5-LOW|Clerk#000000283|0|en courts. carefully express packages +14051|599|F|22238.93|1993-09-17|4-NOT SPECIFIED|Clerk#000000098|0|ss blithely among the closely r +14052|1190|F|23078.95|1995-02-07|4-NOT SPECIFIED|Clerk#000000647|0|mong the regular foxes boost blithely special pinto beans. furious +14053|1453|F|25549.20|1993-02-09|2-HIGH|Clerk#000000597|0| carefully ironic courts sleep quickly pending, pending packag +14054|517|O|285667.97|1996-01-11|4-NOT SPECIFIED|Clerk#000000890|0|unusual waters above the dependencies cajole r +14055|904|F|90239.70|1994-09-02|2-HIGH|Clerk#000000825|0|ounts. carefully final somas unwind fluffily. +14080|791|O|62517.87|1998-05-29|4-NOT SPECIFIED|Clerk#000000106|0|nic packages use final, bold +14081|895|F|114279.17|1993-10-07|2-HIGH|Clerk#000000857|0|uests. fluffily final packages wake slow, ironic dep +14082|875|O|48224.95|1998-05-08|4-NOT SPECIFIED|Clerk#000000700|0|bove the sometimes even deposits. ruthlessly unusual deposit +14083|464|F|11732.48|1994-08-16|4-NOT SPECIFIED|Clerk#000000420|0| quickly ruthless a +14084|647|O|303760.75|1995-08-03|4-NOT SPECIFIED|Clerk#000000160|0|luffily above the final packages. requests +14085|895|F|136353.74|1994-02-05|2-HIGH|Clerk#000000503|0|eas boost carefully evenly pending requests-- furiously thin accounts +14086|346|F|54201.92|1993-10-21|5-LOW|Clerk#000000289|0|ial deposits sleep. express requests nag carefull +14087|275|O|208589.10|1997-02-12|5-LOW|Clerk#000000927|0|dependencies. quickly ironic frets above the fluffily ironic accounts use +14112|112|F|20742.84|1994-07-25|5-LOW|Clerk#000000463|0|ickly dogged accounts breach doggedly +14113|835|O|27091.83|1995-08-05|2-HIGH|Clerk#000000885|0|; carefully pending accounts use among the pending packag +14114|895|F|171306.58|1994-04-07|1-URGENT|Clerk#000000397|0|beans play regular, ironic deposits. instructio +14115|46|F|68488.60|1994-08-15|4-NOT SPECIFIED|Clerk#000000493|0|ckages sleep across the regular, silent pinto beans. bold, un +14116|1291|O|192210.86|1995-10-10|2-HIGH|Clerk#000000065|0|. carefully bold ideas sleep. carefully bold idea +14117|1297|F|281939.12|1993-08-26|4-NOT SPECIFIED|Clerk#000000480|0|uickly ironic ideas boost among the furiously pending deposits. +14118|385|F|41143.91|1993-05-23|4-NOT SPECIFIED|Clerk#000000730|0| toward the express, unusual instructions sleep accordin +14119|482|F|203405.63|1993-06-01|5-LOW|Clerk#000000989|0|osits. furiously pending accounts across the slyly +14144|301|O|308016.67|1997-04-26|1-URGENT|Clerk#000000089|0|nusual instructions sleep. blithely silent requests thr +14145|7|O|270751.41|1997-04-17|1-URGENT|Clerk#000000920|0|x carefully ideas. evenly silent +14146|592|O|108225.88|1996-01-03|3-MEDIUM|Clerk#000000968|0|xpress accounts. even packages about the pen +14147|728|F|262030.95|1993-03-08|4-NOT SPECIFIED|Clerk#000000152|0|, special epitaphs haggle a +14148|965|O|130798.36|1998-04-30|3-MEDIUM|Clerk#000000188|0|ag carefully special foxes. carefully unus +14149|73|O|157174.97|1998-01-28|1-URGENT|Clerk#000000303|0|ests. ironic, special pinto beans try to print slyly along the pending +14150|89|F|196189.74|1994-02-09|2-HIGH|Clerk#000000695|0|y ironic accounts haggle across the furi +14151|1418|O|286984.16|1997-06-06|4-NOT SPECIFIED|Clerk#000000278|0|special accounts. blithely express deposits cajole slyly slyly ex +14176|991|F|141050.11|1994-03-13|5-LOW|Clerk#000000407|0|eodolites. slyly final platelets ca +14177|565|F|112612.65|1992-04-03|5-LOW|Clerk#000000442|0|nooze carefully slyly final packages. platelets about the q +14178|391|F|11236.45|1995-01-01|4-NOT SPECIFIED|Clerk#000000246|0| quick accounts nag carefully. regular accounts could +14179|458|O|384265.43|1997-09-07|1-URGENT|Clerk#000000053|0|about the bold, final pinto bean +14180|292|O|187330.32|1997-05-25|3-MEDIUM|Clerk#000000478|0|out the carefully regular accoun +14181|94|O|226844.98|1998-02-13|3-MEDIUM|Clerk#000000106|0|efully even depende +14182|934|F|68283.44|1994-06-23|5-LOW|Clerk#000000791|0|arefully. sentiments integrate +14183|875|O|85725.94|1997-03-17|5-LOW|Clerk#000000052|0| final requests detect slyly at the +14208|385|O|121214.10|1995-05-01|4-NOT SPECIFIED|Clerk#000000758|0|sly slyly silent requests. carefully special accounts sleep +14209|1025|O|137491.26|1996-11-04|2-HIGH|Clerk#000000211|0|leep slyly against the carefully bold dolphins. +14210|25|F|23549.76|1992-06-27|4-NOT SPECIFIED|Clerk#000000356|0|atelets nag carefully final foxes. ironic, silent +14211|1202|F|189400.90|1994-02-13|4-NOT SPECIFIED|Clerk#000000937|0|the blithely bold deposits are according to the accounts. f +14212|806|F|196439.01|1992-02-17|1-URGENT|Clerk#000000384|0| packages affix special deposits? carefully special pinto bean +14213|478|F|50949.10|1993-12-28|1-URGENT|Clerk#000000959|0|, careful platelets abo +14214|79|O|128802.82|1997-08-15|1-URGENT|Clerk#000000891|0|thely unusual pinto beans against the blithely special warhorses hagg +14215|1408|F|50568.60|1992-07-14|3-MEDIUM|Clerk#000000823|0|ounts haggle furiously. special gifts am +14240|689|F|210064.90|1992-02-18|2-HIGH|Clerk#000000728|0|sly. express, unusual asymptotes across the never fin +14241|928|F|153112.39|1992-06-15|1-URGENT|Clerk#000000866|0|c packages. instructions a +14242|913|P|115246.93|1995-05-09|2-HIGH|Clerk#000000927|0|d have to haggle according +14243|1073|O|63765.25|1997-02-15|3-MEDIUM|Clerk#000000943|0|sly ironic foxes nag carefully along t +14244|205|O|53072.12|1998-03-05|5-LOW|Clerk#000000139|0|press excuses doubt permanently. +14245|1309|F|73717.72|1993-02-12|1-URGENT|Clerk#000000975|0|furiously final foxes boost silent, final requests. slyly unusual deposi +14246|289|O|133280.40|1997-10-10|4-NOT SPECIFIED|Clerk#000000806|0| bold pinto beans. regular accounts +14247|671|O|219431.33|1995-08-17|1-URGENT|Clerk#000000531|0|ests haggle furiously about the pa +14272|1348|F|97840.61|1992-02-13|3-MEDIUM|Clerk#000000075|0|ses. blithely final deposits are. stealthy accounts engage. slyly +14273|1033|O|90555.37|1996-03-13|5-LOW|Clerk#000000938|0| special foxes lose quickly; fina +14274|565|F|244782.98|1994-01-07|4-NOT SPECIFIED|Clerk#000000564|0|nt requests are furiously furiously daring accounts. even +14275|1412|F|168905.36|1993-06-14|5-LOW|Clerk#000000789|0|furiously. slyly pending packages sublate furious +14276|499|F|241009.94|1994-06-19|3-MEDIUM|Clerk#000000149|0|ly bold requests haggle slyly according to the closely +14277|946|O|116805.58|1998-02-14|4-NOT SPECIFIED|Clerk#000000951|0|eep. thin theodolites are bl +14278|559|O|266421.62|1998-06-03|2-HIGH|Clerk#000000768|0|jole slyly ironic theodolites. carefully even deposi +14279|1117|O|157844.27|1998-02-09|2-HIGH|Clerk#000000441|0| after the furiously unusual realms. +14304|788|O|215723.64|1997-11-13|3-MEDIUM|Clerk#000000488|0|egular requests affix. even requ +14305|1427|O|80794.79|1996-07-23|1-URGENT|Clerk#000000396|0|mas cajole above the +14306|587|F|27239.18|1993-10-30|4-NOT SPECIFIED|Clerk#000000981|0|furiously regular e +14307|484|O|178901.14|1997-06-24|1-URGENT|Clerk#000000255|0| deposits wake. regular, special excuses us +14308|5|O|132817.36|1997-08-11|3-MEDIUM|Clerk#000000354|0|iously. packages wake according to the furio +14309|1382|F|103342.31|1994-01-31|1-URGENT|Clerk#000000753|0|s haggle furiously against the carefully final asymptotes. blith +14310|1393|O|59609.50|1997-09-13|5-LOW|Clerk#000000627|0|p furiously evenly final requests. even, ironic excuses are +14311|1412|F|46918.86|1994-08-02|1-URGENT|Clerk#000000916|0|nic pinto beans along the enticingly final reque +14336|760|F|172716.15|1994-11-19|2-HIGH|Clerk#000000699|0|eodolites cajole carefully. quickly ironic foxes about the fluffily ironic +14337|299|O|280177.62|1997-10-09|4-NOT SPECIFIED|Clerk#000000949|0| special ideas into the silently quick dep +14338|752|F|97316.04|1993-02-01|5-LOW|Clerk#000000658|0|l accounts. quickly special packages h +14339|1199|O|209018.11|1997-07-23|4-NOT SPECIFIED|Clerk#000000303|0|ar theodolites after the express, final pinto beans engage car +14340|391|O|222337.16|1995-10-13|5-LOW|Clerk#000000386|0|theodolites. furiously ironic pinto beans are busily +14341|667|F|197341.53|1993-09-03|4-NOT SPECIFIED|Clerk#000000669|0|lphins cajole furiously after the c +14342|160|F|137933.49|1994-04-28|5-LOW|Clerk#000000040|0| haggle quickly. bold excuses against the regular re +14343|1408|O|58414.89|1996-02-25|3-MEDIUM|Clerk#000000792|0| unusual deposits wake slyly even, even packages. slyly final depe +14368|676|O|121598.53|1995-09-11|2-HIGH|Clerk#000000228|0|ly express requests affix furiously. ironically final asymptotes according +14369|1357|O|272333.98|1996-11-26|1-URGENT|Clerk#000000063|0|sublate quickly furiously bold asymptot +14370|958|O|163080.52|1997-05-03|2-HIGH|Clerk#000000475|0|ly regular accounts. fluffil +14371|1192|F|116441.72|1993-06-23|2-HIGH|Clerk#000000831|0|. carefully express packages at th +14372|523|F|166914.23|1992-10-24|1-URGENT|Clerk#000000449|0|y. ironic deposits sleep? finally special pinto bean +14373|511|F|53131.83|1993-09-18|3-MEDIUM|Clerk#000000099|0|nto beans. fluffy requests affix bravely fluffily iron +14374|1180|O|121655.04|1995-05-17|1-URGENT|Clerk#000000237|0|ross the blithely final deposits. asymptotes are. slyl +14375|733|F|140929.00|1993-02-01|3-MEDIUM|Clerk#000000046|0|ans sleep. blithely regular foxes cajole before the ironic packa +14400|632|F|262307.57|1994-02-05|3-MEDIUM|Clerk#000000479|0|uests. furiously unusual platelets hinder final packages. bold +14401|1489|O|156911.31|1995-08-05|4-NOT SPECIFIED|Clerk#000000059|0|ly carefully even instructions. epitaphs solve instructions! bli +14402|838|F|109228.63|1993-10-15|3-MEDIUM|Clerk#000000672|0|azzle slyly. carefully regular instructions affix carefully deposits. careful +14403|241|O|120881.79|1998-03-02|4-NOT SPECIFIED|Clerk#000000202|0|hely packages. blithely pending dependencies wake furiously +14404|7|O|354885.81|1996-11-03|5-LOW|Clerk#000000657|0| the furiously unus +14405|269|O|94417.57|1996-04-24|5-LOW|Clerk#000000460|0| beans until the final, regular theodolites +14406|409|F|194997.99|1993-03-09|3-MEDIUM|Clerk#000000623|0|s. excuses boost bl +14407|952|F|21880.64|1993-11-05|2-HIGH|Clerk#000000124|0|cajole ruthless theodolites. carefully ironic req +14432|1226|O|44225.65|1996-11-12|4-NOT SPECIFIED|Clerk#000000784|0|re carefully against the fluffily final theodolites. furiously unusual d +14433|1082|O|203663.86|1996-05-13|2-HIGH|Clerk#000000011|0|es. furiously final deposits wake b +14434|1015|F|171433.55|1995-02-16|4-NOT SPECIFIED|Clerk#000000769|0|he unusual pinto beans. special realms cajole. quietly blith +14435|269|F|190900.78|1992-12-02|4-NOT SPECIFIED|Clerk#000000308|0|quests nag. final platelets haggle among the st +14436|658|F|231251.51|1994-03-13|5-LOW|Clerk#000000906|0|regular requests run furiously. unusual, +14437|721|F|285484.64|1994-05-15|1-URGENT|Clerk#000000348|0|refully even excuses alongside of the packages are busily final +14438|1117|O|107298.91|1995-08-23|3-MEDIUM|Clerk#000000059|0| the silent ideas wake after the express requests. unusual, final inst +14439|523|F|4033.74|1992-08-31|2-HIGH|Clerk#000000944|0|riously even courts. ev +14464|1429|O|43902.48|1998-01-23|5-LOW|Clerk#000000197|0| blithely. special deposits +14465|617|F|108913.02|1994-06-12|2-HIGH|Clerk#000000816|0|ndencies nag against the furiously special pin +14466|353|O|19731.95|1996-05-22|3-MEDIUM|Clerk#000000795|0|lithely after the slyly special deposits-- quickly regular gifts acros +14467|1126|O|160773.46|1996-05-31|4-NOT SPECIFIED|Clerk#000000927|0|regular, brave foxes +14468|716|O|60718.43|1998-07-13|3-MEDIUM|Clerk#000000164|0|g pinto beans after the special accounts sleep carefully after the regula +14469|1076|O|82731.79|1997-02-01|2-HIGH|Clerk#000000837|0|ep regular, final accounts? fluffily pending the +14470|949|F|140145.86|1995-01-25|3-MEDIUM|Clerk#000000018|0| asymptotes cajole carefully final a +14471|94|P|324194.82|1995-05-27|4-NOT SPECIFIED|Clerk#000001000|0|l pinto beans ought to nag carefully carefully ironic foxes. +14496|1153|O|206156.59|1996-04-11|3-MEDIUM|Clerk#000000350|0|g theodolites eat c +14497|1492|F|130424.80|1992-05-21|3-MEDIUM|Clerk#000000053|0|symptotes. slyly fluffy excuses ought to wake according to the slyly even de +14498|115|O|172949.99|1996-10-05|3-MEDIUM|Clerk#000000709|0| deposits! quickly pend +14499|361|F|306903.43|1993-11-15|5-LOW|Clerk#000000358|0|packages. carefully final ide +14500|1222|O|100773.58|1995-06-25|4-NOT SPECIFIED|Clerk#000000451|0| slyly regular ideas haggle slyly unusual packages. quickly unusual pinto +14501|607|O|83186.27|1997-08-31|2-HIGH|Clerk#000000826|0|e ideas. ironic deposits sleep according to the blithely ironi +14502|799|O|87836.22|1996-07-21|2-HIGH|Clerk#000000875|0| furiously ironic deposits cajole around the carefully silent accounts. expre +14503|671|F|198098.70|1995-02-06|4-NOT SPECIFIED|Clerk#000000519|0|ely regular depths haggle carefull +14528|334|F|155412.29|1994-06-16|1-URGENT|Clerk#000000568|0|gle instead of the carefully pending pinto beans. express, ex +14529|1372|F|193341.12|1993-09-21|5-LOW|Clerk#000000521|0|arefully unusual packages haggle carefully slyly final pinto beans. exp +14530|133|F|240313.77|1994-04-07|2-HIGH|Clerk#000000444|0|eodolites may wake final requests. furious +14531|1331|O|222583.58|1997-06-11|2-HIGH|Clerk#000000003|0|across the blithely even instructions. carefull +14532|1252|O|15069.98|1996-04-17|5-LOW|Clerk#000000906|0|ep furiously according to the quickly final deposits. reg +14533|43|O|161212.58|1996-05-06|4-NOT SPECIFIED|Clerk#000000394|0|ans alongside of the carefully ironic re +14534|1414|F|248752.30|1993-07-19|3-MEDIUM|Clerk#000000324|0|furiously. silent foxes boost finally. dependencies among the furiously fi +14535|1306|F|95671.80|1993-10-02|4-NOT SPECIFIED|Clerk#000000983|0|thely unusual accounts are fluffi +14560|1258|O|33048.76|1997-12-15|3-MEDIUM|Clerk#000000587|0|ckages grow furiously-- carefully final foxes according +14561|697|O|274551.87|1998-06-29|3-MEDIUM|Clerk#000000840|0|onic accounts. even, express excuses cajole carefully. bl +14562|973|O|150256.16|1996-07-20|5-LOW|Clerk#000000189|0|ve the blithely even dependencies-- quickly busy realms wake quickly. permane +14563|568|O|236613.87|1995-12-03|1-URGENT|Clerk#000000904|0|quests. quickly even theodolites nag blit +14564|520|F|1358.25|1993-05-22|4-NOT SPECIFIED|Clerk#000000799|0|carefully even deposits. furiously express acco +14565|1301|O|50022.91|1997-11-23|1-URGENT|Clerk#000000409|0| special foxes. blithely ironic ideas sleep carefully quietly final instruct +14566|1480|O|221337.42|1996-10-25|3-MEDIUM|Clerk#000000118|0|ns? slyly regular theodolites haggle quickly. fluffily bol +14567|1060|O|176372.95|1996-10-18|1-URGENT|Clerk#000000527|0|efully blithe excuses. slyly regular ideas promise. escapad +14592|926|O|93588.02|1995-07-06|3-MEDIUM|Clerk#000000402|0|ts affix alongside of the blithely ironic pinto beans. +14593|184|O|61820.82|1998-01-23|1-URGENT|Clerk#000000880|0| dependencies. slyly +14594|143|F|16529.84|1993-09-07|3-MEDIUM|Clerk#000000022|0| across the carefull +14595|202|O|32654.01|1997-12-03|3-MEDIUM|Clerk#000000854|0|kages. asymptotes dazzle. final, bold pinto be +14596|1198|F|167802.21|1994-01-11|1-URGENT|Clerk#000000754|0| even accounts above the furiously brave dep +14597|1192|F|293673.06|1993-08-31|1-URGENT|Clerk#000000768|0|haggle ironic, quick accounts. quickly special foxes nag slyly above the furi +14598|898|O|171449.52|1998-02-10|4-NOT SPECIFIED|Clerk#000000229|0|slyly even deposits are carefully. final, pe +14599|814|F|13810.80|1992-05-09|2-HIGH|Clerk#000000704|0|ke final theodolites +14624|1177|O|210247.47|1998-04-17|4-NOT SPECIFIED|Clerk#000000014|0|heodolites. quickly regular theodolites haggle ag +14625|1075|F|2059.98|1992-02-12|1-URGENT|Clerk#000000491|0|instructions play blithely? silent excuses snooze quick +14626|1453|O|118335.57|1997-08-12|3-MEDIUM|Clerk#000000450|0|egular platelets are. even requ +14627|679|F|212366.75|1994-02-05|3-MEDIUM|Clerk#000000520|0|quickly according to the b +14628|668|F|75317.77|1993-06-07|3-MEDIUM|Clerk#000000076|0|accounts hang furiously. furiously regular theodolites +14629|1469|F|78503.51|1993-01-08|2-HIGH|Clerk#000000344|0|uests sleep quickly. furiously ironic accounts against the quickly ironic id +14630|277|F|189160.54|1992-10-17|5-LOW|Clerk#000000575|0| theodolites. carefully +14631|1291|O|34502.66|1997-04-14|2-HIGH|Clerk#000000022|0|ly above the pendin +14656|1|O|28599.83|1997-11-18|2-HIGH|Clerk#000000270|0|uests. blithely even platelet +14657|370|F|116160.53|1994-02-28|1-URGENT|Clerk#000000756|0|ly across the ironic, ironic instructions. bold ideas +14658|1381|F|48274.02|1994-04-07|1-URGENT|Clerk#000000175|0|kly regular requests? regular theod +14659|25|O|145504.68|1998-02-10|3-MEDIUM|Clerk#000000260|0|l, ironic attainment +14660|899|O|139267.14|1997-05-24|4-NOT SPECIFIED|Clerk#000000605|0|c pinto beans. fluff +14661|1468|F|38295.53|1993-01-25|4-NOT SPECIFIED|Clerk#000000429|0| believe. silent packages haggle express instructio +14662|1330|O|200128.12|1995-11-17|2-HIGH|Clerk#000000988|0|efully pending accounts about the bold +14663|592|F|42406.05|1992-11-17|1-URGENT|Clerk#000000596|0|ietly above the packages. regular frets haggle slyly blithely regular pinto b +14688|427|O|127535.78|1997-02-18|5-LOW|Clerk#000000822|0|unusual, bold deposits. furiously bold ideas cajole fluffily ironic theodo +14689|226|O|68912.05|1998-07-31|2-HIGH|Clerk#000000100|0|quickly regular realms are along the carefully spe +14690|935|O|41205.72|1997-05-24|1-URGENT|Clerk#000000342|0|ic packages affix sly +14691|1381|O|81185.28|1998-04-11|5-LOW|Clerk#000000211|0|ffily even instructions use blithely. careful +14692|478|O|53591.54|1996-02-27|5-LOW|Clerk#000000309|0|xpress deposits wake slyly after the deposits. slyly re +14693|67|F|246072.95|1995-01-10|1-URGENT|Clerk#000000039|0|to beans. Tiresias above the special, bold packages sleep +14694|379|O|318967.92|1998-07-28|1-URGENT|Clerk#000000742|0|nic pinto beans sleep blithely pending, unusual somas. blithely ironic id +14695|1406|F|205288.40|1992-09-06|2-HIGH|Clerk#000000475|0|. ideas boost carefully around the even, final instruc +14720|401|F|171435.70|1993-09-05|3-MEDIUM|Clerk#000000354|0|ongside of the quickly final excuses sleep quickly dolphins. dinos +14721|1087|O|166081.83|1997-05-05|4-NOT SPECIFIED|Clerk#000000701|0|instructions haggle slyly. +14722|742|O|264702.15|1997-05-28|5-LOW|Clerk#000000048|0|blithely bold requests ar +14723|1282|O|40317.37|1997-01-04|5-LOW|Clerk#000000822|0|ic deposits affix carefully above th +14724|1396|O|41941.26|1995-11-18|1-URGENT|Clerk#000000886|0|bold dependencies about the busy instructions haggle regular ins +14725|569|O|261801.45|1995-06-17|2-HIGH|Clerk#000000177|0|ng asymptotes. final, ironic accounts cajole after +14726|1279|F|93802.35|1992-01-09|5-LOW|Clerk#000000590|0| foxes. deposits cajole blithely even grouches. b +14727|316|F|102382.66|1992-07-20|3-MEDIUM|Clerk#000000383|0|structions. daringly even packages wake slyly final requests. c +14752|1051|F|31543.83|1994-01-30|5-LOW|Clerk#000000802|0|. carefully regular pinto beans grow idly abou +14753|1118|O|45387.36|1997-01-05|1-URGENT|Clerk#000000855|0|n deposits across the +14754|86|O|112289.25|1996-06-23|3-MEDIUM|Clerk#000000283|0|ns. quickly ironic packages sleep furiously fluffily unusual excuses. de +14755|592|F|358175.60|1993-01-06|2-HIGH|Clerk#000000867|0|egular requests sleep careful packages. quickly r +14756|328|F|132718.02|1994-09-01|5-LOW|Clerk#000000491|0|olites. ironic, final instructions pro +14757|1420|O|55954.21|1997-12-24|4-NOT SPECIFIED|Clerk#000000011|0|ggle furiously. carefully special packages are c +14758|1225|F|37812.49|1993-10-27|2-HIGH|Clerk#000000687|0|ages nag about the furio +14759|70|O|40915.46|1997-01-05|3-MEDIUM|Clerk#000000034|0|he dolphins. ruthlessly regular packages play carefully. f +14784|1036|F|188067.67|1992-03-15|3-MEDIUM|Clerk#000000479|0|lyly final theodoli +14785|1249|F|107683.78|1994-10-10|2-HIGH|Clerk#000000446|0| slyly about the quickly sp +14786|1255|O|34058.87|1997-04-08|2-HIGH|Clerk#000000656|0|e carefully special deposits can nag blithely express, express accounts +14787|578|O|135287.72|1998-07-19|5-LOW|Clerk#000000522|0|deas against the blithely r +14788|1192|O|51229.59|1997-10-23|1-URGENT|Clerk#000000647|0|e the slyly pending deposits. c +14789|451|F|214256.97|1993-11-30|4-NOT SPECIFIED|Clerk#000000616|0|st furiously about the ca +14790|613|O|270163.54|1996-08-21|2-HIGH|Clerk#000000347|0|p. regular deposits wake. final n +14791|289|F|86492.66|1993-02-15|3-MEDIUM|Clerk#000000770|0|ideas wake blithely regularly regular requests. s +14816|508|F|89977.38|1993-07-15|4-NOT SPECIFIED|Clerk#000000721|0| requests. slyly even requests haggle? unusual, regula +14817|235|F|138541.57|1992-07-28|3-MEDIUM|Clerk#000000963|0|arefully unusual dolphins. furiously final accounts above the slyly +14818|643|O|182026.46|1996-11-18|4-NOT SPECIFIED|Clerk#000000588|0|totes. bold, final requests are according to the deposits. quickly regular +14819|473|F|141776.24|1993-01-26|4-NOT SPECIFIED|Clerk#000000641|0| permanent deposits. blithely final warthogs x-ray blithely slyly ir +14820|1135|F|160021.51|1992-01-10|2-HIGH|Clerk#000000090|0|posits. regular pinto beans detect carefully at the final pinto beans. unu +14821|1435|O|322002.95|1998-06-12|2-HIGH|Clerk#000000630|0|n packages are furiously ironic ideas. d +14822|473|O|182443.15|1996-03-26|2-HIGH|Clerk#000000675|0|es. even, special request +14823|832|F|190065.85|1994-02-13|5-LOW|Clerk#000000844|0| slyly final accounts: packages integrate quickly along the packages +14848|256|O|115009.62|1996-10-17|5-LOW|Clerk#000000567|0|warthogs use furiously across the +14849|739|O|82597.02|1997-02-07|3-MEDIUM|Clerk#000000123|0| cajole fluffily against the final, reg +14850|1348|O|227401.85|1997-12-04|1-URGENT|Clerk#000000960|0| quickly regular braids. ironic, regular accounts are carefully +14851|175|F|229811.50|1992-05-12|4-NOT SPECIFIED|Clerk#000000075|0|. blithely regular requests wake blithely after the furiously final accou +14852|1060|O|34634.76|1995-12-25|3-MEDIUM|Clerk#000000907|0|ages haggle accounts. careful, ironic excuses sleep quickly dogged asymptotes +14853|458|O|152920.35|1996-09-10|5-LOW|Clerk#000000036|0|ding instructions about the quickly pending requests sleep quickly iro +14854|472|F|75626.15|1993-04-29|5-LOW|Clerk#000000872|0|ronic pinto beans? even deposits nag c +14855|836|F|141609.96|1993-05-01|4-NOT SPECIFIED|Clerk#000000655|0|nent accounts sleep dependencies. furiously regular ideas ca +14880|1210|O|209395.33|1997-11-23|4-NOT SPECIFIED|Clerk#000000545|0|equests above the foxes wake blithely about the packages: ironic ex +14881|23|O|126051.68|1996-10-20|2-HIGH|Clerk#000000826|0|ades past the fluffily ironic foxes m +14882|833|O|89650.26|1997-02-13|1-URGENT|Clerk#000000353|0|y against the slyly ironic accounts. blithely silent acc +14883|865|P|148947.38|1995-05-07|5-LOW|Clerk#000000543|0|detect blithely: carefully regular asymptotes caj +14884|1450|O|278225.35|1995-09-28|2-HIGH|Clerk#000000481|0| carefully ironic multipliers. furiously final deposits +14885|19|O|261263.74|1997-09-21|5-LOW|Clerk#000000462|0|p slyly regular excu +14886|337|F|84441.18|1994-06-23|3-MEDIUM|Clerk#000000757|0|slyly above the deposi +14887|245|O|124720.14|1996-03-25|2-HIGH|Clerk#000000176|0|he pinto beans boost slyly regular deposits. fi +14912|752|F|28125.10|1993-11-07|1-URGENT|Clerk#000000924|0| ideas cajole slyly around the ironic, bold asymptotes. +14913|1411|F|178192.17|1994-02-15|2-HIGH|Clerk#000000823|0|gainst the carefully final orbits hang furiously above t +14914|1199|O|191598.59|1998-02-08|1-URGENT|Clerk#000000536|0|e carefully carefully ironic requests: never final packag +14915|811|O|59911.87|1996-09-10|4-NOT SPECIFIED|Clerk#000000708|0| accounts are above the enticingly express pin +14916|380|F|72290.87|1994-02-28|5-LOW|Clerk#000000656|0|al requests solve slyly above the never express requests. furious +14917|1148|O|280961.18|1998-01-13|1-URGENT|Clerk#000000974|0|as would use fluffily after the +14918|884|O|68255.07|1997-06-01|5-LOW|Clerk#000000674|0|ets. bold, pending deposits sleep. foxes wake +14919|838|O|36633.03|1996-09-10|2-HIGH|Clerk#000000455|0|as. carefully final ideas cajole finally blithely express foxes. slow +14944|535|O|119586.69|1997-10-14|2-HIGH|Clerk#000000962|0|lly. even instructions against +14945|68|O|210519.05|1996-03-30|1-URGENT|Clerk#000000467|0|nts? fluffily bold grouches after +14946|580|O|100402.47|1996-11-12|1-URGENT|Clerk#000000116|0|ffily bold dependencies wake. furiously regular instructions aro diff --git a/src/test/regress/data/part.data b/src/test/regress/data/part.data new file mode 100644 index 000000000..46e0ee167 --- /dev/null +++ b/src/test/regress/data/part.data @@ -0,0 +1,1000 @@ +1|goldenrod lavender spring chocolate lace|Manufacturer#1|Brand#13|PROMO BURNISHED COPPER|7|JUMBO PKG|901.00|ly. slyly ironi +2|blush thistle blue yellow saddle|Manufacturer#1|Brand#13|LARGE BRUSHED BRASS|1|LG CASE|902.00|lar accounts amo +3|spring green yellow purple cornsilk|Manufacturer#4|Brand#42|STANDARD POLISHED BRASS|21|WRAP CASE|903.00|egular deposits hag +4|cornflower chocolate smoke green pink|Manufacturer#3|Brand#34|SMALL PLATED BRASS|14|MED DRUM|904.00|p furiously r +5|forest brown coral puff cream|Manufacturer#3|Brand#32|STANDARD POLISHED TIN|15|SM PKG|905.00| wake carefully +6|bisque cornflower lawn forest magenta|Manufacturer#2|Brand#24|PROMO PLATED STEEL|4|MED BAG|906.00|sual a +7|moccasin green thistle khaki floral|Manufacturer#1|Brand#11|SMALL PLATED COPPER|45|SM BAG|907.00|lyly. ex +8|misty lace thistle snow royal|Manufacturer#4|Brand#44|PROMO BURNISHED TIN|41|LG DRUM|908.00|eposi +9|thistle dim navajo dark gainsboro|Manufacturer#4|Brand#43|SMALL BURNISHED STEEL|12|WRAP CASE|909.00|ironic foxe +10|linen pink saddle puff powder|Manufacturer#5|Brand#54|LARGE BURNISHED STEEL|44|LG CAN|910.01|ithely final deposit +11|spring maroon seashell almond orchid|Manufacturer#2|Brand#25|STANDARD BURNISHED NICKEL|43|WRAP BOX|911.01|ng gr +12|cornflower wheat orange maroon ghost|Manufacturer#3|Brand#33|MEDIUM ANODIZED STEEL|25|JUMBO CASE|912.01| quickly +13|ghost olive orange rosy thistle|Manufacturer#5|Brand#55|MEDIUM BURNISHED NICKEL|1|JUMBO PACK|913.01|osits. +14|khaki seashell rose cornsilk navajo|Manufacturer#1|Brand#13|SMALL POLISHED STEEL|28|JUMBO BOX|914.01|kages c +15|blanched honeydew sky turquoise medium|Manufacturer#1|Brand#15|LARGE ANODIZED BRASS|45|LG CASE|915.01|usual ac +16|deep sky turquoise drab peach|Manufacturer#3|Brand#32|PROMO PLATED TIN|2|MED PACK|916.01|unts a +17|indian navy coral pink deep|Manufacturer#4|Brand#43|ECONOMY BRUSHED STEEL|16|LG BOX|917.01| regular accounts +18|turquoise indian lemon lavender misty|Manufacturer#1|Brand#11|SMALL BURNISHED STEEL|42|JUMBO PACK|918.01|s cajole slyly a +19|chocolate navy tan deep brown|Manufacturer#2|Brand#23|SMALL ANODIZED NICKEL|33|WRAP BOX|919.01| pending acc +20|ivory navy honeydew sandy midnight|Manufacturer#1|Brand#12|LARGE POLISHED NICKEL|48|MED BAG|920.02|are across the asympt +21|lemon floral azure frosted lime|Manufacturer#3|Brand#33|SMALL BURNISHED TIN|31|MED BAG|921.02|ss packages. pendin +22|medium forest blue ghost black|Manufacturer#4|Brand#43|PROMO POLISHED BRASS|19|LG DRUM|922.02| even p +23|coral lavender seashell rosy burlywood|Manufacturer#3|Brand#35|MEDIUM BURNISHED TIN|42|JUMBO JAR|923.02|nic, fina +24|seashell coral metallic midnight floral|Manufacturer#5|Brand#52|MEDIUM PLATED STEEL|20|MED CASE|924.02| final the +25|aquamarine steel firebrick light turquoise|Manufacturer#5|Brand#55|STANDARD BRUSHED COPPER|3|JUMBO BAG|925.02|requests wake +26|beige frosted moccasin chocolate snow|Manufacturer#3|Brand#32|SMALL BRUSHED STEEL|32|SM CASE|926.02| instructions i +27|saddle puff beige linen yellow|Manufacturer#1|Brand#14|LARGE ANODIZED TIN|20|MED PKG|927.02|s wake. ir +28|navajo yellow drab white misty|Manufacturer#4|Brand#44|SMALL PLATED COPPER|19|JUMBO PKG|928.02|x-ray pending, iron +29|lemon sky grey salmon orchid|Manufacturer#3|Brand#33|PROMO PLATED COPPER|7|LG DRUM|929.02| carefully fluffi +30|cream misty steel spring medium|Manufacturer#4|Brand#42|PROMO ANODIZED TIN|17|LG BOX|930.03|carefully bus +31|slate seashell steel medium moccasin|Manufacturer#5|Brand#53|STANDARD BRUSHED TIN|10|LG BAG|931.03|uriously s +32|sandy wheat coral spring burnished|Manufacturer#4|Brand#42|ECONOMY PLATED BRASS|31|LG CASE|932.03|urts. carefully fin +33|spring bisque salmon slate pink|Manufacturer#2|Brand#22|ECONOMY PLATED NICKEL|16|LG PKG|933.03|ly eve +34|khaki steel rose ghost salmon|Manufacturer#1|Brand#13|LARGE BRUSHED STEEL|8|JUMBO BOX|934.03|riously ironic +35|green blush tomato burlywood seashell|Manufacturer#4|Brand#43|MEDIUM ANODIZED BRASS|14|JUMBO PACK|935.03|e carefully furi +36|chiffon tan forest moccasin dark|Manufacturer#2|Brand#25|SMALL BURNISHED COPPER|3|JUMBO CAN|936.03|olites o +37|royal coral orange burnished navajo|Manufacturer#4|Brand#45|LARGE POLISHED TIN|48|JUMBO BOX|937.03|silent +38|seashell papaya white mint brown|Manufacturer#4|Brand#43|ECONOMY ANODIZED BRASS|11|SM JAR|938.03|structions inte +39|rose medium floral salmon powder|Manufacturer#5|Brand#53|SMALL POLISHED TIN|43|JUMBO JAR|939.03|se slowly above the fl +40|lemon midnight metallic sienna steel|Manufacturer#2|Brand#25|ECONOMY BURNISHED COPPER|27|SM CASE|940.04|! blithely specia +41|burlywood goldenrod pink peru sienna|Manufacturer#2|Brand#23|ECONOMY ANODIZED TIN|7|WRAP JAR|941.04|uriously. furiously cl +42|midnight turquoise lawn beige thistle|Manufacturer#5|Brand#52|MEDIUM BURNISHED TIN|45|LG BOX|942.04|the slow +43|medium lace midnight royal chartreuse|Manufacturer#4|Brand#44|PROMO POLISHED STEEL|5|WRAP CASE|943.04|e slyly along the ir +44|saddle cream wheat lemon burnished|Manufacturer#4|Brand#45|MEDIUM PLATED TIN|48|SM PACK|944.04|pinto beans. carefully +45|lawn peru ghost khaki maroon|Manufacturer#4|Brand#43|SMALL BRUSHED NICKEL|9|WRAP BAG|945.04|nts bo +46|honeydew turquoise aquamarine spring tan|Manufacturer#1|Brand#11|STANDARD POLISHED TIN|45|WRAP CASE|946.04|the blithely unusual +47|honeydew red azure magenta brown|Manufacturer#4|Brand#45|LARGE BURNISHED BRASS|14|JUMBO PACK|947.04| even plate +48|slate thistle cornsilk pale forest|Manufacturer#5|Brand#53|STANDARD BRUSHED STEEL|27|JUMBO CASE|948.04|ng to the depo +49|light firebrick cyan puff blue|Manufacturer#2|Brand#24|SMALL BURNISHED TIN|31|MED DRUM|949.04|ar pack +50|linen blanched tomato slate medium|Manufacturer#3|Brand#33|LARGE ANODIZED TIN|25|WRAP PKG|950.05|kages m +51|lime frosted indian dodger linen|Manufacturer#4|Brand#45|ECONOMY BURNISHED NICKEL|34|JUMBO PACK|951.05|n foxes +52|lemon midnight lace sky deep|Manufacturer#3|Brand#35|STANDARD BURNISHED TIN|25|WRAP CASE|952.05| final deposits. fu +53|bisque rose cornsilk seashell purple|Manufacturer#2|Brand#23|ECONOMY BURNISHED NICKEL|32|MED BAG|953.05|mptot +54|blanched mint yellow papaya cyan|Manufacturer#2|Brand#21|LARGE BURNISHED COPPER|19|WRAP CASE|954.05|e blithely +55|sky cream deep tomato rosy|Manufacturer#2|Brand#23|ECONOMY BRUSHED COPPER|9|MED BAG|955.05|ly final pac +56|antique beige brown deep dodger|Manufacturer#1|Brand#12|MEDIUM PLATED STEEL|20|WRAP DRUM|956.05|ts. blithel +57|purple blue light sienna deep|Manufacturer#3|Brand#32|MEDIUM BURNISHED BRASS|49|MED PKG|957.05|lly abov +58|linen hot cornsilk drab bisque|Manufacturer#5|Brand#53|STANDARD POLISHED TIN|44|LG PACK|958.05| fluffily blithely reg +59|misty brown medium mint salmon|Manufacturer#5|Brand#53|MEDIUM POLISHED TIN|2|LG BAG|959.05|regular exc +60|snow spring sandy olive tomato|Manufacturer#1|Brand#11|LARGE POLISHED COPPER|27|JUMBO CASE|960.06| integ +61|light tan linen tomato peach|Manufacturer#5|Brand#54|SMALL BURNISHED NICKEL|18|WRAP DRUM|961.06|es. blithely en +62|tan cornsilk spring grey chocolate|Manufacturer#3|Brand#35|STANDARD BRUSHED BRASS|39|JUMBO BOX|962.06|ckly across the carefu +63|burnished puff coral light papaya|Manufacturer#3|Brand#32|STANDARD BURNISHED NICKEL|10|JUMBO CAN|963.06| quickly +64|aquamarine coral lemon ivory gainsboro|Manufacturer#2|Brand#21|MEDIUM ANODIZED BRASS|1|JUMBO CAN|964.06|efully regular pi +65|slate drab medium puff gainsboro|Manufacturer#5|Brand#53|MEDIUM BRUSHED COPPER|3|MED CAN|965.06|posits after the quic +66|cornflower pale almond lemon linen|Manufacturer#3|Brand#35|PROMO ANODIZED NICKEL|46|SM CASE|966.06|haggle blithely iro +67|slate salmon rose spring seashell|Manufacturer#2|Brand#21|SMALL BRUSHED TIN|31|WRAP DRUM|967.06| regular, p +68|bisque ivory mint purple almond|Manufacturer#1|Brand#11|PROMO ANODIZED STEEL|10|WRAP BOX|968.06|eposits shall h +69|lace burnished rosy antique metallic|Manufacturer#5|Brand#52|MEDIUM POLISHED BRASS|2|SM BOX|969.06|ely final depo +70|violet seashell firebrick dark navajo|Manufacturer#1|Brand#11|STANDARD BRUSHED STEEL|42|LG PACK|970.07|inal gifts. sl +71|violet firebrick cream peru white|Manufacturer#3|Brand#33|STANDARD PLATED BRASS|26|WRAP DRUM|971.07| packages alongside +72|hot spring yellow azure dodger|Manufacturer#2|Brand#23|STANDARD ANODIZED TIN|25|JUMBO PACK|972.07|efully final the +73|cream moccasin royal dim chiffon|Manufacturer#2|Brand#21|SMALL BRUSHED COPPER|35|WRAP DRUM|973.07|ts haggl +74|frosted grey aquamarine thistle papaya|Manufacturer#5|Brand#55|ECONOMY ANODIZED BRASS|25|JUMBO CASE|974.07|ent foxes +75|aquamarine maroon wheat salmon metallic|Manufacturer#3|Brand#35|SMALL BURNISHED NICKEL|39|SM JAR|975.07|s sleep furiou +76|rosy light lime puff sandy|Manufacturer#3|Brand#34|MEDIUM BRUSHED COPPER|9|SM PKG|976.07|n accounts sleep qu +77|mint bisque chiffon snow firebrick|Manufacturer#5|Brand#52|STANDARD BRUSHED COPPER|13|MED PKG|977.07|uests. +78|blush forest slate seashell puff|Manufacturer#1|Brand#14|ECONOMY POLISHED STEEL|24|LG JAR|978.07|icing deposits wake +79|gainsboro pink grey tan almond|Manufacturer#4|Brand#45|PROMO ANODIZED BRASS|22|JUMBO BAG|979.07| foxes are slyly regu +80|tomato chartreuse coral turquoise linen|Manufacturer#4|Brand#44|PROMO PLATED BRASS|28|MED CAN|980.08|unusual dependencies i +81|misty sandy cornsilk dodger blush|Manufacturer#5|Brand#53|ECONOMY BRUSHED TIN|21|MED BAG|981.08|ove the furiou +82|khaki tomato purple almond tan|Manufacturer#1|Brand#15|ECONOMY POLISHED TIN|12|WRAP BOX|982.08|ial requests haggle +83|blush green dim lawn peru|Manufacturer#1|Brand#12|PROMO BURNISHED NICKEL|47|SM CAN|983.08|ly regul +84|salmon floral cream rose dark|Manufacturer#4|Brand#45|SMALL ANODIZED NICKEL|26|JUMBO PACK|984.08|ideas nag +85|dim deep aquamarine smoke pale|Manufacturer#5|Brand#55|PROMO ANODIZED NICKEL|16|LG BAG|985.08| silent +86|green blanched firebrick dim cream|Manufacturer#4|Brand#44|STANDARD PLATED TIN|37|LG CASE|986.08| daring sheaves +87|purple lace seashell antique orange|Manufacturer#4|Brand#41|LARGE PLATED STEEL|41|WRAP PACK|987.08|yly final +88|lime orange bisque chartreuse lemon|Manufacturer#4|Brand#44|PROMO PLATED COPPER|16|SM CASE|988.08|e regular packages. +89|ghost lace lemon sienna saddle|Manufacturer#5|Brand#53|STANDARD BURNISHED STEEL|7|MED JAR|989.08|y final pinto +90|hot rosy violet plum pale|Manufacturer#5|Brand#51|ECONOMY POLISHED STEEL|49|JUMBO CAN|990.09|caref +91|misty bisque lavender spring turquoise|Manufacturer#2|Brand#21|STANDARD BRUSHED TIN|32|JUMBO PKG|991.09|counts dete +92|blush magenta ghost tomato rose|Manufacturer#2|Brand#22|STANDARD ANODIZED TIN|35|JUMBO PKG|992.09|he ironic accounts. sp +93|pale yellow cornsilk dodger moccasin|Manufacturer#2|Brand#24|LARGE ANODIZED TIN|2|WRAP DRUM|993.09| platel +94|blanched pink frosted mint snow|Manufacturer#3|Brand#35|STANDARD POLISHED BRASS|32|SM BOX|994.09|s accounts cajo +95|dodger beige wheat orchid navy|Manufacturer#3|Brand#33|LARGE BRUSHED TIN|36|WRAP DRUM|995.09| final pinto beans +96|chocolate light firebrick rose indian|Manufacturer#5|Brand#53|STANDARD BRUSHED STEEL|32|SM CASE|996.09|ng to the bli +97|coral dodger beige black chartreuse|Manufacturer#3|Brand#33|MEDIUM POLISHED BRASS|49|WRAP CAN|997.09|ss excuses sleep am +98|frosted peru chiffon yellow aquamarine|Manufacturer#5|Brand#54|STANDARD ANODIZED BRASS|22|MED JAR|998.09|e the q +99|mint grey purple sienna metallic|Manufacturer#2|Brand#21|SMALL BURNISHED STEEL|11|JUMBO PKG|999.09|press +100|cyan orchid indian cornflower saddle|Manufacturer#3|Brand#33|ECONOMY ANODIZED TIN|4|LG BAG|1000.10|of the steal +101|powder deep lavender violet gainsboro|Manufacturer#3|Brand#32|LARGE ANODIZED STEEL|26|JUMBO JAR|1001.10|ly even, +102|papaya maroon blush powder sky|Manufacturer#3|Brand#31|MEDIUM BURNISHED BRASS|17|SM DRUM|1002.10|ular packa +103|navy sky spring orchid forest|Manufacturer#2|Brand#25|MEDIUM PLATED BRASS|45|WRAP DRUM|1003.10|e blithely blith +104|plum cyan cornflower midnight royal|Manufacturer#1|Brand#13|MEDIUM ANODIZED STEEL|36|JUMBO BAG|1004.10|ites sleep quickly +105|dodger slate pale mint navajo|Manufacturer#1|Brand#15|SMALL POLISHED COPPER|27|LG DRUM|1005.10|odolites was +106|cornsilk bisque seashell lemon frosted|Manufacturer#3|Brand#31|MEDIUM PLATED BRASS|28|WRAP DRUM|1006.10|unts maintain +107|violet honeydew bisque sienna orchid|Manufacturer#5|Brand#53|SMALL BURNISHED TIN|12|MED BOX|1007.10|slyly special depos +108|bisque peach magenta tomato yellow|Manufacturer#1|Brand#12|PROMO PLATED NICKEL|41|MED PKG|1008.10|after the carefully +109|lemon black indian cornflower pale|Manufacturer#3|Brand#33|ECONOMY POLISHED TIN|11|LG PACK|1009.10|instruction +110|firebrick navy rose beige black|Manufacturer#3|Brand#33|STANDARD BURNISHED COPPER|46|LG DRUM|1010.11|t quickly a +111|orange cornflower mint snow peach|Manufacturer#5|Brand#54|LARGE BRUSHED COPPER|28|JUMBO JAR|1011.11|kly bold epitaphs +112|hot aquamarine tomato lace indian|Manufacturer#4|Brand#43|PROMO BRUSHED STEEL|42|JUMBO CAN|1012.11|the express, +113|almond seashell azure blanched light|Manufacturer#3|Brand#31|PROMO POLISHED TIN|23|LG CAN|1013.11|finally even +114|pink black blanched lace chartreuse|Manufacturer#5|Brand#51|MEDIUM POLISHED NICKEL|41|MED PACK|1014.11|ully final foxes. pint +115|spring chiffon cream orchid dodger|Manufacturer#4|Brand#45|STANDARD POLISHED STEEL|24|MED CAN|1015.11|counts nag! caref +116|goldenrod black slate forest red|Manufacturer#5|Brand#53|PROMO POLISHED NICKEL|33|SM PACK|1016.11|usly final courts +117|tomato honeydew pale red yellow|Manufacturer#1|Brand#14|SMALL BRUSHED TIN|25|LG BAG|1017.11|ages acc +118|ghost plum brown coral cornsilk|Manufacturer#2|Brand#25|PROMO ANODIZED TIN|31|MED PACK|1018.11|ly ironic pinto +119|olive metallic slate peach green|Manufacturer#4|Brand#43|LARGE POLISHED STEEL|30|WRAP CASE|1019.11|out the quickly r +120|pink powder mint moccasin navajo|Manufacturer#1|Brand#14|SMALL ANODIZED NICKEL|45|WRAP JAR|1020.12|lly a +121|bisque royal goldenrod medium thistle|Manufacturer#1|Brand#14|ECONOMY BRUSHED COPPER|13|SM PKG|1021.12|deposi +122|gainsboro royal forest dark lace|Manufacturer#2|Brand#21|MEDIUM ANODIZED TIN|8|LG DRUM|1022.12|sts c +123|deep dim peach light beige|Manufacturer#1|Brand#12|SMALL BURNISHED TIN|31|JUMBO PKG|1023.12|ray regula +124|wheat blush forest metallic navajo|Manufacturer#3|Brand#32|PROMO ANODIZED STEEL|1|LG BOX|1024.12|g the expr +125|mint ivory saddle peach midnight|Manufacturer#1|Brand#12|STANDARD BRUSHED BRASS|17|WRAP BAG|1025.12|kages against +126|burnished black blue metallic orchid|Manufacturer#4|Brand#45|MEDIUM BRUSHED NICKEL|4|LG BAG|1026.12|es sleep al +127|royal coral orchid spring sky|Manufacturer#5|Brand#52|SMALL BURNISHED NICKEL|14|LG JAR|1027.12|lithely expr +128|dark burlywood burnished snow sky|Manufacturer#2|Brand#22|PROMO PLATED TIN|5|SM BAG|1028.12|e of the furiously ex +129|grey spring chiffon thistle lime|Manufacturer#1|Brand#15|LARGE POLISHED TIN|20|SM JAR|1029.12| careful +130|gainsboro powder cyan pale rosy|Manufacturer#2|Brand#23|SMALL PLATED NICKEL|26|LG BOX|1030.13|ake slyly +131|tomato moccasin cyan brown goldenrod|Manufacturer#5|Brand#52|STANDARD ANODIZED BRASS|43|MED DRUM|1031.13|nts wake dar +132|seashell papaya tomato lime hot|Manufacturer#4|Brand#45|STANDARD BURNISHED BRASS|2|WRAP DRUM|1032.13|ckly expre +133|firebrick black dodger pink salmon|Manufacturer#1|Brand#13|SMALL BRUSHED NICKEL|19|LG PKG|1033.13| final pinto beans +134|steel beige mint maroon indian|Manufacturer#4|Brand#42|SMALL POLISHED STEEL|35|SM PKG|1034.13|es. bold pa +135|thistle chocolate ghost gainsboro peru|Manufacturer#2|Brand#21|MEDIUM BURNISHED STEEL|24|JUMBO CASE|1035.13|l frets +136|cornsilk maroon blanched thistle rosy|Manufacturer#2|Brand#22|SMALL PLATED STEEL|2|WRAP BAG|1036.13|kages print carefully +137|cornsilk drab ghost sandy royal|Manufacturer#3|Brand#31|ECONOMY PLATED STEEL|25|MED PACK|1037.13|the t +138|dark aquamarine tomato medium puff|Manufacturer#1|Brand#13|ECONOMY BURNISHED COPPER|42|JUMBO DRUM|1038.13|ts solve acro +139|floral steel burlywood navy cream|Manufacturer#3|Brand#32|MEDIUM BRUSHED STEEL|7|SM BOX|1039.13|ter t +140|aquamarine lavender maroon slate hot|Manufacturer#5|Brand#53|STANDARD PLATED STEEL|45|SM BOX|1040.14|oss the carefu +141|honeydew magenta tomato spring medium|Manufacturer#3|Brand#35|STANDARD ANODIZED STEEL|23|SM PKG|1041.14|ans nag furiously pen +142|chartreuse linen grey slate saddle|Manufacturer#5|Brand#55|STANDARD ANODIZED BRASS|36|MED JAR|1042.14|he accounts. pac +143|bisque dodger blanched steel maroon|Manufacturer#3|Brand#34|ECONOMY PLATED TIN|44|MED BAG|1043.14|nts across the +144|hot midnight orchid dim steel|Manufacturer#1|Brand#14|SMALL ANODIZED TIN|26|SM BOX|1044.14|owly +145|navajo lavender chocolate deep hot|Manufacturer#5|Brand#53|PROMO BRUSHED COPPER|24|SM BAG|1045.14|es wake furiously blit +146|azure smoke mint cream burlywood|Manufacturer#3|Brand#34|STANDARD BRUSHED COPPER|11|WRAP PACK|1046.14|unts cajole +147|honeydew orange dodger linen lace|Manufacturer#1|Brand#11|MEDIUM PLATED COPPER|29|JUMBO PKG|1047.14|wake never bold +148|yellow white ghost lavender salmon|Manufacturer#3|Brand#31|STANDARD PLATED STEEL|20|SM BOX|1048.14|platelets wake fu +149|tan thistle frosted indian lawn|Manufacturer#2|Brand#24|MEDIUM BURNISHED NICKEL|6|MED PKG|1049.14|leep requests. dog +150|pale rose navajo firebrick aquamarine|Manufacturer#3|Brand#35|LARGE BRUSHED TIN|21|SM BAG|1050.15|ironic foxes +151|chartreuse linen violet ghost thistle|Manufacturer#3|Brand#34|LARGE PLATED BRASS|45|MED CAN|1051.15|ccounts nag i +152|white sky antique tomato chartreuse|Manufacturer#5|Brand#53|MEDIUM POLISHED STEEL|48|MED CASE|1052.15|thely regular t +153|linen frosted slate coral peru|Manufacturer#1|Brand#11|STANDARD PLATED TIN|20|MED BAG|1053.15|thlessly. silen +154|peru moccasin peach pale spring|Manufacturer#1|Brand#11|ECONOMY ANODIZED TIN|1|JUMBO BAG|1054.15|posits +155|puff yellow cyan tomato purple|Manufacturer#2|Brand#21|SMALL BRUSHED NICKEL|28|WRAP CASE|1055.15|lly ironic, r +156|almond ghost powder blush forest|Manufacturer#4|Brand#43|SMALL POLISHED NICKEL|2|LG PKG|1056.15| pinto beans. eve +157|navajo linen coral brown forest|Manufacturer#1|Brand#11|ECONOMY ANODIZED STEEL|26|JUMBO PACK|1057.15|ial courts. ru +158|magenta light misty navy honeydew|Manufacturer#4|Brand#45|MEDIUM BURNISHED COPPER|47|LG JAR|1058.15| ideas detect slyl +159|white orange antique beige aquamarine|Manufacturer#4|Brand#43|SMALL ANODIZED BRASS|46|SM BAG|1059.15| ironic requests-- pe +160|frosted cornflower khaki salmon metallic|Manufacturer#5|Brand#55|STANDARD POLISHED COPPER|47|JUMBO CAN|1060.16|nts are carefully +161|metallic khaki navy forest cyan|Manufacturer#2|Brand#22|STANDARD PLATED TIN|17|SM PACK|1061.16|r the bl +162|burlywood cornflower aquamarine misty snow|Manufacturer#3|Brand#33|MEDIUM ANODIZED COPPER|35|JUMBO PACK|1062.16|e slyly around th +163|blush metallic maroon lawn forest|Manufacturer#2|Brand#21|ECONOMY PLATED TIN|34|WRAP DRUM|1063.16|nly s +164|orange cyan magenta navajo indian|Manufacturer#2|Brand#23|LARGE PLATED BRASS|35|JUMBO BAG|1064.16|mong th +165|white dim cornflower sky seashell|Manufacturer#1|Brand#15|STANDARD PLATED STEEL|24|SM CAN|1065.16| carefully fin +166|linen bisque tomato gainsboro goldenrod|Manufacturer#5|Brand#52|LARGE POLISHED COPPER|4|MED BAG|1066.16|ss the +167|almond floral grey dim sky|Manufacturer#3|Brand#32|LARGE ANODIZED STEEL|46|WRAP BOX|1067.16|ic ac +168|lace gainsboro burlywood smoke tomato|Manufacturer#1|Brand#13|SMALL BRUSHED COPPER|20|JUMBO DRUM|1068.16|ss package +169|bisque misty sky cornflower peach|Manufacturer#5|Brand#55|STANDARD POLISHED BRASS|10|JUMBO CASE|1069.16|lets alongside of +170|peru grey blanched goldenrod yellow|Manufacturer#3|Brand#33|LARGE POLISHED COPPER|28|LG DRUM|1070.17|yly s +171|beige violet black magenta chartreuse|Manufacturer#1|Brand#11|STANDARD BURNISHED COPPER|40|LG JAR|1071.17| the r +172|medium goldenrod linen sky coral|Manufacturer#5|Brand#53|PROMO PLATED NICKEL|28|MED CASE|1072.17|quick as +173|chartreuse seashell powder navy grey|Manufacturer#1|Brand#12|ECONOMY BURNISHED TIN|17|LG CASE|1073.17|sly bold excuses haggl +174|hot cornflower slate saddle pale|Manufacturer#1|Brand#15|ECONOMY BRUSHED COPPER|25|LG CASE|1074.17| accounts nag ab +175|magenta blue chartreuse tan green|Manufacturer#1|Brand#11|PROMO ANODIZED TIN|45|JUMBO JAR|1075.17|ole against the +176|pink drab ivory papaya grey|Manufacturer#2|Brand#24|SMALL ANODIZED STEEL|40|MED CAN|1076.17|blithely. ironic +177|indian turquoise purple green spring|Manufacturer#2|Brand#21|MEDIUM BRUSHED STEEL|42|LG BAG|1077.17|ermanently eve +178|lace blanched magenta yellow almond|Manufacturer#1|Brand#13|STANDARD POLISHED TIN|10|LG JAR|1078.17|regular instructions. +179|deep puff brown blue burlywood|Manufacturer#4|Brand#43|ECONOMY BRUSHED STEEL|20|LG JAR|1079.17|ely regul +180|seashell maroon lace burnished lavender|Manufacturer#3|Brand#33|STANDARD BURNISHED NICKEL|7|WRAP BAG|1080.18|oss the +181|antique plum smoke pink dodger|Manufacturer#2|Brand#24|MEDIUM PLATED STEEL|19|WRAP CAN|1081.18|al deposits +182|beige cyan burlywood chiffon light|Manufacturer#3|Brand#31|MEDIUM ANODIZED COPPER|11|JUMBO CAN|1082.18|bits are +183|ivory white burnished papaya cornflower|Manufacturer#5|Brand#52|PROMO POLISHED STEEL|35|LG PKG|1083.18|ly regular excus +184|ghost honeydew cyan lawn powder|Manufacturer#5|Brand#53|SMALL POLISHED TIN|42|LG BOX|1084.18|ding courts. idly iro +185|firebrick black ivory spring medium|Manufacturer#4|Brand#44|ECONOMY POLISHED TIN|4|WRAP BAG|1085.18|even foxe +186|grey purple chocolate turquoise plum|Manufacturer#2|Brand#23|ECONOMY BRUSHED TIN|15|JUMBO PKG|1086.18|ly reg +187|white red lace deep pale|Manufacturer#4|Brand#45|PROMO ANODIZED BRASS|45|MED CAN|1087.18|leep slyly s +188|moccasin steel rosy drab white|Manufacturer#5|Brand#54|ECONOMY ANODIZED BRASS|9|MED CAN|1088.18| above the silent p +189|dodger moccasin lemon purple thistle|Manufacturer#2|Brand#22|MEDIUM BRUSHED BRASS|13|WRAP DRUM|1089.18|en requests. sauternes +190|chartreuse goldenrod midnight cornflower blush|Manufacturer#5|Brand#53|LARGE BURNISHED NICKEL|23|WRAP BAG|1090.19| furiously even d +191|mint midnight puff forest peach|Manufacturer#3|Brand#31|MEDIUM POLISHED BRASS|36|WRAP BOX|1091.19| asymptote +192|thistle puff pink cream orange|Manufacturer#3|Brand#34|STANDARD BRUSHED COPPER|17|MED BAG|1092.19|uickly regular, expr +193|turquoise lime royal metallic azure|Manufacturer#4|Brand#45|ECONOMY BURNISHED BRASS|31|SM PKG|1093.19|final ideas wake furi +194|brown black cream navy plum|Manufacturer#5|Brand#51|ECONOMY POLISHED STEEL|7|SM CAN|1094.19|y special accoun +195|bisque sienna hot goldenrod khaki|Manufacturer#4|Brand#41|STANDARD BRUSHED NICKEL|40|MED CASE|1095.19|oxes sleep care +196|pale peru linen hot maroon|Manufacturer#3|Brand#33|SMALL BURNISHED NICKEL|3|JUMBO JAR|1096.19|uickly special +197|lawn lemon khaki rosy blue|Manufacturer#5|Brand#52|SMALL ANODIZED COPPER|18|SM JAR|1097.19|lithely after the eve +198|orange cornflower indian aquamarine white|Manufacturer#4|Brand#41|PROMO BRUSHED NICKEL|43|SM PACK|1098.19|ackages? carefully re +199|ivory slate lavender tan royal|Manufacturer#3|Brand#31|ECONOMY PLATED STEEL|23|JUMBO DRUM|1099.19|ickly regul +200|peach cornsilk navy rosy red|Manufacturer#5|Brand#54|MEDIUM POLISHED BRASS|22|LG PKG|1100.20|furiously even depo +201|dodger white chiffon moccasin green|Manufacturer#4|Brand#42|SMALL POLISHED STEEL|18|JUMBO BAG|1101.20| courts sl +202|brown violet turquoise frosted navajo|Manufacturer#4|Brand#45|MEDIUM BRUSHED COPPER|49|MED DRUM|1102.20| use slyly c +203|beige cornflower gainsboro chiffon wheat|Manufacturer#5|Brand#55|STANDARD ANODIZED STEEL|42|MED BAG|1103.20|usual instructio +204|floral powder deep linen hot|Manufacturer#5|Brand#54|LARGE BURNISHED COPPER|22|SM JAR|1104.20|egular pl +205|navajo bisque gainsboro forest coral|Manufacturer#5|Brand#54|ECONOMY PLATED NICKEL|2|JUMBO DRUM|1105.20| blithely regular +206|chiffon coral wheat peru lavender|Manufacturer#2|Brand#25|LARGE ANODIZED NICKEL|23|JUMBO CAN|1106.20|ng theodolites +207|blush chocolate light coral midnight|Manufacturer#3|Brand#35|STANDARD PLATED COPPER|48|MED CAN|1107.20|lar, +208|medium pink metallic honeydew ghost|Manufacturer#3|Brand#35|LARGE PLATED COPPER|5|MED PACK|1108.20|l deposits wak +209|sky plum pink lavender firebrick|Manufacturer#1|Brand#11|ECONOMY PLATED STEEL|6|MED CAN|1109.20| haggle a +210|white sky mint chiffon blanched|Manufacturer#3|Brand#32|ECONOMY BURNISHED TIN|5|LG JAR|1110.21|ly until the flu +211|turquoise forest orchid cream blue|Manufacturer#3|Brand#32|MEDIUM ANODIZED NICKEL|43|LG PKG|1111.21|s cajole +212|light sandy white bisque burlywood|Manufacturer#5|Brand#53|PROMO BRUSHED BRASS|42|JUMBO BOX|1112.21|uffily fin +213|pale midnight light ghost saddle|Manufacturer#3|Brand#35|SMALL POLISHED COPPER|14|WRAP CAN|1113.21|der slyly accor +214|cornsilk tomato firebrick tan puff|Manufacturer#4|Brand#41|PROMO PLATED BRASS|30|LG BAG|1114.21|quests. regular, fi +215|lace pink black orange cornflower|Manufacturer#5|Brand#52|ECONOMY BURNISHED NICKEL|19|SM PACK|1115.21| the carefully i +216|tan azure slate white mint|Manufacturer#4|Brand#45|MEDIUM PLATED NICKEL|35|MED JAR|1116.21|gside of the unus +217|lemon thistle sandy royal peru|Manufacturer#5|Brand#52|PROMO PLATED COPPER|44|MED DRUM|1117.21|heodolites integrat +218|sandy khaki ghost cornflower metallic|Manufacturer#4|Brand#41|PROMO BURNISHED TIN|24|WRAP PACK|1118.21| furiously +219|cyan aquamarine red plum frosted|Manufacturer#4|Brand#45|PROMO ANODIZED BRASS|31|MED JAR|1119.21|riously ironic reque +220|lemon firebrick lime white wheat|Manufacturer#1|Brand#14|PROMO BRUSHED BRASS|25|MED CASE|1120.22|heodolites sleep. c +221|chartreuse azure lemon saddle dark|Manufacturer#5|Brand#51|PROMO BRUSHED COPPER|7|LG DRUM|1121.22|ld asymptotes sleep ca +222|aquamarine puff antique drab beige|Manufacturer#3|Brand#33|LARGE ANODIZED BRASS|35|LG CASE|1122.22|ross the ironic, un +223|rose salmon yellow turquoise grey|Manufacturer#3|Brand#33|LARGE ANODIZED STEEL|29|MED BAG|1123.22|ons. even depos +224|drab lavender moccasin almond purple|Manufacturer#1|Brand#13|STANDARD POLISHED NICKEL|46|WRAP BOX|1124.22|y special depos +225|cornsilk powder bisque chartreuse spring|Manufacturer#4|Brand#45|ECONOMY BRUSHED TIN|23|MED CASE|1125.22|ts ca +226|blush navy indian peru lemon|Manufacturer#3|Brand#33|PROMO ANODIZED STEEL|7|SM PKG|1126.22|ular packages. some +227|dim yellow aquamarine lavender peach|Manufacturer#4|Brand#44|SMALL BRUSHED TIN|21|LG PACK|1127.22| silent r +228|saddle lawn blue burlywood white|Manufacturer#4|Brand#44|ECONOMY PLATED STEEL|12|SM DRUM|1128.22|f the fluffily +229|orchid misty cornsilk chartreuse medium|Manufacturer#1|Brand#15|SMALL POLISHED STEEL|19|MED CAN|1129.22|ng to the quick +230|thistle navy lawn sky slate|Manufacturer#5|Brand#51|STANDARD PLATED STEEL|20|SM PKG|1130.23|fter the ironic pin +231|bisque blush beige honeydew slate|Manufacturer#5|Brand#51|MEDIUM BURNISHED COPPER|17|MED PACK|1131.23|ffily. fur +232|ivory peru lavender orange dark|Manufacturer#5|Brand#53|LARGE BURNISHED NICKEL|50|SM PKG|1132.23|r, unusual requests +233|seashell tomato red lemon saddle|Manufacturer#3|Brand#34|MEDIUM ANODIZED BRASS|25|SM PACK|1133.23|ully ironic +234|chocolate slate maroon azure goldenrod|Manufacturer#1|Brand#13|MEDIUM ANODIZED NICKEL|26|WRAP BOX|1134.23| furiously special +235|sky mint aquamarine dark cornsilk|Manufacturer#3|Brand#32|ECONOMY BRUSHED COPPER|4|MED JAR|1135.23|s. carefully regular d +236|salmon antique burlywood linen peach|Manufacturer#5|Brand#55|ECONOMY ANODIZED STEEL|31|LG JAR|1136.23|ss packages hag +237|yellow orchid dark light smoke|Manufacturer#2|Brand#25|LARGE BURNISHED TIN|49|SM DRUM|1137.23|g the furiously +238|purple dark lawn navajo indian|Manufacturer#3|Brand#34|SMALL POLISHED TIN|35|LG CAN|1138.23|d, expres +239|medium olive pink dim firebrick|Manufacturer#2|Brand#24|LARGE PLATED NICKEL|36|WRAP DRUM|1139.23|lites are perman +240|rose beige magenta coral sandy|Manufacturer#3|Brand#32|MEDIUM BURNISHED NICKEL|1|LG CAN|1140.24|ructions. +241|purple drab puff peach tomato|Manufacturer#5|Brand#51|STANDARD BRUSHED COPPER|3|WRAP CASE|1141.24| quickly regular fo +242|spring green lemon medium olive|Manufacturer#3|Brand#35|SMALL POLISHED STEEL|42|LG BAG|1142.24|ously final theodo +243|bisque chiffon orange misty tan|Manufacturer#3|Brand#32|MEDIUM ANODIZED STEEL|49|SM BOX|1143.24|ress sentim +244|seashell ghost cyan burlywood thistle|Manufacturer#5|Brand#51|ECONOMY BURNISHED BRASS|48|LG BOX|1144.24|ns use above the ir +245|beige orchid chartreuse powder slate|Manufacturer#2|Brand#23|PROMO BURNISHED BRASS|39|JUMBO PKG|1145.24| instructions. ca +246|burlywood orchid dark drab dodger|Manufacturer#2|Brand#21|PROMO BRUSHED BRASS|18|SM CAN|1146.24|e caref +247|medium gainsboro lawn coral peach|Manufacturer#5|Brand#53|LARGE BURNISHED BRASS|4|JUMBO PACK|1147.24|r accounts. carefully +248|drab aquamarine red papaya pale|Manufacturer#1|Brand#15|SMALL PLATED BRASS|8|MED PACK|1148.24|furiously fluffily +249|hot sandy lavender saddle rosy|Manufacturer#4|Brand#44|ECONOMY BURNISHED BRASS|15|LG JAR|1149.24| excuses kindle f +250|antique goldenrod floral forest slate|Manufacturer#4|Brand#44|PROMO POLISHED NICKEL|35|WRAP CASE|1150.25|nstructions affix furi +251|dodger gainsboro violet steel papaya|Manufacturer#1|Brand#15|STANDARD BRUSHED NICKEL|41|WRAP CAN|1151.25|inal ideas aff +252|royal sienna magenta lace brown|Manufacturer#1|Brand#11|PROMO PLATED NICKEL|22|WRAP DRUM|1152.25|e slyly after the de +253|blanched ghost turquoise burlywood spring|Manufacturer#4|Brand#45|PROMO ANODIZED TIN|16|LG PKG|1153.25|he even, re +254|navy light red royal olive|Manufacturer#4|Brand#44|MEDIUM PLATED TIN|10|MED JAR|1154.25|ly at t +255|aquamarine seashell grey navy white|Manufacturer#2|Brand#21|LARGE ANODIZED NICKEL|24|JUMBO CAN|1155.25|fter the c +256|royal cream lawn purple powder|Manufacturer#3|Brand#32|LARGE BURNISHED TIN|2|SM DRUM|1156.25|bove the fur +257|blue gainsboro maroon green burnished|Manufacturer#4|Brand#41|ECONOMY POLISHED COPPER|11|SM JAR|1157.25|riously final foxes +258|royal frosted blue pale dim|Manufacturer#4|Brand#43|STANDARD ANODIZED COPPER|18|WRAP DRUM|1158.25|leep blith +259|ghost puff sky linen burnished|Manufacturer#2|Brand#23|SMALL BURNISHED BRASS|41|WRAP PACK|1159.25|l platelets. evenly +260|firebrick thistle lime frosted khaki|Manufacturer#5|Brand#55|STANDARD ANODIZED STEEL|10|LG BAG|1160.26| haggle f +261|floral moccasin puff rosy ghost|Manufacturer#4|Brand#41|STANDARD POLISHED TIN|44|JUMBO PACK|1161.26|ges was i +262|drab lavender lawn purple puff|Manufacturer#5|Brand#52|MEDIUM PLATED NICKEL|16|JUMBO BAG|1162.26|lar theodolites. f +263|linen red plum purple steel|Manufacturer#1|Brand#14|ECONOMY BURNISHED COPPER|46|MED CASE|1163.26|ly ironic the +264|plum floral sienna magenta ivory|Manufacturer#1|Brand#14|SMALL BURNISHED TIN|23|SM CAN|1164.26|ake. noto +265|aquamarine magenta seashell orange royal|Manufacturer#4|Brand#43|SMALL POLISHED STEEL|19|WRAP CASE|1165.26| slyly ac +266|medium brown tomato cornflower moccasin|Manufacturer#4|Brand#43|ECONOMY BRUSHED STEEL|25|LG DRUM|1166.26|odoli +267|pink salmon moccasin orange wheat|Manufacturer#2|Brand#24|LARGE POLISHED BRASS|41|JUMBO PACK|1167.26|ckly speci +268|cornsilk seashell lime aquamarine violet|Manufacturer#2|Brand#22|MEDIUM PLATED NICKEL|8|MED JAR|1168.26| carefully sil +269|chartreuse navajo moccasin orchid spring|Manufacturer#1|Brand#13|LARGE PLATED BRASS|5|WRAP BOX|1169.26|ully about the ca +270|mint deep white navajo floral|Manufacturer#2|Brand#25|PROMO BURNISHED COPPER|45|MED BAG|1170.27|ly even pinto beans. c +271|lace floral peru dim magenta|Manufacturer#5|Brand#52|PROMO PLATED COPPER|32|MED PKG|1171.27| fluffy acco +272|red purple tomato medium papaya|Manufacturer#5|Brand#52|LARGE POLISHED BRASS|39|LG PKG|1172.27| furiousl +273|pink white sky burnished coral|Manufacturer#2|Brand#25|STANDARD BRUSHED BRASS|50|LG BOX|1173.27|ackages along the +274|cyan lawn snow sky peru|Manufacturer#2|Brand#23|MEDIUM POLISHED STEEL|46|LG JAR|1174.27|hless accounts prin +275|steel chartreuse red plum sienna|Manufacturer#4|Brand#45|LARGE BURNISHED BRASS|37|SM BOX|1175.27|equests +276|orange yellow drab grey blanched|Manufacturer#2|Brand#25|SMALL BRUSHED COPPER|5|LG JAR|1176.27|iously. +277|grey navy rosy red burnished|Manufacturer#4|Brand#43|ECONOMY ANODIZED NICKEL|49|JUMBO JAR|1177.27|arefully special dep +278|blanched lime almond moccasin floral|Manufacturer#4|Brand#42|STANDARD BURNISHED NICKEL|49|SM JAR|1178.27| bold p +279|linen olive lawn blanched gainsboro|Manufacturer#3|Brand#35|SMALL ANODIZED BRASS|27|MED CASE|1179.27|eans boos +280|blue azure slate lace burlywood|Manufacturer#2|Brand#21|STANDARD BURNISHED STEEL|33|LG CAN|1180.28|egular, s +281|red mint brown powder rose|Manufacturer#1|Brand#12|SMALL PLATED STEEL|7|MED CAN|1181.28|regula +282|steel burnished cornsilk beige lace|Manufacturer#1|Brand#11|SMALL BRUSHED COPPER|44|WRAP CAN|1182.28|packages. final ex +283|metallic burlywood lavender midnight cornsilk|Manufacturer#1|Brand#12|SMALL PLATED TIN|8|SM DRUM|1183.28| above the i +284|burlywood chocolate almond ivory coral|Manufacturer#5|Brand#51|ECONOMY POLISHED COPPER|9|MED DRUM|1184.28|its haggle fu +285|cream seashell orange frosted brown|Manufacturer#2|Brand#25|LARGE ANODIZED TIN|42|SM PACK|1185.28| the furiously fi +286|chocolate cornsilk goldenrod violet puff|Manufacturer#5|Brand#53|MEDIUM POLISHED TIN|1|WRAP CASE|1186.28| foxes. regular, fi +287|misty snow thistle burlywood wheat|Manufacturer#1|Brand#15|SMALL PLATED NICKEL|27|SM DRUM|1187.28|y even foxes. final, +288|tan purple yellow ivory olive|Manufacturer#2|Brand#23|STANDARD BURNISHED BRASS|31|SM CASE|1188.28|dencies mold among the +289|peach antique deep peru saddle|Manufacturer#4|Brand#43|PROMO POLISHED TIN|40|LG CASE|1189.28|odolites sleep care +290|deep wheat forest powder firebrick|Manufacturer#1|Brand#12|LARGE BURNISHED BRASS|19|JUMBO JAR|1190.29|according to t +291|goldenrod aquamarine olive white pink|Manufacturer#5|Brand#54|ECONOMY PLATED BRASS|26|SM JAR|1191.29|kages alo +292|navajo tan coral slate thistle|Manufacturer#1|Brand#12|SMALL PLATED NICKEL|2|MED CAN|1192.29|zzle among t +293|lawn cyan plum bisque cream|Manufacturer#5|Brand#52|STANDARD POLISHED STEEL|24|SM PACK|1193.29|onic requests +294|midnight misty royal floral brown|Manufacturer#2|Brand#24|ECONOMY POLISHED TIN|35|SM JAR|1194.29|truct +295|honeydew lace powder almond red|Manufacturer#2|Brand#25|MEDIUM BURNISHED NICKEL|49|JUMBO JAR|1195.29|ully ironic +296|tan seashell chocolate lemon orange|Manufacturer#1|Brand#13|LARGE BURNISHED BRASS|28|SM PKG|1196.29|, regul +297|antique powder almond navajo lace|Manufacturer#2|Brand#22|LARGE BURNISHED STEEL|23|LG PACK|1197.29|e of the slyl +298|azure sky tomato midnight lace|Manufacturer#4|Brand#45|PROMO BRUSHED COPPER|13|JUMBO CAN|1198.29|al deposits wake +299|deep coral dodger green peach|Manufacturer#4|Brand#41|STANDARD ANODIZED COPPER|26|WRAP PKG|1199.29|regular dol +300|light goldenrod green lime papaya|Manufacturer#4|Brand#44|PROMO ANODIZED BRASS|1|WRAP PACK|1200.30|tructions int +301|misty snow lace burnished linen|Manufacturer#4|Brand#42|ECONOMY BRUSHED STEEL|6|WRAP CAN|1201.30|orges +302|black seashell sky grey snow|Manufacturer#4|Brand#41|PROMO POLISHED BRASS|34|SM BAG|1202.30| ideas. special asy +303|almond chocolate firebrick black bisque|Manufacturer#4|Brand#45|ECONOMY PLATED BRASS|7|JUMBO CASE|1203.30|yly according +304|forest mint sienna navy ghost|Manufacturer#4|Brand#43|SMALL POLISHED NICKEL|12|LG DRUM|1204.30|ly regu +305|moccasin tan chartreuse cornsilk drab|Manufacturer#1|Brand#15|SMALL ANODIZED TIN|6|SM BAG|1205.30|ake above +306|lemon peach spring rose ghost|Manufacturer#3|Brand#33|SMALL BURNISHED NICKEL|25|LG PKG|1206.30| regular req +307|peru beige firebrick royal navy|Manufacturer#2|Brand#21|LARGE BURNISHED BRASS|30|WRAP DRUM|1207.30|eas. e +308|olive ivory turquoise sienna wheat|Manufacturer#2|Brand#21|STANDARD BURNISHED BRASS|40|WRAP JAR|1208.30|ngside of the s +309|red smoke blue pale lace|Manufacturer#4|Brand#42|LARGE ANODIZED NICKEL|49|JUMBO PKG|1209.30|lly even c +310|sandy sky dark navy blanched|Manufacturer#1|Brand#14|ECONOMY BRUSHED NICKEL|32|MED JAR|1210.31|arefully. requ +311|indian orchid navajo dark forest|Manufacturer#4|Brand#44|MEDIUM PLATED TIN|18|LG DRUM|1211.31|final, +312|powder firebrick white peach goldenrod|Manufacturer#3|Brand#32|PROMO BURNISHED STEEL|29|MED CASE|1212.31|nts doze slyly. d +313|moccasin rosy lemon linen royal|Manufacturer#3|Brand#34|PROMO BRUSHED TIN|13|WRAP PACK|1213.31|nly regular +314|grey royal seashell violet misty|Manufacturer#3|Brand#35|STANDARD PLATED STEEL|14|LG DRUM|1214.31|ular deposits. +315|navy cyan orchid seashell moccasin|Manufacturer#2|Brand#23|LARGE ANODIZED BRASS|20|LG JAR|1215.31|s was slyly pac +316|almond rosy green hot midnight|Manufacturer#4|Brand#41|MEDIUM BRUSHED TIN|9|MED CASE|1216.31|deposits haggle +317|linen peru thistle turquoise medium|Manufacturer#1|Brand#15|LARGE POLISHED STEEL|34|JUMBO BOX|1217.31|e furiously regular pa +318|rosy rose indian puff pale|Manufacturer#1|Brand#12|PROMO BURNISHED NICKEL|20|JUMBO CASE|1218.31|ar re +319|royal metallic lawn spring firebrick|Manufacturer#3|Brand#31|MEDIUM BURNISHED TIN|44|LG BOX|1219.31|kages boost along +320|chiffon linen rose white rosy|Manufacturer#5|Brand#53|LARGE ANODIZED STEEL|26|WRAP DRUM|1220.32|structions a +321|tomato drab cream tan navajo|Manufacturer#5|Brand#51|ECONOMY ANODIZED STEEL|9|SM JAR|1221.32|tructions boost car +322|dark black rosy yellow ivory|Manufacturer#3|Brand#35|STANDARD PLATED STEEL|32|JUMBO CASE|1222.32|uses. blithely pendin +323|moccasin goldenrod tan maroon bisque|Manufacturer#4|Brand#41|MEDIUM BRUSHED BRASS|15|MED CASE|1223.32|ular pi +324|aquamarine ivory magenta linen black|Manufacturer#2|Brand#25|SMALL PLATED TIN|36|SM BAG|1224.32|ages. requests wake. +325|plum cyan almond dark orchid|Manufacturer#1|Brand#15|LARGE PLATED COPPER|22|MED PACK|1225.32|ackages. slyly pendin +326|sky papaya green azure chiffon|Manufacturer#3|Brand#34|LARGE ANODIZED STEEL|48|JUMBO CAN|1226.32|aggle slyly special f +327|metallic lavender green firebrick ghost|Manufacturer#2|Brand#23|PROMO POLISHED BRASS|14|SM PACK|1227.32|regular +328|turquoise bisque wheat cornflower forest|Manufacturer#3|Brand#34|PROMO POLISHED COPPER|24|JUMBO CASE|1228.32|ronic dependencies +329|mint dodger chocolate papaya azure|Manufacturer#3|Brand#31|MEDIUM ANODIZED NICKEL|21|LG PKG|1229.32|. quickly pending pa +330|royal lime misty frosted smoke|Manufacturer#3|Brand#35|LARGE PLATED COPPER|18|LG JAR|1230.33|efully pending depend +331|metallic ivory cornsilk mint hot|Manufacturer#2|Brand#25|SMALL BURNISHED COPPER|15|WRAP JAR|1231.33| the slyly iron +332|frosted blush firebrick linen salmon|Manufacturer#2|Brand#24|STANDARD BRUSHED BRASS|14|SM CAN|1232.33|instru +333|chocolate tomato light chartreuse orange|Manufacturer#2|Brand#21|ECONOMY POLISHED COPPER|1|LG DRUM|1233.33|accordi +334|lawn wheat dodger forest firebrick|Manufacturer#3|Brand#31|ECONOMY PLATED BRASS|32|LG JAR|1234.33|deas. blithely express +335|dark cream plum goldenrod smoke|Manufacturer#3|Brand#32|SMALL BRUSHED COPPER|3|SM JAR|1235.33|ly ironic deposits h +336|maroon medium green tomato rosy|Manufacturer#2|Brand#25|PROMO ANODIZED TIN|3|WRAP JAR|1236.33|nto beans. +337|magenta lavender blush peru aquamarine|Manufacturer#2|Brand#23|MEDIUM BRUSHED COPPER|29|MED DRUM|1237.33|uests. carefully fin +338|turquoise honeydew dim saddle grey|Manufacturer#1|Brand#14|LARGE ANODIZED NICKEL|26|JUMBO JAR|1238.33|of th +339|saddle white red royal midnight|Manufacturer#2|Brand#23|PROMO BURNISHED COPPER|14|LG PACK|1239.33|across the slyly expre +340|sienna purple lawn coral navy|Manufacturer#2|Brand#23|STANDARD BRUSHED TIN|3|JUMBO BOX|1240.34|l ideas wake. quic +341|pale smoke drab spring burnished|Manufacturer#4|Brand#45|PROMO POLISHED COPPER|34|MED PKG|1241.34|ully regular a +342|purple indian burnished khaki puff|Manufacturer#4|Brand#43|LARGE BURNISHED NICKEL|37|JUMBO CAN|1242.34|riously final pac +343|blush thistle chartreuse tomato navy|Manufacturer#3|Brand#35|PROMO ANODIZED NICKEL|7|SM JAR|1243.34|s-- ironic foxes boost +344|lime chiffon sky magenta midnight|Manufacturer#4|Brand#45|LARGE ANODIZED TIN|39|SM BOX|1244.34| according to the pend +345|cyan frosted spring orange puff|Manufacturer#4|Brand#45|ECONOMY BURNISHED NICKEL|22|LG CAN|1245.34|un carefull +346|medium honeydew blush lace lemon|Manufacturer#5|Brand#51|ECONOMY BRUSHED COPPER|8|LG PKG|1246.34|benea +347|deep antique royal bisque rosy|Manufacturer#3|Brand#34|SMALL ANODIZED TIN|28|WRAP BAG|1247.34|r, even instruct +348|blush navajo peru chartreuse dim|Manufacturer#5|Brand#53|MEDIUM POLISHED STEEL|16|WRAP BOX|1248.34| pending +349|ghost black hot salmon lace|Manufacturer#2|Brand#24|ECONOMY BURNISHED NICKEL|12|MED JAR|1249.34|tes. unusual acco +350|peach thistle royal papaya cornsilk|Manufacturer#3|Brand#32|STANDARD ANODIZED NICKEL|25|WRAP CAN|1250.35|luffily p +351|slate pale misty sienna red|Manufacturer#3|Brand#32|STANDARD PLATED TIN|48|WRAP CAN|1251.35|sts integrate. bl +352|sandy almond peach ivory violet|Manufacturer#4|Brand#42|MEDIUM BURNISHED BRASS|44|JUMBO CAN|1252.35|lites ne +353|azure linen grey blanched dim|Manufacturer#3|Brand#34|PROMO BURNISHED TIN|43|WRAP JAR|1253.35|final packages use +354|frosted deep powder beige lemon|Manufacturer#4|Brand#42|PROMO BURNISHED STEEL|38|LG CAN|1254.35|d requests wake +355|mint goldenrod sandy burnished olive|Manufacturer#5|Brand#52|ECONOMY POLISHED NICKEL|16|JUMBO JAR|1255.35| slyly bold theodoli +356|hot pink peach lemon chartreuse|Manufacturer#1|Brand#14|STANDARD BRUSHED NICKEL|46|WRAP BAG|1256.35|according to the furio +357|frosted rosy powder floral mint|Manufacturer#4|Brand#42|STANDARD PLATED COPPER|19|SM DRUM|1257.35|s use at +358|purple maroon lavender cornsilk salmon|Manufacturer#2|Brand#24|STANDARD POLISHED BRASS|39|JUMBO PACK|1258.35|g grouches use slyly +359|pink medium olive rosy linen|Manufacturer#3|Brand#35|PROMO PLATED BRASS|19|LG DRUM|1259.35|ithely +360|midnight papaya violet peach cream|Manufacturer#3|Brand#35|SMALL POLISHED COPPER|14|WRAP BOX|1260.36|. bold +361|indian dim tan antique puff|Manufacturer#5|Brand#52|SMALL ANODIZED COPPER|42|WRAP DRUM|1261.36| dolphins. carefully r +362|sienna green ghost rose lawn|Manufacturer#1|Brand#13|ECONOMY POLISHED COPPER|9|JUMBO BAG|1262.36|accounts. furi +363|rosy grey blush dark lime|Manufacturer#2|Brand#22|MEDIUM ANODIZED BRASS|16|WRAP JAR|1263.36|ideas. regular ac +364|puff almond blanched drab misty|Manufacturer#4|Brand#43|LARGE BRUSHED NICKEL|21|MED PKG|1264.36|ach caref +365|olive blue navy frosted violet|Manufacturer#3|Brand#31|SMALL POLISHED STEEL|8|LG CAN|1265.36|efully regula +366|seashell antique beige thistle cream|Manufacturer#5|Brand#53|ECONOMY BURNISHED STEEL|46|WRAP DRUM|1266.36|unts cajole +367|black lavender dark cornflower grey|Manufacturer#2|Brand#23|STANDARD PLATED BRASS|2|JUMBO PACK|1267.36|ly about the tithe +368|cornsilk blush bisque hot cyan|Manufacturer#5|Brand#52|ECONOMY BRUSHED TIN|8|SM PACK|1268.36|t the even, +369|drab plum olive firebrick beige|Manufacturer#2|Brand#21|SMALL POLISHED BRASS|11|SM BOX|1269.36|ilent request +370|almond linen pale aquamarine ghost|Manufacturer#5|Brand#52|LARGE BRUSHED COPPER|46|JUMBO BOX|1270.37|ost quickly against +371|maroon dark beige forest drab|Manufacturer#4|Brand#45|ECONOMY ANODIZED COPPER|27|MED BAG|1271.37|o beans. even inst +372|black frosted aquamarine maroon orange|Manufacturer#3|Brand#32|LARGE ANODIZED STEEL|35|LG CAN|1272.37| regular accounts +373|beige blanched coral cornsilk sky|Manufacturer#5|Brand#53|STANDARD PLATED TIN|37|JUMBO PACK|1273.37| after the fl +374|orange lemon cream dim midnight|Manufacturer#1|Brand#11|LARGE PLATED STEEL|18|MED BOX|1274.37| packages. furiou +375|floral blush lawn puff brown|Manufacturer#1|Brand#15|SMALL POLISHED BRASS|16|JUMBO JAR|1275.37| ironic courts aga +376|lace drab wheat red tan|Manufacturer#4|Brand#44|MEDIUM BRUSHED STEEL|44|SM PKG|1276.37|blithe +377|green forest rose slate cornflower|Manufacturer#4|Brand#44|STANDARD BURNISHED COPPER|16|WRAP BOX|1277.37|ly regula +378|burnished lime green turquoise red|Manufacturer#3|Brand#32|SMALL PLATED COPPER|45|JUMBO PACK|1278.37| slyly careful, ironic +379|cream sienna sandy thistle medium|Manufacturer#3|Brand#33|ECONOMY POLISHED STEEL|5|SM CASE|1279.37|l have to sl +380|khaki powder royal maroon snow|Manufacturer#4|Brand#41|LARGE BRUSHED TIN|6|JUMBO DRUM|1280.38|tions. blithely ev +381|sienna peach wheat linen tomato|Manufacturer#5|Brand#53|ECONOMY ANODIZED COPPER|37|LG CASE|1281.38|ons. furiousl +382|honeydew ghost lace plum sky|Manufacturer#4|Brand#41|LARGE POLISHED BRASS|4|SM CAN|1282.38|blithely +383|seashell tan purple almond coral|Manufacturer#2|Brand#23|SMALL BRUSHED COPPER|45|SM PACK|1283.38|telet +384|papaya thistle rosy rose puff|Manufacturer#4|Brand#43|STANDARD BURNISHED TIN|2|WRAP CAN|1284.38|blithel +385|snow chocolate ivory lemon magenta|Manufacturer#1|Brand#12|STANDARD PLATED TIN|41|WRAP JAR|1285.38|nts wake +386|red blanched thistle bisque wheat|Manufacturer#1|Brand#13|STANDARD PLATED STEEL|4|SM BOX|1286.38|ests. final a +387|smoke white metallic sky firebrick|Manufacturer#3|Brand#34|LARGE BRUSHED COPPER|23|WRAP CASE|1287.38|gular w +388|lawn puff grey forest indian|Manufacturer#1|Brand#11|STANDARD POLISHED STEEL|20|LG PKG|1288.38|nt pinto beans after t +389|magenta ivory lawn antique turquoise|Manufacturer#1|Brand#11|PROMO BRUSHED TIN|16|MED PKG|1289.38|cial pinto beans amo +390|maroon magenta saddle linen lime|Manufacturer#5|Brand#54|SMALL ANODIZED COPPER|24|MED DRUM|1290.39|unts integrate +391|seashell cornsilk metallic royal sky|Manufacturer#4|Brand#41|SMALL PLATED STEEL|18|LG PACK|1291.39|ickly ironic f +392|medium plum powder blush yellow|Manufacturer#4|Brand#42|MEDIUM BRUSHED COPPER|21|SM BOX|1292.39|even request +393|blue coral gainsboro slate lawn|Manufacturer#3|Brand#34|STANDARD PLATED NICKEL|36|JUMBO CAN|1293.39|gular pi +394|chocolate royal cornflower papaya yellow|Manufacturer#1|Brand#11|MEDIUM POLISHED STEEL|33|MED JAR|1294.39|ely even excuses. +395|drab steel royal medium chartreuse|Manufacturer#3|Brand#32|MEDIUM BURNISHED BRASS|9|LG BOX|1295.39|sits haggle fluffily +396|medium seashell lavender almond tan|Manufacturer#3|Brand#35|SMALL BURNISHED COPPER|37|SM CASE|1296.39|ctions. silent packag +397|purple spring turquoise goldenrod grey|Manufacturer#1|Brand#15|LARGE ANODIZED COPPER|3|JUMBO JAR|1297.39|ly ironic pains. f +398|red salmon sandy white hot|Manufacturer#3|Brand#32|MEDIUM BRUSHED NICKEL|32|SM DRUM|1298.39|ickly sp +399|orange peru yellow blanched seashell|Manufacturer#2|Brand#21|LARGE BRUSHED BRASS|37|WRAP BAG|1299.39|nts sleep dog +400|rose blue smoke olive sandy|Manufacturer#2|Brand#21|ECONOMY POLISHED BRASS|32|SM BOX|1300.40| nag. quick +401|almond chiffon indian green dim|Manufacturer#2|Brand#21|ECONOMY POLISHED STEEL|10|SM PKG|1301.40|ideas cajole +402|black rosy ghost yellow ivory|Manufacturer#4|Brand#45|LARGE ANODIZED BRASS|16|SM PACK|1302.40|s above t +403|indian lemon linen almond tomato|Manufacturer#4|Brand#45|MEDIUM BURNISHED STEEL|19|JUMBO DRUM|1303.40|ic requ +404|maroon olive pink rose cornflower|Manufacturer#4|Brand#41|STANDARD ANODIZED NICKEL|9|SM CASE|1304.40|ckages integrate blit +405|ivory yellow peru almond cornsilk|Manufacturer#3|Brand#34|STANDARD BRUSHED BRASS|17|WRAP JAR|1305.40|e to maintain careful +406|thistle saddle white puff lemon|Manufacturer#2|Brand#21|STANDARD PLATED STEEL|43|JUMBO JAR|1306.40|ake foxes- +407|tomato turquoise dim powder ivory|Manufacturer#5|Brand#53|LARGE BRUSHED NICKEL|39|SM JAR|1307.40|quickl +408|indian metallic peach gainsboro pale|Manufacturer#2|Brand#24|PROMO POLISHED STEEL|4|MED PKG|1308.40|refully b +409|smoke forest metallic saddle hot|Manufacturer#4|Brand#44|SMALL PLATED NICKEL|40|MED CASE|1309.40|usly above +410|tomato sienna hot chartreuse dodger|Manufacturer#2|Brand#25|STANDARD PLATED NICKEL|36|JUMBO BOX|1310.41| ironic pa +411|lemon dark khaki antique slate|Manufacturer#1|Brand#12|ECONOMY BURNISHED STEEL|17|JUMBO DRUM|1311.41|o beans a +412|slate forest spring pink peru|Manufacturer#1|Brand#14|SMALL ANODIZED STEEL|33|WRAP PKG|1312.41|ccording to the fur +413|chiffon ivory lawn metallic beige|Manufacturer#3|Brand#33|PROMO PLATED STEEL|49|MED PKG|1313.41|r deposits wake. alw +414|pink brown purple puff snow|Manufacturer#4|Brand#41|SMALL BURNISHED STEEL|50|WRAP CASE|1314.41|efully. dolph +415|dark chocolate wheat ivory orchid|Manufacturer#2|Brand#22|MEDIUM ANODIZED COPPER|42|SM DRUM|1315.41|blithely blit +416|ghost misty chocolate peach green|Manufacturer#1|Brand#13|MEDIUM POLISHED STEEL|11|WRAP JAR|1316.41|yly pending deposit +417|gainsboro sky turquoise ghost mint|Manufacturer#1|Brand#14|MEDIUM PLATED TIN|31|LG BAG|1317.41| nag blithely: ex +418|lavender forest puff beige tan|Manufacturer#1|Brand#11|MEDIUM ANODIZED NICKEL|32|JUMBO JAR|1318.41| ironic deposits. requ +419|moccasin navy seashell turquoise sienna|Manufacturer#4|Brand#43|ECONOMY BRUSHED TIN|42|WRAP BAG|1319.41|boost slyly among t +420|chocolate cornsilk midnight beige floral|Manufacturer#2|Brand#23|PROMO BRUSHED TIN|15|LG JAR|1320.42|y. fluffi +421|white black burnished brown medium|Manufacturer#1|Brand#12|LARGE PLATED STEEL|36|WRAP PACK|1321.42|regular +422|honeydew smoke violet pink bisque|Manufacturer#3|Brand#33|STANDARD POLISHED TIN|16|LG CAN|1322.42| bold +423|bisque misty dark hot blush|Manufacturer#3|Brand#31|PROMO BRUSHED BRASS|2|SM JAR|1323.42|accou +424|dim almond turquoise beige royal|Manufacturer#3|Brand#34|SMALL BRUSHED TIN|9|LG CASE|1324.42|usly slyl +425|ivory wheat chiffon navy burlywood|Manufacturer#3|Brand#32|PROMO BRUSHED STEEL|23|JUMBO BOX|1325.42|ndenci +426|maroon linen sienna firebrick burnished|Manufacturer#1|Brand#14|STANDARD ANODIZED NICKEL|42|WRAP PACK|1326.42|furiously even pa +427|honeydew azure brown royal sky|Manufacturer#2|Brand#22|PROMO BURNISHED NICKEL|47|JUMBO CAN|1327.42|ts. express, unusual +428|beige spring floral wheat drab|Manufacturer#5|Brand#54|LARGE BURNISHED TIN|14|JUMBO CASE|1328.42|furiously ir +429|red firebrick smoke magenta moccasin|Manufacturer#4|Brand#45|ECONOMY BRUSHED COPPER|21|MED DRUM|1329.42| carefully even +430|snow mint deep brown goldenrod|Manufacturer#3|Brand#34|PROMO BURNISHED NICKEL|34|MED CAN|1330.43| sleep. slyly pend +431|grey smoke navy peach white|Manufacturer#4|Brand#45|MEDIUM POLISHED TIN|30|SM PACK|1331.43|iousl +432|white cornflower honeydew red ivory|Manufacturer#2|Brand#21|MEDIUM PLATED BRASS|6|MED JAR|1332.43|s nag furiously fluff +433|olive moccasin almond tomato plum|Manufacturer#1|Brand#12|STANDARD BURNISHED TIN|2|SM PACK|1333.43|ts haggle furiously +434|turquoise coral violet dim midnight|Manufacturer#5|Brand#51|ECONOMY BURNISHED COPPER|20|JUMBO BAG|1334.43|y against the c +435|coral misty brown grey hot|Manufacturer#3|Brand#35|ECONOMY ANODIZED BRASS|17|WRAP BAG|1335.43|carefully ironic pack +436|turquoise yellow dim purple antique|Manufacturer#1|Brand#14|LARGE POLISHED BRASS|50|WRAP CASE|1336.43| the regul +437|purple slate gainsboro powder magenta|Manufacturer#5|Brand#54|ECONOMY PLATED TIN|17|WRAP PACK|1337.43|e furiously +438|antique orchid cornflower puff almond|Manufacturer#1|Brand#15|LARGE BURNISHED TIN|31|LG DRUM|1338.43|epitaphs wake +439|bisque cyan rosy ivory blanched|Manufacturer#2|Brand#21|MEDIUM BURNISHED TIN|32|SM PKG|1339.43|uests wake slyly over +440|khaki turquoise violet maroon misty|Manufacturer#3|Brand#34|ECONOMY BURNISHED BRASS|22|MED CASE|1340.44|furiously above the +441|goldenrod royal slate grey burlywood|Manufacturer#3|Brand#35|PROMO BURNISHED STEEL|24|MED BOX|1341.44|s wake atop the ru +442|honeydew cornsilk powder salmon purple|Manufacturer#4|Brand#41|LARGE BURNISHED TIN|22|MED PACK|1342.44|refully al +443|chocolate burnished orchid mint royal|Manufacturer#4|Brand#44|STANDARD BURNISHED BRASS|10|SM BOX|1343.44|arefully. sl +444|ghost blanched forest khaki rose|Manufacturer#3|Brand#32|MEDIUM ANODIZED COPPER|42|LG JAR|1344.44|ickly special excuse +445|metallic ivory floral cornsilk burnished|Manufacturer#1|Brand#12|LARGE BURNISHED NICKEL|47|SM DRUM|1345.44|s about the re +446|sandy brown midnight tan bisque|Manufacturer#1|Brand#12|STANDARD BURNISHED NICKEL|11|WRAP CASE|1346.44|s sentiments affix +447|forest smoke aquamarine cyan dim|Manufacturer#5|Brand#53|STANDARD BURNISHED COPPER|22|LG JAR|1347.44|s theodolites above th +448|wheat tomato cyan lemon maroon|Manufacturer#1|Brand#13|PROMO POLISHED BRASS|31|LG CAN|1348.44| excuses affix silen +449|almond thistle cornsilk bisque blush|Manufacturer#2|Brand#25|MEDIUM BRUSHED BRASS|47|JUMBO BAG|1349.44|ular, unusual p +450|sky lace green pale lime|Manufacturer#4|Brand#43|MEDIUM BURNISHED TIN|23|SM CASE|1350.45|slyly +451|rosy ghost sky mint smoke|Manufacturer#4|Brand#42|PROMO PLATED TIN|28|WRAP DRUM|1351.45| detect blithely bl +452|saddle sandy cream sienna blue|Manufacturer#1|Brand#11|STANDARD ANODIZED STEEL|48|JUMBO BOX|1352.45|ic requests wake +453|lemon navy seashell khaki sienna|Manufacturer#3|Brand#34|ECONOMY ANODIZED TIN|20|LG CASE|1353.45|y above the pen +454|royal lime saddle magenta violet|Manufacturer#5|Brand#53|MEDIUM BURNISHED STEEL|32|LG BOX|1354.45|ual requests. +455|aquamarine blanched misty moccasin sky|Manufacturer#2|Brand#22|LARGE BRUSHED BRASS|18|MED JAR|1355.45|ongside of the careful +456|antique maroon olive turquoise lace|Manufacturer#5|Brand#53|PROMO POLISHED BRASS|40|SM PKG|1356.45|usual, +457|navy linen forest moccasin slate|Manufacturer#5|Brand#52|SMALL POLISHED TIN|46|SM CAN|1357.45|express accounts. sp +458|beige papaya grey ivory white|Manufacturer#2|Brand#22|PROMO BRUSHED COPPER|38|MED BAG|1358.45|structions sleep +459|beige slate magenta dim salmon|Manufacturer#2|Brand#23|MEDIUM ANODIZED NICKEL|27|SM PACK|1359.45| blithely. fur +460|maroon papaya orange spring light|Manufacturer#3|Brand#35|STANDARD ANODIZED BRASS|47|JUMBO DRUM|1360.46|he carefully +461|goldenrod dim wheat tan violet|Manufacturer#5|Brand#54|SMALL BRUSHED TIN|44|JUMBO CASE|1361.46|: slyly express pa +462|lime yellow sandy floral khaki|Manufacturer#5|Brand#54|MEDIUM BURNISHED BRASS|11|WRAP CAN|1362.46|s sleep quickly care +463|steel cream grey mint dark|Manufacturer#2|Brand#21|MEDIUM ANODIZED COPPER|48|MED PACK|1363.46|unts use fluffily +464|azure magenta lace smoke ghost|Manufacturer#4|Brand#42|LARGE BURNISHED NICKEL|34|LG BOX|1364.46|l decoys. close exc +465|smoke sky bisque ghost black|Manufacturer#4|Brand#42|SMALL POLISHED BRASS|12|MED JAR|1365.46|nts. slyly special ac +466|deep ghost cornflower ivory burnished|Manufacturer#3|Brand#33|PROMO POLISHED BRASS|12|LG PKG|1366.46|ly special pains. iron +467|cornflower lime midnight plum forest|Manufacturer#2|Brand#24|STANDARD BURNISHED STEEL|48|JUMBO PACK|1367.46|ependenc +468|spring grey azure khaki lace|Manufacturer#4|Brand#41|MEDIUM BURNISHED STEEL|24|SM PACK|1368.46|o the +469|burlywood dark steel sky blue|Manufacturer#1|Brand#13|MEDIUM POLISHED STEEL|43|WRAP PKG|1369.46|osits. slyly unusua +470|honeydew lime khaki saddle indian|Manufacturer#2|Brand#24|STANDARD BRUSHED TIN|38|JUMBO CASE|1370.47|ess deposits +471|goldenrod honeydew frosted almond chiffon|Manufacturer#1|Brand#11|LARGE BRUSHED STEEL|21|JUMBO BAG|1371.47|sits nag caref +472|dim misty lime purple cornsilk|Manufacturer#3|Brand#31|PROMO BRUSHED COPPER|24|SM JAR|1372.47| according +473|moccasin antique lace peach chiffon|Manufacturer#1|Brand#12|ECONOMY PLATED STEEL|2|MED DRUM|1373.47|e furious +474|papaya green royal burlywood saddle|Manufacturer#1|Brand#14|ECONOMY PLATED STEEL|45|LG PACK|1374.47|ously even reques +475|coral peru forest thistle khaki|Manufacturer#3|Brand#34|STANDARD ANODIZED NICKEL|30|MED PACK|1375.47|thely unusual th +476|cornflower deep turquoise slate sandy|Manufacturer#3|Brand#33|STANDARD POLISHED COPPER|33|WRAP PACK|1376.47| according to the blit +477|plum peru spring firebrick lavender|Manufacturer#1|Brand#11|ECONOMY ANODIZED COPPER|35|JUMBO BAG|1377.47|lent s +478|lemon snow coral lime seashell|Manufacturer#4|Brand#45|STANDARD POLISHED COPPER|11|MED CASE|1378.47|ly bold foxes ca +479|snow frosted slate magenta sky|Manufacturer#2|Brand#25|MEDIUM PLATED STEEL|35|SM BAG|1379.47| pending ac +480|saddle light black drab navajo|Manufacturer#5|Brand#54|MEDIUM ANODIZED STEEL|31|WRAP BOX|1380.48|eans. quickly +481|slate red firebrick beige aquamarine|Manufacturer#1|Brand#14|MEDIUM BURNISHED BRASS|17|JUMBO PACK|1381.48|s cajole som +482|burnished spring azure green chocolate|Manufacturer#5|Brand#53|MEDIUM POLISHED STEEL|11|SM DRUM|1382.48|deposits. fluffily b +483|deep white khaki floral cornflower|Manufacturer#1|Brand#15|MEDIUM ANODIZED COPPER|9|SM PKG|1383.48|usly final instru +484|bisque rosy olive peach chiffon|Manufacturer#1|Brand#15|MEDIUM POLISHED BRASS|34|SM CASE|1384.48|uffily final deposits. +485|orchid dark antique deep ivory|Manufacturer#3|Brand#31|PROMO PLATED STEEL|44|LG JAR|1385.48| requests. regularly r +486|tomato lime moccasin turquoise grey|Manufacturer#4|Brand#45|SMALL PLATED COPPER|15|MED PKG|1386.48|ent accounts among t +487|firebrick saddle chocolate peru ghost|Manufacturer#5|Brand#52|SMALL BRUSHED COPPER|43|WRAP PACK|1387.48|iously ruthles +488|forest puff drab beige blue|Manufacturer#2|Brand#21|PROMO PLATED BRASS|47|JUMBO JAR|1388.48| the slyly pending r +489|smoke green blush deep royal|Manufacturer#2|Brand#22|LARGE BURNISHED TIN|36|LG CAN|1389.48|unts. quickly bold id +490|yellow mint saddle dodger orchid|Manufacturer#4|Brand#41|SMALL PLATED NICKEL|11|MED BOX|1390.49|fluffily express packa +491|snow mint rose almond frosted|Manufacturer#3|Brand#31|SMALL POLISHED BRASS|42|MED JAR|1391.49| deposit +492|turquoise rose navajo deep chiffon|Manufacturer#4|Brand#42|MEDIUM BRUSHED COPPER|13|JUMBO DRUM|1392.49|yly slyly express th +493|blue gainsboro sky burnished puff|Manufacturer#4|Brand#45|MEDIUM BURNISHED BRASS|8|MED PKG|1393.49|uses. bold +494|navy pale frosted lawn spring|Manufacturer#4|Brand#42|STANDARD BRUSHED NICKEL|40|MED PKG|1394.49|y pending theodo +495|lemon burlywood chartreuse forest honeydew|Manufacturer#4|Brand#42|SMALL BRUSHED BRASS|28|MED PKG|1395.49|, ironic pac +496|orchid bisque antique ivory lavender|Manufacturer#1|Brand#12|STANDARD BRUSHED BRASS|11|SM BAG|1396.49|ealthily +497|hot powder dim cream metallic|Manufacturer#2|Brand#25|PROMO PLATED TIN|1|SM CAN|1397.49|l accounts sl +498|sandy sky gainsboro peach cornflower|Manufacturer#2|Brand#25|MEDIUM POLISHED STEEL|21|WRAP CASE|1398.49|lthily even co +499|lemon pale blue burnished white|Manufacturer#3|Brand#35|SMALL PLATED COPPER|38|JUMBO PKG|1399.49|furiously across +500|hot medium spring orange violet|Manufacturer#4|Brand#41|MEDIUM POLISHED STEEL|13|SM JAR|1400.50|regul +501|tomato navy midnight cyan chiffon|Manufacturer#4|Brand#45|SMALL BURNISHED COPPER|37|SM BAG|1401.50|press pinto b +502|maroon dark plum brown red|Manufacturer#2|Brand#21|SMALL PLATED TIN|6|JUMBO DRUM|1402.50|quests integrate +503|lavender cyan red lace light|Manufacturer#2|Brand#24|PROMO BRUSHED NICKEL|30|SM PKG|1403.50| the dep +504|pink tan papaya ivory lace|Manufacturer#2|Brand#24|PROMO BRUSHED STEEL|10|SM JAR|1404.50|refully after the fu +505|pink cornsilk antique mint forest|Manufacturer#4|Brand#42|STANDARD PLATED BRASS|32|WRAP JAR|1405.50|ly even +506|beige floral goldenrod lace almond|Manufacturer#1|Brand#14|PROMO BRUSHED NICKEL|30|WRAP PACK|1406.50|y ruthless, fi +507|red misty salmon ivory khaki|Manufacturer#4|Brand#43|SMALL ANODIZED BRASS|20|SM CASE|1407.50|ial foxes. furiously +508|pale peach maroon burlywood tan|Manufacturer#1|Brand#14|LARGE ANODIZED TIN|40|WRAP PKG|1408.50|ect according +509|tomato cornsilk chartreuse blue magenta|Manufacturer#1|Brand#13|MEDIUM BRUSHED NICKEL|30|MED CAN|1409.50|eposits. slyly +510|blush thistle orchid red lace|Manufacturer#4|Brand#43|SMALL PLATED NICKEL|25|JUMBO PACK|1410.51|al platelets. iro +511|red pale plum orchid moccasin|Manufacturer#1|Brand#15|STANDARD BRUSHED COPPER|2|LG JAR|1411.51|ss package +512|firebrick azure mint chocolate wheat|Manufacturer#5|Brand#51|PROMO ANODIZED COPPER|18|LG PACK|1412.51|dolphins cajo +513|mint thistle chiffon magenta salmon|Manufacturer#3|Brand#32|MEDIUM BRUSHED STEEL|10|WRAP CAN|1413.51| after th +514|rosy sienna purple light rose|Manufacturer#4|Brand#42|LARGE POLISHED BRASS|10|JUMBO BOX|1414.51|omise +515|cream navajo drab dark peru|Manufacturer#5|Brand#53|MEDIUM PLATED TIN|37|WRAP BOX|1415.51|ular asymptotes im +516|purple linen lace blanched snow|Manufacturer#1|Brand#12|SMALL BRUSHED NICKEL|28|LG CAN|1416.51|ly express +517|aquamarine rosy violet moccasin snow|Manufacturer#3|Brand#34|SMALL BURNISHED COPPER|30|WRAP CAN|1417.51|uses. +518|yellow tomato lawn rosy lemon|Manufacturer#4|Brand#43|PROMO BRUSHED BRASS|33|JUMBO DRUM|1418.51|n requests hag +519|violet medium dark red smoke|Manufacturer#3|Brand#32|LARGE BRUSHED BRASS|24|WRAP PACK|1419.51|xes are fluffily fluf +520|spring honeydew sky sandy almond|Manufacturer#1|Brand#12|PROMO BURNISHED BRASS|49|MED CASE|1420.52| foxes. +521|grey drab honeydew coral pale|Manufacturer#3|Brand#35|PROMO BRUSHED STEEL|21|JUMBO DRUM|1421.52|the blithe +522|frosted lawn violet turquoise coral|Manufacturer#3|Brand#32|STANDARD BRUSHED NICKEL|15|MED CASE|1422.52|deas. brave ac +523|light goldenrod honeydew indian lemon|Manufacturer#4|Brand#42|ECONOMY BRUSHED NICKEL|7|JUMBO JAR|1423.52|e blithe +524|burnished hot drab midnight tan|Manufacturer#1|Brand#14|SMALL ANODIZED STEEL|17|JUMBO PACK|1424.52|ly reg +525|plum midnight coral snow lemon|Manufacturer#3|Brand#33|STANDARD BURNISHED STEEL|47|JUMBO CAN|1425.52|ly except +526|dodger moccasin wheat puff lace|Manufacturer#5|Brand#53|PROMO ANODIZED BRASS|47|JUMBO PKG|1426.52|ronic, iro +527|moccasin light purple sky magenta|Manufacturer#3|Brand#32|MEDIUM POLISHED NICKEL|39|LG JAR|1427.52|counts wake abov +528|dim deep puff pink floral|Manufacturer#2|Brand#24|STANDARD PLATED STEEL|40|LG CAN|1428.52|ly ironic pl +529|powder tan brown royal blush|Manufacturer#3|Brand#31|MEDIUM PLATED NICKEL|33|SM PKG|1429.52|y along the +530|mint grey chiffon magenta saddle|Manufacturer#4|Brand#42|PROMO PLATED STEEL|45|JUMBO CASE|1430.53|kages about t +531|navajo hot forest puff olive|Manufacturer#2|Brand#22|ECONOMY POLISHED NICKEL|16|WRAP DRUM|1431.53| atta +532|spring wheat purple chiffon puff|Manufacturer#1|Brand#14|LARGE BRUSHED NICKEL|45|WRAP BAG|1432.53|s. blithely +533|cream lemon goldenrod rosy aquamarine|Manufacturer#2|Brand#24|PROMO PLATED STEEL|38|JUMBO PACK|1433.53|ng the blithely final +534|bisque saddle hot steel frosted|Manufacturer#5|Brand#53|STANDARD PLATED NICKEL|27|LG CASE|1434.53|rts poach over th +535|mint chocolate tomato peach sky|Manufacturer#5|Brand#53|STANDARD PLATED TIN|17|SM CASE|1435.53|he unusual idea +536|orchid snow thistle peru moccasin|Manufacturer#2|Brand#23|STANDARD PLATED STEEL|36|JUMBO BAG|1436.53|le slyl +537|hot orange red cornsilk goldenrod|Manufacturer#1|Brand#15|ECONOMY BRUSHED TIN|26|WRAP BOX|1437.53|fully regular platelet +538|rose black peach orchid cyan|Manufacturer#1|Brand#15|ECONOMY POLISHED STEEL|24|SM PACK|1438.53|ic epitap +539|dodger midnight salmon drab saddle|Manufacturer#3|Brand#34|MEDIUM BURNISHED TIN|4|SM DRUM|1439.53| deposits. fi +540|violet white steel chocolate burlywood|Manufacturer#1|Brand#14|MEDIUM PLATED NICKEL|7|LG PACK|1440.54|cial, pending account +541|magenta tan antique sky pale|Manufacturer#3|Brand#35|STANDARD ANODIZED NICKEL|34|LG JAR|1441.54|s are fluffily above t +542|light lace gainsboro coral lavender|Manufacturer#1|Brand#11|SMALL BRUSHED STEEL|40|WRAP CASE|1442.54|sits bo +543|sky powder saddle metallic moccasin|Manufacturer#5|Brand#54|ECONOMY POLISHED BRASS|4|JUMBO BOX|1443.54| cajole +544|peach red azure indian lavender|Manufacturer#2|Brand#22|STANDARD BURNISHED NICKEL|42|SM CASE|1444.54|leep slyl +545|purple peru ivory gainsboro peach|Manufacturer#3|Brand#31|LARGE PLATED NICKEL|14|MED JAR|1445.54|arefully regular packa +546|metallic grey black rosy papaya|Manufacturer#2|Brand#25|ECONOMY ANODIZED STEEL|8|LG CASE|1446.54|ly unusu +547|white turquoise olive cornflower pale|Manufacturer#4|Brand#43|MEDIUM BURNISHED COPPER|48|WRAP DRUM|1447.54|ial theodolites among +548|cyan lime lawn misty mint|Manufacturer#3|Brand#33|ECONOMY ANODIZED TIN|28|SM CAN|1448.54|gular +549|thistle green indian sandy purple|Manufacturer#5|Brand#53|SMALL BRUSHED BRASS|36|SM CAN|1449.54|ly unus +550|brown blush dark white mint|Manufacturer#4|Brand#44|STANDARD BRUSHED STEEL|27|SM JAR|1450.55|arefully iron +551|tan misty floral firebrick puff|Manufacturer#5|Brand#54|LARGE BURNISHED TIN|10|MED JAR|1451.55|dolites cajole furious +552|lime violet puff snow chiffon|Manufacturer#4|Brand#44|LARGE POLISHED BRASS|1|JUMBO CAN|1452.55|longside of the sl +553|gainsboro tomato lawn peru bisque|Manufacturer#2|Brand#23|SMALL POLISHED NICKEL|1|WRAP DRUM|1453.55|fily regular depen +554|blue medium royal blush ghost|Manufacturer#5|Brand#53|STANDARD BRUSHED STEEL|31|LG JAR|1454.55|ts? ironically +555|midnight honeydew brown beige slate|Manufacturer#4|Brand#42|PROMO BURNISHED TIN|49|SM JAR|1455.55|es hag +556|frosted antique aquamarine seashell powder|Manufacturer#2|Brand#23|SMALL BRUSHED BRASS|49|WRAP JAR|1456.55|ar theodolites ma +557|firebrick ghost steel green chartreuse|Manufacturer#3|Brand#35|LARGE BURNISHED TIN|8|JUMBO PKG|1457.55|ccounts im +558|blanched seashell navy black dim|Manufacturer#3|Brand#31|STANDARD PLATED BRASS|25|MED BOX|1458.55|eposits. slyly +559|wheat coral navajo cornflower dark|Manufacturer#3|Brand#31|LARGE PLATED STEEL|27|SM PKG|1459.55|stealthily express +560|tan indian lime olive dodger|Manufacturer#2|Brand#25|STANDARD BRUSHED COPPER|37|WRAP PKG|1460.56|e special pac +561|firebrick slate grey coral goldenrod|Manufacturer#1|Brand#14|SMALL POLISHED STEEL|44|JUMBO CASE|1461.56|-- ironic, iron +562|tan blue thistle forest cornsilk|Manufacturer#3|Brand#32|SMALL BURNISHED STEEL|16|MED PACK|1462.56| fluffi +563|blanched light indian goldenrod dim|Manufacturer#3|Brand#31|MEDIUM POLISHED STEEL|39|MED DRUM|1463.56|furiously bold, +564|drab bisque puff ghost floral|Manufacturer#2|Brand#22|LARGE ANODIZED BRASS|41|SM PKG|1464.56|blithely after the ev +565|coral mint sky rosy red|Manufacturer#1|Brand#14|PROMO BRUSHED STEEL|9|JUMBO JAR|1465.56| blithely unusual r +566|seashell dark yellow turquoise white|Manufacturer#2|Brand#25|ECONOMY BURNISHED TIN|19|LG PKG|1466.56|ounts wake across t +567|cornsilk lace white medium honeydew|Manufacturer#5|Brand#55|STANDARD BRUSHED STEEL|19|JUMBO BAG|1467.56|pending pinto +568|purple burlywood pale cornsilk chartreuse|Manufacturer#3|Brand#31|PROMO POLISHED STEEL|6|SM BOX|1468.56|ts. ideas along t +569|cornflower burlywood blue spring purple|Manufacturer#4|Brand#41|SMALL BRUSHED TIN|46|MED BOX|1469.56|y according to +570|cyan navajo turquoise forest firebrick|Manufacturer#5|Brand#51|ECONOMY BRUSHED COPPER|44|SM PKG|1470.57|le. s +571|medium orchid purple metallic ghost|Manufacturer#2|Brand#22|LARGE PLATED TIN|1|WRAP CAN|1471.57|ly ironic +572|navy plum lime goldenrod saddle|Manufacturer#4|Brand#43|LARGE BURNISHED COPPER|3|SM BOX|1472.57|requests use +573|dark midnight forest lace sandy|Manufacturer#2|Brand#23|SMALL PLATED TIN|42|WRAP PACK|1473.57|expres +574|bisque snow turquoise lace blush|Manufacturer#2|Brand#23|SMALL PLATED BRASS|36|SM PACK|1474.57|oss th +575|brown seashell hot lavender frosted|Manufacturer#1|Brand#14|SMALL BRUSHED NICKEL|10|MED CAN|1475.57|ns integrate a +576|puff lavender black yellow lawn|Manufacturer#3|Brand#32|PROMO BURNISHED TIN|27|SM CAN|1476.57| foxes. accounts bo +577|lime green dark misty chiffon|Manufacturer#2|Brand#22|LARGE BRUSHED STEEL|34|JUMBO BAG|1477.57|ding, fur +578|black lawn light plum blush|Manufacturer#4|Brand#41|MEDIUM ANODIZED NICKEL|9|WRAP DRUM|1478.57| furiously iron +579|spring brown peach bisque sienna|Manufacturer#3|Brand#31|STANDARD POLISHED STEEL|8|WRAP JAR|1479.57|ades. carefully +580|navajo chocolate lemon hot green|Manufacturer#1|Brand#12|LARGE BURNISHED COPPER|30|JUMBO PACK|1480.58|usly expre +581|frosted gainsboro chiffon lawn green|Manufacturer#2|Brand#25|ECONOMY ANODIZED BRASS|44|SM BAG|1481.58| furious foxes. silen +582|tan cyan peach rose salmon|Manufacturer#4|Brand#45|LARGE BRUSHED TIN|23|MED JAR|1482.58|y bold +583|turquoise burnished orchid firebrick blush|Manufacturer#3|Brand#33|LARGE BURNISHED NICKEL|35|JUMBO CAN|1483.58| sleep +584|goldenrod magenta papaya medium chiffon|Manufacturer#1|Brand#12|SMALL POLISHED COPPER|42|MED JAR|1484.58|lar, ironic ac +585|slate hot honeydew midnight burnished|Manufacturer#5|Brand#53|SMALL PLATED COPPER|7|JUMBO PKG|1485.58|sts haggle q +586|ivory rosy royal powder firebrick|Manufacturer#1|Brand#11|PROMO ANODIZED BRASS|11|LG DRUM|1486.58|ts haggle fluffily +587|blanched maroon blush burlywood salmon|Manufacturer#4|Brand#44|SMALL POLISHED STEEL|35|MED PKG|1487.58|c accounts. qui +588|cyan powder brown sandy burlywood|Manufacturer#5|Brand#55|SMALL PLATED COPPER|45|WRAP BAG|1488.58|ss foxes. even, ex +589|red orange salmon rosy thistle|Manufacturer#1|Brand#13|LARGE POLISHED BRASS|3|SM PKG|1489.58|cies. regul +590|azure burnished honeydew navy cyan|Manufacturer#4|Brand#42|LARGE POLISHED COPPER|38|WRAP PKG|1490.59| dependencies sho +591|sienna burlywood salmon navy green|Manufacturer#1|Brand#14|ECONOMY PLATED NICKEL|40|SM PKG|1491.59| the b +592|dodger burnished yellow wheat antique|Manufacturer#2|Brand#23|LARGE POLISHED STEEL|7|MED DRUM|1492.59|ide of the notorni +593|metallic sienna sandy spring frosted|Manufacturer#2|Brand#25|PROMO POLISHED STEEL|20|JUMBO CASE|1493.59|ake after +594|seashell magenta rosy cornsilk smoke|Manufacturer#3|Brand#31|PROMO BRUSHED BRASS|28|SM JAR|1494.59|s detect fu +595|chiffon lace linen steel bisque|Manufacturer#5|Brand#51|PROMO BRUSHED BRASS|23|JUMBO JAR|1495.59|yly fin +596|drab snow chartreuse dim ivory|Manufacturer#5|Brand#52|STANDARD POLISHED TIN|35|JUMBO JAR|1496.59|epend +597|cyan orchid grey tan bisque|Manufacturer#4|Brand#44|STANDARD ANODIZED NICKEL|36|SM DRUM|1497.59|ronic foxes. speci +598|deep royal drab violet chartreuse|Manufacturer#2|Brand#24|MEDIUM POLISHED BRASS|9|MED JAR|1498.59|he fluffily regular +599|cornsilk peru steel beige blue|Manufacturer#5|Brand#51|MEDIUM BRUSHED NICKEL|30|JUMBO PACK|1499.59|ckages against t +600|puff bisque midnight seashell burlywood|Manufacturer#4|Brand#42|STANDARD POLISHED NICKEL|4|SM JAR|1500.60|ow furiously agai +601|coral thistle blanched linen tan|Manufacturer#1|Brand#13|STANDARD POLISHED BRASS|13|SM PKG|1501.60|lithely thi +602|metallic smoke purple rosy magenta|Manufacturer#1|Brand#12|PROMO BRUSHED COPPER|8|SM BAG|1502.60|telets a +603|dim blush puff chiffon salmon|Manufacturer#1|Brand#12|PROMO ANODIZED COPPER|41|WRAP PKG|1503.60|uests. fluffily regul +604|bisque light frosted white olive|Manufacturer#4|Brand#41|MEDIUM PLATED STEEL|19|MED PACK|1504.60|are after the regula +605|grey burlywood linen tan tomato|Manufacturer#1|Brand#11|LARGE POLISHED STEEL|30|LG JAR|1505.60| bold, final accou +606|navajo lace sandy aquamarine light|Manufacturer#3|Brand#32|STANDARD PLATED STEEL|36|LG DRUM|1506.60|hins p +607|dark sienna thistle sandy maroon|Manufacturer#5|Brand#54|MEDIUM POLISHED TIN|13|MED JAR|1507.60|ctions wake qu +608|mint medium blush black metallic|Manufacturer#2|Brand#25|PROMO PLATED BRASS|35|JUMBO PKG|1508.60|xes. express r +609|almond lemon olive smoke moccasin|Manufacturer#2|Brand#21|ECONOMY BRUSHED TIN|49|JUMBO DRUM|1509.60|cial deposits haggle +610|plum purple seashell white lemon|Manufacturer#1|Brand#11|ECONOMY BURNISHED TIN|38|JUMBO BOX|1510.61|slyly pending re +611|light burnished linen sienna dim|Manufacturer#4|Brand#42|MEDIUM PLATED TIN|45|SM DRUM|1511.61|iously even packages. +612|midnight azure moccasin rosy lawn|Manufacturer#4|Brand#42|PROMO PLATED STEEL|19|LG BOX|1512.61|se quickly; +613|cream coral sandy thistle spring|Manufacturer#3|Brand#34|LARGE BURNISHED COPPER|22|LG DRUM|1513.61| cajo +614|dodger beige maroon puff medium|Manufacturer#2|Brand#23|STANDARD BURNISHED NICKEL|6|WRAP PKG|1514.61|ending accounts ca +615|rosy seashell brown blush tan|Manufacturer#4|Brand#41|PROMO ANODIZED COPPER|4|WRAP PKG|1515.61| dogged +616|tan powder lavender dim goldenrod|Manufacturer#2|Brand#25|STANDARD BRUSHED STEEL|1|WRAP JAR|1516.61|w packages cajole b +617|peru grey snow papaya firebrick|Manufacturer#2|Brand#22|MEDIUM ANODIZED NICKEL|37|WRAP DRUM|1517.61|furious +618|ivory wheat smoke deep lemon|Manufacturer#2|Brand#22|PROMO BRUSHED BRASS|9|LG BOX|1518.61|ogs. furiously +619|powder medium drab lemon tomato|Manufacturer#3|Brand#34|LARGE ANODIZED STEEL|46|MED JAR|1519.61|cuses are +620|frosted tomato almond salmon powder|Manufacturer#3|Brand#35|MEDIUM BRUSHED COPPER|4|LG PKG|1520.62|efully carefully speci +621|almond azure drab ghost mint|Manufacturer#5|Brand#53|PROMO PLATED TIN|47|JUMBO DRUM|1521.62|ffily furiously fin +622|burlywood dark blue thistle navajo|Manufacturer#5|Brand#51|LARGE POLISHED STEEL|19|WRAP BAG|1522.62|sly deposits. f +623|chiffon bisque steel orange tomato|Manufacturer#3|Brand#32|ECONOMY POLISHED NICKEL|8|MED BOX|1523.62|ly ironic +624|burlywood ghost orchid misty coral|Manufacturer#1|Brand#12|LARGE BURNISHED NICKEL|29|SM BAG|1524.62|dencies. even d +625|beige indian lime sienna plum|Manufacturer#3|Brand#35|SMALL PLATED COPPER|38|LG JAR|1525.62|blithely slow multipl +626|cream ivory brown peach honeydew|Manufacturer#1|Brand#12|SMALL ANODIZED COPPER|23|SM JAR|1526.62|furiously-- +627|drab yellow spring turquoise rose|Manufacturer#4|Brand#44|PROMO ANODIZED NICKEL|13|SM BAG|1527.62|y ironic +628|black mint olive drab medium|Manufacturer#3|Brand#33|ECONOMY BRUSHED BRASS|40|LG BOX|1528.62|sits. +629|magenta lace red hot pale|Manufacturer#5|Brand#51|MEDIUM POLISHED COPPER|25|WRAP BOX|1529.62|fully even co +630|lawn lace burnished hot frosted|Manufacturer#2|Brand#25|MEDIUM PLATED NICKEL|20|LG DRUM|1530.63|g to th +631|moccasin lawn cornsilk chartreuse midnight|Manufacturer#2|Brand#22|STANDARD ANODIZED NICKEL|34|WRAP BAG|1531.63|ely silen +632|blush floral tan thistle chiffon|Manufacturer#3|Brand#34|PROMO PLATED NICKEL|2|MED PACK|1532.63|y ironic instru +633|navy burnished wheat slate deep|Manufacturer#3|Brand#33|ECONOMY POLISHED NICKEL|24|MED PKG|1533.63|bold brai +634|grey aquamarine deep violet blush|Manufacturer#3|Brand#35|SMALL ANODIZED NICKEL|34|MED DRUM|1534.63|ions. +635|ghost aquamarine gainsboro lemon peach|Manufacturer#5|Brand#51|PROMO POLISHED STEEL|49|WRAP JAR|1535.63|y ironic excuses. +636|burlywood deep antique snow wheat|Manufacturer#5|Brand#55|PROMO BRUSHED STEEL|36|SM PACK|1536.63|ithely +637|brown smoke sandy honeydew antique|Manufacturer#5|Brand#51|LARGE BURNISHED NICKEL|48|JUMBO CASE|1537.63|oxes after the blithel +638|lace royal pink cornsilk antique|Manufacturer#5|Brand#54|SMALL PLATED TIN|37|JUMBO PACK|1538.63| carefully. blithely +639|black plum tomato cornflower medium|Manufacturer#2|Brand#25|STANDARD POLISHED BRASS|33|SM BAG|1539.63|s cajole quickly. care +640|grey seashell bisque indian deep|Manufacturer#1|Brand#12|MEDIUM BRUSHED TIN|20|WRAP CASE|1540.64|ly regular acco +641|mint saddle yellow sienna frosted|Manufacturer#5|Brand#55|MEDIUM PLATED COPPER|18|SM JAR|1541.64| bold instr +642|moccasin ghost sandy goldenrod cornsilk|Manufacturer#4|Brand#43|ECONOMY BRUSHED BRASS|12|MED PACK|1542.64| bold packages bey +643|frosted chocolate dodger honeydew ghost|Manufacturer#3|Brand#32|MEDIUM POLISHED STEEL|8|MED DRUM|1543.64|refully fina +644|rosy bisque hot burnished dark|Manufacturer#5|Brand#52|LARGE PLATED STEEL|34|SM PACK|1544.64|lphins. blithely +645|thistle sky antique khaki chartreuse|Manufacturer#4|Brand#45|MEDIUM BURNISHED NICKEL|45|LG CASE|1545.64| the theodol +646|tan honeydew lime light white|Manufacturer#5|Brand#52|SMALL POLISHED COPPER|21|LG PACK|1546.64|ajole according to t +647|rose khaki drab smoke peach|Manufacturer#3|Brand#35|LARGE BURNISHED STEEL|38|MED PKG|1547.64|ters. ironic pinto +648|bisque blue drab cyan almond|Manufacturer#3|Brand#34|SMALL BRUSHED STEEL|2|WRAP JAR|1548.64|eas. regular +649|lavender blush rosy beige sky|Manufacturer#1|Brand#12|STANDARD BURNISHED TIN|33|JUMBO DRUM|1549.64|fully! +650|bisque navajo mint medium seashell|Manufacturer#5|Brand#53|PROMO ANODIZED NICKEL|40|MED JAR|1550.65|ar dependen +651|bisque floral dim burlywood moccasin|Manufacturer#5|Brand#52|MEDIUM POLISHED BRASS|4|WRAP BAG|1551.65|efully final instruct +652|navajo white indian yellow grey|Manufacturer#1|Brand#12|LARGE BRUSHED TIN|39|WRAP PKG|1552.65|le furiously unusua +653|lime cornflower sky beige antique|Manufacturer#1|Brand#15|ECONOMY BURNISHED BRASS|28|JUMBO DRUM|1553.65|ias. i +654|cyan burnished tomato chiffon navy|Manufacturer#2|Brand#23|PROMO PLATED COPPER|2|WRAP BAG|1554.65|posits haggle +655|tomato firebrick yellow rosy orchid|Manufacturer#1|Brand#12|STANDARD BURNISHED TIN|23|JUMBO CAN|1555.65|ic instructions. +656|maroon dodger ghost gainsboro pink|Manufacturer#1|Brand#15|STANDARD BURNISHED COPPER|17|MED CASE|1556.65|tions wake ca +657|saddle lawn blue cyan cornsilk|Manufacturer#3|Brand#31|ECONOMY BURNISHED COPPER|36|LG PACK|1557.65| packages accord +658|ghost mint hot bisque salmon|Manufacturer#1|Brand#15|MEDIUM PLATED COPPER|27|SM JAR|1558.65| somas haggle quickly +659|black bisque plum pale cyan|Manufacturer#3|Brand#34|MEDIUM BRUSHED BRASS|20|LG JAR|1559.65|across the +660|sky dim thistle saddle pale|Manufacturer#5|Brand#51|STANDARD POLISHED TIN|8|SM CAN|1560.66|ages cajole fluffily +661|snow beige moccasin red lime|Manufacturer#3|Brand#32|PROMO PLATED STEEL|35|SM PKG|1561.66|ng asympt +662|ivory chocolate slate midnight ghost|Manufacturer#4|Brand#45|STANDARD PLATED STEEL|35|LG PACK|1562.66|e eve +663|ivory orchid azure frosted light|Manufacturer#4|Brand#41|PROMO POLISHED COPPER|6|WRAP PACK|1563.66| beans +664|frosted burnished tomato chiffon seashell|Manufacturer#4|Brand#43|MEDIUM BURNISHED TIN|26|LG BAG|1564.66|about the slyly s +665|rose antique cyan cornflower drab|Manufacturer#1|Brand#13|MEDIUM POLISHED STEEL|14|MED DRUM|1565.66|usly final excuse +666|ivory dim orchid antique spring|Manufacturer#1|Brand#13|ECONOMY BURNISHED NICKEL|20|MED PACK|1566.66|ronic theodolites ca +667|wheat ghost honeydew plum grey|Manufacturer#4|Brand#43|MEDIUM PLATED STEEL|42|MED JAR|1567.66|ly pending packages. +668|honeydew pink dodger cream dim|Manufacturer#2|Brand#22|SMALL ANODIZED NICKEL|10|LG PACK|1568.66|odolites. furio +669|khaki metallic plum smoke hot|Manufacturer#1|Brand#11|STANDARD BRUSHED TIN|37|MED BAG|1569.66|bold deposi +670|slate black smoke pale moccasin|Manufacturer#1|Brand#12|ECONOMY PLATED COPPER|24|LG DRUM|1570.67|es use fluffily unusu +671|powder metallic salmon slate chocolate|Manufacturer#5|Brand#53|SMALL PLATED STEEL|31|JUMBO BOX|1571.67|es. s +672|lawn rosy cornsilk floral misty|Manufacturer#2|Brand#23|PROMO BURNISHED STEEL|13|LG PACK|1572.67|, pen +673|navy azure sandy yellow sky|Manufacturer#2|Brand#23|MEDIUM ANODIZED COPPER|26|SM DRUM|1573.67|y final +674|tomato chartreuse cornflower green pale|Manufacturer#3|Brand#35|SMALL BRUSHED TIN|5|LG PKG|1574.67|unts use slyly bold +675|misty hot pale ghost yellow|Manufacturer#1|Brand#11|LARGE BRUSHED COPPER|2|SM CAN|1575.67|ely re +676|moccasin cornflower burlywood tomato light|Manufacturer#1|Brand#11|MEDIUM ANODIZED BRASS|45|SM CAN|1576.67|ges. enticingly ironi +677|pale steel blush mint cream|Manufacturer#4|Brand#44|PROMO ANODIZED BRASS|6|WRAP BAG|1577.67|accounts +678|salmon ivory red dodger spring|Manufacturer#4|Brand#44|PROMO BRUSHED TIN|15|SM BAG|1578.67|ronic pin +679|purple blanched linen metallic indian|Manufacturer#4|Brand#41|SMALL BURNISHED TIN|50|MED BOX|1579.67|iously ironic in +680|burnished ghost coral maroon yellow|Manufacturer#1|Brand#14|SMALL PLATED COPPER|44|LG PACK|1580.68|l depo +681|dark slate almond ghost chartreuse|Manufacturer#3|Brand#32|ECONOMY PLATED COPPER|9|WRAP CAN|1581.68|ic requests wake accor +682|lawn khaki green cornflower sienna|Manufacturer#5|Brand#53|LARGE POLISHED NICKEL|48|SM BOX|1582.68|ackages. +683|sienna cornsilk chiffon olive blush|Manufacturer#5|Brand#53|LARGE BURNISHED NICKEL|1|MED PACK|1583.68|its hag +684|metallic azure hot orange spring|Manufacturer#3|Brand#33|PROMO BURNISHED TIN|6|WRAP BOX|1584.68|unts are fluff +685|turquoise orchid plum green tomato|Manufacturer#3|Brand#31|SMALL PLATED COPPER|36|LG JAR|1585.68|s. furiously ruthless +686|goldenrod deep cornflower dodger rose|Manufacturer#5|Brand#54|STANDARD BRUSHED COPPER|15|WRAP BAG|1586.68|lly ironic accounts +687|frosted cornsilk tomato burnished smoke|Manufacturer#5|Brand#51|LARGE POLISHED NICKEL|47|JUMBO BOX|1587.68|packages. even, +688|navajo khaki almond royal chartreuse|Manufacturer#4|Brand#45|PROMO BRUSHED COPPER|38|JUMBO CAN|1588.68|rious ideas +689|bisque red peru almond grey|Manufacturer#4|Brand#43|LARGE PLATED COPPER|22|SM PACK|1589.68|ual package +690|cornflower dodger saddle ivory tan|Manufacturer#3|Brand#32|SMALL PLATED BRASS|31|WRAP PACK|1590.69|al, bold fra +691|burnished dim gainsboro thistle blue|Manufacturer#3|Brand#35|PROMO BURNISHED BRASS|3|SM JAR|1591.69|ully slyly unusu +692|puff beige smoke seashell sienna|Manufacturer#1|Brand#14|MEDIUM BRUSHED BRASS|20|SM DRUM|1592.69|tructions. ev +693|honeydew ghost azure yellow magenta|Manufacturer#5|Brand#54|SMALL PLATED TIN|14|WRAP CASE|1593.69|lets sle +694|pink maroon blanched beige cyan|Manufacturer#3|Brand#35|ECONOMY PLATED STEEL|35|JUMBO CASE|1594.69|es. final +695|deep peru lavender antique royal|Manufacturer#2|Brand#23|PROMO ANODIZED COPPER|19|MED DRUM|1595.69|eep blithely +696|forest lemon cream black pink|Manufacturer#3|Brand#33|MEDIUM ANODIZED BRASS|3|LG CAN|1596.69|al acco +697|dark white slate honeydew maroon|Manufacturer#4|Brand#41|LARGE PLATED TIN|8|MED CAN|1597.69| special pa +698|blush sienna honeydew yellow goldenrod|Manufacturer#4|Brand#42|ECONOMY ANODIZED COPPER|44|LG PACK|1598.69|ronic, ironic +699|plum orchid red linen misty|Manufacturer#1|Brand#11|MEDIUM PLATED STEEL|5|WRAP CAN|1599.69| regular notornis b +700|lace hot khaki steel orchid|Manufacturer#3|Brand#34|PROMO BRUSHED STEEL|31|SM JAR|1600.70|ly even foxes. fi +701|frosted lavender black deep ghost|Manufacturer#4|Brand#43|MEDIUM ANODIZED COPPER|36|WRAP DRUM|1601.70| use blithe +702|navajo lavender dim puff bisque|Manufacturer#4|Brand#41|STANDARD BURNISHED BRASS|26|SM CAN|1602.70|yly f +703|puff floral red linen dark|Manufacturer#3|Brand#32|ECONOMY POLISHED TIN|20|WRAP CASE|1603.70|nstructions wake alon +704|salmon lawn chocolate lace honeydew|Manufacturer#3|Brand#34|LARGE ANODIZED BRASS|23|MED CAN|1604.70|l, ironic +705|snow drab lawn dark tan|Manufacturer#3|Brand#33|ECONOMY PLATED TIN|47|LG PKG|1605.70|ironic +706|cream white navajo frosted puff|Manufacturer#3|Brand#33|LARGE PLATED BRASS|6|SM PKG|1606.70|quests. i +707|salmon khaki misty deep peru|Manufacturer#1|Brand#11|SMALL POLISHED BRASS|17|SM BAG|1607.70|osits about the fluf +708|brown midnight plum violet tomato|Manufacturer#3|Brand#32|SMALL BRUSHED NICKEL|29|SM DRUM|1608.70|ully final instru +709|tomato sienna cornflower black misty|Manufacturer#4|Brand#43|SMALL BRUSHED TIN|16|SM BAG|1609.70|ns. blithely i +710|chartreuse thistle midnight magenta violet|Manufacturer#1|Brand#15|SMALL POLISHED TIN|27|JUMBO PACK|1610.71|fluffily unu +711|goldenrod sienna linen steel floral|Manufacturer#1|Brand#11|PROMO BRUSHED NICKEL|24|LG DRUM|1611.71|s hang slyly regula +712|blanched rose royal tomato hot|Manufacturer#3|Brand#33|ECONOMY BRUSHED COPPER|25|SM CASE|1612.71|even, fluffy +713|gainsboro plum powder seashell lawn|Manufacturer#2|Brand#25|SMALL ANODIZED COPPER|20|SM CAN|1613.71|onic de +714|chartreuse medium gainsboro honeydew saddle|Manufacturer#1|Brand#11|MEDIUM POLISHED NICKEL|35|SM JAR|1614.71|ions. furiously final +715|deep yellow coral sienna white|Manufacturer#2|Brand#24|LARGE BRUSHED TIN|28|WRAP BAG|1615.71|ons boost. furiou +716|grey floral sienna cyan gainsboro|Manufacturer#1|Brand#12|SMALL POLISHED TIN|37|JUMBO CAN|1616.71|osits! packages hag +717|papaya turquoise spring midnight medium|Manufacturer#2|Brand#22|STANDARD PLATED TIN|28|JUMBO JAR|1617.71| final notornis na +718|khaki navy saddle ghost orchid|Manufacturer#3|Brand#35|PROMO BURNISHED COPPER|24|SM CAN|1618.71|ests. final, exp +719|chocolate honeydew khaki aquamarine white|Manufacturer#3|Brand#35|STANDARD BRUSHED NICKEL|49|JUMBO BAG|1619.71|ect. furiously +720|light khaki dodger dark lawn|Manufacturer#4|Brand#45|SMALL BURNISHED NICKEL|8|JUMBO BAG|1620.72|as. furiously +721|gainsboro chocolate maroon hot sienna|Manufacturer#5|Brand#52|STANDARD ANODIZED STEEL|33|MED PKG|1621.72|ly special instruct +722|forest chartreuse plum royal papaya|Manufacturer#4|Brand#43|ECONOMY BURNISHED NICKEL|43|JUMBO BAG|1622.72|ic packages. fin +723|slate magenta lemon peru pink|Manufacturer#3|Brand#31|LARGE BRUSHED BRASS|34|WRAP CASE|1623.72|unts. excu +724|rosy coral thistle ghost papaya|Manufacturer#3|Brand#35|PROMO POLISHED COPPER|28|JUMBO BOX|1624.72| carefully pend +725|hot blanched salmon slate burlywood|Manufacturer#4|Brand#43|LARGE PLATED NICKEL|11|JUMBO BOX|1625.72|r theo +726|cream aquamarine violet medium midnight|Manufacturer#4|Brand#43|PROMO POLISHED NICKEL|41|JUMBO BAG|1626.72|arefully? carefully i +727|royal pink smoke bisque lime|Manufacturer#3|Brand#35|PROMO PLATED BRASS|35|SM PKG|1627.72| about the furio +728|cornsilk grey sienna blue sky|Manufacturer#3|Brand#33|ECONOMY PLATED TIN|27|LG JAR|1628.72|fily regular package +729|papaya cornsilk gainsboro rose pink|Manufacturer#3|Brand#35|ECONOMY BRUSHED TIN|6|LG JAR|1629.72|egular accou +730|rose blush saddle cyan hot|Manufacturer#4|Brand#45|MEDIUM PLATED TIN|8|SM PKG|1630.73|ironic +731|firebrick indian forest rose khaki|Manufacturer#3|Brand#33|PROMO BURNISHED NICKEL|34|MED CASE|1631.73|snooze above the +732|violet frosted red papaya drab|Manufacturer#2|Brand#21|MEDIUM BRUSHED BRASS|1|SM BAG|1632.73|. sauternes haggl +733|burnished goldenrod royal plum midnight|Manufacturer#4|Brand#43|PROMO ANODIZED STEEL|1|MED CASE|1633.73| special instruct +734|lace light bisque dodger aquamarine|Manufacturer#2|Brand#21|MEDIUM BRUSHED STEEL|34|WRAP DRUM|1634.73|quests +735|wheat white honeydew almond coral|Manufacturer#4|Brand#42|SMALL BRUSHED STEEL|44|SM CAN|1635.73|kages are according +736|slate honeydew pink magenta lace|Manufacturer#3|Brand#32|PROMO ANODIZED BRASS|44|JUMBO DRUM|1636.73|telets wake carefu +737|orange navajo blanched cyan snow|Manufacturer#5|Brand#53|PROMO POLISHED NICKEL|25|SM BAG|1637.73|re slyly. bold, regul +738|peru floral sky steel maroon|Manufacturer#2|Brand#21|ECONOMY BURNISHED COPPER|29|JUMBO CAN|1638.73|ckages wake. slyly fin +739|powder lavender wheat pale puff|Manufacturer#3|Brand#31|ECONOMY BRUSHED COPPER|24|JUMBO BOX|1639.73|the regular +740|almond aquamarine mint misty red|Manufacturer#3|Brand#35|STANDARD POLISHED COPPER|7|WRAP PACK|1640.74| even dep +741|thistle seashell cyan cornsilk indian|Manufacturer#4|Brand#44|STANDARD PLATED TIN|33|WRAP PACK|1641.74|oxes slee +742|dodger cream snow pink floral|Manufacturer#5|Brand#51|STANDARD BRUSHED NICKEL|30|SM PACK|1642.74|out the furiously +743|navajo midnight peru orange salmon|Manufacturer#4|Brand#42|LARGE ANODIZED COPPER|4|MED JAR|1643.74|al packages ar +744|burlywood deep hot turquoise chartreuse|Manufacturer#5|Brand#53|MEDIUM BURNISHED COPPER|47|MED PKG|1644.74|uriously brave ideas +745|seashell dark lime midnight puff|Manufacturer#3|Brand#31|PROMO POLISHED COPPER|25|JUMBO BOX|1645.74| silent +746|honeydew brown sienna red chocolate|Manufacturer#2|Brand#23|ECONOMY ANODIZED STEEL|31|MED CAN|1646.74|osits affix furiously +747|lace red hot mint goldenrod|Manufacturer#1|Brand#11|LARGE BURNISHED NICKEL|20|WRAP PKG|1647.74|deposits b +748|forest indian snow grey peru|Manufacturer#5|Brand#54|STANDARD BURNISHED BRASS|32|SM CAN|1648.74|arefully bo +749|snow goldenrod puff violet mint|Manufacturer#2|Brand#24|SMALL PLATED COPPER|16|MED JAR|1649.74| bold re +750|puff slate magenta powder lawn|Manufacturer#4|Brand#43|LARGE POLISHED NICKEL|47|MED PACK|1650.75|tipliers about the q +751|steel blush indian rosy pink|Manufacturer#1|Brand#11|SMALL POLISHED TIN|17|SM DRUM|1651.75|uests haggle bl +752|medium blue midnight misty frosted|Manufacturer#5|Brand#53|MEDIUM ANODIZED COPPER|1|MED PACK|1652.75|lites mold b +753|blanched plum navajo beige indian|Manufacturer#2|Brand#25|STANDARD ANODIZED TIN|13|LG DRUM|1653.75|nal foxes. quickly f +754|thistle steel sky light red|Manufacturer#5|Brand#51|SMALL ANODIZED STEEL|42|WRAP JAR|1654.75|es. blithely dogge +755|spring dodger floral metallic moccasin|Manufacturer#2|Brand#22|STANDARD PLATED TIN|12|WRAP PACK|1655.75| wake. even packages a +756|ghost antique snow cream cyan|Manufacturer#5|Brand#52|STANDARD PLATED BRASS|44|MED BAG|1656.75|rious +757|papaya dim slate saddle navajo|Manufacturer#3|Brand#35|ECONOMY POLISHED NICKEL|12|JUMBO CASE|1657.75|the quickly +758|yellow orchid dim cyan burlywood|Manufacturer#1|Brand#11|ECONOMY ANODIZED TIN|25|MED BOX|1658.75|haggle +759|yellow powder navajo maroon chartreuse|Manufacturer#3|Brand#34|LARGE BURNISHED TIN|20|JUMBO CAN|1659.75|struction +760|orange navy hot aquamarine sienna|Manufacturer#4|Brand#44|MEDIUM POLISHED COPPER|6|LG JAR|1660.76|jole according +761|seashell green dodger beige linen|Manufacturer#3|Brand#34|ECONOMY ANODIZED TIN|7|SM JAR|1661.76|ages according +762|peach grey firebrick dim smoke|Manufacturer#1|Brand#15|LARGE POLISHED TIN|35|MED PKG|1662.76|xpress ideas. fluff +763|wheat seashell azure chartreuse dodger|Manufacturer#4|Brand#44|LARGE BRUSHED TIN|50|SM PKG|1663.76|counts. regu +764|cyan moccasin blanched light purple|Manufacturer#1|Brand#13|SMALL ANODIZED NICKEL|11|LG JAR|1664.76|es. final, bold +765|thistle red smoke chartreuse orange|Manufacturer#3|Brand#35|STANDARD BRUSHED BRASS|3|WRAP BAG|1665.76|ly regular pint +766|midnight sienna orange gainsboro black|Manufacturer#2|Brand#24|MEDIUM BURNISHED NICKEL|20|MED PACK|1666.76|inal ideas. asy +767|blush firebrick misty blanched purple|Manufacturer#2|Brand#24|LARGE POLISHED TIN|50|MED DRUM|1667.76|ts. carefully unu +768|maroon gainsboro seashell hot sandy|Manufacturer#4|Brand#43|LARGE BRUSHED COPPER|41|SM DRUM|1668.76|olites haggle: car +769|tomato royal firebrick turquoise cream|Manufacturer#2|Brand#24|MEDIUM BRUSHED TIN|8|LG CASE|1669.76|ake carefull +770|lemon yellow coral deep lime|Manufacturer#2|Brand#25|LARGE BRUSHED TIN|7|SM PACK|1670.77|ave ideas. +771|plum maroon lavender tan firebrick|Manufacturer#1|Brand#15|SMALL BURNISHED TIN|17|LG DRUM|1671.77| cajole slyly fina +772|dodger firebrick peach ivory seashell|Manufacturer#3|Brand#35|SMALL PLATED BRASS|33|MED PKG|1672.77|dolites haggle sp +773|saddle medium beige purple plum|Manufacturer#3|Brand#32|PROMO BURNISHED STEEL|16|LG CASE|1673.77| final, sp +774|wheat chiffon cyan misty moccasin|Manufacturer#2|Brand#24|STANDARD ANODIZED NICKEL|26|WRAP CASE|1674.77|ly express dependen +775|papaya misty orchid snow metallic|Manufacturer#1|Brand#14|LARGE PLATED TIN|2|MED PACK|1675.77|azzle carefully +776|powder indian dodger hot lemon|Manufacturer#5|Brand#51|STANDARD ANODIZED BRASS|21|WRAP DRUM|1676.77|egular orbits haggl +777|blanched indian pink frosted grey|Manufacturer#5|Brand#53|SMALL ANODIZED STEEL|50|JUMBO JAR|1677.77| theodolites +778|saddle mint navy cyan cornflower|Manufacturer#3|Brand#32|PROMO BURNISHED STEEL|20|WRAP BOX|1678.77|nic re +779|salmon burnished orange rose cornsilk|Manufacturer#2|Brand#22|ECONOMY BRUSHED STEEL|26|WRAP DRUM|1679.77| regular epitaphs are +780|rosy chocolate tan moccasin salmon|Manufacturer#5|Brand#55|MEDIUM ANODIZED STEEL|31|MED CASE|1680.78|t quickly sly +781|light orchid purple black navy|Manufacturer#1|Brand#13|ECONOMY PLATED STEEL|22|LG DRUM|1681.78|gular, regu +782|peru firebrick coral chartreuse rosy|Manufacturer#1|Brand#13|LARGE POLISHED BRASS|29|SM BAG|1682.78|hely u +783|cyan turquoise azure pink dark|Manufacturer#1|Brand#13|SMALL PLATED NICKEL|4|MED DRUM|1683.78|ss acc +784|light smoke seashell snow chartreuse|Manufacturer#1|Brand#12|MEDIUM BRUSHED COPPER|47|LG DRUM|1684.78|unts. furiously +785|coral saddle indian lime frosted|Manufacturer#3|Brand#33|PROMO ANODIZED TIN|41|SM PACK|1685.78|use carefully +786|royal azure ivory moccasin salmon|Manufacturer#2|Brand#23|STANDARD PLATED NICKEL|20|SM PACK|1686.78|eodoli +787|pale metallic ivory peach slate|Manufacturer#5|Brand#55|SMALL ANODIZED NICKEL|35|WRAP PKG|1687.78|es alongside of +788|floral dark dodger chartreuse lavender|Manufacturer#3|Brand#34|LARGE PLATED STEEL|10|LG JAR|1688.78|s solv +789|dodger spring antique lace papaya|Manufacturer#3|Brand#35|PROMO BURNISHED STEEL|14|LG PACK|1689.78|ts hagg +790|lavender yellow pink puff olive|Manufacturer#4|Brand#42|PROMO POLISHED COPPER|35|JUMBO BOX|1690.79|s are +791|indian blush medium thistle lime|Manufacturer#2|Brand#24|STANDARD ANODIZED COPPER|24|MED PACK|1691.79| special pinto bean +792|plum indian cornflower frosted purple|Manufacturer#1|Brand#13|SMALL BURNISHED BRASS|8|MED PKG|1692.79|efully unusual deposi +793|white chiffon blue green violet|Manufacturer#5|Brand#51|LARGE POLISHED NICKEL|28|JUMBO CAN|1693.79|tions. furiou +794|ivory peach light thistle antique|Manufacturer#5|Brand#51|PROMO PLATED COPPER|47|MED PKG|1694.79|le bl +795|cream royal light yellow hot|Manufacturer#5|Brand#54|MEDIUM POLISHED TIN|46|MED JAR|1695.79|ully regula +796|beige frosted cyan hot puff|Manufacturer#5|Brand#51|ECONOMY BRUSHED STEEL|50|WRAP CAN|1696.79|yly fina +797|violet peach puff orange white|Manufacturer#4|Brand#41|STANDARD BURNISHED STEEL|10|WRAP BAG|1697.79|ments +798|turquoise indian white bisque chartreuse|Manufacturer#1|Brand#12|ECONOMY PLATED NICKEL|18|LG JAR|1698.79|ffily even excuses +799|green azure rose aquamarine floral|Manufacturer#3|Brand#35|PROMO POLISHED TIN|7|MED JAR|1699.79|he slyly brave excuses +800|maroon mint medium lace plum|Manufacturer#1|Brand#11|PROMO BRUSHED BRASS|29|WRAP BAG|1700.80|s sleep about the car +801|linen steel salmon beige lemon|Manufacturer#5|Brand#54|LARGE BRUSHED NICKEL|18|JUMBO DRUM|1701.80|latelets. slyly fi +802|rosy ghost cyan puff dark|Manufacturer#3|Brand#34|ECONOMY PLATED BRASS|41|WRAP JAR|1702.80|equest +803|brown navy tan salmon honeydew|Manufacturer#5|Brand#52|SMALL ANODIZED TIN|50|MED PKG|1703.80|ly at the accou +804|bisque grey honeydew goldenrod ghost|Manufacturer#2|Brand#23|SMALL POLISHED BRASS|9|SM BAG|1704.80|itaphs sle +805|tan ghost cyan salmon goldenrod|Manufacturer#5|Brand#52|STANDARD PLATED BRASS|8|JUMBO PKG|1705.80|t blithe +806|blue violet yellow khaki azure|Manufacturer#3|Brand#32|PROMO BURNISHED TIN|45|LG BAG|1706.80| ironic theodolites a +807|turquoise snow navy brown lime|Manufacturer#2|Brand#24|LARGE ANODIZED NICKEL|25|WRAP JAR|1707.80| quietly express pi +808|rosy indian sky frosted blush|Manufacturer#5|Brand#51|SMALL BRUSHED TIN|36|MED PKG|1708.80| pending asymptotes a +809|almond steel maroon chiffon frosted|Manufacturer#3|Brand#32|STANDARD BRUSHED COPPER|17|SM BAG|1709.80|n pla +810|blanched lemon magenta medium dark|Manufacturer#5|Brand#54|LARGE ANODIZED TIN|13|WRAP BOX|1710.81|instructions. +811|ivory bisque black chiffon gainsboro|Manufacturer#3|Brand#33|PROMO BRUSHED NICKEL|32|SM BOX|1711.81|pecial, ironic pac +812|firebrick olive chartreuse frosted ivory|Manufacturer#3|Brand#33|LARGE PLATED TIN|11|WRAP BAG|1712.81|asymptot +813|sandy ghost khaki frosted goldenrod|Manufacturer#4|Brand#43|MEDIUM POLISHED STEEL|2|WRAP DRUM|1713.81|riously ironic deposi +814|burnished seashell floral moccasin antique|Manufacturer#5|Brand#54|ECONOMY PLATED NICKEL|43|MED PKG|1714.81|xpress requests. +815|light peach saddle medium firebrick|Manufacturer#2|Brand#22|ECONOMY BRUSHED NICKEL|5|LG PACK|1715.81|nt requests a +816|thistle ivory pink olive puff|Manufacturer#1|Brand#13|STANDARD POLISHED NICKEL|35|LG CAN|1716.81| thin +817|azure chocolate lavender blanched burnished|Manufacturer#4|Brand#41|STANDARD ANODIZED TIN|36|JUMBO PKG|1717.81|carefu +818|navajo saddle indian cornflower steel|Manufacturer#4|Brand#43|PROMO BRUSHED BRASS|36|MED JAR|1718.81|ckages +819|light magenta indian khaki lavender|Manufacturer#5|Brand#54|ECONOMY BRUSHED STEEL|27|SM CAN|1719.81|as are slyly against +820|wheat salmon forest lavender papaya|Manufacturer#1|Brand#11|STANDARD BURNISHED STEEL|20|WRAP JAR|1720.82|ely regular theodo +821|smoke drab rose hot spring|Manufacturer#4|Brand#42|PROMO POLISHED TIN|15|MED BOX|1721.82|gle across t +822|purple lawn ivory black slate|Manufacturer#5|Brand#52|PROMO ANODIZED BRASS|21|LG CASE|1722.82|ding to t +823|maroon salmon puff medium brown|Manufacturer#2|Brand#25|SMALL BURNISHED COPPER|21|WRAP CASE|1723.82|inal the +824|dodger snow orange almond magenta|Manufacturer#1|Brand#15|LARGE BURNISHED TIN|34|MED BAG|1724.82|s. ironic +825|puff deep hot tomato powder|Manufacturer#1|Brand#13|PROMO PLATED TIN|47|LG CAN|1725.82|lar ide +826|ghost rosy beige salmon lemon|Manufacturer#3|Brand#34|ECONOMY PLATED TIN|21|SM CASE|1726.82|ifts could +827|linen ghost smoke blanched cream|Manufacturer#1|Brand#13|PROMO POLISHED COPPER|15|JUMBO PACK|1727.82|sits; depe +828|lemon light grey burlywood drab|Manufacturer#4|Brand#44|LARGE BRUSHED NICKEL|11|LG PKG|1728.82|symptotes. furiously +829|cream indian deep linen antique|Manufacturer#3|Brand#35|MEDIUM BURNISHED BRASS|33|SM JAR|1729.82|tegrate. +830|cornflower medium salmon coral magenta|Manufacturer#5|Brand#54|SMALL POLISHED TIN|37|JUMBO CAN|1730.83|ep final instructi +831|violet dark midnight lawn cream|Manufacturer#5|Brand#51|STANDARD POLISHED COPPER|8|LG CAN|1731.83|se blithely. special, +832|orange peach midnight burnished lavender|Manufacturer#4|Brand#44|STANDARD ANODIZED COPPER|3|WRAP BAG|1732.83|fily bo +833|thistle puff cream papaya deep|Manufacturer#4|Brand#41|SMALL BRUSHED STEEL|34|JUMBO CAN|1733.83|s thrash furiously fin +834|aquamarine frosted orange dodger khaki|Manufacturer#5|Brand#52|MEDIUM POLISHED TIN|43|JUMBO CAN|1734.83|mptotes integrate +835|turquoise peru light aquamarine dark|Manufacturer#5|Brand#53|MEDIUM PLATED STEEL|21|SM BOX|1735.83|uses. furi +836|almond sky red lime smoke|Manufacturer#3|Brand#31|LARGE BURNISHED TIN|32|SM JAR|1736.83|lyly bold accounts. t +837|papaya goldenrod burlywood purple brown|Manufacturer#1|Brand#13|MEDIUM BURNISHED BRASS|27|WRAP PKG|1737.83|hely furious packages +838|lime peach puff papaya olive|Manufacturer#2|Brand#22|MEDIUM ANODIZED TIN|9|WRAP BAG|1738.83| final pac +839|cornflower white papaya violet navajo|Manufacturer#2|Brand#25|LARGE BRUSHED NICKEL|19|JUMBO CAN|1739.83|ggle a +840|khaki mint chartreuse dark frosted|Manufacturer#4|Brand#44|ECONOMY ANODIZED BRASS|42|WRAP PKG|1740.84|ending ideas w +841|floral khaki grey metallic firebrick|Manufacturer#1|Brand#15|MEDIUM BURNISHED BRASS|48|WRAP BOX|1741.84|y regul +842|gainsboro dim navajo chartreuse olive|Manufacturer#1|Brand#11|SMALL ANODIZED BRASS|4|MED PACK|1742.84|en accounts! carefu +843|frosted metallic mint lawn blanched|Manufacturer#1|Brand#15|MEDIUM POLISHED STEEL|50|LG PACK|1743.84| the +844|honeydew smoke lemon ghost navajo|Manufacturer#3|Brand#35|LARGE PLATED BRASS|22|SM CASE|1744.84|ix furiously beyond +845|papaya burlywood bisque linen navy|Manufacturer#4|Brand#41|LARGE PLATED STEEL|25|LG JAR|1745.84|ully regula +846|purple papaya saddle cream medium|Manufacturer#2|Brand#24|ECONOMY POLISHED NICKEL|6|SM BAG|1746.84|sometimes bold foxes +847|chartreuse pink azure tan slate|Manufacturer#2|Brand#25|SMALL PLATED STEEL|21|SM PACK|1747.84|ely blith +848|orange olive puff midnight almond|Manufacturer#5|Brand#53|LARGE BURNISHED TIN|26|LG JAR|1748.84|gular requests u +849|lawn cornflower puff rosy saddle|Manufacturer#4|Brand#44|STANDARD POLISHED TIN|41|MED DRUM|1749.84|nts among the pending +850|peach goldenrod honeydew moccasin sienna|Manufacturer#4|Brand#41|STANDARD BRUSHED NICKEL|31|JUMBO DRUM|1750.85|kages are carefu +851|maroon beige navy forest honeydew|Manufacturer#5|Brand#54|ECONOMY BURNISHED COPPER|30|LG CAN|1751.85| asympto +852|lemon slate khaki misty hot|Manufacturer#2|Brand#24|PROMO PLATED NICKEL|47|JUMBO BOX|1752.85|side of the +853|peach honeydew cyan peru light|Manufacturer#5|Brand#51|SMALL ANODIZED NICKEL|42|JUMBO CASE|1753.85|ts sleep! +854|pale wheat lace midnight papaya|Manufacturer#4|Brand#41|SMALL POLISHED COPPER|29|JUMBO CASE|1754.85|ests cajole furious +855|dim blue slate dodger yellow|Manufacturer#3|Brand#31|STANDARD BURNISHED TIN|46|MED BOX|1755.85|ly express fox +856|blush frosted powder antique blanched|Manufacturer#1|Brand#13|MEDIUM BRUSHED STEEL|12|MED BAG|1756.85|posits integrate sly +857|goldenrod beige lemon midnight cornflower|Manufacturer#3|Brand#35|PROMO PLATED TIN|8|MED PACK|1757.85|final de +858|papaya maroon hot blue pink|Manufacturer#3|Brand#33|ECONOMY BURNISHED COPPER|14|SM CAN|1758.85|elets breach f +859|ghost blue indian cornsilk drab|Manufacturer#3|Brand#35|ECONOMY ANODIZED COPPER|10|WRAP BAG|1759.85| even Tiresias wake fu +860|burlywood peach papaya violet midnight|Manufacturer#3|Brand#32|SMALL POLISHED STEEL|36|LG PKG|1760.86|oss the f +861|blue sienna navy coral violet|Manufacturer#4|Brand#43|ECONOMY BRUSHED COPPER|48|JUMBO BOX|1761.86| furiousl +862|tan dim chiffon steel purple|Manufacturer#5|Brand#54|LARGE POLISHED NICKEL|12|LG PKG|1762.86| pending depo +863|light khaki lime lemon burnished|Manufacturer#2|Brand#25|STANDARD ANODIZED COPPER|41|LG CAN|1763.86| regular pinto beans +864|linen drab blush maroon sienna|Manufacturer#1|Brand#11|STANDARD POLISHED TIN|39|JUMBO PACK|1764.86|boost. +865|brown seashell red bisque sandy|Manufacturer#1|Brand#11|SMALL ANODIZED BRASS|12|JUMBO PACK|1765.86|s along t +866|dodger antique tan coral honeydew|Manufacturer#1|Brand#11|STANDARD PLATED COPPER|13|WRAP BOX|1766.86|eas sleep quickly +867|snow spring black white burnished|Manufacturer#5|Brand#54|PROMO POLISHED NICKEL|4|LG BOX|1767.86|nts wake care +868|navajo azure beige aquamarine blush|Manufacturer#3|Brand#33|PROMO BRUSHED BRASS|48|JUMBO PKG|1768.86|packages. e +869|snow blush violet lace ghost|Manufacturer#2|Brand#24|STANDARD ANODIZED COPPER|28|LG BAG|1769.86|y fina +870|antique hot snow burnished ghost|Manufacturer#5|Brand#54|SMALL PLATED NICKEL|11|JUMBO CAN|1770.87|ldly unusual depth +871|midnight dark coral ivory burlywood|Manufacturer#5|Brand#55|SMALL ANODIZED BRASS|27|SM PKG|1771.87|olites snooze quickl +872|papaya frosted cornflower green almond|Manufacturer#1|Brand#15|MEDIUM PLATED STEEL|41|LG CASE|1772.87|gular inst +873|goldenrod maroon snow cream indian|Manufacturer#1|Brand#11|MEDIUM BRUSHED BRASS|45|MED CAN|1773.87|ecial ideas. slyly +874|drab slate hot black khaki|Manufacturer#1|Brand#15|MEDIUM PLATED TIN|9|MED BOX|1774.87|e regular req +875|pale peru red orchid almond|Manufacturer#2|Brand#24|ECONOMY BRUSHED COPPER|1|MED DRUM|1775.87|e furiously. b +876|frosted lace turquoise sky sandy|Manufacturer#3|Brand#31|MEDIUM PLATED NICKEL|25|SM CAN|1776.87|s after the fur +877|lime violet tomato drab blush|Manufacturer#3|Brand#31|STANDARD ANODIZED NICKEL|20|MED PACK|1777.87|thely rut +878|steel lace wheat orchid linen|Manufacturer#3|Brand#32|STANDARD POLISHED NICKEL|40|JUMBO CASE|1778.87| slyly ironic g +879|spring red indian floral sky|Manufacturer#3|Brand#34|STANDARD BURNISHED TIN|23|MED PKG|1779.87|ar, even request +880|sandy turquoise cream firebrick rose|Manufacturer#2|Brand#25|STANDARD ANODIZED COPPER|10|LG CASE|1780.88|ly stealthy deposits +881|bisque frosted khaki linen royal|Manufacturer#2|Brand#21|LARGE BRUSHED BRASS|12|MED PACK|1781.88|ully for +882|chiffon royal lime almond midnight|Manufacturer#4|Brand#44|ECONOMY BRUSHED STEEL|12|MED BAG|1782.88| silent, pendi +883|smoke grey dark yellow brown|Manufacturer#3|Brand#31|STANDARD PLATED NICKEL|18|LG PACK|1783.88|fluffily unusual pint +884|peach medium goldenrod cyan ghost|Manufacturer#1|Brand#11|SMALL POLISHED NICKEL|38|WRAP BAG|1784.88|luffy accounts. +885|dim peach moccasin snow floral|Manufacturer#4|Brand#42|ECONOMY BRUSHED STEEL|31|WRAP DRUM|1785.88|lar, even ideas caj +886|turquoise dodger lemon antique green|Manufacturer#5|Brand#55|LARGE BRUSHED COPPER|46|MED BAG|1786.88|tornis haggle! +887|navajo cream salmon orange smoke|Manufacturer#4|Brand#41|SMALL BRUSHED STEEL|48|JUMBO CAN|1787.88|x slyly aroun +888|pale turquoise rose olive chiffon|Manufacturer#3|Brand#31|STANDARD BRUSHED NICKEL|44|SM DRUM|1788.88|y according t +889|saddle midnight almond drab blanched|Manufacturer#5|Brand#51|LARGE BURNISHED BRASS|19|JUMBO DRUM|1789.88|efully regular +890|sandy lawn chartreuse peru blue|Manufacturer#5|Brand#52|SMALL BRUSHED STEEL|23|MED PKG|1790.89|ests d +891|plum floral dodger lemon almond|Manufacturer#4|Brand#42|ECONOMY POLISHED STEEL|5|MED CASE|1791.89|yly regular, expr +892|thistle chocolate sandy powder drab|Manufacturer#2|Brand#22|SMALL BRUSHED NICKEL|3|LG DRUM|1792.89|quickly regular r +893|dark moccasin bisque cyan azure|Manufacturer#1|Brand#14|PROMO BRUSHED STEEL|9|LG JAR|1793.89|ly regular +894|chocolate blue smoke azure sandy|Manufacturer#3|Brand#35|SMALL BURNISHED TIN|43|MED BAG|1794.89|s. carefully expr +895|thistle azure magenta mint burnished|Manufacturer#4|Brand#41|MEDIUM BRUSHED STEEL|17|SM BOX|1795.89|eaves might +896|peach ivory rose honeydew lace|Manufacturer#4|Brand#43|PROMO ANODIZED TIN|7|LG CASE|1796.89|e across +897|misty olive purple cream red|Manufacturer#4|Brand#41|SMALL BRUSHED COPPER|26|SM JAR|1797.89|cajole bli +898|olive burlywood royal cream drab|Manufacturer#4|Brand#45|PROMO POLISHED NICKEL|8|WRAP BAG|1798.89|e against the pack +899|gainsboro dim misty violet coral|Manufacturer#2|Brand#25|SMALL ANODIZED NICKEL|50|WRAP CASE|1799.89|lithely pending excuse +900|medium antique khaki cream slate|Manufacturer#2|Brand#21|STANDARD PLATED NICKEL|40|LG CAN|1800.90|foxes. carefully s +901|white honeydew orange saddle black|Manufacturer#2|Brand#23|ECONOMY PLATED TIN|38|LG CAN|1801.90|ffily final theodoli +902|red chartreuse firebrick burlywood papaya|Manufacturer#2|Brand#23|LARGE ANODIZED COPPER|14|MED CAN|1802.90|inal pint +903|navajo chiffon mint ghost burlywood|Manufacturer#4|Brand#44|ECONOMY BURNISHED BRASS|4|SM BAG|1803.90|the i +904|black olive light sandy linen|Manufacturer#1|Brand#12|STANDARD ANODIZED TIN|20|WRAP DRUM|1804.90|ar theodolites sleep b +905|burlywood honeydew cornsilk indian green|Manufacturer#2|Brand#25|PROMO BRUSHED BRASS|27|MED CASE|1805.90|es. furiously ir +906|rosy forest navajo light turquoise|Manufacturer#4|Brand#44|MEDIUM BURNISHED COPPER|45|MED DRUM|1806.90|unusua +907|plum lawn black chartreuse sandy|Manufacturer#5|Brand#52|ECONOMY ANODIZED STEEL|8|LG CASE|1807.90|es. carefu +908|pink navy lace papaya brown|Manufacturer#2|Brand#25|MEDIUM BURNISHED TIN|13|JUMBO JAR|1808.90|tions ca +909|cornsilk tomato chiffon bisque navy|Manufacturer#1|Brand#12|STANDARD PLATED TIN|40|WRAP PKG|1809.90|ht boost quic +910|coral antique peach navy violet|Manufacturer#4|Brand#42|STANDARD ANODIZED TIN|15|JUMBO JAR|1810.91|ly final +911|blush coral medium ivory snow|Manufacturer#1|Brand#14|ECONOMY BURNISHED TIN|23|MED CAN|1811.91|foxes cajole after the +912|indian tomato rose powder turquoise|Manufacturer#5|Brand#55|STANDARD POLISHED NICKEL|17|SM BAG|1812.91|ar theodo +913|seashell medium burnished moccasin blue|Manufacturer#2|Brand#23|LARGE PLATED BRASS|49|SM DRUM|1813.91|yly even dol +914|snow rose moccasin tomato linen|Manufacturer#3|Brand#35|ECONOMY POLISHED STEEL|8|LG PKG|1814.91|ckly busil +915|aquamarine purple spring gainsboro salmon|Manufacturer#2|Brand#21|LARGE ANODIZED BRASS|25|WRAP BAG|1815.91|depos +916|chartreuse tomato rose chocolate magenta|Manufacturer#2|Brand#21|MEDIUM BURNISHED BRASS|28|MED CAN|1816.91|ons. bravely ironic +917|midnight khaki medium linen peru|Manufacturer#2|Brand#24|SMALL ANODIZED COPPER|3|SM CASE|1817.91|riously past th +918|ghost steel beige turquoise ivory|Manufacturer#5|Brand#55|ECONOMY PLATED TIN|15|LG PKG|1818.91|losely according to +919|sandy cream royal cyan orchid|Manufacturer#1|Brand#13|PROMO BRUSHED COPPER|49|MED BOX|1819.91|along +920|sky lemon misty slate lawn|Manufacturer#4|Brand#44|MEDIUM BRUSHED STEEL|19|WRAP CAN|1820.92|y regu +921|khaki yellow plum cyan forest|Manufacturer#1|Brand#11|LARGE BURNISHED STEEL|35|JUMBO DRUM|1821.92|pecial in +922|frosted dodger cyan medium indian|Manufacturer#3|Brand#34|LARGE BURNISHED BRASS|30|SM CASE|1822.92|uctions. sl +923|moccasin lace rose navajo forest|Manufacturer#2|Brand#24|STANDARD PLATED TIN|26|WRAP CASE|1823.92|he packag +924|indian smoke orange ghost papaya|Manufacturer#1|Brand#11|ECONOMY POLISHED STEEL|41|JUMBO PKG|1824.92|the ac +925|tomato antique plum snow burlywood|Manufacturer#4|Brand#44|STANDARD POLISHED NICKEL|44|MED PACK|1825.92|aggle slyly. blithe +926|tan deep medium smoke slate|Manufacturer#4|Brand#45|STANDARD BRUSHED TIN|39|MED JAR|1826.92|gle quickly ironic +927|dodger purple green peach navajo|Manufacturer#1|Brand#14|LARGE ANODIZED TIN|13|WRAP BAG|1827.92|otes snooz +928|violet dodger cyan orange moccasin|Manufacturer#4|Brand#43|SMALL ANODIZED TIN|43|SM BOX|1828.92|ully ev +929|burnished pale medium turquoise lace|Manufacturer#3|Brand#33|LARGE PLATED COPPER|40|MED DRUM|1829.92|hely iron +930|violet ivory orchid rose frosted|Manufacturer#2|Brand#23|SMALL BRUSHED BRASS|26|LG DRUM|1830.93|uickly ironic +931|red puff chiffon sienna dark|Manufacturer#3|Brand#31|STANDARD ANODIZED NICKEL|37|LG CAN|1831.93|are fluffily. +932|cornflower sky powder cyan linen|Manufacturer#2|Brand#24|SMALL ANODIZED COPPER|12|LG BOX|1832.93|ly regular depos +933|pink magenta frosted blanched lime|Manufacturer#3|Brand#33|STANDARD BRUSHED STEEL|25|LG CASE|1833.93|he blit +934|beige saddle magenta cyan dim|Manufacturer#4|Brand#45|STANDARD ANODIZED BRASS|40|MED JAR|1834.93|ual packages +935|royal cornflower maroon khaki cornsilk|Manufacturer#5|Brand#53|STANDARD BRUSHED STEEL|8|JUMBO DRUM|1835.93|arefully ironic +936|white beige firebrick dodger olive|Manufacturer#2|Brand#24|MEDIUM PLATED BRASS|6|WRAP DRUM|1836.93|longside of the reg +937|drab peru royal pink peach|Manufacturer#3|Brand#33|PROMO ANODIZED TIN|2|JUMBO CAN|1837.93|ithely +938|chartreuse peach spring cornflower tan|Manufacturer#2|Brand#22|LARGE BRUSHED NICKEL|1|JUMBO CASE|1838.93|ajole slyly r +939|salmon magenta orange coral aquamarine|Manufacturer#1|Brand#14|PROMO BURNISHED BRASS|41|WRAP PACK|1839.93|ages wake doggedly of +940|violet coral blanched orange light|Manufacturer#1|Brand#15|PROMO POLISHED TIN|49|JUMBO JAR|1840.94|ate blithely bold, si +941|lace cornsilk pink medium slate|Manufacturer#2|Brand#25|MEDIUM PLATED NICKEL|8|LG PKG|1841.94|fully +942|coral peach bisque green seashell|Manufacturer#3|Brand#35|PROMO POLISHED TIN|44|MED BAG|1842.94|nic pinto b +943|smoke sky chiffon green steel|Manufacturer#5|Brand#55|ECONOMY BRUSHED BRASS|46|SM PKG|1843.94|s wake +944|medium sandy olive wheat turquoise|Manufacturer#3|Brand#33|SMALL PLATED STEEL|1|LG CAN|1844.94| requests nag furiou +945|chiffon steel peach black moccasin|Manufacturer#5|Brand#52|MEDIUM PLATED NICKEL|22|MED JAR|1845.94|uffily abo +946|medium drab rosy spring salmon|Manufacturer#2|Brand#25|MEDIUM PLATED TIN|30|LG BOX|1846.94|y along +947|black tan salmon maroon chartreuse|Manufacturer#1|Brand#13|MEDIUM BURNISHED STEEL|16|JUMBO JAR|1847.94|usual accounts. b +948|gainsboro chocolate bisque sandy steel|Manufacturer#2|Brand#22|MEDIUM ANODIZED BRASS|31|WRAP PKG|1848.94|furious +949|thistle burnished pink yellow wheat|Manufacturer#5|Brand#51|LARGE BURNISHED TIN|47|LG PKG|1849.94|l theodolit +950|steel purple midnight beige coral|Manufacturer#3|Brand#31|SMALL ANODIZED STEEL|26|WRAP CASE|1850.95|kages cajole quickly +951|gainsboro indian aquamarine lemon blush|Manufacturer#2|Brand#21|STANDARD BURNISHED STEEL|40|JUMBO JAR|1851.95| final deposits nag a +952|frosted purple sky steel papaya|Manufacturer#3|Brand#31|MEDIUM BRUSHED TIN|4|MED PACK|1852.95|l deposits sleep bli +953|tomato cornflower honeydew sandy grey|Manufacturer#4|Brand#41|PROMO ANODIZED TIN|2|WRAP JAR|1853.95|ly quickly final acco +954|turquoise bisque khaki coral antique|Manufacturer#5|Brand#55|ECONOMY ANODIZED STEEL|35|JUMBO CASE|1854.95|furious +955|blue olive tan rosy navajo|Manufacturer#3|Brand#32|PROMO BURNISHED STEEL|43|SM CASE|1855.95|tions +956|orchid yellow dark lawn thistle|Manufacturer#1|Brand#13|STANDARD BRUSHED STEEL|7|LG CASE|1856.95|furiously pending d +957|snow turquoise coral lime goldenrod|Manufacturer#3|Brand#33|SMALL ANODIZED COPPER|23|SM CAN|1857.95|ndencies wake s +958|turquoise sandy drab dodger cyan|Manufacturer#3|Brand#35|LARGE PLATED NICKEL|13|LG BOX|1858.95|quickly careful i +959|sky snow peach olive spring|Manufacturer#4|Brand#41|SMALL BURNISHED STEEL|5|WRAP JAR|1859.95|iously bold depos +960|sienna royal light orchid moccasin|Manufacturer#5|Brand#55|LARGE PLATED COPPER|26|LG CASE|1860.96|lly b +961|cornflower chocolate floral burnished green|Manufacturer#1|Brand#15|PROMO BRUSHED BRASS|1|SM PACK|1861.96|fully. f +962|magenta linen ghost almond floral|Manufacturer#1|Brand#13|MEDIUM PLATED BRASS|38|JUMBO BOX|1862.96|lithely. +963|violet beige lime dark metallic|Manufacturer#4|Brand#44|MEDIUM PLATED BRASS|44|LG CASE|1863.96|y final deposits wake. +964|sky orange indian pale burlywood|Manufacturer#5|Brand#54|SMALL POLISHED BRASS|48|MED BOX|1864.96|nal asymptotes. regul +965|dim cyan bisque black smoke|Manufacturer#3|Brand#34|MEDIUM PLATED STEEL|39|LG PKG|1865.96|dolite +966|turquoise antique brown violet plum|Manufacturer#4|Brand#42|PROMO BURNISHED TIN|24|MED CAN|1866.96| the carefully +967|cyan snow azure slate papaya|Manufacturer#5|Brand#55|SMALL BURNISHED COPPER|16|JUMBO CAN|1867.96|leep fur +968|rose chiffon chocolate lace papaya|Manufacturer#1|Brand#11|LARGE PLATED TIN|23|LG PKG|1868.96|press accounts acro +969|hot azure royal red dark|Manufacturer#5|Brand#55|PROMO POLISHED STEEL|34|JUMBO CASE|1869.96|le aga +970|sienna azure light medium green|Manufacturer#1|Brand#11|STANDARD BURNISHED STEEL|44|SM CAN|1870.97|ironic +971|orange misty green aquamarine forest|Manufacturer#5|Brand#54|LARGE POLISHED BRASS|19|SM DRUM|1871.97|ugouts. bl +972|tomato burlywood pale moccasin plum|Manufacturer#3|Brand#32|MEDIUM PLATED BRASS|21|JUMBO JAR|1872.97|yly ironic deposits +973|medium lavender blue tomato slate|Manufacturer#2|Brand#22|STANDARD ANODIZED STEEL|42|LG PACK|1873.97|along +974|almond steel slate sky rose|Manufacturer#4|Brand#44|MEDIUM ANODIZED BRASS|35|WRAP BAG|1874.97|s. caref +975|moccasin tomato peach yellow drab|Manufacturer#3|Brand#34|MEDIUM ANODIZED COPPER|22|LG JAR|1875.97|torni +976|white maroon firebrick snow light|Manufacturer#5|Brand#51|STANDARD BRUSHED NICKEL|19|JUMBO PACK|1876.97| special reque +977|frosted tomato deep burnished indian|Manufacturer#5|Brand#53|STANDARD BRUSHED STEEL|2|LG CASE|1877.97|the quick +978|cream tomato rose floral steel|Manufacturer#4|Brand#45|MEDIUM POLISHED TIN|46|LG DRUM|1878.97|quests sleep abo +979|blush cyan azure snow sandy|Manufacturer#4|Brand#45|STANDARD ANODIZED TIN|4|MED CAN|1879.97| accounts. blithe +980|saddle burlywood drab deep red|Manufacturer#4|Brand#41|SMALL ANODIZED STEEL|45|LG CASE|1880.98|ronic deposi +981|floral blanched papaya khaki light|Manufacturer#2|Brand#25|MEDIUM POLISHED COPPER|31|WRAP CAN|1881.98| ironic as +982|drab steel linen puff rosy|Manufacturer#3|Brand#31|SMALL POLISHED BRASS|28|SM BAG|1882.98|boost blithely +983|violet mint moccasin black olive|Manufacturer#4|Brand#43|ECONOMY POLISHED TIN|39|MED BOX|1883.98| pack +984|tan frosted antique midnight thistle|Manufacturer#2|Brand#22|LARGE PLATED TIN|40|SM BAG|1884.98|ly. furiously pe +985|drab rosy orange peach medium|Manufacturer#5|Brand#53|MEDIUM BURNISHED STEEL|10|JUMBO PKG|1885.98|s beside +986|forest purple lawn yellow azure|Manufacturer#3|Brand#33|PROMO BRUSHED BRASS|50|JUMBO DRUM|1886.98|ronic foxes +987|seashell pink linen salmon khaki|Manufacturer#5|Brand#53|PROMO POLISHED BRASS|39|LG BOX|1887.98|furiou +988|rose saddle linen peach cream|Manufacturer#2|Brand#24|STANDARD BURNISHED COPPER|27|WRAP PKG|1888.98|special requests sleep +989|misty ivory plum tan steel|Manufacturer#5|Brand#55|LARGE PLATED TIN|9|JUMBO JAR|1889.98|lets. e +990|azure cornsilk indian floral aquamarine|Manufacturer#1|Brand#14|SMALL BURNISHED COPPER|14|SM BAG|1890.99|quick +991|indian yellow red lime seashell|Manufacturer#3|Brand#32|MEDIUM POLISHED BRASS|9|SM CASE|1891.99|ickly slowly spe +992|hot peru beige magenta metallic|Manufacturer#5|Brand#51|PROMO BURNISHED COPPER|39|JUMBO BOX|1892.99| haggle +993|chiffon papaya lavender tomato spring|Manufacturer#5|Brand#54|MEDIUM BRUSHED NICKEL|2|MED JAR|1893.99|bold pear +994|almond saddle papaya seashell burlywood|Manufacturer#2|Brand#25|PROMO ANODIZED STEEL|38|JUMBO BOX|1894.99|ost slyly. boldly bo +995|papaya violet navy khaki sky|Manufacturer#3|Brand#34|ECONOMY BRUSHED TIN|47|MED DRUM|1895.99|ke furiously fluffily +996|slate pink navajo orange firebrick|Manufacturer#3|Brand#31|STANDARD POLISHED COPPER|13|LG CAN|1896.99|ously +997|khaki lawn rose drab cornsilk|Manufacturer#5|Brand#51|STANDARD ANODIZED BRASS|22|JUMBO BAG|1897.99|riously final +998|ivory maroon cream red peru|Manufacturer#5|Brand#53|STANDARD BRUSHED NICKEL|2|MED BOX|1898.99|s. bold requests wake +999|indian honeydew chartreuse navy cyan|Manufacturer#4|Brand#44|STANDARD PLATED STEEL|16|WRAP CAN|1899.99|ans. slyly expre +1000|wheat frosted chiffon aquamarine saddle|Manufacturer#2|Brand#24|ECONOMY BRUSHED NICKEL|10|SM DRUM|901.00|g fluf diff --git a/src/test/regress/data/part.more.data b/src/test/regress/data/part.more.data new file mode 100644 index 000000000..e79c1c007 --- /dev/null +++ b/src/test/regress/data/part.more.data @@ -0,0 +1,1000 @@ +6001|black lavender tomato brown violet|Manufacturer#3|Brand#32|STANDARD BURNISHED STEEL|41|LG BAG|907.00|eposits. +6002|cyan saddle plum navajo tan|Manufacturer#5|Brand#53|MEDIUM POLISHED BRASS|19|MED BOX|908.00|final pinto beans +6003|chocolate wheat cornflower spring linen|Manufacturer#4|Brand#42|LARGE PLATED BRASS|50|LG JAR|909.00|structions. fluffily +6004|white indian burlywood smoke medium|Manufacturer#1|Brand#13|PROMO BURNISHED TIN|19|JUMBO CAN|910.00|about the care +6005|powder green red peru lavender|Manufacturer#2|Brand#25|PROMO BURNISHED TIN|40|SM CAN|911.00|lar notorni +6006|maroon green blanched indian ghost|Manufacturer#5|Brand#51|SMALL BRUSHED COPPER|46|LG CASE|912.00|es. slyly re +6007|steel cornsilk puff navajo drab|Manufacturer#5|Brand#54|PROMO BURNISHED STEEL|37|SM BOX|913.00|t excus +6008|medium midnight orange papaya brown|Manufacturer#5|Brand#53|PROMO POLISHED STEEL|15|LG BAG|914.00|s unwind unusual +6009|navy floral puff misty salmon|Manufacturer#5|Brand#54|STANDARD ANODIZED STEEL|27|SM BAG|915.00|arefull +6010|saddle green salmon red olive|Manufacturer#3|Brand#32|STANDARD ANODIZED COPPER|42|LG JAR|916.01|bold, spec +6011|turquoise royal papaya azure grey|Manufacturer#1|Brand#15|PROMO BRUSHED NICKEL|50|SM BAG|917.01|ts maintai +6012|burlywood chocolate peru deep rose|Manufacturer#4|Brand#42|STANDARD BRUSHED COPPER|18|SM CASE|918.01|final deposits doubt +6013|gainsboro lime rose hot sky|Manufacturer#3|Brand#32|PROMO ANODIZED COPPER|42|JUMBO JAR|919.01|ate slyly silent, iro +6014|red frosted powder medium sienna|Manufacturer#5|Brand#55|STANDARD ANODIZED NICKEL|46|MED DRUM|920.01|egular packages +6015|chartreuse chocolate peru smoke lace|Manufacturer#1|Brand#11|MEDIUM BRUSHED NICKEL|50|LG DRUM|921.01|nts. evenly unusual +6016|red linen orange floral tomato|Manufacturer#1|Brand#14|ECONOMY POLISHED BRASS|41|MED BAG|922.01| pinto be +6017|firebrick light smoke mint midnight|Manufacturer#3|Brand#32|LARGE BRUSHED NICKEL|44|LG BOX|923.01|ly against the +6018|lavender plum gainsboro mint salmon|Manufacturer#3|Brand#33|ECONOMY POLISHED BRASS|46|WRAP BAG|924.01|ckly r +6019|plum rose midnight lawn papaya|Manufacturer#5|Brand#51|PROMO BRUSHED TIN|38|MED CASE|925.01|press dolp +6020|olive forest purple magenta smoke|Manufacturer#5|Brand#55|STANDARD POLISHED TIN|17|WRAP BOX|926.02|ar packages hagg +6021|lavender slate sienna blush tomato|Manufacturer#5|Brand#52|LARGE PLATED STEEL|17|LG PACK|927.02|ve furiou +6022|cream royal white lace rose|Manufacturer#1|Brand#14|PROMO POLISHED COPPER|18|SM DRUM|928.02|ickly +6023|blush chartreuse gainsboro beige maroon|Manufacturer#1|Brand#15|ECONOMY BURNISHED BRASS|43|SM PKG|929.02|ave packa +6024|almond blush snow salmon midnight|Manufacturer#5|Brand#55|LARGE BURNISHED COPPER|5|LG CAN|930.02|l accoun +6025|purple medium light aquamarine dark|Manufacturer#5|Brand#55|MEDIUM PLATED STEEL|34|SM BAG|931.02|ake after t +6026|coral blush honeydew rose dark|Manufacturer#5|Brand#53|STANDARD BRUSHED STEEL|10|JUMBO BAG|932.02|final +6027|snow cream salmon misty tan|Manufacturer#3|Brand#32|LARGE BURNISHED NICKEL|6|JUMBO JAR|933.02|al dep +6028|orchid almond honeydew grey lace|Manufacturer#1|Brand#12|SMALL PLATED NICKEL|38|SM BOX|934.02|ss the pe +6029|seashell moccasin bisque goldenrod violet|Manufacturer#1|Brand#13|MEDIUM ANODIZED TIN|20|MED CASE|935.02| the special pac +6030|linen yellow orchid drab bisque|Manufacturer#5|Brand#51|SMALL PLATED STEEL|28|JUMBO DRUM|936.03|ly across +6031|green drab coral metallic orchid|Manufacturer#1|Brand#14|LARGE POLISHED BRASS|36|MED CAN|937.03|e. regularly ironic +6032|papaya cream cornsilk khaki navajo|Manufacturer#3|Brand#33|ECONOMY BRUSHED TIN|29|SM PACK|938.03|dolites. evenly ir +6033|drab green smoke salmon navy|Manufacturer#3|Brand#32|STANDARD BRUSHED STEEL|31|JUMBO DRUM|939.03|he fur +6034|forest lawn steel smoke dodger|Manufacturer#4|Brand#42|ECONOMY ANODIZED BRASS|44|MED DRUM|940.03|usual packages. depe +6035|royal orange pink burnished salmon|Manufacturer#1|Brand#11|MEDIUM POLISHED BRASS|39|WRAP CAN|941.03|y thin +6036|chartreuse antique linen puff medium|Manufacturer#3|Brand#34|PROMO ANODIZED NICKEL|1|WRAP BAG|942.03|slyly afte +6037|chocolate rose black steel cyan|Manufacturer#1|Brand#13|ECONOMY PLATED STEEL|34|WRAP BAG|943.03|s are speci +6038|dim almond red burnished lace|Manufacturer#2|Brand#24|MEDIUM ANODIZED TIN|1|WRAP PKG|944.03| deposits. +6039|lavender grey dark drab purple|Manufacturer#4|Brand#45|STANDARD BURNISHED TIN|14|LG CAN|945.03|ress packages cajole q +6040|honeydew dark midnight khaki bisque|Manufacturer#4|Brand#42|MEDIUM PLATED NICKEL|29|LG CASE|946.04|l, even asympt +6041|seashell forest linen brown goldenrod|Manufacturer#2|Brand#21|STANDARD ANODIZED NICKEL|19|MED DRUM|947.04|ecial +6042|peach chocolate firebrick frosted papaya|Manufacturer#5|Brand#54|LARGE BURNISHED STEEL|48|WRAP PKG|948.04|y quiet theodol +6043|khaki misty deep almond medium|Manufacturer#4|Brand#41|SMALL ANODIZED TIN|38|SM CASE|949.04|ideas affix +6044|dodger turquoise midnight papaya seashell|Manufacturer#2|Brand#22|SMALL BURNISHED TIN|4|JUMBO CASE|950.04|ccounts. blith +6045|turquoise blanched chocolate blush almond|Manufacturer#4|Brand#42|SMALL BRUSHED NICKEL|37|WRAP DRUM|951.04| final theodolites +6046|dim green wheat light honeydew|Manufacturer#5|Brand#51|ECONOMY BURNISHED BRASS|14|JUMBO PKG|952.04|l packages +6047|orchid dodger magenta beige snow|Manufacturer#2|Brand#22|MEDIUM POLISHED NICKEL|8|JUMBO BOX|953.04|ut the warthog +6048|ivory saddle drab steel pink|Manufacturer#1|Brand#12|MEDIUM BURNISHED STEEL|34|SM PACK|954.04|oss the carefully exp +6049|khaki floral yellow lemon metallic|Manufacturer#5|Brand#55|MEDIUM POLISHED COPPER|17|LG PKG|955.04|uests use +6050|dark thistle orchid slate brown|Manufacturer#4|Brand#42|ECONOMY BRUSHED BRASS|7|JUMBO BAG|956.05|nding packages +6051|linen steel brown medium floral|Manufacturer#3|Brand#33|ECONOMY POLISHED STEEL|20|LG PKG|957.05|usual requests. regul +6052|almond purple burnished dim coral|Manufacturer#2|Brand#21|STANDARD PLATED BRASS|20|SM BOX|958.05| the quickly special +6053|puff chocolate snow sky pale|Manufacturer#2|Brand#24|PROMO BRUSHED TIN|10|MED CAN|959.05|tes. even, +6054|aquamarine antique firebrick saddle cornsilk|Manufacturer#2|Brand#24|MEDIUM ANODIZED COPPER|45|WRAP PACK|960.05|ecial +6055|gainsboro firebrick coral lace hot|Manufacturer#3|Brand#33|SMALL PLATED BRASS|25|MED BOX|961.05|ses are dolphins. qu +6056|green dark tomato blanched cornflower|Manufacturer#4|Brand#43|PROMO PLATED COPPER|42|WRAP CAN|962.05|s. furiously re +6057|cornflower lawn royal linen cyan|Manufacturer#4|Brand#44|STANDARD BURNISHED NICKEL|11|SM CASE|963.05|ly pend +6058|light tomato ivory white medium|Manufacturer#5|Brand#51|LARGE BRUSHED COPPER|21|WRAP CASE|964.05|o the slyly regula +6059|azure peach peru pale ghost|Manufacturer#3|Brand#33|STANDARD POLISHED NICKEL|15|SM BAG|965.05|sits affix around +6060|bisque firebrick antique sandy white|Manufacturer#3|Brand#35|ECONOMY POLISHED COPPER|6|JUMBO BOX|966.06|lyly re +6061|snow coral green midnight floral|Manufacturer#1|Brand#12|SMALL BRUSHED NICKEL|23|MED BOX|967.06|fully iron +6062|lace pink lavender frosted snow|Manufacturer#5|Brand#54|PROMO BURNISHED BRASS|11|JUMBO DRUM|968.06|al ideas use slyly +6063|pale plum aquamarine violet cornflower|Manufacturer#2|Brand#23|PROMO ANODIZED TIN|28|SM BAG|969.06|y unus +6064|dark navajo floral navy chocolate|Manufacturer#5|Brand#55|STANDARD PLATED NICKEL|2|SM BAG|970.06|es-- always regu +6065|royal sienna khaki frosted dim|Manufacturer#1|Brand#11|STANDARD BURNISHED BRASS|3|WRAP BAG|971.06|ronic Tiresias. e +6066|brown papaya seashell magenta burnished|Manufacturer#3|Brand#34|SMALL ANODIZED COPPER|24|JUMBO BOX|972.06| haggle caref +6067|spring sandy blue orange cyan|Manufacturer#4|Brand#43|MEDIUM PLATED BRASS|12|WRAP DRUM|973.06|ly carefully silent +6068|cyan sienna moccasin grey tan|Manufacturer#4|Brand#44|SMALL BURNISHED TIN|2|LG PKG|974.06|gedly regular platel +6069|gainsboro lime maroon cornflower olive|Manufacturer#2|Brand#22|STANDARD ANODIZED TIN|32|WRAP PKG|975.06|ding to t +6070|orange cornsilk khaki salmon snow|Manufacturer#3|Brand#33|MEDIUM POLISHED TIN|35|MED CAN|976.07|s boo +6071|burlywood pink lime turquoise orchid|Manufacturer#2|Brand#24|PROMO BRUSHED NICKEL|35|JUMBO PACK|977.07| maintain ag +6072|pink orange cornflower floral light|Manufacturer#4|Brand#44|SMALL BRUSHED NICKEL|46|MED BAG|978.07|sauternes +6073|cornsilk puff metallic cyan peru|Manufacturer#3|Brand#35|LARGE PLATED STEEL|18|WRAP BOX|979.07|nic instructions d +6074|puff cornflower bisque black khaki|Manufacturer#3|Brand#35|MEDIUM POLISHED STEEL|44|JUMBO CAN|980.07|equests after t +6075|wheat mint chartreuse papaya spring|Manufacturer#3|Brand#35|MEDIUM BRUSHED COPPER|17|WRAP BAG|981.07|unusual, regular +6076|thistle magenta green floral olive|Manufacturer#5|Brand#51|PROMO PLATED NICKEL|41|JUMBO BOX|982.07|ously iron +6077|peru ivory dim pink blush|Manufacturer#1|Brand#15|LARGE BRUSHED NICKEL|32|LG BAG|983.07|arefully. +6078|pale navy coral lace peach|Manufacturer#2|Brand#21|STANDARD BURNISHED NICKEL|23|LG PACK|984.07|y bold d +6079|olive hot magenta maroon thistle|Manufacturer#2|Brand#23|PROMO ANODIZED COPPER|13|MED BOX|985.07|as. express accounts +6080|coral red dim maroon green|Manufacturer#5|Brand#51|PROMO POLISHED NICKEL|44|WRAP CAN|986.08|al instructions wake +6081|blush puff midnight wheat navajo|Manufacturer#5|Brand#53|SMALL PLATED TIN|27|WRAP DRUM|987.08|sts. fluffily fi +6082|bisque blue burnished turquoise steel|Manufacturer#1|Brand#15|LARGE BURNISHED BRASS|34|MED PKG|988.08|lly even courts wake +6083|cyan slate dim purple sky|Manufacturer#2|Brand#25|LARGE ANODIZED COPPER|25|WRAP BAG|989.08|nal requests along +6084|gainsboro floral goldenrod rose papaya|Manufacturer#4|Brand#42|SMALL BURNISHED STEEL|42|SM PKG|990.08| dolphi +6085|blush burnished lime purple mint|Manufacturer#2|Brand#24|ECONOMY POLISHED NICKEL|29|WRAP PKG|991.08|foxes +6086|misty hot tomato gainsboro azure|Manufacturer#1|Brand#11|SMALL BURNISHED COPPER|30|JUMBO CAN|992.08|ly dogged accounts +6087|indian cornsilk khaki burlywood pale|Manufacturer#1|Brand#12|MEDIUM POLISHED BRASS|7|SM BAG|993.08|ly. ex +6088|slate wheat orange orchid chartreuse|Manufacturer#4|Brand#45|SMALL BURNISHED BRASS|8|WRAP PACK|994.08|ffix +6089|light royal green yellow dark|Manufacturer#5|Brand#52|PROMO BURNISHED STEEL|31|JUMBO BAG|995.08|ing excu +6090|turquoise thistle cornsilk forest linen|Manufacturer#4|Brand#42|MEDIUM ANODIZED NICKEL|26|LG BAG|996.09| accounts +6091|wheat violet saddle royal metallic|Manufacturer#5|Brand#51|ECONOMY PLATED COPPER|41|LG PACK|997.09|es. carefully pendin +6092|forest goldenrod deep maroon misty|Manufacturer#3|Brand#34|PROMO ANODIZED STEEL|22|JUMBO JAR|998.09|ns run f +6093|bisque antique cream gainsboro navajo|Manufacturer#4|Brand#43|LARGE ANODIZED BRASS|40|JUMBO CASE|999.09|g depende +6094|bisque frosted drab sky snow|Manufacturer#5|Brand#55|ECONOMY BRUSHED TIN|28|JUMBO BAG|1000.09|ess, pending requests +6095|green orchid dark misty moccasin|Manufacturer#1|Brand#14|ECONOMY BRUSHED STEEL|30|JUMBO JAR|1001.09|. furiously +6096|khaki gainsboro black firebrick royal|Manufacturer#3|Brand#31|SMALL BURNISHED BRASS|30|MED CAN|1002.09|nd the blithely +6097|chocolate violet gainsboro smoke puff|Manufacturer#3|Brand#31|PROMO ANODIZED NICKEL|17|SM CASE|1003.09|cajole blithely +6098|ghost chocolate steel moccasin goldenrod|Manufacturer#1|Brand#13|MEDIUM BRUSHED NICKEL|26|MED PKG|1004.09|. daringly +6099|royal green plum honeydew medium|Manufacturer#2|Brand#25|LARGE BURNISHED STEEL|11|LG PACK|1005.09|ng packages hag +6100|papaya yellow chocolate sky indian|Manufacturer#5|Brand#55|MEDIUM PLATED NICKEL|20|LG BOX|1006.10|ns integrate. regu +6101|goldenrod rosy metallic plum seashell|Manufacturer#2|Brand#25|PROMO ANODIZED COPPER|34|MED BAG|1007.10|. furiously +6102|rosy yellow violet sienna snow|Manufacturer#5|Brand#51|ECONOMY ANODIZED BRASS|50|SM BOX|1008.10|ts are. c +6103|olive mint deep dodger bisque|Manufacturer#4|Brand#44|STANDARD ANODIZED BRASS|8|WRAP PKG|1009.10|leep blith +6104|aquamarine bisque cornflower cyan pale|Manufacturer#5|Brand#52|SMALL BRUSHED STEEL|37|WRAP JAR|1010.10|gedly a +6105|goldenrod cornflower light sandy rosy|Manufacturer#4|Brand#42|MEDIUM BRUSHED TIN|14|MED BAG|1011.10|ns. regular ideas +6106|lace pale dark blush frosted|Manufacturer#3|Brand#35|LARGE ANODIZED COPPER|26|SM BOX|1012.10|ccounts doze careful +6107|dim chartreuse brown salmon antique|Manufacturer#4|Brand#42|ECONOMY ANODIZED TIN|40|MED BOX|1013.10|are carefully among th +6108|cream medium rosy navy brown|Manufacturer#5|Brand#54|SMALL PLATED COPPER|42|SM CAN|1014.10| ironic requests inte +6109|saddle lawn goldenrod yellow dark|Manufacturer#1|Brand#13|STANDARD PLATED COPPER|19|SM PKG|1015.10|y among th +6110|chiffon snow ivory blanched cream|Manufacturer#1|Brand#12|SMALL BURNISHED NICKEL|42|LG JAR|1016.11|ual requests-- fluffi +6111|deep yellow dark lawn antique|Manufacturer#5|Brand#52|PROMO BRUSHED TIN|18|SM JAR|1017.11|tain above the +6112|metallic dark indian brown chartreuse|Manufacturer#4|Brand#44|ECONOMY ANODIZED NICKEL|30|MED PACK|1018.11|equests amo +6113|peach purple puff beige spring|Manufacturer#4|Brand#45|PROMO PLATED COPPER|10|JUMBO PKG|1019.11|he slyly ironic +6114|pale powder chartreuse lime moccasin|Manufacturer#4|Brand#41|STANDARD BRUSHED BRASS|41|LG CASE|1020.11|thely s +6115|chiffon rose plum puff peach|Manufacturer#1|Brand#11|ECONOMY BURNISHED STEEL|33|SM JAR|1021.11|n, unus +6116|burnished khaki wheat sienna violet|Manufacturer#5|Brand#54|PROMO BRUSHED TIN|43|LG BOX|1022.11|ing acc +6117|brown dim lace honeydew burlywood|Manufacturer#5|Brand#51|STANDARD PLATED COPPER|13|SM JAR|1023.11|sual instructions. +6118|rose violet linen burnished frosted|Manufacturer#3|Brand#32|ECONOMY ANODIZED STEEL|37|LG BOX|1024.11|ly acr +6119|royal almond magenta puff navy|Manufacturer#3|Brand#32|MEDIUM BURNISHED BRASS|36|LG BAG|1025.11|atelets. quickly regul +6120|peach white puff dim yellow|Manufacturer#2|Brand#23|ECONOMY ANODIZED COPPER|28|MED BAG|1026.12|bold instructions. +6121|sky papaya bisque gainsboro aquamarine|Manufacturer#1|Brand#13|MEDIUM BRUSHED TIN|29|LG DRUM|1027.12|ly pending pinto b +6122|tomato drab misty grey medium|Manufacturer#5|Brand#55|ECONOMY PLATED NICKEL|41|JUMBO BAG|1028.12|sublate furi +6123|cornsilk sandy khaki indian lawn|Manufacturer#3|Brand#33|PROMO POLISHED STEEL|23|JUMBO CAN|1029.12|bove +6124|red papaya lime cornsilk maroon|Manufacturer#1|Brand#13|SMALL ANODIZED TIN|15|MED DRUM|1030.12|efully fi +6125|ghost cornflower forest indian antique|Manufacturer#4|Brand#44|ECONOMY BURNISHED BRASS|34|MED BAG|1031.12|ve the express pint +6126|yellow smoke cyan khaki steel|Manufacturer#5|Brand#55|MEDIUM PLATED NICKEL|20|WRAP BOX|1032.12|of the blithel +6127|dim lavender thistle magenta sienna|Manufacturer#3|Brand#35|STANDARD BURNISHED TIN|15|WRAP PKG|1033.12| bold deposits ca +6128|sandy tomato light cream midnight|Manufacturer#2|Brand#24|LARGE POLISHED COPPER|8|SM JAR|1034.12|ans integrate quickl +6129|grey cyan sky seashell light|Manufacturer#4|Brand#43|LARGE POLISHED TIN|44|MED JAR|1035.12| should boos +6130|coral azure chartreuse tomato turquoise|Manufacturer#3|Brand#31|MEDIUM BURNISHED STEEL|9|WRAP PACK|1036.13|ggle furiousl +6131|coral brown forest puff lemon|Manufacturer#1|Brand#11|ECONOMY POLISHED NICKEL|1|WRAP BAG|1037.13|es must nag across the +6132|spring lime beige chiffon ghost|Manufacturer#1|Brand#13|MEDIUM PLATED COPPER|41|SM DRUM|1038.13|eas among the slyl +6133|turquoise goldenrod coral hot chartreuse|Manufacturer#3|Brand#32|STANDARD ANODIZED NICKEL|32|LG BOX|1039.13|ully special +6134|brown steel magenta blush sky|Manufacturer#4|Brand#42|LARGE BURNISHED NICKEL|18|MED CAN|1040.13|uests dazzle +6135|cream yellow puff lavender almond|Manufacturer#4|Brand#44|LARGE BURNISHED BRASS|48|JUMBO JAR|1041.13|riously regular +6136|slate peach moccasin mint forest|Manufacturer#4|Brand#41|ECONOMY POLISHED COPPER|16|LG BAG|1042.13|ar pinto +6137|snow misty honeydew thistle ivory|Manufacturer#1|Brand#11|ECONOMY PLATED COPPER|19|JUMBO DRUM|1043.13|riously +6138|forest black deep mint navy|Manufacturer#1|Brand#11|MEDIUM BRUSHED COPPER|8|SM JAR|1044.13|ges play after t +6139|rose lavender snow forest cream|Manufacturer#4|Brand#45|ECONOMY BRUSHED STEEL|4|JUMBO CASE|1045.13|es. asympt +6140|almond medium midnight cornflower beige|Manufacturer#2|Brand#24|SMALL PLATED NICKEL|6|MED CASE|1046.14|equests +6141|purple honeydew midnight lavender red|Manufacturer#3|Brand#35|STANDARD POLISHED TIN|32|SM BOX|1047.14|ole carefully speci +6142|drab deep ivory ghost lace|Manufacturer#2|Brand#23|SMALL BURNISHED NICKEL|30|MED JAR|1048.14|endencies sleep furio +6143|lawn peru medium maroon blue|Manufacturer#1|Brand#12|ECONOMY ANODIZED BRASS|8|LG BAG|1049.14|equests. fluffily +6144|burlywood grey sky sienna gainsboro|Manufacturer#1|Brand#12|STANDARD BURNISHED STEEL|33|WRAP DRUM|1050.14|erns are. sl +6145|dodger peru metallic ghost cornsilk|Manufacturer#1|Brand#15|STANDARD PLATED BRASS|30|WRAP CASE|1051.14|etly ironic accounts. +6146|pink powder white firebrick smoke|Manufacturer#3|Brand#34|SMALL BURNISHED NICKEL|37|JUMBO CASE|1052.14|rhorses wake. caref +6147|yellow bisque cream light medium|Manufacturer#5|Brand#54|ECONOMY POLISHED BRASS|34|MED BOX|1053.14|ously r +6148|sienna spring turquoise almond orange|Manufacturer#3|Brand#34|PROMO BRUSHED STEEL|50|LG PACK|1054.14|y silent +6149|deep papaya blanched honeydew snow|Manufacturer#3|Brand#35|ECONOMY BRUSHED TIN|50|MED CAN|1055.14|coys. +6150|orange powder tomato lemon brown|Manufacturer#1|Brand#11|STANDARD ANODIZED TIN|26|SM PKG|1056.15| blithe do +6151|floral ivory cyan sienna pale|Manufacturer#4|Brand#42|LARGE BRUSHED NICKEL|7|JUMBO CASE|1057.15|hins should cajole. +6152|burnished chiffon cornsilk linen orange|Manufacturer#3|Brand#32|PROMO BURNISHED TIN|42|WRAP PKG|1058.15|ly. unusua +6153|almond orange indian ghost chocolate|Manufacturer#2|Brand#23|MEDIUM BURNISHED COPPER|25|MED BAG|1059.15|instr +6154|lavender metallic black chiffon orchid|Manufacturer#5|Brand#54|PROMO PLATED BRASS|1|LG DRUM|1060.15|ss, express accoun +6155|cyan orange yellow papaya moccasin|Manufacturer#5|Brand#52|PROMO ANODIZED COPPER|2|JUMBO CAN|1061.15|es affi +6156|red maroon lavender burnished brown|Manufacturer#3|Brand#34|PROMO BRUSHED STEEL|36|SM PKG|1062.15|nal instructions +6157|blanched ghost deep sky red|Manufacturer#2|Brand#21|MEDIUM ANODIZED NICKEL|38|JUMBO CASE|1063.15|s wake +6158|navajo peach pink orchid midnight|Manufacturer#3|Brand#34|STANDARD POLISHED STEEL|13|WRAP PACK|1064.15|lly b +6159|orchid salmon tomato honeydew indian|Manufacturer#3|Brand#34|LARGE POLISHED STEEL|15|JUMBO DRUM|1065.15|cording to the final, +6160|navy navajo gainsboro chocolate pale|Manufacturer#2|Brand#22|SMALL POLISHED TIN|40|LG BAG|1066.16|ithely ironic +6161|smoke medium green gainsboro violet|Manufacturer#2|Brand#22|STANDARD PLATED STEEL|12|MED JAR|1067.16| fluffily. slyly +6162|seashell dim snow saddle grey|Manufacturer#3|Brand#32|STANDARD ANODIZED COPPER|16|JUMBO BAG|1068.16|hely slyly regu +6163|linen ghost dodger drab burlywood|Manufacturer#1|Brand#11|MEDIUM BURNISHED TIN|1|WRAP BOX|1069.16|t, final foxes cajo +6164|white drab saddle snow purple|Manufacturer#1|Brand#14|PROMO BRUSHED TIN|8|JUMBO BAG|1070.16|sly slow pearls wake +6165|frosted moccasin red orchid khaki|Manufacturer#1|Brand#12|SMALL ANODIZED BRASS|44|JUMBO JAR|1071.16|carefully b +6166|indian orange orchid turquoise blush|Manufacturer#4|Brand#45|MEDIUM PLATED NICKEL|25|WRAP PACK|1072.16|ven pinto b +6167|lawn seashell cornflower coral indian|Manufacturer#5|Brand#54|SMALL PLATED COPPER|16|LG BOX|1073.16|packages mold slyly r +6168|midnight plum blue spring floral|Manufacturer#1|Brand#14|STANDARD BURNISHED BRASS|12|JUMBO BOX|1074.16|ideas affix +6169|dim violet sienna bisque saddle|Manufacturer#4|Brand#43|STANDARD PLATED BRASS|26|LG PKG|1075.16|even accounts boost. f +6170|honeydew yellow deep blanched smoke|Manufacturer#3|Brand#31|LARGE BRUSHED BRASS|5|LG DRUM|1076.17| fluffily ab +6171|peru light sandy sky antique|Manufacturer#4|Brand#42|ECONOMY ANODIZED STEEL|48|JUMBO JAR|1077.17| along the c +6172|khaki rose dodger metallic orange|Manufacturer#5|Brand#54|PROMO BRUSHED COPPER|34|JUMBO CAN|1078.17|ests integrate +6173|rosy mint cream pale lavender|Manufacturer#4|Brand#43|SMALL PLATED STEEL|10|WRAP BOX|1079.17|ang slyly of +6174|dark seashell spring lavender sienna|Manufacturer#2|Brand#25|SMALL BRUSHED STEEL|8|JUMBO DRUM|1080.17|onic, ironic requests +6175|plum olive papaya purple orange|Manufacturer#1|Brand#15|STANDARD POLISHED TIN|43|SM JAR|1081.17|y against the slyly p +6176|tomato cyan chartreuse sky navy|Manufacturer#5|Brand#55|SMALL BRUSHED STEEL|47|SM CAN|1082.17|ully care +6177|ghost peach turquoise goldenrod spring|Manufacturer#5|Brand#51|ECONOMY BURNISHED COPPER|45|SM CASE|1083.17|ids integrate sil +6178|blush aquamarine black moccasin slate|Manufacturer#3|Brand#33|STANDARD POLISHED COPPER|46|JUMBO PKG|1084.17|ial instructions +6179|beige dark peru moccasin brown|Manufacturer#3|Brand#33|LARGE ANODIZED STEEL|3|LG PKG|1085.17|nts of the unu +6180|mint gainsboro powder maroon royal|Manufacturer#2|Brand#21|MEDIUM POLISHED BRASS|14|LG BOX|1086.18|e carefully unusual th +6181|brown mint drab lemon orange|Manufacturer#2|Brand#23|ECONOMY POLISHED COPPER|8|WRAP BAG|1087.18|ans cajole. +6182|burlywood light dodger honeydew cyan|Manufacturer#3|Brand#34|MEDIUM BRUSHED NICKEL|5|LG BOX|1088.18|ly inside the pla +6183|sienna sandy aquamarine cornsilk deep|Manufacturer#5|Brand#52|SMALL BRUSHED STEEL|39|WRAP BAG|1089.18|ly ironic accounts int +6184|dark orchid blush goldenrod khaki|Manufacturer#5|Brand#55|LARGE PLATED BRASS|15|MED JAR|1090.18|fully final +6185|light snow tan cornsilk misty|Manufacturer#4|Brand#41|STANDARD POLISHED COPPER|39|LG BOX|1091.18|ts bo +6186|antique burnished moccasin cornflower light|Manufacturer#1|Brand#13|LARGE BRUSHED NICKEL|29|LG JAR|1092.18| careful +6187|black burnished cornflower light saddle|Manufacturer#1|Brand#11|LARGE PLATED STEEL|5|JUMBO BAG|1093.18|sits. +6188|indian steel magenta misty olive|Manufacturer#2|Brand#23|SMALL BRUSHED STEEL|13|MED CASE|1094.18| beans boost. r +6189|chocolate midnight deep papaya salmon|Manufacturer#5|Brand#55|SMALL BURNISHED COPPER|29|JUMBO CASE|1095.18|bold foxes wake +6190|chiffon slate navy orchid almond|Manufacturer#4|Brand#43|PROMO BURNISHED COPPER|4|WRAP BOX|1096.19|e fluffily a +6191|papaya cyan purple aquamarine ghost|Manufacturer#4|Brand#43|STANDARD BURNISHED STEEL|4|SM BAG|1097.19|ts. idl +6192|frosted medium mint light drab|Manufacturer#5|Brand#52|PROMO POLISHED BRASS|1|MED PACK|1098.19|s. express pl +6193|aquamarine thistle green almond spring|Manufacturer#4|Brand#45|MEDIUM POLISHED COPPER|38|MED BOX|1099.19|gside of the ruthless, +6194|gainsboro violet pink blanched royal|Manufacturer#1|Brand#11|LARGE BURNISHED COPPER|24|WRAP CAN|1100.19| foxes cajole. s +6195|violet tan salmon moccasin linen|Manufacturer#4|Brand#45|LARGE ANODIZED NICKEL|10|SM JAR|1101.19|ular theodolites. r +6196|cream maroon metallic orange peru|Manufacturer#4|Brand#43|ECONOMY POLISHED TIN|48|MED JAR|1102.19|d, unu +6197|violet saddle cyan orange ivory|Manufacturer#4|Brand#44|SMALL POLISHED STEEL|27|MED JAR|1103.19|gular pinto beans nag +6198|saddle cyan mint linen turquoise|Manufacturer#3|Brand#32|LARGE POLISHED NICKEL|33|JUMBO CASE|1104.19|accounts across t +6199|chartreuse snow saddle ghost medium|Manufacturer#1|Brand#12|LARGE BURNISHED STEEL|18|MED JAR|1105.19|r courts. sl +6200|sky indian lavender coral midnight|Manufacturer#4|Brand#41|ECONOMY BURNISHED COPPER|25|JUMBO BAG|1106.20|ccounts are deposits. +6201|orchid sky frosted yellow lemon|Manufacturer#2|Brand#25|LARGE ANODIZED STEEL|46|SM CAN|1107.20|ole carefully sile +6202|cornsilk metallic sky puff papaya|Manufacturer#5|Brand#53|PROMO BRUSHED BRASS|45|WRAP PACK|1108.20|courts +6203|navy plum linen gainsboro midnight|Manufacturer#5|Brand#54|MEDIUM BRUSHED COPPER|50|WRAP DRUM|1109.20| tithes. furiously ev +6204|hot gainsboro beige rosy chiffon|Manufacturer#5|Brand#51|SMALL PLATED COPPER|40|LG CASE|1110.20|ecial depos +6205|antique gainsboro floral puff blush|Manufacturer#1|Brand#13|LARGE ANODIZED BRASS|16|SM PKG|1111.20|ar requests sleep abov +6206|salmon sandy floral khaki mint|Manufacturer#3|Brand#31|SMALL ANODIZED BRASS|35|LG JAR|1112.20|refully final +6207|antique goldenrod rosy metallic cornsilk|Manufacturer#4|Brand#42|STANDARD POLISHED NICKEL|45|MED PKG|1113.20|nal packa +6208|bisque light saddle black sandy|Manufacturer#1|Brand#11|PROMO BRUSHED TIN|17|SM CAN|1114.20|y unusual deposits a +6209|maroon sienna peach tomato deep|Manufacturer#2|Brand#25|MEDIUM PLATED BRASS|47|JUMBO DRUM|1115.20|ial theodoli +6210|lime lavender grey chiffon burlywood|Manufacturer#5|Brand#51|MEDIUM ANODIZED TIN|9|MED BAG|1116.21|ons lose +6211|orange cyan light beige chiffon|Manufacturer#4|Brand#42|STANDARD POLISHED NICKEL|2|SM JAR|1117.21|ss asymptot +6212|lace medium burnished peach tan|Manufacturer#2|Brand#25|LARGE POLISHED BRASS|9|SM BAG|1118.21|lithely sly +6213|steel snow slate papaya dark|Manufacturer#3|Brand#35|MEDIUM ANODIZED BRASS|15|LG BAG|1119.21|across the furiously +6214|floral spring light firebrick blush|Manufacturer#5|Brand#55|MEDIUM PLATED NICKEL|42|MED CASE|1120.21|ideas. accou +6215|midnight cornflower cornsilk brown antique|Manufacturer#3|Brand#35|STANDARD POLISHED TIN|28|LG JAR|1121.21|e fluffi +6216|forest beige red blush deep|Manufacturer#5|Brand#51|MEDIUM BRUSHED BRASS|47|MED JAR|1122.21|ly about the furiou +6217|aquamarine peru chartreuse green pink|Manufacturer#4|Brand#43|PROMO POLISHED STEEL|36|LG JAR|1123.21|egular pinto beans caj +6218|powder coral olive maroon lace|Manufacturer#3|Brand#33|STANDARD ANODIZED NICKEL|8|WRAP BOX|1124.21|ounts must +6219|honeydew wheat chartreuse drab sky|Manufacturer#4|Brand#44|ECONOMY ANODIZED NICKEL|37|LG PKG|1125.21|nic de +6220|purple light misty frosted puff|Manufacturer#5|Brand#54|LARGE PLATED NICKEL|18|SM BAG|1126.22|ly iron +6221|chartreuse rosy peach tan goldenrod|Manufacturer#4|Brand#41|STANDARD ANODIZED NICKEL|42|MED PKG|1127.22|lly final idea +6222|yellow lemon blush beige light|Manufacturer#2|Brand#25|SMALL POLISHED TIN|16|LG JAR|1128.22| quickly expre +6223|bisque sienna drab yellow almond|Manufacturer#3|Brand#32|PROMO POLISHED COPPER|40|SM BAG|1129.22|lly ironic th +6224|sky dim orchid snow pink|Manufacturer#5|Brand#53|LARGE BRUSHED NICKEL|23|LG PKG|1130.22|realms nag carefu +6225|red cyan green dodger burnished|Manufacturer#5|Brand#54|LARGE BRUSHED STEEL|9|JUMBO BAG|1131.22|usly unusual +6226|drab black tomato pink almond|Manufacturer#3|Brand#34|LARGE ANODIZED TIN|18|JUMBO CAN|1132.22|ls. foxes i +6227|sienna firebrick misty linen sandy|Manufacturer#4|Brand#42|ECONOMY POLISHED TIN|40|LG CASE|1133.22|lly regular theodolit +6228|frosted burlywood dodger red aquamarine|Manufacturer#1|Brand#13|PROMO PLATED STEEL|16|LG BOX|1134.22|d excuses c +6229|bisque white khaki honeydew azure|Manufacturer#4|Brand#43|PROMO BRUSHED BRASS|29|WRAP PKG|1135.22|lar fo +6230|powder navajo linen salmon turquoise|Manufacturer#2|Brand#22|SMALL POLISHED COPPER|35|SM PACK|1136.23|ickly express i +6231|green dodger almond gainsboro indian|Manufacturer#2|Brand#21|PROMO ANODIZED STEEL|20|MED PACK|1137.23| even accounts m +6232|blanched linen cream almond orange|Manufacturer#1|Brand#11|MEDIUM ANODIZED BRASS|30|LG JAR|1138.23|unusual, regular acco +6233|blush floral bisque dodger drab|Manufacturer#3|Brand#33|ECONOMY BURNISHED BRASS|49|JUMBO BOX|1139.23| the final foxes s +6234|green steel grey olive thistle|Manufacturer#4|Brand#45|STANDARD BURNISHED BRASS|50|LG PACK|1140.23|phins wake caref +6235|white tomato goldenrod wheat grey|Manufacturer#2|Brand#25|SMALL PLATED TIN|50|WRAP PACK|1141.23|packages boost +6236|misty lace metallic ivory pink|Manufacturer#4|Brand#45|ECONOMY BRUSHED NICKEL|41|MED PKG|1142.23|onic grouches detect +6237|firebrick white papaya sandy magenta|Manufacturer#1|Brand#14|ECONOMY PLATED TIN|15|SM PKG|1143.23|y after the +6238|powder lace deep lime steel|Manufacturer#1|Brand#15|LARGE ANODIZED TIN|30|MED PACK|1144.23|under the final cour +6239|chocolate spring wheat lawn tan|Manufacturer#5|Brand#51|LARGE BURNISHED STEEL|8|SM JAR|1145.23|y regular multipliers +6240|chartreuse grey thistle azure moccasin|Manufacturer#2|Brand#22|MEDIUM ANODIZED STEEL|34|JUMBO CAN|1146.24|y eve +6241|misty cornflower plum slate medium|Manufacturer#1|Brand#14|SMALL ANODIZED TIN|23|WRAP JAR|1147.24|ptotes across the eve +6242|linen powder brown lace red|Manufacturer#2|Brand#22|PROMO POLISHED STEEL|14|MED BAG|1148.24|ly regular the +6243|royal blush forest papaya navajo|Manufacturer#5|Brand#53|SMALL POLISHED TIN|1|SM CASE|1149.24|he express, reg +6244|azure plum magenta rosy sandy|Manufacturer#5|Brand#55|SMALL ANODIZED TIN|35|LG CAN|1150.24|lly express packages +6245|almond burnished beige peru brown|Manufacturer#1|Brand#12|STANDARD PLATED BRASS|38|WRAP PKG|1151.24|al platele +6246|aquamarine azure smoke lime rose|Manufacturer#4|Brand#44|PROMO PLATED BRASS|47|MED BOX|1152.24|y iro +6247|rose yellow chiffon lemon thistle|Manufacturer#3|Brand#33|LARGE PLATED BRASS|18|MED BOX|1153.24|ong the unusual acco +6248|orange goldenrod chocolate papaya smoke|Manufacturer#3|Brand#35|SMALL POLISHED NICKEL|29|MED PKG|1154.24|efully stealthy req +6249|metallic chiffon ghost goldenrod salmon|Manufacturer#4|Brand#42|MEDIUM BRUSHED BRASS|25|JUMBO BOX|1155.24|e unusua +6250|navajo lace slate steel purple|Manufacturer#3|Brand#34|PROMO BURNISHED NICKEL|2|MED DRUM|1156.25| requests. blithel +6251|lemon gainsboro khaki lavender ivory|Manufacturer#3|Brand#34|PROMO POLISHED BRASS|40|SM BOX|1157.25|egular, unusual re +6252|salmon peach chocolate sky blush|Manufacturer#2|Brand#23|MEDIUM ANODIZED STEEL|45|SM CAN|1158.25|ong the deposits. +6253|seashell navajo snow sky grey|Manufacturer#2|Brand#21|STANDARD BRUSHED STEEL|18|LG CASE|1159.25|uffily ironic +6254|dark tan beige black moccasin|Manufacturer#3|Brand#32|SMALL BRUSHED BRASS|17|WRAP DRUM|1160.25|ular acc +6255|misty olive saddle peach navajo|Manufacturer#5|Brand#55|LARGE BURNISHED BRASS|38|LG PKG|1161.25|ymptotes about the fr +6256|steel lace lavender hot tomato|Manufacturer#3|Brand#33|ECONOMY ANODIZED STEEL|21|LG PACK|1162.25|sly pending gifts ha +6257|tan smoke azure rosy firebrick|Manufacturer#2|Brand#25|ECONOMY ANODIZED NICKEL|22|SM BOX|1163.25|wake. ironic pearls i +6258|red plum tan snow navajo|Manufacturer#5|Brand#55|ECONOMY PLATED STEEL|48|JUMBO BAG|1164.25|eposits. ironic, +6259|chartreuse cream saddle hot spring|Manufacturer#3|Brand#35|STANDARD ANODIZED TIN|33|WRAP PKG|1165.25|ly ironic ideas will +6260|dark cornsilk thistle cornflower saddle|Manufacturer#1|Brand#11|LARGE PLATED STEEL|23|SM PACK|1166.26|ss requests sleep fl +6261|khaki pale blush turquoise mint|Manufacturer#2|Brand#25|ECONOMY BURNISHED COPPER|11|MED PACK|1167.26|ns wake regu +6262|goldenrod aquamarine forest beige purple|Manufacturer#1|Brand#11|MEDIUM POLISHED STEEL|28|WRAP PKG|1168.26|le. pinto beans d +6263|saddle cornsilk aquamarine coral magenta|Manufacturer#5|Brand#52|STANDARD BRUSHED COPPER|14|MED PACK|1169.26|s haggle final pinto +6264|khaki ghost azure antique red|Manufacturer#2|Brand#21|ECONOMY POLISHED TIN|1|WRAP PKG|1170.26|heodolite +6265|lawn lemon indian thistle firebrick|Manufacturer#1|Brand#12|PROMO PLATED COPPER|27|SM PACK|1171.26|ons are careful +6266|powder lace indian rose brown|Manufacturer#1|Brand#13|ECONOMY BURNISHED BRASS|38|SM CAN|1172.26|iously. final instr +6267|azure sky peach slate frosted|Manufacturer#3|Brand#35|ECONOMY POLISHED STEEL|13|WRAP DRUM|1173.26|. carefully b +6268|spring puff coral sandy drab|Manufacturer#1|Brand#11|MEDIUM ANODIZED TIN|17|LG CASE|1174.26|es. fi +6269|navajo saddle thistle papaya black|Manufacturer#3|Brand#31|LARGE ANODIZED NICKEL|41|LG PKG|1175.26|g the +6270|wheat coral chiffon puff blanched|Manufacturer#3|Brand#34|STANDARD BURNISHED STEEL|28|LG BOX|1176.27|l deposits cajole ca +6271|azure sandy blue dodger honeydew|Manufacturer#5|Brand#52|LARGE BURNISHED NICKEL|42|JUMBO JAR|1177.27|onic platelets above +6272|blue floral forest steel salmon|Manufacturer#3|Brand#32|SMALL BRUSHED COPPER|20|JUMBO DRUM|1178.27|among the carefully re +6273|ghost saddle black seashell moccasin|Manufacturer#5|Brand#52|ECONOMY PLATED TIN|26|WRAP BAG|1179.27|inal +6274|lace azure blush wheat frosted|Manufacturer#2|Brand#24|MEDIUM BURNISHED STEEL|18|WRAP DRUM|1180.27|o the even grouches +6275|gainsboro ghost tan rosy ivory|Manufacturer#1|Brand#13|MEDIUM PLATED STEEL|10|SM DRUM|1181.27|foxes. f +6276|khaki slate red frosted snow|Manufacturer#5|Brand#53|SMALL ANODIZED TIN|47|WRAP JAR|1182.27|sts dazzle blit +6277|black forest orange pink medium|Manufacturer#1|Brand#11|SMALL POLISHED TIN|18|LG BAG|1183.27|ily fi +6278|saddle navy orchid forest olive|Manufacturer#5|Brand#54|STANDARD PLATED BRASS|23|WRAP PKG|1184.27|nts. sl +6279|steel ivory blush chiffon cornsilk|Manufacturer#4|Brand#41|SMALL BURNISHED STEEL|15|JUMBO PACK|1185.27|elets +6280|azure antique thistle dark pink|Manufacturer#1|Brand#11|LARGE ANODIZED COPPER|1|MED CASE|1186.28|he regular, regu +6281|tomato honeydew lawn black orange|Manufacturer#3|Brand#33|LARGE BRUSHED BRASS|4|JUMBO PKG|1187.28|deposits haggle +6282|navajo linen dodger honeydew misty|Manufacturer#5|Brand#51|MEDIUM BRUSHED STEEL|3|LG PKG|1188.28|y. even req +6283|puff dim sandy chocolate snow|Manufacturer#5|Brand#52|PROMO ANODIZED NICKEL|50|WRAP CASE|1189.28|ecial orbits bo +6284|maroon spring dodger black blush|Manufacturer#3|Brand#33|MEDIUM PLATED BRASS|38|LG CAN|1190.28|deposits +6285|steel plum mint purple green|Manufacturer#2|Brand#23|STANDARD PLATED STEEL|1|MED PKG|1191.28|nder +6286|wheat pale thistle chartreuse brown|Manufacturer#3|Brand#32|PROMO BRUSHED BRASS|21|JUMBO BOX|1192.28|s. sl +6287|frosted peru bisque powder hot|Manufacturer#5|Brand#55|SMALL PLATED COPPER|49|WRAP DRUM|1193.28|anent deposits haggle +6288|yellow lawn pink peach mint|Manufacturer#2|Brand#21|PROMO BRUSHED TIN|27|MED DRUM|1194.28|the slyly pending the +6289|beige aquamarine dodger chiffon black|Manufacturer#4|Brand#45|MEDIUM BURNISHED BRASS|38|SM BAG|1195.28|s. final, even requ +6290|orange black tomato powder purple|Manufacturer#2|Brand#24|LARGE ANODIZED STEEL|44|WRAP CASE|1196.29|ts boost car +6291|burnished powder chiffon orange wheat|Manufacturer#3|Brand#34|MEDIUM BURNISHED NICKEL|39|WRAP CAN|1197.29|eaves sle +6292|bisque brown moccasin snow maroon|Manufacturer#4|Brand#44|PROMO PLATED BRASS|28|MED DRUM|1198.29|ugouts. final accounts +6293|floral azure brown blue tomato|Manufacturer#5|Brand#54|PROMO BRUSHED COPPER|28|MED CASE|1199.29|dependencies. even +6294|metallic magenta aquamarine midnight linen|Manufacturer#4|Brand#44|MEDIUM POLISHED TIN|44|SM BOX|1200.29|excuses above the +6295|blanched cyan turquoise saddle white|Manufacturer#4|Brand#43|LARGE BRUSHED BRASS|40|SM BAG|1201.29|kly fluffily unusual +6296|coral metallic yellow plum goldenrod|Manufacturer#1|Brand#13|PROMO BRUSHED NICKEL|47|MED BOX|1202.29|cial deposits d +6297|steel burnished dodger cornflower coral|Manufacturer#4|Brand#45|ECONOMY POLISHED TIN|2|JUMBO DRUM|1203.29|ly unusual theodol +6298|cornsilk sky violet green burnished|Manufacturer#3|Brand#35|MEDIUM POLISHED NICKEL|47|SM BAG|1204.29|tes. furiously pend +6299|antique wheat blue seashell hot|Manufacturer#3|Brand#34|PROMO BRUSHED STEEL|43|JUMBO JAR|1205.29|totes. regularly +6300|navy black cornflower white aquamarine|Manufacturer#4|Brand#41|LARGE POLISHED BRASS|10|JUMBO BAG|1206.30|quests haggle +6301|blush ghost azure peach lemon|Manufacturer#4|Brand#45|LARGE ANODIZED BRASS|8|LG CAN|1207.30| pinto b +6302|lace frosted mint misty cream|Manufacturer#4|Brand#42|LARGE PLATED TIN|28|LG JAR|1208.30|blithely even instru +6303|dark powder almond honeydew burnished|Manufacturer#1|Brand#11|SMALL ANODIZED STEEL|46|JUMBO BOX|1209.30|ckages; +6304|chocolate dodger coral maroon beige|Manufacturer#2|Brand#21|MEDIUM BURNISHED BRASS|8|JUMBO DRUM|1210.30|ackages cajole at th +6305|white metallic hot antique olive|Manufacturer#3|Brand#33|ECONOMY BURNISHED COPPER|11|MED PKG|1211.30|ing packages +6306|navajo papaya metallic antique tan|Manufacturer#5|Brand#54|SMALL BRUSHED COPPER|5|WRAP PKG|1212.30|ound the care +6307|orchid magenta papaya cornflower wheat|Manufacturer#5|Brand#52|PROMO ANODIZED STEEL|25|JUMBO CAN|1213.30|kages. caref +6308|seashell red medium violet misty|Manufacturer#2|Brand#22|ECONOMY BRUSHED BRASS|14|LG CAN|1214.30|lose requests. s +6309|hot gainsboro cornflower chartreuse chiffon|Manufacturer#4|Brand#44|PROMO BRUSHED NICKEL|22|SM BOX|1215.30|realms cajole fu +6310|brown cream olive black goldenrod|Manufacturer#4|Brand#44|STANDARD ANODIZED TIN|12|WRAP PKG|1216.31|bout the +6311|rose misty ghost burlywood blush|Manufacturer#2|Brand#25|PROMO PLATED NICKEL|6|LG BOX|1217.31|ully even accounts +6312|burnished smoke metallic mint purple|Manufacturer#2|Brand#24|LARGE BURNISHED COPPER|48|JUMBO CAN|1218.31|ccounts-- sly +6313|yellow salmon gainsboro beige lace|Manufacturer#1|Brand#14|SMALL BURNISHED STEEL|27|LG CAN|1219.31|gular inst +6314|white turquoise plum goldenrod smoke|Manufacturer#5|Brand#51|MEDIUM PLATED TIN|3|LG CAN|1220.31|ake after the sly +6315|purple olive slate pale rosy|Manufacturer#5|Brand#51|LARGE PLATED COPPER|20|JUMBO PKG|1221.31|ecial a +6316|light peach wheat medium orange|Manufacturer#2|Brand#22|LARGE ANODIZED TIN|29|MED DRUM|1222.31|phs. iro +6317|orchid snow maroon ghost smoke|Manufacturer#2|Brand#22|PROMO BRUSHED NICKEL|34|WRAP JAR|1223.31|en accounts. +6318|dim indian coral seashell tomato|Manufacturer#5|Brand#54|ECONOMY BRUSHED COPPER|43|JUMBO BOX|1224.31|dolites. slyly iro +6319|tan pink salmon lavender spring|Manufacturer#2|Brand#23|PROMO BURNISHED COPPER|29|JUMBO CAN|1225.31|sits after the caref +6320|smoke orange purple white dark|Manufacturer#2|Brand#24|ECONOMY BRUSHED COPPER|21|MED BAG|1226.32|nly. furiously unu +6321|green medium goldenrod yellow honeydew|Manufacturer#2|Brand#23|LARGE PLATED COPPER|3|JUMBO PACK|1227.32|ts sleep along +6322|yellow violet medium firebrick turquoise|Manufacturer#5|Brand#52|ECONOMY POLISHED TIN|16|WRAP CAN|1228.32|y final foxes. bli +6323|aquamarine linen moccasin coral medium|Manufacturer#3|Brand#35|MEDIUM POLISHED BRASS|13|JUMBO PKG|1229.32|ng to the +6324|beige dodger burnished misty pink|Manufacturer#3|Brand#35|SMALL BURNISHED TIN|22|MED PKG|1230.32|gularly bo +6325|puff honeydew blush coral magenta|Manufacturer#1|Brand#11|LARGE ANODIZED STEEL|20|WRAP DRUM|1231.32|even deposits. +6326|blue olive lemon goldenrod slate|Manufacturer#3|Brand#35|PROMO POLISHED TIN|45|JUMBO CAN|1232.32|ounts dazzle +6327|forest navy powder black papaya|Manufacturer#1|Brand#11|MEDIUM BRUSHED BRASS|37|MED CAN|1233.32|ncies. even, even p +6328|chocolate red papaya lavender honeydew|Manufacturer#2|Brand#25|MEDIUM BURNISHED TIN|9|WRAP BOX|1234.32|kages. a +6329|lawn hot brown sienna tomato|Manufacturer#4|Brand#41|LARGE PLATED COPPER|47|JUMBO BOX|1235.32| special the +6330|firebrick lime ghost honeydew coral|Manufacturer#1|Brand#14|SMALL ANODIZED STEEL|15|SM PACK|1236.33|ts haggle furiousl +6331|maroon floral blanched burlywood red|Manufacturer#5|Brand#53|LARGE ANODIZED NICKEL|8|WRAP CAN|1237.33|ackages. bo +6332|honeydew sienna rose aquamarine moccasin|Manufacturer#4|Brand#44|LARGE PLATED STEEL|27|MED BOX|1238.33|among the regular +6333|blanched pink black drab wheat|Manufacturer#2|Brand#23|LARGE BURNISHED TIN|28|JUMBO BAG|1239.33|ages. careful +6334|indian wheat turquoise blanched linen|Manufacturer#4|Brand#42|ECONOMY PLATED STEEL|46|JUMBO DRUM|1240.33|e furiously unus +6335|lime burnished purple lemon linen|Manufacturer#3|Brand#31|ECONOMY BURNISHED TIN|12|JUMBO JAR|1241.33|ep. permanent, fina +6336|lemon dodger peach cyan blue|Manufacturer#2|Brand#24|SMALL BRUSHED STEEL|18|SM BAG|1242.33|. express +6337|steel orchid ivory antique navajo|Manufacturer#5|Brand#55|PROMO BURNISHED STEEL|5|SM DRUM|1243.33|xpress packa +6338|plum lace almond cyan seashell|Manufacturer#1|Brand#11|ECONOMY PLATED NICKEL|45|MED PKG|1244.33|unts again +6339|orange navajo coral mint black|Manufacturer#3|Brand#33|ECONOMY ANODIZED BRASS|10|WRAP DRUM|1245.33|eans cajo +6340|lavender midnight cornflower misty red|Manufacturer#2|Brand#21|LARGE POLISHED BRASS|27|MED DRUM|1246.34|nusual pac +6341|sky slate ghost smoke bisque|Manufacturer#5|Brand#51|STANDARD BRUSHED TIN|34|WRAP CASE|1247.34|ely thin accoun +6342|navy puff olive hot violet|Manufacturer#5|Brand#54|ECONOMY BRUSHED BRASS|30|MED CAN|1248.34|slyly unusual asymp +6343|saddle yellow moccasin tomato plum|Manufacturer#2|Brand#22|SMALL BURNISHED BRASS|6|SM CAN|1249.34|sts. fu +6344|blue frosted black linen chocolate|Manufacturer#3|Brand#33|SMALL BURNISHED BRASS|19|WRAP PKG|1250.34|s cajole fluffily. +6345|thistle sienna almond grey lemon|Manufacturer#5|Brand#53|SMALL BURNISHED COPPER|46|LG BAG|1251.34|kly f +6346|saddle ghost orchid brown blush|Manufacturer#5|Brand#55|STANDARD BRUSHED TIN|45|MED JAR|1252.34|nts haggle. ev +6347|honeydew cornsilk rosy linen blue|Manufacturer#4|Brand#44|LARGE BURNISHED BRASS|49|LG BOX|1253.34| alongside of +6348|purple rosy tomato maroon black|Manufacturer#5|Brand#54|ECONOMY POLISHED NICKEL|18|JUMBO PACK|1254.34| blithel +6349|forest frosted bisque orchid sky|Manufacturer#2|Brand#21|SMALL BURNISHED TIN|19|WRAP BAG|1255.34| the f +6350|blush papaya salmon sky gainsboro|Manufacturer#5|Brand#54|ECONOMY BRUSHED BRASS|28|JUMBO BAG|1256.35| carefully +6351|tomato orange honeydew blanched metallic|Manufacturer#1|Brand#11|SMALL BRUSHED BRASS|32|JUMBO BAG|1257.35|refully regular, unu +6352|rosy plum light tomato wheat|Manufacturer#5|Brand#53|MEDIUM BURNISHED TIN|14|LG DRUM|1258.35|t ideas affix along +6353|drab linen blue steel floral|Manufacturer#5|Brand#54|LARGE PLATED COPPER|46|MED CAN|1259.35|ain qui +6354|lawn midnight olive plum blush|Manufacturer#4|Brand#43|SMALL PLATED NICKEL|22|MED PACK|1260.35| final theodolites caj +6355|burlywood moccasin beige dodger lace|Manufacturer#5|Brand#55|STANDARD BURNISHED COPPER|41|LG PACK|1261.35|reful +6356|moccasin magenta dim slate orchid|Manufacturer#3|Brand#35|STANDARD POLISHED STEEL|8|MED CASE|1262.35|according to the +6357|chartreuse snow sandy saddle blush|Manufacturer#1|Brand#12|LARGE BURNISHED NICKEL|14|LG BAG|1263.35|ng foxe +6358|slate royal ghost cyan dark|Manufacturer#5|Brand#51|ECONOMY BURNISHED TIN|35|JUMBO PACK|1264.35|slyly fluffily +6359|cream mint yellow grey sandy|Manufacturer#3|Brand#33|PROMO BRUSHED BRASS|10|WRAP CAN|1265.35|es are blithely. +6360|floral drab salmon purple navy|Manufacturer#3|Brand#32|PROMO BRUSHED COPPER|26|JUMBO PACK|1266.36|al instructions a +6361|orchid magenta indian cream ivory|Manufacturer#5|Brand#55|STANDARD PLATED TIN|35|MED PACK|1267.36|ts use. slyly exp +6362|maroon peru navy drab lawn|Manufacturer#2|Brand#21|SMALL PLATED COPPER|7|JUMBO PACK|1268.36|ecial accounts at +6363|midnight orange maroon forest tomato|Manufacturer#1|Brand#12|ECONOMY BRUSHED TIN|16|LG JAR|1269.36|press the +6364|yellow almond tan chartreuse cream|Manufacturer#5|Brand#54|ECONOMY ANODIZED COPPER|11|LG BAG|1270.36|longside of th +6365|maroon coral magenta salmon mint|Manufacturer#5|Brand#55|SMALL BRUSHED TIN|37|SM CASE|1271.36|le fluffily reque +6366|lawn blue rose gainsboro navajo|Manufacturer#5|Brand#54|STANDARD BURNISHED BRASS|23|SM BAG|1272.36|he furiously d +6367|dark papaya misty forest violet|Manufacturer#4|Brand#44|LARGE PLATED STEEL|14|MED DRUM|1273.36|sleep after th +6368|moccasin linen cornflower light chartreuse|Manufacturer#3|Brand#31|MEDIUM POLISHED BRASS|2|SM CASE|1274.36|r the depo +6369|chocolate lawn navajo violet antique|Manufacturer#4|Brand#44|MEDIUM POLISHED TIN|4|WRAP PKG|1275.36|riously specia +6370|dodger sienna pink aquamarine sky|Manufacturer#5|Brand#53|LARGE ANODIZED TIN|28|LG PKG|1276.37|ctions +6371|peach chocolate dark midnight frosted|Manufacturer#2|Brand#24|STANDARD PLATED BRASS|7|LG JAR|1277.37|ely even reques +6372|plum wheat tomato blue dim|Manufacturer#2|Brand#22|STANDARD PLATED BRASS|5|SM CAN|1278.37|e fluf +6373|royal gainsboro pale lemon misty|Manufacturer#5|Brand#52|STANDARD ANODIZED BRASS|40|MED DRUM|1279.37| across the slyly ex +6374|navajo white plum lemon midnight|Manufacturer#5|Brand#53|ECONOMY BRUSHED STEEL|40|MED CAN|1280.37|xpress +6375|dim peach cornsilk magenta gainsboro|Manufacturer#3|Brand#33|MEDIUM ANODIZED NICKEL|3|LG CAN|1281.37|eodolites. ironic r +6376|white coral burlywood ivory ghost|Manufacturer#3|Brand#32|LARGE BURNISHED STEEL|22|JUMBO JAR|1282.37|to the busily fi +6377|magenta black burnished lawn blush|Manufacturer#1|Brand#12|MEDIUM BURNISHED COPPER|38|LG BAG|1283.37|fily eve +6378|turquoise dim pale red tomato|Manufacturer#5|Brand#52|STANDARD ANODIZED COPPER|21|JUMBO BAG|1284.37|furiously final ide +6379|almond magenta light violet chiffon|Manufacturer#3|Brand#31|LARGE ANODIZED COPPER|27|JUMBO CAN|1285.37|hout the +6380|sky saddle azure yellow cornflower|Manufacturer#3|Brand#33|LARGE BRUSHED NICKEL|29|WRAP JAR|1286.38|the quic +6381|seashell chocolate midnight cyan misty|Manufacturer#2|Brand#25|LARGE BURNISHED BRASS|49|WRAP BOX|1287.38|nag quickly q +6382|orange peru chartreuse linen honeydew|Manufacturer#4|Brand#42|MEDIUM BRUSHED BRASS|8|SM JAR|1288.38|s lose blithely +6383|slate light spring magenta snow|Manufacturer#2|Brand#22|MEDIUM POLISHED STEEL|4|WRAP BAG|1289.38|gular asymptotes. +6384|dark snow maroon spring cornsilk|Manufacturer#5|Brand#51|SMALL ANODIZED BRASS|18|LG PKG|1290.38|unts. blithely dar +6385|sienna white gainsboro peach aquamarine|Manufacturer#1|Brand#11|LARGE BURNISHED NICKEL|24|WRAP BOX|1291.38|s slee +6386|navy azure blue chiffon papaya|Manufacturer#2|Brand#24|STANDARD POLISHED NICKEL|18|MED BAG|1292.38|furiously. +6387|slate firebrick orchid light azure|Manufacturer#4|Brand#45|STANDARD BURNISHED COPPER|25|SM PKG|1293.38|ar instructions. caref +6388|seashell pale maroon floral coral|Manufacturer#2|Brand#23|PROMO POLISHED TIN|47|SM DRUM|1294.38|onic package +6389|antique blush green khaki purple|Manufacturer#5|Brand#51|STANDARD PLATED BRASS|12|JUMBO PACK|1295.38|r foxes. blithely b +6390|bisque pink gainsboro rose lavender|Manufacturer#3|Brand#32|PROMO BRUSHED BRASS|22|MED BOX|1296.39|ctions cajole about +6391|rosy powder yellow linen cyan|Manufacturer#2|Brand#25|LARGE BURNISHED COPPER|1|LG DRUM|1297.39|unusua +6392|linen orchid navajo white ivory|Manufacturer#5|Brand#53|ECONOMY POLISHED COPPER|28|MED BAG|1298.39|furiousl +6393|cornflower dodger khaki rose blush|Manufacturer#4|Brand#42|PROMO ANODIZED TIN|32|JUMBO PACK|1299.39|oxes. regular accou +6394|salmon pink dim azure tomato|Manufacturer#1|Brand#12|PROMO BRUSHED TIN|26|MED PACK|1300.39|cording to the pe +6395|hot turquoise rose ghost burnished|Manufacturer#3|Brand#33|LARGE BRUSHED TIN|22|MED BOX|1301.39|quickly i +6396|dim cornflower frosted pale purple|Manufacturer#3|Brand#34|MEDIUM PLATED BRASS|8|SM BAG|1302.39|t the enticingly fina +6397|turquoise ivory hot rosy violet|Manufacturer#3|Brand#34|STANDARD PLATED COPPER|9|SM JAR|1303.39|accounts sle +6398|papaya sandy black forest lace|Manufacturer#1|Brand#13|ECONOMY BURNISHED BRASS|31|SM BOX|1304.39|ve the iro +6399|papaya saddle midnight sky aquamarine|Manufacturer#4|Brand#42|LARGE BURNISHED COPPER|30|SM JAR|1305.39|nstruction +6400|royal papaya navajo rose thistle|Manufacturer#4|Brand#42|SMALL ANODIZED COPPER|14|SM DRUM|1306.40|d the ironic instruc +6401|floral smoke saddle antique mint|Manufacturer#3|Brand#33|SMALL BRUSHED STEEL|11|SM BAG|1307.40|ial dolphins abov +6402|lawn light puff dark deep|Manufacturer#1|Brand#12|STANDARD POLISHED NICKEL|35|MED JAR|1308.40|he carefully ironi +6403|chiffon tan navajo grey plum|Manufacturer#2|Brand#21|LARGE ANODIZED BRASS|28|WRAP BOX|1309.40|e blithely. sly +6404|rosy turquoise saddle ghost lace|Manufacturer#2|Brand#22|PROMO BURNISHED COPPER|29|SM DRUM|1310.40| requ +6405|wheat metallic sandy ivory spring|Manufacturer#3|Brand#33|LARGE ANODIZED STEEL|24|LG BAG|1311.40| the ironic frays +6406|dim metallic burnished plum salmon|Manufacturer#2|Brand#25|PROMO ANODIZED BRASS|41|LG CAN|1312.40|furio +6407|blue red forest azure violet|Manufacturer#2|Brand#25|STANDARD POLISHED TIN|36|LG CASE|1313.40|y regular requests sl +6408|turquoise frosted tomato navy moccasin|Manufacturer#5|Brand#54|PROMO PLATED TIN|23|JUMBO PKG|1314.40| accounts +6409|frosted plum dark purple aquamarine|Manufacturer#1|Brand#12|PROMO POLISHED TIN|7|SM CAN|1315.40|osits. regu +6410|violet misty rosy antique olive|Manufacturer#4|Brand#44|PROMO BURNISHED TIN|12|MED CAN|1316.41|pecial instruc +6411|lemon deep almond red yellow|Manufacturer#1|Brand#14|STANDARD PLATED TIN|11|WRAP PKG|1317.41| the furiously sp +6412|misty plum moccasin slate orchid|Manufacturer#1|Brand#11|MEDIUM PLATED COPPER|37|JUMBO CAN|1318.41|its. ev +6413|peach azure cornsilk chocolate brown|Manufacturer#5|Brand#51|SMALL PLATED TIN|11|SM CASE|1319.41|inal a +6414|ghost floral khaki aquamarine hot|Manufacturer#4|Brand#43|PROMO BURNISHED TIN|20|WRAP DRUM|1320.41|tructions haggle +6415|forest saddle royal maroon slate|Manufacturer#5|Brand#55|STANDARD BRUSHED STEEL|28|WRAP BOX|1321.41|pending packag +6416|firebrick ivory tomato chiffon floral|Manufacturer#3|Brand#31|PROMO PLATED BRASS|22|JUMBO CASE|1322.41|lyly around t +6417|lace dark thistle medium navajo|Manufacturer#1|Brand#13|PROMO BURNISHED STEEL|23|SM PKG|1323.41|its nod +6418|rose puff orange moccasin royal|Manufacturer#2|Brand#22|PROMO PLATED NICKEL|6|JUMBO CASE|1324.41|furio +6419|chartreuse seashell lemon floral pale|Manufacturer#1|Brand#11|STANDARD POLISHED TIN|47|MED CAN|1325.41|s. perman +6420|azure sky honeydew puff papaya|Manufacturer#2|Brand#24|ECONOMY POLISHED BRASS|36|WRAP CAN|1326.42|reful +6421|sienna peru lace dodger mint|Manufacturer#2|Brand#23|LARGE POLISHED STEEL|10|MED PKG|1327.42|tructions. dogged +6422|olive dark black wheat navy|Manufacturer#2|Brand#24|MEDIUM ANODIZED STEEL|39|MED PACK|1328.42| the s +6423|magenta ghost pale blue honeydew|Manufacturer#3|Brand#33|SMALL PLATED TIN|36|LG BOX|1329.42| even packages hagg +6424|rosy khaki black burlywood floral|Manufacturer#1|Brand#13|LARGE POLISHED BRASS|17|JUMBO BOX|1330.42| pinto beans h +6425|dodger lawn honeydew ghost blush|Manufacturer#1|Brand#12|STANDARD POLISHED BRASS|50|LG PKG|1331.42|ackages. blithel +6426|green steel frosted burlywood puff|Manufacturer#2|Brand#23|LARGE PLATED TIN|44|LG CASE|1332.42|long the carefull +6427|thistle powder floral bisque sienna|Manufacturer#1|Brand#14|MEDIUM POLISHED BRASS|28|SM JAR|1333.42| the +6428|chartreuse lime burlywood magenta lawn|Manufacturer#4|Brand#43|SMALL POLISHED NICKEL|38|JUMBO CAN|1334.42|ironic dependenci +6429|olive tomato rose blue maroon|Manufacturer#2|Brand#22|SMALL ANODIZED TIN|36|JUMBO DRUM|1335.42|ess blithely around t +6430|turquoise tan indian olive ghost|Manufacturer#2|Brand#22|SMALL PLATED STEEL|3|LG JAR|1336.43| regular asymptotes +6431|yellow beige pale gainsboro orchid|Manufacturer#4|Brand#45|ECONOMY BRUSHED COPPER|50|WRAP BOX|1337.43|ironic epitaphs. pint +6432|floral spring snow papaya black|Manufacturer#2|Brand#23|LARGE PLATED TIN|33|SM BOX|1338.43|s. quick, spec +6433|khaki peru turquoise blanched lemon|Manufacturer#1|Brand#14|ECONOMY BRUSHED BRASS|19|LG DRUM|1339.43|dencies doubt. unusu +6434|midnight aquamarine chartreuse powder khaki|Manufacturer#3|Brand#35|MEDIUM ANODIZED NICKEL|46|SM BOX|1340.43|e slyly +6435|frosted wheat royal grey ghost|Manufacturer#5|Brand#51|ECONOMY ANODIZED TIN|12|MED JAR|1341.43|press pack +6436|navy saddle misty blanched gainsboro|Manufacturer#3|Brand#34|PROMO BURNISHED BRASS|40|MED CAN|1342.43|across +6437|brown drab mint sky chocolate|Manufacturer#3|Brand#31|PROMO POLISHED BRASS|16|LG CAN|1343.43| special re +6438|ivory coral misty steel salmon|Manufacturer#5|Brand#52|ECONOMY POLISHED BRASS|23|LG CASE|1344.43|ly express instr +6439|thistle steel lace chocolate chiffon|Manufacturer#5|Brand#55|SMALL ANODIZED COPPER|41|LG JAR|1345.43|arefully bold +6440|floral dim almond ghost thistle|Manufacturer#1|Brand#12|SMALL BURNISHED COPPER|32|LG PKG|1346.44|ously pending r +6441|peach honeydew red blush puff|Manufacturer#1|Brand#13|MEDIUM POLISHED COPPER|16|SM JAR|1347.44|deposi +6442|magenta ivory orange coral grey|Manufacturer#4|Brand#41|ECONOMY BRUSHED TIN|22|WRAP PACK|1348.44|ckages. ca +6443|rose misty brown lavender orange|Manufacturer#5|Brand#55|LARGE PLATED BRASS|26|JUMBO JAR|1349.44|ep quietly across +6444|blanched frosted blush forest burnished|Manufacturer#4|Brand#41|ECONOMY ANODIZED NICKEL|15|SM JAR|1350.44| ironic accounts si +6445|navy lemon grey sky rosy|Manufacturer#1|Brand#11|LARGE ANODIZED STEEL|9|SM CAN|1351.44|pinto beans haggle c +6446|almond floral metallic blush azure|Manufacturer#5|Brand#52|PROMO ANODIZED STEEL|29|SM BOX|1352.44|y regula +6447|olive purple chiffon linen magenta|Manufacturer#2|Brand#21|SMALL PLATED COPPER|48|WRAP BOX|1353.44| sleep. blithely +6448|tomato chartreuse chocolate seashell moccasin|Manufacturer#1|Brand#12|SMALL ANODIZED NICKEL|17|LG BOX|1354.44| fluffily. regula +6449|yellow orchid cream puff dark|Manufacturer#3|Brand#34|SMALL BURNISHED STEEL|12|LG PACK|1355.44|special d +6450|puff light red goldenrod salmon|Manufacturer#5|Brand#55|PROMO ANODIZED BRASS|14|LG PKG|1356.45|equests w +6451|chartreuse cream deep moccasin hot|Manufacturer#1|Brand#13|LARGE POLISHED COPPER|27|WRAP CASE|1357.45| haggle slyly qui +6452|red steel magenta frosted firebrick|Manufacturer#2|Brand#22|PROMO ANODIZED STEEL|36|MED DRUM|1358.45|regular reque +6453|peach wheat sienna dark black|Manufacturer#5|Brand#51|MEDIUM BURNISHED TIN|37|MED JAR|1359.45|y. blithely silen +6454|wheat olive papaya pale goldenrod|Manufacturer#4|Brand#41|LARGE BRUSHED BRASS|20|MED DRUM|1360.45|ackages. slyl +6455|rose snow olive grey navajo|Manufacturer#5|Brand#51|LARGE BURNISHED COPPER|14|WRAP JAR|1361.45|nic dep +6456|lemon almond spring ghost forest|Manufacturer#4|Brand#43|SMALL POLISHED STEEL|22|JUMBO JAR|1362.45|e furiously bold depo +6457|antique pink yellow salmon coral|Manufacturer#3|Brand#33|LARGE BURNISHED NICKEL|50|MED BAG|1363.45| unusual, +6458|turquoise wheat honeydew maroon midnight|Manufacturer#2|Brand#25|MEDIUM POLISHED STEEL|11|SM CAN|1364.45|s sleep blithely abov +6459|navajo almond ghost chartreuse plum|Manufacturer#1|Brand#14|MEDIUM BRUSHED STEEL|14|JUMBO BOX|1365.45|d the ideas nag +6460|peach rose spring snow moccasin|Manufacturer#4|Brand#44|PROMO ANODIZED STEEL|36|MED DRUM|1366.46| reque +6461|black navy khaki sandy ivory|Manufacturer#2|Brand#21|MEDIUM BURNISHED BRASS|33|JUMBO PKG|1367.46|ular accounts hag +6462|papaya lemon lime misty light|Manufacturer#4|Brand#45|MEDIUM BRUSHED NICKEL|16|JUMBO DRUM|1368.46|ns sleep +6463|linen rose blue white honeydew|Manufacturer#3|Brand#31|PROMO BRUSHED BRASS|11|LG BOX|1369.46| sometime +6464|blanched spring chiffon lace indian|Manufacturer#3|Brand#31|PROMO PLATED BRASS|20|JUMBO PKG|1370.46|thely ideas. +6465|metallic cornsilk purple light firebrick|Manufacturer#3|Brand#35|SMALL ANODIZED NICKEL|41|LG JAR|1371.46|he busily regu +6466|thistle azure orange honeydew ivory|Manufacturer#5|Brand#54|LARGE ANODIZED NICKEL|33|MED DRUM|1372.46|lithely +6467|forest sandy azure thistle pale|Manufacturer#4|Brand#41|MEDIUM BURNISHED TIN|3|SM BOX|1373.46|lites. caref +6468|grey honeydew cornsilk light firebrick|Manufacturer#1|Brand#15|SMALL ANODIZED BRASS|1|JUMBO CASE|1374.46| regular a +6469|turquoise navajo indian olive forest|Manufacturer#1|Brand#14|MEDIUM ANODIZED STEEL|8|WRAP JAR|1375.46|ged req +6470|cornflower khaki powder blue black|Manufacturer#4|Brand#43|SMALL PLATED COPPER|45|WRAP CAN|1376.47|ts int +6471|cyan drab almond red burnished|Manufacturer#4|Brand#41|ECONOMY ANODIZED COPPER|40|WRAP PACK|1377.47|g pinto beans dete +6472|cornflower metallic cream bisque plum|Manufacturer#2|Brand#23|PROMO POLISHED STEEL|36|SM PACK|1378.47|al courts wake fur +6473|royal linen antique cornsilk cyan|Manufacturer#3|Brand#31|ECONOMY ANODIZED COPPER|35|LG CASE|1379.47| packages wake s +6474|navy sandy khaki gainsboro tan|Manufacturer#5|Brand#51|MEDIUM ANODIZED BRASS|25|SM BAG|1380.47|nding attainments. +6475|peru peach navajo white lemon|Manufacturer#4|Brand#41|LARGE BURNISHED COPPER|39|LG BAG|1381.47|special reque +6476|peru thistle moccasin olive smoke|Manufacturer#4|Brand#42|MEDIUM POLISHED NICKEL|42|JUMBO JAR|1382.47|uriously +6477|antique black seashell deep burnished|Manufacturer#3|Brand#34|SMALL BURNISHED NICKEL|6|MED BAG|1383.47| careful, ironic +6478|bisque royal seashell floral coral|Manufacturer#1|Brand#12|ECONOMY ANODIZED TIN|29|MED DRUM|1384.47| deposits. pending, do +6479|rose maroon powder orange snow|Manufacturer#3|Brand#33|MEDIUM BURNISHED NICKEL|22|WRAP JAR|1385.47| the final, regul +6480|floral spring beige black cornsilk|Manufacturer#5|Brand#54|STANDARD ANODIZED TIN|3|WRAP BAG|1386.48|re. quickly ir +6481|green khaki cornsilk misty lavender|Manufacturer#4|Brand#42|SMALL BRUSHED BRASS|26|LG JAR|1387.48|ages sleep flu +6482|indian sky orchid orange chocolate|Manufacturer#4|Brand#44|MEDIUM POLISHED NICKEL|24|LG CASE|1388.48| ironic asymptotes wak +6483|almond blush navy mint ghost|Manufacturer#3|Brand#35|PROMO ANODIZED STEEL|5|JUMBO CAN|1389.48|ccounts nag +6484|smoke drab peach pale misty|Manufacturer#2|Brand#25|PROMO PLATED COPPER|1|WRAP BAG|1390.48|w slyly pendi +6485|cream saddle slate floral frosted|Manufacturer#2|Brand#24|MEDIUM POLISHED TIN|26|MED BAG|1391.48|. quickl +6486|frosted indian drab seashell ghost|Manufacturer#2|Brand#23|PROMO BRUSHED TIN|22|WRAP PACK|1392.48|ithely regular dep +6487|slate dodger linen drab green|Manufacturer#1|Brand#11|ECONOMY ANODIZED TIN|46|SM BOX|1393.48|e even +6488|puff royal spring firebrick honeydew|Manufacturer#4|Brand#44|ECONOMY BURNISHED BRASS|4|LG BOX|1394.48|atelet +6489|ivory dodger floral antique plum|Manufacturer#5|Brand#53|STANDARD ANODIZED BRASS|28|LG CASE|1395.48|hes. ironically unusua +6490|cream gainsboro slate puff spring|Manufacturer#3|Brand#34|SMALL PLATED COPPER|36|MED CASE|1396.49|packages. furiously fi +6491|blue goldenrod rose lawn lavender|Manufacturer#2|Brand#21|SMALL ANODIZED STEEL|13|SM DRUM|1397.49|ests boost sly +6492|navy burnished deep cornflower sandy|Manufacturer#5|Brand#55|SMALL POLISHED STEEL|47|WRAP JAR|1398.49|s play carefully +6493|antique turquoise snow gainsboro slate|Manufacturer#5|Brand#52|SMALL PLATED COPPER|36|MED PACK|1399.49|s. silent, even d +6494|brown cyan light peach ivory|Manufacturer#1|Brand#12|LARGE BRUSHED BRASS|11|LG BOX|1400.49|packages. bl +6495|bisque dark orange lawn frosted|Manufacturer#4|Brand#42|LARGE BURNISHED NICKEL|27|SM PACK|1401.49|posits around the +6496|sienna blue goldenrod bisque magenta|Manufacturer#3|Brand#35|MEDIUM BRUSHED BRASS|2|JUMBO CAN|1402.49|e quick +6497|lace plum black deep almond|Manufacturer#4|Brand#45|PROMO BURNISHED TIN|46|WRAP CAN|1403.49|ly above the +6498|grey tomato rosy blanched brown|Manufacturer#1|Brand#14|SMALL POLISHED TIN|26|WRAP PACK|1404.49| packages +6499|cornflower magenta dodger metallic spring|Manufacturer#2|Brand#23|STANDARD POLISHED BRASS|46|WRAP PKG|1405.49|sts are s +6500|antique deep almond black aquamarine|Manufacturer#2|Brand#23|ECONOMY ANODIZED STEEL|1|WRAP DRUM|1406.50|detect slyly +6501|medium snow floral yellow sky|Manufacturer#2|Brand#22|SMALL ANODIZED TIN|46|JUMBO BOX|1407.50|sleep quickly e +6502|cornflower saddle lemon spring peru|Manufacturer#2|Brand#23|LARGE POLISHED COPPER|6|LG BOX|1408.50|ending, brave +6503|royal almond papaya gainsboro orchid|Manufacturer#4|Brand#42|SMALL BRUSHED NICKEL|1|MED CASE|1409.50| deposits cajole furio +6504|orange salmon dark wheat purple|Manufacturer#3|Brand#34|PROMO BRUSHED TIN|48|SM PACK|1410.50|gle slyly ironic, sile +6505|lavender metallic burlywood almond khaki|Manufacturer#4|Brand#42|ECONOMY ANODIZED STEEL|4|LG JAR|1411.50| special i +6506|slate green navy burlywood almond|Manufacturer#5|Brand#52|MEDIUM PLATED COPPER|44|LG CAN|1412.50|de of the express +6507|thistle lemon orchid lace beige|Manufacturer#1|Brand#14|STANDARD PLATED COPPER|47|WRAP CAN|1413.50|uctions haggl +6508|beige maroon almond misty cornflower|Manufacturer#4|Brand#44|SMALL BURNISHED STEEL|10|SM JAR|1414.50|even accou +6509|sienna misty thistle medium powder|Manufacturer#3|Brand#32|MEDIUM ANODIZED STEEL|27|LG PKG|1415.50|ackages for t +6510|indian aquamarine hot yellow drab|Manufacturer#5|Brand#52|MEDIUM BURNISHED BRASS|29|LG JAR|1416.51|sts across the +6511|burnished hot navy steel peru|Manufacturer#3|Brand#33|STANDARD BURNISHED TIN|39|MED JAR|1417.51|gular excuses. fluf +6512|light coral wheat powder rosy|Manufacturer#2|Brand#25|STANDARD PLATED BRASS|3|JUMBO CASE|1418.51|efully expres +6513|moccasin cornsilk misty frosted honeydew|Manufacturer#5|Brand#53|ECONOMY BURNISHED STEEL|21|LG BAG|1419.51| ironic dolphins i +6514|violet spring powder saddle burnished|Manufacturer#5|Brand#51|SMALL PLATED BRASS|28|JUMBO PACK|1420.51|al excuses ca +6515|sienna khaki brown linen purple|Manufacturer#2|Brand#21|SMALL BURNISHED BRASS|2|MED CAN|1421.51|accoun +6516|azure sandy ghost orange antique|Manufacturer#3|Brand#35|ECONOMY BURNISHED TIN|9|LG CASE|1422.51|ar pa +6517|metallic grey plum olive cyan|Manufacturer#4|Brand#41|SMALL BURNISHED COPPER|21|MED PACK|1423.51|nstructi +6518|honeydew goldenrod floral white yellow|Manufacturer#3|Brand#31|SMALL BRUSHED NICKEL|16|WRAP CASE|1424.51|according t +6519|indian seashell cream azure coral|Manufacturer#4|Brand#45|STANDARD ANODIZED NICKEL|17|LG PACK|1425.51|ckly regular +6520|green honeydew cyan yellow peru|Manufacturer#2|Brand#22|PROMO PLATED STEEL|4|LG DRUM|1426.52|y steal +6521|misty powder black linen forest|Manufacturer#2|Brand#24|PROMO BURNISHED NICKEL|42|SM CASE|1427.52|osits after the +6522|lavender almond spring navy blanched|Manufacturer#2|Brand#24|ECONOMY BURNISHED TIN|16|SM PACK|1428.52|s dazzle: careful +6523|hot maroon lawn moccasin ivory|Manufacturer#1|Brand#11|MEDIUM ANODIZED STEEL|43|MED BOX|1429.52|out the quickly +6524|powder blue linen brown peru|Manufacturer#1|Brand#15|PROMO BURNISHED TIN|34|MED CASE|1430.52|unts detect quick +6525|ghost dim antique honeydew dodger|Manufacturer#1|Brand#11|PROMO POLISHED COPPER|11|JUMBO BOX|1431.52|rding t +6526|forest black azure ghost beige|Manufacturer#4|Brand#41|ECONOMY PLATED COPPER|26|MED PKG|1432.52|accounts wake careful +6527|lace coral royal deep sienna|Manufacturer#2|Brand#21|ECONOMY PLATED STEEL|33|SM BOX|1433.52|theodolite +6528|midnight orange floral dim cyan|Manufacturer#5|Brand#51|PROMO ANODIZED COPPER|34|SM DRUM|1434.52|decoys +6529|sienna turquoise olive dark tomato|Manufacturer#1|Brand#15|SMALL BRUSHED STEEL|7|SM BOX|1435.52|ld accou +6530|lawn maroon azure rosy blue|Manufacturer#3|Brand#33|ECONOMY ANODIZED COPPER|33|JUMBO CASE|1436.53|ual packages +6531|floral metallic medium honeydew firebrick|Manufacturer#2|Brand#22|LARGE BURNISHED COPPER|28|WRAP CASE|1437.53|ths after the +6532|navajo burnished misty blue sandy|Manufacturer#5|Brand#54|SMALL BRUSHED COPPER|20|SM DRUM|1438.53| theodolites detect +6533|misty slate cream forest olive|Manufacturer#3|Brand#35|SMALL ANODIZED NICKEL|41|WRAP PKG|1439.53|symptotes +6534|blue metallic midnight forest powder|Manufacturer#3|Brand#32|STANDARD BRUSHED STEEL|11|WRAP JAR|1440.53|reful +6535|linen thistle sandy brown chocolate|Manufacturer#5|Brand#53|SMALL POLISHED COPPER|8|JUMBO JAR|1441.53|ular packa +6536|rosy plum violet peru lemon|Manufacturer#2|Brand#22|ECONOMY BRUSHED NICKEL|31|WRAP BAG|1442.53|aggle. reg +6537|olive cornsilk blanched seashell magenta|Manufacturer#5|Brand#53|PROMO POLISHED NICKEL|20|MED BOX|1443.53|furiously unu +6538|powder turquoise bisque grey steel|Manufacturer#5|Brand#51|PROMO ANODIZED NICKEL|10|JUMBO BAG|1444.53|hins wake ac +6539|black olive metallic azure spring|Manufacturer#1|Brand#13|SMALL POLISHED COPPER|29|MED JAR|1445.53|symptotes? quickly +6540|papaya salmon sienna ivory lime|Manufacturer#3|Brand#32|MEDIUM ANODIZED COPPER|5|JUMBO PACK|1446.54|beans wake re +6541|metallic thistle plum frosted light|Manufacturer#2|Brand#23|SMALL POLISHED BRASS|49|JUMBO DRUM|1447.54|its haggle along +6542|violet peach sienna blue rosy|Manufacturer#3|Brand#34|MEDIUM BRUSHED BRASS|38|SM BAG|1448.54|asymptote +6543|sky red goldenrod bisque tomato|Manufacturer#1|Brand#14|STANDARD POLISHED COPPER|28|JUMBO PACK|1449.54| packages haggle car +6544|firebrick aquamarine black midnight red|Manufacturer#2|Brand#25|STANDARD BRUSHED TIN|13|SM PKG|1450.54|e slyl +6545|powder blue orchid slate lemon|Manufacturer#4|Brand#45|SMALL PLATED COPPER|36|LG PACK|1451.54|ording to the slyly +6546|magenta sandy pale lavender steel|Manufacturer#2|Brand#25|LARGE BRUSHED BRASS|41|MED PKG|1452.54|ic pinto beans use +6547|forest khaki firebrick brown light|Manufacturer#2|Brand#23|LARGE PLATED COPPER|33|WRAP CASE|1453.54|ructions +6548|green slate brown orange sandy|Manufacturer#5|Brand#54|PROMO BURNISHED STEEL|7|WRAP BAG|1454.54|atele +6549|gainsboro sandy slate beige burlywood|Manufacturer#3|Brand#33|SMALL BRUSHED NICKEL|45|LG CAN|1455.54|ckages. +6550|cyan cornflower magenta cornsilk lawn|Manufacturer#2|Brand#24|LARGE POLISHED STEEL|23|WRAP PACK|1456.55|requests +6551|firebrick deep smoke mint peach|Manufacturer#5|Brand#51|PROMO ANODIZED BRASS|35|JUMBO BOX|1457.55|s. carefully +6552|cream lemon chocolate sienna black|Manufacturer#5|Brand#51|LARGE ANODIZED NICKEL|25|LG BOX|1458.55|ronic +6553|white green misty wheat indian|Manufacturer#2|Brand#24|SMALL POLISHED COPPER|33|JUMBO CASE|1459.55|ending excu +6554|drab maroon deep cyan floral|Manufacturer#1|Brand#13|MEDIUM POLISHED NICKEL|42|JUMBO PKG|1460.55|pending accounts +6555|brown thistle frosted sienna moccasin|Manufacturer#2|Brand#25|LARGE ANODIZED STEEL|23|WRAP BAG|1461.55|are furiou +6556|forest misty seashell navy ghost|Manufacturer#3|Brand#32|MEDIUM BRUSHED NICKEL|42|MED CAN|1462.55|nusual ideas. sp +6557|lawn blue navy rose navajo|Manufacturer#1|Brand#15|STANDARD BURNISHED NICKEL|28|SM BOX|1463.55|pendin +6558|floral cornflower burlywood rose firebrick|Manufacturer#5|Brand#52|SMALL ANODIZED BRASS|3|LG DRUM|1464.55|d ideas are +6559|honeydew steel seashell peach cornflower|Manufacturer#3|Brand#31|PROMO POLISHED TIN|8|JUMBO DRUM|1465.55|pades boost blithel +6560|salmon dim moccasin frosted indian|Manufacturer#3|Brand#34|STANDARD BRUSHED BRASS|7|SM BAG|1466.56|d the daringly regula +6561|dodger bisque blush peach lawn|Manufacturer#3|Brand#35|MEDIUM PLATED BRASS|42|LG BOX|1467.56|r the blithely spec +6562|spring hot blanched chocolate orange|Manufacturer#5|Brand#52|ECONOMY ANODIZED STEEL|3|LG PACK|1468.56|g accounts slee +6563|peach royal lemon frosted tomato|Manufacturer#5|Brand#55|ECONOMY POLISHED COPPER|43|LG PACK|1469.56|yly unusual patt +6564|slate brown floral firebrick grey|Manufacturer#4|Brand#44|PROMO BURNISHED TIN|44|WRAP JAR|1470.56|pendencies boost blith +6565|cyan lace chiffon papaya coral|Manufacturer#5|Brand#53|MEDIUM POLISHED STEEL|32|MED DRUM|1471.56|ing to the s +6566|misty salmon frosted antique honeydew|Manufacturer#4|Brand#42|PROMO ANODIZED BRASS|38|LG CASE|1472.56| furiously fur +6567|snow magenta dark saddle sky|Manufacturer#1|Brand#13|STANDARD POLISHED NICKEL|47|WRAP BAG|1473.56|express deposits +6568|dark lime sandy burnished blanched|Manufacturer#2|Brand#23|MEDIUM POLISHED BRASS|50|MED JAR|1474.56|t, pendi +6569|ivory snow red olive lawn|Manufacturer#4|Brand#44|SMALL BURNISHED COPPER|14|JUMBO JAR|1475.56|g the brave foxes dazz +6570|medium lawn puff magenta saddle|Manufacturer#2|Brand#25|SMALL BURNISHED NICKEL|43|WRAP PACK|1476.57|kages. r +6571|lace saddle lavender khaki pink|Manufacturer#5|Brand#51|SMALL PLATED BRASS|34|JUMBO CASE|1477.57|en dolphi +6572|green salmon lace powder lemon|Manufacturer#3|Brand#33|PROMO ANODIZED NICKEL|7|JUMBO PKG|1478.57|quickly final foxe +6573|cyan smoke firebrick papaya brown|Manufacturer#1|Brand#13|LARGE ANODIZED BRASS|32|JUMBO PACK|1479.57|ges affix. +6574|lavender mint olive honeydew lemon|Manufacturer#3|Brand#33|LARGE BURNISHED COPPER|45|MED PACK|1480.57|c pinto beans haggle c +6575|aquamarine red lime pale sandy|Manufacturer#3|Brand#34|STANDARD ANODIZED NICKEL|41|SM BAG|1481.57|into beans +6576|lawn black cyan tomato cornsilk|Manufacturer#5|Brand#51|LARGE BRUSHED NICKEL|9|LG CAN|1482.57|. carefully silent pi +6577|firebrick royal purple khaki burnished|Manufacturer#2|Brand#22|ECONOMY BURNISHED COPPER|41|WRAP CASE|1483.57|oost quickly acro +6578|yellow cyan moccasin aquamarine cornflower|Manufacturer#3|Brand#35|PROMO ANODIZED BRASS|46|SM CASE|1484.57| requests wake blithel +6579|rosy chartreuse green red navy|Manufacturer#4|Brand#45|STANDARD BRUSHED STEEL|17|SM CAN|1485.57|special accounts wil +6580|dark thistle coral cornsilk red|Manufacturer#5|Brand#52|PROMO BRUSHED STEEL|43|JUMBO BOX|1486.58|s caj +6581|khaki purple lawn royal slate|Manufacturer#3|Brand#33|LARGE BRUSHED COPPER|20|MED PKG|1487.58|ily qui +6582|rosy frosted puff drab dim|Manufacturer#1|Brand#15|LARGE BURNISHED BRASS|19|JUMBO CASE|1488.58|y bold ideas. bold +6583|magenta blue burnished azure midnight|Manufacturer#5|Brand#52|SMALL BRUSHED BRASS|10|SM CAN|1489.58|y unusual deposit +6584|peach hot bisque white snow|Manufacturer#4|Brand#42|STANDARD BRUSHED BRASS|44|LG BAG|1490.58|ent th +6585|tomato snow cornflower black mint|Manufacturer#4|Brand#43|SMALL BRUSHED NICKEL|39|JUMBO BOX|1491.58|ly regular deposit +6586|navy yellow frosted tomato wheat|Manufacturer#3|Brand#32|MEDIUM POLISHED COPPER|46|WRAP DRUM|1492.58| nod stealthily +6587|tan cornflower plum dark peru|Manufacturer#1|Brand#14|SMALL PLATED TIN|30|WRAP PKG|1493.58|e slyly +6588|floral tomato white medium burlywood|Manufacturer#3|Brand#34|LARGE BURNISHED BRASS|31|JUMBO BAG|1494.58|refully pending pin +6589|olive white spring misty cream|Manufacturer#1|Brand#11|ECONOMY PLATED NICKEL|30|LG PACK|1495.58| even pin +6590|firebrick chartreuse goldenrod honeydew steel|Manufacturer#1|Brand#13|SMALL BRUSHED COPPER|28|MED DRUM|1496.59|es sleep about th +6591|gainsboro khaki chocolate rosy navajo|Manufacturer#1|Brand#11|ECONOMY PLATED NICKEL|29|SM BAG|1497.59|x daringly bol +6592|puff olive drab grey red|Manufacturer#4|Brand#44|LARGE POLISHED NICKEL|4|MED BAG|1498.59| acco +6593|blanched lime lace magenta rosy|Manufacturer#1|Brand#14|ECONOMY POLISHED COPPER|41|MED PKG|1499.59| slyly regular the +6594|black khaki navajo purple turquoise|Manufacturer#2|Brand#21|MEDIUM BURNISHED TIN|20|WRAP PACK|1500.59|pendenci +6595|bisque lemon firebrick gainsboro pale|Manufacturer#3|Brand#31|SMALL PLATED NICKEL|36|MED CASE|1501.59|ar theod +6596|mint misty coral turquoise cornsilk|Manufacturer#2|Brand#24|LARGE POLISHED TIN|15|SM DRUM|1502.59|y unusual deposits ar +6597|metallic tan khaki beige salmon|Manufacturer#4|Brand#44|LARGE POLISHED TIN|11|WRAP CAN|1503.59|xes against the care +6598|cream brown goldenrod lawn burnished|Manufacturer#3|Brand#32|LARGE PLATED COPPER|33|SM PACK|1504.59|odolites +6599|plum midnight turquoise tan violet|Manufacturer#5|Brand#54|LARGE ANODIZED NICKEL|49|MED BOX|1505.59|fluffily against the f +6600|aquamarine blanched drab floral burnished|Manufacturer#3|Brand#31|PROMO PLATED STEEL|17|JUMBO CASE|1506.60| are around +6601|cyan orange metallic blush navajo|Manufacturer#2|Brand#21|LARGE PLATED NICKEL|8|MED CASE|1507.60|ingly brave dol +6602|blush violet azure black tan|Manufacturer#5|Brand#53|SMALL BURNISHED COPPER|45|JUMBO CASE|1508.60|ly silent deposits. a +6603|wheat blanched grey slate brown|Manufacturer#4|Brand#42|PROMO BRUSHED NICKEL|33|MED JAR|1509.60|posits are furiously +6604|powder smoke rose maroon cornsilk|Manufacturer#4|Brand#43|STANDARD BURNISHED NICKEL|48|SM CASE|1510.60|ckly bold ideas. +6605|peru pale spring orange papaya|Manufacturer#3|Brand#32|MEDIUM ANODIZED STEEL|10|SM PKG|1511.60|lyly. furiously +6606|rosy grey midnight wheat lavender|Manufacturer#5|Brand#51|SMALL ANODIZED STEEL|7|SM DRUM|1512.60|stealthily even ideas +6607|khaki goldenrod floral misty navy|Manufacturer#1|Brand#14|LARGE BRUSHED BRASS|39|SM CAN|1513.60|d dependencies. +6608|lemon ivory cornsilk navy seashell|Manufacturer#2|Brand#21|SMALL PLATED TIN|26|WRAP DRUM|1514.60|lyly among the fu +6609|cornflower medium grey royal slate|Manufacturer#3|Brand#33|SMALL ANODIZED BRASS|41|WRAP BOX|1515.60|cross the fluff +6610|moccasin lavender khaki dim white|Manufacturer#3|Brand#31|ECONOMY BRUSHED COPPER|46|SM JAR|1516.61|are furio +6611|chocolate puff rose indian purple|Manufacturer#4|Brand#42|PROMO ANODIZED BRASS|32|MED BOX|1517.61|fix slyly +6612|blue hot wheat misty gainsboro|Manufacturer#1|Brand#14|MEDIUM PLATED TIN|44|JUMBO JAR|1518.61|dinos. blithely +6613|rose slate antique maroon beige|Manufacturer#3|Brand#31|SMALL BURNISHED COPPER|7|WRAP PACK|1519.61|slyly +6614|misty peach blue cornflower indian|Manufacturer#5|Brand#53|MEDIUM BURNISHED TIN|46|JUMBO DRUM|1520.61|ly bold packages cajo +6615|rosy drab sienna misty royal|Manufacturer#5|Brand#54|SMALL ANODIZED BRASS|16|MED PACK|1521.61|ar requests. blithe +6616|azure coral sienna midnight lavender|Manufacturer#5|Brand#51|ECONOMY ANODIZED STEEL|9|LG PKG|1522.61| the q +6617|dodger black tomato powder peru|Manufacturer#3|Brand#33|ECONOMY BURNISHED COPPER|3|WRAP PACK|1523.61|ithely a +6618|floral spring antique moccasin peru|Manufacturer#4|Brand#43|PROMO BRUSHED BRASS|25|SM CASE|1524.61|r the unusual, +6619|violet frosted medium ivory cornsilk|Manufacturer#2|Brand#22|LARGE ANODIZED COPPER|21|JUMBO BOX|1525.61|s hang bli +6620|puff khaki peru midnight chocolate|Manufacturer#5|Brand#53|STANDARD ANODIZED BRASS|34|MED PACK|1526.62|ounts. pen +6621|steel deep brown cornflower burnished|Manufacturer#3|Brand#31|SMALL BRUSHED COPPER|7|JUMBO CAN|1527.62|tructions bre +6622|rose burlywood blue deep salmon|Manufacturer#2|Brand#22|ECONOMY POLISHED COPPER|16|LG PACK|1528.62| foxes are b +6623|salmon lavender blue medium papaya|Manufacturer#4|Brand#41|ECONOMY POLISHED NICKEL|5|WRAP DRUM|1529.62|lyly above the +6624|tan blanched cream dodger grey|Manufacturer#2|Brand#23|MEDIUM BRUSHED TIN|26|SM CASE|1530.62|s above the slyly cl +6625|chartreuse ghost dim frosted sandy|Manufacturer#2|Brand#23|MEDIUM BRUSHED BRASS|18|MED CASE|1531.62| at the slyly iro +6626|chartreuse lime hot saddle rose|Manufacturer#3|Brand#31|MEDIUM BURNISHED COPPER|17|LG DRUM|1532.62|ctions +6627|medium peru chartreuse orange royal|Manufacturer#4|Brand#42|STANDARD POLISHED NICKEL|32|JUMBO PACK|1533.62|ronic, even dep +6628|lemon sienna medium pink saddle|Manufacturer#5|Brand#55|PROMO PLATED TIN|3|SM CASE|1534.62| across the silent, +6629|deep bisque lavender snow ivory|Manufacturer#4|Brand#43|STANDARD PLATED TIN|29|JUMBO JAR|1535.62|ggle blithely expres +6630|spring metallic chocolate deep blush|Manufacturer#1|Brand#14|STANDARD ANODIZED BRASS|47|MED BAG|1536.63|t slyly al +6631|drab moccasin lace white ghost|Manufacturer#3|Brand#33|SMALL PLATED BRASS|28|WRAP CASE|1537.63|es nag. multi +6632|sandy orchid misty navajo antique|Manufacturer#1|Brand#15|ECONOMY PLATED COPPER|35|JUMBO CAN|1538.63|eas cajole bl +6633|orchid thistle sky linen khaki|Manufacturer#2|Brand#21|ECONOMY ANODIZED STEEL|27|WRAP JAR|1539.63|ounts thrash +6634|lace olive indian orange dim|Manufacturer#4|Brand#41|STANDARD BURNISHED STEEL|34|SM CAN|1540.63| above the +6635|frosted midnight khaki tomato sandy|Manufacturer#4|Brand#43|PROMO PLATED NICKEL|38|SM CAN|1541.63|side +6636|red linen dodger floral hot|Manufacturer#5|Brand#52|STANDARD POLISHED NICKEL|45|MED BOX|1542.63|nstruct +6637|chiffon bisque frosted magenta red|Manufacturer#1|Brand#13|LARGE PLATED BRASS|41|MED CAN|1543.63|. blithely +6638|sandy antique cornflower dim honeydew|Manufacturer#1|Brand#13|PROMO BRUSHED NICKEL|50|LG BAG|1544.63|uickly final +6639|turquoise midnight smoke maroon chiffon|Manufacturer#1|Brand#11|MEDIUM POLISHED STEEL|34|LG CASE|1545.63|y deposits +6640|pink sandy red mint black|Manufacturer#5|Brand#54|ECONOMY POLISHED TIN|3|JUMBO PKG|1546.64|ld depos +6641|cyan indian grey drab chartreuse|Manufacturer#2|Brand#23|ECONOMY ANODIZED COPPER|11|SM BOX|1547.64|ts. quickly +6642|gainsboro navajo cream medium maroon|Manufacturer#3|Brand#33|ECONOMY BURNISHED NICKEL|34|JUMBO BOX|1548.64|al accounts. carefull +6643|white lemon blanched deep yellow|Manufacturer#3|Brand#33|PROMO ANODIZED TIN|44|SM BOX|1549.64|the ironic ins +6644|khaki sandy moccasin goldenrod almond|Manufacturer#2|Brand#24|SMALL BRUSHED COPPER|25|MED CAN|1550.64|ts nag blithely above +6645|blush antique lemon plum dim|Manufacturer#4|Brand#41|STANDARD POLISHED STEEL|43|LG JAR|1551.64|pendencies affix. regu +6646|cornflower green slate spring medium|Manufacturer#5|Brand#55|STANDARD BRUSHED STEEL|2|WRAP BAG|1552.64|equests. de +6647|turquoise forest misty dodger aquamarine|Manufacturer#1|Brand#13|ECONOMY PLATED TIN|3|MED PKG|1553.64|ptotes. slyly ir +6648|forest beige chiffon hot peach|Manufacturer#1|Brand#14|STANDARD PLATED NICKEL|2|SM DRUM|1554.64|gside of the +6649|rosy saddle beige almond light|Manufacturer#2|Brand#22|ECONOMY ANODIZED NICKEL|18|WRAP BOX|1555.64|t. regular ideas are: +6650|almond white misty goldenrod blanched|Manufacturer#3|Brand#32|MEDIUM ANODIZED COPPER|27|SM PACK|1556.65| after the warhors +6651|burlywood sandy olive orange smoke|Manufacturer#2|Brand#23|ECONOMY ANODIZED NICKEL|20|WRAP PKG|1557.65| frays. +6652|red puff green sandy smoke|Manufacturer#1|Brand#12|ECONOMY BRUSHED TIN|33|SM JAR|1558.65|. blithely bold ac +6653|sienna papaya cornflower coral peru|Manufacturer#3|Brand#32|ECONOMY POLISHED NICKEL|10|LG PACK|1559.65|bout the unusual, i +6654|gainsboro dim goldenrod maroon light|Manufacturer#5|Brand#52|STANDARD BURNISHED COPPER|40|MED BAG|1560.65|en decoy +6655|burlywood snow frosted dark drab|Manufacturer#4|Brand#42|SMALL BURNISHED BRASS|36|WRAP PACK|1561.65|? blithel +6656|chiffon indian lace purple cream|Manufacturer#2|Brand#22|LARGE PLATED BRASS|31|MED PACK|1562.65|al excuses +6657|tomato lavender blush drab lawn|Manufacturer#2|Brand#24|SMALL POLISHED NICKEL|19|LG CASE|1563.65|uests. bravely unusua +6658|thistle goldenrod yellow beige black|Manufacturer#4|Brand#43|ECONOMY PLATED BRASS|20|MED BAG|1564.65|nding pl +6659|yellow pink pale rose honeydew|Manufacturer#2|Brand#21|LARGE BRUSHED NICKEL|22|MED JAR|1565.65|xpress asympto +6660|lime blanched rose salmon forest|Manufacturer#2|Brand#23|STANDARD PLATED BRASS|39|SM PKG|1566.66|p. qu +6661|beige coral ghost papaya antique|Manufacturer#2|Brand#23|PROMO BURNISHED STEEL|2|MED CASE|1567.66|ly special instr +6662|almond salmon hot sandy forest|Manufacturer#4|Brand#43|SMALL PLATED TIN|7|SM PKG|1568.66|r requests. +6663|spring seashell violet aquamarine dodger|Manufacturer#2|Brand#25|LARGE ANODIZED COPPER|32|LG JAR|1569.66|c ideas. +6664|lace peach snow pale spring|Manufacturer#3|Brand#35|LARGE POLISHED NICKEL|21|LG CAN|1570.66| quickly pending dol +6665|goldenrod chocolate peru midnight lemon|Manufacturer#5|Brand#55|LARGE BURNISHED BRASS|22|WRAP JAR|1571.66| furiously to +6666|azure blue smoke metallic powder|Manufacturer#1|Brand#15|LARGE PLATED STEEL|42|SM CAN|1572.66|y deposits. even, regu +6667|coral beige turquoise chiffon burnished|Manufacturer#1|Brand#14|MEDIUM POLISHED STEEL|13|MED PKG|1573.66|ents along the quic +6668|turquoise burnished honeydew aquamarine ghost|Manufacturer#5|Brand#55|STANDARD PLATED BRASS|23|WRAP BOX|1574.66|ong the furiously +6669|rose forest lace chocolate peru|Manufacturer#1|Brand#12|STANDARD PLATED BRASS|40|LG CAN|1575.66|ckly regular do +6670|snow wheat steel mint pink|Manufacturer#4|Brand#43|PROMO PLATED TIN|3|WRAP JAR|1576.67|iously regul +6671|lemon linen wheat frosted honeydew|Manufacturer#5|Brand#52|SMALL BURNISHED TIN|35|JUMBO PACK|1577.67|ncies? care +6672|slate dodger pink blanched thistle|Manufacturer#3|Brand#31|MEDIUM BURNISHED STEEL|32|LG CASE|1578.67| pending accou +6673|lavender forest grey slate chiffon|Manufacturer#3|Brand#31|LARGE PLATED BRASS|20|LG PACK|1579.67|ic dependenc +6674|lace frosted rosy chiffon blanched|Manufacturer#2|Brand#21|SMALL ANODIZED NICKEL|47|JUMBO JAR|1580.67|refully even deco +6675|burlywood purple deep goldenrod pink|Manufacturer#5|Brand#53|SMALL POLISHED COPPER|39|WRAP JAR|1581.67| furious foxe +6676|saddle tan sienna burlywood green|Manufacturer#5|Brand#53|SMALL BURNISHED NICKEL|41|WRAP CAN|1582.67|e final asymptotes. s +6677|chiffon royal lace yellow drab|Manufacturer#3|Brand#31|MEDIUM ANODIZED BRASS|31|WRAP CASE|1583.67|riously. unusual depen +6678|spring peru burnished moccasin khaki|Manufacturer#3|Brand#35|PROMO PLATED TIN|11|SM JAR|1584.67|ages ha +6679|lace moccasin puff violet plum|Manufacturer#2|Brand#21|SMALL PLATED TIN|37|LG BOX|1585.67| cour +6680|dim lace cream honeydew wheat|Manufacturer#1|Brand#14|STANDARD POLISHED BRASS|24|SM BAG|1586.68|n dolphins. slyly reg +6681|steel gainsboro burlywood cream hot|Manufacturer#2|Brand#23|STANDARD ANODIZED STEEL|7|LG PACK|1587.68|en excuses. sl +6682|slate sandy mint chiffon peru|Manufacturer#3|Brand#33|MEDIUM BRUSHED COPPER|30|MED CAN|1588.68|e. even packa +6683|cream sandy dodger dim cornflower|Manufacturer#1|Brand#13|SMALL POLISHED STEEL|49|LG BAG|1589.68| pending, silent pac +6684|green firebrick blanched goldenrod grey|Manufacturer#1|Brand#12|MEDIUM BURNISHED STEEL|2|MED CAN|1590.68|y about the c +6685|royal sienna mint green khaki|Manufacturer#4|Brand#45|ECONOMY ANODIZED BRASS|49|MED PKG|1591.68|detect +6686|frosted cornsilk misty light lime|Manufacturer#5|Brand#53|MEDIUM BURNISHED NICKEL|6|WRAP PACK|1592.68| the requests wake sl +6687|bisque pink navy ivory orange|Manufacturer#4|Brand#42|ECONOMY BURNISHED COPPER|8|SM CASE|1593.68|ully silent pa +6688|sienna olive lemon dark blue|Manufacturer#5|Brand#53|STANDARD BRUSHED NICKEL|34|JUMBO PACK|1594.68|ully regular theo +6689|maroon gainsboro cream turquoise cyan|Manufacturer#5|Brand#53|MEDIUM PLATED BRASS|23|WRAP PKG|1595.68| blithely special r +6690|azure wheat lawn midnight spring|Manufacturer#4|Brand#44|SMALL BRUSHED TIN|20|JUMBO CASE|1596.69|deposits. closely ev +6691|seashell chiffon peru chocolate antique|Manufacturer#2|Brand#24|MEDIUM PLATED COPPER|7|JUMBO BAG|1597.69| depo +6692|white deep cornflower purple ivory|Manufacturer#3|Brand#32|ECONOMY PLATED COPPER|24|MED CAN|1598.69|iously ironic court +6693|moccasin cornflower lemon goldenrod light|Manufacturer#4|Brand#44|MEDIUM ANODIZED COPPER|26|JUMBO DRUM|1599.69|regular d +6694|misty linen white spring metallic|Manufacturer#4|Brand#45|LARGE BRUSHED BRASS|26|MED PACK|1600.69|gular requests. +6695|brown yellow mint burlywood medium|Manufacturer#4|Brand#45|STANDARD POLISHED STEEL|13|WRAP BOX|1601.69|riously un +6696|moccasin mint saddle gainsboro seashell|Manufacturer#2|Brand#24|SMALL PLATED STEEL|1|MED DRUM|1602.69|ithely stealt +6697|cream smoke orange brown lawn|Manufacturer#4|Brand#42|PROMO POLISHED STEEL|8|SM PKG|1603.69|ic deposits. slyly spe +6698|orange lace lawn pink papaya|Manufacturer#4|Brand#45|PROMO BURNISHED BRASS|2|SM PACK|1604.69|s. carefu +6699|almond antique metallic honeydew green|Manufacturer#4|Brand#43|MEDIUM BRUSHED TIN|30|LG BAG|1605.69|wake around +6700|frosted metallic khaki coral steel|Manufacturer#4|Brand#44|MEDIUM BURNISHED BRASS|16|SM JAR|1606.70| even theodolit +6701|antique pale honeydew spring maroon|Manufacturer#2|Brand#23|PROMO BRUSHED NICKEL|10|WRAP PKG|1607.70|nto beans doubt qu +6702|violet sienna gainsboro brown cornsilk|Manufacturer#4|Brand#44|SMALL POLISHED NICKEL|44|MED CAN|1608.70|hy reques +6703|light coral sky rose almond|Manufacturer#1|Brand#15|LARGE BRUSHED BRASS|37|JUMBO BOX|1609.70|ic pinto be +6704|lemon burnished firebrick hot royal|Manufacturer#5|Brand#51|SMALL POLISHED NICKEL|23|SM DRUM|1610.70|lyly ironic p +6705|drab sienna cream yellow navajo|Manufacturer#1|Brand#15|STANDARD BURNISHED NICKEL|11|LG BAG|1611.70|ing to the quickly fi +6706|black drab peru almond moccasin|Manufacturer#4|Brand#44|STANDARD ANODIZED STEEL|8|SM PKG|1612.70|fluffil +6707|burlywood snow dark peru saddle|Manufacturer#2|Brand#22|MEDIUM BRUSHED NICKEL|14|SM BOX|1613.70|nusual +6708|goldenrod linen orchid antique azure|Manufacturer#2|Brand#24|SMALL POLISHED BRASS|3|SM DRUM|1614.70|ic deposits +6709|lawn pale red steel rose|Manufacturer#4|Brand#45|LARGE BURNISHED STEEL|16|WRAP CAN|1615.70|iously +6710|plum brown peru cornflower red|Manufacturer#3|Brand#33|LARGE ANODIZED TIN|45|WRAP DRUM|1616.71| are blithely slyly i +6711|honeydew brown powder blue plum|Manufacturer#1|Brand#15|PROMO PLATED NICKEL|35|MED BOX|1617.71|ctions are furiously +6712|moccasin burlywood peru dodger smoke|Manufacturer#3|Brand#35|ECONOMY ANODIZED COPPER|41|WRAP JAR|1618.71|ests hag +6713|sandy midnight honeydew dodger orchid|Manufacturer#5|Brand#55|MEDIUM PLATED NICKEL|31|JUMBO BOX|1619.71|deposits was +6714|midnight lemon blue frosted misty|Manufacturer#3|Brand#31|LARGE BURNISHED COPPER|50|SM BAG|1620.71|detect +6715|ivory azure lavender cyan dim|Manufacturer#3|Brand#33|MEDIUM ANODIZED COPPER|13|WRAP BOX|1621.71|y final deposits a +6716|frosted almond azure hot dim|Manufacturer#3|Brand#31|LARGE ANODIZED STEEL|11|MED CAN|1622.71|ly. platelets are ca +6717|lace sienna plum gainsboro blanched|Manufacturer#1|Brand#15|LARGE BRUSHED STEEL|14|JUMBO DRUM|1623.71|usly ironic pinto +6718|lawn coral papaya steel chartreuse|Manufacturer#4|Brand#41|SMALL BRUSHED COPPER|5|LG CAN|1624.71|eep ironic war +6719|ghost black papaya ivory coral|Manufacturer#2|Brand#21|ECONOMY ANODIZED NICKEL|21|LG CAN|1625.71|kages. +6720|beige burlywood spring olive orange|Manufacturer#5|Brand#53|SMALL BRUSHED NICKEL|8|MED JAR|1626.72|refully regular p +6721|burlywood chocolate midnight puff pink|Manufacturer#2|Brand#23|PROMO POLISHED BRASS|20|LG PKG|1627.72|ely ironic courts. i +6722|ghost moccasin lemon bisque chartreuse|Manufacturer#2|Brand#23|MEDIUM PLATED TIN|10|LG CAN|1628.72|ly even deposits +6723|mint firebrick sienna yellow chocolate|Manufacturer#5|Brand#53|SMALL ANODIZED STEEL|27|SM CAN|1629.72|quickly +6724|seashell sandy pink lemon magenta|Manufacturer#3|Brand#33|PROMO ANODIZED COPPER|27|MED CAN|1630.72|y regular dep +6725|bisque khaki pink chartreuse goldenrod|Manufacturer#4|Brand#45|ECONOMY POLISHED BRASS|50|LG PACK|1631.72|ronic, re +6726|dodger metallic honeydew cream lavender|Manufacturer#3|Brand#33|ECONOMY POLISHED NICKEL|19|SM DRUM|1632.72|fluff +6727|tomato antique brown smoke dark|Manufacturer#2|Brand#24|ECONOMY PLATED TIN|41|WRAP BOX|1633.72|ly. packages +6728|cream antique slate honeydew plum|Manufacturer#5|Brand#53|SMALL BRUSHED COPPER|14|LG PACK|1634.72|riously regular +6729|forest mint cyan goldenrod azure|Manufacturer#1|Brand#12|LARGE BURNISHED TIN|36|LG BOX|1635.72|ong the warthogs i +6730|slate rose cyan blue khaki|Manufacturer#2|Brand#21|STANDARD BURNISHED STEEL|38|SM PKG|1636.73|lites. +6731|steel hot blue dodger ivory|Manufacturer#2|Brand#21|MEDIUM ANODIZED STEEL|10|SM BAG|1637.73|es caj +6732|dark smoke navy dodger papaya|Manufacturer#3|Brand#32|STANDARD PLATED COPPER|16|LG CAN|1638.73|nts-- fluffily i +6733|sienna coral lemon gainsboro grey|Manufacturer#1|Brand#12|SMALL BRUSHED STEEL|11|LG BAG|1639.73|y. slyl +6734|yellow plum powder navajo lavender|Manufacturer#5|Brand#52|SMALL BRUSHED TIN|32|JUMBO DRUM|1640.73|above +6735|sky wheat goldenrod spring plum|Manufacturer#4|Brand#41|MEDIUM BURNISHED STEEL|44|LG PACK|1641.73|ly regular asympto +6736|olive burlywood azure cyan plum|Manufacturer#2|Brand#24|MEDIUM POLISHED TIN|16|SM BOX|1642.73|ts. ex +6737|frosted plum saddle black maroon|Manufacturer#5|Brand#52|PROMO BURNISHED NICKEL|9|WRAP BOX|1643.73|c forges. quickly s +6738|drab slate steel sienna papaya|Manufacturer#3|Brand#32|STANDARD PLATED TIN|50|SM PKG|1644.73|ajole regul +6739|bisque tan coral blue salmon|Manufacturer#1|Brand#11|STANDARD POLISHED COPPER|43|JUMBO CAN|1645.73|blithely unusual +6740|gainsboro mint slate blue coral|Manufacturer#2|Brand#23|LARGE POLISHED STEEL|43|LG JAR|1646.74|xcuses. fluff +6741|brown salmon medium aquamarine magenta|Manufacturer#3|Brand#32|MEDIUM BURNISHED TIN|20|SM BOX|1647.74|osits. furio +6742|wheat yellow dark maroon black|Manufacturer#5|Brand#54|LARGE PLATED BRASS|34|JUMBO PACK|1648.74|ithely special deposi +6743|misty gainsboro sky turquoise forest|Manufacturer#5|Brand#54|STANDARD ANODIZED COPPER|38|MED JAR|1649.74|hely final +6744|navy lavender magenta white dodger|Manufacturer#1|Brand#15|SMALL POLISHED STEEL|6|WRAP DRUM|1650.74| carefully final a +6745|cream steel magenta pale bisque|Manufacturer#3|Brand#33|ECONOMY POLISHED COPPER|12|WRAP BOX|1651.74| theodol +6746|thistle rosy deep mint plum|Manufacturer#5|Brand#51|ECONOMY BURNISHED COPPER|24|MED DRUM|1652.74|refully? slyly +6747|brown drab puff dim thistle|Manufacturer#1|Brand#12|MEDIUM ANODIZED TIN|40|WRAP CAN|1653.74|ymptotes mai +6748|sienna plum papaya green drab|Manufacturer#3|Brand#35|SMALL BURNISHED TIN|26|LG CAN|1654.74|ing to th +6749|yellow royal thistle beige lawn|Manufacturer#4|Brand#41|MEDIUM POLISHED COPPER|44|JUMBO BAG|1655.74|e fluffily after the b +6750|indian dark rosy navy dodger|Manufacturer#5|Brand#51|LARGE POLISHED BRASS|50|SM DRUM|1656.75|arefully ironic packag +6751|sandy steel tomato pink royal|Manufacturer#1|Brand#13|ECONOMY BURNISHED STEEL|15|WRAP PACK|1657.75| foxes. slyl +6752|medium rose sandy puff navy|Manufacturer#4|Brand#42|STANDARD BRUSHED NICKEL|4|SM BOX|1658.75| idea +6753|firebrick lemon burnished ghost maroon|Manufacturer#5|Brand#54|STANDARD BURNISHED STEEL|14|SM PACK|1659.75|ar ideas +6754|medium pink magenta rose burlywood|Manufacturer#1|Brand#15|MEDIUM ANODIZED STEEL|13|WRAP PACK|1660.75|lithely +6755|wheat hot medium honeydew grey|Manufacturer#4|Brand#41|LARGE PLATED COPPER|43|SM BAG|1661.75| to the even p +6756|rosy drab bisque purple ghost|Manufacturer#1|Brand#15|LARGE BURNISHED BRASS|47|JUMBO PACK|1662.75|ickly e +6757|steel brown navajo firebrick medium|Manufacturer#5|Brand#52|LARGE ANODIZED STEEL|5|JUMBO BOX|1663.75|ites serve quickly i +6758|lavender rose honeydew frosted metallic|Manufacturer#5|Brand#55|PROMO PLATED BRASS|38|JUMBO BAG|1664.75|s sleep +6759|burlywood antique bisque brown orchid|Manufacturer#2|Brand#24|ECONOMY BRUSHED COPPER|23|SM DRUM|1665.75|ts nag blithel +6760|rosy azure linen gainsboro chiffon|Manufacturer#5|Brand#52|STANDARD BRUSHED NICKEL|34|MED BAG|1666.76|furiously regula +6761|misty pale aquamarine orange azure|Manufacturer#5|Brand#54|SMALL BURNISHED TIN|26|LG DRUM|1667.76|ular platelets. +6762|rose royal chiffon magenta metallic|Manufacturer#1|Brand#15|SMALL ANODIZED BRASS|34|JUMBO BOX|1668.76|ckage +6763|lace papaya azure aquamarine powder|Manufacturer#4|Brand#43|MEDIUM PLATED STEEL|41|JUMBO PKG|1669.76|wake ca +6764|puff bisque forest almond salmon|Manufacturer#2|Brand#24|PROMO BURNISHED STEEL|50|JUMBO BOX|1670.76|uses cajole furio +6765|maroon tomato royal lavender papaya|Manufacturer#4|Brand#45|MEDIUM ANODIZED TIN|20|JUMBO BAG|1671.76|cing deposits. furi +6766|lace moccasin smoke honeydew burlywood|Manufacturer#2|Brand#22|SMALL POLISHED STEEL|30|MED JAR|1672.76|osits. reg +6767|maroon ghost rosy violet lemon|Manufacturer#2|Brand#25|STANDARD ANODIZED BRASS|12|SM CASE|1673.76|e bli +6768|lace moccasin orchid red beige|Manufacturer#1|Brand#13|SMALL ANODIZED COPPER|40|SM CAN|1674.76|r package +6769|turquoise yellow sky pale olive|Manufacturer#1|Brand#13|PROMO PLATED BRASS|26|JUMBO PKG|1675.76| pack +6770|red pale navajo slate black|Manufacturer#1|Brand#13|LARGE POLISHED COPPER|16|SM DRUM|1676.77|ly ironic asymptotes +6771|misty papaya almond royal chocolate|Manufacturer#3|Brand#31|MEDIUM ANODIZED STEEL|7|JUMBO CASE|1677.77|ully s +6772|lime steel black puff orange|Manufacturer#4|Brand#41|ECONOMY BURNISHED COPPER|8|JUMBO DRUM|1678.77|accounts cajole blithe +6773|orange lime slate powder plum|Manufacturer#2|Brand#23|MEDIUM ANODIZED TIN|24|LG DRUM|1679.77|slyly silent account +6774|cornsilk royal gainsboro powder cream|Manufacturer#5|Brand#51|SMALL ANODIZED NICKEL|40|MED PKG|1680.77|e evenly unusu +6775|rosy navy cream cornflower burnished|Manufacturer#5|Brand#51|LARGE ANODIZED BRASS|22|LG BAG|1681.77|efully expr +6776|puff sienna burlywood midnight drab|Manufacturer#2|Brand#25|SMALL BRUSHED COPPER|26|SM PKG|1682.77|equests boos +6777|honeydew cornflower cyan navajo tan|Manufacturer#1|Brand#15|STANDARD ANODIZED BRASS|35|JUMBO CASE|1683.77| carefully specia +6778|medium goldenrod antique green sandy|Manufacturer#2|Brand#25|MEDIUM POLISHED COPPER|18|MED CASE|1684.77|lways final requests. +6779|floral violet navy tomato maroon|Manufacturer#4|Brand#42|ECONOMY PLATED COPPER|23|LG PACK|1685.77|thely u +6780|rose deep cyan puff navajo|Manufacturer#4|Brand#41|PROMO POLISHED NICKEL|17|SM PKG|1686.78|es. carefully stealthy +6781|saddle pale tan lawn sienna|Manufacturer#2|Brand#25|LARGE BRUSHED STEEL|2|MED BAG|1687.78|ecial +6782|spring khaki bisque honeydew pale|Manufacturer#1|Brand#11|STANDARD BURNISHED STEEL|17|SM CASE|1688.78|counts sleep blithely +6783|hot ghost navy peru blush|Manufacturer#4|Brand#45|LARGE ANODIZED BRASS|7|LG BAG|1689.78|c pinto +6784|thistle burlywood papaya gainsboro lemon|Manufacturer#4|Brand#42|LARGE ANODIZED STEEL|32|JUMBO BOX|1690.78|unts nag blithely wit +6785|chartreuse violet pale puff orchid|Manufacturer#5|Brand#54|STANDARD BURNISHED BRASS|32|MED PKG|1691.78|uickly theodoli +6786|chiffon khaki lawn gainsboro turquoise|Manufacturer#1|Brand#12|LARGE ANODIZED NICKEL|11|JUMBO CAN|1692.78|ently. even, +6787|magenta coral red blush green|Manufacturer#4|Brand#43|STANDARD PLATED NICKEL|14|JUMBO BAG|1693.78|le carefully af +6788|blanched tomato hot chiffon steel|Manufacturer#2|Brand#25|LARGE ANODIZED TIN|50|JUMBO DRUM|1694.78|y bold +6789|cream dodger moccasin violet green|Manufacturer#4|Brand#45|STANDARD ANODIZED TIN|11|LG BAG|1695.78| among the final de +6790|bisque firebrick mint plum burnished|Manufacturer#4|Brand#42|PROMO BURNISHED COPPER|39|SM BOX|1696.79| among the b +6791|moccasin magenta chocolate snow beige|Manufacturer#4|Brand#43|LARGE BURNISHED STEEL|48|WRAP CAN|1697.79|s. pinto beans mainta +6792|aquamarine powder green spring honeydew|Manufacturer#1|Brand#13|MEDIUM PLATED NICKEL|48|MED BAG|1698.79|y above the stealthil +6793|misty grey violet plum lace|Manufacturer#3|Brand#35|PROMO BRUSHED NICKEL|14|JUMBO BAG|1699.79|refully r +6794|khaki seashell pale orange smoke|Manufacturer#3|Brand#34|LARGE BRUSHED NICKEL|23|MED CAN|1700.79|es among +6795|plum maroon azure hot slate|Manufacturer#5|Brand#53|ECONOMY BRUSHED NICKEL|48|WRAP CASE|1701.79|xes w +6796|cyan blue lavender puff tan|Manufacturer#2|Brand#21|PROMO BRUSHED STEEL|14|JUMBO PKG|1702.79|accounts detect furio +6797|almond indian cyan antique snow|Manufacturer#1|Brand#14|STANDARD POLISHED STEEL|8|LG JAR|1703.79|ake furiou +6798|sandy cyan navy hot black|Manufacturer#5|Brand#52|MEDIUM POLISHED TIN|36|SM CAN|1704.79|ely ironic accoun +6799|seashell wheat hot almond rose|Manufacturer#3|Brand#32|MEDIUM BURNISHED NICKEL|1|SM DRUM|1705.79|requests wake f +6800|ghost lawn chartreuse drab plum|Manufacturer#1|Brand#13|STANDARD POLISHED TIN|15|MED CASE|1706.80| express instructi +6801|seashell ghost azure firebrick cornsilk|Manufacturer#3|Brand#34|SMALL ANODIZED BRASS|36|WRAP PKG|1707.80|oxes. foxes among t +6802|floral blush grey frosted wheat|Manufacturer#1|Brand#14|STANDARD BRUSHED NICKEL|41|WRAP BAG|1708.80|ing platele +6803|sienna saddle dodger azure smoke|Manufacturer#3|Brand#33|SMALL BRUSHED BRASS|46|MED BAG|1709.80|ular excus +6804|turquoise medium thistle puff peach|Manufacturer#2|Brand#25|MEDIUM BRUSHED COPPER|40|SM PKG|1710.80|lyly pending ideas. +6805|misty azure green orchid orange|Manufacturer#1|Brand#14|PROMO BURNISHED COPPER|30|WRAP PKG|1711.80| furiously +6806|blush bisque antique lemon gainsboro|Manufacturer#5|Brand#51|PROMO ANODIZED BRASS|28|SM BOX|1712.80|ages. bold foxe +6807|drab wheat snow moccasin saddle|Manufacturer#1|Brand#12|LARGE PLATED NICKEL|48|JUMBO PACK|1713.80| instructions de +6808|steel turquoise drab sky misty|Manufacturer#3|Brand#34|PROMO BURNISHED STEEL|3|MED PKG|1714.80|ously unusual +6809|puff slate misty powder spring|Manufacturer#5|Brand#54|MEDIUM ANODIZED STEEL|22|SM CASE|1715.80|ar requests cajol +6810|tan tomato seashell navajo lawn|Manufacturer#4|Brand#43|STANDARD BRUSHED NICKEL|21|JUMBO JAR|1716.81|uriously regular r +6811|navy blush cornflower lace dim|Manufacturer#5|Brand#54|STANDARD ANODIZED COPPER|42|WRAP BOX|1717.81|kly blithely even a +6812|lime chartreuse papaya blue blush|Manufacturer#4|Brand#41|MEDIUM BURNISHED STEEL|45|SM CAN|1718.81| accounts haggl +6813|light azure royal brown sienna|Manufacturer#2|Brand#25|STANDARD ANODIZED COPPER|17|MED JAR|1719.81|uickly +6814|dim cornflower yellow lemon almond|Manufacturer#4|Brand#44|STANDARD POLISHED BRASS|4|WRAP BOX|1720.81|kages. blithely +6815|deep burlywood aquamarine puff dark|Manufacturer#1|Brand#11|SMALL POLISHED COPPER|14|JUMBO DRUM|1721.81|ss accounts eat dar +6816|peru brown chartreuse dark frosted|Manufacturer#2|Brand#24|STANDARD BURNISHED NICKEL|26|MED BAG|1722.81|s are! slyly +6817|cornsilk peru lavender goldenrod cream|Manufacturer#5|Brand#52|PROMO ANODIZED TIN|8|SM JAR|1723.81|al pinto be +6818|floral smoke light deep pale|Manufacturer#5|Brand#51|PROMO POLISHED BRASS|40|JUMBO PACK|1724.81|nusua +6819|snow violet royal dark khaki|Manufacturer#2|Brand#24|STANDARD PLATED STEEL|5|JUMBO BOX|1725.81| prom +6820|light smoke orchid plum wheat|Manufacturer#1|Brand#11|STANDARD ANODIZED STEEL|1|SM PACK|1726.82|nal deposi +6821|red chocolate tomato orange black|Manufacturer#2|Brand#22|LARGE PLATED BRASS|48|SM DRUM|1727.82|g accounts cajole car +6822|sky deep medium goldenrod lime|Manufacturer#5|Brand#55|STANDARD BRUSHED NICKEL|4|MED CASE|1728.82|ependencies are thinl +6823|tomato white magenta floral ivory|Manufacturer#4|Brand#43|ECONOMY PLATED STEEL|9|JUMBO BOX|1729.82| ironi +6824|tomato firebrick antique mint lemon|Manufacturer#3|Brand#33|LARGE ANODIZED COPPER|45|WRAP JAR|1730.82|ctions alongs +6825|gainsboro lace steel floral orchid|Manufacturer#4|Brand#45|LARGE POLISHED COPPER|24|LG BAG|1731.82|ns. ex +6826|sienna cornflower green lime tomato|Manufacturer#5|Brand#51|MEDIUM POLISHED STEEL|19|JUMBO BOX|1732.82|nts. careful +6827|bisque indian tan red midnight|Manufacturer#3|Brand#32|SMALL BURNISHED BRASS|8|SM BOX|1733.82|accounts-- furiously +6828|bisque sandy powder cornflower blanched|Manufacturer#1|Brand#15|MEDIUM POLISHED TIN|11|JUMBO JAR|1734.82|ic req +6829|midnight lawn steel chocolate salmon|Manufacturer#1|Brand#13|LARGE BRUSHED BRASS|6|MED BAG|1735.82|e regu +6830|violet grey navajo dim blush|Manufacturer#5|Brand#54|PROMO BRUSHED TIN|44|MED CAN|1736.83|s haggle quickly +6831|medium lime papaya cream sky|Manufacturer#1|Brand#15|SMALL BURNISHED BRASS|21|LG JAR|1737.83| final asymptotes. fi +6832|medium blush aquamarine bisque deep|Manufacturer#2|Brand#22|SMALL POLISHED TIN|39|SM BOX|1738.83|xpress +6833|metallic snow black khaki coral|Manufacturer#4|Brand#41|MEDIUM BURNISHED COPPER|25|LG BOX|1739.83|usly final accounts +6834|grey yellow green honeydew navajo|Manufacturer#3|Brand#34|STANDARD BURNISHED COPPER|17|WRAP PACK|1740.83|s inte +6835|blush floral midnight magenta frosted|Manufacturer#4|Brand#44|SMALL ANODIZED NICKEL|38|SM CASE|1741.83|blithely +6836|pale lavender bisque yellow indian|Manufacturer#3|Brand#31|SMALL PLATED TIN|7|LG JAR|1742.83|ges. +6837|drab salmon floral mint burlywood|Manufacturer#3|Brand#31|ECONOMY ANODIZED TIN|29|SM CASE|1743.83|sits na +6838|antique gainsboro aquamarine green spring|Manufacturer#1|Brand#15|PROMO ANODIZED STEEL|35|SM PACK|1744.83|ing packages. bold acc +6839|purple metallic saddle midnight magenta|Manufacturer#3|Brand#32|STANDARD PLATED BRASS|4|MED JAR|1745.83|s wake slyly. +6840|light drab snow coral deep|Manufacturer#1|Brand#15|SMALL ANODIZED NICKEL|26|WRAP BAG|1746.84|riously final ac +6841|lime cornflower ivory dim slate|Manufacturer#1|Brand#14|LARGE POLISHED NICKEL|3|SM DRUM|1747.84|y ruthles +6842|lime medium coral bisque pale|Manufacturer#3|Brand#31|ECONOMY PLATED NICKEL|1|WRAP JAR|1748.84|kages alongside +6843|honeydew violet cornsilk sienna antique|Manufacturer#3|Brand#35|STANDARD BRUSHED STEEL|46|LG PKG|1749.84|s use +6844|cyan chiffon orchid plum rose|Manufacturer#2|Brand#22|LARGE POLISHED TIN|49|SM CAN|1750.84|ess deposits sleep +6845|ghost lime violet cornsilk peach|Manufacturer#4|Brand#45|MEDIUM PLATED STEEL|40|WRAP JAR|1751.84|less fo +6846|white maroon chocolate smoke pink|Manufacturer#5|Brand#53|MEDIUM BURNISHED BRASS|35|WRAP CASE|1752.84|egular pinto +6847|pink moccasin peru puff saddle|Manufacturer#1|Brand#14|SMALL ANODIZED NICKEL|45|SM PACK|1753.84| accounts accord +6848|rosy honeydew plum tomato deep|Manufacturer#1|Brand#14|PROMO POLISHED BRASS|9|LG BOX|1754.84|romis +6849|powder pale dodger firebrick wheat|Manufacturer#3|Brand#34|STANDARD BURNISHED STEEL|32|JUMBO CASE|1755.84|ost sly +6850|brown blue tan hot blush|Manufacturer#5|Brand#53|ECONOMY ANODIZED STEEL|26|MED CAN|1756.85|ts integrate accordin +6851|red peach seashell honeydew burlywood|Manufacturer#5|Brand#51|MEDIUM BRUSHED TIN|36|JUMBO BAG|1757.85|uests kindle f +6852|pale cornsilk metallic brown beige|Manufacturer#2|Brand#23|PROMO POLISHED COPPER|25|SM PKG|1758.85| fluffily even ac +6853|purple sandy dark powder indian|Manufacturer#1|Brand#14|ECONOMY POLISHED COPPER|44|MED CASE|1759.85|bout the p +6854|azure navy gainsboro cream ghost|Manufacturer#4|Brand#41|ECONOMY BRUSHED BRASS|15|JUMBO JAR|1760.85|bout the carefully reg +6855|magenta spring orchid azure frosted|Manufacturer#5|Brand#51|PROMO ANODIZED NICKEL|6|WRAP DRUM|1761.85|l orbi +6856|blanched midnight cream papaya drab|Manufacturer#4|Brand#41|SMALL BRUSHED TIN|5|JUMBO CAN|1762.85|s haggle above the flu +6857|red spring blush cornsilk peach|Manufacturer#4|Brand#42|STANDARD POLISHED TIN|46|LG JAR|1763.85| quickly unu +6858|blush puff firebrick beige deep|Manufacturer#1|Brand#11|SMALL BRUSHED BRASS|30|WRAP BOX|1764.85|t evenly express ac +6859|snow lavender navy linen chartreuse|Manufacturer#3|Brand#35|ECONOMY ANODIZED NICKEL|35|MED PKG|1765.85|sual dolphi +6860|snow green linen dim orange|Manufacturer#1|Brand#14|LARGE POLISHED STEEL|9|LG JAR|1766.86|ly caref +6861|white violet coral olive metallic|Manufacturer#2|Brand#23|STANDARD POLISHED BRASS|32|MED BAG|1767.86| the slyly +6862|violet cornflower pink rose burnished|Manufacturer#1|Brand#13|PROMO POLISHED TIN|36|JUMBO CAN|1768.86|ckages cajole sl +6863|brown bisque linen cyan drab|Manufacturer#3|Brand#35|ECONOMY BURNISHED NICKEL|25|JUMBO CAN|1769.86|aggle slyly ste +6864|burnished misty firebrick cream papaya|Manufacturer#4|Brand#45|SMALL PLATED NICKEL|20|WRAP CAN|1770.86|y even accounts acros +6865|seashell salmon lace mint aquamarine|Manufacturer#3|Brand#35|MEDIUM BRUSHED NICKEL|17|SM BOX|1771.86|l depend +6866|goldenrod midnight metallic cornsilk wheat|Manufacturer#5|Brand#54|ECONOMY POLISHED COPPER|23|SM DRUM|1772.86|quickly along the slyl +6867|green puff blanched light lawn|Manufacturer#2|Brand#21|MEDIUM BRUSHED TIN|21|WRAP DRUM|1773.86|ns. final foxes al +6868|gainsboro goldenrod white forest navy|Manufacturer#5|Brand#52|STANDARD ANODIZED BRASS|17|MED BAG|1774.86|es. furiousl +6869|grey salmon seashell bisque linen|Manufacturer#1|Brand#14|MEDIUM PLATED BRASS|39|WRAP BAG|1775.86|nic ac +6870|chartreuse firebrick indian royal sky|Manufacturer#5|Brand#53|LARGE POLISHED TIN|33|WRAP BOX|1776.87|ar accounts affix bli +6871|peach steel turquoise sky forest|Manufacturer#1|Brand#11|ECONOMY PLATED STEEL|46|WRAP PKG|1777.87|r theodolites. ca +6872|hot almond azure lace forest|Manufacturer#2|Brand#21|PROMO BRUSHED TIN|41|LG PACK|1778.87|l packages boost aft +6873|medium red dark saddle white|Manufacturer#4|Brand#43|PROMO PLATED STEEL|47|MED DRUM|1779.87|unts snooze by the +6874|violet burnished misty medium frosted|Manufacturer#5|Brand#53|SMALL BRUSHED TIN|3|MED PKG|1780.87|above th +6875|blue papaya steel lemon cyan|Manufacturer#2|Brand#25|ECONOMY PLATED NICKEL|22|JUMBO JAR|1781.87|ts are deposits. slyl +6876|lavender sandy mint light deep|Manufacturer#1|Brand#14|LARGE BRUSHED TIN|5|MED PKG|1782.87|ickly regular, silent +6877|lemon ghost green thistle peru|Manufacturer#3|Brand#33|LARGE POLISHED COPPER|16|JUMBO PKG|1783.87|kly b +6878|cream wheat aquamarine yellow burlywood|Manufacturer#1|Brand#12|ECONOMY ANODIZED COPPER|44|LG BOX|1784.87|ular dep +6879|sienna slate chartreuse lavender rose|Manufacturer#5|Brand#51|STANDARD PLATED COPPER|25|JUMBO DRUM|1785.87|r the d +6880|lemon tan orchid white grey|Manufacturer#4|Brand#42|LARGE PLATED NICKEL|11|LG JAR|1786.88|ss deposits. carefull +6881|chiffon indian green salmon antique|Manufacturer#3|Brand#35|STANDARD POLISHED TIN|45|LG CAN|1787.88|he even pinto +6882|burlywood antique light cornflower beige|Manufacturer#2|Brand#21|LARGE ANODIZED BRASS|5|MED CASE|1788.88|e furiously bold +6883|royal aquamarine frosted moccasin beige|Manufacturer#1|Brand#14|ECONOMY BRUSHED BRASS|11|LG BAG|1789.88|venly express ideas. q +6884|smoke misty blanched burnished antique|Manufacturer#4|Brand#41|STANDARD BURNISHED COPPER|35|SM BOX|1790.88|tes use ac +6885|tomato pale dodger ghost orchid|Manufacturer#3|Brand#35|MEDIUM PLATED COPPER|46|JUMBO CASE|1791.88|ly regular d +6886|lace olive navy lime snow|Manufacturer#2|Brand#24|SMALL POLISHED COPPER|16|WRAP PKG|1792.88|e the even d +6887|linen ivory dim smoke seashell|Manufacturer#4|Brand#41|STANDARD BRUSHED BRASS|24|MED BAG|1793.88|s sleep +6888|azure purple moccasin magenta peru|Manufacturer#1|Brand#11|MEDIUM POLISHED TIN|4|SM PKG|1794.88|r request +6889|chiffon royal lemon sandy ivory|Manufacturer#2|Brand#22|MEDIUM PLATED BRASS|4|MED CASE|1795.88|ing to the even pl +6890|magenta misty peach medium peru|Manufacturer#2|Brand#24|ECONOMY POLISHED TIN|22|JUMBO CAN|1796.89|accounts. +6891|salmon brown red lavender sky|Manufacturer#1|Brand#11|SMALL ANODIZED COPPER|31|LG BAG|1797.89|pecia +6892|dim almond deep drab pale|Manufacturer#2|Brand#25|LARGE POLISHED NICKEL|37|WRAP DRUM|1798.89| beans; q +6893|metallic beige azure salmon brown|Manufacturer#2|Brand#21|PROMO BRUSHED BRASS|5|SM PACK|1799.89|ly ironic acc +6894|cyan grey violet deep almond|Manufacturer#1|Brand#13|SMALL PLATED TIN|30|LG JAR|1800.89|. expres +6895|thistle turquoise olive mint antique|Manufacturer#1|Brand#14|MEDIUM BRUSHED BRASS|20|JUMBO CASE|1801.89|sly ironic reque +6896|olive smoke lemon goldenrod moccasin|Manufacturer#3|Brand#35|SMALL PLATED STEEL|43|JUMBO BOX|1802.89|ts. enticingly expre +6897|coral magenta mint firebrick white|Manufacturer#4|Brand#41|ECONOMY BRUSHED BRASS|4|LG BAG|1803.89| blithely +6898|green yellow blue peach thistle|Manufacturer#1|Brand#13|LARGE PLATED STEEL|29|MED DRUM|1804.89|. pinto +6899|lemon maroon drab lace peru|Manufacturer#3|Brand#34|MEDIUM BRUSHED BRASS|49|JUMBO CASE|1805.89|sily express theodolit +6900|bisque blue navy turquoise saddle|Manufacturer#2|Brand#25|MEDIUM BRUSHED NICKEL|42|SM BOX|1806.90|le. bold +6901|indian drab lavender purple bisque|Manufacturer#4|Brand#42|PROMO ANODIZED STEEL|25|WRAP CASE|1807.90|e carefully +6902|ghost green violet mint bisque|Manufacturer#2|Brand#23|STANDARD ANODIZED BRASS|19|LG CAN|1808.90| deposits boost ab +6903|mint grey turquoise burnished spring|Manufacturer#3|Brand#32|LARGE POLISHED NICKEL|3|JUMBO BAG|1809.90|its acros +6904|deep salmon olive drab thistle|Manufacturer#3|Brand#32|SMALL PLATED BRASS|6|LG CAN|1810.90|deas promise ab +6905|sandy powder bisque orchid hot|Manufacturer#1|Brand#12|LARGE BURNISHED BRASS|32|LG BAG|1811.90| ironic packages al +6906|black moccasin deep lace blush|Manufacturer#5|Brand#51|STANDARD BURNISHED STEEL|23|SM PACK|1812.90|unts will sleep sp +6907|grey dodger lawn thistle tomato|Manufacturer#1|Brand#12|ECONOMY BRUSHED NICKEL|22|SM CAN|1813.90|ts mold furiously. +6908|royal rose peach rosy azure|Manufacturer#4|Brand#44|ECONOMY BRUSHED BRASS|7|LG CAN|1814.90|. furiously fi +6909|plum cornflower gainsboro tomato lavender|Manufacturer#5|Brand#53|SMALL ANODIZED NICKEL|12|SM CASE|1815.90|y ironic request +6910|coral steel deep sienna orange|Manufacturer#4|Brand#42|MEDIUM BRUSHED STEEL|6|JUMBO BAG|1816.91| silent accounts aft +6911|sky papaya magenta tomato peach|Manufacturer#2|Brand#22|PROMO POLISHED BRASS|31|JUMBO BOX|1817.91|ously through the +6912|olive brown navy chartreuse rose|Manufacturer#5|Brand#54|MEDIUM BRUSHED NICKEL|6|JUMBO PKG|1818.91|eat b +6913|grey rosy tan puff sienna|Manufacturer#1|Brand#13|SMALL PLATED COPPER|15|MED CAN|1819.91| the slyly +6914|peach indian maroon chiffon saddle|Manufacturer#2|Brand#22|STANDARD PLATED NICKEL|18|WRAP PACK|1820.91|ly final depos +6915|linen khaki saddle chocolate medium|Manufacturer#5|Brand#51|LARGE ANODIZED COPPER|37|SM BAG|1821.91|pendenc +6916|azure snow rose sandy chartreuse|Manufacturer#3|Brand#33|MEDIUM PLATED STEEL|1|SM BAG|1822.91|usly unusua +6917|steel black moccasin lace ghost|Manufacturer#3|Brand#34|SMALL ANODIZED NICKEL|42|LG PACK|1823.91| theo +6918|bisque mint drab gainsboro orange|Manufacturer#1|Brand#14|SMALL BRUSHED TIN|36|SM CASE|1824.91|ges? furiously e +6919|linen smoke light powder papaya|Manufacturer#2|Brand#22|ECONOMY BRUSHED TIN|18|WRAP BAG|1825.91|ully blithely bold id +6920|rose pink chartreuse dim deep|Manufacturer#3|Brand#34|STANDARD PLATED COPPER|50|WRAP CAN|1826.92|carefully. +6921|green puff forest pale lawn|Manufacturer#3|Brand#34|MEDIUM PLATED COPPER|10|SM BOX|1827.92|usly. stealthy courts +6922|firebrick lime cream magenta maroon|Manufacturer#3|Brand#32|LARGE ANODIZED STEEL|25|WRAP JAR|1828.92|the blithely bold th +6923|ivory firebrick seashell peach navajo|Manufacturer#1|Brand#12|STANDARD POLISHED BRASS|49|JUMBO DRUM|1829.92|s. quickly unusual +6924|powder blanched maroon violet magenta|Manufacturer#2|Brand#21|MEDIUM BURNISHED COPPER|43|WRAP PACK|1830.92| fluffy depende +6925|dodger forest cream khaki aquamarine|Manufacturer#5|Brand#51|LARGE POLISHED NICKEL|23|WRAP DRUM|1831.92|areful +6926|azure drab floral khaki spring|Manufacturer#5|Brand#52|LARGE PLATED STEEL|10|WRAP PACK|1832.92|ly pendin +6927|plum honeydew azure lime pale|Manufacturer#5|Brand#52|PROMO POLISHED BRASS|23|JUMBO BAG|1833.92| furi +6928|violet magenta peach lemon burnished|Manufacturer#2|Brand#22|MEDIUM ANODIZED STEEL|39|WRAP CAN|1834.92|s. blith +6929|spring goldenrod violet lemon slate|Manufacturer#3|Brand#35|PROMO PLATED STEEL|4|SM PKG|1835.92|ole fluffily. s +6930|chartreuse plum orchid violet lavender|Manufacturer#4|Brand#43|MEDIUM PLATED BRASS|15|WRAP CASE|1836.93| express, sile +6931|ghost black coral magenta mint|Manufacturer#5|Brand#52|SMALL PLATED NICKEL|43|SM CAN|1837.93|l gifts nag slyly af +6932|red pale firebrick turquoise moccasin|Manufacturer#4|Brand#45|PROMO POLISHED COPPER|30|JUMBO JAR|1838.93|nag carefully theodo +6933|mint smoke white olive powder|Manufacturer#3|Brand#34|STANDARD BURNISHED TIN|39|JUMBO BOX|1839.93|old accounts sleep +6934|tan slate orchid peru red|Manufacturer#1|Brand#13|SMALL BURNISHED STEEL|48|SM CAN|1840.93| quickly f +6935|lawn forest blanched burlywood pale|Manufacturer#2|Brand#24|SMALL PLATED COPPER|14|LG DRUM|1841.93|yly. +6936|dim orange indian drab midnight|Manufacturer#1|Brand#14|STANDARD ANODIZED NICKEL|28|WRAP DRUM|1842.93|es. s +6937|drab beige sky cornsilk firebrick|Manufacturer#2|Brand#21|STANDARD BRUSHED STEEL|33|JUMBO PKG|1843.93|asymptotes: final t +6938|linen burnished lemon drab moccasin|Manufacturer#2|Brand#25|LARGE PLATED STEEL|25|MED PKG|1844.93|nic accounts cajole +6939|mint pale antique rose orange|Manufacturer#1|Brand#15|SMALL PLATED TIN|28|WRAP BAG|1845.93|among the fur +6940|linen cyan chiffon tomato red|Manufacturer#3|Brand#33|PROMO BURNISHED NICKEL|5|SM JAR|1846.94|slyly final, +6941|honeydew plum blush lemon chiffon|Manufacturer#1|Brand#11|PROMO PLATED BRASS|40|WRAP PACK|1847.94|e even, expre +6942|thistle deep dim almond maroon|Manufacturer#3|Brand#31|PROMO BURNISHED STEEL|4|WRAP PKG|1848.94| packag +6943|peru rose lavender light puff|Manufacturer#2|Brand#21|STANDARD ANODIZED BRASS|9|SM BAG|1849.94|ts. bli +6944|sky chocolate olive yellow blanched|Manufacturer#5|Brand#51|MEDIUM POLISHED STEEL|41|JUMBO PACK|1850.94| the pending, final +6945|cornsilk slate peru chiffon orchid|Manufacturer#2|Brand#25|PROMO POLISHED STEEL|34|JUMBO JAR|1851.94|pecial package +6946|chartreuse saddle peach plum burnished|Manufacturer#3|Brand#33|PROMO BURNISHED BRASS|44|SM PACK|1852.94|uests boost furiously +6947|indian dim lace papaya blue|Manufacturer#2|Brand#22|MEDIUM BRUSHED COPPER|18|MED CAN|1853.94| unusu +6948|peach seashell black gainsboro deep|Manufacturer#1|Brand#12|SMALL BRUSHED STEEL|28|WRAP BOX|1854.94|s accou +6949|slate dim cyan navajo white|Manufacturer#5|Brand#55|LARGE BRUSHED NICKEL|26|WRAP PACK|1855.94|lets. +6950|sky ivory cream turquoise aquamarine|Manufacturer#1|Brand#13|ECONOMY BURNISHED STEEL|13|WRAP CAN|1856.95|aggle furiou +6951|tan sandy royal sienna puff|Manufacturer#1|Brand#14|MEDIUM ANODIZED TIN|12|SM BAG|1857.95| accounts wak +6952|gainsboro sienna blush forest lemon|Manufacturer#4|Brand#41|MEDIUM ANODIZED BRASS|37|LG CAN|1858.95|nt packages a +6953|pale plum dark seashell orchid|Manufacturer#3|Brand#34|PROMO BRUSHED NICKEL|12|WRAP PKG|1859.95|. ironic +6954|cornsilk ivory midnight pale blanched|Manufacturer#3|Brand#34|ECONOMY BURNISHED COPPER|27|WRAP BOX|1860.95|regular dep +6955|drab chartreuse cyan wheat snow|Manufacturer#2|Brand#24|SMALL BURNISHED TIN|26|JUMBO CAN|1861.95|ronic, ironic acco +6956|ivory navajo purple blush green|Manufacturer#2|Brand#24|MEDIUM POLISHED COPPER|17|JUMBO DRUM|1862.95| pinto beans sleep fu +6957|salmon pink sky seashell tomato|Manufacturer#5|Brand#54|LARGE PLATED STEEL|5|JUMBO DRUM|1863.95|thely furiously +6958|misty azure floral aquamarine dim|Manufacturer#1|Brand#15|PROMO ANODIZED COPPER|32|SM JAR|1864.95|ully after +6959|puff green deep dark sienna|Manufacturer#5|Brand#51|SMALL PLATED BRASS|28|SM BAG|1865.95| deposits wake care +6960|antique orchid dim linen peru|Manufacturer#5|Brand#53|ECONOMY ANODIZED BRASS|48|JUMBO PKG|1866.96|beans slee +6961|slate drab maroon thistle puff|Manufacturer#3|Brand#35|ECONOMY BURNISHED NICKEL|18|SM JAR|1867.96|s believe furiously! a +6962|green aquamarine azure midnight chiffon|Manufacturer#1|Brand#11|STANDARD BRUSHED BRASS|44|JUMBO JAR|1868.96|e fluffily. expr +6963|maroon deep frosted hot coral|Manufacturer#1|Brand#13|ECONOMY BRUSHED TIN|31|SM PKG|1869.96|arefully carefull +6964|moccasin dodger ivory plum sky|Manufacturer#4|Brand#41|SMALL PLATED TIN|50|LG BOX|1870.96|hless +6965|snow spring peach dodger green|Manufacturer#1|Brand#13|STANDARD BURNISHED COPPER|45|JUMBO CAN|1871.96| nag. q +6966|olive blanched drab smoke light|Manufacturer#4|Brand#42|STANDARD ANODIZED STEEL|22|WRAP BOX|1872.96|sits haggle bold +6967|puff hot brown sky pink|Manufacturer#5|Brand#53|SMALL BURNISHED BRASS|9|SM PACK|1873.96| beans cajole qu +6968|spring red royal turquoise ghost|Manufacturer#3|Brand#35|ECONOMY BRUSHED NICKEL|24|JUMBO BOX|1874.96|indle furiously regula +6969|powder steel lemon aquamarine deep|Manufacturer#2|Brand#21|MEDIUM ANODIZED BRASS|37|JUMBO BAG|1875.96|ily regular requests. +6970|powder hot moccasin deep goldenrod|Manufacturer#5|Brand#52|LARGE POLISHED BRASS|12|JUMBO PKG|1876.97|ly eve +6971|navajo seashell gainsboro light metallic|Manufacturer#4|Brand#45|SMALL BURNISHED NICKEL|6|JUMBO CAN|1877.97|e slyly r +6972|midnight white smoke lavender goldenrod|Manufacturer#2|Brand#23|ECONOMY POLISHED STEEL|20|SM JAR|1878.97|mptotes. depe +6973|grey seashell navajo lace cream|Manufacturer#1|Brand#12|SMALL BRUSHED TIN|16|WRAP PKG|1879.97|t packages inte +6974|beige drab metallic firebrick yellow|Manufacturer#2|Brand#23|MEDIUM ANODIZED STEEL|12|JUMBO BAG|1880.97|ironic ac +6975|smoke maroon peru salmon puff|Manufacturer#4|Brand#41|MEDIUM BRUSHED COPPER|35|JUMBO JAR|1881.97|iously ironic acc +6976|snow blanched midnight smoke olive|Manufacturer#4|Brand#42|PROMO BURNISHED COPPER|20|LG CASE|1882.97|theodolites +6977|papaya lemon olive maroon grey|Manufacturer#4|Brand#42|PROMO POLISHED COPPER|37|LG PACK|1883.97|ld instru +6978|yellow peach lace chiffon linen|Manufacturer#4|Brand#45|MEDIUM ANODIZED BRASS|6|SM PACK|1884.97| abou +6979|dodger saddle thistle drab seashell|Manufacturer#1|Brand#12|STANDARD POLISHED COPPER|2|WRAP PKG|1885.97|e regular, even +6980|thistle linen orange white burlywood|Manufacturer#5|Brand#53|STANDARD BRUSHED STEEL|35|WRAP PACK|1886.98|along the ironi +6981|cyan blue blanched tan hot|Manufacturer#1|Brand#12|PROMO PLATED TIN|34|WRAP PKG|1887.98|ructions are al +6982|brown wheat cream cornsilk pink|Manufacturer#2|Brand#22|SMALL POLISHED BRASS|12|LG PKG|1888.98|ons wake against th +6983|cornsilk royal olive smoke forest|Manufacturer#3|Brand#32|MEDIUM POLISHED BRASS|39|MED CASE|1889.98|uriously special foxes +6984|lime turquoise lavender floral rosy|Manufacturer#2|Brand#21|PROMO BURNISHED TIN|34|JUMBO PACK|1890.98|ly regular gifts det +6985|white black navy turquoise light|Manufacturer#4|Brand#44|MEDIUM BRUSHED COPPER|48|SM CASE|1891.98| packa +6986|lemon sky chocolate green linen|Manufacturer#2|Brand#21|ECONOMY BRUSHED BRASS|14|LG CAN|1892.98|ges. a +6987|grey burnished white antique beige|Manufacturer#2|Brand#23|ECONOMY POLISHED NICKEL|15|JUMBO PACK|1893.98|ctions wake furiously +6988|cream mint drab tomato ghost|Manufacturer#2|Brand#22|STANDARD ANODIZED BRASS|35|MED PKG|1894.98| deposit +6989|puff bisque wheat dim seashell|Manufacturer#5|Brand#55|STANDARD POLISHED COPPER|4|WRAP PACK|1895.98|s use accordi +6990|red coral violet white medium|Manufacturer#5|Brand#53|STANDARD BURNISHED NICKEL|44|JUMBO CASE|1896.99|ously ironic escapades +6991|drab chartreuse plum white goldenrod|Manufacturer#5|Brand#52|MEDIUM BRUSHED STEEL|33|WRAP BAG|1897.99| the +6992|chocolate lawn mint blanched turquoise|Manufacturer#5|Brand#52|SMALL BURNISHED TIN|21|SM BAG|1898.99|refully silent asympt +6993|thistle blanched peach red navy|Manufacturer#2|Brand#23|SMALL BURNISHED BRASS|1|MED JAR|1899.99|cial theodolites alon +6994|plum smoke cream navajo wheat|Manufacturer#4|Brand#43|PROMO BRUSHED NICKEL|35|JUMBO CASE|1900.99|gle. furi +6995|dim sienna navy smoke coral|Manufacturer#5|Brand#54|LARGE PLATED NICKEL|41|MED CASE|1901.99| according to +6996|metallic pale cornsilk antique tan|Manufacturer#2|Brand#21|LARGE ANODIZED TIN|45|WRAP BOX|1902.99|ly. blithely +6997|peru blanched burlywood lavender black|Manufacturer#5|Brand#54|SMALL BRUSHED STEEL|27|SM BAG|1903.99|gular sheaves! ca +6998|metallic khaki purple cyan cream|Manufacturer#1|Brand#12|STANDARD ANODIZED NICKEL|20|JUMBO BAG|1904.99|equest +6999|moccasin burlywood plum tomato azure|Manufacturer#3|Brand#31|PROMO PLATED TIN|18|JUMBO CAN|1905.99|ular deposits a +7000|beige orchid royal lace burnished|Manufacturer#4|Brand#44|ECONOMY ANODIZED NICKEL|37|WRAP CASE|907.00|. furiously c diff --git a/src/test/regress/data/supplier.data b/src/test/regress/data/supplier.data new file mode 100644 index 000000000..a05519f00 --- /dev/null +++ b/src/test/regress/data/supplier.data @@ -0,0 +1,1000 @@ +1|Supplier#000000001| N kD4on9OM Ipw3,gf0JBoQDd7tgrzrddZ|\N|27-918-335-1736|5755.94|each slyly above the careful +2|Supplier#000000002|89eJ5ksX3ImxJQBvxObC,|\N|15-679-861-2259|4032.68| slyly bold instructions. idle dependen +3|Supplier#000000003|q1,G3Pj6OjIuUYfUoH18BFTKP5aU9bEV3|\N|11-383-516-1199|4192.40|blithely silent requests after the express dependencies are sl +4|Supplier#000000004|Bk7ah4CK8SYQTepEmvMkkgMwg|\N|25-843-787-7479|4641.08|riously even requests above the exp +5|Supplier#000000005|Gcdm2rJRzl5qlTVzc|\N|21-151-690-3663|-283.84|. slyly regular pinto bea +6|Supplier#000000006|tQxuVm7s7CnK|\N|24-696-997-4969|1365.79|final accounts. regular dolphins use against the furiously ironic decoys. +7|Supplier#000000007|s,4TicNGB4uO6PaSqNBUq|0|33-990-965-2201|6820.35|s unwind silently furiously regular courts. final requests are deposits. requests wake quietly blit +8|Supplier#000000008|9Sq4bBH2FQEmaFOocY45sRTxo6yuoG|0|27-498-742-3860|7627.85|al pinto beans. asymptotes haggl +9|Supplier#000000009|1KhUgZegwM3ua7dsYmekYBsK|0|20-403-398-8662|5302.37|s. unusual, even requests along the furiously regular pac +10|Supplier#000000010|Saygah3gYWMp72i PY|0|34-852-489-8585|3891.91|ing waters. regular requests ar +11|Supplier#000000011|JfwTs,LZrV, M,9C|18|28-613-996-1505|3393.08|y ironic packages. slyly ironic accounts affix furiously; ironically unusual excuses across the flu +12|Supplier#000000012|aLIW q0HYd|8|18-179-925-7181|1432.69|al packages nag alongside of the bold instructions. express, daring accounts +13|Supplier#000000013|HK71HQyWoqRWOX8GI FpgAifW,2PoH|3|13-727-620-7813|9107.22|requests engage regularly instructions. furiously special requests ar +14|Supplier#000000014|EXsnO5pTNj4iZRm|15|25-656-247-5058|9189.82|l accounts boost. fluffily bold warhorses wake +15|Supplier#000000015|olXVbNBfVzRqgokr1T,Ie|8|18-453-357-6394|308.56| across the furiously regular platelets wake even deposits. quickly express she +16|Supplier#000000016|YjP5C55zHDXL7LalK27zfQnwejdpin4AMpvh|22|32-822-502-4215|2972.26|ously express ideas haggle quickly dugouts? fu +17|Supplier#000000017|c2d,ESHRSkK3WYnxpgw6aOqN0q|19|29-601-884-9219|1687.81|eep against the furiously bold ideas. fluffily bold packa +18|Supplier#000000018|PGGVE5PWAMwKDZw |16|26-729-551-1115|7040.82|accounts snooze slyly furiously bold +19|Supplier#000000019|edZT3es,nBFD8lBXTGeTl|24|34-278-310-2731|6150.38|refully final foxes across the dogged theodolites sleep slyly abou +20|Supplier#000000020|iybAE,RmTymrZVYaFZva2SH,j|3|13-715-945-6730|530.82|n, ironic ideas would nag blithely about the slyly regular accounts. silent, expr +21|Supplier#000000021|81CavellcrJ0PQ3CPBID0Z0JwyJm0ka5igEs|2|12-253-590-5816|9365.80|d. instructions integrate sometimes slyly pending instructions. accounts nag among the +22|Supplier#000000022|okiiQFk 8lm6EVX6Q0,bEcO|4|14-144-830-2814|-966.20| ironically among the deposits. closely expre +23|Supplier#000000023|ssetugTcXc096qlD7 2TL5crEEeS3zk|9|19-559-422-5776|5926.41|ges could have to are ironic deposits. regular, even request +24|Supplier#000000024|C4nPvLrVmKPPabFCj|0|10-620-939-2254|9170.71|usly pending deposits. slyly final accounts run +25|Supplier#000000025|RCQKONXMFnrodzz6w7fObFVV6CUm2q|22|32-431-945-3541|9198.31|ely regular deposits. carefully regular sauternes engage furiously above the regular accounts. idly +26|Supplier#000000026|iV,MHzAx6Z939uzFNkq09M0a1 MBfH7|21|31-758-894-4436|21.18| ideas poach carefully after the blithely bold asymptotes. furiously pending theodoli +27|Supplier#000000027|lC4CjKwNHUr6L4xIpzOBK4NlHkFTg|18|28-708-999-2028|1887.62|s according to the quickly regular hockey playe +28|Supplier#000000028|GBhvoRh,7YIN V|0|10-538-384-8460|-891.99|ld requests across the pinto beans are carefully against the quickly final courts. accounts sleep +29|Supplier#000000029|658tEqXLPvRd6xpFdqC2|1|11-555-705-5922|-811.62|y express ideas play furiously. even accounts sleep fluffily across the accounts. careful +30|Supplier#000000030|84NmC1rmQfO0fj3zkobLT|16|26-940-594-4852|8080.14|ias. carefully silent accounts cajole blithely. pending, special accounts cajole quickly above the f +31|Supplier#000000031|fRJimA7zchyApqRLHcQeocVpP|16|26-515-530-4159|5916.91|into beans wake after the special packages. slyly fluffy requests cajole furio +32|Supplier#000000032|yvoD3TtZSx1skQNCK8agk5bZlZLug|23|33-484-637-7873|3556.47|usly even depths. quickly ironic theodolites s +33|Supplier#000000033|gfeKpYw3400L0SDywXA6Ya1Qmq1w6YB9f3R|7|17-138-897-9374|8564.12|n sauternes along the regular asymptotes are regularly along the +34|Supplier#000000034|mYRe3KvA2O4lL4HhxDKkkrPUDPMKRCSp,Xpa|10|20-519-982-2343|237.31|eposits. slyly final deposits toward the slyly regular dependencies sleep among the excu +35|Supplier#000000035|QymmGXxjVVQ5OuABCXVVsu,4eF gU0Qc6|21|31-720-790-5245|4381.41| ironic deposits! final, bold platelets haggle quickly quickly pendin +36|Supplier#000000036|mzSpBBJvbjdx3UKTW3bLFewRD78D91lAC879|13|23-273-493-3679|2371.51|ular theodolites must haggle regular, bold accounts. slyly final pinto beans bo +37|Supplier#000000037|cqjyB5h1nV|0|10-470-144-1330|3017.47|iously final instructions. quickly special accounts hang fluffily above the accounts. deposits +38|Supplier#000000038|xEcx45vD0FXHT7c9mvWFY|4|14-361-296-6426|2512.41|ins. fluffily special accounts haggle slyly af +39|Supplier#000000039|ZM, nSYpEPWr1yAFHaC91qjFcijjeU5eH|8|18-851-856-5633|6115.65|le slyly requests. special packages shall are blithely. slyly unusual packages sleep +40|Supplier#000000040|zyIeWzbbpkTV37vm1nmSGBxSgd2Kp|22|32-231-247-6991|-290.06| final patterns. accounts haggle idly pas +41|Supplier#000000041|G 1FKHR435 wMKFmyt|18|28-739-447-2525|6942.67|odolites boost across the furiously regular fo +42|Supplier#000000042|1Y5lwEgpe3j2vbUBYj3SwLhK62JlwEMtDC|22|32-698-298-6317|6565.11| fluffily even requests cajole blithely fu +43|Supplier#000000043|Z5mLuAoTUEeKY5v22VnnA4D87Ao6jF2LvMYnlX8h|12|22-421-568-4862|7773.41|unts. unusual, final asymptotes +44|Supplier#000000044|kERxlLDnlIZJdN66zAPHklyL|7|17-713-930-5667|9759.38|x. carefully quiet account +45|Supplier#000000045|LcKnsa8XGtIO0WYSB7hkOrH rnzRg1|9|19-189-635-8862|2944.23|iously according to the ironic, silent accounts. +46|Supplier#000000046|e0URUXfDOYMdKe16Z5h5StMRbzGmTs,D2cjap|24|34-748-308-3215|3580.35|gular, regular ideas across th +47|Supplier#000000047|3XM1x,Pcxqw,HK4XNlgbnZMbLhBHLA|14|24-810-354-4471|2958.09|sly ironic deposits sleep carefully along t +48|Supplier#000000048|jg0U FNPMQDuyuKvTnLXXaLf3Wl6OtONA6mQlWJ|14|24-722-551-9498|5630.62|xpress instructions affix. fluffily even requests boos +49|Supplier#000000049|Nvq 6macF4GtJvz|24|34-211-567-6800|9915.24|the finally bold dependencies. dependencies after the fluffily final foxes boost fluffi +50|Supplier#000000050|rGobqSMMYz0ErrPhCGS|9|19-561-560-7437|4515.87|warhorses. ironic, regular accounts detect slyly after the quickly f +51|Supplier#000000051|rDkBXb01POIKjOwrij62uM8O4|9|19-475-537-1368|7241.40|ges nag at the blithely busy instructions. fluffy packages wake quickly. even, ironic ideas boost b +52|Supplier#000000052|WCk XCHYzBA1dvJDSol4ZJQQcQN,|19|29-974-934-4713|287.16|dolites are slyly against the furiously regular packages. ironic, final deposits cajole quickly +53|Supplier#000000053|i9v3 EsYCfLKFU6PIt8iihBOHBB37yR7b3GD7Rt|7|17-886-101-6083|6177.35|onic, special deposits wake furio +54|Supplier#000000054|J1s,Wxb5pg|12|22-966-435-7200|2733.69|blithely pending dolphins. quickly regular theodolites haggle slyly +55|Supplier#000000055|OqdYSiOQeG4eGi636Tj|24|34-876-912-6007|7162.15|kages. blithely even foxes cajole special, final accounts. blithely even dependencies r +56|Supplier#000000056|fUVtlUVal GiHBOuYoUQ XQ9NfNLQR3Gl|16|26-471-195-5486|-632.16| sleep special deposits. unusual requests wake blithely slyly regular ideas. +57|Supplier#000000057|bEWqUVRR f0mb2o18Y|17|27-681-514-6892|-831.07|detect according to the furiously br +58|Supplier#000000058|01dEADIZoCULZXg|16|26-659-969-5586|92.44|refully final foxes are. even, express courts according to the b +59|Supplier#000000059|N8lKbYjMnVlEHmTPRmBgtLiX8rrJx|17|27-249-395-9123|586.16|ffily along the even decoys. final instructions abov +60|Supplier#000000060|cb08ntDTARo47WmnBcYXu|8|18-550-360-2464|4515.80|thely express ideas use blithely +61|Supplier#000000061|Oz0M1qBR9I|8|18-396-489-9719|6096.58|s the slyly regular ideas shall +62|Supplier#000000062|bSmlFYUKBeRsqJxwC9 zS6xpFdEf5jNTb|19|29-603-653-2494|9202.57|ts. furiously ironic pinto beans are permanently after the bold ideas. regular, express f +63|Supplier#000000063|NlV0OQyIoPvPkw5AYuWGomX,hgqm1|5|15-781-401-3047|5742.03|ar deposits. blithely bold accounts against the slyly final pinto beans sleep about the exp +64|Supplier#000000064|w80JjnIP lGoLdUjRutbv81gGlqqpW4PQBeOtSYU|24|34-278-790-7004|1309.70|uickly regular requests use. carefully i +65|Supplier#000000065|BsAnHUmSFArppKrM|22|32-444-835-2434|-963.79|l ideas wake carefully around the regular packages. furiously ruthless pinto bea +66|Supplier#000000066|qYdruFJQJYYiKvnNVmYfCVydVB8bcW,AW,U6SOV3|23|33-300-836-9529|2455.98|ar requests. express orbits de +67|Supplier#000000067|7YrEKJncHFk5D W7ZaqfAXV|4|14-563-538-1657|3576.55|ray slyly final foxes. furio +68|Supplier#000000068|Ue6N50wH2CwE4PPgTGLmat,ibGYYlDoOb3xQwtgb|21|31-267-327-4328|5119.38|inal requests. ruthlessly ironic packages cajole +69|Supplier#000000069|T2Dl9,f97e333eRuMi2z |4|14-491-707-8310|8466.50|! carefully ironic instructions nag quickly pending requests. fluffily even deposits sleep a +70|Supplier#000000070|INWNH2w,OOWgNDq0BRCcBwOMQc6PdFDc4|6|16-821-608-1166|9508.37|ests sleep quickly express ideas. ironic ideas haggle about the final T +71|Supplier#000000071|YFo8an7P6wi Q|1|11-743-919-7272|8179.68| final accounts. bold, final escapades must have to cajole about the special platelets. fu +72|Supplier#000000072|mKpAJojtawk2alqV4 ZEbJ3PH3wfYqy AM8rGq1|18|28-113-898-6643|7014.50| theodolites sublate furiously about the regularly e +73|Supplier#000000073|HBZA1NHvrswQCxTTjg 5XrfSOGgMRKNCe2ovE|16|26-758-310-7496|3793.13|. never pending asymptotes a +74|Supplier#000000074|uM3yV5NOc6b5wNdpxF69CW 8QvDxqvKubRJtA|20|30-166-486-1559|4170.51|carefully along the quickly regular sentiments. ironic accounts sleep. regular deposits are blith +75|Supplier#000000075|7f3gN4rP1livII|18|28-716-704-8686|-224.84|eans. even, silent packages c +76|Supplier#000000076|JBhSBa3cLYvNgHUYtUHmtECCD|14|24-228-763-7840|2971.10|, even instructions. furiously unusual deposits wake slyly about the ev +77|Supplier#000000077|wVtcr0uH3CyrSiWMLsqnB09Syo,UuZxPMeBghlY|7|17-281-345-4863|4186.95|the slyly final asymptotes. blithely pending theodoli +78|Supplier#000000078|9y3OZ2CV hGrsrQxzB7V3zTtygHVHlG3SD6yrz|5|15-670-998-6860|1044.10|, regular packages wake quickly bold requests. carefully unusual requests about the unusual request +79|Supplier#000000079|p0u3tztSXUD2J8vFfLNFNKsrRRv7qyUtTBTA|14|24-402-227-9600|1191.94|nto beans integrate slyly across the fluffily pending multipliers. carefully ste +80|Supplier#000000080|cJ2MHSEJ13rIL2Wj3D5i6hRo30,ZiNUXhqn|21|31-646-289-1906|-40.45|ackages. blithely bold requests wake quickly. carefully regular foxes are slyly instructions. caref +81|Supplier#000000081|SLlacbhgpKmVa,gF3saYv12e0|12|22-535-310-6971|166.32|oost carefully quickly regular packages. carefully final excuses sleep blithely slyly pendi +82|Supplier#000000082|WyTKA7ZpF15t1aCNlT3|18|28-177-572-9691|-724.31|xpress multipliers wake furiously even foxes. furiously iro +83|Supplier#000000083|WRJUkzCn050seVz57oAfrbCuw|14|24-529-559-2461|1467.77|ly pending courts would cajole enticingly even deposits. slyly express +84|Supplier#000000084|DcYjWMiZGQqEKOJi4wAmIV08ikx|24|34-869-118-7803|4780.93|even depths. regular foxes use slyly. theod +85|Supplier#000000085|Ckls9RtlzKSF|7|17-167-806-8199|7174.74|egular packages. bold pinto beans wake fur +86|Supplier#000000086|J1fgg5QaqnN|19|29-903-665-7065|1883.37|cajole furiously special, final requests: furiously spec +87|Supplier#000000087|WCw7URDj8zoZ7tqC3cpm7|24|34-860-229-1674|4746.66|all are quickly after the ironic platelets. pending dolphins are. final the +88|Supplier#000000088|yOshY8wwzMgS|11|21-191-938-9469|3086.13|furiously special excuses aff +89|Supplier#000000089|fhtzZcSorhud1|9|19-259-876-1014|1638.02|en instructions across the slyly ironic requests engage +90|Supplier#000000090|bPE6Uhz1f2m3gwSGMrnRt,g,3gq37r5kxgphqss1|6|16-380-123-9217|6201.77|hely fluffily regular theodoli +91|Supplier#000000091|YV45D7TkfdQanOOZ7q9QxkyGUapU1oOWU6q3|3|13-604-986-9056|6255.87|nstructions use carefully according to the special packages: quickly silent th +92|Supplier#000000092|n48Wy4QI3lml8T217rk|2|12-701-432-8346|2470.84| even theodolites wake against the blithely fluffy packages +93|Supplier#000000093|wd1djjKXT,4zBm|16|26-528-528-1157|368.76|yly final accounts could are carefully. fluffily ironic instruct +94|Supplier#000000094|lK,pLPjAMVGJOXN80zPZuNQjpChliE|4|14-728-888-8882|2766.80|usly. furiously slow theodolites could haggle carefully fina +95|Supplier#000000095|p2 2hBfH5TD|19|29-142-539-1403|2588.83|sual instructions cajole slyly with the final ac +96|Supplier#000000096|Lbxp3WIipye o2wZme1i9iJx,xTt1Mp|12|22-888-654-7193|3437.24|efully unusual excuses wake fluffily regular theodo +97|Supplier#000000097|MrCQha2G6ndX1fp6CA|4|14-618-678-1789|6642.22|s, regular accounts. furiously bold ideas u +98|Supplier#000000098|ogHn8dpXB5Q|21|31-914-775-1978|5873.07|esias use slyly under the ironic foxes. re +99|Supplier#000000099|4SxkTHG28nZrtT0,MnVF9H|18|28-272-909-1617|3671.34|nic dependencies dazzle flu +100|Supplier#000000100|rIlN li8zvW22l2slbcx ECP4fL|21|31-351-324-5062|3191.70|es. regular instructions sleep carefully. slyly ironic packages across the foxes boost +101|Supplier#000000101|8KUTzVw32Pw3PD7 h,YJ0ysOoBtz9JfZI|11|21-970-795-5691|4901.77|ar foxes. carefully final ideas are. blithely regular deposits about the carefully regular package +102|Supplier#000000102|pDmsZ3V8W7NR1wW|8|18-884-693-5785|2980.07|ly even notornis nod furiously evenly regular platelets. thinly pending pat +103|Supplier#000000103|hBpQ4GYblzpHKTgATLPAS6ph3|2|12-442-523-5043|1050.66| accounts detect slyly bo +104|Supplier#000000104|Dcl4yGrzqv3OPeRO49bKh78XmQEDR7PBXIs0m|6|16-434-972-6922|1381.97|gular ideas. bravely bold deposits haggle through the carefully final deposits. slyly unusual idea +105|Supplier#000000105|cB YSy5Bla|4|14-951-800-2742|3754.75|sual requests haggle slyly. theodolites +106|Supplier#000000106|50EV3vyfAsWJAjTbT4qwU|21|31-810-990-4600|8091.65|eas affix carefully fluffily silent packages. regular deposits bo +107|Supplier#000000107|fqniA2vC1VZU5DZG2TBiN|16|26-958-723-2164|1378.93|thely special foxes nag carefully. requests cajole along the quickly ironic pinto b +108|Supplier#000000108|eL47lfhfMP7zRw|24|34-341-415-7878|7683.71|, regular packages! bold re +109|Supplier#000000109|4 63llZBLxtWRa A|21|31-405-311-8656|9202.82|al courts. unusual escapades cajol +110|Supplier#000000110|ehv9ObpyN0|15|25-824-874-9077|9804.10|eposits nag thinly furiously even accounts; permanent ideas nag fluf +111|Supplier#000000111|uv56H9j8cNa4qnflVSYbLNN|4|14-256-573-2660|6578.65|ing theodolites are about the slowly pending +112|Supplier#000000112|vdWe5lfgvisRCxdd85DTOZHqAzcuq7f7KKThA|12|22-617-876-1402|4332.95|es eat fluffily bold deposits. furiously unusual i +113|Supplier#000000113|5 YOpqbaHs7dR gG4EmXrI7XtA7DcnRMsWPU1z2D|11|21-211-117-1937|1882.05|blithely regular courts wake quickly even pl +114|Supplier#000000114|Uvz iykaBYOC|20|30-998-334-7841|4559.18|jole slyly blithely regular requests-- even requests haggle alongsid +115|Supplier#000000115|nJ 2t0f7Ve,wL1,6WzGBJLNBUCKlsV|23|33-597-248-1220|9192.10|es across the carefully express accounts boost caref +116|Supplier#000000116|gABGPfNYwB 9g1rMYWSAhpo 4|13|23-188-305-1829|5751.39|xcuses wake quickly above the regular packages; s +117|Supplier#000000117|ZnlLNC,8YN10T4mjI8eq5bJ|18|28-470-879-3141|4589.18|ymptotes. blithely regular theodolites are slyly according to the +118|Supplier#000000118|BYtvNtFpQAHHoBFWF|0|10-475-868-5521|7317.43|y ironic theodolites. furiously bold ideas use along t +119|Supplier#000000119|4CxBrM0o4yt6LYFxZIyZ89Xnf8LZNn6KcYc|18|28-558-264-1202|2060.13|ctions: quickly final courts wake quietly foxes. packages hag +120|Supplier#000000120|TNxoTw0SiMmQzGfZY9fTSkL2kmtPwvtR2L|7|17-645-761-5674|5575.40| beans cajole of the sly, dogged courts. +121|Supplier#000000121|CWGri,tKI 7gDcDsI|6|16-275-849-2485|5733.61|against the ironic, permanent pinto beans. doggedly pending deposits sleep agai +122|Supplier#000000122|2RUSHHspScCVTWC6z vw2XVR|16|26-432-258-4986|2732.95|ackages. carefully special accounts use slyly. slyly silent i +123|Supplier#000000123|IqRn20xsj5ibqAQjb6YNQf0xah|19|29-602-688-1506|5726.19|nts x-ray quickly according to t +124|Supplier#000000124|vmVadCZ xHPbQQA2fLxr68T1YhmjVSuRUJKCrcq6|8|18-313-889-3713|-941.38|ular excuses after the fluffily pending pinto +125|Supplier#000000125|XG eO4Xb4TSF7rj4R6WRQ1v2seTlyga3tvFZaC|2|12-419-430-3983|5157.25|ven accounts. fluffily ironic deposits are carefully. s +126|Supplier#000000126|CaO4YuZ oSkzemn|14|24-728-670-3468|6829.86|unts. carefully regular dolphins s +127|Supplier#000000127|VEqo3HZJ,0ggcaxvqZnW7Rq7l,cPqfKgX2bIRavM|1|11-265-565-1616|2502.95|yly above the fluffily ironic accounts. +128|Supplier#000000128|u,I0ayLPI2HKL|23|33-957-200-2556|1091.04|ng requests. slyly final ideas affix slyly even requests. fluffily regular theo +129|Supplier#000000129|9kWUk5K 7TAR40dW5nVeg i60Fy|15|25-314-164-7014|9001.17|even excuses wake even accounts. slyly bold excuses +130|Supplier#000000130|Rnt93MAs0EpPZjPYQIlGOWNUjk|23|33-322-101-6260|8708.17| blithely regular packages sublate. closely idle accounts are fluffily final, brav +131|Supplier#000000131|u3mTHMgBC0yJTLufr01TuHImgflQUXv|14|24-293-181-3975|1301.20|to the regular, pending instructions detect against the p +132|Supplier#000000132|sU92Jd3aQSbV|5|15-776-909-1326|-812.17|al, final accounts cajole requests; fluffily pending instruction +133|Supplier#000000133|QT,semYwdx|4|14-731-952-5158|9754.60|he quickly express instructions +134|Supplier#000000134|Nv7dxj4FGWrdcP56RmNci|6|16-184-952-7778|-329.16|c deposits haggle. dinos a +135|Supplier#000000135|F4Uy ZQNU6ESTmO3mrL,mI|7|17-290-812-8855|9767.99|courts wake slyly instructions. furiously silent requests cajol +136|Supplier#000000136|SyWVom9ZFrTA6BMAS|8|18-175-739-8397|4623.48|requests. boldly regular deposits are. packages are sometimes! c +137|Supplier#000000137|j81M1VQCvKcIVnpMnIUnBNVUOm0XYJuJY|18|28-108-440-4890|837.27|he blithely bold theodolites cajole blithely among the +138|Supplier#000000138|utbplAm g7RmxVfYoNdhcrQGWuzRqPe0qHSwbKw|19|29-533-434-6776|906.07|ickly unusual requests cajole. accounts above the furiously special excuses +139|Supplier#000000139| 2mQLQsVJ8WLBSnl0R bXrcyTgqXKrplgxb|22|32-788-265-2743|2217.93|arefully ironic ideas: slyly regular deposits about the furiously ironic requests +140|Supplier#000000140|mdfYYe8U sSb|16|26-379-377-5829|6727.48|sly final pinto beans affix furiously about the packages. even, bold accounts affix permanently fi +141|Supplier#000000141|5IN1dvjqFhyfKxoslkY3UL7CrNVPCZmq|10|20-557-547-7976|8842.14|quests detect blithely even ideas. unusual, regular accounts sleep blithely carefully regu +142|Supplier#000000142|HvfHnP57pz0w6l|16|26-302-532-7958|8991.41|dly ironic packages cajole amon +143|Supplier#000000143|a3v,6RZMN9p FzRTdV,fm7ehoVgEhifejGnrNY4H|12|22-916-300-5765|9658.99|s lose slyly about the blithely unusual asymptotes. blithely silent instructions cou +144|Supplier#000000144|f8tddEKps816HHqNwsKdn3|20|30-726-423-7363|9806.29| carefully even pinto beans n +145|Supplier#000000145|pSsVRBOlNKVuvXcjAEKxxy0hD8kA aZf|6|16-136-582-9756|-685.94|he carefully silent requests. quickly careful deposits are quickly about the bold, r +146|Supplier#000000146|rBDNgCr04x0sfdzD5,gFOutCiG2|22|32-792-619-3155|8271.39|s cajole quickly special requests. quickly enticing theodolites h +147|Supplier#000000147|oLdl SQpf,ZXebBw5F3g9|23|33-828-583-6731|8387.76|its. carefully pending packages after the ironically special frays wake above the special deposits. +148|Supplier#000000148|bkCBZzewuerw8xHv|7|17-648-666-9156|6089.75|ckly regular grouches. carefully ironic deposits cajole acc +149|Supplier#000000149|pVyWsjOidpHKp4NfKU4yLeym|6|16-660-553-2456|4518.31|ts detect along the foxes. final Tiresias are. idly pending deposits haggle; even, blithe pin +150|Supplier#000000150|kZajmmtJB4g,nNlaHxUvXLfZW0hVtnR35LKA|5|15-169-420-7828|4161.22|l instructions sleep quickly regular requests. final orbits use never furiously ironic reque +151|Supplier#000000151|2hd,3OAKPb39IY7 XuptY|22|32-960-568-5148|8561.72|hely final packages. ironic pinto beans haggle qu +152|Supplier#000000152|jTZy8PjLJqfLxgHm7,fDoJu7ZMs luO2YmN63|24|34-659-493-1274|3846.60|lyly even platelets cajole. fluffil +153|Supplier#000000153|qkCHAU1v9CtEBOGXhdFXJsx5L5gViVm5k,|9|19-346-843-5260|850.55|ress quickly. even accounts are around the carefully bold packages. slyly regular pa +154|Supplier#000000154|gB51OPlY yleFDn,pnDRbsDqy1gYM,SNRbo|13|23-471-808-2661|4155.67| special ideas haggle carefully ironic pack +155|Supplier#000000155|NFoZlgq90N33cC4HbLcfIGb1uqIZy85l42qa6|22|32-417-987-3690|3401.43|es! slyly ironic requests cajole above the daring account +156|Supplier#000000156|,KXbCcjqZNjmyHzeqaL4|5|15-106-692-4998|9780.74|sits cajole carefully instead of the final, ironic requests. furiously ironic deposits abo +157|Supplier#000000157|,mEGorBfVIm|3|13-776-259-5994|-963.19|ove the silent deposits. carefully pending packages cajole furiously final packa +158|Supplier#000000158| fkjbx7,DYi|7|17-873-902-6175|1596.44|cuses sleep after the pending, final +159|Supplier#000000159|xftQu5vkiD6BF|4|14-606-224-3002|326.36| blithely quickly ironic platel +160|Supplier#000000160|LG6VM3F8MhGnmoZUpyqHgsV0IP6gOagh|4|14-471-505-8811|5067.64| after the furiously express deposi +161|Supplier#000000161|fsteD4OulIaUNa IPXVesILV|0|10-604-123-7428|7810.78|doze among the slyly even platelets. packages believe blithely furiously final ac +162|Supplier#000000162|hf2fnryOkI9VjFN8R8i5rRWguXzdlMu3o|9|19-905-888-6020|-170.22|sits. even frets believe fluffily. fluffily regular accounts +163|Supplier#000000163|1MhydNirC ,cuLIZezbkUxJhAC53ii,B|12|22-980-516-1217|7999.27|es sleep about the fluffily express platelets. even multipliers must have to sublate. bli +164|Supplier#000000164|7H,0hAZkls5qVS 6sjbnVnQtpjMnGEv3gKXVS|2|12-414-446-6598|-264.20| the stealthy accounts. quickly stealthy warthogs detect. final deposits +165|Supplier#000000165|iPso5qCxSnxaNsRe9AU05Vl9hWm5oHIS|14|24-906-333-8640|1550.62|ions sleep silently. furiously unusual requests are slyly. express requests hind +166|Supplier#000000166|zCr2Z0hHyLjSz|13|23-117-751-3240|258.33|s. regular, unusual requests about the bold packages grow careful +167|Supplier#000000167|FEDldnEfBHVGOmKdFevemmG2|20|30-725-194-1727|5731.87|rding to the slyly bold deposits haggle furiously furiously regular accounts. blithely bold pac +168|Supplier#000000168|NNvNhn6dWzr80Igr|9|19-985-776-2090|6559.35|y final packages! express, ironic foxes snooze carefully above the furiously daring theodolites +169|Supplier#000000169|ycymrfB5JV1vU,swPXggAt|13|23-698-509-1073|-927.50|ss, even accounts. ironic packages sleep blithely after the slyly regular d +170|Supplier#000000170|RtsXQ,SunkA XHy9|23|33-803-340-5398|7392.78|ake carefully across the quickly +171|Supplier#000000171|eRpB8T GdtMBvJOo|10|20-229-200-1299|3549.54|es are. blithely final packages are unusual requests. fluffily expre +172|Supplier#000000172|NckigAXBRUXbJI|22|32-481-329-1585|2077.39|efully ironic packages x-ray thinly. slyly pending hockey players haggle slyly. sly +173|Supplier#000000173|OqQzF6rfxDvkjpMXVCwGfQzj4oTHBHyW5kC5Gjxd|12|22-640-545-4690|9583.11|ly regular escapades use among the express deposits. unusual, silent deposits wake. ins +174|Supplier#000000174|e1NMjwAq6RdyIKeA|22|32-840-184-9487|-561.50|s. blithely special dugouts integrate furiously. furiously bold accounts haggle th +175|Supplier#000000175|Lgv gYbBdu S9|12|22-392-226-3266|9845.98|leep. quickly blithe theodolites wake slyly. furiously pending ideas haggle after the slyly +176|Supplier#000000176|OLVnGuOx8m6NfApzODj4 JP01JJIm,qI53BChmgQ|10|20-970-245-2712|6387.89|s according to the carefully expr +177|Supplier#000000177|IUZ 7G x212nzZY5aQS|12|22-246-174-4465|-741.79|fully after the always ironic theodolites +178|Supplier#000000178|VJ9DInoVjbDg|16|26-471-122-2582|4693.27|hely final foxes instead of the express, expres +179|Supplier#000000179|d3le3XaTUC|19|29-560-587-5604|7727.83|kages solve carefully alongside of the furiously regular patterns. blithe +180|Supplier#000000180|JJzFp5wZcS0KpMLM95tYmq5Pv526UBfT8vrfwBk|7|17-600-237-1665|2753.77|ic deposits wake furiously even, express accounts. slyly express packages detect doggedly +181|Supplier#000000181|7g8adZQXXuHAYdoULLDVKYRtBhdddGqYj7pMzva|14|24-682-737-4806|3665.07|usual ideas. silent requests boost across the quickly regular instructi +182|Supplier#000000182|KuSXGdsAdYdkhzVLmgo4Xs|7|17-825-333-7344|7872.30|gular instructions. blithely regular sentiments around the slyly silent dependencies inte +183|Supplier#000000183|zAAIv68BEXvllrfgsW,i8e|0|10-842-403-7954|-192.51| slyly final dependencies alongside of the fluffily iro +184|Supplier#000000184|VTbbcJp9vdqn,tJA5pG5V,596mud6ZdspXgpUWX |1|11-802-685-1889|7448.53|special deposits cajole quickly even asymptotes. quickly ironic d +185|Supplier#000000185|F4C0AWRPk3|17|27-586-282-7422|5435.91| pinto beans. quickly express packages +186|Supplier#000000186|g huGEW5nrQ0Lmd6|1|11-398-253-5445|4397.48|g along the pending deposits. slyly final foxes sleep fluffily above th +187|Supplier#000000187|oMtyTl6hTyLQhiBwrUaa42zKOjfNobEq|18|28-127-320-9230|8517.04|riously along the carefully silent instructions. +188|Supplier#000000188|boP,dP6PjNCADoMv3FaXKRREikgs4J7cYng|20|30-573-811-4001|1020.57|ual requests cajole. final deposits +189|Supplier#000000189|SlPFDFJnn4gtrol|9|19-482-239-6669|1636.09|y regular courts. furiously express deposits haggle slyl +190|Supplier#000000190|qpXGL8oM1 wzQd|10|20-995-359-7606|6705.44|regular deposits haggle across the final, si +191|Supplier#000000191|X dZg6Dtv17X7|18|28-437-699-1621|1445.00|en packages haggle blithely regular requests. silently ironic packages n +192|Supplier#000000192|Tub1t4UlJwZ5U|15|25-585-189-5975|7031.84|ccounts use blithely. unusual, regular ideas use qu +193|Supplier#000000193|0HvoBt,qEF EaKzYNCl|5|15-872-804-8448|9095.64| packages. regular ideas sleep about the fluffily even deposits! special dolphins nag sly +194|Supplier#000000194|MDIkT8cHs7|9|19-741-822-3512|1487.08|nusual platelets cajole according to the +195|Supplier#000000195|xWy21YlUy3R6L01|2|12-395-261-9720|-767.31|e unusual foxes. express, final ideas sleep! carefully regular ideas around the quickly expres +196|Supplier#000000196|TQX4fMwB5tXoz4Fi4CEhALhi6|18|28-430-406-1127|4710.62|ke fluffily regular requests. furiously final +197|Supplier#000000197|YC2Acon6kjY3zj3Fbxs2k4Vdf7X0cd2F|3|13-999-250-8664|2398.30|ithely final ideas within the furiously ironic requests cajole +198|Supplier#000000198|ncWe9nTBqJETno|6|16-355-298-7120|2187.91|ts are blithely stealthily unusual asymptotes: blithely final excuses wake. ca +199|Supplier#000000199|k,8F8FGDuN 3udblO|22|32-268-147-8879|8151.22|requests. slyly express foxes across the blithe +200|Supplier#000000200|MNqafnV52UKvwuk3jFCn,AJkL|11|21-962-509-4762|1589.13| beans x-ray enticingly express accounts. blithely final deposits run; regular packages are +201|Supplier#000000201|e3lZO QY9QpCVdc0HXrqXB5uxXnOi r|18|28-782-585-7326|9537.73|kly above the special ideas. even requests nag carefully. quickly pending t +202|Supplier#000000202|NALZjSfea6SY zB1,I09OJYGrA8bwR4pU|23|33-549-918-5721|6739.52|courts cajole bold, special accounts. bold packages haggle re +203|Supplier#000000203|wvdhblw9JkIe52z0gnGSDrDBsMsI3Aidqk|1|11-257-649-3327|2150.78|ar warhorses detect. carefully final requests since the unusual, ironic deposits b +204|Supplier#000000204| 7bts1RIiMsy35F6V7 lC|15|25-718-760-9193|172.87|cording to the furiously even pinto bean +205|Supplier#000000205|rF uV8d0JNEk|3|13-272-651-7242|-670.30| beans cajole regular, pending packages +206|Supplier#000000206|hva5xXEn5j7H27CdKcjFqi,QnunUZyt8,a|19|29-156-330-8311|7136.21|quickly pending packages. regular, quiet packag +207|Supplier#000000207|0QmBvfdQPh7Xy09txlnJcv|2|12-245-833-1389|3285.77|xes. pending, regular deposits x-ray against the unusual deposits. final, bold platel +208|Supplier#000000208|kr uyD ,K95lEvq77tuHVjOJM57|4|14-932-450-9228|1938.69| instructions boost blithely along the +209|Supplier#000000209|fpTboatC6ogrozMPApz2DXmlukC9YVzCLCgQOtgU|18|28-134-789-6780|-395.27|ly ironic ideas sleep carefully even courts. slyly speci +210|Supplier#000000210|eC5 e7DXYBWi8XlnFtBxF,tSWPyQAzqb8gAZ|2|12-385-448-5157|9657.88|ccounts haggle after the carefully pending acc +211|Supplier#000000211|acmexYmhAZhFyM|2|12-150-553-5979|2080.07|quests sleep final pinto beans. blithely bold theodoli +212|Supplier#000000212|ZutN4kNIsv7sPWIV9,7|7|17-617-724-5874|-335.47|ular requests cajole furiously against the spe +213|Supplier#000000213|1s7 4odatD2BWz1QjXR2 2SnFhc,Rvr2Icxh1m7f|18|28-317-938-6979|2616.54|, regular packages. request +214|Supplier#000000214|B3uLKyb, xkfHbTSUBe6HwwaBPdCvhiOqO4y|14|24-114-624-8961|7089.25|omise blithely regular packages +215|Supplier#000000215|YmZQvVCVanip2E|12|22-333-479-3656|6125.89|fully upon the slyly bold excuses. blithely regular deposits promise across the slyl +216|Supplier#000000216|K83M7iWDJx N Y|14|24-182-902-2539|6902.54|luffily final theodolites haggle slyly pending platelets. speci +217|Supplier#000000217|UVrZj7M2mMd7JLjbc tvFmQad14d1oid|15|25-113-702-9259|3084.60|arefully final accounts. slyly even ideas haggle along +218|Supplier#000000218|c7CBVglgEM0XU,8bOU76GjEr5L5EXu9Uxa7U|10|20-180-767-8426|8843.88| fluffily. furiously regular instructions sleep slyly furiously regular packa +219|Supplier#000000219|f0siVrn1T,dOIJgYU|9|19-708-346-1944|5222.69|odolites use carefully about the reg +220|Supplier#000000220|uvWVvuY3tHcE2W34jcO538wy6|19|29-197-645-8102|6746.19|. furiously regular foxes solve blithely. ironic requests mold carefully. blithely unu +221|Supplier#000000221|aU oCBZs0CUUTU|11|21-402-925-9045|4283.34|onic dolphins nag furiously across the silent deposits. carefully even ideas snoo +222|Supplier#000000222|2JQCRHT8coRlrMria2|15|25-899-779-7536|4173.23|ctions x-ray against the s +223|Supplier#000000223|MCS3 zWF3Py8UZK PHdI6LsQD98phHJ7|2|12-790-796-4808|1518.42|y fluffy packages solve amon +224|Supplier#000000224|iD7eF,uwQxxPCAFTmdXYV7N|5|15-446-447-2944|9036.79|atelets. regular, ironic gifts eat furiously across the permanently silent instructions. reg +225|Supplier#000000225|6Ez0sxpUfmtjqFDO|9|19-787-123-9863|2461.11|d packages. unusual requests after the furiously bold packages wa +226|Supplier#000000226|83qOdU2EYRdPQAQhEtn GRZEd|3|13-768-844-6969|1906.46| deposits run fluffily: excuses breach closely against the slyly regular dolp +227|Supplier#000000227|Qo959Dll Bd7xvfq3ELtCq|4|14-215-994-7949|7896.01|ng accounts solve furiously at the furiously express packages. carefully bold packages sl +228|Supplier#000000228|pyTY uocaSasIUlrHUbBwM,r,|14|24-920-216-6514|2291.35|s above the final deposits detect along the furiously idle packages. b +229|Supplier#000000229|ycjgLrk,w8DcakfwTS1SO5kVch|14|24-392-655-8913|8751.47|ly according to the carefully regular +230|Supplier#000000230|TgT146Clu9ODbYYBx4Wd8oe|1|11-819-222-2128|2975.98| regular dependencies. packages after the accounts are blithely blithely bold packages. furiously +231|Supplier#000000231|uZfFnyAs9oFJ0No97rtQ OIV1AOYi|5|15-551-432-9958|9287.33|mptotes sleep above the regular dep +232|Supplier#000000232|90YJjotHlfwyieaTfuBJ8kohU5Oc83bESout,p|7|17-478-427-3811|300.80| asymptotes lose slyly evenly ironic asymptotes-- blithely bol +233|Supplier#000000233|Pu9mqssUjJNoqiGG4vfLTn3ENJnNPVrBNnXJM5Eb|6|16-283-737-6972|4544.18|kly pending platelets sleep blithely along the ironic, +234|Supplier#000000234|iMrk7HUD87at3IIh4rBi|24|34-187-193-2209|9957.00|nag furiously pending dependencies. unusual deposits integrate fur +235|Supplier#000000235|W89jjgy458|8|18-835-352-6531|2424.93|ackages run blithely above the fluffily even dolphins. dep +236|Supplier#000000236|dZExtd1dlMyrPdSqDC3|15|25-250-525-2436|9844.00|lar platelets. blithely ironic packages cajole blithely special ins +237|Supplier#000000237|NzEXFiPN5tnrZzs1E,uGeoEqolOlDYE7oQHnQWg|23|33-976-749-2413|6170.98|regular ideas. carefully express ins +238|Supplier#000000238|xjSZNq AIqmrV UfxyGcS04RYOzW|8|18-950-354-3488|5763.17|s. carefully final courts impress furiously among the slyly regular deposits. ideas thrash furi +239|Supplier#000000239|XO101kgHrJagK2FL1U6QCaTE ncCsMbeuTgK6o8|22|32-396-654-6826|4672.25|arls wake furiously deposits. even, regular depen +240|Supplier#000000240|yMzL86zw28z6sMa|10|20-843-630-4161|6537.07|sly. final, regular pinto beans unwind slyl +241|Supplier#000000241|K3sXvTEnHT9yQSbzZmbPNY0,iPQsmySI|8|18-213-514-9357|9594.49|arefully final foxes. regular, pending requests haggle busily special asymptote +242|Supplier#000000242|cpZMlI77TRq|11|21-489-286-5908|3736.64|nic accounts sleep furiously according to the quickly pending requests; slyly bold deposits haggle. +243|Supplier#000000243|8aQ3HGeOXxgYeMAXZQe B5y2RKEF5jdmN3Qb|6|16-554-376-5494|747.88|kly silent requests among the blithely regular foxes use fu +244|Supplier#000000244| c6fBN9a 6EOcB1ZjbImMBAQMwI BKScDNVRP8|1|11-556-986-9638|5489.08|d blithely. pinto beans boost quickly. blithely bold accounts affix. +245|Supplier#000000245|8qUceq1TSsNaTol3Ul6TDNSu9yRddanHEL|8|18-739-793-2096|6943.28|ual deposits x-ray slyly. carefully regular epitaphs about the +246|Supplier#000000246|BatWQwH8DgkBs|4|14-278-988-3903|5740.87|ealms are. even theodolites use regular, unusual ideas. ironic, final ideas sublate +247|Supplier#000000247|0bkES oiL2joJGmxdGwPfVCOL,pIQ4JNZBPnOR|23|33-695-935-2388|3758.64|final requests. final accounts affix. express accounts about the furio +248|Supplier#000000248|vDPBiu4L7hPZxwaEoNW u,zHgXVHvBXFBdfuek|6|16-646-663-7202|7487.64|ss packages are idly about +249|Supplier#000000249|ktpns6Bvu4fP8Wzzlc8|10|20-241-221-7700|2800.60| regular excuses about the blithely pen +250|Supplier#000000250|JkzOvHRi1rEdkZ|9|19-347-403-1571|9681.99| packages cajole blithely pending theodolites. ironic, silent requests +251|Supplier#000000251|Uqi3s, iqzLxI4duoRfgkciiN4XuCvITGIUf|21|31-869-288-1674|283.61|eep blithely even, ironic requests. carefully pending courts above th +252|Supplier#000000252|xcaKgadrug|11|21-860-636-2585|1523.14|tain slyly fluffily bold ideas. furiously ironic ideas nag furiously slyly even requests. +253|Supplier#000000253|DbryhLi6gCv8A P9FkjNp56mLP4KnV9Do|21|31-811-659-6792|352.61|ng courts wake quickly against the slyly careful packages. even ideas nag caref +254|Supplier#000000254|c6h4mizJAVT0Oz|7|17-100-212-8737|6230.48|nos. bold ideas wake carefully among the furiously +255|Supplier#000000255|qx16XyCEUh9OawVeQWOlGlhAU32iHFPNkO|18|28-629-327-4139|4663.08|s boost. ironic pinto beans along the slyly unusual foxes haggle regular, final asymptotes. reque +256|Supplier#000000256|ma15idU1PzO7itP67W1Rd|11|21-370-961-2170|6469.78|sly pending deposits haggle +257|Supplier#000000257|BjFRji2XvSyOVe MHMP9r5vC2eP4kfF GXwBe |16|26-806-563-6761|630.74|odolites use slyly finally silent requests. package +258|Supplier#000000258|z8ImnYbuBbohh1 WT|7|17-820-568-1141|5736.09|press packages. final dolphins sleep sly +259|Supplier#000000259|2zzYBzG12K|10|20-901-530-6532|439.97|ts wake slyly along the express dep +260|Supplier#000000260|TQGxRpJe08nPRqPYDIMTnst87mC0HZJ,rlnCQTF|23|33-226-804-7400|597.64|silent, stealthy instructions. furiously final tithes hinder regular requests. expres +261|Supplier#000000261|vUT2UDI,GAqIA|0|10-547-567-3297|-466.40|kages. furiously express requests are. carefully silent deposits at +262|Supplier#000000262| 3kCm2eN3Jra2UzvWWBm,P04b|20|30-952-865-8647|2138.97| ironic escapades. furiously even ideas affix blithely. silent accounts thrash beneath the +263|Supplier#000000263|7Vdou,WjHE|14|24-203-272-3139|-316.81|s quickly regular foxes. stealthily ironic p +264|Supplier#000000264|Oeq2ei9wRqt6yOuAAb0KoMRyoH4v|19|29-870-178-3535|8327.34|e busily ironic theodolites. quick deposits after the unusual dependencies print sly +265|Supplier#000000265|eHF4Edu,B8,NgBSSEV4xNC37i1q08WCNKyOe6jP|19|29-734-865-6334|2638.54|le evenly besides the fluffily fina +266|Supplier#000000266|LGWx4Xcq0GwQVwTR|23|33-256-678-2321|2874.22|y express foxes. special, pending deposits are slyly-- packages detect blithely ironic se +267|Supplier#000000267|,E9NoXeK5qOwVRoutS,X8Gr|10|20-501-962-2896|4068.14|riously close asymptotes are. carefully bold p +268|Supplier#000000268|ApLM6aebtP79LIp|23|33-863-692-9039|6261.99|nic frays use furiously among the final, ironic the +269|Supplier#000000269|LxOgEClzbXDEYHYG2ZMFoWHrD,C|2|12-988-623-6829|6331.84|lar foxes wake quickly about the carefully ironic asymptotes. final, regular do +270|Supplier#000000270|PM P65mhBoeFWkFMi9,|23|33-682-295-4727|3339.18|ss slyly after the fluffily regular packages-- quickly express pinto beans nag blithely +271|Supplier#000000271|U0BSsnILvbk7mL1cim,ZX70QIiTz|15|25-270-292-6296|8576.95|its nag above the silently final escapades. final, even inst +272|Supplier#000000272|ywrDqLLTfKUF93|7|17-209-164-6836|6858.73|of the furiously final accounts. bold dependencies after the fluffily ironic asymptotes hag +273|Supplier#000000273|O0TyoQXlzJx|15|25-247-243-3871|3708.18| pending ideas. carefully silen +274|Supplier#000000274|usxbl9KSW41DTE6FAglxHU|21|31-571-345-4549|6296.15|ecial courts. express asymptotes must have to sleep theodo +275|Supplier#000000275|Mh9eZVjmBPZc5I2KHcMcfZOYbpFqrlVOLR|21|31-446-410-5215|8477.48|packages. ironic packages are. pending deposits are according to th +276|Supplier#000000276|KdVDs6EGfWVsPdjuCh9iep|6|16-752-344-8255|7144.78|cial, ironic theodolites against the decoys cajole slyly ironic foxes. carefull +277|Supplier#000000277|REebuerbQmMxlbCXnl2ihK,VyItkTNxU36 c|12|22-758-939-2357|4300.15|final deposits. unusual pinto beans after the even accounts affix idle, final +278|Supplier#000000278|gBQmkVmclUGbjwHVtrdmCk9Dwqd2Dez1|9|19-563-887-6379|665.89|deposits against the final foxes use carefully express ins +279|Supplier#000000279|aVGVO0XNwTEkFwH0OhaQMJC7un0EizPpq|13|23-617-962-7353|2613.77|accounts. quickly special packages nag at the unusual requests-- special d +280|Supplier#000000280|MZAJPsr3TS62ocxtRc|11|21-536-349-7369|4540.53|nticing platelets. ironic theodolites about the regularly final accounts sleep accoun +281|Supplier#000000281|A2sesSQAAj6wvPPKL X4caRp,O|0|10-553-675-3578|3717.19|ooze fluffily express, pending pinto beans. regular instructions haggle ironic +282|Supplier#000000282|Gh,k4vQQPzOyIA9ac9re5IjaV5LyXDtZX9O1kNG|8|18-420-459-8366|3751.04|into beans. carefully special excuses cajole furiously. regular d +283|Supplier#000000283|MWLpGjjs1WoofKSoN7Lm0DXcSY5H4E9CeneF67ZQ|17|27-409-203-4267|785.26|ess instructions. slyly unusual deposits according to the accounts run past the slowly even package +284|Supplier#000000284|7NF0OkJazPIJ7l,LBSw3abv|15|25-955-684-2997|6866.81|quests nag carefully according to the furi +285|Supplier#000000285|Br7e1nnt1yxrw6ImgpJ7YdhFDjuBf|3|13-907-873-9658|7487.27|hely? slyly bold patterns doze carefully according to the fluffily even packages. bol +286|Supplier#000000286|o80iAPvmwqM3WOA93pqBHT4Dsgy1rwG|10|20-459-893-8984|7517.31|iously regular pinto beans sleep carefully slyly even accounts. packages cajol +287|Supplier#000000287|7a9SP7qW5Yku5PvSg|3|13-484-626-4797|6541.85|nic epitaphs are slyly above the foxes. ideas after the quickly bold pin +288|Supplier#000000288|8fUJhFrKTMmi5L|10|20-850-734-7789|1884.76|ual deposits wake furiously i +289|Supplier#000000289|6Tua0IHqN0sod1Tpdax5hD0|16|26-396-901-4544|6144.47|equests can wake: furiously final accounts lose regular, final requests. special somas affix. fi +290|Supplier#000000290|6Bk06GVtwZaKqg01|6|16-675-286-5102|167.56| the theodolites. ironic, ironic deposits above +291|Supplier#000000291|0qDDQst1b1bznHQh5jsmOq8nxf8Pz1Kn|0|10-404-519-2270|9132.12|wake silent, pending accounts. blithely final as +292|Supplier#000000292|POEdp8d ug5bKQa,w4SAMaM2xna1ZtVk4z9loa|21|31-933-112-8506|9598.62|ular excuses. furiously even requests sleep carefully around the fur +293|Supplier#000000293|H2JnUWv1X3s0yI7i2tY5Vd0kd4f0|9|19-143-962-9484|7114.81|t the instructions. daringly bol +294|Supplier#000000294|20vnacv,dtZ0mr5kukNf|18|28-299-788-1836|6700.75|en accounts. silent, regular instructio +295|Supplier#000000295|gpm7fahY9j6YyTr Dozul|23|33-998-989-3147|-435.02|en requests according to the +296|Supplier#000000296|g,WJbekrbjAcpNtn2QRsWtYx2RNVk 9aY|14|24-250-680-5383|1549.59|through the blithely regular depo +297|Supplier#000000297|gfVOI9aT2roNGEgc|1|11-562-493-7660|4954.57|al, express epitaphs? furiously ironic ideas haggle regular, ironic instructions. carefully special +298|Supplier#000000298|oIB13yXjsqGSW|5|15-790-635-6692|-530.05|egularly unusual accounts +299|Supplier#000000299|kvWv3MYn,Q2SqJlckBfhpWYmnSeRwg6|10|20-180-187-8847|-561.38|lar asymptotes integrate darin +300|Supplier#000000300|YU QZvXHJC7,ZspUPGwaIOa|2|12-468-732-4623|811.42|furiously even theodolites haggle along the final, ironic foxes. bold deposits are. +301|Supplier#000000301|YPFTsQOPRAGIlBw|4|14-434-699-9741|6472.62|express foxes sleep carefully even packages. carefully special ideas cajole slyly. carefully r +302|Supplier#000000302|ow8Io1JHkPnIAGCQYCWC|18|28-734-845-8630|4422.77|tructions after the foxes cajole regularly ironic tithes. ruthless forges across the slyly express +303|Supplier#000000303|MCFk0WJH4O9Fj,m3as3bdIgnP4pe 8qPj,wfo|8|18-932-912-3102|4500.90|ously carefully final foxes. fluffily silent requests across the fi +304|Supplier#000000304|b4rSMq4y hBDMJgcNp|11|21-261-644-8980|8564.16|endencies across the bold deposits nag +305|Supplier#000000305|pKYTaixBtQ3AGJLwndRNxUlLUkXN667JT|17|27-607-328-4914|974.24|uriously across the requests; ironic requests serve bl +306|Supplier#000000306|T5EUviO4mqrGO6ruLcIoo29M5S|16|26-954-209-5690|3979.54| wake fluffily. furiously final +307|Supplier#000000307|3wL9YHFIvddxzh3mwy6SSrpfmzKvwAGmXK|14|24-499-938-5607|2168.65|s above the unusual theodolites was quickly quickly perma +308|Supplier#000000308|mVY7rtoxj9uSqzAJIp TOWPsv080hbPbOStGZx|8|18-360-691-8400|3513.89|tructions hang carefully according to the furiously close requests. fur +309|Supplier#000000309|gT84r,AFSrZQpiSCnE02B3QK|2|12-950-744-5100|7875.48|riously final deposits boost blithely about the even foxes +310|Supplier#000000310|I5Mw,rGgWQOFVotMHUmVjH|0|10-119-372-1062|9312.63|ccording to the carefully express dolphins! furiously pending dependencies integrate s +311|Supplier#000000311|yjGDnCKi4Wmtim H3n9p|22|32-445-679-8585|7431.00|uriously final requests integrate. sheaves against the furiously final accounts are evenly abo +312|Supplier#000000312|8XYqBq S,OWbSp9Y2qGBWEV4hH l7ywxk|13|23-829-479-5202|7844.41| furiously requests. always bold accounts solve +313|Supplier#000000313|9xrpKrwr9,Jgvm5q rGkZePkpsH5xEXZnuLJug|9|19-648-945-5128|4114.68| beans. special deposits use carefully after the blithely even +314|Supplier#000000314|CW6uXfPdJ6lmcJ|22|32-389-335-6770|7456.49|s dazzle regular, final dolphins. furiously unusu +315|Supplier#000000315|HRLhxvqBP,f,NjeUiT|2|12-574-691-2832|7315.00|eas. blithely pending packages cajole blithely ironic packa +316|Supplier#000000316|uXJ13cI7fXByGLBoQ8VU9AT|0|10-382-551-5105|5189.82|ding to the slyly unusual frets. accounts use carefully slyly silent theodolites. slyly ironic depen +317|Supplier#000000317|EwuMPFkb3IrSqitX8ddgxy QWhXxeM4RoOu2d|17|27-131-276-7910|4277.34| packages according to the deposits sleep carefully regular hockey players. quietly bold +318|Supplier#000000318|Cm5fnQ4M6VeJF17mBbV6iB0XoQL31STrb3Su|24|34-466-917-6708|2268.02|ly express accounts cajole blithely brave instructions. furiously even +319|Supplier#000000319|tcES8Ay3zcHQER9K6gAKFWlDvcg nrbPl|18|28-288-466-7847|1578.18|ts are furiously even, pending pinto beans. fluffily idle courts cajole bl +320|Supplier#000000320|v2FlHgKKiGiDwR7uoJNWF|21|31-984-744-5308|1485.45|ns nag carefully carefully pending platelets. pending deposits dazzle. requests above the i +321|Supplier#000000321|pLngFl5yeMcHyov|19|29-573-279-1406|4941.88|y final requests impress s +322|Supplier#000000322|lB2qcFCrwazl7Qa|6|16-803-605-4129|6102.62| to wake. slyly even ideas breach furiously. ironic foxes haggle carefully. ironic asy +323|Supplier#000000323|0LEOmcTTomY1F0y|22|32-563-275-6438|704.83|accounts. unusual requests haggle slyly special packages. always silent instructions e +324|Supplier#000000324|QDsgOSozg jniYR2HzxofLZyk0qGdJe|18|28-637-452-5085|8042.43|ithely slyly special waters. +325|Supplier#000000325|bQgx8ABSanNFNfCHY,2 uPvGfafaMC5|8|18-671-443-5744|-786.95|unwind carefully among the ironic, final requests! quietly unusual foxes hagg +326|Supplier#000000326|9kFiCwhcBldg4xwm|7|17-390-604-7483|4680.75|quests could use furiously across the ironic, even f +327|Supplier#000000327|MoC7Jc7oThpZ34HmJPKuUbOZwOyPOb1ksGlvT8o|0|10-519-344-7532|6408.52|final accounts poach quickly slyly regular requests-- furiously careful requests cajole car +328|Supplier#000000328|SMm24d WG62|7|17-231-513-5721|5069.27|he unusual ideas. slyly final packages a +329|Supplier#000000329|zPg8 aqmUQ4wHGC 8nO39C50AOMB1VxTsJWmpYyz|17|27-571-511-5321|2166.85|endencies. boldly silent pinto beans cajole. carefully unusua +330|Supplier#000000330|MUxmICc8xS41A|22|32-845-516-3236|6199.85|ix bold requests! final deposits against the ironic ideas boost across the bl +331|Supplier#000000331|VkdMTxXHy22069CWmK658|22|32-337-220-5366|6929.91|special theodolites use furious +332|Supplier#000000332|OpvOrxiHWJ6QM|9|19-777-809-6033|1106.07|ve the furiously pending warthogs. slyly special ideas haggle carefully. express +333|Supplier#000000333|MaVf XgwPdkiX4nfJGOis8Uu2zKiIZH|22|32-508-202-6136|8702.02|oss the deposits cajole carefully even pinto beans. regular foxes detect alo +334|Supplier#000000334|NHMGXoP 8cWsNXvV46AkZZJuptUm4mFo8|13|23-767-548-6051|7848.40|efully regular requests: final requests solve quickly. pending deposits across the blithely express +335|Supplier#000000335|JSwzRFY7dDNKfBe8ebMtm|16|26-741-643-2945|5119.09|ong the regular ideas haggle along the close ideas. furiously ironic ideas alongside of the fluff +336|Supplier#000000336|orYe2VXtABdK sUvMCOZ9ZMhBJTPp7W3pffWmjZi|1|11-866-373-2323|3603.62|refully even packages above the unusual accounts detect +337|Supplier#000000337|IRrbCdIS,GB4YYhr|12|22-951-643-8793|9029.85|en theodolites-- special, final deposits should have to boost ca +338|Supplier#000000338|2b6Gj,rSxqeIiAOMquj6c03p GmAzIog BrF05|16|26-565-914-7207|6835.16|fully silent requests cajole idly. even dugouts wake f +339|Supplier#000000339| ESOHA53rEW5G7Z75w5hJ|5|15-967-506-6094|3589.64|ts snooze carefully express accounts. foxes nag carefully +340|Supplier#000000340|Pk5F9dPqsa3k16I3UR282gY|22|32-849-350-3343|5001.23|along the packages. blithely final foxes cajole. unusua +341|Supplier#000000341|sdb9yPRPun Z awDuDPUId2NH0Yrz7dnJ1GBDc|14|24-320-626-2836|2755.92| express deposits against the dependencies use blithel +342|Supplier#000000342|YgcA0MYOSB1ou|2|12-829-736-2942|6791.04|s wake above the quickly pending attainments. furiously special re +343|Supplier#000000343|LTRj tcLNq34je60R7LkZtNrEwmry00DIXguSxMS|4|14-617-526-7362|-905.27|ckages sleep among the slyly express excuses. special, regular pinto beans are carefully: express d +344|Supplier#000000344|F mMVT6PuRj5S|11|21-808-924-2361|7082.37|inal courts nod fluffily for the care +345|Supplier#000000345|ZYuibETx2zArwg|18|28-503-710-4886|351.98|lar dolphins. carefully unusual packages according to the furio +346|Supplier#000000346|9vl7c3azrqt9wITrcglQhIGfwea|8|18-148-870-6674|6710.10|ecial accounts. quickly pending packages print. slyly bold pinto beans detect slyly unus +347|Supplier#000000347|zg0m5HrQtl D|8|18-932-818-1269|2674.43|special escapades promise pending, regular deposits. blithel +348|Supplier#000000348|ZNEHF5c7kP5tPGdQ ZrJZNRdQnu0M9LVyO urMm|8|18-338-824-3860|1172.37|eas. frays nag furiously final accounts. fluffily unusual theodolites use furiously above the slyly +349|Supplier#000000349|21Sp51XIZ9vTChQBWv0CA1o1P,26clhjR|13|23-532-708-7267|1033.10|lithe packages. carefully final accounts on the carefully final accounts sleep slyly +350|Supplier#000000350|KIFxV73eovmwhh|7|17-113-181-4017|3294.68|e slyly special foxes. furiously unusual deposits detect carefully carefully ruthless foxes. quick +351|Supplier#000000351|ZLWTvVCSmwsKfElT7K 2O1Ui|12|22-508-407-2628|8684.60|ithely ironic theodolites play. decoys sleep slyly against the deposits. s +352|Supplier#000000352|LsVcltEi9NYu10ByH 5grND|16|26-911-452-7918|1189.55|ickly. platelets sleep slyly blithely slow escapades. special requests boost furiously. slyly enti +353|Supplier#000000353|Bo,HYtujUMsMvE,|15|25-153-823-7261|3646.16|ular packages. deposits nag slyly abo +354|Supplier#000000354|w8fOo5W,aS|3|13-796-527-4255|8965.72|blithely regular accounts around the special foxes kindle blithely across the even dependencies? +355|Supplier#000000355|DuCQn,7qi1KL a99mTWSY4Z9eC53dslWPABGj7|16|26-389-592-6792|6929.22|ackages cajole according to the slyly ironic theo +356|Supplier#000000356|Lefi6RDDtvaVXqvhlbMuUrVm45oJbtkZM,Mup|11|21-198-523-7929|397.74|carefully blithely ironic excuses. enticingly blithe packages along the attainments haggle carefu +357|Supplier#000000357|Vf7Hi5DuzZ6RJ,mfaXBVNqx0|20|30-147-268-1519|5724.04|e slyly among the furious +358|Supplier#000000358|V3yxhHhHSXqOoc5UPv5TwkVDGKQsG|3|13-831-247-2584|6974.74|ans. ironicCustomer requests cajole carefullyComplaintsy regular reque +359|Supplier#000000359|J5HqPZnfLcFMtlgwCnZPUI|24|34-121-923-9858|6476.58|ons. furiously unusual accounts above the blithe +360|Supplier#000000360|3avxIDL4YPrZVHie4rOiPrK8Z IJwEPqZaioHK|5|15-671-472-7761|4956.01|uickly regular asymptotes. packages ar +361|Supplier#000000361|f8IUYRmdVXhQC9qJQjWknCXmzhe38vCbk6|3|13-192-383-9438|1678.56|deposits. carefully final deposits cajole carefully after the furiously regular ideas. +362|Supplier#000000362|XdtN0U5Qm2Z|23|33-445-749-9918|5571.81|e furiously. slowly regular accounts sleep furiously. carefully bo +363|Supplier#000000363|sYpqZxYin8GKkPtNWKOnJMTLm9f5e0lZ61N8wp|1|11-220-343-2951|505.69|express requests cajole furiously blithely final deposits. quickly special foxes breach +364|Supplier#000000364|OhfGUPn8U9oBx5|9|19-653-706-8164|5105.84|regular dolphins promise after the special deposits. blithely final pinto be +365|Supplier#000000365|SZaykm40Np0vOKp|23|33-253-791-9564|901.98|s. deposits use slyly except the slyly final instr +366|Supplier#000000366|AtIdvjsMt9peVyEbpoDerNTteRF|12|22-648-291-8851|-535.40|ts. slyly special asymptotes c +367|Supplier#000000367|E Sv9brQVf43Mzz|22|32-458-198-9557|8488.53|ages. carefully final excuses nag finally. carefully ironic deposits abov +368|Supplier#000000368|3o5w6T5HzjFmSf1|0|10-694-873-8364|5783.96| nag fluffily alongside of the silent depo +369|Supplier#000000369|XKLa3tQT7,TgtuLi2Vme8vGyx|7|17-381-930-4614|2094.34|cording to the special, regular pinto +370|Supplier#000000370|yyNSJAG9UXcWit4SeMkEIrNcdVq5|0|10-602-768-3758|8515.99|ound the unusual foxes sleep finally within the furiously unusual requests. sl +371|Supplier#000000371|7kc0KqnPxrJuGZdrrec7Cn,wrCPdxPemNPZQ|19|29-501-449-3837|5358.50| among the ironic accounts-- regular accounts nod slyly +372|Supplier#000000372|Bdhu5NV4VfPYBxsCmK,YnkoHIaW|5|15-246-325-3001|1311.15|ltipliers. blithely regular deposits was above the furiously even accounts. q +373|Supplier#000000373|oQAQ3UNvyJW|16|26-656-301-9303|1461.85| asymptotes wake quickly around the slyly regular dependencies. regular attainments haggle along th +374|Supplier#000000374|svrrNWiqg1f3tEXZdVbFK CAtLDsW1CidtyS|2|12-699-158-6062|4263.58|ithely. ironic pinto beans use furiously abou +375|Supplier#000000375|3CIBgjwAjB A1uxkiJNjc 7pI9AKhvnr1BHV9|11|21-250-668-2735|1962.02|ully regular pinto beans acros +376|Supplier#000000376|L8OWL3jXMCR3Gh|16|26-752-731-5943|6579.41|usual dependencies haggle above the carefully regular platelets. never regular foxes detec +377|Supplier#000000377|L4SF6EzZ xhyZCQ59onlADR4|16|26-634-598-9185|6113.96|ly express accounts wake enticingly special, express frays. furiously +378|Supplier#000000378|FfbhyCxWvcPrO8ltp9|3|13-930-567-5190|4429.27| among the furiously pending excuses. fluffily express deposits except the slyly final packages +379|Supplier#000000379|jyGWzIJTAdI0Iko2o|20|30-202-917-6929|3698.31|sleep? express packages are quietly around the slyly even ideas. express accoun +380|Supplier#000000380|LiXmikqsO6R40FKovSUZpl|20|30-245-487-4913|5421.70|re. grouches against the blithely regular asymptotes sleep slyly daringly p +381|Supplier#000000381|NfyIKLJrXusWgmgkkCS6Gn3RRra|6|16-117-297-1825|7476.55| packages haggle blithely express tithes. blithely final deposits wake bli +382|Supplier#000000382|wNasxwKglHa|15|25-531-651-1411|3486.56|furiously final deposits-- even foxes haggle carefully about the fur +383|Supplier#000000383|pGEPbc70IKUZuTiTaigKuizjt7Y5oUoDL3Bq1|22|32-792-648-3774|-484.12|nic excuses. carefully even requests alongside of the regular p +384|Supplier#000000384|zMr51gtJ0Vu83Dk|7|17-554-428-8511|1342.17|taphs cajole furiously blithely final +385|Supplier#000000385|4RDwKCNc6 yBY|18|28-730-866-8837|5836.17|frays. requests sleep ironic theodolites. carefully even requests doubt furious +386|Supplier#000000386|zxFf8YWdD9ltSzw0NOTFpKcBH8zJrzif9|13|23-535-472-3290|-404.12| foxes wake carefully dependencies. slyly fluffy depen +387|Supplier#000000387|EEmqrW2gNAbuJjKuTPgA8kmKA0bZcQSmV|7|17-797-328-7624|3854.14|ld, unusual packages alongside of the carefully final deposit +388|Supplier#000000388|n27XQohXrXlJRLdsyXNoljPS|18|28-306-827-7902|6540.34|rate around the regular accounts. furiously special pinto beans use bli +389|Supplier#000000389|FW96liSdq3noHJpwM|24|34-885-883-5717|9467.35|nag ironic packages. ironic pinto beans would sleep furiously. regular realms wake across the +390|Supplier#000000390|8Qv7RjLQSFfyt5JpH8fsTf0|7|17-821-610-9726|868.36| to doze along the foxes. final requests are furiously. furiously express accounts use bl +391|Supplier#000000391|HBkwkigT2P9bU2wXBrPnQ|15|25-736-211-2793|6475.66|ckly furious dolphins about the furiously even d +392|Supplier#000000392|5YSB73Q4LMC9648IF1GGJAP|17|27-961-813-1153|527.38|ckages outside the furiously silent deposits sleep within the fin +393|Supplier#000000393|hxGMP2tFry WHEeI5cmEFVF027E|5|15-120-912-1594|6686.84|t the furiously regular deposits. excuses about the ruthless, regular +394|Supplier#000000394|5mGD3d,LeKycAyeYbVlrGMlzmT|9|19-517-731-4139|7685.82| accounts play quickly carefully unusual requests. blithely pe +395|Supplier#000000395|vYD9APwEz6R1BFWJ,GDJ7yCUZJm|18|28-723-165-7801|688.37|xcuses. regular deposits across the blithely final packages haggle slyly u +396|Supplier#000000396|WMtmXuQwBKESTTFH4ru1f|10|20-236-453-5458|6420.86|ts. quickly unusual accounts are fluffily above the express requests. daring, stealthy pi +397|Supplier#000000397|kFrhzYG1SR8aWrHsftcptN,im88pImSkxxFu|24|34-880-360-3462|3425.62|ependencies about the regular pinto beans haggle quickly about the s +398|Supplier#000000398|WTV,rO0S1KZFKlhLsUpAH|10|20-536-426-8920|9354.75|mong the courts nag slyly special foxes. furiously regular theodolites w +399|Supplier#000000399|UCzZPQfZXnRhGZcXfnnvkfnqLVEOc|20|30-814-148-6803|345.97| haggle furiously about the close theodolites. foxes along the bra +400|Supplier#000000400|QACx8vfYzPsZHCet2Yjst4e2XzjOXF|21|31-514-285-7013|4624.87|eas sleep furiously among the regular ideas; slyly bold excuses alon +401|Supplier#000000401|9 zStaJ sD|10|20-586-179-6994|2233.53|ages. dolphins integrate blithely final waters. carefully unusual accounts are fluf +402|Supplier#000000402|i9Sw4DoyMhzhKXCH9By,AYSgmD|3|13-109-731-3195|4943.01|around the carefully pending dolp +403|Supplier#000000403|TTVlcRcFrglnhCffA11iw l6bZyyaI9xcRF|9|19-513-268-3908|3102.18|he regularly ironic packages. idly final excuses integrate according to the +404|Supplier#000000404|RQwxP4tpScystYCqOJ,XpCWr4Kox4|7|17-943-161-3434|7311.61|. carefully silent instructions affix. blithely even requests unwind. final dolphins de +405|Supplier#000000405|dJIijVTX n7M0NDEQvCA |24|34-728-545-7374|3213.18|er the foxes. special warhorses nag fluffily +406|Supplier#000000406|zMhU58CDF4aHTeodxg9IgRZgq|21|31-926-216-4352|2867.41|o the even accounts. fluffily ironic asympto +407|Supplier#000000407|WliGC47Vto2nh7mj|11|21-112-803-6707|-459.62|ar asymptotes. carefully regular req +408|Supplier#000000408|qcor1u,vJXAokjnL5,dilyYNmh|22|32-858-724-2950|6173.87|blithely pending packages cajole furiously slyly pending notornis. slyly final +409|Supplier#000000409|LyXUYFz7aXrvy65kKAbTatGzGS,NDBcdtD|7|17-719-517-9836|-820.89|y final, slow theodolites. furiously regular req +410|Supplier#000000410|6V,FO4xJPwvxGzReYzVj6dwTSIechnSSCyz9iY|19|29-822-375-4854|6234.92| beans sleep outside the thin instructions. thinly even soma +411|Supplier#000000411|G9H53XVrdbhRgvQwho1AS|18|28-518-787-9625|2250.74|ial foxes. furiously permanent packa +412|Supplier#000000412|S2onAA,jGtQ3qfpN|12|22-351-499-2131|8183.66| the packages! quickly even warhorses haggle slyly along the final, expre +413|Supplier#000000413|GAufsRQQE P,dVCZWIMEUAsm,7|11|21-875-836-5585|7788.45| the fluffily even pinto beans. closely regular asympt +414|Supplier#000000414|FkmlHgU9pqCboQ32Lcx|21|31-118-322-1371|9547.00|. blithely unusual packages might cajole blithely regular requests. +415|Supplier#000000415|ibzrtLp NIBzzQVh2mc6M7GJj3V2Z5uKlIDw,z|20|30-297-706-6489|8575.44|inal deposits against the ironic Tiresias wake according to th +416|Supplier#000000416|F,9zQapGlzjmqRhVTj1DR|11|21-245-879-3004|3550.06|ic orbits according to the furiously f +417|Supplier#000000417|b3CbQxCMWWu,YyeQU 51fccuv7Mt|6|16-563-597-5520|-113.45|equests hinder quiet courts. carefully +418|Supplier#000000418|l07dIg BFdcW|24|34-689-611-9130|5229.01|re of the carefully final courts. ironic pearls haggle slyly along the bold, regular d +419|Supplier#000000419|FpWtqjkbqEXn|6|16-510-433-1061|2899.03|of the carefully express accounts. even tithe +420|Supplier#000000420|kLWtAMtbSn|12|22-971-269-4753|2968.22|eas cajole around the regular accounts. evenly even escapades +421|Supplier#000000421|tXZPR dOYjjbGjarXxKPn,1|8|18-360-757-8604|-128.86|c dependencies. quick, express deposits cajole quickly. fo +422|Supplier#000000422|iu4c7rkFFNOvmfx,aSs62I|10|20-645-417-6790|-755.64|ly even theodolites. blithely c +423|Supplier#000000423|VCgMjClu4IDaVVMwMW0ARf1ho|24|34-577-174-3894|2937.16|quests; bold deposits lose pending deposits-- slyly pending packages play slyly. regular, ironic mul +424|Supplier#000000424|uOdFKME6fSAI,rvLcpTL|22|32-406-948-7901|5881.52|es. furiously pending ideas against the fluffily si +425|Supplier#000000425|a KnEGf,bqEnGd2Wd9Tl|0|10-262-132-6639|2805.77|ular pinto beans are among the fluffily bold acco +426|Supplier#000000426|zjIHPRMAI8vF|23|33-576-289-4702|8621.42| requests nag. slyly regular ideas +427|Supplier#000000427| Hnd2bzQ95, Adq bg7BQAbFVmRV9rQ,jY98|20|30-315-782-5162|6223.17|he regular requests haggle blithely about the forges +428|Supplier#000000428|v,lOR2jikAbT0hNyPuYhhJODDs2VBPp|17|27-542-634-4350|2890.48|ly final packages. silent depo +429|Supplier#000000429|6ITML8w7yXMd5wzp4xUYXX7rb|23|33-283-246-6716|2267.98|l ideas sleep. furiously ironic +430|Supplier#000000430|SMdrDaNv,2XyFOL6oVEfvH|1|11-541-204-3496|939.22|? silent pinto beans are abo +431|Supplier#000000431|WoeV,NINojE6hJjauAdrl5fGcdxX5JUPLnrim|3|13-269-548-1399|9477.34| according to the bravely quick dolphins. deposit +432|Supplier#000000432|ZkBaoMg9n7nXd1fyn |10|20-401-350-6978|3812.16|ven deposits sleep slyly after the blithely busy decoys. slyly ironic deposits +433|Supplier#000000433|At103qyX,VicINJGCOU51mQyfdYBB44Cg0S|14|24-141-780-8375|4988.55|r carefully according to the furiously regu +434|Supplier#000000434|endL6N 85uU0NemLv4L3mSEH4LT2BF|5|15-763-277-6054|9522.03|n, final packages. furiously pending c +435|Supplier#000000435|xKvU,V2SZj3OqEwdlgXs01K jSbJRjYYF|8|18-874-271-6733|6776.54|nic theodolites. blithely dogged accounts haggle furiously express pinto beans +436|Supplier#000000436|MV8Xu3m,93IINpPlE|20|30-253-200-6170|8396.49|. carefully regular request +437|Supplier#000000437|HuqIk0sK4yC6x5be,cTlPrFqqBCHYf|7|17-652-134-3031|9807.53|usly bold deposits about the pending +438|Supplier#000000438|cePboEvTZ6IfUAG 8asHxVbEmZnLSph9z01|24|34-502-705-5611|9291.35|hin deposits. blithely pending deposits sleep slyly. slyl +439|Supplier#000000439|dTnCcwPBKS J WRmt,Emi KnILcwcR9YOrdLuWD2|9|19-415-856-7881|1871.86|ithely ironic packages use special foxes. carefully even packages snooze quickly +440|Supplier#000000440|s4UNoE4WDs9vXLZFJjsCVxZ0W8XU YCgqGBxVX|15|25-475-341-4841|9290.23|uses. requests cajole among the quickly regular fo +441|Supplier#000000441|fvmSClCxNTIEspspva|14|24-252-393-5381|5008.40| the even, unusual ideas. slyly even plat +442|Supplier#000000442|PJSCHXMAsqyRr5aPD9lp4tUl1B1WytbosVY8EdNZ|11|21-463-951-7051|2257.13|es wake. accounts sleep slyly. slyly ironic platelets haggle. slyly +443|Supplier#000000443|nbs9cmnC63bi|10|20-238-345-8589|5569.82|sleep even dolphins. enticing deposits wake. furiously regular deposits acc +444|Supplier#000000444|mHr2VcUpRkvyQ9rjKMaPkeWbVZmEIhxhb8F|21|31-256-493-5644|-12.78|riously final requests sublate slyly. furiously ironic packages +445|Supplier#000000445|WqzJKhnLnF05It4 5TDkGkUwVYszIko|20|30-686-270-2150|3065.22|r the stealthy theodolites. bold, unusual attainmen +446|Supplier#000000446|na LX4kqDQbh|8|18-902-583-3116|2141.08|usual warhorses-- carefully unusual dep +447|Supplier#000000447|UHeJiRfImFw1r4MTrBk0vcwUx9|5|15-104-804-3139|2108.30|deas thrash blithely. unusual packages in +448|Supplier#000000448|cYzWCXDovaNR ,S3PICo3KYKAG3bYm0YKyqaZVu|24|34-817-553-5356|1209.30|e thinly slyly even warthogs; final asymptotes boost unusual pinto b +449|Supplier#000000449|kOYLYC4JQ5tBVlul15gdo6smU,VdIObtXyC|10|20-757-629-3940|5701.21|gular deposits are carefully about the furiously ir +450|Supplier#000000450|t3hxOMnv5AFdpM4|23|33-257-936-2585|8199.71|oss the gifts. final accounts cajole. sometimes special asymptotes are carefully along the package +451|Supplier#000000451|cqMKQiLjokvIFG|6|16-328-146-7253|2503.45|cial packages. pinto beans +452|Supplier#000000452|6bT4efJCWyxEtXmA1ZdwmqfrPGK|17|27-445-799-5245|9524.84|ions wake slyly alongside of the carefully ironic theo +453|Supplier#000000453|bpt98PxU5HSQt61bVB695JPjBmJKUv hNzQeHvC|21|31-882-179-6015|-905.25| quickly until the ironic accounts. pending requests doubt bl +454|Supplier#000000454|K8p1uXD3L,L|0|10-453-843-1585|7337.45|ronic requests haggle furiously furiously regular accounts. stealthy asymptotes sh +455|Supplier#000000455|de1QmawQjYipd|9|19-822-816-5632|8563.10|le. slyly even requests thrash blithely across the flu +456|Supplier#000000456|iSqve6KC7t69,jX6,HF B8Hbat11O|5|15-951-880-7133|5154.37|e along the slyly bold theodolites. packages detect. regular requests sleep furiously b +457|Supplier#000000457|Jld2rUj,Xw3u,lLq2EevCRQVYwSnkCT1K7nY1if|8|18-721-125-2213|2458.18|lyly across the slyly even courts. quickly silent +458|Supplier#000000458|IFNkUK1H53HwUHabiONkMFAUDb|21|31-318-754-9316|7654.94|blithely enticing deposits are. furiously final accounts about the regular requests h +459|Supplier#000000459|w12ixcTkh6AtG1LvWxX8El8Nf4vEGQiZrrpy|18|28-295-883-6516|9569.85|arefully even deposits. furiously final requests sleep. packages sleep. q +460|Supplier#000000460|lGEBJPLJaDwOhZpc7DQMY,PTUEv6BVBUsOGK0oF|20|30-851-458-4942|7619.85|ar theodolites use carefully about +461|Supplier#000000461|VLYMztlQim7tjPGSK0xPZXnb91a8,9wqVRwk62BP|22|32-897-799-8437|2922.33|foxes. ironic, ironic packages lose furiously regular accounts. carefully slow excu +462|Supplier#000000462|Bg,C2gIsljPAG|5|15-387-146-3147|9497.29|uriously unusual courts. blithely express deposits could run +463|Supplier#000000463|XOb4DatMUyqMuFM92ZRaapwsEQ|0|10-178-678-7353|9091.71|lay. deposits breach instructions. sl +464|Supplier#000000464|XwZyuXCVeO5wb5izvhfeX|5|15-653-204-7643|1448.94|ly. ideas are slyly after the ironic, regular accounts. platelets among t +465|Supplier#000000465|YOOuLmTfTFNFiipLtt iL7HQ fj lf0xOKDjnu|17|27-586-454-8554|7267.03|ly regular accounts nag. slyly regular deposits run furiously slyly final requests. accoun +466|Supplier#000000466|HEW3DIL,Aw0Ud|22|32-408-942-6024|2051.26|requests. closely final pinto beans according to the quickly ironic instructions breach b +467|Supplier#000000467|aibBbBkbtmDJ988LnMNkCAi|12|22-666-307-4101|-467.16|ackages. even, final dependencies sleep quickly. carefully regular deposits cajole furi +468|Supplier#000000468|T,pwE,skbYjr5DCAD2EfmEHNychqFKw1loF|6|16-494-568-3545|449.82|nusual dependencies. blithely even packages are blit +469|Supplier#000000469|G4Xq2 RFlLP7uDadWjZ96 uyaGNk8 216c6|9|19-527-692-4725|994.99|ely express foxes. carefully unusual packages nod furiously. blithely unusual pinto beans cajole at +470|Supplier#000000470|XckbzsAgBLbUkdfjgJEPjmUMTM8ebSMEvI|19|29-165-289-1523|727.89|gular excuses. furiously regular excuses sleep slyly caref +471|Supplier#000000471|Fc4 FkVkaA8zsUVr,bT3PcTko0n|12|22-925-324-7167|-414.45|hely ironic accounts. ironic dependencies sleep furiously about the bold requests-- q +472|Supplier#000000472|NlJV2a0ovbomfosgHUBx6sgT|20|30-976-134-3524|6238.12|to the quickly even deposits print slyly ironic requests. sp +473|Supplier#000000473|x1skh3uebekXL4BIKGgIGDUfTk CDn5FIJGaq2|15|25-658-329-5141|1094.74|old, unusual grouches. furiou +474|Supplier#000000474|USHBMdX8iFodU|0|10-327-319-7717|5226.21| wake. even pinto beans sleep quickly about the slyly special theodolites. courts +475|Supplier#000000475|xw4V6,4QQW LI5Qg EOKy4JD B4Cq1tjzaOma9Y|3|13-397-755-1516|-115.01|among the slyly regular deposits cajole after the even theodolites. carefully unusua +476|Supplier#000000476|ZvT qI2gMbh|0|10-219-531-3554|980.32|o the silent hockey players hang quickly around the furiously special theodolites. carefully bold d +477|Supplier#000000477|VtaNKN5Mqui5yh7j2ldd5waf|7|17-180-144-7991|7205.20| excuses wake express deposits. furiously careful asymptotes according to the carefull +478|Supplier#000000478|4jV maCw9SEt8jyLUsjej60bmMhP6zBv ajTk|11|21-580-334-3987|7901.42| regular asymptotes: fluffily unusual accounts integrate +479|Supplier#000000479|tdLkV2Ks0wBP1VlwdnPUxZnWADmxlbmRVE0a6h|18|28-851-500-5156|5283.98|s. blithely final asymptotes haggle fluffily. regular ideas +480|Supplier#000000480|q8,LH5UQiP3Tv60slOsFzX,HM0JPcwM0rD7eg d|14|24-645-644-2970|2927.68|ular deposits according to the furiously even asymptotes use among the bold deposits. quickly +481|Supplier#000000481|VqFS2DPW Ci2TpkfD|9|19-951-947-8520|539.24|refully stealthy instructions hang blithely ironic pinto beans. ironi +482|Supplier#000000482|LkVra4orMCs|14|24-516-940-6953|7978.18|ages. final ideas need to wake quickly fina +483|Supplier#000000483|ncWfnroE1n639qMrW8|2|12-443-228-5035|8366.89|refully regular ideas. furiously express theodolites across the sl +484|Supplier#000000484|WwSH FFzB2lViwrWli6Z4QVV AN1KH2G8|24|34-506-254-3252|7350.40|t the pending, even instructions. blithely +485|Supplier#000000485|ULR12B9vkQg4g0nFMaW|1|11-779-798-5195|6282.72|tegrate across the pending, special instructions. furiously regular di +486|Supplier#000000486|nCwPqLXZwjH20OVRy,fCQskTo3it2JHEGn7l|20|30-632-817-3179|2709.83|nusual, pending deposits wake blithely ironic deposits. +487|Supplier#000000487|BvDBcJa,jQPslM|5|15-551-730-1265|2124.86|ly about the requests. accounts could use blithely? furiously pending accounts nag regular, even ide +488|Supplier#000000488|AzfObar4VYwnQvsGbISGCshVM AIWYq9|13|23-609-606-3265|4546.13|ly ironic packages use quickly about the ironic theodolites! blithel +489|Supplier#000000489|y9NMoYGxDUPfrB1GwjYhLtCeV7pOt|10|20-375-500-2226|9836.43| quickly carefully pending accounts. fina +490|Supplier#000000490|JNqlktPWJ4|2|12-619-779-5325|10.55|ng to the packages. carefully final +491|Supplier#000000491|mTbDcJHQ7d|0|10-361-729-1693|-836.47| to the blithely even deposits. fluffily silent waters sleep blithely above th +492|Supplier#000000492|8wEulEYM zGvMXfDNNEw4B|14|24-875-296-5180|8368.06|y. slyly express deposits alongside of the accounts nag fluffily after the evenl +493|Supplier#000000493|7tdI3AtlDll57sj5K48WLX j5RDbc|11|21-252-702-2543|4999.17|gular foxes. slyly pending requests hang along +494|Supplier#000000494|6hAiQHDGTy6,8bjpxI i3f|13|23-200-629-1426|1080.57|pending packages. slyly even deposits wake closely. specia +495|Supplier#000000495|p086j79twIlC25BD6A|12|22-881-968-9019|9097.65|y regular theodolites shall cajole. requests cajole slyly +496|Supplier#000000496|be4auZxyqAgF5ysH3nXWcc7bDsNgdZ|20|30-810-880-3654|2266.32|theodolites. slyly regular +497|Supplier#000000497|iLAqlCKDLUGqHrjuOcId7 uYoTmpA|12|22-895-454-2151|5980.87|es nag about the furious +498|Supplier#000000498|4jvUQrC4acOQ82EFM vLNHG|17|27-772-853-6514|485.25|. slyly ironic ideas cajole slyly quickly ironic deposits. blithely even theodolites boo +499|Supplier#000000499|NbcQeBiDiN2tFiVxHIaWU03BVFIuxt |18|28-243-638-7646|2518.34|al, express deposits hang furiously. regular, unusual pinto beans wake a +500|Supplier#000000500|jLfNCVrj7X5h31yfSR02Z4x7K|20|30-229-226-6452|6738.72|ly. carefully final packages boost +501|Supplier#000000501|PSStC43vWlQQpmTku4s|24|34-141-983-6520|-264.89|s nag quickly. platelets haggle quickly above the furiously silent packages +502|Supplier#000000502|AutSetu5u6moXK6Y3rpoWREh|4|14-678-262-5636|963.33|al excuses haggle furiously iro +503|Supplier#000000503|OtYqMbur3v7nfzYgFYmMrJvq5YTj1MtXgefj|20|30-263-152-1630|7643.78|players are across the slyly silent requests: even, r +504|Supplier#000000504|P8k2mjRiRUFCJfxw7KrEdRpNNQPDxiI|10|20-322-544-5770|9050.12|y final pinto beans. blithely regular instructions wake abo +505|Supplier#000000505|aqcYZYQD5TYlLDgIxhKZyFCzL3Ch5qKOxj|9|19-480-691-1853|6399.78| requests engage slyly regular ideas. fina +506|Supplier#000000506|hnXNVHB1ao5rlGLkrS64kBz5C5rx7 R4dqO5CNv|23|33-582-741-7991|1202.98|riously even accounts sleep furiously ironic foxes. quickly final requests haggle fu +507|Supplier#000000507|aF2w4JF8qV aaqApYqzTFtIXtKV57Na|9|19-981-569-8699|9464.26|p carefully besides the furiou +508|Supplier#000000508|F9,suuHYbe6kCRCPZaeSHSPAFBk9vOcFX8TUx|14|24-179-400-2422|3878.22|sits. blithely furious requests boost slyly about the quickly even packages. closely +509|Supplier#000000509|SF7dR8V5pK|6|16-298-154-3365|4315.15|ronic orbits are furiously across the requests. quickly express ideas across the special, bold +510|Supplier#000000510|VmXQl ,vY8JiEseo8Mv4zscvNCfsY|19|29-207-852-3454|-314.06| bold deposits. carefully even d +511|Supplier#000000511|RWNdTEe,VJFarN4Pu7Xl|23|33-476-213-8045|-455.12|t the quickly even deposits. carefully careful ideas sleep slyly bold deposits. unusual, even accoun +512|Supplier#000000512|MoNOuMC4QMOnBgD5uLcvtHCcfzf9cW|15|25-617-226-9364|4762.66|special accounts. daring foxes nag quickly silent, special packages. silent, unusual a +513|Supplier#000000513|YMhcTaVkhw0nO9B,|4|14-481-495-8505|8075.30| final requests. slyly final reque +514|Supplier#000000514|Q4ErX,NN,Z2UDP|14|24-677-367-2786|1669.85|arefully regular ideas: pinto beans detect across the slyly pending pinto b +515|Supplier#000000515|5TOuZXAb9df7m3BCW2 TeHMY1Zdf46DqpT2,0t|17|27-470-220-5233|2127.89| beans sleep after the final frays. special ideas across the carefully regular instructi +516|Supplier#000000516|z5Mm65PAP4m|5|15-165-647-2301|371.38|s. idly final theodolites ha +517|Supplier#000000517|NkRQYLe9d8vEXNO KKk8rxK502OI2 |8|18-577-641-3805|2781.03|ing asymptotes. carefully fin +518|Supplier#000000518|g2buDv7WzbkNDU63IN5af0i6SAdUxihirS2X|1|11-853-939-1266|-199.77|egular dependencies integrate carefully among the enticingly f +519|Supplier#000000519|0zgIDeAmk5976RzKiXZi,kobff8IxQn|19|29-133-225-9811|6361.20|onic requests cajole blithely furiously pending ideas. quickly quick accounts sle +520|Supplier#000000520|RHuqyeshPnOa6gwEiV3zDhP0o2aYvZ9glQURu1w|12|22-654-808-2429|1682.84|aggle among the final, pending realms. carefully regular escapades woul +521|Supplier#000000521|jQ648xqiuJaHLQjwrq5b|1|11-887-652-3799|507.99|carefully final asymptotes: carefully regular epitaphs about the blithely u +522|Supplier#000000522|joLGRuiXIsVWk|8|18-355-956-2843|-336.14|tect slyly final instructions. fluffily ironic ideas after the final, fina +523|Supplier#000000523|zzfDhdtZcvmVzA8rNFU,Yctj1zBN|18|28-458-231-8410|2492.06|e, regular deposits eat. fluffily express foxes haggle a +524|Supplier#000000524|rTYNcqhFosNU,4|13|23-993-423-3788|5093.35|c theodolites integrate quickly ironic deposits. furiously even de +525|Supplier#000000525|GtHZ9ooyeKe|11|21-247-956-8546|-79.52|y bold theodolites; express requests across the packages haggle slyly carefully final pinto b +526|Supplier#000000526|x8r7,jgpBRjq6Ns|5|15-539-980-8303|3477.18|as kindle ideas. blithely bold requests +527|Supplier#000000527|udKczd6U1Bm79UVDkA8P2Xa1VY qv9mvsXo|18|28-894-961-1780|6938.43| sublate blithely pending instructions. blithely final packages nag blithe +528|Supplier#000000528|QsnGjo7irxCIbN3|2|12-961-772-2408|1285.81|the furiously final tithes are across the pending ideas. car +529|Supplier#000000529|Fj4vm8y2 Tlgd|10|20-521-276-3787|4581.80|wake across the furiously regular excuses. express dolphins are q +530|Supplier#000000530|0qwCMwobKY OcmLyfRXlagA8ukENJv,|3|13-747-781-9694|4327.86|fily pending dependencies wake slyly final deposits. platelets against the slyly ironic requests na +531|Supplier#000000531|fN0ix827c112YajETqxxuofrfl7v VndWB38n|22|32-950-377-4573|4258.42| the carefully ironic gifts. carefully unusual multipliers sleep slyly amo +532|Supplier#000000532|ep92hT7VLaVlDKM7lgbj02kIL|3|13-595-401-8233|3278.71| fluffily fluffily express ideas; blithely special instructions wake quickly among th +533|Supplier#000000533|WF9wtTxzbBa4kv FAeer9I1pQJ0Qe,uJf3f w|7|17-404-617-2581|4213.95|e ironic foxes believe fluffily across the u +534|Supplier#000000534|JBhF3gZcQiNWGxh8DuoAhmVi|9|19-198-519-8383|3930.79|after the furiously even requests haggle thinly a +535|Supplier#000000535|aiq9Honllr6hFt, YJ6|10|20-121-889-4500|7839.46| foxes. carefully thin dependencies sublate furiously. regular instruction +536|Supplier#000000536|dzf PbgzKpWBDim5S1BSPLBNzxFpxZNUE|17|27-749-678-1361|8797.40|cajole blithely slyly even dependencies. carefu +537|Supplier#000000537|KsYYPIw2kWP|13|23-671-207-6720|5046.81| forges breach upon the bold ideas. final foxes nag frets. final instructions eat fluffily +538|Supplier#000000538|KBZ0RSDGTVJQPbWaU6x|17|27-799-369-5739|9669.24|e fluffily regular theodolites. special packages are into the careful +539|Supplier#000000539|GG5N3GIdNmmvhKs52Y|1|11-844-496-3836|5976.60|otes; carefully ironic deposits sleep idly along +540|Supplier#000000540|Tmyis ,xX7XjU2E|16|26-891-481-8993|5704.81|. blithely final instructions shall cajol +541|Supplier#000000541|Nxggufcm ,hR|17|27-914-557-6989|2830.62|blithely ironic accounts poach blithely alongside of the carefu +542|Supplier#000000542|3yWRklEDbAvfVuidQPgOOe,x7f,4 J5lSp4v|5|15-378-700-5884|8142.81|g requests believe carefully dolphins. quickly pending +543|Supplier#000000543|P10rl2 o A0jtJQDcB|15|25-433-303-6328|3222.71| against the carefully ironic excuses boost bli +544|Supplier#000000544|pUS3drDXbPeNqvI kUNlnz5GDSU5,aLI|1|11-471-707-9878|9042.70| sleep ironic accounts. fluffily even dependen +545|Supplier#000000545|D8SE9UgTdgq3oNH8RzaxDKpbsA BlRKsf|2|12-876-408-4086|2723.99|onic packages use slyly about the theodolites. final platelets are. finall +546|Supplier#000000546|YznQGwWvZbNA0O9ZV|22|32-679-789-3863|9036.47|es haggle. blithely final theodolites wake blithely. carefully regular packages +547|Supplier#000000547|MaV373lvwj|8|18-600-279-8954|7937.31| the quickly ironic asymptotes nag carefully +548|Supplier#000000548|btRiQsq qEK0qg0T|12|22-790-987-6339|3456.36|ly even tithes sleep alongside of the asymptotes. blithely ironic requests are +549|Supplier#000000549|oy89mLRUwTVCoU|0|10-377-880-8280|8948.84|iously final ideas. carefully unusual ideas wake fluffily special platelets. furiously unusual pin +550|Supplier#000000550|QQavssDXnYHbvOrg|12|22-648-743-9295|9238.79|en, bold ideas. ironic, unusual deposits boost carefully quick accounts. slyly e +551|Supplier#000000551|ZNiqP1w6Z SGZsLllIhaicTnLCCuAepdNbkm6pJ|8|18-297-775-8421|9364.67|lithely even instructions poach quickly. furiously bold accounts sleep final, final accoun +552|Supplier#000000552|JP3ebtH5epPwpU2lVQqKNZC3NTvnTlrhLy5eeGN|12|22-861-905-2401|2114.99|uickly about the deposits. furiously pending accounts wake. packages are slyly bold de +553|Supplier#000000553|a,liVofXbCJ|6|16-599-552-3755|3526.53|lar dinos nag slyly brave +554|Supplier#000000554|FAEEZyNtDGEhZ|7|17-365-531-4630|335.69|enticing accounts against the deposits use q +555|Supplier#000000555|TfB,a5bfl3Ah 3Z 74GqnNs6zKVGM|3|13-607-927-7514|7896.01|uriously regular theodolites according to the carefully f +556|Supplier#000000556|g3QRUaiDAI1nQQPJLJfAa9W|6|16-951-842-4482|2253.90| silent deposits haggle quickly ironic, final theodolites. boldly bold accou +557|Supplier#000000557|jj0wUYh9K3fG5Jhdhrkuy ,4|3|13-704-788-7706|6343.15|ckages. unusual, regular attainments +558|Supplier#000000558|T9hNjrRRRQmkbZomdaeLKDOqmmUcJpAJzXOxq|9|19-494-404-8664|6404.51|s against the carefully pending packages cajole al +559|Supplier#000000559|SkKThClbkbH8mIv|11|21-205-567-6566|3646.46| ideas cajole alongside of the carefully ironic packages. regular pint +560|Supplier#000000560|rYTPbri8qJ49rRfFmChtnDIQ|17|27-261-214-5284|3009.57|slow platelets. quickly pending ideas are requests. even theodolites may nag about the regular, +561|Supplier#000000561|1V3DMQWQpfjPJybZYAP|22|32-547-343-1231|1824.47|d packages. carefully bold ideas are quickly across the platelets. final, express pinto b +562|Supplier#000000562|8TXCtnRQzByqjie|23|33-782-496-5965|4848.52|he furiously special accounts hag +563|Supplier#000000563|Rc7U1cRUhYs03JD|7|17-108-537-2691|-942.73|slyly furiously final decoys; silent, special realms poach f +564|Supplier#000000564|IufyqhG4fmo VkgQT w BF4|2|12-702-995-1506|4410.70|epitaphs. even attainments cajole slyly regular packages. final deposits cajole. furiously final +565|Supplier#000000565|,oYB9wlD3mtL lj3PJC67a RGXaqh69sHK5G4e|20|30-487-989-9411|-334.52|s haggle never furiously special deposits. final attainments breach special pains. fl +566|Supplier#000000566|hBRvnhCUVIiXQK6dyAZYN,TNZItOlBvsVYCisb,O|24|34-396-766-5348|7705.73|rs! special packages cajole-- furiously final packages maintain slyly around the blithely spe +567|Supplier#000000567|fvuRpAap0MvoBguGKBfp|1|11-390-878-2811|5264.91|ke fluffily furiously ironic ideas. qu +568|Supplier#000000568|z70Hj8qVi8jQu|10|20-162-593-6831|1367.90|furiously fluffy instructions about the regular +569|Supplier#000000569|jjFjVCjK91yy2B dj|15|25-803-734-8127|9166.95|al frays until the slyly ironic requests cajole furiously about the quietly final foxes. furiously p +570|Supplier#000000570|8VkNpvXFgKgbKY2ypMKyIOBlK|17|27-658-225-4655|922.72|! regular platelets sleep furiously idly silent foxes. even courts sleep slyly. regular, reg +571|Supplier#000000571|GMifmfVJba|9|19-223-236-6710|7132.44|nto beans haggle carefully after the furiously regular reques +572|Supplier#000000572|J,RTwd9mNOTralFovrCrH99 f9rbvsDf3|19|29-444-247-7800|6039.27|its. carefully even requests along the quickly unusual pinto beans inte +573|Supplier#000000573|83GRV1s,yGFwl1NClLSXnJVRlh0xS8YW8|12|22-306-652-6853|3107.46|icing accounts. carefully regular sauternes according to the accounts wake after the fina +574|Supplier#000000574|2O8 sy9g2mlBOuEjzj0pA2pevk,|22|32-866-246-8752|8096.98|ully after the regular requests. slyly final dependencies wake slyly along the busy deposit +575|Supplier#000000575|J24LOV AQiHuYuR|19|29-201-935-5958|2918.54| special packages along the carefully e +576|Supplier#000000576|Plc2DypORn4qNOTpZ|12|22-316-723-5789|817.26|e of the final deposits. regular, unusual requests wake slyly. furio +577|Supplier#000000577|kn5oGAnFD1CQjet8awWorC,UMf37MP71yNcVD|13|23-973-363-7797|5593.17|olites along the quick accounts cajole throughout the regular asymptotes. accounts maintain +578|Supplier#000000578|bn5J0A4426DpcW7m rQ9,qxqJ1KN|20|30-105-334-1726|7428.76|carefully about the slyly regular warthogs. special packages above the regular pa +579|Supplier#000000579|U6sejT6kSPi5p1FUcUxjdJ|19|29-854-341-3857|3144.98|ly regular pinto beans. furiously regular ideas against the accounts nag blithely final pinto b +580|Supplier#000000580|MuRScZH74veaM2|6|16-732-277-6239|614.57|packages. furiously final theodolites integrate according to the carefully silent braids. caref +581|Supplier#000000581|X pNyEcNqxYwiP0gJ7FzkJ,haGkn|18|28-320-345-9799|8998.40|cross the quick packages wake carefully except the accounts? +582|Supplier#000000582|o6h0Bjjwags0FDRSAoKJPCWyt|4|14-341-851-2277|6178.48|ly unusual packages. regular, pending foxes are blithely. fluffily +583|Supplier#000000583|9st8mjB5G7J|15|25-760-126-2928|-339.15| dolphins across the carefully regular instructions hagg +584|Supplier#000000584|XvDYsHYpmY5AkX60fj0bZo4WW|18|28-223-704-2186|6912.86|e requests haggle carefully even ideas. express, bold requests integrate quickly furiously +585|Supplier#000000585|DQZTWEfNYL9UDlMqcQAEThcPdbyD45PYzL|23|33-357-931-8857|433.74|ar, silent instructions i +586|Supplier#000000586|9tfHwYyFe2t2,6pAVpkURXAxtc2cQw4qfGKYJ|2|12-747-610-3099|5850.91|ccording to the stealthily ironi +587|Supplier#000000587|58,gb EuMperMCg2lv XUQ9vi4GzhO2a|7|17-128-699-9949|5322.35|thin pinto beans boost silently. ruthless deposits haggle quickly above the slyly unusual th +588|Supplier#000000588|e3yF5zmSj y81I|14|24-180-601-5741|9760.06|gular, permanent accounts. +589|Supplier#000000589|3C4,WjUCjL59QhMSxyq1|18|28-878-356-5116|3415.90|apades are final, unusual instructions. bold, unusual +590|Supplier#000000590|KhRtsL4Foycp2hUwg bEHkDusXAf|9|19-277-247-1833|-12.84|de of the express requests. pinto beans are +591|Supplier#000000591|iXlVA9y6oX4|24|34-204-742-6291|2082.42|ven instructions try to are slyly about the quickly b +592|Supplier#000000592|tdYqh7rm0Zc7E0etRqHakcg,m34gQX|9|19-220-707-3861|6151.79|sual, express accounts integrate fluffily. dependencies cajole slyly +593|Supplier#000000593|qvlFqgoEMzzksE2uQlchYQ8V|6|16-262-671-5187|2214.36|arefully even ideas sleep quickly. ironic foxes wak +594|Supplier#000000594|8GY0oRK64AFmY7pys51Uqm7YbMn9luO,Z|17|27-826-454-6643|1760.34|quests use fluffily quickly final packages. carefully pending pinto beans are blithely among the ca +595|Supplier#000000595| CURZCs4l306M2ir8rFkgeYVg|24|34-354-570-3604|4922.60|ecial instructions cajole alongside of the requests. i +596|Supplier#000000596|caTnKVKTsCHNEVi1xVPD|4|14-761-106-2656|1180.93|its sleep. carefully unusual somas use furiously above the +597|Supplier#000000597|CKt5G XZ5DBt|24|34-219-790-3864|1828.73|ecoys sleep slyly according to the furiously regular requests. furiously expres +598|Supplier#000000598|p9AGBjg4DZuChQbY8gAj3LtMrxpOWqMpJR|7|17-985-962-2292|-590.83|uickly unusual ideas sleep blithely after the +599|Supplier#000000599|R u1wkvs4 B0wlbPbT8WrSzqoXZG0CjbsuAbPpUs|4|14-208-385-3654|769.29|affix. carefully final accounts about the care +600|Supplier#000000600|YHyUzea88sXoNmqmCMamiEfGC54xpdX|12|22-508-410-2758|2342.35|s. fluffily ironic deposits hinder furiousl +601|Supplier#000000601|TS2xMrQuUs9VrgWt4,gpdcEyWNw3K6,P|8|18-528-362-8573|7906.22|atelets cajole according to the pending, ironic orbits. carefully regular packa +602|Supplier#000000602|xEtByOs0Pydp9y75MSgoy6T R6PT8e|20|30-106-955-5651|8924.02|tes. furiously careful pains are. quickly even platelets boost sly, +603|Supplier#000000603|mECtpm1pmMnqK4K0DLZ5Gtkj 5bUydzBak6|12|22-807-182-2059|-846.12|dependencies. slyly regular accounts +604|Supplier#000000604|B53WjrwJCSh14Bx,oCEinGgCJ3ZCc8m|24|34-390-848-6584|227.59|regular asymptotes solve accordin +605|Supplier#000000605|wdwiNoNT8pVHOTHQ8jhVzaOTkU|6|16-835-870-9488|6071.58|foxes poach blithely beneath the excuses: ironic multipliers haggle quickly furiously unu +606|Supplier#000000606|n,iOFy5X,4GFeXNrCCKBmHucz1|19|29-856-255-1441|6988.38|es haggle across the carefully even accounts: unusual instructions x-ray carefully. blit +607|Supplier#000000607|vgEaPkxAonSSdAUn,7usQ c4G3Ho2r0|15|25-370-994-3762|4667.27|ests are closely quickly ironic orbits. carefully regular attainments cajole furiousl +608|Supplier#000000608|SQ,f89cn6x6g|17|27-435-165-2250|-210.13| do was furiously above the accounts. unusual, ironic packages hang about the carefully final +609|Supplier#000000609|n9 nkdqilT|12|22-852-519-5068|8287.95|ronic, regular ideas nag furiously across the final ideas. bold, express do +610|Supplier#000000610|cRikc,rgxAM3yz0IR85OD|20|30-402-585-4900|668.12|gainst the ideas. regular instructions are. theodolites cajole furiously final, un +611|Supplier#000000611| 6BVljZ1HeradVcmcDm90NYkla3iHPBsTSoUJr|8|18-554-185-6487|7048.30|al courts sleep carefully about the blithely express accounts. fluffily even request +612|Supplier#000000612|gt9T2nnuWBiy5zcrWG2iSdZt,sAEYnD6|23|33-377-769-8060|-118.86| regular requests after the slyly regular packages belie +613|Supplier#000000613|DYwZjMQj26Es8D8pxn2zx|11|21-796-340-9401|2201.94|e furiously. final foxes haggle carefully quickly express theodolites. regular deposits affix bli +614|Supplier#000000614|DteCEt557XpSo8CejUUbFm RgTeT4FRz7bC,6l|14|24-185-488-4015|1956.55|inal theodolites shall have to boost. unusual theodolites are +615|Supplier#000000615|dIT3WOBBwUuakVwd965N4logoVW1A|23|33-196-233-6474|2741.54|platelets. pending, regular +616|Supplier#000000616|Ktao GA3 5k7oF,wkDyhc0uatR72dD65pD|6|16-738-270-6883|7119.71|al packages are carefully after the regular p +617|Supplier#000000617|Q4haZeO8aVzl2dXziDw3f|7|17-563-347-4748|1002.43| blithely unusual theodolites haggle furiously. even courts use quickly against the +618|Supplier#000000618|mPrv5o5d22wyXUgUw69x8m dtx7I3mMh|4|14-912-871-9422|4710.51| the furiously pending deposits x-ray about the fluffily unusual accounts +619|Supplier#000000619|CzILYciyb3fdioa9LflK,ADrP|17|27-505-962-3048|559.50|ironic asymptotes. express, final pinto beans are furiously inside the furiously regu +620|Supplier#000000620|5pd GQ2NTM3c2uR,gCg9NspSE|24|34-347-881-4300|7516.12|posits promise. quickly express accounts according to the regularly pending accounts lose blithely +621|Supplier#000000621|fjFomMNvcBWHb|6|16-492-530-5790|8436.37|ns. even, even platelets up the carefully pending platelets u +622|Supplier#000000622|gCQimU1jYHoQiglDmW1FkQM9wzi YC1P15pMy1|21|31-421-544-2948|9199.28|ent instructions. furiously silent packages detect regularly quickly even somas. even pearls ha +623|Supplier#000000623|dSSQ3dTYwThbLppbetVUeuPfBIUF|7|17-593-337-7365|5408.07|ial frays use. carefully special foxes wake carefully slyly pending deposits-- final requests a +624|Supplier#000000624|JlCK4aBP3PCO|1|11-487-571-9291|9497.65|the silent, final pinto be +625|Supplier#000000625|0zW5d Hyogg0z,sXxl1PHS0Ya,muKs4N dS7|23|33-946-363-3870|4065.25|unts. silent accounts around the quickly final r +626|Supplier#000000626|uaYN3Mg6sVtD|13|23-672-133-9305|1586.50|ic deposits above the blit +627|Supplier#000000627|k6W51QENyVPe4 6z0ajEMTkEA|11|21-632-574-8701|9318.43|l instructions serve slyly regular deposits. carefully busy excuses cajole quickly pending d +628|Supplier#000000628|Gk75kOa26bzFvztn3rgkiOdL M0jTMU|0|10-599-740-9848|5975.00|ccounts play along the special ideas. blithely final deposi +629|Supplier#000000629|SjPnzOlaF3,4u1QAyH1l57EnL,h1IgnmoG|7|17-533-560-8817|856.17| furiously ironic requests by the furiously regular accounts wake slyly across the +630|Supplier#000000630|6hLBs3Rnd5elLLVv1i p3A2U6G1dkIApKDkiCy|23|33-522-267-9970|-418.50|kly bold notornis; idly even forges wake furiously quickly special pinto bea +631|Supplier#000000631|F1uLHPh2tHB6j1YLrB,vilZ5SIn6P1RFTPoz|15|25-354-834-6526|4127.62|egular, ironic packages. slyly fin +632|Supplier#000000632|pSP0SwLWVUKjWyzZtT|2|12-953-253-6464|4975.09|luffily even warhorses. carefully special requests are furious +633|Supplier#000000633|HhHzqIEl0jP8SQYZ7EybSWCtRFhmytByO7CPNZ|20|30-502-537-4154|3322.37|ent accounts mold. blithely unusual packages wake. furiously f +634|Supplier#000000634|hS62vraooyHWnMKyZV3f1GSPeKJ,7uRK6M5|23|33-105-608-2902|1133.80|equests affix around the blithely special theodolites. unusual accounts wake. pend +635|Supplier#000000635|JNDTs06uwtXvRZUWQVpDgAz|10|20-119-524-2053|1739.90|s. packages wake after the slyly ironic frets; quickly pending reque +636|Supplier#000000636|Kc rcRwa,q,TQx1W 3fu|18|28-357-934-4951|2408.11| wake fluffily above the slyly final ideas. silent instructions wake carefully: blithely silent d +637|Supplier#000000637|V6AMGzXQ7Eqs|5|15-832-253-5581|2002.17|rses haggle blithely about the carefully silent deposits. slyly pending packages th +638|Supplier#000000638|YfXfPM0,m6CdwYYiQjmy9dcN|8|18-147-424-5181|-614.31|quickly unusual instructions would wake carefully. slyly ironic request +639|Supplier#000000639|WGqnQRU1xoC,UV9xDGjc48rC4Cow4|9|19-128-575-2303|2172.39|sual theodolites. slyly even accounts according to the quickly special accounts are f +640|Supplier#000000640|mvvtlQKsTOsJj5Ihk7,cq|3|13-758-222-1059|281.90|nic accounts sleep daringly at t +641|Supplier#000000641| 0L8yoIwSCP4EJyESI 6bVH9k|17|27-393-904-4536|5749.43|l accounts use furiously against the fluffi +642|Supplier#000000642|eldBmBVYRbcB YfMRBlNyuQe8k0zYK,v Obk|11|21-775-952-5836|4622.19|reach carefully against the final, pending instructions-- slyly +643|Supplier#000000643|mJN4aN B Lxz2esIAW0GoxEw1rAU|18|28-782-409-7844|1218.59|gular requests. even, pending notornis thrash fluffily against the enticingly regular i +644|Supplier#000000644|70mM6 QN882bcuY|10|20-367-561-9783|7783.86|regular accounts. quickly final theodolites sl +645|Supplier#000000645|blbALMoy2OihlkvD7FtkLXPvTShY9JVtsWT|7|17-742-832-9508|9459.29|accounts. blithely unusual pinto beans at the blithely +646|Supplier#000000646|IUzsmT,2oBgjhWP2TlXTL6IkJH,4h,1SJRt|6|16-601-220-5489|8430.52|ites among the always final ideas kindle according to the theodolites. notornis in +647|Supplier#000000647|x5U7MBZmwfG9|23|33-258-202-4782|9828.21|s the slyly even ideas poach fluffily +648|Supplier#000000648|0RXVM8t80LLWl|20|30-526-602-8400|4877.49|aggle daring instructions. furiously final deposits detect furio +649|Supplier#000000649|8sfoyPTvZbFMXC93ti9qSI6dYN0QuXh3wO|7|17-341-611-2596|1927.21|equests. ironic dependencies are quickly slyl +650|Supplier#000000650|lqBJUDL9EXwh0|4|14-980-933-9338|4624.13|ons are. unusual, pending foxes affi +651|Supplier#000000651|oWekiBV6s,1g|22|32-181-426-4490|683.07|ly regular requests cajole abou +652|Supplier#000000652|Cwyzz7 uW9mWq|12|22-957-225-7894|5235.95|ly fluffily ironic realms. slyly even accounts sleep slyly. carefully even packag +653|Supplier#000000653|IK8OvngBYI1zh9bbK0vLThzVvk7F69hxytOmq|17|27-391-635-2412|9584.63|ar foxes cajole about the quietly final pinto beans. ex +654|Supplier#000000654|T96kVu5bsOeH6|7|17-361-437-5840|2997.61|ial ideas haggle carefully according to the carefully express accounts. ironic accounts pri +655|Supplier#000000655|j8ga9M1KhzXKSk6g,bXi0zbLWjckDEpwBeqs|4|14-708-916-3581|9745.28|stealthily slyly special deposits. final packages behind the regular requests na +656|Supplier#000000656|mQXqRMgstvOI|19|29-633-362-8481|8069.74|ronic packages integrate. even excuses integrate carefully ruthlessly bold packages. regular ideas a +657|Supplier#000000657|nas2fhRwM97W8EEqYpBN|3|13-546-747-5121|7182.24|es wake above the ironic instructi +658|Supplier#000000658|kw9Ts9s38tEPf,IKi6kXNEv02|22|32-991-641-3699|6888.65|ular notornis integrate. permanently final accounts wake final +659|Supplier#000000659|jjVP5XCtV9jbvUnkoeFUTrgB,ke|20|30-917-437-7814|631.86|r, ironic requests. carefully ruthless theodolites across the bravely bold deposits cajole car +660|Supplier#000000660|AmvX 3nxd9r EOYZErE6PvBtFx |20|30-126-295-9200|2555.98|longside of the requests. fluffily bold +661|Supplier#000000661|lZGFurTW1snIqk0oLWMMaeq3L|13|23-401-253-9405|1333.75|s detect quickly. blithely ironic dugouts maintain furiously ironic +662|Supplier#000000662|geJEMlJvE3HdW96Rz3touARh|18|28-497-129-7855|7337.00|the blithely ironic ideas use qui +663|Supplier#000000663|tPtpVTsSAQNw,4GgXR2Hxx5FyCxxgqmW,jE sRT|18|28-798-122-1574|956.88|osits. quickly quiet requests cajole against the slyly regular accounts. ironi +664|Supplier#000000664|ln6wISAnC8Bpj q4V|4|14-244-772-4913|9261.13|ly special foxes cajole slyly ironic reque +665|Supplier#000000665|n4JVAxZUnvT5dVZBK,3CIIDoa|12|22-273-991-9361|-197.51|nding theodolites. fluffily final packages wake? idle req +666|Supplier#000000666|7emVs,4gxuqP95JNK|19|29-330-510-9985|433.93|ously ironic requests haggle. deposits amo +667|Supplier#000000667|La6cVlSLCZZDhhX9FtKsRlylP,,lI3IYjHT8yJJX|23|33-382-268-5150|9009.30|ular accounts after the fluffily pending accounts are according to the +668|Supplier#000000668|lLpUAYxvq5Gu9eLRdlrj|8|18-876-287-5756|2317.52|x quietly among the braids. blithely final asymptotes would a +669|Supplier#000000669|,Csubly4KD59igxGYacW2q7jUvQ4ZaOKQC|20|30-256-757-7811|8577.07| pinto beans nag after the slyly final packages. final requests among the furiousl +670|Supplier#000000670|z2NRPuuVeu1jmuuyzoMOlpoCI6P|20|30-364-864-1141|8887.18|arefully fluffily even pinto beans. pinto bean +671|Supplier#000000671|VlDv51ScrQCe1eVVnz S4Kq5wFZUKJd PyBI|8|18-730-953-4689|6935.18| busy dependencies sleep blithely after the ironic, iron +672|Supplier#000000672|iu9d66fGNBYX|11|21-299-539-7383|1594.77|uickly carefully express foxes. ironic requests cajole about the requests. unusual acco +673|Supplier#000000673|GCmswucbTQe2Q3OHcnsNI|20|30-592-284-5403|5335.98|y ruthless requests. furiously regular accounts wake after +674|Supplier#000000674|jMxLRDxoP1Pf kzzyMVIfLB|6|16-128-338-8014|7822.90|thely after the furiously even pains. quietly +675|Supplier#000000675|pbDwRMZ6nNUpcFirCvv|15|25-499-280-9384|5579.98| bold deposits. regular, regular pinto +676|Supplier#000000676|USGIdhKusoe8dcvWdBbZWUfxnVxNnsgY mG|9|19-833-604-9178|5783.61|s use deposits. quickly even packages haggle quickl +677|Supplier#000000677|8mhrffG7D2WJBSQbOGstQ|13|23-290-639-3315|7128.81|nder blithely. slyly unusual theod +678|Supplier#000000678|SLpBfeoHSImv|1|11-465-565-3513|-58.41|he blithely even requests. blithely unusual theodolites sleep furiously against the +679|Supplier#000000679|qLzdFRbVDeEH|4|14-771-110-7666|6291.34|ole slyly against the furiously silent instructions; ironic instruc +680|Supplier#000000680|UhvDfdEfJh,Qbe7VZb8uSGO2TU 0jEa6nXZXE|22|32-522-382-1620|4586.49| the regularly regular dependencies. carefully bold excuses under th +681|Supplier#000000681|ArTNWD5g1KfANCMFDfk83TUlX|12|22-208-790-6946|6159.40|. carefully special ideas promise slyly foxes-- pending accounts about the furiously special the +682|Supplier#000000682|4bD4f4zKh88YutGs|9|19-577-707-8772|9127.14|eep carefully above the slyly final requests. carefully express foxes nag +683|Supplier#000000683|W0rFJpyes6atCIuwAmktnK|0|10-108-564-6160|2956.02|uests. platelets breach blithely among the furiously regular requests. quickly fin +684|Supplier#000000684|nqw,GGxCoNZ3UOuIa0edX3SdoYKER|19|29-345-334-1955|3810.81|sts are slyly. doggedly final warhorses wake carefully after the deposits. reg +685|Supplier#000000685|JgoYDMLdJeM|12|22-599-473-1489|4297.36|o the furiously final braids. ironic requests sleep among the even foxes. regula +686|Supplier#000000686|LxjyC4i3RxAqWnUF|9|19-818-456-6713|8724.42| requests haggle carefully. silent, ironic accounts along +687|Supplier#000000687|PN0ZGBcv2F7yzeOMZflOAoEnhAUMPocj6sc|20|30-168-842-6668|-624.22|usly. regular theodolites along the careful +688|Supplier#000000688|D fw5ocppmZpYBBIPI718hCihLDZ5KhKX|3|13-855-777-3804|602.75|after the busy platelets serve across the even packages. final pinto bean +689|Supplier#000000689|v8MJCOfDDFgJbxjwgtdKLtlZRKlSRGl|2|12-934-814-6084|8436.92|y final deposits. blithely unusual accounts along +690|Supplier#000000690|nK6Lv WWUh59jE525|19|29-330-952-4018|7448.46|nic pinto beans doubt blithely b +691|Supplier#000000691|XU1STWHllW5I5Rw9X,jsZi7X7M 4|12|22-930-512-3497|4239.95|to beans nag around the careful accounts. ideas integrate: daringly ironic pack +692|Supplier#000000692|K8M3uIAEsKuFGIc43sALPKCDSyKXtc0w VcdS|0|10-727-704-5789|845.01|ly ironic packages. excuses +693|Supplier#000000693|S,mnHfsroFOVieQGdcaY5eod,8Zmji8|8|18-231-996-9225|9956.55|wake quickly around the foxes. +694|Supplier#000000694|20i8TNU3K6H0SEL20|10|20-902-352-7633|5776.60|ounts. regular requests are ca +695|Supplier#000000695|xhSCyzMl iQ|21|31-274-635-2607|-590.99|cial asymptotes across the slyly unusual foxes use slyly furiousl +696|Supplier#000000696|hWvK 9N1EQX0kjEI|0|10-745-572-7198|9114.26|regular packages wake slyly after the carefully silent dependencies. packages dou +697|Supplier#000000697|CnQUnxL9Jk1ew4 kK,DqzwwV34c1KUiu4xFVsG|12|22-673-286-5547|6463.10| furious frets. furiously even accounts should affix furiously blithely final theo +698|Supplier#000000698|ciim3Adyrh1gqQlOsw0YYeF9gIfUM|11|21-373-751-4459|9356.72|y ruthless pinto beans. slyly final pinto bea +699|Supplier#000000699|CplgysgQzKm7KRFKOJe|4|14-247-404-4838|453.28|sts. express accounts boost. silent platelets boost fl +700|Supplier#000000700|K5l3kvvjnRQJJ,|5|15-648-846-4789|4196.26|es haggle quickly. slyly bold ideas serve at the regular attai +701|Supplier#000000701|ijyXEKJPjoVzpXY9g|0|10-713-854-3832|3513.22|ously ironic accounts nag quickly. car +702|Supplier#000000702|1IfvvCrOk6tDle1AjJisjgmZTSrf6Y 2t,Mdv|9|19-354-412-3179|7655.97|about the unusual, bold foxes. quickl +703|Supplier#000000703|QQ Z27PMXZP|13|23-876-543-9729|4921.83|ar patterns sleep about the instructions. p +704|Supplier#000000704|hQvlBqbqqnA5Dgo1BffRBX78tkkRu|19|29-300-896-5991|-845.44|ctions. carefully sly requ +705|Supplier#000000705|9up,Z78TUVPrp2QdumA8fRjL8PG5H6PG|15|25-673-680-4438|571.85|sual packages. carefully ironic reques +706|Supplier#000000706|oXF4XhSiEJMIJouBmMjLZ|11|21-513-570-8754|6043.19|uickly. special, ironic attainments cajole carefully according +707|Supplier#000000707|gIbGXDVlfL3Zl4dmtnAKrnoO|0|10-971-806-9591|2858.06|counts haggle ruthlessly bold deposits. furiously regular instructions wake near the furi +708|Supplier#000000708|qGdOm1xZczyifQ ,Ba2ptq2L7i2K9oWKXu dO9z|20|30-101-252-7593|7364.29|y ironic instructions. bold packages are after +709|Supplier#000000709|D8Mg5T7enR4HOYbpwPgkdDycdI5FpoTnXWUHB|20|30-921-692-7914|8638.35|nal requests. furiously even requests are +710|Supplier#000000710|f19YPvOyb QoYwjKC,oPycpGfieBAcwKJo|3|13-147-519-9896|4876.86|s hang about the accounts. slyl +711|Supplier#000000711|oG9,,CGt6x5c sDr1tzAdzvq1y|19|29-291-385-3264|2462.97|ts. blithely special dependencies i +712|Supplier#000000712|u0ZzFkqHLbJbJ|10|20-433-125-7032|24.49|y express theodolites are busily. bold theodolites cajole carefully furiously ironic pinto bea +713|Supplier#000000713|DBMIf1HiYY8OyRFcbtHpKIz|21|31-890-482-5331|2587.02| accounts serve furiously ironic deposits. ironically pending +714|Supplier#000000714|q1PPTQ0r9QK4PkYS95S yftFXTypAM 2l|1|11-165-805-5563|6077.06|nic excuses run after the final pinto beans. bl +715|Supplier#000000715|feMb9HkfGM8e,4i|14|24-382-559-6937|149.86|lithely quietly express atta +716|Supplier#000000716|OJtq1HiFQczPdQvmhx0gE2exTEdnJr |16|26-413-887-2014|8617.52|requests boost. carefully ironi +717|Supplier#000000717|hhUrgvyxsdTfzGY4OrQSHeZmMNB2L75xk|14|24-797-880-9149|6741.18|ng to the furiously speci +718|Supplier#000000718|W9byXRtqvNdPivnxG76r6|20|30-551-841-7946|8000.05| around the pending, special excuses are against the final instructions. regular deposits +719|Supplier#000000719|nQoXFQ,ztoTyboWFmO,a|18|28-664-720-1497|1922.82|jole about the requests. quickly ironic +720|Supplier#000000720|82 sGqlCVpJgAKKoW6yTkci95tvt|17|27-183-709-8965|7752.13|ckages sleep stealthily above the blithely special deposits. requests sleep furiously above the +721|Supplier#000000721|yF,pgNxRtqb1uql2l21qj|1|11-788-642-3247|4179.15|cajole slyly. requests hind +722|Supplier#000000722|XWycFRsEF4TGhGrCPnM17JRB|2|12-909-341-4605|1895.71|s are carefully. carefully silent somas over the furiously regular dependencies was ironic dugout +723|Supplier#000000723|ZFI9Pb HTy,8e,mY0mqP6ThbN|5|15-714-811-1747|3117.73|ests around the deposits cajole enticingly among the slyly express deposits. quick +724|Supplier#000000724|P92abZ6rWSfO2cm|18|28-471-255-1476|4696.62|ly final accounts use carefully +725|Supplier#000000725|fFk BGhsIcG6|1|11-382-323-5460|9077.74|pinto beans are carefully. blithely regular depos +726|Supplier#000000726|jASHnVdyT7e7Lxf6a|16|26-825-782-3808|8617.63|sual foxes. silent instructions are always across the quickly dogged pinto beans. de +727|Supplier#000000727|kc0Fnr5won8yJhzYC2j4H98m 59CRJTs|2|12-885-980-2162|8518.50|gular pinto beans under the pinto beans haggle around the carefully special pinto bea +728|Supplier#000000728|upr7iaSWGsmneQlVWifcSeJQ4|14|24-789-980-6663|3574.05|as. furiously even deposits are. fluffily ironic pinto beans about the packages +729|Supplier#000000729|pqck2ppy758TQpZCUAjPvlU55K3QjfL7Bi|3|13-627-404-3241|7113.46|haggle furiously among the express accounts. ironic, express warhorses promise. even, expr +730|Supplier#000000730|GQ8t3HK2XoGWSP,Sonc|1|11-468-792-6804|5903.85|kages. furiously ironic accounts are slyly. bold packa +731|Supplier#000000731|dxArCeCKpYV4yBOCZOZb39Y3s7EhIi3d|21|31-306-298-2911|3954.93|s engage carefully alongside of the idly regula +732|Supplier#000000732|3Q117DJd7vC3cBv,L4DAiVqWZNa,nBBoA|17|27-230-428-3838|6432.12|nto beans. carefully ironic dolphins nag reques +733|Supplier#000000733|mUdSdgmayvR|18|28-634-280-5540|5714.85|blithely express packages. final deposits nag above the regular +734|Supplier#000000734|dsoJfURkkt|10|20-428-370-2403|6479.49|ly pending excuses are. even instructions sleep furiously; reque +735|Supplier#000000735|7FqUrdaC732vBX3J7ruv0W4 Jfpx84|17|27-984-128-6691|9895.02|kages. furiously ironic depths unwind permanently slyly regular requests. carefully bold +736|Supplier#000000736|l6i2nMwVuovfKnuVgaSGK2rDy65DlAFLegiL7|3|13-681-806-8650|5700.83|the carefully pending waters wake about the requests. f +737|Supplier#000000737|5fna7sQRrNfLatMkl0Oy,Sps0IWTez|2|12-503-512-3693|1922.80|carefully ironic platelets use across the blithely speci +738|Supplier#000000738|dklvCmHEmlCFTuKU5YNnYAi96v,FMMq|22|32-910-791-4020|7435.07|usual packages use final, even ideas. carefully pending requests integrate carefully regular +739|Supplier#000000739|d7rDQneZCae9E57u3LSq7K|11|21-304-934-6837|-811.26|efully alongside of the slyly f +740|Supplier#000000740|vi82FyqGelGW0G1mpP17eDCBJRgNLvNi |23|33-714-391-9055|3057.29|und the quickly unusual id +741|Supplier#000000741|BLP6zAc29lDLOvSE3 h2|7|17-292-821-2297|824.94|even, unusual instructions b +742|Supplier#000000742|yaX50kwIVnFeY3|0|10-673-629-5928|2697.53|en theodolites are about the blithely unusual requests. bold deposits wake. furiously even packages +743|Supplier#000000743|ccFQShf qHch yPwbryx12DfnIYAp83,F|2|12-841-918-5889|4384.23|e slyly after the quickly final platelets? special, special foxes nag slyl +744|Supplier#000000744|5NKuw5W4mFDMQBbUjUO4k kfokG8yvAe|3|13-573-977-6527|5699.09|ular accounts. blithely ironic th +745|Supplier#000000745|KBaVOy ,RKCWhLiYxW|21|31-469-792-6546|5672.23|thely unusual ideas. pending, final de +746|Supplier#000000746|DI4uPKbEC5 D4LIwwSgGZ8SwqA1hLGJJN6guc|22|32-484-989-2368|5238.76|sly special sentiments-- carefully unusua +747|Supplier#000000747|0XGddxTld5cBDIN4Z30Je siitSCbFC|12|22-543-907-2770|1900.17|dolites haggle closely: theodolites affix after the express, even deposits. even ideas are blithely +748|Supplier#000000748|x3Wq1rbka5LB1UnGMzk0hd5,mWjrLfG49kR|1|11-549-384-3124|1084.18|furiously regular ideas-- express packages sleep quickly quickly e +749|Supplier#000000749|KxSfaofVZcFWnLsjaNszI5GTrlyAW,|5|15-131-224-8530|3839.44|gular pinto beans. blithely even accounts wake blithely accounts. careful +750|Supplier#000000750|uJB curMQwnzz79rXo9v4jy|18|28-361-120-8058|1533.06|y among the blithely regular accounts. regular, ironic instructions +751|Supplier#000000751|20kEocUg39iam9T EzquK P7grgp,QD|5|15-773-726-6594|2094.94|carefully special instructions cajole slow re +752|Supplier#000000752|l cHMtEnodxj3FV|3|13-854-821-4478|7588.27|ages. even, regular packages c +753|Supplier#000000753|Kbxpp9hdpX6bgG,|0|10-667-838-1746|151.10|tructions. pending deposits wake. pending dependencies haggle. regular accounts boost. unusua +754|Supplier#000000754|GLSmwjGddmyMx2D BlOKJm1Ji|17|27-971-371-9417|7425.83|leep. pinto beans haggle according to the unusual, e +755|Supplier#000000755|IRW3Y6qorkh4GBy4gHSpVTF5L|15|25-750-724-4757|9046.17|ding accounts was. carefully express ac +756|Supplier#000000756|ySXGqbQpYbXLoaFMKqIdH5Pai|7|17-726-757-7711|6116.81|out the final, express id +757|Supplier#000000757|PE9,2xp10mYiiKvHbHIVG1KIPLDtomT|8|18-152-957-5174|8209.16|s accounts. unusual instr +758|Supplier#000000758|Dko8jlTeGYKaDg s0o a9|17|27-130-847-7866|7448.00|oldly among the quickly regular platelets. furiously ironic packages around the furiously regula +759|Supplier#000000759|1wnIv4xlR2,zrcb495qI0gcXrJyVPrQjNU |8|18-430-878-7018|7602.04|its nod about the deposits. brave pinto beans lose quickly about the ironic foxes. even, even a +760|Supplier#000000760|ob94rzX66tJ35aKv2jR,inK1|21|31-367-390-9165|486.80|aphs. regular asymptotes wake quickly slyly ironic ideas. si +761|Supplier#000000761|zlSLelQUj2XrvTTFnv7WAcYZGvvMTx882d4|3|13-725-649-4070|6610.51| packages boost doggedly. fluffily pending accou +762|Supplier#000000762|GRVedLFC19uN9o8bNyNZWwzcbDUo2eT|20|30-393-711-8623|939.86|bove the bold packages. blithely final dolphins wake against the +763|Supplier#000000763|rpZRD,h5XXPIOe6bX1KqgwvBPoN|17|27-579-968-4858|9206.66|bold ideas. blithely express theodolites haggle blithe +764|Supplier#000000764|2qcwW0V7q3Ipei1tPW3|0|10-917-495-8225|8465.14|counts nag slyly along the deposits. quickly regular accounts brea +765|Supplier#000000765|RLsvd,9rVYPSoMUCDBVoB9|24|34-103-698-2282|8681.24|accounts grow. ideas cajole slyly. ironic requests haggle slyly e +766|Supplier#000000766|wfQTdIQSA7p5PFFvXNjhO|4|14-284-910-3726|-297.76|ickly along the final, pend +767|Supplier#000000767|bHEuqKKdmCMEKOV|21|31-880-346-2583|9504.89|e slyly carefully special accounts. furiously bold foxes sleep regularly. furiously unusual +768|Supplier#000000768|P,qwP7pGhJVoeq LJI|22|32-493-564-7451|4705.25|ffily unusual foxes sleep carefully according to the special platelets. a +769|Supplier#000000769|ak2320fUkG|6|16-655-591-2134|165.76|ly ironic ideas. quickly ironic platelets hag +770|Supplier#000000770|KNKouHfOJPphqjJXncoGYvv|9|19-372-844-8190|830.15|dolites nag blithely blithely final accounts. fluffily regular +771|Supplier#000000771|lwZ I15rq9kmZXUNhl|19|29-986-304-9006|2221.25|nal foxes eat slyly about the fluffily permanent id +772|Supplier#000000772|GxfKyTzgm 6bVmhZPQ6nUMCx5NSsl0 ATg1WccX|11|21-367-987-9338|7540.44|uietly quick packages! furiously bold pinto beans haggle carefull +773|Supplier#000000773|U0Sh9u896MJve84VFCmc6TLb8RUmg9BzJJBks44|23|33-321-732-9512|-707.02| furiously final sauternes about the carefully special packages could engage slyly +774|Supplier#000000774|XVYeiG4,BopCyYAQwld4l0scarsoe8J0cQ|0|10-311-896-5917|6030.51|sheaves. packages about the slyly express pinto beans thrash according to the +775|Supplier#000000775|tmhWTbbv9lv|2|12-946-153-9942|9751.14|final foxes around the blithely reg +776|Supplier#000000776|nklfFoSkCwf,ooSuF|21|31-317-593-4029|7550.40|es haggle instructions. bravely furious deposits haggle blithely. quickly regular water +777|Supplier#000000777|oJlJ0xr1b9l3t IHmi9|11|21-502-733-8098|1636.48|ly even pinto beans. slyly expre +778|Supplier#000000778|SHE9zl 2BWMYhH25|20|30-653-194-4012|2200.43|tructions along the furiousl +779|Supplier#000000779|iAtd5nxCjii|17|27-104-960-9666|9550.77|ut the permanently silent sauternes. slyly pending dolphins integr +780|Supplier#000000780|,G6UHU26b8dkvwpYiM,|6|16-367-150-9939|5799.04|express theodolites sleep. final, even instructions across the c +781|Supplier#000000781|kim1Maww3pdircDNv6hnVK21cI|2|12-757-769-5008|2501.73|ar, regular instructions. permanent, pending packages sleep blithely among the +782|Supplier#000000782|z5xIc71Rb5CsrmE0kO11P|11|21-940-365-9213|2493.13|s around the ironic requests engage according to the silent packages. attainments sleep about +783|Supplier#000000783|dMpZwZ95xznZWg4acMQW dK8AQMhB|3|13-785-672-8751|958.07|e the blithely ironic accounts. final, final warhorses along the ironic, expre +784|Supplier#000000784|Or3 KncT1AHPPb|0|10-734-420-5738|7284.90|he slyly even accounts. furiously unusual i +785|Supplier#000000785|W VkHBpQyD3qjQjWGpWicOpmILFehmEdWy67kUGY|22|32-297-653-2203|5364.99| packages boost carefully. express ideas along +786|Supplier#000000786|QiKBtsiRdDZ2xGcwZgOSoMaKSH4HQ360,88L|8|18-280-624-2919|406.37|uests. regular warthogs across the blithely express +787|Supplier#000000787|xaSs5H BquWpG7s38xn Rf5X|24|34-278-568-1942|7830.47|ously silent accounts dazzle carefully furiou +788|Supplier#000000788|jL QLbG475Uszs4 2RxBp4oR|20|30-377-394-1108|827.21|bold requests along the quickly special dependencies use outside the +789|Supplier#000000789|LF,j2pxKPgtbDGaj,l47vutF5Vz|13|23-428-566-8444|7874.25|counts. blithely special accounts haggle furiously carefull +790|Supplier#000000790|HSYD9,gCfAwpsgCLKGhf,Z4SH8GSYOc|5|15-189-744-3618|-415.18|iously ironic packages. final accounts boost blithely aft +791|Supplier#000000791|2dFfV7U1kBADWXl,NpgP0|22|32-320-959-1370|4992.15| even foxes alongside of the pending deposits boost foxes. bold, silent +792|Supplier#000000792|vsmDNbNfu2bAX2lAj4OTNaMKF x3pBq0yHYPzmm|1|11-678-517-4073|4128.40| wake fluffily against the doggedly sly pinto beans. final ideas sleep carefully ironic accounts. +793|Supplier#000000793|Z4N2V ERHL ds3jr9F|18|28-379-479-7140|7044.94|y regular packages sleep. requests slee +794|Supplier#000000794|ZUzPptVa1Vq9Xo9Pq8rPENR,0KGFd1Q214Hq3dJ|4|14-851-370-3696|9271.66|s against the unusual packages use about the +795|Supplier#000000795|1ozaCnTPf4sAV7oY6VE6y7RqC,WLUVXi|8|18-772-967-6194|887.34|efully final pinto beans. +796|Supplier#000000796|xre srJq9Ivai94OkW0yhsfrx|11|21-322-901-8359|6452.60|ts nag furiously fluffily even requests-- regular accounts unwind. regular, express pinto beans in +797|Supplier#000000797|3kcPU9j dU i|14|24-356-955-8704|8908.16|press instructions. ironic, even foxes use carefully +798|Supplier#000000798|Q4atQnxS0XRmpP|18|28-182-490-3136|7588.31| regular courts alongside of the requests believe slyly slyly unusual deposits. regul +799|Supplier#000000799|jwFN7ZB3T9sMF|22|32-579-339-1495|765.69|nusual requests. furiously unusual epitaphs integrate. slyly +800|Supplier#000000800|Z4 hpmBjpjBXREqzixsBCIaF|0|10-497-654-8607|7956.80|he bold foxes boost blithely about the blithely final epitaphs. slyly +801|Supplier#000000801|zohVF4 4GHOJpWy9kdytvYwm27mJEBhk|1|11-673-791-6926|976.53|ckly final accounts wake since the even instructions. regular, permanent accounts are against t +802|Supplier#000000802|,6HYXb4uaHITmtMBj4Ak57Pd|19|29-342-882-6463|9453.01|gular frets. permanently special multipliers believe blithely alongs +803|Supplier#000000803|,IXoixqcMluU5OEK7RhD,mDrBE2E3ygs|15|25-347-400-8216|1887.55|uiet ideas. even packages haggle carefully according to the fluffily slow requests. furiously ironi +804|Supplier#000000804|N3B GhiD6nanhYdssmqlpy2XVz5jZH|21|31-830-383-7329|9093.94|osits. regular theodolites are regularly slyly unusu +805|Supplier#000000805|LXWtvxudFJf56Uep17HO,NYC4A4mlr|8|18-407-342-1685|5968.71|ructions haggle. carefully silent foxes must wa +806|Supplier#000000806|mYSUX4mem2|13|23-702-985-4737|5054.15|foxes. blithely special packages are furiously. regular theodolites solve. ironic pinto b +807|Supplier#000000807|ClHvM1nuPUESGg35Ls|14|24-255-894-5069|1077.97|lly. even, pending requests boost furiously furious +808|Supplier#000000808|B3zlGM54ECUk5MgRzKI9f7F bB8|15|25-297-954-4894|9438.28|y even packages. requests sleep quickly fo +809|Supplier#000000809|dPqPaxh,IbS|22|32-172-990-2830|7241.31| accounts. express dolphin +810|Supplier#000000810|RMJoA1yw 1fM|9|19-328-138-9772|9713.42|ithely furiously final dolphins-- furiously ironic warhorses beyond th +811|Supplier#000000811|pLtLc7cdmb|20|30-734-469-7797|558.91|bold ideas sleep against the ideas. silent deposits are furiously even foxes. blithely +812|Supplier#000000812|8qh4tezyScl5bidLAysvutB,,ZI2dn6xP|6|16-585-724-6633|8615.50|y quickly regular deposits? quickly pending packages after the caref +813|Supplier#000000813|6EfZUjqLY8G28PhtbPGfz9FjWIXLx|22|32-887-679-3561|5793.63| silent somas. furiously unusual packages affix blithely along the s +814|Supplier#000000814|GWytN8Vx0IWzB8BByw6thupbonInepu|15|25-147-738-5484|-468.26|accounts. blithely final accounts haggle carefully special instruc +815|Supplier#000000815|3f8XIvP m9v5fv|7|17-984-775-9865|3855.74|ms. final packages use finall +816|Supplier#000000816|uCvvad6NCkXBUkr28t dtq swXPtu|23|33-830-680-6168|361.01|lve furiously according to the final accounts. even accounts on the +817|Supplier#000000817|0GTKh7JybR8sVahPoJT8kbNtDV0TzA79Q|0|10-282-124-6047|4468.89| blithely even requests. blithely ironic deposits wake slyly. ideas haggle! quickly i +818|Supplier#000000818|78Rr rF8zcBGTSud4,5B|16|26-754-547-4185|9594.51|es. carefully final deposits use +819|Supplier#000000819|n1YA v3IWFGmIP tZr|5|15-492-900-7246|4049.06|s use blithely. blithely regular ideas according to the pending theodolites haggle above t +820|Supplier#000000820|QoduMcALdP|15|25-716-340-3140|4604.84|osits. slyly final packages are furiously according to the ironic, pending deposits. ruthl +821|Supplier#000000821|O HVe5AKfowNLnep8qd2brd9fbZm WkJuc9Lli|20|30-472-667-2703|6497.93|old, regular packages about the platelets haggle slyly pending, unusual +822|Supplier#000000822|0NJZiE1bKnpzqT j,0|6|16-795-236-9887|797.90|ly even packages shall cajole up the carefull +823|Supplier#000000823| gC0DrEG5U,v893fp3nj mmXa6rYhJ0tjpJ|21|31-834-127-5277|-723.78|ccounts haggle blithely packages. carefully express pinto beans against the unusual +824|Supplier#000000824|wJnn6YrLnzsQWLOZNdMSBz1utk9EFS6icrvQyy|13|23-197-596-6598|-609.59|o beans are blithely across the bold, fi +825|Supplier#000000825|,9nqq,JWR0ztG0qp4rlDHgtShbP7AViBj|20|30-486-346-1320|4461.68|es haggle since the carefully regular theodolites: bold deposits according +826|Supplier#000000826|n,hapmxkVq19Yy9UQ8BVF00sQD|15|25-731-100-2823|9401.23|sleep furiously. regular deposits wake furio +827|Supplier#000000827|AlFjWDq6jDtaSUKnxn54OwQzt8CPUItYbCGztPQ,|9|19-131-253-5697|515.22|ggle. carefully silent requests lose slyly. final, final foxes among the fluffily iro +828|Supplier#000000828|0B2aPqJ6KTEr2fqxuC7z |21|31-911-715-8972|289.32|ions are carefully along the regular, pending pinto beans. special +829|Supplier#000000829|w247SZbFQvw1Fp4f0JFIfVXmIBfulBxfgUg|2|12-123-147-1171|9542.56|nding packages use fluffily above the blith +830|Supplier#000000830|5DHC2QScT6P6lXgRtHajXOfztB7ddjYH1LLUC3|10|20-415-380-4083|-65.23|ideas wake blithely quickly even notornis: furiously pending theodolites sleep. +831|Supplier#000000831|NkkeNeVsWdw8U SeVBnUX 2GB|15|25-275-692-5827|1536.13|carefully express accounts wake quickly about the quickly silent p +832|Supplier#000000832|SwUNp9Yyt5pe 6i5EYiV3hHU9RWJnd3VzBjsbtvO|15|25-658-573-4042|9747.16|old ideas wake carefully above the slowly regular pack +833|Supplier#000000833|ig2vYxu,8xwEzl0UfA4t5VJ|17|27-470-524-5760|6604.79|. quickly bold packages sleep among the packages. theodolites bo +834|Supplier#000000834|fwX0Z5,PgFaauaEXlVQX6UmHM0RDKS4EXe,Tn3nJ|9|19-419-490-3356|3732.75| express foxes nag slyly after the regular pinto beans. regul +835|Supplier#000000835|a7ZBr9561n7CHzwtrfoZnpNWf71uKtH|14|24-772-959-9240|1348.35|final asymptotes are furiously bold deposits: unusual, even accounts across the blithely +836|Supplier#000000836|KU2O25D5,FXdv|1|11-892-817-2809|-256.13|ke finally even asymptotes. accounts x-ray al +837|Supplier#000000837|717LGrDM2ChnIS91,PE4 ycp4mu4HPdcX|12|22-626-153-5392|5167.00|gular instructions are furiously a +838|Supplier#000000838|Zsa9XTlYna7SUIpK0RQAGYSVum|11|21-409-796-7661|5808.87|xcuses. furiously express deposits wake among the furiously ironic instructi +839|Supplier#000000839|1fSx9Sv6LraqnVP3u|6|16-845-687-7291|2761.59|ess, regular accounts haggle slyly across the carefully +840|Supplier#000000840|iYzUIypKhC0Y|19|29-781-337-5584|2963.09|eep blithely regular dependencies. blithely regular platelets sublate alongside o +841|Supplier#000000841|dvQXS7Wi29wVuSUWsknpHVQWVrJ6cUvB8V|7|17-359-161-6634|1685.95| final accounts unwind furiously among the furiously pending req +842|Supplier#000000842|3D3tmBm8zD3A BxuTWfoKXD|4|14-977-614-8564|8732.97|dolites impress quickly about +843|Supplier#000000843|iguHIr15YUL9RMmH7U3XsDfdyEg1441|18|28-503-987-8146|10.33|ss packages among the pinto beans cajole slyly outside the packages. regular, final +844|Supplier#000000844|COb5r2WsvJ0zf 58tJJLgYvEZHJb74EBdp|24|34-454-417-4967|6538.01| pinto beans. carefully stealthy theodol +845|Supplier#000000845|tgajQJpBFV6PGa9bzWSkW1eSGE3q5NsCMYE|23|33-350-532-8789|3408.47|sual courts. carefully special dependencies nag furiously. deposi +846|Supplier#000000846|C1Cs3zHlceRMxlaPIBprCC76x4LKVdH3QhZ|20|30-283-261-2020|7122.90|thely special deposits was furious +847|Supplier#000000847|wMieciw3 YGegk|15|25-908-575-3915|-382.49|ully express, regular instructions. daringly sp +848|Supplier#000000848|tx44JAuF,Jnw1|3|13-169-466-8402|4404.29|olphins. pending packages are during the regular packages. furiously regular requests haggle c +849|Supplier#000000849|uy a2rQl1Bag,cFo5GRTZigHtqh Gguuj2xtlz|1|11-608-566-4693|1955.97|ideas will have to sleep pinto beans. deposits around the dependencies ha +850|Supplier#000000850|l6KnHycBhdFcz58UReuEe1Jf2R40ZICoQ5Qpjh6f|4|14-161-130-9091|3891.72|e across the regular requests. silent ideas alongside of the carefully even ideas integrate slyl +851|Supplier#000000851|fhhjsCI1s8uC|15|25-692-383-2877|157.21|ffily express instructions. close deposits after the bold instructions nag regular, even asymptot +852|Supplier#000000852|n3zasd04WljXdo9xMjQRkZKrEB|1|11-574-892-3228|213.41|Customer s. even asympRecommends haggl +853|Supplier#000000853|hQuhL6zQSZmVifUzpnKvRLNEfJhShDomdbGC|8|18-286-624-2526|9797.52|iously. bold accounts cajo +854|Supplier#000000854|omM4Df4DWXSTKmenaUUSr|16|26-346-921-7567|6082.22|n requests believe fluffily. carefully special depen +855|Supplier#000000855|ekQwhb9fh5VGIvMBJ m,yT571ICZpI,LEb1e|9|19-105-166-2849|9964.88|ess patterns sublate blithely-- slyly pending requests use carefully about +856|Supplier#000000856|U,GH2ZjlmA78JRbjWhbf7jCgrU7a0Dx|4|14-216-125-2920|2763.95| special packages. theodolites haggle carefully. special packa +857|Supplier#000000857|srpKWldPZrVWm0dKjc7p 8fMKm1fYF|2|12-715-212-6604|9761.92|y final ideas poach across the special dugouts. furiously pending accounts cajole furiously. fin +858|Supplier#000000858|aA2g9NPEljznwqrZp4Fdw1Z|9|19-525-296-9901|1671.59|ependencies boost regular, regular requests. quickl +859|Supplier#000000859|OJ7rr38hbK1BlZSRXKojpIho8QazivUtIh0|16|26-731-166-4296|9296.31|ggle slyly among the express accounts. slyly unusual accounts above the thi +860|Supplier#000000860|C9FacsR,23JNHd8ioSI5qC7FfnR|17|27-547-426-7236|8210.13|ilent, regular ideas. bold, unus +861|Supplier#000000861|vj9yxpOqUdt3HIxfOWbA9|7|17-581-652-1425|1747.35|against the carefully regular requests sleep blithely fluffily ironic packages. +862|Supplier#000000862|JAH3,OdzNzdiWYK2ODrKfLLR2IQ8YVNJcsds|2|12-159-806-3875|6698.84|ously special pinto beans. deposits +863|Supplier#000000863|TsC9OuodnybJhWXq4PFNdEJf9jx2y181N3ilV|21|31-589-608-3508|487.31|ounts. fluffily special platelets along the even pinto beans boost +864|Supplier#000000864|D95VTylwusz7OYesg,|5|15-293-129-4196|4089.61|ites. quickly even ideas wake always express requests. express theodolites are. carefu +865|Supplier#000000865|zYVm4GPPlvV1MysjqDUItehzU9hD0tIaHeg|17|27-993-155-8321|4111.07|ly ironic packages. slyly pendi +866|Supplier#000000866|CosbyBH1bG81zFspjW|24|34-374-244-3932|1768.34|riously regular excuses. quickly close ideas sleep. final requests haggle along th +867|Supplier#000000867|WTM7RpRoZPk5MKGEtE2dsh|11|21-221-554-8461|7476.72|y final requests. blithely final instructions will haggle fluffily. iron +868|Supplier#000000868|dFPwNYsP 9xC|1|11-255-295-8702|6239.02|ar instructions. blithely ironic foxes doubt against the quickly bo +869|Supplier#000000869|xi6g0llBz3O1ECUHCk7p341ThVdavdqf6PM|13|23-269-725-9523|5303.66| regular theodolites thrash slyly about the sl +870|Supplier#000000870|QIgRinpKvCLPG|21|31-675-338-9417|3689.14|ronic accounts. quickly pending pinto beans after the regular asymptotes sleep furiously +871|Supplier#000000871|gTuPG353pz9sxS6iazJuqQtji6xN,Q9qgG2|8|18-566-173-8686|5418.37|ess, ironic platelets boost furio +872|Supplier#000000872|oJQEy8xyrptE|11|21-271-893-1965|6571.13| the pending, even foxes? blithely ironic depe +873|Supplier#000000873|jBfvdFseU7cz315kGbbocXnCwDKW,3iRlyaj3wn0|1|11-253-186-4222|-951.70|pinto beans. platelets serve slyly bold, pendi +874|Supplier#000000874|xsGhP46dDeavM6wnREIi7Q09jfAUTzucwp|16|26-826-579-8300|7755.50|beans. deposits haggle after the blithely express deposi +875|Supplier#000000875|pBjvc 55kMxfQ3gtYUiuy5TNRyd|13|23-165-986-6088|5757.36|ep. furiously final deposits sleep. regular, regular packages affix slyly +876|Supplier#000000876|PYBAM85Nrb2cuXH8VDrX 3TjZbsIAlIQ,,xA|11|21-432-561-3770|5979.92|ly special packages. carefully ironic deposits dazzle furiously acco +877|Supplier#000000877|4yN9i5CbQ8Tw1X5InsMlOjjhGg8MAciTG|4|14-685-851-5424|6489.62|beans. quick packages at the pending dependencies poa +878|Supplier#000000878|cennOpnejXFuwxsxrfoz6U,WN TC7|8|18-462-213-5795|4140.02|gular theodolites wake. blithely bold deposit +879|Supplier#000000879|6DGZ6o7FNRspPhM B1nZiMOAgq9fZT8UHW|17|27-204-329-1068|4269.56|s the ironic, ironic platelets boost carefully bl +880|Supplier#000000880|s7AgxI7139o6arS2SfUX|10|20-178-395-2605|3550.33|s hang always against the pinto beans. blithely spe +881|Supplier#000000881|02RRXg45CBGhuzwpKKz3fi4ewYv|13|23-877-378-2281|4423.06|ounts are according to the express theodolites. silent instructions above the d +882|Supplier#000000882|5op1w94,JerNmOkyPfAVkZEtb7|14|24-437-170-2579|9450.21|ly final requests haggle furiously final, regula +883|Supplier#000000883|5ppzWDz6xcMOO09LkrAOvHzFEMfP3CIpndr|18|28-614-756-7513|9746.01|hely final excuses sleep quickly. slyly pending instructions hang +884|Supplier#000000884|bmhEShejaS|3|13-498-258-4793|9223.93|requests. furiously pending accounts haggle furiously. blithely regular ideas wake along t +885|Supplier#000000885|aJUXiGC6qSAWr0Dl0VBahtF|7|17-578-639-8695|1736.47| furiously. carefully pending pin +886|Supplier#000000886|R52IgT6b0yBuU r8,dNRZVWRY|1|11-329-720-1904|-158.08|ts during the blithely silent packages c +887|Supplier#000000887|urEaTejH5POADP2ARrf|3|13-738-297-6117|3113.73|s. regular realms haggle. special, unusual accounts wake furiously. bold pearls play c +888|Supplier#000000888|JA,f8nt64wdZ4XkiHCYHC0r2FJ|24|34-606-153-4636|3420.34|deas wake blithely. regular, special id +889|Supplier#000000889|saKBdGnsGS9ccCMGJ5NFoKwZ7HkS7|20|30-566-872-3482|8570.93| the furiously final requests +890|Supplier#000000890|yY7XhfdJe4ewh8R, xHR06QABT|11|21-196-765-4250|4685.09|ly unusual asymptotes cajole along the +891|Supplier#000000891|cv64gZAB3Ax5XblZ19gNA zOHb9q2nGjtvUzLm9P|8|18-541-281-5118|2284.88|deposits. slyly final accounts are fluffily slyly +892|Supplier#000000892|j6prA4M3sX9a9xHem3HOZpYy|8|18-893-665-3629|9993.46|mong the regular instructions. regular, regular dependen +893|Supplier#000000893|WxOTCcoe RFwKWyZUCURPNAumww1nW,EYcrVjrj|22|32-328-447-9531|-823.97|ully pending pinto beans affix quickly after the decoys. sl +894|Supplier#000000894|T,9KqHZzFlFVvesdyzvzs9FHOQZjLk|9|19-875-711-4227|9490.22|ss the furiously special packa +895|Supplier#000000895|Tm5QKYFUhtY|2|12-826-730-8247|246.80|y final foxes cajole blithely. packages over the blithely ironic accounts haggle silent, regular dep +896|Supplier#000000896|yvNZycuQYm9d9A8v1m|7|17-790-100-9143|9880.72| regular deposits. carefully unusual accounts haggle ironic, +897|Supplier#000000897|9HoSSwrIPM8ge69XLD81Br993krGbn9aeUW4U|10|20-272-778-2639|7373.28| boost. bold accounts nag furiously +898|Supplier#000000898|Uud3qAUC91Cy,c|4|14-247-832-2299|5737.18|print carefully. blithely regular deposits after the deposits cajole against the sp +899|Supplier#000000899|oLlkiVghtro IwzcwFuzwMCG94rRpux|11|21-980-994-3905|7741.42|equests wake quickly special, express accounts. courts promi +900|Supplier#000000900|,6RXmcRyA48c0yvZ2I|5|15-926-534-2005|165.26|counts cajole carefully pending foxes. bold packages mold carefully unusual +901|Supplier#000000901|dVN377SgJQURQd8,XtVF9|8|18-664-532-4405|3465.20| sly foxes are. special requests x-ray about the slyly unusual foxes. furio +902|Supplier#000000902|VrxG9VHAp45UMWrL|22|32-382-410-6632|3660.22|are slyly unusual excuses. pending, special +903|Supplier#000000903|fQVbA9,L6tB9iFrCfk4Yt1dwT0kRWg9DV|22|32-277-492-3117|3238.01| sometimes across the furiously express accounts. unusual accou +904|Supplier#000000904|Wev4Rig5BkWdQIsATpN7W5lG5jh4LQ ,pMxD|15|25-960-333-1191|2152.23|thogs snooze blithely fluffily bold pinto b +905|Supplier#000000905|WAGJHr1OUm95U5|17|27-266-689-2728|2415.66|usly regular deposits. foxes boost blithely ironic theodolit +906|Supplier#000000906|KwvAh8P9RcDPjbx9Qv2xZeWPmkCmK hY|2|12-926-664-9785|7888.41|ructions. slyly final req +907|Supplier#000000907|Y79rRfd5UhgXi6Ahj9ooM0vNHts|12|22-595-604-3254|6558.92|t the instructions. bold, unusual pinto beans above the regular, unusual foxes wake blithely regu +908|Supplier#000000908|05YocPlDfIe SFz7r5BeVAgqOx8i|4|14-669-206-5538|2844.11|s the slyly unusual foxes. furiously +909|Supplier#000000909|BXuLybzUeFLI0GJqMG8xewTuKFqk8n|11|21-989-597-5142|4012.42|ss requests. even packages haggle furiously. +910|Supplier#000000910|0X S 2E55,maqch|5|15-960-448-6633|4763.20|arefully unusual deposits. +911|Supplier#000000911|TpZMQSDVVmgKZX9 wB,HY|11|21-748-770-4721|6026.09|he dependencies. furiously special deposits cajole slyly. theodolites use fluffil +912|Supplier#000000912|ppF7DX,JePrdoo9qYFYwTOwszgUjHk|8|18-633-593-4048|1492.02|the ironic Tiresias. requests above the slyly even deposits affix abo +913|Supplier#000000913|c78mMYZkHE7ktVSoB9D|24|34-601-419-1634|5266.72|s sleep bold, regular accounts. ironic packages integrate +914|Supplier#000000914|li7dM9CrPF213,Jkh3MJRSRhjSB,wRMuOvidQg8u|14|24-682-308-9029|9767.75|ajole. bold theodolites above the quickly ironic frets are quickly along the fur +915|Supplier#000000915|hzB2437Op7JLYX73d3,qU2|18|28-191-772-5459|687.45|ffily. slyly pending pinto beans haggle furiously regular accounts. furiously regular asymp +916|Supplier#000000916|tD 9oW5VNUWTBQCpsISJO2TZCwFzKLdqIZoTWV6|11|21-185-427-4872|1852.85|e packages haggle carefully along the furiously ironic dugouts. unusual frets impres +917|Supplier#000000917|tMr5motk0IFyIXJDwCr98Q O5|22|32-754-782-6474|8877.42|r dugouts? final, ironic packages breach furiously f +918|Supplier#000000918|e0sB7xAU3,cWF7pzXrpIbATUNydCUZup|20|30-303-831-1662|7893.58|ependencies wake carefull +919|Supplier#000000919|xg60CQmqGaVavmevvCjOSGXC 3YuMRVb|16|26-379-721-3359|5428.44|, regular requests: furiously even deposits wake blithely ironic packages. furiously even +920|Supplier#000000920|Ix0QnIqftxMwHW5KHeB,xB|20|30-713-464-9920|-111.84|leep carefully among the e +921|Supplier#000000921|2dsK093unFO|2|12-670-146-9689|-686.97|ounts. blithely final requests wake blithely. regular instructions cajole among th +922|Supplier#000000922|V2KIQXPxtYnOkul|13|23-456-977-9276|2015.59|yly even packages affix quickly! quickly pending foxes haggle at the final, bold deposits. blit +923|Supplier#000000923|aUJaK ezwGVA43Mo0XF|10|20-376-561-9214|5057.87|y. furiously express courts sleep. +924|Supplier#000000924|13INVXLNjpU9eTsoc4dLeid|14|24-768-719-6154|8562.82| shall have to integrate blithely alongside of the fluffily even epitaphs. quickly unusual +925|Supplier#000000925|x3n4pg,q28EckYO,613G7seoAmTPSX0jTvDvM2U|19|29-398-723-8226|406.59|regular packages can haggle acro +926|Supplier#000000926|SEEq DJHLi I6|10|20-500-435-2716|505.92| the furiously ironic dinos. closely ironic instructions al +927|Supplier#000000927|Ype0QDb17eJbg7l35PFzJso|9|19-185-526-3201|8997.88|ily final courts sleep alongside of the ruthlessly regular escapa +928|Supplier#000000928|VL,J8Fq0GI0BnVTaTU9Dcp9Z|18|28-382-849-1505|8512.48|equests are. slyly specia +929|Supplier#000000929|XYQyy9rraHvHMCBQcoGnAvfw0iGG4jOCMENI|20|30-190-675-2042|1235.72|ully according to the doggedly even theodolites. f +930|Supplier#000000930|jYRHnCNnk55 CODbFLqby,ewwOQa1M|10|20-435-373-1909|9740.48|ly unusual asymptotes at the fluffily ironic requests hinder slyly regular +931|Supplier#000000931|CqslHrffpOBxqMDxiGH8nz7scX,i3HmUhNlwBBU6|8|18-174-741-5563|4398.36|t carefully. express accounts sleep. ironic, final theodolites haggle regul +932|Supplier#000000932|2Ke5SDwuwZ1y7H2QROIfgQ1d7|10|20-315-146-6687|1278.74|counts wake carefully across the pendi +933|Supplier#000000933|TrYn5zjv6nrT47EwbXi1S,IU|7|17-446-406-8093|6756.59|ully pending platelets. quickly ironic realms cajole slyly across the even ex +934|Supplier#000000934|2o3Fav4osE|9|19-497-408-2402|3103.34|t the fluffily ironic platelets. foxes use. blithely pending p +935|Supplier#000000935|ij98czM 2KzWe7dDTOxB8sq0UfCdvrX|3|13-437-885-9309|4734.47|ly regular pinto beans wake blithely bold pinto beans! warthogs between the +936|Supplier#000000936|CuIXj6RYaHGQ5SOkmhu8ZDRt5IU|17|27-555-580-3995|7304.30|leep. final sheaves affix across the requests. carefully express ideas ar +937|Supplier#000000937|UBfhiW HpJzqh9uTnhXkOqjRvP1vAIWokSeR5|15|25-410-699-7522|1463.21|lyly regular decoys lose packages-- quickly ironic foxes across the express accounts bo +938|Supplier#000000938|3xcs3BuTqx8b|4|14-704-203-8596|5204.43| express platelets integrate slyly above the ca +939|Supplier#000000939|mWBKbdzDn3yJNpOT8p|23|33-487-125-3117|7815.06|efully. final requests after the unusual requests wake fluffily after the furiously r +940|Supplier#000000940|QqKPZBeHgcIKDeOfT6J8sRlg4|2|12-972-343-8810|5789.96|ccounts. quickly final patterns mold +941|Supplier#000000941|gqG2XEnVlzUhjjfQGYGlwk,jcaNsplI8Rleg|21|31-412-752-5573|3846.91|ronic theodolites. final, unusual +942|Supplier#000000942|VkukmyN0Dq3NkC1RMw2ZBk,I5icQfLFFG|24|34-943-753-9952|6074.75| deposits haggle. regular packages unwind fluf +943|Supplier#000000943|AaeNFJbUAF8MOb5VKA7wXB6|16|26-877-341-9002|5339.25|uffily unusual packages wake bl +944|Supplier#000000944|tUVVFs351nHm|13|23-452-536-7876|7776.86|pinto beans. quickly express requests haggle +945|Supplier#000000945|y8LENmYfvNpYOnHG4XdxLQGqjOPJJ4c0CacGxu8|1|11-785-307-6941|1706.26|quests wake slyly quickly ironic deposits. instructions wake +946|Supplier#000000946|RpFjkZmA ScvLe|15|25-522-937-5559|9093.75|shall have to use slyly. carefully ironic ideas alon +947|Supplier#000000947|6xS,tBAgcKGW,nXNhfm2Hv26uYicU3|18|28-277-111-4291|2699.78|ronic ideas. slyly final dolphins wake furiously after the +948|Supplier#000000948|LvcPHBbzYZKySxlda,0McYfaV2bb poGXMF|21|31-562-389-2753|9219.26|grate slyly after the quickly even accounts. bold accounts haggle carefully. quick, b +949|Supplier#000000949|a,UE,6nRVl2fCphkOoetR1ajIzAEJ1Aa1G1HV|23|33-332-697-2768|91.39|pinto beans. carefully express requests hagg +950|Supplier#000000950|MukfcGGpbbRXp5v52Rx43QpPjU8RFB|1|11-888-171-3390|4992.53| the furiously daring dependencies wake blithely blithely regular braids. ironic ac +951|Supplier#000000951|Tuh3kFB,zCuI,jtPmV,IMcXQF|2|12-561-627-9752|-511.17|eans. quickly fluffy accounts are quickly about the ironic +952|Supplier#000000952|n8W6MbJdih Ckh6wDvYJz84ZmabvK4yQDz|22|32-276-558-4960|8621.52|cajole permanently? carefully slow deposits cajole quickly. regular +953|Supplier#000000953|wTTb0ilU6Nba1VLsHj6k0jUt4TFFM6rvtXszzA |21|31-642-490-3022|7916.56|kages are carefully platelets. blithely enticing platelets c +954|Supplier#000000954|P3O5p UFz1QsLmZX|6|16-537-341-8517|6721.70|ect blithely blithely final acco +955|Supplier#000000955|7OFLXDHjSgGrFlHTg8VHFS4glUuN|17|27-839-781-6125|-408.45|ave instructions haggle. regular instructions past the theodolites are slyly depos +956|Supplier#000000956|dmmnYeCuIZB7b2pWTOQ9zrAdi6zxwIrj4aT446L|18|28-741-846-4826|8068.26|, regular accounts use against the furiously express ideas. furiously +957|Supplier#000000957|mSpFa,4jJ5R40k10YOvGEtl4KYjo|23|33-616-674-6155|4324.51|hily after the fluffily regular dependencies. deposits nag regular, silent accounts. i +958|Supplier#000000958|uAjh0zBiJ0d|8|18-553-836-9296|3011.31|ress pinto beans cajole carefully among the quickly special requests. fluffily even dep +959|Supplier#000000959|8grA EHBnwOZhO|7|17-108-642-3106|9032.15|nding dependencies nag furiou +960|Supplier#000000960|yk1dgGaQlbTN1YhnJjyM3ULEDDf|12|22-811-163-5363|1480.82|onic theodolites wake carefully. ironic packages use carefully. ironic +961|Supplier#000000961|jlfkD00x6r0M34ctcSTY3cABv4yWKcjvHV|15|25-911-416-1546|4139.88|luffily bold packages wake ste +962|Supplier#000000962|0udWpU30ecw3XMLiEVhaM7I,BhufyzF4i|18|28-105-675-7555|1898.39|ent deposits are furiously slyly ironic es +963|Supplier#000000963|s3WbU6w31FgnuZVtwGnH6PkyZFg|11|21-395-611-8793|4152.04|ily quiet accounts! blithe +964|Supplier#000000964|JpH9YUQjGXD1GChWcPj9LEGMN8xwZkCzpdG8HlNb|7|17-693-102-9498|8411.78| instructions; fluffily ironic pinto beans across the unus +965|Supplier#000000965|aPiA00HXK1,L2FmArcXVT|7|17-117-423-8603|2843.80|ut the express packages. ironic sentiments are qui +966|Supplier#000000966|FRlJWy32I6TsERrGDq,GS7|4|14-681-361-1636|9657.79|beans-- fluffily unusual deposits x-r +967|Supplier#000000967|uPDH,GMFjz|4|14-583-250-9472|502.38| across the quickly regular pinto beans are furiously brave accounts +968|Supplier#000000968|6idVVWn8RbFoZgPeyVJlQOJ|4|14-431-296-9521|4487.96|final accounts. slyly regular deposits wake fluffily after the +969|Supplier#000000969|thRdVx7vCajVFs7gsK8VKxzydPiHvIKK,DtR|21|31-171-204-7902|162.06|ounts nag slyly across the furiously +970|Supplier#000000970|FD,NVDvbAAT7rI6BdKI2rTo9UqH8AghW1e8DSJ|2|12-826-418-6561|4643.76|cording to the regular, ironic depo +971|Supplier#000000971|23XaUVLYuC3tQIPHCuLLgM5UawL|3|13-380-957-8529|709.58|ly final pinto beans among the furiously regular theodolites caj +972|Supplier#000000972|MkZSNXPZf9g8ZW3ez TU, s6S9aPVY|12|22-291-368-8958|-203.99|ing pinto beans integrate. pending +973|Supplier#000000973|5 nhBZ 03rG6EcOEDkZXvt|21|31-385-469-4031|1548.60|al ideas cajole quickly ironic packages. carefully unusual theodolites detect. unusual packa +974|Supplier#000000974|xIscm3sM7v5hU7NioMfSJ9tLeIBvSm3vGc|16|26-370-235-3418|-778.92|x furiously slyly regular +975|Supplier#000000975|,AC e,tBpNwKb5xMUzeohxlRn, hdZJo73gFQF8y|3|13-892-333-9275|7577.42| slyly express deposits. pending asymptotes could have to use furiously. fluff +976|Supplier#000000976|MVpCgFTl7sGge4cFxVXD|24|34-998-900-4911|4744.07|t the pending dependencies sleep blithely about the blithely pending acco +977|Supplier#000000977|Kuud1x4l,UNEkRAQjCEsu|20|30-938-867-9723|3633.55|lithely ironic requests sleep enticingly ironic foxes. deposits along the slyly pending dolphi +978|Supplier#000000978|XzhDlm7Mr3RyWZL7PV6ush|16|26-135-110-8202|6104.45|ly ironic requests. carefully bold ideas haggle quick +979|Supplier#000000979|cdvHjrKZR7iDlmSWU2a|10|20-151-688-1408|9538.15|ckages cajole quietly carefully regular in +980|Supplier#000000980|jfgiJfywBW88ZEYM 5V|13|23-105-829-3910|2783.33|xcuses. unusual, special accounts integrate furio +981|Supplier#000000981|uf24XV3FD7J0BY5FQ29Nbco8A|19|29-161-734-6046|5343.95|inal packages sleep along the accounts. fluffily special pains wake fluffily. blithely bold requests +982|Supplier#000000982|2GJow4mz8ZkIPUSibA0NZ3OyR5TkfHx0|10|20-884-330-2979|9763.28|deas cajole carefully furiously regula +983|Supplier#000000983|XOYb xohl2j0U7wTTUaT4F6DShKfH4Hv3p,hnP |0|10-384-209-1825|2576.28|onic requests. slyly unusual ideas wake carefully final depo +984|Supplier#000000984|6H6qqye iYbYzCmwWhj|21|31-519-879-5266|1444.79|iously except the blithely unusual packages. c +985|Supplier#000000985|kzI8mk3jN9F67EStJ 8dlpx 6GwZYwzXPFOKJ5R|1|11-131-656-2612|3524.10|ut the furiously final deposits integrate according to th +986|Supplier#000000986|tKoJtnykz0R39BWTgglt0rZxT|22|32-342-471-2481|3516.69|jole enticingly: regular foxes among the regular deposits shou +987|Supplier#000000987|DAWJ1lDhybbSO3mngqD28aX|18|28-375-179-1732|-40.30|uriously unusual courts. slyly unus +988|Supplier#000000988|dFt73JWMYsSxR3 UQN K3FAz|0|10-630-928-4130|2536.81| according to the ironic packages. +989|Supplier#000000989|e5uX8AJF,,zRIIDgJc YMB59ITz4v|1|11-895-219-9405|9098.64|t the silent, final dependencies use busily above the reg +990|Supplier#000000990|DeOjGX,4Ns1|2|12-647-684-5389|7985.78|y ironic packages sleep fluffily despite the grouches-- bold, special accounts nag along the carefu +991|Supplier#000000991|Bh4Danx VvUpMce x42|16|26-793-462-2874|4026.14|foxes are slyly above the furiously express t +992|Supplier#000000992|iZPAlGecV0uUsxMikQG7s|2|12-663-356-1288|4379.45|silent packages. quickly regular requests against the carefully unusual theodolites affix fu +993|Supplier#000000993|z2NwUJ TPfd9MP8K3Blp1prYQ116 |2|12-316-384-2073|2336.52| asymptotes haggle slowly above the +994|Supplier#000000994|0qF9I2cfv48Cu|4|14-183-331-6019|8855.24|sits boost blithely final instructions. ironic m +995|Supplier#000000995|CgVUX8DtNbtug2M,N|18|28-180-818-2912|9025.90|s nag. furiously even theodolites cajole. +996|Supplier#000000996|Wx4dQwOAwWjfSCGupfrM|7|17-447-811-3282|6329.90| ironic forges cajole blithely agai +997|Supplier#000000997|7eUWMrOCKCp2JYas6P4mL93eaWIOtKKWtTX|3|13-221-322-7971|3659.56|y regular excuses boost slyly furiously final deposits. evenly fi +998|Supplier#000000998|lgaoC,43IUbHf3Ar5odS8wQKp|15|25-430-605-1180|3282.62|hs against the unusual accounts haggle r +999|Supplier#000000999|XIA9uPu,fDZTOC,ItOGKYNXnoTvCuULtzmnSk|2|12-991-892-1050|3898.69| ironic requests snooze? unusual depths alongside of the furiously +1000|Supplier#000001000|sep4GQHrXe|17|27-971-649-2792|7307.62|press deposits boost thinly quickly unusual instructions. unusual forges haggle ruthlessly. packa diff --git a/src/test/regress/expected/.gitignore b/src/test/regress/expected/.gitignore new file mode 100644 index 000000000..3099ad00d --- /dev/null +++ b/src/test/regress/expected/.gitignore @@ -0,0 +1,17 @@ +/multi_agg_distinct.out +/multi_agg_type_conversion.out +/multi_alter_table_statements.out +/multi_alter_table_statements_0.out +/multi_append_table_to_shard.out +/multi_create_schema.out +/multi_fdw_large_shardid.out +/multi_fdw_stage_data.out +/multi_large_shardid.out +/multi_master_delete_protocol.out +/multi_outer_join.out +/multi_stage_data.out +/multi_stage_large_records.out +/multi_stage_more_data.out +/multi_subquery.out +/multi_subquery_0.out +/worker_copy.out diff --git a/src/test/regress/expected/multi_agg_approximate_distinct.out b/src/test/regress/expected/multi_agg_approximate_distinct.out new file mode 100644 index 000000000..13f4fcdf5 --- /dev/null +++ b/src/test/regress/expected/multi_agg_approximate_distinct.out @@ -0,0 +1,130 @@ +-- +-- MULTI_AGG_APPROXIMATE_DISTINCT +-- +-- Try to execute count(distinct) when approximate distincts aren't enabled +SELECT count(distinct l_orderkey) FROM lineitem; +ERROR: cannot compute aggregate (distinct) +DETAIL: table partitioning is unsuitable for aggregate (distinct) +HINT: You can load the hll extension from contrib packages and enable distinct approximations. +-- Check approximate count(distinct) at different precisions / error rates +SET citusdb.count_distinct_error_rate = 0.1; +SELECT count(distinct l_orderkey) FROM lineitem; + count +------- + 2612 +(1 row) + +SET citusdb.count_distinct_error_rate = 0.01; +SELECT count(distinct l_orderkey) FROM lineitem; + count +------- + 2967 +(1 row) + +-- Check approximate count(distinct) for different data types +SELECT count(distinct l_partkey) FROM lineitem; + count +------- + 11654 +(1 row) + +SELECT count(distinct l_extendedprice) FROM lineitem; + count +------- + 11691 +(1 row) + +SELECT count(distinct l_shipdate) FROM lineitem; + count +------- + 2483 +(1 row) + +SELECT count(distinct l_comment) FROM lineitem; + count +------- + 11788 +(1 row) + +-- Check that we can execute approximate count(distinct) on complex expressions +SELECT count(distinct (l_orderkey * 2 + 1)) FROM lineitem; + count +------- + 2980 +(1 row) + +SELECT count(distinct extract(month from l_shipdate)) AS my_month FROM lineitem; + my_month +---------- + 12 +(1 row) + +SELECT count(distinct l_partkey) / count(distinct l_orderkey) FROM lineitem; + ?column? +---------- + 3 +(1 row) + +-- Check that we can execute approximate count(distinct) on select queries that +-- contain different filter, join, sort and limit clauses +SELECT count(distinct l_orderkey) FROM lineitem + WHERE octet_length(l_comment) + octet_length('randomtext'::text) > 40; + count +------- + 2355 +(1 row) + +SELECT count(DISTINCT l_orderkey) FROM lineitem, orders + WHERE l_orderkey = o_orderkey AND l_quantity < 5; + count +------- + 835 +(1 row) + +SELECT count(DISTINCT l_orderkey) as distinct_order_count, l_quantity FROM lineitem + WHERE l_quantity < 32.0 + GROUP BY l_quantity + ORDER BY distinct_order_count ASC, l_quantity ASC + LIMIT 10; + distinct_order_count | l_quantity +----------------------+------------ + 210 | 29.00 + 216 | 13.00 + 217 | 16.00 + 219 | 3.00 + 220 | 18.00 + 222 | 14.00 + 223 | 7.00 + 223 | 17.00 + 223 | 26.00 + 223 | 31.00 +(10 rows) + +-- If we have an order by on count(distinct) that we intend to push down to +-- worker nodes, we need to error out. Otherwise, we are fine. +SET citusdb.limit_clause_row_fetch_count = 1000; +SELECT l_returnflag, count(DISTINCT l_shipdate) as count_distinct, count(*) as total + FROM lineitem + GROUP BY l_returnflag + ORDER BY count_distinct + LIMIT 10; +ERROR: cannot approximate count(distinct) and order by it +HINT: You might need to disable approximations for either count(distinct) or limit through configuration. +SELECT l_returnflag, count(DISTINCT l_shipdate) as count_distinct, count(*) as total + FROM lineitem + GROUP BY l_returnflag + ORDER BY total + LIMIT 10; + l_returnflag | count_distinct | total +--------------+----------------+------- + R | 1103 | 2901 + A | 1108 | 2944 + N | 1265 | 6155 +(3 rows) + +-- Check that we can revert config and disable count(distinct) approximations +SET citusdb.count_distinct_error_rate = 0.0; +SELECT count(distinct l_orderkey) FROM lineitem; +ERROR: cannot compute aggregate (distinct) +DETAIL: table partitioning is unsuitable for aggregate (distinct) +HINT: You can load the hll extension from contrib packages and enable distinct approximations. diff --git a/src/test/regress/expected/multi_array_agg.out b/src/test/regress/expected/multi_array_agg.out new file mode 100644 index 000000000..9a1d0b00c --- /dev/null +++ b/src/test/regress/expected/multi_array_agg.out @@ -0,0 +1,141 @@ +-- +-- MULTI_ARRAY_AGG +-- +-- Check multi_cat_agg() aggregate which is used to implement array_agg() +SELECT array_cat_agg(i) FROM (VALUES (ARRAY[1,2]), (NULL), (ARRAY[3,4])) AS t(i); + array_cat_agg +--------------- + {1,2,3,4} +(1 row) + +-- Check that we don't support distinct and order by with array_agg() +SELECT array_agg(distinct l_orderkey) FROM lineitem; +ERROR: array_agg (distinct) is unsupported +SELECT array_agg(l_orderkey ORDER BY l_partkey) FROM lineitem; +ERROR: array_agg with order by is unsupported +SELECT array_agg(distinct l_orderkey ORDER BY l_orderkey) FROM lineitem; +ERROR: array_agg with order by is unsupported +-- Check array_agg() for different data types and LIMIT clauses +SELECT array_agg(l_partkey) FROM lineitem GROUP BY l_orderkey + ORDER BY l_orderkey LIMIT 10; + array_agg +-------------------------------------------------- + {155190,67310,63700,2132,24027,15635} + {106170} + {4297,19036,128449,29380,183095,62143} + {88035} + {108570,123927,37531} + {139636} + {182052,145243,94780,163073,151894,79251,157238} + {82704,197921,44161,2743,85811,11615} + {61336,60519,137469,33918} + {88362,89414,169544} +(10 rows) + +SELECT array_agg(l_extendedprice) FROM lineitem GROUP BY l_orderkey + ORDER BY l_orderkey LIMIT 10; + array_agg +----------------------------------------------------------------- + {21168.23,45983.16,13309.60,28955.64,22824.48,49620.16} + {44694.46} + {54058.05,46796.47,39890.88,2618.76,32986.52,28733.64} + {30690.90} + {23678.55,50723.92,73426.50} + {61998.31} + {13608.60,11594.16,81639.88,31809.96,73943.82,43058.75,6476.15} + {47227.60,64605.44,2210.32,6582.96,79059.64,9159.66} + {40217.23,47344.32,7532.30,75928.31} + {17554.68,30875.02,9681.24} +(10 rows) + +SELECT array_agg(l_shipdate) FROM lineitem GROUP BY l_orderkey + ORDER BY l_orderkey LIMIT 10; + array_agg +-------------------------------------------------------------------------------- + {03-13-1996,04-12-1996,01-29-1996,04-21-1996,03-30-1996,01-30-1996} + {01-28-1997} + {02-02-1994,11-09-1993,01-16-1994,12-04-1993,12-14-1993,10-29-1993} + {01-10-1996} + {10-31-1994,10-16-1994,08-08-1994} + {04-27-1992} + {05-07-1996,02-01-1996,01-15-1996,03-21-1996,02-11-1996,01-16-1996,02-10-1996} + {10-23-1995,08-14-1995,08-07-1995,08-04-1995,08-28-1995,07-21-1995} + {10-29-1993,12-09-1993,12-09-1993,11-09-1993} + {10-23-1998,10-09-1998,10-30-1998} +(10 rows) + +SELECT array_agg(l_shipmode) FROM lineitem GROUP BY l_orderkey + ORDER BY l_orderkey LIMIT 10; + array_agg +---------------------------------------------------------------------------------------------- + {"TRUCK ","MAIL ","REG AIR ","AIR ","FOB ","MAIL "} + {"RAIL "} + {"AIR ","RAIL ","SHIP ","TRUCK ","FOB ","RAIL "} + {"REG AIR "} + {"AIR ","FOB ","AIR "} + {"TRUCK "} + {"FOB ","SHIP ","MAIL ","FOB ","TRUCK ","FOB ","FOB "} + {"TRUCK ","AIR ","AIR ","REG AIR ","AIR ","RAIL "} + {"TRUCK ","MAIL ","AIR ","MAIL "} + {"REG AIR ","FOB ","FOB "} +(10 rows) + +-- Check that we can execute array_agg() within other functions +SELECT array_length(array_agg(l_orderkey), 1) FROM lineitem; + array_length +-------------- + 12000 +(1 row) + +-- Check that we can execute array_agg() on select queries that hit multiple +-- shards and contain different aggregates, filter clauses and other complex +-- expressions. Note that the l_orderkey ranges are such that the matching rows +-- lie in different shards. +SELECT l_quantity, count(*), avg(l_extendedprice), array_agg(l_orderkey) FROM lineitem + WHERE l_quantity < 5 AND l_orderkey > 5500 AND l_orderkey < 9500 + GROUP BY l_quantity ORDER BY l_quantity; + l_quantity | count | avg | array_agg +------------+-------+-----------------------+-------------------------------------------------------------------------------------------------- + 1.00 | 17 | 1477.1258823529411765 | {5543,5633,5634,5698,5766,5856,5857,5986,8997,9026,9158,9184,9220,9222,9348,9383,9476} + 2.00 | 19 | 3078.4242105263157895 | {5506,5540,5573,5669,5703,5730,5798,5831,5893,5920,5923,9030,9058,9123,9124,9188,9344,9441,9476} + 3.00 | 14 | 4714.0392857142857143 | {5509,5543,5605,5606,5827,9124,9157,9184,9223,9254,9349,9414,9475,9477} + 4.00 | 19 | 5929.7136842105263158 | {5504,5507,5508,5511,5538,5764,5766,5826,5829,5862,5959,5985,9091,9120,9281,9347,9382,9440,9473} +(4 rows) + +SELECT l_quantity, array_agg(extract (month FROM o_orderdate)) AS my_month + FROM lineitem, orders WHERE l_orderkey = o_orderkey AND l_quantity < 5 + AND l_orderkey > 5500 AND l_orderkey < 9500 GROUP BY l_quantity ORDER BY l_quantity; + l_quantity | my_month +------------+------------------------------------------------ + 1.00 | {9,5,7,5,9,11,11,4,7,7,4,7,4,2,6,3,5} + 2.00 | {11,10,8,5,5,12,3,11,7,11,5,7,6,6,10,1,12,6,5} + 3.00 | {4,9,8,11,7,10,6,7,8,5,8,9,11,3} + 4.00 | {1,5,6,11,12,10,9,6,1,2,5,1,11,6,2,8,2,6,10} +(4 rows) + +SELECT l_quantity, array_agg(l_orderkey * 2 + 1) FROM lineitem WHERE l_quantity < 5 + AND octet_length(l_comment) + octet_length('randomtext'::text) > 40 + AND l_orderkey > 5500 AND l_orderkey < 9500 GROUP BY l_quantity ORDER BY l_quantity; + l_quantity | array_agg +------------+--------------------------------------------- + 1.00 | {11269,11397,11713,11715,11973,18317,18445} + 2.00 | {11847,18061,18247,18953} + 3.00 | {18249,18315,18699,18951,18955} + 4.00 | {11653,11659,18241,18765} +(4 rows) + +-- Check that we can execute array_agg() with an expression containing NULL values +SELECT array_agg(case when l_quantity > 20 then l_quantity else NULL end) + FROM lineitem WHERE l_orderkey < 10; + array_agg +-------------------------------------------------------------------------------------------------------------------------------------------------- + {NULL,36.00,NULL,28.00,24.00,32.00,38.00,45.00,49.00,27.00,NULL,28.00,26.00,30.00,NULL,26.00,50.00,37.00,NULL,NULL,46.00,28.00,38.00,35.00,NULL} +(1 row) + +-- Check that we return NULL in case there are no input rows to array_agg() +SELECT array_agg(l_orderkey) FROM lineitem WHERE l_quantity < 0; + array_agg +----------- + +(1 row) + diff --git a/src/test/regress/expected/multi_average_expression.out b/src/test/regress/expected/multi_average_expression.out new file mode 100644 index 000000000..74511d553 --- /dev/null +++ b/src/test/regress/expected/multi_average_expression.out @@ -0,0 +1,65 @@ +-- +-- MULTI_AVERAGE_EXPRESSION_ORDER +-- +-- This test checks that the group-by columns don't need to be above an average +-- expression, and can be anywhere in the projection order. This is in response +-- to a bug we had due to the average expression introducing new columns. +SELECT + sum(l_quantity) as sum_qty, + sum(l_extendedprice) as sum_base_price, + sum(l_extendedprice * (1 - l_discount)) as sum_disc_price, + sum(l_extendedprice * (1 - l_discount) * (1 + l_tax)) as sum_charge, + avg(l_quantity) as avg_qty, + avg(l_extendedprice) as avg_price, + avg(l_discount) as avg_disc, + count(*) as count_order, + l_returnflag, + l_linestatus +FROM + lineitem +WHERE + l_shipdate <= date '1998-12-01' - interval '90 days' +GROUP BY + l_returnflag, + l_linestatus +ORDER BY + l_returnflag, + l_linestatus; + sum_qty | sum_base_price | sum_disc_price | sum_charge | avg_qty | avg_price | avg_disc | count_order | l_returnflag | l_linestatus +-----------+----------------+----------------+------------------+---------------------+--------------------+------------------------+-------------+--------------+-------------- + 75465.00 | 113619873.63 | 107841287.0728 | 112171153.245923 | 25.6334918478260870 | 38593.707075407609 | 0.05055027173913043478 | 2944 | A | F + 2022.00 | 3102551.45 | 2952540.7118 | 3072642.770652 | 26.6052631578947368 | 40823.045394736842 | 0.05263157894736842105 | 76 | N | F + 149778.00 | 224706948.16 | 213634857.6854 | 222134071.929801 | 25.4594594594594595 | 38195.979629440762 | 0.04939486656467788543 | 5883 | N | O + 73156.00 | 108937979.73 | 103516623.6698 | 107743533.784328 | 25.2175112030334367 | 37551.871675284385 | 0.04983798690106859704 | 2901 | R | F +(4 rows) + +-- These tests check that distributed averages only consider non-null input +-- values. This is in response to a bug we had due to the distributed average +-- using sum(expression)/count(*) to calculate avg(expression). We now use the +-- correct form sum(expression)/count(expression) for average calculations. +-- Run avg() on an expression that contains some null values +SELECT + avg(case + when l_quantity > 20 + then l_quantity + end) +FROM + lineitem; + avg +--------------------- + 35.3570440077497924 +(1 row) + +-- Run avg() on an expression that contains only null values +SELECT + avg(case + when l_quantity > 5000 + then l_quantity + end) +FROM + lineitem; + avg +----- + +(1 row) + diff --git a/src/test/regress/expected/multi_basic_queries.out b/src/test/regress/expected/multi_basic_queries.out new file mode 100644 index 000000000..f226ac6e3 --- /dev/null +++ b/src/test/regress/expected/multi_basic_queries.out @@ -0,0 +1,30 @@ +-- +-- MULTI_BASIC_QUERIES +-- +-- Execute simple sum, average, and count queries on data recently uploaded to +-- our partitioned table. +SELECT count(*) FROM lineitem; + count +------- + 12000 +(1 row) + +SELECT sum(l_extendedprice) FROM lineitem; + sum +-------------- + 457702024.50 +(1 row) + +SELECT avg(l_extendedprice) FROM lineitem; + avg +-------------------- + 38141.835375000000 +(1 row) + +-- Verify temp tables which are used for final result aggregation don't persist. +SELECT count(*) FROM pg_class WHERE relname LIKE 'pg_merge_job_%' AND relkind = 'r'; + count +------- + 0 +(1 row) + diff --git a/src/test/regress/expected/multi_binary_master_copy_format.out b/src/test/regress/expected/multi_binary_master_copy_format.out new file mode 100644 index 000000000..eef2f7f05 --- /dev/null +++ b/src/test/regress/expected/multi_binary_master_copy_format.out @@ -0,0 +1,33 @@ +-- +-- MULTI_BINARY_MASTER_COPY +-- +-- Try binary master copy for different executors +SET citusdb.binary_master_copy_format TO 'on'; +SET citusdb.task_executor_type TO 'task-tracker'; +SELECT count(*) FROM lineitem; + count +------- + 12000 +(1 row) + +SELECT l_shipmode FROM lineitem WHERE l_partkey = 67310 OR l_partkey = 155190; + l_shipmode +------------ + TRUCK + MAIL +(2 rows) + +SET citusdb.task_executor_type TO 'real-time'; +SELECT count(*) FROM lineitem; + count +------- + 12000 +(1 row) + +SELECT l_shipmode FROM lineitem WHERE l_partkey = 67310 OR l_partkey = 155190; + l_shipmode +------------ + TRUCK + MAIL +(2 rows) + diff --git a/src/test/regress/expected/multi_complex_expressions.out b/src/test/regress/expected/multi_complex_expressions.out new file mode 100644 index 000000000..e66c60f7d --- /dev/null +++ b/src/test/regress/expected/multi_complex_expressions.out @@ -0,0 +1,160 @@ +-- +-- MULTI_COMPLEX_EXPRESSIONS +-- +-- Check that we can correctly handle complex expressions and aggregates. +SELECT sum(l_quantity) / avg(l_quantity) FROM lineitem; + ?column? +------------------------ + 12000.0000000000000000 +(1 row) + +SELECT sum(l_quantity) / (10 * avg(l_quantity)) FROM lineitem; + ?column? +----------------------- + 1200.0000000000000000 +(1 row) + +SELECT (sum(l_quantity) / (10 * avg(l_quantity))) + 11 FROM lineitem; + ?column? +----------------------- + 1211.0000000000000000 +(1 row) + +SELECT avg(l_quantity) as average FROM lineitem; + average +--------------------- + 25.4462500000000000 +(1 row) + +SELECT 100 * avg(l_quantity) as average_times_hundred FROM lineitem; + average_times_hundred +----------------------- + 2544.6250000000000000 +(1 row) + +SELECT 100 * avg(l_quantity) / 10 as average_times_ten FROM lineitem; + average_times_ten +---------------------- + 254.4625000000000000 +(1 row) + +SELECT l_quantity, 10 * count(*) count_quantity FROM lineitem + GROUP BY l_quantity ORDER BY count_quantity, l_quantity; + l_quantity | count_quantity +------------+---------------- + 44.00 | 2150 + 38.00 | 2160 + 45.00 | 2180 + 13.00 | 2190 + 47.00 | 2200 + 29.00 | 2220 + 36.00 | 2230 + 49.00 | 2230 + 3.00 | 2270 + 35.00 | 2280 + 18.00 | 2290 + 31.00 | 2290 + 43.00 | 2290 + 14.00 | 2300 + 16.00 | 2300 + 17.00 | 2300 + 26.00 | 2300 + 7.00 | 2320 + 10.00 | 2340 + 34.00 | 2340 + 15.00 | 2350 + 25.00 | 2360 + 33.00 | 2360 + 42.00 | 2360 + 2.00 | 2370 + 12.00 | 2410 + 37.00 | 2410 + 6.00 | 2420 + 22.00 | 2420 + 1.00 | 2430 + 19.00 | 2430 + 4.00 | 2440 + 20.00 | 2460 + 48.00 | 2460 + 41.00 | 2470 + 24.00 | 2490 + 27.00 | 2490 + 8.00 | 2500 + 11.00 | 2500 + 5.00 | 2540 + 21.00 | 2550 + 32.00 | 2550 + 9.00 | 2580 + 39.00 | 2600 + 46.00 | 2600 + 50.00 | 2600 + 23.00 | 2610 + 30.00 | 2640 + 40.00 | 2690 + 28.00 | 2730 +(50 rows) + +-- Check that we can handle complex select clause expressions. +SELECT count(*) FROM lineitem + WHERE octet_length(l_comment || l_comment) > 40; + count +------- + 8148 +(1 row) + +SELECT count(*) FROM lineitem + WHERE octet_length(concat(l_comment, l_comment)) > 40; + count +------- + 8148 +(1 row) + +SELECT count(*) FROM lineitem + WHERE octet_length(l_comment) + octet_length('randomtext'::text) > 40; + count +------- + 4611 +(1 row) + +SELECT count(*) FROM lineitem + WHERE octet_length(l_comment) + 10 > 40; + count +------- + 4611 +(1 row) + +SELECT count(*) FROM lineitem + WHERE (l_receiptdate::timestamp - l_shipdate::timestamp) > interval '5 days'; + count +------- + 10008 +(1 row) + +SELECT count(*) FROM lineitem WHERE random() = 0.1; +ERROR: unsupported clause type +-- Check that we can handle implicit and explicit join clause definitions. +SELECT count(*) FROM lineitem, orders + WHERE l_orderkey = o_orderkey AND l_quantity < 5; + count +------- + 951 +(1 row) + +SELECT count(*) FROM lineitem + JOIN orders ON l_orderkey = o_orderkey AND l_quantity < 5; + count +------- + 951 +(1 row) + +SELECT count(*) FROM lineitem JOIN orders ON l_orderkey = o_orderkey + WHERE l_quantity < 5; + count +------- + 951 +(1 row) + +-- Check that we make sure local joins are between columns only. +SELECT count(*) FROM lineitem, orders WHERE l_orderkey + 1 = o_orderkey; +ERROR: cannot perform local joins that involve expressions +DETAIL: local joins can be performed between columns only diff --git a/src/test/regress/expected/multi_connection_cache.out b/src/test/regress/expected/multi_connection_cache.out new file mode 100644 index 000000000..acd921a1c --- /dev/null +++ b/src/test/regress/expected/multi_connection_cache.out @@ -0,0 +1,104 @@ +-- =================================================================== +-- create test functions +-- =================================================================== +CREATE FUNCTION initialize_remote_temp_table(cstring, integer) + RETURNS bool + AS 'citusdb' + LANGUAGE C STRICT; +CREATE FUNCTION count_remote_temp_table_rows(cstring, integer) + RETURNS integer + AS 'citusdb' + LANGUAGE C STRICT; +CREATE FUNCTION get_and_purge_connection(cstring, integer) + RETURNS bool + AS 'citusdb' + LANGUAGE C STRICT; +CREATE FUNCTION set_connection_status_bad(cstring, integer) + RETURNS bool + AS 'citusdb' + LANGUAGE C STRICT; +-- =================================================================== +-- test connection hash functionality +-- =================================================================== +-- worker port number is set in pg_regress_multi.pl +\set worker_port 57638 +-- reduce verbosity to squelch chatty warnings +\set VERBOSITY terse +-- connect to non-existent host +SELECT initialize_remote_temp_table('dummy-host-name', 12345); +WARNING: Connection failed to dummy-host-name:12345 + initialize_remote_temp_table +------------------------------ + f +(1 row) + +\set VERBOSITY default +-- try to use hostname over 255 characters +SELECT initialize_remote_temp_table(repeat('a', 256)::cstring, :worker_port); +ERROR: hostname exceeds the maximum length of 255 +-- connect to localhost and build a temp table +SELECT initialize_remote_temp_table('localhost', :worker_port); + initialize_remote_temp_table +------------------------------ + t +(1 row) + +-- table should still be visible since session is reused +SELECT count_remote_temp_table_rows('localhost', :worker_port); + count_remote_temp_table_rows +------------------------------ + 100 +(1 row) + +-- purge existing connection to localhost +SELECT get_and_purge_connection('localhost', :worker_port); + get_and_purge_connection +-------------------------- + t +(1 row) + +-- squelch WARNINGs that contain worker_port +SET client_min_messages TO ERROR; +-- should not be able to see table anymore +SELECT count_remote_temp_table_rows('localhost', :worker_port); + count_remote_temp_table_rows +------------------------------ + -1 +(1 row) + +-- recreate once more +SELECT initialize_remote_temp_table('localhost', :worker_port); + initialize_remote_temp_table +------------------------------ + t +(1 row) + +-- set the connection status to bad +SELECT set_connection_status_bad('localhost', :worker_port); + set_connection_status_bad +--------------------------- + t +(1 row) + +-- should get connection failure (cached connection bad) +SELECT count_remote_temp_table_rows('localhost', :worker_port); + count_remote_temp_table_rows +------------------------------ + -1 +(1 row) + +-- should get result failure (reconnected, so no temp table) +SELECT count_remote_temp_table_rows('localhost', :worker_port); + count_remote_temp_table_rows +------------------------------ + -1 +(1 row) + +-- purge the connection so that we clean up the bad connection +SELECT get_and_purge_connection('localhost', :worker_port); + get_and_purge_connection +-------------------------- + t +(1 row) + +SET client_min_messages TO DEFAULT; diff --git a/src/test/regress/expected/multi_count_type_conversion.out b/src/test/regress/expected/multi_count_type_conversion.out new file mode 100644 index 000000000..a258ebef2 --- /dev/null +++ b/src/test/regress/expected/multi_count_type_conversion.out @@ -0,0 +1,85 @@ +-- +-- MULTI_COUNT_TYPE_CONVERSION +-- +-- Verify that we can sort count(*) results correctly. We perform this check as +-- our count() operations execute in two steps: worker nodes report their +-- count() results, and the master node sums these counts up. During this sum(), +-- the data type changes from int8 to numeric. When we sort the numeric value, +-- we get erroneous results on 64-bit architectures. To fix this issue, we +-- manually cast back the sum() result to an int8 data type. +SELECT count(*) count_quantity, l_quantity FROM lineitem WHERE l_quantity < 32.0 + GROUP BY l_quantity + ORDER BY count_quantity ASC, l_quantity DESC; + count_quantity | l_quantity +----------------+------------ + 219 | 13.00 + 222 | 29.00 + 227 | 3.00 + 229 | 31.00 + 229 | 18.00 + 230 | 26.00 + 230 | 17.00 + 230 | 16.00 + 230 | 14.00 + 232 | 7.00 + 234 | 10.00 + 235 | 15.00 + 236 | 25.00 + 237 | 2.00 + 241 | 12.00 + 242 | 22.00 + 242 | 6.00 + 243 | 19.00 + 243 | 1.00 + 244 | 4.00 + 246 | 20.00 + 249 | 27.00 + 249 | 24.00 + 250 | 11.00 + 250 | 8.00 + 254 | 5.00 + 255 | 21.00 + 258 | 9.00 + 261 | 23.00 + 264 | 30.00 + 273 | 28.00 +(31 rows) + +SELECT count(*) count_quantity, l_quantity FROM lineitem WHERE l_quantity < 32.0 + GROUP BY l_quantity + ORDER BY count_quantity DESC, l_quantity ASC; + count_quantity | l_quantity +----------------+------------ + 273 | 28.00 + 264 | 30.00 + 261 | 23.00 + 258 | 9.00 + 255 | 21.00 + 254 | 5.00 + 250 | 8.00 + 250 | 11.00 + 249 | 24.00 + 249 | 27.00 + 246 | 20.00 + 244 | 4.00 + 243 | 1.00 + 243 | 19.00 + 242 | 6.00 + 242 | 22.00 + 241 | 12.00 + 237 | 2.00 + 236 | 25.00 + 235 | 15.00 + 234 | 10.00 + 232 | 7.00 + 230 | 14.00 + 230 | 16.00 + 230 | 17.00 + 230 | 26.00 + 229 | 18.00 + 229 | 31.00 + 227 | 3.00 + 222 | 29.00 + 219 | 13.00 +(31 rows) + diff --git a/src/test/regress/expected/multi_create_fdw.out b/src/test/regress/expected/multi_create_fdw.out new file mode 100644 index 000000000..abd6a5616 --- /dev/null +++ b/src/test/regress/expected/multi_create_fdw.out @@ -0,0 +1,10 @@ +-- =================================================================== +-- get ready for the foreign data wrapper tests +-- =================================================================== +-- create fake fdw for use in tests +CREATE FUNCTION fake_fdw_handler() +RETURNS fdw_handler +AS 'citusdb' +LANGUAGE C STRICT; +CREATE FOREIGN DATA WRAPPER fake_fdw HANDLER fake_fdw_handler; +CREATE SERVER fake_fdw_server FOREIGN DATA WRAPPER fake_fdw; diff --git a/src/test/regress/expected/multi_create_insert_proxy.out b/src/test/regress/expected/multi_create_insert_proxy.out new file mode 100644 index 000000000..5737338ef --- /dev/null +++ b/src/test/regress/expected/multi_create_insert_proxy.out @@ -0,0 +1,90 @@ +-- =================================================================== +-- test INSERT proxy creation functionality +-- =================================================================== +-- use transaction to permit multiple calls to proxy function in one session +BEGIN; +-- use "unorthodox" object names to test quoting +CREATE SCHEMA "A$AP Mob" + CREATE TABLE "Dr. Bronner's ""Magic"" Soaps" ( + id bigint PRIMARY KEY, + data text NOT NULL DEFAULT 'lorem ipsum' + ); +NOTICE: CitusDB partially supports CREATE SCHEMA for distributed databases +DETAIL: schema usage in joins and in some UDFs provided by CitusDB are not supported yet +\set insert_target '"A$AP Mob"."Dr. Bronner''s ""Magic"" Soaps"' +-- create proxy and save proxy table name +SELECT create_insert_proxy_for_table(:'insert_target') AS proxy_tablename +\gset +-- insert to proxy, relying on default value +INSERT INTO pg_temp.:"proxy_tablename" (id) VALUES (1); +-- copy some rows into the proxy +COPY pg_temp.:"proxy_tablename" FROM stdin; +-- verify rows were copied to target +SELECT * FROM :insert_target ORDER BY id ASC; + id | data +----+----------------------------- + 1 | lorem ipsum + 2 | dolor sit amet + 3 | consectetur adipiscing elit + 4 | sed do eiusmod + 5 | tempor incididunt ut + 6 | labore et dolore +(6 rows) + +-- and not to proxy +SELECT count(*) FROM pg_temp.:"proxy_tablename"; + count +------- + 0 +(1 row) + +ROLLBACK; +-- test behavior with distributed table, (so no transaction) +CREATE TABLE insert_target ( + id bigint PRIMARY KEY, + data text NOT NULL DEFAULT 'lorem ipsum' +); +-- squelch WARNINGs that contain worker_port +SET client_min_messages TO ERROR; +SELECT master_create_distributed_table('insert_target', 'id', 'hash'); + master_create_distributed_table +--------------------------------- + +(1 row) + +SELECT master_create_worker_shards('insert_target', 2, 1); + master_create_worker_shards +----------------------------- + +(1 row) + +CREATE TEMPORARY SEQUENCE rows_inserted; +SELECT create_insert_proxy_for_table('insert_target', 'rows_inserted') AS proxy_tablename +\gset +-- insert to proxy, again relying on default value +INSERT INTO pg_temp.:"proxy_tablename" (id) VALUES (1); +-- test copy with bad row in middle +\set VERBOSITY terse +COPY pg_temp.:"proxy_tablename" FROM stdin; +ERROR: could not modify any active placements +\set VERBOSITY default +-- verify rows were copied to distributed table +SELECT * FROM insert_target ORDER BY id ASC; + id | data +----+----------------------------- + 1 | lorem ipsum + 2 | dolor sit amet + 3 | consectetur adipiscing elit + 4 | sed do eiusmod + 5 | tempor incididunt ut + 6 | labore et dolore +(6 rows) + +-- the counter should match the number of rows stored +SELECT currval('rows_inserted'); + currval +--------- + 6 +(1 row) + +SET client_min_messages TO DEFAULT; diff --git a/src/test/regress/expected/multi_create_shards.out b/src/test/regress/expected/multi_create_shards.out new file mode 100644 index 000000000..01e44580d --- /dev/null +++ b/src/test/regress/expected/multi_create_shards.out @@ -0,0 +1,237 @@ +-- =================================================================== +-- create test functions and types needed for tests +-- =================================================================== +CREATE FUNCTION sort_names(cstring, cstring, cstring) + RETURNS cstring + AS 'citusdb' + LANGUAGE C STRICT; +-- create a custom type... +CREATE TYPE dummy_type AS ( + i integer +); +-- ... as well as a function to use as its comparator... +CREATE FUNCTION dummy_type_function(dummy_type, dummy_type) RETURNS boolean +AS 'SELECT TRUE;' +LANGUAGE SQL +IMMUTABLE +RETURNS NULL ON NULL INPUT; +-- ... use that function to create a custom operator... +CREATE OPERATOR = ( + LEFTARG = dummy_type, + RIGHTARG = dummy_type, + PROCEDURE = dummy_type_function +); +-- ... and create a custom operator family for hash indexes... +CREATE OPERATOR FAMILY dummy_op_family USING hash; +-- ... finally, build an operator class, designate it as the default operator +-- class for the type, but only specify an equality operator. So the type will +-- have a default op class but no hash operator in that class. +CREATE OPERATOR CLASS dummy_op_family_class +DEFAULT FOR TYPE dummy_type USING hash FAMILY dummy_op_family AS +OPERATOR 1 =; +-- =================================================================== +-- test shard creation functionality +-- =================================================================== +CREATE TABLE table_to_distribute ( + name text PRIMARY KEY, + id bigint, + json_data json, + test_type_data dummy_type +); +-- use an index instead of table name +SELECT master_create_distributed_table('table_to_distribute_pkey', 'id', 'hash'); +ERROR: cannot distribute relation: table_to_distribute_pkey +DETAIL: Distributed relations must be regular or foreign tables. +-- use a bad column name +SELECT master_create_distributed_table('table_to_distribute', 'bad_column', 'hash'); +ERROR: column "bad_column" of relation "table_to_distribute" does not exist +-- use unrecognized partition type +SELECT master_create_distributed_table('table_to_distribute', 'name', 'unrecognized'); +ERROR: invalid input value for enum citusdb.distribution_type: "unrecognized" +LINE 1: ..._distributed_table('table_to_distribute', 'name', 'unrecogni... + ^ +-- use a partition column of a type lacking any default operator class +SELECT master_create_distributed_table('table_to_distribute', 'json_data', 'hash'); +ERROR: data type json has no default operator class for specified partition method +DETAIL: Partition column types must have a default operator class defined. +-- use a partition column of type lacking the required support function (hash) +SELECT master_create_distributed_table('table_to_distribute', 'test_type_data', 'hash'); +ERROR: could not identify a hash function for type dummy_type +DETAIL: Partition column types must have a hash function defined to use hash partitioning. +-- distribute table and inspect side effects +SELECT master_create_distributed_table('table_to_distribute', 'name', 'hash'); + master_create_distributed_table +--------------------------------- + +(1 row) + +SELECT partmethod, partkey FROM pg_dist_partition + WHERE logicalrelid = 'table_to_distribute'::regclass; + partmethod | partkey +------------+-------------------------------------------------------------------------------------------------------------------------- + h | {VAR :varno 1 :varattno 1 :vartype 25 :vartypmod -1 :varcollid 100 :varlevelsup 0 :varnoold 1 :varoattno 1 :location -1} +(1 row) + +-- use a bad shard count +SELECT master_create_worker_shards('table_to_distribute', 0, 1); +ERROR: shard_count must be positive +-- use a bad replication factor +SELECT master_create_worker_shards('table_to_distribute', 16, 0); +ERROR: replication_factor must be positive +-- use a replication factor higher than shard count +SELECT master_create_worker_shards('table_to_distribute', 16, 3); +ERROR: replication_factor (3) exceeds number of worker nodes (2) +HINT: Add more worker nodes or try again with a lower replication factor. +-- finally, create shards and inspect metadata +SELECT master_create_worker_shards('table_to_distribute', 16, 1); + master_create_worker_shards +----------------------------- + +(1 row) + +SELECT shardstorage, shardminvalue, shardmaxvalue FROM pg_dist_shard + WHERE logicalrelid = 'table_to_distribute'::regclass + ORDER BY (shardminvalue::integer) ASC; + shardstorage | shardminvalue | shardmaxvalue +--------------+---------------+--------------- + t | -2147483648 | -1879048193 + t | -1879048192 | -1610612737 + t | -1610612736 | -1342177281 + t | -1342177280 | -1073741825 + t | -1073741824 | -805306369 + t | -805306368 | -536870913 + t | -536870912 | -268435457 + t | -268435456 | -1 + t | 0 | 268435455 + t | 268435456 | 536870911 + t | 536870912 | 805306367 + t | 805306368 | 1073741823 + t | 1073741824 | 1342177279 + t | 1342177280 | 1610612735 + t | 1610612736 | 1879048191 + t | 1879048192 | 2147483647 +(16 rows) + +-- all shards should have the same size (16 divides evenly into the hash space) +SELECT count(*) AS shard_count, + shardmaxvalue::integer - shardminvalue::integer AS shard_size + FROM pg_dist_shard + WHERE logicalrelid='table_to_distribute'::regclass + GROUP BY shard_size; + shard_count | shard_size +-------------+------------ + 16 | 268435455 +(1 row) + +SELECT COUNT(*) FROM pg_class WHERE relname LIKE 'table_to_distribute%' AND relkind = 'r'; + count +------- + 1 +(1 row) + +-- try to create them again +SELECT master_create_worker_shards('table_to_distribute', 16, 1); +ERROR: table "table_to_distribute" has already had shards created for it +-- test list sorting +SELECT sort_names('sumedh', 'jason', 'ozgun'); + sort_names +------------ + jason + + ozgun + + sumedh + + +(1 row) + +SELECT COUNT(*) FROM pg_class WHERE relname LIKE 'throwaway%' AND relkind = 'r'; + count +------- + 0 +(1 row) + +-- test foreign table creation +CREATE FOREIGN TABLE foreign_table_to_distribute +( + name text, + id bigint +) +SERVER fake_fdw_server; +SELECT master_create_distributed_table('foreign_table_to_distribute', 'id', 'hash'); + master_create_distributed_table +--------------------------------- + +(1 row) + +SELECT master_create_worker_shards('foreign_table_to_distribute', 16, 1); +NOTICE: foreign-data wrapper "fake_fdw" does not have an extension defined + master_create_worker_shards +----------------------------- + +(1 row) + +SELECT shardstorage, shardminvalue, shardmaxvalue FROM pg_dist_shard + WHERE logicalrelid = 'foreign_table_to_distribute'::regclass + ORDER BY (shardminvalue::integer) ASC; + shardstorage | shardminvalue | shardmaxvalue +--------------+---------------+--------------- + f | -2147483648 | -1879048193 + f | -1879048192 | -1610612737 + f | -1610612736 | -1342177281 + f | -1342177280 | -1073741825 + f | -1073741824 | -805306369 + f | -805306368 | -536870913 + f | -536870912 | -268435457 + f | -268435456 | -1 + f | 0 | 268435455 + f | 268435456 | 536870911 + f | 536870912 | 805306367 + f | 805306368 | 1073741823 + f | 1073741824 | 1342177279 + f | 1342177280 | 1610612735 + f | 1610612736 | 1879048191 + f | 1879048192 | 2147483647 +(16 rows) + +-- test shard creation using weird shard count +CREATE TABLE weird_shard_count +( + name text, + id bigint +); +SELECT master_create_distributed_table('weird_shard_count', 'id', 'hash'); + master_create_distributed_table +--------------------------------- + +(1 row) + +SELECT master_create_worker_shards('weird_shard_count', 7, 1); + master_create_worker_shards +----------------------------- + +(1 row) + +-- CitusDB ensures all shards are roughly the same size +SELECT shardmaxvalue::integer - shardminvalue::integer AS shard_size + FROM pg_dist_shard + WHERE logicalrelid = 'weird_shard_count'::regclass + ORDER BY shardminvalue::integer ASC; + shard_size +------------ + 613566755 + 613566755 + 613566755 + 613566755 + 613566755 + 613566755 + 613566759 +(7 rows) + +-- cleanup foreign table, related shards and shard placements +DELETE FROM pg_dist_shard_placement + WHERE shardid IN (SELECT shardid FROM pg_dist_shard + WHERE logicalrelid = 'foreign_table_to_distribute'::regclass); + +DELETE FROM pg_dist_shard + WHERE logicalrelid = 'foreign_table_to_distribute'::regclass; + +DELETE FROM pg_dist_partition + WHERE logicalrelid = 'foreign_table_to_distribute'::regclass; diff --git a/src/test/regress/expected/multi_create_table.out b/src/test/regress/expected/multi_create_table.out new file mode 100644 index 000000000..b079d7873 --- /dev/null +++ b/src/test/regress/expected/multi_create_table.out @@ -0,0 +1,194 @@ +-- +-- MULTI_CREATE_TABLE +-- +-- Create new table definitions for use in testing in distributed planning and +-- execution functionality. Also create indexes to boost performance. +CREATE TABLE lineitem ( + l_orderkey bigint not null, + l_partkey integer not null, + l_suppkey integer not null, + l_linenumber integer not null, + l_quantity decimal(15, 2) not null, + l_extendedprice decimal(15, 2) not null, + l_discount decimal(15, 2) not null, + l_tax decimal(15, 2) not null, + l_returnflag char(1) not null, + l_linestatus char(1) not null, + l_shipdate date not null, + l_commitdate date not null, + l_receiptdate date not null, + l_shipinstruct char(25) not null, + l_shipmode char(10) not null, + l_comment varchar(44) not null, + PRIMARY KEY(l_orderkey, l_linenumber) ); +SELECT master_create_distributed_table('lineitem', 'l_orderkey', 'append'); +WARNING: table "lineitem" has a unique constraint +DETAIL: Unique constraints and primary keys on append-partitioned tables cannot be enforced. +HINT: Consider using hash partitioning. + master_create_distributed_table +--------------------------------- + +(1 row) + +CREATE INDEX lineitem_time_index ON lineitem (l_shipdate); +CREATE TABLE orders ( + o_orderkey bigint not null, + o_custkey integer not null, + o_orderstatus char(1) not null, + o_totalprice decimal(15,2) not null, + o_orderdate date not null, + o_orderpriority char(15) not null, + o_clerk char(15) not null, + o_shippriority integer not null, + o_comment varchar(79) not null, + PRIMARY KEY(o_orderkey) ); +SELECT master_create_distributed_table('orders', 'o_orderkey', 'append'); +WARNING: table "orders" has a unique constraint +DETAIL: Unique constraints and primary keys on append-partitioned tables cannot be enforced. +HINT: Consider using hash partitioning. + master_create_distributed_table +--------------------------------- + +(1 row) + +CREATE TABLE customer ( + c_custkey integer not null, + c_name varchar(25) not null, + c_address varchar(40) not null, + c_nationkey integer not null, + c_phone char(15) not null, + c_acctbal decimal(15,2) not null, + c_mktsegment char(10) not null, + c_comment varchar(117) not null); +SELECT master_create_distributed_table('customer', 'c_custkey', 'append'); + master_create_distributed_table +--------------------------------- + +(1 row) + +CREATE TABLE nation ( + n_nationkey integer not null, + n_name char(25) not null, + n_regionkey integer not null, + n_comment varchar(152)); +SELECT master_create_distributed_table('nation', 'n_nationkey', 'append'); + master_create_distributed_table +--------------------------------- + +(1 row) + +CREATE TABLE part ( + p_partkey integer not null, + p_name varchar(55) not null, + p_mfgr char(25) not null, + p_brand char(10) not null, + p_type varchar(25) not null, + p_size integer not null, + p_container char(10) not null, + p_retailprice decimal(15,2) not null, + p_comment varchar(23) not null); +SELECT master_create_distributed_table('part', 'p_partkey', 'append'); + master_create_distributed_table +--------------------------------- + +(1 row) + +CREATE TABLE supplier +( + s_suppkey integer not null, + s_name char(25) not null, + s_address varchar(40) not null, + s_nationkey integer, + s_phone char(15) not null, + s_acctbal decimal(15,2) not null, + s_comment varchar(101) not null +); +SELECT master_create_distributed_table('supplier', 's_suppkey', 'append'); + master_create_distributed_table +--------------------------------- + +(1 row) + +-- now test that CitusDB cannot distribute unique constraints that do not include +-- the partition column +CREATE TABLE primary_key_on_non_part_col +( + partition_col integer, + other_col integer PRIMARY KEY +); +SELECT master_create_distributed_table('primary_key_on_non_part_col', 'partition_col', 'hash'); +ERROR: cannot distribute relation: "primary_key_on_non_part_col" +DETAIL: Distributed relations cannot have UNIQUE constraints or PRIMARY KEYs that do not include the partition column. +CREATE TABLE unique_const_on_non_part_col +( + partition_col integer, + other_col integer UNIQUE +); +SELECT master_create_distributed_table('primary_key_on_non_part_col', 'partition_col', 'hash'); +ERROR: cannot distribute relation: "primary_key_on_non_part_col" +DETAIL: Distributed relations cannot have UNIQUE constraints or PRIMARY KEYs that do not include the partition column. +-- now show that CitusDB can distribute unique constrints that include +-- the partition column +CREATE TABLE primary_key_on_part_col +( + partition_col integer PRIMARY KEY, + other_col integer +); +SELECT master_create_distributed_table('primary_key_on_part_col', 'partition_col', 'hash'); + master_create_distributed_table +--------------------------------- + +(1 row) + +CREATE TABLE unique_const_on_part_col +( + partition_col integer UNIQUE, + other_col integer +); +SELECT master_create_distributed_table('unique_const_on_part_col', 'partition_col', 'hash'); + master_create_distributed_table +--------------------------------- + +(1 row) + +CREATE TABLE unique_const_on_two_columns +( + partition_col integer, + other_col integer, + UNIQUE (partition_col, other_col) +); +SELECT master_create_distributed_table('unique_const_on_two_columns', 'partition_col', 'hash'); + master_create_distributed_table +--------------------------------- + +(1 row) + +CREATE TABLE unique_const_append_partitioned_tables +( + partition_col integer UNIQUE, + other_col integer +); +SELECT master_create_distributed_table('unique_const_append_partitioned_tables', 'partition_col', 'append'); +WARNING: table "unique_const_append_partitioned_tables" has a unique constraint +DETAIL: Unique constraints and primary keys on append-partitioned tables cannot be enforced. +HINT: Consider using hash partitioning. + master_create_distributed_table +--------------------------------- + +(1 row) + +CREATE TABLE unique_const_range_partitioned_tables +( + partition_col integer UNIQUE, + other_col integer +); +SELECT master_create_distributed_table('unique_const_range_partitioned_tables', 'partition_col', 'range'); + master_create_distributed_table +--------------------------------- + +(1 row) + +-- drop unnecessary tables +DROP TABLE primary_key_on_non_part_col, unique_const_on_non_part_col CASCADE; +DROP TABLE primary_key_on_part_col, unique_const_on_part_col, unique_const_on_two_columns CASCADE; +DROP TABLE unique_const_range_partitioned_tables CASCADE; diff --git a/src/test/regress/expected/multi_data_types.out b/src/test/regress/expected/multi_data_types.out new file mode 100644 index 000000000..8dc78f841 --- /dev/null +++ b/src/test/regress/expected/multi_data_types.out @@ -0,0 +1,154 @@ +-- =================================================================== +-- test composite type, varchar and enum types +-- create, distribute, INSERT, SELECT and UPDATE +-- =================================================================== +-- create a custom type... +CREATE TYPE test_composite_type AS ( + i integer, + i2 integer +); +-- ... as well as a function to use as its comparator... +CREATE FUNCTION equal_test_composite_type_function(test_composite_type, test_composite_type) RETURNS boolean +AS 'select $1.i = $2.i AND $1.i2 = $2.i2;' +LANGUAGE SQL +IMMUTABLE +RETURNS NULL ON NULL INPUT; +-- ... use that function to create a custom equality operator... +CREATE OPERATOR = ( + LEFTARG = test_composite_type, + RIGHTARG = test_composite_type, + PROCEDURE = equal_test_composite_type_function, + HASHES +); +-- ... and create a custom operator family for hash indexes... +CREATE OPERATOR FAMILY cats_op_fam USING hash; +-- ... create a test HASH function. Though it is a poor hash function, +-- it is acceptable for our tests +CREATE FUNCTION test_composite_type_hash(test_composite_type) RETURNS int +AS 'SELECT hashtext( ($1.i + $1.i2)::text);' +LANGUAGE SQL +IMMUTABLE +RETURNS NULL ON NULL INPUT; +-- We need to define two different operator classes for the composite types +-- One uses BTREE the other uses HASH +CREATE OPERATOR CLASS cats_op_fam_clas3 +DEFAULT FOR TYPE test_composite_type USING BTREE AS +OPERATOR 3 = (test_composite_type, test_composite_type); +CREATE OPERATOR CLASS cats_op_fam_class +DEFAULT FOR TYPE test_composite_type USING HASH AS +OPERATOR 1 = (test_composite_type, test_composite_type), +FUNCTION 1 test_composite_type_hash(test_composite_type); +-- create and distribute a table on composite type column +CREATE TABLE composite_type_partitioned_table +( + id integer, + col test_composite_type +); +SELECT master_create_distributed_table('composite_type_partitioned_table', 'col', 'hash'); + master_create_distributed_table +--------------------------------- + +(1 row) + +SELECT master_create_worker_shards('composite_type_partitioned_table', 4, 1); + master_create_worker_shards +----------------------------- + +(1 row) + +-- execute INSERT, SELECT and UPDATE queries on composite_type_partitioned_table +INSERT INTO composite_type_partitioned_table VALUES (1, '(1, 2)'::test_composite_type); +INSERT INTO composite_type_partitioned_table VALUES (2, '(3, 4)'::test_composite_type); +INSERT INTO composite_type_partitioned_table VALUES (3, '(5, 6)'::test_composite_type); +INSERT INTO composite_type_partitioned_table VALUES (4, '(7, 8)'::test_composite_type); +INSERT INTO composite_type_partitioned_table VALUES (5, '(9, 10)'::test_composite_type); +SELECT * FROM composite_type_partitioned_table WHERE col = '(7, 8)'::test_composite_type; + id | col +----+------- + 4 | (7,8) +(1 row) + +UPDATE composite_type_partitioned_table SET id = 6 WHERE col = '(7, 8)'::test_composite_type; +SELECT * FROM composite_type_partitioned_table WHERE col = '(7, 8)'::test_composite_type; + id | col +----+------- + 6 | (7,8) +(1 row) + +-- create and distribute a table on enum type column +CREATE TYPE bug_status AS ENUM ('new', 'open', 'closed'); +CREATE TABLE bugs ( + id integer, + status bug_status +); +SELECT master_create_distributed_table('bugs', 'status', 'hash'); + master_create_distributed_table +--------------------------------- + +(1 row) + +SELECT master_create_worker_shards('bugs', 4, 1); + master_create_worker_shards +----------------------------- + +(1 row) + +-- execute INSERT, SELECT and UPDATE queries on composite_type_partitioned_table +INSERT INTO bugs VALUES (1, 'new'); +INSERT INTO bugs VALUES (2, 'open'); +INSERT INTO bugs VALUES (3, 'closed'); +INSERT INTO bugs VALUES (4, 'closed'); +INSERT INTO bugs VALUES (5, 'open'); +SELECT * FROM bugs WHERE status = 'closed'::bug_status; + id | status +----+-------- + 3 | closed + 4 | closed +(2 rows) + +UPDATE bugs SET status = 'closed'::bug_status WHERE id = 2; +ERROR: modifying the partition value of rows is not allowed +SELECT * FROM bugs WHERE status = 'open'::bug_status; + id | status +----+-------- + 2 | open + 5 | open +(2 rows) + +-- create and distribute a table on varchar column +CREATE TABLE varchar_hash_partitioned_table +( + id int, + name varchar +); +SELECT master_create_distributed_table('varchar_hash_partitioned_table', 'id', 'hash'); + master_create_distributed_table +--------------------------------- + +(1 row) + +SELECT master_create_worker_shards('varchar_hash_partitioned_table', 4, 1); + master_create_worker_shards +----------------------------- + +(1 row) + +-- execute INSERT, SELECT and UPDATE queries on composite_type_partitioned_table +INSERT INTO varchar_hash_partitioned_table VALUES (1, 'Jason'); +INSERT INTO varchar_hash_partitioned_table VALUES (2, 'Ozgun'); +INSERT INTO varchar_hash_partitioned_table VALUES (3, 'Onder'); +INSERT INTO varchar_hash_partitioned_table VALUES (4, 'Sumedh'); +INSERT INTO varchar_hash_partitioned_table VALUES (5, 'Marco'); +SELECT * FROM varchar_hash_partitioned_table WHERE name = 'Onder'; + id | name +----+------- + 3 | Onder +(1 row) + +UPDATE varchar_hash_partitioned_table SET name = 'Samay' WHERE id = 5; +SELECT * FROM varchar_hash_partitioned_table WHERE name = 'Samay'; + id | name +----+------- + 5 | Samay +(1 row) + diff --git a/src/test/regress/expected/multi_distribution_metadata.out b/src/test/regress/expected/multi_distribution_metadata.out new file mode 100644 index 000000000..6c69be7b8 --- /dev/null +++ b/src/test/regress/expected/multi_distribution_metadata.out @@ -0,0 +1,296 @@ +-- =================================================================== +-- create test functions +-- =================================================================== +CREATE FUNCTION load_shard_id_array(regclass) + RETURNS bigint[] + AS 'citusdb' + LANGUAGE C STRICT; +CREATE FUNCTION load_shard_interval_array(bigint, anyelement) + RETURNS anyarray + AS 'citusdb' + LANGUAGE C STRICT; +CREATE FUNCTION load_shard_placement_array(bigint, bool) + RETURNS text[] + AS 'citusdb' + LANGUAGE C STRICT; +CREATE FUNCTION partition_column_id(regclass) + RETURNS smallint + AS 'citusdb' + LANGUAGE C STRICT; +CREATE FUNCTION partition_type(regclass) + RETURNS "char" + AS 'citusdb' + LANGUAGE C STRICT; +CREATE FUNCTION is_distributed_table(regclass) + RETURNS boolean + AS 'citusdb' + LANGUAGE C STRICT; +CREATE FUNCTION column_name_to_column_id(regclass, cstring) + RETURNS smallint + AS 'citusdb' + LANGUAGE C STRICT; +CREATE FUNCTION create_monolithic_shard_row(regclass) + RETURNS bigint + AS 'citusdb' + LANGUAGE C STRICT; +CREATE FUNCTION create_healthy_local_shard_placement_row(bigint) + RETURNS void + AS 'citusdb' + LANGUAGE C STRICT; +CREATE FUNCTION delete_shard_placement_row(bigint, text, bigint) + RETURNS bool + AS 'citusdb' + LANGUAGE C STRICT; +CREATE FUNCTION update_shard_placement_row_state(bigint, text, bigint, int) + RETURNS bool + AS 'citusdb' + LANGUAGE C STRICT; +CREATE FUNCTION acquire_shared_shard_lock(bigint) + RETURNS void + AS 'citusdb' + LANGUAGE C STRICT; +CREATE FUNCTION column_name_to_column(regclass, text) + RETURNS text + AS 'citusdb' + LANGUAGE C STRICT; +-- =================================================================== +-- test distribution metadata functionality +-- =================================================================== +-- create table to be distributed +CREATE TABLE events_hash ( + id bigint, + name text +); +-- for this table we'll "distribute" manually but verify using function calls +INSERT INTO pg_dist_shard + (shardid, logicalrelid, shardstorage, shardminvalue, shardmaxvalue) +VALUES + (1, 'events_hash'::regclass, 't', '0', '10'), + (2, 'events_hash'::regclass, 't', '10', '20'), + (3, 'events_hash'::regclass, 't', '20', '30'), + (4, 'events_hash'::regclass, 't', '30', '40'); +INSERT INTO pg_dist_shard_placement + (nodename, nodeport, shardid, shardstate, shardlength) +VALUES + ('cluster-worker-01', 5432, 1, 0, 0), + ('cluster-worker-01', 5432, 2, 0, 0), + ('cluster-worker-02', 5433, 3, 0, 0), + ('cluster-worker-02', 5433, 4, 0, 0), + ('cluster-worker-03', 5434, 1, 1, 0), + ('cluster-worker-03', 5434, 2, 1, 0), + ('cluster-worker-04', 5435, 3, 1, 0), + ('cluster-worker-04', 5435, 4, 1, 0); +INSERT INTO pg_dist_partition (logicalrelid, partmethod, partkey) +VALUES + ('events_hash'::regclass, 'h', column_name_to_column('events_hash'::regclass, 'name')); +-- should see above shard identifiers +SELECT load_shard_id_array('events_hash'); + load_shard_id_array +--------------------- + {4,3,2,1} +(1 row) + +-- should see array with first shard range +SELECT load_shard_interval_array(1, 0); + load_shard_interval_array +--------------------------- + {0,10} +(1 row) + +-- should even work for range-partitioned shards +BEGIN; + UPDATE pg_dist_shard SET + shardminvalue = 'Aardvark', + shardmaxvalue = 'Zebra' + WHERE shardid = 1; + UPDATE pg_dist_partition SET partmethod = 'r' + WHERE logicalrelid = 'events_hash'::regclass; + SELECT load_shard_interval_array(1, ''::text); + load_shard_interval_array +--------------------------- + {Aardvark,Zebra} +(1 row) + +ROLLBACK; +-- should see error for non-existent shard +SELECT load_shard_interval_array(5, 0); +ERROR: could not find valid entry for shard 5 +-- should see two placements +SELECT load_shard_placement_array(2, false); + load_shard_placement_array +------------------------------------------------- + {cluster-worker-03:5434,cluster-worker-01:5432} +(1 row) + +-- only one of which is finalized +SELECT load_shard_placement_array(2, true); + load_shard_placement_array +---------------------------- + {cluster-worker-03:5434} +(1 row) + +-- should see error for non-existent shard +SELECT load_shard_placement_array(6, false); +WARNING: could not find any shard placements for shardId 6 + load_shard_placement_array +---------------------------- + {} +(1 row) + +-- should see column id of 'name' +SELECT partition_column_id('events_hash'); + partition_column_id +--------------------- + 2 +(1 row) + +-- should see hash partition type and fail for non-distributed tables +SELECT partition_type('events_hash'); + partition_type +---------------- + h +(1 row) + +SELECT partition_type('pg_type'); +ERROR: relation 1247 is not distributed +-- should see true for events_hash, false for others +SELECT is_distributed_table('events_hash'); + is_distributed_table +---------------------- + t +(1 row) + +SELECT is_distributed_table('pg_type'); + is_distributed_table +---------------------- + f +(1 row) + +SELECT is_distributed_table('pg_dist_shard'); + is_distributed_table +---------------------- + f +(1 row) + +-- test underlying column name-id translation +SELECT column_name_to_column_id('events_hash', 'name'); + column_name_to_column_id +-------------------------- + 2 +(1 row) + +SELECT column_name_to_column_id('events_hash', 'ctid'); +ERROR: cannot reference system column "ctid" in relation "events_hash" +SELECT column_name_to_column_id('events_hash', 'non_existent'); +ERROR: column "non_existent" of relation "events_hash" does not exist +-- drop shard rows (must drop placements first) +DELETE FROM pg_dist_shard_placement + WHERE shardid BETWEEN 1 AND 4; +DELETE FROM pg_dist_shard + WHERE logicalrelid = 'events_hash'::regclass; +-- verify that an eager load shows them missing +SELECT load_shard_id_array('events_hash'); + load_shard_id_array +--------------------- + {} +(1 row) + +-- create second table to distribute +CREATE TABLE customers ( + id bigint, + name text +); +-- now we'll distribute using function calls but verify metadata manually... +-- partition on id and manually inspect partition row +INSERT INTO pg_dist_partition (logicalrelid, partmethod, partkey) +VALUES + ('customers'::regclass, 'h', column_name_to_column('customers'::regclass, 'id')); +SELECT partmethod, partkey FROM pg_dist_partition + WHERE logicalrelid = 'customers'::regclass; + partmethod | partkey +------------+------------------------------------------------------------------------------------------------------------------------ + h | {VAR :varno 1 :varattno 1 :vartype 20 :vartypmod -1 :varcollid 0 :varlevelsup 0 :varnoold 1 :varoattno 1 :location -1} +(1 row) + +-- make one huge shard and manually inspect shard row +SELECT create_monolithic_shard_row('customers') AS new_shard_id +\gset +SELECT shardstorage, shardminvalue, shardmaxvalue FROM pg_dist_shard +WHERE shardid = :new_shard_id; + shardstorage | shardminvalue | shardmaxvalue +--------------+---------------+--------------- + t | -2147483648 | 2147483647 +(1 row) + +-- add a placement and manually inspect row +SELECT create_healthy_local_shard_placement_row(:new_shard_id); + create_healthy_local_shard_placement_row +------------------------------------------ + +(1 row) + +SELECT shardstate, nodename, nodeport FROM pg_dist_shard_placement +WHERE shardid = :new_shard_id AND nodename = 'localhost' and nodeport = 5432; + shardstate | nodename | nodeport +------------+-----------+---------- + 1 | localhost | 5432 +(1 row) + +-- mark it as unhealthy and inspect +SELECT update_shard_placement_row_state(:new_shard_id, 'localhost', 5432, 3); + update_shard_placement_row_state +---------------------------------- + t +(1 row) + +SELECT shardstate FROM pg_dist_shard_placement +WHERE shardid = :new_shard_id AND nodename = 'localhost' and nodeport = 5432; + shardstate +------------ + 3 +(1 row) + +-- remove it and verify it is gone +SELECT delete_shard_placement_row(:new_shard_id, 'localhost', 5432); + delete_shard_placement_row +---------------------------- + t +(1 row) + +SELECT COUNT(*) FROM pg_dist_shard_placement +WHERE shardid = :new_shard_id AND nodename = 'localhost' and nodeport = 5432; + count +------- + 0 +(1 row) + +-- deleting or updating a non-existent row should fail +SELECT delete_shard_placement_row(:new_shard_id, 'wrong_localhost', 5432); +ERROR: could not find valid entry for shard placement 103024 on node "wrong_localhost:5432" +SELECT update_shard_placement_row_state(:new_shard_id, 'localhost', 5432, 3); +ERROR: could not find valid entry for shard placement 103024 on node "localhost:5432" +-- now we'll even test our lock methods... +-- use transaction to bound how long we hold the lock +BEGIN; +-- pick up a shard lock and look for it in pg_locks +SELECT acquire_shared_shard_lock(5); + acquire_shared_shard_lock +--------------------------- + +(1 row) + +SELECT objid, mode FROM pg_locks WHERE locktype = 'advisory' AND objid = 5; + objid | mode +-------+----------- + 5 | ShareLock +(1 row) + +-- commit should drop the lock +COMMIT; +-- lock should be gone now +SELECT COUNT(*) FROM pg_locks WHERE locktype = 'advisory' AND objid = 5; + count +------- + 0 +(1 row) + diff --git a/src/test/regress/expected/multi_dropped_column_aliases.out b/src/test/regress/expected/multi_dropped_column_aliases.out new file mode 100644 index 000000000..4329adc63 --- /dev/null +++ b/src/test/regress/expected/multi_dropped_column_aliases.out @@ -0,0 +1,62 @@ +-- Tests that check that our query functionality behaves as expected when the +-- table schema is modified via ALTER statements. +SELECT count(*) FROM customer; + count +------- + 1000 +(1 row) + +SELECT * FROM customer LIMIT 2; + c_custkey | c_name | c_address | c_nationkey | c_phone | c_acctbal | c_mktsegment | c_comment +-----------+--------------------+--------------------------------+-------------+-----------------+-----------+--------------+----------------------------------------------------------------- + 1 | Customer#000000001 | IVhzIApeRb ot,c,E | 15 | 25-989-741-2988 | 711.56 | BUILDING | to the even, regular platelets. regular, ironic epitaphs nag e + 2 | Customer#000000002 | XSTf4,NCwDVaWNe6tEgvwfmRchLXak | 13 | 23-768-687-3665 | 121.65 | AUTOMOBILE | l accounts. blithely ironic theodolites integrate boldly: caref +(2 rows) + +ALTER TABLE customer ADD COLUMN new_column1 INTEGER; +ALTER TABLE customer ADD COLUMN new_column2 INTEGER; +SELECT count(*) FROM customer; + count +------- + 1000 +(1 row) + +SELECT * FROM customer LIMIT 2; + c_custkey | c_name | c_address | c_nationkey | c_phone | c_acctbal | c_mktsegment | c_comment | new_column1 | new_column2 +-----------+--------------------+--------------------------------+-------------+-----------------+-----------+--------------+-----------------------------------------------------------------+-------------+------------- + 1 | Customer#000000001 | IVhzIApeRb ot,c,E | 15 | 25-989-741-2988 | 711.56 | BUILDING | to the even, regular platelets. regular, ironic epitaphs nag e | | + 2 | Customer#000000002 | XSTf4,NCwDVaWNe6tEgvwfmRchLXak | 13 | 23-768-687-3665 | 121.65 | AUTOMOBILE | l accounts. blithely ironic theodolites integrate boldly: caref | | +(2 rows) + +ALTER TABLE customer DROP COLUMN new_column1; +ALTER TABLE customer DROP COLUMN new_column2; +SELECT count(*) FROM customer; + count +------- + 1000 +(1 row) + +SELECT * FROM customer LIMIT 2; + c_custkey | c_name | c_address | c_nationkey | c_phone | c_acctbal | c_mktsegment | c_comment +-----------+--------------------+--------------------------------+-------------+-----------------+-----------+--------------+----------------------------------------------------------------- + 1 | Customer#000000001 | IVhzIApeRb ot,c,E | 15 | 25-989-741-2988 | 711.56 | BUILDING | to the even, regular platelets. regular, ironic epitaphs nag e + 2 | Customer#000000002 | XSTf4,NCwDVaWNe6tEgvwfmRchLXak | 13 | 23-768-687-3665 | 121.65 | AUTOMOBILE | l accounts. blithely ironic theodolites integrate boldly: caref +(2 rows) + +-- Verify joins work with dropped columns. +SELECT count(*) FROM customer, orders WHERE c_custkey = o_custkey; + count +------- + 1955 +(1 row) + +-- Test joinExpr aliases by performing an outer-join. This code path is +-- currently not exercised, but we are adding this test to catch this bug when +-- we start supporting outer joins. +SELECT c_custkey +FROM (customer LEFT OUTER JOIN orders ON (c_custkey = o_custkey)) AS + test(c_custkey, c_nationkey) + INNER JOIN lineitem ON (test.c_custkey = l_orderkey) +LIMIT 10; +ERROR: cannot perform distributed planning on this query +DETAIL: Shards of relations in outer join queries must have 1-to-1 shard partitioning diff --git a/src/test/regress/expected/multi_fdw_create_table.out b/src/test/regress/expected/multi_fdw_create_table.out new file mode 100644 index 000000000..6557e318a --- /dev/null +++ b/src/test/regress/expected/multi_fdw_create_table.out @@ -0,0 +1,103 @@ +-- +-- MULTI_FDW_CREATE_TABLE +-- +-- Create new table definitions for use in testing in distributed foreign data +-- wrapper functionality. +SELECT fdwname FROM pg_foreign_data_wrapper; + fdwname +---------- + file_fdw +(1 row) + +CREATE SERVER file_server FOREIGN DATA WRAPPER file_fdw; +CREATE FOREIGN TABLE lineitem ( + l_orderkey bigint not null, + l_partkey integer not null, + l_suppkey integer not null, + l_linenumber integer not null, + l_quantity decimal(15, 2) not null, + l_extendedprice decimal(15, 2) not null, + l_discount decimal(15, 2) not null, + l_tax decimal(15, 2) not null, + l_returnflag char(1) not null, + l_linestatus char(1) not null, + l_shipdate date not null, + l_commitdate date not null, + l_receiptdate date not null, + l_shipinstruct char(25) not null, + l_shipmode char(10) not null, + l_comment varchar(44) not null) +SERVER file_server +OPTIONS (format 'text', filename '', delimiter '|', null ''); +SELECT master_create_distributed_table('lineitem', 'l_orderkey', 'append'); + master_create_distributed_table +--------------------------------- + +(1 row) + +CREATE FOREIGN TABLE orders ( + o_orderkey bigint not null, + o_custkey integer not null, + o_orderstatus char(1) not null, + o_totalprice decimal(15,2) not null, + o_orderdate date not null, + o_orderpriority char(15) not null, + o_clerk char(15) not null, + o_shippriority integer not null, + o_comment varchar(79) not null) +SERVER file_server +OPTIONS (format 'text', filename '', delimiter '|', null ''); +SELECT master_create_distributed_table('orders', 'o_orderkey', 'append'); + master_create_distributed_table +--------------------------------- + +(1 row) + +CREATE FOREIGN TABLE customer ( + c_custkey integer not null, + c_name varchar(25) not null, + c_address varchar(40) not null, + c_nationkey integer not null, + c_phone char(15) not null, + c_acctbal decimal(15,2) not null, + c_mktsegment char(10) not null, + c_comment varchar(117) not null) +SERVER file_server +OPTIONS (format 'text', filename '', delimiter '|', null ''); +SELECT master_create_distributed_table('customer', 'c_custkey', 'append'); + master_create_distributed_table +--------------------------------- + +(1 row) + +CREATE FOREIGN TABLE nation ( + n_nationkey integer not null, + n_name char(25) not null, + n_regionkey integer not null, + n_comment varchar(152)) +SERVER file_server +OPTIONS (format 'text', filename '', delimiter '|', null ''); +SELECT master_create_distributed_table('nation', 'n_nationkey', 'append'); + master_create_distributed_table +--------------------------------- + +(1 row) + +CREATE FOREIGN TABLE part ( + p_partkey integer not null, + p_name varchar(55) not null, + p_mfgr char(25) not null, + p_brand char(10) not null, + p_type varchar(25) not null, + p_size integer not null, + p_container char(10) not null, + p_retailprice decimal(15,2) not null, + p_comment varchar(23) not null) +SERVER file_server +OPTIONS (format 'text', filename '', delimiter '|', null ''); +SELECT master_create_distributed_table('part', 'p_partkey', 'append'); + master_create_distributed_table +--------------------------------- + +(1 row) + diff --git a/src/test/regress/expected/multi_fdw_master_protocol.out b/src/test/regress/expected/multi_fdw_master_protocol.out new file mode 100644 index 000000000..bffb6d356 --- /dev/null +++ b/src/test/regress/expected/multi_fdw_master_protocol.out @@ -0,0 +1,32 @@ +-- +-- MULTI_FDW_MASTER_PROTOCOL +-- +-- Tests that check the metadata returned by the master node. +SELECT part_storage_type, part_key, part_replica_count, part_max_size, + part_placement_policy FROM master_get_table_metadata('lineitem'); + part_storage_type | part_key | part_replica_count | part_max_size | part_placement_policy +-------------------+------------+--------------------+---------------+----------------------- + f | l_orderkey | 2 | 307200 | 2 +(1 row) + +SELECT * FROM master_get_table_ddl_events('lineitem'); + master_get_table_ddl_events +---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + CREATE EXTENSION IF NOT EXISTS file_fdw WITH SCHEMA public + CREATE SERVER file_server FOREIGN DATA WRAPPER file_fdw + CREATE FOREIGN TABLE lineitem (l_orderkey bigint NOT NULL, l_partkey integer NOT NULL, l_suppkey integer NOT NULL, l_linenumber integer NOT NULL, l_quantity numeric(15,2) NOT NULL, l_extendedprice numeric(15,2) NOT NULL, l_discount numeric(15,2) NOT NULL, l_tax numeric(15,2) NOT NULL, l_returnflag character(1) NOT NULL, l_linestatus character(1) NOT NULL, l_shipdate date NOT NULL, l_commitdate date NOT NULL, l_receiptdate date NOT NULL, l_shipinstruct character(25) NOT NULL, l_shipmode character(10) NOT NULL, l_comment character varying(44) NOT NULL) SERVER file_server OPTIONS (format 'text', filename '', delimiter '|', "null" '') +(3 rows) + +SELECT * FROM master_get_new_shardid(); + master_get_new_shardid +------------------------ + 102008 +(1 row) + +SELECT node_name FROM master_get_local_first_candidate_nodes(); + node_name +----------- + localhost + localhost +(2 rows) + diff --git a/src/test/regress/expected/multi_generate_ddl_commands.out b/src/test/regress/expected/multi_generate_ddl_commands.out new file mode 100644 index 000000000..aa4d58822 --- /dev/null +++ b/src/test/regress/expected/multi_generate_ddl_commands.out @@ -0,0 +1,156 @@ +-- =================================================================== +-- create test functions +-- =================================================================== +CREATE FUNCTION table_ddl_command_array(regclass) + RETURNS text[] + AS 'citusdb' + LANGUAGE C STRICT; +-- =================================================================== +-- test ddl command generation functionality +-- =================================================================== +-- first make sure a simple table works +CREATE TABLE simple_table ( + first_name text, + last_name text, + id bigint +); +SELECT table_ddl_command_array('simple_table'); + table_ddl_command_array +---------------------------------------------------------------------------- + {"CREATE TABLE simple_table (first_name text, last_name text, id bigint)"} +(1 row) + +-- ensure not-null constraints are propagated +CREATE TABLE not_null_table ( + city text, + id bigint not null +); +SELECT table_ddl_command_array('not_null_table'); + table_ddl_command_array +----------------------------------------------------------------- + {"CREATE TABLE not_null_table (city text, id bigint NOT NULL)"} +(1 row) + +-- ensure tables not in search path are schema-prefixed +CREATE SCHEMA not_in_path CREATE TABLE simple_table (id bigint); +NOTICE: CitusDB partially supports CREATE SCHEMA for distributed databases +DETAIL: schema usage in joins and in some UDFs provided by CitusDB are not supported yet +SELECT table_ddl_command_array('not_in_path.simple_table'); + table_ddl_command_array +------------------------------------------------------------------------------------------------- + {"CREATE SCHEMA IF NOT EXISTS not_in_path","CREATE TABLE not_in_path.simple_table (id bigint)"} +(1 row) + +-- even more complex constraints should be preserved... +CREATE TABLE column_constraint_table ( + first_name text, + last_name text, + age int CONSTRAINT non_negative_age CHECK (age >= 0) +); +SELECT table_ddl_command_array('column_constraint_table'); + table_ddl_command_array +--------------------------------------------------------------------------------------------------------------------------------------- + {"CREATE TABLE column_constraint_table (first_name text, last_name text, age integer, CONSTRAINT non_negative_age CHECK (age >= 0))"} +(1 row) + +-- including table constraints +CREATE TABLE table_constraint_table ( + bid_item_id bigint, + min_bid decimal not null, + max_bid decimal not null, + CONSTRAINT bids_ordered CHECK (min_bid > max_bid) +); +SELECT table_ddl_command_array('table_constraint_table'); + table_ddl_command_array +--------------------------------------------------------------------------------------------------------------------------------------------------------------------- + {"CREATE TABLE table_constraint_table (bid_item_id bigint, min_bid numeric NOT NULL, max_bid numeric NOT NULL, CONSTRAINT bids_ordered CHECK (min_bid > max_bid))"} +(1 row) + +-- default values are supported +CREATE TABLE default_value_table ( + name text, + price decimal default 0.00 +); +SELECT table_ddl_command_array('default_value_table'); + table_ddl_command_array +------------------------------------------------------------------------------ + {"CREATE TABLE default_value_table (name text, price numeric DEFAULT 0.00)"} +(1 row) + +-- of course primary keys work... +CREATE TABLE pkey_table ( + first_name text, + last_name text, + id bigint PRIMARY KEY +); +SELECT table_ddl_command_array('pkey_table'); + table_ddl_command_array +----------------------------------------------------------------------------------------------------------------------------------------------------------------- + {"CREATE TABLE pkey_table (first_name text, last_name text, id bigint NOT NULL)","ALTER TABLE ONLY pkey_table ADD CONSTRAINT pkey_table_pkey PRIMARY KEY (id)"} +(1 row) + +-- as do unique indexes... +CREATE TABLE unique_table ( + user_id bigint not null, + username text UNIQUE not null +); +SELECT table_ddl_command_array('unique_table'); + table_ddl_command_array +---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + {"CREATE TABLE unique_table (user_id bigint NOT NULL, username text NOT NULL)","ALTER TABLE ONLY unique_table ADD CONSTRAINT unique_table_username_key UNIQUE (username)"} +(1 row) + +-- and indexes used for clustering +CREATE TABLE clustered_table ( + data json not null, + received_at timestamp not null +); +CREATE INDEX clustered_time_idx ON clustered_table (received_at); +CLUSTER clustered_table USING clustered_time_idx; +SELECT table_ddl_command_array('clustered_table'); + table_ddl_command_array +---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + {"CREATE TABLE clustered_table (data json NOT NULL, received_at timestamp without time zone NOT NULL)","CREATE INDEX clustered_time_idx ON clustered_table USING btree (received_at)","ALTER TABLE clustered_table CLUSTER ON clustered_time_idx"} +(1 row) + +-- fiddly things like storage type and statistics also work +CREATE TABLE fiddly_table ( + hostname char(255) not null, + os char(255) not null, + ip_addr inet not null, + traceroute text not null +); +ALTER TABLE fiddly_table + ALTER hostname SET STORAGE PLAIN, + ALTER os SET STORAGE MAIN, + ALTER ip_addr SET STORAGE EXTENDED, + ALTER traceroute SET STORAGE EXTERNAL, + ALTER ip_addr SET STATISTICS 500; +SELECT table_ddl_command_array('fiddly_table'); + table_ddl_command_array +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + {"CREATE TABLE fiddly_table (hostname character(255) NOT NULL, os character(255) NOT NULL, ip_addr inet NOT NULL, traceroute text NOT NULL)","ALTER TABLE ONLY fiddly_table ALTER COLUMN hostname SET STORAGE PLAIN, ALTER COLUMN os SET STORAGE MAIN, ALTER COLUMN ip_addr SET STORAGE EXTENDED, ALTER COLUMN ip_addr SET STATISTICS 500, ALTER COLUMN traceroute SET STORAGE EXTERNAL"} +(1 row) + +-- test foreign tables using fake FDW +CREATE FOREIGN TABLE foreign_table ( + id bigint not null, + full_name text not null default '' +) SERVER fake_fdw_server OPTIONS (encoding 'utf-8', compression 'true'); +SELECT table_ddl_command_array('foreign_table'); +NOTICE: foreign-data wrapper "fake_fdw" does not have an extension defined + table_ddl_command_array +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + {"CREATE SERVER fake_fdw_server FOREIGN DATA WRAPPER fake_fdw","CREATE FOREIGN TABLE foreign_table (id bigint NOT NULL, full_name text DEFAULT ''::text NOT NULL) SERVER fake_fdw_server OPTIONS (encoding 'utf-8', compression 'true')"} +(1 row) + +-- propagating views is not supported +CREATE VIEW local_view AS SELECT * FROM simple_table; +SELECT table_ddl_command_array('local_view'); +ERROR: local_view is not a regular or foreign table +-- clean up +DROP VIEW IF EXISTS local_view; +DROP FOREIGN TABLE IF EXISTS foreign_table; +DROP TABLE IF EXISTS simple_table, not_null_table, column_constraint_table, + table_constraint_table, default_value_table, pkey_table, + unique_table, clustered_table, fiddly_table; diff --git a/src/test/regress/expected/multi_generate_ddl_commands_0.out b/src/test/regress/expected/multi_generate_ddl_commands_0.out new file mode 100644 index 000000000..1d042bc26 --- /dev/null +++ b/src/test/regress/expected/multi_generate_ddl_commands_0.out @@ -0,0 +1,156 @@ +-- =================================================================== +-- create test functions +-- =================================================================== +CREATE FUNCTION table_ddl_command_array(regclass) + RETURNS text[] + AS 'citusdb' + LANGUAGE C STRICT; +-- =================================================================== +-- test ddl command generation functionality +-- =================================================================== +-- first make sure a simple table works +CREATE TABLE simple_table ( + first_name text, + last_name text, + id bigint +); +SELECT table_ddl_command_array('simple_table'); + table_ddl_command_array +---------------------------------------------------------------------------- + {"CREATE TABLE simple_table (first_name text, last_name text, id bigint)"} +(1 row) + +-- ensure not-null constraints are propagated +CREATE TABLE not_null_table ( + city text, + id bigint not null +); +SELECT table_ddl_command_array('not_null_table'); + table_ddl_command_array +----------------------------------------------------------------- + {"CREATE TABLE not_null_table (city text, id bigint NOT NULL)"} +(1 row) + +-- ensure tables not in search path are schema-prefixed +CREATE SCHEMA not_in_path CREATE TABLE simple_table (id bigint); +NOTICE: CitusDB partially supports CREATE SCHEMA for distributed databases +DETAIL: schema usage in joins and in some UDFs provided by CitusDB are not supported yet +SELECT table_ddl_command_array('not_in_path.simple_table'); + table_ddl_command_array +------------------------------------------------------------------------------------------------- + {"CREATE SCHEMA IF NOT EXISTS not_in_path","CREATE TABLE not_in_path.simple_table (id bigint)"} +(1 row) + +-- even more complex constraints should be preserved... +CREATE TABLE column_constraint_table ( + first_name text, + last_name text, + age int CONSTRAINT non_negative_age CHECK (age >= 0) +); +SELECT table_ddl_command_array('column_constraint_table'); + table_ddl_command_array +--------------------------------------------------------------------------------------------------------------------------------------- + {"CREATE TABLE column_constraint_table (first_name text, last_name text, age integer, CONSTRAINT non_negative_age CHECK (age >= 0))"} +(1 row) + +-- including table constraints +CREATE TABLE table_constraint_table ( + bid_item_id bigint, + min_bid decimal not null, + max_bid decimal not null, + CONSTRAINT bids_ordered CHECK (min_bid > max_bid) +); +SELECT table_ddl_command_array('table_constraint_table'); + table_ddl_command_array +--------------------------------------------------------------------------------------------------------------------------------------------------------------------- + {"CREATE TABLE table_constraint_table (bid_item_id bigint, min_bid numeric NOT NULL, max_bid numeric NOT NULL, CONSTRAINT bids_ordered CHECK (min_bid > max_bid))"} +(1 row) + +-- default values are supported +CREATE TABLE default_value_table ( + name text, + price decimal default 0.00 +); +SELECT table_ddl_command_array('default_value_table'); + table_ddl_command_array +------------------------------------------------------------------------------ + {"CREATE TABLE default_value_table (name text, price numeric DEFAULT 0.00)"} +(1 row) + +-- of course primary keys work... +CREATE TABLE pkey_table ( + first_name text, + last_name text, + id bigint PRIMARY KEY +); +SELECT table_ddl_command_array('pkey_table'); + table_ddl_command_array +------------------------------------------------------------------------------------------------------------------------------------------------------------------- + {"CREATE TABLE pkey_table (first_name text, last_name text, id bigint NOT NULL)","ALTER TABLE public.pkey_table ADD CONSTRAINT pkey_table_pkey PRIMARY KEY (id)"} +(1 row) + +-- as do unique indexes... +CREATE TABLE unique_table ( + user_id bigint not null, + username text UNIQUE not null +); +SELECT table_ddl_command_array('unique_table'); + table_ddl_command_array +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ + {"CREATE TABLE unique_table (user_id bigint NOT NULL, username text NOT NULL)","ALTER TABLE public.unique_table ADD CONSTRAINT unique_table_username_key UNIQUE (username)"} +(1 row) + +-- and indexes used for clustering +CREATE TABLE clustered_table ( + data json not null, + received_at timestamp not null +); +CREATE INDEX clustered_time_idx ON clustered_table (received_at); +CLUSTER clustered_table USING clustered_time_idx; +SELECT table_ddl_command_array('clustered_table'); + table_ddl_command_array +---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + {"CREATE TABLE clustered_table (data json NOT NULL, received_at timestamp without time zone NOT NULL)","CREATE INDEX clustered_time_idx ON clustered_table USING btree (received_at)","ALTER TABLE clustered_table CLUSTER ON clustered_time_idx"} +(1 row) + +-- fiddly things like storage type and statistics also work +CREATE TABLE fiddly_table ( + hostname char(255) not null, + os char(255) not null, + ip_addr inet not null, + traceroute text not null +); +ALTER TABLE fiddly_table + ALTER hostname SET STORAGE PLAIN, + ALTER os SET STORAGE MAIN, + ALTER ip_addr SET STORAGE EXTENDED, + ALTER traceroute SET STORAGE EXTERNAL, + ALTER ip_addr SET STATISTICS 500; +SELECT table_ddl_command_array('fiddly_table'); + table_ddl_command_array +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + {"CREATE TABLE fiddly_table (hostname character(255) NOT NULL, os character(255) NOT NULL, ip_addr inet NOT NULL, traceroute text NOT NULL)","ALTER TABLE ONLY fiddly_table ALTER COLUMN hostname SET STORAGE PLAIN, ALTER COLUMN os SET STORAGE MAIN, ALTER COLUMN ip_addr SET STORAGE EXTENDED, ALTER COLUMN ip_addr SET STATISTICS 500, ALTER COLUMN traceroute SET STORAGE EXTERNAL"} +(1 row) + +-- test foreign tables using fake FDW +CREATE FOREIGN TABLE foreign_table ( + id bigint not null, + full_name text not null default '' +) SERVER fake_fdw_server OPTIONS (encoding 'utf-8', compression 'true'); +SELECT table_ddl_command_array('foreign_table'); +NOTICE: foreign-data wrapper "fake_fdw" does not have an extension defined + table_ddl_command_array +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + {"CREATE SERVER fake_fdw_server FOREIGN DATA WRAPPER fake_fdw","CREATE FOREIGN TABLE foreign_table (id bigint NOT NULL, full_name text DEFAULT ''::text NOT NULL) SERVER fake_fdw_server OPTIONS (encoding 'utf-8', compression 'true')"} +(1 row) + +-- propagating views is not supported +CREATE VIEW local_view AS SELECT * FROM simple_table; +SELECT table_ddl_command_array('local_view'); +ERROR: local_view is not a regular or foreign table +-- clean up +DROP VIEW IF EXISTS local_view; +DROP FOREIGN TABLE IF EXISTS foreign_table; +DROP TABLE IF EXISTS simple_table, not_null_table, column_constraint_table, + table_constraint_table, default_value_table, pkey_table, + unique_table, clustered_table, fiddly_table; diff --git a/src/test/regress/expected/multi_hash_pruning.out b/src/test/regress/expected/multi_hash_pruning.out new file mode 100644 index 000000000..bec70984f --- /dev/null +++ b/src/test/regress/expected/multi_hash_pruning.out @@ -0,0 +1,244 @@ +-- +-- MULTI_HASH_PRUNING +-- +-- Tests for shard and join pruning logic on hash partitioned tables. +-- Create a table partitioned on integer column and update partition type to +-- hash. Then stage data to this table and update shard min max values with +-- hashed ones. Hash value of 1, 2, 3 and 4 are consecutively -1905060026, +-- 1134484726, -28094569 and -1011077333. +CREATE TABLE orders_hash_partitioned ( + o_orderkey integer, + o_custkey integer, + o_orderstatus char(1), + o_totalprice decimal(15,2), + o_orderdate date, + o_orderpriority char(15), + o_clerk char(15), + o_shippriority integer, + o_comment varchar(79) ); +SELECT master_create_distributed_table('orders_hash_partitioned', 'o_orderkey', 'append'); + master_create_distributed_table +--------------------------------- + +(1 row) + +UPDATE pg_dist_partition SET partmethod = 'h' + WHERE logicalrelid = 'orders_hash_partitioned'::regclass; +-- Create logical shards with shardids 110, 111, 112 and 113 +INSERT INTO pg_dist_shard (logicalrelid, shardid, shardstorage, shardminvalue, shardmaxvalue) + VALUES ('orders_hash_partitioned'::regclass, 110, 't', -1905060026, -1905060026), + ('orders_hash_partitioned'::regclass, 111, 't', 1134484726, 1134484726), + ('orders_hash_partitioned'::regclass, 112, 't', -1905060026, -28094569), + ('orders_hash_partitioned'::regclass, 113, 't', -1011077333, 0); +-- Create shard placements for shards 110, 111, 112 and 113 +INSERT INTO pg_dist_shard_placement (shardid, shardstate, shardlength, nodename, nodeport) + SELECT 110, 1, 1, nodename, nodeport + FROM pg_dist_shard_placement + GROUP BY nodename, nodeport + ORDER BY nodename, nodeport ASC + LIMIT 1; +INSERT INTO pg_dist_shard_placement (shardid, shardstate, shardlength, nodename, nodeport) + SELECT 111, 1, 1, nodename, nodeport + FROM pg_dist_shard_placement + GROUP BY nodename, nodeport + ORDER BY nodename, nodeport ASC + LIMIT 1; +INSERT INTO pg_dist_shard_placement (shardid, shardstate, shardlength, nodename, nodeport) + SELECT 112, 1, 1, nodename, nodeport + FROM pg_dist_shard_placement + GROUP BY nodename, nodeport + ORDER BY nodename, nodeport ASC + LIMIT 1; +INSERT INTO pg_dist_shard_placement (shardid, shardstate, shardlength, nodename, nodeport) + SELECT 113, 1, 1, nodename, nodeport + FROM pg_dist_shard_placement + GROUP BY nodename, nodeport + ORDER BY nodename, nodeport ASC + LIMIT 1; +SET client_min_messages TO DEBUG2; +-- Check that we can prune shards for simple cases, boolean expressions and +-- immutable functions. +EXPLAIN SELECT count(*) FROM orders_hash_partitioned; + QUERY PLAN +---------------------------------------------------------------------- + explain statements for distributed queries are currently unsupported +(1 row) + +EXPLAIN SELECT count(*) FROM orders_hash_partitioned WHERE o_orderkey = 1; +DEBUG: predicate pruning for shardId 113 +DEBUG: predicate pruning for shardId 111 + QUERY PLAN +---------------------------------------------------------------------- + explain statements for distributed queries are currently unsupported +(1 row) + +EXPLAIN SELECT count(*) FROM orders_hash_partitioned WHERE o_orderkey = 2; +DEBUG: predicate pruning for shardId 113 +DEBUG: predicate pruning for shardId 112 +DEBUG: predicate pruning for shardId 110 + QUERY PLAN +---------------------------------------------------------------------- + explain statements for distributed queries are currently unsupported +(1 row) + +EXPLAIN SELECT count(*) FROM orders_hash_partitioned WHERE o_orderkey = 3; +DEBUG: predicate pruning for shardId 111 +DEBUG: predicate pruning for shardId 110 + QUERY PLAN +---------------------------------------------------------------------- + explain statements for distributed queries are currently unsupported +(1 row) + +EXPLAIN SELECT count(*) FROM orders_hash_partitioned WHERE o_orderkey = 4; +DEBUG: predicate pruning for shardId 111 +DEBUG: predicate pruning for shardId 110 + QUERY PLAN +---------------------------------------------------------------------- + explain statements for distributed queries are currently unsupported +(1 row) + +EXPLAIN SELECT count(*) FROM orders_hash_partitioned WHERE o_orderkey is NULL; +DEBUG: predicate pruning for shardId 112 +DEBUG: predicate pruning for shardId 111 +DEBUG: predicate pruning for shardId 110 + QUERY PLAN +---------------------------------------------------------------------- + explain statements for distributed queries are currently unsupported +(1 row) + +EXPLAIN SELECT count(*) FROM orders_hash_partitioned WHERE o_orderkey is not NULL; + QUERY PLAN +---------------------------------------------------------------------- + explain statements for distributed queries are currently unsupported +(1 row) + +EXPLAIN SELECT count(*) FROM orders_hash_partitioned WHERE o_orderkey > 2; + QUERY PLAN +---------------------------------------------------------------------- + explain statements for distributed queries are currently unsupported +(1 row) + +EXPLAIN SELECT count(*) FROM orders_hash_partitioned + WHERE o_orderkey = 1 OR o_orderkey = 2; +DEBUG: predicate pruning for shardId 113 + QUERY PLAN +---------------------------------------------------------------------- + explain statements for distributed queries are currently unsupported +(1 row) + +EXPLAIN SELECT count(*) FROM orders_hash_partitioned + WHERE o_orderkey = 1 OR o_clerk = 'aaa'; + QUERY PLAN +---------------------------------------------------------------------- + explain statements for distributed queries are currently unsupported +(1 row) + +EXPLAIN SELECT count(*) FROM orders_hash_partitioned + WHERE o_orderkey = 1 AND o_clerk = 'aaa'; +DEBUG: predicate pruning for shardId 113 +DEBUG: predicate pruning for shardId 111 + QUERY PLAN +---------------------------------------------------------------------- + explain statements for distributed queries are currently unsupported +(1 row) + +EXPLAIN SELECT count(*) FROM orders_hash_partitioned + WHERE o_orderkey = 1 OR (o_orderkey = 3 AND o_clerk = 'aaa'); +DEBUG: predicate pruning for shardId 111 + QUERY PLAN +---------------------------------------------------------------------- + explain statements for distributed queries are currently unsupported +(1 row) + +EXPLAIN SELECT count(*) FROM orders_hash_partitioned + WHERE o_orderkey = 1 OR o_orderkey is NULL; +DEBUG: predicate pruning for shardId 111 + QUERY PLAN +---------------------------------------------------------------------- + explain statements for distributed queries are currently unsupported +(1 row) + +EXPLAIN SELECT count(*) FROM + (SELECT o_orderkey FROM orders_hash_partitioned WHERE o_orderkey = 1) AS orderkeys; +DEBUG: predicate pruning for shardId 113 +DEBUG: predicate pruning for shardId 111 + QUERY PLAN +---------------------------------------------------------------------- + explain statements for distributed queries are currently unsupported +(1 row) + +EXPLAIN SELECT count(*) FROM orders_hash_partitioned WHERE o_orderkey = abs(-1); +DEBUG: predicate pruning for shardId 113 +DEBUG: predicate pruning for shardId 111 + QUERY PLAN +---------------------------------------------------------------------- + explain statements for distributed queries are currently unsupported +(1 row) + +-- Check that we don't support pruning for ANY (array expression) +EXPLAIN SELECT count(*) FROM orders_hash_partitioned + WHERE o_orderkey = 1 OR o_totalprice IN (2, 5); +NOTICE: cannot use shard pruning with ANY (array expression) +HINT: Consider rewriting the expression with OR clauses. + QUERY PLAN +---------------------------------------------------------------------- + explain statements for distributed queries are currently unsupported +(1 row) + +-- Check that we cannot prune for mutable functions. +EXPLAIN SELECT count(*) FROM orders_hash_partitioned WHERE o_orderkey = random(); + QUERY PLAN +---------------------------------------------------------------------- + explain statements for distributed queries are currently unsupported +(1 row) + +EXPLAIN SELECT count(*) FROM orders_hash_partitioned + WHERE o_orderkey = random() OR o_orderkey = 1; + QUERY PLAN +---------------------------------------------------------------------- + explain statements for distributed queries are currently unsupported +(1 row) + +EXPLAIN SELECT count(*) FROM orders_hash_partitioned + WHERE o_orderkey = random() AND o_orderkey = 1; +DEBUG: predicate pruning for shardId 113 +DEBUG: predicate pruning for shardId 111 + QUERY PLAN +---------------------------------------------------------------------- + explain statements for distributed queries are currently unsupported +(1 row) + +-- Check that we can do join pruning. +EXPLAIN SELECT count(*) + FROM orders_hash_partitioned orders1, orders_hash_partitioned orders2 + WHERE orders1.o_orderkey = orders2.o_orderkey; +DEBUG: join prunable for intervals [-1011077333,0] and [1134484726,1134484726] +DEBUG: join prunable for intervals [-1011077333,0] and [-1905060026,-1905060026] +DEBUG: join prunable for intervals [-1905060026,-28094569] and [1134484726,1134484726] +DEBUG: join prunable for intervals [1134484726,1134484726] and [-1011077333,0] +DEBUG: join prunable for intervals [1134484726,1134484726] and [-1905060026,-28094569] +DEBUG: join prunable for intervals [1134484726,1134484726] and [-1905060026,-1905060026] +DEBUG: join prunable for intervals [-1905060026,-1905060026] and [-1011077333,0] +DEBUG: join prunable for intervals [-1905060026,-1905060026] and [1134484726,1134484726] + QUERY PLAN +---------------------------------------------------------------------- + explain statements for distributed queries are currently unsupported +(1 row) + +EXPLAIN SELECT count(*) + FROM orders_hash_partitioned orders1, orders_hash_partitioned orders2 + WHERE orders1.o_orderkey = orders2.o_orderkey + AND orders1.o_orderkey = 1 + AND orders2.o_orderkey is NULL; +DEBUG: predicate pruning for shardId 113 +DEBUG: predicate pruning for shardId 111 +DEBUG: predicate pruning for shardId 112 +DEBUG: predicate pruning for shardId 111 +DEBUG: predicate pruning for shardId 110 +DEBUG: join prunable for intervals [-1905060026,-1905060026] and [-1011077333,0] + QUERY PLAN +---------------------------------------------------------------------- + explain statements for distributed queries are currently unsupported +(1 row) + +SET client_min_messages TO NOTICE; diff --git a/src/test/regress/expected/multi_index_statements.out b/src/test/regress/expected/multi_index_statements.out new file mode 100644 index 000000000..245e2870f --- /dev/null +++ b/src/test/regress/expected/multi_index_statements.out @@ -0,0 +1,191 @@ +-- +-- MULTI_INDEX_STATEMENTS +-- +-- Check that we can run CREATE INDEX and DROP INDEX statements on distributed +-- tables. We increase the logging verbosity to verify that commands are +-- propagated to all worker shards. +SET client_min_messages TO DEBUG2; +-- +-- CREATE INDEX +-- +-- Verify that we can create different types of indexes +CREATE INDEX lineitem_orderkey_index ON lineitem (l_orderkey); +DEBUG: applied command on shard 102014 on node localhost:57637 +DEBUG: applied command on shard 102014 on node localhost:57638 +DEBUG: applied command on shard 102013 on node localhost:57637 +DEBUG: applied command on shard 102013 on node localhost:57638 +DEBUG: applied command on shard 102012 on node localhost:57637 +DEBUG: applied command on shard 102012 on node localhost:57638 +DEBUG: applied command on shard 102011 on node localhost:57637 +DEBUG: applied command on shard 102011 on node localhost:57638 +DEBUG: applied command on shard 102010 on node localhost:57637 +DEBUG: applied command on shard 102010 on node localhost:57638 +DEBUG: applied command on shard 102009 on node localhost:57637 +DEBUG: applied command on shard 102009 on node localhost:57638 +DEBUG: building index "lineitem_orderkey_index" on table "lineitem" +CREATE INDEX lineitem_partkey_desc_index ON lineitem (l_partkey DESC); +DEBUG: applied command on shard 102014 on node localhost:57637 +DEBUG: applied command on shard 102014 on node localhost:57638 +DEBUG: applied command on shard 102013 on node localhost:57637 +DEBUG: applied command on shard 102013 on node localhost:57638 +DEBUG: applied command on shard 102012 on node localhost:57637 +DEBUG: applied command on shard 102012 on node localhost:57638 +DEBUG: applied command on shard 102011 on node localhost:57637 +DEBUG: applied command on shard 102011 on node localhost:57638 +DEBUG: applied command on shard 102010 on node localhost:57637 +DEBUG: applied command on shard 102010 on node localhost:57638 +DEBUG: applied command on shard 102009 on node localhost:57637 +DEBUG: applied command on shard 102009 on node localhost:57638 +DEBUG: building index "lineitem_partkey_desc_index" on table "lineitem" +CREATE INDEX lineitem_partial_index ON lineitem (l_shipdate) + WHERE l_shipdate < '1995-01-01'; +DEBUG: applied command on shard 102014 on node localhost:57637 +DEBUG: applied command on shard 102014 on node localhost:57638 +DEBUG: applied command on shard 102013 on node localhost:57637 +DEBUG: applied command on shard 102013 on node localhost:57638 +DEBUG: applied command on shard 102012 on node localhost:57637 +DEBUG: applied command on shard 102012 on node localhost:57638 +DEBUG: applied command on shard 102011 on node localhost:57637 +DEBUG: applied command on shard 102011 on node localhost:57638 +DEBUG: applied command on shard 102010 on node localhost:57637 +DEBUG: applied command on shard 102010 on node localhost:57638 +DEBUG: applied command on shard 102009 on node localhost:57637 +DEBUG: applied command on shard 102009 on node localhost:57638 +DEBUG: building index "lineitem_partial_index" on table "lineitem" +CREATE INDEX lineitem_orderkey_hash_index ON lineitem USING hash (l_partkey); +DEBUG: applied command on shard 102014 on node localhost:57637 +DEBUG: applied command on shard 102014 on node localhost:57638 +DEBUG: applied command on shard 102013 on node localhost:57637 +DEBUG: applied command on shard 102013 on node localhost:57638 +DEBUG: applied command on shard 102012 on node localhost:57637 +DEBUG: applied command on shard 102012 on node localhost:57638 +DEBUG: applied command on shard 102011 on node localhost:57637 +DEBUG: applied command on shard 102011 on node localhost:57638 +DEBUG: applied command on shard 102010 on node localhost:57637 +DEBUG: applied command on shard 102010 on node localhost:57638 +DEBUG: applied command on shard 102009 on node localhost:57637 +DEBUG: applied command on shard 102009 on node localhost:57638 +DEBUG: building index "lineitem_orderkey_hash_index" on table "lineitem" +-- Verify that all indexes got created on the master node +SELECT * FROM pg_indexes WHERE tablename = 'lineitem' ORDER BY indexname; + schemaname | tablename | indexname | tablespace | indexdef +------------+-----------+------------------------------+------------+------------------------------------------------------------------------------------------------------------------ + public | lineitem | lineitem_orderkey_hash_index | | CREATE INDEX lineitem_orderkey_hash_index ON lineitem USING hash (l_partkey) + public | lineitem | lineitem_orderkey_index | | CREATE INDEX lineitem_orderkey_index ON lineitem USING btree (l_orderkey) + public | lineitem | lineitem_partial_index | | CREATE INDEX lineitem_partial_index ON lineitem USING btree (l_shipdate) WHERE (l_shipdate < '01-01-1995'::date) + public | lineitem | lineitem_partkey_desc_index | | CREATE INDEX lineitem_partkey_desc_index ON lineitem USING btree (l_partkey DESC) + public | lineitem | lineitem_pkey | | CREATE UNIQUE INDEX lineitem_pkey ON lineitem USING btree (l_orderkey, l_linenumber) + public | lineitem | lineitem_time_index | | CREATE INDEX lineitem_time_index ON lineitem USING btree (l_shipdate) +(6 rows) + +-- Verify that we error out on unsupported statement types +CREATE INDEX CONCURRENTLY try_index ON lineitem (l_orderkey); +ERROR: creating indexes concurrently on distributed tables is currently unsupported +CREATE UNIQUE INDEX try_index ON lineitem (l_orderkey); +ERROR: creating unique indexes on distributed tables is currently unsupported +CREATE INDEX try_index ON lineitem (l_orderkey) TABLESPACE newtablespace; +ERROR: specifying tablespaces with CREATE INDEX statements is currently unsupported +-- Verify that we error out in case of postgres errors on supported statement +-- types. +CREATE INDEX lineitem_orderkey_index ON lineitem (l_orderkey); +WARNING: could not receive query results from localhost:57637 +DETAIL: Client error: relation "lineitem_orderkey_index_102014" already exists +ERROR: could not execute DDL command on worker node shards +CREATE INDEX try_index ON lineitem USING gist (l_orderkey); +WARNING: could not receive query results from localhost:57637 +DETAIL: Client error: data type bigint has no default operator class for access method "gist" +ERROR: could not execute DDL command on worker node shards +CREATE INDEX try_index ON lineitem (non_existent_column); +WARNING: could not receive query results from localhost:57637 +DETAIL: Client error: column "non_existent_column" does not exist +ERROR: could not execute DDL command on worker node shards +-- Verify that none of failed indexes got created on the master node +SELECT * FROM pg_indexes WHERE tablename = 'lineitem' ORDER BY indexname; + schemaname | tablename | indexname | tablespace | indexdef +------------+-----------+------------------------------+------------+------------------------------------------------------------------------------------------------------------------ + public | lineitem | lineitem_orderkey_hash_index | | CREATE INDEX lineitem_orderkey_hash_index ON lineitem USING hash (l_partkey) + public | lineitem | lineitem_orderkey_index | | CREATE INDEX lineitem_orderkey_index ON lineitem USING btree (l_orderkey) + public | lineitem | lineitem_partial_index | | CREATE INDEX lineitem_partial_index ON lineitem USING btree (l_shipdate) WHERE (l_shipdate < '01-01-1995'::date) + public | lineitem | lineitem_partkey_desc_index | | CREATE INDEX lineitem_partkey_desc_index ON lineitem USING btree (l_partkey DESC) + public | lineitem | lineitem_pkey | | CREATE UNIQUE INDEX lineitem_pkey ON lineitem USING btree (l_orderkey, l_linenumber) + public | lineitem | lineitem_time_index | | CREATE INDEX lineitem_time_index ON lineitem USING btree (l_shipdate) +(6 rows) + +-- +-- DROP INDEX +-- +-- Verify that we can't drop multiple indexes in a single command +DROP INDEX lineitem_orderkey_index, lineitem_partial_index; +ERROR: cannot drop multiple distributed objects in a single command +HINT: Try dropping each object in a separate DROP command. +-- Verify that we error out on the CONCURRENTLY clause +DROP INDEX CONCURRENTLY lineitem_orderkey_index; +ERROR: dropping indexes concurrently on distributed tables is currently unsupported +-- Verify that we can succesfully drop indexes +DROP INDEX lineitem_orderkey_index; +DEBUG: applied command on shard 102014 on node localhost:57637 +DEBUG: applied command on shard 102014 on node localhost:57638 +DEBUG: applied command on shard 102013 on node localhost:57637 +DEBUG: applied command on shard 102013 on node localhost:57638 +DEBUG: applied command on shard 102012 on node localhost:57637 +DEBUG: applied command on shard 102012 on node localhost:57638 +DEBUG: applied command on shard 102011 on node localhost:57637 +DEBUG: applied command on shard 102011 on node localhost:57638 +DEBUG: applied command on shard 102010 on node localhost:57637 +DEBUG: applied command on shard 102010 on node localhost:57638 +DEBUG: applied command on shard 102009 on node localhost:57637 +DEBUG: applied command on shard 102009 on node localhost:57638 +DROP INDEX lineitem_partkey_desc_index; +DEBUG: applied command on shard 102014 on node localhost:57637 +DEBUG: applied command on shard 102014 on node localhost:57638 +DEBUG: applied command on shard 102013 on node localhost:57637 +DEBUG: applied command on shard 102013 on node localhost:57638 +DEBUG: applied command on shard 102012 on node localhost:57637 +DEBUG: applied command on shard 102012 on node localhost:57638 +DEBUG: applied command on shard 102011 on node localhost:57637 +DEBUG: applied command on shard 102011 on node localhost:57638 +DEBUG: applied command on shard 102010 on node localhost:57637 +DEBUG: applied command on shard 102010 on node localhost:57638 +DEBUG: applied command on shard 102009 on node localhost:57637 +DEBUG: applied command on shard 102009 on node localhost:57638 +DROP INDEX lineitem_partial_index; +DEBUG: applied command on shard 102014 on node localhost:57637 +DEBUG: applied command on shard 102014 on node localhost:57638 +DEBUG: applied command on shard 102013 on node localhost:57637 +DEBUG: applied command on shard 102013 on node localhost:57638 +DEBUG: applied command on shard 102012 on node localhost:57637 +DEBUG: applied command on shard 102012 on node localhost:57638 +DEBUG: applied command on shard 102011 on node localhost:57637 +DEBUG: applied command on shard 102011 on node localhost:57638 +DEBUG: applied command on shard 102010 on node localhost:57637 +DEBUG: applied command on shard 102010 on node localhost:57638 +DEBUG: applied command on shard 102009 on node localhost:57637 +DEBUG: applied command on shard 102009 on node localhost:57638 +-- Verify that we handle if exists statements correctly +DROP INDEX non_existent_index; +ERROR: index "non_existent_index" does not exist +DROP INDEX IF EXISTS non_existent_index; +NOTICE: index "non_existent_index" does not exist, skipping +DROP INDEX IF EXISTS lineitem_orderkey_hash_index; +DEBUG: applied command on shard 102014 on node localhost:57637 +DEBUG: applied command on shard 102014 on node localhost:57638 +DEBUG: applied command on shard 102013 on node localhost:57637 +DEBUG: applied command on shard 102013 on node localhost:57638 +DEBUG: applied command on shard 102012 on node localhost:57637 +DEBUG: applied command on shard 102012 on node localhost:57638 +DEBUG: applied command on shard 102011 on node localhost:57637 +DEBUG: applied command on shard 102011 on node localhost:57638 +DEBUG: applied command on shard 102010 on node localhost:57637 +DEBUG: applied command on shard 102010 on node localhost:57638 +DEBUG: applied command on shard 102009 on node localhost:57637 +DEBUG: applied command on shard 102009 on node localhost:57638 +DROP INDEX lineitem_orderkey_hash_index; +ERROR: index "lineitem_orderkey_hash_index" does not exist +-- Verify that all the indexes are also dropped from the master node +SELECT * FROM pg_indexes WHERE tablename = 'lineitem' ORDER BY indexname; + schemaname | tablename | indexname | tablespace | indexdef +------------+-----------+---------------------+------------+-------------------------------------------------------------------------------------- + public | lineitem | lineitem_pkey | | CREATE UNIQUE INDEX lineitem_pkey ON lineitem USING btree (l_orderkey, l_linenumber) + public | lineitem | lineitem_time_index | | CREATE INDEX lineitem_time_index ON lineitem USING btree (l_shipdate) +(2 rows) + diff --git a/src/test/regress/expected/multi_index_statements_0.out b/src/test/regress/expected/multi_index_statements_0.out new file mode 100644 index 000000000..e7cc610e4 --- /dev/null +++ b/src/test/regress/expected/multi_index_statements_0.out @@ -0,0 +1,196 @@ +-- +-- MULTI_INDEX_STATEMENTS +-- +-- Check that we can run CREATE INDEX and DROP INDEX statements on distributed +-- tables. We increase the logging verbosity to verify that commands are +-- propagated to all worker shards. +SET client_min_messages TO DEBUG2; +-- +-- CREATE INDEX +-- +-- Verify that we can create different types of indexes +CREATE INDEX lineitem_orderkey_index ON lineitem (l_orderkey); +DEBUG: applied command on shard 102014 on node localhost:57637 +DEBUG: applied command on shard 102014 on node localhost:57638 +DEBUG: applied command on shard 102013 on node localhost:57637 +DEBUG: applied command on shard 102013 on node localhost:57638 +DEBUG: applied command on shard 102012 on node localhost:57637 +DEBUG: applied command on shard 102012 on node localhost:57638 +DEBUG: applied command on shard 102011 on node localhost:57637 +DEBUG: applied command on shard 102011 on node localhost:57638 +DEBUG: applied command on shard 102010 on node localhost:57637 +DEBUG: applied command on shard 102010 on node localhost:57638 +DEBUG: applied command on shard 102009 on node localhost:57637 +DEBUG: applied command on shard 102009 on node localhost:57638 +DEBUG: building index "lineitem_orderkey_index" on table "lineitem" +CREATE INDEX lineitem_partkey_desc_index ON lineitem (l_partkey DESC); +DEBUG: applied command on shard 102014 on node localhost:57637 +DEBUG: applied command on shard 102014 on node localhost:57638 +DEBUG: applied command on shard 102013 on node localhost:57637 +DEBUG: applied command on shard 102013 on node localhost:57638 +DEBUG: applied command on shard 102012 on node localhost:57637 +DEBUG: applied command on shard 102012 on node localhost:57638 +DEBUG: applied command on shard 102011 on node localhost:57637 +DEBUG: applied command on shard 102011 on node localhost:57638 +DEBUG: applied command on shard 102010 on node localhost:57637 +DEBUG: applied command on shard 102010 on node localhost:57638 +DEBUG: applied command on shard 102009 on node localhost:57637 +DEBUG: applied command on shard 102009 on node localhost:57638 +DEBUG: building index "lineitem_partkey_desc_index" on table "lineitem" +CREATE INDEX lineitem_partial_index ON lineitem (l_shipdate) + WHERE l_shipdate < '1995-01-01'; +DEBUG: applied command on shard 102014 on node localhost:57637 +DEBUG: applied command on shard 102014 on node localhost:57638 +DEBUG: applied command on shard 102013 on node localhost:57637 +DEBUG: applied command on shard 102013 on node localhost:57638 +DEBUG: applied command on shard 102012 on node localhost:57637 +DEBUG: applied command on shard 102012 on node localhost:57638 +DEBUG: applied command on shard 102011 on node localhost:57637 +DEBUG: applied command on shard 102011 on node localhost:57638 +DEBUG: applied command on shard 102010 on node localhost:57637 +DEBUG: applied command on shard 102010 on node localhost:57638 +DEBUG: applied command on shard 102009 on node localhost:57637 +DEBUG: applied command on shard 102009 on node localhost:57638 +DEBUG: building index "lineitem_partial_index" on table "lineitem" +CREATE INDEX lineitem_orderkey_hash_index ON lineitem USING hash (l_partkey); +DEBUG: applied command on shard 102014 on node localhost:57637 +DEBUG: applied command on shard 102014 on node localhost:57638 +DEBUG: applied command on shard 102013 on node localhost:57637 +DEBUG: applied command on shard 102013 on node localhost:57638 +DEBUG: applied command on shard 102012 on node localhost:57637 +DEBUG: applied command on shard 102012 on node localhost:57638 +DEBUG: applied command on shard 102011 on node localhost:57637 +DEBUG: applied command on shard 102011 on node localhost:57638 +DEBUG: applied command on shard 102010 on node localhost:57637 +DEBUG: applied command on shard 102010 on node localhost:57638 +DEBUG: applied command on shard 102009 on node localhost:57637 +DEBUG: applied command on shard 102009 on node localhost:57638 +WARNING: hash indexes are not WAL-logged and their use is discouraged +DEBUG: building index "lineitem_orderkey_hash_index" on table "lineitem" +-- Verify that all indexes got created on the master node +SELECT * FROM pg_indexes WHERE tablename = 'lineitem' ORDER BY indexname; + schemaname | tablename | indexname | tablespace | indexdef +------------+-----------+------------------------------+------------+------------------------------------------------------------------------------------------------------------------ + public | lineitem | lineitem_orderkey_hash_index | | CREATE INDEX lineitem_orderkey_hash_index ON lineitem USING hash (l_partkey) + public | lineitem | lineitem_orderkey_index | | CREATE INDEX lineitem_orderkey_index ON lineitem USING btree (l_orderkey) + public | lineitem | lineitem_partial_index | | CREATE INDEX lineitem_partial_index ON lineitem USING btree (l_shipdate) WHERE (l_shipdate < '01-01-1995'::date) + public | lineitem | lineitem_partkey_desc_index | | CREATE INDEX lineitem_partkey_desc_index ON lineitem USING btree (l_partkey DESC) + public | lineitem | lineitem_pkey | | CREATE UNIQUE INDEX lineitem_pkey ON lineitem USING btree (l_orderkey, l_linenumber) + public | lineitem | lineitem_time_index | | CREATE INDEX lineitem_time_index ON lineitem USING btree (l_shipdate) +(6 rows) + +-- Verify that we error out on unsupported statement types +CREATE INDEX CONCURRENTLY try_index ON lineitem (l_orderkey); +ERROR: creating indexes concurrently on distributed tables is currently unsupported +CREATE UNIQUE INDEX try_index ON lineitem (l_orderkey); +ERROR: creating unique indexes on distributed tables is currently unsupported +CREATE INDEX try_index ON lineitem (l_orderkey) TABLESPACE newtablespace; +ERROR: specifying tablespaces with CREATE INDEX statements is currently unsupported +-- Verify that we error out in case of postgres errors on supported statement +-- types. +CREATE INDEX lineitem_orderkey_index ON lineitem (l_orderkey); +WARNING: could not receive query results from localhost:57637 +DETAIL: Client error: relation "lineitem_orderkey_index_102014" already exists +ERROR: could not execute DDL command on worker node shards +CREATE INDEX try_index ON lineitem USING gist (l_orderkey); +WARNING: could not receive query results from localhost:57637 +DETAIL: Client error: data type bigint has no default operator class for access method "gist" +ERROR: could not execute DDL command on worker node shards +CREATE INDEX try_index ON lineitem (non_existent_column); +WARNING: could not receive query results from localhost:57637 +DETAIL: Client error: column "non_existent_column" does not exist +ERROR: could not execute DDL command on worker node shards +-- Verify that none of failed indexes got created on the master node +SELECT * FROM pg_indexes WHERE tablename = 'lineitem' ORDER BY indexname; + schemaname | tablename | indexname | tablespace | indexdef +------------+-----------+------------------------------+------------+------------------------------------------------------------------------------------------------------------------ + public | lineitem | lineitem_orderkey_hash_index | | CREATE INDEX lineitem_orderkey_hash_index ON lineitem USING hash (l_partkey) + public | lineitem | lineitem_orderkey_index | | CREATE INDEX lineitem_orderkey_index ON lineitem USING btree (l_orderkey) + public | lineitem | lineitem_partial_index | | CREATE INDEX lineitem_partial_index ON lineitem USING btree (l_shipdate) WHERE (l_shipdate < '01-01-1995'::date) + public | lineitem | lineitem_partkey_desc_index | | CREATE INDEX lineitem_partkey_desc_index ON lineitem USING btree (l_partkey DESC) + public | lineitem | lineitem_pkey | | CREATE UNIQUE INDEX lineitem_pkey ON lineitem USING btree (l_orderkey, l_linenumber) + public | lineitem | lineitem_time_index | | CREATE INDEX lineitem_time_index ON lineitem USING btree (l_shipdate) +(6 rows) + +-- +-- DROP INDEX +-- +-- Verify that we can't drop multiple indexes in a single command +DROP INDEX lineitem_orderkey_index, lineitem_partial_index; +ERROR: cannot drop multiple distributed objects in a single command +HINT: Try dropping each object in a separate DROP command. +-- Verify that we error out on the CONCURRENTLY clause +DROP INDEX CONCURRENTLY lineitem_orderkey_index; +ERROR: dropping indexes concurrently on distributed tables is currently unsupported +-- Verify that we can succesfully drop indexes +DROP INDEX lineitem_orderkey_index; +DEBUG: applied command on shard 102014 on node localhost:57637 +DEBUG: applied command on shard 102014 on node localhost:57638 +DEBUG: applied command on shard 102013 on node localhost:57637 +DEBUG: applied command on shard 102013 on node localhost:57638 +DEBUG: applied command on shard 102012 on node localhost:57637 +DEBUG: applied command on shard 102012 on node localhost:57638 +DEBUG: applied command on shard 102011 on node localhost:57637 +DEBUG: applied command on shard 102011 on node localhost:57638 +DEBUG: applied command on shard 102010 on node localhost:57637 +DEBUG: applied command on shard 102010 on node localhost:57638 +DEBUG: applied command on shard 102009 on node localhost:57637 +DEBUG: applied command on shard 102009 on node localhost:57638 +DEBUG: EventTriggerInvoke 16532 +DROP INDEX lineitem_partkey_desc_index; +DEBUG: applied command on shard 102014 on node localhost:57637 +DEBUG: applied command on shard 102014 on node localhost:57638 +DEBUG: applied command on shard 102013 on node localhost:57637 +DEBUG: applied command on shard 102013 on node localhost:57638 +DEBUG: applied command on shard 102012 on node localhost:57637 +DEBUG: applied command on shard 102012 on node localhost:57638 +DEBUG: applied command on shard 102011 on node localhost:57637 +DEBUG: applied command on shard 102011 on node localhost:57638 +DEBUG: applied command on shard 102010 on node localhost:57637 +DEBUG: applied command on shard 102010 on node localhost:57638 +DEBUG: applied command on shard 102009 on node localhost:57637 +DEBUG: applied command on shard 102009 on node localhost:57638 +DEBUG: EventTriggerInvoke 16532 +DROP INDEX lineitem_partial_index; +DEBUG: applied command on shard 102014 on node localhost:57637 +DEBUG: applied command on shard 102014 on node localhost:57638 +DEBUG: applied command on shard 102013 on node localhost:57637 +DEBUG: applied command on shard 102013 on node localhost:57638 +DEBUG: applied command on shard 102012 on node localhost:57637 +DEBUG: applied command on shard 102012 on node localhost:57638 +DEBUG: applied command on shard 102011 on node localhost:57637 +DEBUG: applied command on shard 102011 on node localhost:57638 +DEBUG: applied command on shard 102010 on node localhost:57637 +DEBUG: applied command on shard 102010 on node localhost:57638 +DEBUG: applied command on shard 102009 on node localhost:57637 +DEBUG: applied command on shard 102009 on node localhost:57638 +DEBUG: EventTriggerInvoke 16532 +-- Verify that we handle if exists statements correctly +DROP INDEX non_existent_index; +ERROR: index "non_existent_index" does not exist +DROP INDEX IF EXISTS non_existent_index; +NOTICE: index "non_existent_index" does not exist, skipping +DROP INDEX IF EXISTS lineitem_orderkey_hash_index; +DEBUG: applied command on shard 102014 on node localhost:57637 +DEBUG: applied command on shard 102014 on node localhost:57638 +DEBUG: applied command on shard 102013 on node localhost:57637 +DEBUG: applied command on shard 102013 on node localhost:57638 +DEBUG: applied command on shard 102012 on node localhost:57637 +DEBUG: applied command on shard 102012 on node localhost:57638 +DEBUG: applied command on shard 102011 on node localhost:57637 +DEBUG: applied command on shard 102011 on node localhost:57638 +DEBUG: applied command on shard 102010 on node localhost:57637 +DEBUG: applied command on shard 102010 on node localhost:57638 +DEBUG: applied command on shard 102009 on node localhost:57637 +DEBUG: applied command on shard 102009 on node localhost:57638 +DEBUG: EventTriggerInvoke 16532 +DROP INDEX lineitem_orderkey_hash_index; +ERROR: index "lineitem_orderkey_hash_index" does not exist +-- Verify that all the indexes are also dropped from the master node +SELECT * FROM pg_indexes WHERE tablename = 'lineitem' ORDER BY indexname; + schemaname | tablename | indexname | tablespace | indexdef +------------+-----------+---------------------+------------+-------------------------------------------------------------------------------------- + public | lineitem | lineitem_pkey | | CREATE UNIQUE INDEX lineitem_pkey ON lineitem USING btree (l_orderkey, l_linenumber) + public | lineitem | lineitem_time_index | | CREATE INDEX lineitem_time_index ON lineitem USING btree (l_shipdate) +(2 rows) + diff --git a/src/test/regress/expected/multi_join_order_additional.out b/src/test/regress/expected/multi_join_order_additional.out new file mode 100644 index 000000000..c641140a7 --- /dev/null +++ b/src/test/regress/expected/multi_join_order_additional.out @@ -0,0 +1,150 @@ +-- +-- MULTI_JOIN_ORDER_ADDITIONAL +-- +-- Set configuration to print table join order and pruned shards +SET citusdb.log_multi_join_order TO TRUE; +SET client_min_messages TO DEBUG2; +-- The following query checks that we can correctly handle self-joins +EXPLAIN SELECT l1.l_quantity FROM lineitem l1, lineitem l2 + WHERE l1.l_orderkey = l2.l_orderkey AND l1.l_quantity > 5; +LOG: join order: [ "lineitem" ][ local partition join "lineitem" ] +DEBUG: join prunable for intervals [13921,14947] and [11554,13920] +DEBUG: join prunable for intervals [13921,14947] and [8997,11554] +DEBUG: join prunable for intervals [13921,14947] and [4965,5986] +DEBUG: join prunable for intervals [13921,14947] and [2497,4964] +DEBUG: join prunable for intervals [13921,14947] and [1,2496] +DEBUG: join prunable for intervals [11554,13920] and [13921,14947] +DEBUG: join prunable for intervals [11554,13920] and [4965,5986] +DEBUG: join prunable for intervals [11554,13920] and [2497,4964] +DEBUG: join prunable for intervals [11554,13920] and [1,2496] +DEBUG: join prunable for intervals [8997,11554] and [13921,14947] +DEBUG: join prunable for intervals [8997,11554] and [4965,5986] +DEBUG: join prunable for intervals [8997,11554] and [2497,4964] +DEBUG: join prunable for intervals [8997,11554] and [1,2496] +DEBUG: join prunable for intervals [4965,5986] and [13921,14947] +DEBUG: join prunable for intervals [4965,5986] and [11554,13920] +DEBUG: join prunable for intervals [4965,5986] and [8997,11554] +DEBUG: join prunable for intervals [4965,5986] and [2497,4964] +DEBUG: join prunable for intervals [4965,5986] and [1,2496] +DEBUG: join prunable for intervals [2497,4964] and [13921,14947] +DEBUG: join prunable for intervals [2497,4964] and [11554,13920] +DEBUG: join prunable for intervals [2497,4964] and [8997,11554] +DEBUG: join prunable for intervals [2497,4964] and [4965,5986] +DEBUG: join prunable for intervals [2497,4964] and [1,2496] +DEBUG: join prunable for intervals [1,2496] and [13921,14947] +DEBUG: join prunable for intervals [1,2496] and [11554,13920] +DEBUG: join prunable for intervals [1,2496] and [8997,11554] +DEBUG: join prunable for intervals [1,2496] and [4965,5986] +DEBUG: join prunable for intervals [1,2496] and [2497,4964] + QUERY PLAN +---------------------------------------------------------------------- + explain statements for distributed queries are currently unsupported +(1 row) + +-- Update configuration to treat lineitem and orders tables as large +SET citusdb.large_table_shard_count TO 2; +SET client_min_messages TO LOG; +-- The following queries check that we correctly handle joins and OR clauses. In +-- particular, these queries check that we factorize out OR clauses if possible, +-- and that we default to a cartesian product otherwise. +EXPLAIN SELECT count(*) FROM lineitem, orders + WHERE (l_orderkey = o_orderkey AND l_quantity > 5) + OR (l_orderkey = o_orderkey AND l_quantity < 10); +LOG: join order: [ "lineitem" ][ local partition join "orders" ] + QUERY PLAN +---------------------------------------------------------------------- + explain statements for distributed queries are currently unsupported +(1 row) + +EXPLAIN SELECT l_quantity FROM lineitem, orders + WHERE (l_orderkey = o_orderkey OR l_quantity > 5); +LOG: join order: [ "lineitem" ][ cartesian product "orders" ] +ERROR: cannot perform distributed planning on this query +DETAIL: Cartesian products are currently unsupported +-- The below queries modify the partition method in pg_dist_partition. We thus +-- begin a transaction here so the changes don't impact any other parallel +-- running tests. +BEGIN; +-- Validate that we take into account the partition method when building the +-- join-order plan. +UPDATE pg_dist_partition SET partmethod = 'h' WHERE + logicalrelid = (SELECT relfilenode FROM pg_class WHERE relname = 'lineitem'); +EXPLAIN SELECT count(*) FROM orders, lineitem + WHERE o_orderkey = l_orderkey; +LOG: join order: [ "orders" ][ single partition join "lineitem" ] + QUERY PLAN +---------------------------------------------------------------------- + explain statements for distributed queries are currently unsupported +(1 row) + +-- Verify we handle local joins between two hash-partitioned tables. +UPDATE pg_dist_partition SET partmethod = 'h' WHERE + logicalrelid = (SELECT relfilenode FROM pg_class WHERE relname = 'orders'); +EXPLAIN SELECT count(*) FROM orders, lineitem + WHERE o_orderkey = l_orderkey; +LOG: join order: [ "orders" ][ local partition join "lineitem" ] + QUERY PLAN +---------------------------------------------------------------------- + explain statements for distributed queries are currently unsupported +(1 row) + +UPDATE pg_dist_partition SET partmethod = 'a' WHERE + logicalrelid = (SELECT relfilenode FROM pg_class WHERE relname = 'lineitem'); +UPDATE pg_dist_partition SET partmethod = 'a' WHERE + logicalrelid = (SELECT relfilenode FROM pg_class WHERE relname = 'orders'); +-- Validate that we can handle broadcast joins with hash-partitioned tables. +UPDATE pg_dist_partition SET partmethod = 'h' WHERE + logicalrelid = (SELECT relfilenode FROM pg_class WHERE relname = 'customer'); +EXPLAIN SELECT count(*) FROM customer, nation + WHERE c_nationkey = n_nationkey; +LOG: join order: [ "customer" ][ broadcast join "nation" ] + QUERY PLAN +---------------------------------------------------------------------- + explain statements for distributed queries are currently unsupported +(1 row) + +UPDATE pg_dist_partition SET partmethod = 'a' WHERE + logicalrelid = (SELECT relfilenode FROM pg_class WHERE relname = 'customer'); +-- Update the large table shard count for all the following tests. +SET citusdb.large_table_shard_count TO 1; +-- Validate that we don't use a single-partition join method for a hash +-- re-partitioned table, thus preventing a partition of just the customer table. +EXPLAIN SELECT count(*) FROM orders, lineitem, customer + WHERE o_custkey = l_partkey AND o_custkey = c_nationkey; +LOG: join order: [ "orders" ][ dual partition join "lineitem" ][ dual partition join "customer" ] + QUERY PLAN +---------------------------------------------------------------------- + explain statements for distributed queries are currently unsupported +(1 row) + +-- Validate that we don't chose a single-partition join method with a +-- hash-partitioned base table +UPDATE pg_dist_partition SET partmethod = 'h' WHERE + logicalrelid = (SELECT relfilenode FROM pg_class WHERE relname = 'customer'); +EXPLAIN SELECT count(*) FROM orders, customer + WHERE c_custkey = o_custkey; +LOG: join order: [ "orders" ][ dual partition join "customer" ] + QUERY PLAN +---------------------------------------------------------------------- + explain statements for distributed queries are currently unsupported +(1 row) + +UPDATE pg_dist_partition SET partmethod = 'a' WHERE + logicalrelid = (SELECT relfilenode FROM pg_class WHERE relname = 'customer'); +-- Validate that we can re-partition a hash partitioned table to join with a +-- range partitioned one. +UPDATE pg_dist_partition SET partmethod = 'h' WHERE + logicalrelid = (SELECT relfilenode FROM pg_class WHERE relname = 'orders'); +EXPLAIN SELECT count(*) FROM orders, customer + WHERE c_custkey = o_custkey; +LOG: join order: [ "orders" ][ single partition join "customer" ] + QUERY PLAN +---------------------------------------------------------------------- + explain statements for distributed queries are currently unsupported +(1 row) + +UPDATE pg_dist_partition SET partmethod = 'a' WHERE + logicalrelid = (SELECT relfilenode FROM pg_class WHERE relname = 'orders'); +COMMIT; +-- Reset client logging level to its previous value +SET client_min_messages TO NOTICE; diff --git a/src/test/regress/expected/multi_join_order_tpch_large.out b/src/test/regress/expected/multi_join_order_tpch_large.out new file mode 100644 index 000000000..14bc84cff --- /dev/null +++ b/src/test/regress/expected/multi_join_order_tpch_large.out @@ -0,0 +1,149 @@ +-- +-- MULTI_JOIN_ORDER_TPCH_LARGE +-- +-- Enable configuration to print table join order +SET citusdb.log_multi_join_order TO TRUE; +SET client_min_messages TO LOG; +-- Change configuration to treat lineitem, orders, customer, and part tables as +-- large. The following queries are basically the same as the ones in tpch_small +-- except that more data has been staged to customer and part tables. Therefore, +-- we will apply different distributed join strategies for these queries. +SET citusdb.large_table_shard_count TO 2; +-- Query #6 from the TPC-H decision support benchmark +EXPLAIN SELECT + sum(l_extendedprice * l_discount) as revenue +FROM + lineitem +WHERE + l_shipdate >= date '1994-01-01' + and l_shipdate < date '1994-01-01' + interval '1 year' + and l_discount between 0.06 - 0.01 and 0.06 + 0.01 + and l_quantity < 24; +LOG: join order: [ "lineitem" ] + QUERY PLAN +---------------------------------------------------------------------- + explain statements for distributed queries are currently unsupported +(1 row) + +-- Query #3 from the TPC-H decision support benchmark +EXPLAIN SELECT + l_orderkey, + sum(l_extendedprice * (1 - l_discount)) as revenue, + o_orderdate, + o_shippriority +FROM + customer, + orders, + lineitem +WHERE + c_mktsegment = 'BUILDING' + AND c_custkey = o_custkey + AND l_orderkey = o_orderkey + AND o_orderdate < date '1995-03-15' + AND l_shipdate > date '1995-03-15' +GROUP BY + l_orderkey, + o_orderdate, + o_shippriority +ORDER BY + revenue DESC, + o_orderdate; +LOG: join order: [ "orders" ][ local partition join "lineitem" ][ single partition join "customer" ] + QUERY PLAN +---------------------------------------------------------------------- + explain statements for distributed queries are currently unsupported +(1 row) + +-- Query #10 from the TPC-H decision support benchmark +EXPLAIN SELECT + c_custkey, + c_name, + sum(l_extendedprice * (1 - l_discount)) as revenue, + c_acctbal, + n_name, + c_address, + c_phone, + c_comment +FROM + customer, + orders, + lineitem, + nation +WHERE + c_custkey = o_custkey + AND l_orderkey = o_orderkey + AND o_orderdate >= date '1993-10-01' + AND o_orderdate < date '1993-10-01' + interval '3' month + AND l_returnflag = 'R' + AND c_nationkey = n_nationkey +GROUP BY + c_custkey, + c_name, + c_acctbal, + c_phone, + n_name, + c_address, + c_comment +ORDER BY + revenue DESC; +LOG: join order: [ "orders" ][ local partition join "lineitem" ][ single partition join "customer" ][ broadcast join "nation" ] + QUERY PLAN +---------------------------------------------------------------------- + explain statements for distributed queries are currently unsupported +(1 row) + +-- Query #19 from the TPC-H decision support benchmark (modified) +EXPLAIN SELECT + sum(l_extendedprice* (1 - l_discount)) as revenue +FROM + lineitem, + part +WHERE + ( + p_partkey = l_partkey + AND (p_brand = 'Brand#12' OR p_brand= 'Brand#14' OR p_brand='Brand#15') + AND l_quantity >= 10 + AND l_shipmode in ('AIR', 'AIR REG', 'TRUCK') + AND l_shipinstruct = 'DELIVER IN PERSON' + ) + OR + ( + p_partkey = l_partkey + AND (p_brand = 'Brand#23' OR p_brand='Brand#24') + AND l_quantity >= 20 + AND l_shipmode in ('AIR', 'AIR REG', 'TRUCK') + AND l_shipinstruct = 'DELIVER IN PERSON' + ) + OR + ( + p_partkey = l_partkey + AND (p_brand = 'Brand#33' OR p_brand = 'Brand#34' OR p_brand = 'Brand#35') + AND l_quantity >= 1 + AND l_shipmode in ('AIR', 'AIR REG', 'TRUCK') + AND l_shipinstruct = 'DELIVER IN PERSON' + ); +LOG: join order: [ "lineitem" ][ single partition join "part" ] + QUERY PLAN +---------------------------------------------------------------------- + explain statements for distributed queries are currently unsupported +(1 row) + +-- Query to test multiple re-partition jobs in a single query +EXPLAIN SELECT + l_partkey, count(*) +FROM + lineitem, part, orders, customer +WHERE + l_orderkey = o_orderkey AND + l_partkey = p_partkey AND + c_custkey = o_custkey +GROUP BY + l_partkey; +LOG: join order: [ "lineitem" ][ local partition join "orders" ][ single partition join "part" ][ single partition join "customer" ] + QUERY PLAN +---------------------------------------------------------------------- + explain statements for distributed queries are currently unsupported +(1 row) + +-- Reset client logging level to its previous value +SET client_min_messages TO NOTICE; diff --git a/src/test/regress/expected/multi_join_order_tpch_small.out b/src/test/regress/expected/multi_join_order_tpch_small.out new file mode 100644 index 000000000..696736a00 --- /dev/null +++ b/src/test/regress/expected/multi_join_order_tpch_small.out @@ -0,0 +1,129 @@ +-- +-- MULTI_JOIN_ORDER_TPCH_SMALL +-- +-- Enable configuration to print table join order +SET citusdb.log_multi_join_order TO TRUE; +SET client_min_messages TO LOG; +-- Change configuration to treat lineitem and orders tables as large +SET citusdb.large_table_shard_count TO 2; +-- Query #6 from the TPC-H decision support benchmark +EXPLAIN SELECT + sum(l_extendedprice * l_discount) as revenue +FROM + lineitem +WHERE + l_shipdate >= date '1994-01-01' + and l_shipdate < date '1994-01-01' + interval '1 year' + and l_discount between 0.06 - 0.01 and 0.06 + 0.01 + and l_quantity < 24; +LOG: join order: [ "lineitem" ] + QUERY PLAN +---------------------------------------------------------------------- + explain statements for distributed queries are currently unsupported +(1 row) + +-- Query #3 from the TPC-H decision support benchmark +EXPLAIN SELECT + l_orderkey, + sum(l_extendedprice * (1 - l_discount)) as revenue, + o_orderdate, + o_shippriority +FROM + customer, + orders, + lineitem +WHERE + c_mktsegment = 'BUILDING' + AND c_custkey = o_custkey + AND l_orderkey = o_orderkey + AND o_orderdate < date '1995-03-15' + AND l_shipdate > date '1995-03-15' +GROUP BY + l_orderkey, + o_orderdate, + o_shippriority +ORDER BY + revenue DESC, + o_orderdate; +LOG: join order: [ "orders" ][ broadcast join "customer" ][ local partition join "lineitem" ] + QUERY PLAN +---------------------------------------------------------------------- + explain statements for distributed queries are currently unsupported +(1 row) + +-- Query #10 from the TPC-H decision support benchmark +EXPLAIN SELECT + c_custkey, + c_name, + sum(l_extendedprice * (1 - l_discount)) as revenue, + c_acctbal, + n_name, + c_address, + c_phone, + c_comment +FROM + customer, + orders, + lineitem, + nation +WHERE + c_custkey = o_custkey + AND l_orderkey = o_orderkey + AND o_orderdate >= date '1993-10-01' + AND o_orderdate < date '1993-10-01' + interval '3' month + AND l_returnflag = 'R' + AND c_nationkey = n_nationkey +GROUP BY + c_custkey, + c_name, + c_acctbal, + c_phone, + n_name, + c_address, + c_comment +ORDER BY + revenue DESC; +LOG: join order: [ "orders" ][ broadcast join "customer" ][ broadcast join "nation" ][ local partition join "lineitem" ] + QUERY PLAN +---------------------------------------------------------------------- + explain statements for distributed queries are currently unsupported +(1 row) + +-- Query #19 from the TPC-H decision support benchmark (modified) +EXPLAIN SELECT + sum(l_extendedprice* (1 - l_discount)) as revenue +FROM + lineitem, + part +WHERE + ( + p_partkey = l_partkey + AND (p_brand = 'Brand#12' OR p_brand= 'Brand#14' OR p_brand='Brand#15') + AND l_quantity >= 10 + AND l_shipmode in ('AIR', 'AIR REG', 'TRUCK') + AND l_shipinstruct = 'DELIVER IN PERSON' + ) + OR + ( + p_partkey = l_partkey + AND (p_brand = 'Brand#23' OR p_brand='Brand#24') + AND l_quantity >= 20 + AND l_shipmode in ('AIR', 'AIR REG', 'TRUCK') + AND l_shipinstruct = 'DELIVER IN PERSON' + ) + OR + ( + p_partkey = l_partkey + AND (p_brand = 'Brand#33' OR p_brand = 'Brand#34' OR p_brand = 'Brand#35') + AND l_quantity >= 1 + AND l_shipmode in ('AIR', 'AIR REG', 'TRUCK') + AND l_shipinstruct = 'DELIVER IN PERSON' + ); +LOG: join order: [ "lineitem" ][ broadcast join "part" ] + QUERY PLAN +---------------------------------------------------------------------- + explain statements for distributed queries are currently unsupported +(1 row) + +-- Reset client logging level to its previous value +SET client_min_messages TO NOTICE; diff --git a/src/test/regress/expected/multi_join_pruning.out b/src/test/regress/expected/multi_join_pruning.out new file mode 100644 index 000000000..e690636ee --- /dev/null +++ b/src/test/regress/expected/multi_join_pruning.out @@ -0,0 +1,101 @@ +-- +-- MULTI_JOIN_PRUNING +-- +-- Check that join-pruning works for joins between two large relations. For now +-- we only check for join-pruning between locally partitioned relations. In the +-- future we want to check for pruning between re-partitioned relations as well. +SET client_min_messages TO DEBUG2; +-- Change configuration to treat all tables as large +SET citusdb.large_table_shard_count TO 2; +SELECT sum(l_linenumber), avg(l_linenumber) FROM lineitem, orders + WHERE l_orderkey = o_orderkey; +DEBUG: join prunable for intervals [13921,14947] and [1,5986] +DEBUG: join prunable for intervals [11554,13920] and [1,5986] +DEBUG: join prunable for intervals [8997,11554] and [1,5986] +DEBUG: join prunable for intervals [4965,5986] and [8997,14946] +DEBUG: join prunable for intervals [2497,4964] and [8997,14946] +DEBUG: join prunable for intervals [1,2496] and [8997,14946] + sum | avg +-------+-------------------- + 36086 | 3.0076679446574429 +(1 row) + +SELECT sum(l_linenumber), avg(l_linenumber) FROM lineitem, orders + WHERE l_orderkey = o_orderkey AND l_orderkey > 9030; +DEBUG: predicate pruning for shardId 102011 +DEBUG: predicate pruning for shardId 102010 +DEBUG: predicate pruning for shardId 102009 +DEBUG: join prunable for intervals [13921,14947] and [1,5986] +DEBUG: join prunable for intervals [11554,13920] and [1,5986] +DEBUG: join prunable for intervals [8997,11554] and [1,5986] + sum | avg +-------+-------------------- + 17996 | 3.0194630872483221 +(1 row) + +-- Shards for the lineitem table have been pruned away. Check that join pruning +-- works as expected in this case. +SELECT sum(l_linenumber), avg(l_linenumber) FROM lineitem, orders + WHERE l_orderkey = o_orderkey AND l_orderkey > 20000; +DEBUG: predicate pruning for shardId 102014 +DEBUG: predicate pruning for shardId 102013 +DEBUG: predicate pruning for shardId 102012 +DEBUG: predicate pruning for shardId 102011 +DEBUG: predicate pruning for shardId 102010 +DEBUG: predicate pruning for shardId 102009 + sum | avg +-----+----- + | +(1 row) + +-- Partition pruning left three shards for the lineitem and one shard for the +-- orders table. These shard sets don't overlap, so join pruning should prune +-- out all the shards, and leave us with an empty task list. +SELECT sum(l_linenumber), avg(l_linenumber) FROM lineitem, orders + WHERE l_orderkey = o_orderkey AND l_orderkey > 6000 AND o_orderkey < 6000; +DEBUG: predicate pruning for shardId 102011 +DEBUG: predicate pruning for shardId 102010 +DEBUG: predicate pruning for shardId 102009 +DEBUG: predicate pruning for shardId 102016 +DEBUG: join prunable for intervals [13921,14947] and [1,5986] +DEBUG: join prunable for intervals [11554,13920] and [1,5986] +DEBUG: join prunable for intervals [8997,11554] and [1,5986] + sum | avg +-----+----- + | +(1 row) + +-- These tests check that we can do join pruning for tables partitioned over +-- different type of columns including varchar, array types, composite types +-- etc. This is in response to a bug we had where we were not able to resolve +-- correct operator types for some kind of column types. +EXPLAIN SELECT count(*) + FROM array_partitioned_table table1, array_partitioned_table table2 + WHERE table1.array_column = table2.array_column; +DEBUG: join prunable for intervals [{BA1000U2AMO4ZGX,BZZXSP27F21T6},{CA1000U2AMO4ZGX,CZZXSP27F21T6}] and [{},{AZZXSP27F21T6,AZZXSP27F21T6}] +DEBUG: join prunable for intervals [{},{AZZXSP27F21T6,AZZXSP27F21T6}] and [{BA1000U2AMO4ZGX,BZZXSP27F21T6},{CA1000U2AMO4ZGX,CZZXSP27F21T6}] + QUERY PLAN +---------------------------------------------------------------------- + explain statements for distributed queries are currently unsupported +(1 row) + +EXPLAIN SELECT count(*) + FROM composite_partitioned_table table1, composite_partitioned_table table2 + WHERE table1.composite_column = table2.composite_column; +DEBUG: join prunable for intervals [(c,5,d),(d,6,e)] and [(a,3,b),(b,4,c)] +DEBUG: join prunable for intervals [(a,3,b),(b,4,c)] and [(c,5,d),(d,6,e)] + QUERY PLAN +---------------------------------------------------------------------- + explain statements for distributed queries are currently unsupported +(1 row) + +-- Large table joins between varchar columns do not work because of a bug we +-- have. Currently, we require joins to be only on columns. Postgres adds a +-- relabel to typecast varchars to text due to which our check fails and we +-- error out. +EXPLAIN SELECT count(*) + FROM varchar_partitioned_table table1, varchar_partitioned_table table2 + WHERE table1.varchar_column = table2.varchar_column; +ERROR: cannot perform local joins that involve expressions +DETAIL: local joins can be performed between columns only +SET client_min_messages TO NOTICE; diff --git a/src/test/regress/expected/multi_large_table_join_planning.out b/src/test/regress/expected/multi_large_table_join_planning.out new file mode 100644 index 000000000..499a1f5be --- /dev/null +++ b/src/test/regress/expected/multi_large_table_join_planning.out @@ -0,0 +1,237 @@ +-- +-- MULTI_LARGE_TABLE_PLANNING +-- +-- Tests that cover large table join planning. Note that we explicitly start a +-- transaction block here so that we don't emit debug messages with changing +-- transaction ids in them. Also, we set the executor type to task tracker +-- executor here, as we cannot run repartition jobs with real time executor. +BEGIN; +SET client_min_messages TO DEBUG4; +DEBUG: CommitTransactionCommand +SET citusdb.large_table_shard_count TO 2; +DEBUG: StartTransactionCommand +DEBUG: ProcessUtility +DEBUG: CommitTransactionCommand +SET citusdb.task_executor_type TO 'task-tracker'; +DEBUG: StartTransactionCommand +DEBUG: ProcessUtility +DEBUG: CommitTransactionCommand +-- Debug4 log messages display jobIds within them. We explicitly set the jobId +-- sequence here so that the regression output becomes independent of the number +-- of jobs executed prior to running this test. +ALTER SEQUENCE pg_catalog.pg_dist_jobid_seq RESTART 1250; +DEBUG: StartTransactionCommand +DEBUG: ProcessUtility +DEBUG: CommitTransactionCommand +-- Multi-level repartition join to verify our projection columns are correctly +-- referenced and propagated across multiple repartition jobs. The test also +-- validates that only the minimal necessary projection columns are transferred +-- between jobs. +SELECT + l_partkey, o_orderkey, count(*) +FROM + lineitem, part, orders, customer +WHERE + l_orderkey = o_orderkey AND + l_partkey = p_partkey AND + c_custkey = o_custkey AND + (l_quantity > 5.0 OR l_extendedprice > 1200.0) AND + p_size > 8 AND o_totalprice > 10 AND + c_acctbal < 5000.0 +GROUP BY + l_partkey, o_orderkey +ORDER BY + l_partkey, o_orderkey +LIMIT 30; +DEBUG: StartTransactionCommand +DEBUG: push down of limit count: 30 +DEBUG: join prunable for intervals [13921,14947] and [1,5986] +DEBUG: join prunable for intervals [11554,13920] and [1,5986] +DEBUG: join prunable for intervals [8997,11554] and [1,5986] +DEBUG: join prunable for intervals [4965,5986] and [8997,14946] +DEBUG: join prunable for intervals [2497,4964] and [8997,14946] +DEBUG: join prunable for intervals [1,2496] and [8997,14946] +DEBUG: generated sql query for job 1250 and task 3 +DETAIL: query string: "SELECT lineitem.l_partkey, orders.o_orderkey, lineitem.l_quantity, lineitem.l_extendedprice, orders.o_custkey FROM (lineitem_102014 lineitem JOIN orders_102016 orders ON ((lineitem.l_orderkey = orders.o_orderkey))) WHERE (orders.o_totalprice > '10'::numeric)" +DEBUG: generated sql query for job 1250 and task 6 +DETAIL: query string: "SELECT lineitem.l_partkey, orders.o_orderkey, lineitem.l_quantity, lineitem.l_extendedprice, orders.o_custkey FROM (lineitem_102013 lineitem JOIN orders_102016 orders ON ((lineitem.l_orderkey = orders.o_orderkey))) WHERE (orders.o_totalprice > '10'::numeric)" +DEBUG: generated sql query for job 1250 and task 9 +DETAIL: query string: "SELECT lineitem.l_partkey, orders.o_orderkey, lineitem.l_quantity, lineitem.l_extendedprice, orders.o_custkey FROM (lineitem_102012 lineitem JOIN orders_102016 orders ON ((lineitem.l_orderkey = orders.o_orderkey))) WHERE (orders.o_totalprice > '10'::numeric)" +DEBUG: generated sql query for job 1250 and task 12 +DETAIL: query string: "SELECT lineitem.l_partkey, orders.o_orderkey, lineitem.l_quantity, lineitem.l_extendedprice, orders.o_custkey FROM (lineitem_102011 lineitem JOIN orders_102015 orders ON ((lineitem.l_orderkey = orders.o_orderkey))) WHERE (orders.o_totalprice > '10'::numeric)" +DEBUG: generated sql query for job 1250 and task 15 +DETAIL: query string: "SELECT lineitem.l_partkey, orders.o_orderkey, lineitem.l_quantity, lineitem.l_extendedprice, orders.o_custkey FROM (lineitem_102010 lineitem JOIN orders_102015 orders ON ((lineitem.l_orderkey = orders.o_orderkey))) WHERE (orders.o_totalprice > '10'::numeric)" +DEBUG: generated sql query for job 1250 and task 18 +DETAIL: query string: "SELECT lineitem.l_partkey, orders.o_orderkey, lineitem.l_quantity, lineitem.l_extendedprice, orders.o_custkey FROM (lineitem_102009 lineitem JOIN orders_102015 orders ON ((lineitem.l_orderkey = orders.o_orderkey))) WHERE (orders.o_totalprice > '10'::numeric)" +DEBUG: assigned task 18 to node localhost:57637 +DEBUG: assigned task 15 to node localhost:57638 +DEBUG: assigned task 12 to node localhost:57637 +DEBUG: assigned task 9 to node localhost:57638 +DEBUG: assigned task 6 to node localhost:57637 +DEBUG: assigned task 3 to node localhost:57638 +DEBUG: join prunable for intervals [1,1000] and [6001,7000] +DEBUG: join prunable for intervals [6001,7000] and [1,1000] +DEBUG: generated sql query for job 1251 and task 3 +DETAIL: query string: "SELECT "pg_merge_job_1250.task_000019".intermediate_column_1250_0, "pg_merge_job_1250.task_000019".intermediate_column_1250_1, "pg_merge_job_1250.task_000019".intermediate_column_1250_2, "pg_merge_job_1250.task_000019".intermediate_column_1250_3, "pg_merge_job_1250.task_000019".intermediate_column_1250_4 FROM (pg_merge_job_1250.task_000019 "pg_merge_job_1250.task_000019" JOIN part_102019 part ON (("pg_merge_job_1250.task_000019".intermediate_column_1250_0 = part.p_partkey))) WHERE (part.p_size > 8)" +DEBUG: generated sql query for job 1251 and task 6 +DETAIL: query string: "SELECT "pg_merge_job_1250.task_000026".intermediate_column_1250_0, "pg_merge_job_1250.task_000026".intermediate_column_1250_1, "pg_merge_job_1250.task_000026".intermediate_column_1250_2, "pg_merge_job_1250.task_000026".intermediate_column_1250_3, "pg_merge_job_1250.task_000026".intermediate_column_1250_4 FROM (pg_merge_job_1250.task_000026 "pg_merge_job_1250.task_000026" JOIN part_102035 part ON (("pg_merge_job_1250.task_000026".intermediate_column_1250_0 = part.p_partkey))) WHERE (part.p_size > 8)" +DEBUG: pruning merge fetch taskId 1 +DETAIL: Creating dependency on merge taskId 19 +DEBUG: pruning merge fetch taskId 4 +DETAIL: Creating dependency on merge taskId 26 +DEBUG: assigned task 3 to node localhost:57637 +DEBUG: assigned task 6 to node localhost:57638 +DEBUG: join prunable for intervals [1,1000] and [1001,2000] +DEBUG: join prunable for intervals [1,1000] and [6001,7000] +DEBUG: join prunable for intervals [1001,2000] and [6001,7000] +DEBUG: join prunable for intervals [1001,2000] and [1,1000] +DEBUG: join prunable for intervals [6001,7000] and [1001,2000] +DEBUG: join prunable for intervals [6001,7000] and [1,1000] +DEBUG: generated sql query for job 1252 and task 3 +DETAIL: query string: "SELECT "pg_merge_job_1251.task_000007".intermediate_column_1251_0 AS l_partkey, "pg_merge_job_1251.task_000007".intermediate_column_1251_1 AS o_orderkey, count(*) AS count FROM (pg_merge_job_1251.task_000007 "pg_merge_job_1251.task_000007" JOIN customer_102017 customer ON ((customer.c_custkey = "pg_merge_job_1251.task_000007".intermediate_column_1251_4))) WHERE ((("pg_merge_job_1251.task_000007".intermediate_column_1251_2 > 5.0) OR ("pg_merge_job_1251.task_000007".intermediate_column_1251_3 > 1200.0)) AND (customer.c_acctbal < 5000.0)) GROUP BY "pg_merge_job_1251.task_000007".intermediate_column_1251_0, "pg_merge_job_1251.task_000007".intermediate_column_1251_1 ORDER BY "pg_merge_job_1251.task_000007".intermediate_column_1251_0, "pg_merge_job_1251.task_000007".intermediate_column_1251_1, "pg_merge_job_1251.task_000007".intermediate_column_1251_0, "pg_merge_job_1251.task_000007".intermediate_column_1251_1 LIMIT '30'::bigint" +DEBUG: generated sql query for job 1252 and task 6 +DETAIL: query string: "SELECT "pg_merge_job_1251.task_000010".intermediate_column_1251_0 AS l_partkey, "pg_merge_job_1251.task_000010".intermediate_column_1251_1 AS o_orderkey, count(*) AS count FROM (pg_merge_job_1251.task_000010 "pg_merge_job_1251.task_000010" JOIN customer_102034 customer ON ((customer.c_custkey = "pg_merge_job_1251.task_000010".intermediate_column_1251_4))) WHERE ((("pg_merge_job_1251.task_000010".intermediate_column_1251_2 > 5.0) OR ("pg_merge_job_1251.task_000010".intermediate_column_1251_3 > 1200.0)) AND (customer.c_acctbal < 5000.0)) GROUP BY "pg_merge_job_1251.task_000010".intermediate_column_1251_0, "pg_merge_job_1251.task_000010".intermediate_column_1251_1 ORDER BY "pg_merge_job_1251.task_000010".intermediate_column_1251_0, "pg_merge_job_1251.task_000010".intermediate_column_1251_1, "pg_merge_job_1251.task_000010".intermediate_column_1251_0, "pg_merge_job_1251.task_000010".intermediate_column_1251_1 LIMIT '30'::bigint" +DEBUG: generated sql query for job 1252 and task 9 +DETAIL: query string: "SELECT "pg_merge_job_1251.task_000013".intermediate_column_1251_0 AS l_partkey, "pg_merge_job_1251.task_000013".intermediate_column_1251_1 AS o_orderkey, count(*) AS count FROM (pg_merge_job_1251.task_000013 "pg_merge_job_1251.task_000013" JOIN customer_102033 customer ON ((customer.c_custkey = "pg_merge_job_1251.task_000013".intermediate_column_1251_4))) WHERE ((("pg_merge_job_1251.task_000013".intermediate_column_1251_2 > 5.0) OR ("pg_merge_job_1251.task_000013".intermediate_column_1251_3 > 1200.0)) AND (customer.c_acctbal < 5000.0)) GROUP BY "pg_merge_job_1251.task_000013".intermediate_column_1251_0, "pg_merge_job_1251.task_000013".intermediate_column_1251_1 ORDER BY "pg_merge_job_1251.task_000013".intermediate_column_1251_0, "pg_merge_job_1251.task_000013".intermediate_column_1251_1, "pg_merge_job_1251.task_000013".intermediate_column_1251_0, "pg_merge_job_1251.task_000013".intermediate_column_1251_1 LIMIT '30'::bigint" +DEBUG: pruning merge fetch taskId 1 +DETAIL: Creating dependency on merge taskId 7 +DEBUG: pruning merge fetch taskId 4 +DETAIL: Creating dependency on merge taskId 10 +DEBUG: pruning merge fetch taskId 7 +DETAIL: Creating dependency on merge taskId 13 +DEBUG: assigned task 3 to node localhost:57637 +DEBUG: assigned task 9 to node localhost:57638 +DEBUG: assigned task 6 to node localhost:57637 +DEBUG: completed cleanup query for job 1252 on node "localhost:57638" +DEBUG: completed cleanup query for job 1252 on node "localhost:57637" +DEBUG: completed cleanup query for job 1251 on node "localhost:57638" +DEBUG: completed cleanup query for job 1251 on node "localhost:57637" +DEBUG: completed cleanup query for job 1250 on node "localhost:57638" +DEBUG: completed cleanup query for job 1250 on node "localhost:57637" +DEBUG: CommitTransactionCommand + l_partkey | o_orderkey | count +-----------+------------+------- + 18 | 12005 | 1 + 79 | 5121 | 1 + 91 | 2883 | 1 + 222 | 9413 | 1 + 278 | 1287 | 1 + 309 | 2374 | 1 + 318 | 321 | 1 + 321 | 5984 | 1 + 337 | 10403 | 1 + 350 | 13698 | 1 + 358 | 4323 | 1 + 364 | 9347 | 1 + 416 | 640 | 1 + 426 | 10855 | 1 + 450 | 35 | 1 + 484 | 3843 | 1 + 504 | 14566 | 1 + 510 | 13569 | 1 + 532 | 3175 | 1 + 641 | 134 | 1 + 669 | 10944 | 1 + 716 | 2885 | 1 + 738 | 4355 | 1 + 802 | 2534 | 1 + 824 | 9287 | 1 + 864 | 3175 | 1 + 957 | 4293 | 1 + 960 | 10980 | 1 + 963 | 4580 | 1 + 6014 | 4614 | 1 +(30 rows) + +SELECT + l_partkey, o_orderkey, count(*) +FROM + lineitem, orders +WHERE + l_suppkey = o_shippriority AND + l_quantity < 5.0 AND o_totalprice <> 4.0 +GROUP BY + l_partkey, o_orderkey +ORDER BY + l_partkey, o_orderkey; +DEBUG: StartTransactionCommand +DEBUG: generated sql query for job 1253 and task 2 +DETAIL: query string: "SELECT l_partkey, l_suppkey FROM lineitem_102014 lineitem WHERE (l_quantity < 5.0)" +DEBUG: generated sql query for job 1253 and task 4 +DETAIL: query string: "SELECT l_partkey, l_suppkey FROM lineitem_102013 lineitem WHERE (l_quantity < 5.0)" +DEBUG: generated sql query for job 1253 and task 6 +DETAIL: query string: "SELECT l_partkey, l_suppkey FROM lineitem_102012 lineitem WHERE (l_quantity < 5.0)" +DEBUG: generated sql query for job 1253 and task 8 +DETAIL: query string: "SELECT l_partkey, l_suppkey FROM lineitem_102011 lineitem WHERE (l_quantity < 5.0)" +DEBUG: generated sql query for job 1253 and task 10 +DETAIL: query string: "SELECT l_partkey, l_suppkey FROM lineitem_102010 lineitem WHERE (l_quantity < 5.0)" +DEBUG: generated sql query for job 1253 and task 12 +DETAIL: query string: "SELECT l_partkey, l_suppkey FROM lineitem_102009 lineitem WHERE (l_quantity < 5.0)" +DEBUG: assigned task 12 to node localhost:57637 +DEBUG: assigned task 10 to node localhost:57638 +DEBUG: assigned task 8 to node localhost:57637 +DEBUG: assigned task 6 to node localhost:57638 +DEBUG: assigned task 4 to node localhost:57637 +DEBUG: assigned task 2 to node localhost:57638 +DEBUG: generated sql query for job 1254 and task 2 +DETAIL: query string: "SELECT o_orderkey, o_shippriority FROM orders_102016 orders WHERE (o_totalprice <> 4.0)" +DEBUG: generated sql query for job 1254 and task 4 +DETAIL: query string: "SELECT o_orderkey, o_shippriority FROM orders_102015 orders WHERE (o_totalprice <> 4.0)" +DEBUG: assigned task 4 to node localhost:57637 +DEBUG: assigned task 2 to node localhost:57638 +DEBUG: join prunable for task partitionId 0 and 1 +DEBUG: join prunable for task partitionId 0 and 2 +DEBUG: join prunable for task partitionId 0 and 3 +DEBUG: join prunable for task partitionId 1 and 0 +DEBUG: join prunable for task partitionId 1 and 2 +DEBUG: join prunable for task partitionId 1 and 3 +DEBUG: join prunable for task partitionId 2 and 0 +DEBUG: join prunable for task partitionId 2 and 1 +DEBUG: join prunable for task partitionId 2 and 3 +DEBUG: join prunable for task partitionId 3 and 0 +DEBUG: join prunable for task partitionId 3 and 1 +DEBUG: join prunable for task partitionId 3 and 2 +DEBUG: generated sql query for job 1255 and task 3 +DETAIL: query string: "SELECT "pg_merge_job_1253.task_000013".intermediate_column_1253_0 AS l_partkey, "pg_merge_job_1254.task_000005".intermediate_column_1254_0 AS o_orderkey, count(*) AS count FROM (pg_merge_job_1253.task_000013 "pg_merge_job_1253.task_000013" JOIN pg_merge_job_1254.task_000005 "pg_merge_job_1254.task_000005" ON (("pg_merge_job_1253.task_000013".intermediate_column_1253_1 = "pg_merge_job_1254.task_000005".intermediate_column_1254_1))) WHERE true GROUP BY "pg_merge_job_1253.task_000013".intermediate_column_1253_0, "pg_merge_job_1254.task_000005".intermediate_column_1254_0" +DEBUG: generated sql query for job 1255 and task 6 +DETAIL: query string: "SELECT "pg_merge_job_1253.task_000020".intermediate_column_1253_0 AS l_partkey, "pg_merge_job_1254.task_000008".intermediate_column_1254_0 AS o_orderkey, count(*) AS count FROM (pg_merge_job_1253.task_000020 "pg_merge_job_1253.task_000020" JOIN pg_merge_job_1254.task_000008 "pg_merge_job_1254.task_000008" ON (("pg_merge_job_1253.task_000020".intermediate_column_1253_1 = "pg_merge_job_1254.task_000008".intermediate_column_1254_1))) WHERE true GROUP BY "pg_merge_job_1253.task_000020".intermediate_column_1253_0, "pg_merge_job_1254.task_000008".intermediate_column_1254_0" +DEBUG: generated sql query for job 1255 and task 9 +DETAIL: query string: "SELECT "pg_merge_job_1253.task_000027".intermediate_column_1253_0 AS l_partkey, "pg_merge_job_1254.task_000011".intermediate_column_1254_0 AS o_orderkey, count(*) AS count FROM (pg_merge_job_1253.task_000027 "pg_merge_job_1253.task_000027" JOIN pg_merge_job_1254.task_000011 "pg_merge_job_1254.task_000011" ON (("pg_merge_job_1253.task_000027".intermediate_column_1253_1 = "pg_merge_job_1254.task_000011".intermediate_column_1254_1))) WHERE true GROUP BY "pg_merge_job_1253.task_000027".intermediate_column_1253_0, "pg_merge_job_1254.task_000011".intermediate_column_1254_0" +DEBUG: generated sql query for job 1255 and task 12 +DETAIL: query string: "SELECT "pg_merge_job_1253.task_000034".intermediate_column_1253_0 AS l_partkey, "pg_merge_job_1254.task_000014".intermediate_column_1254_0 AS o_orderkey, count(*) AS count FROM (pg_merge_job_1253.task_000034 "pg_merge_job_1253.task_000034" JOIN pg_merge_job_1254.task_000014 "pg_merge_job_1254.task_000014" ON (("pg_merge_job_1253.task_000034".intermediate_column_1253_1 = "pg_merge_job_1254.task_000014".intermediate_column_1254_1))) WHERE true GROUP BY "pg_merge_job_1253.task_000034".intermediate_column_1253_0, "pg_merge_job_1254.task_000014".intermediate_column_1254_0" +DEBUG: pruning merge fetch taskId 1 +DETAIL: Creating dependency on merge taskId 13 +DEBUG: pruning merge fetch taskId 2 +DETAIL: Creating dependency on merge taskId 5 +DEBUG: pruning merge fetch taskId 4 +DETAIL: Creating dependency on merge taskId 20 +DEBUG: pruning merge fetch taskId 5 +DETAIL: Creating dependency on merge taskId 8 +DEBUG: pruning merge fetch taskId 7 +DETAIL: Creating dependency on merge taskId 27 +DEBUG: pruning merge fetch taskId 8 +DETAIL: Creating dependency on merge taskId 11 +DEBUG: pruning merge fetch taskId 10 +DETAIL: Creating dependency on merge taskId 34 +DEBUG: pruning merge fetch taskId 11 +DETAIL: Creating dependency on merge taskId 14 +DEBUG: assigned task 3 to node localhost:57638 +DEBUG: assigned task 6 to node localhost:57637 +DEBUG: assigned task 9 to node localhost:57638 +DEBUG: assigned task 12 to node localhost:57637 +DEBUG: completed cleanup query for job 1255 on node "localhost:57638" +DEBUG: completed cleanup query for job 1255 on node "localhost:57637" +DEBUG: completed cleanup query for job 1253 on node "localhost:57638" +DEBUG: completed cleanup query for job 1253 on node "localhost:57637" +DEBUG: completed cleanup query for job 1254 on node "localhost:57638" +DEBUG: completed cleanup query for job 1254 on node "localhost:57637" +DEBUG: CommitTransactionCommand + l_partkey | o_orderkey | count +-----------+------------+------- +(0 rows) + +-- Reset client logging level to its previous value +SET client_min_messages TO NOTICE; +DEBUG: StartTransactionCommand +DEBUG: ProcessUtility +COMMIT; diff --git a/src/test/regress/expected/multi_large_table_join_planning_0.out b/src/test/regress/expected/multi_large_table_join_planning_0.out new file mode 100644 index 000000000..48c7f8a77 --- /dev/null +++ b/src/test/regress/expected/multi_large_table_join_planning_0.out @@ -0,0 +1,237 @@ +-- +-- MULTI_LARGE_TABLE_PLANNING +-- +-- Tests that cover large table join planning. Note that we explicitly start a +-- transaction block here so that we don't emit debug messages with changing +-- transaction ids in them. Also, we set the executor type to task tracker +-- executor here, as we cannot run repartition jobs with real time executor. +BEGIN; +SET client_min_messages TO DEBUG4; +DEBUG: CommitTransactionCommand +SET citusdb.large_table_shard_count TO 2; +DEBUG: StartTransactionCommand +DEBUG: ProcessUtility +DEBUG: CommitTransactionCommand +SET citusdb.task_executor_type TO 'task-tracker'; +DEBUG: StartTransactionCommand +DEBUG: ProcessUtility +DEBUG: CommitTransactionCommand +-- Debug4 log messages display jobIds within them. We explicitly set the jobId +-- sequence here so that the regression output becomes independent of the number +-- of jobs executed prior to running this test. +ALTER SEQUENCE pg_catalog.pg_dist_jobid_seq RESTART 1250; +DEBUG: StartTransactionCommand +DEBUG: ProcessUtility +DEBUG: CommitTransactionCommand +-- Multi-level repartition join to verify our projection columns are correctly +-- referenced and propagated across multiple repartition jobs. The test also +-- validates that only the minimal necessary projection columns are transferred +-- between jobs. +SELECT + l_partkey, o_orderkey, count(*) +FROM + lineitem, part, orders, customer +WHERE + l_orderkey = o_orderkey AND + l_partkey = p_partkey AND + c_custkey = o_custkey AND + (l_quantity > 5.0 OR l_extendedprice > 1200.0) AND + p_size > 8 AND o_totalprice > 10 AND + c_acctbal < 5000.0 +GROUP BY + l_partkey, o_orderkey +ORDER BY + l_partkey, o_orderkey +LIMIT 30; +DEBUG: StartTransactionCommand +DEBUG: push down of limit count: 30 +DEBUG: join prunable for intervals [13921,14947] and [1,5986] +DEBUG: join prunable for intervals [11554,13920] and [1,5986] +DEBUG: join prunable for intervals [8997,11554] and [1,5986] +DEBUG: join prunable for intervals [4965,5986] and [8997,14946] +DEBUG: join prunable for intervals [2497,4964] and [8997,14946] +DEBUG: join prunable for intervals [1,2496] and [8997,14946] +DEBUG: generated sql query for job 1250 and task 3 +DETAIL: query string: "SELECT lineitem.l_partkey, orders.o_orderkey, lineitem.l_quantity, lineitem.l_extendedprice, orders.o_custkey FROM (lineitem_102014 lineitem JOIN orders_102016 orders ON ((lineitem.l_orderkey = orders.o_orderkey))) WHERE (orders.o_totalprice > 10::numeric)" +DEBUG: generated sql query for job 1250 and task 6 +DETAIL: query string: "SELECT lineitem.l_partkey, orders.o_orderkey, lineitem.l_quantity, lineitem.l_extendedprice, orders.o_custkey FROM (lineitem_102013 lineitem JOIN orders_102016 orders ON ((lineitem.l_orderkey = orders.o_orderkey))) WHERE (orders.o_totalprice > 10::numeric)" +DEBUG: generated sql query for job 1250 and task 9 +DETAIL: query string: "SELECT lineitem.l_partkey, orders.o_orderkey, lineitem.l_quantity, lineitem.l_extendedprice, orders.o_custkey FROM (lineitem_102012 lineitem JOIN orders_102016 orders ON ((lineitem.l_orderkey = orders.o_orderkey))) WHERE (orders.o_totalprice > 10::numeric)" +DEBUG: generated sql query for job 1250 and task 12 +DETAIL: query string: "SELECT lineitem.l_partkey, orders.o_orderkey, lineitem.l_quantity, lineitem.l_extendedprice, orders.o_custkey FROM (lineitem_102011 lineitem JOIN orders_102015 orders ON ((lineitem.l_orderkey = orders.o_orderkey))) WHERE (orders.o_totalprice > 10::numeric)" +DEBUG: generated sql query for job 1250 and task 15 +DETAIL: query string: "SELECT lineitem.l_partkey, orders.o_orderkey, lineitem.l_quantity, lineitem.l_extendedprice, orders.o_custkey FROM (lineitem_102010 lineitem JOIN orders_102015 orders ON ((lineitem.l_orderkey = orders.o_orderkey))) WHERE (orders.o_totalprice > 10::numeric)" +DEBUG: generated sql query for job 1250 and task 18 +DETAIL: query string: "SELECT lineitem.l_partkey, orders.o_orderkey, lineitem.l_quantity, lineitem.l_extendedprice, orders.o_custkey FROM (lineitem_102009 lineitem JOIN orders_102015 orders ON ((lineitem.l_orderkey = orders.o_orderkey))) WHERE (orders.o_totalprice > 10::numeric)" +DEBUG: assigned task 18 to node localhost:57637 +DEBUG: assigned task 15 to node localhost:57638 +DEBUG: assigned task 12 to node localhost:57637 +DEBUG: assigned task 9 to node localhost:57638 +DEBUG: assigned task 6 to node localhost:57637 +DEBUG: assigned task 3 to node localhost:57638 +DEBUG: join prunable for intervals [1,1000] and [6001,7000] +DEBUG: join prunable for intervals [6001,7000] and [1,1000] +DEBUG: generated sql query for job 1251 and task 3 +DETAIL: query string: "SELECT "pg_merge_job_1250.task_000019".intermediate_column_1250_0, "pg_merge_job_1250.task_000019".intermediate_column_1250_1, "pg_merge_job_1250.task_000019".intermediate_column_1250_2, "pg_merge_job_1250.task_000019".intermediate_column_1250_3, "pg_merge_job_1250.task_000019".intermediate_column_1250_4 FROM (pg_merge_job_1250.task_000019 "pg_merge_job_1250.task_000019" JOIN part_102019 part ON (("pg_merge_job_1250.task_000019".intermediate_column_1250_0 = part.p_partkey))) WHERE (part.p_size > 8)" +DEBUG: generated sql query for job 1251 and task 6 +DETAIL: query string: "SELECT "pg_merge_job_1250.task_000026".intermediate_column_1250_0, "pg_merge_job_1250.task_000026".intermediate_column_1250_1, "pg_merge_job_1250.task_000026".intermediate_column_1250_2, "pg_merge_job_1250.task_000026".intermediate_column_1250_3, "pg_merge_job_1250.task_000026".intermediate_column_1250_4 FROM (pg_merge_job_1250.task_000026 "pg_merge_job_1250.task_000026" JOIN part_102035 part ON (("pg_merge_job_1250.task_000026".intermediate_column_1250_0 = part.p_partkey))) WHERE (part.p_size > 8)" +DEBUG: pruning merge fetch taskId 1 +DETAIL: Creating dependency on merge taskId 19 +DEBUG: pruning merge fetch taskId 4 +DETAIL: Creating dependency on merge taskId 26 +DEBUG: assigned task 3 to node localhost:57637 +DEBUG: assigned task 6 to node localhost:57638 +DEBUG: join prunable for intervals [1,1000] and [1001,2000] +DEBUG: join prunable for intervals [1,1000] and [6001,7000] +DEBUG: join prunable for intervals [1001,2000] and [6001,7000] +DEBUG: join prunable for intervals [1001,2000] and [1,1000] +DEBUG: join prunable for intervals [6001,7000] and [1001,2000] +DEBUG: join prunable for intervals [6001,7000] and [1,1000] +DEBUG: generated sql query for job 1252 and task 3 +DETAIL: query string: "SELECT "pg_merge_job_1251.task_000007".intermediate_column_1251_0 AS l_partkey, "pg_merge_job_1251.task_000007".intermediate_column_1251_1 AS o_orderkey, count(*) AS count FROM (pg_merge_job_1251.task_000007 "pg_merge_job_1251.task_000007" JOIN customer_102017 customer ON ((customer.c_custkey = "pg_merge_job_1251.task_000007".intermediate_column_1251_4))) WHERE ((("pg_merge_job_1251.task_000007".intermediate_column_1251_2 > 5.0) OR ("pg_merge_job_1251.task_000007".intermediate_column_1251_3 > 1200.0)) AND (customer.c_acctbal < 5000.0)) GROUP BY "pg_merge_job_1251.task_000007".intermediate_column_1251_0, "pg_merge_job_1251.task_000007".intermediate_column_1251_1 ORDER BY "pg_merge_job_1251.task_000007".intermediate_column_1251_0, "pg_merge_job_1251.task_000007".intermediate_column_1251_1, "pg_merge_job_1251.task_000007".intermediate_column_1251_0, "pg_merge_job_1251.task_000007".intermediate_column_1251_1 LIMIT 30::bigint" +DEBUG: generated sql query for job 1252 and task 6 +DETAIL: query string: "SELECT "pg_merge_job_1251.task_000010".intermediate_column_1251_0 AS l_partkey, "pg_merge_job_1251.task_000010".intermediate_column_1251_1 AS o_orderkey, count(*) AS count FROM (pg_merge_job_1251.task_000010 "pg_merge_job_1251.task_000010" JOIN customer_102034 customer ON ((customer.c_custkey = "pg_merge_job_1251.task_000010".intermediate_column_1251_4))) WHERE ((("pg_merge_job_1251.task_000010".intermediate_column_1251_2 > 5.0) OR ("pg_merge_job_1251.task_000010".intermediate_column_1251_3 > 1200.0)) AND (customer.c_acctbal < 5000.0)) GROUP BY "pg_merge_job_1251.task_000010".intermediate_column_1251_0, "pg_merge_job_1251.task_000010".intermediate_column_1251_1 ORDER BY "pg_merge_job_1251.task_000010".intermediate_column_1251_0, "pg_merge_job_1251.task_000010".intermediate_column_1251_1, "pg_merge_job_1251.task_000010".intermediate_column_1251_0, "pg_merge_job_1251.task_000010".intermediate_column_1251_1 LIMIT 30::bigint" +DEBUG: generated sql query for job 1252 and task 9 +DETAIL: query string: "SELECT "pg_merge_job_1251.task_000013".intermediate_column_1251_0 AS l_partkey, "pg_merge_job_1251.task_000013".intermediate_column_1251_1 AS o_orderkey, count(*) AS count FROM (pg_merge_job_1251.task_000013 "pg_merge_job_1251.task_000013" JOIN customer_102033 customer ON ((customer.c_custkey = "pg_merge_job_1251.task_000013".intermediate_column_1251_4))) WHERE ((("pg_merge_job_1251.task_000013".intermediate_column_1251_2 > 5.0) OR ("pg_merge_job_1251.task_000013".intermediate_column_1251_3 > 1200.0)) AND (customer.c_acctbal < 5000.0)) GROUP BY "pg_merge_job_1251.task_000013".intermediate_column_1251_0, "pg_merge_job_1251.task_000013".intermediate_column_1251_1 ORDER BY "pg_merge_job_1251.task_000013".intermediate_column_1251_0, "pg_merge_job_1251.task_000013".intermediate_column_1251_1, "pg_merge_job_1251.task_000013".intermediate_column_1251_0, "pg_merge_job_1251.task_000013".intermediate_column_1251_1 LIMIT 30::bigint" +DEBUG: pruning merge fetch taskId 1 +DETAIL: Creating dependency on merge taskId 7 +DEBUG: pruning merge fetch taskId 4 +DETAIL: Creating dependency on merge taskId 10 +DEBUG: pruning merge fetch taskId 7 +DETAIL: Creating dependency on merge taskId 13 +DEBUG: assigned task 3 to node localhost:57637 +DEBUG: assigned task 9 to node localhost:57638 +DEBUG: assigned task 6 to node localhost:57637 +DEBUG: completed cleanup query for job 1252 on node "localhost:57638" +DEBUG: completed cleanup query for job 1252 on node "localhost:57637" +DEBUG: completed cleanup query for job 1251 on node "localhost:57638" +DEBUG: completed cleanup query for job 1251 on node "localhost:57637" +DEBUG: completed cleanup query for job 1250 on node "localhost:57638" +DEBUG: completed cleanup query for job 1250 on node "localhost:57637" +DEBUG: CommitTransactionCommand + l_partkey | o_orderkey | count +-----------+------------+------- + 18 | 12005 | 1 + 79 | 5121 | 1 + 91 | 2883 | 1 + 222 | 9413 | 1 + 278 | 1287 | 1 + 309 | 2374 | 1 + 318 | 321 | 1 + 321 | 5984 | 1 + 337 | 10403 | 1 + 350 | 13698 | 1 + 358 | 4323 | 1 + 364 | 9347 | 1 + 416 | 640 | 1 + 426 | 10855 | 1 + 450 | 35 | 1 + 484 | 3843 | 1 + 504 | 14566 | 1 + 510 | 13569 | 1 + 532 | 3175 | 1 + 641 | 134 | 1 + 669 | 10944 | 1 + 716 | 2885 | 1 + 738 | 4355 | 1 + 802 | 2534 | 1 + 824 | 9287 | 1 + 864 | 3175 | 1 + 957 | 4293 | 1 + 960 | 10980 | 1 + 963 | 4580 | 1 + 6014 | 4614 | 1 +(30 rows) + +SELECT + l_partkey, o_orderkey, count(*) +FROM + lineitem, orders +WHERE + l_suppkey = o_shippriority AND + l_quantity < 5.0 AND o_totalprice <> 4.0 +GROUP BY + l_partkey, o_orderkey +ORDER BY + l_partkey, o_orderkey; +DEBUG: StartTransactionCommand +DEBUG: generated sql query for job 1253 and task 2 +DETAIL: query string: "SELECT l_partkey, l_suppkey FROM lineitem_102014 lineitem WHERE (l_quantity < 5.0)" +DEBUG: generated sql query for job 1253 and task 4 +DETAIL: query string: "SELECT l_partkey, l_suppkey FROM lineitem_102013 lineitem WHERE (l_quantity < 5.0)" +DEBUG: generated sql query for job 1253 and task 6 +DETAIL: query string: "SELECT l_partkey, l_suppkey FROM lineitem_102012 lineitem WHERE (l_quantity < 5.0)" +DEBUG: generated sql query for job 1253 and task 8 +DETAIL: query string: "SELECT l_partkey, l_suppkey FROM lineitem_102011 lineitem WHERE (l_quantity < 5.0)" +DEBUG: generated sql query for job 1253 and task 10 +DETAIL: query string: "SELECT l_partkey, l_suppkey FROM lineitem_102010 lineitem WHERE (l_quantity < 5.0)" +DEBUG: generated sql query for job 1253 and task 12 +DETAIL: query string: "SELECT l_partkey, l_suppkey FROM lineitem_102009 lineitem WHERE (l_quantity < 5.0)" +DEBUG: assigned task 12 to node localhost:57637 +DEBUG: assigned task 10 to node localhost:57638 +DEBUG: assigned task 8 to node localhost:57637 +DEBUG: assigned task 6 to node localhost:57638 +DEBUG: assigned task 4 to node localhost:57637 +DEBUG: assigned task 2 to node localhost:57638 +DEBUG: generated sql query for job 1254 and task 2 +DETAIL: query string: "SELECT o_orderkey, o_shippriority FROM orders_102016 orders WHERE (o_totalprice <> 4.0)" +DEBUG: generated sql query for job 1254 and task 4 +DETAIL: query string: "SELECT o_orderkey, o_shippriority FROM orders_102015 orders WHERE (o_totalprice <> 4.0)" +DEBUG: assigned task 4 to node localhost:57637 +DEBUG: assigned task 2 to node localhost:57638 +DEBUG: join prunable for task partitionId 0 and 1 +DEBUG: join prunable for task partitionId 0 and 2 +DEBUG: join prunable for task partitionId 0 and 3 +DEBUG: join prunable for task partitionId 1 and 0 +DEBUG: join prunable for task partitionId 1 and 2 +DEBUG: join prunable for task partitionId 1 and 3 +DEBUG: join prunable for task partitionId 2 and 0 +DEBUG: join prunable for task partitionId 2 and 1 +DEBUG: join prunable for task partitionId 2 and 3 +DEBUG: join prunable for task partitionId 3 and 0 +DEBUG: join prunable for task partitionId 3 and 1 +DEBUG: join prunable for task partitionId 3 and 2 +DEBUG: generated sql query for job 1255 and task 3 +DETAIL: query string: "SELECT "pg_merge_job_1253.task_000013".intermediate_column_1253_0 AS l_partkey, "pg_merge_job_1254.task_000005".intermediate_column_1254_0 AS o_orderkey, count(*) AS count FROM (pg_merge_job_1253.task_000013 "pg_merge_job_1253.task_000013" JOIN pg_merge_job_1254.task_000005 "pg_merge_job_1254.task_000005" ON (("pg_merge_job_1253.task_000013".intermediate_column_1253_1 = "pg_merge_job_1254.task_000005".intermediate_column_1254_1))) WHERE true GROUP BY "pg_merge_job_1253.task_000013".intermediate_column_1253_0, "pg_merge_job_1254.task_000005".intermediate_column_1254_0" +DEBUG: generated sql query for job 1255 and task 6 +DETAIL: query string: "SELECT "pg_merge_job_1253.task_000020".intermediate_column_1253_0 AS l_partkey, "pg_merge_job_1254.task_000008".intermediate_column_1254_0 AS o_orderkey, count(*) AS count FROM (pg_merge_job_1253.task_000020 "pg_merge_job_1253.task_000020" JOIN pg_merge_job_1254.task_000008 "pg_merge_job_1254.task_000008" ON (("pg_merge_job_1253.task_000020".intermediate_column_1253_1 = "pg_merge_job_1254.task_000008".intermediate_column_1254_1))) WHERE true GROUP BY "pg_merge_job_1253.task_000020".intermediate_column_1253_0, "pg_merge_job_1254.task_000008".intermediate_column_1254_0" +DEBUG: generated sql query for job 1255 and task 9 +DETAIL: query string: "SELECT "pg_merge_job_1253.task_000027".intermediate_column_1253_0 AS l_partkey, "pg_merge_job_1254.task_000011".intermediate_column_1254_0 AS o_orderkey, count(*) AS count FROM (pg_merge_job_1253.task_000027 "pg_merge_job_1253.task_000027" JOIN pg_merge_job_1254.task_000011 "pg_merge_job_1254.task_000011" ON (("pg_merge_job_1253.task_000027".intermediate_column_1253_1 = "pg_merge_job_1254.task_000011".intermediate_column_1254_1))) WHERE true GROUP BY "pg_merge_job_1253.task_000027".intermediate_column_1253_0, "pg_merge_job_1254.task_000011".intermediate_column_1254_0" +DEBUG: generated sql query for job 1255 and task 12 +DETAIL: query string: "SELECT "pg_merge_job_1253.task_000034".intermediate_column_1253_0 AS l_partkey, "pg_merge_job_1254.task_000014".intermediate_column_1254_0 AS o_orderkey, count(*) AS count FROM (pg_merge_job_1253.task_000034 "pg_merge_job_1253.task_000034" JOIN pg_merge_job_1254.task_000014 "pg_merge_job_1254.task_000014" ON (("pg_merge_job_1253.task_000034".intermediate_column_1253_1 = "pg_merge_job_1254.task_000014".intermediate_column_1254_1))) WHERE true GROUP BY "pg_merge_job_1253.task_000034".intermediate_column_1253_0, "pg_merge_job_1254.task_000014".intermediate_column_1254_0" +DEBUG: pruning merge fetch taskId 1 +DETAIL: Creating dependency on merge taskId 13 +DEBUG: pruning merge fetch taskId 2 +DETAIL: Creating dependency on merge taskId 5 +DEBUG: pruning merge fetch taskId 4 +DETAIL: Creating dependency on merge taskId 20 +DEBUG: pruning merge fetch taskId 5 +DETAIL: Creating dependency on merge taskId 8 +DEBUG: pruning merge fetch taskId 7 +DETAIL: Creating dependency on merge taskId 27 +DEBUG: pruning merge fetch taskId 8 +DETAIL: Creating dependency on merge taskId 11 +DEBUG: pruning merge fetch taskId 10 +DETAIL: Creating dependency on merge taskId 34 +DEBUG: pruning merge fetch taskId 11 +DETAIL: Creating dependency on merge taskId 14 +DEBUG: assigned task 3 to node localhost:57638 +DEBUG: assigned task 6 to node localhost:57637 +DEBUG: assigned task 9 to node localhost:57638 +DEBUG: assigned task 12 to node localhost:57637 +DEBUG: completed cleanup query for job 1255 on node "localhost:57638" +DEBUG: completed cleanup query for job 1255 on node "localhost:57637" +DEBUG: completed cleanup query for job 1253 on node "localhost:57638" +DEBUG: completed cleanup query for job 1253 on node "localhost:57637" +DEBUG: completed cleanup query for job 1254 on node "localhost:57638" +DEBUG: completed cleanup query for job 1254 on node "localhost:57637" +DEBUG: CommitTransactionCommand + l_partkey | o_orderkey | count +-----------+------------+------- +(0 rows) + +-- Reset client logging level to its previous value +SET client_min_messages TO NOTICE; +DEBUG: StartTransactionCommand +DEBUG: ProcessUtility +COMMIT; diff --git a/src/test/regress/expected/multi_large_table_pruning.out b/src/test/regress/expected/multi_large_table_pruning.out new file mode 100644 index 000000000..d957e7669 --- /dev/null +++ b/src/test/regress/expected/multi_large_table_pruning.out @@ -0,0 +1,130 @@ +-- +-- MULTI_LARGE_TABLE_PRUNING +-- +-- Tests covering partition and join-pruning for large table joins. Note that we +-- set executor type to task tracker executor here, as we cannot run repartition +-- jobs with real time executor. +SET citusdb.large_table_shard_count TO 2; +SET client_min_messages TO DEBUG2; +SET citusdb.task_executor_type TO 'task-tracker'; +-- Single range-repartition join to test join-pruning behaviour. +SELECT + count(*) +FROM + orders, customer +WHERE + o_custkey = c_custkey; +DEBUG: join prunable for intervals [1,1000] and [1001,2000] +DEBUG: join prunable for intervals [1,1000] and [6001,7000] +DEBUG: join prunable for intervals [1001,2000] and [6001,7000] +DEBUG: join prunable for intervals [1001,2000] and [1,1000] +DEBUG: join prunable for intervals [6001,7000] and [1001,2000] +DEBUG: join prunable for intervals [6001,7000] and [1,1000] +DEBUG: pruning merge fetch taskId 1 +DETAIL: Creating dependency on merge taskId 5 +DEBUG: pruning merge fetch taskId 4 +DETAIL: Creating dependency on merge taskId 8 +DEBUG: pruning merge fetch taskId 7 +DETAIL: Creating dependency on merge taskId 11 + count +------- + 2984 +(1 row) + +-- Single range-repartition join with a selection clause on the partitioned +-- table to test the case when all map tasks are pruned away. +SELECT + count(*) +FROM + orders, customer +WHERE + o_custkey = c_custkey AND + o_orderkey < 0; +DEBUG: predicate pruning for shardId 102016 +DEBUG: predicate pruning for shardId 102015 + count +------- + +(1 row) + +-- Single range-repartition join with a selection clause on the base table to +-- test the case when all sql tasks are pruned away. +SELECT + count(*) +FROM + orders, customer +WHERE + o_custkey = c_custkey AND + c_custkey < 0; +DEBUG: predicate pruning for shardId 102034 +DEBUG: predicate pruning for shardId 102033 +DEBUG: predicate pruning for shardId 102017 + count +------- + +(1 row) + +-- Dual hash-repartition join test case. Note that this query doesn't produce +-- meaningful results and is only to test hash-partitioning of two large tables +-- on non-partition columns. +SELECT + count(*) +FROM + lineitem, customer +WHERE + l_partkey = c_nationkey; +DEBUG: join prunable for task partitionId 0 and 1 +DEBUG: join prunable for task partitionId 0 and 2 +DEBUG: join prunable for task partitionId 0 and 3 +DEBUG: join prunable for task partitionId 1 and 0 +DEBUG: join prunable for task partitionId 1 and 2 +DEBUG: join prunable for task partitionId 1 and 3 +DEBUG: join prunable for task partitionId 2 and 0 +DEBUG: join prunable for task partitionId 2 and 1 +DEBUG: join prunable for task partitionId 2 and 3 +DEBUG: join prunable for task partitionId 3 and 0 +DEBUG: join prunable for task partitionId 3 and 1 +DEBUG: join prunable for task partitionId 3 and 2 +DEBUG: pruning merge fetch taskId 1 +DETAIL: Creating dependency on merge taskId 13 +DEBUG: pruning merge fetch taskId 2 +DETAIL: Creating dependency on merge taskId 7 +DEBUG: pruning merge fetch taskId 4 +DETAIL: Creating dependency on merge taskId 20 +DEBUG: pruning merge fetch taskId 5 +DETAIL: Creating dependency on merge taskId 11 +DEBUG: pruning merge fetch taskId 7 +DETAIL: Creating dependency on merge taskId 27 +DEBUG: pruning merge fetch taskId 8 +DETAIL: Creating dependency on merge taskId 15 +DEBUG: pruning merge fetch taskId 10 +DETAIL: Creating dependency on merge taskId 34 +DEBUG: pruning merge fetch taskId 11 +DETAIL: Creating dependency on merge taskId 19 + count +------- + 125 +(1 row) + +-- Dual hash-repartition join with a selection clause on one of the tables to +-- test the case when all map tasks are pruned away. +SELECT + count(*) +FROM + lineitem, customer +WHERE + l_partkey = c_nationkey AND + l_orderkey < 0; +DEBUG: predicate pruning for shardId 102014 +DEBUG: predicate pruning for shardId 102013 +DEBUG: predicate pruning for shardId 102012 +DEBUG: predicate pruning for shardId 102011 +DEBUG: predicate pruning for shardId 102010 +DEBUG: predicate pruning for shardId 102009 + count +------- + +(1 row) + +-- Reset client logging level to its previous value +SET client_min_messages TO NOTICE; diff --git a/src/test/regress/expected/multi_large_table_task_assignment.out b/src/test/regress/expected/multi_large_table_task_assignment.out new file mode 100644 index 000000000..9bf12ff00 --- /dev/null +++ b/src/test/regress/expected/multi_large_table_task_assignment.out @@ -0,0 +1,208 @@ +-- +-- MULTI_LARGE_TABLE_TASK_ASSIGNMENT +-- +-- Tests which cover task assignment for MapMerge jobs for single range repartition +-- and dual hash repartition joins. The tests also cover task assignment propagation +-- from a sql task to its depended tasks. Note that we set the executor type to task +-- tracker executor here, as we cannot run repartition jobs with real time executor. +BEGIN; +SET client_min_messages TO DEBUG3; +DEBUG: CommitTransactionCommand +SET citusdb.large_table_shard_count TO 2; +DEBUG: StartTransactionCommand +DEBUG: ProcessUtility +DEBUG: CommitTransactionCommand +SET citusdb.task_executor_type TO 'task-tracker'; +DEBUG: StartTransactionCommand +DEBUG: ProcessUtility +DEBUG: CommitTransactionCommand +-- Single range repartition join to test anchor-shard based task assignment and +-- assignment propagation to merge and data-fetch tasks. +SELECT + count(*) +FROM + orders, customer +WHERE + o_custkey = c_custkey; +DEBUG: StartTransactionCommand +DEBUG: assigned task 4 to node localhost:57637 +DEBUG: assigned task 2 to node localhost:57638 +DEBUG: join prunable for intervals [1,1000] and [1001,2000] +DEBUG: join prunable for intervals [1,1000] and [6001,7000] +DEBUG: join prunable for intervals [1001,2000] and [6001,7000] +DEBUG: join prunable for intervals [1001,2000] and [1,1000] +DEBUG: join prunable for intervals [6001,7000] and [1001,2000] +DEBUG: join prunable for intervals [6001,7000] and [1,1000] +DEBUG: pruning merge fetch taskId 1 +DETAIL: Creating dependency on merge taskId 5 +DEBUG: pruning merge fetch taskId 4 +DETAIL: Creating dependency on merge taskId 8 +DEBUG: pruning merge fetch taskId 7 +DETAIL: Creating dependency on merge taskId 11 +DEBUG: assigned task 3 to node localhost:57637 +DEBUG: assigned task 9 to node localhost:57638 +DEBUG: assigned task 6 to node localhost:57637 +DEBUG: CommitTransactionCommand + count +------- + 2984 +(1 row) + +-- Single range repartition join, along with a join with a small table containing +-- more than one shard. This situation results in multiple sql tasks depending on +-- the same merge task, and tests our constraint group creation and assignment +-- propagation. Here 'orders' is considered the small table. +SET citusdb.large_table_shard_count TO 3; +DEBUG: StartTransactionCommand +DEBUG: ProcessUtility +DEBUG: CommitTransactionCommand +SELECT + count(*) +FROM + orders, customer, lineitem +WHERE + o_custkey = c_custkey AND + o_orderkey = l_orderkey; +DEBUG: StartTransactionCommand +DEBUG: assigned task 15 to node localhost:57637 +DEBUG: assigned task 18 to node localhost:57638 +DEBUG: assigned task 9 to node localhost:57637 +DEBUG: assigned task 12 to node localhost:57638 +DEBUG: assigned task 3 to node localhost:57637 +DEBUG: assigned task 6 to node localhost:57638 +DEBUG: join prunable for intervals [1,2496] and [13921,14947] +DEBUG: join prunable for intervals [1,2496] and [11554,13920] +DEBUG: join prunable for intervals [1,2496] and [8997,11554] +DEBUG: join prunable for intervals [1,2496] and [4965,5986] +DEBUG: join prunable for intervals [1,2496] and [2497,4964] +DEBUG: join prunable for intervals [2497,4964] and [13921,14947] +DEBUG: join prunable for intervals [2497,4964] and [11554,13920] +DEBUG: join prunable for intervals [2497,4964] and [8997,11554] +DEBUG: join prunable for intervals [2497,4964] and [4965,5986] +DEBUG: join prunable for intervals [2497,4964] and [1,2496] +DEBUG: join prunable for intervals [4965,5986] and [13921,14947] +DEBUG: join prunable for intervals [4965,5986] and [11554,13920] +DEBUG: join prunable for intervals [4965,5986] and [8997,11554] +DEBUG: join prunable for intervals [4965,5986] and [2497,4964] +DEBUG: join prunable for intervals [4965,5986] and [1,2496] +DEBUG: join prunable for intervals [8997,11554] and [13921,14947] +DEBUG: join prunable for intervals [8997,11554] and [4965,5986] +DEBUG: join prunable for intervals [8997,11554] and [2497,4964] +DEBUG: join prunable for intervals [8997,11554] and [1,2496] +DEBUG: join prunable for intervals [11554,13920] and [13921,14947] +DEBUG: join prunable for intervals [11554,13920] and [4965,5986] +DEBUG: join prunable for intervals [11554,13920] and [2497,4964] +DEBUG: join prunable for intervals [11554,13920] and [1,2496] +DEBUG: join prunable for intervals [13921,14947] and [11554,13920] +DEBUG: join prunable for intervals [13921,14947] and [8997,11554] +DEBUG: join prunable for intervals [13921,14947] and [4965,5986] +DEBUG: join prunable for intervals [13921,14947] and [2497,4964] +DEBUG: join prunable for intervals [13921,14947] and [1,2496] +DEBUG: pruning merge fetch taskId 1 +DETAIL: Creating dependency on merge taskId 19 +DEBUG: pruning merge fetch taskId 4 +DETAIL: Creating dependency on merge taskId 26 +DEBUG: pruning merge fetch taskId 7 +DETAIL: Creating dependency on merge taskId 33 +DEBUG: pruning merge fetch taskId 10 +DETAIL: Creating dependency on merge taskId 40 +DEBUG: pruning merge fetch taskId 13 +DETAIL: Creating dependency on merge taskId 40 +DEBUG: pruning merge fetch taskId 16 +DETAIL: Creating dependency on merge taskId 47 +DEBUG: pruning merge fetch taskId 19 +DETAIL: Creating dependency on merge taskId 47 +DEBUG: pruning merge fetch taskId 22 +DETAIL: Creating dependency on merge taskId 54 +DEBUG: assigned task 3 to node localhost:57637 +DEBUG: assigned task 6 to node localhost:57638 +DEBUG: assigned task 9 to node localhost:57637 +DEBUG: assigned task 12 to node localhost:57638 +DEBUG: assigned task 18 to node localhost:57637 +DEBUG: assigned task 24 to node localhost:57638 +DEBUG: propagating assignment from merge task 40 to constrained sql task 15 +DEBUG: propagating assignment from merge task 47 to constrained sql task 21 +DEBUG: CommitTransactionCommand + count +------- + 11998 +(1 row) + +SET citusdb.large_table_shard_count TO 2; +DEBUG: StartTransactionCommand +DEBUG: ProcessUtility +DEBUG: CommitTransactionCommand +-- The next test, dual hash repartition join, uses the current jobId to assign +-- tasks in a round-robin fashion. We therefore need to ensure that jobIds start +-- with an odd number here to get consistent test output. +SELECT case when (currval('pg_dist_jobid_seq') % 2) = 0 + then nextval('pg_dist_jobid_seq') % 2 + else 1 end; +DEBUG: StartTransactionCommand +DEBUG: CommitTransactionCommand + case +------ + 1 +(1 row) + +-- Dual hash repartition join which tests the separate hash repartition join +-- task assignment algorithm. +SELECT + count(*) +FROM + lineitem, customer +WHERE + l_partkey = c_nationkey; +DEBUG: StartTransactionCommand +DEBUG: assigned task 12 to node localhost:57637 +DEBUG: assigned task 10 to node localhost:57638 +DEBUG: assigned task 8 to node localhost:57637 +DEBUG: assigned task 6 to node localhost:57638 +DEBUG: assigned task 4 to node localhost:57637 +DEBUG: assigned task 2 to node localhost:57638 +DEBUG: assigned task 6 to node localhost:57637 +DEBUG: assigned task 4 to node localhost:57638 +DEBUG: assigned task 2 to node localhost:57637 +DEBUG: join prunable for task partitionId 0 and 1 +DEBUG: join prunable for task partitionId 0 and 2 +DEBUG: join prunable for task partitionId 0 and 3 +DEBUG: join prunable for task partitionId 1 and 0 +DEBUG: join prunable for task partitionId 1 and 2 +DEBUG: join prunable for task partitionId 1 and 3 +DEBUG: join prunable for task partitionId 2 and 0 +DEBUG: join prunable for task partitionId 2 and 1 +DEBUG: join prunable for task partitionId 2 and 3 +DEBUG: join prunable for task partitionId 3 and 0 +DEBUG: join prunable for task partitionId 3 and 1 +DEBUG: join prunable for task partitionId 3 and 2 +DEBUG: pruning merge fetch taskId 1 +DETAIL: Creating dependency on merge taskId 13 +DEBUG: pruning merge fetch taskId 2 +DETAIL: Creating dependency on merge taskId 7 +DEBUG: pruning merge fetch taskId 4 +DETAIL: Creating dependency on merge taskId 20 +DEBUG: pruning merge fetch taskId 5 +DETAIL: Creating dependency on merge taskId 11 +DEBUG: pruning merge fetch taskId 7 +DETAIL: Creating dependency on merge taskId 27 +DEBUG: pruning merge fetch taskId 8 +DETAIL: Creating dependency on merge taskId 15 +DEBUG: pruning merge fetch taskId 10 +DETAIL: Creating dependency on merge taskId 34 +DEBUG: pruning merge fetch taskId 11 +DETAIL: Creating dependency on merge taskId 19 +DEBUG: assigned task 3 to node localhost:57637 +DEBUG: assigned task 6 to node localhost:57638 +DEBUG: assigned task 9 to node localhost:57637 +DEBUG: assigned task 12 to node localhost:57638 +DEBUG: CommitTransactionCommand + count +------- + 125 +(1 row) + +-- Reset client logging level to its previous value +SET client_min_messages TO NOTICE; +DEBUG: StartTransactionCommand +DEBUG: ProcessUtility +COMMIT; diff --git a/src/test/regress/expected/multi_limit_clause.out b/src/test/regress/expected/multi_limit_clause.out new file mode 100644 index 000000000..18e1adf20 --- /dev/null +++ b/src/test/regress/expected/multi_limit_clause.out @@ -0,0 +1,206 @@ +-- +-- MULTI_LIMIT_CLAUSE +-- +-- Display debug messages on limit clause push down. +SET client_min_messages TO DEBUG1; +-- Check that we can correctly handle the Limit clause in distributed queries. +-- Note that we don't have the limit optimization enabled for these queries, and +-- will end up fetching all rows to the master database. +SELECT count(*) count_quantity, l_quantity FROM lineitem WHERE l_quantity < 32.0 + GROUP BY l_quantity + ORDER BY count_quantity ASC, l_quantity ASC; + count_quantity | l_quantity +----------------+------------ + 219 | 13.00 + 222 | 29.00 + 227 | 3.00 + 229 | 18.00 + 229 | 31.00 + 230 | 14.00 + 230 | 16.00 + 230 | 17.00 + 230 | 26.00 + 232 | 7.00 + 234 | 10.00 + 235 | 15.00 + 236 | 25.00 + 237 | 2.00 + 241 | 12.00 + 242 | 6.00 + 242 | 22.00 + 243 | 1.00 + 243 | 19.00 + 244 | 4.00 + 246 | 20.00 + 249 | 24.00 + 249 | 27.00 + 250 | 8.00 + 250 | 11.00 + 254 | 5.00 + 255 | 21.00 + 258 | 9.00 + 261 | 23.00 + 264 | 30.00 + 273 | 28.00 +(31 rows) + +SELECT count(*) count_quantity, l_quantity FROM lineitem WHERE l_quantity < 32.0 + GROUP BY l_quantity + ORDER BY count_quantity DESC, l_quantity DESC; + count_quantity | l_quantity +----------------+------------ + 273 | 28.00 + 264 | 30.00 + 261 | 23.00 + 258 | 9.00 + 255 | 21.00 + 254 | 5.00 + 250 | 11.00 + 250 | 8.00 + 249 | 27.00 + 249 | 24.00 + 246 | 20.00 + 244 | 4.00 + 243 | 19.00 + 243 | 1.00 + 242 | 22.00 + 242 | 6.00 + 241 | 12.00 + 237 | 2.00 + 236 | 25.00 + 235 | 15.00 + 234 | 10.00 + 232 | 7.00 + 230 | 26.00 + 230 | 17.00 + 230 | 16.00 + 230 | 14.00 + 229 | 31.00 + 229 | 18.00 + 227 | 3.00 + 222 | 29.00 + 219 | 13.00 +(31 rows) + +SELECT count(*) count_quantity, l_quantity FROM lineitem WHERE l_quantity < 32.0 + GROUP BY l_quantity + ORDER BY count_quantity ASC, l_quantity ASC LIMIT 5; + count_quantity | l_quantity +----------------+------------ + 219 | 13.00 + 222 | 29.00 + 227 | 3.00 + 229 | 18.00 + 229 | 31.00 +(5 rows) + +SELECT count(*) count_quantity, l_quantity FROM lineitem WHERE l_quantity < 32.0 + GROUP BY l_quantity + ORDER BY count_quantity ASC, l_quantity ASC LIMIT 10; + count_quantity | l_quantity +----------------+------------ + 219 | 13.00 + 222 | 29.00 + 227 | 3.00 + 229 | 18.00 + 229 | 31.00 + 230 | 14.00 + 230 | 16.00 + 230 | 17.00 + 230 | 26.00 + 232 | 7.00 +(10 rows) + +SELECT count(*) count_quantity, l_quantity FROM lineitem WHERE l_quantity < 32.0 + GROUP BY l_quantity + ORDER BY count_quantity DESC, l_quantity DESC LIMIT 10; + count_quantity | l_quantity +----------------+------------ + 273 | 28.00 + 264 | 30.00 + 261 | 23.00 + 258 | 9.00 + 255 | 21.00 + 254 | 5.00 + 250 | 11.00 + 250 | 8.00 + 249 | 27.00 + 249 | 24.00 +(10 rows) + +-- Check that we can handle limits for simple sort clauses. We order by columns +-- in the first two tests, and then by a simple expression in the last test. +SELECT min(l_orderkey) FROM lineitem; + min +----- + 1 +(1 row) + +SELECT l_orderkey FROM lineitem ORDER BY l_orderkey ASC LIMIT 1; +DEBUG: push down of limit count: 1 + l_orderkey +------------ + 1 +(1 row) + +SELECT max(l_orderkey) FROM lineitem; + max +------- + 14947 +(1 row) + +SELECT l_orderkey FROM lineitem ORDER BY l_orderkey DESC LIMIT 1; +DEBUG: push down of limit count: 1 + l_orderkey +------------ + 14947 +(1 row) + +SELECT * FROM lineitem ORDER BY l_orderkey DESC, l_linenumber DESC LIMIT 3; +DEBUG: push down of limit count: 3 + l_orderkey | l_partkey | l_suppkey | l_linenumber | l_quantity | l_extendedprice | l_discount | l_tax | l_returnflag | l_linestatus | l_shipdate | l_commitdate | l_receiptdate | l_shipinstruct | l_shipmode | l_comment +------------+-----------+-----------+--------------+------------+-----------------+------------+-------+--------------+--------------+------------+--------------+---------------+---------------------------+------------+--------------------------------- + 14947 | 107098 | 7099 | 2 | 29.00 | 32047.61 | 0.04 | 0.06 | N | O | 11-08-1995 | 08-30-1995 | 12-03-1995 | TAKE BACK RETURN | FOB | inal sentiments t + 14947 | 31184 | 3688 | 1 | 14.00 | 15612.52 | 0.09 | 0.02 | N | O | 11-05-1995 | 09-25-1995 | 11-27-1995 | TAKE BACK RETURN | RAIL | bout the even, iro + 14946 | 79479 | 4494 | 2 | 37.00 | 53963.39 | 0.01 | 0.01 | N | O | 11-27-1996 | 02-01-1997 | 11-29-1996 | COLLECT COD | AIR | sleep furiously after the furio +(3 rows) + +SELECT max(extract(epoch from l_shipdate)) FROM lineitem; + max +----------- + 912124800 +(1 row) + +SELECT * FROM lineitem + ORDER BY extract(epoch from l_shipdate) DESC, l_orderkey DESC LIMIT 3; +DEBUG: push down of limit count: 3 + l_orderkey | l_partkey | l_suppkey | l_linenumber | l_quantity | l_extendedprice | l_discount | l_tax | l_returnflag | l_linestatus | l_shipdate | l_commitdate | l_receiptdate | l_shipinstruct | l_shipmode | l_comment +------------+-----------+-----------+--------------+------------+-----------------+------------+-------+--------------+--------------+------------+--------------+---------------+---------------------------+------------+-------------------------------------- + 4678 | 57388 | 9894 | 1 | 35.00 | 47088.30 | 0.04 | 0.08 | N | O | 11-27-1998 | 10-02-1998 | 12-17-1998 | TAKE BACK RETURN | AIR | he accounts. fluffily bold sheaves b + 12384 | 84161 | 1686 | 5 | 6.00 | 6870.96 | 0.04 | 0.00 | N | O | 11-26-1998 | 10-04-1998 | 12-08-1998 | COLLECT COD | RAIL | ep blithely. blithely ironic r + 1124 | 92298 | 4808 | 3 | 35.00 | 45160.15 | 0.10 | 0.05 | N | O | 11-25-1998 | 10-08-1998 | 12-25-1998 | TAKE BACK RETURN | AIR | ut the slyly bold pinto beans; fi +(3 rows) + +-- Exercise the scenario where order by clauses don't have any aggregates, and +-- that we can push down the limit as a result. Check that when this happens, we +-- also sort on all group by clauses behind the covers. +SELECT l_quantity, l_discount, avg(l_partkey) FROM lineitem + GROUP BY l_quantity, l_discount + ORDER BY l_quantity LIMIT 1; +DEBUG: push down of limit count: 1 + l_quantity | l_discount | avg +------------+------------+-------------------- + 1.00 | 0.00 | 99167.304347826087 +(1 row) + +-- Results from the previous query should match this query's results. +SELECT l_quantity, l_discount, avg(l_partkey) FROM lineitem + GROUP BY l_quantity, l_discount + ORDER BY l_quantity, l_discount LIMIT 1; +DEBUG: push down of limit count: 1 + l_quantity | l_discount | avg +------------+------------+-------------------- + 1.00 | 0.00 | 99167.304347826087 +(1 row) + +SET client_min_messages TO NOTICE; diff --git a/src/test/regress/expected/multi_limit_clause_approximate.out b/src/test/regress/expected/multi_limit_clause_approximate.out new file mode 100644 index 000000000..d65c6ae6f --- /dev/null +++ b/src/test/regress/expected/multi_limit_clause_approximate.out @@ -0,0 +1,151 @@ +-- +-- MULTI_LIMIT_CLAUSE_APPROXIMATE +-- +-- Display debug messages on limit clause push down. +SET client_min_messages TO DEBUG1; +-- We first look at results with limit optimization disabled. This first query +-- has a group and an order by. The order by clause is a commutative aggregate +-- function. +SELECT l_partkey, sum(l_partkey * (1 + l_suppkey)) AS aggregate FROM lineitem + GROUP BY l_partkey + ORDER BY aggregate DESC LIMIT 10; + l_partkey | aggregate +-----------+------------ + 194541 | 3727794642 + 160895 | 3671463005 + 183486 | 3128069328 + 179825 | 3093889125 + 162432 | 2834113536 + 153937 | 2761321906 + 199283 | 2726988572 + 185925 | 2672114100 + 196629 | 2622637602 + 157064 | 2614644408 +(10 rows) + +-- Enable limit optimization to fetch one third of each shard's data +SET citusdb.limit_clause_row_fetch_count TO 600; +SELECT l_partkey, sum(l_partkey * (1 + l_suppkey)) AS aggregate FROM lineitem + GROUP BY l_partkey + ORDER BY aggregate DESC LIMIT 10; +DEBUG: push down of limit count: 600 + l_partkey | aggregate +-----------+------------ + 194541 | 3727794642 + 160895 | 3671463005 + 183486 | 3128069328 + 179825 | 3093889125 + 162432 | 2834113536 + 153937 | 2761321906 + 199283 | 2726988572 + 185925 | 2672114100 + 157064 | 2614644408 + 189336 | 2596175232 +(10 rows) + +-- Disable limit optimization for our second test. This time, we have a query +-- that joins several tables, and that groups and orders the results. +RESET citusdb.limit_clause_row_fetch_count; +SELECT c_custkey, c_name, count(*) as lineitem_count + FROM customer, orders, lineitem + WHERE c_custkey = o_custkey AND l_orderkey = o_orderkey + GROUP BY c_custkey, c_name + ORDER BY lineitem_count DESC, c_custkey LIMIT 10; + c_custkey | c_name | lineitem_count +-----------+--------------------+---------------- + 43 | Customer#000000043 | 42 + 370 | Customer#000000370 | 40 + 79 | Customer#000000079 | 38 + 689 | Customer#000000689 | 38 + 685 | Customer#000000685 | 37 + 472 | Customer#000000472 | 36 + 643 | Customer#000000643 | 34 + 226 | Customer#000000226 | 33 + 496 | Customer#000000496 | 32 + 304 | Customer#000000304 | 31 +(10 rows) + +-- Now, enable limit optimization to fetch half of each task's results. For this +-- test, we also change a config setting to ensure that we don't repartition any +-- of the tables during the query. +SET citusdb.limit_clause_row_fetch_count TO 150; +SET citusdb.large_table_shard_count TO 2; +SELECT c_custkey, c_name, count(*) as lineitem_count + FROM customer, orders, lineitem + WHERE c_custkey = o_custkey AND l_orderkey = o_orderkey + GROUP BY c_custkey, c_name + ORDER BY lineitem_count DESC, c_custkey LIMIT 10; +DEBUG: push down of limit count: 150 + c_custkey | c_name | lineitem_count +-----------+--------------------+---------------- + 43 | Customer#000000043 | 42 + 370 | Customer#000000370 | 36 + 689 | Customer#000000689 | 36 + 226 | Customer#000000226 | 33 + 496 | Customer#000000496 | 32 + 685 | Customer#000000685 | 32 + 304 | Customer#000000304 | 31 + 472 | Customer#000000472 | 31 + 79 | Customer#000000079 | 30 + 145 | Customer#000000145 | 30 +(10 rows) + +RESET citusdb.large_table_shard_count; +-- We now test scenarios where applying the limit optimization wouldn't produce +-- meaningful results. First, we check that we don't push down the limit clause +-- for non-commutative aggregates. +SELECT l_partkey, avg(l_suppkey) AS average FROM lineitem + GROUP BY l_partkey + ORDER BY average DESC, l_partkey LIMIT 10; + l_partkey | average +-----------+----------------------- + 9998 | 9999.0000000000000000 + 102466 | 9997.0000000000000000 + 184959 | 9996.0000000000000000 + 17492 | 9994.0000000000000000 + 124966 | 9991.0000000000000000 + 89989 | 9990.0000000000000000 + 32479 | 9989.0000000000000000 + 144960 | 9989.0000000000000000 + 147473 | 9988.0000000000000000 + 37481 | 9985.0000000000000000 +(10 rows) + +-- Next, check that we don't apply the limit optimization for expressions that +-- have aggregates within them +SELECT l_partkey, round(sum(l_suppkey)) AS complex_expression FROM lineitem + GROUP BY l_partkey + ORDER BY complex_expression DESC LIMIT 10; + l_partkey | complex_expression +-----------+-------------------- + 160895 | 22816 + 194541 | 19160 + 37018 | 19044 + 64284 | 18594 + 15283 | 18357 + 1927 | 18284 + 136884 | 18194 + 114073 | 18192 + 1051 | 18156 + 41555 | 18136 +(10 rows) + +-- Check that query execution works as expected for other queries without limits +SELECT count(*) count_quantity, l_quantity FROM lineitem WHERE l_quantity < 10.0 + GROUP BY l_quantity + ORDER BY count_quantity ASC, l_quantity ASC; + count_quantity | l_quantity +----------------+------------ + 227 | 3.00 + 232 | 7.00 + 237 | 2.00 + 242 | 6.00 + 243 | 1.00 + 244 | 4.00 + 250 | 8.00 + 254 | 5.00 + 258 | 9.00 +(9 rows) + +RESET citusdb.limit_clause_row_fetch_count; +RESET client_min_messages; diff --git a/src/test/regress/expected/multi_master_protocol.out b/src/test/regress/expected/multi_master_protocol.out new file mode 100644 index 000000000..3d6e627a5 --- /dev/null +++ b/src/test/regress/expected/multi_master_protocol.out @@ -0,0 +1,53 @@ +-- +-- MULTI_MASTER_PROTOCOL +-- +-- Tests that check the metadata returned by the master node. +SELECT part_storage_type, part_key, part_replica_count, part_max_size, + part_placement_policy FROM master_get_table_metadata('lineitem'); + part_storage_type | part_key | part_replica_count | part_max_size | part_placement_policy +-------------------+------------+--------------------+---------------+----------------------- + t | l_orderkey | 2 | 307200 | 2 +(1 row) + +SELECT * FROM master_get_table_ddl_events('lineitem'); + master_get_table_ddl_events +---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + CREATE TABLE lineitem (l_orderkey bigint NOT NULL, l_partkey integer NOT NULL, l_suppkey integer NOT NULL, l_linenumber integer NOT NULL, l_quantity numeric(15,2) NOT NULL, l_extendedprice numeric(15,2) NOT NULL, l_discount numeric(15,2) NOT NULL, l_tax numeric(15,2) NOT NULL, l_returnflag character(1) NOT NULL, l_linestatus character(1) NOT NULL, l_shipdate date NOT NULL, l_commitdate date NOT NULL, l_receiptdate date NOT NULL, l_shipinstruct character(25) NOT NULL, l_shipmode character(10) NOT NULL, l_comment character varying(44) NOT NULL) + CREATE INDEX lineitem_time_index ON lineitem USING btree (l_shipdate) + ALTER TABLE public.lineitem ADD CONSTRAINT lineitem_pkey PRIMARY KEY (l_orderkey, l_linenumber) +(3 rows) + +SELECT * FROM master_get_new_shardid(); + master_get_new_shardid +------------------------ + 102008 +(1 row) + +SELECT * FROM master_get_local_first_candidate_nodes(); + node_name | node_port +-----------+----------- + localhost | 57638 + localhost | 57637 +(2 rows) + +SELECT * FROM master_get_round_robin_candidate_nodes(1); + node_name | node_port +-----------+----------- + localhost | 57638 + localhost | 57637 +(2 rows) + +SELECT * FROM master_get_round_robin_candidate_nodes(2); + node_name | node_port +-----------+----------- + localhost | 57637 + localhost | 57638 +(2 rows) + +SELECT * FROM master_get_active_worker_nodes(); + node_name | node_port +-----------+----------- + localhost | 57638 + localhost | 57637 +(2 rows) + diff --git a/src/test/regress/expected/multi_master_protocol_0.out b/src/test/regress/expected/multi_master_protocol_0.out new file mode 100644 index 000000000..3f502a931 --- /dev/null +++ b/src/test/regress/expected/multi_master_protocol_0.out @@ -0,0 +1,53 @@ +-- +-- MULTI_MASTER_PROTOCOL +-- +-- Tests that check the metadata returned by the master node. +SELECT part_storage_type, part_key, part_replica_count, part_max_size, + part_placement_policy FROM master_get_table_metadata('lineitem'); + part_storage_type | part_key | part_replica_count | part_max_size | part_placement_policy +-------------------+------------+--------------------+---------------+----------------------- + t | l_orderkey | 2 | 307200 | 2 +(1 row) + +SELECT * FROM master_get_table_ddl_events('lineitem'); + master_get_table_ddl_events +---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + CREATE TABLE lineitem (l_orderkey bigint NOT NULL, l_partkey integer NOT NULL, l_suppkey integer NOT NULL, l_linenumber integer NOT NULL, l_quantity numeric(15,2) NOT NULL, l_extendedprice numeric(15,2) NOT NULL, l_discount numeric(15,2) NOT NULL, l_tax numeric(15,2) NOT NULL, l_returnflag character(1) NOT NULL, l_linestatus character(1) NOT NULL, l_shipdate date NOT NULL, l_commitdate date NOT NULL, l_receiptdate date NOT NULL, l_shipinstruct character(25) NOT NULL, l_shipmode character(10) NOT NULL, l_comment character varying(44) NOT NULL) + CREATE INDEX lineitem_time_index ON lineitem USING btree (l_shipdate) + ALTER TABLE ONLY lineitem ADD CONSTRAINT lineitem_pkey PRIMARY KEY (l_orderkey, l_linenumber) +(3 rows) + +SELECT * FROM master_get_new_shardid(); + master_get_new_shardid +------------------------ + 102008 +(1 row) + +SELECT * FROM master_get_local_first_candidate_nodes(); + node_name | node_port +-----------+----------- + localhost | 57638 + localhost | 57637 +(2 rows) + +SELECT * FROM master_get_round_robin_candidate_nodes(1); + node_name | node_port +-----------+----------- + localhost | 57638 + localhost | 57637 +(2 rows) + +SELECT * FROM master_get_round_robin_candidate_nodes(2); + node_name | node_port +-----------+----------- + localhost | 57637 + localhost | 57638 +(2 rows) + +SELECT * FROM master_get_active_worker_nodes(); + node_name | node_port +-----------+----------- + localhost | 57638 + localhost | 57637 +(2 rows) + diff --git a/src/test/regress/expected/multi_modifications.out b/src/test/regress/expected/multi_modifications.out new file mode 100644 index 000000000..5da80026b --- /dev/null +++ b/src/test/regress/expected/multi_modifications.out @@ -0,0 +1,309 @@ +-- =================================================================== +-- test end-to-end modification functionality +-- =================================================================== +CREATE TYPE order_side AS ENUM ('buy', 'sell'); +CREATE TABLE limit_orders ( + id bigint PRIMARY KEY, + symbol text NOT NULL, + bidder_id bigint NOT NULL, + placed_at timestamp NOT NULL, + kind order_side NOT NULL, + limit_price decimal NOT NULL DEFAULT 0.00 CHECK (limit_price >= 0.00) +); +CREATE TABLE insufficient_shards ( LIKE limit_orders ); +CREATE TABLE range_partitioned ( LIKE limit_orders ); +CREATE TABLE append_partitioned ( LIKE limit_orders ); +SELECT master_create_distributed_table('limit_orders', 'id', 'hash'); + master_create_distributed_table +--------------------------------- + +(1 row) + +SELECT master_create_distributed_table('insufficient_shards', 'id', 'hash'); + master_create_distributed_table +--------------------------------- + +(1 row) + +SELECT master_create_distributed_table('range_partitioned', 'id', 'range'); + master_create_distributed_table +--------------------------------- + +(1 row) + +SELECT master_create_distributed_table('append_partitioned', 'id', 'append'); + master_create_distributed_table +--------------------------------- + +(1 row) + +SELECT master_create_worker_shards('limit_orders', 2, 2); + master_create_worker_shards +----------------------------- + +(1 row) + +-- make a single shard that covers no partition values +SELECT master_create_worker_shards('insufficient_shards', 1, 1); + master_create_worker_shards +----------------------------- + +(1 row) + +UPDATE pg_dist_shard SET shardminvalue = 0, shardmaxvalue = 0 +WHERE logicalrelid = 'insufficient_shards'::regclass; +-- create range-partitioned shards +SELECT master_create_empty_shard('range_partitioned') AS new_shard_id +\gset +UPDATE pg_dist_shard SET shardminvalue = 0, shardmaxvalue = 49999 +WHERE shardid = :new_shard_id; +SELECT master_create_empty_shard('range_partitioned') AS new_shard_id +\gset +UPDATE pg_dist_shard SET shardminvalue = 50000, shardmaxvalue = 99999 +WHERE shardid = :new_shard_id; +-- create append-partitioned shard +SELECT master_create_empty_shard('append_partitioned') AS new_shard_id +\gset +UPDATE pg_dist_shard SET shardminvalue = 0, shardmaxvalue = 100000 +WHERE shardid = :new_shard_id; +-- basic single-row INSERT +INSERT INTO limit_orders VALUES (32743, 'AAPL', 9580, '2004-10-19 10:23:54', 'buy', + 20.69); +SELECT COUNT(*) FROM limit_orders WHERE id = 32743; + count +------- + 1 +(1 row) + +-- try a single-row INSERT with no shard to receive it +INSERT INTO insufficient_shards VALUES (32743, 'AAPL', 9580, '2004-10-19 10:23:54', 'buy', + 20.69); +ERROR: distributed modifications must target exactly one shard +-- try an insert to a range-partitioned table +INSERT INTO range_partitioned VALUES (32743, 'AAPL', 9580, '2004-10-19 10:23:54', 'buy', + 20.69); +-- ensure the value is where we put it and query to find it is properly pruned +SET client_min_messages TO 'DEBUG2'; +SET citusdb.task_executor_type TO 'router'; +SELECT * FROM range_partitioned WHERE id = 32743; +DEBUG: predicate pruning for shardId 103070 + id | symbol | bidder_id | placed_at | kind | limit_price +-------+--------+-----------+--------------------------+------+------------- + 32743 | AAPL | 9580 | Tue Oct 19 10:23:54 2004 | buy | 20.69 +(1 row) + +SET client_min_messages TO DEFAULT; +SET citusdb.task_executor_type TO DEFAULT; +-- also try inserting without a range-partitioned shard to receive the value +INSERT INTO range_partitioned VALUES (999999, 'AAPL', 9580, '2004-10-19 10:23:54', 'buy', + 20.69); +ERROR: distributed modifications must target exactly one shard +-- try an insert to an append-partitioned table +INSERT INTO append_partitioned VALUES (414123, 'AAPL', 9580, '2004-10-19 10:23:54', 'buy', + 20.69); +ERROR: cannot perform distributed planning for the given modification +DETAIL: Only hash- or range-partitioned tables may be the target of distributed modifications +-- INSERT with DEFAULT in the target list +INSERT INTO limit_orders VALUES (12756, 'MSFT', 10959, '2013-05-08 07:29:23', 'sell', + DEFAULT); +SELECT COUNT(*) FROM limit_orders WHERE id = 12756; + count +------- + 1 +(1 row) + +-- INSERT with expressions in target list +INSERT INTO limit_orders VALUES (430, upper('ibm'), 214, timestamp '2003-01-28 10:31:17' + + interval '5 hours', 'buy', sqrt(2)); +SELECT COUNT(*) FROM limit_orders WHERE id = 430; + count +------- + 1 +(1 row) + +-- INSERT without partition key +INSERT INTO limit_orders DEFAULT VALUES; +ERROR: cannot plan INSERT using row with NULL value in partition column +-- squelch WARNINGs that contain worker_port +SET client_min_messages TO ERROR; +-- INSERT violating NOT NULL constraint +INSERT INTO limit_orders VALUES (NULL, 'T', 975234, DEFAULT); +ERROR: cannot plan INSERT using row with NULL value in partition column +-- INSERT violating column constraint +INSERT INTO limit_orders VALUES (18811, 'BUD', 14962, '2014-04-05 08:32:16', 'sell', + -5.00); +ERROR: could not modify any active placements +-- INSERT violating primary key constraint +INSERT INTO limit_orders VALUES (32743, 'LUV', 5994, '2001-04-16 03:37:28', 'buy', 0.58); +ERROR: could not modify any active placements +SET client_min_messages TO DEFAULT; +-- commands with non-constant partition values are unsupported +INSERT INTO limit_orders VALUES (random() * 100, 'ORCL', 152, '2011-08-25 11:50:45', + 'sell', 0.58); +ERROR: cannot plan sharded modification containing values which are not constants or constant expressions +-- commands with expressions that cannot be collapsed are unsupported +INSERT INTO limit_orders VALUES (2036, 'GOOG', 5634, now(), 'buy', random()); +ERROR: cannot plan sharded modification containing values which are not constants or constant expressions +-- commands with mutable functions in their quals +DELETE FROM limit_orders WHERE id = 246 AND bidder_id = (random() * 1000); +ERROR: cannot plan sharded modification containing values which are not constants or constant expressions +-- commands with mutable but non-volatilte functions(ie: stable func.) in their quals +DELETE FROM limit_orders WHERE id = 246 AND placed_at = current_timestamp; +ERROR: cannot plan sharded modification containing values which are not constants or constant expressions +-- commands with multiple rows are unsupported +INSERT INTO limit_orders VALUES (DEFAULT), (DEFAULT); +ERROR: cannot perform distributed planning for the given modification +DETAIL: Multi-row INSERTs to distributed tables are not supported. +-- INSERT ... SELECT ... FROM commands are unsupported +INSERT INTO limit_orders SELECT * FROM limit_orders; +ERROR: cannot perform distributed planning for the given modifications +DETAIL: Subqueries are not supported in distributed modifications. +-- commands with a RETURNING clause are unsupported +INSERT INTO limit_orders VALUES (7285, 'AMZN', 3278, '2016-01-05 02:07:36', 'sell', 0.00) + RETURNING *; +ERROR: cannot perform distributed planning for the given modification +DETAIL: RETURNING clauses are not supported in distributed modifications. +-- commands containing a CTE are unsupported +WITH deleted_orders AS (DELETE FROM limit_orders RETURNING *) +INSERT INTO limit_orders DEFAULT VALUES; +ERROR: cannot perform distributed planning for the given modification +DETAIL: Common table expressions are not supported in distributed modifications. +-- test simple DELETE +INSERT INTO limit_orders VALUES (246, 'TSLA', 162, '2007-07-02 16:32:15', 'sell', 20.69); +SELECT COUNT(*) FROM limit_orders WHERE id = 246; + count +------- + 1 +(1 row) + +DELETE FROM limit_orders WHERE id = 246; +SELECT COUNT(*) FROM limit_orders WHERE id = 246; + count +------- + 0 +(1 row) + +-- DELETE with expression in WHERE clause +INSERT INTO limit_orders VALUES (246, 'TSLA', 162, '2007-07-02 16:32:15', 'sell', 20.69); +SELECT COUNT(*) FROM limit_orders WHERE id = 246; + count +------- + 1 +(1 row) + +DELETE FROM limit_orders WHERE id = (2 * 123); +SELECT COUNT(*) FROM limit_orders WHERE id = 246; + count +------- + 0 +(1 row) + +-- commands with no constraints on the partition key are not supported +DELETE FROM limit_orders WHERE bidder_id = 162; +ERROR: distributed modifications must target exactly one shard +-- commands with a USING clause are unsupported +CREATE TABLE bidders ( name text, id bigint ); +DELETE FROM limit_orders USING bidders WHERE limit_orders.id = 246 AND + limit_orders.bidder_id = bidders.id AND + bidders.name = 'Bernie Madoff'; +ERROR: cannot plan queries that include both regular and partitioned relations +-- commands with a RETURNING clause are unsupported +DELETE FROM limit_orders WHERE id = 246 RETURNING *; +ERROR: cannot perform distributed planning for the given modification +DETAIL: RETURNING clauses are not supported in distributed modifications. +-- commands containing a CTE are unsupported +WITH deleted_orders AS (INSERT INTO limit_orders DEFAULT VALUES RETURNING *) +DELETE FROM limit_orders; +ERROR: cannot perform distributed planning for the given modification +DETAIL: Common table expressions are not supported in distributed modifications. +-- cursors are not supported +DELETE FROM limit_orders WHERE CURRENT OF cursor_name; +ERROR: distributed modifications must target exactly one shard +INSERT INTO limit_orders VALUES (246, 'TSLA', 162, '2007-07-02 16:32:15', 'sell', 20.69); +-- simple UPDATE +UPDATE limit_orders SET symbol = 'GM' WHERE id = 246; +SELECT symbol FROM limit_orders WHERE id = 246; + symbol +-------- + GM +(1 row) + +-- expression UPDATE +UPDATE limit_orders SET bidder_id = 6 * 3 WHERE id = 246; +SELECT bidder_id FROM limit_orders WHERE id = 246; + bidder_id +----------- + 18 +(1 row) + +-- multi-column UPDATE +UPDATE limit_orders SET (kind, limit_price) = ('buy', DEFAULT) WHERE id = 246; +SELECT kind, limit_price FROM limit_orders WHERE id = 246; + kind | limit_price +------+------------- + buy | 0.00 +(1 row) + +-- Test that shards which miss a modification are marked unhealthy +\set first_worker_port 57637 +\set second_worker_port 57638 +-- First: Mark all placements for a node as inactive +UPDATE pg_dist_shard_placement +SET shardstate = 3 +WHERE nodename = 'localhost' AND + nodeport = :first_worker_port; +-- Second: Perform an INSERT to the remaining node +INSERT INTO limit_orders VALUES (275, 'ADR', 140, '2007-07-02 16:32:15', 'sell', 43.67); +-- Third: Mark the original placements as healthy again +UPDATE pg_dist_shard_placement +SET shardstate = 1 +WHERE nodename = 'localhost' AND + nodeport = :first_worker_port; +-- Fourth: Perform the same INSERT (primary key violation) +INSERT INTO limit_orders VALUES (275, 'ADR', 140, '2007-07-02 16:32:15', 'sell', 43.67); +WARNING: Bad result from localhost:57638 +DETAIL: Remote message: duplicate key value violates unique constraint "limit_orders_pkey_103067" +-- Last: Verify the insert worked but the placement with the PK violation is now unhealthy +SELECT count(*) FROM limit_orders WHERE id = 275; + count +------- + 1 +(1 row) + +SELECT count(*) +FROM pg_dist_shard_placement AS sp, + pg_dist_shard AS s +WHERE sp.shardid = s.shardid +AND sp.nodename = 'localhost' +AND sp.nodeport = :second_worker_port +AND sp.shardstate = 3 +AND s.logicalrelid = 'limit_orders'::regclass; + count +------- + 1 +(1 row) + +-- commands with no constraints on the partition key are not supported +UPDATE limit_orders SET limit_price = 0.00; +ERROR: distributed modifications must target exactly one shard +-- attempting to change the partition key is unsupported +UPDATE limit_orders SET id = 0 WHERE id = 246; +ERROR: modifying the partition value of rows is not allowed +-- UPDATEs with a FROM clause are unsupported +UPDATE limit_orders SET limit_price = 0.00 FROM bidders + WHERE limit_orders.id = 246 AND + limit_orders.bidder_id = bidders.id AND + bidders.name = 'Bernie Madoff'; +ERROR: cannot plan queries that include both regular and partitioned relations +-- commands with a RETURNING clause are unsupported +UPDATE limit_orders SET symbol = 'GM' WHERE id = 246 RETURNING *; +ERROR: cannot perform distributed planning for the given modification +DETAIL: RETURNING clauses are not supported in distributed modifications. +-- commands containing a CTE are unsupported +WITH deleted_orders AS (INSERT INTO limit_orders DEFAULT VALUES RETURNING *) +UPDATE limit_orders SET symbol = 'GM'; +ERROR: cannot perform distributed planning for the given modification +DETAIL: Common table expressions are not supported in distributed modifications. +-- cursors are not supported +UPDATE limit_orders SET symbol = 'GM' WHERE CURRENT OF cursor_name; +ERROR: distributed modifications must target exactly one shard diff --git a/src/test/regress/expected/multi_null_minmax_value_pruning.out b/src/test/regress/expected/multi_null_minmax_value_pruning.out new file mode 100644 index 000000000..53e5a10a5 --- /dev/null +++ b/src/test/regress/expected/multi_null_minmax_value_pruning.out @@ -0,0 +1,142 @@ +-- +-- MULTI_NULL_MINMAX_VALUE_PRUNING +-- +-- This test checks that we can handle null min/max values in shard statistics +-- and that we don't partition or join prune shards that have null values. +SET client_min_messages TO DEBUG2; +-- Change configuration to treat lineitem and orders tables as large +SET citusdb.large_table_shard_count TO 2; +SELECT shardminvalue, shardmaxvalue from pg_dist_shard WHERE shardid = 102009; + shardminvalue | shardmaxvalue +---------------+--------------- + 1 | 2496 +(1 row) + +SELECT shardminvalue, shardmaxvalue from pg_dist_shard WHERE shardid = 102010; + shardminvalue | shardmaxvalue +---------------+--------------- + 2497 | 4964 +(1 row) + +-- Check that partition and join pruning works when min/max values exist +SELECT l_orderkey, l_linenumber, l_shipdate FROM lineitem WHERE l_orderkey = 9030; +DEBUG: predicate pruning for shardId 102014 +DEBUG: predicate pruning for shardId 102013 +DEBUG: predicate pruning for shardId 102011 +DEBUG: predicate pruning for shardId 102010 +DEBUG: predicate pruning for shardId 102009 + l_orderkey | l_linenumber | l_shipdate +------------+--------------+------------ + 9030 | 1 | 09-02-1998 + 9030 | 2 | 08-19-1998 + 9030 | 3 | 08-27-1998 + 9030 | 4 | 07-20-1998 + 9030 | 5 | 09-29-1998 + 9030 | 6 | 09-03-1998 +(6 rows) + +SELECT sum(l_linenumber), avg(l_linenumber) FROM lineitem, orders + WHERE l_orderkey = o_orderkey; +DEBUG: join prunable for intervals [13921,14947] and [1,5986] +DEBUG: join prunable for intervals [11554,13920] and [1,5986] +DEBUG: join prunable for intervals [8997,11554] and [1,5986] +DEBUG: join prunable for intervals [4965,5986] and [8997,14946] +DEBUG: join prunable for intervals [2497,4964] and [8997,14946] +DEBUG: join prunable for intervals [1,2496] and [8997,14946] + sum | avg +-------+-------------------- + 36086 | 3.0076679446574429 +(1 row) + +-- Now set the minimum value for a shard to null. Then check that we don't apply +-- partition or join pruning for the shard with null min value. +UPDATE pg_dist_shard SET shardminvalue = NULL WHERE shardid = 102009; +SELECT l_orderkey, l_linenumber, l_shipdate FROM lineitem WHERE l_orderkey = 9030; +DEBUG: predicate pruning for shardId 102014 +DEBUG: predicate pruning for shardId 102013 +DEBUG: predicate pruning for shardId 102011 +DEBUG: predicate pruning for shardId 102010 + l_orderkey | l_linenumber | l_shipdate +------------+--------------+------------ + 9030 | 1 | 09-02-1998 + 9030 | 2 | 08-19-1998 + 9030 | 3 | 08-27-1998 + 9030 | 4 | 07-20-1998 + 9030 | 5 | 09-29-1998 + 9030 | 6 | 09-03-1998 +(6 rows) + +SELECT sum(l_linenumber), avg(l_linenumber) FROM lineitem, orders + WHERE l_orderkey = o_orderkey; +DEBUG: join prunable for intervals [13921,14947] and [1,5986] +DEBUG: join prunable for intervals [11554,13920] and [1,5986] +DEBUG: join prunable for intervals [8997,11554] and [1,5986] +DEBUG: join prunable for intervals [4965,5986] and [8997,14946] +DEBUG: join prunable for intervals [2497,4964] and [8997,14946] + sum | avg +-------+-------------------- + 36086 | 3.0076679446574429 +(1 row) + +-- Next, set the maximum value for another shard to null. Then check that we +-- don't apply partition or join pruning for this other shard either. +UPDATE pg_dist_shard SET shardmaxvalue = NULL WHERE shardid = 102010; +SELECT l_orderkey, l_linenumber, l_shipdate FROM lineitem WHERE l_orderkey = 9030; +DEBUG: predicate pruning for shardId 102014 +DEBUG: predicate pruning for shardId 102013 +DEBUG: predicate pruning for shardId 102011 + l_orderkey | l_linenumber | l_shipdate +------------+--------------+------------ + 9030 | 1 | 09-02-1998 + 9030 | 2 | 08-19-1998 + 9030 | 3 | 08-27-1998 + 9030 | 4 | 07-20-1998 + 9030 | 5 | 09-29-1998 + 9030 | 6 | 09-03-1998 +(6 rows) + +SELECT sum(l_linenumber), avg(l_linenumber) FROM lineitem, orders + WHERE l_orderkey = o_orderkey; +DEBUG: join prunable for intervals [13921,14947] and [1,5986] +DEBUG: join prunable for intervals [11554,13920] and [1,5986] +DEBUG: join prunable for intervals [8997,11554] and [1,5986] +DEBUG: join prunable for intervals [4965,5986] and [8997,14946] + sum | avg +-------+-------------------- + 36086 | 3.0076679446574429 +(1 row) + +-- Last, set the minimum value to 0 and check that we don't treat it as null. We +-- should apply partition and join pruning for this shard now. +UPDATE pg_dist_shard SET shardminvalue = '0' WHERE shardid = 102009; +SELECT l_orderkey, l_linenumber, l_shipdate FROM lineitem WHERE l_orderkey = 9030; +DEBUG: predicate pruning for shardId 102014 +DEBUG: predicate pruning for shardId 102013 +DEBUG: predicate pruning for shardId 102011 +DEBUG: predicate pruning for shardId 102009 + l_orderkey | l_linenumber | l_shipdate +------------+--------------+------------ + 9030 | 1 | 09-02-1998 + 9030 | 2 | 08-19-1998 + 9030 | 3 | 08-27-1998 + 9030 | 4 | 07-20-1998 + 9030 | 5 | 09-29-1998 + 9030 | 6 | 09-03-1998 +(6 rows) + +SELECT sum(l_linenumber), avg(l_linenumber) FROM lineitem, orders + WHERE l_orderkey = o_orderkey; +DEBUG: join prunable for intervals [13921,14947] and [1,5986] +DEBUG: join prunable for intervals [11554,13920] and [1,5986] +DEBUG: join prunable for intervals [8997,11554] and [1,5986] +DEBUG: join prunable for intervals [4965,5986] and [8997,14946] +DEBUG: join prunable for intervals [0,2496] and [8997,14946] + sum | avg +-------+-------------------- + 36086 | 3.0076679446574429 +(1 row) + +-- Set minimum and maximum values for two shards back to their original values +UPDATE pg_dist_shard SET shardminvalue = '1' WHERE shardid = 102009; +UPDATE pg_dist_shard SET shardmaxvalue = '4964' WHERE shardid = 102010; +SET client_min_messages TO NOTICE; diff --git a/src/test/regress/expected/multi_partition_pruning.out b/src/test/regress/expected/multi_partition_pruning.out new file mode 100644 index 000000000..cc312078b --- /dev/null +++ b/src/test/regress/expected/multi_partition_pruning.out @@ -0,0 +1,180 @@ +-- +-- MULTI_PARTITION_PRUNING +-- +-- Tests to verify that we correctly prune unreferenced shards. For this, we +-- need to increase the logging verbosity of messages displayed on the client. +SET client_min_messages TO DEBUG2; +SELECT l_orderkey, l_linenumber, l_shipdate FROM lineitem WHERE l_orderkey = 9030; +DEBUG: predicate pruning for shardId 102014 +DEBUG: predicate pruning for shardId 102013 +DEBUG: predicate pruning for shardId 102011 +DEBUG: predicate pruning for shardId 102010 +DEBUG: predicate pruning for shardId 102009 + l_orderkey | l_linenumber | l_shipdate +------------+--------------+------------ + 9030 | 1 | 09-02-1998 + 9030 | 2 | 08-19-1998 + 9030 | 3 | 08-27-1998 + 9030 | 4 | 07-20-1998 + 9030 | 5 | 09-29-1998 + 9030 | 6 | 09-03-1998 +(6 rows) + +-- We use the l_linenumber field for the following aggregations. We need to use +-- an integer type, as aggregations on numerics or big integers return numerics +-- of unknown length. When the numerics are read into our temporary table, they +-- trigger the the creation of toasted tables and indexes. This in turn prints +-- non-deterministic debug messages. To avoid this chain, we use l_linenumber. +SELECT sum(l_linenumber), avg(l_linenumber) FROM lineitem WHERE l_orderkey > 9030; +DEBUG: predicate pruning for shardId 102011 +DEBUG: predicate pruning for shardId 102010 +DEBUG: predicate pruning for shardId 102009 + sum | avg +-------+-------------------- + 17999 | 3.0189533713518953 +(1 row) + +SELECT sum(l_linenumber), avg(l_linenumber) FROM lineitem + WHERE (l_orderkey < 4000 OR l_orderkey > 9030); +DEBUG: predicate pruning for shardId 102011 + sum | avg +-------+-------------------- + 30184 | 3.0159872102318145 +(1 row) + +-- The following query should prune out all shards and return empty results +SELECT sum(l_linenumber), avg(l_linenumber) FROM lineitem WHERE l_orderkey > 20000; +DEBUG: predicate pruning for shardId 102014 +DEBUG: predicate pruning for shardId 102013 +DEBUG: predicate pruning for shardId 102012 +DEBUG: predicate pruning for shardId 102011 +DEBUG: predicate pruning for shardId 102010 +DEBUG: predicate pruning for shardId 102009 + sum | avg +-----+----- + | +(1 row) + +-- The tests below verify that we can prune shards partitioned over different +-- types of columns including varchar, array types, composite types etc. This is +-- in response to a bug we had where we were not able to resolve correct operator +-- types for some kind of column types. First we create tables partitioned on +-- these types and the logical shards and placements for them. +-- Create varchar partitioned table +CREATE TABLE varchar_partitioned_table +( + varchar_column varchar(100) +); +SELECT master_create_distributed_table('varchar_partitioned_table', 'varchar_column', 'append'); + master_create_distributed_table +--------------------------------- + +(1 row) + +-- Create logical shards and shard placements with shardid 100,101 +INSERT INTO pg_dist_shard (logicalrelid, shardid, shardstorage, shardminvalue, shardmaxvalue) + VALUES('varchar_partitioned_table'::regclass, 100, 't', 'AA1000U2AMO4ZGX', 'AZZXSP27F21T6'), + ('varchar_partitioned_table'::regclass, 101, 't', 'BA1000U2AMO4ZGX', 'BZZXSP27F21T6'); +INSERT INTO pg_dist_shard_placement (shardid, shardstate, shardlength, nodename, nodeport) + SELECT 100, 1, 1, nodename, nodeport + FROM pg_dist_shard_placement + GROUP BY nodename, nodeport + ORDER BY nodename, nodeport ASC + LIMIT 1; +INSERT INTO pg_dist_shard_placement (shardid, shardstate, shardlength, nodename, nodeport) + SELECT 101, 1, 1, nodename, nodeport + FROM pg_dist_shard_placement + GROUP BY nodename, nodeport + ORDER BY nodename, nodeport ASC + LIMIT 1; +-- Create array partitioned table +RESET client_min_messages; -- avoid debug messages about toast index creation +CREATE TABLE array_partitioned_table +( + array_column text[] +); +SELECT master_create_distributed_table('array_partitioned_table', 'array_column', 'append'); + master_create_distributed_table +--------------------------------- + +(1 row) + +SET client_min_messages TO DEBUG2; +-- Create logical shard with shardid 102, 103 +INSERT INTO pg_dist_shard (logicalrelid, shardid, shardstorage, shardminvalue, shardmaxvalue) + VALUES('array_partitioned_table'::regclass, 102, 't', '{}', '{AZZXSP27F21T6, AZZXSP27F21T6}'), + ('array_partitioned_table'::regclass, 103, 't', '{BA1000U2AMO4ZGX, BZZXSP27F21T6}', + '{CA1000U2AMO4ZGX, CZZXSP27F21T6}'); +INSERT INTO pg_dist_shard_placement (shardid, shardstate, shardlength, nodename, nodeport) + SELECT 102, 1, 1, nodename, nodeport + FROM pg_dist_shard_placement + GROUP BY nodename, nodeport + ORDER BY nodename, nodeport ASC + LIMIT 1; +INSERT INTO pg_dist_shard_placement (shardid, shardstate, shardlength, nodename, nodeport) + SELECT 103, 1, 1, nodename, nodeport + FROM pg_dist_shard_placement + GROUP BY nodename, nodeport + ORDER BY nodename, nodeport ASC + LIMIT 1; +-- Create composite type partitioned table +CREATE TYPE composite_type AS +( + text_column text, + double_column decimal, + varchar_column varchar(50) +); +RESET client_min_messages; -- avoid debug messages about toast index creation +CREATE TABLE composite_partitioned_table +( + composite_column composite_type +); +SELECT master_create_distributed_table('composite_partitioned_table', 'composite_column', 'append'); + master_create_distributed_table +--------------------------------- + +(1 row) + +SET client_min_messages TO DEBUG2; +-- Create logical shard with shardid 104, 105 +INSERT INTO pg_dist_shard (logicalrelid, shardid, shardstorage, shardminvalue, shardmaxvalue) + VALUES('composite_partitioned_table'::regclass, 104, 't', '(a,3,b)', '(b,4,c)'), + ('composite_partitioned_table'::regclass, 105, 't', '(c,5,d)', '(d,6,e)'); +INSERT INTO pg_dist_shard_placement (shardid, shardstate, shardlength, nodename, nodeport) + SELECT 104, 1, 1, nodename, nodeport + FROM pg_dist_shard_placement + GROUP BY nodename, nodeport + ORDER BY nodename, nodeport ASC + LIMIT 1; +INSERT INTO pg_dist_shard_placement (shardid, shardstate, shardlength, nodename, nodeport) + SELECT 105, 1, 1, nodename, nodeport + FROM pg_dist_shard_placement + GROUP BY nodename, nodeport + ORDER BY nodename, nodeport ASC + LIMIT 1; +-- Verify that shard pruning works. Note that these queries should all prune +-- one shard. +EXPLAIN SELECT count(*) FROM varchar_partitioned_table WHERE varchar_column = 'BA2'; +DEBUG: predicate pruning for shardId 100 + QUERY PLAN +---------------------------------------------------------------------- + explain statements for distributed queries are currently unsupported +(1 row) + +EXPLAIN SELECT count(*) FROM array_partitioned_table + WHERE array_column > '{BA1000U2AMO4ZGX, BZZXSP27F21T6}'; +DEBUG: predicate pruning for shardId 102 + QUERY PLAN +---------------------------------------------------------------------- + explain statements for distributed queries are currently unsupported +(1 row) + +EXPLAIN SELECT count(*) FROM composite_partitioned_table + WHERE composite_column < '(b,5,c)'::composite_type; +DEBUG: predicate pruning for shardId 105 + QUERY PLAN +---------------------------------------------------------------------- + explain statements for distributed queries are currently unsupported +(1 row) + +SET client_min_messages TO NOTICE; diff --git a/src/test/regress/expected/multi_prepare_plsql.out b/src/test/regress/expected/multi_prepare_plsql.out new file mode 100644 index 000000000..c2848b7cb --- /dev/null +++ b/src/test/regress/expected/multi_prepare_plsql.out @@ -0,0 +1,363 @@ +-- +-- MULTI_PREPARE_PLSQL +-- +-- Many of the queries are taken from other regression test files +-- and converted into both plain SQL and PL/pgsql functions, which +-- use prepared statements internally. +CREATE FUNCTION sql_test_no_1() RETURNS bigint AS ' + SELECT + count(*) + FROM + orders; +' LANGUAGE SQL; +CREATE FUNCTION sql_test_no_2() RETURNS bigint AS ' + SELECT + count(*) + FROM + orders, lineitem + WHERE + o_orderkey = l_orderkey; +' LANGUAGE SQL; +CREATE FUNCTION sql_test_no_3() RETURNS bigint AS ' + SELECT + count(*) + FROM + orders, customer + WHERE + o_custkey = c_custkey; +' LANGUAGE SQL; +CREATE FUNCTION sql_test_no_4() RETURNS bigint AS ' + SELECT + count(*) + FROM + orders, customer, lineitem + WHERE + o_custkey = c_custkey AND + o_orderkey = l_orderkey; +' LANGUAGE SQL; +CREATE OR REPLACE FUNCTION sql_test_no_6(integer) RETURNS bigint AS $$ + SELECT + count(*) + FROM + orders, lineitem + WHERE + o_orderkey = l_orderkey AND + l_suppkey > $1; +$$ LANGUAGE SQL RETURNS NULL ON NULL INPUT; +CREATE OR REPLACE FUNCTION plpgsql_test_1() RETURNS TABLE(count bigint) AS $$ +DECLARE +BEGIN + RETURN QUERY + SELECT + count(*) + FROM + orders; + +END; +$$ LANGUAGE plpgsql; +CREATE OR REPLACE FUNCTION plpgsql_test_2() RETURNS TABLE(count bigint) AS $$ +DECLARE +BEGIN + RETURN QUERY + SELECT + count(*) + FROM + orders, lineitem + WHERE + o_orderkey = l_orderkey; + +END; +$$ LANGUAGE plpgsql; +CREATE OR REPLACE FUNCTION plpgsql_test_3() RETURNS TABLE(count bigint) AS $$ +DECLARE +BEGIN + RETURN QUERY + SELECT + count(*) + FROM + orders, customer + WHERE + o_custkey = c_custkey; + +END; +$$ LANGUAGE plpgsql; +CREATE OR REPLACE FUNCTION plpgsql_test_4() RETURNS TABLE(count bigint) AS $$ +DECLARE +BEGIN + RETURN QUERY + SELECT + count(*) + FROM + orders, customer, lineitem + WHERE + o_custkey = c_custkey AND + o_orderkey = l_orderkey; +END; +$$ LANGUAGE plpgsql; +CREATE OR REPLACE FUNCTION plpgsql_test_5() RETURNS TABLE(count bigint) AS $$ +DECLARE +BEGIN + RETURN QUERY + SELECT + count(*) + FROM + lineitem, customer + WHERE + l_partkey = c_nationkey; +END; +$$ LANGUAGE plpgsql; +CREATE OR REPLACE FUNCTION plpgsql_test_6(int) RETURNS TABLE(count bigint) AS $$ +DECLARE +BEGIN + RETURN QUERY + SELECT + count(*) + FROM + orders, lineitem + WHERE + o_orderkey = l_orderkey AND + l_suppkey > $1; +END; +$$ LANGUAGE plpgsql; +CREATE OR REPLACE FUNCTION plpgsql_test_7(text, text) RETURNS TABLE(supp_natadsion text, cusasdt_nation text, l_yeasdar int, sasdaum double precision) AS $$ +DECLARE +BEGIN + RETURN QUERY + SELECT + supp_nation::text, + cust_nation::text, + l_year::int, + sum(volume)::double precision AS revenue + FROM + ( + SELECT + supp_nation, + cust_nation, + extract(year FROM l_shipdate) AS l_year, + l_extendedprice * (1 - l_discount) AS volume + FROM + supplier, + lineitem, + orders, + customer, + ( + SELECT + n1.n_nationkey AS supp_nation_key, + n2.n_nationkey AS cust_nation_key, + n1.n_name AS supp_nation, + n2.n_name AS cust_nation + FROM + nation n1, + nation n2 + WHERE + ( + (n1.n_name = $1 AND n2.n_name = $2) + OR (n1.n_name = $2 AND n2.n_name = $1) + ) + ) AS temp + WHERE + s_suppkey = l_suppkey + AND o_orderkey = l_orderkey + AND c_custkey = o_custkey + AND s_nationkey = supp_nation_key + AND c_nationkey = cust_nation_key + AND l_shipdate between date '1995-01-01' AND date '1996-12-31' + ) AS shipping + GROUP BY + supp_nation, + cust_nation, + l_year + ORDER BY + supp_nation, + cust_nation, + l_year; +END; +$$ LANGUAGE plpgsql; +SET citusdb.task_executor_type TO 'task-tracker'; +SET client_min_messages TO INFO; +-- now, run plain SQL functions +SELECT sql_test_no_1(); + sql_test_no_1 +--------------- + 2984 +(1 row) + +SELECT sql_test_no_2(); + sql_test_no_2 +--------------- + 11998 +(1 row) + +SELECT sql_test_no_3(); + sql_test_no_3 +--------------- + 1955 +(1 row) + +SELECT sql_test_no_4(); + sql_test_no_4 +--------------- + 7804 +(1 row) + +-- now, run PL/pgsql functions +SELECT plpgsql_test_1(); + plpgsql_test_1 +---------------- + 2984 +(1 row) + +SELECT plpgsql_test_2(); + plpgsql_test_2 +---------------- + 11998 +(1 row) + +SELECT plpgsql_test_3(); + plpgsql_test_3 +---------------- + 1955 +(1 row) + +SELECT plpgsql_test_4(); + plpgsql_test_4 +---------------- + 7804 +(1 row) + +SELECT plpgsql_test_5(); + plpgsql_test_5 +---------------- + 39 +(1 row) + +-- run PL/pgsql functions with different parameters +SELECT plpgsql_test_6(155); + plpgsql_test_6 +---------------- + 11811 +(1 row) + +SELECT plpgsql_test_6(1555); + plpgsql_test_6 +---------------- + 10183 +(1 row) + +SELECT plpgsql_test_7('UNITED KINGDOM', 'CHINA'); + plpgsql_test_7 +---------------------------------------- + ("UNITED KINGDOM",CHINA,1996,18560.22) +(1 row) + +SELECT plpgsql_test_7('FRANCE', 'GERMANY'); + plpgsql_test_7 +--------------------------------- + (GERMANY,FRANCE,1995,2399.2948) +(1 row) + +-- now, PL/pgsql functions with random order +SELECT plpgsql_test_6(155); + plpgsql_test_6 +---------------- + 11811 +(1 row) + +SELECT plpgsql_test_3(); + plpgsql_test_3 +---------------- + 1955 +(1 row) + +SELECT plpgsql_test_7('FRANCE', 'GERMANY'); + plpgsql_test_7 +--------------------------------- + (GERMANY,FRANCE,1995,2399.2948) +(1 row) + +SELECT plpgsql_test_5(); + plpgsql_test_5 +---------------- + 39 +(1 row) + +SELECT plpgsql_test_1(); + plpgsql_test_1 +---------------- + 2984 +(1 row) + +SELECT plpgsql_test_6(1555); + plpgsql_test_6 +---------------- + 10183 +(1 row) + +SELECT plpgsql_test_4(); + plpgsql_test_4 +---------------- + 7804 +(1 row) + +SELECT plpgsql_test_7('UNITED KINGDOM', 'CHINA'); + plpgsql_test_7 +---------------------------------------- + ("UNITED KINGDOM",CHINA,1996,18560.22) +(1 row) + +SELECT plpgsql_test_2(); + plpgsql_test_2 +---------------- + 11998 +(1 row) + +-- run the tests which do not require re-partition +-- with real-time executor +SET citusdb.task_executor_type TO 'real-time'; +-- now, run plain SQL functions +SELECT sql_test_no_1(); + sql_test_no_1 +--------------- + 2984 +(1 row) + +SELECT sql_test_no_2(); + sql_test_no_2 +--------------- + 11998 +(1 row) + +-- plain SQL functions with parameters cannot be executed +-- FIXME: temporarily disabled, bad error message - waiting for proper parametrized query +-- FIXME: support +-- SELECT sql_test_no_6(155); +-- now, run PL/pgsql functions +SELECT plpgsql_test_1(); + plpgsql_test_1 +---------------- + 2984 +(1 row) + +SELECT plpgsql_test_2(); + plpgsql_test_2 +---------------- + 11998 +(1 row) + +-- run PL/pgsql functions with different parameters +-- FIXME: temporarily disabled, waiting for proper parametrized query support +-- SELECT plpgsql_test_6(155); +-- SELECT plpgsql_test_6(1555); +-- clean-up functions +DROP FUNCTION sql_test_no_1(); +DROP FUNCTION sql_test_no_2(); +DROP FUNCTION sql_test_no_3(); +DROP FUNCTION sql_test_no_4(); +DROP FUNCTION sql_test_no_6(int); +DROP FUNCTION plpgsql_test_1(); +DROP FUNCTION plpgsql_test_2(); +DROP FUNCTION plpgsql_test_3(); +DROP FUNCTION plpgsql_test_4(); +DROP FUNCTION plpgsql_test_5(); +DROP FUNCTION plpgsql_test_6(int); +DROP FUNCTION plpgsql_test_7(text, text); diff --git a/src/test/regress/expected/multi_prepare_sql.out b/src/test/regress/expected/multi_prepare_sql.out new file mode 100644 index 000000000..1aff5bccf --- /dev/null +++ b/src/test/regress/expected/multi_prepare_sql.out @@ -0,0 +1,244 @@ +-- +-- MULTI_PREPARE_SQL +-- +-- Tests covering PREPARE statements. Many of the queries are +-- taken from other regression test files and converted into +-- prepared statements. +PREPARE prepared_test_1 AS +SELECT + count(*) +FROM + orders; +PREPARE prepared_test_2 AS +SELECT + count(*) +FROM + orders, lineitem +WHERE + o_orderkey = l_orderkey; +PREPARE prepared_test_3 AS +SELECT + count(*) +FROM + orders, customer +WHERE + o_custkey = c_custkey; +PREPARE prepared_test_4 AS +SELECT + count(*) +FROM + orders, customer, lineitem +WHERE + o_custkey = c_custkey AND + o_orderkey = l_orderkey; +PREPARE prepared_test_5 AS +SELECT + count(*) +FROM + lineitem, customer +WHERE + l_partkey = c_nationkey; +PREPARE prepared_test_6(int) AS +SELECT + count(*) +FROM + orders, lineitem +WHERE + o_orderkey = l_orderkey AND + l_suppkey > $1; +PREPARE prepared_test_7(text, text) AS +SELECT + supp_nation, + cust_nation, + l_year, + sum(volume) AS revenue +FROM + ( + SELECT + supp_nation, + cust_nation, + extract(year FROM l_shipdate) AS l_year, + l_extendedprice * (1 - l_discount) AS volume + FROM + supplier, + lineitem, + orders, + customer, + ( + SELECT + n1.n_nationkey AS supp_nation_key, + n2.n_nationkey AS cust_nation_key, + n1.n_name AS supp_nation, + n2.n_name AS cust_nation + FROM + nation n1, + nation n2 + WHERE + ( + (n1.n_name = $1 AND n2.n_name = $2) + OR (n1.n_name = $2 AND n2.n_name = $1) + ) + ) AS temp + WHERE + s_suppkey = l_suppkey + AND o_orderkey = l_orderkey + AND c_custkey = o_custkey + AND s_nationkey = supp_nation_key + AND c_nationkey = cust_nation_key + AND l_shipdate between date '1995-01-01' AND date '1996-12-31' + ) AS shipping +GROUP BY + supp_nation, + cust_nation, + l_year +ORDER BY + supp_nation, + cust_nation, + l_year; +SET citusdb.task_executor_type TO 'task-tracker'; +SET client_min_messages TO INFO; +-- execute prepared statements +EXECUTE prepared_test_1; + count +------- + 2984 +(1 row) + +EXECUTE prepared_test_2; + count +------- + 11998 +(1 row) + +EXECUTE prepared_test_3; + count +------- + 1955 +(1 row) + +EXECUTE prepared_test_4; + count +------- + 7804 +(1 row) + +EXECUTE prepared_test_5; + count +------- + 39 +(1 row) + +-- execute prepared statements with different parameters +EXECUTE prepared_test_6(155); + count +------- + 11811 +(1 row) + +EXECUTE prepared_test_6(1555); + count +------- + 10183 +(1 row) + +EXECUTE prepared_test_7('UNITED KINGDOM', 'CHINA'); + supp_nation | cust_nation | l_year | revenue +---------------------------+---------------------------+--------+------------ + UNITED KINGDOM | CHINA | 1996 | 18560.2200 +(1 row) + +EXECUTE prepared_test_7('FRANCE', 'GERMANY'); + supp_nation | cust_nation | l_year | revenue +---------------------------+---------------------------+--------+----------- + GERMANY | FRANCE | 1995 | 2399.2948 +(1 row) + +-- now, execute prepared statements with random order +EXECUTE prepared_test_6(155); + count +------- + 11811 +(1 row) + +EXECUTE prepared_test_3; + count +------- + 1955 +(1 row) + +EXECUTE prepared_test_7('FRANCE', 'GERMANY'); + supp_nation | cust_nation | l_year | revenue +---------------------------+---------------------------+--------+----------- + GERMANY | FRANCE | 1995 | 2399.2948 +(1 row) + +EXECUTE prepared_test_5; + count +------- + 39 +(1 row) + +EXECUTE prepared_test_1; + count +------- + 2984 +(1 row) + +EXECUTE prepared_test_6(1555); + count +------- + 10183 +(1 row) + +EXECUTE prepared_test_4; + count +------- + 7804 +(1 row) + +EXECUTE prepared_test_7('UNITED KINGDOM', 'CHINA'); + supp_nation | cust_nation | l_year | revenue +---------------------------+---------------------------+--------+------------ + UNITED KINGDOM | CHINA | 1996 | 18560.2200 +(1 row) + +EXECUTE prepared_test_2; + count +------- + 11998 +(1 row) + +-- CREATE TABLE ... AS EXECUTE prepared_statement tests +CREATE TEMP TABLE prepared_sql_test_7 AS EXECUTE prepared_test_7('UNITED KINGDOM', 'CHINA'); +SELECT * from prepared_sql_test_7; + supp_nation | cust_nation | l_year | revenue +---------------------------+---------------------------+--------+------------ + UNITED KINGDOM | CHINA | 1996 | 18560.2200 +(1 row) + +-- now, run some of the tests with real-time executor +SET citusdb.task_executor_type TO 'real-time'; +-- execute prepared statements +EXECUTE prepared_test_1; + count +------- + 2984 +(1 row) + +EXECUTE prepared_test_2; + count +------- + 11998 +(1 row) + +-- execute prepared statements with different parameters +EXECUTE prepared_test_6(155); + count +------- + 11811 +(1 row) + +-- FIXME: temporarily disabled +-- EXECUTE prepared_test_6(1555); +-- clean-up prepared statements +DEALLOCATE ALL; diff --git a/src/test/regress/expected/multi_prune_shard_list.out b/src/test/regress/expected/multi_prune_shard_list.out new file mode 100644 index 000000000..029228841 --- /dev/null +++ b/src/test/regress/expected/multi_prune_shard_list.out @@ -0,0 +1,87 @@ +-- =================================================================== +-- create test functions +-- =================================================================== +CREATE FUNCTION prune_using_no_values(regclass) + RETURNS text[] + AS 'citusdb' + LANGUAGE C STRICT; +CREATE FUNCTION prune_using_single_value(regclass, text) + RETURNS text[] + AS 'citusdb' + LANGUAGE C; +CREATE FUNCTION prune_using_either_value(regclass, text, text) + RETURNS text[] + AS 'citusdb' + LANGUAGE C STRICT; +CREATE FUNCTION prune_using_both_values(regclass, text, text) + RETURNS text[] + AS 'citusdb' + LANGUAGE C STRICT; +CREATE FUNCTION debug_equality_expression(regclass) + RETURNS cstring + AS 'citusdb' + LANGUAGE C STRICT; +-- =================================================================== +-- test shard pruning functionality +-- =================================================================== +-- create distributed table metadata to observe shard pruning +CREATE TABLE pruning ( species text, last_pruned date, plant_id integer ); +INSERT INTO pg_dist_partition (logicalrelid, partmethod, partkey) +VALUES + ('pruning'::regclass, 'h', column_name_to_column('pruning'::regclass, 'species')); +INSERT INTO pg_dist_shard + (shardid, logicalrelid, shardstorage, shardminvalue, shardmaxvalue) +VALUES + (10, 'pruning'::regclass, 't', '-2147483648', '-1073741826'), + (11, 'pruning'::regclass, 't', '-1073741825', '-3'), + (12, 'pruning'::regclass, 't', '-2', '1073741820'), + (13, 'pruning'::regclass, 't', '1073741821', '2147483647'); +-- with no values, expect all shards +SELECT prune_using_no_values('pruning'); + prune_using_no_values +----------------------- + {13,12,11,10} +(1 row) + +-- with a single value, expect a single shard +SELECT prune_using_single_value('pruning', 'tomato'); + prune_using_single_value +-------------------------- + {12} +(1 row) + +-- the above is true even if that value is null +SELECT prune_using_single_value('pruning', NULL); + prune_using_single_value +-------------------------- + {12} +(1 row) + +-- build an OR clause and expect more than one sahrd +SELECT prune_using_either_value('pruning', 'tomato', 'petunia'); + prune_using_either_value +-------------------------- + {12,11} +(1 row) + +-- an AND clause with incompatible values returns no shards +SELECT prune_using_both_values('pruning', 'tomato', 'petunia'); + prune_using_both_values +------------------------- + {} +(1 row) + +-- but if both values are on the same shard, should get back that shard +SELECT prune_using_both_values('pruning', 'tomato', 'rose'); + prune_using_both_values +------------------------- + {12} +(1 row) + +-- unit test of the equality expression generation code +SELECT debug_equality_expression('pruning'); + debug_equality_expression +-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + {OPEXPR :opno 98 :opfuncid 67 :opresulttype 16 :opretset false :opcollid 0 :inputcollid 100 :args ({VAR :varno 1 :varattno 1 :vartype 25 :vartypmod -1 :varcollid 100 :varlevelsup 0 :varnoold 1 :varoattno 1 :location -1} {CONST :consttype 25 :consttypmod -1 :constcollid 100 :constlen -1 :constbyval false :constisnull true :location -1 :constvalue <>}) :location -1} +(1 row) + diff --git a/src/test/regress/expected/multi_query_directory_cleanup.out b/src/test/regress/expected/multi_query_directory_cleanup.out new file mode 100644 index 000000000..a72a3a06d --- /dev/null +++ b/src/test/regress/expected/multi_query_directory_cleanup.out @@ -0,0 +1,152 @@ +-- +-- MULTI_QUERY_DIRECTORY_CLEANUP +-- +-- We execute sub-queries on worker nodes, and copy query results to a directory +-- on the master node for final processing. When the query completes or fails, +-- the resource owner should automatically clean up these intermediate query +-- result files. +BEGIN; +-- pg_ls_dir() displays jobids. We explicitly set the jobId sequence +-- here so that the regression output becomes independent of the +-- number of jobs executed prior to running this test. +ALTER SEQUENCE pg_catalog.pg_dist_jobid_seq RESTART 1250; +SELECT sum(l_extendedprice * l_discount) as revenue FROM lineitem; + revenue +--------------- + 22770844.7654 +(1 row) + +SELECT sum(l_extendedprice * l_discount) as revenue FROM lineitem; + revenue +--------------- + 22770844.7654 +(1 row) + +SELECT sum(l_extendedprice * l_discount) as revenue FROM lineitem; + revenue +--------------- + 22770844.7654 +(1 row) + +SELECT pg_ls_dir('base/pgsql_job_cache'); + pg_ls_dir +----------- +(0 rows) + +COMMIT; +SELECT pg_ls_dir('base/pgsql_job_cache'); + pg_ls_dir +----------- +(0 rows) + +BEGIN; +SELECT sum(l_extendedprice * l_discount) as revenue FROM lineitem; + revenue +--------------- + 22770844.7654 +(1 row) + +SELECT sum(l_extendedprice * l_discount) as revenue FROM lineitem; + revenue +--------------- + 22770844.7654 +(1 row) + +SELECT sum(l_extendedprice * l_discount) as revenue FROM lineitem; + revenue +--------------- + 22770844.7654 +(1 row) + +SELECT pg_ls_dir('base/pgsql_job_cache'); + pg_ls_dir +----------- +(0 rows) + +ROLLBACK; +SELECT pg_ls_dir('base/pgsql_job_cache'); + pg_ls_dir +----------- +(0 rows) + +-- Test that multiple job directories are all cleaned up correctly, +-- both individually (by closing a cursor) and in bulk when ending a +-- transaction. +BEGIN; +DECLARE c_00 CURSOR FOR SELECT sum(l_extendedprice * l_discount) as revenue FROM lineitem; +DECLARE c_01 CURSOR FOR SELECT sum(l_extendedprice * l_discount) as revenue FROM lineitem; +DECLARE c_02 CURSOR FOR SELECT sum(l_extendedprice * l_discount) as revenue FROM lineitem; +DECLARE c_03 CURSOR FOR SELECT sum(l_extendedprice * l_discount) as revenue FROM lineitem; +DECLARE c_04 CURSOR FOR SELECT sum(l_extendedprice * l_discount) as revenue FROM lineitem; +DECLARE c_05 CURSOR FOR SELECT sum(l_extendedprice * l_discount) as revenue FROM lineitem; +DECLARE c_06 CURSOR FOR SELECT sum(l_extendedprice * l_discount) as revenue FROM lineitem; +DECLARE c_07 CURSOR FOR SELECT sum(l_extendedprice * l_discount) as revenue FROM lineitem; +DECLARE c_08 CURSOR FOR SELECT sum(l_extendedprice * l_discount) as revenue FROM lineitem; +DECLARE c_09 CURSOR FOR SELECT sum(l_extendedprice * l_discount) as revenue FROM lineitem; +DECLARE c_10 CURSOR FOR SELECT sum(l_extendedprice * l_discount) as revenue FROM lineitem; +DECLARE c_11 CURSOR FOR SELECT sum(l_extendedprice * l_discount) as revenue FROM lineitem; +DECLARE c_12 CURSOR FOR SELECT sum(l_extendedprice * l_discount) as revenue FROM lineitem; +DECLARE c_13 CURSOR FOR SELECT sum(l_extendedprice * l_discount) as revenue FROM lineitem; +DECLARE c_14 CURSOR FOR SELECT sum(l_extendedprice * l_discount) as revenue FROM lineitem; +DECLARE c_15 CURSOR FOR SELECT sum(l_extendedprice * l_discount) as revenue FROM lineitem; +DECLARE c_16 CURSOR FOR SELECT sum(l_extendedprice * l_discount) as revenue FROM lineitem; +DECLARE c_17 CURSOR FOR SELECT sum(l_extendedprice * l_discount) as revenue FROM lineitem; +DECLARE c_18 CURSOR FOR SELECT sum(l_extendedprice * l_discount) as revenue FROM lineitem; +DECLARE c_19 CURSOR FOR SELECT sum(l_extendedprice * l_discount) as revenue FROM lineitem; +SELECT * FROM pg_ls_dir('base/pgsql_job_cache') f ORDER BY f; + f +---------- + job_1256 + job_1257 + job_1258 + job_1259 + job_1260 + job_1261 + job_1262 + job_1263 + job_1264 + job_1265 + job_1266 + job_1267 + job_1268 + job_1269 + job_1270 + job_1271 + job_1272 + job_1273 + job_1274 + job_1275 +(20 rows) + +-- close first, 17th (first after re-alloc) and last cursor. +CLOSE c_00; +CLOSE c_16; +CLOSE c_19; +SELECT * FROM pg_ls_dir('base/pgsql_job_cache') f ORDER BY f; + f +---------- + job_1257 + job_1258 + job_1259 + job_1260 + job_1261 + job_1262 + job_1263 + job_1264 + job_1265 + job_1266 + job_1267 + job_1268 + job_1269 + job_1270 + job_1271 + job_1273 + job_1274 +(17 rows) + +ROLLBACK; +SELECT pg_ls_dir('base/pgsql_job_cache'); + pg_ls_dir +----------- +(0 rows) + diff --git a/src/test/regress/expected/multi_repair_shards.out b/src/test/regress/expected/multi_repair_shards.out new file mode 100644 index 000000000..8cdc949aa --- /dev/null +++ b/src/test/regress/expected/multi_repair_shards.out @@ -0,0 +1,96 @@ +-- =================================================================== +-- test shard repair functionality +-- =================================================================== +-- create a table and create its distribution metadata +CREATE TABLE customer_engagements ( id integer, created_at date, event_data text ); +-- add some indexes +CREATE INDEX ON customer_engagements (id); +CREATE INDEX ON customer_engagements (created_at); +CREATE INDEX ON customer_engagements (event_data); +\set first_worker_port 57637 +\set second_worker_port 57638 +-- distribute the table +SELECT master_create_distributed_table('customer_engagements', 'id', 'hash'); + master_create_distributed_table +--------------------------------- + +(1 row) + +-- create a single shard on the first worker +SELECT master_create_worker_shards('customer_engagements', 1, 2); + master_create_worker_shards +----------------------------- + +(1 row) + +-- ingest some data for the tests +INSERT INTO customer_engagements VALUES (1, '01-01-2015', 'first event'); +INSERT INTO customer_engagements VALUES (2, '02-01-2015', 'second event'); +INSERT INTO customer_engagements VALUES (1, '03-01-2015', 'third event'); +-- the following queries does the following: +-- (i) create a new shard +-- (ii) mark the second shard placements as unhealthy +-- (iii) do basic checks i.e., only allow copy from healthy placement to unhealthy ones +-- (iv) do a successful master_copy_shard_placement from the first placement to the second +-- (v) mark the first placement as unhealthy and execute a query that is routed to the second placement +-- get the newshardid +SELECT shardid as newshardid FROM pg_dist_shard WHERE logicalrelid = 'customer_engagements'::regclass +\gset +-- now, update the second placement as unhealthy +UPDATE pg_dist_shard_placement SET shardstate = 3 WHERE shardid = :newshardid AND nodeport = :second_worker_port; +-- add a fake healthy placement for the tests +INSERT INTO pg_dist_shard_placement (nodename, nodeport, shardid, shardstate, shardlength) + VALUES ('dummyhost', :second_worker_port, :newshardid, 1, 0); +SELECT master_copy_shard_placement(:newshardid, 'localhost', :first_worker_port, 'dummyhost', :second_worker_port); +ERROR: target placement must be in inactive state +-- also try to copy from an inactive placement +SELECT master_copy_shard_placement(:newshardid, 'localhost', :second_worker_port, 'localhost', :first_worker_port); +ERROR: source placement must be in finalized state +-- "copy" this shard from the first placement to the second one +SELECT master_copy_shard_placement(:newshardid, 'localhost', :first_worker_port, 'localhost', :second_worker_port); + master_copy_shard_placement +----------------------------- + +(1 row) + +-- now, update first placement as unhealthy (and raise a notice) so that queries are not routed to there +UPDATE pg_dist_shard_placement SET shardstate = 3 WHERE shardid = :newshardid AND nodeport = :first_worker_port; +-- get the data from the second placement +SELECT * FROM customer_engagements; + id | created_at | event_data +----+------------+-------------- + 1 | 01-01-2015 | first event + 2 | 02-01-2015 | second event + 1 | 03-01-2015 | third event +(3 rows) + +-- now do the same test over again with a foreign table +CREATE FOREIGN TABLE remote_engagements ( + id integer, + created_at date, + event_data text +) SERVER fake_fdw_server; +-- distribute the table +SELECT master_create_distributed_table('remote_engagements', 'id', 'hash'); + master_create_distributed_table +--------------------------------- + +(1 row) + +-- create a single shard on the first worker +SELECT master_create_worker_shards('remote_engagements', 1, 2); +NOTICE: foreign-data wrapper "fake_fdw" does not have an extension defined + master_create_worker_shards +----------------------------- + +(1 row) + +-- get the newshardid +SELECT shardid as remotenewshardid FROM pg_dist_shard WHERE logicalrelid = 'remote_engagements'::regclass +\gset +-- now, update the second placement as unhealthy +UPDATE pg_dist_shard_placement SET shardstate = 3 WHERE shardid = :remotenewshardid AND nodeport = :second_worker_port; +-- oops! we don't support repairing shards backed by foreign tables +SELECT master_copy_shard_placement(:remotenewshardid, 'localhost', :first_worker_port, 'localhost', :second_worker_port); +ERROR: cannot repair shard +DETAIL: Repairing shards backed by foreign tables is not supported. diff --git a/src/test/regress/expected/multi_simple_queries.out b/src/test/regress/expected/multi_simple_queries.out new file mode 100644 index 000000000..4407ec697 --- /dev/null +++ b/src/test/regress/expected/multi_simple_queries.out @@ -0,0 +1,498 @@ +-- =================================================================== +-- test end-to-end query functionality +-- =================================================================== +CREATE TABLE articles ( + id bigint NOT NULL, + author_id bigint NOT NULL, + title text NOT NULL, + word_count integer NOT NULL CHECK (word_count > 0) +); +-- this table is used in a CTE test +CREATE TABLE authors ( name text, id bigint ); +-- this table is used in router executor tests +CREATE TABLE articles_single_shard (LIKE articles); +SELECT master_create_distributed_table('articles', 'author_id', 'hash'); + master_create_distributed_table +--------------------------------- + +(1 row) + +SELECT master_create_distributed_table('articles_single_shard', 'author_id', 'hash'); + master_create_distributed_table +--------------------------------- + +(1 row) + +-- test when a table is distributed but no shards created yet +SELECT count(*) from articles; + count +------- + +(1 row) + +SELECT master_create_worker_shards('articles', 2, 1); + master_create_worker_shards +----------------------------- + +(1 row) + +SELECT master_create_worker_shards('articles_single_shard', 1, 1); + master_create_worker_shards +----------------------------- + +(1 row) + +-- create a bunch of test data +INSERT INTO articles VALUES ( 1, 1, 'arsenous', 9572); +INSERT INTO articles VALUES ( 2, 2, 'abducing', 13642); +INSERT INTO articles VALUES ( 3, 3, 'asternal', 10480); +INSERT INTO articles VALUES ( 4, 4, 'altdorfer', 14551); +INSERT INTO articles VALUES ( 5, 5, 'aruru', 11389); +INSERT INTO articles VALUES ( 6, 6, 'atlases', 15459); +INSERT INTO articles VALUES ( 7, 7, 'aseptic', 12298); +INSERT INTO articles VALUES ( 8, 8, 'agatized', 16368); +INSERT INTO articles VALUES ( 9, 9, 'alligate', 438); +INSERT INTO articles VALUES (10, 10, 'aggrandize', 17277); +INSERT INTO articles VALUES (11, 1, 'alamo', 1347); +INSERT INTO articles VALUES (12, 2, 'archiblast', 18185); +INSERT INTO articles VALUES (13, 3, 'aseyev', 2255); +INSERT INTO articles VALUES (14, 4, 'andesite', 19094); +INSERT INTO articles VALUES (15, 5, 'adversa', 3164); +INSERT INTO articles VALUES (16, 6, 'allonym', 2); +INSERT INTO articles VALUES (17, 7, 'auriga', 4073); +INSERT INTO articles VALUES (18, 8, 'assembly', 911); +INSERT INTO articles VALUES (19, 9, 'aubergiste', 4981); +INSERT INTO articles VALUES (20, 10, 'absentness', 1820); +INSERT INTO articles VALUES (21, 1, 'arcading', 5890); +INSERT INTO articles VALUES (22, 2, 'antipope', 2728); +INSERT INTO articles VALUES (23, 3, 'abhorring', 6799); +INSERT INTO articles VALUES (24, 4, 'audacious', 3637); +INSERT INTO articles VALUES (25, 5, 'antehall', 7707); +INSERT INTO articles VALUES (26, 6, 'abington', 4545); +INSERT INTO articles VALUES (27, 7, 'arsenous', 8616); +INSERT INTO articles VALUES (28, 8, 'aerophyte', 5454); +INSERT INTO articles VALUES (29, 9, 'amateur', 9524); +INSERT INTO articles VALUES (30, 10, 'andelee', 6363); +INSERT INTO articles VALUES (31, 1, 'athwartships', 7271); +INSERT INTO articles VALUES (32, 2, 'amazon', 11342); +INSERT INTO articles VALUES (33, 3, 'autochrome', 8180); +INSERT INTO articles VALUES (34, 4, 'amnestied', 12250); +INSERT INTO articles VALUES (35, 5, 'aminate', 9089); +INSERT INTO articles VALUES (36, 6, 'ablation', 13159); +INSERT INTO articles VALUES (37, 7, 'archduchies', 9997); +INSERT INTO articles VALUES (38, 8, 'anatine', 14067); +INSERT INTO articles VALUES (39, 9, 'anchises', 10906); +INSERT INTO articles VALUES (40, 10, 'attemper', 14976); +INSERT INTO articles VALUES (41, 1, 'aznavour', 11814); +INSERT INTO articles VALUES (42, 2, 'ausable', 15885); +INSERT INTO articles VALUES (43, 3, 'affixal', 12723); +INSERT INTO articles VALUES (44, 4, 'anteport', 16793); +INSERT INTO articles VALUES (45, 5, 'afrasia', 864); +INSERT INTO articles VALUES (46, 6, 'atlanta', 17702); +INSERT INTO articles VALUES (47, 7, 'abeyance', 1772); +INSERT INTO articles VALUES (48, 8, 'alkylic', 18610); +INSERT INTO articles VALUES (49, 9, 'anyone', 2681); +INSERT INTO articles VALUES (50, 10, 'anjanette', 19519); +-- insert a single row for the test +INSERT INTO articles_single_shard VALUES (50, 10, 'anjanette', 19519); +-- first, test zero-shard SELECT, which should return an empty row +SELECT COUNT(*) FROM articles WHERE author_id = 1 AND author_id = 2; + count +------- + +(1 row) + +-- zero-shard modifications should fail +UPDATE articles SET title = '' WHERE author_id = 1 AND author_id = 2; +ERROR: distributed modifications must target exactly one shard +DELETE FROM articles WHERE author_id = 1 AND author_id = 2; +ERROR: distributed modifications must target exactly one shard +-- single-shard tests +-- test simple select for a single row +SELECT * FROM articles WHERE author_id = 10 AND id = 50; + id | author_id | title | word_count +----+-----------+-----------+------------ + 50 | 10 | anjanette | 19519 +(1 row) + +-- get all titles by a single author +SELECT title FROM articles WHERE author_id = 10; + title +------------ + aggrandize + absentness + andelee + attemper + anjanette +(5 rows) + +-- try ordering them by word count +SELECT title, word_count FROM articles + WHERE author_id = 10 + ORDER BY word_count DESC NULLS LAST; + title | word_count +------------+------------ + anjanette | 19519 + aggrandize | 17277 + attemper | 14976 + andelee | 6363 + absentness | 1820 +(5 rows) + +-- look at last two articles by an author +SELECT title, id FROM articles + WHERE author_id = 5 + ORDER BY id + LIMIT 2; + title | id +---------+---- + aruru | 5 + adversa | 15 +(2 rows) + +-- find all articles by two authors in same shard +SELECT title, author_id FROM articles + WHERE author_id = 7 OR author_id = 8 + ORDER BY author_id ASC, id; + title | author_id +-------------+----------- + aseptic | 7 + auriga | 7 + arsenous | 7 + archduchies | 7 + abeyance | 7 + agatized | 8 + assembly | 8 + aerophyte | 8 + anatine | 8 + alkylic | 8 +(10 rows) + +-- add in some grouping expressions, still on same shard +-- having queries unsupported in CitusDB +SELECT author_id, sum(word_count) AS corpus_size FROM articles + WHERE author_id = 1 OR author_id = 7 OR author_id = 8 OR author_id = 10 + GROUP BY author_id + HAVING sum(word_count) > 40000 + ORDER BY sum(word_count) DESC; +ERROR: cannot perform distributed planning on this query +DETAIL: Having qual is currently unsupported +-- UNION/INTERSECT queries are unsupported +SELECT * FROM articles WHERE author_id = 10 UNION +SELECT * FROM articles WHERE author_id = 1; +ERROR: cannot perform distributed planning on this query +DETAIL: Union, Intersect, or Except are currently unsupported +-- queries using CTEs are unsupported +WITH long_names AS ( SELECT id FROM authors WHERE char_length(name) > 15 ) +SELECT title FROM articles; +ERROR: cannot plan queries that include both regular and partitioned relations +-- queries which involve functions in FROM clause are unsupported. +SELECT * FROM articles, position('om' in 'Thomas'); +ERROR: cannot perform distributed planning on this query +DETAIL: Complex table expressions are currently unsupported +-- subqueries are not supported in WHERE clause in CitusDB +SELECT * FROM articles WHERE author_id IN (SELECT id FROM authors WHERE name LIKE '%a'); +ERROR: cannot plan queries that include both regular and partitioned relations +-- subqueries are supported in FROM clause +SELECT articles.id,test.word_count +FROM articles, (SELECT id, word_count FROM articles) AS test WHERE test.id = articles.id +ORDER BY articles.id; + id | word_count +----+------------ + 1 | 9572 + 2 | 13642 + 3 | 10480 + 4 | 14551 + 5 | 11389 + 6 | 15459 + 7 | 12298 + 8 | 16368 + 9 | 438 + 10 | 17277 + 11 | 1347 + 12 | 18185 + 13 | 2255 + 14 | 19094 + 15 | 3164 + 16 | 2 + 17 | 4073 + 18 | 911 + 19 | 4981 + 20 | 1820 + 21 | 5890 + 22 | 2728 + 23 | 6799 + 24 | 3637 + 25 | 7707 + 26 | 4545 + 27 | 8616 + 28 | 5454 + 29 | 9524 + 30 | 6363 + 31 | 7271 + 32 | 11342 + 33 | 8180 + 34 | 12250 + 35 | 9089 + 36 | 13159 + 37 | 9997 + 38 | 14067 + 39 | 10906 + 40 | 14976 + 41 | 11814 + 42 | 15885 + 43 | 12723 + 44 | 16793 + 45 | 864 + 46 | 17702 + 47 | 1772 + 48 | 18610 + 49 | 2681 + 50 | 19519 +(50 rows) + +-- subqueries are not supported in SELECT clause +SELECT a.title AS name, (SELECT a2.id FROM authors a2 WHERE a.id = a2.id LIMIT 1) + AS special_price FROM articles a; +ERROR: cannot perform distributed planning on this query +DETAIL: Subqueries other than in from-clause are currently unsupported +-- joins are not supported between local and distributed tables +SELECT title, authors.name FROM authors, articles WHERE authors.id = articles.author_id; +ERROR: cannot plan queries that include both regular and partitioned relations +-- inner joins are not supported (I think) +SELECT * FROM (articles INNER JOIN authors ON articles.id = authors.id); +ERROR: cannot plan queries that include both regular and partitioned relations +-- test use of EXECUTE statements within plpgsql +DO $sharded_execute$ + BEGIN + EXECUTE 'SELECT COUNT(*) FROM articles ' || + 'WHERE author_id = $1 AND author_id = $2' USING 1, 2; + END +$sharded_execute$; +-- test use of bare SQL within plpgsql +DO $sharded_sql$ + BEGIN + SELECT COUNT(*) FROM articles WHERE author_id = 1 AND author_id = 2; + END +$sharded_sql$; +ERROR: query has no destination for result data +HINT: If you want to discard the results of a SELECT, use PERFORM instead. +CONTEXT: PL/pgSQL function inline_code_block line 3 at SQL statement +-- test cross-shard queries +SELECT COUNT(*) FROM articles; + count +------- + 50 +(1 row) + +-- having queries unsupported in CitusDB +SELECT author_id, sum(word_count) AS corpus_size FROM articles + GROUP BY author_id + HAVING sum(word_count) > 25000 + ORDER BY sum(word_count) DESC + LIMIT 5; +ERROR: cannot perform distributed planning on this query +DETAIL: Having qual is currently unsupported +-- more proof CitusDB doesn't support having clauses +SELECT author_id FROM articles + GROUP BY author_id + HAVING sum(word_count) > 50000 + ORDER BY author_id; +ERROR: cannot perform distributed planning on this query +DETAIL: Having qual is currently unsupported +-- now, test the cases where CitusDB do or do not need to create +-- the master queries +SET citusdb.task_executor_type TO 'router'; +SET citusdb.large_table_shard_count TO 2; +SET client_min_messages TO 'DEBUG2'; +-- start with the simple lookup query +SELECT * + FROM articles + WHERE author_id = 1; +DEBUG: predicate pruning for shardId 103093 + id | author_id | title | word_count +----+-----------+--------------+------------ + 1 | 1 | arsenous | 9572 + 11 | 1 | alamo | 1347 + 21 | 1 | arcading | 5890 + 31 | 1 | athwartships | 7271 + 41 | 1 | aznavour | 11814 +(5 rows) + +-- below query hits a single shard, so no need to create the master query +SELECT * + FROM articles + WHERE author_id = 1 OR author_id = 17; +DEBUG: predicate pruning for shardId 103093 + id | author_id | title | word_count +----+-----------+--------------+------------ + 1 | 1 | arsenous | 9572 + 11 | 1 | alamo | 1347 + 21 | 1 | arcading | 5890 + 31 | 1 | athwartships | 7271 + 41 | 1 | aznavour | 11814 +(5 rows) + +-- below query hits two shards, so needs to create the master query +SELECT * + FROM articles + WHERE author_id = 1 OR author_id = 18; +ERROR: cannot use router executor with queries that hit multiple shards +HINT: Set citusdb.task_executor_type to "real-time" or "task-tracker". +-- rename the output columns on a no master query case +SELECT id as article_id, word_count * id as random_value + FROM articles + WHERE author_id = 1; +DEBUG: predicate pruning for shardId 103093 + article_id | random_value +------------+-------------- + 1 | 9572 + 11 | 14817 + 21 | 123690 + 31 | 225401 + 41 | 484374 +(5 rows) + +-- we can push down co-located joins to a single worker without the +-- master query being required for only the same tables +SELECT a.author_id as first_author, b.word_count as second_word_count + FROM articles a, articles b + WHERE a.author_id = 10 and a.author_id = b.author_id + LIMIT 3; +DEBUG: push down of limit count: 3 +DEBUG: predicate pruning for shardId 103093 +DEBUG: join prunable for intervals [-2147483648,-1] and [0,2147483647] + first_author | second_word_count +--------------+------------------- + 10 | 17277 + 10 | 1820 + 10 | 6363 +(3 rows) + +-- now show that JOINs don't work with multiple tables +SELECT a.author_id as first_author, b.word_count as second_word_count + FROM articles a, articles_single_shard b + WHERE a.author_id = 10 and a.author_id = b.author_id + LIMIT 3; +DEBUG: push down of limit count: 3 +DEBUG: predicate pruning for shardId 103093 +ERROR: cannot use router executor with JOINs +HINT: Set citusdb.task_executor_type to "real-time" or "task-tracker". +-- do not create the master query for LIMIT on a single shard SELECT +SELECT * + FROM articles + WHERE author_id = 1 + LIMIT 2; +DEBUG: push down of limit count: 2 +DEBUG: predicate pruning for shardId 103093 + id | author_id | title | word_count +----+-----------+----------+------------ + 1 | 1 | arsenous | 9572 + 11 | 1 | alamo | 1347 +(2 rows) + +-- This query hits a single shard. So GROUP BY can be +-- pushed down to the workers directly. This query is +-- equivalent to SELECT DISTINCT on a single shard. +SELECT id + FROM articles + WHERE author_id = 1 + GROUP BY id; +DEBUG: predicate pruning for shardId 103093 + id +---- + 41 + 11 + 31 + 1 + 21 +(5 rows) + +-- copying from a single shard table does not require the master query +COPY articles_single_shard TO stdout; +50 10 anjanette 19519 +-- error out for queries with aggregates +SELECT avg(word_count) + FROM articles + WHERE author_id = 2; +DEBUG: predicate pruning for shardId 103092 +ERROR: cannot use router executor with aggregates +HINT: Set citusdb.task_executor_type to "real-time" or "task-tracker". +-- max, min, sum, count is somehow implemented +-- differently in distributed planning but, still error out +SELECT max(word_count) as max, min(word_count) as min, + sum(word_count) as sum, count(word_count) as cnt + FROM articles + WHERE author_id = 2; +DEBUG: predicate pruning for shardId 103092 +ERROR: cannot use router executor with aggregates +HINT: Set citusdb.task_executor_type to "real-time" or "task-tracker". +-- error out for queries with ORDER BY +SELECT * + FROM articles + WHERE author_id = 1 + ORDER BY word_count; +DEBUG: predicate pruning for shardId 103093 +ERROR: cannot use router executor with ORDER BY clauses +HINT: Set citusdb.task_executor_type to "real-time" or "task-tracker". +-- error out for queries with ORDER BY and LIMIT +SELECT * + FROM articles + WHERE author_id = 1 + ORDER BY word_count + LIMIT 2; +DEBUG: push down of limit count: 2 +DEBUG: predicate pruning for shardId 103093 +ERROR: cannot use router executor with ORDER BY clauses +HINT: Set citusdb.task_executor_type to "real-time" or "task-tracker". +-- error out for queries with aggregates and GROUP BY +SELECT max(word_count) + FROM articles + WHERE author_id = 1 + GROUP BY author_id; +DEBUG: predicate pruning for shardId 103093 +ERROR: cannot use router executor with aggregates +HINT: Set citusdb.task_executor_type to "real-time" or "task-tracker". +-- error out for queries with repartition jobs +SELECT * + FROM articles a, articles b + WHERE a.id = b.id AND a.author_id = 1; +DEBUG: predicate pruning for shardId 103093 +DEBUG: join prunable for task partitionId 0 and 1 +DEBUG: join prunable for task partitionId 0 and 2 +DEBUG: join prunable for task partitionId 0 and 3 +DEBUG: join prunable for task partitionId 1 and 0 +DEBUG: join prunable for task partitionId 1 and 2 +DEBUG: join prunable for task partitionId 1 and 3 +DEBUG: join prunable for task partitionId 2 and 0 +DEBUG: join prunable for task partitionId 2 and 1 +DEBUG: join prunable for task partitionId 2 and 3 +DEBUG: join prunable for task partitionId 3 and 0 +DEBUG: join prunable for task partitionId 3 and 1 +DEBUG: join prunable for task partitionId 3 and 2 +DEBUG: pruning merge fetch taskId 1 +DETAIL: Creating dependency on merge taskId 3 +DEBUG: pruning merge fetch taskId 2 +DETAIL: Creating dependency on merge taskId 5 +DEBUG: pruning merge fetch taskId 4 +DETAIL: Creating dependency on merge taskId 5 +DEBUG: pruning merge fetch taskId 5 +DETAIL: Creating dependency on merge taskId 8 +DEBUG: pruning merge fetch taskId 7 +DETAIL: Creating dependency on merge taskId 7 +DEBUG: pruning merge fetch taskId 8 +DETAIL: Creating dependency on merge taskId 11 +DEBUG: pruning merge fetch taskId 10 +DETAIL: Creating dependency on merge taskId 9 +DEBUG: pruning merge fetch taskId 11 +DETAIL: Creating dependency on merge taskId 14 +ERROR: cannot use router executor with repartition jobs +HINT: Set citusdb.task_executor_type to "task-tracker". +-- error out for queries which hit more than 1 shards +SELECT * + FROM articles + WHERE author_id >= 1 AND author_id <= 3; +ERROR: cannot use router executor with queries that hit multiple shards +HINT: Set citusdb.task_executor_type to "real-time" or "task-tracker". +SET client_min_messages to 'NOTICE'; +SET citusdb.task_executor_type TO 'real-time'; diff --git a/src/test/regress/expected/multi_single_relation_subquery.out b/src/test/regress/expected/multi_single_relation_subquery.out new file mode 100644 index 000000000..1573e3a0a --- /dev/null +++ b/src/test/regress/expected/multi_single_relation_subquery.out @@ -0,0 +1,194 @@ +-- +-- MULTI_SINGLE_RELATION_SUBQUERY +-- +-- This test checks that we are able to run selected set of distributed SQL subqueries. +SET citusdb.task_executor_type TO 'task-tracker'; +select + number_sum, + count(*) as total, + avg(total_count) avg_count +from + (select + l_suppkey, + l_linestatus, + sum(l_linenumber) as number_sum, + count(*) as total_count + from + lineitem + group by + l_suppkey, + l_linestatus) as distributed_table +where + number_sum >= 10 +group by + number_sum +order by + total desc, + number_sum desc +limit 10; + number_sum | total | avg_count +------------+-------+-------------------- + 10 | 136 | 2.3970588235294118 + 11 | 97 | 2.6082474226804124 + 12 | 56 | 2.8392857142857143 + 13 | 42 | 2.8809523809523810 + 14 | 21 | 3.2857142857142857 + 16 | 10 | 3.5000000000000000 + 15 | 10 | 3.3000000000000000 + 17 | 6 | 3.3333333333333333 + 18 | 3 | 4.0000000000000000 + 19 | 2 | 4.0000000000000000 +(10 rows) + +select + (l_suppkey / 100) as suppkey_bin, + avg(total_count) avg_count +from + (select + l_suppkey, + sum(l_linenumber) as number_sum, + count(*) as total_count + from + lineitem + group by + l_suppkey, + l_linestatus) as distributed_table +group by + suppkey_bin +order by + avg_count desc +limit 20; + suppkey_bin | avg_count +-------------+-------------------- + 95 | 1.4851485148514851 + 90 | 1.4761904761904762 + 52 | 1.4680851063829787 + 40 | 1.4659090909090909 + 15 | 1.4642857142857143 + 75 | 1.4444444444444444 + 72 | 1.4375000000000000 + 84 | 1.4242424242424242 + 35 | 1.4226804123711340 + 64 | 1.4166666666666667 + 74 | 1.4117647058823529 + 21 | 1.4000000000000000 + 18 | 1.4000000000000000 + 26 | 1.3932584269662921 + 96 | 1.3913043478260870 + 71 | 1.3913043478260870 + 86 | 1.3894736842105263 + 55 | 1.3882352941176471 + 57 | 1.3875000000000000 + 1 | 1.3846153846153846 +(20 rows) + +select + total, + avg(avg_count) as total_avg_count +from + (select + number_sum, + count(*) as total, + avg(total_count) avg_count + from + (select + l_suppkey, + sum(l_linenumber) as number_sum, + count(*) as total_count + from + lineitem + where + l_partkey > 100 and + l_quantity > 2 and + l_orderkey < 10000 + group by + l_suppkey) as distributed_table + where + number_sum >= 10 + group by + number_sum) as distributed_table_2 +group by + total +order by + total; + total | total_avg_count +-------+-------------------- + 1 | 4.8000000000000000 + 6 | 3.0000000000000000 + 10 | 3.5000000000000000 + 27 | 2.9259259259259259 + 32 | 2.8125000000000000 + 57 | 2.4912280701754386 + 77 | 2.3896103896103896 +(7 rows) + +-- Check that we support subquery even though group by clause is an expression +-- and it is not referred in the target list. +select + avg(count) +from + (select + l_suppkey, + count(*) as count + from + lineitem + group by + (l_orderkey/4)::int, + l_suppkey ) as distributed_table; + avg +------------------------ + 1.00083402835696413678 +(1 row) + +-- Check that we don't support subqueries with limit. +select + l_suppkey, + sum(suppkey_count) as total_suppkey_count +from + (select + l_suppkey, + count(*) as suppkey_count + from + lineitem + group by + l_suppkey + order by + l_suppkey + limit 100) as distributed_table +group by + l_suppkey; +ERROR: cannot perform distributed planning on this query +DETAIL: Subqueries with limit are not supported yet +-- Check that we don't support subqueries without aggregates. +select + rounded_tax +from + (select + round(l_tax) as rounded_tax + from + lineitem + group by + l_tax) as distributed_table; +ERROR: cannot perform distributed planning on this query +DETAIL: Subqueries without aggregates are not supported yet +-- Check that if subquery is pulled, we don't error and run query properly. +SELECT max(l_suppkey) FROM +( + SELECT + l_suppkey + FROM ( + SELECT + l_suppkey, + count(*) + FROM + lineitem_subquery + WHERE + l_orderkey < 20000 + GROUP BY + l_suppkey) z +) y; + max +------ + 9999 +(1 row) + diff --git a/src/test/regress/expected/multi_table_ddl.out b/src/test/regress/expected/multi_table_ddl.out new file mode 100644 index 000000000..9c2488fe0 --- /dev/null +++ b/src/test/regress/expected/multi_table_ddl.out @@ -0,0 +1,70 @@ +-- +-- MULTI_TABLE_DDL +-- +-- Tests around changing the schema and dropping of a distributed table +CREATE TABLE testtableddl(somecol int, distributecol text NOT NULL); +SELECT master_create_distributed_table('testtableddl', 'distributecol', 'append'); + master_create_distributed_table +--------------------------------- + +(1 row) + +-- verify that the citusdb extension can't be dropped while distributed tables exist +DROP EXTENSION citusdb; +WARNING: could not clean the metadata cache on DROP EXTENSION command +HINT: Reconnect to the server again. +ERROR: cannot drop extension citusdb because other objects depend on it +DETAIL: table testtableddl depends on extension citusdb +HINT: Use DROP ... CASCADE to drop the dependent objects too. +-- verify that the distribution column can't have its type changed +ALTER TABLE testtableddl ALTER COLUMN distributecol TYPE text; +ERROR: cannot execute ALTER TABLE command involving partition column +-- verify that the distribution column can't be dropped +ALTER TABLE testtableddl DROP COLUMN distributecol; +ERROR: cannot execute ALTER TABLE command involving partition column +-- verify that the table cannot be dropped while shards exist +SELECT 1 FROM master_create_empty_shard('testtableddl'); + ?column? +---------- + 1 +(1 row) + +DROP TABLE testtableddl; +ERROR: cannot drop distributed table with existing shards +HINT: Delete shards first using: SELECT master_apply_delete_command('DELETE FROM public.testtableddl') +-- not even with cascade +DROP TABLE testtableddl CASCADE; +ERROR: cannot drop distributed table with existing shards +HINT: Delete shards first using: SELECT master_apply_delete_command('DELETE FROM public.testtableddl') +-- but it can be dropped after dropping the shards +SELECT master_apply_delete_command('DELETE FROM testtableddl'); + master_apply_delete_command +----------------------------- + 1 +(1 row) + +DROP TABLE testtableddl; +-- ensure no metadata of distributed tables are remaining +SELECT * FROM pg_dist_partition; + logicalrelid | partmethod | partkey +--------------+------------+--------- +(0 rows) + +SELECT * FROM pg_dist_shard; + logicalrelid | shardid | shardstorage | shardalias | shardminvalue | shardmaxvalue +--------------+---------+--------------+------------+---------------+--------------- +(0 rows) + +SELECT * FROM pg_dist_shard_placement; + shardid | shardstate | shardlength | nodename | nodeport +---------+------------+-------------+----------+---------- +(0 rows) + +-- check that the extension now can be dropped (and recreated). We reconnect +-- before creating the extension to expire extension specific variables which +-- are cached for performance. +DROP EXTENSION citusdb; +WARNING: could not clean the metadata cache on DROP EXTENSION command +HINT: Reconnect to the server again. +\c +CREATE EXTENSION citusdb; diff --git a/src/test/regress/expected/multi_task_assignment_policy.out b/src/test/regress/expected/multi_task_assignment_policy.out new file mode 100644 index 000000000..11f4b5115 --- /dev/null +++ b/src/test/regress/expected/multi_task_assignment_policy.out @@ -0,0 +1,168 @@ +-- +-- MULTI_TASK_ASSIGNMENT +-- +-- Check that our policies for assigning tasks to worker nodes run as expected. +-- To test this, we first create a shell table, and then manually insert shard +-- and shard placement data into system catalogs. We next run Explain command, +-- and check that tasks are assigned to worker nodes as expected. +CREATE TABLE task_assignment_test_table (test_id integer); +SELECT master_create_distributed_table('task_assignment_test_table', 'test_id', 'append'); + master_create_distributed_table +--------------------------------- + +(1 row) + +-- Create logical shards with shardids 200, 201, and 202 +INSERT INTO pg_dist_shard (logicalrelid, shardid, shardstorage, shardminvalue, shardmaxvalue) + SELECT pg_class.oid, series.index, 'r', 1, 1000 + FROM pg_class, generate_series(200, 202) AS series(index) + WHERE pg_class.relname = 'task_assignment_test_table'; +-- Create shard placements for shard 200 and 201 +INSERT INTO pg_dist_shard_placement (shardid, shardstate, shardlength, nodename, nodeport) + SELECT 200, 1, 1, nodename, nodeport + FROM pg_dist_shard_placement + GROUP BY nodename, nodeport + ORDER BY nodename, nodeport ASC + LIMIT 2; +INSERT INTO pg_dist_shard_placement (shardid, shardstate, shardlength, nodename, nodeport) + SELECT 201, 1, 1, nodename, nodeport + FROM pg_dist_shard_placement + GROUP BY nodename, nodeport + ORDER BY nodename, nodeport ASC + LIMIT 2; +-- Create shard placements for shard 202 +INSERT INTO pg_dist_shard_placement (shardid, shardstate, shardlength, nodename, nodeport) + SELECT 202, 1, 1, nodename, nodeport + FROM pg_dist_shard_placement + GROUP BY nodename, nodeport + ORDER BY nodename, nodeport DESC + LIMIT 2; +-- Start transaction block to avoid auto commits. This avoids additional debug +-- messages from getting printed at real transaction starts and commits. +BEGIN; +-- Increase log level to see which worker nodes tasks are assigned to. Note that +-- the following log messages print node name and port numbers; and node numbers +-- in regression tests depend upon PG_VERSION_NUM. +SET client_min_messages TO DEBUG3; +DEBUG: CommitTransactionCommand +-- First test the default greedy task assignment policy +SET citusdb.task_assignment_policy TO 'greedy'; +DEBUG: StartTransactionCommand +DEBUG: ProcessUtility +DEBUG: CommitTransactionCommand +EXPLAIN SELECT count(*) FROM task_assignment_test_table; +DEBUG: StartTransactionCommand +DEBUG: ProcessUtility +DEBUG: assigned task 6 to node localhost:57637 +DEBUG: assigned task 2 to node localhost:57638 +DEBUG: assigned task 4 to node localhost:57637 +DEBUG: CommitTransactionCommand + QUERY PLAN +---------------------------------------------------------------------- + explain statements for distributed queries are currently unsupported +(1 row) + +EXPLAIN SELECT count(*) FROM task_assignment_test_table; +DEBUG: StartTransactionCommand +DEBUG: ProcessUtility +DEBUG: assigned task 6 to node localhost:57637 +DEBUG: assigned task 2 to node localhost:57638 +DEBUG: assigned task 4 to node localhost:57637 +DEBUG: CommitTransactionCommand + QUERY PLAN +---------------------------------------------------------------------- + explain statements for distributed queries are currently unsupported +(1 row) + +-- Next test the first-replica task assignment policy +SET citusdb.task_assignment_policy TO 'first-replica'; +DEBUG: StartTransactionCommand +DEBUG: ProcessUtility +DEBUG: CommitTransactionCommand +EXPLAIN SELECT count(*) FROM task_assignment_test_table; +DEBUG: StartTransactionCommand +DEBUG: ProcessUtility +DEBUG: assigned task 6 to node localhost:57637 +DEBUG: assigned task 4 to node localhost:57637 +DEBUG: assigned task 2 to node localhost:57638 +DEBUG: CommitTransactionCommand + QUERY PLAN +---------------------------------------------------------------------- + explain statements for distributed queries are currently unsupported +(1 row) + +EXPLAIN SELECT count(*) FROM task_assignment_test_table; +DEBUG: StartTransactionCommand +DEBUG: ProcessUtility +DEBUG: assigned task 6 to node localhost:57637 +DEBUG: assigned task 4 to node localhost:57637 +DEBUG: assigned task 2 to node localhost:57638 +DEBUG: CommitTransactionCommand + QUERY PLAN +---------------------------------------------------------------------- + explain statements for distributed queries are currently unsupported +(1 row) + +-- Round-robin task assignment relies on the current jobId. We therefore need to +-- ensure that jobIds start with an odd number here; this way, task assignment +-- debug messages always produce the same output. Also, we make sure that the +-- following case statement always prints out "1" as the query's result. +SELECT case when (currval('pg_dist_jobid_seq') % 2) = 0 + then nextval('pg_dist_jobid_seq') % 2 + else 1 end; +DEBUG: StartTransactionCommand +DEBUG: CommitTransactionCommand + case +------ + 1 +(1 row) + +-- Finally test the round-robin task assignment policy +SET citusdb.task_assignment_policy TO 'round-robin'; +DEBUG: StartTransactionCommand +DEBUG: ProcessUtility +DEBUG: CommitTransactionCommand +EXPLAIN SELECT count(*) FROM task_assignment_test_table; +DEBUG: StartTransactionCommand +DEBUG: ProcessUtility +DEBUG: assigned task 6 to node localhost:57637 +DEBUG: assigned task 4 to node localhost:57637 +DEBUG: assigned task 2 to node localhost:57638 +DEBUG: CommitTransactionCommand + QUERY PLAN +---------------------------------------------------------------------- + explain statements for distributed queries are currently unsupported +(1 row) + +EXPLAIN SELECT count(*) FROM task_assignment_test_table; +DEBUG: StartTransactionCommand +DEBUG: ProcessUtility +DEBUG: assigned task 6 to node localhost:57638 +DEBUG: assigned task 4 to node localhost:57638 +DEBUG: assigned task 2 to node localhost:57637 +DEBUG: CommitTransactionCommand + QUERY PLAN +---------------------------------------------------------------------- + explain statements for distributed queries are currently unsupported +(1 row) + +EXPLAIN SELECT count(*) FROM task_assignment_test_table; +DEBUG: StartTransactionCommand +DEBUG: ProcessUtility +DEBUG: assigned task 6 to node localhost:57637 +DEBUG: assigned task 4 to node localhost:57637 +DEBUG: assigned task 2 to node localhost:57638 +DEBUG: CommitTransactionCommand + QUERY PLAN +---------------------------------------------------------------------- + explain statements for distributed queries are currently unsupported +(1 row) + +RESET citusdb.task_assignment_policy; +DEBUG: StartTransactionCommand +DEBUG: ProcessUtility +DEBUG: CommitTransactionCommand +RESET client_min_messages; +DEBUG: StartTransactionCommand +DEBUG: ProcessUtility +COMMIT; diff --git a/src/test/regress/expected/multi_tpch_query1.out b/src/test/regress/expected/multi_tpch_query1.out new file mode 100644 index 000000000..39e75276a --- /dev/null +++ b/src/test/regress/expected/multi_tpch_query1.out @@ -0,0 +1,35 @@ +-- +-- MULTI_TPCH_QUERY1 +-- +-- Change configuration to treat lineitem and orders tables as large +SET citusdb.large_table_shard_count TO 2; +-- Query #1 from the TPC-H decision support benchmark +SELECT + l_returnflag, + l_linestatus, + sum(l_quantity) as sum_qty, + sum(l_extendedprice) as sum_base_price, + sum(l_extendedprice * (1 - l_discount)) as sum_disc_price, + sum(l_extendedprice * (1 - l_discount) * (1 + l_tax)) as sum_charge, + avg(l_quantity) as avg_qty, + avg(l_extendedprice) as avg_price, + avg(l_discount) as avg_disc, + count(*) as count_order +FROM + lineitem +WHERE + l_shipdate <= date '1998-12-01' - interval '90 days' +GROUP BY + l_returnflag, + l_linestatus +ORDER BY + l_returnflag, + l_linestatus; + l_returnflag | l_linestatus | sum_qty | sum_base_price | sum_disc_price | sum_charge | avg_qty | avg_price | avg_disc | count_order +--------------+--------------+-----------+----------------+----------------+------------------+---------------------+--------------------+------------------------+------------- + A | F | 75465.00 | 113619873.63 | 107841287.0728 | 112171153.245923 | 25.6334918478260870 | 38593.707075407609 | 0.05055027173913043478 | 2944 + N | F | 2022.00 | 3102551.45 | 2952540.7118 | 3072642.770652 | 26.6052631578947368 | 40823.045394736842 | 0.05263157894736842105 | 76 + N | O | 149778.00 | 224706948.16 | 213634857.6854 | 222134071.929801 | 25.4594594594594595 | 38195.979629440762 | 0.04939486656467788543 | 5883 + R | F | 73156.00 | 108937979.73 | 103516623.6698 | 107743533.784328 | 25.2175112030334367 | 37551.871675284385 | 0.04983798690106859704 | 2901 +(4 rows) + diff --git a/src/test/regress/expected/multi_tpch_query10.out b/src/test/regress/expected/multi_tpch_query10.out new file mode 100644 index 000000000..ea6f8406e --- /dev/null +++ b/src/test/regress/expected/multi_tpch_query10.out @@ -0,0 +1,62 @@ +-- +-- MULTI_TPCH_QUERY10 +-- +-- Query #10 from the TPC-H decision support benchmark. Unlike other TPC-H tests, +-- we don't set citusdb.large_table_shard_count here, and instead use the default value +-- coming from postgresql.conf or multi_task_tracker_executor.conf. +SELECT + c_custkey, + c_name, + sum(l_extendedprice * (1 - l_discount)) as revenue, + c_acctbal, + n_name, + c_address, + c_phone, + c_comment +FROM + customer, + orders, + lineitem, + nation +WHERE + c_custkey = o_custkey + AND l_orderkey = o_orderkey + AND o_orderdate >= date '1993-10-01' + AND o_orderdate < date '1993-10-01' + interval '3' month + AND l_returnflag = 'R' + AND c_nationkey = n_nationkey +GROUP BY + c_custkey, + c_name, + c_acctbal, + c_phone, + n_name, + c_address, + c_comment +ORDER BY + revenue DESC +LIMIT 20; + c_custkey | c_name | revenue | c_acctbal | n_name | c_address | c_phone | c_comment +-----------+--------------------+-------------+-----------+---------------------------+---------------------------------------+-----------------+--------------------------------------------------------------------------------------------------------------------- + 436 | Customer#000000436 | 255187.7382 | 5896.87 | ROMANIA | 4DCNzAT842cVYTcaUS94kR0QXHSRM5oco0D6Z | 29-927-687-6390 | olites engage carefully. slyly ironic asymptotes about the ironi + 640 | Customer#000000640 | 251941.1430 | 3025.84 | BRAZIL | j3vjr0 n,pJFG4gIOtC | 12-702-315-6637 | lly. furiously quick deposits haggle quickly regular packages. pinto + 361 | Customer#000000361 | 239204.0858 | 7451.84 | SAUDI ARABIA | l0F8jMJVe63cb | 30-164-267-4590 | fully busy ideas. regular foxes cajole + 223 | Customer#000000223 | 218652.8040 | 7476.20 | SAUDI ARABIA | ftau6Pk,brboMyEl,,kFm | 30-193-643-1517 | al, regular requests run furiously blithely silent packages. blithely ironic accounts across the furious + 613 | Customer#000000613 | 186092.2017 | 6679.75 | EGYPT | AJT,26RbanTdEHOBgTWg | 14-275-416-1669 | ironic, pending deposits: quickl + 355 | Customer#000000355 | 168184.4825 | 8727.90 | KENYA | 205r3Xg9ZWjPZNX1z | 24-656-787-6091 | ly bold requests detect furiously. unusual instructions sleep aft + 872 | Customer#000000872 | 166831.7294 | -858.61 | PERU | vLP7iNZBK4B,HANFTKabVI3AO Y9O8H | 27-357-139-7164 | detect. packages wake slyly express foxes. even deposits ru + 805 | Customer#000000805 | 165239.8440 | 511.69 | IRAN | wCKx5zcHvwpSffyc9qfi9dvqcm9LT,cLAG | 20-732-989-5653 | busy sentiments. pending packages haggle among the express requests-- slyly regular excuses above the slyl + 427 | Customer#000000427 | 148033.5226 | 4376.80 | BRAZIL | LHzXa71U2AGqfbqj1yYYqw2MEXq99dWmY | 12-124-309-3821 | y even multipliers according to the regu + 581 | Customer#000000581 | 146369.1712 | 3242.10 | UNITED STATES | s9SoN9XeVuCri | 34-415-978-2518 | ns. quickly regular pinto beans must sleep fluffily + 679 | Customer#000000679 | 145188.0664 | 1394.44 | IRAN | IJf1FlZL9I9m,rvofcoKy5pRUOjUQV | 20-146-696-9508 | ely pending frays boost carefully + 160 | Customer#000000160 | 138511.7370 | 4363.17 | JORDAN | 5soVQ3dOCRBWBS | 23-428-666-4806 | olites. silently ironic accounts cajole furious + 883 | Customer#000000883 | 128224.1349 | 479.96 | CANADA | qVQ8rWNU5KZYDcS | 13-526-239-6950 | uctions are carefully across the regular, regular asymptote + 101 | Customer#000000101 | 124996.0120 | 7470.96 | BRAZIL | sMmL2rNeHDltovSm Y | 12-514-298-3699 | sleep. pending packages detect slyly ironic pack + 671 | Customer#000000671 | 124125.2191 | 3227.87 | VIETNAM | ic6qGrt0giB,HDEiBK,,FYGHXQpc | 31-593-213-9388 | bold ideas above the ironic packages affix blithely about the furiou + 526 | Customer#000000526 | 120324.0048 | 705.93 | ARGENTINA | 0oAVPhh1I4JdrDafVG2Z8 | 11-170-679-3115 | ctions cajole after the furiously unusual ideas. ironic packages among the instructions are carefully carefully iro + 367 | Customer#000000367 | 118572.6180 | 9108.65 | JORDAN | yZaDoEZCqt2VMTVKoZUkf6gJ4yj | 23-939-319-4691 | eodolites under the ironic, stealthy requests affix furiously among the unusual tit + 745 | Customer#000000745 | 113738.6908 | 7115.14 | CHINA | vjuHvDKdaomsivy l | 28-913-438-9403 | o beans. bold, regular theodolites haggle carefully about the quickl + 118 | Customer#000000118 | 113149.7832 | 3582.37 | CHINA | OVnFuHygK9wx3xpg8 | 28-639-943-7051 | uick packages alongside of the furiously final deposits haggle above the fluffily even foxes. blithely dogged dep + 50 | Customer#000000050 | 111600.5870 | 4266.13 | FRANCE | 9SzDYlkzxByyJ1QeTI o | 16-658-112-3221 | ts. furiously ironic accounts cajole furiously slyly ironic dinos. +(20 rows) + diff --git a/src/test/regress/expected/multi_tpch_query12.out b/src/test/regress/expected/multi_tpch_query12.out new file mode 100644 index 000000000..8d692752d --- /dev/null +++ b/src/test/regress/expected/multi_tpch_query12.out @@ -0,0 +1,40 @@ +-- +-- MULTI_TPCH_QUERY12 +-- +-- Change configuration to treat lineitem and orders tables as large +SET citusdb.large_table_shard_count TO 2; +-- Query #12 from the TPC-H decision support benchmark +SELECT + l_shipmode, + sum(case + when o_orderpriority = '1-URGENT' + OR o_orderpriority = '2-HIGH' + then 1 + else 0 + end) as high_line_count, + sum(case + when o_orderpriority <> '1-URGENT' + AND o_orderpriority <> '2-HIGH' + then 1 + else 0 + end) AS low_line_count +FROM + orders, + lineitem +WHERE + o_orderkey = l_orderkey + AND l_shipmode in ('MAIL', 'SHIP') + AND l_commitdate < l_receiptdate + AND l_shipdate < l_commitdate + AND l_receiptdate >= date '1994-01-01' + AND l_receiptdate < date '1994-01-01' + interval '1' year +GROUP BY + l_shipmode +ORDER BY + l_shipmode; + l_shipmode | high_line_count | low_line_count +------------+-----------------+---------------- + MAIL | 11 | 15 + SHIP | 11 | 19 +(2 rows) + diff --git a/src/test/regress/expected/multi_tpch_query14.out b/src/test/regress/expected/multi_tpch_query14.out new file mode 100644 index 000000000..1f96ff96c --- /dev/null +++ b/src/test/regress/expected/multi_tpch_query14.out @@ -0,0 +1,24 @@ +-- +-- MULTI_TPCH_QUERY14 +-- +-- Change configuration to treat lineitem and orders tables as large +SET citusdb.large_table_shard_count TO 2; +-- Query #14 from the TPC-H decision support benchmark +SELECT + 100.00 * sum(case + when p_type like 'PROMO%' + then l_extendedprice * (1 - l_discount) + else 0 + end) / sum(l_extendedprice * (1 - l_discount)) as promo_revenue +FROM + lineitem, + part +WHERE + l_partkey = p_partkey + AND l_shipdate >= date '1995-09-01' + AND l_shipdate < date '1995-09-01' + interval '1' year; + promo_revenue +--------------------- + 32.1126387112005225 +(1 row) + diff --git a/src/test/regress/expected/multi_tpch_query19.out b/src/test/regress/expected/multi_tpch_query19.out new file mode 100644 index 000000000..784c2f5ce --- /dev/null +++ b/src/test/regress/expected/multi_tpch_query19.out @@ -0,0 +1,41 @@ +-- +-- MULTI_TPCH_QUERY19 +-- +-- Change configuration to treat lineitem and orders tables as large +SET citusdb.large_table_shard_count TO 2; +-- Query #19 from the TPC-H decision support benchmark. Note that we modified +-- the query from its original to make it work on smaller data sets. +SELECT + sum(l_extendedprice* (1 - l_discount)) as revenue +FROM + lineitem, + part +WHERE + ( + p_partkey = l_partkey + AND (p_brand = 'Brand#12' OR p_brand= 'Brand#14' OR p_brand='Brand#15') + AND l_quantity >= 10 + AND l_shipmode in ('AIR', 'AIR REG', 'TRUCK') + AND l_shipinstruct = 'DELIVER IN PERSON' + ) + OR + ( + p_partkey = l_partkey + AND (p_brand = 'Brand#23' OR p_brand='Brand#24') + AND l_quantity >= 20 + AND l_shipmode in ('AIR', 'AIR REG', 'TRUCK') + AND l_shipinstruct = 'DELIVER IN PERSON' + ) + OR + ( + p_partkey = l_partkey + AND (p_brand = 'Brand#33' OR p_brand = 'Brand#34' OR p_brand = 'Brand#35') + AND l_quantity >= 1 + AND l_shipmode in ('AIR', 'AIR REG', 'TRUCK') + AND l_shipinstruct = 'DELIVER IN PERSON' + ); + revenue +------------- + 144747.0857 +(1 row) + diff --git a/src/test/regress/expected/multi_tpch_query3.out b/src/test/regress/expected/multi_tpch_query3.out new file mode 100644 index 000000000..c16171339 --- /dev/null +++ b/src/test/regress/expected/multi_tpch_query3.out @@ -0,0 +1,48 @@ +-- +-- MULTI_TPCH_QUERY3 +-- +-- Query #3 from the TPC-H decision support benchmark. Unlike other TPC-H tests, +-- we don't set citusdb.large_table_shard_count here, and instead use the default value +-- coming from postgresql.conf or multi_task_tracker_executor.conf. +SELECT + l_orderkey, + sum(l_extendedprice * (1 - l_discount)) as revenue, + o_orderdate, + o_shippriority +FROM + customer, + orders, + lineitem +WHERE + c_mktsegment = 'BUILDING' + AND c_custkey = o_custkey + AND l_orderkey = o_orderkey + AND o_orderdate < date '1995-03-15' + AND l_shipdate > date '1995-03-15' +GROUP BY + l_orderkey, + o_orderdate, + o_shippriority +ORDER BY + revenue DESC, + o_orderdate; + l_orderkey | revenue | o_orderdate | o_shippriority +------------+-------------+-------------+---------------- + 1637 | 268170.6408 | 02-08-1995 | 0 + 9696 | 252014.5497 | 02-20-1995 | 0 + 10916 | 242749.1996 | 03-11-1995 | 0 + 450 | 221012.3165 | 03-05-1995 | 0 + 5347 | 198353.7942 | 02-22-1995 | 0 + 10691 | 112800.1020 | 03-14-1995 | 0 + 386 | 104975.2484 | 01-25-1995 | 0 + 5765 | 88222.7556 | 12-15-1994 | 0 + 4707 | 88143.7774 | 02-27-1995 | 0 + 5312 | 83750.7028 | 02-24-1995 | 0 + 5728 | 70101.6400 | 12-11-1994 | 0 + 577 | 57986.6224 | 12-19-1994 | 0 + 12706 | 16636.6368 | 11-21-1994 | 0 + 3844 | 8851.3200 | 12-29-1994 | 0 + 11073 | 7433.6295 | 12-02-1994 | 0 + 13924 | 3111.4970 | 12-20-1994 | 0 +(16 rows) + diff --git a/src/test/regress/expected/multi_tpch_query6.out b/src/test/regress/expected/multi_tpch_query6.out new file mode 100644 index 000000000..977009bbb --- /dev/null +++ b/src/test/regress/expected/multi_tpch_query6.out @@ -0,0 +1,20 @@ +-- +-- MULTI_TPCH_QUERY6 +-- +-- Change configuration to treat lineitem and orders tables as large +SET citusdb.large_table_shard_count TO 2; +-- Query #6 from the TPC-H decision support benchmark +SELECT + sum(l_extendedprice * l_discount) as revenue +FROM + lineitem +WHERE + l_shipdate >= date '1994-01-01' + and l_shipdate < date '1994-01-01' + interval '1 year' + and l_discount between 0.06 - 0.01 and 0.06 + 0.01 + and l_quantity < 24; + revenue +------------- + 243277.7858 +(1 row) + diff --git a/src/test/regress/expected/multi_tpch_query7.out b/src/test/regress/expected/multi_tpch_query7.out new file mode 100644 index 000000000..253da5c71 --- /dev/null +++ b/src/test/regress/expected/multi_tpch_query7.out @@ -0,0 +1,50 @@ +-- +-- MULTI_TPCH_QUERY7 +-- +-- Change configuration to treat lineitem AND orders tables as large +SET citusdb.large_table_shard_count TO 2; +-- Query #7 from the TPC-H decision support benchmark +SELECT + supp_nation, + cust_nation, + l_year, + sum(volume) as revenue +FROM + ( + SELECT + n1.n_name as supp_nation, + n2.n_name as cust_nation, + extract(year FROM l_shipdate) as l_year, + l_extendedprice * (1 - l_discount) as volume + FROM + supplier, + lineitem, + orders, + customer, + nation n1, + nation n2 + WHERE + s_suppkey = l_suppkey + AND o_orderkey = l_orderkey + AND c_custkey = o_custkey + AND s_nationkey = n1.n_nationkey + AND c_nationkey = n2.n_nationkey + AND ( + (n1.n_name = 'FRANCE' AND n2.n_name = 'GERMANY') + OR (n1.n_name = 'GERMANY' AND n2.n_name = 'FRANCE') + ) + AND l_shipdate between date '1995-01-01' AND date '1996-12-31' + ) as shipping +GROUP BY + supp_nation, + cust_nation, + l_year +ORDER BY + supp_nation, + cust_nation, + l_year; + supp_nation | cust_nation | l_year | revenue +---------------------------+---------------------------+--------+----------- + GERMANY | FRANCE | 1995 | 2399.2948 +(1 row) + diff --git a/src/test/regress/expected/multi_tpch_query7_nested.out b/src/test/regress/expected/multi_tpch_query7_nested.out new file mode 100644 index 000000000..493b3bf1e --- /dev/null +++ b/src/test/regress/expected/multi_tpch_query7_nested.out @@ -0,0 +1,59 @@ +-- +-- MULTI_TPCH_QUERY7_NESTED +-- +-- Change configuration to treat lineitem AND orders tables AS large +SET citusdb.large_table_shard_count TO 2; +-- Query #7 from the TPC-H benchmark; modified to include sub-selects +SELECT + supp_nation, + cust_nation, + l_year, + sum(volume) AS revenue +FROM + ( + SELECT + supp_nation, + cust_nation, + extract(year FROM l_shipdate) AS l_year, + l_extendedprice * (1 - l_discount) AS volume + FROM + supplier, + lineitem, + orders, + customer, + ( + SELECT + n1.n_nationkey AS supp_nation_key, + n2.n_nationkey AS cust_nation_key, + n1.n_name AS supp_nation, + n2.n_name AS cust_nation + FROM + nation n1, + nation n2 + WHERE + ( + (n1.n_name = 'FRANCE' AND n2.n_name = 'GERMANY') + OR (n1.n_name = 'GERMANY' AND n2.n_name = 'FRANCE') + ) + ) AS temp + WHERE + s_suppkey = l_suppkey + AND o_orderkey = l_orderkey + AND c_custkey = o_custkey + AND s_nationkey = supp_nation_key + AND c_nationkey = cust_nation_key + AND l_shipdate between date '1995-01-01' AND date '1996-12-31' + ) AS shipping +GROUP BY + supp_nation, + cust_nation, + l_year +ORDER BY + supp_nation, + cust_nation, + l_year; + supp_nation | cust_nation | l_year | revenue +---------------------------+---------------------------+--------+----------- + GERMANY | FRANCE | 1995 | 2399.2948 +(1 row) + diff --git a/src/test/regress/expected/multi_upsert.out b/src/test/regress/expected/multi_upsert.out new file mode 100644 index 000000000..6222c87e8 --- /dev/null +++ b/src/test/regress/expected/multi_upsert.out @@ -0,0 +1,238 @@ +-- this test file aims to test UPSERT feature on CitusDB +-- note that output of this file for postgresql 9.4 will +-- be full syntax errors, which is expected. +CREATE TABLE upsert_test +( + part_key int UNIQUE, + other_col int, + third_col int +); +-- distribute the table and create shards +SELECT master_create_distributed_table('upsert_test', 'part_key', 'hash'); + master_create_distributed_table +--------------------------------- + +(1 row) + +SELECT master_create_worker_shards('upsert_test', '4', '2'); + master_create_worker_shards +----------------------------- + +(1 row) + +-- do a regular insert +INSERT INTO upsert_test (part_key, other_col) VALUES (1, 1); +-- observe that there is a conflict and the following query does nothing +INSERT INTO upsert_test (part_key, other_col) VALUES (1, 1) ON CONFLICT DO NOTHING; +-- same as the above with different syntax +INSERT INTO upsert_test (part_key, other_col) VALUES (1, 1) ON CONFLICT (part_key) DO NOTHING; +--again the same query with another syntax +INSERT INTO upsert_test (part_key, other_col) VALUES (1, 1) ON CONFLICT ON CONSTRAINT upsert_test_part_key_key DO NOTHING; +-- now, update the columns +INSERT INTO upsert_test (part_key, other_col) VALUES (1, 1) + ON CONFLICT (part_key) DO UPDATE SET other_col = 2, third_col = 4; +-- see the results +SELECT * FROM upsert_test; + part_key | other_col | third_col +----------+-----------+----------- + 1 | 2 | 4 +(1 row) + +-- use a WHERE clause, so that SET doesn't have an affect +INSERT INTO upsert_test (part_key, other_col) VALUES (1, 1) ON CONFLICT (part_key) + DO UPDATE SET other_col = 30 WHERE upsert_test.other_col = 3; +-- see the results +SELECT * FROM upsert_test; + part_key | other_col | third_col +----------+-----------+----------- + 1 | 2 | 4 +(1 row) + +-- use a WHERE clause, that hits the row and updates it +INSERT INTO upsert_test (part_key, other_col) VALUES (1, 1) ON CONFLICT (part_key) + DO UPDATE SET other_col = 30 WHERE upsert_test.other_col = 2; +-- see the results +SELECT * FROM upsert_test; + part_key | other_col | third_col +----------+-----------+----------- + 1 | 30 | 4 +(1 row) + +-- use two elements in the WHERE, that doesn't hit the row and updates it +INSERT INTO upsert_test (part_key, other_col) VALUES (1, 1) ON CONFLICT (part_key) + DO UPDATE SET other_col = 30 WHERE upsert_test.other_col = 2 AND upsert_test.other_col = 3; +-- use EXCLUDED keyword +INSERT INTO upsert_test (part_key, other_col, third_col) VALUES (1, 1, 100) ON CONFLICT (part_key) + DO UPDATE SET other_col = EXCLUDED.third_col; +-- see the results +SELECT * FROM upsert_test; + part_key | other_col | third_col +----------+-----------+----------- + 1 | 100 | 4 +(1 row) + +-- now update multiple columns with ALIAS table and reference to the row itself +INSERT INTO upsert_test as ups_test (part_key) VALUES (1) + ON CONFLICT (part_key) DO UPDATE SET other_col = ups_test.other_col + 50, third_col = 200; +-- see the results +SELECT * FROM upsert_test; + part_key | other_col | third_col +----------+-----------+----------- + 1 | 150 | 200 +(1 row) + +-- now, do some more complex assignments +INSERT INTO upsert_test (part_key, other_col) VALUES (1, 1) ON CONFLICT (part_key) + DO UPDATE SET other_col = upsert_test.other_col + 1, + third_col = upsert_test.third_col + (EXCLUDED.part_key + EXCLUDED.other_col) + 670; +-- see the results +SELECT * FROM upsert_test; + part_key | other_col | third_col +----------+-----------+----------- + 1 | 151 | 872 +(1 row) + +-- now, WHERE clause also has table reference +INSERT INTO upsert_test as ups_test (part_key, other_col) VALUES (1, 1) ON CONFLICT (part_key) + DO UPDATE SET other_col = (ups_test.other_col + ups_test.third_col + (EXCLUDED.part_key + EXCLUDED.other_col)) % 15 + WHERE ups_test.third_col < 1000 + ups_test.other_col; +-- see the results +SELECT * FROM upsert_test; + part_key | other_col | third_col +----------+-----------+----------- + 1 | 5 | 872 +(1 row) + +-- create another table +CREATE TABLE upsert_test_2 +( + part_key int, + other_col int, + third_col int, + PRIMARY KEY (part_key, other_col) +); +-- distribute the table and create shards +SELECT master_create_distributed_table('upsert_test_2', 'part_key', 'hash'); + master_create_distributed_table +--------------------------------- + +(1 row) + +SELECT master_create_worker_shards('upsert_test_2', '4', '2'); + master_create_worker_shards +----------------------------- + +(1 row) + +-- now show that CitusDB works with multiple columns as the PRIMARY KEY, including the partiton key +INSERT INTO upsert_test_2 (part_key, other_col) VALUES (1, 1); +INSERT INTO upsert_test_2 (part_key, other_col) VALUES (1, 1) ON CONFLICT (part_key, other_col) DO NOTHING; +-- this errors out since there is no unique constraint on partition key +INSERT INTO upsert_test_2 (part_key, other_col) VALUES (1, 1) ON CONFLICT (part_key) DO NOTHING; +ERROR: there is no unique or exclusion constraint matching the ON CONFLICT specification +-- create another table +CREATE TABLE upsert_test_3 +( + part_key int, + count int +); +-- note that this is not a unique index +CREATE INDEX idx_ups_test ON upsert_test_3(part_key); +-- distribute the table and create shards +SELECT master_create_distributed_table('upsert_test_3', 'part_key', 'hash'); + master_create_distributed_table +--------------------------------- + +(1 row) + +SELECT master_create_worker_shards('upsert_test_3', '4', '2'); + master_create_worker_shards +----------------------------- + +(1 row) + +-- since there are no unique indexes, error-out +INSERT INTO upsert_test_3 VALUES (1, 0) ON CONFLICT(part_key) DO UPDATE SET count = upsert_test_3.count + 1; +ERROR: there is no unique or exclusion constraint matching the ON CONFLICT specification +-- create another table +CREATE TABLE upsert_test_4 +( + part_key int UNIQUE, + count int +); +-- distribute the table and create shards +SELECT master_create_distributed_table('upsert_test_4', 'part_key', 'hash'); + master_create_distributed_table +--------------------------------- + +(1 row) + +SELECT master_create_worker_shards('upsert_test_4', '4', '2'); + master_create_worker_shards +----------------------------- + +(1 row) + +-- a single row insert +INSERT INTO upsert_test_4 VALUES (1, 0); +-- show a simple count example use case +INSERT INTO upsert_test_4 VALUES (1, 0) ON CONFLICT(part_key) DO UPDATE SET count = upsert_test_4.count + 1; +INSERT INTO upsert_test_4 VALUES (1, 0) ON CONFLICT(part_key) DO UPDATE SET count = upsert_test_4.count + 1; +INSERT INTO upsert_test_4 VALUES (1, 0) ON CONFLICT(part_key) DO UPDATE SET count = upsert_test_4.count + 1; +INSERT INTO upsert_test_4 VALUES (1, 0) ON CONFLICT(part_key) DO UPDATE SET count = upsert_test_4.count + 1; +INSERT INTO upsert_test_4 VALUES (1, 0) ON CONFLICT(part_key) DO UPDATE SET count = upsert_test_4.count + 1; +INSERT INTO upsert_test_4 VALUES (1, 0) ON CONFLICT(part_key) DO UPDATE SET count = upsert_test_4.count + 1; +-- now see the results +SELECT * FROM upsert_test_4; + part_key | count +----------+------- + 1 | 6 +(1 row) + +-- now test dropped columns +CREATE TABLE dropcol_distributed(key int primary key, drop1 int, keep1 text, drop2 numeric, keep2 float); +SELECT master_create_distributed_table('dropcol_distributed', 'key', 'hash'); + master_create_distributed_table +--------------------------------- + +(1 row) + +SELECT master_create_worker_shards('dropcol_distributed', 4, 1); + master_create_worker_shards +----------------------------- + +(1 row) + +INSERT INTO dropcol_distributed AS dropcol (key, keep1, keep2) VALUES (1, '5', 5) ON CONFLICT(key) + DO UPDATE SET keep1 = dropcol.keep1; +ALTER TABLE dropcol_distributed DROP COLUMN drop2; +INSERT INTO dropcol_distributed (key, keep1, keep2) VALUES (1, '5', 5) ON CONFLICT(key) + DO UPDATE SET keep1 = dropcol_distributed.keep1; +ALTER TABLE dropcol_distributed DROP COLUMN keep2; +INSERT INTO dropcol_distributed AS dropcol (key, keep1) VALUES (1, '5') ON CONFLICT(key) + DO UPDATE SET keep1 = dropcol.keep1; +ALTER TABLE dropcol_distributed DROP COLUMN drop1; +INSERT INTO dropcol_distributed AS dropcol (key, keep1) VALUES (1, '5') ON CONFLICT(key) + DO UPDATE SET keep1 = dropcol.keep1; +-- below we test the cases that CitusDB does not support +-- subquery in the SET clause +INSERT INTO upsert_test (part_key, other_col) VALUES (1, 1) ON CONFLICT (part_key) DO + UPDATE SET other_col = (SELECT count(*) from upsert_test); +ERROR: cannot perform distributed planning for the given modification +DETAIL: Subqueries are not supported in distributed modifications. +-- non mutable function call in the SET +INSERT INTO upsert_test (part_key, other_col) VALUES (1, 1) ON CONFLICT (part_key) DO + UPDATE SET other_col = random()::int; +ERROR: cannot plan sharded modification containing values which are not constants or constant expressions +-- non mutable function call in the WHERE +INSERT INTO upsert_test (part_key, other_col) VALUES (1, 1) ON CONFLICT (part_key) DO + UPDATE SET other_col = 5 WHERE upsert_test.other_col = random()::int; +ERROR: cannot plan sharded modification containing values which are not constants or constant expressions +-- non mutable function call in the arbiter WHERE +INSERT INTO upsert_test (part_key, other_col) VALUES (1, 1) ON CONFLICT (part_key) WHERE part_key = random()::int + DO UPDATE SET other_col = 5; +ERROR: cannot plan sharded modification containing values which are not constants or constant expressions +-- error out on attempt to update the partition key +INSERT INTO upsert_test (part_key, other_col) VALUES (1, 1) ON CONFLICT (part_key) DO + UPDATE SET part_key = 15; +ERROR: modifying the partition value of rows is not allowed diff --git a/src/test/regress/expected/multi_upsert_0.out b/src/test/regress/expected/multi_upsert_0.out new file mode 100644 index 000000000..461eb804c --- /dev/null +++ b/src/test/regress/expected/multi_upsert_0.out @@ -0,0 +1,317 @@ +-- this test file aims to test UPSERT feature on CitusDB +-- note that output of this file for postgresql 9.4 will +-- be full syntax errors, which is expected. +CREATE TABLE upsert_test +( + part_key int UNIQUE, + other_col int, + third_col int +); +-- distribute the table and create shards +SELECT master_create_distributed_table('upsert_test', 'part_key', 'hash'); + master_create_distributed_table +--------------------------------- + +(1 row) + +SELECT master_create_worker_shards('upsert_test', '4', '2'); + master_create_worker_shards +----------------------------- + +(1 row) + +-- do a regular insert +INSERT INTO upsert_test (part_key, other_col) VALUES (1, 1); +-- observe that there is a conflict and the following query does nothing +INSERT INTO upsert_test (part_key, other_col) VALUES (1, 1) ON CONFLICT DO NOTHING; +ERROR: syntax error at or near "ON" +LINE 1: ...O upsert_test (part_key, other_col) VALUES (1, 1) ON CONFLIC... + ^ +-- same as the above with different syntax +INSERT INTO upsert_test (part_key, other_col) VALUES (1, 1) ON CONFLICT (part_key) DO NOTHING; +ERROR: syntax error at or near "ON" +LINE 1: ...O upsert_test (part_key, other_col) VALUES (1, 1) ON CONFLIC... + ^ +--again the same query with another syntax +INSERT INTO upsert_test (part_key, other_col) VALUES (1, 1) ON CONFLICT ON CONSTRAINT upsert_test_part_key_key DO NOTHING; +ERROR: syntax error at or near "ON" +LINE 1: ...O upsert_test (part_key, other_col) VALUES (1, 1) ON CONFLIC... + ^ +-- now, update the columns +INSERT INTO upsert_test (part_key, other_col) VALUES (1, 1) + ON CONFLICT (part_key) DO UPDATE SET other_col = 2, third_col = 4; +ERROR: syntax error at or near "ON" +LINE 2: ON CONFLICT (part_key) DO UPDATE SET other_col = 2, third_... + ^ +-- see the results +SELECT * FROM upsert_test; + part_key | other_col | third_col +----------+-----------+----------- + 1 | 1 | +(1 row) + +-- use a WHERE clause, so that SET doesn't have an affect +INSERT INTO upsert_test (part_key, other_col) VALUES (1, 1) ON CONFLICT (part_key) + DO UPDATE SET other_col = 30 WHERE upsert_test.other_col = 3; +ERROR: syntax error at or near "ON" +LINE 1: ...O upsert_test (part_key, other_col) VALUES (1, 1) ON CONFLIC... + ^ +-- see the results +SELECT * FROM upsert_test; + part_key | other_col | third_col +----------+-----------+----------- + 1 | 1 | +(1 row) + +-- use a WHERE clause, that hits the row and updates it +INSERT INTO upsert_test (part_key, other_col) VALUES (1, 1) ON CONFLICT (part_key) + DO UPDATE SET other_col = 30 WHERE upsert_test.other_col = 2; +ERROR: syntax error at or near "ON" +LINE 1: ...O upsert_test (part_key, other_col) VALUES (1, 1) ON CONFLIC... + ^ +-- see the results +SELECT * FROM upsert_test; + part_key | other_col | third_col +----------+-----------+----------- + 1 | 1 | +(1 row) + +-- use two elements in the WHERE, that doesn't hit the row and updates it +INSERT INTO upsert_test (part_key, other_col) VALUES (1, 1) ON CONFLICT (part_key) + DO UPDATE SET other_col = 30 WHERE upsert_test.other_col = 2 AND upsert_test.other_col = 3; +ERROR: syntax error at or near "ON" +LINE 1: ...O upsert_test (part_key, other_col) VALUES (1, 1) ON CONFLIC... + ^ +-- use EXCLUDED keyword +INSERT INTO upsert_test (part_key, other_col, third_col) VALUES (1, 1, 100) ON CONFLICT (part_key) + DO UPDATE SET other_col = EXCLUDED.third_col; +ERROR: syntax error at or near "ON" +LINE 1: ...art_key, other_col, third_col) VALUES (1, 1, 100) ON CONFLIC... + ^ +-- see the results +SELECT * FROM upsert_test; + part_key | other_col | third_col +----------+-----------+----------- + 1 | 1 | +(1 row) + +-- now update multiple columns with ALIAS table and reference to the row itself +INSERT INTO upsert_test as ups_test (part_key) VALUES (1) + ON CONFLICT (part_key) DO UPDATE SET other_col = ups_test.other_col + 50, third_col = 200; +ERROR: syntax error at or near "as" +LINE 1: INSERT INTO upsert_test as ups_test (part_key) VALUES (1) + ^ +-- see the results +SELECT * FROM upsert_test; + part_key | other_col | third_col +----------+-----------+----------- + 1 | 1 | +(1 row) + +-- now, do some more complex assignments +INSERT INTO upsert_test (part_key, other_col) VALUES (1, 1) ON CONFLICT (part_key) + DO UPDATE SET other_col = upsert_test.other_col + 1, + third_col = upsert_test.third_col + (EXCLUDED.part_key + EXCLUDED.other_col) + 670; +ERROR: syntax error at or near "ON" +LINE 1: ...O upsert_test (part_key, other_col) VALUES (1, 1) ON CONFLIC... + ^ +-- see the results +SELECT * FROM upsert_test; + part_key | other_col | third_col +----------+-----------+----------- + 1 | 1 | +(1 row) + +-- now, WHERE clause also has table reference +INSERT INTO upsert_test as ups_test (part_key, other_col) VALUES (1, 1) ON CONFLICT (part_key) + DO UPDATE SET other_col = (ups_test.other_col + ups_test.third_col + (EXCLUDED.part_key + EXCLUDED.other_col)) % 15 + WHERE ups_test.third_col < 1000 + ups_test.other_col; +ERROR: syntax error at or near "as" +LINE 1: INSERT INTO upsert_test as ups_test (part_key, other_col) VA... + ^ +-- see the results +SELECT * FROM upsert_test; + part_key | other_col | third_col +----------+-----------+----------- + 1 | 1 | +(1 row) + +-- create another table +CREATE TABLE upsert_test_2 +( + part_key int, + other_col int, + third_col int, + PRIMARY KEY (part_key, other_col) +); +-- distribute the table and create shards +SELECT master_create_distributed_table('upsert_test_2', 'part_key', 'hash'); + master_create_distributed_table +--------------------------------- + +(1 row) + +SELECT master_create_worker_shards('upsert_test_2', '4', '2'); + master_create_worker_shards +----------------------------- + +(1 row) + +-- now show that CitusDB works with multiple columns as the PRIMARY KEY, including the partiton key +INSERT INTO upsert_test_2 (part_key, other_col) VALUES (1, 1); +INSERT INTO upsert_test_2 (part_key, other_col) VALUES (1, 1) ON CONFLICT (part_key, other_col) DO NOTHING; +ERROR: syntax error at or near "ON" +LINE 1: ...upsert_test_2 (part_key, other_col) VALUES (1, 1) ON CONFLIC... + ^ +-- this errors out since there is no unique constraint on partition key +INSERT INTO upsert_test_2 (part_key, other_col) VALUES (1, 1) ON CONFLICT (part_key) DO NOTHING; +ERROR: syntax error at or near "ON" +LINE 1: ...upsert_test_2 (part_key, other_col) VALUES (1, 1) ON CONFLIC... + ^ +-- create another table +CREATE TABLE upsert_test_3 +( + part_key int, + count int +); +-- note that this is not a unique index +CREATE INDEX idx_ups_test ON upsert_test_3(part_key); +-- distribute the table and create shards +SELECT master_create_distributed_table('upsert_test_3', 'part_key', 'hash'); + master_create_distributed_table +--------------------------------- + +(1 row) + +SELECT master_create_worker_shards('upsert_test_3', '4', '2'); + master_create_worker_shards +----------------------------- + +(1 row) + +-- since there are no unique indexes, error-out +INSERT INTO upsert_test_3 VALUES (1, 0) ON CONFLICT(part_key) DO UPDATE SET count = upsert_test_3.count + 1; +ERROR: syntax error at or near "ON" +LINE 1: INSERT INTO upsert_test_3 VALUES (1, 0) ON CONFLICT(part_key... + ^ +-- create another table +CREATE TABLE upsert_test_4 +( + part_key int UNIQUE, + count int +); +-- distribute the table and create shards +SELECT master_create_distributed_table('upsert_test_4', 'part_key', 'hash'); + master_create_distributed_table +--------------------------------- + +(1 row) + +SELECT master_create_worker_shards('upsert_test_4', '4', '2'); + master_create_worker_shards +----------------------------- + +(1 row) + +-- a single row insert +INSERT INTO upsert_test_4 VALUES (1, 0); +-- show a simple count example use case +INSERT INTO upsert_test_4 VALUES (1, 0) ON CONFLICT(part_key) DO UPDATE SET count = upsert_test_4.count + 1; +ERROR: syntax error at or near "ON" +LINE 1: INSERT INTO upsert_test_4 VALUES (1, 0) ON CONFLICT(part_key... + ^ +INSERT INTO upsert_test_4 VALUES (1, 0) ON CONFLICT(part_key) DO UPDATE SET count = upsert_test_4.count + 1; +ERROR: syntax error at or near "ON" +LINE 1: INSERT INTO upsert_test_4 VALUES (1, 0) ON CONFLICT(part_key... + ^ +INSERT INTO upsert_test_4 VALUES (1, 0) ON CONFLICT(part_key) DO UPDATE SET count = upsert_test_4.count + 1; +ERROR: syntax error at or near "ON" +LINE 1: INSERT INTO upsert_test_4 VALUES (1, 0) ON CONFLICT(part_key... + ^ +INSERT INTO upsert_test_4 VALUES (1, 0) ON CONFLICT(part_key) DO UPDATE SET count = upsert_test_4.count + 1; +ERROR: syntax error at or near "ON" +LINE 1: INSERT INTO upsert_test_4 VALUES (1, 0) ON CONFLICT(part_key... + ^ +INSERT INTO upsert_test_4 VALUES (1, 0) ON CONFLICT(part_key) DO UPDATE SET count = upsert_test_4.count + 1; +ERROR: syntax error at or near "ON" +LINE 1: INSERT INTO upsert_test_4 VALUES (1, 0) ON CONFLICT(part_key... + ^ +INSERT INTO upsert_test_4 VALUES (1, 0) ON CONFLICT(part_key) DO UPDATE SET count = upsert_test_4.count + 1; +ERROR: syntax error at or near "ON" +LINE 1: INSERT INTO upsert_test_4 VALUES (1, 0) ON CONFLICT(part_key... + ^ +-- now see the results +SELECT * FROM upsert_test_4; + part_key | count +----------+------- + 1 | 0 +(1 row) + +-- now test dropped columns +CREATE TABLE dropcol_distributed(key int primary key, drop1 int, keep1 text, drop2 numeric, keep2 float); +SELECT master_create_distributed_table('dropcol_distributed', 'key', 'hash'); + master_create_distributed_table +--------------------------------- + +(1 row) + +SELECT master_create_worker_shards('dropcol_distributed', 4, 1); + master_create_worker_shards +----------------------------- + +(1 row) + +INSERT INTO dropcol_distributed AS dropcol (key, keep1, keep2) VALUES (1, '5', 5) ON CONFLICT(key) + DO UPDATE SET keep1 = dropcol.keep1; +ERROR: syntax error at or near "AS" +LINE 1: INSERT INTO dropcol_distributed AS dropcol (key, keep1, keep... + ^ +ALTER TABLE dropcol_distributed DROP COLUMN drop2; +INSERT INTO dropcol_distributed (key, keep1, keep2) VALUES (1, '5', 5) ON CONFLICT(key) + DO UPDATE SET keep1 = dropcol_distributed.keep1; +ERROR: syntax error at or near "ON" +LINE 1: ...istributed (key, keep1, keep2) VALUES (1, '5', 5) ON CONFLIC... + ^ +ALTER TABLE dropcol_distributed DROP COLUMN keep2; +INSERT INTO dropcol_distributed AS dropcol (key, keep1) VALUES (1, '5') ON CONFLICT(key) + DO UPDATE SET keep1 = dropcol.keep1; +ERROR: syntax error at or near "AS" +LINE 1: INSERT INTO dropcol_distributed AS dropcol (key, keep1) VALU... + ^ +ALTER TABLE dropcol_distributed DROP COLUMN drop1; +INSERT INTO dropcol_distributed AS dropcol (key, keep1) VALUES (1, '5') ON CONFLICT(key) + DO UPDATE SET keep1 = dropcol.keep1; +ERROR: syntax error at or near "AS" +LINE 1: INSERT INTO dropcol_distributed AS dropcol (key, keep1) VALU... + ^ +-- below we test the cases that CitusDB does not support +-- subquery in the SET clause +INSERT INTO upsert_test (part_key, other_col) VALUES (1, 1) ON CONFLICT (part_key) DO + UPDATE SET other_col = (SELECT count(*) from upsert_test); +ERROR: syntax error at or near "ON" +LINE 1: ...O upsert_test (part_key, other_col) VALUES (1, 1) ON CONFLIC... + ^ +-- non mutable function call in the SET +INSERT INTO upsert_test (part_key, other_col) VALUES (1, 1) ON CONFLICT (part_key) DO + UPDATE SET other_col = random()::int; +ERROR: syntax error at or near "ON" +LINE 1: ...O upsert_test (part_key, other_col) VALUES (1, 1) ON CONFLIC... + ^ +-- non mutable function call in the WHERE +INSERT INTO upsert_test (part_key, other_col) VALUES (1, 1) ON CONFLICT (part_key) DO + UPDATE SET other_col = 5 WHERE upsert_test.other_col = random()::int; +ERROR: syntax error at or near "ON" +LINE 1: ...O upsert_test (part_key, other_col) VALUES (1, 1) ON CONFLIC... + ^ +-- non mutable function call in the arbiter WHERE +INSERT INTO upsert_test (part_key, other_col) VALUES (1, 1) ON CONFLICT (part_key) WHERE part_key = random()::int + DO UPDATE SET other_col = 5; +ERROR: syntax error at or near "ON" +LINE 1: ...O upsert_test (part_key, other_col) VALUES (1, 1) ON CONFLIC... + ^ +-- error out on attempt to update the partition key +INSERT INTO upsert_test (part_key, other_col) VALUES (1, 1) ON CONFLICT (part_key) DO + UPDATE SET part_key = 15; +ERROR: syntax error at or near "ON" +LINE 1: ...O upsert_test (part_key, other_col) VALUES (1, 1) ON CONFLIC... + ^ diff --git a/src/test/regress/expected/multi_utilities.out b/src/test/regress/expected/multi_utilities.out new file mode 100644 index 000000000..46d2213eb --- /dev/null +++ b/src/test/regress/expected/multi_utilities.out @@ -0,0 +1,84 @@ +-- =================================================================== +-- test utility statement functionality +-- =================================================================== +CREATE TABLE sharded_table ( name text, id bigint ); +SELECT master_create_distributed_table('sharded_table', 'id', 'hash'); + master_create_distributed_table +--------------------------------- + +(1 row) + +SELECT master_create_worker_shards('sharded_table', 2, 1); + master_create_worker_shards +----------------------------- + +(1 row) + +-- COPY out is supported with distributed tables +COPY sharded_table TO STDOUT; +COPY (SELECT COUNT(*) FROM sharded_table) TO STDOUT; +0 +-- but COPY in is not +COPY sharded_table FROM STDIN; +ERROR: cannot execute COPY FROM on a distributed table on master node +-- cursors may not involve distributed tables +DECLARE all_sharded_rows CURSOR FOR SELECT * FROM sharded_table; +ERROR: DECLARE CURSOR can only be used in transaction blocks +-- EXPLAIN support isn't implemented for distributed queries... +EXPLAIN SELECT * FROM sharded_table; + QUERY PLAN +---------------------------------------------------------------------- + explain statements for distributed queries are currently unsupported +(1 row) + +-- ... or for distributed modifications +EXPLAIN INSERT INTO sharded_table VALUES ('dan', 4); +ERROR: cannot show execution plan for distributed modification +DETAIL: EXPLAIN commands are unsupported for distributed modifications. +-- verify PREPARE functionality +PREPARE sharded_insert AS INSERT INTO sharded_table VALUES ('adam', 1); +PREPARE sharded_update AS UPDATE sharded_table SET name = 'bob' WHERE id = 1; +PREPARE sharded_delete AS DELETE FROM sharded_table WHERE id = 1; +PREPARE sharded_query AS SELECT name FROM sharded_table WHERE id = 1; +EXECUTE sharded_query; + name +------ +(0 rows) + +EXECUTE sharded_insert; +EXECUTE sharded_query; + name +------ + adam +(1 row) + +EXECUTE sharded_update; +EXECUTE sharded_query; + name +------ + bob +(1 row) + +EXECUTE sharded_delete; +EXECUTE sharded_query; + name +------ +(0 rows) + +-- try to drop table +DROP TABLE sharded_table; +ERROR: cannot drop distributed table with existing shards +HINT: Delete shards first using: SELECT master_apply_delete_command('DELETE FROM public.sharded_table') +-- try to drop shards with where clause +SELECT master_apply_delete_command('DELETE FROM sharded_table WHERE id > 0'); +ERROR: cannot delete from distributed table +DETAIL: Delete statements on hash-partitioned tables with where clause is not supported +-- drop all shards +SELECT master_apply_delete_command('DELETE FROM sharded_table'); + master_apply_delete_command +----------------------------- + 2 +(1 row) + +-- drop table +DROP TABLE sharded_table; diff --git a/src/test/regress/expected/multi_utility_statements.out b/src/test/regress/expected/multi_utility_statements.out new file mode 100644 index 000000000..04317ce81 --- /dev/null +++ b/src/test/regress/expected/multi_utility_statements.out @@ -0,0 +1,267 @@ +-- +-- MULTI_UTILITY_STATEMENTS +-- +-- Check that we can run utility statements with embedded SELECT statements on +-- distributed tables. Currently we only support CREATE TABLE AS (SELECT..), +-- DECLARE CURSOR, and COPY ... TO statements. +CREATE TEMP TABLE lineitem_pricing_summary AS +( + SELECT + l_returnflag, + l_linestatus, + sum(l_quantity) as sum_qty, + sum(l_extendedprice) as sum_base_price, + sum(l_extendedprice * (1 - l_discount)) as sum_disc_price, + sum(l_extendedprice * (1 - l_discount) * (1 + l_tax)) as sum_charge, + avg(l_quantity) as avg_qty, + avg(l_extendedprice) as avg_price, + avg(l_discount) as avg_disc, + count(*) as count_order + FROM + lineitem + WHERE + l_shipdate <= date '1998-12-01' - interval '90 days' + GROUP BY + l_returnflag, + l_linestatus + ORDER BY + l_returnflag, + l_linestatus +); +SELECT * FROM lineitem_pricing_summary ORDER BY l_returnflag, l_linestatus; + l_returnflag | l_linestatus | sum_qty | sum_base_price | sum_disc_price | sum_charge | avg_qty | avg_price | avg_disc | count_order +--------------+--------------+-----------+----------------+----------------+------------------+---------------------+--------------------+------------------------+------------- + A | F | 75465.00 | 113619873.63 | 107841287.0728 | 112171153.245923 | 25.6334918478260870 | 38593.707075407609 | 0.05055027173913043478 | 2944 + N | F | 2022.00 | 3102551.45 | 2952540.7118 | 3072642.770652 | 26.6052631578947368 | 40823.045394736842 | 0.05263157894736842105 | 76 + N | O | 149778.00 | 224706948.16 | 213634857.6854 | 222134071.929801 | 25.4594594594594595 | 38195.979629440762 | 0.04939486656467788543 | 5883 + R | F | 73156.00 | 108937979.73 | 103516623.6698 | 107743533.784328 | 25.2175112030334367 | 37551.871675284385 | 0.04983798690106859704 | 2901 +(4 rows) + +-- Test we can handle joins +SET citusdb.large_table_shard_count TO 2; +CREATE TABLE shipping_priority AS +( + SELECT + l_orderkey, + sum(l_extendedprice * (1 - l_discount)) as revenue, + o_orderdate, + o_shippriority + FROM + customer, + orders, + lineitem + WHERE + c_mktsegment = 'BUILDING' + AND c_custkey = o_custkey + AND l_orderkey = o_orderkey + AND o_orderdate < date '1995-03-15' + AND l_shipdate > date '1995-03-15' + GROUP BY + l_orderkey, + o_orderdate, + o_shippriority + ORDER BY + revenue DESC, + o_orderdate +); +SELECT * FROM shipping_priority; + l_orderkey | revenue | o_orderdate | o_shippriority +------------+-------------+-------------+---------------- + 1637 | 268170.6408 | 02-08-1995 | 0 + 9696 | 252014.5497 | 02-20-1995 | 0 + 10916 | 242749.1996 | 03-11-1995 | 0 + 450 | 221012.3165 | 03-05-1995 | 0 + 5347 | 198353.7942 | 02-22-1995 | 0 + 10691 | 112800.1020 | 03-14-1995 | 0 + 386 | 104975.2484 | 01-25-1995 | 0 + 5765 | 88222.7556 | 12-15-1994 | 0 + 4707 | 88143.7774 | 02-27-1995 | 0 + 5312 | 83750.7028 | 02-24-1995 | 0 + 5728 | 70101.6400 | 12-11-1994 | 0 + 577 | 57986.6224 | 12-19-1994 | 0 + 12706 | 16636.6368 | 11-21-1994 | 0 + 3844 | 8851.3200 | 12-29-1994 | 0 + 11073 | 7433.6295 | 12-02-1994 | 0 + 13924 | 3111.4970 | 12-20-1994 | 0 +(16 rows) + +DROP TABLE shipping_priority; +-- Check COPY against distributed tables works both when specifying a +-- query as the source, and when directly naming a table. +COPY ( + SELECT + l_orderkey, + sum(l_extendedprice * (1 - l_discount)) as revenue, + o_orderdate, + o_shippriority + FROM + customer, + orders, + lineitem + WHERE + c_mktsegment = 'BUILDING' + AND c_custkey = o_custkey + AND l_orderkey = o_orderkey + AND o_orderdate < date '1995-03-15' + AND l_shipdate > date '1995-03-15' + GROUP BY + l_orderkey, + o_orderdate, + o_shippriority + ORDER BY + revenue DESC, + o_orderdate +) TO stdout; +1637 268170.6408 02-08-1995 0 +9696 252014.5497 02-20-1995 0 +10916 242749.1996 03-11-1995 0 +450 221012.3165 03-05-1995 0 +5347 198353.7942 02-22-1995 0 +10691 112800.1020 03-14-1995 0 +386 104975.2484 01-25-1995 0 +5765 88222.7556 12-15-1994 0 +4707 88143.7774 02-27-1995 0 +5312 83750.7028 02-24-1995 0 +5728 70101.6400 12-11-1994 0 +577 57986.6224 12-19-1994 0 +12706 16636.6368 11-21-1994 0 +3844 8851.3200 12-29-1994 0 +11073 7433.6295 12-02-1994 0 +13924 3111.4970 12-20-1994 0 +-- check copying to file +-- (quiet off to force number of copied records to be displayed) +\set QUIET off +COPY nation TO '/dev/null'; +COPY 25 +\set QUIET on +-- stdout +COPY nation TO STDOUT; +0 ALGERIA 0 haggle. carefully final deposits detect slyly agai +1 ARGENTINA 1 al foxes promise slyly according to the regular accounts. bold requests alon +2 BRAZIL 1 y alongside of the pending deposits. carefully special packages are about the ironic forges. slyly special +3 CANADA 1 eas hang ironic, silent packages. slyly regular packages are furiously over the tithes. fluffily bold +4 EGYPT 4 y above the carefully unusual theodolites. final dugouts are quickly across the furiously regular d +5 ETHIOPIA 0 ven packages wake quickly. regu +6 FRANCE 3 refully final requests. regular, ironi +7 GERMANY 3 l platelets. regular accounts x-ray: unusual, regular acco +8 INDIA 2 ss excuses cajole slyly across the packages. deposits print aroun +9 INDONESIA 2 slyly express asymptotes. regular deposits haggle slyly. carefully ironic hockey players sleep blithely. carefull +10 IRAN 4 efully alongside of the slyly final dependencies. +11 IRAQ 4 nic deposits boost atop the quickly final requests? quickly regula +12 JAPAN 2 ously. final, express gifts cajole a +13 JORDAN 4 ic deposits are blithely about the carefully regular pa +14 KENYA 0 pending excuses haggle furiously deposits. pending, express pinto beans wake fluffily past t +15 MOROCCO 0 rns. blithely bold courts among the closely regular packages use furiously bold platelets? +16 MOZAMBIQUE 0 s. ironic, unusual asymptotes wake blithely r +17 PERU 1 platelets. blithely pending dependencies use fluffily across the even pinto beans. carefully silent accoun +18 CHINA 2 c dependencies. furiously express notornis sleep slyly regular accounts. ideas sleep. depos +19 ROMANIA 3 ular asymptotes are about the furious multipliers. express dependencies nag above the ironically ironic account +20 SAUDI ARABIA 4 ts. silent requests haggle. closely express packages sleep across the blithely +21 VIETNAM 2 hely enticingly express accounts. even, final +22 RUSSIA 3 requests against the platelets use never according to the quickly regular pint +23 UNITED KINGDOM 3 eans boost carefully special requests. accounts are. carefull +24 UNITED STATES 1 y final packages. slow foxes cajole quickly. quickly silent platelets breach ironic accounts. unusual pinto be +-- ensure individual cols can be copied out, too +COPY nation(n_name) TO STDOUT; +ALGERIA +ARGENTINA +BRAZIL +CANADA +EGYPT +ETHIOPIA +FRANCE +GERMANY +INDIA +INDONESIA +IRAN +IRAQ +JAPAN +JORDAN +KENYA +MOROCCO +MOZAMBIQUE +PERU +CHINA +ROMANIA +SAUDI ARABIA +VIETNAM +RUSSIA +UNITED KINGDOM +UNITED STATES +-- Ensure that preventing COPY FROM against distributed tables works +COPY customer FROM STDIN; +ERROR: cannot execute COPY FROM on a distributed table on master node +-- Test that we can create on-commit drop tables, and also test creating with +-- oids, along with changing column names +BEGIN; +CREATE TEMP TABLE customer_few (customer_key) WITH (OIDS) ON COMMIT DROP AS + (SELECT * FROM customer WHERE c_nationkey = 1 ORDER BY c_custkey LIMIT 10); +SELECT customer_key, c_name, c_address + FROM customer_few ORDER BY customer_key LIMIT 5; + customer_key | c_name | c_address +--------------+--------------------+----------------------------------------- + 3 | Customer#000000003 | MG9kdTD2WBHm + 14 | Customer#000000014 | KXkletMlL2JQEA + 30 | Customer#000000030 | nJDsELGAavU63Jl0c5NKsKfL8rIJQQkQnYL2QJY + 59 | Customer#000000059 | zLOCP0wh92OtBihgspOGl4 + 106 | Customer#000000106 | xGCOEAUjUNG +(5 rows) + +COMMIT; +SELECT customer_key, c_name, c_address + FROM customer_few ORDER BY customer_key LIMIT 5; +ERROR: relation "customer_few" does not exist +LINE 2: FROM customer_few ORDER BY customer_key LIMIT 5; + ^ +-- Test DECLARE CURSOR statements +DECLARE holdCursor SCROLL CURSOR WITH HOLD FOR + SELECT l_orderkey, l_linenumber, l_quantity, l_discount + FROM lineitem + ORDER BY l_orderkey, l_linenumber; +FETCH NEXT FROM holdCursor; + l_orderkey | l_linenumber | l_quantity | l_discount +------------+--------------+------------+------------ + 1 | 1 | 17.00 | 0.04 +(1 row) + +FETCH FORWARD 5 FROM holdCursor; + l_orderkey | l_linenumber | l_quantity | l_discount +------------+--------------+------------+------------ + 1 | 2 | 36.00 | 0.09 + 1 | 3 | 8.00 | 0.10 + 1 | 4 | 28.00 | 0.09 + 1 | 5 | 24.00 | 0.10 + 1 | 6 | 32.00 | 0.07 +(5 rows) + +FETCH LAST FROM holdCursor; + l_orderkey | l_linenumber | l_quantity | l_discount +------------+--------------+------------+------------ + 14947 | 2 | 29.00 | 0.04 +(1 row) + +FETCH BACKWARD 5 FROM holdCursor; + l_orderkey | l_linenumber | l_quantity | l_discount +------------+--------------+------------+------------ + 14947 | 1 | 14.00 | 0.09 + 14946 | 2 | 37.00 | 0.01 + 14946 | 1 | 38.00 | 0.00 + 14945 | 6 | 37.00 | 0.05 + 14945 | 5 | 44.00 | 0.08 +(5 rows) + +-- Test WITHOUT HOLD cursors inside transactions +BEGIN; +DECLARE noHoldCursor SCROLL CURSOR FOR + SELECT l_orderkey, l_linenumber, l_quantity, l_discount + FROM lineitem + ORDER BY l_orderkey, l_linenumber; +FETCH ABSOLUTE 5 FROM noHoldCursor; + l_orderkey | l_linenumber | l_quantity | l_discount +------------+--------------+------------+------------ + 1 | 5 | 24.00 | 0.10 +(1 row) + +COMMIT; +FETCH ABSOLUTE 5 FROM noHoldCursor; +ERROR: cursor "noholdcursor" does not exist diff --git a/src/test/regress/expected/multi_utility_warnings.out b/src/test/regress/expected/multi_utility_warnings.out new file mode 100644 index 000000000..6b564d473 --- /dev/null +++ b/src/test/regress/expected/multi_utility_warnings.out @@ -0,0 +1,18 @@ +-- +-- MULTI_UTILITY_WARNINGS +-- +-- Tests to check if we inform the user about potential caveats of creating new +-- databases, schemas, and roles. +CREATE DATABASE new_database; +NOTICE: CitusDB partially supports CREATE DATABASE for distributed databases +DETAIL: CitusDB does not propagate CREATE DATABASE command to workers +HINT: You can manually create a database and its extensions on workers. +CREATE SCHEMA new_schema; +NOTICE: CitusDB partially supports CREATE SCHEMA for distributed databases +DETAIL: schema usage in joins and in some UDFs provided by CitusDB are not supported yet +CREATE ROLE new_role; +NOTICE: CitusDB does not support CREATE ROLE/USER for distributed databases +DETAIL: Multiple roles are currently supported only for local tables +CREATE USER new_user; +NOTICE: CitusDB does not support CREATE ROLE/USER for distributed databases +DETAIL: Multiple roles are currently supported only for local tables diff --git a/src/test/regress/expected/multi_verify_no_join_with_alias.out b/src/test/regress/expected/multi_verify_no_join_with_alias.out new file mode 100644 index 000000000..8d33250cd --- /dev/null +++ b/src/test/regress/expected/multi_verify_no_join_with_alias.out @@ -0,0 +1,20 @@ +-- +-- MULTI_VERIFY_NO_JOIN_WITH_ALIAS +-- +-- This test checks that we simply emit an error message instead of trying to +-- fetch and join a shard which has an alias set. +-- Show that the join works without an alias +SELECT COUNT(*) FROM lineitem, part WHERE l_partkey = p_partkey; + count +------- + 61 +(1 row) + +-- Assign an alias to the parts shard +UPDATE pg_dist_shard SET shardalias = 'my_alias' WHERE shardid = 102019; +-- Attempt a join which uses this shard +SELECT COUNT(*) FROM lineitem, part WHERE l_partkey = p_partkey; +ERROR: cannot fetch shard 102019 +DETAIL: Fetching shards with aliases is currently unsupported +-- Remove the alias from the parts shard +UPDATE pg_dist_shard SET shardalias = NULL WHERE shardid = 102019; diff --git a/src/test/regress/expected/multi_verify_no_subquery.out b/src/test/regress/expected/multi_verify_no_subquery.out new file mode 100644 index 000000000..db1501098 --- /dev/null +++ b/src/test/regress/expected/multi_verify_no_subquery.out @@ -0,0 +1,22 @@ +-- +-- MULTI_VERIFY_NO_SUBQUERY +-- +-- This test checks that we simply emit an error message instead of trying to +-- process a distributed unsupported SQL subquery. +SELECT * FROM lineitem WHERE l_orderkey IN + (SELECT l_orderkey FROM lineitem WHERE l_quantity > 0); +ERROR: cannot perform distributed planning on this query +DETAIL: Join types other than inner/outer joins are currently unsupported +SELECT l_quantity FROM lineitem WHERE EXISTS + (SELECT 1 FROM orders WHERE o_orderkey = l_orderkey); +ERROR: cannot perform distributed planning on this query +DETAIL: Join types other than inner/outer joins are currently unsupported +SELECT l_quantity FROM lineitem WHERE l_orderkey IN (SELECT o_orderkey FROM orders); +ERROR: cannot perform distributed planning on this query +DETAIL: Join types other than inner/outer joins are currently unsupported +SELECT l_orderkey FROM lineitem WHERE l_quantity > ALL(SELECT o_orderkey FROM orders); +ERROR: cannot perform distributed planning on this query +DETAIL: Subqueries other than in from-clause are currently unsupported +SELECT l_quantity FROM lineitem WHERE l_orderkey = (SELECT min(o_orderkey) FROM orders); +ERROR: cannot perform distributed planning on this query +DETAIL: Subqueries other than in from-clause are currently unsupported diff --git a/src/test/regress/expected/multi_working_columns.out b/src/test/regress/expected/multi_working_columns.out new file mode 100644 index 000000000..38c05af49 --- /dev/null +++ b/src/test/regress/expected/multi_working_columns.out @@ -0,0 +1,86 @@ +-- +-- MULTI_WORKING_COLUMNS +-- +-- Columns that are used in sorting and grouping but that do not appear in the +-- projection order are called working (resjunk) columns. We check in here that +-- these columns are pulled to the master, and are correctly used in sorting and +-- grouping. +SELECT l_quantity FROM lineitem ORDER BY l_shipdate, l_quantity LIMIT 20; + l_quantity +------------ + 38.00 + 13.00 + 15.00 + 17.00 + 30.00 + 24.00 + 24.00 + 5.00 + 38.00 + 13.00 + 26.00 + 30.00 + 30.00 + 35.00 + 38.00 + 24.00 + 37.00 + 11.00 + 18.00 + 17.00 +(20 rows) + +SELECT l_quantity, count(*) as count FROM lineitem + GROUP BY l_quantity, l_shipdate ORDER BY l_quantity, count + LIMIT 20; + l_quantity | count +------------+------- + 1.00 | 1 + 1.00 | 1 + 1.00 | 1 + 1.00 | 1 + 1.00 | 1 + 1.00 | 1 + 1.00 | 1 + 1.00 | 1 + 1.00 | 1 + 1.00 | 1 + 1.00 | 1 + 1.00 | 1 + 1.00 | 1 + 1.00 | 1 + 1.00 | 1 + 1.00 | 1 + 1.00 | 1 + 1.00 | 1 + 1.00 | 1 + 1.00 | 1 +(20 rows) + +SELECT l_quantity, l_shipdate, count(*) as count FROM lineitem + GROUP BY l_quantity, l_shipdate ORDER BY l_quantity, count, l_shipdate + LIMIT 20; + l_quantity | l_shipdate | count +------------+------------+------- + 1.00 | 02-07-1992 | 1 + 1.00 | 02-23-1992 | 1 + 1.00 | 03-17-1992 | 1 + 1.00 | 04-22-1992 | 1 + 1.00 | 04-23-1992 | 1 + 1.00 | 04-30-1992 | 1 + 1.00 | 05-13-1992 | 1 + 1.00 | 05-15-1992 | 1 + 1.00 | 05-27-1992 | 1 + 1.00 | 05-29-1992 | 1 + 1.00 | 06-09-1992 | 1 + 1.00 | 06-23-1992 | 1 + 1.00 | 07-15-1992 | 1 + 1.00 | 07-18-1992 | 1 + 1.00 | 07-23-1992 | 1 + 1.00 | 08-03-1992 | 1 + 1.00 | 08-11-1992 | 1 + 1.00 | 08-29-1992 | 1 + 1.00 | 09-08-1992 | 1 + 1.00 | 09-11-1992 | 1 +(20 rows) + diff --git a/src/test/regress/expected/task_tracker_assign_task.out b/src/test/regress/expected/task_tracker_assign_task.out new file mode 100644 index 000000000..d9dff929b --- /dev/null +++ b/src/test/regress/expected/task_tracker_assign_task.out @@ -0,0 +1,89 @@ +-- +-- TASK_TRACKER_ASSIGN_TASK +-- +\set JobId 401010 +\set SimpleTaskId 101101 +\set RecoverableTaskId 801102 +\set SimpleTaskTable lineitem_simple_task +\set BadQueryString '\'SELECT COUNT(*) FROM bad_table_name\'' +\set GoodQueryString '\'SELECT COUNT(*) FROM lineitem\'' +\set SelectAll 'SELECT *' +-- We assign two tasks to the task tracker. The first task simply executes. The +-- recoverable task on the other hand repeatedly fails, and we sleep until the +-- task tracker stops retrying the recoverable task. +SELECT task_tracker_assign_task(:JobId, :SimpleTaskId, + 'COPY (SELECT * FROM lineitem) TO ' + '''base/pgsql_job_cache/job_401010/task_101101'''); + task_tracker_assign_task +-------------------------- + +(1 row) + +SELECT task_tracker_assign_task(:JobId, :RecoverableTaskId, :BadQueryString); + task_tracker_assign_task +-------------------------- + +(1 row) + +-- After assigning the two tasks, we wait for them to make progress. Note that +-- these tasks get scheduled and run asynchronously, so if the sleep interval is +-- not enough, the regression tests may fail on an overloaded box. +SELECT pg_sleep(3.0); + pg_sleep +---------- + +(1 row) + +SELECT task_tracker_task_status(:JobId, :SimpleTaskId); + task_tracker_task_status +-------------------------- + 6 +(1 row) + +SELECT task_tracker_task_status(:JobId, :RecoverableTaskId); + task_tracker_task_status +-------------------------- + 5 +(1 row) + +COPY :SimpleTaskTable FROM 'base/pgsql_job_cache/job_401010/task_101101'; +SELECT COUNT(*) FROM :SimpleTaskTable; + count +------- + 12000 +(1 row) + +SELECT COUNT(*) AS diff_lhs FROM ( :SelectAll FROM :SimpleTaskTable EXCEPT ALL + :SelectAll FROM lineitem ) diff; + diff_lhs +---------- + 0 +(1 row) + +SELECT COUNT(*) As diff_rhs FROM ( :SelectAll FROM lineitem EXCEPT ALL + :SelectAll FROM :SimpleTaskTable ) diff; + diff_rhs +---------- + 0 +(1 row) + +-- We now reassign the recoverable task with a good query string. This updates +-- the task's query string, and reschedules the updated task for execution. +SELECT task_tracker_assign_task(:JobId, :RecoverableTaskId, :GoodQueryString); + task_tracker_assign_task +-------------------------- + +(1 row) + +SELECT pg_sleep(2.0); + pg_sleep +---------- + +(1 row) + +SELECT task_tracker_task_status(:JobId, :RecoverableTaskId); + task_tracker_task_status +-------------------------- + 6 +(1 row) + diff --git a/src/test/regress/expected/task_tracker_cleanup_job.out b/src/test/regress/expected/task_tracker_cleanup_job.out new file mode 100644 index 000000000..e1e63fbde --- /dev/null +++ b/src/test/regress/expected/task_tracker_cleanup_job.out @@ -0,0 +1,77 @@ +-- +-- TASK_TRACKER_CLEANUP_JOB +-- +\set JobId 401010 +\set CompletedTaskId 801107 +\set RunningTaskId 801108 +-- We assign two tasks to the task tracker. The first task should complete and +-- the second task should continue to keep running. +SELECT task_tracker_assign_task(:JobId, :CompletedTaskId, + 'COPY (SELECT * FROM lineitem) TO ' + '''base/pgsql_job_cache/job_401010/task_801107'''); + task_tracker_assign_task +-------------------------- + +(1 row) + +SELECT task_tracker_assign_task(:JobId, :RunningTaskId, + 'SELECT pg_sleep(100)'); + task_tracker_assign_task +-------------------------- + +(1 row) + +SELECT pg_sleep(2.0); + pg_sleep +---------- + +(1 row) + +SELECT task_tracker_task_status(:JobId, :CompletedTaskId); + task_tracker_task_status +-------------------------- + 6 +(1 row) + +SELECT task_tracker_task_status(:JobId, :RunningTaskId); + task_tracker_task_status +-------------------------- + 3 +(1 row) + +SELECT isdir FROM pg_stat_file('base/pgsql_job_cache/job_401010/task_801107'); + isdir +------- + f +(1 row) + +SELECT isdir FROM pg_stat_file('base/pgsql_job_cache/job_401010'); + isdir +------- + t +(1 row) + +-- We now clean up all tasks for this job id. As a result, shared hash entries, +-- files, and connections associated with these tasks should all be cleaned up. +SELECT task_tracker_cleanup_job(:JobId); + task_tracker_cleanup_job +-------------------------- + +(1 row) + +SELECT pg_sleep(1.0); + pg_sleep +---------- + +(1 row) + +SELECT task_tracker_task_status(:JobId, :CompletedTaskId); +ERROR: could not find the worker task +DETAIL: Task jobId: 401010 and taskId: 801107 +SELECT task_tracker_task_status(:JobId, :RunningTaskId); +ERROR: could not find the worker task +DETAIL: Task jobId: 401010 and taskId: 801108 +SELECT isdir FROM pg_stat_file('base/pgsql_job_cache/job_401010/task_801107'); +ERROR: could not stat file "base/pgsql_job_cache/job_401010/task_801107": No such file or directory +SELECT isdir FROM pg_stat_file('base/pgsql_job_cache/job_401010'); +ERROR: could not stat file "base/pgsql_job_cache/job_401010": No such file or directory diff --git a/src/test/regress/expected/task_tracker_create_table.out b/src/test/regress/expected/task_tracker_create_table.out new file mode 100644 index 000000000..30d45728c --- /dev/null +++ b/src/test/regress/expected/task_tracker_create_table.out @@ -0,0 +1,10 @@ +-- +-- TASK_TRACKER_CREATE_TABLE +-- +-- New table definitions to test the task tracker process and protocol +CREATE TABLE lineitem_simple_task ( LIKE lineitem ); +CREATE TABLE lineitem_compute_task ( LIKE lineitem ); +CREATE TABLE lineitem_compute_update_task ( LIKE lineitem ); +CREATE TABLE lineitem_partition_task_part_00 ( LIKE lineitem ); +CREATE TABLE lineitem_partition_task_part_01 ( LIKE lineitem ); +CREATE TABLE lineitem_partition_task_part_02 ( LIKE lineitem ); diff --git a/src/test/regress/expected/task_tracker_partition_task.out b/src/test/regress/expected/task_tracker_partition_task.out new file mode 100644 index 000000000..2d36f93b0 --- /dev/null +++ b/src/test/regress/expected/task_tracker_partition_task.out @@ -0,0 +1,103 @@ +-- +-- TASK_TRACKER_PARTITION_TASK +-- +\set JobId 401010 +\set PartitionTaskId 801106 +\set PartitionColumn l_orderkey +\set SelectAll 'SELECT *' +\set TablePart00 lineitem_partition_task_part_00 +\set TablePart01 lineitem_partition_task_part_01 +\set TablePart02 lineitem_partition_task_part_02 +-- We assign a partition task and wait for it to complete. Note that we hardcode +-- the partition function call string, including the job and task identifiers, +-- into the argument in the task assignment function. This hardcoding is +-- necessary as the current psql version does not perform variable interpolation +-- for names inside single quotes. +SELECT task_tracker_assign_task(:JobId, :PartitionTaskId, + 'SELECT worker_range_partition_table(' + '401010, 801106, ''SELECT * FROM lineitem'', ' + '''l_orderkey'', 20, ARRAY[1000, 3000]::_int8)'); + task_tracker_assign_task +-------------------------- + +(1 row) + +SELECT pg_sleep(4.0); + pg_sleep +---------- + +(1 row) + +SELECT task_tracker_task_status(:JobId, :PartitionTaskId); + task_tracker_task_status +-------------------------- + 6 +(1 row) + +COPY :TablePart00 FROM 'base/pgsql_job_cache/job_401010/task_801106/p_00000'; +COPY :TablePart01 FROM 'base/pgsql_job_cache/job_401010/task_801106/p_00001'; +COPY :TablePart02 FROM 'base/pgsql_job_cache/job_401010/task_801106/p_00002'; +SELECT COUNT(*) FROM :TablePart00; + count +------- + 1004 +(1 row) + +SELECT COUNT(*) FROM :TablePart02; + count +------- + 8970 +(1 row) + +-- We first compute the difference of partition tables against the base table. +-- Then, we compute the difference of the base table against partitioned tables. +SELECT COUNT(*) AS diff_lhs_00 FROM ( + :SelectAll FROM :TablePart00 EXCEPT ALL + :SelectAll FROM lineitem WHERE :PartitionColumn < 1000 ) diff; + diff_lhs_00 +------------- + 0 +(1 row) + +SELECT COUNT(*) AS diff_lhs_01 FROM ( + :SelectAll FROM :TablePart01 EXCEPT ALL + :SelectAll FROM lineitem WHERE :PartitionColumn >= 1000 AND + :PartitionColumn < 3000 ) diff; + diff_lhs_01 +------------- + 0 +(1 row) + +SELECT COUNT(*) AS diff_lhs_02 FROM ( + :SelectAll FROM :TablePart02 EXCEPT ALL + :SelectAll FROM lineitem WHERE :PartitionColumn >= 3000 ) diff; + diff_lhs_02 +------------- + 0 +(1 row) + +SELECT COUNT(*) AS diff_rhs_00 FROM ( + :SelectAll FROM lineitem WHERE :PartitionColumn < 1000 EXCEPT ALL + :SelectAll FROM :TablePart00 ) diff; + diff_rhs_00 +------------- + 0 +(1 row) + +SELECT COUNT(*) AS diff_rhs_01 FROM ( + :SelectAll FROM lineitem WHERE :PartitionColumn >= 1000 AND + :PartitionColumn < 3000 EXCEPT ALL + :SelectAll FROM :TablePart01 ) diff; + diff_rhs_01 +------------- + 0 +(1 row) + +SELECT COUNT(*) AS diff_rhs_02 FROM ( + :SelectAll FROM lineitem WHERE :PartitionColumn >= 3000 EXCEPT ALL + :SelectAll FROM :TablePart02 ) diff; + diff_rhs_02 +------------- + 0 +(1 row) + diff --git a/src/test/regress/expected/worker_binary_data_partition.out b/src/test/regress/expected/worker_binary_data_partition.out new file mode 100644 index 000000000..afab11021 --- /dev/null +++ b/src/test/regress/expected/worker_binary_data_partition.out @@ -0,0 +1,116 @@ +-- +-- WORKER_BINARY_DATA_PARTITION +-- +\set JobId 201010 +\set TaskId 101105 +\set Partition_Column textcolumn +\set Partition_Column_Text '\'textcolumn\'' +\set Partition_Column_Type 25 +\set Select_Query_Text '\'SELECT * FROM binary_data_table\'' +\set Select_All 'SELECT *' +\set Table_Name binary_data_table +\set Table_Part_00 binary_data_table_part_00 +\set Table_Part_01 binary_data_table_part_01 +\set Table_Part_02 binary_data_table_part_02 +-- Create table with special characters +CREATE TABLE :Table_Name(textcolumn text, binarycolumn bytea); +COPY :Table_Name FROM stdin; +SELECT length(binarycolumn) FROM :Table_Name; + length +-------- + 2 + 4 + 3 + 2 + 4 + 14 + 28 + 16 + 9 + 11 + 11 + 24 + 17 + 12 +(14 rows) + +-- Run select query, and apply range partitioning on query results +SELECT worker_range_partition_table(:JobId, :TaskId, :Select_Query_Text, + :Partition_Column_Text, :Partition_Column_Type, + ARRAY['aaa', 'some']::_text); + worker_range_partition_table +------------------------------ + +(1 row) + +-- Copy range partitioned files into tables +CREATE TABLE :Table_Part_00 ( LIKE :Table_Name ); +CREATE TABLE :Table_Part_01 ( LIKE :Table_Name ); +CREATE TABLE :Table_Part_02 ( LIKE :Table_Name ); +COPY :Table_Part_00 FROM 'base/pgsql_job_cache/job_201010/task_101105/p_00000'; +COPY :Table_Part_01 FROM 'base/pgsql_job_cache/job_201010/task_101105/p_00001'; +COPY :Table_Part_02 FROM 'base/pgsql_job_cache/job_201010/task_101105/p_00002'; +-- The union of the three partitions should have as many rows as original table +SELECT COUNT(*) AS total_row_count FROM ( + SELECT * FROM :Table_Part_00 UNION ALL + SELECT * FROM :Table_Part_01 UNION ALL + SELECT * FROM :Table_Part_02 ) AS all_rows; + total_row_count +----------------- + 14 +(1 row) + +-- We first compute the difference of partition tables against the base table. +-- Then, we compute the difference of the base table against partitioned tables. +SELECT COUNT(*) AS diff_lhs_00 FROM ( + :Select_All FROM :Table_Part_00 EXCEPT ALL + :Select_All FROM :Table_Name WHERE :Partition_Column IS NULL OR + :Partition_Column < 'aaa' ) diff; + diff_lhs_00 +------------- + 0 +(1 row) + +SELECT COUNT(*) AS diff_lhs_01 FROM ( + :Select_All FROM :Table_Part_01 EXCEPT ALL + :Select_All FROM :Table_Name WHERE :Partition_Column >= 'aaa' AND + :Partition_Column < 'some' ) diff; + diff_lhs_01 +------------- + 0 +(1 row) + +SELECT COUNT(*) AS diff_lhs_02 FROM ( + :Select_All FROM :Table_Part_02 EXCEPT ALL + :Select_All FROM :Table_Name WHERE :Partition_Column >= 'some' ) diff; + diff_lhs_02 +------------- + 0 +(1 row) + +SELECT COUNT(*) AS diff_rhs_00 FROM ( + :Select_All FROM :Table_Name WHERE :Partition_Column IS NULL OR + :Partition_Column < 'aaa' EXCEPT ALL + :Select_All FROM :Table_Part_00 ) diff; + diff_rhs_00 +------------- + 0 +(1 row) + +SELECT COUNT(*) AS diff_rhs_01 FROM ( + :Select_All FROM :Table_Name WHERE :Partition_Column >= 'aaa' AND + :Partition_Column < 'some' EXCEPT ALL + :Select_All FROM :Table_Part_01 ) diff; + diff_rhs_01 +------------- + 0 +(1 row) + +SELECT COUNT(*) AS diff_rhs_02 FROM ( + :Select_All FROM :Table_Name WHERE :Partition_Column >= 'some' EXCEPT ALL + :Select_All FROM :Table_Part_02 ) diff; + diff_rhs_02 +------------- + 0 +(1 row) + diff --git a/src/test/regress/expected/worker_check_invalid_arguments.out b/src/test/regress/expected/worker_check_invalid_arguments.out new file mode 100644 index 000000000..1ecefdcb5 --- /dev/null +++ b/src/test/regress/expected/worker_check_invalid_arguments.out @@ -0,0 +1,79 @@ +-- +-- WORKER_CHECK_INVALID_ARGUMENTS +-- +\set JobId 201010 +\set TaskId 101108 +\set Table_Name simple_binary_data_table +\set Partition_Column_Name '\'textcolumn\'' +\set Partition_Column_Type 25 +\set Partition_Count 2 +\set Select_Query_Text '\'SELECT * FROM simple_binary_data_table\'' +\set Bad_Partition_Column_Name '\'badcolumnname\'' +\set Bad_Partition_Column_Type 20 +\set Bad_Select_Query_Text '\'SELECT * FROM bad_table_name\'' +-- Create simple table and insert a few rows into this table +-- N.B. - These rows will be partitioned to files on disk then read back in the +-- order the files are listed by a call to readdir; because this order is not +-- predictable, the second column of these rows always has the same value, to +-- avoid an error message differing based on file read order. +CREATE TABLE :Table_Name(textcolumn text, binarycolumn bytea); +COPY :Table_Name FROM stdin; +SELECT COUNT(*) FROM :Table_Name; + count +------- + 2 +(1 row) + +-- Check that we fail with bad SQL query +SELECT worker_range_partition_table(:JobId, :TaskId, :Bad_Select_Query_Text, + :Partition_Column_Name, :Partition_Column_Type, + ARRAY['aaa', 'some']::_text); +ERROR: relation "bad_table_name" does not exist +LINE 1: SELECT * FROM bad_table_name + ^ +QUERY: SELECT * FROM bad_table_name +-- Check that we fail with bad partition column name +SELECT worker_range_partition_table(:JobId, :TaskId, :Select_Query_Text, + :Bad_Partition_Column_Name, :Partition_Column_Type, + ARRAY['aaa', 'some']::_text); +ERROR: could not find column name "badcolumnname" +-- Check that we fail when partition column and split point types do not match +SELECT worker_range_partition_table(:JobId, :TaskId, :Select_Query_Text, + :Partition_Column_Name, :Bad_Partition_Column_Type, + ARRAY['aaa', 'some']::_text); +ERROR: partition column type 20 and split point type 25 do not match +-- Check that we fail with bad partition column type on hash partitioning +SELECT worker_hash_partition_table(:JobId, :TaskId, :Select_Query_Text, + :Partition_Column_Name, :Bad_Partition_Column_Type, + :Partition_Count); +ERROR: partition column types 25 and 20 do not match +-- Now, partition table data using valid arguments +SELECT worker_range_partition_table(:JobId, :TaskId, :Select_Query_Text, + :Partition_Column_Name, :Partition_Column_Type, + ARRAY['aaa', 'some']::_text); + worker_range_partition_table +------------------------------ + +(1 row) + +-- Check that we fail to merge when the number of column names and column types +-- do not match +SELECT worker_merge_files_into_table(:JobId, :TaskId, + ARRAY['textcolumn', 'binarycolumn'], + ARRAY['text', 'bytea', 'integer']); +ERROR: column name array size: 2 and type array size: 3 do not match +-- Check that we fail to merge when column types do not match underlying data +SELECT worker_merge_files_into_table(:JobId, :TaskId, + ARRAY['textcolumn', 'binarycolumn'], + ARRAY['text', 'integer']); +ERROR: invalid input syntax for integer: "\x0b50" +CONTEXT: COPY task_101108, line 1, column binarycolumn: "\x0b50" +-- Finally, merge partitioned files using valid arguments +SELECT worker_merge_files_into_table(:JobId, :TaskId, + ARRAY['textcolumn', 'binarycolumn'], + ARRAY['text', 'bytea']); + worker_merge_files_into_table +------------------------------- + +(1 row) + diff --git a/src/test/regress/expected/worker_create_table.out b/src/test/regress/expected/worker_create_table.out new file mode 100644 index 000000000..2d083a5ae --- /dev/null +++ b/src/test/regress/expected/worker_create_table.out @@ -0,0 +1,69 @@ +-- +-- WORKER_CREATE_TABLE +-- +-- Create new table definitions for lineitem and supplier tables to test worker +-- node execution logic. For now,the tests include range and hash partitioning +-- of existing tables. +CREATE TABLE lineitem ( + l_orderkey bigint not null, + l_partkey integer not null, + l_suppkey integer not null, + l_linenumber integer not null, + l_quantity decimal(15, 2) not null, + l_extendedprice decimal(15, 2) not null, + l_discount decimal(15, 2) not null, + l_tax decimal(15, 2) not null, + l_returnflag char(1) not null, + l_linestatus char(1) not null, + l_shipdate date not null, + l_commitdate date not null, + l_receiptdate date not null, + l_shipinstruct char(25) not null, + l_shipmode char(10) not null, + l_comment varchar(44) not null, + PRIMARY KEY(l_orderkey, l_linenumber) ); +CREATE TABLE lineitem_complex ( + l_partkey integer not null, + l_discount decimal(15, 2) not null, + l_shipdate date not null, + l_comment varchar(44) not null ); +-- Range partitioned lineitem data are inserted into these four tables +CREATE TABLE lineitem_range_part_00 ( LIKE lineitem ); +CREATE TABLE lineitem_range_part_01 ( LIKE lineitem ); +CREATE TABLE lineitem_range_part_02 ( LIKE lineitem ); +CREATE TABLE lineitem_range_part_03 ( LIKE lineitem ); +-- Complex range partitioned lineitem data are inserted into these four tables +CREATE TABLE lineitem_range_complex_part_00 ( LIKE lineitem_complex ); +CREATE TABLE lineitem_range_complex_part_01 ( LIKE lineitem_complex ); +CREATE TABLE lineitem_range_complex_part_02 ( LIKE lineitem_complex ); +CREATE TABLE lineitem_range_complex_part_03 ( LIKE lineitem_complex ); +-- Hash partitioned lineitem data are inserted into these four tables +CREATE TABLE lineitem_hash_part_00 ( LIKE lineitem ); +CREATE TABLE lineitem_hash_part_01 ( LIKE lineitem ); +CREATE TABLE lineitem_hash_part_02 ( LIKE lineitem ); +CREATE TABLE lineitem_hash_part_03 ( LIKE lineitem ); +-- Complex hash partitioned lineitem data are inserted into these four tables +CREATE TABLE lineitem_hash_complex_part_00 ( LIKE lineitem_complex ); +CREATE TABLE lineitem_hash_complex_part_01 ( LIKE lineitem_complex ); +CREATE TABLE lineitem_hash_complex_part_02 ( LIKE lineitem_complex ); +CREATE TABLE lineitem_hash_complex_part_03 ( LIKE lineitem_complex ); +-- Now create a supplier table to test repartitioning the data on the nation key +-- column, where the column's values can be null or zero. +CREATE TABLE SUPPLIER +( + s_suppkey integer not null, + s_name char(25) not null, + s_address varchar(40) not null, + s_nationkey integer, + s_phone char(15) not null, + s_acctbal decimal(15,2) not null, + s_comment varchar(101) not null +); +-- Range partitioned supplier data are inserted into three tables +CREATE TABLE supplier_range_part_00 ( LIKE supplier ); +CREATE TABLE supplier_range_part_01 ( LIKE supplier ); +CREATE TABLE supplier_range_part_02 ( LIKE supplier ); +-- Hash partitioned supplier data are inserted into three tables +CREATE TABLE supplier_hash_part_00 ( LIKE supplier ); +CREATE TABLE supplier_hash_part_01 ( LIKE supplier ); +CREATE TABLE supplier_hash_part_02 ( LIKE supplier ); diff --git a/src/test/regress/expected/worker_hash_partition.out b/src/test/regress/expected/worker_hash_partition.out new file mode 100644 index 000000000..f324571b2 --- /dev/null +++ b/src/test/regress/expected/worker_hash_partition.out @@ -0,0 +1,113 @@ +-- +-- WORKER_HASH_PARTITION +-- +\set JobId 201010 +\set TaskId 101103 +\set Partition_Column l_orderkey +\set Partition_Column_Text '\'l_orderkey\'' +\set Partition_Column_Type 20 +\set Partition_Count 4 +\set Select_Query_Text '\'SELECT * FROM lineitem\'' +\set Select_All 'SELECT *' +-- Hash functions internally return unsigned 32-bit integers. However, when +-- called externally, the return value becomes a signed 32-bit integer. We hack +-- around this conversion issue by bitwise-anding the hash results. Note that +-- this only works because we are modding with 4. The proper Hash_Mod_Function +-- would be (case when hashint8(l_orderkey) >= 0 then (hashint8(l_orderkey) % 4) +-- else ((hashint8(l_orderkey) + 4294967296) % 4) end). +\set Hash_Mod_Function '( (hashint8(l_orderkey) & 2147483647) % 4 )' +\set Table_Part_00 lineitem_hash_part_00 +\set Table_Part_01 lineitem_hash_part_01 +\set Table_Part_02 lineitem_hash_part_02 +\set Table_Part_03 lineitem_hash_part_03 +-- Run select query, and apply hash partitioning on query results +SELECT worker_hash_partition_table(:JobId, :TaskId, :Select_Query_Text, + :Partition_Column_Text, :Partition_Column_Type, + :Partition_Count); + worker_hash_partition_table +----------------------------- + +(1 row) + +COPY :Table_Part_00 FROM 'base/pgsql_job_cache/job_201010/task_101103/p_00000'; +COPY :Table_Part_01 FROM 'base/pgsql_job_cache/job_201010/task_101103/p_00001'; +COPY :Table_Part_02 FROM 'base/pgsql_job_cache/job_201010/task_101103/p_00002'; +COPY :Table_Part_03 FROM 'base/pgsql_job_cache/job_201010/task_101103/p_00003'; +SELECT COUNT(*) FROM :Table_Part_00; + count +------- + 3081 +(1 row) + +SELECT COUNT(*) FROM :Table_Part_03; + count +------- + 2935 +(1 row) + +-- We first compute the difference of partition tables against the base table. +-- Then, we compute the difference of the base table against partitioned tables. +SELECT COUNT(*) AS diff_lhs_00 FROM ( + :Select_All FROM :Table_Part_00 EXCEPT ALL + :Select_All FROM lineitem WHERE (:Hash_Mod_Function = 0) ) diff; + diff_lhs_00 +------------- + 0 +(1 row) + +SELECT COUNT(*) AS diff_lhs_01 FROM ( + :Select_All FROM :Table_Part_01 EXCEPT ALL + :Select_All FROM lineitem WHERE (:Hash_Mod_Function = 1) ) diff; + diff_lhs_01 +------------- + 0 +(1 row) + +SELECT COUNT(*) AS diff_lhs_02 FROM ( + :Select_All FROM :Table_Part_02 EXCEPT ALL + :Select_All FROM lineitem WHERE (:Hash_Mod_Function = 2) ) diff; + diff_lhs_02 +------------- + 0 +(1 row) + +SELECT COUNT(*) AS diff_lhs_03 FROM ( + :Select_All FROM :Table_Part_03 EXCEPT ALL + :Select_All FROM lineitem WHERE (:Hash_Mod_Function = 3) ) diff; + diff_lhs_03 +------------- + 0 +(1 row) + +SELECT COUNT(*) AS diff_rhs_00 FROM ( + :Select_All FROM lineitem WHERE (:Hash_Mod_Function = 0) EXCEPT ALL + :Select_All FROM :Table_Part_00 ) diff; + diff_rhs_00 +------------- + 0 +(1 row) + +SELECT COUNT(*) AS diff_rhs_01 FROM ( + :Select_All FROM lineitem WHERE (:Hash_Mod_Function = 1) EXCEPT ALL + :Select_All FROM :Table_Part_01 ) diff; + diff_rhs_01 +------------- + 0 +(1 row) + +SELECT COUNT(*) AS diff_rhs_02 FROM ( + :Select_All FROM lineitem WHERE (:Hash_Mod_Function = 2) EXCEPT ALL + :Select_All FROM :Table_Part_02 ) diff; + diff_rhs_02 +------------- + 0 +(1 row) + +SELECT COUNT(*) AS diff_rhs_03 FROM ( + :Select_All FROM lineitem WHERE (:Hash_Mod_Function = 3) EXCEPT ALL + :Select_All FROM :Table_Part_03 ) diff; + diff_rhs_03 +------------- + 0 +(1 row) + diff --git a/src/test/regress/expected/worker_hash_partition_complex.out b/src/test/regress/expected/worker_hash_partition_complex.out new file mode 100644 index 000000000..2dfbe3702 --- /dev/null +++ b/src/test/regress/expected/worker_hash_partition_complex.out @@ -0,0 +1,121 @@ +-- +-- WORKER_HASH_PARTITION_COMPLEX +-- +\set JobId 201010 +\set TaskId 101104 +\set Partition_Column l_partkey +\set Partition_Column_Text '\'l_partkey\'' +\set Partition_Column_Type 23 +\set Partition_Count 4 +\set Select_Columns 'SELECT l_partkey, l_discount, l_shipdate, l_comment' +\set Select_Filters 'l_shipdate >= date \'1992-01-15\' AND l_discount between 0.02 AND 0.08' +\set Hash_Mod_Function '( (hashint4(l_partkey) & 2147483647) % 4 )' +\set Table_Part_00 lineitem_hash_complex_part_00 +\set Table_Part_01 lineitem_hash_complex_part_01 +\set Table_Part_02 lineitem_hash_complex_part_02 +\set Table_Part_03 lineitem_hash_complex_part_03 +-- Run hardcoded complex select query, and apply hash partitioning on query +-- results +SELECT worker_hash_partition_table(:JobId, :TaskId, + 'SELECT l_partkey, l_discount, l_shipdate, l_comment' + ' FROM lineitem ' + ' WHERE l_shipdate >= date ''1992-01-15''' + ' AND l_discount between 0.02 AND 0.08', + :Partition_Column_Text, :Partition_Column_Type, + :Partition_Count); + worker_hash_partition_table +----------------------------- + +(1 row) + +-- Copy partitioned data files into tables for testing purposes +COPY :Table_Part_00 FROM 'base/pgsql_job_cache/job_201010/task_101104/p_00000'; +COPY :Table_Part_01 FROM 'base/pgsql_job_cache/job_201010/task_101104/p_00001'; +COPY :Table_Part_02 FROM 'base/pgsql_job_cache/job_201010/task_101104/p_00002'; +COPY :Table_Part_03 FROM 'base/pgsql_job_cache/job_201010/task_101104/p_00003'; +SELECT COUNT(*) FROM :Table_Part_00; + count +------- + 1988 +(1 row) + +SELECT COUNT(*) FROM :Table_Part_03; + count +------- + 1881 +(1 row) + +-- We first compute the difference of partition tables against the base table. +-- Then, we compute the difference of the base table against partitioned tables. +SELECT COUNT(*) AS diff_lhs_00 FROM ( + :Select_Columns FROM :Table_Part_00 EXCEPT ALL + :Select_Columns FROM lineitem WHERE :Select_Filters AND + (:Hash_Mod_Function = 0) ) diff; + diff_lhs_00 +------------- + 0 +(1 row) + +SELECT COUNT(*) AS diff_lhs_01 FROM ( + :Select_Columns FROM :Table_Part_01 EXCEPT ALL + :Select_Columns FROM lineitem WHERE :Select_Filters AND + (:Hash_Mod_Function = 1) ) diff; + diff_lhs_01 +------------- + 0 +(1 row) + +SELECT COUNT(*) AS diff_lhs_02 FROM ( + :Select_Columns FROM :Table_Part_02 EXCEPT ALL + :Select_Columns FROM lineitem WHERE :Select_Filters AND + (:Hash_Mod_Function = 2) ) diff; + diff_lhs_02 +------------- + 0 +(1 row) + +SELECT COUNT(*) AS diff_lhs_03 FROM ( + :Select_Columns FROM :Table_Part_03 EXCEPT ALL + :Select_Columns FROM lineitem WHERE :Select_Filters AND + (:Hash_Mod_Function = 3) ) diff; + diff_lhs_03 +------------- + 0 +(1 row) + +SELECT COUNT(*) AS diff_rhs_00 FROM ( + :Select_Columns FROM lineitem WHERE :Select_Filters AND + (:Hash_Mod_Function = 0) EXCEPT ALL + :Select_Columns FROM :Table_Part_00 ) diff; + diff_rhs_00 +------------- + 0 +(1 row) + +SELECT COUNT(*) AS diff_rhs_01 FROM ( + :Select_Columns FROM lineitem WHERE :Select_Filters AND + (:Hash_Mod_Function = 1) EXCEPT ALL + :Select_Columns FROM :Table_Part_01 ) diff; + diff_rhs_01 +------------- + 0 +(1 row) + +SELECT COUNT(*) AS diff_rhs_02 FROM ( + :Select_Columns FROM lineitem WHERE :Select_Filters AND + (:Hash_Mod_Function = 2) EXCEPT ALL + :Select_Columns FROM :Table_Part_02 ) diff; + diff_rhs_02 +------------- + 0 +(1 row) + +SELECT COUNT(*) AS diff_rhs_03 FROM ( + :Select_Columns FROM lineitem WHERE :Select_Filters AND + (:Hash_Mod_Function = 3) EXCEPT ALL + :Select_Columns FROM :Table_Part_03 ) diff; + diff_rhs_03 +------------- + 0 +(1 row) + diff --git a/src/test/regress/expected/worker_merge_hash_files.out b/src/test/regress/expected/worker_merge_hash_files.out new file mode 100644 index 000000000..89246b89f --- /dev/null +++ b/src/test/regress/expected/worker_merge_hash_files.out @@ -0,0 +1,50 @@ +-- +-- WORKER_MERGE_HASH_FILES +-- +\set JobId 201010 +\set TaskId 101103 +\set Task_Table_Name public.task_101103 +\set Select_All 'SELECT *' +-- TaskId determines our dependency on hash partitioned files. We take these +-- files, and merge them in a task table. We also pass the column names and +-- column types that are used to create the task table. +SELECT worker_merge_files_into_table(:JobId, :TaskId, + ARRAY['orderkey', 'partkey', 'suppkey', 'linenumber', 'quantity', 'extendedprice', + 'discount', 'tax', 'returnflag', 'linestatus', 'shipdate', 'commitdate', + 'receiptdate', 'shipinstruct', 'shipmode', 'comment']::_text, + ARRAY['bigint', 'integer', 'integer', 'integer', 'decimal(15, 2)', 'decimal(15, 2)', + 'decimal(15, 2)', 'decimal(15, 2)', 'char(1)', 'char(1)', 'date', 'date', + 'date', 'char(25)', 'char(10)', 'varchar(44)']::_text); + worker_merge_files_into_table +------------------------------- + +(1 row) + +-- We first count elements from the merged table and the original table we hash +-- partitioned. We then compute the difference of these two tables. +SELECT COUNT(*) FROM :Task_Table_Name; + count +------- + 12000 +(1 row) + +SELECT COUNT(*) FROM lineitem; + count +------- + 12000 +(1 row) + +SELECT COUNT(*) AS diff_lhs FROM ( :Select_All FROM :Task_Table_Name EXCEPT ALL + :Select_All FROM lineitem ) diff; + diff_lhs +---------- + 0 +(1 row) + +SELECT COUNT(*) AS diff_rhs FROM ( :Select_All FROM lineitem EXCEPT ALL + :Select_All FROM :Task_Table_Name ) diff; + diff_rhs +---------- + 0 +(1 row) + diff --git a/src/test/regress/expected/worker_merge_range_files.out b/src/test/regress/expected/worker_merge_range_files.out new file mode 100644 index 000000000..b39f52731 --- /dev/null +++ b/src/test/regress/expected/worker_merge_range_files.out @@ -0,0 +1,50 @@ +-- +-- WORKER_MERGE_RANGE_FILES +-- +\set JobId 201010 +\set TaskId 101101 +\set Task_Table_Name public.task_101101 +\set Select_All 'SELECT *' +-- TaskId determines our dependency on range partitioned files. We take these +-- files, and merge them in a task table. We also pass the column names and +-- column types that are used to create the task table. +SELECT worker_merge_files_into_table(:JobId, :TaskId, + ARRAY['orderkey', 'partkey', 'suppkey', 'linenumber', 'quantity', 'extendedprice', + 'discount', 'tax', 'returnflag', 'linestatus', 'shipdate', 'commitdate', + 'receiptdate', 'shipinstruct', 'shipmode', 'comment']::_text, + ARRAY['bigint', 'integer', 'integer', 'integer', 'decimal(15, 2)', 'decimal(15, 2)', + 'decimal(15, 2)', 'decimal(15, 2)', 'char(1)', 'char(1)', 'date', 'date', + 'date', 'char(25)', 'char(10)', 'varchar(44)']::_text); + worker_merge_files_into_table +------------------------------- + +(1 row) + +-- We first count elements from the merged table and the original table we range +-- partitioned. We then compute the difference of these two tables. +SELECT COUNT(*) FROM :Task_Table_Name; + count +------- + 12000 +(1 row) + +SELECT COUNT(*) FROM lineitem; + count +------- + 12000 +(1 row) + +SELECT COUNT(*) AS diff_lhs FROM ( :Select_All FROM :Task_Table_Name EXCEPT ALL + :Select_All FROM lineitem ) diff; + diff_lhs +---------- + 0 +(1 row) + +SELECT COUNT(*) AS diff_rhs FROM ( :Select_All FROM lineitem EXCEPT ALL + :Select_All FROM :Task_Table_Name ) diff; + diff_rhs +---------- + 0 +(1 row) + diff --git a/src/test/regress/expected/worker_null_data_partition.out b/src/test/regress/expected/worker_null_data_partition.out new file mode 100644 index 000000000..11881fbc9 --- /dev/null +++ b/src/test/regress/expected/worker_null_data_partition.out @@ -0,0 +1,180 @@ +-- +-- WORKER_NULL_DATA_PARTITION +-- +\set JobId 201010 +\set Range_TaskId 101106 +\set Partition_Column s_nationkey +\set Partition_Column_Text '\'s_nationkey\'' +\set Partition_Column_Type 23 +\set Select_Query_Text '\'SELECT * FROM supplier\'' +\set Select_All 'SELECT *' +\set Range_Table_Part_00 supplier_range_part_00 +\set Range_Table_Part_01 supplier_range_part_01 +\set Range_Table_Part_02 supplier_range_part_02 +-- Run select query, and apply range partitioning on query results. Note that +-- one of the split point values is 0, We are checking here that the partition +-- function doesn't treat 0 as null, and that range repartitioning correctly +-- puts null nation key values into the 0th repartition bucket. +SELECT worker_range_partition_table(:JobId, :Range_TaskId, :Select_Query_Text, + :Partition_Column_Text, :Partition_Column_Type, + ARRAY[0, 10]::_int4); + worker_range_partition_table +------------------------------ + +(1 row) + +-- Copy partitioned data files into tables for testing purposes +COPY :Range_Table_Part_00 FROM 'base/pgsql_job_cache/job_201010/task_101106/p_00000'; +COPY :Range_Table_Part_01 FROM 'base/pgsql_job_cache/job_201010/task_101106/p_00001'; +COPY :Range_Table_Part_02 FROM 'base/pgsql_job_cache/job_201010/task_101106/p_00002'; +SELECT COUNT(*) FROM :Range_Table_Part_00; + count +------- + 6 +(1 row) + +SELECT COUNT(*) FROM :Range_Table_Part_02; + count +------- + 588 +(1 row) + +-- We first compute the difference of partition tables against the base table. +-- Then, we compute the difference of the base table against partitioned tables. +SELECT COUNT(*) AS diff_lhs_00 FROM ( + :Select_All FROM :Range_Table_Part_00 EXCEPT ALL + (:Select_All FROM supplier WHERE :Partition_Column < 0 OR + :Partition_Column IS NULL) ) diff; + diff_lhs_00 +------------- + 0 +(1 row) + +SELECT COUNT(*) AS diff_lhs_01 FROM ( + :Select_All FROM :Range_Table_Part_01 EXCEPT ALL + :Select_All FROM supplier WHERE :Partition_Column >= 0 AND + :Partition_Column < 10 ) diff; + diff_lhs_01 +------------- + 0 +(1 row) + +SELECT COUNT(*) AS diff_rhs_02 FROM ( + :Select_All FROM supplier WHERE :Partition_Column >= 10 EXCEPT ALL + :Select_All FROM :Range_Table_Part_02 ) diff; + diff_rhs_02 +------------- + 0 +(1 row) + +SELECT COUNT(*) AS diff_rhs_00 FROM ( + (:Select_All FROM supplier WHERE :Partition_Column < 0 OR + :Partition_Column IS NULL) EXCEPT ALL + :Select_All FROM :Range_Table_Part_00 ) diff; + diff_rhs_00 +------------- + 0 +(1 row) + +SELECT COUNT(*) AS diff_rhs_01 FROM ( + :Select_All FROM supplier WHERE :Partition_Column >= 0 AND + :Partition_Column < 10 EXCEPT ALL + :Select_All FROM :Range_Table_Part_01 ) diff; + diff_rhs_01 +------------- + 0 +(1 row) + +SELECT COUNT(*) AS diff_rhs_02 FROM ( + :Select_All FROM supplier WHERE :Partition_Column >= 10 EXCEPT ALL + :Select_All FROM :Range_Table_Part_02 ) diff; + diff_rhs_02 +------------- + 0 +(1 row) + +-- Next, run select query and apply hash partitioning on query results. We are +-- checking here that hash repartitioning correctly puts null nation key values +-- into the 0th repartition bucket. +\set Hash_TaskId 101107 +\set Partition_Count 4 +\set Hash_Mod_Function '( (hashint4(s_nationkey) & 2147483647) % 4 )' +\set Hash_Table_Part_00 supplier_hash_part_00 +\set Hash_Table_Part_01 supplier_hash_part_01 +\set Hash_Table_Part_02 supplier_hash_part_02 +-- Run select query, and apply hash partitioning on query results +SELECT worker_hash_partition_table(:JobId, :Hash_TaskId, :Select_Query_Text, + :Partition_Column_Text, :Partition_Column_Type, + :Partition_Count); + worker_hash_partition_table +----------------------------- + +(1 row) + +COPY :Hash_Table_Part_00 FROM 'base/pgsql_job_cache/job_201010/task_101107/p_00000'; +COPY :Hash_Table_Part_01 FROM 'base/pgsql_job_cache/job_201010/task_101107/p_00001'; +COPY :Hash_Table_Part_02 FROM 'base/pgsql_job_cache/job_201010/task_101107/p_00002'; +SELECT COUNT(*) FROM :Hash_Table_Part_00; + count +------- + 298 +(1 row) + +SELECT COUNT(*) FROM :Hash_Table_Part_02; + count +------- + 203 +(1 row) + +-- We first compute the difference of partition tables against the base table. +-- Then, we compute the difference of the base table against partitioned tables. +SELECT COUNT(*) AS diff_lhs_00 FROM ( + :Select_All FROM :Hash_Table_Part_00 EXCEPT ALL + (:Select_All FROM supplier WHERE (:Hash_Mod_Function = 0) OR + :Partition_Column IS NULL) ) diff; + diff_lhs_00 +------------- + 0 +(1 row) + +SELECT COUNT(*) AS diff_lhs_01 FROM ( + :Select_All FROM :Hash_Table_Part_01 EXCEPT ALL + :Select_All FROM supplier WHERE (:Hash_Mod_Function = 1) ) diff; + diff_lhs_01 +------------- + 0 +(1 row) + +SELECT COUNT(*) AS diff_lhs_02 FROM ( + :Select_All FROM :Hash_Table_Part_02 EXCEPT ALL + :Select_All FROM supplier WHERE (:Hash_Mod_Function = 2) ) diff; + diff_lhs_02 +------------- + 0 +(1 row) + +SELECT COUNT(*) AS diff_rhs_00 FROM ( + (:Select_All FROM supplier WHERE (:Hash_Mod_Function = 0) OR + :Partition_Column IS NULL) EXCEPT ALL + :Select_All FROM :Hash_Table_Part_00 ) diff; + diff_rhs_00 +------------- + 0 +(1 row) + +SELECT COUNT(*) AS diff_rhs_01 FROM ( + :Select_All FROM supplier WHERE (:Hash_Mod_Function = 1) EXCEPT ALL + :Select_All FROM :Hash_Table_Part_01 ) diff; + diff_rhs_01 +------------- + 0 +(1 row) + +SELECT COUNT(*) AS diff_rhs_02 FROM ( + :Select_All FROM supplier WHERE (:Hash_Mod_Function = 2) EXCEPT ALL + :Select_All FROM :Hash_Table_Part_02 ) diff; + diff_rhs_02 +------------- + 0 +(1 row) + diff --git a/src/test/regress/expected/worker_range_partition.out b/src/test/regress/expected/worker_range_partition.out new file mode 100644 index 000000000..f33801018 --- /dev/null +++ b/src/test/regress/expected/worker_range_partition.out @@ -0,0 +1,114 @@ +-- +-- WORKER_RANGE_PARTITION +-- +\set JobId 201010 +\set TaskId 101101 +\set Partition_Column l_orderkey +\set Partition_Column_Text '\'l_orderkey\'' +\set Partition_Column_Type 20 +\set Select_Query_Text '\'SELECT * FROM lineitem\'' +\set Select_All 'SELECT *' +\set Table_Part_00 lineitem_range_part_00 +\set Table_Part_01 lineitem_range_part_01 +\set Table_Part_02 lineitem_range_part_02 +\set Table_Part_03 lineitem_range_part_03 +-- Run select query, and apply range partitioning on query results +SELECT worker_range_partition_table(:JobId, :TaskId, :Select_Query_Text, + :Partition_Column_Text, :Partition_Column_Type, + ARRAY[1, 3000, 12000]::_int8); + worker_range_partition_table +------------------------------ + +(1 row) + +-- Note that the following file names depend on job and task identifiers. We +-- prefer to substitute them here, but the current psql version does not perform +-- variable interpolation for names inside single quotes. This SQL interpolation +-- issue is fixed in PostgreSQL 9.0; and once we upgrade, we will change both +-- the following filenames, and the sequence names in the relay_sequence tests. +COPY :Table_Part_00 FROM 'base/pgsql_job_cache/job_201010/task_101101/p_00000'; +COPY :Table_Part_01 FROM 'base/pgsql_job_cache/job_201010/task_101101/p_00001'; +COPY :Table_Part_02 FROM 'base/pgsql_job_cache/job_201010/task_101101/p_00002'; +COPY :Table_Part_03 FROM 'base/pgsql_job_cache/job_201010/task_101101/p_00003'; +SELECT COUNT(*) FROM :Table_Part_00; + count +------- + 0 +(1 row) + +SELECT COUNT(*) FROM :Table_Part_03; + count +------- + 3047 +(1 row) + +-- We first compute the difference of partition tables against the base table. +-- Then, we compute the difference of the base table against partitioned tables. +SELECT COUNT(*) AS diff_lhs_00 FROM ( + :Select_All FROM :Table_Part_00 EXCEPT ALL + :Select_All FROM lineitem WHERE :Partition_Column < 1 ) diff; + diff_lhs_00 +------------- + 0 +(1 row) + +SELECT COUNT(*) AS diff_lhs_01 FROM ( + :Select_All FROM :Table_Part_01 EXCEPT ALL + :Select_All FROM lineitem WHERE :Partition_Column >= 1 AND + :Partition_Column < 3000 ) diff; + diff_lhs_01 +------------- + 0 +(1 row) + +SELECT COUNT(*) AS diff_lhs_02 FROM ( + :Select_All FROM :Table_Part_02 EXCEPT ALL + :Select_All FROM lineitem WHERE :Partition_Column >= 3000 AND + :Partition_Column < 12000 ) diff; + diff_lhs_02 +------------- + 0 +(1 row) + +SELECT COUNT(*) AS diff_lhs_03 FROM ( + :Select_All FROM :Table_Part_03 EXCEPT ALL + :Select_All FROM lineitem WHERE :Partition_Column >= 12000 ) diff; + diff_lhs_03 +------------- + 0 +(1 row) + +SELECT COUNT(*) AS diff_rhs_00 FROM ( + :Select_All FROM lineitem WHERE :Partition_Column < 1 EXCEPT ALL + :Select_All FROM :Table_Part_00 ) diff; + diff_rhs_00 +------------- + 0 +(1 row) + +SELECT COUNT(*) AS diff_rhs_01 FROM ( + :Select_All FROM lineitem WHERE :Partition_Column >= 1 AND + :Partition_Column < 3000 EXCEPT ALL + :Select_All FROM :Table_Part_01 ) diff; + diff_rhs_01 +------------- + 0 +(1 row) + +SELECT COUNT(*) AS diff_rhs_02 FROM ( + :Select_All FROM lineitem WHERE :Partition_Column >= 3000 AND + :Partition_Column < 12000 EXCEPT ALL + :Select_All FROM :Table_Part_02 ) diff; + diff_rhs_02 +------------- + 0 +(1 row) + +SELECT COUNT(*) AS diff_rhs_03 FROM ( + :Select_All FROM lineitem WHERE :Partition_Column >= 12000 EXCEPT ALL + :Select_All FROM :Table_Part_03 ) diff; + diff_rhs_03 +------------- + 0 +(1 row) + diff --git a/src/test/regress/expected/worker_range_partition_complex.out b/src/test/regress/expected/worker_range_partition_complex.out new file mode 100644 index 000000000..57b2c7795 --- /dev/null +++ b/src/test/regress/expected/worker_range_partition_complex.out @@ -0,0 +1,123 @@ +-- +-- WORKER_RANGE_PARTITION_COMPLEX +-- +\set JobId 201010 +\set TaskId 101102 +\set Partition_Column l_partkey +\set Partition_Column_Text '\'l_partkey\'' +\set Partition_Column_Type 23 +\set Select_Columns 'SELECT l_partkey, l_discount, l_shipdate, l_comment' +\set Select_Filters 'l_shipdate >= date \'1992-01-15\' AND l_discount between 0.02 AND 0.08' +\set Table_Part_00 lineitem_range_complex_part_00 +\set Table_Part_01 lineitem_range_complex_part_01 +\set Table_Part_02 lineitem_range_complex_part_02 +\set Table_Part_03 lineitem_range_complex_part_03 +-- Run hardcoded complex select query, and apply range partitioning on query +-- results +SELECT worker_range_partition_table(:JobId, :TaskId, + 'SELECT l_partkey, l_discount, l_shipdate, l_comment' + ' FROM lineitem ' + ' WHERE l_shipdate >= date ''1992-01-15''' + ' AND l_discount between 0.02 AND 0.08', + :Partition_Column_Text, :Partition_Column_Type, + ARRAY[101, 12000, 18000]::_int4); + worker_range_partition_table +------------------------------ + +(1 row) + +-- Copy partitioned data files into tables for testing purposes +COPY :Table_Part_00 FROM 'base/pgsql_job_cache/job_201010/task_101102/p_00000'; +COPY :Table_Part_01 FROM 'base/pgsql_job_cache/job_201010/task_101102/p_00001'; +COPY :Table_Part_02 FROM 'base/pgsql_job_cache/job_201010/task_101102/p_00002'; +COPY :Table_Part_03 FROM 'base/pgsql_job_cache/job_201010/task_101102/p_00003'; +SELECT COUNT(*) FROM :Table_Part_00; + count +------- + 3 +(1 row) + +SELECT COUNT(*) FROM :Table_Part_03; + count +------- + 7022 +(1 row) + +-- We first compute the difference of partition tables against the base table. +-- Then, we compute the difference of the base table against partitioned tables. +SELECT COUNT(*) AS diff_lhs_00 FROM ( + :Select_Columns FROM :Table_Part_00 EXCEPT ALL + :Select_Columns FROM lineitem WHERE :Select_Filters AND + :Partition_Column < 101 ) diff; + diff_lhs_00 +------------- + 0 +(1 row) + +SELECT COUNT(*) AS diff_lhs_01 FROM ( + :Select_Columns FROM :Table_Part_01 EXCEPT ALL + :Select_Columns FROM lineitem WHERE :Select_Filters AND + :Partition_Column >= 101 AND + :Partition_Column < 12000 ) diff; + diff_lhs_01 +------------- + 0 +(1 row) + +SELECT COUNT(*) AS diff_lhs_02 FROM ( + :Select_Columns FROM :Table_Part_02 EXCEPT ALL + :Select_Columns FROM lineitem WHERE :Select_Filters AND + :Partition_Column >= 12000 AND + :Partition_Column < 18000 ) diff; + diff_lhs_02 +------------- + 0 +(1 row) + +SELECT COUNT(*) AS diff_lhs_03 FROM ( + :Select_Columns FROM :Table_Part_03 EXCEPT ALL + :Select_Columns FROM lineitem WHERE :Select_Filters AND + :Partition_Column >= 18000 ) diff; + diff_lhs_03 +------------- + 0 +(1 row) + +SELECT COUNT(*) AS diff_rhs_00 FROM ( + :Select_Columns FROM lineitem WHERE :Select_Filters AND + :Partition_Column < 101 EXCEPT ALL + :Select_Columns FROM :Table_Part_00 ) diff; + diff_rhs_00 +------------- + 0 +(1 row) + +SELECT COUNT(*) AS diff_rhs_01 FROM ( + :Select_Columns FROM lineitem WHERE :Select_Filters AND + :Partition_Column >= 101 AND + :Partition_Column < 12000 EXCEPT ALL + :Select_Columns FROM :Table_Part_01 ) diff; + diff_rhs_01 +------------- + 0 +(1 row) + +SELECT COUNT(*) AS diff_rhs_02 FROM ( + :Select_Columns FROM lineitem WHERE :Select_Filters AND + :Partition_Column >= 12000 AND + :Partition_Column < 18000 EXCEPT ALL + :Select_Columns FROM :Table_Part_02 ) diff; + diff_rhs_02 +------------- + 0 +(1 row) + +SELECT COUNT(*) AS diff_rhs_03 FROM ( + :Select_Columns FROM lineitem WHERE :Select_Filters AND + :Partition_Column >= 18000 EXCEPT ALL + :Select_Columns FROM :Table_Part_03 ) diff; + diff_rhs_03 +------------- + 0 +(1 row) + diff --git a/src/test/regress/input/multi_agg_distinct.source b/src/test/regress/input/multi_agg_distinct.source new file mode 100644 index 000000000..5d7fa7e53 --- /dev/null +++ b/src/test/regress/input/multi_agg_distinct.source @@ -0,0 +1,62 @@ +-- +-- MULTI_AGG_DISTINCT +-- + +-- Create a new range partitioned lineitem table and stage data into it + +CREATE TABLE lineitem_range ( + l_orderkey bigint not null, + l_partkey integer not null, + l_suppkey integer not null, + l_linenumber integer not null, + l_quantity decimal(15, 2) not null, + l_extendedprice decimal(15, 2) not null, + l_discount decimal(15, 2) not null, + l_tax decimal(15, 2) not null, + l_returnflag char(1) not null, + l_linestatus char(1) not null, + l_shipdate date not null, + l_commitdate date not null, + l_receiptdate date not null, + l_shipinstruct char(25) not null, + l_shipmode char(10) not null, + l_comment varchar(44) not null ); +SELECT master_create_distributed_table('lineitem_range', 'l_orderkey', 'range'); + +\STAGE lineitem_range FROM '@abs_srcdir@/data/lineitem.1.data' with delimiter '|' +\STAGE lineitem_range FROM '@abs_srcdir@/data/lineitem.2.data' with delimiter '|' + +-- Run aggregate(distinct) on partition column for range partitioned table + +SELECT count(distinct l_orderkey) FROM lineitem_range; +SELECT avg(distinct l_orderkey) FROM lineitem_range; + +-- Run count(distinct) on join between a range partitioned table and a single +-- sharded table. For this test, we also change a config setting to ensure that +-- we don't repartition any of the tables during the query. + +SET citusdb.large_table_shard_count TO 2; + +SELECT p_partkey, count(distinct l_orderkey) FROM lineitem_range, part + WHERE l_partkey = p_partkey + GROUP BY p_partkey + ORDER BY p_partkey LIMIT 10; + +RESET citusdb.large_table_shard_count; + +-- Check that we don't support count(distinct) on non-partition column, and +-- complex expressions. + +SELECT count(distinct l_partkey) FROM lineitem_range; +SELECT count(distinct (l_orderkey + 1)) FROM lineitem_range; + +-- Now test append partitioned tables. First run count(distinct) on a single +-- sharded table. + +SELECT count(distinct p_mfgr) FROM part; +SELECT p_mfgr, count(distinct p_partkey) FROM part GROUP BY p_mfgr; + +-- We don't support count(distinct) queries if table is append partitioned and +-- has multiple shards + +SELECT count(distinct o_orderkey) FROM orders; diff --git a/src/test/regress/input/multi_agg_type_conversion.source b/src/test/regress/input/multi_agg_type_conversion.source new file mode 100644 index 000000000..65e4375be --- /dev/null +++ b/src/test/regress/input/multi_agg_type_conversion.source @@ -0,0 +1,56 @@ +-- +-- MULTI_AGG_TYPE_CONVERSION +-- + +-- Test aggregate type conversions using sums of integers and division operator + +SELECT sum(l_suppkey) FROM lineitem; +SELECT sum(l_suppkey) / 2 FROM lineitem; +SELECT sum(l_suppkey) / 2::numeric FROM lineitem; +SELECT sum(l_suppkey)::int8 / 2 FROM lineitem; + + +-- Create a new table to test type conversions on different types, and stage +-- data into this table. Then, apply aggregate functions and divide / multiply +-- the results to test type conversions. + +CREATE TABLE aggregate_type ( + float_value float(20) not null, + double_value float(40) not null, + interval_value interval not null); +SELECT master_create_distributed_table('aggregate_type', 'float_value', 'append'); + +\STAGE aggregate_type FROM '@abs_srcdir@/data/agg_type.data' + +-- Test conversions using aggregates on floats and division + +SELECT min(float_value), max(float_value), + sum(float_value), count(float_value), avg(float_value) +FROM aggregate_type; + +SELECT min(float_value) / 2, max(float_value) / 2, + sum(float_value) / 2, count(float_value) / 2, avg(float_value) / 2 +FROM aggregate_type; + +-- Test conversions using aggregates on large floats and multiplication + +SELECT min(double_value), max(double_value), + sum(double_value), count(double_value), avg(double_value) +FROM aggregate_type; + +SELECT min(double_value) * 2, max(double_value) * 2, + sum(double_value) * 2, count(double_value) * 2, avg(double_value) * 2 +FROM aggregate_type; + +-- Test conversions using aggregates on intervals and division. We also use the +-- default configuration value for IntervalStyle. + +SET IntervalStyle TO 'postgres'; + +SELECT min(interval_value), max(interval_value), + sum(interval_value), count(interval_value), avg(interval_value) +FROM aggregate_type; + +SELECT min(interval_value) / 2, max(interval_value) / 2, + sum(interval_value) / 2, count(interval_value) / 2, avg(interval_value) / 2 +FROM aggregate_type; diff --git a/src/test/regress/input/multi_alter_table_statements.source b/src/test/regress/input/multi_alter_table_statements.source new file mode 100644 index 000000000..a588de5d2 --- /dev/null +++ b/src/test/regress/input/multi_alter_table_statements.source @@ -0,0 +1,153 @@ +-- +-- MULTI_ALTER_TABLE_STATEMENTS +-- + +-- Check that we can run ALTER TABLE statements on distributed tables. We +-- increase the logging verbosity to verify that commands are propagated to +-- all worker shards. We also set the shardid sequence here so that the shardids +-- in this test aren't affected by changes to the previous tests. + +ALTER SEQUENCE pg_catalog.pg_dist_shardid_seq RESTART 103000; +CREATE TABLE lineitem_alter ( + l_orderkey bigint not null, + l_partkey integer not null, + l_suppkey integer not null, + l_linenumber integer not null, + l_quantity decimal(15, 2) not null, + l_extendedprice decimal(15, 2) not null, + l_discount decimal(15, 2) not null, + l_tax decimal(15, 2) not null, + l_returnflag char(1) not null, + l_linestatus char(1) not null, + l_shipdate date not null, + l_commitdate date not null, + l_receiptdate date not null, + l_shipinstruct char(25) not null, + l_shipmode char(10) not null, + l_comment varchar(44) not null + ); +SELECT master_create_distributed_table('lineitem_alter', 'l_orderkey', 'append'); +\STAGE lineitem_alter FROM '@abs_srcdir@/data/lineitem.1.data' with delimiter '|' + +SET client_min_messages TO DEBUG2; + +-- Verify that we can add columns + +ALTER TABLE lineitem_alter ADD COLUMN float_column FLOAT; +ALTER TABLE lineitem_alter ADD COLUMN date_column DATE; +ALTER TABLE lineitem_alter ADD COLUMN int_column1 INTEGER DEFAULT 1; +ALTER TABLE lineitem_alter ADD COLUMN int_column2 INTEGER DEFAULT 2; +ALTER TABLE lineitem_alter ADD COLUMN null_column INTEGER; + +\d lineitem_alter +SELECT float_column, count(*) FROM lineitem_alter GROUP BY float_column; +SELECT int_column1, count(*) FROM lineitem_alter GROUP BY int_column1; + +-- Verify that SET|DROP DEFAULT works + +ALTER TABLE lineitem_alter ALTER COLUMN float_column SET DEFAULT 1; +ALTER TABLE lineitem_alter ALTER COLUMN int_column1 DROP DEFAULT; + +-- \stage to verify that default values take effect +\STAGE lineitem_alter (l_orderkey, l_partkey, l_suppkey, l_linenumber, l_quantity, l_extendedprice, l_discount, l_tax, l_returnflag, l_linestatus, l_shipdate, l_commitdate, l_receiptdate, l_shipinstruct, l_shipmode, l_comment) FROM '@abs_srcdir@/data/lineitem.1.data' with delimiter '|' + +SELECT float_column, count(*) FROM lineitem_alter GROUP BY float_column; +SELECT int_column1, count(*) FROM lineitem_alter GROUP BY int_column1; + +-- Verify that SET NOT NULL works + +ALTER TABLE lineitem_alter ALTER COLUMN int_column2 SET NOT NULL; +\d lineitem_alter + +-- Drop default so that NULLs will be inserted for this column +ALTER TABLE lineitem_alter ALTER COLUMN int_column2 DROP DEFAULT; + +-- \stage should fail because it will try to insert NULLs for a NOT NULL column +\STAGE lineitem_alter (l_orderkey, l_partkey, l_suppkey, l_linenumber, l_quantity, l_extendedprice, l_discount, l_tax, l_returnflag, l_linestatus, l_shipdate, l_commitdate, l_receiptdate, l_shipinstruct, l_shipmode, l_comment) FROM '@abs_srcdir@/data/lineitem.1.data' with delimiter '|' + +-- Verify that DROP NOT NULL works + +ALTER TABLE lineitem_alter ALTER COLUMN int_column2 DROP NOT NULL; +\d lineitem_alter + +-- \stage should succeed now +\STAGE lineitem_alter (l_orderkey, l_partkey, l_suppkey, l_linenumber, l_quantity, l_extendedprice, l_discount, l_tax, l_returnflag, l_linestatus, l_shipdate, l_commitdate, l_receiptdate, l_shipinstruct, l_shipmode, l_comment) FROM '@abs_srcdir@/data/lineitem.1.data' with delimiter '|' +SELECT count(*) from lineitem_alter; + +-- Verify that SET DATA TYPE works + +SELECT int_column2, pg_typeof(int_column2), count(*) from lineitem_alter GROUP BY int_column2; + +ALTER TABLE lineitem_alter ALTER COLUMN int_column2 SET DATA TYPE FLOAT; +\d lineitem_alter + +SELECT int_column2, pg_typeof(int_column2), count(*) from lineitem_alter GROUP BY int_column2; + +-- Verify that DROP COLUMN works + +ALTER TABLE lineitem_alter DROP COLUMN int_column1; +ALTER TABLE lineitem_alter DROP COLUMN float_column; +ALTER TABLE lineitem_alter DROP COLUMN date_column; + +-- Verify that IF EXISTS works as expected + +ALTER TABLE non_existent_table ADD COLUMN new_column INTEGER; +ALTER TABLE IF EXISTS non_existent_table ADD COLUMN new_column INTEGER; +ALTER TABLE IF EXISTS lineitem_alter ALTER COLUMN int_column2 SET DATA TYPE INTEGER; + +ALTER TABLE lineitem_alter DROP COLUMN non_existent_column; +ALTER TABLE lineitem_alter DROP COLUMN IF EXISTS non_existent_column; +ALTER TABLE lineitem_alter DROP COLUMN IF EXISTS int_column2; +\d lineitem_alter + +-- Verify that we can execute commands with multiple subcommands + +ALTER TABLE lineitem_alter ADD COLUMN int_column1 INTEGER, + ADD COLUMN int_column2 INTEGER; +\d lineitem_alter + +ALTER TABLE lineitem_alter ADD COLUMN int_column3 INTEGER, + ALTER COLUMN int_column1 SET STATISTICS 10; + +ALTER TABLE lineitem_alter DROP COLUMN int_column1, DROP COLUMN int_column2; +\d lineitem_alter + +-- Verify that we cannot execute alter commands on the distribution column + +ALTER TABLE lineitem_alter ALTER COLUMN l_orderkey DROP NOT NULL; +ALTER TABLE lineitem_alter DROP COLUMN l_orderkey; + +-- Verify that we error out on unsupported statement types + +ALTER TABLE lineitem_alter ALTER COLUMN l_orderkey SET STATISTICS 100; +ALTER TABLE lineitem_alter DROP CONSTRAINT IF EXISTS non_existent_contraint; +ALTER TABLE lineitem_alter SET WITHOUT OIDS; + +-- Verify that we error out in case of postgres errors on supported statement +-- types + +ALTER TABLE lineitem_alter ADD COLUMN new_column non_existent_type; +ALTER TABLE lineitem_alter ALTER COLUMN null_column SET NOT NULL; +ALTER TABLE lineitem_alter ALTER COLUMN l_partkey SET DEFAULT 'a'; + +-- Verify that we error out on statements involving RENAME + +ALTER TABLE lineitem_alter RENAME TO lineitem_renamed; +ALTER TABLE lineitem_alter RENAME COLUMN l_orderkey TO l_orderkey_renamed; +ALTER TABLE lineitem_alter RENAME CONSTRAINT constraint_a TO constraint_b; + +-- Verify that IF EXISTS works as expected with RENAME statements + +ALTER TABLE non_existent_table RENAME TO non_existent_table_renamed; +ALTER TABLE IF EXISTS non_existent_table RENAME TO non_existent_table_renamed; +ALTER TABLE IF EXISTS non_existent_table RENAME COLUMN column1 TO column2; +ALTER TABLE IF EXISTS lineitem_alter RENAME l_orderkey TO l_orderkey_renamed; + +-- Verify that none of the failed alter table commands took effect on the master +-- node +\d lineitem_alter + +-- Cleanup the table and its shards +RESET client_min_messages; +SELECT master_apply_delete_command('DELETE FROM lineitem_alter'); +DROP TABLE lineitem_alter; diff --git a/src/test/regress/input/multi_append_table_to_shard.source b/src/test/regress/input/multi_append_table_to_shard.source new file mode 100644 index 000000000..3c33fe34c --- /dev/null +++ b/src/test/regress/input/multi_append_table_to_shard.source @@ -0,0 +1,92 @@ +-- +-- MULTI_APPEND_TABLE_TO_SHARD +-- +-- Initialize tables to join +CREATE TABLE multi_append_table_to_shard_right +( + right_number INTEGER not null, + right_text TEXT not null +); +SELECT master_create_distributed_table('multi_append_table_to_shard_right', 'right_number', 'append'); + +CREATE TABLE multi_append_table_to_shard_left +( + left_number INTEGER not null, + left_text TEXT not null +); +SELECT master_create_distributed_table('multi_append_table_to_shard_left', 'left_number', 'append'); + +-- Replicate 'left' table on both workers +SELECT set_config('citusdb.shard_replication_factor', '2', false); +\STAGE multi_append_table_to_shard_left FROM '@abs_srcdir@/data/agg.data' +\STAGE multi_append_table_to_shard_left FROM '@abs_srcdir@/data/agg.data' + +-- Place 'right' table only on the primary worker +SELECT set_config('citusdb.shard_replication_factor', '1', false); +\STAGE multi_append_table_to_shard_right FROM '@abs_srcdir@/data/agg.data' + +-- Reset shard replication factor to ensure tasks will be assigned to both workers +SELECT set_config('citusdb.shard_replication_factor', '2', false); + +-- All 8 rows in left table match a row in right table +SELECT COUNT(*) +FROM multi_append_table_to_shard_left, + multi_append_table_to_shard_right +WHERE left_number = right_number; + +-- Now append more data to the 'right' table +CREATE TABLE multi_append_table_to_shard_stage +( + number INTEGER not null, + text TEXT not null +); + +COPY multi_append_table_to_shard_stage FROM '@abs_srcdir@/data/agg.data'; + +SELECT master_append_table_to_shard(shardid, 'multi_append_table_to_shard_stage', 'localhost', 57636) +FROM + pg_dist_shard +WHERE 'multi_append_table_to_shard_right'::regclass::oid = logicalrelid; + +-- Only the primary worker will see the new matches, as the secondary still uses a cached shard +SELECT COUNT(*) +FROM multi_append_table_to_shard_left, + multi_append_table_to_shard_right +WHERE left_number = right_number; + +-- Now add a lot of data to ensure we increase the size on disk +DELETE FROM multi_append_table_to_shard_stage; +COPY multi_append_table_to_shard_stage FROM '@abs_srcdir@/data/large_records.data' with delimiter '|'; + +SELECT master_append_table_to_shard(shardid, 'multi_append_table_to_shard_stage', 'localhost', 57636) +FROM + pg_dist_shard +WHERE 'multi_append_table_to_shard_right'::regclass::oid = logicalrelid; + +-- This join will refresh the shard on the secondary, all 8 rows in the left table will match twice (16) +SELECT COUNT(*) +FROM multi_append_table_to_shard_left, + multi_append_table_to_shard_right +WHERE left_number = right_number; + +-- Check that we error out if we try to append data to a hash partitioned table. + +UPDATE pg_dist_partition SET partmethod = 'h' WHERE + logicalrelid = 'multi_append_table_to_shard_right'::regclass::oid; + +SELECT master_create_empty_shard('multi_append_table_to_shard_right'); + +SELECT master_append_table_to_shard(shardid, 'multi_append_table_to_shard_stage', 'localhost', 57636) +FROM + pg_dist_shard +WHERE 'multi_append_table_to_shard_right'::regclass::oid = logicalrelid; + +UPDATE pg_dist_partition SET partmethod = 'a' WHERE + logicalrelid = 'multi_append_table_to_shard_right'::regclass::oid; + +-- Clean up after test +SELECT master_apply_delete_command('DELETE FROM multi_append_table_to_shard_right'); +SELECT master_apply_delete_command('DELETE FROM multi_append_table_to_shard_left'); +DROP TABLE multi_append_table_to_shard_stage; +DROP TABLE multi_append_table_to_shard_right; +DROP TABLE multi_append_table_to_shard_left; diff --git a/src/test/regress/input/multi_create_schema.source b/src/test/regress/input/multi_create_schema.source new file mode 100644 index 000000000..333188d86 --- /dev/null +++ b/src/test/regress/input/multi_create_schema.source @@ -0,0 +1,11 @@ +CREATE SCHEMA tpch +CREATE TABLE nation ( + n_nationkey integer not null, + n_name char(25) not null, + n_regionkey integer not null, + n_comment varchar(152)); +SELECT master_create_distributed_table('tpch.nation', 'n_nationkey', 'append'); + +\STAGE tpch.nation FROM '@abs_srcdir@/data/nation.data' with delimiter '|' + +SELECT count(*) from tpch.nation; diff --git a/src/test/regress/input/multi_fdw_large_shardid.source b/src/test/regress/input/multi_fdw_large_shardid.source new file mode 100644 index 000000000..75a3b1cc5 --- /dev/null +++ b/src/test/regress/input/multi_fdw_large_shardid.source @@ -0,0 +1,50 @@ +-- +-- MULTI_FDW_LARGE_SHARDID +-- + +-- Stage data to distributed tables, and run TPC-H query #1 and #6. This test +-- differs from previous tests in that it modifies the *internal* shardId +-- generator, forcing the distributed database to use 64-bit shard identifiers. + +ALTER SEQUENCE pg_catalog.pg_dist_shardid_seq RESTART 100200300400500; + +-- Stage additional data to start using large shard identifiers. + +\STAGE lineitem FROM '@abs_srcdir@/data/lineitem.1.data' +\STAGE lineitem FROM '@abs_srcdir@/data/lineitem.2.data' + +-- Query #1 from the TPC-H decision support benchmark. + +SELECT + l_returnflag, + l_linestatus, + sum(l_quantity) as sum_qty, + sum(l_extendedprice) as sum_base_price, + sum(l_extendedprice * (1 - l_discount)) as sum_disc_price, + sum(l_extendedprice * (1 - l_discount) * (1 + l_tax)) as sum_charge, + avg(l_quantity) as avg_qty, + avg(l_extendedprice) as avg_price, + avg(l_discount) as avg_disc, + count(*) as count_order +FROM + lineitem +WHERE + l_shipdate <= date '1998-12-01' - interval '90 days' +GROUP BY + l_returnflag, + l_linestatus +ORDER BY + l_returnflag, + l_linestatus; + +-- Query #6 from the TPC-H decision support benchmark. + +SELECT + sum(l_extendedprice * l_discount) as revenue +FROM + lineitem +WHERE + l_shipdate >= date '1994-01-01' + and l_shipdate < date '1994-01-01' + interval '1 year' + and l_discount between 0.06 - 0.01 and 0.06 + 0.01 + and l_quantity < 24; diff --git a/src/test/regress/input/multi_fdw_stage_data.source b/src/test/regress/input/multi_fdw_stage_data.source new file mode 100644 index 000000000..67e45d351 --- /dev/null +++ b/src/test/regress/input/multi_fdw_stage_data.source @@ -0,0 +1,17 @@ +-- +-- MULTI_FDW_STAGE_DATA +-- + +-- Tests for staging foreign data in a distributed cluster. + +\STAGE lineitem FROM '@abs_srcdir@/data/lineitem.1.data' +\STAGE lineitem FROM '@abs_srcdir@/data/lineitem.2.data' + +\STAGE orders FROM '@abs_srcdir@/data/orders.1.data' +\STAGE orders FROM '@abs_srcdir@/data/orders.2.data' + +SELECT set_config('citusdb.shard_replication_factor', '1', false); + +\STAGE customer FROM '@abs_srcdir@/data/customer.1.data' +\STAGE nation FROM '@abs_srcdir@/data/nation.data' +\STAGE part FROM '@abs_srcdir@/data/part.data' diff --git a/src/test/regress/input/multi_large_shardid.source b/src/test/regress/input/multi_large_shardid.source new file mode 100644 index 000000000..99f96a7df --- /dev/null +++ b/src/test/regress/input/multi_large_shardid.source @@ -0,0 +1,50 @@ +-- +-- MULTI_LARGE_SHARDID +-- + +-- Stage data to distributed tables, and run TPC-H query #1 and #6. This test +-- differs from previous tests in that it modifies the *internal* shardId +-- generator, forcing the distributed database to use 64-bit shard identifiers. + +ALTER SEQUENCE pg_catalog.pg_dist_shardid_seq RESTART 100200300400500; + +-- Stage additional data to start using large shard identifiers. + +\STAGE lineitem FROM '@abs_srcdir@/data/lineitem.1.data' with delimiter '|' +\STAGE lineitem FROM '@abs_srcdir@/data/lineitem.2.data' with delimiter '|' + +-- Query #1 from the TPC-H decision support benchmark. + +SELECT + l_returnflag, + l_linestatus, + sum(l_quantity) as sum_qty, + sum(l_extendedprice) as sum_base_price, + sum(l_extendedprice * (1 - l_discount)) as sum_disc_price, + sum(l_extendedprice * (1 - l_discount) * (1 + l_tax)) as sum_charge, + avg(l_quantity) as avg_qty, + avg(l_extendedprice) as avg_price, + avg(l_discount) as avg_disc, + count(*) as count_order +FROM + lineitem +WHERE + l_shipdate <= date '1998-12-01' - interval '90 days' +GROUP BY + l_returnflag, + l_linestatus +ORDER BY + l_returnflag, + l_linestatus; + +-- Query #6 from the TPC-H decision support benchmark. + +SELECT + sum(l_extendedprice * l_discount) as revenue +FROM + lineitem +WHERE + l_shipdate >= date '1994-01-01' + and l_shipdate < date '1994-01-01' + interval '1 year' + and l_discount between 0.06 - 0.01 and 0.06 + 0.01 + and l_quantity < 24; diff --git a/src/test/regress/input/multi_master_delete_protocol.source b/src/test/regress/input/multi_master_delete_protocol.source new file mode 100644 index 000000000..bafece8dd --- /dev/null +++ b/src/test/regress/input/multi_master_delete_protocol.source @@ -0,0 +1,48 @@ +-- +-- MULTI_MASTER_DELETE_PROTOCOL +-- + +-- Create a new range partitioned customer_delete_protocol table and stage data into it. + +CREATE TABLE customer_delete_protocol ( + c_custkey integer not null, + c_name varchar(25) not null, + c_address varchar(40) not null, + c_nationkey integer not null, + c_phone char(15) not null, + c_acctbal decimal(15,2) not null, + c_mktsegment char(10) not null, + c_comment varchar(117) not null); +SELECT master_create_distributed_table('customer_delete_protocol', 'c_custkey', 'append'); + +\STAGE customer_delete_protocol FROM '@abs_srcdir@/data/customer.1.data' with delimiter '|' +\STAGE customer_delete_protocol FROM '@abs_srcdir@/data/customer.2.data' with delimiter '|' +\STAGE customer_delete_protocol FROM '@abs_srcdir@/data/customer.3.data' with delimiter '|' + +-- Check that we don't support conditions on columns other than partition key. + +SELECT master_apply_delete_command('DELETE FROM customer_delete_protocol + WHERE c_acctbal > 0.0'); + +-- Check that we delete a shard if and only if all rows in the shard satisfy the condition. + +SELECT master_apply_delete_command('DELETE FROM customer_delete_protocol + WHERE c_custkey > 6500'); +SELECT count(*) from customer_delete_protocol; + +-- Delete one shard that satisfies the given conditions. + +SELECT master_apply_delete_command('DELETE FROM customer_delete_protocol + WHERE c_custkey > 1000 AND c_custkey < 3000'); +SELECT count(*) from customer_delete_protocol; + +-- Delete all shards if no condition is provided. + +SELECT master_apply_delete_command('DELETE FROM customer_delete_protocol'); +SELECT count(*) FROM customer_delete_protocol; + +-- Verify that empty shards are deleted if no condition is provided +SELECT master_create_empty_shard('customer_delete_protocol'); +SELECT master_apply_delete_command('DELETE FROM customer_delete_protocol + WHERE c_custkey > 1000'); +SELECT master_apply_delete_command('DELETE FROM customer_delete_protocol'); diff --git a/src/test/regress/input/multi_outer_join.source b/src/test/regress/input/multi_outer_join.source new file mode 100644 index 000000000..7b46790ce --- /dev/null +++ b/src/test/regress/input/multi_outer_join.source @@ -0,0 +1,383 @@ +SET citusdb.large_table_shard_count TO 2; +SET citusdb.log_multi_join_order to true; +SET client_min_messages TO LOG; + +CREATE TABLE multi_outer_join_left +( + l_custkey integer not null, + l_name varchar(25) not null, + l_address varchar(40) not null, + l_nationkey integer not null, + l_phone char(15) not null, + l_acctbal decimal(15,2) not null, + l_mktsegment char(10) not null, + l_comment varchar(117) not null +); +SELECT master_create_distributed_table('multi_outer_join_left', 'l_custkey', 'append'); + +CREATE TABLE multi_outer_join_right +( + r_custkey integer not null, + r_name varchar(25) not null, + r_address varchar(40) not null, + r_nationkey integer not null, + r_phone char(15) not null, + r_acctbal decimal(15,2) not null, + r_mktsegment char(10) not null, + r_comment varchar(117) not null +); +SELECT master_create_distributed_table('multi_outer_join_right', 'r_custkey', 'append'); + +CREATE TABLE multi_outer_join_third +( + t_custkey integer not null, + t_name varchar(25) not null, + t_address varchar(40) not null, + t_nationkey integer not null, + t_phone char(15) not null, + t_acctbal decimal(15,2) not null, + t_mktsegment char(10) not null, + t_comment varchar(117) not null +); +SELECT master_create_distributed_table('multi_outer_join_third', 't_custkey', 'append'); + +-- Make sure we do not crash if both tables have no shards +SELECT + min(l_custkey), max(l_custkey) +FROM + multi_outer_join_left a LEFT JOIN multi_outer_join_third b ON (l_custkey = t_custkey); + +-- Left table is a large table +\STAGE multi_outer_join_left FROM '@abs_srcdir@/data/customer-1-10.data' with delimiter '|' +\STAGE multi_outer_join_left FROM '@abs_srcdir@/data/customer-11-20.data' with delimiter '|' + +-- Right table is a small table +\STAGE multi_outer_join_right FROM '@abs_srcdir@/data/customer-1-15.data' with delimiter '|' + +-- Make sure we do not crash if one table has no shards +SELECT + min(l_custkey), max(l_custkey) +FROM + multi_outer_join_left a LEFT JOIN multi_outer_join_third b ON (l_custkey = t_custkey); + +SELECT + min(t_custkey), max(t_custkey) +FROM + multi_outer_join_third a LEFT JOIN multi_outer_join_right b ON (r_custkey = t_custkey); + +-- Third table is a single shard table with all data +\STAGE multi_outer_join_third FROM '@abs_srcdir@/data/customer-1-30.data' with delimiter '|' + +-- Regular outer join should return results for all rows +SELECT + min(l_custkey), max(l_custkey) +FROM + multi_outer_join_left a LEFT JOIN multi_outer_join_right b ON (l_custkey = r_custkey); + +-- Since this is a broadcast join, we should be able to join on any key +SELECT + count(*) +FROM + multi_outer_join_left a LEFT JOIN multi_outer_join_right b ON (l_nationkey = r_nationkey); + + +-- Anti-join should return customers for which there is no row in the right table +SELECT + min(l_custkey), max(l_custkey) +FROM + multi_outer_join_left a LEFT JOIN multi_outer_join_right b ON (l_custkey = r_custkey) +WHERE + r_custkey IS NULL; + + +-- Partial anti-join with specific value +SELECT + min(l_custkey), max(l_custkey) +FROM + multi_outer_join_left a LEFT JOIN multi_outer_join_right b ON (l_custkey = r_custkey) +WHERE + r_custkey IS NULL OR r_custkey = 5; + + +-- This query is an INNER JOIN in disguise since there cannot be NULL results +SELECT + min(l_custkey), max(l_custkey) +FROM + multi_outer_join_left a LEFT JOIN multi_outer_join_right b ON (l_custkey = r_custkey) +WHERE + r_custkey = 5; + + +-- Right join should be disallowed in this case +SELECT + min(r_custkey), max(r_custkey) +FROM + multi_outer_join_left a RIGHT JOIN multi_outer_join_right b ON (l_custkey = r_custkey); + + +-- Reverse right join should be same as left join +SELECT + min(l_custkey), max(l_custkey) +FROM + multi_outer_join_right a RIGHT JOIN multi_outer_join_left b ON (l_custkey = r_custkey); + + +-- Turn the right table into a large table +\STAGE multi_outer_join_right FROM '@abs_srcdir@/data/customer-21-30.data' with delimiter '|' + + +-- Shards do not have 1-1 matching. We should error here. +SELECT + min(l_custkey), max(l_custkey) +FROM + multi_outer_join_left a LEFT JOIN multi_outer_join_right b ON (l_custkey = r_custkey); + +-- empty tables +SELECT * FROM master_apply_delete_command('DELETE FROM multi_outer_join_left'); +SELECT * FROM master_apply_delete_command('DELETE FROM multi_outer_join_right'); + +-- reload shards with 1-1 matching +\STAGE multi_outer_join_left FROM '@abs_srcdir@/data/customer-1-15.data' with delimiter '|' +\STAGE multi_outer_join_left FROM '@abs_srcdir@/data/customer-21-30.data' with delimiter '|' + +\STAGE multi_outer_join_right FROM '@abs_srcdir@/data/customer-11-20.data' with delimiter '|' +\STAGE multi_outer_join_right FROM '@abs_srcdir@/data/customer-21-30.data' with delimiter '|' + +-- multi_outer_join_third is a single shard table + +-- Regular left join should work as expected +SELECT + min(l_custkey), max(l_custkey) +FROM + multi_outer_join_left a LEFT JOIN multi_outer_join_right b ON (l_custkey = r_custkey); + + +-- Since we cannot broadcast or re-partition, joining on a different key should error out +SELECT + count(*) +FROM + multi_outer_join_left a LEFT JOIN multi_outer_join_right b ON (l_nationkey = r_nationkey); + + +-- Anti-join should return customers for which there is no row in the right table +SELECT + min(l_custkey), max(l_custkey) +FROM + multi_outer_join_left a LEFT JOIN multi_outer_join_right b ON (l_custkey = r_custkey) +WHERE + r_custkey IS NULL; + + +-- Partial anti-join with specific value (5, 11-15) +SELECT + min(l_custkey), max(l_custkey) +FROM + multi_outer_join_left a LEFT JOIN multi_outer_join_right b ON (l_custkey = r_custkey) +WHERE + r_custkey IS NULL OR r_custkey = 15; + + +-- This query is an INNER JOIN in disguise since there cannot be NULL results (21) +SELECT + min(l_custkey), max(l_custkey) +FROM + multi_outer_join_left a LEFT JOIN multi_outer_join_right b ON (l_custkey = r_custkey) +WHERE + r_custkey = 21; + + +-- Right join should be allowed in this case +SELECT + min(r_custkey), max(r_custkey) +FROM + multi_outer_join_left a RIGHT JOIN multi_outer_join_right b ON (l_custkey = r_custkey); + + +-- Reverse right join should be same as left join +SELECT + min(l_custkey), max(l_custkey) +FROM + multi_outer_join_right a RIGHT JOIN multi_outer_join_left b ON (l_custkey = r_custkey); + + +-- complex query tree should error out +SELECT + * +FROM + multi_outer_join_left l1 + LEFT JOIN multi_outer_join_right r1 ON (l1.l_custkey = r1.r_custkey) + LEFT JOIN multi_outer_join_right r2 ON (l1.l_custkey = r2.r_custkey) + RIGHT JOIN multi_outer_join_left l2 ON (r2.r_custkey = l2.l_custkey); + +-- add an anti-join, this should also error out +SELECT + * +FROM + multi_outer_join_left l1 + LEFT JOIN multi_outer_join_right r1 ON (l1.l_custkey = r1.r_custkey) + LEFT JOIN multi_outer_join_right r2 ON (l1.l_custkey = r2.r_custkey) + RIGHT JOIN multi_outer_join_left l2 ON (r2.r_custkey = l2.l_custkey) +WHERE + r1.r_custkey is NULL; + +-- Three way join 2-2-1 (local + broadcast join) should work +SELECT + l_custkey, r_custkey, t_custkey +FROM + multi_outer_join_left l1 + LEFT JOIN multi_outer_join_right r1 ON (l1.l_custkey = r1.r_custkey) + LEFT JOIN multi_outer_join_third t1 ON (r1.r_custkey = t1.t_custkey); + +-- Right join with single shard right most table should error out +SELECT + l_custkey, r_custkey, t_custkey +FROM + multi_outer_join_left l1 + LEFT JOIN multi_outer_join_right r1 ON (l1.l_custkey = r1.r_custkey) + RIGHT JOIN multi_outer_join_third t1 ON (r1.r_custkey = t1.t_custkey); + +-- Right join with single shard left most table should work +SELECT + t_custkey, r_custkey, l_custkey +FROM + multi_outer_join_third t1 + RIGHT JOIN multi_outer_join_right r1 ON (t1.t_custkey = r1.r_custkey) + LEFT JOIN multi_outer_join_left l1 ON (r1.r_custkey = l1.l_custkey); + +-- Make it anti-join, should display values with l_custkey is null +SELECT + t_custkey, r_custkey, l_custkey +FROM + multi_outer_join_third t1 + RIGHT JOIN multi_outer_join_right r1 ON (t1.t_custkey = r1.r_custkey) + LEFT JOIN multi_outer_join_left l1 ON (r1.r_custkey = l1.l_custkey) +WHERE + l_custkey is NULL; + +-- Cascading right join with single shard left most table should error out +SELECT + t_custkey, r_custkey, l_custkey +FROM + multi_outer_join_third t1 + RIGHT JOIN multi_outer_join_right r1 ON (t1.t_custkey = r1.r_custkey) + RIGHT JOIN multi_outer_join_left l1 ON (r1.r_custkey = l1.l_custkey); + +-- full outer join should work with 1-1 matched shards +SELECT + l_custkey, r_custkey +FROM + multi_outer_join_left l1 + FULL JOIN multi_outer_join_right r1 ON (l1.l_custkey = r1.r_custkey); + +-- full outer join + anti (right) should work with 1-1 matched shards +SELECT + l_custkey, r_custkey +FROM + multi_outer_join_left l1 + FULL JOIN multi_outer_join_right r1 ON (l1.l_custkey = r1.r_custkey) +WHERE + r_custkey is NULL; + +-- full outer join + anti (left) should work with 1-1 matched shards +SELECT + l_custkey, r_custkey +FROM + multi_outer_join_left l1 + FULL JOIN multi_outer_join_right r1 ON (l1.l_custkey = r1.r_custkey) +WHERE + l_custkey is NULL; + +-- full outer join + anti (both) should work with 1-1 matched shards +SELECT + l_custkey, r_custkey +FROM + multi_outer_join_left l1 + FULL JOIN multi_outer_join_right r1 ON (l1.l_custkey = r1.r_custkey) +WHERE + l_custkey is NULL or r_custkey is NULL; + +-- full outer join should error out for mismatched shards +SELECT + l_custkey, t_custkey +FROM + multi_outer_join_left l1 + FULL JOIN multi_outer_join_third t1 ON (l1.l_custkey = t1.t_custkey); + +-- inner join + single shard left join should work +SELECT + l_custkey, r_custkey, t_custkey +FROM + multi_outer_join_left l1 + INNER JOIN multi_outer_join_right r1 ON (l1.l_custkey = r1.r_custkey) + LEFT JOIN multi_outer_join_third t1 ON (r1.r_custkey = t1.t_custkey); + +-- inner (broadcast) join + 2 shards left (local) join should work +SELECT + l_custkey, t_custkey, r_custkey +FROM + multi_outer_join_left l1 + INNER JOIN multi_outer_join_third t1 ON (l1.l_custkey = t1.t_custkey) + LEFT JOIN multi_outer_join_right r1 ON (l1.l_custkey = r1.r_custkey); + +-- inner (local) join + 2 shards left (dual partition) join should error out +SELECT + t_custkey, l_custkey, r_custkey +FROM + multi_outer_join_third t1 + INNER JOIN multi_outer_join_left l1 ON (l1.l_custkey = t1.t_custkey) + LEFT JOIN multi_outer_join_right r1 ON (l1.l_custkey = r1.r_custkey); + +-- inner (local) join + 2 shards left (dual partition) join should error out +SELECT + l_custkey, t_custkey, r_custkey +FROM + multi_outer_join_left l1 + INNER JOIN multi_outer_join_third t1 ON (l1.l_custkey = t1.t_custkey) + LEFT JOIN multi_outer_join_right r1 ON (l1.l_custkey = r1.r_custkey); + +-- inner (broadcast) join + 2 shards left (local) + anti join should work +SELECT + l_custkey, t_custkey, r_custkey +FROM + multi_outer_join_left l1 + INNER JOIN multi_outer_join_third t1 ON (l1.l_custkey = t1.t_custkey) + LEFT JOIN multi_outer_join_right r1 ON (l1.l_custkey = r1.r_custkey) +WHERE + r_custkey is NULL; + +-- Test joinExpr aliases by performing an outer-join. +SELECT + t_custkey +FROM + (multi_outer_join_right r1 + LEFT OUTER JOIN multi_outer_join_left l1 ON (l1.l_custkey = r1.r_custkey)) AS + test(c_custkey, c_nationkey) + INNER JOIN multi_outer_join_third t1 ON (test.c_custkey = t1.t_custkey); + +-- Add a shard to the left table that overlaps with multiple shards in the right +\STAGE multi_outer_join_left FROM '@abs_srcdir@/data/customer.1.data' with delimiter '|' + + +-- All outer joins should error out +SELECT + min(l_custkey), max(l_custkey) +FROM + multi_outer_join_left a LEFT JOIN multi_outer_join_right b ON (l_custkey = r_custkey); + +SELECT + min(l_custkey), max(l_custkey) +FROM + multi_outer_join_left a RIGHT JOIN multi_outer_join_right b ON (l_custkey = r_custkey); + +SELECT + min(l_custkey), max(l_custkey) +FROM + multi_outer_join_left a FULL JOIN multi_outer_join_right b ON (l_custkey = r_custkey); + +SELECT + t_custkey +FROM + (multi_outer_join_right r1 + LEFT OUTER JOIN multi_outer_join_left l1 ON (l1.l_custkey = r1.r_custkey)) AS + test(c_custkey, c_nationkey) + INNER JOIN multi_outer_join_third t1 ON (test.c_custkey = t1.t_custkey); diff --git a/src/test/regress/input/multi_stage_data.source b/src/test/regress/input/multi_stage_data.source new file mode 100644 index 000000000..3e093f9ed --- /dev/null +++ b/src/test/regress/input/multi_stage_data.source @@ -0,0 +1,33 @@ +-- +-- MULTI_STAGE_DATA +-- + +-- Tests for staging data in a distributed cluster. Please note that the number +-- of shards uploaded depends on two config values: citusdb.shard_replication_factor and +-- citusdb.shard_max_size. These values are manually set in pg_regress.c. We also set +-- the shard placement policy to the local-node-first policy as other regression +-- tests expect the placements to be in that order. + +SET citusdb.shard_placement_policy TO 'local-node-first'; + +\STAGE lineitem FROM '@abs_srcdir@/data/lineitem.1.data' with delimiter '|' +\STAGE lineitem FROM '@abs_srcdir@/data/lineitem.2.data' with delimiter '|' + +\STAGE orders FROM '@abs_srcdir@/data/orders.1.data' with delimiter '|' +\STAGE orders FROM '@abs_srcdir@/data/orders.2.data' with delimiter '|' + +\STAGE customer FROM '@abs_srcdir@/data/customer.1.data' with delimiter '|' +\STAGE nation FROM '@abs_srcdir@/data/nation.data' with delimiter '|' +\STAGE part FROM '@abs_srcdir@/data/part.data' with delimiter '|' +\STAGE supplier FROM '@abs_srcdir@/data/supplier.data' with delimiter '|' + +-- check that we error out if we try to stage into a hash partitioned table + +CREATE TABLE nation_hash_partitioned ( + n_nationkey integer not null, + n_name char(25) not null, + n_regionkey integer not null, + n_comment varchar(152)); +SELECT master_create_distributed_table('nation_hash_partitioned', 'n_nationkey', 'hash'); + +\STAGE nation_hash_partitioned FROM '@abs_srcdir@/data/nation.data' with delimiter '|' diff --git a/src/test/regress/input/multi_stage_large_records.source b/src/test/regress/input/multi_stage_large_records.source new file mode 100644 index 000000000..5e92bb960 --- /dev/null +++ b/src/test/regress/input/multi_stage_large_records.source @@ -0,0 +1,20 @@ +-- +-- MULTI_STAGE_LARGE_RECORDS +-- + +-- Tests for staging data with large records (i.e. greater than the read buffer +-- size, which is 32kB) in a distributed cluster. These tests make sure that we +-- are creating shards of correct size even when records are large. + +SET citusdb.shard_max_size TO "256kB"; + +CREATE TABLE large_records_table (data_id integer, data text); +SELECT master_create_distributed_table('large_records_table', 'data_id', 'append'); + +\STAGE large_records_table FROM '@abs_srcdir@/data/large_records.data' with delimiter '|' + +SELECT shardminvalue, shardmaxvalue FROM pg_dist_shard, pg_class + WHERE pg_class.oid=logicalrelid AND relname='large_records_table' + ORDER BY shardid; + +RESET citusdb.shard_max_size; diff --git a/src/test/regress/input/multi_stage_more_data.source b/src/test/regress/input/multi_stage_more_data.source new file mode 100644 index 000000000..4b685988a --- /dev/null +++ b/src/test/regress/input/multi_stage_more_data.source @@ -0,0 +1,15 @@ +-- +-- MULTI_STAGE_MORE_DATA +-- + +-- We stage more data to customer and part tables to test distributed joins. The +-- staging causes the planner to consider customer and part tables as large, and +-- evaluate plans where some of the underlying tables need to be repartitioned. +-- We also set the shard placement policy to the local-node-first policy as other +-- regression tests expect the placements to be in that order. + +SET citusdb.shard_placement_policy TO 'local-node-first'; + +\STAGE customer FROM '@abs_srcdir@/data/customer.2.data' with delimiter '|' +\STAGE customer FROM '@abs_srcdir@/data/customer.3.data' with delimiter '|' +\STAGE part FROM '@abs_srcdir@/data/part.more.data' with delimiter '|' diff --git a/src/test/regress/input/multi_subquery.source b/src/test/regress/input/multi_subquery.source new file mode 100644 index 000000000..c4d8bb86f --- /dev/null +++ b/src/test/regress/input/multi_subquery.source @@ -0,0 +1,296 @@ +-- +-- MULTI_SUBQUERY +-- + +-- Create tables for subquery tests + +CREATE TABLE lineitem_subquery ( + l_orderkey bigint not null, + l_partkey integer not null, + l_suppkey integer not null, + l_linenumber integer not null, + l_quantity decimal(15, 2) not null, + l_extendedprice decimal(15, 2) not null, + l_discount decimal(15, 2) not null, + l_tax decimal(15, 2) not null, + l_returnflag char(1) not null, + l_linestatus char(1) not null, + l_shipdate date not null, + l_commitdate date not null, + l_receiptdate date not null, + l_shipinstruct char(25) not null, + l_shipmode char(10) not null, + l_comment varchar(44) not null, + PRIMARY KEY(l_orderkey, l_linenumber) ); +SELECT master_create_distributed_table('lineitem_subquery', 'l_orderkey', 'range'); + +CREATE TABLE orders_subquery ( + o_orderkey bigint not null, + o_custkey integer not null, + o_orderstatus char(1) not null, + o_totalprice decimal(15,2) not null, + o_orderdate date not null, + o_orderpriority char(15) not null, + o_clerk char(15) not null, + o_shippriority integer not null, + o_comment varchar(79) not null, + PRIMARY KEY(o_orderkey) ); +SELECT master_create_distributed_table('orders_subquery', 'o_orderkey', 'range'); + +SET citusdb.task_executor_type TO 'task-tracker'; + +-- Check that we don't allow subquery pushdown in default settings. + +SELECT + avg(unit_price) +FROM + (SELECT + l_orderkey, + avg(o_totalprice) AS unit_price + FROM + lineitem_subquery, + orders_subquery + WHERE + l_orderkey = o_orderkey + GROUP BY + l_orderkey) AS unit_prices; + +SET citusdb.subquery_pushdown to TRUE; + +-- Check that we don't crash if there are not any shards. + +SELECT + avg(unit_price) +FROM + (SELECT + l_orderkey, + avg(o_totalprice) AS unit_price + FROM + lineitem_subquery, + orders_subquery + WHERE + l_orderkey = o_orderkey + GROUP BY + l_orderkey) AS unit_prices; + +-- Stage data to tables. + +SET citusdb.shard_max_size TO "1MB"; + +\STAGE lineitem_subquery FROM '@abs_srcdir@/data/lineitem.1.data' with delimiter '|' +\STAGE lineitem_subquery FROM '@abs_srcdir@/data/lineitem.2.data' with delimiter '|' + +\STAGE orders_subquery FROM '@abs_srcdir@/data/orders.1.data' with delimiter '|' +\STAGE orders_subquery FROM '@abs_srcdir@/data/orders.2.data' with delimiter '|' + +-- Check that we error out if shard min/max values are not exactly same. + +SELECT + avg(unit_price) +FROM + (SELECT + l_orderkey, + avg(o_totalprice) AS unit_price + FROM + lineitem_subquery, + orders_subquery + WHERE + l_orderkey = o_orderkey + GROUP BY + l_orderkey) AS unit_prices; + +-- Update metadata in order to make all shards equal. + +UPDATE pg_dist_shard SET shardmaxvalue = '14947' WHERE shardid = 102024; + +-- If group by is not on partition column then we error out. + +SELECT + avg(order_count) +FROM + (SELECT + l_suppkey, + count(*) AS order_count + FROM + lineitem_subquery + GROUP BY + l_suppkey) AS order_counts; + +-- Check that we error out if join is not on partition columns. + +SELECT + avg(unit_price) +FROM + (SELECT + l_orderkey, + avg(o_totalprice / l_quantity) AS unit_price + FROM + lineitem_subquery, + orders_subquery + GROUP BY + l_orderkey) AS unit_prices; + +SELECT + avg(unit_price) +FROM + (SELECT + l_orderkey, + avg(o_totalprice / l_quantity) AS unit_price + FROM + lineitem_subquery, + orders_subquery + WHERE + l_orderkey = o_custkey + GROUP BY + l_orderkey) AS unit_prices; + +-- Check that we error out if there is union all. + +SELECT count(*) FROM +( + (SELECT l_orderkey FROM lineitem_subquery) UNION ALL + (SELECT 1::bigint) +) b; + +-- Check that we error out if queries in union do not include partition columns. + +SELECT count(*) FROM +( + (SELECT l_orderkey FROM lineitem_subquery) UNION + (SELECT l_partkey FROM lineitem_subquery) +) b; + +-- Check that we run union queries if partition column is selected. + +SELECT count(*) FROM +( + (SELECT l_orderkey FROM lineitem_subquery) UNION + (SELECT l_orderkey FROM lineitem_subquery) +) b; + +-- Check that we error out if the outermost query has subquery join. + +SELECT + avg(o_totalprice/l_quantity) +FROM + (SELECT + l_orderkey, + l_quantity + FROM + lineitem_subquery + ORDER BY + l_quantity + LIMIT 10 + ) lineitem_quantities + JOIN LATERAL + (SELECT + o_totalprice + FROM + orders_subquery + WHERE + lineitem_quantities.l_orderkey = o_orderkey) orders_price ON true; + +-- Check that we error out if the outermost query is a distinct clause. + +SELECT + count(DISTINCT a) +FROM ( + SELECT + count(*) a + FROM + lineitem_subquery +) z; + +-- Check supported subquery types. + +SELECT + o_custkey, + sum(order_count) as total_order_count +FROM + (SELECT + o_orderkey, + o_custkey, + count(*) AS order_count + FROM + orders_subquery + WHERE + o_orderkey > 0 AND + o_orderkey < 12000 + GROUP BY + o_orderkey, o_custkey) AS order_counts +GROUP BY + o_custkey +ORDER BY + total_order_count DESC, + o_custkey ASC +LIMIT 10; + +SELECT + avg(unit_price) +FROM + (SELECT + l_orderkey, + avg(o_totalprice / l_quantity) AS unit_price + FROM + lineitem_subquery, + orders_subquery + WHERE + l_orderkey = o_orderkey + GROUP BY + l_orderkey) AS unit_prices +WHERE + unit_price > 1000 AND + unit_price < 10000; + +-- Check that if subquery is pulled, we don't error and run query properly. + +SELECT count(*) FROM +( + SELECT l_orderkey FROM ( + (SELECT l_orderkey FROM lineitem_subquery) UNION + (SELECT l_orderkey FROM lineitem_subquery) + ) a + WHERE l_orderkey = 1 +) b; + +SELECT count(*) FROM +( + SELECT * FROM ( + (SELECT * FROM lineitem_subquery) UNION + (SELECT * FROM lineitem_subquery) + ) a + WHERE l_orderkey = 1 +) b; + +SELECT max(l_orderkey) FROM +( + SELECT l_orderkey FROM ( + SELECT + l_orderkey + FROM + lineitem_subquery + WHERE + l_orderkey < 20000 + GROUP BY + l_orderkey + ) z +) y; + +-- Load more data to one relation, then test if we error out because of different +-- shard counts for joining relations. + +\STAGE orders_subquery FROM '@abs_srcdir@/data/orders.1.data' with delimiter '|' + +SELECT + avg(unit_price) +FROM + (SELECT + l_orderkey, + avg(o_totalprice / l_quantity) AS unit_price + FROM + lineitem_subquery, + orders_subquery + WHERE + l_orderkey = o_orderkey + GROUP BY + l_orderkey) AS unit_prices; diff --git a/src/test/regress/input/worker_copy.source b/src/test/regress/input/worker_copy.source new file mode 100644 index 000000000..0aba63e76 --- /dev/null +++ b/src/test/regress/input/worker_copy.source @@ -0,0 +1,8 @@ +-- +-- WORKER_COPY +-- + +COPY lineitem FROM '@abs_srcdir@/data/lineitem.1.data' WITH DELIMITER '|'; +COPY lineitem FROM '@abs_srcdir@/data/lineitem.2.data' WITH DELIMITER '|'; + +COPY supplier FROM '@abs_srcdir@/data/supplier.data' WITH DELIMITER '|'; diff --git a/src/test/regress/multi_fdw_schedule b/src/test/regress/multi_fdw_schedule new file mode 100644 index 000000000..9165da4ac --- /dev/null +++ b/src/test/regress/multi_fdw_schedule @@ -0,0 +1,24 @@ +# ---------- +# $Id$ +# +# Regression tests that exercise distributed foreign data wrappers functionality. +# ---------- + +# ---------- +# All distributed tests depend on creating a distributed foreign table and uploading +# data to it. +# ---------- +test: multi_fdw_create_table +test: multi_fdw_master_protocol +test: multi_fdw_stage_data + +# ---------- +# Parallel TPC-H tests to check our distributed execution behavior +# ---------- +test: multi_tpch_query1 multi_tpch_query3 multi_tpch_query6 multi_tpch_query10 +test: multi_tpch_query12 multi_tpch_query14 multi_tpch_query19 + +# ---------- +# multi_fdw_large_shardid stages more shards into lineitem, and must come last +# ---------- +test: multi_fdw_large_shardid diff --git a/src/test/regress/multi_schedule b/src/test/regress/multi_schedule new file mode 100644 index 000000000..39ea82a34 --- /dev/null +++ b/src/test/regress/multi_schedule @@ -0,0 +1,125 @@ +# ---------- +# $Id$ +# +# Regression tests that exercise distributed planning/execution functionality. +# +# Note that we use variant comparison files to test version dependent regression +# test results. For more information: +# http://www.postgresql.org/docs/9.5/static/regress-variant.html +# ---------- + +# --- +# Tests around schema changes, these are run first, so there's no preexisting objects. +# --- +test: multi_table_ddl + +# ---------- +# The following distributed tests depend on creating a partitioned table and +# uploading data to it. +# ---------- +test: multi_create_table +test: multi_master_protocol +test: multi_stage_data + +# ---------- +# Miscellaneous tests to check our query planning behavior +# ---------- +test: multi_basic_queries multi_complex_expressions multi_verify_no_subquery +test: multi_subquery +test: multi_single_relation_subquery +test: multi_agg_distinct multi_limit_clause multi_limit_clause_approximate +test: multi_average_expression multi_working_columns +test: multi_array_agg +test: multi_agg_type_conversion multi_count_type_conversion +test: multi_partition_pruning +test: multi_join_pruning multi_hash_pruning +test: multi_null_minmax_value_pruning +test: multi_query_directory_cleanup +test: multi_task_assignment_policy +test: multi_utility_statements +test: multi_dropped_column_aliases +test: multi_verify_no_join_with_alias +test: multi_binary_master_copy_format +test: multi_prepare_sql multi_prepare_plsql + +# ---------- +# Parallel TPC-H tests to check our distributed execution behavior +# ---------- +test: multi_tpch_query1 multi_tpch_query3 multi_tpch_query6 multi_tpch_query10 +test: multi_tpch_query12 multi_tpch_query14 multi_tpch_query19 +test: multi_tpch_query7 multi_tpch_query7_nested + +# ---------- +# Parallel tests to check our join order planning logic. Note that we stage data +# below; and therefore these tests should come after the execution tests. +# ---------- +test: multi_join_order_tpch_small multi_join_order_additional +test: multi_stage_more_data +test: multi_join_order_tpch_large + +# ---------- +# Tests for large-table join planning and execution. +# Be careful when staging new data before these tests, as they +# expect specific shard identifiers in the output. +# ---------- +test: multi_large_table_join_planning +test: multi_large_table_pruning +test: multi_large_table_task_assignment + +# ---------- +# Tests to check our large record staging and shard deletion behavior +# ---------- +test: multi_stage_large_records multi_master_delete_protocol + +# ---------- +# Tests around DDL statements run on distributed tables +# ---------- +test: multi_index_statements multi_alter_table_statements + +# ---------- +# multi_create_schema tests creation, staging and querying of a table in a new +# schema (namespace). +# ---------- +test: multi_create_schema + +# ---------- +# Tests to check if we inform the user about potential caveats of creating new +# databases, schemas, and roles. +# ---------- +test: multi_utility_warnings + +# --------- +# multi_append_table_to_shard stages shards in a way that forces +# shard caching. +# --------- +test: multi_append_table_to_shard + +# --------- +# multi_outer_join stages shards to create different mappings for outer joins +# --------- +test: multi_outer_join + +# --- +# Tests covering mostly modification queries and required preliminary +# functionality related to metadata, shard creation, shard pruning and +# "hacky" copy script for hash partitioned tables. +# Note that the order of the following tests are important. +# --- +test: multi_create_fdw +test: multi_connection_cache +test: multi_distribution_metadata +test: multi_generate_ddl_commands +test: multi_create_shards +test: multi_prune_shard_list +test: multi_repair_shards +test: multi_modifications +test: multi_upsert +test: multi_simple_queries +test: multi_utilities +test: multi_create_insert_proxy +test: multi_data_types + +# ---------- +# multi_large_shardid stages more shards into lineitem +# ---------- +test: multi_large_shardid diff --git a/src/test/regress/output/multi_agg_distinct.source b/src/test/regress/output/multi_agg_distinct.source new file mode 100644 index 000000000..19510dbd0 --- /dev/null +++ b/src/test/regress/output/multi_agg_distinct.source @@ -0,0 +1,99 @@ +-- +-- MULTI_AGG_DISTINCT +-- +-- Create a new range partitioned lineitem table and stage data into it +CREATE TABLE lineitem_range ( + l_orderkey bigint not null, + l_partkey integer not null, + l_suppkey integer not null, + l_linenumber integer not null, + l_quantity decimal(15, 2) not null, + l_extendedprice decimal(15, 2) not null, + l_discount decimal(15, 2) not null, + l_tax decimal(15, 2) not null, + l_returnflag char(1) not null, + l_linestatus char(1) not null, + l_shipdate date not null, + l_commitdate date not null, + l_receiptdate date not null, + l_shipinstruct char(25) not null, + l_shipmode char(10) not null, + l_comment varchar(44) not null ); +SELECT master_create_distributed_table('lineitem_range', 'l_orderkey', 'range'); + master_create_distributed_table +--------------------------------- + +(1 row) + +\STAGE lineitem_range FROM '@abs_srcdir@/data/lineitem.1.data' with delimiter '|' +\STAGE lineitem_range FROM '@abs_srcdir@/data/lineitem.2.data' with delimiter '|' +-- Run aggregate(distinct) on partition column for range partitioned table +SELECT count(distinct l_orderkey) FROM lineitem_range; + count +------- + 2986 +(1 row) + +SELECT avg(distinct l_orderkey) FROM lineitem_range; + avg +----------------------- + 7465.3171466845277964 +(1 row) + +-- Run count(distinct) on join between a range partitioned table and a single +-- sharded table. For this test, we also change a config setting to ensure that +-- we don't repartition any of the tables during the query. +SET citusdb.large_table_shard_count TO 2; +SELECT p_partkey, count(distinct l_orderkey) FROM lineitem_range, part + WHERE l_partkey = p_partkey + GROUP BY p_partkey + ORDER BY p_partkey LIMIT 10; + p_partkey | count +-----------+------- + 18 | 1 + 79 | 1 + 91 | 1 + 149 | 2 + 175 | 1 + 179 | 1 + 182 | 1 + 195 | 1 + 204 | 1 + 222 | 1 +(10 rows) + +RESET citusdb.large_table_shard_count; +-- Check that we don't support count(distinct) on non-partition column, and +-- complex expressions. +SELECT count(distinct l_partkey) FROM lineitem_range; +ERROR: cannot compute aggregate (distinct) +DETAIL: table partitioning is unsuitable for aggregate (distinct) +HINT: You can load the hll extension from contrib packages and enable distinct approximations. +SELECT count(distinct (l_orderkey + 1)) FROM lineitem_range; +ERROR: cannot compute aggregate (distinct) +DETAIL: aggregate (distinct) on complex expressions is unsupported +HINT: You can load the hll extension from contrib packages and enable distinct approximations. +-- Now test append partitioned tables. First run count(distinct) on a single +-- sharded table. +SELECT count(distinct p_mfgr) FROM part; + count +------- + 5 +(1 row) + +SELECT p_mfgr, count(distinct p_partkey) FROM part GROUP BY p_mfgr; + p_mfgr | count +---------------------------+------- + Manufacturer#1 | 193 + Manufacturer#3 | 228 + Manufacturer#5 | 185 + Manufacturer#2 | 190 + Manufacturer#4 | 204 +(5 rows) + +-- We don't support count(distinct) queries if table is append partitioned and +-- has multiple shards +SELECT count(distinct o_orderkey) FROM orders; +ERROR: cannot compute aggregate (distinct) +DETAIL: table partitioning is unsuitable for aggregate (distinct) +HINT: You can load the hll extension from contrib packages and enable distinct approximations. diff --git a/src/test/regress/output/multi_agg_type_conversion.source b/src/test/regress/output/multi_agg_type_conversion.source new file mode 100644 index 000000000..cb73a98cb --- /dev/null +++ b/src/test/regress/output/multi_agg_type_conversion.source @@ -0,0 +1,95 @@ +-- +-- MULTI_AGG_TYPE_CONVERSION +-- +-- Test aggregate type conversions using sums of integers and division operator +SELECT sum(l_suppkey) FROM lineitem; + sum +---------- + 60617976 +(1 row) + +SELECT sum(l_suppkey) / 2 FROM lineitem; + ?column? +---------- + 30308988 +(1 row) + +SELECT sum(l_suppkey) / 2::numeric FROM lineitem; + ?column? +----------------------- + 30308988.000000000000 +(1 row) + +SELECT sum(l_suppkey)::int8 / 2 FROM lineitem; + ?column? +---------- + 30308988 +(1 row) + +-- Create a new table to test type conversions on different types, and stage +-- data into this table. Then, apply aggregate functions and divide / multiply +-- the results to test type conversions. +CREATE TABLE aggregate_type ( + float_value float(20) not null, + double_value float(40) not null, + interval_value interval not null); +SELECT master_create_distributed_table('aggregate_type', 'float_value', 'append'); + master_create_distributed_table +--------------------------------- + +(1 row) + +\STAGE aggregate_type FROM '@abs_srcdir@/data/agg_type.data' +-- Test conversions using aggregates on floats and division +SELECT min(float_value), max(float_value), + sum(float_value), count(float_value), avg(float_value) +FROM aggregate_type; + min | max | sum | count | avg +-----+-----+------+-------+------- + 1 | 4.5 | 10.5 | 4 | 2.625 +(1 row) + +SELECT min(float_value) / 2, max(float_value) / 2, + sum(float_value) / 2, count(float_value) / 2, avg(float_value) / 2 +FROM aggregate_type; + ?column? | ?column? | ?column? | ?column? | ?column? +----------+----------+----------+----------+---------- + 0.5 | 2.25 | 5.25 | 2 | 1.3125 +(1 row) + +-- Test conversions using aggregates on large floats and multiplication +SELECT min(double_value), max(double_value), + sum(double_value), count(double_value), avg(double_value) +FROM aggregate_type; + min | max | sum | count | avg +-------+---------+----------+-------+----------- + 2.343 | 6.34343 | 15.79703 | 4 | 3.9492575 +(1 row) + +SELECT min(double_value) * 2, max(double_value) * 2, + sum(double_value) * 2, count(double_value) * 2, avg(double_value) * 2 +FROM aggregate_type; + ?column? | ?column? | ?column? | ?column? | ?column? +----------+----------+----------+----------+---------- + 4.686 | 12.68686 | 31.59406 | 8 | 7.898515 +(1 row) + +-- Test conversions using aggregates on intervals and division. We also use the +-- default configuration value for IntervalStyle. +SET IntervalStyle TO 'postgres'; +SELECT min(interval_value), max(interval_value), + sum(interval_value), count(interval_value), avg(interval_value) +FROM aggregate_type; + min | max | sum | count | avg +-------------+------------+-------------+-------+------------- + 00:00:23.44 | 00:38:52.9 | 01:23:33.64 | 4 | 00:20:53.41 +(1 row) + +SELECT min(interval_value) / 2, max(interval_value) / 2, + sum(interval_value) / 2, count(interval_value) / 2, avg(interval_value) / 2 +FROM aggregate_type; + ?column? | ?column? | ?column? | ?column? | ?column? +-------------+-------------+-------------+----------+-------------- + 00:00:11.72 | 00:19:26.45 | 00:41:46.82 | 2 | 00:10:26.705 +(1 row) + diff --git a/src/test/regress/output/multi_alter_table_statements.source b/src/test/regress/output/multi_alter_table_statements.source new file mode 100644 index 000000000..90b644d72 --- /dev/null +++ b/src/test/regress/output/multi_alter_table_statements.source @@ -0,0 +1,715 @@ +-- +-- MULTI_ALTER_TABLE_STATEMENTS +-- +-- Check that we can run ALTER TABLE statements on distributed tables. We +-- increase the logging verbosity to verify that commands are propagated to +-- all worker shards. We also set the shardid sequence here so that the shardids +-- in this test aren't affected by changes to the previous tests. +ALTER SEQUENCE pg_catalog.pg_dist_shardid_seq RESTART 103000; +CREATE TABLE lineitem_alter ( + l_orderkey bigint not null, + l_partkey integer not null, + l_suppkey integer not null, + l_linenumber integer not null, + l_quantity decimal(15, 2) not null, + l_extendedprice decimal(15, 2) not null, + l_discount decimal(15, 2) not null, + l_tax decimal(15, 2) not null, + l_returnflag char(1) not null, + l_linestatus char(1) not null, + l_shipdate date not null, + l_commitdate date not null, + l_receiptdate date not null, + l_shipinstruct char(25) not null, + l_shipmode char(10) not null, + l_comment varchar(44) not null + ); +SELECT master_create_distributed_table('lineitem_alter', 'l_orderkey', 'append'); + master_create_distributed_table +--------------------------------- + +(1 row) + +\STAGE lineitem_alter FROM '@abs_srcdir@/data/lineitem.1.data' with delimiter '|' +SET client_min_messages TO DEBUG2; +-- Verify that we can add columns +ALTER TABLE lineitem_alter ADD COLUMN float_column FLOAT; +DEBUG: applied command on shard 103002 on node localhost:57638 +DEBUG: applied command on shard 103002 on node localhost:57637 +DEBUG: applied command on shard 103001 on node localhost:57637 +DEBUG: applied command on shard 103001 on node localhost:57638 +DEBUG: applied command on shard 103000 on node localhost:57638 +DEBUG: applied command on shard 103000 on node localhost:57637 +ALTER TABLE lineitem_alter ADD COLUMN date_column DATE; +DEBUG: applied command on shard 103002 on node localhost:57638 +DEBUG: applied command on shard 103002 on node localhost:57637 +DEBUG: applied command on shard 103001 on node localhost:57637 +DEBUG: applied command on shard 103001 on node localhost:57638 +DEBUG: applied command on shard 103000 on node localhost:57638 +DEBUG: applied command on shard 103000 on node localhost:57637 +ALTER TABLE lineitem_alter ADD COLUMN int_column1 INTEGER DEFAULT 1; +DEBUG: applied command on shard 103002 on node localhost:57638 +DEBUG: applied command on shard 103002 on node localhost:57637 +DEBUG: applied command on shard 103001 on node localhost:57637 +DEBUG: applied command on shard 103001 on node localhost:57638 +DEBUG: applied command on shard 103000 on node localhost:57638 +DEBUG: applied command on shard 103000 on node localhost:57637 +DEBUG: rewriting table "lineitem_alter" +DEBUG: drop auto-cascades to type pg_temp_17666 +DEBUG: drop auto-cascades to type pg_temp_17666[] +ALTER TABLE lineitem_alter ADD COLUMN int_column2 INTEGER DEFAULT 2; +DEBUG: applied command on shard 103002 on node localhost:57638 +DEBUG: applied command on shard 103002 on node localhost:57637 +DEBUG: applied command on shard 103001 on node localhost:57637 +DEBUG: applied command on shard 103001 on node localhost:57638 +DEBUG: applied command on shard 103000 on node localhost:57638 +DEBUG: applied command on shard 103000 on node localhost:57637 +DEBUG: rewriting table "lineitem_alter" +DEBUG: drop auto-cascades to type pg_temp_17666 +DEBUG: drop auto-cascades to type pg_temp_17666[] +ALTER TABLE lineitem_alter ADD COLUMN null_column INTEGER; +DEBUG: applied command on shard 103002 on node localhost:57638 +DEBUG: applied command on shard 103002 on node localhost:57637 +DEBUG: applied command on shard 103001 on node localhost:57637 +DEBUG: applied command on shard 103001 on node localhost:57638 +DEBUG: applied command on shard 103000 on node localhost:57638 +DEBUG: applied command on shard 103000 on node localhost:57637 +\d lineitem_alter + Table "public.lineitem_alter" + Column | Type | Modifiers +-----------------+-----------------------+----------- + l_orderkey | bigint | not null + l_partkey | integer | not null + l_suppkey | integer | not null + l_linenumber | integer | not null + l_quantity | numeric(15,2) | not null + l_extendedprice | numeric(15,2) | not null + l_discount | numeric(15,2) | not null + l_tax | numeric(15,2) | not null + l_returnflag | character(1) | not null + l_linestatus | character(1) | not null + l_shipdate | date | not null + l_commitdate | date | not null + l_receiptdate | date | not null + l_shipinstruct | character(25) | not null + l_shipmode | character(10) | not null + l_comment | character varying(44) | not null + float_column | double precision | + date_column | date | + int_column1 | integer | default 1 + int_column2 | integer | default 2 + null_column | integer | + +SELECT float_column, count(*) FROM lineitem_alter GROUP BY float_column; + float_column | count +--------------+------- + | 6000 +(1 row) + +SELECT int_column1, count(*) FROM lineitem_alter GROUP BY int_column1; + int_column1 | count +-------------+------- + 1 | 6000 +(1 row) + +-- Verify that SET|DROP DEFAULT works +ALTER TABLE lineitem_alter ALTER COLUMN float_column SET DEFAULT 1; +DEBUG: applied command on shard 103002 on node localhost:57638 +DEBUG: applied command on shard 103002 on node localhost:57637 +DEBUG: applied command on shard 103001 on node localhost:57637 +DEBUG: applied command on shard 103001 on node localhost:57638 +DEBUG: applied command on shard 103000 on node localhost:57638 +DEBUG: applied command on shard 103000 on node localhost:57637 +ALTER TABLE lineitem_alter ALTER COLUMN int_column1 DROP DEFAULT; +DEBUG: applied command on shard 103002 on node localhost:57638 +DEBUG: applied command on shard 103002 on node localhost:57637 +DEBUG: applied command on shard 103001 on node localhost:57637 +DEBUG: applied command on shard 103001 on node localhost:57638 +DEBUG: applied command on shard 103000 on node localhost:57638 +DEBUG: applied command on shard 103000 on node localhost:57637 +-- \stage to verify that default values take effect +\STAGE lineitem_alter (l_orderkey, l_partkey, l_suppkey, l_linenumber, l_quantity, l_extendedprice, l_discount, l_tax, l_returnflag, l_linestatus, l_shipdate, l_commitdate, l_receiptdate, l_shipinstruct, l_shipmode, l_comment) FROM '@abs_srcdir@/data/lineitem.1.data' with delimiter '|' +DEBUG: parse : SELECT * FROM master_get_table_metadata($1::text) +DEBUG: bind to +DEBUG: parse : SELECT * FROM master_get_table_ddl_events($1::text) +DEBUG: bind to +DEBUG: parse : SELECT * FROM master_get_new_shardid() +DEBUG: bind to +DEBUG: parse : SELECT * FROM master_get_round_robin_candidate_nodes($1::int8) +DEBUG: bind to +DEBUG: parse : SELECT * FROM master_get_new_shardid() +DEBUG: bind to +DEBUG: parse : SELECT * FROM master_get_round_robin_candidate_nodes($1::int8) +DEBUG: bind to +DEBUG: parse : SELECT * FROM master_get_new_shardid() +DEBUG: bind to +DEBUG: parse : SELECT * FROM master_get_round_robin_candidate_nodes($1::int8) +DEBUG: bind to +DEBUG: parse : INSERT INTO pg_dist_shard (logicalrelid, shardid, shardstorage, shardminvalue, shardmaxvalue) VALUES ($1::oid, $2::int8, $3::char, $4::text, $5::text) +DEBUG: bind to +DEBUG: parse : INSERT INTO pg_dist_shard_placement (shardid, shardstate, shardlength, nodename, nodeport) VALUES ($1::int8, $2::int4, $3::int8, $4::text, $5::int4) +DEBUG: bind to +DEBUG: parse : INSERT INTO pg_dist_shard_placement (shardid, shardstate, shardlength, nodename, nodeport) VALUES ($1::int8, $2::int4, $3::int8, $4::text, $5::int4) +DEBUG: bind to +DEBUG: parse : INSERT INTO pg_dist_shard (logicalrelid, shardid, shardstorage, shardminvalue, shardmaxvalue) VALUES ($1::oid, $2::int8, $3::char, $4::text, $5::text) +DEBUG: bind to +DEBUG: parse : INSERT INTO pg_dist_shard_placement (shardid, shardstate, shardlength, nodename, nodeport) VALUES ($1::int8, $2::int4, $3::int8, $4::text, $5::int4) +DEBUG: bind to +DEBUG: parse : INSERT INTO pg_dist_shard_placement (shardid, shardstate, shardlength, nodename, nodeport) VALUES ($1::int8, $2::int4, $3::int8, $4::text, $5::int4) +DEBUG: bind to +DEBUG: parse : INSERT INTO pg_dist_shard (logicalrelid, shardid, shardstorage, shardminvalue, shardmaxvalue) VALUES ($1::oid, $2::int8, $3::char, $4::text, $5::text) +DEBUG: bind to +DEBUG: parse : INSERT INTO pg_dist_shard_placement (shardid, shardstate, shardlength, nodename, nodeport) VALUES ($1::int8, $2::int4, $3::int8, $4::text, $5::int4) +DEBUG: bind to +DEBUG: parse : INSERT INTO pg_dist_shard_placement (shardid, shardstate, shardlength, nodename, nodeport) VALUES ($1::int8, $2::int4, $3::int8, $4::text, $5::int4) +DEBUG: bind to +SELECT float_column, count(*) FROM lineitem_alter GROUP BY float_column; + float_column | count +--------------+------- + | 6000 + 1 | 6000 +(2 rows) + +SELECT int_column1, count(*) FROM lineitem_alter GROUP BY int_column1; + int_column1 | count +-------------+------- + | 6000 + 1 | 6000 +(2 rows) + +-- Verify that SET NOT NULL works +ALTER TABLE lineitem_alter ALTER COLUMN int_column2 SET NOT NULL; +DEBUG: applied command on shard 103005 on node localhost:57637 +DEBUG: applied command on shard 103005 on node localhost:57638 +DEBUG: applied command on shard 103004 on node localhost:57638 +DEBUG: applied command on shard 103004 on node localhost:57637 +DEBUG: applied command on shard 103003 on node localhost:57637 +DEBUG: applied command on shard 103003 on node localhost:57638 +DEBUG: applied command on shard 103002 on node localhost:57638 +DEBUG: applied command on shard 103002 on node localhost:57637 +DEBUG: applied command on shard 103001 on node localhost:57637 +DEBUG: applied command on shard 103001 on node localhost:57638 +DEBUG: applied command on shard 103000 on node localhost:57638 +DEBUG: applied command on shard 103000 on node localhost:57637 +DEBUG: verifying table "lineitem_alter" +\d lineitem_alter + Table "public.lineitem_alter" + Column | Type | Modifiers +-----------------+-----------------------+-------------------- + l_orderkey | bigint | not null + l_partkey | integer | not null + l_suppkey | integer | not null + l_linenumber | integer | not null + l_quantity | numeric(15,2) | not null + l_extendedprice | numeric(15,2) | not null + l_discount | numeric(15,2) | not null + l_tax | numeric(15,2) | not null + l_returnflag | character(1) | not null + l_linestatus | character(1) | not null + l_shipdate | date | not null + l_commitdate | date | not null + l_receiptdate | date | not null + l_shipinstruct | character(25) | not null + l_shipmode | character(10) | not null + l_comment | character varying(44) | not null + float_column | double precision | default 1 + date_column | date | + int_column1 | integer | + int_column2 | integer | not null default 2 + null_column | integer | + +-- Drop default so that NULLs will be inserted for this column +ALTER TABLE lineitem_alter ALTER COLUMN int_column2 DROP DEFAULT; +DEBUG: applied command on shard 103005 on node localhost:57637 +DEBUG: applied command on shard 103005 on node localhost:57638 +DEBUG: applied command on shard 103004 on node localhost:57638 +DEBUG: applied command on shard 103004 on node localhost:57637 +DEBUG: applied command on shard 103003 on node localhost:57637 +DEBUG: applied command on shard 103003 on node localhost:57638 +DEBUG: applied command on shard 103002 on node localhost:57638 +DEBUG: applied command on shard 103002 on node localhost:57637 +DEBUG: applied command on shard 103001 on node localhost:57637 +DEBUG: applied command on shard 103001 on node localhost:57638 +DEBUG: applied command on shard 103000 on node localhost:57638 +DEBUG: applied command on shard 103000 on node localhost:57637 +-- \stage should fail because it will try to insert NULLs for a NOT NULL column +\STAGE lineitem_alter (l_orderkey, l_partkey, l_suppkey, l_linenumber, l_quantity, l_extendedprice, l_discount, l_tax, l_returnflag, l_linestatus, l_shipdate, l_commitdate, l_receiptdate, l_shipinstruct, l_shipmode, l_comment) FROM '@abs_srcdir@/data/lineitem.1.data' with delimiter '|' +DEBUG: parse : SELECT * FROM master_get_table_metadata($1::text) +DEBUG: bind to +DEBUG: parse : SELECT * FROM master_get_table_ddl_events($1::text) +DEBUG: bind to +DEBUG: parse : SELECT * FROM master_get_new_shardid() +DEBUG: bind to +DEBUG: parse : SELECT * FROM master_get_round_robin_candidate_nodes($1::int8) +DEBUG: bind to +ERROR: null value in column "int_column2" violates not-null constraint +DETAIL: Failing row contains (1, 155190, 7706, 1, 17.00, 21168.23, 0.04, 0.02, N, O, 03-13-1996, 02-12-1996, 03-22-1996, DELIVER IN PERSON , TRUCK , egular courts above the, 1, null, null, null, null). +CONTEXT: COPY lineitem_alter_103006, line 1: "1|155190|7706|1|17|21168.23|0.04|0.02|N|O|1996-03-13|1996-02-12|1996-03-22|DELIVER IN PERSON|TRUCK|e..." +ERROR: null value in column "int_column2" violates not-null constraint +DETAIL: Failing row contains (1, 155190, 7706, 1, 17.00, 21168.23, 0.04, 0.02, N, O, 03-13-1996, 02-12-1996, 03-22-1996, DELIVER IN PERSON , TRUCK , egular courts above the, 1, null, null, null, null). +CONTEXT: COPY lineitem_alter_103006, line 1: "1|155190|7706|1|17|21168.23|0.04|0.02|N|O|1996-03-13|1996-02-12|1996-03-22|DELIVER IN PERSON|TRUCK|e..." +\stage: failed to replicate shard to enough replicas +-- Verify that DROP NOT NULL works +ALTER TABLE lineitem_alter ALTER COLUMN int_column2 DROP NOT NULL; +DEBUG: applied command on shard 103005 on node localhost:57637 +DEBUG: applied command on shard 103005 on node localhost:57638 +DEBUG: applied command on shard 103004 on node localhost:57638 +DEBUG: applied command on shard 103004 on node localhost:57637 +DEBUG: applied command on shard 103003 on node localhost:57637 +DEBUG: applied command on shard 103003 on node localhost:57638 +DEBUG: applied command on shard 103002 on node localhost:57638 +DEBUG: applied command on shard 103002 on node localhost:57637 +DEBUG: applied command on shard 103001 on node localhost:57637 +DEBUG: applied command on shard 103001 on node localhost:57638 +DEBUG: applied command on shard 103000 on node localhost:57638 +DEBUG: applied command on shard 103000 on node localhost:57637 +\d lineitem_alter + Table "public.lineitem_alter" + Column | Type | Modifiers +-----------------+-----------------------+----------- + l_orderkey | bigint | not null + l_partkey | integer | not null + l_suppkey | integer | not null + l_linenumber | integer | not null + l_quantity | numeric(15,2) | not null + l_extendedprice | numeric(15,2) | not null + l_discount | numeric(15,2) | not null + l_tax | numeric(15,2) | not null + l_returnflag | character(1) | not null + l_linestatus | character(1) | not null + l_shipdate | date | not null + l_commitdate | date | not null + l_receiptdate | date | not null + l_shipinstruct | character(25) | not null + l_shipmode | character(10) | not null + l_comment | character varying(44) | not null + float_column | double precision | default 1 + date_column | date | + int_column1 | integer | + int_column2 | integer | + null_column | integer | + +-- \stage should succeed now +\STAGE lineitem_alter (l_orderkey, l_partkey, l_suppkey, l_linenumber, l_quantity, l_extendedprice, l_discount, l_tax, l_returnflag, l_linestatus, l_shipdate, l_commitdate, l_receiptdate, l_shipinstruct, l_shipmode, l_comment) FROM '@abs_srcdir@/data/lineitem.1.data' with delimiter '|' +DEBUG: parse : SELECT * FROM master_get_table_metadata($1::text) +DEBUG: bind to +DEBUG: parse : SELECT * FROM master_get_table_ddl_events($1::text) +DEBUG: bind to +DEBUG: parse : SELECT * FROM master_get_new_shardid() +DEBUG: bind to +DEBUG: parse : SELECT * FROM master_get_round_robin_candidate_nodes($1::int8) +DEBUG: bind to +DEBUG: parse : SELECT * FROM master_get_new_shardid() +DEBUG: bind to +DEBUG: parse : SELECT * FROM master_get_round_robin_candidate_nodes($1::int8) +DEBUG: bind to +DEBUG: parse : SELECT * FROM master_get_new_shardid() +DEBUG: bind to +DEBUG: parse : SELECT * FROM master_get_round_robin_candidate_nodes($1::int8) +DEBUG: bind to +DEBUG: parse : INSERT INTO pg_dist_shard (logicalrelid, shardid, shardstorage, shardminvalue, shardmaxvalue) VALUES ($1::oid, $2::int8, $3::char, $4::text, $5::text) +DEBUG: bind to +DEBUG: parse : INSERT INTO pg_dist_shard_placement (shardid, shardstate, shardlength, nodename, nodeport) VALUES ($1::int8, $2::int4, $3::int8, $4::text, $5::int4) +DEBUG: bind to +DEBUG: parse : INSERT INTO pg_dist_shard_placement (shardid, shardstate, shardlength, nodename, nodeport) VALUES ($1::int8, $2::int4, $3::int8, $4::text, $5::int4) +DEBUG: bind to +DEBUG: parse : INSERT INTO pg_dist_shard (logicalrelid, shardid, shardstorage, shardminvalue, shardmaxvalue) VALUES ($1::oid, $2::int8, $3::char, $4::text, $5::text) +DEBUG: bind to +DEBUG: parse : INSERT INTO pg_dist_shard_placement (shardid, shardstate, shardlength, nodename, nodeport) VALUES ($1::int8, $2::int4, $3::int8, $4::text, $5::int4) +DEBUG: bind to +DEBUG: parse : INSERT INTO pg_dist_shard_placement (shardid, shardstate, shardlength, nodename, nodeport) VALUES ($1::int8, $2::int4, $3::int8, $4::text, $5::int4) +DEBUG: bind to +DEBUG: parse : INSERT INTO pg_dist_shard (logicalrelid, shardid, shardstorage, shardminvalue, shardmaxvalue) VALUES ($1::oid, $2::int8, $3::char, $4::text, $5::text) +DEBUG: bind to +DEBUG: parse : INSERT INTO pg_dist_shard_placement (shardid, shardstate, shardlength, nodename, nodeport) VALUES ($1::int8, $2::int4, $3::int8, $4::text, $5::int4) +DEBUG: bind to +DEBUG: parse : INSERT INTO pg_dist_shard_placement (shardid, shardstate, shardlength, nodename, nodeport) VALUES ($1::int8, $2::int4, $3::int8, $4::text, $5::int4) +DEBUG: bind to +SELECT count(*) from lineitem_alter; + count +------- + 18000 +(1 row) + +-- Verify that SET DATA TYPE works +SELECT int_column2, pg_typeof(int_column2), count(*) from lineitem_alter GROUP BY int_column2; + int_column2 | pg_typeof | count +-------------+-----------+------- + | integer | 6000 + 2 | integer | 12000 +(2 rows) + +ALTER TABLE lineitem_alter ALTER COLUMN int_column2 SET DATA TYPE FLOAT; +DEBUG: applied command on shard 103009 on node localhost:57637 +DEBUG: applied command on shard 103009 on node localhost:57638 +DEBUG: applied command on shard 103008 on node localhost:57638 +DEBUG: applied command on shard 103008 on node localhost:57637 +DEBUG: applied command on shard 103007 on node localhost:57637 +DEBUG: applied command on shard 103007 on node localhost:57638 +DEBUG: applied command on shard 103005 on node localhost:57637 +DEBUG: applied command on shard 103005 on node localhost:57638 +DEBUG: applied command on shard 103004 on node localhost:57638 +DEBUG: applied command on shard 103004 on node localhost:57637 +DEBUG: applied command on shard 103003 on node localhost:57637 +DEBUG: applied command on shard 103003 on node localhost:57638 +DEBUG: applied command on shard 103002 on node localhost:57638 +DEBUG: applied command on shard 103002 on node localhost:57637 +DEBUG: applied command on shard 103001 on node localhost:57637 +DEBUG: applied command on shard 103001 on node localhost:57638 +DEBUG: applied command on shard 103000 on node localhost:57638 +DEBUG: applied command on shard 103000 on node localhost:57637 +DEBUG: rewriting table "lineitem_alter" +DEBUG: drop auto-cascades to type pg_temp_17666 +DEBUG: drop auto-cascades to type pg_temp_17666[] +\d lineitem_alter + Table "public.lineitem_alter" + Column | Type | Modifiers +-----------------+-----------------------+----------- + l_orderkey | bigint | not null + l_partkey | integer | not null + l_suppkey | integer | not null + l_linenumber | integer | not null + l_quantity | numeric(15,2) | not null + l_extendedprice | numeric(15,2) | not null + l_discount | numeric(15,2) | not null + l_tax | numeric(15,2) | not null + l_returnflag | character(1) | not null + l_linestatus | character(1) | not null + l_shipdate | date | not null + l_commitdate | date | not null + l_receiptdate | date | not null + l_shipinstruct | character(25) | not null + l_shipmode | character(10) | not null + l_comment | character varying(44) | not null + float_column | double precision | default 1 + date_column | date | + int_column1 | integer | + int_column2 | double precision | + null_column | integer | + +SELECT int_column2, pg_typeof(int_column2), count(*) from lineitem_alter GROUP BY int_column2; + int_column2 | pg_typeof | count +-------------+------------------+------- + | double precision | 6000 + 2 | double precision | 12000 +(2 rows) + +-- Verify that DROP COLUMN works +ALTER TABLE lineitem_alter DROP COLUMN int_column1; +DEBUG: applied command on shard 103009 on node localhost:57637 +DEBUG: applied command on shard 103009 on node localhost:57638 +DEBUG: applied command on shard 103008 on node localhost:57638 +DEBUG: applied command on shard 103008 on node localhost:57637 +DEBUG: applied command on shard 103007 on node localhost:57637 +DEBUG: applied command on shard 103007 on node localhost:57638 +DEBUG: applied command on shard 103005 on node localhost:57637 +DEBUG: applied command on shard 103005 on node localhost:57638 +DEBUG: applied command on shard 103004 on node localhost:57638 +DEBUG: applied command on shard 103004 on node localhost:57637 +DEBUG: applied command on shard 103003 on node localhost:57637 +DEBUG: applied command on shard 103003 on node localhost:57638 +DEBUG: applied command on shard 103002 on node localhost:57638 +DEBUG: applied command on shard 103002 on node localhost:57637 +DEBUG: applied command on shard 103001 on node localhost:57637 +DEBUG: applied command on shard 103001 on node localhost:57638 +DEBUG: applied command on shard 103000 on node localhost:57638 +DEBUG: applied command on shard 103000 on node localhost:57637 +ALTER TABLE lineitem_alter DROP COLUMN float_column; +DEBUG: applied command on shard 103009 on node localhost:57637 +DEBUG: applied command on shard 103009 on node localhost:57638 +DEBUG: applied command on shard 103008 on node localhost:57638 +DEBUG: applied command on shard 103008 on node localhost:57637 +DEBUG: applied command on shard 103007 on node localhost:57637 +DEBUG: applied command on shard 103007 on node localhost:57638 +DEBUG: applied command on shard 103005 on node localhost:57637 +DEBUG: applied command on shard 103005 on node localhost:57638 +DEBUG: applied command on shard 103004 on node localhost:57638 +DEBUG: applied command on shard 103004 on node localhost:57637 +DEBUG: applied command on shard 103003 on node localhost:57637 +DEBUG: applied command on shard 103003 on node localhost:57638 +DEBUG: applied command on shard 103002 on node localhost:57638 +DEBUG: applied command on shard 103002 on node localhost:57637 +DEBUG: applied command on shard 103001 on node localhost:57637 +DEBUG: applied command on shard 103001 on node localhost:57638 +DEBUG: applied command on shard 103000 on node localhost:57638 +DEBUG: applied command on shard 103000 on node localhost:57637 +DEBUG: drop auto-cascades to default for table lineitem_alter column float_column +ALTER TABLE lineitem_alter DROP COLUMN date_column; +DEBUG: applied command on shard 103009 on node localhost:57637 +DEBUG: applied command on shard 103009 on node localhost:57638 +DEBUG: applied command on shard 103008 on node localhost:57638 +DEBUG: applied command on shard 103008 on node localhost:57637 +DEBUG: applied command on shard 103007 on node localhost:57637 +DEBUG: applied command on shard 103007 on node localhost:57638 +DEBUG: applied command on shard 103005 on node localhost:57637 +DEBUG: applied command on shard 103005 on node localhost:57638 +DEBUG: applied command on shard 103004 on node localhost:57638 +DEBUG: applied command on shard 103004 on node localhost:57637 +DEBUG: applied command on shard 103003 on node localhost:57637 +DEBUG: applied command on shard 103003 on node localhost:57638 +DEBUG: applied command on shard 103002 on node localhost:57638 +DEBUG: applied command on shard 103002 on node localhost:57637 +DEBUG: applied command on shard 103001 on node localhost:57637 +DEBUG: applied command on shard 103001 on node localhost:57638 +DEBUG: applied command on shard 103000 on node localhost:57638 +DEBUG: applied command on shard 103000 on node localhost:57637 +-- Verify that IF EXISTS works as expected +ALTER TABLE non_existent_table ADD COLUMN new_column INTEGER; +ERROR: relation "non_existent_table" does not exist +ALTER TABLE IF EXISTS non_existent_table ADD COLUMN new_column INTEGER; +NOTICE: relation "non_existent_table" does not exist, skipping +ALTER TABLE IF EXISTS lineitem_alter ALTER COLUMN int_column2 SET DATA TYPE INTEGER; +DEBUG: applied command on shard 103009 on node localhost:57637 +DEBUG: applied command on shard 103009 on node localhost:57638 +DEBUG: applied command on shard 103008 on node localhost:57638 +DEBUG: applied command on shard 103008 on node localhost:57637 +DEBUG: applied command on shard 103007 on node localhost:57637 +DEBUG: applied command on shard 103007 on node localhost:57638 +DEBUG: applied command on shard 103005 on node localhost:57637 +DEBUG: applied command on shard 103005 on node localhost:57638 +DEBUG: applied command on shard 103004 on node localhost:57638 +DEBUG: applied command on shard 103004 on node localhost:57637 +DEBUG: applied command on shard 103003 on node localhost:57637 +DEBUG: applied command on shard 103003 on node localhost:57638 +DEBUG: applied command on shard 103002 on node localhost:57638 +DEBUG: applied command on shard 103002 on node localhost:57637 +DEBUG: applied command on shard 103001 on node localhost:57637 +DEBUG: applied command on shard 103001 on node localhost:57638 +DEBUG: applied command on shard 103000 on node localhost:57638 +DEBUG: applied command on shard 103000 on node localhost:57637 +DEBUG: rewriting table "lineitem_alter" +DEBUG: drop auto-cascades to type pg_temp_17666 +DEBUG: drop auto-cascades to type pg_temp_17666[] +ALTER TABLE lineitem_alter DROP COLUMN non_existent_column; +WARNING: could not receive query results from localhost:57637 +DETAIL: Client error: column "non_existent_column" of relation "lineitem_alter_103009" does not exist +ERROR: could not execute DDL command on worker node shards +ALTER TABLE lineitem_alter DROP COLUMN IF EXISTS non_existent_column; +DEBUG: applied command on shard 103009 on node localhost:57637 +DEBUG: applied command on shard 103009 on node localhost:57638 +DEBUG: applied command on shard 103008 on node localhost:57638 +DEBUG: applied command on shard 103008 on node localhost:57637 +DEBUG: applied command on shard 103007 on node localhost:57637 +DEBUG: applied command on shard 103007 on node localhost:57638 +DEBUG: applied command on shard 103005 on node localhost:57637 +DEBUG: applied command on shard 103005 on node localhost:57638 +DEBUG: applied command on shard 103004 on node localhost:57638 +DEBUG: applied command on shard 103004 on node localhost:57637 +DEBUG: applied command on shard 103003 on node localhost:57637 +DEBUG: applied command on shard 103003 on node localhost:57638 +DEBUG: applied command on shard 103002 on node localhost:57638 +DEBUG: applied command on shard 103002 on node localhost:57637 +DEBUG: applied command on shard 103001 on node localhost:57637 +DEBUG: applied command on shard 103001 on node localhost:57638 +DEBUG: applied command on shard 103000 on node localhost:57638 +DEBUG: applied command on shard 103000 on node localhost:57637 +NOTICE: column "non_existent_column" of relation "lineitem_alter" does not exist, skipping +ALTER TABLE lineitem_alter DROP COLUMN IF EXISTS int_column2; +DEBUG: applied command on shard 103009 on node localhost:57637 +DEBUG: applied command on shard 103009 on node localhost:57638 +DEBUG: applied command on shard 103008 on node localhost:57638 +DEBUG: applied command on shard 103008 on node localhost:57637 +DEBUG: applied command on shard 103007 on node localhost:57637 +DEBUG: applied command on shard 103007 on node localhost:57638 +DEBUG: applied command on shard 103005 on node localhost:57637 +DEBUG: applied command on shard 103005 on node localhost:57638 +DEBUG: applied command on shard 103004 on node localhost:57638 +DEBUG: applied command on shard 103004 on node localhost:57637 +DEBUG: applied command on shard 103003 on node localhost:57637 +DEBUG: applied command on shard 103003 on node localhost:57638 +DEBUG: applied command on shard 103002 on node localhost:57638 +DEBUG: applied command on shard 103002 on node localhost:57637 +DEBUG: applied command on shard 103001 on node localhost:57637 +DEBUG: applied command on shard 103001 on node localhost:57638 +DEBUG: applied command on shard 103000 on node localhost:57638 +DEBUG: applied command on shard 103000 on node localhost:57637 +\d lineitem_alter + Table "public.lineitem_alter" + Column | Type | Modifiers +-----------------+-----------------------+----------- + l_orderkey | bigint | not null + l_partkey | integer | not null + l_suppkey | integer | not null + l_linenumber | integer | not null + l_quantity | numeric(15,2) | not null + l_extendedprice | numeric(15,2) | not null + l_discount | numeric(15,2) | not null + l_tax | numeric(15,2) | not null + l_returnflag | character(1) | not null + l_linestatus | character(1) | not null + l_shipdate | date | not null + l_commitdate | date | not null + l_receiptdate | date | not null + l_shipinstruct | character(25) | not null + l_shipmode | character(10) | not null + l_comment | character varying(44) | not null + null_column | integer | + +-- Verify that we can execute commands with multiple subcommands +ALTER TABLE lineitem_alter ADD COLUMN int_column1 INTEGER, + ADD COLUMN int_column2 INTEGER; +DEBUG: applied command on shard 103009 on node localhost:57637 +DEBUG: applied command on shard 103009 on node localhost:57638 +DEBUG: applied command on shard 103008 on node localhost:57638 +DEBUG: applied command on shard 103008 on node localhost:57637 +DEBUG: applied command on shard 103007 on node localhost:57637 +DEBUG: applied command on shard 103007 on node localhost:57638 +DEBUG: applied command on shard 103005 on node localhost:57637 +DEBUG: applied command on shard 103005 on node localhost:57638 +DEBUG: applied command on shard 103004 on node localhost:57638 +DEBUG: applied command on shard 103004 on node localhost:57637 +DEBUG: applied command on shard 103003 on node localhost:57637 +DEBUG: applied command on shard 103003 on node localhost:57638 +DEBUG: applied command on shard 103002 on node localhost:57638 +DEBUG: applied command on shard 103002 on node localhost:57637 +DEBUG: applied command on shard 103001 on node localhost:57637 +DEBUG: applied command on shard 103001 on node localhost:57638 +DEBUG: applied command on shard 103000 on node localhost:57638 +DEBUG: applied command on shard 103000 on node localhost:57637 +\d lineitem_alter + Table "public.lineitem_alter" + Column | Type | Modifiers +-----------------+-----------------------+----------- + l_orderkey | bigint | not null + l_partkey | integer | not null + l_suppkey | integer | not null + l_linenumber | integer | not null + l_quantity | numeric(15,2) | not null + l_extendedprice | numeric(15,2) | not null + l_discount | numeric(15,2) | not null + l_tax | numeric(15,2) | not null + l_returnflag | character(1) | not null + l_linestatus | character(1) | not null + l_shipdate | date | not null + l_commitdate | date | not null + l_receiptdate | date | not null + l_shipinstruct | character(25) | not null + l_shipmode | character(10) | not null + l_comment | character varying(44) | not null + null_column | integer | + int_column1 | integer | + int_column2 | integer | + +ALTER TABLE lineitem_alter ADD COLUMN int_column3 INTEGER, + ALTER COLUMN int_column1 SET STATISTICS 10; +ERROR: alter table command is currently supported +DETAIL: Only ADD|DROP COLUMN, SET|DROP NOT NULL, SET|DROP DEFAULT and TYPE subcommands are supported. +ALTER TABLE lineitem_alter DROP COLUMN int_column1, DROP COLUMN int_column2; +DEBUG: applied command on shard 103009 on node localhost:57637 +DEBUG: applied command on shard 103009 on node localhost:57638 +DEBUG: applied command on shard 103008 on node localhost:57638 +DEBUG: applied command on shard 103008 on node localhost:57637 +DEBUG: applied command on shard 103007 on node localhost:57637 +DEBUG: applied command on shard 103007 on node localhost:57638 +DEBUG: applied command on shard 103005 on node localhost:57637 +DEBUG: applied command on shard 103005 on node localhost:57638 +DEBUG: applied command on shard 103004 on node localhost:57638 +DEBUG: applied command on shard 103004 on node localhost:57637 +DEBUG: applied command on shard 103003 on node localhost:57637 +DEBUG: applied command on shard 103003 on node localhost:57638 +DEBUG: applied command on shard 103002 on node localhost:57638 +DEBUG: applied command on shard 103002 on node localhost:57637 +DEBUG: applied command on shard 103001 on node localhost:57637 +DEBUG: applied command on shard 103001 on node localhost:57638 +DEBUG: applied command on shard 103000 on node localhost:57638 +DEBUG: applied command on shard 103000 on node localhost:57637 +\d lineitem_alter + Table "public.lineitem_alter" + Column | Type | Modifiers +-----------------+-----------------------+----------- + l_orderkey | bigint | not null + l_partkey | integer | not null + l_suppkey | integer | not null + l_linenumber | integer | not null + l_quantity | numeric(15,2) | not null + l_extendedprice | numeric(15,2) | not null + l_discount | numeric(15,2) | not null + l_tax | numeric(15,2) | not null + l_returnflag | character(1) | not null + l_linestatus | character(1) | not null + l_shipdate | date | not null + l_commitdate | date | not null + l_receiptdate | date | not null + l_shipinstruct | character(25) | not null + l_shipmode | character(10) | not null + l_comment | character varying(44) | not null + null_column | integer | + +-- Verify that we cannot execute alter commands on the distribution column +ALTER TABLE lineitem_alter ALTER COLUMN l_orderkey DROP NOT NULL; +ERROR: cannot execute ALTER TABLE command involving partition column +ALTER TABLE lineitem_alter DROP COLUMN l_orderkey; +ERROR: cannot execute ALTER TABLE command involving partition column +-- Verify that we error out on unsupported statement types +ALTER TABLE lineitem_alter ALTER COLUMN l_orderkey SET STATISTICS 100; +ERROR: alter table command is currently supported +DETAIL: Only ADD|DROP COLUMN, SET|DROP NOT NULL, SET|DROP DEFAULT and TYPE subcommands are supported. +ALTER TABLE lineitem_alter DROP CONSTRAINT IF EXISTS non_existent_contraint; +ERROR: alter table command is currently supported +DETAIL: Only ADD|DROP COLUMN, SET|DROP NOT NULL, SET|DROP DEFAULT and TYPE subcommands are supported. +ALTER TABLE lineitem_alter SET WITHOUT OIDS; +ERROR: alter table command is currently supported +DETAIL: Only ADD|DROP COLUMN, SET|DROP NOT NULL, SET|DROP DEFAULT and TYPE subcommands are supported. +-- Verify that we error out in case of postgres errors on supported statement +-- types +ALTER TABLE lineitem_alter ADD COLUMN new_column non_existent_type; +WARNING: could not receive query results from localhost:57637 +DETAIL: Client error: type "non_existent_type" does not exist +ERROR: could not execute DDL command on worker node shards +ALTER TABLE lineitem_alter ALTER COLUMN null_column SET NOT NULL; +WARNING: could not receive query results from localhost:57637 +DETAIL: Client error: column "null_column" contains null values +ERROR: could not execute DDL command on worker node shards +ALTER TABLE lineitem_alter ALTER COLUMN l_partkey SET DEFAULT 'a'; +WARNING: could not receive query results from localhost:57637 +DETAIL: Client error: invalid input syntax for integer: "a" +ERROR: could not execute DDL command on worker node shards +-- Verify that we error out on statements involving RENAME +ALTER TABLE lineitem_alter RENAME TO lineitem_renamed; +ERROR: renaming distributed tables or their objects is currently unsupported +ALTER TABLE lineitem_alter RENAME COLUMN l_orderkey TO l_orderkey_renamed; +ERROR: renaming distributed tables or their objects is currently unsupported +ALTER TABLE lineitem_alter RENAME CONSTRAINT constraint_a TO constraint_b; +ERROR: renaming distributed tables or their objects is currently unsupported +-- Verify that IF EXISTS works as expected with RENAME statements +ALTER TABLE non_existent_table RENAME TO non_existent_table_renamed; +ERROR: relation "non_existent_table" does not exist +ALTER TABLE IF EXISTS non_existent_table RENAME TO non_existent_table_renamed; +NOTICE: relation "non_existent_table" does not exist, skipping +ALTER TABLE IF EXISTS non_existent_table RENAME COLUMN column1 TO column2; +NOTICE: relation "non_existent_table" does not exist, skipping +ALTER TABLE IF EXISTS lineitem_alter RENAME l_orderkey TO l_orderkey_renamed; +ERROR: renaming distributed tables or their objects is currently unsupported +-- Verify that none of the failed alter table commands took effect on the master +-- node +\d lineitem_alter + Table "public.lineitem_alter" + Column | Type | Modifiers +-----------------+-----------------------+----------- + l_orderkey | bigint | not null + l_partkey | integer | not null + l_suppkey | integer | not null + l_linenumber | integer | not null + l_quantity | numeric(15,2) | not null + l_extendedprice | numeric(15,2) | not null + l_discount | numeric(15,2) | not null + l_tax | numeric(15,2) | not null + l_returnflag | character(1) | not null + l_linestatus | character(1) | not null + l_shipdate | date | not null + l_commitdate | date | not null + l_receiptdate | date | not null + l_shipinstruct | character(25) | not null + l_shipmode | character(10) | not null + l_comment | character varying(44) | not null + null_column | integer | + +-- Cleanup the table and its shards +RESET client_min_messages; +SELECT master_apply_delete_command('DELETE FROM lineitem_alter'); + master_apply_delete_command +----------------------------- + 9 +(1 row) + +DROP TABLE lineitem_alter; diff --git a/src/test/regress/output/multi_alter_table_statements_0.source b/src/test/regress/output/multi_alter_table_statements_0.source new file mode 100644 index 000000000..1e5bd8cc6 --- /dev/null +++ b/src/test/regress/output/multi_alter_table_statements_0.source @@ -0,0 +1,726 @@ +-- +-- MULTI_ALTER_TABLE_STATEMENTS +-- +-- Check that we can run ALTER TABLE statements on distributed tables. We +-- increase the logging verbosity to verify that commands are propagated to +-- all worker shards. We also set the shardid sequence here so that the shardids +-- in this test aren't affected by changes to the previous tests. +ALTER SEQUENCE pg_catalog.pg_dist_shardid_seq RESTART 103000; +CREATE TABLE lineitem_alter ( + l_orderkey bigint not null, + l_partkey integer not null, + l_suppkey integer not null, + l_linenumber integer not null, + l_quantity decimal(15, 2) not null, + l_extendedprice decimal(15, 2) not null, + l_discount decimal(15, 2) not null, + l_tax decimal(15, 2) not null, + l_returnflag char(1) not null, + l_linestatus char(1) not null, + l_shipdate date not null, + l_commitdate date not null, + l_receiptdate date not null, + l_shipinstruct char(25) not null, + l_shipmode char(10) not null, + l_comment varchar(44) not null + ); +SELECT master_create_distributed_table('lineitem_alter', 'l_orderkey', 'append'); + master_create_distributed_table +--------------------------------- + +(1 row) + +\STAGE lineitem_alter FROM '@abs_srcdir@/data/lineitem.1.data' with delimiter '|' +SET client_min_messages TO DEBUG2; +-- Verify that we can add columns +ALTER TABLE lineitem_alter ADD COLUMN float_column FLOAT; +DEBUG: applied command on shard 103002 on node localhost:57638 +DEBUG: applied command on shard 103002 on node localhost:57637 +DEBUG: applied command on shard 103001 on node localhost:57637 +DEBUG: applied command on shard 103001 on node localhost:57638 +DEBUG: applied command on shard 103000 on node localhost:57638 +DEBUG: applied command on shard 103000 on node localhost:57637 +ALTER TABLE lineitem_alter ADD COLUMN date_column DATE; +DEBUG: applied command on shard 103002 on node localhost:57638 +DEBUG: applied command on shard 103002 on node localhost:57637 +DEBUG: applied command on shard 103001 on node localhost:57637 +DEBUG: applied command on shard 103001 on node localhost:57638 +DEBUG: applied command on shard 103000 on node localhost:57638 +DEBUG: applied command on shard 103000 on node localhost:57637 +ALTER TABLE lineitem_alter ADD COLUMN int_column1 INTEGER DEFAULT 1; +DEBUG: applied command on shard 103002 on node localhost:57638 +DEBUG: applied command on shard 103002 on node localhost:57637 +DEBUG: applied command on shard 103001 on node localhost:57637 +DEBUG: applied command on shard 103001 on node localhost:57638 +DEBUG: applied command on shard 103000 on node localhost:57638 +DEBUG: applied command on shard 103000 on node localhost:57637 +DEBUG: EventTriggerTableRewrite(17667) +DEBUG: rewriting table "lineitem_alter" +DEBUG: drop auto-cascades to type pg_temp_17667 +DEBUG: drop auto-cascades to type pg_temp_17667[] +ALTER TABLE lineitem_alter ADD COLUMN int_column2 INTEGER DEFAULT 2; +DEBUG: applied command on shard 103002 on node localhost:57638 +DEBUG: applied command on shard 103002 on node localhost:57637 +DEBUG: applied command on shard 103001 on node localhost:57637 +DEBUG: applied command on shard 103001 on node localhost:57638 +DEBUG: applied command on shard 103000 on node localhost:57638 +DEBUG: applied command on shard 103000 on node localhost:57637 +DEBUG: EventTriggerTableRewrite(17667) +DEBUG: rewriting table "lineitem_alter" +DEBUG: drop auto-cascades to type pg_temp_17667 +DEBUG: drop auto-cascades to type pg_temp_17667[] +ALTER TABLE lineitem_alter ADD COLUMN null_column INTEGER; +DEBUG: applied command on shard 103002 on node localhost:57638 +DEBUG: applied command on shard 103002 on node localhost:57637 +DEBUG: applied command on shard 103001 on node localhost:57637 +DEBUG: applied command on shard 103001 on node localhost:57638 +DEBUG: applied command on shard 103000 on node localhost:57638 +DEBUG: applied command on shard 103000 on node localhost:57637 +\d lineitem_alter + Table "public.lineitem_alter" + Column | Type | Modifiers +-----------------+-----------------------+----------- + l_orderkey | bigint | not null + l_partkey | integer | not null + l_suppkey | integer | not null + l_linenumber | integer | not null + l_quantity | numeric(15,2) | not null + l_extendedprice | numeric(15,2) | not null + l_discount | numeric(15,2) | not null + l_tax | numeric(15,2) | not null + l_returnflag | character(1) | not null + l_linestatus | character(1) | not null + l_shipdate | date | not null + l_commitdate | date | not null + l_receiptdate | date | not null + l_shipinstruct | character(25) | not null + l_shipmode | character(10) | not null + l_comment | character varying(44) | not null + float_column | double precision | + date_column | date | + int_column1 | integer | default 1 + int_column2 | integer | default 2 + null_column | integer | + +SELECT float_column, count(*) FROM lineitem_alter GROUP BY float_column; + float_column | count +--------------+------- + | 6000 +(1 row) + +SELECT int_column1, count(*) FROM lineitem_alter GROUP BY int_column1; + int_column1 | count +-------------+------- + 1 | 6000 +(1 row) + +-- Verify that SET|DROP DEFAULT works +ALTER TABLE lineitem_alter ALTER COLUMN float_column SET DEFAULT 1; +DEBUG: applied command on shard 103002 on node localhost:57638 +DEBUG: applied command on shard 103002 on node localhost:57637 +DEBUG: applied command on shard 103001 on node localhost:57637 +DEBUG: applied command on shard 103001 on node localhost:57638 +DEBUG: applied command on shard 103000 on node localhost:57638 +DEBUG: applied command on shard 103000 on node localhost:57637 +ALTER TABLE lineitem_alter ALTER COLUMN int_column1 DROP DEFAULT; +DEBUG: applied command on shard 103002 on node localhost:57638 +DEBUG: applied command on shard 103002 on node localhost:57637 +DEBUG: applied command on shard 103001 on node localhost:57637 +DEBUG: applied command on shard 103001 on node localhost:57638 +DEBUG: applied command on shard 103000 on node localhost:57638 +DEBUG: applied command on shard 103000 on node localhost:57637 +DEBUG: EventTriggerInvoke 16532 +-- \stage to verify that default values take effect +\STAGE lineitem_alter (l_orderkey, l_partkey, l_suppkey, l_linenumber, l_quantity, l_extendedprice, l_discount, l_tax, l_returnflag, l_linestatus, l_shipdate, l_commitdate, l_receiptdate, l_shipinstruct, l_shipmode, l_comment) FROM '@abs_srcdir@/data/lineitem.1.data' with delimiter '|' +DEBUG: parse : SELECT * FROM master_get_table_metadata($1::text) +DEBUG: bind to +DEBUG: parse : SELECT * FROM master_get_table_ddl_events($1::text) +DEBUG: bind to +DEBUG: parse : SELECT * FROM master_get_new_shardid() +DEBUG: bind to +DEBUG: parse : SELECT * FROM master_get_round_robin_candidate_nodes($1::int8) +DEBUG: bind to +DEBUG: parse : SELECT * FROM master_get_new_shardid() +DEBUG: bind to +DEBUG: parse : SELECT * FROM master_get_round_robin_candidate_nodes($1::int8) +DEBUG: bind to +DEBUG: parse : SELECT * FROM master_get_new_shardid() +DEBUG: bind to +DEBUG: parse : SELECT * FROM master_get_round_robin_candidate_nodes($1::int8) +DEBUG: bind to +DEBUG: parse : INSERT INTO pg_dist_shard (logicalrelid, shardid, shardstorage, shardminvalue, shardmaxvalue) VALUES ($1::oid, $2::int8, $3::char, $4::text, $5::text) +DEBUG: bind to +DEBUG: parse : INSERT INTO pg_dist_shard_placement (shardid, shardstate, shardlength, nodename, nodeport) VALUES ($1::int8, $2::int4, $3::int8, $4::text, $5::int4) +DEBUG: bind to +DEBUG: parse : INSERT INTO pg_dist_shard_placement (shardid, shardstate, shardlength, nodename, nodeport) VALUES ($1::int8, $2::int4, $3::int8, $4::text, $5::int4) +DEBUG: bind to +DEBUG: parse : INSERT INTO pg_dist_shard (logicalrelid, shardid, shardstorage, shardminvalue, shardmaxvalue) VALUES ($1::oid, $2::int8, $3::char, $4::text, $5::text) +DEBUG: bind to +DEBUG: parse : INSERT INTO pg_dist_shard_placement (shardid, shardstate, shardlength, nodename, nodeport) VALUES ($1::int8, $2::int4, $3::int8, $4::text, $5::int4) +DEBUG: bind to +DEBUG: parse : INSERT INTO pg_dist_shard_placement (shardid, shardstate, shardlength, nodename, nodeport) VALUES ($1::int8, $2::int4, $3::int8, $4::text, $5::int4) +DEBUG: bind to +DEBUG: parse : INSERT INTO pg_dist_shard (logicalrelid, shardid, shardstorage, shardminvalue, shardmaxvalue) VALUES ($1::oid, $2::int8, $3::char, $4::text, $5::text) +DEBUG: bind to +DEBUG: parse : INSERT INTO pg_dist_shard_placement (shardid, shardstate, shardlength, nodename, nodeport) VALUES ($1::int8, $2::int4, $3::int8, $4::text, $5::int4) +DEBUG: bind to +DEBUG: parse : INSERT INTO pg_dist_shard_placement (shardid, shardstate, shardlength, nodename, nodeport) VALUES ($1::int8, $2::int4, $3::int8, $4::text, $5::int4) +DEBUG: bind to +SELECT float_column, count(*) FROM lineitem_alter GROUP BY float_column; + float_column | count +--------------+------- + | 6000 + 1 | 6000 +(2 rows) + +SELECT int_column1, count(*) FROM lineitem_alter GROUP BY int_column1; + int_column1 | count +-------------+------- + | 6000 + 1 | 6000 +(2 rows) + +-- Verify that SET NOT NULL works +ALTER TABLE lineitem_alter ALTER COLUMN int_column2 SET NOT NULL; +DEBUG: applied command on shard 103005 on node localhost:57637 +DEBUG: applied command on shard 103005 on node localhost:57638 +DEBUG: applied command on shard 103004 on node localhost:57638 +DEBUG: applied command on shard 103004 on node localhost:57637 +DEBUG: applied command on shard 103003 on node localhost:57637 +DEBUG: applied command on shard 103003 on node localhost:57638 +DEBUG: applied command on shard 103002 on node localhost:57638 +DEBUG: applied command on shard 103002 on node localhost:57637 +DEBUG: applied command on shard 103001 on node localhost:57637 +DEBUG: applied command on shard 103001 on node localhost:57638 +DEBUG: applied command on shard 103000 on node localhost:57638 +DEBUG: applied command on shard 103000 on node localhost:57637 +DEBUG: verifying table "lineitem_alter" +\d lineitem_alter + Table "public.lineitem_alter" + Column | Type | Modifiers +-----------------+-----------------------+-------------------- + l_orderkey | bigint | not null + l_partkey | integer | not null + l_suppkey | integer | not null + l_linenumber | integer | not null + l_quantity | numeric(15,2) | not null + l_extendedprice | numeric(15,2) | not null + l_discount | numeric(15,2) | not null + l_tax | numeric(15,2) | not null + l_returnflag | character(1) | not null + l_linestatus | character(1) | not null + l_shipdate | date | not null + l_commitdate | date | not null + l_receiptdate | date | not null + l_shipinstruct | character(25) | not null + l_shipmode | character(10) | not null + l_comment | character varying(44) | not null + float_column | double precision | default 1 + date_column | date | + int_column1 | integer | + int_column2 | integer | not null default 2 + null_column | integer | + +-- Drop default so that NULLs will be inserted for this column +ALTER TABLE lineitem_alter ALTER COLUMN int_column2 DROP DEFAULT; +DEBUG: applied command on shard 103005 on node localhost:57637 +DEBUG: applied command on shard 103005 on node localhost:57638 +DEBUG: applied command on shard 103004 on node localhost:57638 +DEBUG: applied command on shard 103004 on node localhost:57637 +DEBUG: applied command on shard 103003 on node localhost:57637 +DEBUG: applied command on shard 103003 on node localhost:57638 +DEBUG: applied command on shard 103002 on node localhost:57638 +DEBUG: applied command on shard 103002 on node localhost:57637 +DEBUG: applied command on shard 103001 on node localhost:57637 +DEBUG: applied command on shard 103001 on node localhost:57638 +DEBUG: applied command on shard 103000 on node localhost:57638 +DEBUG: applied command on shard 103000 on node localhost:57637 +DEBUG: EventTriggerInvoke 16532 +-- \stage should fail because it will try to insert NULLs for a NOT NULL column +\STAGE lineitem_alter (l_orderkey, l_partkey, l_suppkey, l_linenumber, l_quantity, l_extendedprice, l_discount, l_tax, l_returnflag, l_linestatus, l_shipdate, l_commitdate, l_receiptdate, l_shipinstruct, l_shipmode, l_comment) FROM '@abs_srcdir@/data/lineitem.1.data' with delimiter '|' +DEBUG: parse : SELECT * FROM master_get_table_metadata($1::text) +DEBUG: bind to +DEBUG: parse : SELECT * FROM master_get_table_ddl_events($1::text) +DEBUG: bind to +DEBUG: parse : SELECT * FROM master_get_new_shardid() +DEBUG: bind to +DEBUG: parse : SELECT * FROM master_get_round_robin_candidate_nodes($1::int8) +DEBUG: bind to +ERROR: null value in column "int_column2" violates not-null constraint +DETAIL: Failing row contains (1, 155190, 7706, 1, 17.00, 21168.23, 0.04, 0.02, N, O, 03-13-1996, 02-12-1996, 03-22-1996, DELIVER IN PERSON , TRUCK , egular courts above the, 1, null, null, null, null). +CONTEXT: COPY lineitem_alter_103006, line 1: "1|155190|7706|1|17|21168.23|0.04|0.02|N|O|1996-03-13|1996-02-12|1996-03-22|DELIVER IN PERSON|TRUCK|e..." +ERROR: null value in column "int_column2" violates not-null constraint +DETAIL: Failing row contains (1, 155190, 7706, 1, 17.00, 21168.23, 0.04, 0.02, N, O, 03-13-1996, 02-12-1996, 03-22-1996, DELIVER IN PERSON , TRUCK , egular courts above the, 1, null, null, null, null). +CONTEXT: COPY lineitem_alter_103006, line 1: "1|155190|7706|1|17|21168.23|0.04|0.02|N|O|1996-03-13|1996-02-12|1996-03-22|DELIVER IN PERSON|TRUCK|e..." +\stage: failed to replicate shard to enough replicas +-- Verify that DROP NOT NULL works +ALTER TABLE lineitem_alter ALTER COLUMN int_column2 DROP NOT NULL; +DEBUG: applied command on shard 103005 on node localhost:57637 +DEBUG: applied command on shard 103005 on node localhost:57638 +DEBUG: applied command on shard 103004 on node localhost:57638 +DEBUG: applied command on shard 103004 on node localhost:57637 +DEBUG: applied command on shard 103003 on node localhost:57637 +DEBUG: applied command on shard 103003 on node localhost:57638 +DEBUG: applied command on shard 103002 on node localhost:57638 +DEBUG: applied command on shard 103002 on node localhost:57637 +DEBUG: applied command on shard 103001 on node localhost:57637 +DEBUG: applied command on shard 103001 on node localhost:57638 +DEBUG: applied command on shard 103000 on node localhost:57638 +DEBUG: applied command on shard 103000 on node localhost:57637 +\d lineitem_alter + Table "public.lineitem_alter" + Column | Type | Modifiers +-----------------+-----------------------+----------- + l_orderkey | bigint | not null + l_partkey | integer | not null + l_suppkey | integer | not null + l_linenumber | integer | not null + l_quantity | numeric(15,2) | not null + l_extendedprice | numeric(15,2) | not null + l_discount | numeric(15,2) | not null + l_tax | numeric(15,2) | not null + l_returnflag | character(1) | not null + l_linestatus | character(1) | not null + l_shipdate | date | not null + l_commitdate | date | not null + l_receiptdate | date | not null + l_shipinstruct | character(25) | not null + l_shipmode | character(10) | not null + l_comment | character varying(44) | not null + float_column | double precision | default 1 + date_column | date | + int_column1 | integer | + int_column2 | integer | + null_column | integer | + +-- \stage should succeed now +\STAGE lineitem_alter (l_orderkey, l_partkey, l_suppkey, l_linenumber, l_quantity, l_extendedprice, l_discount, l_tax, l_returnflag, l_linestatus, l_shipdate, l_commitdate, l_receiptdate, l_shipinstruct, l_shipmode, l_comment) FROM '@abs_srcdir@/data/lineitem.1.data' with delimiter '|' +DEBUG: parse : SELECT * FROM master_get_table_metadata($1::text) +DEBUG: bind to +DEBUG: parse : SELECT * FROM master_get_table_ddl_events($1::text) +DEBUG: bind to +DEBUG: parse : SELECT * FROM master_get_new_shardid() +DEBUG: bind to +DEBUG: parse : SELECT * FROM master_get_round_robin_candidate_nodes($1::int8) +DEBUG: bind to +DEBUG: parse : SELECT * FROM master_get_new_shardid() +DEBUG: bind to +DEBUG: parse : SELECT * FROM master_get_round_robin_candidate_nodes($1::int8) +DEBUG: bind to +DEBUG: parse : SELECT * FROM master_get_new_shardid() +DEBUG: bind to +DEBUG: parse : SELECT * FROM master_get_round_robin_candidate_nodes($1::int8) +DEBUG: bind to +DEBUG: parse : INSERT INTO pg_dist_shard (logicalrelid, shardid, shardstorage, shardminvalue, shardmaxvalue) VALUES ($1::oid, $2::int8, $3::char, $4::text, $5::text) +DEBUG: bind to +DEBUG: parse : INSERT INTO pg_dist_shard_placement (shardid, shardstate, shardlength, nodename, nodeport) VALUES ($1::int8, $2::int4, $3::int8, $4::text, $5::int4) +DEBUG: bind to +DEBUG: parse : INSERT INTO pg_dist_shard_placement (shardid, shardstate, shardlength, nodename, nodeport) VALUES ($1::int8, $2::int4, $3::int8, $4::text, $5::int4) +DEBUG: bind to +DEBUG: parse : INSERT INTO pg_dist_shard (logicalrelid, shardid, shardstorage, shardminvalue, shardmaxvalue) VALUES ($1::oid, $2::int8, $3::char, $4::text, $5::text) +DEBUG: bind to +DEBUG: parse : INSERT INTO pg_dist_shard_placement (shardid, shardstate, shardlength, nodename, nodeport) VALUES ($1::int8, $2::int4, $3::int8, $4::text, $5::int4) +DEBUG: bind to +DEBUG: parse : INSERT INTO pg_dist_shard_placement (shardid, shardstate, shardlength, nodename, nodeport) VALUES ($1::int8, $2::int4, $3::int8, $4::text, $5::int4) +DEBUG: bind to +DEBUG: parse : INSERT INTO pg_dist_shard (logicalrelid, shardid, shardstorage, shardminvalue, shardmaxvalue) VALUES ($1::oid, $2::int8, $3::char, $4::text, $5::text) +DEBUG: bind to +DEBUG: parse : INSERT INTO pg_dist_shard_placement (shardid, shardstate, shardlength, nodename, nodeport) VALUES ($1::int8, $2::int4, $3::int8, $4::text, $5::int4) +DEBUG: bind to +DEBUG: parse : INSERT INTO pg_dist_shard_placement (shardid, shardstate, shardlength, nodename, nodeport) VALUES ($1::int8, $2::int4, $3::int8, $4::text, $5::int4) +DEBUG: bind to +SELECT count(*) from lineitem_alter; + count +------- + 18000 +(1 row) + +-- Verify that SET DATA TYPE works +SELECT int_column2, pg_typeof(int_column2), count(*) from lineitem_alter GROUP BY int_column2; + int_column2 | pg_typeof | count +-------------+-----------+------- + | integer | 6000 + 2 | integer | 12000 +(2 rows) + +ALTER TABLE lineitem_alter ALTER COLUMN int_column2 SET DATA TYPE FLOAT; +DEBUG: applied command on shard 103009 on node localhost:57637 +DEBUG: applied command on shard 103009 on node localhost:57638 +DEBUG: applied command on shard 103008 on node localhost:57638 +DEBUG: applied command on shard 103008 on node localhost:57637 +DEBUG: applied command on shard 103007 on node localhost:57637 +DEBUG: applied command on shard 103007 on node localhost:57638 +DEBUG: applied command on shard 103005 on node localhost:57637 +DEBUG: applied command on shard 103005 on node localhost:57638 +DEBUG: applied command on shard 103004 on node localhost:57638 +DEBUG: applied command on shard 103004 on node localhost:57637 +DEBUG: applied command on shard 103003 on node localhost:57637 +DEBUG: applied command on shard 103003 on node localhost:57638 +DEBUG: applied command on shard 103002 on node localhost:57638 +DEBUG: applied command on shard 103002 on node localhost:57637 +DEBUG: applied command on shard 103001 on node localhost:57637 +DEBUG: applied command on shard 103001 on node localhost:57638 +DEBUG: applied command on shard 103000 on node localhost:57638 +DEBUG: applied command on shard 103000 on node localhost:57637 +DEBUG: EventTriggerTableRewrite(17667) +DEBUG: rewriting table "lineitem_alter" +DEBUG: drop auto-cascades to type pg_temp_17667 +DEBUG: drop auto-cascades to type pg_temp_17667[] +\d lineitem_alter + Table "public.lineitem_alter" + Column | Type | Modifiers +-----------------+-----------------------+----------- + l_orderkey | bigint | not null + l_partkey | integer | not null + l_suppkey | integer | not null + l_linenumber | integer | not null + l_quantity | numeric(15,2) | not null + l_extendedprice | numeric(15,2) | not null + l_discount | numeric(15,2) | not null + l_tax | numeric(15,2) | not null + l_returnflag | character(1) | not null + l_linestatus | character(1) | not null + l_shipdate | date | not null + l_commitdate | date | not null + l_receiptdate | date | not null + l_shipinstruct | character(25) | not null + l_shipmode | character(10) | not null + l_comment | character varying(44) | not null + float_column | double precision | default 1 + date_column | date | + int_column1 | integer | + int_column2 | double precision | + null_column | integer | + +SELECT int_column2, pg_typeof(int_column2), count(*) from lineitem_alter GROUP BY int_column2; + int_column2 | pg_typeof | count +-------------+------------------+------- + | double precision | 6000 + 2 | double precision | 12000 +(2 rows) + +-- Verify that DROP COLUMN works +ALTER TABLE lineitem_alter DROP COLUMN int_column1; +DEBUG: applied command on shard 103009 on node localhost:57637 +DEBUG: applied command on shard 103009 on node localhost:57638 +DEBUG: applied command on shard 103008 on node localhost:57638 +DEBUG: applied command on shard 103008 on node localhost:57637 +DEBUG: applied command on shard 103007 on node localhost:57637 +DEBUG: applied command on shard 103007 on node localhost:57638 +DEBUG: applied command on shard 103005 on node localhost:57637 +DEBUG: applied command on shard 103005 on node localhost:57638 +DEBUG: applied command on shard 103004 on node localhost:57638 +DEBUG: applied command on shard 103004 on node localhost:57637 +DEBUG: applied command on shard 103003 on node localhost:57637 +DEBUG: applied command on shard 103003 on node localhost:57638 +DEBUG: applied command on shard 103002 on node localhost:57638 +DEBUG: applied command on shard 103002 on node localhost:57637 +DEBUG: applied command on shard 103001 on node localhost:57637 +DEBUG: applied command on shard 103001 on node localhost:57638 +DEBUG: applied command on shard 103000 on node localhost:57638 +DEBUG: applied command on shard 103000 on node localhost:57637 +DEBUG: EventTriggerInvoke 16532 +ALTER TABLE lineitem_alter DROP COLUMN float_column; +DEBUG: applied command on shard 103009 on node localhost:57637 +DEBUG: applied command on shard 103009 on node localhost:57638 +DEBUG: applied command on shard 103008 on node localhost:57638 +DEBUG: applied command on shard 103008 on node localhost:57637 +DEBUG: applied command on shard 103007 on node localhost:57637 +DEBUG: applied command on shard 103007 on node localhost:57638 +DEBUG: applied command on shard 103005 on node localhost:57637 +DEBUG: applied command on shard 103005 on node localhost:57638 +DEBUG: applied command on shard 103004 on node localhost:57638 +DEBUG: applied command on shard 103004 on node localhost:57637 +DEBUG: applied command on shard 103003 on node localhost:57637 +DEBUG: applied command on shard 103003 on node localhost:57638 +DEBUG: applied command on shard 103002 on node localhost:57638 +DEBUG: applied command on shard 103002 on node localhost:57637 +DEBUG: applied command on shard 103001 on node localhost:57637 +DEBUG: applied command on shard 103001 on node localhost:57638 +DEBUG: applied command on shard 103000 on node localhost:57638 +DEBUG: applied command on shard 103000 on node localhost:57637 +DEBUG: drop auto-cascades to default for table lineitem_alter column float_column +DEBUG: EventTriggerInvoke 16532 +ALTER TABLE lineitem_alter DROP COLUMN date_column; +DEBUG: applied command on shard 103009 on node localhost:57637 +DEBUG: applied command on shard 103009 on node localhost:57638 +DEBUG: applied command on shard 103008 on node localhost:57638 +DEBUG: applied command on shard 103008 on node localhost:57637 +DEBUG: applied command on shard 103007 on node localhost:57637 +DEBUG: applied command on shard 103007 on node localhost:57638 +DEBUG: applied command on shard 103005 on node localhost:57637 +DEBUG: applied command on shard 103005 on node localhost:57638 +DEBUG: applied command on shard 103004 on node localhost:57638 +DEBUG: applied command on shard 103004 on node localhost:57637 +DEBUG: applied command on shard 103003 on node localhost:57637 +DEBUG: applied command on shard 103003 on node localhost:57638 +DEBUG: applied command on shard 103002 on node localhost:57638 +DEBUG: applied command on shard 103002 on node localhost:57637 +DEBUG: applied command on shard 103001 on node localhost:57637 +DEBUG: applied command on shard 103001 on node localhost:57638 +DEBUG: applied command on shard 103000 on node localhost:57638 +DEBUG: applied command on shard 103000 on node localhost:57637 +DEBUG: EventTriggerInvoke 16532 +-- Verify that IF EXISTS works as expected +ALTER TABLE non_existent_table ADD COLUMN new_column INTEGER; +ERROR: relation "non_existent_table" does not exist +ALTER TABLE IF EXISTS non_existent_table ADD COLUMN new_column INTEGER; +NOTICE: relation "non_existent_table" does not exist, skipping +ALTER TABLE IF EXISTS lineitem_alter ALTER COLUMN int_column2 SET DATA TYPE INTEGER; +DEBUG: applied command on shard 103009 on node localhost:57637 +DEBUG: applied command on shard 103009 on node localhost:57638 +DEBUG: applied command on shard 103008 on node localhost:57638 +DEBUG: applied command on shard 103008 on node localhost:57637 +DEBUG: applied command on shard 103007 on node localhost:57637 +DEBUG: applied command on shard 103007 on node localhost:57638 +DEBUG: applied command on shard 103005 on node localhost:57637 +DEBUG: applied command on shard 103005 on node localhost:57638 +DEBUG: applied command on shard 103004 on node localhost:57638 +DEBUG: applied command on shard 103004 on node localhost:57637 +DEBUG: applied command on shard 103003 on node localhost:57637 +DEBUG: applied command on shard 103003 on node localhost:57638 +DEBUG: applied command on shard 103002 on node localhost:57638 +DEBUG: applied command on shard 103002 on node localhost:57637 +DEBUG: applied command on shard 103001 on node localhost:57637 +DEBUG: applied command on shard 103001 on node localhost:57638 +DEBUG: applied command on shard 103000 on node localhost:57638 +DEBUG: applied command on shard 103000 on node localhost:57637 +DEBUG: EventTriggerTableRewrite(17667) +DEBUG: rewriting table "lineitem_alter" +DEBUG: drop auto-cascades to type pg_temp_17667 +DEBUG: drop auto-cascades to type pg_temp_17667[] +ALTER TABLE lineitem_alter DROP COLUMN non_existent_column; +WARNING: could not receive query results from localhost:57637 +DETAIL: Client error: column "non_existent_column" of relation "lineitem_alter_103009" does not exist +ERROR: could not execute DDL command on worker node shards +ALTER TABLE lineitem_alter DROP COLUMN IF EXISTS non_existent_column; +DEBUG: applied command on shard 103009 on node localhost:57637 +DEBUG: applied command on shard 103009 on node localhost:57638 +DEBUG: applied command on shard 103008 on node localhost:57638 +DEBUG: applied command on shard 103008 on node localhost:57637 +DEBUG: applied command on shard 103007 on node localhost:57637 +DEBUG: applied command on shard 103007 on node localhost:57638 +DEBUG: applied command on shard 103005 on node localhost:57637 +DEBUG: applied command on shard 103005 on node localhost:57638 +DEBUG: applied command on shard 103004 on node localhost:57638 +DEBUG: applied command on shard 103004 on node localhost:57637 +DEBUG: applied command on shard 103003 on node localhost:57637 +DEBUG: applied command on shard 103003 on node localhost:57638 +DEBUG: applied command on shard 103002 on node localhost:57638 +DEBUG: applied command on shard 103002 on node localhost:57637 +DEBUG: applied command on shard 103001 on node localhost:57637 +DEBUG: applied command on shard 103001 on node localhost:57638 +DEBUG: applied command on shard 103000 on node localhost:57638 +DEBUG: applied command on shard 103000 on node localhost:57637 +NOTICE: column "non_existent_column" of relation "lineitem_alter" does not exist, skipping +ALTER TABLE lineitem_alter DROP COLUMN IF EXISTS int_column2; +DEBUG: applied command on shard 103009 on node localhost:57637 +DEBUG: applied command on shard 103009 on node localhost:57638 +DEBUG: applied command on shard 103008 on node localhost:57638 +DEBUG: applied command on shard 103008 on node localhost:57637 +DEBUG: applied command on shard 103007 on node localhost:57637 +DEBUG: applied command on shard 103007 on node localhost:57638 +DEBUG: applied command on shard 103005 on node localhost:57637 +DEBUG: applied command on shard 103005 on node localhost:57638 +DEBUG: applied command on shard 103004 on node localhost:57638 +DEBUG: applied command on shard 103004 on node localhost:57637 +DEBUG: applied command on shard 103003 on node localhost:57637 +DEBUG: applied command on shard 103003 on node localhost:57638 +DEBUG: applied command on shard 103002 on node localhost:57638 +DEBUG: applied command on shard 103002 on node localhost:57637 +DEBUG: applied command on shard 103001 on node localhost:57637 +DEBUG: applied command on shard 103001 on node localhost:57638 +DEBUG: applied command on shard 103000 on node localhost:57638 +DEBUG: applied command on shard 103000 on node localhost:57637 +DEBUG: EventTriggerInvoke 16532 +\d lineitem_alter + Table "public.lineitem_alter" + Column | Type | Modifiers +-----------------+-----------------------+----------- + l_orderkey | bigint | not null + l_partkey | integer | not null + l_suppkey | integer | not null + l_linenumber | integer | not null + l_quantity | numeric(15,2) | not null + l_extendedprice | numeric(15,2) | not null + l_discount | numeric(15,2) | not null + l_tax | numeric(15,2) | not null + l_returnflag | character(1) | not null + l_linestatus | character(1) | not null + l_shipdate | date | not null + l_commitdate | date | not null + l_receiptdate | date | not null + l_shipinstruct | character(25) | not null + l_shipmode | character(10) | not null + l_comment | character varying(44) | not null + null_column | integer | + +-- Verify that we can execute commands with multiple subcommands +ALTER TABLE lineitem_alter ADD COLUMN int_column1 INTEGER, + ADD COLUMN int_column2 INTEGER; +DEBUG: applied command on shard 103009 on node localhost:57637 +DEBUG: applied command on shard 103009 on node localhost:57638 +DEBUG: applied command on shard 103008 on node localhost:57638 +DEBUG: applied command on shard 103008 on node localhost:57637 +DEBUG: applied command on shard 103007 on node localhost:57637 +DEBUG: applied command on shard 103007 on node localhost:57638 +DEBUG: applied command on shard 103005 on node localhost:57637 +DEBUG: applied command on shard 103005 on node localhost:57638 +DEBUG: applied command on shard 103004 on node localhost:57638 +DEBUG: applied command on shard 103004 on node localhost:57637 +DEBUG: applied command on shard 103003 on node localhost:57637 +DEBUG: applied command on shard 103003 on node localhost:57638 +DEBUG: applied command on shard 103002 on node localhost:57638 +DEBUG: applied command on shard 103002 on node localhost:57637 +DEBUG: applied command on shard 103001 on node localhost:57637 +DEBUG: applied command on shard 103001 on node localhost:57638 +DEBUG: applied command on shard 103000 on node localhost:57638 +DEBUG: applied command on shard 103000 on node localhost:57637 +\d lineitem_alter + Table "public.lineitem_alter" + Column | Type | Modifiers +-----------------+-----------------------+----------- + l_orderkey | bigint | not null + l_partkey | integer | not null + l_suppkey | integer | not null + l_linenumber | integer | not null + l_quantity | numeric(15,2) | not null + l_extendedprice | numeric(15,2) | not null + l_discount | numeric(15,2) | not null + l_tax | numeric(15,2) | not null + l_returnflag | character(1) | not null + l_linestatus | character(1) | not null + l_shipdate | date | not null + l_commitdate | date | not null + l_receiptdate | date | not null + l_shipinstruct | character(25) | not null + l_shipmode | character(10) | not null + l_comment | character varying(44) | not null + null_column | integer | + int_column1 | integer | + int_column2 | integer | + +ALTER TABLE lineitem_alter ADD COLUMN int_column3 INTEGER, + ALTER COLUMN int_column1 SET STATISTICS 10; +ERROR: alter table command is currently supported +DETAIL: Only ADD|DROP COLUMN, SET|DROP NOT NULL, SET|DROP DEFAULT and TYPE subcommands are supported. +ALTER TABLE lineitem_alter DROP COLUMN int_column1, DROP COLUMN int_column2; +DEBUG: applied command on shard 103009 on node localhost:57637 +DEBUG: applied command on shard 103009 on node localhost:57638 +DEBUG: applied command on shard 103008 on node localhost:57638 +DEBUG: applied command on shard 103008 on node localhost:57637 +DEBUG: applied command on shard 103007 on node localhost:57637 +DEBUG: applied command on shard 103007 on node localhost:57638 +DEBUG: applied command on shard 103005 on node localhost:57637 +DEBUG: applied command on shard 103005 on node localhost:57638 +DEBUG: applied command on shard 103004 on node localhost:57638 +DEBUG: applied command on shard 103004 on node localhost:57637 +DEBUG: applied command on shard 103003 on node localhost:57637 +DEBUG: applied command on shard 103003 on node localhost:57638 +DEBUG: applied command on shard 103002 on node localhost:57638 +DEBUG: applied command on shard 103002 on node localhost:57637 +DEBUG: applied command on shard 103001 on node localhost:57637 +DEBUG: applied command on shard 103001 on node localhost:57638 +DEBUG: applied command on shard 103000 on node localhost:57638 +DEBUG: applied command on shard 103000 on node localhost:57637 +DEBUG: EventTriggerInvoke 16532 +\d lineitem_alter + Table "public.lineitem_alter" + Column | Type | Modifiers +-----------------+-----------------------+----------- + l_orderkey | bigint | not null + l_partkey | integer | not null + l_suppkey | integer | not null + l_linenumber | integer | not null + l_quantity | numeric(15,2) | not null + l_extendedprice | numeric(15,2) | not null + l_discount | numeric(15,2) | not null + l_tax | numeric(15,2) | not null + l_returnflag | character(1) | not null + l_linestatus | character(1) | not null + l_shipdate | date | not null + l_commitdate | date | not null + l_receiptdate | date | not null + l_shipinstruct | character(25) | not null + l_shipmode | character(10) | not null + l_comment | character varying(44) | not null + null_column | integer | + +-- Verify that we cannot execute alter commands on the distribution column +ALTER TABLE lineitem_alter ALTER COLUMN l_orderkey DROP NOT NULL; +ERROR: cannot execute ALTER TABLE command involving partition column +ALTER TABLE lineitem_alter DROP COLUMN l_orderkey; +ERROR: cannot execute ALTER TABLE command involving partition column +-- Verify that we error out on unsupported statement types +ALTER TABLE lineitem_alter ALTER COLUMN l_orderkey SET STATISTICS 100; +ERROR: alter table command is currently supported +DETAIL: Only ADD|DROP COLUMN, SET|DROP NOT NULL, SET|DROP DEFAULT and TYPE subcommands are supported. +ALTER TABLE lineitem_alter DROP CONSTRAINT IF EXISTS non_existent_contraint; +ERROR: alter table command is currently supported +DETAIL: Only ADD|DROP COLUMN, SET|DROP NOT NULL, SET|DROP DEFAULT and TYPE subcommands are supported. +ALTER TABLE lineitem_alter SET WITHOUT OIDS; +ERROR: alter table command is currently supported +DETAIL: Only ADD|DROP COLUMN, SET|DROP NOT NULL, SET|DROP DEFAULT and TYPE subcommands are supported. +-- Verify that we error out in case of postgres errors on supported statement +-- types +ALTER TABLE lineitem_alter ADD COLUMN new_column non_existent_type; +WARNING: could not receive query results from localhost:57637 +DETAIL: Client error: type "non_existent_type" does not exist +ERROR: could not execute DDL command on worker node shards +ALTER TABLE lineitem_alter ALTER COLUMN null_column SET NOT NULL; +WARNING: could not receive query results from localhost:57637 +DETAIL: Client error: column "null_column" contains null values +ERROR: could not execute DDL command on worker node shards +ALTER TABLE lineitem_alter ALTER COLUMN l_partkey SET DEFAULT 'a'; +WARNING: could not receive query results from localhost:57637 +DETAIL: Client error: invalid input syntax for integer: "a" +ERROR: could not execute DDL command on worker node shards +-- Verify that we error out on statements involving RENAME +ALTER TABLE lineitem_alter RENAME TO lineitem_renamed; +ERROR: renaming distributed tables or their objects is currently unsupported +ALTER TABLE lineitem_alter RENAME COLUMN l_orderkey TO l_orderkey_renamed; +ERROR: renaming distributed tables or their objects is currently unsupported +ALTER TABLE lineitem_alter RENAME CONSTRAINT constraint_a TO constraint_b; +ERROR: renaming distributed tables or their objects is currently unsupported +-- Verify that IF EXISTS works as expected with RENAME statements +ALTER TABLE non_existent_table RENAME TO non_existent_table_renamed; +ERROR: relation "non_existent_table" does not exist +ALTER TABLE IF EXISTS non_existent_table RENAME TO non_existent_table_renamed; +NOTICE: relation "non_existent_table" does not exist, skipping +ALTER TABLE IF EXISTS non_existent_table RENAME COLUMN column1 TO column2; +NOTICE: relation "non_existent_table" does not exist, skipping +ALTER TABLE IF EXISTS lineitem_alter RENAME l_orderkey TO l_orderkey_renamed; +ERROR: renaming distributed tables or their objects is currently unsupported +-- Verify that none of the failed alter table commands took effect on the master +-- node +\d lineitem_alter + Table "public.lineitem_alter" + Column | Type | Modifiers +-----------------+-----------------------+----------- + l_orderkey | bigint | not null + l_partkey | integer | not null + l_suppkey | integer | not null + l_linenumber | integer | not null + l_quantity | numeric(15,2) | not null + l_extendedprice | numeric(15,2) | not null + l_discount | numeric(15,2) | not null + l_tax | numeric(15,2) | not null + l_returnflag | character(1) | not null + l_linestatus | character(1) | not null + l_shipdate | date | not null + l_commitdate | date | not null + l_receiptdate | date | not null + l_shipinstruct | character(25) | not null + l_shipmode | character(10) | not null + l_comment | character varying(44) | not null + null_column | integer | + +-- Cleanup the table and its shards +RESET client_min_messages; +SELECT master_apply_delete_command('DELETE FROM lineitem_alter'); + master_apply_delete_command +----------------------------- + 9 +(1 row) + +DROP TABLE lineitem_alter; diff --git a/src/test/regress/output/multi_append_table_to_shard.source b/src/test/regress/output/multi_append_table_to_shard.source new file mode 100644 index 000000000..62580647c --- /dev/null +++ b/src/test/regress/output/multi_append_table_to_shard.source @@ -0,0 +1,138 @@ +-- +-- MULTI_APPEND_TABLE_TO_SHARD +-- +-- Initialize tables to join +CREATE TABLE multi_append_table_to_shard_right +( + right_number INTEGER not null, + right_text TEXT not null +); +SELECT master_create_distributed_table('multi_append_table_to_shard_right', 'right_number', 'append'); + master_create_distributed_table +--------------------------------- + +(1 row) + +CREATE TABLE multi_append_table_to_shard_left +( + left_number INTEGER not null, + left_text TEXT not null +); +SELECT master_create_distributed_table('multi_append_table_to_shard_left', 'left_number', 'append'); + master_create_distributed_table +--------------------------------- + +(1 row) + +-- Replicate 'left' table on both workers +SELECT set_config('citusdb.shard_replication_factor', '2', false); + set_config +------------ + 2 +(1 row) + +\STAGE multi_append_table_to_shard_left FROM '@abs_srcdir@/data/agg.data' +\STAGE multi_append_table_to_shard_left FROM '@abs_srcdir@/data/agg.data' +-- Place 'right' table only on the primary worker +SELECT set_config('citusdb.shard_replication_factor', '1', false); + set_config +------------ + 1 +(1 row) + +\STAGE multi_append_table_to_shard_right FROM '@abs_srcdir@/data/agg.data' +-- Reset shard replication factor to ensure tasks will be assigned to both workers +SELECT set_config('citusdb.shard_replication_factor', '2', false); + set_config +------------ + 2 +(1 row) + +-- All 8 rows in left table match a row in right table +SELECT COUNT(*) +FROM multi_append_table_to_shard_left, + multi_append_table_to_shard_right +WHERE left_number = right_number; + count +------- + 8 +(1 row) + +-- Now append more data to the 'right' table +CREATE TABLE multi_append_table_to_shard_stage +( + number INTEGER not null, + text TEXT not null +); +COPY multi_append_table_to_shard_stage FROM '@abs_srcdir@/data/agg.data'; +SELECT master_append_table_to_shard(shardid, 'multi_append_table_to_shard_stage', 'localhost', 57636) +FROM + pg_dist_shard +WHERE 'multi_append_table_to_shard_right'::regclass::oid = logicalrelid; + master_append_table_to_shard +------------------------------ + 0.0533333 +(1 row) + +-- Only the primary worker will see the new matches, as the secondary still uses a cached shard +SELECT COUNT(*) +FROM multi_append_table_to_shard_left, + multi_append_table_to_shard_right +WHERE left_number = right_number; + count +------- + 12 +(1 row) + +-- Now add a lot of data to ensure we increase the size on disk +DELETE FROM multi_append_table_to_shard_stage; +COPY multi_append_table_to_shard_stage FROM '@abs_srcdir@/data/large_records.data' with delimiter '|'; +SELECT master_append_table_to_shard(shardid, 'multi_append_table_to_shard_stage', 'localhost', 57636) +FROM + pg_dist_shard +WHERE 'multi_append_table_to_shard_right'::regclass::oid = logicalrelid; + master_append_table_to_shard +------------------------------ + 0.106667 +(1 row) + +-- This join will refresh the shard on the secondary, all 8 rows in the left table will match twice (16) +SELECT COUNT(*) +FROM multi_append_table_to_shard_left, + multi_append_table_to_shard_right +WHERE left_number = right_number; + count +------- + 16 +(1 row) + +-- Check that we error out if we try to append data to a hash partitioned table. +UPDATE pg_dist_partition SET partmethod = 'h' WHERE + logicalrelid = 'multi_append_table_to_shard_right'::regclass::oid; +SELECT master_create_empty_shard('multi_append_table_to_shard_right'); +ERROR: relation "multi_append_table_to_shard_right" is a hash partitioned table +DETAIL: We currently don't support creating shards on hash-partitioned tables +SELECT master_append_table_to_shard(shardid, 'multi_append_table_to_shard_stage', 'localhost', 57636) +FROM + pg_dist_shard +WHERE 'multi_append_table_to_shard_right'::regclass::oid = logicalrelid; +ERROR: cannot append to shardId 103013 +DETAIL: We currently don't support appending to shards in hash-partitioned tables +UPDATE pg_dist_partition SET partmethod = 'a' WHERE + logicalrelid = 'multi_append_table_to_shard_right'::regclass::oid; +-- Clean up after test +SELECT master_apply_delete_command('DELETE FROM multi_append_table_to_shard_right'); + master_apply_delete_command +----------------------------- + 1 +(1 row) + +SELECT master_apply_delete_command('DELETE FROM multi_append_table_to_shard_left'); + master_apply_delete_command +----------------------------- + 2 +(1 row) + +DROP TABLE multi_append_table_to_shard_stage; +DROP TABLE multi_append_table_to_shard_right; +DROP TABLE multi_append_table_to_shard_left; diff --git a/src/test/regress/output/multi_create_schema.source b/src/test/regress/output/multi_create_schema.source new file mode 100644 index 000000000..26512abd3 --- /dev/null +++ b/src/test/regress/output/multi_create_schema.source @@ -0,0 +1,25 @@ +CREATE SCHEMA tpch +CREATE TABLE nation ( + n_nationkey integer not null, + n_name char(25) not null, + n_regionkey integer not null, + n_comment varchar(152)); +NOTICE: CitusDB partially supports CREATE SCHEMA for distributed databases +DETAIL: schema usage in joins and in some UDFs provided by CitusDB are not supported yet +SELECT master_create_distributed_table('tpch.nation', 'n_nationkey', 'append'); + master_create_distributed_table +--------------------------------- + +(1 row) + +\STAGE tpch.nation FROM '@abs_srcdir@/data/nation.data' with delimiter '|' +NOTICE: CitusDB partially supports CREATE SCHEMA for distributed databases +DETAIL: schema usage in joins and in some UDFs provided by CitusDB are not supported yet +NOTICE: CitusDB partially supports CREATE SCHEMA for distributed databases +DETAIL: schema usage in joins and in some UDFs provided by CitusDB are not supported yet +SELECT count(*) from tpch.nation; + count +------- + 25 +(1 row) + diff --git a/src/test/regress/output/multi_fdw_large_shardid.source b/src/test/regress/output/multi_fdw_large_shardid.source new file mode 100644 index 000000000..485280e68 --- /dev/null +++ b/src/test/regress/output/multi_fdw_large_shardid.source @@ -0,0 +1,59 @@ +-- +-- MULTI_FDW_LARGE_SHARDID +-- +-- Stage data to distributed tables, and run TPC-H query #1 and #6. This test +-- differs from previous tests in that it modifies the *internal* shardId +-- generator, forcing the distributed database to use 64-bit shard identifiers. +ALTER SEQUENCE pg_catalog.pg_dist_shardid_seq RESTART 100200300400500; +-- Stage additional data to start using large shard identifiers. +\STAGE lineitem FROM '@abs_srcdir@/data/lineitem.1.data' +NOTICE: extension "file_fdw" already exists, skipping +NOTICE: extension "file_fdw" already exists, skipping +\STAGE lineitem FROM '@abs_srcdir@/data/lineitem.2.data' +NOTICE: extension "file_fdw" already exists, skipping +NOTICE: extension "file_fdw" already exists, skipping +-- Query #1 from the TPC-H decision support benchmark. +SELECT + l_returnflag, + l_linestatus, + sum(l_quantity) as sum_qty, + sum(l_extendedprice) as sum_base_price, + sum(l_extendedprice * (1 - l_discount)) as sum_disc_price, + sum(l_extendedprice * (1 - l_discount) * (1 + l_tax)) as sum_charge, + avg(l_quantity) as avg_qty, + avg(l_extendedprice) as avg_price, + avg(l_discount) as avg_disc, + count(*) as count_order +FROM + lineitem +WHERE + l_shipdate <= date '1998-12-01' - interval '90 days' +GROUP BY + l_returnflag, + l_linestatus +ORDER BY + l_returnflag, + l_linestatus; + l_returnflag | l_linestatus | sum_qty | sum_base_price | sum_disc_price | sum_charge | avg_qty | avg_price | avg_disc | count_order +--------------+--------------+-----------+----------------+----------------+------------------+---------------------+--------------------+------------------------+------------- + A | F | 150930.00 | 227239747.26 | 215682574.1456 | 224342306.491846 | 25.6334918478260870 | 38593.707075407609 | 0.05055027173913043478 | 5888 + N | F | 4044.00 | 6205102.90 | 5905081.4236 | 6145285.541304 | 26.6052631578947368 | 40823.045394736842 | 0.05263157894736842105 | 152 + N | O | 299556.00 | 449413896.32 | 427269715.3708 | 444268143.859602 | 25.4594594594594595 | 38195.979629440762 | 0.04939486656467788543 | 11766 + R | F | 146312.00 | 217875959.46 | 207033247.3396 | 215487067.568656 | 25.2175112030334367 | 37551.871675284385 | 0.04983798690106859704 | 5802 +(4 rows) + +-- Query #6 from the TPC-H decision support benchmark. +SELECT + sum(l_extendedprice * l_discount) as revenue +FROM + lineitem +WHERE + l_shipdate >= date '1994-01-01' + and l_shipdate < date '1994-01-01' + interval '1 year' + and l_discount between 0.06 - 0.01 and 0.06 + 0.01 + and l_quantity < 24; + revenue +------------- + 486555.5716 +(1 row) + diff --git a/src/test/regress/output/multi_fdw_stage_data.source b/src/test/regress/output/multi_fdw_stage_data.source new file mode 100644 index 000000000..b32c1321b --- /dev/null +++ b/src/test/regress/output/multi_fdw_stage_data.source @@ -0,0 +1,28 @@ +-- +-- MULTI_FDW_STAGE_DATA +-- +-- Tests for staging foreign data in a distributed cluster. +\STAGE lineitem FROM '@abs_srcdir@/data/lineitem.1.data' +NOTICE: extension "file_fdw" already exists, skipping +NOTICE: extension "file_fdw" already exists, skipping +\STAGE lineitem FROM '@abs_srcdir@/data/lineitem.2.data' +NOTICE: extension "file_fdw" already exists, skipping +NOTICE: extension "file_fdw" already exists, skipping +\STAGE orders FROM '@abs_srcdir@/data/orders.1.data' +NOTICE: extension "file_fdw" already exists, skipping +NOTICE: extension "file_fdw" already exists, skipping +\STAGE orders FROM '@abs_srcdir@/data/orders.2.data' +NOTICE: extension "file_fdw" already exists, skipping +NOTICE: extension "file_fdw" already exists, skipping +SELECT set_config('citusdb.shard_replication_factor', '1', false); + set_config +------------ + 1 +(1 row) + +\STAGE customer FROM '@abs_srcdir@/data/customer.1.data' +NOTICE: extension "file_fdw" already exists, skipping +\STAGE nation FROM '@abs_srcdir@/data/nation.data' +NOTICE: extension "file_fdw" already exists, skipping +\STAGE part FROM '@abs_srcdir@/data/part.data' +NOTICE: extension "file_fdw" already exists, skipping diff --git a/src/test/regress/output/multi_large_shardid.source b/src/test/regress/output/multi_large_shardid.source new file mode 100644 index 000000000..65d8f6bda --- /dev/null +++ b/src/test/regress/output/multi_large_shardid.source @@ -0,0 +1,55 @@ +-- +-- MULTI_LARGE_SHARDID +-- +-- Stage data to distributed tables, and run TPC-H query #1 and #6. This test +-- differs from previous tests in that it modifies the *internal* shardId +-- generator, forcing the distributed database to use 64-bit shard identifiers. +ALTER SEQUENCE pg_catalog.pg_dist_shardid_seq RESTART 100200300400500; +-- Stage additional data to start using large shard identifiers. +\STAGE lineitem FROM '@abs_srcdir@/data/lineitem.1.data' with delimiter '|' +\STAGE lineitem FROM '@abs_srcdir@/data/lineitem.2.data' with delimiter '|' +-- Query #1 from the TPC-H decision support benchmark. +SELECT + l_returnflag, + l_linestatus, + sum(l_quantity) as sum_qty, + sum(l_extendedprice) as sum_base_price, + sum(l_extendedprice * (1 - l_discount)) as sum_disc_price, + sum(l_extendedprice * (1 - l_discount) * (1 + l_tax)) as sum_charge, + avg(l_quantity) as avg_qty, + avg(l_extendedprice) as avg_price, + avg(l_discount) as avg_disc, + count(*) as count_order +FROM + lineitem +WHERE + l_shipdate <= date '1998-12-01' - interval '90 days' +GROUP BY + l_returnflag, + l_linestatus +ORDER BY + l_returnflag, + l_linestatus; + l_returnflag | l_linestatus | sum_qty | sum_base_price | sum_disc_price | sum_charge | avg_qty | avg_price | avg_disc | count_order +--------------+--------------+-----------+----------------+----------------+------------------+---------------------+--------------------+------------------------+------------- + A | F | 150930.00 | 227239747.26 | 215682574.1456 | 224342306.491846 | 25.6334918478260870 | 38593.707075407609 | 0.05055027173913043478 | 5888 + N | F | 4044.00 | 6205102.90 | 5905081.4236 | 6145285.541304 | 26.6052631578947368 | 40823.045394736842 | 0.05263157894736842105 | 152 + N | O | 299556.00 | 449413896.32 | 427269715.3708 | 444268143.859602 | 25.4594594594594595 | 38195.979629440762 | 0.04939486656467788543 | 11766 + R | F | 146312.00 | 217875959.46 | 207033247.3396 | 215487067.568656 | 25.2175112030334367 | 37551.871675284385 | 0.04983798690106859704 | 5802 +(4 rows) + +-- Query #6 from the TPC-H decision support benchmark. +SELECT + sum(l_extendedprice * l_discount) as revenue +FROM + lineitem +WHERE + l_shipdate >= date '1994-01-01' + and l_shipdate < date '1994-01-01' + interval '1 year' + and l_discount between 0.06 - 0.01 and 0.06 + 0.01 + and l_quantity < 24; + revenue +------------- + 486555.5716 +(1 row) + diff --git a/src/test/regress/output/multi_master_delete_protocol.source b/src/test/regress/output/multi_master_delete_protocol.source new file mode 100644 index 000000000..1306eb668 --- /dev/null +++ b/src/test/regress/output/multi_master_delete_protocol.source @@ -0,0 +1,88 @@ +-- +-- MULTI_MASTER_DELETE_PROTOCOL +-- +-- Create a new range partitioned customer_delete_protocol table and stage data into it. +CREATE TABLE customer_delete_protocol ( + c_custkey integer not null, + c_name varchar(25) not null, + c_address varchar(40) not null, + c_nationkey integer not null, + c_phone char(15) not null, + c_acctbal decimal(15,2) not null, + c_mktsegment char(10) not null, + c_comment varchar(117) not null); +SELECT master_create_distributed_table('customer_delete_protocol', 'c_custkey', 'append'); + master_create_distributed_table +--------------------------------- + +(1 row) + +\STAGE customer_delete_protocol FROM '@abs_srcdir@/data/customer.1.data' with delimiter '|' +\STAGE customer_delete_protocol FROM '@abs_srcdir@/data/customer.2.data' with delimiter '|' +\STAGE customer_delete_protocol FROM '@abs_srcdir@/data/customer.3.data' with delimiter '|' +-- Check that we don't support conditions on columns other than partition key. +SELECT master_apply_delete_command('DELETE FROM customer_delete_protocol + WHERE c_acctbal > 0.0'); +ERROR: cannot delete from distributed table +DETAIL: Where clause includes a column other than partition column +-- Check that we delete a shard if and only if all rows in the shard satisfy the condition. +SELECT master_apply_delete_command('DELETE FROM customer_delete_protocol + WHERE c_custkey > 6500'); + master_apply_delete_command +----------------------------- + 0 +(1 row) + +SELECT count(*) from customer_delete_protocol; + count +------- + 3000 +(1 row) + +-- Delete one shard that satisfies the given conditions. +SELECT master_apply_delete_command('DELETE FROM customer_delete_protocol + WHERE c_custkey > 1000 AND c_custkey < 3000'); + master_apply_delete_command +----------------------------- + 1 +(1 row) + +SELECT count(*) from customer_delete_protocol; + count +------- + 2000 +(1 row) + +-- Delete all shards if no condition is provided. +SELECT master_apply_delete_command('DELETE FROM customer_delete_protocol'); + master_apply_delete_command +----------------------------- + 2 +(1 row) + +SELECT count(*) FROM customer_delete_protocol; + count +------- + +(1 row) + +-- Verify that empty shards are deleted if no condition is provided +SELECT master_create_empty_shard('customer_delete_protocol'); + master_create_empty_shard +--------------------------- + 102041 +(1 row) + +SELECT master_apply_delete_command('DELETE FROM customer_delete_protocol + WHERE c_custkey > 1000'); + master_apply_delete_command +----------------------------- + 0 +(1 row) + +SELECT master_apply_delete_command('DELETE FROM customer_delete_protocol'); + master_apply_delete_command +----------------------------- + 1 +(1 row) + diff --git a/src/test/regress/output/multi_outer_join.source b/src/test/regress/output/multi_outer_join.source new file mode 100644 index 000000000..02e0ce21f --- /dev/null +++ b/src/test/regress/output/multi_outer_join.source @@ -0,0 +1,714 @@ +SET citusdb.large_table_shard_count TO 2; +SET citusdb.log_multi_join_order to true; +SET client_min_messages TO LOG; +CREATE TABLE multi_outer_join_left +( + l_custkey integer not null, + l_name varchar(25) not null, + l_address varchar(40) not null, + l_nationkey integer not null, + l_phone char(15) not null, + l_acctbal decimal(15,2) not null, + l_mktsegment char(10) not null, + l_comment varchar(117) not null +); +SELECT master_create_distributed_table('multi_outer_join_left', 'l_custkey', 'append'); + master_create_distributed_table +--------------------------------- + +(1 row) + +CREATE TABLE multi_outer_join_right +( + r_custkey integer not null, + r_name varchar(25) not null, + r_address varchar(40) not null, + r_nationkey integer not null, + r_phone char(15) not null, + r_acctbal decimal(15,2) not null, + r_mktsegment char(10) not null, + r_comment varchar(117) not null +); +SELECT master_create_distributed_table('multi_outer_join_right', 'r_custkey', 'append'); + master_create_distributed_table +--------------------------------- + +(1 row) + +CREATE TABLE multi_outer_join_third +( + t_custkey integer not null, + t_name varchar(25) not null, + t_address varchar(40) not null, + t_nationkey integer not null, + t_phone char(15) not null, + t_acctbal decimal(15,2) not null, + t_mktsegment char(10) not null, + t_comment varchar(117) not null +); +SELECT master_create_distributed_table('multi_outer_join_third', 't_custkey', 'append'); + master_create_distributed_table +--------------------------------- + +(1 row) + +-- Make sure we do not crash if both tables have no shards +SELECT + min(l_custkey), max(l_custkey) +FROM + multi_outer_join_left a LEFT JOIN multi_outer_join_third b ON (l_custkey = t_custkey); +ERROR: cannot perform distributed planning on this query +DETAIL: Shards of relations in outer join queries must have 1-to-1 shard partitioning +-- Left table is a large table +\STAGE multi_outer_join_left FROM '@abs_srcdir@/data/customer-1-10.data' with delimiter '|' +\STAGE multi_outer_join_left FROM '@abs_srcdir@/data/customer-11-20.data' with delimiter '|' +-- Right table is a small table +\STAGE multi_outer_join_right FROM '@abs_srcdir@/data/customer-1-15.data' with delimiter '|' +-- Make sure we do not crash if one table has no shards +SELECT + min(l_custkey), max(l_custkey) +FROM + multi_outer_join_left a LEFT JOIN multi_outer_join_third b ON (l_custkey = t_custkey); +ERROR: cannot perform distributed planning on this query +DETAIL: Shards of relations in outer join queries must have 1-to-1 shard partitioning +SELECT + min(t_custkey), max(t_custkey) +FROM + multi_outer_join_third a LEFT JOIN multi_outer_join_right b ON (r_custkey = t_custkey); +LOG: join order: [ "multi_outer_join_third" ][ broadcast join "multi_outer_join_right" ] + min | max +-----+----- + | +(1 row) + +-- Third table is a single shard table with all data +\STAGE multi_outer_join_third FROM '@abs_srcdir@/data/customer-1-30.data' with delimiter '|' +-- Regular outer join should return results for all rows +SELECT + min(l_custkey), max(l_custkey) +FROM + multi_outer_join_left a LEFT JOIN multi_outer_join_right b ON (l_custkey = r_custkey); +LOG: join order: [ "multi_outer_join_left" ][ broadcast join "multi_outer_join_right" ] + min | max +-----+----- + 1 | 20 +(1 row) + +-- Since this is a broadcast join, we should be able to join on any key +SELECT + count(*) +FROM + multi_outer_join_left a LEFT JOIN multi_outer_join_right b ON (l_nationkey = r_nationkey); +LOG: join order: [ "multi_outer_join_left" ][ broadcast join "multi_outer_join_right" ] + count +------- + 28 +(1 row) + +-- Anti-join should return customers for which there is no row in the right table +SELECT + min(l_custkey), max(l_custkey) +FROM + multi_outer_join_left a LEFT JOIN multi_outer_join_right b ON (l_custkey = r_custkey) +WHERE + r_custkey IS NULL; +LOG: join order: [ "multi_outer_join_left" ][ broadcast join "multi_outer_join_right" ] + min | max +-----+----- + 16 | 20 +(1 row) + +-- Partial anti-join with specific value +SELECT + min(l_custkey), max(l_custkey) +FROM + multi_outer_join_left a LEFT JOIN multi_outer_join_right b ON (l_custkey = r_custkey) +WHERE + r_custkey IS NULL OR r_custkey = 5; +LOG: join order: [ "multi_outer_join_left" ][ broadcast join "multi_outer_join_right" ] + min | max +-----+----- + 5 | 20 +(1 row) + +-- This query is an INNER JOIN in disguise since there cannot be NULL results +SELECT + min(l_custkey), max(l_custkey) +FROM + multi_outer_join_left a LEFT JOIN multi_outer_join_right b ON (l_custkey = r_custkey) +WHERE + r_custkey = 5; +LOG: join order: [ "multi_outer_join_left" ][ broadcast join "multi_outer_join_right" ] + min | max +-----+----- + 5 | 5 +(1 row) + +-- Right join should be disallowed in this case +SELECT + min(r_custkey), max(r_custkey) +FROM + multi_outer_join_left a RIGHT JOIN multi_outer_join_right b ON (l_custkey = r_custkey); +ERROR: cannot perform distributed planning on this query +DETAIL: Shards of relations in outer join queries must have 1-to-1 shard partitioning +-- Reverse right join should be same as left join +SELECT + min(l_custkey), max(l_custkey) +FROM + multi_outer_join_right a RIGHT JOIN multi_outer_join_left b ON (l_custkey = r_custkey); +LOG: join order: [ "multi_outer_join_left" ][ broadcast join "multi_outer_join_right" ] + min | max +-----+----- + 1 | 20 +(1 row) + +-- Turn the right table into a large table +\STAGE multi_outer_join_right FROM '@abs_srcdir@/data/customer-21-30.data' with delimiter '|' +-- Shards do not have 1-1 matching. We should error here. +SELECT + min(l_custkey), max(l_custkey) +FROM + multi_outer_join_left a LEFT JOIN multi_outer_join_right b ON (l_custkey = r_custkey); +ERROR: cannot perform distributed planning on this query +DETAIL: Shards of relations in outer join queries must have 1-to-1 shard partitioning +-- empty tables +SELECT * FROM master_apply_delete_command('DELETE FROM multi_outer_join_left'); + master_apply_delete_command +----------------------------- + 2 +(1 row) + +SELECT * FROM master_apply_delete_command('DELETE FROM multi_outer_join_right'); + master_apply_delete_command +----------------------------- + 2 +(1 row) + +-- reload shards with 1-1 matching +\STAGE multi_outer_join_left FROM '@abs_srcdir@/data/customer-1-15.data' with delimiter '|' +\STAGE multi_outer_join_left FROM '@abs_srcdir@/data/customer-21-30.data' with delimiter '|' +\STAGE multi_outer_join_right FROM '@abs_srcdir@/data/customer-11-20.data' with delimiter '|' +\STAGE multi_outer_join_right FROM '@abs_srcdir@/data/customer-21-30.data' with delimiter '|' +-- multi_outer_join_third is a single shard table +-- Regular left join should work as expected +SELECT + min(l_custkey), max(l_custkey) +FROM + multi_outer_join_left a LEFT JOIN multi_outer_join_right b ON (l_custkey = r_custkey); +LOG: join order: [ "multi_outer_join_left" ][ local partition join "multi_outer_join_right" ] + min | max +-----+----- + 1 | 30 +(1 row) + +-- Since we cannot broadcast or re-partition, joining on a different key should error out +SELECT + count(*) +FROM + multi_outer_join_left a LEFT JOIN multi_outer_join_right b ON (l_nationkey = r_nationkey); +ERROR: cannot perform distributed planning on this query +DETAIL: Shards of relations in outer join queries must have 1-to-1 shard partitioning +-- Anti-join should return customers for which there is no row in the right table +SELECT + min(l_custkey), max(l_custkey) +FROM + multi_outer_join_left a LEFT JOIN multi_outer_join_right b ON (l_custkey = r_custkey) +WHERE + r_custkey IS NULL; +LOG: join order: [ "multi_outer_join_left" ][ local partition join "multi_outer_join_right" ] + min | max +-----+----- + 1 | 10 +(1 row) + +-- Partial anti-join with specific value (5, 11-15) +SELECT + min(l_custkey), max(l_custkey) +FROM + multi_outer_join_left a LEFT JOIN multi_outer_join_right b ON (l_custkey = r_custkey) +WHERE + r_custkey IS NULL OR r_custkey = 15; +LOG: join order: [ "multi_outer_join_left" ][ local partition join "multi_outer_join_right" ] + min | max +-----+----- + 1 | 15 +(1 row) + +-- This query is an INNER JOIN in disguise since there cannot be NULL results (21) +SELECT + min(l_custkey), max(l_custkey) +FROM + multi_outer_join_left a LEFT JOIN multi_outer_join_right b ON (l_custkey = r_custkey) +WHERE + r_custkey = 21; +LOG: join order: [ "multi_outer_join_left" ][ local partition join "multi_outer_join_right" ] + min | max +-----+----- + 21 | 21 +(1 row) + +-- Right join should be allowed in this case +SELECT + min(r_custkey), max(r_custkey) +FROM + multi_outer_join_left a RIGHT JOIN multi_outer_join_right b ON (l_custkey = r_custkey); +LOG: join order: [ "multi_outer_join_right" ][ local partition join "multi_outer_join_left" ] + min | max +-----+----- + 11 | 30 +(1 row) + +-- Reverse right join should be same as left join +SELECT + min(l_custkey), max(l_custkey) +FROM + multi_outer_join_right a RIGHT JOIN multi_outer_join_left b ON (l_custkey = r_custkey); +LOG: join order: [ "multi_outer_join_left" ][ local partition join "multi_outer_join_right" ] + min | max +-----+----- + 1 | 30 +(1 row) + +-- complex query tree should error out +SELECT + * +FROM + multi_outer_join_left l1 + LEFT JOIN multi_outer_join_right r1 ON (l1.l_custkey = r1.r_custkey) + LEFT JOIN multi_outer_join_right r2 ON (l1.l_custkey = r2.r_custkey) + RIGHT JOIN multi_outer_join_left l2 ON (r2.r_custkey = l2.l_custkey); +ERROR: cannot perform distributed planning on this query +DETAIL: Complex join orders are currently unsupported +-- add an anti-join, this should also error out +SELECT + * +FROM + multi_outer_join_left l1 + LEFT JOIN multi_outer_join_right r1 ON (l1.l_custkey = r1.r_custkey) + LEFT JOIN multi_outer_join_right r2 ON (l1.l_custkey = r2.r_custkey) + RIGHT JOIN multi_outer_join_left l2 ON (r2.r_custkey = l2.l_custkey) +WHERE + r1.r_custkey is NULL; +ERROR: cannot perform distributed planning on this query +DETAIL: Complex join orders are currently unsupported +-- Three way join 2-2-1 (local + broadcast join) should work +SELECT + l_custkey, r_custkey, t_custkey +FROM + multi_outer_join_left l1 + LEFT JOIN multi_outer_join_right r1 ON (l1.l_custkey = r1.r_custkey) + LEFT JOIN multi_outer_join_third t1 ON (r1.r_custkey = t1.t_custkey); +LOG: join order: [ "multi_outer_join_left" ][ local partition join "multi_outer_join_right" ][ broadcast join "multi_outer_join_third" ] + l_custkey | r_custkey | t_custkey +-----------+-----------+----------- + 21 | 21 | 21 + 22 | 22 | 22 + 23 | 23 | 23 + 24 | 24 | 24 + 25 | 25 | 25 + 26 | 26 | 26 + 27 | 27 | 27 + 28 | 28 | 28 + 29 | 29 | 29 + 30 | 30 | 30 + 1 | | + 2 | | + 3 | | + 4 | | + 5 | | + 6 | | + 7 | | + 8 | | + 9 | | + 10 | | + 11 | 11 | 11 + 12 | 12 | 12 + 13 | 13 | 13 + 14 | 14 | 14 + 15 | 15 | 15 +(25 rows) + +-- Right join with single shard right most table should error out +SELECT + l_custkey, r_custkey, t_custkey +FROM + multi_outer_join_left l1 + LEFT JOIN multi_outer_join_right r1 ON (l1.l_custkey = r1.r_custkey) + RIGHT JOIN multi_outer_join_third t1 ON (r1.r_custkey = t1.t_custkey); +ERROR: cannot perform distributed planning on this query +DETAIL: Complex join orders are currently unsupported +-- Right join with single shard left most table should work +SELECT + t_custkey, r_custkey, l_custkey +FROM + multi_outer_join_third t1 + RIGHT JOIN multi_outer_join_right r1 ON (t1.t_custkey = r1.r_custkey) + LEFT JOIN multi_outer_join_left l1 ON (r1.r_custkey = l1.l_custkey); +LOG: join order: [ "multi_outer_join_right" ][ broadcast join "multi_outer_join_third" ][ local partition join "multi_outer_join_left" ] + t_custkey | r_custkey | l_custkey +-----------+-----------+----------- + 21 | 21 | 21 + 22 | 22 | 22 + 23 | 23 | 23 + 24 | 24 | 24 + 25 | 25 | 25 + 26 | 26 | 26 + 27 | 27 | 27 + 28 | 28 | 28 + 29 | 29 | 29 + 30 | 30 | 30 + 11 | 11 | 11 + 12 | 12 | 12 + 13 | 13 | 13 + 14 | 14 | 14 + 15 | 15 | 15 + 16 | 16 | + 17 | 17 | + 18 | 18 | + 19 | 19 | + 20 | 20 | +(20 rows) + +-- Make it anti-join, should display values with l_custkey is null +SELECT + t_custkey, r_custkey, l_custkey +FROM + multi_outer_join_third t1 + RIGHT JOIN multi_outer_join_right r1 ON (t1.t_custkey = r1.r_custkey) + LEFT JOIN multi_outer_join_left l1 ON (r1.r_custkey = l1.l_custkey) +WHERE + l_custkey is NULL; +LOG: join order: [ "multi_outer_join_right" ][ broadcast join "multi_outer_join_third" ][ local partition join "multi_outer_join_left" ] + t_custkey | r_custkey | l_custkey +-----------+-----------+----------- + 16 | 16 | + 17 | 17 | + 18 | 18 | + 19 | 19 | + 20 | 20 | +(5 rows) + +-- Cascading right join with single shard left most table should error out +SELECT + t_custkey, r_custkey, l_custkey +FROM + multi_outer_join_third t1 + RIGHT JOIN multi_outer_join_right r1 ON (t1.t_custkey = r1.r_custkey) + RIGHT JOIN multi_outer_join_left l1 ON (r1.r_custkey = l1.l_custkey); +ERROR: cannot perform distributed planning on this query +DETAIL: Complex join orders are currently unsupported +-- full outer join should work with 1-1 matched shards +SELECT + l_custkey, r_custkey +FROM + multi_outer_join_left l1 + FULL JOIN multi_outer_join_right r1 ON (l1.l_custkey = r1.r_custkey); +LOG: join order: [ "multi_outer_join_left" ][ local partition join "multi_outer_join_right" ] + l_custkey | r_custkey +-----------+----------- + 21 | 21 + 22 | 22 + 23 | 23 + 24 | 24 + 25 | 25 + 26 | 26 + 27 | 27 + 28 | 28 + 29 | 29 + 30 | 30 + 1 | + 2 | + 3 | + 4 | + 5 | + 6 | + 7 | + 8 | + 9 | + 10 | + 11 | 11 + 12 | 12 + 13 | 13 + 14 | 14 + 15 | 15 + | 20 + | 17 + | 18 + | 19 + | 16 +(30 rows) + +-- full outer join + anti (right) should work with 1-1 matched shards +SELECT + l_custkey, r_custkey +FROM + multi_outer_join_left l1 + FULL JOIN multi_outer_join_right r1 ON (l1.l_custkey = r1.r_custkey) +WHERE + r_custkey is NULL; +LOG: join order: [ "multi_outer_join_left" ][ local partition join "multi_outer_join_right" ] + l_custkey | r_custkey +-----------+----------- + 1 | + 2 | + 3 | + 4 | + 5 | + 6 | + 7 | + 8 | + 9 | + 10 | +(10 rows) + +-- full outer join + anti (left) should work with 1-1 matched shards +SELECT + l_custkey, r_custkey +FROM + multi_outer_join_left l1 + FULL JOIN multi_outer_join_right r1 ON (l1.l_custkey = r1.r_custkey) +WHERE + l_custkey is NULL; +LOG: join order: [ "multi_outer_join_left" ][ local partition join "multi_outer_join_right" ] + l_custkey | r_custkey +-----------+----------- + | 20 + | 17 + | 18 + | 19 + | 16 +(5 rows) + +-- full outer join + anti (both) should work with 1-1 matched shards +SELECT + l_custkey, r_custkey +FROM + multi_outer_join_left l1 + FULL JOIN multi_outer_join_right r1 ON (l1.l_custkey = r1.r_custkey) +WHERE + l_custkey is NULL or r_custkey is NULL; +LOG: join order: [ "multi_outer_join_left" ][ local partition join "multi_outer_join_right" ] + l_custkey | r_custkey +-----------+----------- + 1 | + 2 | + 3 | + 4 | + 5 | + 6 | + 7 | + 8 | + 9 | + 10 | + | 20 + | 17 + | 18 + | 19 + | 16 +(15 rows) + +-- full outer join should error out for mismatched shards +SELECT + l_custkey, t_custkey +FROM + multi_outer_join_left l1 + FULL JOIN multi_outer_join_third t1 ON (l1.l_custkey = t1.t_custkey); +ERROR: cannot perform distributed planning on this query +DETAIL: Shards of relations in outer join queries must have 1-to-1 shard partitioning +-- inner join + single shard left join should work +SELECT + l_custkey, r_custkey, t_custkey +FROM + multi_outer_join_left l1 + INNER JOIN multi_outer_join_right r1 ON (l1.l_custkey = r1.r_custkey) + LEFT JOIN multi_outer_join_third t1 ON (r1.r_custkey = t1.t_custkey); +LOG: join order: [ "multi_outer_join_left" ][ local partition join "multi_outer_join_right" ][ broadcast join "multi_outer_join_third" ] + l_custkey | r_custkey | t_custkey +-----------+-----------+----------- + 21 | 21 | 21 + 22 | 22 | 22 + 23 | 23 | 23 + 24 | 24 | 24 + 25 | 25 | 25 + 26 | 26 | 26 + 27 | 27 | 27 + 28 | 28 | 28 + 29 | 29 | 29 + 30 | 30 | 30 + 11 | 11 | 11 + 12 | 12 | 12 + 13 | 13 | 13 + 14 | 14 | 14 + 15 | 15 | 15 +(15 rows) + +-- inner (broadcast) join + 2 shards left (local) join should work +SELECT + l_custkey, t_custkey, r_custkey +FROM + multi_outer_join_left l1 + INNER JOIN multi_outer_join_third t1 ON (l1.l_custkey = t1.t_custkey) + LEFT JOIN multi_outer_join_right r1 ON (l1.l_custkey = r1.r_custkey); +LOG: join order: [ "multi_outer_join_left" ][ broadcast join "multi_outer_join_third" ][ local partition join "multi_outer_join_right" ] + l_custkey | t_custkey | r_custkey +-----------+-----------+----------- + 21 | 21 | 21 + 22 | 22 | 22 + 23 | 23 | 23 + 24 | 24 | 24 + 25 | 25 | 25 + 26 | 26 | 26 + 27 | 27 | 27 + 28 | 28 | 28 + 29 | 29 | 29 + 30 | 30 | 30 + 1 | 1 | + 2 | 2 | + 3 | 3 | + 4 | 4 | + 5 | 5 | + 6 | 6 | + 7 | 7 | + 8 | 8 | + 9 | 9 | + 10 | 10 | + 11 | 11 | 11 + 12 | 12 | 12 + 13 | 13 | 13 + 14 | 14 | 14 + 15 | 15 | 15 +(25 rows) + +-- inner (local) join + 2 shards left (dual partition) join should error out +SELECT + t_custkey, l_custkey, r_custkey +FROM + multi_outer_join_third t1 + INNER JOIN multi_outer_join_left l1 ON (l1.l_custkey = t1.t_custkey) + LEFT JOIN multi_outer_join_right r1 ON (l1.l_custkey = r1.r_custkey); +ERROR: cannot perform distributed planning on this query +DETAIL: Shards of relations in outer join queries must have 1-to-1 shard partitioning +-- inner (local) join + 2 shards left (dual partition) join should error out +SELECT + l_custkey, t_custkey, r_custkey +FROM + multi_outer_join_left l1 + INNER JOIN multi_outer_join_third t1 ON (l1.l_custkey = t1.t_custkey) + LEFT JOIN multi_outer_join_right r1 ON (l1.l_custkey = r1.r_custkey); +LOG: join order: [ "multi_outer_join_left" ][ broadcast join "multi_outer_join_third" ][ local partition join "multi_outer_join_right" ] + l_custkey | t_custkey | r_custkey +-----------+-----------+----------- + 21 | 21 | 21 + 22 | 22 | 22 + 23 | 23 | 23 + 24 | 24 | 24 + 25 | 25 | 25 + 26 | 26 | 26 + 27 | 27 | 27 + 28 | 28 | 28 + 29 | 29 | 29 + 30 | 30 | 30 + 1 | 1 | + 2 | 2 | + 3 | 3 | + 4 | 4 | + 5 | 5 | + 6 | 6 | + 7 | 7 | + 8 | 8 | + 9 | 9 | + 10 | 10 | + 11 | 11 | 11 + 12 | 12 | 12 + 13 | 13 | 13 + 14 | 14 | 14 + 15 | 15 | 15 +(25 rows) + +-- inner (broadcast) join + 2 shards left (local) + anti join should work +SELECT + l_custkey, t_custkey, r_custkey +FROM + multi_outer_join_left l1 + INNER JOIN multi_outer_join_third t1 ON (l1.l_custkey = t1.t_custkey) + LEFT JOIN multi_outer_join_right r1 ON (l1.l_custkey = r1.r_custkey) +WHERE + r_custkey is NULL; +LOG: join order: [ "multi_outer_join_left" ][ broadcast join "multi_outer_join_third" ][ local partition join "multi_outer_join_right" ] + l_custkey | t_custkey | r_custkey +-----------+-----------+----------- + 1 | 1 | + 2 | 2 | + 3 | 3 | + 4 | 4 | + 5 | 5 | + 6 | 6 | + 7 | 7 | + 8 | 8 | + 9 | 9 | + 10 | 10 | +(10 rows) + +-- Test joinExpr aliases by performing an outer-join. +SELECT + t_custkey +FROM + (multi_outer_join_right r1 + LEFT OUTER JOIN multi_outer_join_left l1 ON (l1.l_custkey = r1.r_custkey)) AS + test(c_custkey, c_nationkey) + INNER JOIN multi_outer_join_third t1 ON (test.c_custkey = t1.t_custkey); +LOG: join order: [ "multi_outer_join_right" ][ local partition join "multi_outer_join_left" ][ broadcast join "multi_outer_join_third" ] + t_custkey +----------- + 21 + 22 + 23 + 24 + 25 + 26 + 27 + 28 + 29 + 30 + 11 + 12 + 13 + 14 + 15 + 16 + 17 + 18 + 19 + 20 +(20 rows) + +-- Add a shard to the left table that overlaps with multiple shards in the right +\STAGE multi_outer_join_left FROM '@abs_srcdir@/data/customer.1.data' with delimiter '|' +-- All outer joins should error out +SELECT + min(l_custkey), max(l_custkey) +FROM + multi_outer_join_left a LEFT JOIN multi_outer_join_right b ON (l_custkey = r_custkey); +ERROR: cannot perform distributed planning on this query +DETAIL: Shards of relations in outer join queries must have 1-to-1 shard partitioning +SELECT + min(l_custkey), max(l_custkey) +FROM + multi_outer_join_left a RIGHT JOIN multi_outer_join_right b ON (l_custkey = r_custkey); +ERROR: cannot perform distributed planning on this query +DETAIL: Shards of relations in outer join queries must have 1-to-1 shard partitioning +SELECT + min(l_custkey), max(l_custkey) +FROM + multi_outer_join_left a FULL JOIN multi_outer_join_right b ON (l_custkey = r_custkey); +ERROR: cannot perform distributed planning on this query +DETAIL: Shards of relations in outer join queries must have 1-to-1 shard partitioning +SELECT + t_custkey +FROM + (multi_outer_join_right r1 + LEFT OUTER JOIN multi_outer_join_left l1 ON (l1.l_custkey = r1.r_custkey)) AS + test(c_custkey, c_nationkey) + INNER JOIN multi_outer_join_third t1 ON (test.c_custkey = t1.t_custkey); +ERROR: cannot perform distributed planning on this query +DETAIL: Shards of relations in outer join queries must have 1-to-1 shard partitioning diff --git a/src/test/regress/output/multi_stage_data.source b/src/test/regress/output/multi_stage_data.source new file mode 100644 index 000000000..58a8b15a0 --- /dev/null +++ b/src/test/regress/output/multi_stage_data.source @@ -0,0 +1,31 @@ +-- +-- MULTI_STAGE_DATA +-- +-- Tests for staging data in a distributed cluster. Please note that the number +-- of shards uploaded depends on two config values: citusdb.shard_replication_factor and +-- citusdb.shard_max_size. These values are manually set in pg_regress.c. We also set +-- the shard placement policy to the local-node-first policy as other regression +-- tests expect the placements to be in that order. +SET citusdb.shard_placement_policy TO 'local-node-first'; +\STAGE lineitem FROM '@abs_srcdir@/data/lineitem.1.data' with delimiter '|' +\STAGE lineitem FROM '@abs_srcdir@/data/lineitem.2.data' with delimiter '|' +\STAGE orders FROM '@abs_srcdir@/data/orders.1.data' with delimiter '|' +\STAGE orders FROM '@abs_srcdir@/data/orders.2.data' with delimiter '|' +\STAGE customer FROM '@abs_srcdir@/data/customer.1.data' with delimiter '|' +\STAGE nation FROM '@abs_srcdir@/data/nation.data' with delimiter '|' +\STAGE part FROM '@abs_srcdir@/data/part.data' with delimiter '|' +\STAGE supplier FROM '@abs_srcdir@/data/supplier.data' with delimiter '|' +-- check that we error out if we try to stage into a hash partitioned table +CREATE TABLE nation_hash_partitioned ( + n_nationkey integer not null, + n_name char(25) not null, + n_regionkey integer not null, + n_comment varchar(152)); +SELECT master_create_distributed_table('nation_hash_partitioned', 'n_nationkey', 'hash'); + master_create_distributed_table +--------------------------------- + +(1 row) + +\STAGE nation_hash_partitioned FROM '@abs_srcdir@/data/nation.data' with delimiter '|' +\stage: staging data into hash partitioned tables is not supported diff --git a/src/test/regress/output/multi_stage_large_records.source b/src/test/regress/output/multi_stage_large_records.source new file mode 100644 index 000000000..a8e7549f3 --- /dev/null +++ b/src/test/regress/output/multi_stage_large_records.source @@ -0,0 +1,25 @@ +-- +-- MULTI_STAGE_LARGE_RECORDS +-- +-- Tests for staging data with large records (i.e. greater than the read buffer +-- size, which is 32kB) in a distributed cluster. These tests make sure that we +-- are creating shards of correct size even when records are large. +SET citusdb.shard_max_size TO "256kB"; +CREATE TABLE large_records_table (data_id integer, data text); +SELECT master_create_distributed_table('large_records_table', 'data_id', 'append'); + master_create_distributed_table +--------------------------------- + +(1 row) + +\STAGE large_records_table FROM '@abs_srcdir@/data/large_records.data' with delimiter '|' +SELECT shardminvalue, shardmaxvalue FROM pg_dist_shard, pg_class + WHERE pg_class.oid=logicalrelid AND relname='large_records_table' + ORDER BY shardid; + shardminvalue | shardmaxvalue +---------------+--------------- + 1 | 1 + 2 | 2 +(2 rows) + +RESET citusdb.shard_max_size; diff --git a/src/test/regress/output/multi_stage_more_data.source b/src/test/regress/output/multi_stage_more_data.source new file mode 100644 index 000000000..d4b95c01d --- /dev/null +++ b/src/test/regress/output/multi_stage_more_data.source @@ -0,0 +1,12 @@ +-- +-- MULTI_STAGE_MORE_DATA +-- +-- We stage more data to customer and part tables to test distributed joins. The +-- staging causes the planner to consider customer and part tables as large, and +-- evaluate plans where some of the underlying tables need to be repartitioned. +-- We also set the shard placement policy to the local-node-first policy as other +-- regression tests expect the placements to be in that order. +SET citusdb.shard_placement_policy TO 'local-node-first'; +\STAGE customer FROM '@abs_srcdir@/data/customer.2.data' with delimiter '|' +\STAGE customer FROM '@abs_srcdir@/data/customer.3.data' with delimiter '|' +\STAGE part FROM '@abs_srcdir@/data/part.more.data' with delimiter '|' diff --git a/src/test/regress/output/multi_subquery.source b/src/test/regress/output/multi_subquery.source new file mode 100644 index 000000000..84e38aa5c --- /dev/null +++ b/src/test/regress/output/multi_subquery.source @@ -0,0 +1,328 @@ +-- +-- MULTI_SUBQUERY +-- +-- Create tables for subquery tests +CREATE TABLE lineitem_subquery ( + l_orderkey bigint not null, + l_partkey integer not null, + l_suppkey integer not null, + l_linenumber integer not null, + l_quantity decimal(15, 2) not null, + l_extendedprice decimal(15, 2) not null, + l_discount decimal(15, 2) not null, + l_tax decimal(15, 2) not null, + l_returnflag char(1) not null, + l_linestatus char(1) not null, + l_shipdate date not null, + l_commitdate date not null, + l_receiptdate date not null, + l_shipinstruct char(25) not null, + l_shipmode char(10) not null, + l_comment varchar(44) not null, + PRIMARY KEY(l_orderkey, l_linenumber) ); +SELECT master_create_distributed_table('lineitem_subquery', 'l_orderkey', 'range'); + master_create_distributed_table +--------------------------------- + +(1 row) + +CREATE TABLE orders_subquery ( + o_orderkey bigint not null, + o_custkey integer not null, + o_orderstatus char(1) not null, + o_totalprice decimal(15,2) not null, + o_orderdate date not null, + o_orderpriority char(15) not null, + o_clerk char(15) not null, + o_shippriority integer not null, + o_comment varchar(79) not null, + PRIMARY KEY(o_orderkey) ); +SELECT master_create_distributed_table('orders_subquery', 'o_orderkey', 'range'); + master_create_distributed_table +--------------------------------- + +(1 row) + +SET citusdb.task_executor_type TO 'task-tracker'; +-- Check that we don't allow subquery pushdown in default settings. +SELECT + avg(unit_price) +FROM + (SELECT + l_orderkey, + avg(o_totalprice) AS unit_price + FROM + lineitem_subquery, + orders_subquery + WHERE + l_orderkey = o_orderkey + GROUP BY + l_orderkey) AS unit_prices; +ERROR: cannot perform distributed planning on this query +DETAIL: Join in subqueries is not supported yet +SET citusdb.subquery_pushdown to TRUE; +-- Check that we don't crash if there are not any shards. +SELECT + avg(unit_price) +FROM + (SELECT + l_orderkey, + avg(o_totalprice) AS unit_price + FROM + lineitem_subquery, + orders_subquery + WHERE + l_orderkey = o_orderkey + GROUP BY + l_orderkey) AS unit_prices; + avg +----- + +(1 row) + +-- Stage data to tables. +SET citusdb.shard_max_size TO "1MB"; +\STAGE lineitem_subquery FROM '@abs_srcdir@/data/lineitem.1.data' with delimiter '|' +\STAGE lineitem_subquery FROM '@abs_srcdir@/data/lineitem.2.data' with delimiter '|' +\STAGE orders_subquery FROM '@abs_srcdir@/data/orders.1.data' with delimiter '|' +\STAGE orders_subquery FROM '@abs_srcdir@/data/orders.2.data' with delimiter '|' +-- Check that we error out if shard min/max values are not exactly same. +SELECT + avg(unit_price) +FROM + (SELECT + l_orderkey, + avg(o_totalprice) AS unit_price + FROM + lineitem_subquery, + orders_subquery + WHERE + l_orderkey = o_orderkey + GROUP BY + l_orderkey) AS unit_prices; +ERROR: cannot push down this subquery +DETAIL: Shards of relations in subquery need to have 1-to-1 shard partitioning +-- Update metadata in order to make all shards equal. +UPDATE pg_dist_shard SET shardmaxvalue = '14947' WHERE shardid = 102024; +-- If group by is not on partition column then we error out. +SELECT + avg(order_count) +FROM + (SELECT + l_suppkey, + count(*) AS order_count + FROM + lineitem_subquery + GROUP BY + l_suppkey) AS order_counts; +ERROR: cannot push down this subquery +DETAIL: Group by list without partition column is currently unsupported +-- Check that we error out if join is not on partition columns. +SELECT + avg(unit_price) +FROM + (SELECT + l_orderkey, + avg(o_totalprice / l_quantity) AS unit_price + FROM + lineitem_subquery, + orders_subquery + GROUP BY + l_orderkey) AS unit_prices; +ERROR: cannot push down this subquery +DETAIL: Relations need to be joining on partition columns +SELECT + avg(unit_price) +FROM + (SELECT + l_orderkey, + avg(o_totalprice / l_quantity) AS unit_price + FROM + lineitem_subquery, + orders_subquery + WHERE + l_orderkey = o_custkey + GROUP BY + l_orderkey) AS unit_prices; +ERROR: cannot push down this subquery +DETAIL: Relations need to be joining on partition columns +-- Check that we error out if there is union all. +SELECT count(*) FROM +( + (SELECT l_orderkey FROM lineitem_subquery) UNION ALL + (SELECT 1::bigint) +) b; +ERROR: cannot perform distributed planning on this query +DETAIL: Complex table expressions are currently unsupported +-- Check that we error out if queries in union do not include partition columns. +SELECT count(*) FROM +( + (SELECT l_orderkey FROM lineitem_subquery) UNION + (SELECT l_partkey FROM lineitem_subquery) +) b; +ERROR: cannot push down this subquery +DETAIL: Union clauses need to select partition columns +-- Check that we run union queries if partition column is selected. +SELECT count(*) FROM +( + (SELECT l_orderkey FROM lineitem_subquery) UNION + (SELECT l_orderkey FROM lineitem_subquery) +) b; + count +------- + 2985 +(1 row) + +-- Check that we error out if the outermost query has subquery join. +SELECT + avg(o_totalprice/l_quantity) +FROM + (SELECT + l_orderkey, + l_quantity + FROM + lineitem_subquery + ORDER BY + l_quantity + LIMIT 10 + ) lineitem_quantities + JOIN LATERAL + (SELECT + o_totalprice + FROM + orders_subquery + WHERE + lineitem_quantities.l_orderkey = o_orderkey) orders_price ON true; +ERROR: cannot perform distributed planning on this query +DETAIL: Join in subqueries is not supported yet +-- Check that we error out if the outermost query is a distinct clause. +SELECT + count(DISTINCT a) +FROM ( + SELECT + count(*) a + FROM + lineitem_subquery +) z; +ERROR: cannot push down this subquery +DETAIL: distinct in the outermost query is unsupported +-- Check supported subquery types. +SELECT + o_custkey, + sum(order_count) as total_order_count +FROM + (SELECT + o_orderkey, + o_custkey, + count(*) AS order_count + FROM + orders_subquery + WHERE + o_orderkey > 0 AND + o_orderkey < 12000 + GROUP BY + o_orderkey, o_custkey) AS order_counts +GROUP BY + o_custkey +ORDER BY + total_order_count DESC, + o_custkey ASC +LIMIT 10; + o_custkey | total_order_count +-----------+------------------- + 1462 | 9 + 619 | 8 + 643 | 8 + 1030 | 8 + 1486 | 8 + 79 | 7 + 304 | 7 + 319 | 7 + 343 | 7 + 448 | 7 +(10 rows) + +SELECT + avg(unit_price) +FROM + (SELECT + l_orderkey, + avg(o_totalprice / l_quantity) AS unit_price + FROM + lineitem_subquery, + orders_subquery + WHERE + l_orderkey = o_orderkey + GROUP BY + l_orderkey) AS unit_prices +WHERE + unit_price > 1000 AND + unit_price < 10000; + avg +----------------------- + 4968.2889885208475549 +(1 row) + +-- Check that if subquery is pulled, we don't error and run query properly. +SELECT count(*) FROM +( + SELECT l_orderkey FROM ( + (SELECT l_orderkey FROM lineitem_subquery) UNION + (SELECT l_orderkey FROM lineitem_subquery) + ) a + WHERE l_orderkey = 1 +) b; + count +------- + 1 +(1 row) + +SELECT count(*) FROM +( + SELECT * FROM ( + (SELECT * FROM lineitem_subquery) UNION + (SELECT * FROM lineitem_subquery) + ) a + WHERE l_orderkey = 1 +) b; + count +------- + 6 +(1 row) + +SELECT max(l_orderkey) FROM +( + SELECT l_orderkey FROM ( + SELECT + l_orderkey + FROM + lineitem_subquery + WHERE + l_orderkey < 20000 + GROUP BY + l_orderkey + ) z +) y; + max +------- + 14947 +(1 row) + +-- Load more data to one relation, then test if we error out because of different +-- shard counts for joining relations. +\STAGE orders_subquery FROM '@abs_srcdir@/data/orders.1.data' with delimiter '|' +SELECT + avg(unit_price) +FROM + (SELECT + l_orderkey, + avg(o_totalprice / l_quantity) AS unit_price + FROM + lineitem_subquery, + orders_subquery + WHERE + l_orderkey = o_orderkey + GROUP BY + l_orderkey) AS unit_prices; +ERROR: cannot push down this subquery +DETAIL: Shards of relations in subquery need to have 1-to-1 shard partitioning diff --git a/src/test/regress/output/worker_copy.source b/src/test/regress/output/worker_copy.source new file mode 100644 index 000000000..954d47931 --- /dev/null +++ b/src/test/regress/output/worker_copy.source @@ -0,0 +1,6 @@ +-- +-- WORKER_COPY +-- +COPY lineitem FROM '@abs_srcdir@/data/lineitem.1.data' WITH DELIMITER '|'; +COPY lineitem FROM '@abs_srcdir@/data/lineitem.2.data' WITH DELIMITER '|'; +COPY supplier FROM '@abs_srcdir@/data/supplier.data' WITH DELIMITER '|'; diff --git a/src/test/regress/pg_regress_multi.pl b/src/test/regress/pg_regress_multi.pl new file mode 100644 index 000000000..e1f106f90 --- /dev/null +++ b/src/test/regress/pg_regress_multi.pl @@ -0,0 +1,293 @@ +#!/usr/bin/perl -w +#---------------------------------------------------------------------- +# +# pg_regress_multi.pl - Test runner for CitusDB +# +# Portions Copyright (c) 2012-2015, Citus Data, Inc. +# Portions Copyright (c) 1996-2015, PostgreSQL Global Development Group +# Portions Copyright (c) 1994, Regents of the University of California +# +# src/test/regress/pg_regress_multi.pl +# +#---------------------------------------------------------------------- + +use strict; +use warnings; + +use Getopt::Long; + + +sub Usage() +{ + print "pg_regress_multi - CitusDB test runner\n"; + print "\n"; + print "Usage:\n"; + print " pg_regress_multi [MULTI OPTIONS] -- [PG REGRESS OPTS]\n"; + print "\n"; + print "Multi Options:\n"; + print " --bindir Path to postgres binary directory\n"; + print " --libdir Path to postgres library directory\n"; + print " --pgxsdir Path to the PGXS directory\n"; + print " --load-extension Extensions to install in all nodes\n"; + print " --server-option Config option to pass to the server\n"; + exit 1; +} + +# Option parsing +my $bindir = ""; +my $libdir = undef; +my $pgxsdir = ""; +my $majorversion = ""; +my @extensions = (); +my @userPgOptions = (); +my %dataTypes = (); +my %fdws = (); +my %fdwServers = (); +my %functions = (); + +GetOptions( + 'bindir=s' => \$bindir, + 'libdir=s' => \$libdir, + 'pgxsdir=s' => \$pgxsdir, + 'majorversion=s' => \$majorversion, + 'load-extension=s' => \@extensions, + 'server-option=s' => \@userPgOptions, + 'help' => sub { Usage() }); + +# Update environment to include [DY]LD_LIBRARY_PATH/LIBDIR/etc - +# pointing to the libdir - that's required so the right version of +# libpq, citusdb et al is being picked up. +# +# XXX: There's some issues with el capitan's SIP here, causing +# DYLD_LIBRARY_PATH not being inherited if SIP is enabled. That's a +# know problem, present in postgres itself as well. +if (defined $libdir) +{ + $ENV{LD_LIBRARY_PATH} = "$libdir:".($ENV{LD_LIBRARY_PATH} || ''); + $ENV{DYLD_LIBRARY_PATH} = "$libdir:".($ENV{DYLD_LIBRARY_PATH} || ''); + $ENV{LIBPATH} = "$libdir:".($ENV{LIBPATH} || ''); + $ENV{PATH} = "$libdir:".($ENV{PATH} || ''); +} + +# Set some default configuration options +my $masterPort = 57636; +my $workerCount = 2; +my @workerPorts = (); + +for (my $workerIndex = 1; $workerIndex <= $workerCount; $workerIndex++) { + my $workerPort = $masterPort + $workerIndex; + push(@workerPorts, $workerPort); +} + +my $host = "localhost"; +my @pgOptions = (); + +# Postgres options set for the tests +push(@pgOptions, '-c', "listen_addresses='${host}'"); +# not required, and we don't necessarily have access to the default directory +push(@pgOptions, '-c', "unix_socket_directories="); +push(@pgOptions, '-c', "fsync=off"); +push(@pgOptions, '-c', "shared_preload_libraries=citusdb"); + +# CitusDB options set for the tests +push(@pgOptions, '-c', "citusdb.shard_max_size=300kB"); +push(@pgOptions, '-c', "citusdb.max_running_tasks_per_node=4"); +push(@pgOptions, '-c', "citusdb.expire_cached_shards=on"); + +# Add externally added options last, so they overwrite the default ones above +for my $option (@userPgOptions) +{ + push(@pgOptions, '-c', $option); +} + +#define data types as a name->definition +%dataTypes = ('dummy_type', '(i integer)', + 'order_side', ' ENUM (\'buy\', \'sell\')', + 'test_composite_type', '(i integer, i2 integer)', + 'bug_status', ' ENUM (\'new\', \'open\', \'closed\')'); + +# define functions as signature->definition +%functions = ('fake_fdw_handler()', 'fdw_handler AS \'citusdb\' LANGUAGE C STRICT;'); + +#define fdws as name->handler name +%fdws = ('fake_fdw', 'fake_fdw_handler'); + +#define server_name->fdw +%fdwServers = ('fake_fdw_server', 'fake_fdw'); + +# Cleanup leftovers and prepare directories for the run +system("rm", ('-rf', 'tmp_check/tmp-bin')) == 0 or die "Could not remove tmp-bin directory"; + +system("rm", ('-rf', 'tmp_check/master')) == 0 or die "Could not remove master directory"; +for my $port (@workerPorts) +{ + system("rm", ('-rf', "tmp_check/worker.$port")) == 0 or die "Could not remove worker directory"; +} + +# Prepare a wrapper directory in which 'psql' is a symlink to 'csql' +system("mkdir", ('-p', "tmp_check/tmp-bin")) == 0 + or die "Could not create tmp-bin directory"; +system("ln", ('-s', "$bindir/csql", "tmp_check/tmp-bin/psql")) == 0 + or die "Could not create psql to csql symlink"; + +system("mkdir", ('-p', 'tmp_check/master/log')) == 0 or die "Could not create master directory"; +for my $port (@workerPorts) +{ + system("mkdir", ('-p', "tmp_check/worker.$port/log")) == 0 + or die "Could not create worker directory"; +} + +# Create new data directories, copy workers for speed +system("$bindir/initdb", ("--nosync", "tmp_check/master/data")) == 0 + or die "Could not create master data directory"; + +for my $port (@workerPorts) +{ + system("cp -a tmp_check/master/data tmp_check/worker.$port/data") == 0 + or die "Could not create worker data directory"; +} + +# Initialize master's worker list +for my $port (@workerPorts) +{ + system("echo $host $port >> tmp_check/master/data/pg_worker_list.conf") == 0 + or die "Could not initialize master's worker list"; +} + +# Routine to shutdown servers at failure/exit +my $serversAreShutdown = "FALSE"; +sub ShutdownServers() +{ + if ($serversAreShutdown eq "FALSE") + { + system("$bindir/pg_ctl", + ('stop', '-w', '-D', 'tmp_check/master/data')) == 0 + or warn "Could not shutdown worker server"; + + for my $port (@workerPorts) + { + system("$bindir/pg_ctl", + ('stop', '-w', '-D', "tmp_check/worker.$port/data")) == 0 + or warn "Could not shutdown worker server"; + } + $serversAreShutdown = "TRUE"; + } +} + +# Set signals to shutdown servers +$SIG{INT} = \&ShutdownServers; +$SIG{QUIT} = \&ShutdownServers; +$SIG{TERM} = \&ShutdownServers; +$SIG{__DIE__} = \&ShutdownServers; + +# Shutdown servers on exit only if help option is not used +END +{ + if ($? != 1) + { + ShutdownServers(); + } +} + +# Start servers +system("$bindir/pg_ctl", + ('start', '-w', + '-o', join(" ", @pgOptions)." -c port=$masterPort", + '-D', 'tmp_check/master/data', '-l', 'tmp_check/master/log/postmaster.log')) == 0 + or die "Could not start master server"; + +for my $port (@workerPorts) +{ + system("$bindir/pg_ctl", + ('start', '-w', + '-o', join(" ", @pgOptions)." -c port=$port", + '-D', "tmp_check/worker.$port/data", + '-l', "tmp_check/worker.$port/log/postmaster.log")) == 0 + or die "Could not start worker server"; +} + +### +# Create database, extensions, types, functions and fdws on the workers, +# pg_regress won't know to create them for us. +### +for my $port (@workerPorts) +{ + system("$bindir/psql", + ('-h', $host, '-p', $port, "postgres", + '-c', "CREATE DATABASE regression;")) == 0 + or die "Could not create regression database on worker"; + + for my $extension (@extensions) + { + system("$bindir/psql", + ('-h', $host, '-p', $port, "regression", + '-c', "CREATE EXTENSION IF NOT EXISTS \"$extension\";")) == 0 + or die "Could not create extension on worker"; + } + + foreach my $dataType (keys %dataTypes) + { + system("$bindir/psql", + ('-h', $host, '-p', $port, "regression", + '-c', "CREATE TYPE $dataType AS $dataTypes{$dataType};")) == 0 + or die "Could not create TYPE $dataType on worker"; + } + + foreach my $function (keys %functions) + { + system("$bindir/psql", + ('-h', $host, '-p', $port, "regression", + '-c', "CREATE FUNCTION $function RETURNS $functions{$function};")) == 0 + or die "Could not create FUNCTION $function on worker"; + } + + foreach my $fdw (keys %fdws) + { + system("$bindir/psql", + ('-h', $host, '-p', $port, "regression", + '-c', "CREATE FOREIGN DATA WRAPPER $fdw HANDLER $fdws{$fdw};")) == 0 + or die "Could not create foreign data wrapper $fdw on worker"; + } + + foreach my $fdwServer (keys %fdwServers) + { + system("$bindir/psql", + ('-h', $host, '-p', $port, "regression", + '-c', "CREATE SERVER $fdwServer FOREIGN DATA WRAPPER $fdwServers{$fdwServer};")) == 0 + or die "Could not create server $fdwServer on worker"; + } +} + +# Prepare pg_regress arguments +my @arguments = ( + "--host", $host, + '--port', $masterPort +); + +if ($majorversion eq '9.5') +{ + push(@arguments, '--bindir', "tmp_check/tmp-bin"); +} +elsif ($majorversion eq '9.4') +{ + push(@arguments, '--psqldir', "tmp_check/tmp-bin"); +} +else +{ + die "CitusDB is not compatible with the detected PostgreSQL version $majorversion"; +} + +# Add load extension parameters to the argument list +for my $extension (@extensions) +{ + push(@arguments, "--load-extension=$extension"); +} + +# Append remaining ARGV arguments to pg_regress arguments +push(@arguments, @ARGV); + +# Finally run the tests +system("$pgxsdir/src/test/regress/pg_regress", @arguments) == 0 + or die "Could not run regression tests"; + +exit 0; diff --git a/src/test/regress/sql/.gitignore b/src/test/regress/sql/.gitignore new file mode 100644 index 000000000..d503face0 --- /dev/null +++ b/src/test/regress/sql/.gitignore @@ -0,0 +1,15 @@ +/multi_agg_distinct.sql +/multi_agg_type_conversion.sql +/multi_alter_table_statements.sql +/multi_append_table_to_shard.sql +/multi_create_schema.sql +/multi_fdw_large_shardid.sql +/multi_fdw_stage_data.sql +/multi_large_shardid.sql +/multi_master_delete_protocol.sql +/multi_outer_join.sql +/multi_stage_data.sql +/multi_stage_large_records.sql +/multi_stage_more_data.sql +/multi_subquery.sql +/worker_copy.sql diff --git a/src/test/regress/sql/multi_agg_approximate_distinct.sql b/src/test/regress/sql/multi_agg_approximate_distinct.sql new file mode 100644 index 000000000..386ca3abb --- /dev/null +++ b/src/test/regress/sql/multi_agg_approximate_distinct.sql @@ -0,0 +1,69 @@ +-- +-- MULTI_AGG_APPROXIMATE_DISTINCT +-- + +-- Try to execute count(distinct) when approximate distincts aren't enabled + +SELECT count(distinct l_orderkey) FROM lineitem; + +-- Check approximate count(distinct) at different precisions / error rates + +SET citusdb.count_distinct_error_rate = 0.1; +SELECT count(distinct l_orderkey) FROM lineitem; + +SET citusdb.count_distinct_error_rate = 0.01; +SELECT count(distinct l_orderkey) FROM lineitem; + +-- Check approximate count(distinct) for different data types + +SELECT count(distinct l_partkey) FROM lineitem; + +SELECT count(distinct l_extendedprice) FROM lineitem; + +SELECT count(distinct l_shipdate) FROM lineitem; + +SELECT count(distinct l_comment) FROM lineitem; + +-- Check that we can execute approximate count(distinct) on complex expressions + +SELECT count(distinct (l_orderkey * 2 + 1)) FROM lineitem; + +SELECT count(distinct extract(month from l_shipdate)) AS my_month FROM lineitem; + +SELECT count(distinct l_partkey) / count(distinct l_orderkey) FROM lineitem; + +-- Check that we can execute approximate count(distinct) on select queries that +-- contain different filter, join, sort and limit clauses + +SELECT count(distinct l_orderkey) FROM lineitem + WHERE octet_length(l_comment) + octet_length('randomtext'::text) > 40; + +SELECT count(DISTINCT l_orderkey) FROM lineitem, orders + WHERE l_orderkey = o_orderkey AND l_quantity < 5; + +SELECT count(DISTINCT l_orderkey) as distinct_order_count, l_quantity FROM lineitem + WHERE l_quantity < 32.0 + GROUP BY l_quantity + ORDER BY distinct_order_count ASC, l_quantity ASC + LIMIT 10; + +-- If we have an order by on count(distinct) that we intend to push down to +-- worker nodes, we need to error out. Otherwise, we are fine. + +SET citusdb.limit_clause_row_fetch_count = 1000; +SELECT l_returnflag, count(DISTINCT l_shipdate) as count_distinct, count(*) as total + FROM lineitem + GROUP BY l_returnflag + ORDER BY count_distinct + LIMIT 10; + +SELECT l_returnflag, count(DISTINCT l_shipdate) as count_distinct, count(*) as total + FROM lineitem + GROUP BY l_returnflag + ORDER BY total + LIMIT 10; + +-- Check that we can revert config and disable count(distinct) approximations + +SET citusdb.count_distinct_error_rate = 0.0; +SELECT count(distinct l_orderkey) FROM lineitem; diff --git a/src/test/regress/sql/multi_array_agg.sql b/src/test/regress/sql/multi_array_agg.sql new file mode 100644 index 000000000..d4031827a --- /dev/null +++ b/src/test/regress/sql/multi_array_agg.sql @@ -0,0 +1,59 @@ +-- +-- MULTI_ARRAY_AGG +-- + +-- Check multi_cat_agg() aggregate which is used to implement array_agg() + +SELECT array_cat_agg(i) FROM (VALUES (ARRAY[1,2]), (NULL), (ARRAY[3,4])) AS t(i); + +-- Check that we don't support distinct and order by with array_agg() + +SELECT array_agg(distinct l_orderkey) FROM lineitem; + +SELECT array_agg(l_orderkey ORDER BY l_partkey) FROM lineitem; + +SELECT array_agg(distinct l_orderkey ORDER BY l_orderkey) FROM lineitem; + +-- Check array_agg() for different data types and LIMIT clauses + +SELECT array_agg(l_partkey) FROM lineitem GROUP BY l_orderkey + ORDER BY l_orderkey LIMIT 10; + +SELECT array_agg(l_extendedprice) FROM lineitem GROUP BY l_orderkey + ORDER BY l_orderkey LIMIT 10; + +SELECT array_agg(l_shipdate) FROM lineitem GROUP BY l_orderkey + ORDER BY l_orderkey LIMIT 10; + +SELECT array_agg(l_shipmode) FROM lineitem GROUP BY l_orderkey + ORDER BY l_orderkey LIMIT 10; + +-- Check that we can execute array_agg() within other functions + +SELECT array_length(array_agg(l_orderkey), 1) FROM lineitem; + +-- Check that we can execute array_agg() on select queries that hit multiple +-- shards and contain different aggregates, filter clauses and other complex +-- expressions. Note that the l_orderkey ranges are such that the matching rows +-- lie in different shards. + +SELECT l_quantity, count(*), avg(l_extendedprice), array_agg(l_orderkey) FROM lineitem + WHERE l_quantity < 5 AND l_orderkey > 5500 AND l_orderkey < 9500 + GROUP BY l_quantity ORDER BY l_quantity; + +SELECT l_quantity, array_agg(extract (month FROM o_orderdate)) AS my_month + FROM lineitem, orders WHERE l_orderkey = o_orderkey AND l_quantity < 5 + AND l_orderkey > 5500 AND l_orderkey < 9500 GROUP BY l_quantity ORDER BY l_quantity; + +SELECT l_quantity, array_agg(l_orderkey * 2 + 1) FROM lineitem WHERE l_quantity < 5 + AND octet_length(l_comment) + octet_length('randomtext'::text) > 40 + AND l_orderkey > 5500 AND l_orderkey < 9500 GROUP BY l_quantity ORDER BY l_quantity; + +-- Check that we can execute array_agg() with an expression containing NULL values + +SELECT array_agg(case when l_quantity > 20 then l_quantity else NULL end) + FROM lineitem WHERE l_orderkey < 10; + +-- Check that we return NULL in case there are no input rows to array_agg() + +SELECT array_agg(l_orderkey) FROM lineitem WHERE l_quantity < 0; diff --git a/src/test/regress/sql/multi_average_expression.sql b/src/test/regress/sql/multi_average_expression.sql new file mode 100644 index 000000000..856dfc74c --- /dev/null +++ b/src/test/regress/sql/multi_average_expression.sql @@ -0,0 +1,54 @@ +-- +-- MULTI_AVERAGE_EXPRESSION_ORDER +-- + +-- This test checks that the group-by columns don't need to be above an average +-- expression, and can be anywhere in the projection order. This is in response +-- to a bug we had due to the average expression introducing new columns. + +SELECT + sum(l_quantity) as sum_qty, + sum(l_extendedprice) as sum_base_price, + sum(l_extendedprice * (1 - l_discount)) as sum_disc_price, + sum(l_extendedprice * (1 - l_discount) * (1 + l_tax)) as sum_charge, + avg(l_quantity) as avg_qty, + avg(l_extendedprice) as avg_price, + avg(l_discount) as avg_disc, + count(*) as count_order, + l_returnflag, + l_linestatus +FROM + lineitem +WHERE + l_shipdate <= date '1998-12-01' - interval '90 days' +GROUP BY + l_returnflag, + l_linestatus +ORDER BY + l_returnflag, + l_linestatus; + +-- These tests check that distributed averages only consider non-null input +-- values. This is in response to a bug we had due to the distributed average +-- using sum(expression)/count(*) to calculate avg(expression). We now use the +-- correct form sum(expression)/count(expression) for average calculations. + +-- Run avg() on an expression that contains some null values + +SELECT + avg(case + when l_quantity > 20 + then l_quantity + end) +FROM + lineitem; + +-- Run avg() on an expression that contains only null values + +SELECT + avg(case + when l_quantity > 5000 + then l_quantity + end) +FROM + lineitem; diff --git a/src/test/regress/sql/multi_basic_queries.sql b/src/test/regress/sql/multi_basic_queries.sql new file mode 100644 index 000000000..10e195725 --- /dev/null +++ b/src/test/regress/sql/multi_basic_queries.sql @@ -0,0 +1,15 @@ +-- +-- MULTI_BASIC_QUERIES +-- + +-- Execute simple sum, average, and count queries on data recently uploaded to +-- our partitioned table. + +SELECT count(*) FROM lineitem; + +SELECT sum(l_extendedprice) FROM lineitem; + +SELECT avg(l_extendedprice) FROM lineitem; + +-- Verify temp tables which are used for final result aggregation don't persist. +SELECT count(*) FROM pg_class WHERE relname LIKE 'pg_merge_job_%' AND relkind = 'r'; diff --git a/src/test/regress/sql/multi_binary_master_copy_format.sql b/src/test/regress/sql/multi_binary_master_copy_format.sql new file mode 100644 index 000000000..37623ce36 --- /dev/null +++ b/src/test/regress/sql/multi_binary_master_copy_format.sql @@ -0,0 +1,16 @@ +-- +-- MULTI_BINARY_MASTER_COPY +-- + +-- Try binary master copy for different executors + +SET citusdb.binary_master_copy_format TO 'on'; +SET citusdb.task_executor_type TO 'task-tracker'; + +SELECT count(*) FROM lineitem; +SELECT l_shipmode FROM lineitem WHERE l_partkey = 67310 OR l_partkey = 155190; + +SET citusdb.task_executor_type TO 'real-time'; + +SELECT count(*) FROM lineitem; +SELECT l_shipmode FROM lineitem WHERE l_partkey = 67310 OR l_partkey = 155190; diff --git a/src/test/regress/sql/multi_complex_expressions.sql b/src/test/regress/sql/multi_complex_expressions.sql new file mode 100644 index 000000000..1db7fb3c1 --- /dev/null +++ b/src/test/regress/sql/multi_complex_expressions.sql @@ -0,0 +1,54 @@ +-- +-- MULTI_COMPLEX_EXPRESSIONS +-- + +-- Check that we can correctly handle complex expressions and aggregates. + +SELECT sum(l_quantity) / avg(l_quantity) FROM lineitem; + +SELECT sum(l_quantity) / (10 * avg(l_quantity)) FROM lineitem; + +SELECT (sum(l_quantity) / (10 * avg(l_quantity))) + 11 FROM lineitem; + +SELECT avg(l_quantity) as average FROM lineitem; + +SELECT 100 * avg(l_quantity) as average_times_hundred FROM lineitem; + +SELECT 100 * avg(l_quantity) / 10 as average_times_ten FROM lineitem; + +SELECT l_quantity, 10 * count(*) count_quantity FROM lineitem + GROUP BY l_quantity ORDER BY count_quantity, l_quantity; + +-- Check that we can handle complex select clause expressions. + +SELECT count(*) FROM lineitem + WHERE octet_length(l_comment || l_comment) > 40; + +SELECT count(*) FROM lineitem + WHERE octet_length(concat(l_comment, l_comment)) > 40; + +SELECT count(*) FROM lineitem + WHERE octet_length(l_comment) + octet_length('randomtext'::text) > 40; + +SELECT count(*) FROM lineitem + WHERE octet_length(l_comment) + 10 > 40; + +SELECT count(*) FROM lineitem + WHERE (l_receiptdate::timestamp - l_shipdate::timestamp) > interval '5 days'; + +SELECT count(*) FROM lineitem WHERE random() = 0.1; + +-- Check that we can handle implicit and explicit join clause definitions. + +SELECT count(*) FROM lineitem, orders + WHERE l_orderkey = o_orderkey AND l_quantity < 5; + +SELECT count(*) FROM lineitem + JOIN orders ON l_orderkey = o_orderkey AND l_quantity < 5; + +SELECT count(*) FROM lineitem JOIN orders ON l_orderkey = o_orderkey + WHERE l_quantity < 5; + +-- Check that we make sure local joins are between columns only. + +SELECT count(*) FROM lineitem, orders WHERE l_orderkey + 1 = o_orderkey; diff --git a/src/test/regress/sql/multi_connection_cache.sql b/src/test/regress/sql/multi_connection_cache.sql new file mode 100644 index 000000000..33bad147e --- /dev/null +++ b/src/test/regress/sql/multi_connection_cache.sql @@ -0,0 +1,73 @@ +-- =================================================================== +-- create test functions +-- =================================================================== + +CREATE FUNCTION initialize_remote_temp_table(cstring, integer) + RETURNS bool + AS 'citusdb' + LANGUAGE C STRICT; + +CREATE FUNCTION count_remote_temp_table_rows(cstring, integer) + RETURNS integer + AS 'citusdb' + LANGUAGE C STRICT; + +CREATE FUNCTION get_and_purge_connection(cstring, integer) + RETURNS bool + AS 'citusdb' + LANGUAGE C STRICT; + +CREATE FUNCTION set_connection_status_bad(cstring, integer) + RETURNS bool + AS 'citusdb' + LANGUAGE C STRICT; + +-- =================================================================== +-- test connection hash functionality +-- =================================================================== + +-- worker port number is set in pg_regress_multi.pl +\set worker_port 57638 + +-- reduce verbosity to squelch chatty warnings +\set VERBOSITY terse + +-- connect to non-existent host +SELECT initialize_remote_temp_table('dummy-host-name', 12345); + +\set VERBOSITY default + +-- try to use hostname over 255 characters +SELECT initialize_remote_temp_table(repeat('a', 256)::cstring, :worker_port); + +-- connect to localhost and build a temp table +SELECT initialize_remote_temp_table('localhost', :worker_port); + +-- table should still be visible since session is reused +SELECT count_remote_temp_table_rows('localhost', :worker_port); + +-- purge existing connection to localhost +SELECT get_and_purge_connection('localhost', :worker_port); + +-- squelch WARNINGs that contain worker_port +SET client_min_messages TO ERROR; + +-- should not be able to see table anymore +SELECT count_remote_temp_table_rows('localhost', :worker_port); + +-- recreate once more +SELECT initialize_remote_temp_table('localhost', :worker_port); + +-- set the connection status to bad +SELECT set_connection_status_bad('localhost', :worker_port); + +-- should get connection failure (cached connection bad) +SELECT count_remote_temp_table_rows('localhost', :worker_port); + +-- should get result failure (reconnected, so no temp table) +SELECT count_remote_temp_table_rows('localhost', :worker_port); + +-- purge the connection so that we clean up the bad connection +SELECT get_and_purge_connection('localhost', :worker_port); + +SET client_min_messages TO DEFAULT; diff --git a/src/test/regress/sql/multi_count_type_conversion.sql b/src/test/regress/sql/multi_count_type_conversion.sql new file mode 100644 index 000000000..2f84da988 --- /dev/null +++ b/src/test/regress/sql/multi_count_type_conversion.sql @@ -0,0 +1,18 @@ +-- +-- MULTI_COUNT_TYPE_CONVERSION +-- + +-- Verify that we can sort count(*) results correctly. We perform this check as +-- our count() operations execute in two steps: worker nodes report their +-- count() results, and the master node sums these counts up. During this sum(), +-- the data type changes from int8 to numeric. When we sort the numeric value, +-- we get erroneous results on 64-bit architectures. To fix this issue, we +-- manually cast back the sum() result to an int8 data type. + +SELECT count(*) count_quantity, l_quantity FROM lineitem WHERE l_quantity < 32.0 + GROUP BY l_quantity + ORDER BY count_quantity ASC, l_quantity DESC; + +SELECT count(*) count_quantity, l_quantity FROM lineitem WHERE l_quantity < 32.0 + GROUP BY l_quantity + ORDER BY count_quantity DESC, l_quantity ASC; diff --git a/src/test/regress/sql/multi_create_fdw.sql b/src/test/regress/sql/multi_create_fdw.sql new file mode 100644 index 000000000..0f237be11 --- /dev/null +++ b/src/test/regress/sql/multi_create_fdw.sql @@ -0,0 +1,12 @@ +-- =================================================================== +-- get ready for the foreign data wrapper tests +-- =================================================================== + +-- create fake fdw for use in tests +CREATE FUNCTION fake_fdw_handler() +RETURNS fdw_handler +AS 'citusdb' +LANGUAGE C STRICT; + +CREATE FOREIGN DATA WRAPPER fake_fdw HANDLER fake_fdw_handler; +CREATE SERVER fake_fdw_server FOREIGN DATA WRAPPER fake_fdw; diff --git a/src/test/regress/sql/multi_create_insert_proxy.sql b/src/test/regress/sql/multi_create_insert_proxy.sql new file mode 100644 index 000000000..bfd3adcbd --- /dev/null +++ b/src/test/regress/sql/multi_create_insert_proxy.sql @@ -0,0 +1,79 @@ +-- =================================================================== +-- test INSERT proxy creation functionality +-- =================================================================== + +-- use transaction to permit multiple calls to proxy function in one session +BEGIN; + +-- use "unorthodox" object names to test quoting +CREATE SCHEMA "A$AP Mob" + CREATE TABLE "Dr. Bronner's ""Magic"" Soaps" ( + id bigint PRIMARY KEY, + data text NOT NULL DEFAULT 'lorem ipsum' + ); + +\set insert_target '"A$AP Mob"."Dr. Bronner''s ""Magic"" Soaps"' + +-- create proxy and save proxy table name +SELECT create_insert_proxy_for_table(:'insert_target') AS proxy_tablename +\gset + +-- insert to proxy, relying on default value +INSERT INTO pg_temp.:"proxy_tablename" (id) VALUES (1); + +-- copy some rows into the proxy +COPY pg_temp.:"proxy_tablename" FROM stdin; +2 dolor sit amet +3 consectetur adipiscing elit +4 sed do eiusmod +5 tempor incididunt ut +6 labore et dolore +\. + +-- verify rows were copied to target +SELECT * FROM :insert_target ORDER BY id ASC; + +-- and not to proxy +SELECT count(*) FROM pg_temp.:"proxy_tablename"; + +ROLLBACK; + +-- test behavior with distributed table, (so no transaction) +CREATE TABLE insert_target ( + id bigint PRIMARY KEY, + data text NOT NULL DEFAULT 'lorem ipsum' +); + +-- squelch WARNINGs that contain worker_port +SET client_min_messages TO ERROR; + +SELECT master_create_distributed_table('insert_target', 'id', 'hash'); +SELECT master_create_worker_shards('insert_target', 2, 1); + +CREATE TEMPORARY SEQUENCE rows_inserted; +SELECT create_insert_proxy_for_table('insert_target', 'rows_inserted') AS proxy_tablename +\gset + +-- insert to proxy, again relying on default value +INSERT INTO pg_temp.:"proxy_tablename" (id) VALUES (1); + +-- test copy with bad row in middle +\set VERBOSITY terse +COPY pg_temp.:"proxy_tablename" FROM stdin; +2 dolor sit amet +3 consectetur adipiscing elit +4 sed do eiusmod +5 tempor incididunt ut +6 labore et dolore +7 \N +8 magna aliqua +\. +\set VERBOSITY default + +-- verify rows were copied to distributed table +SELECT * FROM insert_target ORDER BY id ASC; + +-- the counter should match the number of rows stored +SELECT currval('rows_inserted'); + +SET client_min_messages TO DEFAULT; diff --git a/src/test/regress/sql/multi_create_shards.sql b/src/test/regress/sql/multi_create_shards.sql new file mode 100644 index 000000000..5b51dccd2 --- /dev/null +++ b/src/test/regress/sql/multi_create_shards.sql @@ -0,0 +1,143 @@ +-- =================================================================== +-- create test functions and types needed for tests +-- =================================================================== + +CREATE FUNCTION sort_names(cstring, cstring, cstring) + RETURNS cstring + AS 'citusdb' + LANGUAGE C STRICT; + +-- create a custom type... +CREATE TYPE dummy_type AS ( + i integer +); + +-- ... as well as a function to use as its comparator... +CREATE FUNCTION dummy_type_function(dummy_type, dummy_type) RETURNS boolean +AS 'SELECT TRUE;' +LANGUAGE SQL +IMMUTABLE +RETURNS NULL ON NULL INPUT; + +-- ... use that function to create a custom operator... +CREATE OPERATOR = ( + LEFTARG = dummy_type, + RIGHTARG = dummy_type, + PROCEDURE = dummy_type_function +); + +-- ... and create a custom operator family for hash indexes... +CREATE OPERATOR FAMILY dummy_op_family USING hash; + +-- ... finally, build an operator class, designate it as the default operator +-- class for the type, but only specify an equality operator. So the type will +-- have a default op class but no hash operator in that class. +CREATE OPERATOR CLASS dummy_op_family_class +DEFAULT FOR TYPE dummy_type USING hash FAMILY dummy_op_family AS +OPERATOR 1 =; + +-- =================================================================== +-- test shard creation functionality +-- =================================================================== + +CREATE TABLE table_to_distribute ( + name text PRIMARY KEY, + id bigint, + json_data json, + test_type_data dummy_type +); + +-- use an index instead of table name +SELECT master_create_distributed_table('table_to_distribute_pkey', 'id', 'hash'); + +-- use a bad column name +SELECT master_create_distributed_table('table_to_distribute', 'bad_column', 'hash'); + +-- use unrecognized partition type +SELECT master_create_distributed_table('table_to_distribute', 'name', 'unrecognized'); + +-- use a partition column of a type lacking any default operator class +SELECT master_create_distributed_table('table_to_distribute', 'json_data', 'hash'); + +-- use a partition column of type lacking the required support function (hash) +SELECT master_create_distributed_table('table_to_distribute', 'test_type_data', 'hash'); + +-- distribute table and inspect side effects +SELECT master_create_distributed_table('table_to_distribute', 'name', 'hash'); +SELECT partmethod, partkey FROM pg_dist_partition + WHERE logicalrelid = 'table_to_distribute'::regclass; + +-- use a bad shard count +SELECT master_create_worker_shards('table_to_distribute', 0, 1); + +-- use a bad replication factor +SELECT master_create_worker_shards('table_to_distribute', 16, 0); + +-- use a replication factor higher than shard count +SELECT master_create_worker_shards('table_to_distribute', 16, 3); + +-- finally, create shards and inspect metadata +SELECT master_create_worker_shards('table_to_distribute', 16, 1); + +SELECT shardstorage, shardminvalue, shardmaxvalue FROM pg_dist_shard + WHERE logicalrelid = 'table_to_distribute'::regclass + ORDER BY (shardminvalue::integer) ASC; + +-- all shards should have the same size (16 divides evenly into the hash space) +SELECT count(*) AS shard_count, + shardmaxvalue::integer - shardminvalue::integer AS shard_size + FROM pg_dist_shard + WHERE logicalrelid='table_to_distribute'::regclass + GROUP BY shard_size; + +SELECT COUNT(*) FROM pg_class WHERE relname LIKE 'table_to_distribute%' AND relkind = 'r'; + +-- try to create them again +SELECT master_create_worker_shards('table_to_distribute', 16, 1); + +-- test list sorting +SELECT sort_names('sumedh', 'jason', 'ozgun'); + +SELECT COUNT(*) FROM pg_class WHERE relname LIKE 'throwaway%' AND relkind = 'r'; + +-- test foreign table creation +CREATE FOREIGN TABLE foreign_table_to_distribute +( + name text, + id bigint +) +SERVER fake_fdw_server; + +SELECT master_create_distributed_table('foreign_table_to_distribute', 'id', 'hash'); +SELECT master_create_worker_shards('foreign_table_to_distribute', 16, 1); + +SELECT shardstorage, shardminvalue, shardmaxvalue FROM pg_dist_shard + WHERE logicalrelid = 'foreign_table_to_distribute'::regclass + ORDER BY (shardminvalue::integer) ASC; + +-- test shard creation using weird shard count +CREATE TABLE weird_shard_count +( + name text, + id bigint +); + +SELECT master_create_distributed_table('weird_shard_count', 'id', 'hash'); +SELECT master_create_worker_shards('weird_shard_count', 7, 1); + +-- CitusDB ensures all shards are roughly the same size +SELECT shardmaxvalue::integer - shardminvalue::integer AS shard_size + FROM pg_dist_shard + WHERE logicalrelid = 'weird_shard_count'::regclass + ORDER BY shardminvalue::integer ASC; + +-- cleanup foreign table, related shards and shard placements +DELETE FROM pg_dist_shard_placement + WHERE shardid IN (SELECT shardid FROM pg_dist_shard + WHERE logicalrelid = 'foreign_table_to_distribute'::regclass); + +DELETE FROM pg_dist_shard + WHERE logicalrelid = 'foreign_table_to_distribute'::regclass; + +DELETE FROM pg_dist_partition + WHERE logicalrelid = 'foreign_table_to_distribute'::regclass; diff --git a/src/test/regress/sql/multi_create_table.sql b/src/test/regress/sql/multi_create_table.sql new file mode 100644 index 000000000..987988771 --- /dev/null +++ b/src/test/regress/sql/multi_create_table.sql @@ -0,0 +1,145 @@ +-- +-- MULTI_CREATE_TABLE +-- + +-- Create new table definitions for use in testing in distributed planning and +-- execution functionality. Also create indexes to boost performance. + +CREATE TABLE lineitem ( + l_orderkey bigint not null, + l_partkey integer not null, + l_suppkey integer not null, + l_linenumber integer not null, + l_quantity decimal(15, 2) not null, + l_extendedprice decimal(15, 2) not null, + l_discount decimal(15, 2) not null, + l_tax decimal(15, 2) not null, + l_returnflag char(1) not null, + l_linestatus char(1) not null, + l_shipdate date not null, + l_commitdate date not null, + l_receiptdate date not null, + l_shipinstruct char(25) not null, + l_shipmode char(10) not null, + l_comment varchar(44) not null, + PRIMARY KEY(l_orderkey, l_linenumber) ); +SELECT master_create_distributed_table('lineitem', 'l_orderkey', 'append'); + +CREATE INDEX lineitem_time_index ON lineitem (l_shipdate); + +CREATE TABLE orders ( + o_orderkey bigint not null, + o_custkey integer not null, + o_orderstatus char(1) not null, + o_totalprice decimal(15,2) not null, + o_orderdate date not null, + o_orderpriority char(15) not null, + o_clerk char(15) not null, + o_shippriority integer not null, + o_comment varchar(79) not null, + PRIMARY KEY(o_orderkey) ); +SELECT master_create_distributed_table('orders', 'o_orderkey', 'append'); + +CREATE TABLE customer ( + c_custkey integer not null, + c_name varchar(25) not null, + c_address varchar(40) not null, + c_nationkey integer not null, + c_phone char(15) not null, + c_acctbal decimal(15,2) not null, + c_mktsegment char(10) not null, + c_comment varchar(117) not null); +SELECT master_create_distributed_table('customer', 'c_custkey', 'append'); + +CREATE TABLE nation ( + n_nationkey integer not null, + n_name char(25) not null, + n_regionkey integer not null, + n_comment varchar(152)); +SELECT master_create_distributed_table('nation', 'n_nationkey', 'append'); + +CREATE TABLE part ( + p_partkey integer not null, + p_name varchar(55) not null, + p_mfgr char(25) not null, + p_brand char(10) not null, + p_type varchar(25) not null, + p_size integer not null, + p_container char(10) not null, + p_retailprice decimal(15,2) not null, + p_comment varchar(23) not null); +SELECT master_create_distributed_table('part', 'p_partkey', 'append'); + +CREATE TABLE supplier +( + s_suppkey integer not null, + s_name char(25) not null, + s_address varchar(40) not null, + s_nationkey integer, + s_phone char(15) not null, + s_acctbal decimal(15,2) not null, + s_comment varchar(101) not null +); +SELECT master_create_distributed_table('supplier', 's_suppkey', 'append'); + + +-- now test that CitusDB cannot distribute unique constraints that do not include +-- the partition column +CREATE TABLE primary_key_on_non_part_col +( + partition_col integer, + other_col integer PRIMARY KEY +); +SELECT master_create_distributed_table('primary_key_on_non_part_col', 'partition_col', 'hash'); + +CREATE TABLE unique_const_on_non_part_col +( + partition_col integer, + other_col integer UNIQUE +); +SELECT master_create_distributed_table('primary_key_on_non_part_col', 'partition_col', 'hash'); + +-- now show that CitusDB can distribute unique constrints that include +-- the partition column +CREATE TABLE primary_key_on_part_col +( + partition_col integer PRIMARY KEY, + other_col integer +); +SELECT master_create_distributed_table('primary_key_on_part_col', 'partition_col', 'hash'); + +CREATE TABLE unique_const_on_part_col +( + partition_col integer UNIQUE, + other_col integer +); +SELECT master_create_distributed_table('unique_const_on_part_col', 'partition_col', 'hash'); + +CREATE TABLE unique_const_on_two_columns +( + partition_col integer, + other_col integer, + UNIQUE (partition_col, other_col) +); +SELECT master_create_distributed_table('unique_const_on_two_columns', 'partition_col', 'hash'); + +CREATE TABLE unique_const_append_partitioned_tables +( + partition_col integer UNIQUE, + other_col integer +); +SELECT master_create_distributed_table('unique_const_append_partitioned_tables', 'partition_col', 'append'); + +CREATE TABLE unique_const_range_partitioned_tables +( + partition_col integer UNIQUE, + other_col integer +); +SELECT master_create_distributed_table('unique_const_range_partitioned_tables', 'partition_col', 'range'); + +-- drop unnecessary tables +DROP TABLE primary_key_on_non_part_col, unique_const_on_non_part_col CASCADE; +DROP TABLE primary_key_on_part_col, unique_const_on_part_col, unique_const_on_two_columns CASCADE; +DROP TABLE unique_const_range_partitioned_tables CASCADE; + + diff --git a/src/test/regress/sql/multi_data_types.sql b/src/test/regress/sql/multi_data_types.sql new file mode 100644 index 000000000..99c603e63 --- /dev/null +++ b/src/test/regress/sql/multi_data_types.sql @@ -0,0 +1,121 @@ +-- =================================================================== +-- test composite type, varchar and enum types +-- create, distribute, INSERT, SELECT and UPDATE +-- =================================================================== + +-- create a custom type... +CREATE TYPE test_composite_type AS ( + i integer, + i2 integer +); + +-- ... as well as a function to use as its comparator... +CREATE FUNCTION equal_test_composite_type_function(test_composite_type, test_composite_type) RETURNS boolean +AS 'select $1.i = $2.i AND $1.i2 = $2.i2;' +LANGUAGE SQL +IMMUTABLE +RETURNS NULL ON NULL INPUT; + +-- ... use that function to create a custom equality operator... +CREATE OPERATOR = ( + LEFTARG = test_composite_type, + RIGHTARG = test_composite_type, + PROCEDURE = equal_test_composite_type_function, + HASHES +); + +-- ... and create a custom operator family for hash indexes... +CREATE OPERATOR FAMILY cats_op_fam USING hash; + +-- ... create a test HASH function. Though it is a poor hash function, +-- it is acceptable for our tests +CREATE FUNCTION test_composite_type_hash(test_composite_type) RETURNS int +AS 'SELECT hashtext( ($1.i + $1.i2)::text);' +LANGUAGE SQL +IMMUTABLE +RETURNS NULL ON NULL INPUT; + + +-- We need to define two different operator classes for the composite types +-- One uses BTREE the other uses HASH +CREATE OPERATOR CLASS cats_op_fam_clas3 +DEFAULT FOR TYPE test_composite_type USING BTREE AS +OPERATOR 3 = (test_composite_type, test_composite_type); + +CREATE OPERATOR CLASS cats_op_fam_class +DEFAULT FOR TYPE test_composite_type USING HASH AS +OPERATOR 1 = (test_composite_type, test_composite_type), +FUNCTION 1 test_composite_type_hash(test_composite_type); + +-- create and distribute a table on composite type column +CREATE TABLE composite_type_partitioned_table +( + id integer, + col test_composite_type +); + +SELECT master_create_distributed_table('composite_type_partitioned_table', 'col', 'hash'); + +SELECT master_create_worker_shards('composite_type_partitioned_table', 4, 1); + +-- execute INSERT, SELECT and UPDATE queries on composite_type_partitioned_table +INSERT INTO composite_type_partitioned_table VALUES (1, '(1, 2)'::test_composite_type); +INSERT INTO composite_type_partitioned_table VALUES (2, '(3, 4)'::test_composite_type); +INSERT INTO composite_type_partitioned_table VALUES (3, '(5, 6)'::test_composite_type); +INSERT INTO composite_type_partitioned_table VALUES (4, '(7, 8)'::test_composite_type); +INSERT INTO composite_type_partitioned_table VALUES (5, '(9, 10)'::test_composite_type); + +SELECT * FROM composite_type_partitioned_table WHERE col = '(7, 8)'::test_composite_type; + +UPDATE composite_type_partitioned_table SET id = 6 WHERE col = '(7, 8)'::test_composite_type; + +SELECT * FROM composite_type_partitioned_table WHERE col = '(7, 8)'::test_composite_type; + + +-- create and distribute a table on enum type column +CREATE TYPE bug_status AS ENUM ('new', 'open', 'closed'); + +CREATE TABLE bugs ( + id integer, + status bug_status +); + +SELECT master_create_distributed_table('bugs', 'status', 'hash'); + +SELECT master_create_worker_shards('bugs', 4, 1); + +-- execute INSERT, SELECT and UPDATE queries on composite_type_partitioned_table +INSERT INTO bugs VALUES (1, 'new'); +INSERT INTO bugs VALUES (2, 'open'); +INSERT INTO bugs VALUES (3, 'closed'); +INSERT INTO bugs VALUES (4, 'closed'); +INSERT INTO bugs VALUES (5, 'open'); + +SELECT * FROM bugs WHERE status = 'closed'::bug_status; + +UPDATE bugs SET status = 'closed'::bug_status WHERE id = 2; + +SELECT * FROM bugs WHERE status = 'open'::bug_status; + +-- create and distribute a table on varchar column +CREATE TABLE varchar_hash_partitioned_table +( + id int, + name varchar +); + +SELECT master_create_distributed_table('varchar_hash_partitioned_table', 'id', 'hash'); +SELECT master_create_worker_shards('varchar_hash_partitioned_table', 4, 1); + +-- execute INSERT, SELECT and UPDATE queries on composite_type_partitioned_table +INSERT INTO varchar_hash_partitioned_table VALUES (1, 'Jason'); +INSERT INTO varchar_hash_partitioned_table VALUES (2, 'Ozgun'); +INSERT INTO varchar_hash_partitioned_table VALUES (3, 'Onder'); +INSERT INTO varchar_hash_partitioned_table VALUES (4, 'Sumedh'); +INSERT INTO varchar_hash_partitioned_table VALUES (5, 'Marco'); + +SELECT * FROM varchar_hash_partitioned_table WHERE name = 'Onder'; + +UPDATE varchar_hash_partitioned_table SET name = 'Samay' WHERE id = 5; + +SELECT * FROM varchar_hash_partitioned_table WHERE name = 'Samay'; diff --git a/src/test/regress/sql/multi_distribution_metadata.sql b/src/test/regress/sql/multi_distribution_metadata.sql new file mode 100644 index 000000000..51b3fe2ee --- /dev/null +++ b/src/test/regress/sql/multi_distribution_metadata.sql @@ -0,0 +1,215 @@ +-- =================================================================== +-- create test functions +-- =================================================================== + +CREATE FUNCTION load_shard_id_array(regclass) + RETURNS bigint[] + AS 'citusdb' + LANGUAGE C STRICT; + +CREATE FUNCTION load_shard_interval_array(bigint, anyelement) + RETURNS anyarray + AS 'citusdb' + LANGUAGE C STRICT; + +CREATE FUNCTION load_shard_placement_array(bigint, bool) + RETURNS text[] + AS 'citusdb' + LANGUAGE C STRICT; + +CREATE FUNCTION partition_column_id(regclass) + RETURNS smallint + AS 'citusdb' + LANGUAGE C STRICT; + +CREATE FUNCTION partition_type(regclass) + RETURNS "char" + AS 'citusdb' + LANGUAGE C STRICT; + +CREATE FUNCTION is_distributed_table(regclass) + RETURNS boolean + AS 'citusdb' + LANGUAGE C STRICT; + +CREATE FUNCTION column_name_to_column_id(regclass, cstring) + RETURNS smallint + AS 'citusdb' + LANGUAGE C STRICT; + +CREATE FUNCTION create_monolithic_shard_row(regclass) + RETURNS bigint + AS 'citusdb' + LANGUAGE C STRICT; + +CREATE FUNCTION create_healthy_local_shard_placement_row(bigint) + RETURNS void + AS 'citusdb' + LANGUAGE C STRICT; + +CREATE FUNCTION delete_shard_placement_row(bigint, text, bigint) + RETURNS bool + AS 'citusdb' + LANGUAGE C STRICT; + +CREATE FUNCTION update_shard_placement_row_state(bigint, text, bigint, int) + RETURNS bool + AS 'citusdb' + LANGUAGE C STRICT; + +CREATE FUNCTION acquire_shared_shard_lock(bigint) + RETURNS void + AS 'citusdb' + LANGUAGE C STRICT; + +CREATE FUNCTION column_name_to_column(regclass, text) + RETURNS text + AS 'citusdb' + LANGUAGE C STRICT; + +-- =================================================================== +-- test distribution metadata functionality +-- =================================================================== + +-- create table to be distributed +CREATE TABLE events_hash ( + id bigint, + name text +); + +-- for this table we'll "distribute" manually but verify using function calls +INSERT INTO pg_dist_shard + (shardid, logicalrelid, shardstorage, shardminvalue, shardmaxvalue) +VALUES + (1, 'events_hash'::regclass, 't', '0', '10'), + (2, 'events_hash'::regclass, 't', '10', '20'), + (3, 'events_hash'::regclass, 't', '20', '30'), + (4, 'events_hash'::regclass, 't', '30', '40'); + +INSERT INTO pg_dist_shard_placement + (nodename, nodeport, shardid, shardstate, shardlength) +VALUES + ('cluster-worker-01', 5432, 1, 0, 0), + ('cluster-worker-01', 5432, 2, 0, 0), + ('cluster-worker-02', 5433, 3, 0, 0), + ('cluster-worker-02', 5433, 4, 0, 0), + ('cluster-worker-03', 5434, 1, 1, 0), + ('cluster-worker-03', 5434, 2, 1, 0), + ('cluster-worker-04', 5435, 3, 1, 0), + ('cluster-worker-04', 5435, 4, 1, 0); + +INSERT INTO pg_dist_partition (logicalrelid, partmethod, partkey) +VALUES + ('events_hash'::regclass, 'h', column_name_to_column('events_hash'::regclass, 'name')); + +-- should see above shard identifiers +SELECT load_shard_id_array('events_hash'); + +-- should see array with first shard range +SELECT load_shard_interval_array(1, 0); + +-- should even work for range-partitioned shards +BEGIN; + UPDATE pg_dist_shard SET + shardminvalue = 'Aardvark', + shardmaxvalue = 'Zebra' + WHERE shardid = 1; + + UPDATE pg_dist_partition SET partmethod = 'r' + WHERE logicalrelid = 'events_hash'::regclass; + + SELECT load_shard_interval_array(1, ''::text); +ROLLBACK; + +-- should see error for non-existent shard +SELECT load_shard_interval_array(5, 0); + +-- should see two placements +SELECT load_shard_placement_array(2, false); + +-- only one of which is finalized +SELECT load_shard_placement_array(2, true); + +-- should see error for non-existent shard +SELECT load_shard_placement_array(6, false); + +-- should see column id of 'name' +SELECT partition_column_id('events_hash'); + +-- should see hash partition type and fail for non-distributed tables +SELECT partition_type('events_hash'); +SELECT partition_type('pg_type'); + +-- should see true for events_hash, false for others +SELECT is_distributed_table('events_hash'); +SELECT is_distributed_table('pg_type'); +SELECT is_distributed_table('pg_dist_shard'); + +-- test underlying column name-id translation +SELECT column_name_to_column_id('events_hash', 'name'); +SELECT column_name_to_column_id('events_hash', 'ctid'); +SELECT column_name_to_column_id('events_hash', 'non_existent'); + +-- drop shard rows (must drop placements first) +DELETE FROM pg_dist_shard_placement + WHERE shardid BETWEEN 1 AND 4; +DELETE FROM pg_dist_shard + WHERE logicalrelid = 'events_hash'::regclass; + +-- verify that an eager load shows them missing +SELECT load_shard_id_array('events_hash'); + +-- create second table to distribute +CREATE TABLE customers ( + id bigint, + name text +); + +-- now we'll distribute using function calls but verify metadata manually... + +-- partition on id and manually inspect partition row +INSERT INTO pg_dist_partition (logicalrelid, partmethod, partkey) +VALUES + ('customers'::regclass, 'h', column_name_to_column('customers'::regclass, 'id')); +SELECT partmethod, partkey FROM pg_dist_partition + WHERE logicalrelid = 'customers'::regclass; + +-- make one huge shard and manually inspect shard row +SELECT create_monolithic_shard_row('customers') AS new_shard_id +\gset +SELECT shardstorage, shardminvalue, shardmaxvalue FROM pg_dist_shard +WHERE shardid = :new_shard_id; + +-- add a placement and manually inspect row +SELECT create_healthy_local_shard_placement_row(:new_shard_id); +SELECT shardstate, nodename, nodeport FROM pg_dist_shard_placement +WHERE shardid = :new_shard_id AND nodename = 'localhost' and nodeport = 5432; + +-- mark it as unhealthy and inspect +SELECT update_shard_placement_row_state(:new_shard_id, 'localhost', 5432, 3); +SELECT shardstate FROM pg_dist_shard_placement +WHERE shardid = :new_shard_id AND nodename = 'localhost' and nodeport = 5432; + +-- remove it and verify it is gone +SELECT delete_shard_placement_row(:new_shard_id, 'localhost', 5432); +SELECT COUNT(*) FROM pg_dist_shard_placement +WHERE shardid = :new_shard_id AND nodename = 'localhost' and nodeport = 5432; + +-- deleting or updating a non-existent row should fail +SELECT delete_shard_placement_row(:new_shard_id, 'wrong_localhost', 5432); +SELECT update_shard_placement_row_state(:new_shard_id, 'localhost', 5432, 3); + +-- now we'll even test our lock methods... + +-- use transaction to bound how long we hold the lock +BEGIN; + +-- pick up a shard lock and look for it in pg_locks +SELECT acquire_shared_shard_lock(5); +SELECT objid, mode FROM pg_locks WHERE locktype = 'advisory' AND objid = 5; + +-- commit should drop the lock +COMMIT; + +-- lock should be gone now +SELECT COUNT(*) FROM pg_locks WHERE locktype = 'advisory' AND objid = 5; diff --git a/src/test/regress/sql/multi_dropped_column_aliases.sql b/src/test/regress/sql/multi_dropped_column_aliases.sql new file mode 100644 index 000000000..689e64a00 --- /dev/null +++ b/src/test/regress/sql/multi_dropped_column_aliases.sql @@ -0,0 +1,29 @@ + +-- Tests that check that our query functionality behaves as expected when the +-- table schema is modified via ALTER statements. + +SELECT count(*) FROM customer; +SELECT * FROM customer LIMIT 2; + +ALTER TABLE customer ADD COLUMN new_column1 INTEGER; +ALTER TABLE customer ADD COLUMN new_column2 INTEGER; +SELECT count(*) FROM customer; +SELECT * FROM customer LIMIT 2; + +ALTER TABLE customer DROP COLUMN new_column1; +ALTER TABLE customer DROP COLUMN new_column2; +SELECT count(*) FROM customer; +SELECT * FROM customer LIMIT 2; + +-- Verify joins work with dropped columns. +SELECT count(*) FROM customer, orders WHERE c_custkey = o_custkey; + +-- Test joinExpr aliases by performing an outer-join. This code path is +-- currently not exercised, but we are adding this test to catch this bug when +-- we start supporting outer joins. + +SELECT c_custkey +FROM (customer LEFT OUTER JOIN orders ON (c_custkey = o_custkey)) AS + test(c_custkey, c_nationkey) + INNER JOIN lineitem ON (test.c_custkey = l_orderkey) +LIMIT 10; diff --git a/src/test/regress/sql/multi_fdw_create_table.sql b/src/test/regress/sql/multi_fdw_create_table.sql new file mode 100644 index 000000000..e0ccd9a3e --- /dev/null +++ b/src/test/regress/sql/multi_fdw_create_table.sql @@ -0,0 +1,81 @@ +-- +-- MULTI_FDW_CREATE_TABLE +-- + +-- Create new table definitions for use in testing in distributed foreign data +-- wrapper functionality. + +SELECT fdwname FROM pg_foreign_data_wrapper; + +CREATE SERVER file_server FOREIGN DATA WRAPPER file_fdw; + +CREATE FOREIGN TABLE lineitem ( + l_orderkey bigint not null, + l_partkey integer not null, + l_suppkey integer not null, + l_linenumber integer not null, + l_quantity decimal(15, 2) not null, + l_extendedprice decimal(15, 2) not null, + l_discount decimal(15, 2) not null, + l_tax decimal(15, 2) not null, + l_returnflag char(1) not null, + l_linestatus char(1) not null, + l_shipdate date not null, + l_commitdate date not null, + l_receiptdate date not null, + l_shipinstruct char(25) not null, + l_shipmode char(10) not null, + l_comment varchar(44) not null) +SERVER file_server +OPTIONS (format 'text', filename '', delimiter '|', null ''); +SELECT master_create_distributed_table('lineitem', 'l_orderkey', 'append'); + +CREATE FOREIGN TABLE orders ( + o_orderkey bigint not null, + o_custkey integer not null, + o_orderstatus char(1) not null, + o_totalprice decimal(15,2) not null, + o_orderdate date not null, + o_orderpriority char(15) not null, + o_clerk char(15) not null, + o_shippriority integer not null, + o_comment varchar(79) not null) +SERVER file_server +OPTIONS (format 'text', filename '', delimiter '|', null ''); +SELECT master_create_distributed_table('orders', 'o_orderkey', 'append'); + +CREATE FOREIGN TABLE customer ( + c_custkey integer not null, + c_name varchar(25) not null, + c_address varchar(40) not null, + c_nationkey integer not null, + c_phone char(15) not null, + c_acctbal decimal(15,2) not null, + c_mktsegment char(10) not null, + c_comment varchar(117) not null) +SERVER file_server +OPTIONS (format 'text', filename '', delimiter '|', null ''); +SELECT master_create_distributed_table('customer', 'c_custkey', 'append'); + +CREATE FOREIGN TABLE nation ( + n_nationkey integer not null, + n_name char(25) not null, + n_regionkey integer not null, + n_comment varchar(152)) +SERVER file_server +OPTIONS (format 'text', filename '', delimiter '|', null ''); +SELECT master_create_distributed_table('nation', 'n_nationkey', 'append'); + +CREATE FOREIGN TABLE part ( + p_partkey integer not null, + p_name varchar(55) not null, + p_mfgr char(25) not null, + p_brand char(10) not null, + p_type varchar(25) not null, + p_size integer not null, + p_container char(10) not null, + p_retailprice decimal(15,2) not null, + p_comment varchar(23) not null) +SERVER file_server +OPTIONS (format 'text', filename '', delimiter '|', null ''); +SELECT master_create_distributed_table('part', 'p_partkey', 'append'); diff --git a/src/test/regress/sql/multi_fdw_master_protocol.sql b/src/test/regress/sql/multi_fdw_master_protocol.sql new file mode 100644 index 000000000..dfd495538 --- /dev/null +++ b/src/test/regress/sql/multi_fdw_master_protocol.sql @@ -0,0 +1,14 @@ +-- +-- MULTI_FDW_MASTER_PROTOCOL +-- + +-- Tests that check the metadata returned by the master node. + +SELECT part_storage_type, part_key, part_replica_count, part_max_size, + part_placement_policy FROM master_get_table_metadata('lineitem'); + +SELECT * FROM master_get_table_ddl_events('lineitem'); + +SELECT * FROM master_get_new_shardid(); + +SELECT node_name FROM master_get_local_first_candidate_nodes(); diff --git a/src/test/regress/sql/multi_generate_ddl_commands.sql b/src/test/regress/sql/multi_generate_ddl_commands.sql new file mode 100644 index 000000000..5e7c4be99 --- /dev/null +++ b/src/test/regress/sql/multi_generate_ddl_commands.sql @@ -0,0 +1,127 @@ +-- =================================================================== +-- create test functions +-- =================================================================== + +CREATE FUNCTION table_ddl_command_array(regclass) + RETURNS text[] + AS 'citusdb' + LANGUAGE C STRICT; + +-- =================================================================== +-- test ddl command generation functionality +-- =================================================================== + +-- first make sure a simple table works +CREATE TABLE simple_table ( + first_name text, + last_name text, + id bigint +); + +SELECT table_ddl_command_array('simple_table'); + +-- ensure not-null constraints are propagated +CREATE TABLE not_null_table ( + city text, + id bigint not null +); + +SELECT table_ddl_command_array('not_null_table'); + +-- ensure tables not in search path are schema-prefixed +CREATE SCHEMA not_in_path CREATE TABLE simple_table (id bigint); + +SELECT table_ddl_command_array('not_in_path.simple_table'); + +-- even more complex constraints should be preserved... +CREATE TABLE column_constraint_table ( + first_name text, + last_name text, + age int CONSTRAINT non_negative_age CHECK (age >= 0) +); + +SELECT table_ddl_command_array('column_constraint_table'); + +-- including table constraints +CREATE TABLE table_constraint_table ( + bid_item_id bigint, + min_bid decimal not null, + max_bid decimal not null, + CONSTRAINT bids_ordered CHECK (min_bid > max_bid) +); + +SELECT table_ddl_command_array('table_constraint_table'); + +-- default values are supported +CREATE TABLE default_value_table ( + name text, + price decimal default 0.00 +); + +SELECT table_ddl_command_array('default_value_table'); + +-- of course primary keys work... +CREATE TABLE pkey_table ( + first_name text, + last_name text, + id bigint PRIMARY KEY +); + +SELECT table_ddl_command_array('pkey_table'); + +-- as do unique indexes... +CREATE TABLE unique_table ( + user_id bigint not null, + username text UNIQUE not null +); + +SELECT table_ddl_command_array('unique_table'); + +-- and indexes used for clustering +CREATE TABLE clustered_table ( + data json not null, + received_at timestamp not null +); + +CREATE INDEX clustered_time_idx ON clustered_table (received_at); + +CLUSTER clustered_table USING clustered_time_idx; + +SELECT table_ddl_command_array('clustered_table'); + +-- fiddly things like storage type and statistics also work +CREATE TABLE fiddly_table ( + hostname char(255) not null, + os char(255) not null, + ip_addr inet not null, + traceroute text not null +); + +ALTER TABLE fiddly_table + ALTER hostname SET STORAGE PLAIN, + ALTER os SET STORAGE MAIN, + ALTER ip_addr SET STORAGE EXTENDED, + ALTER traceroute SET STORAGE EXTERNAL, + ALTER ip_addr SET STATISTICS 500; + +SELECT table_ddl_command_array('fiddly_table'); + +-- test foreign tables using fake FDW +CREATE FOREIGN TABLE foreign_table ( + id bigint not null, + full_name text not null default '' +) SERVER fake_fdw_server OPTIONS (encoding 'utf-8', compression 'true'); + +SELECT table_ddl_command_array('foreign_table'); + +-- propagating views is not supported +CREATE VIEW local_view AS SELECT * FROM simple_table; + +SELECT table_ddl_command_array('local_view'); + +-- clean up +DROP VIEW IF EXISTS local_view; +DROP FOREIGN TABLE IF EXISTS foreign_table; +DROP TABLE IF EXISTS simple_table, not_null_table, column_constraint_table, + table_constraint_table, default_value_table, pkey_table, + unique_table, clustered_table, fiddly_table; diff --git a/src/test/regress/sql/multi_hash_pruning.sql b/src/test/regress/sql/multi_hash_pruning.sql new file mode 100644 index 000000000..6cdd6a504 --- /dev/null +++ b/src/test/regress/sql/multi_hash_pruning.sql @@ -0,0 +1,119 @@ +-- +-- MULTI_HASH_PRUNING +-- + +-- Tests for shard and join pruning logic on hash partitioned tables. + +-- Create a table partitioned on integer column and update partition type to +-- hash. Then stage data to this table and update shard min max values with +-- hashed ones. Hash value of 1, 2, 3 and 4 are consecutively -1905060026, +-- 1134484726, -28094569 and -1011077333. + +CREATE TABLE orders_hash_partitioned ( + o_orderkey integer, + o_custkey integer, + o_orderstatus char(1), + o_totalprice decimal(15,2), + o_orderdate date, + o_orderpriority char(15), + o_clerk char(15), + o_shippriority integer, + o_comment varchar(79) ); +SELECT master_create_distributed_table('orders_hash_partitioned', 'o_orderkey', 'append'); + +UPDATE pg_dist_partition SET partmethod = 'h' + WHERE logicalrelid = 'orders_hash_partitioned'::regclass; + +-- Create logical shards with shardids 110, 111, 112 and 113 + +INSERT INTO pg_dist_shard (logicalrelid, shardid, shardstorage, shardminvalue, shardmaxvalue) + VALUES ('orders_hash_partitioned'::regclass, 110, 't', -1905060026, -1905060026), + ('orders_hash_partitioned'::regclass, 111, 't', 1134484726, 1134484726), + ('orders_hash_partitioned'::regclass, 112, 't', -1905060026, -28094569), + ('orders_hash_partitioned'::regclass, 113, 't', -1011077333, 0); + +-- Create shard placements for shards 110, 111, 112 and 113 + +INSERT INTO pg_dist_shard_placement (shardid, shardstate, shardlength, nodename, nodeport) + SELECT 110, 1, 1, nodename, nodeport + FROM pg_dist_shard_placement + GROUP BY nodename, nodeport + ORDER BY nodename, nodeport ASC + LIMIT 1; + +INSERT INTO pg_dist_shard_placement (shardid, shardstate, shardlength, nodename, nodeport) + SELECT 111, 1, 1, nodename, nodeport + FROM pg_dist_shard_placement + GROUP BY nodename, nodeport + ORDER BY nodename, nodeport ASC + LIMIT 1; + +INSERT INTO pg_dist_shard_placement (shardid, shardstate, shardlength, nodename, nodeport) + SELECT 112, 1, 1, nodename, nodeport + FROM pg_dist_shard_placement + GROUP BY nodename, nodeport + ORDER BY nodename, nodeport ASC + LIMIT 1; + +INSERT INTO pg_dist_shard_placement (shardid, shardstate, shardlength, nodename, nodeport) + SELECT 113, 1, 1, nodename, nodeport + FROM pg_dist_shard_placement + GROUP BY nodename, nodeport + ORDER BY nodename, nodeport ASC + LIMIT 1; + +SET client_min_messages TO DEBUG2; + +-- Check that we can prune shards for simple cases, boolean expressions and +-- immutable functions. + +EXPLAIN SELECT count(*) FROM orders_hash_partitioned; +EXPLAIN SELECT count(*) FROM orders_hash_partitioned WHERE o_orderkey = 1; +EXPLAIN SELECT count(*) FROM orders_hash_partitioned WHERE o_orderkey = 2; +EXPLAIN SELECT count(*) FROM orders_hash_partitioned WHERE o_orderkey = 3; +EXPLAIN SELECT count(*) FROM orders_hash_partitioned WHERE o_orderkey = 4; +EXPLAIN SELECT count(*) FROM orders_hash_partitioned WHERE o_orderkey is NULL; +EXPLAIN SELECT count(*) FROM orders_hash_partitioned WHERE o_orderkey is not NULL; +EXPLAIN SELECT count(*) FROM orders_hash_partitioned WHERE o_orderkey > 2; + +EXPLAIN SELECT count(*) FROM orders_hash_partitioned + WHERE o_orderkey = 1 OR o_orderkey = 2; +EXPLAIN SELECT count(*) FROM orders_hash_partitioned + WHERE o_orderkey = 1 OR o_clerk = 'aaa'; +EXPLAIN SELECT count(*) FROM orders_hash_partitioned + WHERE o_orderkey = 1 AND o_clerk = 'aaa'; +EXPLAIN SELECT count(*) FROM orders_hash_partitioned + WHERE o_orderkey = 1 OR (o_orderkey = 3 AND o_clerk = 'aaa'); +EXPLAIN SELECT count(*) FROM orders_hash_partitioned + WHERE o_orderkey = 1 OR o_orderkey is NULL; +EXPLAIN SELECT count(*) FROM + (SELECT o_orderkey FROM orders_hash_partitioned WHERE o_orderkey = 1) AS orderkeys; + +EXPLAIN SELECT count(*) FROM orders_hash_partitioned WHERE o_orderkey = abs(-1); + +-- Check that we don't support pruning for ANY (array expression) + +EXPLAIN SELECT count(*) FROM orders_hash_partitioned + WHERE o_orderkey = 1 OR o_totalprice IN (2, 5); + +-- Check that we cannot prune for mutable functions. + +EXPLAIN SELECT count(*) FROM orders_hash_partitioned WHERE o_orderkey = random(); +EXPLAIN SELECT count(*) FROM orders_hash_partitioned + WHERE o_orderkey = random() OR o_orderkey = 1; +EXPLAIN SELECT count(*) FROM orders_hash_partitioned + WHERE o_orderkey = random() AND o_orderkey = 1; + +-- Check that we can do join pruning. + +EXPLAIN SELECT count(*) + FROM orders_hash_partitioned orders1, orders_hash_partitioned orders2 + WHERE orders1.o_orderkey = orders2.o_orderkey; + +EXPLAIN SELECT count(*) + FROM orders_hash_partitioned orders1, orders_hash_partitioned orders2 + WHERE orders1.o_orderkey = orders2.o_orderkey + AND orders1.o_orderkey = 1 + AND orders2.o_orderkey is NULL; + +SET client_min_messages TO NOTICE; diff --git a/src/test/regress/sql/multi_index_statements.sql b/src/test/regress/sql/multi_index_statements.sql new file mode 100644 index 000000000..a9a4506ff --- /dev/null +++ b/src/test/regress/sql/multi_index_statements.sql @@ -0,0 +1,70 @@ +-- +-- MULTI_INDEX_STATEMENTS +-- + +-- Check that we can run CREATE INDEX and DROP INDEX statements on distributed +-- tables. We increase the logging verbosity to verify that commands are +-- propagated to all worker shards. + +SET client_min_messages TO DEBUG2; + +-- +-- CREATE INDEX +-- + +-- Verify that we can create different types of indexes + +CREATE INDEX lineitem_orderkey_index ON lineitem (l_orderkey); + +CREATE INDEX lineitem_partkey_desc_index ON lineitem (l_partkey DESC); + +CREATE INDEX lineitem_partial_index ON lineitem (l_shipdate) + WHERE l_shipdate < '1995-01-01'; + +CREATE INDEX lineitem_orderkey_hash_index ON lineitem USING hash (l_partkey); + +-- Verify that all indexes got created on the master node +SELECT * FROM pg_indexes WHERE tablename = 'lineitem' ORDER BY indexname; + +-- Verify that we error out on unsupported statement types + +CREATE INDEX CONCURRENTLY try_index ON lineitem (l_orderkey); +CREATE UNIQUE INDEX try_index ON lineitem (l_orderkey); +CREATE INDEX try_index ON lineitem (l_orderkey) TABLESPACE newtablespace; + +-- Verify that we error out in case of postgres errors on supported statement +-- types. + +CREATE INDEX lineitem_orderkey_index ON lineitem (l_orderkey); +CREATE INDEX try_index ON lineitem USING gist (l_orderkey); +CREATE INDEX try_index ON lineitem (non_existent_column); + +-- Verify that none of failed indexes got created on the master node +SELECT * FROM pg_indexes WHERE tablename = 'lineitem' ORDER BY indexname; + +-- +-- DROP INDEX +-- + +-- Verify that we can't drop multiple indexes in a single command +DROP INDEX lineitem_orderkey_index, lineitem_partial_index; + +-- Verify that we error out on the CONCURRENTLY clause +DROP INDEX CONCURRENTLY lineitem_orderkey_index; + +-- Verify that we can succesfully drop indexes +DROP INDEX lineitem_orderkey_index; +DROP INDEX lineitem_partkey_desc_index; +DROP INDEX lineitem_partial_index; + +-- Verify that we handle if exists statements correctly + +DROP INDEX non_existent_index; +DROP INDEX IF EXISTS non_existent_index; + +DROP INDEX IF EXISTS lineitem_orderkey_hash_index; +DROP INDEX lineitem_orderkey_hash_index; + +-- Verify that all the indexes are also dropped from the master node +SELECT * FROM pg_indexes WHERE tablename = 'lineitem' ORDER BY indexname; + diff --git a/src/test/regress/sql/multi_join_order_additional.sql b/src/test/regress/sql/multi_join_order_additional.sql new file mode 100644 index 000000000..678d9077c --- /dev/null +++ b/src/test/regress/sql/multi_join_order_additional.sql @@ -0,0 +1,102 @@ +-- +-- MULTI_JOIN_ORDER_ADDITIONAL +-- + +-- Set configuration to print table join order and pruned shards + +SET citusdb.log_multi_join_order TO TRUE; +SET client_min_messages TO DEBUG2; + +-- The following query checks that we can correctly handle self-joins + +EXPLAIN SELECT l1.l_quantity FROM lineitem l1, lineitem l2 + WHERE l1.l_orderkey = l2.l_orderkey AND l1.l_quantity > 5; + +-- Update configuration to treat lineitem and orders tables as large + +SET citusdb.large_table_shard_count TO 2; +SET client_min_messages TO LOG; + +-- The following queries check that we correctly handle joins and OR clauses. In +-- particular, these queries check that we factorize out OR clauses if possible, +-- and that we default to a cartesian product otherwise. + +EXPLAIN SELECT count(*) FROM lineitem, orders + WHERE (l_orderkey = o_orderkey AND l_quantity > 5) + OR (l_orderkey = o_orderkey AND l_quantity < 10); + +EXPLAIN SELECT l_quantity FROM lineitem, orders + WHERE (l_orderkey = o_orderkey OR l_quantity > 5); + +-- The below queries modify the partition method in pg_dist_partition. We thus +-- begin a transaction here so the changes don't impact any other parallel +-- running tests. +BEGIN; + +-- Validate that we take into account the partition method when building the +-- join-order plan. + +UPDATE pg_dist_partition SET partmethod = 'h' WHERE + logicalrelid = (SELECT relfilenode FROM pg_class WHERE relname = 'lineitem'); + +EXPLAIN SELECT count(*) FROM orders, lineitem + WHERE o_orderkey = l_orderkey; + +-- Verify we handle local joins between two hash-partitioned tables. +UPDATE pg_dist_partition SET partmethod = 'h' WHERE + logicalrelid = (SELECT relfilenode FROM pg_class WHERE relname = 'orders'); + +EXPLAIN SELECT count(*) FROM orders, lineitem + WHERE o_orderkey = l_orderkey; + +UPDATE pg_dist_partition SET partmethod = 'a' WHERE + logicalrelid = (SELECT relfilenode FROM pg_class WHERE relname = 'lineitem'); +UPDATE pg_dist_partition SET partmethod = 'a' WHERE + logicalrelid = (SELECT relfilenode FROM pg_class WHERE relname = 'orders'); + + +-- Validate that we can handle broadcast joins with hash-partitioned tables. +UPDATE pg_dist_partition SET partmethod = 'h' WHERE + logicalrelid = (SELECT relfilenode FROM pg_class WHERE relname = 'customer'); + +EXPLAIN SELECT count(*) FROM customer, nation + WHERE c_nationkey = n_nationkey; + +UPDATE pg_dist_partition SET partmethod = 'a' WHERE + logicalrelid = (SELECT relfilenode FROM pg_class WHERE relname = 'customer'); + +-- Update the large table shard count for all the following tests. +SET citusdb.large_table_shard_count TO 1; + +-- Validate that we don't use a single-partition join method for a hash +-- re-partitioned table, thus preventing a partition of just the customer table. +EXPLAIN SELECT count(*) FROM orders, lineitem, customer + WHERE o_custkey = l_partkey AND o_custkey = c_nationkey; + +-- Validate that we don't chose a single-partition join method with a +-- hash-partitioned base table +UPDATE pg_dist_partition SET partmethod = 'h' WHERE + logicalrelid = (SELECT relfilenode FROM pg_class WHERE relname = 'customer'); + +EXPLAIN SELECT count(*) FROM orders, customer + WHERE c_custkey = o_custkey; + +UPDATE pg_dist_partition SET partmethod = 'a' WHERE + logicalrelid = (SELECT relfilenode FROM pg_class WHERE relname = 'customer'); + +-- Validate that we can re-partition a hash partitioned table to join with a +-- range partitioned one. +UPDATE pg_dist_partition SET partmethod = 'h' WHERE + logicalrelid = (SELECT relfilenode FROM pg_class WHERE relname = 'orders'); + +EXPLAIN SELECT count(*) FROM orders, customer + WHERE c_custkey = o_custkey; + +UPDATE pg_dist_partition SET partmethod = 'a' WHERE + logicalrelid = (SELECT relfilenode FROM pg_class WHERE relname = 'orders'); + +COMMIT; + +-- Reset client logging level to its previous value + +SET client_min_messages TO NOTICE; diff --git a/src/test/regress/sql/multi_join_order_tpch_large.sql b/src/test/regress/sql/multi_join_order_tpch_large.sql new file mode 100644 index 000000000..7b0431fd8 --- /dev/null +++ b/src/test/regress/sql/multi_join_order_tpch_large.sql @@ -0,0 +1,135 @@ +-- +-- MULTI_JOIN_ORDER_TPCH_LARGE +-- + +-- Enable configuration to print table join order + +SET citusdb.log_multi_join_order TO TRUE; +SET client_min_messages TO LOG; + +-- Change configuration to treat lineitem, orders, customer, and part tables as +-- large. The following queries are basically the same as the ones in tpch_small +-- except that more data has been staged to customer and part tables. Therefore, +-- we will apply different distributed join strategies for these queries. + +SET citusdb.large_table_shard_count TO 2; + +-- Query #6 from the TPC-H decision support benchmark + +EXPLAIN SELECT + sum(l_extendedprice * l_discount) as revenue +FROM + lineitem +WHERE + l_shipdate >= date '1994-01-01' + and l_shipdate < date '1994-01-01' + interval '1 year' + and l_discount between 0.06 - 0.01 and 0.06 + 0.01 + and l_quantity < 24; + +-- Query #3 from the TPC-H decision support benchmark + +EXPLAIN SELECT + l_orderkey, + sum(l_extendedprice * (1 - l_discount)) as revenue, + o_orderdate, + o_shippriority +FROM + customer, + orders, + lineitem +WHERE + c_mktsegment = 'BUILDING' + AND c_custkey = o_custkey + AND l_orderkey = o_orderkey + AND o_orderdate < date '1995-03-15' + AND l_shipdate > date '1995-03-15' +GROUP BY + l_orderkey, + o_orderdate, + o_shippriority +ORDER BY + revenue DESC, + o_orderdate; + +-- Query #10 from the TPC-H decision support benchmark + +EXPLAIN SELECT + c_custkey, + c_name, + sum(l_extendedprice * (1 - l_discount)) as revenue, + c_acctbal, + n_name, + c_address, + c_phone, + c_comment +FROM + customer, + orders, + lineitem, + nation +WHERE + c_custkey = o_custkey + AND l_orderkey = o_orderkey + AND o_orderdate >= date '1993-10-01' + AND o_orderdate < date '1993-10-01' + interval '3' month + AND l_returnflag = 'R' + AND c_nationkey = n_nationkey +GROUP BY + c_custkey, + c_name, + c_acctbal, + c_phone, + n_name, + c_address, + c_comment +ORDER BY + revenue DESC; + +-- Query #19 from the TPC-H decision support benchmark (modified) + +EXPLAIN SELECT + sum(l_extendedprice* (1 - l_discount)) as revenue +FROM + lineitem, + part +WHERE + ( + p_partkey = l_partkey + AND (p_brand = 'Brand#12' OR p_brand= 'Brand#14' OR p_brand='Brand#15') + AND l_quantity >= 10 + AND l_shipmode in ('AIR', 'AIR REG', 'TRUCK') + AND l_shipinstruct = 'DELIVER IN PERSON' + ) + OR + ( + p_partkey = l_partkey + AND (p_brand = 'Brand#23' OR p_brand='Brand#24') + AND l_quantity >= 20 + AND l_shipmode in ('AIR', 'AIR REG', 'TRUCK') + AND l_shipinstruct = 'DELIVER IN PERSON' + ) + OR + ( + p_partkey = l_partkey + AND (p_brand = 'Brand#33' OR p_brand = 'Brand#34' OR p_brand = 'Brand#35') + AND l_quantity >= 1 + AND l_shipmode in ('AIR', 'AIR REG', 'TRUCK') + AND l_shipinstruct = 'DELIVER IN PERSON' + ); + +-- Query to test multiple re-partition jobs in a single query + +EXPLAIN SELECT + l_partkey, count(*) +FROM + lineitem, part, orders, customer +WHERE + l_orderkey = o_orderkey AND + l_partkey = p_partkey AND + c_custkey = o_custkey +GROUP BY + l_partkey; + +-- Reset client logging level to its previous value + +SET client_min_messages TO NOTICE; diff --git a/src/test/regress/sql/multi_join_order_tpch_small.sql b/src/test/regress/sql/multi_join_order_tpch_small.sql new file mode 100644 index 000000000..545bab32c --- /dev/null +++ b/src/test/regress/sql/multi_join_order_tpch_small.sql @@ -0,0 +1,119 @@ +-- +-- MULTI_JOIN_ORDER_TPCH_SMALL +-- + +-- Enable configuration to print table join order + +SET citusdb.log_multi_join_order TO TRUE; +SET client_min_messages TO LOG; + +-- Change configuration to treat lineitem and orders tables as large + +SET citusdb.large_table_shard_count TO 2; + +-- Query #6 from the TPC-H decision support benchmark + +EXPLAIN SELECT + sum(l_extendedprice * l_discount) as revenue +FROM + lineitem +WHERE + l_shipdate >= date '1994-01-01' + and l_shipdate < date '1994-01-01' + interval '1 year' + and l_discount between 0.06 - 0.01 and 0.06 + 0.01 + and l_quantity < 24; + +-- Query #3 from the TPC-H decision support benchmark + +EXPLAIN SELECT + l_orderkey, + sum(l_extendedprice * (1 - l_discount)) as revenue, + o_orderdate, + o_shippriority +FROM + customer, + orders, + lineitem +WHERE + c_mktsegment = 'BUILDING' + AND c_custkey = o_custkey + AND l_orderkey = o_orderkey + AND o_orderdate < date '1995-03-15' + AND l_shipdate > date '1995-03-15' +GROUP BY + l_orderkey, + o_orderdate, + o_shippriority +ORDER BY + revenue DESC, + o_orderdate; + +-- Query #10 from the TPC-H decision support benchmark + +EXPLAIN SELECT + c_custkey, + c_name, + sum(l_extendedprice * (1 - l_discount)) as revenue, + c_acctbal, + n_name, + c_address, + c_phone, + c_comment +FROM + customer, + orders, + lineitem, + nation +WHERE + c_custkey = o_custkey + AND l_orderkey = o_orderkey + AND o_orderdate >= date '1993-10-01' + AND o_orderdate < date '1993-10-01' + interval '3' month + AND l_returnflag = 'R' + AND c_nationkey = n_nationkey +GROUP BY + c_custkey, + c_name, + c_acctbal, + c_phone, + n_name, + c_address, + c_comment +ORDER BY + revenue DESC; + +-- Query #19 from the TPC-H decision support benchmark (modified) + +EXPLAIN SELECT + sum(l_extendedprice* (1 - l_discount)) as revenue +FROM + lineitem, + part +WHERE + ( + p_partkey = l_partkey + AND (p_brand = 'Brand#12' OR p_brand= 'Brand#14' OR p_brand='Brand#15') + AND l_quantity >= 10 + AND l_shipmode in ('AIR', 'AIR REG', 'TRUCK') + AND l_shipinstruct = 'DELIVER IN PERSON' + ) + OR + ( + p_partkey = l_partkey + AND (p_brand = 'Brand#23' OR p_brand='Brand#24') + AND l_quantity >= 20 + AND l_shipmode in ('AIR', 'AIR REG', 'TRUCK') + AND l_shipinstruct = 'DELIVER IN PERSON' + ) + OR + ( + p_partkey = l_partkey + AND (p_brand = 'Brand#33' OR p_brand = 'Brand#34' OR p_brand = 'Brand#35') + AND l_quantity >= 1 + AND l_shipmode in ('AIR', 'AIR REG', 'TRUCK') + AND l_shipinstruct = 'DELIVER IN PERSON' + ); + +-- Reset client logging level to its previous value + +SET client_min_messages TO NOTICE; diff --git a/src/test/regress/sql/multi_join_pruning.sql b/src/test/regress/sql/multi_join_pruning.sql new file mode 100644 index 000000000..29df48095 --- /dev/null +++ b/src/test/regress/sql/multi_join_pruning.sql @@ -0,0 +1,56 @@ +-- +-- MULTI_JOIN_PRUNING +-- + +-- Check that join-pruning works for joins between two large relations. For now +-- we only check for join-pruning between locally partitioned relations. In the +-- future we want to check for pruning between re-partitioned relations as well. + +SET client_min_messages TO DEBUG2; + +-- Change configuration to treat all tables as large + +SET citusdb.large_table_shard_count TO 2; + +SELECT sum(l_linenumber), avg(l_linenumber) FROM lineitem, orders + WHERE l_orderkey = o_orderkey; + +SELECT sum(l_linenumber), avg(l_linenumber) FROM lineitem, orders + WHERE l_orderkey = o_orderkey AND l_orderkey > 9030; + +-- Shards for the lineitem table have been pruned away. Check that join pruning +-- works as expected in this case. + +SELECT sum(l_linenumber), avg(l_linenumber) FROM lineitem, orders + WHERE l_orderkey = o_orderkey AND l_orderkey > 20000; + +-- Partition pruning left three shards for the lineitem and one shard for the +-- orders table. These shard sets don't overlap, so join pruning should prune +-- out all the shards, and leave us with an empty task list. + +SELECT sum(l_linenumber), avg(l_linenumber) FROM lineitem, orders + WHERE l_orderkey = o_orderkey AND l_orderkey > 6000 AND o_orderkey < 6000; + +-- These tests check that we can do join pruning for tables partitioned over +-- different type of columns including varchar, array types, composite types +-- etc. This is in response to a bug we had where we were not able to resolve +-- correct operator types for some kind of column types. + +EXPLAIN SELECT count(*) + FROM array_partitioned_table table1, array_partitioned_table table2 + WHERE table1.array_column = table2.array_column; + +EXPLAIN SELECT count(*) + FROM composite_partitioned_table table1, composite_partitioned_table table2 + WHERE table1.composite_column = table2.composite_column; + +-- Large table joins between varchar columns do not work because of a bug we +-- have. Currently, we require joins to be only on columns. Postgres adds a +-- relabel to typecast varchars to text due to which our check fails and we +-- error out. + +EXPLAIN SELECT count(*) + FROM varchar_partitioned_table table1, varchar_partitioned_table table2 + WHERE table1.varchar_column = table2.varchar_column; + +SET client_min_messages TO NOTICE; diff --git a/src/test/regress/sql/multi_large_table_join_planning.sql b/src/test/regress/sql/multi_large_table_join_planning.sql new file mode 100644 index 000000000..06a914361 --- /dev/null +++ b/src/test/regress/sql/multi_large_table_join_planning.sql @@ -0,0 +1,58 @@ +-- +-- MULTI_LARGE_TABLE_PLANNING +-- + +-- Tests that cover large table join planning. Note that we explicitly start a +-- transaction block here so that we don't emit debug messages with changing +-- transaction ids in them. Also, we set the executor type to task tracker +-- executor here, as we cannot run repartition jobs with real time executor. + +BEGIN; +SET client_min_messages TO DEBUG4; +SET citusdb.large_table_shard_count TO 2; +SET citusdb.task_executor_type TO 'task-tracker'; + +-- Debug4 log messages display jobIds within them. We explicitly set the jobId +-- sequence here so that the regression output becomes independent of the number +-- of jobs executed prior to running this test. + +ALTER SEQUENCE pg_catalog.pg_dist_jobid_seq RESTART 1250; + +-- Multi-level repartition join to verify our projection columns are correctly +-- referenced and propagated across multiple repartition jobs. The test also +-- validates that only the minimal necessary projection columns are transferred +-- between jobs. + +SELECT + l_partkey, o_orderkey, count(*) +FROM + lineitem, part, orders, customer +WHERE + l_orderkey = o_orderkey AND + l_partkey = p_partkey AND + c_custkey = o_custkey AND + (l_quantity > 5.0 OR l_extendedprice > 1200.0) AND + p_size > 8 AND o_totalprice > 10 AND + c_acctbal < 5000.0 +GROUP BY + l_partkey, o_orderkey +ORDER BY + l_partkey, o_orderkey +LIMIT 30; + +SELECT + l_partkey, o_orderkey, count(*) +FROM + lineitem, orders +WHERE + l_suppkey = o_shippriority AND + l_quantity < 5.0 AND o_totalprice <> 4.0 +GROUP BY + l_partkey, o_orderkey +ORDER BY + l_partkey, o_orderkey; + +-- Reset client logging level to its previous value + +SET client_min_messages TO NOTICE; +COMMIT; diff --git a/src/test/regress/sql/multi_large_table_pruning.sql b/src/test/regress/sql/multi_large_table_pruning.sql new file mode 100644 index 000000000..897aa73a7 --- /dev/null +++ b/src/test/regress/sql/multi_large_table_pruning.sql @@ -0,0 +1,68 @@ +-- +-- MULTI_LARGE_TABLE_PRUNING +-- + +-- Tests covering partition and join-pruning for large table joins. Note that we +-- set executor type to task tracker executor here, as we cannot run repartition +-- jobs with real time executor. + +SET citusdb.large_table_shard_count TO 2; +SET client_min_messages TO DEBUG2; +SET citusdb.task_executor_type TO 'task-tracker'; + +-- Single range-repartition join to test join-pruning behaviour. + +SELECT + count(*) +FROM + orders, customer +WHERE + o_custkey = c_custkey; + +-- Single range-repartition join with a selection clause on the partitioned +-- table to test the case when all map tasks are pruned away. + +SELECT + count(*) +FROM + orders, customer +WHERE + o_custkey = c_custkey AND + o_orderkey < 0; + +-- Single range-repartition join with a selection clause on the base table to +-- test the case when all sql tasks are pruned away. + +SELECT + count(*) +FROM + orders, customer +WHERE + o_custkey = c_custkey AND + c_custkey < 0; + +-- Dual hash-repartition join test case. Note that this query doesn't produce +-- meaningful results and is only to test hash-partitioning of two large tables +-- on non-partition columns. + +SELECT + count(*) +FROM + lineitem, customer +WHERE + l_partkey = c_nationkey; + +-- Dual hash-repartition join with a selection clause on one of the tables to +-- test the case when all map tasks are pruned away. + +SELECT + count(*) +FROM + lineitem, customer +WHERE + l_partkey = c_nationkey AND + l_orderkey < 0; + +-- Reset client logging level to its previous value + +SET client_min_messages TO NOTICE; diff --git a/src/test/regress/sql/multi_large_table_task_assignment.sql b/src/test/regress/sql/multi_large_table_task_assignment.sql new file mode 100644 index 000000000..8fd902950 --- /dev/null +++ b/src/test/regress/sql/multi_large_table_task_assignment.sql @@ -0,0 +1,63 @@ +-- +-- MULTI_LARGE_TABLE_TASK_ASSIGNMENT +-- + +-- Tests which cover task assignment for MapMerge jobs for single range repartition +-- and dual hash repartition joins. The tests also cover task assignment propagation +-- from a sql task to its depended tasks. Note that we set the executor type to task +-- tracker executor here, as we cannot run repartition jobs with real time executor. + +BEGIN; +SET client_min_messages TO DEBUG3; +SET citusdb.large_table_shard_count TO 2; +SET citusdb.task_executor_type TO 'task-tracker'; + +-- Single range repartition join to test anchor-shard based task assignment and +-- assignment propagation to merge and data-fetch tasks. + +SELECT + count(*) +FROM + orders, customer +WHERE + o_custkey = c_custkey; + +-- Single range repartition join, along with a join with a small table containing +-- more than one shard. This situation results in multiple sql tasks depending on +-- the same merge task, and tests our constraint group creation and assignment +-- propagation. Here 'orders' is considered the small table. + +SET citusdb.large_table_shard_count TO 3; + +SELECT + count(*) +FROM + orders, customer, lineitem +WHERE + o_custkey = c_custkey AND + o_orderkey = l_orderkey; + +SET citusdb.large_table_shard_count TO 2; + +-- The next test, dual hash repartition join, uses the current jobId to assign +-- tasks in a round-robin fashion. We therefore need to ensure that jobIds start +-- with an odd number here to get consistent test output. + +SELECT case when (currval('pg_dist_jobid_seq') % 2) = 0 + then nextval('pg_dist_jobid_seq') % 2 + else 1 end; + +-- Dual hash repartition join which tests the separate hash repartition join +-- task assignment algorithm. + +SELECT + count(*) +FROM + lineitem, customer +WHERE + l_partkey = c_nationkey; + +-- Reset client logging level to its previous value + +SET client_min_messages TO NOTICE; +COMMIT; diff --git a/src/test/regress/sql/multi_limit_clause.sql b/src/test/regress/sql/multi_limit_clause.sql new file mode 100644 index 000000000..9d68ec526 --- /dev/null +++ b/src/test/regress/sql/multi_limit_clause.sql @@ -0,0 +1,61 @@ +-- +-- MULTI_LIMIT_CLAUSE +-- + +-- Display debug messages on limit clause push down. + +SET client_min_messages TO DEBUG1; + +-- Check that we can correctly handle the Limit clause in distributed queries. +-- Note that we don't have the limit optimization enabled for these queries, and +-- will end up fetching all rows to the master database. + +SELECT count(*) count_quantity, l_quantity FROM lineitem WHERE l_quantity < 32.0 + GROUP BY l_quantity + ORDER BY count_quantity ASC, l_quantity ASC; + +SELECT count(*) count_quantity, l_quantity FROM lineitem WHERE l_quantity < 32.0 + GROUP BY l_quantity + ORDER BY count_quantity DESC, l_quantity DESC; + +SELECT count(*) count_quantity, l_quantity FROM lineitem WHERE l_quantity < 32.0 + GROUP BY l_quantity + ORDER BY count_quantity ASC, l_quantity ASC LIMIT 5; + +SELECT count(*) count_quantity, l_quantity FROM lineitem WHERE l_quantity < 32.0 + GROUP BY l_quantity + ORDER BY count_quantity ASC, l_quantity ASC LIMIT 10; + +SELECT count(*) count_quantity, l_quantity FROM lineitem WHERE l_quantity < 32.0 + GROUP BY l_quantity + ORDER BY count_quantity DESC, l_quantity DESC LIMIT 10; + +-- Check that we can handle limits for simple sort clauses. We order by columns +-- in the first two tests, and then by a simple expression in the last test. + +SELECT min(l_orderkey) FROM lineitem; +SELECT l_orderkey FROM lineitem ORDER BY l_orderkey ASC LIMIT 1; + +SELECT max(l_orderkey) FROM lineitem; +SELECT l_orderkey FROM lineitem ORDER BY l_orderkey DESC LIMIT 1; +SELECT * FROM lineitem ORDER BY l_orderkey DESC, l_linenumber DESC LIMIT 3; + +SELECT max(extract(epoch from l_shipdate)) FROM lineitem; +SELECT * FROM lineitem + ORDER BY extract(epoch from l_shipdate) DESC, l_orderkey DESC LIMIT 3; + +-- Exercise the scenario where order by clauses don't have any aggregates, and +-- that we can push down the limit as a result. Check that when this happens, we +-- also sort on all group by clauses behind the covers. + +SELECT l_quantity, l_discount, avg(l_partkey) FROM lineitem + GROUP BY l_quantity, l_discount + ORDER BY l_quantity LIMIT 1; + +-- Results from the previous query should match this query's results. + +SELECT l_quantity, l_discount, avg(l_partkey) FROM lineitem + GROUP BY l_quantity, l_discount + ORDER BY l_quantity, l_discount LIMIT 1; + +SET client_min_messages TO NOTICE; diff --git a/src/test/regress/sql/multi_limit_clause_approximate.sql b/src/test/regress/sql/multi_limit_clause_approximate.sql new file mode 100644 index 000000000..8daca0930 --- /dev/null +++ b/src/test/regress/sql/multi_limit_clause_approximate.sql @@ -0,0 +1,73 @@ +-- +-- MULTI_LIMIT_CLAUSE_APPROXIMATE +-- + +-- Display debug messages on limit clause push down. + +SET client_min_messages TO DEBUG1; + +-- We first look at results with limit optimization disabled. This first query +-- has a group and an order by. The order by clause is a commutative aggregate +-- function. + +SELECT l_partkey, sum(l_partkey * (1 + l_suppkey)) AS aggregate FROM lineitem + GROUP BY l_partkey + ORDER BY aggregate DESC LIMIT 10; + +-- Enable limit optimization to fetch one third of each shard's data + +SET citusdb.limit_clause_row_fetch_count TO 600; + +SELECT l_partkey, sum(l_partkey * (1 + l_suppkey)) AS aggregate FROM lineitem + GROUP BY l_partkey + ORDER BY aggregate DESC LIMIT 10; + +-- Disable limit optimization for our second test. This time, we have a query +-- that joins several tables, and that groups and orders the results. + +RESET citusdb.limit_clause_row_fetch_count; + +SELECT c_custkey, c_name, count(*) as lineitem_count + FROM customer, orders, lineitem + WHERE c_custkey = o_custkey AND l_orderkey = o_orderkey + GROUP BY c_custkey, c_name + ORDER BY lineitem_count DESC, c_custkey LIMIT 10; + +-- Now, enable limit optimization to fetch half of each task's results. For this +-- test, we also change a config setting to ensure that we don't repartition any +-- of the tables during the query. + +SET citusdb.limit_clause_row_fetch_count TO 150; +SET citusdb.large_table_shard_count TO 2; + +SELECT c_custkey, c_name, count(*) as lineitem_count + FROM customer, orders, lineitem + WHERE c_custkey = o_custkey AND l_orderkey = o_orderkey + GROUP BY c_custkey, c_name + ORDER BY lineitem_count DESC, c_custkey LIMIT 10; + +RESET citusdb.large_table_shard_count; + +-- We now test scenarios where applying the limit optimization wouldn't produce +-- meaningful results. First, we check that we don't push down the limit clause +-- for non-commutative aggregates. + +SELECT l_partkey, avg(l_suppkey) AS average FROM lineitem + GROUP BY l_partkey + ORDER BY average DESC, l_partkey LIMIT 10; + +-- Next, check that we don't apply the limit optimization for expressions that +-- have aggregates within them + +SELECT l_partkey, round(sum(l_suppkey)) AS complex_expression FROM lineitem + GROUP BY l_partkey + ORDER BY complex_expression DESC LIMIT 10; + +-- Check that query execution works as expected for other queries without limits + +SELECT count(*) count_quantity, l_quantity FROM lineitem WHERE l_quantity < 10.0 + GROUP BY l_quantity + ORDER BY count_quantity ASC, l_quantity ASC; + +RESET citusdb.limit_clause_row_fetch_count; +RESET client_min_messages; diff --git a/src/test/regress/sql/multi_master_protocol.sql b/src/test/regress/sql/multi_master_protocol.sql new file mode 100644 index 000000000..054220e76 --- /dev/null +++ b/src/test/regress/sql/multi_master_protocol.sql @@ -0,0 +1,20 @@ +-- +-- MULTI_MASTER_PROTOCOL +-- + +-- Tests that check the metadata returned by the master node. + +SELECT part_storage_type, part_key, part_replica_count, part_max_size, + part_placement_policy FROM master_get_table_metadata('lineitem'); + +SELECT * FROM master_get_table_ddl_events('lineitem'); + +SELECT * FROM master_get_new_shardid(); + +SELECT * FROM master_get_local_first_candidate_nodes(); + +SELECT * FROM master_get_round_robin_candidate_nodes(1); + +SELECT * FROM master_get_round_robin_candidate_nodes(2); + +SELECT * FROM master_get_active_worker_nodes(); diff --git a/src/test/regress/sql/multi_modifications.sql b/src/test/regress/sql/multi_modifications.sql new file mode 100644 index 000000000..040411079 --- /dev/null +++ b/src/test/regress/sql/multi_modifications.sql @@ -0,0 +1,232 @@ +-- =================================================================== +-- test end-to-end modification functionality +-- =================================================================== + +CREATE TYPE order_side AS ENUM ('buy', 'sell'); + +CREATE TABLE limit_orders ( + id bigint PRIMARY KEY, + symbol text NOT NULL, + bidder_id bigint NOT NULL, + placed_at timestamp NOT NULL, + kind order_side NOT NULL, + limit_price decimal NOT NULL DEFAULT 0.00 CHECK (limit_price >= 0.00) +); + +CREATE TABLE insufficient_shards ( LIKE limit_orders ); +CREATE TABLE range_partitioned ( LIKE limit_orders ); +CREATE TABLE append_partitioned ( LIKE limit_orders ); + +SELECT master_create_distributed_table('limit_orders', 'id', 'hash'); +SELECT master_create_distributed_table('insufficient_shards', 'id', 'hash'); +SELECT master_create_distributed_table('range_partitioned', 'id', 'range'); +SELECT master_create_distributed_table('append_partitioned', 'id', 'append'); + +SELECT master_create_worker_shards('limit_orders', 2, 2); + +-- make a single shard that covers no partition values +SELECT master_create_worker_shards('insufficient_shards', 1, 1); +UPDATE pg_dist_shard SET shardminvalue = 0, shardmaxvalue = 0 +WHERE logicalrelid = 'insufficient_shards'::regclass; + +-- create range-partitioned shards +SELECT master_create_empty_shard('range_partitioned') AS new_shard_id +\gset +UPDATE pg_dist_shard SET shardminvalue = 0, shardmaxvalue = 49999 +WHERE shardid = :new_shard_id; + +SELECT master_create_empty_shard('range_partitioned') AS new_shard_id +\gset +UPDATE pg_dist_shard SET shardminvalue = 50000, shardmaxvalue = 99999 +WHERE shardid = :new_shard_id; + +-- create append-partitioned shard +SELECT master_create_empty_shard('append_partitioned') AS new_shard_id +\gset +UPDATE pg_dist_shard SET shardminvalue = 0, shardmaxvalue = 100000 +WHERE shardid = :new_shard_id; + +-- basic single-row INSERT +INSERT INTO limit_orders VALUES (32743, 'AAPL', 9580, '2004-10-19 10:23:54', 'buy', + 20.69); +SELECT COUNT(*) FROM limit_orders WHERE id = 32743; + +-- try a single-row INSERT with no shard to receive it +INSERT INTO insufficient_shards VALUES (32743, 'AAPL', 9580, '2004-10-19 10:23:54', 'buy', + 20.69); + +-- try an insert to a range-partitioned table +INSERT INTO range_partitioned VALUES (32743, 'AAPL', 9580, '2004-10-19 10:23:54', 'buy', + 20.69); + +-- ensure the value is where we put it and query to find it is properly pruned +SET client_min_messages TO 'DEBUG2'; +SET citusdb.task_executor_type TO 'router'; +SELECT * FROM range_partitioned WHERE id = 32743; +SET client_min_messages TO DEFAULT; +SET citusdb.task_executor_type TO DEFAULT; + +-- also try inserting without a range-partitioned shard to receive the value +INSERT INTO range_partitioned VALUES (999999, 'AAPL', 9580, '2004-10-19 10:23:54', 'buy', + 20.69); + +-- try an insert to an append-partitioned table +INSERT INTO append_partitioned VALUES (414123, 'AAPL', 9580, '2004-10-19 10:23:54', 'buy', + 20.69); + +-- INSERT with DEFAULT in the target list +INSERT INTO limit_orders VALUES (12756, 'MSFT', 10959, '2013-05-08 07:29:23', 'sell', + DEFAULT); +SELECT COUNT(*) FROM limit_orders WHERE id = 12756; + +-- INSERT with expressions in target list +INSERT INTO limit_orders VALUES (430, upper('ibm'), 214, timestamp '2003-01-28 10:31:17' + + interval '5 hours', 'buy', sqrt(2)); +SELECT COUNT(*) FROM limit_orders WHERE id = 430; + +-- INSERT without partition key +INSERT INTO limit_orders DEFAULT VALUES; + +-- squelch WARNINGs that contain worker_port +SET client_min_messages TO ERROR; + +-- INSERT violating NOT NULL constraint +INSERT INTO limit_orders VALUES (NULL, 'T', 975234, DEFAULT); + +-- INSERT violating column constraint +INSERT INTO limit_orders VALUES (18811, 'BUD', 14962, '2014-04-05 08:32:16', 'sell', + -5.00); + +-- INSERT violating primary key constraint +INSERT INTO limit_orders VALUES (32743, 'LUV', 5994, '2001-04-16 03:37:28', 'buy', 0.58); + +SET client_min_messages TO DEFAULT; + +-- commands with non-constant partition values are unsupported +INSERT INTO limit_orders VALUES (random() * 100, 'ORCL', 152, '2011-08-25 11:50:45', + 'sell', 0.58); + +-- commands with expressions that cannot be collapsed are unsupported +INSERT INTO limit_orders VALUES (2036, 'GOOG', 5634, now(), 'buy', random()); + +-- commands with mutable functions in their quals +DELETE FROM limit_orders WHERE id = 246 AND bidder_id = (random() * 1000); + +-- commands with mutable but non-volatilte functions(ie: stable func.) in their quals +DELETE FROM limit_orders WHERE id = 246 AND placed_at = current_timestamp; + +-- commands with multiple rows are unsupported +INSERT INTO limit_orders VALUES (DEFAULT), (DEFAULT); + +-- INSERT ... SELECT ... FROM commands are unsupported +INSERT INTO limit_orders SELECT * FROM limit_orders; + +-- commands with a RETURNING clause are unsupported +INSERT INTO limit_orders VALUES (7285, 'AMZN', 3278, '2016-01-05 02:07:36', 'sell', 0.00) + RETURNING *; + +-- commands containing a CTE are unsupported +WITH deleted_orders AS (DELETE FROM limit_orders RETURNING *) +INSERT INTO limit_orders DEFAULT VALUES; + +-- test simple DELETE +INSERT INTO limit_orders VALUES (246, 'TSLA', 162, '2007-07-02 16:32:15', 'sell', 20.69); +SELECT COUNT(*) FROM limit_orders WHERE id = 246; + +DELETE FROM limit_orders WHERE id = 246; +SELECT COUNT(*) FROM limit_orders WHERE id = 246; + +-- DELETE with expression in WHERE clause +INSERT INTO limit_orders VALUES (246, 'TSLA', 162, '2007-07-02 16:32:15', 'sell', 20.69); +SELECT COUNT(*) FROM limit_orders WHERE id = 246; + +DELETE FROM limit_orders WHERE id = (2 * 123); +SELECT COUNT(*) FROM limit_orders WHERE id = 246; + +-- commands with no constraints on the partition key are not supported +DELETE FROM limit_orders WHERE bidder_id = 162; + +-- commands with a USING clause are unsupported +CREATE TABLE bidders ( name text, id bigint ); +DELETE FROM limit_orders USING bidders WHERE limit_orders.id = 246 AND + limit_orders.bidder_id = bidders.id AND + bidders.name = 'Bernie Madoff'; + +-- commands with a RETURNING clause are unsupported +DELETE FROM limit_orders WHERE id = 246 RETURNING *; + +-- commands containing a CTE are unsupported +WITH deleted_orders AS (INSERT INTO limit_orders DEFAULT VALUES RETURNING *) +DELETE FROM limit_orders; + +-- cursors are not supported +DELETE FROM limit_orders WHERE CURRENT OF cursor_name; + +INSERT INTO limit_orders VALUES (246, 'TSLA', 162, '2007-07-02 16:32:15', 'sell', 20.69); + +-- simple UPDATE +UPDATE limit_orders SET symbol = 'GM' WHERE id = 246; +SELECT symbol FROM limit_orders WHERE id = 246; + +-- expression UPDATE +UPDATE limit_orders SET bidder_id = 6 * 3 WHERE id = 246; +SELECT bidder_id FROM limit_orders WHERE id = 246; + +-- multi-column UPDATE +UPDATE limit_orders SET (kind, limit_price) = ('buy', DEFAULT) WHERE id = 246; +SELECT kind, limit_price FROM limit_orders WHERE id = 246; + +-- Test that shards which miss a modification are marked unhealthy +\set first_worker_port 57637 +\set second_worker_port 57638 + +-- First: Mark all placements for a node as inactive +UPDATE pg_dist_shard_placement +SET shardstate = 3 +WHERE nodename = 'localhost' AND + nodeport = :first_worker_port; + +-- Second: Perform an INSERT to the remaining node +INSERT INTO limit_orders VALUES (275, 'ADR', 140, '2007-07-02 16:32:15', 'sell', 43.67); + +-- Third: Mark the original placements as healthy again +UPDATE pg_dist_shard_placement +SET shardstate = 1 +WHERE nodename = 'localhost' AND + nodeport = :first_worker_port; + +-- Fourth: Perform the same INSERT (primary key violation) +INSERT INTO limit_orders VALUES (275, 'ADR', 140, '2007-07-02 16:32:15', 'sell', 43.67); + +-- Last: Verify the insert worked but the placement with the PK violation is now unhealthy +SELECT count(*) FROM limit_orders WHERE id = 275; +SELECT count(*) +FROM pg_dist_shard_placement AS sp, + pg_dist_shard AS s +WHERE sp.shardid = s.shardid +AND sp.nodename = 'localhost' +AND sp.nodeport = :second_worker_port +AND sp.shardstate = 3 +AND s.logicalrelid = 'limit_orders'::regclass; + +-- commands with no constraints on the partition key are not supported +UPDATE limit_orders SET limit_price = 0.00; + +-- attempting to change the partition key is unsupported +UPDATE limit_orders SET id = 0 WHERE id = 246; + +-- UPDATEs with a FROM clause are unsupported +UPDATE limit_orders SET limit_price = 0.00 FROM bidders + WHERE limit_orders.id = 246 AND + limit_orders.bidder_id = bidders.id AND + bidders.name = 'Bernie Madoff'; + +-- commands with a RETURNING clause are unsupported +UPDATE limit_orders SET symbol = 'GM' WHERE id = 246 RETURNING *; + +-- commands containing a CTE are unsupported +WITH deleted_orders AS (INSERT INTO limit_orders DEFAULT VALUES RETURNING *) +UPDATE limit_orders SET symbol = 'GM'; + +-- cursors are not supported +UPDATE limit_orders SET symbol = 'GM' WHERE CURRENT OF cursor_name; diff --git a/src/test/regress/sql/multi_null_minmax_value_pruning.sql b/src/test/regress/sql/multi_null_minmax_value_pruning.sql new file mode 100644 index 000000000..91828359d --- /dev/null +++ b/src/test/regress/sql/multi_null_minmax_value_pruning.sql @@ -0,0 +1,59 @@ +-- +-- MULTI_NULL_MINMAX_VALUE_PRUNING +-- + +-- This test checks that we can handle null min/max values in shard statistics +-- and that we don't partition or join prune shards that have null values. + +SET client_min_messages TO DEBUG2; + +-- Change configuration to treat lineitem and orders tables as large + +SET citusdb.large_table_shard_count TO 2; + +SELECT shardminvalue, shardmaxvalue from pg_dist_shard WHERE shardid = 102009; +SELECT shardminvalue, shardmaxvalue from pg_dist_shard WHERE shardid = 102010; + +-- Check that partition and join pruning works when min/max values exist + +SELECT l_orderkey, l_linenumber, l_shipdate FROM lineitem WHERE l_orderkey = 9030; + +SELECT sum(l_linenumber), avg(l_linenumber) FROM lineitem, orders + WHERE l_orderkey = o_orderkey; + +-- Now set the minimum value for a shard to null. Then check that we don't apply +-- partition or join pruning for the shard with null min value. + +UPDATE pg_dist_shard SET shardminvalue = NULL WHERE shardid = 102009; + +SELECT l_orderkey, l_linenumber, l_shipdate FROM lineitem WHERE l_orderkey = 9030; + +SELECT sum(l_linenumber), avg(l_linenumber) FROM lineitem, orders + WHERE l_orderkey = o_orderkey; + +-- Next, set the maximum value for another shard to null. Then check that we +-- don't apply partition or join pruning for this other shard either. + +UPDATE pg_dist_shard SET shardmaxvalue = NULL WHERE shardid = 102010; + +SELECT l_orderkey, l_linenumber, l_shipdate FROM lineitem WHERE l_orderkey = 9030; + +SELECT sum(l_linenumber), avg(l_linenumber) FROM lineitem, orders + WHERE l_orderkey = o_orderkey; + +-- Last, set the minimum value to 0 and check that we don't treat it as null. We +-- should apply partition and join pruning for this shard now. + +UPDATE pg_dist_shard SET shardminvalue = '0' WHERE shardid = 102009; + +SELECT l_orderkey, l_linenumber, l_shipdate FROM lineitem WHERE l_orderkey = 9030; + +SELECT sum(l_linenumber), avg(l_linenumber) FROM lineitem, orders + WHERE l_orderkey = o_orderkey; + +-- Set minimum and maximum values for two shards back to their original values + +UPDATE pg_dist_shard SET shardminvalue = '1' WHERE shardid = 102009; +UPDATE pg_dist_shard SET shardmaxvalue = '4964' WHERE shardid = 102010; + +SET client_min_messages TO NOTICE; diff --git a/src/test/regress/sql/multi_partition_pruning.sql b/src/test/regress/sql/multi_partition_pruning.sql new file mode 100644 index 000000000..d3c407bf9 --- /dev/null +++ b/src/test/regress/sql/multi_partition_pruning.sql @@ -0,0 +1,139 @@ +-- +-- MULTI_PARTITION_PRUNING +-- + +-- Tests to verify that we correctly prune unreferenced shards. For this, we +-- need to increase the logging verbosity of messages displayed on the client. + +SET client_min_messages TO DEBUG2; + +SELECT l_orderkey, l_linenumber, l_shipdate FROM lineitem WHERE l_orderkey = 9030; + +-- We use the l_linenumber field for the following aggregations. We need to use +-- an integer type, as aggregations on numerics or big integers return numerics +-- of unknown length. When the numerics are read into our temporary table, they +-- trigger the the creation of toasted tables and indexes. This in turn prints +-- non-deterministic debug messages. To avoid this chain, we use l_linenumber. + +SELECT sum(l_linenumber), avg(l_linenumber) FROM lineitem WHERE l_orderkey > 9030; + +SELECT sum(l_linenumber), avg(l_linenumber) FROM lineitem + WHERE (l_orderkey < 4000 OR l_orderkey > 9030); + +-- The following query should prune out all shards and return empty results + +SELECT sum(l_linenumber), avg(l_linenumber) FROM lineitem WHERE l_orderkey > 20000; + +-- The tests below verify that we can prune shards partitioned over different +-- types of columns including varchar, array types, composite types etc. This is +-- in response to a bug we had where we were not able to resolve correct operator +-- types for some kind of column types. First we create tables partitioned on +-- these types and the logical shards and placements for them. + +-- Create varchar partitioned table + +CREATE TABLE varchar_partitioned_table +( + varchar_column varchar(100) +); +SELECT master_create_distributed_table('varchar_partitioned_table', 'varchar_column', 'append'); + +-- Create logical shards and shard placements with shardid 100,101 + +INSERT INTO pg_dist_shard (logicalrelid, shardid, shardstorage, shardminvalue, shardmaxvalue) + VALUES('varchar_partitioned_table'::regclass, 100, 't', 'AA1000U2AMO4ZGX', 'AZZXSP27F21T6'), + ('varchar_partitioned_table'::regclass, 101, 't', 'BA1000U2AMO4ZGX', 'BZZXSP27F21T6'); + +INSERT INTO pg_dist_shard_placement (shardid, shardstate, shardlength, nodename, nodeport) + SELECT 100, 1, 1, nodename, nodeport + FROM pg_dist_shard_placement + GROUP BY nodename, nodeport + ORDER BY nodename, nodeport ASC + LIMIT 1; + +INSERT INTO pg_dist_shard_placement (shardid, shardstate, shardlength, nodename, nodeport) + SELECT 101, 1, 1, nodename, nodeport + FROM pg_dist_shard_placement + GROUP BY nodename, nodeport + ORDER BY nodename, nodeport ASC + LIMIT 1; + +-- Create array partitioned table + +RESET client_min_messages; -- avoid debug messages about toast index creation +CREATE TABLE array_partitioned_table +( + array_column text[] +); +SELECT master_create_distributed_table('array_partitioned_table', 'array_column', 'append'); +SET client_min_messages TO DEBUG2; + +-- Create logical shard with shardid 102, 103 + +INSERT INTO pg_dist_shard (logicalrelid, shardid, shardstorage, shardminvalue, shardmaxvalue) + VALUES('array_partitioned_table'::regclass, 102, 't', '{}', '{AZZXSP27F21T6, AZZXSP27F21T6}'), + ('array_partitioned_table'::regclass, 103, 't', '{BA1000U2AMO4ZGX, BZZXSP27F21T6}', + '{CA1000U2AMO4ZGX, CZZXSP27F21T6}'); + +INSERT INTO pg_dist_shard_placement (shardid, shardstate, shardlength, nodename, nodeport) + SELECT 102, 1, 1, nodename, nodeport + FROM pg_dist_shard_placement + GROUP BY nodename, nodeport + ORDER BY nodename, nodeport ASC + LIMIT 1; + +INSERT INTO pg_dist_shard_placement (shardid, shardstate, shardlength, nodename, nodeport) + SELECT 103, 1, 1, nodename, nodeport + FROM pg_dist_shard_placement + GROUP BY nodename, nodeport + ORDER BY nodename, nodeport ASC + LIMIT 1; + +-- Create composite type partitioned table + +CREATE TYPE composite_type AS +( + text_column text, + double_column decimal, + varchar_column varchar(50) +); + +RESET client_min_messages; -- avoid debug messages about toast index creation +CREATE TABLE composite_partitioned_table +( + composite_column composite_type +); +SELECT master_create_distributed_table('composite_partitioned_table', 'composite_column', 'append'); +SET client_min_messages TO DEBUG2; + +-- Create logical shard with shardid 104, 105 +INSERT INTO pg_dist_shard (logicalrelid, shardid, shardstorage, shardminvalue, shardmaxvalue) + VALUES('composite_partitioned_table'::regclass, 104, 't', '(a,3,b)', '(b,4,c)'), + ('composite_partitioned_table'::regclass, 105, 't', '(c,5,d)', '(d,6,e)'); + +INSERT INTO pg_dist_shard_placement (shardid, shardstate, shardlength, nodename, nodeport) + SELECT 104, 1, 1, nodename, nodeport + FROM pg_dist_shard_placement + GROUP BY nodename, nodeport + ORDER BY nodename, nodeport ASC + LIMIT 1; + +INSERT INTO pg_dist_shard_placement (shardid, shardstate, shardlength, nodename, nodeport) + SELECT 105, 1, 1, nodename, nodeport + FROM pg_dist_shard_placement + GROUP BY nodename, nodeport + ORDER BY nodename, nodeport ASC + LIMIT 1; + +-- Verify that shard pruning works. Note that these queries should all prune +-- one shard. + +EXPLAIN SELECT count(*) FROM varchar_partitioned_table WHERE varchar_column = 'BA2'; + +EXPLAIN SELECT count(*) FROM array_partitioned_table + WHERE array_column > '{BA1000U2AMO4ZGX, BZZXSP27F21T6}'; + +EXPLAIN SELECT count(*) FROM composite_partitioned_table + WHERE composite_column < '(b,5,c)'::composite_type; + +SET client_min_messages TO NOTICE; diff --git a/src/test/regress/sql/multi_prepare_plsql.sql b/src/test/regress/sql/multi_prepare_plsql.sql new file mode 100644 index 000000000..2a91d5483 --- /dev/null +++ b/src/test/regress/sql/multi_prepare_plsql.sql @@ -0,0 +1,257 @@ +-- +-- MULTI_PREPARE_PLSQL +-- + +-- Many of the queries are taken from other regression test files +-- and converted into both plain SQL and PL/pgsql functions, which +-- use prepared statements internally. + +CREATE FUNCTION sql_test_no_1() RETURNS bigint AS ' + SELECT + count(*) + FROM + orders; +' LANGUAGE SQL; + +CREATE FUNCTION sql_test_no_2() RETURNS bigint AS ' + SELECT + count(*) + FROM + orders, lineitem + WHERE + o_orderkey = l_orderkey; +' LANGUAGE SQL; + +CREATE FUNCTION sql_test_no_3() RETURNS bigint AS ' + SELECT + count(*) + FROM + orders, customer + WHERE + o_custkey = c_custkey; +' LANGUAGE SQL; + +CREATE FUNCTION sql_test_no_4() RETURNS bigint AS ' + SELECT + count(*) + FROM + orders, customer, lineitem + WHERE + o_custkey = c_custkey AND + o_orderkey = l_orderkey; +' LANGUAGE SQL; + +CREATE OR REPLACE FUNCTION sql_test_no_6(integer) RETURNS bigint AS $$ + SELECT + count(*) + FROM + orders, lineitem + WHERE + o_orderkey = l_orderkey AND + l_suppkey > $1; +$$ LANGUAGE SQL RETURNS NULL ON NULL INPUT; + +CREATE OR REPLACE FUNCTION plpgsql_test_1() RETURNS TABLE(count bigint) AS $$ +DECLARE +BEGIN + RETURN QUERY + SELECT + count(*) + FROM + orders; + +END; +$$ LANGUAGE plpgsql; + +CREATE OR REPLACE FUNCTION plpgsql_test_2() RETURNS TABLE(count bigint) AS $$ +DECLARE +BEGIN + RETURN QUERY + SELECT + count(*) + FROM + orders, lineitem + WHERE + o_orderkey = l_orderkey; + +END; +$$ LANGUAGE plpgsql; + +CREATE OR REPLACE FUNCTION plpgsql_test_3() RETURNS TABLE(count bigint) AS $$ +DECLARE +BEGIN + RETURN QUERY + SELECT + count(*) + FROM + orders, customer + WHERE + o_custkey = c_custkey; + +END; +$$ LANGUAGE plpgsql; + +CREATE OR REPLACE FUNCTION plpgsql_test_4() RETURNS TABLE(count bigint) AS $$ +DECLARE +BEGIN + RETURN QUERY + SELECT + count(*) + FROM + orders, customer, lineitem + WHERE + o_custkey = c_custkey AND + o_orderkey = l_orderkey; +END; +$$ LANGUAGE plpgsql; + +CREATE OR REPLACE FUNCTION plpgsql_test_5() RETURNS TABLE(count bigint) AS $$ +DECLARE +BEGIN + RETURN QUERY + SELECT + count(*) + FROM + lineitem, customer + WHERE + l_partkey = c_nationkey; +END; +$$ LANGUAGE plpgsql; + +CREATE OR REPLACE FUNCTION plpgsql_test_6(int) RETURNS TABLE(count bigint) AS $$ +DECLARE +BEGIN + RETURN QUERY + SELECT + count(*) + FROM + orders, lineitem + WHERE + o_orderkey = l_orderkey AND + l_suppkey > $1; +END; +$$ LANGUAGE plpgsql; + +CREATE OR REPLACE FUNCTION plpgsql_test_7(text, text) RETURNS TABLE(supp_natadsion text, cusasdt_nation text, l_yeasdar int, sasdaum double precision) AS $$ +DECLARE +BEGIN + RETURN QUERY + SELECT + supp_nation::text, + cust_nation::text, + l_year::int, + sum(volume)::double precision AS revenue + FROM + ( + SELECT + supp_nation, + cust_nation, + extract(year FROM l_shipdate) AS l_year, + l_extendedprice * (1 - l_discount) AS volume + FROM + supplier, + lineitem, + orders, + customer, + ( + SELECT + n1.n_nationkey AS supp_nation_key, + n2.n_nationkey AS cust_nation_key, + n1.n_name AS supp_nation, + n2.n_name AS cust_nation + FROM + nation n1, + nation n2 + WHERE + ( + (n1.n_name = $1 AND n2.n_name = $2) + OR (n1.n_name = $2 AND n2.n_name = $1) + ) + ) AS temp + WHERE + s_suppkey = l_suppkey + AND o_orderkey = l_orderkey + AND c_custkey = o_custkey + AND s_nationkey = supp_nation_key + AND c_nationkey = cust_nation_key + AND l_shipdate between date '1995-01-01' AND date '1996-12-31' + ) AS shipping + GROUP BY + supp_nation, + cust_nation, + l_year + ORDER BY + supp_nation, + cust_nation, + l_year; +END; +$$ LANGUAGE plpgsql; + +SET citusdb.task_executor_type TO 'task-tracker'; +SET client_min_messages TO INFO; + +-- now, run plain SQL functions +SELECT sql_test_no_1(); +SELECT sql_test_no_2(); +SELECT sql_test_no_3(); +SELECT sql_test_no_4(); + +-- now, run PL/pgsql functions +SELECT plpgsql_test_1(); +SELECT plpgsql_test_2(); +SELECT plpgsql_test_3(); +SELECT plpgsql_test_4(); +SELECT plpgsql_test_5(); + +-- run PL/pgsql functions with different parameters +SELECT plpgsql_test_6(155); +SELECT plpgsql_test_6(1555); +SELECT plpgsql_test_7('UNITED KINGDOM', 'CHINA'); +SELECT plpgsql_test_7('FRANCE', 'GERMANY'); + +-- now, PL/pgsql functions with random order +SELECT plpgsql_test_6(155); +SELECT plpgsql_test_3(); +SELECT plpgsql_test_7('FRANCE', 'GERMANY'); +SELECT plpgsql_test_5(); +SELECT plpgsql_test_1(); +SELECT plpgsql_test_6(1555); +SELECT plpgsql_test_4(); +SELECT plpgsql_test_7('UNITED KINGDOM', 'CHINA'); +SELECT plpgsql_test_2(); + +-- run the tests which do not require re-partition +-- with real-time executor +SET citusdb.task_executor_type TO 'real-time'; + +-- now, run plain SQL functions +SELECT sql_test_no_1(); +SELECT sql_test_no_2(); + +-- plain SQL functions with parameters cannot be executed +-- FIXME: temporarily disabled, bad error message - waiting for proper parametrized query +-- FIXME: support +-- SELECT sql_test_no_6(155); + +-- now, run PL/pgsql functions +SELECT plpgsql_test_1(); +SELECT plpgsql_test_2(); + +-- run PL/pgsql functions with different parameters +-- FIXME: temporarily disabled, waiting for proper parametrized query support +-- SELECT plpgsql_test_6(155); +-- SELECT plpgsql_test_6(1555); + +-- clean-up functions +DROP FUNCTION sql_test_no_1(); +DROP FUNCTION sql_test_no_2(); +DROP FUNCTION sql_test_no_3(); +DROP FUNCTION sql_test_no_4(); +DROP FUNCTION sql_test_no_6(int); +DROP FUNCTION plpgsql_test_1(); +DROP FUNCTION plpgsql_test_2(); +DROP FUNCTION plpgsql_test_3(); +DROP FUNCTION plpgsql_test_4(); +DROP FUNCTION plpgsql_test_5(); +DROP FUNCTION plpgsql_test_6(int); +DROP FUNCTION plpgsql_test_7(text, text); diff --git a/src/test/regress/sql/multi_prepare_sql.sql b/src/test/regress/sql/multi_prepare_sql.sql new file mode 100644 index 000000000..64a1c0b10 --- /dev/null +++ b/src/test/regress/sql/multi_prepare_sql.sql @@ -0,0 +1,151 @@ +-- +-- MULTI_PREPARE_SQL +-- + +-- Tests covering PREPARE statements. Many of the queries are +-- taken from other regression test files and converted into +-- prepared statements. + +PREPARE prepared_test_1 AS +SELECT + count(*) +FROM + orders; + +PREPARE prepared_test_2 AS +SELECT + count(*) +FROM + orders, lineitem +WHERE + o_orderkey = l_orderkey; + +PREPARE prepared_test_3 AS +SELECT + count(*) +FROM + orders, customer +WHERE + o_custkey = c_custkey; + +PREPARE prepared_test_4 AS +SELECT + count(*) +FROM + orders, customer, lineitem +WHERE + o_custkey = c_custkey AND + o_orderkey = l_orderkey; + +PREPARE prepared_test_5 AS +SELECT + count(*) +FROM + lineitem, customer +WHERE + l_partkey = c_nationkey; + +PREPARE prepared_test_6(int) AS +SELECT + count(*) +FROM + orders, lineitem +WHERE + o_orderkey = l_orderkey AND + l_suppkey > $1; + +PREPARE prepared_test_7(text, text) AS +SELECT + supp_nation, + cust_nation, + l_year, + sum(volume) AS revenue +FROM + ( + SELECT + supp_nation, + cust_nation, + extract(year FROM l_shipdate) AS l_year, + l_extendedprice * (1 - l_discount) AS volume + FROM + supplier, + lineitem, + orders, + customer, + ( + SELECT + n1.n_nationkey AS supp_nation_key, + n2.n_nationkey AS cust_nation_key, + n1.n_name AS supp_nation, + n2.n_name AS cust_nation + FROM + nation n1, + nation n2 + WHERE + ( + (n1.n_name = $1 AND n2.n_name = $2) + OR (n1.n_name = $2 AND n2.n_name = $1) + ) + ) AS temp + WHERE + s_suppkey = l_suppkey + AND o_orderkey = l_orderkey + AND c_custkey = o_custkey + AND s_nationkey = supp_nation_key + AND c_nationkey = cust_nation_key + AND l_shipdate between date '1995-01-01' AND date '1996-12-31' + ) AS shipping +GROUP BY + supp_nation, + cust_nation, + l_year +ORDER BY + supp_nation, + cust_nation, + l_year; + +SET citusdb.task_executor_type TO 'task-tracker'; +SET client_min_messages TO INFO; + +-- execute prepared statements +EXECUTE prepared_test_1; +EXECUTE prepared_test_2; +EXECUTE prepared_test_3; +EXECUTE prepared_test_4; +EXECUTE prepared_test_5; + +-- execute prepared statements with different parameters +EXECUTE prepared_test_6(155); +EXECUTE prepared_test_6(1555); +EXECUTE prepared_test_7('UNITED KINGDOM', 'CHINA'); +EXECUTE prepared_test_7('FRANCE', 'GERMANY'); + +-- now, execute prepared statements with random order +EXECUTE prepared_test_6(155); +EXECUTE prepared_test_3; +EXECUTE prepared_test_7('FRANCE', 'GERMANY'); +EXECUTE prepared_test_5; +EXECUTE prepared_test_1; +EXECUTE prepared_test_6(1555); +EXECUTE prepared_test_4; +EXECUTE prepared_test_7('UNITED KINGDOM', 'CHINA'); +EXECUTE prepared_test_2; + +-- CREATE TABLE ... AS EXECUTE prepared_statement tests +CREATE TEMP TABLE prepared_sql_test_7 AS EXECUTE prepared_test_7('UNITED KINGDOM', 'CHINA'); +SELECT * from prepared_sql_test_7; + +-- now, run some of the tests with real-time executor +SET citusdb.task_executor_type TO 'real-time'; + +-- execute prepared statements +EXECUTE prepared_test_1; +EXECUTE prepared_test_2; + +-- execute prepared statements with different parameters +EXECUTE prepared_test_6(155); +-- FIXME: temporarily disabled +-- EXECUTE prepared_test_6(1555); + +-- clean-up prepared statements +DEALLOCATE ALL; diff --git a/src/test/regress/sql/multi_prune_shard_list.sql b/src/test/regress/sql/multi_prune_shard_list.sql new file mode 100644 index 000000000..f684bfa83 --- /dev/null +++ b/src/test/regress/sql/multi_prune_shard_list.sql @@ -0,0 +1,68 @@ +-- =================================================================== +-- create test functions +-- =================================================================== + +CREATE FUNCTION prune_using_no_values(regclass) + RETURNS text[] + AS 'citusdb' + LANGUAGE C STRICT; + +CREATE FUNCTION prune_using_single_value(regclass, text) + RETURNS text[] + AS 'citusdb' + LANGUAGE C; + +CREATE FUNCTION prune_using_either_value(regclass, text, text) + RETURNS text[] + AS 'citusdb' + LANGUAGE C STRICT; + +CREATE FUNCTION prune_using_both_values(regclass, text, text) + RETURNS text[] + AS 'citusdb' + LANGUAGE C STRICT; + +CREATE FUNCTION debug_equality_expression(regclass) + RETURNS cstring + AS 'citusdb' + LANGUAGE C STRICT; + +-- =================================================================== +-- test shard pruning functionality +-- =================================================================== + +-- create distributed table metadata to observe shard pruning +CREATE TABLE pruning ( species text, last_pruned date, plant_id integer ); + +INSERT INTO pg_dist_partition (logicalrelid, partmethod, partkey) +VALUES + ('pruning'::regclass, 'h', column_name_to_column('pruning'::regclass, 'species')); + +INSERT INTO pg_dist_shard + (shardid, logicalrelid, shardstorage, shardminvalue, shardmaxvalue) +VALUES + (10, 'pruning'::regclass, 't', '-2147483648', '-1073741826'), + (11, 'pruning'::regclass, 't', '-1073741825', '-3'), + (12, 'pruning'::regclass, 't', '-2', '1073741820'), + (13, 'pruning'::regclass, 't', '1073741821', '2147483647'); + +-- with no values, expect all shards +SELECT prune_using_no_values('pruning'); + +-- with a single value, expect a single shard +SELECT prune_using_single_value('pruning', 'tomato'); + +-- the above is true even if that value is null +SELECT prune_using_single_value('pruning', NULL); + +-- build an OR clause and expect more than one sahrd +SELECT prune_using_either_value('pruning', 'tomato', 'petunia'); + +-- an AND clause with incompatible values returns no shards +SELECT prune_using_both_values('pruning', 'tomato', 'petunia'); + +-- but if both values are on the same shard, should get back that shard +SELECT prune_using_both_values('pruning', 'tomato', 'rose'); + +-- unit test of the equality expression generation code +SELECT debug_equality_expression('pruning'); diff --git a/src/test/regress/sql/multi_query_directory_cleanup.sql b/src/test/regress/sql/multi_query_directory_cleanup.sql new file mode 100644 index 000000000..0f83e4802 --- /dev/null +++ b/src/test/regress/sql/multi_query_directory_cleanup.sql @@ -0,0 +1,70 @@ +-- +-- MULTI_QUERY_DIRECTORY_CLEANUP +-- + +-- We execute sub-queries on worker nodes, and copy query results to a directory +-- on the master node for final processing. When the query completes or fails, +-- the resource owner should automatically clean up these intermediate query +-- result files. + +BEGIN; + +-- pg_ls_dir() displays jobids. We explicitly set the jobId sequence +-- here so that the regression output becomes independent of the +-- number of jobs executed prior to running this test. +ALTER SEQUENCE pg_catalog.pg_dist_jobid_seq RESTART 1250; + +SELECT sum(l_extendedprice * l_discount) as revenue FROM lineitem; +SELECT sum(l_extendedprice * l_discount) as revenue FROM lineitem; +SELECT sum(l_extendedprice * l_discount) as revenue FROM lineitem; + +SELECT pg_ls_dir('base/pgsql_job_cache'); + +COMMIT; + +SELECT pg_ls_dir('base/pgsql_job_cache'); + +BEGIN; + +SELECT sum(l_extendedprice * l_discount) as revenue FROM lineitem; +SELECT sum(l_extendedprice * l_discount) as revenue FROM lineitem; +SELECT sum(l_extendedprice * l_discount) as revenue FROM lineitem; + +SELECT pg_ls_dir('base/pgsql_job_cache'); + +ROLLBACK; + +SELECT pg_ls_dir('base/pgsql_job_cache'); + +-- Test that multiple job directories are all cleaned up correctly, +-- both individually (by closing a cursor) and in bulk when ending a +-- transaction. +BEGIN; +DECLARE c_00 CURSOR FOR SELECT sum(l_extendedprice * l_discount) as revenue FROM lineitem; +DECLARE c_01 CURSOR FOR SELECT sum(l_extendedprice * l_discount) as revenue FROM lineitem; +DECLARE c_02 CURSOR FOR SELECT sum(l_extendedprice * l_discount) as revenue FROM lineitem; +DECLARE c_03 CURSOR FOR SELECT sum(l_extendedprice * l_discount) as revenue FROM lineitem; +DECLARE c_04 CURSOR FOR SELECT sum(l_extendedprice * l_discount) as revenue FROM lineitem; +DECLARE c_05 CURSOR FOR SELECT sum(l_extendedprice * l_discount) as revenue FROM lineitem; +DECLARE c_06 CURSOR FOR SELECT sum(l_extendedprice * l_discount) as revenue FROM lineitem; +DECLARE c_07 CURSOR FOR SELECT sum(l_extendedprice * l_discount) as revenue FROM lineitem; +DECLARE c_08 CURSOR FOR SELECT sum(l_extendedprice * l_discount) as revenue FROM lineitem; +DECLARE c_09 CURSOR FOR SELECT sum(l_extendedprice * l_discount) as revenue FROM lineitem; +DECLARE c_10 CURSOR FOR SELECT sum(l_extendedprice * l_discount) as revenue FROM lineitem; +DECLARE c_11 CURSOR FOR SELECT sum(l_extendedprice * l_discount) as revenue FROM lineitem; +DECLARE c_12 CURSOR FOR SELECT sum(l_extendedprice * l_discount) as revenue FROM lineitem; +DECLARE c_13 CURSOR FOR SELECT sum(l_extendedprice * l_discount) as revenue FROM lineitem; +DECLARE c_14 CURSOR FOR SELECT sum(l_extendedprice * l_discount) as revenue FROM lineitem; +DECLARE c_15 CURSOR FOR SELECT sum(l_extendedprice * l_discount) as revenue FROM lineitem; +DECLARE c_16 CURSOR FOR SELECT sum(l_extendedprice * l_discount) as revenue FROM lineitem; +DECLARE c_17 CURSOR FOR SELECT sum(l_extendedprice * l_discount) as revenue FROM lineitem; +DECLARE c_18 CURSOR FOR SELECT sum(l_extendedprice * l_discount) as revenue FROM lineitem; +DECLARE c_19 CURSOR FOR SELECT sum(l_extendedprice * l_discount) as revenue FROM lineitem; +SELECT * FROM pg_ls_dir('base/pgsql_job_cache') f ORDER BY f; +-- close first, 17th (first after re-alloc) and last cursor. +CLOSE c_00; +CLOSE c_16; +CLOSE c_19; +SELECT * FROM pg_ls_dir('base/pgsql_job_cache') f ORDER BY f; +ROLLBACK; +SELECT pg_ls_dir('base/pgsql_job_cache'); diff --git a/src/test/regress/sql/multi_repair_shards.sql b/src/test/regress/sql/multi_repair_shards.sql new file mode 100644 index 000000000..15fd58e13 --- /dev/null +++ b/src/test/regress/sql/multi_repair_shards.sql @@ -0,0 +1,80 @@ +-- =================================================================== +-- test shard repair functionality +-- =================================================================== + +-- create a table and create its distribution metadata +CREATE TABLE customer_engagements ( id integer, created_at date, event_data text ); + +-- add some indexes +CREATE INDEX ON customer_engagements (id); +CREATE INDEX ON customer_engagements (created_at); +CREATE INDEX ON customer_engagements (event_data); + +\set first_worker_port 57637 +\set second_worker_port 57638 + +-- distribute the table +SELECT master_create_distributed_table('customer_engagements', 'id', 'hash'); + +-- create a single shard on the first worker +SELECT master_create_worker_shards('customer_engagements', 1, 2); + +-- ingest some data for the tests +INSERT INTO customer_engagements VALUES (1, '01-01-2015', 'first event'); +INSERT INTO customer_engagements VALUES (2, '02-01-2015', 'second event'); +INSERT INTO customer_engagements VALUES (1, '03-01-2015', 'third event'); + +-- the following queries does the following: +-- (i) create a new shard +-- (ii) mark the second shard placements as unhealthy +-- (iii) do basic checks i.e., only allow copy from healthy placement to unhealthy ones +-- (iv) do a successful master_copy_shard_placement from the first placement to the second +-- (v) mark the first placement as unhealthy and execute a query that is routed to the second placement + +-- get the newshardid +SELECT shardid as newshardid FROM pg_dist_shard WHERE logicalrelid = 'customer_engagements'::regclass +\gset + +-- now, update the second placement as unhealthy +UPDATE pg_dist_shard_placement SET shardstate = 3 WHERE shardid = :newshardid AND nodeport = :second_worker_port; + +-- add a fake healthy placement for the tests +INSERT INTO pg_dist_shard_placement (nodename, nodeport, shardid, shardstate, shardlength) + VALUES ('dummyhost', :second_worker_port, :newshardid, 1, 0); + +SELECT master_copy_shard_placement(:newshardid, 'localhost', :first_worker_port, 'dummyhost', :second_worker_port); + +-- also try to copy from an inactive placement +SELECT master_copy_shard_placement(:newshardid, 'localhost', :second_worker_port, 'localhost', :first_worker_port); + +-- "copy" this shard from the first placement to the second one +SELECT master_copy_shard_placement(:newshardid, 'localhost', :first_worker_port, 'localhost', :second_worker_port); + +-- now, update first placement as unhealthy (and raise a notice) so that queries are not routed to there +UPDATE pg_dist_shard_placement SET shardstate = 3 WHERE shardid = :newshardid AND nodeport = :first_worker_port; + +-- get the data from the second placement +SELECT * FROM customer_engagements; + +-- now do the same test over again with a foreign table +CREATE FOREIGN TABLE remote_engagements ( + id integer, + created_at date, + event_data text +) SERVER fake_fdw_server; + +-- distribute the table +SELECT master_create_distributed_table('remote_engagements', 'id', 'hash'); + +-- create a single shard on the first worker +SELECT master_create_worker_shards('remote_engagements', 1, 2); + +-- get the newshardid +SELECT shardid as remotenewshardid FROM pg_dist_shard WHERE logicalrelid = 'remote_engagements'::regclass +\gset + +-- now, update the second placement as unhealthy +UPDATE pg_dist_shard_placement SET shardstate = 3 WHERE shardid = :remotenewshardid AND nodeport = :second_worker_port; + +-- oops! we don't support repairing shards backed by foreign tables +SELECT master_copy_shard_placement(:remotenewshardid, 'localhost', :first_worker_port, 'localhost', :second_worker_port); diff --git a/src/test/regress/sql/multi_simple_queries.sql b/src/test/regress/sql/multi_simple_queries.sql new file mode 100644 index 000000000..1e774ebb6 --- /dev/null +++ b/src/test/regress/sql/multi_simple_queries.sql @@ -0,0 +1,280 @@ +-- =================================================================== +-- test end-to-end query functionality +-- =================================================================== + +CREATE TABLE articles ( + id bigint NOT NULL, + author_id bigint NOT NULL, + title text NOT NULL, + word_count integer NOT NULL CHECK (word_count > 0) +); + +-- this table is used in a CTE test +CREATE TABLE authors ( name text, id bigint ); + +-- this table is used in router executor tests +CREATE TABLE articles_single_shard (LIKE articles); + +SELECT master_create_distributed_table('articles', 'author_id', 'hash'); +SELECT master_create_distributed_table('articles_single_shard', 'author_id', 'hash'); + + +-- test when a table is distributed but no shards created yet +SELECT count(*) from articles; + +SELECT master_create_worker_shards('articles', 2, 1); +SELECT master_create_worker_shards('articles_single_shard', 1, 1); + +-- create a bunch of test data +INSERT INTO articles VALUES ( 1, 1, 'arsenous', 9572); +INSERT INTO articles VALUES ( 2, 2, 'abducing', 13642); +INSERT INTO articles VALUES ( 3, 3, 'asternal', 10480); +INSERT INTO articles VALUES ( 4, 4, 'altdorfer', 14551); +INSERT INTO articles VALUES ( 5, 5, 'aruru', 11389); +INSERT INTO articles VALUES ( 6, 6, 'atlases', 15459); +INSERT INTO articles VALUES ( 7, 7, 'aseptic', 12298); +INSERT INTO articles VALUES ( 8, 8, 'agatized', 16368); +INSERT INTO articles VALUES ( 9, 9, 'alligate', 438); +INSERT INTO articles VALUES (10, 10, 'aggrandize', 17277); +INSERT INTO articles VALUES (11, 1, 'alamo', 1347); +INSERT INTO articles VALUES (12, 2, 'archiblast', 18185); +INSERT INTO articles VALUES (13, 3, 'aseyev', 2255); +INSERT INTO articles VALUES (14, 4, 'andesite', 19094); +INSERT INTO articles VALUES (15, 5, 'adversa', 3164); +INSERT INTO articles VALUES (16, 6, 'allonym', 2); +INSERT INTO articles VALUES (17, 7, 'auriga', 4073); +INSERT INTO articles VALUES (18, 8, 'assembly', 911); +INSERT INTO articles VALUES (19, 9, 'aubergiste', 4981); +INSERT INTO articles VALUES (20, 10, 'absentness', 1820); +INSERT INTO articles VALUES (21, 1, 'arcading', 5890); +INSERT INTO articles VALUES (22, 2, 'antipope', 2728); +INSERT INTO articles VALUES (23, 3, 'abhorring', 6799); +INSERT INTO articles VALUES (24, 4, 'audacious', 3637); +INSERT INTO articles VALUES (25, 5, 'antehall', 7707); +INSERT INTO articles VALUES (26, 6, 'abington', 4545); +INSERT INTO articles VALUES (27, 7, 'arsenous', 8616); +INSERT INTO articles VALUES (28, 8, 'aerophyte', 5454); +INSERT INTO articles VALUES (29, 9, 'amateur', 9524); +INSERT INTO articles VALUES (30, 10, 'andelee', 6363); +INSERT INTO articles VALUES (31, 1, 'athwartships', 7271); +INSERT INTO articles VALUES (32, 2, 'amazon', 11342); +INSERT INTO articles VALUES (33, 3, 'autochrome', 8180); +INSERT INTO articles VALUES (34, 4, 'amnestied', 12250); +INSERT INTO articles VALUES (35, 5, 'aminate', 9089); +INSERT INTO articles VALUES (36, 6, 'ablation', 13159); +INSERT INTO articles VALUES (37, 7, 'archduchies', 9997); +INSERT INTO articles VALUES (38, 8, 'anatine', 14067); +INSERT INTO articles VALUES (39, 9, 'anchises', 10906); +INSERT INTO articles VALUES (40, 10, 'attemper', 14976); +INSERT INTO articles VALUES (41, 1, 'aznavour', 11814); +INSERT INTO articles VALUES (42, 2, 'ausable', 15885); +INSERT INTO articles VALUES (43, 3, 'affixal', 12723); +INSERT INTO articles VALUES (44, 4, 'anteport', 16793); +INSERT INTO articles VALUES (45, 5, 'afrasia', 864); +INSERT INTO articles VALUES (46, 6, 'atlanta', 17702); +INSERT INTO articles VALUES (47, 7, 'abeyance', 1772); +INSERT INTO articles VALUES (48, 8, 'alkylic', 18610); +INSERT INTO articles VALUES (49, 9, 'anyone', 2681); +INSERT INTO articles VALUES (50, 10, 'anjanette', 19519); + +-- insert a single row for the test +INSERT INTO articles_single_shard VALUES (50, 10, 'anjanette', 19519); + +-- first, test zero-shard SELECT, which should return an empty row +SELECT COUNT(*) FROM articles WHERE author_id = 1 AND author_id = 2; + +-- zero-shard modifications should fail +UPDATE articles SET title = '' WHERE author_id = 1 AND author_id = 2; +DELETE FROM articles WHERE author_id = 1 AND author_id = 2; + +-- single-shard tests + +-- test simple select for a single row +SELECT * FROM articles WHERE author_id = 10 AND id = 50; + +-- get all titles by a single author +SELECT title FROM articles WHERE author_id = 10; + +-- try ordering them by word count +SELECT title, word_count FROM articles + WHERE author_id = 10 + ORDER BY word_count DESC NULLS LAST; + +-- look at last two articles by an author +SELECT title, id FROM articles + WHERE author_id = 5 + ORDER BY id + LIMIT 2; + +-- find all articles by two authors in same shard +SELECT title, author_id FROM articles + WHERE author_id = 7 OR author_id = 8 + ORDER BY author_id ASC, id; + +-- add in some grouping expressions, still on same shard +-- having queries unsupported in CitusDB +SELECT author_id, sum(word_count) AS corpus_size FROM articles + WHERE author_id = 1 OR author_id = 7 OR author_id = 8 OR author_id = 10 + GROUP BY author_id + HAVING sum(word_count) > 40000 + ORDER BY sum(word_count) DESC; + +-- UNION/INTERSECT queries are unsupported +SELECT * FROM articles WHERE author_id = 10 UNION +SELECT * FROM articles WHERE author_id = 1; + +-- queries using CTEs are unsupported +WITH long_names AS ( SELECT id FROM authors WHERE char_length(name) > 15 ) +SELECT title FROM articles; + +-- queries which involve functions in FROM clause are unsupported. +SELECT * FROM articles, position('om' in 'Thomas'); + +-- subqueries are not supported in WHERE clause in CitusDB +SELECT * FROM articles WHERE author_id IN (SELECT id FROM authors WHERE name LIKE '%a'); + +-- subqueries are supported in FROM clause +SELECT articles.id,test.word_count +FROM articles, (SELECT id, word_count FROM articles) AS test WHERE test.id = articles.id +ORDER BY articles.id; + +-- subqueries are not supported in SELECT clause +SELECT a.title AS name, (SELECT a2.id FROM authors a2 WHERE a.id = a2.id LIMIT 1) + AS special_price FROM articles a; + +-- joins are not supported between local and distributed tables +SELECT title, authors.name FROM authors, articles WHERE authors.id = articles.author_id; + +-- inner joins are not supported (I think) +SELECT * FROM (articles INNER JOIN authors ON articles.id = authors.id); + +-- test use of EXECUTE statements within plpgsql +DO $sharded_execute$ + BEGIN + EXECUTE 'SELECT COUNT(*) FROM articles ' || + 'WHERE author_id = $1 AND author_id = $2' USING 1, 2; + END +$sharded_execute$; + +-- test use of bare SQL within plpgsql +DO $sharded_sql$ + BEGIN + SELECT COUNT(*) FROM articles WHERE author_id = 1 AND author_id = 2; + END +$sharded_sql$; + +-- test cross-shard queries +SELECT COUNT(*) FROM articles; + +-- having queries unsupported in CitusDB +SELECT author_id, sum(word_count) AS corpus_size FROM articles + GROUP BY author_id + HAVING sum(word_count) > 25000 + ORDER BY sum(word_count) DESC + LIMIT 5; + +-- more proof CitusDB doesn't support having clauses +SELECT author_id FROM articles + GROUP BY author_id + HAVING sum(word_count) > 50000 + ORDER BY author_id; + +-- now, test the cases where CitusDB do or do not need to create +-- the master queries +SET citusdb.task_executor_type TO 'router'; +SET citusdb.large_table_shard_count TO 2; +SET client_min_messages TO 'DEBUG2'; + +-- start with the simple lookup query +SELECT * + FROM articles + WHERE author_id = 1; + +-- below query hits a single shard, so no need to create the master query +SELECT * + FROM articles + WHERE author_id = 1 OR author_id = 17; + +-- below query hits two shards, so needs to create the master query +SELECT * + FROM articles + WHERE author_id = 1 OR author_id = 18; + +-- rename the output columns on a no master query case +SELECT id as article_id, word_count * id as random_value + FROM articles + WHERE author_id = 1; + +-- we can push down co-located joins to a single worker without the +-- master query being required for only the same tables +SELECT a.author_id as first_author, b.word_count as second_word_count + FROM articles a, articles b + WHERE a.author_id = 10 and a.author_id = b.author_id + LIMIT 3; + +-- now show that JOINs don't work with multiple tables +SELECT a.author_id as first_author, b.word_count as second_word_count + FROM articles a, articles_single_shard b + WHERE a.author_id = 10 and a.author_id = b.author_id + LIMIT 3; + +-- do not create the master query for LIMIT on a single shard SELECT +SELECT * + FROM articles + WHERE author_id = 1 + LIMIT 2; + +-- This query hits a single shard. So GROUP BY can be +-- pushed down to the workers directly. This query is +-- equivalent to SELECT DISTINCT on a single shard. +SELECT id + FROM articles + WHERE author_id = 1 + GROUP BY id; + +-- copying from a single shard table does not require the master query +COPY articles_single_shard TO stdout; + +-- error out for queries with aggregates +SELECT avg(word_count) + FROM articles + WHERE author_id = 2; + +-- max, min, sum, count is somehow implemented +-- differently in distributed planning but, still error out +SELECT max(word_count) as max, min(word_count) as min, + sum(word_count) as sum, count(word_count) as cnt + FROM articles + WHERE author_id = 2; + +-- error out for queries with ORDER BY +SELECT * + FROM articles + WHERE author_id = 1 + ORDER BY word_count; + +-- error out for queries with ORDER BY and LIMIT +SELECT * + FROM articles + WHERE author_id = 1 + ORDER BY word_count + LIMIT 2; + +-- error out for queries with aggregates and GROUP BY +SELECT max(word_count) + FROM articles + WHERE author_id = 1 + GROUP BY author_id; + +-- error out for queries with repartition jobs +SELECT * + FROM articles a, articles b + WHERE a.id = b.id AND a.author_id = 1; + +-- error out for queries which hit more than 1 shards +SELECT * + FROM articles + WHERE author_id >= 1 AND author_id <= 3; + +SET client_min_messages to 'NOTICE'; +SET citusdb.task_executor_type TO 'real-time'; diff --git a/src/test/regress/sql/multi_single_relation_subquery.sql b/src/test/regress/sql/multi_single_relation_subquery.sql new file mode 100644 index 000000000..19e56f60e --- /dev/null +++ b/src/test/regress/sql/multi_single_relation_subquery.sql @@ -0,0 +1,145 @@ +-- +-- MULTI_SINGLE_RELATION_SUBQUERY +-- + +-- This test checks that we are able to run selected set of distributed SQL subqueries. + +SET citusdb.task_executor_type TO 'task-tracker'; + +select + number_sum, + count(*) as total, + avg(total_count) avg_count +from + (select + l_suppkey, + l_linestatus, + sum(l_linenumber) as number_sum, + count(*) as total_count + from + lineitem + group by + l_suppkey, + l_linestatus) as distributed_table +where + number_sum >= 10 +group by + number_sum +order by + total desc, + number_sum desc +limit 10; + +select + (l_suppkey / 100) as suppkey_bin, + avg(total_count) avg_count +from + (select + l_suppkey, + sum(l_linenumber) as number_sum, + count(*) as total_count + from + lineitem + group by + l_suppkey, + l_linestatus) as distributed_table +group by + suppkey_bin +order by + avg_count desc +limit 20; + +select + total, + avg(avg_count) as total_avg_count +from + (select + number_sum, + count(*) as total, + avg(total_count) avg_count + from + (select + l_suppkey, + sum(l_linenumber) as number_sum, + count(*) as total_count + from + lineitem + where + l_partkey > 100 and + l_quantity > 2 and + l_orderkey < 10000 + group by + l_suppkey) as distributed_table + where + number_sum >= 10 + group by + number_sum) as distributed_table_2 +group by + total +order by + total; + +-- Check that we support subquery even though group by clause is an expression +-- and it is not referred in the target list. + +select + avg(count) +from + (select + l_suppkey, + count(*) as count + from + lineitem + group by + (l_orderkey/4)::int, + l_suppkey ) as distributed_table; + +-- Check that we don't support subqueries with limit. + +select + l_suppkey, + sum(suppkey_count) as total_suppkey_count +from + (select + l_suppkey, + count(*) as suppkey_count + from + lineitem + group by + l_suppkey + order by + l_suppkey + limit 100) as distributed_table +group by + l_suppkey; + +-- Check that we don't support subqueries without aggregates. + +select + rounded_tax +from + (select + round(l_tax) as rounded_tax + from + lineitem + group by + l_tax) as distributed_table; + +-- Check that if subquery is pulled, we don't error and run query properly. + +SELECT max(l_suppkey) FROM +( + SELECT + l_suppkey + FROM ( + SELECT + l_suppkey, + count(*) + FROM + lineitem_subquery + WHERE + l_orderkey < 20000 + GROUP BY + l_suppkey) z +) y; + diff --git a/src/test/regress/sql/multi_table_ddl.sql b/src/test/regress/sql/multi_table_ddl.sql new file mode 100644 index 000000000..f2f8a6290 --- /dev/null +++ b/src/test/regress/sql/multi_table_ddl.sql @@ -0,0 +1,39 @@ +-- +-- MULTI_TABLE_DDL +-- +-- Tests around changing the schema and dropping of a distributed table + +CREATE TABLE testtableddl(somecol int, distributecol text NOT NULL); +SELECT master_create_distributed_table('testtableddl', 'distributecol', 'append'); + +-- verify that the citusdb extension can't be dropped while distributed tables exist +DROP EXTENSION citusdb; + +-- verify that the distribution column can't have its type changed +ALTER TABLE testtableddl ALTER COLUMN distributecol TYPE text; + +-- verify that the distribution column can't be dropped +ALTER TABLE testtableddl DROP COLUMN distributecol; + +-- verify that the table cannot be dropped while shards exist +SELECT 1 FROM master_create_empty_shard('testtableddl'); +DROP TABLE testtableddl; + +-- not even with cascade +DROP TABLE testtableddl CASCADE; + +-- but it can be dropped after dropping the shards +SELECT master_apply_delete_command('DELETE FROM testtableddl'); +DROP TABLE testtableddl; + +-- ensure no metadata of distributed tables are remaining +SELECT * FROM pg_dist_partition; +SELECT * FROM pg_dist_shard; +SELECT * FROM pg_dist_shard_placement; + +-- check that the extension now can be dropped (and recreated). We reconnect +-- before creating the extension to expire extension specific variables which +-- are cached for performance. +DROP EXTENSION citusdb; +\c +CREATE EXTENSION citusdb; diff --git a/src/test/regress/sql/multi_task_assignment_policy.sql b/src/test/regress/sql/multi_task_assignment_policy.sql new file mode 100644 index 000000000..935c13558 --- /dev/null +++ b/src/test/regress/sql/multi_task_assignment_policy.sql @@ -0,0 +1,94 @@ +-- +-- MULTI_TASK_ASSIGNMENT +-- + +-- Check that our policies for assigning tasks to worker nodes run as expected. +-- To test this, we first create a shell table, and then manually insert shard +-- and shard placement data into system catalogs. We next run Explain command, +-- and check that tasks are assigned to worker nodes as expected. + +CREATE TABLE task_assignment_test_table (test_id integer); +SELECT master_create_distributed_table('task_assignment_test_table', 'test_id', 'append'); + +-- Create logical shards with shardids 200, 201, and 202 + +INSERT INTO pg_dist_shard (logicalrelid, shardid, shardstorage, shardminvalue, shardmaxvalue) + SELECT pg_class.oid, series.index, 'r', 1, 1000 + FROM pg_class, generate_series(200, 202) AS series(index) + WHERE pg_class.relname = 'task_assignment_test_table'; + +-- Create shard placements for shard 200 and 201 + +INSERT INTO pg_dist_shard_placement (shardid, shardstate, shardlength, nodename, nodeport) + SELECT 200, 1, 1, nodename, nodeport + FROM pg_dist_shard_placement + GROUP BY nodename, nodeport + ORDER BY nodename, nodeport ASC + LIMIT 2; + +INSERT INTO pg_dist_shard_placement (shardid, shardstate, shardlength, nodename, nodeport) + SELECT 201, 1, 1, nodename, nodeport + FROM pg_dist_shard_placement + GROUP BY nodename, nodeport + ORDER BY nodename, nodeport ASC + LIMIT 2; + +-- Create shard placements for shard 202 + +INSERT INTO pg_dist_shard_placement (shardid, shardstate, shardlength, nodename, nodeport) + SELECT 202, 1, 1, nodename, nodeport + FROM pg_dist_shard_placement + GROUP BY nodename, nodeport + ORDER BY nodename, nodeport DESC + LIMIT 2; + +-- Start transaction block to avoid auto commits. This avoids additional debug +-- messages from getting printed at real transaction starts and commits. + +BEGIN; + +-- Increase log level to see which worker nodes tasks are assigned to. Note that +-- the following log messages print node name and port numbers; and node numbers +-- in regression tests depend upon PG_VERSION_NUM. + +SET client_min_messages TO DEBUG3; + +-- First test the default greedy task assignment policy + +SET citusdb.task_assignment_policy TO 'greedy'; + +EXPLAIN SELECT count(*) FROM task_assignment_test_table; + +EXPLAIN SELECT count(*) FROM task_assignment_test_table; + +-- Next test the first-replica task assignment policy + +SET citusdb.task_assignment_policy TO 'first-replica'; + +EXPLAIN SELECT count(*) FROM task_assignment_test_table; + +EXPLAIN SELECT count(*) FROM task_assignment_test_table; + +-- Round-robin task assignment relies on the current jobId. We therefore need to +-- ensure that jobIds start with an odd number here; this way, task assignment +-- debug messages always produce the same output. Also, we make sure that the +-- following case statement always prints out "1" as the query's result. + +SELECT case when (currval('pg_dist_jobid_seq') % 2) = 0 + then nextval('pg_dist_jobid_seq') % 2 + else 1 end; + +-- Finally test the round-robin task assignment policy + +SET citusdb.task_assignment_policy TO 'round-robin'; + +EXPLAIN SELECT count(*) FROM task_assignment_test_table; + +EXPLAIN SELECT count(*) FROM task_assignment_test_table; + +EXPLAIN SELECT count(*) FROM task_assignment_test_table; + +RESET citusdb.task_assignment_policy; +RESET client_min_messages; + +COMMIT; diff --git a/src/test/regress/sql/multi_tpch_query1.sql b/src/test/regress/sql/multi_tpch_query1.sql new file mode 100644 index 000000000..f79aa6586 --- /dev/null +++ b/src/test/regress/sql/multi_tpch_query1.sql @@ -0,0 +1,31 @@ +-- +-- MULTI_TPCH_QUERY1 +-- + +-- Change configuration to treat lineitem and orders tables as large + +SET citusdb.large_table_shard_count TO 2; + +-- Query #1 from the TPC-H decision support benchmark + +SELECT + l_returnflag, + l_linestatus, + sum(l_quantity) as sum_qty, + sum(l_extendedprice) as sum_base_price, + sum(l_extendedprice * (1 - l_discount)) as sum_disc_price, + sum(l_extendedprice * (1 - l_discount) * (1 + l_tax)) as sum_charge, + avg(l_quantity) as avg_qty, + avg(l_extendedprice) as avg_price, + avg(l_discount) as avg_disc, + count(*) as count_order +FROM + lineitem +WHERE + l_shipdate <= date '1998-12-01' - interval '90 days' +GROUP BY + l_returnflag, + l_linestatus +ORDER BY + l_returnflag, + l_linestatus; diff --git a/src/test/regress/sql/multi_tpch_query10.sql b/src/test/regress/sql/multi_tpch_query10.sql new file mode 100644 index 000000000..581647403 --- /dev/null +++ b/src/test/regress/sql/multi_tpch_query10.sql @@ -0,0 +1,40 @@ +-- +-- MULTI_TPCH_QUERY10 +-- + +-- Query #10 from the TPC-H decision support benchmark. Unlike other TPC-H tests, +-- we don't set citusdb.large_table_shard_count here, and instead use the default value +-- coming from postgresql.conf or multi_task_tracker_executor.conf. + +SELECT + c_custkey, + c_name, + sum(l_extendedprice * (1 - l_discount)) as revenue, + c_acctbal, + n_name, + c_address, + c_phone, + c_comment +FROM + customer, + orders, + lineitem, + nation +WHERE + c_custkey = o_custkey + AND l_orderkey = o_orderkey + AND o_orderdate >= date '1993-10-01' + AND o_orderdate < date '1993-10-01' + interval '3' month + AND l_returnflag = 'R' + AND c_nationkey = n_nationkey +GROUP BY + c_custkey, + c_name, + c_acctbal, + c_phone, + n_name, + c_address, + c_comment +ORDER BY + revenue DESC +LIMIT 20; diff --git a/src/test/regress/sql/multi_tpch_query12.sql b/src/test/regress/sql/multi_tpch_query12.sql new file mode 100644 index 000000000..fd85c82c0 --- /dev/null +++ b/src/test/regress/sql/multi_tpch_query12.sql @@ -0,0 +1,38 @@ +-- +-- MULTI_TPCH_QUERY12 +-- + +-- Change configuration to treat lineitem and orders tables as large + +SET citusdb.large_table_shard_count TO 2; + +-- Query #12 from the TPC-H decision support benchmark + +SELECT + l_shipmode, + sum(case + when o_orderpriority = '1-URGENT' + OR o_orderpriority = '2-HIGH' + then 1 + else 0 + end) as high_line_count, + sum(case + when o_orderpriority <> '1-URGENT' + AND o_orderpriority <> '2-HIGH' + then 1 + else 0 + end) AS low_line_count +FROM + orders, + lineitem +WHERE + o_orderkey = l_orderkey + AND l_shipmode in ('MAIL', 'SHIP') + AND l_commitdate < l_receiptdate + AND l_shipdate < l_commitdate + AND l_receiptdate >= date '1994-01-01' + AND l_receiptdate < date '1994-01-01' + interval '1' year +GROUP BY + l_shipmode +ORDER BY + l_shipmode; diff --git a/src/test/regress/sql/multi_tpch_query14.sql b/src/test/regress/sql/multi_tpch_query14.sql new file mode 100644 index 000000000..83cf9e954 --- /dev/null +++ b/src/test/regress/sql/multi_tpch_query14.sql @@ -0,0 +1,23 @@ +-- +-- MULTI_TPCH_QUERY14 +-- + +-- Change configuration to treat lineitem and orders tables as large + +SET citusdb.large_table_shard_count TO 2; + +-- Query #14 from the TPC-H decision support benchmark + +SELECT + 100.00 * sum(case + when p_type like 'PROMO%' + then l_extendedprice * (1 - l_discount) + else 0 + end) / sum(l_extendedprice * (1 - l_discount)) as promo_revenue +FROM + lineitem, + part +WHERE + l_partkey = p_partkey + AND l_shipdate >= date '1995-09-01' + AND l_shipdate < date '1995-09-01' + interval '1' year; diff --git a/src/test/regress/sql/multi_tpch_query19.sql b/src/test/regress/sql/multi_tpch_query19.sql new file mode 100644 index 000000000..32255e74c --- /dev/null +++ b/src/test/regress/sql/multi_tpch_query19.sql @@ -0,0 +1,40 @@ +-- +-- MULTI_TPCH_QUERY19 +-- + +-- Change configuration to treat lineitem and orders tables as large + +SET citusdb.large_table_shard_count TO 2; + +-- Query #19 from the TPC-H decision support benchmark. Note that we modified +-- the query from its original to make it work on smaller data sets. + +SELECT + sum(l_extendedprice* (1 - l_discount)) as revenue +FROM + lineitem, + part +WHERE + ( + p_partkey = l_partkey + AND (p_brand = 'Brand#12' OR p_brand= 'Brand#14' OR p_brand='Brand#15') + AND l_quantity >= 10 + AND l_shipmode in ('AIR', 'AIR REG', 'TRUCK') + AND l_shipinstruct = 'DELIVER IN PERSON' + ) + OR + ( + p_partkey = l_partkey + AND (p_brand = 'Brand#23' OR p_brand='Brand#24') + AND l_quantity >= 20 + AND l_shipmode in ('AIR', 'AIR REG', 'TRUCK') + AND l_shipinstruct = 'DELIVER IN PERSON' + ) + OR + ( + p_partkey = l_partkey + AND (p_brand = 'Brand#33' OR p_brand = 'Brand#34' OR p_brand = 'Brand#35') + AND l_quantity >= 1 + AND l_shipmode in ('AIR', 'AIR REG', 'TRUCK') + AND l_shipinstruct = 'DELIVER IN PERSON' + ); diff --git a/src/test/regress/sql/multi_tpch_query3.sql b/src/test/regress/sql/multi_tpch_query3.sql new file mode 100644 index 000000000..e23ba3329 --- /dev/null +++ b/src/test/regress/sql/multi_tpch_query3.sql @@ -0,0 +1,30 @@ +-- +-- MULTI_TPCH_QUERY3 +-- + +-- Query #3 from the TPC-H decision support benchmark. Unlike other TPC-H tests, +-- we don't set citusdb.large_table_shard_count here, and instead use the default value +-- coming from postgresql.conf or multi_task_tracker_executor.conf. + +SELECT + l_orderkey, + sum(l_extendedprice * (1 - l_discount)) as revenue, + o_orderdate, + o_shippriority +FROM + customer, + orders, + lineitem +WHERE + c_mktsegment = 'BUILDING' + AND c_custkey = o_custkey + AND l_orderkey = o_orderkey + AND o_orderdate < date '1995-03-15' + AND l_shipdate > date '1995-03-15' +GROUP BY + l_orderkey, + o_orderdate, + o_shippriority +ORDER BY + revenue DESC, + o_orderdate; diff --git a/src/test/regress/sql/multi_tpch_query6.sql b/src/test/regress/sql/multi_tpch_query6.sql new file mode 100644 index 000000000..7a31c47fe --- /dev/null +++ b/src/test/regress/sql/multi_tpch_query6.sql @@ -0,0 +1,19 @@ +-- +-- MULTI_TPCH_QUERY6 +-- + +-- Change configuration to treat lineitem and orders tables as large + +SET citusdb.large_table_shard_count TO 2; + +-- Query #6 from the TPC-H decision support benchmark + +SELECT + sum(l_extendedprice * l_discount) as revenue +FROM + lineitem +WHERE + l_shipdate >= date '1994-01-01' + and l_shipdate < date '1994-01-01' + interval '1 year' + and l_discount between 0.06 - 0.01 and 0.06 + 0.01 + and l_quantity < 24; diff --git a/src/test/regress/sql/multi_tpch_query7.sql b/src/test/regress/sql/multi_tpch_query7.sql new file mode 100644 index 000000000..875c1e86a --- /dev/null +++ b/src/test/regress/sql/multi_tpch_query7.sql @@ -0,0 +1,49 @@ +-- +-- MULTI_TPCH_QUERY7 +-- + +-- Change configuration to treat lineitem AND orders tables as large + +SET citusdb.large_table_shard_count TO 2; + +-- Query #7 from the TPC-H decision support benchmark + +SELECT + supp_nation, + cust_nation, + l_year, + sum(volume) as revenue +FROM + ( + SELECT + n1.n_name as supp_nation, + n2.n_name as cust_nation, + extract(year FROM l_shipdate) as l_year, + l_extendedprice * (1 - l_discount) as volume + FROM + supplier, + lineitem, + orders, + customer, + nation n1, + nation n2 + WHERE + s_suppkey = l_suppkey + AND o_orderkey = l_orderkey + AND c_custkey = o_custkey + AND s_nationkey = n1.n_nationkey + AND c_nationkey = n2.n_nationkey + AND ( + (n1.n_name = 'FRANCE' AND n2.n_name = 'GERMANY') + OR (n1.n_name = 'GERMANY' AND n2.n_name = 'FRANCE') + ) + AND l_shipdate between date '1995-01-01' AND date '1996-12-31' + ) as shipping +GROUP BY + supp_nation, + cust_nation, + l_year +ORDER BY + supp_nation, + cust_nation, + l_year; diff --git a/src/test/regress/sql/multi_tpch_query7_nested.sql b/src/test/regress/sql/multi_tpch_query7_nested.sql new file mode 100644 index 000000000..fd93a17c9 --- /dev/null +++ b/src/test/regress/sql/multi_tpch_query7_nested.sql @@ -0,0 +1,58 @@ +-- +-- MULTI_TPCH_QUERY7_NESTED +-- + +-- Change configuration to treat lineitem AND orders tables AS large + +SET citusdb.large_table_shard_count TO 2; + +-- Query #7 from the TPC-H benchmark; modified to include sub-selects + +SELECT + supp_nation, + cust_nation, + l_year, + sum(volume) AS revenue +FROM + ( + SELECT + supp_nation, + cust_nation, + extract(year FROM l_shipdate) AS l_year, + l_extendedprice * (1 - l_discount) AS volume + FROM + supplier, + lineitem, + orders, + customer, + ( + SELECT + n1.n_nationkey AS supp_nation_key, + n2.n_nationkey AS cust_nation_key, + n1.n_name AS supp_nation, + n2.n_name AS cust_nation + FROM + nation n1, + nation n2 + WHERE + ( + (n1.n_name = 'FRANCE' AND n2.n_name = 'GERMANY') + OR (n1.n_name = 'GERMANY' AND n2.n_name = 'FRANCE') + ) + ) AS temp + WHERE + s_suppkey = l_suppkey + AND o_orderkey = l_orderkey + AND c_custkey = o_custkey + AND s_nationkey = supp_nation_key + AND c_nationkey = cust_nation_key + AND l_shipdate between date '1995-01-01' AND date '1996-12-31' + ) AS shipping +GROUP BY + supp_nation, + cust_nation, + l_year +ORDER BY + supp_nation, + cust_nation, + l_year; diff --git a/src/test/regress/sql/multi_upsert.sql b/src/test/regress/sql/multi_upsert.sql new file mode 100644 index 000000000..3e47862c6 --- /dev/null +++ b/src/test/regress/sql/multi_upsert.sql @@ -0,0 +1,187 @@ +-- this test file aims to test UPSERT feature on CitusDB +-- note that output of this file for postgresql 9.4 will +-- be full syntax errors, which is expected. + +CREATE TABLE upsert_test +( + part_key int UNIQUE, + other_col int, + third_col int +); + +-- distribute the table and create shards +SELECT master_create_distributed_table('upsert_test', 'part_key', 'hash'); +SELECT master_create_worker_shards('upsert_test', '4', '2'); + +-- do a regular insert +INSERT INTO upsert_test (part_key, other_col) VALUES (1, 1); + +-- observe that there is a conflict and the following query does nothing +INSERT INTO upsert_test (part_key, other_col) VALUES (1, 1) ON CONFLICT DO NOTHING; + +-- same as the above with different syntax +INSERT INTO upsert_test (part_key, other_col) VALUES (1, 1) ON CONFLICT (part_key) DO NOTHING; + +--again the same query with another syntax +INSERT INTO upsert_test (part_key, other_col) VALUES (1, 1) ON CONFLICT ON CONSTRAINT upsert_test_part_key_key DO NOTHING; + +-- now, update the columns +INSERT INTO upsert_test (part_key, other_col) VALUES (1, 1) + ON CONFLICT (part_key) DO UPDATE SET other_col = 2, third_col = 4; + +-- see the results +SELECT * FROM upsert_test; + +-- use a WHERE clause, so that SET doesn't have an affect +INSERT INTO upsert_test (part_key, other_col) VALUES (1, 1) ON CONFLICT (part_key) + DO UPDATE SET other_col = 30 WHERE upsert_test.other_col = 3; + +-- see the results +SELECT * FROM upsert_test; + +-- use a WHERE clause, that hits the row and updates it +INSERT INTO upsert_test (part_key, other_col) VALUES (1, 1) ON CONFLICT (part_key) + DO UPDATE SET other_col = 30 WHERE upsert_test.other_col = 2; + +-- see the results +SELECT * FROM upsert_test; + +-- use two elements in the WHERE, that doesn't hit the row and updates it +INSERT INTO upsert_test (part_key, other_col) VALUES (1, 1) ON CONFLICT (part_key) + DO UPDATE SET other_col = 30 WHERE upsert_test.other_col = 2 AND upsert_test.other_col = 3; + +-- use EXCLUDED keyword +INSERT INTO upsert_test (part_key, other_col, third_col) VALUES (1, 1, 100) ON CONFLICT (part_key) + DO UPDATE SET other_col = EXCLUDED.third_col; + +-- see the results +SELECT * FROM upsert_test; + +-- now update multiple columns with ALIAS table and reference to the row itself +INSERT INTO upsert_test as ups_test (part_key) VALUES (1) + ON CONFLICT (part_key) DO UPDATE SET other_col = ups_test.other_col + 50, third_col = 200; + +-- see the results +SELECT * FROM upsert_test; + +-- now, do some more complex assignments +INSERT INTO upsert_test (part_key, other_col) VALUES (1, 1) ON CONFLICT (part_key) + DO UPDATE SET other_col = upsert_test.other_col + 1, + third_col = upsert_test.third_col + (EXCLUDED.part_key + EXCLUDED.other_col) + 670; + +-- see the results +SELECT * FROM upsert_test; + +-- now, WHERE clause also has table reference +INSERT INTO upsert_test as ups_test (part_key, other_col) VALUES (1, 1) ON CONFLICT (part_key) + DO UPDATE SET other_col = (ups_test.other_col + ups_test.third_col + (EXCLUDED.part_key + EXCLUDED.other_col)) % 15 + WHERE ups_test.third_col < 1000 + ups_test.other_col; + +-- see the results +SELECT * FROM upsert_test; + +-- create another table +CREATE TABLE upsert_test_2 +( + part_key int, + other_col int, + third_col int, + PRIMARY KEY (part_key, other_col) +); + +-- distribute the table and create shards +SELECT master_create_distributed_table('upsert_test_2', 'part_key', 'hash'); +SELECT master_create_worker_shards('upsert_test_2', '4', '2'); + +-- now show that CitusDB works with multiple columns as the PRIMARY KEY, including the partiton key +INSERT INTO upsert_test_2 (part_key, other_col) VALUES (1, 1); +INSERT INTO upsert_test_2 (part_key, other_col) VALUES (1, 1) ON CONFLICT (part_key, other_col) DO NOTHING; + +-- this errors out since there is no unique constraint on partition key +INSERT INTO upsert_test_2 (part_key, other_col) VALUES (1, 1) ON CONFLICT (part_key) DO NOTHING; + +-- create another table +CREATE TABLE upsert_test_3 +( + part_key int, + count int +); + +-- note that this is not a unique index +CREATE INDEX idx_ups_test ON upsert_test_3(part_key); + +-- distribute the table and create shards +SELECT master_create_distributed_table('upsert_test_3', 'part_key', 'hash'); +SELECT master_create_worker_shards('upsert_test_3', '4', '2'); + +-- since there are no unique indexes, error-out +INSERT INTO upsert_test_3 VALUES (1, 0) ON CONFLICT(part_key) DO UPDATE SET count = upsert_test_3.count + 1; + +-- create another table +CREATE TABLE upsert_test_4 +( + part_key int UNIQUE, + count int +); + +-- distribute the table and create shards +SELECT master_create_distributed_table('upsert_test_4', 'part_key', 'hash'); +SELECT master_create_worker_shards('upsert_test_4', '4', '2'); + +-- a single row insert +INSERT INTO upsert_test_4 VALUES (1, 0); + +-- show a simple count example use case +INSERT INTO upsert_test_4 VALUES (1, 0) ON CONFLICT(part_key) DO UPDATE SET count = upsert_test_4.count + 1; +INSERT INTO upsert_test_4 VALUES (1, 0) ON CONFLICT(part_key) DO UPDATE SET count = upsert_test_4.count + 1; +INSERT INTO upsert_test_4 VALUES (1, 0) ON CONFLICT(part_key) DO UPDATE SET count = upsert_test_4.count + 1; +INSERT INTO upsert_test_4 VALUES (1, 0) ON CONFLICT(part_key) DO UPDATE SET count = upsert_test_4.count + 1; +INSERT INTO upsert_test_4 VALUES (1, 0) ON CONFLICT(part_key) DO UPDATE SET count = upsert_test_4.count + 1; +INSERT INTO upsert_test_4 VALUES (1, 0) ON CONFLICT(part_key) DO UPDATE SET count = upsert_test_4.count + 1; + +-- now see the results +SELECT * FROM upsert_test_4; + +-- now test dropped columns +CREATE TABLE dropcol_distributed(key int primary key, drop1 int, keep1 text, drop2 numeric, keep2 float); +SELECT master_create_distributed_table('dropcol_distributed', 'key', 'hash'); +SELECT master_create_worker_shards('dropcol_distributed', 4, 1); + +INSERT INTO dropcol_distributed AS dropcol (key, keep1, keep2) VALUES (1, '5', 5) ON CONFLICT(key) + DO UPDATE SET keep1 = dropcol.keep1; + +ALTER TABLE dropcol_distributed DROP COLUMN drop2; + +INSERT INTO dropcol_distributed (key, keep1, keep2) VALUES (1, '5', 5) ON CONFLICT(key) + DO UPDATE SET keep1 = dropcol_distributed.keep1; + +ALTER TABLE dropcol_distributed DROP COLUMN keep2; + +INSERT INTO dropcol_distributed AS dropcol (key, keep1) VALUES (1, '5') ON CONFLICT(key) + DO UPDATE SET keep1 = dropcol.keep1; + +ALTER TABLE dropcol_distributed DROP COLUMN drop1; + +INSERT INTO dropcol_distributed AS dropcol (key, keep1) VALUES (1, '5') ON CONFLICT(key) + DO UPDATE SET keep1 = dropcol.keep1; + +-- below we test the cases that CitusDB does not support +-- subquery in the SET clause +INSERT INTO upsert_test (part_key, other_col) VALUES (1, 1) ON CONFLICT (part_key) DO + UPDATE SET other_col = (SELECT count(*) from upsert_test); + +-- non mutable function call in the SET +INSERT INTO upsert_test (part_key, other_col) VALUES (1, 1) ON CONFLICT (part_key) DO + UPDATE SET other_col = random()::int; + +-- non mutable function call in the WHERE +INSERT INTO upsert_test (part_key, other_col) VALUES (1, 1) ON CONFLICT (part_key) DO + UPDATE SET other_col = 5 WHERE upsert_test.other_col = random()::int; + +-- non mutable function call in the arbiter WHERE +INSERT INTO upsert_test (part_key, other_col) VALUES (1, 1) ON CONFLICT (part_key) WHERE part_key = random()::int + DO UPDATE SET other_col = 5; + +-- error out on attempt to update the partition key +INSERT INTO upsert_test (part_key, other_col) VALUES (1, 1) ON CONFLICT (part_key) DO + UPDATE SET part_key = 15; diff --git a/src/test/regress/sql/multi_utilities.sql b/src/test/regress/sql/multi_utilities.sql new file mode 100644 index 000000000..457a79489 --- /dev/null +++ b/src/test/regress/sql/multi_utilities.sql @@ -0,0 +1,49 @@ +-- =================================================================== +-- test utility statement functionality +-- =================================================================== + +CREATE TABLE sharded_table ( name text, id bigint ); +SELECT master_create_distributed_table('sharded_table', 'id', 'hash'); +SELECT master_create_worker_shards('sharded_table', 2, 1); + +-- COPY out is supported with distributed tables +COPY sharded_table TO STDOUT; +COPY (SELECT COUNT(*) FROM sharded_table) TO STDOUT; + +-- but COPY in is not +COPY sharded_table FROM STDIN; + +-- cursors may not involve distributed tables +DECLARE all_sharded_rows CURSOR FOR SELECT * FROM sharded_table; + +-- EXPLAIN support isn't implemented for distributed queries... +EXPLAIN SELECT * FROM sharded_table; + +-- ... or for distributed modifications +EXPLAIN INSERT INTO sharded_table VALUES ('dan', 4); + +-- verify PREPARE functionality +PREPARE sharded_insert AS INSERT INTO sharded_table VALUES ('adam', 1); +PREPARE sharded_update AS UPDATE sharded_table SET name = 'bob' WHERE id = 1; +PREPARE sharded_delete AS DELETE FROM sharded_table WHERE id = 1; +PREPARE sharded_query AS SELECT name FROM sharded_table WHERE id = 1; + +EXECUTE sharded_query; +EXECUTE sharded_insert; +EXECUTE sharded_query; +EXECUTE sharded_update; +EXECUTE sharded_query; +EXECUTE sharded_delete; +EXECUTE sharded_query; + +-- try to drop table +DROP TABLE sharded_table; + +-- try to drop shards with where clause +SELECT master_apply_delete_command('DELETE FROM sharded_table WHERE id > 0'); + +-- drop all shards +SELECT master_apply_delete_command('DELETE FROM sharded_table'); + +-- drop table +DROP TABLE sharded_table; diff --git a/src/test/regress/sql/multi_utility_statements.sql b/src/test/regress/sql/multi_utility_statements.sql new file mode 100644 index 000000000..ddf0b37a5 --- /dev/null +++ b/src/test/regress/sql/multi_utility_statements.sql @@ -0,0 +1,148 @@ +-- +-- MULTI_UTILITY_STATEMENTS +-- + +-- Check that we can run utility statements with embedded SELECT statements on +-- distributed tables. Currently we only support CREATE TABLE AS (SELECT..), +-- DECLARE CURSOR, and COPY ... TO statements. + +CREATE TEMP TABLE lineitem_pricing_summary AS +( + SELECT + l_returnflag, + l_linestatus, + sum(l_quantity) as sum_qty, + sum(l_extendedprice) as sum_base_price, + sum(l_extendedprice * (1 - l_discount)) as sum_disc_price, + sum(l_extendedprice * (1 - l_discount) * (1 + l_tax)) as sum_charge, + avg(l_quantity) as avg_qty, + avg(l_extendedprice) as avg_price, + avg(l_discount) as avg_disc, + count(*) as count_order + FROM + lineitem + WHERE + l_shipdate <= date '1998-12-01' - interval '90 days' + GROUP BY + l_returnflag, + l_linestatus + ORDER BY + l_returnflag, + l_linestatus +); + +SELECT * FROM lineitem_pricing_summary ORDER BY l_returnflag, l_linestatus; + +-- Test we can handle joins + +SET citusdb.large_table_shard_count TO 2; + +CREATE TABLE shipping_priority AS +( + SELECT + l_orderkey, + sum(l_extendedprice * (1 - l_discount)) as revenue, + o_orderdate, + o_shippriority + FROM + customer, + orders, + lineitem + WHERE + c_mktsegment = 'BUILDING' + AND c_custkey = o_custkey + AND l_orderkey = o_orderkey + AND o_orderdate < date '1995-03-15' + AND l_shipdate > date '1995-03-15' + GROUP BY + l_orderkey, + o_orderdate, + o_shippriority + ORDER BY + revenue DESC, + o_orderdate +); + +SELECT * FROM shipping_priority; +DROP TABLE shipping_priority; + +-- Check COPY against distributed tables works both when specifying a +-- query as the source, and when directly naming a table. + +COPY ( + SELECT + l_orderkey, + sum(l_extendedprice * (1 - l_discount)) as revenue, + o_orderdate, + o_shippriority + FROM + customer, + orders, + lineitem + WHERE + c_mktsegment = 'BUILDING' + AND c_custkey = o_custkey + AND l_orderkey = o_orderkey + AND o_orderdate < date '1995-03-15' + AND l_shipdate > date '1995-03-15' + GROUP BY + l_orderkey, + o_orderdate, + o_shippriority + ORDER BY + revenue DESC, + o_orderdate +) TO stdout; + +-- check copying to file +-- (quiet off to force number of copied records to be displayed) +\set QUIET off +COPY nation TO '/dev/null'; +\set QUIET on +-- stdout +COPY nation TO STDOUT; +-- ensure individual cols can be copied out, too +COPY nation(n_name) TO STDOUT; + +-- Ensure that preventing COPY FROM against distributed tables works +COPY customer FROM STDIN; + +-- Test that we can create on-commit drop tables, and also test creating with +-- oids, along with changing column names + +BEGIN; + +CREATE TEMP TABLE customer_few (customer_key) WITH (OIDS) ON COMMIT DROP AS + (SELECT * FROM customer WHERE c_nationkey = 1 ORDER BY c_custkey LIMIT 10); + +SELECT customer_key, c_name, c_address + FROM customer_few ORDER BY customer_key LIMIT 5; + +COMMIT; + +SELECT customer_key, c_name, c_address + FROM customer_few ORDER BY customer_key LIMIT 5; + +-- Test DECLARE CURSOR statements + +DECLARE holdCursor SCROLL CURSOR WITH HOLD FOR + SELECT l_orderkey, l_linenumber, l_quantity, l_discount + FROM lineitem + ORDER BY l_orderkey, l_linenumber; + +FETCH NEXT FROM holdCursor; +FETCH FORWARD 5 FROM holdCursor; +FETCH LAST FROM holdCursor; +FETCH BACKWARD 5 FROM holdCursor; + +-- Test WITHOUT HOLD cursors inside transactions + +BEGIN; +DECLARE noHoldCursor SCROLL CURSOR FOR + SELECT l_orderkey, l_linenumber, l_quantity, l_discount + FROM lineitem + ORDER BY l_orderkey, l_linenumber; + +FETCH ABSOLUTE 5 FROM noHoldCursor; +COMMIT; +FETCH ABSOLUTE 5 FROM noHoldCursor; diff --git a/src/test/regress/sql/multi_utility_warnings.sql b/src/test/regress/sql/multi_utility_warnings.sql new file mode 100644 index 000000000..6f7503fa4 --- /dev/null +++ b/src/test/regress/sql/multi_utility_warnings.sql @@ -0,0 +1,14 @@ +-- +-- MULTI_UTILITY_WARNINGS +-- + +-- Tests to check if we inform the user about potential caveats of creating new +-- databases, schemas, and roles. + +CREATE DATABASE new_database; + +CREATE SCHEMA new_schema; + +CREATE ROLE new_role; + +CREATE USER new_user; diff --git a/src/test/regress/sql/multi_verify_no_join_with_alias.sql b/src/test/regress/sql/multi_verify_no_join_with_alias.sql new file mode 100644 index 000000000..b957d6227 --- /dev/null +++ b/src/test/regress/sql/multi_verify_no_join_with_alias.sql @@ -0,0 +1,22 @@ +-- +-- MULTI_VERIFY_NO_JOIN_WITH_ALIAS +-- + +-- This test checks that we simply emit an error message instead of trying to +-- fetch and join a shard which has an alias set. + +-- Show that the join works without an alias + +SELECT COUNT(*) FROM lineitem, part WHERE l_partkey = p_partkey; + +-- Assign an alias to the parts shard + +UPDATE pg_dist_shard SET shardalias = 'my_alias' WHERE shardid = 102019; + +-- Attempt a join which uses this shard + +SELECT COUNT(*) FROM lineitem, part WHERE l_partkey = p_partkey; + +-- Remove the alias from the parts shard + +UPDATE pg_dist_shard SET shardalias = NULL WHERE shardid = 102019; diff --git a/src/test/regress/sql/multi_verify_no_subquery.sql b/src/test/regress/sql/multi_verify_no_subquery.sql new file mode 100644 index 000000000..d6d1c1b41 --- /dev/null +++ b/src/test/regress/sql/multi_verify_no_subquery.sql @@ -0,0 +1,18 @@ +-- +-- MULTI_VERIFY_NO_SUBQUERY +-- + +-- This test checks that we simply emit an error message instead of trying to +-- process a distributed unsupported SQL subquery. + +SELECT * FROM lineitem WHERE l_orderkey IN + (SELECT l_orderkey FROM lineitem WHERE l_quantity > 0); + +SELECT l_quantity FROM lineitem WHERE EXISTS + (SELECT 1 FROM orders WHERE o_orderkey = l_orderkey); + +SELECT l_quantity FROM lineitem WHERE l_orderkey IN (SELECT o_orderkey FROM orders); + +SELECT l_orderkey FROM lineitem WHERE l_quantity > ALL(SELECT o_orderkey FROM orders); + +SELECT l_quantity FROM lineitem WHERE l_orderkey = (SELECT min(o_orderkey) FROM orders); diff --git a/src/test/regress/sql/multi_working_columns.sql b/src/test/regress/sql/multi_working_columns.sql new file mode 100644 index 000000000..ae792ae2b --- /dev/null +++ b/src/test/regress/sql/multi_working_columns.sql @@ -0,0 +1,18 @@ +-- +-- MULTI_WORKING_COLUMNS +-- + +-- Columns that are used in sorting and grouping but that do not appear in the +-- projection order are called working (resjunk) columns. We check in here that +-- these columns are pulled to the master, and are correctly used in sorting and +-- grouping. + +SELECT l_quantity FROM lineitem ORDER BY l_shipdate, l_quantity LIMIT 20; + +SELECT l_quantity, count(*) as count FROM lineitem + GROUP BY l_quantity, l_shipdate ORDER BY l_quantity, count + LIMIT 20; + +SELECT l_quantity, l_shipdate, count(*) as count FROM lineitem + GROUP BY l_quantity, l_shipdate ORDER BY l_quantity, count, l_shipdate + LIMIT 20; diff --git a/src/test/regress/sql/task_tracker_assign_task.sql b/src/test/regress/sql/task_tracker_assign_task.sql new file mode 100644 index 000000000..d9e24ee65 --- /dev/null +++ b/src/test/regress/sql/task_tracker_assign_task.sql @@ -0,0 +1,49 @@ +-- +-- TASK_TRACKER_ASSIGN_TASK +-- + +\set JobId 401010 +\set SimpleTaskId 101101 +\set RecoverableTaskId 801102 + +\set SimpleTaskTable lineitem_simple_task +\set BadQueryString '\'SELECT COUNT(*) FROM bad_table_name\'' +\set GoodQueryString '\'SELECT COUNT(*) FROM lineitem\'' +\set SelectAll 'SELECT *' + +-- We assign two tasks to the task tracker. The first task simply executes. The +-- recoverable task on the other hand repeatedly fails, and we sleep until the +-- task tracker stops retrying the recoverable task. + +SELECT task_tracker_assign_task(:JobId, :SimpleTaskId, + 'COPY (SELECT * FROM lineitem) TO ' + '''base/pgsql_job_cache/job_401010/task_101101'''); + +SELECT task_tracker_assign_task(:JobId, :RecoverableTaskId, :BadQueryString); + +-- After assigning the two tasks, we wait for them to make progress. Note that +-- these tasks get scheduled and run asynchronously, so if the sleep interval is +-- not enough, the regression tests may fail on an overloaded box. + +SELECT pg_sleep(3.0); + +SELECT task_tracker_task_status(:JobId, :SimpleTaskId); +SELECT task_tracker_task_status(:JobId, :RecoverableTaskId); + +COPY :SimpleTaskTable FROM 'base/pgsql_job_cache/job_401010/task_101101'; + +SELECT COUNT(*) FROM :SimpleTaskTable; + +SELECT COUNT(*) AS diff_lhs FROM ( :SelectAll FROM :SimpleTaskTable EXCEPT ALL + :SelectAll FROM lineitem ) diff; +SELECT COUNT(*) As diff_rhs FROM ( :SelectAll FROM lineitem EXCEPT ALL + :SelectAll FROM :SimpleTaskTable ) diff; + +-- We now reassign the recoverable task with a good query string. This updates +-- the task's query string, and reschedules the updated task for execution. + +SELECT task_tracker_assign_task(:JobId, :RecoverableTaskId, :GoodQueryString); + +SELECT pg_sleep(2.0); + +SELECT task_tracker_task_status(:JobId, :RecoverableTaskId); diff --git a/src/test/regress/sql/task_tracker_cleanup_job.sql b/src/test/regress/sql/task_tracker_cleanup_job.sql new file mode 100644 index 000000000..be026d62f --- /dev/null +++ b/src/test/regress/sql/task_tracker_cleanup_job.sql @@ -0,0 +1,38 @@ +-- +-- TASK_TRACKER_CLEANUP_JOB +-- + +\set JobId 401010 +\set CompletedTaskId 801107 +\set RunningTaskId 801108 + +-- We assign two tasks to the task tracker. The first task should complete and +-- the second task should continue to keep running. + +SELECT task_tracker_assign_task(:JobId, :CompletedTaskId, + 'COPY (SELECT * FROM lineitem) TO ' + '''base/pgsql_job_cache/job_401010/task_801107'''); + +SELECT task_tracker_assign_task(:JobId, :RunningTaskId, + 'SELECT pg_sleep(100)'); + +SELECT pg_sleep(2.0); + +SELECT task_tracker_task_status(:JobId, :CompletedTaskId); +SELECT task_tracker_task_status(:JobId, :RunningTaskId); + +SELECT isdir FROM pg_stat_file('base/pgsql_job_cache/job_401010/task_801107'); +SELECT isdir FROM pg_stat_file('base/pgsql_job_cache/job_401010'); + +-- We now clean up all tasks for this job id. As a result, shared hash entries, +-- files, and connections associated with these tasks should all be cleaned up. + +SELECT task_tracker_cleanup_job(:JobId); + +SELECT pg_sleep(1.0); + +SELECT task_tracker_task_status(:JobId, :CompletedTaskId); +SELECT task_tracker_task_status(:JobId, :RunningTaskId); + +SELECT isdir FROM pg_stat_file('base/pgsql_job_cache/job_401010/task_801107'); +SELECT isdir FROM pg_stat_file('base/pgsql_job_cache/job_401010'); diff --git a/src/test/regress/sql/task_tracker_create_table.sql b/src/test/regress/sql/task_tracker_create_table.sql new file mode 100644 index 000000000..d27e3354e --- /dev/null +++ b/src/test/regress/sql/task_tracker_create_table.sql @@ -0,0 +1,13 @@ +-- +-- TASK_TRACKER_CREATE_TABLE +-- + +-- New table definitions to test the task tracker process and protocol + +CREATE TABLE lineitem_simple_task ( LIKE lineitem ); +CREATE TABLE lineitem_compute_task ( LIKE lineitem ); +CREATE TABLE lineitem_compute_update_task ( LIKE lineitem ); + +CREATE TABLE lineitem_partition_task_part_00 ( LIKE lineitem ); +CREATE TABLE lineitem_partition_task_part_01 ( LIKE lineitem ); +CREATE TABLE lineitem_partition_task_part_02 ( LIKE lineitem ); diff --git a/src/test/regress/sql/task_tracker_partition_task.sql b/src/test/regress/sql/task_tracker_partition_task.sql new file mode 100644 index 000000000..a77092882 --- /dev/null +++ b/src/test/regress/sql/task_tracker_partition_task.sql @@ -0,0 +1,60 @@ +-- +-- TASK_TRACKER_PARTITION_TASK +-- + +\set JobId 401010 +\set PartitionTaskId 801106 + +\set PartitionColumn l_orderkey +\set SelectAll 'SELECT *' + +\set TablePart00 lineitem_partition_task_part_00 +\set TablePart01 lineitem_partition_task_part_01 +\set TablePart02 lineitem_partition_task_part_02 + +-- We assign a partition task and wait for it to complete. Note that we hardcode +-- the partition function call string, including the job and task identifiers, +-- into the argument in the task assignment function. This hardcoding is +-- necessary as the current psql version does not perform variable interpolation +-- for names inside single quotes. + +SELECT task_tracker_assign_task(:JobId, :PartitionTaskId, + 'SELECT worker_range_partition_table(' + '401010, 801106, ''SELECT * FROM lineitem'', ' + '''l_orderkey'', 20, ARRAY[1000, 3000]::_int8)'); + +SELECT pg_sleep(4.0); + +SELECT task_tracker_task_status(:JobId, :PartitionTaskId); + +COPY :TablePart00 FROM 'base/pgsql_job_cache/job_401010/task_801106/p_00000'; +COPY :TablePart01 FROM 'base/pgsql_job_cache/job_401010/task_801106/p_00001'; +COPY :TablePart02 FROM 'base/pgsql_job_cache/job_401010/task_801106/p_00002'; + +SELECT COUNT(*) FROM :TablePart00; +SELECT COUNT(*) FROM :TablePart02; + +-- We first compute the difference of partition tables against the base table. +-- Then, we compute the difference of the base table against partitioned tables. + +SELECT COUNT(*) AS diff_lhs_00 FROM ( + :SelectAll FROM :TablePart00 EXCEPT ALL + :SelectAll FROM lineitem WHERE :PartitionColumn < 1000 ) diff; +SELECT COUNT(*) AS diff_lhs_01 FROM ( + :SelectAll FROM :TablePart01 EXCEPT ALL + :SelectAll FROM lineitem WHERE :PartitionColumn >= 1000 AND + :PartitionColumn < 3000 ) diff; +SELECT COUNT(*) AS diff_lhs_02 FROM ( + :SelectAll FROM :TablePart02 EXCEPT ALL + :SelectAll FROM lineitem WHERE :PartitionColumn >= 3000 ) diff; + +SELECT COUNT(*) AS diff_rhs_00 FROM ( + :SelectAll FROM lineitem WHERE :PartitionColumn < 1000 EXCEPT ALL + :SelectAll FROM :TablePart00 ) diff; +SELECT COUNT(*) AS diff_rhs_01 FROM ( + :SelectAll FROM lineitem WHERE :PartitionColumn >= 1000 AND + :PartitionColumn < 3000 EXCEPT ALL + :SelectAll FROM :TablePart01 ) diff; +SELECT COUNT(*) AS diff_rhs_02 FROM ( + :SelectAll FROM lineitem WHERE :PartitionColumn >= 3000 EXCEPT ALL + :SelectAll FROM :TablePart02 ) diff; diff --git a/src/test/regress/sql/worker_binary_data_partition.sql b/src/test/regress/sql/worker_binary_data_partition.sql new file mode 100644 index 000000000..0c2d487dc --- /dev/null +++ b/src/test/regress/sql/worker_binary_data_partition.sql @@ -0,0 +1,89 @@ +-- +-- WORKER_BINARY_DATA_PARTITION +-- + +\set JobId 201010 +\set TaskId 101105 +\set Partition_Column textcolumn +\set Partition_Column_Text '\'textcolumn\'' +\set Partition_Column_Type 25 + +\set Select_Query_Text '\'SELECT * FROM binary_data_table\'' +\set Select_All 'SELECT *' + +\set Table_Name binary_data_table +\set Table_Part_00 binary_data_table_part_00 +\set Table_Part_01 binary_data_table_part_01 +\set Table_Part_02 binary_data_table_part_02 + +-- Create table with special characters + +CREATE TABLE :Table_Name(textcolumn text, binarycolumn bytea); +COPY :Table_Name FROM stdin; +aaa \013\120 +binary data first \012\120\20\21 +binary data second \21\120\130 +binary data hex \x1E\x0D +binary data with tabs \012\t\120\v +some\t tabs\t with \t spaces text with tabs +some\\ special\n characters \b text with special characters +some ' and " and '' characters text with quotes +\N null text +\N null text 2 +\N null text 3 +\\N actual backslash N value +\NN null string and N + empty string +\. + +SELECT length(binarycolumn) FROM :Table_Name; + +-- Run select query, and apply range partitioning on query results + +SELECT worker_range_partition_table(:JobId, :TaskId, :Select_Query_Text, + :Partition_Column_Text, :Partition_Column_Type, + ARRAY['aaa', 'some']::_text); + +-- Copy range partitioned files into tables + +CREATE TABLE :Table_Part_00 ( LIKE :Table_Name ); +CREATE TABLE :Table_Part_01 ( LIKE :Table_Name ); +CREATE TABLE :Table_Part_02 ( LIKE :Table_Name ); + +COPY :Table_Part_00 FROM 'base/pgsql_job_cache/job_201010/task_101105/p_00000'; +COPY :Table_Part_01 FROM 'base/pgsql_job_cache/job_201010/task_101105/p_00001'; +COPY :Table_Part_02 FROM 'base/pgsql_job_cache/job_201010/task_101105/p_00002'; + +-- The union of the three partitions should have as many rows as original table + +SELECT COUNT(*) AS total_row_count FROM ( + SELECT * FROM :Table_Part_00 UNION ALL + SELECT * FROM :Table_Part_01 UNION ALL + SELECT * FROM :Table_Part_02 ) AS all_rows; + +-- We first compute the difference of partition tables against the base table. +-- Then, we compute the difference of the base table against partitioned tables. + +SELECT COUNT(*) AS diff_lhs_00 FROM ( + :Select_All FROM :Table_Part_00 EXCEPT ALL + :Select_All FROM :Table_Name WHERE :Partition_Column IS NULL OR + :Partition_Column < 'aaa' ) diff; +SELECT COUNT(*) AS diff_lhs_01 FROM ( + :Select_All FROM :Table_Part_01 EXCEPT ALL + :Select_All FROM :Table_Name WHERE :Partition_Column >= 'aaa' AND + :Partition_Column < 'some' ) diff; +SELECT COUNT(*) AS diff_lhs_02 FROM ( + :Select_All FROM :Table_Part_02 EXCEPT ALL + :Select_All FROM :Table_Name WHERE :Partition_Column >= 'some' ) diff; + +SELECT COUNT(*) AS diff_rhs_00 FROM ( + :Select_All FROM :Table_Name WHERE :Partition_Column IS NULL OR + :Partition_Column < 'aaa' EXCEPT ALL + :Select_All FROM :Table_Part_00 ) diff; +SELECT COUNT(*) AS diff_rhs_01 FROM ( + :Select_All FROM :Table_Name WHERE :Partition_Column >= 'aaa' AND + :Partition_Column < 'some' EXCEPT ALL + :Select_All FROM :Table_Part_01 ) diff; +SELECT COUNT(*) AS diff_rhs_02 FROM ( + :Select_All FROM :Table_Name WHERE :Partition_Column >= 'some' EXCEPT ALL + :Select_All FROM :Table_Part_02 ) diff; diff --git a/src/test/regress/sql/worker_check_invalid_arguments.sql b/src/test/regress/sql/worker_check_invalid_arguments.sql new file mode 100644 index 000000000..464e92985 --- /dev/null +++ b/src/test/regress/sql/worker_check_invalid_arguments.sql @@ -0,0 +1,78 @@ +-- +-- WORKER_CHECK_INVALID_ARGUMENTS +-- + +\set JobId 201010 +\set TaskId 101108 +\set Table_Name simple_binary_data_table +\set Partition_Column_Name '\'textcolumn\'' +\set Partition_Column_Type 25 +\set Partition_Count 2 +\set Select_Query_Text '\'SELECT * FROM simple_binary_data_table\'' + +\set Bad_Partition_Column_Name '\'badcolumnname\'' +\set Bad_Partition_Column_Type 20 +\set Bad_Select_Query_Text '\'SELECT * FROM bad_table_name\'' + +-- Create simple table and insert a few rows into this table +-- N.B. - These rows will be partitioned to files on disk then read back in the +-- order the files are listed by a call to readdir; because this order is not +-- predictable, the second column of these rows always has the same value, to +-- avoid an error message differing based on file read order. + +CREATE TABLE :Table_Name(textcolumn text, binarycolumn bytea); +COPY :Table_Name FROM stdin; +aaa \013\120 +some\t tabs\t with \t spaces \013\120 +\. + +SELECT COUNT(*) FROM :Table_Name; + +-- Check that we fail with bad SQL query + +SELECT worker_range_partition_table(:JobId, :TaskId, :Bad_Select_Query_Text, + :Partition_Column_Name, :Partition_Column_Type, + ARRAY['aaa', 'some']::_text); + +-- Check that we fail with bad partition column name + +SELECT worker_range_partition_table(:JobId, :TaskId, :Select_Query_Text, + :Bad_Partition_Column_Name, :Partition_Column_Type, + ARRAY['aaa', 'some']::_text); + +-- Check that we fail when partition column and split point types do not match + +SELECT worker_range_partition_table(:JobId, :TaskId, :Select_Query_Text, + :Partition_Column_Name, :Bad_Partition_Column_Type, + ARRAY['aaa', 'some']::_text); + +-- Check that we fail with bad partition column type on hash partitioning + +SELECT worker_hash_partition_table(:JobId, :TaskId, :Select_Query_Text, + :Partition_Column_Name, :Bad_Partition_Column_Type, + :Partition_Count); + +-- Now, partition table data using valid arguments + +SELECT worker_range_partition_table(:JobId, :TaskId, :Select_Query_Text, + :Partition_Column_Name, :Partition_Column_Type, + ARRAY['aaa', 'some']::_text); + +-- Check that we fail to merge when the number of column names and column types +-- do not match + +SELECT worker_merge_files_into_table(:JobId, :TaskId, + ARRAY['textcolumn', 'binarycolumn'], + ARRAY['text', 'bytea', 'integer']); + +-- Check that we fail to merge when column types do not match underlying data + +SELECT worker_merge_files_into_table(:JobId, :TaskId, + ARRAY['textcolumn', 'binarycolumn'], + ARRAY['text', 'integer']); + +-- Finally, merge partitioned files using valid arguments + +SELECT worker_merge_files_into_table(:JobId, :TaskId, + ARRAY['textcolumn', 'binarycolumn'], + ARRAY['text', 'bytea']); diff --git a/src/test/regress/sql/worker_create_table.sql b/src/test/regress/sql/worker_create_table.sql new file mode 100644 index 000000000..7f9699d65 --- /dev/null +++ b/src/test/regress/sql/worker_create_table.sql @@ -0,0 +1,87 @@ +-- +-- WORKER_CREATE_TABLE +-- + +-- Create new table definitions for lineitem and supplier tables to test worker +-- node execution logic. For now,the tests include range and hash partitioning +-- of existing tables. + +CREATE TABLE lineitem ( + l_orderkey bigint not null, + l_partkey integer not null, + l_suppkey integer not null, + l_linenumber integer not null, + l_quantity decimal(15, 2) not null, + l_extendedprice decimal(15, 2) not null, + l_discount decimal(15, 2) not null, + l_tax decimal(15, 2) not null, + l_returnflag char(1) not null, + l_linestatus char(1) not null, + l_shipdate date not null, + l_commitdate date not null, + l_receiptdate date not null, + l_shipinstruct char(25) not null, + l_shipmode char(10) not null, + l_comment varchar(44) not null, + PRIMARY KEY(l_orderkey, l_linenumber) ); + +CREATE TABLE lineitem_complex ( + l_partkey integer not null, + l_discount decimal(15, 2) not null, + l_shipdate date not null, + l_comment varchar(44) not null ); + +-- Range partitioned lineitem data are inserted into these four tables + +CREATE TABLE lineitem_range_part_00 ( LIKE lineitem ); +CREATE TABLE lineitem_range_part_01 ( LIKE lineitem ); +CREATE TABLE lineitem_range_part_02 ( LIKE lineitem ); +CREATE TABLE lineitem_range_part_03 ( LIKE lineitem ); + +-- Complex range partitioned lineitem data are inserted into these four tables + +CREATE TABLE lineitem_range_complex_part_00 ( LIKE lineitem_complex ); +CREATE TABLE lineitem_range_complex_part_01 ( LIKE lineitem_complex ); +CREATE TABLE lineitem_range_complex_part_02 ( LIKE lineitem_complex ); +CREATE TABLE lineitem_range_complex_part_03 ( LIKE lineitem_complex ); + +-- Hash partitioned lineitem data are inserted into these four tables + +CREATE TABLE lineitem_hash_part_00 ( LIKE lineitem ); +CREATE TABLE lineitem_hash_part_01 ( LIKE lineitem ); +CREATE TABLE lineitem_hash_part_02 ( LIKE lineitem ); +CREATE TABLE lineitem_hash_part_03 ( LIKE lineitem ); + +-- Complex hash partitioned lineitem data are inserted into these four tables + +CREATE TABLE lineitem_hash_complex_part_00 ( LIKE lineitem_complex ); +CREATE TABLE lineitem_hash_complex_part_01 ( LIKE lineitem_complex ); +CREATE TABLE lineitem_hash_complex_part_02 ( LIKE lineitem_complex ); +CREATE TABLE lineitem_hash_complex_part_03 ( LIKE lineitem_complex ); + + +-- Now create a supplier table to test repartitioning the data on the nation key +-- column, where the column's values can be null or zero. + +CREATE TABLE SUPPLIER +( + s_suppkey integer not null, + s_name char(25) not null, + s_address varchar(40) not null, + s_nationkey integer, + s_phone char(15) not null, + s_acctbal decimal(15,2) not null, + s_comment varchar(101) not null +); + +-- Range partitioned supplier data are inserted into three tables + +CREATE TABLE supplier_range_part_00 ( LIKE supplier ); +CREATE TABLE supplier_range_part_01 ( LIKE supplier ); +CREATE TABLE supplier_range_part_02 ( LIKE supplier ); + +-- Hash partitioned supplier data are inserted into three tables + +CREATE TABLE supplier_hash_part_00 ( LIKE supplier ); +CREATE TABLE supplier_hash_part_01 ( LIKE supplier ); +CREATE TABLE supplier_hash_part_02 ( LIKE supplier ); diff --git a/src/test/regress/sql/worker_hash_partition.sql b/src/test/regress/sql/worker_hash_partition.sql new file mode 100644 index 000000000..0bf5e2ef8 --- /dev/null +++ b/src/test/regress/sql/worker_hash_partition.sql @@ -0,0 +1,70 @@ +-- +-- WORKER_HASH_PARTITION +-- + +\set JobId 201010 +\set TaskId 101103 +\set Partition_Column l_orderkey +\set Partition_Column_Text '\'l_orderkey\'' +\set Partition_Column_Type 20 +\set Partition_Count 4 + +\set Select_Query_Text '\'SELECT * FROM lineitem\'' +\set Select_All 'SELECT *' + +-- Hash functions internally return unsigned 32-bit integers. However, when +-- called externally, the return value becomes a signed 32-bit integer. We hack +-- around this conversion issue by bitwise-anding the hash results. Note that +-- this only works because we are modding with 4. The proper Hash_Mod_Function +-- would be (case when hashint8(l_orderkey) >= 0 then (hashint8(l_orderkey) % 4) +-- else ((hashint8(l_orderkey) + 4294967296) % 4) end). + +\set Hash_Mod_Function '( (hashint8(l_orderkey) & 2147483647) % 4 )' + +\set Table_Part_00 lineitem_hash_part_00 +\set Table_Part_01 lineitem_hash_part_01 +\set Table_Part_02 lineitem_hash_part_02 +\set Table_Part_03 lineitem_hash_part_03 + +-- Run select query, and apply hash partitioning on query results + +SELECT worker_hash_partition_table(:JobId, :TaskId, :Select_Query_Text, + :Partition_Column_Text, :Partition_Column_Type, + :Partition_Count); + +COPY :Table_Part_00 FROM 'base/pgsql_job_cache/job_201010/task_101103/p_00000'; +COPY :Table_Part_01 FROM 'base/pgsql_job_cache/job_201010/task_101103/p_00001'; +COPY :Table_Part_02 FROM 'base/pgsql_job_cache/job_201010/task_101103/p_00002'; +COPY :Table_Part_03 FROM 'base/pgsql_job_cache/job_201010/task_101103/p_00003'; + +SELECT COUNT(*) FROM :Table_Part_00; +SELECT COUNT(*) FROM :Table_Part_03; + +-- We first compute the difference of partition tables against the base table. +-- Then, we compute the difference of the base table against partitioned tables. + +SELECT COUNT(*) AS diff_lhs_00 FROM ( + :Select_All FROM :Table_Part_00 EXCEPT ALL + :Select_All FROM lineitem WHERE (:Hash_Mod_Function = 0) ) diff; +SELECT COUNT(*) AS diff_lhs_01 FROM ( + :Select_All FROM :Table_Part_01 EXCEPT ALL + :Select_All FROM lineitem WHERE (:Hash_Mod_Function = 1) ) diff; +SELECT COUNT(*) AS diff_lhs_02 FROM ( + :Select_All FROM :Table_Part_02 EXCEPT ALL + :Select_All FROM lineitem WHERE (:Hash_Mod_Function = 2) ) diff; +SELECT COUNT(*) AS diff_lhs_03 FROM ( + :Select_All FROM :Table_Part_03 EXCEPT ALL + :Select_All FROM lineitem WHERE (:Hash_Mod_Function = 3) ) diff; + +SELECT COUNT(*) AS diff_rhs_00 FROM ( + :Select_All FROM lineitem WHERE (:Hash_Mod_Function = 0) EXCEPT ALL + :Select_All FROM :Table_Part_00 ) diff; +SELECT COUNT(*) AS diff_rhs_01 FROM ( + :Select_All FROM lineitem WHERE (:Hash_Mod_Function = 1) EXCEPT ALL + :Select_All FROM :Table_Part_01 ) diff; +SELECT COUNT(*) AS diff_rhs_02 FROM ( + :Select_All FROM lineitem WHERE (:Hash_Mod_Function = 2) EXCEPT ALL + :Select_All FROM :Table_Part_02 ) diff; +SELECT COUNT(*) AS diff_rhs_03 FROM ( + :Select_All FROM lineitem WHERE (:Hash_Mod_Function = 3) EXCEPT ALL + :Select_All FROM :Table_Part_03 ) diff; diff --git a/src/test/regress/sql/worker_hash_partition_complex.sql b/src/test/regress/sql/worker_hash_partition_complex.sql new file mode 100644 index 000000000..0aa89ef79 --- /dev/null +++ b/src/test/regress/sql/worker_hash_partition_complex.sql @@ -0,0 +1,78 @@ +-- +-- WORKER_HASH_PARTITION_COMPLEX +-- + +\set JobId 201010 +\set TaskId 101104 +\set Partition_Column l_partkey +\set Partition_Column_Text '\'l_partkey\'' +\set Partition_Column_Type 23 +\set Partition_Count 4 + +\set Select_Columns 'SELECT l_partkey, l_discount, l_shipdate, l_comment' +\set Select_Filters 'l_shipdate >= date \'1992-01-15\' AND l_discount between 0.02 AND 0.08' + +\set Hash_Mod_Function '( (hashint4(l_partkey) & 2147483647) % 4 )' + +\set Table_Part_00 lineitem_hash_complex_part_00 +\set Table_Part_01 lineitem_hash_complex_part_01 +\set Table_Part_02 lineitem_hash_complex_part_02 +\set Table_Part_03 lineitem_hash_complex_part_03 + +-- Run hardcoded complex select query, and apply hash partitioning on query +-- results + +SELECT worker_hash_partition_table(:JobId, :TaskId, + 'SELECT l_partkey, l_discount, l_shipdate, l_comment' + ' FROM lineitem ' + ' WHERE l_shipdate >= date ''1992-01-15''' + ' AND l_discount between 0.02 AND 0.08', + :Partition_Column_Text, :Partition_Column_Type, + :Partition_Count); + +-- Copy partitioned data files into tables for testing purposes + +COPY :Table_Part_00 FROM 'base/pgsql_job_cache/job_201010/task_101104/p_00000'; +COPY :Table_Part_01 FROM 'base/pgsql_job_cache/job_201010/task_101104/p_00001'; +COPY :Table_Part_02 FROM 'base/pgsql_job_cache/job_201010/task_101104/p_00002'; +COPY :Table_Part_03 FROM 'base/pgsql_job_cache/job_201010/task_101104/p_00003'; + +SELECT COUNT(*) FROM :Table_Part_00; +SELECT COUNT(*) FROM :Table_Part_03; + +-- We first compute the difference of partition tables against the base table. +-- Then, we compute the difference of the base table against partitioned tables. + +SELECT COUNT(*) AS diff_lhs_00 FROM ( + :Select_Columns FROM :Table_Part_00 EXCEPT ALL + :Select_Columns FROM lineitem WHERE :Select_Filters AND + (:Hash_Mod_Function = 0) ) diff; +SELECT COUNT(*) AS diff_lhs_01 FROM ( + :Select_Columns FROM :Table_Part_01 EXCEPT ALL + :Select_Columns FROM lineitem WHERE :Select_Filters AND + (:Hash_Mod_Function = 1) ) diff; +SELECT COUNT(*) AS diff_lhs_02 FROM ( + :Select_Columns FROM :Table_Part_02 EXCEPT ALL + :Select_Columns FROM lineitem WHERE :Select_Filters AND + (:Hash_Mod_Function = 2) ) diff; +SELECT COUNT(*) AS diff_lhs_03 FROM ( + :Select_Columns FROM :Table_Part_03 EXCEPT ALL + :Select_Columns FROM lineitem WHERE :Select_Filters AND + (:Hash_Mod_Function = 3) ) diff; + +SELECT COUNT(*) AS diff_rhs_00 FROM ( + :Select_Columns FROM lineitem WHERE :Select_Filters AND + (:Hash_Mod_Function = 0) EXCEPT ALL + :Select_Columns FROM :Table_Part_00 ) diff; +SELECT COUNT(*) AS diff_rhs_01 FROM ( + :Select_Columns FROM lineitem WHERE :Select_Filters AND + (:Hash_Mod_Function = 1) EXCEPT ALL + :Select_Columns FROM :Table_Part_01 ) diff; +SELECT COUNT(*) AS diff_rhs_02 FROM ( + :Select_Columns FROM lineitem WHERE :Select_Filters AND + (:Hash_Mod_Function = 2) EXCEPT ALL + :Select_Columns FROM :Table_Part_02 ) diff; +SELECT COUNT(*) AS diff_rhs_03 FROM ( + :Select_Columns FROM lineitem WHERE :Select_Filters AND + (:Hash_Mod_Function = 3) EXCEPT ALL + :Select_Columns FROM :Table_Part_03 ) diff; diff --git a/src/test/regress/sql/worker_merge_hash_files.sql b/src/test/regress/sql/worker_merge_hash_files.sql new file mode 100644 index 000000000..3f8c59f00 --- /dev/null +++ b/src/test/regress/sql/worker_merge_hash_files.sql @@ -0,0 +1,33 @@ +-- +-- WORKER_MERGE_HASH_FILES +-- + +\set JobId 201010 +\set TaskId 101103 +\set Task_Table_Name public.task_101103 +\set Select_All 'SELECT *' + +-- TaskId determines our dependency on hash partitioned files. We take these +-- files, and merge them in a task table. We also pass the column names and +-- column types that are used to create the task table. + +SELECT worker_merge_files_into_table(:JobId, :TaskId, + ARRAY['orderkey', 'partkey', 'suppkey', 'linenumber', 'quantity', 'extendedprice', + 'discount', 'tax', 'returnflag', 'linestatus', 'shipdate', 'commitdate', + 'receiptdate', 'shipinstruct', 'shipmode', 'comment']::_text, + ARRAY['bigint', 'integer', 'integer', 'integer', 'decimal(15, 2)', 'decimal(15, 2)', + 'decimal(15, 2)', 'decimal(15, 2)', 'char(1)', 'char(1)', 'date', 'date', + 'date', 'char(25)', 'char(10)', 'varchar(44)']::_text); + + +-- We first count elements from the merged table and the original table we hash +-- partitioned. We then compute the difference of these two tables. + +SELECT COUNT(*) FROM :Task_Table_Name; +SELECT COUNT(*) FROM lineitem; + +SELECT COUNT(*) AS diff_lhs FROM ( :Select_All FROM :Task_Table_Name EXCEPT ALL + :Select_All FROM lineitem ) diff; + +SELECT COUNT(*) AS diff_rhs FROM ( :Select_All FROM lineitem EXCEPT ALL + :Select_All FROM :Task_Table_Name ) diff; diff --git a/src/test/regress/sql/worker_merge_range_files.sql b/src/test/regress/sql/worker_merge_range_files.sql new file mode 100644 index 000000000..26f67e94b --- /dev/null +++ b/src/test/regress/sql/worker_merge_range_files.sql @@ -0,0 +1,33 @@ +-- +-- WORKER_MERGE_RANGE_FILES +-- + +\set JobId 201010 +\set TaskId 101101 +\set Task_Table_Name public.task_101101 +\set Select_All 'SELECT *' + +-- TaskId determines our dependency on range partitioned files. We take these +-- files, and merge them in a task table. We also pass the column names and +-- column types that are used to create the task table. + +SELECT worker_merge_files_into_table(:JobId, :TaskId, + ARRAY['orderkey', 'partkey', 'suppkey', 'linenumber', 'quantity', 'extendedprice', + 'discount', 'tax', 'returnflag', 'linestatus', 'shipdate', 'commitdate', + 'receiptdate', 'shipinstruct', 'shipmode', 'comment']::_text, + ARRAY['bigint', 'integer', 'integer', 'integer', 'decimal(15, 2)', 'decimal(15, 2)', + 'decimal(15, 2)', 'decimal(15, 2)', 'char(1)', 'char(1)', 'date', 'date', + 'date', 'char(25)', 'char(10)', 'varchar(44)']::_text); + + +-- We first count elements from the merged table and the original table we range +-- partitioned. We then compute the difference of these two tables. + +SELECT COUNT(*) FROM :Task_Table_Name; +SELECT COUNT(*) FROM lineitem; + +SELECT COUNT(*) AS diff_lhs FROM ( :Select_All FROM :Task_Table_Name EXCEPT ALL + :Select_All FROM lineitem ) diff; + +SELECT COUNT(*) AS diff_rhs FROM ( :Select_All FROM lineitem EXCEPT ALL + :Select_All FROM :Task_Table_Name ) diff; diff --git a/src/test/regress/sql/worker_null_data_partition.sql b/src/test/regress/sql/worker_null_data_partition.sql new file mode 100644 index 000000000..b696c8d14 --- /dev/null +++ b/src/test/regress/sql/worker_null_data_partition.sql @@ -0,0 +1,112 @@ +-- +-- WORKER_NULL_DATA_PARTITION +-- + +\set JobId 201010 +\set Range_TaskId 101106 +\set Partition_Column s_nationkey +\set Partition_Column_Text '\'s_nationkey\'' +\set Partition_Column_Type 23 + +\set Select_Query_Text '\'SELECT * FROM supplier\'' +\set Select_All 'SELECT *' + +\set Range_Table_Part_00 supplier_range_part_00 +\set Range_Table_Part_01 supplier_range_part_01 +\set Range_Table_Part_02 supplier_range_part_02 + +-- Run select query, and apply range partitioning on query results. Note that +-- one of the split point values is 0, We are checking here that the partition +-- function doesn't treat 0 as null, and that range repartitioning correctly +-- puts null nation key values into the 0th repartition bucket. + +SELECT worker_range_partition_table(:JobId, :Range_TaskId, :Select_Query_Text, + :Partition_Column_Text, :Partition_Column_Type, + ARRAY[0, 10]::_int4); + +-- Copy partitioned data files into tables for testing purposes + +COPY :Range_Table_Part_00 FROM 'base/pgsql_job_cache/job_201010/task_101106/p_00000'; +COPY :Range_Table_Part_01 FROM 'base/pgsql_job_cache/job_201010/task_101106/p_00001'; +COPY :Range_Table_Part_02 FROM 'base/pgsql_job_cache/job_201010/task_101106/p_00002'; + +SELECT COUNT(*) FROM :Range_Table_Part_00; +SELECT COUNT(*) FROM :Range_Table_Part_02; + +-- We first compute the difference of partition tables against the base table. +-- Then, we compute the difference of the base table against partitioned tables. + +SELECT COUNT(*) AS diff_lhs_00 FROM ( + :Select_All FROM :Range_Table_Part_00 EXCEPT ALL + (:Select_All FROM supplier WHERE :Partition_Column < 0 OR + :Partition_Column IS NULL) ) diff; +SELECT COUNT(*) AS diff_lhs_01 FROM ( + :Select_All FROM :Range_Table_Part_01 EXCEPT ALL + :Select_All FROM supplier WHERE :Partition_Column >= 0 AND + :Partition_Column < 10 ) diff; +SELECT COUNT(*) AS diff_rhs_02 FROM ( + :Select_All FROM supplier WHERE :Partition_Column >= 10 EXCEPT ALL + :Select_All FROM :Range_Table_Part_02 ) diff; + +SELECT COUNT(*) AS diff_rhs_00 FROM ( + (:Select_All FROM supplier WHERE :Partition_Column < 0 OR + :Partition_Column IS NULL) EXCEPT ALL + :Select_All FROM :Range_Table_Part_00 ) diff; +SELECT COUNT(*) AS diff_rhs_01 FROM ( + :Select_All FROM supplier WHERE :Partition_Column >= 0 AND + :Partition_Column < 10 EXCEPT ALL + :Select_All FROM :Range_Table_Part_01 ) diff; +SELECT COUNT(*) AS diff_rhs_02 FROM ( + :Select_All FROM supplier WHERE :Partition_Column >= 10 EXCEPT ALL + :Select_All FROM :Range_Table_Part_02 ) diff; + + +-- Next, run select query and apply hash partitioning on query results. We are +-- checking here that hash repartitioning correctly puts null nation key values +-- into the 0th repartition bucket. + +\set Hash_TaskId 101107 +\set Partition_Count 4 +\set Hash_Mod_Function '( (hashint4(s_nationkey) & 2147483647) % 4 )' + +\set Hash_Table_Part_00 supplier_hash_part_00 +\set Hash_Table_Part_01 supplier_hash_part_01 +\set Hash_Table_Part_02 supplier_hash_part_02 + +-- Run select query, and apply hash partitioning on query results + +SELECT worker_hash_partition_table(:JobId, :Hash_TaskId, :Select_Query_Text, + :Partition_Column_Text, :Partition_Column_Type, + :Partition_Count); + +COPY :Hash_Table_Part_00 FROM 'base/pgsql_job_cache/job_201010/task_101107/p_00000'; +COPY :Hash_Table_Part_01 FROM 'base/pgsql_job_cache/job_201010/task_101107/p_00001'; +COPY :Hash_Table_Part_02 FROM 'base/pgsql_job_cache/job_201010/task_101107/p_00002'; + +SELECT COUNT(*) FROM :Hash_Table_Part_00; +SELECT COUNT(*) FROM :Hash_Table_Part_02; + +-- We first compute the difference of partition tables against the base table. +-- Then, we compute the difference of the base table against partitioned tables. + +SELECT COUNT(*) AS diff_lhs_00 FROM ( + :Select_All FROM :Hash_Table_Part_00 EXCEPT ALL + (:Select_All FROM supplier WHERE (:Hash_Mod_Function = 0) OR + :Partition_Column IS NULL) ) diff; +SELECT COUNT(*) AS diff_lhs_01 FROM ( + :Select_All FROM :Hash_Table_Part_01 EXCEPT ALL + :Select_All FROM supplier WHERE (:Hash_Mod_Function = 1) ) diff; +SELECT COUNT(*) AS diff_lhs_02 FROM ( + :Select_All FROM :Hash_Table_Part_02 EXCEPT ALL + :Select_All FROM supplier WHERE (:Hash_Mod_Function = 2) ) diff; + +SELECT COUNT(*) AS diff_rhs_00 FROM ( + (:Select_All FROM supplier WHERE (:Hash_Mod_Function = 0) OR + :Partition_Column IS NULL) EXCEPT ALL + :Select_All FROM :Hash_Table_Part_00 ) diff; +SELECT COUNT(*) AS diff_rhs_01 FROM ( + :Select_All FROM supplier WHERE (:Hash_Mod_Function = 1) EXCEPT ALL + :Select_All FROM :Hash_Table_Part_01 ) diff; +SELECT COUNT(*) AS diff_rhs_02 FROM ( + :Select_All FROM supplier WHERE (:Hash_Mod_Function = 2) EXCEPT ALL + :Select_All FROM :Hash_Table_Part_02 ) diff; diff --git a/src/test/regress/sql/worker_range_partition.sql b/src/test/regress/sql/worker_range_partition.sql new file mode 100644 index 000000000..f6c0d87b2 --- /dev/null +++ b/src/test/regress/sql/worker_range_partition.sql @@ -0,0 +1,70 @@ +-- +-- WORKER_RANGE_PARTITION +-- + +\set JobId 201010 +\set TaskId 101101 +\set Partition_Column l_orderkey +\set Partition_Column_Text '\'l_orderkey\'' +\set Partition_Column_Type 20 + +\set Select_Query_Text '\'SELECT * FROM lineitem\'' +\set Select_All 'SELECT *' + +\set Table_Part_00 lineitem_range_part_00 +\set Table_Part_01 lineitem_range_part_01 +\set Table_Part_02 lineitem_range_part_02 +\set Table_Part_03 lineitem_range_part_03 + +-- Run select query, and apply range partitioning on query results + +SELECT worker_range_partition_table(:JobId, :TaskId, :Select_Query_Text, + :Partition_Column_Text, :Partition_Column_Type, + ARRAY[1, 3000, 12000]::_int8); + +-- Note that the following file names depend on job and task identifiers. We +-- prefer to substitute them here, but the current psql version does not perform +-- variable interpolation for names inside single quotes. This SQL interpolation +-- issue is fixed in PostgreSQL 9.0; and once we upgrade, we will change both +-- the following filenames, and the sequence names in the relay_sequence tests. + +COPY :Table_Part_00 FROM 'base/pgsql_job_cache/job_201010/task_101101/p_00000'; +COPY :Table_Part_01 FROM 'base/pgsql_job_cache/job_201010/task_101101/p_00001'; +COPY :Table_Part_02 FROM 'base/pgsql_job_cache/job_201010/task_101101/p_00002'; +COPY :Table_Part_03 FROM 'base/pgsql_job_cache/job_201010/task_101101/p_00003'; + +SELECT COUNT(*) FROM :Table_Part_00; +SELECT COUNT(*) FROM :Table_Part_03; + +-- We first compute the difference of partition tables against the base table. +-- Then, we compute the difference of the base table against partitioned tables. + +SELECT COUNT(*) AS diff_lhs_00 FROM ( + :Select_All FROM :Table_Part_00 EXCEPT ALL + :Select_All FROM lineitem WHERE :Partition_Column < 1 ) diff; +SELECT COUNT(*) AS diff_lhs_01 FROM ( + :Select_All FROM :Table_Part_01 EXCEPT ALL + :Select_All FROM lineitem WHERE :Partition_Column >= 1 AND + :Partition_Column < 3000 ) diff; +SELECT COUNT(*) AS diff_lhs_02 FROM ( + :Select_All FROM :Table_Part_02 EXCEPT ALL + :Select_All FROM lineitem WHERE :Partition_Column >= 3000 AND + :Partition_Column < 12000 ) diff; +SELECT COUNT(*) AS diff_lhs_03 FROM ( + :Select_All FROM :Table_Part_03 EXCEPT ALL + :Select_All FROM lineitem WHERE :Partition_Column >= 12000 ) diff; + +SELECT COUNT(*) AS diff_rhs_00 FROM ( + :Select_All FROM lineitem WHERE :Partition_Column < 1 EXCEPT ALL + :Select_All FROM :Table_Part_00 ) diff; +SELECT COUNT(*) AS diff_rhs_01 FROM ( + :Select_All FROM lineitem WHERE :Partition_Column >= 1 AND + :Partition_Column < 3000 EXCEPT ALL + :Select_All FROM :Table_Part_01 ) diff; +SELECT COUNT(*) AS diff_rhs_02 FROM ( + :Select_All FROM lineitem WHERE :Partition_Column >= 3000 AND + :Partition_Column < 12000 EXCEPT ALL + :Select_All FROM :Table_Part_02 ) diff; +SELECT COUNT(*) AS diff_rhs_03 FROM ( + :Select_All FROM lineitem WHERE :Partition_Column >= 12000 EXCEPT ALL + :Select_All FROM :Table_Part_03 ) diff; diff --git a/src/test/regress/sql/worker_range_partition_complex.sql b/src/test/regress/sql/worker_range_partition_complex.sql new file mode 100644 index 000000000..14a536a57 --- /dev/null +++ b/src/test/regress/sql/worker_range_partition_complex.sql @@ -0,0 +1,80 @@ +-- +-- WORKER_RANGE_PARTITION_COMPLEX +-- + +\set JobId 201010 +\set TaskId 101102 +\set Partition_Column l_partkey +\set Partition_Column_Text '\'l_partkey\'' +\set Partition_Column_Type 23 + +\set Select_Columns 'SELECT l_partkey, l_discount, l_shipdate, l_comment' +\set Select_Filters 'l_shipdate >= date \'1992-01-15\' AND l_discount between 0.02 AND 0.08' + +\set Table_Part_00 lineitem_range_complex_part_00 +\set Table_Part_01 lineitem_range_complex_part_01 +\set Table_Part_02 lineitem_range_complex_part_02 +\set Table_Part_03 lineitem_range_complex_part_03 + +-- Run hardcoded complex select query, and apply range partitioning on query +-- results + +SELECT worker_range_partition_table(:JobId, :TaskId, + 'SELECT l_partkey, l_discount, l_shipdate, l_comment' + ' FROM lineitem ' + ' WHERE l_shipdate >= date ''1992-01-15''' + ' AND l_discount between 0.02 AND 0.08', + :Partition_Column_Text, :Partition_Column_Type, + ARRAY[101, 12000, 18000]::_int4); + +-- Copy partitioned data files into tables for testing purposes + +COPY :Table_Part_00 FROM 'base/pgsql_job_cache/job_201010/task_101102/p_00000'; +COPY :Table_Part_01 FROM 'base/pgsql_job_cache/job_201010/task_101102/p_00001'; +COPY :Table_Part_02 FROM 'base/pgsql_job_cache/job_201010/task_101102/p_00002'; +COPY :Table_Part_03 FROM 'base/pgsql_job_cache/job_201010/task_101102/p_00003'; + +SELECT COUNT(*) FROM :Table_Part_00; +SELECT COUNT(*) FROM :Table_Part_03; + +-- We first compute the difference of partition tables against the base table. +-- Then, we compute the difference of the base table against partitioned tables. + +SELECT COUNT(*) AS diff_lhs_00 FROM ( + :Select_Columns FROM :Table_Part_00 EXCEPT ALL + :Select_Columns FROM lineitem WHERE :Select_Filters AND + :Partition_Column < 101 ) diff; +SELECT COUNT(*) AS diff_lhs_01 FROM ( + :Select_Columns FROM :Table_Part_01 EXCEPT ALL + :Select_Columns FROM lineitem WHERE :Select_Filters AND + :Partition_Column >= 101 AND + :Partition_Column < 12000 ) diff; +SELECT COUNT(*) AS diff_lhs_02 FROM ( + :Select_Columns FROM :Table_Part_02 EXCEPT ALL + :Select_Columns FROM lineitem WHERE :Select_Filters AND + :Partition_Column >= 12000 AND + :Partition_Column < 18000 ) diff; +SELECT COUNT(*) AS diff_lhs_03 FROM ( + :Select_Columns FROM :Table_Part_03 EXCEPT ALL + :Select_Columns FROM lineitem WHERE :Select_Filters AND + :Partition_Column >= 18000 ) diff; + +SELECT COUNT(*) AS diff_rhs_00 FROM ( + :Select_Columns FROM lineitem WHERE :Select_Filters AND + :Partition_Column < 101 EXCEPT ALL + :Select_Columns FROM :Table_Part_00 ) diff; +SELECT COUNT(*) AS diff_rhs_01 FROM ( + :Select_Columns FROM lineitem WHERE :Select_Filters AND + :Partition_Column >= 101 AND + :Partition_Column < 12000 EXCEPT ALL + :Select_Columns FROM :Table_Part_01 ) diff; +SELECT COUNT(*) AS diff_rhs_02 FROM ( + :Select_Columns FROM lineitem WHERE :Select_Filters AND + :Partition_Column >= 12000 AND + :Partition_Column < 18000 EXCEPT ALL + :Select_Columns FROM :Table_Part_02 ) diff; +SELECT COUNT(*) AS diff_rhs_03 FROM ( + :Select_Columns FROM lineitem WHERE :Select_Filters AND + :Partition_Column >= 18000 EXCEPT ALL + :Select_Columns FROM :Table_Part_03 ) diff; + diff --git a/src/test/regress/worker_schedule b/src/test/regress/worker_schedule new file mode 100644 index 000000000..e3b3d7a51 --- /dev/null +++ b/src/test/regress/worker_schedule @@ -0,0 +1,28 @@ +# ---------- +# $Id$ +# +# Regression tests that exercise worker node related distributed execution +# logic. +# ---------- + +# ---------- +# All worker tests use the following table and its data +# ---------- +test: worker_create_table +test: worker_copy + +# ---------- +# Range and hash re-partitioning related regression tests +# ---------- +test: worker_range_partition worker_range_partition_complex +test: worker_hash_partition worker_hash_partition_complex +test: worker_merge_range_files worker_merge_hash_files +test: worker_binary_data_partition worker_null_data_partition +test: worker_check_invalid_arguments + +# ---------- +# All task tracker tests use the following tables +# ---------- +test: task_tracker_create_table +test: task_tracker_assign_task task_tracker_partition_task +test: task_tracker_cleanup_job